Imported Upstream version 1.1.0 upstream/1.1.0
authorAnas Nashif <anas.nashif@intel.com>
Sat, 2 Feb 2013 16:35:08 +0000 (08:35 -0800)
committerAnas Nashif <anas.nashif@intel.com>
Sat, 2 Feb 2013 16:35:08 +0000 (08:35 -0800)
879 files changed:
.gitattributes [new file with mode: 0644]
.gitignore [new file with mode: 0644]
.mailmap [new file with mode: 0644]
AUTHORS [new file with mode: 0644]
CHANGELOG [new file with mode: 0644]
LICENSE [new file with mode: 0644]
PATENTS [new file with mode: 0644]
README [new file with mode: 0644]
args.c [new file with mode: 0644]
args.h [new file with mode: 0644]
build/.gitattributes [new file with mode: 0644]
build/.gitignore [new file with mode: 0644]
build/make/Android.mk [new file with mode: 0644]
build/make/Makefile [new file with mode: 0644]
build/make/ads2gas.pl [new file with mode: 0755]
build/make/ads2gas_apple.pl [new file with mode: 0755]
build/make/armlink_adapter.sh [new file with mode: 0755]
build/make/configure.sh [new file with mode: 0755]
build/make/gen_asm_deps.sh [new file with mode: 0755]
build/make/gen_msvs_def.sh [new file with mode: 0755]
build/make/gen_msvs_proj.sh [new file with mode: 0755]
build/make/gen_msvs_sln.sh [new file with mode: 0755]
build/make/obj_int_extract.c [new file with mode: 0644]
build/make/rtcd.sh [new file with mode: 0755]
build/make/version.sh [new file with mode: 0755]
build/x86-msvs/obj_int_extract.bat [new file with mode: 0644]
build/x86-msvs/yasm.rules [new file with mode: 0644]
configure [new file with mode: 0755]
docs.mk [new file with mode: 0644]
example_xma.c [new file with mode: 0644]
examples.mk [new file with mode: 0644]
examples/decode_to_md5.txt [new file with mode: 0644]
examples/decode_with_drops.txt [new file with mode: 0644]
examples/decode_with_partial_drops.txt [new file with mode: 0644]
examples/decoder_tmpl.c [new file with mode: 0644]
examples/decoder_tmpl.txt [new file with mode: 0644]
examples/encoder_tmpl.c [new file with mode: 0644]
examples/encoder_tmpl.txt [new file with mode: 0644]
examples/error_resilient.txt [new file with mode: 0644]
examples/force_keyframe.txt [new file with mode: 0644]
examples/gen_example_code.sh [new file with mode: 0755]
examples/gen_example_doxy.php [new file with mode: 0755]
examples/gen_example_text.sh [new file with mode: 0755]
examples/includes/ASCIIMathPHP-2.0/ASCIIMathPHP-2.0.cfg.php [new file with mode: 0644]
examples/includes/ASCIIMathPHP-2.0/ASCIIMathPHP-2.0.class.php [new file with mode: 0644]
examples/includes/ASCIIMathPHP-2.0/htmlMathML.js [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/.gitattributes [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/Changes [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/MANIFEST [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/Makefile.PL [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/Toc.pm [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/Toc.pod [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/TocGenerator.pm [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/TocInsertor.pm [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/TocUpdator.pm [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/t/ManualTest/manualTest1.htm [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir1/SubSubDir1/index.htm [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir1/index.htm [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir2/SubSubDir1/index.htm [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir2/SubSubDir2/index.htm [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir2/index.htm [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir3/index.htm [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/t/SiteMap/index.htm [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/t/extend.t [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/t/format.t [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/t/generate.t [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/t/insert.t [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/t/manualTest.t [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/t/options.t [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/t/podExamples.t [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/t/propagate.t [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/t/siteMap.t [new file with mode: 0644]
examples/includes/HTML-Toc-0.91/t/update.t [new file with mode: 0644]
examples/includes/PHP-Markdown-Extra-1.2.3/License.text [new file with mode: 0644]
examples/includes/PHP-Markdown-Extra-1.2.3/PHP Markdown Extra Readme.text [new file with mode: 0644]
examples/includes/PHP-Markdown-Extra-1.2.3/markdown.php [new file with mode: 0644]
examples/includes/PHP-SmartyPants-1.5.1e/PHP SmartyPants Readme.txt [new file with mode: 0644]
examples/includes/PHP-SmartyPants-1.5.1e/smartypants.php [new file with mode: 0644]
examples/includes/geshi/contrib/aliased.php [new file with mode: 0644]
examples/includes/geshi/contrib/cssgen.php [new file with mode: 0644]
examples/includes/geshi/contrib/cssgen2.php [new file with mode: 0644]
examples/includes/geshi/contrib/example.php [new file with mode: 0644]
examples/includes/geshi/contrib/langcheck.php [new file with mode: 0644]
examples/includes/geshi/docs/BUGS [new file with mode: 0644]
examples/includes/geshi/docs/CHANGES [new file with mode: 0644]
examples/includes/geshi/docs/COPYING [new file with mode: 0644]
examples/includes/geshi/docs/README [new file with mode: 0644]
examples/includes/geshi/docs/THANKS [new file with mode: 0644]
examples/includes/geshi/docs/TODO [new file with mode: 0644]
examples/includes/geshi/docs/api/__filesource/fsource_geshi_core_geshi.php.html [new file with mode: 0644]
examples/includes/geshi/docs/api/blank.html [new file with mode: 0644]
examples/includes/geshi/docs/api/classtrees_geshi.html [new file with mode: 0644]
examples/includes/geshi/docs/api/elementindex.html [new file with mode: 0644]
examples/includes/geshi/docs/api/elementindex_geshi.html [new file with mode: 0644]
examples/includes/geshi/docs/api/errors.html [new file with mode: 0644]
examples/includes/geshi/docs/api/geshi/core/GeSHi.html [new file with mode: 0644]
examples/includes/geshi/docs/api/geshi/core/_geshi.php.html [new file with mode: 0644]
examples/includes/geshi/docs/api/index.html [new file with mode: 0644]
examples/includes/geshi/docs/api/li_geshi.html [new file with mode: 0644]
examples/includes/geshi/docs/api/media/banner.css [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/AbstractClass.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/AbstractClass_logo.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/AbstractMethod.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/AbstractPrivateClass.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/AbstractPrivateClass_logo.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/AbstractPrivateMethod.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/Class.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/Class_logo.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/Constant.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/Constructor.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/Destructor.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/Function.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/Global.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/I.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/Index.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/Interface.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/Interface_logo.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/L.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/Lminus.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/Lplus.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/Method.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/Page.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/Page_logo.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/PrivateClass.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/PrivateClass_logo.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/PrivateMethod.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/PrivateVariable.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/StaticMethod.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/StaticVariable.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/T.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/Tminus.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/Tplus.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/Variable.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/blank.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/class_folder.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/empty.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/file.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/folder.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/function_folder.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/next_button.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/next_button_disabled.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/package.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/package_folder.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/previous_button.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/previous_button_disabled.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/private_class_logo.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/tutorial.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/tutorial_folder.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/images/up_button.png [new file with mode: 0644]
examples/includes/geshi/docs/api/media/stylesheet.css [new file with mode: 0644]
examples/includes/geshi/docs/api/packages.html [new file with mode: 0644]
examples/includes/geshi/docs/api/todolist.html [new file with mode: 0644]
examples/includes/geshi/docs/geshi-doc.html [new file with mode: 0644]
examples/includes/geshi/docs/geshi-doc.txt [new file with mode: 0644]
examples/includes/geshi/docs/phpdoc.ini [new file with mode: 0644]
examples/includes/geshi/geshi.php [new file with mode: 0644]
examples/includes/geshi/geshi/abap.php [new file with mode: 0644]
examples/includes/geshi/geshi/actionscript.php [new file with mode: 0644]
examples/includes/geshi/geshi/actionscript3.php [new file with mode: 0644]
examples/includes/geshi/geshi/ada.php [new file with mode: 0644]
examples/includes/geshi/geshi/apache.php [new file with mode: 0644]
examples/includes/geshi/geshi/applescript.php [new file with mode: 0644]
examples/includes/geshi/geshi/apt_sources.php [new file with mode: 0644]
examples/includes/geshi/geshi/asm.php [new file with mode: 0644]
examples/includes/geshi/geshi/asp.php [new file with mode: 0644]
examples/includes/geshi/geshi/autoit.php [new file with mode: 0644]
examples/includes/geshi/geshi/avisynth.php [new file with mode: 0644]
examples/includes/geshi/geshi/bash.php [new file with mode: 0644]
examples/includes/geshi/geshi/basic4gl.php [new file with mode: 0644]
examples/includes/geshi/geshi/bf.php [new file with mode: 0644]
examples/includes/geshi/geshi/blitzbasic.php [new file with mode: 0644]
examples/includes/geshi/geshi/bnf.php [new file with mode: 0644]
examples/includes/geshi/geshi/boo.php [new file with mode: 0644]
examples/includes/geshi/geshi/c.php [new file with mode: 0644]
examples/includes/geshi/geshi/c_mac.php [new file with mode: 0644]
examples/includes/geshi/geshi/caddcl.php [new file with mode: 0644]
examples/includes/geshi/geshi/cadlisp.php [new file with mode: 0644]
examples/includes/geshi/geshi/cfdg.php [new file with mode: 0644]
examples/includes/geshi/geshi/cfm.php [new file with mode: 0644]
examples/includes/geshi/geshi/cil.php [new file with mode: 0644]
examples/includes/geshi/geshi/cobol.php [new file with mode: 0644]
examples/includes/geshi/geshi/cpp-qt.php [new file with mode: 0644]
examples/includes/geshi/geshi/cpp.php [new file with mode: 0644]
examples/includes/geshi/geshi/csharp.php [new file with mode: 0644]
examples/includes/geshi/geshi/css.php [new file with mode: 0644]
examples/includes/geshi/geshi/d.php [new file with mode: 0644]
examples/includes/geshi/geshi/dcs.php [new file with mode: 0644]
examples/includes/geshi/geshi/delphi.php [new file with mode: 0644]
examples/includes/geshi/geshi/diff.php [new file with mode: 0644]
examples/includes/geshi/geshi/div.php [new file with mode: 0644]
examples/includes/geshi/geshi/dos.php [new file with mode: 0644]
examples/includes/geshi/geshi/dot.php [new file with mode: 0644]
examples/includes/geshi/geshi/eiffel.php [new file with mode: 0644]
examples/includes/geshi/geshi/email.php [new file with mode: 0644]
examples/includes/geshi/geshi/fortran.php [new file with mode: 0644]
examples/includes/geshi/geshi/freebasic.php [new file with mode: 0644]
examples/includes/geshi/geshi/genero.php [new file with mode: 0644]
examples/includes/geshi/geshi/gettext.php [new file with mode: 0644]
examples/includes/geshi/geshi/glsl.php [new file with mode: 0644]
examples/includes/geshi/geshi/gml.php [new file with mode: 0644]
examples/includes/geshi/geshi/gnuplot.php [new file with mode: 0644]
examples/includes/geshi/geshi/groovy.php [new file with mode: 0644]
examples/includes/geshi/geshi/haskell.php [new file with mode: 0644]
examples/includes/geshi/geshi/hq9plus.php [new file with mode: 0644]
examples/includes/geshi/geshi/html4strict.php [new file with mode: 0644]
examples/includes/geshi/geshi/idl.php [new file with mode: 0644]
examples/includes/geshi/geshi/ini.php [new file with mode: 0644]
examples/includes/geshi/geshi/inno.php [new file with mode: 0644]
examples/includes/geshi/geshi/intercal.php [new file with mode: 0644]
examples/includes/geshi/geshi/io.php [new file with mode: 0644]
examples/includes/geshi/geshi/java.php [new file with mode: 0644]
examples/includes/geshi/geshi/java5.php [new file with mode: 0644]
examples/includes/geshi/geshi/javascript.php [new file with mode: 0644]
examples/includes/geshi/geshi/kixtart.php [new file with mode: 0644]
examples/includes/geshi/geshi/klonec.php [new file with mode: 0644]
examples/includes/geshi/geshi/klonecpp.php [new file with mode: 0644]
examples/includes/geshi/geshi/latex.php [new file with mode: 0644]
examples/includes/geshi/geshi/lisp.php [new file with mode: 0644]
examples/includes/geshi/geshi/locobasic.php [new file with mode: 0644]
examples/includes/geshi/geshi/lolcode.php [new file with mode: 0644]
examples/includes/geshi/geshi/lotusformulas.php [new file with mode: 0644]
examples/includes/geshi/geshi/lotusscript.php [new file with mode: 0644]
examples/includes/geshi/geshi/lscript.php [new file with mode: 0644]
examples/includes/geshi/geshi/lsl2.php [new file with mode: 0644]
examples/includes/geshi/geshi/lua.php [new file with mode: 0644]
examples/includes/geshi/geshi/m68k.php [new file with mode: 0644]
examples/includes/geshi/geshi/make.php [new file with mode: 0644]
examples/includes/geshi/geshi/matlab.php [new file with mode: 0644]
examples/includes/geshi/geshi/mirc.php [new file with mode: 0644]
examples/includes/geshi/geshi/modula3.php [new file with mode: 0644]
examples/includes/geshi/geshi/mpasm.php [new file with mode: 0644]
examples/includes/geshi/geshi/mxml.php [new file with mode: 0644]
examples/includes/geshi/geshi/mysql.php [new file with mode: 0644]
examples/includes/geshi/geshi/nsis.php [new file with mode: 0644]
examples/includes/geshi/geshi/objc.php [new file with mode: 0644]
examples/includes/geshi/geshi/ocaml-brief.php [new file with mode: 0644]
examples/includes/geshi/geshi/ocaml.php [new file with mode: 0644]
examples/includes/geshi/geshi/oobas.php [new file with mode: 0644]
examples/includes/geshi/geshi/oracle11.php [new file with mode: 0644]
examples/includes/geshi/geshi/oracle8.php [new file with mode: 0644]
examples/includes/geshi/geshi/pascal.php [new file with mode: 0644]
examples/includes/geshi/geshi/per.php [new file with mode: 0644]
examples/includes/geshi/geshi/perl.php [new file with mode: 0644]
examples/includes/geshi/geshi/php-brief.php [new file with mode: 0644]
examples/includes/geshi/geshi/php.php [new file with mode: 0644]
examples/includes/geshi/geshi/pic16.php [new file with mode: 0644]
examples/includes/geshi/geshi/pixelbender.php [new file with mode: 0644]
examples/includes/geshi/geshi/plsql.php [new file with mode: 0644]
examples/includes/geshi/geshi/povray.php [new file with mode: 0644]
examples/includes/geshi/geshi/powershell.php [new file with mode: 0644]
examples/includes/geshi/geshi/progress.php [new file with mode: 0644]
examples/includes/geshi/geshi/prolog.php [new file with mode: 0644]
examples/includes/geshi/geshi/providex.php [new file with mode: 0644]
examples/includes/geshi/geshi/python.php [new file with mode: 0644]
examples/includes/geshi/geshi/qbasic.php [new file with mode: 0644]
examples/includes/geshi/geshi/rails.php [new file with mode: 0644]
examples/includes/geshi/geshi/rebol.php [new file with mode: 0644]
examples/includes/geshi/geshi/reg.php [new file with mode: 0644]
examples/includes/geshi/geshi/robots.php [new file with mode: 0644]
examples/includes/geshi/geshi/ruby.php [new file with mode: 0644]
examples/includes/geshi/geshi/sas.php [new file with mode: 0644]
examples/includes/geshi/geshi/scala.php [new file with mode: 0644]
examples/includes/geshi/geshi/scheme.php [new file with mode: 0644]
examples/includes/geshi/geshi/scilab.php [new file with mode: 0644]
examples/includes/geshi/geshi/sdlbasic.php [new file with mode: 0644]
examples/includes/geshi/geshi/smalltalk.php [new file with mode: 0644]
examples/includes/geshi/geshi/smarty.php [new file with mode: 0644]
examples/includes/geshi/geshi/sql.php [new file with mode: 0644]
examples/includes/geshi/geshi/tcl.php [new file with mode: 0644]
examples/includes/geshi/geshi/teraterm.php [new file with mode: 0644]
examples/includes/geshi/geshi/text.php [new file with mode: 0644]
examples/includes/geshi/geshi/thinbasic.php [new file with mode: 0644]
examples/includes/geshi/geshi/tsql.php [new file with mode: 0644]
examples/includes/geshi/geshi/typoscript.php [new file with mode: 0644]
examples/includes/geshi/geshi/vb.php [new file with mode: 0644]
examples/includes/geshi/geshi/vbnet.php [new file with mode: 0644]
examples/includes/geshi/geshi/verilog.php [new file with mode: 0644]
examples/includes/geshi/geshi/vhdl.php [new file with mode: 0644]
examples/includes/geshi/geshi/vim.php [new file with mode: 0644]
examples/includes/geshi/geshi/visualfoxpro.php [new file with mode: 0644]
examples/includes/geshi/geshi/visualprolog.php [new file with mode: 0644]
examples/includes/geshi/geshi/whitespace.php [new file with mode: 0644]
examples/includes/geshi/geshi/winbatch.php [new file with mode: 0644]
examples/includes/geshi/geshi/xml.php [new file with mode: 0644]
examples/includes/geshi/geshi/xorg_conf.php [new file with mode: 0644]
examples/includes/geshi/geshi/xpp.php [new file with mode: 0644]
examples/includes/geshi/geshi/z80.php [new file with mode: 0644]
examples/includes/vp8_doc_tools.php [new file with mode: 0644]
examples/postproc.txt [new file with mode: 0644]
examples/simple_decoder.txt [new file with mode: 0644]
examples/simple_encoder.txt [new file with mode: 0644]
examples/twopass_encoder.txt [new file with mode: 0644]
examples/vp8_set_maps.txt [new file with mode: 0644]
examples/vp8cx_set_ref.txt [new file with mode: 0644]
keywords.dox [new file with mode: 0644]
libmkv/EbmlBufferWriter.c [new file with mode: 0644]
libmkv/EbmlBufferWriter.h [new file with mode: 0644]
libmkv/EbmlIDs.h [new file with mode: 0644]
libmkv/EbmlWriter.c [new file with mode: 0644]
libmkv/EbmlWriter.h [new file with mode: 0644]
libmkv/Makefile [new file with mode: 0644]
libmkv/WebMElement.c [new file with mode: 0644]
libmkv/WebMElement.h [new file with mode: 0644]
libmkv/testlibmkv.c [new file with mode: 0644]
libs.doxy_template [new file with mode: 0644]
libs.mk [new file with mode: 0644]
mainpage.dox [new file with mode: 0644]
md5_utils.c [new file with mode: 0644]
md5_utils.h [new file with mode: 0644]
nestegg/.gitignore [new file with mode: 0644]
nestegg/AUTHORS [new file with mode: 0644]
nestegg/INSTALL [new file with mode: 0644]
nestegg/LICENSE [new file with mode: 0644]
nestegg/Makefile.am [new file with mode: 0644]
nestegg/README [new file with mode: 0644]
nestegg/TODO [new file with mode: 0644]
nestegg/configure.ac [new file with mode: 0644]
nestegg/docs/Doxyfile.in [new file with mode: 0644]
nestegg/docs/Makefile.am [new file with mode: 0644]
nestegg/halloc/README [new file with mode: 0644]
nestegg/halloc/halloc.h [new file with mode: 0644]
nestegg/halloc/src/align.h [new file with mode: 0644]
nestegg/halloc/src/halloc.c [new file with mode: 0644]
nestegg/halloc/src/hlist.h [new file with mode: 0644]
nestegg/halloc/src/macros.h [new file with mode: 0644]
nestegg/include/nestegg/nestegg.h [new file with mode: 0644]
nestegg/m4/as-ac-expand.m4 [new file with mode: 0644]
nestegg/m4/ax_create_stdint_h.m4 [new file with mode: 0644]
nestegg/m4/pkg.m4 [new file with mode: 0644]
nestegg/nestegg-uninstalled.pc.in [new file with mode: 0644]
nestegg/nestegg.pc.in [new file with mode: 0644]
nestegg/src/nestegg.c [new file with mode: 0644]
nestegg/test/test.c [new file with mode: 0644]
solution.mk [new file with mode: 0644]
third_party/googletest/README.webm [new file with mode: 0644]
third_party/googletest/gtest.mk [new file with mode: 0644]
third_party/googletest/src/CHANGES [new file with mode: 0644]
third_party/googletest/src/CMakeLists.txt [new file with mode: 0644]
third_party/googletest/src/CONTRIBUTORS [new file with mode: 0644]
third_party/googletest/src/COPYING [new file with mode: 0644]
third_party/googletest/src/Makefile.am [new file with mode: 0644]
third_party/googletest/src/README [new file with mode: 0644]
third_party/googletest/src/build-aux/.keep [new file with mode: 0644]
third_party/googletest/src/cmake/internal_utils.cmake [new file with mode: 0644]
third_party/googletest/src/codegear/gtest.cbproj [new file with mode: 0644]
third_party/googletest/src/codegear/gtest.groupproj [new file with mode: 0644]
third_party/googletest/src/codegear/gtest_all.cc [new file with mode: 0644]
third_party/googletest/src/codegear/gtest_link.cc [new file with mode: 0644]
third_party/googletest/src/codegear/gtest_main.cbproj [new file with mode: 0644]
third_party/googletest/src/codegear/gtest_unittest.cbproj [new file with mode: 0644]
third_party/googletest/src/configure.ac [new file with mode: 0644]
third_party/googletest/src/include/gtest/gtest-death-test.h [new file with mode: 0644]
third_party/googletest/src/include/gtest/gtest-message.h [new file with mode: 0644]
third_party/googletest/src/include/gtest/gtest-param-test.h [new file with mode: 0644]
third_party/googletest/src/include/gtest/gtest-param-test.h.pump [new file with mode: 0644]
third_party/googletest/src/include/gtest/gtest-printers.h [new file with mode: 0644]
third_party/googletest/src/include/gtest/gtest-spi.h [new file with mode: 0644]
third_party/googletest/src/include/gtest/gtest-test-part.h [new file with mode: 0644]
third_party/googletest/src/include/gtest/gtest-typed-test.h [new file with mode: 0644]
third_party/googletest/src/include/gtest/gtest.h [new file with mode: 0644]
third_party/googletest/src/include/gtest/gtest_pred_impl.h [new file with mode: 0644]
third_party/googletest/src/include/gtest/gtest_prod.h [new file with mode: 0644]
third_party/googletest/src/include/gtest/internal/gtest-death-test-internal.h [new file with mode: 0644]
third_party/googletest/src/include/gtest/internal/gtest-filepath.h [new file with mode: 0644]
third_party/googletest/src/include/gtest/internal/gtest-internal.h [new file with mode: 0644]
third_party/googletest/src/include/gtest/internal/gtest-linked_ptr.h [new file with mode: 0644]
third_party/googletest/src/include/gtest/internal/gtest-param-util-generated.h [new file with mode: 0644]
third_party/googletest/src/include/gtest/internal/gtest-param-util-generated.h.pump [new file with mode: 0644]
third_party/googletest/src/include/gtest/internal/gtest-param-util.h [new file with mode: 0644]
third_party/googletest/src/include/gtest/internal/gtest-port.h [new file with mode: 0644]
third_party/googletest/src/include/gtest/internal/gtest-string.h [new file with mode: 0644]
third_party/googletest/src/include/gtest/internal/gtest-tuple.h [new file with mode: 0644]
third_party/googletest/src/include/gtest/internal/gtest-tuple.h.pump [new file with mode: 0644]
third_party/googletest/src/include/gtest/internal/gtest-type-util.h [new file with mode: 0644]
third_party/googletest/src/include/gtest/internal/gtest-type-util.h.pump [new file with mode: 0644]
third_party/googletest/src/m4/acx_pthread.m4 [new file with mode: 0644]
third_party/googletest/src/m4/gtest.m4 [new file with mode: 0644]
third_party/googletest/src/make/Makefile [new file with mode: 0644]
third_party/googletest/src/msvc/gtest-md.sln [new file with mode: 0644]
third_party/googletest/src/msvc/gtest-md.vcproj [new file with mode: 0644]
third_party/googletest/src/msvc/gtest.sln [new file with mode: 0644]
third_party/googletest/src/msvc/gtest.vcproj [new file with mode: 0644]
third_party/googletest/src/msvc/gtest_main-md.vcproj [new file with mode: 0644]
third_party/googletest/src/msvc/gtest_main.vcproj [new file with mode: 0644]
third_party/googletest/src/msvc/gtest_prod_test-md.vcproj [new file with mode: 0644]
third_party/googletest/src/msvc/gtest_prod_test.vcproj [new file with mode: 0644]
third_party/googletest/src/msvc/gtest_unittest-md.vcproj [new file with mode: 0644]
third_party/googletest/src/msvc/gtest_unittest.vcproj [new file with mode: 0644]
third_party/googletest/src/samples/prime_tables.h [new file with mode: 0644]
third_party/googletest/src/samples/sample1.cc [new file with mode: 0644]
third_party/googletest/src/samples/sample1.h [new file with mode: 0644]
third_party/googletest/src/samples/sample10_unittest.cc [new file with mode: 0644]
third_party/googletest/src/samples/sample1_unittest.cc [new file with mode: 0644]
third_party/googletest/src/samples/sample2.cc [new file with mode: 0644]
third_party/googletest/src/samples/sample2.h [new file with mode: 0644]
third_party/googletest/src/samples/sample2_unittest.cc [new file with mode: 0644]
third_party/googletest/src/samples/sample3-inl.h [new file with mode: 0644]
third_party/googletest/src/samples/sample3_unittest.cc [new file with mode: 0644]
third_party/googletest/src/samples/sample4.cc [new file with mode: 0644]
third_party/googletest/src/samples/sample4.h [new file with mode: 0644]
third_party/googletest/src/samples/sample4_unittest.cc [new file with mode: 0644]
third_party/googletest/src/samples/sample5_unittest.cc [new file with mode: 0644]
third_party/googletest/src/samples/sample6_unittest.cc [new file with mode: 0644]
third_party/googletest/src/samples/sample7_unittest.cc [new file with mode: 0644]
third_party/googletest/src/samples/sample8_unittest.cc [new file with mode: 0644]
third_party/googletest/src/samples/sample9_unittest.cc [new file with mode: 0644]
third_party/googletest/src/scripts/fuse_gtest_files.py [new file with mode: 0755]
third_party/googletest/src/scripts/gen_gtest_pred_impl.py [new file with mode: 0755]
third_party/googletest/src/scripts/gtest-config.in [new file with mode: 0644]
third_party/googletest/src/scripts/pump.py [new file with mode: 0755]
third_party/googletest/src/scripts/test/Makefile [new file with mode: 0644]
third_party/googletest/src/scripts/upload.py [new file with mode: 0755]
third_party/googletest/src/scripts/upload_gtest.py [new file with mode: 0755]
third_party/googletest/src/src/gtest-all.cc [new file with mode: 0644]
third_party/googletest/src/src/gtest-death-test.cc [new file with mode: 0644]
third_party/googletest/src/src/gtest-filepath.cc [new file with mode: 0644]
third_party/googletest/src/src/gtest-internal-inl.h [new file with mode: 0644]
third_party/googletest/src/src/gtest-port.cc [new file with mode: 0644]
third_party/googletest/src/src/gtest-printers.cc [new file with mode: 0644]
third_party/googletest/src/src/gtest-test-part.cc [new file with mode: 0644]
third_party/googletest/src/src/gtest-typed-test.cc [new file with mode: 0644]
third_party/googletest/src/src/gtest.cc [new file with mode: 0644]
third_party/googletest/src/src/gtest_main.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest-death-test_ex_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest-death-test_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest-filepath_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest-linked_ptr_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest-listener_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest-message_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest-options_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest-param-test2_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest-param-test_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest-param-test_test.h [new file with mode: 0644]
third_party/googletest/src/test/gtest-port_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest-printers_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest-test-part_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest-tuple_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest-typed-test2_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest-typed-test_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest-typed-test_test.h [new file with mode: 0644]
third_party/googletest/src/test/gtest-unittest-api_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_all_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_break_on_failure_unittest.py [new file with mode: 0755]
third_party/googletest/src/test/gtest_break_on_failure_unittest_.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_catch_exceptions_test.py [new file with mode: 0755]
third_party/googletest/src/test/gtest_catch_exceptions_test_.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_color_test.py [new file with mode: 0755]
third_party/googletest/src/test/gtest_color_test_.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_env_var_test.py [new file with mode: 0755]
third_party/googletest/src/test/gtest_env_var_test_.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_environment_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_filter_unittest.py [new file with mode: 0755]
third_party/googletest/src/test/gtest_filter_unittest_.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_help_test.py [new file with mode: 0755]
third_party/googletest/src/test/gtest_help_test_.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_list_tests_unittest.py [new file with mode: 0755]
third_party/googletest/src/test/gtest_list_tests_unittest_.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_main_unittest.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_no_test_unittest.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_output_test.py [new file with mode: 0755]
third_party/googletest/src/test/gtest_output_test_.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_output_test_golden_lin.txt [new file with mode: 0644]
third_party/googletest/src/test/gtest_pred_impl_unittest.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_prod_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_repeat_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_shuffle_test.py [new file with mode: 0755]
third_party/googletest/src/test/gtest_shuffle_test_.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_sole_header_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_stress_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_test_utils.py [new file with mode: 0755]
third_party/googletest/src/test/gtest_throw_on_failure_ex_test.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_throw_on_failure_test.py [new file with mode: 0755]
third_party/googletest/src/test/gtest_throw_on_failure_test_.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_uninitialized_test.py [new file with mode: 0755]
third_party/googletest/src/test/gtest_uninitialized_test_.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_unittest.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_xml_outfile1_test_.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_xml_outfile2_test_.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_xml_outfiles_test.py [new file with mode: 0755]
third_party/googletest/src/test/gtest_xml_output_unittest.py [new file with mode: 0755]
third_party/googletest/src/test/gtest_xml_output_unittest_.cc [new file with mode: 0644]
third_party/googletest/src/test/gtest_xml_test_utils.py [new file with mode: 0755]
third_party/googletest/src/test/production.cc [new file with mode: 0644]
third_party/googletest/src/test/production.h [new file with mode: 0644]
third_party/googletest/src/xcode/Config/DebugProject.xcconfig [new file with mode: 0644]
third_party/googletest/src/xcode/Config/FrameworkTarget.xcconfig [new file with mode: 0644]
third_party/googletest/src/xcode/Config/General.xcconfig [new file with mode: 0644]
third_party/googletest/src/xcode/Config/ReleaseProject.xcconfig [new file with mode: 0644]
third_party/googletest/src/xcode/Config/StaticLibraryTarget.xcconfig [new file with mode: 0644]
third_party/googletest/src/xcode/Config/TestTarget.xcconfig [new file with mode: 0644]
third_party/googletest/src/xcode/Resources/Info.plist [new file with mode: 0644]
third_party/googletest/src/xcode/Samples/FrameworkSample/Info.plist [new file with mode: 0644]
third_party/googletest/src/xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj [new file with mode: 0644]
third_party/googletest/src/xcode/Samples/FrameworkSample/runtests.sh [new file with mode: 0755]
third_party/googletest/src/xcode/Samples/FrameworkSample/widget.cc [new file with mode: 0644]
third_party/googletest/src/xcode/Samples/FrameworkSample/widget.h [new file with mode: 0644]
third_party/googletest/src/xcode/Samples/FrameworkSample/widget_test.cc [new file with mode: 0644]
third_party/googletest/src/xcode/Scripts/runtests.sh [new file with mode: 0755]
third_party/googletest/src/xcode/Scripts/versiongenerate.py [new file with mode: 0755]
third_party/googletest/src/xcode/gtest.xcodeproj/project.pbxproj [new file with mode: 0644]
third_party/libyuv/README.webm [new file with mode: 0644]
third_party/libyuv/include/libyuv/basic_types.h [new file with mode: 0644]
third_party/libyuv/include/libyuv/cpu_id.h [new file with mode: 0644]
third_party/libyuv/include/libyuv/scale.h [new file with mode: 0644]
third_party/libyuv/source/cpu_id.c [new file with mode: 0644]
third_party/libyuv/source/row.h [new file with mode: 0644]
third_party/libyuv/source/scale.c [new file with mode: 0644]
tools/author_first_release.sh [new file with mode: 0755]
tools/ftfy.sh [new file with mode: 0755]
tools/gen_authors.sh [new file with mode: 0755]
tools/intersect-diffs.py [new file with mode: 0755]
tools/wrap-commit-msg.py [new file with mode: 0755]
tools_common.c [new file with mode: 0644]
tools_common.h [new file with mode: 0644]
usage.dox [new file with mode: 0644]
usage_cx.dox [new file with mode: 0644]
usage_dx.dox [new file with mode: 0644]
vp8/common/alloccommon.c [new file with mode: 0644]
vp8/common/alloccommon.h [new file with mode: 0644]
vp8/common/arm/armv6/bilinearfilter_v6.asm [new file with mode: 0644]
vp8/common/arm/armv6/copymem16x16_v6.asm [new file with mode: 0644]
vp8/common/arm/armv6/copymem8x4_v6.asm [new file with mode: 0644]
vp8/common/arm/armv6/copymem8x8_v6.asm [new file with mode: 0644]
vp8/common/arm/armv6/dc_only_idct_add_v6.asm [new file with mode: 0644]
vp8/common/arm/armv6/dequant_idct_v6.asm [new file with mode: 0644]
vp8/common/arm/armv6/dequantize_v6.asm [new file with mode: 0644]
vp8/common/arm/armv6/filter_v6.asm [new file with mode: 0644]
vp8/common/arm/armv6/idct_blk_v6.c [new file with mode: 0644]
vp8/common/arm/armv6/idct_v6.asm [new file with mode: 0644]
vp8/common/arm/armv6/intra4x4_predict_v6.asm [new file with mode: 0644]
vp8/common/arm/armv6/iwalsh_v6.asm [new file with mode: 0644]
vp8/common/arm/armv6/loopfilter_v6.asm [new file with mode: 0644]
vp8/common/arm/armv6/simpleloopfilter_v6.asm [new file with mode: 0644]
vp8/common/arm/armv6/sixtappredict8x4_v6.asm [new file with mode: 0644]
vp8/common/arm/armv6/vp8_sad16x16_armv6.asm [new file with mode: 0644]
vp8/common/arm/armv6/vp8_variance16x16_armv6.asm [new file with mode: 0644]
vp8/common/arm/armv6/vp8_variance8x8_armv6.asm [new file with mode: 0644]
vp8/common/arm/armv6/vp8_variance_halfpixvar16x16_h_armv6.asm [new file with mode: 0644]
vp8/common/arm/armv6/vp8_variance_halfpixvar16x16_hv_armv6.asm [new file with mode: 0644]
vp8/common/arm/armv6/vp8_variance_halfpixvar16x16_v_armv6.asm [new file with mode: 0644]
vp8/common/arm/bilinearfilter_arm.c [new file with mode: 0644]
vp8/common/arm/bilinearfilter_arm.h [new file with mode: 0644]
vp8/common/arm/dequantize_arm.c [new file with mode: 0644]
vp8/common/arm/filter_arm.c [new file with mode: 0644]
vp8/common/arm/loopfilter_arm.c [new file with mode: 0644]
vp8/common/arm/neon/bilinearpredict16x16_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/bilinearpredict4x4_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/bilinearpredict8x4_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/bilinearpredict8x8_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/buildintrapredictorsmby_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/copymem16x16_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/copymem8x4_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/copymem8x8_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/dc_only_idct_add_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/dequant_idct_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/dequantizeb_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/idct_blk_neon.c [new file with mode: 0644]
vp8/common/arm/neon/idct_dequant_0_2x_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/idct_dequant_full_2x_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/iwalsh_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/loopfilter_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/loopfiltersimplehorizontaledge_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/loopfiltersimpleverticaledge_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/mbloopfilter_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/sad16_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/sad8_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/save_reg_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/shortidct4x4llm_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/sixtappredict16x16_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/sixtappredict4x4_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/sixtappredict8x4_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/sixtappredict8x8_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/variance_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/vp8_subpixelvariance16x16_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/vp8_subpixelvariance16x16s_neon.asm [new file with mode: 0644]
vp8/common/arm/neon/vp8_subpixelvariance8x8_neon.asm [new file with mode: 0644]
vp8/common/arm/reconintra_arm.c [new file with mode: 0644]
vp8/common/arm/variance_arm.c [new file with mode: 0644]
vp8/common/asm_com_offsets.c [new file with mode: 0644]
vp8/common/blockd.c [new file with mode: 0644]
vp8/common/blockd.h [new file with mode: 0644]
vp8/common/coefupdateprobs.h [new file with mode: 0644]
vp8/common/common.h [new file with mode: 0644]
vp8/common/context.c [new file with mode: 0644]
vp8/common/debugmodes.c [new file with mode: 0644]
vp8/common/default_coef_probs.h [new file with mode: 0644]
vp8/common/dequantize.c [new file with mode: 0644]
vp8/common/entropy.c [new file with mode: 0644]
vp8/common/entropy.h [new file with mode: 0644]
vp8/common/entropymode.c [new file with mode: 0644]
vp8/common/entropymode.h [new file with mode: 0644]
vp8/common/entropymv.c [new file with mode: 0644]
vp8/common/entropymv.h [new file with mode: 0644]
vp8/common/extend.c [new file with mode: 0644]
vp8/common/extend.h [new file with mode: 0644]
vp8/common/filter.c [new file with mode: 0644]
vp8/common/filter.h [new file with mode: 0644]
vp8/common/findnearmv.c [new file with mode: 0644]
vp8/common/findnearmv.h [new file with mode: 0644]
vp8/common/generic/systemdependent.c [new file with mode: 0644]
vp8/common/header.h [new file with mode: 0644]
vp8/common/idct_blk.c [new file with mode: 0644]
vp8/common/idctllm.c [new file with mode: 0644]
vp8/common/idctllm_test.cc [new file with mode: 0755]
vp8/common/idctllm_test.h [new file with mode: 0755]
vp8/common/invtrans.h [new file with mode: 0644]
vp8/common/loopfilter.c [new file with mode: 0644]
vp8/common/loopfilter.h [new file with mode: 0644]
vp8/common/loopfilter_filters.c [new file with mode: 0644]
vp8/common/mbpitch.c [new file with mode: 0644]
vp8/common/mfqe.c [new file with mode: 0644]
vp8/common/modecont.c [new file with mode: 0644]
vp8/common/modecont.h [new file with mode: 0644]
vp8/common/mv.h [new file with mode: 0644]
vp8/common/onyx.h [new file with mode: 0644]
vp8/common/onyxc_int.h [new file with mode: 0644]
vp8/common/onyxd.h [new file with mode: 0644]
vp8/common/postproc.c [new file with mode: 0644]
vp8/common/postproc.h [new file with mode: 0644]
vp8/common/ppc/copy_altivec.asm [new file with mode: 0644]
vp8/common/ppc/filter_altivec.asm [new file with mode: 0644]
vp8/common/ppc/filter_bilinear_altivec.asm [new file with mode: 0644]
vp8/common/ppc/idctllm_altivec.asm [new file with mode: 0644]
vp8/common/ppc/loopfilter_altivec.c [new file with mode: 0644]
vp8/common/ppc/loopfilter_filters_altivec.asm [new file with mode: 0644]
vp8/common/ppc/platform_altivec.asm [new file with mode: 0644]
vp8/common/ppc/recon_altivec.asm [new file with mode: 0644]
vp8/common/ppc/sad_altivec.asm [new file with mode: 0644]
vp8/common/ppc/systemdependent.c [new file with mode: 0644]
vp8/common/ppc/variance_altivec.asm [new file with mode: 0644]
vp8/common/ppc/variance_subpixel_altivec.asm [new file with mode: 0644]
vp8/common/ppflags.h [new file with mode: 0644]
vp8/common/pragmas.h [new file with mode: 0644]
vp8/common/quant_common.c [new file with mode: 0644]
vp8/common/quant_common.h [new file with mode: 0644]
vp8/common/reconinter.c [new file with mode: 0644]
vp8/common/reconinter.h [new file with mode: 0644]
vp8/common/reconintra.c [new file with mode: 0644]
vp8/common/reconintra4x4.c [new file with mode: 0644]
vp8/common/reconintra4x4.h [new file with mode: 0644]
vp8/common/rtcd.c [new file with mode: 0644]
vp8/common/rtcd_defs.sh [new file with mode: 0644]
vp8/common/sad_c.c [new file with mode: 0644]
vp8/common/setupintrarecon.c [new file with mode: 0644]
vp8/common/setupintrarecon.h [new file with mode: 0644]
vp8/common/swapyv12buffer.c [new file with mode: 0644]
vp8/common/swapyv12buffer.h [new file with mode: 0644]
vp8/common/systemdependent.h [new file with mode: 0644]
vp8/common/textblit.c [new file with mode: 0644]
vp8/common/threading.h [new file with mode: 0644]
vp8/common/treecoder.c [new file with mode: 0644]
vp8/common/treecoder.h [new file with mode: 0644]
vp8/common/variance.h [new file with mode: 0644]
vp8/common/variance_c.c [new file with mode: 0644]
vp8/common/vp8_entropymodedata.h [new file with mode: 0755]
vp8/common/x86/dequantize_mmx.asm [new file with mode: 0644]
vp8/common/x86/filter_x86.c [new file with mode: 0644]
vp8/common/x86/filter_x86.h [new file with mode: 0644]
vp8/common/x86/idct_blk_mmx.c [new file with mode: 0644]
vp8/common/x86/idct_blk_sse2.c [new file with mode: 0644]
vp8/common/x86/idctllm_mmx.asm [new file with mode: 0644]
vp8/common/x86/idctllm_mmx_test.cc [new file with mode: 0755]
vp8/common/x86/idctllm_sse2.asm [new file with mode: 0644]
vp8/common/x86/iwalsh_mmx.asm [new file with mode: 0644]
vp8/common/x86/iwalsh_sse2.asm [new file with mode: 0644]
vp8/common/x86/loopfilter_block_sse2.asm [new file with mode: 0644]
vp8/common/x86/loopfilter_mmx.asm [new file with mode: 0644]
vp8/common/x86/loopfilter_sse2.asm [new file with mode: 0644]
vp8/common/x86/loopfilter_x86.c [new file with mode: 0644]
vp8/common/x86/mfqe_sse2.asm [new file with mode: 0644]
vp8/common/x86/postproc_mmx.asm [new file with mode: 0644]
vp8/common/x86/postproc_sse2.asm [new file with mode: 0644]
vp8/common/x86/postproc_x86.c [new file with mode: 0644]
vp8/common/x86/recon_mmx.asm [new file with mode: 0644]
vp8/common/x86/recon_sse2.asm [new file with mode: 0644]
vp8/common/x86/recon_wrapper_sse2.c [new file with mode: 0644]
vp8/common/x86/sad_mmx.asm [new file with mode: 0644]
vp8/common/x86/sad_sse2.asm [new file with mode: 0644]
vp8/common/x86/sad_sse3.asm [new file with mode: 0644]
vp8/common/x86/sad_sse4.asm [new file with mode: 0644]
vp8/common/x86/sad_ssse3.asm [new file with mode: 0644]
vp8/common/x86/subpixel_mmx.asm [new file with mode: 0644]
vp8/common/x86/subpixel_sse2.asm [new file with mode: 0644]
vp8/common/x86/subpixel_ssse3.asm [new file with mode: 0644]
vp8/common/x86/variance_impl_mmx.asm [new file with mode: 0644]
vp8/common/x86/variance_impl_sse2.asm [new file with mode: 0644]
vp8/common/x86/variance_impl_ssse3.asm [new file with mode: 0644]
vp8/common/x86/variance_mmx.c [new file with mode: 0644]
vp8/common/x86/variance_sse2.c [new file with mode: 0644]
vp8/common/x86/variance_ssse3.c [new file with mode: 0644]
vp8/common/x86/vp8_asm_stubs.c [new file with mode: 0644]
vp8/decoder/asm_dec_offsets.c [new file with mode: 0644]
vp8/decoder/dboolhuff.c [new file with mode: 0644]
vp8/decoder/dboolhuff.h [new file with mode: 0644]
vp8/decoder/decodemv.c [new file with mode: 0644]
vp8/decoder/decodemv.h [new file with mode: 0644]
vp8/decoder/decoderthreading.h [new file with mode: 0644]
vp8/decoder/decodframe.c [new file with mode: 0644]
vp8/decoder/detokenize.c [new file with mode: 0644]
vp8/decoder/detokenize.h [new file with mode: 0644]
vp8/decoder/ec_types.h [new file with mode: 0644]
vp8/decoder/error_concealment.c [new file with mode: 0644]
vp8/decoder/error_concealment.h [new file with mode: 0644]
vp8/decoder/onyxd_if.c [new file with mode: 0644]
vp8/decoder/onyxd_int.h [new file with mode: 0644]
vp8/decoder/threading.c [new file with mode: 0644]
vp8/decoder/treereader.h [new file with mode: 0644]
vp8/encoder/arm/armv5te/boolhuff_armv5te.asm [new file with mode: 0644]
vp8/encoder/arm/armv5te/vp8_packtokens_armv5.asm [new file with mode: 0644]
vp8/encoder/arm/armv5te/vp8_packtokens_mbrow_armv5.asm [new file with mode: 0644]
vp8/encoder/arm/armv5te/vp8_packtokens_partitions_armv5.asm [new file with mode: 0644]
vp8/encoder/arm/armv6/vp8_fast_quantize_b_armv6.asm [new file with mode: 0644]
vp8/encoder/arm/armv6/vp8_mse16x16_armv6.asm [new file with mode: 0644]
vp8/encoder/arm/armv6/vp8_short_fdct4x4_armv6.asm [new file with mode: 0644]
vp8/encoder/arm/armv6/vp8_subtract_armv6.asm [new file with mode: 0644]
vp8/encoder/arm/armv6/walsh_v6.asm [new file with mode: 0644]
vp8/encoder/arm/boolhuff_arm.c [new file with mode: 0644]
vp8/encoder/arm/dct_arm.c [new file with mode: 0644]
vp8/encoder/arm/neon/fastquantizeb_neon.asm [new file with mode: 0644]
vp8/encoder/arm/neon/picklpf_arm.c [new file with mode: 0644]
vp8/encoder/arm/neon/shortfdct_neon.asm [new file with mode: 0644]
vp8/encoder/arm/neon/subtract_neon.asm [new file with mode: 0644]
vp8/encoder/arm/neon/vp8_memcpy_neon.asm [new file with mode: 0644]
vp8/encoder/arm/neon/vp8_mse16x16_neon.asm [new file with mode: 0644]
vp8/encoder/arm/neon/vp8_shortwalsh4x4_neon.asm [new file with mode: 0644]
vp8/encoder/arm/quantize_arm.c [new file with mode: 0644]
vp8/encoder/asm_enc_offsets.c [new file with mode: 0644]
vp8/encoder/bitstream.c [new file with mode: 0644]
vp8/encoder/bitstream.h [new file with mode: 0644]
vp8/encoder/block.h [new file with mode: 0644]
vp8/encoder/boolhuff.c [new file with mode: 0644]
vp8/encoder/boolhuff.h [new file with mode: 0644]
vp8/encoder/dct.c [new file with mode: 0644]
vp8/encoder/dct_value_cost.h [new file with mode: 0644]
vp8/encoder/dct_value_tokens.h [new file with mode: 0644]
vp8/encoder/defaultcoefcounts.h [new file with mode: 0644]
vp8/encoder/denoising.c [new file with mode: 0644]
vp8/encoder/denoising.h [new file with mode: 0644]
vp8/encoder/encodeframe.c [new file with mode: 0644]
vp8/encoder/encodeframe.h [new file with mode: 0644]
vp8/encoder/encodeintra.c [new file with mode: 0644]
vp8/encoder/encodeintra.h [new file with mode: 0644]
vp8/encoder/encodemb.c [new file with mode: 0644]
vp8/encoder/encodemb.h [new file with mode: 0644]
vp8/encoder/encodemv.c [new file with mode: 0644]
vp8/encoder/encodemv.h [new file with mode: 0644]
vp8/encoder/ethreading.c [new file with mode: 0644]
vp8/encoder/firstpass.c [new file with mode: 0644]
vp8/encoder/firstpass.h [new file with mode: 0644]
vp8/encoder/lookahead.c [new file with mode: 0644]
vp8/encoder/lookahead.h [new file with mode: 0644]
vp8/encoder/mcomp.c [new file with mode: 0644]
vp8/encoder/mcomp.h [new file with mode: 0644]
vp8/encoder/modecosts.c [new file with mode: 0644]
vp8/encoder/modecosts.h [new file with mode: 0644]
vp8/encoder/mr_dissim.c [new file with mode: 0644]
vp8/encoder/mr_dissim.h [new file with mode: 0644]
vp8/encoder/onyx_if.c [new file with mode: 0644]
vp8/encoder/onyx_int.h [new file with mode: 0644]
vp8/encoder/pickinter.c [new file with mode: 0644]
vp8/encoder/pickinter.h [new file with mode: 0644]
vp8/encoder/picklpf.c [new file with mode: 0644]
vp8/encoder/ppc/csystemdependent.c [new file with mode: 0644]
vp8/encoder/ppc/encodemb_altivec.asm [new file with mode: 0644]
vp8/encoder/ppc/fdct_altivec.asm [new file with mode: 0644]
vp8/encoder/ppc/rdopt_altivec.asm [new file with mode: 0644]
vp8/encoder/psnr.c [new file with mode: 0644]
vp8/encoder/psnr.h [new file with mode: 0644]
vp8/encoder/quantize.c [new file with mode: 0644]
vp8/encoder/quantize.h [new file with mode: 0644]
vp8/encoder/ratectrl.c [new file with mode: 0644]
vp8/encoder/ratectrl.h [new file with mode: 0644]
vp8/encoder/rdopt.c [new file with mode: 0644]
vp8/encoder/rdopt.h [new file with mode: 0644]
vp8/encoder/segmentation.c [new file with mode: 0644]
vp8/encoder/segmentation.h [new file with mode: 0644]
vp8/encoder/ssim.c [new file with mode: 0644]
vp8/encoder/temporal_filter.c [new file with mode: 0644]
vp8/encoder/tokenize.c [new file with mode: 0644]
vp8/encoder/tokenize.h [new file with mode: 0644]
vp8/encoder/treewriter.c [new file with mode: 0644]
vp8/encoder/treewriter.h [new file with mode: 0644]
vp8/encoder/x86/dct_mmx.asm [new file with mode: 0644]
vp8/encoder/x86/dct_sse2.asm [new file with mode: 0644]
vp8/encoder/x86/encodeopt.asm [new file with mode: 0644]
vp8/encoder/x86/fwalsh_sse2.asm [new file with mode: 0644]
vp8/encoder/x86/quantize_mmx.asm [new file with mode: 0644]
vp8/encoder/x86/quantize_sse2.asm [new file with mode: 0644]
vp8/encoder/x86/quantize_sse4.asm [new file with mode: 0644]
vp8/encoder/x86/quantize_ssse3.asm [new file with mode: 0644]
vp8/encoder/x86/ssim_opt.asm [new file with mode: 0644]
vp8/encoder/x86/subtract_mmx.asm [new file with mode: 0644]
vp8/encoder/x86/subtract_sse2.asm [new file with mode: 0644]
vp8/encoder/x86/temporal_filter_apply_sse2.asm [new file with mode: 0644]
vp8/encoder/x86/vp8_enc_stubs_mmx.c [new file with mode: 0644]
vp8/encoder/x86/vp8_enc_stubs_sse2.c [new file with mode: 0644]
vp8/exports_dec [new file with mode: 0644]
vp8/exports_enc [new file with mode: 0644]
vp8/vp8_common.mk [new file with mode: 0644]
vp8/vp8_cx_iface.c [new file with mode: 0644]
vp8/vp8_dx_iface.c [new file with mode: 0644]
vp8/vp8cx.mk [new file with mode: 0644]
vp8/vp8cx_arm.mk [new file with mode: 0644]
vp8/vp8dx.mk [new file with mode: 0644]
vp8_multi_resolution_encoder.c [new file with mode: 0644]
vp8_scalable_patterns.c [new file with mode: 0644]
vpx/exports_com [new file with mode: 0644]
vpx/exports_dec [new file with mode: 0644]
vpx/exports_enc [new file with mode: 0644]
vpx/internal/vpx_codec_internal.h [new file with mode: 0644]
vpx/src/vpx_codec.c [new file with mode: 0644]
vpx/src/vpx_decoder.c [new file with mode: 0644]
vpx/src/vpx_encoder.c [new file with mode: 0644]
vpx/src/vpx_image.c [new file with mode: 0644]
vpx/vp8.h [new file with mode: 0644]
vpx/vp8cx.h [new file with mode: 0644]
vpx/vp8dx.h [new file with mode: 0644]
vpx/vpx_codec.h [new file with mode: 0644]
vpx/vpx_codec.mk [new file with mode: 0644]
vpx/vpx_codec_impl_bottom.h [new file with mode: 0644]
vpx/vpx_codec_impl_top.h [new file with mode: 0644]
vpx/vpx_decoder.h [new file with mode: 0644]
vpx/vpx_encoder.h [new file with mode: 0644]
vpx/vpx_image.h [new file with mode: 0644]
vpx/vpx_integer.h [new file with mode: 0644]
vpx_mem/include/vpx_mem_intrnl.h [new file with mode: 0644]
vpx_mem/include/vpx_mem_tracker.h [new file with mode: 0644]
vpx_mem/memory_manager/hmm_alloc.c [new file with mode: 0644]
vpx_mem/memory_manager/hmm_base.c [new file with mode: 0644]
vpx_mem/memory_manager/hmm_dflt_abort.c [new file with mode: 0644]
vpx_mem/memory_manager/hmm_grow.c [new file with mode: 0644]
vpx_mem/memory_manager/hmm_largest.c [new file with mode: 0644]
vpx_mem/memory_manager/hmm_resize.c [new file with mode: 0644]
vpx_mem/memory_manager/hmm_shrink.c [new file with mode: 0644]
vpx_mem/memory_manager/hmm_true.c [new file with mode: 0644]
vpx_mem/memory_manager/include/cavl_if.h [new file with mode: 0644]
vpx_mem/memory_manager/include/cavl_impl.h [new file with mode: 0644]
vpx_mem/memory_manager/include/heapmm.h [new file with mode: 0644]
vpx_mem/memory_manager/include/hmm_cnfg.h [new file with mode: 0644]
vpx_mem/memory_manager/include/hmm_intrnl.h [new file with mode: 0644]
vpx_mem/vpx_mem.c [new file with mode: 0644]
vpx_mem/vpx_mem.h [new file with mode: 0644]
vpx_mem/vpx_mem.mk [new file with mode: 0644]
vpx_mem/vpx_mem_tracker.c [new file with mode: 0644]
vpx_ports/arm.h [new file with mode: 0644]
vpx_ports/arm_cpudetect.c [new file with mode: 0644]
vpx_ports/asm_offsets.h [new file with mode: 0644]
vpx_ports/emms.asm [new file with mode: 0644]
vpx_ports/mem.h [new file with mode: 0644]
vpx_ports/mem_ops.h [new file with mode: 0644]
vpx_ports/mem_ops_aligned.h [new file with mode: 0644]
vpx_ports/vpx_timer.h [new file with mode: 0644]
vpx_ports/vpxtypes.h [new file with mode: 0644]
vpx_ports/x86.h [new file with mode: 0644]
vpx_ports/x86_abi_support.asm [new file with mode: 0644]
vpx_ports/x86_cpuid.c [new file with mode: 0644]
vpx_scale/arm/neon/vp8_vpxyv12_copy_y_neon.asm [new file with mode: 0644]
vpx_scale/arm/neon/vp8_vpxyv12_copyframe_func_neon.asm [new file with mode: 0644]
vpx_scale/arm/neon/vp8_vpxyv12_copysrcframe_func_neon.asm [new file with mode: 0644]
vpx_scale/arm/neon/vp8_vpxyv12_extendframeborders_neon.asm [new file with mode: 0644]
vpx_scale/arm/neon/yv12extend_arm.c [new file with mode: 0644]
vpx_scale/generic/bicubic_scaler.c [new file with mode: 0644]
vpx_scale/generic/gen_scalers.c [new file with mode: 0644]
vpx_scale/generic/vpxscale.c [new file with mode: 0644]
vpx_scale/generic/yv12config.c [new file with mode: 0644]
vpx_scale/generic/yv12extend.c [new file with mode: 0644]
vpx_scale/generic/yv12extend_generic.h [new file with mode: 0644]
vpx_scale/include/generic/vpxscale_arbitrary.h [new file with mode: 0644]
vpx_scale/include/generic/vpxscale_depricated.h [new file with mode: 0644]
vpx_scale/scale_mode.h [new file with mode: 0644]
vpx_scale/vpx_scale.mk [new file with mode: 0644]
vpx_scale/vpxscale.h [new file with mode: 0644]
vpx_scale/win32/scaleopt.c [new file with mode: 0644]
vpx_scale/win32/scalesystemdependent.c [new file with mode: 0644]
vpx_scale/yv12config.h [new file with mode: 0644]
vpxdec.c [new file with mode: 0644]
vpxenc.c [new file with mode: 0644]
y4minput.c [new file with mode: 0644]
y4minput.h [new file with mode: 0644]

diff --git a/.gitattributes b/.gitattributes
new file mode 100644 (file)
index 0000000..ffc6912
--- /dev/null
@@ -0,0 +1,18 @@
+*.[chs]      filter=fixtabswsp
+*.[ch]pp     filter=fixtabswsp
+*.[ch]xx     filter=fixtabswsp
+*.asm        filter=fixtabswsp
+*.php        filter=fixtabswsp
+*.pl         filter=fixtabswsp
+*.sh         filter=fixtabswsp
+*.txt       filter=fixwsp
+[Mm]akefile  filter=fixwsp
+*.mk         filter=fixwsp
+*.rc         -crlf
+*.ds[pw]     -crlf
+*.bat        -crlf
+*.mmp        -crlf
+*.dpj        -crlf
+*.pjt        -crlf
+*.vcp        -crlf
+*.inf        -crlf
diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..110146d
--- /dev/null
@@ -0,0 +1,61 @@
+*.a
+*.asm.s
+*.d
+*.o
+*~
+/*-*.mk
+/*.asm
+/*.doxy
+/.bins
+/.deps
+/.docs
+/.install-*
+/.libs
+/Makefile
+/config.err
+/config.mk
+/decode_to_md5
+/decode_to_md5.c
+/decode_to_md5.dox
+/decode_with_drops
+/decode_with_drops.c
+/decode_with_drops.dox
+/docs/
+/doxyfile
+/error_resilient
+/error_resilient.c
+/error_resilient.dox
+/force_keyframe
+/force_keyframe.c
+/force_keyframe.dox
+/ivfdec
+/ivfdec.dox
+/ivfenc
+/ivfenc.dox
+/obj_int_extract
+/postproc
+/postproc.c
+/postproc.dox
+/samples.dox
+/simple_decoder
+/simple_decoder.c
+/simple_decoder.dox
+/simple_encoder
+/simple_encoder.c
+/simple_encoder.dox
+/twopass_encoder
+/twopass_encoder.c
+/twopass_encoder.dox
+/vp8_api1_migration.dox
+/vp8_scalable_patterns
+/vp8_scalable_patterns.dox
+/vp8_set_maps
+/vp8_set_maps.c
+/vp8_set_maps.dox
+/vp8cx_set_ref
+/vp8cx_set_ref.c
+/vp8cx_set_ref.dox
+/vpx_config.c
+/vpx_config.h
+/vpx_version.h
+TAGS
diff --git a/.mailmap b/.mailmap
new file mode 100644 (file)
index 0000000..ba1279b
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,8 @@
+Adrian Grange <agrange@google.com>
+Johann Koenig <johannkoenig@google.com>
+Tero Rintaluoma <teror@google.com> <tero.rintaluoma@on2.com>
+Tom Finegan <tomfinegan@google.com>
+Ralph Giles <giles@xiph.org> <giles@entropywave.com>
+Ralph Giles <giles@xiph.org> <giles@mozilla.com>
+Alpha Lam <hclam@google.com> <hclam@chromium.org>
+Deb Mukherjee <debargha@google.com>
diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..0937d5d
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,65 @@
+# This file is automatically generated from the git commit history
+# by tools/gen_authors.sh.
+
+Aaron Watry <awatry@gmail.com>
+Adrian Grange <agrange@google.com>
+Alex Converse <alex.converse@gmail.com>
+Alexis Ballier <aballier@gentoo.org>
+Alok Ahuja <waveletcoeff@gmail.com>
+Alpha Lam <hclam@google.com>
+Andoni Morales Alastruey <ylatuya@gmail.com>
+Andres Mejia <mcitadel@gmail.com>
+Aron Rosenberg <arosenberg@logitech.com>
+Attila Nagy <attilanagy@google.com>
+Deb Mukherjee <debargha@google.com>
+Fabio Pedretti <fabio.ped@libero.it>
+Frank Galligan <fgalligan@google.com>
+Fredrik Söderquist <fs@opera.com>
+Fritz Koenig <frkoenig@google.com>
+Gaute Strokkenes <gaute.strokkenes@broadcom.com>
+Giuseppe Scrivano <gscrivano@gnu.org>
+Guillermo Ballester Valor <gbvalor@gmail.com>
+Henrik Lundin <hlundin@google.com>
+James Berry <jamesberry@google.com>
+James Zern <jzern@google.com>
+Jan Kratochvil <jan.kratochvil@redhat.com>
+Jeff Faust <jfaust@google.com>
+Jeff Muizelaar <jmuizelaar@mozilla.com>
+Jim Bankoski <jimbankoski@google.com>
+Johann Koenig <johannkoenig@google.com>
+John Koleszar <jkoleszar@google.com>
+Joshua Bleecher Snyder <josh@treelinelabs.com>
+Justin Clift <justin@salasaga.org>
+Justin Lebar <justin.lebar@gmail.com>
+KO Myung-Hun <komh@chollian.net>
+Lou Quillio <louquillio@google.com>
+Luca Barbato <lu_zero@gentoo.org>
+Makoto Kato <makoto.kt@gmail.com>
+Marco Paniconi <marpan@google.com>
+Martin Ettl <ettl.martin78@googlemail.com>
+Michael Kohler <michaelkohler@live.com>
+Mike Hommey <mhommey@mozilla.com>
+Mikhal Shemer <mikhal@google.com>
+Pascal Massimino <pascal.massimino@gmail.com>
+Patrik Westin <patrik.westin@gmail.com>
+Paul Wilkins <paulwilkins@google.com>
+Pavol Rusnak <stick@gk2.sk>
+Philip Jägenstedt <philipj@opera.com>
+Priit Laes <plaes@plaes.org>
+Rafael Ávila de Espíndola <rafael.espindola@gmail.com>
+Rafaël Carré <funman@videolan.org>
+Ralph Giles <giles@xiph.org>
+Ronald S. Bultje <rbultje@google.com>
+Scott LaVarnway <slavarnway@google.com>
+Stefan Holmer <holmer@google.com>
+Taekhyun Kim <takim@nvidia.com>
+Takanori MATSUURA <t.matsuu@gmail.com>
+Tero Rintaluoma <teror@google.com>
+Thijs Vermeir <thijsvermeir@gmail.com>
+Timothy B. Terriberry <tterribe@xiph.org>
+Tom Finegan <tomfinegan@google.com>
+Yaowu Xu <yaowu@google.com>
+Yunqing Wang <yunqingwang@google.com>
+Google Inc.
+The Mozilla Foundation
+The Xiph.Org Foundation
diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644 (file)
index 0000000..dcb9f73
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,505 @@
+2012-05-09 v1.1.0 "Eider"
+  This introduces a number of enhancements, mostly focused on real-time
+  encoding. In addition, it fixes a decoder bug (first introduced in
+  Duclair) so all users of that release are encouraged to upgrade.
+
+  - Upgrading:
+    This release is ABI and API compatible with Duclair (v1.0.0). Users
+    of older releases should refer to the Upgrading notes in this
+    document for that release.
+
+    This release introduces a new temporal denoiser, controlled by the
+    VP8E_SET_NOISE_SENSITIVITY control. The temporal denoiser does not
+    currently take a strength parameter, so the control is effectively
+    a boolean - zero (off) or non-zero (on). For compatibility with
+    existing applications, the values accepted are the same as those
+    for the spatial denoiser (0-6). The temporal denoiser is enabled
+    by default, and the older spatial denoiser may be restored by
+    configuring with --disable-temporal-denoising. The temporal denoiser
+    is more computationally intensive than the spatial one.
+
+    This release removes support for a legacy, decode only API that was
+    supported, but deprecated, at the initial release of libvpx
+    (v0.9.0). This is not expected to have any impact. If you are
+    impacted, you can apply a reversion to commit 2bf8fb58 locally.
+    Please update to the latest libvpx API if you are affected.
+
+  - Enhancements:
+      Adds a motion compensated temporal denoiser to the encoder, which
+      gives higher quality than the older spatial denoiser. (See above
+      for notes on upgrading).
+
+      In addition, support for new compilers and platforms were added,
+      including:
+        improved support for XCode
+        Android x86 NDK build
+        OS/2 support
+        SunCC support
+
+      Changing resolution with vpx_codec_enc_config_set() is now
+      supported. Previously, reinitializing the codec was required to
+      change the input resolution.
+
+      The vpxenc application has initial support for producing multiple
+      encodes from the same input in one call. Resizing is not yet
+      supported, but varying other codec parameters is. Use -- to
+      delineate output streams. Options persist from one stream to the
+      next.
+
+      Also, the vpxenc application will now use a keyframe interval of
+      5 seconds by default. Use the --kf-max-dist option to override.
+
+  - Speed:
+      Decoder performance improved 2.5% versus Duclair. Encoder speed is
+      consistent with Duclair for most material. Two pass encoding of
+      slideshow-like material will see significant improvements.
+
+      Large realtime encoding speed gains at a small quality expense are
+      possible by configuring the on-the-fly bitpacking experiment with
+      --enable-onthefly-bitpacking. Realtime encoder can be up to 13%
+      faster (ARM) depending on the number of threads and bitrate
+      settings. This technique sees constant gain over the 5-16 speed
+      range. For VC style input the loss seen is up to 0.2dB. See commit
+      52cf4dca for further details.
+
+  - Quality:
+      On the whole, quality is consistent with the Duclair release. Some
+      tweaks:
+
+        Reduced blockiness in easy sections by applying a penalty to
+        intra modes.
+
+        Improved quality of static sections (like slideshows) with
+        two pass encoding.
+
+        Improved keyframe sizing with multiple temporal layers
+
+  - Bug Fixes:
+      Corrected alt-ref contribution to frame rate for visible updates
+      to the alt-ref buffer. This affected applications making manual
+      usage of the frame reference flags, or temporal layers.
+
+      Additional constraints were added to disable multi-frame quality
+      enhancement (MFQE) in sections of the frame where there is motion.
+      (#392)
+
+      Fixed corruption issues when vpx_codec_enc_config_set() was called
+      with spatial resampling enabled.
+
+      Fixed a decoder error introduced in Duclair where the segmentation
+      map was not being reinitialized on keyframes (#378)
+
+
+2012-01-27 v1.0.0 "Duclair"
+  Our fourth named release, focused on performance and features related to
+  real-time encoding. It also fixes a decoder crash bug introduced in
+  v0.9.7, so all users of that release are encouraged to upgrade.
+
+  - Upgrading:
+      This release is ABI incompatible with prior releases of libvpx, so the
+      "major" version number has been bumped to 1. You must recompile your
+      applications against the latest version of the libvpx headers. The
+      API remains compatible, and this should not require code changes in most
+      applications.
+
+  - Enhancements:
+      This release introduces several substantial new features to the encoder,
+      of particular interest to real time streaming applications.
+
+      Temporal scalability allows the encoder to produce a stream that can
+      be decimated to different frame rates, with independent rate targetting
+      for each substream.
+
+      Multiframe quality enhancement postprocessing can make visual quality
+      more consistent in the presence of frames that are substantially
+      different quality than the surrounding frames, as in the temporal
+      scalability case and in some forced keyframe scenarios.
+
+      Multiple-resolution encoding support allows the encoding of the
+      same content at different resolutions faster than encoding them
+      separately.
+
+  - Speed:
+      Optimization targets for this release included the decoder and the real-
+      time modes of the encoder. Decoder speed on x86 has improved 10.5% with
+      this release. Encoder improvements followed a curve where speeds 1-3
+      improved 4.0%-1.5%, speeds 4-8 improved <1%, and speeds 9-16 improved
+      1.5% to 10.5%, respectively. "Best" mode speed is consistent with the
+      Cayuga release.
+
+  - Quality:
+      Encoder quality in the single stream case is consistent with the Cayuga
+      release.
+
+  - Bug Fixes:
+      This release fixes an OOB read decoder crash bug present in v0.9.7
+      related to the clamping of motion vectors in SPLITMV blocks. This
+      behavior could be triggered by corrupt input or by starting
+      decoding from a P-frame.
+
+
+2011-08-15 v0.9.7-p1 "Cayuga" patch 1
+  This is an incremental bugfix release against Cayuga. All users of that
+  release are strongly encouraged to upgrade.
+
+    - Fix potential OOB reads (cdae03a)
+
+          An unbounded out of bounds read was discovered when the
+          decoder was requested to perform error concealment (new in
+          Cayuga) given a frame with corrupt partition sizes.
+
+          A bounded out of bounds read was discovered affecting all
+          versions of libvpx. Given an multipartition input frame that
+          is truncated between the mode/mv partition and the first
+          residiual paritition (in the block of partition offsets), up
+          to 3 extra bytes could have been read from the source buffer.
+          The code will not take any action regardless of the contents
+          of these undefined bytes, as the truncated buffer is detected
+          immediately following the read based on the calculated
+          starting position of the coefficient partition.
+
+    - Fix potential error concealment crash when the very first frame
+      is missing or corrupt (a609be5)
+
+    - Fix significant artifacts in error concealment (a4c2211, 99d870a)
+
+    - Revert 1-pass CBR rate control changes (e961317)
+      Further testing showed this change produced undesirable visual
+      artifacts, rolling back for now.
+
+
+2011-08-02 v0.9.7 "Cayuga"
+  Our third named release, focused on a faster, higher quality, encoder.
+
+  - Upgrading:
+    This release is backwards compatible with Aylesbury (v0.9.5) and
+    Bali (v0.9.6). Users of older releases should refer to the Upgrading
+    notes in this document for that release.
+
+  - Enhancements:
+          Stereo 3D format support for vpxenc
+          Runtime detection of available processor cores.
+          Allow specifying --end-usage by enum name
+          vpxdec: test for frame corruption
+          vpxenc: add quantizer histogram display
+          vpxenc: add rate histogram display
+          Set VPX_FRAME_IS_DROPPABLE
+          update configure for ios sdk 4.3
+          Avoid text relocations in ARM vp8 decoder
+          Generate a vpx.pc file for pkg-config.
+          New ways of passing encoded data between encoder and decoder.
+
+  - Speed:
+      This release includes across-the-board speed improvements to the
+      encoder. On x86, these measure at approximately 11.5% in Best mode,
+      21.5% in Good mode (speed 0), and 22.5% in Realtime mode (speed 6).
+      On ARM Cortex A9 with Neon extensions, real-time encoding of video
+      telephony content is 35% faster than Bali on single core and 48%
+      faster on multi-core. On the NVidia Tegra2 platform, real time
+      encoding is 40% faster than Bali.
+
+      Decoder speed was not a priority for this release, but improved
+      approximately 8.4% on x86.
+
+          Reduce motion vector search on alt-ref frame.
+          Encoder loopfilter running in its own thread
+          Reworked loopfilter to precalculate more parameters
+          SSE2/SSSE3 optimizations for build_predictors_mbuv{,_s}().
+          Make hor UV predict ~2x faster (73 vs 132 cycles) using SSSE3.
+          Removed redundant checks
+          Reduced structure sizes
+          utilize preload in ARMv6 MC/LPF/Copy routines
+          ARM optimized quantization, dfct, variance, subtract
+          Increase chrow row alignment to 16 bytes.
+          disable trellis optimization for first pass
+          Write SSSE3 sub-pixel filter function
+          Improve SSE2 half-pixel filter funtions
+          Add vp8_sub_pixel_variance16x8_ssse3 function
+          Reduce unnecessary distortion computation
+          Use diamond search to replace full search
+          Preload reference area in sub-pixel motion search (real-time mode)
+
+  - Quality:
+      This release focused primarily on one-pass use cases, including
+      video conferencing. Low latency data rate control was significantly
+      improved, improving streamability over bandwidth constrained links.
+      Added support for error concealment, allowing frames to maintain
+      visual quality in the presence of substantial packet loss.
+
+          Add rc_max_intra_bitrate_pct control
+          Limit size of initial keyframe in one-pass.
+          Improve framerate adaptation
+          Improved 1-pass CBR rate control
+          Improved KF insertion after fades to still.
+          Improved key frame detection.
+          Improved activity masking (lower PSNR impact for same SSIM boost)
+          Improved interaction between GF and ARFs
+          Adding error-concealment to the decoder.
+          Adding support for independent partitions
+          Adjusted rate-distortion constants
+
+
+  - Bug Fixes:
+          Removed firstpass motion map
+          Fix parallel make install
+          Fix multithreaded encoding for 1 MB wide frame
+          Fixed iwalsh_neon build problems with RVDS4.1
+          Fix semaphore emulation, spin-wait intrinsics on Windows
+          Fix build with xcode4 and simplify GLOBAL.
+          Mark ARM asm objects as allowing a non-executable stack.
+          Fix vpxenc encoding incorrect webm file header on big endian
+
+
+2011-03-07 v0.9.6 "Bali"
+  Our second named release, focused on a faster, higher quality, encoder.
+
+  - Upgrading:
+    This release is backwards compatible with Aylesbury (v0.9.5). Users
+    of older releases should refer to the Upgrading notes in this
+    document for that release.
+
+  - Enhancements:
+      vpxenc --psnr shows a summary when encode completes
+      --tune=ssim option to enable activity masking
+      improved postproc visualizations for development
+      updated support for Apple iOS to SDK 4.2
+      query decoder to determine which reference frames were updated
+      implemented error tracking in the decoder
+      fix pipe support on windows
+
+  - Speed:
+      Primary focus was on good quality mode, speed 0. Average improvement
+      on x86 about 40%, up to 100% on user-generated content at that speed.
+      Best quality mode speed improved 35%, and realtime speed 10-20%. This
+      release also saw significant improvement in realtime encoding speed
+      on ARM platforms.
+
+        Improved encoder threading
+        Dont pick encoder filter level when loopfilter is disabled.
+        Avoid double copying of key frames into alt and golden buffer
+        FDCT optimizations.
+        x86 sse2 temporal filter
+        SSSE3 version of fast quantizer
+        vp8_rd_pick_best_mbsegmentation code restructure
+        Adjusted breakout RD for SPLITMV
+        Changed segmentation check order
+        Improved rd_pick_intra4x4block
+        Adds armv6 optimized variance calculation
+        ARMv6 optimized sad16x16
+        ARMv6 optimized half pixel variance calculations
+        Full search SAD function optimization in SSE4.1
+        Improve MV prediction accuracy to achieve performance gain
+        Improve MV prediction in vp8_pick_inter_mode() for speed>3
+
+  - Quality:
+      Best quality mode improved PSNR 6.3%, and SSIM 6.1%. This release
+      also includes support for "activity masking," which greatly improves
+      SSIM at the expense of PSNR. For now, this feature is available with
+      the --tune=ssim option. Further experimentation in this area
+      is ongoing. This release also introduces a new rate control mode
+      called "CQ," which changes the allocation of bits within a clip to
+      the sections where they will have the most visual impact.
+
+        Tuning for the more exact quantizer.
+        Relax rate control for last few frames
+        CQ Mode
+        Limit key frame quantizer for forced key frames.
+        KF/GF Pulsing
+        Add simple version of activity masking.
+        make rdmult adaptive for intra in quantizer RDO
+        cap the best quantizer for 2nd order DC
+        change the threshold of DC check for encode breakout
+
+  - Bug Fixes:
+      Fix crash on Sparc Solaris.
+      Fix counter of fixed keyframe distance
+      ARNR filter pointer update bug fix
+      Fixed use of motion percentage in KF/GF group calc
+      Changed condition for using RD in Intra Mode
+      Fix encoder real-time only configuration.
+      Fix ARM encoder crash with multiple token partitions
+      Fixed bug first cluster timecode of webm file is wrong.
+      Fixed various encoder bugs with odd-sized images
+      vp8e_get_preview fixed when spatial resampling enabled
+      quantizer: fix assertion in fast quantizer path
+      Allocate source buffers to be multiples of 16
+      Fix for manual Golden frame frequency
+      Fix drastic undershoot in long form content
+
+
+2010-10-28 v0.9.5 "Aylesbury"
+  Our first named release, focused on a faster decoder, and a better encoder.
+
+  - Upgrading:
+    This release incorporates backwards-incompatible changes to the
+    ivfenc and ivfdec tools. These tools are now called vpxenc and vpxdec.
+
+    vpxdec
+      * the -q (quiet) option has been removed, and replaced with
+        -v (verbose). the output is quiet by default. Use -v to see
+        the version number of the binary.
+
+      * The default behavior is now to write output to a single file
+        instead of individual frames. The -y option has been removed.
+        Y4M output is the default.
+
+      * For raw I420/YV12 output instead of Y4M, the --i420 or --yv12
+        options must be specified.
+
+          $ ivfdec -o OUTPUT INPUT
+          $ vpxdec --i420 -o OUTPUT INPUT
+
+      * If an output file is not specified, the default is to write
+        Y4M to stdout. This makes piping more natural.
+
+          $ ivfdec -y -o - INPUT | ...
+          $ vpxdec INPUT | ...
+
+      * The output file has additional flexibility for formatting the
+        filename. It supports escape characters for constructing a
+        filename from the width, height, and sequence number. This
+        replaces the -p option. To get the equivalent:
+
+          $ ivfdec -p frame INPUT
+          $ vpxdec --i420 -o frame-%wx%h-%4.i420 INPUT
+
+    vpxenc
+      * The output file must be specified with -o, rather than as the
+        last argument.
+
+          $ ivfenc <options> INPUT OUTPUT
+          $ vpxenc <options> -o OUTPUT INPUT
+
+      * The output defaults to webm. To get IVF output, use the --ivf
+        option.
+
+          $ ivfenc <options> INPUT OUTPUT.ivf
+          $ vpxenc <options> -o OUTPUT.ivf --ivf INPUT
+
+
+  - Enhancements:
+      ivfenc and ivfdec have been renamed to vpxenc, vpxdec.
+      vpxdec supports .webm input
+      vpxdec writes .y4m by default
+      vpxenc writes .webm output by default
+      vpxenc --psnr now shows the average/overall PSNR at the end
+      ARM platforms now support runtime cpu detection
+      vpxdec visualizations added for motion vectors, block modes, references
+      vpxdec now silent by default
+      vpxdec --progress shows frame-by-frame timing information
+      vpxenc supports the distinction between --fps and --timebase
+      NASM is now a supported assembler
+      configure: enable PIC for shared libs by default
+      configure: add --enable-small
+      configure: support for ppc32-linux-gcc
+      configure: support for sparc-solaris-gcc
+
+  - Bugs:
+      Improve handling of invalid frames
+      Fix valgrind errors in the NEON loop filters.
+      Fix loopfilter delta zero transitions
+      Fix valgrind errors in vp8_sixtap_predict8x4_armv6().
+      Build fixes for darwin-icc
+
+  - Speed:
+      20-40% (average 28%) improvement in libvpx decoder speed,
+      including:
+        Rewrite vp8_short_walsh4x4_sse2()
+        Optimizations on the loopfilters.
+        Miscellaneous improvements for Atom
+        Add 4-tap version of 2nd-pass ARMv6 MC filter.
+        Improved multithread utilization
+        Better instruction choices on x86
+        reorder data to use wider instructions
+        Update NEON wide idcts
+        Make block access to frame buffer sequential
+        Improved subset block search
+        Bilinear subpixel optimizations for ssse3.
+        Decrease memory footprint
+
+      Encoder speed improvements (percentage gain not measured):
+        Skip unnecessary search of identical frames
+        Add SSE2 subtract functions
+        Improve bounds checking in vp8_diamond_search_sadx4()
+        Added vp8_fast_quantize_b_sse2
+
+  - Quality:
+      Over 7% overall PSNR improvement (6.3% SSIM) in "best" quality
+      encoding mode, and up to 60% improvement on very noisy, still
+      or slow moving source video
+
+        Motion compensated temporal filter for Alt-Ref Noise Reduction
+        Improved use of trellis quantization on 2nd order Y blocks
+        Tune effect of motion on KF/GF boost in two pass
+        Allow coefficient optimization for good quality speed 0.
+        Improved control of active min quantizer for two pass.
+        Enable ARFs for non-lagged compress
+
+2010-09-02 v0.9.2
+  - Enhancements:
+      Disable frame dropping by default
+      Improved multithreaded performance
+      Improved Force Key Frame Behaviour
+      Increased rate control buffer level precision
+      Fix bug in 1st pass motion compensation
+      ivfenc: correct fixed kf interval, --disable-kf
+  - Speed:
+      Changed above and left context data layout
+      Rework idct calling structure.
+      Removed unnecessary MB_MODE_INFO copies
+      x86: SSSE3 sixtap prediction
+      Reworked IDCT to include reconstruction (add) step
+      Swap alt/gold/new/last frame buffer ptrs instead of copying.
+      Improve SSE2 loopfilter functions
+      Change bitreader to use a larger window.
+      Avoid loopfilter reinitialization when possible
+  - Quality:
+      Normalize quantizer's zero bin and rounding factors
+      Add trellis quantization.
+      Make the quantizer exact.
+      Updates to ARNR filtering algorithm
+      Fix breakout thresh computation for golden & AltRef frames
+      Redo the forward 4x4 dct
+      Improve the accuracy of forward walsh-hadamard transform
+      Further adjustment of RD behaviour with Q and Zbin.
+  - Build System:
+      Allow linking of libs built with MinGW to MSVC
+      Fix target auto-detection on mingw32
+      Allow --cpu= to work for x86.
+      configure: pass original arguments through to make dist
+      Fix builds without runtime CPU detection
+      msvs: fix install of codec sources
+      msvs: Change devenv.com command line for better msys support
+      msvs: Add vs9 targets.
+      Add x86_64-linux-icc target
+  - Bugs:
+      Potential crashes on older MinGW builds
+      Fix two-pass framrate for Y4M input.
+      Fixed simple loop filter, other crashes on ARM v6
+      arm: fix missing dependency with --enable-shared
+      configure: support directories containing .o
+      Replace pinsrw (SSE) with MMX instructions
+      apple: include proper mach primatives
+      Fixed rate control bug with long key frame interval.
+      Fix DSO link errors on x86-64 when not using a version script
+      Fixed buffer selection for UV in AltRef filtering
+
+
+2010-06-17 v0.9.1
+  - Enhancements:
+      * ivfenc/ivfdec now support YUV4MPEG2 input and pipe I/O
+      * Speed optimizations
+  - Bugfixes:
+      * Rate control
+      * Prevent out-of-bounds accesses on invalid data
+  - Build system updates:
+      * Detect toolchain to be used automatically for native builds
+      * Support building shared libraries
+      * Better autotools emulation (--prefix, --libdir, DESTDIR)
+  - Updated LICENSE
+      * http://webmproject.blogspot.com/2010/06/changes-to-webm-open-source-license.html
+
+
+2010-05-18 v0.9.0
+  - Initial open source release. Welcome to WebM and VP8!
+
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..1ce4434
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,31 @@
+Copyright (c) 2010, The WebM Project authors. 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, nor the WebM Project, 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
+HOLDER 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.
+
diff --git a/PATENTS b/PATENTS
new file mode 100644 (file)
index 0000000..4414d83
--- /dev/null
+++ b/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the WebM Project.
+
+Google hereby grants to you a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer, and otherwise run, modify and propagate the contents of this
+implementation of VP8, where such license applies only to those patent
+claims, both currently owned by Google and acquired in the future,
+licensable by Google that are necessarily infringed by this
+implementation of VP8. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of VP8 or any code incorporated within this
+implementation of VP8 constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of VP8
+shall terminate as of the date such litigation is filed.
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..0dfb0fe
--- /dev/null
+++ b/README
@@ -0,0 +1,98 @@
+vpx Multi-Format Codec SDK
+README - 19 May 2010
+
+Welcome to the WebM VP8 Codec SDK!
+
+COMPILING THE APPLICATIONS/LIBRARIES:
+  The build system used is similar to autotools. Building generally consists of
+  "configuring" with your desired build options, then using GNU make to build
+  the application.
+
+  1. Prerequisites
+
+    * All x86 targets require the Yasm[1] assembler be installed.
+    * All Windows builds require that Cygwin[2] be installed.
+    * Building the documentation requires PHP[3] and Doxygen[4]. If you do not
+      have these packages, you must pass --disable-install-docs to the
+      configure script.
+
+    [1]: http://www.tortall.net/projects/yasm
+    [2]: http://www.cygwin.com
+    [3]: http://php.net
+    [4]: http://www.doxygen.org
+
+  2. Out-of-tree builds
+  Out of tree builds are a supported method of building the application. For
+  an out of tree build, the source tree is kept separate from the object
+  files produced during compilation. For instance:
+
+    $ mkdir build
+    $ cd build
+    $ ../libvpx/configure <options>
+    $ make
+
+  3. Configuration options
+  The 'configure' script supports a number of options. The --help option can be
+  used to get a list of supported options:
+    $ ../libvpx/configure --help
+
+  4. Cross development
+  For cross development, the most notable option is the --target option. The
+  most up-to-date list of supported targets can be found at the bottom of the
+  --help output of the configure script. As of this writing, the list of
+  available targets is:
+
+    armv5te-android-gcc
+    armv5te-linux-rvct
+    armv5te-linux-gcc
+    armv6-darwin-gcc
+    armv6-linux-rvct
+    armv6-linux-gcc
+    armv7-android-gcc
+    armv7-linux-rvct
+    armv7-linux-gcc
+    mips32-linux-gcc
+    ppc32-darwin8-gcc
+    ppc32-darwin9-gcc
+    ppc64-darwin8-gcc
+    ppc64-darwin9-gcc
+    ppc64-linux-gcc
+    x86-darwin8-gcc
+    x86-darwin8-icc
+    x86-darwin9-gcc
+    x86-darwin9-icc
+    x86-linux-gcc
+    x86-linux-icc
+    x86-solaris-gcc
+    x86-win32-vs7
+    x86-win32-vs8
+    x86_64-darwin9-gcc
+    x86_64-linux-gcc
+    x86_64-solaris-gcc
+    x86_64-win64-vs8
+    universal-darwin8-gcc
+    universal-darwin9-gcc
+    generic-gnu
+
+  The generic-gnu target, in conjunction with the CROSS environment variable,
+  can be used to cross compile architectures that aren't explicitly listed, if
+  the toolchain is a cross GNU (gcc/binutils) toolchain. Other POSIX toolchains
+  will likely work as well. For instance, to build using the mipsel-linux-uclibc
+  toolchain, the following command could be used (note, POSIX SH syntax, adapt
+  to your shell as necessary):
+
+    $ CROSS=mipsel-linux-uclibc- ../libvpx/configure
+
+  In addition, the executables to be invoked can be overridden by specifying the
+  environment variables: CC, AR, LD, AS, STRIP, NM. Additional flags can be
+  passed to these executables with CFLAGS, LDFLAGS, and ASFLAGS.
+
+  5. Configuration errors
+  If the configuration step fails, the first step is to look in the error log.
+  This defaults to config.err. This should give a good indication of what went
+  wrong. If not, contact us for support.
+
+SUPPORT
+  This library is an open source project supported by its community. Please
+  please email webm-users@webmproject.org for help.
+
diff --git a/args.c b/args.c
new file mode 100644 (file)
index 0000000..37ba778
--- /dev/null
+++ b/args.c
@@ -0,0 +1,265 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include "args.h"
+
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#endif
+
+#if defined(__GNUC__) && __GNUC__
+extern void die(const char *fmt, ...) __attribute__((noreturn));
+#else
+extern void die(const char *fmt, ...);
+#endif
+
+
+struct arg arg_init(char **argv)
+{
+    struct arg a;
+
+    a.argv      = argv;
+    a.argv_step = 1;
+    a.name      = NULL;
+    a.val       = NULL;
+    a.def       = NULL;
+    return a;
+}
+
+int arg_match(struct arg *arg_, const struct arg_def *def, char **argv)
+{
+    struct arg arg;
+
+    if (!argv[0] || argv[0][0] != '-')
+        return 0;
+
+    arg = arg_init(argv);
+
+    if (def->short_name
+        && strlen(arg.argv[0]) == strlen(def->short_name) + 1
+        && !strcmp(arg.argv[0] + 1, def->short_name))
+    {
+
+        arg.name = arg.argv[0] + 1;
+        arg.val = def->has_val ? arg.argv[1] : NULL;
+        arg.argv_step = def->has_val ? 2 : 1;
+    }
+    else if (def->long_name)
+    {
+        const size_t name_len = strlen(def->long_name);
+
+        if (strlen(arg.argv[0]) >= name_len + 2
+            && arg.argv[0][1] == '-'
+            && !strncmp(arg.argv[0] + 2, def->long_name, name_len)
+            && (arg.argv[0][name_len+2] == '='
+                || arg.argv[0][name_len+2] == '\0'))
+        {
+
+            arg.name = arg.argv[0] + 2;
+            arg.val = arg.name[name_len] == '=' ? arg.name + name_len + 1 : NULL;
+            arg.argv_step = 1;
+        }
+    }
+
+    if (arg.name && !arg.val && def->has_val)
+        die("Error: option %s requires argument.\n", arg.name);
+
+    if (arg.name && arg.val && !def->has_val)
+        die("Error: option %s requires no argument.\n", arg.name);
+
+    if (arg.name
+        && (arg.val || !def->has_val))
+    {
+        arg.def = def;
+        *arg_ = arg;
+        return 1;
+    }
+
+    return 0;
+}
+
+
+const char *arg_next(struct arg *arg)
+{
+    if (arg->argv[0])
+        arg->argv += arg->argv_step;
+
+    return *arg->argv;
+}
+
+
+char **argv_dup(int argc, const char **argv)
+{
+    char **new_argv = malloc((argc + 1) * sizeof(*argv));
+
+    memcpy(new_argv, argv, argc * sizeof(*argv));
+    new_argv[argc] = NULL;
+    return new_argv;
+}
+
+
+void arg_show_usage(FILE *fp, const struct arg_def *const *defs)
+{
+    char option_text[40] = {0};
+
+    for (; *defs; defs++)
+    {
+        const struct arg_def *def = *defs;
+        char *short_val = def->has_val ? " <arg>" : "";
+        char *long_val = def->has_val ? "=<arg>" : "";
+
+        if (def->short_name && def->long_name)
+        {
+            char *comma = def->has_val ? "," : ",      ";
+
+            snprintf(option_text, 37, "-%s%s%s --%s%6s",
+                     def->short_name, short_val, comma,
+                     def->long_name, long_val);
+        }
+        else if (def->short_name)
+            snprintf(option_text, 37, "-%s%s",
+                     def->short_name, short_val);
+        else if (def->long_name)
+            snprintf(option_text, 37, "          --%s%s",
+                     def->long_name, long_val);
+
+        fprintf(fp, "  %-37s\t%s\n", option_text, def->desc);
+
+        if(def->enums)
+        {
+            const struct arg_enum_list *listptr;
+
+            fprintf(fp, "  %-37s\t  ", "");
+
+            for(listptr = def->enums; listptr->name; listptr++)
+                fprintf(fp, "%s%s", listptr->name,
+                        listptr[1].name ? ", " : "\n");
+        }
+    }
+}
+
+
+unsigned int arg_parse_uint(const struct arg *arg)
+{
+    long int   rawval;
+    char      *endptr;
+
+    rawval = strtol(arg->val, &endptr, 10);
+
+    if (arg->val[0] != '\0' && endptr[0] == '\0')
+    {
+        if (rawval >= 0 && rawval <= UINT_MAX)
+            return rawval;
+
+        die("Option %s: Value %ld out of range for unsigned int\n",
+            arg->name, rawval);
+    }
+
+    die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
+    return 0;
+}
+
+
+int arg_parse_int(const struct arg *arg)
+{
+    long int   rawval;
+    char      *endptr;
+
+    rawval = strtol(arg->val, &endptr, 10);
+
+    if (arg->val[0] != '\0' && endptr[0] == '\0')
+    {
+        if (rawval >= INT_MIN && rawval <= INT_MAX)
+            return rawval;
+
+        die("Option %s: Value %ld out of range for signed int\n",
+            arg->name, rawval);
+    }
+
+    die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
+    return 0;
+}
+
+
+struct vpx_rational
+{
+    int num; /**< fraction numerator */
+    int den; /**< fraction denominator */
+};
+struct vpx_rational arg_parse_rational(const struct arg *arg)
+{
+    long int             rawval;
+    char                *endptr;
+    struct vpx_rational  rat;
+
+    /* parse numerator */
+    rawval = strtol(arg->val, &endptr, 10);
+
+    if (arg->val[0] != '\0' && endptr[0] == '/')
+    {
+        if (rawval >= INT_MIN && rawval <= INT_MAX)
+            rat.num = rawval;
+        else die("Option %s: Value %ld out of range for signed int\n",
+                     arg->name, rawval);
+    }
+    else die("Option %s: Expected / at '%c'\n", arg->name, *endptr);
+
+    /* parse denominator */
+    rawval = strtol(endptr + 1, &endptr, 10);
+
+    if (arg->val[0] != '\0' && endptr[0] == '\0')
+    {
+        if (rawval >= INT_MIN && rawval <= INT_MAX)
+            rat.den = rawval;
+        else die("Option %s: Value %ld out of range for signed int\n",
+                     arg->name, rawval);
+    }
+    else die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
+
+    return rat;
+}
+
+
+int arg_parse_enum(const struct arg *arg)
+{
+    const struct arg_enum_list *listptr;
+    long int                    rawval;
+    char                       *endptr;
+
+    /* First see if the value can be parsed as a raw value */
+    rawval = strtol(arg->val, &endptr, 10);
+    if (arg->val[0] != '\0' && endptr[0] == '\0')
+    {
+        /* Got a raw value, make sure it's valid */
+        for(listptr = arg->def->enums; listptr->name; listptr++)
+            if(listptr->val == rawval)
+                return rawval;
+    }
+
+    /* Next see if it can be parsed as a string */
+    for(listptr = arg->def->enums; listptr->name; listptr++)
+        if(!strcmp(arg->val, listptr->name))
+            return listptr->val;
+
+    die("Option %s: Invalid value '%s'\n", arg->name, arg->val);
+    return 0;
+}
+
+
+int arg_parse_enum_or_int(const struct arg *arg)
+{
+    if(arg->def->enums)
+        return arg_parse_enum(arg);
+    return arg_parse_int(arg);
+}
diff --git a/args.h b/args.h
new file mode 100644 (file)
index 0000000..7963fa6
--- /dev/null
+++ b/args.h
@@ -0,0 +1,54 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef ARGS_H
+#define ARGS_H
+#include <stdio.h>
+
+struct arg
+{
+    char                 **argv;
+    const char            *name;
+    const char            *val;
+    unsigned int           argv_step;
+    const struct arg_def  *def;
+};
+
+struct arg_enum_list
+{
+    const char *name;
+    int         val;
+};
+#define ARG_ENUM_LIST_END {0}
+
+typedef struct arg_def
+{
+    const char *short_name;
+    const char *long_name;
+    int         has_val;
+    const char *desc;
+    const struct arg_enum_list *enums;
+} arg_def_t;
+#define ARG_DEF(s,l,v,d) {s,l,v,d, NULL}
+#define ARG_DEF_ENUM(s,l,v,d,e) {s,l,v,d,e}
+#define ARG_DEF_LIST_END {0}
+
+struct arg arg_init(char **argv);
+int arg_match(struct arg *arg_, const struct arg_def *def, char **argv);
+const char *arg_next(struct arg *arg);
+void arg_show_usage(FILE *fp, const struct arg_def *const *defs);
+char **argv_dup(int argc, const char **argv);
+
+unsigned int arg_parse_uint(const struct arg *arg);
+int arg_parse_int(const struct arg *arg);
+struct vpx_rational arg_parse_rational(const struct arg *arg);
+int arg_parse_enum_or_int(const struct arg *arg);
+#endif
diff --git a/build/.gitattributes b/build/.gitattributes
new file mode 100644 (file)
index 0000000..03db79b
--- /dev/null
@@ -0,0 +1,2 @@
+*-vs8/*.rules -crlf
+*-msvs/*.rules -crlf
diff --git a/build/.gitignore b/build/.gitignore
new file mode 100644 (file)
index 0000000..1350fcb
--- /dev/null
@@ -0,0 +1 @@
+x86*-win32-vs*
diff --git a/build/make/Android.mk b/build/make/Android.mk
new file mode 100644 (file)
index 0000000..6fcd4ae
--- /dev/null
@@ -0,0 +1,199 @@
+##
+##  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+#
+# This file is to be used for compiling libvpx for Android using the NDK.
+# In an Android project place a libvpx checkout in the jni directory.
+# Run the configure script from the jni directory.  Base libvpx
+# encoder/decoder configuration will look similar to:
+# ./libvpx/configure --target=armv7-android-gcc --disable-examples \
+#                    --sdk-path=/opt/android-ndk-r6b/
+#
+# When targeting Android, realtime-only is enabled by default.  This can
+# be overridden by adding the command line flag:
+#  --disable-realtime-only
+#
+# This will create .mk files that contain variables that contain the
+# source files to compile.
+#
+# Place an Android.mk file in the jni directory that references the
+# Android.mk file in the libvpx directory:
+# LOCAL_PATH := $(call my-dir)
+# include $(CLEAR_VARS)
+# include libvpx/build/make/Android.mk
+#
+# There are currently two TARGET_ARCH_ABI targets for ARM.
+# armeabi and armeabi-v7a.  armeabi-v7a is selected by creating an
+# Application.mk in the jni directory that contains:
+# APP_ABI := armeabi-v7a
+#
+# To change to building armeabi, run ./libvpx/configure again, but with
+# --target=arm5te-android-gcc and and modify the Application.mk file to
+# set APP_ABI := armeabi
+#
+# Running ndk-build will build libvpx and include it in your project.
+#
+
+CONFIG_DIR := $(LOCAL_PATH)
+LIBVPX_PATH := $(LOCAL_PATH)/libvpx
+ASM_CNV_PATH_LOCAL := $(TARGET_ARCH_ABI)/ads2gas
+ASM_CNV_PATH := $(LOCAL_PATH)/$(ASM_CNV_PATH_LOCAL)
+
+# Makefiles created by the libvpx configure process
+# This will need to be fixed to handle x86.
+ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
+  include $(CONFIG_DIR)/libs-armv7-android-gcc.mk
+else
+  include $(CONFIG_DIR)/libs-armv5te-android-gcc.mk
+endif
+
+# Rule that is normally in Makefile created by libvpx
+# configure.  Used to filter out source files based on configuration.
+enabled=$(filter-out $($(1)-no),$($(1)-yes))
+
+# Override the relative path that is defined by the libvpx
+# configure process
+SRC_PATH_BARE := $(LIBVPX_PATH)
+
+# Include the list of files to be built
+include $(LIBVPX_PATH)/libs.mk
+
+# Want arm, not thumb, optimized
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -O3
+
+# -----------------------------------------------------------------------------
+# Template  : asm_offsets_template
+# Arguments : 1: assembly offsets file to be created
+#             2: c file to base assembly offsets on
+# Returns   : None
+# Usage     : $(eval $(call asm_offsets_template,<asmfile>, <srcfile>
+# Rationale : Create offsets at compile time using for structures that are
+#             defined in c, but used in assembly functions.
+# -----------------------------------------------------------------------------
+define asm_offsets_template
+
+_SRC:=$(2)
+_OBJ:=$(ASM_CNV_PATH)/$$(notdir $(2)).S
+
+_FLAGS = $$($$(my)CFLAGS) \
+          $$(call get-src-file-target-cflags,$(2)) \
+          $$(call host-c-includes,$$(LOCAL_C_INCLUDES) $$(CONFIG_DIR)) \
+          $$(LOCAL_CFLAGS) \
+          $$(NDK_APP_CFLAGS) \
+          $$(call host-c-includes,$$($(my)C_INCLUDES)) \
+          -DINLINE_ASM \
+          -S \
+
+_TEXT = "Compile $$(call get-src-file-text,$(2))"
+_CC   = $$(TARGET_CC)
+
+$$(eval $$(call ev-build-file))
+
+$(1) : $$(_OBJ) $(2)
+       @mkdir -p $$(dir $$@)
+       @grep $(OFFSET_PATTERN) $$< | tr -d '\#' | $(CONFIG_DIR)/$(ASM_CONVERSION) > $$@
+endef
+
+# Use ads2gas script to convert from RVCT format to GAS format.  This passes
+#  puts the processed file under $(ASM_CNV_PATH).  Local clean rule
+#  to handle removing these
+ASM_CNV_OFFSETS_DEPEND = $(ASM_CNV_PATH)/asm_com_offsets.asm
+ifeq ($(CONFIG_VP8_DECODER), yes)
+  ASM_CNV_OFFSETS_DEPEND += $(ASM_CNV_PATH)/asm_dec_offsets.asm
+endif
+ifeq ($(CONFIG_VP8_ENCODER), yes)
+  ASM_CNV_OFFSETS_DEPEND += $(ASM_CNV_PATH)/asm_enc_offsets.asm
+endif
+
+.PRECIOUS: %.asm.s
+$(ASM_CNV_PATH)/libvpx/%.asm.s: $(LIBVPX_PATH)/%.asm $(ASM_CNV_OFFSETS_DEPEND)
+       @mkdir -p $(dir $@)
+       @$(CONFIG_DIR)/$(ASM_CONVERSION) <$< > $@
+
+# For building vpx_rtcd.h, which has a rule in libs.mk
+TGT_ISA:=$(word 1, $(subst -, ,$(TOOLCHAIN)))
+target := libs
+
+LOCAL_SRC_FILES += vpx_config.c
+
+# Remove duplicate entries
+CODEC_SRCS_UNIQUE = $(sort $(CODEC_SRCS))
+
+# Pull out C files.  vpx_config.c is in the immediate directory and
+# so it does not need libvpx/ prefixed like the rest of the source files.
+CODEC_SRCS_C = $(filter %.c, $(CODEC_SRCS_UNIQUE))
+LOCAL_CODEC_SRCS_C = $(filter-out vpx_config.c, $(CODEC_SRCS_C))
+
+LOCAL_SRC_FILES += $(foreach file, $(LOCAL_CODEC_SRCS_C), libvpx/$(file))
+
+# Pull out assembly files, splitting NEON from the rest.  This is
+# done to specify that the NEON assembly files use NEON assembler flags.
+CODEC_SRCS_ASM_ALL = $(filter %.asm.s, $(CODEC_SRCS_UNIQUE))
+CODEC_SRCS_ASM = $(foreach v, \
+                 $(CODEC_SRCS_ASM_ALL), \
+                 $(if $(findstring neon,$(v)),,$(v)))
+CODEC_SRCS_ASM_ADS2GAS = $(patsubst %.s, \
+                         $(ASM_CNV_PATH_LOCAL)/libvpx/%.s, \
+                         $(CODEC_SRCS_ASM))
+LOCAL_SRC_FILES += $(CODEC_SRCS_ASM_ADS2GAS)
+
+ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
+  CODEC_SRCS_ASM_NEON = $(foreach v, \
+                        $(CODEC_SRCS_ASM_ALL),\
+                        $(if $(findstring neon,$(v)),$(v),))
+  CODEC_SRCS_ASM_NEON_ADS2GAS = $(patsubst %.s, \
+                                $(ASM_CNV_PATH_LOCAL)/libvpx/%.s, \
+                                $(CODEC_SRCS_ASM_NEON))
+  LOCAL_SRC_FILES += $(patsubst %.s, \
+                     %.s.neon, \
+                     $(CODEC_SRCS_ASM_NEON_ADS2GAS))
+endif
+
+LOCAL_CFLAGS += \
+    -DHAVE_CONFIG_H=vpx_config.h \
+    -I$(LIBVPX_PATH) \
+    -I$(ASM_CNV_PATH)
+
+LOCAL_MODULE := libvpx
+
+LOCAL_LDLIBS := -llog
+
+LOCAL_STATIC_LIBRARIES := cpufeatures
+
+$(foreach file, $(LOCAL_SRC_FILES), $(LOCAL_PATH)/$(file)): vpx_rtcd.h
+
+.PHONY: clean
+clean:
+       @echo "Clean: ads2gas files [$(TARGET_ARCH_ABI)]"
+       @$(RM) $(CODEC_SRCS_ASM_ADS2GAS) $(CODEC_SRCS_ASM_NEON_ADS2GAS)
+       @$(RM) $(patsubst %.asm, %.*, $(ASM_CNV_OFFSETS_DEPEND))
+       @$(RM) -r $(ASM_CNV_PATH)
+       @$(RM) $(CLEAN-OBJS)
+
+include $(BUILD_SHARED_LIBRARY)
+
+$(eval $(call asm_offsets_template,\
+    $(ASM_CNV_PATH)/asm_com_offsets.asm, \
+    $(LIBVPX_PATH)/vp8/common/asm_com_offsets.c))
+
+ifeq ($(CONFIG_VP8_DECODER), yes)
+  $(eval $(call asm_offsets_template,\
+    $(ASM_CNV_PATH)/asm_dec_offsets.asm, \
+    $(LIBVPX_PATH)/vp8/decoder/asm_dec_offsets.c))
+endif
+
+ifeq ($(CONFIG_VP8_ENCODER), yes)
+  $(eval $(call asm_offsets_template,\
+    $(ASM_CNV_PATH)/asm_enc_offsets.asm, \
+    $(LIBVPX_PATH)/vp8/encoder/asm_enc_offsets.c))
+endif
+
+$(call import-module,cpufeatures)
diff --git a/build/make/Makefile b/build/make/Makefile
new file mode 100644 (file)
index 0000000..b6cf320
--- /dev/null
@@ -0,0 +1,384 @@
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+
+include config.mk
+quiet?=true
+ifeq ($(target),)
+# If a target wasn't specified, invoke for all enabled targets.
+.DEFAULT:
+       @for t in $(ALL_TARGETS); do \
+            $(MAKE) --no-print-directory target=$$t $(MAKECMDGOALS) || exit $$?;\
+        done
+all: .DEFAULT
+clean:: .DEFAULT
+install:: .DEFAULT
+test:: .DEFAULT
+
+
+# Note: md5sum is not installed on OS X, but openssl is. Openssl may not be
+# installed on cygwin, so we need to autodetect here.
+md5sum := $(firstword $(wildcard \
+          $(foreach e,md5sum openssl,\
+          $(foreach p,$(subst :, ,$(PATH)),$(p)/$(e)*))\
+          ))
+md5sum := $(if $(filter %openssl,$(md5sum)),$(md5sum) dgst -md5,$(md5sum))
+
+TGT_CC:=$(word 3, $(subst -, ,$(TOOLCHAIN)))
+dist:
+       @for t in $(ALL_TARGETS); do \
+            $(MAKE) --no-print-directory target=$$t $(MAKECMDGOALS) || exit $$?;\
+        done
+        # Run configure for the user with the current toolchain.
+       @if [ -d "$(DIST_DIR)/src" ]; then \
+            mkdir -p "$(DIST_DIR)/build"; \
+            cd "$(DIST_DIR)/build"; \
+            echo "Rerunning configure $(CONFIGURE_ARGS)"; \
+            ../src/configure $(CONFIGURE_ARGS); \
+            $(if $(filter vs%,$(TGT_CC)),make NO_LAUNCH_DEVENV=1;) \
+        fi
+       @if [ -d "$(DIST_DIR)" ]; then \
+            echo "    [MD5SUM] $(DIST_DIR)"; \
+           cd $(DIST_DIR) && \
+           $(md5sum) `find . -name md5sums.txt -prune -o -type f -print` \
+                | sed -e 's/MD5(\(.*\))= \([0-9a-f]\{32\}\)/\2  \1/' \
+                > md5sums.txt;\
+        fi
+
+
+endif
+
+ifneq ($(target),)
+# Normally, we want to build the filename from the target and the toolchain.
+# This disambiguates from the $(target).mk file that exists in the source tree.
+# However, the toolchain is part of the target in universal builds, so we
+# don't want to include TOOLCHAIN in that case. FAT_ARCHS is used to test
+# if we're in the universal case.
+include $(target)$(if $(FAT_ARCHS),,-$(TOOLCHAIN)).mk
+endif
+BUILD_ROOT?=.
+VPATH=$(SRC_PATH_BARE)
+CFLAGS+=-I$(BUILD_PFX)$(BUILD_ROOT) -I$(SRC_PATH)
+ASFLAGS+=-I$(BUILD_PFX)$(BUILD_ROOT)/ -I$(SRC_PATH)/
+DIST_DIR?=dist
+HOSTCC?=gcc
+TGT_ISA:=$(word 1, $(subst -, ,$(TOOLCHAIN)))
+TGT_OS:=$(word 2, $(subst -, ,$(TOOLCHAIN)))
+TGT_CC:=$(word 3, $(subst -, ,$(TOOLCHAIN)))
+quiet:=$(if $(verbose),,yes)
+qexec=$(if $(quiet),@)
+
+# Cancel built-in implicit rules
+%: %.o
+%.asm:
+%.a:
+%: %.cc
+
+#
+# Common rules"
+#
+.PHONY: all
+all:
+
+.PHONY: clean
+clean::
+       rm -f $(OBJS-yes) $(OBJS-yes:.o=.d) $(OBJS-yes:.asm.s.o=.asm.s)
+       rm -f $(CLEAN-OBJS)
+
+.PHONY: dist
+dist:
+.PHONY: install
+install::
+.PHONY: test
+test::
+
+$(BUILD_PFX)%.c.d: %.c
+       $(if $(quiet),@echo "    [DEP] $@")
+       $(qexec)mkdir -p $(dir $@)
+       $(qexec)$(CC) $(INTERNAL_CFLAGS) $(CFLAGS) -M $< | $(fmt_deps) > $@
+
+$(BUILD_PFX)%.c.o: %.c
+       $(if $(quiet),@echo "    [CC] $@")
+       $(qexec)$(CC) $(INTERNAL_CFLAGS) $(CFLAGS) -c -o $@ $<
+
+$(BUILD_PFX)%.cc.d: %.cc
+       $(if $(quiet),@echo "    [DEP] $@")
+       $(qexec)mkdir -p $(dir $@)
+       $(qexec)g++ $(INTERNAL_CFLAGS) $(CFLAGS) -M $< | $(fmt_deps) > $@
+
+$(BUILD_PFX)%.cc.o: %.cc
+       $(if $(quiet),@echo "    [CXX] $@")
+       $(qexec)g++ $(INTERNAL_CFLAGS) $(CFLAGS) -c -o $@ $<
+
+$(BUILD_PFX)%.asm.d: %.asm
+       $(if $(quiet),@echo "    [DEP] $@")
+       $(qexec)mkdir -p $(dir $@)
+       $(qexec)$(SRC_PATH_BARE)/build/make/gen_asm_deps.sh \
+            --build-pfx=$(BUILD_PFX) --depfile=$@ $(ASFLAGS) $< > $@
+
+$(BUILD_PFX)%.asm.o: %.asm
+       $(if $(quiet),@echo "    [AS] $@")
+       $(qexec)$(AS) $(ASFLAGS) -o $@ $<
+
+$(BUILD_PFX)%.s.d: %.s
+       $(if $(quiet),@echo "    [DEP] $@")
+       $(qexec)mkdir -p $(dir $@)
+       $(qexec)$(SRC_PATH_BARE)/build/make/gen_asm_deps.sh \
+            --build-pfx=$(BUILD_PFX) --depfile=$@ $(ASFLAGS) $< > $@
+
+$(BUILD_PFX)%.s.o: %.s
+       $(if $(quiet),@echo "    [AS] $@")
+       $(qexec)$(AS) $(ASFLAGS) -o $@ $<
+
+.PRECIOUS: %.c.S
+%.c.S: CFLAGS += -DINLINE_ASM
+$(BUILD_PFX)%.c.S: %.c
+       $(if $(quiet),@echo "    [GEN] $@")
+       $(qexec)$(CC) -S $(CFLAGS) -o $@ $<
+
+.PRECIOUS: %.asm.s
+$(BUILD_PFX)%.asm.s: %.asm
+       $(if $(quiet),@echo "    [ASM CONVERSION] $@")
+       $(qexec)mkdir -p $(dir $@)
+       $(qexec)$(ASM_CONVERSION) <$< >$@
+
+# If we're in debug mode, pretend we don't have GNU strip, to fall back to
+# the copy implementation
+HAVE_GNU_STRIP := $(if $(CONFIG_DEBUG),,$(HAVE_GNU_STRIP))
+ifeq ($(HAVE_GNU_STRIP),yes)
+# Older binutils strip global sybols not needed for relocation processing
+# when given --strip-unneeded. Use nm and awk to identify globals and
+# keep them.
+%.a: %_g.a
+       $(if $(quiet),@echo "    [STRIP] $@ < $<")
+       $(qexec)$(STRIP) --strip-unneeded \
+         `$(NM) $< | grep ' [A-TV-Z] ' | awk '{print "-K"$$3'}`\
+          -o $@ $<
+else
+%.a: %_g.a
+       $(if $(quiet),@echo "    [CP] $@ < $<")
+       $(qexec)cp $< $@
+endif
+
+#
+# Rule to extract assembly constants from C sources
+#
+obj_int_extract: build/make/obj_int_extract.c
+       $(if $(quiet),@echo "    [HOSTCC] $@")
+       $(qexec)$(HOSTCC) -I. -I$(SRC_PATH_BARE) -o $@ $<
+CLEAN-OBJS += obj_int_extract
+
+#
+# Utility functions
+#
+pairmap=$(if $(strip $(2)),\
+    $(call $(1),$(word 1,$(2)),$(word 2,$(2)))\
+    $(call pairmap,$(1),$(wordlist 3,$(words $(2)),$(2)))\
+)
+
+enabled=$(filter-out $($(1)-no),$($(1)-yes))
+cond_enabled=$(if $(filter yes,$($(1))), $(call enabled,$(2)))
+
+find_file1=$(word 1,$(wildcard $(subst //,/,$(addsuffix /$(1),$(2)))))
+find_file=$(foreach f,$(1),$(call find_file1,$(strip $(f)),$(strip $(2))) )
+obj_pats=.c=.c.o $(AS_SFX)=$(AS_SFX).o .cc=.cc.o
+objs=$(addprefix $(BUILD_PFX),$(foreach p,$(obj_pats),$(filter %.o,$(1:$(p))) ))
+
+install_map_templates=$(eval $(call install_map_template,$(1),$(2)))
+
+not=$(subst yes,no,$(1))
+
+ifeq ($(CONFIG_MSVS),yes)
+lib_file_name=$(1).lib
+else
+lib_file_name=lib$(1).a
+endif
+#
+# Rule Templates
+#
+define linker_template
+$(1): $(filter-out -%,$(2))
+$(1):
+       $(if $(quiet),@echo    "    [LD] $$@")
+       $(qexec)$$(LD) $$(strip $$(INTERNAL_LDFLAGS) $$(LDFLAGS) -o $$@ $(2) $(3) $$(extralibs))
+endef
+define linkerxx_template
+$(1): $(filter-out -%,$(2))
+$(1):
+       $(if $(quiet),@echo    "    [LD] $$@")
+       $(qexec)g++ $$(strip $$(INTERNAL_LDFLAGS) $$(LDFLAGS) -o $$@ $(2) $(3) $$(extralibs))
+endef
+# make-3.80 has a bug with expanding large input strings to the eval function,
+# which was triggered in some cases by the following component of
+# linker_template:
+#   $(1): $$(call find_file, $(patsubst -l%,lib%.a,$(filter -l%,$(2))),\
+#                           $$(patsubst -L%,%,$$(filter -L%,$$(LDFLAGS) $(2))))
+# This may be useful to revisit in the future (it tries to locate libraries
+# in a search path and add them as prerequisites
+
+define install_map_template
+$(DIST_DIR)/$(1): $(2)
+       $(if $(quiet),@echo "    [INSTALL] $$@")
+       $(qexec)mkdir -p $$(dir $$@)
+       $(qexec)cp -p $$< $$@
+endef
+
+define archive_template
+# Not using a pattern rule here because we don't want to generate empty
+# archives when they are listed as a dependency in files not responsible
+# for creating them.
+$(1):
+       $(if $(quiet),@echo "    [AR] $$@")
+       $(qexec)$$(AR) $$(ARFLAGS) $$@ $$?
+endef
+
+define so_template
+# Not using a pattern rule here because we don't want to generate empty
+# archives when they are listed as a dependency in files not responsible
+# for creating them.
+#
+# This needs further abstraction for dealing with non-GNU linkers.
+$(1):
+       $(if $(quiet),@echo "    [LD] $$@")
+       $(qexec)$$(LD) -shared $$(LDFLAGS) \
+            -Wl,--no-undefined -Wl,-soname,$$(SONAME) \
+            -Wl,--version-script,$$(SO_VERSION_SCRIPT) -o $$@ \
+            $$(filter %.o,$$?) $$(extralibs)
+endef
+
+define lipo_lib_template
+$(1): $(addsuffix /$(1),$(FAT_ARCHS))
+       $(if $(quiet),@echo "    [LIPO] $$@")
+       $(qexec)libtool -static -o $$@ $$?
+endef
+
+define lipo_bin_template
+$(1): $(addsuffix /$(1),$(FAT_ARCHS))
+       $(if $(quiet),@echo "    [LIPO] $$@")
+       $(qexec)lipo -output $$@ -create $$?
+endef
+
+
+#
+# Get current configuration
+#
+ifneq ($(target),)
+include $(SRC_PATH_BARE)/$(target:-$(TOOLCHAIN)=).mk
+endif
+ifeq ($(filter clean,$(MAKECMDGOALS)),)
+  # Older versions of make don't like -include directives with no arguments
+  ifneq ($(filter %.d,$(OBJS-yes:.o=.d)),)
+    -include $(filter %.d,$(OBJS-yes:.o=.d))
+  endif
+endif
+
+#
+# Configuration dependent rules
+#
+$(call pairmap,install_map_templates,$(INSTALL_MAPS))
+
+DOCS=$(call cond_enabled,CONFIG_INSTALL_DOCS,DOCS)
+.docs: $(DOCS)
+       @touch $@
+
+INSTALL-DOCS=$(call cond_enabled,CONFIG_INSTALL_DOCS,INSTALL-DOCS)
+ifeq ($(MAKECMDGOALS),dist)
+INSTALL-DOCS+=$(call cond_enabled,CONFIG_INSTALL_DOCS,DIST-DOCS)
+endif
+.install-docs: .docs $(addprefix $(DIST_DIR)/,$(INSTALL-DOCS))
+       @touch $@
+
+clean::
+       rm -f .docs .install-docs $(DOCS)
+
+BINS=$(call enabled,BINS)
+.bins: $(BINS)
+       @touch $@
+
+INSTALL-BINS=$(call cond_enabled,CONFIG_INSTALL_BINS,INSTALL-BINS)
+ifeq ($(MAKECMDGOALS),dist)
+INSTALL-BINS+=$(call cond_enabled,CONFIG_INSTALL_BINS,DIST-BINS)
+endif
+.install-bins: .bins $(addprefix $(DIST_DIR)/,$(INSTALL-BINS))
+       @touch $@
+
+clean::
+       rm -f .bins .install-bins $(BINS)
+
+LIBS=$(call enabled,LIBS)
+.libs: $(LIBS)
+       @touch $@
+$(foreach lib,$(filter %_g.a,$(LIBS)),$(eval $(call archive_template,$(lib))))
+$(foreach lib,$(filter %so.$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH),$(LIBS)),$(eval $(call so_template,$(lib))))
+
+INSTALL-LIBS=$(call cond_enabled,CONFIG_INSTALL_LIBS,INSTALL-LIBS)
+ifeq ($(MAKECMDGOALS),dist)
+INSTALL-LIBS+=$(call cond_enabled,CONFIG_INSTALL_LIBS,DIST-LIBS)
+endif
+.install-libs: .libs $(addprefix $(DIST_DIR)/,$(INSTALL-LIBS))
+       @touch $@
+
+clean::
+       rm -f .libs .install-libs $(LIBS)
+
+ifeq ($(CONFIG_EXTERNAL_BUILD),yes)
+PROJECTS=$(call enabled,PROJECTS)
+.projects: $(PROJECTS)
+       @touch $@
+
+INSTALL-PROJECTS=$(call cond_enabled,CONFIG_INSTALL_PROJECTS,INSTALL-PROJECTS)
+ifeq ($(MAKECMDGOALS),dist)
+INSTALL-PROJECTS+=$(call cond_enabled,CONFIG_INSTALL_PROJECTS,DIST-PROJECTS)
+endif
+.install-projects: .projects $(addprefix $(DIST_DIR)/,$(INSTALL-PROJECTS))
+       @touch $@
+
+clean::
+       rm -f .projects .install-projects $(PROJECTS)
+endif
+
+# If there are any source files to be distributed, then include the build
+# system too.
+ifneq ($(call enabled,DIST-SRCS),)
+    DIST-SRCS-yes            += configure
+    DIST-SRCS-yes            += build/make/configure.sh
+    DIST-SRCS-yes            += build/make/gen_asm_deps.sh
+    DIST-SRCS-yes            += build/make/Makefile
+    DIST-SRCS-$(CONFIG_MSVS)  += build/make/gen_msvs_def.sh
+    DIST-SRCS-$(CONFIG_MSVS)  += build/make/gen_msvs_proj.sh
+    DIST-SRCS-$(CONFIG_MSVS)  += build/make/gen_msvs_sln.sh
+    DIST-SRCS-$(CONFIG_MSVS)  += build/x86-msvs/yasm.rules
+    DIST-SRCS-$(CONFIG_MSVS)  += build/x86-msvs/obj_int_extract.bat
+    DIST-SRCS-$(CONFIG_RVCT) += build/make/armlink_adapter.sh
+    # Include obj_int_extract if we use offsets from asm_*_offsets
+    DIST-SRCS-$(ARCH_ARM)$(ARCH_X86)$(ARCH_X86_64)    += build/make/obj_int_extract.c
+    DIST-SRCS-$(ARCH_ARM)    += build/make/ads2gas.pl
+    DIST-SRCS-yes            += $(target:-$(TOOLCHAIN)=).mk
+endif
+INSTALL-SRCS := $(call cond_enabled,CONFIG_INSTALL_SRCS,INSTALL-SRCS)
+ifeq ($(MAKECMDGOALS),dist)
+INSTALL-SRCS += $(call cond_enabled,CONFIG_INSTALL_SRCS,DIST-SRCS)
+endif
+.install-srcs: $(addprefix $(DIST_DIR)/src/,$(INSTALL-SRCS))
+       @touch $@
+
+clean::
+       rm -f .install-srcs
+
+ifeq ($(CONFIG_EXTERNAL_BUILD),yes)
+    BUILD_TARGETS += .projects
+    INSTALL_TARGETS += .install-projects
+endif
+BUILD_TARGETS += .docs .libs .bins
+INSTALL_TARGETS += .install-docs .install-srcs .install-libs .install-bins
+all: $(BUILD_TARGETS)
+install:: $(INSTALL_TARGETS)
+dist: $(INSTALL_TARGETS)
+test::
diff --git a/build/make/ads2gas.pl b/build/make/ads2gas.pl
new file mode 100755 (executable)
index 0000000..c55ed0f
--- /dev/null
@@ -0,0 +1,178 @@
+#!/usr/bin/perl
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+
+# ads2gas.pl
+# Author: Eric Fung (efung (at) acm.org)
+#
+# Convert ARM Developer Suite 1.0.1 syntax assembly source to GNU as format
+#
+# Usage: cat inputfile | perl ads2gas.pl > outputfile
+#
+print "@ This file was created from a .asm file\n";
+print "@  using the ads2gas.pl script.\n";
+print "\t.equ DO1STROUNDING, 0\n";
+
+# Stack of procedure names.
+@proc_stack = ();
+
+while (<STDIN>)
+{
+    # Load and store alignment
+    s/@/,:/g;
+
+    # Comment character
+    s/;/@/g;
+
+    # Hexadecimal constants prefaced by 0x
+    s/#&/#0x/g;
+
+    # Convert :OR: to |
+    s/:OR:/ | /g;
+
+    # Convert :AND: to &
+    s/:AND:/ & /g;
+
+    # Convert :NOT: to ~
+    s/:NOT:/ ~ /g;
+
+    # Convert :SHL: to <<
+    s/:SHL:/ << /g;
+
+    # Convert :SHR: to >>
+    s/:SHR:/ >> /g;
+
+    # Convert ELSE to .else
+    s/ELSE/.else/g;
+
+    # Convert ENDIF to .endif
+    s/ENDIF/.endif/g;
+
+    # Convert ELSEIF to .elseif
+    s/ELSEIF/.elseif/g;
+
+    # Convert LTORG to .ltorg
+    s/LTORG/.ltorg/g;
+
+    # Convert IF :DEF:to .if
+    # gcc doesn't have the ability to do a conditional
+    # if defined variable that is set by IF :DEF: on
+    # armasm, so convert it to a normal .if and then
+    # make sure to define a value elesewhere
+    if (s/\bIF :DEF:\b/.if /g)
+    {
+        s/=/==/g;
+    }
+
+    # Convert IF to .if
+    if (s/\bIF\b/.if/g)
+    {
+        s/=+/==/g;
+    }
+
+    # Convert INCLUDE to .INCLUDE "file"
+    s/INCLUDE(\s*)(.*)$/.include $1\"$2\"/;
+
+    # Code directive (ARM vs Thumb)
+    s/CODE([0-9][0-9])/.code $1/;
+
+    # No AREA required
+    # But ALIGNs in AREA must be obeyed
+    s/^\s*AREA.*ALIGN=([0-9])$/.text\n.p2align $1/;
+    # If no ALIGN, strip the AREA and align to 4 bytes
+    s/^\s*AREA.*$/.text\n.p2align 2/;
+
+    # DCD to .word
+    # This one is for incoming symbols
+    s/DCD\s+\|(\w*)\|/.long $1/;
+
+    # DCW to .short
+    s/DCW\s+\|(\w*)\|/.short $1/;
+    s/DCW(.*)/.short $1/;
+
+    # Constants defined in scope
+    s/DCD(.*)/.long $1/;
+    s/DCB(.*)/.byte $1/;
+
+    # RN to .req
+    if (s/RN\s+([Rr]\d+|lr)/.req $1/)
+    {
+        print;
+        next;
+    }
+
+    # Make function visible to linker, and make additional symbol with
+    # prepended underscore
+    s/EXPORT\s+\|([\$\w]*)\|/.global $1 \n\t.type $1, function/;
+    s/IMPORT\s+\|([\$\w]*)\|/.global $1/;
+
+    # No vertical bars required; make additional symbol with prepended
+    # underscore
+    s/^\|(\$?\w+)\|/_$1\n\t$1:/g;
+
+    # Labels need trailing colon
+#   s/^(\w+)/$1:/ if !/EQU/;
+    # put the colon at the end of the line in the macro
+    s/^([a-zA-Z_0-9\$]+)/$1:/ if !/EQU/;
+
+    # ALIGN directive
+    s/ALIGN/.balign/g;
+
+    # ARM code
+    s/\sARM/.arm/g;
+
+    # eabi_attributes numerical equivalents can be found in the
+    # "ARM IHI 0045C" document.
+
+    # REQUIRE8 Stack is required to be 8-byte aligned
+    s/\sREQUIRE8/.eabi_attribute 24, 1 \@Tag_ABI_align_needed/g;
+
+    # PRESERVE8 Stack 8-byte align is preserved
+    s/\sPRESERVE8/.eabi_attribute 25, 1 \@Tag_ABI_align_preserved/g;
+
+    # Use PROC and ENDP to give the symbols a .size directive.
+    # This makes them show up properly in debugging tools like gdb and valgrind.
+    if (/\bPROC\b/)
+    {
+        my $proc;
+        /^_([\.0-9A-Z_a-z]\w+)\b/;
+        $proc = $1;
+        push(@proc_stack, $proc) if ($proc);
+        s/\bPROC\b/@ $&/;
+    }
+    if (/\bENDP\b/)
+    {
+        my $proc;
+        s/\bENDP\b/@ $&/;
+        $proc = pop(@proc_stack);
+        $_ = "\t.size $proc, .-$proc".$_ if ($proc);
+    }
+
+    # EQU directive
+    s/(.*)EQU(.*)/.equ $1, $2/;
+
+    # Begin macro definition
+    if (/MACRO/) {
+        $_ = <STDIN>;
+        s/^/.macro/;
+        s/\$//g;                # remove formal param reference
+        s/;/@/g;                # change comment characters
+    }
+
+    # For macros, use \ to reference formal params
+    s/\$/\\/g;                  # End macro definition
+    s/MEND/.endm/;              # No need to tell it where to stop assembling
+    next if /^\s*END\s*$/;
+    print;
+}
+
+# Mark that this object doesn't need an executable stack.
+printf ("\t.section\t.note.GNU-stack,\"\",\%\%progbits\n");
diff --git a/build/make/ads2gas_apple.pl b/build/make/ads2gas_apple.pl
new file mode 100755 (executable)
index 0000000..81280bf
--- /dev/null
@@ -0,0 +1,214 @@
+#!/usr/bin/env perl
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+
+# ads2gas.pl
+# Author: Eric Fung (efung (at) acm.org)
+#
+# Convert ARM Developer Suite 1.0.1 syntax assembly source to GNU as format
+#
+# Usage: cat inputfile | perl ads2gas.pl > outputfile
+#
+print "@ This file was created from a .asm file\n";
+print "@  using the ads2gas_apple.pl script.\n\n";
+print "\t.set WIDE_REFERENCE, 0\n";
+print "\t.set ARCHITECTURE, 5\n";
+print "\t.set DO1STROUNDING, 0\n";
+
+my %register_aliases;
+my %macro_aliases;
+
+my @mapping_list = ("\$0", "\$1", "\$2", "\$3", "\$4", "\$5", "\$6", "\$7", "\$8", "\$9");
+
+my @incoming_array;
+
+my @imported_functions;
+
+# Perl trim function to remove whitespace from the start and end of the string
+sub trim($)
+{
+    my $string = shift;
+    $string =~ s/^\s+//;
+    $string =~ s/\s+$//;
+    return $string;
+}
+
+while (<STDIN>)
+{
+    # Load and store alignment
+    s/@/,:/g;
+
+    # Comment character
+    s/;/@/g;
+
+    # Hexadecimal constants prefaced by 0x
+    s/#&/#0x/g;
+
+    # Convert :OR: to |
+    s/:OR:/ | /g;
+
+    # Convert :AND: to &
+    s/:AND:/ & /g;
+
+    # Convert :NOT: to ~
+    s/:NOT:/ ~ /g;
+
+    # Convert :SHL: to <<
+    s/:SHL:/ << /g;
+
+    # Convert :SHR: to >>
+    s/:SHR:/ >> /g;
+
+    # Convert ELSE to .else
+    s/ELSE/.else/g;
+
+    # Convert ENDIF to .endif
+    s/ENDIF/.endif/g;
+
+    # Convert ELSEIF to .elseif
+    s/ELSEIF/.elseif/g;
+
+    # Convert LTORG to .ltorg
+    s/LTORG/.ltorg/g;
+
+    # Convert IF :DEF:to .if
+    # gcc doesn't have the ability to do a conditional
+    # if defined variable that is set by IF :DEF: on
+    # armasm, so convert it to a normal .if and then
+    # make sure to define a value elesewhere
+    if (s/\bIF :DEF:\b/.if /g)
+    {
+        s/=/==/g;
+    }
+
+    # Convert IF to .if
+    if (s/\bIF\b/.if/g)
+    {
+        s/=/==/g;
+    }
+
+    # Convert INCLUDE to .INCLUDE "file"
+    s/INCLUDE(\s*)(.*)$/.include $1\"$2\"/;
+
+    # Code directive (ARM vs Thumb)
+    s/CODE([0-9][0-9])/.code $1/;
+
+    # No AREA required
+    # But ALIGNs in AREA must be obeyed
+    s/^\s*AREA.*ALIGN=([0-9])$/.text\n.p2align $1/;
+    # If no ALIGN, strip the AREA and align to 4 bytes
+    s/^\s*AREA.*$/.text\n.p2align 2/;
+
+    # DCD to .word
+    # This one is for incoming symbols
+    s/DCD\s+\|(\w*)\|/.long $1/;
+
+    # DCW to .short
+    s/DCW\s+\|(\w*)\|/.short $1/;
+    s/DCW(.*)/.short $1/;
+
+    # Constants defined in scope
+    s/DCD(.*)/.long $1/;
+    s/DCB(.*)/.byte $1/;
+
+    # Build a hash of all the register - alias pairs.
+    if (s/(.*)RN(.*)/$1 .req $2/g)
+    {
+        $register_aliases{trim($1)} = trim($2);
+        next;
+    }
+
+    while (($key, $value) = each(%register_aliases))
+    {
+        s/\b$key\b/$value/g;
+    }
+
+    # Make function visible to linker, and make additional symbol with
+    # prepended underscore
+    s/EXPORT\s+\|([\$\w]*)\|/.globl _$1\n\t.globl $1/;
+
+    # Prepend imported functions with _
+    if (s/IMPORT\s+\|([\$\w]*)\|/.globl $1/)
+    {
+        $function = trim($1);
+        push(@imported_functions, $function);
+    }
+
+    foreach $function (@imported_functions)
+    {
+        s/$function/_$function/;
+    }
+
+    # No vertical bars required; make additional symbol with prepended
+    # underscore
+    s/^\|(\$?\w+)\|/_$1\n\t$1:/g;
+
+    # Labels need trailing colon
+#   s/^(\w+)/$1:/ if !/EQU/;
+    # put the colon at the end of the line in the macro
+    s/^([a-zA-Z_0-9\$]+)/$1:/ if !/EQU/;
+
+    # ALIGN directive
+    s/ALIGN/.balign/g;
+
+    # Strip ARM
+    s/\sARM/@ ARM/g;
+
+    # Strip REQUIRE8
+    #s/\sREQUIRE8/@ REQUIRE8/g;
+    s/\sREQUIRE8/@ /g;
+
+    # Strip PRESERVE8
+    s/\sPRESERVE8/@ PRESERVE8/g;
+
+    # Strip PROC and ENDPROC
+    s/\bPROC\b/@/g;
+    s/\bENDP\b/@/g;
+
+    # EQU directive
+    s/(.*)EQU(.*)/.set $1, $2/;
+
+    # Begin macro definition
+    if (/MACRO/)
+    {
+        # Process next line down, which will be the macro definition
+        $_ = <STDIN>;
+
+        $trimmed = trim($_);
+
+        # remove commas that are separating list
+        $trimmed =~ s/,//g;
+
+        # string to array
+        @incoming_array = split(/ /, $trimmed);
+
+        print ".macro @incoming_array[0]\n";
+
+        # remove the first element, as that is the name of the macro
+        shift (@incoming_array);
+
+        @macro_aliases{@incoming_array} = @mapping_list;
+
+        next;
+    }
+
+    while (($key, $value) = each(%macro_aliases))
+    {
+        $key =~ s/\$/\\\$/;
+        s/$key\b/$value/g;
+    }
+
+    # For macros, use \ to reference formal params
+#   s/\$/\\/g;                  # End macro definition
+    s/MEND/.endm/;              # No need to tell it where to stop assembling
+    next if /^\s*END\s*$/;
+    print;
+}
diff --git a/build/make/armlink_adapter.sh b/build/make/armlink_adapter.sh
new file mode 100755 (executable)
index 0000000..b53669c
--- /dev/null
@@ -0,0 +1,54 @@
+#!/bin/bash
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+
+verbose=0
+set -- $*
+for i; do
+    if [ "$i" == "-o" ]; then
+        on_of=1
+    elif [ "$i" == "-v" ]; then
+        verbose=1
+    elif [ "$i" == "-g" ]; then
+        args="${args} --debug"
+    elif [ "$on_of" == "1" ]; then
+        outfile=$i
+        on_of=0
+    elif [ -f "$i" ]; then
+        infiles="$infiles $i"
+    elif [ "${i:0:2}" == "-l" ]; then
+        libs="$libs ${i#-l}"
+    elif [ "${i:0:2}" == "-L" ]; then
+        libpaths="${libpaths} ${i#-L}"
+    else
+        args="${args} ${i}"
+    fi
+    shift
+done
+
+# Absolutize library file names
+for f in $libs; do
+    found=0
+    for d in $libpaths; do
+        [ -f "$d/$f" ] && infiles="$infiles $d/$f" && found=1 && break
+        [ -f "$d/lib${f}.so" ] && infiles="$infiles $d/lib${f}.so" && found=1 && break
+        [ -f "$d/lib${f}.a" ] && infiles="$infiles $d/lib${f}.a" && found=1 && break
+    done
+    [ $found -eq 0 ] && infiles="$infiles $f"
+done
+for d in $libpaths; do
+    [ -n "$libsearchpath" ] && libsearchpath="${libsearchpath},"
+    libsearchpath="${libsearchpath}$d"
+done
+
+cmd="armlink $args --userlibpath=$libsearchpath --output=$outfile $infiles"
+[ $verbose -eq 1 ] && echo $cmd
+$cmd
diff --git a/build/make/configure.sh b/build/make/configure.sh
new file mode 100755 (executable)
index 0000000..3c772e5
--- /dev/null
@@ -0,0 +1,1187 @@
+#!/bin/bash
+##
+##  configure.sh
+##
+##  This script is sourced by the main configure script and contains
+##  utility functions and other common bits that aren't strictly libvpx
+##  related.
+##
+##  This build system is based in part on the FFmpeg configure script.
+##
+
+
+#
+# Logging / Output Functions
+#
+die_unknown(){
+    echo "Unknown option \"$1\"."
+    echo "See $0 --help for available options."
+    clean_temp_files
+    exit 1
+}
+
+
+die() {
+    echo "$@"
+    echo
+    echo "Configuration failed. This could reflect a misconfiguration of your"
+    echo "toolchains, improper options selected, or another problem. If you"
+    echo "don't see any useful error messages above, the next step is to look"
+    echo "at the configure error log file ($logfile) to determine what"
+    echo "configure was trying to do when it died."
+    clean_temp_files
+    exit 1
+}
+
+
+log(){
+    echo "$@" >>$logfile
+}
+
+
+log_file(){
+    log BEGIN $1
+    pr -n -t $1 >>$logfile
+    log END $1
+}
+
+
+log_echo() {
+    echo "$@"
+    log "$@"
+}
+
+
+fwrite () {
+    outfile=$1
+    shift
+    echo "$@" >> ${outfile}
+}
+
+
+show_help_pre(){
+    for opt in ${CMDLINE_SELECT}; do
+        opt2=`echo $opt | sed -e 's;_;-;g'`
+        if enabled $opt; then
+            eval "toggle_${opt}=\"--disable-${opt2}\""
+        else
+            eval "toggle_${opt}=\"--enable-${opt2} \""
+        fi
+    done
+
+    cat <<EOF
+Usage: configure [options]
+Options:
+
+Build options:
+  --help                      print this message
+  --log=yes|no|FILE           file configure log is written to [config.err]
+  --target=TARGET             target platform tuple [generic-gnu]
+  --cpu=CPU                   optimize for a specific cpu rather than a family
+  --extra-cflags=ECFLAGS      add ECFLAGS to CFLAGS [$CFLAGS]
+  ${toggle_extra_warnings}    emit harmless warnings (always non-fatal)
+  ${toggle_werror}            treat warnings as errors, if possible
+                              (not available with all compilers)
+  ${toggle_optimizations}     turn on/off compiler optimization flags
+  ${toggle_pic}               turn on/off Position Independent Code
+  ${toggle_ccache}            turn on/off compiler cache
+  ${toggle_debug}             enable/disable debug mode
+  ${toggle_gprof}             enable/disable gprof profiling instrumentation
+  ${toggle_gcov}              enable/disable gcov coverage instrumentation
+
+Install options:
+  ${toggle_install_docs}      control whether docs are installed
+  ${toggle_install_bins}      control whether binaries are installed
+  ${toggle_install_libs}      control whether libraries are installed
+  ${toggle_install_srcs}      control whether sources are installed
+
+
+EOF
+}
+
+
+show_help_post(){
+    cat <<EOF
+
+
+NOTES:
+    Object files are built at the place where configure is launched.
+
+    All boolean options can be negated. The default value is the opposite
+    of that shown above. If the option --disable-foo is listed, then
+    the default value for foo is enabled.
+
+Supported targets:
+EOF
+  show_targets ${all_platforms}
+  echo
+  exit 1
+}
+
+
+show_targets() {
+    while [ -n "$*" ]; do
+        if [ "${1%%-*}" = "${2%%-*}" ]; then
+            if [ "${2%%-*}" = "${3%%-*}" ]; then
+                printf "    %-24s %-24s %-24s\n" "$1" "$2" "$3"
+                shift; shift; shift
+            else
+                printf "    %-24s %-24s\n" "$1" "$2"
+                shift; shift
+            fi
+        else
+            printf "    %-24s\n" "$1"
+            shift
+        fi
+    done
+}
+
+
+show_help() {
+    show_help_pre
+    show_help_post
+}
+
+#
+# List Processing Functions
+#
+set_all(){
+    value=$1
+    shift
+    for var in $*; do
+        eval $var=$value
+    done
+}
+
+
+is_in(){
+    value=$1
+    shift
+    for var in $*; do
+        [ $var = $value ] && return 0
+    done
+    return 1
+}
+
+
+add_cflags() {
+    CFLAGS="${CFLAGS} $@"
+}
+
+
+add_ldflags() {
+    LDFLAGS="${LDFLAGS} $@"
+}
+
+
+add_asflags() {
+    ASFLAGS="${ASFLAGS} $@"
+}
+
+
+add_extralibs() {
+    extralibs="${extralibs} $@"
+}
+
+#
+# Boolean Manipulation Functions
+#
+enable(){
+    set_all yes $*
+}
+
+disable(){
+    set_all no $*
+}
+
+enabled(){
+    eval test "x\$$1" = "xyes"
+}
+
+disabled(){
+    eval test "x\$$1" = "xno"
+}
+
+
+soft_enable() {
+    for var in $*; do
+        if ! disabled $var; then
+            log_echo "  enabling $var"
+            enable $var
+        fi
+    done
+}
+
+soft_disable() {
+    for var in $*; do
+        if ! enabled $var; then
+            log_echo "  disabling $var"
+            disable $var
+        fi
+    done
+}
+
+
+#
+# Text Processing Functions
+#
+toupper(){
+    echo "$@" | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ
+}
+
+
+tolower(){
+    echo "$@" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz
+}
+
+
+#
+# Temporary File Functions
+#
+source_path=${0%/*}
+enable source_path_used
+if test -z "$source_path" -o "$source_path" = "." ; then
+    source_path="`pwd`"
+    disable source_path_used
+fi
+
+if test ! -z "$TMPDIR" ; then
+    TMPDIRx="${TMPDIR}"
+elif test ! -z "$TEMPDIR" ; then
+    TMPDIRx="${TEMPDIR}"
+else
+    TMPDIRx="/tmp"
+fi
+TMP_H="${TMPDIRx}/vpx-conf-$$-${RANDOM}.h"
+TMP_C="${TMPDIRx}/vpx-conf-$$-${RANDOM}.c"
+TMP_O="${TMPDIRx}/vpx-conf-$$-${RANDOM}.o"
+TMP_X="${TMPDIRx}/vpx-conf-$$-${RANDOM}.x"
+TMP_ASM="${TMPDIRx}/vpx-conf-$$-${RANDOM}.asm"
+
+clean_temp_files() {
+    rm -f ${TMP_C} ${TMP_H} ${TMP_O} ${TMP_X} ${TMP_ASM}
+}
+
+#
+# Toolchain Check Functions
+#
+check_cmd() {
+    log "$@"
+    "$@" >>${logfile} 2>&1
+}
+
+check_cc() {
+    log check_cc "$@"
+    cat >${TMP_C}
+    log_file ${TMP_C}
+    check_cmd ${CC} ${CFLAGS} "$@" -c -o ${TMP_O} ${TMP_C}
+}
+
+check_cpp() {
+    log check_cpp "$@"
+    cat > ${TMP_C}
+    log_file ${TMP_C}
+    check_cmd ${CC} ${CFLAGS} "$@" -E -o ${TMP_O} ${TMP_C}
+}
+
+check_ld() {
+    log check_ld "$@"
+    check_cc $@ \
+        && check_cmd ${LD} ${LDFLAGS} "$@" -o ${TMP_X} ${TMP_O} ${extralibs}
+}
+
+check_header(){
+    log check_header "$@"
+    header=$1
+    shift
+    var=`echo $header | sed 's/[^A-Za-z0-9_]/_/g'`
+    disable $var
+    check_cpp "$@" <<EOF && enable $var
+#include "$header"
+int x;
+EOF
+}
+
+
+check_cflags() {
+    log check_cflags "$@"
+    check_cc "$@" <<EOF
+int x;
+EOF
+}
+
+check_add_cflags() {
+    check_cflags "$@" && add_cflags "$@"
+}
+
+check_add_asflags() {
+    log add_asflags "$@"
+    add_asflags "$@"
+}
+
+check_add_ldflags() {
+    log add_ldflags "$@"
+    add_ldflags "$@"
+}
+
+check_asm_align() {
+    log check_asm_align "$@"
+    cat >${TMP_ASM} <<EOF
+section .rodata
+align 16
+EOF
+    log_file ${TMP_ASM}
+    check_cmd ${AS} ${ASFLAGS} -o ${TMP_O} ${TMP_ASM}
+    readelf -WS ${TMP_O} >${TMP_X}
+    log_file ${TMP_X}
+    if ! grep -q '\.rodata .* 16$' ${TMP_X}; then
+        die "${AS} ${ASFLAGS} does not support section alignment (nasm <=2.08?)"
+    fi
+}
+
+write_common_config_banner() {
+    print_webm_license config.mk "##" ""
+    echo '# This file automatically generated by configure. Do not edit!' >> config.mk
+    echo "TOOLCHAIN := ${toolchain}" >> config.mk
+
+    case ${toolchain} in
+        *-linux-rvct)
+            echo "ALT_LIBC := ${alt_libc}" >> config.mk
+            ;;
+    esac
+}
+
+write_common_config_targets() {
+    for t in ${all_targets}; do
+        if enabled ${t}; then
+            if enabled universal || enabled child; then
+                fwrite config.mk "ALL_TARGETS += ${t}-${toolchain}"
+            else
+                fwrite config.mk "ALL_TARGETS += ${t}"
+            fi
+        fi
+    true;
+    done
+true
+}
+
+write_common_target_config_mk() {
+    local CC=${CC}
+    enabled ccache && CC="ccache ${CC}"
+    print_webm_license $1 "##" ""
+
+    cat >> $1 << EOF
+# This file automatically generated by configure. Do not edit!
+SRC_PATH="$source_path"
+SRC_PATH_BARE=$source_path
+BUILD_PFX=${BUILD_PFX}
+TOOLCHAIN=${toolchain}
+ASM_CONVERSION=${asm_conversion_cmd:-${source_path}/build/make/ads2gas.pl}
+
+CC=${CC}
+AR=${AR}
+LD=${LD}
+AS=${AS}
+STRIP=${STRIP}
+NM=${NM}
+
+CFLAGS  = ${CFLAGS}
+ARFLAGS = -rus\$(if \$(quiet),c,v)
+LDFLAGS = ${LDFLAGS}
+ASFLAGS = ${ASFLAGS}
+extralibs = ${extralibs}
+AS_SFX    = ${AS_SFX:-.asm}
+EXE_SFX   = ${EXE_SFX}
+RTCD_OPTIONS = ${RTCD_OPTIONS}
+EOF
+
+    if enabled rvct; then cat >> $1 << EOF
+fmt_deps = sed -e 's;^__image.axf;\$(dir \$@)\$(notdir \$<).o \$@;' #hide
+EOF
+    else cat >> $1 << EOF
+fmt_deps = sed -e 's;^\([a-zA-Z0-9_]*\)\.o;\$(dir \$@)\1\$(suffix \$<).o \$@;'
+EOF
+    fi
+
+    print_config_mk ARCH   "${1}" ${ARCH_LIST}
+    print_config_mk HAVE   "${1}" ${HAVE_LIST}
+    print_config_mk CONFIG "${1}" ${CONFIG_LIST}
+    print_config_mk HAVE   "${1}" gnu_strip
+
+    enabled msvs && echo "CONFIG_VS_VERSION=${vs_version}" >> "${1}"
+
+}
+
+
+write_common_target_config_h() {
+    print_webm_license ${TMP_H} "/*" " */"
+    cat >> ${TMP_H} << EOF
+/* This file automatically generated by configure. Do not edit! */
+#ifndef VPX_CONFIG_H
+#define VPX_CONFIG_H
+#define RESTRICT    ${RESTRICT}
+EOF
+    print_config_h ARCH   "${TMP_H}" ${ARCH_LIST}
+    print_config_h HAVE   "${TMP_H}" ${HAVE_LIST}
+    print_config_h CONFIG "${TMP_H}" ${CONFIG_LIST}
+    echo "#endif /* VPX_CONFIG_H */" >> ${TMP_H}
+    mkdir -p `dirname "$1"`
+    cmp "$1" ${TMP_H} >/dev/null 2>&1 || mv ${TMP_H} "$1"
+}
+
+process_common_cmdline() {
+    for opt in "$@"; do
+        optval="${opt#*=}"
+        case "$opt" in
+        --child) enable child
+        ;;
+        --log*)
+        logging="$optval"
+        if ! disabled logging ; then
+            enabled logging || logfile="$logging"
+        else
+            logfile=/dev/null
+        fi
+        ;;
+        --target=*) toolchain="${toolchain:-${optval}}"
+        ;;
+        --force-target=*) toolchain="${toolchain:-${optval}}"; enable force_toolchain
+        ;;
+        --cpu)
+        ;;
+        --cpu=*) tune_cpu="$optval"
+        ;;
+        --extra-cflags=*)
+        extra_cflags="${optval}"
+        ;;
+        --enable-?*|--disable-?*)
+        eval `echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g'`
+        if echo "${ARCH_EXT_LIST}" | grep "^ *$option\$" >/dev/null; then
+            [ $action = "disable" ] && RTCD_OPTIONS="${RTCD_OPTIONS}${opt} "
+        elif [ $action = "disable" ] && ! disabled $option ; then
+          echo "${CMDLINE_SELECT}" | grep "^ *$option\$" >/dev/null ||
+            die_unknown $opt
+        elif [ $action = "enable" ] && ! enabled $option ; then
+          echo "${CMDLINE_SELECT}" | grep "^ *$option\$" >/dev/null ||
+            die_unknown $opt
+        fi
+        $action $option
+        ;;
+        --require-?*)
+        eval `echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g'`
+        if echo "${ARCH_EXT_LIST}" none | grep "^ *$option\$" >/dev/null; then
+            RTCD_OPTIONS="${RTCD_OPTIONS}${opt} "
+        else
+            die_unknown $opt
+        fi
+        ;;
+        --force-enable-?*|--force-disable-?*)
+        eval `echo "$opt" | sed 's/--force-/action=/;s/-/ option=/;s/-/_/g'`
+        $action $option
+        ;;
+        --libc=*)
+        [ -d "${optval}" ] || die "Not a directory: ${optval}"
+        disable builtin_libc
+        alt_libc="${optval}"
+        ;;
+        --as=*)
+        [ "${optval}" = yasm -o "${optval}" = nasm -o "${optval}" = auto ] \
+            || die "Must be yasm, nasm or auto: ${optval}"
+        alt_as="${optval}"
+        ;;
+        --prefix=*)
+        prefix="${optval}"
+        ;;
+        --libdir=*)
+        libdir="${optval}"
+        ;;
+        --sdk-path=*)
+        [ -d "${optval}" ] || die "Not a directory: ${optval}"
+        sdk_path="${optval}"
+        ;;
+        --libc|--as|--prefix|--libdir|--sdk-path)
+        die "Option ${opt} requires argument"
+        ;;
+        --help|-h) show_help
+        ;;
+        *) die_unknown $opt
+        ;;
+        esac
+    done
+}
+
+process_cmdline() {
+    for opt do
+        optval="${opt#*=}"
+        case "$opt" in
+        *) process_common_cmdline $opt
+        ;;
+        esac
+    done
+}
+
+
+post_process_common_cmdline() {
+    prefix="${prefix:-/usr/local}"
+    prefix="${prefix%/}"
+    libdir="${libdir:-${prefix}/lib}"
+    libdir="${libdir%/}"
+    if [ "${libdir#${prefix}}" = "${libdir}" ]; then
+        die "Libdir ${libdir} must be a subdirectory of ${prefix}"
+    fi
+}
+
+
+post_process_cmdline() {
+    true;
+}
+
+setup_gnu_toolchain() {
+        CC=${CC:-${CROSS}gcc}
+        AR=${AR:-${CROSS}ar}
+        LD=${LD:-${CROSS}${link_with_cc:-ld}}
+        AS=${AS:-${CROSS}as}
+    STRIP=${STRIP:-${CROSS}strip}
+    NM=${NM:-${CROSS}nm}
+        AS_SFX=.s
+        EXE_SFX=
+}
+
+process_common_toolchain() {
+    if [ -z "$toolchain" ]; then
+        gcctarget="$(gcc -dumpmachine 2> /dev/null)"
+
+        # detect tgt_isa
+        case "$gcctarget" in
+            *x86_64*|*amd64*)
+                tgt_isa=x86_64
+                ;;
+            *i[3456]86*)
+                tgt_isa=x86
+                ;;
+            *powerpc64*)
+                tgt_isa=ppc64
+                ;;
+            *powerpc*)
+                tgt_isa=ppc32
+                ;;
+            *sparc*)
+                tgt_isa=sparc
+                ;;
+        esac
+
+        # detect tgt_os
+        case "$gcctarget" in
+            *darwin8*)
+                tgt_isa=universal
+                tgt_os=darwin8
+                ;;
+            *darwin9*)
+                tgt_isa=universal
+                tgt_os=darwin9
+                ;;
+            *darwin10*)
+                tgt_isa=x86_64
+                tgt_os=darwin10
+                ;;
+            *darwin11*)
+                tgt_isa=x86_64
+                tgt_os=darwin11
+                ;;
+            *darwin12*)
+                tgt_isa=x86_64
+                tgt_os=darwin12
+                ;;
+            *mingw32*|*cygwin*)
+                [ -z "$tgt_isa" ] && tgt_isa=x86
+                tgt_os=win32
+                ;;
+            *linux*|*bsd*)
+                tgt_os=linux
+                ;;
+            *solaris2.10)
+                tgt_os=solaris
+                ;;
+            *os2*)
+                tgt_os=os2
+                ;;
+        esac
+
+        if [ -n "$tgt_isa" ] && [ -n "$tgt_os" ]; then
+            toolchain=${tgt_isa}-${tgt_os}-gcc
+        fi
+    fi
+
+    toolchain=${toolchain:-generic-gnu}
+
+    is_in ${toolchain} ${all_platforms} || enabled force_toolchain \
+        || die "Unrecognized toolchain '${toolchain}'"
+
+    enabled child || log_echo "Configuring for target '${toolchain}'"
+
+    #
+    # Set up toolchain variables
+    #
+    tgt_isa=$(echo ${toolchain} | awk 'BEGIN{FS="-"}{print $1}')
+    tgt_os=$(echo ${toolchain} | awk 'BEGIN{FS="-"}{print $2}')
+    tgt_cc=$(echo ${toolchain} | awk 'BEGIN{FS="-"}{print $3}')
+
+    # Mark the specific ISA requested as enabled
+    soft_enable ${tgt_isa}
+    enable ${tgt_os}
+    enable ${tgt_cc}
+
+    # Enable the architecture family
+    case ${tgt_isa} in
+        arm*) enable arm;;
+        mips*) enable mips;;
+    esac
+
+    # PIC is probably what we want when building shared libs
+    enabled shared && soft_enable pic
+
+    # Handle darwin variants. Newer SDKs allow targeting older
+    # platforms, so find the newest SDK available.
+    case ${toolchain} in
+        *-darwin*)
+            if [ -z "${DEVELOPER_DIR}" ]; then
+                DEVELOPER_DIR=`xcode-select -print-path 2> /dev/null`
+                [ $? -ne 0 ] && OSX_SKIP_DIR_CHECK=1
+            fi
+            if [ -z "${OSX_SKIP_DIR_CHECK}" ]; then
+                OSX_SDK_ROOTS="${DEVELOPER_DIR}/SDKs"
+                OSX_SDK_VERSIONS="MacOSX10.4u.sdk MacOSX10.5.sdk MacOSX10.6.sdk"
+                OSX_SDK_VERSIONS="${OSX_SDK_VERSIONS} MacOSX10.7.sdk"
+                for v in ${OSX_SDK_VERSIONS}; do
+                    if [ -d "${OSX_SDK_ROOTS}/${v}" ]; then
+                        osx_sdk_dir="${OSX_SDK_ROOTS}/${v}"
+                    fi
+                done
+            fi
+            ;;
+    esac
+
+    if [ -d "${osx_sdk_dir}" ]; then
+        add_cflags  "-isysroot ${osx_sdk_dir}"
+        add_ldflags "-isysroot ${osx_sdk_dir}"
+    fi
+
+    case ${toolchain} in
+        *-darwin8-*)
+            add_cflags  "-mmacosx-version-min=10.4"
+            add_ldflags "-mmacosx-version-min=10.4"
+            ;;
+        *-darwin9-*)
+            add_cflags  "-mmacosx-version-min=10.5"
+            add_ldflags "-mmacosx-version-min=10.5"
+            ;;
+        *-darwin10-*)
+            add_cflags  "-mmacosx-version-min=10.6"
+            add_ldflags "-mmacosx-version-min=10.6"
+            ;;
+        *-darwin11-*)
+            add_cflags  "-mmacosx-version-min=10.7"
+            add_ldflags "-mmacosx-version-min=10.7"
+            ;;
+        *-darwin12-*)
+            add_cflags  "-mmacosx-version-min=10.8"
+            add_ldflags "-mmacosx-version-min=10.8"
+            ;;
+    esac
+
+    # Handle Solaris variants. Solaris 10 needs -lposix4
+    case ${toolchain} in
+        sparc-solaris-*)
+            add_extralibs -lposix4
+            disable fast_unaligned
+            ;;
+        *-solaris-*)
+            add_extralibs -lposix4
+            ;;
+    esac
+
+    # Process ARM architecture variants
+    case ${toolchain} in
+    arm*)
+        # on arm, isa versions are supersets
+        case ${tgt_isa} in
+        armv7)
+            soft_enable neon
+            soft_enable media
+            soft_enable edsp
+            soft_enable fast_unaligned
+            ;;
+        armv6)
+            soft_enable media
+            soft_enable edsp
+            soft_enable fast_unaligned
+            ;;
+        armv5te)
+            soft_enable edsp
+            ;;
+        esac
+
+        asm_conversion_cmd="cat"
+
+        case ${tgt_cc} in
+        gcc)
+            CROSS=${CROSS:-arm-none-linux-gnueabi-}
+            link_with_cc=gcc
+            setup_gnu_toolchain
+            arch_int=${tgt_isa##armv}
+            arch_int=${arch_int%%te}
+            check_add_asflags --defsym ARCHITECTURE=${arch_int}
+            tune_cflags="-mtune="
+            if [ ${tgt_isa} == "armv7" ]; then
+                if enabled neon
+                then
+                    check_add_cflags -mfpu=neon #-ftree-vectorize
+                    check_add_asflags -mfpu=neon
+                fi
+                check_add_cflags -march=armv7-a -mcpu=cortex-a8 -mfloat-abi=softfp
+                check_add_asflags -mcpu=cortex-a8 -mfloat-abi=softfp  #-march=armv7-a
+            else
+                check_add_cflags -march=${tgt_isa}
+                check_add_asflags -march=${tgt_isa}
+            fi
+            enabled debug && add_asflags -g
+            asm_conversion_cmd="${source_path}/build/make/ads2gas.pl"
+            ;;
+        rvct)
+            CC=armcc
+            AR=armar
+            AS=armasm
+            LD=${source_path}/build/make/armlink_adapter.sh
+            STRIP=arm-none-linux-gnueabi-strip
+            NM=arm-none-linux-gnueabi-nm
+            tune_cflags="--cpu="
+            tune_asflags="--cpu="
+            if [ -z "${tune_cpu}" ]; then
+                if [ ${tgt_isa} == "armv7" ]; then
+                    if enabled neon
+                    then
+                        check_add_cflags --fpu=softvfp+vfpv3
+                        check_add_asflags --fpu=softvfp+vfpv3
+                    fi
+                    check_add_cflags --cpu=Cortex-A8
+                    check_add_asflags --cpu=Cortex-A8
+                else
+                    check_add_cflags --cpu=${tgt_isa##armv}
+                    check_add_asflags --cpu=${tgt_isa##armv}
+                fi
+            fi
+            arch_int=${tgt_isa##armv}
+            arch_int=${arch_int%%te}
+            check_add_asflags --pd "\"ARCHITECTURE SETA ${arch_int}\""
+            enabled debug && add_asflags -g
+            add_cflags --gnu
+            add_cflags --enum_is_int
+            add_cflags --wchar32
+        ;;
+        esac
+
+        case ${tgt_os} in
+        none*)
+            disable multithread
+            disable os_support
+            ;;
+
+        android*)
+            SDK_PATH=${sdk_path}
+            COMPILER_LOCATION=`find "${SDK_PATH}" \
+                               -name "arm-linux-androideabi-gcc*" -print -quit`
+            TOOLCHAIN_PATH=${COMPILER_LOCATION%/*}/arm-linux-androideabi-
+            CC=${TOOLCHAIN_PATH}gcc
+            AR=${TOOLCHAIN_PATH}ar
+            LD=${TOOLCHAIN_PATH}gcc
+            AS=${TOOLCHAIN_PATH}as
+            STRIP=${TOOLCHAIN_PATH}strip
+            NM=${TOOLCHAIN_PATH}nm
+
+            if [ -z "${alt_libc}" ]; then
+                alt_libc=`find "${SDK_PATH}" -name arch-arm -print | \
+                          awk '{n = split($0,a,"/"); \
+                                split(a[n-1],b,"-"); \
+                                print $0 " " b[2]}' | \
+                          sort -g -k 2 | \
+                          awk '{ print $1 }' | tail -1`
+            fi
+
+            add_cflags "--sysroot=${alt_libc}"
+            add_ldflags "--sysroot=${alt_libc}"
+
+            add_cflags "-I${SDK_PATH}/sources/android/cpufeatures/"
+
+            enable pic
+            soft_enable realtime_only
+            if [ ${tgt_isa} == "armv7" ]; then
+                enable runtime_cpu_detect
+            fi
+          ;;
+
+        darwin*)
+            if [ -z "${sdk_path}" ]; then
+                SDK_PATH=`xcode-select -print-path 2> /dev/null`
+                SDK_PATH=${SDK_PATH}/Platforms/iPhoneOS.platform/Developer
+            else
+                SDK_PATH=${sdk_path}
+            fi
+            TOOLCHAIN_PATH=${SDK_PATH}/usr/bin
+            CC=${TOOLCHAIN_PATH}/gcc
+            AR=${TOOLCHAIN_PATH}/ar
+            LD=${TOOLCHAIN_PATH}/arm-apple-darwin10-llvm-gcc-4.2
+            AS=${TOOLCHAIN_PATH}/as
+            STRIP=${TOOLCHAIN_PATH}/strip
+            NM=${TOOLCHAIN_PATH}/nm
+            AS_SFX=.s
+
+            # ASFLAGS is written here instead of using check_add_asflags
+            # because we need to overwrite all of ASFLAGS and purge the
+            # options that were put in above
+            ASFLAGS="-version -arch ${tgt_isa} -g"
+
+            add_cflags -arch ${tgt_isa}
+            add_ldflags -arch_only ${tgt_isa}
+
+            if [ -z "${alt_libc}" ]; then
+                alt_libc=${SDK_PATH}/SDKs/iPhoneOS5.1.sdk
+            fi
+
+            add_cflags  "-isysroot ${alt_libc}"
+
+            # Add the paths for the alternate libc
+            for d in usr/include; do
+                try_dir="${alt_libc}/${d}"
+                [ -d "${try_dir}" ] && add_cflags -I"${try_dir}"
+            done
+
+            for d in lib usr/lib usr/lib/system; do
+                try_dir="${alt_libc}/${d}"
+                [ -d "${try_dir}" ] && add_ldflags -L"${try_dir}"
+            done
+
+            asm_conversion_cmd="${source_path}/build/make/ads2gas_apple.pl"
+         ;;
+
+        linux*)
+            enable linux
+            if enabled rvct; then
+                # Check if we have CodeSourcery GCC in PATH. Needed for
+                # libraries
+                hash arm-none-linux-gnueabi-gcc 2>&- || \
+                  die "Couldn't find CodeSourcery GCC from PATH"
+
+                # Use armcc as a linker to enable translation of
+                # some gcc specific options such as -lm and -lpthread.
+                LD="armcc --translate_gcc"
+
+                # create configuration file (uses path to CodeSourcery GCC)
+                armcc --arm_linux_configure --arm_linux_config_file=arm_linux.cfg
+
+                add_cflags --arm_linux_paths --arm_linux_config_file=arm_linux.cfg
+                add_asflags --no_hide_all --apcs=/interwork
+                add_ldflags --arm_linux_paths --arm_linux_config_file=arm_linux.cfg
+                enabled pic && add_cflags --apcs=/fpic
+                enabled pic && add_asflags --apcs=/fpic
+                enabled shared && add_cflags --shared
+            fi
+        ;;
+
+        esac
+    ;;
+    mips*)
+        CROSS=${CROSS:-mipsel-linux-uclibc-}
+        link_with_cc=gcc
+        setup_gnu_toolchain
+        tune_cflags="-mtune="
+        check_add_cflags -march=${tgt_isa}
+    check_add_asflags -march=${tgt_isa}
+    check_add_asflags -KPIC
+    ;;
+    ppc*)
+        enable ppc
+        bits=${tgt_isa##ppc}
+        link_with_cc=gcc
+        setup_gnu_toolchain
+        add_asflags -force_cpusubtype_ALL -I"\$(dir \$<)darwin"
+        soft_enable altivec
+        enabled altivec && add_cflags -maltivec
+
+        case "$tgt_os" in
+        linux*)
+            add_asflags -maltivec -mregnames -I"\$(dir \$<)linux"
+        ;;
+        darwin*)
+            darwin_arch="-arch ppc"
+            enabled ppc64 && darwin_arch="${darwin_arch}64"
+            add_cflags  ${darwin_arch} -m${bits} -fasm-blocks
+            add_asflags ${darwin_arch} -force_cpusubtype_ALL -I"\$(dir \$<)darwin"
+            add_ldflags ${darwin_arch} -m${bits}
+            enabled altivec && add_cflags -faltivec
+        ;;
+        esac
+    ;;
+    x86*)
+        bits=32
+        enabled x86_64 && bits=64
+        soft_enable runtime_cpu_detect
+        soft_enable mmx
+        soft_enable sse
+        soft_enable sse2
+        soft_enable sse3
+        soft_enable ssse3
+        soft_enable sse4_1
+
+        case  ${tgt_os} in
+            win*)
+                enabled gcc && add_cflags -fno-common
+                ;;
+            solaris*)
+                CC=${CC:-${CROSS}gcc}
+                LD=${LD:-${CROSS}gcc}
+                CROSS=${CROSS:-g}
+                ;;
+            os2)
+                AS=${AS:-nasm}
+                ;;
+        esac
+
+        AS="${alt_as:-${AS:-auto}}"
+        case  ${tgt_cc} in
+            icc*)
+                CC=${CC:-icc}
+                LD=${LD:-icc}
+                setup_gnu_toolchain
+                add_cflags -use-msasm -use-asm
+                add_ldflags -i-static
+                enabled x86_64 && add_cflags -ipo -no-prec-div -static -xSSE2 -axSSE2
+                enabled x86_64 && AR=xiar
+                case ${tune_cpu} in
+                    atom*)
+                        tune_cflags="-x"
+                        tune_cpu="SSE3_ATOM"
+                    ;;
+                    *)
+                        tune_cflags="-march="
+                    ;;
+                esac
+                ;;
+            gcc*)
+                add_cflags  -m${bits}
+                add_ldflags -m${bits}
+                link_with_cc=gcc
+                tune_cflags="-march="
+            setup_gnu_toolchain
+                #for 32 bit x86 builds, -O3 did not turn on this flag
+                enabled optimizations && check_add_cflags -fomit-frame-pointer
+                ;;
+        esac
+
+        case "${AS}" in
+            auto|"")
+                which nasm >/dev/null 2>&1 && AS=nasm
+                which yasm >/dev/null 2>&1 && AS=yasm
+                [ "${AS}" = auto -o -z "${AS}" ] \
+                    && die "Neither yasm nor nasm have been found"
+                ;;
+        esac
+        log_echo "  using $AS"
+        [ "${AS##*/}" = nasm ] && add_asflags -Ox
+        AS_SFX=.asm
+        case  ${tgt_os} in
+            win32)
+                add_asflags -f win32
+                enabled debug && add_asflags -g cv8
+            ;;
+            win64)
+                add_asflags -f x64
+                enabled debug && add_asflags -g cv8
+            ;;
+            linux*|solaris*)
+                add_asflags -f elf${bits}
+                enabled debug && [ "${AS}" = yasm ] && add_asflags -g dwarf2
+                enabled debug && [ "${AS}" = nasm ] && add_asflags -g
+                [ "${AS##*/}" = nasm ] && check_asm_align
+            ;;
+            darwin*)
+                add_asflags -f macho${bits}
+                enabled x86 && darwin_arch="-arch i386" || darwin_arch="-arch x86_64"
+                add_cflags  ${darwin_arch}
+                add_ldflags ${darwin_arch}
+                # -mdynamic-no-pic is still a bit of voodoo -- it was required at
+                # one time, but does not seem to be now, and it breaks some of the
+                # code that still relies on inline assembly.
+                # enabled icc && ! enabled pic && add_cflags -fno-pic -mdynamic-no-pic
+                enabled icc && ! enabled pic && add_cflags -fno-pic
+            ;;
+            os2)
+                add_asflags -f aout
+                enabled debug && add_asflags -g
+                EXE_SFX=.exe
+            ;;
+            *) log "Warning: Unknown os $tgt_os while setting up $AS flags"
+            ;;
+        esac
+    ;;
+    universal*|*-gcc|generic-gnu)
+        link_with_cc=gcc
+        enable gcc
+    setup_gnu_toolchain
+    ;;
+    esac
+
+    # Try to enable CPU specific tuning
+    if [ -n "${tune_cpu}" ]; then
+        if [ -n "${tune_cflags}" ]; then
+            check_add_cflags ${tune_cflags}${tune_cpu} || \
+                die "Requested CPU '${tune_cpu}' not supported by compiler"
+        fi
+    if [ -n "${tune_asflags}" ]; then
+            check_add_asflags ${tune_asflags}${tune_cpu} || \
+                die "Requested CPU '${tune_cpu}' not supported by assembler"
+        fi
+    if [ -z "${tune_cflags}${tune_asflags}" ]; then
+            log_echo "Warning: CPU tuning not supported by this toolchain"
+        fi
+    fi
+
+    enabled debug && check_add_cflags -g && check_add_ldflags -g
+    enabled gprof && check_add_cflags -pg && check_add_ldflags -pg
+    enabled gcov &&
+        check_add_cflags -fprofile-arcs -ftest-coverage &&
+        check_add_ldflags -fprofile-arcs -ftest-coverage
+
+    if enabled optimizations; then
+        if enabled rvct; then
+            enabled small && check_add_cflags -Ospace || check_add_cflags -Otime
+        else
+            enabled small && check_add_cflags -O2 ||  check_add_cflags -O3
+        fi
+    fi
+
+    # Position Independent Code (PIC) support, for building relocatable
+    # shared objects
+    enabled gcc && enabled pic && check_add_cflags -fPIC
+
+    # Work around longjmp interception on glibc >= 2.11, to improve binary
+    # compatibility. See http://code.google.com/p/webm/issues/detail?id=166
+    enabled linux && check_add_cflags -D_FORTIFY_SOURCE=0
+
+    # Check for strip utility variant
+    ${STRIP} -V 2>/dev/null | grep GNU >/dev/null && enable gnu_strip
+
+    # Try to determine target endianness
+    check_cc <<EOF
+    unsigned int e = 'O'<<24 | '2'<<16 | 'B'<<8 | 'E';
+EOF
+    [ -f "${TMP_O}" ] && od -A n -t x1 "${TMP_O}" | tr -d '\n' |
+        grep '4f *32 *42 *45' >/dev/null 2>&1 && enable big_endian
+
+    # Almost every platform uses pthreads.
+    if enabled multithread; then
+        case ${toolchain} in
+            *-win*);;
+            *-android-gcc);;
+            *) check_header pthread.h && add_extralibs -lpthread
+        esac
+    fi
+
+    # for sysconf(3) and friends.
+    check_header unistd.h
+
+    # glibc needs these
+    if enabled linux; then
+        add_cflags -D_LARGEFILE_SOURCE
+        add_cflags -D_FILE_OFFSET_BITS=64
+    fi
+
+    # append any user defined extra cflags
+    if [ -n "${extra_cflags}" ] ; then
+        check_add_cflags ${extra_cflags} || \
+        die "Requested extra CFLAGS '${extra_cflags}' not supported by compiler"
+    fi
+}
+
+process_toolchain() {
+    process_common_toolchain
+}
+
+print_config_mk() {
+    local prefix=$1
+    local makefile=$2
+    shift 2
+    for cfg; do
+        upname="`toupper $cfg`"
+        if enabled $cfg; then
+            echo "${prefix}_${upname}=yes" >> $makefile
+        fi
+    done
+}
+
+print_config_h() {
+    local prefix=$1
+    local header=$2
+    shift 2
+    for cfg; do
+        upname="`toupper $cfg`"
+        if enabled $cfg; then
+            echo "#define ${prefix}_${upname} 1" >> $header
+        else
+            echo "#define ${prefix}_${upname} 0" >> $header
+        fi
+    done
+}
+
+print_webm_license() {
+    local destination=$1
+    local prefix=$2
+    local suffix=$3
+    shift 3
+    cat <<EOF > ${destination}
+${prefix} Copyright (c) 2011 The WebM project authors. All Rights Reserved.${suffix}
+${prefix} ${suffix}
+${prefix} Use of this source code is governed by a BSD-style license${suffix}
+${prefix} that can be found in the LICENSE file in the root of the source${suffix}
+${prefix} tree. An additional intellectual property rights grant can be found${suffix}
+${prefix} in the file PATENTS.  All contributing project authors may${suffix}
+${prefix} be found in the AUTHORS file in the root of the source tree.${suffix}
+EOF
+}
+
+process_targets() {
+    true;
+}
+
+process_detect() {
+    true;
+}
+
+enable logging
+logfile="config.err"
+self=$0
+process() {
+    cmdline_args="$@"
+    process_cmdline "$@"
+    if enabled child; then
+        echo "# ${self} $@" >> ${logfile}
+    else
+        echo "# ${self} $@" > ${logfile}
+    fi
+    post_process_common_cmdline
+    post_process_cmdline
+    process_toolchain
+    process_detect
+    process_targets
+
+    OOT_INSTALLS="${OOT_INSTALLS}"
+    if enabled source_path_used; then
+    # Prepare the PWD for building.
+    for f in ${OOT_INSTALLS}; do
+            install -D ${source_path}/$f $f
+    done
+    fi
+    cp ${source_path}/build/make/Makefile .
+
+    clean_temp_files
+    true
+}
diff --git a/build/make/gen_asm_deps.sh b/build/make/gen_asm_deps.sh
new file mode 100755 (executable)
index 0000000..717f870
--- /dev/null
@@ -0,0 +1,64 @@
+#!/bin/bash
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+
+self=$0
+show_help() {
+    echo "usage: $self [options] <srcfile>"
+    echo
+    echo "Generate Makefile dependency information from assembly code source"
+    echo
+    exit 1
+}
+die_unknown(){
+    echo "Unknown option \"$1\"."
+    echo "See $0 --help for available options."
+    exit 1
+}
+for opt do
+    optval="${opt#*=}"
+    case "$opt" in
+    --build-pfx=*) pfx="${optval}"
+    ;;
+    --depfile=*) out="${optval}"
+    ;;
+    -I*) raw_inc_paths="${raw_inc_paths} ${opt}"
+         inc_path="${inc_path} ${opt#-I}"
+    ;;
+    -h|--help) show_help
+    ;;
+    *) [ -f "$opt" ] && srcfile="$opt"
+    ;;
+    esac
+done
+
+[ -n "$srcfile" ] || show_help
+sfx=${sfx:-asm}
+includes=$(LC_ALL=C egrep -i "include +\"?+[a-z0-9_/]+\.${sfx}" $srcfile |
+           perl -p -e "s;.*?([a-z0-9_/]+.${sfx}).*;\1;")
+#" restore editor state
+for inc in ${includes}; do
+    found_inc_path=
+    for idir in ${inc_path}; do
+        [ -f "${idir}/${inc}" ] && found_inc_path="${idir}" && break
+    done
+    if [ -f `dirname $srcfile`/$inc ]; then
+        # Handle include files in the same directory as the source
+        $self --build-pfx=$pfx --depfile=$out ${raw_inc_paths} `dirname $srcfile`/$inc
+    elif [ -n "${found_inc_path}" ]; then
+        # Handle include files on the include path
+        $self --build-pfx=$pfx --depfile=$out ${raw_inc_paths} "${found_inc_path}/$inc"
+    else
+        # Handle generated includes in the build root (which may not exist yet)
+        echo ${out} ${out%d}o: "${pfx}${inc}"
+    fi
+done
+echo ${out} ${out%d}o: $srcfile
diff --git a/build/make/gen_msvs_def.sh b/build/make/gen_msvs_def.sh
new file mode 100755 (executable)
index 0000000..4defcc2
--- /dev/null
@@ -0,0 +1,83 @@
+#!/bin/bash
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+
+self=$0
+self_basename=${self##*/}
+EOL=$'\n'
+
+show_help() {
+    cat <<EOF
+Usage: ${self_basename} [options] file1 [file2 ...]
+
+This script generates a MSVC module definition file containing a list of symbols
+to export from a DLL. Source files are technically bash scripts (and thus may
+use #comment syntax) but in general, take the form of a list of symbols:
+
+  <kind> symbol1 [symbol2, symbol3, ...]
+
+where <kind> is either 'text' or 'data'
+
+
+Options:
+    --help                      Print this message
+    --out=filename              Write output to a file [stdout]
+    --name=project_name         Name of the library (required)
+EOF
+    exit 1
+}
+
+die() {
+    echo "${self_basename}: $@"
+    exit 1
+}
+
+die_unknown(){
+    echo "Unknown option \"$1\"."
+    echo "See ${self_basename} --help for available options."
+    exit 1
+}
+
+text() {
+    for sym in "$@"; do
+        echo "  $sym" >> ${outfile}
+    done
+}
+
+data() {
+    for sym in "$@"; do
+        printf "  %-40s DATA\n" "$sym" >> ${outfile}
+    done
+}
+
+# Process command line
+for opt in "$@"; do
+    optval="${opt#*=}"
+    case "$opt" in
+    --help|-h) show_help
+    ;;
+    --out=*) outfile="$optval"
+    ;;
+    --name=*) name="${optval}"
+    ;;
+     -*) die_unknown $opt
+    ;;
+    *) file_list[${#file_list[@]}]="$opt"
+    esac
+done
+outfile=${outfile:-/dev/stdout}
+[ -n "$name" ] || die "Library name (--name) must be specified!"
+
+echo "LIBRARY ${name}" > ${outfile}
+echo "EXPORTS" >> ${outfile}
+for f in "${file_list[@]}"; do
+    . $f
+done
diff --git a/build/make/gen_msvs_proj.sh b/build/make/gen_msvs_proj.sh
new file mode 100755 (executable)
index 0000000..6d42941
--- /dev/null
@@ -0,0 +1,573 @@
+#!/bin/bash
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+
+self=$0
+self_basename=${self##*/}
+self_dirname=$(dirname "$0")
+EOL=$'\n'
+
+show_help() {
+    cat <<EOF
+Usage: ${self_basename} --name=projname [options] file1 [file2 ...]
+
+This script generates a Visual Studio project file from a list of source
+code files.
+
+Options:
+    --help                      Print this message
+    --exe                       Generate a project for building an Application
+    --lib                       Generate a project for creating a static library
+    --static-crt                Use the static C runtime (/MT)
+    --target=isa-os-cc          Target specifier (required)
+    --out=filename              Write output to a file [stdout]
+    --name=project_name         Name of the project (required)
+    --proj-guid=GUID            GUID to use for the project
+    --module-def=filename       File containing export definitions (for DLLs)
+    --ver=version               Version (7,8,9) of visual studio to generate for
+    --src-path-bare=dir         Path to root of source tree
+    -Ipath/to/include           Additional include directories
+    -DFLAG[=value]              Preprocessor macros to define
+    -Lpath/to/lib               Additional library search paths
+    -llibname                   Library to link against
+EOF
+    exit 1
+}
+
+die() {
+    echo "${self_basename}: $@" >&2
+    exit 1
+}
+
+die_unknown(){
+    echo "Unknown option \"$1\"." >&2
+    echo "See ${self_basename} --help for available options." >&2
+    exit 1
+}
+
+generate_uuid() {
+    local hex="0123456789ABCDEF"
+    local i
+    local uuid=""
+    local j
+    #93995380-89BD-4b04-88EB-625FBE52EBFB
+    for ((i=0; i<32; i++)); do
+        (( j = $RANDOM % 16 ))
+        uuid="${uuid}${hex:$j:1}"
+    done
+    echo "${uuid:0:8}-${uuid:8:4}-${uuid:12:4}-${uuid:16:4}-${uuid:20:12}"
+}
+
+indent1="    "
+indent=""
+indent_push() {
+    indent="${indent}${indent1}"
+}
+indent_pop() {
+    indent="${indent%${indent1}}"
+}
+
+tag_attributes() {
+    for opt in "$@"; do
+        optval="${opt#*=}"
+        [ -n "${optval}" ] ||
+            die "Missing attribute value in '$opt' while generating $tag tag"
+        echo "${indent}${opt%%=*}=\"${optval}\""
+    done
+}
+
+open_tag() {
+    local tag=$1
+    shift
+    if [ $# -ne 0 ]; then
+        echo "${indent}<${tag}"
+        indent_push
+        tag_attributes "$@"
+        echo "${indent}>"
+    else
+        echo "${indent}<${tag}>"
+        indent_push
+    fi
+}
+
+close_tag() {
+    local tag=$1
+    indent_pop
+    echo "${indent}</${tag}>"
+}
+
+tag() {
+    local tag=$1
+    shift
+    if [ $# -ne 0 ]; then
+        echo "${indent}<${tag}"
+        indent_push
+        tag_attributes "$@"
+        indent_pop
+        echo "${indent}/>"
+    else
+        echo "${indent}<${tag}/>"
+    fi
+}
+
+generate_filter() {
+    local var=$1
+    local name=$2
+    local pats=$3
+    local file_list_sz
+    local i
+    local f
+    local saveIFS="$IFS"
+    local pack
+    echo "generating filter '$name' from ${#file_list[@]} files" >&2
+    IFS=*
+
+    open_tag Filter \
+        Name=$name \
+        Filter=$pats \
+        UniqueIdentifier=`generate_uuid` \
+
+    file_list_sz=${#file_list[@]}
+    for i in ${!file_list[@]}; do
+        f=${file_list[i]}
+        for pat in ${pats//;/$IFS}; do
+            if [ "${f##*.}" == "$pat" ]; then
+                unset file_list[i]
+
+                open_tag File RelativePath="./$f"
+                if [ "$pat" == "asm" ] && $asm_use_custom_step; then
+                    for plat in "${platforms[@]}"; do
+                        for cfg in Debug Release; do
+                            open_tag FileConfiguration \
+                                Name="${cfg}|${plat}" \
+
+                            tag Tool \
+                                Name="VCCustomBuildTool" \
+                                Description="Assembling \$(InputFileName)" \
+                                CommandLine="$(eval echo \$asm_${cfg}_cmdline)" \
+                                Outputs="\$(InputName).obj" \
+
+                            close_tag FileConfiguration
+                        done
+                    done
+                fi
+
+                close_tag File
+
+                break
+            fi
+        done
+    done
+
+    close_tag Filter
+    IFS="$saveIFS"
+}
+
+# Process command line
+unset target
+for opt in "$@"; do
+    optval="${opt#*=}"
+    case "$opt" in
+        --help|-h) show_help
+        ;;
+        --target=*) target="${optval}"
+        ;;
+        --out=*) outfile="$optval"
+        ;;
+        --name=*) name="${optval}"
+        ;;
+        --proj-guid=*) guid="${optval}"
+        ;;
+        --module-def=*) link_opts="${link_opts} ModuleDefinitionFile=${optval}"
+        ;;
+        --exe) proj_kind="exe"
+        ;;
+        --lib) proj_kind="lib"
+        ;;
+        --src-path-bare=*) src_path_bare="$optval"
+        ;;
+        --static-crt) use_static_runtime=true
+        ;;
+        --ver=*)
+            vs_ver="$optval"
+            case "$optval" in
+                [789])
+                ;;
+                *) die Unrecognized Visual Studio Version in $opt
+                ;;
+            esac
+        ;;
+        -I*)
+            opt="${opt%/}"
+            incs="${incs}${incs:+;}&quot;${opt##-I}&quot;"
+            yasmincs="${yasmincs} ${opt}"
+        ;;
+        -D*) defines="${defines}${defines:+;}${opt##-D}"
+        ;;
+        -L*) # fudge . to $(OutDir)
+            if [ "${opt##-L}" == "." ]; then
+                libdirs="${libdirs}${libdirs:+;}&quot;\$(OutDir)&quot;"
+            else
+                 # Also try directories for this platform/configuration
+                 libdirs="${libdirs}${libdirs:+;}&quot;${opt##-L}&quot;"
+                 libdirs="${libdirs}${libdirs:+;}&quot;${opt##-L}/\$(PlatformName)/\$(ConfigurationName)&quot;"
+                 libdirs="${libdirs}${libdirs:+;}&quot;${opt##-L}/\$(PlatformName)&quot;"
+            fi
+        ;;
+        -l*) libs="${libs}${libs:+ }${opt##-l}.lib"
+        ;;
+        -*) die_unknown $opt
+        ;;
+        *)
+            file_list[${#file_list[@]}]="$opt"
+            case "$opt" in
+                 *.asm) uses_asm=true
+                 ;;
+            esac
+        ;;
+    esac
+done
+outfile=${outfile:-/dev/stdout}
+guid=${guid:-`generate_uuid`}
+asm_use_custom_step=false
+uses_asm=${uses_asm:-false}
+case "${vs_ver:-8}" in
+    7) vs_ver_id="7.10"
+       asm_use_custom_step=$uses_asm
+    ;;
+    8) vs_ver_id="8.00"
+    ;;
+    9) vs_ver_id="9.00"
+    ;;
+esac
+
+[ -n "$name" ] || die "Project name (--name) must be specified!"
+[ -n "$target" ] || die "Target (--target) must be specified!"
+
+if ${use_static_runtime:-false}; then
+    release_runtime=0
+    debug_runtime=1
+    lib_sfx=mt
+else
+    release_runtime=2
+    debug_runtime=3
+    lib_sfx=md
+fi
+
+# Calculate debug lib names: If a lib ends in ${lib_sfx}.lib, then rename
+# it to ${lib_sfx}d.lib. This precludes linking to release libs from a
+# debug exe, so this may need to be refactored later.
+for lib in ${libs}; do
+    if [ "$lib" != "${lib%${lib_sfx}.lib}" ]; then
+        lib=${lib%.lib}d.lib
+    fi
+    debug_libs="${debug_libs}${debug_libs:+ }${lib}"
+done
+
+
+# List Keyword for this target
+case "$target" in
+    x86*) keyword="ManagedCProj"
+    ;;
+    *) die "Unsupported target $target!"
+esac
+
+# List of all platforms supported for this target
+case "$target" in
+    x86_64*)
+        platforms[0]="x64"
+    ;;
+    x86*)
+        platforms[0]="Win32"
+        # these are only used by vs7
+        asm_Debug_cmdline="yasm -Xvc -g cv8 -f \$(PlatformName) ${yasmincs} &quot;\$(InputPath)&quot;"
+        asm_Release_cmdline="yasm -Xvc -f \$(PlatformName) ${yasmincs} &quot;\$(InputPath)&quot;"
+    ;;
+    *) die "Unsupported target $target!"
+    ;;
+esac
+
+generate_vcproj() {
+    case "$proj_kind" in
+        exe) vs_ConfigurationType=1
+        ;;
+        *)   vs_ConfigurationType=4
+        ;;
+    esac
+
+    echo "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>"
+    open_tag VisualStudioProject \
+        ProjectType="Visual C++" \
+        Version="${vs_ver_id}" \
+        Name="${name}" \
+        ProjectGUID="{${guid}}" \
+        RootNamespace="${name}" \
+        Keyword="${keyword}" \
+
+    open_tag Platforms
+    for plat in "${platforms[@]}"; do
+        tag Platform Name="$plat"
+    done
+    close_tag Platforms
+
+    open_tag ToolFiles
+    case "$target" in
+        x86*) $uses_asm && tag ToolFile RelativePath="$self_dirname/../x86-msvs/yasm.rules"
+        ;;
+    esac
+    close_tag ToolFiles
+
+    open_tag Configurations
+    for plat in "${platforms[@]}"; do
+        plat_no_ws=`echo $plat | sed 's/[^A-Za-z0-9_]/_/g'`
+        open_tag Configuration \
+            Name="Debug|$plat" \
+            OutputDirectory="\$(SolutionDir)$plat_no_ws/\$(ConfigurationName)" \
+            IntermediateDirectory="$plat_no_ws/\$(ConfigurationName)/${name}" \
+            ConfigurationType="$vs_ConfigurationType" \
+            CharacterSet="1" \
+
+        case "$target" in
+            x86*)
+                case "$name" in
+                    obj_int_extract)
+                        tag Tool \
+                            Name="VCCLCompilerTool" \
+                            Optimization="0" \
+                            AdditionalIncludeDirectories="$incs" \
+                            PreprocessorDefinitions="WIN32;DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" \
+                            RuntimeLibrary="$debug_runtime" \
+                            WarningLevel="3" \
+                            Detect64BitPortabilityProblems="true" \
+                            DebugInformationFormat="1" \
+                    ;;
+                    vpx)
+                        tag Tool \
+                            Name="VCPreBuildEventTool" \
+                            CommandLine="call obj_int_extract.bat $src_path_bare" \
+
+                        tag Tool \
+                            Name="VCCLCompilerTool" \
+                            Optimization="0" \
+                            AdditionalIncludeDirectories="$incs" \
+                            PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
+                            RuntimeLibrary="$debug_runtime" \
+                            UsePrecompiledHeader="0" \
+                            WarningLevel="3" \
+                            DebugInformationFormat="1" \
+                            Detect64BitPortabilityProblems="true" \
+
+                        $uses_asm && tag Tool Name="YASM"  IncludePaths="$incs" Debug="true"
+                    ;;
+                    *)
+                        tag Tool \
+                            Name="VCCLCompilerTool" \
+                            Optimization="0" \
+                            AdditionalIncludeDirectories="$incs" \
+                            PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
+                            RuntimeLibrary="$debug_runtime" \
+                            UsePrecompiledHeader="0" \
+                            WarningLevel="3" \
+                            DebugInformationFormat="1" \
+                            Detect64BitPortabilityProblems="true" \
+
+                        $uses_asm && tag Tool Name="YASM"  IncludePaths="$incs" Debug="true"
+                    ;;
+                esac
+            ;;
+        esac
+
+        case "$proj_kind" in
+            exe)
+                case "$target" in
+                    x86*)
+                        case "$name" in
+                            obj_int_extract)
+                                tag Tool \
+                                    Name="VCLinkerTool" \
+                                    OutputFile="${name}.exe" \
+                                    GenerateDebugInformation="true" \
+                            ;;
+                            *)
+                                tag Tool \
+                                    Name="VCLinkerTool" \
+                                    AdditionalDependencies="$debug_libs \$(NoInherit)" \
+                                    AdditionalLibraryDirectories="$libdirs" \
+                                    GenerateDebugInformation="true" \
+                                    ProgramDatabaseFile="\$(OutDir)/${name}.pdb" \
+                            ;;
+                        esac
+                    ;;
+                 esac
+            ;;
+            lib)
+                case "$target" in
+                    x86*)
+                        tag Tool \
+                            Name="VCLibrarianTool" \
+                            OutputFile="\$(OutDir)/${name}${lib_sfx}d.lib" \
+
+                    ;;
+                esac
+            ;;
+            dll)
+                tag Tool \
+                    Name="VCLinkerTool" \
+                    AdditionalDependencies="\$(NoInherit)" \
+                    LinkIncremental="2" \
+                    GenerateDebugInformation="true" \
+                    AssemblyDebug="1" \
+                    TargetMachine="1" \
+                    $link_opts \
+
+            ;;
+        esac
+
+        close_tag Configuration
+
+        open_tag Configuration \
+            Name="Release|$plat" \
+            OutputDirectory="\$(SolutionDir)$plat_no_ws/\$(ConfigurationName)" \
+            IntermediateDirectory="$plat_no_ws/\$(ConfigurationName)/${name}" \
+            ConfigurationType="$vs_ConfigurationType" \
+            CharacterSet="1" \
+            WholeProgramOptimization="0" \
+
+        case "$target" in
+            x86*)
+                case "$name" in
+                    obj_int_extract)
+                        tag Tool \
+                            Name="VCCLCompilerTool" \
+                            Optimization="2" \
+                            FavorSizeorSpeed="1" \
+                            AdditionalIncludeDirectories="$incs" \
+                            PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" \
+                            RuntimeLibrary="$release_runtime" \
+                            UsePrecompiledHeader="0" \
+                            WarningLevel="3" \
+                            Detect64BitPortabilityProblems="true" \
+                            DebugInformationFormat="0" \
+                    ;;
+                    vpx)
+                        tag Tool \
+                            Name="VCPreBuildEventTool" \
+                            CommandLine="call obj_int_extract.bat $src_path_bare" \
+
+                        tag Tool \
+                            Name="VCCLCompilerTool" \
+                            Optimization="2" \
+                            FavorSizeorSpeed="1" \
+                            AdditionalIncludeDirectories="$incs" \
+                            PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
+                            RuntimeLibrary="$release_runtime" \
+                            UsePrecompiledHeader="0" \
+                            WarningLevel="3" \
+                            DebugInformationFormat="0" \
+                            Detect64BitPortabilityProblems="true" \
+
+                        $uses_asm && tag Tool Name="YASM"  IncludePaths="$incs"
+                    ;;
+                    *)
+                        tag Tool \
+                            Name="VCCLCompilerTool" \
+                            AdditionalIncludeDirectories="$incs" \
+                            Optimization="2" \
+                            FavorSizeorSpeed="1" \
+                            PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
+                            RuntimeLibrary="$release_runtime" \
+                            UsePrecompiledHeader="0" \
+                            WarningLevel="3" \
+                            DebugInformationFormat="0" \
+                            Detect64BitPortabilityProblems="true" \
+
+                        $uses_asm && tag Tool Name="YASM"  IncludePaths="$incs"
+                    ;;
+                esac
+            ;;
+        esac
+
+        case "$proj_kind" in
+            exe)
+                case "$target" in
+                    x86*)
+                        case "$name" in
+                            obj_int_extract)
+                                tag Tool \
+                                    Name="VCLinkerTool" \
+                                    OutputFile="${name}.exe" \
+                                    GenerateDebugInformation="true" \
+                            ;;
+                            *)
+                                tag Tool \
+                                    Name="VCLinkerTool" \
+                                    AdditionalDependencies="$libs \$(NoInherit)" \
+                                    AdditionalLibraryDirectories="$libdirs" \
+
+                            ;;
+                        esac
+                    ;;
+                 esac
+            ;;
+            lib)
+                case "$target" in
+                    x86*)
+                        tag Tool \
+                            Name="VCLibrarianTool" \
+                            OutputFile="\$(OutDir)/${name}${lib_sfx}.lib" \
+
+                    ;;
+                esac
+            ;;
+            dll) # note differences to debug version: LinkIncremental, AssemblyDebug
+                tag Tool \
+                    Name="VCLinkerTool" \
+                    AdditionalDependencies="\$(NoInherit)" \
+                    LinkIncremental="1" \
+                    GenerateDebugInformation="true" \
+                    TargetMachine="1" \
+                    $link_opts \
+
+            ;;
+        esac
+
+        close_tag Configuration
+    done
+    close_tag Configurations
+
+    open_tag Files
+    generate_filter srcs   "Source Files"   "c;cc;def;odl;idl;hpj;bat;asm;asmx"
+    generate_filter hdrs   "Header Files"   "h;hm;inl;inc;xsd"
+    generate_filter resrcs "Resource Files" "rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+    generate_filter resrcs "Build Files"    "mk"
+    close_tag Files
+
+    tag       Globals
+    close_tag VisualStudioProject
+
+    # This must be done from within the {} subshell
+    echo "Ignored files list (${#file_list[@]} items) is:" >&2
+    for f in "${file_list[@]}"; do
+        echo "    $f" >&2
+    done
+}
+
+generate_vcproj |
+    sed  -e '/"/s;\([^ "]\)/;\1\\;g' > ${outfile}
+
+exit
+<!--
+TODO: Add any files not captured by filters.
+                <File
+                        RelativePath=".\ReadMe.txt"
+                        >
+                </File>
+-->
diff --git a/build/make/gen_msvs_sln.sh b/build/make/gen_msvs_sln.sh
new file mode 100755 (executable)
index 0000000..240678b
--- /dev/null
@@ -0,0 +1,273 @@
+#!/bin/bash
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+
+self=$0
+self_basename=${self##*/}
+EOL=$'\n'
+EOLDOS=$'\r'
+
+show_help() {
+    cat <<EOF
+Usage: ${self_basename} [options] file1 [file2 ...]
+
+This script generates a Visual Studio 2005 solution file from a list of project
+files.
+
+Options:
+    --help                      Print this message
+    --out=outfile               Redirect output to a file
+    --ver=version               Version (7,8,9) of visual studio to generate for
+    --target=isa-os-cc          Target specifier
+EOF
+    exit 1
+}
+
+die() {
+    echo "${self_basename}: $@" >&2
+    [ -f "${outfile}" ] && rm -f ${outfile}{,.mk}
+    exit 1
+}
+
+die_unknown(){
+    echo "Unknown option \"$1\"." >&2
+    echo "See ${self_basename} --help for available options." >&2
+    [ -f "${outfile}" ] && rm -f ${outfile}{,.mk}
+    exit 1
+}
+
+indent1=$'\t'
+indent=""
+indent_push() {
+    indent="${indent}${indent1}"
+}
+indent_pop() {
+    indent="${indent%${indent1}}"
+}
+
+parse_project() {
+    local file=$1
+    local name=`grep Name "$file" | awk 'BEGIN {FS="\""}{if (NR==1) print $2}'`
+    local guid=`grep ProjectGUID "$file" | awk 'BEGIN {FS="\""}{if (NR==1) print $2}'`
+
+    # save the project GUID to a varaible, normalizing to the basename of the
+    # vcproj file without the extension
+    local var
+    var=${file##*/}
+    var=${var%%.vcproj}
+    eval "${var}_file=\"$1\""
+    eval "${var}_name=$name"
+    eval "${var}_guid=$guid"
+
+    # assume that all projects have the same list of possible configurations,
+    # so overwriting old config_lists is not a problem
+    config_list=`grep -A1 '<Configuration' $file |
+        grep Name | cut -d\" -f2`
+    proj_list="${proj_list} ${var}"
+}
+
+process_project() {
+    eval "local file=\${$1_file}"
+    eval "local name=\${$1_name}"
+    eval "local guid=\${$1_guid}"
+
+    # save the project GUID to a varaible, normalizing to the basename of the
+    # vcproj file without the extension
+    local var
+    var=${file##*/}
+    var=${var%%.vcproj}
+    eval "${var}_guid=$guid"
+
+    echo "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"$name\", \"$file\", \"$guid\""
+    indent_push
+
+    eval "local deps=\"\${${var}_deps}\""
+    if [ -n "$deps" ]; then
+        echo "${indent}ProjectSection(ProjectDependencies) = postProject"
+        indent_push
+
+        for dep in $deps; do
+            eval "local dep_guid=\${${dep}_guid}"
+            [ -z "${dep_guid}" ] && die "Unknown GUID for $dep (dependency of $var)"
+            echo "${indent}$dep_guid = $dep_guid"
+        done
+
+        indent_pop
+        echo "${indent}EndProjectSection"
+
+    fi
+
+    indent_pop
+    echo "EndProject"
+}
+
+process_global() {
+    echo "Global"
+    indent_push
+
+    #
+    # Solution Configuration Platforms
+    #
+    echo "${indent}GlobalSection(SolutionConfigurationPlatforms) = preSolution"
+    indent_push
+    IFS_bak=${IFS}
+    IFS=$'\r'$'\n'
+    for config in ${config_list}; do
+        echo "${indent}$config = $config"
+    done
+    IFS=${IFS_bak}
+    indent_pop
+    echo "${indent}EndGlobalSection"
+
+    #
+    # Project Configuration Platforms
+    #
+    echo "${indent}GlobalSection(ProjectConfigurationPlatforms) = postSolution"
+    indent_push
+    for proj in ${proj_list}; do
+        eval "local proj_guid=\${${proj}_guid}"
+        IFS=$'\r'$'\n'
+        for config in ${config_list}; do
+            echo "${indent}${proj_guid}.${config}.ActiveCfg = ${config}"
+            echo "${indent}${proj_guid}.${config}.Build.0 = ${config}"
+
+        done
+        IFS=${IFS_bak}
+    done
+    indent_pop
+    echo "${indent}EndGlobalSection"
+
+    #
+    # Solution Properties
+    #
+    echo "${indent}GlobalSection(SolutionProperties) = preSolution"
+    indent_push
+    echo "${indent}HideSolutionNode = FALSE"
+    indent_pop
+    echo "${indent}EndGlobalSection"
+
+    indent_pop
+    echo "EndGlobal"
+}
+
+process_makefile() {
+    IFS_bak=${IFS}
+    IFS=$'\r'$'\n'
+    local TAB=$'\t'
+    cat <<EOF
+found_devenv := \$(shell which devenv.com >/dev/null 2>&1 && echo yes)
+.nodevenv.once:
+${TAB}@echo "  * devenv.com not found in path."
+${TAB}@echo "  * "
+${TAB}@echo "  * You will have to build all configurations manually using the"
+${TAB}@echo "  * Visual Studio IDE. To allow make to build them automatically,"
+${TAB}@echo "  * add the Common7/IDE directory of your Visual Studio"
+${TAB}@echo "  * installation to your path, eg:"
+${TAB}@echo "  *   C:\Program Files\Microsoft Visual Studio 8\Common7\IDE"
+${TAB}@echo "  * "
+${TAB}@touch \$@
+CLEAN-OBJS += \$(if \$(found_devenv),,.nodevenv.once)
+
+EOF
+
+    for sln_config in ${config_list}; do
+        local config=${sln_config%%|*}
+        local platform=${sln_config##*|}
+        local nows_sln_config=`echo $sln_config | sed -e 's/[^a-zA-Z0-9]/_/g'`
+        cat <<EOF
+BUILD_TARGETS += \$(if \$(NO_LAUNCH_DEVENV),,$nows_sln_config)
+clean::
+${TAB}rm -rf "$platform"/"$config"
+.PHONY: $nows_sln_config
+ifneq (\$(found_devenv),)
+  ifeq (\$(CONFIG_VS_VERSION),7)
+$nows_sln_config: $outfile
+${TAB}devenv.com $outfile -build "$config"
+
+  else
+$nows_sln_config: $outfile
+${TAB}devenv.com $outfile -build "$sln_config"
+
+  endif
+else
+$nows_sln_config: $outfile .nodevenv.once
+${TAB}@echo "  * Skipping build of $sln_config (devenv.com not in path)."
+${TAB}@echo "  * "
+endif
+
+EOF
+    done
+    IFS=${IFS_bak}
+}
+
+# Process command line
+outfile=/dev/stdout
+for opt in "$@"; do
+    optval="${opt#*=}"
+    case "$opt" in
+    --help|-h) show_help
+    ;;
+    --out=*) outfile="${optval}"; mkoutfile="${optval}".mk
+    ;;
+    --dep=*) eval "${optval%%:*}_deps=\"\${${optval%%:*}_deps} ${optval##*:}\""
+    ;;
+    --ver=*) vs_ver="$optval"
+             case $optval in
+             [789])
+             ;;
+             *) die Unrecognized Visual Studio Version in $opt
+             ;;
+             esac
+    ;;
+    --ver=*) vs_ver="$optval"
+             case $optval in
+             7) sln_vers="8.00"
+                sln_vers_str="Visual Studio .NET 2003"
+             ;;
+             [89])
+             ;;
+             *) die "Unrecognized Visual Studio Version '$optval' in $opt"
+             ;;
+             esac
+    ;;
+    --target=*) target="${optval}"
+    ;;
+    -*) die_unknown $opt
+    ;;
+    *) file_list[${#file_list[@]}]="$opt"
+    esac
+done
+outfile=${outfile:-/dev/stdout}
+mkoutfile=${mkoutfile:-/dev/stdout}
+case "${vs_ver:-8}" in
+    7) sln_vers="8.00"
+       sln_vers_str="Visual Studio .NET 2003"
+    ;;
+    8) sln_vers="9.00"
+       sln_vers_str="Visual Studio 2005"
+    ;;
+    9) sln_vers="10.00"
+       sln_vers_str="Visual Studio 2008"
+    ;;
+esac
+
+for f in "${file_list[@]}"; do
+    parse_project $f
+done
+cat  >${outfile} <<EOF
+Microsoft Visual Studio Solution File, Format Version $sln_vers${EOLDOS}
+# $sln_vers_str${EOLDOS}
+EOF
+for proj in ${proj_list}; do
+    process_project $proj >>${outfile}
+done
+process_global >>${outfile}
+process_makefile >${mkoutfile}
diff --git a/build/make/obj_int_extract.c b/build/make/obj_int_extract.c
new file mode 100644 (file)
index 0000000..04e14a6
--- /dev/null
@@ -0,0 +1,914 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vpx_config.h"
+#include "vpx/vpx_integer.h"
+
+typedef enum
+{
+    OUTPUT_FMT_PLAIN,
+    OUTPUT_FMT_RVDS,
+    OUTPUT_FMT_GAS,
+} output_fmt_t;
+
+int log_msg(const char *fmt, ...)
+{
+    int res;
+    va_list ap;
+    va_start(ap, fmt);
+    res = vfprintf(stderr, fmt, ap);
+    va_end(ap);
+    return res;
+}
+
+#if defined(__GNUC__) && __GNUC__
+#if defined(__MACH__)
+
+#include <mach-o/loader.h>
+#include <mach-o/nlist.h>
+
+int parse_macho(uint8_t *base_buf, size_t sz)
+{
+    int i, j;
+    struct mach_header header;
+    uint8_t *buf = base_buf;
+    int base_data_section = 0;
+    int bits = 0;
+
+    /* We can read in mach_header for 32 and 64 bit architectures
+     * because it's identical to mach_header_64 except for the last
+     * element (uint32_t reserved), which we don't use. Then, when
+     * we know which architecture we're looking at, increment buf
+     * appropriately.
+     */
+    memcpy(&header, buf, sizeof(struct mach_header));
+
+    if (header.magic == MH_MAGIC)
+    {
+        if (header.cputype == CPU_TYPE_ARM
+            || header.cputype == CPU_TYPE_X86)
+        {
+            bits = 32;
+            buf += sizeof(struct mach_header);
+        }
+        else
+        {
+            log_msg("Bad cputype for object file. Currently only tested for CPU_TYPE_[ARM|X86].\n");
+            goto bail;
+        }
+    }
+    else if (header.magic == MH_MAGIC_64)
+    {
+        if (header.cputype == CPU_TYPE_X86_64)
+        {
+            bits = 64;
+            buf += sizeof(struct mach_header_64);
+        }
+        else
+        {
+            log_msg("Bad cputype for object file. Currently only tested for CPU_TYPE_X86_64.\n");
+            goto bail;
+        }
+    }
+    else
+    {
+        log_msg("Bad magic number for object file. 0x%x or 0x%x expected, 0x%x found.\n",
+                MH_MAGIC, MH_MAGIC_64, header.magic);
+        goto bail;
+    }
+
+    if (header.filetype != MH_OBJECT)
+    {
+        log_msg("Bad filetype for object file. Currently only tested for MH_OBJECT.\n");
+        goto bail;
+    }
+
+    for (i = 0; i < header.ncmds; i++)
+    {
+        struct load_command lc;
+
+        memcpy(&lc, buf, sizeof(struct load_command));
+
+        if (lc.cmd == LC_SEGMENT)
+        {
+            uint8_t *seg_buf = buf;
+            struct section s;
+            struct segment_command seg_c;
+
+            memcpy(&seg_c, seg_buf, sizeof(struct segment_command));
+            seg_buf += sizeof(struct segment_command);
+
+            /* Although each section is given it's own offset, nlist.n_value
+             * references the offset of the first section. This isn't
+             * apparent without debug information because the offset of the
+             * data section is the same as the first section. However, with
+             * debug sections mixed in, the offset of the debug section
+             * increases but n_value still references the first section.
+             */
+            if (seg_c.nsects < 1)
+            {
+                log_msg("Not enough sections\n");
+                goto bail;
+            }
+
+            memcpy(&s, seg_buf, sizeof(struct section));
+            base_data_section = s.offset;
+        }
+        else if (lc.cmd == LC_SEGMENT_64)
+        {
+            uint8_t *seg_buf = buf;
+            struct section_64 s;
+            struct segment_command_64 seg_c;
+
+            memcpy(&seg_c, seg_buf, sizeof(struct segment_command_64));
+            seg_buf += sizeof(struct segment_command_64);
+
+            /* Explanation in LG_SEGMENT */
+            if (seg_c.nsects < 1)
+            {
+                log_msg("Not enough sections\n");
+                goto bail;
+            }
+
+            memcpy(&s, seg_buf, sizeof(struct section_64));
+            base_data_section = s.offset;
+        }
+        else if (lc.cmd == LC_SYMTAB)
+        {
+            if (base_data_section != 0)
+            {
+                struct symtab_command sc;
+                uint8_t *sym_buf = base_buf;
+                uint8_t *str_buf = base_buf;
+
+                memcpy(&sc, buf, sizeof(struct symtab_command));
+
+                if (sc.cmdsize != sizeof(struct symtab_command))
+                {
+                    log_msg("Can't find symbol table!\n");
+                    goto bail;
+                }
+
+                sym_buf += sc.symoff;
+                str_buf += sc.stroff;
+
+                for (j = 0; j < sc.nsyms; j++)
+                {
+                    /* Location of string is cacluated each time from the
+                     * start of the string buffer.  On darwin the symbols
+                     * are prefixed by "_", so we bump the pointer by 1.
+                     * The target value is defined as an int in asm_*_offsets.c,
+                     * which is 4 bytes on all targets we currently use.
+                     */
+                    if (bits == 32)
+                    {
+                        struct nlist nl;
+                        int val;
+
+                        memcpy(&nl, sym_buf, sizeof(struct nlist));
+                        sym_buf += sizeof(struct nlist);
+
+                        memcpy(&val, base_buf + base_data_section + nl.n_value,
+                               sizeof(val));
+                        printf("%-40s EQU %5d\n",
+                               str_buf + nl.n_un.n_strx + 1, val);
+                    }
+                    else /* if (bits == 64) */
+                    {
+                        struct nlist_64 nl;
+                        int val;
+
+                        memcpy(&nl, sym_buf, sizeof(struct nlist_64));
+                        sym_buf += sizeof(struct nlist_64);
+
+                        memcpy(&val, base_buf + base_data_section + nl.n_value,
+                               sizeof(val));
+                        printf("%-40s EQU %5d\n",
+                               str_buf + nl.n_un.n_strx + 1, val);
+                    }
+                }
+            }
+        }
+
+        buf += lc.cmdsize;
+    }
+
+    return 0;
+bail:
+    return 1;
+
+}
+
+#elif defined(__ELF__)
+#include "elf.h"
+
+#define COPY_STRUCT(dst, buf, ofst, sz) do {\
+        if(ofst + sizeof((*(dst))) > sz) goto bail;\
+        memcpy(dst, buf+ofst, sizeof((*(dst))));\
+    } while(0)
+
+#define ENDIAN_ASSIGN(val, memb) do {\
+        if(!elf->le_data) {log_msg("Big Endian data not supported yet!\n");goto bail;}\
+        (val) = (memb);\
+    } while(0)
+
+#define ENDIAN_ASSIGN_IN_PLACE(memb) do {\
+        ENDIAN_ASSIGN(memb, memb);\
+    } while(0)
+
+typedef struct
+{
+    uint8_t      *buf; /* Buffer containing ELF data */
+    size_t        sz;  /* Buffer size */
+    int           le_data; /* Data is little-endian */
+    unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
+    int           bits; /* 32 or 64 */
+    Elf32_Ehdr    hdr32;
+    Elf64_Ehdr    hdr64;
+} elf_obj_t;
+
+int parse_elf_header(elf_obj_t *elf)
+{
+    int res;
+    /* Verify ELF Magic numbers */
+    COPY_STRUCT(&elf->e_ident, elf->buf, 0, elf->sz);
+    res = elf->e_ident[EI_MAG0] == ELFMAG0;
+    res &= elf->e_ident[EI_MAG1] == ELFMAG1;
+    res &= elf->e_ident[EI_MAG2] == ELFMAG2;
+    res &= elf->e_ident[EI_MAG3] == ELFMAG3;
+    res &= elf->e_ident[EI_CLASS] == ELFCLASS32
+        || elf->e_ident[EI_CLASS] == ELFCLASS64;
+    res &= elf->e_ident[EI_DATA] == ELFDATA2LSB;
+
+    if (!res) goto bail;
+
+    elf->le_data = elf->e_ident[EI_DATA] == ELFDATA2LSB;
+
+    /* Read in relevant values */
+    if (elf->e_ident[EI_CLASS] == ELFCLASS32)
+    {
+        elf->bits = 32;
+        COPY_STRUCT(&elf->hdr32, elf->buf, 0, elf->sz);
+
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_type);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_machine);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_version);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_entry);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phoff);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shoff);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_flags);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_ehsize);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phentsize);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phnum);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shentsize);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shnum);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shstrndx);
+    }
+    else /* if (elf->e_ident[EI_CLASS] == ELFCLASS64) */
+    {
+        elf->bits = 64;
+        COPY_STRUCT(&elf->hdr64, elf->buf, 0, elf->sz);
+
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_type);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_machine);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_version);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_entry);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phoff);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shoff);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_flags);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_ehsize);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phentsize);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phnum);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shentsize);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shnum);
+        ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shstrndx);
+    }
+
+    return 0;
+bail:
+    log_msg("Failed to parse ELF file header");
+    return 1;
+}
+
+int parse_elf_section(elf_obj_t *elf, int idx, Elf32_Shdr *hdr32, Elf64_Shdr *hdr64)
+{
+    if (hdr32)
+    {
+        if (idx >= elf->hdr32.e_shnum)
+            goto bail;
+
+        COPY_STRUCT(hdr32, elf->buf, elf->hdr32.e_shoff + idx * elf->hdr32.e_shentsize,
+                    elf->sz);
+        ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_name);
+        ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_type);
+        ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_flags);
+        ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_addr);
+        ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_offset);
+        ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_size);
+        ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_link);
+        ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_info);
+        ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_addralign);
+        ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_entsize);
+    }
+    else /* if (hdr64) */
+    {
+        if (idx >= elf->hdr64.e_shnum)
+            goto bail;
+
+        COPY_STRUCT(hdr64, elf->buf, elf->hdr64.e_shoff + idx * elf->hdr64.e_shentsize,
+                    elf->sz);
+        ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_name);
+        ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_type);
+        ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_flags);
+        ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_addr);
+        ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_offset);
+        ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_size);
+        ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_link);
+        ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_info);
+        ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_addralign);
+        ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_entsize);
+    }
+
+    return 0;
+bail:
+    return 1;
+}
+
+char *parse_elf_string_table(elf_obj_t *elf, int s_idx, int idx)
+{
+    if (elf->bits == 32)
+    {
+        Elf32_Shdr shdr;
+
+        if (parse_elf_section(elf, s_idx, &shdr, NULL))
+        {
+            log_msg("Failed to parse ELF string table: section %d, index %d\n",
+                    s_idx, idx);
+            return "";
+        }
+
+        return (char *)(elf->buf + shdr.sh_offset + idx);
+    }
+    else /* if (elf->bits == 64) */
+    {
+        Elf64_Shdr shdr;
+
+        if (parse_elf_section(elf, s_idx, NULL, &shdr))
+        {
+            log_msg("Failed to parse ELF string table: section %d, index %d\n",
+                    s_idx, idx);
+            return "";
+        }
+
+        return (char *)(elf->buf + shdr.sh_offset + idx);
+    }
+}
+
+int parse_elf_symbol(elf_obj_t *elf, unsigned int ofst, Elf32_Sym *sym32, Elf64_Sym *sym64)
+{
+    if (sym32)
+    {
+        COPY_STRUCT(sym32, elf->buf, ofst, elf->sz);
+        ENDIAN_ASSIGN_IN_PLACE(sym32->st_name);
+        ENDIAN_ASSIGN_IN_PLACE(sym32->st_value);
+        ENDIAN_ASSIGN_IN_PLACE(sym32->st_size);
+        ENDIAN_ASSIGN_IN_PLACE(sym32->st_info);
+        ENDIAN_ASSIGN_IN_PLACE(sym32->st_other);
+        ENDIAN_ASSIGN_IN_PLACE(sym32->st_shndx);
+    }
+    else /* if (sym64) */
+    {
+        COPY_STRUCT(sym64, elf->buf, ofst, elf->sz);
+        ENDIAN_ASSIGN_IN_PLACE(sym64->st_name);
+        ENDIAN_ASSIGN_IN_PLACE(sym64->st_value);
+        ENDIAN_ASSIGN_IN_PLACE(sym64->st_size);
+        ENDIAN_ASSIGN_IN_PLACE(sym64->st_info);
+        ENDIAN_ASSIGN_IN_PLACE(sym64->st_other);
+        ENDIAN_ASSIGN_IN_PLACE(sym64->st_shndx);
+    }
+    return 0;
+bail:
+    return 1;
+}
+
+int parse_elf(uint8_t *buf, size_t sz, output_fmt_t mode)
+{
+    elf_obj_t    elf;
+    unsigned int ofst;
+    int          i;
+    Elf32_Off    strtab_off32;
+    Elf64_Off    strtab_off64; /* save String Table offset for later use */
+
+    memset(&elf, 0, sizeof(elf));
+    elf.buf = buf;
+    elf.sz = sz;
+
+    /* Parse Header */
+    if (parse_elf_header(&elf))
+      goto bail;
+
+    if (elf.bits == 32)
+    {
+        Elf32_Shdr shdr;
+        for (i = 0; i < elf.hdr32.e_shnum; i++)
+        {
+            parse_elf_section(&elf, i, &shdr, NULL);
+
+            if (shdr.sh_type == SHT_STRTAB)
+            {
+                char strtsb_name[128];
+
+                strcpy(strtsb_name, (char *)(elf.buf + shdr.sh_offset + shdr.sh_name));
+
+                if (!(strcmp(strtsb_name, ".shstrtab")))
+                {
+                    /* log_msg("found section: %s\n", strtsb_name); */
+                    strtab_off32 = shdr.sh_offset;
+                    break;
+                }
+            }
+        }
+    }
+    else /* if (elf.bits == 64) */
+    {
+        Elf64_Shdr shdr;
+        for (i = 0; i < elf.hdr64.e_shnum; i++)
+        {
+            parse_elf_section(&elf, i, NULL, &shdr);
+
+            if (shdr.sh_type == SHT_STRTAB)
+            {
+                char strtsb_name[128];
+
+                strcpy(strtsb_name, (char *)(elf.buf + shdr.sh_offset + shdr.sh_name));
+
+                if (!(strcmp(strtsb_name, ".shstrtab")))
+                {
+                    /* log_msg("found section: %s\n", strtsb_name); */
+                    strtab_off64 = shdr.sh_offset;
+                    break;
+                }
+            }
+        }
+    }
+
+    /* Parse all Symbol Tables */
+    if (elf.bits == 32)
+    {
+        Elf32_Shdr shdr;
+        for (i = 0; i < elf.hdr32.e_shnum; i++)
+        {
+            parse_elf_section(&elf, i, &shdr, NULL);
+
+            if (shdr.sh_type == SHT_SYMTAB)
+            {
+                for (ofst = shdr.sh_offset;
+                     ofst < shdr.sh_offset + shdr.sh_size;
+                     ofst += shdr.sh_entsize)
+                {
+                    Elf32_Sym sym;
+
+                    parse_elf_symbol(&elf, ofst, &sym, NULL);
+
+                    /* For all OBJECTS (data objects), extract the value from the
+                     * proper data segment.
+                     */
+                    /* if (ELF32_ST_TYPE(sym.st_info) == STT_OBJECT && sym.st_name)
+                        log_msg("found data object %s\n",
+                                parse_elf_string_table(&elf,
+                                                       shdr.sh_link,
+                                                       sym.st_name));
+                     */
+
+                    if (ELF32_ST_TYPE(sym.st_info) == STT_OBJECT
+                        && sym.st_size == 4)
+                    {
+                        Elf32_Shdr dhdr;
+                        int val = 0;
+                        char section_name[128];
+
+                        parse_elf_section(&elf, sym.st_shndx, &dhdr, NULL);
+
+                        /* For explanition - refer to _MSC_VER version of code */
+                        strcpy(section_name, (char *)(elf.buf + strtab_off32 + dhdr.sh_name));
+                        /* log_msg("Section_name: %s, Section_type: %d\n", section_name, dhdr.sh_type); */
+
+                        if (strcmp(section_name, ".bss"))
+                        {
+                            if (sizeof(val) != sym.st_size)
+                            {
+                                /* The target value is declared as an int in
+                                 * asm_*_offsets.c, which is 4 bytes on all
+                                 * targets we currently use. Complain loudly if
+                                 * this is not true.
+                                 */
+                                log_msg("Symbol size is wrong\n");
+                                goto bail;
+                            }
+
+                            memcpy(&val,
+                                   elf.buf + dhdr.sh_offset + sym.st_value,
+                                   sym.st_size);
+                        }
+
+                        if (!elf.le_data)
+                        {
+                            log_msg("Big Endian data not supported yet!\n");
+                            goto bail;
+                        }
+
+                        switch (mode)
+                        {
+                            case OUTPUT_FMT_RVDS:
+                                printf("%-40s EQU %5d\n",
+                                       parse_elf_string_table(&elf,
+                                                              shdr.sh_link,
+                                                              sym.st_name),
+                                       val);
+                                break;
+                            case OUTPUT_FMT_GAS:
+                                printf(".equ %-40s, %5d\n",
+                                       parse_elf_string_table(&elf,
+                                                              shdr.sh_link,
+                                                              sym.st_name),
+                                       val);
+                                break;
+                            default:
+                                printf("%s = %d\n",
+                                       parse_elf_string_table(&elf,
+                                                              shdr.sh_link,
+                                                              sym.st_name),
+                                       val);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    else /* if (elf.bits == 64) */
+    {
+        Elf64_Shdr shdr;
+        for (i = 0; i < elf.hdr64.e_shnum; i++)
+        {
+            parse_elf_section(&elf, i, NULL, &shdr);
+
+            if (shdr.sh_type == SHT_SYMTAB)
+            {
+                for (ofst = shdr.sh_offset;
+                     ofst < shdr.sh_offset + shdr.sh_size;
+                     ofst += shdr.sh_entsize)
+                {
+                    Elf64_Sym sym;
+
+                    parse_elf_symbol(&elf, ofst, NULL, &sym);
+
+                    /* For all OBJECTS (data objects), extract the value from the
+                     * proper data segment.
+                     */
+                    /* if (ELF64_ST_TYPE(sym.st_info) == STT_OBJECT && sym.st_name)
+                        log_msg("found data object %s\n",
+                                parse_elf_string_table(&elf,
+                                                       shdr.sh_link,
+                                                       sym.st_name));
+                     */
+
+                    if (ELF64_ST_TYPE(sym.st_info) == STT_OBJECT
+                        && sym.st_size == 4)
+                    {
+                        Elf64_Shdr dhdr;
+                        int val = 0;
+                        char section_name[128];
+
+                        parse_elf_section(&elf, sym.st_shndx, NULL, &dhdr);
+
+                        /* For explanition - refer to _MSC_VER version of code */
+                        strcpy(section_name, (char *)(elf.buf + strtab_off64 + dhdr.sh_name));
+                        /* log_msg("Section_name: %s, Section_type: %d\n", section_name, dhdr.sh_type); */
+
+                        if ((strcmp(section_name, ".bss")))
+                        {
+                            if (sizeof(val) != sym.st_size)
+                            {
+                                /* The target value is declared as an int in
+                                 * asm_*_offsets.c, which is 4 bytes on all
+                                 * targets we currently use. Complain loudly if
+                                 * this is not true.
+                                 */
+                                log_msg("Symbol size is wrong\n");
+                                goto bail;
+                            }
+
+                            memcpy(&val,
+                                   elf.buf + dhdr.sh_offset + sym.st_value,
+                                   sym.st_size);
+                        }
+
+                        if (!elf.le_data)
+                        {
+                            log_msg("Big Endian data not supported yet!\n");
+                            goto bail;
+                        }
+
+                        switch (mode)
+                        {
+                            case OUTPUT_FMT_RVDS:
+                                printf("%-40s EQU %5d\n",
+                                       parse_elf_string_table(&elf,
+                                                              shdr.sh_link,
+                                                              sym.st_name),
+                                       val);
+                                break;
+                            case OUTPUT_FMT_GAS:
+                                printf(".equ %-40s, %5d\n",
+                                       parse_elf_string_table(&elf,
+                                                              shdr.sh_link,
+                                                              sym.st_name),
+                                       val);
+                                break;
+                            default:
+                                printf("%s = %d\n",
+                                       parse_elf_string_table(&elf,
+                                                              shdr.sh_link,
+                                                              sym.st_name),
+                                       val);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    if (mode == OUTPUT_FMT_RVDS)
+        printf("    END\n");
+
+    return 0;
+bail:
+    log_msg("Parse error: File does not appear to be valid ELF32 or ELF64\n");
+    return 1;
+}
+
+#endif
+#endif /* defined(__GNUC__) && __GNUC__ */
+
+
+#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__)
+/*  See "Microsoft Portable Executable and Common Object File Format Specification"
+    for reference.
+*/
+#define get_le32(x) ((*(x)) | (*(x+1)) << 8 |(*(x+2)) << 16 | (*(x+3)) << 24 )
+#define get_le16(x) ((*(x)) | (*(x+1)) << 8)
+
+int parse_coff(uint8_t *buf, size_t sz)
+{
+    unsigned int nsections, symtab_ptr, symtab_sz, strtab_ptr;
+    unsigned int sectionrawdata_ptr;
+    unsigned int i;
+    uint8_t *ptr;
+    uint32_t symoffset;
+
+    char **sectionlist;  //this array holds all section names in their correct order.
+    //it is used to check if the symbol is in .bss or .data section.
+
+    nsections = get_le16(buf + 2);
+    symtab_ptr = get_le32(buf + 8);
+    symtab_sz = get_le32(buf + 12);
+    strtab_ptr = symtab_ptr + symtab_sz * 18;
+
+    if (nsections > 96)
+    {
+        log_msg("Too many sections\n");
+        return 1;
+    }
+
+    sectionlist = malloc(nsections * sizeof(sectionlist));
+
+    if (sectionlist == NULL)
+    {
+        log_msg("Allocating first level of section list failed\n");
+        return 1;
+    }
+
+    //log_msg("COFF: Found %u symbols in %u sections.\n", symtab_sz, nsections);
+
+    /*
+    The size of optional header is always zero for an obj file. So, the section header
+    follows the file header immediately.
+    */
+
+    ptr = buf + 20;     //section header
+
+    for (i = 0; i < nsections; i++)
+    {
+        char sectionname[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+        strncpy(sectionname, ptr, 8);
+        //log_msg("COFF: Parsing section %s\n",sectionname);
+
+        sectionlist[i] = malloc(strlen(sectionname) + 1);
+
+        if (sectionlist[i] == NULL)
+        {
+            log_msg("Allocating storage for %s failed\n", sectionname);
+            goto bail;
+        }
+        strcpy(sectionlist[i], sectionname);
+
+        if (!strcmp(sectionname, ".data")) sectionrawdata_ptr = get_le32(ptr + 20);
+
+        ptr += 40;
+    }
+
+    //log_msg("COFF: Symbol table at offset %u\n", symtab_ptr);
+    //log_msg("COFF: raw data pointer ofset for section .data is %u\n", sectionrawdata_ptr);
+
+    /*  The compiler puts the data with non-zero offset in .data section, but puts the data with
+        zero offset in .bss section. So, if the data in in .bss section, set offset=0.
+        Note from Wiki: In an object module compiled from C, the bss section contains
+        the local variables (but not functions) that were declared with the static keyword,
+        except for those with non-zero initial values. (In C, static variables are initialized
+        to zero by default.) It also contains the non-local (both extern and static) variables
+        that are also initialized to zero (either explicitly or by default).
+        */
+    //move to symbol table
+    /* COFF symbol table:
+        offset      field
+        0           Name(*)
+        8           Value
+        12          SectionNumber
+        14          Type
+        16          StorageClass
+        17          NumberOfAuxSymbols
+        */
+    ptr = buf + symtab_ptr;
+
+    for (i = 0; i < symtab_sz; i++)
+    {
+        int16_t section = get_le16(ptr + 12); //section number
+
+        if (section > 0 && ptr[16] == 2)
+        {
+            //if(section > 0 && ptr[16] == 3 && get_le32(ptr+8)) {
+
+            if (get_le32(ptr))
+            {
+                char name[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+                strncpy(name, ptr, 8);
+                //log_msg("COFF: Parsing symbol %s\n",name);
+                /* The 64bit Windows compiler doesn't prefix with an _.
+                 * Check what's there, and bump if necessary
+                 */
+                if (name[0] == '_')
+                    printf("%-40s EQU ", name + 1);
+                else
+                    printf("%-40s EQU ", name);
+            }
+            else
+            {
+                //log_msg("COFF: Parsing symbol %s\n",
+                //        buf + strtab_ptr + get_le32(ptr+4));
+                if ((buf + strtab_ptr + get_le32(ptr + 4))[0] == '_')
+                    printf("%-40s EQU ",
+                           buf + strtab_ptr + get_le32(ptr + 4) + 1);
+                else
+                    printf("%-40s EQU ", buf + strtab_ptr + get_le32(ptr + 4));
+            }
+
+            if (!(strcmp(sectionlist[section-1], ".bss")))
+            {
+                symoffset = 0;
+            }
+            else
+            {
+                symoffset = get_le32(buf + sectionrawdata_ptr + get_le32(ptr + 8));
+            }
+
+            //log_msg("      Section: %d\n",section);
+            //log_msg("      Class:   %d\n",ptr[16]);
+            //log_msg("      Address: %u\n",get_le32(ptr+8));
+            //log_msg("      Offset: %u\n", symoffset);
+
+            printf("%5d\n", symoffset);
+        }
+
+        ptr += 18;
+    }
+
+    printf("    END\n");
+
+    for (i = 0; i < nsections; i++)
+    {
+        free(sectionlist[i]);
+    }
+
+    free(sectionlist);
+
+    return 0;
+bail:
+
+    for (i = 0; i < nsections; i++)
+    {
+        free(sectionlist[i]);
+    }
+
+    free(sectionlist);
+
+    return 1;
+}
+#endif /* defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__) */
+
+int main(int argc, char **argv)
+{
+    output_fmt_t mode = OUTPUT_FMT_PLAIN;
+    const char *f;
+    uint8_t *file_buf;
+    int res;
+    FILE *fp;
+    long int file_size;
+
+    if (argc < 2 || argc > 3)
+    {
+        fprintf(stderr, "Usage: %s [output format] <obj file>\n\n", argv[0]);
+        fprintf(stderr, "  <obj file>\tobject file to parse\n");
+        fprintf(stderr, "Output Formats:\n");
+        fprintf(stderr, "  gas  - compatible with GNU assembler\n");
+        fprintf(stderr, "  rvds - compatible with armasm\n");
+        goto bail;
+    }
+
+    f = argv[2];
+
+    if (!strcmp(argv[1], "rvds"))
+        mode = OUTPUT_FMT_RVDS;
+    else if (!strcmp(argv[1], "gas"))
+        mode = OUTPUT_FMT_GAS;
+    else
+        f = argv[1];
+
+    fp = fopen(f, "rb");
+
+    if (!fp)
+    {
+        perror("Unable to open file");
+        goto bail;
+    }
+
+    if (fseek(fp, 0, SEEK_END))
+    {
+        perror("stat");
+        goto bail;
+    }
+
+    file_size = ftell(fp);
+    file_buf = malloc(file_size);
+
+    if (!file_buf)
+    {
+        perror("malloc");
+        goto bail;
+    }
+
+    rewind(fp);
+
+    if (fread(file_buf, sizeof(char), file_size, fp) != file_size)
+    {
+        perror("read");
+        goto bail;
+    }
+
+    if (fclose(fp))
+    {
+        perror("close");
+        goto bail;
+    }
+
+#if defined(__GNUC__) && __GNUC__
+#if defined(__MACH__)
+    res = parse_macho(file_buf, file_size);
+#elif defined(__ELF__)
+    res = parse_elf(file_buf, file_size, mode);
+#endif
+#endif
+#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__)
+    res = parse_coff(file_buf, file_size);
+#endif
+
+    free(file_buf);
+
+    if (!res)
+        return EXIT_SUCCESS;
+
+bail:
+    return EXIT_FAILURE;
+}
diff --git a/build/make/rtcd.sh b/build/make/rtcd.sh
new file mode 100755 (executable)
index 0000000..1dffde5
--- /dev/null
@@ -0,0 +1,330 @@
+#!/bin/sh
+self=$0
+
+usage() {
+  cat <<EOF >&2
+Usage: $self [options] FILE
+
+Reads the Run Time CPU Detections definitions from FILE and generates a
+C header file on stdout.
+
+Options:
+  --arch=ARCH   Architecture to generate defs for (required)
+  --disable-EXT Disable support for EXT extensions
+  --require-EXT Require support for EXT extensions
+  --sym=SYMBOL  Unique symbol to use for RTCD initialization function
+  --config=FILE File with CONFIG_FOO=yes lines to parse
+EOF
+  exit 1
+}
+
+die() {
+  echo "$@" >&2
+  exit 1
+}
+
+die_argument_required() {
+  die "Option $opt requires argument"
+}
+
+for opt; do
+  optval="${opt#*=}"
+  case "$opt" in
+    --arch) die_argument_required;;
+    --arch=*) arch=${optval};;
+    --disable-*) eval "disable_${opt#--disable-}=true";;
+    --require-*) REQUIRES="${REQUIRES}${opt#--require-} ";;
+    --sym) die_argument_required;;
+    --sym=*) symbol=${optval};;
+    --config=*) config_file=${optval};;
+    -h|--help)
+      usage
+      ;;
+    -*)
+      die "Unrecognized option: ${opt%%=*}"
+      ;;
+    *)
+      defs_file="$defs_file $opt"
+      ;;
+  esac
+  shift
+done
+for f in $defs_file; do [ -f "$f" ] || usage; done
+[ -n "$arch" ] || usage
+
+# Import the configuration
+[ -f "$config_file" ] && eval $(grep CONFIG_ "$config_file")
+
+#
+# Routines for the RTCD DSL to call
+#
+prototype() {
+  local rtyp
+  case "$1" in
+    unsigned) rtyp="$1 "; shift;;
+  esac
+  rtyp="${rtyp}$1"
+  local fn="$2"
+  local args="$3"
+
+  eval "${2}_rtyp='$rtyp'"
+  eval "${2}_args='$3'"
+  ALL_FUNCS="$ALL_FUNCS $fn"
+  specialize $fn c
+}
+
+specialize() {
+  local fn="$1"
+  shift
+  for opt in "$@"; do
+    eval "${fn}_${opt}=${fn}_${opt}"
+  done
+}
+
+require() {
+  for fn in $ALL_FUNCS; do
+    for opt in "$@"; do
+      local ofn=$(eval "echo \$${fn}_${opt}")
+      [ -z "$ofn" ] && continue
+
+      # if we already have a default, then we can disable it, as we know
+      # we can do better.
+      local best=$(eval "echo \$${fn}_default")
+      local best_ofn=$(eval "echo \$${best}")
+      [ -n "$best" ] && [ "$best_ofn" != "$ofn" ] && eval "${best}_link=false"
+      eval "${fn}_default=${fn}_${opt}"
+      eval "${fn}_${opt}_link=true"
+    done
+  done
+}
+
+forward_decls() {
+  ALL_FORWARD_DECLS="$ALL_FORWARD_DECLS $1"
+}
+
+#
+# Include the user's directives
+#
+for f in $defs_file; do
+  . $f
+done
+
+#
+# Process the directives according to the command line
+#
+process_forward_decls() {
+  for fn in $ALL_FORWARD_DECLS; do
+    eval $fn
+  done
+}
+
+determine_indirection() {
+  [ "$CONFIG_RUNTIME_CPU_DETECT" = "yes" ] || require $ALL_ARCHS
+  for fn in $ALL_FUNCS; do
+    local n=""
+    local rtyp="$(eval "echo \$${fn}_rtyp")"
+    local args="$(eval "echo \"\$${fn}_args\"")"
+    local dfn="$(eval "echo \$${fn}_default")"
+    dfn=$(eval "echo \$${dfn}")
+    for opt in "$@"; do
+      local ofn=$(eval "echo \$${fn}_${opt}")
+      [ -z "$ofn" ] && continue
+      local link=$(eval "echo \$${fn}_${opt}_link")
+      [ "$link" = "false" ] && continue
+      n="${n}x"
+    done
+    if [ "$n" = "x" ]; then
+      eval "${fn}_indirect=false"
+    else
+      eval "${fn}_indirect=true"
+    fi
+  done
+}
+
+declare_function_pointers() {
+  for fn in $ALL_FUNCS; do
+    local rtyp="$(eval "echo \$${fn}_rtyp")"
+    local args="$(eval "echo \"\$${fn}_args\"")"
+    local dfn="$(eval "echo \$${fn}_default")"
+    dfn=$(eval "echo \$${dfn}")
+    for opt in "$@"; do
+      local ofn=$(eval "echo \$${fn}_${opt}")
+      [ -z "$ofn" ] && continue
+      echo "$rtyp ${ofn}($args);"
+    done
+    if [ "$(eval "echo \$${fn}_indirect")" = "false" ]; then
+      echo "#define ${fn} ${dfn}"
+    else
+      echo "RTCD_EXTERN $rtyp (*${fn})($args);"
+    fi
+    echo
+  done
+}
+
+set_function_pointers() {
+  for fn in $ALL_FUNCS; do
+    local n=""
+    local rtyp="$(eval "echo \$${fn}_rtyp")"
+    local args="$(eval "echo \"\$${fn}_args\"")"
+    local dfn="$(eval "echo \$${fn}_default")"
+    dfn=$(eval "echo \$${dfn}")
+    if $(eval "echo \$${fn}_indirect"); then
+      echo "    $fn = $dfn;"
+      for opt in "$@"; do
+        local ofn=$(eval "echo \$${fn}_${opt}")
+        [ -z "$ofn" ] && continue
+        [ "$ofn" = "$dfn" ] && continue;
+        local link=$(eval "echo \$${fn}_${opt}_link")
+        [ "$link" = "false" ] && continue
+        local cond="$(eval "echo \$have_${opt}")"
+        echo "    if (${cond}) $fn = $ofn;"
+      done
+    fi
+    echo
+  done
+}
+
+filter() {
+  local filtered
+  for opt in "$@"; do
+    [ -z $(eval "echo \$disable_${opt}") ] && filtered="$filtered $opt"
+  done
+  echo $filtered
+}
+
+#
+# Helper functions for generating the arch specific RTCD files
+#
+common_top() {
+  local outfile_basename=$(basename ${symbol:-rtcd.h})
+  local include_guard=$(echo $outfile_basename | tr '[a-z]' '[A-Z]' | tr -c '[A-Z]' _)
+  cat <<EOF
+#ifndef ${include_guard}
+#define ${include_guard}
+
+#ifdef RTCD_C
+#define RTCD_EXTERN
+#else
+#define RTCD_EXTERN extern
+#endif
+
+$(process_forward_decls)
+
+$(declare_function_pointers c $ALL_ARCHS)
+EOF
+}
+
+common_bottom() {
+  cat <<EOF
+#endif
+EOF
+}
+
+x86() {
+  determine_indirection c $ALL_ARCHS
+
+  # Assign the helper variable for each enabled extension
+  for opt in $ALL_ARCHS; do
+    local uc=$(echo $opt | tr '[a-z]' '[A-Z]')
+    eval "have_${opt}=\"flags & HAS_${uc}\""
+  done
+
+  cat <<EOF
+$(common_top)
+void ${symbol:-rtcd}(void);
+
+#ifdef RTCD_C
+#include "vpx_ports/x86.h"
+void ${symbol:-rtcd}(void)
+{
+    int flags = x86_simd_caps();
+
+    (void)flags;
+
+$(set_function_pointers c $ALL_ARCHS)
+}
+#endif
+$(common_bottom)
+EOF
+}
+
+arm() {
+  determine_indirection c $ALL_ARCHS
+
+  # Assign the helper variable for each enabled extension
+  for opt in $ALL_ARCHS; do
+    local uc=$(echo $opt | tr '[a-z]' '[A-Z]')
+    eval "have_${opt}=\"flags & HAS_${uc}\""
+  done
+
+  cat <<EOF
+$(common_top)
+#include "vpx_config.h"
+
+void ${symbol:-rtcd}(void);
+
+#ifdef RTCD_C
+#include "vpx_ports/arm.h"
+void ${symbol:-rtcd}(void)
+{
+    int flags = arm_cpu_caps();
+
+    (void)flags;
+
+$(set_function_pointers c $ALL_ARCHS)
+}
+#endif
+$(common_bottom)
+EOF
+}
+
+
+unoptimized() {
+  determine_indirection c
+  cat <<EOF
+$(common_top)
+#include "vpx_config.h"
+
+void ${symbol:-rtcd}(void);
+
+#ifdef RTCD_C
+void ${symbol:-rtcd}(void)
+{
+$(set_function_pointers c)
+}
+#endif
+$(common_bottom)
+EOF
+
+}
+#
+# Main Driver
+#
+require c
+case $arch in
+  x86)
+    ALL_ARCHS=$(filter mmx sse sse2 sse3 ssse3 sse4_1)
+    x86
+    ;;
+  x86_64)
+    ALL_ARCHS=$(filter mmx sse sse2 sse3 ssse3 sse4_1)
+    REQUIRES=${REQUIRES:-mmx sse sse2}
+    require $(filter $REQUIRES)
+    x86
+    ;;
+  armv5te)
+    ALL_ARCHS=$(filter edsp)
+    arm
+    ;;
+  armv6)
+    ALL_ARCHS=$(filter edsp media)
+    arm
+    ;;
+  armv7)
+    ALL_ARCHS=$(filter edsp media neon)
+    arm
+    ;;
+  *)
+    unoptimized
+    ;;
+esac
diff --git a/build/make/version.sh b/build/make/version.sh
new file mode 100755 (executable)
index 0000000..3efb956
--- /dev/null
@@ -0,0 +1,76 @@
+#!/bin/bash
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+
+
+for opt in "$@"; do
+    optval="${opt#*=}"
+    case "$opt" in
+    --bare) bare=true ;;
+    *) break ;;
+    esac
+    shift
+done
+source_path=${1:-.}
+out_file=${2}
+id=${3:-VERSION_STRING}
+
+git_version_id=""
+if [ -d ${source_path}/.git ]; then
+    # Source Path is a git working copy. Check for local modifications.
+    export GIT_DIR=${source_path}/.git
+    git_version_id=`git describe --match=v[0-9]* 2>/dev/null`
+fi
+
+changelog_version=""
+for p in "${source_path}" "${source_path}/.."; do
+    if [ -z "$git_version_id" -a -f "${p}/CHANGELOG" ]; then
+        changelog_version=`head -n1 "${p}/CHANGELOG" | awk '{print $2}'`
+        changelog_version="${changelog_version}"
+        break
+    fi
+done
+version_str="${changelog_version}${git_version_id}"
+bare_version=${version_str#v}
+major_version=${bare_version%%.*}
+bare_version=${bare_version#*.}
+minor_version=${bare_version%%.*}
+bare_version=${bare_version#*.}
+patch_version=${bare_version%%-*}
+bare_version=${bare_version#${patch_version}}
+extra_version=${bare_version##-}
+
+#since they'll be used as integers below make sure they are or force to 0
+for v in major_version minor_version patch_version; do
+    if eval echo \$$v |grep -E -q '[^[:digit:]]'; then
+        eval $v=0
+    fi
+done
+
+if [ ${bare} ]; then
+    echo "${changelog_version}${git_version_id}" > $$.tmp
+else
+    cat<<EOF>$$.tmp
+#define VERSION_MAJOR  $major_version
+#define VERSION_MINOR  $minor_version
+#define VERSION_PATCH  $patch_version
+#define VERSION_EXTRA  "$extra_version"
+#define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH))
+#define ${id}_NOSP "${version_str}"
+#define ${id}      " ${version_str}"
+EOF
+fi
+if [ -n "$out_file" ]; then
+diff $$.tmp ${out_file} >/dev/null 2>&1 || cat $$.tmp > ${out_file}
+else
+cat $$.tmp
+fi
+rm $$.tmp
diff --git a/build/x86-msvs/obj_int_extract.bat b/build/x86-msvs/obj_int_extract.bat
new file mode 100644 (file)
index 0000000..1bb8653
--- /dev/null
@@ -0,0 +1,15 @@
+REM   Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+REM
+REM   Use of this source code is governed by a BSD-style license
+REM   that can be found in the LICENSE file in the root of the source
+REM   tree. An additional intellectual property rights grant can be found
+REM   in the file PATENTS.  All contributing project authors may
+REM   be found in the AUTHORS file in the root of the source tree.
+echo on
+
+cl /I "./" /I "%1" /nologo /c "%1/vp8/common/asm_com_offsets.c"
+cl /I "./" /I "%1" /nologo /c "%1/vp8/decoder/asm_dec_offsets.c"
+cl /I "./" /I "%1" /nologo /c "%1/vp8/encoder/asm_enc_offsets.c"
+obj_int_extract.exe rvds "asm_com_offsets.obj" > "asm_com_offsets.asm"
+obj_int_extract.exe rvds "asm_dec_offsets.obj" > "asm_dec_offsets.asm"
+obj_int_extract.exe rvds "asm_enc_offsets.obj" > "asm_enc_offsets.asm"
diff --git a/build/x86-msvs/yasm.rules b/build/x86-msvs/yasm.rules
new file mode 100644 (file)
index 0000000..ee1fefb
--- /dev/null
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<VisualStudioToolFile\r
+       Name="Yasm"\r
+       Version="8.00"\r
+       >\r
+  <Rules>\r
+    <CustomBuildRule\r
+                       Name="YASM"\r
+                       DisplayName="Yasm Assembler"\r
+                       CommandLine="yasm -Xvc -f $(PlatformName) [AllOptions] [AdditionalOptions] [Inputs]"\r
+                       Outputs="[$ObjectFileName]"\r
+                       FileExtensions="*.asm"\r
+                       ExecutionDescription="Assembling $(InputFileName)"\r
+                       ShowOnlyRuleProperties="false"\r
+                       >\r
+      <Properties>\r
+        <StringProperty\r
+                                       Name="Defines"\r
+                                       DisplayName="Definitions"\r
+                                       Category="Pre-Defined Symbols"\r
+                                       Description="Specify pre-defined symbols (&apos;symbol&apos; or &apos;symbol = value&apos;) "\r
+                                       Switch="-D [value]"\r
+                                       Delimited="true"\r
+                                       Inheritable="true"\r
+                               />\r
+        <StringProperty\r
+                                       Name="IncludePaths"\r
+                                       DisplayName="Include Paths"\r
+                                       Category="Configuration"\r
+                                       Description="Set the paths for any additional include files"\r
+                                       Switch="-I [value]"\r
+                                       Delimited="true"\r
+                                       Inheritable="true"\r
+                               />\r
+        <StringProperty\r
+                                       Name="UnDefines"\r
+                                       DisplayName="Remove Definitions"\r
+                                       Category="Pre-Defined Symbols"\r
+                                       Description="Remove pre-defined symbols "\r
+                                       Switch="-U [value]"\r
+                                       Delimited="true"\r
+                                       Inheritable="true"\r
+                               />\r
+        <StringProperty\r
+                                       Name="ObjectFileName"\r
+                                       DisplayName="Object File Name"\r
+                                       Category="Output"\r
+                                       Description="Select the output file name"\r
+                                       Switch="-o [value]"\r
+                                       DefaultValue="$(IntDir)\$(InputName).obj"\r
+                               />\r
+        <StringProperty\r
+                                       Name="ListFileName"\r
+                                       DisplayName="List File Name"\r
+                                       Category="Output"\r
+                                       Description="Select an output listing by setting its file name"\r
+                                       Switch="-l [value]"\r
+                               />\r
+        <StringProperty\r
+                                       Name="PreIncludeFile"\r
+                                       DisplayName="Pre Include File"\r
+                                       Category="Configuration"\r
+                                       Description="Select a pre-included file by setting its name"\r
+                                       Switch="-P [value]"\r
+                               />\r
+        <BooleanProperty\r
+                                       Name="Debug"\r
+                                       DisplayName="Debug Information"\r
+                                       Category="Output"\r
+                                       Description="Generate debugging information"\r
+                                       Switch="-g cv8"\r
+                               />\r
+        <EnumProperty\r
+                                       Name="PreProc"\r
+                                       DisplayName="Pre-Processor"\r
+                                       Category="Configuration"\r
+                                       Description="Select the pre-processor (&apos;nasm&apos; or &apos;raw&apos;)"\r
+                                       >\r
+          <Values>\r
+            <EnumValue\r
+                                                       Value="0"\r
+                                                       Switch="-rnasm"\r
+                                                       DisplayName="Nasm "\r
+                                               />\r
+            <EnumValue\r
+                                                       Value="1"\r
+                                                       Switch="-rraw"\r
+                                                       DisplayName="Raw"\r
+                                               />\r
+          </Values>\r
+        </EnumProperty>\r
+        <EnumProperty\r
+                                       Name="Parser"\r
+                                       DisplayName="Parser"\r
+                                       Category="Configuration"\r
+                                       Description="Select the parser for Intel (&apos;nasm&apos;) or AT&amp;T ( &apos;gas&apos;) syntax"\r
+                                       >\r
+          <Values>\r
+            <EnumValue\r
+                                                       Value="0"\r
+                                                       Switch="-pnasm"\r
+                                                       DisplayName="Nasm"\r
+                                               />\r
+            <EnumValue\r
+                                                       Value="1"\r
+                                                       Switch="-pgas"\r
+                                                       DisplayName="Gas"\r
+                                               />\r
+          </Values>\r
+        </EnumProperty>\r
+      </Properties>\r
+    </CustomBuildRule>\r
+  </Rules>\r
+</VisualStudioToolFile>\r
+\r
diff --git a/configure b/configure
new file mode 100755 (executable)
index 0000000..62e1ffb
--- /dev/null
+++ b/configure
@@ -0,0 +1,601 @@
+#!/bin/bash
+##
+##  configure
+##
+##  This script is the front-end to the build system. It provides a similar
+##  interface to standard configure scripts with some extra bits for dealing
+##  with toolchains that differ from the standard POSIX interface and
+##  for extracting subsets of the source tree. In theory, reusable parts
+##  of this script were intended to live in build/make/configure.sh,
+##  but in practice, the line is pretty blurry.
+##
+##  This build system is based in part on the FFmpeg configure script.
+##
+
+#source_path="`dirname \"$0\"`"
+source_path=${0%/*}
+. "${source_path}/build/make/configure.sh"
+
+show_help(){
+    show_help_pre
+    cat << EOF
+Advanced options:
+  ${toggle_libs}                  don't build libraries
+  ${toggle_examples}              don't build examples
+  ${toggle_unit_tests}            build unit tests
+  --libc=PATH                     path to alternate libc
+  --as={yasm|nasm|auto}           use specified assembler [auto, yasm preferred]
+  --sdk-path=PATH                 path to root of sdk (iOS, android builds only)
+  ${toggle_fast_unaligned}        don't use unaligned accesses, even when
+                                  supported by hardware [auto]
+  ${toggle_codec_srcs}            in/exclude codec library source code
+  ${toggle_debug_libs}            in/exclude debug version of libraries
+  ${toggle_md5}                   support for output of checksum data
+  ${toggle_static_msvcrt}         use static MSVCRT (VS builds only)
+  ${toggle_vp8}                   VP8 codec support
+  ${toggle_internal_stats}        output of encoder internal stats for debug, if supported (encoders)
+  ${toggle_mem_tracker}           track memory usage
+  ${toggle_postproc}              postprocessing
+  ${toggle_multithread}           multithreaded encoding and decoding
+  ${toggle_spatial_resampling}    spatial sampling (scaling) support
+  ${toggle_realtime_only}         enable this option while building for real-time encoding
+  ${toggle_onthefly_bitpacking}   enable on-the-fly bitpacking in real-time encoding
+  ${toggle_error_concealment}     enable this option to get a decoder which is able to conceal losses
+  ${toggle_runtime_cpu_detect}    runtime cpu detection
+  ${toggle_shared}                shared library support
+  ${toggle_static}                static library support
+  ${toggle_small}                 favor smaller size over speed
+  ${toggle_postproc_visualizer}   macro block / block level visualizers
+  ${toggle_multi_res_encoding}    enable multiple-resolution encoding
+  ${toggle_temporal_denoising}    enable temporal denoising and disable the spatial denoiser
+
+Codecs:
+  Codecs can be selectively enabled or disabled individually, or by family:
+      --disable-<codec>
+  is equivalent to:
+      --disable-<codec>-encoder
+      --disable-<codec>-decoder
+
+  Codecs available in this distribution:
+EOF
+#restore editor state '
+
+    local family;
+    local last_family;
+    local c;
+    local str;
+    for c in ${CODECS}; do
+        family=${c%_*}
+        if [ "${family}" != "${last_family}" ]; then
+            [ -z "${str}" ] || echo "${str}"
+            str="$(printf '    %10s:' ${family})"
+        fi
+        str="${str} $(printf '%10s' ${c#*_})"
+        last_family=${family}
+    done
+    echo "${str}"
+    show_help_post
+}
+
+##
+## BEGIN APPLICATION SPECIFIC CONFIGURATION
+##
+
+# all_platforms is a list of all supported target platforms. Maintain
+# alphabetically by architecture, generic-gnu last.
+all_platforms="${all_platforms} armv5te-android-gcc"
+all_platforms="${all_platforms} armv5te-linux-rvct"
+all_platforms="${all_platforms} armv5te-linux-gcc"
+all_platforms="${all_platforms} armv5te-none-rvct"
+all_platforms="${all_platforms} armv6-darwin-gcc"
+all_platforms="${all_platforms} armv6-linux-rvct"
+all_platforms="${all_platforms} armv6-linux-gcc"
+all_platforms="${all_platforms} armv6-none-rvct"
+all_platforms="${all_platforms} armv7-android-gcc"   #neon Cortex-A8
+all_platforms="${all_platforms} armv7-darwin-gcc"    #neon Cortex-A8
+all_platforms="${all_platforms} armv7-linux-rvct"    #neon Cortex-A8
+all_platforms="${all_platforms} armv7-linux-gcc"     #neon Cortex-A8
+all_platforms="${all_platforms} armv7-none-rvct"     #neon Cortex-A8
+all_platforms="${all_platforms} mips32-linux-gcc"
+all_platforms="${all_platforms} ppc32-darwin8-gcc"
+all_platforms="${all_platforms} ppc32-darwin9-gcc"
+all_platforms="${all_platforms} ppc32-linux-gcc"
+all_platforms="${all_platforms} ppc64-darwin8-gcc"
+all_platforms="${all_platforms} ppc64-darwin9-gcc"
+all_platforms="${all_platforms} ppc64-linux-gcc"
+all_platforms="${all_platforms} sparc-solaris-gcc"
+all_platforms="${all_platforms} x86-darwin8-gcc"
+all_platforms="${all_platforms} x86-darwin8-icc"
+all_platforms="${all_platforms} x86-darwin9-gcc"
+all_platforms="${all_platforms} x86-darwin9-icc"
+all_platforms="${all_platforms} x86-darwin10-gcc"
+all_platforms="${all_platforms} x86-darwin11-gcc"
+all_platforms="${all_platforms} x86-darwin12-gcc"
+all_platforms="${all_platforms} x86-linux-gcc"
+all_platforms="${all_platforms} x86-linux-icc"
+all_platforms="${all_platforms} x86-os2-gcc"
+all_platforms="${all_platforms} x86-solaris-gcc"
+all_platforms="${all_platforms} x86-win32-gcc"
+all_platforms="${all_platforms} x86-win32-vs7"
+all_platforms="${all_platforms} x86-win32-vs8"
+all_platforms="${all_platforms} x86-win32-vs9"
+all_platforms="${all_platforms} x86_64-darwin9-gcc"
+all_platforms="${all_platforms} x86_64-darwin10-gcc"
+all_platforms="${all_platforms} x86_64-darwin11-gcc"
+all_platforms="${all_platforms} x86_64-darwin12-gcc"
+all_platforms="${all_platforms} x86_64-linux-gcc"
+all_platforms="${all_platforms} x86_64-linux-icc"
+all_platforms="${all_platforms} x86_64-solaris-gcc"
+all_platforms="${all_platforms} x86_64-win64-gcc"
+all_platforms="${all_platforms} x86_64-win64-vs8"
+all_platforms="${all_platforms} x86_64-win64-vs9"
+all_platforms="${all_platforms} universal-darwin8-gcc"
+all_platforms="${all_platforms} universal-darwin9-gcc"
+all_platforms="${all_platforms} universal-darwin10-gcc"
+all_platforms="${all_platforms} universal-darwin11-gcc"
+all_platforms="${all_platforms} universal-darwin12-gcc"
+all_platforms="${all_platforms} generic-gnu"
+
+# all_targets is a list of all targets that can be configured
+# note that these should be in dependency order for now.
+all_targets="libs examples docs"
+
+# all targets available are enabled, by default.
+for t in ${all_targets}; do
+    [ -f ${source_path}/${t}.mk ] && enable ${t}
+done
+
+# check installed doxygen version
+doxy_version=$(doxygen --version 2>/dev/null)
+doxy_major=${doxy_version%%.*}
+if [ ${doxy_major:-0} -ge 1 ]; then
+    doxy_version=${doxy_version#*.}
+    doxy_minor=${doxy_version%%.*}
+    doxy_patch=${doxy_version##*.}
+
+    [ $doxy_major -gt 1 ] && enable doxygen
+    [ $doxy_minor -gt 5 ] && enable doxygen
+    [ $doxy_minor -eq 5 ] && [ $doxy_patch -ge 3 ] && enable doxygen
+fi
+
+# install everything except the sources, by default. sources will have
+# to be enabled when doing dist builds, since that's no longer a common
+# case.
+enabled doxygen && php -v >/dev/null 2>&1 && enable install_docs
+enable install_bins
+enable install_libs
+
+enable static
+enable optimizations
+enable fast_unaligned #allow unaligned accesses, if supported by hw
+enable md5
+enable spatial_resampling
+enable multithread
+enable os_support
+enable temporal_denoising
+
+[ -d ${source_path}/../include ] && enable alt_tree_layout
+for d in vp8; do
+    [ -d ${source_path}/${d} ] && disable alt_tree_layout;
+done
+
+if ! enabled alt_tree_layout; then
+# development environment
+[ -d ${source_path}/vp8 ] && CODECS="${CODECS} vp8_encoder vp8_decoder"
+else
+# customer environment
+[ -f ${source_path}/../include/vpx/vp8cx.h ] && CODECS="${CODECS} vp8_encoder"
+[ -f ${source_path}/../include/vpx/vp8dx.h ] && CODECS="${CODECS} vp8_decoder"
+[ -f ${source_path}/../include/vpx/vp8cx.h ] || disable vp8_encoder
+[ -f ${source_path}/../include/vpx/vp8dx.h ] || disable vp8_decoder
+
+[ -f ${source_path}/../lib/*/*mt.lib ] && soft_enable static_msvcrt
+fi
+
+CODECS="$(echo ${CODECS} | tr ' ' '\n')"
+CODEC_FAMILIES="$(for c in ${CODECS}; do echo ${c%_*}; done | sort | uniq)"
+
+ARCH_LIST="
+    arm
+    mips
+    x86
+    x86_64
+    ppc32
+    ppc64
+"
+ARCH_EXT_LIST="
+    edsp
+    media
+    neon
+
+    mips32
+
+    mmx
+    sse
+    sse2
+    sse3
+    ssse3
+    sse4_1
+
+    altivec
+"
+HAVE_LIST="
+    ${ARCH_EXT_LIST}
+    vpx_ports
+    stdint_h
+    alt_tree_layout
+    pthread_h
+    sys_mman_h
+    unistd_h
+"
+CONFIG_LIST="
+    external_build
+    install_docs
+    install_bins
+    install_libs
+    install_srcs
+    debug
+    gprof
+    gcov
+    rvct
+    gcc
+    msvs
+    pic
+    big_endian
+
+    codec_srcs
+    debug_libs
+    fast_unaligned
+    mem_manager
+    mem_tracker
+    mem_checks
+    md5
+
+    dequant_tokens
+    dc_recon
+    runtime_cpu_detect
+    postproc
+    multithread
+    internal_stats
+    ${CODECS}
+    ${CODEC_FAMILIES}
+    encoders
+    decoders
+    static_msvcrt
+    spatial_resampling
+    realtime_only
+    onthefly_bitpacking
+    error_concealment
+    shared
+    static
+    small
+    postproc_visualizer
+    os_support
+    unit_tests
+    multi_res_encoding
+    temporal_denoising
+"
+CMDLINE_SELECT="
+    extra_warnings
+    werror
+    install_docs
+    install_bins
+    install_libs
+    install_srcs
+    debug
+    gprof
+    gcov
+    pic
+    optimizations
+    ccache
+    runtime_cpu_detect
+
+    libs
+    examples
+    libc
+    as
+    fast_unaligned
+    codec_srcs
+    debug_libs
+    md5
+
+    dequant_tokens
+    dc_recon
+    postproc
+    multithread
+    internal_stats
+    ${CODECS}
+    ${CODEC_FAMILIES}
+    static_msvcrt
+    mem_tracker
+    spatial_resampling
+    realtime_only
+    onthefly_bitpacking
+    error_concealment
+    shared
+    static
+    small
+    postproc_visualizer
+    unit_tests
+    multi_res_encoding
+    temporal_denoising
+"
+
+process_cmdline() {
+    for opt do
+        optval="${opt#*=}"
+        case "$opt" in
+        --disable-codecs) for c in ${CODECS}; do disable $c; done ;;
+        *) process_common_cmdline "$opt"
+        ;;
+        esac
+    done
+}
+
+post_process_cmdline() {
+    local c
+
+    # If the codec family is disabled, disable all components of that family.
+    # If the codec family is enabled, enable all components of that family.
+    log_echo "Configuring selected codecs"
+    for c in ${CODECS}; do
+        disabled ${c%%_*} && disable ${c}
+        enabled ${c%%_*} && enable ${c}
+    done
+
+    # Enable all detected codecs, if they haven't been disabled
+    for c in ${CODECS}; do soft_enable $c; done
+
+    # Enable the codec family if any component of that family is enabled
+    for c in ${CODECS}; do
+        enabled $c && enable ${c%_*}
+    done
+
+    # Set the {en,de}coders variable if any algorithm in that class is enabled
+    for c in ${CODECS}; do
+        enabled ${c} && enable ${c##*_}s
+    done
+}
+
+
+process_targets() {
+    enabled child || write_common_config_banner
+    enabled universal || write_common_target_config_h  ${BUILD_PFX}vpx_config.h
+
+    # TODO: add host tools target (obj_int_extract, etc)
+
+    # For fat binaries, call configure recursively to configure for each
+    # binary architecture to be included.
+    if enabled universal; then
+        # Call configure (ourselves) for each subarchitecture
+        for arch in $fat_bin_archs; do
+            BUILD_PFX=${arch}/ toolchain=${arch} $self --child $cmdline_args || exit $?
+        done
+    fi
+
+    # The write_common_config (config.mk) logic is deferred until after the
+    # recursive calls to configure complete, becuase we want our universal
+    # targets to be executed last.
+    write_common_config_targets
+    enabled universal && echo "FAT_ARCHS=${fat_bin_archs}" >> config.mk
+
+    # Calculate the default distribution name, based on the enabled features
+    local cf
+    local DIST_DIR=vpx
+    for cf in $CODEC_FAMILIES; do
+        if enabled ${cf}_encoder && enabled ${cf}_decoder; then
+            DIST_DIR="${DIST_DIR}-${cf}"
+        elif enabled ${cf}_encoder; then
+            DIST_DIR="${DIST_DIR}-${cf}cx"
+        elif enabled ${cf}_decoder; then
+            DIST_DIR="${DIST_DIR}-${cf}dx"
+        fi
+    done
+    enabled debug_libs && DIST_DIR="${DIST_DIR}-debug"
+    enabled codec_srcs && DIST_DIR="${DIST_DIR}-src"
+    ! enabled postproc && DIST_DIR="${DIST_DIR}-nopost"
+    ! enabled multithread && DIST_DIR="${DIST_DIR}-nomt"
+    ! enabled install_docs && DIST_DIR="${DIST_DIR}-nodocs"
+    DIST_DIR="${DIST_DIR}-${tgt_isa}-${tgt_os}"
+    case "${tgt_os}" in
+    win*) enabled static_msvcrt && DIST_DIR="${DIST_DIR}mt" || DIST_DIR="${DIST_DIR}md"
+          DIST_DIR="${DIST_DIR}-${tgt_cc}"
+          ;;
+    esac
+    if [ -f "${source_path}/build/make/version.sh" ]; then
+        local ver=`"$source_path/build/make/version.sh" --bare $source_path`
+        DIST_DIR="${DIST_DIR}-${ver}"
+        VERSION_STRING=${ver}
+        ver=${ver%%-*}
+        VERSION_PATCH=${ver##*.}
+        ver=${ver%.*}
+        VERSION_MINOR=${ver##*.}
+        ver=${ver#v}
+        VERSION_MAJOR=${ver%.*}
+    fi
+    enabled child || cat <<EOF >> config.mk
+
+PREFIX=${prefix}
+ifeq (\$(MAKECMDGOALS),dist)
+DIST_DIR?=${DIST_DIR}
+else
+DIST_DIR?=\$(DESTDIR)${prefix}
+endif
+LIBSUBDIR=${libdir##${prefix}/}
+
+VERSION_STRING=${VERSION_STRING}
+
+VERSION_MAJOR=${VERSION_MAJOR}
+VERSION_MINOR=${VERSION_MINOR}
+VERSION_PATCH=${VERSION_PATCH}
+
+CONFIGURE_ARGS=${CONFIGURE_ARGS}
+EOF
+    enabled child || echo "CONFIGURE_ARGS?=${CONFIGURE_ARGS}" >> config.mk
+
+    #
+    # Write makefiles for all enabled targets
+    #
+    for tgt in libs examples docs solution; do
+        local tgt_fn="$tgt-$toolchain.mk"
+
+        if enabled $tgt; then
+            echo "Creating makefiles for ${toolchain} ${tgt}"
+            write_common_target_config_mk $tgt_fn ${BUILD_PFX}vpx_config.h
+            #write_${tgt}_config
+        fi
+    done
+
+}
+
+process_detect() {
+    if enabled shared; then
+        # Can only build shared libs on a subset of platforms. Doing this check
+        # here rather than at option parse time because the target auto-detect
+        # magic happens after the command line has been parsed.
+        enabled linux || die "--enable-shared only supported on ELF for now"
+    fi
+    if [ -z "$CC" ]; then
+        echo "Bypassing toolchain for environment detection."
+        enable external_build
+        check_header() {
+            log fake_check_header "$@"
+            header=$1
+            shift
+            var=`echo $header | sed 's/[^A-Za-z0-9_]/_/g'`
+            disable $var
+            case $header in
+                stdio.h)
+                    true;
+                ;;
+                *)
+                    local result=false
+                    for d in "$@"; do
+                        [ -f "${d##-I}/$header" ] && result=true && break
+                    done
+                    ${result:-true}
+            esac && enable $var
+        }
+        check_ld() {
+            true
+        }
+    fi
+    check_header stdio.h || die "Unable to invoke compiler: ${CC} ${CFLAGS}"
+    check_ld <<EOF || die "Toolchain is unable to link executables"
+int main(void) {return 0;}
+EOF
+    # check system headers
+    check_header stdint.h
+    check_header pthread.h
+    check_header sys/mman.h
+
+    check_header vpx/vpx_integer.h -I${source_path} && enable vpx_ports
+}
+
+process_toolchain() {
+    process_common_toolchain
+
+    # Handle universal binaries for this architecture
+    case $toolchain in
+        universal-darwin*)
+            local darwin_ver=${tgt_os##darwin}
+
+            # Snow Leopard (10.6/darwin10) dropped support for PPC
+            # Include PPC support for all prior versions
+            if [ $darwin_ver -lt 10 ]; then
+                fat_bin_archs="$fat_bin_archs ppc32-${tgt_os}-gcc"
+            fi
+
+            # Tiger (10.4/darwin8) brought support for x86
+            if [ $darwin_ver -ge 8 ]; then
+                fat_bin_archs="$fat_bin_archs x86-${tgt_os}-${tgt_cc}"
+            fi
+
+            # Leopard (10.5/darwin9) brought 64 bit support
+            if [ $darwin_ver -ge 9 ]; then
+                fat_bin_archs="$fat_bin_archs x86_64-${tgt_os}-${tgt_cc}"
+            fi
+            ;;
+    esac
+
+
+    # Enable some useful compiler flags
+    if enabled gcc; then
+        enabled werror && check_add_cflags -Werror
+        check_add_cflags -Wall
+        check_add_cflags -Wdeclaration-after-statement
+        check_add_cflags -Wdisabled-optimization
+        check_add_cflags -Wpointer-arith
+        check_add_cflags -Wtype-limits
+        check_add_cflags -Wcast-qual
+        check_add_cflags -Wimplicit-function-declaration
+        check_add_cflags -Wuninitialized
+        check_add_cflags -Wunused-variable
+        check_add_cflags -Wunused-but-set-variable        
+        enabled extra_warnings || check_add_cflags -Wno-unused-function
+    fi
+
+    if enabled icc; then
+        enabled werror && check_add_cflags -Werror
+        check_add_cflags -Wall
+        check_add_cflags -Wpointer-arith
+
+        # ICC has a number of floating point optimizations that we disable
+        # in favor of deterministic output WRT to other compilers
+        add_cflags -fp-model precise
+    fi
+
+    # Enable extra, harmless warnings. These might provide additional insight
+    # to what the compiler is doing and why, but in general, but they shouldn't
+    # be treated as fatal, even if we're treating warnings as errors.
+    GCC_EXTRA_WARNINGS="
+        -Wdisabled-optimization
+        -Winline
+    "
+    enabled gcc && EXTRA_WARNINGS="${GCC_EXTRA_WARNINGS}"
+    RVCT_EXTRA_WARNINGS="
+        --remarks
+    "
+    enabled rvct && EXTRA_WARNINGS="${RVCT_EXTRA_WARNINGS}"
+    if enabled extra_warnings; then
+        for w in ${EXTRA_WARNINGS}; do
+            check_add_cflags ${w}
+            enabled gcc && enabled werror && check_add_cflags -Wno-error=${w}
+        done
+    fi
+
+    # ccache only really works on gcc toolchains
+    enabled gcc || soft_disable ccache
+    if enabled mips; then
+        enable dequant_tokens
+        enable dc_recon
+    fi
+
+    # Enable the postbuild target if building for visual studio.
+    case "$tgt_cc" in
+        vs*) enable msvs
+             enable solution
+             vs_version=${tgt_cc##vs}
+             all_targets="${all_targets} solution"
+        ;;
+    esac
+
+    # Other toolchain specific defaults
+    case $toolchain in x86*|ppc*|universal*) soft_enable postproc;; esac
+
+    if enabled postproc_visualizer; then
+        enabled postproc || die "postproc_visualizer requires postproc to be enabled"
+    fi
+}
+
+
+##
+## END APPLICATION SPECIFIC CONFIGURATION
+##
+CONFIGURE_ARGS="$@"
+process "$@"
+print_webm_license ${BUILD_PFX}vpx_config.c "/*" " */"
+cat <<EOF >> ${BUILD_PFX}vpx_config.c
+static const char* const cfg = "$CONFIGURE_ARGS";
+const char *vpx_codec_build_config(void) {return cfg;}
+EOF
diff --git a/docs.mk b/docs.mk
new file mode 100644 (file)
index 0000000..cfe57ed
--- /dev/null
+++ b/docs.mk
@@ -0,0 +1,53 @@
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+
+INSTALL_MAPS += docs/%    docs/%
+INSTALL_MAPS += src/%     %
+INSTALL_MAPS += %         %
+
+# Static documentation authored in doxygen
+CODEC_DOX :=    mainpage.dox \
+               keywords.dox \
+               usage.dox \
+               usage_cx.dox \
+               usage_dx.dox \
+
+# Other doxy files sourced in Markdown
+TXT_DOX = $(call enabled,TXT_DOX)
+
+%.dox: %.txt
+       @echo "    [DOXY] $@"
+       @$(SRC_PATH_BARE)/examples/gen_example_doxy.php \
+             $(@:.dox=)  "$($@.DESC)" > $@ < $<
+
+
+EXAMPLE_PATH += $(SRC_PATH_BARE) #for CHANGELOG, README, etc
+
+doxyfile: $(if $(findstring examples, $(ALL_TARGETS)),examples.doxy)
+doxyfile: libs.doxy_template libs.doxy
+       @echo "    [CREATE] $@"
+       @cat $^ > $@
+       @echo "STRIP_FROM_PATH += $(SRC_PATH_BARE) $(BUILD_ROOT)" >> $@
+       @echo "INPUT += $(addprefix $(SRC_PATH_BARE)/,$(CODEC_DOX))" >> $@;
+       @echo "INPUT += $(TXT_DOX)" >> $@;
+       @echo "EXAMPLE_PATH += $(EXAMPLE_PATH)" >> $@
+
+CLEAN-OBJS += doxyfile $(wildcard docs/html/*)
+docs/html/index.html: doxyfile $(CODEC_DOX) $(TXT_DOX)
+       @echo "    [DOXYGEN] $<"
+       @doxygen $<
+DOCS-yes += docs/html/index.html
+
+DIST-DOCS-yes = $(wildcard docs/html/*)
+DIST-DOCS-$(CONFIG_CODEC_SRCS) += $(addprefix src/,$(CODEC_DOX))
+DIST-DOCS-$(CONFIG_CODEC_SRCS) += src/libs.doxy_template
+DIST-DOCS-yes                  += CHANGELOG
+DIST-DOCS-yes                  += README
diff --git a/example_xma.c b/example_xma.c
new file mode 100644 (file)
index 0000000..72eb470
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/* This is a simple program showing how to initialize the decoder in XMA mode */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#define VPX_CODEC_DISABLE_COMPAT 1
+#include "vpx_config.h"
+#include "vpx/vpx_decoder.h"
+#include "vpx/vpx_integer.h"
+#if CONFIG_VP8_DECODER
+#include "vpx/vp8dx.h"
+#endif
+
+static char *exec_name;
+static int   verbose = 0;
+
+static const struct
+{
+    const char *name;
+    const vpx_codec_iface_t *iface;
+} ifaces[] =
+{
+#if CONFIG_VP8_DECODER
+    {"vp8",  &vpx_codec_vp8_dx_algo},
+#endif
+};
+
+static void usage_exit(void)
+{
+    int i;
+
+    printf("Usage: %s <options>\n\n"
+           "Options:\n"
+           "\t--codec <name>\tCodec to use (default=%s)\n"
+           "\t-h <height>\tHeight of the simulated video frame, in pixels\n"
+           "\t-w <width> \tWidth of the simulated video frame, in pixels\n"
+           "\t-v         \tVerbose mode (show individual segment sizes)\n"
+           "\t--help     \tShow this message\n"
+           "\n"
+           "Included decoders:\n"
+           "\n",
+           exec_name,
+           ifaces[0].name);
+
+    for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
+        printf("    %-6s - %s\n",
+               ifaces[i].name,
+               vpx_codec_iface_name(ifaces[i].iface));
+
+    exit(EXIT_FAILURE);
+}
+
+static void usage_error(const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    vprintf(fmt, ap);
+    printf("\n");
+    usage_exit();
+}
+
+void my_mem_dtor(vpx_codec_mmap_t *mmap)
+{
+    if (verbose)
+        printf("freeing segment %d\n", mmap->id);
+
+    free(mmap->priv);
+}
+
+int main(int argc, char **argv)
+{
+    vpx_codec_ctx_t           decoder;
+    vpx_codec_iface_t        *iface = ifaces[0].iface;
+    vpx_codec_iter_t          iter;
+    vpx_codec_dec_cfg_t       cfg;
+    vpx_codec_err_t           res = VPX_CODEC_OK;
+    unsigned int            alloc_sz = 0;
+    unsigned int            w = 352;
+    unsigned int            h = 288;
+    int                     i;
+
+    exec_name = argv[0];
+
+    for (i = 1; i < argc; i++)
+    {
+        if (!strcmp(argv[i], "--codec"))
+        {
+            if (i + 1 < argc)
+            {
+                int j, k = -1;
+
+                i++;
+
+                for (j = 0; j < sizeof(ifaces) / sizeof(ifaces[0]); j++)
+                    if (!strcmp(ifaces[j].name, argv[i]))
+                        k = j;
+
+                if (k >= 0)
+                    iface = ifaces[k].iface;
+                else
+                    usage_error("Error: Unrecognized argument (%s) to --codec\n",
+                                argv[i]);
+            }
+            else
+                usage_error("Error: Option --codec requires argument.\n");
+        }
+        else if (!strcmp(argv[i], "-v"))
+            verbose = 1;
+        else if (!strcmp(argv[i], "-h"))
+            if (i + 1 < argc)
+            {
+                h = atoi(argv[++i]);
+            }
+            else
+                usage_error("Error: Option -h requires argument.\n");
+        else if (!strcmp(argv[i], "-w"))
+            if (i + 1 < argc)
+            {
+                w = atoi(argv[++i]);
+            }
+            else
+                usage_error("Error: Option -w requires argument.\n");
+        else if (!strcmp(argv[i], "--help"))
+            usage_exit();
+        else
+            usage_error("Error: Unrecognized option %s\n\n", argv[i]);
+    }
+
+    if (argc == 1)
+        printf("Using built-in defaults. For options, rerun with --help\n\n");
+
+    /* XMA mode is not supported on all decoders! */
+    if (!(vpx_codec_get_caps(iface) & VPX_CODEC_CAP_XMA))
+    {
+        printf("%s does not support XMA mode!\n", vpx_codec_iface_name(iface));
+        return EXIT_FAILURE;
+    }
+
+    /* The codec knows how much memory to allocate based on the size of the
+     * encoded frames. This data can be parsed from the bitstream with
+     * vpx_codec_peek_stream_info() if a bitstream is available. Otherwise,
+     * a fixed size can be used that will be the upper limit on the frame
+     * size the decoder can decode.
+     */
+    cfg.w = w;
+    cfg.h = h;
+
+    /* Initialize the decoder in XMA mode. */
+    if (vpx_codec_dec_init(&decoder, iface, &cfg, VPX_CODEC_USE_XMA))
+    {
+        printf("Failed to initialize decoder in XMA mode: %s\n", vpx_codec_error(&decoder));
+        return EXIT_FAILURE;
+    }
+
+    /* Iterate through the list of memory maps, allocating them with the
+     * requested alignment.
+     */
+    iter = NULL;
+
+    do
+    {
+        vpx_codec_mmap_t  mmap;
+        unsigned int    align;
+
+        res = vpx_codec_get_mem_map(&decoder, &mmap, &iter);
+        align = mmap.align ? mmap.align - 1 : 0;
+
+        if (!res)
+        {
+            if (verbose)
+                printf("Allocating segment %u, size %lu, align %u %s\n",
+                       mmap.id, mmap.sz, mmap.align,
+                       mmap.flags & VPX_CODEC_MEM_ZERO ? "(ZEROED)" : "");
+
+            if (mmap.flags & VPX_CODEC_MEM_ZERO)
+                mmap.priv = calloc(1, mmap.sz + align);
+            else
+                mmap.priv = malloc(mmap.sz + align);
+
+            mmap.base = (void *)((((uintptr_t)mmap.priv) + align) & ~(uintptr_t)align);
+            mmap.dtor = my_mem_dtor;
+            alloc_sz += mmap.sz + align;
+
+            if (vpx_codec_set_mem_map(&decoder, &mmap, 1))
+            {
+                printf("Failed to set mmap: %s\n", vpx_codec_error(&decoder));
+                return EXIT_FAILURE;
+            }
+        }
+        else if (res != VPX_CODEC_LIST_END)
+        {
+            printf("Failed to get mmap: %s\n", vpx_codec_error(&decoder));
+            return EXIT_FAILURE;
+        }
+    }
+    while (res != VPX_CODEC_LIST_END);
+
+    printf("%s\n    %d bytes external memory required for %dx%d.\n",
+           decoder.name, alloc_sz, cfg.w, cfg.h);
+    vpx_codec_destroy(&decoder);
+    return EXIT_SUCCESS;
+
+}
diff --git a/examples.mk b/examples.mk
new file mode 100644 (file)
index 0000000..b93a16b
--- /dev/null
@@ -0,0 +1,285 @@
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+
+# List of examples to build. UTILS are files that are taken from the source
+# tree directly, and GEN_EXAMPLES are files that are created from the
+# examples folder.
+UTILS-$(CONFIG_DECODERS)    += vpxdec.c
+vpxdec.SRCS                 += md5_utils.c md5_utils.h
+vpxdec.SRCS                 += vpx_ports/vpx_timer.h
+vpxdec.SRCS                 += vpx/vpx_integer.h
+vpxdec.SRCS                 += args.c args.h
+vpxdec.SRCS                 += tools_common.c tools_common.h
+vpxdec.SRCS                 += nestegg/halloc/halloc.h
+vpxdec.SRCS                 += nestegg/halloc/src/align.h
+vpxdec.SRCS                 += nestegg/halloc/src/halloc.c
+vpxdec.SRCS                 += nestegg/halloc/src/hlist.h
+vpxdec.SRCS                 += nestegg/halloc/src/macros.h
+vpxdec.SRCS                 += nestegg/include/nestegg/nestegg.h
+vpxdec.SRCS                 += nestegg/src/nestegg.c
+vpxdec.GUID                  = BA5FE66F-38DD-E034-F542-B1578C5FB950
+vpxdec.DESCRIPTION           = Full featured decoder
+UTILS-$(CONFIG_ENCODERS)    += vpxenc.c
+vpxenc.SRCS                 += args.c args.h y4minput.c y4minput.h
+vpxenc.SRCS                 += tools_common.c tools_common.h
+vpxenc.SRCS                 += vpx_ports/mem_ops.h
+vpxenc.SRCS                 += vpx_ports/mem_ops_aligned.h
+vpxenc.SRCS                 += vpx_ports/vpx_timer.h
+vpxenc.SRCS                 += libmkv/EbmlIDs.h
+vpxenc.SRCS                 += libmkv/EbmlWriter.c
+vpxenc.SRCS                 += libmkv/EbmlWriter.h
+vpxenc.GUID                  = 548DEC74-7A15-4B2B-AFC3-AA102E7C25C1
+vpxenc.DESCRIPTION           = Full featured encoder
+UTILS-$(CONFIG_ENCODERS)    += vp8_scalable_patterns.c
+vp8_scalable_patterns.GUID   = 0D6A210B-F482-4D6F-8570-4A9C01ACC88C
+vp8_scalable_patterns.DESCRIPTION = Temporal Scalability Encoder
+
+# Clean up old ivfenc, ivfdec binaries.
+ifeq ($(CONFIG_MSVS),yes)
+CLEAN-OBJS += $(foreach p,$(VS_PLATFORMS),$(p)/Release/ivfenc.exe)
+CLEAN-OBJS += $(foreach p,$(VS_PLATFORMS),$(p)/Release/ivfdec.exe)
+else
+CLEAN-OBJS += ivfenc{.c.o,.c.d,.dox,.exe,}
+CLEAN-OBJS += ivfdec{.c.o,.c.d,.dox,.exe,}
+endif
+
+# XMA example disabled for now, not used in VP8
+#UTILS-$(CONFIG_DECODERS)    += example_xma.c
+#example_xma.GUID             = A955FC4A-73F1-44F7-135E-30D84D32F022
+#example_xma.DESCRIPTION      = External Memory Allocation mode usage
+
+GEN_EXAMPLES-$(CONFIG_DECODERS) += simple_decoder.c
+simple_decoder.GUID              = D3BBF1E9-2427-450D-BBFF-B2843C1D44CC
+simple_decoder.DESCRIPTION       = Simplified decoder loop
+GEN_EXAMPLES-$(CONFIG_DECODERS) += postproc.c
+postproc.GUID                    = 65E33355-F35E-4088-884D-3FD4905881D7
+postproc.DESCRIPTION             = Decoder postprocessor control
+GEN_EXAMPLES-$(CONFIG_DECODERS) += decode_to_md5.c
+decode_to_md5.SRCS              += md5_utils.h md5_utils.c
+decode_to_md5.GUID               = 59120B9B-2735-4BFE-B022-146CA340FE42
+decode_to_md5.DESCRIPTION        = Frame by frame MD5 checksum
+
+GEN_EXAMPLES-$(CONFIG_ENCODERS) += simple_encoder.c
+simple_encoder.GUID              = 4607D299-8A71-4D2C-9B1D-071899B6FBFD
+simple_encoder.DESCRIPTION       = Simplified encoder loop
+GEN_EXAMPLES-$(CONFIG_ENCODERS) += twopass_encoder.c
+twopass_encoder.GUID             = 73494FA6-4AF9-4763-8FBB-265C92402FD8
+twopass_encoder.DESCRIPTION      = Two-pass encoder loop
+GEN_EXAMPLES-$(CONFIG_ENCODERS) += force_keyframe.c
+force_keyframe.GUID              = 3C67CADF-029F-4C86-81F5-D6D4F51177F0
+force_keyframe.DESCRIPTION       = Force generation of keyframes
+ifeq ($(CONFIG_DECODERS),yes)
+GEN_EXAMPLES-$(CONFIG_ENCODERS) += decode_with_drops.c
+endif
+decode_with_drops.GUID           = CE5C53C4-8DDA-438A-86ED-0DDD3CDB8D26
+decode_with_drops.DESCRIPTION    = Drops frames while decoding
+ifeq ($(CONFIG_DECODERS),yes)
+GEN_EXAMPLES-$(CONFIG_ERROR_CONCEALMENT) += decode_with_partial_drops.c
+endif
+decode_with_partial_drops.GUID           = 61C2D026-5754-46AC-916F-1343ECC5537E
+decode_with_partial_drops.DESCRIPTION    = Drops parts of frames while decoding
+GEN_EXAMPLES-$(CONFIG_ENCODERS) += error_resilient.c
+error_resilient.GUID             = DF5837B9-4145-4F92-A031-44E4F832E00C
+error_resilient.DESCRIPTION      = Error Resiliency Feature
+
+GEN_EXAMPLES-$(CONFIG_VP8_ENCODER) += vp8_set_maps.c
+vp8_set_maps.GUID                   = ECB2D24D-98B8-4015-A465-A4AF3DCC145F
+vp8_set_maps.DESCRIPTION            = VP8 set active and ROI maps
+GEN_EXAMPLES-$(CONFIG_VP8_ENCODER) += vp8cx_set_ref.c
+vp8cx_set_ref.GUID                  = C5E31F7F-96F6-48BD-BD3E-10EBF6E8057A
+vp8cx_set_ref.DESCRIPTION           = VP8 set encoder reference frame
+
+# C file is provided, not generated automatically.
+GEN_EXAMPLES-$(CONFIG_MULTI_RES_ENCODING) += vp8_multi_resolution_encoder.c
+vp8_multi_resolution_encoder.SRCS  \
+                         += third_party/libyuv/include/libyuv/basic_types.h  \
+                            third_party/libyuv/include/libyuv/cpu_id.h  \
+                            third_party/libyuv/include/libyuv/scale.h  \
+                            third_party/libyuv/source/row.h \
+                            third_party/libyuv/source/scale.c  \
+                            third_party/libyuv/source/cpu_id.c
+vp8_multi_resolution_encoder.GUID         = 04f8738e-63c8-423b-90fa-7c2703a374de
+vp8_multi_resolution_encoder.DESCRIPTION  = VP8 Multiple-resolution Encoding
+
+# Handle extra library flags depending on codec configuration
+
+# We should not link to math library (libm) on RVCT
+# when building for bare-metal targets
+ifeq ($(CONFIG_OS_SUPPORT), yes)
+CODEC_EXTRA_LIBS-$(CONFIG_VP8)         += m
+else
+    ifeq ($(CONFIG_GCC), yes)
+    CODEC_EXTRA_LIBS-$(CONFIG_VP8)         += m
+    endif
+endif
+#
+# End of specified files. The rest of the build rules should happen
+# automagically from here.
+#
+
+
+# Examples need different flags based on whether we're building
+# from an installed tree or a version controlled tree. Determine
+# the proper paths.
+ifeq ($(HAVE_ALT_TREE_LAYOUT),yes)
+    LIB_PATH := $(SRC_PATH_BARE)/../lib
+    INC_PATH := $(SRC_PATH_BARE)/../include
+else
+    LIB_PATH-yes                     += $(if $(BUILD_PFX),$(BUILD_PFX),.)
+    INC_PATH-$(CONFIG_VP8_DECODER)   += $(SRC_PATH_BARE)/vp8
+    INC_PATH-$(CONFIG_VP8_ENCODER)   += $(SRC_PATH_BARE)/vp8
+    LIB_PATH := $(call enabled,LIB_PATH)
+    INC_PATH := $(call enabled,INC_PATH)
+endif
+INTERNAL_CFLAGS = $(addprefix -I,$(INC_PATH))
+INTERNAL_LDFLAGS += $(addprefix -L,$(LIB_PATH))
+
+
+# Expand list of selected examples to build (as specified above)
+UTILS           = $(call enabled,UTILS)
+GEN_EXAMPLES    = $(call enabled,GEN_EXAMPLES)
+ALL_EXAMPLES    = $(UTILS) $(GEN_EXAMPLES)
+UTIL_SRCS       = $(foreach ex,$(UTILS),$($(ex:.c=).SRCS))
+ALL_SRCS        = $(foreach ex,$(ALL_EXAMPLES),$($(ex:.c=).SRCS))
+CODEC_EXTRA_LIBS=$(sort $(call enabled,CODEC_EXTRA_LIBS))
+
+
+# Expand all example sources into a variable containing all sources
+# for that example (not just them main one specified in UTILS/GEN_EXAMPLES)
+# and add this file to the list (for MSVS workspace generation)
+$(foreach ex,$(ALL_EXAMPLES),$(eval $(ex:.c=).SRCS += $(ex) examples.mk))
+
+
+# If this is a universal (fat) binary, then all the subarchitectures have
+# already been built and our job is to stitch them together. The
+# BUILD_OBJS variable indicates whether we should be building
+# (compiling, linking) the library. The LIPO_OBJS variable indicates
+# that we're stitching.
+$(eval $(if $(filter universal%,$(TOOLCHAIN)),LIPO_OBJS,BUILD_OBJS):=yes)
+
+
+# Create build/install dependencies for all examples. The common case
+# is handled here. The MSVS case is handled below.
+NOT_MSVS = $(if $(CONFIG_MSVS),,yes)
+DIST-BINS-$(NOT_MSVS)      += $(addprefix bin/,$(ALL_EXAMPLES:.c=$(EXE_SFX)))
+INSTALL-BINS-$(NOT_MSVS)   += $(addprefix bin/,$(UTILS:.c=$(EXE_SFX)))
+DIST-SRCS-yes              += $(ALL_SRCS)
+INSTALL-SRCS-yes           += $(UTIL_SRCS)
+OBJS-$(NOT_MSVS)           += $(if $(BUILD_OBJS),$(call objs,$(ALL_SRCS)))
+BINS-$(NOT_MSVS)           += $(addprefix $(BUILD_PFX),$(ALL_EXAMPLES:.c=$(EXE_SFX)))
+
+
+# Instantiate linker template for all examples.
+CODEC_LIB=$(if $(CONFIG_DEBUG_LIBS),vpx_g,vpx)
+CODEC_LIB_SUF=$(if $(CONFIG_SHARED),.so,.a)
+$(foreach bin,$(BINS-yes),\
+    $(if $(BUILD_OBJS),$(eval $(bin):\
+        $(LIB_PATH)/lib$(CODEC_LIB)$(CODEC_LIB_SUF)))\
+    $(if $(BUILD_OBJS),$(eval $(call linker_template,$(bin),\
+        $(call objs,$($(notdir $(bin:$(EXE_SFX)=)).SRCS)) \
+        -l$(CODEC_LIB) $(addprefix -l,$(CODEC_EXTRA_LIBS))\
+        )))\
+    $(if $(LIPO_OBJS),$(eval $(call lipo_bin_template,$(bin))))\
+    )
+
+
+# Rules to generate the GEN_EXAMPLES sources
+.PRECIOUS: %.c
+CLEAN-OBJS += $(GEN_EXAMPLES)
+%.c: examples/%.txt
+       @echo "    [EXAMPLE] $@"
+       @$(SRC_PATH_BARE)/examples/gen_example_code.sh $< > $@
+
+
+# The following pairs define a mapping of locations in the distribution
+# tree to locations in the source/build trees.
+INSTALL_MAPS += src/%.c   %.c
+INSTALL_MAPS += src/%     $(SRC_PATH_BARE)/%
+INSTALL_MAPS += bin/%     %
+INSTALL_MAPS += %         %
+
+
+# Set up additional MSVS environment
+ifeq ($(CONFIG_MSVS),yes)
+CODEC_LIB=$(if $(CONFIG_STATIC_MSVCRT),vpxmt,vpxmd)
+# This variable uses deferred expansion intentionally, since the results of
+# $(wildcard) may change during the course of the Make.
+VS_PLATFORMS = $(foreach d,$(wildcard */Release/$(CODEC_LIB).lib),$(word 1,$(subst /, ,$(d))))
+INSTALL_MAPS += $(foreach p,$(VS_PLATFORMS),bin/$(p)/%  $(p)/Release/%)
+endif
+
+# Build Visual Studio Projects. We use a template here to instantiate
+# explicit rules rather than using an implicit rule because we want to
+# leverage make's VPATH searching rather than specifying the paths on
+# each file in ALL_EXAMPLES. This has the unfortunate side effect that
+# touching the source files trigger a rebuild of the project files
+# even though there is no real dependency there (the dependency is on
+# the makefiles). We may want to revisit this.
+define vcproj_template
+$(1): $($(1:.vcproj=).SRCS)
+       @echo "    [vcproj] $$@"
+       $$(SRC_PATH_BARE)/build/make/gen_msvs_proj.sh\
+            --exe\
+            --target=$$(TOOLCHAIN)\
+            --name=$$(@:.vcproj=)\
+            --ver=$$(CONFIG_VS_VERSION)\
+            --proj-guid=$$($$(@:.vcproj=).GUID)\
+            $$(if $$(CONFIG_STATIC_MSVCRT),--static-crt) \
+            --out=$$@ $$(INTERNAL_CFLAGS) $$(CFLAGS) \
+            $$(INTERNAL_LDFLAGS) $$(LDFLAGS) -l$$(CODEC_LIB) -lwinmm $$^
+endef
+PROJECTS-$(CONFIG_MSVS) += $(ALL_EXAMPLES:.c=.vcproj)
+INSTALL-BINS-$(CONFIG_MSVS) += $(foreach p,$(VS_PLATFORMS),\
+                               $(addprefix bin/$(p)/,$(ALL_EXAMPLES:.c=.exe)))
+$(foreach proj,$(call enabled,PROJECTS),\
+    $(eval $(call vcproj_template,$(proj))))
+
+
+
+#
+# Documentation Rules
+#
+%.dox: examples/%.txt
+       @echo "    [DOXY] $@"
+       @$(SRC_PATH_BARE)/examples/gen_example_text.sh $< | \
+         $(SRC_PATH_BARE)/examples/gen_example_doxy.php \
+             example_$(@:.dox=)  $(@:.dox=.c) > $@
+
+%.dox: %.c
+       @echo "    [DOXY] $@"
+       @echo "/*!\page example_$(@:.dox=) $(@:.dox=)" > $@
+       @echo "   \includelineno $(notdir $<)" >> $@
+       @echo "*/" >> $@
+
+samples.dox: examples.mk
+       @echo "    [DOXY] $@"
+       @echo "/*!\page samples Sample Code" > $@
+       @echo "    This SDK includes a number of sample applications."\
+             "each sample documents a feature of the SDK in both prose"\
+             "and the associated C code. In general, later samples"\
+             "build upon prior samples, so it is best to work through the"\
+             "list in order. The following samples are included: ">>$@
+       @$(foreach ex,$(GEN_EXAMPLES:.c=),\
+          echo "     - \subpage example_$(ex) $($(ex).DESCRIPTION)" >> $@;)
+       @echo >> $@
+       @echo "    In addition, the SDK contains a number of utilities."\
+              "Since these utilities are built upon the concepts described"\
+              "in the sample code listed above, they are not documented in"\
+              "pieces like the samples are. Thir sourcre is included here"\
+              "for reference. The following utilities are included:" >> $@
+       @$(foreach ex,$(UTILS:.c=),\
+          echo "     - \subpage example_$(ex) $($(ex).DESCRIPTION)" >> $@;)
+       @echo "*/" >> $@
+
+CLEAN-OBJS += examples.doxy samples.dox $(ALL_EXAMPLES:.c=.dox)
+DOCS-yes += examples.doxy samples.dox $(ALL_EXAMPLES:.c=.dox)
+examples.doxy: samples.dox $(ALL_EXAMPLES:.c=.dox)
+       @echo "INPUT += $^" > $@
diff --git a/examples/decode_to_md5.txt b/examples/decode_to_md5.txt
new file mode 100644 (file)
index 0000000..ea0eb69
--- /dev/null
@@ -0,0 +1,48 @@
+@TEMPLATE decoder_tmpl.c
+Frame-by-frame MD5 Checksum
+===========================
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+This example builds upon the simple decoder loop to show how checksums
+of the decoded output can be generated. These are used for validating
+decoder implementations against the reference implementation, for example.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+
+MD5 algorithm
+-------------
+The Message-Digest 5 (MD5) is a well known hash function. We have provided
+an implementation derived from the RSA Data Security, Inc. MD5 Message-Digest
+Algorithm for your use. Our implmentation only changes the interface of this
+reference code. You must include the `md5_utils.h` header for access to these
+functions.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_INCLUDES
+#include "md5_utils.h"
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_INCLUDES
+
+
+Processing The Decoded Data
+---------------------------
+Each row of the image is passed to the MD5 accumulator. First the Y plane
+is processed, then U, then V. It is important to honor the image's `stride`
+values.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_DX
+unsigned char  md5_sum[16];
+MD5Context     md5;
+int            i;
+
+MD5Init(&md5);
+
+for(plane=0; plane < 3; plane++) {
+    unsigned char *buf =img->planes[plane];
+
+    for(y=0; y < (plane ? (img->d_h + 1) >> 1 : img->d_h); y++) {
+        MD5Update(&md5, buf, (plane ? (img->d_w + 1) >> 1 : img->d_w));
+        buf += img->stride[plane];
+    }
+}
+
+MD5Final(md5_sum, &md5);
+for(i=0; i<16; i++)
+    fprintf(outfile, "%02x",md5_sum[i]);
+fprintf(outfile, "  img-%dx%d-%04d.i420\n", img->d_w, img->d_h,
+        frame_cnt);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_DX
diff --git a/examples/decode_with_drops.txt b/examples/decode_with_drops.txt
new file mode 100644 (file)
index 0000000..fb77a7e
--- /dev/null
@@ -0,0 +1,73 @@
+@TEMPLATE decoder_tmpl.c
+Decode With Drops Example
+=========================
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+This is an example utility which drops a series of frames, as specified
+on the command line. This is useful for observing the error recovery
+features of the codec.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+
+Usage
+-----
+This example adds a single argument to the `simple_decoder` example,
+which specifies the range or pattern of frames to drop. The parameter is
+parsed as follows:
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
+if(argc!=4)
+    die("Usage: %s <infile> <outfile> <N-M|N/M>\n", argv[0]);
+{
+    char *nptr;
+    n = strtol(argv[3], &nptr, 0);
+    m = strtol(nptr+1, NULL, 0);
+    is_range = *nptr == '-';
+    if(!n || !m || (*nptr != '-' && *nptr != '/'))
+        die("Couldn't parse pattern %s\n", argv[3]);
+}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
+
+
+Dropping A Range Of Frames
+--------------------------
+To drop a range of frames, specify the starting frame and the ending
+frame to drop, separated by a dash. The following command will drop
+frames 5 through 10 (base 1).
+
+  $ ./decode_with_drops in.ivf out.i420 5-10
+
+
+Dropping A Pattern Of Frames
+----------------------------
+To drop a pattern of frames, specify the number of frames to drop and
+the number of frames after which to repeat the pattern, separated by
+a forward-slash. The following command will drop 3 of 7 frames.
+Specifically, it will decode 4 frames, then drop 3 frames, and then
+repeat.
+
+  $ ./decode_with_drops in.ivf out.i420 3/7
+
+
+Extra Variables
+---------------
+This example maintains the pattern passed on the command line in the
+`n`, `m`, and `is_range` variables:
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_VARS
+int              n, m, is_range;
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_VARS
+
+
+Making The Drop Decision
+------------------------
+The example decides whether to drop the frame based on the current
+frame number, immediately before decoding the frame.
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PRE_DECODE
+if((is_range && frame_cnt >= n && frame_cnt <= m)
+   ||(!is_range && m - (frame_cnt-1)%m <= n)) {
+   putc('X', stdout);
+   continue;
+}
+putc('.', stdout);
+fflush(stdout);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PRE_DECODE
diff --git a/examples/decode_with_partial_drops.txt b/examples/decode_with_partial_drops.txt
new file mode 100644 (file)
index 0000000..7b0d3d2
--- /dev/null
@@ -0,0 +1,238 @@
+@TEMPLATE decoder_tmpl.c
+Decode With Partial Drops Example
+=========================
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+This is an example utility which drops a series of frames (or parts of frames),
+as specified on the command line. This is useful for observing the error
+recovery features of the codec.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_INCLUDES
+#include <time.h>
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_INCLUDES
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ HELPERS
+struct parsed_header
+{
+    char key_frame;
+    int version;
+    char show_frame;
+    int first_part_size;
+};
+
+int next_packet(struct parsed_header* hdr, int pos, int length, int mtu)
+{
+    int size = 0;
+    int remaining = length - pos;
+    /* Uncompressed part is 3 bytes for P frames and 10 bytes for I frames */
+    int uncomp_part_size = (hdr->key_frame ? 10 : 3);
+    /* number of bytes yet to send from header and the first partition */
+    int remainFirst = uncomp_part_size + hdr->first_part_size - pos;
+    if (remainFirst > 0)
+    {
+        if (remainFirst <= mtu)
+        {
+            size = remainFirst;
+        }
+        else
+        {
+            size = mtu;
+        }
+
+        return size;
+    }
+
+    /* second partition; just slot it up according to MTU */
+    if (remaining <= mtu)
+    {
+        size = remaining;
+        return size;
+    }
+    return mtu;
+}
+
+void throw_packets(unsigned char* frame, int* size, int loss_rate,
+                   int* thrown, int* kept)
+{
+    unsigned char loss_frame[256*1024];
+    int pkg_size = 1;
+    int pos = 0;
+    int loss_pos = 0;
+    struct parsed_header hdr;
+    unsigned int tmp;
+    int mtu = 1500;
+
+    if (*size < 3)
+    {
+        return;
+    }
+    putc('|', stdout);
+    /* parse uncompressed 3 bytes */
+    tmp = (frame[2] << 16) | (frame[1] << 8) | frame[0];
+    hdr.key_frame = !(tmp & 0x1); /* inverse logic */
+    hdr.version = (tmp >> 1) & 0x7;
+    hdr.show_frame = (tmp >> 4) & 0x1;
+    hdr.first_part_size = (tmp >> 5) & 0x7FFFF;
+
+    /* don't drop key frames */
+    if (hdr.key_frame)
+    {
+        int i;
+        *kept = *size/mtu + ((*size % mtu > 0) ? 1 : 0); /* approximate */
+        for (i=0; i < *kept; i++)
+            putc('.', stdout);
+        return;
+    }
+
+    while ((pkg_size = next_packet(&hdr, pos, *size, mtu)) > 0)
+    {
+        int loss_event = ((rand() + 1.0)/(RAND_MAX + 1.0) < loss_rate/100.0);
+        if (*thrown == 0 && !loss_event)
+        {
+            memcpy(loss_frame + loss_pos, frame + pos, pkg_size);
+            loss_pos += pkg_size;
+            (*kept)++;
+            putc('.', stdout);
+        }
+        else
+        {
+            (*thrown)++;
+            putc('X', stdout);
+        }
+        pos += pkg_size;
+    }
+    memcpy(frame, loss_frame, loss_pos);
+    memset(frame + loss_pos, 0, *size - loss_pos);
+    *size = loss_pos;
+}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ HELPERS
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INIT
+/* Initialize codec */
+flags = VPX_CODEC_USE_ERROR_CONCEALMENT;
+res = vpx_codec_dec_init(&codec, interface, &dec_cfg, flags);
+if(res)
+    die_codec(&codec, "Failed to initialize decoder");
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INIT
+
+Usage
+-----
+This example adds a single argument to the `simple_decoder` example,
+which specifies the range or pattern of frames to drop. The parameter is
+parsed as follows:
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
+if(argc < 4 || argc > 6)
+    die("Usage: %s <infile> <outfile> [-t <num threads>] <N-M|N/M|L,S>\n",
+        argv[0]);
+{
+    char *nptr;
+    int arg_num = 3;
+    if (argc == 6 && strncmp(argv[arg_num++], "-t", 2) == 0)
+        dec_cfg.threads = strtol(argv[arg_num++], NULL, 0);
+    n = strtol(argv[arg_num], &nptr, 0);
+    mode = (*nptr == '\0' || *nptr == ',') ? 2 : (*nptr == '-') ? 1 : 0;
+
+    m = strtol(nptr+1, NULL, 0);
+    if((!n && !m) || (*nptr != '-' && *nptr != '/' &&
+        *nptr != '\0' && *nptr != ','))
+        die("Couldn't parse pattern %s\n", argv[3]);
+}
+seed = (m > 0) ? m : (unsigned int)time(NULL);
+srand(seed);thrown_frame = 0;
+printf("Seed: %u\n", seed);
+printf("Threads: %d\n", dec_cfg.threads);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
+
+
+Dropping A Range Of Frames
+--------------------------
+To drop a range of frames, specify the starting frame and the ending
+frame to drop, separated by a dash. The following command will drop
+frames 5 through 10 (base 1).
+
+  $ ./decode_with_partial_drops in.ivf out.i420 5-10
+
+
+Dropping A Pattern Of Frames
+----------------------------
+To drop a pattern of frames, specify the number of frames to drop and
+the number of frames after which to repeat the pattern, separated by
+a forward-slash. The following command will drop 3 of 7 frames.
+Specifically, it will decode 4 frames, then drop 3 frames, and then
+repeat.
+
+  $ ./decode_with_partial_drops in.ivf out.i420 3/7
+
+Dropping Random Parts Of Frames
+-------------------------------
+A third argument tuple is available to split the frame into 1500 bytes pieces
+and randomly drop pieces rather than frames. The frame will be split at
+partition boundaries where possible. The following example will seed the RNG
+with the seed 123 and drop approximately 5% of the pieces. Pieces which
+are depending on an already dropped piece will also be dropped.
+
+  $ ./decode_with_partial_drops in.ivf out.i420 5,123
+
+
+Extra Variables
+---------------
+This example maintains the pattern passed on the command line in the
+`n`, `m`, and `is_range` variables:
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_VARS
+int              n, m, mode;
+unsigned int     seed;
+int              thrown=0, kept=0;
+int              thrown_frame=0, kept_frame=0;
+vpx_codec_dec_cfg_t  dec_cfg = {0};
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_VARS
+
+
+Making The Drop Decision
+------------------------
+The example decides whether to drop the frame based on the current
+frame number, immediately before decoding the frame.
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PRE_DECODE
+/* Decide whether to throw parts of the frame or the whole frame
+   depending on the drop mode */
+thrown_frame = 0;
+kept_frame = 0;
+switch (mode)
+{
+case 0:
+    if (m - (frame_cnt-1)%m <= n)
+    {
+        frame_sz = 0;
+    }
+    break;
+case 1:
+    if (frame_cnt >= n && frame_cnt <= m)
+    {
+        frame_sz = 0;
+    }
+    break;
+case 2:
+    throw_packets(frame, &frame_sz, n, &thrown_frame, &kept_frame);
+    break;
+default: break;
+}
+if (mode < 2)
+{
+    if (frame_sz == 0)
+    {
+        putc('X', stdout);
+        thrown_frame++;
+    }
+    else
+    {
+        putc('.', stdout);
+        kept_frame++;
+    }
+}
+thrown += thrown_frame;
+kept += kept_frame;
+fflush(stdout);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PRE_DECODE
diff --git a/examples/decoder_tmpl.c b/examples/decoder_tmpl.c
new file mode 100644 (file)
index 0000000..8194f0a
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+@*INTRODUCTION
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#define VPX_CODEC_DISABLE_COMPAT 1
+#include "vpx/vpx_decoder.h"
+#include "vpx/vp8dx.h"
+#define interface (vpx_codec_vp8_dx())
+@EXTRA_INCLUDES
+
+
+#define IVF_FILE_HDR_SZ  (32)
+#define IVF_FRAME_HDR_SZ (12)
+
+static unsigned int mem_get_le32(const unsigned char *mem) {
+    return (mem[3] << 24)|(mem[2] << 16)|(mem[1] << 8)|(mem[0]);
+}
+
+static void die(const char *fmt, ...) {
+    va_list ap;
+
+    va_start(ap, fmt);
+    vprintf(fmt, ap);
+    if(fmt[strlen(fmt)-1] != '\n')
+        printf("\n");
+    exit(EXIT_FAILURE);
+}
+
+@DIE_CODEC
+
+@HELPERS
+
+int main(int argc, char **argv) {
+    FILE            *infile, *outfile;
+    vpx_codec_ctx_t  codec;
+    int              flags = 0, frame_cnt = 0;
+    unsigned char    file_hdr[IVF_FILE_HDR_SZ];
+    unsigned char    frame_hdr[IVF_FRAME_HDR_SZ];
+    unsigned char    frame[256*1024];
+    vpx_codec_err_t  res;
+@@@@EXTRA_VARS
+
+    (void)res;
+    /* Open files */
+@@@@USAGE
+    if(!(infile = fopen(argv[1], "rb")))
+        die("Failed to open %s for reading", argv[1]);
+    if(!(outfile = fopen(argv[2], "wb")))
+        die("Failed to open %s for writing", argv[2]);
+
+    /* Read file header */
+    if(!(fread(file_hdr, 1, IVF_FILE_HDR_SZ, infile) == IVF_FILE_HDR_SZ
+         && file_hdr[0]=='D' && file_hdr[1]=='K' && file_hdr[2]=='I'
+         && file_hdr[3]=='F'))
+        die("%s is not an IVF file.", argv[1]);
+
+    printf("Using %s\n",vpx_codec_iface_name(interface));
+@@@@DEC_INIT
+
+    /* Read each frame */
+    while(fread(frame_hdr, 1, IVF_FRAME_HDR_SZ, infile) == IVF_FRAME_HDR_SZ) {
+        int               frame_sz = mem_get_le32(frame_hdr);
+        vpx_codec_iter_t  iter = NULL;
+        vpx_image_t      *img;
+
+
+        frame_cnt++;
+        if(frame_sz > sizeof(frame))
+            die("Frame %d data too big for example code buffer", frame_sz);
+        if(fread(frame, 1, frame_sz, infile) != frame_sz)
+            die("Frame %d failed to read complete frame", frame_cnt);
+
+@@@@@@@@PRE_DECODE
+@@@@@@@@DECODE
+
+        /* Write decoded data to disk */
+@@@@@@@@GET_FRAME
+            unsigned int plane, y;
+
+@@@@@@@@@@@@PROCESS_DX
+        }
+    }
+    printf("Processed %d frames.\n",frame_cnt);
+@@@@DESTROY
+
+    fclose(outfile);
+    fclose(infile);
+    return EXIT_SUCCESS;
+}
diff --git a/examples/decoder_tmpl.txt b/examples/decoder_tmpl.txt
new file mode 100644 (file)
index 0000000..92a2c30
--- /dev/null
@@ -0,0 +1,62 @@
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INCLUDES
+#define VPX_CODEC_DISABLE_COMPAT 1
+#include "vpx/vpx_decoder.h"
+#include "vpx/vp8dx.h"
+#define interface (vpx_codec_vp8_dx())
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INCLUDES
+
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DIE_CODEC
+static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
+    const char *detail = vpx_codec_error_detail(ctx);
+
+    printf("%s: %s\n", s, vpx_codec_error(ctx));
+    if(detail)
+        printf("    %s\n",detail);
+    exit(EXIT_FAILURE);
+}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DIE_CODEC
+
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
+if(argc!=3)
+    die("Usage: %s <infile> <outfile>\n", argv[0]);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
+
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INIT
+/* Initialize codec */
+if(vpx_codec_dec_init(&codec, interface, NULL, flags))
+    die_codec(&codec, "Failed to initialize decoder");
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INIT
+
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DECODE
+/* Decode the frame */
+if(vpx_codec_decode(&codec, frame, frame_sz, NULL, 0))
+    die_codec(&codec, "Failed to decode frame");
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DECODE
+
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GET_FRAME
+while((img = vpx_codec_get_frame(&codec, &iter))) {
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GET_FRAME
+
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_DX
+for(plane=0; plane < 3; plane++) {
+    unsigned char *buf =img->planes[plane];
+
+    for(y=0; y < (plane ? (img->d_h + 1) >> 1 : img->d_h); y++) {
+        if(fwrite(buf, 1, (plane ? (img->d_w + 1) >> 1 : img->d_w),
+           outfile));
+        buf += img->stride[plane];
+    }
+}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_DX
+
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DESTROY
+if(vpx_codec_destroy(&codec))
+    die_codec(&codec, "Failed to destroy codec");
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DESTROY
diff --git a/examples/encoder_tmpl.c b/examples/encoder_tmpl.c
new file mode 100644 (file)
index 0000000..cc70b00
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+@*INTRODUCTION
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#define VPX_CODEC_DISABLE_COMPAT 1
+#include "vpx/vpx_encoder.h"
+#include "vpx/vp8cx.h"
+#define interface (vpx_codec_vp8_cx())
+#define fourcc    0x30385056
+@EXTRA_INCLUDES
+
+#define IVF_FILE_HDR_SZ  (32)
+#define IVF_FRAME_HDR_SZ (12)
+
+static void mem_put_le16(char *mem, unsigned int val) {
+    mem[0] = val;
+    mem[1] = val>>8;
+}
+
+static void mem_put_le32(char *mem, unsigned int val) {
+    mem[0] = val;
+    mem[1] = val>>8;
+    mem[2] = val>>16;
+    mem[3] = val>>24;
+}
+
+static void die(const char *fmt, ...) {
+    va_list ap;
+
+    va_start(ap, fmt);
+    vprintf(fmt, ap);
+    if(fmt[strlen(fmt)-1] != '\n')
+        printf("\n");
+    exit(EXIT_FAILURE);
+}
+
+@DIE_CODEC
+
+static int read_frame(FILE *f, vpx_image_t *img) {
+    size_t nbytes, to_read;
+    int    res = 1;
+
+    to_read = img->w*img->h*3/2;
+    nbytes = fread(img->planes[0], 1, to_read, f);
+    if(nbytes != to_read) {
+        res = 0;
+        if(nbytes > 0)
+            printf("Warning: Read partial frame. Check your width & height!\n");
+    }
+    return res;
+}
+
+static void write_ivf_file_header(FILE *outfile,
+                                  const vpx_codec_enc_cfg_t *cfg,
+                                  int frame_cnt) {
+    char header[32];
+
+    if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
+        return;
+    header[0] = 'D';
+    header[1] = 'K';
+    header[2] = 'I';
+    header[3] = 'F';
+    mem_put_le16(header+4,  0);                   /* version */
+    mem_put_le16(header+6,  32);                  /* headersize */
+    mem_put_le32(header+8,  fourcc);              /* headersize */
+    mem_put_le16(header+12, cfg->g_w);            /* width */
+    mem_put_le16(header+14, cfg->g_h);            /* height */
+    mem_put_le32(header+16, cfg->g_timebase.den); /* rate */
+    mem_put_le32(header+20, cfg->g_timebase.num); /* scale */
+    mem_put_le32(header+24, frame_cnt);           /* length */
+    mem_put_le32(header+28, 0);                   /* unused */
+
+    if(fwrite(header, 1, 32, outfile));
+}
+
+
+static void write_ivf_frame_header(FILE *outfile,
+                                   const vpx_codec_cx_pkt_t *pkt)
+{
+    char             header[12];
+    vpx_codec_pts_t  pts;
+
+    if(pkt->kind != VPX_CODEC_CX_FRAME_PKT)
+        return;
+
+    pts = pkt->data.frame.pts;
+    mem_put_le32(header, pkt->data.frame.sz);
+    mem_put_le32(header+4, pts&0xFFFFFFFF);
+    mem_put_le32(header+8, pts >> 32);
+
+    if(fwrite(header, 1, 12, outfile));
+}
+
+int main(int argc, char **argv) {
+    FILE                *infile, *outfile;
+    vpx_codec_ctx_t      codec;
+    vpx_codec_enc_cfg_t  cfg;
+    int                  frame_cnt = 0;
+    vpx_image_t          raw;
+    vpx_codec_err_t      res;
+    long                 width;
+    long                 height;
+    int                  frame_avail;
+    int                  got_data;
+    int                  flags = 0;
+@@@@TWOPASS_VARS
+
+    /* Open files */
+@@@@USAGE
+    width = strtol(argv[1], NULL, 0);
+    height = strtol(argv[2], NULL, 0);
+    if(width < 16 || width%2 || height <16 || height%2)
+        die("Invalid resolution: %ldx%ld", width, height);
+    if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1))
+        die("Faile to allocate image", width, height);
+    if(!(outfile = fopen(argv[4], "wb")))
+        die("Failed to open %s for writing", argv[4]);
+
+    printf("Using %s\n",vpx_codec_iface_name(interface));
+
+@@@@ENC_DEF_CFG
+
+@@@@ENC_SET_CFG
+@@@@ENC_SET_CFG2
+
+    write_ivf_file_header(outfile, &cfg, 0);
+
+@@@@TWOPASS_LOOP_BEGIN
+
+        /* Open input file for this encoding pass */
+        if(!(infile = fopen(argv[3], "rb")))
+            die("Failed to open %s for reading", argv[3]);
+
+@@@@@@@@ENC_INIT
+
+        frame_avail = 1;
+        got_data = 0;
+        while(frame_avail || got_data) {
+            vpx_codec_iter_t iter = NULL;
+            const vpx_codec_cx_pkt_t *pkt;
+
+@@@@@@@@@@@@PER_FRAME_CFG
+@@@@@@@@@@@@ENCODE_FRAME
+            got_data = 0;
+            while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
+                got_data = 1;
+                switch(pkt->kind) {
+@@@@@@@@@@@@@@@@PROCESS_FRAME
+@@@@@@@@@@@@@@@@PROCESS_STATS
+                default:
+                    break;
+                }
+                printf(pkt->kind == VPX_CODEC_CX_FRAME_PKT
+                       && (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":".");
+                fflush(stdout);
+            }
+            frame_cnt++;
+        }
+        printf("\n");
+        fclose(infile);
+@@@@TWOPASS_LOOP_END
+
+    printf("Processed %d frames.\n",frame_cnt-1);
+@@@@DESTROY
+
+    /* Try to rewrite the file header with the actual frame count */
+    if(!fseek(outfile, 0, SEEK_SET))
+        write_ivf_file_header(outfile, &cfg, frame_cnt-1);
+    fclose(outfile);
+    return EXIT_SUCCESS;
+}
diff --git a/examples/encoder_tmpl.txt b/examples/encoder_tmpl.txt
new file mode 100644 (file)
index 0000000..0042071
--- /dev/null
@@ -0,0 +1,73 @@
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_INCLUDES
+#define VPX_CODEC_DISABLE_COMPAT 1
+#include "vpx/vpx_encoder.h"
+#include "vpx/vp8cx.h"
+#define interface (vpx_codec_vp8_cx())
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_INCLUDES
+
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DIE_CODEC
+static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
+    const char *detail = vpx_codec_error_detail(ctx);
+
+    printf("%s: %s\n", s, vpx_codec_error(ctx));
+    if(detail)
+        printf("    %s\n",detail);
+    exit(EXIT_FAILURE);
+}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DIE_CODEC
+
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
+if(argc!=5)
+    die("Usage: %s <width> <height> <infile> <outfile>\n", argv[0]);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
+
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_DEF_CFG
+/* Populate encoder configuration */
+res = vpx_codec_enc_config_default(interface, &cfg, 0);
+if(res) {
+    printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
+    return EXIT_FAILURE;
+}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_DEF_CFG
+
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_SET_CFG
+/* Update the default configuration with our settings */
+cfg.rc_target_bitrate = width * height * cfg.rc_target_bitrate
+                        / cfg.g_w / cfg.g_h;
+cfg.g_w = width;
+cfg.g_h = height;
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_SET_CFG
+
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_INIT
+/* Initialize codec */
+if(vpx_codec_enc_init(&codec, interface, &cfg, 0))
+    die_codec(&codec, "Failed to initialize encoder");
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_INIT
+
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENCODE_FRAME
+frame_avail = read_frame(infile, &raw);
+if(vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt,
+                    1, flags, VPX_DL_REALTIME))
+    die_codec(&codec, "Failed to encode frame");
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENCODE_FRAME
+
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_FRAME
+case VPX_CODEC_CX_FRAME_PKT:
+    write_ivf_frame_header(outfile, pkt);
+    if(fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
+              outfile));
+    break;
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_FRAME
+
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DESTROY
+if(vpx_codec_destroy(&codec))
+    die_codec(&codec, "Failed to destroy codec");
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DESTROY
diff --git a/examples/error_resilient.txt b/examples/error_resilient.txt
new file mode 100644 (file)
index 0000000..e9d0949
--- /dev/null
@@ -0,0 +1,25 @@
+@TEMPLATE encoder_tmpl.c
+Error Resiliency Features
+=========================
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+This is an example demonstrating how to enable the error resiliency
+features of the codec.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+
+
+Configuration
+-------------
+Error resiliency is controlled by the g_error_resilient member of the
+configuration structure.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  ENC_SET_CFG2
+
+/* Enable error resilient mode */
+cfg.g_error_resilient = 1;
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_SET_CFG2
+
+
+Observing The Effects
+---------------------
+Use the `decode_with_drops` example to decode with frames 5-10 dropped.
+Compare the output for a file encoded with this example versus one
+encoded with the `simple_encoder` example.
diff --git a/examples/force_keyframe.txt b/examples/force_keyframe.txt
new file mode 100644 (file)
index 0000000..a9c16be
--- /dev/null
@@ -0,0 +1,28 @@
+@TEMPLATE encoder_tmpl.c
+Forcing A Keyframe
+==================
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+This is an example demonstrating how to control placement of keyframes
+on a frame-by-frame basis.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+
+
+Configuration
+-------------
+Keyframes can be forced by setting the VPX_EFLAG_FORCE_KF bit of the
+flags passed to `vpx_codec_control()`. In this example, we force a
+keyframe every 8 frames.
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  PER_FRAME_CFG
+if(!(frame_cnt & 7))
+    flags |= VPX_EFLAG_FORCE_KF;
+else
+    flags &= ~VPX_EFLAG_FORCE_KF;
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PER_FRAME_CFG
+
+
+Observing The Effects
+---------------------
+The output of the encoder examples shows a 'K' rather than a dot '.'
+when the encoder generates a keyframe. Note that every 8 frames a 'K'
+is output.
diff --git a/examples/gen_example_code.sh b/examples/gen_example_code.sh
new file mode 100755 (executable)
index 0000000..1133b49
--- /dev/null
@@ -0,0 +1,85 @@
+#!/bin/bash
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+
+# gen_example_code.sh
+
+self=$0
+
+die_usage() {
+    echo "Usage: $self <example.txt>"
+    exit 1
+}
+
+die() {
+    echo "$@"
+    exit 1
+}
+
+include_block() {
+    show_bar=$1
+    block_name=${line##*@}
+    indent=${line%%${block_name}}
+    indent=${#indent}
+    [ $indent -eq 1 ] && indent=0
+    local on_block
+    while IFS=$'\n' read -r t_line; do
+        case "$t_line" in
+            \~*\ ${block_name})
+                if [ "x$on_block" == "xyes" ]; then
+                    return 0;
+                else
+                    on_block=yes
+                fi
+                ;;
+            @DEFAULT)
+                if [ "x$on_block" == "xyes" ]; then
+                    include_block $show_bar < "${template%.c}.txt"
+                    return 0
+                fi
+                ;;
+            *)
+                if [ "x$on_block" == "xyes" ]; then
+                    local rem
+                    (( rem = 78 - indent ))
+                    case "$block_name" in
+                      \**) printf "%${indent}s * %s\n" "" "$t_line" ;;
+                        *)
+                            if [ "$show_bar" == "yes" ]; then
+                                printf "%${indent}s%-${rem}s//\n" "" "$t_line"
+                            else
+                                printf "%${indent}s%s\n" "" "$t_line"
+                            fi
+                            ;;
+                    esac
+                fi
+        esac
+    done
+    return 1
+}
+
+txt=$1
+[ -f "$txt" ] || die_usage
+read -r template < "$txt"
+case "$template" in
+    @TEMPLATE*) template=${txt%/*}/${template##@TEMPLATE } ;;
+    *) die "Failed to parse template name from '$template'" ;;
+esac
+
+while IFS=$'\n' read -r line; do
+    case "$line" in
+        @*) include_block yes < "$txt" \
+            || include_block < "${template%.c}.txt" \
+            #|| echo "WARNING: failed to find text for block $block_name" >&2
+            ;;
+        *)  echo "$line" ;;
+    esac
+done < "$template"
diff --git a/examples/gen_example_doxy.php b/examples/gen_example_doxy.php
new file mode 100755 (executable)
index 0000000..701bbd3
--- /dev/null
@@ -0,0 +1,224 @@
+#!/usr/bin/env php
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+<?php
+
+/* This script converts markdown to doxygen htmlonly syntax, nesting the
+ * content inside a \page. It expects input on stdin and outputs on stdout.
+ *
+ * Usage: gen_example_doxy.php <page_identifier> "<page description>"
+ */
+
+
+$geshi_path = dirname($argv[0])."/includes/geshi/geshi/"; // Language files
+$tmp_token  = '<!-- I wanna rock you, Chaka Khan -->';
+
+// Include prerequisites or exit
+if(!include_once('includes/PHP-Markdown-Extra-1.2.3/markdown.php'))
+  die("Cannot load Markdown transformer.\n");
+if(!include_once('includes/PHP-SmartyPants-1.5.1e/smartypants.php'))
+  die("Cannot load SmartyPants transformer.\n");
+if(!include_once('includes/geshi/geshi.php'))
+  die("Cannot load GeSHi transformer.\n");
+// ASCIIMathPHP?
+// HTML::Toc?
+// Tidy?
+// Prince?
+
+/**
+ *  Generate XHTML body
+ *
+ */
+
+$page_body = file_get_contents('php://stdin');
+
+// Transform any MathML expressions in the body text
+$regexp = '/\[\[(.*?)\]\]/'; // Double square bracket delimiters
+$page_body = preg_replace_callback($regexp, 'ASCIIMathPHPCallback', $page_body);
+
+// Fix ASCIIMathPHP's output
+$page_body = fix_asciiMath($page_body);
+
+// Wrap block-style <math> elements in <p>, since Markdown doesn't.
+$page_body = preg_replace('/\n(<math.*<\/math>)\n/', '<p class="eq_para">$1</p>', $page_body);
+
+// Transform the body text to HTML
+$page_body = Markdown($page_body);
+
+// Preprocess code blocks
+// Decode XML entities. GeSHi doesn't anticipate that
+// Markdown has already done this.
+$regexp = '|<pre><code>(.*?)<\/code><\/pre>|si';
+while (preg_match($regexp, $page_body, $matches) > 0)
+{
+  // Replace 1st match with token
+  $page_body = preg_replace($regexp, $tmp_token, $page_body, 1);
+  $block_new = $matches[1];
+  // Un-encode ampersand entities
+  $block_new = decode_markdown($block_new);
+  // Replace token with revised string
+  $page_body = preg_replace("|$tmp_token|", '<div class="codeblock">'.$block_new.'</div>', $page_body);
+}
+
+// Run GeSHi over code blocks
+$regexp   = '|<div class="codeblock">(.*?)<\/div>|si';
+$language = 'c';
+
+while (preg_match($regexp, $page_body, $matches))
+{
+  $geshi = new GeSHi($matches[1], $language);
+  $geshi->set_language_path($geshi_path);
+  $block_new = $geshi->parse_code();
+  // Strip annoying final newline
+  $block_new = preg_replace('|\n&nbsp;<\/pre>|', '</pre>' , $block_new);
+  // Remove style attribute (TODO: Research this in GeSHi)
+  $block_new = preg_replace('| style="font-family:monospace;"|', '' , $block_new);
+  $page_body = preg_replace($regexp, $block_new, $page_body, 1);
+  unset($geshi);    // Clean up
+}
+unset($block_new);  // Clean up
+
+// Apply typographic flourishes
+$page_body = SmartyPants($page_body);
+
+
+/**
+ *  Generate Doxygen Body
+ *
+ */
+$page_id=(isset($argv[1]))?$argv[1]:"";
+$page_desc=(isset($argv[2]))?$argv[2]:"";
+print "/*!\\page ".$page_id." ".$page_desc."\n\\htmlonly\n";
+print $page_body;
+print "\\endhtmlonly\n*/\n";
+
+// ---------------------------------------------------------
+
+/**
+ * decode_markdown()
+ *
+ * Markdown encodes '&', '<' and '>' in detected code
+ * blocks, as a convenience. This will restore the
+ * encoded entities to ordinary characters, since a
+ * downstream transformer (like GeSHi) may not
+ * anticipate this.
+ *
+ **********************************************************/
+
+function decode_markdown($input)
+{
+  $out = FALSE;
+
+  $entities   = array ('|&amp;|'
+                      ,'|&lt;|'
+                      ,'|&gt;|'
+                      );
+  $characters = array ('&'
+                      ,'<'
+                      ,'>'
+                      );
+  $input = preg_replace($entities, $characters, $input);
+  $out = $input;
+
+  return $out;
+}
+
+
+/**
+ * ASCIIMathML parser
+ * http://tinyurl.com/ASCIIMathPHP
+ *
+ * @PARAM mtch_arr array - Array of ASCIIMath expressions
+ *   as returned by preg_replace_callback([pattern]). First
+ *   dimension is the full matched string (with delimiter);
+ *   2nd dimension is the undelimited contents (typically
+ *   a capture group).
+ *
+ **********************************************************/
+
+function ASCIIMathPHPCallback($mtch_arr)
+{
+  $txt = trim($mtch_arr[1]);
+
+  include('includes/ASCIIMathPHP-2.0/ASCIIMathPHP-2.0.cfg.php');
+  require_once('includes/ASCIIMathPHP-2.0/ASCIIMathPHP-2.0.class.php');
+
+  static $asciimath;
+
+  if (!isset($asciimath)) $asciimath = new ASCIIMathPHP($symbol_arr);
+
+  $math_attr_arr = array('displaystyle' => 'true');
+
+  $asciimath->setExpr($txt);
+  $asciimath->genMathML($math_attr_arr);
+
+  return($asciimath->getMathML());
+}
+
+/**
+ * fix_asciiMath()
+ *
+ * ASCIIMath pretty-prints its output, with linefeeds
+ * and tabs. Causes unexpected behavior in some renderers.
+ * This flattens <math> blocks.
+ *
+ * @PARAM page_body str - The <body> element of an
+ * XHTML page to transform.
+ *
+ **********************************************************/
+
+function fix_asciiMath($page_body)
+{
+  $out = FALSE;
+
+  // Remove linefeeds and whitespace in <math> elements
+  $tags_bad  = array('/(<math.*?>)\n*\s*/'
+                    , '/(<mstyle.*?>)\n*\s*/'
+                    , '/(<\/mstyle>)\n*\s*/'
+                    , '/(<mrow.*?>)\n*\s*/'
+                    , '/(<\/mrow>)\n*\s*/'
+                    , '/(<mo.*?>)\n*\s*/'
+                    , '/(<\/mo>)\n*\s*/'
+                    , '/(<mi.*?>)\n*\s*/'
+                    , '/(<\/mi>)\n*\s*/'
+                    , '/(<mn.*?>)\n*\s*/'
+                    , '/(<\/mn>)\n*\s*/'
+                    , '/(<mtext.*?>)\n*\s*/'
+                    , '/(<\/mtext>)\n*\s*/'
+                    , '/(<msqrt.*?>)\n*\s*/'
+                    , '/(<\/msqrt>)\n*\s*/'
+                    , '/(<mfrac.*?>)\n*\s*/'
+                    , '/(<\/mfrac>)\n*\s*/'
+                    );
+  $tags_good = array( '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    );
+  $out = preg_replace($tags_bad, $tags_good, $page_body);
+
+  return $out;
+
+}
diff --git a/examples/gen_example_text.sh b/examples/gen_example_text.sh
new file mode 100755 (executable)
index 0000000..9a8703d
--- /dev/null
@@ -0,0 +1,84 @@
+#!/bin/bash
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+
+# gen_example_text.sh
+
+self=$0
+
+die_usage() {
+    echo "Usage: $self <example.txt>"
+    exit 1
+}
+
+die() {
+    echo "$@"
+    exit 1
+}
+
+include_block() {
+    local on_block
+    while IFS=$'\n' read -r t_line; do
+        case "$t_line" in
+            \~*\ ${block_name})
+                if [ "x$on_block" == "xyes" ]; then
+                    return 0;
+                else
+                    on_block=yes
+                fi
+                ;;
+            *)
+                if [ "x$on_block" == "xyes" ]; then
+                    echo "$t_line"
+                fi
+                ;;
+        esac
+    done
+    echo "WARNING: failed to find text for block $block_name" >&2
+    return 1
+}
+
+txt=$1
+[ -f "$txt" ] || die_usage
+read -r template < "$txt"
+case "$template" in
+    @TEMPLATE*) template=${txt%/*}/${template##@TEMPLATE } ;;
+    *) die "Failed to parse template name from '$template'" ;;
+esac
+
+fence="~~~~~~~~~"
+fence="${fence}${fence}"
+fence="${fence}${fence}"
+fence="${fence}${fence}"
+while IFS=$'\n' read -r line; do
+    case "$line" in
+        @TEMPLATE*)
+            template=${template##@TEMPLATE }
+            template=${template%.c}.txt
+            ;;
+        @DEFAULT)
+            include_block < "$template"
+            ;;
+        ~~~*)
+            block_name=${line##~* }
+            [ "$block_name" == "INTRODUCTION" ] || echo "$fence"
+            ;;
+        *)  echo "$line"
+            ;;
+    esac
+done < "$txt"
+
+echo
+echo "Putting It All Together"
+echo "======================="
+echo "${fence}"
+${self%/*}/gen_example_code.sh "${txt}"
+echo "${fence}"
diff --git a/examples/includes/ASCIIMathPHP-2.0/ASCIIMathPHP-2.0.cfg.php b/examples/includes/ASCIIMathPHP-2.0/ASCIIMathPHP-2.0.cfg.php
new file mode 100644 (file)
index 0000000..06f7979
--- /dev/null
@@ -0,0 +1,218 @@
+<?php
+
+$symbol_arr = array(
+
+// Greek symbols
+'alpha' => array( 'input'=>'alpha','tag'=>'mi', 'output'=>'&#' . hexdec('03B1') . ';'),
+'beta'  => array( 'input'=>'beta','tag'=>'mi', 'output'=>'&#' . hexdec('03B2') . ';'),
+'chi'   => array( 'input'=>'chi','tag'=>'mi', 'output'=>'&#' . hexdec('03C7') . ';'),
+'delta' => array( 'input'=>'delta','tag'=>'mi', 'output'=>'&#' . hexdec('03B4') . ';'),
+'Delta' => array( 'input'=>'Delta','tag'=>'mo', 'output'=>'&#' . hexdec('0394') . ';'),
+'epsi'  => array( 'input'=>'epsi','tag'=>'mi', 'output'=>'&#' . hexdec('03B5') . ';'),
+'varepsilon'    => array( 'input'=>'varepsilon','tag'=>'mi', 'output'=>'&#' . hexdec('025B') . ';'),
+'eta'   => array( 'input'=>'eta','tag'=>'mi', 'output'=>'&#' . hexdec('03B7') . ';'),
+'gamma' => array( 'input'=>'gamma','tag'=>'mi', 'output'=>'&#' . hexdec('03B3') . ';'),
+'Gamma' => array( 'input'=>'Gamma','tag'=>'mi', 'output'=>'&#' . hexdec('0393') . ';'),
+'iota'  => array( 'input'=>'iota','tag'=>'mi', 'output'=>'&#' . hexdec('03B9') . ';'),
+'kappa' => array( 'input'=>'kappa','tag'=>'mi', 'output'=>'&#' . hexdec('03BA') . ';'),
+'lambda'    => array( 'input'=>'lambda','tag'=>'mi', 'output'=>'&#' . hexdec('03BB') . ';'),
+'Lambda'    => array( 'input'=>'Lambda','tag'=>'mo', 'output'=>'&#' . hexdec('039B') . ';'),
+'mu'    => array( 'input'=>'mu','tag'=>'mi', 'output'=>'&#' . hexdec('03BC') . ';'),
+'nu'    => array( 'input'=>'nu','tag'=>'mi', 'output'=>'&#' . hexdec('03BD') . ';'),
+'omega' => array( 'input'=>'omega','tag'=>'mi', 'output'=>'&#' . hexdec('03C9') . ';'),
+'Omega' => array( 'input'=>'Omega','tag'=>'mo', 'output'=>'&#' . hexdec('03A9') . ';'),
+'phi'   => array( 'input'=>'phi','tag'=>'mi', 'output'=>'&#' . hexdec('03C6') . ';'),
+'varphi'    => array( 'input'=>'varphi','tag'=>'mi', 'output'=>'&#' . hexdec('03D5') . ';'),
+'Phi'   => array( 'input'=>'Phi','tag'=>'mo', 'output'=>'&#' . hexdec('03A6') . ';'),
+'pi'    => array( 'input'=>'pi','tag'=>'mi', 'output'=>'&#' . hexdec('03C0') . ';'),
+'Pi'    => array( 'input'=>'Pi','tag'=>'mo', 'output'=>'&#' . hexdec('03A0') . ';'),
+'psi'   => array( 'input'=>'psi','tag'=>'mi', 'output'=>'&#' . hexdec('03C8') . ';'),
+'rho'   => array( 'input'=>'rho','tag'=>'mi', 'output'=>'&#' . hexdec('03C1') . ';'),
+'sigma' => array( 'input'=>'sigma','tag'=>'mi', 'output'=>'&#' . hexdec('03C3') . ';'),
+'Sigma' => array( 'input'=>'Sigma','tag'=>'mo', 'output'=>'&#' . hexdec('03A3') . ';'),
+'tau'   => array( 'input'=>'tau','tag'=>'mi', 'output'=>'&#' . hexdec('03C4') . ';'),
+'theta' => array( 'input'=>'theta','tag'=>'mi', 'output'=>'&#' . hexdec('03B8') . ';'),
+'vartheta'  => array( 'input'=>'vartheta','tag'=>'mi', 'output'=>'&#' . hexdec('03D1') . ';'),
+'Theta' => array( 'input'=>'Theta','tag'=>'mo', 'output'=>'&#' . hexdec('0398') . ';'),
+'upsilon'   => array( 'input'=>'upsilon','tag'=>'mi', 'output'=>'&#' . hexdec('03C5') . ';'),
+'xi'    => array( 'input'=>'xi','tag'=>'mi', 'output'=>'&#' . hexdec('03BE') . ';'),
+'Xi'    => array( 'input'=>'alpha','tag'=>'mo', 'output'=>'&#' . hexdec('039E') . ';'),
+'zeta'  => array( 'input'=>'zeta','tag'=>'mi', 'output'=>'&#' . hexdec('03B6') . ';'),
+
+// Binary operation symbols
+'*'     => array( 'input'=>'*','tag'=>'mo', 'output'=>'&#' . hexdec('22C5') . ';'),
+'**'    => array( 'input'=>'**','tag'=>'mo', 'output'=>'&#' . hexdec('22C6') . ';'),
+'//'    => array( 'input'=>'//','tag'=>'mo', 'output'=>'/'),
+'\\\\'  => array( 'input'=>'\\\\','tag'=>'mo', 'output'=>'\\'),
+'xx'    => array( 'input'=>'xx','tag'=>'mo', 'output'=>'&#' . hexdec('00D7') . ';'),
+'-:'    => array( 'input'=>'-:','tag'=>'mo', 'output'=>'&#' . hexdec('00F7') . ';'),
+'@'     => array( 'input'=>'@','tag'=>'mo', 'output'=>'&#' . hexdec('2218') . ';'),
+'o+'    => array( 'input'=>'o+','tag'=>'mo', 'output'=>'&#' . hexdec('2295') . ';'),
+'ox'    => array( 'input'=>'ox','tag'=>'mo', 'output'=>'&#' . hexdec('2297') . ';'),
+'sum'   => array( 'input'=>'sum','tag'=>'mo', 'output'=>'&#' . hexdec('2211') . ';', 'underover'=>TRUE),
+'prod'  => array( 'input'=>'prod','tag'=>'mo', 'output'=>'&#' . hexdec('220F') . ';', 'underover'=>TRUE),
+'^^'    => array( 'input'=>'^^','tag'=>'mo', 'output'=>'&#' . hexdec('2227') . ';'),
+'^^^'   => array( 'input'=>'^^^','tag'=>'mo', 'output'=>'&#' . hexdec('22C0') . ';', 'underover'=>TRUE),
+'vv'    => array( 'input'=>'vv','tag'=>'mo', 'output'=>'&#' . hexdec('2228') . ';'),
+'vvv'   => array( 'input'=>'vvv','tag'=>'mo', 'output'=>'&#' . hexdec('22C1') . ';', 'underover'=>TRUE),
+'nn'    => array( 'input'=>'nn','tag'=>'mo', 'output'=>'&#' . hexdec('2229') . ';'),
+'nnn'   => array( 'input'=>'nnn','tag'=>'mo', 'output'=>'&#' . hexdec('22C5') . ';', 'underover'=>TRUE),
+'uu'    => array( 'input'=>'uu','tag'=>'mo', 'output'=>'&#' . hexdec('222A') . ';'),
+'uuu'   => array( 'input'=>'uuu','tag'=>'mo', 'output'=>'&#' . hexdec('22C3') . ';', 'underover'=>TRUE),
+
+// Binary relation symbols
+'!='    => array( 'input'=>'!=','tag'=>'mo', 'output'=>'&#' . hexdec('2260') . ';'),
+':='    => array( 'input'=>':=','tag'=>'mo', 'output'=>':=' ),              /* 2005-06-05 wes */
+'<'     => array( 'input'=>'<','tag'=>'mo', 'output'=>'&lt;'),
+'lt'    => array( 'input'=>'lt','tag'=>'mo', 'output'=>'&lt;'),             /* 2005-06-05 wes */
+'<='    => array( 'input'=>'<=','tag'=>'mo', 'output'=>'&#' . hexdec('2264') . ';'),
+'lt='   => array( 'input'=>'lt=','tag'=>'mo', 'output'=>'&#' . hexdec('2264') . ';'),
+'le'    => array( 'input'=>'le','tag'=>'mo', 'output'=>'&#' . hexdec('2264') . ';'),    /* 2005-06-05 wes */
+'>'     => array( 'input'=>'>','tag'=>'mo', 'output'=>'&gt;'),
+'>='    => array( 'input'=>'>=','tag'=>'mo', 'output'=>'&#' . hexdec('2265') . ';'),
+'qeq'   => array( 'input'=>'geq','tag'=>'mo', 'output'=>'&#' . hexdec('2265') . ';'),
+'-<'    => array( 'input'=>'-<','tag'=>'mo', 'output'=>'&#' . hexdec('227A') . ';'),
+'-lt'   => array( 'input'=>'-lt','tag'=>'mo', 'output'=>'&#' . hexdec('227A') . ';'),
+'>-'    => array( 'input'=>'>-','tag'=>'mo', 'output'=>'&#' . hexdec('227B') . ';'),
+'in'    => array( 'input'=>'in','tag'=>'mo', 'output'=>'&#' . hexdec('2208') . ';'),
+'!in'   => array( 'input'=>'!in','tag'=>'mo', 'output'=>'&#' . hexdec('2209') . ';'),
+'sub'   => array( 'input'=>'sub','tag'=>'mo', 'output'=>'&#' . hexdec('2282') . ';'),
+'sup'   => array( 'input'=>'sup','tag'=>'mo', 'output'=>'&#' . hexdec('2283') . ';'),
+'sube'  => array( 'input'=>'sube','tag'=>'mo', 'output'=>'&#' . hexdec('2286') . ';'),
+'supe'  => array( 'input'=>'supe','tag'=>'mo', 'output'=>'&#' . hexdec('2287') . ';'),
+'-='    => array( 'input'=>'-=','tag'=>'mo', 'output'=>'&#' . hexdec('2261') . ';'),
+'~='    => array( 'input'=>'~=','tag'=>'mo', 'output'=>'&#' . hexdec('2245') . ';'),
+'~~'    => array( 'input'=>'~~','tag'=>'mo', 'output'=>'&#' . hexdec('2248') . ';'),
+'prop'  => array( 'input'=>'prop','tag'=>'mo', 'output'=>'&#' . hexdec('221D') . ';'),
+
+// Logical symbols
+'and'   => array( 'input'=>'and','tag'=>'mtext', 'output'=>'and', 'space'=>'1ex'),
+'or'    => array( 'input'=>'or','tag'=>'mtext', 'output'=>'or', 'space'=>'1ex'),
+'not'   => array( 'input'=>'not','tag'=>'mo', 'output'=>'&#' . hexdec('00AC') . ';'),
+'=>'    => array( 'input'=>'=>','tag'=>'mo', 'output'=>'&#' . hexdec('21D2') . ';'),
+'if'    => array( 'input'=>'if','tag'=>'mo', 'output'=>'if', 'space'=>'1ex'),
+'iff'   => array( 'input'=>'iff','tag'=>'mo', 'output'=>'&#' . hexdec('21D4') . ';'),
+'<=>'   => array( 'input'=>'iff','tag'=>'mo', 'output'=>'&#' . hexdec('21D4') . ';'), /* 2005-06-07 wes */
+'AA'    => array( 'input'=>'AA','tag'=>'mo', 'output'=>'&#' . hexdec('2200') . ';'),
+'EE'    => array( 'input'=>'EE','tag'=>'mo', 'output'=>'&#' . hexdec('2203') . ';'),
+'_|_'   => array( 'input'=>'_|_','tag'=>'mo', 'output'=>'&#' . hexdec('22A5') . ';'),
+'TT'    => array( 'input'=>'TT','tag'=>'mo', 'output'=>'&#' . hexdec('22A4') . ';'),
+'|-'    => array( 'input'=>'|-','tag'=>'mo', 'output'=>'&#' . hexdec('22A2') . ';'),
+'|='    => array( 'input'=>'|=','tag'=>'mo', 'output'=>'&#' . hexdec('22A8') . ';'),
+
+// Miscellaneous symbols
+'ang'   => array('input'=>'ang','tag'=>'mo','output'=>'&#' . hexdec('2220') . ';'),
+'deg'   => array('input'=>'deg','tag'=>'mo','output'=>'&#' . hexdec('00B0') . ';'),
+'int'   => array( 'input'=>'int','tag'=>'mo', 'output'=>'&#' . hexdec('222B') . ';'),
+'dx'    => array( 'input'=>'dx','tag'=>'mi', 'output'=>'{:d x:}', 'definition'=>TRUE), /* 2005-06-11 wes */
+'dy'    => array( 'input'=>'dy','tag'=>'mi', 'output'=>'{:d y:}', 'definition'=>TRUE), /* 2005-06-11 wes */
+'dz'    => array( 'input'=>'dz','tag'=>'mi', 'output'=>'{:d z:}', 'definition'=>TRUE), /* 2005-06-11 wes */
+'dt'    => array( 'input'=>'dt','tag'=>'mi', 'output'=>'{:d t:}', 'definition'=>TRUE), /* 2005-06-11 wes */
+'oint'  => array( 'input'=>'oint','tag'=>'mo', 'output'=>'&#' . hexdec('222E') . ';'),
+'del'   => array( 'input'=>'del','tag'=>'mo', 'output'=>'&#' . hexdec('2202') . ';'),
+'grad'  => array( 'input'=>'grad','tag'=>'mo', 'output'=>'&#' . hexdec('2207') . ';'),
+'+-'    => array( 'input'=>'+-','tag'=>'mo', 'output'=>'&#' . hexdec('00B1') . ';'),
+'O/'    => array( 'input'=>'0/','tag'=>'mo', 'output'=>'&#' . hexdec('2205') . ';'),
+'oo'    => array( 'input'=>'oo','tag'=>'mo', 'output'=>'&#' . hexdec('221E') . ';'),
+'aleph' => array( 'input'=>'aleph','tag'=>'mo', 'output'=>'&#' . hexdec('2135') . ';'),
+'...'   => array( 'input'=>'int','tag'=>'mo', 'output'=>'...'),
+'~' => array( 'input'=>'!~','tag'=>'mo', 'output'=>'&#' . hexdec('0020') . ';'),
+'\\ '   => array( 'input'=>'~','tag'=>'mo', 'output'=>'&#' . hexdec('00A0') . ';'),
+'quad'  => array( 'input'=>'quad','tag'=>'mo', 'output'=>'&#' . hexdec('00A0') . ';&#' . hexdec('00A0') . ';'),
+'qquad' => array( 'input'=>'qquad','tag'=>'mo', 'output'=>  '&#' . hexdec('00A0') . ';&#' . hexdec('00A0') . ';&#' . hexdec('00A0') . ';'),
+'cdots' => array( 'input'=>'cdots','tag'=>'mo', 'output'=>'&#' . hexdec('22EF') . ';'),
+'vdots' => array( 'input'=>'vdots','tag'=>'mo', 'output'=>'&#' . hexdec('22EE') . ';'), /* 2005-06-11 wes */
+'ddots' => array( 'input'=>'ddots','tag'=>'mo', 'output'=>'&#' . hexdec('22F1') . ';'), /* 2005-06-11 wes */
+'diamond'   => array( 'input'=>'diamond','tag'=>'mo', 'output'=>'&#' . hexdec('22C4') . ';'),
+'square'    => array( 'input'=>'square','tag'=>'mo', 'output'=>'&#' . hexdec('25A1') . ';'),
+'|_'    => array( 'input'=>'|_','tag'=>'mo', 'output'=>'&#' . hexdec('230A') . ';'),
+'_|'    => array( 'input'=>'_|','tag'=>'mo', 'output'=>'&#' . hexdec('230B') . ';'),
+'|~'    => array( 'input'=>'|~','tag'=>'mo', 'output'=>'&#' . hexdec('2308') . ';'),
+'~|'    => array( 'input'=>'~|','tag'=>'mo', 'output'=>'&#' . hexdec('2309') . ';'),
+'CC'    => array( 'input'=>'CC','tag'=>'mo', 'output'=>'&#' . hexdec('2102') . ';'),
+'NN'    => array( 'input'=>'NN','tag'=>'mo', 'output'=>'&#' . hexdec('2115') . ';'),
+'QQ'    => array( 'input'=>'QQ','tag'=>'mo', 'output'=>'&#' . hexdec('211A') . ';'),
+'RR'    => array( 'input'=>'RR','tag'=>'mo', 'output'=>'&#' . hexdec('211D') . ';'),
+'ZZ'    => array( 'input'=>'ZZ','tag'=>'mo', 'output'=>'&#' . hexdec('2124') . ';'),
+
+// Standard functions
+'lim'   => array( 'input'=>'lim','tag'=>'mo', 'output'=>'lim', 'underover'=>TRUE),
+'Lim'   => array( 'input'=>'Lim','tag'=>'mo', 'output'=>'Lim', 'underover'=>TRUE), /* 2005-06-11 wes */
+'sin'   => array( 'input'=>'sin','tag'=>'mo', 'output'=>'sin', 'unary'=>TRUE, 'func'=>TRUE),
+'cos'   => array( 'input'=>'cos', 'tag'=>'mo', 'output'=>'cos', 'unary'=>TRUE, 'func'=>TRUE),
+'tan'   => array( 'input'=>'tan', 'tag'=>'mo', 'output'=>'tan', 'unary'=>TRUE, 'func'=>TRUE),
+'arcsin'    => array( 'input'=>'arcsin','tag'=>'mo', 'output'=>'arcsin', 'unary'=>TRUE, 'func'=>TRUE), //2006-9-7 DL
+'arccos'    => array( 'input'=>'arccos', 'tag'=>'mo', 'output'=>'arccos', 'unary'=>TRUE, 'func'=>TRUE), //2006-9-7 DL
+'arctan'    => array( 'input'=>'arctan', 'tag'=>'mo', 'output'=>'arctan', 'unary'=>TRUE, 'func'=>TRUE), //2006-9-7 DL
+'sinh'  => array( 'input'=>'sinh','tag'=>'mo', 'output'=>'sinh', 'unary'=>TRUE, 'func'=>TRUE),
+'cosh'  => array( 'input'=>'cosh', 'tag'=>'mo', 'output'=>'cosh', 'unary'=>TRUE, 'func'=>TRUE),
+'tanh'  => array( 'input'=>'tanh', 'tag'=>'mo', 'output'=>'tanh', 'unary'=>TRUE, 'func'=>TRUE),
+'cot'   => array( 'input'=>'cot','tag'=>'mo', 'output'=>'cot', 'unary'=>TRUE, 'func'=>TRUE),
+'sec'   => array( 'input'=>'sec', 'tag'=>'mo', 'output'=>'sec', 'unary'=>TRUE, 'func'=>TRUE),
+'csc'   => array( 'input'=>'csc', 'tag'=>'mo', 'output'=>'csc', 'unary'=>TRUE, 'func'=>TRUE),
+'coth'  => array( 'input'=>'coth','tag'=>'mo', 'output'=>'coth', 'unary'=>TRUE, 'func'=>TRUE),
+'sech'  => array( 'input'=>'sech', 'tag'=>'mo', 'output'=>'sech', 'unary'=>TRUE, 'func'=>TRUE),
+'csch'  => array( 'input'=>'csch', 'tag'=>'mo', 'output'=>'csch', 'unary'=>TRUE, 'func'=>TRUE),
+'log'   => array( 'input'=>'log', 'tag'=>'mo', 'output'=>'log', 'unary'=>TRUE, 'func'=>TRUE),
+'ln'    => array( 'input'=>'ln', 'tag'=>'mo', 'output'=>'ln', 'unary'=>TRUE, 'func'=>TRUE),
+'det'   => array( 'input'=>'det', 'tag'=>'mo', 'output'=>'det', 'unary'=>TRUE, 'func'=>TRUE),
+'dim'   => array( 'input'=>'dim', 'tag'=>'mo', 'output'=>'dim'),
+'mod'   => array( 'input'=>'mod', 'tag'=>'mo', 'output'=>'mod'),
+'gcd'   => array( 'input'=>'gcd', 'tag'=>'mo', 'output'=>'gcd', 'unary'=>TRUE, 'func'=>TRUE),
+'lcm'   => array( 'input'=>'lcm', 'tag'=>'mo', 'output'=>'lcm', 'unary'=>TRUE, 'func'=>TRUE),
+'lub'   => array( 'input'=>'lub', 'tag'=>'mo', 'output'=>'lub'), /* 2005-06-11 wes */
+'glb'   => array( 'input'=>'glb', 'tag'=>'mo', 'output'=>'glb'), /* 2005-06-11 wes */
+'min'   => array( 'input'=>'min', 'tag'=>'mo', 'output'=>'min', 'underover'=>TRUE), /* 2005-06-11 wes */
+'max'   => array( 'input'=>'max', 'tag'=>'mo', 'output'=>'max', 'underover'=>TRUE), /* 2005-06-11 wes */
+'f' => array( 'input'=>'f','tag'=>'mi', 'output'=>'f', 'unary'=>TRUE, 'func'=>TRUE), //2006-9-7 DL
+'g' => array( 'input'=>'g', 'tag'=>'mi', 'output'=>'g', 'unary'=>TRUE, 'func'=>TRUE), //2006-9-7 DL
+
+// Arrows
+'uarr'  => array( 'input'=>'uarr', 'tag'=>'mo', 'output'=>'&#' . hexdec('2191') . ';'),
+'darr'  => array( 'input'=>'darr', 'tag'=>'mo', 'output'=>'&#' . hexdec('2193') . ';'),
+'rarr'  => array( 'input'=>'rarr', 'tag'=>'mo', 'output'=>'&#' . hexdec('2192') . ';'),
+'->'    => array( 'input'=>'->', 'tag'=>'mo', 'output'=>'&#' . hexdec('2192') . ';'),
+'|->'   => array( 'input'=>'|->', 'tag'=>'mo', 'output'=>'&#' . hexdec('21A6') . ';'), /* 2005-06-11 wes */
+'larr'  => array( 'input'=>'larr', 'tag'=>'mo', 'output'=>'&#' . hexdec('2190') . ';'),
+'harr'  => array( 'input'=>'harr', 'tag'=>'mo', 'output'=>'&#' . hexdec('2194') . ';'),
+'rArr'  => array( 'input'=>'rArr', 'tag'=>'mo', 'output'=>'&#' . hexdec('21D2') . ';'),
+'lArr'  => array( 'input'=>'lArr', 'tag'=>'mo', 'output'=>'&#' . hexdec('21D0') . ';'),
+'hArr'  => array( 'input'=>'hArr', 'tag'=>'mo', 'output'=>'&#' . hexdec('21D4') . ';'),
+
+// Commands with argument
+'sqrt'  => array( 'input'=>'sqrt', 'tag'=>'msqrt', 'output'=>'sqrt', 'unary'=>TRUE ),
+'root'  => array( 'input'=>'root', 'tag'=>'mroot', 'output'=>'root', 'binary'=>TRUE ),
+'frac'  => array( 'input'=>'frac', 'tag'=>'mfrac', 'output'=>'/', 'binary'=>TRUE),
+'/'     => array( 'input'=>'/', 'tag'=>'mfrac', 'output'=>'/', 'infix'=>TRUE),
+'_'     => array( 'input'=>'_', 'tag'=>'msub', 'output'=>'_', 'infix'=>TRUE),
+'^'     => array( 'input'=>'^', 'tag'=>'msup', 'output'=>'^', 'infix'=>TRUE),
+'hat'   => array( 'input'=>'hat', 'tag'=>'mover', 'output'=>'&#' . hexdec('005E') . ';', 'unary'=>TRUE, 'acc'=>TRUE),
+'bar'   => array( 'input'=>'bar', 'tag'=>'mover', 'output'=>'&#' . hexdec('00AF') . ';', 'unary'=>TRUE, 'acc'=>TRUE),
+'vec'   => array( 'input'=>'vec', 'tag'=>'mover', 'output'=>'&#' . hexdec('2192') . ';', 'unary'=>TRUE, 'acc'=>TRUE),
+'dot'   => array( 'input'=>'dot', 'tag'=>'mover', 'output'=>'.', 'unary'=>TRUE, 'acc'=>TRUE),
+'ddot'  => array( 'input'=>'ddot', 'tag'=>'mover', 'output'=>'..', 'unary'=>TRUE, 'acc'=>TRUE),
+'ul'    => array( 'input'=>'ul', 'tag'=>'munder', 'output'=>'&#' . hexdec('0332') . ';', 'unary'=>TRUE, 'acc'=>TRUE),
+'avec'  => array( 'input'=>'avec', 'tag'=>'munder', 'output'=>'~', 'unary'=>TRUE, 'acc'=>TRUE),
+'text'  => array( 'input'=>'text', 'tag'=>'mtext', 'output'=>'text', 'unary'=>TRUE),
+'mbox'  => array( 'input'=>'mbox', 'tag'=>'mtext', 'output'=>'mbox', 'unary'=>TRUE),
+'"' => array( 'input'=>'"', 'tag'=>'mtext','output'=>'mbox', 'unary'=>TRUE),
+
+/* 2005-06-05 wes: added stackrel */
+'stackrel' => array( 'input'=>'stackrel', 'tag'=>'mover', 'output'=>'stackrel', 'binary'=>TRUE),
+
+// Grouping brackets
+'('     => array( 'input'=>'(', 'tag'=>'mo', 'output'=>'(', 'left_bracket'=>TRUE),
+')'     => array( 'input'=>')', 'tag'=>'mo', 'output'=>')', 'right_bracket'=>TRUE),
+'['     => array( 'input'=>'[', 'tag'=>'mo', 'output'=>'[', 'left_bracket'=>TRUE),
+']'     => array( 'input'=>']', 'tag'=>'mo', 'output'=>']', 'right_bracket'=>TRUE),
+'{'     => array( 'input'=>'{', 'tag'=>'mo', 'output'=>'{', 'left_bracket'=>TRUE),
+'}'     => array( 'input'=>'}', 'tag'=>'mo', 'output'=>'}', 'right_bracket'=>TRUE),
+'(:'    => array( 'input'=>'(:', 'tag'=>'mo', 'output'=>'&#' . hexdec('2329') . ';', 'left_bracket'=>TRUE),
+':)'    => array( 'input'=>':)', 'tag'=>'mo', 'output'=>'&#' . hexdec('232A') . ';', 'right_bracket'=>TRUE),
+'{:'    => array( 'input'=>'{:', 'tag'=>'mo', 'output'=>'{:', 'left_bracket'=>TRUE, 'invisible'=>TRUE),
+':}'    => array( 'input'=>':}', 'tag'=>'mo', 'output'=>':}', 'right_bracket'=>TRUE ,'invisible'=>TRUE),
+'<<'    => array( 'input'=>'<<', 'tag'=>'mo', 'output'=>'&#' . hexdec('2329') . ';', 'left_bracket'=>TRUE), // 2005-06-07 wes
+'>>'    => array( 'input'=>'>>', 'tag'=>'mo', 'output'=>'&#' . hexdec('232A') . ';', 'right_bracket'=>TRUE) // 2005-06-07 wes
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/ASCIIMathPHP-2.0/ASCIIMathPHP-2.0.class.php b/examples/includes/ASCIIMathPHP-2.0/ASCIIMathPHP-2.0.class.php
new file mode 100644 (file)
index 0000000..5fb1060
--- /dev/null
@@ -0,0 +1,1119 @@
+<?php
+
+/****
+ * ASCIIMathPHP and associated classes:
+ * -- XMLNode
+ * -- MathMLNode extends XMLNode
+ *
+ * These classes are a PHP port of ASCIIMath
+ * Version 1.3 Feb 19 2004, (c) Peter Jipsen http://www.chapman.edu/~jipsen
+ *
+ * ASCIIMathPHP Version 1.11, 26 April 2006, (c) Kee-Lin Steven Chan (kc56@cornell.edu)
+ *
+ * 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 (at http://www.gnu.org/copyleft/gpl.html)
+ * for more details.
+ *
+ * ChangeLog
+ *
+ * Ver 2.0
+ * -- PHP5 only version of ASCIIMathPHP
+ *
+ * Ver 1.12.1
+ * -- Included the missing setCurrExpr() method
+ *
+ * Ver 1.12
+ * -- Added changes that David Lippman <DLippman@pierce.ctc.edu> made to bring ASCIIMathPHP up to
+ * ASCIIMath 1.4.7 functionality.
+ * -- Added parseIntExpr, for intermediate expression parsing rule, allowing x^2/x^3 to render as (x^2)/(x^3)
+ * -- Added quotes as another way of designating text; "hello" is equivalent to text(hello)
+ * -- Added FUNC designator to allow sin, cos, etc to act as functions, so sin(x)/x renders as {sin(x)}/x
+ *
+ * Ver 1.11
+ * -- Fixed bug that stopped script execution for incomplete expressions
+ * -- Changed the algorithm for parsing expressions so that it matches the longest string possible (greedy)
+ *
+ * Ver 1.10
+ * -- Added definition support
+ * -- Added stackrel support
+ * -- Added a bunch of different symbols etc. >>, << and definitions like dx, dy, dz etc.
+ *
+ * Ver 1.02
+ * -- Fixed bug with mbox and text
+ * -- Fixed spacing bug with mbox and text
+ *
+ * Ver 1.01
+ * -- Fixed Bug that did not parse symbols greater than a single character
+ * correctly when appearing at end of expression.
+ *
+ ***/
+
+class XMLNode
+{
+    // Private variables
+    var $_id;
+    var $_name;
+    var $_content;
+    var $_mt_elem_flg;
+    var $_attr_arr;
+    var $_child_arr;
+    var $_nmspc;
+    var $_nmspc_alias;
+    var $_parent_id;
+    var $_parent_node;
+
+    function XMLNode($id = NULL)
+    {
+        $this->_id = isset($id) ? $id : md5(uniqid(rand(),1));
+        $this->_name = '';
+        $this->_content = '';
+        $this->_mt_elem_flg = FALSE;
+        $this->_attr_arr = array();
+        $this->_child_arr = array();
+        $this->_nmspc = '';
+        $this->_nmspc_alias = '';
+        $this->_parent_id = FALSE;
+        $this->_parent_node = NULL;
+    }
+
+    function addChild(&$node)
+    {
+        $this->_child_arr[$node->getId()] = $node;
+        $node->setParentId($this->_id);
+        $node->setParentNode($this);
+    }
+
+    function addChildArr(&$node_arr)
+    {
+        $key_arr = array_keys($node_arr);
+        $num_key = count($key_arr);
+
+        for ($i = 0; $i < $num_key; $i++) {
+            $node = $node_arr[$key_arr[$i]];
+            $this->addChild($node);
+        }
+    }
+
+    function insertChildBefore($idx,&$node)
+    {
+        $key_arr = array_keys($this->_child_arr);
+        $num_key = count($key_arr);
+        $tmp_arr = arry();
+
+        for ($i = 0;$i < $num_key;$i++) {
+            if ($i == $idx) {
+                $tmp_arr[$node->getId()] = $node;
+            }
+            $tmp_arr[$key_arr[$i]] = $this->_child_arr[$key_arr[$i]];
+        }
+        $this->_child_arr = $tmp_arr;
+    }
+
+    function insertChildAfter($idx,&$node)
+    {
+        $key_arr = array_keys($this->_child_arr);
+        $num_key = count($key_arr);
+        $tmp_arr = arry();
+
+        for ($i = 0;$i < $num_key;$i++) {
+            $tmp_arr[$key_arr[$i]] = $this->_child_arr[$key_arr[$i]];
+            if ($i == $idx) {
+                $tmp_arr[$node->getId()] = $node;
+            }
+        }
+        $this->_child_arr = $tmp_arr;
+    }
+
+    function setId($id)
+    {
+        $this->_id = $id;
+    }
+
+    function setName($name)
+    {
+        $this->_name = $name;
+    }
+
+    function setNamepace($nmspc)
+    {
+        $this->_nmspc = $nmspc;
+    }
+
+    function setNamespaceAlias($nmspc_alias)
+    {
+        $this->_nmspc_alias = $nmspc_alias;
+    }
+
+    function setContent($content)
+    {
+        $this->_content = $content;
+    }
+
+    function setEmptyElem($mt_elem_flg)
+    {
+        $this->_mt_elem_flg = $mt_elem_flg;
+    }
+
+    function setAttr($attr_nm,$attr_val)
+    {
+        $this->_attr_arr[$attr_nm] = $attr_val;
+    }
+
+    function setAttrArr($attr_arr)
+    {
+        $this->_attr_arr = $attr_arr;
+    }
+
+    function setParentId($id)
+    {
+        $this->_parent_id = $id;
+    }
+
+    function setParentNode(&$node)
+    {
+        $this->_parent_node = $node;
+    }
+
+    function getId()
+    {
+        return($this->_id);
+    }
+
+    function getName()
+    {
+        return($this->_name);
+    }
+
+    function getNamespace()
+    {
+        return($this->_nmspc);
+    }
+
+    function getNamespaceAlias()
+    {
+        return($this->_nmspc_alias);
+    }
+
+    function getContent()
+    {
+        return($this->_content);
+    }
+
+    function getAttr($attr_nm)
+    {
+        if (isset($this->_attr_arr[$attr_nm])) {
+            return($this->_attr_arr[$attr_nm]);
+        } else {
+            return(NULL);
+        }
+    }
+
+    function getAttrArr()
+    {
+        return($this->_attr_arr);
+    }
+
+    function getParentId()
+    {
+        return($this->parent_id);
+    }
+
+    function getParentNode()
+    {
+        return($this->_parent_node);
+    }
+
+    function getChild($id)
+    {
+        if (isset($this->_child_arr[$id])) {
+            return($this->_child_arr[$id]);
+        } else {
+            return(FALSE);
+        }
+    }
+
+    function getFirstChild()
+    {
+        $id_arr = array_keys($this->_child_arr);
+        $num_child = count($id_arr);
+
+        if ($num_child > 0) {
+            return($this->_child_arr[$id_arr[0]]);
+        } else {
+            return(FALSE);
+        }
+    }
+
+    function getLastChild()
+    {
+        $id_arr = array_keys($this->_child_arr);
+        $num_child = count($id_arr);
+
+        if ($num_child > 0) {
+            return($this->_child_arr[$id_arr[$num_child - 1]]);
+        } else {
+            return(FALSE);
+        }
+    }
+
+    function getChildByIdx($idx)
+    {
+        $id_arr = array_keys($this->_child_arr);
+
+        if (isset($this->_child_arr[$id_arr[$idx]])) {
+            return($this->_child_arr[$id_arr[$idx]]);
+        } else {
+            return(FALSE);
+        }
+    }
+
+    function getNumChild()
+    {
+        return(count($this->_child_arr));
+    }
+
+    function removeChild($id)
+    {
+        unset($this->_child_arr[$id]);
+    }
+
+    function removeChildByIdx($idx)
+    {
+        $key_arr = array_keys($this->_child_arr);
+        unset($this->_child_arr[$key_arr[$idx]]);
+    }
+
+    function removeFirstChild()
+    {
+        $key_arr = array_keys($this->_child_arr);
+        unset($this->_child_arr[$key_arr[0]]);
+    }
+
+    function removeLastChild()
+    {
+        $key_arr = array_keys($this->_child_arr);
+        unset($this->_child_arr[$key_arr[count($key_arr)-1]]);
+    }
+
+    function dumpXML($indent_str = "\t")
+    {
+        $attr_txt = $this->_dumpAttr();
+        $name = $this->_dumpName();
+        $xmlns = $this->_dumpXmlns();
+        $lvl = $this->_getCurrentLevel();
+        $indent = str_pad('',$lvl,$indent_str);
+
+        if ($this->_mt_elem_flg) {
+            $tag = "$indent<$name$xmlns$attr_txt />";
+            return($tag);
+        } else {
+            $key_arr = array_keys($this->_child_arr);
+            $num_child = count($key_arr);
+
+            $tag = "$indent<$name$xmlns$attr_txt>$this->_content";
+
+            for ($i = 0;$i < $num_child;$i++) {
+                $node = $this->_child_arr[$key_arr[$i]];
+
+                $child_txt = $node->dumpXML($indent_str);
+                $tag .= "\n$child_txt";
+            }
+
+            $tag .= ($num_child > 0 ? "\n$indent</$name>" : "</$name>");
+            return($tag);
+        }
+    }
+
+    function _dumpAttr()
+    {
+        $id_arr = array_keys($this->_attr_arr);
+        $id_arr_cnt = count($id_arr);
+        $attr_txt = '';
+
+        for($i = 0;$i < $id_arr_cnt;$i++) {
+            $key = $id_arr[$i];
+            $attr_txt .= " $key=\"{$this->_attr_arr[$key]}\"";
+        }
+
+        return($attr_txt);
+    }
+
+    function _dumpName()
+    {
+        $alias = $this->getNamespaceAlias();
+        if ($alias == '') {
+            return($this->getName());
+        } else {
+            return("$alias:" . $this->getName());
+        }
+    }
+
+    function _dumpXmlns()
+    {
+        $nmspc = $this->getNamespace();
+        $alias = $this->getNamespaceAlias();
+
+        if ($nmspc != '') {
+            if ($alias == '') {
+                return(" xmlns=\"" . $nmspc . "\"");
+            } else {
+                return(" xmlns:$alias=\"" . $nmspc . "\"");
+            }
+        } else {
+            return('');
+        }
+    }
+
+    function _getCurrentLevel()
+    {
+        if ($this->_parent_id === FALSE) {
+            return(0);
+        } else {
+            $node = $this->getParentNode();
+            $lvl = $node->_getCurrentLevel();
+            $lvl++;
+            return($lvl);
+        }
+    }
+}
+
+class MathMLNode extends XMLNode
+{
+    function MathMLNode($id = NULL)
+    {
+        parent::XMLNode($id);
+    }
+
+    function removeBrackets()
+    {
+        if ($this->_name == 'mrow') {
+            if ($c_node_0 = $this->getFirstChild()) {
+                $c_node_0->isLeftBracket() ? $this->removeFirstChild() : 0;
+            }
+
+            if ($c_node_0 = $this->getLastChild()) {
+                $c_node_0->isRightBracket() ? $this->removeLastChild() : 0;
+            }
+        }
+    }
+
+    function isLeftBracket()
+    {
+        switch ($this->_content) {
+            case '{':
+            case '[':
+            case '(':
+                return(TRUE);
+                break;
+        }
+        return(FALSE);
+    }
+
+    function isRightBracket()
+    {
+        switch ($this->_content) {
+            case '}':
+            case ']':
+            case ')':
+                return(TRUE);
+                break;
+        }
+        return(FALSE);
+    }
+}
+
+class ASCIIMathPHP
+{
+    var $_expr;
+    var $_curr_expr;
+    var $_prev_expr;
+    var $_symbol_arr;
+    var $_node_arr;
+    var $_node_cntr;
+
+    function ASCIIMathPHP($symbol_arr,$expr = NULL)
+    {
+        $this->_symbol_arr = $symbol_arr;
+        if (isset($expr)) {
+            $this->setExpr($expr);
+        }
+    }
+
+    /**
+     * Returns an empty node (containing a non-breaking space) 26-Apr-2006
+     *
+     * Used when an expression is incomplete
+     *
+     * @return object
+     *
+     * @access private
+     */
+    function emptyNode()
+    {
+        $tmp_node = $this->createNode();
+        $tmp_node->setName('mn');
+        $tmp_node->setContent('&#' . hexdec('200B') . ';');
+        return $tmp_node;
+    }
+
+    function pushExpr($prefix) // 2005-06-11 wes
+    {
+        $this->_curr_expr = $prefix . $this->_curr_expr;
+    }
+
+    function setExpr($expr)
+    {
+        $this->_expr = $expr;
+        $this->_curr_expr = $expr;
+        $this->_prev_expr = $expr;
+
+        $this->_node_arr = array();
+        $this->_node_cntr = 0;
+    }
+
+    function genMathML($attr_arr = NULL)
+    {
+        // <math> node
+        $node_0 = $this->createNode();
+        $node_0->setName('math');
+        $node_0->setNamepace('http://www.w3.org/1998/Math/MathML');
+
+        // <mstyle> node
+        if (isset($attr_arr)) {
+            $node_1 = $this->createNode();
+            $node_1->setName('mstyle');
+            $node_1->setAttrArr($attr_arr);
+
+            $node_arr = $this->parseExpr();
+
+            $node_1->addChildArr($node_arr);
+            $node_0->addChild($node_1);
+        } else {
+            $node_arr = $this->parseExpr();
+            $node_0->addChildArr($node_arr);
+        }
+
+        return TRUE;
+    }
+
+    /*
+    function  mergeNodeArr(&$node_arr_0,&$node_arr_1)
+    {
+        $key_arr_0 = array_keys($node_arr_0);
+        $key_arr_1 = array_keys($node_arr_1);
+
+        $num_key_0 = count($key_arr_0);
+        $num_key_1 = count($key_arr_1);
+
+        $merge_arr = array();
+
+        for ($i = 0;$i < $num_key_0;$i++) {
+            $merge_arr[$key_arr_0[$i]] = $node_arr_0[$key_arr_0[$i]];
+        }
+
+        for ($j = 0;$j < $num_key_1;$i++) {
+            $merge_arr[$key_arr_1[$i]] = $node_arr_1[$key_arr_1[$i]];
+        }
+
+        return($merge_arr);
+    }
+    */
+
+    //Broken out of parseExpr Sept 7, 2006 David Lippman for
+    //ASCIIMathML 1.4.7 compatibility
+    function  parseIntExpr()
+    {
+        $sym_0 = $this->getSymbol();
+        $node_0 = $this->parseSmplExpr();
+        $sym = $this->getSymbol();
+
+        if (isset($sym['infix']) && $sym['input'] != '/') {
+            $this->chopExpr($sym['symlen']);
+            $node_1 = $this->parseSmplExpr();
+
+            if ($node_1 === FALSE) { //show box in place of missing argument
+                $node_1 = $this->emptyNode();//??
+            } else {
+                $node_1->removeBrackets();
+            }
+
+            // If 'sub' -- subscript
+            if ($sym['input'] == '_') {
+
+                $sym_1 = $this->getSymbol();
+
+                // If 'sup' -- superscript
+                if ($sym_1['input'] == '^') {
+                    $this->chopExpr($sym_1['symlen']);
+                    $node_2 = $this->parseSmplExpr();
+                    $node_2->removeBrackets();
+
+                    $node_3 = $this->createNode();
+                    $node_3->setName(isset($sym_0['underover']) ? 'munderover' : 'msubsup');
+                    $node_3->addChild($node_0);
+                    $node_3->addChild($node_1);
+                    $node_3->addChild($node_2);
+
+                    $node_4 = $this->createNode();
+                    $node_4->setName('mrow');
+                    $node_4->addChild($node_3);
+
+                    return $node_4;
+                } else {
+                    $node_2 = $this->createNode();
+                    $node_2->setName(isset($sym_0['underover']) ? 'munder' : 'msub');
+                    $node_2->addChild($node_0);
+                    $node_2->addChild($node_1);
+
+                    return $node_2;
+                }
+            } else {
+                $node_2 = $this->createNode();
+                $node_2->setName($sym['tag']);
+                $node_2->addChild($node_0);
+                $node_2->addChild($node_1);
+
+                return($node_2);
+            }
+        } elseif ($node_0 !== FALSE) {
+            return($node_0);
+        } else {
+            return $this->emptyNode();
+        }
+
+    }
+
+    function  parseExpr()
+    {
+        // Child/Fragment array
+        $node_arr = array();
+
+        // Deal whole expressions like 'ax + by + c = 0' etc.
+        do {
+            $sym_0 = $this->getSymbol();
+            $node_0 = $this->parseIntExpr();
+            $sym = $this->getSymbol();
+            // var_dump($sym);
+
+            if (isset($sym['infix']) && $sym['input'] == '/') {
+                $this->chopExpr($sym['symlen']);
+                $node_1 = $this->parseIntExpr();
+
+                if ($node_1 === FALSE) { //should show box in place of missing argument
+                    $node_1 = $this->emptyNode();
+                    continue;
+                }
+
+                $node_1->removeBrackets();
+
+                // If 'div' -- divide
+                $node_0->removeBrackets();
+                $node_2 = $this->createNode();
+                $node_2->setName($sym['tag']);
+                $node_2->addChild($node_0);
+                $node_2->addChild($node_1);
+                $node_arr[$node_2->getId()] = $node_2;
+
+            } elseif ($node_0 !== FALSE) {
+                $node_arr[$node_0->getId()] = $node_0;
+            }
+        } while (!isset($sym['right_bracket']) && $sym !== FALSE && $sym['output'] != '');
+
+        //var_dump($sym);
+        // Possibly to deal with matrices
+        if (isset($sym['right_bracket'])) {
+            $node_cnt = count($node_arr);
+            $key_node_arr = array_keys($node_arr);
+
+            if ($node_cnt > 1) {
+                $node_5 = $node_arr[$key_node_arr[$node_cnt-1]];
+                $node_6 = $node_arr[$key_node_arr[$node_cnt-2]];
+            } else {
+                $node_5 = FALSE;
+                $node_6 = FALSE;
+            }
+
+            // Dealing with matrices
+            if ($node_5 !== FALSE && $node_6 !== FALSE &&
+                $node_cnt > 1 &&
+                $node_5->getName() == 'mrow' &&
+                $node_6->getName() == 'mo' &&
+                $node_6->getContent() == ',') {
+
+                // Checking if Node 5 has a LastChild
+                if ($node_7 = $node_5->getLastChild()) {
+                    $node_7_cntnt = $node_7->getContent();
+                } else {
+                    $node_7_cntnt = FALSE;
+                }
+
+                // If there is a right bracket
+                if ($node_7 !== FALSE && ($node_7_cntnt == ']' || $node_7_cntnt == ')')) {
+
+                    // Checking if Node 5 has a firstChild
+                    if ($node_8 = $node_5->getFirstChild()) {
+                        $node_8_cntnt = $node_8->getContent();
+                    } else {
+                        $node_8_cntnt = FALSE;
+                    }
+
+                    // If there is a matching left bracket
+                    if ($node_8 !== FALSE &&
+                        (($node_8_cntnt == '(' && $node_7_cntnt == ')' && $sym['output'] != '}') ||
+                        ($node_8_cntnt == '[' && $node_7_cntnt == ']'))) {
+
+                        $is_mtrx_flg = TRUE;
+                        $comma_pos_arr = array();
+
+                        $i = 0;
+
+                        while ($i < $node_cnt && $is_mtrx_flg) {
+                            $tmp_node = $node_arr[$key_node_arr[$i]];
+
+                            if($tmp_node_first = $tmp_node->getFirstChild()) {
+                                $tnfc = $tmp_node_first->getContent();
+                            } else {
+                                $tnfc = FALSE;
+                            }
+
+                            if($tmp_node_last = $tmp_node->getLastChild()) {
+                                $tnlc = $tmp_node_last->getContent();
+                            } else {
+                                $tnlc = FALSE;
+                            }
+
+                            if (isset($key_node_arr[$i+1])) {
+                                $next_tmp_node = $node_arr[$key_node_arr[$i+1]];
+                                $ntnn = $next_tmp_node->getName();
+                                $ntnc = $next_tmp_node->getContent();
+                            } else {
+                                $ntnn = FALSE;
+                                $ntnc = FALSE;
+                            }
+
+                            // Checking each node in node array for matrix criteria
+                            if ($is_mtrx_flg) {
+                                $is_mtrx_flg = $tmp_node->getName() == 'mrow' &&
+                                    ($i == $node_cnt-1 || $ntnn == 'mo' && $ntnc == ',') &&
+                                    $tnfc == $node_8_cntnt && $tnlc == $node_7_cntnt;
+                            }
+
+                            if ($is_mtrx_flg) {
+                                for ($j = 0;$j < $tmp_node->getNumChild();$j++) {
+                                    $tmp_c_node = $tmp_node->getChildByIdx($j);
+
+                                    if ($tmp_c_node->getContent() == ',') {
+                                        $comma_pos_arr[$i][] = $j;
+                                    }
+                                }
+                            }
+
+                            if ($is_mtrx_flg && $i > 1) {
+
+                                $cnt_cpan = isset($comma_pos_arr[$i]) ? count($comma_pos_arr[$i]) : NULL;
+                                $cnt_cpap = isset($comma_pos_arr[$i-2]) ? count($comma_pos_arr[$i-2]) : NULL;
+                                $is_mtrx_flg = $cnt_cpan == $cnt_cpap;
+                            }
+
+                            $i += 2;
+                        }
+
+                        // If the node passes the matrix tests
+                        if ($is_mtrx_flg) {
+                            $tab_node_arr = array();
+
+                            for ($i = 0;$i < $node_cnt;$i += 2) {
+                                $tmp_key_node_arr = array_keys($node_arr);
+                                if (!($tmp_node = $node_arr[$tmp_key_node_arr[0]])) {
+                                    break;
+                                }
+                                $num_child = $tmp_node->getNumChild();
+                                $k = 0;
+
+                                $tmp_node->removeFirstChild();
+
+                                $row_node_arr = array();
+                                $row_frag_node_arr = array();
+
+                                for ($j = 1;$j < ($num_child-1);$j++) {
+                                    if (isset($comma_pos_arr[$i][$k]) &&
+                                        $j == $comma_pos_arr[$i][$k]) {
+
+                                        $tmp_node->removeFirstChild();
+
+                                        $tmp_c_node = $this->createNode();
+                                        $tmp_c_node->setName('mtd');
+                                        $tmp_c_node->addChildArr($row_frag_node_arr);
+                                        $row_frag_node_arr = array();
+
+                                        $row_node_arr[$tmp_c_node->getId()] = $tmp_c_node;
+
+                                        $k++;
+                                    } else {
+
+                                        if ($tmp_c_node = $tmp_node->getFirstChild()) {
+                                            $row_frag_node_arr[$tmp_c_node->getId()] = $tmp_c_node;
+                                            $tmp_node->removeFirstChild();
+                                        }
+                                    }
+                                }
+
+                                $tmp_c_node = $this->createNode();
+                                $tmp_c_node->setName('mtd');
+                                $tmp_c_node->addChildArr($row_frag_node_arr);
+
+                                $row_node_arr[$tmp_c_node->getId()] = $tmp_c_node;
+
+                                if (count($node_arr) > 2) {
+                                    $tmp_key_node_arr = array_keys($node_arr);
+                                    unset($node_arr[$tmp_key_node_arr[0]]);
+                                    unset($node_arr[$tmp_key_node_arr[1]]);
+                                }
+
+                                $tmp_c_node = $this->createNode();
+                                $tmp_c_node->setName('mtr');
+                                $tmp_c_node->addChildArr($row_node_arr);
+
+                                $tab_node_arr[$tmp_c_node->getId()] = $tmp_c_node;
+                            }
+
+                            $tmp_c_node = $this->createNode();
+                            $tmp_c_node->setName('mtable');
+                            $tmp_c_node->addChildArr($tab_node_arr);
+
+                            if (isset($sym['invisible'])) {
+                                $tmp_c_node->setAttr('columnalign','left');
+                            }
+
+                            $key_node_arr = array_keys($node_arr);
+                            $tmp_c_node->setId($key_node_arr[0]);
+
+                            $node_arr[$tmp_c_node->getId()] = $tmp_c_node;
+                        }
+                    }
+                }
+            }
+
+            $this->chopExpr($sym['symlen']);
+            if (!isset($sym['invisible'])) {
+                $node_7 = $this->createNode();
+                $node_7->setName('mo');
+                $node_7->setContent($sym['output']);
+                $node_arr[$node_7->getId()] = $node_7;
+            }
+        }
+
+        return($node_arr);
+    }
+
+    function  parseSmplExpr()
+    {
+        $sym = $this->getSymbol();
+
+        if (!$sym || isset($sym['right_bracket'])) //return FALSE;
+            return $this->emptyNode();
+
+        $this->chopExpr($sym['symlen']);
+
+        // 2005-06-11 wes: add definition type support
+        if(isset($sym['definition'])) {
+            $this->pushExpr($sym['output']);
+            $sym = $this->getSymbol();
+            $this->chopExpr($sym['symlen']);
+        }
+
+        if (isset($sym['left_bracket'])) {
+            $node_arr = $this->parseExpr();
+
+            if (isset($sym['invisible'])) {
+                $node_0 = $this->createNode();
+                $node_0->setName('mrow');
+                $node_0->addChildArr($node_arr);
+
+                return($node_0);
+            } else {
+                $node_0 = $this->createNode();
+                $node_0->setName('mo');
+                $node_0->setContent($sym['output']);
+
+                $node_1 = $this->createNode();
+                $node_1->setName('mrow');
+                $node_1->addChild($node_0);
+                $node_1->addChildArr($node_arr);
+
+                return($node_1);
+            }
+        } elseif (isset($sym['unary'])) {
+
+            if ($sym['input'] == 'sqrt') {
+                $node_0 = $this->parseSmplExpr();
+                $node_0->removeBrackets();
+
+                $node_1 = $this->createNode();
+                $node_1->setName($sym['tag']);
+                $node_1->addChild($node_0);
+
+                return($node_1);
+            } elseif (isset($sym['func'])) { //added 2006-9-7 David Lippman
+                $expr = ltrim($this->getCurrExpr());
+                $st = $expr{0};
+                $node_0 = $this->parseSmplExpr();
+                //$node_0->removeBrackets();
+                if ($st=='^' || $st == '_' || $st=='/' || $st=='|' || $st==',') {
+                    $node_1 = $this->createNode();
+                    $node_1->setName($sym['tag']);
+                    $node_1->setContent($sym['output']);
+                    $this->setCurrExpr($expr);
+                    return($node_1);
+                } else {
+                    $node_1 = $this->createNode();
+                    $node_1->setName('mrow');
+                    $node_2 = $this->createNode();
+                    $node_2->setName($sym['tag']);
+                    $node_2->setContent($sym['output']);
+                    $node_1->addChild($node_2);
+                    $node_1->addChild($node_0);
+                    return($node_1);
+                }
+            } elseif ($sym['input'] == 'text' || $sym['input'] == 'mbox' || $sym['input'] == '"') {
+                $expr = ltrim($this->getCurrExpr());
+                if ($sym['input']=='"') {
+                    $end_brckt = '"';
+                    $txt = substr($expr,0,strpos($expr,$end_brckt));
+                } else {
+                    switch($expr{0}) {
+                        case '(':
+                            $end_brckt = ')';
+                            break;
+                        case '[':
+                            $end_brckt = ']';
+                            break;
+                        case '{':
+                            $end_brckt = '}';
+                            break;
+                        default:
+                            $end_brckt = chr(11); // A character that will never be matched.
+                            break;
+                    }
+                    $txt = substr($expr,1,strpos($expr,$end_brckt)-1);
+                }
+
+                //$txt = substr($expr,1,strpos($expr,$end_brckt)-1);
+                $len = strlen($txt);
+
+                $node_0 = $this->createNode();
+                $node_0->setName('mrow');
+
+                if ($len > 0) {
+                    if ($txt{0} == " ") {
+                        $node_1 = $this->createNode();
+                        $node_1->setName('mspace');
+                        $node_1->setAttr('width','1ex');
+
+                        $node_0->addChild($node_1);
+                    }
+
+                    $node_3 = $this->createNode();
+                    $node_3->setName($sym['tag']);
+                    $node_3->setContent(trim($txt));
+
+                    $node_0->addChild($node_3);
+
+                    if ($len > 1 && $txt{$len-1} == " ") {
+                        $node_2 = $this->createNode();
+                        $node_2->setName('mspace');
+                        $node_2->setAttr('width','1ex');
+
+                        $node_0->addChild($node_2);
+                    }
+
+                    $this->chopExpr($len+2);
+                }
+                return($node_0);
+
+            } elseif (isset($sym['acc'])) {
+                $node_0 = $this->parseSmplExpr();
+                $node_0->removeBrackets();
+
+                $node_1 = $this->createNode();
+                $node_1->setName($sym['tag']);
+                $node_1->addChild($node_0);
+
+                $node_2 = $this->createNode();
+                $node_2->setName('mo');
+                $node_2->setContent($sym['output']);
+
+                $node_1->addChild($node_2);
+                return($node_1);
+            } else {
+                // Font change commands -- to complete
+            }
+        } elseif (isset($sym['binary'])) {
+            $node_arr = array();
+
+            $node_0 = $this->parseSmplExpr();
+            $node_0->removeBrackets();
+
+            $node_1 = $this->parseSmplExpr();
+            $node_1->removeBrackets();
+
+            /* 2005-06-05 wes: added stackrel */
+            if ($sym['input'] == 'root' || $sym['input'] == 'stackrel') {
+                $node_arr[$node_1->getId()] = $node_1;
+                $node_arr[$node_0->getId()] = $node_0;
+            } elseif ($sym['input'] == 'frac') {
+                $node_arr[$node_0->getId()] = $node_0;
+                $node_arr[$node_1->getId()] = $node_1;
+            }
+
+            $node_2 = $this->createNode();
+            $node_2->setName($sym['tag']);
+            $node_2->addChildArr($node_arr);
+
+            return($node_2);
+        } elseif (isset($sym['infix'])) {
+            $node_0 = $this->createNode();
+            $node_0->setName('mo');
+            $node_0->setContent($sym['output']);
+
+            return($node_0);
+        } elseif (isset($sym['space'])) {
+            $node_0 = $this->createNode();
+            $node_0->setName('mrow');
+
+            $node_1 = $this->createNode();
+            $node_1->setName('mspace');
+            $node_1->setAttr('width',$sym['space']);
+
+            $node_2 = $this->createNode();
+            $node_2->setName($sym['tag']);
+            $node_2->setContent($sym['output']);
+
+            $node_3 = $this->createNode();
+            $node_3->setName('mspace');
+            $node_3->setAttr('width',$sym['space']);
+
+            $node_0->addChild($node_1);
+            $node_0->addChild($node_2);
+            $node_0->addChild($node_3);
+
+            return($node_0);
+        } else {
+
+            // A constant
+            $node_0 = $this->createNode();
+            $node_0->setName($sym['tag']);
+            $node_0->setContent($sym['output']);
+            return($node_0);
+        }
+
+        // Return an empty node
+        return $this->emptyNode();
+    }
+
+    function getMathML()
+    {
+        $root = $this->_node_arr[0];
+        return($root->dumpXML());
+    }
+
+    function getCurrExpr()
+    {
+        return($this->_curr_expr);
+    }
+
+    function setCurrExpr($str)
+    {
+        $this->_curr_expr = $str;
+    }
+
+    function getExpr()
+    {
+        return($this->_expr);
+    }
+
+    function getPrevExpr()
+    {
+        return($this->_prev_expr);
+    }
+
+    function  createNode()
+    {
+        $node = new MathMLNode($this->_node_cntr);
+        // $node->setNamespaceAlias('m');
+        $this->_node_arr[$this->_node_cntr] = $node;
+        $this->_node_cntr++;
+        return($node);
+    }
+
+    /**
+     * Gets the largest symbol in the expression (greedy). Changed from non-greedy 26-Apr-2006
+     *
+     * @parameter boolean[optional] Chop original string?
+     *
+     * @return mixed
+     *
+     * @access private
+     */
+    function getSymbol($chop_flg = FALSE)
+    {
+        // Implemented a reverse symbol matcher.
+        // Instead of going front to back, it goes back to front. Steven 26-Apr-2006
+        $chr_cnt = strlen($this->_curr_expr);
+
+        if ($chr_cnt == 0) return FALSE;
+
+        for ($i = $chr_cnt; $i > 0; $i--) {
+            $sym_0 = substr($this->_curr_expr,0,$i);
+
+            // Reading string for numeric values
+            if (is_numeric($sym_0)) {
+
+                if ($chop_flg) $this->chopExpr($i);
+                return array('input'=>$sym_0, 'tag'=>'mn', 'output'=>$sym_0, 'symlen'=>$i);
+
+            } elseif (isset($this->_symbol_arr[$sym_0])) {
+
+                if ($chop_flg) $this->chopExpr($i);
+                $sym_arr = $this->_symbol_arr[$sym_0];
+                $sym_arr['symlen'] = $i;
+                return $sym_arr;
+            }
+        }
+
+        // Reading string for alphabetic constants and the minus sign
+        $char = $this->_curr_expr{0};
+        $len_left = $chop_flg ? $this->chopExpr(1) : strlen($this->_curr_expr)-1;
+
+        // Deals with expressions of length 1
+        if ($len_left == 0 && isset($this->_symbol_arr[$char])) {
+            $sym_arr = $this->_symbol_arr[$char];
+            $sym_arr['symlen'] = 1;
+            return $sym_arr;
+        } else {
+            $tag = preg_match('/[a-z]/i',$char) ? 'mi' : 'mo';
+            return array('input'=>$char, 'tag'=>$tag, 'output'=>$char, 'symlen'=>1);
+        }
+    }
+
+    function chopExpr($strlen)
+    {
+        $this->_prev_expr = $this->_curr_expr;
+
+        if ($strlen == strlen($this->_curr_expr)) {
+            $this->_curr_expr = '';
+            return(0);
+        } else {
+            $this->_curr_expr = ltrim(substr($this->_curr_expr,$strlen));
+            return(strlen($this->_curr_expr));
+        }
+    }
+}
+?>
\ No newline at end of file
diff --git a/examples/includes/ASCIIMathPHP-2.0/htmlMathML.js b/examples/includes/ASCIIMathPHP-2.0/htmlMathML.js
new file mode 100644 (file)
index 0000000..f81a1d2
--- /dev/null
@@ -0,0 +1,86 @@
+/* March 19, 2004 MathHTML (c) Peter Jipsen http://www.chapman.edu/~jipsen
+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 
+(at http://www.gnu.org/copyleft/gpl.html) for more details.*/
+
+function convertMath(node) {// for Gecko
+  if (node.nodeType==1) {
+    var newnode = 
+      document.createElementNS("http://www.w3.org/1998/Math/MathML",
+        node.nodeName.toLowerCase());
+    for(var i=0; i < node.attributes.length; i++) {
+           if (node.attributes[i].nodeName == 'displaystyle') {
+             newnode.setAttribute(node.attributes[i].nodeName,node.attributes[i].nodeValue);
+           }
+    }
+    for (var i=0; i<node.childNodes.length; i++) {
+      var st = node.childNodes[i].nodeValue;
+      if (st==null || st.slice(0,1)!=" " && st.slice(0,1)!="\n") 
+        newnode.appendChild(convertMath(node.childNodes[i]));
+    }
+    return newnode;
+  }
+  else return node;
+}
+function convert() {
+       
+       if (document.createElementNS) {
+               var mmlnode = document.getElementsByTagName("span");
+               
+               for (var i=0; i<mmlnode.length; i++) {
+                       var tmp_node = mmlnode[i];
+                       if (tmp_node.className == 'asciimath') {
+                               tmp_node.replaceChild(convertMath(tmp_node.firstChild),tmp_node.firstChild);
+                               /*
+                               for (var j=0;j<tmp_node.childNodes.length;j++) {
+                                       if (tmp_node.childNodes[j].nodeType != 3) {
+                                               
+                                       }
+                               }
+                               */
+                       }
+               }
+       } else {
+               var st,node,newnode;
+               var mmlnode = document.getElementsByTagName("math");
+               
+               for (var i=0; i<mmlnode.length; i++) {
+                       var str = "";
+                       node = mmlnode[i];
+                       while (node.nodeName!="/MATH" && node.nextSibling) {
+                               st = node.nodeName.toLowerCase();
+                               if (st=="#text") { 
+                                       str += node.nodeValue;
+                               } else {
+                                       str += (st.slice(0,1)=="/" ? "</m:"+st.slice(1) : "<m:"+st);
+                                       if (st.slice(0,1)!="/") {
+                                               for(var j=0; j < node.attributes.length; j++) {
+                                                       if (node.attributes[j].nodeValue!="italic" &&
+                                                        node.attributes[j].nodeValue!="" &&
+                                                        node.attributes[j].nodeValue!="inherit" &&
+                                                        node.attributes[j].nodeValue!=undefined) {
+                                                        str += " "+node.attributes[j].nodeName+"="+
+                                                            "\""+node.attributes[j].nodeValue+"\"";
+                                                       }
+                                               }
+                                       }
+                                       str += ">";
+                               }
+                               node = node.nextSibling;
+                               node.parentNode.removeChild(node.previousSibling);
+                       }
+                       
+                       if (str != '') {
+                               str += "</m:math>";
+                               newnode = document.createElement("span");
+                               node.parentNode.replaceChild(newnode,node);
+                               newnode.innerHTML = str;
+                       }
+               }
+       }
+}
\ No newline at end of file
diff --git a/examples/includes/HTML-Toc-0.91/.gitattributes b/examples/includes/HTML-Toc-0.91/.gitattributes
new file mode 100644 (file)
index 0000000..aecf250
--- /dev/null
@@ -0,0 +1 @@
+* -crlf
diff --git a/examples/includes/HTML-Toc-0.91/Changes b/examples/includes/HTML-Toc-0.91/Changes
new file mode 100644 (file)
index 0000000..81f8339
--- /dev/null
@@ -0,0 +1,26 @@
+Revision history for Perl extension HTML::Toc.\r
+\r
+2001-09-03   Freddy Vulto <fvu@fvu.myweb.nl>\r
+\r
+       Release 0.91\r
+\r
+       - Tested on Cygwin.\r
+       - Used Unix file type for source files.\r
+       - Updated documentation.\r
+       - Prohibited call with undefined parameter to HTML::Parser->parse() from\r
+         HTML::_tokenTocEndParser->parse() which caused havoc with version 3.25\r
+         of HTML::Parser.\r
+       - Specified 'HTML::Parser' as module that needs to be available in order\r
+         to use HTML::Toc.\r
+       - Added protected method HTML::TocGenerator::_setActiveAnchorName().\r
+         This method replaces the incongruous access of \r
+         'HTML::TocUpdator::_doDeleteTokens' by HTML::TocGenerator.\r
+         HTML::TocUpdator now overrides '_setActiveAnchorName()' to allow\r
+         the ancestor call to HTML::TocGenerator only when '_doDeleteTokens'\r
+         equals false.\r
+\r
+2001-08-09   Freddy Vulto <fvu@fvu.myweb.nl>\r
+\r
+       Release 0.90\r
+\r
+       - First release.\r
diff --git a/examples/includes/HTML-Toc-0.91/MANIFEST b/examples/includes/HTML-Toc-0.91/MANIFEST
new file mode 100644 (file)
index 0000000..e90f3a8
--- /dev/null
@@ -0,0 +1,26 @@
+Changes\r
+Toc.pod\r
+Toc.pm\r
+TocGenerator.pm\r
+TocInsertor.pm\r
+TocUpdator.pm\r
+Makefile.PL\r
+MANIFEST\r
+t/extend.t\r
+t/format.t\r
+t/generate.t\r
+t/insert.t\r
+t/manualTest.t\r
+t/options.t\r
+t/podExamples.t\r
+t/propagate.t\r
+t/siteMap.t\r
+t/update.t\r
+t/ManualTest/manualTest1.htm\r
+t/SiteMap/index.htm\r
+t/SiteMap/SubDir1/index.htm\r
+t/SiteMap/SubDir1/SubSubDir1/index.htm\r
+t/SiteMap/SubDir2/index.htm\r
+t/SiteMap/SubDir2/SubSubDir1/index.htm\r
+t/SiteMap/SubDir2/SubSubDir2/index.htm\r
+t/SiteMap/SubDir3/index.htm\r
diff --git a/examples/includes/HTML-Toc-0.91/Makefile.PL b/examples/includes/HTML-Toc-0.91/Makefile.PL
new file mode 100644 (file)
index 0000000..434d4fd
--- /dev/null
@@ -0,0 +1,8 @@
+use ExtUtils::MakeMaker;\r
+\r
+WriteMakefile(\r
+    'NAME'                   => 'HTML::Toc',\r
+    'VERSION_FROM'     => 'Toc.pm',\r
+    'PREREQ_PM'                => {'HTML::Parser' => 0},\r
+        'MAN3PODS'       => {},\r
+);\r
diff --git a/examples/includes/HTML-Toc-0.91/Toc.pm b/examples/includes/HTML-Toc-0.91/Toc.pm
new file mode 100644 (file)
index 0000000..ae2e8d8
--- /dev/null
@@ -0,0 +1,549 @@
+#=== HTML::Toc ================================================================
+# function: HTML Table of Contents
+
+
+package HTML::Toc;
+
+
+use strict;
+
+
+BEGIN {
+       use vars qw($VERSION);
+
+       $VERSION = '0.91';
+}
+
+
+use constant FILE_FILTER             => '.*';
+use constant GROUP_ID_H              => 'h';
+use constant LEVEL_1                 => 1;
+use constant NUMBERING_STYLE_DECIMAL => 'decimal';
+
+       # Templates
+
+       # Anchor templates
+use constant TEMPLATE_ANCHOR_NAME       => '$groupId."-".$node';
+use constant TEMPLATE_ANCHOR_HREF_BEGIN       => 
+                                       '"<a href=#$anchorName>"';
+use constant TEMPLATE_ANCHOR_HREF_BEGIN_FILE  => 
+                                       '"<a href=$file#$anchorName>"';
+use constant TEMPLATE_ANCHOR_HREF_END         => '"</a>"';
+use constant TEMPLATE_ANCHOR_NAME_BEGIN => 
+                                       '"<a name=$anchorName>"';
+use constant TEMPLATE_ANCHOR_NAME_END   => '"</a>"';
+use constant TOKEN_UPDATE_BEGIN_OF_ANCHOR_NAME_BEGIN => 
+                                       '<!-- #BeginTocAnchorNameBegin -->';
+use constant TOKEN_UPDATE_END_OF_ANCHOR_NAME_BEGIN   => 
+                                       '<!-- #EndTocAnchorNameBegin -->';
+use constant TOKEN_UPDATE_BEGIN_OF_ANCHOR_NAME_END => 
+                                       '<!-- #BeginTocAnchorNameEnd -->';
+use constant TOKEN_UPDATE_END_OF_ANCHOR_NAME_END   => 
+                                       '<!-- #EndTocAnchorNameEnd -->';
+use constant TOKEN_UPDATE_BEGIN_NUMBER      => 
+                                       '<!-- #BeginTocNumber -->';
+use constant TOKEN_UPDATE_END_NUMBER        => 
+                                       '<!-- #EndTocNumber -->';
+use constant TOKEN_UPDATE_BEGIN_TOC         => 
+                                       '<!-- #BeginToc -->';
+use constant TOKEN_UPDATE_END_TOC           => 
+                                       '<!-- #EndToc -->';
+
+use constant TEMPLATE_TOKEN_NUMBER      => '"$node &nbsp;"';
+
+       # Level templates
+use constant TEMPLATE_LEVEL             => '"<li>$text\n"';
+use constant TEMPLATE_LEVEL_BEGIN       => '"<ul>\n"';
+use constant TEMPLATE_LEVEL_END         => '"</ul>\n"';
+
+
+END {}
+
+
+#--- HTML::Toc::new() ---------------------------------------------------------
+# function: Constructor
+
+sub new {
+               # Get arguments
+       my ($aType) = @_;
+               # Local variables
+       my $self;
+
+       $self = bless({}, $aType);
+               # Default to empty 'options' array
+       $self->{options} = {};
+               # Empty toc
+       $self->{_toc} = "";
+               # Hash reference to array for each groupId, each array element
+               # referring to the group of the level indicated by the array index.
+               # For example, with the default 'tokenGroups', '_levelGroups' would
+               # look like: 
+               #
+               # {'h'} => [\$group1, \$group2, \$group3, \$group4, \$group5, \$group6];
+               #
+       $self->{_levelGroups} = undef;
+               # Set default options
+       $self->_setDefaults();
+       return $self;
+}  # new()
+
+
+#--- HTML::Toc::_compareLevels() ----------------------------------------------
+# function: Compare levels.
+# args:     - $aLevel: pointer to level
+#           - $aGroupLevel
+#           - $aPreviousLevel
+#           - $aPreviousGroupLevel
+# returns:  0 if new level equals previous level, 1 if new level exceeds
+#           previous level, -1 if new level is smaller then previous level.
+
+sub _compareLevels {
+               # Get arguments
+       my (
+               $self, $aLevel, $aPreviousLevel, $aGroupLevel, $aPreviousGroupLevel 
+       ) = @_;
+               # Local variables
+       my ($result);
+               # Levels equals?
+       if (
+               ($aLevel == $aPreviousLevel) &&
+               ($aGroupLevel == $aPreviousGroupLevel)
+       ) {
+               # Yes, levels are equals;
+                       # Indicate so
+               $result = 0;
+       }
+       else {
+               # No, levels differ;
+                       # Bias to new level being smaller than previous level;
+               $result = -1;
+                       # Must groups not be nested and do group levels differ?
+               if (
+                       ($self->{options}{'doNestGroup'} == 0) &&
+                       ($aGroupLevel != $aPreviousGroupLevel)
+               ) {
+                       # Yes, groups must be kept apart and the group levels differ;
+                               # Level is greater than previous level?
+                       if (
+                               ($aLevel > $aPreviousLevel)
+                       ) {
+                               # Yes, level is greater than previous level;
+                                       # Indicate so
+                               $result = 1;
+                       }
+               }
+               else {
+                       # No, group must be nested;
+                               # Level is greater than previous level?
+                       if (
+                               ($aLevel > $aPreviousLevel) ||
+                               ($aGroupLevel > $aPreviousGroupLevel)
+                       ) {
+                               # Yes, level is greater than previous level;
+                                       # Indicate so
+                               $result = 1;
+                       }
+               }
+       }
+               # Return value
+       return $result;
+}  # _compareLevels()
+
+
+#--- HTML::TocGenerator::_formatLevelIndent() ---------------------------------
+# function: Format indent.
+# args:     - $aText: text to indent
+#           - $aLevel: Level.
+#           - $aGroupLevel: Group level.
+#           - $aAdd
+#           - $aGlobalLevel
+
+sub _formatLevelIndent {
+               # Get arguments
+       my ($self, $aText, $aAdd, $aGlobalLevel) = @_;
+               # Local variables
+       my ($levelIndent, $indent, $nrOfIndents);
+               # Alias indentation option
+       $levelIndent = $self->{options}{'levelIndent'}; #=~ s/[0-9]+/&/;
+               # Calculate number of indents
+       $nrOfIndents = ($aGlobalLevel + $aAdd) * $levelIndent;
+               # Assemble indents
+       $indent = pack("A$nrOfIndents");
+               # Return value
+       return $indent . $aText;
+}  # _formatLevelIndent()
+
+
+#--- HTML::Toc::_formatToc() --------------------------------------------------
+# function: Format ToC.
+# args:     - aPreviousLevel
+#           - aPreviousGroupLevel
+#           - aToc: ToC to format.
+#           - aHeaderLines
+# note:     Recursive function this is.
+
+sub _formatToc {
+               # Get arguments
+       my (
+               $self, $aPreviousLevel, $aPreviousGroupLevel, $aToc, $aHeaderLines, 
+               $aGlobalLevel
+       ) = @_;
+               # Local variables
+       my ($level, $groupLevel, $line, $groupId, $text, $compareStatus);
+       my ($anchorName, $globalLevel, $node, $sequenceNr);
+
+       LOOP: {
+                       # Lines need processing?
+               while (scalar(@$aHeaderLines) > 0) {
+                       # Yes, lines need processing;
+                               # Get line
+                       $line = shift @$aHeaderLines;
+                               
+                               # Determine levels
+                       ($level, $groupLevel, $groupId, $node, $sequenceNr, 
+                       $anchorName, $text) = split(
+                               / /, $line, 7
+                       );
+                               # Must level and group be processed?
+                       if (
+                               ($level =~ m/$self->{options}{'levelToToc'}/) &&
+                               ($groupId =~ m/$self->{options}{'groupToToc'}/)
+                       ) {
+                               # Yes, level must be processed;
+                                       # Compare levels
+                               $compareStatus = $self->_compareLevels(
+                                       $level, $aPreviousLevel, $groupLevel, $aPreviousGroupLevel
+                               );
+
+                               COMPARE_LEVELS: {
+
+                                               # Equals?
+                                       if ($compareStatus == 0) {
+                                               # Yes, levels are equal;
+                                                       # Format level
+                                               $$aToc .= $self->_formatLevelIndent(
+                                                       ref($self->{_templateLevel}) eq "CODE" ?
+                                                               &{$self->{_templateLevel}}(
+                                                                       $level, $groupId, $node, $sequenceNr, $text
+                                                               ) :
+                                                               eval($self->{_templateLevel}),
+                                                       0, $aGlobalLevel
+                                               );
+                                       }
+
+                                               # Greater?
+                                       if ($compareStatus > 0) {
+                                               # Yes, new level is greater than previous level;
+                                                       # Must level be single-stepped?
+                                               if (
+                                                       $self->{options}{'doSingleStepLevel'} && 
+                                                       ($aPreviousLevel) && 
+                                                       ($level > $aPreviousLevel)
+                                               ) {
+                                                       # Yes, level must be single-stepped;
+                                                               # Make sure, new level is increased one step only
+                                                       $level = $aPreviousLevel + 1;
+                                               }
+                                                       # Increase global level
+                                               $aGlobalLevel++;
+                                                       # Format begin of level
+                                               $$aToc .= $self->_formatLevelIndent(
+                                                       eval($self->{_templateLevelBegin}), -1, $aGlobalLevel
+                                               );
+                                                       # Process line again
+                                               unshift @$aHeaderLines, $line;
+                                                       # Assemble TOC (recursive) for next level
+                                               $self->_formatToc(
+                                                       $level, $groupLevel, $aToc, $aHeaderLines, $aGlobalLevel
+                                               );
+                                                       # Format end of level
+                                               $$aToc .= $self->_formatLevelIndent(
+                                                       eval($self->{_templateLevelEnd}), -1, $aGlobalLevel
+                                               );
+                                                       # Decrease global level
+                                               $aGlobalLevel--;
+                                                       # Exit loop
+                                               last COMPARE_LEVELS;
+                                       }
+
+                                               # Smaller?
+                                       if ($compareStatus < 0) {
+                                               # Yes, new level is smaller than previous level;
+                                                       # Process line again
+                                               unshift @$aHeaderLines, $line;
+                                                       # End loop
+                                               last LOOP;
+                                       }
+                               }
+                       }
+               }
+       }
+}      # _formatToc()
+
+
+#--- HTML::Toc::_parseTokenGroups() -------------------------------------------
+# function: Parse token groups
+
+sub _parseTokenGroups {
+               # Get arguments
+       my ($self) = @_;
+               # Local variables
+       my ($group, $levelGroups, $numberingStyle);
+
+               # Clear any previous 'levelGroups'
+       $self->{_levelGroups} = undef;
+               # Determine default 'numberingStyle'
+       $numberingStyle = defined($self->{options}{'numberingStyle'}) ?
+               $self->{options}{'numberingStyle'} : NUMBERING_STYLE_DECIMAL;
+
+               # Loop through groups
+       foreach $group (@{$self->{options}{'tokenToToc'}}) {
+                       # 'groupId' is specified?
+               if (! defined($group->{'groupId'})) {
+                       # No, 'groupId' isn't specified;
+                               # Set default groupId
+                       $group->{'groupId'} = GROUP_ID_H;
+               }
+                       # 'level' is specified?
+               if (! defined($group->{'level'})) {
+                       # No, 'level' isn't specified;
+                               # Set default level
+                       $group->{'level'} = LEVEL_1;
+               }
+                       # 'numberingStyle' is specified?
+               if (! defined($group->{'numberingStyle'})) {
+                       # No, 'numberingStyle' isn't specified;
+                               # Set default numberingStyle
+                       $group->{'numberingStyle'} = $numberingStyle;
+               }
+                       # Add group to '_levelGroups' variabele
+               $self->{_levelGroups}{$group->{'groupId'}}[$group->{'level'} - 1] = 
+                       $group;
+       }
+}  # _parseTokenGroups()
+
+
+#--- HTML::Toc::_setDefaults() ------------------------------------------------
+# function: Set default options.
+
+sub _setDefaults {
+               # Get arguments
+       my ($self) = @_;
+               # Set default options
+       $self->setOptions(
+               {
+                       'attributeToExcludeToken' => '-',
+                       'attributeToTocToken'     => '@',
+                       'insertionPoint'          => 'after <body>',
+                       'levelToToc'              => '.*',
+                       'groupToToc'              => '.*',
+                       'doNumberToken'           => 0,
+                       'doLinkToFile'            => 0,
+                       'doLinkToToken'           => 1,
+                       'doLinkToId'              => 0,
+                       'doSingleStepLevel'       => 1,
+                       'linkUri'                 => '',
+                       'levelIndent'             => 3,
+                       'doNestGroup'             => 0,
+                       'doUseExistingAnchors'    => 1,
+                       'doUseExistingIds'        => 1,
+                       'tokenToToc'              => [
+                               {
+                                       'level'  => 1,
+                                       'tokenBegin' => '<h1>'
+                               }, {
+                                       'level'  => 2,
+                                       'tokenBegin' => '<h2>'
+                               }, {
+                                       'level'  => 3,
+                                       'tokenBegin' => '<h3>'
+                               }, {
+                                       'level'  => 4,
+                                       'tokenBegin' => '<h4>'
+                               }, {
+                                       'level'  => 5,
+                                       'tokenBegin' => '<h5>'
+                               }, {
+                                       'level'  => 6,
+                                       'tokenBegin' => '<h6>'
+                               }
+                       ],
+                       'header'            =>
+                               "\n<!-- Table of Contents generated by Perl - HTML::Toc -->\n",
+                       'footer'            =>
+                               "\n<!-- End of generated Table of Contents -->\n",
+               }
+       );
+}  # _setDefaults()
+
+
+#--- HTML::Toc::clear() -------------------------------------------------------
+# function: Clear ToC.
+
+sub clear {
+               # Get arguments
+       my ($self) = @_;
+               # Clear ToC
+       $self->{_toc}          = "";
+       $self->{toc}           = "";
+       $self->{groupIdLevels} = undef;
+       $self->{levels}        = undef;
+}   # clear()
+
+
+#--- HTML::Toc::format() ------------------------------------------------------
+# function: Format ToC.
+# returns:  Formatted ToC.
+
+sub format {
+               # Get arguments
+       my ($self) = @_;
+               # Local variables;
+       my $toc = "";
+       my @tocLines = split(/\r\n|\n/, $self->{_toc});
+               # Format table of contents
+       $self->_formatToc("0", "0", \$toc, \@tocLines, 0);
+               # Remove last newline
+       $toc =~ s/\n$//m;
+               # Add header & footer
+       $toc = $self->{options}{'header'} . $toc . $self->{options}{'footer'};
+               # Return value
+       return $toc;
+}      # format()
+
+
+#--- HTML::Toc::parseOptions() ------------------------------------------------
+# function: Parse options.
+
+sub parseOptions {
+               # Get arguments
+       my ($self) = @_;
+               # Alias options
+       my $options = $self->{options};
+
+               # Parse token groups
+       $self->_parseTokenGroups();
+
+               # Link ToC to tokens?
+       if ($self->{options}{'doLinkToToken'}) {
+               # Yes, link ToC to tokens;
+                       # Determine anchor href template begin
+               $self->{_templateAnchorHrefBegin} =
+                       defined($options->{'templateAnchorHrefBegin'}) ?
+                               $options->{'templateAnchorHrefBegin'} :
+                               $options->{'doLinkToFile'} ? 
+                                       TEMPLATE_ANCHOR_HREF_BEGIN_FILE : TEMPLATE_ANCHOR_HREF_BEGIN;
+
+                       # Determine anchor href template end
+               $self->{_templateAnchorHrefEnd} =
+                       defined($options->{'templateAnchorHrefEnd'}) ?
+                               $options->{'templateAnchorHrefEnd'} :
+                               TEMPLATE_ANCHOR_HREF_END;
+
+                       # Determine anchor name template
+               $self->{_templateAnchorName} =
+                       defined($options->{'templateAnchorName'}) ?
+                               $options->{'templateAnchorName'} :
+                               TEMPLATE_ANCHOR_NAME;
+
+                       # Determine anchor name template begin
+               $self->{_templateAnchorNameBegin} =
+                       defined($options->{'templateAnchorNameBegin'}) ?
+                               $options->{'templateAnchorNameBegin'} :
+                               TEMPLATE_ANCHOR_NAME_BEGIN;
+
+                       # Determine anchor name template end
+               $self->{_templateAnchorNameEnd} =
+                       defined($options->{'templateAnchorNameEnd'}) ?
+                               $options->{'templateAnchorNameEnd'} :
+                               TEMPLATE_ANCHOR_NAME_END;
+       }
+
+               # Determine token number template
+       $self->{_templateTokenNumber} = 
+               defined($options->{'templateTokenNumber'}) ?
+                       $options->{'templateTokenNumber'} :
+                       TEMPLATE_TOKEN_NUMBER;
+
+               # Determine level template
+       $self->{_templateLevel} =
+               defined($options->{'templateLevel'}) ?
+                       $options->{'templateLevel'} :
+                       TEMPLATE_LEVEL;
+
+               # Determine level begin template
+       $self->{_templateLevelBegin} =
+               defined($options->{'templateLevelBegin'}) ?
+                       $options->{'templateLevelBegin'} :
+                       TEMPLATE_LEVEL_BEGIN;
+
+               # Determine level end template
+       $self->{_templateLevelEnd} =
+               defined($options->{'templateLevelEnd'}) ?
+                       $options->{'templateLevelEnd'} :
+                       TEMPLATE_LEVEL_END;
+
+               # Determine 'anchor name begin' begin update token
+       $self->{_tokenUpdateBeginOfAnchorNameBegin} =
+               defined($options->{'tokenUpdateBeginOfAnchorNameBegin'}) ?
+                       $options->{'tokenUpdateBeginOfAnchorNameBegin'} :
+                       TOKEN_UPDATE_BEGIN_OF_ANCHOR_NAME_BEGIN;
+
+               # Determine 'anchor name begin' end update token
+       $self->{_tokenUpdateEndOfAnchorNameBegin} =
+               defined($options->{'tokenUpdateEndOfAnchorNameBegin'}) ?
+                       $options->{'tokenUpdateEndOfAnchorNameBegin'} :
+                       TOKEN_UPDATE_END_OF_ANCHOR_NAME_BEGIN;
+
+               # Determine 'anchor name end' begin update token
+       $self->{_tokenUpdateBeginOfAnchorNameEnd} =
+               defined($options->{'tokenUpdateBeginOfAnchorNameEnd'}) ?
+                       $options->{'tokenUpdateBeginOfAnchorNameEnd'} :
+                       TOKEN_UPDATE_BEGIN_OF_ANCHOR_NAME_END;
+
+               # Determine 'anchor name end' end update token
+       $self->{_tokenUpdateEndOfAnchorNameEnd} =
+               defined($options->{'tokenUpdateEndOfAnchorNameEnd'}) ?
+                       $options->{'tokenUpdateEndOfAnchorNameEnd'} :
+                       TOKEN_UPDATE_END_OF_ANCHOR_NAME_END;
+
+               # Determine number begin update token
+       $self->{_tokenUpdateBeginNumber} =
+               defined($options->{'tokenUpdateBeginNumber'}) ?
+                       $options->{'tokenUpdateBeginNumber'} :
+                       TOKEN_UPDATE_BEGIN_NUMBER;
+
+               # Determine number end update token
+       $self->{_tokenUpdateEndNumber} =
+               defined($options->{'tokenUpdateEndNumber'}) ?
+                       $options->{'tokenUpdateEndNumber'} :
+                       TOKEN_UPDATE_END_NUMBER;
+
+               # Determine toc begin update token
+       $self->{_tokenUpdateBeginToc} =
+               defined($options->{'tokenUpdateBeginToc'}) ?
+                       $options->{'tokenUpdateBeginToc'} :
+                       TOKEN_UPDATE_BEGIN_TOC;
+
+               # Determine toc end update token
+       $self->{_tokenUpdateEndToc} =
+               defined($options->{'tokenUpdateEndToc'}) ?
+                       $options->{'tokenUpdateEndToc'} :
+                       TOKEN_UPDATE_END_TOC;
+
+}  # parseOptions()
+
+
+#--- HTML::Toc::setOptions() --------------------------------------------------
+# function: Set options.
+# args:     - aOptions: Reference to hash containing options.
+
+sub setOptions {
+               # Get arguments
+       my ($self, $aOptions) = @_;
+               # Add options
+       %{$self->{options}} = (%{$self->{options}}, %$aOptions);
+}  # setOptions()
+
+
+1;
diff --git a/examples/includes/HTML-Toc-0.91/Toc.pod b/examples/includes/HTML-Toc-0.91/Toc.pod
new file mode 100644 (file)
index 0000000..6348503
--- /dev/null
@@ -0,0 +1,1710 @@
+=head1 NAME
+
+HTML::Toc - Generate, insert and update HTML Table of Contents.
+
+=head1 DESCRIPTION
+
+Generate, insert and update HTML Table of Contents.
+
+=head1 Introduction
+
+The HTML::Toc consists out of the following packages:
+
+    HTML::Toc
+    HTML::TocGenerator
+    HTML::TocInsertor
+    HTML::TocUpdator
+
+HTML::Toc is the object which will eventually hold the Table of Contents.  HTML::TocGenerator does the actual generation of the ToC.  HTML::TocInsertor handles the insertion of the ToC in the source.  HTML::TocUpdator takes care of updating previously inserted ToCs.
+
+HTML::Parser is the base object of HTML::TocGenerator, HTML::TocInsertor and HTML::TocUpdator.  Each of these objects uses its predecessor as its ancestor, as shown in the UML diagram underneath:
+    
+    +---------------------+
+    |    HTML::Parser     |
+    +---------------------+
+    +---------------------+
+    |    +parse()         |
+    |    +parse_file()    |
+    +----------+----------+
+              /_\
+               |
+    +----------+----------+  <<uses>>  +-----------+
+    | HTML::TocGenerator  + - - - - - -+ HTML::Toc |
+    +---------------------+            +-----------+
+    +---------------------+            +-----------+
+    | +extend()           |            | +clear()  |
+    | +extendFromFile()   |            | +format() |
+    | +generate()         |            +-----+-----+
+    | +generateFromFile() |                  :
+    +----------+----------+                  :
+              /_\                            :
+               |                             :
+    +----------+----------+     <<uses>>     :
+    |  HTML::TocInsertor  + - - - - - - - - -+
+    +---------------------+                  :
+    +---------------------+                  :
+    |  +insert()          |                  :
+    |  +insertIntoFile()  |                  :
+    +----------+----------+                  :
+              /_\                            :
+               |                             :
+    +----------+----------+     <<uses>>     :
+    |  HTML::TocUpdator   + - - - - - - - - -+
+    +---------------------+
+    +---------------------+
+    |  +insert()          |
+    |  +insertIntoFile()  |
+    |  +update()          |
+    |  +updateFile()      |
+    +---------------------+
+
+When generating a ToC you'll have to decide which object you want to use:
+
+    TocGenerator:
+        for generating a ToC without inserting the ToC into the source
+    TocInsertor:
+        for generating a ToC and inserting the ToC into the source
+    TocUpdator:
+        for generating and inserting a ToC, removing any previously
+        inserted ToC elements
+
+Thus in tabular view, each object is capable of:
+
+                   generating   inserting   updating
+                   ---------------------------------
+    TocGenerator        X
+    TocInsertor         X           X
+    TocUpdator          X           X           X
+
+=head2 Generating
+
+The code underneath will generate a ToC of the HTML headings C<<h1>>..C<<h6>> from a file C<index.htm>:
+
+    use HTML::Toc;
+    use HTML::TocGenerator;
+
+    my $toc          = HTML::Toc->new();
+    my $tocGenerator = HTML::TocGenerator->new();
+
+    $tocGenerator->generateFromFile($toc, 'index.htm');
+    print $toc->format();
+
+For example, with C<index.htm> containing:
+
+    <html>
+    <body>
+       <h1>Chapter</h1>
+    </body>
+    </html>
+
+the output will be:
+
+    
+    <!-- Table of Contents generated by Perl - HTML::Toc -->
+    <ul>
+       <li><a href=#h-1>Chapter</a>
+    </ul>
+    <!-- End of generated Table of Contents -->
+
+=head2 Inserting
+
+This code will generate a ToC of HTML headings C<<h1>>..C<<h6>> of file C<index.htm>, and insert the ToC after the C<<body>> tag at the same time:
+
+    use HTML::Toc;
+    use HTML::TocInsertor;
+
+    my $toc         = HTML::Toc->new();
+    my $tocInsertor = HTML::TocInsertor->new();
+
+    $tocInsertor->insertIntoFile($toc, 'index.htm');
+
+For example, with C<index.htm> containing:
+
+    <html>
+    <body>
+       <h1>Chapter</h1>
+    </body>
+    </html>
+
+the output will be:
+
+    <html>
+    <body>
+    <!-- Table of Contents generated by Perl - HTML::Toc -->
+    <ul>
+       <li><a href=#h-1>Chapter</a>
+    </ul>
+    <!-- End of generated Table of Contents -->
+
+       <a name=h-1><h1>Chapter</h1></a>
+    </body>
+    </html>
+
+If you're planning to update the inserted ToC, you'd better use C<TocUpdator> to insert the ToC.  C<TocUpdator> marks the inserted ToC elements with update tokens.  These update tokens allow C<TocUpdator> to identify and remove the ToC elements during a future update session.  This code uses C<TocUpdator> instead of C<TocInsertor>:
+
+    use HTML::Toc;
+    use HTML::TocUpdator;
+
+    my $toc        = HTML::Toc->new();
+    my $tocUpdator = HTML::TocUpdator->new();
+
+    $tocUpdator->insertIntoFile($toc, 'index.htm');
+
+When applying the code above on 'index.htm':
+
+    <html>
+    <body>
+       <h1>
+       Chapter
+       </h1>
+    </body>
+    </html>
+
+the output will contain additional update tokens:
+
+    <!-- #BeginToc -->
+    <!-- #EndToc -->
+    <!-- #BeginTocAnchorNameBegin -->
+    <!-- #EndTocAnchorNameBegin -->
+    <!-- #BeginTocAnchorNameEnd -->
+    <!-- #EndTocAnchorNameEnd -->
+
+around the inserted ToC elements:
+
+    <html>
+    <body><!-- #BeginToc-->
+    <!-- Table of Contents generated by Perl - HTML::Toc -->
+    <ul>
+       <li><a href=#h-1> Chapter </a>
+    </ul>
+    <!-- End of generated Table of Contents -->
+    <!-- #EndToc -->
+       <!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1>
+       Chapter
+       </h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+    </body>
+    </html>
+
+Instead of C<HTML::TocUpdator::insertIntoFile> you can also use C<HTML::TocUpdator::updateFile()>.  C<HTML::TocUpdator::updateFile()> will also insert the ToC, whether there is a ToC already inserted or not.
+
+=head2 Updating
+
+This code will generate a ToC of HTML headings C<<h1>>..C<<h6>> of file C<indexToc.htm>, and insert or update the ToC after the C<<body>> tag at the same time:
+
+    use HTML::Toc;
+    use HTML::TocUpdator;
+
+    my $toc        = HTML::Toc->new();
+    my $tocUpdator = HTML::TocUpdator->new();
+
+    $tocUpdator->updateFile($toc, 'indexToc.htm');
+
+For example, with C<indexToc.htm> containing:
+
+    <html>
+    <body><!-- #BeginToc -->
+    foo
+    <!-- #EndToc -->
+       <!-- #BeginTocAnchorNameBegin -->bar<!-- #EndTocAnchorNameBegin --><h1>
+       Chapter
+       </h1><!-- #BeginTocAnchorNameEnd -->foo<!-- #EndTocAnchorNameEnd -->
+    </body>h
+    </html>
+
+the output will be:
+
+    <html>
+    <body><!-- #BeginToc -->
+    <!-- Table of Contents generated by Perl - HTML::Toc -->
+    <ul>
+       <li><a href=#h-1> Chapter </a>
+    </ul>
+    <!-- End of generated Table of Contents -->
+    <!-- #EndToc -->
+       <!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1>
+       Chapter
+       </h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+    </body>
+    </html>
+
+All text between the update tokens will be replaced.  So be warned: all manual changes made to text between update tokens will be removed unrecoverable after calling C<HTML::TocUpdator::update()> or C<HTML::TocUpdator::updateFile()>.
+
+=head2 Formatting
+
+The ToC isn't generated all at once.  There are two stages involved: generating and formatting.  Generating the ToC actually means storing a preliminary ToC in C<HTML::Toc-E<gt>{_toc}>.  This preliminary, tokenized ToC has to be turned into something useful by calling C<HTML::Toc-E<gt>format()>.  For an example, see paragraph 'L<Generating|"generating">'.
+
+=head1 Advanced
+
+The ToC generation can be modified in a variety of ways.  The following paragraphs each explain a single modification.  An example of most of the modifications can be found in the C<manualTest.t> test file.  Within this test, a manual containing:
+
+    preface
+    introduction
+    table of contents
+    table of figures
+    table of tables
+    parts
+    chapters
+    appendixes
+    bibliography
+
+is formatted.
+
+=head2 Using attribute value as ToC text
+
+Normally, the ToC will be made of text between specified ToC tokens.  It's also possible to use the attribute value of a token as a ToC text.  This can be done by specifying the attribute marked with an L<attributeToTocToken|"attributeToTocToken"> within the L<tokenBegin|"tokenBegin"> token.  For example, suppose you want to generate a ToC of the C<alt> attributes of the following image tokens:
+
+    <body>
+       <img src=test1.gif alt="First picture">
+       <img src=test2.gif alt="Second picture">
+    </body>
+
+This would be the code:
+
+    use HTML::Toc;
+    use HTML::TocInsertor;
+
+    my $toc         = HTML::Toc->new();
+    my $tocInsertor = HTML::TocInsertor->new();
+
+    $toc->setOptions({
+       'tokenToToc'   => [{
+          'groupId'    => 'image',
+          'tokenBegin' => '<img alt=@>'
+       }],
+    });
+    $tocInsertor->insertIntoFile($toc, $filename);
+
+and the output will be:
+
+    <body>
+    <!-- Table of Contents generated by Perl - HTML::Toc -->
+    <ul>
+       <li><a href=#image-1>First picture</a>
+       <li><a href=#image-2>Second picture</a>
+    </ul>
+    <!-- End of generated Table of Contents -->
+
+       <a name=image-1><img src=test1.gif alt="First picture"></a>
+       <a name=image-2><img src=test2.gif alt="Second picture"></a>
+    </body>
+
+=head2 Generate single ToC of multiple files
+
+Besides generating a ToC of a single file, it's also possible to generate a single ToC of multiple files.  This can be done by specifying either an array of files as the file argument and/or by extending an existing ToC.
+
+=head3 Specify an array of files
+
+For example, suppose you want to generate a ToC of both C<doc1.htm>:
+
+    <body>
+       <h1>Chapter of document 1</h1>
+    </body>
+
+and C<doc2.htm>:
+
+    <body>
+       <h1>Chapter of document 2</h1>
+    </body>
+
+Here's the code to do so by specifying an array of files:
+
+    use HTML::Toc;
+    use HTML::TocGenerator;
+
+    my $toc          = HTML::Toc->new();
+    my $tocGenerator = HTML::TocGenerator->new();
+
+    $toc->setOptions({'doLinkToFile' => 1});
+    $tocGenerator->generateFromFile($toc, ['doc1.htm', 'doc2.htm']);
+    print $toc->format();
+
+And the output will be:
+
+
+    <!-- Table of Contents generated by Perl - HTML::Toc -->
+    <ul>
+       <li><a href=doc1.htm#h-1>Chapter of document 1</a>
+       <li><a href=doc2.htm#h-2>Chapter of document 2</a>
+    </ul>
+    <!-- End of generated Table of Contents -->
+
+=head3 Extend an existing ToC
+
+It's also possible to extend an existing ToC.  For example, suppose we want the generate a ToC of file C<doc1.htm>:
+
+    <body>
+       <h1>Chapter of document 1</h1>
+    </body>
+
+and extend this ToC with text from C<doc2.htm>:
+
+    <body>
+       <h1>Chapter of document 2</h1>
+    </body>
+
+Here's the code to do so:
+
+    use HTML::Toc;
+    use HTML::TocGenerator;
+
+    my $toc          = HTML::Toc->new();
+    my $tocGenerator = HTML::TocGenerator->new();
+
+    $toc->setOptions({'doLinkToFile' => 1});
+    $tocGenerator->generateFromFile($toc, 'doc1.htm');
+    $tocGenerator->extendFromFile($toc, 'doc2.htm');
+    print $toc->format();
+
+And the output will be:
+
+
+    <!-- Table of Contents generated by Perl - HTML::Toc -->
+    <ul>
+       <li><a href=doc1.htm#h-1>Chapter of document 1</a>
+       <li><a href=doc2.htm#h-2>Chapter of document 2</a>
+    </ul>
+    <!-- End of generated Table of Contents -->
+
+=head2 Generate multiple ToCs
+
+It's possible to generate multiple ToCs at once by specifying a C<HTML::Toc> object array as the ToC argument.  For example, suppose you want to generate a default ToC of HTML headings <h1>..<h6> as well as a ToC of the C<alt> image attributes of the following text:
+
+    <body>
+       <h1>Header One</h1>
+       <img src=test1.gif alt="First picture" id=image_001>
+       <h2>Paragraph One</h2>
+       <img src=test2.gif alt="Second picture" id=image_002>
+    </body>
+
+Here's how you would do so:
+
+    use HTML::Toc;
+    use HTML::TocInsertor;
+
+    my $toc1        = HTML::Toc->new();
+    my $toc2        = HTML::Toc->new();
+    my $tocInsertor = HTML::TocInsertor->new();
+
+    $toc2->setOptions({
+       'tokenToToc'   => [{
+          'groupId'    => 'image',
+          'tokenBegin' => '<img alt=@>'
+       }],
+    });
+    $tocInsertor->insertIntoFile([$toc1, $toc2], $filename);
+
+And the output will be:
+
+    <body>
+    <!-- Table of Contents generated by Perl - HTML::Toc -->
+    <ul>
+       <li><a href=#h-1>Header One</a>
+       <ul>
+          <li><a href=#h-1.1>Paragraph One</a>
+       </ul>
+    </ul>
+    <!-- End of generated Table of Contents -->
+
+    <!-- Table of Contents generated by Perl - HTML::Toc -->
+    <ul>
+       <li><a href=#image-1>First picture</a>
+       <li><a href=#image-2>Second picture</a>
+    </ul>
+    <!-- End of generated Table of Contents -->
+
+       <a name=h-1><h1>Header One</h1></a>
+       <a name=image-1><img src=test1.gif alt="First picture"></a>
+       <a name=h-1.1><h2>Paragraph One</h2></a>
+       <a name=image-2><img src=test2.gif alt="Second picture"></a>
+    </body>
+
+=head2 Generate multiple groups in one ToC
+
+You may want to generate a ToC consisting of multiple ToC groups.
+
+=head3 Specify an additional 'Appendix' group
+
+Suppose you want to generate a ToC with one group for the normal headings, and one group for the appendix headings, using this source file:
+
+    <body>
+       <h1>Chapter</h1>
+       <h2>Paragraph</h2>
+       <h3>Subparagraph</h3>
+       <h1>Chapter</h1>
+       <h1 class=appendix>Appendix Chapter</h1>
+       <h2 class=appendix>Appendix Paragraph</h2>
+    </body>
+
+With the code underneath:
+
+    use HTML::Toc;
+    use HTML::TocInsertor;
+
+    my $toc         = HTML::Toc->new();
+    my $tocInsertor = HTML::TocInsertor->new();
+
+    $toc->setOptions({
+       'tokenToToc' => [{
+             'tokenBegin' => '<h1 class=-appendix>'
+          }, {
+             'tokenBegin' => '<h2 class=-appendix>',
+             'level'      => 2
+          }, {
+             'groupId'    => 'appendix',
+             'tokenBegin' => '<h1 class=appendix>',
+          }, {
+             'groupId'    => 'appendix',
+             'tokenBegin' => '<h2 class=appendix>',
+             'level'      => 2
+          }]
+    });
+    $tocInsertor->insertIntoFile($toc, $filename);
+
+the output will be:
+
+    <body>
+    <!-- Table of Contents generated by Perl - HTML::Toc -->
+    <ul>
+       <li><a href=#h-1>Chapter</a>
+       <ul>
+          <li><a href=#h-1.1>Paragraph</a>
+       </ul>
+       <li><a href=#h-2>Chapter</a>
+    </ul>
+    <ul>
+       <li><a href=#appendix-1>Appendix Chapter</a>
+       <ul>
+          <li><a href=#appendix-1.1>Appendix Paragraph</a>
+       </ul>
+    </ul>
+    <!-- End of generated Table of Contents -->
+
+       <a name=h-1><h1>Chapter</h1></a>
+       <a name=h-1.1><h2>Paragraph</h2></a>
+       <h3>Subparagraph</h3>
+       <a name=h-2><h1>Chapter</h1></a>
+       <a name=appendix-1><h1 class=appendix>Appendix Chapter</h1></a>
+       <a name=appendix-1.1><h2 class=appendix>Appendix Paragraph</h2></a>
+    </body>
+
+=head3 Specify an additional 'Part' group
+
+Suppose you want to generate a ToC of a document which is divided in multiple parts like this file underneath:
+
+    <body>
+       <h1 class=part>First Part</h1>
+       <h1>Chapter</h1>
+       <h2>Paragraph</h2>
+       <h1 class=part>Second Part</h1>
+       <h1>Chapter</h1>
+       <h2>Paragraph</h2>
+    </body>
+
+With the code underneath:
+
+    use HTML::Toc;
+    use HTML::TocInsertor;
+
+    my $toc         = HTML::Toc->new();
+    my $tocInsertor = HTML::TocInsertor->new();
+
+    $toc->setOptions({
+       'doNumberToken'    => 1,
+       'tokenToToc' => [{
+             'tokenBegin' => '<h1 class=-part>'
+          }, {
+             'tokenBegin' => '<h2 class=-part>',
+             'level'      => 2,
+          }, {
+             'groupId'        => 'part',
+             'tokenBegin'     => '<h1 class=part>',
+             'level'          => 1,
+             'numberingStyle' => 'upper-alpha'
+          }]
+    });
+    $tocInsertor->insertIntoFile($toc, $filename);
+
+the output will be:
+
+    <body>
+    <!-- Table of Contents generated by Perl - HTML::Toc -->
+    <ul>
+       <li><a href=#part-A>First Part</a>
+    </ul>
+    <ul>
+       <li><a href=#h-1>Chapter</a>
+       <ul>
+          <li><a href=#h-1.1>Paragraph</a>
+       </ul>
+    </ul>
+    <ul>
+       <li><a href=#part-B>Second Part</a>
+    </ul>
+    <ul>
+       <li><a href=#h-2>Chapter</a>
+       <ul>
+          <li><a href=#h-2.1>Paragraph</a>
+       </ul>
+    </ul>
+    <!-- End of generated Table of Contents -->
+
+       <a name=part-A><h1 class=part>A &nbsp;First Part</h1></a>
+       <a name=h-1><h1>1 &nbsp;Chapter</h1></a>
+       <a name=h-1.1><h2>1.1 &nbsp;Paragraph</h2></a>
+       <a name=part-B><h1 class=part>B &nbsp;Second Part</h1></a>
+       <a name=h-2><h1>2 &nbsp;Chapter</h1></a>
+       <a name=h-2.1><h2>2.1 &nbsp;Paragraph</h2></a>
+    </body>
+
+=head2 Number ToC entries
+
+By default, the generated ToC will list its entries unnumbered.  If you want to number the ToC entries, two options are available.  Either you can specify a numbered list by modifying L<templateLevelBegin|"templateLevelBegin"> and L<templateLevelEnd|"templateLevelEnd">.  Or when the ToC isn't a simple numbered list, you can use the numbers generated by HTML::TocGenerator.
+
+=head3 Specify numbered list
+
+By modifying L<templateLevelBegin|"templateLevelBegin"> and L<templateLevelEnd|"templateLevelEnd"> you can specify a numbered ToC:
+
+    use HTML::Toc;
+    use HTML::TocGenerator;
+
+    my $toc          = HTML::Toc->new();
+    my $tocGenerator = HTML::TocGenerator->new();
+
+    $toc->setOptions({
+        'templateLevelBegin' => '"<ol>\n"',
+        'templateLevelEnd'   => '"</ol>\n"',
+    });
+    $tocGenerator->generateFromFile($toc, 'index.htm');
+    print $toc->format();
+
+For instance with the original file containing:
+
+    <body>
+        <h1>Chapter</h1>
+        <h2>Paragraph</h2>
+    </body>
+
+The formatted ToC now will contain C<ol> instead of C<ul> tags:
+
+    <!-- Table of Contents generated by Perl - HTML::Toc -->
+    <ol>
+       <li><a href=#h-1>Chapter</a>
+       <ol>
+          <li><a href=#h-1.1>Paragraph</a>
+       </ol>
+    </ol>
+    <!-- End of generated Table of Contents -->
+
+See also: L<Using CSS for ToC formatting|"Using CSS for ToC formatting">.
+
+=head3 Use generated numbers
+
+Instead of using the HTML ordered list (OL), it's also possible to use the generated numbers to number to ToC nodes.  This can be done by modifying L<templateLevel|"templateLevel">:
+
+    use HTML::Toc;
+    use HTML::TocGenerator;
+
+    my $toc          = HTML::Toc->new();
+    my $tocGenerator = HTML::TocGenerator->new();
+
+    $toc->setOptions({
+               'templateLevel' => '"<li>$node &nbsp;$text\n"',
+    });
+    $tocGenerator->generateFromFile($toc, 'index.htm');
+    print $toc->format();
+
+For instance with the original file containing:
+
+    <body>
+        <h1>Chapter</h1>
+        <h2>Paragraph</h2>
+    </body>
+
+The formatted ToC now will have the node numbers hard-coded:
+
+    <!-- Table of Contents generated by Perl - HTML::Toc -->
+    <ul>
+       <li>1 &nbsp;<a href=#h-1>Chapter</a>
+       <ul>
+          <li>1.1 &nbsp;<a href=#h-1.1>Paragraph</a>
+       </ul>
+    </ul>
+    <!-- End of generated Table of Contents -->
+
+See also: L<Using CSS for ToC formatting|"Using CSS for ToC formatting">.
+
+=head2 Using CSS for ToC formatting
+
+Suppose you want to display a ToC with upper-alpha numbered appendix headings.  To accomplish this, you can specify a CSS style within the source document:
+
+    <html>
+    <head>
+       <style type="text/css">
+          ol.toc_appendix1 { list-style-type: upper-alpha }
+       </style>
+    </head>
+    <body>
+       <h1 class=appendix>Appendix</h1>
+       <h2 class=appendix>Appendix Paragraph</h2>
+       <h1 class=appendix>Appendix</h1>
+       <h2 class=appendix>Appendix Paragraph</h2>
+    </body>
+    </html>
+
+Here's the code:
+
+    my $toc          = new HTML::Toc;
+    my $tocInsertor  = new HTML::TocInsertor;
+
+    $toc->setOptions({
+       'templateLevelBegin'   => '"<ol class=toc_$groupId$level>\n"',
+       'templateLevelEnd'     => '"</ol>\n"',
+       'doNumberToken'        => 1,
+       'tokenToToc' => [{
+             'groupId'        => 'appendix',
+             'tokenBegin'     => '<h1>',
+             'numberingStyle' => 'upper-alpha'
+          }, {
+             'groupId'        => 'appendix',
+             'tokenBegin'     => '<h2>',
+             'level'          => 2,
+         }]
+    });
+    $tocInsertor->insertIntoFile($toc, $filename);
+
+Which whill result in the following output:
+
+    <html>
+    <head>
+       <style type="text/css">
+          ol.toc_appendix1 { list-style-type: upper-alpha }
+       </style>
+    </head>
+    <body>
+    <!-- Table of Contents generated by Perl - HTML::Toc -->
+    <ol class=toc_appendix1>
+       <li><a href=#appendix-A>Appendix</a>
+       <ol class=toc_appendix2>
+          <li><a href=#appendix-A.1>Appendix Paragraph</a>
+       </ol>
+       <li><a href=#appendix-B>Appendix</a>
+       <ol class=toc_appendix2>
+          <li><a href=#appendix-B.1>Appendix Paragraph</a>
+       </ol>
+    </ol>
+    <!-- End of generated Table of Contents -->
+
+       <a name=appendix-A><h1>A &nbsp;Appendix</h1></a>
+       <a name=appendix-A.1><h2>A.1 &nbsp;Appendix Paragraph</h2></a>
+       <a name=appendix-B><h1>B &nbsp;Appendix</h1></a>
+       <a name=appendix-B.1><h2>B.1 &nbsp;Appendix Paragraph</h2></a>
+    </body>
+    </html>
+
+=head2 Creating site map
+
+Suppose you want to generate a table of contents of the E<lt>titleE<gt> tags of the files in the following directory structure:
+
+    path               file
+
+    .                  index.htm, <title>Main</title>
+    |- SubDir1         index.htm, <title>Sub1</title>
+    |  |- SubSubDir1   index.htm, <title>SubSub1</title>
+    |
+    |- SubDir2         index.htm, <title>Sub2</title>
+    |  |- SubSubDir1   index.htm, <title>SubSub1</title>
+    |  |- SubSubDir2   index.htm, <title>SubSub2</title>
+    |
+    |- SubDir3         index.htm, <title>Sub3</title>
+
+By specifying 'fileSpec' which determine how many slashes (/) each file may contain for a specific level:
+
+    use HTML::Toc;
+    use HTML::TocGenerator;
+    use File::Find;
+
+    my $toc          = HTML::Toc->new;
+    my $tocGenerator = HTML::TocGenerator->new;
+    my @fileList;
+
+    sub wanted {
+          # Add file to 'fileList' if extension matches '.htm'
+       push (@fileList, $File::Find::name) if (m/\.htm$/);
+    }
+
+    $toc->setOptions({
+       'doLinkToFile'       => 1,
+       'templateAnchorName' => '""',
+       'templateAnchorHref' => '"<a href=$file"."#".$groupId.$level.">"',
+       'doLinkTocToToken'   => 1,
+       'tokenToToc'         => [{
+          'groupId'         => 'dir',
+          'level'           => 1,
+          'tokenBegin'      => '<title>',
+          'tokenEnd'        => '</title>',
+          'fileSpec'        => '\./[^/]+$'
+       }, {
+          'groupId'         => 'dir',
+          'level'           => 2,
+          'tokenBegin'      => '<title>',
+          'tokenEnd'        => '</title>',
+          'fileSpec'        => '\./[^/]+?/[^/]+$'
+       }, {
+          'groupId'         => 'dir',
+          'level'           => 3,
+          'tokenBegin'      => '<title>',
+          'tokenEnd'        => '</title>',
+          'fileSpec'        => '\./[^/]+?/[^/]+?/[^/]+$'
+       }]
+    });
+
+       # Traverse directory structure
+    find({wanted => \&wanted, no_chdir => 1}, '.');
+       # Generate ToC of case-insensitively sorted file list
+    $tocGenerator->extendFromFile(
+       $toc, [sort {uc($a) cmp uc($b)} @fileList]
+    );
+    print $toc->format();
+
+the following ToC will be generated:
+
+    <!-- Table of Contents generated by Perl - HTML::Toc -->
+    <ul>
+       <li><a href=./index.htm#>Main</a>
+       <ul>
+          <li><a href=./SubDir1/index.htm#>Sub1</a>
+          <ul>
+             <li><a href=./SubDir1/SubSubDir1/index.htm#>SubSub1</a>
+          </ul>
+          <li><a href=./SubDir2/index.htm#>Sub2</a>
+          <ul>
+             <li><a href=./SubDir2/SubSubDir1/index.htm#>SubSub1</a>
+             <li><a href=./SubDir2/SubSubDir2/index.htm#>SubSub2</a>
+          </ul>
+          <li><a href=./SubDir3/index.htm#>Sub3</a>
+       </ul>
+    </ul>
+    <!-- End of generated Table of Contents -->
+
+=head1 Methods
+
+=head2 HTML::Toc::clear()
+
+    syntax:  $toc->clear()
+    returns: --
+
+Clear the ToC.
+
+=head2 HTML::Toc::format()
+
+    syntax:  $scalar = $toc->format()
+    returns: Formatted ToC.
+
+Format tokenized ToC.
+
+=head2 HTML::TocGenerator::extend()
+
+    syntax:  $tocGenerator->extend($toc, $string [, $options])
+    args:    - $toc:     (reference to array of) HTML::Toc object(s) to extend
+             - $string:  string to retrieve ToC from
+             - $options: hash reference containing generator options.
+
+Extend ToC from specified string.  For generator options, see L<HTML::TocGenerator Options|"HTML::TocGenerator Options">
+
+=head2 HTML::TocGenerator::extendFromFile()
+
+    syntax:  $tocGenerator->extendFromFile($toc, $filename [, $options])
+    args:    - $toc:      (reference to array of) HTML::Toc object(s) to extend
+             - $filename: (reference to array of) file(s) to extend ToC from
+             - $options:  hash reference containing generator options.
+
+Extend ToC from specified file.  For generator options, see L<HTML::TocGenerator Options|"HTML::TocGenerator Options">.  For an example, see L<Extend an existing ToC>.
+
+=head2 HTML::TocGenerator::generate()
+
+    syntax:  $tocGenerator->generate($toc, $string [, $options])
+    args:    - $toc:     (reference to array of) HTML::Toc object(s) to generate
+             - $string:  string to retrieve ToC from
+             - $options: hash reference containing generator options.
+
+Generate ToC from specified string.  Before generating, the ToC will be cleared.  For extending an existing ToC, use the L<HTML::TocGenerator::extend()|"HTML::TocGenerator::extend()"> method.  For generator options, see L<HTML::TocGenerator Options|"HTML::TocGenerator Options">.
+
+=head2 HTML::TocGenerator::generateFromFile()
+
+    syntax:  $tocGenerator->generateFromFile($toc, $filename [, $options])
+    args:    - $toc:      (reference to array of) HTML::Toc object(s) to 
+                          generate
+             - $filename: (reference to array of) file(s) to generate ToC from
+             - $options:  hash reference containing generator options.
+
+Generate ToC from specified file.  Before generating, the ToC will be cleared.  For extending an extisting ToC, use the L<HTML::TocGenerator::extendFromFile()|"HTML::TocGenerator::extendFromFile()"> method.  For generator options, see L<HTML::TocGenerator Options|"HTML::TocGenerator Options">.
+
+=head2 HTML::TocInsertor::insert()
+
+    syntax:  $tocInsertor->insert($toc, $string [, $options])
+    args:    - $toc:     (reference to array of) HTML::Toc object(s) to insert
+             - $string:  string to insert ToC in
+             - $options: hash reference containing insertor options.
+
+Insert ToC into specified string.  For insertor options, see L<HTML::TocInsertor Options|"HTML::TocInsertor Options">.
+
+=head2 HTML::TocInsertor::insertIntoFile()
+
+    syntax:  $tocInsertor->insertIntoFile($toc, $filename [, $options])
+    args:    - $toc:      (reference to array of) HTML::Toc object(s) to insert
+             - $filename: (reference to array of) file(s) to insert ToC in
+             - $options:  hash reference containing insertor options.
+
+Insert ToC into specified file.  For insertor options, see L<HTML::TocInsertor Options|"HTML::TocInsertor Options">.
+
+=head2 HTML::TocUpdator::insert()
+
+    syntax:  $tocUpdator->insert($toc, $string [, $options])
+    args:    - $toc:     (reference to array of) HTML::Toc object(s) to insert
+             - $string:  string to insert ToC in
+             - $options: hash reference containing updator options.
+
+Insert ToC into specified string.  Differs from L<HTML::TocInsertor::insert()|"HTML::TocInsertor::insert()"> in that inserted text will be surrounded with update tokens in order for C<HTML::TocUpdator> to be able to update this text the next time an update is issued.  For updator options, see L<HTML::TocUpdator Options|"HTML::TocUpdator Options">.
+
+=head2 HTML::TocUpdator::insertIntoFile()
+
+    syntax:  $tocUpdator->insertIntoFile($toc, $filename [, $options])
+    args:    - $toc:      (reference to array of) HTML::Toc object(s) to insert
+             - $filename: (reference to array of) file(s) to insert ToC in
+             - $options:  hash reference containing updator options.
+
+Insert ToC into specified file.  Differs from L<HTML::TocInsertor::insert()|"HTML::TocInsertor::insert()"> in that inserted text will be surrounded with update tokens in order for C<HTML::TocUpdator> to be able to update this text the next time an update is issued.  For updator options, see L<HTML::TocUpdator Options|"HTML::TocUpdator Options">.
+
+=head2 HTML::TocUpdator::update()
+
+    syntax:  $tocUpdator->update($toc, $string [, $options])
+    args:    - $toc:     (reference to array of) HTML::Toc object(s) to insert
+             - $string:  string to update ToC in
+             - $options: hash reference containing updator options.
+
+Update ToC within specified string.  For updator options, see L<HTML::TocUpdator Options|"HTML::TocUpdator Options">.
+
+=head2 HTML::TocUpdator::updateFile()
+
+    syntax:  $tocUpdator->updateFile($toc, $filename [, $options])
+    args:    - $toc:      (reference to array of) HTML::Toc object(s) to insert
+             - $filename: (reference to array of) file(s) to update ToC in
+             - $options:  hash reference containing updator options.
+
+Update ToC of specified file.  For updator options, see L<HTML::TocUpdator Options|"HTML::TocUpdator Options">.
+
+=head1 Parser Options
+
+When generating a ToC, additional options may be specified which influence the way the ToCs are generated using either C<TocGenerator>, C<TocInsertor> or C<TocUpdator>.  The options must be specified as a hash reference.  For example:
+
+    $tocGenerator->generateFromFile($toc, $filename, {doUseGroupsGlobal => 1});
+
+Available options are:
+
+=over 4
+
+=item L<doGenerateToc|"doGenerateToc">
+
+=item L<doUseGroupsGlobal|"doUseGroupsGlobal">
+
+=item L<output|"output">
+
+=item L<outputFile|"outputFile">
+
+=back
+
+=head2 doGenerateToc
+
+    syntax:         [0|1]
+    default:        1
+    applicable to:  TocInsertor, TocUpdator
+
+True (1) if ToC must be generated.  False (0) if ToC must be inserted only.
+
+=head2 doUseGroupsGlobal
+
+    syntax:         [0|1]
+    default:        0
+    applicable to:  TocGenerator, TocInsertor, TocUpdator
+
+True (1) if group levels must be used globally accross ToCs.  False (0) if not.  This option only makes sense when an array of ToCs is specified.  For example, suppose you want to generate two ToCs, one ToC for '<h1>' tokens and one ToC for '<h2>' tokens, of the file 'index.htm':
+
+    <h1>Chapter</h1>
+    <h2>Paragraph</h2>
+
+Using the default setting of 'doUseGroupsGlobal' => 0:
+
+    use HTML::Toc;
+    use HTML::TocGenerator;
+
+    my $toc1         = HTML::Toc->new();
+    my $toc2         = HTML::Toc->new();
+    my $tocGenerator = HTML::TocGenerator->new();
+
+    $toc1->setOptions({
+       'header'     => '',
+       'footer'     => '',
+       'tokenToToc' => [{'tokenBegin' => '<h1>'}]
+    });
+    $toc2->setOptions({
+       'header'     => '',
+       'footer'     => '',
+       'tokenToToc' => [{'tokenBegin' => '<h2>'}]
+    });
+    $tocGenerator->generateFromFile([$toc1, $toc2], 'index.htm');
+    print $toc1->format() . "\n\n" . $toc2->format();
+
+the output will be:
+
+    <ul>
+       <li><a href=#h-1>Chapter</a>
+    </ul>
+
+    <ul>
+       <li><a href=#h-1>Paragraph</a>
+    </ul>
+
+Each ToC will use its own numbering scheme.  Now if 'C<doUseGroupsGlobal = 1>' is specified:
+
+    $tocGenerator->generateFromFile(
+       [$toc1, $toc2], 'index.htm', {'doUseGroupsGlobal' => 1}
+    );
+
+the output will be:
+
+    <ul>
+       <li><a href=#h-1>Chapter</a>
+    </ul>
+
+    <ul>
+       <li><a href=#h-2>Paragraph</a>
+    </ul>
+
+using a global numbering scheme for all ToCs.
+
+=head2 output
+
+    syntax:         reference to scalar
+    default:        none
+    applicable to:  TocInsertor, TocUpdator
+
+Reference to scalar where the output must be stored in.
+
+=head2 outputFile
+
+    syntax:         scalar
+    default:        none
+    applicable to:  TocInsertor, TocUpdator
+
+Filename to write output to.  If no filename is specified, output will be written to standard output.
+
+=head1 HTML::Toc Options
+
+The C<HTML::Toc> options can be grouped in the following categories:
+
+=over 4
+
+=item L<Generate options|"Generate options">
+
+=item L<Insert options|"Insert options">
+
+=item L<Update options|"Update options">
+
+=item L<Format options|"Format options">
+
+=back
+
+The ToC options must be specified using the 'setOptions' method.  For example:
+
+    my $toc = new HTML::Toc;
+
+    $toc->setOptions({
+       'doNumberToken' => 1,
+       'footer'        => '<!-- End Of ToC -->'
+       'tokenToToc'    => [{
+          'level'          => 1,
+          'tokenBegin'     => '<h1>',
+          'numberingStyle' => 'lower-alpha'
+       }]
+    });
+
+=head2 Generate options
+
+=over 4
+
+=item Token groups
+
+=over 4
+
+=item L<tokenToToc|"tokenToToc">
+
+=over 4
+
+=item L<doNumberToken|"doNumberToken">
+
+=item L<fileSpec|"fileSpec">
+
+=item L<groupId|"groupId">
+
+=item L<level|"level">
+
+=item L<tokenBegin|"tokenBegin">
+
+=item L<tokenEnd|"tokenEnd">
+
+=item L<numberingStyle|"numberingStyle">
+
+=back
+
+=item L<groupToToc|"groupToToc">
+
+=item L<levelToToc|"levelToToc">
+
+=back
+
+=item Numbering tokens
+
+=over 4
+
+=item L<doNumberToken|"doNumberToken">
+
+=item L<numberingStyle|"numberingStyle">
+
+=item L<templateTokenNumber|"templateTokenNumber">
+
+=back
+
+=item Miscellaneous
+
+=over 4
+
+=item L<attributeToExcludeToken|"attributeToExcludeToken">
+
+=item L<attributeToTocToken|"attributeToTocToken">
+
+=item L<groupToToc|"groupToToc">
+
+=item L<levelToToc|"levelToToc">
+
+=back
+
+=item Linking ToC to tokens
+
+=over 4
+
+=item L<doLinkToToken|"doLinkToToken">
+
+=item L<doLinkToFile|"doLinkToFile">
+
+=item L<doLinkToId|"doLinkToId">
+
+=item L<templateAnchorName|"templateAnchorName">
+
+=item L<templateAnchorHrefBegin|"templateAnchorHrefBegin">
+
+=item L<templateAnchorHrefEnd|"templateAnchorHrefEnd">
+
+=item L<templateAnchorNameBegin|"templateAnchorNameBegin">
+
+=item L<templateAnchorNameEnd|"templateAnchorNameEnd">
+
+=back
+
+=back
+
+=head2 Insert options
+
+=over 4
+
+=item L<insertionPoint|"insertionPoint">
+
+=back
+
+=head2 Update options
+
+=over 4
+
+=item L<tokenUpdateBeginAnchorName|"tokenUpdateBeginAnchorName">
+
+=item L<tokenUpdateEndAnchorName|"tokenUpdateEndAnchorName">
+
+=item L<tokenUpdateBeginToc|"tokenUpdateBeginToc">
+
+=item L<tokenUpdateEndToc|"tokenUpdateEndToc">
+
+=item L<tokenUpdateBeginNumber|"tokenUpdateBeginNumber">
+
+=item L<tokenUpdateEndNumber|"tokenUpdateEndNumber">
+
+=back
+
+=head2 Format options
+
+=over 4
+
+=item L<doSingleStepLevel|"doSingleStepLevel">
+
+=item L<doNestGroup|"doNestGroup">
+
+=item L<footer|"footer">
+
+=item L<groupToToc|"groupToToc">
+
+=item L<header|"header">
+
+=item L<levelIndent|"levelIndent">
+
+=item L<levelToToc|"levelToToc">
+
+=item L<templateLevelBegin|"templateLevelBegin">
+
+=item L<templateLevelEnd|"templateLevelEnd">
+
+=back
+
+=head1 HTML::Toc Options Reference
+
+=head2 attributeToExcludeToken
+
+    syntax:  $scalar
+    default: '-'
+
+Token which marks an attribute value in a L<tokenBegin|"tokenBegin"> or L<insertionPoint|"insertionPoint"> token as an attribute value a token should not have to be marked as a ToC token.  See also: L<Using attribute value as ToC entry|"Using attribute value as ToC text">.
+
+=head2 attributeToTocToken
+
+    syntax:  $scalar
+    default: '@'
+
+Token which marks an attribute in a L<tokenBegin|"tokenBegin"> token as an attribute which must be used as ToC text.  See also: L<Using attribute value as ToC entry|"Using attribute value as ToC text">.
+
+=head2 doLinkToToken
+
+    syntax:  [0|1]
+    default: 1
+
+True (1) if ToC must be linked to tokens, False (0) if not.  Note that 'HTML::TocInsertor' must be used to do the actual insertion of the anchor name within the source data.
+
+=head2 doLinkToFile
+
+    syntax:  [0|1]
+    default: 0
+
+True (1) if ToC must be linked to file, False (0) if not.  In effect only when L<doLinkToToken|"doLinkToToken"> equals True (1) and L<templateAnchorHrefBegin|"templateAnchorHrefBegin"> isn't specified.
+
+=head2 doLinkToId
+
+    syntax:  [0|1]
+    default: 0
+
+True (1) if ToC must be linked to tokens by using token ids.  False (0) if ToC must be linked to tokens by using anchor names.
+
+=head2 doNestGroup
+
+    syntax:  [0|1]
+    default: 0
+
+True (1) if groups must be nested in the formatted ToC, False (0) if not.  In effect only when multiple groups are specified within the L<tokenToToc|"tokenToToc"> setting.  For an example, see L<Generate multiple groups in one ToC|"Generate multiple groups in one ToC">.
+
+=head2 doNumberToken
+
+    syntax:  [0|1]
+    default: 0
+
+True (1) if tokens which are used for the ToC generation must be numbered.  This option may be specified both as a global ToC option or within a L<tokenToToc|"tokenToToc"> group.  When specified within a C<tokenToToc> option, the C<doNumberToken> applies to that group only.  For an example, see L<Specify an additional 'Part' group|"Specify an additional 'Part' group">.
+
+=head2 doSingleStepLevel
+
+    syntax:  [0|1]
+    default: 1
+
+True (1) if levels of a formatted ToC must advance one level at a time.  For example, when generating a ToC of a file with a missing '<h2>':
+
+    <h1>Chapter</h1>
+    <h3>Paragraph</h3>
+
+By default, an empty indentation level will be inserted in the ToC:
+
+    <!-- Table of Contents generated by Perl - HTML::Toc -->
+    <ul>
+       <li><a href=#h-1>Header 1</a>
+       <ul>
+          <ul>
+             <li><a href=#h-1.0.1>Header 3</a>
+          </ul>
+       </ul>
+    </ul>
+    <!-- End of generated Table of Contents -->
+
+After specifying:
+
+    $toc->setOptions({'doSingleStepLevel' => 0});
+
+the ToC will not have an indentation level inserted for level 2:
+
+    <!-- Table of Contents generated by Perl - HTML::Toc -->
+    <ul>
+       <li><a href=#h-1>Header 1</a>
+       <ul>
+             <li><a href=#h-1.0.1>Header 3</a>
+       </ul>
+    </ul>
+    <!-- End of generated Table of Contents -->
+
+=head2 fileSpec
+
+    syntax:  <regexp>
+    default: undef
+
+Specifies which files should match the current level.  Valid only if L<doLinkToFile|"doLinkToFile"> equals 1.  For an example, see L<Site map|"Site map">.
+
+=head2 footer
+
+    syntax:  $scalar
+    default: "\n<!-- End of generated Table of Contents -->\n"
+
+String to output at end of ToC.
+
+=head2 groupId
+
+    syntax:  $scalar
+    default: 'h'
+
+Sets the group id attribute of a tokenGroup.  With this attribute it's possible to divide the ToC into multiple groups.  Each group has its own numbering scheme.  For example, to generate a ToC of both normal headings and 'appendix' headings, specify the following ToC settings:
+
+    $toc->setOptions({
+       'tokenToToc' => [{
+              'tokenBegin' => '<h1 class=-appendix>'
+           }, {
+              'groupId' => 'appendix',
+              'tokenBegin' => '<h1 class=appendix>'
+       }]
+    });
+
+=head2 groupToToc
+
+    syntax:  <regexp>
+    default: '.*'
+
+Determines which groups to use for generating the ToC.  For example, to create a ToC for groups [a-b] only, specify:
+
+    'groupToToc => '[a-b]'
+
+This option is evaluated during both ToC generation and ToC formatting.  This enables you to generate a ToC of all groups, but - after generating - format only specified groups:
+
+    $toc->setOptions({'groupToToc' => '.*'});
+    $tocGenerator->generateToc($toc, ...);
+        # Get ToC of all groups
+    $fullToc = $toc->format();
+        # Get ToC of 'appendix' group only
+    $toc->setOptions({'groupToToc' => 'appendix'});
+    $appendixToc = $toc->format();
+
+=head2 header
+
+    syntax:  $scalar
+    default: "\n<!-- Table of Contents generated by Perl - HTML::Toc -->\n"
+
+String to output at begin of ToC.
+
+
+=head2 insertionPoint
+
+    syntax:  [<before|after|replace>] <token>
+    default: 'after <body>'
+    token:   <[/]tag{ attribute=[-|@]<regexp>}> |
+             <text regexp> |
+             <declaration regexp> |
+             <comment regexp>
+
+Determines the point within the source, where the ToC should be inserted.  When specifying a start tag as the insertion point token, attributes to be included may be specified as well.  Note that the attribute value must be specified as a regular expression.  For example, to specify the C<<h1 class=header>> tag as insertion point:
+
+    '<h1 class=^header$>'
+
+Examples of valid 'insertionPoint' tokens are:
+
+    '<h1>'
+    '</h1>'
+    '<!-- ToC -->'
+    '<!ToC>'
+    'ToC will be placed here'
+
+It is also possible to specify attributes to exclude, by prefixing the value with an L<attributeToExcludeToken|"attributeToExcludeToken">, default a minus sign (-).  For example, to specify the C<<h1>> tag as insertion point, excluding all C<<h1 class=header>> tags:
+
+    '<h1 class=-^header$>'
+
+See also L<tokenBegin|"tokenBegin">.
+
+=head2 level
+
+    syntax:  number
+    default: 1
+
+Number which identifies at which level the tokengroup should be incorporated into the ToC.  See also: L<tokenToToc|"tokenToToc">.
+
+=head2 levelIndent
+
+    syntax:  number
+    default: 3
+
+Sets the number of spaces each level will be indented, when formatting the ToC.
+
+=head2 levelToToc
+
+    syntax:  <regexp>
+    default: '.*'
+
+Determines which group levels to use for generating the ToC.  For example, to create a ToC for levels 1-2 only, specify:
+
+    'levelToToc => '[1-2]'
+
+This option is evaluated during both ToC generation and ToC formatting.  This enables you to generate a ToC of all levels, but - after generating - retrieve only specified levels:
+
+    $toc->setOptions({'levelToToc' => '.*'});
+    $tocGenerator->generateToc($toc, ...);
+        # Get ToC of all levels
+    $fullToc = $toc->getToc();
+        # Get ToC of level 1 only
+    $toc->setOptions({'levelToToc' => '1'});
+    $level1Toc = $toc->getToc();
+
+=head2 numberingStyle
+
+    syntax:  [decimal|lower-alpha|upper-alpha|lower-roman|upper-roman]}
+    default: decimal
+
+Determines which numbering style to use for a token group when L<doLinkToToken|"doLinkToToken"> is set to True (1).  When specified as a main ToC option, the setting will be the default for all groups.  When specified within a tokengroup, this setting will override any default for that particular tokengroup, e.g.:
+
+    $toc->setOptions({
+       'doNumberToken' => 1,
+       'tokenToToc' => [{
+          'level'          => 1,
+          'tokenBegin'     => '<h1>',
+          'numberingStyle' => 'lower-alpha'
+       }]
+    });
+
+If C<roman> style is specified, be sure to have the Roman module installed, available from L<http://www.perl.com/CPAN/modules/by-module/Roman>.
+
+=head2 templateAnchorName
+
+    syntax:  <expression|function reference>
+    default: '$groupId."-".$node'
+
+Anchor name to use when L<doLinkToToken|"doLinkToToken"> is set to True (1).  The anchor name is passed to both L<templateAnchorHrefBegin|"templateAnchorHrefBegin"> and L<templateAnchorNameBegin|"templateAnchorNameBegin">.  The template may be specified as either an expression or a function reference.  The expression may contain the following variables:
+
+    $file
+    $groupId
+    $level
+    $node
+
+If C<templateAnchorHrefBegin> is a function reference to a function returning the anchor, like in:
+
+    $toc->setOptions({'templateAnchorName' => \&assembleAnchorName});
+
+the function will be called with the following arguments:
+
+    $anchorName = assembleAnchorName($file, $groupId, $level, $node);
+
+=head2 templateAnchorHrefBegin
+
+    syntax:  <expression|function reference>
+    default: '"<a href=#$anchorName>"' or
+             '"<a href=$file#$anchorName>"',
+             depending on 'doLinkToFile' being 0 or 1 respectively.
+
+Anchor reference begin token to use when L<doLinkToToken|"doLinkToToken"> is set to True (1).  The template may be specified as either an expression or a function reference.  The expression may contain the following variables:
+
+    $file
+    $groupId
+    $level
+    $node
+    $anchorName
+
+If C<templateAnchorHrefBegin> is a function reference to a function returning the anchor, like in:
+
+    $toc->setOptions({'templateAnchorHrefBegin' => \&assembleAnchorHrefBegin});
+
+the function will be called with the following arguments:
+
+    $anchorHrefBegin = &assembleAnchorHrefBegin(
+       $file, $groupId, $level, $node, $anchorName
+    );
+
+See also: L<templateAnchorName|"templateAnchorName">, L<templateAnchorHrefEnd|"templateAnchorHrefEnd">.
+
+=head2 templateAnchorHrefEnd
+
+    syntax:  <expression|function reference>
+    default: '"</a>"'
+
+Anchor reference end token to use when L<doLinkToToken|"doLinkToToken"> is set to True (1).  The template may be specified as either an expression or a function reference.  If L<templateAnchorHrefEnd|"templateAnchorHrefEnd"> is a function reference to a function returning the anchor end, like in:
+
+    $toc->setOptions({'templateAnchorHrefEnd' => \&assembleAnchorHrefEnd});
+
+the function will be called without arguments:
+
+    $anchorHrefEnd = &assembleAnchorHrefEnd;
+
+See also: L<templateAnchorHrefBegin|"templateAnchorHrefBegin">.
+
+=head2 templateAnchorNameBegin
+
+    syntax:  <expression|function reference>
+    default: '"<a name=$anchorName>"'
+
+Anchor name begin token to use when L<doLinkToToken|"doLinkToToken"> is set to True (1).  The template may be specified as either an expression or a function reference.  The expression may contain the following variables:
+
+    $file
+    $groupId
+    $level
+    $node
+    $anchorName
+
+If C<templateAnchorNameBegin> is a function reference to a function returning the anchor name, like in:
+
+    $toc->setOptions({'templateAnchorNameBegin' => \&assembleAnchorNameBegin});
+
+the function will be called with the following arguments:
+
+    $anchorNameBegin = assembleAnchorNameBegin(
+        $file, $groupId, $level, $node, $anchorName
+    );
+
+See also: L<templateAnchorName|"templateAnchorName">, L<templateAnchorNameEnd|"templateAnchorNameEnd">.
+
+=head2 templateAnchorNameEnd
+
+    syntax:  <expression|function reference>
+    default: '"</a>"'
+
+Anchor name end token to use when L<doLinkToToken|"doLinkToToken"> is set to True (1).  The template may be specified as either an expression or a function reference.  If L<templateAnchorNameEnd|"templateAnchorNameEnd"> is a function reference to a function returning the anchor end, like in:
+
+    $toc->setOptions({'templateAnchorNameEnd' => \&assembleAnchorNameEnd});
+
+the function will be called without arguments:
+
+    $anchorNameEnd = &assembleAnchorNameEnd;
+
+See also: L<templateAnchorNameBegin|"templateAnchorNameBegin">.
+
+=head2 templateLevel
+
+    syntax:  <expression|function reference>
+    default: '"<li>$text\n"'
+
+Expression to use when formatting a ToC node.  The template may be specified as either an expression or a function reference.  The expression may contain the following variables:
+
+    $level
+    $groupId
+    $node
+    $sequenceNr
+    $text
+
+If C<templateLevel> is a function reference to a function returning the ToC node, like in:
+
+    $toc->setOptions({'templateLevel' => \&AssembleTocNode});
+
+the function will be called with the following arguments:
+
+    $tocNode = &AssembleTocNode(
+        $level, $groupId, $node, $sequenceNr, $text
+    );
+
+=head2 templateLevelBegin
+
+    syntax:  <expression>
+    default: '"<ul>\n"'
+
+Expression to use when formatting begin of ToC level.  See L<templateLevel|"templateLevel"> for list of available variables to use within the expression.  For example, to give each ToC level a class name to use with Cascading Style Sheets (CSS), use the expression:
+
+    '"<ul class=toc_$groupId$level>\n"'
+
+which will result in each ToC group being given a class name:
+
+    <ul class=toc_h1>
+       <li>Header
+    </ul>
+
+For an example, see L<Using CSS for ToC formatting|"Using CSS for ToC formatting">.
+
+=head2 templateLevelEnd
+
+    syntax:  <expression>
+    default: '"<ul>\n"'
+
+Expression to use when formatting end of ToC level.  See L<templateLevel|"templateLevel"> for a list of available variables to use within the expression.  The default expression is:
+
+    '"</ul>\n"'
+
+For an example, see L<Using CSS for ToC formatting|"Using CSS for ToC formatting">.
+
+=head2 templateTokenNumber
+
+    syntax:  <expression|function reference>
+    default: '"$node &nbsp;"'
+
+Token number to use when L<doNumberToken|"doNumberToken"> equals True (1).  The template may be specified as either an expression or a function reference.  The expression has access to the following variables:
+
+    $file
+    $groupId
+    $groupLevel
+    $level
+    $node
+    $toc
+
+If C<templateTokenNumber> is a function reference to a function returning the token number, like in:
+
+    $toc->setOptions({'templateTokenNumber' => \&assembleTokenNumber});
+
+the function will be called with the following arguments:
+
+    $number = &assembleTokenNumber(
+        $node, $groupId, $file, $groupLevel, $level, $toc
+    );
+
+=head2 tokenBegin
+
+    syntax:  <token>
+    default: '<h1>'
+    token:   <[/]tag{ attribute=[-|@]<regexp>}> |
+             <text regexp> |
+             <declaration regexp> |
+             <comment regexp>
+
+This scalar defines the token that will trigger text to be put into the ToC.  Any start tag, end tag, comment, declaration or text string can be specified.  Examples of valid 'tokenBegin' tokens are:
+
+    '<h1>'
+    '</end>'
+    '<!-- Start ToC entry -->'
+    '<!Start ToC entry>'
+    'ToC entry'
+
+When specifying a start tag, attributes to be included may be specified as well.  Note that the attribute value is used as a regular expression.  For example, to specify the C<<h1 class=header>> tag as tokenBegin:
+
+    '<h1 class=^header$>'
+
+It is also possible to specify attributes to exclude, by prefixing the value with an L<attributeToExcludeToken|"attributeToExcludeToken">, default a minus sign (-).  For example, to specify the C<<h1>> tag as tokenBegin, excluding all C<<h1 class=header>> tags:
+
+    '<h1 class=-^header$>'
+
+Also, you can specify here an attribute value which has to be used as ToC text, by prefixing the value with an L<attributeToTocToken|"">, default an at sign (@).  For example, to use the class value as ToC text:
+
+    '<h1 class=@>'
+
+See L<Generate multiple ToCs|"Generate multiple ToCs"> for an elaborated example using the C<attributeToTocToken> to generate a ToC of image C<alt> attribute values.
+
+See also: L<tokenEnd|"tokenEnd">, L<tokenToToc|"tokenToToc">.
+
+=head2 tokenEnd
+
+    syntax:  $scalar
+    default: empty string ('') or end tag counterpart of 'tokenBegin' if 
+             'tokenBegin' is a start tag
+
+The 'tokenEnd' definition applies to the same rules as L<tokenBegin|"tokenBegin">.
+
+See also: L<tokenBegin|"tokenBegin">, L<tokenToToc|"tokenToToc">.
+
+=head2 tokenToToc
+
+    syntax:  [{array of hashrefs}]
+    default: [{
+                'level'      => 1,
+                'tokenBegin' => '<h1>'
+             }, {
+                'level'      => 2,
+                'tokenBegin' => '<h2>'
+             }, {
+                'level'      => 3,
+                'tokenBegin' => '<h3>'
+             }, {
+                'level'      => 4,
+                'tokenBegin' => '<h4>'
+             }, {
+                'level'      => 5,
+                'tokenBegin' => '<h5>'
+             }, {
+                'level'      => 6,
+                'tokenBegin' => '<h6>'
+             }]
+
+This hash define the tokens that must act as ToC entries.  Each tokengroup may contain a L<groupId|"groupId">, L<level|"level">, L<numberingStyle|"numberingStyle">, L<tokenBegin|"tokenBegin"> and L<tokenEnd|"tokenEnd"> identifier.
+
+=head2 tokenUpdateBeginAnchorName
+
+    syntax:  <string>
+    default: '<!-- #BeginTocAnchorNameBegin -->';
+
+This token marks the begin of an anchor name, inserted by C<HTML::TocInsertor>.  This option is used by C<HTML::TocUpdator>.
+
+=head2 tokenUpdateEndAnchorName
+
+    syntax:  <string>
+    default: '<!-- #EndTocAnchorName -->';
+
+This option is used by C<HTML::TocUpdator>, to mark the end of an inserted anchor name.
+
+=head2 tokenUpdateBeginNumber
+
+    syntax:  <string>
+    default: '<!-- #BeginTocNumber -->';
+
+This option is used by C<HTML::TocUpdator>, to mark the begin of an inserted number.
+
+=head2 tokenUpdateEndNumber
+
+    syntax:  <string>
+    default: '<!-- #EndTocAnchorName -->';
+
+This option is used by C<HTML::TocUpdator>, to mark the end of an inserted number.
+
+=head2 tokenUpdateBeginToc
+
+    syntax:  <string>
+    default: '<!-- #BeginToc -->';
+
+This option is used by C<HTML::TocUpdator>, to mark the begin of an inserted ToC.
+
+=head2 tokenUpdateEndToc
+
+    syntax:  <string>
+    default: '<!-- #EndToc -->';
+
+This option is used by C<HTML::TocUpdator>, to mark the end of an inserted ToC.
+
+=head1 Known issues
+
+=head2 Cygwin
+
+In order for the test files to run on Cygwin without errors, the 'UNIX' default text file type has to be selected during the Cygwin setup.
+When extracting the tar.gz file with WinZip the 'TAR file smart CR/LF conversion' has to be turned off via {Options|Configuration...|Miscellaneous} in order for the files 'toc.pod' and './manualTest/manualTest1.htm' to be left in UNIX format.
+
+=head2 Nested anchors
+
+HTML::Toc can only link to existing anchors if these anchors are placed outside of the ToC tokens.  Otherwise a warning will be given.  For example, generating a L<linked|"doLinkToToken"> ToC of C<E<lt>h1E<gt>> tokens of the following text:
+
+    <a name=foo><h1>Header</h1></a>
+
+will go all right, whereas:
+
+    <h1><a name=foo>Header</a></h1>
+
+will yield the warning:
+
+    warning (1): Nested anchor '<a name=foo>' within anchor '<a name=h-1>'.
+
+since anchor names aren't allowed to be nested according to the HTML 4.01 specification.
+
+=head1 AUTHOR
+
+Freddy Vulto E<lt>L<"fvu@fvu.myweb.nl">E<gt>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2001 Freddy Vulto.  All rights reserved.
+
+This library is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=cut
diff --git a/examples/includes/HTML-Toc-0.91/TocGenerator.pm b/examples/includes/HTML-Toc-0.91/TocGenerator.pm
new file mode 100644 (file)
index 0000000..8c49194
--- /dev/null
@@ -0,0 +1,1793 @@
+#=== HTML::TocGenerator =======================================================
+# function: Generate 'HTML::Toc' table of contents.
+# note:     - 'TT' is an abbrevation of 'TocToken'.
+
+
+package HTML::TocGenerator;
+
+
+use strict;
+use HTML::Parser;
+
+
+BEGIN {
+       use vars qw(@ISA $VERSION);
+
+       $VERSION = '0.91';
+
+       @ISA = qw(HTML::Parser);
+}
+
+
+       # Warnings
+use constant WARNING_NESTED_ANCHOR_PS_WITHIN_PS               => 1;
+use constant WARNING_TOC_ATTRIBUTE_PS_NOT_AVAILABLE_WITHIN_PS => 2;
+
+
+use constant TOC_TOKEN_ID       => 0;
+use constant TOC_TOKEN_INCLUDE  => 1;
+use constant TOC_TOKEN_EXCLUDE  => 2;
+use constant TOC_TOKEN_TOKENS   => 3;
+use constant TOC_TOKEN_GROUP    => 4;
+use constant TOC_TOKEN_TOC      => 5;
+
+       # Token types
+use constant TT_TAG_BEGIN                => 0;
+use constant TT_TAG_END                  => 1;
+use constant TT_TAG_TYPE_END             => 2;
+use constant TT_INCLUDE_ATTRIBUTES_BEGIN => 3;
+use constant TT_EXCLUDE_ATTRIBUTES_BEGIN => 4;
+use constant TT_INCLUDE_ATTRIBUTES_END   => 5;
+use constant TT_EXCLUDE_ATTRIBUTES_END   => 6;
+use constant TT_GROUP                    => 7;
+use constant TT_TOC                      => 8;
+use constant TT_ATTRIBUTES_TOC           => 9;
+
+
+use constant CONTAINMENT_INCLUDE => 0;
+use constant CONTAINMENT_EXCLUDE => 1;
+
+use constant TEMPLATE_ANCHOR            => '$groupId."-".$node';
+use constant TEMPLATE_ANCHOR_HREF       => 
+                                       '"<a href=#".' . TEMPLATE_ANCHOR . '.">"';
+use constant TEMPLATE_ANCHOR_HREF_FILE  => 
+                                       '"<a href=".$file."#".' . TEMPLATE_ANCHOR . '.">"';
+use constant TEMPLATE_ANCHOR_NAME       => 
+                                       '"<a name=".' . TEMPLATE_ANCHOR . '.">"';
+
+use constant TEMPLATE_TOKEN_NUMBER      => '"$node &nbsp"';
+
+
+use constant TT_TOKENTYPE_START        => 0;
+use constant TT_TOKENTYPE_END          => 1;
+use constant TT_TOKENTYPE_TEXT         => 2;
+use constant TT_TOKENTYPE_COMMENT      => 3;
+use constant TT_TOKENTYPE_DECLARATION  => 4;
+
+
+END {}
+
+
+#--- HTML::TocGenerator::new() ------------------------------------------------
+# function: Constructor
+
+sub new {
+               # Get arguments
+       my ($aType) = @_;
+       my $self = $aType->SUPER::new;
+               # Bias to not generate ToC
+       $self->{_doGenerateToc} = 0;
+               # Bias to not use global groups
+       $self->{_doUseGroupsGlobal} = 0;
+               # Output
+       $self->{output} = "";
+               # Reset internal variables
+       $self->_resetBatchVariables();
+
+       $self->{options} = {};
+
+       return $self;
+}  # new()
+
+
+#--- HTML::TocGenerator::_deinitializeBatch() ---------------------------------
+
+sub _deinitializeBatch() {
+               # Get arguments
+       my ($self) = @_;
+}  # _deinitializeBatch()
+
+
+#--- HTML::TocGenerator::_deinitializeExtenderBatch() -------------------------
+
+sub _deinitializeExtenderBatch() {
+               # Get arguments
+       my ($self) = @_;
+               # Do general batch deinitialization
+       $self->_deinitializeBatch();
+               # Indicate end of ToC generation
+       $self->{_doGenerateToc} = 0;
+               # Reset batch variables
+       $self->_resetBatchVariables();
+}  # _deinitializeExtenderBatch()
+
+
+#--- HTML::TocGenerator::_deinitializeGeneratorBatch() ------------------------
+
+sub _deinitializeGeneratorBatch() {
+               # Get arguments
+       my ($self) = @_;
+               # Do 'extender' batch deinitialization
+       $self->_deinitializeExtenderBatch();
+}  # _deinitializeBatchGenerator()
+
+
+#--- HTML::TocGenerator::_doesHashContainHash() -------------------------------
+# function: Determines whether hash1 matches regular expressions of hash2.
+# args:     - $aHash1
+#           - $aHash2
+#           - $aContainmentType: 0 (include) or 1 (exclude)
+# returns:  True (1) if hash1 satisfies hash2, 0 if not.  For example, with the
+#           following hashes:
+#
+#              %hash1 = {                                                      %hash2 = {
+#                 'class' => 'header'                          'class' => '^h'
+#                 'id'    => 'intro'         }
+#              }
+#
+#           the routine will return 1 if 'aContainmentType' equals 0, cause
+#           'hash1' satisfies the conditions of 'hash2'.  The routine will
+#           return 0 if 'aContainmentType' equals 1, cause 'hash1' doesn't
+#           exclude the conditions of 'hash2'.
+# note:     Class function.
+
+sub _doesHashContainHash {
+               # Get arguments
+       my ($aHash1, $aHash2, $aContainmentType) = @_;
+               # Local variables
+       my ($key1, $value1, $key2, $value2, $result);
+               # Bias to success
+       $result = 1;
+               # Loop through hash2
+       HASH2: while (($key2, $value2) = each %$aHash2) {
+               # Yes, values are available;
+                       # Get value1
+               $value1 = $aHash1->{$key2};
+                       # Does value1 match criteria of value2?
+               if (defined($value1) && $value1 =~ m/$value2/) {
+                       # Yes, value1 matches criteria of value2;
+                               # Containment type was exclude?
+                       if ($aContainmentType == CONTAINMENT_EXCLUDE) {
+                               # Yes, containment type was exclude;
+                                       # Indicate condition fails
+                               $result = 0;
+                                       # Reset 'each' iterator which we're going to break
+                               keys %$aHash2;
+                                       # Break loop
+                               last HASH2;
+                       }
+               }
+               else {
+                       # No, value1 didn't match criteria of value2;
+                               # Containment type was include?
+                       if ($aContainmentType == CONTAINMENT_INCLUDE) {
+                               # Yes, containment type was include;
+                                       # Indicate condition fails
+                               $result = 0;
+                                       # Reset 'each' iterator which we're going to break
+                               keys %$aHash2;
+                                       # Break loop
+                               last HASH2;
+                       }
+               }
+       }
+               # Return value
+       return $result;
+}  # _doesHashContainHash()
+
+
+#--- HTML::TocGenerator::_extend() --------------------------------------------
+# function: Extend ToC.
+#           - $aString: String to parse.
+
+sub _extend {
+               # Get arguments
+       my ($self, $aFile) = @_;
+               # Local variables
+       my ($file);
+               # Parse string
+       $self->parse($aFile);
+               # Flush remaining buffered text
+       $self->eof();
+}  # _extend()
+
+
+#--- HTML::TocGenerator::_extendFromFile() ------------------------------------
+# function: Extend ToC.
+#           - $aFile: (reference to array of) file to parse.
+
+sub _extendFromFile {
+               # Get arguments
+       my ($self, $aFile) = @_;
+               # Local variables
+       my ($file, @files);
+               # Dereference array reference or make array of file specification
+       @files = (ref($aFile) =~ m/ARRAY/) ? @$aFile : ($aFile);
+               # Loop through files
+       foreach $file (@files) {
+                       # Store filename
+               $self->{_currentFile} = $file;
+                       # Parse file
+               $self->parse_file($file);
+                       # Flush remaining buffered text
+               $self->eof();
+       }
+}  # _extendFromFile()
+
+
+#--- HTML::TocGenerator::_formatHeadingLevel() --------------------------------
+# function: Format heading level.
+# args:     - $aLevel: Level of current heading
+#           - $aClass: Class of current heading
+#           - $aGroup: Group of current heading
+#           - $aToc: Toc of current heading
+
+sub _formatHeadingLevel {
+               # Get arguments
+       my ($self, $aLevel, $aClass, $aGroup, $aToc) = @_;
+               # Local variables
+       my ($result, $headingNumber, $numberingStyle);
+
+       $headingNumber = $self->_getGroupIdManager($aToc)->
+               {levels}{$aClass}[$aLevel - 1] || 0;
+
+               # Alias numbering style of current group
+       $numberingStyle = $aGroup->{numberingStyle};
+
+       SWITCH: {
+               if ($numberingStyle eq "decimal") {
+                       $result = $headingNumber;
+                       last SWITCH;
+               }
+               if ($numberingStyle eq "lower-alpha") {
+                       $result = chr($headingNumber + ord('a') - 1);
+                       last SWITCH;
+               }
+               if ($numberingStyle eq "upper-alpha") {
+                       $result = chr($headingNumber + ord('A') - 1);
+                       last SWITCH;
+               }
+               if ($numberingStyle eq "lower-roman") {
+                       require Roman;
+                       $result = Roman::roman($headingNumber);
+                       last SWITCH;
+               }
+               if ($numberingStyle eq "upper-roman") {
+                       require Roman;
+                       $result = Roman::Roman($headingNumber);
+                       last SWITCH;
+               }
+               die "Unknown case: $numberingStyle";
+       }
+               # Return value
+       return $result;
+}      # _formatHeadingLevel()
+
+
+#--- HTML::TocGenerator::_formatTocNode() -------------------------------------
+# function: Format heading node.
+# args:     - $aLevel: Level of current heading
+#           - $aClass: Class of current heading
+#           - $aGroup: Group of current heading
+#           - $aToc: Toc of current heading
+
+sub _formatTocNode {
+               # Get arguments
+       my ($self, $aLevel, $aClass, $aGroup, $aToc) = @_;
+               # Local variables
+       my ($result, $level, $levelGroups);
+
+               # Alias 'levelGroups' of right 'groupId'
+       $levelGroups = $aToc->{_levelGroups}{$aGroup->{'groupId'}};
+               # Loop through levels
+       for ($level = 1; $level <= $aLevel; $level++) {
+                       # If not first level, add dot
+               $result = ($result ? $result . "." : $result);
+                       # Format heading level using argument group
+               $result .= $self->_formatHeadingLevel(
+                       $level, $aClass, @{$levelGroups}[$level - 1], $aToc
+               );
+       }
+               # Return value
+       return $result;
+}  # _formatTocNode()
+       
+       
+#--- HTML::TocGenerator::_generate() ------------------------------------------
+# function: Generate ToC.
+# args:     - $aString: Reference to string to parse
+
+sub _generate {
+               # Get arguments
+       my ($self, $aString) = @_;
+               # Local variables
+       my ($toc);
+               # Loop through ToCs
+       foreach $toc (@{$self->{_tocs}}) {
+                       # Clear ToC
+               $toc->clear();
+       }
+               # Extend ToCs
+       $self->_extend($aString);
+}  # _generate()
+
+
+#--- HTML::TocGenerator::_generateFromFile() ----------------------------------
+# function: Generate ToC.
+# args:     - $aFile: (reference to array of) file to parse.
+
+sub _generateFromFile {
+               # Get arguments
+       my ($self, $aFile) = @_;
+               # Local variables
+       my ($toc);
+               # Loop through ToCs
+       foreach $toc (@{$self->{_tocs}}) {
+                       # Clear ToC
+               $toc->clear();
+       }
+               # Extend ToCs
+       $self->_extendFromFile($aFile);
+}  # _generateFromFile()
+
+
+#--- HTML::TocGenerator::_getGroupIdManager() ---------------------------------
+# function: Get group id manager.
+# args:     - $aToc: Active ToC.
+# returns:  Group id levels.
+
+sub _getGroupIdManager {
+               # Get arguments
+       my ($self, $aToc) = @_;
+               # Local variables
+       my ($result);
+               # Global groups?
+       if ($self->{options}{'doUseGroupsGlobal'}) {
+               # Yes, global groups;
+               $result = $self;
+       }
+       else {
+               # No, local groups;
+               $result = $aToc;
+       }
+               # Return value
+       return $result;
+}  # _getGroupIdManager()
+
+
+#--- HTML::TocGenerator::_initializeBatch() -----------------------------------
+# function: Initialize batch.  This function is called once when a parse batch
+#           is started.
+# args:     - $aTocs: Reference to array of tocs.
+
+sub _initializeBatch {
+               # Get arguments
+       my ($self, $aTocs) = @_;
+               # Local variables
+       my ($toc);
+
+               # Store reference to tocs
+               
+               # Is ToC specification reference to array?
+       if (ref($aTocs) =~ m/ARRAY/) {
+               # Yes, ToC specification is reference to array;
+                       # Store array reference
+               $self->{_tocs} = $aTocs;
+       }
+       else {
+               # No, ToC specification is reference to ToC object;
+                       # Wrap reference in array reference, containing only one element
+               $self->{_tocs} = [$aTocs];
+       }
+               # Loop through ToCs
+       foreach $toc (@{$self->{_tocs}}) {
+                       # Parse ToC options
+               $toc->parseOptions();
+       }
+}  # _initializeBatch()
+
+
+#--- HTML::TocGenerator::_initializeExtenderBatch() --------------------------
+# function: Initialize 'extender' batch.  This function is called once when a 
+#           parse batch is started.
+# args:     - $aTocs: Reference to array of tocs.
+
+sub _initializeExtenderBatch {
+               # Get arguments
+       my ($self, $aTocs) = @_;
+               # Do general batch initialization
+       $self->_initializeBatch($aTocs);
+               # Parse ToC options
+       $self->_parseTocOptions();
+               # Indicate start of batch
+       $self->{_doGenerateToc} = 1;
+}  # _initializeExtenderBatch()
+
+
+#--- HTML::TocGenerator::_initializeGeneratorBatch() --------------------------
+# function: Initialize generator batch.  This function is called once when a 
+#           parse batch is started.
+# args:     - $aTocs: Reference to array of tocs.
+#           - $aOptions: optional options
+
+sub _initializeGeneratorBatch {
+               # Get arguments
+       my ($self, $aTocs, $aOptions) = @_;
+               # Add invocation options
+       $self->setOptions($aOptions);
+               # Option 'doUseGroupsGlobal' specified?
+       if (!defined($self->{options}{'doUseGroupsGlobal'})) {
+               # No, options 'doUseGroupsGlobal' not specified;
+                       # Default to no 'doUseGroupsGlobal'
+               $self->{options}{'doUseGroupsGlobal'} = 0;
+       }
+               # Global groups?
+       if ($self->{options}{'doUseGroupsGlobal'}) {
+               # Yes, global groups;
+                       # Reset groups and levels
+               $self->_resetStackVariables();
+       }
+               # Do 'extender' batch initialization
+       $self->_initializeExtenderBatch($aTocs);
+}  # _initializeGeneratorBatch()
+
+
+#--- HTML::TocGenerator::_linkTocToToken() ------------------------------------
+# function: Link ToC to token.
+# args:     - $aToc: ToC to add token to.
+#           - $aFile
+#           - $aGroupId
+#           - $aLevel
+#           - $aNode
+#           - $aGroupLevel
+#           - $aLinkType
+#           - $aTokenAttributes: reference to hash containing attributes of 
+#                currently parsed token
+
+sub _linkTocToToken {
+               # Get arguments
+       my (
+               $self, $aToc, $aFile, $aGroupId, $aLevel, $aNode, $aGroupLevel, 
+               $aDoLinkToId, $aTokenAttributes
+       ) = @_;
+               # Local variables
+       my ($file, $groupId, $level, $node, $anchorName);
+       my ($doInsertAnchor, $doInsertId);
+
+               # Fill local arguments to be used by templates
+       $file    = $aFile;
+       $groupId = $aGroupId;
+       $level   = $aLevel;
+       $node    = $aNode;
+       
+               # Assemble anchor name
+       $anchorName = 
+               ref($aToc->{_templateAnchorName}) eq "CODE" ?
+                       &{$aToc->{_templateAnchorName}}(
+                               $aFile, $aGroupId, $aLevel, $aNode
+                       ) : 
+                       eval($aToc->{_templateAnchorName});
+
+               # Bias to insert anchor name
+       $doInsertAnchor = 1;
+       $doInsertId     = 0;
+               # Link to 'id'?
+       if ($aDoLinkToId) {
+               # Yes, link to 'id';
+                       # Indicate to insert anchor id
+               $doInsertAnchor = 0;
+               $doInsertId     = 1;
+                       # Id attribute is available?
+               if (defined($aTokenAttributes->{id})) {
+                       # Yes, id attribute is available;
+                               # Use existing ids?
+                       if ($aToc->{options}{'doUseExistingIds'}) {
+                               # Yes, use existing ids;
+                                       # Use existing id
+                               $anchorName = $aTokenAttributes->{id};
+                                       # Indicate to not insert id
+                               $doInsertId = 0;
+                       }
+               }
+
+       }
+       else {
+               # No, link to 'name';
+                       # Anchor name is currently active?
+               if (defined($self->{_activeAnchorName})) {
+                       # Yes, anchor name is currently active;
+                               # Use existing anchors?
+                       if ($aToc->{options}{'doUseExistingAnchors'}) {
+                               # Yes, use existing anchors;
+                                       # Use existing anchor name
+                               $anchorName = $self->{_activeAnchorName};
+                                       # Indicate to not insert anchor name
+                               $doInsertAnchor = 0;
+                       }
+                       else {
+                               # No, don't use existing anchors; insert new anchor;
+                                       # 
+                       }
+               }
+       }
+
+               # Add reference to ToC
+       $aToc->{_toc} .= 
+               ref($aToc->{_templateAnchorHrefBegin}) eq "CODE" ?
+                       &{$aToc->{_templateAnchorHrefBegin}}(
+                               $aFile, $aGroupId, $aLevel, $aNode, $anchorName
+                       ) : 
+                       eval($aToc->{_templateAnchorHrefBegin});
+
+               # Bias to not output anchor name end
+       $self->{_doOutputAnchorNameEnd} = 0;
+               # Must anchor be inserted?
+       if ($doInsertAnchor) {
+               # Yes, anchor must be inserted;
+                       # Allow adding of anchor name begin token to text by calling 
+                       # 'anchorNameBegin' method
+               $self->anchorNameBegin(
+                       ref($aToc->{_templateAnchorNameBegin}) eq "CODE" ?
+                               &{$aToc->{_templateAnchorNameBegin}}(
+                                       $aFile, $aGroupId, $aLevel, $aNode, $anchorName
+                               ) :
+                               eval($aToc->{_templateAnchorNameBegin}),
+                       $aToc
+               );
+       }
+
+               # Must anchorId attribute be inserted?
+       if ($doInsertId) {
+               # Yes, anchorId attribute must be inserted;
+                       # Allow adding of anchorId attribute to text by calling 'anchorId'
+                       # method
+               $self->anchorId($anchorName);
+       }
+}  # _linkTocToToken()
+
+
+#--- HTML::TocGenerator::_outputAnchorNameEndConditionally() ------------------
+# function: Output 'anchor name end' if necessary
+# args:     - $aToc: ToC of which 'anchor name end' must be output.
+
+sub _outputAnchorNameEndConditionally {
+               # Get arguments
+       my ($self, $aToc) = @_;
+               # Must anchor name end be output?
+       if ($self->{_doOutputAnchorNameEnd}) {
+               # Yes, output anchor name end;
+                       # Allow adding of anchor to text by calling 'anchorNameEnd' 
+                       # method
+               $self->anchorNameEnd(
+                       ref($aToc->{_templateAnchorNameEnd}) eq "CODE" ?
+                               &{$aToc->{_templateAnchorNameEnd}} :
+                               eval($aToc->{_templateAnchorNameEnd}),
+                       $aToc
+               );
+       }
+}  # _outputAnchorNameEndConditionally()
+
+
+#--- HTML::TocGenerator::_parseTocOptions() -----------------------------------
+# function: Parse ToC options.
+
+sub _parseTocOptions {
+               # Get arguments
+       my ($self) = @_;
+               # Local variables
+       my ($toc, $group, $tokens, $tokenType, $i);
+               # Create parsers for ToC tokens
+       $self->{_tokensTocBegin} = [];
+       my $tokenTocBeginParser = HTML::_TokenTocBeginParser->new(
+               $self->{_tokensTocBegin}
+       );
+       my $tokenTocEndParser = HTML::_TokenTocEndParser->new();
+               # Loop through ToCs
+       foreach $toc (@{$self->{_tocs}}) {
+                       # Reference parser ToC to current ToC
+               $tokenTocBeginParser->setToc($toc);
+                       # Loop through 'tokenToToc' groups
+               foreach $group (@{$toc->{options}{'tokenToToc'}}) {
+                               # Reference parser group to current group
+                       $tokenTocBeginParser->setGroup($group);
+                               # Parse 'tokenToToc' group
+                       $tokenTocBeginParser->parse($group->{'tokenBegin'});
+                               # Flush remaining buffered text
+                       $tokenTocBeginParser->eof();
+                       $tokenTocEndParser->parse(
+                               $group->{'tokenEnd'}, 
+                               $tokenTocBeginParser->{_lastAddedToken},
+                               $tokenTocBeginParser->{_lastAddedTokenType}
+                       );
+                               # Flush remaining buffered text
+                       $tokenTocEndParser->eof();
+               }
+       }
+}  # _parseTocOptions()
+
+
+#--- HTML::TocGenerator::_processTocEndingToken() -----------------------------
+# function: Process ToC-ending-token.
+# args:     - $aTocToken: token which acts as ToC-ending-token.
+
+sub _processTocEndingToken {
+               # Get arguments
+       my ($self, $aTocToken) = @_;
+               # Local variables
+       my ($toc);
+               # Aliases
+       $toc = $aTocToken->[TT_TOC];
+               # Link ToC to tokens?
+       if ($toc->{options}{'doLinkToToken'}) {
+               # Yes, link ToC to tokens;
+                       # Add anchor href end
+               $toc->{_toc} .= 
+                       (ref($toc->{_templateAnchorHrefEnd}) eq "CODE") ?
+                               &{$toc->{_templateAnchorHrefEnd}} : 
+                               eval($toc->{_templateAnchorHrefEnd});
+
+                       # Output anchor name end only if necessary
+               $self->_outputAnchorNameEndConditionally($toc);
+       }
+}  # _processTocEndingToken()
+
+
+#--- HTML::TocGenerator::_processTocStartingToken() ---------------------------
+# function: Process ToC-starting-token.
+# args:     - $aTocToken: token which acts as ToC-starting-token.
+#           - $aTokenType: type of token.  Can be either TT_TOKENTYPE_START,
+#                _END, _TEXT, _COMMENT or _DECLARATION.
+#           - $aTokenAttributes: reference to hash containing attributes of 
+#                currently parsed token
+#           - $aTokenOrigText: reference to original token text
+
+sub _processTocStartingToken {
+               # Get arguments
+       my ($self, $aTocToken, $aTokenType, $aTokenAttributes, $aTokenOrigText) = @_;
+               # Local variables
+       my ($i, $level, $doLinkToId, $node, $groupLevel);
+       my ($file, $tocTokenId, $groupId, $toc, $attribute);
+               # Aliases
+       $file        = $self->{_currentFile};
+       $toc                = $aTocToken->[TT_TOC];
+       $level      = $aTocToken->[TT_GROUP]{'level'};
+       $groupId            = $aTocToken->[TT_GROUP]{'groupId'};
+
+               # Retrieve 'doLinkToId' setting from either group options or toc options
+       $doLinkToId = (defined($aTocToken->[TT_GROUP]{'doLinkToId'})) ?
+               $aTocToken->[TT_GROUP]{'doLinkToId'} : $toc->{options}{'doLinkToId'}; 
+       
+               # Link to 'id' and tokenType isn't 'start'?
+       if (($doLinkToId) && ($aTokenType != TT_TOKENTYPE_START)) {
+               # Yes, link to 'id' and tokenType isn't 'start';
+                       # Indicate to *not* link to 'id'
+               $doLinkToId = 0;
+       }
+
+       if (ref($level) eq "CODE") {
+               $level = &$level($self->{_currentFile}, $node);
+       }
+       if (ref($groupId) eq "CODE") {
+               $groupId = &$groupId($self->{_currentFile}, $node);
+       }
+
+               # Determine class level
+
+       my $groupIdManager = $self->_getGroupIdManager($toc);
+               # Known group?
+       if (!exists($groupIdManager->{groupIdLevels}{$groupId})) {
+               # No, unknown group;
+                       # Add group
+               $groupIdManager->{groupIdLevels}{$groupId} = keys(
+                       %{$groupIdManager->{groupIdLevels}}
+               ) + 1;
+       }
+       $groupLevel = $groupIdManager->{groupIdLevels}{$groupId};
+
+               # Temporarily allow symbolic references
+       #no strict qw(refs);
+               # Increase level
+       $groupIdManager->{levels}{$groupId}[$level - 1] += 1;
+               # Reset remaining levels of same group
+       for ($i = $level; $i < @{$groupIdManager->{levels}{$groupId}}; $i++) {
+               $groupIdManager->{levels}{$groupId}[$i] = 0;
+       }
+
+               # Assemble numeric string indicating current level
+       $node = $self->_formatTocNode(
+               $level, $groupId, $aTocToken->[TT_GROUP], $toc
+       );
+
+               # Add newline if _toc not empty
+       if ($toc->{_toc}) { 
+               $toc->{_toc} .= "\n";
+       }
+
+               # Add toc item info
+       $toc->{_toc} .= "$level $groupLevel $groupId $node " .
+               $groupIdManager->{levels}{$groupId}[$level - 1] . " ";
+
+               # Add value of 'id' attribute if available
+       if (defined($aTokenAttributes->{id})) {
+               $toc->{_toc} .= $aTokenAttributes->{id};
+       }
+       $toc->{_toc} .= " ";
+               # Link ToC to tokens?
+       if ($toc->{options}{'doLinkToToken'}) {
+               # Yes, link ToC to tokens;
+                       # Link ToC to token
+               $self->_linkTocToToken(
+                       $toc, $file, $groupId, $level, $node, $groupLevel, $doLinkToId,
+                       $aTokenAttributes
+               );
+       }
+
+               # Number tokens?
+       if (
+               $aTocToken->[TT_GROUP]{'doNumberToken'} || 
+               (
+                       ! defined($aTocToken->[TT_GROUP]{'doNumberToken'}) && 
+                       $toc->{options}{'doNumberToken'}
+               )
+       ) {
+               # Yes, number tokens;
+                       # Add number by calling 'number' method
+               $self->number(
+                       ref($toc->{_templateTokenNumber}) eq "CODE" ?
+                               &{$toc->{_templateTokenNumber}}(
+                                       $node, $groupId, $file, $groupLevel, $level, $toc
+                               ) : 
+                               eval($toc->{_templateTokenNumber}),
+                       $toc
+               );
+       }
+
+               # Must attribute be used as ToC text?
+       if (defined($aTocToken->[TT_ATTRIBUTES_TOC])) {
+               # Yes, attribute must be used as ToC text;
+                       # Loop through attributes
+               foreach $attribute (@{$aTocToken->[TT_ATTRIBUTES_TOC]}) {
+                               # Attribute is available?
+                       if (defined($$aTokenAttributes{$attribute})) {
+                               # Yes, attribute is available;
+                                       # Add attribute value to ToC
+                               $self->_processTocText($$aTokenAttributes{$attribute}, $toc);
+                       }
+                       else {
+                               # No, attribute isn't available;
+                                       # Show warning
+                               $self->_showWarning(
+                                       WARNING_TOC_ATTRIBUTE_PS_NOT_AVAILABLE_WITHIN_PS,
+                                       [$attribute, $$aTokenOrigText]
+                               );
+                       }
+                               # Output anchor name end only if necessary
+                       #$self->_outputAnchorNameEndConditionally($toc);
+                               # End attribute
+                       $self->_processTocEndingToken($aTocToken);
+               }
+       }
+       else {
+               # No, attribute mustn't be used as ToC text;
+                       # Add end token to 'end token array'
+               push(
+                       @{$self->{_tokensTocEnd}[$aTocToken->[TT_TAG_TYPE_END]]}, $aTocToken
+               );
+       }
+}  # _processTocStartingToken()
+
+
+#--- HTML::TocGenerator::_processTocText() ------------------------------------
+# function: This function processes text which must be added to the preliminary
+#           ToC.
+# args:     - $aText: Text to add to ToC.
+#           - $aToc: ToC to add text to.
+
+sub _processTocText {
+               # Get arguments
+       my ($self, $aText, $aToc) = @_;
+               # Add text to ToC
+       $aToc->{_toc} .= $aText;
+}  # _processTocText()
+
+
+#--- HTML::TocGenerator::_processTokenAsTocEndingToken() ----------------------
+# function: Check for token being a token to use for triggering the end of
+#           a ToC line and process it accordingly.
+# args:     - $aTokenType: type of token: 'start', 'end', 'comment' or 'text'.
+#           - $aTokenId: token id of currently parsed token
+
+sub _processTokenAsTocEndingToken {
+               # Get arguments
+       my ($self, $aTokenType, $aTokenId) = @_;
+               # Local variables
+       my ($i, $tokenId, $toc, $tokens);
+               # Loop through dirty start tokens
+       $i = 0;
+
+               # Alias token array of right type
+       $tokens = $self->{_tokensTocEnd}[$aTokenType];
+               # Loop through token array
+       while ($i < scalar @$tokens) {
+                       # Aliases
+               $tokenId = $tokens->[$i][TT_TAG_END];
+                       # Does current end tag equals dirty tag?
+               if ($aTokenId eq $tokenId) {
+                       # Yes, current end tag equals dirty tag;
+                               # Process ToC-ending-token
+                       $self->_processTocEndingToken($tokens->[$i]);
+                               # Remove dirty tag from array, automatically advancing to
+                               # next token
+                       splice(@$tokens, $i, 1);
+               }
+               else {
+                       # No, current end tag doesn't equal dirty tag;
+                               # Advance to next token
+                       $i++;
+               }
+       }
+}  # _processTokenAsTocEndingToken()
+
+
+#--- HTML::TocGenerator::_processTokenAsTocStartingToken() --------------------
+# function: Check for token being a ToC-starting-token and process it 
+#           accordingly.
+# args:     - $aTokenType: type of token.  Can be either TT_TOKENTYPE_START,
+#                _END, _TEXT, _COMMENT or _DECLARATION.
+#           - $aTokenId: token id of currently parsed token
+#           - $aTokenAttributes: reference to hash containing attributes of 
+#                currently parsed token
+#           - $aTokenOrigText: reference to original text of token
+# returns:  1 if successful, i.e. token is processed as ToC-starting-token, 0
+#           if not.
+
+sub _processTokenAsTocStartingToken {
+               # Get arguments
+       my ($self, $aTokenType, $aTokenId, $aTokenAttributes, $aTokenOrigText) = @_;
+               # Local variables
+       my ($level, $levelToToc, $groupId, $groupToToc);
+       my ($result, $tocToken, $tagBegin, @tokensTocBegin, $fileSpec);
+               # Bias to token not functioning as ToC-starting-token
+       $result = 0;
+               # Loop through start tokens of right type
+       foreach $tocToken (@{$self->{_tokensTocBegin}[$aTokenType]}) {
+                       # Alias file filter
+               $fileSpec = $tocToken->[TT_GROUP]{'fileSpec'};
+                       # File matches?
+               if (!defined($fileSpec) || (
+                       defined($fileSpec) &&
+                       ($self->{_currentFile} =~ m/$fileSpec/)
+               )) {
+                       # Yes, file matches;
+                               # Alias tag begin
+                       $tagBegin = $tocToken->[TT_TAG_BEGIN];
+                               # Tag and attributes match?
+                       if (
+                               defined($tagBegin) && 
+                               ($aTokenId =~ m/$tagBegin/) && 
+                               HTML::TocGenerator::_doesHashContainHash(
+                                       $aTokenAttributes, $tocToken->[TT_INCLUDE_ATTRIBUTES_BEGIN], 0
+                               ) &&
+                               HTML::TocGenerator::_doesHashContainHash(
+                                       $aTokenAttributes, $tocToken->[TT_EXCLUDE_ATTRIBUTES_BEGIN], 1
+                               )
+                       ) {
+                               # Yes, tag and attributes match;
+                                       # Aliases
+                               $level      = $tocToken->[TT_GROUP]{'level'};
+                               $levelToToc = $tocToken->[TT_TOC]{options}{'levelToToc'};
+                               $groupId     = $tocToken->[TT_GROUP]{'groupId'}; 
+                               $groupToToc = $tocToken->[TT_TOC]{options}{'groupToToc'};
+                                       # Must level and group be processed?
+                               if (
+                                       ($level =~ m/$levelToToc/) &&
+                                       ($groupId =~ m/$groupToToc/)
+                               ) {
+                                       # Yes, level and group must be processed;
+                                               # Indicate token acts as ToC-starting-token
+                                       $result = 1;
+                                               # Process ToC-starting-token
+                                       $self->_processTocStartingToken(
+                                               $tocToken, $aTokenType, $aTokenAttributes, $aTokenOrigText
+                                       );
+                               }
+                       }
+               }
+       }
+               # Return value
+       return $result;
+}  # _processTokenAsTocStartingToken()
+
+
+#--- HTML::TocGenerator::_resetBatchVariables() -------------------------------
+# function: Reset variables which are set because of batch invocation.
+
+sub _resetBatchVariables {
+               # Get arguments
+       my ($self) = @_;
+
+               # Filename of current file being parsed, empty string if not available
+       $self->{_currentFile} = "";
+               # Arrays containing start, end, comment, text & declaration tokens which 
+               # must trigger the ToC assembling.  Each array element may contain a 
+               # reference to an array containing the following elements:
+               #
+      #    TT_TAG_BEGIN                => 0;
+      #    TT_TAG_END                  => 1;
+      #    TT_TAG_TYPE_END             => 2;
+      #    TT_INCLUDE_ATTRIBUTES_BEGIN => 3;
+      #    TT_EXCLUDE_ATTRIBUTES_BEGIN => 4;
+      #    TT_INCLUDE_ATTRIBUTES_END   => 5;
+      #    TT_EXCLUDE_ATTRIBUTES_END   => 6;
+      #    TT_GROUP                    => 7;
+      #    TT_TOC                      => 8;
+               #    TT_ATTRIBUTES_TOC           => 9;
+               #
+       $self->{_tokensTocBegin} = [
+               [],  # TT_TOKENTYPE_START      
+               [],  # TT_TOKENTYPE_END        
+               [],  # TT_TOKENTYPE_COMMENT    
+               [],  # TT_TOKENTYPE_TEXT       
+               []   # TT_TOKENTYPE_DECLARATION
+       ];
+       $self->{_tokensTocEnd} = [
+               [],  # TT_TOKENTYPE_START      
+               [],  # TT_TOKENTYPE_END        
+               [],  # TT_TOKENTYPE_COMMENT    
+               [],  # TT_TOKENTYPE_TEXT       
+               []   # TT_TOKENTYPE_DECLARATION
+       ];
+               # TRUE if ToCs have been initialized, FALSE if not.
+       $self->{_doneInitializeTocs} = 0;
+               # Array of ToCs to process
+       $self->{_tocs} = [];
+               # Active anchor name
+       $self->{_activeAnchorName} = undef;
+}  # _resetBatchVariables()
+
+
+#--- HTML::TocGenerator::_resetStackVariables() -------------------------------
+# function: Reset variables which cumulate during ToC generation.
+
+sub _resetStackVariables {
+               # Get arguments
+       my ($self) = @_;
+               # Reset variables
+       $self->{levels}        = undef;
+       $self->{groupIdLevels} = undef;
+}  # _resetStackVariables()
+
+
+#--- HTML::TocGenerator::_setActiveAnchorName() -------------------------------
+# function: Set active anchor name.
+# args:     - aAnchorName: Name of anchor name to set active.
+
+sub _setActiveAnchorName {
+               # Get arguments
+       my ($self, $aAnchorName) = @_;
+               # Set active anchor name
+       $self->{_activeAnchorName} = $aAnchorName;
+}  # _setActiveAnchorName()
+
+
+#--- HTML::TocGenerator::_showWarning() ---------------------------------------
+# function: Show warning.
+# args:     - aWarningNr: Number of warning to show.
+#           - aWarningArgs: Arguments to display within the warning.
+
+sub _showWarning {
+               # Get arguments
+       my ($self, $aWarningNr, $aWarningArgs) = @_;
+               # Local variables
+       my (%warnings);
+               # Set warnings
+       %warnings = (
+               WARNING_NESTED_ANCHOR_PS_WITHIN_PS()               => 
+                       "Nested anchor '%s' within anchor '%s'.", 
+               WARNING_TOC_ATTRIBUTE_PS_NOT_AVAILABLE_WITHIN_PS() =>
+                       "ToC attribute '%s' not available within token '%s'.",
+       );
+               # Show warning
+       print STDERR "warning ($aWarningNr): " . sprintf($warnings{"$aWarningNr"}, @$aWarningArgs) . "\n";
+}  # _showWarning()
+
+
+#--- HTML::TocGenerator::anchorId() -------------------------------------------
+# function: Anchor id processing method.  Leave it up to the descendant to do 
+#           something useful with it.
+# args:     - $aAnchorId
+#           - $aToc: Reference to ToC to which anchorId belongs.
+
+sub anchorId {
+}  # anchorId()
+
+
+#--- HTML::TocGenerator::anchorNameBegin() ------------------------------------
+# function: Anchor name begin processing method.  Leave it up to the descendant
+#           to do something useful with it.
+# args:     - $aAnchorName
+#           - $aToc: Reference to ToC to which anchorname belongs.
+
+sub anchorNameBegin {
+}  # anchorNameBegin()
+
+
+#--- HTML::TocGenerator::anchorNameEnd() --------------------------------------
+# function: Anchor name end processing method.  Leave it up to the descendant
+#           to do something useful with it.
+# args:     - $aAnchorName
+#           - $aToc: Reference to ToC to which anchorname belongs.
+
+sub anchorNameEnd {
+}  # anchorNameEnd()
+
+
+#--- HTML::TocGenerator::comment() --------------------------------------------
+# function: Process comment.
+# args:     - $aComment: comment text with '<!--' and '-->' tags stripped off.
+
+sub comment {
+               # Get arguments
+       my ($self, $aComment) = @_;
+               # Must a ToC be generated?
+       if ($self->{_doGenerateToc}) {
+               # Yes, a ToC must be generated
+                       # Process end tag as ToC-starting-token
+               $self->_processTokenAsTocStartingToken(
+                       TT_TOKENTYPE_COMMENT, $aComment, undef, \$aComment
+               );
+                       # Process end tag as token which ends ToC registration
+               $self->_processTokenAsTocEndingToken(
+                       TT_TOKENTYPE_COMMENT, $aComment
+               );
+       }
+}  # comment()
+
+
+#--- HTML::TocGenerator::end() ------------------------------------------------
+# function: This function is called every time a closing tag is encountered.
+# args:     - $aTag: tag name (in lower case).
+#           - $aOrigText: tag name including brackets.
+
+sub end {
+               # Get arguments
+       my ($self, $aTag, $aOrigText) = @_;
+               # Local variables
+       my ($tag, $toc, $i);
+               # Must a ToC be generated?
+       if ($self->{_doGenerateToc}) {
+               # Yes, a ToC must be generated
+                       # Process end tag as ToC-starting-token
+               $self->_processTokenAsTocStartingToken(
+                       TT_TOKENTYPE_END, $aTag, undef, \$aOrigText
+               );
+                       # Process end tag as ToC-ending-token
+               $self->_processTokenAsTocEndingToken(
+                       TT_TOKENTYPE_END, $aTag
+               );
+                       # Tag is of type 'anchor'?
+               if (defined($self->{_activeAnchorName}) && ($aTag eq "a")) {
+                       # Yes, tag is of type 'anchor';
+                               # Reset dirty anchor
+                       $self->{_activeAnchorName} = undef;
+               }
+       }
+}  # end()
+
+
+#--- HTML::TocGenerator::extend() ---------------------------------------------
+# function: Extend ToCs.
+# args:     - $aTocs: Reference to array of ToC objects
+#           - $aString: String to parse.
+
+sub extend {
+               # Get arguments
+       my ($self, $aTocs, $aString) = @_;
+               # Initialize TocGenerator batch
+       $self->_initializeExtenderBatch($aTocs);
+               # Extend ToCs
+       $self->_extend($aString);
+               # Deinitialize TocGenerator batch
+       $self->_deinitializeExtenderBatch();
+}  # extend()
+
+
+#--- HTML::TocGenerator::extendFromFile() -------------------------------------
+# function: Extend ToCs.
+# args:     - @aTocs: Reference to array of ToC objects
+#           - @aFiles: Reference to array of files to parse.
+
+sub extendFromFile {
+               # Get arguments
+       my ($self, $aTocs, $aFiles) = @_;
+               # Initialize TocGenerator batch
+       $self->_initializeExtenderBatch($aTocs);
+               # Extend ToCs
+       $self->_extendFromFile($aFiles);
+               # Deinitialize TocGenerator batch
+       $self->_deinitializeExtenderBatch();
+}  # extendFromFile()
+
+
+#--- HTML::TocGenerator::generate() -------------------------------------------
+# function: Generate ToC.
+# args:     - $aToc: Reference to (array of) ToC object(s)
+#           - $aString: Reference to string to parse
+#           - $aOptions: optional options
+
+sub generate {
+               # Get arguments
+       my ($self, $aToc, $aString, $aOptions) = @_;
+               # Initialize TocGenerator batch
+       $self->_initializeGeneratorBatch($aToc, $aOptions);
+               # Do generate ToC
+       $self->_generate($aString);
+               # Deinitialize TocGenerator batch
+       $self->_deinitializeGeneratorBatch();
+}  # generate()
+
+
+#--- HTML::TocGenerator::generateFromFile() -----------------------------------
+# function: Generate ToC.
+# args:     - $aToc: Reference to (array of) ToC object(s)
+#           - $aFile: (reference to array of) file to parse.
+#           - $aOptions: optional options
+
+sub generateFromFile {
+               # Get arguments
+       my ($self, $aToc, $aFile, $aOptions) = @_;
+               # Initialize TocGenerator batch
+       $self->_initializeGeneratorBatch($aToc, $aOptions);
+               # Do generate ToC
+       $self->_generateFromFile($aFile);
+               # Deinitialize TocGenerator batch
+       $self->_deinitializeGeneratorBatch();
+}  # generateFromFile()
+
+
+#--- HTML::TocGenerator::number() ---------------------------------------------
+# function: Heading number processing method.  Leave it up to the descendant
+#           to do something useful with it.
+# args:     - $aNumber
+#           - $aToc: Reference to ToC to which anchorname belongs.
+
+sub number {
+               # Get arguments
+       my ($self, $aNumber, $aToc) = @_;
+}  # number()
+
+
+#--- HTML::TocGenerator::parse() ----------------------------------------------
+# function: Parse scalar.
+# args:     - $aString: string to parse
+
+sub parse {
+               # Get arguments
+       my ($self, $aString) = @_;
+               # Call ancestor
+       $self->SUPER::parse($aString);
+}  # parse()
+
+
+#--- HTML::TocGenerator::parse_file() -----------------------------------------
+# function: Parse file.
+
+sub parse_file {
+               # Get arguments
+       my ($self, $aFile) = @_;
+               # Call ancestor
+       $self->SUPER::parse_file($aFile);
+}  # parse_file()
+
+
+#--- HTML::TocGenerator::setOptions() -----------------------------------------
+# function: Set options.
+# args:     - aOptions: Reference to hash containing options.
+
+sub setOptions {
+               # Get arguments
+       my ($self, $aOptions) = @_;
+               # Options are defined?
+       if (defined($aOptions)) {
+               # Yes, options are defined; add to options
+               %{$self->{options}} = (%{$self->{options}}, %$aOptions);
+       }
+}  # setOptions()
+
+
+#--- HTML::TocGenerator::start() ----------------------------------------------
+# function: This function is called every time an opening tag is encountered.
+# args:     - $aTag: tag name (in lower case).
+#           - $aAttr: reference to hash containing all tag attributes (in lower
+#                case).
+#           - $aAttrSeq: reference to array containing all tag attributes (in 
+#                lower case) in the original order
+#           - $aOrigText: the original HTML text
+
+sub start {
+               # Get arguments
+       my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
+       $self->{isTocToken} = 0;
+               # Start tag is of type 'anchor name'?
+       if ($aTag eq "a" && defined($aAttr->{name})) {
+               # Yes, start tag is of type 'anchor name';
+                       # Is another anchor already active?
+               if (defined($self->{_activeAnchorName})) {
+                       # Yes, another anchor is already active;
+                               # Is the first anchor inserted by 'TocGenerator'?
+                       if ($self->{_doOutputAnchorNameEnd}) {
+                               # Yes, the first anchor is inserted by 'TocGenerator';
+                                       # Show warning
+                               $self->_showWarning(
+                                       WARNING_NESTED_ANCHOR_PS_WITHIN_PS,
+                                       [$aOrigText, $self->{_activeAnchorName}]
+                               );
+                       }
+               }
+                       # Set active anchor name
+               $self->_setActiveAnchorName($aAttr->{name});
+       }
+               # Must a ToC be generated?
+       if ($self->{_doGenerateToc}) {
+               # Yes, a ToC must be generated
+                       # Process start tag as ToC token
+               $self->{isTocToken} = $self->_processTokenAsTocStartingToken(
+                       TT_TOKENTYPE_START, $aTag, $aAttr, \$aOrigText
+               );
+                       # Process end tag as ToC-ending-token
+               $self->_processTokenAsTocEndingToken(
+                       TT_TOKENTYPE_START, $aTag
+               );
+       }
+}  # start()
+
+
+#--- HTML::TocGenerator::text() -----------------------------------------------
+# function: This function is called every time plain text is encountered.
+# args:     - @_: array containing data.
+
+sub text {
+               # Get arguments
+       my ($self, $aText) = @_;
+               # Local variables
+       my ($text, $toc, $i, $token, $tokens);
+               # Must a ToC be generated?
+       if ($self->{_doGenerateToc}) {
+               # Yes, a ToC must be generated
+                       # Are there dirty start tags?
+
+                       # Loop through token types
+               foreach $tokens (@{$self->{_tokensTocEnd}}) {
+                               # Loop though tokens
+                       foreach $token (@$tokens) {
+                                       # Add text to toc
+
+                                       # Alias
+                               $toc = $token->[TT_TOC];
+                                       # Remove possible newlines from text
+                               ($text = $aText) =~ s/\s*\n\s*/ /g;
+                                       # Add text to toc
+                               $self->_processTocText($text, $toc);
+                       }
+               }
+       }
+}  # text()
+
+
+
+
+#=== HTML::_TokenTocParser ====================================================
+# function: Parse 'toc tokens'.  'Toc tokens' mark HTML code which is to be
+#           inserted into the ToC.
+# note:     Used internally.
+
+package HTML::_TokenTocParser;
+
+
+BEGIN {
+       use vars qw(@ISA);
+
+       @ISA = qw(HTML::Parser);
+}
+
+
+END {}
+
+
+#--- HTML::_TokenTocParser::new() ---------------------------------------------
+# function: Constructor
+
+sub new {
+               # Get arguments
+       my ($aType) = @_;
+               # Create instance
+       my $self = $aType->SUPER::new;
+
+               # Return instance
+       return $self;
+}  # new()
+
+
+#--- HTML::_TokenTocParser::_parseAttributes() --------------------------------
+# function: Parse attributes.
+# args:     - $aAttr: Reference to hash containing all tag attributes (in lower
+#                case).
+#           - $aIncludeAttributes: Reference to hash to which 'include
+#                attributes' must be added.
+#           - $aExcludeAttributes: Reference to hash to which 'exclude
+#                attributes' must be added.
+#           - $aTocAttributes: Reference to hash to which 'ToC attributes' 
+#                must be added.
+
+sub _parseAttributes {
+               # Get arguments
+       my (
+               $self, $aAttr, $aIncludeAttributes, $aExcludeAttributes,
+               $aTocAttributes
+       ) = @_;
+               # Local variables
+       my ($key, $value);
+       my ($attributeToExcludeToken, $attributeToTocToken);
+               # Get token which marks attributes which must be excluded
+       $attributeToExcludeToken = $self->{_toc}{options}{'attributeToExcludeToken'};
+       $attributeToTocToken     = $self->{_toc}{options}{'attributeToTocToken'};
+               # Loop through attributes
+       while (($key, $value) = each %$aAttr) {
+                       # Attribute value equals 'ToC token'?
+               if ($value =~ m/$attributeToTocToken/) {
+                       # Yes, attribute value equals 'ToC token';
+                               # Add attribute to 'ToC attributes'
+                       push @$aTocAttributes, $key;
+               }
+               else {
+                       # No, attribute isn't 'ToC' token;
+                               # Attribute value starts with 'exclude token'?
+                       if ($value =~ m/^$attributeToExcludeToken(.*)/) {
+                               # Yes, attribute value starts with 'exclude token';
+                                       # Add attribute to 'exclude attributes'
+                               $$aExcludeAttributes{$key} = "$1";
+                       }
+                       else {
+                               # No, attribute key doesn't start with '-';
+                                       # Add attribute to 'include attributes'
+                               $$aIncludeAttributes{$key} = $value;
+                       }
+               }
+       }
+}  # _parseAttributes()
+
+
+
+
+#=== HTML::_TokenTocBeginParser ===============================================
+# function: Parse 'toc tokens'.  'Toc tokens' mark HTML code which is to be
+#           inserted into the ToC.
+# note:     Used internally.
+
+package HTML::_TokenTocBeginParser;
+
+
+BEGIN {
+       use vars qw(@ISA);
+
+       @ISA = qw(HTML::_TokenTocParser);
+}
+
+END {}
+
+
+#--- HTML::_TokenTocBeginParser::new() ----------------------------------------
+# function: Constructor
+
+sub new {
+               # Get arguments
+       my ($aType, $aTokenArray) = @_;
+               # Create instance
+       my $self = $aType->SUPER::new;
+               # Reference token array
+       $self->{tokens} = $aTokenArray;
+               # Reference to last added token
+       $self->{_lastAddedToken}     = undef;
+       $self->{_lastAddedTokenType} = undef;
+               # Return instance
+       return $self;
+}  # new()
+
+
+#--- HTML::_TokenTocBeginParser::_processAttributes() -------------------------
+# function: Process attributes.
+# args:     - $aAttributes: Attributes to parse.
+
+sub _processAttributes {
+               # Get arguments
+       my ($self, $aAttributes) = @_;
+               # Local variables
+       my (%includeAttributes, %excludeAttributes, @tocAttributes);
+
+               # Parse attributes
+       $self->_parseAttributes(
+               $aAttributes, \%includeAttributes, \%excludeAttributes, \@tocAttributes
+       );
+               # Include attributes are specified?
+       if (keys(%includeAttributes) > 0) {
+               # Yes, include attributes are specified;
+                       # Store include attributes
+               @${$self->{_lastAddedToken}}[
+                       HTML::TocGenerator::TT_INCLUDE_ATTRIBUTES_BEGIN
+               ] = \%includeAttributes;
+       }
+               # Exclude attributes are specified?
+       if (keys(%excludeAttributes) > 0) {
+               # Yes, exclude attributes are specified;
+                       # Store exclude attributes
+               @${$self->{_lastAddedToken}}[
+                       HTML::TocGenerator::TT_EXCLUDE_ATTRIBUTES_BEGIN
+               ] = \%excludeAttributes;
+       }
+               # Toc attributes are specified?
+       if (@tocAttributes > 0) {
+               # Yes, toc attributes are specified;
+                       # Store toc attributes
+               @${$self->{_lastAddedToken}}[
+                       HTML::TocGenerator::TT_ATTRIBUTES_TOC
+               ] = \@tocAttributes;
+       }
+}  # _processAttributes()
+
+
+#--- HTML::_TokenTocBeginParser::_processToken() ------------------------------
+# function: Process token.
+# args:     - $aTokenType: Type of token to process.
+#           - $aTag: Tag of token.
+
+sub _processToken {
+               # Get arguments
+       my ($self, $aTokenType, $aTag) = @_;
+               # Local variables
+       my ($tokenArray, $index);
+               # Push element on array of update tokens
+       $index = push(@{$self->{tokens}[$aTokenType]}, []) - 1;
+               # Alias token array to add element to
+       $tokenArray = $self->{tokens}[$aTokenType];
+               # Indicate last updated token array element
+       $self->{_lastAddedTokenType} = $aTokenType;
+       $self->{_lastAddedToken}     = \$$tokenArray[$index];
+               # Add fields
+       $$tokenArray[$index][HTML::TocGenerator::TT_TAG_BEGIN] = $aTag;
+       $$tokenArray[$index][HTML::TocGenerator::TT_GROUP]     = $self->{_group};
+       $$tokenArray[$index][HTML::TocGenerator::TT_TOC]       = $self->{_toc};
+}  # _processToken()
+
+
+#--- HTML::_TokenTocBeginParser::comment() ------------------------------------
+# function: Process comment.
+# args:     - $aComment: comment text with '<!--' and '-->' tags stripped off.
+
+sub comment {
+               # Get arguments
+       my ($self, $aComment) = @_;
+               # Process token
+       $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_COMMENT, $aComment);
+}  # comment()
+
+
+#--- HTML::_TokenTocBeginParser::declaration() --------------------------------
+# function: This function is called every time a markup declaration is
+#           encountered by HTML::Parser.
+# args:     - $aDeclaration: Markup declaration.
+
+sub declaration {
+               # Get arguments
+       my ($self, $aDeclaration) = @_;
+               # Process token
+       $self->_processToken(
+               HTML::TocGenerator::TT_TOKENTYPE_DECLARATION, $aDeclaration
+       );
+}  # declaration()
+
+       
+#--- HTML::_TokenTocBeginParser::end() ----------------------------------------
+# function: This function is called every time a closing tag is encountered
+#           by HTML::Parser.
+# args:     - $aTag: tag name (in lower case).
+
+sub end {
+               # Get arguments
+       my ($self, $aTag, $aOrigText) = @_;
+               # Process token
+       $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_END, $aTag);
+}  # end()
+
+
+#--- HTML::_TokenTocBeginParser::parse() --------------------------------------
+# function: Parse begin token.
+# args:     - $aToken: 'toc token' to parse
+
+sub parse {
+               # Get arguments
+       my ($self, $aString) = @_;
+               # Call ancestor
+       $self->SUPER::parse($aString);
+}  # parse()
+
+
+#--- HTML::_TokenTocBeginParser->setGroup() -----------------------------------
+# function: Set current 'tokenToToc' group.
+
+sub setGroup {
+               # Get arguments
+       my ($self, $aGroup) = @_;
+               # Set current 'tokenToToc' group
+       $self->{_group} = $aGroup;
+}  # setGroup()
+
+
+#--- HTML::_TokenTocBeginParser->setToc() -------------------------------------
+# function: Set current ToC.
+
+sub setToc {
+               # Get arguments
+       my ($self, $aToc) = @_;
+               # Set current ToC
+       $self->{_toc} = $aToc;
+}  # setToc()
+
+
+#--- HTML::_TokenTocBeginParser::start() --------------------------------------
+# function: This function is called every time an opening tag is encountered.
+# args:     - $aTag: tag name (in lower case).
+#           - $aAttr: reference to hash containing all tag attributes (in lower
+#                case).
+#           - $aAttrSeq: reference to array containing all attribute keys (in 
+#                lower case) in the original order
+#           - $aOrigText: the original HTML text
+
+sub start {
+               # Get arguments
+       my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
+               # Process token
+       $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_START, $aTag);
+               # Process attributes
+       $self->_processAttributes($aAttr);
+}  # start()
+
+
+#--- HTML::_TokenTocBeginParser::text() ---------------------------------------
+# function: This function is called every time plain text is encountered.
+# args:     - @_: array containing data.
+
+sub text {
+               # Get arguments
+       my ($self, $aText) = @_;
+               # Was token already created and is last added token of type 'text'?
+       if (
+               defined($self->{_lastAddedToken}) && 
+               $self->{_lastAddedTokenType} == HTML::TocGenerator::TT_TOKENTYPE_TEXT
+       ) {
+               # Yes, token is already created;
+                       # Add tag to existing token
+               @${$self->{_lastAddedToken}}[HTML::TocGenerator::TT_TAG_BEGIN] .= $aText;
+       }
+       else {
+               # No, token isn't created;
+                       # Process token
+               $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_TEXT, $aText);
+       }
+}  # text()
+
+
+
+
+#=== HTML::_TokenTocEndParser =================================================
+# function: Parse 'toc tokens'.  'Toc tokens' mark HTML code which is to be
+#           inserted into the ToC.
+# note:     Used internally.
+
+package HTML::_TokenTocEndParser;
+
+
+BEGIN {
+       use vars qw(@ISA);
+
+       @ISA = qw(HTML::_TokenTocParser);
+}
+
+
+END {}
+
+
+#--- HTML::_TokenTocEndParser::new() ------------------------------------------
+# function: Constructor
+# args:     - $aType: Class type.
+
+sub new {
+               # Get arguments
+       my ($aType) = @_;
+               # Create instance
+       my $self = $aType->SUPER::new;
+               # Reference to last added token
+       $self->{_lastAddedToken} = undef;
+               # Return instance
+       return $self;
+}  # new()
+
+
+#--- HTML::_TokenTocEndParser::_processAttributes() ---------------------------
+# function: Process attributes.
+# args:     - $aAttributes: Attributes to parse.
+
+sub _processAttributes {
+               # Get arguments
+       my ($self, $aAttributes) = @_;
+               # Local variables
+       my (%includeAttributes, %excludeAttributes);
+
+               # Parse attributes
+       $self->_parseAttributes(
+               $aAttributes, \%includeAttributes, \%excludeAttributes
+       );
+               # Include attributes are specified?
+       if (keys(%includeAttributes) > 0) {
+               # Yes, include attributes are specified;
+                       # Store include attributes
+               @${$self->{_Token}}[
+                       HTML::TocGenerator::TT_INCLUDE_ATTRIBUTES_END
+               ] = \%includeAttributes;
+       }
+               # Exclude attributes are specified?
+       if (keys(%excludeAttributes) > 0) {
+               # Yes, exclude attributes are specified;
+                       # Store exclude attributes
+               @${$self->{_Token}}[
+                       HTML::TocGenerator::TT_EXCLUDE_ATTRIBUTES_END
+               ] = \%excludeAttributes;
+       }
+}  # _processAttributes()
+
+
+#--- HTML::_TokenTocEndParser::_processToken() --------------------------------
+# function: Process token.
+# args:     - $aTokenType: Type of token to process.
+#           - $aTag: Tag of token.
+
+sub _processToken {
+               # Get arguments
+       my ($self, $aTokenType, $aTag) = @_;
+               # Update token
+       @${$self->{_token}}[HTML::TocGenerator::TT_TAG_TYPE_END] = $aTokenType;
+       @${$self->{_token}}[HTML::TocGenerator::TT_TAG_END]      = $aTag;
+               # Indicate token type which has been processed
+       $self->{_lastAddedTokenType} = $aTokenType;
+}  # _processToken()
+
+
+#--- HTML::_TokenTocEndParser::comment() --------------------------------------
+# function: Process comment.
+# args:     - $aComment: comment text with '<!--' and '-->' tags stripped off.
+
+sub comment {
+               # Get arguments
+       my ($self, $aComment) = @_;
+               # Process token
+       $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_COMMENT, $aComment);
+}  # comment()
+
+
+#--- HTML::_TokenTocDeclarationParser::declaration() --------------------------
+# function: This function is called every time a markup declaration is
+#           encountered by HTML::Parser.
+# args:     - $aDeclaration: Markup declaration.
+
+sub declaration {
+               # Get arguments
+       my ($self, $aDeclaration) = @_;
+               # Process token
+       $self->_processToken(
+               HTML::TocGenerator::TT_TOKENTYPE_DECLARATION, $aDeclaration
+       );
+}  # declaration()
+
+       
+#--- HTML::_TokenTocEndParser::end() ------------------------------------------
+# function: This function is called every time a closing tag is encountered
+#           by HTML::Parser.
+# args:     - $aTag: tag name (in lower case).
+
+sub end {
+               # Get arguments
+       my ($self, $aTag, $aOrigText) = @_;
+               # Process token
+       $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_END, $aTag);
+}  # end()
+
+
+#--- HTML::_TokenTocEndParser::parse() ----------------------------------------
+# function: Parse token.
+# args:     - $aString: 'toc token' to parse
+#           - $aToken: Reference to token
+#           - $aTokenTypeBegin: Type of begin token
+
+sub parse {
+               # Get arguments
+       my ($self, $aString, $aToken, $aTokenTypeBegin) = @_;
+               # Token argument specified?
+       if (defined($aToken)) {
+               # Yes, token argument is specified;
+                       # Store token reference
+               $self->{_token} = $aToken;
+       }
+               # End tag defined?
+       if (! defined($aString)) {
+               # No, end tag isn't defined;
+                       # Last added tokentype was of type 'start'?
+               if (
+                       (defined($aTokenTypeBegin)) &&
+                       ($aTokenTypeBegin == HTML::TocGenerator::TT_TOKENTYPE_START) 
+               ) {
+                       # Yes, last added tokentype was of type 'start';
+                               # Assume end tag
+                       $self->_processToken(
+                               HTML::TocGenerator::TT_TAG_END,
+                               @${$self->{_token}}[HTML::TocGenerator::TT_TAG_BEGIN]
+                       );
+               }
+       }
+       else {
+                       # Call ancestor
+               $self->SUPER::parse($aString);
+       }
+}  # parse()
+
+
+#--- HTML::_TokenTocEndParser::start() ----------------------------------------
+# function: This function is called every time an opening tag is encountered.
+# args:     - $aTag: tag name (in lower case).
+#           - $aAttr: reference to hash containing all tag attributes (in lower
+#                case).
+#           - $aAttrSeq: reference to array containing all attribute keys (in 
+#                lower case) in the original order
+#           - $aOrigText: the original HTML text
+
+sub start {
+               # Get arguments
+       my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
+               # Process token
+       $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_START, $aTag);
+               # Process attributes
+       $self->_processAttributes($aAttr);
+}  # start()
+
+
+#--- HTML::_TokenTocEndParser::text() -----------------------------------------
+# function: This function is called every time plain text is encountered.
+# args:     - @_: array containing data.
+
+sub text {
+               # Get arguments
+       my ($self, $aText) = @_;
+
+               # Is token already created?
+       if (defined($self->{_lastAddedTokenType})) {
+               # Yes, token is already created;
+                       # Add tag to existing token
+               @${$self->{_token}}[HTML::TocGenerator::TT_TAG_END] .= $aText;
+       }
+       else {
+               # No, token isn't created;
+                       # Process token
+               $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_TEXT, $aText);
+       }
+}  # text()
+
+
+1;
diff --git a/examples/includes/HTML-Toc-0.91/TocInsertor.pm b/examples/includes/HTML-Toc-0.91/TocInsertor.pm
new file mode 100644 (file)
index 0000000..b554870
--- /dev/null
@@ -0,0 +1,1066 @@
+#--- TocInsertor.pm -----------------------------------------------------------
+# function: Insert Table of Contents HTML::Toc, generated by 
+#           HTML::TocGenerator.
+# note:     - The term 'propagate' is used as a shortcut for the process of 
+#             both generating and inserting a ToC at the same time.
+#           - 'TIP' is an abbreviation of 'Toc Insertion Point'.
+
+
+package HTML::TocInsertor;
+
+
+use strict;
+use FileHandle;
+use HTML::TocGenerator;
+
+
+BEGIN {
+       use vars qw(@ISA $VERSION);
+
+       $VERSION = '0.91';
+
+       @ISA = qw(HTML::TocGenerator);
+}
+
+       # TocInsertionPoint (TIP) constants
+       
+use constant TIP_PREPOSITION_REPLACE => 'replace';
+use constant TIP_PREPOSITION_BEFORE  => 'before';
+use constant TIP_PREPOSITION_AFTER   => 'after';
+
+use constant TIP_TOKEN_ID           => 0;
+use constant TIP_PREPOSITION        => 1;
+use constant TIP_INCLUDE_ATTRIBUTES => 2;
+use constant TIP_EXCLUDE_ATTRIBUTES => 3;
+use constant TIP_TOC                => 4;
+
+use constant MODE_DO_NOTHING   => 0;   # 0b00
+use constant MODE_DO_INSERT    => 1;   # 0b01
+use constant MODE_DO_PROPAGATE => 3;   # 0b11
+
+END {}
+
+
+#--- HTML::TocInsertor::new() -------------------------------------------------
+# function: Constructor.
+
+sub new {
+               # Get arguments
+       my ($aType) = @_;
+       my $self = $aType->SUPER::new;
+               # TRUE if insertion point token must be output, FALSE if not
+       $self->{_doOutputInsertionPointToken} = 1;
+               # Reset batch variables
+       $self->_resetBatchVariables;
+               # Bias to not insert ToC
+       $self->{hti__Mode} = MODE_DO_NOTHING;
+
+               # TODO: Initialize output
+
+       return $self;
+}  # new()
+
+
+#--- HTML::TocInsertor::_deinitializeOutput() ---------------------------------
+# function: Deinitialize output.
+
+sub _deinitializeOutput {
+               # Get arguments
+       my ($self) = @_;
+               # Filehandle is defined?
+       if (defined($self->{_outputFileHandle})) {
+               # Yes, filehandle is defined;
+                       # Restore selected filehandle
+               select($self->{_oldFileHandle});
+                       # Undefine filehandle, closing it automatically
+               undef $self->{_outputFileHandle};
+       }
+}  # _deinitializeOutput()
+
+
+#--- HTML::TocInsertor::_initializeOutput() -----------------------------------
+# function: Initialize output.
+
+sub _initializeOutput {
+               # Get arguments
+       my ($self) = @_;
+               # Bias to write to outputfile
+       my $doOutputToFile = 1;
+
+               # Is output specified?
+       if (defined($self->{options}{'output'})) {
+               # Yes, output is specified;
+                       # Indicate to not output to outputfile
+               $doOutputToFile = 0;
+                       # Alias output reference
+               $self->{_output} = $self->{options}{'output'};
+                       # Clear output
+               ${$self->{_output}} = "";
+       }
+
+               # Is output file specified?
+       if (defined($self->{options}{'outputFile'})) {
+               # Yes, output file is specified;
+                       # Indicate to output to outputfile
+               $doOutputToFile = 1;
+                       # Open file
+               $self->{_outputFileHandle} = 
+                       new FileHandle ">" . $self->{options}{'outputFile'};
+
+                       # Backup currently selected filehandle
+               $self->{_oldFileHandle} = select;
+                       # Set new default filehandle
+               select($self->{_outputFileHandle});
+       }
+
+               # Alias output-to-file indicator
+       $self->{_doOutputToFile} = $doOutputToFile;
+}  # _initializeOutput()
+
+
+#--- HTML::TocInsertor::_deinitializeInsertorBatch() --------------------------
+# function: Deinitialize insertor batch.
+
+sub _deinitializeInsertorBatch {
+               # Get arguments
+       my ($self) = @_;
+               # Indicate ToC insertion has finished
+       $self->{_isTocInsertionPointPassed} = 0;
+               # Write buffered output
+       $self->_writeBufferedOutput();
+               # Propagate?
+       if ($self->{hti__Mode} == MODE_DO_PROPAGATE) {
+               # Yes, propagate;
+                       # Deinitialize generator batch
+               $self->_deinitializeGeneratorBatch();
+       }
+       else {
+               # No, insert only;
+                       # Do general batch deinitialization
+               $self->_deinitializeBatch();
+       }
+               # Deinitialize output
+       $self->_deinitializeOutput();
+               # Indicate end of batch
+       $self->{hti__Mode} = MODE_DO_NOTHING;
+               # Reset batch variables
+       $self->_resetBatchVariables();
+}  # _deinitializeInsertorBatch()
+
+
+#--- HTML::TocInsertor::_initializeInsertorBatch() ----------------------------
+# function: Initialize insertor batch.
+# args:     - $aTocs: Reference to array of tocs.
+#           - $aOptions: optional options
+
+sub _initializeInsertorBatch {
+               # Get arguments
+       my ($self, $aTocs, $aOptions) = @_;
+               # Add invocation options
+       $self->setOptions($aOptions);
+               # Option 'doGenerateToc' specified?
+       if (!defined($self->{options}{'doGenerateToc'})) {
+               # No, options 'doGenerateToc' not specified;
+                       # Default to 'doGenerateToc'
+               $self->{options}{'doGenerateToc'} = 1;
+       }
+               # Propagate?
+       if ($self->{options}{'doGenerateToc'}) {
+               # Yes, propagate;
+                       # Indicate mode
+               $self->{hti__Mode} = MODE_DO_PROPAGATE;
+                       # Initialize generator batch
+                       # NOTE: This method takes care of calling '_initializeBatch()'
+               $self->_initializeGeneratorBatch($aTocs);
+       }
+       else {
+               # No, insert;
+                       # Indicate mode
+               $self->{hti__Mode} = MODE_DO_INSERT;
+                       # Do general batch initialization
+               $self->_initializeBatch($aTocs);
+       }
+               # Initialize output
+       $self->_initializeOutput();
+               # Parse ToC insertion points
+       $self->_parseTocInsertionPoints();
+}  # _initializeInsertorBatch()
+
+
+#--- HTML::TocInsertor::_insert() ---------------------------------------------
+# function: Insert ToC in string.
+# args:     - $aString: Reference to string to parse.
+# note:     Used internally.
+
+sub _insert {
+               # Get arguments
+       my ($self, $aString) = @_;
+               # Propagate?
+       if ($self->{options}{'doGenerateToc'}) {
+               # Yes, propagate;
+                       # Generate & insert ToC
+               $self->_generate($aString);
+       }
+       else {
+               # No, just insert ToC
+                       # Insert by parsing file
+               $self->parse($aString);
+                       # Flush remaining buffered text
+               $self->eof();
+       }
+}  # _insert()
+
+
+#--- HTML::TocInsertor::_insertIntoFile() -------------------------------------
+# function: Do insert generated ToCs in file.
+# args:     - $aToc: (reference to array of) ToC object(s) to insert.
+#           - $aFile: (reference to array of) file(s) to parse for insertion
+#                points.
+#           - $aOptions: optional insertor options
+# note:     Used internally.
+
+sub _insertIntoFile {
+               # Get arguments
+       my ($self, $aFile) = @_;
+               # Local variables;
+       my ($file, @files);
+               # Dereference array reference or make array of file specification
+       @files = (ref($aFile) =~ m/ARRAY/) ? @$aFile : ($aFile);
+               # Loop through files
+       foreach $file (@files) {
+                       # Propagate?
+               if ($self->{options}{'doGenerateToc'}) {
+                       # Yes, propagate;
+                               # Generate and insert ToC
+                       $self->_generateFromFile($file);
+               }
+               else {
+                       # No, just insert ToC
+                               # Insert by parsing file
+                       $self->parse_file($file);
+               }
+       }
+}  # _insertIntoFile()
+
+
+#--- HTML::TocInsertor::_parseTocInsertionPoints() ----------------------------
+# function: Parse ToC insertion point specifier.
+
+sub _parseTocInsertionPoints {
+               # Get arguments
+       my ($self) = @_;
+               # Local variables
+       my ($tipPreposition, $tipToken, $toc, $tokenTipParser);
+               # Create parser for TIP tokens
+       $tokenTipParser = HTML::_TokenTipParser->new(
+               $self->{_tokensTip}
+       );
+               # Loop through ToCs
+       foreach $toc (@{$self->{_tocs}}) {
+                       # Split TIP in preposition and token
+               ($tipPreposition, $tipToken) = split(
+                       '\s+', $toc->{options}{'insertionPoint'}, 2
+               );
+                       # Known preposition?
+               if (
+                       ($tipPreposition ne TIP_PREPOSITION_REPLACE) &&
+                       ($tipPreposition ne TIP_PREPOSITION_BEFORE) &&
+                       ($tipPreposition ne TIP_PREPOSITION_AFTER)
+               ) {
+                       # No, unknown preposition;
+                               # Use default preposition
+                       $tipPreposition = TIP_PREPOSITION_AFTER;
+                               # Use entire 'insertionPoint' as token
+                       $tipToken = $toc->{options}{'insertionPoint'};
+               }
+                       # Indicate current ToC to parser
+               $tokenTipParser->setToc($toc);
+                       # Indicate current preposition to parser
+               $tokenTipParser->setPreposition($tipPreposition);
+                       # Parse ToC Insertion Point
+               $tokenTipParser->parse($tipToken);
+                       # Flush remaining buffered text
+               $tokenTipParser->eof();
+       }
+}  # _parseTocInsertionPoints()
+
+
+#--- HTML::TocInsertor::_processTokenAsInsertionPoint() -----------------------
+# function: Check for token being a ToC insertion point (Tip) token and
+#           process it accordingly.
+# args:     - $aTokenType: type of token: start, end, comment or text.
+#           - $aTokenId: token id of currently parsed token
+#           - $aTokenAttributes: attributes of currently parsed token
+#           - $aOrigText: complete token
+# returns:  1 if successful -- token is processed as insertion point, 0
+#           if not.
+
+sub _processTokenAsInsertionPoint {
+               # Get arguments
+       my ($self, $aTokenType, $aTokenId, $aTokenAttributes, $aOrigText) = @_;
+               # Local variables
+       my ($i, $result, $tipToken, $tipTokenId, $tipTokens);
+               # Bias to token not functioning as a ToC insertion point (Tip) token
+       $result = 0;
+               # Alias ToC insertion point (Tip) array of right type
+       $tipTokens = $self->{_tokensTip}[$aTokenType];
+               # Loop through tipTokens
+       $i = 0;
+       while ($i < scalar @{$tipTokens}) {
+                       # Aliases
+               $tipToken                                = $tipTokens->[$i];
+               $tipTokenId                              = $tipToken->[TIP_TOKEN_ID];
+                       # Id & attributes match?
+               if (
+                       ($aTokenId =~ m/$tipTokenId/) && (
+                               HTML::TocGenerator::_doesHashContainHash(
+                                       $aTokenAttributes, $tipToken->[TIP_INCLUDE_ATTRIBUTES], 0
+                               ) &&
+                               HTML::TocGenerator::_doesHashContainHash(
+                                       $aTokenAttributes, $tipToken->[TIP_EXCLUDE_ATTRIBUTES], 1
+                               )
+                       )
+               ) {
+                       # Yes, id and attributes match;
+                               # Process ToC insertion point
+                       $self->_processTocInsertionPoint($tipToken);
+                               # Indicate token functions as ToC insertion point
+                       $result = 1;
+                               # Remove Tip token, automatically advancing to next token
+                       splice(@$tipTokens, $i, 1);
+               }
+               else {
+                       # No, tag doesn't match ToC insertion point
+                               # Advance to next start token
+                       $i++;
+               }
+       }
+               # Token functions as ToC insertion point?
+       if ($result) {
+               # Yes, token functions as ToC insertion point;
+                       # Process insertion point(s)
+               $self->_processTocInsertionPoints($aOrigText);
+       }
+               # Return value
+       return $result;
+}  # _processTokenAsInsertionPoint()
+
+
+#--- HTML::TocInsertor::toc() -------------------------------------------------
+# function: Toc processing method.  Add toc reference to scenario.
+# args:     - $aScenario: Scenario to add ToC reference to.
+#           - $aToc: Reference to ToC to insert.
+# note:     The ToC hasn't been build yet; only a reference to the ToC to be
+#           build is inserted.
+
+sub toc {
+               # Get arguments
+       my ($self, $aScenario, $aToc) = @_;
+               # Add toc to scenario
+       push(@$aScenario, $aToc);
+}  # toc()
+
+
+#--- HTML::TocInsertor::_processTocInsertionPoint() ----------------------------
+# function: Process ToC insertion point.
+# args:     - $aTipToken: Reference to token array item which matches the ToC 
+#                insertion point.
+
+sub _processTocInsertionPoint {
+               # Get arguments
+       my ($self, $aTipToken) = @_;
+               # Local variables
+       my ($tipToc, $tipPreposition); 
+       
+               # Aliases
+       $tipToc         = $aTipToken->[TIP_TOC];
+       $tipPreposition = $aTipToken->[TIP_PREPOSITION];
+
+       SWITCH: {
+                       # Replace token with ToC?
+               if ($tipPreposition eq TIP_PREPOSITION_REPLACE) {
+                       # Yes, replace token;
+                               # Indicate ToC insertion point has been passed
+                       $self->{_isTocInsertionPointPassed} = 1;
+                               # Add ToC reference to scenario reference by calling 'toc' method
+                       $self->toc($self->{_scenarioAfterToken}, $tipToc);
+                       #push(@{$self->{_scenarioAfterToken}}, $tipTokenToc);
+                               # Indicate token itself must not be output
+                       $self->{_doOutputInsertionPointToken} = 0;
+                       last SWITCH;
+               }
+                       # Output ToC before token?
+               if ($tipPreposition eq TIP_PREPOSITION_BEFORE) {
+                       # Yes, output ToC before token;
+                               # Indicate ToC insertion point has been passed
+                       $self->{_isTocInsertionPointPassed} = 1;
+                               # Add ToC reference to scenario reference by calling 'toc' method
+                       $self->toc($self->{_scenarioBeforeToken}, $tipToc);
+                       #push(@{$self->{_scenarioBeforeToken}}, $tipTokenToc);
+                       last SWITCH;
+               }
+                       # Output ToC after token?
+               if ($tipPreposition eq TIP_PREPOSITION_AFTER) {
+                       # Yes, output ToC after token;
+                               # Indicate ToC insertion point has been passed
+                       $self->{_isTocInsertionPointPassed} = 1;
+                               # Add ToC reference to scenario reference by calling 'toc' method
+                       $self->toc($self->{_scenarioAfterToken}, $tipToc);
+                       #push(@{$self->{_scenarioAfterToken}}, $tipTokenToc);
+                       last SWITCH;
+               }
+       }
+}  # _processTocInsertionPoint()
+
+
+#--- HTML::TocInsertor::_processTocInsertionPoints() --------------------------
+# function: Process ToC insertion points
+# args:     - $aTokenText: Text of token which acts as insertion point for one
+#                or multiple ToCs.
+
+sub _processTocInsertionPoints {
+               # Get arguments
+       my ($self, $aTokenText) = @_;
+               # Local variables
+       my ($outputPrefix, $outputSuffix);
+               # Extend scenario
+       push(@{$self->{_scenario}}, @{$self->{_scenarioBeforeToken}});
+
+       if ($outputPrefix = $self->{_outputPrefix}) {
+               push(@{$self->{_scenario}}, \$outputPrefix);
+               $self->{_outputPrefix} = "";
+       }
+
+               # Must insertion point token be output?
+       if ($self->{_doOutputInsertionPointToken}) {
+               # Yes, output insertion point token;
+               push(@{$self->{_scenario}}, \$aTokenText);
+       }
+
+       if ($outputSuffix = $self->{_outputSuffix}) {
+               push(@{$self->{_scenario}}, \$outputSuffix);
+               $self->{_outputSuffix} = "";
+       }
+
+       push(@{$self->{_scenario}}, @{$self->{_scenarioAfterToken}});
+               # Add new act to scenario for output to come
+       my $output = "";
+       push(@{$self->{_scenario}}, \$output);
+               # Write output, processing possible '_outputSuffix'
+       #$self->_writeOrBufferOutput("");
+               # Reset helper scenario's
+       $self->{_scenarioBeforeToken} = [];
+       $self->{_scenarioAfterToken}  = [];
+               # Reset bias value to output insertion point token
+       $self->{_doOutputInsertionPointToken} = 1;
+
+}  # _processTocInsertionPoints()
+
+
+#--- HTML::Toc::_resetBatchVariables() ----------------------------------------
+# function: Reset batch variables.
+
+sub _resetBatchVariables {
+       my ($self) = @_;
+               # Call ancestor
+       $self->SUPER::_resetBatchVariables();
+               # Array containing references to scalars.  This array depicts the order
+               # in which output must be performed after the first ToC Insertion Point
+               # has been passed.
+       $self->{_scenario}            = [];
+               # Helper scenario
+       $self->{_scenarioBeforeToken} = [];
+               # Helper scenario
+       $self->{_scenarioAfterToken}  = [];
+               # Arrays containing start, end, comment, text & declaration tokens which 
+               # must trigger the ToC insertion.  Each array element may contain a 
+               # reference to an array containing the following elements:
+       $self->{_tokensTip} = [
+               [],     # TT_TOKENTYPE_START
+               [],     # TT_TOKENTYPE_END
+               [],     # TT_TOKENTYPE_COMMENT
+               [],     # TT_TOKENTYPE_TEXT
+               []              # TT_TOKENTYPE_DECLARATION
+       ];
+               # 1 if ToC insertion point has been passed, 0 if not
+       $self->{_isTocInsertionPointPassed} = 0;
+               # Tokens after ToC
+       $self->{outputBuffer} = "";
+               # Trailing text after parsed token
+       $self->{_outputSuffix} = "";
+               # Preceding text before parsed token
+       $self->{_outputPrefix} = "";
+}  # _resetBatchVariables()
+
+
+#--- HTML::TocInsertor::_writeBufferedOutput() --------------------------------
+# function: Write buffered output to output device(s).
+
+sub _writeBufferedOutput {
+               # Get arguments
+       my ($self) = @_;
+               # Local variables
+       my ($scene);
+               # Must ToC be parsed?
+       if ($self->{options}{'parseToc'}) {
+               # Yes, ToC must be parsed;
+                       # Parse ToC
+               #$self->parse($self->{toc});
+                       # Output tokens after ToC
+               #$self->_writeOrBufferOutput($self->{outputBuffer});
+       }
+       else {
+               # No, ToC needn't be parsed;
+                       # Output scenario
+               foreach $scene (@{$self->{_scenario}}) {
+                               # Is scene a reference to a scalar?
+                       if (ref($scene) eq "SCALAR") {
+                               # Yes, scene is a reference to a scalar;
+                                       # Output scene
+                               $self->_writeOutput($$scene);
+                       }
+                       else {
+                               # No, scene must be reference to HTML::Toc;
+                                       # Output toc
+                               $self->_writeOutput($scene->format());
+                       }
+               }
+       }
+}  # _writeBufferedOutput()
+
+
+#--- HTML::TocInsertor::_writeOrBufferOutput() --------------------------------
+# function: Write processed HTML to output device(s).
+# args:     - aOutput: scalar to write
+# note:     If '_isTocInsertionPointPassed' text is buffered before being 
+#           output because the ToC has to be generated before it can be output.
+#           Only after the entire data has been parsed, the ToC and the 
+#           following text will be output.
+
+sub _writeOrBufferOutput {
+               # Get arguments
+       my ($self, $aOutput) = @_;
+
+               # Add possible output prefix and suffix
+       $aOutput = $self->{_outputPrefix} . $aOutput . $self->{_outputSuffix};
+               # Clear output prefix and suffix
+       $self->{_outputPrefix} = "";
+       $self->{_outputSuffix} = "";
+
+               # Has ToC insertion point been passed?
+       if ($self->{_isTocInsertionPointPassed}) {
+               # Yes, ToC insertion point has been passed;
+                       # Buffer output; add output to last '_scenario' item
+               my $index = scalar(@{$self->{_scenario}}) - 1;
+               ${$self->{_scenario}[$index]} .= $aOutput;
+       }
+       else {
+               # No, ToC insertion point hasn't been passed;
+                       # Write output
+               $self->_writeOutput($aOutput);
+       }
+}  # _writeOrBufferOutput()
+
+
+#--- HTML::TocInsertor::_writeOutput() ----------------------------------------
+# function: Write processed HTML to output device(s).
+# args:     - aOutput: scalar to write
+
+sub _writeOutput {
+               # Get arguments
+       my ($self, $aOutput) = @_;
+               # Write output to scalar;
+       ${$self->{_output}} .= $aOutput if (defined($self->{_output}));
+               # Write output to output file
+       print $aOutput if ($self->{_doOutputToFile})
+}  # _writeOutput()
+
+
+#--- HTML::TocGenerator::anchorId() -------------------------------------------
+# function: Anchor id processing method.
+# args:     - $aAnchorId
+
+sub anchorId {
+               # Get arguments
+       my ($self, $aAnchorId) = @_;
+               # Indicate id must be added to start tag
+       $self->{_doAddAnchorIdToStartTag} = 1;
+       $self->{_anchorId} = $aAnchorId;
+}  # anchorId()
+
+
+#--- HTML::TocInsertor::anchorNameBegin() -------------------------------------
+# function: Process anchor name begin, generated by HTML::TocGenerator.
+# args:     - $aAnchorNameBegin: Anchor name begin tag to output.
+#           - $aToc: Reference to ToC to which anchorname belongs.
+
+sub anchorNameBegin {
+               # Get arguments
+       my ($self, $aAnchorNameBegin, $aToc) = @_;
+               # Is another anchorName active?
+       if (defined($self->{_activeAnchorName})) {
+               # Yes, another anchorName is active;
+                       # Show warning
+               print "Warn\n";
+               $self->_showWarning(
+                       HTML::TocGenerator::WARNING_NESTED_ANCHOR_PS_WITHIN_PS,
+                       [$aAnchorNameBegin, $self->{_activeAnchorName}]
+               );
+       }
+               # Store anchor name as output prefix
+       $self->{_outputPrefix} = $aAnchorNameBegin;
+               # Indicate active anchor name
+       $self->{_activeAnchorName} = $aAnchorNameBegin;
+               # Indicate anchor name end must be output
+       $self->{_doOutputAnchorNameEnd} = 1;
+}      # anchorNameBegin()
+
+
+#--- HTML::TocInsertor::anchorNameEnd() ---------------------------------------
+# function: Process anchor name end, generated by HTML::TocGenerator.
+# args:     - $aAnchorNameEnd: Anchor name end tag to output.
+#           - $aToc: Reference to ToC to which anchorname belongs.
+
+sub anchorNameEnd {
+               # Get arguments
+       my ($self, $aAnchorNameEnd) = @_;
+               # Store anchor name as output prefix
+       $self->{_outputSuffix} .= $aAnchorNameEnd;
+               # Indicate deactive anchor name
+       $self->{_activeAnchorName} = undef;
+}      # anchorNameEnd()
+
+
+#--- HTML::TocInsertor::comment() ---------------------------------------------
+# function: Process comment.
+# args:     - $aComment: comment text with '<!--' and '-->' tags stripped off.
+
+sub comment {
+               # Get arguments
+       my ($self, $aComment) = @_;
+               # Local variables
+       my ($tocInsertionPointToken, $doOutput, $origText);
+               # Allow ancestor to process the comment tag
+       $self->SUPER::comment($aComment);
+               # Assemble original comment
+       $origText = "<!--$aComment-->";
+               # Must ToCs be inserted?
+       if ($self->{hti__Mode} & MODE_DO_INSERT) {
+               # Yes, ToCs must be inserted;
+                       # Processing comment as ToC insertion point is successful?
+               if (! $self->_processTokenAsInsertionPoint(
+                       HTML::TocGenerator::TT_TOKENTYPE_COMMENT, $aComment, undef, $origText
+               )) {
+                       # No, comment isn't a ToC insertion point;
+                               # Output comment normally
+                       $self->_writeOrBufferOutput($origText);
+               }
+       }
+}  # comment()
+
+
+#--- HTML::TocInsertor::declaration() -----------------------------------------
+# function: This function is called every time a declaration is encountered
+#           by HTML::Parser.
+
+sub declaration {
+               # Get arguments
+       my ($self, $aDeclaration) = @_;
+               # Allow ancestor to process the declaration tag
+       $self->SUPER::declaration($aDeclaration);
+               # Must ToCs be inserted?
+       if ($self->{hti__Mode} & MODE_DO_INSERT) {
+               # Yes, ToCs must be inserted;
+                       # Processing declaration as ToC insertion point is successful?
+               if (! $self->_processTokenAsInsertionPoint(
+                       HTML::TocGenerator::TT_TOKENTYPE_DECLARATION, $aDeclaration, undef, 
+                       "<!$aDeclaration>"
+               )) {
+                       # No, declaration isn't a ToC insertion point;
+                               # Output declaration normally
+                       $self->_writeOrBufferOutput("<!$aDeclaration>");
+               }
+       }
+}  # declaration()
+
+
+#--- HTML::TocInsertor::end() -------------------------------------------------
+# function: This function is called every time a closing tag is encountered
+#           by HTML::Parser.
+# args:     - $aTag: tag name (in lower case).
+
+sub end {
+               # Get arguments
+       my ($self, $aTag, $aOrigText) = @_;
+               # Allow ancestor to process the end tag
+       $self->SUPER::end($aTag, $aOrigText);
+               # Must ToCs be inserted?
+       if ($self->{hti__Mode} & MODE_DO_INSERT) {
+               # Yes, ToCs must be inserted;
+                       # Processing end tag as ToC insertion point is successful?
+               if (! $self->_processTokenAsInsertionPoint(
+                       HTML::TocGenerator::TT_TOKENTYPE_END, $aTag, undef, $aOrigText
+               )) {
+                       # No, end tag isn't a ToC insertion point;
+                               # Output end tag normally
+                       $self->_writeOrBufferOutput($aOrigText);
+               }
+       }
+}  # end()
+
+
+#--- HTML::TocInsertor::insert() ----------------------------------------------
+# function: Insert ToC in string.
+# args:     - $aToc: (reference to array of) ToC object to insert
+#           - $aString: string to insert ToC in
+#           - $aOptions: hash reference with optional insertor options
+
+sub insert {
+               # Get arguments
+       my ($self, $aToc, $aString, $aOptions) = @_;
+               # Initialize TocInsertor batch
+       $self->_initializeInsertorBatch($aToc, $aOptions);
+               # Do insert Toc
+       $self->_insert($aString);
+               # Deinitialize TocInsertor batch
+       $self->_deinitializeInsertorBatch();
+}  # insert()
+
+
+#--- HTML::TocInsertor::insertIntoFile() --------------------------------------
+# function: Insert ToCs in file.
+# args:     - $aToc: (reference to array of) ToC object(s) to insert.
+#           - $aFile: (reference to array of) file(s) to parse for insertion
+#                points.
+#           - $aOptions: optional insertor options
+
+sub insertIntoFile {
+               # Get arguments
+       my ($self, $aToc, $aFile, $aOptions) = @_;
+               # Initialize TocInsertor batch
+       $self->_initializeInsertorBatch($aToc, $aOptions);
+               # Do insert ToCs into file
+       $self->_insertIntoFile($aFile);
+               # Deinitialize TocInsertor batch
+       $self->_deinitializeInsertorBatch();
+}  # insertIntoFile()
+
+
+#--- HTML::TocInsertor::number() ----------------------------------------------
+# function: Process heading number generated by HTML::Toc.
+# args:     - $aNumber
+
+sub number {
+               # Get arguments
+       my ($self, $aNumber) = @_;
+               # Store heading number as output suffix
+       $self->{_outputSuffix} .= $aNumber;
+}      # number()
+
+
+#--- HTML::TocInsertor::propagateFile() ---------------------------------------
+# function: Propagate ToC; generate & insert ToC, using file as input.
+# args:     - $aToc: (reference to array of) ToC object to insert
+#           - $aFile: (reference to array of) file to parse for insertion
+#                points.
+#           - $aOptions: optional insertor options
+
+sub propagateFile {
+               # Get arguments
+       my ($self, $aToc, $aFile, $aOptions) = @_;
+               # Local variables;
+       my ($file, @files);
+               # Initialize TocInsertor batch
+       $self->_initializeInsertorBatch($aToc, $aOptions);
+               # Dereference array reference or make array of file specification
+       @files = (ref($aFile) =~ m/ARRAY/) ? @$aFile : ($aFile);
+               # Loop through files
+       foreach $file (@files) {
+                       # Generate and insert ToC
+               $self->_generateFromFile($file);
+       }
+               # Deinitialize TocInsertor batch
+       $self->_deinitializeInsertorBatch();
+}  # propagateFile()
+
+
+#--- HTML::TocInsertor::start() -----------------------------------------------
+# function: This function is called every time an opening tag is encountered.
+# args:     - $aTag: tag name (in lower case).
+#           - $aAttr: reference to hash containing all tag attributes (in lower
+#                case).
+#           - $aAttrSeq: reference to array containing all tag attributes (in 
+#                lower case) in the original order
+#           - $aOrigText: the original HTML text
+
+sub start {
+               # Get arguments
+       my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
+               # Local variables
+       my ($doOutput, $i, $tocToken, $tag, $anchorId);
+               # Let ancestor process the start tag
+       $self->SUPER::start($aTag, $aAttr, $aAttrSeq, $aOrigText);
+               # Must ToC be inserted?
+       if ($self->{hti__Mode} & MODE_DO_INSERT) {
+               # Yes, ToC must be inserted;
+                       # Processing start tag as ToC insertion point is successful?
+               if (! $self->_processTokenAsInsertionPoint(
+                       HTML::TocGenerator::TT_TOKENTYPE_START, $aTag, $aAttr, $aOrigText
+               )) {
+                       # No, start tag isn't a ToC insertion point;
+                               # Add anchor id?
+                       if ($self->{_doAddAnchorIdToStartTag}) {
+                               # Yes, anchor id must be added;
+                                       # Reset indicator;
+                               $self->{_doAddAnchorIdToStartTag} = 0;
+                                       # Alias anchor id
+                               $anchorId = $self->{_anchorId};
+                                       # Attribute 'id' already exists?
+                               if (defined($aAttr->{id})) {
+                                       # Yes, attribute 'id' already exists;
+                                               # Show warning
+                                       print STDERR "WARNING: Overwriting existing id attribute '" .
+                                               $aAttr->{id} . "' of tag $aOrigText\n";
+                                       
+                                               # Add anchor id to start tag
+                                       $aOrigText =~ s/(id)=\S*([\s>])/$1=$anchorId$2/i;
+                               }
+                               else {
+                                       # No, attribute 'id' doesn't exist;
+                                               # Add anchor id to start tag
+                                       $aOrigText =~ s/>/ id=$anchorId>/;
+                               }
+                       }
+                               # Output start tag normally
+                       $self->_writeOrBufferOutput($aOrigText);
+               }
+       }
+}  # start()
+
+
+#--- HTML::TocInsertor::text() ------------------------------------------------
+# function: This function is called every time plain text is encountered.
+# args:     - @_: array containing data.
+
+sub text {
+               # Get arguments
+       my ($self, $aText) = @_;
+               # Let ancestor process the text
+       $self->SUPER::text($aText);
+               # Must ToC be inserted?
+       if ($self->{hti__Mode} & MODE_DO_INSERT) {
+               # Yes, ToC must be inserted;
+                       # Processing text as ToC insertion point is successful?
+               if (! $self->_processTokenAsInsertionPoint(
+                       HTML::TocGenerator::TT_TOKENTYPE_TEXT, $aText, undef, $aText
+               )) {
+                       # No, text isn't a ToC insertion point;
+                               # Output text normally
+                       $self->_writeOrBufferOutput($aText);
+               }
+       }
+}  # text()
+
+
+
+
+#=== HTML::_TokenTipParser ====================================================
+# function: Parse 'TIP tokens'.  'TIP tokens' mark HTML code which is to be
+#           used as the ToC Insertion Point.
+# note:     Used internally.
+
+package HTML::_TokenTipParser;
+
+
+BEGIN {
+       use vars qw(@ISA);
+
+       @ISA = qw(HTML::_TokenTocParser);
+}
+
+
+END {}
+
+
+#--- HTML::_TokenTipParser::new() ---------------------------------------------
+# function: Constructor
+
+sub new {
+               # Get arguments
+       my ($aType, $aTokenArray) = @_;
+               # Create instance
+       my $self = $aType->SUPER::new;
+               # Reference token array
+       $self->{tokens} = $aTokenArray;
+               # Reference to last added token
+       $self->{_lastAddedToken}     = undef;
+       $self->{_lastAddedTokenType} = undef;
+               # Return instance
+       return $self;
+}  # new()
+
+
+#--- HTML::_TokenTipParser::_processAttributes() ------------------------------
+# function: Process attributes.
+# args:     - $aAttributes: Attributes to parse.
+
+sub _processAttributes {
+               # Get arguments
+       my ($self, $aAttributes) = @_;
+               # Local variables
+       my (%includeAttributes, %excludeAttributes);
+
+               # Parse attributes
+       $self->_parseAttributes(
+               $aAttributes, \%includeAttributes, \%excludeAttributes
+       );
+               # Include attributes are specified?
+       if (keys(%includeAttributes) > 0) {
+               # Yes, include attributes are specified;
+                       # Store include attributes
+               @${$self->{_lastAddedToken}}[
+                       HTML::TocInsertor::TIP_INCLUDE_ATTRIBUTES
+               ] = \%includeAttributes;
+       }
+               # Exclude attributes are specified?
+       if (keys(%excludeAttributes) > 0) {
+               # Yes, exclude attributes are specified;
+                       # Store exclude attributes
+               @${$self->{_lastAddedToken}}[
+                       HTML::TocInsertor::TIP_EXCLUDE_ATTRIBUTES
+               ] = \%excludeAttributes;
+       }
+}  # _processAttributes()
+
+
+#--- HTML::_TokenTipParser::_processToken() -----------------------------------
+# function: Process token.
+# args:     - $aTokenType: Type of token to process.
+#           - $aTag: Tag of token.
+
+sub _processToken {
+               # Get arguments
+       my ($self, $aTokenType, $aTag) = @_;
+               # Local variables
+       my ($tokenArray, $index);
+               # Push element on array of update tokens
+       $index = push(@{$self->{tokens}[$aTokenType]}, []) - 1;
+               # Alias token array to add element to
+       $tokenArray = $self->{tokens}[$aTokenType];
+               # Indicate last updated token array element
+       $self->{_lastAddedTokenType} = $aTokenType;
+       $self->{_lastAddedToken}     = \$$tokenArray[$index];
+               # Add fields
+       $$tokenArray[$index][HTML::TocInsertor::TIP_TOC]         = $self->{_toc};
+       $$tokenArray[$index][HTML::TocInsertor::TIP_TOKEN_ID]   = $aTag;
+       $$tokenArray[$index][HTML::TocInsertor::TIP_PREPOSITION] =
+               $self->{_preposition};
+}  # _processToken()
+
+
+#--- HTML::_TokenTipParser::comment() -----------------------------------------
+# function: Process comment.
+# args:     - $aComment: comment text with '<!--' and '-->' tags stripped off.
+
+sub comment {
+               # Get arguments
+       my ($self, $aComment) = @_;
+               # Process token
+       $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_COMMENT, $aComment);
+}  # comment()
+
+
+#--- HTML::_TokenTipParser::declaration() --------------------------------
+# function: This function is called every time a markup declaration is
+#           encountered by HTML::Parser.
+# args:     - $aDeclaration: Markup declaration.
+
+sub declaration {
+               # Get arguments
+       my ($self, $aDeclaration) = @_;
+               # Process token
+       $self->_processToken(
+               HTML::TocGenerator::TT_TOKENTYPE_DECLARATION, $aDeclaration
+       );
+}  # declaration()
+
+       
+#--- HTML::_TokenTipParser::end() ----------------------------------------
+# function: This function is called every time a closing tag is encountered
+#           by HTML::Parser.
+# args:     - $aTag: tag name (in lower case).
+
+sub end {
+               # Get arguments
+       my ($self, $aTag, $aOrigText) = @_;
+               # Process token
+       $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_END, $aTag);
+}  # end()
+
+
+#--- HTML::_TokenTipParser->setPreposition() ----------------------------------
+# function: Set current preposition.
+
+sub setPreposition {
+               # Get arguments
+       my ($self, $aPreposition) = @_;
+               # Set current ToC
+       $self->{_preposition} = $aPreposition;
+}  # setPreposition()
+
+
+#--- HTML::_TokenTipParser->setToc() ------------------------------------------
+# function: Set current ToC.
+
+sub setToc {
+               # Get arguments
+       my ($self, $aToc) = @_;
+               # Set current ToC
+       $self->{_toc} = $aToc;
+}  # setToc()
+
+
+#--- HTML::_TokenTipParser::start() --------------------------------------
+# function: This function is called every time an opening tag is encountered.
+# args:     - $aTag: tag name (in lower case).
+#           - $aAttr: reference to hash containing all tag attributes (in lower
+#                case).
+#           - $aAttrSeq: reference to array containing all attribute keys (in 
+#                lower case) in the original order
+#           - $aOrigText: the original HTML text
+
+sub start {
+               # Get arguments
+       my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
+               # Process token
+       $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_START, $aTag);
+               # Process attributes
+       $self->_processAttributes($aAttr);
+}  # start()
+
+
+#--- HTML::_TokenTipParser::text() ---------------------------------------
+# function: This function is called every time plain text is encountered.
+# args:     - @_: array containing data.
+
+sub text {
+               # Get arguments
+       my ($self, $aText) = @_;
+               # Was token already created and is last added token of type 'text'?
+       if (
+               defined($self->{_lastAddedToken}) && 
+               $self->{_lastAddedTokenType} == HTML::TocGenerator::TT_TOKENTYPE_TEXT
+       ) {
+               # Yes, token is already created;
+                       # Add tag to existing token
+               @${$self->{_lastAddedToken}}[HTML::TocGenerator::TT_TAG_BEGIN] .= $aText;
+       }
+       else {
+               # No, token isn't created;
+                       # Process token
+               $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_TEXT, $aText);
+       }
+}  # text()
+
+
+1;
diff --git a/examples/includes/HTML-Toc-0.91/TocUpdator.pm b/examples/includes/HTML-Toc-0.91/TocUpdator.pm
new file mode 100644 (file)
index 0000000..affca9d
--- /dev/null
@@ -0,0 +1,693 @@
+#==== HTML::TocUpdator ========================================================
+# function: Update 'HTML::Toc' table of contents.
+# note:     - 'TUT' is an abbreviation of 'Toc Update Token'.
+
+
+package HTML::TocUpdator;
+
+
+use strict;
+use HTML::TocInsertor;
+
+
+BEGIN {
+       use vars qw(@ISA $VERSION);
+
+       $VERSION = '0.91';
+
+       @ISA = qw(HTML::TocInsertor);
+}
+
+
+use constant TUT_TOKENTYPE_START    => 0;
+use constant TUT_TOKENTYPE_END      => 1;
+use constant TUT_TOKENTYPE_TEXT     => 2;
+use constant TUT_TOKENTYPE_COMMENT  => 3;
+
+use constant MODE_DO_NOTHING   => 0;   # 0b00
+use constant MODE_DO_INSERT    => 1;   # 0b01
+use constant MODE_DO_UPDATE    => 3;   # 0b11
+
+
+END {}
+
+
+#--- HTML::TocUpdator::new() --------------------------------------------------
+# function: Constructor.
+
+sub new {
+               # Get arguments
+       my ($aType) = @_;
+       my $self = $aType->SUPER::new;
+               # Bias to not update ToC
+       $self->{htu__Mode} = MODE_DO_NOTHING;
+               # Bias to not delete tokens
+       $self->{_doDeleteTokens} = 0;
+               # Reset batch variables
+       #$self->_resetBatchVariables;
+
+       $self->{options} = {};
+               
+               # TODO: Initialize output
+
+       return $self;
+}  # new()
+
+
+#--- HTML::TocUpdator::_deinitializeUpdatorBatch() --------------------------
+# function: Deinitialize updator batch.
+# args:     - $aTocs: Reference to array of tocs.
+
+sub _deinitializeUpdatorBatch {
+               # Get arguments
+       my ($self, $aTocs) = @_;
+               # Indicate end of ToC updating
+       $self->{htu__Mode} = MODE_DO_NOTHING;
+               # Deinitialize insertor batch
+       $self->_deinitializeInsertorBatch();
+}  # _deinitializeUpdatorBatch()
+
+
+#--- HTML::TokenUpdator::_doesHashEqualHash() ---------------------------------
+# function: Determines whether hash1 equals hash2.
+# args:     - $aHash1
+#           - $aHash2
+# returns:  True (1) if hash1 equals hash2, 0 if not.  For example, with the
+#           following hashes:
+#
+#              %hash1 = {                     %hash2 = {
+#                 'class' => 'header',          'class' => 'header',
+#                 'id'    => 'intro1'           'id'    => 'intro2'
+#              }                             }
+#
+#           the routine will return 0, cause the hash fields 'id' differ.
+# note:     Class function.
+
+sub _doesHashEqualHash {
+               # Get arguments
+       my ($aHash1, $aHash2) = @_;
+               # Local variables
+       my ($key1, $value1, $key2, $value2, $result);
+               # Bias to success
+       $result = 1;
+               # Loop through hash1 while values available
+       HASH1: while (($key1, $value1) = each %$aHash1) {
+               # Yes, values are available;
+                       # Value1 differs from value2?
+               if ($value1 ne $aHash2->{$key1}) {
+                       # Yes, hashes differ;
+                               # Indicate condition fails
+                       $result = 0;
+                               # Reset 'each' iterator which we're going to break
+                       keys %$aHash2;
+                               # Break loop
+                       last HASH1;
+               }
+       }
+               # Return value
+       return $result;
+}  # _doesHashEqualHash()
+
+
+#--- HTML::TokenUpdator::_doesTagExistInArray() -------------------------------
+# function: Check whether tag & attributes matches any of the tags & attributes
+#           in the specified array.  The array must consist of elements with 
+#           format:
+#
+#              [$tag, \%attributes]
+#
+# args:     - $aTag: tag to search for
+#           - $aAttributes: tag attributes to search for
+#           - $aArray: Array to search in.
+# returns:  1 if tag does exist in array, 0 if not.
+# note:     Class function.
+
+sub _doesTagExistInArray {
+               # Get arguments
+       my ($aTag, $aAttributes, $aArray) = @_;
+               # Local variables
+       my ($tag, $result);
+               # Bias to non-existing tag
+       $result = 0;
+               # Loop through existing tags
+       TAG: foreach $tag (@{$aArray}) {
+               if (defined(@{$tag}[0])) {
+                               # Does tag equals any existing tag?
+                       if ($aTag eq @{$tag}[0]) {
+                               # Yes, tag equals existing tag;
+                                       # Do hashes equal?
+                               if (HTML::TocUpdator::_doesHashEqualHash(
+                                       $aAttributes, @{$tag}[1]
+                               )) {
+                                       # Yes, hashes are the same;
+                                               # Indicate tag exists in array
+                                       $result = 1;
+                                               # Break loop
+                                       last TAG;
+                               }
+                       }
+               }
+       }
+               # Return value
+       return $result;
+}  # _doesTagExistInArray()
+
+
+#--- HTML::TocUpdator::_initializeUpdatorBatch() ----------------------------
+# function: Initialize insertor batch.
+# args:     - $aMode: Mode.  Can be either MODE_DO_INSERT or MODE_DO_UPDATE
+#           - $aTocs: Reference to array of tocs.
+#           - $aOptions: optional options
+# note:     Updating actually means: deleting the old ToC and inserting a new
+#           ToC.  That's why we're calling 'insertor' methods here.
+
+sub _initializeUpdatorBatch {
+               # Get arguments
+       my ($self, $aMode, $aTocs, $aOptions) = @_;
+               # Initialize insertor batch
+       $self->_initializeInsertorBatch($aTocs, $aOptions);
+               # Parse ToC update templates
+       $self->_parseTocUpdateTokens();
+               # Indicate start of ToC updating
+       $self->{htu__Mode} = $aMode;
+}  # _initializeUpdatorBatch()
+
+
+#--- HTML::TocUpdator::_parseTocUpdateTokens() --------------------------------
+# function: Parse ToC insertion point specifier.
+
+sub _parseTocUpdateTokens {
+               # Get arguments
+       my ($self) = @_;
+               # Local variables
+       my ($toc, $tokenType, $tokenPreposition, $token);
+       my ($tocInsertionPoint, $tocInsertionPointTokenAttributes);
+               # Create parser for update begin tokens
+       my $tokenUpdateBeginParser = HTML::_TokenUpdateParser->new(
+               $self->{_tokensUpdateBegin}
+       );
+               # Create parser for update end tokens
+       my $tokenUpdateEndParser = HTML::_TokenUpdateParser->new(
+               $self->{_tokensUpdateEnd}
+       );
+
+               # Loop through ToCs
+       foreach $toc (@{$self->{_tocs}}) {
+                       # Parse update tokens
+               $tokenUpdateBeginParser->parse(
+                       $toc->{_tokenUpdateBeginOfAnchorNameBegin}
+               );
+               $tokenUpdateBeginParser->parse($toc->{_tokenUpdateBeginOfAnchorNameEnd});
+               $tokenUpdateBeginParser->parse($toc->{_tokenUpdateBeginNumber});
+               $tokenUpdateBeginParser->parse($toc->{_tokenUpdateBeginToc});
+
+               $tokenUpdateEndParser->parse($toc->{_tokenUpdateEndOfAnchorNameBegin});
+               $tokenUpdateEndParser->parse($toc->{_tokenUpdateEndOfAnchorNameEnd});
+               $tokenUpdateEndParser->parse($toc->{_tokenUpdateEndNumber});
+               $tokenUpdateEndParser->parse($toc->{_tokenUpdateEndToc});
+       }
+}  # _parseTocUpdateTokens()
+
+
+#--- HTML::TocUpdator::_resetBatchVariables() ---------------------------------
+# function: Reset batch variables
+
+sub _resetBatchVariables {
+               # Get arguments
+       my ($self) = @_;
+               # Call ancestor
+       $self->SUPER::_resetBatchVariables();
+               # Arrays containing start, end, comment & text tokens which indicate
+               # the begin of ToC tokens.  The tokens are stored in keys of hashes to 
+               # avoid storing duplicates as an array would.
+       $self->{_tokensUpdateBegin} = [
+               [],     # ['<start tag>', <attributes>]
+               {},     # {'<end tag>' => ''}
+               {},     # {'<text>'    => ''}
+               {}              # {'<comment>' => ''}
+       ];
+               # Arrays containing start, end, comment & text tokens which indicate
+               # the end of ToC tokens.  The tokens are stored in keys of hashes to 
+               # avoid storing duplicates as an array would.
+       $self->{_tokensUpdateEnd} = [
+               [],     # ['<start tag>', <attributes>]
+               {},     # {'<end tag>' => ''}
+               {},     # {'<text>'    => ''}
+               {}              # {'<comment>' => ''}
+       ];
+}  # _resetBatchVariables()
+
+
+#--- HTML::TocUpdator::_setActiveAnchorName() ---------------------------------
+# function: Set active anchor name.
+# args:     - aAnchorName: Name of anchor name to set active.
+
+sub _setActiveAnchorName {
+               # Get arguments
+       my ($self, $aAnchorName) = @_;
+               # Are tokens being deleted?
+       if (! $self->{_doDeleteTokens}) {
+               # No, tokens aren't being deleted;
+                       # Call ancestor to set anchor name
+               $self->SUPER::_setActiveAnchorName($aAnchorName);
+       }
+}  # _setActiveAnchorName()
+
+
+#--- HTML::TocUpdator::_update() ----------------------------------------------
+# function: Update ToC in string.
+# args:     - $aMode: Mode.  Can be either MODE_DO_UPDATE or MODE_DO_INSERT.
+#           - $aToc: (reference to array of) ToC object to update
+#           - $aString: string to update ToC of
+#           - $aOptions: optional updator options
+# note:     Used internally.
+
+sub _update {
+               # Get arguments
+       my ($self, $aMode, $aToc, $aString, $aOptions) = @_;
+               # Initialize TocUpdator batch
+       $self->_initializeUpdatorBatch($aMode, $aToc, $aOptions);
+               # Start updating ToC by starting ToC insertion
+       $self->_insert($aString);
+               # Deinitialize TocUpdator batch
+       $self->_deinitializeUpdatorBatch();
+}  # update()
+
+
+#--- HTML::TocUpdator::_updateFile() ------------------------------------------
+# function: Update ToCs in file.
+# args:     - $aMode: Mode.  Can be either MODE_DO_UPDATE or MODE_DO_INSERT.
+#           - $aToc: (reference to array of) ToC object to update
+#           - $aFile: (reference to array of) file to parse for updating.
+#           - $aOptions: optional updator options
+# note:     Used internally.
+
+sub _updateFile {
+               # Get arguments
+       my ($self, $aMode, $aToc, $aFile, $aOptions) = @_;
+               # Initialize TocUpdator batch
+       $self->_initializeUpdatorBatch($aMode, $aToc, $aOptions);
+               # Start updating ToC by starting ToC insertion
+       $self->_insertIntoFile($aFile);
+               # Deinitialize TocUpdator batch
+       $self->_deinitializeUpdatorBatch();
+}  # _updateFile()
+
+
+#--- HTML::TocUpdator::_writeOrBufferOutput() ---------------------------------
+# function: Write processed HTML to output device(s).
+# args:     - aOutput: scalar to write
+
+sub _writeOrBufferOutput {
+               # Get arguments
+       my ($self, $aOutput) = @_;
+               # Delete output?
+       if (! $self->{_doDeleteTokens}) {
+               # No, don't delete output;
+                       # Call ancestor
+               $self->SUPER::_writeOrBufferOutput($aOutput);
+       }
+}  # _writeOrBufferOutput()
+
+
+#--- HTML::TocUpdator::anchorNameBegin() --------------------------------------
+# function: Process 'anchor name begin' generated by HTML::Toc.
+# args:     - $aAnchorName: Anchor name begin tag to output.
+#           - $aToc: Reference to ToC to which anchorname belongs.
+
+sub anchorNameBegin {
+               # Get arguments
+       my ($self, $aAnchorNameBegin, $aToc) = @_;
+               # Call ancestor
+       $self->SUPER::anchorNameBegin($aAnchorNameBegin);
+               # Must ToC be inserted or updated?
+       if ($self->{htu__Mode} != MODE_DO_NOTHING) {
+               # Yes, ToC must be inserted or updated;
+                       # Surround anchor name with update tags
+               $self->{_outputPrefix} = 
+                       $aToc->{_tokenUpdateBeginOfAnchorNameBegin} .
+                       $self->{_outputPrefix} . 
+                       $aToc->{_tokenUpdateEndOfAnchorNameBegin};
+       }
+}      # anchorNameBegin()
+
+
+#--- HTML::TocUpdator::anchorNameEnd() ----------------------------------------
+# function: Process 'anchor name end' generated by HTML::Toc.
+# args:     - $aAnchorNameEnd: Anchor name end tag to output.
+#           - $aToc: Reference to ToC to which anchorname belongs.
+
+sub anchorNameEnd {
+               # Get arguments
+       my ($self, $aAnchorNameEnd, $aToc) = @_;
+               # Call ancestor
+       $self->SUPER::anchorNameEnd($aAnchorNameEnd);
+               # Must ToC be inserted or updated?
+       if ($self->{htu__Mode} != MODE_DO_NOTHING) {
+               # Yes, ToC must be inserted or updated;
+                       # Surround anchor name with update tags
+               $self->{_outputSuffix} = 
+                       $aToc->{_tokenUpdateBeginOfAnchorNameEnd} .
+                       $self->{_outputSuffix} . 
+                       $aToc->{_tokenUpdateEndOfAnchorNameEnd};
+       }
+}      # anchorNameEnd()
+
+
+#--- HTML::TocUpdator::comment() ----------------------------------------------
+# function: Process comment.
+# args:     - $aComment: comment text with '<!--' and '-->' tags stripped off.
+
+sub comment {
+               # Get arguments
+       my ($self, $aComment) = @_;
+               # Must ToC be updated?
+       if ($self->{htu__Mode} == MODE_DO_UPDATE) {
+               # Yes, ToC must be updated;
+                       # Updator is currently deleting tokens?
+               if ($self->{_doDeleteTokens}) {
+                       # Yes, tokens must be deleted;
+                               # Call ancestor
+                       $self->SUPER::comment($aComment);
+
+                               # Look for update end token
+
+                               # Does comment matches update end token?
+                       if (defined(
+                               $self->{_tokensUpdateEnd}[TUT_TOKENTYPE_COMMENT]{$aComment}
+                       )) {
+                               # Yes, comment matches update end token;
+                                       # Indicate to stop deleting tokens
+                               $self->{_doDeleteTokens} = 0;
+                       }
+               }
+               else {
+                       # No, tokens mustn't be deleted;
+
+                               # Look for update begin token
+
+                               # Does comment matches update begin token?
+                       if (defined(
+                               $self->{_tokensUpdateBegin}[TUT_TOKENTYPE_COMMENT]{$aComment}
+                       )) {
+                               # Yes, comment matches update begin token;
+                                       # Indicate to start deleting tokens
+                               $self->{_doDeleteTokens} = 1;
+                       }
+                               # Call ancestor
+                       $self->SUPER::comment($aComment);
+               }
+       }
+       else {
+               # No, ToC mustn't be updated;
+                       # Call ancestor
+               $self->SUPER::comment($aComment);
+       }
+}  # comment()
+
+
+#--- HTML::TocUpdator::end() --------------------------------------------------
+# function: This function is called every time a closing tag is encountered.
+# args:     - $aTag: tag name (in lower case).
+#           - $aOrigText: tag name including brackets.
+
+sub end {
+               # Get arguments
+       my ($self, $aTag, $aOrigText) = @_;
+               # Call ancestor
+       $self->SUPER::end($aTag, $aOrigText);
+               # Must ToC be updated?
+       if ($self->{htu__Mode} == MODE_DO_UPDATE) {
+               # Yes, ToC must be updated;
+                       # Updator is currently deleting tokens?
+               if ($self->{_doDeleteTokens}) {
+                       # Yes, tokens must be deleted;
+                               # Does end tag matches update end token?
+                       if (defined(
+                               $self->{_tokensUpdateEnd}[TUT_TOKENTYPE_END]{$aTag}
+                       )) {
+                               # Yes, end tag matches update end token;
+                                       # Indicate to stop deleting tokens
+                               $self->{_doDeleteTokens} = 0;
+                       }
+               }
+       }
+}  # end()
+
+
+#--- HTML::TocUpdator::insert() -----------------------------------------------
+# function: Insert ToC in string.
+# args:     - $aToc: (reference to array of) ToC object to update
+#           - $aString: string to insert ToC in.
+#           - $aOptions: optional updator options
+
+sub insert {
+               # Get arguments
+       my ($self, $aToc, $aString, $aOptions) = @_;
+               # Do start insert
+       $self->_update(MODE_DO_INSERT, $aToc, $aString, $aOptions);
+}  # insert()
+
+
+#--- HTML::TocUpdator::insertIntoFile() --------------------------------------
+# function: Insert ToC in file.
+# args:     - $aToc: (reference to array of) ToC object to update
+#           - $aFile: File to insert ToC in.
+#           - $aOptions: optional updator options
+
+sub insertIntoFile {
+               # Get arguments
+       my ($self, $aToc, $aFile, $aOptions) = @_;
+               # Do start insert
+       $self->_updateFile(MODE_DO_INSERT, $aToc, $aFile, $aOptions);
+}  # insertIntoFile()
+
+
+#--- HTML::TocUpdator::number() -----------------------------------------------
+# function: Process heading number generated by HTML::Toc.
+# args:     - $aNumber
+#           - $aToc: Reference to ToC to which anchorname belongs.
+
+sub number {
+               # Get arguments
+       my ($self, $aNumber, $aToc) = @_;
+               # Call ancestor
+       $self->SUPER::number($aNumber);
+               # Must ToC be inserted or updated?
+       if ($self->{htu__Mode} != MODE_DO_NOTHING) {
+               # Yes, ToC must be inserted or updated;
+                       # Surround number with update tags
+               $self->{_outputSuffix} = 
+                       $aToc->{_tokenUpdateBeginNumber} .
+                       $self->{_outputSuffix} . 
+                       $aToc->{_tokenUpdateEndNumber};
+       }
+}      # number()
+
+
+#--- HTML::TocUpdator::start() ------------------------------------------------
+# function: This function is called every time an opening tag is encountered.
+# args:     - $aTag: tag name (in lower case).
+#           - $aAttr: reference to hash containing all tag attributes (in lower
+#                case).
+#           - $aAttrSeq: reference to array containing all tag attributes (in 
+#                lower case) in the original order
+#           - $aOrigText: the original HTML text
+
+sub start {
+               # Get arguments
+       my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
+               # Must ToC be updated?
+       if ($self->{htu__Mode} == MODE_DO_UPDATE) {
+               # Yes, ToC must be updated;
+                       # Does start tag matches token update begin tag?
+               if (HTML::TocUpdator::_doesTagExistInArray(
+                       $aTag, $aAttr, $self->{_tokensUpdateBegin}[TUT_TOKENTYPE_START]
+               )) {
+                       # Yes, start tag matches token update tag;
+                               # Indicate to delete tokens
+                       $self->{_doDeleteTokens} = 1;
+               }
+       }
+               # Let ancestor process the start tag
+       $self->SUPER::start($aTag, $aAttr, $aAttrSeq, $aOrigText);
+}  # start()
+
+
+#--- HTML::TocUpdator::toc() --------------------------------------------------
+# function: Toc processing method.  Add toc reference to scenario.
+# args:     - $aScenario: Scenario to add ToC reference to.
+#           - $aToc: Reference to ToC to insert.
+# note:     The ToC hasn't been build yet; only a reference to the ToC to be
+#           build is inserted.
+
+sub toc {
+               # Get arguments
+       my ($self, $aScenario, $aToc) = @_;
+
+               # Surround toc with update tokens
+
+               # Add update begin token
+       push(@$aScenario, \$aToc->{_tokenUpdateBeginToc});
+               # Call ancestor
+       $self->SUPER::toc($aScenario, $aToc);
+               # Add update end token
+       push(@$aScenario, \$aToc->{_tokenUpdateEndToc});
+}  # toc()
+
+
+#--- HTML::TocUpdator::_processTocText() --------------------------------------
+# function: Toc text processing function.
+# args:     - $aText: Text to add to ToC.
+#           - $aToc: ToC to add text to.
+
+sub _processTocText {
+               # Get arguments
+       my ($self, $aText, $aToc) = @_;
+               # Delete output?
+       if (! $self->{_doDeleteTokens}) {
+               # No, don't delete output;
+                       # Call ancestor
+               $self->SUPER::_processTocText($aText, $aToc);
+       }
+}  # _processTocText()
+
+
+#--- HTML::TocUpdator::update() -----------------------------------------------
+# function: Update ToC in string.
+# args:     - $aToc: (reference to array of) ToC object to update
+#           - $aString: string to update ToC of
+#           - $aOptions: optional updator options
+
+sub update {
+               # Get arguments
+       my ($self, $aToc, $aString, $aOptions) = @_;
+               # Do start update
+       $self->_update(MODE_DO_UPDATE, $aToc, $aString, $aOptions);
+}  # update()
+
+
+#--- HTML::TocUpdator::updateFile() -------------------------------------------
+# function: Update ToC of file.
+# args:     - $aToc: (reference to array of) ToC object to update
+#           - $aFile: (reference to array of) file to parse for updating.
+#           - $aOptions: optional updator options
+
+sub updateFile {
+               # Get arguments
+       my ($self, $aToc, $aFile, $aOptions) = @_;
+               # Do start update
+       $self->_updateFile(MODE_DO_UPDATE, $aToc, $aFile, $aOptions);
+}  # update()
+
+
+
+
+#=== HTML::_TokenUpdateParser =================================================
+# function: Parse 'update tokens'.  'Update tokens' mark HTML code which is
+#           inserted by 'HTML::TocInsertor'.
+# note:     Used internally.
+
+package HTML::_TokenUpdateParser;
+
+
+BEGIN {
+       use vars qw(@ISA);
+
+       @ISA = qw(HTML::Parser);
+}
+
+END {}
+
+
+#--- HTML::_TokenUpdateParser::new() ------------------------------------------
+# function: Constructor
+
+sub new {
+               # Get arguments
+       my ($aType, $aTokenArray) = @_;
+               # Create instance
+       my $self = $aType->SUPER::new;
+               # Reference token array
+       $self->{tokens} = $aTokenArray;
+               # Return instance
+       return $self;
+}  # new()
+
+
+#--- HTML::_TokenUpdateParser::comment() --------------------------------------
+# function: Process comment.
+# args:     - $aComment: comment text with '<!--' and '-->' tags stripped off.
+
+sub comment {
+               # Get arguments
+       my ($self, $aComment) = @_;
+               # Add token to array of update tokens
+       $self->{tokens}[HTML::TocUpdator::TUT_TOKENTYPE_COMMENT]{$aComment} = '';
+}  # comment()
+
+
+#--- HTML::_TokenUpdateParser::end() ------------------------------------------
+# function: This function is called every time a closing tag is encountered
+#           by HTML::Parser.
+# args:     - $aTag: tag name (in lower case).
+
+sub end {
+               # Get arguments
+       my ($self, $aTag, $aOrigText) = @_;
+               # Add token to array of update tokens
+       $self->{tokens}[HTML::TocUpdator::TUT_TOKENTYPE_END]{$aTag} = '';
+}  # end()
+
+
+#--- HTML::_TokenUpdateParser::parse() ----------------------------------------
+# function: Parse token.
+# args:     - $aToken: 'update token' to parse
+
+sub parse {
+               # Get arguments
+       my ($self, $aString) = @_;
+               # Call ancestor
+       $self->SUPER::parse($aString);
+}  # parse()
+
+
+#--- HTML::_TokenUpdateParser::start() ----------------------------------------
+# function: This function is called every time an opening tag is encountered.
+# args:     - $aTag: tag name (in lower case).
+#           - $aAttr: reference to hash containing all tag attributes (in lower
+#                case).
+#           - $aAttrSeq: reference to array containing all tag attributes (in 
+#                lower case) in the original order
+#           - $aOrigText: the original HTML text
+
+sub start {
+               # Get arguments
+       my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
+               # Does token exist in array?
+       if (! HTML::TocUpdator::_doesTagExistInArray(
+               $aTag, $aAttr, $self->{tokens}[HTML::TocUpdator::TUT_TOKENTYPE_START]
+       )) {
+               # No, token doesn't exist in array;
+                       # Add token to array of update tokens
+               push(
+                       @{$self->{tokens}[HTML::TocUpdator::TUT_TOKENTYPE_START]},
+                       [$aTag, $aAttr]
+               );
+       }
+}  # start()
+
+
+#--- HTML::_TokenUpdateParser::text() -----------------------------------------
+# function: This function is called every time plain text is encountered.
+# args:     - @_: array containing data.
+
+sub text {
+               # Get arguments
+       my ($self, $aText) = @_;
+               # Add token to array of update tokens
+       $self->{tokens}[HTML::TocUpdator::TUT_TOKENTYPE_TEXT]{$aText} = '';
+}  # text()
+
+
+1;
diff --git a/examples/includes/HTML-Toc-0.91/t/ManualTest/manualTest1.htm b/examples/includes/HTML-Toc-0.91/t/ManualTest/manualTest1.htm
new file mode 100644 (file)
index 0000000..1bd250f
--- /dev/null
@@ -0,0 +1,92 @@
+<html>
+<head>
+   <title>Manual</title>
+    <style type="text/css">
+       ul.toc_appendix1 { 
+         list-style-type: none;
+         margin-left: 0;
+         margin-top: 1em;
+         margin-bottom: 1em;
+       }
+       ul.toc_h1 {
+         list-style-type: none;
+         margin-left: 1;
+         margin-top: 1em;
+         margin-bottom: 1em;
+       }
+       ul.toc_h2 {
+         list-style-type: none;
+       }
+       ul.toc_h3 {
+         list-style-type: none;
+       }
+       ul.toc_part1 {
+         list-style-type: none;
+         margin-left: 1;
+         margin-top: 1em;
+         margin-bottom: 1em;
+       }
+       ul.toc_prelude1 {
+         list-style: none;
+       }
+       p.captionFigure {
+         font-style: italic;
+         font-weight: bold;
+       }
+       p.captionTable {
+         font-style: italic;
+         font-weight: bold;
+       }
+    </style>
+</head>
+<body>
+
+<h1 class=prelude>Preface</h1>
+Better C than never.
+
+<h1 class=hidden>Table of Contents</h1>
+<!-- Table of Contents -->
+
+<h1 class=prelude>Table of Figures</h1>
+<!-- Table of Figures -->
+
+<h1 class=prelude>Table of Tables</h1>
+<!-- Table of Tables -->
+
+<h1 class=prelude>Introduction</h1>
+Thanks to standardisation and the excellent work of the QWERTY corporation it is possible to learn C with almost any C manual.
+<p class=captionTable>Compile Steps</p>
+<ul><pre>
+   Parser
+   Compiler
+   Linker
+</pre></ul>
+
+<h1 class=part>Disks</h1>
+<h1>Compiler Disk v1</h1>
+<img src=img.gif alt="Contents Compiler Disk v1">
+<p class=captionFigure>Contents Compiler Disk v1</p>
+
+<h2>System</h2>
+<h2>Standard Library</h2>
+
+<h1>Compiler Disk v2</h1>
+<img src=img.gif alt="Contents Compiler Disk v2">
+<p class=captionFigure>Contents Compiler Disk v2</p>
+
+<h2>System</h2>
+<h3>parser.com</h3>
+<h3>compiler.com</h3>
+<h3>linker.com</h3>
+<h2>Standard Library</h2>
+
+<h1>Library System Disk</h1>
+<h1 class=part>Personal</h1>
+<h1>Tips & Tricks</h1>
+<h1 class=part>Appendixes</h1>
+<h1 class=appendix>Functions Standard Library v1</h1>
+<h1 class=appendix>Functions Standard Library v2</h1>
+<h1 class=appendix>Functions Graphic Library</h1>
+<h1 class=prelude>Bibliography</h1>
+</body>
+</html>
diff --git a/examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir1/SubSubDir1/index.htm b/examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir1/SubSubDir1/index.htm
new file mode 100644 (file)
index 0000000..5288cde
--- /dev/null
@@ -0,0 +1,5 @@
+<html>\r
+<head>\r
+<title>SubSub1</title>\r
+</head>\r
+</html>\r
diff --git a/examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir1/index.htm b/examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir1/index.htm
new file mode 100644 (file)
index 0000000..c938212
--- /dev/null
@@ -0,0 +1,5 @@
+<html>\r
+<head>\r
+<title>Sub1</title>\r
+</head>\r
+</html>\r
diff --git a/examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir2/SubSubDir1/index.htm b/examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir2/SubSubDir1/index.htm
new file mode 100644 (file)
index 0000000..5288cde
--- /dev/null
@@ -0,0 +1,5 @@
+<html>\r
+<head>\r
+<title>SubSub1</title>\r
+</head>\r
+</html>\r
diff --git a/examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir2/SubSubDir2/index.htm b/examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir2/SubSubDir2/index.htm
new file mode 100644 (file)
index 0000000..eaadf8c
--- /dev/null
@@ -0,0 +1,5 @@
+<html>\r
+<head>\r
+<title>SubSub2</title>\r
+</head>\r
+</html>\r
diff --git a/examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir2/index.htm b/examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir2/index.htm
new file mode 100644 (file)
index 0000000..8445eb1
--- /dev/null
@@ -0,0 +1,5 @@
+<html>\r
+<head>\r
+<title>Sub2</title>\r
+</head>\r
+</html>\r
diff --git a/examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir3/index.htm b/examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir3/index.htm
new file mode 100644 (file)
index 0000000..cf9aa99
--- /dev/null
@@ -0,0 +1,5 @@
+<html>\r
+<head>\r
+<title>Sub3</title>\r
+</head>\r
+</html>\r
diff --git a/examples/includes/HTML-Toc-0.91/t/SiteMap/index.htm b/examples/includes/HTML-Toc-0.91/t/SiteMap/index.htm
new file mode 100644 (file)
index 0000000..864b0b5
--- /dev/null
@@ -0,0 +1,5 @@
+<html>\r
+<head>\r
+<title>Main</title>\r
+</head>\r
+</html>\r
diff --git a/examples/includes/HTML-Toc-0.91/t/extend.t b/examples/includes/HTML-Toc-0.91/t/extend.t
new file mode 100644 (file)
index 0000000..fe9daee
--- /dev/null
@@ -0,0 +1,87 @@
+#--- generate.t ---------------------------------------------------------------
+# function: Test ToC generation.
+
+use strict;
+use Test;
+
+BEGIN { plan tests => 4; }
+
+use HTML::Toc;
+use HTML::TocGenerator;
+
+my ($filename);
+my $toc          = HTML::Toc->new;
+my $tocGenerator = HTML::TocGenerator->new;
+
+$toc->setOptions({
+       'doLinkToToken' => 0,
+       'levelIndent'       => 0,
+       'header'            => '',
+       'footer'            => '',
+});
+
+
+BEGIN {
+               # Create test file
+       $filename = "file$$.htm";
+       die "$filename is already there" if -e $filename;
+       open(FILE, ">$filename") || die "Can't create $filename: $!";
+       print FILE <<'EOT';
+<h1>Header</h1>
+EOT
+       close(FILE);
+}
+
+
+END {
+               # Remove test file
+       unlink($filename) or warn "Can't unlink $filename: $!";
+}
+
+
+#--- 1. extend ----------------------------------------------------------------
+
+       # Generate ToC
+$tocGenerator->generate($toc, "<h1>Header</h1>");
+       # Extend ToC
+$tocGenerator->extend($toc, "<h1>Header</h1>");
+       # Test ToC
+ok($toc->format(), "<ul>\n<li>Header\n<li>Header\n</ul>");
+
+
+#--- 2. extendFromFile --------------------------------------------------------
+
+       # Generate ToC
+$tocGenerator->generateFromFile($toc, $filename);
+       # Extend ToC
+$tocGenerator->extendFromFile($toc, $filename);
+       # Test ToC
+ok($toc->format(), "<ul>\n<li>Header\n<li>Header\n</ul>");
+
+
+#--- 3. extendFromFiles -------------------------------------------------------
+
+       # Generate ToC
+$tocGenerator->generateFromFile($toc, $filename);
+       # Extend ToC
+$tocGenerator->extendFromFile($toc, [$filename, $filename]);
+       # Test ToC
+ok($toc->format(), "<ul>\n<li>Header\n<li>Header\n<li>Header\n</ul>");
+
+
+#--- 4. linkTocToToken --------------------------------------------------------
+
+$toc->setOptions({
+       'doLinkToToken' => 1,
+});
+       # Generate ToC
+$tocGenerator->generate($toc, "<h1>Header</h1>");
+       # Extend ToC
+$tocGenerator->extend($toc, "<h1>Header</h1>");
+       # Test ToC
+ok($toc->format() . "\n", <<'EOT');
+<ul>
+<li><a href=#h-1>Header</a>
+<li><a href=#h-2>Header</a>
+</ul>
+EOT
diff --git a/examples/includes/HTML-Toc-0.91/t/format.t b/examples/includes/HTML-Toc-0.91/t/format.t
new file mode 100644 (file)
index 0000000..62d2b6c
--- /dev/null
@@ -0,0 +1,157 @@
+#--- format.t -----------------------------------------------------------------
+# function: Test ToC formatting.
+
+use strict;
+use Test;
+
+BEGIN { plan tests => 6; }
+
+use HTML::Toc;
+use HTML::TocGenerator;
+use HTML::TocInsertor;
+
+my ($output, $content, $filename);
+my $toc          = HTML::Toc->new;
+my $tocGenerator = HTML::TocGenerator->new;
+my $tocInsertor  = HTML::TocInsertor->new;
+
+$toc->setOptions({
+       'doLinkToToken'  => 0,
+       'levelIndent'       => 0,
+       'insertionPoint'    => 'before <h1>',
+       'header'            => '',
+       'footer'            => '',
+});
+
+
+BEGIN {
+               # Create test file
+       $filename = "file$$.htm";
+       die "$filename is already there" if -e $filename;
+       open(FILE, ">$filename") || die "Can't create $filename: $!";
+       print FILE <<'EOT'; close(FILE);
+<h1>Header</h1>
+EOT
+}
+
+
+END {
+               # Remove test file
+       unlink($filename) or warn "Can't unlink $filename: $!";
+}
+
+
+#--- 1. templateLevelBegin ----------------------------------------------------
+
+$toc->setOptions({
+       'templateLevelBegin' => '"<ul class=toc_$groupId$level>\n"'
+});
+$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
+ok($output, "<ul class=toc_h1>\n<li>Header\n</ul><h1>Header</h1>");
+$toc->setOptions({'templateLevelBegin' => undef});
+
+
+#--- 2. levelToToc -----------------------------------------------------------
+
+$tocGenerator->generate($toc, "<h1>Header1</h1>\n<h2>Header2</h2>");
+$toc->setOptions({'levelToToc' => '1'});
+ok($toc->format(), "<ul>\n<li>Header1\n</ul>");
+$toc->setOptions({'levelToToc' => '.*'});
+
+
+#--- 3. groupToToc -----------------------------------------------------------
+
+$toc->setOptions({
+       'tokenToToc' => [{
+               'level' => 1,
+               'tokenBegin' => '<h1 class=-foo>'
+       }, {
+               'groupId' => 'foo',
+               'level' => 1,
+               'tokenBegin' => '<h1 class=foo>'
+       }]
+});
+$tocGenerator->generate($toc, "<h1>Header1</h1>\n<h1 class=foo>Foo</h1>");
+$toc->setOptions({'groupToToc' => 'foo'});
+ok($toc->format(), "<ul>\n<li>Foo\n</ul>");
+$toc->setOptions({'groupToToc' => '.*'});
+
+
+#--- 4. header & footer -------------------------------------------------------
+
+$toc->setOptions({
+       'tokenToToc' => [{
+               'level'      => 1,
+               'tokenBegin' => '<h1>'
+       }],
+       'header' => '<!-- TocHeader -->',
+       'footer' => '<!-- TocFooter -->',
+});
+$tocInsertor->insert($toc, "<h1>Header1</h1>", {'output' => \$output});
+ok("$output\n", <<EOT);
+<!-- TocHeader --><ul>
+<li>Header1
+</ul><!-- TocFooter --><h1>Header1</h1>
+EOT
+
+
+       # Test 'doSingleStepLevel' => 1
+TestSingleStepLevel1();
+       # Test 'doSingleStepLevel' => 0
+TestSingleStepLevel0();
+
+
+#--- 5. TestSingleStepLevel1 --------------------------------------------------
+
+sub TestSingleStepLevel1 {
+       my $toc          = new HTML::Toc;
+       my $tocGenerator = new HTML::TocGenerator;
+       
+               # Generate ToC
+       $tocGenerator->generate($toc, <<EOT);
+<h1>Header 1</h1>
+<h3>Header 3</h3>
+EOT
+               # Compare output
+       ok($toc->format(), <<EOT);
+
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul>
+   <li><a href=#h-1>Header 1</a>
+   <ul>
+      <ul>
+         <li><a href=#h-1.0.1>Header 3</a>
+      </ul>
+   </ul>
+</ul>
+<!-- End of generated Table of Contents -->
+EOT
+}  # TestSingleStepLevel1()
+
+
+#--- 6. TestSingleStepLevel0 --------------------------------------------------
+
+sub TestSingleStepLevel0 {
+       my $toc          = new HTML::Toc;
+       my $tocGenerator = new HTML::TocGenerator;
+       
+               # Set ToC options
+       $toc->setOptions({'doSingleStepLevel' => 0});
+               # Generate ToC
+       $tocGenerator->generate($toc, <<EOT);
+<h1>Header 1</h1>
+<h3>Header 3</h3>
+EOT
+               # Compare output
+       ok($toc->format(), <<EOT);
+
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul>
+   <li><a href=#h-1>Header 1</a>
+   <ul>
+      <li><a href=#h-1.0.1>Header 3</a>
+   </ul>
+</ul>
+<!-- End of generated Table of Contents -->
+EOT
+}  # TestSingleStepLevel0()
diff --git a/examples/includes/HTML-Toc-0.91/t/generate.t b/examples/includes/HTML-Toc-0.91/t/generate.t
new file mode 100644 (file)
index 0000000..869bdf4
--- /dev/null
@@ -0,0 +1,200 @@
+#--- generate.t ---------------------------------------------------------------
+# function: Test ToC generation.
+
+use strict;
+use Test;
+
+BEGIN { plan tests => 13; }
+
+use HTML::Toc;
+use HTML::TocGenerator;
+
+my ($filename);
+my $toc          = HTML::Toc->new;
+my $tocGenerator = HTML::TocGenerator->new;
+
+$toc->setOptions({
+       'doLinkToToken' => 0,
+       'levelIndent'   => 0,
+       'header'        => '',
+       'footer'        => '',
+});
+
+
+BEGIN {
+               # Create test file
+       $filename = "file$$.htm";
+       die "$filename is already there" if -e $filename;
+       open(FILE, ">$filename") || die "Can't create $filename: $!";
+       print FILE <<'EOT';
+<h1>Header</h1>
+EOT
+       close(FILE);
+}
+
+
+END {
+               # Remove test file
+       unlink($filename) or warn "Can't unlink $filename: $!";
+}
+
+
+#--- 1. generate --------------------------------------------------------------
+
+$tocGenerator->generate($toc, "<h1>Header</h1>");
+ok($toc->format(), "<ul>\n<li>Header\n</ul>");
+
+
+#--- 2. generateFromFile ------------------------------------------------------
+
+$tocGenerator->generateFromFile($toc, $filename);
+ok($toc->format(), "<ul>\n<li>Header\n</ul>");
+
+
+#--- 3. generateFromFiles -----------------------------------------------------
+
+$tocGenerator->generateFromFile($toc, [$filename, $filename]);
+ok($toc->format(), "<ul>\n<li>Header\n<li>Header\n</ul>");
+       
+
+#--- 4. doLinkToToken -----------------------------------------------------
+
+$toc->setOptions({'doLinkToToken' => 1});
+$tocGenerator->generateFromFile($toc, $filename, {'globalGroups' => 1});
+ok($toc->format(), "<ul>\n<li><a href=#h-1>Header</a>\n</ul>");
+
+
+#--- 5. doLinkToFile -------------------------------------------------------
+
+$toc->setOptions({'doLinkToFile' => 1});
+$tocGenerator->generateFromFile($toc, $filename);
+ok($toc->format(), "<ul>\n<li><a href=$filename#h-1>Header</a>\n</ul>");
+
+
+#--- 6. templateAnchorHrefBegin -----------------------------------------------
+
+       # Set options
+$toc->setOptions({'templateAnchorHrefBegin' => '"test-$file"'});
+       # Generate ToC
+$tocGenerator->generateFromFile($toc, $filename);
+       # Test ToC
+ok($toc->format(), "<ul>\n<li>test-".$filename."Header</a>\n</ul>");
+       # Reset options
+$toc->setOptions({'templateAnchorHrefBegin' => undef});
+
+
+#--- 7. templateAnchorHrefBegin function --------------------------------------
+
+sub AssembleAnchorHrefBegin {
+               # Get arguments
+       my ($aFile, $aGroupId, $aLevel, $aNode) = @_;
+               # Return value
+       return $aFile . $aGroupId . $aLevel . $aNode;
+}  # AssembleAnchorHrefBegin()
+
+
+       # Set options
+$toc->setOptions({'templateAnchorHrefBegin' => \&AssembleAnchorHrefBegin});
+       # Generate ToC
+$tocGenerator->generateFromFile($toc, $filename);
+       # Test ToC
+ok($toc->format(), "<ul>\n<li>".$filename."h11Header</a>\n</ul>");
+       # Reset options
+$toc->setOptions({'templateAnchorHrefBegin' => undef});
+
+
+#--- 8. levelToToc no levels available ---------------------------------------
+
+$toc->setOptions({'levelToToc' => '2'});
+$tocGenerator->generate($toc, "<h1>Header</h1>");
+ok($toc->format(), "");
+
+
+#--- 9. levelToToc level 1 ---------------------------------------------------
+
+       # Set options
+$toc->setOptions({
+       'levelToToc' => '1',
+       'doLinkToToken' => 0,
+});
+$tocGenerator->generate($toc, "<h1>Header1</h1>\n<h2>Header2</h2>");
+ok($toc->format(), "<ul>\n<li>Header1\n</ul>");
+
+
+#--- 10. levelToToc level 2 --------------------------------------------------
+
+       # Set options
+$toc->setOptions({
+       'levelToToc' => '2',
+       'doLinkToToken' => 0,
+});
+$tocGenerator->generate($toc, "<h1>Header1</h1>\n<h2>Header2</h2>");
+ok($toc->format(), "<ul>\n<li>Header2\n</ul>");
+       # Restore options
+$toc->setOptions({
+       'levelToToc' => '.*',
+});
+
+
+#--- 11. tokenToToc empty array ----------------------------------------------
+
+       # Set options
+$toc->setOptions({'tokenToToc' => []});
+$tocGenerator->generate($toc, "<h1>Header</h1>");
+ok($toc->format(), "");
+
+
+#--- 12. groups nested --------------------------------------------------------
+
+$toc->setOptions({
+       'doNestGroup' => 1,
+       'tokenToToc' => [
+               {
+                       'level' => 1,
+                       'tokenBegin' => '<h1 class=-appendix>'
+               }, {
+                       'groupId' => 'appendix',
+                       'level' => 1,
+                       'tokenBegin' => '<h1 class=appendix>'
+               }
+       ]
+});
+$tocGenerator->generate(
+       $toc, "<h1>Header1</h1>\n<h1 class=appendix>Appendix</h1>"
+);
+ok($toc->format() . "\n", <<'EOT');
+<ul>
+<li>Header1
+<ul>
+<li>Appendix
+</ul>
+</ul>
+EOT
+
+
+#--- 13. groups not nested ----------------------------------------------------
+
+$toc->setOptions({
+       'doNestGroup' => 0,
+       'tokenToToc' => [
+               {
+                       'level' => 1,
+                       'tokenBegin' => '<h1 class=-appendix>'
+               }, {
+                       'groupId' => 'appendix',
+                       'level' => 1,
+                       'tokenBegin' => '<h1 class=appendix>'
+               }
+       ]
+});
+$tocGenerator->generate(
+       $toc, "<h1>Header1</h1>\n<h1 class=appendix>Appendix</h1>"
+);
+ok($toc->format() . "\n", <<'EOT');
+<ul>
+<li>Header1
+</ul>
+<ul>
+<li>Appendix
+</ul>
+EOT
diff --git a/examples/includes/HTML-Toc-0.91/t/insert.t b/examples/includes/HTML-Toc-0.91/t/insert.t
new file mode 100644 (file)
index 0000000..3f1adba
--- /dev/null
@@ -0,0 +1,336 @@
+#--- insert.t -----------------------------------------------------------------
+# function: Test ToC insertion.
+
+use strict;
+use Test;
+
+BEGIN { plan tests => 10; }
+
+use HTML::Toc;
+use HTML::TocGenerator;
+use HTML::TocInsertor;
+
+my ($output, $content, $filename);
+my $toc          = HTML::Toc->new;
+my $tocGenerator = HTML::TocGenerator->new;
+my $tocInsertor  = HTML::TocInsertor->new;
+
+$toc->setOptions({
+       'doLinkToToken'  => 0,
+       'levelIndent'       => 0,
+       'header'            => "",
+       'footer'            => "",
+});
+
+
+BEGIN {
+               # Create test file
+       $filename = "file$$.htm";
+       die "$filename is already there" if -e $filename;
+       open(FILE, ">$filename") || die "Can't create $filename: $!";
+       print FILE <<'EOT'; close(FILE);
+<h1>Header</h1>
+EOT
+}
+
+
+END {
+               # Remove test file
+       unlink($filename) or warn "Can't unlink $filename: $!";
+}
+
+
+#--- 1. insert before start ---------------------------------------------------
+
+$toc->setOptions({'insertionPoint' => 'before <h1>'});
+       # Generate ToC
+$tocGenerator->generate($toc, "<h1>Header</h1>");
+$tocInsertor->insert($toc, "<h1>Header</h1>", {
+       'output'        => \$output,
+       'doGenerateToc' => 0
+});
+       # Test ToC
+ok($output, "<ul>\n<li>Header\n</ul><h1>Header</h1>");
+
+
+#--- 2. insert after start ----------------------------------------------------
+
+$toc->setOptions({'insertionPoint' => 'after <h1>'});
+       # Generate ToC
+$tocGenerator->generate($toc, "<h1>Header</h1>");
+$tocInsertor->insert($toc, "<h1>Header</h1>", {
+       'output' => \$output,
+       'doGenerateToc' => 0
+});
+       # Test ToC
+ok($output, "<h1><ul>\n<li>Header\n</ul>Header</h1>");
+
+
+#--- 3. insert before end -----------------------------------------------------
+
+$toc->setOptions({'insertionPoint' => 'before </h1>'});
+       # Generate ToC
+$tocGenerator->generate($toc, "<h1>Header</h1>");
+$tocInsertor->insert($toc, "<h1>Header</h1>", {
+       'output' => \$output,
+       'doGenerateToc' => 0
+});
+       # Test ToC
+ok($output, "<h1>Header<ul>\n<li>Header\n</ul></h1>");
+
+
+#--- 4. insert after end ------------------------------------------------------
+
+$toc->setOptions({'insertionPoint' => 'after </h1>'});
+       # Generate ToC
+$tocGenerator->generate($toc, "<h1>Header</h1>");
+$tocInsertor->insert($toc, "<h1>Header</h1>", {
+       'output' => \$output,
+       'doGenerateToc' => 0
+});
+       # Test ToC
+ok($output, "<h1>Header</h1><ul>\n<li>Header\n</ul>");
+
+
+#--- 5. outputFile ------------------------------------------------------------
+
+$toc->setOptions({'insertionPoint' => 'before <h1>'});
+       # Generate ToC
+$tocGenerator->generate($toc, "<h1>Header</h1>");
+       # Insert ToC, output to file
+$tocInsertor->insert($toc, "<h1>Header</h1>", {
+       'outputFile' => $filename,
+       'doGenerateToc' => 0
+});
+       # Read outputfile
+open(FILE, "<$filename") || die "Can't open $filename: $!";
+$content = join('', <FILE>);
+close(FILE);
+       # Test ToC
+ok($output, "<ul>\n<li>Header\n</ul><h1>Header</h1>");
+
+
+#--- 6. empty toc -------------------------------------------------------------
+
+$tocGenerator->generate($toc, "");
+$tocInsertor->insert($toc, "", {
+       'output' => \$output,
+       'doGenerateToc' => 0
+});
+ok($output, "");
+
+
+#--- TestAfterDeclaration() ---------------------------------------------------
+# function: Test putting HTML comment after declaration.  
+
+sub TestAfterDeclaration {
+               # Create objects
+       my $toc         = HTML::Toc->new();
+       my $tocInsertor = HTML::TocInsertor->new();
+       my $output;
+       
+               # Set ToC options
+   $toc->setOptions({
+               'insertionPoint' => "after <!ToC>",
+   });
+               # Generate ToC
+       $tocInsertor->insert($toc, <<EOT, {'output' => \$output});
+<!ToC><body>
+   <h1>Appendix</h1>
+   <h2>Appendix Paragraph</h2>
+   <h1>Appendix</h1>
+   <h2>Appendix Paragraph</h2>
+</body>
+EOT
+               # Test ToC
+       ok($output, <<EOT);
+<!ToC>
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul>
+   <li><a href=#h-1>Appendix</a>
+   <ul>
+      <li><a href=#h-1.1>Appendix Paragraph</a>
+   </ul>
+   <li><a href=#h-2>Appendix</a>
+   <ul>
+      <li><a href=#h-2.1>Appendix Paragraph</a>
+   </ul>
+</ul>
+<!-- End of generated Table of Contents -->
+<body>
+   <a name=h-1><h1>Appendix</h1></a>
+   <a name=h-1.1><h2>Appendix Paragraph</h2></a>
+   <a name=h-2><h1>Appendix</h1></a>
+   <a name=h-2.1><h2>Appendix Paragraph</h2></a>
+</body>
+EOT
+}  # TestAfterDeclaration()
+
+
+#--- TestNumberingStyle() -----------------------------------------------------
+# function: Test numberingstyle.
+
+sub TestNumberingStyle {
+               # Create objects
+       my $toc         = HTML::Toc->new();
+       my $tocInsertor = HTML::TocInsertor->new();
+       my $output;
+       
+               # Set ToC options
+   $toc->setOptions({
+               'numberingStyle'            => 'lower-alpha',
+               'doNumberToken'             => 1,
+      'tokenToToc' => [{
+            'tokenBegin'          => '<h1>',
+                       }, {
+            'tokenBegin'                        => '<h2>',
+            'level'                             => 2,
+                               'numberingStyle'      => 'upper-alpha'
+                       }, {
+            'tokenBegin'                        => '<h3>',
+            'level'                             => 3,
+                               'numberingStyle'      => 'decimal'
+         }]
+   });
+               # Generate ToC
+       $tocInsertor->insert($toc, <<EOT, {'output' => \$output});
+<body>
+   <h1>Chapter</h1>
+   <h2>Paragraph</h2>
+   <h3>Paragraph</h3>
+   <h3>Paragraph</h3>
+   <h3>Paragraph</h3>
+</body>
+EOT
+               # Test ToC
+       ok($output, <<EOT);
+<body>
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul>
+   <li><a href=#h-a>Chapter</a>
+   <ul>
+      <li><a href=#h-a.A>Paragraph</a>
+      <ul>
+         <li><a href=#h-a.A.1>Paragraph</a>
+         <li><a href=#h-a.A.2>Paragraph</a>
+         <li><a href=#h-a.A.3>Paragraph</a>
+      </ul>
+   </ul>
+</ul>
+<!-- End of generated Table of Contents -->
+
+   <a name=h-a><h1>a &nbsp;Chapter</h1></a>
+   <a name=h-a.A><h2>a.A &nbsp;Paragraph</h2></a>
+   <a name=h-a.A.1><h3>a.A.1 &nbsp;Paragraph</h3></a>
+   <a name=h-a.A.2><h3>a.A.2 &nbsp;Paragraph</h3></a>
+   <a name=h-a.A.3><h3>a.A.3 &nbsp;Paragraph</h3></a>
+</body>
+EOT
+}  # TestNumberingStyle()
+
+
+#--- TestReplaceComment() -----------------------------------------------------
+# function: Test replacing HTML comment with ToC.
+
+sub TestReplaceComment {
+               # Create objects
+       my $toc         = HTML::Toc->new();
+       my $tocInsertor = HTML::TocInsertor->new();
+       my $output;
+       
+               # Set ToC options
+   $toc->setOptions({
+               'insertionPoint' => "replace <!-- ToC -->"
+   });
+               # Generate ToC
+       $tocInsertor->insert($toc, <<EOT, {'output' => \$output});
+<!-- ToC -->
+<body>
+   <h1>Appendix</h1>
+   <h2>Appendix Paragraph</h2>
+   <h1>Appendix</h1>
+   <h2>Appendix Paragraph</h2>
+</body>
+EOT
+               # Test ToC
+       ok($output, <<EOT);
+
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul>
+   <li><a href=#h-1>Appendix</a>
+   <ul>
+      <li><a href=#h-1.1>Appendix Paragraph</a>
+   </ul>
+   <li><a href=#h-2>Appendix</a>
+   <ul>
+      <li><a href=#h-2.1>Appendix Paragraph</a>
+   </ul>
+</ul>
+<!-- End of generated Table of Contents -->
+
+<body>
+   <a name=h-1><h1>Appendix</h1></a>
+   <a name=h-1.1><h2>Appendix Paragraph</h2></a>
+   <a name=h-2><h1>Appendix</h1></a>
+   <a name=h-2.1><h2>Appendix Paragraph</h2></a>
+</body>
+EOT
+}  # TestReplaceComment()
+
+
+#--- TestReplaceText() -----------------------------------------------------
+# function: Test replacing HTML comment with ToC.
+
+sub TestReplaceText {
+               # Create objects
+       my $toc         = HTML::Toc->new();
+       my $tocInsertor = HTML::TocInsertor->new();
+       my $output;
+       
+               # Set ToC options
+   $toc->setOptions({
+               'insertionPoint' => "replace ToC will be placed here[,]"
+   });
+               # Generate ToC
+       $tocInsertor->insert($toc, <<EOT, {'output' => \$output});
+The ToC will be placed here, overnight.
+<body>
+   <h1>Appendix</h1>
+   <h2>Appendix Paragraph</h2>
+   <h1>Appendix</h1>
+   <h2>Appendix Paragraph</h2>
+</body>
+EOT
+               # Test ToC
+       ok($output, <<EOT);
+
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul>
+   <li><a href=#h-1>Appendix</a>
+   <ul>
+      <li><a href=#h-1.1>Appendix Paragraph</a>
+   </ul>
+   <li><a href=#h-2>Appendix</a>
+   <ul>
+      <li><a href=#h-2.1>Appendix Paragraph</a>
+   </ul>
+</ul>
+<!-- End of generated Table of Contents -->
+<body>
+   <a name=h-1><h1>Appendix</h1></a>
+   <a name=h-1.1><h2>Appendix Paragraph</h2></a>
+   <a name=h-2><h1>Appendix</h1></a>
+   <a name=h-2.1><h2>Appendix Paragraph</h2></a>
+</body>
+EOT
+}  # TestReplaceText()
+
+
+       # 7.  Test 'numberingStyle'
+TestNumberingStyle();
+       # 8.  Test replace comment
+TestReplaceComment();
+       # 9.  Test after declaration
+TestAfterDeclaration();
+       # 10.  Test replace text
+TestReplaceText();
diff --git a/examples/includes/HTML-Toc-0.91/t/manualTest.t b/examples/includes/HTML-Toc-0.91/t/manualTest.t
new file mode 100644 (file)
index 0000000..cc19fff
--- /dev/null
@@ -0,0 +1,768 @@
+#--- manual.t -----------------------------------------------------------------
+# function: Test HTML::ToC generating a manual.
+
+use strict;
+use Test;
+
+BEGIN { plan tests => 3; }
+
+use HTML::Toc;
+use HTML::TocGenerator;
+use HTML::TocInsertor;
+use HTML::TocUpdator;
+
+
+#--- AssembleTocLine() --------------------------------------------------------
+# function: Assemble ToC line.
+
+sub AssembleTocLine {
+               # Get arguments
+       my ($aLevel, $aGroupId, $aNode, $aSequenceNr, $aText) = @_;
+               # Local variables
+       my ($result);
+
+               # Assemble ToC line
+       SWITCH: {
+               if ($aGroupId eq "prelude") {
+                       $result = "<li>$aText\n";
+                       last SWITCH;
+               }
+               if ($aGroupId eq "part") {
+                       $result = "<li>Part $aNode &nbsp;$aText\n";
+                       last SWITCH;
+               }
+               if ($aGroupId eq "h") {
+                       $result = "<li>$aSequenceNr. &nbsp;$aText\n";
+                       last SWITCH;
+               }
+               else {
+                       $result = "<li>$aNode &nbsp;$aText\n";
+                       last SWITCH;
+               }
+       }
+
+               # Return value
+       return $result;
+}  # AssembleTocLine()
+
+
+#--- AssembleTokenNumber() ----------------------------------------------------
+# function: Assemble token number.
+
+sub AssembleTokenNumber {
+               # Get arguments
+       my ($aNode, $aGroupId, $aFile, $aGroupLevel, $aLevel, $aToc) = @_;
+               # Local variables
+       my ($result);
+               # Assemble token number
+       SWITCH: {
+               if ($aGroupId eq "part") {
+                       $result = "Part $aNode &nbsp;";
+                       last SWITCH;
+               }
+               else {
+                       $result = "$aNode &nbsp;";
+                       last SWITCH;
+               }
+       }
+               # Return value
+       return $result;
+}  # AssembleTokenNumber()
+
+
+#--- TestInsertManualToc ------------------------------------------------------
+# function: Test inserting ToC into manual.
+
+sub TestInsertManualToc {
+       my $output;
+               # Create objects
+       my $toc          = new HTML::Toc;
+       my $tocOfFigures = new HTML::Toc;
+       my $tocOfTables  = new HTML::Toc;
+       my $tocInsertor  = new HTML::TocInsertor;
+       
+               # Set ToC options
+       $toc->setOptions({
+               'doNestGroup'          => 1,
+               'doNumberToken'        => 1,
+               'insertionPoint'       => "replace <!-- Table of Contents -->",
+               'templateLevel'        => \&AssembleTocLine,
+      'templateLevelBegin'   => '"<ul class=toc_$groupId$level>\n"',
+      'templateLevelEnd'     => '"</ul>\n"',
+               'templateTokenNumber'  => \&AssembleTokenNumber,
+      'tokenToToc'           => [{
+            'groupId'        => 'part',
+                          'doNumberToken'  => 1,
+            'level'          => 1,
+            'tokenBegin'     => '<h1 class=part>',
+         }, {
+            'tokenBegin'     => '<h1 class=-[appendix|prelude|hidden|part]>'
+         }, {
+            'tokenBegin'     => '<h2>',
+            'level'          => 2
+         }, {
+            'tokenBegin'     => '<h3>',
+            'level'          => 3
+         }, {
+            'groupId'        => 'appendix',
+            'tokenBegin'     => '<h1 class=appendix>',
+                          'numberingStyle' => 'upper-alpha',
+         }, {
+            'groupId'        => 'appendix',
+            'tokenBegin'     => '<h2 class=appendix>',
+            'level'          => 2
+         }, {
+            'groupId'        => 'prelude',
+            'tokenBegin'     => '<h1 class=prelude>',
+            'level'          => 1,
+                          'doNumberToken'  => 0,
+         }],
+       });
+       $tocOfFigures->setOptions({
+               'doNumberToken'        => 1,
+               'insertionPoint'       => "replace <!-- Table of Figures -->",
+               'templateLevelBegin'   => '"<ol>\n"',
+               'templateLevelEnd'     => '"</ol>\n"',
+               'templateTokenNumber'  => '"Figure $node: &nbsp;"',
+               'tokenToToc'           => [{
+                               'groupId'        => 'Figure',
+                               'tokenBegin'     => '<p class=captionFigure>'
+                       }]
+       });
+       $tocOfTables->setOptions({
+               'doNumberToken'        => 1,
+               'insertionPoint'       => "replace <!-- Table of Tables -->",
+               'templateLevelBegin'   => '"<ol>\n"',
+               'templateLevelEnd'     => '"</ol>\n"',
+               'templateTokenNumber'  => '"Table $node: &nbsp;"',
+               'tokenToToc'           => [{
+                               'groupId'        => 'Table',
+                               'tokenBegin'     => '<p class=captionTable>'
+                       }]
+       });
+               # Insert ToC
+       $tocInsertor->insertIntoFile(
+               [$toc, $tocOfFigures, $tocOfTables], 
+               't/ManualTest/manualTest1.htm', {
+                        'doUseGroupsGlobal' => 1,
+                        'output'            => \$output,
+                        'outputFile'        => 't/ManualTest/manualTest2.htm'
+               }
+       );
+       ok($output, <<EOT);
+<html>
+<head>
+   <title>Manual</title>
+    <style type="text/css">
+       ul.toc_appendix1 { 
+         list-style-type: none;
+         margin-left: 0;
+         margin-top: 1em;
+         margin-bottom: 1em;
+       }
+       ul.toc_h1 {
+         list-style-type: none;
+         margin-left: 1;
+         margin-top: 1em;
+         margin-bottom: 1em;
+       }
+       ul.toc_h2 {
+         list-style-type: none;
+       }
+       ul.toc_h3 {
+         list-style-type: none;
+       }
+       ul.toc_part1 {
+         list-style-type: none;
+         margin-left: 1;
+         margin-top: 1em;
+         margin-bottom: 1em;
+       }
+       ul.toc_prelude1 {
+         list-style: none;
+       }
+       p.captionFigure {
+         font-style: italic;
+         font-weight: bold;
+       }
+       p.captionTable {
+         font-style: italic;
+         font-weight: bold;
+       }
+    </style>
+</head>
+<body>
+
+<a name=prelude-1><h1 class=prelude>Preface</h1></a>
+Better C than never.
+
+<h1 class=hidden>Table of Contents</h1>
+
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul class=toc_prelude1>
+   <li><a href=#prelude-1>Preface</a>
+   <li><a href=#prelude-2>Table of Figures</a>
+   <li><a href=#prelude-3>Table of Tables</a>
+   <li><a href=#prelude-4>Introduction</a>
+   <ul class=toc_part1>
+      <li>Part 1 &nbsp;<a href=#part-1>Disks</a>
+      <ul class=toc_h1>
+         <li>1. &nbsp;<a href=#h-1>Compiler Disk v1</a>
+         <ul class=toc_h2>
+            <li>1. &nbsp;<a href=#h-1.1>System</a>
+            <li>2. &nbsp;<a href=#h-1.2>Standard Library</a>
+         </ul>
+         <li>2. &nbsp;<a href=#h-2>Compiler Disk v2</a>
+         <ul class=toc_h2>
+            <li>1. &nbsp;<a href=#h-2.1>System</a>
+            <ul class=toc_h3>
+               <li>1. &nbsp;<a href=#h-2.1.1>parser.com</a>
+               <li>2. &nbsp;<a href=#h-2.1.2>compiler.com</a>
+               <li>3. &nbsp;<a href=#h-2.1.3>linker.com</a>
+            </ul>
+            <li>2. &nbsp;<a href=#h-2.2>Standard Library</a>
+         </ul>
+         <li>3. &nbsp;<a href=#h-3>Library System Disk</a>
+      </ul>
+      <li>Part 2 &nbsp;<a href=#part-2>Personal</a>
+      <ul class=toc_h1>
+         <li>4. &nbsp;<a href=#h-4>Tips & Tricks</a>
+      </ul>
+      <li>Part 3 &nbsp;<a href=#part-3>Appendixes</a>
+      <ul class=toc_appendix1>
+         <li>A &nbsp;<a href=#appendix-A>Functions Standard Library v1</a>
+         <li>B &nbsp;<a href=#appendix-B>Functions Standard Library v2</a>
+         <li>C &nbsp;<a href=#appendix-C>Functions Graphic Library</a>
+      </ul>
+   </ul>
+   <li><a href=#prelude-5>Bibliography</a>
+</ul>
+<!-- End of generated Table of Contents -->
+
+
+<a name=prelude-2><h1 class=prelude>Table of Figures</h1></a>
+
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ol>
+   <li><a href=#Figure-1>Contents Compiler Disk v1</a>
+   <li><a href=#Figure-2>Contents Compiler Disk v2</a>
+</ol>
+<!-- End of generated Table of Contents -->
+
+
+<a name=prelude-3><h1 class=prelude>Table of Tables</h1></a>
+
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ol>
+   <li><a href=#Table-1>Compile Steps</a>
+</ol>
+<!-- End of generated Table of Contents -->
+
+
+<a name=prelude-4><h1 class=prelude>Introduction</h1></a>
+Thanks to standardisation and the excellent work of the QWERTY corporation it is possible to learn C with almost any C manual.
+<a name=Table-1><p class=captionTable>Table 1: &nbsp;Compile Steps</p></a>
+<ul><pre>
+   Parser
+   Compiler
+   Linker
+</pre></ul>
+
+<a name=part-1><h1 class=part>Part 1 &nbsp;Disks</h1></a>
+<a name=h-1><h1>1 &nbsp;Compiler Disk v1</h1></a>
+<img src=img.gif alt="Contents Compiler Disk v1">
+<a name=Figure-1><p class=captionFigure>Figure 1: &nbsp;Contents Compiler Disk v1</p></a>
+
+<a name=h-1.1><h2>1.1 &nbsp;System</h2></a>
+<a name=h-1.2><h2>1.2 &nbsp;Standard Library</h2></a>
+
+<a name=h-2><h1>2 &nbsp;Compiler Disk v2</h1></a>
+<img src=img.gif alt="Contents Compiler Disk v2">
+<a name=Figure-2><p class=captionFigure>Figure 2: &nbsp;Contents Compiler Disk v2</p></a>
+
+<a name=h-2.1><h2>2.1 &nbsp;System</h2></a>
+<a name=h-2.1.1><h3>2.1.1 &nbsp;parser.com</h3></a>
+<a name=h-2.1.2><h3>2.1.2 &nbsp;compiler.com</h3></a>
+<a name=h-2.1.3><h3>2.1.3 &nbsp;linker.com</h3></a>
+<a name=h-2.2><h2>2.2 &nbsp;Standard Library</h2></a>
+
+<a name=h-3><h1>3 &nbsp;Library System Disk</h1></a>
+<a name=part-2><h1 class=part>Part 2 &nbsp;Personal</h1></a>
+<a name=h-4><h1>4 &nbsp;Tips & Tricks</h1></a>
+<a name=part-3><h1 class=part>Part 3 &nbsp;Appendixes</h1></a>
+<a name=appendix-A><h1 class=appendix>A &nbsp;Functions Standard Library v1</h1></a>
+<a name=appendix-B><h1 class=appendix>B &nbsp;Functions Standard Library v2</h1></a>
+<a name=appendix-C><h1 class=appendix>C &nbsp;Functions Graphic Library</h1></a>
+<a name=prelude-5><h1 class=prelude>Bibliography</h1></a>
+</body>
+</html>
+EOT
+}  # TestInsertManualToc()
+
+
+#--- TestInsertManualForUpdating() --------------------------------------------
+# function: Test inserting ToC into manual.
+
+sub TestInsertManualForUpdating {
+       my $output;
+               # Create objects
+       my $toc          = new HTML::Toc;
+       my $tocOfFigures = new HTML::Toc;
+       my $tocOfTables  = new HTML::Toc;
+       my $tocUpdator   = new HTML::TocUpdator;
+       
+               # Set ToC options
+       $toc->setOptions({
+               'doNestGroup'          => 1,
+               'doNumberToken'        => 1,
+               'insertionPoint'       => "after <!-- Table of Contents -->",
+               'templateLevel'        => \&AssembleTocLine,
+      'templateLevelBegin'   => '"<ul class=toc_$groupId$level>\n"',
+      'templateLevelEnd'     => '"</ul>\n"',
+               'templateTokenNumber'  => \&AssembleTokenNumber,
+      'tokenToToc'           => [{
+            'groupId'        => 'part',
+                          'doNumberToken'  => 1,
+            'level'          => 1,
+            'tokenBegin'     => '<h1 class=part>',
+         }, {
+            'tokenBegin'     => '<h1 class=-[appendix|prelude|hidden|part]>'
+         }, {
+            'tokenBegin'     => '<h2>',
+            'level'          => 2
+         }, {
+            'tokenBegin'     => '<h3>',
+            'level'          => 3
+         }, {
+            'groupId'        => 'appendix',
+            'tokenBegin'     => '<h1 class=appendix>',
+                          'numberingStyle' => 'upper-alpha',
+         }, {
+            'groupId'        => 'appendix',
+            'tokenBegin'     => '<h2 class=appendix>',
+            'level'          => 2
+         }, {
+            'groupId'        => 'prelude',
+            'tokenBegin'     => '<h1 class=prelude>',
+            'level'          => 1,
+                          'doNumberToken'  => 0,
+         }],
+       });
+       $tocOfFigures->setOptions({
+               'doNumberToken'        => 1,
+               'insertionPoint'       => "after <!-- Table of Figures -->",
+               'templateLevelBegin'   => '"<ol>\n"',
+               'templateLevelEnd'     => '"</ol>\n"',
+               'templateTokenNumber'  => '"Figure $node: &nbsp;"',
+               'tokenToToc'           => [{
+                               'groupId'        => 'Figure',
+                               'tokenBegin'     => '<p class=captionFigure>'
+                       }]
+       });
+       $tocOfTables->setOptions({
+               'doNumberToken'        => 1,
+               'insertionPoint'       => "after <!-- Table of Tables -->",
+               'templateLevelBegin'   => '"<ol>\n"',
+               'templateLevelEnd'     => '"</ol>\n"',
+               'templateTokenNumber'  => '"Table $node: &nbsp;"',
+               'tokenToToc'           => [{
+                               'groupId'        => 'Table',
+                               'tokenBegin'     => '<p class=captionTable>'
+                       }]
+       });
+               # Insert ToC
+       $tocUpdator->updateFile(
+               [$toc, $tocOfFigures, $tocOfTables], 
+               't/ManualTest/manualTest1.htm', {
+                        'doUseGroupsGlobal' => 1,
+                        'output'            => \$output,
+                        'outputFile'        => 't/ManualTest/manualTest3.htm'
+               }
+       );
+       ok($output, <<EOT);
+<html>
+<head>
+   <title>Manual</title>
+    <style type="text/css">
+       ul.toc_appendix1 { 
+         list-style-type: none;
+         margin-left: 0;
+         margin-top: 1em;
+         margin-bottom: 1em;
+       }
+       ul.toc_h1 {
+         list-style-type: none;
+         margin-left: 1;
+         margin-top: 1em;
+         margin-bottom: 1em;
+       }
+       ul.toc_h2 {
+         list-style-type: none;
+       }
+       ul.toc_h3 {
+         list-style-type: none;
+       }
+       ul.toc_part1 {
+         list-style-type: none;
+         margin-left: 1;
+         margin-top: 1em;
+         margin-bottom: 1em;
+       }
+       ul.toc_prelude1 {
+         list-style: none;
+       }
+       p.captionFigure {
+         font-style: italic;
+         font-weight: bold;
+       }
+       p.captionTable {
+         font-style: italic;
+         font-weight: bold;
+       }
+    </style>
+</head>
+<body>
+
+<!-- #BeginTocAnchorNameBegin --><a name=prelude-1><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Preface</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+Better C than never.
+
+<h1 class=hidden>Table of Contents</h1>
+<!-- Table of Contents --><!-- #BeginToc -->
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul class=toc_prelude1>
+   <li><a href=#prelude-1>Preface</a>
+   <li><a href=#prelude-2>Table of Figures</a>
+   <li><a href=#prelude-3>Table of Tables</a>
+   <li><a href=#prelude-4>Introduction</a>
+   <ul class=toc_part1>
+      <li>Part 1 &nbsp;<a href=#part-1>Disks</a>
+      <ul class=toc_h1>
+         <li>1. &nbsp;<a href=#h-1>Compiler Disk v1</a>
+         <ul class=toc_h2>
+            <li>1. &nbsp;<a href=#h-1.1>System</a>
+            <li>2. &nbsp;<a href=#h-1.2>Standard Library</a>
+         </ul>
+         <li>2. &nbsp;<a href=#h-2>Compiler Disk v2</a>
+         <ul class=toc_h2>
+            <li>1. &nbsp;<a href=#h-2.1>System</a>
+            <ul class=toc_h3>
+               <li>1. &nbsp;<a href=#h-2.1.1>parser.com</a>
+               <li>2. &nbsp;<a href=#h-2.1.2>compiler.com</a>
+               <li>3. &nbsp;<a href=#h-2.1.3>linker.com</a>
+            </ul>
+            <li>2. &nbsp;<a href=#h-2.2>Standard Library</a>
+         </ul>
+         <li>3. &nbsp;<a href=#h-3>Library System Disk</a>
+      </ul>
+      <li>Part 2 &nbsp;<a href=#part-2>Personal</a>
+      <ul class=toc_h1>
+         <li>4. &nbsp;<a href=#h-4>Tips & Tricks</a>
+      </ul>
+      <li>Part 3 &nbsp;<a href=#part-3>Appendixes</a>
+      <ul class=toc_appendix1>
+         <li>A &nbsp;<a href=#appendix-A>Functions Standard Library v1</a>
+         <li>B &nbsp;<a href=#appendix-B>Functions Standard Library v2</a>
+         <li>C &nbsp;<a href=#appendix-C>Functions Graphic Library</a>
+      </ul>
+   </ul>
+   <li><a href=#prelude-5>Bibliography</a>
+</ul>
+<!-- End of generated Table of Contents -->
+<!-- #EndToc -->
+
+<!-- #BeginTocAnchorNameBegin --><a name=prelude-2><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Table of Figures</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- Table of Figures --><!-- #BeginToc -->
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ol>
+   <li><a href=#Figure-1>Contents Compiler Disk v1</a>
+   <li><a href=#Figure-2>Contents Compiler Disk v2</a>
+</ol>
+<!-- End of generated Table of Contents -->
+<!-- #EndToc -->
+
+<!-- #BeginTocAnchorNameBegin --><a name=prelude-3><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Table of Tables</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- Table of Tables --><!-- #BeginToc -->
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ol>
+   <li><a href=#Table-1>Compile Steps</a>
+</ol>
+<!-- End of generated Table of Contents -->
+<!-- #EndToc -->
+
+<!-- #BeginTocAnchorNameBegin --><a name=prelude-4><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Introduction</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+Thanks to standardisation and the excellent work of the QWERTY corporation it is possible to learn C with almost any C manual.
+<!-- #BeginTocAnchorNameBegin --><a name=Table-1><!-- #EndTocAnchorNameBegin --><p class=captionTable><!-- #BeginTocNumber -->Table 1: &nbsp;<!-- #EndTocNumber -->Compile Steps</p><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<ul><pre>
+   Parser
+   Compiler
+   Linker
+</pre></ul>
+
+<!-- #BeginTocAnchorNameBegin --><a name=part-1><!-- #EndTocAnchorNameBegin --><h1 class=part><!-- #BeginTocNumber -->Part 1 &nbsp;<!-- #EndTocNumber -->Disks</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Compiler Disk v1</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<img src=img.gif alt="Contents Compiler Disk v1">
+<!-- #BeginTocAnchorNameBegin --><a name=Figure-1><!-- #EndTocAnchorNameBegin --><p class=captionFigure><!-- #BeginTocNumber -->Figure 1: &nbsp;<!-- #EndTocNumber -->Contents Compiler Disk v1</p><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+
+<!-- #BeginTocAnchorNameBegin --><a name=h-1.1><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->1.1 &nbsp;<!-- #EndTocNumber -->System</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=h-1.2><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->1.2 &nbsp;<!-- #EndTocNumber -->Standard Library</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+
+<!-- #BeginTocAnchorNameBegin --><a name=h-2><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->2 &nbsp;<!-- #EndTocNumber -->Compiler Disk v2</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<img src=img.gif alt="Contents Compiler Disk v2">
+<!-- #BeginTocAnchorNameBegin --><a name=Figure-2><!-- #EndTocAnchorNameBegin --><p class=captionFigure><!-- #BeginTocNumber -->Figure 2: &nbsp;<!-- #EndTocNumber -->Contents Compiler Disk v2</p><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+
+<!-- #BeginTocAnchorNameBegin --><a name=h-2.1><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->2.1 &nbsp;<!-- #EndTocNumber -->System</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=h-2.1.1><!-- #EndTocAnchorNameBegin --><h3><!-- #BeginTocNumber -->2.1.1 &nbsp;<!-- #EndTocNumber -->parser.com</h3><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=h-2.1.2><!-- #EndTocAnchorNameBegin --><h3><!-- #BeginTocNumber -->2.1.2 &nbsp;<!-- #EndTocNumber -->compiler.com</h3><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=h-2.1.3><!-- #EndTocAnchorNameBegin --><h3><!-- #BeginTocNumber -->2.1.3 &nbsp;<!-- #EndTocNumber -->linker.com</h3><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=h-2.2><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->2.2 &nbsp;<!-- #EndTocNumber -->Standard Library</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+
+<!-- #BeginTocAnchorNameBegin --><a name=h-3><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->3 &nbsp;<!-- #EndTocNumber -->Library System Disk</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=part-2><!-- #EndTocAnchorNameBegin --><h1 class=part><!-- #BeginTocNumber -->Part 2 &nbsp;<!-- #EndTocNumber -->Personal</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=h-4><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->4 &nbsp;<!-- #EndTocNumber -->Tips & Tricks</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=part-3><!-- #EndTocAnchorNameBegin --><h1 class=part><!-- #BeginTocNumber -->Part 3 &nbsp;<!-- #EndTocNumber -->Appendixes</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=appendix-A><!-- #EndTocAnchorNameBegin --><h1 class=appendix><!-- #BeginTocNumber -->A &nbsp;<!-- #EndTocNumber -->Functions Standard Library v1</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=appendix-B><!-- #EndTocAnchorNameBegin --><h1 class=appendix><!-- #BeginTocNumber -->B &nbsp;<!-- #EndTocNumber -->Functions Standard Library v2</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=appendix-C><!-- #EndTocAnchorNameBegin --><h1 class=appendix><!-- #BeginTocNumber -->C &nbsp;<!-- #EndTocNumber -->Functions Graphic Library</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=prelude-5><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Bibliography</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+</body>
+</html>
+EOT
+}  # TestInsertManualForUpdating()
+
+
+#--- TestUpdateManual() -------------------------------------------------------
+# function: Test inserting ToC into manual.
+
+sub TestUpdateManual {
+       my $output;
+               # Create objects
+       my $toc          = new HTML::Toc;
+       my $tocOfFigures = new HTML::Toc;
+       my $tocOfTables  = new HTML::Toc;
+       my $tocUpdator   = new HTML::TocUpdator;
+       
+               # Set ToC options
+       $toc->setOptions({
+               'doNestGroup'          => 1,
+               'doNumberToken'        => 1,
+               'insertionPoint'       => "after <!-- Table of Contents -->",
+               'templateLevel'        => \&AssembleTocLine,
+      'templateLevelBegin'   => '"<ul class=toc_$groupId$level>\n"',
+      'templateLevelEnd'     => '"</ul>\n"',
+               'templateTokenNumber'  => \&AssembleTokenNumber,
+      'tokenToToc'           => [{
+            'groupId'        => 'part',
+                          'doNumberToken'  => 1,
+            'level'          => 1,
+            'tokenBegin'     => '<h1 class=part>',
+         }, {
+            'tokenBegin'     => '<h1 class=-[appendix|prelude|hidden|part]>'
+         }, {
+            'tokenBegin'     => '<h2>',
+            'level'          => 2
+         }, {
+            'tokenBegin'     => '<h3>',
+            'level'          => 3
+         }, {
+            'groupId'        => 'appendix',
+            'tokenBegin'     => '<h1 class=appendix>',
+                          'numberingStyle' => 'upper-alpha',
+         }, {
+            'groupId'        => 'appendix',
+            'tokenBegin'     => '<h2 class=appendix>',
+            'level'          => 2
+         }, {
+            'groupId'        => 'prelude',
+            'tokenBegin'     => '<h1 class=prelude>',
+            'level'          => 1,
+                          'doNumberToken'  => 0,
+         }],
+       });
+       $tocOfFigures->setOptions({
+               'doNumberToken'        => 1,
+               'insertionPoint'       => "after <!-- Table of Figures -->",
+               'templateLevelBegin'   => '"<ol>\n"',
+               'templateLevelEnd'     => '"</ol>\n"',
+               'templateTokenNumber'  => '"Figure $node: &nbsp;"',
+               'tokenToToc'           => [{
+                               'groupId'        => 'Figure',
+                               'tokenBegin'     => '<p class=captionFigure>'
+                       }]
+       });
+       $tocOfTables->setOptions({
+               'doNumberToken'        => 1,
+               'insertionPoint'       => "after <!-- Table of Tables -->",
+               'templateLevelBegin'   => '"<ol>\n"',
+               'templateLevelEnd'     => '"</ol>\n"',
+               'templateTokenNumber'  => '"Table $node: &nbsp;"',
+               'tokenToToc'           => [{
+                               'groupId'        => 'Table',
+                               'tokenBegin'     => '<p class=captionTable>'
+                       }]
+       });
+               # Insert ToC
+       $tocUpdator->updateFile(
+               [$toc, $tocOfFigures, $tocOfTables], 
+               't/ManualTest/manualTest3.htm', {
+                        'doUseGroupsGlobal' => 1,
+                        'output'            => \$output,
+                        'outputFile'        => 't/ManualTest/manualTest4.htm'
+               }
+       );
+       ok($output, <<EOT);
+<html>
+<head>
+   <title>Manual</title>
+    <style type="text/css">
+       ul.toc_appendix1 { 
+         list-style-type: none;
+         margin-left: 0;
+         margin-top: 1em;
+         margin-bottom: 1em;
+       }
+       ul.toc_h1 {
+         list-style-type: none;
+         margin-left: 1;
+         margin-top: 1em;
+         margin-bottom: 1em;
+       }
+       ul.toc_h2 {
+         list-style-type: none;
+       }
+       ul.toc_h3 {
+         list-style-type: none;
+       }
+       ul.toc_part1 {
+         list-style-type: none;
+         margin-left: 1;
+         margin-top: 1em;
+         margin-bottom: 1em;
+       }
+       ul.toc_prelude1 {
+         list-style: none;
+       }
+       p.captionFigure {
+         font-style: italic;
+         font-weight: bold;
+       }
+       p.captionTable {
+         font-style: italic;
+         font-weight: bold;
+       }
+    </style>
+</head>
+<body>
+
+<!-- #BeginTocAnchorNameBegin --><a name=prelude-1><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Preface</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+Better C than never.
+
+<h1 class=hidden>Table of Contents</h1>
+<!-- Table of Contents --><!-- #BeginToc -->
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul class=toc_prelude1>
+   <li><a href=#prelude-1>Preface</a>
+   <li><a href=#prelude-2>Table of Figures</a>
+   <li><a href=#prelude-3>Table of Tables</a>
+   <li><a href=#prelude-4>Introduction</a>
+   <ul class=toc_part1>
+      <li>Part 1 &nbsp;<a href=#part-1>Disks</a>
+      <ul class=toc_h1>
+         <li>1. &nbsp;<a href=#h-1>Compiler Disk v1</a>
+         <ul class=toc_h2>
+            <li>1. &nbsp;<a href=#h-1.1>System</a>
+            <li>2. &nbsp;<a href=#h-1.2>Standard Library</a>
+         </ul>
+         <li>2. &nbsp;<a href=#h-2>Compiler Disk v2</a>
+         <ul class=toc_h2>
+            <li>1. &nbsp;<a href=#h-2.1>System</a>
+            <ul class=toc_h3>
+               <li>1. &nbsp;<a href=#h-2.1.1>parser.com</a>
+               <li>2. &nbsp;<a href=#h-2.1.2>compiler.com</a>
+               <li>3. &nbsp;<a href=#h-2.1.3>linker.com</a>
+            </ul>
+            <li>2. &nbsp;<a href=#h-2.2>Standard Library</a>
+         </ul>
+         <li>3. &nbsp;<a href=#h-3>Library System Disk</a>
+      </ul>
+      <li>Part 2 &nbsp;<a href=#part-2>Personal</a>
+      <ul class=toc_h1>
+         <li>4. &nbsp;<a href=#h-4>Tips & Tricks</a>
+      </ul>
+      <li>Part 3 &nbsp;<a href=#part-3>Appendixes</a>
+      <ul class=toc_appendix1>
+         <li>A &nbsp;<a href=#appendix-A>Functions Standard Library v1</a>
+         <li>B &nbsp;<a href=#appendix-B>Functions Standard Library v2</a>
+         <li>C &nbsp;<a href=#appendix-C>Functions Graphic Library</a>
+      </ul>
+   </ul>
+   <li><a href=#prelude-5>Bibliography</a>
+</ul>
+<!-- End of generated Table of Contents -->
+<!-- #EndToc -->
+
+<!-- #BeginTocAnchorNameBegin --><a name=prelude-2><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Table of Figures</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- Table of Figures --><!-- #BeginToc -->
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ol>
+   <li><a href=#Figure-1>Contents Compiler Disk v1</a>
+   <li><a href=#Figure-2>Contents Compiler Disk v2</a>
+</ol>
+<!-- End of generated Table of Contents -->
+<!-- #EndToc -->
+
+<!-- #BeginTocAnchorNameBegin --><a name=prelude-3><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Table of Tables</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- Table of Tables --><!-- #BeginToc -->
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ol>
+   <li><a href=#Table-1>Compile Steps</a>
+</ol>
+<!-- End of generated Table of Contents -->
+<!-- #EndToc -->
+
+<!-- #BeginTocAnchorNameBegin --><a name=prelude-4><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Introduction</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+Thanks to standardisation and the excellent work of the QWERTY corporation it is possible to learn C with almost any C manual.
+<!-- #BeginTocAnchorNameBegin --><a name=Table-1><!-- #EndTocAnchorNameBegin --><p class=captionTable><!-- #BeginTocNumber -->Table 1: &nbsp;<!-- #EndTocNumber -->Compile Steps</p><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<ul><pre>
+   Parser
+   Compiler
+   Linker
+</pre></ul>
+
+<!-- #BeginTocAnchorNameBegin --><a name=part-1><!-- #EndTocAnchorNameBegin --><h1 class=part><!-- #BeginTocNumber -->Part 1 &nbsp;<!-- #EndTocNumber -->Disks</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Compiler Disk v1</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<img src=img.gif alt="Contents Compiler Disk v1">
+<!-- #BeginTocAnchorNameBegin --><a name=Figure-1><!-- #EndTocAnchorNameBegin --><p class=captionFigure><!-- #BeginTocNumber -->Figure 1: &nbsp;<!-- #EndTocNumber -->Contents Compiler Disk v1</p><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+
+<!-- #BeginTocAnchorNameBegin --><a name=h-1.1><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->1.1 &nbsp;<!-- #EndTocNumber -->System</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=h-1.2><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->1.2 &nbsp;<!-- #EndTocNumber -->Standard Library</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+
+<!-- #BeginTocAnchorNameBegin --><a name=h-2><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->2 &nbsp;<!-- #EndTocNumber -->Compiler Disk v2</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<img src=img.gif alt="Contents Compiler Disk v2">
+<!-- #BeginTocAnchorNameBegin --><a name=Figure-2><!-- #EndTocAnchorNameBegin --><p class=captionFigure><!-- #BeginTocNumber -->Figure 2: &nbsp;<!-- #EndTocNumber -->Contents Compiler Disk v2</p><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+
+<!-- #BeginTocAnchorNameBegin --><a name=h-2.1><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->2.1 &nbsp;<!-- #EndTocNumber -->System</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=h-2.1.1><!-- #EndTocAnchorNameBegin --><h3><!-- #BeginTocNumber -->2.1.1 &nbsp;<!-- #EndTocNumber -->parser.com</h3><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=h-2.1.2><!-- #EndTocAnchorNameBegin --><h3><!-- #BeginTocNumber -->2.1.2 &nbsp;<!-- #EndTocNumber -->compiler.com</h3><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=h-2.1.3><!-- #EndTocAnchorNameBegin --><h3><!-- #BeginTocNumber -->2.1.3 &nbsp;<!-- #EndTocNumber -->linker.com</h3><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=h-2.2><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->2.2 &nbsp;<!-- #EndTocNumber -->Standard Library</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+
+<!-- #BeginTocAnchorNameBegin --><a name=h-3><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->3 &nbsp;<!-- #EndTocNumber -->Library System Disk</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=part-2><!-- #EndTocAnchorNameBegin --><h1 class=part><!-- #BeginTocNumber -->Part 2 &nbsp;<!-- #EndTocNumber -->Personal</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=h-4><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->4 &nbsp;<!-- #EndTocNumber -->Tips & Tricks</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=part-3><!-- #EndTocAnchorNameBegin --><h1 class=part><!-- #BeginTocNumber -->Part 3 &nbsp;<!-- #EndTocNumber -->Appendixes</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=appendix-A><!-- #EndTocAnchorNameBegin --><h1 class=appendix><!-- #BeginTocNumber -->A &nbsp;<!-- #EndTocNumber -->Functions Standard Library v1</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=appendix-B><!-- #EndTocAnchorNameBegin --><h1 class=appendix><!-- #BeginTocNumber -->B &nbsp;<!-- #EndTocNumber -->Functions Standard Library v2</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=appendix-C><!-- #EndTocAnchorNameBegin --><h1 class=appendix><!-- #BeginTocNumber -->C &nbsp;<!-- #EndTocNumber -->Functions Graphic Library</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+<!-- #BeginTocAnchorNameBegin --><a name=prelude-5><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Bibliography</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+</body>
+</html>
+EOT
+}  # TestUpdateManual()
+
+
+       # Test inserting ToC into manual
+TestInsertManualToc();
+       # Test inserting ToC with update tokens into manual
+TestInsertManualForUpdating();
+       # Test updating ToC
+TestUpdateManual();
diff --git a/examples/includes/HTML-Toc-0.91/t/options.t b/examples/includes/HTML-Toc-0.91/t/options.t
new file mode 100644 (file)
index 0000000..04bedac
--- /dev/null
@@ -0,0 +1,194 @@
+#--- options.t ----------------------------------------------------------------
+# function: Test HTML::ToC.  In particular test the available options.
+
+use strict;
+use Test;
+
+BEGIN { plan tests => 5; }
+
+use HTML::Toc;
+use HTML::TocGenerator;
+use HTML::TocInsertor;
+use HTML::TocUpdator;
+
+my ($filename);
+
+BEGIN {
+               # Create test file
+       $filename = "file$$.htm";
+       die "$filename is already there" if -e $filename;
+}
+
+
+END {
+               # Remove test file
+       unlink($filename) or warn "Can't unlink $filename: $!";
+}
+
+
+#--- TestAttributeToExcludeToken() --------------------------------------------
+# function: Test 'HTML::Toc' option 'attributeToExcludeToken'
+
+sub TestAttributeToExcludeToken {
+               # Assemble test file
+       open(FILE, ">$filename") || die "Can't create $filename: $!";
+       print FILE <<'EOT'; close(FILE);
+<body>
+   <h1>Chapter 1</h1>
+   <h1 class=appendix>Appendix</h1>
+</body>
+EOT
+
+               # Create objects
+       my $toc          = HTML::Toc->new();
+       my $tocGenerator = HTML::TocGenerator->new();
+       
+   $toc->setOptions({
+               'attributeToExcludeToken' => 'foo',
+               'tokenToToc' => [{
+                       'tokenBegin' => '<h1 class=foodix>'
+               }]
+   });
+               # Generate ToC
+       $tocGenerator->generateFromFile($toc, $filename);
+               # Test ToC
+       ok($toc->format(), <<EOT);
+
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul>
+   <li><a href=#h-1>Chapter 1</a>
+</ul>
+<!-- End of generated Table of Contents -->
+EOT
+}  # TestAttributeToExcludeToken()
+
+
+#--- TestAttributeToTocToken() ------------------------------------------------
+# function: Test 'HTML::Toc' option 'attributeToTocToken'
+
+sub TestAttributeToTocToken {
+               # Assemble test file
+       open(FILE, ">$filename") || die "Can't create $filename: $!";
+       print FILE <<'EOT'; close(FILE);
+<body>
+   <img src=test.gif alt=Picture>
+</body>
+</html>
+EOT
+
+               # Create objects
+       my $toc          = HTML::Toc->new();
+       my $tocGenerator = HTML::TocGenerator->new();
+       
+   $toc->setOptions({
+       'attributeToTocToken' => 'foo',
+      'tokenToToc'   => [{
+         'groupId'    => 'image',
+         'tokenBegin' => '<img alt=foo>'
+      }],
+   });
+               # Generate ToC
+       $tocGenerator->generateFromFile($toc, $filename);
+               # Test ToC
+       ok($toc->format(), <<EOT);
+
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul>
+   <li><a href=#image-1>Picture</a>
+</ul>
+<!-- End of generated Table of Contents -->
+EOT
+}  # TestAttributeToTocToken()
+
+
+#--- TestNumberingStyleDecimal ------------------------------------------------
+# function: Test 'decimal' numbering style.
+
+sub TestNumberingStyleDecimal {
+               # Local variables
+       my $output;
+               # Create objects
+       my $toc         = HTML::Toc->new();
+       my $tocInsertor = HTML::TocInsertor->new();
+       
+   $toc->setOptions({
+               'doNumberToken' => 1,
+      'tokenToToc'   => [{
+                       'level' => 1,
+                       'tokenBegin' => '<h1>',
+                       'numberingStyle' => 'decimal'
+      }],
+   });
+               # Generate ToC
+       $tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
+               # Test ToC
+       ok("$output\n", <<EOT);
+<a name=h-1><h1>1 &nbsp;Header</h1></a>
+EOT
+}  # TestNumberingStyleDecimal()
+
+
+#--- TestNumberingStyleLowerAlpha ---------------------------------------------
+# function: Test 'lower-alpha' numbering style.
+
+sub TestNumberingStyleLowerAlpha {
+               # Local variables
+       my $output;
+               # Create objects
+       my $toc         = HTML::Toc->new();
+       my $tocInsertor = HTML::TocInsertor->new();
+       
+   $toc->setOptions({
+               'doNumberToken' => 1,
+      'tokenToToc'   => [{
+                       'level' => 1,
+                       'tokenBegin' => '<h1>',
+                       'numberingStyle' => 'lower-alpha'
+      }],
+   });
+               # Generate ToC
+       $tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
+               # Test ToC
+       ok("$output\n", <<EOT);
+<a name=h-a><h1>a &nbsp;Header</h1></a>
+EOT
+}  # TestNumberingStyleLowerAlpha()
+
+
+#--- TestNumberingStyleUpperAlpha ---------------------------------------------
+# function: Test 'upper-alpha' numbering style.
+
+sub TestNumberingStyleUpperAlpha {
+               # Local variables
+       my $output;
+               # Create objects
+       my $toc         = HTML::Toc->new();
+       my $tocInsertor = HTML::TocInsertor->new();
+       
+   $toc->setOptions({
+               'doNumberToken' => 1,
+      'tokenToToc'   => [{
+                       'level' => 1,
+                       'tokenBegin' => '<h1>',
+                       'numberingStyle' => 'upper-alpha'
+      }],
+   });
+               # Generate ToC
+       $tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
+               # Test ToC
+       ok("$output\n", <<EOT);
+<a name=h-A><h1>A &nbsp;Header</h1></a>
+EOT
+}  # TestNumberingStyleUpperAlpha()
+
+
+       # Test 'attributeToTocToken'
+TestAttributeToTocToken();
+       # Test 'attributeToExcludeToken'
+TestAttributeToExcludeToken();
+       # Test 'numberingStyleDecimal'
+TestNumberingStyleDecimal();
+       # Test 'numberingStyleLowerAlpha'
+TestNumberingStyleLowerAlpha();
+       # Test 'numberingStyleUpperAlpha'
+TestNumberingStyleUpperAlpha();
diff --git a/examples/includes/HTML-Toc-0.91/t/podExamples.t b/examples/includes/HTML-Toc-0.91/t/podExamples.t
new file mode 100644 (file)
index 0000000..6a546e6
--- /dev/null
@@ -0,0 +1,709 @@
+#--- podExamples.t ------------------------------------------------------------
+# function: Test HTML::ToC.  In particular test the examples as described in 
+#           the POD documentation.
+
+use strict;
+use Test;
+
+BEGIN { plan tests => 13; }
+
+use HTML::Toc;
+use HTML::TocGenerator;
+use HTML::TocInsertor;
+use HTML::TocUpdator;
+
+my ($filename, $filename2);
+       
+
+BEGIN {
+               # Create test file
+       $filename = "tmp.htm";
+       die "$filename is already there" if -e $filename;
+               # Create test file 2
+       $filename2 = "tmp2.htm";
+       die "$filename2 is already there" if -e $filename2;
+}
+
+
+END {
+               # Remove test file
+       unlink($filename) or warn "Can't unlink $filename: $!";
+               # Remove test file 2
+       unlink($filename2) or warn "Can't unlink $filename2: $!";
+}
+
+
+#--- TestExtendFromFile() --------------------------------------------------
+# function: Test 'HTML::TocGenerator->extendFromFile()
+
+sub TestExtendFromFile {
+               # Assemble test file
+       open(FILE, ">$filename") || die "Can't create $filename: $!";
+       print FILE <<'EOT'; close(FILE);
+<body>
+   <h1>Chapter of document 1</h1>
+</body>
+EOT
+
+               # Assemble test file 2
+       open(FILE, ">$filename2") || die "Can't create $filename2: $!";
+       print FILE <<'EOT'; close(FILE);
+<html>
+<body>
+   <h1>Chapter of document 2</h1>
+</body>
+</html>
+EOT
+
+               # Create objects
+       my $toc          = HTML::Toc->new();
+       my $tocGenerator = HTML::TocGenerator->new();
+       
+               # Set ToC options
+   $toc->setOptions({'doLinkToFile' => 1});
+               # Generate ToC
+       $tocGenerator->generateFromFile($toc, $filename);
+       $tocGenerator->extendFromFile($toc, $filename2);
+               # Test ToC
+       ok($toc->format(), <<EOT);
+
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul>
+   <li><a href=tmp.htm#h-1>Chapter of document 1</a>
+   <li><a href=tmp2.htm#h-2>Chapter of document 2</a>
+</ul>
+<!-- End of generated Table of Contents -->
+EOT
+}  # TestExtendFromFile()
+
+
+#--- TestGenerateFromFiles() --------------------------------------------------
+# function: Test 'HTML::TocGenerator->generateFromFile()
+
+sub TestGenerateFromFiles {
+               # Assemble test file
+       open(FILE, ">$filename") || die "Can't create $filename: $!";
+       print FILE <<'EOT'; close(FILE);
+<body>
+   <h1>Chapter of document 1</h1>
+</body>
+EOT
+
+               # Assemble test file 2
+       open(FILE, ">$filename2") || die "Can't create $filename2: $!";
+       print FILE <<'EOT'; close(FILE);
+<html>
+<body>
+   <h1>Chapter of document 2</h1>
+</body>
+</html>
+EOT
+
+               # Create objects
+       my $toc          = HTML::Toc->new();
+       my $tocGenerator = HTML::TocGenerator->new();
+       
+               # Set ToC options
+   $toc->setOptions({'doLinkToFile' => 1});
+               # Generate ToC
+       $tocGenerator->generateFromFile($toc, [$filename, $filename2]);
+               # Test ToC
+       ok($toc->format(), <<EOT);
+
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul>
+   <li><a href=tmp.htm#h-1>Chapter of document 1</a>
+   <li><a href=tmp2.htm#h-2>Chapter of document 2</a>
+</ul>
+<!-- End of generated Table of Contents -->
+EOT
+}  # TestGenerateFromFiles()
+
+
+#--- TestGenerateFromFiles() --------------------------------------------------
+# function: Test 'HTML::TocGenerator->generateFromFile() using multiple files.
+
+sub TestGenerateFromFile {
+               # Assemble test file 1
+       open(FILE, ">$filename") || die "Can't create $filename: $!";
+       print FILE <<'EOT'; close(FILE);
+<html>
+<body>
+   <h1>Chapter</h1>
+</body>
+</html>
+EOT
+
+               # Create objects
+       my $toc          = HTML::Toc->new();
+       my $tocGenerator = HTML::TocGenerator->new();
+       
+               # Generate ToC
+       $tocGenerator->generateFromFile($toc, $filename);
+               # Test ToC
+       ok($toc->format(), <<EOT);
+
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul>
+   <li><a href=#h-1>Chapter</a>
+</ul>
+<!-- End of generated Table of Contents -->
+EOT
+}  # TestGenerateFromFile()
+
+
+#--- TestInsertIntoFile() -----------------------------------------------------
+# function: Test 'HTML::TocInsertor->insertIntoFile()
+
+sub TestInsertIntoFile {
+               # Assemble test file
+       open(FILE, ">$filename") || die "Can't create $filename: $!";
+       print FILE <<'EOT'; close(FILE);
+<html>
+<body>
+   <h1>Chapter</h1>
+</body>
+</html>
+EOT
+
+               # Create objects
+       my $toc         = HTML::Toc->new();
+       my $tocInsertor = HTML::TocInsertor->new();
+       my $output;
+       
+               # Generate ToC
+       $tocInsertor->insertIntoFile($toc, $filename, {'output' => \$output});
+               # Test ToC
+       ok($output, <<EOT);
+<html>
+<body>
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul>
+   <li><a href=#h-1>Chapter</a>
+</ul>
+<!-- End of generated Table of Contents -->
+
+   <a name=h-1><h1>Chapter</h1></a>
+</body>
+</html>
+EOT
+}  # TestInsertIntoFile()
+
+
+#--- TestInsertIntoFileUsingTocUpdator() --------------------------------------
+# function: Test 'HTML::TocUpdator->insertIntoFile()
+
+sub TestInsertIntoFileUsingTocUpdator {
+               # Assemble test file
+       open(FILE, ">$filename") || die "Can't create $filename: $!";
+       print FILE <<'EOT'; close(FILE);
+<html>
+<body>
+   <h1>
+   Chapter
+   </h1>
+</body>
+</html>
+EOT
+
+               # Create objects
+       my $toc        = HTML::Toc->new();
+       my $tocUpdator = HTML::TocUpdator->new();
+       my $output;
+       
+               # Generate ToC
+       $tocUpdator->insertIntoFile($toc, $filename, {'output' => \$output});
+               # Test ToC
+       ok($output, <<EOT);
+<html>
+<body><!-- #BeginToc -->
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul>
+   <li><a href=#h-1> Chapter </a>
+</ul>
+<!-- End of generated Table of Contents -->
+<!-- #EndToc -->
+   <!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1>
+   Chapter
+   </h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+</body>
+</html>
+EOT
+}  # TestInsertIntoFileUsingTocUpdator()
+
+
+#--- TestGlobalGroups0() ------------------------------------------------------
+# function: Test 'HTML::TocGenerator' option 'doUseGroupsGlobal = 0'.
+
+sub TestGlobalGroups0 {
+               # Assemble test file
+       open(FILE, ">$filename") || die "Can't create $filename: $!";
+       print FILE <<'EOT'; close(FILE);
+<h1>Chapter</h1>
+<h2>Paragraph</h2>
+EOT
+
+               # Create objects
+       my $toc1         = HTML::Toc->new();
+       my $toc2         = HTML::Toc->new();
+       my $tocGenerator = HTML::TocGenerator->new();
+
+               # Set options
+       $toc1->setOptions({
+               'header'      => '',
+               'footer'      => '',
+               'tokenToToc' => [{'tokenBegin' => '<h1>'}]
+       });
+       $toc2->setOptions({
+               'header'      => '',
+               'footer'      => '',
+               'tokenToToc' => [{'tokenBegin' => '<h2>'}]
+       });
+               # Generate ToC
+       $tocGenerator->generateFromFile([$toc1, $toc2], $filename);
+               # Test ToC
+       ok($toc1->format() . $toc2->format() . "\n", <<'EOT');
+<ul>
+   <li><a href=#h-1>Chapter</a>
+</ul><ul>
+   <li><a href=#h-1>Paragraph</a>
+</ul>
+EOT
+}      # TestGlobalGroups0()
+
+
+#--- TestGlobalGroups1() ------------------------------------------------------
+# function: Test 'HTML::TocGenerator' option 'doUseGroupsGlobal = 0'.
+
+sub TestGlobalGroups1 {
+               # Assemble test file
+       open(FILE, ">$filename") || die "Can't create $filename: $!";
+       print FILE <<'EOT';
+<h1>Chapter</h1>
+<h2>Paragraph</h2>
+EOT
+       close(FILE);
+
+               # Create objects
+       my $toc1         = HTML::Toc->new();
+       my $toc2         = HTML::Toc->new();
+       my $tocGenerator = HTML::TocGenerator->new();
+
+               # Set options
+       $toc1->setOptions({
+               'header'      => '',
+               'footer'      => '',
+               'tokenToToc' => [{'tokenBegin' => '<h1>'}]
+       });
+       $toc2->setOptions({
+               'header'      => '',
+               'footer'      => '',
+               'tokenToToc' => [{'tokenBegin' => '<h2>'}]
+       });
+               # Generate ToC
+       $tocGenerator->generateFromFile(
+               [$toc1, $toc2], $filename, {'doUseGroupsGlobal' => 1}
+       );
+               # Test ToC
+       ok($toc1->format() . $toc2->format() . "\n", <<'EOT');
+<ul>
+   <li><a href=#h-1>Chapter</a>
+</ul><ul>
+   <li><a href=#h-2>Paragraph</a>
+</ul>
+EOT
+}      # TestGlobalGroups1()
+
+
+#--- TestMultipleGroupsAppendix() ---------------------------------------------
+# function: Test multiple ToCs
+
+sub TestMultipleGroupsAppendix() {
+               # Create objects
+       my $toc         = HTML::Toc->new();
+       my $tocInsertor = HTML::TocInsertor->new();
+       my $output;
+       
+               # Set ToC options
+       $toc->setOptions({
+               'tokenToToc' => [{
+                               'tokenBegin' => '<h1 class=-appendix>'
+                       }, {
+                               'tokenBegin' => '<h2 class=-appendix>',
+                               'level'      => 2
+                       }, {
+                               'groupId'    => 'appendix',
+                               'tokenBegin' => '<h1 class=appendix>',
+                       }, {
+                               'groupId'    => 'appendix',
+                               'tokenBegin' => '<h2 class=appendix>',
+                               'level'      => 2
+                       }],
+       });
+               # Generate ToC
+       $tocInsertor->insert($toc, <<EOT, {'output' => \$output});
+<body>
+   <h1>Chapter</h1>
+   <h2>Paragraph</h2>
+   <h3>Subparagraph</h3>
+   <h1>Chapter</h1>
+   <h1 class=appendix>Appendix Chapter</h1>
+   <h2 class=appendix>Appendix Paragraph</h2>
+</body>
+EOT
+               # Test ToC
+       ok($output, <<EOT);
+<body>
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul>
+   <li><a href=#h-1>Chapter</a>
+   <ul>
+      <li><a href=#h-1.1>Paragraph</a>
+   </ul>
+   <li><a href=#h-2>Chapter</a>
+</ul>
+<ul>
+   <li><a href=#appendix-1>Appendix Chapter</a>
+   <ul>
+      <li><a href=#appendix-1.1>Appendix Paragraph</a>
+   </ul>
+</ul>
+<!-- End of generated Table of Contents -->
+
+   <a name=h-1><h1>Chapter</h1></a>
+   <a name=h-1.1><h2>Paragraph</h2></a>
+   <h3>Subparagraph</h3>
+   <a name=h-2><h1>Chapter</h1></a>
+   <a name=appendix-1><h1 class=appendix>Appendix Chapter</h1></a>
+   <a name=appendix-1.1><h2 class=appendix>Appendix Paragraph</h2></a>
+</body>
+EOT
+}  # TestMultipleGroupsAppendix()
+
+
+#--- TestMultipleGroupsPart() -------------------------------------------------
+# function: Test multiple ToCs
+
+sub TestMultipleGroupsPart() {
+               # Create objects
+       my $toc         = HTML::Toc->new();
+       my $tocInsertor = HTML::TocInsertor->new();
+       my $output;
+       
+               # Set ToC options
+       $toc->setOptions({
+               'tokenToToc' => [{
+                               'tokenBegin' => '<h1 class=-part>'
+                       }, {
+                               'tokenBegin' => '<h2 class=-part>',
+                               'level'      => 2,
+                       }, {
+                               'groupId'        => 'part',
+                               'tokenBegin'     => '<h1 class=part>',
+                               'level'          => 1,
+                               'doNumberToken'  => 1,
+                               'numberingStyle' => 'upper-alpha'
+                       }]
+       });
+               # Generate ToC
+       $tocInsertor->insert($toc, <<EOT, {'output' => \$output});
+<body>
+   <h1 class=part>First Part</h1>
+   <h1>Chapter</h1>
+   <h2>Paragraph</h2>
+   <h1 class=part>Second Part</h1>
+   <h1>Chapter</h1>
+   <h2>Paragraph</h2>
+</body>
+EOT
+               # Test ToC
+       ok($output, <<EOT);
+<body>
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul>
+   <li><a href=#part-A>First Part</a>
+</ul>
+<ul>
+   <li><a href=#h-1>Chapter</a>
+   <ul>
+      <li><a href=#h-1.1>Paragraph</a>
+   </ul>
+</ul>
+<ul>
+   <li><a href=#part-B>Second Part</a>
+</ul>
+<ul>
+   <li><a href=#h-2>Chapter</a>
+   <ul>
+      <li><a href=#h-2.1>Paragraph</a>
+   </ul>
+</ul>
+<!-- End of generated Table of Contents -->
+
+   <a name=part-A><h1 class=part>A &nbsp;First Part</h1></a>
+   <a name=h-1><h1>Chapter</h1></a>
+   <a name=h-1.1><h2>Paragraph</h2></a>
+   <a name=part-B><h1 class=part>B &nbsp;Second Part</h1></a>
+   <a name=h-2><h1>Chapter</h1></a>
+   <a name=h-2.1><h2>Paragraph</h2></a>
+</body>
+EOT
+}  # TestMultipleGroupsPart()
+
+
+#--- TestMultipleTocs() -------------------------------------------------------
+# function: Test multiple ToCs
+
+sub TestMultipleTocs() {
+               # Assemble test file
+       open(FILE, ">$filename") || die "Can't create $filename: $!";
+       print FILE <<'EOT'; close(FILE);
+<body>
+   <h1>Header One</h1>
+   <img src=test1.gif alt="First picture">
+   <h2>Paragraph One</h2>
+   <img src=test2.gif alt="Second picture">
+</body>
+EOT
+
+               # Create objects
+       my $toc1        = HTML::Toc->new();
+       my $toc2        = HTML::Toc->new();
+       my $tocInsertor = HTML::TocInsertor->new();
+       my $output;
+       
+               # Set ToC options
+       $toc2->setOptions({
+               'tokenToToc'             => [{
+                       'groupId'    => 'image',
+                       'tokenBegin' => '<img alt=@>'
+               }],
+       });
+               # Generate ToC
+       $tocInsertor->insertIntoFile(
+               [$toc1, $toc2], $filename, {'output' => \$output}
+       );
+               # Test ToC
+       ok($output, <<EOT);
+<body>
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul>
+   <li><a href=#h-1>Header One</a>
+   <ul>
+      <li><a href=#h-1.1>Paragraph One</a>
+   </ul>
+</ul>
+<!-- End of generated Table of Contents -->
+
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul>
+   <li><a href=#image-1>First picture</a>
+   <li><a href=#image-2>Second picture</a>
+</ul>
+<!-- End of generated Table of Contents -->
+
+   <a name=h-1><h1>Header One</h1></a>
+   <a name=image-1><img src=test1.gif alt="First picture"></a>
+   <a name=h-1.1><h2>Paragraph One</h2></a>
+   <a name=image-2><img src=test2.gif alt="Second picture"></a>
+</body>
+EOT
+}  # TestMultipleTocs()
+
+
+#--- TestSpecifyNumberedList() ------------------------------------------------
+# function: Test specifying numbered list.
+
+sub TestSpecifyNumberedList {
+               # Assemble test file
+       open(FILE, ">$filename") || die "Can't create $filename: $!";
+       print FILE <<'EOT'; close(FILE);
+<body>
+   <h1>Chapter</h1>
+       <h2>Paragraph</h2>
+</body>
+EOT
+
+               # Create objects
+       my $toc        = HTML::Toc->new();
+   my $tocGenerator = HTML::TocGenerator->new();
+       
+               # Set ToC options
+       $toc->setOptions({
+               'templateLevelBegin' => '"<ol>\n"',
+               'templateLevelEnd'   => '"</ol>\n"',
+       });
+               # Generate ToC
+       $tocGenerator->generateFromFile($toc, $filename);
+               # Test ToC
+       ok($toc->format(), <<EOT);
+
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ol>
+   <li><a href=#h-1>Chapter</a>
+   <ol>
+      <li><a href=#h-1.1>Paragraph</a>
+   </ol>
+</ol>
+<!-- End of generated Table of Contents -->
+EOT
+}  # TestSpecifyNumberedList()
+
+
+#--- TestUpdateFile() ---------------------------------------------------------
+# function: Test 'HTML::TocUpdator->updateFile()'
+
+sub TestUpdateFile {
+               # Assemble test file
+       open(FILE, ">$filename") || die "Can't create $filename: $!";
+       print FILE <<'EOT'; close(FILE);
+<html>
+<body><!-- #BeginToc -->
+foo
+<!-- #EndToc -->
+   <!-- #BeginTocAnchorNameBegin -->bar<!-- #EndTocAnchorNameBegin --><h1>
+   Chapter
+   </h1><!-- #BeginTocAnchorNameEnd -->foo<!-- #EndTocAnchorNameEnd -->
+</body>
+</html>
+EOT
+
+               # Create objects
+       my $toc        = HTML::Toc->new();
+       my $tocUpdator = HTML::TocUpdator->new();
+       my $output;
+       
+               # Generate ToC
+       $tocUpdator->updateFile($toc, $filename, {'output' => \$output});
+               # Test ToC
+       ok($output, <<EOT);
+<html>
+<body><!-- #BeginToc -->
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul>
+   <li><a href=#h-1> Chapter </a>
+</ul>
+<!-- End of generated Table of Contents -->
+<!-- #EndToc -->
+   <!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1>
+   Chapter
+   </h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+</body>
+</html>
+EOT
+}  # TestUpdateFile()
+
+
+#--- TestUsingCSS() -----------------------------------------------------------
+# function: Test multiple ToCs
+
+sub TestUsingCSS() {
+
+               # Create objects
+       my $toc          = new HTML::Toc;
+       my $tocInsertor  = new HTML::TocInsertor;
+       my $output;
+
+   $toc->setOptions({
+               'templateLevelBegin'   => '"<ol class=toc_$groupId$level>\n"',
+               'templateLevelEnd'     => '"</ol>\n"',
+               'doNumberToken'        => 1,
+      'tokenToToc' => [{
+                               'groupId'        => 'appendix',
+            'tokenBegin'     => '<h1>',
+                               'numberingStyle' => 'upper-alpha'
+                       }, {
+                               'groupId'        => 'appendix',
+            'tokenBegin'         => '<h2>',
+            'level'              => 2,
+         }]
+   });
+       $tocInsertor->insert($toc, <<EOT);
+<html>
+<head>
+   <style type="text/css">
+      ol.toc_appendix1 { list-style-type: upper-alpha }
+   </style>
+</head>
+<body>
+   <h1>Appendix</h1>
+   <h2>Appendix Paragraph</h2>
+   <h1>Appendix</h1>
+   <h2>Appendix Paragraph</h2>
+</body>
+</html>
+EOT
+               # Insert ToC
+       $tocInsertor->insert($toc, <<EOT, {'output' => \$output});
+<html>
+<head>
+   <style type="text/css">
+      ol.toc_appendix1 { list-style-type: upper-alpha }
+   </style>
+</head>
+<body>
+   <h1>Appendix</h1>
+   <h2>Appendix Paragraph</h2>
+   <h1>Appendix</h1>
+   <h2>Appendix Paragraph</h2>
+</body>
+</html>
+EOT
+               # Test ToC
+       ok($output, <<EOT);
+<html>
+<head>
+   <style type="text/css">
+      ol.toc_appendix1 { list-style-type: upper-alpha }
+   </style>
+</head>
+<body>
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ol class=toc_appendix1>
+   <li><a href=#appendix-A>Appendix</a>
+   <ol class=toc_appendix2>
+      <li><a href=#appendix-A.1>Appendix Paragraph</a>
+   </ol>
+   <li><a href=#appendix-B>Appendix</a>
+   <ol class=toc_appendix2>
+      <li><a href=#appendix-B.1>Appendix Paragraph</a>
+   </ol>
+</ol>
+<!-- End of generated Table of Contents -->
+
+   <a name=appendix-A><h1>A &nbsp;Appendix</h1></a>
+   <a name=appendix-A.1><h2>A.1 &nbsp;Appendix Paragraph</h2></a>
+   <a name=appendix-B><h1>B &nbsp;Appendix</h1></a>
+   <a name=appendix-B.1><h2>B.1 &nbsp;Appendix Paragraph</h2></a>
+</body>
+</html>
+EOT
+}  # TestUsingCSS()
+
+
+       # Test 'extendFromFile()'
+TestExtendFromFile();
+       # Test 'generateFromFile()'
+TestGenerateFromFile();
+       # Test 'generateFromFiles()'
+TestGenerateFromFiles();
+       # Test 'doUseGroupsGlobal = 0'
+TestGlobalGroups0();
+       # Test 'doUseGroupsGlobal = 1'
+TestGlobalGroups1();
+       # Test 'tocInsertor->insertIntoFile'
+TestInsertIntoFile();
+       # Test 'tocUpdator->insertIntoFile'
+TestInsertIntoFileUsingTocUpdator();
+       # Test additional 'appendix' group
+TestMultipleGroupsAppendix();
+       # Test additional 'part' group
+TestMultipleGroupsPart();
+       # Test multiple ToCs
+TestMultipleTocs();
+       # Test specifying numbered list
+TestSpecifyNumberedList();
+       # Test 'updateFile()'
+TestUpdateFile();
+       # Test using CSS
+TestUsingCSS();
diff --git a/examples/includes/HTML-Toc-0.91/t/propagate.t b/examples/includes/HTML-Toc-0.91/t/propagate.t
new file mode 100644 (file)
index 0000000..63de18d
--- /dev/null
@@ -0,0 +1,176 @@
+#--- propagate.t --------------------------------------------------------------
+# function: Test ToC propagation.
+
+use strict;
+use Test;
+
+BEGIN { plan tests => 10; }
+
+use HTML::Toc;
+use HTML::TocGenerator;
+use HTML::TocInsertor;
+
+my ($output, $content, $filename);
+my $toc          = HTML::Toc->new;
+my $tocGenerator = HTML::TocGenerator->new;
+my $tocInsertor  = HTML::TocInsertor->new;
+
+$toc->setOptions({
+       'doLinkToToken'  => 0,
+       'levelIndent'    => 0,
+       'insertionPoint' => 'before <h1>',
+       'header'         => '',
+       'footer'         => '',
+});
+
+
+BEGIN {
+               # Create test file
+       $filename = "file$$.htm";
+       die "$filename is already there" if -e $filename;
+       open(FILE, ">$filename") || die "Can't create $filename: $!";
+       print FILE <<'EOT'; close(FILE);
+<h1>Header</h1>
+EOT
+}
+
+
+END {
+               # Remove test file
+       unlink($filename) or warn "Can't unlink $filename: $!";
+}
+
+
+#--- 1. propagate -------------------------------------------------------------
+
+$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
+ok($output, "<ul>\n<li>Header\n</ul><h1>Header</h1>");
+
+
+#--- 2. propagateFile ---------------------------------------------------------
+
+$tocInsertor->insertIntoFile($toc, $filename, {'output' => \$output});
+ok($output, "<ul>\n<li>Header\n</ul><h1>Header</h1>\n");
+
+
+#--- 3. doLinkToToken -----------------------------------------------------
+
+$toc->setOptions({'doLinkToToken' => 1});
+$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
+ok("$output\n", <<'EOT');
+<ul>
+<li><a href=#h-1>Header</a>
+</ul><a name=h-1><h1>Header</h1></a>
+EOT
+
+
+#--- 4. templateAnchorHrefBegin -----------------------------------------------
+
+$toc->setOptions(
+       {'templateAnchorHrefBegin' => '"<$node${file}test${groupId}>"'}
+);
+$tocInsertor->insertIntoFile($toc, $filename, {'output' => \$output});
+ok($output, "<ul>\n<li><1${filename}testh>Header</a>\n</ul><a name=h-1><h1>Header</h1></a>\n");
+$toc->setOptions({'templateAnchorHrefBegin' => undef});
+
+
+#--- 5. templateAnchorNameBegin -----------------------------------------------
+
+$toc->setOptions({
+       'templateAnchorName'      => '"$node$groupId"',
+       'templateAnchorNameBegin' => '"<$anchorName>"'
+});
+$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
+ok($output, "<ul>\n<li><a href=#1h>Header</a>\n</ul><1h><h1>Header</h1></a>");
+$toc->setOptions({'templateAnchorName' => undef});
+
+
+#--- 6. templateAnchorName function -------------------------------------------
+
+sub AssembleAnchorName {
+               # Get arguments
+       my ($aFile, $aGroupId, $aLevel, $aNode) = @_;
+               # Return value
+       return $aFile . $aGroupId . $aLevel . $aNode;
+}  # AssembleAnchorName()
+
+       # Set options
+$toc->setOptions({'templateAnchorNameBegin' => \&AssembleAnchorName});
+       # Propagate ToC
+$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
+       # Test ToC
+ok($output, "<ul>\n<li><a href=#h-1>Header</a>\n</ul>h11<h1>Header</h1></a>");
+       # Restore options
+$toc->setOptions({'templateAnchorNameBegin' => undef});
+
+
+#--- 7. doNumberToken --------------------------------------------------------
+
+       # Set options
+$toc->setOptions({'doNumberToken' => 1});
+$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
+ok("$output\n", <<'EOT');
+<ul>
+<li><a href=#h-1>Header</a>
+</ul><a name=h-1><h1>1 &nbsp;Header</h1></a>
+EOT
+       # Reset options
+$toc->setOptions({
+       'templateTokenNumber' => undef,
+       'doNumberToken'      => 0
+});
+
+
+#--- 8. templateTokenNumber ---------------------------------------------------
+
+       # Set options
+$toc->setOptions({
+       'templateTokenNumber' => '"-$node-"',
+       'doNumberToken'      => 1
+});
+       # Propagate ToC
+$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
+       # Test ToC
+ok("$output\n", <<'EOT');
+<ul>
+<li><a href=#h-1>Header</a>
+</ul><a name=h-1><h1>-1-Header</h1></a>
+EOT
+       # Reset options
+$toc->setOptions({
+       'doNumberToken'      => 0,
+       'templateTokenNumber' => undef
+});
+
+
+#--- 9. numberingStyle --------------------------------------------------------
+
+       # Set options
+$toc->setOptions({
+       'doNumberToken' => 1,
+       'tokenToToc' => [{
+               'level' => 1,
+               'tokenBegin' => '<h1>',
+               'numberingStyle' => 'lower-alpha'
+       }]
+});
+       # Propagate ToC
+$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
+       # Test ToC
+ok("$output\n", <<'EOT');
+<ul>
+<li><a href=#h-a>Header</a>
+</ul><a name=h-a><h1>a &nbsp;Header</h1></a>
+EOT
+       # Reset options
+$toc->setOptions({
+       'doNumberToken' => 0,
+       'tokenToToc' => undef,
+});
+
+
+#--- 10. declaration pass through ---------------------------------------------
+
+$tocInsertor->insert($toc, '<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><h1>Header</h1>', {'output' => \$output});
+       # Test ToC
+ok($output, '<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><h1>Header</h1>');
diff --git a/examples/includes/HTML-Toc-0.91/t/siteMap.t b/examples/includes/HTML-Toc-0.91/t/siteMap.t
new file mode 100644 (file)
index 0000000..074f0bd
--- /dev/null
@@ -0,0 +1,97 @@
+#--- manual.t -----------------------------------------------------------------
+# function: Test HTML::ToC generating a manual.
+
+use strict;
+use Test;
+
+BEGIN { plan tests => 1; }
+
+use Data::Dumper;
+use File::Find;
+use HTML::Toc;
+use HTML::TocGenerator;
+use HTML::TocInsertor;
+use HTML::TocUpdator;
+
+
+       # Create objects
+my $toc          = HTML::Toc->new();
+my $tocGenerator = HTML::TocGenerator->new();
+my @fileList;
+
+
+#--- TestSiteMap() ------------------------------------------------------------
+# function: Test specifying numbered list.
+
+sub TestSiteMap {
+               # Set ToC options
+       $toc->setOptions({
+               'doLinkToFile'       => 1,
+               'templateAnchorName' => '""',
+               'templateAnchorHref' => '"<a href=$file"."#".$groupId.$level.">"',
+               'doLinkTocToToken'   => 1,
+               'tokenToToc'         => [{
+                       'groupId'         => 'dir',
+                       'level'           => 1,
+                       'tokenBegin'      => '<title>',
+                       'tokenEnd'        => '</title>',
+                       'fileSpec'        => '\./[^/]+$'
+               }, {
+                       'groupId'         => 'dir',
+                       'level'           => 2,
+                       'tokenBegin'      => '<title>',
+                       'tokenEnd'        => '</title>',
+                       'fileSpec'        => '\./[^/]+?/[^/]+$'
+               }, {
+                       'groupId'         => 'dir',
+                       'level'           => 3,
+                       'tokenBegin'      => '<title>',
+                       'tokenEnd'        => '</title>',
+                       'fileSpec'        => '\./[^/]+?/[^/]+?/[^/]+$'
+               }]
+       });
+               # Change current directory
+       chdir("t/SiteMap");
+               # Find files, filling 'fileList'
+       find({wanted => \&WantedSiteMap, no_chdir => 1}, '.');
+               # Generate ToC of case-insensitively sorted file list
+       $tocGenerator->extendFromFile(
+               $toc, [sort {uc($a) cmp uc($b)} @fileList]
+       );
+               # Restore current directory
+       chdir("../..");
+               # Test ToC
+       ok($toc->format(), <<EOT);
+
+<!-- Table of Contents generated by Perl - HTML::Toc -->
+<ul>
+   <li><a href=./index.htm#>Main</a>
+   <ul>
+      <li><a href=./SubDir1/index.htm#>Sub1</a>
+      <ul>
+         <li><a href=./SubDir1/SubSubDir1/index.htm#>SubSub1</a>
+      </ul>
+      <li><a href=./SubDir2/index.htm#>Sub2</a>
+      <ul>
+         <li><a href=./SubDir2/SubSubDir1/index.htm#>SubSub1</a>
+         <li><a href=./SubDir2/SubSubDir2/index.htm#>SubSub2</a>
+      </ul>
+      <li><a href=./SubDir3/index.htm#>Sub3</a>
+   </ul>
+</ul>
+<!-- End of generated Table of Contents -->
+EOT
+}  # TestSiteMap()
+
+
+#--- WantedSiteMap() ----------------------------------------------------------
+# function: 'Wanted' function, used by File::Find of 'TestSiteMap()'.
+
+sub WantedSiteMap {
+               # Add file to 'fileList' if extension matches '.htm'
+       push (@fileList, $File::Find::name) if (m/\.htm$/);
+} # WantedSiteMap()
+
+
+       # Test site map
+TestSiteMap();
diff --git a/examples/includes/HTML-Toc-0.91/t/update.t b/examples/includes/HTML-Toc-0.91/t/update.t
new file mode 100644 (file)
index 0000000..e4777b6
--- /dev/null
@@ -0,0 +1,114 @@
+#--- update.t -----------------------------------------------------------------
+# function: Test ToC updating.
+
+use strict;
+use Test;
+
+BEGIN { plan tests => 6; }
+
+use HTML::Toc;
+use HTML::TocUpdator;
+
+my ($output, $output2, $content, $filename);
+my $toc         = HTML::Toc->new;
+my $tocUpdator  = HTML::TocUpdator->new;
+
+$toc->setOptions({
+       'doLinkToToken'  => 1,
+       'doNumberToken'  => 1,
+       'levelIndent'    => 0,
+       'insertionPoint' => 'before <h1>',
+       'header'         => '',
+       'footer'         => '',
+});
+
+
+BEGIN {
+               # Create test file
+       $filename = "file$$.htm";
+       die "$filename is already there" if -e $filename;
+       open(FILE, ">$filename") || die "Can't create $filename: $!";
+       print FILE <<'EOT'; close(FILE);
+<h1>Header</h1>
+EOT
+}
+
+
+END {
+               # Remove test file
+       unlink($filename) or warn "Can't unlink $filename: $!";
+}
+
+
+#--- 1. update ----------------------------------------------------------------
+
+$tocUpdator->update($toc, "<h1>Header</h1>", {'output' => \$output});
+ok("$output\n", <<'EOT');
+<!-- #BeginToc --><ul>
+<li><a href=#h-1>Header</a>
+</ul><!-- #EndToc --><!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Header</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+EOT
+
+#--- 2. updateFile ------------------------------------------------------------
+
+$tocUpdator->updateFile($toc, $filename, {'output' => \$output});
+       open(FILE, ">a.out1") || die "Can't create a.out1: $!";
+       print FILE $output; close(FILE);
+$output2 = <<'EOT';
+<!-- #BeginToc --><ul>
+<li><a href=#h-1>Header</a>
+</ul><!-- #EndToc --><!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Header</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+EOT
+       open(FILE, ">a.out2") || die "Can't create a.out2: $!";
+       print FILE $output2; close(FILE);
+ok($output, $output2);
+
+
+#--- 3. insert ----------------------------------------------------------------
+
+$tocUpdator->insert($toc, "<h1>Header</h1>", {'output' => \$output});
+ok("$output\n", <<'EOT');
+<!-- #BeginToc --><ul>
+<li><a href=#h-1>Header</a>
+</ul><!-- #EndToc --><!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Header</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+EOT
+
+#--- 4. insertIntoFile --------------------------------------------------------
+
+$tocUpdator->insertIntoFile($toc, $filename, {'output' => \$output});
+ok($output, <<'EOT');
+<!-- #BeginToc --><ul>
+<li><a href=#h-1>Header</a>
+</ul><!-- #EndToc --><!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Header</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+EOT
+
+
+#--- 5. update twice ----------------------------------------------------------
+
+$tocUpdator->update($toc, "<h1>Header</h1>", {'output' => \$output});
+$tocUpdator->update($toc, $output, {'output' => \$output2});
+ok("$output\n", <<'EOT');
+<!-- #BeginToc --><ul>
+<li><a href=#h-1>Header</a>
+</ul><!-- #EndToc --><!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Header</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
+EOT
+
+
+#--- 6. tokens update begin & end ---------------------------------------------
+
+$toc->setOptions({
+       'tokenUpdateBeginOfAnchorNameBegin' => '<tocAnchorNameBegin>',
+       'tokenUpdateEndOfAnchorNameBegin'   => '</tocAnchorNameBegin>',
+       'tokenUpdateBeginOfAnchorNameEnd'   => '<tocAnchorNameEnd>',
+       'tokenUpdateEndOfAnchorNameEnd'     => '</tocAnchorNameEnd>',
+       'tokenUpdateBeginNumber'            => '<tocNumber>',
+       'tokenUpdateEndNumber'              => '</tocNumber>',
+       'tokenUpdateBeginToc'               => '<toc>',
+       'tokenUpdateEndToc',                => '</toc>'
+});
+$tocUpdator->update($toc, "<h1>Header</h1>", {'output' => \$output});
+ok("$output\n", <<'EOT');
+<toc><ul>
+<li><a href=#h-1>Header</a>
+</ul></toc><tocAnchorNameBegin><a name=h-1></tocAnchorNameBegin><h1><tocNumber>1 &nbsp;</tocNumber>Header</h1><tocAnchorNameEnd></a></tocAnchorNameEnd>
+EOT
diff --git a/examples/includes/PHP-Markdown-Extra-1.2.3/License.text b/examples/includes/PHP-Markdown-Extra-1.2.3/License.text
new file mode 100644 (file)
index 0000000..52c868b
--- /dev/null
@@ -0,0 +1,36 @@
+PHP Markdown & Extra
+Copyright (c) 2004-2008 Michel Fortin  
+<http://www.michelf.com/>  
+All rights reserved.
+
+Based on Markdown  
+Copyright (c) 2003-2006 John Gruber   
+<http://daringfireball.net/>   
+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 "Markdown" 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.
diff --git a/examples/includes/PHP-Markdown-Extra-1.2.3/PHP Markdown Extra Readme.text b/examples/includes/PHP-Markdown-Extra-1.2.3/PHP Markdown Extra Readme.text
new file mode 100644 (file)
index 0000000..a1c520e
--- /dev/null
@@ -0,0 +1,731 @@
+PHP Markdown Extra
+==================
+
+Version 1.2.3 - Wed 31 Dec 2008
+
+by Michel Fortin
+<http://www.michelf.com/>
+
+based on Markdown by John Gruber  
+<http://daringfireball.net/>
+
+
+Introduction
+------------
+
+This is a special version of PHP Markdown with extra features. See
+<http://www.michelf.com/projects/php-markdown/extra/> for details.
+
+Markdown is a text-to-HTML conversion tool for web writers. Markdown
+allows you to write using an easy-to-read, easy-to-write plain text
+format, then convert it to structurally valid XHTML (or HTML).
+
+"Markdown" is two things: a plain text markup syntax, and a software 
+tool, written in Perl, that converts the plain text markup to HTML. 
+PHP Markdown is a port to PHP of the original Markdown program by 
+John Gruber.
+
+PHP Markdown can work as a plug-in for WordPress and bBlog, as a 
+modifier for the Smarty templating engine, or as a remplacement for
+textile formatting in any software that support textile.
+
+Full documentation of Markdown's syntax is available on John's 
+Markdown page: <http://daringfireball.net/projects/markdown/>
+
+
+Installation and Requirement
+----------------------------
+
+PHP Markdown requires PHP version 4.0.5 or later.
+
+
+### WordPress ###
+
+PHP Markdown works with [WordPress][wp], version 1.2 or later.
+
+ [wp]: http://wordpress.org/
+
+1.  To use PHP Markdown with WordPress, place the "makrdown.php" file 
+    in the "plugins" folder. This folder is located inside 
+    "wp-content" at the root of your site:
+
+        (site home)/wp-content/plugins/
+
+2.  Activate the plugin with the administrative interface of 
+    WordPress. In the "Plugins" section you will now find Markdown. 
+    To activate the plugin, click on the "Activate" button on the 
+    same line than Markdown. Your entries will now be formatted by 
+    PHP Markdown.
+
+3.  To post Markdown content, you'll first have to disable the 
+       "visual" editor in the User section of WordPress.
+
+You can configure PHP Markdown to not apply to the comments on your 
+WordPress weblog. See the "Configuration" section below.
+
+It is not possible at this time to apply a different set of 
+filters to different entries. All your entries will be formated by 
+PHP Markdown. This is a limitation of WordPress. If your old entries 
+are written in HTML (as opposed to another formatting syntax, like 
+Textile), they'll probably stay fine after installing Markdown.
+
+
+### bBlog ###
+
+PHP Markdown also works with [bBlog][bb].
+
+ [bb]: http://www.bblog.com/
+
+To use PHP Markdown with bBlog, rename "markdown.php" to 
+"modifier.markdown.php" and place the file in the "bBlog_plugins" 
+folder. This folder is located inside the "bblog" directory of 
+your site, like this:
+
+        (site home)/bblog/bBlog_plugins/modifier.markdown.php
+
+Select "Markdown" as the "Entry Modifier" when you post a new 
+entry. This setting will only apply to the entry you are editing.
+
+
+### Replacing Textile in TextPattern ###
+
+[TextPattern][tp] use [Textile][tx] to format your text. You can 
+replace Textile by Markdown in TextPattern without having to change
+any code by using the *Texitle Compatibility Mode*. This may work 
+with other software that expect Textile too.
+
+ [tx]: http://www.textism.com/tools/textile/
+ [tp]: http://www.textpattern.com/
+
+1.  Rename the "markdown.php" file to "classTextile.php". This will
+       make PHP Markdown behave as if it was the actual Textile parser.
+
+2.  Replace the "classTextile.php" file TextPattern installed in your
+       web directory. It can be found in the "lib" directory:
+
+               (site home)/textpattern/lib/
+
+Contrary to Textile, Markdown does not convert quotes to curly ones 
+and does not convert multiple hyphens (`--` and `---`) into en- and 
+em-dashes. If you use PHP Markdown in Textile Compatibility Mode, you 
+can solve this problem by installing the "smartypants.php" file from 
+[PHP SmartyPants][psp] beside the "classTextile.php" file. The Textile 
+Compatibility Mode function will use SmartyPants automatically without 
+further modification.
+
+ [psp]: http://www.michelf.com/projects/php-smartypants/
+
+
+### In Your Own Programs ###
+
+You can use PHP Markdown easily in your current PHP program. Simply 
+include the file and then call the Markdown function on the text you 
+want to convert:
+
+    include_once "markdown.php";
+    $my_html = Markdown($my_text);
+
+If you wish to use PHP Markdown with another text filter function 
+built to parse HTML, you should filter the text *after* the Markdown
+function call. This is an example with [PHP SmartyPants][psp]:
+
+    $my_html = SmartyPants(Markdown($my_text));
+
+
+### With Smarty ###
+
+If your program use the [Smarty][sm] template engine, PHP Markdown 
+can now be used as a modifier for your templates. Rename "markdown.php" 
+to "modifier.markdown.php" and put it in your smarty plugins folder.
+
+  [sm]: http://smarty.php.net/
+
+If you are using MovableType 3.1 or later, the Smarty plugin folder is 
+located at `(MT CGI root)/php/extlib/smarty/plugins`. This will allow 
+Markdown to work on dynamic pages.
+
+
+### Updating Markdown in Other Programs ###
+
+Many web applications now ship with PHP Markdown, or have plugins to 
+perform the conversion to HTML. You can update PHP Markdown -- or 
+replace it with PHP Markdown Extra -- in many of these programs by 
+swapping the old "markdown.php" file for the new one.
+
+Here is a short non-exhaustive list of some programs and where they 
+hide the "markdown.php" file.
+
+| Program   | Path to Markdown
+| -------   | ----------------
+| [Pivot][] | `(site home)/pivot/includes/markdown/`
+
+If you're unsure if you can do this with your application, ask the 
+developer, or wait for the developer to update his application or 
+plugin with the new version of PHP Markdown.
+
+ [Pivot]: http://pivotlog.net/
+
+
+Configuration
+-------------
+
+By default, PHP Markdown produces XHTML output for tags with empty 
+elements. E.g.:
+
+    <br />
+
+Markdown can be configured to produce HTML-style tags; e.g.:
+
+    <br>
+
+To do this, you  must edit the "MARKDOWN_EMPTY_ELEMENT_SUFFIX" 
+definition below the "Global default settings" header at the start of 
+the "markdown.php" file.
+
+
+### WordPress-Specific Settings ###
+
+By default, the Markdown plugin applies to both posts and comments on 
+your WordPress weblog. To deactivate one or the other, edit the 
+`MARKDOWN_WP_POSTS` or `MARKDOWN_WP_COMMENTS` definitions under the 
+"WordPress settings" header at the start of the "markdown.php" file.
+
+
+Bugs
+----
+
+To file bug reports please send email to:
+<michel.fortin@michelf.com>
+
+Please include with your report: (1) the example input; (2) the output you
+expected; (3) the output PHP Markdown actually produced.
+
+
+Version History
+---------------
+
+Extra 1.2.3 (31 Dec 2008):
+
+*      In WordPress pages featuring more than one post, footnote id prefixes are 
+       now automatically applied with the current post ID to avoid clashes
+       between footnotes belonging to different posts.
+
+*      Fix for a bug introduced in Extra 1.2 where block-level HTML tags where 
+       not detected correctly, thus the addition of erroneous `<p>` tags and
+       interpretation of their content as Markdown-formatted instead of
+       HTML-formatted.
+
+
+Extra 1.2.2 (21 Jun 2008):
+
+*      Fixed a problem where abbreviation definitions, footnote
+       definitions and link references were stripped inside
+       fenced code blocks.
+
+*      Fixed a bug where characters such as `"` in abbreviation
+       definitions weren't properly encoded to HTML entities.
+
+*      Fixed a bug where double quotes `"` were not correctly encoded
+       as HTML entities when used inside a footnote reference id.
+
+
+1.0.1m (21 Jun 2008):
+
+*      Lists can now have empty items.
+
+*      Rewrote the emphasis and strong emphasis parser to fix some issues
+       with odly placed and overlong markers.
+
+
+Extra 1.2.1 (27 May 2008):
+
+*      Fixed a problem where Markdown headers and horizontal rules were
+       transformed into their HTML equivalent inside fenced code blocks.
+
+
+Extra 1.2 (11 May 2008):
+
+*      Added fenced code block syntax which don't require indentation
+       and can start and end with blank lines. A fenced code block
+       starts with a line of consecutive tilde (~) and ends on the
+       next line with the same number of consecutive tilde. Here's an
+       example:
+       
+           ~~~~~~~~~~~~
+               Hello World!
+               ~~~~~~~~~~~~
+
+*      Rewrote parts of the HTML block parser to better accomodate
+       fenced code blocks.
+
+*      Footnotes may now be referenced from within another footnote.
+
+*      Added programatically-settable parser property `predef_attr` for 
+       predefined attribute definitions.
+
+*      Fixed an issue where an indented code block preceded by a blank
+       line containing some other whitespace would confuse the HTML 
+       block parser into creating an HTML block when it should have 
+       been code.
+
+
+1.0.1l (11 May 2008):
+
+*      Now removing the UTF-8 BOM at the start of a document, if present.
+
+*      Now accepting capitalized URI schemes (such as HTTP:) in automatic
+       links, such as `<HTTP://EXAMPLE.COM/>`.
+
+*      Fixed a problem where `<hr@example.com>` was seen as a horizontal
+       rule instead of an automatic link.
+
+*      Fixed an issue where some characters in Markdown-generated HTML
+       attributes weren't properly escaped with entities.
+
+*      Fix for code blocks as first element of a list item. Previously,
+       this didn't create any code block for item 2:
+       
+               *   Item 1 (regular paragraph)
+               
+               *       Item 2 (code block)
+
+*      A code block starting on the second line of a document wasn't seen
+       as a code block. This has been fixed.
+       
+*      Added programatically-settable parser properties `predef_urls` and 
+       `predef_titles` for predefined URLs and titles for reference-style 
+       links. To use this, your PHP code must call the parser this way:
+       
+               $parser = new Markdwon_Parser;
+               $parser->predef_urls = array('linkref' => 'http://example.com');
+               $html = $parser->transform($text);
+       
+       You can then use the URL as a normal link reference:
+       
+               [my link][linkref]      
+               [my link][linkRef]
+               
+       Reference names in the parser properties *must* be lowercase.
+       Reference names in the Markdown source may have any case.
+
+*      Added `setup` and `teardown` methods which can be used by subclassers
+       as hook points to arrange the state of some parser variables before and 
+       after parsing.
+
+
+Extra 1.1.7 (26 Sep 2007):
+
+1.0.1k (26 Sep 2007):
+
+*      Fixed a problem introduced in 1.0.1i where three or more identical
+       uppercase letters, as well as a few other symbols, would trigger
+       a horizontal line.
+
+
+Extra 1.1.6 (4 Sep 2007):
+
+1.0.1j (4 Sep 2007):
+
+*      Fixed a problem introduced in 1.0.1i where the closing `code` and 
+       `pre` tags at the end of a code block were appearing in the wrong 
+       order.
+
+*      Overriding configuration settings by defining constants from an 
+       external before markdown.php is included is now possible without 
+       producing a PHP warning.
+
+
+Extra 1.1.5 (31 Aug 2007):
+
+1.0.1i (31 Aug 2007):
+
+*      Fixed a problem where an escaped backslash before a code span 
+       would prevent the code span from being created. This should now
+       work as expected:
+       
+               Litteral backslash: \\`code span`
+
+*      Overall speed improvements, especially with long documents.
+
+
+Extra 1.1.4 (3 Aug 2007):
+
+1.0.1h (3 Aug 2007):
+
+*      Added two properties (`no_markup` and `no_entities`) to the parser 
+       allowing HTML tags and entities to be disabled.
+
+*      Fix for a problem introduced in 1.0.1g where posting comments in 
+       WordPress would trigger PHP warnings and cause some markup to be 
+       incorrectly filtered by the kses filter in WordPress.
+
+
+Extra 1.1.3 (3 Jul 2007):
+
+*      Fixed a performance problem when parsing some invalid HTML as an HTML 
+       block which was resulting in too much recusion and a segmentation fault 
+       for long documents.
+
+*      The markdown="" attribute now accepts unquoted values.
+
+*      Fixed an issue where underscore-emphasis didn't work when applied on the 
+       first or the last word of an element having the markdown="1" or 
+       markdown="span" attribute set unless there was some surrounding whitespace.
+       This didn't work:
+       
+               <p markdown="1">_Hello_ _world_</p>
+       
+       Now it does produce emphasis as expected.
+
+*      Fixed an issue preventing footnotes from working when the parser's 
+       footnote id prefix variable (fn_id_prefix) is not empty.
+
+*      Fixed a performance problem where the regular expression for strong 
+       emphasis introduced in version 1.1 could sometime be long to process, 
+       give slightly wrong results, and in some circumstances could remove 
+       entirely the content for a whole paragraph.
+
+*      Fixed an issue were abbreviations tags could be incorrectly added 
+       inside URLs and title of links.
+
+*      Placing footnote markers inside a link, resulting in two nested links, is 
+       no longer allowed.
+
+
+1.0.1g (3 Jul 2007):
+
+*      Fix for PHP 5 compiled without the mbstring module. Previous fix to 
+       calculate the length of UTF-8 strings in `detab` when `mb_strlen` is 
+       not available was only working with PHP 4.
+
+*      Fixed a problem with WordPress 2.x where full-content posts in RSS feeds 
+       were not processed correctly by Markdown.
+
+*      Now supports URLs containing literal parentheses for inline links 
+       and images, such as:
+
+               [WIMP](http://en.wikipedia.org/wiki/WIMP_(computing))
+
+       Such parentheses may be arbitrarily nested, but must be
+       balanced. Unbalenced parentheses are allowed however when the URL 
+       when escaped or when the URL is enclosed in angle brakets `<>`.
+
+*      Fixed a performance problem where the regular expression for strong 
+       emphasis introduced in version 1.0.1d could sometime be long to process, 
+       give slightly wrong results, and in some circumstances could remove 
+       entirely the content for a whole paragraph.
+
+*      Some change in version 1.0.1d made possible the incorrect nesting of 
+       anchors within each other. This is now fixed.
+
+*      Fixed a rare issue where certain MD5 hashes in the content could
+       be changed to their corresponding text. For instance, this:
+
+               The MD5 value for "+" is "26b17225b626fb9238849fd60eabdf60".
+       
+       was incorrectly changed to this in previous versions of PHP Markdown:
+
+               <p>The MD5 value for "+" is "+".</p>
+
+*      Now convert escaped characters to their numeric character 
+       references equivalent.
+       
+       This fix an integration issue with SmartyPants and backslash escapes. 
+       Since Markdown and SmartyPants have some escapable characters in common, 
+       it was sometime necessary to escape them twice. Previously, two 
+       backslashes were sometime required to prevent Markdown from "eating" the 
+       backslash before SmartyPants sees it:
+       
+               Here are two hyphens: \\--
+       
+       Now, only one backslash will do:
+       
+               Here are two hyphens: \--
+
+
+Extra 1.1.2 (7 Feb 2007)
+
+*      Fixed an issue where headers preceded too closely by a paragraph 
+       (with no blank line separating them) where put inside the paragraph.
+
+*      Added the missing TextileRestricted method that was added to regular
+       PHP Markdown since 1.0.1d but which I forgot to add to Extra.
+
+
+1.0.1f (7 Feb 2007):
+
+*      Fixed an issue with WordPress where manually-entered excerpts, but 
+       not the auto-generated ones, would contain nested paragraphs.
+
+*      Fixed an issue introduced in 1.0.1d where headers and blockquotes 
+       preceded too closely by a paragraph (not separated by a blank line) 
+       where incorrectly put inside the paragraph.
+
+*      Fixed an issue introduced in 1.0.1d in the tokenizeHTML method where 
+       two consecutive code spans would be merged into one when together they 
+       form a valid tag in a multiline paragraph.
+
+*      Fixed an long-prevailing issue where blank lines in code blocks would 
+       be doubled when the code block is in a list item.
+       
+       This was due to the list processing functions relying on artificially 
+       doubled blank lines to correctly determine when list items should 
+       contain block-level content. The list item processing model was thus 
+       changed to avoid the need for double blank lines.
+
+*      Fixed an issue with `<% asp-style %>` instructions used as inline 
+       content where the opening `<` was encoded as `&lt;`.
+
+*      Fixed a parse error occuring when PHP is configured to accept 
+       ASP-style delimiters as boundaries for PHP scripts.
+
+*      Fixed a bug introduced in 1.0.1d where underscores in automatic links
+       got swapped with emphasis tags.
+
+
+Extra 1.1.1 (28 Dec 2006)
+
+*      Fixed a problem where whitespace at the end of the line of an atx-style
+       header would cause tailing `#` to appear as part of the header's content.
+       This was caused by a small error in the regex that handles the definition
+       for the id attribute in PHP Markdown Extra.
+
+*      Fixed a problem where empty abbreviations definitions would eat the 
+       following line as its definition.
+
+*      Fixed an issue with calling the Markdown parser repetitivly with text 
+       containing footnotes. The footnote hashes were not reinitialized properly.
+
+
+1.0.1e (28 Dec 2006)
+
+*      Added support for internationalized domain names for email addresses in 
+       automatic link. Improved the speed at which email addresses are converted 
+       to entities. Thanks to Milian Wolff for his optimisations.
+
+*      Made deterministic the conversion to entities of email addresses in 
+       automatic links. This means that a given email address will always be 
+       encoded the same way.
+
+*      PHP Markdown will now use its own function to calculate the length of an 
+       UTF-8 string in `detab` when `mb_strlen` is not available instead of 
+       giving a fatal error.
+
+
+Extra 1.1 (1 Dec 2006)
+
+*      Added a syntax for footnotes.
+
+*      Added an experimental syntax to define abbreviations.
+
+
+1.0.1d (1 Dec 2006)
+
+*   Fixed a bug where inline images always had an empty title attribute. The 
+       title attribute is now present only when explicitly defined.
+
+*      Link references definitions can now have an empty title, previously if the 
+       title was defined but left empty the link definition was ignored. This can 
+       be useful if you want an empty title attribute in images to hide the 
+       tooltip in Internet Explorer.
+
+*      Made `detab` aware of UTF-8 characters. UTF-8 multi-byte sequences are now 
+       correctly mapped to one character instead of the number of bytes.
+
+*      Fixed a small bug with WordPress where WordPress' default filter `wpautop`
+       was not properly deactivated on comment text, resulting in hard line breaks
+       where Markdown do not prescribes them.
+
+*      Added a `TextileRestrited` method to the textile compatibility mode. There
+       is no restriction however, as Markdown does not have a restricted mode at 
+       this point. This should make PHP Markdown work again in the latest 
+       versions of TextPattern.
+
+*   Converted PHP Markdown to a object-oriented design.
+
+*      Changed span and block gamut methods so that they loop over a 
+       customizable list of methods. This makes subclassing the parser a more 
+       interesting option for creating syntax extensions.
+
+*      Also added a "document" gamut loop which can be used to hook document-level 
+       methods (like for striping link definitions).
+
+*      Changed all methods which were inserting HTML code so that they now return 
+       a hashed representation of the code. New methods `hashSpan` and `hashBlock`
+       are used to hash respectivly span- and block-level generated content. This 
+       has a couple of significant effects:
+       
+       1.      It prevents invalid nesting of Markdown-generated elements which 
+           could occur occuring with constructs like `*something [link*][1]`.
+       2.      It prevents problems occuring with deeply nested lists on which 
+           paragraphs were ill-formed.
+       3.      It removes the need to call `hashHTMLBlocks` twice during the the 
+               block gamut.
+       
+       Hashes are turned back to HTML prior output.
+
+*      Made the block-level HTML parser smarter using a specially-crafted regular 
+       expression capable of handling nested tags.
+
+*      Solved backtick issues in tag attributes by rewriting the HTML tokenizer to 
+       be aware of code spans. All these lines should work correctly now:
+       
+               <span attr='`ticks`'>bar</span>
+               <span attr='``double ticks``'>bar</span>
+               `<test a="` content of attribute `">`
+
+*      Changed the parsing of HTML comments to match simply from `<!--` to `-->` 
+       instead using of the more complicated SGML-style rule with paired `--`.
+       This is how most browsers parse comments and how XML defines them too.
+
+*      `<address>` has been added to the list of block-level elements and is now
+       treated as an HTML block instead of being wrapped within paragraph tags.
+
+*      Now only trim trailing newlines from code blocks, instead of trimming
+       all trailing whitespace characters.
+
+*      Fixed bug where this:
+
+               [text](http://m.com "title" )
+               
+       wasn't working as expected, because the parser wasn't allowing for spaces
+       before the closing paren.
+
+*      Filthy hack to support markdown='1' in div tags.
+
+*      _DoAutoLinks() now supports the 'dict://' URL scheme.
+
+*      PHP- and ASP-style processor instructions are now protected as
+       raw HTML blocks.
+
+               <? ... ?>
+               <% ... %>
+
+*      Fix for escaped backticks still triggering code spans:
+
+               There are two raw backticks here: \` and here: \`, not a code span
+
+
+Extra 1.0 - 5 September 2005
+
+*   Added support for setting the id attributes for headers like this:
+       
+        Header 1            {#header1}
+        ========
+       
+        ## Header 2 ##      {#header2}
+       
+    This only work only for headers for now.
+
+*   Tables will now work correctly as the first element of a definition 
+    list. For example, this input:
+
+        Term
+
+        :   Header  | Header
+            ------- | -------
+            Cell    | Cell
+                   
+    used to produce no definition list and a table where the first 
+    header was named ": Header". This is now fixed.
+
+*   Fix for a problem where a paragraph following a table was not 
+    placed between `<p>` tags.
+
+
+Extra 1.0b4 - 1 August 2005
+
+*   Fixed some issues where whitespace around HTML blocks were trigging
+    empty paragraph tags.
+
+*   Fixed an HTML block parsing issue that would cause a block element 
+    following a code span or block with unmatched opening bracket to be
+    placed inside a paragraph.
+
+*   Removed some PHP notices that could appear when parsing definition
+    lists and tables with PHP notice reporting flag set.
+
+
+Extra 1.0b3 - 29 July 2005
+
+*   Definition lists now require a blank line before each term. Solves
+    an ambiguity where the last line of lazy-indented definitions could 
+    be mistaken by PHP Markdown as a new term in the list.
+
+*   Definition lists now support multiple terms per definition.
+
+*   Some special tags were replaced in the output by their md5 hash 
+    key. Things such as this now work as expected:
+       
+        ## Header <?php echo $number ?> ##
+
+
+Extra 1.0b2 - 26 July 2005
+
+*   Definition lists can now take two or more definitions for one term.
+    This should have been the case before, but a bug prevented this 
+    from working right.
+
+*   Fixed a problem where single column table with a pipe only at the
+    end where not parsed as table. Here is such a table:
+       
+        | header
+        | ------
+        | cell
+
+*   Fixed problems with empty cells in the first column of a table with 
+    no leading pipe, like this one:
+       
+        header | header
+        ------ | ------
+               | cell
+
+*   Code spans containing pipes did not within a table. This is now 
+    fixed by parsing code spans before splitting rows into cells.
+
+*   Added the pipe character to the backlash escape character lists.
+
+Extra 1.0b1 (25 Jun 2005)
+
+*   First public release of PHP Markdown Extra.
+
+
+Copyright and License
+---------------------
+
+Copyright (c) 2004-2005 Michel Fortin  
+<http://www.michelf.com/>  
+All rights reserved.
+
+Based on Markdown  
+Copyright (c) 2003-2005 John Gruber   
+<http://daringfireball.net/>   
+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 "Markdown" 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.
diff --git a/examples/includes/PHP-Markdown-Extra-1.2.3/markdown.php b/examples/includes/PHP-Markdown-Extra-1.2.3/markdown.php
new file mode 100644 (file)
index 0000000..1b7c042
--- /dev/null
@@ -0,0 +1,2909 @@
+<?php
+#
+# Markdown Extra  -  A text-to-HTML conversion tool for web writers
+#
+# PHP Markdown & Extra
+# Copyright (c) 2004-2008 Michel Fortin
+# <http://www.michelf.com/projects/php-markdown/>
+#
+# Original Markdown
+# Copyright (c) 2004-2006 John Gruber
+# <http://daringfireball.net/projects/markdown/>
+#
+
+
+define( 'MARKDOWN_VERSION',  "1.0.1m" ); # Sat 21 Jun 2008
+define( 'MARKDOWNEXTRA_VERSION',  "1.2.3" ); # Wed 31 Dec 2008
+
+
+#
+# Global default settings:
+#
+
+# Change to ">" for HTML output
+@define( 'MARKDOWN_EMPTY_ELEMENT_SUFFIX',  " />");
+
+# Define the width of a tab for code blocks.
+@define( 'MARKDOWN_TAB_WIDTH',     4 );
+
+# Optional title attribute for footnote links and backlinks.
+@define( 'MARKDOWN_FN_LINK_TITLE',         "" );
+@define( 'MARKDOWN_FN_BACKLINK_TITLE',     "" );
+
+# Optional class attribute for footnote links and backlinks.
+@define( 'MARKDOWN_FN_LINK_CLASS',         "" );
+@define( 'MARKDOWN_FN_BACKLINK_CLASS',     "" );
+
+
+#
+# WordPress settings:
+#
+
+# Change to false to remove Markdown from posts and/or comments.
+@define( 'MARKDOWN_WP_POSTS',      true );
+@define( 'MARKDOWN_WP_COMMENTS',   true );
+
+
+
+### Standard Function Interface ###
+
+@define( 'MARKDOWN_PARSER_CLASS',  'MarkdownExtra_Parser' );
+
+function Markdown($text) {
+#
+# Initialize the parser and return the result of its transform method.
+#
+    # Setup static parser variable.
+    static $parser;
+    if (!isset($parser)) {
+        $parser_class = MARKDOWN_PARSER_CLASS;
+        $parser = new $parser_class;
+    }
+
+    # Transform text using parser.
+    return $parser->transform($text);
+}
+
+
+### WordPress Plugin Interface ###
+
+/*
+Plugin Name: Markdown Extra
+Plugin URI: http://www.michelf.com/projects/php-markdown/
+Description: <a href="http://daringfireball.net/projects/markdown/syntax">Markdown syntax</a> allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by <a href="http://daringfireball.net/">John Gruber</a>. <a href="http://www.michelf.com/projects/php-markdown/">More...</a>
+Version: 1.2.2
+Author: Michel Fortin
+Author URI: http://www.michelf.com/
+*/
+
+if (isset($wp_version)) {
+    # More details about how it works here:
+    # <http://www.michelf.com/weblog/2005/wordpress-text-flow-vs-markdown/>
+
+    # Post content and excerpts
+    # - Remove WordPress paragraph generator.
+    # - Run Markdown on excerpt, then remove all tags.
+    # - Add paragraph tag around the excerpt, but remove it for the excerpt rss.
+    if (MARKDOWN_WP_POSTS) {
+        remove_filter('the_content',     'wpautop');
+        remove_filter('the_content_rss', 'wpautop');
+        remove_filter('the_excerpt',     'wpautop');
+        add_filter('the_content',     'mdwp_MarkdownPost', 6);
+        add_filter('the_content_rss', 'mdwp_MarkdownPost', 6);
+        add_filter('get_the_excerpt', 'mdwp_MarkdownPost', 6);
+        add_filter('get_the_excerpt', 'trim', 7);
+        add_filter('the_excerpt',     'mdwp_add_p');
+        add_filter('the_excerpt_rss', 'mdwp_strip_p');
+
+        remove_filter('content_save_pre',  'balanceTags', 50);
+        remove_filter('excerpt_save_pre',  'balanceTags', 50);
+        add_filter('the_content',     'balanceTags', 50);
+        add_filter('get_the_excerpt', 'balanceTags', 9);
+    }
+
+    # Add a footnote id prefix to posts when inside a loop.
+    function mdwp_MarkdownPost($text) {
+        static $parser;
+        if (!$parser) {
+            $parser_class = MARKDOWN_PARSER_CLASS;
+            $parser = new $parser_class;
+        }
+        if (is_single() || is_page() || is_feed()) {
+            $parser->fn_id_prefix = "";
+        } else {
+            $parser->fn_id_prefix = get_the_ID() . ".";
+        }
+        return $parser->transform($text);
+    }
+
+    # Comments
+    # - Remove WordPress paragraph generator.
+    # - Remove WordPress auto-link generator.
+    # - Scramble important tags before passing them to the kses filter.
+    # - Run Markdown on excerpt then remove paragraph tags.
+    if (MARKDOWN_WP_COMMENTS) {
+        remove_filter('comment_text', 'wpautop', 30);
+        remove_filter('comment_text', 'make_clickable');
+        add_filter('pre_comment_content', 'Markdown', 6);
+        add_filter('pre_comment_content', 'mdwp_hide_tags', 8);
+        add_filter('pre_comment_content', 'mdwp_show_tags', 12);
+        add_filter('get_comment_text',    'Markdown', 6);
+        add_filter('get_comment_excerpt', 'Markdown', 6);
+        add_filter('get_comment_excerpt', 'mdwp_strip_p', 7);
+
+        global $mdwp_hidden_tags, $mdwp_placeholders;
+        $mdwp_hidden_tags = explode(' ',
+            '<p> </p> <pre> </pre> <ol> </ol> <ul> </ul> <li> </li>');
+        $mdwp_placeholders = explode(' ', str_rot13(
+            'pEj07ZbbBZ U1kqgh4w4p pre2zmeN6K QTi31t9pre ol0MP1jzJR '.
+            'ML5IjmbRol ulANi1NsGY J7zRLJqPul liA8ctl16T K9nhooUHli'));
+    }
+
+    function mdwp_add_p($text) {
+        if (!preg_match('{^$|^<(p|ul|ol|dl|pre|blockquote)>}i', $text)) {
+            $text = '<p>'.$text.'</p>';
+            $text = preg_replace('{\n{2,}}', "</p>\n\n<p>", $text);
+        }
+        return $text;
+    }
+
+    function mdwp_strip_p($t) { return preg_replace('{</?p>}i', '', $t); }
+
+    function mdwp_hide_tags($text) {
+        global $mdwp_hidden_tags, $mdwp_placeholders;
+        return str_replace($mdwp_hidden_tags, $mdwp_placeholders, $text);
+    }
+    function mdwp_show_tags($text) {
+        global $mdwp_hidden_tags, $mdwp_placeholders;
+        return str_replace($mdwp_placeholders, $mdwp_hidden_tags, $text);
+    }
+}
+
+
+### bBlog Plugin Info ###
+
+function identify_modifier_markdown() {
+    return array(
+        'name' => 'markdown',
+        'type' => 'modifier',
+        'nicename' => 'PHP Markdown Extra',
+        'description' => 'A text-to-HTML conversion tool for web writers',
+        'authors' => 'Michel Fortin and John Gruber',
+        'licence' => 'GPL',
+        'version' => MARKDOWNEXTRA_VERSION,
+        'help' => '<a href="http://daringfireball.net/projects/markdown/syntax">Markdown syntax</a> allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by <a href="http://daringfireball.net/">John Gruber</a>. <a href="http://www.michelf.com/projects/php-markdown/">More...</a>',
+        );
+}
+
+
+### Smarty Modifier Interface ###
+
+function smarty_modifier_markdown($text) {
+    return Markdown($text);
+}
+
+
+### Textile Compatibility Mode ###
+
+# Rename this file to "classTextile.php" and it can replace Textile everywhere.
+
+if (strcasecmp(substr(__FILE__, -16), "classTextile.php") == 0) {
+    # Try to include PHP SmartyPants. Should be in the same directory.
+    @include_once 'smartypants.php';
+    # Fake Textile class. It calls Markdown instead.
+    class Textile {
+        function TextileThis($text, $lite='', $encode='') {
+            if ($lite == '' && $encode == '')    $text = Markdown($text);
+            if (function_exists('SmartyPants'))  $text = SmartyPants($text);
+            return $text;
+        }
+        # Fake restricted version: restrictions are not supported for now.
+        function TextileRestricted($text, $lite='', $noimage='') {
+            return $this->TextileThis($text, $lite);
+        }
+        # Workaround to ensure compatibility with TextPattern 4.0.3.
+        function blockLite($text) { return $text; }
+    }
+}
+
+
+
+#
+# Markdown Parser Class
+#
+
+class Markdown_Parser {
+
+    # Regex to match balanced [brackets].
+    # Needed to insert a maximum bracked depth while converting to PHP.
+    var $nested_brackets_depth = 6;
+    var $nested_brackets_re;
+
+    var $nested_url_parenthesis_depth = 4;
+    var $nested_url_parenthesis_re;
+
+    # Table of hash values for escaped characters:
+    var $escape_chars = '\`*_{}[]()>#+-.!';
+    var $escape_chars_re;
+
+    # Change to ">" for HTML output.
+    var $empty_element_suffix = MARKDOWN_EMPTY_ELEMENT_SUFFIX;
+    var $tab_width = MARKDOWN_TAB_WIDTH;
+
+    # Change to `true` to disallow markup or entities.
+    var $no_markup = false;
+    var $no_entities = false;
+
+    # Predefined urls and titles for reference links and images.
+    var $predef_urls = array();
+    var $predef_titles = array();
+
+
+    function Markdown_Parser() {
+    #
+    # Constructor function. Initialize appropriate member variables.
+    #
+        $this->_initDetab();
+        $this->prepareItalicsAndBold();
+
+        $this->nested_brackets_re =
+            str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth).
+            str_repeat('\])*', $this->nested_brackets_depth);
+
+        $this->nested_url_parenthesis_re =
+            str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth).
+            str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth);
+
+        $this->escape_chars_re = '['.preg_quote($this->escape_chars).']';
+
+        # Sort document, block, and span gamut in ascendent priority order.
+        asort($this->document_gamut);
+        asort($this->block_gamut);
+        asort($this->span_gamut);
+    }
+
+
+    # Internal hashes used during transformation.
+    var $urls = array();
+    var $titles = array();
+    var $html_hashes = array();
+
+    # Status flag to avoid invalid nesting.
+    var $in_anchor = false;
+
+
+    function setup() {
+    #
+    # Called before the transformation process starts to setup parser
+    # states.
+    #
+        # Clear global hashes.
+        $this->urls = $this->predef_urls;
+        $this->titles = $this->predef_titles;
+        $this->html_hashes = array();
+
+        $in_anchor = false;
+    }
+
+    function teardown() {
+    #
+    # Called after the transformation process to clear any variable
+    # which may be taking up memory unnecessarly.
+    #
+        $this->urls = array();
+        $this->titles = array();
+        $this->html_hashes = array();
+    }
+
+
+    function transform($text) {
+    #
+    # Main function. Performs some preprocessing on the input text
+    # and pass it through the document gamut.
+    #
+        $this->setup();
+
+        # Remove UTF-8 BOM and marker character in input, if present.
+        $text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text);
+
+        # Standardize line endings:
+        #   DOS to Unix and Mac to Unix
+        $text = preg_replace('{\r\n?}', "\n", $text);
+
+        # Make sure $text ends with a couple of newlines:
+        $text .= "\n\n";
+
+        # Convert all tabs to spaces.
+        $text = $this->detab($text);
+
+        # Turn block-level HTML blocks into hash entries
+        $text = $this->hashHTMLBlocks($text);
+
+        # Strip any lines consisting only of spaces and tabs.
+        # This makes subsequent regexen easier to write, because we can
+        # match consecutive blank lines with /\n+/ instead of something
+        # contorted like /[ ]*\n+/ .
+        $text = preg_replace('/^[ ]+$/m', '', $text);
+
+        # Run document gamut methods.
+        foreach ($this->document_gamut as $method => $priority) {
+            $text = $this->$method($text);
+        }
+
+        $this->teardown();
+
+        return $text . "\n";
+    }
+
+    var $document_gamut = array(
+        # Strip link definitions, store in hashes.
+        "stripLinkDefinitions" => 20,
+
+        "runBasicBlockGamut"   => 30,
+        );
+
+
+    function stripLinkDefinitions($text) {
+    #
+    # Strips link definitions from text, stores the URLs and titles in
+    # hash references.
+    #
+        $less_than_tab = $this->tab_width - 1;
+
+        # Link defs are in the form: ^[id]: url "optional title"
+        $text = preg_replace_callback('{
+                            ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1
+                              [ ]*
+                              \n?               # maybe *one* newline
+                              [ ]*
+                            <?(\S+?)>?          # url = $2
+                              [ ]*
+                              \n?               # maybe one newline
+                              [ ]*
+                            (?:
+                                (?<=\s)         # lookbehind for whitespace
+                                ["(]
+                                (.*?)           # title = $3
+                                [")]
+                                [ ]*
+                            )?  # title is optional
+                            (?:\n+|\Z)
+            }xm',
+            array(&$this, '_stripLinkDefinitions_callback'),
+            $text);
+        return $text;
+    }
+    function _stripLinkDefinitions_callback($matches) {
+        $link_id = strtolower($matches[1]);
+        $this->urls[$link_id] = $matches[2];
+        $this->titles[$link_id] =& $matches[3];
+        return ''; # String that will replace the block
+    }
+
+
+    function hashHTMLBlocks($text) {
+        if ($this->no_markup)  return $text;
+
+        $less_than_tab = $this->tab_width - 1;
+
+        # Hashify HTML blocks:
+        # We only want to do this for block-level HTML tags, such as headers,
+        # lists, and tables. That's because we still want to wrap <p>s around
+        # "paragraphs" that are wrapped in non-block-level tags, such as anchors,
+        # phrase emphasis, and spans. The list of tags we're looking for is
+        # hard-coded:
+        #
+        # *  List "a" is made of tags which can be both inline or block-level.
+        #    These will be treated block-level when the start tag is alone on
+        #    its line, otherwise they're not matched here and will be taken as
+        #    inline later.
+        # *  List "b" is made of tags which are always block-level;
+        #
+        $block_tags_a_re = 'ins|del';
+        $block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'.
+                           'script|noscript|form|fieldset|iframe|math';
+
+        # Regular expression for the content of a block tag.
+        $nested_tags_level = 4;
+        $attr = '
+            (?>             # optional tag attributes
+              \s            # starts with whitespace
+              (?>
+                [^>"/]+     # text outside quotes
+              |
+                /+(?!>)     # slash not followed by ">"
+              |
+                "[^"]*"     # text inside double quotes (tolerate ">")
+              |
+                \'[^\']*\'  # text inside single quotes (tolerate ">")
+              )*
+            )?
+            ';
+        $content =
+            str_repeat('
+                (?>
+                  [^<]+         # content without tag
+                |
+                  <\2           # nested opening tag
+                    '.$attr.'   # attributes
+                    (?>
+                      />
+                    |
+                      >', $nested_tags_level).  # end of opening tag
+                      '.*?'.                    # last level nested tag content
+            str_repeat('
+                      </\2\s*>  # closing nested tag
+                    )
+                  |
+                    <(?!/\2\s*> # other tags with a different name
+                  )
+                )*',
+                $nested_tags_level);
+        $content2 = str_replace('\2', '\3', $content);
+
+        # First, look for nested blocks, e.g.:
+        #   <div>
+        #       <div>
+        #       tags for inner block must be indented.
+        #       </div>
+        #   </div>
+        #
+        # The outermost tags must start at the left margin for this to match, and
+        # the inner nested divs must be indented.
+        # We need to do this before the next, more liberal match, because the next
+        # match will start at the first `<div>` and stop at the first `</div>`.
+        $text = preg_replace_callback('{(?>
+            (?>
+                (?<=\n\n)       # Starting after a blank line
+                |               # or
+                \A\n?           # the beginning of the doc
+            )
+            (                       # save in $1
+
+              # Match from `\n<tag>` to `</tag>\n`, handling nested tags
+              # in between.
+
+                        [ ]{0,'.$less_than_tab.'}
+                        <('.$block_tags_b_re.')# start tag = $2
+                        '.$attr.'>          # attributes followed by > and \n
+                        '.$content.'        # content, support nesting
+                        </\2>               # the matching end tag
+                        [ ]*                # trailing spaces/tabs
+                        (?=\n+|\Z)  # followed by a newline or end of document
+
+            | # Special version for tags of group a.
+
+                        [ ]{0,'.$less_than_tab.'}
+                        <('.$block_tags_a_re.')# start tag = $3
+                        '.$attr.'>[ ]*\n    # attributes followed by >
+                        '.$content2.'       # content, support nesting
+                        </\3>               # the matching end tag
+                        [ ]*                # trailing spaces/tabs
+                        (?=\n+|\Z)  # followed by a newline or end of document
+
+            | # Special case just for <hr />. It was easier to make a special
+              # case than to make the other regex more complicated.
+
+                        [ ]{0,'.$less_than_tab.'}
+                        <(hr)               # start tag = $2
+                        '.$attr.'           # attributes
+                        /?>                 # the matching end tag
+                        [ ]*
+                        (?=\n{2,}|\Z)       # followed by a blank line or end of document
+
+            | # Special case for standalone HTML comments:
+
+                    [ ]{0,'.$less_than_tab.'}
+                    (?s:
+                        <!-- .*? -->
+                    )
+                    [ ]*
+                    (?=\n{2,}|\Z)       # followed by a blank line or end of document
+
+            | # PHP and ASP-style processor instructions (<? and <%)
+
+                    [ ]{0,'.$less_than_tab.'}
+                    (?s:
+                        <([?%])         # $2
+                        .*?
+                        \2>
+                    )
+                    [ ]*
+                    (?=\n{2,}|\Z)       # followed by a blank line or end of document
+
+            )
+            )}Sxmi',
+            array(&$this, '_hashHTMLBlocks_callback'),
+            $text);
+
+        return $text;
+    }
+    function _hashHTMLBlocks_callback($matches) {
+        $text = $matches[1];
+        $key  = $this->hashBlock($text);
+        return "\n\n$key\n\n";
+    }
+
+
+    function hashPart($text, $boundary = 'X') {
+    #
+    # Called whenever a tag must be hashed when a function insert an atomic
+    # element in the text stream. Passing $text to through this function gives
+    # a unique text-token which will be reverted back when calling unhash.
+    #
+    # The $boundary argument specify what character should be used to surround
+    # the token. By convension, "B" is used for block elements that needs not
+    # to be wrapped into paragraph tags at the end, ":" is used for elements
+    # that are word separators and "X" is used in the general case.
+    #
+        # Swap back any tag hash found in $text so we do not have to `unhash`
+        # multiple times at the end.
+        $text = $this->unhash($text);
+
+        # Then hash the block.
+        static $i = 0;
+        $key = "$boundary\x1A" . ++$i . $boundary;
+        $this->html_hashes[$key] = $text;
+        return $key; # String that will replace the tag.
+    }
+
+
+    function hashBlock($text) {
+    #
+    # Shortcut function for hashPart with block-level boundaries.
+    #
+        return $this->hashPart($text, 'B');
+    }
+
+
+    var $block_gamut = array(
+    #
+    # These are all the transformations that form block-level
+    # tags like paragraphs, headers, and list items.
+    #
+        "doHeaders"         => 10,
+        "doHorizontalRules" => 20,
+
+        "doLists"           => 40,
+        "doCodeBlocks"      => 50,
+        "doBlockQuotes"     => 60,
+        );
+
+    function runBlockGamut($text) {
+    #
+    # Run block gamut tranformations.
+    #
+        # We need to escape raw HTML in Markdown source before doing anything
+        # else. This need to be done for each block, and not only at the
+        # begining in the Markdown function since hashed blocks can be part of
+        # list items and could have been indented. Indented blocks would have
+        # been seen as a code block in a previous pass of hashHTMLBlocks.
+        $text = $this->hashHTMLBlocks($text);
+
+        return $this->runBasicBlockGamut($text);
+    }
+
+    function runBasicBlockGamut($text) {
+    #
+    # Run block gamut tranformations, without hashing HTML blocks. This is
+    # useful when HTML blocks are known to be already hashed, like in the first
+    # whole-document pass.
+    #
+        foreach ($this->block_gamut as $method => $priority) {
+            $text = $this->$method($text);
+        }
+
+        # Finally form paragraph and restore hashed blocks.
+        $text = $this->formParagraphs($text);
+
+        return $text;
+    }
+
+
+    function doHorizontalRules($text) {
+        # Do Horizontal Rules:
+        return preg_replace(
+            '{
+                ^[ ]{0,3}   # Leading space
+                ([-*_])     # $1: First marker
+                (?>         # Repeated marker group
+                    [ ]{0,2}    # Zero, one, or two spaces.
+                    \1          # Marker character
+                ){2,}       # Group repeated at least twice
+                [ ]*        # Tailing spaces
+                $           # End of line.
+            }mx',
+            "\n".$this->hashBlock("<hr$this->empty_element_suffix")."\n",
+            $text);
+    }
+
+
+    var $span_gamut = array(
+    #
+    # These are all the transformations that occur *within* block-level
+    # tags like paragraphs, headers, and list items.
+    #
+        # Process character escapes, code spans, and inline HTML
+        # in one shot.
+        "parseSpan"           => -30,
+
+        # Process anchor and image tags. Images must come first,
+        # because ![foo][f] looks like an anchor.
+        "doImages"            =>  10,
+        "doAnchors"           =>  20,
+
+        # Make links out of things like `<http://example.com/>`
+        # Must come after doAnchors, because you can use < and >
+        # delimiters in inline links like [this](<url>).
+        "doAutoLinks"         =>  30,
+        "encodeAmpsAndAngles" =>  40,
+
+        "doItalicsAndBold"    =>  50,
+        "doHardBreaks"        =>  60,
+        );
+
+    function runSpanGamut($text) {
+    #
+    # Run span gamut tranformations.
+    #
+        foreach ($this->span_gamut as $method => $priority) {
+            $text = $this->$method($text);
+        }
+
+        return $text;
+    }
+
+
+    function doHardBreaks($text) {
+        # Do hard breaks:
+        return preg_replace_callback('/ {2,}\n/',
+            array(&$this, '_doHardBreaks_callback'), $text);
+    }
+    function _doHardBreaks_callback($matches) {
+        return $this->hashPart("<br$this->empty_element_suffix\n");
+    }
+
+
+    function doAnchors($text) {
+    #
+    # Turn Markdown link shortcuts into XHTML <a> tags.
+    #
+        if ($this->in_anchor) return $text;
+        $this->in_anchor = true;
+
+        #
+        # First, handle reference-style links: [link text] [id]
+        #
+        $text = preg_replace_callback('{
+            (                   # wrap whole match in $1
+              \[
+                ('.$this->nested_brackets_re.') # link text = $2
+              \]
+
+              [ ]?              # one optional space
+              (?:\n[ ]*)?       # one optional newline followed by spaces
+
+              \[
+                (.*?)       # id = $3
+              \]
+            )
+            }xs',
+            array(&$this, '_doAnchors_reference_callback'), $text);
+
+        #
+        # Next, inline-style links: [link text](url "optional title")
+        #
+        $text = preg_replace_callback('{
+            (               # wrap whole match in $1
+              \[
+                ('.$this->nested_brackets_re.') # link text = $2
+              \]
+              \(            # literal paren
+                [ ]*
+                (?:
+                    <(\S*)> # href = $3
+                |
+                    ('.$this->nested_url_parenthesis_re.')  # href = $4
+                )
+                [ ]*
+                (           # $5
+                  ([\'"])   # quote char = $6
+                  (.*?)     # Title = $7
+                  \6        # matching quote
+                  [ ]*  # ignore any spaces/tabs between closing quote and )
+                )?          # title is optional
+              \)
+            )
+            }xs',
+            array(&$this, '_DoAnchors_inline_callback'), $text);
+
+        #
+        # Last, handle reference-style shortcuts: [link text]
+        # These must come last in case you've also got [link test][1]
+        # or [link test](/foo)
+        #
+//      $text = preg_replace_callback('{
+//          (                   # wrap whole match in $1
+//            \[
+//              ([^\[\]]+)      # link text = $2; can\'t contain [ or ]
+//            \]
+//          )
+//          }xs',
+//          array(&$this, '_doAnchors_reference_callback'), $text);
+
+        $this->in_anchor = false;
+        return $text;
+    }
+    function _doAnchors_reference_callback($matches) {
+        $whole_match =  $matches[1];
+        $link_text   =  $matches[2];
+        $link_id     =& $matches[3];
+
+        if ($link_id == "") {
+            # for shortcut links like [this][] or [this].
+            $link_id = $link_text;
+        }
+
+        # lower-case and turn embedded newlines into spaces
+        $link_id = strtolower($link_id);
+        $link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
+
+        if (isset($this->urls[$link_id])) {
+            $url = $this->urls[$link_id];
+            $url = $this->encodeAttribute($url);
+
+            $result = "<a href=\"$url\"";
+            if ( isset( $this->titles[$link_id] ) ) {
+                $title = $this->titles[$link_id];
+                $title = $this->encodeAttribute($title);
+                $result .=  " title=\"$title\"";
+            }
+
+            $link_text = $this->runSpanGamut($link_text);
+            $result .= ">$link_text</a>";
+            $result = $this->hashPart($result);
+        }
+        else {
+            $result = $whole_match;
+        }
+        return $result;
+    }
+    function _doAnchors_inline_callback($matches) {
+        $whole_match    =  $matches[1];
+        $link_text      =  $this->runSpanGamut($matches[2]);
+        $url            =  $matches[3] == '' ? $matches[4] : $matches[3];
+        $title          =& $matches[7];
+
+        $url = $this->encodeAttribute($url);
+
+        $result = "<a href=\"$url\"";
+        if (isset($title)) {
+            $title = $this->encodeAttribute($title);
+            $result .=  " title=\"$title\"";
+        }
+
+        $link_text = $this->runSpanGamut($link_text);
+        $result .= ">$link_text</a>";
+
+        return $this->hashPart($result);
+    }
+
+
+    function doImages($text) {
+    #
+    # Turn Markdown image shortcuts into <img> tags.
+    #
+        #
+        # First, handle reference-style labeled images: ![alt text][id]
+        #
+        $text = preg_replace_callback('{
+            (               # wrap whole match in $1
+              !\[
+                ('.$this->nested_brackets_re.')     # alt text = $2
+              \]
+
+              [ ]?              # one optional space
+              (?:\n[ ]*)?       # one optional newline followed by spaces
+
+              \[
+                (.*?)       # id = $3
+              \]
+
+            )
+            }xs',
+            array(&$this, '_doImages_reference_callback'), $text);
+
+        #
+        # Next, handle inline images:  ![alt text](url "optional title")
+        # Don't forget: encode * and _
+        #
+        $text = preg_replace_callback('{
+            (               # wrap whole match in $1
+              !\[
+                ('.$this->nested_brackets_re.')     # alt text = $2
+              \]
+              \s?           # One optional whitespace character
+              \(            # literal paren
+                [ ]*
+                (?:
+                    <(\S*)> # src url = $3
+                |
+                    ('.$this->nested_url_parenthesis_re.')  # src url = $4
+                )
+                [ ]*
+                (           # $5
+                  ([\'"])   # quote char = $6
+                  (.*?)     # title = $7
+                  \6        # matching quote
+                  [ ]*
+                )?          # title is optional
+              \)
+            )
+            }xs',
+            array(&$this, '_doImages_inline_callback'), $text);
+
+        return $text;
+    }
+    function _doImages_reference_callback($matches) {
+        $whole_match = $matches[1];
+        $alt_text    = $matches[2];
+        $link_id     = strtolower($matches[3]);
+
+        if ($link_id == "") {
+            $link_id = strtolower($alt_text); # for shortcut links like ![this][].
+        }
+
+        $alt_text = $this->encodeAttribute($alt_text);
+        if (isset($this->urls[$link_id])) {
+            $url = $this->encodeAttribute($this->urls[$link_id]);
+            $result = "<img src=\"$url\" alt=\"$alt_text\"";
+            if (isset($this->titles[$link_id])) {
+                $title = $this->titles[$link_id];
+                $title = $this->encodeAttribute($title);
+                $result .=  " title=\"$title\"";
+            }
+            $result .= $this->empty_element_suffix;
+            $result = $this->hashPart($result);
+        }
+        else {
+            # If there's no such link ID, leave intact:
+            $result = $whole_match;
+        }
+
+        return $result;
+    }
+    function _doImages_inline_callback($matches) {
+        $whole_match    = $matches[1];
+        $alt_text       = $matches[2];
+        $url            = $matches[3] == '' ? $matches[4] : $matches[3];
+        $title          =& $matches[7];
+
+        $alt_text = $this->encodeAttribute($alt_text);
+        $url = $this->encodeAttribute($url);
+        $result = "<img src=\"$url\" alt=\"$alt_text\"";
+        if (isset($title)) {
+            $title = $this->encodeAttribute($title);
+            $result .=  " title=\"$title\""; # $title already quoted
+        }
+        $result .= $this->empty_element_suffix;
+
+        return $this->hashPart($result);
+    }
+
+
+    function doHeaders($text) {
+        # Setext-style headers:
+        #     Header 1
+        #     ========
+        #
+        #     Header 2
+        #     --------
+        #
+        $text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx',
+            array(&$this, '_doHeaders_callback_setext'), $text);
+
+        # atx-style headers:
+        #   # Header 1
+        #   ## Header 2
+        #   ## Header 2 with closing hashes ##
+        #   ...
+        #   ###### Header 6
+        #
+        $text = preg_replace_callback('{
+                ^(\#{1,6})  # $1 = string of #\'s
+                [ ]*
+                (.+?)       # $2 = Header text
+                [ ]*
+                \#*         # optional closing #\'s (not counted)
+                \n+
+            }xm',
+            array(&$this, '_doHeaders_callback_atx'), $text);
+
+        return $text;
+    }
+    function _doHeaders_callback_setext($matches) {
+        # Terrible hack to check we haven't found an empty list item.
+        if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1]))
+            return $matches[0];
+
+        $level = $matches[2]{0} == '=' ? 1 : 2;
+        $block = "<h$level>".$this->runSpanGamut($matches[1])."</h$level>";
+        return "\n" . $this->hashBlock($block) . "\n\n";
+    }
+    function _doHeaders_callback_atx($matches) {
+        $level = strlen($matches[1]);
+        $block = "<h$level>".$this->runSpanGamut($matches[2])."</h$level>";
+        return "\n" . $this->hashBlock($block) . "\n\n";
+    }
+
+
+    function doLists($text) {
+    #
+    # Form HTML ordered (numbered) and unordered (bulleted) lists.
+    #
+        $less_than_tab = $this->tab_width - 1;
+
+        # Re-usable patterns to match list item bullets and number markers:
+        $marker_ul_re  = '[*+-]';
+        $marker_ol_re  = '\d+[.]';
+        $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
+
+        $markers_relist = array($marker_ul_re, $marker_ol_re);
+
+        foreach ($markers_relist as $marker_re) {
+            # Re-usable pattern to match any entirel ul or ol list:
+            $whole_list_re = '
+                (                               # $1 = whole list
+                  (                             # $2
+                    [ ]{0,'.$less_than_tab.'}
+                    ('.$marker_re.')            # $3 = first list item marker
+                    [ ]+
+                  )
+                  (?s:.+?)
+                  (                             # $4
+                      \z
+                    |
+                      \n{2,}
+                      (?=\S)
+                      (?!                       # Negative lookahead for another list item marker
+                        [ ]*
+                        '.$marker_re.'[ ]+
+                      )
+                  )
+                )
+            '; // mx
+
+            # We use a different prefix before nested lists than top-level lists.
+            # See extended comment in _ProcessListItems().
+
+            if ($this->list_level) {
+                $text = preg_replace_callback('{
+                        ^
+                        '.$whole_list_re.'
+                    }mx',
+                    array(&$this, '_doLists_callback'), $text);
+            }
+            else {
+                $text = preg_replace_callback('{
+                        (?:(?<=\n)\n|\A\n?) # Must eat the newline
+                        '.$whole_list_re.'
+                    }mx',
+                    array(&$this, '_doLists_callback'), $text);
+            }
+        }
+
+        return $text;
+    }
+    function _doLists_callback($matches) {
+        # Re-usable patterns to match list item bullets and number markers:
+        $marker_ul_re  = '[*+-]';
+        $marker_ol_re  = '\d+[.]';
+        $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
+
+        $list = $matches[1];
+        $list_type = preg_match("/$marker_ul_re/", $matches[3]) ? "ul" : "ol";
+
+        $marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re );
+
+        $list .= "\n";
+        $result = $this->processListItems($list, $marker_any_re);
+
+        $result = $this->hashBlock("<$list_type>\n" . $result . "</$list_type>");
+        return "\n". $result ."\n\n";
+    }
+
+    var $list_level = 0;
+
+    function processListItems($list_str, $marker_any_re) {
+    #
+    #   Process the contents of a single ordered or unordered list, splitting it
+    #   into individual list items.
+    #
+        # The $this->list_level global keeps track of when we're inside a list.
+        # Each time we enter a list, we increment it; when we leave a list,
+        # we decrement. If it's zero, we're not in a list anymore.
+        #
+        # We do this because when we're not inside a list, we want to treat
+        # something like this:
+        #
+        #       I recommend upgrading to version
+        #       8. Oops, now this line is treated
+        #       as a sub-list.
+        #
+        # As a single paragraph, despite the fact that the second line starts
+        # with a digit-period-space sequence.
+        #
+        # Whereas when we're inside a list (or sub-list), that line will be
+        # treated as the start of a sub-list. What a kludge, huh? This is
+        # an aspect of Markdown's syntax that's hard to parse perfectly
+        # without resorting to mind-reading. Perhaps the solution is to
+        # change the syntax rules such that sub-lists must start with a
+        # starting cardinal number; e.g. "1." or "a.".
+
+        $this->list_level++;
+
+        # trim trailing blank lines:
+        $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
+
+        $list_str = preg_replace_callback('{
+            (\n)?                           # leading line = $1
+            (^[ ]*)                         # leading whitespace = $2
+            ('.$marker_any_re.'             # list marker and space = $3
+                (?:[ ]+|(?=\n)) # space only required if item is not empty
+            )
+            ((?s:.*?))                      # list item text   = $4
+            (?:(\n+(?=\n))|\n)              # tailing blank line = $5
+            (?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n))))
+            }xm',
+            array(&$this, '_processListItems_callback'), $list_str);
+
+        $this->list_level--;
+        return $list_str;
+    }
+    function _processListItems_callback($matches) {
+        $item = $matches[4];
+        $leading_line =& $matches[1];
+        $leading_space =& $matches[2];
+        $marker_space = $matches[3];
+        $tailing_blank_line =& $matches[5];
+
+        if ($leading_line || $tailing_blank_line ||
+            preg_match('/\n{2,}/', $item))
+        {
+            # Replace marker with the appropriate whitespace indentation
+            $item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item;
+            $item = $this->runBlockGamut($this->outdent($item)."\n");
+        }
+        else {
+            # Recursion for sub-lists:
+            $item = $this->doLists($this->outdent($item));
+            $item = preg_replace('/\n+$/', '', $item);
+            $item = $this->runSpanGamut($item);
+        }
+
+        return "<li>" . $item . "</li>\n";
+    }
+
+
+    function doCodeBlocks($text) {
+    #
+    #   Process Markdown `<pre><code>` blocks.
+    #
+        $text = preg_replace_callback('{
+                (?:\n\n|\A\n?)
+                (               # $1 = the code block -- one or more lines, starting with a space/tab
+                  (?>
+                    [ ]{'.$this->tab_width.'}  # Lines must start with a tab or a tab-width of spaces
+                    .*\n+
+                  )+
+                )
+                ((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z) # Lookahead for non-space at line-start, or end of doc
+            }xm',
+            array(&$this, '_doCodeBlocks_callback'), $text);
+
+        return $text;
+    }
+    function _doCodeBlocks_callback($matches) {
+        $codeblock = $matches[1];
+
+        $codeblock = $this->outdent($codeblock);
+        $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
+
+        # trim leading newlines and trailing newlines
+        $codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
+
+        $codeblock = "<pre><code>$codeblock\n</code></pre>";
+        return "\n\n".$this->hashBlock($codeblock)."\n\n";
+    }
+
+
+    function makeCodeSpan($code) {
+    #
+    # Create a code span markup for $code. Called from handleSpanToken.
+    #
+        $code = htmlspecialchars(trim($code), ENT_NOQUOTES);
+        return $this->hashPart("<code>$code</code>");
+    }
+
+
+    var $em_relist = array(
+        ''  => '(?:(?<!\*)\*(?!\*)|(?<!_)_(?!_))(?=\S)(?![.,:;]\s)',
+        '*' => '(?<=\S)(?<!\*)\*(?!\*)',
+        '_' => '(?<=\S)(?<!_)_(?!_)',
+        );
+    var $strong_relist = array(
+        ''   => '(?:(?<!\*)\*\*(?!\*)|(?<!_)__(?!_))(?=\S)(?![.,:;]\s)',
+        '**' => '(?<=\S)(?<!\*)\*\*(?!\*)',
+        '__' => '(?<=\S)(?<!_)__(?!_)',
+        );
+    var $em_strong_relist = array(
+        ''    => '(?:(?<!\*)\*\*\*(?!\*)|(?<!_)___(?!_))(?=\S)(?![.,:;]\s)',
+        '***' => '(?<=\S)(?<!\*)\*\*\*(?!\*)',
+        '___' => '(?<=\S)(?<!_)___(?!_)',
+        );
+    var $em_strong_prepared_relist;
+
+    function prepareItalicsAndBold() {
+    #
+    # Prepare regular expressions for seraching emphasis tokens in any
+    # context.
+    #
+        foreach ($this->em_relist as $em => $em_re) {
+            foreach ($this->strong_relist as $strong => $strong_re) {
+                # Construct list of allowed token expressions.
+                $token_relist = array();
+                if (isset($this->em_strong_relist["$em$strong"])) {
+                    $token_relist[] = $this->em_strong_relist["$em$strong"];
+                }
+                $token_relist[] = $em_re;
+                $token_relist[] = $strong_re;
+
+                # Construct master expression from list.
+                $token_re = '{('. implode('|', $token_relist) .')}';
+                $this->em_strong_prepared_relist["$em$strong"] = $token_re;
+            }
+        }
+    }
+
+    function doItalicsAndBold($text) {
+        $token_stack = array('');
+        $text_stack = array('');
+        $em = '';
+        $strong = '';
+        $tree_char_em = false;
+
+        while (1) {
+            #
+            # Get prepared regular expression for seraching emphasis tokens
+            # in current context.
+            #
+            $token_re = $this->em_strong_prepared_relist["$em$strong"];
+
+            #
+            # Each loop iteration seach for the next emphasis token.
+            # Each token is then passed to handleSpanToken.
+            #
+            $parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
+            $text_stack[0] .= $parts[0];
+            $token =& $parts[1];
+            $text =& $parts[2];
+
+            if (empty($token)) {
+                # Reached end of text span: empty stack without emitting.
+                # any more emphasis.
+                while ($token_stack[0]) {
+                    $text_stack[1] .= array_shift($token_stack);
+                    $text_stack[0] .= array_shift($text_stack);
+                }
+                break;
+            }
+
+            $token_len = strlen($token);
+            if ($tree_char_em) {
+                # Reached closing marker while inside a three-char emphasis.
+                if ($token_len == 3) {
+                    # Three-char closing marker, close em and strong.
+                    array_shift($token_stack);
+                    $span = array_shift($text_stack);
+                    $span = $this->runSpanGamut($span);
+                    $span = "<strong><em>$span</em></strong>";
+                    $text_stack[0] .= $this->hashPart($span);
+                    $em = '';
+                    $strong = '';
+                } else {
+                    # Other closing marker: close one em or strong and
+                    # change current token state to match the other
+                    $token_stack[0] = str_repeat($token{0}, 3-$token_len);
+                    $tag = $token_len == 2 ? "strong" : "em";
+                    $span = $text_stack[0];
+                    $span = $this->runSpanGamut($span);
+                    $span = "<$tag>$span</$tag>";
+                    $text_stack[0] = $this->hashPart($span);
+                    $$tag = ''; # $$tag stands for $em or $strong
+                }
+                $tree_char_em = false;
+            } else if ($token_len == 3) {
+                if ($em) {
+                    # Reached closing marker for both em and strong.
+                    # Closing strong marker:
+                    for ($i = 0; $i < 2; ++$i) {
+                        $shifted_token = array_shift($token_stack);
+                        $tag = strlen($shifted_token) == 2 ? "strong" : "em";
+                        $span = array_shift($text_stack);
+                        $span = $this->runSpanGamut($span);
+                        $span = "<$tag>$span</$tag>";
+                        $text_stack[0] .= $this->hashPart($span);
+                        $$tag = ''; # $$tag stands for $em or $strong
+                    }
+                } else {
+                    # Reached opening three-char emphasis marker. Push on token
+                    # stack; will be handled by the special condition above.
+                    $em = $token{0};
+                    $strong = "$em$em";
+                    array_unshift($token_stack, $token);
+                    array_unshift($text_stack, '');
+                    $tree_char_em = true;
+                }
+            } else if ($token_len == 2) {
+                if ($strong) {
+                    # Unwind any dangling emphasis marker:
+                    if (strlen($token_stack[0]) == 1) {
+                        $text_stack[1] .= array_shift($token_stack);
+                        $text_stack[0] .= array_shift($text_stack);
+                    }
+                    # Closing strong marker:
+                    array_shift($token_stack);
+                    $span = array_shift($text_stack);
+                    $span = $this->runSpanGamut($span);
+                    $span = "<strong>$span</strong>";
+                    $text_stack[0] .= $this->hashPart($span);
+                    $strong = '';
+                } else {
+                    array_unshift($token_stack, $token);
+                    array_unshift($text_stack, '');
+                    $strong = $token;
+                }
+            } else {
+                # Here $token_len == 1
+                if ($em) {
+                    if (strlen($token_stack[0]) == 1) {
+                        # Closing emphasis marker:
+                        array_shift($token_stack);
+                        $span = array_shift($text_stack);
+                        $span = $this->runSpanGamut($span);
+                        $span = "<em>$span</em>";
+                        $text_stack[0] .= $this->hashPart($span);
+                        $em = '';
+                    } else {
+                        $text_stack[0] .= $token;
+                    }
+                } else {
+                    array_unshift($token_stack, $token);
+                    array_unshift($text_stack, '');
+                    $em = $token;
+                }
+            }
+        }
+        return $text_stack[0];
+    }
+
+
+    function doBlockQuotes($text) {
+        $text = preg_replace_callback('/
+              (                             # Wrap whole match in $1
+                (?>
+                  ^[ ]*>[ ]?            # ">" at the start of a line
+                    .+\n                    # rest of the first line
+                  (.+\n)*                   # subsequent consecutive lines
+                  \n*                       # blanks
+                )+
+              )
+            /xm',
+            array(&$this, '_doBlockQuotes_callback'), $text);
+
+        return $text;
+    }
+    function _doBlockQuotes_callback($matches) {
+        $bq = $matches[1];
+        # trim one level of quoting - trim whitespace-only lines
+        $bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq);
+        $bq = $this->runBlockGamut($bq);        # recurse
+
+        $bq = preg_replace('/^/m', "  ", $bq);
+        # These leading spaces cause problem with <pre> content,
+        # so we need to fix that:
+        $bq = preg_replace_callback('{(\s*<pre>.+?</pre>)}sx',
+            array(&$this, '_DoBlockQuotes_callback2'), $bq);
+
+        return "\n". $this->hashBlock("<blockquote>\n$bq\n</blockquote>")."\n\n";
+    }
+    function _doBlockQuotes_callback2($matches) {
+        $pre = $matches[1];
+        $pre = preg_replace('/^  /m', '', $pre);
+        return $pre;
+    }
+
+
+    function formParagraphs($text) {
+    #
+    #   Params:
+    #       $text - string to process with html <p> tags
+    #
+        # Strip leading and trailing lines:
+        $text = preg_replace('/\A\n+|\n+\z/', '', $text);
+
+        $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
+
+        #
+        # Wrap <p> tags and unhashify HTML blocks
+        #
+        foreach ($grafs as $key => $value) {
+            if (!preg_match('/^B\x1A[0-9]+B$/', $value)) {
+                # Is a paragraph.
+                $value = $this->runSpanGamut($value);
+                $value = preg_replace('/^([ ]*)/', "<p>", $value);
+                $value .= "</p>";
+                $grafs[$key] = $this->unhash($value);
+            }
+            else {
+                # Is a block.
+                # Modify elements of @grafs in-place...
+                $graf = $value;
+                $block = $this->html_hashes[$graf];
+                $graf = $block;
+//              if (preg_match('{
+//                  \A
+//                  (                           # $1 = <div> tag
+//                    <div  \s+
+//                    [^>]*
+//                    \b
+//                    markdown\s*=\s*  ([\'"])  #   $2 = attr quote char
+//                    1
+//                    \2
+//                    [^>]*
+//                    >
+//                  )
+//                  (                           # $3 = contents
+//                  .*
+//                  )
+//                  (</div>)                    # $4 = closing tag
+//                  \z
+//                  }xs', $block, $matches))
+//              {
+//                  list(, $div_open, , $div_content, $div_close) = $matches;
+//
+//                  # We can't call Markdown(), because that resets the hash;
+//                  # that initialization code should be pulled into its own sub, though.
+//                  $div_content = $this->hashHTMLBlocks($div_content);
+//
+//                  # Run document gamut methods on the content.
+//                  foreach ($this->document_gamut as $method => $priority) {
+//                      $div_content = $this->$method($div_content);
+//                  }
+//
+//                  $div_open = preg_replace(
+//                      '{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open);
+//
+//                  $graf = $div_open . "\n" . $div_content . "\n" . $div_close;
+//              }
+                $grafs[$key] = $graf;
+            }
+        }
+
+        return implode("\n\n", $grafs);
+    }
+
+
+    function encodeAttribute($text) {
+    #
+    # Encode text for a double-quoted HTML attribute. This function
+    # is *not* suitable for attributes enclosed in single quotes.
+    #
+        $text = $this->encodeAmpsAndAngles($text);
+        $text = str_replace('"', '&quot;', $text);
+        return $text;
+    }
+
+
+    function encodeAmpsAndAngles($text) {
+    #
+    # Smart processing for ampersands and angle brackets that need to
+    # be encoded. Valid character entities are left alone unless the
+    # no-entities mode is set.
+    #
+        if ($this->no_entities) {
+            $text = str_replace('&', '&amp;', $text);
+        } else {
+            # Ampersand-encoding based entirely on Nat Irons's Amputator
+            # MT plugin: <http://bumppo.net/projects/amputator/>
+            $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/',
+                                '&amp;', $text);;
+        }
+        # Encode remaining <'s
+        $text = str_replace('<', '&lt;', $text);
+
+        return $text;
+    }
+
+
+    function doAutoLinks($text) {
+        $text = preg_replace_callback('{<((https?|ftp|dict):[^\'">\s]+)>}i',
+            array(&$this, '_doAutoLinks_url_callback'), $text);
+
+        # Email addresses: <address@domain.foo>
+        $text = preg_replace_callback('{
+            <
+            (?:mailto:)?
+            (
+                [-.\w\x80-\xFF]+
+                \@
+                [-a-z0-9\x80-\xFF]+(\.[-a-z0-9\x80-\xFF]+)*\.[a-z]+
+            )
+            >
+            }xi',
+            array(&$this, '_doAutoLinks_email_callback'), $text);
+
+        return $text;
+    }
+    function _doAutoLinks_url_callback($matches) {
+        $url = $this->encodeAttribute($matches[1]);
+        $link = "<a href=\"$url\">$url</a>";
+        return $this->hashPart($link);
+    }
+    function _doAutoLinks_email_callback($matches) {
+        $address = $matches[1];
+        $link = $this->encodeEmailAddress($address);
+        return $this->hashPart($link);
+    }
+
+
+    function encodeEmailAddress($addr) {
+    #
+    #   Input: an email address, e.g. "foo@example.com"
+    #
+    #   Output: the email address as a mailto link, with each character
+    #       of the address encoded as either a decimal or hex entity, in
+    #       the hopes of foiling most address harvesting spam bots. E.g.:
+    #
+    #     <p><a href="&#109;&#x61;&#105;&#x6c;&#116;&#x6f;&#58;&#x66;o&#111;
+    #        &#x40;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;&#101;&#46;&#x63;&#111;
+    #        &#x6d;">&#x66;o&#111;&#x40;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;
+    #        &#101;&#46;&#x63;&#111;&#x6d;</a></p>
+    #
+    #   Based by a filter by Matthew Wickline, posted to BBEdit-Talk.
+    #   With some optimizations by Milian Wolff.
+    #
+        $addr = "mailto:" . $addr;
+        $chars = preg_split('/(?<!^)(?!$)/', $addr);
+        $seed = (int)abs(crc32($addr) / strlen($addr)); # Deterministic seed.
+
+        foreach ($chars as $key => $char) {
+            $ord = ord($char);
+            # Ignore non-ascii chars.
+            if ($ord < 128) {
+                $r = ($seed * (1 + $key)) % 100; # Pseudo-random function.
+                # roughly 10% raw, 45% hex, 45% dec
+                # '@' *must* be encoded. I insist.
+                if ($r > 90 && $char != '@') /* do nothing */;
+                else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';';
+                else              $chars[$key] = '&#'.$ord.';';
+            }
+        }
+
+        $addr = implode('', $chars);
+        $text = implode('', array_slice($chars, 7)); # text without `mailto:`
+        $addr = "<a href=\"$addr\">$text</a>";
+
+        return $addr;
+    }
+
+
+    function parseSpan($str) {
+    #
+    # Take the string $str and parse it into tokens, hashing embeded HTML,
+    # escaped characters and handling code spans.
+    #
+        $output = '';
+
+        $span_re = '{
+                (
+                    \\\\'.$this->escape_chars_re.'
+                |
+                    (?<![`\\\\])
+                    `+                      # code span marker
+            '.( $this->no_markup ? '' : '
+                |
+                    <!--    .*?     -->     # comment
+                |
+                    <\?.*?\?> | <%.*?%>     # processing instruction
+                |
+                    <[/!$]?[-a-zA-Z0-9:]+   # regular tags
+                    (?>
+                        \s
+                        (?>[^"\'>]+|"[^"]*"|\'[^\']*\')*
+                    )?
+                    >
+            ').'
+                )
+                }xs';
+
+        while (1) {
+            #
+            # Each loop iteration seach for either the next tag, the next
+            # openning code span marker, or the next escaped character.
+            # Each token is then passed to handleSpanToken.
+            #
+            $parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE);
+
+            # Create token from text preceding tag.
+            if ($parts[0] != "") {
+                $output .= $parts[0];
+            }
+
+            # Check if we reach the end.
+            if (isset($parts[1])) {
+                $output .= $this->handleSpanToken($parts[1], $parts[2]);
+                $str = $parts[2];
+            }
+            else {
+                break;
+            }
+        }
+
+        return $output;
+    }
+
+
+    function handleSpanToken($token, &$str) {
+    #
+    # Handle $token provided by parseSpan by determining its nature and
+    # returning the corresponding value that should replace it.
+    #
+        switch ($token{0}) {
+            case "\\":
+                return $this->hashPart("&#". ord($token{1}). ";");
+            case "`":
+                # Search for end marker in remaining text.
+                if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm',
+                    $str, $matches))
+                {
+                    $str = $matches[2];
+                    $codespan = $this->makeCodeSpan($matches[1]);
+                    return $this->hashPart($codespan);
+                }
+                return $token; // return as text since no ending marker found.
+            default:
+                return $this->hashPart($token);
+        }
+    }
+
+
+    function outdent($text) {
+    #
+    # Remove one level of line-leading tabs or spaces
+    #
+        return preg_replace('/^(\t|[ ]{1,'.$this->tab_width.'})/m', '', $text);
+    }
+
+
+    # String length function for detab. `_initDetab` will create a function to
+    # hanlde UTF-8 if the default function does not exist.
+    var $utf8_strlen = 'mb_strlen';
+
+    function detab($text) {
+    #
+    # Replace tabs with the appropriate amount of space.
+    #
+        # For each line we separate the line in blocks delemited by
+        # tab characters. Then we reconstruct every line by adding the
+        # appropriate number of space between each blocks.
+
+        $text = preg_replace_callback('/^.*\t.*$/m',
+            array(&$this, '_detab_callback'), $text);
+
+        return $text;
+    }
+    function _detab_callback($matches) {
+        $line = $matches[0];
+        $strlen = $this->utf8_strlen; # strlen function for UTF-8.
+
+        # Split in blocks.
+        $blocks = explode("\t", $line);
+        # Add each blocks to the line.
+        $line = $blocks[0];
+        unset($blocks[0]); # Do not add first block twice.
+        foreach ($blocks as $block) {
+            # Calculate amount of space, insert spaces, insert block.
+            $amount = $this->tab_width -
+                $strlen($line, 'UTF-8') % $this->tab_width;
+            $line .= str_repeat(" ", $amount) . $block;
+        }
+        return $line;
+    }
+    function _initDetab() {
+    #
+    # Check for the availability of the function in the `utf8_strlen` property
+    # (initially `mb_strlen`). If the function is not available, create a
+    # function that will loosely count the number of UTF-8 characters with a
+    # regular expression.
+    #
+        if (function_exists($this->utf8_strlen)) return;
+        $this->utf8_strlen = create_function('$text', 'return preg_match_all(
+            "/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/",
+            $text, $m);');
+    }
+
+
+    function unhash($text) {
+    #
+    # Swap back in all the tags hashed by _HashHTMLBlocks.
+    #
+        return preg_replace_callback('/(.)\x1A[0-9]+\1/',
+            array(&$this, '_unhash_callback'), $text);
+    }
+    function _unhash_callback($matches) {
+        return $this->html_hashes[$matches[0]];
+    }
+
+}
+
+
+#
+# Markdown Extra Parser Class
+#
+
+class MarkdownExtra_Parser extends Markdown_Parser {
+
+    # Prefix for footnote ids.
+    var $fn_id_prefix = "";
+
+    # Optional title attribute for footnote links and backlinks.
+    var $fn_link_title = MARKDOWN_FN_LINK_TITLE;
+    var $fn_backlink_title = MARKDOWN_FN_BACKLINK_TITLE;
+
+    # Optional class attribute for footnote links and backlinks.
+    var $fn_link_class = MARKDOWN_FN_LINK_CLASS;
+    var $fn_backlink_class = MARKDOWN_FN_BACKLINK_CLASS;
+
+    # Predefined abbreviations.
+    var $predef_abbr = array();
+
+
+    function MarkdownExtra_Parser() {
+    #
+    # Constructor function. Initialize the parser object.
+    #
+        # Add extra escapable characters before parent constructor
+        # initialize the table.
+        $this->escape_chars .= ':|';
+
+        # Insert extra document, block, and span transformations.
+        # Parent constructor will do the sorting.
+        $this->document_gamut += array(
+            "doFencedCodeBlocks" => 5,
+            "stripFootnotes"     => 15,
+            "stripAbbreviations" => 25,
+            "appendFootnotes"    => 50,
+            );
+        $this->block_gamut += array(
+            "doFencedCodeBlocks" => 5,
+            "doTables"           => 15,
+            "doDefLists"         => 45,
+            );
+        $this->span_gamut += array(
+            "doFootnotes"        => 5,
+            "doAbbreviations"    => 70,
+            );
+
+        parent::Markdown_Parser();
+    }
+
+
+    # Extra variables used during extra transformations.
+    var $footnotes = array();
+    var $footnotes_ordered = array();
+    var $abbr_desciptions = array();
+    var $abbr_word_re = '';
+
+    # Give the current footnote number.
+    var $footnote_counter = 1;
+
+
+    function setup() {
+    #
+    # Setting up Extra-specific variables.
+    #
+        parent::setup();
+
+        $this->footnotes = array();
+        $this->footnotes_ordered = array();
+        $this->abbr_desciptions = array();
+        $this->abbr_word_re = '';
+        $this->footnote_counter = 1;
+
+        foreach ($this->predef_abbr as $abbr_word => $abbr_desc) {
+            if ($this->abbr_word_re)
+                $this->abbr_word_re .= '|';
+            $this->abbr_word_re .= preg_quote($abbr_word);
+            $this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
+        }
+    }
+
+    function teardown() {
+    #
+    # Clearing Extra-specific variables.
+    #
+        $this->footnotes = array();
+        $this->footnotes_ordered = array();
+        $this->abbr_desciptions = array();
+        $this->abbr_word_re = '';
+
+        parent::teardown();
+    }
+
+
+    ### HTML Block Parser ###
+
+    # Tags that are always treated as block tags:
+    var $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend';
+
+    # Tags treated as block tags only if the opening tag is alone on it's line:
+    var $context_block_tags_re = 'script|noscript|math|ins|del';
+
+    # Tags where markdown="1" default to span mode:
+    var $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address';
+
+    # Tags which must not have their contents modified, no matter where
+    # they appear:
+    var $clean_tags_re = 'script|math';
+
+    # Tags that do not need to be closed.
+    var $auto_close_tags_re = 'hr|img';
+
+
+    function hashHTMLBlocks($text) {
+    #
+    # Hashify HTML Blocks and "clean tags".
+    #
+    # We only want to do this for block-level HTML tags, such as headers,
+    # lists, and tables. That's because we still want to wrap <p>s around
+    # "paragraphs" that are wrapped in non-block-level tags, such as anchors,
+    # phrase emphasis, and spans. The list of tags we're looking for is
+    # hard-coded.
+    #
+    # This works by calling _HashHTMLBlocks_InMarkdown, which then calls
+    # _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1"
+    # attribute is found whitin a tag, _HashHTMLBlocks_InHTML calls back
+    #  _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag.
+    # These two functions are calling each other. It's recursive!
+    #
+        #
+        # Call the HTML-in-Markdown hasher.
+        #
+        list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text);
+
+        return $text;
+    }
+    function _hashHTMLBlocks_inMarkdown($text, $indent = 0,
+                                        $enclosing_tag_re = '', $span = false)
+    {
+    #
+    # Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags.
+    #
+    # *   $indent is the number of space to be ignored when checking for code
+    #     blocks. This is important because if we don't take the indent into
+    #     account, something like this (which looks right) won't work as expected:
+    #
+    #     <div>
+    #         <div markdown="1">
+    #         Hello World.  <-- Is this a Markdown code block or text?
+    #         </div>  <-- Is this a Markdown code block or a real tag?
+    #     <div>
+    #
+    #     If you don't like this, just don't indent the tag on which
+    #     you apply the markdown="1" attribute.
+    #
+    # *   If $enclosing_tag_re is not empty, stops at the first unmatched closing
+    #     tag with that name. Nested tags supported.
+    #
+    # *   If $span is true, text inside must treated as span. So any double
+    #     newline will be replaced by a single newline so that it does not create
+    #     paragraphs.
+    #
+    # Returns an array of that form: ( processed text , remaining text )
+    #
+        if ($text === '') return array('', '');
+
+        # Regex to check for the presense of newlines around a block tag.
+        $newline_before_re = '/(?:^\n?|\n\n)*$/';
+        $newline_after_re =
+            '{
+                ^                       # Start of text following the tag.
+                (?>[ ]*<!--.*?-->)?     # Optional comment.
+                [ ]*\n                  # Must be followed by newline.
+            }xs';
+
+        # Regex to match any tag.
+        $block_tag_re =
+            '{
+                (                   # $2: Capture hole tag.
+                    </?                 # Any opening or closing tag.
+                        (?>             # Tag name.
+                            '.$this->block_tags_re.'            |
+                            '.$this->context_block_tags_re.'    |
+                            '.$this->clean_tags_re.'            |
+                            (?!\s)'.$enclosing_tag_re.'
+                        )
+                        (?:
+                            (?=[\s"\'/a-zA-Z0-9])   # Allowed characters after tag name.
+                            (?>
+                                ".*?"       |   # Double quotes (can contain `>`)
+                                \'.*?\'     |   # Single quotes (can contain `>`)
+                                .+?             # Anything but quotes and `>`.
+                            )*?
+                        )?
+                    >                   # End of tag.
+                |
+                    <!--    .*?     --> # HTML Comment
+                |
+                    <\?.*?\?> | <%.*?%> # Processing instruction
+                |
+                    <!\[CDATA\[.*?\]\]> # CData Block
+                |
+                    # Code span marker
+                    `+
+                '. ( !$span ? ' # If not in span.
+                |
+                    # Indented code block
+                    (?> ^[ ]*\n? | \n[ ]*\n )
+                    [ ]{'.($indent+4).'}[^\n]* \n
+                    (?>
+                        (?: [ ]{'.($indent+4).'}[^\n]* | [ ]* ) \n
+                    )*
+                |
+                    # Fenced code block marker
+                    (?> ^ | \n )
+                    [ ]{'.($indent).'}~~~+[ ]*\n
+                ' : '' ). ' # End (if not is span).
+                )
+            }xs';
+
+
+        $depth = 0;     # Current depth inside the tag tree.
+        $parsed = "";   # Parsed text that will be returned.
+
+        #
+        # Loop through every tag until we find the closing tag of the parent
+        # or loop until reaching the end of text if no parent tag specified.
+        #
+        do {
+            #
+            # Split the text using the first $tag_match pattern found.
+            # Text before  pattern will be first in the array, text after
+            # pattern will be at the end, and between will be any catches made
+            # by the pattern.
+            #
+            $parts = preg_split($block_tag_re, $text, 2,
+                                PREG_SPLIT_DELIM_CAPTURE);
+
+            # If in Markdown span mode, add a empty-string span-level hash
+            # after each newline to prevent triggering any block element.
+            if ($span) {
+                $void = $this->hashPart("", ':');
+                $newline = "$void\n";
+                $parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void;
+            }
+
+            $parsed .= $parts[0]; # Text before current tag.
+
+            # If end of $text has been reached. Stop loop.
+            if (count($parts) < 3) {
+                $text = "";
+                break;
+            }
+
+            $tag  = $parts[1]; # Tag to handle.
+            $text = $parts[2]; # Remaining text after current tag.
+            $tag_re = preg_quote($tag); # For use in a regular expression.
+
+            #
+            # Check for: Code span marker
+            #
+            if ($tag{0} == "`") {
+                # Find corresponding end marker.
+                $tag_re = preg_quote($tag);
+                if (preg_match('{^(?>.+?|\n(?!\n))*?(?<!`)'.$tag_re.'(?!`)}',
+                    $text, $matches))
+                {
+                    # End marker found: pass text unchanged until marker.
+                    $parsed .= $tag . $matches[0];
+                    $text = substr($text, strlen($matches[0]));
+                }
+                else {
+                    # Unmatched marker: just skip it.
+                    $parsed .= $tag;
+                }
+            }
+            #
+            # Check for: Indented code block or fenced code block marker.
+            #
+            else if ($tag{0} == "\n" || $tag{0} == "~") {
+                if ($tag{1} == "\n" || $tag{1} == " ") {
+                    # Indented code block: pass it unchanged, will be handled
+                    # later.
+                    $parsed .= $tag;
+                }
+                else {
+                    # Fenced code block marker: find matching end marker.
+                    $tag_re = preg_quote(trim($tag));
+                    if (preg_match('{^(?>.*\n)+?'.$tag_re.' *\n}', $text,
+                        $matches))
+                    {
+                        # End marker found: pass text unchanged until marker.
+                        $parsed .= $tag . $matches[0];
+                        $text = substr($text, strlen($matches[0]));
+                    }
+                    else {
+                        # No end marker: just skip it.
+                        $parsed .= $tag;
+                    }
+                }
+            }
+            #
+            # Check for: Opening Block level tag or
+            #            Opening Context Block tag (like ins and del)
+            #               used as a block tag (tag is alone on it's line).
+            #
+            else if (preg_match('{^<(?:'.$this->block_tags_re.')\b}', $tag) ||
+                (   preg_match('{^<(?:'.$this->context_block_tags_re.')\b}', $tag) &&
+                    preg_match($newline_before_re, $parsed) &&
+                    preg_match($newline_after_re, $text)    )
+                )
+            {
+                # Need to parse tag and following text using the HTML parser.
+                list($block_text, $text) =
+                    $this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true);
+
+                # Make sure it stays outside of any paragraph by adding newlines.
+                $parsed .= "\n\n$block_text\n\n";
+            }
+            #
+            # Check for: Clean tag (like script, math)
+            #            HTML Comments, processing instructions.
+            #
+            else if (preg_match('{^<(?:'.$this->clean_tags_re.')\b}', $tag) ||
+                $tag{1} == '!' || $tag{1} == '?')
+            {
+                # Need to parse tag and following text using the HTML parser.
+                # (don't check for markdown attribute)
+                list($block_text, $text) =
+                    $this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false);
+
+                $parsed .= $block_text;
+            }
+            #
+            # Check for: Tag with same name as enclosing tag.
+            #
+            else if ($enclosing_tag_re !== '' &&
+                # Same name as enclosing tag.
+                preg_match('{^</?(?:'.$enclosing_tag_re.')\b}', $tag))
+            {
+                #
+                # Increase/decrease nested tag count.
+                #
+                if ($tag{1} == '/')                     $depth--;
+                else if ($tag{strlen($tag)-2} != '/')   $depth++;
+
+                if ($depth < 0) {
+                    #
+                    # Going out of parent element. Clean up and break so we
+                    # return to the calling function.
+                    #
+                    $text = $tag . $text;
+                    break;
+                }
+
+                $parsed .= $tag;
+            }
+            else {
+                $parsed .= $tag;
+            }
+        } while ($depth >= 0);
+
+        return array($parsed, $text);
+    }
+    function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) {
+    #
+    # Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags.
+    #
+    # *   Calls $hash_method to convert any blocks.
+    # *   Stops when the first opening tag closes.
+    # *   $md_attr indicate if the use of the `markdown="1"` attribute is allowed.
+    #     (it is not inside clean tags)
+    #
+    # Returns an array of that form: ( processed text , remaining text )
+    #
+        if ($text === '') return array('', '');
+
+        # Regex to match `markdown` attribute inside of a tag.
+        $markdown_attr_re = '
+            {
+                \s*         # Eat whitespace before the `markdown` attribute
+                markdown
+                \s*=\s*
+                (?>
+                    (["\'])     # $1: quote delimiter
+                    (.*?)       # $2: attribute value
+                    \1          # matching delimiter
+                |
+                    ([^\s>]*)   # $3: unquoted attribute value
+                )
+                ()              # $4: make $3 always defined (avoid warnings)
+            }xs';
+
+        # Regex to match any tag.
+        $tag_re = '{
+                (                   # $2: Capture hole tag.
+                    </?                 # Any opening or closing tag.
+                        [\w:$]+         # Tag name.
+                        (?:
+                            (?=[\s"\'/a-zA-Z0-9])   # Allowed characters after tag name.
+                            (?>
+                                ".*?"       |   # Double quotes (can contain `>`)
+                                \'.*?\'     |   # Single quotes (can contain `>`)
+                                .+?             # Anything but quotes and `>`.
+                            )*?
+                        )?
+                    >                   # End of tag.
+                |
+                    <!--    .*?     --> # HTML Comment
+                |
+                    <\?.*?\?> | <%.*?%> # Processing instruction
+                |
+                    <!\[CDATA\[.*?\]\]> # CData Block
+                )
+            }xs';
+
+        $original_text = $text;     # Save original text in case of faliure.
+
+        $depth      = 0;    # Current depth inside the tag tree.
+        $block_text = "";   # Temporary text holder for current text.
+        $parsed     = "";   # Parsed text that will be returned.
+
+        #
+        # Get the name of the starting tag.
+        # (This pattern makes $base_tag_name_re safe without quoting.)
+        #
+        if (preg_match('/^<([\w:$]*)\b/', $text, $matches))
+            $base_tag_name_re = $matches[1];
+
+        #
+        # Loop through every tag until we find the corresponding closing tag.
+        #
+        do {
+            #
+            # Split the text using the first $tag_match pattern found.
+            # Text before  pattern will be first in the array, text after
+            # pattern will be at the end, and between will be any catches made
+            # by the pattern.
+            #
+            $parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
+
+            if (count($parts) < 3) {
+                #
+                # End of $text reached with unbalenced tag(s).
+                # In that case, we return original text unchanged and pass the
+                # first character as filtered to prevent an infinite loop in the
+                # parent function.
+                #
+                return array($original_text{0}, substr($original_text, 1));
+            }
+
+            $block_text .= $parts[0]; # Text before current tag.
+            $tag         = $parts[1]; # Tag to handle.
+            $text        = $parts[2]; # Remaining text after current tag.
+
+            #
+            # Check for: Auto-close tag (like <hr/>)
+            #            Comments and Processing Instructions.
+            #
+            if (preg_match('{^</?(?:'.$this->auto_close_tags_re.')\b}', $tag) ||
+                $tag{1} == '!' || $tag{1} == '?')
+            {
+                # Just add the tag to the block as if it was text.
+                $block_text .= $tag;
+            }
+            else {
+                #
+                # Increase/decrease nested tag count. Only do so if
+                # the tag's name match base tag's.
+                #
+                if (preg_match('{^</?'.$base_tag_name_re.'\b}', $tag)) {
+                    if ($tag{1} == '/')                     $depth--;
+                    else if ($tag{strlen($tag)-2} != '/')   $depth++;
+                }
+
+                #
+                # Check for `markdown="1"` attribute and handle it.
+                #
+                if ($md_attr &&
+                    preg_match($markdown_attr_re, $tag, $attr_m) &&
+                    preg_match('/^1|block|span$/', $attr_m[2] . $attr_m[3]))
+                {
+                    # Remove `markdown` attribute from opening tag.
+                    $tag = preg_replace($markdown_attr_re, '', $tag);
+
+                    # Check if text inside this tag must be parsed in span mode.
+                    $this->mode = $attr_m[2] . $attr_m[3];
+                    $span_mode = $this->mode == 'span' || $this->mode != 'block' &&
+                        preg_match('{^<(?:'.$this->contain_span_tags_re.')\b}', $tag);
+
+                    # Calculate indent before tag.
+                    if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) {
+                        $strlen = $this->utf8_strlen;
+                        $indent = $strlen($matches[1], 'UTF-8');
+                    } else {
+                        $indent = 0;
+                    }
+
+                    # End preceding block with this tag.
+                    $block_text .= $tag;
+                    $parsed .= $this->$hash_method($block_text);
+
+                    # Get enclosing tag name for the ParseMarkdown function.
+                    # (This pattern makes $tag_name_re safe without quoting.)
+                    preg_match('/^<([\w:$]*)\b/', $tag, $matches);
+                    $tag_name_re = $matches[1];
+
+                    # Parse the content using the HTML-in-Markdown parser.
+                    list ($block_text, $text)
+                        = $this->_hashHTMLBlocks_inMarkdown($text, $indent,
+                            $tag_name_re, $span_mode);
+
+                    # Outdent markdown text.
+                    if ($indent > 0) {
+                        $block_text = preg_replace("/^[ ]{1,$indent}/m", "",
+                                                    $block_text);
+                    }
+
+                    # Append tag content to parsed text.
+                    if (!$span_mode)    $parsed .= "\n\n$block_text\n\n";
+                    else                $parsed .= "$block_text";
+
+                    # Start over a new block.
+                    $block_text = "";
+                }
+                else $block_text .= $tag;
+            }
+
+        } while ($depth > 0);
+
+        #
+        # Hash last block text that wasn't processed inside the loop.
+        #
+        $parsed .= $this->$hash_method($block_text);
+
+        return array($parsed, $text);
+    }
+
+
+    function hashClean($text) {
+    #
+    # Called whenever a tag must be hashed when a function insert a "clean" tag
+    # in $text, it pass through this function and is automaticaly escaped,
+    # blocking invalid nested overlap.
+    #
+        return $this->hashPart($text, 'C');
+    }
+
+
+    function doHeaders($text) {
+    #
+    # Redefined to add id attribute support.
+    #
+        # Setext-style headers:
+        #     Header 1  {#header1}
+        #     ========
+        #
+        #     Header 2  {#header2}
+        #     --------
+        #
+        $text = preg_replace_callback(
+            '{
+                (^.+?)                              # $1: Header text
+                (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})?    # $2: Id attribute
+                [ ]*\n(=+|-+)[ ]*\n+                # $3: Header footer
+            }mx',
+            array(&$this, '_doHeaders_callback_setext'), $text);
+
+        # atx-style headers:
+        #   # Header 1        {#header1}
+        #   ## Header 2       {#header2}
+        #   ## Header 2 with closing hashes ##  {#header3}
+        #   ...
+        #   ###### Header 6   {#header2}
+        #
+        $text = preg_replace_callback('{
+                ^(\#{1,6})  # $1 = string of #\'s
+                [ ]*
+                (.+?)       # $2 = Header text
+                [ ]*
+                \#*         # optional closing #\'s (not counted)
+                (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? # id attribute
+                [ ]*
+                \n+
+            }xm',
+            array(&$this, '_doHeaders_callback_atx'), $text);
+
+        return $text;
+    }
+    function _doHeaders_attr($attr) {
+        if (empty($attr))  return "";
+        return " id=\"$attr\"";
+    }
+    function _doHeaders_callback_setext($matches) {
+        if ($matches[3] == '-' && preg_match('{^- }', $matches[1]))
+            return $matches[0];
+        $level = $matches[3]{0} == '=' ? 1 : 2;
+        $attr  = $this->_doHeaders_attr($id =& $matches[2]);
+        $block = "<h$level$attr>".$this->runSpanGamut($matches[1])."</h$level>";
+        return "\n" . $this->hashBlock($block) . "\n\n";
+    }
+    function _doHeaders_callback_atx($matches) {
+        $level = strlen($matches[1]);
+        $attr  = $this->_doHeaders_attr($id =& $matches[3]);
+        $block = "<h$level$attr>".$this->runSpanGamut($matches[2])."</h$level>";
+        return "\n" . $this->hashBlock($block) . "\n\n";
+    }
+
+
+    function doTables($text) {
+    #
+    # Form HTML tables.
+    #
+        $less_than_tab = $this->tab_width - 1;
+        #
+        # Find tables with leading pipe.
+        #
+        #   | Header 1 | Header 2
+        #   | -------- | --------
+        #   | Cell 1   | Cell 2
+        #   | Cell 3   | Cell 4
+        #
+        $text = preg_replace_callback('
+            {
+                ^                           # Start of a line
+                [ ]{0,'.$less_than_tab.'}   # Allowed whitespace.
+                [|]                         # Optional leading pipe (present)
+                (.+) \n                     # $1: Header row (at least one pipe)
+
+                [ ]{0,'.$less_than_tab.'}   # Allowed whitespace.
+                [|] ([ ]*[-:]+[-| :]*) \n   # $2: Header underline
+
+                (                           # $3: Cells
+                    (?>
+                        [ ]*                # Allowed whitespace.
+                        [|] .* \n           # Row content.
+                    )*
+                )
+                (?=\n|\Z)                   # Stop at final double newline.
+            }xm',
+            array(&$this, '_doTable_leadingPipe_callback'), $text);
+
+        #
+        # Find tables without leading pipe.
+        #
+        #   Header 1 | Header 2
+        #   -------- | --------
+        #   Cell 1   | Cell 2
+        #   Cell 3   | Cell 4
+        #
+        $text = preg_replace_callback('
+            {
+                ^                           # Start of a line
+                [ ]{0,'.$less_than_tab.'}   # Allowed whitespace.
+                (\S.*[|].*) \n              # $1: Header row (at least one pipe)
+
+                [ ]{0,'.$less_than_tab.'}   # Allowed whitespace.
+                ([-:]+[ ]*[|][-| :]*) \n    # $2: Header underline
+
+                (                           # $3: Cells
+                    (?>
+                        .* [|] .* \n        # Row content
+                    )*
+                )
+                (?=\n|\Z)                   # Stop at final double newline.
+            }xm',
+            array(&$this, '_DoTable_callback'), $text);
+
+        return $text;
+    }
+    function _doTable_leadingPipe_callback($matches) {
+        $head       = $matches[1];
+        $underline  = $matches[2];
+        $content    = $matches[3];
+
+        # Remove leading pipe for each row.
+        $content    = preg_replace('/^ *[|]/m', '', $content);
+
+        return $this->_doTable_callback(array($matches[0], $head, $underline, $content));
+    }
+    function _doTable_callback($matches) {
+        $head       = $matches[1];
+        $underline  = $matches[2];
+        $content    = $matches[3];
+
+        # Remove any tailing pipes for each line.
+        $head       = preg_replace('/[|] *$/m', '', $head);
+        $underline  = preg_replace('/[|] *$/m', '', $underline);
+        $content    = preg_replace('/[|] *$/m', '', $content);
+
+        # Reading alignement from header underline.
+        $separators = preg_split('/ *[|] */', $underline);
+        foreach ($separators as $n => $s) {
+            if (preg_match('/^ *-+: *$/', $s))      $attr[$n] = ' align="right"';
+            else if (preg_match('/^ *:-+: *$/', $s))$attr[$n] = ' align="center"';
+            else if (preg_match('/^ *:-+ *$/', $s)) $attr[$n] = ' align="left"';
+            else                                    $attr[$n] = '';
+        }
+
+        # Parsing span elements, including code spans, character escapes,
+        # and inline HTML tags, so that pipes inside those gets ignored.
+        $head       = $this->parseSpan($head);
+        $headers    = preg_split('/ *[|] */', $head);
+        $col_count  = count($headers);
+
+        # Write column headers.
+        $text = "<table>\n";
+        $text .= "<thead>\n";
+        $text .= "<tr>\n";
+        foreach ($headers as $n => $header)
+            $text .= "  <th$attr[$n]>".$this->runSpanGamut(trim($header))."</th>\n";
+        $text .= "</tr>\n";
+        $text .= "</thead>\n";
+
+        # Split content by row.
+        $rows = explode("\n", trim($content, "\n"));
+
+        $text .= "<tbody>\n";
+        foreach ($rows as $row) {
+            # Parsing span elements, including code spans, character escapes,
+            # and inline HTML tags, so that pipes inside those gets ignored.
+            $row = $this->parseSpan($row);
+
+            # Split row by cell.
+            $row_cells = preg_split('/ *[|] */', $row, $col_count);
+            $row_cells = array_pad($row_cells, $col_count, '');
+
+            $text .= "<tr>\n";
+            foreach ($row_cells as $n => $cell)
+                $text .= "  <td$attr[$n]>".$this->runSpanGamut(trim($cell))."</td>\n";
+            $text .= "</tr>\n";
+        }
+        $text .= "</tbody>\n";
+        $text .= "</table>";
+
+        return $this->hashBlock($text) . "\n";
+    }
+
+
+    function doDefLists($text) {
+    #
+    # Form HTML definition lists.
+    #
+        $less_than_tab = $this->tab_width - 1;
+
+        # Re-usable pattern to match any entire dl list:
+        $whole_list_re = '(?>
+            (                               # $1 = whole list
+              (                             # $2
+                [ ]{0,'.$less_than_tab.'}
+                ((?>.*\S.*\n)+)             # $3 = defined term
+                \n?
+                [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
+              )
+              (?s:.+?)
+              (                             # $4
+                  \z
+                |
+                  \n{2,}
+                  (?=\S)
+                  (?!                       # Negative lookahead for another term
+                    [ ]{0,'.$less_than_tab.'}
+                    (?: \S.*\n )+?          # defined term
+                    \n?
+                    [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
+                  )
+                  (?!                       # Negative lookahead for another definition
+                    [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
+                  )
+              )
+            )
+        )'; // mx
+
+        $text = preg_replace_callback('{
+                (?>\A\n?|(?<=\n\n))
+                '.$whole_list_re.'
+            }mx',
+            array(&$this, '_doDefLists_callback'), $text);
+
+        return $text;
+    }
+    function _doDefLists_callback($matches) {
+        # Re-usable patterns to match list item bullets and number markers:
+        $list = $matches[1];
+
+        # Turn double returns into triple returns, so that we can make a
+        # paragraph for the last item in a list, if necessary:
+        $result = trim($this->processDefListItems($list));
+        $result = "<dl>\n" . $result . "\n</dl>";
+        return $this->hashBlock($result) . "\n\n";
+    }
+
+
+    function processDefListItems($list_str) {
+    #
+    #   Process the contents of a single definition list, splitting it
+    #   into individual term and definition list items.
+    #
+        $less_than_tab = $this->tab_width - 1;
+
+        # trim trailing blank lines:
+        $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
+
+        # Process definition terms.
+        $list_str = preg_replace_callback('{
+            (?>\A\n?|\n\n+)                 # leading line
+            (                               # definition terms = $1
+                [ ]{0,'.$less_than_tab.'}   # leading whitespace
+                (?![:][ ]|[ ])              # negative lookahead for a definition
+                                            #   mark (colon) or more whitespace.
+                (?> \S.* \n)+?              # actual term (not whitespace).
+            )
+            (?=\n?[ ]{0,3}:[ ])             # lookahead for following line feed
+                                            #   with a definition mark.
+            }xm',
+            array(&$this, '_processDefListItems_callback_dt'), $list_str);
+
+        # Process actual definitions.
+        $list_str = preg_replace_callback('{
+            \n(\n+)?                        # leading line = $1
+            (                               # marker space = $2
+                [ ]{0,'.$less_than_tab.'}   # whitespace before colon
+                [:][ ]+                     # definition mark (colon)
+            )
+            ((?s:.+?))                      # definition text = $3
+            (?= \n+                         # stop at next definition mark,
+                (?:                         # next term or end of text
+                    [ ]{0,'.$less_than_tab.'} [:][ ]    |
+                    <dt> | \z
+                )
+            )
+            }xm',
+            array(&$this, '_processDefListItems_callback_dd'), $list_str);
+
+        return $list_str;
+    }
+    function _processDefListItems_callback_dt($matches) {
+        $terms = explode("\n", trim($matches[1]));
+        $text = '';
+        foreach ($terms as $term) {
+            $term = $this->runSpanGamut(trim($term));
+            $text .= "\n<dt>" . $term . "</dt>";
+        }
+        return $text . "\n";
+    }
+    function _processDefListItems_callback_dd($matches) {
+        $leading_line   = $matches[1];
+        $marker_space   = $matches[2];
+        $def            = $matches[3];
+
+        if ($leading_line || preg_match('/\n{2,}/', $def)) {
+            # Replace marker with the appropriate whitespace indentation
+            $def = str_repeat(' ', strlen($marker_space)) . $def;
+            $def = $this->runBlockGamut($this->outdent($def . "\n\n"));
+            $def = "\n". $def ."\n";
+        }
+        else {
+            $def = rtrim($def);
+            $def = $this->runSpanGamut($this->outdent($def));
+        }
+
+        return "\n<dd>" . $def . "</dd>\n";
+    }
+
+
+    function doFencedCodeBlocks($text) {
+    #
+    # Adding the fenced code block syntax to regular Markdown:
+    #
+    # ~~~
+    # Code block
+    # ~~~
+    #
+        $less_than_tab = $this->tab_width;
+
+        $text = preg_replace_callback('{
+                (?:\n|\A)
+                # 1: Opening marker
+                (
+                    ~{3,} # Marker: three tilde or more.
+                )
+                [ ]* \n # Whitespace and newline following marker.
+
+                # 2: Content
+                (
+                    (?>
+                        (?!\1 [ ]* \n)  # Not a closing marker.
+                        .*\n+
+                    )+
+                )
+
+                # Closing marker.
+                \1 [ ]* \n
+            }xm',
+            array(&$this, '_doFencedCodeBlocks_callback'), $text);
+
+        return $text;
+    }
+    function _doFencedCodeBlocks_callback($matches) {
+        $codeblock = $matches[2];
+        $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
+        $codeblock = preg_replace_callback('/^\n+/',
+            array(&$this, '_doFencedCodeBlocks_newlines'), $codeblock);
+        $codeblock = "<pre><code>$codeblock</code></pre>";
+        return "\n\n".$this->hashBlock($codeblock)."\n\n";
+    }
+    function _doFencedCodeBlocks_newlines($matches) {
+        return str_repeat("<br$this->empty_element_suffix",
+            strlen($matches[0]));
+    }
+
+
+    #
+    # Redefining emphasis markers so that emphasis by underscore does not
+    # work in the middle of a word.
+    #
+    var $em_relist = array(
+        ''  => '(?:(?<!\*)\*(?!\*)|(?<![a-zA-Z0-9_])_(?!_))(?=\S)(?![.,:;]\s)',
+        '*' => '(?<=\S)(?<!\*)\*(?!\*)',
+        '_' => '(?<=\S)(?<!_)_(?![a-zA-Z0-9_])',
+        );
+    var $strong_relist = array(
+        ''   => '(?:(?<!\*)\*\*(?!\*)|(?<![a-zA-Z0-9_])__(?!_))(?=\S)(?![.,:;]\s)',
+        '**' => '(?<=\S)(?<!\*)\*\*(?!\*)',
+        '__' => '(?<=\S)(?<!_)__(?![a-zA-Z0-9_])',
+        );
+    var $em_strong_relist = array(
+        ''    => '(?:(?<!\*)\*\*\*(?!\*)|(?<![a-zA-Z0-9_])___(?!_))(?=\S)(?![.,:;]\s)',
+        '***' => '(?<=\S)(?<!\*)\*\*\*(?!\*)',
+        '___' => '(?<=\S)(?<!_)___(?![a-zA-Z0-9_])',
+        );
+
+
+    function formParagraphs($text) {
+    #
+    #   Params:
+    #       $text - string to process with html <p> tags
+    #
+        # Strip leading and trailing lines:
+        $text = preg_replace('/\A\n+|\n+\z/', '', $text);
+
+        $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
+
+        #
+        # Wrap <p> tags and unhashify HTML blocks
+        #
+        foreach ($grafs as $key => $value) {
+            $value = trim($this->runSpanGamut($value));
+
+            # Check if this should be enclosed in a paragraph.
+            # Clean tag hashes & block tag hashes are left alone.
+            $is_p = !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value);
+
+            if ($is_p) {
+                $value = "<p>$value</p>";
+            }
+            $grafs[$key] = $value;
+        }
+
+        # Join grafs in one text, then unhash HTML tags.
+        $text = implode("\n\n", $grafs);
+
+        # Finish by removing any tag hashes still present in $text.
+        $text = $this->unhash($text);
+
+        return $text;
+    }
+
+
+    ### Footnotes
+
+    function stripFootnotes($text) {
+    #
+    # Strips link definitions from text, stores the URLs and titles in
+    # hash references.
+    #
+        $less_than_tab = $this->tab_width - 1;
+
+        # Link defs are in the form: [^id]: url "optional title"
+        $text = preg_replace_callback('{
+            ^[ ]{0,'.$less_than_tab.'}\[\^(.+?)\][ ]?:  # note_id = $1
+              [ ]*
+              \n?                   # maybe *one* newline
+            (                       # text = $2 (no blank lines allowed)
+                (?:
+                    .+              # actual text
+                |
+                    \n              # newlines but
+                    (?!\[\^.+?\]:\s)# negative lookahead for footnote marker.
+                    (?!\n+[ ]{0,3}\S)# ensure line is not blank and followed
+                                    # by non-indented content
+                )*
+            )
+            }xm',
+            array(&$this, '_stripFootnotes_callback'),
+            $text);
+        return $text;
+    }
+    function _stripFootnotes_callback($matches) {
+        $note_id = $this->fn_id_prefix . $matches[1];
+        $this->footnotes[$note_id] = $this->outdent($matches[2]);
+        return ''; # String that will replace the block
+    }
+
+
+    function doFootnotes($text) {
+    #
+    # Replace footnote references in $text [^id] with a special text-token
+    # which will be replaced by the actual footnote marker in appendFootnotes.
+    #
+        if (!$this->in_anchor) {
+            $text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text);
+        }
+        return $text;
+    }
+
+
+    function appendFootnotes($text) {
+    #
+    # Append footnote list to text.
+    #
+        $text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
+            array(&$this, '_appendFootnotes_callback'), $text);
+
+        if (!empty($this->footnotes_ordered)) {
+            $text .= "\n\n";
+            $text .= "<div class=\"footnotes\">\n";
+            $text .= "<hr". MARKDOWN_EMPTY_ELEMENT_SUFFIX ."\n";
+            $text .= "<ol>\n\n";
+
+            $attr = " rev=\"footnote\"";
+            if ($this->fn_backlink_class != "") {
+                $class = $this->fn_backlink_class;
+                $class = $this->encodeAttribute($class);
+                $attr .= " class=\"$class\"";
+            }
+            if ($this->fn_backlink_title != "") {
+                $title = $this->fn_backlink_title;
+                $title = $this->encodeAttribute($title);
+                $attr .= " title=\"$title\"";
+            }
+            $num = 0;
+
+            while (!empty($this->footnotes_ordered)) {
+                $footnote = reset($this->footnotes_ordered);
+                $note_id = key($this->footnotes_ordered);
+                unset($this->footnotes_ordered[$note_id]);
+
+                $footnote .= "\n"; # Need to append newline before parsing.
+                $footnote = $this->runBlockGamut("$footnote\n");
+                $footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
+                    array(&$this, '_appendFootnotes_callback'), $footnote);
+
+                $attr = str_replace("%%", ++$num, $attr);
+                $note_id = $this->encodeAttribute($note_id);
+
+                # Add backlink to last paragraph; create new paragraph if needed.
+                $backlink = "<a href=\"#fnref:$note_id\"$attr>&#8617;</a>";
+                if (preg_match('{</p>$}', $footnote)) {
+                    $footnote = substr($footnote, 0, -4) . "&#160;$backlink</p>";
+                } else {
+                    $footnote .= "\n\n<p>$backlink</p>";
+                }
+
+                $text .= "<li id=\"fn:$note_id\">\n";
+                $text .= $footnote . "\n";
+                $text .= "</li>\n\n";
+            }
+
+            $text .= "</ol>\n";
+            $text .= "</div>";
+        }
+        return $text;
+    }
+    function _appendFootnotes_callback($matches) {
+        $node_id = $this->fn_id_prefix . $matches[1];
+
+        # Create footnote marker only if it has a corresponding footnote *and*
+        # the footnote hasn't been used by another marker.
+        if (isset($this->footnotes[$node_id])) {
+            # Transfert footnote content to the ordered list.
+            $this->footnotes_ordered[$node_id] = $this->footnotes[$node_id];
+            unset($this->footnotes[$node_id]);
+
+            $num = $this->footnote_counter++;
+            $attr = " rel=\"footnote\"";
+            if ($this->fn_link_class != "") {
+                $class = $this->fn_link_class;
+                $class = $this->encodeAttribute($class);
+                $attr .= " class=\"$class\"";
+            }
+            if ($this->fn_link_title != "") {
+                $title = $this->fn_link_title;
+                $title = $this->encodeAttribute($title);
+                $attr .= " title=\"$title\"";
+            }
+
+            $attr = str_replace("%%", $num, $attr);
+            $node_id = $this->encodeAttribute($node_id);
+
+            return
+                "<sup id=\"fnref:$node_id\">".
+                "<a href=\"#fn:$node_id\"$attr>$num</a>".
+                "</sup>";
+        }
+
+        return "[^".$matches[1]."]";
+    }
+
+
+    ### Abbreviations ###
+
+    function stripAbbreviations($text) {
+    #
+    # Strips abbreviations from text, stores titles in hash references.
+    #
+        $less_than_tab = $this->tab_width - 1;
+
+        # Link defs are in the form: [id]*: url "optional title"
+        $text = preg_replace_callback('{
+            ^[ ]{0,'.$less_than_tab.'}\*\[(.+?)\][ ]?:  # abbr_id = $1
+            (.*)                    # text = $2 (no blank lines allowed)
+            }xm',
+            array(&$this, '_stripAbbreviations_callback'),
+            $text);
+        return $text;
+    }
+    function _stripAbbreviations_callback($matches) {
+        $abbr_word = $matches[1];
+        $abbr_desc = $matches[2];
+        if ($this->abbr_word_re)
+            $this->abbr_word_re .= '|';
+        $this->abbr_word_re .= preg_quote($abbr_word);
+        $this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
+        return ''; # String that will replace the block
+    }
+
+
+    function doAbbreviations($text) {
+    #
+    # Find defined abbreviations in text and wrap them in <abbr> elements.
+    #
+        if ($this->abbr_word_re) {
+            // cannot use the /x modifier because abbr_word_re may
+            // contain significant spaces:
+            $text = preg_replace_callback('{'.
+                '(?<![\w\x1A])'.
+                '(?:'.$this->abbr_word_re.')'.
+                '(?![\w\x1A])'.
+                '}',
+                array(&$this, '_doAbbreviations_callback'), $text);
+        }
+        return $text;
+    }
+    function _doAbbreviations_callback($matches) {
+        $abbr = $matches[0];
+        if (isset($this->abbr_desciptions[$abbr])) {
+            $desc = $this->abbr_desciptions[$abbr];
+            if (empty($desc)) {
+                return $this->hashPart("<abbr>$abbr</abbr>");
+            } else {
+                $desc = $this->encodeAttribute($desc);
+                return $this->hashPart("<abbr title=\"$desc\">$abbr</abbr>");
+            }
+        } else {
+            return $matches[0];
+        }
+    }
+
+}
+
+
+/*
+
+PHP Markdown Extra
+==================
+
+Description
+-----------
+
+This is a PHP port of the original Markdown formatter written in Perl
+by John Gruber. This special "Extra" version of PHP Markdown features
+further enhancements to the syntax for making additional constructs
+such as tables and definition list.
+
+Markdown is a text-to-HTML filter; it translates an easy-to-read /
+easy-to-write structured text format into HTML. Markdown's text format
+is most similar to that of plain text email, and supports features such
+as headers, *emphasis*, code blocks, blockquotes, and links.
+
+Markdown's syntax is designed not as a generic markup language, but
+specifically to serve as a front-end to (X)HTML. You can use span-level
+HTML tags anywhere in a Markdown document, and you can use block level
+HTML tags (like <div> and <table> as well).
+
+For more information about Markdown's syntax, see:
+
+<http://daringfireball.net/projects/markdown/>
+
+
+Bugs
+----
+
+To file bug reports please send email to:
+
+<michel.fortin@michelf.com>
+
+Please include with your report: (1) the example input; (2) the output you
+expected; (3) the output Markdown actually produced.
+
+
+Version History
+---------------
+
+See the readme file for detailed release notes for this version.
+
+
+Copyright and License
+---------------------
+
+PHP Markdown & Extra
+Copyright (c) 2004-2008 Michel Fortin
+<http://www.michelf.com/>
+All rights reserved.
+
+Based on Markdown
+Copyright (c) 2003-2006 John Gruber
+<http://daringfireball.net/>
+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 "Markdown" 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.
+
+*/
+?>
\ No newline at end of file
diff --git a/examples/includes/PHP-SmartyPants-1.5.1e/PHP SmartyPants Readme.txt b/examples/includes/PHP-SmartyPants-1.5.1e/PHP SmartyPants Readme.txt
new file mode 100644 (file)
index 0000000..39d36dd
--- /dev/null
@@ -0,0 +1,394 @@
+PHP SmartyPants
+===============
+
+Version 1.5.1e - Fri 9 Dec 2005
+
+by Michel Fortin
+<http://www.michelf.com/>
+
+based on work by John Gruber
+<http://daringfireball.net/>
+
+
+Introduction
+------------
+
+PHP SmartyPants is a port to PHP of the original SmartyPants written
+in Perl by John Gruber.
+
+PHP SmartyPants is a free web publishing plug-in for WordPress and
+Smarty template engine that easily translates plain ASCII punctuation
+characters into "smart" typographic punctuation HTML entities.
+SmartyPants can also be invoked as a standalone PHP function.
+
+SmartyPants can perform the following transformations:
+
+*   Straight quotes (`"` and `'`) into "curly" quote HTML entities
+*   Backtick-style quotes (` ``like this'' `) into "curly" quote HTML
+    entities
+*   Dashes (`--` and `---`) into en- and em-dash entities
+*   Three consecutive dots (`...`) into an ellipsis entity
+
+This means you can write, edit, and save using plain old ASCII straight
+quotes, plain dashes, and plain dots, but your published posts (and
+final HTML output) will appear with smart quotes, em-dashes, and proper
+ellipses.
+
+SmartyPants does not modify characters within `<pre>`, `<code>`,
+`<kbd>`, or `<script>` tag blocks. Typically, these tags are used to
+display text where smart quotes and other "smart punctuation" would not
+be appropriate, such as source code or example markup.
+
+
+### Backslash Escapes ###
+
+If you need to use literal straight quotes (or plain hyphens and
+periods), SmartyPants accepts the following backslash escape sequences
+to force non-smart punctuation. It does so by transforming the escape
+sequence into a decimal-encoded HTML entity:
+
+
+    Escape  Value  Character
+    ------  -----  ---------
+      \\    &#92;    \
+      \"    &#34;    "
+      \'    &#39;    '
+      \.    &#46;    .
+      \-    &#45;    -
+      \`    &#96;    `
+
+
+This is useful, for example, when you want to use straight quotes as
+foot and inch marks:
+
+    6\'2\" tall
+
+translates into:
+
+    6&#39;2&#34; tall
+
+in SmartyPants's HTML output. Which, when rendered by a web browser,
+looks like:
+
+    6'2" tall
+
+
+Installation and Requirement
+----------------------------
+
+PHP SmartyPants require PHP version 4.0.5 or later.
+
+
+### WordPress ###
+
+WordPress already include a filter called "Texturize" with the same
+goal as SmartyPants. You could still find some usefulness to
+PHP SmartyPants if you are not happy enough with the standard algorithm.
+
+PHP SmartyPants works with [WordPress][wp], version 1.2 or later.
+
+[wp]: http://wordpress.org/
+
+1.  To use PHP SmartyPants with WordPress, place the "smartypants.php"
+    file in the "plugins" folder. This folder is hidden inside
+    "wp-content" at the root of your site:
+
+        (site home)/wp-content/plugins/smartypants.php
+
+2.  Activate the plugin with the administrative interface of WordPress.
+    In the "Plugins" section you will now find SmartyPants. To activate
+    the plugin, click on the "Activate" button on the same line than
+    SmartyPants. Your entries will now be filtered by PHP SmartyPants.
+
+Note: It is not possible at this time to apply a different set of
+filters to different entries. All your entries will be filtered by
+PHP SmartyPants if the plugin is active. This is currently a limitation
+of WordPress.
+
+
+### Blosxom ###
+
+SmartyPants works with Blosxom version 2.0 or later.
+
+1.  Rename the "SmartyPants.pl" plug-in to "SmartyPants" (case is
+    important). Movable Type requires plug-ins to have a ".pl"
+    extension; Blosxom forbids it (at least as of this writing).
+
+2.  Copy the "SmartyPants" plug-in file to your Blosxom plug-ins folder.
+    If you're not sure where your Blosxom plug-ins folder is, see the
+    Blosxom documentation for information.
+
+3.  That's it. The entries in your weblog should now automatically have
+    SmartyPants's default transformations applied.
+
+4.  If you wish to configure SmartyPants's behavior, open the
+    "SmartyPants" plug-in, and edit the value of the `$smartypants_attr`
+    configuration variable, located near the top of the script. The
+    default value is 1; see "Options", below, for the full list of
+    supported values.
+
+
+### In your programs ###
+
+You can use PHP SmartyPants easily in your current PHP program. Simply
+include the file and then call the `SmartyPants` function on the text
+you want to convert:
+
+       include_once "smartypants.php";
+       $my_text = SmartyPants($my_text);
+
+
+### With Smarty ###
+
+If your program use the [Smarty][sm] template engine, PHP SmartyPants
+can now be used as a modifier for your templates. Rename
+"smartypants.php" to "modifier.smartypants.php" and put it in your
+smarty plugins folder.
+
+[sm]: http://smarty.php.net/
+
+
+Options and Configuration
+-------------------------
+
+Settings are specified by editing the value of the `$smartypants_attr`
+variable in the "smartypants.php" file. For users of the Smarty template
+engine, the "smartypants" modifier also takes an optional attribute where
+you can specify configuration options, like this:
+`{$var|smartypants:1}` (where "1" is the configuration option).
+
+Numeric values are the easiest way to configure SmartyPants's behavior:
+
+"0"
+    Suppress all transformations. (Do nothing.)
+
+"1"
+    Performs default SmartyPants transformations: quotes (including
+    backticks-style), em-dashes, and ellipses. `--` (dash dash) is
+    used to signify an em-dash; there is no support for en-dashes.
+
+"2"
+    Same as smarty_pants="1", except that it uses the old-school
+    typewriter shorthand for dashes: `--` (dash dash) for en-dashes,
+    `---` (dash dash dash) for em-dashes.
+
+"3"
+    Same as smarty_pants="2", but inverts the shorthand for dashes: `--`
+    (dash dash) for em-dashes, and `---` (dash dash dash) for en-dashes.
+
+"-1"
+    Stupefy mode. Reverses the SmartyPants transformation process,
+    turning the HTML entities produced by SmartyPants into their ASCII
+    equivalents. E.g. `&#8220;` is turned into a simple double-quote
+    (`"`), `&#8212;` is turned into two dashes, etc. This is useful if you
+    wish to suppress smart punctuation in specific pages, such as
+    RSS feeds.
+
+The following single-character attribute values can be combined to
+toggle individual transformations from within the smarty_pants
+attribute. For example, to educate normal quotes and em-dashes, but not
+ellipses or backticks-style quotes:
+
+    $smartypants_attr = "qd";
+
+Or inside a Smarty template:
+
+    {$var|smartypants:"qd"}
+
+"q"
+    Educates normal quote characters: (`"`) and (`'`).
+
+"b"
+    Educates ` ``backticks'' ` double quotes.
+
+"B"
+    Educates backticks-style double quotes and ` `single' ` quotes.
+
+"d"
+    Educates em-dashes.
+
+"D"
+    Educates em-dashes and en-dashes, using old-school typewriter
+    shorthand: (dash dash) for en-dashes, (dash dash dash) for
+    em-dashes.
+
+"i"
+    Educates em-dashes and en-dashes, using inverted old-school
+    typewriter shorthand: (dash dash) for em-dashes, (dash dash dash)
+    for en-dashes.
+
+"e"
+    Educates ellipses.
+
+"w"
+    Translates any instance of `&quot;` into a normal double-quote
+    character. This should be of no interest to most people, but of
+    particular interest to anyone who writes their posts using
+    Dreamweaver, as Dreamweaver inexplicably uses this entity to
+    represent a literal double-quote character. SmartyPants only
+    educates normal quotes, not entities (because ordinarily, entities
+    are used for the explicit purpose of representing the specific
+    character they represent). The "w" option must be used in
+    conjunction with one (or both) of the other quote options ("q" or
+    "b"). Thus, if you wish to apply all SmartyPants transformations
+    (quotes, en- and em-dashes, and ellipses) and also translate
+    `&quot;` entities into regular quotes so SmartyPants can educate
+    them, you should pass the following to the smarty_pants attribute:
+
+        $smartypants_attr = "qDew";
+
+    Inside a Smarty template, this will be:
+
+        {$var|smartypants:"qDew"}
+
+
+Caveats
+-------
+
+### Why You Might Not Want to Use Smart Quotes in Your Weblog ###
+
+For one thing, you might not care.
+
+Most normal, mentally stable individuals do not take notice of proper
+typographic punctuation. Many design and typography nerds, however,
+break out in a nasty rash when they encounter, say, a restaurant sign
+that uses a straight apostrophe to spell "Joe's".
+
+If you're the sort of person who just doesn't care, you might well want
+to continue not caring. Using straight quotes -- and sticking to the
+7-bit ASCII character set in general -- is certainly a simpler way to
+live.
+
+Even if you *do* care about accurate typography, you still might want to
+think twice before educating the quote characters in your weblog. One
+side effect of publishing curly quote HTML entities is that it makes
+your weblog a bit harder for others to quote from using copy-and-paste.
+What happens is that when someone copies text from your blog, the copied
+text contains the 8-bit curly quote characters (as well as the 8-bit
+characters for em-dashes and ellipses, if you use these options). These
+characters are not standard across different text encoding methods,
+which is why they need to be encoded as HTML entities.
+
+People copying text from your weblog, however, may not notice that
+you're using curly quotes, and they'll go ahead and paste the unencoded
+8-bit characters copied from their browser into an email message or
+their own weblog. When pasted as raw "smart quotes", these characters
+are likely to get mangled beyond recognition.
+
+That said, my own opinion is that any decent text editor or email client
+makes it easy to stupefy smart quote characters into their 7-bit
+equivalents, and I don't consider it my problem if you're using an
+indecent text editor or email client.
+
+### Algorithmic Shortcomings ###
+
+One situation in which quotes will get curled the wrong way is when
+apostrophes are used at the start of leading contractions. For example:
+
+    'Twas the night before Christmas.
+
+In the case above, SmartyPants will turn the apostrophe into an opening
+single-quote, when in fact it should be a closing one. I don't think
+this problem can be solved in the general case -- every word processor
+I've tried gets this wrong as well. In such cases, it's best to use the
+proper HTML entity for closing single-quotes (`&#8217;` or `&rsquo;`) by
+hand.
+
+
+Bugs
+----
+
+To file bug reports or feature requests (other than topics listed in the
+Caveats section above) please send email to:
+
+<michel.fortin@michelf.com>
+
+If the bug involves quotes being curled the wrong way, please send
+example text to illustrate.
+
+
+Version History
+---------------
+
+1.5.1e (9 Dec 2005)
+
+*      Corrected a bug that prevented special characters from being
+    escaped.
+
+
+1.5.1d (6 Jun 2005)
+
+*      Correct a small bug in `_TokenizeHTML` where a Doctype declaration
+       was not seen as HTML, making curly quotes inside it.
+
+
+1.5.1c (13 Dec 2004)
+
+*      Changed a regular expression in `_TokenizeHTML` that could lead
+       to a segmentation fault with PHP 4.3.8 on Linux.
+
+
+1.5.1b (6 Sep 2004)
+
+*      Corrected a problem with quotes immediately following a dash
+       with no space between: `Text--"quoted text"--text.`
+
+*      PHP SmartyPants can now be used as a modifier by the Smarty
+       template engine. Rename the file to "modifier.smartypants.php"
+       and put it in your smarty plugins folder.
+
+*      Replaced a lot of spaces characters by tabs, saving about 4 KB.
+
+
+1.5.1a (30 Jun 2004)
+
+*      PHP Markdown and PHP Smartypants now share the same `_TokenizeHTML`
+       function when loaded simultanously.
+
+*      Changed the internals of `_TokenizeHTML` to lower the PHP version
+       requirement to PHP 4.0.5.
+
+
+1.5.1 (6 Jun 2004)
+
+*      Initial release of PHP SmartyPants, based on version 1.5.1 of the
+       original SmartyPants written in Perl.
+
+
+Copyright and License
+---------------------
+
+Copyright (c) 2005 Michel Fortin
+<http://www.michelf.com/>
+All rights reserved.
+
+Copyright (c) 2003-2004 John Gruber
+<http://daringfireball.net/>
+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 "SmartyPants" 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.
diff --git a/examples/includes/PHP-SmartyPants-1.5.1e/smartypants.php b/examples/includes/PHP-SmartyPants-1.5.1e/smartypants.php
new file mode 100644 (file)
index 0000000..cc0dd96
--- /dev/null
@@ -0,0 +1,860 @@
+<?php
+
+#
+# SmartyPants  -  Smart punctuation for web sites
+#
+# by John Gruber
+# <http://daringfireball.net>
+#
+# PHP port by Michel Fortin
+# <http://www.michelf.com/>
+#
+# Copyright (c) 2003-2004 John Gruber
+# Copyright (c) 2004-2005 Michel Fortin
+#
+
+
+global  $SmartyPantsPHPVersion, $SmartyPantsSyntaxVersion,
+        $smartypants_attr, $sp_tags_to_skip;
+
+$SmartyPantsPHPVersion    = '1.5.1e'; # Fru 9 Dec 2005
+$SmartyPantsSyntaxVersion = '1.5.1';  # Fri 12 Mar 2004
+
+
+# Configurable variables:
+$smartypants_attr = "1";  # Change this to configure.
+                          #  1 =>  "--" for em-dashes; no en-dash support
+                          #  2 =>  "---" for em-dashes; "--" for en-dashes
+                          #  3 =>  "--" for em-dashes; "---" for en-dashes
+                          #  See docs for more configuration options.
+
+# Globals:
+$sp_tags_to_skip = '<(/?)(?:pre|code|kbd|script|math)[\s>]';
+
+
+# -- WordPress plugin interface -----------------------------------------------
+/*
+Plugin Name: SmartyPants
+Plugin URI: http://www.michelf.com/projects/php-smartypants/
+Description: SmartyPants is a web publishing utility that translates plain ASCII punctuation characters into &#8220;smart&#8221; typographic punctuation HTML entities. This plugin <strong>replace the default WordPress Texturize algorithm</strong> for the content and the title of your posts, the comments body and author name, and everywhere else Texturize normally apply. Based on the original Perl version by <a href="http://daringfireball.net/">John Gruber</a>.
+Version: 1.5.1e
+Author: Michel Fortin
+Author URI: http://www.michelf.com/
+*/
+if (isset($wp_version)) {
+    # Remove default Texturize filter that would conflict with SmartyPants.
+    remove_filter('category_description', 'wptexturize');
+    remove_filter('list_cats', 'wptexturize');
+    remove_filter('comment_author', 'wptexturize');
+    remove_filter('comment_text', 'wptexturize');
+    remove_filter('single_post_title', 'wptexturize');
+    remove_filter('the_title', 'wptexturize');
+    remove_filter('the_content', 'wptexturize');
+    remove_filter('the_excerpt', 'wptexturize');
+    # Add SmartyPants filter with priority 10 (same as Texturize).
+    add_filter('category_description', 'SmartyPants', 10);
+    add_filter('list_cats', 'SmartyPants', 10);
+    add_filter('comment_author', 'SmartyPants', 10);
+    add_filter('comment_text', 'SmartyPants', 10);
+    add_filter('single_post_title', 'SmartyPants', 10);
+    add_filter('the_title', 'SmartyPants', 10);
+    add_filter('the_content', 'SmartyPants', 10);
+    add_filter('the_excerpt', 'SmartyPants', 10);
+}
+
+# -- Smarty Modifier Interface ------------------------------------------------
+function smarty_modifier_smartypants($text, $attr = NULL) {
+    return SmartyPants($text, $attr);
+}
+
+
+
+function SmartyPants($text, $attr = NULL, $ctx = NULL) {
+    global $smartypants_attr, $sp_tags_to_skip;
+    # Paramaters:
+    $text;   # text to be parsed
+    $attr;   # value of the smart_quotes="" attribute
+    $ctx;    # MT context object (unused)
+    if ($attr == NULL) $attr = $smartypants_attr;
+
+    # Options to specify which transformations to make:
+    $do_stupefy = FALSE;
+    $convert_quot = 0;  # should we translate &quot; entities into normal quotes?
+
+    # Parse attributes:
+    # 0 : do nothing
+    # 1 : set all
+    # 2 : set all, using old school en- and em- dash shortcuts
+    # 3 : set all, using inverted old school en and em- dash shortcuts
+    #
+    # q : quotes
+    # b : backtick quotes (``double'' only)
+    # B : backtick quotes (``double'' and `single')
+    # d : dashes
+    # D : old school dashes
+    # i : inverted old school dashes
+    # e : ellipses
+    # w : convert &quot; entities to " for Dreamweaver users
+
+    if ($attr == "0") {
+        # Do nothing.
+        return $text;
+    }
+    else if ($attr == "1") {
+        # Do everything, turn all options on.
+        $do_quotes    = 1;
+        $do_backticks = 1;
+        $do_dashes    = 1;
+        $do_ellipses  = 1;
+    }
+    else if ($attr == "2") {
+        # Do everything, turn all options on, use old school dash shorthand.
+        $do_quotes    = 1;
+        $do_backticks = 1;
+        $do_dashes    = 2;
+        $do_ellipses  = 1;
+    }
+    else if ($attr == "3") {
+        # Do everything, turn all options on, use inverted old school dash shorthand.
+        $do_quotes    = 1;
+        $do_backticks = 1;
+        $do_dashes    = 3;
+        $do_ellipses  = 1;
+    }
+    else if ($attr == "-1") {
+        # Special "stupefy" mode.
+        $do_stupefy   = 1;
+    }
+    else {
+        $chars = preg_split('//', $attr);
+        foreach ($chars as $c){
+            if      ($c == "q") { $do_quotes    = 1; }
+            else if ($c == "b") { $do_backticks = 1; }
+            else if ($c == "B") { $do_backticks = 2; }
+            else if ($c == "d") { $do_dashes    = 1; }
+            else if ($c == "D") { $do_dashes    = 2; }
+            else if ($c == "i") { $do_dashes    = 3; }
+            else if ($c == "e") { $do_ellipses  = 1; }
+            else if ($c == "w") { $convert_quot = 1; }
+            else {
+                # Unknown attribute option, ignore.
+            }
+        }
+    }
+
+    $tokens = _TokenizeHTML($text);
+    $result = '';
+    $in_pre = 0;  # Keep track of when we're inside <pre> or <code> tags.
+
+    $prev_token_last_char = "";     # This is a cheat, used to get some context
+                                    # for one-character tokens that consist of
+                                    # just a quote char. What we do is remember
+                                    # the last character of the previous text
+                                    # token, to use as context to curl single-
+                                    # character quote tokens correctly.
+
+    foreach ($tokens as $cur_token) {
+        if ($cur_token[0] == "tag") {
+            # Don't mess with quotes inside tags.
+            $result .= $cur_token[1];
+            if (preg_match("@$sp_tags_to_skip@", $cur_token[1], $matches)) {
+                $in_pre = isset($matches[1]) && $matches[1] == '/' ? 0 : 1;
+            }
+        } else {
+            $t = $cur_token[1];
+            $last_char = substr($t, -1); # Remember last char of this token before processing.
+            if (! $in_pre) {
+                $t = ProcessEscapes($t);
+
+                if ($convert_quot) {
+                    $t = preg_replace('/&quot;/', '"', $t);
+                }
+
+                if ($do_dashes) {
+                    if ($do_dashes == 1) $t = EducateDashes($t);
+                    if ($do_dashes == 2) $t = EducateDashesOldSchool($t);
+                    if ($do_dashes == 3) $t = EducateDashesOldSchoolInverted($t);
+                }
+
+                if ($do_ellipses) $t = EducateEllipses($t);
+
+                # Note: backticks need to be processed before quotes.
+                if ($do_backticks) {
+                    $t = EducateBackticks($t);
+                    if ($do_backticks == 2) $t = EducateSingleBackticks($t);
+                }
+
+                if ($do_quotes) {
+                    if ($t == "'") {
+                        # Special case: single-character ' token
+                        if (preg_match('/\S/', $prev_token_last_char)) {
+                            $t = "&#8217;";
+                        }
+                        else {
+                            $t = "&#8216;";
+                        }
+                    }
+                    else if ($t == '"') {
+                        # Special case: single-character " token
+                        if (preg_match('/\S/', $prev_token_last_char)) {
+                            $t = "&#8221;";
+                        }
+                        else {
+                            $t = "&#8220;";
+                        }
+                    }
+                    else {
+                        # Normal case:
+                        $t = EducateQuotes($t);
+                    }
+                }
+
+                if ($do_stupefy) $t = StupefyEntities($t);
+            }
+            $prev_token_last_char = $last_char;
+            $result .= $t;
+        }
+    }
+
+    return $result;
+}
+
+
+function SmartQuotes($text, $attr = NULL, $ctx = NULL) {
+    global $smartypants_attr, $sp_tags_to_skip;
+    # Paramaters:
+    $text;   # text to be parsed
+    $attr;   # value of the smart_quotes="" attribute
+    $ctx;    # MT context object (unused)
+    if ($attr == NULL) $attr = $smartypants_attr;
+
+    $do_backticks;   # should we educate ``backticks'' -style quotes?
+
+    if ($attr == 0) {
+        # do nothing;
+        return $text;
+    }
+    else if ($attr == 2) {
+        # smarten ``backticks'' -style quotes
+        $do_backticks = 1;
+    }
+    else {
+        $do_backticks = 0;
+    }
+
+    # Special case to handle quotes at the very end of $text when preceded by
+    # an HTML tag. Add a space to give the quote education algorithm a bit of
+    # context, so that it can guess correctly that it's a closing quote:
+    $add_extra_space = 0;
+    if (preg_match("/>['\"]\\z/", $text)) {
+        $add_extra_space = 1; # Remember, so we can trim the extra space later.
+        $text .= " ";
+    }
+
+    $tokens = _TokenizeHTML($text);
+    $result = '';
+    $in_pre = 0;  # Keep track of when we're inside <pre> or <code> tags
+
+    $prev_token_last_char = "";     # This is a cheat, used to get some context
+                                    # for one-character tokens that consist of
+                                    # just a quote char. What we do is remember
+                                    # the last character of the previous text
+                                    # token, to use as context to curl single-
+                                    # character quote tokens correctly.
+
+    foreach ($tokens as $cur_token) {
+        if ($cur_token[0] == "tag") {
+            # Don't mess with quotes inside tags
+            $result .= $cur_token[1];
+            if (preg_match("@$sp_tags_to_skip@", $cur_token[1], $matches)) {
+                $in_pre = isset($matches[1]) && $matches[1] == '/' ? 0 : 1;
+            }
+        } else {
+            $t = $cur_token[1];
+            $last_char = substr($t, -1); # Remember last char of this token before processing.
+            if (! $in_pre) {
+                $t = ProcessEscapes($t);
+                if ($do_backticks) {
+                    $t = EducateBackticks($t);
+                }
+
+                if ($t == "'") {
+                    # Special case: single-character ' token
+                    if (preg_match('/\S/', $prev_token_last_char)) {
+                        $t = "&#8217;";
+                    }
+                    else {
+                        $t = "&#8216;";
+                    }
+                }
+                else if ($t == '"') {
+                    # Special case: single-character " token
+                    if (preg_match('/\S/', $prev_token_last_char)) {
+                        $t = "&#8221;";
+                    }
+                    else {
+                        $t = "&#8220;";
+                    }
+                }
+                else {
+                    # Normal case:
+                    $t = EducateQuotes($t);
+                }
+
+            }
+            $prev_token_last_char = $last_char;
+            $result .= $t;
+        }
+    }
+
+    if ($add_extra_space) {
+        preg_replace('/ \z/', '', $result);  # Trim trailing space if we added one earlier.
+    }
+    return $result;
+}
+
+
+function SmartDashes($text, $attr = NULL, $ctx = NULL) {
+    global $smartypants_attr, $sp_tags_to_skip;
+    # Paramaters:
+    $text;   # text to be parsed
+    $attr;   # value of the smart_dashes="" attribute
+    $ctx;    # MT context object (unused)
+    if ($attr == NULL) $attr = $smartypants_attr;
+
+    # reference to the subroutine to use for dash education, default to EducateDashes:
+    $dash_sub_ref = 'EducateDashes';
+
+    if ($attr == 0) {
+        # do nothing;
+        return $text;
+    }
+    else if ($attr == 2) {
+        # use old smart dash shortcuts, "--" for en, "---" for em
+        $dash_sub_ref = 'EducateDashesOldSchool';
+    }
+    else if ($attr == 3) {
+        # inverse of 2, "--" for em, "---" for en
+        $dash_sub_ref = 'EducateDashesOldSchoolInverted';
+    }
+
+    $tokens;
+    $tokens = _TokenizeHTML($text);
+
+    $result = '';
+    $in_pre = 0;  # Keep track of when we're inside <pre> or <code> tags
+    foreach ($tokens as $cur_token) {
+        if ($cur_token[0] == "tag") {
+            # Don't mess with quotes inside tags
+            $result .= $cur_token[1];
+            if (preg_match("@$sp_tags_to_skip@", $cur_token[1], $matches)) {
+                $in_pre = isset($matches[1]) && $matches[1] == '/' ? 0 : 1;
+            }
+        } else {
+            $t = $cur_token[1];
+            if (! $in_pre) {
+                $t = ProcessEscapes($t);
+                $t = $dash_sub_ref($t);
+            }
+            $result .= $t;
+        }
+    }
+    return $result;
+}
+
+
+function SmartEllipses($text, $attr = NULL, $ctx = NULL) {
+    # Paramaters:
+    $text;   # text to be parsed
+    $attr;   # value of the smart_ellipses="" attribute
+    $ctx;    # MT context object (unused)
+    if ($attr == NULL) $attr = $smartypants_attr;
+
+    if ($attr == 0) {
+        # do nothing;
+        return $text;
+    }
+
+    $tokens;
+    $tokens = _TokenizeHTML($text);
+
+    $result = '';
+    $in_pre = 0;  # Keep track of when we're inside <pre> or <code> tags
+    foreach ($tokens as $cur_token) {
+        if ($cur_token[0] == "tag") {
+            # Don't mess with quotes inside tags
+            $result .= $cur_token[1];
+            if (preg_match("@$sp_tags_to_skip@", $cur_token[1], $matches)) {
+                $in_pre = isset($matches[1]) && $matches[1] == '/' ? 0 : 1;
+            }
+        } else {
+            $t = $cur_token[1];
+            if (! $in_pre) {
+                $t = ProcessEscapes($t);
+                $t = EducateEllipses($t);
+            }
+            $result .= $t;
+        }
+    }
+    return $result;
+}
+
+
+function EducateQuotes($_) {
+#
+#   Parameter:  String.
+#
+#   Returns:    The string, with "educated" curly quote HTML entities.
+#
+#   Example input:  "Isn't this fun?"
+#   Example output: &#8220;Isn&#8217;t this fun?&#8221;
+#
+    # Make our own "punctuation" character class, because the POSIX-style
+    # [:PUNCT:] is only available in Perl 5.6 or later:
+    $punct_class = "[!\"#\\$\\%'()*+,-.\\/:;<=>?\\@\\[\\\\\]\\^_`{|}~]";
+
+    # Special case if the very first character is a quote
+    # followed by punctuation at a non-word-break. Close the quotes by brute force:
+    $_ = preg_replace(
+        array("/^'(?=$punct_class\\B)/", "/^\"(?=$punct_class\\B)/"),
+        array('&#8217;',                 '&#8221;'), $_);
+
+
+    # Special case for double sets of quotes, e.g.:
+    #   <p>He said, "'Quoted' words in a larger quote."</p>
+    $_ = preg_replace(
+        array("/\"'(?=\w)/",    "/'\"(?=\w)/"),
+        array('&#8220;&#8216;', '&#8216;&#8220;'), $_);
+
+    # Special case for decade abbreviations (the '80s):
+    $_ = preg_replace("/'(?=\\d{2}s)/", '&#8217;', $_);
+
+    $close_class = '[^\ \t\r\n\[\{\(\-]';
+    $dec_dashes = '&\#8211;|&\#8212;';
+
+    # Get most opening single quotes:
+    $_ = preg_replace("{
+        (
+            \\s          |   # a whitespace char, or
+            &nbsp;      |   # a non-breaking space entity, or
+            --          |   # dashes, or
+            &[mn]dash;  |   # named dash entities
+            $dec_dashes |   # or decimal entities
+            &\\#x201[34];    # or hex
+        )
+        '                   # the quote
+        (?=\\w)              # followed by a word character
+        }x", '\1&#8216;', $_);
+    # Single closing quotes:
+    $_ = preg_replace("{
+        ($close_class)?
+        '
+        (?(1)|          # If $1 captured, then do nothing;
+          (?=\\s | s\\b)  # otherwise, positive lookahead for a whitespace
+        )               # char or an 's' at a word ending position. This
+                        # is a special case to handle something like:
+                        # \"<i>Custer</i>'s Last Stand.\"
+        }xi", '\1&#8217;', $_);
+
+    # Any remaining single quotes should be opening ones:
+    $_ = str_replace("'", '&#8216;', $_);
+
+
+    # Get most opening double quotes:
+    $_ = preg_replace("{
+        (
+            \\s          |   # a whitespace char, or
+            &nbsp;      |   # a non-breaking space entity, or
+            --          |   # dashes, or
+            &[mn]dash;  |   # named dash entities
+            $dec_dashes |   # or decimal entities
+            &\\#x201[34];    # or hex
+        )
+        \"                   # the quote
+        (?=\\w)              # followed by a word character
+        }x", '\1&#8220;', $_);
+
+    # Double closing quotes:
+    $_ = preg_replace("{
+        ($close_class)?
+        \"
+        (?(1)|(?=\\s))   # If $1 captured, then do nothing;
+                           # if not, then make sure the next char is whitespace.
+        }x", '\1&#8221;', $_);
+
+    # Any remaining quotes should be opening ones.
+    $_ = str_replace('"', '&#8220;', $_);
+
+    return $_;
+}
+
+
+function EducateBackticks($_) {
+#
+#   Parameter:  String.
+#   Returns:    The string, with ``backticks'' -style double quotes
+#               translated into HTML curly quote entities.
+#
+#   Example input:  ``Isn't this fun?''
+#   Example output: &#8220;Isn't this fun?&#8221;
+#
+
+    $_ = str_replace(array("``",       "''",),
+                     array('&#8220;', '&#8221;'), $_);
+    return $_;
+}
+
+
+function EducateSingleBackticks($_) {
+#
+#   Parameter:  String.
+#   Returns:    The string, with `backticks' -style single quotes
+#               translated into HTML curly quote entities.
+#
+#   Example input:  `Isn't this fun?'
+#   Example output: &#8216;Isn&#8217;t this fun?&#8217;
+#
+
+    $_ = str_replace(array("`",       "'",),
+                     array('&#8216;', '&#8217;'), $_);
+    return $_;
+}
+
+
+function EducateDashes($_) {
+#
+#   Parameter:  String.
+#
+#   Returns:    The string, with each instance of "--" translated to
+#               an em-dash HTML entity.
+#
+
+    $_ = str_replace('--', '&#8212;', $_);
+    return $_;
+}
+
+
+function EducateDashesOldSchool($_) {
+#
+#   Parameter:  String.
+#
+#   Returns:    The string, with each instance of "--" translated to
+#               an en-dash HTML entity, and each "---" translated to
+#               an em-dash HTML entity.
+#
+
+    #                      em         en
+    $_ = str_replace(array("---",     "--",),
+                     array('&#8212;', '&#8211;'), $_);
+    return $_;
+}
+
+
+function EducateDashesOldSchoolInverted($_) {
+#
+#   Parameter:  String.
+#
+#   Returns:    The string, with each instance of "--" translated to
+#               an em-dash HTML entity, and each "---" translated to
+#               an en-dash HTML entity. Two reasons why: First, unlike the
+#               en- and em-dash syntax supported by
+#               EducateDashesOldSchool(), it's compatible with existing
+#               entries written before SmartyPants 1.1, back when "--" was
+#               only used for em-dashes.  Second, em-dashes are more
+#               common than en-dashes, and so it sort of makes sense that
+#               the shortcut should be shorter to type. (Thanks to Aaron
+#               Swartz for the idea.)
+#
+
+    #                      en         em
+    $_ = str_replace(array("---",     "--",),
+                     array('&#8211;', '&#8212;'), $_);
+    return $_;
+}
+
+
+function EducateEllipses($_) {
+#
+#   Parameter:  String.
+#   Returns:    The string, with each instance of "..." translated to
+#               an ellipsis HTML entity. Also converts the case where
+#               there are spaces between the dots.
+#
+#   Example input:  Huh...?
+#   Example output: Huh&#8230;?
+#
+
+    $_ = str_replace(array("...",     ". . .",), '&#8230;', $_);
+    return $_;
+}
+
+
+function StupefyEntities($_) {
+#
+#   Parameter:  String.
+#   Returns:    The string, with each SmartyPants HTML entity translated to
+#               its ASCII counterpart.
+#
+#   Example input:  &#8220;Hello &#8212; world.&#8221;
+#   Example output: "Hello -- world."
+#
+
+                        #  en-dash    em-dash
+    $_ = str_replace(array('&#8211;', '&#8212;'),
+                     array('-',       '--'), $_);
+
+    # single quote         open       close
+    $_ = str_replace(array('&#8216;', '&#8217;'), "'", $_);
+
+    # double quote         open       close
+    $_ = str_replace(array('&#8220;', '&#8221;'), '"', $_);
+
+    $_ = str_replace('&#8230;', '...', $_); # ellipsis
+
+    return $_;
+}
+
+
+function ProcessEscapes($_) {
+#
+#   Parameter:  String.
+#   Returns:    The string, with after processing the following backslash
+#               escape sequences. This is useful if you want to force a "dumb"
+#               quote or other character to appear.
+#
+#               Escape  Value
+#               ------  -----
+#               \\      &#92;
+#               \"      &#34;
+#               \'      &#39;
+#               \.      &#46;
+#               \-      &#45;
+#               \`      &#96;
+#
+    $_ = str_replace(
+        array('\\\\',  '\"',    "\'",    '\.',    '\-',    '\`'),
+        array('&#92;', '&#34;', '&#39;', '&#46;', '&#45;', '&#96;'), $_);
+
+    return $_;
+}
+
+
+# _TokenizeHTML is shared between PHP SmartyPants and PHP Markdown.
+# We only define it if it is not already defined.
+if (!function_exists('_TokenizeHTML')) :
+function _TokenizeHTML($str) {
+#
+#   Parameter:  String containing HTML markup.
+#   Returns:    An array of the tokens comprising the input
+#               string. Each token is either a tag (possibly with nested,
+#               tags contained therein, such as <a href="<MTFoo>">, or a
+#               run of text between tags. Each element of the array is a
+#               two-element array; the first is either 'tag' or 'text';
+#               the second is the actual value.
+#
+#
+#   Regular expression derived from the _tokenize() subroutine in
+#   Brad Choate's MTRegex plugin.
+#   <http://www.bradchoate.com/past/mtregex.php>
+#
+    $index = 0;
+    $tokens = array();
+
+    $match = '(?s:<!(?:--.*?--\s*)+>)|'.    # comment
+             '(?s:<\?.*?\?>)|'.             # processing instruction
+                                            # regular tags
+             '(?:<[/!$]?[-a-zA-Z0-9:]+\b(?>[^"\'>]+|"[^"]*"|\'[^\']*\')*>)';
+
+    $parts = preg_split("{($match)}", $str, -1, PREG_SPLIT_DELIM_CAPTURE);
+
+    foreach ($parts as $part) {
+        if (++$index % 2 && $part != '')
+            $tokens[] = array('text', $part);
+        else
+            $tokens[] = array('tag', $part);
+    }
+    return $tokens;
+}
+endif;
+
+
+/*
+
+PHP SmartyPants
+===============
+
+Description
+-----------
+
+This is a PHP translation of the original SmartyPants quote educator written in
+Perl by John Gruber.
+
+SmartyPants is a web publishing utility that translates plain ASCII
+punctuation characters into "smart" typographic punctuation HTML
+entities. SmartyPants can perform the following transformations:
+
+*   Straight quotes (`"` and `'`) into "curly" quote HTML entities
+*   Backticks-style quotes (` ``like this'' `) into "curly" quote HTML
+    entities
+*   Dashes (`--` and `---`) into en- and em-dash entities
+*   Three consecutive dots (`...`) into an ellipsis entity
+
+SmartyPants does not modify characters within `<pre>`, `<code>`, `<kbd>`,
+`<script>`, or `<math>` tag blocks. Typically, these tags are used to
+display text where smart quotes and other "smart punctuation" would not
+be appropriate, such as source code or example markup.
+
+
+### Backslash Escapes ###
+
+If you need to use literal straight quotes (or plain hyphens and
+periods), SmartyPants accepts the following backslash escape sequences
+to force non-smart punctuation. It does so by transforming the escape
+sequence into a decimal-encoded HTML entity:
+
+    Escape  Value  Character
+    ------  -----  ---------
+      \\    &#92;    \
+      \"    &#34;    "
+      \'    &#39;    '
+      \.    &#46;    .
+      \-    &#45;    -
+      \`    &#96;    `
+
+This is useful, for example, when you want to use straight quotes as
+foot and inch marks: 6'2" tall; a 17" iMac.
+
+
+Bugs
+----
+
+To file bug reports or feature requests (other than topics listed in the
+Caveats section above) please send email to:
+
+<michel.fortin@michelf.com>
+
+If the bug involves quotes being curled the wrong way, please send example
+text to illustrate.
+
+
+### Algorithmic Shortcomings ###
+
+One situation in which quotes will get curled the wrong way is when
+apostrophes are used at the start of leading contractions. For example:
+
+    'Twas the night before Christmas.
+
+In the case above, SmartyPants will turn the apostrophe into an opening
+single-quote, when in fact it should be a closing one. I don't think
+this problem can be solved in the general case -- every word processor
+I've tried gets this wrong as well. In such cases, it's best to use the
+proper HTML entity for closing single-quotes (`&#8217;`) by hand.
+
+
+Version History
+---------------
+
+1.5.1e (9 Dec 2005)
+
+*   Corrected a bug that prevented special characters from being
+    escaped.
+
+
+1.5.1d (25 May 2005)
+
+*   Corrected a small bug in `_TokenizeHTML` where a Doctype declaration
+    was not seen as HTML (smart quotes where applied inside).
+
+
+1.5.1c (13 Dec 2004)
+
+*   Changed a regular expression in `_TokenizeHTML` that could lead to
+    a segmentation fault with PHP 4.3.8 on Linux.
+
+
+1.5.1b (6 Sep 2004)
+
+*   Corrected a problem with quotes immediately following a dash
+    with no space between: `Text--"quoted text"--text.`
+
+*   PHP SmartyPants can now be used as a modifier by the Smarty
+    template engine. Rename the file to "modifier.smartypants.php"
+    and put it in your smarty plugins folder.
+
+*   Replaced a lot of space characters by tabs, saving about 4 KB.
+
+
+1.5.1a (30 Jun 2004)
+
+*   PHP Markdown and PHP Smartypants now share the same `_TokenizeHTML`
+    function when loaded simultanously.
+
+*   Changed the internals of `_TokenizeHTML` to lower the PHP version
+    requirement to PHP 4.0.5.
+
+
+1.5.1 (6 Jun 2004)
+
+*   Initial release of PHP SmartyPants, based on version 1.5.1 of the
+    original SmartyPants written in Perl.
+
+
+Author
+------
+
+John Gruber
+<http://daringfireball.net/>
+
+Ported to PHP by Michel Fortin
+<http://www.michelf.com/>
+
+
+Additional Credits
+------------------
+
+Portions of this plug-in are based on Brad Choate's nifty MTRegex plug-in.
+Brad Choate also contributed a few bits of source code to this plug-in.
+Brad Choate is a fine hacker indeed. (<http://bradchoate.com/>)
+
+Jeremy Hedley (<http://antipixel.com/>) and Charles Wiltgen
+(<http://playbacktime.com/>) deserve mention for exemplary beta testing.
+
+
+Copyright and License
+---------------------
+
+Copyright (c) 2003 John Gruber
+<http://daringfireball.net/>
+All rights reserved.
+
+Copyright (c) 2004-2005 Michel Fortin
+<http://www.michelf.com>
+
+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 "SmartyPants" 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.
+
+*/
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/contrib/aliased.php b/examples/includes/geshi/contrib/aliased.php
new file mode 100644 (file)
index 0000000..4680ffb
--- /dev/null
@@ -0,0 +1,124 @@
+<?php
+
+/**
+ * Another GeSHi example script
+ *
+ * Configure your Apache server with 'AcceptPathInfo true' and something like
+ * 'Alias /viewmysource /var/www/geshi/contrib/aliased.php'. Don't forget
+ * to protect this alias as necessary.
+ *
+ * Usage - visit /viewmysource/file.name.ext to see that file with syntax
+ * highlighting, where "viewmysource" is the name of the alias you set up.
+ * You can use this without an alias too, just by visiting
+ * aliased.php/file.name.ext.
+ *
+ * @author  Ross Golder <ross@golder.org>
+ * @version $Id: aliased.php 785 2006-07-19 10:09:45Z oracleshinoda $
+ */
+
+// Your config here
+define("SOURCE_ROOT", "/var/www/your/source/root/");
+
+// Assume you've put geshi in the include_path already
+require_once("geshi.php");
+
+// Get path info
+$path = SOURCE_ROOT.$_SERVER['PATH_INFO'];
+
+// Check for dickheads trying to use '../' to get to sensitive areas
+$base_path_len = strlen(SOURCE_ROOT);
+$real_path = realpath($path);
+if(strncmp($real_path, SOURCE_ROOT, $base_path_len)) {
+    exit("Stop that.");
+}
+
+// Check file exists
+if(!file_exists($path)) {
+    exit("File not found ($path).");
+}
+
+// Gather contents
+$contents = file_get_contents($path);
+
+// Prepare GeSHi instance
+$geshi =& new GeSHi($contents, "PHP");
+$geshi->set_header_type(GESHI_HEADER_PRE);
+$geshi->enable_classes();
+$geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS, 10);
+$geshi->set_overall_style('color: #000066; border: 1px solid #d0d0d0; background-color: #f0f0f0;', true);
+$geshi->set_line_style('font: normal normal 95% \'Courier New\', Courier, monospace; color: #003030;', 'font-weight: bold; color: #006060;', true);
+$geshi->set_code_style('color: #000020;', 'color: #000020;');
+$geshi->set_link_styles(GESHI_LINK, 'color: #000060;');
+$geshi->set_link_styles(GESHI_HOVER, 'background-color: #f0f000;');
+$geshi->set_header_content('Source code viewer');
+$geshi->set_header_content_style('font-family: Verdana, Arial, sans-serif; color: #808080; font-size: 70%; font-weight: bold; background-color: #f0f0ff; border-bottom: 1px solid #d0d0d0; padding: 2px;');
+$geshi->set_footer_content('Parsed in <TIME> seconds,  using GeSHi <VERSION>');
+$geshi->set_footer_content_style('font-family: Verdana, Arial, sans-serif; color: #808080; font-size: 70%; font-weight: bold; background-color: #f0f0ff; border-top: 1px solid #d0d0d0; padding: 2px;');
+
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+    <title>Source code viewer - <?php echo $path; ?></title>
+    <style type="text/css">
+    <!--
+    <?php
+        // Output the stylesheet. Note it doesn't output the <style> tag
+    echo $geshi->get_stylesheet();
+    ?>
+    html {
+        background-color: #f0f0f0;
+    }
+    body {
+        font-family: Verdana, Arial, sans-serif;
+        margin: 10px;
+        border: 2px solid #e0e0e0;
+        background-color: #fcfcfc;
+        padding: 5px;
+    }
+    h2 {
+        margin: .1em 0 .2em .5em;
+        border-bottom: 1px solid #b0b0b0;
+        color: #b0b0b0;
+        font-weight: normal;
+        font-size: 150%;
+    }
+    h3 {
+        margin: .1em 0 .2em .5em;
+        color: #b0b0b0;
+        font-weight: normal;
+        font-size: 120%;
+    }
+    #footer {
+        text-align: center;
+        font-size: 80%;
+        color: #a9a9a9;
+    }
+    #footer a {
+        color: #9999ff;
+    }
+    textarea {
+        border: 1px solid #b0b0b0;
+        font-size: 90%;
+        color: #333;
+        margin-left: 20px;
+    }
+    select, input {
+        margin-left: 20px;
+    }
+    p {
+        font-size: 90%;
+        margin-left: .5em;
+    }
+    -->
+    </style>
+</head>
+<body>
+<?php
+// The fun part :)
+echo $geshi->parse_code();
+?>
+<hr/>
+</body>
+</html>
diff --git a/examples/includes/geshi/contrib/cssgen.php b/examples/includes/geshi/contrib/cssgen.php
new file mode 100644 (file)
index 0000000..b75edc8
--- /dev/null
@@ -0,0 +1,456 @@
+<?php
+/*************************************************************************************
+ * cssgen.php
+ * ----------
+ * Author: Nigel McNie (nigel@geshi.org)
+ * Copyright: (c) 2004 Nigel McNie
+ * Release Version: 1.0.8.1
+ * Date Started: 2004/05/20
+ *
+ * Application to generate custom CSS files for GeSHi (based on an idea by Andreas
+ * Gohr)
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+set_magic_quotes_runtime(0);
+//
+// Functions
+//
+
+function make_header ( $title )
+{
+    echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+    <title>GeSHi CSS Generator :: ' . $title . ' </title>
+    <style type="text/css" media="screen">
+    <!--
+        html {
+            font-family: Verdana, Arial, sans-serif;
+            font-size: 80%;
+            background-color: #d0d0d0;
+        }
+        body {
+            margin: 10px;
+            padding: 5px;
+            border: 1px solid #f0f0f0;
+            background-color: #f6f6f6;
+        }
+        h1 {
+            border-bottom: 2px solid #e0e0e0;
+            font-weight: normal;
+            font-size: 150%;
+            color: #c0c0c0;
+        }
+        input, textarea {
+            border: 1px solid #d0d0d0;
+        }
+        th {
+            text-align: right;
+            font-weight: normal;
+        }
+        pre {
+            font-size: 110%;
+            color: #202020;
+        }
+        #footer {
+            color: #b0b0b0;
+            text-align: center;
+            font-size: 90%;
+            margin: 0 auto;
+            border-top: 1px solid #e0e0e0;
+        }
+        #footer a {
+            color: #c0c0c0;
+        }
+    -->
+    </style>
+    <script type="text/javascript">
+    function select (state)
+    {
+        var cboxes = document.getElementsByTagName(\'input\');
+        for (var i = 0; i < cboxes.length; i++) {
+            if (cboxes[i].type == "checkbox") {
+                if (state == "true") {
+                    cboxes[i].checked = true;
+                } else if (state == "false") {
+                    cboxes[i].checked = false;
+                } else if (state == "invert") {
+                    cboxes[i].checked = !cboxes[i].checked;
+                }
+            }
+        }
+    }
+    </script>
+</head>
+<body>
+<h1>' . $title . '</h1>
+';
+}
+
+function make_footer ()
+{
+    echo '<div id="footer"><a href="http://qbnz.com/highlighter/">GeSHi</a> &copy; Nigel McNie, 2004, released under the GPL</div></body>
+</html>';
+}
+
+
+function get_var ( $var_name )
+{
+    if ( isset($_GET[$var_name]) )
+    {
+        return str_replace("\'", "'", $_GET[$var_name]);
+    }
+    elseif ( isset($_POST[$var_name]) )
+    {
+        return str_replace("\'", "'", $_POST[$var_name]);
+    }
+    return null;
+}
+
+
+
+//
+// Unset everything
+//
+foreach ( $_REQUEST as $var )
+{
+    unset($$var);
+}
+foreach ( array(
+    '_POST' => 'HTTP_POST_VARS',
+    '_GET' => 'HTTP_GET_VARS',
+    '_COOKIE' => 'HTTP_COOKIE_VARS',
+    '_SERVER' => 'HTTP_SERVER_VARS',
+    '_ENV' => 'HTTP_ENV_VARS',
+    '_FILES' => 'HTTP_POST_FILES')  as $array => $other )
+{
+    if ( !isset($$array) )
+    {
+        $$array = $$other;
+    }
+    unset($$other);
+}
+
+
+// Get what step we're up to
+$step = get_var('step');
+
+if ( !$step || $step == 1 )
+{
+    $errors = 0;
+    make_header('Step 1');
+    echo "Welcome to the GeSHi CSS generator.<br /><pre>Searching for GeSHi...          ";
+
+    // Find GeSHi
+    $geshi_path = get_var('geshi-path');
+    $geshi_lang_path = get_var('geshi-lang-path');
+
+    if ( !$geshi_path )
+    {
+        $geshi_path = '../geshi.php';
+    }
+    if ( !$geshi_lang_path )
+    {
+        $geshi_lang_path = '../geshi/';
+    }
+
+
+    if ( is_file($geshi_path) && is_readable($geshi_path) )
+    {
+        // Get file contents and see if GeSHi is in here
+        $file = @file($geshi_path);
+        $contents = '';
+        foreach ( $file as $line )
+        {
+            $contents .= $line;
+        }
+        if ( strpos($contents, '<?php
+/**
+ * GeSHi - Generic Syntax Highlighter') !== false )
+         {
+            echo '<span style="color: green;">Found at ' . realpath($geshi_path) . '</span>';
+        }
+        else
+        {
+            ++$errors;
+            $no_geshi_dot_php_error = true;
+            echo '<span style="color: red;">Not found</span>';
+        }
+    }
+    else
+    {
+        ++$errors;
+        $no_geshi_dot_php_error = true;
+        echo '<span style="color: red;">Not found</span>';
+    }
+
+    // Find language files
+    echo "\nSearching for language files... ";
+    if ( is_readable($geshi_lang_path . 'css-gen.cfg') )
+    {
+
+        echo '<span style="color: green;">Found at ' . realpath($geshi_lang_path) . '</span>';
+    }
+    else
+    {
+        ++$errors;
+        $no_lang_dir_error = true;
+        echo '<span style="color: red;">Not found</span>';
+    }
+    echo "</pre>\n";
+
+    if ( $errors > 0 )
+    {
+        // We're gonna have to ask for the paths...
+        echo 'Unfortunately CSSGen could not detect the following paths. Please input them and press &quot;submit&quot; to try again.';
+        echo "
+<form action=\"cssgen.php\" method=\"post\">";
+        if ( $no_geshi_dot_php_error )
+        {
+            echo "
+<br />geshi.php: <input type=\"text\" name=\"geshi-path\" value=\"" . realpath('../geshi.php') . "\" size=\"50\" />";
+        }
+        else
+        {
+            echo '<input type="hidden" name="geshi-path" value="' . htmlspecialchars($geshi_path) . '" />';
+        }
+        if ( $no_lang_dir_error )
+        {
+            echo "
+<br />language files directory: <input type=\"text\" name=\"geshi-lang-path\" value=\"" . realpath('../geshi/') . "/\" size=\"50\" /> (should have a trailing slash)";
+        }
+        else
+        {
+            echo '<input type="hidden" name="geshi-lang-path" value="' . $geshi_lang_path . '" />';
+        }
+
+        echo "
+<br /><input type=\"submit\" value=\"Search\" /></form>";
+    }
+    else
+    {
+        // no errors - echo continue form
+        echo 'Everything seems to be detected successfully. Use the button to continue.
+<br /><br /><form action="cssgen.php?step=2" method="post">
+<input type="hidden" name="geshi-path" value="' . realpath($geshi_path) . '" /><input type="hidden" name="geshi-lang-path" value="' . realpath($geshi_lang_path) . '" />
+<input type="submit" value="Step 2" />';
+    }
+
+    make_footer();
+}
+// Step 2
+elseif ( $step == 2 )
+{
+    make_header('Step 2');
+
+    $geshi_path = get_var('geshi-path');
+    $geshi_lang_path = get_var('geshi-lang-path');
+
+    $dh = opendir($geshi_lang_path);
+    $lang_files = array();
+    $file = readdir($dh);
+    while ( $file !== false )
+    {
+        if ( $file == '.' || $file == '..' || $file == 'CVS' || $file == 'css-gen.cfg' )
+        {
+            $file = readdir($dh);
+            continue;
+        }
+        $lang_files[] = $file;
+        $file = readdir($dh);
+    }
+    closedir($dh);
+    sort($lang_files);
+
+    // Now installed languages are in $lang_files
+
+    echo '<form action="cssgen.php?step=3" method="post" id="step2">
+What languages are you wanting to make this stylesheet for?<br /><br />
+Detected languages:<br />';
+
+    foreach ( $lang_files as $lang )
+    {
+        $lang = substr($lang, 0, strpos($lang, '.'));
+        if ($lang) {
+            echo "<input type=\"checkbox\" name=\"langs[$lang]\" checked=\"checked\" />&nbsp;$lang<br />\n";
+        }
+    }
+
+    echo "Select: <a href=\"javascript:select('true')\">All</a>, <a href=\"javascript:select('false')\">None</a>, <a href=\"javascript:select('invert')\">Invert</a><br />\n";
+
+    echo 'If you\'d like any other languages not detected here to be supported, please enter
+them here, one per line:<br /><textarea rows="4" cols="20" name="extra-langs"></textarea><br />
+';
+
+    echo '<br />Styles:
+<table>
+    <tr><th>Style for the overall code block:</th><td><input type="text" name="overall" value="border: 1px dotted #a0a0a0; font-family: \'Courier New\', Courier, monospace; background-color: #f0f0f0; color: #0000bb;" /></td></tr>
+    <tr><th>Default Styles</th><td><input type="text" name="default-styles" value="font-weight:normal;background:transparent;color:#000; padding-left: 5px;" /></td></tr>
+    <tr><th>Keywords I (if, do, while etc)</th><td><input type="text" name="keywords-1" value="color: #a1a100;" /></td></tr>
+    <tr><th>Keywords II (null, true, false etc)</th><td><input type="text" name="keywords-2" value="color: #000; font-weight: bold;" /></td></tr>
+    <tr><th>Inbuilt Functions (echo, print etc)</th><td><input type="text" name="keywords-3" value="color: #000066;" /></td></tr>
+    <tr><th>Data Types (int, boolean etc)</th><td><input type="text" name="keywords-4" value="color: #f63333;" /></td></tr>
+
+    <tr><th>Comments (//, <!--  --> etc)</th><td><input type="text" name="comments" value="color: #808080;" /></td></tr>
+    <tr><th>Escaped Characters (\n, \t etc)</th><td><input type="text" name="escaped-chars" value="color: #000033; font-weight: bold;" /></td></tr>
+    <tr><th>Brackets ( ([{}]) etc)</th><td><input type="text" name="brackets" value="color: #66cc66;" /></td></tr>
+    <tr><th>Strings ("foo" etc)</th><td><input type="text" name="strings" value="color: #ff0000;" /></td></tr>
+    <tr><th>Numbers (1, -54, 2.5 etc)</th><td><input type="text" name="numbers" value="color: #ff33ff;" /></td></tr>
+    <tr><th>Methods (Foo.bar() etc)</th><td><input type="text" name="methods" value="color: #006600;" /></td></tr>
+</table>';
+
+    echo '<input type="hidden" name="geshi-path" value="' . realpath($geshi_path) . '" /><input type="hidden" name="geshi-lang-path" value="' . realpath($geshi_lang_path) . '" />
+<input type="submit" value="Step 3" /></form>';
+
+    make_footer();
+}
+// Step 3
+elseif ( $step == 3 )
+{
+    make_header('Step 3');
+    echo '<p>Here is your completed stylesheet. Note that it may not be perfect - no regular expression styles are included for one thing,
+you\'ll have to add those yourself (php and xml are just two languages that use them), and line numbers are not included, however
+it includes most of the basic information.</p>';
+
+    // Make the stylesheet
+    $part_selector_1 = '';
+    $part_selector_2 = '';
+    $part_selector_3 = '';
+
+    $langs = get_var('langs');
+    $extra_langs = trim(get_var('extra-langs'));
+    if ( $extra_langs != '' )
+    {
+        $l = explode("\r\n", $extra_langs);
+        foreach ( $l as $lng )
+        {
+            $langs[$lng] = true;
+        }
+    }
+
+
+    foreach ( $langs as $lang => $dummy )
+    {
+        $part_selector_1 .= ".$lang {PART}, ";
+        $part_selector_2 .= ".$lang {PART1}, .$lang {PART2}, ";
+        $part_selector_3 .= ".$lang {PART1}, .$lang {PART2}, .$lang {PART3}, ";
+    }
+    $part_selector_1 = substr($part_selector_1, 0, -2);
+    $part_selector_2 = substr($part_selector_2, 0, -2);
+    $part_selector_3 = substr($part_selector_3, 0, -2);
+
+
+    $default_styles = get_var('default-styles');
+    $ol_selector = str_replace('{PART}', 'ol', $part_selector_1);
+    $overall_styles = get_var('overall');
+    $overall_selector = str_replace('{PART}', '', $part_selector_1);
+
+    $stylesheet = "/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */";
+
+    if ( $overall != '' )
+    {
+        $stylesheet .= "\n$overall_selector {{$overall_styles}}";
+    }
+    if ( $default_styles != '' )
+    {
+        $default_selector = str_replace(array('{PART1}', '{PART2}'), array('.de1', '.de2'), $part_selector_2);
+        $stylesheet .= "\n$default_selector {{$default_styles}}";
+    }
+
+    // Do keywords
+    $keywords_1 = get_var('keywords-1');
+    $keyword_selector_1 = str_replace('{PART}', '.kw1', $part_selector_1);
+    if ( $keywords_1 != '' )
+    {
+        $stylesheet .= "\n$keyword_selector_1 {{$keywords_1}}";
+    }
+
+    $keywords_2 = get_var('keywords-2');
+    $keyword_selector_2 = str_replace('{PART}', '.kw2', $part_selector_1);
+    if ( $keywords_2 != '' )
+    {
+        $stylesheet .= "\n$keyword_selector_2 {{$keywords_2}}";
+    }
+
+    $keywords_3 = get_var('keywords-3');
+    $keyword_selector_3 = str_replace('{PART}', '.kw3', $part_selector_1);
+    if ( $keywords_3 != '' )
+    {
+        $stylesheet .= "\n$keyword_selector_3 {{$keywords_3}}";
+    }
+
+    $keywords_4 = get_var('keywords-4');
+    $keyword_selector_4 = str_replace('{PART}', '.kw4', $part_selector_1);
+    if ( $keywords_4 != '' )
+    {
+        $stylesheet .= "\n$keyword_selector_4 {{$keywords_4}}";
+    }
+
+    // Do other lexics
+    $comments = get_var('comments');
+    $comment_selector = str_replace(array('{PART1}', '{PART2}', '{PART3}'), array('.co1', '.co2', '.coMULTI'), $part_selector_3);
+    if ( $comments != '' )
+    {
+        $stylesheet .= "\n$comment_selector {{$comments}}";
+    }
+
+    $esc = get_var('escaped-chars');
+    $esc_selector = str_replace('{PART}', '.es0', $part_selector_1);
+    if ( $esc != '' )
+    {
+        $stylesheet .= "\n$esc_selector {{$esc}}";
+    }
+
+    $brackets = get_var('brackets');
+    $brk_selector = str_replace('{PART}', '.br0', $part_selector_1);
+    if ( $brackets != '' )
+    {
+        $stylesheet .= "\n$brk_selector {{$brackets}}";
+    }
+
+    $strings = get_var('strings');
+    $string_selector = str_replace('{PART}', '.st0', $part_selector_1);
+    if ( $strings != '' )
+    {
+        $stylesheet .= "\n$string_selector {{$strings}}";
+    }
+
+    $numbers = get_var('numbers');
+    $num_selector = str_replace('{PART}', '.nu0', $part_selector_1);
+    if ( $numbers != '' )
+    {
+        $stylesheet .= "\n$num_selector {{$numbers}}";
+    }
+
+    $methods = get_var('methods');
+    $method_selector = str_replace('{PART}', '.me0', $part_selector_1);
+    if ( $methods != '' )
+    {
+        $stylesheet .= "\n$method_selector {{$methods}}";
+    }
+
+    echo "<pre>$stylesheet</pre>";
+
+    make_footer();
+}
+
+?>
diff --git a/examples/includes/geshi/contrib/cssgen2.php b/examples/includes/geshi/contrib/cssgen2.php
new file mode 100644 (file)
index 0000000..cc3c39c
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+/**
+ *  A simple script which outputs the CSS classes for all languages
+ *  supported by GeSHi. You can access it directly to download
+ *  the CSS file. On *NIX you can also do a simple `php cssgen.php > geshi.css`.
+ *
+ *   This file is part of GeSHi.
+ *
+ *  GeSHi 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.
+ *
+ *  GeSHi 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 GeSHi; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @package    geshi
+ * @subpackage contrib
+ * @author     revulo <revulon@gmail.com>
+ * @copyright  2008 revulo
+ * @license    http://gnu.org/copyleft/gpl.html GNU GPL
+ *
+ */
+
+require dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'geshi.php';
+$geshi = new GeSHi;
+
+$languages = array();
+if ($handle = opendir($geshi->language_path)) {
+    while (($file = readdir($handle)) !== false) {
+        $pos = strpos($file, '.');
+        if ($pos > 0 && substr($file, $pos) == '.php') {
+            $languages[] = substr($file, 0, $pos);
+        }
+    }
+    closedir($handle);
+}
+sort($languages);
+
+header('Content-Type: application/octet-stream');
+header('Content-Disposition: attachment; filename="geshi.css"');
+
+echo "/**\n".
+     " * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann\n" .
+     " * (http://qbnz.com/highlighter/ and http://geshi.org/)\n".
+     " */\n";
+
+foreach ($languages as $language) {
+    $geshi->set_language($language);
+    // note: the false argument is required for stylesheet generators, see API documentation
+    $css = $geshi->get_stylesheet(false);
+    echo preg_replace('/^\/\*\*.*?\*\//s', '', $css);
+}
diff --git a/examples/includes/geshi/contrib/example.php b/examples/includes/geshi/contrib/example.php
new file mode 100644 (file)
index 0000000..32e6f0c
--- /dev/null
@@ -0,0 +1,217 @@
+<?php
+/**
+ * GeSHi example script
+ *
+ * Just point your browser at this script (with geshi.php in the parent directory,
+ * and the language files in subdirectory "../geshi/")
+ *
+ * @author  Nigel McNie
+ * @version $Id: example.php 1512 2008-07-21 21:05:40Z benbe $
+ */
+header('Content-Type: text/html; charset=utf-8');
+
+error_reporting(E_ALL);
+
+// Rudimentary checking of where GeSHi is. In a default install it will be in ../, but
+// it could be in the current directory if the include_path is set. There's nowhere else
+// we can reasonably guess.
+if (is_readable('../geshi.php')) {
+    $path = '../';
+} elseif (is_readable('geshi.php')) {
+    $path = './';
+} else {
+    die('Could not find geshi.php - make sure it is in your include path!');
+}
+require $path . 'geshi.php';
+
+$fill_source = false;
+if (isset($_POST['submit'])) {
+    if (get_magic_quotes_gpc()) {
+        $_POST['source'] = stripslashes($_POST['source']);
+    }
+    if (!strlen(trim($_POST['source']))) {
+        $_POST['language'] = preg_replace('#[^a-zA-Z0-9\-_]#', '', $_POST['language']);
+        $_POST['source'] = implode('', @file($path . 'geshi/' . $_POST['language'] . '.php'));
+        $_POST['language'] = 'php';
+    } else {
+        $fill_source = true;
+    }
+
+    // Here's a free demo of how GeSHi works.
+
+    // First the initialisation: source code to highlight and the language to use. Make sure
+    // you sanitise correctly if you use $_POST of course - this very script has had a security
+    // advisory against it in the past because of this. Please try not to use this script on a
+    // live site.
+    $geshi = new GeSHi($_POST['source'], $_POST['language']);
+
+    // Use the PRE_VALID header. This means less output source since we don't have to output &nbsp;
+    // everywhere. Of course it also means you can't set the tab width.
+    // HEADER_PRE_VALID puts the <pre> tag inside the list items (<li>) thus producing valid HTML markup.
+    // HEADER_PRE puts the <pre> tag around the list (<ol>) which is invalid in HTML 4 and XHTML 1
+    // HEADER_DIV puts a <div> tag arount the list (valid!) but needs to replace whitespaces with &nbsp
+    //            thus producing much larger overhead. You can set the tab width though.
+    $geshi->set_header_type(GESHI_HEADER_PRE_VALID);
+
+    // Enable CSS classes. You can use get_stylesheet() to output a stylesheet for your code. Using
+    // CSS classes results in much less output source.
+    $geshi->enable_classes();
+
+    // Enable line numbers. We want fancy line numbers, and we want every 5th line number to be fancy
+    $geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS, 5);
+
+    // Set the style for the PRE around the code. The line numbers are contained within this box (not
+    // XHTML compliant btw, but if you are liberally minded about these things then you'll appreciate
+    // the reduced source output).
+    $geshi->set_overall_style('font: normal normal 90% monospace; color: #000066; border: 1px solid #d0d0d0; background-color: #f0f0f0;', false);
+
+    // Set the style for line numbers. In order to get style for line numbers working, the <li> element
+    // is being styled. This means that the code on the line will also be styled, and most of the time
+    // you don't want this. So the set_code_style reverts styles for the line (by using a <div> on the line).
+    // So the source output looks like this:
+    //
+    // <pre style="[set_overall_style styles]"><ol>
+    // <li style="[set_line_style styles]"><div style="[set_code_style styles]>...</div></li>
+    // ...
+    // </ol></pre>
+    $geshi->set_line_style('color: #003030;', 'font-weight: bold; color: #006060;', true);
+    $geshi->set_code_style('color: #000020;', true);
+
+    // Styles for hyperlinks in the code. GESHI_LINK for default styles, GESHI_HOVER for hover style etc...
+    // note that classes must be enabled for this to work.
+    $geshi->set_link_styles(GESHI_LINK, 'color: #000060;');
+    $geshi->set_link_styles(GESHI_HOVER, 'background-color: #f0f000;');
+
+    // Use the header/footer functionality. This puts a div with content within the PRE element, so it is
+    // affected by the styles set by set_overall_style. So if the PRE has a border then the header/footer will
+    // appear inside it.
+    $geshi->set_header_content('<SPEED> <TIME> GeSHi &copy; 2004-2007, Nigel McNie, 2007-2008 Benny Baumann. View source of example.php for example of using GeSHi');
+    $geshi->set_header_content_style('font-family: sans-serif; color: #808080; font-size: 70%; font-weight: bold; background-color: #f0f0ff; border-bottom: 1px solid #d0d0d0; padding: 2px;');
+
+    // You can use <TIME> and <VERSION> as placeholders
+    $geshi->set_footer_content('Parsed in <TIME> seconds at <SPEED>, using GeSHi <VERSION>');
+    $geshi->set_footer_content_style('font-family: sans-serif; color: #808080; font-size: 70%; font-weight: bold; background-color: #f0f0ff; border-top: 1px solid #d0d0d0; padding: 2px;');
+} else {
+    // make sure we don't preselect any language
+    $_POST['language'] = null;
+}
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+    <title>GeSHi examples</title>
+    <style type="text/css">
+    <!--
+    <?php
+    if (isset($_POST['submit'])) {
+        // Output the stylesheet. Note it doesn't output the <style> tag
+        echo $geshi->get_stylesheet(true);
+    }
+    ?>
+    html {
+        background-color: #f0f0f0;
+    }
+    body {
+        font-family: Verdana, Arial, sans-serif;
+        margin: 10px;
+        border: 2px solid #e0e0e0;
+        background-color: #fcfcfc;
+        padding: 5px;
+    }
+    h2 {
+        margin: .1em 0 .2em .5em;
+        border-bottom: 1px solid #b0b0b0;
+        color: #b0b0b0;
+        font-weight: normal;
+        font-size: 150%;
+    }
+    h3 {
+        margin: .1em 0 .2em .5em;
+        color: #b0b0b0;
+        font-weight: normal;
+        font-size: 120%;
+    }
+    #footer {
+        text-align: center;
+        font-size: 80%;
+        color: #a9a9a9;
+    }
+    #footer a {
+        color: #9999ff;
+    }
+    textarea {
+        border: 1px solid #b0b0b0;
+        font-size: 90%;
+        color: #333;
+        margin-left: 20px;
+    }
+    select, input {
+        margin-left: 20px;
+    }
+    p {
+        font-size: 90%;
+        margin-left: .5em;
+    }
+    -->
+    </style>
+</head>
+<body>
+<h2>GeSHi Example Script</h2>
+<p>To use this script, make sure that <strong>geshi.php</strong> is in the parent directory or in your
+include_path, and that the language files are in a subdirectory of GeSHi's directory called <strong>geshi/</strong>.</p>
+<p>Enter your source and a language to highlight the source in and submit, or just choose a language to
+have that language file highlighted in PHP.</p>
+<?php
+if (isset($_POST['submit'])) {
+    // The fun part :)
+    echo $geshi->parse_code();
+    echo '<hr />';
+}
+?>
+<form action="<?php echo basename($_SERVER['PHP_SELF']); ?>" method="post">
+<h3>Source to highlight</h3>
+<p>
+<textarea rows="10" cols="60" name="source" id="source"><?php echo $fill_source ? htmlspecialchars($_POST['source']) : '' ?></textarea>
+</p>
+<h3>Choose a language</h3>
+<p>
+<select name="language" id="language">
+<?php
+if (!($dir = @opendir(dirname(__FILE__) . '/geshi'))) {
+    if (!($dir = @opendir(dirname(__FILE__) . '/../geshi'))) {
+        echo '<option>No languages available!</option>';
+    }
+}
+$languages = array();
+while ($file = readdir($dir)) {
+    if ( $file[0] == '.' || strpos($file, '.', 1) === false) {
+        continue;
+    }
+    $lang = substr($file, 0,  strpos($file, '.'));
+    $languages[] = $lang;
+}
+closedir($dir);
+sort($languages);
+foreach ($languages as $lang) {
+    if (isset($_POST['language']) && $_POST['language'] == $lang) {
+        $selected = 'selected="selected"';
+    } else {
+        $selected = '';
+    }
+    echo '<option value="' . $lang . '" '. $selected .'>' . $lang . "</option>\n";
+}
+
+?>
+</select>
+</p>
+<p>
+<input type="submit" name="submit" value="Highlight Source" />
+<input type="submit" name="clear" onclick="document.getElementById('source').value='';document.getElementById('language').value='';return false" value="clear" />
+</p>
+</form>
+<div id="footer">GeSHi &copy; Nigel McNie, 2004, released under the GNU GPL<br />
+For a better demonstration, check out the <a href="http://qbnz.com/highlighter/demo.php">online demo</a>
+</div>
+</body>
+</html>
diff --git a/examples/includes/geshi/contrib/langcheck.php b/examples/includes/geshi/contrib/langcheck.php
new file mode 100644 (file)
index 0000000..0a2ca32
--- /dev/null
@@ -0,0 +1,666 @@
+<?php
+/**
+ * GeSHi example script
+ *
+ * Just point your browser at this script (with geshi.php in the parent directory,
+ * and the language files in subdirectory "../geshi/")
+ *
+ * @author  Nigel McNie
+ * @version $Id: langcheck.php 1971 2008-12-25 15:14:14Z benbe $
+ */
+header('Content-Type: text/html; charset=utf-8');
+
+set_time_limit(0);
+error_reporting(E_ALL);
+$time_start = explode(' ', microtime());
+
+define ('TYPE_NOTICE', 0);
+define ('TYPE_WARNING', 1);
+define ('TYPE_ERROR', 2);
+
+$error_abort = false;
+$error_cache = array();
+function output_error_cache(){
+    global $error_cache, $error_abort;
+
+    if(count($error_cache)) {
+        echo "<span style=\"color: #F00; font-weight: bold;\">Failed</span><br />";
+        echo "<ol>\n";
+        foreach($error_cache as $error_msg) {
+            echo "<li>";
+            switch($error_msg['t']) {
+                case TYPE_NOTICE:
+                    echo "<span style=\"color: #080; font-weight: bold;\">NOTICE:</span>";
+                    break;
+                case TYPE_WARNING:
+                    echo "<span style=\"color: #CC0; font-weight: bold;\">WARNING:</span>";
+                    break;
+                case TYPE_ERROR:
+                    echo "<span style=\"color: #F00; font-weight: bold;\">ERROR:</span>";
+                    break;
+            }
+            echo " " . $error_msg['m'] . "</li>";
+        }
+        echo "</ol>\n";
+    } else {
+        echo "<span style=\"color: #080; font-weight: bold;\">OK</span><br />";
+    }
+    echo "\n";
+
+    $error_cache = array();
+}
+
+function report_error($type, $message) {
+    global $error_cache, $error_abort;
+
+    $error_cache[] = array('t' => $type, 'm' => $message);
+    if(TYPE_ERROR == $type) {
+        $error_abort = true;
+    }
+}
+
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+    <title>GeSHi Language File Validation Script</title>
+    <style type="text/css">
+    <!--
+    html {
+        background-color: #f0f0f0;
+    }
+    body {
+        font-family: Verdana, Arial, sans-serif;
+        margin: 10px;
+        border: 2px solid #e0e0e0;
+        background-color: #fcfcfc;
+        padding: 5px;
+        font-size: 10pt;
+    }
+    h2 {
+        margin: .1em 0 .2em .5em;
+        border-bottom: 1px solid #b0b0b0;
+        color: #b0b0b0;
+        font-weight: normal;
+        font-size: 150%;
+    }
+    h3 {
+        margin: .1em 0 .2em .5em;
+        color: #b0b0b0;
+        font-weight: normal;
+        font-size: 120%;
+    }
+    #footer {
+        text-align: center;
+        font-size: 80%;
+        color: #a9a9a9;
+    }
+    #footer a {
+        color: #9999ff;
+    }
+    textarea {
+        border: 1px solid #b0b0b0;
+        font-size: 90%;
+        color: #333;
+        margin-left: 20px;
+    }
+    select, input {
+        margin-left: 20px;
+    }
+    p {
+        font-size: 90%;
+        margin-left: .5em;
+    }
+    -->
+    </style>
+</head>
+<body>
+<h2>GeSHi Language File Validation Script</h2>
+<p>To use this script, make sure that <strong>geshi.php</strong> is in the
+parent directory or in your include_path, and that the language files are in a
+subdirectory of GeSHi's directory called <strong>geshi/</strong>.</p>
+<p>Everything else will be done by this script automatically. After the script
+finished you should see messages of what could cause trouble with GeSHi or where
+your language files can be improved. Please be patient, as this might take some time.</p>
+
+<ol>
+<li>Checking where to find GeSHi installation ... <?php
+// Rudimentary checking of where GeSHi is. In a default install it will be in ../, but
+// it could be in the current directory if the include_path is set. There's nowhere else
+// we can reasonably guess.
+if (is_readable('../geshi.php')) {
+    $path = '../';
+} elseif (is_readable('geshi.php')) {
+    $path = './';
+} else {
+    report_error(TYPE_ERROR, 'Could not find geshi.php - make sure it is in your include path!');
+}
+
+if(!$error_abort) {
+    require $path . 'geshi.php';
+
+    if(!class_exists('GeSHi')) {
+        report_error(TYPE_ERROR, 'The GeSHi class was not found, although it seemed we loaded the correct file!');
+    }
+}
+
+if(!$error_abort) {
+    if(!defined('GESHI_LANG_ROOT')) {
+        report_error(TYPE_ERROR, 'There\'s no information present on where to find the language files!');
+    } else if(!is_dir(GESHI_LANG_ROOT)) {
+        report_error(TYPE_ERROR, 'The path "'.GESHI_LANG_ROOT.'" given, does not ressemble a directory!');
+    } else if(!is_readable(GESHI_LANG_ROOT)) {
+        report_error(TYPE_ERROR, 'The path "'.GESHI_LANG_ROOT.'" is not readable to this script!');
+    }
+}
+
+output_error_cache();
+
+if(!$error_abort) {
+    echo "</li>\n<li>Listing available language files ... ";
+
+    if (!($dir = @opendir(GESHI_LANG_ROOT))) {
+        report_error(TYPE_ERROR, 'Error requesting listing for available language files!');
+    }
+
+    $languages = array();
+
+    if(!$error_abort) {
+        while ($file = readdir($dir)) {
+            if (!$file || $file[0] == '.' || strpos($file, '.') === false) {
+                continue;
+            }
+            $lang = substr($file, 0,  strpos($file, '.'));
+            $languages[] = $lang;
+        }
+        closedir($dir);
+    }
+
+    $languages = array_unique($languages);
+    sort($languages);
+
+    if(!count($languages)) {
+        report_error(TYPE_WARNING, 'Unable to locate any usable language files in "'.GESHI_LANG_ROOT.'"!');
+    }
+
+    output_error_cache();
+}
+
+if (isset($_REQUEST['show']) && in_array($_REQUEST['show'], $languages)) {
+    $languages = array($_REQUEST['show']);
+}
+
+if(!$error_abort) {
+    foreach ($languages as $lang) {
+        echo "</li>\n<li>Validating language file for '$lang' ... ";
+
+        $langfile = GESHI_LANG_ROOT . $lang . '.php';
+
+        unset($language_data);
+
+        if(!is_file($langfile)) {
+            report_error(TYPE_ERROR, 'The path "' .$langfile. '" does not ressemble a regular file!');
+        } else if(!is_readable($langfile)) {
+            report_error(TYPE_ERROR, 'Cannot read file "' .$langfile. '"!');
+        } else {
+            $langfile_content = file_get_contents($langfile);
+            if(preg_match("/\?>(?:\r?\n|\r(?!\n)){2,}\Z/", $langfile_content)) {
+                report_error(TYPE_ERROR, 'Language file contains trailing empty lines at EOF!');
+            }
+            if(!preg_match("/\?>(?:\r?\n|\r(?!\n))?\Z/", $langfile_content)) {
+                report_error(TYPE_ERROR, 'Language file contains no PHP end marker at EOF!');
+            }
+            if(preg_match("/\t/", $langfile_content)) {
+                report_error(TYPE_NOTICE, 'Language file contains unescaped tabulator chars (probably for indentation)!');
+            }
+            if(preg_match('/^(?:    )*(?!    )(?! \*) /m', $langfile_content)) {
+                report_error(TYPE_NOTICE, 'Language file contains irregular indentation (other than 4 spaces per indentation level)!');
+            }
+
+            if(!preg_match("/\/\*\*((?!\*\/).)*?Author:((?!\*\/).)*?\*\//s", $langfile_content)) {
+                report_error(TYPE_WARNING, 'Language file does not contain a specification of an author!');
+            }
+            if(!preg_match("/\/\*\*((?!\*\/).)*?Copyright:((?!\*\/).)*?\*\//s", $langfile_content)) {
+                report_error(TYPE_WARNING, 'Language file does not contain a specification of the copyright!');
+            }
+            if(!preg_match("/\/\*\*((?!\*\/).)*?Release Version:((?!\*\/).)*?\*\//s", $langfile_content)) {
+                report_error(TYPE_WARNING, 'Language file does not contain a specification of the release version!');
+            }
+            if(!preg_match("/\/\*\*((?!\*\/).)*?Date Started:((?!\*\/).)*?\*\//s", $langfile_content)) {
+                report_error(TYPE_WARNING, 'Language file does not contain a specification of the date it was started!');
+            }
+            if(!preg_match("/\/\*\*((?!\*\/).)*?This file is part of GeSHi\.((?!\*\/).)*?\*\//s", $langfile_content)) {
+                report_error(TYPE_WARNING, 'Language file does not state that it belongs to GeSHi!');
+            }
+            if(!preg_match("/\/\*\*((?!\*\/).)*?language file for GeSHi\.((?!\*\/).)*?\*\//s", $langfile_content)) {
+                report_error(TYPE_WARNING, 'Language file does not state that it is a language file for GeSHi!');
+            }
+            if(!preg_match("/\/\*\*((?!\*\/).)*?GNU General Public License((?!\*\/).)*?\*\//s", $langfile_content)) {
+                report_error(TYPE_WARNING, 'Language file does not state that it is provided under the terms of the GNU GPL!');
+            }
+
+            unset($langfile_content);
+
+            include $langfile;
+
+            if(!isset($language_data)) {
+                report_error(TYPE_ERROR, 'Language file does not contain a $language_data structure to check!');
+            } else if (!is_array($language_data)) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data structure which is not an array!');
+            }
+        }
+
+        if(!$error_abort) {
+            if(!isset($language_data['LANG_NAME'])) {
+                report_error(TYPE_ERROR, 'Language file contains no $language_data[\'LANG_NAME\'] specification!');
+            } else if (!is_string($language_data['LANG_NAME'])) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'LANG_NAME\'] specification which is not a string!');
+            }
+
+            if(!isset($language_data['COMMENT_SINGLE'])) {
+                report_error(TYPE_ERROR, 'Language file contains no $language_data[\'COMMENT_SIGNLE\'] structure to check!');
+            } else if (!is_array($language_data['COMMENT_SINGLE'])) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'COMMENT_SINGLE\'] structure which is not an array!');
+            }
+
+            if(!isset($language_data['COMMENT_MULTI'])) {
+                report_error(TYPE_ERROR, 'Language file contains no $language_data[\'COMMENT_MULTI\'] structure to check!');
+            } else if (!is_array($language_data['COMMENT_MULTI'])) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'COMMENT_MULTI\'] structure which is not an array!');
+            }
+
+            if(isset($language_data['COMMENT_REGEXP'])) {
+                if (!is_array($language_data['COMMENT_REGEXP'])) {
+                    report_error(TYPE_ERROR, 'Language file contains a $language_data[\'COMMENT_REGEXP\'] structure which is not an array!');
+                }
+            }
+
+            if(!isset($language_data['QUOTEMARKS'])) {
+                report_error(TYPE_ERROR, 'Language file contains no $language_data[\'QUOTEMARKS\'] structure to check!');
+            } else if (!is_array($language_data['QUOTEMARKS'])) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'QUOTEMARKS\'] structure which is not an array!');
+            }
+
+            if(isset($language_data['HARDQUOTE'])) {
+                if (!is_array($language_data['HARDQUOTE'])) {
+                    report_error(TYPE_ERROR, 'Language file contains a $language_data[\'HARDQUOTE\'] structure which is not an array!');
+                }
+            }
+
+            if(!isset($language_data['ESCAPE_CHAR'])) {
+                report_error(TYPE_ERROR, 'Language file contains no $language_data[\'ESCAPE_CHAR\'] specification to check!');
+            } else if (!is_string($language_data['ESCAPE_CHAR'])) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'ESCAPE_CHAR\'] specification which is not a string!');
+            } else if (1 < strlen($language_data['ESCAPE_CHAR'])) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'ESCAPE_CHAR\'] specification is not empty or exactly one char!');
+            }
+
+            if(!isset($language_data['CASE_KEYWORDS'])) {
+                report_error(TYPE_ERROR, 'Language file contains no $language_data[\'CASE_KEYWORDS\'] specification!');
+            } else if (!is_int($language_data['CASE_KEYWORDS'])) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'CASE_KEYWORDS\'] specification which is not an integer!');
+            } else if (GESHI_CAPS_NO_CHANGE != $language_data['CASE_KEYWORDS'] &&
+                GESHI_CAPS_LOWER != $language_data['CASE_KEYWORDS'] &&
+                GESHI_CAPS_UPPER != $language_data['CASE_KEYWORDS']) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'CASE_KEYWORDS\'] specification which is neither of GESHI_CAPS_NO_CHANGE, GESHI_CAPS_LOWER nor GESHI_CAPS_UPPER!');
+            }
+
+            if(!isset($language_data['KEYWORDS'])) {
+                report_error(TYPE_ERROR, 'Language file contains no $language_data[\'KEYWORDS\'] structure to check!');
+            } else if (!is_array($language_data['KEYWORDS'])) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'KEYWORDS\'] structure which is not an array!');
+            } else {
+                foreach($language_data['KEYWORDS'] as $kw_key => $kw_value) {
+                    if(!is_integer($kw_key)) {
+                        report_error(TYPE_WARNING, "Language file contains an key '$kw_key' in \$language_data['KEYWORDS'] that is not integer!");
+                    } else if (!is_array($kw_value)) {
+                        report_error(TYPE_ERROR, "Language file contains a \$language_data['CASE_SENSITIVE']['$kw_value'] structure which is not an array!");
+                    }
+                }
+            }
+
+            if(!isset($language_data['SYMBOLS'])) {
+                report_error(TYPE_ERROR, 'Language file contains no $language_data[\'SYMBOLS\'] structure to check!');
+            } else if (!is_array($language_data['SYMBOLS'])) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'SYMBOLS\'] structure which is not an array!');
+            }
+
+            if(!isset($language_data['CASE_SENSITIVE'])) {
+                report_error(TYPE_ERROR, 'Language file contains no $language_data[\'CASE_SENSITIVE\'] structure to check!');
+            } else if (!is_array($language_data['CASE_SENSITIVE'])) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'CASE_SENSITIVE\'] structure which is not an array!');
+            } else {
+                foreach($language_data['CASE_SENSITIVE'] as $cs_key => $cs_value) {
+                    if(!is_integer($cs_key)) {
+                        report_error(TYPE_WARNING, "Language file contains an key '$cs_key' in \$language_data['CASE_SENSITIVE'] that is not integer!");
+                    } else if (!is_bool($cs_value)) {
+                        report_error(TYPE_ERROR, "Language file contains a Case Sensitivity specification for \$language_data['CASE_SENSITIVE']['$cs_value'] which is not a boolean!");
+                    }
+                }
+            }
+
+            if(!isset($language_data['URLS'])) {
+                report_error(TYPE_ERROR, 'Language file contains no $language_data[\'URLS\'] structure to check!');
+            } else if (!is_array($language_data['URLS'])) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'URLS\'] structure which is not an array!');
+            } else {
+                foreach($language_data['URLS'] as $url_key => $url_value) {
+                    if(!is_integer($url_key)) {
+                        report_error(TYPE_WARNING, "Language file contains an key '$url_key' in \$language_data['URLS'] that is not integer!");
+                    } else if (!is_string($url_value)) {
+                        report_error(TYPE_ERROR, "Language file contains a Documentation URL specification for \$language_data['URLS']['$url_value'] which is not a string!");
+                    } else if (preg_match('#&([^;]*(=|$))#U', $url_value)) {
+                        report_error(TYPE_ERROR, "Language file contains unescaped ampersands (&amp;) in \$language_data['URLS']!");
+                    }
+                }
+            }
+
+            if(!isset($language_data['OOLANG'])) {
+                report_error(TYPE_ERROR, 'Language file contains no $language_data[\'OOLANG\'] specification!');
+            } else if (!is_int($language_data['OOLANG']) && !is_bool($language_data['OOLANG'])) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'OOLANG\'] specification which is neither boolean nor integer!');
+            } else if (false !== $language_data['OOLANG'] &&
+                true !== $language_data['OOLANG'] &&
+                2 !== $language_data['OOLANG']) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'OOLANG\'] specification which is neither of false, true or 2!');
+            }
+
+            if(!isset($language_data['OBJECT_SPLITTERS'])) {
+                report_error(TYPE_ERROR, 'Language file contains no $language_data[\'OBJECT_SPLITTERS\'] structure to check!');
+            } else if (!is_array($language_data['OBJECT_SPLITTERS'])) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'OBJECT_SPLITTERS\'] structure which is not an array!');
+            }
+
+            if(!isset($language_data['REGEXPS'])) {
+                report_error(TYPE_ERROR, 'Language file contains no $language_data[\'REGEXPS\'] structure to check!');
+            } else if (!is_array($language_data['REGEXPS'])) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'REGEXPS\'] structure which is not an array!');
+            }
+
+            if(!isset($language_data['STRICT_MODE_APPLIES'])) {
+                report_error(TYPE_ERROR, 'Language file contains no $language_data[\'STRICT_MODE_APPLIES\'] specification!');
+            } else if (!is_int($language_data['STRICT_MODE_APPLIES'])) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'STRICT_MODE_APPLIES\'] specification which is not an integer!');
+            } else if (GESHI_MAYBE != $language_data['STRICT_MODE_APPLIES'] &&
+                GESHI_ALWAYS != $language_data['STRICT_MODE_APPLIES'] &&
+                GESHI_NEVER != $language_data['STRICT_MODE_APPLIES']) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'STRICT_MODE_APPLIES\'] specification which is neither of GESHI_MAYBE, GESHI_ALWAYS nor GESHI_NEVER!');
+            }
+
+            if(!isset($language_data['SCRIPT_DELIMITERS'])) {
+                report_error(TYPE_ERROR, 'Language file contains no $language_data[\'SCRIPT_DELIMITERS\'] structure to check!');
+            } else if (!is_array($language_data['SCRIPT_DELIMITERS'])) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'SCRIPT_DELIMITERS\'] structure which is not an array!');
+            }
+
+            if(!isset($language_data['HIGHLIGHT_STRICT_BLOCK'])) {
+                report_error(TYPE_ERROR, 'Language file contains no $language_data[\'HIGHLIGHT_STRICT_BLOCK\'] structure to check!');
+            } else if (!is_array($language_data['HIGHLIGHT_STRICT_BLOCK'])) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'HIGHLIGHT_STRICT_BLOCK\'] structure which is not an array!');
+            }
+
+            if(isset($language_data['TAB_WIDTH'])) {
+                if (!is_int($language_data['TAB_WIDTH'])) {
+                    report_error(TYPE_ERROR, 'Language file contains a $language_data[\'TAB_WIDTH\'] specification which is not an integer!');
+                } else if (1 > $language_data['TAB_WIDTH']) {
+                    report_error(TYPE_ERROR, 'Language file contains a $language_data[\'TAB_WIDTH\'] specification which is less than 1!');
+                }
+            }
+
+            if(isset($language_data['PARSER_CONTROL'])) {
+                if (!is_array($language_data['PARSER_CONTROL'])) {
+                    report_error(TYPE_ERROR, 'Language file contains a $language_data[\'PARSER_CONTROL\'] structure which is not an array!');
+                }
+            }
+
+            if(!isset($language_data['STYLES'])) {
+                report_error(TYPE_ERROR, 'Language file contains no $language_data[\'STYLES\'] structure to check!');
+            } else if (!is_array($language_data['STYLES'])) {
+                report_error(TYPE_ERROR, 'Language file contains a $language_data[\'STYLES\'] structure which is not an array!');
+            } else {
+                $style_arrays = array('KEYWORDS', 'COMMENTS', 'ESCAPE_CHAR',
+                    'BRACKETS', 'STRINGS', 'NUMBERS', 'METHODS', 'SYMBOLS',
+                    'REGEXPS', 'SCRIPT');
+                foreach($style_arrays as $style_kind) {
+                    if(!isset($language_data['STYLES'][$style_kind])) {
+                        report_error(TYPE_ERROR, "Language file contains no \$language_data['STYLES']['$style_kind'] structure to check!");
+                    } else if (!is_array($language_data['STYLES'][$style_kind])) {
+                        report_error(TYPE_ERROR, "Language file contains a \$language_data['STYLES\']['$style_kind'] structure which is not an array!");
+                    } else {
+                        foreach($language_data['STYLES'][$style_kind] as $sk_key => $sk_value) {
+                            if(!is_int($sk_key) && ('COMMENTS' != $style_kind && 'MULTI' != $sk_key)
+                                && !(('STRINGS' == $style_kind || 'ESCAPE_CHAR' == $style_kind) && 'HARD' == $sk_key)) {
+                                report_error(TYPE_WARNING, "Language file contains an key '$sk_key' in \$language_data['STYLES']['$style_kind'] that is not integer!");
+                            } else if (!is_string($sk_value)) {
+                                report_error(TYPE_WARNING, "Language file contains a CSS specification for \$language_data['STYLES']['$style_kind'][$key] which is not a string!");
+                            }
+                        }
+                    }
+                }
+
+                unset($style_arrays);
+            }
+        }
+
+        if(!$error_abort) {
+            //Initial sanity checks survived? --> Let's dig deeper!
+            foreach($language_data['KEYWORDS'] as $key => $keywords) {
+                if(!isset($language_data['CASE_SENSITIVE'][$key])) {
+                    report_error(TYPE_ERROR, "Language file contains no \$language_data['CASE_SENSITIVE'] specification for keyword group $key!");
+                }
+                if(!isset($language_data['URLS'][$key])) {
+                    report_error(TYPE_ERROR, "Language file contains no \$language_data['URLS'] specification for keyword group $key!");
+                }
+                if(empty($keywords)) {
+                    report_error(TYPE_WARNING, "Language file contains an empty keyword list in \$language_data['KEYWORDS'] for group $key!");
+                }
+                foreach($keywords as $id => $kw) {
+                    if(!is_string($kw)) {
+                        report_error(TYPE_WARNING, "Language file contains an non-string entry at \$language_data['KEYWORDS'][$key][$id]!");
+                    } else if (!strlen($kw)) {
+                        report_error(TYPE_ERROR, "Language file contains an empty string entry at \$language_data['KEYWORDS'][$key][$id]!");
+                    } else if (preg_match('/^([\(\)\{\}\[\]\^=.,:;\-+\*\/%\$\"\'\?]|&[\w#]\w*;)+$/i', $kw)) {
+                        report_error(TYPE_NOTICE, "Language file contains an keyword ('$kw') at \$language_data['KEYWORDS'][$key][$id] which seems to be better suited for the symbols section!");
+                    }
+                }
+                if(count($keywords) != count(array_unique($keywords))) {
+                    $kw_diffs = array_count_values($keywords);
+                    foreach($kw_diffs as $kw => $kw_count) {
+                        if($kw_count > 1) {
+                            report_error(TYPE_WARNING, "Language file contains per-group duplicate keyword '$kw' in \$language_data['KEYWORDS'][$key]!");
+                        }
+                    }
+                }
+            }
+
+            $disallowed_before = "(?<![a-zA-Z0-9\$_\|\#;>|^&";
+            $disallowed_after = "(?![a-zA-Z0-9_\|%\\-&;";
+
+            foreach($language_data['KEYWORDS'] as $key => $keywords) {
+                foreach($language_data['KEYWORDS'] as $key2 => $keywords2) {
+                    if($key2 <= $key) {
+                        continue;
+                    }
+                    $kw_diffs = array_intersect($keywords, $keywords2);
+                    foreach($kw_diffs as $kw) {
+                        if(isset($language_data['PARSER_CONTROL']['KEYWORDS'])) {
+                            //Check the precondition\post-cindition for the involved keyword groups
+                            $g1_pre = $disallowed_before;
+                            $g2_pre = $disallowed_before;
+                            $g1_post = $disallowed_after;
+                            $g2_post = $disallowed_after;
+                            if(isset($language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'])) {
+                                $g1_pre = $language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'];
+                                $g2_pre = $language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'];
+                            }
+                            if(isset($language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'])) {
+                                $g1_post = $language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'];
+                                $g2_post = $language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'];
+                            }
+
+                            if(isset($language_data['PARSER_CONTROL']['KEYWORDS'][$key]['DISALLOWED_BEFORE'])) {
+                                $g1_pre = $language_data['PARSER_CONTROL']['KEYWORDS'][$key]['DISALLOWED_BEFORE'];
+                            }
+                            if(isset($language_data['PARSER_CONTROL']['KEYWORDS'][$key]['DISALLOWED_AFTER'])) {
+                                $g1_post = $language_data['PARSER_CONTROL']['KEYWORDS'][$key]['DISALLOWED_AFTER'];
+                            }
+
+                            if(isset($language_data['PARSER_CONTROL']['KEYWORDS'][$key2]['DISALLOWED_BEFORE'])) {
+                                $g2_pre = $language_data['PARSER_CONTROL']['KEYWORDS'][$key2]['DISALLOWED_BEFORE'];
+                            }
+                            if(isset($language_data['PARSER_CONTROL']['KEYWORDS'][$key2]['DISALLOWED_AFTER'])) {
+                                $g2_post = $language_data['PARSER_CONTROL']['KEYWORDS'][$key2]['DISALLOWED_AFTER'];
+                            }
+
+                            if($g1_pre != $g2_pre || $g1_post != $g2_post) {
+                                continue;
+                            }
+                        }
+                        report_error(TYPE_WARNING, "Language file contains cross-group duplicate keyword '$kw' in \$language_data['KEYWORDS'][$key] and \$language_data['KEYWORDS'][$key2]!");
+                    }
+                }
+            }
+            foreach($language_data['CASE_SENSITIVE'] as $key => $keywords) {
+                if(!isset($language_data['KEYWORDS'][$key]) && $key != GESHI_COMMENTS) {
+                    report_error(TYPE_WARNING, "Language file contains an superfluous \$language_data['CASE_SENSITIVE'] specification for non-existing keyword group $key!");
+                }
+            }
+            foreach($language_data['URLS'] as $key => $keywords) {
+                if(!isset($language_data['KEYWORDS'][$key])) {
+                    report_error(TYPE_WARNING, "Language file contains an superfluous \$language_data['URLS'] specification for non-existing keyword group $key!");
+                }
+            }
+            foreach($language_data['STYLES']['KEYWORDS'] as $key => $keywords) {
+                if(!isset($language_data['KEYWORDS'][$key])) {
+                    report_error(TYPE_WARNING, "Language file contains an superfluous \$language_data['STYLES']['KEYWORDS'] specification for non-existing keyword group $key!");
+                }
+            }
+
+            foreach($language_data['COMMENT_SINGLE'] as $ck => $cv) {
+                if(!is_int($ck)) {
+                    report_error(TYPE_WARNING, "Language file contains an key '$ck' in \$language_data['COMMENT_SINGLE'] that is not integer!");
+                }
+                if(!is_string($cv)) {
+                    report_error(TYPE_WARNING, "Language file contains an non-string entry at \$language_data['COMMENT_SINGLE'][$ck]!");
+                }
+                if(!isset($language_data['STYLES']['COMMENTS'][$ck])) {
+                    report_error(TYPE_WARNING, "Language file contains no \$language_data['STYLES']['COMMENTS'] specification for comment group $ck!");
+                }
+            }
+            if(isset($language_data['COMMENT_REGEXP'])) {
+                foreach($language_data['COMMENT_REGEXP'] as $ck => $cv) {
+                    if(!is_int($ck)) {
+                        report_error(TYPE_WARNING, "Language file contains an key '$ck' in \$language_data['COMMENT_REGEXP'] that is not integer!");
+                    }
+                    if(!is_string($cv)) {
+                        report_error(TYPE_WARNING, "Language file contains an non-string entry at \$language_data['COMMENT_REGEXP'][$ck]!");
+                    }
+                    if(!isset($language_data['STYLES']['COMMENTS'][$ck])) {
+                        report_error(TYPE_WARNING, "Language file contains no \$language_data['STYLES']['COMMENTS'] specification for comment group $ck!");
+                    }
+                }
+            }
+            foreach($language_data['STYLES']['COMMENTS'] as $ck => $cv) {
+                if($ck != 'MULTI' && !isset($language_data['COMMENT_SINGLE'][$ck]) &&
+                    !isset($language_data['COMMENT_REGEXP'][$ck])) {
+                    report_error(TYPE_NOTICE, "Language file contains an superfluous \$language_data['STYLES']['COMMENTS'] specification for Single Line or Regular-Expression Comment key $ck!");
+                }
+            }
+            if (isset($language_data['STYLES']['STRINGS']['HARD'])) {
+                if (empty($language_data['HARDQUOTE'])) {
+                    report_error(TYPE_NOTICE, "Language file contains superfluous \$language_data['STYLES']['STRINGS'] specification for key 'HARD', but no 'HARDQUOTE's are defined!");
+                }
+                unset($language_data['STYLES']['STRINGS']['HARD']);
+            }
+            foreach($language_data['STYLES']['STRINGS'] as $sk => $sv) {
+                if($sk && !isset($language_data['QUOTEMARKS'][$sk])) {
+                    report_error(TYPE_NOTICE, "Language file contains an superfluous \$language_data['STYLES']['STRINGS'] specification for non-existing quotemark key $sk!");
+                }
+            }
+
+            foreach($language_data['REGEXPS'] as $rk => $rv) {
+                if(!is_int($rk)) {
+                    report_error(TYPE_WARNING, "Language file contains an key '$rk' in \$language_data['REGEXPS'] that is not integer!");
+                }
+                if(is_string($rv)) {
+                    //Check for unmasked / in regular expressions ...
+                    if(empty($rv)) {
+                        report_error(TYPE_WARNING, "Language file contains an empty regular expression at \$language_data['REGEXPS'][$rk]!");
+                    } else {
+                        if(preg_match("/(?<!\\\\)\//s", $rv)) {
+                            report_error(TYPE_WARNING, "Language file contains a regular expression with an unmasked / character at \$language_data['REGEXPS'][$rk]!");
+                        } elseif (preg_match("/(?<!<)(\\\\\\\\)*\\\\\|(?!>)/s", $rv)) {
+                            report_error(TYPE_WARNING, "Language file contains a regular expression with an unescaped match for a pipe character '|' which needs escaping as '&lt;PIPE&gt;' instead at \$language_data['REGEXPS'][$rk]!");
+                        }
+                    }
+                } elseif(is_array($rv)) {
+                    if(!isset($rv[GESHI_SEARCH])) {
+                        report_error(TYPE_ERROR, "Language file contains no GESHI_SEARCH entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
+                    } elseif(!is_string($rv[GESHI_SEARCH])) {
+                        report_error(TYPE_ERROR, "Language file contains a GESHI_SEARCH entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!");
+                    } else {
+                        if(preg_match("/(?<!\\\\)\//s", $rv[GESHI_SEARCH])) {
+                            report_error(TYPE_WARNING, "Language file contains a regular expression with an unmasked / character at \$language_data['REGEXPS'][$rk]!");
+                        } elseif (preg_match("/(?<!<)(\\\\\\\\)*\\\\\|(?!>)/s", $rv[GESHI_SEARCH])) {
+                            report_error(TYPE_WARNING, "Language file contains a regular expression with an unescaped match for a pipe character '|' which needs escaping as '&lt;PIPE&gt;' instead at \$language_data['REGEXPS'][$rk]!");
+                        }
+                    }
+                    if(!isset($rv[GESHI_REPLACE])) {
+                        report_error(TYPE_WARNING, "Language file contains no GESHI_REPLACE entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
+                    } elseif(!is_string($rv[GESHI_REPLACE])) {
+                        report_error(TYPE_ERROR, "Language file contains a GESHI_REPLACE entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!");
+                    }
+                    if(!isset($rv[GESHI_MODIFIERS])) {
+                        report_error(TYPE_WARNING, "Language file contains no GESHI_MODIFIERS entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
+                    } elseif(!is_string($rv[GESHI_MODIFIERS])) {
+                        report_error(TYPE_ERROR, "Language file contains a GESHI_MODIFIERS entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!");
+                    }
+                    if(!isset($rv[GESHI_BEFORE])) {
+                        report_error(TYPE_WARNING, "Language file contains no GESHI_BEFORE entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
+                    } elseif(!is_string($rv[GESHI_BEFORE])) {
+                        report_error(TYPE_ERROR, "Language file contains a GESHI_BEFORE entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!");
+                    }
+                    if(!isset($rv[GESHI_AFTER])) {
+                        report_error(TYPE_WARNING, "Language file contains no GESHI_AFTER entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
+                    } elseif(!is_string($rv[GESHI_AFTER])) {
+                        report_error(TYPE_ERROR, "Language file contains a GESHI_AFTER entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!");
+                    }
+                } else {
+                    report_error(TYPE_WARNING, "Language file contains an non-string and non-array entry at \$language_data['REGEXPS'][$rk]!");
+                }
+                if(!isset($language_data['STYLES']['REGEXPS'][$rk])) {
+                    report_error(TYPE_WARNING, "Language file contains no \$language_data['STYLES']['REGEXPS'] specification for regexp group $rk!");
+                }
+            }
+            foreach($language_data['STYLES']['REGEXPS'] as $rk => $rv) {
+                if(!isset($language_data['REGEXPS'][$rk])) {
+                    report_error(TYPE_NOTICE, "Language file contains an superfluous \$language_data['STYLES']['REGEXPS'] specification for regexp key $rk!");
+                }
+            }
+
+
+        }
+
+        output_error_cache();
+
+        flush();
+
+        if($error_abort) {
+            break;
+        }
+    }
+}
+?></li>
+</ol>
+
+<p>Validation process completed in <?
+$time_end = explode(' ', microtime());
+$time_diff = $time_end[0] + $time_end[1] - $time_start[0] - $time_start[1];
+
+echo sprintf("%.2f", $time_diff);
+?> seconds.</p>
+
+<div id="footer">GeSHi &copy; 2004-2007 Nigel McNie, 2007-2008 Benny Baumann, released under the GNU GPL</div>
+</body>
+</html>
diff --git a/examples/includes/geshi/docs/BUGS b/examples/includes/geshi/docs/BUGS
new file mode 100644 (file)
index 0000000..8a5cf04
--- /dev/null
@@ -0,0 +1,29 @@
+
+                      BUGS - list of known bugs in GeSHi
+                                Version 1.0.8
+
+- Number highlighting is quite poor [possibly better now]
+- I'm not happy with URLS - there still could be extra bugs, and it's rather unflexible
+  (see TODO for a possible fix)
+- "Important" sections for some reason seem to have their spans added after every
+  newline up until the next lexic, instead of stopping at the <END GeSHi> part. In fact,
+  context sensitiveness is quite poor...
+- Using the extra line number highlighting feature without actually using line numbers
+  will result in malformed XHTML (not sure about this one though...)
+- Slow!!! Especially for source with lots of strings in it. GeSHi will work acceptably
+  for sourcecode under 5K (for simple language files like SQL, a 100K file can be
+  highlighted in just 6 seconds), but above about 25K things get a little slow... If
+  you're using this as part of some larger software, you may want to think about
+  making some sort of "cache" effect to speed things up and reduce server load.
+- The result is built by string replacement instead of by building another string based
+  on the source, that would be much safer. The focus of releases beyond 1.0.7 will be on
+  changing this behaviour, which may well fix some of the other bugs mentioned above.
+- As of 1.0.7.1, dots (.) are allowed before keywords. This may change highlighting of some
+  things slightly, if you notice anything odd about the highlighting then please report
+  it to me.
+- Perl/Javascript /.../ regex syntax is only supported basically and there's no
+  guarantee it is working all the time.
+- The <pre> header output is not XHTML compliant. Please use the <div> header instead.
+
+Send any bug reports to BenBE@omorphia.de, or submit them via the bug tracker at
+sourceforge (http://sourceforge.net/tracker/?group_id=114997&atid=670231)
diff --git a/examples/includes/geshi/docs/CHANGES b/examples/includes/geshi/docs/CHANGES
new file mode 100644 (file)
index 0000000..d64c4e5
--- /dev/null
@@ -0,0 +1,682 @@
+
+              CHANGES - Changelog for GeSHi (geshi.php only)
+
+Changes to the code are listed under the version they occured in, with who suggested
+it by each one (if there's nobody listed as suggesting it I dreamed it up :)). Users
+who suggested an idea often also provided the code that was used as a basis for the
+changes - thanks to all who suggested these ideas and gave me the code to show me how!
+
+Language files listed under each version were made by the author beside them, and then
+modified by me for consistency/bug fixing.
+
+Please send any bug reports to BenBE@omorphia.de, or use the bug report tracker
+at sourceforge (http://sourceforge.net/tracker/?group_id=114997&atid=670231)
+
+Version 1.0.8.3
+  -  Added language files
+     * DCS (Stelio Passaris)
+     * Locomotive Basic (Nacho Cabanes)
+     * LSL2 (Linden Scripting Language) (William Fry)
+     * Modula-3 (Martin Bishop)
+     * Oberon-2 (Mike Mol)
+     * Rebol (Lecanu Guillaume)
+  -  Fixed a problem where HardEscapes weren't working when no escape char was given (BenBE)
+  -  Added a PARSER_CONTROL setting to treat whitespace inside of keywords in
+     the language file as "any whitespace" in the source (i.e. "CREATE TABLE"
+     in SQL will match "CREATE\s+TABLE" instead of literally matching) (BenBE)
+  -  Added a possibility to allow setting the style for escape characters (BenBE)
+  -  Improvements to language files (BenBE)
+     * Added some missing Perl keywords and obscure default variables (BenBE)
+     * Allow for escaped colons to appear in CSS names (BenBE, simon)
+     * Added multiline continuation suppoert of preprocessor defines for
+       C, C for Mac, C++ and CC++ with Qt support (BenBE)
+     * keywords for C-based languages are case-sensitive (BenBE)
+     * Broken AutoIt highlighting (BenBE)
+     * Problem with escaped backslash in PHP and D (BenBE)
+     * Added some more functions for PHP (BenBE)
+     * Some changes for AppleScript (Stefan Klieme)
+     * Forbid highlighting keywords followed by / in bash (BenBE)
+     * Updated the LaTeX file to link some keywords (BenBE)
+     * Additional text rendered when matching special variables for PowerShell (BenBE)
+     * Added some more keywords for ABAP (BenBE, Sandra Rossi, Jacob Laursen)
+Version 1.0.8.2
+  -  Added language files
+     * Brainfuck \ Brainfork (Benny Baumann)
+     * HQ9+ (Benny Baumann)
+     * INTERCAL (Benny Baumann)
+     * LOLcode (Benny Baumann)
+     * LScript (Beau McGuigan)
+     * Pixel Bender (Richard Olsson)
+     * ProvideX (Jeff Wilder)
+     * VIM Script (Swaroop C H)
+     * Visual Prolog (Thomas Linder Puls)
+     * Whitespace (Benny Baumann)
+  -  Changed priority for COMMENT_REGEXP compared to String highlighting (BenBE)
+  -  Fixed correct escaping of spaces inside of URLs (BenBE)
+  -  Updated the list of common file extensions (BenBE)
+  -  Updated the language file check script in contrib/ (BenBE)
+  -  Fixed a problem with link targets resulting in unclickable links (SF#2379120, BenBE)
+  -  Fixed an undefined variable issue in langcheck.php (BenBE)
+  -  Improvements to language files (BenBE)
+     * eMail Header highlighting now uses the correct delimiters for keywords (BenBE)
+     * eMail (RFC822\mbox) highlighting now highlights IPs, MIME types and
+       subfield assignments correctly (BenBE)
+     * Minor style changes in COBOL to improve loading performance (BenBE)
+     * Added some missing keywords for D (BenBE)
+     * Removed duplicate keywords from Progres, SAS and TSQL (BenBE)
+     * Fixed Heredoc Syntax for Bash (SF#2185319, BenBE)
+     * Moved symbol-lookalike sequences from keyword groups to separate symbol group
+       for languages asp, klonec, klonecpp, php, php-brief (BenBE)
+     * Fixed a lot of duplicate keyword warnings (BenBE)
+     * Added missing keywords to the Python language file,
+       introducing support for Python 3.0. (SF#2441839, milian)
+     * Updated documentation links for TypoScript (SF#2014276, BenBE)
+     * Fixed a problem with tag and attribute names in XML highlighting (SF#2276119, BenBE)
+     * Improved MySQL language file (BenBE, JavaWoman)
+     * Some commentss accidentially mistaken for DocComments (SF#2454897, BenBE)
+     * Added improved Escape Char handling for c, c_mac, cpp and cpp_qt (SF#2458743, BenBE)
+Version 1.0.8.1
+  -  Added language files
+     * AviSynth (Ryan Jones)
+     * eMail \ mbox (Benny Baumann)
+     * GNU Make (Neil Bird)
+     * Oracle 11i support (Simon Redhead)
+     * Prolog (Benny Baumann)
+     * SciLab (Christophe David)
+     * TeraTerm macro language (Boris Maisuradze)
+  -  Added support for Escape Regular Expressions (BenBE)
+     * Implemented C-style Escapes in PHP (BenBE)
+     * Introduced support for \xAB and \007 style Char Escapes in PHP (BenBE)
+     * Implemented Variable Highlighting in PHP (BenBE)
+     * Implemented Variable Highlighting in Bash (milian)
+  -  Fixed a problem with PCRE patterns for Keyword matching sometimes producing
+     very large strings, that could not be handled by some versions of PCRE lib,
+     causing broken highlighting an Regexp Compile errors (BenBE, milian)
+  -  Fixed broken highlighting of bash commands like `dbus-send --dest=org.....`,
+     i.e. the dest was highlighted as variable declaration (milian)
+  -  Fixed broken highlighting of some symbols in their escaped form (BenBE)
+     (<SEMI> and <PIPE> were accidentially filtered even though they are valid)
+  -  Fixed a "memory leak" in the *_regexp_caches (milian)
+  -  Fixed broken Escape chars if classes were disabled
+  -  start_line_numbers_at() was ignored when GESHI_HEADER_PRE_TABLE was set (revulo)
+  -  Fixed a problem allowing Remote Code Inclusion under certain circumstances (BenBE)
+  -  Changes to default CSS in order to make the GESHI_HEADER_PRE_TABLE align properly,
+     even on Windows / Mac systems with strange fonts (milian, revulo, ^RT)
+  -  Minor style changes to the following languages:
+     * cpp-qt (milian)
+     * MySQL (BenBE)
+     * PHP (BenBE)
+  -  Improvements to language files (BenBE, milian)
+     * Added MinSpareThread\MaxSpareThreads to Apache highlighter (BenBE)
+     * Added new Keyword group for APT sources.list highlighter (BenBE)
+     * Fixed highlighting in LaTeX for \begin{} and \end{}, i.e. the stuff inside
+       the curly braces. (milian, thanks for the report go to Matthias Pospiech)
+     * Improved String support for D (BenBE)
+     * MySQL was seriously broken (BenBE)
+     * Reworked Keyword groups for MySQL to allow for more configuration (BenBE)
+     * Improved Mirc script language file (milian)
+     * Improved C++ Qt language file (milian)
+     * Minor bug with Transpose Operator in Matlab (BenBE, Daniele de Rigo)
+     * Highlighting of Batch Files for Windows (BenBE)
+     * Updated AutoIt to include latest changes for AutoIt v3.2.12.1 (BenBE, Thierry)
+     * Fixed duplicate keyword warnings for Perl, Tcl and Typoscript (BenBE)
+     * Fixed Doc-URL getting reparsed by highlighted keywords of other groups (BenBE, Jordi Boggiano)
+Version 1.0.8
+  -  Added language files
+     * APT sources.list (milian)
+     * Boo (Marcus Griep)
+     * CIL (Common Intermediate Language, .NET Assembly) (Marcus Griep)
+     * COBOL (Benny Baumann)
+     * Gnuplot (milian)
+     * KLoneC (Mickael Auger)
+     * KLoneC++ (Mickael Auger)
+     * PIC16xxx assembler (Phil Mattison)
+     * POV-Ray (Carl Fürstenberg)
+     * PowerShell (Frode Aarebrot)
+     * Progress (Marco Aurelio de Pasqual)
+     * TypoScript (Jan-Philipp Halle)
+     * Xorg configuration (milian)
+  -  Make GeSHi's constructor arguments optional, so something like `$foo = new GeSHi;` is possible. (milian)
+  -  Added an optimizer for lists to regular expressions. Using these cached lists results in a speedup of approx. 50%.
+     The slightly increased memory consumption (~150KB for PHP language file) is more than worth it! (milian)
+  -  Some more memory & speed optimizations all over GeSHi (milian)
+     * Reduced memory overhead when highlighting keywords (BenBE)
+     * Keyword Linking now uses considerably less strtolower calls (milian)
+     * Cache Symbol Search Regexp and make Symbol Highlighting faster (milian)
+     * Use more native functions like substr_replace and strcasecmp to speed things up (milian)
+     * Use considerably less strlen() calls on various points by caching the results (milian)
+     * Properly set comments to be case insensitive where appropriate to increase performance (milian)
+     * Improve the performance of the strict mode tokenizer, making highlighting of languages like
+       HTML, ColdFusion or XML faster (milian)
+     * Setup caches for parsing on demand to make stylesheet generators fast (milian)
+  -  Various improvements to Strict Block Handling (BenBE, milian)
+     * Added support for RegExp-based Strict Blocks (BenBE)
+     * Fixed highlighting incorrectly stopping at ?> in PHP (SF#1330968, BenBE)
+     * Languages with STRICT_MODE_APPLIES = GESHI_MAYBE default to strict mode now. When no highlightable
+       code is found in this mode, we fallback to the same setting as if GESHI_NEVER was set. That way it
+       should not be needed to call enable_strictmode() manually. (milian)
+  -  Added new GESHI_HEADER_PRE_VALID type which uses the following markup: (milian)
+     * With line numbers:     <div>header<ol><li><pre>...</pre></li>...</ol></div>
+     * Without line numbers:  <pre>header...CODE...</pre>
+     => valid HTML and no need for &nbsp; indentation
+  -  Added new GESHI_HEADER_PRE_TABLE type which can be used to prevent linenumber-selection in Firefox
+     on copy'n'paste. (milian)
+  -  set_language will not reset any language settings by default anymore.
+     * Added $force_reset param for to force full reload of a language. (milian)
+     * Make sure strict_mode is set properly when doing repeated set_language calls (milian)
+  -  Fixed some problems with old PHP versions (SF#1975625, milian, BenBE)
+  -  Fixed broken use with Suhosin Patch when /e modifier was disabled (SF#2021800, BenBE)
+  -  Added support for external style information files to override language defaults without modifying language files (BenBE)
+  -  The overall_class is now up to the user, and the language-code is _always_ added as a class (milian)
+  -  Fixed Economy Mode for GeSHi::get_stylesheet() - now it just makes so much more sense! (milian)
+  -  Fixed Economy Mode when COMMENT_REGEXP are used (BenBE)
+  -  Changed the default encoding to use UTF-8, due to SF#2037598, BenBE)
+  -  Improved overall string support:
+     * Added support for multichar string delimiters (SF#1932083, BenBE)
+     * Fixed problems of unfinished strings and comments producing invalid XHTML (SF#1996353, BenBE)
+     * Multichar Quotemarks sometimes had inconsistent behaviour (BenBE)
+     * Support for multiple styles of strings depending on the starter (BenBE)
+     * Properly handle escapes in strings, i.e. '\\' was not working properly before (milian)
+     * Fixed escape char support when an escape char is followed by multi-byte chars (SF#2037598, BenBE)
+  -  Improved flexibility in language files (BenBE, milian)
+     * Added PARSER_CONTROL for OOLANG method highlighting (SF#1923060, BenBE)
+     * Added possibility to define strict blocks using an Regexp (BenBE)
+     * Removed explicit escaping of / in Regular Expressions (BenBE)
+     * Ignoring empty keyword groups when highlighting (milian)
+     * Make language_permissions configurable in language files via ['PARSER_CONTROL']['ENABLE_FLAGS']
+       this makes is_a calls unneeded and thus prevents PHP notices in PHP 5.x (milian)
+     * Extended support for number formats now covering the most common formats (SF#1923058, BenBE)
+     * Lifted a limitation that keywords had to have at least 2 subsequent letters (BenBE)
+     * Changed behaviour of PARSER_CONTROL now allowing to provide the full Lookahead and Lookbehind
+       expressions used as delimiters inside keywords instead of a simple char group (BenBE)
+     * Fixed improper handling of newlines in REGEXPS so this does not produce invalid html anylonger (milian)
+  -  Some typos and mistakes in the documentation (BenBE)
+  -  Added a script to contrib/ to verify language files are correct (BenBE)
+  -  Fixed loads of compliancy warnings detected with that automated compliance testing script (BenBE)
+  -  Many other improvements to various language files (BenBE, milian)
+     * Reduce strict errors & notices for language files (milian)
+     * Fixed symbol highlighting with C++ sometimes missing keywords after ; and comments (BenBE)
+     * Improved comment handling with TCL (Lars Hellström, BenBE)
+     * Fixed broken handling with XML comments (BenBE, SF#1849233)
+     * Fixed HTML comments spawning multiple lines producing invalid XHTML output (SF#1738173, BenBE)
+     * Added support for parameters beginning with dash in BASH language (BenBE)
+     * Support Apache's configuration sections, see http://httpd.apache.org/docs/2.2/sections.html (milian)
+     * Minor issue with PHP Heredoc and Nowdoc syntax sometimes not getting highlighted (BenBE)
+     * Updated Objective-C language file (SF#2013961, Quinn Taylor, BenBE)
+     * Added some keywords for VHDL (beshig, BenBE)
+     * Fixed severly broken ColdFusion language file (milian)
+     * Fixed some incorrectly highlighted things with the CSS language file (milian, BenBE)
+     * Improved Smarty language file (milian)
+     * Improved CSS language file (milian)
+     * Improved Pascal language file (milian)
+     * Improved LaTeX language file (Андрей Парамонов, BenBE)
+     * Fixed a regular expression in mIRC language file that caused a warning message to be issued (BenBE)
+     * Removed <, > and / from HTML names, now only containing the real tag names (BenBE)
+     * Use spaces instead of tabs for indendation in language files to have a consistent
+       coding standard accross geshi files (milian)
+     * Added some comment styles, keywords and added index highlighting (Chusslove Illich, Часлав Илић)
+  -  Removed some private methods which were only called at exactly one place (milian)
+     * format_header_content
+     * format_footer_content
+     * get_attributes
+  -  Second part of default style changes. Affected in this release:
+     * C++
+     * C++ (QT)
+     * CSS
+     * VHDL
+Version 1.0.7.22
+  -  Added language files
+     * glSlang (BenBE)
+     * KiXtart (Riley McArdle)
+     * Lotus Notes @Formulas (Richard Civil)
+     * LotusScript (Richard Civil)
+     * MXML (David Spurr)
+     * Scala (Franco Lombardo)
+     * ActionScript 3 (Jordi Boggiano)
+     * GNU Gettext .po/.pot (Milian Wolff)
+     * Verilog (Günter Dannoritzer)
+  -  Fixed a problem not yet addressed in 1.0.7.21 regarding highlighting of
+     symbols that caused some extra characters to be added in the output or
+     broke highlighting and standard compliance due to missing escaping of
+     internally used characters (SF#192320 and SF#1926259, BenBE)
+  -  Fixed missing style information for ocaml language file (The_PHP_Jedi)
+  -  Fixed a bug causing masses of warnings in rendered output if language file
+     miss style information (The_PHP_Jedi, BenBE)
+  -  Missing tab width information could lead to warnings (BenBE)
+  -  Missing symbol information for ASP (SF#1952038, nfsupport, BenBE)
+  -  Empty delimiter message with OOoBasic (BenBE, Ccornell)
+  -  Escaping of comments in LaTeX ignored (SF#1749806, BenBE)
+  -  Modified Math environment $$ in LaTeX to be non-greedy (BenBE)
+  -  Added possibility to match a regexp as comment (SF#1914640, SF#1945301, SF#1934832, BenBE)
+  -  Introduced C-Style multiline continuation comments (SF#1914640, SF#1945301, BenBE)
+  -  Introduced Fortran Comments (SF#1914640, SF#1934832, BenBE)
+  -  Implemented Heredoc and Nowdoc Syntax for PHP and Perl (SF#1914640, BenBE)
+  -  Implemented Compiler Directives for Delphi (SF#1914640, BenBE)
+  -  Implemented minimalistic support for JavaScript \ Perl Regular Expressions (SF#1786665, SF#1754333, SF#1956631, BenBE)
+  -  Fixed Strings in Matlab to be handled as comments instead of regexps, to prevent keywords being linked (BenBE)
+  -  Applied PARSER_CONTROL fix of CPP for CPP-QT-Derivative (BenBE)
+  -  Fixed incorrect treatment of unequally long multiline comment separators (related to SF #1891630, BenBE)
+  -  Added PARSER_CONTROL settings for keywords in ASM language file (SF#1835148, BenBE)
+  -  Fixed missing CASSE_SENSITIVE entry for DOS language file (SF#1956314, BenBE)
+  -  Fixed accidential highlighting of keywords in argument names (SF#1956456, Milian Wolff, BenBE)
+  -  Fixed yet again some #-related bash problem (SF#1956459, Milian Wolff, BenBE)
+  -  Added backticks as symbols (Milian Wolff)
+  -  Example script remembers selections and source submitted (Milian Wolff)
+  -  Example script allows remembered source and preselected language to be cleared (Milian Wolff)
+  -  Example script now properly includes geshi and doesn't suppress error messages anylonger. (Milian Wolff)
+  -  Code cleanup by using direct string indexing instead of substr with length 1 (Milian Wolff)
+  -  Optimized generation of code parts in strict mode (Milian Wolff)
+  -  Optimized COMMENT_REGEXP by using an incremental regexp cache (Milian Wolff, BenBE)
+  -  Fixed a problem that rarely skipped highlighting of escaped chars which usually should have gotten highlighted (BenBE)
+  -  Optimized generation of highlighted strings to use fast skip forward while highlighting them (Milian Wolff, BenBE)
+  -  Optimization using basic rework of indent function improving tab expansion performance (BenBE)
+  -  Lots of other minor optimizations based on coding style improvements (Milian Wolff)
+  -  Implemented setting to force spans to be closed before newlines, see SF#1727398 (Milian Wolff)
+  -  Added missing credits for D language file to THANKS file (SF#1720899, BenBE)
+  -  Optimization to prevent loading the current language file twice (Milian Wolff)
+  -  Optimization: Use file_get_contents() to load sourcecode from files.
+     Even if GeSHi worked with PHP 4.1 before, it doesn't now. (Milian Wolff)
+  -  Added description of extra language features (SF#1970248, BenBE)
+  -  Added support for highlighting the C# using and namespace directives (SF #1395677, BenBE)
+  -  Added support for highlighting the Java import and package directives (SF #1395677, BenBE)
+  -  Fixed minor problem in Haskell cuasing accidential start of comment (SF#1987221, BenBE)
+  -  Fixed minor issue causing loads of warnings if a language files defines no symbols (BenBE)
+  -  Updated some aspects of the documentation and included further hints (BenBE)
+  -  First of series of color scheme changes. Affected languages (sofar):
+     * Assembler (x86)
+     * Bash
+     * C
+     * C#
+     * Delphi
+     * Fortran77
+     * glSlang
+     * Java & Java 5
+     * JavaScript
+     * OCaml
+     * OpenOffice.org Basic
+     * Pascal
+     * Perl
+     * PHP and PHP-Brief
+Version 1.0.7.21
+  -  Added language files
+     * Basic4GL (Matthew Webb)
+  -  Fixed problem with mIRC language highlighting spaces only (BenBE)
+  -  Language files can now specify a function to be called to decide the
+     colour of a regular expression match
+  -  Added single quote to Lua (Darrin Roenfanz)
+  -  Compare comments case insensitively (fixes AutoIT comments somewhat)
+     (Daniel Gordon)
+  -  Fixed symbols not being highlighted at all (SF #1767953, BenBE)
+  -  Fixed brackets not correctly managed (SF #1767954, BenBE)
+  -  Changed default languages for some extensions
+  -  Included color and character information for symbol highlighting in some languages (BenBE)
+  -  Fixed a problem with extension detection if default was used (BenBE)
+  -  Fixed a highlighting problem with the LaTeX language (SF #1776182, BenBE)
+  -  Added a new parameter for enable_highlighting to reduce source duplication (SF #1786104, BenBE)
+  -  Updated doxygen documentation to include since tags and some missing parameters
+  -  Disabled symbol highlighting by default (doesn't affect brackets, cf. documentation) (BenBE)
+  -  Added a check for set_case_keywords for the given param to be supported (BenBE)
+  -  Minor rework of the HTML documentation layout \ W3C compliance (BenBE)
+  -  Fixed highlighting error in bash language avoiding keywords in comments (SF #1786314, SF #1564839, BenBE)
+  -  Fixed template params for C++ and C# not being highlighted (SF #1772919, BenBE)
+  -  Fixed more reported problems about mirc highlighting
+  -  Added some missing keywords for VB.NET
+  -  Fixed some warnings in DOS language file (Florian Angehrn)
+  -  Add possibility to handle more than one extra line style (SF #1698255, German Rumm, BenBE)
+  -  Fixed handling of URLs when output case differs from URL case (SF #1815504, Tom Samstag, BenBE)
+  -  Fixed POD (Plain Old Documentation) format problems breaking highlighting of Perl (SF #1891630, Shannon Wynter, BenBE)
+  -  Fixed a problem with mIRC when & was used for identifiers (SF #1875552, BenBE)
+Version 1.0.7.20
+  -  Added language files
+     * Genero (logic) and Per (forms) (FOURJ's Genero 4GL) (Lars Gersmann)
+     * Haskell (Dagit)
+     * ABAP (Andres Picazo)
+     * Motorola 68k Assembler (for MC68HC908GP32 Microcontroller) (BenBE)
+     * Dot (Adrien Friggeri)
+  -  Fixed java documentation search for keywords to actually go to the
+     documentation (spaze)
+  -  Applied fix for bug 1688864 (bad regexes) (Tim Starling)
+  -  Fixed comment CSS rule in visualfoxpro
+  -  ThinBASIC language update (Eros Olmi)
+  -  mIRC language update (BenBE)
+  -  Fixed outdated documentation URL of Perl language file (RuralMoon by BenBE)
+  -  Fixed tab replacement code not generating the correct number of spaces in
+     some cases (Guillermo Calvo)
+  -  Fixed two typos in Z80 language file
+  -  Applied fix for bug 1730168 (Daniel Naber)
+  -  Applied fix for bug 1705482 (Jason Frame)
+     * Configurable line endings (Replace \n by custom string)
+     * per-language tab-widths (Adjustable for width>=1)
+     * Included defaults for ASM (x86, m68k, z80), C, C (Mac), C++, C++ (QT), C#,
+       Delphi, CSS,, HTML, PHP, PHP (Brief), QBasic, Ruby, XML
+  -  Added a possibility to force generation of a surrounding tag around
+     the highlighted source
+  -  Applied fix for additional keywords for the bash language
+     (cf. http://bash.thefreebizhost.com/bash_geshi.php, BenBE / Jan G)
+  -  Fix bad colour definition in GML language (Andreas Gohr)
+  -  Fixed phpdoc comments not being indented one space if they should be (Andy
+     Hassall)
+Version 1.0.7.19
+  -  Added language files
+     * X++ (Simon Butcher)
+     * Rails (Moises Deniz)
+  -  Fixed invalid HTML being generated and doctypes not being highlighted over
+     multiple lines properly when line numbers are on (Validome)
+  -  Improved the ruby syntax highlighting by basing it off the Rails file
+  -  Changed some regular expressions to possibly help with badly performing
+     regex support in PHP (Tim Starling)
+  -  Allow {TIME}, {LANGUAGE} and {VERSION} to be used in the header as well as
+     the normal <TIME>/<LANGUAGE>/<VERSION> (AthanD)
+  -  Changed comment regex in bash to prevent malformed XHTML (rv1971)
+Version 1.0.7.18
+  -  Added language files
+     * ZiLOG Z80 Assembly (BenBE)
+  -  Fixed incorrect highlighting when the starter of a multiline comment is
+     longer than the ender (Robert Anthony).
+  -  Fixed "</span" generated if a multiline comment is the last thing in the
+     source (related to the above).
+  -  Added #cs => #ce comment markers to AutoIT (Robert Anthony)
+  -  Fixed spelling mistake for keyword in Python (wd3)
+  -  Added a method to enable/disable keyword linking (Ian McKellar)
+  -  Improved empty line detection for HTML output (BenBE)
+  -  Changed code style of geshi.php, and removed tabs
+Version 1.0.7.17
+  -  Fixed up ends of files having too many newlines (binarygroop)
+  -  Removed background colour on keyword group in eiffel (Julian Tschannen)
+  -  Removed GESHI_DIR_SEPARATOR constant usage, it's unnecessary (Aleksey Zapparov)
+  -  Added /* ... */ comments to coldfusion (Jeff Howden)
+Version 1.0.7.16
+  -  Added language files
+     * ActionScript (Steffen Krause)
+     * C++/QT (Iulian M)
+     * PL/SQL (Victor Engmark)
+  -  Fixed up my e-mail address everywhere
+  -  Fixed notice with "error" property (IZIU Zielona Góra)
+  -  Added some entries to the get_language_name_from_extension table
+     (Stebastian Schuberth)
+Version 1.0.7.15
+  - Added language files
+     * BNF (Rowan Rodrik van der Molen)
+     * IO (me, thanks to Johnathan Wright)
+     * mIRC (Alberto de Areba Sánchez)
+  -  Fixed use of colon in XML (Grigory Rubtsov)
+  -  Fixed notices in text.php, reg.php and latex.php when $this is not
+     available (Clemens Weiß)
+  -  Made third parameter of geshi_highlight optional (Gaetano Giunta)
+  -  Fix incorrect highlighting of the $# variable in bash (Michael Knight)
+  -  Fixed single line comment mistake in thinbasic.php (Eros Olmi)
+Version 1.0.7.14
+  -  Added language files
+     * thinBasic (Eros Olmi)
+     * LaTeX (Matthais Pospiech)
+  -  Removed extra newlines at the end of some files
+  -  Fixed SF bug 1556404 - check before using $this in language files
+     (Clemens Weiß)
+Version 1.0.7.13
+  -  Added language files
+     * Uno IDL (Cedric Bosdonnat)
+  -  Fixed add_ids causing odd XHTML (RyanJ)
+  -  Fixed extra newline being added to end of result (Andreas Gohr)
+Version 1.0.7.12
+  -  Fixed lines being collapsed when they contain just a space (artlover)
+  -  Allowed matching for regexes using start/end matchers at the start/end
+     of the code (Sheri)
+  -  Added (dubious) fix for google "I'm feeling lucky" search for java keywords
+     (dubious in that it doesn't work for me)
+  -  mysql - Made the symbols into their own keyword group as the symbol group
+     isn't used. Added a style for multiline comments.
+  -  Added a couple of php5 keywords to the php language files.
+  -  Allow XML tags to have dashes.
+  -  Changed LANG_NAME for many languages to be more sensible/correct case
+     (Matthias Mohr)
+  -  Added case-sensitivity indices to python
+Version 1.0.7.11
+  -  Added language files
+     * Smalltalk (Bananeweizen)
+  -  Minor style improvements to matlab
+  -  Moved a couple of functions to the correct group in smarty (arwan)
+Version 1.0.7.10
+  -  Added language files
+     * TCL (Reid van Melle)
+     * Winbatch (Craig Storey)
+     * Groovy (Ivan F. Villanueva B.)
+     * Text (SmokingRope)
+     * Reg (SmokingRope)
+  -  Removed \ as an escape character in T-SQL (Dave Jackson)
+  -  Reset extra lines to highlight if source is changed (Diogo Resende)
+  -  Allow setting of lexic permissions in language files (SmokingRope)
+  -  Allow regexes to set a CSS class name (SmokingRope)
+  -  Added URL support to DOS language (mastrboy)
+Version 1.0.7.9
+  -  Added language files
+     * Fortran (Cedric Arrabie)
+     * SAS (Galen Johnson)
+     * CFDG (John Horigan)
+  -  Fixed & in URL in java5 (Clemens Weiß)
+  -  Added MD5 and SHA1 to mysql keywords (polarina)
+  -  Fixes for highlight_lines_extra with line numbers (ithcy)
+  -  Fixed backslash characters being removed (ArTourter)
+Version 1.0.7.8
+  -  Fixed blank at start of MySQL file (W. Tasin)
+  -  Fixed smarty functions being broken (ultrabob)
+  -  Changed keyword and regexp detection and parsing
+     slightly to allow more "meta characters" (like #) in
+     keywords
+  -  Minor fixes for XML and GML
+Version 1.0.7.7
+  -  Added language files
+     * T-SQL (Duncan Lock)
+     * Robots.txt (Christian Lescuyer)
+     * AutoIT (mastrboy)
+     * Java 5 (Clemens Bruckmann)
+     * ColdFusion (Diego)
+  -  A few keyword changes in java, removed :: object splitter (amphi)
+  -  Now using a simpler regular expression for numbers (Brice Bernard)
+  -  Fixed ah, bh etc. regs being highlighted as numbers (Unknown)
+Version 1.0.7.6
+  -  Fix backtick-string highlighting in ruby (Juan J. Martínez)
+  -  Add =begin multiline comments in ruby (Juan J. Martínez)
+  -  Added support for :keywords and ::access in lisp (Denis Mashkevich)
+  -  Prevented number highlighting if they are just after underscores (Joce)
+  -  Removed escape characters for strings in XML and HTML (floele)
+  -  Added instanceof keyword to java (jgottschling)
+  -  Fixed comments in ASP (SBD)
+  -  Removed unnecessary keyword style index from ini
+  -  Added support for " strings in ini
+  -  Removed unnecessary regex style index from blitzbasic
+  -  Keyword case of URL-ed keywords should be defined by language file (Benny Baumann)
+  -  Added "Hardquote" feature, provides more accurate string highlighting (Cliff Stanford)
+  -  Used hardquote support for @"..." strings in C# (Cliff Stanford)
+  -  Used hardquote support for ' strings in perl (Cliff Stanford)
+  -  Fixed setting of language path (Cliff Stanford)
+  -  Display source correctly formatted with line numbers (if requested) if an error
+     has occured (several people)
+  -  Having no source to highlight is not an error condition anymore
+  -  Delphi language updated to include more keywords and types (BenBE)
+  -  Updated NSIS to version 2.11 (deguix)
+Version 1.0.7.5
+  -  Fix for using escape characters to escape newlines breaking XHTML compliance (Yves Goergen)
+  -  Fixed method highlighting in VB (Matt Beale)
+  -  Fixed multiline comment highlighting in SQL (MrBaseball34)
+  -  Fixed two ">" symbols being outputted when using a footer but not CSS classes (MrBaseball34)
+  -  Marked important block stuff as deprecated
+  -  Some documentation tidyup
+  -  Updated GML language file (Jos? Jorge Enr?quez Rodr?guez)
+  -  THANKS file tidied up
+  -  Fixed double </a> for elements in HTML (Yves Goergen)
+  -  Added some keywords for ASM (Dreuzzo)
+Version 1.0.7.4
+  -  Added language files
+     * MySQL (Carl Fürstenberg)
+     * BlitzBasic (Pàdraig O`Connel)
+  -  Fixed up geshi_highlight function: it now correctly uses <code> instead of <div> (Remi Faure)
+  -  When using GESHI_HEADER_NONE, remove the <ol> if line numbering is not enabled
+  -  Commented example.php so people can use it as a guide better
+  -  Fixed extra newline being generated if a comment is at the end
+     of the source (many people, including Yves Goergen)
+  -  Fixed up some documentation issues
+  -  Some minor language file fixes (C++, Lua) (Lua fixes by chromix)
+  -  Fixed up no </span> in XML and other strict languages (regression from 1.0.7.3 fix: removed
+        unnecessary </span> when using strict mode) (Daniel Ecer, drskrud),
+Version 1.0.7.3
+  -  Added language files
+     * Scheme (Jon Raphaelson)
+     * Ocaml and Ocaml-brief (Flaie)
+     * Ruby (Amit Gupta)
+  -  Make urls generated for java highlighting XHTML compliant (Tim Van Wassenhove)
+  -  Removed unnecessary </span> when using strict mode (Tim Van Wassenhove)
+  -  Fixed warning in dos.php about undefined constant (Tim Van Wassenhove)
+  -  Fixed security hole in contrib/example.php - able to view any file if source
+     not set and language is set to wierd value (Maksymilian Arciemowicz)
+Version 1.0.7.2
+  -  Added language files
+     * Inno (Thomas Klinger)
+     * Ini (Deguix)
+     * DOS (Batchfile) (Alessandro Staltali)
+     * Applescript (Stephan Klimek)
+     * Freebasic (Roberto Rossi)
+     * SDLBasic (Roberto Rossi)
+     * ActionScript (links to French documentation) (NikO)
+  -  NSIS language file updated (deguix)
+  -  Lua language file updated (Roberto Rossi)
+  -  Bugfix: Styles incorrectly overriding default styles instead of being merged
+     in set_*_styles methods (Stebastian Werner)
+  -  Added GESHI_HEADER_NONE as valid header type. This still allows header content.
+Version 1.0.7.1
+  -  Added language files:
+     * Div (Gabriel Lorenzo)
+     * GML (José Jorge Enríquez Rodríguez)
+     * Eiffel (Zoran Simic)
+  -  Minor change to rules regarding when keywords can appear - now dots (.) are
+     allowed before keywords. (NikO)
+  -  Bugfix: the line style for non-fancy lines when fancy highlighting is enabled
+     is now applied (Amit Gupta)
+Version 1.0.7
+  -  Added language files:
+     * Diff (Conny Brunnkvist)
+     * VHDL (Alexander Krause)
+     * D (Thomas Kuehne)
+     * Matlab (Florian Knorn)
+  -  Python highlighting improved (thither, Federico Quagliata)
+  -  Changed file comments to use phpdoc syntax, and changed code style to be more
+        like PEAR
+  -  Fixed bug in set_code_style: Second parameter is now optional
+  -  The $_GESHI_ERRORS array is gone, error messages are internal to the GeSHi class
+  -  Changed name of XML language to XML from HTML
+  -  Removed min and max tab width checks
+  -  Backported GeSHi 1.1.X's automatic language file path detection so you no longer
+     need to use the third parameter of the constructor or set_language_path except for
+     special circumstances.
+  -  Source is checked to make sure it is not empty else an error occurs
+  -  Removed excess characters after ?> in ada.php, apache.php and cpp.php that caused
+     http headers to be sent (psichron)
+  -  Removed second "foreach" keyword for smarty language file that was causing
+     duplication (Iss)
+  -  Added underscore to allowed characters in match for XML tags (anonymous)
+  -  Added some missing java keywords like "abstract" and "transient"
+  -  Added "list" and "continue" PHP keywords
+  -  set_language resets error status and strict mode (Andrew Black)
+  -  Removed margin:0 declaration from cssgen.php (Andrzej Kubaszek)
+  -  Fixed multiline comment selector in cssgen.php (Andrzej Kubaszek)
+Version 1.0.6
+  -  Added support for smart tabs - tabs that behave just like normal tabs when in
+     GESHI_HEADER_DIV mode.
+  -  Partial patch for UTF-8 encoding applied (doesn't quite work however...)
+Version 1.0.5
+  -  Added language files:
+     * MPASM (Bakalex)
+     * Oracle 8 (Guy Wicks)
+  -  Fixed bug where not using an encoding type would sometime result in warnings (although
+     there still seems to be issues with encoding in general that I'm trying to gather more
+     data on) (Alexander Spennemann)
+  -  Removed "margin: 0" from <ol> in an attempt to make line numbers visible in IE again
+     by default (untested, but I don't really care if it works... get firefox! ;))
+  -  Added note on php5 support (Karim Scheik)
+  -  Added two new methods: load_from_file and get_language_name_from_extension, that can
+     help automate file highlighting (though the extension array at this time is quite bare)
+     (David Gartner, Brian Cheesman)
+Version 1.0.4
+  -  Fixed many version-reporting bugs (Jack Lloyd)
+  -  Fixed bug where methods were not having the correct CSS generated for them
+     by get_stylesheet() (Jack Lloyd)
+  -  Added new keywords to C and C++ files (Jack Lloyd)
+  -  Added section on case sensitivity to documentation that wasn't in the other versions
+Version 1.0.3
+  -  Added language files:
+     * Smarty (Alan Juden)
+     * C# (Alan Juden)
+     * VB.NET (Alan Juden)
+     * C for Macs (M. Uli Kusterer)
+     * Objective C (M. Uli Kusterer)
+  -  Links can have a target attribute (Andreas Gohr)
+  -  Fixed multiline string bug if not using classes
+  -  Added method set_encoding that allows you to set the character
+     set used by calls to htmlentities() in GeSHi
+  -  You can now specify an array of object splitters, and each
+     type of method separated by each object splitter can be highlighted
+     differently
+  -  If a language uses a case sensitive keyword group and that group
+     has a URL associated with it, the keyword will not be lowercased
+     in the URL (M. Uli Kusterer)
+Version 1.0.2
+  -  Added language files:
+     * Actionscript (Steffen Krause)
+     * ASP (Amit Gupta)
+     * Bash (Andreas Gohr)
+     * CADDCL (Roberto Rossi)
+     * CadLisp (Roberto Rossi)
+     * C++ (Dennis Bayer)
+     * Delphi (Járja Norbert)
+     * Javascript (Ben Keen)
+     * Lisp (Roberto Rossi)
+     * OpenOffice.org BASIC (Roberto Rossi)
+     * Perl (Andreas Gohr and Ben Keen)
+     * Python (Roberto Rossi)
+     * VisualFoxPro (Roberto Armellin)
+     * XML (Nigel McNie, from an idea/file by Christian Weiske)
+  -  Added contrib/ directory with script to create one external stylesheet
+     from many languages(base script by Andreas Gohr, modified by Nigel McNie),
+     and an example script (needs lotsa work...)
+  -  Code lines can have their own unique ID (for use with javascript)
+     (suggested by Andreas von Oettingen)
+  -  Certain rows can be specified to be highlighted differently (suggested by
+     Andreas von Oettingen)
+  -  Getter available for human-readable language name (suggested by Simon Patterson)
+  -  Line numbers aren't highlighted when a user selects the code
+  -  Contextual highlighting with <BEGIN GeSHi> ... <END GeSHi> in the code (which
+     can be disabled)
+  -  Functions can be made into URLs to appropriate documentation (suggested
+     by cybot_tm). Also thanks to Marcin Gryszkalis for the links for C, Java
+     and Perl.
+  -  Code can have a header and footer
+  -  Time taken to parse the code is recorded and made available with the get_time()
+     method
+  -  error() now returns a human-readable error message
+  -  Function geshi_highlight added to make it even easier to highlight on the fly
+  -  Advanced regular expression handling
+  -  Bug fixes to lexic_permission handling
+Version 1.0.1
+  -  Added methods set_symbols_style() and set_symbols_highlighting(). These should be used
+     instead of set_brackets_style and set_brackets_highlighting respectively.
+  -  Added a new field - language_path - that can be set either when the constructor is
+     called, or by the new method set_language_path(), that specifies a path to the directory
+     containing the language files (bug reported by bbspliff)
+  -  Added a new method set_case_keywords(), that allows the auto-casing feature to be
+     changed on the fly instead of simply being specified in the language file
+  -  If there is an error the source that is outputted is now handled much better
+  -  Lines are broken in the source only by \n now, not by \r\n (to save on output source)
+  -  Indentation moved into its own method
+  -  Method header() modified to allow the user to choose whether the code is surrounded in
+     a <div> or a <pre> (see documentation for benefits of both). Method footer() likewise
+     modified.
+  -  Method get_stylesheet() modified so that a smaller comment is outputted in economy mode,
+     and bugs with when line number classes are outputted in economy mode have been fixed
+  -  Bug where spans had two quotes at the end of the attributes fixed (ie. <span style=".."">)
+  -  Added language files:
+     * Ada (Tux)
+     * Apache log file (Tux)
+     * ASM (Tux)
+     * NSIS (Tux)
+     * Pascal (Tux)
+Version 1.0.0
+  -  Initial Release
\ No newline at end of file
diff --git a/examples/includes/geshi/docs/COPYING b/examples/includes/geshi/docs/COPYING
new file mode 100644 (file)
index 0000000..5b6e7c6
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/examples/includes/geshi/docs/README b/examples/includes/geshi/docs/README
new file mode 100644 (file)
index 0000000..a08e78e
--- /dev/null
@@ -0,0 +1,33 @@
+
+        GeSHi - GEneric Syntax HIghlighter
+        ----------------------------------
+                 Version 1.0.8
+
+Author:          Nigel McNie, Benny Baumann
+Email:           nigel@geshi.org, BenBE@omorphia.de
+GeSHi Website:   http://qbnz.com/highlighter
+
+GeSHi is a generic syntax highlighter, written in PHP. You simply
+input the source code you wish to highlight with the language you
+wish to use, and the output will be a file syntax highlighted to
+XHTML standards.
+
+For more information on how to use GeSHi, please consult the
+documentation. If you got this readme from a GeSHi package, then
+the documentation is available in the docs/ directory. Documentation
+is also available at http://qbnz.com/highlighter/documentation.php
+
+If you think you've found a bug in GeSHi, contact me with a bug
+report at BenBE@omorphia.de, or submit it to the bug tracker at
+http://sourceforge.net/tracker/?group_id=114997&atid=670231. Be
+aware that minor highlighting errors may well just be incorrect
+language files, but if you do find something major please contact me.
+
+And if you're using GeSHi as a plugin/mod for some other software,
+please tell me about it! It's worth a link to you, and I can give
+you specialist help if you need it.
+
+GeSHi is free software, released under the GNU GPL. Please see the
+COPYING file for more information. If you do modify this program,
+please tell me about it! Perhaps you've made a good improvement that
+I can learn from :)
diff --git a/examples/includes/geshi/docs/THANKS b/examples/includes/geshi/docs/THANKS
new file mode 100644 (file)
index 0000000..9580567
--- /dev/null
@@ -0,0 +1,163 @@
+
+             THANKS - List of credits for GeSHi
+
+I owe these people/groups my thanks for help with GeSHi. Thanks, guys!
+
+- Amit Gupta            - Thanks for all that constructive criticism - it's
+                          a great help for making GeSHi even better. And
+                          thanks for the Wordpress plugin! (Anyone who is
+                          interested in the plugin can visit:
+                          http://blog.igeek.info/still-fresh/category/wp-plugins/igsyntax-hiliter/)
+- Andreas Gohr          - Thanks for language files and for using GeSHi for DokuWiki
+                          (http://www.splitbrain.org/dokuwiki/wiki:dokuwiki). And thanks
+                          for all your criticisms and for that stylesheet-maker code :).
+                          Also, thanks for the UTF-8 patch.
+- Andreas von Oettingen - Thanks for those great ideas! :)
+- bbspliff              - Thanks for pointing out that bug (pity I already
+                          found it though ;))
+- Benny Baumann         - Thanks for your innumerable suggestions for improvements, and your
+                          work on Delphi support :)
+- Ben Keen              - Thanks for the language files and pointing out some
+                          ideas for future releases. Lookin' forward to seeing that
+                          software soon! ;)
+- Brian Cheesman        - Thanks for using GeSHi in phpCvsView, and for the suggestion about
+                          extension => language lookup
+- Christian Weiske      - Thanks for the inspiration for creating advanced regexp
+                          highlighting :D
+- Cliff Stanford        - Thanks for the hardquote support for C# and Perl (can be used elsewhere
+                          I'm sure)
+- David Gartner         - Thanks for using GeSHi in net2ftp, and for the idea about a load_from_file
+                          method
+- forum.qbasicnews.com  - Thanks for putting up with the crappy versions
+                          that I "forced" on you guys before ;)
+- Jack Lloyd            - Thanks for pointing out the versioning and method CSS bugs, and giving
+                          me the extra C/C++ keywords
+- Karim Scheik          - Thanks for the php5 support report
+- Marcin Gryszkalis     - Thanks for those links for C, Java, Perl
+- M. Uli Kusterer       - Thanks for the idea about URL case conversion
+- Milian Wolff          - Thanks for the loads of optimizations
+                        - Thanks for helping with implementation of various features
+- Roberto Armellin      - Thanks for pointing out some flaws in GeSHi (that will be solved
+                          in 1.2 guaranteed)
+- Sterling Christensen  - Thanks for those links to language specs
+- Tux                   - Thanks for making all those language files :D
+- zbw                   - Thanks for proving a phpBB port was possible
+
+PEOPE WHO MADE LANGUAGE FILES
+
+- ABAP                   Andres Picazo
+- Actionscript           Steffen Krause (french translation by NikO)
+- ActionScript 3         Jordi Boggiano (version for ActionScript3 and MXML)
+- Ada                    Tux
+- Apache                 Tux
+- Applescript            Stephan Klimek
+- Apt sources.list       Milian Wolff
+- ASM                    Tux
+- ASP                    Amit Gupta
+- AutoIT                 mastrboy
+- AviSynth               Ryan Jones
+- Bash                   Andreas Gohr
+- Basic4GL               Matthew Webb
+- BlitzBasic             P�draig O`Connel
+- BNF                    Rowan Rodrik van der Molen
+- Boo                    Marcus Griep
+- Brainfuck \ Brainfork  Benny Baumann
+- C++                    Dennis Bayer, M. Uli Kusterer
+- C++/QT                 Iulian M
+- C#                     Alan Juden
+- C for Macs             M. Uli Kusterer
+- CADDCL                 Roberto Rossi
+- CadLisp                Roberto Rossi
+- CDFG                   John Horigan
+- CIL                    Marcus Griep
+- COBOL                  Benny Baumann
+- ColdFusion             Diego
+- D                      Thomas Kuehne
+- DCS                    Stelio Passaris
+- Delphi                 Járja Norbert, Benny Baumann
+- Div                    Gabriel Lorenzo
+- DOS                    Alessandro Staltari
+- Eiffel                 Zoran Simic
+- eMail \ mbox           Benny Baumann
+- FreeBasic              Roberto Rossi
+- Fortran                Cedric Arrabie
+- glSlang                Benny Baumann
+- Gettext                Milian Wolff
+- GNU make               Neil Bird
+- Gnuplot                Milian Wolff
+- GML                    José Jorge Enríquez Rodríguez
+- Groovy                 Ivan F. Villanueva B.
+- Haskell                Dagit
+- HQ9+                   Benny Baumann
+- Ini                    Deguix
+- Inno                   Thomas Klinger
+- INTERCAL               Benny Baumann
+- Java 5                 Clemens Bruckmann
+- Javascript             Ben Keen
+- KiXtart                Riley McArdle
+- KLone C                Mickael Auger
+- KLone C++              Mickael Auger
+- LaTeX                  Matthais Pospiech
+- Lisp                   Roberto Rossi
+- Locomotive Basic       Nacho Cabanes
+- LOLcode                Benny Baumann
+- LScript                Beau McGuigan
+- LSL2                   William Fry
+- Lua                    Roberto Rossi
+- m86k                   Benny Baumann
+- mIRC                   Alberto de Areba Sánchez
+- Modula-3               Martin Bishop
+- MPASM                  Bakalex
+- MXML                   David Spurr
+- MySQL                  Carl Fürstenberg, Marjolein Katsma
+- NSIS                   Tux, Deguix
+- Oberon-2               Mike Mol
+- Objective C            M. Uli Kusterer
+- Ocaml                  Flaie
+- Ocaml-brief            Flaie
+- OpenOffice.org BASIC   Roberto Rossi
+- Oracle 8               Guy Wicks
+- Oracle 11i             Simon Redhead
+- Pascal                 Tux
+- Perl                   Andreas Gohr, Ben Keen
+- PIC16xxx assembler     Phil Mattison
+- Pixel Bender           Richard Olsson
+- PL/SQL                 Victor Engmark
+- POV-Ray                Carl Fürstenberg
+- PowerShell             Frode Aarebrot
+- Progress               Marco Aurelio de Pasqual
+- Prolog                 Benny Baumann
+- ProvideX               Jeff Wilder
+- Python                 Roberto Rossi
+- Rails                  Moises Deniz
+- Rebol                  Lecanu Guillaume
+- Reg                    SmokingRope
+- Robots                 Christian Lescuyer
+- Ruby                   Amit Gupta, Moises Deniz
+- SAS                    Galen Johnson
+- SDLBasic               Roberto Rossi
+- Scheme                 Jon Raphaelson
+- SciLab                 Christophe David
+- Smalltalk              Bananeweizen
+- Smarty                 Alan Juden
+- T-SQL                  Duncan Lock
+- TeraTerm               Boris Maisuradze
+- Text                   SmokingRope
+- TCL                    Reid van Melle
+- thinBasic              Eros Olmi
+- TypoScript             Jan-Philipp Halle
+- Uno IDL                Cedric Bosdonnat
+- VB                     Roberto Rossi
+- VB.NET                 Alan Juden
+- Verilog                Günter Dannoritzer
+- VIM Script             Swaroop C H
+- Visual FoxPro          Roberto Armellin
+- Visual Prolog          Thomas Linder Puls
+- Whitespace             Benny Baumann
+- Winbatch               Craig Storey
+- X++                    Simon Butcher
+- Xorg config            Milian Wolff
+- Z80 Assembler          Benny Baumann
+
+Do you want your name in here? Help me out! Make a language file, or suggest a new
+feature, or make a plugin for GeSHi for some other software, then tell me about it!
\ No newline at end of file
diff --git a/examples/includes/geshi/docs/TODO b/examples/includes/geshi/docs/TODO
new file mode 100644 (file)
index 0000000..ee71c77
--- /dev/null
@@ -0,0 +1,71 @@
+       TODO - List of things to do as of 2005/01/29
+
+Suggestions for things to add are welcome, if you have a feature request you
+can either post it to the forums:
+
+http://qbnz.com/highlighter/forum.php
+
+Or to the feature request tracker:
+
+http://sourceforge.net/tracker/?group_id=114997&atid=670234
+
+
+  TODO for version 1.0.8.x
+
+- Rework the load_from_file method and the one for getting a file extension,
+  as documented in the source.
+- use analogous vars to $next_comment_regexp_pos for more GeSHi structures,
+  should reduce number of functions called and hence improve performance
+- make a set of default colours which can be used in the language files.
+  this way we can give languages a uniform look and maybe even add "themes"
+- Get better coverage in our coderepo
+- README / INSTALL / ... file for phpdoc integration => take geshi-doc.*?
+- rework HARDQUOTE + styles, currently this is a bit of a mess imo (milian)
+- Allow per-keywordgroup AutoCaps/NoCaps
+- Complete API to support latest features
+    set_number_style ($key missing)
+    set_string_style ($key missing)
+    set_case_keywords (support for per_keywordgroup AutoCaps)
+
+
+  TODO for version 1.2.0
+
+- Rewrite engine to use remove/replace method (will hopefully almost
+  eliminate the need for regular expressions except for numbers/methods
+  etc). This will also assist for making different output formats [DONE]
+- "Intelligent" output format - eg if the user doesn't want lines to
+  wrap and wants line numbers don't use <ol>, use the <table> method
+  instead. (This saves on output)
+- Clear split between "public" and "private" methods [DONE]
+- PHP5 version
+- "Themes" for styles - basically pre-made stylesheets that can be used
+  to highlight code of any language in a similar manner [DONE]
+- "Dialects" for languages - eg php4, php5. One master language definition
+  file, and a bunch of "specialised" dialect files for each language
+  Ability to specify a "specialised" dialect as default? [DONE]
+- Look at load/memory usage and try to reduce
+- Make tabs into tab-stops like a normal editor [DONE]
+- Ability to add more than one multiline comment or string [DONE]
+- Ability to specify that strings cannot be multiline [DONE]
+- Create a "wrapper" class for ultra-easy use
+- Code written in a style that conforms to a phpdoc utility [DONE, PEAR]
+- Dig functions/methods out of code and where they are called make an internal
+  link back to their definition
+
+
+  TODO for version 2.0.0
+
+- Support for multiple output formats (XHTML, XML, PDF, RTF etc) [DONE IN 1.2]
+- Support for auto-indent/code "beautifing"
+- Option for "Lite" highlighting - aims for speed and low server load
+- "Intelligent" highlighting inside comments, and ability to highlight
+  source in multiple languages at once (eg PHP+HTML) [DONE IN 1.2]
+- Perhaps a script on the GeSHi site that would map urls to appropriate
+  definitions and relocate the user? (eg, java documentation is
+  structured in such a way that urls are not able to be used with GeSHi.
+  Instead the URL could become:
+  http://qbnz.com/highlighter/redirect.php?lang=java&kw=KeyWord
+  and that script would redirect to the correct location.
+  [BETTER FIX IN 1.2]
+
+              $Id: TODO 1727 2008-08-08 13:36:52Z benbe $
diff --git a/examples/includes/geshi/docs/api/__filesource/fsource_geshi_core_geshi.php.html b/examples/includes/geshi/docs/api/__filesource/fsource_geshi_core_geshi.php.html
new file mode 100644 (file)
index 0000000..3d79982
--- /dev/null
@@ -0,0 +1,4616 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+  <html xmlns="http://www.w3.org/1999/xhtml">
+               <head>
+                       <!-- template designed by Marco Von Ballmoos -->
+                       <title>File Source for geshi.php</title>
+                       <link rel="stylesheet" href="../media/stylesheet.css" />
+                       <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
+               </head>
+               <body>
+                                               <h1>Source for file geshi.php</h1>
+<p>Documentation is available at <a href="../geshi/core/_geshi.php.html">geshi.php</a></p>
+<div class="src-code">
+<div class="src-code"><ol><li><div class="src-line"><a name="a1"></a><span class="src-php">&lt;?php</span></div></li>
+<li><div class="src-line"><a name="a2"></a><span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a3"></a><span class="src-doc">&nbsp;*&nbsp;GeSHi&nbsp;-&nbsp;Generic&nbsp;Syntax&nbsp;Highlighter</span></div></li>
+<li><div class="src-line"><a name="a4"></a><span class="src-doc">&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a5"></a><span class="src-doc">&nbsp;*&nbsp;The&nbsp;GeSHi&nbsp;class&nbsp;for&nbsp;Generic&nbsp;Syntax&nbsp;Highlighting.&nbsp;Please&nbsp;refer&nbsp;to&nbsp;the</span></div></li>
+<li><div class="src-line"><a name="a6"></a><span class="src-doc">&nbsp;*&nbsp;documentation&nbsp;at&nbsp;http://qbnz.com/highlighter/documentation.php&nbsp;for&nbsp;more</span></div></li>
+<li><div class="src-line"><a name="a7"></a><span class="src-doc">&nbsp;*&nbsp;information&nbsp;about&nbsp;how&nbsp;to&nbsp;use&nbsp;this&nbsp;class.</span></div></li>
+<li><div class="src-line"><a name="a8"></a><span class="src-doc">&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a9"></a><span class="src-doc">&nbsp;*&nbsp;For&nbsp;changes,&nbsp;release&nbsp;notes,&nbsp;TODOs&nbsp;etc,&nbsp;see&nbsp;the&nbsp;relevant&nbsp;files&nbsp;in&nbsp;the&nbsp;docs/</span></div></li>
+<li><div class="src-line"><a name="a10"></a><span class="src-doc">&nbsp;*&nbsp;directory.</span></div></li>
+<li><div class="src-line"><a name="a11"></a><span class="src-doc">&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a12"></a><span class="src-doc">&nbsp;*&nbsp;&nbsp;&nbsp;This&nbsp;file&nbsp;is&nbsp;part&nbsp;of&nbsp;GeSHi.</span></div></li>
+<li><div class="src-line"><a name="a13"></a><span class="src-doc">&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a14"></a><span class="src-doc">&nbsp;*&nbsp;&nbsp;GeSHi&nbsp;is&nbsp;free&nbsp;software;&nbsp;you&nbsp;can&nbsp;redistribute&nbsp;it&nbsp;and/or&nbsp;modify</span></div></li>
+<li><div class="src-line"><a name="a15"></a><span class="src-doc">&nbsp;*&nbsp;&nbsp;it&nbsp;under&nbsp;the&nbsp;terms&nbsp;of&nbsp;the&nbsp;GNU&nbsp;General&nbsp;Public&nbsp;License&nbsp;as&nbsp;published&nbsp;by</span></div></li>
+<li><div class="src-line"><a name="a16"></a><span class="src-doc">&nbsp;*&nbsp;&nbsp;the&nbsp;Free&nbsp;Software&nbsp;Foundation;&nbsp;either&nbsp;version&nbsp;2&nbsp;of&nbsp;the&nbsp;License,&nbsp;or</span></div></li>
+<li><div class="src-line"><a name="a17"></a><span class="src-doc">&nbsp;*&nbsp;&nbsp;(at&nbsp;your&nbsp;option)&nbsp;any&nbsp;later&nbsp;version.</span></div></li>
+<li><div class="src-line"><a name="a18"></a><span class="src-doc">&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a19"></a><span class="src-doc">&nbsp;*&nbsp;&nbsp;GeSHi&nbsp;is&nbsp;distributed&nbsp;in&nbsp;the&nbsp;hope&nbsp;that&nbsp;it&nbsp;will&nbsp;be&nbsp;useful,</span></div></li>
+<li><div class="src-line"><a name="a20"></a><span class="src-doc">&nbsp;*&nbsp;&nbsp;but&nbsp;WITHOUT&nbsp;ANY&nbsp;WARRANTY;&nbsp;without&nbsp;even&nbsp;the&nbsp;implied&nbsp;warranty&nbsp;of</span></div></li>
+<li><div class="src-line"><a name="a21"></a><span class="src-doc">&nbsp;*&nbsp;&nbsp;MERCHANTABILITY&nbsp;or&nbsp;FITNESS&nbsp;FOR&nbsp;A&nbsp;PARTICULAR&nbsp;PURPOSE.&nbsp;&nbsp;See&nbsp;the</span></div></li>
+<li><div class="src-line"><a name="a22"></a><span class="src-doc">&nbsp;*&nbsp;&nbsp;GNU&nbsp;General&nbsp;Public&nbsp;License&nbsp;for&nbsp;more&nbsp;details.</span></div></li>
+<li><div class="src-line"><a name="a23"></a><span class="src-doc">&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a24"></a><span class="src-doc">&nbsp;*&nbsp;&nbsp;You&nbsp;should&nbsp;have&nbsp;received&nbsp;a&nbsp;copy&nbsp;of&nbsp;the&nbsp;GNU&nbsp;General&nbsp;Public&nbsp;License</span></div></li>
+<li><div class="src-line"><a name="a25"></a><span class="src-doc">&nbsp;*&nbsp;&nbsp;along&nbsp;with&nbsp;GeSHi;&nbsp;if&nbsp;not,&nbsp;write&nbsp;to&nbsp;the&nbsp;Free&nbsp;Software</span></div></li>
+<li><div class="src-line"><a name="a26"></a><span class="src-doc">&nbsp;*&nbsp;&nbsp;Foundation,&nbsp;Inc.,&nbsp;59&nbsp;Temple&nbsp;Place,&nbsp;Suite&nbsp;330,&nbsp;Boston,&nbsp;MA&nbsp;&nbsp;02111-1307&nbsp;&nbsp;USA</span></div></li>
+<li><div class="src-line"><a name="a27"></a><span class="src-doc">&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a28"></a><span class="src-doc">&nbsp;*&nbsp;</span><span class="src-doc-coretag">@package</span><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;geshi</span></div></li>
+<li><div class="src-line"><a name="a29"></a><span class="src-doc">&nbsp;*&nbsp;</span><span class="src-doc-coretag">@subpackage</span><span class="src-doc">&nbsp;core</span></div></li>
+<li><div class="src-line"><a name="a30"></a><span class="src-doc">&nbsp;*&nbsp;</span><span class="src-doc-coretag">@author</span><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Nigel&nbsp;McNie&nbsp;&lt;nigel@geshi.org&gt;,&nbsp;Benny&nbsp;Baumann&nbsp;&lt;BenBE@omorphia.de&gt;</span></div></li>
+<li><div class="src-line"><a name="a31"></a><span class="src-doc">&nbsp;*&nbsp;</span><span class="src-doc-coretag">@copyright</span><span class="src-doc">&nbsp;&nbsp;(C)&nbsp;2004&nbsp;-&nbsp;2007&nbsp;Nigel&nbsp;McNie,&nbsp;(C)&nbsp;2007&nbsp;-&nbsp;2008&nbsp;Benny&nbsp;Baumann</span></div></li>
+<li><div class="src-line"><a name="a32"></a><span class="src-doc">&nbsp;*&nbsp;</span><span class="src-doc-coretag">@license</span><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;http://gnu.org/copyleft/gpl.html&nbsp;GNU&nbsp;GPL</span></div></li>
+<li><div class="src-line"><a name="a33"></a><span class="src-doc">&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a34"></a><span class="src-doc">&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a35"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a36"></a><span class="src-comm">//</span></div></li>
+<li><div class="src-line"><a name="a37"></a><span class="src-comm">//&nbsp;GeSHi&nbsp;Constants</span></div></li>
+<li><div class="src-line"><a name="a38"></a><span class="src-comm">//&nbsp;You&nbsp;should&nbsp;use&nbsp;these&nbsp;constant&nbsp;names&nbsp;in&nbsp;your&nbsp;programs&nbsp;instead&nbsp;of</span></div></li>
+<li><div class="src-line"><a name="a39"></a><span class="src-comm">//&nbsp;their&nbsp;values&nbsp;-&nbsp;you&nbsp;never&nbsp;know&nbsp;when&nbsp;a&nbsp;value&nbsp;may&nbsp;change&nbsp;in&nbsp;a&nbsp;future</span></div></li>
+<li><div class="src-line"><a name="a40"></a><span class="src-comm">//&nbsp;version</span></div></li>
+<li><div class="src-line"><a name="a41"></a><span class="src-comm">//</span></div></li>
+<li><div class="src-line"><a name="a42"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a43"></a><span class="src-doc">/**&nbsp;The&nbsp;version&nbsp;of&nbsp;this&nbsp;GeSHi&nbsp;file&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a44"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_VERSION'</span><span class="src-sym">,&nbsp;</span><span class="src-str">'1.0.8.2'</span><span class="src-sym">,</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a45"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a46"></a><span class="src-comm">//&nbsp;Define&nbsp;the&nbsp;root&nbsp;directory&nbsp;for&nbsp;the&nbsp;GeSHi&nbsp;code&nbsp;tree</span></div></li>
+<li><div class="src-line"><a name="a47"></a><span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-sym">!</span><a href="http://www.php.net/defined">defined</a><span class="src-sym">(</span><span class="src-str">'GESHI_ROOT'</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a48"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**&nbsp;The&nbsp;root&nbsp;directory&nbsp;for&nbsp;GeSHi&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a49"></a>&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_ROOT'</span><span class="src-sym">,&nbsp;</span><span class="src-id">dirname</span><span class="src-sym">(</span>__FILE__<span class="src-sym">)&nbsp;</span>.&nbsp;<span class="src-id">DIRECTORY_SEPARATOR</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a50"></a><span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a51"></a><span class="src-doc">/**&nbsp;The&nbsp;language&nbsp;file&nbsp;directory&nbsp;for&nbsp;GeSHi</span></div></li>
+<li><div class="src-line"><a name="a52"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;@access&nbsp;private&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a53"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_LANG_ROOT'</span><span class="src-sym">,&nbsp;</span><span class="src-id">GESHI_ROOT&nbsp;</span>.&nbsp;<span class="src-str">'geshi'&nbsp;</span>.&nbsp;<span class="src-id">DIRECTORY_SEPARATOR</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a54"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a55"></a><span class="src-comm">//&nbsp;Define&nbsp;if&nbsp;GeSHi&nbsp;should&nbsp;be&nbsp;paranoid&nbsp;about&nbsp;security</span></div></li>
+<li><div class="src-line"><a name="a56"></a><span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-sym">!</span><a href="http://www.php.net/defined">defined</a><span class="src-sym">(</span><span class="src-str">'GESHI_SECURITY_PARANOID'</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a57"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**&nbsp;Tells&nbsp;GeSHi&nbsp;to&nbsp;be&nbsp;paranoid&nbsp;about&nbsp;security&nbsp;settings&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a58"></a>&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_SECURITY_PARANOID'</span><span class="src-sym">,&nbsp;</span><span class="src-id">false</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a59"></a><span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a60"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a61"></a><span class="src-comm">//&nbsp;Line&nbsp;numbers&nbsp;-&nbsp;use&nbsp;with&nbsp;enable_line_numbers()</span></div></li>
+<li><div class="src-line"><a name="a62"></a><span class="src-doc">/**&nbsp;Use&nbsp;no&nbsp;line&nbsp;numbers&nbsp;when&nbsp;building&nbsp;the&nbsp;result&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a63"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_NO_LINE_NUMBERS'</span><span class="src-sym">,&nbsp;</span><span class="src-num">0</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a64"></a><span class="src-doc">/**&nbsp;Use&nbsp;normal&nbsp;line&nbsp;numbers&nbsp;when&nbsp;building&nbsp;the&nbsp;result&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a65"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_NORMAL_LINE_NUMBERS'</span><span class="src-sym">,&nbsp;</span><span class="src-num">1</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a66"></a><span class="src-doc">/**&nbsp;Use&nbsp;fancy&nbsp;line&nbsp;numbers&nbsp;when&nbsp;building&nbsp;the&nbsp;result&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a67"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_FANCY_LINE_NUMBERS'</span><span class="src-sym">,&nbsp;</span><span class="src-num">2</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a68"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a69"></a><span class="src-comm">//&nbsp;Container&nbsp;HTML&nbsp;type</span></div></li>
+<li><div class="src-line"><a name="a70"></a><span class="src-doc">/**&nbsp;Use&nbsp;nothing&nbsp;to&nbsp;surround&nbsp;the&nbsp;source&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a71"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_HEADER_NONE'</span><span class="src-sym">,&nbsp;</span><span class="src-num">0</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a72"></a><span class="src-doc">/**&nbsp;Use&nbsp;a&nbsp;&quot;div&quot;&nbsp;to&nbsp;surround&nbsp;the&nbsp;source&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a73"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_HEADER_DIV'</span><span class="src-sym">,&nbsp;</span><span class="src-num">1</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a74"></a><span class="src-doc">/**&nbsp;Use&nbsp;a&nbsp;&quot;pre&quot;&nbsp;to&nbsp;surround&nbsp;the&nbsp;source&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a75"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_HEADER_PRE'</span><span class="src-sym">,&nbsp;</span><span class="src-num">2</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a76"></a><span class="src-doc">/**&nbsp;Use&nbsp;a&nbsp;pre&nbsp;to&nbsp;wrap&nbsp;lines&nbsp;when&nbsp;line&nbsp;numbers&nbsp;are&nbsp;enabled&nbsp;or&nbsp;to&nbsp;wrap&nbsp;the&nbsp;whole&nbsp;code.&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a77"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_HEADER_PRE_VALID'</span><span class="src-sym">,&nbsp;</span><span class="src-num">3</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a78"></a><span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a79"></a><span class="src-doc">&nbsp;*&nbsp;Use&nbsp;a&nbsp;&quot;table&quot;&nbsp;to&nbsp;surround&nbsp;the&nbsp;source:</span></div></li>
+<li><div class="src-line"><a name="a80"></a><span class="src-doc">&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a81"></a><span class="src-doc">&nbsp;*&nbsp;&nbsp;&lt;table&gt;</span></div></li>
+<li><div class="src-line"><a name="a82"></a><span class="src-doc">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&lt;thead&gt;&lt;tr&gt;&lt;td&nbsp;colspan=&quot;2&quot;&gt;$header&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;</span></div></li>
+<li><div class="src-line"><a name="a83"></a><span class="src-doc">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre&gt;$linenumbers&lt;/pre&gt;&lt;/td&gt;&lt;td&gt;&lt;pre&gt;$code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;</span></div></li>
+<li><div class="src-line"><a name="a84"></a><span class="src-doc">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&lt;tfooter&gt;&lt;tr&gt;&lt;td&nbsp;colspan=&quot;2&quot;&gt;$footer&lt;/td&gt;&lt;/tr&gt;&lt;/tfoot&gt;</span></div></li>
+<li><div class="src-line"><a name="a85"></a><span class="src-doc">&nbsp;*&nbsp;&nbsp;&lt;/table&gt;</span></div></li>
+<li><div class="src-line"><a name="a86"></a><span class="src-doc">&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a87"></a><span class="src-doc">&nbsp;*&nbsp;this&nbsp;is&nbsp;essentially&nbsp;only&nbsp;a&nbsp;workaround&nbsp;for&nbsp;Firefox,&nbsp;see&nbsp;sf#1651996&nbsp;or&nbsp;take&nbsp;a&nbsp;look&nbsp;at</span></div></li>
+<li><div class="src-line"><a name="a88"></a><span class="src-doc">&nbsp;*&nbsp;https://bugzilla.mozilla.org/show_bug.cgi?id=365805</span></div></li>
+<li><div class="src-line"><a name="a89"></a><span class="src-doc">&nbsp;*&nbsp;</span><span class="src-doc-tag">@note</span><span class="src-doc">&nbsp;when&nbsp;linenumbers&nbsp;are&nbsp;disabled&nbsp;this&nbsp;is&nbsp;essentially&nbsp;the&nbsp;same&nbsp;as&nbsp;GESHI_HEADER_PRE</span></div></li>
+<li><div class="src-line"><a name="a90"></a><span class="src-doc">&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a91"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_HEADER_PRE_TABLE'</span><span class="src-sym">,&nbsp;</span><span class="src-num">4</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a92"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a93"></a><span class="src-comm">//&nbsp;Capatalisation&nbsp;constants</span></div></li>
+<li><div class="src-line"><a name="a94"></a><span class="src-doc">/**&nbsp;Lowercase&nbsp;keywords&nbsp;found&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a95"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_CAPS_NO_CHANGE'</span><span class="src-sym">,&nbsp;</span><span class="src-num">0</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a96"></a><span class="src-doc">/**&nbsp;Uppercase&nbsp;keywords&nbsp;found&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a97"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_CAPS_UPPER'</span><span class="src-sym">,&nbsp;</span><span class="src-num">1</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a98"></a><span class="src-doc">/**&nbsp;Leave&nbsp;keywords&nbsp;found&nbsp;as&nbsp;the&nbsp;case&nbsp;that&nbsp;they&nbsp;are&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a99"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_CAPS_LOWER'</span><span class="src-sym">,&nbsp;</span><span class="src-num">2</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a100"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a101"></a><span class="src-comm">//&nbsp;Link&nbsp;style&nbsp;constants</span></div></li>
+<li><div class="src-line"><a name="a102"></a><span class="src-doc">/**&nbsp;Links&nbsp;in&nbsp;the&nbsp;source&nbsp;in&nbsp;the&nbsp;:link&nbsp;state&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a103"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_LINK'</span><span class="src-sym">,&nbsp;</span><span class="src-num">0</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a104"></a><span class="src-doc">/**&nbsp;Links&nbsp;in&nbsp;the&nbsp;source&nbsp;in&nbsp;the&nbsp;:hover&nbsp;state&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a105"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_HOVER'</span><span class="src-sym">,&nbsp;</span><span class="src-num">1</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a106"></a><span class="src-doc">/**&nbsp;Links&nbsp;in&nbsp;the&nbsp;source&nbsp;in&nbsp;the&nbsp;:active&nbsp;state&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a107"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_ACTIVE'</span><span class="src-sym">,&nbsp;</span><span class="src-num">2</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a108"></a><span class="src-doc">/**&nbsp;Links&nbsp;in&nbsp;the&nbsp;source&nbsp;in&nbsp;the&nbsp;:visited&nbsp;state&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a109"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_VISITED'</span><span class="src-sym">,&nbsp;</span><span class="src-num">3</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a110"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a111"></a><span class="src-comm">//&nbsp;Important&nbsp;string&nbsp;starter/finisher</span></div></li>
+<li><div class="src-line"><a name="a112"></a><span class="src-comm">//&nbsp;Note&nbsp;that&nbsp;if&nbsp;you&nbsp;change&nbsp;these,&nbsp;they&nbsp;should&nbsp;be&nbsp;as-is:&nbsp;i.e.,&nbsp;don't</span></div></li>
+<li><div class="src-line"><a name="a113"></a><span class="src-comm">//&nbsp;write&nbsp;them&nbsp;as&nbsp;if&nbsp;they&nbsp;had&nbsp;been&nbsp;run&nbsp;through&nbsp;htmlentities()</span></div></li>
+<li><div class="src-line"><a name="a114"></a><span class="src-doc">/**&nbsp;The&nbsp;starter&nbsp;for&nbsp;important&nbsp;parts&nbsp;of&nbsp;the&nbsp;source&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a115"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_START_IMPORTANT'</span><span class="src-sym">,&nbsp;</span><span class="src-str">'&lt;BEGIN&nbsp;GeSHi&gt;'</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a116"></a><span class="src-doc">/**&nbsp;The&nbsp;ender&nbsp;for&nbsp;important&nbsp;parts&nbsp;of&nbsp;the&nbsp;source&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a117"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_END_IMPORTANT'</span><span class="src-sym">,&nbsp;</span><span class="src-str">'&lt;END&nbsp;GeSHi&gt;'</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a118"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a119"></a><span class="src-comm">/**#@+</span></div></li>
+<li><div class="src-line"><a name="a120"></a><span class="src-comm">&nbsp;*&nbsp;&nbsp;@access&nbsp;private</span></div></li>
+<li><div class="src-line"><a name="a121"></a><span class="src-comm">&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a122"></a><span class="src-comm">//&nbsp;When&nbsp;strict&nbsp;mode&nbsp;applies&nbsp;for&nbsp;a&nbsp;language</span></div></li>
+<li><div class="src-line"><a name="a123"></a><span class="src-doc">/**&nbsp;Strict&nbsp;mode&nbsp;never&nbsp;applies&nbsp;(this&nbsp;is&nbsp;the&nbsp;most&nbsp;common)&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a124"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_NEVER'</span><span class="src-sym">,&nbsp;</span><span class="src-num">0</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a125"></a><span class="src-doc">/**&nbsp;Strict&nbsp;mode&nbsp;*might*&nbsp;apply,&nbsp;and&nbsp;can&nbsp;be&nbsp;enabled&nbsp;or</span></div></li>
+<li><div class="src-line"><a name="a126"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;disabled&nbsp;by&nbsp;</span><span class="src-doc-inlinetag">{@link&nbsp;GeSHi-&gt;enable_strict_mode()}</span><span class="src-doc">&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a127"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_MAYBE'</span><span class="src-sym">,&nbsp;</span><span class="src-num">1</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a128"></a><span class="src-doc">/**&nbsp;Strict&nbsp;mode&nbsp;always&nbsp;applies&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a129"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_ALWAYS'</span><span class="src-sym">,&nbsp;</span><span class="src-num">2</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a130"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a131"></a><span class="src-comm">//&nbsp;Advanced&nbsp;regexp&nbsp;handling&nbsp;constants,&nbsp;used&nbsp;in&nbsp;language&nbsp;files</span></div></li>
+<li><div class="src-line"><a name="a132"></a><span class="src-doc">/**&nbsp;The&nbsp;key&nbsp;of&nbsp;the&nbsp;regex&nbsp;array&nbsp;defining&nbsp;what&nbsp;to&nbsp;search&nbsp;for&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a133"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_SEARCH'</span><span class="src-sym">,&nbsp;</span><span class="src-num">0</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a134"></a><span class="src-doc">/**&nbsp;The&nbsp;key&nbsp;of&nbsp;the&nbsp;regex&nbsp;array&nbsp;defining&nbsp;what&nbsp;bracket&nbsp;group&nbsp;in&nbsp;a</span></div></li>
+<li><div class="src-line"><a name="a135"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;matched&nbsp;search&nbsp;to&nbsp;use&nbsp;as&nbsp;a&nbsp;replacement&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a136"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_REPLACE'</span><span class="src-sym">,&nbsp;</span><span class="src-num">1</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a137"></a><span class="src-doc">/**&nbsp;The&nbsp;key&nbsp;of&nbsp;the&nbsp;regex&nbsp;array&nbsp;defining&nbsp;any&nbsp;modifiers&nbsp;to&nbsp;the&nbsp;regular&nbsp;expression&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a138"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_MODIFIERS'</span><span class="src-sym">,&nbsp;</span><span class="src-num">2</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a139"></a><span class="src-doc">/**&nbsp;The&nbsp;key&nbsp;of&nbsp;the&nbsp;regex&nbsp;array&nbsp;defining&nbsp;what&nbsp;bracket&nbsp;group&nbsp;in&nbsp;a</span></div></li>
+<li><div class="src-line"><a name="a140"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;matched&nbsp;search&nbsp;to&nbsp;put&nbsp;before&nbsp;the&nbsp;replacement&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a141"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_BEFORE'</span><span class="src-sym">,&nbsp;</span><span class="src-num">3</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a142"></a><span class="src-doc">/**&nbsp;The&nbsp;key&nbsp;of&nbsp;the&nbsp;regex&nbsp;array&nbsp;defining&nbsp;what&nbsp;bracket&nbsp;group&nbsp;in&nbsp;a</span></div></li>
+<li><div class="src-line"><a name="a143"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;matched&nbsp;search&nbsp;to&nbsp;put&nbsp;after&nbsp;the&nbsp;replacement&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a144"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_AFTER'</span><span class="src-sym">,&nbsp;</span><span class="src-num">4</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a145"></a><span class="src-doc">/**&nbsp;The&nbsp;key&nbsp;of&nbsp;the&nbsp;regex&nbsp;array&nbsp;defining&nbsp;a&nbsp;custom&nbsp;keyword&nbsp;to&nbsp;use</span></div></li>
+<li><div class="src-line"><a name="a146"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;this&nbsp;regexp's&nbsp;html&nbsp;tag&nbsp;class&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a147"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_CLASS'</span><span class="src-sym">,&nbsp;</span><span class="src-num">5</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a148"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a149"></a><span class="src-doc">/**&nbsp;Used&nbsp;in&nbsp;language&nbsp;files&nbsp;to&nbsp;mark&nbsp;comments&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a150"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_COMMENTS'</span><span class="src-sym">,&nbsp;</span><span class="src-num">0</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a151"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a152"></a><span class="src-doc">/**&nbsp;Used&nbsp;to&nbsp;work&nbsp;around&nbsp;missing&nbsp;PHP&nbsp;features&nbsp;**/</span></div></li>
+<li><div class="src-line"><a name="a153"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_PHP_PRE_433'</span><span class="src-sym">,&nbsp;</span><span class="src-sym">!</span><span class="src-sym">(</span><span class="src-id">version_compare</span><span class="src-sym">(</span><span class="src-id">PHP_VERSION</span><span class="src-sym">,&nbsp;</span><span class="src-str">'4.3.3'</span><span class="src-sym">)&nbsp;</span>===&nbsp;<span class="src-num">1</span><span class="src-sym">))</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a154"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a155"></a><span class="src-doc">/**&nbsp;make&nbsp;sure&nbsp;we&nbsp;can&nbsp;call&nbsp;stripos&nbsp;**/</span></div></li>
+<li><div class="src-line"><a name="a156"></a><span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-sym">!</span><a href="http://www.php.net/function_exists">function_exists</a><span class="src-sym">(</span><span class="src-str">'stripos'</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a157"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;the&nbsp;offset&nbsp;param&nbsp;of&nbsp;preg_match&nbsp;is&nbsp;not&nbsp;supported&nbsp;below&nbsp;PHP&nbsp;4.3.3</span></div></li>
+<li><div class="src-line"><a name="a158"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-id">GESHI_PHP_PRE_433</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a159"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a160"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@ignore</span></div></li>
+<li><div class="src-line"><a name="a161"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a162"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function&nbsp;</span><a href="http://www.php.net/stripos">stripos</a><span class="src-sym">(</span><span class="src-var">$haystack</span><span class="src-sym">,&nbsp;</span><span class="src-var">$needle</span><span class="src-sym">,&nbsp;</span><span class="src-var">$offset&nbsp;</span>=&nbsp;<span class="src-id">null</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a163"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-sym">!</span><a href="http://www.php.net/is_null">is_null</a><span class="src-sym">(</span><span class="src-var">$offset</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a164"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$haystack&nbsp;</span>=&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$haystack</span><span class="src-sym">,&nbsp;</span><span class="src-var">$offset</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a165"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a166"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><a href="http://www.php.net/preg_match">preg_match</a><span class="src-sym">(</span><span class="src-str">'/'</span>.&nbsp;<a href="http://www.php.net/preg_quote">preg_quote</a><span class="src-sym">(</span><span class="src-var">$needle</span><span class="src-sym">,&nbsp;</span><span class="src-str">'/'</span><span class="src-sym">)&nbsp;</span>.&nbsp;<span class="src-str">'/'</span><span class="src-sym">,&nbsp;</span><span class="src-var">$haystack</span><span class="src-sym">,&nbsp;</span><span class="src-var">$match</span><span class="src-sym">,&nbsp;</span><span class="src-id">PREG_OFFSET_CAPTURE</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a167"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return&nbsp;</span><span class="src-var">$match</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a168"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a169"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return&nbsp;</span><span class="src-id">false</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a170"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a171"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a172"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">else&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a173"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a174"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@ignore</span></div></li>
+<li><div class="src-line"><a name="a175"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a176"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function&nbsp;</span><a href="http://www.php.net/stripos">stripos</a><span class="src-sym">(</span><span class="src-var">$haystack</span><span class="src-sym">,&nbsp;</span><span class="src-var">$needle</span><span class="src-sym">,&nbsp;</span><span class="src-var">$offset&nbsp;</span>=&nbsp;<span class="src-id">null</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a177"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><a href="http://www.php.net/preg_match">preg_match</a><span class="src-sym">(</span><span class="src-str">'/'</span>.&nbsp;<a href="http://www.php.net/preg_quote">preg_quote</a><span class="src-sym">(</span><span class="src-var">$needle</span><span class="src-sym">,&nbsp;</span><span class="src-str">'/'</span><span class="src-sym">)&nbsp;</span>.&nbsp;<span class="src-str">'/'</span><span class="src-sym">,&nbsp;</span><span class="src-var">$haystack</span><span class="src-sym">,&nbsp;</span><span class="src-var">$match</span><span class="src-sym">,&nbsp;</span><span class="src-id">PREG_OFFSET_CAPTURE</span><span class="src-sym">,&nbsp;</span><span class="src-var">$offset</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a178"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return&nbsp;</span><span class="src-var">$match</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a179"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a180"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return&nbsp;</span><span class="src-id">false</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a181"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a182"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a183"></a><span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a184"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a185"></a><span class="src-doc">/**&nbsp;some&nbsp;old&nbsp;PHP&nbsp;/&nbsp;PCRE&nbsp;subpatterns&nbsp;only&nbsp;support&nbsp;up&nbsp;to&nbsp;xxx&nbsp;subpatterns&nbsp;in</span></div></li>
+<li><div class="src-line"><a name="a186"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;regular&nbsp;expressions.&nbsp;Set&nbsp;this&nbsp;to&nbsp;false&nbsp;if&nbsp;your&nbsp;PCRE&nbsp;lib&nbsp;is&nbsp;up&nbsp;to&nbsp;date</span></div></li>
+<li><div class="src-line"><a name="a187"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;@see&nbsp;GeSHi-&gt;optimize_regexp_list()</span></div></li>
+<li><div class="src-line"><a name="a188"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;**/</span></div></li>
+<li><div class="src-line"><a name="a188"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a189"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_MAX_PCRE_SUBPATTERNS'</span><span class="src-sym">,&nbsp;</span><span class="src-num">500</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a190"></a><span class="src-doc">/**&nbsp;it's&nbsp;also&nbsp;important&nbsp;not&nbsp;to&nbsp;generate&nbsp;too&nbsp;long&nbsp;regular&nbsp;expressions</span></div></li>
+<li><div class="src-line"><a name="a191"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;be&nbsp;generous&nbsp;here...&nbsp;but&nbsp;keep&nbsp;in&nbsp;mind,&nbsp;that&nbsp;when&nbsp;reaching&nbsp;this&nbsp;limit&nbsp;we</span></div></li>
+<li><div class="src-line"><a name="a192"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;still&nbsp;have&nbsp;to&nbsp;close&nbsp;open&nbsp;patterns.&nbsp;12k&nbsp;should&nbsp;do&nbsp;just&nbsp;fine&nbsp;on&nbsp;a&nbsp;16k&nbsp;limit.</span></div></li>
+<li><div class="src-line"><a name="a193"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;@see&nbsp;GeSHi-&gt;optimize_regexp_list()</span></div></li>
+<li><div class="src-line"><a name="a194"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;**/</span></div></li>
+<li><div class="src-line"><a name="a194"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a195"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_MAX_PCRE_LENGTH'</span><span class="src-sym">,&nbsp;</span><span class="src-num">12288</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a196"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a197"></a><span class="src-comm">//Number&nbsp;format&nbsp;specification</span></div></li>
+<li><div class="src-line"><a name="a198"></a><span class="src-doc">/**&nbsp;Basic&nbsp;number&nbsp;format&nbsp;for&nbsp;integers&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a199"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_NUMBER_INT_BASIC'</span><span class="src-sym">,&nbsp;</span><span class="src-num">1</span><span class="src-sym">)</span><span class="src-sym">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="src-comm">//Default&nbsp;integers&nbsp;\d+</span></div></li>
+<li><div class="src-line"><a name="a200"></a><span class="src-doc">/**&nbsp;Enhanced&nbsp;number&nbsp;format&nbsp;for&nbsp;integers&nbsp;like&nbsp;seen&nbsp;in&nbsp;C&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a201"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_NUMBER_INT_CSTYLE'</span><span class="src-sym">,&nbsp;</span><span class="src-num">2</span><span class="src-sym">)</span><span class="src-sym">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="src-comm">//Default&nbsp;C-Style&nbsp;\d+[lL]?</span></div></li>
+<li><div class="src-line"><a name="a202"></a><span class="src-doc">/**&nbsp;Number&nbsp;format&nbsp;to&nbsp;highlight&nbsp;binary&nbsp;numbers&nbsp;with&nbsp;a&nbsp;suffix&nbsp;&quot;b&quot;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a203"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_NUMBER_BIN_SUFFIX'</span><span class="src-sym">,&nbsp;</span><span class="src-num">16</span><span class="src-sym">)</span><span class="src-sym">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="src-comm">//[01]+[bB]</span></div></li>
+<li><div class="src-line"><a name="a204"></a><span class="src-doc">/**&nbsp;Number&nbsp;format&nbsp;to&nbsp;highlight&nbsp;binary&nbsp;numbers&nbsp;with&nbsp;a&nbsp;prefix&nbsp;%&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a205"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_NUMBER_BIN_PREFIX_PERCENT'</span><span class="src-sym">,&nbsp;</span><span class="src-num">32</span><span class="src-sym">)</span><span class="src-sym">;&nbsp;&nbsp;&nbsp;</span><span class="src-comm">//%[01]+</span></div></li>
+<li><div class="src-line"><a name="a206"></a><span class="src-doc">/**&nbsp;Number&nbsp;format&nbsp;to&nbsp;highlight&nbsp;binary&nbsp;numbers&nbsp;with&nbsp;a&nbsp;prefix&nbsp;0b&nbsp;(C)&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a207"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_NUMBER_BIN_PREFIX_0B'</span><span class="src-sym">,&nbsp;</span><span class="src-num">64</span><span class="src-sym">)</span><span class="src-sym">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="src-comm">//0b[01]+</span></div></li>
+<li><div class="src-line"><a name="a208"></a><span class="src-doc">/**&nbsp;Number&nbsp;format&nbsp;to&nbsp;highlight&nbsp;octal&nbsp;numbers&nbsp;with&nbsp;a&nbsp;leading&nbsp;zero&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a209"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_NUMBER_OCT_PREFIX'</span><span class="src-sym">,&nbsp;</span><span class="src-num">256</span><span class="src-sym">)</span><span class="src-sym">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="src-comm">//0[0-7]+</span></div></li>
+<li><div class="src-line"><a name="a210"></a><span class="src-doc">/**&nbsp;Number&nbsp;format&nbsp;to&nbsp;highlight&nbsp;octal&nbsp;numbers&nbsp;with&nbsp;a&nbsp;suffix&nbsp;of&nbsp;o&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a211"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_NUMBER_OCT_SUFFIX'</span><span class="src-sym">,&nbsp;</span><span class="src-num">512</span><span class="src-sym">)</span><span class="src-sym">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="src-comm">//[0-7]+[oO]</span></div></li>
+<li><div class="src-line"><a name="a212"></a><span class="src-doc">/**&nbsp;Number&nbsp;format&nbsp;to&nbsp;highlight&nbsp;hex&nbsp;numbers&nbsp;with&nbsp;a&nbsp;prefix&nbsp;0x&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a213"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_NUMBER_HEX_PREFIX'</span><span class="src-sym">,&nbsp;</span><span class="src-num">4096</span><span class="src-sym">)</span><span class="src-sym">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="src-comm">//0x[0-9a-fA-F]+</span></div></li>
+<li><div class="src-line"><a name="a214"></a><span class="src-doc">/**&nbsp;Number&nbsp;format&nbsp;to&nbsp;highlight&nbsp;hex&nbsp;numbers&nbsp;with&nbsp;a&nbsp;suffix&nbsp;of&nbsp;h&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a215"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_NUMBER_HEX_SUFFIX'</span><span class="src-sym">,&nbsp;</span><span class="src-num">8192</span><span class="src-sym">)</span><span class="src-sym">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="src-comm">//[0-9][0-9a-fA-F]*h</span></div></li>
+<li><div class="src-line"><a name="a216"></a><span class="src-doc">/**&nbsp;Number&nbsp;format&nbsp;to&nbsp;highlight&nbsp;floating-point&nbsp;numbers&nbsp;without&nbsp;support&nbsp;for&nbsp;scientific&nbsp;notation&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a217"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_NUMBER_FLT_NONSCI'</span><span class="src-sym">,&nbsp;</span><span class="src-num">65536</span><span class="src-sym">)</span><span class="src-sym">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="src-comm">//\d+\.\d+</span></div></li>
+<li><div class="src-line"><a name="a218"></a><span class="src-doc">/**&nbsp;Number&nbsp;format&nbsp;to&nbsp;highlight&nbsp;floating-point&nbsp;numbers&nbsp;without&nbsp;support&nbsp;for&nbsp;scientific&nbsp;notation&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a219"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_NUMBER_FLT_NONSCI_F'</span><span class="src-sym">,&nbsp;</span><span class="src-num">131072</span><span class="src-sym">)</span><span class="src-sym">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="src-comm">//\d+(\.\d+)?f</span></div></li>
+<li><div class="src-line"><a name="a220"></a><span class="src-doc">/**&nbsp;Number&nbsp;format&nbsp;to&nbsp;highlight&nbsp;floating-point&nbsp;numbers&nbsp;with&nbsp;support&nbsp;for&nbsp;scientific&nbsp;notation&nbsp;(E)&nbsp;and&nbsp;optional&nbsp;leading&nbsp;zero&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a221"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_NUMBER_FLT_SCI_SHORT'</span><span class="src-sym">,&nbsp;</span><span class="src-num">262144</span><span class="src-sym">)</span><span class="src-sym">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="src-comm">//\.\d+e\d+</span></div></li>
+<li><div class="src-line"><a name="a222"></a><span class="src-doc">/**&nbsp;Number&nbsp;format&nbsp;to&nbsp;highlight&nbsp;floating-point&nbsp;numbers&nbsp;with&nbsp;support&nbsp;for&nbsp;scientific&nbsp;notation&nbsp;(E)&nbsp;and&nbsp;required&nbsp;leading&nbsp;digit&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a223"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_NUMBER_FLT_SCI_ZERO'</span><span class="src-sym">,&nbsp;</span><span class="src-num">524288</span><span class="src-sym">)</span><span class="src-sym">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="src-comm">//\d+(\.\d+)?e\d+</span></div></li>
+<li><div class="src-line"><a name="a224"></a><span class="src-comm">//Custom&nbsp;formats&nbsp;are&nbsp;passed&nbsp;by&nbsp;RX&nbsp;array</span></div></li>
+<li><div class="src-line"><a name="a225"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a226"></a><span class="src-comm">//&nbsp;Error&nbsp;detection&nbsp;-&nbsp;use&nbsp;these&nbsp;to&nbsp;analyse&nbsp;faults</span></div></li>
+<li><div class="src-line"><a name="a227"></a><span class="src-doc">/**&nbsp;No&nbsp;sourcecode&nbsp;to&nbsp;highlight&nbsp;was&nbsp;specified</span></div></li>
+<li><div class="src-line"><a name="a228"></a><span class="src-doc">&nbsp;*&nbsp;</span><span class="src-doc-coretag">@deprecated</span></div></li>
+<li><div class="src-line"><a name="a229"></a><span class="src-doc">&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a230"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_ERROR_NO_INPUT'</span><span class="src-sym">,&nbsp;</span><span class="src-num">1</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a231"></a><span class="src-doc">/**&nbsp;The&nbsp;language&nbsp;specified&nbsp;does&nbsp;not&nbsp;exist&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a232"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_ERROR_NO_SUCH_LANG'</span><span class="src-sym">,&nbsp;</span><span class="src-num">2</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a233"></a><span class="src-doc">/**&nbsp;GeSHi&nbsp;could&nbsp;not&nbsp;open&nbsp;a&nbsp;file&nbsp;for&nbsp;reading&nbsp;(generally&nbsp;a&nbsp;language&nbsp;file)&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a234"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_ERROR_FILE_NOT_READABLE'</span><span class="src-sym">,&nbsp;</span><span class="src-num">3</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a235"></a><span class="src-doc">/**&nbsp;The&nbsp;header&nbsp;type&nbsp;passed&nbsp;to&nbsp;</span><span class="src-doc-inlinetag">{@link&nbsp;GeSHi-&gt;set_header_type()}</span><span class="src-doc">&nbsp;was&nbsp;invalid&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a236"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_ERROR_INVALID_HEADER_TYPE'</span><span class="src-sym">,&nbsp;</span><span class="src-num">4</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a237"></a><span class="src-doc">/**&nbsp;The&nbsp;line&nbsp;number&nbsp;type&nbsp;passed&nbsp;to&nbsp;</span><span class="src-doc-inlinetag">{@link&nbsp;GeSHi-&gt;enable_line_numbers()}</span><span class="src-doc">&nbsp;was&nbsp;invalid&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a238"></a><a href="http://www.php.net/define">define</a><span class="src-sym">(</span><span class="src-str">'GESHI_ERROR_INVALID_LINE_NUMBER_TYPE'</span><span class="src-sym">,&nbsp;</span><span class="src-num">5</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a239"></a><span class="src-comm">/**#@-*/</span></div></li>
+<li><div class="src-line"><a name="a240"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a241"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a242"></a><span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a243"></a><span class="src-doc">&nbsp;*&nbsp;The&nbsp;GeSHi&nbsp;Class.</span></div></li>
+<li><div class="src-line"><a name="a244"></a><span class="src-doc">&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a245"></a><span class="src-doc">&nbsp;*&nbsp;Please&nbsp;refer&nbsp;to&nbsp;the&nbsp;documentation&nbsp;for&nbsp;GeSHi&nbsp;1.0.X&nbsp;that&nbsp;is&nbsp;available</span></div></li>
+<li><div class="src-line"><a name="a246"></a><span class="src-doc">&nbsp;*&nbsp;at&nbsp;http://qbnz.com/highlighter/documentation.php&nbsp;for&nbsp;more&nbsp;information</span></div></li>
+<li><div class="src-line"><a name="a247"></a><span class="src-doc">&nbsp;*&nbsp;about&nbsp;how&nbsp;to&nbsp;use&nbsp;this&nbsp;class.</span></div></li>
+<li><div class="src-line"><a name="a248"></a><span class="src-doc">&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a249"></a><span class="src-doc">&nbsp;*&nbsp;</span><span class="src-doc-coretag">@package</span><span class="src-doc">&nbsp;&nbsp;&nbsp;geshi</span></div></li>
+<li><div class="src-line"><a name="a250"></a><span class="src-doc">&nbsp;*&nbsp;</span><span class="src-doc-coretag">@author</span><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;Nigel&nbsp;McNie&nbsp;&lt;nigel@geshi.org&gt;,&nbsp;Benny&nbsp;Baumann&nbsp;&lt;BenBE@omorphia.de&gt;</span></div></li>
+<li><div class="src-line"><a name="a251"></a><span class="src-doc">&nbsp;*&nbsp;</span><span class="src-doc-coretag">@copyright</span><span class="src-doc">&nbsp;(C)&nbsp;2004&nbsp;-&nbsp;2007&nbsp;Nigel&nbsp;McNie,&nbsp;(C)&nbsp;2007&nbsp;-&nbsp;2008&nbsp;Benny&nbsp;Baumann</span></div></li>
+<li><div class="src-line"><a name="a252"></a><span class="src-doc">&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a253"></a><span class="src-key">class&nbsp;</span><a href="../geshi/core/GeSHi.html">GeSHi</a>&nbsp;<span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a254"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">/**#@+</span></div></li>
+<li><div class="src-line"><a name="a255"></a><span class="src-comm">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@access&nbsp;private</span></div></li>
+<li><div class="src-line"><a name="a256"></a><span class="src-comm">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a257"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a258"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;source&nbsp;code&nbsp;to&nbsp;highlight</span></div></li>
+<li><div class="src-line"><a name="a259"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a260"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a261"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$source&nbsp;</span>=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a262"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a263"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a264"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;language&nbsp;to&nbsp;use&nbsp;when&nbsp;highlighting</span></div></li>
+<li><div class="src-line"><a name="a265"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a266"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a267"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$language&nbsp;</span>=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a268"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a269"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a270"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;data&nbsp;for&nbsp;the&nbsp;language&nbsp;used</span></div></li>
+<li><div class="src-line"><a name="a271"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">array&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a272"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a273"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$language_data&nbsp;</span>=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a274"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a275"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a276"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;path&nbsp;to&nbsp;the&nbsp;language&nbsp;files</span></div></li>
+<li><div class="src-line"><a name="a277"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a278"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a279"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$language_path&nbsp;</span>=&nbsp;<span class="src-id">GESHI_LANG_ROOT</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a280"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a281"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a282"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;error&nbsp;message&nbsp;associated&nbsp;with&nbsp;an&nbsp;error</span></div></li>
+<li><div class="src-line"><a name="a283"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a284"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@todo</span><span class="src-doc">&nbsp;check&nbsp;err&nbsp;reporting&nbsp;works</span></div></li>
+<li><div class="src-line"><a name="a285"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a286"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$error&nbsp;</span>=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a287"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a288"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a289"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Possible&nbsp;error&nbsp;messages</span></div></li>
+<li><div class="src-line"><a name="a290"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">array&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a291"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a292"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$error_messages&nbsp;</span>=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></div></li>
+<li><div class="src-line"><a name="a293"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">GESHI_ERROR_NO_SUCH_LANG&nbsp;</span>=&gt;&nbsp;<span class="src-str">'GeSHi&nbsp;could&nbsp;not&nbsp;find&nbsp;the&nbsp;language&nbsp;{LANGUAGE}&nbsp;(using&nbsp;path&nbsp;{PATH})'</span><span class="src-sym">,</span></div></li>
+<li><div class="src-line"><a name="a294"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">GESHI_ERROR_FILE_NOT_READABLE&nbsp;</span>=&gt;&nbsp;<span class="src-str">'The&nbsp;file&nbsp;specified&nbsp;for&nbsp;load_from_file&nbsp;was&nbsp;not&nbsp;readable'</span><span class="src-sym">,</span></div></li>
+<li><div class="src-line"><a name="a295"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">GESHI_ERROR_INVALID_HEADER_TYPE&nbsp;</span>=&gt;&nbsp;<span class="src-str">'The&nbsp;header&nbsp;type&nbsp;specified&nbsp;is&nbsp;invalid'</span><span class="src-sym">,</span></div></li>
+<li><div class="src-line"><a name="a296"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">GESHI_ERROR_INVALID_LINE_NUMBER_TYPE&nbsp;</span>=&gt;&nbsp;<span class="src-str">'The&nbsp;line&nbsp;number&nbsp;type&nbsp;specified&nbsp;is&nbsp;invalid'</span></div></li>
+<li><div class="src-line"><a name="a297"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a298"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a299"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a300"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Whether&nbsp;highlighting&nbsp;is&nbsp;strict&nbsp;or&nbsp;not</span></div></li>
+<li><div class="src-line"><a name="a301"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a302"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a303"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$strict_mode&nbsp;</span>=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a304"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a305"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a306"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Whether&nbsp;to&nbsp;use&nbsp;CSS&nbsp;classes&nbsp;in&nbsp;output</span></div></li>
+<li><div class="src-line"><a name="a307"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a308"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a309"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$use_classes&nbsp;</span>=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a310"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a311"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a312"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;type&nbsp;of&nbsp;header&nbsp;to&nbsp;use.&nbsp;Can&nbsp;be&nbsp;one&nbsp;of&nbsp;the&nbsp;following</span></div></li>
+<li><div class="src-line"><a name="a313"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;values:</span></div></li>
+<li><div class="src-line"><a name="a314"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a315"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;-&nbsp;GESHI_HEADER_PRE:&nbsp;Source&nbsp;is&nbsp;outputted&nbsp;in&nbsp;a&nbsp;&quot;pre&quot;&nbsp;HTML&nbsp;element.</span></div></li>
+<li><div class="src-line"><a name="a316"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;-&nbsp;GESHI_HEADER_DIV:&nbsp;Source&nbsp;is&nbsp;outputted&nbsp;in&nbsp;a&nbsp;&quot;div&quot;&nbsp;HTML&nbsp;element.</span></div></li>
+<li><div class="src-line"><a name="a317"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;-&nbsp;GESHI_HEADER_NONE:&nbsp;No&nbsp;header&nbsp;is&nbsp;outputted.</span></div></li>
+<li><div class="src-line"><a name="a318"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a319"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">int&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a320"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a321"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$header_type&nbsp;</span>=&nbsp;<span class="src-id">GESHI_HEADER_PRE</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a322"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a323"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a324"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Array&nbsp;of&nbsp;permissions&nbsp;for&nbsp;which&nbsp;lexics&nbsp;should&nbsp;be&nbsp;highlighted</span></div></li>
+<li><div class="src-line"><a name="a325"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">array&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a326"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a327"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$lexic_permissions&nbsp;</span>=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></div></li>
+<li><div class="src-line"><a name="a328"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'KEYWORDS'&nbsp;</span>=&gt;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">,</span></div></li>
+<li><div class="src-line"><a name="a329"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'COMMENTS'&nbsp;</span>=&gt;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'MULTI'&nbsp;</span>=&gt;&nbsp;<span class="src-id">true</span><span class="src-sym">)</span><span class="src-sym">,</span></div></li>
+<li><div class="src-line"><a name="a330"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'REGEXPS'&nbsp;</span>=&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">,</span></div></li>
+<li><div class="src-line"><a name="a331"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'ESCAPE_CHAR'&nbsp;</span>=&gt;&nbsp;<span class="src-id">true</span><span class="src-sym">,</span></div></li>
+<li><div class="src-line"><a name="a332"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'BRACKETS'&nbsp;</span>=&gt;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">true</span><span class="src-sym">,</span></div></li>
+<li><div class="src-line"><a name="a333"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'SYMBOLS'&nbsp;</span>=&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">false</span><span class="src-sym">,</span></div></li>
+<li><div class="src-line"><a name="a334"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'STRINGS'&nbsp;</span>=&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">true</span><span class="src-sym">,</span></div></li>
+<li><div class="src-line"><a name="a335"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'NUMBERS'&nbsp;</span>=&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">true</span><span class="src-sym">,</span></div></li>
+<li><div class="src-line"><a name="a336"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'METHODS'&nbsp;</span>=&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">true</span><span class="src-sym">,</span></div></li>
+<li><div class="src-line"><a name="a337"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'SCRIPT'&nbsp;</span>=&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">true</span></div></li>
+<li><div class="src-line"><a name="a338"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a339"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a340"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a341"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;time&nbsp;it&nbsp;took&nbsp;to&nbsp;parse&nbsp;the&nbsp;code</span></div></li>
+<li><div class="src-line"><a name="a342"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">double&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a343"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a344"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$time&nbsp;</span>=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a345"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a346"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a347"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;content&nbsp;of&nbsp;the&nbsp;header&nbsp;block</span></div></li>
+<li><div class="src-line"><a name="a348"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a349"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a350"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$header_content&nbsp;</span>=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a351"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a352"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a353"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;content&nbsp;of&nbsp;the&nbsp;footer&nbsp;block</span></div></li>
+<li><div class="src-line"><a name="a354"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a355"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a356"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$footer_content&nbsp;</span>=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a357"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a358"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a359"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;style&nbsp;of&nbsp;the&nbsp;header&nbsp;block</span></div></li>
+<li><div class="src-line"><a name="a360"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a361"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a362"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$header_content_style&nbsp;</span>=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a363"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a364"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a365"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;style&nbsp;of&nbsp;the&nbsp;footer&nbsp;block</span></div></li>
+<li><div class="src-line"><a name="a366"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a367"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a368"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$footer_content_style&nbsp;</span>=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a369"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a370"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a371"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Tells&nbsp;if&nbsp;a&nbsp;block&nbsp;around&nbsp;the&nbsp;highlighted&nbsp;source&nbsp;should&nbsp;be&nbsp;forced</span></div></li>
+<li><div class="src-line"><a name="a372"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;if&nbsp;not&nbsp;using&nbsp;line&nbsp;numbering</span></div></li>
+<li><div class="src-line"><a name="a373"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a374"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a375"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$force_code_block&nbsp;</span>=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a376"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a377"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a378"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;styles&nbsp;for&nbsp;hyperlinks&nbsp;in&nbsp;the&nbsp;code</span></div></li>
+<li><div class="src-line"><a name="a379"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">array&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a380"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a381"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$link_styles&nbsp;</span>=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a382"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a383"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a384"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Whether&nbsp;important&nbsp;blocks&nbsp;should&nbsp;be&nbsp;recognised&nbsp;or&nbsp;not</span></div></li>
+<li><div class="src-line"><a name="a385"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a386"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@deprecated</span></div></li>
+<li><div class="src-line"><a name="a387"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@todo</span><span class="src-doc">&nbsp;REMOVE&nbsp;THIS&nbsp;FUNCTIONALITY!</span></div></li>
+<li><div class="src-line"><a name="a388"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a389"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$enable_important_blocks&nbsp;</span>=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a390"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a391"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a392"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Styles&nbsp;for&nbsp;important&nbsp;parts&nbsp;of&nbsp;the&nbsp;code</span></div></li>
+<li><div class="src-line"><a name="a393"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a394"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@deprecated</span></div></li>
+<li><div class="src-line"><a name="a395"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@todo</span><span class="src-doc">&nbsp;As&nbsp;above&nbsp;-&nbsp;rethink&nbsp;the&nbsp;whole&nbsp;idea&nbsp;of&nbsp;important&nbsp;blocks&nbsp;as&nbsp;it&nbsp;is&nbsp;buggy&nbsp;and</span></div></li>
+<li><div class="src-line"><a name="a396"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;will&nbsp;be&nbsp;hard&nbsp;to&nbsp;implement&nbsp;in&nbsp;1.2</span></div></li>
+<li><div class="src-line"><a name="a397"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a398"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$important_styles&nbsp;</span>=&nbsp;<span class="src-str">'font-weight:&nbsp;bold;&nbsp;color:&nbsp;red;'</span><span class="src-sym">;&nbsp;</span><span class="src-comm">//&nbsp;Styles&nbsp;for&nbsp;important&nbsp;parts&nbsp;of&nbsp;the&nbsp;code</span></div></li>
+<li><div class="src-line"><a name="a399"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a400"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a401"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Whether&nbsp;CSS&nbsp;IDs&nbsp;should&nbsp;be&nbsp;added&nbsp;to&nbsp;the&nbsp;code</span></div></li>
+<li><div class="src-line"><a name="a402"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a403"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a404"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$add_ids&nbsp;</span>=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a405"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a406"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a407"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Lines&nbsp;that&nbsp;should&nbsp;be&nbsp;highlighted&nbsp;extra</span></div></li>
+<li><div class="src-line"><a name="a408"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">array&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a409"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a410"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$highlight_extra_lines&nbsp;</span>=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a411"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a412"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a413"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Styles&nbsp;of&nbsp;lines&nbsp;that&nbsp;should&nbsp;be&nbsp;highlighted&nbsp;extra</span></div></li>
+<li><div class="src-line"><a name="a414"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">array&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a415"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a416"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$highlight_extra_lines_styles&nbsp;</span>=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a417"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a418"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a419"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Styles&nbsp;of&nbsp;extra-highlighted&nbsp;lines</span></div></li>
+<li><div class="src-line"><a name="a420"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a421"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a422"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$highlight_extra_lines_style&nbsp;</span>=&nbsp;<span class="src-str">'background-color:&nbsp;#ffc;'</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a423"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a424"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a425"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;line&nbsp;ending</span></div></li>
+<li><div class="src-line"><a name="a426"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;If&nbsp;null,&nbsp;nl2br()&nbsp;will&nbsp;be&nbsp;used&nbsp;on&nbsp;the&nbsp;result&nbsp;string.</span></div></li>
+<li><div class="src-line"><a name="a427"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Otherwise,&nbsp;all&nbsp;instances&nbsp;of&nbsp;\n&nbsp;will&nbsp;be&nbsp;replaced&nbsp;with&nbsp;$line_ending</span></div></li>
+<li><div class="src-line"><a name="a428"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a429"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a430"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$line_ending&nbsp;</span>=&nbsp;<span class="src-id">null</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a431"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a432"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a433"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Number&nbsp;at&nbsp;which&nbsp;line&nbsp;numbers&nbsp;should&nbsp;start&nbsp;at</span></div></li>
+<li><div class="src-line"><a name="a434"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">int&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a435"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a436"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$line_numbers_start&nbsp;</span>=&nbsp;<span class="src-num">1</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a437"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a438"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a439"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;overall&nbsp;style&nbsp;for&nbsp;this&nbsp;code&nbsp;block</span></div></li>
+<li><div class="src-line"><a name="a440"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a441"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a442"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$overall_style&nbsp;</span>=&nbsp;<span class="src-str">'font-family:monospace;'</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a443"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a444"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a445"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;The&nbsp;style&nbsp;for&nbsp;the&nbsp;actual&nbsp;code</span></div></li>
+<li><div class="src-line"><a name="a446"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a447"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a448"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$code_style&nbsp;</span>=&nbsp;<span class="src-str">'font:&nbsp;normal&nbsp;normal&nbsp;1em/1.2em&nbsp;monospace;&nbsp;margin:0;&nbsp;padding:0;&nbsp;background:none;&nbsp;vertical-align:top;'</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a449"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a450"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a451"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;overall&nbsp;class&nbsp;for&nbsp;this&nbsp;code&nbsp;block</span></div></li>
+<li><div class="src-line"><a name="a452"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a453"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a454"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$overall_class&nbsp;</span>=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a455"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a456"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a457"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;overall&nbsp;ID&nbsp;for&nbsp;this&nbsp;code&nbsp;block</span></div></li>
+<li><div class="src-line"><a name="a458"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a459"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a460"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$overall_id&nbsp;</span>=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a461"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a462"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a463"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Line&nbsp;number&nbsp;styles</span></div></li>
+<li><div class="src-line"><a name="a464"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a465"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a466"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$line_style1&nbsp;</span>=&nbsp;<span class="src-str">'font-weight:&nbsp;normal;&nbsp;vertical-align:top;'</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a467"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a468"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a469"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Line&nbsp;number&nbsp;styles&nbsp;for&nbsp;fancy&nbsp;lines</span></div></li>
+<li><div class="src-line"><a name="a470"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a471"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a472"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$line_style2&nbsp;</span>=&nbsp;<span class="src-str">'font-weight:&nbsp;bold;&nbsp;vertical-align:top;'</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a473"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a474"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a475"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Style&nbsp;for&nbsp;line&nbsp;numbers&nbsp;when&nbsp;GESHI_HEADER_PRE_TABLE&nbsp;is&nbsp;chosen</span></div></li>
+<li><div class="src-line"><a name="a476"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a477"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a478"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$table_linenumber_style&nbsp;</span>=&nbsp;<span class="src-str">'width:1px;text-align:right;margin:0;padding:0&nbsp;2px;vertical-align:top;'</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a479"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a480"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a481"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Flag&nbsp;for&nbsp;how&nbsp;line&nbsp;numbers&nbsp;are&nbsp;displayed</span></div></li>
+<li><div class="src-line"><a name="a482"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a483"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a484"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$line_numbers&nbsp;</span>=&nbsp;<span class="src-id">GESHI_NO_LINE_NUMBERS</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a485"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a486"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a487"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Flag&nbsp;to&nbsp;decide&nbsp;if&nbsp;multi&nbsp;line&nbsp;spans&nbsp;are&nbsp;allowed.&nbsp;Set&nbsp;it&nbsp;to&nbsp;false&nbsp;to&nbsp;make&nbsp;sure</span></div></li>
+<li><div class="src-line"><a name="a488"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;each&nbsp;tag&nbsp;is&nbsp;closed&nbsp;before&nbsp;and&nbsp;reopened&nbsp;after&nbsp;each&nbsp;linefeed.</span></div></li>
+<li><div class="src-line"><a name="a489"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a490"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a491"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$allow_multiline_span&nbsp;</span>=&nbsp;<span class="src-id">true</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a492"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a493"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a494"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;&quot;nth&quot;&nbsp;value&nbsp;for&nbsp;fancy&nbsp;line&nbsp;highlighting</span></div></li>
+<li><div class="src-line"><a name="a495"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">int&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a496"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a497"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$line_nth_row&nbsp;</span>=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a498"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a499"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a500"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;size&nbsp;of&nbsp;tab&nbsp;stops</span></div></li>
+<li><div class="src-line"><a name="a501"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">int&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a502"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a503"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$tab_width&nbsp;</span>=&nbsp;<span class="src-num">8</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a504"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a505"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a506"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Should&nbsp;we&nbsp;use&nbsp;language-defined&nbsp;tab&nbsp;stop&nbsp;widths?</span></div></li>
+<li><div class="src-line"><a name="a507"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">int&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a508"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a509"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$use_language_tab_width&nbsp;</span>=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a510"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a511"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a512"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Default&nbsp;target&nbsp;for&nbsp;keyword&nbsp;links</span></div></li>
+<li><div class="src-line"><a name="a513"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a514"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a515"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$link_target&nbsp;</span>=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a516"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a517"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a518"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;encoding&nbsp;to&nbsp;use&nbsp;for&nbsp;entity&nbsp;encoding</span></div></li>
+<li><div class="src-line"><a name="a519"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;NOTE:&nbsp;Used&nbsp;with&nbsp;Escape&nbsp;Char&nbsp;Sequences&nbsp;to&nbsp;fix&nbsp;UTF-8&nbsp;handling&nbsp;(cf.&nbsp;SF#2037598)</span></div></li>
+<li><div class="src-line"><a name="a520"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a521"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a522"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$encoding&nbsp;</span>=&nbsp;<span class="src-str">'utf-8'</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a523"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a524"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a525"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Should&nbsp;keywords&nbsp;be&nbsp;linked?</span></div></li>
+<li><div class="src-line"><a name="a526"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a527"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a528"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$keyword_links&nbsp;</span>=&nbsp;<span class="src-id">true</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a529"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a530"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a531"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Currently&nbsp;loaded&nbsp;language&nbsp;file</span></div></li>
+<li><div class="src-line"><a name="a532"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a533"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.7.22</span></div></li>
+<li><div class="src-line"><a name="a534"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a535"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$loaded_language&nbsp;</span>=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a536"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a537"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a538"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Wether&nbsp;the&nbsp;caches&nbsp;needed&nbsp;for&nbsp;parsing&nbsp;are&nbsp;built&nbsp;or&nbsp;not</span></div></li>
+<li><div class="src-line"><a name="a539"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a540"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">bool&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a541"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.8</span></div></li>
+<li><div class="src-line"><a name="a542"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a543"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$parse_cache_built&nbsp;</span>=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a544"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a545"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a546"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Work&nbsp;around&nbsp;for&nbsp;Suhosin&nbsp;Patch&nbsp;with&nbsp;disabled&nbsp;/e&nbsp;modifier</span></div></li>
+<li><div class="src-line"><a name="a547"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a548"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Note&nbsp;from&nbsp;suhosins&nbsp;author&nbsp;in&nbsp;config&nbsp;file:</span></div></li>
+<li><div class="src-line"><a name="a549"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;blockquote&gt;</span></div></li>
+<li><div class="src-line"><a name="a550"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;The&nbsp;/e&nbsp;modifier&nbsp;inside&nbsp;&lt;code&gt;preg_replace()&lt;/code&gt;&nbsp;allows&nbsp;code&nbsp;execution.</span></div></li>
+<li><div class="src-line"><a name="a551"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;Often&nbsp;it&nbsp;is&nbsp;the&nbsp;cause&nbsp;for&nbsp;remote&nbsp;code&nbsp;execution&nbsp;exploits.&nbsp;It&nbsp;is&nbsp;wise&nbsp;to</span></div></li>
+<li><div class="src-line"><a name="a552"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;deactivate&nbsp;this&nbsp;feature&nbsp;and&nbsp;test&nbsp;where&nbsp;in&nbsp;the&nbsp;application&nbsp;it&nbsp;is&nbsp;used.</span></div></li>
+<li><div class="src-line"><a name="a553"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;The&nbsp;developer&nbsp;using&nbsp;the&nbsp;/e&nbsp;modifier&nbsp;should&nbsp;be&nbsp;made&nbsp;aware&nbsp;that&nbsp;he&nbsp;should</span></div></li>
+<li><div class="src-line"><a name="a554"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;use&nbsp;&lt;code&gt;preg_replace_callback()&lt;/code&gt;&nbsp;instead</span></div></li>
+<li><div class="src-line"><a name="a555"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;/blockquote&gt;</span></div></li>
+<li><div class="src-line"><a name="a556"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a557"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">array&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a558"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.8</span></div></li>
+<li><div class="src-line"><a name="a559"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a560"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$_kw_replace_group&nbsp;</span>=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a561"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$_rx_key&nbsp;</span>=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a562"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a563"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a564"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;some&nbsp;&quot;callback&nbsp;parameters&quot;&nbsp;for&nbsp;handle_multiline_regexps</span></div></li>
+<li><div class="src-line"><a name="a565"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a566"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.8</span></div></li>
+<li><div class="src-line"><a name="a567"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@access</span><span class="src-doc">&nbsp;private</span></div></li>
+<li><div class="src-line"><a name="a568"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@var&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a569"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a570"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$_hmr_before&nbsp;</span>=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a571"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$_hmr_replace&nbsp;</span>=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a572"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$_hmr_after&nbsp;</span>=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a573"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">var&nbsp;</span><span class="src-var">$_hmr_key&nbsp;</span>=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a574"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a575"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">/**#@-*/</span></div></li>
+<li><div class="src-line"><a name="a576"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a577"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a578"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Creates&nbsp;a&nbsp;new&nbsp;GeSHi&nbsp;object,&nbsp;with&nbsp;source&nbsp;and&nbsp;language</span></div></li>
+<li><div class="src-line"><a name="a579"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a580"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;source&nbsp;code&nbsp;to&nbsp;highlight</span></div></li>
+<li><div class="src-line"><a name="a581"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;language&nbsp;to&nbsp;highlight&nbsp;the&nbsp;source&nbsp;with</span></div></li>
+<li><div class="src-line"><a name="a582"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;path&nbsp;to&nbsp;the&nbsp;language&nbsp;file&nbsp;directory.&nbsp;&lt;b&gt;This</span></div></li>
+<li><div class="src-line"><a name="a583"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;is&nbsp;deprecated!&lt;/b&gt;&nbsp;I've&nbsp;backported&nbsp;the&nbsp;auto&nbsp;path</span></div></li>
+<li><div class="src-line"><a name="a584"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;detection&nbsp;from&nbsp;the&nbsp;1.1.X&nbsp;dev&nbsp;branch,&nbsp;so&nbsp;now&nbsp;it</span></div></li>
+<li><div class="src-line"><a name="a585"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;should&nbsp;be&nbsp;automatically&nbsp;set&nbsp;correctly.&nbsp;If&nbsp;you&nbsp;have</span></div></li>
+<li><div class="src-line"><a name="a586"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;renamed&nbsp;the&nbsp;language&nbsp;directory&nbsp;however,&nbsp;you&nbsp;will</span></div></li>
+<li><div class="src-line"><a name="a587"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;still&nbsp;need&nbsp;to&nbsp;set&nbsp;the&nbsp;path&nbsp;using&nbsp;this&nbsp;parameter&nbsp;or</span></div></li>
+<li><div class="src-line"><a name="a588"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="src-doc-inlinetag">{@link&nbsp;GeSHi-&gt;set_language_path()}</span></div></li>
+<li><div class="src-line"><a name="a589"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a590"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a591"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function&nbsp;</span><a href="../geshi/core/GeSHi.html#methodGeSHi">GeSHi</a><span class="src-sym">(</span><span class="src-var">$source&nbsp;</span>=&nbsp;<span class="src-str">''</span><span class="src-sym">,&nbsp;</span><span class="src-var">$language&nbsp;</span>=&nbsp;<span class="src-str">''</span><span class="src-sym">,&nbsp;</span><span class="src-var">$path&nbsp;</span>=&nbsp;<span class="src-str">''</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a592"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-sym">!</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$source</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a593"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodset_source">set_source</a><span class="src-sym">(</span><span class="src-var">$source</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a594"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a595"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-sym">!</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$language</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a596"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodset_language">set_language</a><span class="src-sym">(</span><span class="src-var">$language</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a597"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a598"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodset_language_path">set_language_path</a><span class="src-sym">(</span><span class="src-var">$path</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a599"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a600"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a601"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-doc">/**</span></div></li>
+<li><div class="src-line"><a name="a602"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Returns&nbsp;an&nbsp;error&nbsp;message&nbsp;associated&nbsp;with&nbsp;the&nbsp;last&nbsp;GeSHi&nbsp;operation,</span></div></li>
+<li><div class="src-line"><a name="a603"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;or&nbsp;false&nbsp;if&nbsp;no&nbsp;error&nbsp;has&nbsp;occured</span></div></li>
+<li><div class="src-line"><a name="a604"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a605"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@return&nbsp;</span><span class="src-doc-type">string</span><span class="src-doc">|</span><span class="src-doc-type">false</span><span class="src-doc">An&nbsp;error&nbsp;message&nbsp;if&nbsp;there&nbsp;has&nbsp;been&nbsp;an&nbsp;error,&nbsp;else&nbsp;false</span></div></li>
+<li><div class="src-line"><a name="a606"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a607"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a608"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function&nbsp;</span><a href="../geshi/core/GeSHi.html#methoderror">error</a><span class="src-sym">(</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a609"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">error</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a610"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Put&nbsp;some&nbsp;template&nbsp;variables&nbsp;for&nbsp;debugging&nbsp;here&nbsp;...</span></div></li>
+<li><div class="src-line"><a name="a611"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$debug_tpl_vars&nbsp;</span>=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></div></li>
+<li><div class="src-line"><a name="a612"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'{LANGUAGE}'&nbsp;</span>=&gt;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language</span><span class="src-sym">,</span></div></li>
+<li><div class="src-line"><a name="a613"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'{PATH}'&nbsp;</span>=&gt;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_path</span></div></li>
+<li><div class="src-line"><a name="a614"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a615"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$msg&nbsp;</span>=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span></div></li>
+<li><div class="src-line"><a name="a616"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/array_keys">array_keys</a><span class="src-sym">(</span><span class="src-var">$debug_tpl_vars</span><span class="src-sym">)</span><span class="src-sym">,</span></div></li>
+<li><div class="src-line"><a name="a617"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/array_values">array_values</a><span class="src-sym">(</span><span class="src-var">$debug_tpl_vars</span><span class="src-sym">)</span><span class="src-sym">,</span></div></li>
+<li><div class="src-line"><a name="a618"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">error_messages</span><span class="src-sym">[</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">error</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a619"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a620"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return&nbsp;</span><span class="src-str">&quot;</span><span class="src-str">&lt;br&nbsp;/&gt;&lt;strong&gt;GeSHi&nbsp;Error:&lt;/strong&gt;&nbsp;<span class="src-var">$msg</span>&nbsp;(code&nbsp;{<span class="src-var">$this</span></span><span class="src-sym">-&gt;</span><span class="src-var">error</span><span class="src-sym">}</span>)&lt;br&nbsp;/&gt;</span><span class="src-str"><span class="src-str">"</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a621"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a622"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a623"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a624"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a625"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;/**</span></div></li>
+<li><div class="src-line"><a name="a626"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Gets&nbsp;a&nbsp;human-readable&nbsp;language&nbsp;name&nbsp;(thanks&nbsp;to&nbsp;Simon&nbsp;Patterson</span></div></li>
+<li><div class="src-line"><a name="a627"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;for&nbsp;the&nbsp;idea&nbsp;:))</span></div></li>
+<li><div class="src-line"><a name="a628"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a629"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;string&nbsp;The&nbsp;name&nbsp;for&nbsp;the&nbsp;current&nbsp;language</span></div></li>
+<li><div class="src-line"><a name="a630"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@since&nbsp;&nbsp;1.0.2</span></div></li>
+<li><div class="src-line"><a name="a631"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a632"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<span class="src-id">get_language_name</span><span class="src-sym">(</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a633"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-id">GESHI_ERROR_NO_SUCH_LANG</span>&nbsp;==&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">error</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a634"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'LANG_NAME'</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&nbsp;(Unknown&nbsp;Language)'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a635"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a636"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'LANG_NAME'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a637"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a638"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a639"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a640"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;source&nbsp;code&nbsp;for&nbsp;this&nbsp;object</span></div></li>
+<li><div class="src-line"><a name="a641"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a642"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;source&nbsp;code&nbsp;to&nbsp;highlight</span></div></li>
+<li><div class="src-line"><a name="a643"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a644"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a645"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_source">set_source</a><span class="src-sym">(</span><span class="src-var">$source</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a646"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">source</span>&nbsp;=&nbsp;<span class="src-var">$source</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a647"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">highlight_extra_lines</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a648"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a649"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a650"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a651"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;language&nbsp;for&nbsp;this&nbsp;object</span></div></li>
+<li><div class="src-line"><a name="a652"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a653"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-tag">@note</span><span class="src-doc">&nbsp;since&nbsp;1.0.8&nbsp;this&nbsp;function&nbsp;won't&nbsp;reset&nbsp;language-settings&nbsp;by&nbsp;default&nbsp;anymore!</span></div></li>
+<li><div class="src-line"><a name="a654"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;you&nbsp;need&nbsp;this&nbsp;set&nbsp;$force_reset&nbsp;=&nbsp;true</span></div></li>
+<li><div class="src-line"><a name="a655"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a656"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;name&nbsp;of&nbsp;the&nbsp;language&nbsp;to&nbsp;use</span></div></li>
+<li><div class="src-line"><a name="a657"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a658"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a659"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_language">set_language</a><span class="src-sym">(</span><span class="src-var">$language</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$force_reset</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a660"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$force_reset</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a661"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">loaded_language</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a662"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a663"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a664"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Clean&nbsp;up&nbsp;the&nbsp;language&nbsp;name&nbsp;to&nbsp;prevent&nbsp;malicious&nbsp;code&nbsp;injection</span></span></div></li>
+<li><div class="src-line"><a name="a665"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$language</span>&nbsp;=&nbsp;<a href="http://www.php.net/preg_replace">preg_replace</a><span class="src-sym">(</span><span class="src-str">'#[^a-zA-Z0-9\-_]#'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">''</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$language</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a666"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a667"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$language</span>&nbsp;=&nbsp;<a href="http://www.php.net/strtolower">strtolower</a><span class="src-sym">(</span><span class="src-var">$language</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a668"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a669"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Retreive&nbsp;the&nbsp;full&nbsp;filename</span></span></div></li>
+<li><div class="src-line"><a name="a670"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$file_name</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_path</span>&nbsp;.&nbsp;<span class="src-var">$language</span>&nbsp;.&nbsp;<span class="src-str">'.php'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a671"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$file_name</span>&nbsp;==&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">loaded_language</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a672"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;this&nbsp;language&nbsp;is&nbsp;already&nbsp;loaded!</span></span></div></li>
+<li><div class="src-line"><a name="a673"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a674"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a675"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a676"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language</span>&nbsp;=&nbsp;<span class="src-var">$language</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a677"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a678"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">error</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a679"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">strict_mode</span>&nbsp;=&nbsp;<span class="src-id">GESHI_NEVER</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a680"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a681"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Check&nbsp;if&nbsp;we&nbsp;can&nbsp;read&nbsp;the&nbsp;desired&nbsp;file</span></span></div></li>
+<li><div class="src-line"><a name="a682"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><a href="http://www.php.net/is_readable">is_readable</a><span class="src-sym">(</span><span class="src-var">$file_name</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a683"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">error</span>&nbsp;=&nbsp;<span class="src-id">GESHI_ERROR_NO_SUCH_LANG</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a684"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a685"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a686"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a687"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Load&nbsp;the&nbsp;language&nbsp;for&nbsp;parsing</span></span></div></li>
+<li><div class="src-line"><a name="a688"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">load_language</span><span class="src-sym">(</span><span class="src-var">$file_name</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a689"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a690"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a691"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a692"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;path&nbsp;to&nbsp;the&nbsp;directory&nbsp;containing&nbsp;the&nbsp;language&nbsp;files.&nbsp;Note</span></div></li>
+<li><div class="src-line"><a name="a693"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;that&nbsp;this&nbsp;path&nbsp;is&nbsp;relative&nbsp;to&nbsp;the&nbsp;directory&nbsp;of&nbsp;the&nbsp;script&nbsp;that&nbsp;included</span></div></li>
+<li><div class="src-line"><a name="a694"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;geshi.php,&nbsp;NOT&nbsp;geshi.php&nbsp;itself.</span></div></li>
+<li><div class="src-line"><a name="a695"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a696"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;path&nbsp;to&nbsp;the&nbsp;language&nbsp;directory</span></div></li>
+<li><div class="src-line"><a name="a697"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a698"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@deprecated</span><span class="src-doc">&nbsp;The&nbsp;path&nbsp;to&nbsp;the&nbsp;language&nbsp;files&nbsp;should&nbsp;now&nbsp;be&nbsp;automatically</span></div></li>
+<li><div class="src-line"><a name="a699"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;detected,&nbsp;so&nbsp;this&nbsp;method&nbsp;should&nbsp;no&nbsp;longer&nbsp;be&nbsp;needed.&nbsp;The</span></div></li>
+<li><div class="src-line"><a name="a700"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.1.X&nbsp;branch&nbsp;handles&nbsp;manual&nbsp;setting&nbsp;of&nbsp;the&nbsp;path&nbsp;differently</span></div></li>
+<li><div class="src-line"><a name="a701"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;so&nbsp;this&nbsp;method&nbsp;will&nbsp;disappear&nbsp;in&nbsp;1.2.0.</span></div></li>
+<li><div class="src-line"><a name="a702"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a703"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_language_path">set_language_path</a><span class="src-sym">(</span><span class="src-var">$path</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a704"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$path</span><span class="src-sym">,</span><span class="src-str">':'</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a705"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Security&nbsp;Fix&nbsp;to&nbsp;prevent&nbsp;external&nbsp;directories&nbsp;using&nbsp;fopen&nbsp;wrappers.</span></span></div></li>
+<li><div class="src-line"><a name="a706"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-id">DIRECTORY_SEPARATOR</span>&nbsp;==&nbsp;<span class="src-str">&quot;\\&quot;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a707"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-sym">!</span><a href="http://www.php.net/preg_match">preg_match</a><span class="src-sym">(</span><span class="src-str">'#^[a-zA-Z]:#'</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$path</span><span class="src-sym">)</span>&nbsp;||&nbsp;<span class="src-id">false</span>&nbsp;!==&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$path</span><span class="src-sym">,</span>&nbsp;<span class="src-str">':'</span><span class="src-sym">,</span>&nbsp;<span class="src-num">2</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a708"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a709"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a710"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a711"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a712"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a713"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a714"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><a href="http://www.php.net/preg_match">preg_match</a><span class="src-sym">(</span><span class="src-str">'#[^/a-zA-Z0-9_\.\-\\\s:]#'</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$path</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a715"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Security&nbsp;Fix&nbsp;to&nbsp;prevent&nbsp;external&nbsp;directories&nbsp;using&nbsp;fopen&nbsp;wrappers.</span></span></div></li>
+<li><div class="src-line"><a name="a716"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a717"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a718"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_SECURITY_PARANOID&quot;&gt;GESHI_SECURITY_PARANOID&lt;/a&gt;</span>&nbsp;&amp;&amp;&nbsp;<span class="src-id">false</span>&nbsp;!==&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$path</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'/.'</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a719"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Security&nbsp;Fix&nbsp;to&nbsp;prevent&nbsp;external&nbsp;directories&nbsp;using&nbsp;fopen&nbsp;wrappers.</span></span></div></li>
+<li><div class="src-line"><a name="a720"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a721"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a722"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_SECURITY_PARANOID&quot;&gt;GESHI_SECURITY_PARANOID&lt;/a&gt;</span>&nbsp;&amp;&amp;&nbsp;<span class="src-id">false</span>&nbsp;!==&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$path</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'..'</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a723"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Security&nbsp;Fix&nbsp;to&nbsp;prevent&nbsp;external&nbsp;directories&nbsp;using&nbsp;fopen&nbsp;wrappers.</span></span></div></li>
+<li><div class="src-line"><a name="a724"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a725"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a726"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$path</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a727"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_path</span>&nbsp;=&nbsp;<span class="src-sym">(</span><span class="src-str">'/'</span>&nbsp;==&nbsp;<span class="src-var">$path</span><span class="src-sym">[</span><a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$path</span><span class="src-sym">)</span>&nbsp;-&nbsp;<span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;?&nbsp;<span class="src-var">$path</span>&nbsp;:&nbsp;<span class="src-var">$path</span>&nbsp;.&nbsp;<span class="src-str">'/'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a728"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodset_language">set_language</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language</span><span class="src-sym">)</span><span class="src-sym">;</span>&nbsp;<span class="src-comm">//&nbsp;otherwise&nbsp;set_language_path&nbsp;has&nbsp;no&nbsp;effect</span></span></div></li>
+<li><div class="src-line"><a name="a729"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a730"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a731"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a732"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a733"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;type&nbsp;of&nbsp;header&nbsp;to&nbsp;be&nbsp;used.</span></div></li>
+<li><div class="src-line"><a name="a734"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a735"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;If&nbsp;GESHI_HEADER_DIV&nbsp;is&nbsp;used,&nbsp;the&nbsp;code&nbsp;is&nbsp;surrounded&nbsp;in&nbsp;a&nbsp;&quot;div&quot;.This</span></div></li>
+<li><div class="src-line"><a name="a736"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;means&nbsp;more&nbsp;source&nbsp;code&nbsp;but&nbsp;more&nbsp;control&nbsp;over&nbsp;tab&nbsp;width&nbsp;and&nbsp;line-wrapping.</span></div></li>
+<li><div class="src-line"><a name="a737"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;GESHI_HEADER_PRE&nbsp;means&nbsp;that&nbsp;a&nbsp;&quot;pre&quot;&nbsp;is&nbsp;used&nbsp;-&nbsp;less&nbsp;source,&nbsp;but&nbsp;less</span></div></li>
+<li><div class="src-line"><a name="a738"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;control.&nbsp;Default&nbsp;is&nbsp;GESHI_HEADER_PRE.</span></div></li>
+<li><div class="src-line"><a name="a739"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a740"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;From&nbsp;1.0.7.2,&nbsp;you&nbsp;can&nbsp;use&nbsp;GESHI_HEADER_NONE&nbsp;to&nbsp;specify&nbsp;that&nbsp;no&nbsp;header&nbsp;code</span></div></li>
+<li><div class="src-line"><a name="a741"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;should&nbsp;be&nbsp;outputted.</span></div></li>
+<li><div class="src-line"><a name="a742"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a743"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">The&nbsp;type&nbsp;of&nbsp;header&nbsp;to&nbsp;be&nbsp;used</span></div></li>
+<li><div class="src-line"><a name="a744"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a745"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a746"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_header_type">set_header_type</a><span class="src-sym">(</span><span class="src-var">$type</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a747"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Check&nbsp;if&nbsp;we&nbsp;got&nbsp;a&nbsp;valid&nbsp;header&nbsp;type</span></span></div></li>
+<li><div class="src-line"><a name="a748"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><a href="http://www.php.net/in_array">in_array</a><span class="src-sym">(</span><span class="src-var">$type</span><span class="src-sym">,</span>&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_NONE&quot;&gt;GESHI_HEADER_NONE&lt;/a&gt;</span><span class="src-sym">,</span>&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_DIV&quot;&gt;GESHI_HEADER_DIV&lt;/a&gt;</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a749"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE&quot;&gt;GESHI_HEADER_PRE&lt;/a&gt;</span><span class="src-sym">,</span>&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_VALID&quot;&gt;GESHI_HEADER_PRE_VALID&lt;/a&gt;</span><span class="src-sym">,</span>&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_TABLE&quot;&gt;GESHI_HEADER_PRE_TABLE&lt;/a&gt;</span><span class="src-sym">)))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a750"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">error</span>&nbsp;=&nbsp;<span class="src-id">GESHI_ERROR_INVALID_HEADER_TYPE</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a751"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a752"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a753"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a754"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Set&nbsp;that&nbsp;new&nbsp;header&nbsp;type</span></span></div></li>
+<li><div class="src-line"><a name="a755"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">header_type</span>&nbsp;=&nbsp;<span class="src-var">$type</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a756"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a757"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a758"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a759"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;styles&nbsp;for&nbsp;the&nbsp;code&nbsp;that&nbsp;will&nbsp;be&nbsp;outputted</span></div></li>
+<li><div class="src-line"><a name="a760"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;when&nbsp;this&nbsp;object&nbsp;is&nbsp;parsed.&nbsp;The&nbsp;style&nbsp;should&nbsp;be&nbsp;a</span></div></li>
+<li><div class="src-line"><a name="a761"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;string&nbsp;of&nbsp;valid&nbsp;stylesheet&nbsp;declarations</span></div></li>
+<li><div class="src-line"><a name="a762"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a763"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">&nbsp;The&nbsp;overall&nbsp;style&nbsp;for&nbsp;the&nbsp;outputted&nbsp;code&nbsp;block</span></div></li>
+<li><div class="src-line"><a name="a764"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;merge&nbsp;the&nbsp;styles&nbsp;with&nbsp;the&nbsp;current&nbsp;styles&nbsp;or&nbsp;not</span></div></li>
+<li><div class="src-line"><a name="a765"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a766"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a767"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_overall_style">set_overall_style</a><span class="src-sym">(</span><span class="src-var">$style</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$preserve_defaults</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a768"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$preserve_defaults</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a769"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">overall_style</span>&nbsp;=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a770"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a771"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">overall_style</span>&nbsp;.=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a772"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a773"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a774"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a775"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a776"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;overall&nbsp;classname&nbsp;for&nbsp;this&nbsp;block&nbsp;of&nbsp;code.&nbsp;This</span></div></li>
+<li><div class="src-line"><a name="a777"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;class&nbsp;can&nbsp;then&nbsp;be&nbsp;used&nbsp;in&nbsp;a&nbsp;stylesheet&nbsp;to&nbsp;style&nbsp;this&nbsp;object's</span></div></li>
+<li><div class="src-line"><a name="a778"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;output</span></div></li>
+<li><div class="src-line"><a name="a779"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a780"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;class&nbsp;name&nbsp;to&nbsp;use&nbsp;for&nbsp;this&nbsp;block&nbsp;of&nbsp;code</span></div></li>
+<li><div class="src-line"><a name="a781"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a782"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a783"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_overall_class">set_overall_class</a><span class="src-sym">(</span><span class="src-var">$class</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a784"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">overall_class</span>&nbsp;=&nbsp;<span class="src-var">$class</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a785"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a786"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a787"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a788"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;overall&nbsp;id&nbsp;for&nbsp;this&nbsp;block&nbsp;of&nbsp;code.&nbsp;This&nbsp;id&nbsp;can&nbsp;then</span></div></li>
+<li><div class="src-line"><a name="a789"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;be&nbsp;used&nbsp;in&nbsp;a&nbsp;stylesheet&nbsp;to&nbsp;style&nbsp;this&nbsp;object's&nbsp;output</span></div></li>
+<li><div class="src-line"><a name="a790"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a791"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;ID&nbsp;to&nbsp;use&nbsp;for&nbsp;this&nbsp;block&nbsp;of&nbsp;code</span></div></li>
+<li><div class="src-line"><a name="a792"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a793"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a794"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_overall_id">set_overall_id</a><span class="src-sym">(</span><span class="src-var">$id</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a795"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">overall_id</span>&nbsp;=&nbsp;<span class="src-var">$id</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a796"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a797"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a798"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a799"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;whether&nbsp;CSS&nbsp;classes&nbsp;should&nbsp;be&nbsp;used&nbsp;to&nbsp;highlight&nbsp;the&nbsp;source.&nbsp;Default</span></div></li>
+<li><div class="src-line"><a name="a800"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;is&nbsp;off,&nbsp;calling&nbsp;this&nbsp;method&nbsp;with&nbsp;no&nbsp;arguments&nbsp;will&nbsp;turn&nbsp;it&nbsp;on</span></div></li>
+<li><div class="src-line"><a name="a801"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a802"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;turn&nbsp;classes&nbsp;on&nbsp;or&nbsp;not</span></div></li>
+<li><div class="src-line"><a name="a803"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a804"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a805"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodenable_classes">enable_classes</a><span class="src-sym">(</span><span class="src-var">$flag</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a806"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">use_classes</span>&nbsp;=&nbsp;<span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;?&nbsp;<span class="src-id">true</span>&nbsp;:&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a807"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a808"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a809"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a810"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;style&nbsp;for&nbsp;the&nbsp;actual&nbsp;code.&nbsp;This&nbsp;should&nbsp;be&nbsp;a&nbsp;string</span></div></li>
+<li><div class="src-line"><a name="a811"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;containing&nbsp;valid&nbsp;stylesheet&nbsp;declarations.&nbsp;If&nbsp;$preserve_defaults&nbsp;is</span></div></li>
+<li><div class="src-line"><a name="a812"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;true,&nbsp;then&nbsp;styles&nbsp;are&nbsp;merged&nbsp;with&nbsp;the&nbsp;default&nbsp;styles,&nbsp;with&nbsp;the</span></div></li>
+<li><div class="src-line"><a name="a813"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;user&nbsp;defined&nbsp;styles&nbsp;having&nbsp;priority</span></div></li>
+<li><div class="src-line"><a name="a814"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a815"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Note:&nbsp;Use&nbsp;this&nbsp;method&nbsp;to&nbsp;override&nbsp;any&nbsp;style&nbsp;changes&nbsp;you&nbsp;made&nbsp;to</span></div></li>
+<li><div class="src-line"><a name="a816"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;the&nbsp;line&nbsp;numbers&nbsp;if&nbsp;you&nbsp;are&nbsp;using&nbsp;line&nbsp;numbers,&nbsp;else&nbsp;the&nbsp;line&nbsp;of</span></div></li>
+<li><div class="src-line"><a name="a817"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;code&nbsp;will&nbsp;have&nbsp;the&nbsp;same&nbsp;style&nbsp;as&nbsp;the&nbsp;line&nbsp;number!&nbsp;Consult&nbsp;the</span></div></li>
+<li><div class="src-line"><a name="a818"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;GeSHi&nbsp;documentation&nbsp;for&nbsp;more&nbsp;information&nbsp;about&nbsp;this.</span></div></li>
+<li><div class="src-line"><a name="a819"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a820"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">&nbsp;The&nbsp;style&nbsp;to&nbsp;use&nbsp;for&nbsp;actual&nbsp;code</span></div></li>
+<li><div class="src-line"><a name="a821"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;merge&nbsp;the&nbsp;current&nbsp;styles&nbsp;with&nbsp;the&nbsp;new&nbsp;styles</span></div></li>
+<li><div class="src-line"><a name="a822"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.2</span></div></li>
+<li><div class="src-line"><a name="a823"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a824"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_code_style">set_code_style</a><span class="src-sym">(</span><span class="src-var">$style</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$preserve_defaults</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a825"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$preserve_defaults</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a826"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">code_style</span>&nbsp;=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a827"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a828"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">code_style</span>&nbsp;.=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a829"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a830"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a831"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a832"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a833"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;styles&nbsp;for&nbsp;the&nbsp;line&nbsp;numbers.</span></div></li>
+<li><div class="src-line"><a name="a834"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a835"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;style&nbsp;for&nbsp;the&nbsp;line&nbsp;numbers&nbsp;that&nbsp;are&nbsp;&quot;normal&quot;</span></div></li>
+<li><div class="src-line"><a name="a836"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string</span><span class="src-doc">|</span><span class="src-doc-type">boolean</span><span class="src-doc">If&nbsp;a&nbsp;string,&nbsp;this&nbsp;is&nbsp;the&nbsp;style&nbsp;of&nbsp;the&nbsp;line</span></div></li>
+<li><div class="src-line"><a name="a837"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;numbers&nbsp;that&nbsp;are&nbsp;&quot;fancy&quot;,&nbsp;otherwise&nbsp;if&nbsp;boolean&nbsp;then&nbsp;this</span></div></li>
+<li><div class="src-line"><a name="a838"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defines&nbsp;whether&nbsp;the&nbsp;normal&nbsp;styles&nbsp;should&nbsp;be&nbsp;merged&nbsp;with&nbsp;the</span></div></li>
+<li><div class="src-line"><a name="a839"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;normal&nbsp;styles&nbsp;or&nbsp;not</span></div></li>
+<li><div class="src-line"><a name="a840"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">If&nbsp;set,&nbsp;is&nbsp;the&nbsp;flag&nbsp;for&nbsp;whether&nbsp;to&nbsp;merge&nbsp;the&nbsp;&quot;fancy&quot;</span></div></li>
+<li><div class="src-line"><a name="a841"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;styles&nbsp;with&nbsp;the&nbsp;current&nbsp;styles&nbsp;or&nbsp;not</span></div></li>
+<li><div class="src-line"><a name="a842"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.2</span></div></li>
+<li><div class="src-line"><a name="a843"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a844"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_line_style">set_line_style</a><span class="src-sym">(</span><span class="src-var">$style1</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$style2</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$preserve_defaults</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a845"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Check&nbsp;if&nbsp;we&nbsp;got&nbsp;2&nbsp;or&nbsp;three&nbsp;parameters</span></span></div></li>
+<li><div class="src-line"><a name="a846"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/is_bool">is_bool</a><span class="src-sym">(</span><span class="src-var">$style2</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a847"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$preserve_defaults</span>&nbsp;=&nbsp;<span class="src-var">$style2</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a848"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$style2</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a849"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a850"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a851"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Actually&nbsp;set&nbsp;the&nbsp;new&nbsp;styles</span></span></div></li>
+<li><div class="src-line"><a name="a852"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$preserve_defaults</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a853"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">line_style1</span>&nbsp;=&nbsp;<span class="src-var">$style1</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a854"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">line_style2</span>&nbsp;=&nbsp;<span class="src-var">$style2</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a855"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a856"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">line_style1</span>&nbsp;.=&nbsp;<span class="src-var">$style1</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a857"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">line_style2</span>&nbsp;.=&nbsp;<span class="src-var">$style2</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a858"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a859"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a860"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a861"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a862"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;whether&nbsp;line&nbsp;numbers&nbsp;should&nbsp;be&nbsp;displayed.</span></div></li>
+<li><div class="src-line"><a name="a863"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a864"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Valid&nbsp;values&nbsp;for&nbsp;the&nbsp;first&nbsp;parameter&nbsp;are:</span></div></li>
+<li><div class="src-line"><a name="a865"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a866"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;-&nbsp;GESHI_NO_LINE_NUMBERS:&nbsp;Line&nbsp;numbers&nbsp;will&nbsp;not&nbsp;be&nbsp;displayed</span></div></li>
+<li><div class="src-line"><a name="a867"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;-&nbsp;GESHI_NORMAL_LINE_NUMBERS:&nbsp;Line&nbsp;numbers&nbsp;will&nbsp;be&nbsp;displayed</span></div></li>
+<li><div class="src-line"><a name="a868"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;-&nbsp;GESHI_FANCY_LINE_NUMBERS:&nbsp;Fancy&nbsp;line&nbsp;numbers&nbsp;will&nbsp;be&nbsp;displayed</span></div></li>
+<li><div class="src-line"><a name="a869"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a870"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;For&nbsp;fancy&nbsp;line&nbsp;numbers,&nbsp;the&nbsp;second&nbsp;parameter&nbsp;is&nbsp;used&nbsp;to&nbsp;signal&nbsp;which&nbsp;lines</span></div></li>
+<li><div class="src-line"><a name="a871"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;are&nbsp;to&nbsp;be&nbsp;fancy.&nbsp;For&nbsp;example,&nbsp;if&nbsp;the&nbsp;value&nbsp;of&nbsp;this&nbsp;parameter&nbsp;is&nbsp;5&nbsp;then&nbsp;every</span></div></li>
+<li><div class="src-line"><a name="a872"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;5th&nbsp;line&nbsp;will&nbsp;be&nbsp;fancy.</span></div></li>
+<li><div class="src-line"><a name="a873"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a874"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">How&nbsp;line&nbsp;numbers&nbsp;should&nbsp;be&nbsp;displayed</span></div></li>
+<li><div class="src-line"><a name="a875"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">Defines&nbsp;which&nbsp;lines&nbsp;are&nbsp;fancy</span></div></li>
+<li><div class="src-line"><a name="a876"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a877"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a878"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodenable_line_numbers">enable_line_numbers</a><span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$nth_row</span>&nbsp;=&nbsp;<span class="src-num">5</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a879"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_NO_LINE_NUMBERS&quot;&gt;GESHI_NO_LINE_NUMBERS&lt;/a&gt;</span>&nbsp;!=&nbsp;<span class="src-var">$flag</span>&nbsp;&amp;&amp;&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_NORMAL_LINE_NUMBERS&quot;&gt;GESHI_NORMAL_LINE_NUMBERS&lt;/a&gt;</span>&nbsp;!=&nbsp;<span class="src-var">$flag</span></span></div></li>
+<li><div class="src-line"><a name="a880"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp;&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_FANCY_LINE_NUMBERS&quot;&gt;GESHI_FANCY_LINE_NUMBERS&lt;/a&gt;</span>&nbsp;!=&nbsp;<span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a881"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">error</span>&nbsp;=&nbsp;<span class="src-id">GESHI_ERROR_INVALID_LINE_NUMBER_TYPE</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a882"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a883"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">line_numbers</span>&nbsp;=&nbsp;<span class="src-var">$flag</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a884"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">line_nth_row</span>&nbsp;=&nbsp;<span class="src-var">$nth_row</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a885"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a886"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a887"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a888"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;wether&nbsp;spans&nbsp;and&nbsp;other&nbsp;HTML&nbsp;markup&nbsp;generated&nbsp;by&nbsp;GeSHi&nbsp;can</span></div></li>
+<li><div class="src-line"><a name="a889"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;span&nbsp;over&nbsp;multiple&nbsp;lines&nbsp;or&nbsp;not.&nbsp;Defaults&nbsp;to&nbsp;true&nbsp;to&nbsp;reduce&nbsp;overhead.</span></div></li>
+<li><div class="src-line"><a name="a890"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Set&nbsp;it&nbsp;to&nbsp;false&nbsp;if&nbsp;you&nbsp;want&nbsp;to&nbsp;manipulate&nbsp;the&nbsp;output&nbsp;or&nbsp;manually&nbsp;display</span></div></li>
+<li><div class="src-line"><a name="a891"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;the&nbsp;code&nbsp;in&nbsp;an&nbsp;ordered&nbsp;list.</span></div></li>
+<li><div class="src-line"><a name="a892"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a893"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Wether&nbsp;multiline&nbsp;spans&nbsp;are&nbsp;allowed&nbsp;or&nbsp;not</span></div></li>
+<li><div class="src-line"><a name="a894"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.7.22</span></div></li>
+<li><div class="src-line"><a name="a895"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a896"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodenable_multiline_span">enable_multiline_span</a><span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a897"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">allow_multiline_span</span>&nbsp;=&nbsp;(bool)&nbsp;<span class="src-var">$flag</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a898"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a899"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a900"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a901"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Get&nbsp;current&nbsp;setting&nbsp;for&nbsp;multiline&nbsp;spans,&nbsp;see&nbsp;GeSHi-&gt;enable_multiline_span().</span></div></li>
+<li><div class="src-line"><a name="a902"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a903"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@see</span><span class="src-doc">&nbsp;enable_multiline_span</span></div></li>
+<li><div class="src-line"><a name="a904"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@return&nbsp;</span><span class="src-doc-type">bool&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a905"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a906"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodget_multiline_span">get_multiline_span</a><span class="src-sym">(</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a907"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">allow_multiline_span</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a908"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a909"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a910"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a911"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;style&nbsp;for&nbsp;a&nbsp;keyword&nbsp;group.&nbsp;If&nbsp;$preserve_defaults&nbsp;is</span></div></li>
+<li><div class="src-line"><a name="a912"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;true,&nbsp;then&nbsp;styles&nbsp;are&nbsp;merged&nbsp;with&nbsp;the&nbsp;default&nbsp;styles,&nbsp;with&nbsp;the</span></div></li>
+<li><div class="src-line"><a name="a913"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;user&nbsp;defined&nbsp;styles&nbsp;having&nbsp;priority</span></div></li>
+<li><div class="src-line"><a name="a914"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a915"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;The&nbsp;key&nbsp;of&nbsp;the&nbsp;keyword&nbsp;group&nbsp;to&nbsp;change&nbsp;the&nbsp;styles&nbsp;of</span></div></li>
+<li><div class="src-line"><a name="a916"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">&nbsp;The&nbsp;style&nbsp;to&nbsp;make&nbsp;the&nbsp;keywords</span></div></li>
+<li><div class="src-line"><a name="a917"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;merge&nbsp;the&nbsp;new&nbsp;styles&nbsp;with&nbsp;the&nbsp;old&nbsp;or&nbsp;just</span></div></li>
+<li><div class="src-line"><a name="a918"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;overwrite&nbsp;them</span></div></li>
+<li><div class="src-line"><a name="a919"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a920"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a921"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_keyword_group_style">set_keyword_group_style</a><span class="src-sym">(</span><span class="src-var">$key</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$style</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$preserve_defaults</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a922"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Set&nbsp;the&nbsp;style&nbsp;for&nbsp;this&nbsp;keyword&nbsp;group</span></span></div></li>
+<li><div class="src-line"><a name="a923"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$preserve_defaults</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a924"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a925"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a926"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;.=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a927"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a928"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a929"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Update&nbsp;the&nbsp;lexic&nbsp;permissions</span></span></div></li>
+<li><div class="src-line"><a name="a930"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a931"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a932"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a933"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a934"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a935"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a936"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Turns&nbsp;highlighting&nbsp;on/off&nbsp;for&nbsp;a&nbsp;keyword&nbsp;group</span></div></li>
+<li><div class="src-line"><a name="a937"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a938"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;The&nbsp;key&nbsp;of&nbsp;the&nbsp;keyword&nbsp;group&nbsp;to&nbsp;turn&nbsp;on&nbsp;or&nbsp;off</span></div></li>
+<li><div class="src-line"><a name="a939"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;turn&nbsp;highlighting&nbsp;for&nbsp;that&nbsp;group&nbsp;on&nbsp;or&nbsp;off</span></div></li>
+<li><div class="src-line"><a name="a940"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a941"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a942"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_keyword_group_highlighting">set_keyword_group_highlighting</a><span class="src-sym">(</span><span class="src-var">$key</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$flag</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a943"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;?&nbsp;<span class="src-id">true</span>&nbsp;:&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a944"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a945"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a946"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a947"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;styles&nbsp;for&nbsp;comment&nbsp;groups.&nbsp;&nbsp;If&nbsp;$preserve_defaults&nbsp;is</span></div></li>
+<li><div class="src-line"><a name="a948"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;true,&nbsp;then&nbsp;styles&nbsp;are&nbsp;merged&nbsp;with&nbsp;the&nbsp;default&nbsp;styles,&nbsp;with&nbsp;the</span></div></li>
+<li><div class="src-line"><a name="a949"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;user&nbsp;defined&nbsp;styles&nbsp;having&nbsp;priority</span></div></li>
+<li><div class="src-line"><a name="a950"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a951"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;The&nbsp;key&nbsp;of&nbsp;the&nbsp;comment&nbsp;group&nbsp;to&nbsp;change&nbsp;the&nbsp;styles&nbsp;of</span></div></li>
+<li><div class="src-line"><a name="a952"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">&nbsp;The&nbsp;style&nbsp;to&nbsp;make&nbsp;the&nbsp;comments</span></div></li>
+<li><div class="src-line"><a name="a953"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;merge&nbsp;the&nbsp;new&nbsp;styles&nbsp;with&nbsp;the&nbsp;old&nbsp;or&nbsp;just</span></div></li>
+<li><div class="src-line"><a name="a954"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;overwrite&nbsp;them</span></div></li>
+<li><div class="src-line"><a name="a955"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a956"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a957"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_comments_style">set_comments_style</a><span class="src-sym">(</span><span class="src-var">$key</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$style</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$preserve_defaults</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a958"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$preserve_defaults</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a959"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a960"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a961"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;.=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a962"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a963"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a964"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a965"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a966"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Turns&nbsp;highlighting&nbsp;on/off&nbsp;for&nbsp;comment&nbsp;groups</span></div></li>
+<li><div class="src-line"><a name="a967"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a968"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;The&nbsp;key&nbsp;of&nbsp;the&nbsp;comment&nbsp;group&nbsp;to&nbsp;turn&nbsp;on&nbsp;or&nbsp;off</span></div></li>
+<li><div class="src-line"><a name="a969"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;turn&nbsp;highlighting&nbsp;for&nbsp;that&nbsp;group&nbsp;on&nbsp;or&nbsp;off</span></div></li>
+<li><div class="src-line"><a name="a970"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a971"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a972"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_comments_highlighting">set_comments_highlighting</a><span class="src-sym">(</span><span class="src-var">$key</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$flag</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a973"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;?&nbsp;<span class="src-id">true</span>&nbsp;:&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a974"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a975"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a976"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a977"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;styles&nbsp;for&nbsp;escaped&nbsp;characters.&nbsp;If&nbsp;$preserve_defaults&nbsp;is</span></div></li>
+<li><div class="src-line"><a name="a978"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;true,&nbsp;then&nbsp;styles&nbsp;are&nbsp;merged&nbsp;with&nbsp;the&nbsp;default&nbsp;styles,&nbsp;with&nbsp;the</span></div></li>
+<li><div class="src-line"><a name="a979"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;user&nbsp;defined&nbsp;styles&nbsp;having&nbsp;priority</span></div></li>
+<li><div class="src-line"><a name="a980"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a981"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">&nbsp;The&nbsp;style&nbsp;to&nbsp;make&nbsp;the&nbsp;escape&nbsp;characters</span></div></li>
+<li><div class="src-line"><a name="a982"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;merge&nbsp;the&nbsp;new&nbsp;styles&nbsp;with&nbsp;the&nbsp;old&nbsp;or&nbsp;just</span></div></li>
+<li><div class="src-line"><a name="a983"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;overwrite&nbsp;them</span></div></li>
+<li><div class="src-line"><a name="a984"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a985"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a986"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_escape_characters_style">set_escape_characters_style</a><span class="src-sym">(</span><span class="src-var">$style</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$preserve_defaults</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a987"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$preserve_defaults</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a988"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a989"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a990"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;.=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a991"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a992"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a993"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a994"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a995"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Turns&nbsp;highlighting&nbsp;on/off&nbsp;for&nbsp;escaped&nbsp;characters</span></div></li>
+<li><div class="src-line"><a name="a996"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a997"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;turn&nbsp;highlighting&nbsp;for&nbsp;escape&nbsp;characters&nbsp;on&nbsp;or&nbsp;off</span></div></li>
+<li><div class="src-line"><a name="a998"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a999"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1000"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_escape_characters_highlighting">set_escape_characters_highlighting</a><span class="src-sym">(</span><span class="src-var">$flag</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1001"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;?&nbsp;<span class="src-id">true</span>&nbsp;:&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1002"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1003"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1004"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1005"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;styles&nbsp;for&nbsp;brackets.&nbsp;If&nbsp;$preserve_defaults&nbsp;is</span></div></li>
+<li><div class="src-line"><a name="a1006"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;true,&nbsp;then&nbsp;styles&nbsp;are&nbsp;merged&nbsp;with&nbsp;the&nbsp;default&nbsp;styles,&nbsp;with&nbsp;the</span></div></li>
+<li><div class="src-line"><a name="a1007"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;user&nbsp;defined&nbsp;styles&nbsp;having&nbsp;priority</span></div></li>
+<li><div class="src-line"><a name="a1008"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1009"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;This&nbsp;method&nbsp;is&nbsp;DEPRECATED:&nbsp;use&nbsp;set_symbols_style&nbsp;instead.</span></div></li>
+<li><div class="src-line"><a name="a1010"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;This&nbsp;method&nbsp;will&nbsp;be&nbsp;removed&nbsp;in&nbsp;1.2.X</span></div></li>
+<li><div class="src-line"><a name="a1011"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1012"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">&nbsp;The&nbsp;style&nbsp;to&nbsp;make&nbsp;the&nbsp;brackets</span></div></li>
+<li><div class="src-line"><a name="a1013"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;merge&nbsp;the&nbsp;new&nbsp;styles&nbsp;with&nbsp;the&nbsp;old&nbsp;or&nbsp;just</span></div></li>
+<li><div class="src-line"><a name="a1014"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;overwrite&nbsp;them</span></div></li>
+<li><div class="src-line"><a name="a1015"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1016"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@deprecated</span><span class="src-doc">&nbsp;In&nbsp;favour&nbsp;of&nbsp;set_symbols_style</span></div></li>
+<li><div class="src-line"><a name="a1017"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1018"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_brackets_style">set_brackets_style</a><span class="src-sym">(</span><span class="src-var">$style</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$preserve_defaults</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1019"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$preserve_defaults</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1020"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'BRACKETS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1021"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1022"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'BRACKETS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;.=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1023"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1024"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1025"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1026"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1027"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Turns&nbsp;highlighting&nbsp;on/off&nbsp;for&nbsp;brackets</span></div></li>
+<li><div class="src-line"><a name="a1028"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1029"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;This&nbsp;method&nbsp;is&nbsp;DEPRECATED:&nbsp;use&nbsp;set_symbols_highlighting&nbsp;instead.</span></div></li>
+<li><div class="src-line"><a name="a1030"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;This&nbsp;method&nbsp;will&nbsp;be&nbsp;remove&nbsp;in&nbsp;1.2.X</span></div></li>
+<li><div class="src-line"><a name="a1031"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1032"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;turn&nbsp;highlighting&nbsp;for&nbsp;brackets&nbsp;on&nbsp;or&nbsp;off</span></div></li>
+<li><div class="src-line"><a name="a1033"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1034"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@deprecated</span><span class="src-doc">&nbsp;In&nbsp;favour&nbsp;of&nbsp;set_symbols_highlighting</span></div></li>
+<li><div class="src-line"><a name="a1035"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1036"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_brackets_highlighting">set_brackets_highlighting</a><span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1037"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'BRACKETS'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;?&nbsp;<span class="src-id">true</span>&nbsp;:&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1038"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1039"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1040"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1041"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;styles&nbsp;for&nbsp;symbols.&nbsp;If&nbsp;$preserve_defaults&nbsp;is</span></div></li>
+<li><div class="src-line"><a name="a1042"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;true,&nbsp;then&nbsp;styles&nbsp;are&nbsp;merged&nbsp;with&nbsp;the&nbsp;default&nbsp;styles,&nbsp;with&nbsp;the</span></div></li>
+<li><div class="src-line"><a name="a1043"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;user&nbsp;defined&nbsp;styles&nbsp;having&nbsp;priority</span></div></li>
+<li><div class="src-line"><a name="a1044"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1045"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">&nbsp;The&nbsp;style&nbsp;to&nbsp;make&nbsp;the&nbsp;symbols</span></div></li>
+<li><div class="src-line"><a name="a1046"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;merge&nbsp;the&nbsp;new&nbsp;styles&nbsp;with&nbsp;the&nbsp;old&nbsp;or&nbsp;just</span></div></li>
+<li><div class="src-line"><a name="a1047"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;overwrite&nbsp;them</span></div></li>
+<li><div class="src-line"><a name="a1048"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;Tells&nbsp;the&nbsp;group&nbsp;of&nbsp;symbols&nbsp;for&nbsp;which&nbsp;style&nbsp;should&nbsp;be&nbsp;set.</span></div></li>
+<li><div class="src-line"><a name="a1049"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.1</span></div></li>
+<li><div class="src-line"><a name="a1050"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1051"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_symbols_style">set_symbols_style</a><span class="src-sym">(</span><span class="src-var">$style</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$preserve_defaults</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$group</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1052"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Update&nbsp;the&nbsp;style&nbsp;of&nbsp;symbols</span></span></div></li>
+<li><div class="src-line"><a name="a1053"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$preserve_defaults</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1054"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'SYMBOLS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$group</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1055"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1056"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'SYMBOLS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$group</span><span class="src-sym">]</span>&nbsp;.=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1057"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1058"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1059"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;For&nbsp;backward&nbsp;compatibility</span></span></div></li>
+<li><div class="src-line"><a name="a1060"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-num">0</span>&nbsp;==&nbsp;<span class="src-var">$group</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1061"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodset_brackets_style">set_brackets_style</a>&nbsp;<span class="src-sym">(</span><span class="src-var">$style</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$preserve_defaults</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1062"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1063"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1064"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1065"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1066"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Turns&nbsp;highlighting&nbsp;on/off&nbsp;for&nbsp;symbols</span></div></li>
+<li><div class="src-line"><a name="a1067"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1068"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;turn&nbsp;highlighting&nbsp;for&nbsp;symbols&nbsp;on&nbsp;or&nbsp;off</span></div></li>
+<li><div class="src-line"><a name="a1069"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1070"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1071"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_symbols_highlighting">set_symbols_highlighting</a><span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1072"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Update&nbsp;lexic&nbsp;permissions&nbsp;for&nbsp;this&nbsp;symbol&nbsp;group</span></span></div></li>
+<li><div class="src-line"><a name="a1073"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'SYMBOLS'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;?&nbsp;<span class="src-id">true</span>&nbsp;:&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1074"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1075"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;For&nbsp;backward&nbsp;compatibility</span></span></div></li>
+<li><div class="src-line"><a name="a1076"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodset_brackets_highlighting">set_brackets_highlighting</a>&nbsp;<span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1077"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1078"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1079"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1080"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;styles&nbsp;for&nbsp;strings.&nbsp;If&nbsp;$preserve_defaults&nbsp;is</span></div></li>
+<li><div class="src-line"><a name="a1081"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;true,&nbsp;then&nbsp;styles&nbsp;are&nbsp;merged&nbsp;with&nbsp;the&nbsp;default&nbsp;styles,&nbsp;with&nbsp;the</span></div></li>
+<li><div class="src-line"><a name="a1082"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;user&nbsp;defined&nbsp;styles&nbsp;having&nbsp;priority</span></div></li>
+<li><div class="src-line"><a name="a1083"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1084"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">&nbsp;The&nbsp;style&nbsp;to&nbsp;make&nbsp;the&nbsp;escape&nbsp;characters</span></div></li>
+<li><div class="src-line"><a name="a1085"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;merge&nbsp;the&nbsp;new&nbsp;styles&nbsp;with&nbsp;the&nbsp;old&nbsp;or&nbsp;just</span></div></li>
+<li><div class="src-line"><a name="a1086"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;overwrite&nbsp;them</span></div></li>
+<li><div class="src-line"><a name="a1087"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1088"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1089"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_strings_style">set_strings_style</a><span class="src-sym">(</span><span class="src-var">$style</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$preserve_defaults</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1090"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$preserve_defaults</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1091"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'STRINGS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1092"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1093"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'STRINGS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;.=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1094"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1095"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1096"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1097"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1098"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Turns&nbsp;highlighting&nbsp;on/off&nbsp;for&nbsp;strings</span></div></li>
+<li><div class="src-line"><a name="a1099"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1100"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;turn&nbsp;highlighting&nbsp;for&nbsp;strings&nbsp;on&nbsp;or&nbsp;off</span></div></li>
+<li><div class="src-line"><a name="a1101"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1102"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1103"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_strings_highlighting">set_strings_highlighting</a><span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1104"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'STRINGS'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;?&nbsp;<span class="src-id">true</span>&nbsp;:&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1105"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1106"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1107"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1108"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;styles&nbsp;for&nbsp;numbers.&nbsp;If&nbsp;$preserve_defaults&nbsp;is</span></div></li>
+<li><div class="src-line"><a name="a1109"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;true,&nbsp;then&nbsp;styles&nbsp;are&nbsp;merged&nbsp;with&nbsp;the&nbsp;default&nbsp;styles,&nbsp;with&nbsp;the</span></div></li>
+<li><div class="src-line"><a name="a1110"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;user&nbsp;defined&nbsp;styles&nbsp;having&nbsp;priority</span></div></li>
+<li><div class="src-line"><a name="a1111"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1112"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">&nbsp;The&nbsp;style&nbsp;to&nbsp;make&nbsp;the&nbsp;numbers</span></div></li>
+<li><div class="src-line"><a name="a1113"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;merge&nbsp;the&nbsp;new&nbsp;styles&nbsp;with&nbsp;the&nbsp;old&nbsp;or&nbsp;just</span></div></li>
+<li><div class="src-line"><a name="a1114"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;overwrite&nbsp;them</span></div></li>
+<li><div class="src-line"><a name="a1115"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1116"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1117"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_numbers_style">set_numbers_style</a><span class="src-sym">(</span><span class="src-var">$style</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$preserve_defaults</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1118"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$preserve_defaults</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1119"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1120"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1121"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;.=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1122"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1123"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1124"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1125"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1126"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Turns&nbsp;highlighting&nbsp;on/off&nbsp;for&nbsp;numbers</span></div></li>
+<li><div class="src-line"><a name="a1127"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1128"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;turn&nbsp;highlighting&nbsp;for&nbsp;numbers&nbsp;on&nbsp;or&nbsp;off</span></div></li>
+<li><div class="src-line"><a name="a1129"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1130"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1131"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_numbers_highlighting">set_numbers_highlighting</a><span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1132"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;?&nbsp;<span class="src-id">true</span>&nbsp;:&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1133"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1134"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1135"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1136"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;styles&nbsp;for&nbsp;methods.&nbsp;$key&nbsp;is&nbsp;a&nbsp;number&nbsp;that&nbsp;references&nbsp;the</span></div></li>
+<li><div class="src-line"><a name="a1137"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;appropriate&nbsp;&quot;object&nbsp;splitter&quot;&nbsp;-&nbsp;see&nbsp;the&nbsp;language&nbsp;file&nbsp;for&nbsp;the&nbsp;language</span></div></li>
+<li><div class="src-line"><a name="a1138"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;you&nbsp;are&nbsp;highlighting&nbsp;to&nbsp;get&nbsp;this&nbsp;number.&nbsp;If&nbsp;$preserve_defaults&nbsp;is</span></div></li>
+<li><div class="src-line"><a name="a1139"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;true,&nbsp;then&nbsp;styles&nbsp;are&nbsp;merged&nbsp;with&nbsp;the&nbsp;default&nbsp;styles,&nbsp;with&nbsp;the</span></div></li>
+<li><div class="src-line"><a name="a1140"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;user&nbsp;defined&nbsp;styles&nbsp;having&nbsp;priority</span></div></li>
+<li><div class="src-line"><a name="a1141"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1142"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;The&nbsp;key&nbsp;of&nbsp;the&nbsp;object&nbsp;splitter&nbsp;to&nbsp;change&nbsp;the&nbsp;styles&nbsp;of</span></div></li>
+<li><div class="src-line"><a name="a1143"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">&nbsp;The&nbsp;style&nbsp;to&nbsp;make&nbsp;the&nbsp;methods</span></div></li>
+<li><div class="src-line"><a name="a1144"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;merge&nbsp;the&nbsp;new&nbsp;styles&nbsp;with&nbsp;the&nbsp;old&nbsp;or&nbsp;just</span></div></li>
+<li><div class="src-line"><a name="a1145"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;overwrite&nbsp;them</span></div></li>
+<li><div class="src-line"><a name="a1146"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1147"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1148"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_methods_style">set_methods_style</a><span class="src-sym">(</span><span class="src-var">$key</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$style</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$preserve_defaults</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1149"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$preserve_defaults</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1150"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'METHODS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1151"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1152"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'METHODS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;.=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1153"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1154"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1155"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1156"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1157"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Turns&nbsp;highlighting&nbsp;on/off&nbsp;for&nbsp;methods</span></div></li>
+<li><div class="src-line"><a name="a1158"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1159"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;turn&nbsp;highlighting&nbsp;for&nbsp;methods&nbsp;on&nbsp;or&nbsp;off</span></div></li>
+<li><div class="src-line"><a name="a1160"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1161"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1162"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_methods_highlighting">set_methods_highlighting</a><span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1163"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'METHODS'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;?&nbsp;<span class="src-id">true</span>&nbsp;:&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1164"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1165"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1166"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1167"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;styles&nbsp;for&nbsp;regexps.&nbsp;If&nbsp;$preserve_defaults&nbsp;is</span></div></li>
+<li><div class="src-line"><a name="a1168"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;true,&nbsp;then&nbsp;styles&nbsp;are&nbsp;merged&nbsp;with&nbsp;the&nbsp;default&nbsp;styles,&nbsp;with&nbsp;the</span></div></li>
+<li><div class="src-line"><a name="a1169"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;user&nbsp;defined&nbsp;styles&nbsp;having&nbsp;priority</span></div></li>
+<li><div class="src-line"><a name="a1170"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1171"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">&nbsp;The&nbsp;style&nbsp;to&nbsp;make&nbsp;the&nbsp;regular&nbsp;expression&nbsp;matches</span></div></li>
+<li><div class="src-line"><a name="a1172"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;merge&nbsp;the&nbsp;new&nbsp;styles&nbsp;with&nbsp;the&nbsp;old&nbsp;or&nbsp;just</span></div></li>
+<li><div class="src-line"><a name="a1173"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;overwrite&nbsp;them</span></div></li>
+<li><div class="src-line"><a name="a1174"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1175"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1176"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_regexps_style">set_regexps_style</a><span class="src-sym">(</span><span class="src-var">$key</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$style</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$preserve_defaults</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1177"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$preserve_defaults</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1178"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1179"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1180"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;.=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1181"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1182"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1183"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1184"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1185"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Turns&nbsp;highlighting&nbsp;on/off&nbsp;for&nbsp;regexps</span></div></li>
+<li><div class="src-line"><a name="a1186"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1187"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;The&nbsp;key&nbsp;of&nbsp;the&nbsp;regular&nbsp;expression&nbsp;group&nbsp;to&nbsp;turn&nbsp;on&nbsp;or&nbsp;off</span></div></li>
+<li><div class="src-line"><a name="a1188"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;turn&nbsp;highlighting&nbsp;for&nbsp;the&nbsp;regular&nbsp;expression&nbsp;group&nbsp;on&nbsp;or&nbsp;off</span></div></li>
+<li><div class="src-line"><a name="a1189"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1190"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1191"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_regexps_highlighting">set_regexps_highlighting</a><span class="src-sym">(</span><span class="src-var">$key</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1192"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;?&nbsp;<span class="src-id">true</span>&nbsp;:&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1193"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1194"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1195"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1196"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;whether&nbsp;a&nbsp;set&nbsp;of&nbsp;keywords&nbsp;are&nbsp;checked&nbsp;for&nbsp;in&nbsp;a&nbsp;case&nbsp;sensitive&nbsp;manner</span></div></li>
+<li><div class="src-line"><a name="a1197"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1198"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">The&nbsp;key&nbsp;of&nbsp;the&nbsp;keyword&nbsp;group&nbsp;to&nbsp;change&nbsp;the&nbsp;case&nbsp;sensitivity&nbsp;of</span></div></li>
+<li><div class="src-line"><a name="a1199"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;check&nbsp;in&nbsp;a&nbsp;case&nbsp;sensitive&nbsp;manner&nbsp;or&nbsp;not</span></div></li>
+<li><div class="src-line"><a name="a1200"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1201"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1202"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_case_sensitivity">set_case_sensitivity</a><span class="src-sym">(</span><span class="src-var">$key</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$case</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1203"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'CASE_SENSITIVE'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-sym">(</span><span class="src-var">$case</span><span class="src-sym">)</span>&nbsp;?&nbsp;<span class="src-id">true</span>&nbsp;:&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1204"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1205"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1206"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1207"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;case&nbsp;that&nbsp;keywords&nbsp;should&nbsp;use&nbsp;when&nbsp;found.&nbsp;Use&nbsp;the&nbsp;constants:</span></div></li>
+<li><div class="src-line"><a name="a1208"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1209"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;-&nbsp;GESHI_CAPS_NO_CHANGE:&nbsp;leave&nbsp;keywords&nbsp;as-is</span></div></li>
+<li><div class="src-line"><a name="a1210"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;-&nbsp;GESHI_CAPS_UPPER:&nbsp;convert&nbsp;all&nbsp;keywords&nbsp;to&nbsp;uppercase&nbsp;where&nbsp;found</span></div></li>
+<li><div class="src-line"><a name="a1211"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;-&nbsp;GESHI_CAPS_LOWER:&nbsp;convert&nbsp;all&nbsp;keywords&nbsp;to&nbsp;lowercase&nbsp;where&nbsp;found</span></div></li>
+<li><div class="src-line"><a name="a1212"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1213"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">A&nbsp;constant&nbsp;specifying&nbsp;what&nbsp;to&nbsp;do&nbsp;with&nbsp;matched&nbsp;keywords</span></div></li>
+<li><div class="src-line"><a name="a1214"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.1</span></div></li>
+<li><div class="src-line"><a name="a1215"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1216"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_case_keywords">set_case_keywords</a><span class="src-sym">(</span><span class="src-var">$case</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1217"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/in_array">in_array</a><span class="src-sym">(</span><span class="src-var">$case</span><span class="src-sym">,</span>&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a1218"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_CAPS_NO_CHANGE&quot;&gt;GESHI_CAPS_NO_CHANGE&lt;/a&gt;</span><span class="src-sym">,</span>&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_CAPS_UPPER&quot;&gt;GESHI_CAPS_UPPER&lt;/a&gt;</span><span class="src-sym">,</span>&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_CAPS_LOWER&quot;&gt;GESHI_CAPS_LOWER&lt;/a&gt;</span><span class="src-sym">)))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1219"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'CASE_KEYWORDS'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$case</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1220"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1221"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1222"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1223"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1224"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;how&nbsp;many&nbsp;spaces&nbsp;a&nbsp;tab&nbsp;is&nbsp;substituted&nbsp;for</span></div></li>
+<li><div class="src-line"><a name="a1225"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1226"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Widths&nbsp;below&nbsp;zero&nbsp;are&nbsp;ignored</span></div></li>
+<li><div class="src-line"><a name="a1227"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1228"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">The&nbsp;tab&nbsp;width</span></div></li>
+<li><div class="src-line"><a name="a1229"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1230"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1231"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_tab_width">set_tab_width</a><span class="src-sym">(</span><span class="src-var">$width</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1232"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">tab_width</span>&nbsp;=&nbsp;<a href="http://www.php.net/intval">intval</a><span class="src-sym">(</span><span class="src-var">$width</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1233"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1234"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Check&nbsp;if&nbsp;it&nbsp;fit's&nbsp;the&nbsp;constraints:</span></span></div></li>
+<li><div class="src-line"><a name="a1235"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">tab_width</span>&nbsp;<&nbsp;<span class="src-num">1</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1236"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Return&nbsp;it&nbsp;to&nbsp;the&nbsp;default</span></span></div></li>
+<li><div class="src-line"><a name="a1237"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">tab_width</span>&nbsp;=&nbsp;<span class="src-num">8</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1238"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1239"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1240"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1241"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1242"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;whether&nbsp;or&nbsp;not&nbsp;to&nbsp;use&nbsp;tab-stop&nbsp;width&nbsp;specifed&nbsp;by&nbsp;language</span></div></li>
+<li><div class="src-line"><a name="a1243"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1244"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;use&nbsp;language-specific&nbsp;tab-stop&nbsp;widths</span></div></li>
+<li><div class="src-line"><a name="a1245"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.7.20</span></div></li>
+<li><div class="src-line"><a name="a1246"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1247"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_use_language_tab_width">set_use_language_tab_width</a><span class="src-sym">(</span><span class="src-var">$use</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1248"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">use_language_tab_width</span>&nbsp;=&nbsp;(bool)&nbsp;<span class="src-var">$use</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1249"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1250"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1251"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1252"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Returns&nbsp;the&nbsp;tab&nbsp;width&nbsp;to&nbsp;use,&nbsp;based&nbsp;on&nbsp;the&nbsp;current&nbsp;language&nbsp;and&nbsp;user</span></div></li>
+<li><div class="src-line"><a name="a1253"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;preference</span></div></li>
+<li><div class="src-line"><a name="a1254"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1255"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@return&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">Tab&nbsp;width</span></div></li>
+<li><div class="src-line"><a name="a1256"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.7.20</span></div></li>
+<li><div class="src-line"><a name="a1257"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1258"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodget_real_tab_width">get_real_tab_width</a><span class="src-sym">(</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1259"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">use_language_tab_width</span>&nbsp;||</span></div></li>
+<li><div class="src-line"><a name="a1260"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">!</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'TAB_WIDTH'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1261"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">tab_width</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1262"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1263"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'TAB_WIDTH'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1264"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1265"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1266"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1267"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1268"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Enables/disables&nbsp;strict&nbsp;highlighting.&nbsp;Default&nbsp;is&nbsp;off,&nbsp;calling&nbsp;this</span></div></li>
+<li><div class="src-line"><a name="a1269"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;method&nbsp;without&nbsp;parameters&nbsp;will&nbsp;turn&nbsp;it&nbsp;on.&nbsp;See&nbsp;documentation</span></div></li>
+<li><div class="src-line"><a name="a1270"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;for&nbsp;more&nbsp;details&nbsp;on&nbsp;strict&nbsp;mode&nbsp;and&nbsp;where&nbsp;to&nbsp;use&nbsp;it.</span></div></li>
+<li><div class="src-line"><a name="a1271"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1272"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;to&nbsp;enable&nbsp;strict&nbsp;mode&nbsp;or&nbsp;not</span></div></li>
+<li><div class="src-line"><a name="a1273"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1274"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1275"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodenable_strict_mode">enable_strict_mode</a><span class="src-sym">(</span><span class="src-var">$mode</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1276"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-id">GESHI_MAYBE</span>&nbsp;==&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STRICT_MODE_APPLIES'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1277"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">strict_mode</span>&nbsp;=&nbsp;<span class="src-sym">(</span><span class="src-var">$mode</span><span class="src-sym">)</span>&nbsp;?&nbsp;<span class="src-id">GESHI_ALWAYS</span>&nbsp;:&nbsp;<span class="src-id">GESHI_NEVER</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1278"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1279"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1280"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1281"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1282"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Disables&nbsp;all&nbsp;highlighting</span></div></li>
+<li><div class="src-line"><a name="a1283"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1284"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1285"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@todo</span><span class="src-doc">&nbsp;&nbsp;Rewrite&nbsp;with&nbsp;array&nbsp;traversal</span></div></li>
+<li><div class="src-line"><a name="a1286"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@deprecated</span><span class="src-doc">&nbsp;In&nbsp;favour&nbsp;of&nbsp;enable_highlighting</span></div></li>
+<li><div class="src-line"><a name="a1287"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1288"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methoddisable_highlighting">disable_highlighting</a><span class="src-sym">(</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1289"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodenable_highlighting">enable_highlighting</a><span class="src-sym">(</span><span class="src-id">false</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1290"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1291"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1292"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1293"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Enables&nbsp;all&nbsp;highlighting</span></div></li>
+<li><div class="src-line"><a name="a1294"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1295"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;optional&nbsp;flag&nbsp;parameter&nbsp;was&nbsp;added&nbsp;in&nbsp;version&nbsp;1.0.7.21&nbsp;and&nbsp;can&nbsp;be&nbsp;used</span></div></li>
+<li><div class="src-line"><a name="a1296"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;to&nbsp;enable&nbsp;(true)&nbsp;or&nbsp;disable&nbsp;(false)&nbsp;all&nbsp;highlighting.</span></div></li>
+<li><div class="src-line"><a name="a1297"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1298"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1299"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">A&nbsp;flag&nbsp;specifying&nbsp;whether&nbsp;to&nbsp;enable&nbsp;or&nbsp;disable&nbsp;all&nbsp;highlighting</span></div></li>
+<li><div class="src-line"><a name="a1300"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@todo</span><span class="src-doc">&nbsp;&nbsp;Rewrite&nbsp;with&nbsp;array&nbsp;traversal</span></div></li>
+<li><div class="src-line"><a name="a1301"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1302"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodenable_highlighting">enable_highlighting</a><span class="src-sym">(</span><span class="src-var">$flag</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1303"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$flag</span>&nbsp;=&nbsp;<span class="src-var">$flag</span>&nbsp;?&nbsp;<span class="src-id">true</span>&nbsp;:&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1304"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$key</span>&nbsp;=&gt;&nbsp;<span class="src-var">$value</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1305"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/is_array">is_array</a><span class="src-sym">(</span><span class="src-var">$value</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1306"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$value</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$k</span>&nbsp;=&gt;&nbsp;<span class="src-var">$v</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1307"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$flag</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1308"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1309"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1310"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$flag</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1311"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1312"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1313"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1314"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Context&nbsp;blocks</span></span></div></li>
+<li><div class="src-line"><a name="a1315"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">enable_important_blocks</span>&nbsp;=&nbsp;<span class="src-var">$flag</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1316"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1317"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1318"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1319"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Given&nbsp;a&nbsp;file&nbsp;extension,&nbsp;this&nbsp;method&nbsp;returns&nbsp;either&nbsp;a&nbsp;valid&nbsp;geshi&nbsp;language</span></div></li>
+<li><div class="src-line"><a name="a1320"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;name,&nbsp;or&nbsp;the&nbsp;empty&nbsp;string&nbsp;if&nbsp;it&nbsp;couldn't&nbsp;be&nbsp;found</span></div></li>
+<li><div class="src-line"><a name="a1321"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1322"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;extension&nbsp;to&nbsp;get&nbsp;a&nbsp;language&nbsp;name&nbsp;for</span></div></li>
+<li><div class="src-line"><a name="a1323"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">array&nbsp;</span><span class="src-doc">&nbsp;A&nbsp;lookup&nbsp;array&nbsp;to&nbsp;use&nbsp;instead&nbsp;of&nbsp;the&nbsp;default&nbsp;one</span></div></li>
+<li><div class="src-line"><a name="a1324"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.5</span></div></li>
+<li><div class="src-line"><a name="a1325"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@todo</span><span class="src-doc">&nbsp;Re-think&nbsp;about&nbsp;how&nbsp;this&nbsp;method&nbsp;works&nbsp;(maybe&nbsp;make&nbsp;it&nbsp;private&nbsp;and/or&nbsp;make&nbsp;it</span></div></li>
+<li><div class="src-line"><a name="a1326"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a&nbsp;extension-&gt;lang&nbsp;lookup?)</span></div></li>
+<li><div class="src-line"><a name="a1327"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@todo</span><span class="src-doc">&nbsp;static?</span></div></li>
+<li><div class="src-line"><a name="a1328"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1329"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodget_language_name_from_extension">get_language_name_from_extension</a><span class="src-sym">(</span>&nbsp;<span class="src-var">$extension</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$lookup</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1330"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>&nbsp;<span class="src-sym">!</span><a href="http://www.php.net/is_array">is_array</a><span class="src-sym">(</span><span class="src-var">$lookup</span><span class="src-sym">)</span>&nbsp;||&nbsp;<span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$lookup</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1331"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$lookup</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a1332"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'actionscript'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'as'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1333"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'ada'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'a'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'ada'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'adb'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'ads'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1334"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'apache'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'conf'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1335"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'asm'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'ash'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'asm'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'inc'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1336"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'asp'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'asp'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1337"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'bash'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'sh'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1338"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'bf'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'bf'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1339"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'c'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'c'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'h'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1340"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'c_mac'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'c'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'h'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1341"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'caddcl'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1342"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'cadlisp'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1343"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'cdfg'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'cdfg'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1344"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'cobol'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'cbl'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1345"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'cpp'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'cpp'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'hpp'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'C'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'H'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'CPP'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'HPP'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1346"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'csharp'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'cs'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1347"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'css'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'css'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1348"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'d'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'d'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1349"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'delphi'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'dpk'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'dpr'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'pp'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'pas'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1350"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'diff'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'diff'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'patch'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1351"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'dos'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'bat'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'cmd'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1352"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'gettext'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'po'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'pot'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1353"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'gml'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'gml'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1354"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'gnuplot'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'plt'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1355"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'groovy'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'groovy'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1356"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'haskell'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'hs'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1357"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'html4strict'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'html'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'htm'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1358"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'ini'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'ini'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'desktop'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1359"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'java'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'java'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1360"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'javascript'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'js'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1361"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'klonec'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'kl1'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1362"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'klonecpp'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'klx'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1363"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'latex'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'tex'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1364"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'lisp'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'lisp'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1365"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'lua'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'lua'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1366"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'matlab'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'m'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1367"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'mpasm'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1368"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'mysql'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'sql'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1369"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'nsis'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1370"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'objc'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1371"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'oobas'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1372"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'oracle8'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1373"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'oracle10'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1374"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'pascal'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'pas'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1375"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'perl'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'pl'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'pm'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1376"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'php'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'php'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'php5'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'phtml'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'phps'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1377"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'povray'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'pov'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1378"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'providex'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'pvc'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'pvx'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1379"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'prolog'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'pl'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1380"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'python'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'py'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1381"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'qbasic'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'bi'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1382"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'reg'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'reg'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1383"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'ruby'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'rb'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1384"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'sas'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'sas'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1385"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'scala'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'scala'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1386"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'scheme'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'scm'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1387"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'scilab'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'sci'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1388"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'smalltalk'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'st'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1389"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'smarty'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1390"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'tcl'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'tcl'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1391"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'vb'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'bas'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1392"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'vbnet'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1393"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'visualfoxpro'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1394"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'whitespace'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'ws'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1395"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'xml'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'xml'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'svg'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1396"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'z80'</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'z80'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'asm'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'inc'</span><span class="src-sym">)</span></span></div></li>
+<li><div class="src-line"><a name="a1397"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1398"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1399"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1400"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$lookup</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$lang</span>&nbsp;=&gt;&nbsp;<span class="src-var">$extensions</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1401"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/in_array">in_array</a><span class="src-sym">(</span><span class="src-var">$extension</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$extensions</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1402"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-var">$lang</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1403"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1404"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1405"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1406"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1407"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1408"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1409"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Given&nbsp;a&nbsp;file&nbsp;name,&nbsp;this&nbsp;method&nbsp;loads&nbsp;its&nbsp;contents&nbsp;in,&nbsp;and&nbsp;attempts</span></div></li>
+<li><div class="src-line"><a name="a1410"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;to&nbsp;set&nbsp;the&nbsp;language&nbsp;automatically.&nbsp;An&nbsp;optional&nbsp;lookup&nbsp;table&nbsp;can&nbsp;be</span></div></li>
+<li><div class="src-line"><a name="a1411"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;passed&nbsp;for&nbsp;looking&nbsp;up&nbsp;the&nbsp;language&nbsp;name.&nbsp;If&nbsp;not&nbsp;specified&nbsp;a&nbsp;default</span></div></li>
+<li><div class="src-line"><a name="a1412"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;table&nbsp;is&nbsp;used</span></div></li>
+<li><div class="src-line"><a name="a1413"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1414"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;language&nbsp;table&nbsp;is&nbsp;in&nbsp;the&nbsp;form</span></div></li>
+<li><div class="src-line"><a name="a1415"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;pre&gt;array(</span></div></li>
+<li><div class="src-line"><a name="a1416"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;'lang_name'&nbsp;=&gt;&nbsp;array('extension',&nbsp;'extension',&nbsp;...),</span></div></li>
+<li><div class="src-line"><a name="a1417"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;'lang_name'&nbsp;...</span></div></li>
+<li><div class="src-line"><a name="a1418"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;);&lt;/pre&gt;</span></div></li>
+<li><div class="src-line"><a name="a1419"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1420"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;filename&nbsp;to&nbsp;load&nbsp;the&nbsp;source&nbsp;from</span></div></li>
+<li><div class="src-line"><a name="a1421"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">array&nbsp;</span><span class="src-doc">&nbsp;A&nbsp;lookup&nbsp;array&nbsp;to&nbsp;use&nbsp;instead&nbsp;of&nbsp;the&nbsp;default&nbsp;one</span></div></li>
+<li><div class="src-line"><a name="a1422"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@todo</span><span class="src-doc">&nbsp;Complete&nbsp;rethink&nbsp;of&nbsp;this&nbsp;and&nbsp;above&nbsp;method</span></div></li>
+<li><div class="src-line"><a name="a1423"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.5</span></div></li>
+<li><div class="src-line"><a name="a1424"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1425"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodload_from_file">load_from_file</a><span class="src-sym">(</span><span class="src-var">$file_name</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$lookup</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1426"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/is_readable">is_readable</a><span class="src-sym">(</span><span class="src-var">$file_name</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1427"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodset_source">set_source</a><span class="src-sym">(</span><a href="http://www.php.net/file_get_contents">file_get_contents</a><span class="src-sym">(</span><span class="src-var">$file_name</span><span class="src-sym">))</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1428"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodset_language">set_language</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodget_language_name_from_extension">get_language_name_from_extension</a><span class="src-sym">(</span><a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><a href="http://www.php.net/strrchr">strrchr</a><span class="src-sym">(</span><span class="src-var">$file_name</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'.'</span><span class="src-sym">)</span><span class="src-sym">,</span>&nbsp;<span class="src-num">1</span><span class="src-sym">)</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$lookup</span><span class="src-sym">))</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1429"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1430"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">error</span>&nbsp;=&nbsp;<span class="src-id">GESHI_ERROR_FILE_NOT_READABLE</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1431"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1432"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1433"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1434"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1435"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Adds&nbsp;a&nbsp;keyword&nbsp;to&nbsp;a&nbsp;keyword&nbsp;group&nbsp;for&nbsp;highlighting</span></div></li>
+<li><div class="src-line"><a name="a1436"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1437"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">&nbsp;&nbsp;&nbsp;The&nbsp;key&nbsp;of&nbsp;the&nbsp;keyword&nbsp;group&nbsp;to&nbsp;add&nbsp;the&nbsp;keyword&nbsp;to</span></div></li>
+<li><div class="src-line"><a name="a1438"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;word&nbsp;to&nbsp;add&nbsp;to&nbsp;the&nbsp;keyword&nbsp;group</span></div></li>
+<li><div class="src-line"><a name="a1439"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1440"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1441"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodadd_keyword">add_keyword</a><span class="src-sym">(</span><span class="src-var">$key</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$word</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1442"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><a href="http://www.php.net/in_array">in_array</a><span class="src-sym">(</span><span class="src-var">$word</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1443"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$word</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1444"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1445"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//NEW&nbsp;in&nbsp;1.0.8&nbsp;don't&nbsp;recompile&nbsp;the&nbsp;whole&nbsp;optimized&nbsp;regexp,&nbsp;simply&nbsp;append&nbsp;it</span></span></div></li>
+<li><div class="src-line"><a name="a1446"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">parse_cache_built</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1447"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$subkey</span>&nbsp;=&nbsp;<a href="http://www.php.net/count">count</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'CACHED_KEYWORD_LISTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;-&nbsp;<span class="src-num">1</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1448"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'CACHED_KEYWORD_LISTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$subkey</span><span class="src-sym">]</span>&nbsp;.=&nbsp;<span class="src-str">'|'</span>&nbsp;.&nbsp;<a href="http://www.php.net/preg_quote">preg_quote</a><span class="src-sym">(</span><span class="src-var">$word</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'/'</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1449"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1450"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1451"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1452"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1453"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1454"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Removes&nbsp;a&nbsp;keyword&nbsp;from&nbsp;a&nbsp;keyword&nbsp;group</span></div></li>
+<li><div class="src-line"><a name="a1455"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1456"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">&nbsp;&nbsp;&nbsp;The&nbsp;key&nbsp;of&nbsp;the&nbsp;keyword&nbsp;group&nbsp;to&nbsp;remove&nbsp;the&nbsp;keyword&nbsp;from</span></div></li>
+<li><div class="src-line"><a name="a1457"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;word&nbsp;to&nbsp;remove&nbsp;from&nbsp;the&nbsp;keyword&nbsp;group</span></div></li>
+<li><div class="src-line"><a name="a1458"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">bool&nbsp;</span><span class="src-doc">&nbsp;&nbsp;Wether&nbsp;to&nbsp;automatically&nbsp;recompile&nbsp;the&nbsp;optimized&nbsp;regexp&nbsp;list&nbsp;or&nbsp;not.</span></div></li>
+<li><div class="src-line"><a name="a1459"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Note:&nbsp;if&nbsp;you&nbsp;set&nbsp;this&nbsp;to&nbsp;false&nbsp;and&nbsp;@see&nbsp;GeSHi-&gt;parse_code()&nbsp;was&nbsp;already&nbsp;called&nbsp;once,</span></div></li>
+<li><div class="src-line"><a name="a1460"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;the&nbsp;current&nbsp;language,&nbsp;you&nbsp;have&nbsp;to&nbsp;manually&nbsp;call&nbsp;@see&nbsp;GeSHi-&gt;optimize_keyword_group()</span></div></li>
+<li><div class="src-line"><a name="a1461"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;or&nbsp;the&nbsp;removed&nbsp;keyword&nbsp;will&nbsp;stay&nbsp;in&nbsp;cache&nbsp;and&nbsp;still&nbsp;be&nbsp;highlighted!&nbsp;On&nbsp;the&nbsp;other&nbsp;hand</span></div></li>
+<li><div class="src-line"><a name="a1462"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it&nbsp;might&nbsp;be&nbsp;too&nbsp;expensive&nbsp;to&nbsp;recompile&nbsp;the&nbsp;regexp&nbsp;list&nbsp;for&nbsp;every&nbsp;removal&nbsp;if&nbsp;you&nbsp;want&nbsp;to</span></div></li>
+<li><div class="src-line"><a name="a1463"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;remove&nbsp;a&nbsp;lot&nbsp;of&nbsp;keywords.</span></div></li>
+<li><div class="src-line"><a name="a1464"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1465"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1466"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodremove_keyword">remove_keyword</a><span class="src-sym">(</span><span class="src-var">$key</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$word</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$recompile</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1467"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$key_to_remove</span>&nbsp;=&nbsp;<a href="http://www.php.net/array_search">array_search</a><span class="src-sym">(</span><span class="src-var">$word</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1468"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$key_to_remove</span>&nbsp;!==&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1469"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key_to_remove</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1470"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1471"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//NEW&nbsp;in&nbsp;1.0.8,&nbsp;optionally&nbsp;recompile&nbsp;keyword&nbsp;group</span></span></div></li>
+<li><div class="src-line"><a name="a1472"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$recompile</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">parse_cache_built</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1473"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodoptimize_keyword_group">optimize_keyword_group</a><span class="src-sym">(</span><span class="src-var">$key</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1474"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1475"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1476"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1477"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1478"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1479"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Creates&nbsp;a&nbsp;new&nbsp;keyword&nbsp;group</span></div></li>
+<li><div class="src-line"><a name="a1480"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1481"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">&nbsp;&nbsp;&nbsp;The&nbsp;key&nbsp;of&nbsp;the&nbsp;keyword&nbsp;group&nbsp;to&nbsp;create</span></div></li>
+<li><div class="src-line"><a name="a1482"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;styles&nbsp;for&nbsp;the&nbsp;keyword&nbsp;group</span></div></li>
+<li><div class="src-line"><a name="a1483"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Whether&nbsp;the&nbsp;keyword&nbsp;group&nbsp;is&nbsp;case&nbsp;sensitive&nbsp;ornot</span></div></li>
+<li><div class="src-line"><a name="a1484"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">array&nbsp;</span><span class="src-doc">&nbsp;The&nbsp;words&nbsp;to&nbsp;use&nbsp;for&nbsp;the&nbsp;keyword&nbsp;group</span></div></li>
+<li><div class="src-line"><a name="a1485"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1486"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1487"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodadd_keyword_group">add_keyword_group</a><span class="src-sym">(</span><span class="src-var">$key</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$styles</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$case_sensitive</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$words</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1488"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$words</span>&nbsp;=&nbsp;(array)&nbsp;<span class="src-var">$words</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1489"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;&nbsp;<span class="src-sym">(</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$words</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1490"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;empty&nbsp;word&nbsp;lists&nbsp;mess&nbsp;up&nbsp;highlighting</span></span></div></li>
+<li><div class="src-line"><a name="a1491"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1492"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1493"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1494"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Add&nbsp;the&nbsp;new&nbsp;keyword&nbsp;group&nbsp;internally</span></span></div></li>
+<li><div class="src-line"><a name="a1495"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$words</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1496"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1497"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'CASE_SENSITIVE'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$case_sensitive</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1498"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$styles</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1499"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1500"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//NEW&nbsp;in&nbsp;1.0.8,&nbsp;cache&nbsp;keyword&nbsp;regexp</span></span></div></li>
+<li><div class="src-line"><a name="a1501"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">parse_cache_built</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1502"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodoptimize_keyword_group">optimize_keyword_group</a><span class="src-sym">(</span><span class="src-var">$key</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1503"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1504"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1505"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1506"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1507"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Removes&nbsp;a&nbsp;keyword&nbsp;group</span></div></li>
+<li><div class="src-line"><a name="a1508"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1509"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">&nbsp;&nbsp;&nbsp;The&nbsp;key&nbsp;of&nbsp;the&nbsp;keyword&nbsp;group&nbsp;to&nbsp;remove</span></div></li>
+<li><div class="src-line"><a name="a1510"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1511"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1512"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodremove_keyword_group">remove_keyword_group</a>&nbsp;<span class="src-sym">(</span><span class="src-var">$key</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1513"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Remove&nbsp;the&nbsp;keyword&nbsp;group&nbsp;internally</span></span></div></li>
+<li><div class="src-line"><a name="a1514"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1515"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1516"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'CASE_SENSITIVE'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1517"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1518"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1519"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//NEW&nbsp;in&nbsp;1.0.8</span></span></div></li>
+<li><div class="src-line"><a name="a1520"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'CACHED_KEYWORD_LISTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1521"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1522"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1523"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1524"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;compile&nbsp;optimized&nbsp;regexp&nbsp;list&nbsp;for&nbsp;keyword&nbsp;group</span></div></li>
+<li><div class="src-line"><a name="a1525"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1526"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">&nbsp;&nbsp;The&nbsp;key&nbsp;of&nbsp;the&nbsp;keyword&nbsp;group&nbsp;to&nbsp;compile&nbsp;&amp;&nbsp;optimize</span></div></li>
+<li><div class="src-line"><a name="a1527"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.8</span></div></li>
+<li><div class="src-line"><a name="a1528"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1529"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodoptimize_keyword_group">optimize_keyword_group</a><span class="src-sym">(</span><span class="src-var">$key</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1530"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'CACHED_KEYWORD_LISTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=</span></div></li>
+<li><div class="src-line"><a name="a1531"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">optimize_regexp_list</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1532"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1533"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1534"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1535"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;content&nbsp;of&nbsp;the&nbsp;header&nbsp;block</span></div></li>
+<li><div class="src-line"><a name="a1536"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1537"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;content&nbsp;of&nbsp;the&nbsp;header&nbsp;block</span></div></li>
+<li><div class="src-line"><a name="a1538"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.2</span></div></li>
+<li><div class="src-line"><a name="a1539"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1540"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_header_content">set_header_content</a><span class="src-sym">(</span><span class="src-var">$content</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1541"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">header_content</span>&nbsp;=&nbsp;<span class="src-var">$content</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1542"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1543"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1544"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1545"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;content&nbsp;of&nbsp;the&nbsp;footer&nbsp;block</span></div></li>
+<li><div class="src-line"><a name="a1546"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1547"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;content&nbsp;of&nbsp;the&nbsp;footer&nbsp;block</span></div></li>
+<li><div class="src-line"><a name="a1548"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.2</span></div></li>
+<li><div class="src-line"><a name="a1549"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1550"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_footer_content">set_footer_content</a><span class="src-sym">(</span><span class="src-var">$content</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1551"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">footer_content</span>&nbsp;=&nbsp;<span class="src-var">$content</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1552"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1553"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1554"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1555"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;style&nbsp;for&nbsp;the&nbsp;header&nbsp;content</span></div></li>
+<li><div class="src-line"><a name="a1556"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1557"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;style&nbsp;for&nbsp;the&nbsp;header&nbsp;content</span></div></li>
+<li><div class="src-line"><a name="a1558"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.2</span></div></li>
+<li><div class="src-line"><a name="a1559"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1560"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_header_content_style">set_header_content_style</a><span class="src-sym">(</span><span class="src-var">$style</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1561"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">header_content_style</span>&nbsp;=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1562"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1563"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1564"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1565"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;style&nbsp;for&nbsp;the&nbsp;footer&nbsp;content</span></div></li>
+<li><div class="src-line"><a name="a1566"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1567"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;style&nbsp;for&nbsp;the&nbsp;footer&nbsp;content</span></div></li>
+<li><div class="src-line"><a name="a1568"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.2</span></div></li>
+<li><div class="src-line"><a name="a1569"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1570"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_footer_content_style">set_footer_content_style</a><span class="src-sym">(</span><span class="src-var">$style</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1571"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">footer_content_style</span>&nbsp;=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1572"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1573"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1574"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1575"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;whether&nbsp;to&nbsp;force&nbsp;a&nbsp;surrounding&nbsp;block&nbsp;around</span></div></li>
+<li><div class="src-line"><a name="a1576"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;the&nbsp;highlighted&nbsp;code&nbsp;or&nbsp;not</span></div></li>
+<li><div class="src-line"><a name="a1577"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1578"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Tells&nbsp;whether&nbsp;to&nbsp;enable&nbsp;or&nbsp;disable&nbsp;this&nbsp;feature</span></div></li>
+<li><div class="src-line"><a name="a1579"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.7.20</span></div></li>
+<li><div class="src-line"><a name="a1580"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1581"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodenable_inner_code_block">enable_inner_code_block</a><span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1582"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">force_code_block</span>&nbsp;=&nbsp;(bool)<span class="src-var">$flag</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1583"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1584"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1585"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1586"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;base&nbsp;URL&nbsp;to&nbsp;be&nbsp;used&nbsp;for&nbsp;keywords</span></div></li>
+<li><div class="src-line"><a name="a1587"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1588"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">The&nbsp;key&nbsp;of&nbsp;the&nbsp;keyword&nbsp;group&nbsp;to&nbsp;set&nbsp;the&nbsp;URL&nbsp;for</span></div></li>
+<li><div class="src-line"><a name="a1589"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;URL&nbsp;to&nbsp;set&nbsp;for&nbsp;the&nbsp;group.&nbsp;If&nbsp;{FNAME}&nbsp;is&nbsp;in</span></div></li>
+<li><div class="src-line"><a name="a1590"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;url&nbsp;somewhere,&nbsp;it&nbsp;is&nbsp;replaced&nbsp;by&nbsp;the&nbsp;keyword</span></div></li>
+<li><div class="src-line"><a name="a1591"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;that&nbsp;the&nbsp;URL&nbsp;is&nbsp;being&nbsp;made&nbsp;for</span></div></li>
+<li><div class="src-line"><a name="a1592"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.2</span></div></li>
+<li><div class="src-line"><a name="a1593"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1594"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_url_for_keyword_group">set_url_for_keyword_group</a><span class="src-sym">(</span><span class="src-var">$group</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$url</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1595"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'URLS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$group</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$url</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1596"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1597"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1598"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1599"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;styles&nbsp;for&nbsp;links&nbsp;in&nbsp;code</span></div></li>
+<li><div class="src-line"><a name="a1600"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1601"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">A&nbsp;constant&nbsp;that&nbsp;specifies&nbsp;what&nbsp;state&nbsp;the&nbsp;style&nbsp;is&nbsp;being</span></div></li>
+<li><div class="src-line"><a name="a1602"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set&nbsp;for&nbsp;-&nbsp;e.g.&nbsp;:hover&nbsp;or&nbsp;:visited</span></div></li>
+<li><div class="src-line"><a name="a1603"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;styles&nbsp;to&nbsp;use&nbsp;for&nbsp;that&nbsp;state</span></div></li>
+<li><div class="src-line"><a name="a1604"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.2</span></div></li>
+<li><div class="src-line"><a name="a1605"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1606"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_link_styles">set_link_styles</a><span class="src-sym">(</span><span class="src-var">$type</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$styles</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1607"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">link_styles</span><span class="src-sym">[</span><span class="src-var">$type</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$styles</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1608"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1609"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1610"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1611"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;target&nbsp;for&nbsp;links&nbsp;in&nbsp;code</span></div></li>
+<li><div class="src-line"><a name="a1612"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1613"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;target&nbsp;for&nbsp;links&nbsp;in&nbsp;the&nbsp;code,&nbsp;e.g.&nbsp;_blank</span></div></li>
+<li><div class="src-line"><a name="a1614"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.3</span></div></li>
+<li><div class="src-line"><a name="a1615"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1616"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_link_target">set_link_target</a><span class="src-sym">(</span><span class="src-var">$target</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1617"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$target</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1618"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">link_target</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1619"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1620"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">link_target</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;target=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$target</span>&nbsp;.&nbsp;<span class="src-str">'&quot;&nbsp;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1621"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1622"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1623"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1624"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1625"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;styles&nbsp;for&nbsp;important&nbsp;parts&nbsp;of&nbsp;the&nbsp;code</span></div></li>
+<li><div class="src-line"><a name="a1626"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1627"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;styles&nbsp;to&nbsp;use&nbsp;on&nbsp;important&nbsp;parts&nbsp;of&nbsp;the&nbsp;code</span></div></li>
+<li><div class="src-line"><a name="a1628"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.2</span></div></li>
+<li><div class="src-line"><a name="a1629"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1630"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_important_styles">set_important_styles</a><span class="src-sym">(</span><span class="src-var">$styles</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1631"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">important_styles</span>&nbsp;=&nbsp;<span class="src-var">$styles</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1632"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1633"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1634"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1635"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;whether&nbsp;context-important&nbsp;blocks&nbsp;are&nbsp;highlighted</span></div></li>
+<li><div class="src-line"><a name="a1636"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1637"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">Tells&nbsp;whether&nbsp;to&nbsp;enable&nbsp;or&nbsp;disable&nbsp;highlighting&nbsp;of&nbsp;important&nbsp;blocks</span></div></li>
+<li><div class="src-line"><a name="a1638"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@todo</span><span class="src-doc">&nbsp;REMOVE&nbsp;THIS&nbsp;SHIZ&nbsp;FROM&nbsp;GESHI!</span></div></li>
+<li><div class="src-line"><a name="a1639"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@deprecated</span></div></li>
+<li><div class="src-line"><a name="a1640"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.2</span></div></li>
+<li><div class="src-line"><a name="a1641"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1642"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodenable_important_blocks">enable_important_blocks</a><span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1643"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">enable_important_blocks</span>&nbsp;=&nbsp;<span class="src-sym">(</span>&nbsp;<span class="src-var">$flag</span>&nbsp;<span class="src-sym">)</span>&nbsp;?&nbsp;<span class="src-id">true</span>&nbsp;:&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1644"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1645"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1646"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1647"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Whether&nbsp;CSS&nbsp;IDs&nbsp;should&nbsp;be&nbsp;added&nbsp;to&nbsp;each&nbsp;line</span></div></li>
+<li><div class="src-line"><a name="a1648"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1649"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">If&nbsp;true,&nbsp;IDs&nbsp;will&nbsp;be&nbsp;added&nbsp;to&nbsp;each&nbsp;line.</span></div></li>
+<li><div class="src-line"><a name="a1650"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.2</span></div></li>
+<li><div class="src-line"><a name="a1651"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1652"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodenable_ids">enable_ids</a><span class="src-sym">(</span><span class="src-var">$flag</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1653"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">add_ids</span>&nbsp;=&nbsp;<span class="src-sym">(</span><span class="src-var">$flag</span><span class="src-sym">)</span>&nbsp;?&nbsp;<span class="src-id">true</span>&nbsp;:&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1654"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1655"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1656"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1657"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Specifies&nbsp;which&nbsp;lines&nbsp;to&nbsp;highlight&nbsp;extra</span></div></li>
+<li><div class="src-line"><a name="a1658"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1659"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;extra&nbsp;style&nbsp;parameter&nbsp;was&nbsp;added&nbsp;in&nbsp;1.0.7.21.</span></div></li>
+<li><div class="src-line"><a name="a1660"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1661"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">mixed&nbsp;</span><span class="src-doc">An&nbsp;array&nbsp;of&nbsp;line&nbsp;numbers&nbsp;to&nbsp;highlight,&nbsp;or&nbsp;just&nbsp;a&nbsp;line</span></div></li>
+<li><div class="src-line"><a name="a1662"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;number&nbsp;on&nbsp;its&nbsp;own.</span></div></li>
+<li><div class="src-line"><a name="a1663"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">A&nbsp;string&nbsp;specifying&nbsp;the&nbsp;style&nbsp;to&nbsp;use&nbsp;for&nbsp;this&nbsp;line.</span></div></li>
+<li><div class="src-line"><a name="a1664"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;null&nbsp;is&nbsp;specified,&nbsp;the&nbsp;default&nbsp;style&nbsp;is&nbsp;used.</span></div></li>
+<li><div class="src-line"><a name="a1665"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;false&nbsp;is&nbsp;specified,&nbsp;the&nbsp;line&nbsp;will&nbsp;be&nbsp;removed&nbsp;from</span></div></li>
+<li><div class="src-line"><a name="a1666"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;special&nbsp;highlighting</span></div></li>
+<li><div class="src-line"><a name="a1667"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.2</span></div></li>
+<li><div class="src-line"><a name="a1668"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@todo</span><span class="src-doc">&nbsp;&nbsp;Some&nbsp;data&nbsp;replication&nbsp;here&nbsp;that&nbsp;could&nbsp;be&nbsp;cut&nbsp;down&nbsp;on</span></div></li>
+<li><div class="src-line"><a name="a1669"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1670"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodhighlight_lines_extra">highlight_lines_extra</a><span class="src-sym">(</span><span class="src-var">$lines</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$style</span>&nbsp;=&nbsp;<span class="src-id">null</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1671"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/is_array">is_array</a><span class="src-sym">(</span><span class="src-var">$lines</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1672"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Split&nbsp;up&nbsp;the&nbsp;job&nbsp;using&nbsp;single&nbsp;lines&nbsp;at&nbsp;a&nbsp;time</span></span></div></li>
+<li><div class="src-line"><a name="a1673"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$lines</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$line</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1674"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodhighlight_lines_extra">highlight_lines_extra</a><span class="src-sym">(</span><span class="src-var">$line</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$style</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1675"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1676"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1677"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Mark&nbsp;the&nbsp;line&nbsp;as&nbsp;being&nbsp;highlighted&nbsp;specially</span></span></div></li>
+<li><div class="src-line"><a name="a1678"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$lines</span>&nbsp;=&nbsp;<a href="http://www.php.net/intval">intval</a><span class="src-sym">(</span><span class="src-var">$lines</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1679"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">highlight_extra_lines</span><span class="src-sym">[</span><span class="src-var">$lines</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$lines</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1680"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1681"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Decide&nbsp;on&nbsp;which&nbsp;style&nbsp;to&nbsp;use</span></span></div></li>
+<li><div class="src-line"><a name="a1682"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$style</span>&nbsp;===&nbsp;<span class="src-id">null</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span>&nbsp;<span class="src-comm">//Check&nbsp;if&nbsp;we&nbsp;should&nbsp;use&nbsp;default&nbsp;style</span></span></div></li>
+<li><div class="src-line"><a name="a1683"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">highlight_extra_lines_styles</span><span class="src-sym">[</span><span class="src-var">$lines</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1684"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$style</span>&nbsp;===&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span>&nbsp;<span class="src-comm">//Check&nbsp;if&nbsp;to&nbsp;remove&nbsp;this&nbsp;line</span></span></div></li>
+<li><div class="src-line"><a name="a1685"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">highlight_extra_lines</span><span class="src-sym">[</span><span class="src-var">$lines</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1686"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">highlight_extra_lines_styles</span><span class="src-sym">[</span><span class="src-var">$lines</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1687"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1688"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">highlight_extra_lines_styles</span><span class="src-sym">[</span><span class="src-var">$lines</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$style</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1689"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1690"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1691"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1692"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1693"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1694"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;style&nbsp;for&nbsp;extra-highlighted&nbsp;lines</span></div></li>
+<li><div class="src-line"><a name="a1695"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1696"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;style&nbsp;for&nbsp;extra-highlighted&nbsp;lines</span></div></li>
+<li><div class="src-line"><a name="a1697"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.2</span></div></li>
+<li><div class="src-line"><a name="a1698"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1699"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_highlight_lines_extra_style">set_highlight_lines_extra_style</a><span class="src-sym">(</span><span class="src-var">$styles</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1700"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">highlight_extra_lines_style</span>&nbsp;=&nbsp;<span class="src-var">$styles</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1701"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1702"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1703"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1704"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;line-ending</span></div></li>
+<li><div class="src-line"><a name="a1705"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1706"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;new&nbsp;line-ending</span></div></li>
+<li><div class="src-line"><a name="a1707"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.2</span></div></li>
+<li><div class="src-line"><a name="a1708"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1709"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_line_ending">set_line_ending</a><span class="src-sym">(</span><span class="src-var">$line_ending</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1710"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">line_ending</span>&nbsp;=&nbsp;(string)<span class="src-var">$line_ending</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1711"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1712"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1713"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1714"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;what&nbsp;number&nbsp;line&nbsp;numbers&nbsp;should&nbsp;start&nbsp;at.&nbsp;Should</span></div></li>
+<li><div class="src-line"><a name="a1715"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;be&nbsp;a&nbsp;positive&nbsp;integer,&nbsp;and&nbsp;will&nbsp;be&nbsp;converted&nbsp;to&nbsp;one.</span></div></li>
+<li><div class="src-line"><a name="a1716"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1717"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;b&gt;Warning:&lt;/b&gt;&nbsp;Using&nbsp;this&nbsp;method&nbsp;will&nbsp;add&nbsp;the&nbsp;&quot;start&quot;</span></div></li>
+<li><div class="src-line"><a name="a1718"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;attribute&nbsp;to&nbsp;the&nbsp;&amp;lt;ol&amp;gt;&nbsp;that&nbsp;is&nbsp;used&nbsp;for&nbsp;line&nbsp;numbering.</span></div></li>
+<li><div class="src-line"><a name="a1719"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;This&nbsp;is&nbsp;&lt;b&gt;not&lt;/b&gt;&nbsp;valid&nbsp;XHTML&nbsp;strict,&nbsp;so&nbsp;if&nbsp;that's&nbsp;what&nbsp;you</span></div></li>
+<li><div class="src-line"><a name="a1720"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;care&nbsp;about&nbsp;then&nbsp;don't&nbsp;use&nbsp;this&nbsp;method.&nbsp;Firefox&nbsp;is&nbsp;getting</span></div></li>
+<li><div class="src-line"><a name="a1721"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;support&nbsp;for&nbsp;the&nbsp;CSS&nbsp;method&nbsp;of&nbsp;doing&nbsp;this&nbsp;in&nbsp;1.1&nbsp;and&nbsp;Opera</span></div></li>
+<li><div class="src-line"><a name="a1722"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;has&nbsp;support&nbsp;for&nbsp;the&nbsp;CSS&nbsp;method,&nbsp;but&nbsp;(of&nbsp;course)&nbsp;IE&nbsp;doesn't</span></div></li>
+<li><div class="src-line"><a name="a1723"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;so&nbsp;it's&nbsp;not&nbsp;worth&nbsp;doing&nbsp;it&nbsp;the&nbsp;CSS&nbsp;way&nbsp;yet.</span></div></li>
+<li><div class="src-line"><a name="a1724"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1725"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">int&nbsp;</span><span class="src-doc">The&nbsp;number&nbsp;to&nbsp;start&nbsp;line&nbsp;numbers&nbsp;at</span></div></li>
+<li><div class="src-line"><a name="a1726"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.2</span></div></li>
+<li><div class="src-line"><a name="a1727"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1728"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodstart_line_numbers_at">start_line_numbers_at</a><span class="src-sym">(</span><span class="src-var">$number</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1729"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">line_numbers_start</span>&nbsp;=&nbsp;<a href="http://www.php.net/abs">abs</a><span class="src-sym">(</span><a href="http://www.php.net/intval">intval</a><span class="src-sym">(</span><span class="src-var">$number</span><span class="src-sym">))</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1730"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1731"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1732"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1733"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;encoding&nbsp;used&nbsp;for&nbsp;htmlspecialchars(),&nbsp;for&nbsp;international</span></div></li>
+<li><div class="src-line"><a name="a1734"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;support.</span></div></li>
+<li><div class="src-line"><a name="a1735"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1736"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;NOTE:&nbsp;This&nbsp;is&nbsp;not&nbsp;needed&nbsp;for&nbsp;now&nbsp;because&nbsp;htmlspecialchars()&nbsp;is&nbsp;not</span></div></li>
+<li><div class="src-line"><a name="a1737"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;being&nbsp;used&nbsp;(it&nbsp;has&nbsp;a&nbsp;security&nbsp;hole&nbsp;in&nbsp;PHP4&nbsp;that&nbsp;has&nbsp;not&nbsp;been&nbsp;patched).</span></div></li>
+<li><div class="src-line"><a name="a1738"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Maybe&nbsp;in&nbsp;a&nbsp;future&nbsp;version&nbsp;it&nbsp;may&nbsp;make&nbsp;a&nbsp;return&nbsp;for&nbsp;speed&nbsp;reasons,&nbsp;but</span></div></li>
+<li><div class="src-line"><a name="a1739"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;I&nbsp;doubt&nbsp;it.</span></div></li>
+<li><div class="src-line"><a name="a1740"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1741"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;encoding&nbsp;to&nbsp;use&nbsp;for&nbsp;the&nbsp;source</span></div></li>
+<li><div class="src-line"><a name="a1742"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.3</span></div></li>
+<li><div class="src-line"><a name="a1743"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1744"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodset_encoding">set_encoding</a><span class="src-sym">(</span><span class="src-var">$encoding</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1745"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$encoding</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1746"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">encoding</span>&nbsp;=&nbsp;<a href="http://www.php.net/strtolower">strtolower</a><span class="src-sym">(</span><span class="src-var">$encoding</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1747"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1748"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1749"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1750"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1751"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Turns&nbsp;linking&nbsp;of&nbsp;keywords&nbsp;on&nbsp;or&nbsp;off.</span></div></li>
+<li><div class="src-line"><a name="a1752"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1753"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">boolean&nbsp;</span><span class="src-doc">If&nbsp;true,&nbsp;links&nbsp;will&nbsp;be&nbsp;added&nbsp;to&nbsp;keywords</span></div></li>
+<li><div class="src-line"><a name="a1754"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.2</span></div></li>
+<li><div class="src-line"><a name="a1755"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1756"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodenable_keyword_links">enable_keyword_links</a><span class="src-sym">(</span><span class="src-var">$enable</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1757"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">keyword_links</span>&nbsp;=&nbsp;(bool)&nbsp;<span class="src-var">$enable</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1758"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1759"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1760"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1761"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Setup&nbsp;caches&nbsp;needed&nbsp;for&nbsp;styling.&nbsp;This&nbsp;is&nbsp;automatically&nbsp;called&nbsp;in</span></div></li>
+<li><div class="src-line"><a name="a1762"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;parse_code()&nbsp;and&nbsp;get_stylesheet()&nbsp;when&nbsp;appropriate.&nbsp;This&nbsp;function&nbsp;helps</span></div></li>
+<li><div class="src-line"><a name="a1763"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;stylesheet&nbsp;generators&nbsp;as&nbsp;they&nbsp;rely&nbsp;on&nbsp;some&nbsp;style&nbsp;information&nbsp;being</span></div></li>
+<li><div class="src-line"><a name="a1764"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;preprocessed</span></div></li>
+<li><div class="src-line"><a name="a1765"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1766"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.8</span></div></li>
+<li><div class="src-line"><a name="a1767"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@access</span><span class="src-doc">&nbsp;private</span></div></li>
+<li><div class="src-line"><a name="a1768"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1769"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<span class="src-id">build_style_cache</span><span class="src-sym">(</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1770"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Build&nbsp;the&nbsp;style&nbsp;cache&nbsp;needed&nbsp;to&nbsp;highlight&nbsp;numbers&nbsp;appropriate</span></span></div></li>
+<li><div class="src-line"><a name="a1771"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1772"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//First&nbsp;check&nbsp;what&nbsp;way&nbsp;highlighting&nbsp;information&nbsp;for&nbsp;numbers&nbsp;are&nbsp;given</span></span></div></li>
+<li><div class="src-line"><a name="a1773"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-sym">!</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1774"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1775"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1776"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1777"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><a href="http://www.php.net/is_array">is_array</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1778"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'NUMBERS_CACHE'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1779"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1780"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'NUMBERS_CACHE'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1781"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1782"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]</span>&nbsp;=</span></div></li>
+<li><div class="src-line"><a name="a1783"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">GESHI_NUMBER_INT_BASIC</span>&nbsp;|</span></div></li>
+<li><div class="src-line"><a name="a1784"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">GESHI_NUMBER_FLT_NONSCI</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1785"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1786"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1787"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">for</span><span class="src-sym">(</span><span class="src-var">$i</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$j</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]</span><span class="src-sym">;</span>&nbsp;<span class="src-var">$j</span>&nbsp;>&nbsp;<span class="src-num">0</span><span class="src-sym">;</span>&nbsp;++<span class="src-var">$i</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$j</span>&gt;&gt;=<span class="src-num">1</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1788"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Rearrange&nbsp;style&nbsp;indices&nbsp;if&nbsp;required&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a1789"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">1</span>&lt;&lt;<span class="src-var">$i</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1790"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$i</span><span class="src-sym">]</span>&nbsp;=</span></div></li>
+<li><div class="src-line"><a name="a1791"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">1</span>&lt;&lt;<span class="src-var">$i</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1792"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">1</span>&lt;&lt;<span class="src-var">$i</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1793"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1794"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1795"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Check&nbsp;if&nbsp;this&nbsp;bit&nbsp;is&nbsp;set&nbsp;for&nbsp;highlighting</span></span></div></li>
+<li><div class="src-line"><a name="a1796"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-var">$j</span><span class="src-sym">&</span><span class="src-num">1</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1797"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//So&nbsp;this&nbsp;bit&nbsp;is&nbsp;set&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a1798"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Check&nbsp;if&nbsp;it&nbsp;belongs&nbsp;to&nbsp;group&nbsp;0&nbsp;or&nbsp;the&nbsp;actual&nbsp;stylegroup</span></span></div></li>
+<li><div class="src-line"><a name="a1799"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$i</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1800"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'NUMBERS_CACHE'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$i</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-num">1</span>&nbsp;&lt;&lt;&nbsp;<span class="src-var">$i</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1801"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1802"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-sym">!</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'NUMBERS_CACHE'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1803"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'NUMBERS_CACHE'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1804"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1805"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'NUMBERS_CACHE'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;|=&nbsp;<span class="src-num">1</span>&nbsp;&lt;&lt;&nbsp;<span class="src-var">$i</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1806"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1807"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1808"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1809"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1810"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1811"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1812"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1813"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a1814"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Setup&nbsp;caches&nbsp;needed&nbsp;for&nbsp;parsing.&nbsp;This&nbsp;is&nbsp;automatically&nbsp;called&nbsp;in&nbsp;parse_code()&nbsp;when&nbsp;appropriate.</span></div></li>
+<li><div class="src-line"><a name="a1815"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;This&nbsp;function&nbsp;makes&nbsp;stylesheet&nbsp;generators&nbsp;much&nbsp;faster&nbsp;as&nbsp;they&nbsp;do&nbsp;not&nbsp;need&nbsp;these&nbsp;caches.</span></div></li>
+<li><div class="src-line"><a name="a1816"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1817"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.8</span></div></li>
+<li><div class="src-line"><a name="a1818"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@access</span><span class="src-doc">&nbsp;private</span></div></li>
+<li><div class="src-line"><a name="a1819"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a1820"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<span class="src-id">build_parse_cache</span><span class="src-sym">(</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1821"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;cache&nbsp;symbol&nbsp;regexp</span></span></div></li>
+<li><div class="src-line"><a name="a1822"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//As&nbsp;this&nbsp;is&nbsp;a&nbsp;costy&nbsp;operation,&nbsp;we&nbsp;avoid&nbsp;doing&nbsp;it&nbsp;for&nbsp;multiple&nbsp;groups&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a1823"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Instead&nbsp;we&nbsp;perform&nbsp;it&nbsp;for&nbsp;all&nbsp;symbols&nbsp;at&nbsp;once.</span></span></div></li>
+<li><div class="src-line"><a name="a1824"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//</span></span></div></li>
+<li><div class="src-line"><a name="a1825"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//For&nbsp;this&nbsp;to&nbsp;work,&nbsp;we&nbsp;need&nbsp;to&nbsp;reorganize&nbsp;the&nbsp;data&nbsp;arrays.</span></span></div></li>
+<li><div class="src-line"><a name="a1826"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'SYMBOLS'</span><span class="src-sym">]</span>&nbsp;&amp;&amp;&nbsp;<span class="src-sym">!</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'SYMBOLS'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1827"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'MULTIPLE_SYMBOL_GROUPS'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<a href="http://www.php.net/count">count</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'SYMBOLS'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;>&nbsp;<span class="src-num">1</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1828"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1829"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'SYMBOL_DATA'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1830"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_preg_multi</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span>&nbsp;<span class="src-comm">//&nbsp;multi&nbsp;char&nbsp;symbols</span></span></div></li>
+<li><div class="src-line"><a name="a1831"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_preg_single</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span>&nbsp;<span class="src-comm">//&nbsp;single&nbsp;char&nbsp;symbols</span></span></div></li>
+<li><div class="src-line"><a name="a1832"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'SYMBOLS'</span><span class="src-sym">]</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$key</span>&nbsp;=&gt;&nbsp;<span class="src-var">$symbols</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1833"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/is_array">is_array</a><span class="src-sym">(</span><span class="src-var">$symbols</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1834"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$symbols</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$sym</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1835"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$sym</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$sym</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1836"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'SYMBOL_DATA'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$sym</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1837"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'SYMBOL_DATA'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$sym</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$key</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1838"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$sym</span><span class="src-sym">[</span><span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span>&nbsp;<span class="src-comm">//&nbsp;multiple&nbsp;chars</span></span></div></li>
+<li><div class="src-line"><a name="a1839"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_preg_multi</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<a href="http://www.php.net/preg_quote">preg_quote</a><span class="src-sym">(</span><span class="src-var">$sym</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'/'</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1840"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span>&nbsp;<span class="src-comm">//&nbsp;single&nbsp;char</span></span></div></li>
+<li><div class="src-line"><a name="a1841"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$sym</span>&nbsp;==&nbsp;<span class="src-str">'-'</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1842"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;don't&nbsp;trigger&nbsp;range&nbsp;out&nbsp;of&nbsp;order&nbsp;error</span></span></div></li>
+<li><div class="src-line"><a name="a1843"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_preg_single</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">'\-'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1844"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1845"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_preg_single</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<a href="http://www.php.net/preg_quote">preg_quote</a><span class="src-sym">(</span><span class="src-var">$sym</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'/'</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1846"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1847"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1848"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1849"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1850"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1851"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbols</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$symbols</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1852"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'SYMBOL_DATA'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$symbols</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1853"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'SYMBOL_DATA'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$symbols</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1854"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$symbols</span><span class="src-sym">[</span><span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span>&nbsp;<span class="src-comm">//&nbsp;multiple&nbsp;chars</span></span></div></li>
+<li><div class="src-line"><a name="a1855"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_preg_multi</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<a href="http://www.php.net/preg_quote">preg_quote</a><span class="src-sym">(</span><span class="src-var">$symbols</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'/'</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1856"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$symbols</span>&nbsp;==&nbsp;<span class="src-str">'-'</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1857"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;don't&nbsp;trigger&nbsp;range&nbsp;out&nbsp;of&nbsp;order&nbsp;error</span></span></div></li>
+<li><div class="src-line"><a name="a1858"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_preg_single</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">'\-'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1859"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span>&nbsp;<span class="src-comm">//&nbsp;single&nbsp;char</span></span></div></li>
+<li><div class="src-line"><a name="a1860"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_preg_single</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<a href="http://www.php.net/preg_quote">preg_quote</a><span class="src-sym">(</span><span class="src-var">$symbols</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'/'</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1861"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1862"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1863"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1864"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1865"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1866"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Now&nbsp;we&nbsp;have&nbsp;an&nbsp;array&nbsp;with&nbsp;each&nbsp;possible&nbsp;symbol&nbsp;as&nbsp;the&nbsp;key&nbsp;and&nbsp;the&nbsp;style&nbsp;as&nbsp;the&nbsp;actual&nbsp;data.</span></span></div></li>
+<li><div class="src-line"><a name="a1867"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//This&nbsp;way&nbsp;we&nbsp;can&nbsp;set&nbsp;the&nbsp;correct&nbsp;style&nbsp;just&nbsp;the&nbsp;moment&nbsp;we&nbsp;highlight&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a1868"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//</span></span></div></li>
+<li><div class="src-line"><a name="a1869"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Now&nbsp;we&nbsp;need&nbsp;to&nbsp;rewrite&nbsp;our&nbsp;array&nbsp;to&nbsp;get&nbsp;a&nbsp;search&nbsp;string&nbsp;that</span></span></div></li>
+<li><div class="src-line"><a name="a1870"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_preg</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1871"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$symbol_preg_multi</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1872"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/rsort">rsort</a><span class="src-sym">(</span><span class="src-var">$symbol_preg_multi</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1873"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_preg</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<a href="http://www.php.net/implode">implode</a><span class="src-sym">(</span><span class="src-str">'|'</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$symbol_preg_multi</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1874"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1875"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$symbol_preg_single</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1876"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/rsort">rsort</a><span class="src-sym">(</span><span class="src-var">$symbol_preg_single</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1877"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_preg</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">'['</span>&nbsp;.&nbsp;<a href="http://www.php.net/implode">implode</a><span class="src-sym">(</span><span class="src-str">''</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$symbol_preg_single</span><span class="src-sym">)</span>&nbsp;.&nbsp;<span class="src-str">']'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1878"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1879"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'SYMBOL_SEARCH'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<a href="http://www.php.net/implode">implode</a><span class="src-sym">(</span><span class="src-str">&quot;|&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$symbol_preg</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1880"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1881"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1882"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;cache&nbsp;optimized&nbsp;regexp&nbsp;for&nbsp;keyword&nbsp;matching</span></span></div></li>
+<li><div class="src-line"><a name="a1883"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;remove&nbsp;old&nbsp;cache</span></span></div></li>
+<li><div class="src-line"><a name="a1884"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'CACHED_KEYWORD_LISTS'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1885"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/array_keys">array_keys</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$key</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1886"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;||</span></div></li>
+<li><div class="src-line"><a name="a1887"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1888"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodoptimize_keyword_group">optimize_keyword_group</a><span class="src-sym">(</span><span class="src-var">$key</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1889"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1890"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1891"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1892"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;brackets</span></span></div></li>
+<li><div class="src-line"><a name="a1893"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'BRACKETS'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1894"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'CACHE_BRACKET_MATCH'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'['</span><span class="src-sym">,</span>&nbsp;<span class="src-str">']'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'('</span><span class="src-sym">,</span>&nbsp;<span class="src-str">')'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'{'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'}'</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1895"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">use_classes</span>&nbsp;&amp;&amp;&nbsp;isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'BRACKETS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1896"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'CACHE_BRACKET_REPLACE'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a1897"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'&lt;|&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'BRACKETS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;&gt;&amp;#91;|&gt;'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1898"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'&lt;|&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'BRACKETS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;&gt;&amp;#93;|&gt;'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1899"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'&lt;|&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'BRACKETS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;&gt;&amp;#40;|&gt;'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1900"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'&lt;|&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'BRACKETS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;&gt;&amp;#41;|&gt;'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1901"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'&lt;|&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'BRACKETS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;&gt;&amp;#123;|&gt;'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1902"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'&lt;|&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'BRACKETS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;&gt;&amp;#125;|&gt;'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1903"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1904"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1905"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1906"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'CACHE_BRACKET_REPLACE'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a1907"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'&lt;|&nbsp;class=&quot;br0&quot;&gt;&amp;#91;|&gt;'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1908"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'&lt;|&nbsp;class=&quot;br0&quot;&gt;&amp;#93;|&gt;'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1909"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'&lt;|&nbsp;class=&quot;br0&quot;&gt;&amp;#40;|&gt;'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1910"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'&lt;|&nbsp;class=&quot;br0&quot;&gt;&amp;#41;|&gt;'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1911"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'&lt;|&nbsp;class=&quot;br0&quot;&gt;&amp;#123;|&gt;'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1912"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'&lt;|&nbsp;class=&quot;br0&quot;&gt;&amp;#125;|&gt;'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1913"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1914"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1915"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1916"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1917"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Build&nbsp;the&nbsp;parse&nbsp;cache&nbsp;needed&nbsp;to&nbsp;highlight&nbsp;numbers&nbsp;appropriate</span></span></div></li>
+<li><div class="src-line"><a name="a1918"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1919"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Check&nbsp;if&nbsp;the&nbsp;style&nbsp;rearrangements&nbsp;have&nbsp;been&nbsp;processed&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a1920"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//This&nbsp;also&nbsp;does&nbsp;some&nbsp;preprocessing&nbsp;to&nbsp;check&nbsp;which&nbsp;style&nbsp;groups&nbsp;are&nbsp;useable&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a1921"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-sym">!</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'NUMBERS_CACHE'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1922"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">build_style_cache</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1923"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1924"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1925"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Number&nbsp;format&nbsp;specification</span></span></div></li>
+<li><div class="src-line"><a name="a1926"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//All&nbsp;this&nbsp;formats&nbsp;are&nbsp;matched&nbsp;case-insensitively!</span></span></div></li>
+<li><div class="src-line"><a name="a1927"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">static</span>&nbsp;<span class="src-var">$numbers_format</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a1928"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">GESHI_NUMBER_INT_BASIC</span>&nbsp;=&gt;</span></div></li>
+<li><div class="src-line"><a name="a1929"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'(?&lt;![0-9a-z_\.%])(?&lt;![\d\.]e[+\-])([1-9]\d*?|0)(?![0-9a-z\.])'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1930"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">GESHI_NUMBER_INT_CSTYLE</span>&nbsp;=&gt;</span></div></li>
+<li><div class="src-line"><a name="a1931"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'(?&lt;![0-9a-z_\.%])(?&lt;![\d\.]e[+\-])([1-9]\d*?|0)l(?![0-9a-z\.])'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1932"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">GESHI_NUMBER_BIN_SUFFIX</span>&nbsp;=&gt;</span></div></li>
+<li><div class="src-line"><a name="a1933"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'(?&lt;![0-9a-z_\.])(?&lt;![\d\.]e[+\-])[01]+?b(?![0-9a-z\.])'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1934"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">GESHI_NUMBER_BIN_PREFIX_PERCENT</span>&nbsp;=&gt;</span></div></li>
+<li><div class="src-line"><a name="a1935"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'(?&lt;![0-9a-z_\.%])(?&lt;![\d\.]e[+\-])%[01]+?(?![0-9a-z\.])'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1936"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">GESHI_NUMBER_BIN_PREFIX_0B</span>&nbsp;=&gt;</span></div></li>
+<li><div class="src-line"><a name="a1937"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'(?&lt;![0-9a-z_\.%])(?&lt;![\d\.]e[+\-])0b[01]+?(?![0-9a-z\.])'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1938"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">GESHI_NUMBER_OCT_PREFIX</span>&nbsp;=&gt;</span></div></li>
+<li><div class="src-line"><a name="a1939"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'(?&lt;![0-9a-z_\.])(?&lt;![\d\.]e[+\-])0[0-7]+?(?![0-9a-z\.])'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1940"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">GESHI_NUMBER_OCT_SUFFIX</span>&nbsp;=&gt;</span></div></li>
+<li><div class="src-line"><a name="a1941"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'(?&lt;![0-9a-z_\.])(?&lt;![\d\.]e[+\-])[0-7]+?o(?![0-9a-z\.])'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1942"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">GESHI_NUMBER_HEX_PREFIX</span>&nbsp;=&gt;</span></div></li>
+<li><div class="src-line"><a name="a1943"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'(?&lt;![0-9a-z_\.])(?&lt;![\d\.]e[+\-])0x[0-9a-f]+?(?![0-9a-z\.])'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1944"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">GESHI_NUMBER_HEX_SUFFIX</span>&nbsp;=&gt;</span></div></li>
+<li><div class="src-line"><a name="a1945"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'(?&lt;![0-9a-z_\.])(?&lt;![\d\.]e[+\-])\d[0-9a-f]*?h(?![0-9a-z\.])'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1946"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">GESHI_NUMBER_FLT_NONSCI</span>&nbsp;=&gt;</span></div></li>
+<li><div class="src-line"><a name="a1947"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'(?&lt;![0-9a-z_\.])(?&lt;![\d\.]e[+\-])\d+?\.\d+?(?![0-9a-z\.])'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1948"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">GESHI_NUMBER_FLT_NONSCI_F</span>&nbsp;=&gt;</span></div></li>
+<li><div class="src-line"><a name="a1949"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'(?&lt;![0-9a-z_\.])(?&lt;![\d\.]e[+\-])(?:\d+?(?:\.\d*?)?|\.\d+?)f(?![0-9a-z\.])'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1950"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">GESHI_NUMBER_FLT_SCI_SHORT</span>&nbsp;=&gt;</span></div></li>
+<li><div class="src-line"><a name="a1951"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'(?&lt;![0-9a-z_\.])(?&lt;![\d\.]e[+\-])\.\d+?(?:e[+\-]?\d+?)?(?![0-9a-z\.])'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a1952"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">GESHI_NUMBER_FLT_SCI_ZERO</span>&nbsp;=&gt;</span></div></li>
+<li><div class="src-line"><a name="a1953"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'(?&lt;![0-9a-z_\.])(?&lt;![\d\.]e[+\-])(?:\d+?(?:\.\d*?)?|\.\d+?)(?:e[+\-]?\d+?)?(?![0-9a-z\.])'</span></span></div></li>
+<li><div class="src-line"><a name="a1954"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1955"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1956"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//At&nbsp;this&nbsp;step&nbsp;we&nbsp;have&nbsp;an&nbsp;associative&nbsp;array&nbsp;with&nbsp;flag&nbsp;groups&nbsp;for&nbsp;a</span></span></div></li>
+<li><div class="src-line"><a name="a1957"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//specific&nbsp;style&nbsp;or&nbsp;an&nbsp;string&nbsp;denoting&nbsp;a&nbsp;regexp&nbsp;given&nbsp;its&nbsp;index.</span></span></div></li>
+<li><div class="src-line"><a name="a1958"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'NUMBERS_RXCACHE'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1959"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'NUMBERS_CACHE'</span><span class="src-sym">]</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$key</span>&nbsp;=&gt;&nbsp;<span class="src-var">$rxdata</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1960"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-id">is_string</span><span class="src-sym">(</span><span class="src-var">$rxdata</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1961"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$regexp</span>&nbsp;=&nbsp;<span class="src-var">$rxdata</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1962"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1963"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//This&nbsp;is&nbsp;a&nbsp;bitfield&nbsp;of&nbsp;number&nbsp;flags&nbsp;to&nbsp;highlight:</span></span></div></li>
+<li><div class="src-line"><a name="a1964"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Build&nbsp;an&nbsp;array,&nbsp;implode&nbsp;them&nbsp;together&nbsp;and&nbsp;make&nbsp;this&nbsp;the&nbsp;actual&nbsp;RX</span></span></div></li>
+<li><div class="src-line"><a name="a1965"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$rxuse</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1966"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">for</span><span class="src-sym">(</span><span class="src-var">$i</span>&nbsp;=&nbsp;<span class="src-num">1</span><span class="src-sym">;</span>&nbsp;<span class="src-var">$i</span>&nbsp;&lt;=&nbsp;<span class="src-var">$rxdata</span><span class="src-sym">;</span>&nbsp;<span class="src-var">$i</span>&lt;&lt;=<span class="src-num">1</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1967"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-var">$rxdata</span>&nbsp;<span class="src-sym">&</span>&nbsp;<span class="src-var">$i</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1968"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$rxuse</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$numbers_format</span><span class="src-sym">[</span><span class="src-var">$i</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1969"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1970"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1971"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$regexp</span>&nbsp;=&nbsp;<a href="http://www.php.net/implode">implode</a><span class="src-sym">(</span><span class="src-str">&quot;|&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$rxuse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1972"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1973"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1974"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">language_data</span><span class="src-sym">[</span><span class="src-str">'NUMBERS_RXCACHE'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=</span></div></li>
+<li><div class="src-line"><a name="a1975"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">"</span></span>/(?&lt;!&lt;\|\/NUM!)(?&lt;!\d\/&gt;)(<span class="src-var">$regexp</span>)(?!\|&gt;)/i<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1976"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1977"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1978"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1979"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">parse_cache_built</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1980"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a1981"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1982"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;/**</span></div></li>
+<li><div class="src-line"><a name="a1983"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Returns&nbsp;the&nbsp;code&nbsp;in&nbsp;$this-&gt;source,&nbsp;highlighted&nbsp;and&nbsp;surrounded&nbsp;by&nbsp;the</span></div></li>
+<li><div class="src-line"><a name="a1984"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;nessecary&nbsp;HTML.</span></div></li>
+<li><div class="src-line"><a name="a1985"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1986"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;This&nbsp;should&nbsp;only&nbsp;be&nbsp;called&nbsp;ONCE,&nbsp;cos&nbsp;it's&nbsp;SLOW!&nbsp;If&nbsp;you&nbsp;want&nbsp;to&nbsp;highlight</span></div></li>
+<li><div class="src-line"><a name="a1987"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;the&nbsp;same&nbsp;source&nbsp;multiple&nbsp;times,&nbsp;you're&nbsp;better&nbsp;off&nbsp;doing&nbsp;a&nbsp;whole&nbsp;lot&nbsp;of</span></div></li>
+<li><div class="src-line"><a name="a1988"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;str_replaces&nbsp;to&nbsp;replace&nbsp;the&nbsp;&amp;lt;span&amp;gt;s</span></div></li>
+<li><div class="src-line"><a name="a1989"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a1990"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@since&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a1991"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a1992"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<span class="src-id">parse_code</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1993"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Start&nbsp;the&nbsp;timer</span></span></div></li>
+<li><div class="src-line"><a name="a1994"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$start_time</span>&nbsp;=&nbsp;<span class="src-id">microtime</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a1995"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a1996"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Firstly,&nbsp;if&nbsp;there&nbsp;is&nbsp;an&nbsp;error,&nbsp;we&nbsp;won't&nbsp;highlight</span></span></div></li>
+<li><div class="src-line"><a name="a1997"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">error</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a1998"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Escape&nbsp;the&nbsp;source&nbsp;for&nbsp;output</span></span></div></li>
+<li><div class="src-line"><a name="a1999"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-var">source</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2000"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2001"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//This&nbsp;fix&nbsp;is&nbsp;related&nbsp;to&nbsp;SF#1923020,&nbsp;but&nbsp;has&nbsp;to&nbsp;be&nbsp;applied&nbsp;regardless&nbsp;of</span></span></div></li>
+<li><div class="src-line"><a name="a2002"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//actually&nbsp;highlighting&nbsp;symbols.</span></span></div></li>
+<li><div class="src-line"><a name="a2003"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;=&nbsp;<span class="src-id">str_replace</span><span class="src-sym">(</span><span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'&lt;SEMI&gt;'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'&lt;PIPE&gt;'</span><span class="src-sym">)</span><span class="src-sym">,</span>&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">';'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'|'</span><span class="src-sym">)</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$result</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2004"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2005"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Timing&nbsp;is&nbsp;irrelevant</span></span></div></li>
+<li><div class="src-line"><a name="a2006"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">set_time</span><span class="src-sym">(</span><span class="src-var">$start_time</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$start_time</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2007"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">finalise</span><span class="src-sym">(</span><span class="src-var">$result</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2008"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-var">$result</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2009"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2010"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2011"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;make&nbsp;sure&nbsp;the&nbsp;parse&nbsp;cache&nbsp;is&nbsp;up2date</span></span></div></li>
+<li><div class="src-line"><a name="a2012"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">parse_cache_built</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2013"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">build_parse_cache</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2014"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2015"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2016"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Replace&nbsp;all&nbsp;newlines&nbsp;to&nbsp;a&nbsp;common&nbsp;form.</span></span></div></li>
+<li><div class="src-line"><a name="a2017"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$code</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-str">&quot;\r\n&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-str">&quot;\n&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">source</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2018"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$code</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-str">&quot;\r&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-str">&quot;\n&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$code</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2019"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2020"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Add&nbsp;spaces&nbsp;for&nbsp;regular&nbsp;expression&nbsp;matching&nbsp;and&nbsp;line&nbsp;numbers</span></span></div></li>
+<li><div class="src-line"><a name="a2021"></a></span><span class="src-str"><span class="src-comm">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$code&nbsp;=&nbsp;&quot;\n&quot;&nbsp;.&nbsp;$code&nbsp;.&nbsp;&quot;\n&quot;;</span></span></div></li>
+<li><div class="src-line"><a name="a2022"></a></span><span class="src-str"><span class="src-comm"></span></span></div></li>
+<li><div class="src-line"><a name="a2023"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Initialise&nbsp;various&nbsp;stuff</span></span></div></li>
+<li><div class="src-line"><a name="a2024"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$length</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$code</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2025"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$COMMENT_MATCHED</span>&nbsp;&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2026"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;&nbsp;&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2027"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$endresult</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2028"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2029"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;&quot;Important&quot;&nbsp;selections&nbsp;are&nbsp;handled&nbsp;like&nbsp;multiline&nbsp;comments</span></span></div></li>
+<li><div class="src-line"><a name="a2030"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;@todo&nbsp;GET&nbsp;RID&nbsp;OF&nbsp;THIS&nbsp;SHIZ</span></span></div></li>
+<li><div class="src-line"><a name="a2031"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodenable_important_blocks">enable_important_blocks</a><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2032"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'COMMENT_MULTI'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_START_IMPORTANT&quot;&gt;GESHI_START_IMPORTANT&lt;/a&gt;</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_END_IMPORTANT&quot;&gt;GESHI_END_IMPORTANT&lt;/a&gt;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2033"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2034"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2035"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">strict_mode</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2036"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Break&nbsp;the&nbsp;source&nbsp;into&nbsp;bits.&nbsp;Each&nbsp;bit&nbsp;will&nbsp;be&nbsp;a&nbsp;portion&nbsp;of&nbsp;the&nbsp;code</span></span></div></li>
+<li><div class="src-line"><a name="a2037"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;within&nbsp;script&nbsp;delimiters&nbsp;-&nbsp;for&nbsp;example,&nbsp;HTML&nbsp;between&nbsp;&lt;&nbsp;and&nbsp;&gt;</span></span></div></li>
+<li><div class="src-line"><a name="a2038"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$k</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2039"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parts</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2040"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$matches</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2041"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_match_pointer</span>&nbsp;=&nbsp;<span class="src-id">null</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2042"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;we&nbsp;use&nbsp;a&nbsp;copy&nbsp;to&nbsp;unset&nbsp;delimiters&nbsp;on&nbsp;demand&nbsp;(when&nbsp;they&nbsp;are&nbsp;not&nbsp;found)</span></span></div></li>
+<li><div class="src-line"><a name="a2043"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$delim_copy</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'SCRIPT_DELIMITERS'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2044"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$i</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2045"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">while</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$i</span>&nbsp;<&nbsp;<span class="src-var">$length</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2046"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_match_pos</span>&nbsp;=&nbsp;<span class="src-var">$length</span>&nbsp;+&nbsp;<span class="src-num">1</span><span class="src-sym">;</span>&nbsp;<span class="src-comm">//&nbsp;never&nbsp;true</span></span></div></li>
+<li><div class="src-line"><a name="a2047"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$delim_copy</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$dk</span>&nbsp;=&gt;&nbsp;<span class="src-var">$delimiters</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2048"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><a href="http://www.php.net/is_array">is_array</a><span class="src-sym">(</span><span class="src-var">$delimiters</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2049"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$delimiters</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$open</span>&nbsp;=&gt;&nbsp;<span class="src-var">$close</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2050"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;make&nbsp;sure&nbsp;the&nbsp;cache&nbsp;is&nbsp;setup&nbsp;properly</span></span></div></li>
+<li><div class="src-line"><a name="a2051"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span>isset<span class="src-sym">(</span><span class="src-var">$matches</span><span class="src-sym">[</span><span class="src-var">$dk</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$open</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2052"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$matches</span><span class="src-sym">[</span><span class="src-var">$dk</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$open</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a2053"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'next_match'</span>&nbsp;=&gt;&nbsp;-<span class="src-num">1</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2054"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'dk'</span>&nbsp;=&gt;&nbsp;<span class="src-var">$dk</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2055"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2056"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'open'</span>&nbsp;=&gt;&nbsp;<span class="src-var">$open</span><span class="src-sym">,</span>&nbsp;<span class="src-comm">//&nbsp;needed&nbsp;for&nbsp;grouping&nbsp;of&nbsp;adjacent&nbsp;code&nbsp;blocks&nbsp;(see&nbsp;below)</span></span></div></li>
+<li><div class="src-line"><a name="a2057"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'open_strlen'</span>&nbsp;=&gt;&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$open</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2058"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2059"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'close'</span>&nbsp;=&gt;&nbsp;<span class="src-var">$close</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2060"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'close_strlen'</span>&nbsp;=&gt;&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$close</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2061"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2062"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2063"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Get&nbsp;the&nbsp;next&nbsp;little&nbsp;bit&nbsp;for&nbsp;this&nbsp;opening&nbsp;string</span></span></div></li>
+<li><div class="src-line"><a name="a2064"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$matches</span><span class="src-sym">[</span><span class="src-var">$dk</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$open</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'next_match'</span><span class="src-sym">]</span>&nbsp;<&nbsp;<span class="src-var">$i</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2065"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;only&nbsp;find&nbsp;the&nbsp;next&nbsp;pos&nbsp;if&nbsp;it&nbsp;was&nbsp;not&nbsp;already&nbsp;cached</span></span></div></li>
+<li><div class="src-line"><a name="a2066"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$open_pos</span>&nbsp;=&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$code</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$open</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2067"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$open_pos</span>&nbsp;===&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2068"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;no&nbsp;match&nbsp;for&nbsp;this&nbsp;delimiter&nbsp;ever</span></span></div></li>
+<li><div class="src-line"><a name="a2069"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$delim_copy</span><span class="src-sym">[</span><span class="src-var">$dk</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$open</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2070"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2071"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2072"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$matches</span><span class="src-sym">[</span><span class="src-var">$dk</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$open</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'next_match'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$open_pos</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2073"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2074"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$matches</span><span class="src-sym">[</span><span class="src-var">$dk</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$open</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'next_match'</span><span class="src-sym">]</span>&nbsp;<&nbsp;<span class="src-var">$next_match_pos</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2075"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//So&nbsp;we&nbsp;got&nbsp;a&nbsp;new&nbsp;match,&nbsp;update&nbsp;the&nbsp;close_pos</span></span></div></li>
+<li><div class="src-line"><a name="a2076"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$matches</span><span class="src-sym">[</span><span class="src-var">$dk</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$open</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'close_pos'</span><span class="src-sym">]</span>&nbsp;=</span></div></li>
+<li><div class="src-line"><a name="a2077"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$code</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$close</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$matches</span><span class="src-sym">[</span><span class="src-var">$dk</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$open</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'next_match'</span><span class="src-sym">]</span>+<span class="src-num">1</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2078"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2079"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_match_pointer</span>&nbsp;=<span class="src-sym">&</span>&nbsp;<span class="src-var">$matches</span><span class="src-sym">[</span><span class="src-var">$dk</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$open</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2080"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_match_pos</span>&nbsp;=&nbsp;<span class="src-var">$matches</span><span class="src-sym">[</span><span class="src-var">$dk</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$open</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'next_match'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2081"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2082"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2083"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2084"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//So&nbsp;we&nbsp;should&nbsp;match&nbsp;an&nbsp;RegExp&nbsp;as&nbsp;Strict&nbsp;Block&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a2085"></a><span class="src-doc">/**</span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a2086"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;value&nbsp;in&nbsp;$delimiters&nbsp;is&nbsp;expected&nbsp;to&nbsp;be&nbsp;an&nbsp;RegExp</span></div></li>
+<li><div class="src-line"><a name="a2087"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;containing&nbsp;exactly&nbsp;2&nbsp;matching&nbsp;groups:</span></div></li>
+<li><div class="src-line"><a name="a2088"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;-&nbsp;Group&nbsp;1&nbsp;is&nbsp;the&nbsp;opener</span></div></li>
+<li><div class="src-line"><a name="a2089"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;-&nbsp;Group&nbsp;2&nbsp;is&nbsp;the&nbsp;closer</span></div></li>
+<li><div class="src-line"><a name="a2090"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a2091"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-sym">!</span><span class="src-id">GESHI_PHP_PRE_433</span>&nbsp;&amp;&amp;&nbsp;<span class="src-comm">//Needs&nbsp;proper&nbsp;rewrite&nbsp;to&nbsp;work&nbsp;with&nbsp;PHP&nbsp;&gt;=4.3.0;&nbsp;4.3.3&nbsp;is&nbsp;guaranteed&nbsp;to&nbsp;work.</span></span></div></li>
+<li><div class="src-line"><a name="a2092"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/preg_match">preg_match</a><span class="src-sym">(</span><span class="src-var">$delimiters</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$code</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$matches_rx</span><span class="src-sym">,</span>&nbsp;<span class="src-id">PREG_OFFSET_CAPTURE</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2093"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//We&nbsp;got&nbsp;a&nbsp;match&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a2094"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$matches</span><span class="src-sym">[</span><span class="src-var">$dk</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a2095"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'next_match'</span>&nbsp;=&gt;&nbsp;<span class="src-var">$matches_rx</span><span class="src-sym">[</span><span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2096"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'dk'</span>&nbsp;=&gt;&nbsp;<span class="src-var">$dk</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2097"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2098"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'close_strlen'</span>&nbsp;=&gt;&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$matches_rx</span><span class="src-sym">[</span><span class="src-num">2</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2099"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'close_pos'</span>&nbsp;=&gt;&nbsp;<span class="src-var">$matches_rx</span><span class="src-sym">[</span><span class="src-num">2</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2100"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2101"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2102"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;no&nbsp;match&nbsp;for&nbsp;this&nbsp;delimiter&nbsp;ever</span></span></div></li>
+<li><div class="src-line"><a name="a2103"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$delim_copy</span><span class="src-sym">[</span><span class="src-var">$dk</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2104"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2105"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2106"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2107"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$matches</span><span class="src-sym">[</span><span class="src-var">$dk</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'next_match'</span><span class="src-sym">]</span>&nbsp;&lt;=&nbsp;<span class="src-var">$next_match_pos</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2108"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_match_pointer</span>&nbsp;=<span class="src-sym">&</span>&nbsp;<span class="src-var">$matches</span><span class="src-sym">[</span><span class="src-var">$dk</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2109"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_match_pos</span>&nbsp;=&nbsp;<span class="src-var">$matches</span><span class="src-sym">[</span><span class="src-var">$dk</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'next_match'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2110"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2111"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2112"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2113"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;non-highlightable&nbsp;text</span></span></div></li>
+<li><div class="src-line"><a name="a2114"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parts</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a2115"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-num">1</span>&nbsp;=&gt;&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$code</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$next_match_pos</span>&nbsp;-&nbsp;<span class="src-var">$i</span><span class="src-sym">)</span></span></div></li>
+<li><div class="src-line"><a name="a2116"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2117"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++<span class="src-var">$k</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2118"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2119"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$next_match_pos</span>&nbsp;>&nbsp;<span class="src-var">$length</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2120"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;out&nbsp;of&nbsp;bounds&nbsp;means&nbsp;no&nbsp;next&nbsp;match&nbsp;was&nbsp;found</span></span></div></li>
+<li><div class="src-line"><a name="a2121"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">break</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2122"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2123"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2124"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;highlightable&nbsp;code</span></span></div></li>
+<li><div class="src-line"><a name="a2125"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parts</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$next_match_pointer</span><span class="src-sym">[</span><span class="src-str">'dk'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2126"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2127"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Only&nbsp;combine&nbsp;for&nbsp;non-rx&nbsp;script&nbsp;blocks</span></span></div></li>
+<li><div class="src-line"><a name="a2128"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><a href="http://www.php.net/is_array">is_array</a><span class="src-sym">(</span><span class="src-var">$delim_copy</span><span class="src-sym">[</span><span class="src-var">$next_match_pointer</span><span class="src-sym">[</span><span class="src-str">'dk'</span><span class="src-sym">]]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2129"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;group&nbsp;adjacent&nbsp;script&nbsp;blocks,&nbsp;e.g.&nbsp;&lt;foobar&gt;&lt;asdf&gt;&nbsp;should&nbsp;be&nbsp;one&nbsp;block,&nbsp;not&nbsp;three!</span></span></div></li>
+<li><div class="src-line"><a name="a2130"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$i</span>&nbsp;=&nbsp;<span class="src-var">$next_match_pos</span>&nbsp;+&nbsp;<span class="src-var">$next_match_pointer</span><span class="src-sym">[</span><span class="src-str">'open_strlen'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2131"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">while</span>&nbsp;<span class="src-sym">(</span><span class="src-id">true</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2132"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$close_pos</span>&nbsp;=&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$code</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$next_match_pointer</span><span class="src-sym">[</span><span class="src-str">'close'</span><span class="src-sym">]</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2133"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$close_pos</span>&nbsp;==&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2134"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">break</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2135"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2136"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$i</span>&nbsp;=&nbsp;<span class="src-var">$close_pos</span>&nbsp;+&nbsp;<span class="src-var">$next_match_pointer</span><span class="src-sym">[</span><span class="src-str">'close_strlen'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2137"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$i</span>&nbsp;==&nbsp;<span class="src-var">$length</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2138"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">break</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2139"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2140"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$code</span><span class="src-sym">[</span><span class="src-var">$i</span><span class="src-sym">]</span>&nbsp;==&nbsp;<span class="src-var">$next_match_pointer</span><span class="src-sym">[</span><span class="src-str">'open'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;&amp;&amp;&nbsp;<span class="src-sym">(</span><span class="src-var">$next_match_pointer</span><span class="src-sym">[</span><span class="src-str">'open_strlen'</span><span class="src-sym">]</span>&nbsp;==&nbsp;<span class="src-num">1</span>&nbsp;||</span></div></li>
+<li><div class="src-line"><a name="a2141"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$code</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$next_match_pointer</span><span class="src-sym">[</span><span class="src-str">'open_strlen'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;==&nbsp;<span class="src-var">$next_match_pointer</span><span class="src-sym">[</span><span class="src-str">'open'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2142"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;merge&nbsp;adjacent&nbsp;but&nbsp;make&nbsp;sure&nbsp;we&nbsp;don't&nbsp;merge&nbsp;things&nbsp;like&nbsp;&lt;tag&gt;&lt;!--&nbsp;comment&nbsp;--&gt;</span></span></div></li>
+<li><div class="src-line"><a name="a2143"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$matches</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$submatches</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2144"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$submatches</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$match</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2145"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$match</span><span class="src-sym">[</span><span class="src-str">'next_match'</span><span class="src-sym">]</span>&nbsp;==&nbsp;<span class="src-var">$i</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2146"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;a&nbsp;different&nbsp;block&nbsp;already&nbsp;matches&nbsp;here!</span></span></div></li>
+<li><div class="src-line"><a name="a2147"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">break</span>&nbsp;<span class="src-num">3</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2148"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2149"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2150"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2151"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2152"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">break</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2153"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2154"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2155"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2156"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$close_pos</span>&nbsp;=&nbsp;<span class="src-var">$next_match_pointer</span><span class="src-sym">[</span><span class="src-str">'close_pos'</span><span class="src-sym">]</span>&nbsp;+&nbsp;<span class="src-var">$next_match_pointer</span><span class="src-sym">[</span><span class="src-str">'close_strlen'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2157"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$i</span>&nbsp;=&nbsp;<span class="src-var">$close_pos</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2158"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2159"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2160"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$close_pos</span>&nbsp;===&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2161"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;no&nbsp;closing&nbsp;delimiter&nbsp;found!</span></span></div></li>
+<li><div class="src-line"><a name="a2162"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parts</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">1</span><span class="src-sym">]</span>&nbsp;=&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$code</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$next_match_pos</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2163"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++<span class="src-var">$k</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2164"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">break</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2165"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2166"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parts</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">1</span><span class="src-sym">]</span>&nbsp;=&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$code</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$next_match_pos</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span>&nbsp;-&nbsp;<span class="src-var">$next_match_pos</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2167"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++<span class="src-var">$k</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2168"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2169"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2170"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$delim_copy</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$next_match_pointer</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$next_match_pos</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$matches</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2171"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$num_parts</span>&nbsp;=&nbsp;<span class="src-var">$k</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2172"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2173"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$num_parts</span>&nbsp;==&nbsp;<span class="src-num">1</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">strict_mode</span>&nbsp;==&nbsp;<span class="src-id">GESHI_MAYBE</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2174"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;when&nbsp;we&nbsp;have&nbsp;only&nbsp;one&nbsp;part,&nbsp;we&nbsp;don't&nbsp;have&nbsp;anything&nbsp;to&nbsp;highlight&nbsp;at&nbsp;all.</span></span></div></li>
+<li><div class="src-line"><a name="a2175"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;if&nbsp;we&nbsp;have&nbsp;a&nbsp;&quot;maybe&quot;&nbsp;strict&nbsp;language,&nbsp;this&nbsp;should&nbsp;be&nbsp;handled&nbsp;as&nbsp;highlightable&nbsp;code</span></span></div></li>
+<li><div class="src-line"><a name="a2176"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parts</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a2177"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-num">0</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a2178"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-num">0</span>&nbsp;=&gt;&nbsp;<span class="src-str">''</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2179"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-num">1</span>&nbsp;=&gt;&nbsp;<span class="src-str">''</span></span></div></li>
+<li><div class="src-line"><a name="a2180"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2181"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-num">1</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a2182"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-num">0</span>&nbsp;=&gt;&nbsp;<span class="src-id">null</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2183"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-num">1</span>&nbsp;=&gt;&nbsp;<span class="src-var">$parts</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">1</span><span class="src-sym">]</span></span></div></li>
+<li><div class="src-line"><a name="a2184"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span></span></div></li>
+<li><div class="src-line"><a name="a2185"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2186"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$num_parts</span>&nbsp;=&nbsp;<span class="src-num">2</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2187"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2188"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2189"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2190"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Not&nbsp;strict&nbsp;mode&nbsp;-&nbsp;simply&nbsp;dump&nbsp;the&nbsp;source&nbsp;into</span></span></div></li>
+<li><div class="src-line"><a name="a2191"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;the&nbsp;array&nbsp;at&nbsp;index&nbsp;1&nbsp;(the&nbsp;first&nbsp;highlightable&nbsp;block)</span></span></div></li>
+<li><div class="src-line"><a name="a2192"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parts</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a2193"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-num">0</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a2194"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-num">0</span>&nbsp;=&gt;&nbsp;<span class="src-str">''</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2195"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-num">1</span>&nbsp;=&gt;&nbsp;<span class="src-str">''</span></span></div></li>
+<li><div class="src-line"><a name="a2196"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2197"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-num">1</span>&nbsp;=&gt;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a2198"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-num">0</span>&nbsp;=&gt;&nbsp;<span class="src-id">null</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2199"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-num">1</span>&nbsp;=&gt;&nbsp;<span class="src-var">$code</span></span></div></li>
+<li><div class="src-line"><a name="a2200"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span></span></div></li>
+<li><div class="src-line"><a name="a2201"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2202"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$num_parts</span>&nbsp;=&nbsp;<span class="src-num">2</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2203"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2204"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2205"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Unset&nbsp;variables&nbsp;we&nbsp;won't&nbsp;need&nbsp;any&nbsp;longer</span></span></div></li>
+<li><div class="src-line"><a name="a2206"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$code</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2207"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2208"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Preload&nbsp;some&nbsp;repeatedly&nbsp;used&nbsp;values&nbsp;regarding&nbsp;hardquotes&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a2209"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$hq</span>&nbsp;=&nbsp;isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'HARDQUOTE'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;?&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'HARDQUOTE'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;:&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2210"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$hq_strlen</span>&nbsp;=&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$hq</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2211"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2212"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Preload&nbsp;if&nbsp;line&nbsp;numbers&nbsp;are&nbsp;to&nbsp;be&nbsp;generated&nbsp;afterwards</span></span></div></li>
+<li><div class="src-line"><a name="a2213"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Added&nbsp;a&nbsp;check&nbsp;if&nbsp;line&nbsp;breaks&nbsp;should&nbsp;be&nbsp;forced&nbsp;even&nbsp;without&nbsp;line&nbsp;numbers,&nbsp;fixes&nbsp;SF#1727398</span></span></div></li>
+<li><div class="src-line"><a name="a2214"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$check_linenumbers</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers</span>&nbsp;!=&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_NO_LINE_NUMBERS&quot;&gt;GESHI_NO_LINE_NUMBERS&lt;/a&gt;</span>&nbsp;||</span></div></li>
+<li><div class="src-line"><a name="a2215"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">!</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">highlight_extra_lines</span><span class="src-sym">)</span>&nbsp;||&nbsp;<span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">allow_multiline_span</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2216"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2217"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//preload&nbsp;the&nbsp;escape&nbsp;char&nbsp;for&nbsp;faster&nbsp;checking&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a2218"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$escaped_escape_char</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2219"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2220"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;this&nbsp;is&nbsp;used&nbsp;for&nbsp;single-line&nbsp;comments</span></span></div></li>
+<li><div class="src-line"><a name="a2221"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$sc_disallowed_before</span>&nbsp;=&nbsp;<span class="src-str">&quot;&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2222"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$sc_disallowed_after</span>&nbsp;=&nbsp;<span class="src-str">&quot;&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2223"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2224"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2225"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2226"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'DISALLOWED_BEFORE'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2227"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$sc_disallowed_before</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'DISALLOWED_BEFORE'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2228"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2229"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'DISALLOWED_AFTER'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2230"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$sc_disallowed_after</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'DISALLOWED_AFTER'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2231"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2232"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2233"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2234"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2235"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Fix&nbsp;for&nbsp;SF#1932083:&nbsp;Multichar&nbsp;Quotemarks&nbsp;unsupported</span></span></div></li>
+<li><div class="src-line"><a name="a2236"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$is_string_starter</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2237"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'STRINGS'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2238"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'QUOTEMARKS'</span><span class="src-sym">]</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$quotemark</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2239"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span>isset<span class="src-sym">(</span><span class="src-var">$is_string_starter</span><span class="src-sym">[</span><span class="src-var">$quotemark</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2240"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$is_string_starter</span><span class="src-sym">[</span><span class="src-var">$quotemark</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]]</span>&nbsp;=&nbsp;(string)<span class="src-var">$quotemark</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2241"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/is_string">is_string</a><span class="src-sym">(</span><span class="src-var">$is_string_starter</span><span class="src-sym">[</span><span class="src-var">$quotemark</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2242"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$is_string_starter</span><span class="src-sym">[</span><span class="src-var">$quotemark</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]]</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a2243"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$is_string_starter</span><span class="src-sym">[</span><span class="src-var">$quotemark</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]]</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2244"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$quotemark</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2245"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2246"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$is_string_starter</span><span class="src-sym">[</span><span class="src-var">$quotemark</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]]</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$quotemark</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2247"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2248"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2249"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2250"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2251"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Now&nbsp;we&nbsp;go&nbsp;through&nbsp;each&nbsp;part.&nbsp;We&nbsp;know&nbsp;that&nbsp;even-indexed&nbsp;parts&nbsp;are</span></span></div></li>
+<li><div class="src-line"><a name="a2252"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;code&nbsp;that&nbsp;shouldn't&nbsp;be&nbsp;highlighted,&nbsp;and&nbsp;odd-indexed&nbsp;parts&nbsp;should</span></span></div></li>
+<li><div class="src-line"><a name="a2253"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;be&nbsp;highlighted</span></span></div></li>
+<li><div class="src-line"><a name="a2254"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">for</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$key</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span>&nbsp;<span class="src-var">$key</span>&nbsp;<&nbsp;<span class="src-var">$num_parts</span><span class="src-sym">;</span>&nbsp;++<span class="src-var">$key</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2255"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$STRICTATTRS</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2256"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2257"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;If&nbsp;this&nbsp;block&nbsp;should&nbsp;be&nbsp;highlighted...</span></span></div></li>
+<li><div class="src-line"><a name="a2258"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-sym">(</span><span class="src-var">$key</span>&nbsp;<span class="src-sym">&</span>&nbsp;<span class="src-num">1</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2259"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Else&nbsp;not&nbsp;a&nbsp;block&nbsp;to&nbsp;highlight</span></span></div></li>
+<li><div class="src-line"><a name="a2260"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$endresult</span>&nbsp;.=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$parts</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2261"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$parts</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2262"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2263"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2264"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2265"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2266"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$part</span>&nbsp;=&nbsp;<span class="src-var">$parts</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2267"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2268"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$highlight_part</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2269"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">strict_mode</span>&nbsp;&amp;&amp;&nbsp;<span class="src-sym">!</span><a href="http://www.php.net/is_null">is_null</a><span class="src-sym">(</span><span class="src-var">$parts</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2270"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;get&nbsp;the&nbsp;class&nbsp;key&nbsp;for&nbsp;this&nbsp;block&nbsp;of&nbsp;code</span></span></div></li>
+<li><div class="src-line"><a name="a2271"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$script_key</span>&nbsp;=&nbsp;<span class="src-var">$parts</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2272"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$highlight_part</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'HIGHLIGHT_STRICT_BLOCK'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$script_key</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2273"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'SCRIPT'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$script_key</span><span class="src-sym">]</span>&nbsp;!=&nbsp;<span class="src-str">''</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a2274"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'SCRIPT'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2275"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Add&nbsp;a&nbsp;span&nbsp;element&nbsp;around&nbsp;the&nbsp;source&nbsp;to</span></span></div></li>
+<li><div class="src-line"><a name="a2276"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;highlight&nbsp;the&nbsp;overall&nbsp;source&nbsp;block</span></span></div></li>
+<li><div class="src-line"><a name="a2277"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a2278"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'SCRIPT'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$script_key</span><span class="src-sym">]</span>&nbsp;!=&nbsp;<span class="src-str">''</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2279"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'SCRIPT'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$script_key</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2280"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2281"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;sc'</span>&nbsp;.&nbsp;<span class="src-var">$script_key</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2282"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2283"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;.=&nbsp;<span class="src-str">"</span></span>&lt;span<span class="src-var">$attributes</span>&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2284"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$STRICTATTRS</span>&nbsp;=&nbsp;<span class="src-var">$attributes</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2285"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2286"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2287"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2288"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$highlight_part</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2289"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Now,&nbsp;highlight&nbsp;the&nbsp;code&nbsp;in&nbsp;this&nbsp;block.&nbsp;This&nbsp;code</span></span></div></li>
+<li><div class="src-line"><a name="a2290"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;is&nbsp;really&nbsp;the&nbsp;engine&nbsp;of&nbsp;GeSHi&nbsp;(along&nbsp;with&nbsp;the&nbsp;method</span></span></div></li>
+<li><div class="src-line"><a name="a2291"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;parse_non_string_part).</span></span></div></li>
+<li><div class="src-line"><a name="a2292"></a></span><span class="src-str"><span class="src-comm"></span></span></div></li>
+<li><div class="src-line"><a name="a2293"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;cache&nbsp;comment&nbsp;regexps&nbsp;incrementally</span></span></div></li>
+<li><div class="src-line"><a name="a2294"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_comment_regexp_key</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2295"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_comment_regexp_pos</span>&nbsp;=&nbsp;-<span class="src-num">1</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2296"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_comment_multi_pos</span>&nbsp;=&nbsp;-<span class="src-num">1</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2297"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_comment_single_pos</span>&nbsp;=&nbsp;-<span class="src-num">1</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2298"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$comment_regexp_cache_per_key</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2299"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$comment_multi_cache_per_key</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2300"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$comment_single_cache_per_key</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2301"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_open_comment_multi</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2302"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_comment_single_key</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2303"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$escape_regexp_cache_per_key</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2304"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_escape_regexp_key</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2305"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_escape_regexp_pos</span>&nbsp;=&nbsp;-<span class="src-num">1</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2306"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2307"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$length</span>&nbsp;=&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2308"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">for</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$i</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span>&nbsp;<span class="src-var">$i</span>&nbsp;<&nbsp;<span class="src-var">$length</span><span class="src-sym">;</span>&nbsp;++<span class="src-var">$i</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2309"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Get&nbsp;the&nbsp;next&nbsp;char</span></span></div></li>
+<li><div class="src-line"><a name="a2310"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$char</span>&nbsp;=&nbsp;<span class="src-var">$part</span><span class="src-sym">[</span><span class="src-var">$i</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2311"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$char_len</span>&nbsp;=&nbsp;<span class="src-num">1</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2312"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2313"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;update&nbsp;regexp&nbsp;comment&nbsp;cache&nbsp;if&nbsp;needed</span></span></div></li>
+<li><div class="src-line"><a name="a2314"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'COMMENT_REGEXP'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$next_comment_regexp_pos</span>&nbsp;<&nbsp;<span class="src-var">$i</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2315"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_comment_regexp_pos</span>&nbsp;=&nbsp;<span class="src-var">$length</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2316"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'COMMENT_REGEXP'</span><span class="src-sym">]</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$comment_key</span>&nbsp;=&gt;&nbsp;<span class="src-var">$regexp</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2317"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$match_i</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2318"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$comment_regexp_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$comment_key</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a2319"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span><span class="src-var">$comment_regexp_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$comment_key</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'pos'</span><span class="src-sym">]</span>&nbsp;&gt;=&nbsp;<span class="src-var">$i</span>&nbsp;||</span></div></li>
+<li><div class="src-line"><a name="a2320"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$comment_regexp_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$comment_key</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'pos'</span><span class="src-sym">]</span>&nbsp;===&nbsp;<span class="src-id">false</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2321"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;we&nbsp;have&nbsp;already&nbsp;matched&nbsp;something</span></span></div></li>
+<li><div class="src-line"><a name="a2322"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$comment_regexp_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$comment_key</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'pos'</span><span class="src-sym">]</span>&nbsp;===&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2323"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;this&nbsp;comment&nbsp;is&nbsp;never&nbsp;matched</span></span></div></li>
+<li><div class="src-line"><a name="a2324"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2325"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2326"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$match_i</span>&nbsp;=&nbsp;<span class="src-var">$comment_regexp_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$comment_key</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'pos'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2327"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a2328"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//This&nbsp;is&nbsp;to&nbsp;allow&nbsp;use&nbsp;of&nbsp;the&nbsp;offset&nbsp;parameter&nbsp;in&nbsp;preg_match&nbsp;and&nbsp;stay&nbsp;as&nbsp;compatible&nbsp;with&nbsp;older&nbsp;PHP&nbsp;versions&nbsp;as&nbsp;possible</span></span></div></li>
+<li><div class="src-line"><a name="a2329"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span><span class="src-id">GESHI_PHP_PRE_433</span>&nbsp;&amp;&amp;&nbsp;<a href="http://www.php.net/preg_match">preg_match</a><span class="src-sym">(</span><span class="src-var">$regexp</span><span class="src-sym">,</span>&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span><span class="src-sym">)</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$match</span><span class="src-sym">,</span>&nbsp;<span class="src-id">PREG_OFFSET_CAPTURE</span><span class="src-sym">))</span>&nbsp;||</span></div></li>
+<li><div class="src-line"><a name="a2330"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-id">GESHI_PHP_PRE_433</span>&nbsp;&amp;&amp;&nbsp;<a href="http://www.php.net/preg_match">preg_match</a><span class="src-sym">(</span><span class="src-var">$regexp</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$match</span><span class="src-sym">,</span>&nbsp;<span class="src-id">PREG_OFFSET_CAPTURE</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span><span class="src-sym">))</span></span></div></li>
+<li><div class="src-line"><a name="a2331"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2332"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$match_i</span>&nbsp;=&nbsp;<span class="src-var">$match</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2333"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-id">GESHI_PHP_PRE_433</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2334"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$match_i</span>&nbsp;+=&nbsp;<span class="src-var">$i</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2335"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2336"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2337"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$comment_regexp_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$comment_key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a2338"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'key'</span>&nbsp;=&gt;&nbsp;<span class="src-var">$comment_key</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2339"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'length'</span>&nbsp;=&gt;&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$match</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2340"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'pos'</span>&nbsp;=&gt;&nbsp;<span class="src-var">$match_i</span></span></div></li>
+<li><div class="src-line"><a name="a2341"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2342"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2343"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$comment_regexp_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$comment_key</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'pos'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2344"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2345"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2346"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2347"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$match_i</span>&nbsp;!==&nbsp;<span class="src-id">false</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$match_i</span>&nbsp;<&nbsp;<span class="src-var">$next_comment_regexp_pos</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2348"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_comment_regexp_pos</span>&nbsp;=&nbsp;<span class="src-var">$match_i</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2349"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_comment_regexp_key</span>&nbsp;=&nbsp;<span class="src-var">$comment_key</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2350"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$match_i</span>&nbsp;===&nbsp;<span class="src-var">$i</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2351"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">break</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2352"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2353"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2354"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2355"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2356"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2357"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string_started</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2358"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2359"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$is_string_starter</span><span class="src-sym">[</span><span class="src-var">$char</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2360"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Possibly&nbsp;the&nbsp;start&nbsp;of&nbsp;a&nbsp;new&nbsp;string&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a2361"></a></span><span class="src-str"><span class="src-comm"></span></span></div></li>
+<li><div class="src-line"><a name="a2362"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Check&nbsp;which&nbsp;starter&nbsp;it&nbsp;was&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a2363"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Fix&nbsp;for&nbsp;SF#1932083:&nbsp;Multichar&nbsp;Quotemarks&nbsp;unsupported</span></span></div></li>
+<li><div class="src-line"><a name="a2364"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/is_array">is_array</a><span class="src-sym">(</span><span class="src-var">$is_string_starter</span><span class="src-sym">[</span><span class="src-var">$char</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2365"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$char_new</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2366"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$is_string_starter</span><span class="src-sym">[</span><span class="src-var">$char</span><span class="src-sym">]</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$testchar</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2367"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$testchar</span>&nbsp;===&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span><span class="src-sym">,</span>&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$testchar</span><span class="src-sym">))</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a2368"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$testchar</span><span class="src-sym">)</span>&nbsp;>&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$char_new</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2369"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$char_new</span>&nbsp;=&nbsp;<span class="src-var">$testchar</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2370"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string_started</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2371"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2372"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2373"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$string_started</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2374"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$char</span>&nbsp;=&nbsp;<span class="src-var">$char_new</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2375"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2376"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2377"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$testchar</span>&nbsp;=&nbsp;<span class="src-var">$is_string_starter</span><span class="src-sym">[</span><span class="src-var">$char</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2378"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$testchar</span>&nbsp;===&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span><span class="src-sym">,</span>&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$testchar</span><span class="src-sym">)))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2379"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$char</span>&nbsp;=&nbsp;<span class="src-var">$testchar</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2380"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string_started</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2381"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2382"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2383"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$char_len</span>&nbsp;=&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$char</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2384"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2385"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2386"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$string_started</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$i</span>&nbsp;!=&nbsp;<span class="src-var">$next_comment_regexp_pos</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2387"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Hand&nbsp;out&nbsp;the&nbsp;correct&nbsp;style&nbsp;information&nbsp;for&nbsp;this&nbsp;string</span></span></div></li>
+<li><div class="src-line"><a name="a2388"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string_key</span>&nbsp;=&nbsp;<a href="http://www.php.net/array_search">array_search</a><span class="src-sym">(</span><span class="src-var">$char</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'QUOTEMARKS'</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2389"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'STRINGS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$string_key</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;||</span></div></li>
+<li><div class="src-line"><a name="a2390"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">!</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$string_key</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2391"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string_key</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2392"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2393"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2394"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;parse&nbsp;the&nbsp;stuff&nbsp;before&nbsp;this</span></span></div></li>
+<li><div class="src-line"><a name="a2395"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;.=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">parse_non_string_part</span><span class="src-sym">(</span><span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2396"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2397"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2398"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2399"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string_attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'STRINGS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$string_key</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2400"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2401"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string_attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;st'</span>.<span class="src-var">$string_key</span>.<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2402"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2403"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2404"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;now&nbsp;handle&nbsp;the&nbsp;string</span></span></div></li>
+<li><div class="src-line"><a name="a2405"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string</span>&nbsp;=&nbsp;<span class="src-str">"</span></span>&lt;span<span class="src-var">$string_attributes</span>&gt;<span class="src-str">&quot;&nbsp;</span><span class="src-str">.&nbsp;<span class="src-id">GeSHi</span><span class="src-sym">::</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$char</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2406"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$start</span>&nbsp;=&nbsp;<span class="src-var">$i</span>&nbsp;+&nbsp;<span class="src-var">$char_len</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2407"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string_open</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2408"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2409"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_REGEXP'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2410"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_escape_regexp_pos</span>&nbsp;=&nbsp;<span class="src-var">$length</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2411"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2412"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2413"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2414"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Get&nbsp;the&nbsp;regular&nbsp;ending&nbsp;pos&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a2415"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$close_pos</span>&nbsp;=&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$char</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$start</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2416"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-id">false</span>&nbsp;===&nbsp;<span class="src-var">$close_pos</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2417"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$close_pos</span>&nbsp;=&nbsp;<span class="src-var">$length</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2418"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2419"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2420"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2421"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;update&nbsp;escape&nbsp;regexp&nbsp;cache&nbsp;if&nbsp;needed</span></span></div></li>
+<li><div class="src-line"><a name="a2422"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_REGEXP'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$next_escape_regexp_pos</span>&nbsp;<&nbsp;<span class="src-var">$start</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2423"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_escape_regexp_pos</span>&nbsp;=&nbsp;<span class="src-var">$length</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2424"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_REGEXP'</span><span class="src-sym">]</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$escape_key</span>&nbsp;=&gt;&nbsp;<span class="src-var">$regexp</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2425"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$match_i</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2426"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$escape_regexp_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$escape_key</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a2427"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span><span class="src-var">$escape_regexp_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$escape_key</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'pos'</span><span class="src-sym">]</span>&nbsp;&gt;=&nbsp;<span class="src-var">$start</span>&nbsp;||</span></div></li>
+<li><div class="src-line"><a name="a2428"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$escape_regexp_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$escape_key</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'pos'</span><span class="src-sym">]</span>&nbsp;===&nbsp;<span class="src-id">false</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2429"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;we&nbsp;have&nbsp;already&nbsp;matched&nbsp;something</span></span></div></li>
+<li><div class="src-line"><a name="a2430"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$escape_regexp_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$escape_key</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'pos'</span><span class="src-sym">]</span>&nbsp;===&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2431"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;this&nbsp;comment&nbsp;is&nbsp;never&nbsp;matched</span></span></div></li>
+<li><div class="src-line"><a name="a2432"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2433"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2434"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$match_i</span>&nbsp;=&nbsp;<span class="src-var">$escape_regexp_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$escape_key</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'pos'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2435"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a2436"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//This&nbsp;is&nbsp;to&nbsp;allow&nbsp;use&nbsp;of&nbsp;the&nbsp;offset&nbsp;parameter&nbsp;in&nbsp;preg_match&nbsp;and&nbsp;stay&nbsp;as&nbsp;compatible&nbsp;with&nbsp;older&nbsp;PHP&nbsp;versions&nbsp;as&nbsp;possible</span></span></div></li>
+<li><div class="src-line"><a name="a2437"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span><span class="src-id">GESHI_PHP_PRE_433</span>&nbsp;&amp;&amp;&nbsp;<a href="http://www.php.net/preg_match">preg_match</a><span class="src-sym">(</span><span class="src-var">$regexp</span><span class="src-sym">,</span>&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$start</span><span class="src-sym">)</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$match</span><span class="src-sym">,</span>&nbsp;<span class="src-id">PREG_OFFSET_CAPTURE</span><span class="src-sym">))</span>&nbsp;||</span></div></li>
+<li><div class="src-line"><a name="a2438"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-id">GESHI_PHP_PRE_433</span>&nbsp;&amp;&amp;&nbsp;<a href="http://www.php.net/preg_match">preg_match</a><span class="src-sym">(</span><span class="src-var">$regexp</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$match</span><span class="src-sym">,</span>&nbsp;<span class="src-id">PREG_OFFSET_CAPTURE</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$start</span><span class="src-sym">))</span></span></div></li>
+<li><div class="src-line"><a name="a2439"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2440"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$match_i</span>&nbsp;=&nbsp;<span class="src-var">$match</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2441"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-id">GESHI_PHP_PRE_433</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2442"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$match_i</span>&nbsp;+=&nbsp;<span class="src-var">$start</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2443"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2444"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2445"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$escape_regexp_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$escape_key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a2446"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'key'</span>&nbsp;=&gt;&nbsp;<span class="src-var">$escape_key</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2447"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'length'</span>&nbsp;=&gt;&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$match</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2448"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'pos'</span>&nbsp;=&gt;&nbsp;<span class="src-var">$match_i</span></span></div></li>
+<li><div class="src-line"><a name="a2449"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2450"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2451"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$escape_regexp_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$escape_key</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'pos'</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2452"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2453"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2454"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2455"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$match_i</span>&nbsp;!==&nbsp;<span class="src-id">false</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$match_i</span>&nbsp;<&nbsp;<span class="src-var">$next_escape_regexp_pos</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2456"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_escape_regexp_pos</span>&nbsp;=&nbsp;<span class="src-var">$match_i</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2457"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_escape_regexp_key</span>&nbsp;=&nbsp;<span class="src-var">$escape_key</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2458"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$match_i</span>&nbsp;===&nbsp;<span class="src-var">$start</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2459"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">break</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2460"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2461"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2462"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2463"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2464"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2465"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Find&nbsp;the&nbsp;next&nbsp;simple&nbsp;escape&nbsp;position</span></span></div></li>
+<li><div class="src-line"><a name="a2466"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-str">''</span>&nbsp;!=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2467"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$simple_escape</span>&nbsp;=&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$start</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2468"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-id">false</span>&nbsp;===&nbsp;<span class="src-var">$simple_escape</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2469"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$simple_escape</span>&nbsp;=&nbsp;<span class="src-var">$length</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2470"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2471"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2472"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$simple_escape</span>&nbsp;=&nbsp;<span class="src-var">$length</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2473"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2474"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2475"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_escape_regexp_pos</span>&nbsp;=&nbsp;<span class="src-var">$length</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2476"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$simple_escape</span>&nbsp;=&nbsp;<span class="src-var">$length</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2477"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2478"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2479"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-var">$simple_escape</span>&nbsp;<&nbsp;<span class="src-var">$next_escape_regexp_pos</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a2480"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$simple_escape</span>&nbsp;<&nbsp;<span class="src-var">$length</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a2481"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$simple_escape</span>&nbsp;<&nbsp;<span class="src-var">$close_pos</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2482"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//The&nbsp;nexxt&nbsp;escape&nbsp;sequence&nbsp;is&nbsp;a&nbsp;simple&nbsp;one&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a2483"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$es_pos</span>&nbsp;=&nbsp;<span class="src-var">$simple_escape</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2484"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2485"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Add&nbsp;the&nbsp;stuff&nbsp;not&nbsp;in&nbsp;the&nbsp;string&nbsp;yet&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a2486"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string</span>&nbsp;.=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$start</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$es_pos</span>&nbsp;-&nbsp;<span class="src-var">$start</span><span class="src-sym">))</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2487"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2488"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Get&nbsp;the&nbsp;style&nbsp;for&nbsp;this&nbsp;escaped&nbsp;char&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a2489"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2490"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$escape_char_attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2491"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2492"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$escape_char_attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;es0&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2493"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2494"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2495"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Add&nbsp;the&nbsp;style&nbsp;for&nbsp;the&nbsp;escape&nbsp;char&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a2496"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string</span>&nbsp;.=&nbsp;<span class="src-str">"</span></span>&lt;span<span class="src-var">$escape_char_attributes</span>&gt;<span class="src-str">&quot;&nbsp;</span><span class="src-str">.</span></div></li>
+<li><div class="src-line"><a name="a2497"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">GeSHi</span><span class="src-sym">::</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2498"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2499"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Get&nbsp;the&nbsp;byte&nbsp;AFTER&nbsp;the&nbsp;ESCAPE_CHAR&nbsp;we&nbsp;just&nbsp;found</span></span></div></li>
+<li><div class="src-line"><a name="a2500"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$es_char</span>&nbsp;=&nbsp;<span class="src-var">$part</span><span class="src-sym">[</span><span class="src-var">$es_pos</span>&nbsp;+&nbsp;<span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2501"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$es_char</span>&nbsp;==&nbsp;<span class="src-str">&quot;\n&quot;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2502"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;don't&nbsp;put&nbsp;a&nbsp;newline&nbsp;around&nbsp;newlines</span></span></div></li>
+<li><div class="src-line"><a name="a2503"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string</span>&nbsp;.=&nbsp;<span class="src-str">&quot;&lt;/span&gt;\n&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2504"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$start</span>&nbsp;=&nbsp;<span class="src-var">$es_pos</span>&nbsp;+&nbsp;<span class="src-num">2</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2505"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/ord">ord</a><span class="src-sym">(</span><span class="src-var">$es_char</span><span class="src-sym">)</span>&nbsp;&gt;=&nbsp;<span class="src-num">128</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2506"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//This&nbsp;is&nbsp;an&nbsp;non-ASCII&nbsp;char&nbsp;(UTF8&nbsp;or&nbsp;single&nbsp;byte)</span></span></div></li>
+<li><div class="src-line"><a name="a2507"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//This&nbsp;code&nbsp;tries&nbsp;to&nbsp;work&nbsp;around&nbsp;SF#2037598&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a2508"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><a href="http://www.php.net/function_exists">function_exists</a><span class="src-sym">(</span><span class="src-str">'mb_substr'</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2509"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$es_char_m</span>&nbsp;=&nbsp;<a href="http://www.php.net/mb_substr">mb_substr</a><span class="src-sym">(</span><a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$es_pos</span>+<span class="src-num">1</span><span class="src-sym">,</span>&nbsp;<span class="src-num">16</span><span class="src-sym">)</span><span class="src-sym">,</span>&nbsp;<span class="src-num">0</span><span class="src-sym">,</span>&nbsp;<span class="src-num">1</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">encoding</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2510"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string</span>&nbsp;.=&nbsp;<span class="src-var">$es_char_m</span>&nbsp;.&nbsp;<span class="src-str">'&lt;/span&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2511"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-id">GESHI_PHP_PRE_433</span>&nbsp;&amp;&amp;&nbsp;<span class="src-str">'utf-8'</span>&nbsp;==&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">encoding</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2512"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><a href="http://www.php.net/preg_match">preg_match</a><span class="src-sym">(</span><span class="src-str">&quot;/[\xC2-\xDF][\x80-\xBF]&quot;</span>.</span></div></li>
+<li><div class="src-line"><a name="a2513"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">&quot;|\xE0[\xA0-\xBF][\x80-\xBF]&quot;</span>.</span></div></li>
+<li><div class="src-line"><a name="a2514"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">&quot;|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}&quot;</span>.</span></div></li>
+<li><div class="src-line"><a name="a2515"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">&quot;|\xED[\x80-\x9F][\x80-\xBF]&quot;</span>.</span></div></li>
+<li><div class="src-line"><a name="a2516"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">&quot;|\xF0[\x90-\xBF][\x80-\xBF]{2}&quot;</span>.</span></div></li>
+<li><div class="src-line"><a name="a2517"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">&quot;|[\xF1-\xF3][\x80-\xBF]{3}&quot;</span>.</span></div></li>
+<li><div class="src-line"><a name="a2518"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">&quot;|\xF4[\x80-\x8F][\x80-\xBF]{2}/s&quot;</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2519"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$es_char_m</span><span class="src-sym">,</span>&nbsp;<span class="src-id">null</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$es_pos</span>&nbsp;+&nbsp;<span class="src-num">1</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2520"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$es_char_m</span>&nbsp;=&nbsp;<span class="src-var">$es_char_m</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2521"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2522"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$es_char_m</span>&nbsp;=&nbsp;<span class="src-var">$es_char</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2523"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2524"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string</span>&nbsp;.=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$es_char_m</span><span class="src-sym">)</span>&nbsp;.&nbsp;<span class="src-str">'&lt;/span&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2525"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2526"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$es_char_m</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$es_char</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2527"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2528"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$start</span>&nbsp;=&nbsp;<span class="src-var">$es_pos</span>&nbsp;+&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$es_char_m</span><span class="src-sym">)</span>&nbsp;+&nbsp;<span class="src-num">1</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2529"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2530"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string</span>&nbsp;.=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$es_char</span><span class="src-sym">)</span>&nbsp;.&nbsp;<span class="src-str">'&lt;/span&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2531"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$start</span>&nbsp;=&nbsp;<span class="src-var">$es_pos</span>&nbsp;+&nbsp;<span class="src-num">2</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2532"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2533"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$next_escape_regexp_pos</span>&nbsp;<&nbsp;<span class="src-var">$length</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a2534"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_escape_regexp_pos</span>&nbsp;<&nbsp;<span class="src-var">$close_pos</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2535"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$es_pos</span>&nbsp;=&nbsp;<span class="src-var">$next_escape_regexp_pos</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2536"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Add&nbsp;the&nbsp;stuff&nbsp;not&nbsp;in&nbsp;the&nbsp;string&nbsp;yet&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a2537"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string</span>&nbsp;.=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$start</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$es_pos</span>&nbsp;-&nbsp;<span class="src-var">$start</span><span class="src-sym">))</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2538"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2539"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Get&nbsp;the&nbsp;key&nbsp;and&nbsp;length&nbsp;of&nbsp;this&nbsp;match&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a2540"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$escape</span>&nbsp;=&nbsp;<span class="src-var">$escape_regexp_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$next_escape_regexp_key</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2541"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$escape_str</span>&nbsp;=&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$es_pos</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$escape</span><span class="src-sym">[</span><span class="src-str">'length'</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2542"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$escape_key</span>&nbsp;=&nbsp;<span class="src-var">$escape</span><span class="src-sym">[</span><span class="src-str">'key'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2543"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2544"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Get&nbsp;the&nbsp;style&nbsp;for&nbsp;this&nbsp;escaped&nbsp;char&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a2545"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2546"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$escape_char_attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$escape_key</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2547"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2548"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$escape_char_attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;es'</span>&nbsp;.&nbsp;<span class="src-var">$escape_key</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2549"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2550"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2551"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Add&nbsp;the&nbsp;style&nbsp;for&nbsp;the&nbsp;escape&nbsp;char&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a2552"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string</span>&nbsp;.=&nbsp;<span class="src-str">"</span></span>&lt;span<span class="src-var">$escape_char_attributes</span>&gt;<span class="src-str">&quot;&nbsp;</span><span class="src-str">.</span></div></li>
+<li><div class="src-line"><a name="a2553"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$escape_str</span><span class="src-sym">)</span>&nbsp;.&nbsp;<span class="src-str">'&lt;/span&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2554"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2555"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$start</span>&nbsp;=&nbsp;<span class="src-var">$es_pos</span>&nbsp;+&nbsp;<span class="src-var">$escape</span><span class="src-sym">[</span><span class="src-str">'length'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2556"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2557"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Copy&nbsp;the&nbsp;remainder&nbsp;of&nbsp;the&nbsp;string&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a2558"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string</span>&nbsp;.=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$start</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$close_pos</span>&nbsp;-&nbsp;<span class="src-var">$start</span>&nbsp;+&nbsp;<span class="src-var">$char_len</span><span class="src-sym">))</span>&nbsp;.&nbsp;<span class="src-str">'&lt;/span&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2559"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$start</span>&nbsp;=&nbsp;<span class="src-var">$close_pos</span>&nbsp;+&nbsp;<span class="src-var">$char_len</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2560"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string_open</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2561"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2562"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">while</span><span class="src-sym">(</span><span class="src-var">$string_open</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2563"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2564"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$check_linenumbers</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2565"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Are&nbsp;line&nbsp;numbers&nbsp;used?&nbsp;If,&nbsp;we&nbsp;should&nbsp;end&nbsp;the&nbsp;string&nbsp;before</span></span></div></li>
+<li><div class="src-line"><a name="a2566"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;the&nbsp;newline&nbsp;and&nbsp;begin&nbsp;it&nbsp;again&nbsp;(so&nbsp;when&nbsp;&lt;li&gt;s&nbsp;are&nbsp;put&nbsp;in&nbsp;the&nbsp;source</span></span></div></li>
+<li><div class="src-line"><a name="a2567"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;remains&nbsp;XHTML&nbsp;compliant)</span></span></div></li>
+<li><div class="src-line"><a name="a2568"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;note&nbsp;to&nbsp;self:&nbsp;This&nbsp;opens&nbsp;up&nbsp;possibility&nbsp;of&nbsp;config&nbsp;files&nbsp;specifying</span></span></div></li>
+<li><div class="src-line"><a name="a2569"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;that&nbsp;languages&nbsp;can/cannot&nbsp;have&nbsp;multiline&nbsp;strings???</span></span></div></li>
+<li><div class="src-line"><a name="a2570"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-str">&quot;\n&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-str">"</span></span>&lt;/span&gt;\n&lt;span<span class="src-var">$string_attributes</span>&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">,</span>&nbsp;<span class="src-var">$string</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2571"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2572"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2573"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;.=&nbsp;<span class="src-var">$string</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2574"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2575"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$i</span>&nbsp;=&nbsp;<span class="src-var">$start</span>&nbsp;-&nbsp;<span class="src-num">1</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2576"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2577"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'STRINGS'</span><span class="src-sym">]</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$hq</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$hq</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;==&nbsp;<span class="src-var">$char</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a2578"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$hq_strlen</span><span class="src-sym">)</span>&nbsp;==&nbsp;<span class="src-var">$hq</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2579"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;The&nbsp;start&nbsp;of&nbsp;a&nbsp;hard&nbsp;quoted&nbsp;string</span></span></div></li>
+<li><div class="src-line"><a name="a2580"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2581"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string_attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'STRINGS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'HARD'</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2582"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$escape_char_attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'HARD'</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2583"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2584"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string_attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;st_h&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2585"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$escape_char_attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;es_h&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2586"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2587"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;parse&nbsp;the&nbsp;stuff&nbsp;before&nbsp;this</span></span></div></li>
+<li><div class="src-line"><a name="a2588"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;.=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">parse_non_string_part</span><span class="src-sym">(</span><span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2589"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2590"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2591"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;now&nbsp;handle&nbsp;the&nbsp;string</span></span></div></li>
+<li><div class="src-line"><a name="a2592"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2593"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2594"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;look&nbsp;for&nbsp;closing&nbsp;quote</span></span></div></li>
+<li><div class="src-line"><a name="a2595"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$start</span>&nbsp;=&nbsp;<span class="src-var">$i</span>&nbsp;+&nbsp;<span class="src-var">$hq_strlen</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2596"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">while</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$close_pos</span>&nbsp;=&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'HARDQUOTE'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$start</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2597"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$start</span>&nbsp;=&nbsp;<span class="src-var">$close_pos</span>&nbsp;+&nbsp;<span class="src-num">1</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2598"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$part</span><span class="src-sym">[</span><span class="src-var">$close_pos</span>&nbsp;-&nbsp;<span class="src-num">1</span><span class="src-sym">]</span>&nbsp;==&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2599"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;make&nbsp;sure&nbsp;this&nbsp;quote&nbsp;is&nbsp;not&nbsp;escaped</span></span></div></li>
+<li><div class="src-line"><a name="a2600"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'HARDESCAPE'</span><span class="src-sym">]</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$hardescape</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2601"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$close_pos</span>&nbsp;-&nbsp;<span class="src-num">1</span><span class="src-sym">,</span>&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$hardescape</span><span class="src-sym">))</span>&nbsp;==&nbsp;<span class="src-var">$hardescape</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2602"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;check&nbsp;wether&nbsp;this&nbsp;quote&nbsp;is&nbsp;escaped&nbsp;or&nbsp;if&nbsp;it&nbsp;is&nbsp;something&nbsp;like&nbsp;'\\'</span></span></div></li>
+<li><div class="src-line"><a name="a2603"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$escape_char_pos</span>&nbsp;=&nbsp;<span class="src-var">$close_pos</span>&nbsp;-&nbsp;<span class="src-num">1</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2604"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">while</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$escape_char_pos</span>&nbsp;>&nbsp;<span class="src-num">0</span></span></div></li>
+<li><div class="src-line"><a name="a2605"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp;&nbsp;<span class="src-var">$part</span><span class="src-sym">[</span><span class="src-var">$escape_char_pos</span>&nbsp;-&nbsp;<span class="src-num">1</span><span class="src-sym">]</span>&nbsp;==&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2606"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--<span class="src-var">$escape_char_pos</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2607"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2608"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">((</span><span class="src-var">$close_pos</span>&nbsp;-&nbsp;<span class="src-var">$escape_char_pos</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">&</span>&nbsp;<span class="src-num">1</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2609"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;uneven&nbsp;number&nbsp;of&nbsp;escape&nbsp;chars&nbsp;=&gt;&nbsp;this&nbsp;quote&nbsp;is&nbsp;escaped</span></span></div></li>
+<li><div class="src-line"><a name="a2610"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span>&nbsp;<span class="src-num">2</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2611"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2612"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2613"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2614"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2615"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2616"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;found&nbsp;closing&nbsp;quote</span></span></div></li>
+<li><div class="src-line"><a name="a2617"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">break</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2618"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2619"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2620"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Found&nbsp;the&nbsp;closing&nbsp;delimiter?</span></span></div></li>
+<li><div class="src-line"><a name="a2621"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$close_pos</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2622"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;span&nbsp;till&nbsp;the&nbsp;end&nbsp;of&nbsp;this&nbsp;$part&nbsp;when&nbsp;no&nbsp;closing&nbsp;delimiter&nbsp;is&nbsp;found</span></span></div></li>
+<li><div class="src-line"><a name="a2623"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$close_pos</span>&nbsp;=&nbsp;<span class="src-var">$length</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2624"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2625"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2626"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Get&nbsp;the&nbsp;actual&nbsp;string</span></span></div></li>
+<li><div class="src-line"><a name="a2627"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string</span>&nbsp;=&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$close_pos</span>&nbsp;-&nbsp;<span class="src-var">$i</span>&nbsp;+&nbsp;<span class="src-num">1</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2628"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$i</span>&nbsp;=&nbsp;<span class="src-var">$close_pos</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2629"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2630"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;handle&nbsp;escape&nbsp;chars&nbsp;and&nbsp;encode&nbsp;html&nbsp;chars</span></span></div></li>
+<li><div class="src-line"><a name="a2631"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;(special&nbsp;because&nbsp;when&nbsp;we&nbsp;have&nbsp;escape&nbsp;chars&nbsp;within&nbsp;our&nbsp;string&nbsp;they&nbsp;may&nbsp;not&nbsp;be&nbsp;escaped)</span></span></div></li>
+<li><div class="src-line"><a name="a2632"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2633"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$start</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2634"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$new_string</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2635"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">while</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$es_pos</span>&nbsp;=&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$string</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$start</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2636"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;hmtl&nbsp;escape&nbsp;stuff&nbsp;before</span></span></div></li>
+<li><div class="src-line"><a name="a2637"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$new_string</span>&nbsp;.=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$string</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$start</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$es_pos</span>&nbsp;-&nbsp;<span class="src-var">$start</span><span class="src-sym">))</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2638"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;check&nbsp;if&nbsp;this&nbsp;is&nbsp;a&nbsp;hard&nbsp;escape</span></span></div></li>
+<li><div class="src-line"><a name="a2639"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'HARDESCAPE'</span><span class="src-sym">]</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$hardescape</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2640"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$string</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$es_pos</span><span class="src-sym">,</span>&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$hardescape</span><span class="src-sym">))</span>&nbsp;==&nbsp;<span class="src-var">$hardescape</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2641"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;indeed,&nbsp;this&nbsp;is&nbsp;a&nbsp;hardescape</span></span></div></li>
+<li><div class="src-line"><a name="a2642"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$new_string</span>&nbsp;.=&nbsp;<span class="src-str">"</span></span>&lt;span<span class="src-var">$escape_char_attributes</span>&gt;<span class="src-str">&quot;&nbsp;</span><span class="src-str">.</span></div></li>
+<li><div class="src-line"><a name="a2643"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$hardescape</span><span class="src-sym">)</span>&nbsp;.&nbsp;<span class="src-str">'&lt;/span&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2644"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$start</span>&nbsp;=&nbsp;<span class="src-var">$es_pos</span>&nbsp;+&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$hardescape</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2645"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span>&nbsp;<span class="src-num">2</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2646"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2647"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2648"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;not&nbsp;a&nbsp;hard&nbsp;escape,&nbsp;but&nbsp;a&nbsp;normal&nbsp;escape</span></span></div></li>
+<li><div class="src-line"><a name="a2649"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;they&nbsp;come&nbsp;in&nbsp;pairs&nbsp;of&nbsp;two</span></span></div></li>
+<li><div class="src-line"><a name="a2650"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$c</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2651"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">while</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$string</span><span class="src-sym">[</span><span class="src-var">$es_pos</span>&nbsp;+&nbsp;<span class="src-var">$c</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;&amp;&amp;&nbsp;isset<span class="src-sym">(</span><span class="src-var">$string</span><span class="src-sym">[</span><span class="src-var">$es_pos</span>&nbsp;+&nbsp;<span class="src-var">$c</span>&nbsp;+&nbsp;<span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">)</span></span></div></li>
+<li><div class="src-line"><a name="a2652"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp;&nbsp;<span class="src-var">$string</span><span class="src-sym">[</span><span class="src-var">$es_pos</span>&nbsp;+&nbsp;<span class="src-var">$c</span><span class="src-sym">]</span>&nbsp;==&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span></span></div></li>
+<li><div class="src-line"><a name="a2653"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp;&nbsp;<span class="src-var">$string</span><span class="src-sym">[</span><span class="src-var">$es_pos</span>&nbsp;+&nbsp;<span class="src-var">$c</span>&nbsp;+&nbsp;<span class="src-num">1</span><span class="src-sym">]</span>&nbsp;==&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2654"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$c</span>&nbsp;+=&nbsp;<span class="src-num">2</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2655"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2656"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$c</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2657"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$new_string</span>&nbsp;.=&nbsp;<span class="src-str">"</span></span>&lt;span<span class="src-var">$escape_char_attributes</span>&gt;<span class="src-str">&quot;&nbsp;</span><span class="src-str">.</span></div></li>
+<li><div class="src-line"><a name="a2658"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">str_repeat</span><span class="src-sym">(</span><span class="src-var">$escaped_escape_char</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$c</span><span class="src-sym">)</span>&nbsp;.</span></div></li>
+<li><div class="src-line"><a name="a2659"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'&lt;/span&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2660"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$start</span>&nbsp;=&nbsp;<span class="src-var">$es_pos</span>&nbsp;+&nbsp;<span class="src-var">$c</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2661"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2662"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;this&nbsp;is&nbsp;just&nbsp;a&nbsp;single&nbsp;lonely&nbsp;escape&nbsp;char...</span></span></div></li>
+<li><div class="src-line"><a name="a2663"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$new_string</span>&nbsp;.=&nbsp;<span class="src-var">$escaped_escape_char</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2664"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$start</span>&nbsp;=&nbsp;<span class="src-var">$es_pos</span>&nbsp;+&nbsp;<span class="src-num">1</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2665"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2666"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2667"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string</span>&nbsp;=&nbsp;<span class="src-var">$new_string</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$string</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$start</span><span class="src-sym">))</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2668"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2669"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$string</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2670"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2671"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2672"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$check_linenumbers</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2673"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Are&nbsp;line&nbsp;numbers&nbsp;used?&nbsp;If,&nbsp;we&nbsp;should&nbsp;end&nbsp;the&nbsp;string&nbsp;before</span></span></div></li>
+<li><div class="src-line"><a name="a2674"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;the&nbsp;newline&nbsp;and&nbsp;begin&nbsp;it&nbsp;again&nbsp;(so&nbsp;when&nbsp;&lt;li&gt;s&nbsp;are&nbsp;put&nbsp;in&nbsp;the&nbsp;source</span></span></div></li>
+<li><div class="src-line"><a name="a2675"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;remains&nbsp;XHTML&nbsp;compliant)</span></span></div></li>
+<li><div class="src-line"><a name="a2676"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;note&nbsp;to&nbsp;self:&nbsp;This&nbsp;opens&nbsp;up&nbsp;possibility&nbsp;of&nbsp;config&nbsp;files&nbsp;specifying</span></span></div></li>
+<li><div class="src-line"><a name="a2677"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;that&nbsp;languages&nbsp;can/cannot&nbsp;have&nbsp;multiline&nbsp;strings???</span></span></div></li>
+<li><div class="src-line"><a name="a2678"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-str">&quot;\n&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-str">"</span></span>&lt;/span&gt;\n&lt;span<span class="src-var">$string_attributes</span>&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">,</span>&nbsp;<span class="src-var">$string</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2679"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2680"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2681"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;.=&nbsp;</span><span class="src-str">&quot;</span>&lt;span<span class="src-var">$string_attributes</span>&gt;<span class="src-str">&quot;&nbsp;</span><span class="src-str">.&nbsp;<span class="src-var">$string</span>&nbsp;.&nbsp;<span class="src-str">'&lt;/span&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2682"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$string</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2683"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2684"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2685"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Have&nbsp;a&nbsp;look&nbsp;for&nbsp;regexp&nbsp;comments</span></span></div></li>
+<li><div class="src-line"><a name="a2686"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$i</span>&nbsp;==&nbsp;<span class="src-var">$next_comment_regexp_pos</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2687"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$COMMENT_MATCHED</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2688"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$comment</span>&nbsp;=&nbsp;<span class="src-var">$comment_regexp_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$next_comment_regexp_key</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2689"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$test_str</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$comment</span><span class="src-sym">[</span><span class="src-str">'length'</span><span class="src-sym">]</span><span class="src-sym">))</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2690"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2691"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//@todo&nbsp;If&nbsp;remove&nbsp;important&nbsp;do&nbsp;remove&nbsp;here</span></span></div></li>
+<li><div class="src-line"><a name="a2692"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'MULTI'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2693"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2694"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$comment</span><span class="src-sym">[</span><span class="src-str">'key'</span><span class="src-sym">]]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2695"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2696"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;co'</span>&nbsp;.&nbsp;<span class="src-var">$comment</span><span class="src-sym">[</span><span class="src-str">'key'</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2697"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2698"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2699"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$test_str</span>&nbsp;=&nbsp;<span class="src-str">"</span></span>&lt;span<span class="src-var">$attributes</span>&gt;<span class="src-str">&quot;&nbsp;</span><span class="src-str">.&nbsp;<span class="src-var">$test_str</span>&nbsp;.&nbsp;<span class="src-str">&quot;&lt;/span&gt;&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2700"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2701"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Short-cut&nbsp;through&nbsp;all&nbsp;the&nbsp;multiline&nbsp;code</span></span></div></li>
+<li><div class="src-line"><a name="a2702"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$check_linenumbers</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2703"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;strreplace&nbsp;to&nbsp;put&nbsp;close&nbsp;span&nbsp;and&nbsp;open&nbsp;span&nbsp;around&nbsp;multiline&nbsp;newlines</span></span></div></li>
+<li><div class="src-line"><a name="a2704"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$test_str</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a2705"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">&quot;\n&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-str">"</span></span>&lt;/span&gt;\n&lt;span<span class="src-var">$attributes</span>&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2706"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">str_replace</span><span class="src-sym">(</span><span class="src-str">&quot;\n&nbsp;&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-str">&quot;\n&amp;nbsp;&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$test_str</span><span class="src-sym">)</span></span></div></li>
+<li><div class="src-line"><a name="a2707"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2708"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2709"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2710"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2711"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$i</span>&nbsp;+=&nbsp;<span class="src-var">$comment</span><span class="src-sym">[</span><span class="src-str">'length'</span><span class="src-sym">]</span>&nbsp;-&nbsp;<span class="src-num">1</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2712"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2713"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;parse&nbsp;the&nbsp;rest</span></span></div></li>
+<li><div class="src-line"><a name="a2714"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;.=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">parse_non_string_part</span><span class="src-sym">(</span><span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2715"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2716"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2717"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2718"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;If&nbsp;we&nbsp;haven't&nbsp;matched&nbsp;a&nbsp;regexp&nbsp;comment,&nbsp;try&nbsp;multi-line&nbsp;comments</span></span></div></li>
+<li><div class="src-line"><a name="a2719"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$COMMENT_MATCHED</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2720"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Is&nbsp;this&nbsp;a&nbsp;multiline&nbsp;comment?</span></span></div></li>
+<li><div class="src-line"><a name="a2721"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'COMMENT_MULTI'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$next_comment_multi_pos</span>&nbsp;<&nbsp;<span class="src-var">$i</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2722"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_comment_multi_pos</span>&nbsp;=&nbsp;<span class="src-var">$length</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2723"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'COMMENT_MULTI'</span><span class="src-sym">]</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$open</span>&nbsp;=&gt;&nbsp;<span class="src-var">$close</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2724"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$match_i</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2725"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$comment_multi_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$open</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a2726"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span><span class="src-var">$comment_multi_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$open</span><span class="src-sym">]</span>&nbsp;&gt;=&nbsp;<span class="src-var">$i</span>&nbsp;||</span></div></li>
+<li><div class="src-line"><a name="a2727"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$comment_multi_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$open</span><span class="src-sym">]</span>&nbsp;===&nbsp;<span class="src-id">false</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2728"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;we&nbsp;have&nbsp;already&nbsp;matched&nbsp;something</span></span></div></li>
+<li><div class="src-line"><a name="a2729"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$comment_multi_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$open</span><span class="src-sym">]</span>&nbsp;===&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2730"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;this&nbsp;comment&nbsp;is&nbsp;never&nbsp;matched</span></span></div></li>
+<li><div class="src-line"><a name="a2731"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2732"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2733"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$match_i</span>&nbsp;=&nbsp;<span class="src-var">$comment_multi_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$open</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2734"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">((</span><span class="src-var">$match_i</span>&nbsp;=&nbsp;<a href="http://www.php.net/stripos">stripos</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$open</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span><span class="src-sym">))</span>&nbsp;!==&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2735"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$comment_multi_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$open</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$match_i</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2736"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2737"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$comment_multi_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$open</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2738"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2739"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2740"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$match_i</span>&nbsp;!==&nbsp;<span class="src-id">false</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$match_i</span>&nbsp;<&nbsp;<span class="src-var">$next_comment_multi_pos</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2741"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_comment_multi_pos</span>&nbsp;=&nbsp;<span class="src-var">$match_i</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2742"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_open_comment_multi</span>&nbsp;=&nbsp;<span class="src-var">$open</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2743"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$match_i</span>&nbsp;===&nbsp;<span class="src-var">$i</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2744"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">break</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2745"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2746"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2747"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2748"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2749"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$i</span>&nbsp;==&nbsp;<span class="src-var">$next_comment_multi_pos</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2750"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$open</span>&nbsp;=&nbsp;<span class="src-var">$next_open_comment_multi</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2751"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$close</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'COMMENT_MULTI'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$open</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2752"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$open_strlen</span>&nbsp;=&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$open</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2753"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$close_strlen</span>&nbsp;=&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$close</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2754"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$COMMENT_MATCHED</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2755"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$test_str_match</span>&nbsp;=&nbsp;<span class="src-var">$open</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2756"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//@todo&nbsp;If&nbsp;remove&nbsp;important&nbsp;do&nbsp;remove&nbsp;here</span></span></div></li>
+<li><div class="src-line"><a name="a2757"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'MULTI'</span><span class="src-sym">]</span>&nbsp;||</span></div></li>
+<li><div class="src-line"><a name="a2758"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$open</span>&nbsp;==&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_START_IMPORTANT&quot;&gt;GESHI_START_IMPORTANT&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2759"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$open</span>&nbsp;!=&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_START_IMPORTANT&quot;&gt;GESHI_START_IMPORTANT&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2760"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2761"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'MULTI'</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2762"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2763"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;coMULTI&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2764"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2765"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$test_str</span>&nbsp;=&nbsp;<span class="src-str">"</span></span>&lt;span<span class="src-var">$attributes</span>&gt;<span class="src-str">&quot;&nbsp;</span><span class="src-str">.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$open</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2766"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2767"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2768"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">important_styles</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2769"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2770"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;imp&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2771"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2772"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2773"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;We&nbsp;don't&nbsp;include&nbsp;the&nbsp;start&nbsp;of&nbsp;the&nbsp;comment&nbsp;if&nbsp;it's&nbsp;an</span></span></div></li>
+<li><div class="src-line"><a name="a2774"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;&quot;important&quot;&nbsp;part</span></span></div></li>
+<li><div class="src-line"><a name="a2775"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$test_str</span>&nbsp;=&nbsp;<span class="src-str">"</span></span>&lt;span<span class="src-var">$attributes</span>&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2776"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2777"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2778"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$test_str</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$open</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2779"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2780"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2781"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$close_pos</span>&nbsp;=&nbsp;<span class="src-id">strpos</span><span class="src-sym">(</span>&nbsp;<span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$close</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span>&nbsp;+&nbsp;<span class="src-var">$open_strlen</span>&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2782"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2783"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$close_pos</span>&nbsp;===&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2784"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$close_pos</span>&nbsp;=&nbsp;<span class="src-var">$length</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2785"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2786"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2787"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Short-cut&nbsp;through&nbsp;all&nbsp;the&nbsp;multiline&nbsp;code</span></span></div></li>
+<li><div class="src-line"><a name="a2788"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$rest_of_comment</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-id">substr</span><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span>&nbsp;+&nbsp;<span class="src-var">$open_strlen</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$close_pos</span>&nbsp;-&nbsp;<span class="src-var">$i</span>&nbsp;-&nbsp;<span class="src-var">$open_strlen</span>&nbsp;+&nbsp;<span class="src-var">$close_strlen</span><span class="src-sym">))</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2789"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">((</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'MULTI'</span><span class="src-sym">]</span>&nbsp;||</span></div></li>
+<li><div class="src-line"><a name="a2790"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$test_str_match</span>&nbsp;==&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_START_IMPORTANT&quot;&gt;GESHI_START_IMPORTANT&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a2791"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$check_linenumbers</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2792"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2793"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;strreplace&nbsp;to&nbsp;put&nbsp;close&nbsp;span&nbsp;and&nbsp;open&nbsp;span&nbsp;around&nbsp;multiline&nbsp;newlines</span></span></div></li>
+<li><div class="src-line"><a name="a2794"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$test_str</span>&nbsp;.=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a2795"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">&quot;\n&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-str">"</span></span>&lt;/span&gt;\n&lt;span<span class="src-var">$attributes</span>&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a2796"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-id">str_replace</span><span class="src-sym">(</span><span class="src-str">&quot;\n&nbsp;&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-str">&quot;\n&amp;nbsp;&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$rest_of_comment</span><span class="src-sym">)</span></span></div></li>
+<li><div class="src-line"><a name="a2797"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2798"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2799"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$test_str</span>&nbsp;.=&nbsp;<span class="src-var">$rest_of_comment</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2800"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2801"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2802"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'MULTI'</span><span class="src-sym">]</span>&nbsp;||</span></div></li>
+<li><div class="src-line"><a name="a2803"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$test_str_match</span>&nbsp;==&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_START_IMPORTANT&quot;&gt;GESHI_START_IMPORTANT&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2804"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$test_str</span>&nbsp;.=&nbsp;<span class="src-str">'&lt;/span&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2805"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2806"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2807"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$i</span>&nbsp;=&nbsp;<span class="src-var">$close_pos</span>&nbsp;+&nbsp;<span class="src-var">$close_strlen</span>&nbsp;-&nbsp;<span class="src-num">1</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2808"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2809"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;parse&nbsp;the&nbsp;rest</span></span></div></li>
+<li><div class="src-line"><a name="a2810"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;.=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">parse_non_string_part</span><span class="src-sym">(</span><span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2811"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2812"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2813"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2814"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2815"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;If&nbsp;we&nbsp;haven't&nbsp;matched&nbsp;a&nbsp;multiline&nbsp;comment,&nbsp;try&nbsp;single-line&nbsp;comments</span></span></div></li>
+<li><div class="src-line"><a name="a2816"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$COMMENT_MATCHED</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2817"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;cache&nbsp;potential&nbsp;single&nbsp;line&nbsp;comment&nbsp;occurances</span></span></div></li>
+<li><div class="src-line"><a name="a2818"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'COMMENT_SINGLE'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$next_comment_single_pos</span>&nbsp;<&nbsp;<span class="src-var">$i</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2819"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_comment_single_pos</span>&nbsp;=&nbsp;<span class="src-var">$length</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2820"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'COMMENT_SINGLE'</span><span class="src-sym">]</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$comment_key</span>&nbsp;=&gt;&nbsp;<span class="src-var">$comment_mark</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2821"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$match_i</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2822"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$comment_single_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$comment_key</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a2823"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span><span class="src-var">$comment_single_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$comment_key</span><span class="src-sym">]</span>&nbsp;&gt;=&nbsp;<span class="src-var">$i</span>&nbsp;||</span></div></li>
+<li><div class="src-line"><a name="a2824"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$comment_single_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$comment_key</span><span class="src-sym">]</span>&nbsp;===&nbsp;<span class="src-id">false</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2825"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;we&nbsp;have&nbsp;already&nbsp;matched&nbsp;something</span></span></div></li>
+<li><div class="src-line"><a name="a2826"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$comment_single_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$comment_key</span><span class="src-sym">]</span>&nbsp;===&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2827"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;this&nbsp;comment&nbsp;is&nbsp;never&nbsp;matched</span></span></div></li>
+<li><div class="src-line"><a name="a2828"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2829"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2830"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$match_i</span>&nbsp;=&nbsp;<span class="src-var">$comment_single_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$comment_key</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2831"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a2832"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;case&nbsp;sensitive&nbsp;comments</span></span></div></li>
+<li><div class="src-line"><a name="a2833"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'CASE_SENSITIVE'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-id">GESHI_COMMENTS</span><span class="src-sym">]</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a2834"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span><span class="src-var">$match_i</span>&nbsp;=&nbsp;<a href="http://www.php.net/stripos">stripos</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$comment_mark</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span><span class="src-sym">))</span>&nbsp;!==&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;||</span></div></li>
+<li><div class="src-line"><a name="a2835"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;non&nbsp;case&nbsp;sensitive</span></span></div></li>
+<li><div class="src-line"><a name="a2836"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'CASE_SENSITIVE'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-id">GESHI_COMMENTS</span><span class="src-sym">]</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a2837"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">((</span><span class="src-var">$match_i</span>&nbsp;=&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$comment_mark</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span><span class="src-sym">))</span>&nbsp;!==&nbsp;<span class="src-id">false</span><span class="src-sym">)))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2838"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$comment_single_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$comment_key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$match_i</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2839"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2840"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$comment_single_cache_per_key</span><span class="src-sym">[</span><span class="src-var">$comment_key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2841"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2842"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2843"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$match_i</span>&nbsp;!==&nbsp;<span class="src-id">false</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$match_i</span>&nbsp;<&nbsp;<span class="src-var">$next_comment_single_pos</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2844"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_comment_single_pos</span>&nbsp;=&nbsp;<span class="src-var">$match_i</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2845"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$next_comment_single_key</span>&nbsp;=&nbsp;<span class="src-var">$comment_key</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2846"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$match_i</span>&nbsp;===&nbsp;<span class="src-var">$i</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2847"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">break</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2848"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2849"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2850"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2851"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2852"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$next_comment_single_pos</span>&nbsp;==&nbsp;<span class="src-var">$i</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2853"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$comment_key</span>&nbsp;=&nbsp;<span class="src-var">$next_comment_single_key</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2854"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$comment_mark</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'COMMENT_SINGLE'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$comment_key</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2855"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$com_len</span>&nbsp;=&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$comment_mark</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2856"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2857"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;This&nbsp;check&nbsp;will&nbsp;find&nbsp;special&nbsp;variables&nbsp;like&nbsp;$#&nbsp;in&nbsp;bash</span></span></div></li>
+<li><div class="src-line"><a name="a2858"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;or&nbsp;compiler&nbsp;directives&nbsp;of&nbsp;Delphi&nbsp;beginning&nbsp;{$</span></span></div></li>
+<li><div class="src-line"><a name="a2859"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">((</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$sc_disallowed_before</span><span class="src-sym">)</span>&nbsp;||&nbsp;<span class="src-sym">(</span><span class="src-var">$i</span>&nbsp;==&nbsp;<span class="src-num">0</span><span class="src-sym">)</span>&nbsp;||</span></div></li>
+<li><div class="src-line"><a name="a2860"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span><span class="src-id">false</span>&nbsp;===&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$sc_disallowed_before</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$part</span><span class="src-sym">[</span><span class="src-var">$i</span>-<span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">)))</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a2861"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$sc_disallowed_after</span><span class="src-sym">)</span>&nbsp;||&nbsp;<span class="src-sym">(</span><span class="src-var">$length</span>&nbsp;&lt;=&nbsp;<span class="src-var">$i</span>&nbsp;+&nbsp;<span class="src-var">$com_len</span><span class="src-sym">)</span>&nbsp;||</span></div></li>
+<li><div class="src-line"><a name="a2862"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span><span class="src-id">false</span>&nbsp;===&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$sc_disallowed_after</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$part</span><span class="src-sym">[</span><span class="src-var">$i</span>&nbsp;+&nbsp;<span class="src-var">$com_len</span><span class="src-sym">]</span><span class="src-sym">))))</span></span></div></li>
+<li><div class="src-line"><a name="a2863"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2864"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;this&nbsp;is&nbsp;a&nbsp;valid&nbsp;comment</span></span></div></li>
+<li><div class="src-line"><a name="a2865"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$COMMENT_MATCHED</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2866"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$comment_key</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2867"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2868"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$comment_key</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2869"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2870"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;co'</span>&nbsp;.&nbsp;<span class="src-var">$comment_key</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2871"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2872"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$test_str</span>&nbsp;=&nbsp;<span class="src-str">"</span></span>&lt;span<span class="src-var">$attributes</span>&gt;<span class="src-str">&quot;&nbsp;</span><span class="src-str">.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">change_case</span><span class="src-sym">(</span><span class="src-var">$comment_mark</span><span class="src-sym">))</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2873"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2874"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$test_str</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$comment_mark</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2875"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2876"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2877"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Check&nbsp;if&nbsp;this&nbsp;comment&nbsp;is&nbsp;the&nbsp;last&nbsp;in&nbsp;the&nbsp;source</span></span></div></li>
+<li><div class="src-line"><a name="a2878"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$close_pos</span>&nbsp;=&nbsp;<span class="src-id">strpos</span><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-str">&quot;\n&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2879"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$oops</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2880"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$close_pos</span>&nbsp;===&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2881"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$close_pos</span>&nbsp;=&nbsp;<span class="src-var">$length</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2882"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$oops</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2883"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2884"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$test_str</span>&nbsp;.=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span>&nbsp;+&nbsp;<span class="src-var">$com_len</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$close_pos</span>&nbsp;-&nbsp;<span class="src-var">$i</span>&nbsp;-&nbsp;<span class="src-var">$com_len</span><span class="src-sym">))</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2885"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$comment_key</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2886"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$test_str</span>&nbsp;.=&nbsp;<span class="src-str">&quot;&lt;/span&gt;&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2887"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2888"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2889"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Take&nbsp;into&nbsp;account&nbsp;that&nbsp;the&nbsp;comment&nbsp;might&nbsp;be&nbsp;the&nbsp;last&nbsp;in&nbsp;the&nbsp;source</span></span></div></li>
+<li><div class="src-line"><a name="a2890"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$oops</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2891"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$test_str</span>&nbsp;.=&nbsp;<span class="src-str">&quot;\n&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2892"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2893"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2894"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$i</span>&nbsp;=&nbsp;<span class="src-var">$close_pos</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2895"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2896"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;parse&nbsp;the&nbsp;rest</span></span></div></li>
+<li><div class="src-line"><a name="a2897"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;.=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">parse_non_string_part</span><span class="src-sym">(</span><span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2898"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2899"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2900"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2901"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2902"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2903"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2904"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Where&nbsp;are&nbsp;we&nbsp;adding&nbsp;this&nbsp;char?</span></span></div></li>
+<li><div class="src-line"><a name="a2905"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$COMMENT_MATCHED</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2906"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;.=&nbsp;<span class="src-var">$char</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2907"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2908"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;.=&nbsp;<span class="src-var">$test_str</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2909"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$test_str</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2910"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$COMMENT_MATCHED</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2911"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2912"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2913"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Parse&nbsp;the&nbsp;last&nbsp;bit</span></span></div></li>
+<li><div class="src-line"><a name="a2914"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;.=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">parse_non_string_part</span><span class="src-sym">(</span><span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2915"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2916"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2917"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;.=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2918"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2919"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Close&nbsp;the&nbsp;&lt;span&gt;&nbsp;that&nbsp;surrounds&nbsp;the&nbsp;block</span></span></div></li>
+<li><div class="src-line"><a name="a2920"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$STRICTATTRS</span>&nbsp;!=&nbsp;<span class="src-str">''</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2921"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-str">&quot;\n&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-str">"</span></span>&lt;/span&gt;\n&lt;span<span class="src-var">$STRICTATTRS</span>&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">,</span>&nbsp;<span class="src-var">$result</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2922"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;.=&nbsp;<span class="src-str">'&lt;/span&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2923"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2924"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2925"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$endresult</span>&nbsp;.=&nbsp;<span class="src-var">$result</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2926"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$part</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$parts</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$result</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2927"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2928"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2929"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//This&nbsp;fix&nbsp;is&nbsp;related&nbsp;to&nbsp;SF#1923020,&nbsp;but&nbsp;has&nbsp;to&nbsp;be&nbsp;applied&nbsp;regardless&nbsp;of</span></span></div></li>
+<li><div class="src-line"><a name="a2930"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//actually&nbsp;highlighting&nbsp;symbols.</span></span></div></li>
+<li><div class="src-line"><a name="a2931"></a><span class="src-doc">/**&nbsp;NOTE:&nbsp;memorypeak&nbsp;#3&nbsp;*/</span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a2932"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$endresult</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'&lt;SEMI&gt;'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'&lt;PIPE&gt;'</span><span class="src-sym">)</span><span class="src-sym">,</span>&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">';'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'|'</span><span class="src-sym">)</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$endresult</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2933"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2934"></a></span><span class="src-str"><span class="src-comm">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Parse&nbsp;the&nbsp;last&nbsp;stuff&nbsp;(redundant?)</span></span></div></li>
+<li><div class="src-line"><a name="a2935"></a></span><span class="src-str"><span class="src-comm">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$result&nbsp;.=&nbsp;$this-&gt;parse_non_string_part($stuff_to_parse);</span></span></div></li>
+<li><div class="src-line"><a name="a2936"></a></span><span class="src-str"><span class="src-comm"></span></span></div></li>
+<li><div class="src-line"><a name="a2937"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Lop&nbsp;off&nbsp;the&nbsp;very&nbsp;first&nbsp;and&nbsp;last&nbsp;spaces</span></span></div></li>
+<li><div class="src-line"><a name="a2938"></a></span><span class="src-str"><span class="src-comm">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$result&nbsp;=&nbsp;substr($result,&nbsp;1,&nbsp;-1);</span></span></div></li>
+<li><div class="src-line"><a name="a2939"></a></span><span class="src-str"><span class="src-comm"></span></span></div></li>
+<li><div class="src-line"><a name="a2940"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;We're&nbsp;finished:&nbsp;stop&nbsp;timing</span></span></div></li>
+<li><div class="src-line"><a name="a2941"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">set_time</span><span class="src-sym">(</span><span class="src-var">$start_time</span><span class="src-sym">,</span>&nbsp;<a href="http://www.php.net/microtime">microtime</a><span class="src-sym">(</span><span class="src-sym">))</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2942"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2943"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">finalise</span><span class="src-sym">(</span><span class="src-var">$endresult</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2944"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-var">$endresult</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2945"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2946"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2947"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a2948"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Swaps&nbsp;out&nbsp;spaces&nbsp;and&nbsp;tabs&nbsp;for&nbsp;HTML&nbsp;indentation.&nbsp;Not&nbsp;needed&nbsp;if</span></div></li>
+<li><div class="src-line"><a name="a2949"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;the&nbsp;code&nbsp;is&nbsp;in&nbsp;a&nbsp;pre&nbsp;block...</span></div></li>
+<li><div class="src-line"><a name="a2950"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a2951"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc">&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;source&nbsp;to&nbsp;indent&nbsp;(reference!)</span></div></li>
+<li><div class="src-line"><a name="a2952"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a2953"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@access</span><span class="src-doc">&nbsp;private</span></div></li>
+<li><div class="src-line"><a name="a2954"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a2955"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<span class="src-id">indent</span><span class="src-sym">(</span><span class="src-sym">&</span><span class="src-var">$result</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2956"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">///&nbsp;Replace&nbsp;tabs&nbsp;with&nbsp;the&nbsp;correct&nbsp;number&nbsp;of&nbsp;spaces</span></span></div></li>
+<li><div class="src-line"><a name="a2957"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-id">false</span>&nbsp;!==&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$result</span><span class="src-sym">,</span>&nbsp;<span class="src-str">&quot;\t&quot;</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2958"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$lines</span>&nbsp;=&nbsp;<a href="http://www.php.net/explode">explode</a><span class="src-sym">(</span><span class="src-str">&quot;\n&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$result</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2959"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;=&nbsp;<span class="src-id">null</span><span class="src-sym">;</span><span class="src-comm">//Save&nbsp;memory&nbsp;while&nbsp;we&nbsp;process&nbsp;the&nbsp;lines&nbsp;individually</span></span></div></li>
+<li><div class="src-line"><a name="a2960"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$tab_width</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodget_real_tab_width">get_real_tab_width</a><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2961"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$tab_string</span>&nbsp;=&nbsp;<span class="src-str">'&amp;nbsp;'</span>&nbsp;.&nbsp;<a href="http://www.php.net/str_repeat">str_repeat</a><span class="src-sym">(</span><span class="src-str">'&nbsp;'</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$tab_width</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2962"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2963"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">for</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$key</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$n</span>&nbsp;=&nbsp;<a href="http://www.php.net/count">count</a><span class="src-sym">(</span><span class="src-var">$lines</span><span class="src-sym">)</span><span class="src-sym">;</span>&nbsp;<span class="src-var">$key</span>&nbsp;<&nbsp;<span class="src-var">$n</span><span class="src-sym">;</span>&nbsp;<span class="src-var">$key</span>++<span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2964"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$line</span>&nbsp;=&nbsp;<span class="src-var">$lines</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2965"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-id">false</span>&nbsp;===&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$line</span><span class="src-sym">,</span>&nbsp;<span class="src-str">&quot;\t&quot;</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2966"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2967"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2968"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a2969"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$pos</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2970"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$length</span>&nbsp;=&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$line</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2971"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$lines</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span>&nbsp;<span class="src-comm">//&nbsp;reduce&nbsp;memory</span></span></div></li>
+<li><div class="src-line"><a name="a2972"></a></span><span class="src-str"><span class="src-comm"></span></span></div></li>
+<li><div class="src-line"><a name="a2973"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$IN_TAG</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2974"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">for</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$i</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span>&nbsp;<span class="src-var">$i</span>&nbsp;<&nbsp;<span class="src-var">$length</span><span class="src-sym">;</span>&nbsp;++<span class="src-var">$i</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2975"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$char</span>&nbsp;=&nbsp;<span class="src-var">$line</span><span class="src-sym">[</span><span class="src-var">$i</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2976"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Simple&nbsp;engine&nbsp;to&nbsp;work&nbsp;out&nbsp;whether&nbsp;we're&nbsp;in&nbsp;a&nbsp;tag.</span></span></div></li>
+<li><div class="src-line"><a name="a2977"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;If&nbsp;we&nbsp;are&nbsp;we&nbsp;modify&nbsp;$pos.&nbsp;This&nbsp;is&nbsp;so&nbsp;we&nbsp;ignore&nbsp;HTML</span></span></div></li>
+<li><div class="src-line"><a name="a2978"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;in&nbsp;the&nbsp;line&nbsp;and&nbsp;only&nbsp;workout&nbsp;the&nbsp;tab&nbsp;replacement</span></span></div></li>
+<li><div class="src-line"><a name="a2979"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;via&nbsp;the&nbsp;actual&nbsp;content&nbsp;of&nbsp;the&nbsp;string</span></span></div></li>
+<li><div class="src-line"><a name="a2980"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;This&nbsp;test&nbsp;could&nbsp;be&nbsp;improved&nbsp;to&nbsp;include&nbsp;strings&nbsp;in&nbsp;the</span></span></div></li>
+<li><div class="src-line"><a name="a2981"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;html&nbsp;so&nbsp;that&nbsp;&lt;&nbsp;or&nbsp;&gt;&nbsp;would&nbsp;be&nbsp;allowed&nbsp;in&nbsp;user's&nbsp;styles</span></span></div></li>
+<li><div class="src-line"><a name="a2982"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;(e.g.&nbsp;quotes:&nbsp;'&lt;'&nbsp;'&gt;';&nbsp;or&nbsp;similar)</span></span></div></li>
+<li><div class="src-line"><a name="a2983"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$IN_TAG</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2984"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-str">'&gt;'</span>&nbsp;==&nbsp;<span class="src-var">$char</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2985"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$IN_TAG</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2986"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2987"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$lines</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;.=&nbsp;<span class="src-var">$char</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2988"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-str">'&lt;'</span>&nbsp;==&nbsp;<span class="src-var">$char</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2989"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$IN_TAG</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2990"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$lines</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;.=&nbsp;<span class="src-str">'&lt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2991"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-str">'&amp;'</span>&nbsp;==&nbsp;<span class="src-var">$char</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2992"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$substr</span>&nbsp;=&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$line</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span>&nbsp;+&nbsp;<span class="src-num">3</span><span class="src-sym">,</span>&nbsp;<span class="src-num">5</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2993"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$posi</span>&nbsp;=&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$substr</span><span class="src-sym">,</span>&nbsp;<span class="src-str">';'</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2994"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-id">false</span>&nbsp;===&nbsp;<span class="src-var">$posi</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2995"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++<span class="src-var">$pos</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2996"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a2997"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$pos</span>&nbsp;-=&nbsp;<span class="src-var">$posi</span>+<span class="src-num">2</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a2998"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a2999"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$lines</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;.=&nbsp;<span class="src-var">$char</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3000"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-str">&quot;\t&quot;</span>&nbsp;==&nbsp;<span class="src-var">$char</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3001"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$str</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3002"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;OPTIMISE&nbsp;-&nbsp;move&nbsp;$strs&nbsp;out.&nbsp;Make&nbsp;an&nbsp;array:</span></span></div></li>
+<li><div class="src-line"><a name="a3003"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;$tabs&nbsp;=&nbsp;array(</span></span></div></li>
+<li><div class="src-line"><a name="a3004"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;&nbsp;1&nbsp;=&gt;&nbsp;'&amp;nbsp;',</span></span></div></li>
+<li><div class="src-line"><a name="a3005"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;&nbsp;2&nbsp;=&gt;&nbsp;'&amp;nbsp;&nbsp;',</span></span></div></li>
+<li><div class="src-line"><a name="a3006"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;&nbsp;3&nbsp;=&gt;&nbsp;'&amp;nbsp;&nbsp;&amp;nbsp;'&nbsp;etc&nbsp;etc</span></span></div></li>
+<li><div class="src-line"><a name="a3007"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;to&nbsp;use&nbsp;instead&nbsp;of&nbsp;building&nbsp;a&nbsp;string&nbsp;every&nbsp;time</span></span></div></li>
+<li><div class="src-line"><a name="a3008"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$tab_end_width</span>&nbsp;=&nbsp;<span class="src-var">$tab_width</span>&nbsp;-&nbsp;<span class="src-sym">(</span><span class="src-var">$pos</span>&nbsp;%&nbsp;<span class="src-var">$tab_width</span><span class="src-sym">)</span><span class="src-sym">;</span>&nbsp;<span class="src-comm">//Moved&nbsp;out&nbsp;of&nbsp;the&nbsp;look&nbsp;as&nbsp;it&nbsp;doesn't&nbsp;change&nbsp;within&nbsp;the&nbsp;loop</span></span></div></li>
+<li><div class="src-line"><a name="a3009"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">((</span><span class="src-var">$pos</span>&nbsp;<span class="src-sym">&</span>&nbsp;<span class="src-num">1</span><span class="src-sym">)</span>&nbsp;||&nbsp;<span class="src-num">1</span>&nbsp;==&nbsp;<span class="src-var">$tab_end_width</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3010"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$str</span>&nbsp;.=&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$tab_string</span><span class="src-sym">,</span>&nbsp;<span class="src-num">6</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$tab_end_width</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3011"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3012"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$str</span>&nbsp;.=&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$tab_string</span><span class="src-sym">,</span>&nbsp;<span class="src-num">0</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$tab_end_width</span>+<span class="src-num">5</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3013"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3014"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$lines</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;.=&nbsp;<span class="src-var">$str</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3015"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$pos</span>&nbsp;+=&nbsp;<span class="src-var">$tab_end_width</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3016"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3017"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-id">false</span>&nbsp;===&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$line</span><span class="src-sym">,</span>&nbsp;<span class="src-str">&quot;\t&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span>&nbsp;+&nbsp;<span class="src-num">1</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3018"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$lines</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;.=&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$line</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$i</span>&nbsp;+&nbsp;<span class="src-num">1</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3019"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">break</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3020"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3021"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-num">0</span>&nbsp;==&nbsp;<span class="src-var">$pos</span>&nbsp;&amp;&amp;&nbsp;<span class="src-str">'&nbsp;'</span>&nbsp;==&nbsp;<span class="src-var">$char</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3022"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$lines</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;.=&nbsp;<span class="src-str">'&amp;nbsp;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3023"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++<span class="src-var">$pos</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3024"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3025"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$lines</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;.=&nbsp;<span class="src-var">$char</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3026"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++<span class="src-var">$pos</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3027"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3028"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3029"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3030"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;=&nbsp;<a href="http://www.php.net/implode">implode</a><span class="src-sym">(</span><span class="src-str">&quot;\n&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$lines</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3031"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$lines</span><span class="src-sym">)</span><span class="src-sym">;</span><span class="src-comm">//We&nbsp;don't&nbsp;need&nbsp;the&nbsp;lines&nbsp;separated&nbsp;beyond&nbsp;this&nbsp;---&nbsp;free&nbsp;them!</span></span></div></li>
+<li><div class="src-line"><a name="a3032"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3033"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Other&nbsp;whitespace</span></span></div></li>
+<li><div class="src-line"><a name="a3034"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;BenBE:&nbsp;Fix&nbsp;to&nbsp;reduce&nbsp;the&nbsp;number&nbsp;of&nbsp;replacements&nbsp;to&nbsp;be&nbsp;done</span></span></div></li>
+<li><div class="src-line"><a name="a3035"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;=&nbsp;<a href="http://www.php.net/preg_replace">preg_replace</a><span class="src-sym">(</span><span class="src-str">'/^&nbsp;/m'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'&amp;nbsp;'</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$result</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3036"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-str">'&nbsp;&nbsp;'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'&nbsp;&amp;nbsp;'</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$result</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3037"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3038"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers</span>&nbsp;==&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_NO_LINE_NUMBERS&quot;&gt;GESHI_NO_LINE_NUMBERS&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3039"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_ending</span>&nbsp;===&nbsp;<span class="src-id">null</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3040"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;=&nbsp;<a href="http://www.php.net/nl2br">nl2br</a><span class="src-sym">(</span><span class="src-var">$result</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3041"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3042"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$result</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-str">&quot;\n&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_ending</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$result</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3043"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3044"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3045"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3046"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3047"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a3048"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Changes&nbsp;the&nbsp;case&nbsp;of&nbsp;a&nbsp;keyword&nbsp;for&nbsp;those&nbsp;languages&nbsp;where&nbsp;a&nbsp;change&nbsp;is&nbsp;asked&nbsp;for</span></div></li>
+<li><div class="src-line"><a name="a3049"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a3050"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc">&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;keyword&nbsp;to&nbsp;change&nbsp;the&nbsp;case&nbsp;of</span></div></li>
+<li><div class="src-line"><a name="a3051"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@return&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;keyword&nbsp;with&nbsp;its&nbsp;case&nbsp;changed</span></div></li>
+<li><div class="src-line"><a name="a3052"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a3053"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@access</span><span class="src-doc">&nbsp;private</span></div></li>
+<li><div class="src-line"><a name="a3054"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a3055"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<span class="src-id">change_case</span><span class="src-sym">(</span><span class="src-var">$instr</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3056"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">switch</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'CASE_KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3057"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">case</span>&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_CAPS_UPPER&quot;&gt;GESHI_CAPS_UPPER&lt;/a&gt;</span>:</span></div></li>
+<li><div class="src-line"><a name="a3058"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<a href="http://www.php.net/strtoupper">strtoupper</a><span class="src-sym">(</span><span class="src-var">$instr</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3059"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">case</span>&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_CAPS_LOWER&quot;&gt;GESHI_CAPS_LOWER&lt;/a&gt;</span>:</span></div></li>
+<li><div class="src-line"><a name="a3060"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<a href="http://www.php.net/strtolower">strtolower</a><span class="src-sym">(</span><span class="src-var">$instr</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3061"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">default</span>:</span></div></li>
+<li><div class="src-line"><a name="a3062"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-var">$instr</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3063"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3064"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3065"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3066"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a3067"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Handles&nbsp;replacements&nbsp;of&nbsp;keywords&nbsp;to&nbsp;include&nbsp;markup&nbsp;and&nbsp;links&nbsp;if&nbsp;requested</span></div></li>
+<li><div class="src-line"><a name="a3068"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a3069"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc">&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;keyword&nbsp;to&nbsp;add&nbsp;the&nbsp;Markup&nbsp;to</span></div></li>
+<li><div class="src-line"><a name="a3070"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@return&nbsp;</span><span class="src-doc-type">The&nbsp;</span><span class="src-doc">HTML&nbsp;for&nbsp;the&nbsp;match&nbsp;found</span></div></li>
+<li><div class="src-line"><a name="a3071"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;&nbsp;1.0.8</span></div></li>
+<li><div class="src-line"><a name="a3072"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@access</span><span class="src-doc">&nbsp;private</span></div></li>
+<li><div class="src-line"><a name="a3073"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a3074"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@todo</span><span class="src-doc">&nbsp;&nbsp;&nbsp;Get&nbsp;rid&nbsp;of&nbsp;ender&nbsp;in&nbsp;keyword&nbsp;links</span></div></li>
+<li><div class="src-line"><a name="a3075"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a3076"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<span class="src-id">handle_keyword_replace</span><span class="src-sym">(</span><span class="src-var">$match</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3077"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$k</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_kw_replace_group</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3078"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$keyword</span>&nbsp;=&nbsp;<span class="src-var">$match</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3079"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3080"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$before</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3081"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$after</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3082"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3083"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">keyword_links</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3084"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Keyword&nbsp;links&nbsp;have&nbsp;been&nbsp;ebabled</span></span></div></li>
+<li><div class="src-line"><a name="a3085"></a></span><span class="src-str"><span class="src-comm"></span></span></div></li>
+<li><div class="src-line"><a name="a3086"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'URLS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a3087"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'URLS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span>&nbsp;!=&nbsp;<span class="src-str">''</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3088"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;There&nbsp;is&nbsp;a&nbsp;base&nbsp;group&nbsp;for&nbsp;this&nbsp;keyword</span></span></div></li>
+<li><div class="src-line"><a name="a3089"></a></span><span class="src-str"><span class="src-comm"></span></span></div></li>
+<li><div class="src-line"><a name="a3090"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Old&nbsp;system:&nbsp;strtolower</span></span></div></li>
+<li><div class="src-line"><a name="a3091"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//$keyword&nbsp;=&nbsp;(&nbsp;$this-&gt;language_data['CASE_SENSITIVE'][$group]&nbsp;)&nbsp;?&nbsp;$keyword&nbsp;:&nbsp;strtolower($keyword);</span></span></div></li>
+<li><div class="src-line"><a name="a3092"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;New&nbsp;system:&nbsp;get&nbsp;keyword&nbsp;from&nbsp;language&nbsp;file&nbsp;to&nbsp;get&nbsp;correct&nbsp;case</span></span></div></li>
+<li><div class="src-line"><a name="a3093"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'CASE_SENSITIVE'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a3094"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'URLS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'{FNAME}'</span><span class="src-sym">)</span>&nbsp;!==&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3095"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$word</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3096"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/strcasecmp">strcasecmp</a><span class="src-sym">(</span><span class="src-var">$word</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$keyword</span><span class="src-sym">)</span>&nbsp;==&nbsp;<span class="src-num">0</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3097"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">break</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3098"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3099"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3100"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3101"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$word</span>&nbsp;=&nbsp;<span class="src-var">$keyword</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3102"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3103"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3104"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$before</span>&nbsp;=&nbsp;<span class="src-str">'&lt;|UR1|&quot;'</span>&nbsp;.</span></div></li>
+<li><div class="src-line"><a name="a3105"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a3106"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a3107"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'{FNAME}'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a3108"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'{FNAMEL}'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a3109"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'{FNAMEU}'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a3110"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'.'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a3111"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a3112"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-str">'+'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'%20'</span><span class="src-sym">,</span>&nbsp;<a href="http://www.php.net/urlencode">urlencode</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$word</span><span class="src-sym">)))</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a3113"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-str">'+'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'%20'</span><span class="src-sym">,</span>&nbsp;<a href="http://www.php.net/urlencode">urlencode</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><a href="http://www.php.net/strtolower">strtolower</a><span class="src-sym">(</span><span class="src-var">$word</span><span class="src-sym">))))</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a3114"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-str">'+'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'%20'</span><span class="src-sym">,</span>&nbsp;<a href="http://www.php.net/urlencode">urlencode</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><a href="http://www.php.net/strtoupper">strtoupper</a><span class="src-sym">(</span><span class="src-var">$word</span><span class="src-sym">))))</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a3115"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'&lt;DOT&gt;'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a3116"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'URLS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span></span></div></li>
+<li><div class="src-line"><a name="a3117"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span>&nbsp;.&nbsp;<span class="src-str">'&quot;&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3118"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$after</span>&nbsp;=&nbsp;<span class="src-str">'&lt;/a&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3119"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3120"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3121"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3122"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-var">$before</span>&nbsp;.&nbsp;<span class="src-str">'&lt;|/'</span>.&nbsp;<span class="src-var">$k</span>&nbsp;.<span class="src-str">'/&gt;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">change_case</span><span class="src-sym">(</span><span class="src-var">$keyword</span><span class="src-sym">)</span>&nbsp;.&nbsp;<span class="src-str">'|&gt;'</span>&nbsp;.&nbsp;<span class="src-var">$after</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3123"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3124"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3125"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a3126"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;handles&nbsp;regular&nbsp;expressions&nbsp;highlighting-definitions&nbsp;with&nbsp;callback&nbsp;functions</span></div></li>
+<li><div class="src-line"><a name="a3127"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a3128"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-tag">@note</span><span class="src-doc">&nbsp;this&nbsp;is&nbsp;a&nbsp;callback,&nbsp;don't&nbsp;use&nbsp;it&nbsp;directly</span></div></li>
+<li><div class="src-line"><a name="a3129"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a3130"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">array&nbsp;</span><span class="src-doc">the&nbsp;matches&nbsp;array</span></div></li>
+<li><div class="src-line"><a name="a3131"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@return&nbsp;</span><span class="src-doc-type">The&nbsp;</span><span class="src-doc">highlighted&nbsp;string</span></div></li>
+<li><div class="src-line"><a name="a3132"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.8</span></div></li>
+<li><div class="src-line"><a name="a3133"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@access</span><span class="src-doc">&nbsp;private</span></div></li>
+<li><div class="src-line"><a name="a3134"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a3135"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<span class="src-id">handle_regexps_callback</span><span class="src-sym">(</span><span class="src-var">$matches</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3136"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;before:&nbsp;&quot;'&nbsp;style=\&quot;'&nbsp;.&nbsp;call_user_func(\&quot;$func\&quot;,&nbsp;'\\1')&nbsp;.&nbsp;'\&quot;\\1|&gt;'&quot;,</span></span></div></li>
+<li><div class="src-line"><a name="a3137"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<a href="http://www.php.net/call_user_func">call_user_func</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_rx_key</span><span class="src-sym">]</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$matches</span><span class="src-sym">[</span><span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span>.&nbsp;<span class="src-var">$matches</span><span class="src-sym">[</span><span class="src-num">1</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'|&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3138"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3139"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3140"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a3141"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;handles&nbsp;newlines&nbsp;in&nbsp;REGEXPS&nbsp;matches.&nbsp;Set&nbsp;the&nbsp;_hmr_*&nbsp;vars&nbsp;before&nbsp;calling&nbsp;this</span></div></li>
+<li><div class="src-line"><a name="a3142"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a3143"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-tag">@note</span><span class="src-doc">&nbsp;this&nbsp;is&nbsp;a&nbsp;callback,&nbsp;don't&nbsp;use&nbsp;it&nbsp;directly</span></div></li>
+<li><div class="src-line"><a name="a3144"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a3145"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">array&nbsp;</span><span class="src-doc">the&nbsp;matches&nbsp;array</span></div></li>
+<li><div class="src-line"><a name="a3146"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@return&nbsp;</span><span class="src-doc-type">string&nbsp;</span></div></li>
+<li><div class="src-line"><a name="a3147"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.8</span></div></li>
+<li><div class="src-line"><a name="a3148"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@access</span><span class="src-doc">&nbsp;private</span></div></li>
+<li><div class="src-line"><a name="a3149"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a3150"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<span class="src-id">handle_multiline_regexps</span><span class="src-sym">(</span><span class="src-var">$matches</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3151"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$before</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_hmr_before</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3152"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$after</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_hmr_after</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3153"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_hmr_replace</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3154"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$replace</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_hmr_replace</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3155"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$search</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3156"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3157"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/array_keys">array_keys</a><span class="src-sym">(</span><span class="src-var">$matches</span><span class="src-sym">)</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$k</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3158"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$search</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">'\\'</span>&nbsp;.&nbsp;<span class="src-var">$k</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3159"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3160"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3161"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$before</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-var">$search</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$matches</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$before</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3162"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$after</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-var">$search</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$matches</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$after</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3163"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$replace</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-var">$search</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$matches</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$replace</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3164"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3165"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$replace</span>&nbsp;=&nbsp;<span class="src-var">$matches</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3166"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3167"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-var">$before</span></span></div></li>
+<li><div class="src-line"><a name="a3168"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;<span class="src-str">'&lt;|!REG3XP'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_hmr_key</span>&nbsp;.<span class="src-str">'!&gt;'</span></span></div></li>
+<li><div class="src-line"><a name="a3169"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-str">&quot;\n&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-str">&quot;|&gt;\n&lt;|!REG3XP&quot;</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_hmr_key</span>&nbsp;.&nbsp;<span class="src-str">'!&gt;'</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$replace</span><span class="src-sym">)</span></span></div></li>
+<li><div class="src-line"><a name="a3170"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;<span class="src-str">'|&gt;'</span></span></div></li>
+<li><div class="src-line"><a name="a3171"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.&nbsp;<span class="src-var">$after</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3172"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3173"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3174"></a><span class="src-doc">/**</span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;</span></span></div></li>
+<li><div class="src-line"><a name="a3175"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Takes&nbsp;a&nbsp;string&nbsp;that&nbsp;has&nbsp;no&nbsp;strings&nbsp;or&nbsp;comments&nbsp;in&nbsp;it,&nbsp;and&nbsp;highlights</span></div></li>
+<li><div class="src-line"><a name="a3176"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;stuff&nbsp;like&nbsp;keywords,&nbsp;numbers&nbsp;and&nbsp;methods.</span></div></li>
+<li><div class="src-line"><a name="a3177"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a3178"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@param&nbsp;</span><span class="src-doc-type">string&nbsp;</span><span class="src-doc">The&nbsp;string&nbsp;to&nbsp;parse&nbsp;for&nbsp;keyword,&nbsp;numbers&nbsp;etc.</span></div></li>
+<li><div class="src-line"><a name="a3179"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@since</span><span class="src-doc">&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a3180"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@access</span><span class="src-doc">&nbsp;private</span></div></li>
+<li><div class="src-line"><a name="a3181"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span class="src-doc-coretag">@todo</span><span class="src-doc">&nbsp;BUGGY!&nbsp;Why?&nbsp;Why&nbsp;not&nbsp;build&nbsp;string&nbsp;and&nbsp;return?</span></div></li>
+<li><div class="src-line"><a name="a3182"></a><span class="src-doc">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span class="src-str"></span></span></div></li>
+<li><div class="src-line"><a name="a3183"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<span class="src-id">parse_non_string_part</span><span class="src-sym">(</span><span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3184"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3185"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3186"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Regular&nbsp;expressions</span></span></div></li>
+<li><div class="src-line"><a name="a3187"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$key</span>&nbsp;=&gt;&nbsp;<span class="src-var">$regexp</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3188"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3189"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/is_array">is_array</a><span class="src-sym">(</span><span class="src-var">$regexp</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3190"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers</span>&nbsp;!=&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_NO_LINE_NUMBERS&quot;&gt;GESHI_NO_LINE_NUMBERS&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3191"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;produce&nbsp;valid&nbsp;HTML&nbsp;when&nbsp;we&nbsp;match&nbsp;multiple&nbsp;lines</span></span></div></li>
+<li><div class="src-line"><a name="a3192"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_hmr_replace</span>&nbsp;=&nbsp;<span class="src-var">$regexp</span><span class="src-sym">[</span><span class="src-id">GESHI_REPLACE</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3193"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_hmr_before</span>&nbsp;=&nbsp;<span class="src-var">$regexp</span><span class="src-sym">[</span><span class="src-id">GESHI_BEFORE</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3194"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_hmr_key</span>&nbsp;=&nbsp;<span class="src-var">$key</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3195"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_hmr_after</span>&nbsp;=&nbsp;<span class="src-var">$regexp</span><span class="src-sym">[</span><span class="src-id">GESHI_AFTER</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3196"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<a href="http://www.php.net/preg_replace_callback">preg_replace_callback</a><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a3197"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">&quot;/&quot;</span>&nbsp;.&nbsp;<span class="src-var">$regexp</span><span class="src-sym">[</span><span class="src-id">GESHI_SEARCH</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">"</span></span>/{<span class="src-var">$regexp</span><span class="src-sym">[</span><span class="src-id">GESHI_MODIFIERS</span><span class="src-sym">]</span><span class="src-sym">}</span><span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a3198"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'handle_multiline_regexps'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a3199"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3200"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_hmr_replace</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3201"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_hmr_before</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3202"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_hmr_after</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3203"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3204"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<a href="http://www.php.net/preg_replace">preg_replace</a><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a3205"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'/'</span>&nbsp;.&nbsp;<span class="src-var">$regexp</span><span class="src-sym">[</span><span class="src-id">GESHI_SEARCH</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'/'</span>&nbsp;.&nbsp;<span class="src-var">$regexp</span><span class="src-sym">[</span><span class="src-id">GESHI_MODIFIERS</span><span class="src-sym">]</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a3206"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$regexp</span><span class="src-sym">[</span><span class="src-id">GESHI_BEFORE</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&lt;|!REG3XP'</span>.&nbsp;<span class="src-var">$key</span>&nbsp;.<span class="src-str">'!&gt;'</span>&nbsp;.&nbsp;<span class="src-var">$regexp</span><span class="src-sym">[</span><span class="src-id">GESHI_REPLACE</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'|&gt;'</span>&nbsp;.&nbsp;<span class="src-var">$regexp</span><span class="src-sym">[</span><span class="src-id">GESHI_AFTER</span><span class="src-sym">]</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a3207"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3208"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3209"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3210"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers</span>&nbsp;!=&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_NO_LINE_NUMBERS&quot;&gt;GESHI_NO_LINE_NUMBERS&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3211"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;produce&nbsp;valid&nbsp;HTML&nbsp;when&nbsp;we&nbsp;match&nbsp;multiple&nbsp;lines</span></span></div></li>
+<li><div class="src-line"><a name="a3212"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_hmr_key</span>&nbsp;=&nbsp;<span class="src-var">$key</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3213"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<a href="http://www.php.net/preg_replace_callback">preg_replace_callback</a><span class="src-sym">(</span>&nbsp;<span class="src-str">&quot;/(&quot;</span>&nbsp;.&nbsp;<span class="src-var">$regexp</span>&nbsp;.&nbsp;<span class="src-str">&quot;)/&quot;</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a3214"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'handle_multiline_regexps'</span><span class="src-sym">)</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3215"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_hmr_key</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3216"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3217"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<a href="http://www.php.net/preg_replace">preg_replace</a><span class="src-sym">(</span>&nbsp;<span class="src-str">&quot;/(&quot;</span>&nbsp;.&nbsp;<span class="src-var">$regexp</span>&nbsp;.&nbsp;<span class="src-str">&quot;)/&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-str">"</span></span>&lt;|!REG3XP<span class="src-var">$key</span>!&gt;\\1|&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">,</span>&nbsp;<span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3218"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3219"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3220"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3221"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3222"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3223"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Highlight&nbsp;numbers.&nbsp;As&nbsp;of&nbsp;1.0.8&nbsp;we&nbsp;support&nbsp;diffent&nbsp;types&nbsp;of&nbsp;numbers</span></span></div></li>
+<li><div class="src-line"><a name="a3224"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$numbers_found</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3225"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]</span>&nbsp;&amp;&amp;&nbsp;<a href="http://www.php.net/preg_match">preg_match</a><span class="src-sym">(</span><span class="src-str">'#\d#'</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;<span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3226"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$numbers_found</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3227"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3228"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//For&nbsp;each&nbsp;of&nbsp;the&nbsp;formats&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a3229"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'NUMBERS_RXCACHE'</span><span class="src-sym">]</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$id</span>&nbsp;=&gt;&nbsp;<span class="src-var">$regexp</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3230"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Check&nbsp;if&nbsp;it&nbsp;should&nbsp;be&nbsp;highlighted&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a3231"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<a href="http://www.php.net/preg_replace">preg_replace</a><span class="src-sym">(</span><span class="src-var">$regexp</span><span class="src-sym">,</span>&nbsp;<span class="src-str">"</span></span>&lt;|/NUM!<span class="src-var">$id</span>/&gt;\\1|&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">,</span>&nbsp;<span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3232"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3233"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3234"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3235"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Highlight&nbsp;keywords</span></span></div></li>
+<li><div class="src-line"><a name="a3236"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$disallowed_before</span>&nbsp;=&nbsp;<span class="src-str">&quot;(?&lt;![a-zA-Z0-9\$_\|\#;&gt;|^&amp;&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3237"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$disallowed_after</span>&nbsp;=&nbsp;<span class="src-str">&quot;(?![a-zA-Z0-9_\|%\\-&amp;;&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3238"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'STRINGS'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3239"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$quotemarks</span>&nbsp;=&nbsp;<a href="http://www.php.net/preg_quote">preg_quote</a><span class="src-sym">(</span><a href="http://www.php.net/implode">implode</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'QUOTEMARKS'</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'/'</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3240"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$disallowed_before</span>&nbsp;.=&nbsp;<span class="src-var">$quotemarks</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3241"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$disallowed_after</span>&nbsp;.=&nbsp;<span class="src-var">$quotemarks</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3242"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3243"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$disallowed_before</span>&nbsp;.=&nbsp;<span class="src-str">&quot;])&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3244"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$disallowed_after</span>&nbsp;.=&nbsp;<span class="src-str">&quot;])&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3245"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3246"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parser_control_pergroup</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3247"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3248"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3249"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$x</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span>&nbsp;<span class="src-comm">//&nbsp;check&nbsp;wether&nbsp;per-keyword-group&nbsp;parser_control&nbsp;is&nbsp;enabled</span></span></div></li>
+<li><div class="src-line"><a name="a3250"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'DISALLOWED_BEFORE'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3251"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$disallowed_before</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'DISALLOWED_BEFORE'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3252"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++<span class="src-var">$x</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3253"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3254"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'DISALLOWED_AFTER'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3255"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$disallowed_after</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'DISALLOWED_AFTER'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3256"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++<span class="src-var">$x</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3257"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3258"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parser_control_pergroup</span>&nbsp;=&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/count">count</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;-&nbsp;<span class="src-var">$x</span><span class="src-sym">)</span>&nbsp;>&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3259"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3260"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3261"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3262"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;if&nbsp;this&nbsp;is&nbsp;changed,&nbsp;don't&nbsp;forget&nbsp;to&nbsp;change&nbsp;it&nbsp;below</span></span></div></li>
+<li><div class="src-line"><a name="a3263"></a></span><span class="src-str"><span class="src-comm">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!empty($disallowed_before))&nbsp;{</span></span></div></li>
+<li><div class="src-line"><a name="a3264"></a></span><span class="src-str"><span class="src-comm">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$disallowed_before&nbsp;=&nbsp;&quot;(?&lt;![$disallowed_before])&quot;;</span></span></div></li>
+<li><div class="src-line"><a name="a3265"></a></span><span class="src-str"><span class="src-comm">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div></li>
+<li><div class="src-line"><a name="a3266"></a></span><span class="src-str"><span class="src-comm">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!empty($disallowed_after))&nbsp;{</span></span></div></li>
+<li><div class="src-line"><a name="a3267"></a></span><span class="src-str"><span class="src-comm">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$disallowed_after&nbsp;=&nbsp;&quot;(?![$disallowed_after])&quot;;</span></span></div></li>
+<li><div class="src-line"><a name="a3268"></a></span><span class="src-str"><span class="src-comm">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div></li>
+<li><div class="src-line"><a name="a3269"></a></span><span class="src-str"><span class="src-comm"></span></span></div></li>
+<li><div class="src-line"><a name="a3270"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/array_keys">array_keys</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$k</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3271"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;||</span></div></li>
+<li><div class="src-line"><a name="a3272"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3273"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3274"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$case_sensitive</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'CASE_SENSITIVE'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3275"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$modifiers</span>&nbsp;=&nbsp;<span class="src-var">$case_sensitive</span>&nbsp;?&nbsp;<span class="src-str">''</span>&nbsp;:&nbsp;<span class="src-str">'i'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3276"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3277"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;NEW&nbsp;in&nbsp;1.0.8&nbsp;-&nbsp;per-keyword-group&nbsp;parser&nbsp;control</span></span></div></li>
+<li><div class="src-line"><a name="a3278"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$disallowed_before_local</span>&nbsp;=&nbsp;<span class="src-var">$disallowed_before</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3279"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$disallowed_after_local</span>&nbsp;=&nbsp;<span class="src-var">$disallowed_after</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3280"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$parser_control_pergroup</span>&nbsp;&amp;&amp;&nbsp;isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3281"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'DISALLOWED_BEFORE'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3282"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$disallowed_before_local</span>&nbsp;=</span></div></li>
+<li><div class="src-line"><a name="a3283"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'DISALLOWED_BEFORE'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3284"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3285"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3286"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'DISALLOWED_AFTER'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3287"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$disallowed_after_local</span>&nbsp;=</span></div></li>
+<li><div class="src-line"><a name="a3288"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'DISALLOWED_AFTER'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3289"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3290"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3291"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3292"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_kw_replace_group</span>&nbsp;=&nbsp;<span class="src-var">$k</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3293"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3294"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//NEW&nbsp;in&nbsp;1.0.8,&nbsp;the&nbsp;cached&nbsp;regexp&nbsp;list</span></span></div></li>
+<li><div class="src-line"><a name="a3295"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;since&nbsp;we&nbsp;don't&nbsp;want&nbsp;PHP&nbsp;/&nbsp;PCRE&nbsp;to&nbsp;crash&nbsp;due&nbsp;to&nbsp;too&nbsp;large&nbsp;patterns&nbsp;we&nbsp;split&nbsp;them&nbsp;into&nbsp;smaller&nbsp;chunks</span></span></div></li>
+<li><div class="src-line"><a name="a3296"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">for</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$set</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$set_length</span>&nbsp;=&nbsp;<a href="http://www.php.net/count">count</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'CACHED_KEYWORD_LISTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span>&nbsp;<span class="src-var">$set</span>&nbsp;<&nbsp;&nbsp;<span class="src-var">$set_length</span><span class="src-sym">;</span>&nbsp;++<span class="src-var">$set</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3297"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$keywordset</span>&nbsp;=<span class="src-sym">&</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'CACHED_KEYWORD_LISTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$set</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3298"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Might&nbsp;make&nbsp;a&nbsp;more&nbsp;unique&nbsp;string&nbsp;for&nbsp;putting&nbsp;the&nbsp;number&nbsp;in&nbsp;soon</span></span></div></li>
+<li><div class="src-line"><a name="a3299"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Basically,&nbsp;we&nbsp;don't&nbsp;put&nbsp;the&nbsp;styles&nbsp;in&nbsp;yet&nbsp;because&nbsp;then&nbsp;the&nbsp;styles&nbsp;themselves&nbsp;will</span></span></div></li>
+<li><div class="src-line"><a name="a3300"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;get&nbsp;highlighted&nbsp;if&nbsp;the&nbsp;language&nbsp;has&nbsp;a&nbsp;CSS&nbsp;keyword&nbsp;in&nbsp;it&nbsp;(like&nbsp;CSS,&nbsp;for&nbsp;example&nbsp;;))</span></span></div></li>
+<li><div class="src-line"><a name="a3301"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<a href="http://www.php.net/preg_replace_callback">preg_replace_callback</a><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a3302"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">"</span></span>/<span class="src-var">$disallowed_before_local</span>({<span class="src-var">$keywordset</span><span class="src-sym">}</span>)(?!\&lt;DOT\&gt;(?:htm|php))<span class="src-var">$disallowed_after_local</span>/<span class="src-var">$modifiers</span><span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a3303"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'handle_keyword_replace'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a3304"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span></span></div></li>
+<li><div class="src-line"><a name="a3305"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3306"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3307"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3308"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3309"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3310"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//</span></span></div></li>
+<li><div class="src-line"><a name="a3311"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Now&nbsp;that's&nbsp;all&nbsp;done,&nbsp;replace&nbsp;/[number]/&nbsp;with&nbsp;the&nbsp;correct&nbsp;styles</span></span></div></li>
+<li><div class="src-line"><a name="a3312"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//</span></span></div></li>
+<li><div class="src-line"><a name="a3313"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/array_keys">array_keys</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$k</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3314"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3315"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>&nbsp;.</span></div></li>
+<li><div class="src-line"><a name="a3316"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;?</span></div></li>
+<li><div class="src-line"><a name="a3317"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$k</span><span class="src-sym">]</span>&nbsp;:&nbsp;<span class="src-str">&quot;&quot;</span><span class="src-sym">)</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3318"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3319"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;kw'</span>&nbsp;.&nbsp;<span class="src-var">$k</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3320"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3321"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-str">"</span></span>&lt;|/<span class="src-var">$k</span>/&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">,</span>&nbsp;</span><span class="src-str">&quot;</span>&lt;|<span class="src-var">$attributes</span>&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">,</span>&nbsp;<span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3322"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3323"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3324"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$numbers_found</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3325"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Put&nbsp;number&nbsp;styles&nbsp;in</span></span></div></li>
+<li><div class="src-line"><a name="a3326"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'NUMBERS_RXCACHE'</span><span class="src-sym">]</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$id</span>&nbsp;=&gt;&nbsp;<span class="src-var">$regexp</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3327"></a></span><span class="src-str"><span class="src-comm">//Commented&nbsp;out&nbsp;for&nbsp;now,&nbsp;as&nbsp;this&nbsp;needs&nbsp;some&nbsp;review&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a3328"></a></span><span class="src-str"><span class="src-comm">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($numbers_permissions&nbsp;&amp;&nbsp;$id)&nbsp;{</span></span></div></li>
+<li><div class="src-line"><a name="a3329"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Get&nbsp;the&nbsp;appropriate&nbsp;style&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a3330"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Checking&nbsp;for&nbsp;unset&nbsp;styles&nbsp;is&nbsp;done&nbsp;by&nbsp;the&nbsp;style&nbsp;cache&nbsp;builder&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a3331"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3332"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$id</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3333"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3334"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;nu'</span>.<span class="src-var">$id</span>.<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3335"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3336"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3337"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Set&nbsp;in&nbsp;the&nbsp;correct&nbsp;styles&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a3338"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-str">"</span></span>/NUM!<span class="src-var">$id</span>/<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">,</span>&nbsp;<span class="src-var">$attributes</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3339"></a></span><span class="src-str"><span class="src-comm">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div></li>
+<li><div class="src-line"><a name="a3340"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3341"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3342"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3343"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Highlight&nbsp;methods&nbsp;and&nbsp;fields&nbsp;in&nbsp;objects</span></span></div></li>
+<li><div class="src-line"><a name="a3344"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'METHODS'</span><span class="src-sym">]</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'OOLANG'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3345"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$oolang_spaces</span>&nbsp;=&nbsp;<span class="src-str">&quot;[\s]*&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3346"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$oolang_before</span>&nbsp;=&nbsp;<span class="src-str">&quot;&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3347"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$oolang_after</span>&nbsp;=&nbsp;<span class="src-str">&quot;[a-zA-Z][a-zA-Z0-9_]*&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3348"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3349"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'OOLANG'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3350"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'OOLANG'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'MATCH_BEFORE'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3351"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$oolang_before</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'OOLANG'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'MATCH_BEFORE'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3352"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3353"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'OOLANG'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'MATCH_AFTER'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3354"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$oolang_after</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'OOLANG'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'MATCH_AFTER'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3355"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3356"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'OOLANG'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'MATCH_SPACES'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3357"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$oolang_spaces</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'OOLANG'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'MATCH_SPACES'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3358"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3359"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3360"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3361"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3362"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'OBJECT_SPLITTERS'</span><span class="src-sym">]</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$key</span>&nbsp;=&gt;&nbsp;<span class="src-var">$splitter</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3363"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-id">false</span>&nbsp;!==&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$stuff_to_parse</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$splitter</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3364"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3365"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'METHODS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3366"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3367"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;me'</span>&nbsp;.&nbsp;<span class="src-var">$key</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3368"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3369"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<a href="http://www.php.net/preg_replace">preg_replace</a><span class="src-sym">(</span><span class="src-str">"</span></span>/(<span class="src-var">$oolang_before</span>)(<span class="src-str">&quot;&nbsp;</span><span class="src-str">.&nbsp;<span class="src-id">preg_quote</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'OBJECT_SPLITTERS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'/'</span><span class="src-sym">)</span>&nbsp;.&nbsp;<span class="src-str">"</span></span>)(<span class="src-var">$oolang_spaces</span>)(<span class="src-var">$oolang_after</span>)/<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">,</span>&nbsp;</span><span class="src-str">&quot;</span>\\1\\2\\3&lt;|<span class="src-var">$attributes</span>&gt;\\4|&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">,</span>&nbsp;<span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3370"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3371"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3372"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3373"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3374"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//</span></span></div></li>
+<li><div class="src-line"><a name="a3375"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Highlight&nbsp;brackets.&nbsp;Yes,&nbsp;I've&nbsp;tried&nbsp;adding&nbsp;a&nbsp;semi-colon&nbsp;to&nbsp;this&nbsp;list.</span></span></div></li>
+<li><div class="src-line"><a name="a3376"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;You&nbsp;try&nbsp;it,&nbsp;and&nbsp;see&nbsp;what&nbsp;happens&nbsp;;)</span></span></div></li>
+<li><div class="src-line"><a name="a3377"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;TODO:&nbsp;Fix&nbsp;lexic&nbsp;permissions&nbsp;not&nbsp;converting&nbsp;entities&nbsp;if&nbsp;shouldn't</span></span></div></li>
+<li><div class="src-line"><a name="a3378"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;be&nbsp;highlighting&nbsp;regardless</span></span></div></li>
+<li><div class="src-line"><a name="a3379"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//</span></span></div></li>
+<li><div class="src-line"><a name="a3380"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'BRACKETS'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3381"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'CACHE_BRACKET_MATCH'</span><span class="src-sym">]</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a3382"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'CACHE_BRACKET_REPLACE'</span><span class="src-sym">]</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3383"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3384"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3385"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3386"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//FIX&nbsp;for&nbsp;symbol&nbsp;highlighting&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a3387"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'SYMBOLS'</span><span class="src-sym">]</span>&nbsp;&amp;&amp;&nbsp;<span class="src-sym">!</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'SYMBOLS'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3388"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Get&nbsp;all&nbsp;matches&nbsp;and&nbsp;throw&nbsp;away&nbsp;those&nbsp;witin&nbsp;a&nbsp;block&nbsp;that&nbsp;is&nbsp;already&nbsp;highlighted...&nbsp;(i.e.&nbsp;matched&nbsp;by&nbsp;a&nbsp;regexp)</span></span></div></li>
+<li><div class="src-line"><a name="a3389"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$n_symbols</span>&nbsp;=&nbsp;<a href="http://www.php.net/preg_match_all">preg_match_all</a><span class="src-sym">(</span><span class="src-str">&quot;/&lt;\|(?:&lt;DOT&gt;|[^&gt;])+&gt;(?:(?!\|&gt;).*?)\|&gt;|&lt;\/a&gt;|(?:&quot;</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'SYMBOL_SEARCH'</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">&quot;)+/&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$stuff_to_parse</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$pot_symbols</span><span class="src-sym">,</span>&nbsp;<span class="src-id">PREG_OFFSET_CAPTURE</span>&nbsp;|&nbsp;<span class="src-id">PREG_SET_ORDER</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3390"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$global_offset</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3391"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">for</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$s_id</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span>&nbsp;<span class="src-var">$s_id</span>&nbsp;<&nbsp;<span class="src-var">$n_symbols</span><span class="src-sym">;</span>&nbsp;++<span class="src-var">$s_id</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3392"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_match</span>&nbsp;=&nbsp;<span class="src-var">$pot_symbols</span><span class="src-sym">[</span><span class="src-var">$s_id</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3393"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$symbol_match</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'&lt;'</span><span class="src-sym">)</span>&nbsp;!==&nbsp;<span class="src-id">false</span>&nbsp;||&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$symbol_match</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'&gt;'</span><span class="src-sym">)</span>&nbsp;!==&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3394"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;already&nbsp;highlighted&nbsp;blocks&nbsp;_must_&nbsp;include&nbsp;either&nbsp;&lt;&nbsp;or&nbsp;&gt;</span></span></div></li>
+<li><div class="src-line"><a name="a3395"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;so&nbsp;if&nbsp;this&nbsp;conditional&nbsp;applies,&nbsp;we&nbsp;have&nbsp;to&nbsp;skip&nbsp;this&nbsp;match</span></span></div></li>
+<li><div class="src-line"><a name="a3396"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;BenBE:&nbsp;UNLESS&nbsp;the&nbsp;block&nbsp;contains&nbsp;&lt;SEMI&gt;&nbsp;or&nbsp;&lt;PIPE&gt;</span></span></div></li>
+<li><div class="src-line"><a name="a3397"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$symbol_match</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'&lt;SEMI&gt;'</span><span class="src-sym">)</span>&nbsp;===&nbsp;<span class="src-id">false</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a3398"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$symbol_match</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'&lt;PIPE&gt;'</span><span class="src-sym">)</span>&nbsp;===&nbsp;<span class="src-id">false</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3399"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3400"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3401"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3402"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3403"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;if&nbsp;we&nbsp;reach&nbsp;this&nbsp;point,&nbsp;we&nbsp;have&nbsp;a&nbsp;valid&nbsp;match&nbsp;which&nbsp;needs&nbsp;to&nbsp;be&nbsp;highlighted</span></span></div></li>
+<li><div class="src-line"><a name="a3404"></a></span><span class="src-str"><span class="src-comm"></span></span></div></li>
+<li><div class="src-line"><a name="a3405"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_length</span>&nbsp;=&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$symbol_match</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3406"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_offset</span>&nbsp;=&nbsp;<span class="src-var">$pot_symbols</span><span class="src-sym">[</span><span class="src-var">$s_id</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3407"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$pot_symbols</span><span class="src-sym">[</span><span class="src-var">$s_id</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3408"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_end</span>&nbsp;=&nbsp;<span class="src-var">$symbol_length</span>&nbsp;+&nbsp;<span class="src-var">$symbol_offset</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3409"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_hl</span>&nbsp;=&nbsp;<span class="src-str">&quot;&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3410"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3411"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;if&nbsp;we&nbsp;have&nbsp;multiple&nbsp;styles,&nbsp;we&nbsp;have&nbsp;to&nbsp;handle&nbsp;them&nbsp;properly</span></span></div></li>
+<li><div class="src-line"><a name="a3412"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'MULTIPLE_SYMBOL_GROUPS'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3413"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$old_sym</span>&nbsp;=&nbsp;-<span class="src-num">1</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3414"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Split&nbsp;the&nbsp;current&nbsp;stuff&nbsp;to&nbsp;replace&nbsp;into&nbsp;its&nbsp;atomic&nbsp;symbols&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a3415"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/preg_match_all">preg_match_all</a><span class="src-sym">(</span><span class="src-str">&quot;/&quot;</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'SYMBOL_SEARCH'</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">&quot;/&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$symbol_match</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$sym_match_syms</span><span class="src-sym">,</span>&nbsp;<span class="src-id">PREG_PATTERN_ORDER</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3416"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$sym_match_syms</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$sym_ms</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3417"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Check&nbsp;if&nbsp;consequtive&nbsp;symbols&nbsp;belong&nbsp;to&nbsp;the&nbsp;same&nbsp;group&nbsp;to&nbsp;save&nbsp;output&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a3418"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'SYMBOL_DATA'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$sym_ms</span><span class="src-sym">]</span><span class="src-sym">)</span></span></div></li>
+<li><div class="src-line"><a name="a3419"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp;&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'SYMBOL_DATA'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$sym_ms</span><span class="src-sym">]</span>&nbsp;!=&nbsp;<span class="src-var">$old_sym</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3420"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>-<span class="src-num">1</span>&nbsp;!=&nbsp;<span class="src-var">$old_sym</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3421"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_hl</span>&nbsp;.=&nbsp;<span class="src-str">&quot;|&gt;&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3422"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3423"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$old_sym</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'SYMBOL_DATA'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$sym_ms</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3424"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3425"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_hl</span>&nbsp;.=&nbsp;<span class="src-str">'&lt;|&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'SYMBOLS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$old_sym</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3426"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3427"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_hl</span>&nbsp;.=&nbsp;<span class="src-str">'&lt;|&nbsp;class=&quot;sy'</span>&nbsp;.&nbsp;<span class="src-var">$old_sym</span>&nbsp;.&nbsp;<span class="src-str">'&quot;&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3428"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3429"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3430"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_hl</span>&nbsp;.=&nbsp;<span class="src-var">$sym_ms</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3431"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3432"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$sym_match_syms</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3433"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3434"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Close&nbsp;remaining&nbsp;tags&nbsp;and&nbsp;insert&nbsp;the&nbsp;replacement&nbsp;at&nbsp;the&nbsp;right&nbsp;position&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a3435"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Take&nbsp;caution&nbsp;if&nbsp;symbol_hl&nbsp;is&nbsp;empty&nbsp;to&nbsp;avoid&nbsp;doubled&nbsp;closing&nbsp;spans.</span></span></div></li>
+<li><div class="src-line"><a name="a3436"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>-<span class="src-num">1</span>&nbsp;!=&nbsp;<span class="src-var">$old_sym</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3437"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_hl</span>&nbsp;.=&nbsp;<span class="src-str">&quot;|&gt;&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3438"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3439"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3440"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3441"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_hl</span>&nbsp;=&nbsp;<span class="src-str">'&lt;|&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'SYMBOLS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3442"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3443"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_hl</span>&nbsp;=&nbsp;<span class="src-str">'&lt;|&nbsp;class=&quot;sy0&quot;&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3444"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3445"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$symbol_hl</span>&nbsp;.=&nbsp;<span class="src-var">$symbol_match</span>&nbsp;.&nbsp;<span class="src-str">'|&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3446"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3447"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3448"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<a href="http://www.php.net/substr_replace">substr_replace</a><span class="src-sym">(</span><span class="src-var">$stuff_to_parse</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$symbol_hl</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$symbol_offset</span>&nbsp;+&nbsp;<span class="src-var">$global_offset</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$symbol_length</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3449"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3450"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;since&nbsp;we&nbsp;replace&nbsp;old&nbsp;text&nbsp;with&nbsp;something&nbsp;of&nbsp;different&nbsp;size,</span></span></div></li>
+<li><div class="src-line"><a name="a3451"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;we'll&nbsp;have&nbsp;to&nbsp;keep&nbsp;track&nbsp;of&nbsp;the&nbsp;differences</span></span></div></li>
+<li><div class="src-line"><a name="a3452"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$global_offset</span>&nbsp;+=&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$symbol_hl</span><span class="src-sym">)</span>&nbsp;-&nbsp;<span class="src-var">$symbol_length</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3453"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3454"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3455"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//FIX&nbsp;for&nbsp;symbol&nbsp;highlighting&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a3456"></a></span><span class="src-str"><span class="src-comm"></span></span></div></li>
+<li><div class="src-line"><a name="a3457"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Add&nbsp;class/style&nbsp;for&nbsp;regexps</span></span></div></li>
+<li><div class="src-line"><a name="a3458"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/array_keys">array_keys</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$key</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3459"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3460"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/is_callable">is_callable</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3461"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_rx_key</span>&nbsp;=&nbsp;<span class="src-var">$key</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3462"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<a href="http://www.php.net/preg_replace_callback">preg_replace_callback</a><span class="src-sym">(</span><span class="src-str">"</span></span>/!REG3XP<span class="src-var">$key</span>!(.*)\|&gt;/U<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a3463"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'handle_regexps_callback'</span><span class="src-sym">)</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a3464"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3465"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3466"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3467"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3468"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3469"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/is_array">is_array</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a3470"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/array_key_exists">array_key_exists</a><span class="src-sym">(</span><span class="src-id">GESHI_CLASS</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3471"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;'</span>&nbsp;.</span></div></li>
+<li><div class="src-line"><a name="a3472"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-id">GESHI_CLASS</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3473"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3474"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;re'</span>&nbsp;.&nbsp;<span class="src-var">$key</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3475"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3476"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3477"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-str">"</span></span>!REG3XP<span class="src-var">$key</span>!<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">,</span>&nbsp;</span><span class="src-str">&quot;</span><span class="src-var">$attributes</span><span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">,</span>&nbsp;<span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3478"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3479"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3480"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3481"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3482"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Replace&nbsp;&lt;DOT&gt;&nbsp;with&nbsp;.&nbsp;for&nbsp;urls</span></span></div></li>
+<li><div class="src-line"><a name="a3483"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<span class="src-id">str_replace</span><span class="src-sym">(</span><span class="src-str">'&lt;DOT&gt;'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'.'</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3484"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Replace&nbsp;&lt;|UR1|&nbsp;with&nbsp;&lt;a&nbsp;href=&nbsp;for&nbsp;urls&nbsp;also</span></span></div></li>
+<li><div class="src-line"><a name="a3485"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">link_styles</span><span class="src-sym">[</span><span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_LINK&quot;&gt;GESHI_LINK&lt;/a&gt;</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3486"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3487"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-str">'&lt;|UR1|'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'&lt;a'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">link_target</span>&nbsp;.&nbsp;<span class="src-str">'&nbsp;href='</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3488"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3489"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-str">'&lt;|UR1|'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'&lt;a'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">link_target</span>&nbsp;.&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">link_styles</span><span class="src-sym">[</span><span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_LINK&quot;&gt;GESHI_LINK&lt;/a&gt;</span><span class="src-sym">]</span>&nbsp;.&nbsp;<span class="src-str">'&quot;&nbsp;href='</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3490"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3491"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3492"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-str">'&lt;|UR1|'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'&lt;a'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">link_target</span>&nbsp;.&nbsp;<span class="src-str">'&nbsp;href='</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3493"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3494"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3495"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//</span></span></div></li>
+<li><div class="src-line"><a name="a3496"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;NOW&nbsp;we&nbsp;add&nbsp;the&nbsp;span&nbsp;thingy&nbsp;;)</span></span></div></li>
+<li><div class="src-line"><a name="a3497"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//</span></span></div></li>
+<li><div class="src-line"><a name="a3498"></a></span><span class="src-str"><span class="src-comm"></span></span></div></li>
+<li><div class="src-line"><a name="a3499"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-str">'&lt;|'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'&lt;span'</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$stuff_to_parse</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3500"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a>&nbsp;<span class="src-sym">(</span>&nbsp;<span class="src-str">'|&gt;'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'&lt;/span&gt;'</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$stuff_to_parse</span>&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3501"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$stuff_to_parse</span><span class="src-sym">,</span>&nbsp;<span class="src-num">1</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3502"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3503"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3504"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;/**</span></div></li>
+<li><div class="src-line"><a name="a3505"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Sets&nbsp;the&nbsp;time&nbsp;taken&nbsp;to&nbsp;parse&nbsp;the&nbsp;code</span></div></li>
+<li><div class="src-line"><a name="a3506"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a3507"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;microtime&nbsp;The&nbsp;time&nbsp;when&nbsp;parsing&nbsp;started</span></div></li>
+<li><div class="src-line"><a name="a3508"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;microtime&nbsp;The&nbsp;time&nbsp;when&nbsp;parsing&nbsp;ended</span></div></li>
+<li><div class="src-line"><a name="a3509"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@since&nbsp;1.0.2</span></div></li>
+<li><div class="src-line"><a name="a3510"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@access&nbsp;private</span></div></li>
+<li><div class="src-line"><a name="a3511"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a3512"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<span class="src-id">set_time</span><span class="src-sym">(</span><span class="src-var">$start_time</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$end_time</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3513"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$start</span>&nbsp;=&nbsp;<a href="http://www.php.net/explode">explode</a><span class="src-sym">(</span><span class="src-str">'&nbsp;'</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$start_time</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3514"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$end</span>&nbsp;=&nbsp;<a href="http://www.php.net/explode">explode</a><span class="src-sym">(</span><span class="src-str">'&nbsp;'</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$end_time</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3515"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="http://www.php.net/time">time</a>&nbsp;=&nbsp;<span class="src-var">$end</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;+&nbsp;<span class="src-var">$end</span><span class="src-sym">[</span><span class="src-num">1</span><span class="src-sym">]</span>&nbsp;-&nbsp;<span class="src-var">$start</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span>&nbsp;-&nbsp;<span class="src-var">$start</span><span class="src-sym">[</span><span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3516"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3517"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3518"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;/**</span></div></li>
+<li><div class="src-line"><a name="a3519"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Gets&nbsp;the&nbsp;time&nbsp;taken&nbsp;to&nbsp;parse&nbsp;the&nbsp;code</span></div></li>
+<li><div class="src-line"><a name="a3520"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a3521"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;double&nbsp;The&nbsp;time&nbsp;taken&nbsp;to&nbsp;parse&nbsp;the&nbsp;code</span></div></li>
+<li><div class="src-line"><a name="a3522"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@since&nbsp;&nbsp;1.0.2</span></div></li>
+<li><div class="src-line"><a name="a3523"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a3524"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodget_time">get_time</a><span class="src-sym">(</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3525"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="http://www.php.net/time">time</a><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3526"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3527"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3528"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;/**</span></div></li>
+<li><div class="src-line"><a name="a3529"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Merges&nbsp;arrays&nbsp;recursively,&nbsp;overwriting&nbsp;values&nbsp;of&nbsp;the&nbsp;first&nbsp;array&nbsp;with&nbsp;values&nbsp;of&nbsp;later&nbsp;arrays</span></div></li>
+<li><div class="src-line"><a name="a3530"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a3531"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@since&nbsp;1.0.8</span></div></li>
+<li><div class="src-line"><a name="a3532"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@access&nbsp;private</span></div></li>
+<li><div class="src-line"><a name="a3533"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a3534"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<span class="src-id">merge_arrays</span><span class="src-sym">(</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3535"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$arrays</span>&nbsp;=&nbsp;<a href="http://www.php.net/func_get_args">func_get_args</a><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3536"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$narrays</span>&nbsp;=&nbsp;<a href="http://www.php.net/count">count</a><span class="src-sym">(</span><span class="src-var">$arrays</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3537"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3538"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;check&nbsp;arguments</span></span></div></li>
+<li><div class="src-line"><a name="a3539"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;comment&nbsp;out&nbsp;if&nbsp;more&nbsp;performance&nbsp;is&nbsp;necessary&nbsp;(in&nbsp;this&nbsp;case&nbsp;the&nbsp;foreach&nbsp;loop&nbsp;will&nbsp;trigger&nbsp;a&nbsp;warning&nbsp;if&nbsp;the&nbsp;argument&nbsp;is&nbsp;not&nbsp;an&nbsp;array)</span></span></div></li>
+<li><div class="src-line"><a name="a3540"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">for</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$i</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span>&nbsp;<span class="src-var">$i</span>&nbsp;<&nbsp;<span class="src-var">$narrays</span><span class="src-sym">;</span>&nbsp;<span class="src-var">$i</span>&nbsp;++<span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3541"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><a href="http://www.php.net/is_array">is_array</a><span class="src-sym">(</span><span class="src-var">$arrays</span><span class="src-sym">[</span><span class="src-var">$i</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3542"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;also&nbsp;array_merge_recursive&nbsp;returns&nbsp;nothing&nbsp;in&nbsp;this&nbsp;case</span></span></div></li>
+<li><div class="src-line"><a name="a3543"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/trigger_error">trigger_error</a><span class="src-sym">(</span><span class="src-str">'Argument&nbsp;#'</span>&nbsp;.&nbsp;<span class="src-sym">(</span><span class="src-var">$i</span>+<span class="src-num">1</span><span class="src-sym">)</span>&nbsp;.&nbsp;<span class="src-str">'&nbsp;is&nbsp;not&nbsp;an&nbsp;array&nbsp;-&nbsp;trying&nbsp;to&nbsp;merge&nbsp;array&nbsp;with&nbsp;scalar!&nbsp;Returning&nbsp;false!'</span><span class="src-sym">,</span>&nbsp;<span class="src-id">E_USER_WARNING</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3544"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3545"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3546"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3547"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3548"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;the&nbsp;first&nbsp;array&nbsp;is&nbsp;in&nbsp;the&nbsp;output&nbsp;set&nbsp;in&nbsp;every&nbsp;case</span></span></div></li>
+<li><div class="src-line"><a name="a3549"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$ret</span>&nbsp;=&nbsp;<span class="src-var">$arrays</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3550"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3551"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;merege&nbsp;$ret&nbsp;with&nbsp;the&nbsp;remaining&nbsp;arrays</span></span></div></li>
+<li><div class="src-line"><a name="a3552"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">for</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$i</span>&nbsp;=&nbsp;<span class="src-num">1</span><span class="src-sym">;</span>&nbsp;<span class="src-var">$i</span>&nbsp;<&nbsp;<span class="src-var">$narrays</span><span class="src-sym">;</span>&nbsp;<span class="src-var">$i</span>&nbsp;++<span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3553"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$arrays</span><span class="src-sym">[</span><span class="src-var">$i</span><span class="src-sym">]</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$key</span>&nbsp;=&gt;&nbsp;<span class="src-var">$value</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3554"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/is_array">is_array</a><span class="src-sym">(</span><span class="src-var">$value</span><span class="src-sym">)</span>&nbsp;&amp;&amp;&nbsp;isset<span class="src-sym">(</span><span class="src-var">$ret</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3555"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;if&nbsp;$ret[$key]&nbsp;is&nbsp;not&nbsp;an&nbsp;array&nbsp;you&nbsp;try&nbsp;to&nbsp;merge&nbsp;an&nbsp;scalar&nbsp;value&nbsp;with&nbsp;an&nbsp;array&nbsp;-&nbsp;the&nbsp;result&nbsp;is&nbsp;not&nbsp;defined&nbsp;(incompatible&nbsp;arrays)</span></span></div></li>
+<li><div class="src-line"><a name="a3556"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;in&nbsp;this&nbsp;case&nbsp;the&nbsp;call&nbsp;will&nbsp;trigger&nbsp;an&nbsp;E_USER_WARNING&nbsp;and&nbsp;the&nbsp;$ret[$key]&nbsp;will&nbsp;be&nbsp;false.</span></span></div></li>
+<li><div class="src-line"><a name="a3557"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$ret</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">merge_arrays</span><span class="src-sym">(</span><span class="src-var">$ret</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$value</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3558"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3559"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$ret</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$value</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3560"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3561"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3562"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3563"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3564"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-var">$ret</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3565"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3566"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3567"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;/**</span></div></li>
+<li><div class="src-line"><a name="a3568"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Gets&nbsp;language&nbsp;information&nbsp;and&nbsp;stores&nbsp;it&nbsp;for&nbsp;later&nbsp;use</span></div></li>
+<li><div class="src-line"><a name="a3569"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a3570"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;string&nbsp;The&nbsp;filename&nbsp;of&nbsp;the&nbsp;language&nbsp;file&nbsp;you&nbsp;want&nbsp;to&nbsp;load</span></div></li>
+<li><div class="src-line"><a name="a3571"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@since&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a3572"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@access&nbsp;private</span></div></li>
+<li><div class="src-line"><a name="a3573"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@todo&nbsp;Needs&nbsp;to&nbsp;load&nbsp;keys&nbsp;for&nbsp;lexic&nbsp;permissions&nbsp;for&nbsp;keywords,&nbsp;regexps&nbsp;etc</span></div></li>
+<li><div class="src-line"><a name="a3574"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a3575"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<span class="src-id">load_language</span><span class="src-sym">(</span><span class="src-var">$file_name</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3576"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$file_name</span>&nbsp;==&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">loaded_language</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3577"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;this&nbsp;file&nbsp;is&nbsp;already&nbsp;loaded!</span></span></div></li>
+<li><div class="src-line"><a name="a3578"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3579"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3580"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3581"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Prepare&nbsp;some&nbsp;stuff&nbsp;before&nbsp;actually&nbsp;loading&nbsp;the&nbsp;language&nbsp;file</span></span></div></li>
+<li><div class="src-line"><a name="a3582"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">loaded_language</span>&nbsp;=&nbsp;<span class="src-var">$file_name</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3583"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">parse_cache_built</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3584"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodenable_highlighting">enable_highlighting</a><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3585"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$language_data</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3586"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3587"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Load&nbsp;the&nbsp;language&nbsp;file</span></span></div></li>
+<li><div class="src-line"><a name="a3588"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;require&nbsp;<span class="src-var">$file_name</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3589"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3590"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Perhaps&nbsp;some&nbsp;checking&nbsp;might&nbsp;be&nbsp;added&nbsp;here&nbsp;later&nbsp;to&nbsp;check&nbsp;that</span></span></div></li>
+<li><div class="src-line"><a name="a3591"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;$language&nbsp;data&nbsp;is&nbsp;a&nbsp;valid&nbsp;thing&nbsp;but&nbsp;maybe&nbsp;not</span></span></div></li>
+<li><div class="src-line"><a name="a3592"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span>&nbsp;=&nbsp;<span class="src-var">$language_data</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3593"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3594"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Set&nbsp;strict&nbsp;mode&nbsp;if&nbsp;should&nbsp;be&nbsp;set</span></span></div></li>
+<li><div class="src-line"><a name="a3595"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">strict_mode</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STRICT_MODE_APPLIES'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3596"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3597"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Set&nbsp;permissions&nbsp;for&nbsp;all&nbsp;lexics&nbsp;to&nbsp;true</span></span></div></li>
+<li><div class="src-line"><a name="a3598"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;so&nbsp;they'll&nbsp;be&nbsp;highlighted&nbsp;by&nbsp;default</span></span></div></li>
+<li><div class="src-line"><a name="a3599"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/array_keys">array_keys</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$key</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3600"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3601"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3602"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3603"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-id">false</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3604"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3605"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3606"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3607"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/array_keys">array_keys</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'COMMENT_SINGLE'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$key</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3608"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3609"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3610"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/array_keys">array_keys</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]</span><span class="src-sym">)</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$key</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3611"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3612"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3613"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3614"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;for&nbsp;BenBE&nbsp;and&nbsp;future&nbsp;code&nbsp;reviews:</span></span></div></li>
+<li><div class="src-line"><a name="a3615"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;we&nbsp;can&nbsp;use&nbsp;empty&nbsp;here&nbsp;since&nbsp;we&nbsp;only&nbsp;check&nbsp;for&nbsp;existance&nbsp;and&nbsp;emptiness&nbsp;of&nbsp;an&nbsp;array</span></span></div></li>
+<li><div class="src-line"><a name="a3616"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;if&nbsp;it&nbsp;is&nbsp;not&nbsp;an&nbsp;array&nbsp;at&nbsp;all&nbsp;but&nbsp;rather&nbsp;false&nbsp;or&nbsp;null&nbsp;this&nbsp;will&nbsp;work&nbsp;as&nbsp;intended&nbsp;as&nbsp;well</span></span></div></li>
+<li><div class="src-line"><a name="a3617"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;even&nbsp;if&nbsp;$this-&gt;language_data['PARSER_CONTROL']&nbsp;is&nbsp;undefined&nbsp;this&nbsp;won't&nbsp;trigger&nbsp;a&nbsp;notice</span></span></div></li>
+<li><div class="src-line"><a name="a3618"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'ENABLE_FLAGS'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3619"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'ENABLE_FLAGS'</span><span class="src-sym">]</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$flag</span>&nbsp;=&gt;&nbsp;<span class="src-var">$value</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3620"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;it's&nbsp;either&nbsp;true&nbsp;or&nbsp;false&nbsp;and&nbsp;maybe&nbsp;is&nbsp;true&nbsp;as&nbsp;well</span></span></div></li>
+<li><div class="src-line"><a name="a3621"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$perm</span>&nbsp;=&nbsp;<span class="src-var">$value</span>&nbsp;!==&nbsp;<span class="src-id">GESHI_NEVER</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3622"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$flag</span>&nbsp;==&nbsp;<span class="src-str">'ALL'</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3623"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodenable_highlighting">enable_highlighting</a><span class="src-sym">(</span><span class="src-var">$perm</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3624"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3625"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3626"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-var">$flag</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3627"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;unknown&nbsp;lexic&nbsp;permission</span></span></div></li>
+<li><div class="src-line"><a name="a3628"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3629"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3630"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/is_array">is_array</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-var">$flag</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3631"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-var">$flag</span><span class="src-sym">]</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$key</span>&nbsp;=&gt;&nbsp;<span class="src-var">$val</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3632"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-var">$flag</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$key</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$perm</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3633"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3634"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3635"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-var">$flag</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$perm</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3636"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3637"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3638"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'PARSER_CONTROL'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'ENABLE_FLAGS'</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3639"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3640"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3641"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//NEW&nbsp;in&nbsp;1.0.8:&nbsp;Allow&nbsp;styles&nbsp;to&nbsp;be&nbsp;loaded&nbsp;from&nbsp;a&nbsp;separate&nbsp;file&nbsp;to&nbsp;override&nbsp;defaults</span></span></div></li>
+<li><div class="src-line"><a name="a3642"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$style_filename</span>&nbsp;=&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$file_name</span><span class="src-sym">,</span>&nbsp;<span class="src-num">0</span><span class="src-sym">,</span>&nbsp;-<span class="src-num">4</span><span class="src-sym">)</span>&nbsp;.&nbsp;<span class="src-str">'.style.php'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3643"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/is_readable">is_readable</a><span class="src-sym">(</span><span class="src-var">$style_filename</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3644"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Clear&nbsp;any&nbsp;style_data&nbsp;that&nbsp;could&nbsp;have&nbsp;been&nbsp;set&nbsp;before&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a3645"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$style_data</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3646"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$style_data</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3647"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3648"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3649"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Read&nbsp;the&nbsp;Style&nbsp;Information&nbsp;from&nbsp;the&nbsp;style&nbsp;file</span></span></div></li>
+<li><div class="src-line"><a name="a3650"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-inc">include</span>&nbsp;<span class="src-var">$style_filename</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3651"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3652"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Apply&nbsp;the&nbsp;new&nbsp;styles&nbsp;to&nbsp;our&nbsp;current&nbsp;language&nbsp;styles</span></span></div></li>
+<li><div class="src-line"><a name="a3653"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$style_data</span><span class="src-sym">)</span>&nbsp;&amp;&amp;&nbsp;<a href="http://www.php.net/is_array">is_array</a><span class="src-sym">(</span><span class="src-var">$style_data</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3654"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span>&nbsp;=</span></div></li>
+<li><div class="src-line"><a name="a3655"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">merge_arrays</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$style_data</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3656"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3657"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3658"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3659"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3660"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;/**</span></div></li>
+<li><div class="src-line"><a name="a3661"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Takes&nbsp;the&nbsp;parsed&nbsp;code&nbsp;and&nbsp;various&nbsp;options,&nbsp;and&nbsp;creates&nbsp;the&nbsp;HTML</span></div></li>
+<li><div class="src-line"><a name="a3662"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;surrounding&nbsp;it&nbsp;to&nbsp;make&nbsp;it&nbsp;look&nbsp;nice.</span></div></li>
+<li><div class="src-line"><a name="a3663"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a3664"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;string&nbsp;The&nbsp;code&nbsp;already&nbsp;parsed&nbsp;(reference!)</span></div></li>
+<li><div class="src-line"><a name="a3665"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@since&nbsp;&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a3666"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@access&nbsp;private</span></div></li>
+<li><div class="src-line"><a name="a3667"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a3668"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<span class="src-id">finalise</span><span class="src-sym">(</span><span class="src-sym">&</span><span class="src-var">$parsed_code</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3669"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Remove&nbsp;end&nbsp;parts&nbsp;of&nbsp;important&nbsp;declarations</span></span></div></li>
+<li><div class="src-line"><a name="a3670"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;This&nbsp;is&nbsp;BUGGY!!&nbsp;My&nbsp;fault&nbsp;for&nbsp;bad&nbsp;code:&nbsp;fix&nbsp;coming&nbsp;in&nbsp;1.2</span></span></div></li>
+<li><div class="src-line"><a name="a3671"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;@todo&nbsp;Remove&nbsp;this&nbsp;crap</span></span></div></li>
+<li><div class="src-line"><a name="a3672"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodenable_important_blocks">enable_important_blocks</a>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a3673"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/strpos">strpos</a><span class="src-sym">(</span><span class="src-var">$parsed_code</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_START_IMPORTANT&quot;&gt;GESHI_START_IMPORTANT&lt;/a&gt;</span><span class="src-sym">))</span>&nbsp;===&nbsp;<span class="src-id">false</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3674"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_END_IMPORTANT&quot;&gt;GESHI_END_IMPORTANT&lt;/a&gt;</span><span class="src-sym">)</span><span class="src-sym">,</span>&nbsp;<span class="src-str">''</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$parsed_code</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3675"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3676"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3677"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Add&nbsp;HTML&nbsp;whitespace&nbsp;stuff&nbsp;if&nbsp;we're&nbsp;using&nbsp;the&nbsp;&lt;div&gt;&nbsp;header</span></span></div></li>
+<li><div class="src-line"><a name="a3678"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;!=&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE&quot;&gt;GESHI_HEADER_PRE&lt;/a&gt;</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;!=&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_VALID&quot;&gt;GESHI_HEADER_PRE_VALID&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3679"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">indent</span><span class="src-sym">(</span><span class="src-var">$parsed_code</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3680"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3681"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3682"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;purge&nbsp;some&nbsp;unnecessary&nbsp;stuff</span></span></div></li>
+<li><div class="src-line"><a name="a3683"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;NOTE:&nbsp;memorypeak&nbsp;#1&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a3684"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;=&nbsp;<a href="http://www.php.net/preg_replace">preg_replace</a><span class="src-sym">(</span><span class="src-str">'#&lt;span[^&gt;]+&gt;(\s*)&lt;/span&gt;#'</span><span class="src-sym">,</span>&nbsp;<span class="src-str">'\\1'</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$parsed_code</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3685"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3686"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;If&nbsp;we&nbsp;are&nbsp;using&nbsp;IDs&nbsp;for&nbsp;line&nbsp;numbers,&nbsp;there&nbsp;needs&nbsp;to&nbsp;be&nbsp;an&nbsp;overall</span></span></div></li>
+<li><div class="src-line"><a name="a3687"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;ID&nbsp;set&nbsp;to&nbsp;prevent&nbsp;collisions.</span></span></div></li>
+<li><div class="src-line"><a name="a3688"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">add_ids</span>&nbsp;&amp;&amp;&nbsp;<span class="src-sym">!</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">overall_id</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3689"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">overall_id</span>&nbsp;=&nbsp;<span class="src-str">'geshi-'</span>&nbsp;.&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><a href="http://www.php.net/md5">md5</a><span class="src-sym">(</span><a href="http://www.php.net/microtime">microtime</a><span class="src-sym">(</span><span class="src-sym">))</span><span class="src-sym">,</span>&nbsp;<span class="src-num">0</span><span class="src-sym">,</span>&nbsp;<span class="src-num">4</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3690"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3691"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3692"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Get&nbsp;code&nbsp;into&nbsp;lines</span></span></div></li>
+<li><div class="src-line"><a name="a3693"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;NOTE:&nbsp;memorypeak&nbsp;#2&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a3694"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$code</span>&nbsp;=&nbsp;<a href="http://www.php.net/explode">explode</a><span class="src-sym">(</span><span class="src-str">&quot;\n&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$parsed_code</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3695"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="http://www.php.net/header">header</a><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3696"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3697"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;If&nbsp;we're&nbsp;using&nbsp;line&nbsp;numbers,&nbsp;we&nbsp;insert&nbsp;&lt;li&gt;s&nbsp;and&nbsp;appropriate</span></span></div></li>
+<li><div class="src-line"><a name="a3698"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;markup&nbsp;to&nbsp;style&nbsp;them&nbsp;(otherwise&nbsp;we&nbsp;don't&nbsp;need&nbsp;to&nbsp;do&nbsp;anything)</span></span></div></li>
+<li><div class="src-line"><a name="a3699"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers</span>&nbsp;!=&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_NO_LINE_NUMBERS&quot;&gt;GESHI_NO_LINE_NUMBERS&lt;/a&gt;</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;!=&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_TABLE&quot;&gt;GESHI_HEADER_PRE_TABLE&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3700"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;If&nbsp;we're&nbsp;using&nbsp;the&nbsp;&lt;pre&gt;&nbsp;header,&nbsp;we&nbsp;shouldn't&nbsp;add&nbsp;newlines&nbsp;because</span></span></div></li>
+<li><div class="src-line"><a name="a3701"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;the&nbsp;&lt;pre&gt;&nbsp;will&nbsp;line-break&nbsp;them&nbsp;(and&nbsp;the&nbsp;&lt;li&gt;s&nbsp;already&nbsp;do&nbsp;this&nbsp;for&nbsp;us)</span></span></div></li>
+<li><div class="src-line"><a name="a3702"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$ls</span>&nbsp;=&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;!=&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE&quot;&gt;GESHI_HEADER_PRE&lt;/a&gt;</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;!=&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_VALID&quot;&gt;GESHI_HEADER_PRE_VALID&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;?&nbsp;<span class="src-str">&quot;\n&quot;</span>&nbsp;:&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3703"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3704"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Set&nbsp;vars&nbsp;to&nbsp;defaults&nbsp;for&nbsp;following&nbsp;loop</span></span></div></li>
+<li><div class="src-line"><a name="a3705"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$i</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3706"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3707"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Foreach&nbsp;line...</span></span></div></li>
+<li><div class="src-line"><a name="a3708"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">for</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$i</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$n</span>&nbsp;=&nbsp;<a href="http://www.php.net/count">count</a><span class="src-sym">(</span><span class="src-var">$code</span><span class="src-sym">)</span><span class="src-sym">;</span>&nbsp;<span class="src-var">$i</span>&nbsp;<&nbsp;<span class="src-var">$n</span><span class="src-sym">;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3709"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Reset&nbsp;the&nbsp;attributes&nbsp;for&nbsp;a&nbsp;new&nbsp;line&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a3710"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attrs</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3711"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3712"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Make&nbsp;lines&nbsp;have&nbsp;at&nbsp;least&nbsp;one&nbsp;space&nbsp;in&nbsp;them&nbsp;if&nbsp;they're&nbsp;empty</span></span></div></li>
+<li><div class="src-line"><a name="a3713"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;BenBE:&nbsp;Checking&nbsp;emptiness&nbsp;using&nbsp;trim&nbsp;instead&nbsp;of&nbsp;relying&nbsp;on&nbsp;blanks</span></span></div></li>
+<li><div class="src-line"><a name="a3714"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-str">''</span>&nbsp;==&nbsp;<a href="http://www.php.net/trim">trim</a><span class="src-sym">(</span><span class="src-var">$code</span><span class="src-sym">[</span><span class="src-var">$i</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3715"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$code</span><span class="src-sym">[</span><span class="src-var">$i</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">'&amp;nbsp;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3716"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3717"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3718"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;If&nbsp;this&nbsp;is&nbsp;a&nbsp;&quot;special&nbsp;line&quot;...</span></span></div></li>
+<li><div class="src-line"><a name="a3719"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers</span>&nbsp;==&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_FANCY_LINE_NUMBERS&quot;&gt;GESHI_FANCY_LINE_NUMBERS&lt;/a&gt;</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a3720"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$i</span>&nbsp;%&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_nth_row</span>&nbsp;==&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_nth_row</span>&nbsp;-&nbsp;<span class="src-num">1</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3721"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Set&nbsp;the&nbsp;attributes&nbsp;to&nbsp;style&nbsp;the&nbsp;line</span></span></div></li>
+<li><div class="src-line"><a name="a3722"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3723"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//$attr&nbsp;=&nbsp;'&nbsp;class=&quot;li2&quot;';</span></span></div></li>
+<li><div class="src-line"><a name="a3724"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attrs</span><span class="src-sym">[</span><span class="src-str">'class'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">'li2'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3725"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$def_attr</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;de2&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3726"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3727"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//$attr&nbsp;=&nbsp;'&nbsp;style=&quot;'&nbsp;.&nbsp;$this-&gt;line_style2&nbsp;.&nbsp;'&quot;';</span></span></div></li>
+<li><div class="src-line"><a name="a3728"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attrs</span><span class="src-sym">[</span><span class="src-str">'style'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_style2</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3729"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;This&nbsp;style&nbsp;&quot;covers&nbsp;up&quot;&nbsp;the&nbsp;special&nbsp;styles&nbsp;set&nbsp;for&nbsp;special&nbsp;lines</span></span></div></li>
+<li><div class="src-line"><a name="a3730"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;so&nbsp;that&nbsp;styles&nbsp;applied&nbsp;to&nbsp;special&nbsp;lines&nbsp;don't&nbsp;apply&nbsp;to&nbsp;the&nbsp;actual</span></span></div></li>
+<li><div class="src-line"><a name="a3731"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;code&nbsp;on&nbsp;that&nbsp;line</span></span></div></li>
+<li><div class="src-line"><a name="a3732"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$def_attr</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">code_style</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3733"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3734"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3735"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3736"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//$attr&nbsp;=&nbsp;'&nbsp;class=&quot;li1&quot;';</span></span></div></li>
+<li><div class="src-line"><a name="a3737"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attrs</span><span class="src-sym">[</span><span class="src-str">'class'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">'li1'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3738"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$def_attr</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;de1&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3739"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3740"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//$attr&nbsp;=&nbsp;'&nbsp;style=&quot;'&nbsp;.&nbsp;$this-&gt;line_style1&nbsp;.&nbsp;'&quot;';</span></span></div></li>
+<li><div class="src-line"><a name="a3741"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attrs</span><span class="src-sym">[</span><span class="src-str">'style'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_style1</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3742"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$def_attr</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">code_style</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3743"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3744"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3745"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3746"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Check&nbsp;which&nbsp;type&nbsp;of&nbsp;tag&nbsp;to&nbsp;insert&nbsp;for&nbsp;this&nbsp;line</span></span></div></li>
+<li><div class="src-line"><a name="a3747"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;==&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_VALID&quot;&gt;GESHI_HEADER_PRE_VALID&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3748"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$start</span>&nbsp;=&nbsp;<span class="src-str">"</span></span>&lt;pre<span class="src-var">$def_attr</span>&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3749"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$end</span>&nbsp;=&nbsp;<span class="src-str">'&lt;/pre&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3750"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3751"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Span&nbsp;or&nbsp;div?</span></span></div></li>
+<li><div class="src-line"><a name="a3752"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$start</span>&nbsp;=&nbsp;<span class="src-str">"</span></span>&lt;div<span class="src-var">$def_attr</span>&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3753"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$end</span>&nbsp;=&nbsp;<span class="src-str">'&lt;/div&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3754"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3755"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3756"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++<span class="src-var">$i</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3757"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3758"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Are&nbsp;we&nbsp;supposed&nbsp;to&nbsp;use&nbsp;ids?&nbsp;If&nbsp;so,&nbsp;add&nbsp;them</span></span></div></li>
+<li><div class="src-line"><a name="a3759"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">add_ids</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3760"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attrs</span><span class="src-sym">[</span><span class="src-str">'id'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">"</span></span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">overall_id</span>-<span class="src-var">$i</span><span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3761"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3762"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3763"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Is&nbsp;this&nbsp;some&nbsp;line&nbsp;with&nbsp;extra&nbsp;styles???</span></span></div></li>
+<li><div class="src-line"><a name="a3764"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-id">in_array</span><span class="src-sym">(</span><span class="src-var">$i</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">highlight_extra_lines</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3765"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3766"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">highlight_extra_lines_styles</span><span class="src-sym">[</span><span class="src-var">$i</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3767"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attrs</span><span class="src-sym">[</span><span class="src-str">'class'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">"</span></span>lx<span class="src-var">$i</span><span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3768"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3769"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attrs</span><span class="src-sym">[</span><span class="src-str">'class'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">&quot;ln-xtra&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3770"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3771"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3772"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/array_push">array_push</a><span class="src-sym">(</span><span class="src-var">$attrs</span><span class="src-sym">[</span><span class="src-str">'style'</span><span class="src-sym">]</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">get_line_style</span><span class="src-sym">(</span><span class="src-var">$i</span><span class="src-sym">))</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3773"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3774"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3775"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3776"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Add&nbsp;in&nbsp;the&nbsp;line&nbsp;surrounded&nbsp;by&nbsp;appropriate&nbsp;list&nbsp;HTML</span></span></div></li>
+<li><div class="src-line"><a name="a3777"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attr_string</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3778"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$attrs</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$key</span>&nbsp;=&gt;&nbsp;<span class="src-var">$attr</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3779"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attr_string</span>&nbsp;.=&nbsp;<span class="src-str">'&nbsp;'</span>&nbsp;.&nbsp;<span class="src-var">$key</span>&nbsp;.&nbsp;<span class="src-str">'=&quot;'</span>&nbsp;.&nbsp;<a href="http://www.php.net/implode">implode</a><span class="src-sym">(</span><span class="src-str">'&nbsp;'</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$attr</span><span class="src-sym">)</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3780"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3781"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3782"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-str">"</span></span>&lt;li<span class="src-var">$attr_string</span>&gt;<span class="src-var">$start</span>{<span class="src-var">$code</span><span class="src-sym">[</span><span class="src-var">$i</span>-<span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">}</span><span class="src-var">$end</span>&lt;/li&gt;<span class="src-var">$ls</span><span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3783"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$code</span><span class="src-sym">[</span><span class="src-var">$i</span>&nbsp;-&nbsp;<span class="src-num">1</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3784"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3785"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3786"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$n</span>&nbsp;=&nbsp;<span class="src-id">count</span><span class="src-sym">(</span><span class="src-var">$code</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3787"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3788"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;de1&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3789"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3790"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">code_style</span>&nbsp;.<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3791"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3792"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;==&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_VALID&quot;&gt;GESHI_HEADER_PRE_VALID&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3793"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-str">'&lt;pre'</span>.&nbsp;<span class="src-var">$attributes</span>&nbsp;.<span class="src-str">'&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3794"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">elseif</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;==&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_TABLE&quot;&gt;GESHI_HEADER_PRE_TABLE&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3795"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers</span>&nbsp;!=&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_NO_LINE_NUMBERS&quot;&gt;GESHI_NO_LINE_NUMBERS&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3796"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3797"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attrs</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;ln&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3798"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3799"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attrs</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">table_linenumber_style</span>&nbsp;.<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3800"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3801"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-str">'&lt;td'</span>.<span class="src-var">$attrs</span>.<span class="src-str">'&gt;&lt;pre'</span>.<span class="src-var">$attributes</span>.<span class="src-str">'&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3802"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;get&nbsp;linenumbers</span></span></div></li>
+<li><div class="src-line"><a name="a3803"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;we&nbsp;don't&nbsp;merge&nbsp;it&nbsp;with&nbsp;the&nbsp;for&nbsp;below,&nbsp;since&nbsp;it&nbsp;should&nbsp;be&nbsp;better&nbsp;for</span></span></div></li>
+<li><div class="src-line"><a name="a3804"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;memory&nbsp;consumption&nbsp;this&nbsp;way</span></span></div></li>
+<li><div class="src-line"><a name="a3805"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;@todo:&nbsp;but...&nbsp;actually&nbsp;it&nbsp;would&nbsp;still&nbsp;be&nbsp;somewhat&nbsp;nice&nbsp;to&nbsp;merge&nbsp;the&nbsp;two&nbsp;loops</span></span></div></li>
+<li><div class="src-line"><a name="a3806"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;mem&nbsp;peaks&nbsp;are&nbsp;at&nbsp;different&nbsp;positions</span></span></div></li>
+<li><div class="src-line"><a name="a3807"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">for</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$i</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span>&nbsp;<span class="src-var">$i</span>&nbsp;<&nbsp;<span class="src-var">$n</span><span class="src-sym">;</span>&nbsp;++<span class="src-var">$i</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3808"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$close</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3809"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;fancy&nbsp;lines</span></span></div></li>
+<li><div class="src-line"><a name="a3810"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers</span>&nbsp;==&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_FANCY_LINE_NUMBERS&quot;&gt;GESHI_FANCY_LINE_NUMBERS&lt;/a&gt;</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a3811"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$i</span>&nbsp;%&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_nth_row</span>&nbsp;==&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_nth_row</span>&nbsp;-&nbsp;<span class="src-num">1</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3812"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Set&nbsp;the&nbsp;attributes&nbsp;to&nbsp;style&nbsp;the&nbsp;line</span></span></div></li>
+<li><div class="src-line"><a name="a3813"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3814"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-str">'&lt;span&nbsp;class=&quot;xtra&nbsp;li2&quot;&gt;&lt;span&nbsp;class=&quot;de2&quot;&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3815"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3816"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;This&nbsp;style&nbsp;&quot;covers&nbsp;up&quot;&nbsp;the&nbsp;special&nbsp;styles&nbsp;set&nbsp;for&nbsp;special&nbsp;lines</span></span></div></li>
+<li><div class="src-line"><a name="a3817"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;so&nbsp;that&nbsp;styles&nbsp;applied&nbsp;to&nbsp;special&nbsp;lines&nbsp;don't&nbsp;apply&nbsp;to&nbsp;the&nbsp;actual</span></span></div></li>
+<li><div class="src-line"><a name="a3818"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;code&nbsp;on&nbsp;that&nbsp;line</span></span></div></li>
+<li><div class="src-line"><a name="a3819"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-str">'&lt;span&nbsp;style=&quot;display:block;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_style2</span>&nbsp;.&nbsp;<span class="src-str">'&quot;&gt;'</span></span></div></li>
+<li><div class="src-line"><a name="a3820"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.<span class="src-str">'&lt;span&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">code_style</span>&nbsp;.<span class="src-str">'&quot;&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3821"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3822"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$close</span>&nbsp;+=&nbsp;<span class="src-num">2</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3823"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3824"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Is&nbsp;this&nbsp;some&nbsp;line&nbsp;with&nbsp;extra&nbsp;styles???</span></span></div></li>
+<li><div class="src-line"><a name="a3825"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/in_array">in_array</a><span class="src-sym">(</span><span class="src-var">$i</span>&nbsp;+&nbsp;<span class="src-num">1</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">highlight_extra_lines</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3826"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3827"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">highlight_extra_lines_styles</span><span class="src-sym">[</span><span class="src-var">$i</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3828"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-str">"</span></span>&lt;span&nbsp;class=\&quot;xtra&nbsp;lx<span class="src-var">$i</span>\&quot;&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3829"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3830"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-str">&quot;&lt;span&nbsp;class=\&quot;xtra&nbsp;ln-xtra\&quot;&gt;&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3831"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3832"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3833"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-str">&quot;&lt;span&nbsp;style=\&quot;display:block;&quot;</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">get_line_style</span><span class="src-sym">(</span><span class="src-var">$i</span><span class="src-sym">)</span>&nbsp;.&nbsp;<span class="src-str">&quot;\&quot;&gt;&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3834"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3835"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++<span class="src-var">$close</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3836"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3837"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers_start</span>&nbsp;+&nbsp;<span class="src-var">$i</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3838"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$close</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3839"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<a href="http://www.php.net/str_repeat">str_repeat</a><span class="src-sym">(</span><span class="src-str">'&lt;/span&gt;'</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$close</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3840"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$i</span>&nbsp;!=&nbsp;<span class="src-var">$n</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3841"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-str">&quot;\n&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3842"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3843"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3844"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-str">'&lt;/pre&gt;&lt;/td&gt;&lt;td'</span>.<span class="src-var">$attributes</span>.<span class="src-str">'&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3845"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3846"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-str">'&lt;pre'</span>.&nbsp;<span class="src-var">$attributes</span>&nbsp;.<span class="src-str">'&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3847"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3848"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;No&nbsp;line&nbsp;numbers,&nbsp;but&nbsp;still&nbsp;need&nbsp;to&nbsp;handle&nbsp;highlighting&nbsp;lines&nbsp;extra.</span></span></div></li>
+<li><div class="src-line"><a name="a3849"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Have&nbsp;to&nbsp;use&nbsp;divs&nbsp;so&nbsp;the&nbsp;full&nbsp;width&nbsp;of&nbsp;the&nbsp;code&nbsp;is&nbsp;highlighted</span></span></div></li>
+<li><div class="src-line"><a name="a3850"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$close</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3851"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">for</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$i</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span>&nbsp;<span class="src-var">$i</span>&nbsp;<&nbsp;<span class="src-var">$n</span><span class="src-sym">;</span>&nbsp;++<span class="src-var">$i</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3852"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Make&nbsp;lines&nbsp;have&nbsp;at&nbsp;least&nbsp;one&nbsp;space&nbsp;in&nbsp;them&nbsp;if&nbsp;they're&nbsp;empty</span></span></div></li>
+<li><div class="src-line"><a name="a3853"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;BenBE:&nbsp;Checking&nbsp;emptiness&nbsp;using&nbsp;trim&nbsp;instead&nbsp;of&nbsp;relying&nbsp;on&nbsp;blanks</span></span></div></li>
+<li><div class="src-line"><a name="a3854"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-str">''</span>&nbsp;==&nbsp;<a href="http://www.php.net/trim">trim</a><span class="src-sym">(</span><span class="src-var">$code</span><span class="src-sym">[</span><span class="src-var">$i</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3855"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$code</span><span class="src-sym">[</span><span class="src-var">$i</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">'&amp;nbsp;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3856"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3857"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;fancy&nbsp;lines</span></span></div></li>
+<li><div class="src-line"><a name="a3858"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers</span>&nbsp;==&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_FANCY_LINE_NUMBERS&quot;&gt;GESHI_FANCY_LINE_NUMBERS&lt;/a&gt;</span>&nbsp;&amp;&amp;</span></div></li>
+<li><div class="src-line"><a name="a3859"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$i</span>&nbsp;%&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_nth_row</span>&nbsp;==&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_nth_row</span>&nbsp;-&nbsp;<span class="src-num">1</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3860"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Set&nbsp;the&nbsp;attributes&nbsp;to&nbsp;style&nbsp;the&nbsp;line</span></span></div></li>
+<li><div class="src-line"><a name="a3861"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3862"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-str">'&lt;span&nbsp;class=&quot;xtra&nbsp;li2&quot;&gt;&lt;span&nbsp;class=&quot;de2&quot;&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3863"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3864"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;This&nbsp;style&nbsp;&quot;covers&nbsp;up&quot;&nbsp;the&nbsp;special&nbsp;styles&nbsp;set&nbsp;for&nbsp;special&nbsp;lines</span></span></div></li>
+<li><div class="src-line"><a name="a3865"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;so&nbsp;that&nbsp;styles&nbsp;applied&nbsp;to&nbsp;special&nbsp;lines&nbsp;don't&nbsp;apply&nbsp;to&nbsp;the&nbsp;actual</span></span></div></li>
+<li><div class="src-line"><a name="a3866"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;code&nbsp;on&nbsp;that&nbsp;line</span></span></div></li>
+<li><div class="src-line"><a name="a3867"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-str">'&lt;span&nbsp;style=&quot;display:block;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_style2</span>&nbsp;.&nbsp;<span class="src-str">'&quot;&gt;'</span></span></div></li>
+<li><div class="src-line"><a name="a3868"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.<span class="src-str">'&lt;span&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">code_style</span>&nbsp;.<span class="src-str">'&quot;&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3869"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3870"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$close</span>&nbsp;+=&nbsp;<span class="src-num">2</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3871"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3872"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Is&nbsp;this&nbsp;some&nbsp;line&nbsp;with&nbsp;extra&nbsp;styles???</span></span></div></li>
+<li><div class="src-line"><a name="a3873"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/in_array">in_array</a><span class="src-sym">(</span><span class="src-var">$i</span>&nbsp;+&nbsp;<span class="src-num">1</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">highlight_extra_lines</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3874"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3875"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">highlight_extra_lines_styles</span><span class="src-sym">[</span><span class="src-var">$i</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3876"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-str">"</span></span>&lt;span&nbsp;class=\&quot;xtra&nbsp;lx<span class="src-var">$i</span>\&quot;&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3877"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3878"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-str">&quot;&lt;span&nbsp;class=\&quot;xtra&nbsp;ln-xtra\&quot;&gt;&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3879"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3880"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3881"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-str">&quot;&lt;span&nbsp;style=\&quot;display:block;&quot;</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">get_line_style</span><span class="src-sym">(</span><span class="src-var">$i</span><span class="src-sym">)</span>&nbsp;.&nbsp;<span class="src-str">&quot;\&quot;&gt;&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3882"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3883"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++<span class="src-var">$close</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3884"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3885"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3886"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-var">$code</span><span class="src-sym">[</span><span class="src-var">$i</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3887"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3888"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$close</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3889"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<a href="http://www.php.net/str_repeat">str_repeat</a><span class="src-sym">(</span><span class="src-str">'&lt;/span&gt;'</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$close</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3890"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$close</span>&nbsp;=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3891"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3892"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">elseif</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$i</span>&nbsp;+&nbsp;<span class="src-num">1</span>&nbsp;<&nbsp;<span class="src-var">$n</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3893"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-str">&quot;\n&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3894"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3895"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$code</span><span class="src-sym">[</span><span class="src-var">$i</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3896"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3897"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3898"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;==&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_VALID&quot;&gt;GESHI_HEADER_PRE_VALID&lt;/a&gt;</span>&nbsp;||&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;==&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_TABLE&quot;&gt;GESHI_HEADER_PRE_TABLE&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3899"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-str">'&lt;/pre&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3900"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3901"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;==&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_TABLE&quot;&gt;GESHI_HEADER_PRE_TABLE&lt;/a&gt;</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers</span>&nbsp;!=&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_NO_LINE_NUMBERS&quot;&gt;GESHI_NO_LINE_NUMBERS&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3902"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-str">'&lt;/td&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3903"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3904"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3905"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3906"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$parsed_code</span>&nbsp;.=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">footer</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3907"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3908"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3909"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;/**</span></div></li>
+<li><div class="src-line"><a name="a3910"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Creates&nbsp;the&nbsp;header&nbsp;for&nbsp;the&nbsp;code&nbsp;block&nbsp;(with&nbsp;correct&nbsp;attributes)</span></div></li>
+<li><div class="src-line"><a name="a3911"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a3912"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;string&nbsp;The&nbsp;header&nbsp;for&nbsp;the&nbsp;code&nbsp;block</span></div></li>
+<li><div class="src-line"><a name="a3913"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@since&nbsp;&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a3914"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@access&nbsp;private</span></div></li>
+<li><div class="src-line"><a name="a3915"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a3916"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="http://www.php.net/header">header</a><span class="src-sym">(</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3917"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Get&nbsp;attributes&nbsp;needed</span></span></div></li>
+<li><div class="src-line"><a name="a3918"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/**</span></div></li>
+<li><div class="src-line"><a name="a3919"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@todo&nbsp;&nbsp;&nbsp;Document&nbsp;behaviour&nbsp;change&nbsp;-&nbsp;class&nbsp;is&nbsp;outputted&nbsp;regardless&nbsp;of&nbsp;whether</span></div></li>
+<li><div class="src-line"><a name="a3920"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;we're&nbsp;using&nbsp;classes&nbsp;or&nbsp;not.&nbsp;Same&nbsp;with&nbsp;style</span></div></li>
+<li><div class="src-line"><a name="a3921"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a3922"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3923"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">overall_class</span>&nbsp;!=&nbsp;<span class="src-str">''</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3924"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;.=&nbsp;<span class="src-str">&quot;&nbsp;&quot;</span>.<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">overall_class</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3925"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3926"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;.=&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3927"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3928"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">overall_id</span>&nbsp;!=&nbsp;<span class="src-str">''</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3929"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;.=&nbsp;<span class="src-str">"</span></span>&nbsp;id=\&quot;{<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">overall_id</span><span class="src-sym">}</span>\&quot;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3930"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3931"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">overall_style</span>&nbsp;!=&nbsp;<span class="src-str">''</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3932"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attributes</span>&nbsp;.=&nbsp;<span class="src-str">'&nbsp;style=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">overall_style</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3933"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3934"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3935"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$ol_attributes</span>&nbsp;=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3936"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3937"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers_start</span>&nbsp;!=&nbsp;<span class="src-num">1</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3938"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$ol_attributes</span>&nbsp;.=&nbsp;<span class="src-str">'&nbsp;start=&quot;'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers_start</span>&nbsp;.&nbsp;<span class="src-str">'&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3939"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3940"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3941"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Get&nbsp;the&nbsp;header&nbsp;HTML</span></span></div></li>
+<li><div class="src-line"><a name="a3942"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$header</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_content</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3943"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$header</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3944"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;==&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE&quot;&gt;GESHI_HEADER_PRE&lt;/a&gt;</span>&nbsp;||&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;==&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_VALID&quot;&gt;GESHI_HEADER_PRE_VALID&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3945"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$header</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-str">&quot;\n&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-str">''</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$header</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3946"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3947"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$header</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">replace_keywords</span><span class="src-sym">(</span><span class="src-var">$header</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3948"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3949"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3950"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attr</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;head&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3951"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3952"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attr</span>&nbsp;=&nbsp;<span class="src-str">"</span></span>&nbsp;style=\&quot;{<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_content_style</span><span class="src-sym">}</span>\&quot;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3953"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3954"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;==&nbsp;<span class="src-id">GESHI_HEADER_PRE_TABLE</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers</span>&nbsp;!=&nbsp;<span class="src-id">GESHI_NO_LINE_NUMBERS</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3955"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$header</span>&nbsp;=&nbsp;</span><span class="src-str">&quot;</span>&lt;thead&gt;&lt;tr&gt;&lt;td&nbsp;colspan=\&quot;2\&quot;&nbsp;<span class="src-var">$attr</span>&gt;<span class="src-var">$header</span>&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3956"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3957"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$header</span>&nbsp;=&nbsp;</span><span class="src-str">&quot;</span>&lt;div<span class="src-var">$attr</span>&gt;<span class="src-var">$header</span>&lt;/div&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3958"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3959"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3960"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3961"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-id">GESHI_HEADER_NONE</span>&nbsp;==&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3962"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers</span>&nbsp;!=&nbsp;<span class="src-id">GESHI_NO_LINE_NUMBERS</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3963"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;</span><span class="src-str">&quot;</span><span class="src-var">$header</span>&lt;ol<span class="src-var">$attributes$ol_attributes</span>&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3964"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3965"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-var">$header</span>&nbsp;.&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">force_code_block</span>&nbsp;?&nbsp;<span class="src-str">'&lt;div&gt;'</span>&nbsp;:&nbsp;<span class="src-str">''</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3966"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3967"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3968"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Work&nbsp;out&nbsp;what&nbsp;to&nbsp;return&nbsp;and&nbsp;do&nbsp;it</span></span></div></li>
+<li><div class="src-line"><a name="a3969"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers</span>&nbsp;!=&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_NO_LINE_NUMBERS&quot;&gt;GESHI_NO_LINE_NUMBERS&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3970"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;==&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE&quot;&gt;GESHI_HEADER_PRE&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3971"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-str">"</span></span>&lt;pre<span class="src-var">$attributes</span>&gt;<span class="src-var">$header</span>&lt;ol<span class="src-var">$ol_attributes</span>&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3972"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;==&nbsp;<span class="src-id">GESHI_HEADER_DIV</span>&nbsp;||</span></div></li>
+<li><div class="src-line"><a name="a3973"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;==&nbsp;<span class="src-id">GESHI_HEADER_PRE_VALID</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3974"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;</span><span class="src-str">&quot;</span>&lt;div<span class="src-var">$attributes</span>&gt;<span class="src-var">$header</span>&lt;ol<span class="src-var">$ol_attributes</span>&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3975"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;==&nbsp;<span class="src-id">GESHI_HEADER_PRE_TABLE</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3976"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;</span><span class="src-str">&quot;</span>&lt;table<span class="src-var">$attributes</span>&gt;<span class="src-var">$header</span>&lt;tbody&gt;&lt;tr&nbsp;class=\&quot;li1\&quot;&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3977"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3978"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3979"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;==&nbsp;<span class="src-id">GESHI_HEADER_PRE</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3980"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;</span><span class="src-str">&quot;</span>&lt;pre<span class="src-var">$attributes</span>&gt;<span class="src-var">$header</span><span class="src-str">&quot;&nbsp;&nbsp;</span><span class="src-str">.</span></div></li>
+<li><div class="src-line"><a name="a3981"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">force_code_block</span>&nbsp;?&nbsp;<span class="src-str">'&lt;div&gt;'</span>&nbsp;:&nbsp;<span class="src-str">''</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3982"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3983"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-str">"</span></span>&lt;div<span class="src-var">$attributes</span>&gt;<span class="src-var">$header</span><span class="src-str">&quot;&nbsp;</span><span class="src-str">.</span></div></li>
+<li><div class="src-line"><a name="a3984"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">force_code_block</span>&nbsp;?&nbsp;<span class="src-str">'&lt;div&gt;'</span>&nbsp;:&nbsp;<span class="src-str">''</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3985"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3986"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3987"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a3988"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a3989"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;/**</span></div></li>
+<li><div class="src-line"><a name="a3990"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Returns&nbsp;the&nbsp;footer&nbsp;for&nbsp;the&nbsp;code&nbsp;block.</span></div></li>
+<li><div class="src-line"><a name="a3991"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a3992"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;string&nbsp;The&nbsp;footer&nbsp;for&nbsp;the&nbsp;code&nbsp;block</span></div></li>
+<li><div class="src-line"><a name="a3993"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@since&nbsp;&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a3994"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@access&nbsp;private</span></div></li>
+<li><div class="src-line"><a name="a3995"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a3996"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<span class="src-id">footer</span><span class="src-sym">(</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3997"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$footer</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">footer_content</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a3998"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$footer</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a3999"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;==&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE&quot;&gt;GESHI_HEADER_PRE&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4000"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$footer</span>&nbsp;=&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-str">&quot;\n&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-str">''</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$footer</span><span class="src-sym">)</span><span class="src-sym">;;</span></span></div></li>
+<li><div class="src-line"><a name="a4001"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4002"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$footer</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">replace_keywords</span><span class="src-sym">(</span><span class="src-var">$footer</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4003"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4004"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">use_classes</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4005"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attr</span>&nbsp;=&nbsp;<span class="src-str">'&nbsp;class=&quot;foot&quot;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4006"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4007"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$attr</span>&nbsp;=&nbsp;<span class="src-str">"</span></span>&nbsp;style=\&quot;{<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">footer_content_style</span><span class="src-sym">}</span>\&quot;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4008"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4009"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;==&nbsp;<span class="src-id">GESHI_HEADER_PRE_TABLE</span>&nbsp;&amp;&amp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">linenumbers</span>&nbsp;!=&nbsp;<span class="src-id">GESHI_NO_LINE_NUMBERS</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4010"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$footer</span>&nbsp;=&nbsp;</span><span class="src-str">&quot;</span>&lt;tfoot&gt;&lt;tr&gt;&lt;td&nbsp;colspan=\&quot;2\&quot;&gt;<span class="src-var">$footer</span>&lt;/td&gt;&lt;/tr&gt;&lt;/tfoot&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4011"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4012"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$footer</span>&nbsp;=&nbsp;</span><span class="src-str">&quot;</span>&lt;div<span class="src-var">$attr</span>&gt;<span class="src-var">$footer</span>&lt;/div&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4013"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4014"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4015"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4016"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-id">GESHI_HEADER_NONE</span>&nbsp;==&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4017"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers</span>&nbsp;!=&nbsp;<span class="src-id">GESHI_NO_LINE_NUMBERS</span><span class="src-sym">)</span>&nbsp;?&nbsp;<span class="src-str">'&lt;/ol&gt;'</span>&nbsp;.&nbsp;<span class="src-var">$footer</span>&nbsp;:&nbsp;<span class="src-var">$footer</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4018"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4019"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4020"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;==&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_DIV&quot;&gt;GESHI_HEADER_DIV&lt;/a&gt;</span>&nbsp;||&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;==&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_VALID&quot;&gt;GESHI_HEADER_PRE_VALID&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4021"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers</span>&nbsp;!=&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_NO_LINE_NUMBERS&quot;&gt;GESHI_NO_LINE_NUMBERS&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4022"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-str">"</span></span>&lt;/ol&gt;<span class="src-var">$footer</span>&lt;/div&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4023"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4024"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">force_code_block</span>&nbsp;?&nbsp;<span class="src-str">'&lt;/div&gt;'</span>&nbsp;:&nbsp;<span class="src-str">''</span><span class="src-sym">)</span>&nbsp;.</span></div></li>
+<li><div class="src-line"><a name="a4025"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">"</span></span><span class="src-var">$footer</span>&lt;/div&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4026"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4027"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">elseif</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_type</span>&nbsp;==&nbsp;<span class="src-id">GESHI_HEADER_PRE_TABLE</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4028"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers</span>&nbsp;!=&nbsp;<span class="src-id">GESHI_NO_LINE_NUMBERS</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4029"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;</span><span class="src-str">&quot;</span>&lt;/tr&gt;&lt;/tbody&gt;<span class="src-var">$footer</span>&lt;/table&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4030"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4031"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">force_code_block</span>&nbsp;?&nbsp;<span class="src-str">'&lt;/div&gt;'</span>&nbsp;:&nbsp;<span class="src-str">''</span><span class="src-sym">)</span>&nbsp;.</span></div></li>
+<li><div class="src-line"><a name="a4032"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">"</span></span><span class="src-var">$footer</span>&lt;/div&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4033"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4034"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4035"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers</span>&nbsp;!=&nbsp;<span class="src-id">GESHI_NO_LINE_NUMBERS</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4036"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;</span><span class="src-str">&quot;</span>&lt;/ol&gt;<span class="src-var">$footer</span>&lt;/pre&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4037"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4038"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">force_code_block</span>&nbsp;?&nbsp;<span class="src-str">'&lt;/div&gt;'</span>&nbsp;:&nbsp;<span class="src-str">''</span><span class="src-sym">)</span>&nbsp;.</span></div></li>
+<li><div class="src-line"><a name="a4039"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">"</span></span><span class="src-var">$footer</span>&lt;/pre&gt;<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4040"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4041"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4042"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4043"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;/**</span></div></li>
+<li><div class="src-line"><a name="a4044"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Replaces&nbsp;certain&nbsp;keywords&nbsp;in&nbsp;the&nbsp;header&nbsp;and&nbsp;footer&nbsp;with</span></div></li>
+<li><div class="src-line"><a name="a4045"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;certain&nbsp;configuration&nbsp;values</span></div></li>
+<li><div class="src-line"><a name="a4046"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a4047"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;string&nbsp;The&nbsp;header&nbsp;or&nbsp;footer&nbsp;content&nbsp;to&nbsp;do&nbsp;replacement&nbsp;on</span></div></li>
+<li><div class="src-line"><a name="a4048"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;string&nbsp;The&nbsp;header&nbsp;or&nbsp;footer&nbsp;with&nbsp;replaced&nbsp;keywords</span></div></li>
+<li><div class="src-line"><a name="a4049"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@since&nbsp;&nbsp;1.0.2</span></div></li>
+<li><div class="src-line"><a name="a4050"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@access&nbsp;private</span></div></li>
+<li><div class="src-line"><a name="a4051"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a4052"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<span class="src-id">replace_keywords</span><span class="src-sym">(</span><span class="src-var">$instr</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4053"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$keywords</span>&nbsp;=&nbsp;<span class="src-var">$replacements</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4054"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4055"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$keywords</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">'&lt;TIME&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4056"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$keywords</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">'{TIME}'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4057"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$replacements</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$replacements</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<a href="http://www.php.net/number_format">number_format</a><span class="src-sym">(</span><span class="src-var">$time</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodget_time">get_time</a><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">,</span>&nbsp;<span class="src-num">3</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4058"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4059"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$keywords</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">'&lt;LANGUAGE&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4060"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$keywords</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">'{LANGUAGE}'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4061"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$replacements</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$replacements</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'LANG_NAME'</span><span class="src-sym">]</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4062"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4063"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$keywords</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">'&lt;VERSION&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4064"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$keywords</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">'{VERSION}'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4065"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$replacements</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$replacements</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_VERSION&quot;&gt;GESHI_VERSION&lt;/a&gt;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4066"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4067"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$keywords</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">'&lt;SPEED&gt;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4068"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$keywords</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">'{SPEED}'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4069"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$time</span>&nbsp;&lt;=&nbsp;<span class="src-num">0</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4070"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$speed</span>&nbsp;=&nbsp;<span class="src-str">'N/A'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4071"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4072"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$speed</span>&nbsp;=&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">source</span><span class="src-sym">)</span>&nbsp;/&nbsp;<span class="src-var">$time</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4073"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$speed</span>&nbsp;&gt;=&nbsp;<span class="src-num">1024</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4074"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$speed</span>&nbsp;=&nbsp;<a href="http://www.php.net/sprintf">sprintf</a><span class="src-sym">(</span><span class="src-str">&quot;%.2f&nbsp;KB/s&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$speed</span>&nbsp;/&nbsp;<span class="src-num">1024.0</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4075"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4076"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$speed</span>&nbsp;=&nbsp;<a href="http://www.php.net/sprintf">sprintf</a><span class="src-sym">(</span><span class="src-str">&quot;%.0f&nbsp;B/s&quot;</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$speed</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4077"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4078"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4079"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$replacements</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$replacements</span><span class="src-sym">[</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-var">$speed</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4080"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4081"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<a href="http://www.php.net/str_replace">str_replace</a><span class="src-sym">(</span><span class="src-var">$keywords</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$replacements</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$instr</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4082"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4083"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4084"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;/**</span></div></li>
+<li><div class="src-line"><a name="a4085"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Secure&nbsp;replacement&nbsp;for&nbsp;PHP&nbsp;built-in&nbsp;function&nbsp;htmlspecialchars().</span></div></li>
+<li><div class="src-line"><a name="a4086"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a4087"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;See&nbsp;ticket&nbsp;#427&nbsp;(http://wush.net/trac/wikka/ticket/427)&nbsp;for&nbsp;the&nbsp;rationale</span></div></li>
+<li><div class="src-line"><a name="a4088"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;for&nbsp;this&nbsp;replacement&nbsp;function.</span></div></li>
+<li><div class="src-line"><a name="a4089"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a4090"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;INTERFACE&nbsp;for&nbsp;this&nbsp;function&nbsp;is&nbsp;almost&nbsp;the&nbsp;same&nbsp;as&nbsp;that&nbsp;for</span></div></li>
+<li><div class="src-line"><a name="a4091"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;htmlspecialchars(),&nbsp;with&nbsp;the&nbsp;same&nbsp;default&nbsp;for&nbsp;quote&nbsp;style;&nbsp;however,&nbsp;there</span></div></li>
+<li><div class="src-line"><a name="a4092"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;is&nbsp;no&nbsp;'charset'&nbsp;parameter.&nbsp;The&nbsp;reason&nbsp;for&nbsp;this&nbsp;is&nbsp;as&nbsp;follows:</span></div></li>
+<li><div class="src-line"><a name="a4093"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a4094"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;PHP&nbsp;docs&nbsp;say:</span></div></li>
+<li><div class="src-line"><a name="a4095"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;The&nbsp;third&nbsp;argument&nbsp;charset&nbsp;defines&nbsp;character&nbsp;set&nbsp;used&nbsp;in&nbsp;conversion.&quot;</span></div></li>
+<li><div class="src-line"><a name="a4096"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a4097"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;I&nbsp;suspect&nbsp;PHP's&nbsp;htmlspecialchars()&nbsp;is&nbsp;working&nbsp;at&nbsp;the&nbsp;byte-value&nbsp;level&nbsp;and</span></div></li>
+<li><div class="src-line"><a name="a4098"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;thus&nbsp;_needs_&nbsp;to&nbsp;know&nbsp;(or&nbsp;asssume)&nbsp;a&nbsp;character&nbsp;set&nbsp;because&nbsp;the&nbsp;special</span></div></li>
+<li><div class="src-line"><a name="a4099"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;characters&nbsp;to&nbsp;be&nbsp;replaced&nbsp;could&nbsp;exist&nbsp;at&nbsp;different&nbsp;code&nbsp;points&nbsp;in</span></div></li>
+<li><div class="src-line"><a name="a4100"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;different&nbsp;character&nbsp;sets.&nbsp;(If&nbsp;indeed&nbsp;htmlspecialchars()&nbsp;works&nbsp;at</span></div></li>
+<li><div class="src-line"><a name="a4101"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;byte-value&nbsp;level&nbsp;that&nbsp;goes&nbsp;some&nbsp;&nbsp;way&nbsp;towards&nbsp;explaining&nbsp;why&nbsp;the</span></div></li>
+<li><div class="src-line"><a name="a4102"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;vulnerability&nbsp;would&nbsp;exist&nbsp;in&nbsp;this&nbsp;function,&nbsp;too,&nbsp;and&nbsp;not&nbsp;only&nbsp;in</span></div></li>
+<li><div class="src-line"><a name="a4103"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;htmlentities()&nbsp;which&nbsp;certainly&nbsp;is&nbsp;working&nbsp;at&nbsp;byte-value&nbsp;level.)</span></div></li>
+<li><div class="src-line"><a name="a4104"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a4105"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;This&nbsp;replacement&nbsp;function&nbsp;however&nbsp;works&nbsp;at&nbsp;character&nbsp;level&nbsp;and&nbsp;should</span></div></li>
+<li><div class="src-line"><a name="a4106"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;therefore&nbsp;be&nbsp;&quot;immune&quot;&nbsp;to&nbsp;character&nbsp;set&nbsp;differences&nbsp;-&nbsp;so&nbsp;no&nbsp;charset</span></div></li>
+<li><div class="src-line"><a name="a4107"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;parameter&nbsp;is&nbsp;needed&nbsp;or&nbsp;provided.&nbsp;If&nbsp;a&nbsp;third&nbsp;parameter&nbsp;is&nbsp;passed,&nbsp;it&nbsp;will</span></div></li>
+<li><div class="src-line"><a name="a4108"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;be&nbsp;silently&nbsp;ignored.</span></div></li>
+<li><div class="src-line"><a name="a4109"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a4110"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;In&nbsp;the&nbsp;OUTPUT&nbsp;there&nbsp;is&nbsp;a&nbsp;minor&nbsp;difference&nbsp;in&nbsp;that&nbsp;we&nbsp;use&nbsp;'&amp;#39;'&nbsp;instead</span></div></li>
+<li><div class="src-line"><a name="a4111"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;of&nbsp;PHP's&nbsp;'&amp;#039;'&nbsp;for&nbsp;a&nbsp;single&nbsp;quote:&nbsp;this&nbsp;provides&nbsp;compatibility&nbsp;with</span></div></li>
+<li><div class="src-line"><a name="a4112"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get_html_translation_table(HTML_SPECIALCHARS,&nbsp;ENT_QUOTES)</span></div></li>
+<li><div class="src-line"><a name="a4113"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;(see&nbsp;comment&nbsp;by&nbsp;mikiwoz&nbsp;at&nbsp;yahoo&nbsp;dot&nbsp;co&nbsp;dot&nbsp;uk&nbsp;on</span></div></li>
+<li><div class="src-line"><a name="a4114"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;http://php.net/htmlspecialchars);&nbsp;it&nbsp;also&nbsp;matches&nbsp;the&nbsp;entity&nbsp;definition</span></div></li>
+<li><div class="src-line"><a name="a4115"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;for&nbsp;XML&nbsp;1.0</span></div></li>
+<li><div class="src-line"><a name="a4116"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;(http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters).</span></div></li>
+<li><div class="src-line"><a name="a4117"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Like&nbsp;PHP&nbsp;we&nbsp;use&nbsp;a&nbsp;numeric&nbsp;character&nbsp;reference&nbsp;instead&nbsp;of&nbsp;'&amp;apos;'&nbsp;for&nbsp;the</span></div></li>
+<li><div class="src-line"><a name="a4118"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;single&nbsp;quote.&nbsp;For&nbsp;the&nbsp;other&nbsp;special&nbsp;characters&nbsp;we&nbsp;use&nbsp;the&nbsp;named&nbsp;entity</span></div></li>
+<li><div class="src-line"><a name="a4119"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;references,&nbsp;as&nbsp;PHP&nbsp;is&nbsp;doing.</span></div></li>
+<li><div class="src-line"><a name="a4120"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a4121"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@author&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{@link&nbsp;http://wikkawiki.org/JavaWoman&nbsp;Marjolein&nbsp;Katsma}</span></div></li>
+<li><div class="src-line"><a name="a4122"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a4123"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@license&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;http://www.gnu.org/copyleft/lgpl.html</span></div></li>
+<li><div class="src-line"><a name="a4124"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GNU&nbsp;Lesser&nbsp;General&nbsp;Public&nbsp;License</span></div></li>
+<li><div class="src-line"><a name="a4125"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@copyright&nbsp;&nbsp;&nbsp;Copyright&nbsp;2007,&nbsp;{@link&nbsp;http://wikkawiki.org/CreditsPage</span></div></li>
+<li><div class="src-line"><a name="a4126"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Wikka&nbsp;Development&nbsp;Team}</span></div></li>
+<li><div class="src-line"><a name="a4127"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a4128"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@access&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private</span></div></li>
+<li><div class="src-line"><a name="a4129"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;&nbsp;$string&nbsp;string&nbsp;to&nbsp;be&nbsp;converted</span></div></li>
+<li><div class="src-line"><a name="a4130"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;integer&nbsp;$quote_style</span></div></li>
+<li><div class="src-line"><a name="a4131"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;ENT_COMPAT:&nbsp;&nbsp;&nbsp;escapes&nbsp;&amp;,&nbsp;&lt;,&nbsp;&gt;&nbsp;and&nbsp;double&nbsp;quote&nbsp;(default)</span></div></li>
+<li><div class="src-line"><a name="a4132"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;ENT_NOQUOTES:&nbsp;escapes&nbsp;only&nbsp;&amp;,&nbsp;&lt;&nbsp;and&nbsp;&gt;</span></div></li>
+<li><div class="src-line"><a name="a4133"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;ENT_QUOTES:&nbsp;&nbsp;&nbsp;escapes&nbsp;&amp;,&nbsp;&lt;,&nbsp;&gt;,&nbsp;double&nbsp;and&nbsp;single&nbsp;quotes</span></div></li>
+<li><div class="src-line"><a name="a4134"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;&nbsp;converted&nbsp;string</span></div></li>
+<li><div class="src-line"><a name="a4135"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@since&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.0.7.18</span></div></li>
+<li><div class="src-line"><a name="a4136"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a4137"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<span class="src-id">hsc</span><span class="src-sym">(</span><span class="src-var">$string</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$quote_style</span>&nbsp;=&nbsp;<span class="src-id">ENT_COMPAT</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4138"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;init</span></span></div></li>
+<li><div class="src-line"><a name="a4139"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">static</span>&nbsp;<span class="src-var">$aTransSpecchar</span>&nbsp;=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span></span></div></li>
+<li><div class="src-line"><a name="a4140"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'&amp;'</span>&nbsp;=&gt;&nbsp;<span class="src-str">'&amp;amp;'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a4141"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'&quot;'</span>&nbsp;=&gt;&nbsp;<span class="src-str">'&amp;quot;'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a4142"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'&lt;'</span>&nbsp;=&gt;&nbsp;<span class="src-str">'&amp;lt;'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a4143"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'&gt;'</span>&nbsp;=&gt;&nbsp;<span class="src-str">'&amp;gt;'</span><span class="src-sym">,</span></span></div></li>
+<li><div class="src-line"><a name="a4144"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4145"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//This&nbsp;fix&nbsp;is&nbsp;related&nbsp;to&nbsp;SF#1923020,&nbsp;but&nbsp;has&nbsp;to&nbsp;be&nbsp;applied</span></span></div></li>
+<li><div class="src-line"><a name="a4146"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//regardless&nbsp;of&nbsp;actually&nbsp;highlighting&nbsp;symbols.</span></span></div></li>
+<li><div class="src-line"><a name="a4147"></a></span><span class="src-str"><span class="src-comm"></span></span></div></li>
+<li><div class="src-line"><a name="a4148"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Circumvent&nbsp;a&nbsp;bug&nbsp;with&nbsp;symbol&nbsp;highlighting</span></span></div></li>
+<li><div class="src-line"><a name="a4149"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//This&nbsp;is&nbsp;required&nbsp;as&nbsp;;&nbsp;would&nbsp;produce&nbsp;undesirable&nbsp;side-effects&nbsp;if&nbsp;it</span></span></div></li>
+<li><div class="src-line"><a name="a4150"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//was&nbsp;not&nbsp;to&nbsp;be&nbsp;processed&nbsp;as&nbsp;an&nbsp;entity.</span></span></div></li>
+<li><div class="src-line"><a name="a4151"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">';'</span>&nbsp;=&gt;&nbsp;<span class="src-str">'&lt;SEMI&gt;'</span><span class="src-sym">,</span>&nbsp;<span class="src-comm">//&nbsp;Force&nbsp;;&nbsp;to&nbsp;be&nbsp;processed&nbsp;as&nbsp;entity</span></span></div></li>
+<li><div class="src-line"><a name="a4152"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'|'</span>&nbsp;=&gt;&nbsp;<span class="src-str">'&lt;PIPE&gt;'</span>&nbsp;<span class="src-comm">//&nbsp;Force&nbsp;|&nbsp;to&nbsp;be&nbsp;processed&nbsp;as&nbsp;entity</span></span></div></li>
+<li><div class="src-line"><a name="a4153"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">)</span><span class="src-sym">;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;ENT_COMPAT&nbsp;set</span></span></div></li>
+<li><div class="src-line"><a name="a4154"></a></span><span class="src-str"><span class="src-comm"></span></span></div></li>
+<li><div class="src-line"><a name="a4155"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">switch</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$quote_style</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4156"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">case</span>&nbsp;<span class="src-id">ENT_NOQUOTES</span>:&nbsp;<span class="src-comm">//&nbsp;don't&nbsp;convert&nbsp;double&nbsp;quotes</span></span></div></li>
+<li><div class="src-line"><a name="a4157"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$aTransSpecchar</span><span class="src-sym">[</span><span class="src-str">'&quot;'</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4158"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">break</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4159"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">case</span>&nbsp;<span class="src-id">ENT_QUOTES</span>:&nbsp;<span class="src-comm">//&nbsp;convert&nbsp;single&nbsp;quotes&nbsp;as&nbsp;well</span></span></div></li>
+<li><div class="src-line"><a name="a4160"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$aTransSpecchar</span><span class="src-sym">[</span><span class="src-str">&quot;'&quot;</span><span class="src-sym">]</span>&nbsp;=&nbsp;<span class="src-str">'&amp;#39;'</span><span class="src-sym">;</span>&nbsp;<span class="src-comm">//&nbsp;(apos)&nbsp;htmlspecialchars()&nbsp;uses&nbsp;'&amp;#039;'</span></span></div></li>
+<li><div class="src-line"><a name="a4161"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">break</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4162"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4163"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4164"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;return&nbsp;translated&nbsp;string</span></span></div></li>
+<li><div class="src-line"><a name="a4165"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<a href="http://www.php.net/strtr">strtr</a><span class="src-sym">(</span><span class="src-var">$string</span><span class="src-sym">,</span>&nbsp;<span class="src-var">$aTransSpecchar</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4166"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4167"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4168"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;/**</span></div></li>
+<li><div class="src-line"><a name="a4169"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Returns&nbsp;a&nbsp;stylesheet&nbsp;for&nbsp;the&nbsp;highlighted&nbsp;code.&nbsp;If&nbsp;$economy&nbsp;mode</span></div></li>
+<li><div class="src-line"><a name="a4170"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;is&nbsp;true,&nbsp;we&nbsp;only&nbsp;return&nbsp;the&nbsp;stylesheet&nbsp;declarations&nbsp;that&nbsp;matter&nbsp;for</span></div></li>
+<li><div class="src-line"><a name="a4171"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;this&nbsp;code&nbsp;block&nbsp;instead&nbsp;of&nbsp;the&nbsp;whole&nbsp;thing</span></div></li>
+<li><div class="src-line"><a name="a4172"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</span></div></li>
+<li><div class="src-line"><a name="a4173"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&nbsp;boolean&nbsp;Whether&nbsp;to&nbsp;use&nbsp;economy&nbsp;mode&nbsp;or&nbsp;not</span></div></li>
+<li><div class="src-line"><a name="a4174"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;string&nbsp;A&nbsp;stylesheet&nbsp;built&nbsp;on&nbsp;the&nbsp;data&nbsp;for&nbsp;the&nbsp;current&nbsp;language</span></div></li>
+<li><div class="src-line"><a name="a4175"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@since&nbsp;&nbsp;1.0.0</span></div></li>
+<li><div class="src-line"><a name="a4176"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></div></li>
+<li><div class="src-line"><a name="a4177"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function</span>&nbsp;<a href="../geshi/core/GeSHi.html#methodget_stylesheet">get_stylesheet</a><span class="src-sym">(</span><span class="src-var">$economy_mode</span>&nbsp;=&nbsp;<span class="src-id">true</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4178"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;If&nbsp;there's&nbsp;an&nbsp;error,&nbsp;chances&nbsp;are&nbsp;that&nbsp;the&nbsp;language&nbsp;file</span></span></div></li>
+<li><div class="src-line"><a name="a4179"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;won't&nbsp;have&nbsp;populated&nbsp;the&nbsp;language&nbsp;data&nbsp;file,&nbsp;so&nbsp;we&nbsp;can't</span></span></div></li>
+<li><div class="src-line"><a name="a4180"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;risk&nbsp;getting&nbsp;a&nbsp;stylesheet...</span></span></div></li>
+<li><div class="src-line"><a name="a4181"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methoderror">error</a><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4182"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return</span>&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4183"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4184"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4185"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//Check&nbsp;if&nbsp;the&nbsp;style&nbsp;rearrangements&nbsp;have&nbsp;been&nbsp;processed&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a4186"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//This&nbsp;also&nbsp;does&nbsp;some&nbsp;preprocessing&nbsp;to&nbsp;check&nbsp;which&nbsp;style&nbsp;groups&nbsp;are&nbsp;useable&nbsp;...</span></span></div></li>
+<li><div class="src-line"><a name="a4187"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span><span class="src-sym">(</span><span class="src-sym">!</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'NUMBERS_CACHE'</span><span class="src-sym">]</span><span class="src-sym">))</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4188"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">build_style_cache</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4189"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4190"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4191"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;First,&nbsp;work&nbsp;out&nbsp;what&nbsp;the&nbsp;selector&nbsp;should&nbsp;be.&nbsp;If&nbsp;there's&nbsp;an&nbsp;ID,</span></span></div></li>
+<li><div class="src-line"><a name="a4192"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;that&nbsp;should&nbsp;be&nbsp;used,&nbsp;the&nbsp;same&nbsp;for&nbsp;a&nbsp;class.&nbsp;Otherwise,&nbsp;a&nbsp;selector</span></span></div></li>
+<li><div class="src-line"><a name="a4193"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;of&nbsp;''&nbsp;means&nbsp;that&nbsp;these&nbsp;styles&nbsp;will&nbsp;be&nbsp;applied&nbsp;anywhere</span></span></div></li>
+<li><div class="src-line"><a name="a4194"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">overall_id</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4195"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$selector</span>&nbsp;=&nbsp;<span class="src-str">'#'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">overall_id</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4196"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4197"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$selector</span>&nbsp;=&nbsp;<span class="src-str">'.'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4198"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">overall_class</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4199"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$selector</span>&nbsp;.=&nbsp;<span class="src-str">'.'</span>&nbsp;.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">overall_class</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4200"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4201"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4202"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$selector</span>&nbsp;.=&nbsp;<span class="src-str">'&nbsp;'</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4203"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4204"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Header&nbsp;of&nbsp;the&nbsp;stylesheet</span></span></div></li>
+<li><div class="src-line"><a name="a4205"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$economy_mode</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4206"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet</span>&nbsp;=&nbsp;<span class="src-str">&quot;/**\n&quot;</span>.</span></div></li>
+<li><div class="src-line"><a name="a4207"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">&quot;&nbsp;*&nbsp;GeSHi&nbsp;Dynamically&nbsp;Generated&nbsp;Stylesheet\n&quot;</span>.</span></div></li>
+<li><div class="src-line"><a name="a4208"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">&quot;&nbsp;*&nbsp;--------------------------------------\n&quot;</span>.</span></div></li>
+<li><div class="src-line"><a name="a4209"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">"</span></span>&nbsp;*&nbsp;Dynamically&nbsp;generated&nbsp;stylesheet&nbsp;for&nbsp;{<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language</span><span class="src-sym">}</span>\n<span class="src-str">&quot;</span><span class="src-str">.</span></div></li>
+<li><div class="src-line"><a name="a4210"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="src-str">&quot;</span>&nbsp;*&nbsp;CSS&nbsp;class:&nbsp;{<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">overall_class</span><span class="src-sym">}</span>,&nbsp;CSS&nbsp;id:&nbsp;{<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">overall_id</span><span class="src-sym">}</span>\n<span class="src-str">&quot;</span><span class="src-str">.</span></div></li>
+<li><div class="src-line"><a name="a4211"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">&quot;&nbsp;*&nbsp;GeSHi&nbsp;(C)&nbsp;2004&nbsp;-&nbsp;2007&nbsp;Nigel&nbsp;McNie,&nbsp;2007&nbsp;-&nbsp;2008&nbsp;Benny&nbsp;Baumann\n&quot;</span>&nbsp;.</span></div></li>
+<li><div class="src-line"><a name="a4212"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">&quot;&nbsp;*&nbsp;(http://qbnz.com/highlighter/&nbsp;and&nbsp;http://geshi.org/)\n&quot;</span>.</span></div></li>
+<li><div class="src-line"><a name="a4213"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">&quot;&nbsp;*&nbsp;--------------------------------------\n&quot;</span>.</span></div></li>
+<li><div class="src-line"><a name="a4214"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">&quot;&nbsp;*/\n&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4215"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span>&nbsp;<span class="src-key">else</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4216"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet</span>&nbsp;=&nbsp;<span class="src-str">&quot;/**\n&quot;</span>.</span></div></li>
+<li><div class="src-line"><a name="a4217"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">&quot;&nbsp;*&nbsp;GeSHi&nbsp;(C)&nbsp;2004&nbsp;-&nbsp;2007&nbsp;Nigel&nbsp;McNie,&nbsp;2007&nbsp;-&nbsp;2008&nbsp;Benny&nbsp;Baumann\n&quot;</span>&nbsp;.</span></div></li>
+<li><div class="src-line"><a name="a4218"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">&quot;&nbsp;*&nbsp;(http://qbnz.com/highlighter/&nbsp;and&nbsp;http://geshi.org/)\n&quot;</span>.</span></div></li>
+<li><div class="src-line"><a name="a4219"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">&quot;&nbsp;*/\n&quot;</span><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4220"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4221"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4222"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Set&nbsp;the&nbsp;&lt;ol&gt;&nbsp;to&nbsp;have&nbsp;no&nbsp;effect&nbsp;at&nbsp;all&nbsp;if&nbsp;there&nbsp;are&nbsp;line&nbsp;numbers</span></span></div></li>
+<li><div class="src-line"><a name="a4223"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;(&lt;ol&gt;s&nbsp;have&nbsp;margins&nbsp;that&nbsp;should&nbsp;be&nbsp;destroyed&nbsp;so&nbsp;all&nbsp;layout&nbsp;is</span></span></div></li>
+<li><div class="src-line"><a name="a4224"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;controlled&nbsp;by&nbsp;the&nbsp;set_overall_style&nbsp;method,&nbsp;which&nbsp;works&nbsp;on&nbsp;the</span></span></div></li>
+<li><div class="src-line"><a name="a4225"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;&lt;pre&gt;&nbsp;or&nbsp;&lt;div&gt;&nbsp;container).&nbsp;Additionally,&nbsp;set&nbsp;default&nbsp;styles&nbsp;for&nbsp;lines</span></span></div></li>
+<li><div class="src-line"><a name="a4226"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$economy_mode</span>&nbsp;||&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers</span>&nbsp;!=&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_NO_LINE_NUMBERS&quot;&gt;GESHI_NO_LINE_NUMBERS&lt;/a&gt;</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4227"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//$stylesheet&nbsp;.=&nbsp;&quot;$selector,&nbsp;{$selector}ol,&nbsp;{$selector}ol&nbsp;li&nbsp;{margin:&nbsp;0;}\n&quot;;</span></span></div></li>
+<li><div class="src-line"><a name="a4228"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet</span>&nbsp;.=&nbsp;<span class="src-str">"</span></span><span class="src-var">$selector</span>.de1,&nbsp;<span class="src-var">$selector</span>.de2&nbsp;{{<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">code_style</span><span class="src-sym">}</span>}\n<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4229"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4230"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4231"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Add&nbsp;overall&nbsp;styles</span></span></div></li>
+<li><div class="src-line"><a name="a4232"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;note:&nbsp;neglect&nbsp;economy_mode,&nbsp;empty&nbsp;styles&nbsp;are&nbsp;meaningless</span></span></div></li>
+<li><div class="src-line"><a name="a4233"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">overall_style</span>&nbsp;!=&nbsp;<span class="src-str">''</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4234"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet</span>&nbsp;.=&nbsp;<span class="src-str">"</span></span><span class="src-var">$selector</span>&nbsp;{{<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">overall_style</span><span class="src-sym">}</span>}\n<span class="src-str">&quot;</span><span class="src-str"><span class="src-sym">;</span></span></div></li>
+<li><div class="src-line"><a name="a4235"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></span></div></li>
+<li><div class="src-line"><a name="a4236"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4237"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Add&nbsp;styles&nbsp;for&nbsp;links</span></span></div></li>
+<li><div class="src-line"><a name="a4238"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;note:&nbsp;economy&nbsp;mode&nbsp;does&nbsp;not&nbsp;make&nbsp;_any_&nbsp;sense&nbsp;here</span></span></div></li>
+<li><div class="src-line"><a name="a4239"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;either&nbsp;the&nbsp;style&nbsp;is&nbsp;empty&nbsp;and&nbsp;thus&nbsp;no&nbsp;selector&nbsp;is&nbsp;needed</span></span></div></li>
+<li><div class="src-line"><a name="a4240"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;or&nbsp;the&nbsp;appropriate&nbsp;key&nbsp;is&nbsp;given.</span></span></div></li>
+<li><div class="src-line"><a name="a4241"></a></span><span class="src-str"><span class="src-comm"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">link_styles</span>&nbsp;<span class="src-key">as</span>&nbsp;<span class="src-var">$key</span>&nbsp;=&gt;&nbsp;<span class="src-var">$style</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4242"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$style</span>&nbsp;!=&nbsp;<span class="src-str">''</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4243"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">switch</span>&nbsp;<span class="src-sym">(</span><span class="src-var">$key</span><span class="src-sym">)</span>&nbsp;<span class="src-sym">{</span></span></div></li>
+<li><div class="src-line"><a name="a4244"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">case</span>&nbsp;<span class="src-id">&lt;a&nbsp;href=&quot;../geshi/core/_geshi.php.html#defineGESHI_LINK&quot;&gt;GESHI_LINK&lt;/a&gt;</span>:</span></div></li>
+<li><div class="src-line"><a name="a4245"></a></span><span class="src-str">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet</span>&nbsp;.=&nbsp;<span class="src-str">"</span>{<span class="src-var">$selector</span><span class="src-sym">}</span>a:link&nbsp;{{<span class="src-var">$style</span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4246"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">break</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4247"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">case&nbsp;</span><span class="src-id"><a href="../geshi/core/_geshi.php.html#defineGESHI_HOVER">GESHI_HOVER</a></span>:</div></li>
+<li><div class="src-line"><a name="a4248"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span>{<span class="src-var">$selector</span><span class="src-str"></span><span class="src-sym">}</span>a:hover&nbsp;{{<span class="src-var">$style</span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4249"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">break</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4250"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">case&nbsp;</span><span class="src-id"><a href="../geshi/core/_geshi.php.html#defineGESHI_ACTIVE">GESHI_ACTIVE</a></span>:</div></li>
+<li><div class="src-line"><a name="a4251"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span>{<span class="src-var">$selector</span><span class="src-str"></span><span class="src-sym">}</span>a:active&nbsp;{{<span class="src-var">$style</span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4252"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">break</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4253"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">case&nbsp;</span><span class="src-id"><a href="../geshi/core/_geshi.php.html#defineGESHI_VISITED">GESHI_VISITED</a></span>:</div></li>
+<li><div class="src-line"><a name="a4254"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span>{<span class="src-var">$selector</span><span class="src-str"></span><span class="src-sym">}</span>a:visited&nbsp;{{<span class="src-var">$style</span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4255"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">break</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4256"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4257"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4258"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4259"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4260"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Header&nbsp;and&nbsp;footer</span></div></li>
+<li><div class="src-line"><a name="a4261"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;note:&nbsp;neglect&nbsp;economy_mode,&nbsp;empty&nbsp;styles&nbsp;are&nbsp;meaningless</span></div></li>
+<li><div class="src-line"><a name="a4262"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">header_content_style&nbsp;</span>!=&nbsp;<span class="src-str">''</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4263"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span><span class="src-str"><span class="src-var">$selector</span>.head&nbsp;{{<span class="src-var">$this</span></span><span class="src-sym">-&gt;</span><span class="src-id">header_content_style</span><span class="src-str"></span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4264"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4265"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">footer_content_style&nbsp;</span>!=&nbsp;<span class="src-str">''</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4266"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span><span class="src-str"><span class="src-var">$selector</span>.foot&nbsp;{{<span class="src-var">$this</span></span><span class="src-sym">-&gt;</span><span class="src-id">footer_content_style</span><span class="src-str"></span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4267"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4268"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4269"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Styles&nbsp;for&nbsp;important&nbsp;stuff</span></div></li>
+<li><div class="src-line"><a name="a4270"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;note:&nbsp;neglect&nbsp;economy_mode,&nbsp;empty&nbsp;styles&nbsp;are&nbsp;meaningless</span></div></li>
+<li><div class="src-line"><a name="a4271"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">important_styles&nbsp;</span>!=&nbsp;<span class="src-str">''</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4272"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span><span class="src-str"><span class="src-var">$selector</span>.imp&nbsp;{{<span class="src-var">$this</span></span><span class="src-sym">-&gt;</span><span class="src-id">important_styles</span><span class="src-str"></span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4273"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4274"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4275"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Simple&nbsp;line&nbsp;number&nbsp;styles</span></div></li>
+<li><div class="src-line"><a name="a4276"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">((</span><span class="src-sym">!</span><span class="src-var">$economy_mode&nbsp;</span>||&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers&nbsp;</span>!=&nbsp;<span class="src-id"><a href="../geshi/core/_geshi.php.html#defineGESHI_NO_LINE_NUMBERS">GESHI_NO_LINE_NUMBERS</a></span><span class="src-sym">)&nbsp;</span>&amp;&amp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_style1&nbsp;</span>!=&nbsp;<span class="src-str">''</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4277"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span>{<span class="src-var">$selector</span><span class="src-str"></span><span class="src-sym">}</span>li,&nbsp;{<span class="src-var">$selector</span><span class="src-sym">}</span>.li1&nbsp;{{<span class="src-var">$this</span></span><span class="src-sym">-&gt;</span><span class="src-id">line_style1</span><span class="src-str"></span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4278"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4279"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">((</span><span class="src-sym">!</span><span class="src-var">$economy_mode&nbsp;</span>||&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers&nbsp;</span>!=&nbsp;<span class="src-id"><a href="../geshi/core/_geshi.php.html#defineGESHI_NO_LINE_NUMBERS">GESHI_NO_LINE_NUMBERS</a></span><span class="src-sym">)&nbsp;</span>&amp;&amp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">table_linenumber_style&nbsp;</span>!=&nbsp;<span class="src-str">''</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4280"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span>{<span class="src-var">$selector</span><span class="src-str"></span><span class="src-sym">}</span>.ln&nbsp;{{<span class="src-var">$this</span></span><span class="src-sym">-&gt;</span><span class="src-id">table_linenumber_style</span><span class="src-str"></span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4281"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4282"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;If&nbsp;there&nbsp;is&nbsp;a&nbsp;style&nbsp;set&nbsp;for&nbsp;fancy&nbsp;line&nbsp;numbers,&nbsp;echo&nbsp;it&nbsp;out</span></div></li>
+<li><div class="src-line"><a name="a4283"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">((</span><span class="src-sym">!</span><span class="src-var">$economy_mode&nbsp;</span>||&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_numbers&nbsp;</span>==&nbsp;<span class="src-id"><a href="../geshi/core/_geshi.php.html#defineGESHI_FANCY_LINE_NUMBERS">GESHI_FANCY_LINE_NUMBERS</a></span><span class="src-sym">)&nbsp;</span>&amp;&amp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">line_style2&nbsp;</span>!=&nbsp;<span class="src-str">''</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4284"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span>{<span class="src-var">$selector</span><span class="src-str"></span><span class="src-sym">}</span>.li2&nbsp;{{<span class="src-var">$this</span></span><span class="src-sym">-&gt;</span><span class="src-id">line_style2</span><span class="src-str"></span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4285"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4286"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4287"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;note:&nbsp;empty&nbsp;styles&nbsp;are&nbsp;meaningless</span></div></li>
+<li><div class="src-line"><a name="a4288"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach&nbsp;</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]&nbsp;</span><span class="src-key">as&nbsp;</span><span class="src-var">$group&nbsp;</span>=&gt;&nbsp;<span class="src-var">$styles</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4289"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$styles&nbsp;</span>!=&nbsp;<span class="src-str">''&nbsp;</span>&amp;&amp;&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$economy_mode&nbsp;</span>||</div></li>
+<li><div class="src-line"><a name="a4290"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$group</span><span class="src-sym">]</span><span class="src-sym">)&nbsp;</span>&amp;&amp;</div></li>
+<li><div class="src-line"><a name="a4291"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'KEYWORDS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$group</span><span class="src-sym">]</span><span class="src-sym">)))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4292"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span><span class="src-str"><span class="src-var">$selector</span>.kw<span class="src-var">$group</span>&nbsp;{{<span class="src-var">$styles</span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4293"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4294"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4295"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach&nbsp;</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]&nbsp;</span><span class="src-key">as&nbsp;</span><span class="src-var">$group&nbsp;</span>=&gt;&nbsp;<span class="src-var">$styles</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4296"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$styles&nbsp;</span>!=&nbsp;<span class="src-str">''&nbsp;</span>&amp;&amp;&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$economy_mode&nbsp;</span>||</div></li>
+<li><div class="src-line"><a name="a4297"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$group</span><span class="src-sym">]</span><span class="src-sym">)&nbsp;</span>&amp;&amp;</div></li>
+<li><div class="src-line"><a name="a4298"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'COMMENTS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$group</span><span class="src-sym">]</span><span class="src-sym">)&nbsp;</span>||</div></li>
+<li><div class="src-line"><a name="a4299"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'COMMENT_REGEXP'</span><span class="src-sym">]</span><span class="src-sym">)&nbsp;</span>&amp;&amp;</div></li>
+<li><div class="src-line"><a name="a4300"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">!</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'COMMENT_REGEXP'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$group</span><span class="src-sym">]</span><span class="src-sym">))))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4301"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span><span class="src-str"><span class="src-var">$selector</span>.co<span class="src-var">$group</span>&nbsp;{{<span class="src-var">$styles</span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4302"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4303"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4304"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach&nbsp;</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]&nbsp;</span><span class="src-key">as&nbsp;</span><span class="src-var">$group&nbsp;</span>=&gt;&nbsp;<span class="src-var">$styles</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4305"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$styles&nbsp;</span>!=&nbsp;<span class="src-str">''&nbsp;</span>&amp;&amp;&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$economy_mode&nbsp;</span>||&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'ESCAPE_CHAR'</span><span class="src-sym">]</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4306"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;NEW:&nbsp;since&nbsp;1.0.8&nbsp;we&nbsp;have&nbsp;to&nbsp;handle&nbsp;hardescapes</span></div></li>
+<li><div class="src-line"><a name="a4307"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$group&nbsp;</span>===&nbsp;<span class="src-str">'HARD'</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4308"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$group&nbsp;</span>=&nbsp;<span class="src-str">'_h'</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4309"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4310"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span><span class="src-str"><span class="src-var">$selector</span>.es<span class="src-var">$group</span>&nbsp;{{<span class="src-var">$styles</span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4311"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4312"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4313"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach&nbsp;</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'BRACKETS'</span><span class="src-sym">]&nbsp;</span><span class="src-key">as&nbsp;</span><span class="src-var">$group&nbsp;</span>=&gt;&nbsp;<span class="src-var">$styles</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4314"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$styles&nbsp;</span>!=&nbsp;<span class="src-str">''&nbsp;</span>&amp;&amp;&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$economy_mode&nbsp;</span>||&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'BRACKETS'</span><span class="src-sym">]</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4315"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span><span class="src-str"><span class="src-var">$selector</span>.br<span class="src-var">$group</span>&nbsp;{{<span class="src-var">$styles</span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4316"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4317"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4318"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach&nbsp;</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'SYMBOLS'</span><span class="src-sym">]&nbsp;</span><span class="src-key">as&nbsp;</span><span class="src-var">$group&nbsp;</span>=&gt;&nbsp;<span class="src-var">$styles</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4319"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$styles&nbsp;</span>!=&nbsp;<span class="src-str">''&nbsp;</span>&amp;&amp;&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$economy_mode&nbsp;</span>||&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'SYMBOLS'</span><span class="src-sym">]</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4320"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span><span class="src-str"><span class="src-var">$selector</span>.sy<span class="src-var">$group</span>&nbsp;{{<span class="src-var">$styles</span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4321"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4322"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4323"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach&nbsp;</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'STRINGS'</span><span class="src-sym">]&nbsp;</span><span class="src-key">as&nbsp;</span><span class="src-var">$group&nbsp;</span>=&gt;&nbsp;<span class="src-var">$styles</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4324"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$styles&nbsp;</span>!=&nbsp;<span class="src-str">''&nbsp;</span>&amp;&amp;&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$economy_mode&nbsp;</span>||&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'STRINGS'</span><span class="src-sym">]</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4325"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;NEW:&nbsp;since&nbsp;1.0.8&nbsp;we&nbsp;have&nbsp;to&nbsp;handle&nbsp;hardquotes</span></div></li>
+<li><div class="src-line"><a name="a4326"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$group&nbsp;</span>===&nbsp;<span class="src-str">'HARD'</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4327"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$group&nbsp;</span>=&nbsp;<span class="src-str">'_h'</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4328"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4329"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span><span class="src-str"><span class="src-var">$selector</span>.st<span class="src-var">$group</span>&nbsp;{{<span class="src-var">$styles</span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4330"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4331"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4332"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach&nbsp;</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]&nbsp;</span><span class="src-key">as&nbsp;</span><span class="src-var">$group&nbsp;</span>=&gt;&nbsp;<span class="src-var">$styles</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4333"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$styles&nbsp;</span>!=&nbsp;<span class="src-str">''&nbsp;</span>&amp;&amp;&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$economy_mode&nbsp;</span>||&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'NUMBERS'</span><span class="src-sym">]</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4334"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span><span class="src-str"><span class="src-var">$selector</span>.nu<span class="src-var">$group</span>&nbsp;{{<span class="src-var">$styles</span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4335"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4336"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4337"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach&nbsp;</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'METHODS'</span><span class="src-sym">]&nbsp;</span><span class="src-key">as&nbsp;</span><span class="src-var">$group&nbsp;</span>=&gt;&nbsp;<span class="src-var">$styles</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4338"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$styles&nbsp;</span>!=&nbsp;<span class="src-str">''&nbsp;</span>&amp;&amp;&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$economy_mode&nbsp;</span>||&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'METHODS'</span><span class="src-sym">]</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4339"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span><span class="src-str"><span class="src-var">$selector</span>.me<span class="src-var">$group</span>&nbsp;{{<span class="src-var">$styles</span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4340"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4341"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4342"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;note:&nbsp;neglect&nbsp;economy_mode,&nbsp;empty&nbsp;styles&nbsp;are&nbsp;meaningless</span></div></li>
+<li><div class="src-line"><a name="a4343"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach&nbsp;</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'SCRIPT'</span><span class="src-sym">]&nbsp;</span><span class="src-key">as&nbsp;</span><span class="src-var">$group&nbsp;</span>=&gt;&nbsp;<span class="src-var">$styles</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4344"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$styles&nbsp;</span>!=&nbsp;<span class="src-str">''</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4345"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span><span class="src-str"><span class="src-var">$selector</span>.sc<span class="src-var">$group</span>&nbsp;{{<span class="src-var">$styles</span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4346"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4347"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4348"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach&nbsp;</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'STYLES'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]&nbsp;</span><span class="src-key">as&nbsp;</span><span class="src-var">$group&nbsp;</span>=&gt;&nbsp;<span class="src-var">$styles</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4349"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$styles&nbsp;</span>!=&nbsp;<span class="src-str">''&nbsp;</span>&amp;&amp;&nbsp;<span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$economy_mode&nbsp;</span>||</div></li>
+<li><div class="src-line"><a name="a4350"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$group</span><span class="src-sym">]</span><span class="src-sym">)&nbsp;</span>&amp;&amp;</div></li>
+<li><div class="src-line"><a name="a4351"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">lexic_permissions</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$group</span><span class="src-sym">]</span><span class="src-sym">)))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4352"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><a href="http://www.php.net/is_array">is_array</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$group</span><span class="src-sym">]</span><span class="src-sym">)&nbsp;</span>&amp;&amp;</div></li>
+<li><div class="src-line"><a name="a4353"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/array_key_exists">array_key_exists</a><span class="src-sym">(</span><span class="src-id">GESHI_CLASS</span><span class="src-sym">,&nbsp;</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$group</span><span class="src-sym">]</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4354"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span><span class="src-str"><span class="src-var">$selector</span>.</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4355"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">language_data</span><span class="src-sym">[</span><span class="src-str">'REGEXPS'</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$group</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-id">GESHI_CLASS</span><span class="src-sym">]</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4356"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span><span class="src-str">&nbsp;{{<span class="src-var">$styles</span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4357"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}&nbsp;</span><span class="src-key">else&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4358"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span><span class="src-str"><span class="src-var">$selector</span>.re<span class="src-var">$group</span>&nbsp;{{<span class="src-var">$styles</span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4359"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4360"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4361"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4362"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;Styles&nbsp;for&nbsp;lines&nbsp;being&nbsp;highlighted&nbsp;extra</span></div></li>
+<li><div class="src-line"><a name="a4363"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$economy_mode&nbsp;</span>||&nbsp;<span class="src-sym">(</span><a href="http://www.php.net/count">count</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">highlight_extra_lines</span><span class="src-sym">)</span>!=<a href="http://www.php.net/count">count</a><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">highlight_extra_lines_styles</span><span class="src-sym">)))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4364"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span>{<span class="src-var">$selector</span><span class="src-str"></span><span class="src-sym">}</span>.ln-xtra,&nbsp;{<span class="src-var">$selector</span><span class="src-sym">}</span>li.ln-xtra,&nbsp;{<span class="src-var">$selector</span><span class="src-sym">}</span>div.ln-xtra&nbsp;{{<span class="src-var">$this</span></span><span class="src-sym">-&gt;</span><span class="src-id">highlight_extra_lines_style</span><span class="src-str"></span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4365"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4366"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span>{<span class="src-var">$selector</span><span class="src-str"></span><span class="src-sym">}</span>span.xtra&nbsp;{&nbsp;display:block;&nbsp;}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4367"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach&nbsp;</span><span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">highlight_extra_lines_styles&nbsp;</span><span class="src-key">as&nbsp;</span><span class="src-var">$lineid&nbsp;</span>=&gt;&nbsp;<span class="src-var">$linestyle</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4368"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$stylesheet&nbsp;</span>.=&nbsp;<span class="src-str">&quot;</span>{<span class="src-var">$selector</span><span class="src-str"></span><span class="src-sym">}</span>.lx<span class="src-var">$lineid</span>,&nbsp;{<span class="src-var">$selector</span><span class="src-sym">}</span>li.lx<span class="src-var">$lineid</span>,&nbsp;{<span class="src-var">$selector</span><span class="src-sym">}</span>div.lx<span class="src-var">$lineid</span>&nbsp;{{<span class="src-var">$linestyle</span><span class="src-sym">}</span>}\n</span><span class="src-str">&quot;</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4369"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4370"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4371"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return&nbsp;</span><span class="src-var">$stylesheet</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4372"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4373"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4374"></a>&nbsp;&nbsp;&nbsp;&nbsp;/**</div></li>
+<li><div class="src-line"><a name="a4375"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Get's&nbsp;the&nbsp;style&nbsp;that&nbsp;is&nbsp;used&nbsp;for&nbsp;the&nbsp;specified&nbsp;line</div></li>
+<li><div class="src-line"><a name="a4376"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</div></li>
+<li><div class="src-line"><a name="a4377"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;int&nbsp;The&nbsp;line&nbsp;number&nbsp;information&nbsp;is&nbsp;requested&nbsp;for</div></li>
+<li><div class="src-line"><a name="a4378"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@access&nbsp;private</div></li>
+<li><div class="src-line"><a name="a4379"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@since&nbsp;1.0.7.21</div></li>
+<li><div class="src-line"><a name="a4380"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</div></li>
+<li><div class="src-line"><a name="a4381"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function&nbsp;</span><span class="src-id">get_line_style</span><span class="src-sym">(</span><span class="src-var">$line</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4382"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//$style&nbsp;=&nbsp;null;</span></div></li>
+<li><div class="src-line"><a name="a4383"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$style&nbsp;</span>=&nbsp;<span class="src-id">null</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4384"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">highlight_extra_lines_styles</span><span class="src-sym">[</span><span class="src-var">$line</span><span class="src-sym">]</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4385"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$style&nbsp;</span>=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">highlight_extra_lines_styles</span><span class="src-sym">[</span><span class="src-var">$line</span><span class="src-sym">]</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4386"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}&nbsp;</span><span class="src-key">else&nbsp;</span><span class="src-sym">{&nbsp;</span><span class="src-comm">//&nbsp;if&nbsp;no&nbsp;&quot;extra&quot;&nbsp;style&nbsp;assigned</span></div></li>
+<li><div class="src-line"><a name="a4387"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$style&nbsp;</span>=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">highlight_extra_lines_style</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4388"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4389"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4390"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return&nbsp;</span><span class="src-var">$style</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4391"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4392"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4393"></a>&nbsp;&nbsp;&nbsp;&nbsp;/**</div></li>
+<li><div class="src-line"><a name="a4394"></a>&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;this&nbsp;functions&nbsp;creates&nbsp;an&nbsp;optimized&nbsp;regular&nbsp;expression&nbsp;list</div></li>
+<li><div class="src-line"><a name="a4395"></a>&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;of&nbsp;an&nbsp;array&nbsp;of&nbsp;strings.</div></li>
+<li><div class="src-line"><a name="a4396"></a>&nbsp;&nbsp;&nbsp;&nbsp;*</div></li>
+<li><div class="src-line"><a name="a4397"></a>&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Example:</div></li>
+<li><div class="src-line"><a name="a4398"></a>&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;code&gt;$list&nbsp;=&nbsp;array('faa',&nbsp;'foo',&nbsp;'foobar');</div></li>
+<li><div class="src-line"><a name="a4399"></a>&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;&nbsp;string&nbsp;'f(aa|oo(bar)?)'&lt;/code&gt;</div></li>
+<li><div class="src-line"><a name="a4400"></a>&nbsp;&nbsp;&nbsp;&nbsp;*</div></li>
+<li><div class="src-line"><a name="a4401"></a>&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;$list&nbsp;array&nbsp;of&nbsp;(unquoted)&nbsp;strings</div></li>
+<li><div class="src-line"><a name="a4402"></a>&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;$regexp_delimiter&nbsp;your&nbsp;regular&nbsp;expression&nbsp;delimiter,&nbsp;@see&nbsp;preg_quote()</div></li>
+<li><div class="src-line"><a name="a4403"></a>&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;string&nbsp;for&nbsp;regular&nbsp;expression</div></li>
+<li><div class="src-line"><a name="a4404"></a>&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@author&nbsp;Milian&nbsp;Wolff&nbsp;&lt;mail@milianw.de&gt;</div></li>
+<li><div class="src-line"><a name="a4405"></a>&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@since&nbsp;1.0.8</div></li>
+<li><div class="src-line"><a name="a4406"></a>&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@access&nbsp;private</div></li>
+<li><div class="src-line"><a name="a4407"></a>&nbsp;&nbsp;&nbsp;&nbsp;*/</div></li>
+<li><div class="src-line"><a name="a4408"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function&nbsp;</span><span class="src-id">optimize_regexp_list</span><span class="src-sym">(</span><span class="src-var">$list</span><span class="src-sym">,&nbsp;</span><span class="src-var">$regexp_delimiter&nbsp;</span>=&nbsp;<span class="src-str">'/'</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4409"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$regex_chars&nbsp;</span>=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">'.'</span><span class="src-sym">,&nbsp;</span><span class="src-str">'\\'</span><span class="src-sym">,&nbsp;</span><span class="src-str">'+'</span><span class="src-sym">,&nbsp;</span><span class="src-str">'*'</span><span class="src-sym">,&nbsp;</span><span class="src-str">'?'</span><span class="src-sym">,&nbsp;</span><span class="src-str">'['</span><span class="src-sym">,&nbsp;</span><span class="src-str">'^'</span><span class="src-sym">,&nbsp;</span><span class="src-str">']'</span><span class="src-sym">,&nbsp;</span><span class="src-str">'$'</span><span class="src-sym">,</span></div></li>
+<li><div class="src-line"><a name="a4410"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-str">'('</span><span class="src-sym">,&nbsp;</span><span class="src-str">')'</span><span class="src-sym">,&nbsp;</span><span class="src-str">'{'</span><span class="src-sym">,&nbsp;</span><span class="src-str">'}'</span><span class="src-sym">,&nbsp;</span><span class="src-str">'='</span><span class="src-sym">,&nbsp;</span><span class="src-str">'!'</span><span class="src-sym">,&nbsp;</span><span class="src-str">'&lt;'</span><span class="src-sym">,&nbsp;</span><span class="src-str">'&gt;'</span><span class="src-sym">,&nbsp;</span><span class="src-str">'|'</span><span class="src-sym">,&nbsp;</span><span class="src-str">':'</span><span class="src-sym">,&nbsp;</span><span class="src-var">$regexp_delimiter</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4411"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/sort">sort</a><span class="src-sym">(</span><span class="src-var">$list</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4412"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$regexp_list&nbsp;</span>=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">''</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4413"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$num_subpatterns&nbsp;</span>=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4414"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$list_key&nbsp;</span>=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4415"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4416"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;the&nbsp;tokens&nbsp;which&nbsp;we&nbsp;will&nbsp;use&nbsp;to&nbsp;generate&nbsp;the&nbsp;regexp&nbsp;list</span></div></li>
+<li><div class="src-line"><a name="a4417"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$tokens&nbsp;</span>=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4418"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$prev_keys&nbsp;</span>=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4419"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;go&nbsp;through&nbsp;all&nbsp;entries&nbsp;of&nbsp;the&nbsp;list&nbsp;and&nbsp;generate&nbsp;the&nbsp;token&nbsp;list</span></div></li>
+<li><div class="src-line"><a name="a4420"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$cur_len&nbsp;</span>=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4421"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">for&nbsp;</span><span class="src-sym">(</span><span class="src-var">$i&nbsp;</span>=&nbsp;<span class="src-num">0</span><span class="src-sym">,&nbsp;</span><span class="src-var">$i_max&nbsp;</span>=&nbsp;<a href="http://www.php.net/count">count</a><span class="src-sym">(</span><span class="src-var">$list</span><span class="src-sym">)</span><span class="src-sym">;&nbsp;</span><span class="src-var">$i&nbsp;</span>&lt;&nbsp;<span class="src-var">$i_max</span><span class="src-sym">;&nbsp;</span>++<span class="src-var">$i</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4422"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$cur_len&nbsp;</span>&gt;&nbsp;<span class="src-id">GESHI_MAX_PCRE_LENGTH</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4423"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;seems&nbsp;like&nbsp;the&nbsp;length&nbsp;of&nbsp;this&nbsp;pcre&nbsp;is&nbsp;growing&nbsp;exorbitantly</span></div></li>
+<li><div class="src-line"><a name="a4424"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$regexp_list</span><span class="src-sym">[</span>++<span class="src-var">$list_key</span><span class="src-sym">]&nbsp;</span>=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_optimize_regexp_list_tokens_to_string</span><span class="src-sym">(</span><span class="src-var">$tokens</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4425"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$num_subpatterns&nbsp;</span>=&nbsp;<a href="http://www.php.net/substr_count">substr_count</a><span class="src-sym">(</span><span class="src-var">$regexp_list</span><span class="src-sym">[</span><span class="src-var">$list_key</span><span class="src-sym">]</span><span class="src-sym">,&nbsp;</span><span class="src-str">'(?:'</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4426"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$tokens&nbsp;</span>=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4427"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$cur_len&nbsp;</span>=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4428"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4429"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$level&nbsp;</span>=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4430"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$entry&nbsp;</span>=&nbsp;<a href="http://www.php.net/preg_quote">preg_quote</a><span class="src-sym">(</span>(string)&nbsp;<span class="src-var">$list</span><span class="src-sym">[</span><span class="src-var">$i</span><span class="src-sym">]</span><span class="src-sym">,&nbsp;</span><span class="src-var">$regexp_delimiter</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4431"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$pointer&nbsp;</span>=&nbsp;<span class="src-sym">&amp;</span><span class="src-var">$tokens</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4432"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;properly&nbsp;assign&nbsp;the&nbsp;new&nbsp;entry&nbsp;to&nbsp;the&nbsp;correct&nbsp;position&nbsp;in&nbsp;the&nbsp;token&nbsp;array</span></div></li>
+<li><div class="src-line"><a name="a4433"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;possibly&nbsp;generate&nbsp;smaller&nbsp;common&nbsp;denominator&nbsp;keys</span></div></li>
+<li><div class="src-line"><a name="a4434"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">while&nbsp;</span><span class="src-sym">(</span><span class="src-id">true</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4435"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;get&nbsp;the&nbsp;common&nbsp;denominator</span></div></li>
+<li><div class="src-line"><a name="a4436"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$prev_keys</span><span class="src-sym">[</span><span class="src-var">$level</span><span class="src-sym">]</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4437"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$prev_keys</span><span class="src-sym">[</span><span class="src-var">$level</span><span class="src-sym">]&nbsp;</span>==&nbsp;<span class="src-var">$entry</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4438"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;this&nbsp;is&nbsp;a&nbsp;duplicate&nbsp;entry,&nbsp;skip&nbsp;it</span></div></li>
+<li><div class="src-line"><a name="a4439"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue&nbsp;</span><span class="src-num">2</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4440"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4441"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$char&nbsp;</span>=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4442"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">while&nbsp;</span><span class="src-sym">(</span>isset<span class="src-sym">(</span><span class="src-var">$entry</span><span class="src-sym">[</span><span class="src-var">$char</span><span class="src-sym">]</span><span class="src-sym">)&nbsp;</span>&amp;&amp;&nbsp;isset<span class="src-sym">(</span><span class="src-var">$prev_keys</span><span class="src-sym">[</span><span class="src-var">$level</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$char</span><span class="src-sym">]</span><span class="src-sym">)</span></div></li>
+<li><div class="src-line"><a name="a4443"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp;&nbsp;<span class="src-var">$entry</span><span class="src-sym">[</span><span class="src-var">$char</span><span class="src-sym">]&nbsp;</span>==&nbsp;<span class="src-var">$prev_keys</span><span class="src-sym">[</span><span class="src-var">$level</span><span class="src-sym">]</span><span class="src-sym">[</span><span class="src-var">$char</span><span class="src-sym">]</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4444"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++<span class="src-var">$char</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4445"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4446"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$char&nbsp;</span>&gt;&nbsp;<span class="src-num">0</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4447"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;this&nbsp;entry&nbsp;has&nbsp;at&nbsp;least&nbsp;some&nbsp;chars&nbsp;in&nbsp;common&nbsp;with&nbsp;the&nbsp;current&nbsp;key</span></div></li>
+<li><div class="src-line"><a name="a4448"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$char&nbsp;</span>==&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$prev_keys</span><span class="src-sym">[</span><span class="src-var">$level</span><span class="src-sym">]</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4449"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;current&nbsp;key&nbsp;is&nbsp;totally&nbsp;matched,&nbsp;i.e.&nbsp;this&nbsp;entry&nbsp;has&nbsp;just&nbsp;some&nbsp;bits&nbsp;appended</span></div></li>
+<li><div class="src-line"><a name="a4450"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$pointer&nbsp;</span>=&nbsp;<span class="src-sym">&amp;</span><span class="src-var">$pointer</span><span class="src-sym">[</span><span class="src-var">$prev_keys</span><span class="src-sym">[</span><span class="src-var">$level</span><span class="src-sym">]]</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4451"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}&nbsp;</span><span class="src-key">else&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4452"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;only&nbsp;part&nbsp;of&nbsp;the&nbsp;keys&nbsp;match</span></div></li>
+<li><div class="src-line"><a name="a4453"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$new_key_part1&nbsp;</span>=&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$prev_keys</span><span class="src-sym">[</span><span class="src-var">$level</span><span class="src-sym">]</span><span class="src-sym">,&nbsp;</span><span class="src-num">0</span><span class="src-sym">,&nbsp;</span><span class="src-var">$char</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4454"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$new_key_part2&nbsp;</span>=&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$prev_keys</span><span class="src-sym">[</span><span class="src-var">$level</span><span class="src-sym">]</span><span class="src-sym">,&nbsp;</span><span class="src-var">$char</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4455"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4456"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><a href="http://www.php.net/in_array">in_array</a><span class="src-sym">(</span><span class="src-var">$new_key_part1</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">,&nbsp;</span><span class="src-var">$regex_chars</span><span class="src-sym">)</span></div></li>
+<li><div class="src-line"><a name="a4457"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;||&nbsp;<a href="http://www.php.net/in_array">in_array</a><span class="src-sym">(</span><span class="src-var">$new_key_part2</span><span class="src-sym">[</span><span class="src-num">0</span><span class="src-sym">]</span><span class="src-sym">,&nbsp;</span><span class="src-var">$regex_chars</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4458"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;this&nbsp;is&nbsp;bad,&nbsp;a&nbsp;regex&nbsp;char&nbsp;as&nbsp;first&nbsp;character</span></div></li>
+<li><div class="src-line"><a name="a4459"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$pointer</span><span class="src-sym">[</span><span class="src-var">$entry</span><span class="src-sym">]&nbsp;</span>=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">''&nbsp;</span>=&gt;&nbsp;<span class="src-id">true</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4460"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/array_splice">array_splice</a><span class="src-sym">(</span><span class="src-var">$prev_keys</span><span class="src-sym">,&nbsp;</span><span class="src-var">$level</span><span class="src-sym">,&nbsp;</span><a href="http://www.php.net/count">count</a><span class="src-sym">(</span><span class="src-var">$prev_keys</span><span class="src-sym">)</span><span class="src-sym">,&nbsp;</span><span class="src-var">$entry</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4461"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$cur_len&nbsp;</span>+=&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$entry</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4462"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4463"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}&nbsp;</span><span class="src-key">else&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4464"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;relocate&nbsp;previous&nbsp;tokens</span></div></li>
+<li><div class="src-line"><a name="a4465"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$pointer</span><span class="src-sym">[</span><span class="src-var">$new_key_part1</span><span class="src-sym">]&nbsp;</span>=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-var">$new_key_part2&nbsp;</span>=&gt;&nbsp;<span class="src-var">$pointer</span><span class="src-sym">[</span><span class="src-var">$prev_keys</span><span class="src-sym">[</span><span class="src-var">$level</span><span class="src-sym">]]</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4466"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$pointer</span><span class="src-sym">[</span><span class="src-var">$prev_keys</span><span class="src-sym">[</span><span class="src-var">$level</span><span class="src-sym">]]</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4467"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$pointer&nbsp;</span>=&nbsp;<span class="src-sym">&amp;</span><span class="src-var">$pointer</span><span class="src-sym">[</span><span class="src-var">$new_key_part1</span><span class="src-sym">]</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4468"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;recreate&nbsp;key&nbsp;index</span></div></li>
+<li><div class="src-line"><a name="a4469"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/array_splice">array_splice</a><span class="src-sym">(</span><span class="src-var">$prev_keys</span><span class="src-sym">,&nbsp;</span><span class="src-var">$level</span><span class="src-sym">,&nbsp;</span><a href="http://www.php.net/count">count</a><span class="src-sym">(</span><span class="src-var">$prev_keys</span><span class="src-sym">)</span><span class="src-sym">,&nbsp;</span><span class="src-key">array</span><span class="src-sym">(</span><span class="src-var">$new_key_part1</span><span class="src-sym">,&nbsp;</span><span class="src-var">$new_key_part2</span><span class="src-sym">))</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4470"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$cur_len&nbsp;</span>+=&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$new_key_part2</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4471"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4472"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4473"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++<span class="src-var">$level</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4474"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$entry&nbsp;</span>=&nbsp;<a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$entry</span><span class="src-sym">,&nbsp;</span><span class="src-var">$char</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4475"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">continue</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4476"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4477"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;else:&nbsp;fall&nbsp;trough,&nbsp;i.e.&nbsp;no&nbsp;common&nbsp;denominator&nbsp;was&nbsp;found</span></div></li>
+<li><div class="src-line"><a name="a4478"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4479"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$level&nbsp;</span>==&nbsp;<span class="src-num">0&nbsp;</span>&amp;&amp;&nbsp;<span class="src-sym">!</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$tokens</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4480"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;we&nbsp;can&nbsp;dump&nbsp;current&nbsp;tokens&nbsp;into&nbsp;the&nbsp;string&nbsp;and&nbsp;throw&nbsp;them&nbsp;away&nbsp;afterwards</span></div></li>
+<li><div class="src-line"><a name="a4481"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$new_entry&nbsp;</span>=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_optimize_regexp_list_tokens_to_string</span><span class="src-sym">(</span><span class="src-var">$tokens</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4482"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$new_subpatterns&nbsp;</span>=&nbsp;<a href="http://www.php.net/substr_count">substr_count</a><span class="src-sym">(</span><span class="src-var">$new_entry</span><span class="src-sym">,&nbsp;</span><span class="src-str">'(?:'</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4483"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-id">GESHI_MAX_PCRE_SUBPATTERNS&nbsp;</span>&amp;&amp;&nbsp;<span class="src-var">$num_subpatterns&nbsp;</span>+&nbsp;<span class="src-var">$new_subpatterns&nbsp;</span>&gt;&nbsp;<span class="src-id">GESHI_MAX_PCRE_SUBPATTERNS</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4484"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$regexp_list</span><span class="src-sym">[</span>++<span class="src-var">$list_key</span><span class="src-sym">]&nbsp;</span>=&nbsp;<span class="src-var">$new_entry</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4485"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$num_subpatterns&nbsp;</span>=&nbsp;<span class="src-var">$new_subpatterns</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4486"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}&nbsp;</span><span class="src-key">else&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4487"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-sym">!</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$regexp_list</span><span class="src-sym">[</span><span class="src-var">$list_key</span><span class="src-sym">]</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4488"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$new_entry&nbsp;</span>=&nbsp;<span class="src-str">'|'&nbsp;</span>.&nbsp;<span class="src-var">$new_entry</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4489"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4490"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$regexp_list</span><span class="src-sym">[</span><span class="src-var">$list_key</span><span class="src-sym">]&nbsp;</span>.=&nbsp;<span class="src-var">$new_entry</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4491"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$num_subpatterns&nbsp;</span>+=&nbsp;<span class="src-var">$new_subpatterns</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4492"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4493"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$tokens&nbsp;</span>=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4494"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$cur_len&nbsp;</span>=&nbsp;<span class="src-num">0</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4495"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4496"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;no&nbsp;further&nbsp;common&nbsp;denominator&nbsp;found</span></div></li>
+<li><div class="src-line"><a name="a4497"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$pointer</span><span class="src-sym">[</span><span class="src-var">$entry</span><span class="src-sym">]&nbsp;</span>=&nbsp;<span class="src-key">array</span><span class="src-sym">(</span><span class="src-str">''&nbsp;</span>=&gt;&nbsp;<span class="src-id">true</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4498"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.php.net/array_splice">array_splice</a><span class="src-sym">(</span><span class="src-var">$prev_keys</span><span class="src-sym">,&nbsp;</span><span class="src-var">$level</span><span class="src-sym">,&nbsp;</span><a href="http://www.php.net/count">count</a><span class="src-sym">(</span><span class="src-var">$prev_keys</span><span class="src-sym">)</span><span class="src-sym">,&nbsp;</span><span class="src-var">$entry</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4499"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4500"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$cur_len&nbsp;</span>+=&nbsp;<a href="http://www.php.net/strlen">strlen</a><span class="src-sym">(</span><span class="src-var">$entry</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4501"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">break</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4502"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4503"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$list</span><span class="src-sym">[</span><span class="src-var">$i</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4504"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4505"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;make&nbsp;sure&nbsp;the&nbsp;last&nbsp;tokens&nbsp;get&nbsp;converted&nbsp;as&nbsp;well</span></div></li>
+<li><div class="src-line"><a name="a4506"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$new_entry&nbsp;</span>=&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_optimize_regexp_list_tokens_to_string</span><span class="src-sym">(</span><span class="src-var">$tokens</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4507"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-id">GESHI_MAX_PCRE_SUBPATTERNS&nbsp;</span>&amp;&amp;&nbsp;<span class="src-var">$num_subpatterns&nbsp;</span>+&nbsp;<a href="http://www.php.net/substr_count">substr_count</a><span class="src-sym">(</span><span class="src-var">$new_entry</span><span class="src-sym">,&nbsp;</span><span class="src-str">'(?:'</span><span class="src-sym">)&nbsp;</span>&gt;&nbsp;<span class="src-id">GESHI_MAX_PCRE_SUBPATTERNS</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4508"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$regexp_list</span><span class="src-sym">[</span>++<span class="src-var">$list_key</span><span class="src-sym">]&nbsp;</span>=&nbsp;<span class="src-var">$new_entry</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4509"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}&nbsp;</span><span class="src-key">else&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4510"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-sym">!</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$regexp_list</span><span class="src-sym">[</span><span class="src-var">$list_key</span><span class="src-sym">]</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4511"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$new_entry&nbsp;</span>=&nbsp;<span class="src-str">'|'&nbsp;</span>.&nbsp;<span class="src-var">$new_entry</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4512"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4513"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$regexp_list</span><span class="src-sym">[</span><span class="src-var">$list_key</span><span class="src-sym">]&nbsp;</span>.=&nbsp;<span class="src-var">$new_entry</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4514"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4515"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return&nbsp;</span><span class="src-var">$regexp_list</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4516"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4517"></a>&nbsp;&nbsp;&nbsp;&nbsp;/**</div></li>
+<li><div class="src-line"><a name="a4518"></a>&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;this&nbsp;function&nbsp;creates&nbsp;the&nbsp;appropriate&nbsp;regexp&nbsp;string&nbsp;of&nbsp;an&nbsp;token&nbsp;array</div></li>
+<li><div class="src-line"><a name="a4519"></a>&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;you&nbsp;should&nbsp;not&nbsp;call&nbsp;this&nbsp;function&nbsp;directly,&nbsp;@see&nbsp;$this-&gt;optimize_regexp_list().</div></li>
+<li><div class="src-line"><a name="a4520"></a>&nbsp;&nbsp;&nbsp;&nbsp;*</div></li>
+<li><div class="src-line"><a name="a4521"></a>&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;&amp;$tokens&nbsp;array&nbsp;of&nbsp;tokens</div></li>
+<li><div class="src-line"><a name="a4522"></a>&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;$recursed&nbsp;bool&nbsp;to&nbsp;know&nbsp;wether&nbsp;we&nbsp;recursed&nbsp;or&nbsp;not</div></li>
+<li><div class="src-line"><a name="a4523"></a>&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;string</div></li>
+<li><div class="src-line"><a name="a4524"></a>&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@author&nbsp;Milian&nbsp;Wolff&nbsp;&lt;mail@milianw.de&gt;</div></li>
+<li><div class="src-line"><a name="a4525"></a>&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@since&nbsp;1.0.8</div></li>
+<li><div class="src-line"><a name="a4526"></a>&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@access&nbsp;private</div></li>
+<li><div class="src-line"><a name="a4527"></a>&nbsp;&nbsp;&nbsp;&nbsp;*/</div></li>
+<li><div class="src-line"><a name="a4528"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function&nbsp;</span><span class="src-id">_optimize_regexp_list_tokens_to_string</span><span class="src-sym">(</span><span class="src-sym">&amp;</span><span class="src-var">$tokens</span><span class="src-sym">,&nbsp;</span><span class="src-var">$recursed&nbsp;</span>=&nbsp;<span class="src-id">false</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4529"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$list&nbsp;</span>=&nbsp;<span class="src-str">''</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4530"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">foreach&nbsp;</span><span class="src-sym">(</span><span class="src-var">$tokens&nbsp;</span><span class="src-key">as&nbsp;</span><span class="src-var">$token&nbsp;</span>=&gt;&nbsp;<span class="src-var">$sub_tokens</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4531"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$list&nbsp;</span>.=&nbsp;<span class="src-var">$token</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4532"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$close_entry&nbsp;</span>=&nbsp;isset<span class="src-sym">(</span><span class="src-var">$sub_tokens</span><span class="src-sym">[</span><span class="src-str">''</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4533"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unset<span class="src-sym">(</span><span class="src-var">$sub_tokens</span><span class="src-sym">[</span><span class="src-str">''</span><span class="src-sym">]</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4534"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-sym">!</span><span class="src-key">empty</span><span class="src-sym">(</span><span class="src-var">$sub_tokens</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4535"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$list&nbsp;</span>.=&nbsp;<span class="src-str">'(?:'&nbsp;</span>.&nbsp;<span class="src-var">$this</span><span class="src-sym">-&gt;</span><span class="src-id">_optimize_regexp_list_tokens_to_string</span><span class="src-sym">(</span><span class="src-var">$sub_tokens</span><span class="src-sym">,&nbsp;</span><span class="src-id">true</span><span class="src-sym">)&nbsp;</span>.&nbsp;<span class="src-str">')'</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4536"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$close_entry</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4537"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;make&nbsp;sub_tokens&nbsp;optional</span></div></li>
+<li><div class="src-line"><a name="a4538"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$list&nbsp;</span>.=&nbsp;<span class="src-str">'?'</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4539"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4540"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4541"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$list&nbsp;</span>.=&nbsp;<span class="src-str">'|'</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4542"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4543"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-sym">!</span><span class="src-var">$recursed</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4544"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;do&nbsp;some&nbsp;optimizations</span></div></li>
+<li><div class="src-line"><a name="a4545"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;common&nbsp;trailing&nbsp;strings</span></div></li>
+<li><div class="src-line"><a name="a4546"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;BUGGY!</span></div></li>
+<li><div class="src-line"><a name="a4547"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//$list&nbsp;=&nbsp;preg_replace_callback('#(?&lt;=^|\:|\|)\w+?(\w+)(?:\|.+\1)+(?=\|)#',&nbsp;create_function(</span></div></li>
+<li><div class="src-line"><a name="a4548"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;&nbsp;&nbsp;&nbsp;'$matches',&nbsp;'return&nbsp;&quot;(?:&quot;&nbsp;.&nbsp;preg_replace(&quot;#&quot;&nbsp;.&nbsp;preg_quote($matches[1],&nbsp;&quot;#&quot;)&nbsp;.&nbsp;&quot;(?=\||$)#&quot;,&nbsp;&quot;&quot;,&nbsp;$matches[0])&nbsp;.&nbsp;&quot;)&quot;&nbsp;.&nbsp;$matches[1];'),&nbsp;$list);</span></div></li>
+<li><div class="src-line"><a name="a4549"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;(?:p)?&nbsp;=&gt;&nbsp;p?</span></div></li>
+<li><div class="src-line"><a name="a4550"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$list&nbsp;</span>=&nbsp;<a href="http://www.php.net/preg_replace">preg_replace</a><span class="src-sym">(</span><span class="src-str">'#\(\?\:(.)\)\?#'</span><span class="src-sym">,&nbsp;</span><span class="src-str">'\1?'</span><span class="src-sym">,&nbsp;</span><span class="src-var">$list</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4551"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;(?:a|b|c|d|...)?&nbsp;=&gt;&nbsp;[abcd...]?</span></div></li>
+<li><div class="src-line"><a name="a4552"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;TODO:&nbsp;a|bb|c&nbsp;=&gt;&nbsp;[ac]|bb</span></div></li>
+<li><div class="src-line"><a name="a4553"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">static&nbsp;</span><span class="src-var">$callback_2</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4554"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-sym">!</span>isset<span class="src-sym">(</span><span class="src-var">$callback_2</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4555"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$callback_2&nbsp;</span>=&nbsp;<a href="http://www.php.net/create_function">create_function</a><span class="src-sym">(</span><span class="src-str">'$matches'</span><span class="src-sym">,&nbsp;</span><span class="src-str">'return&nbsp;&quot;[&quot;&nbsp;.&nbsp;str_replace(&quot;|&quot;,&nbsp;&quot;&quot;,&nbsp;$matches[1])&nbsp;.&nbsp;&quot;]&quot;;'</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4556"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4557"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$list&nbsp;</span>=&nbsp;<a href="http://www.php.net/preg_replace_callback">preg_replace_callback</a><span class="src-sym">(</span><span class="src-str">'#\(\?\:((?:.\|)+.)\)#'</span><span class="src-sym">,&nbsp;</span><span class="src-var">$callback_2</span><span class="src-sym">,&nbsp;</span><span class="src-var">$list</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4558"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4559"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-comm">//&nbsp;return&nbsp;$list&nbsp;without&nbsp;trailing&nbsp;pipe</span></div></li>
+<li><div class="src-line"><a name="a4560"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return&nbsp;</span><a href="http://www.php.net/substr">substr</a><span class="src-sym">(</span><span class="src-var">$list</span><span class="src-sym">,&nbsp;</span><span class="src-num">0</span><span class="src-sym">,&nbsp;</span>-<span class="src-num">1</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4561"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4562"></a><span class="src-sym">}&nbsp;</span><span class="src-comm">//&nbsp;End&nbsp;Class&nbsp;GeSHi</span></div></li>
+<li><div class="src-line"><a name="a4563"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4564"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4565"></a><span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-sym">!</span><a href="http://www.php.net/function_exists">function_exists</a><span class="src-sym">(</span><span class="src-str">'geshi_highlight'</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4566"></a>&nbsp;&nbsp;&nbsp;&nbsp;/**</div></li>
+<li><div class="src-line"><a name="a4567"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Easy&nbsp;way&nbsp;to&nbsp;highlight&nbsp;stuff.&nbsp;Behaves&nbsp;just&nbsp;like&nbsp;highlight_string</div></li>
+<li><div class="src-line"><a name="a4568"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</div></li>
+<li><div class="src-line"><a name="a4569"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;string&nbsp;The&nbsp;code&nbsp;to&nbsp;highlight</div></li>
+<li><div class="src-line"><a name="a4570"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;string&nbsp;The&nbsp;language&nbsp;to&nbsp;highlight&nbsp;the&nbsp;code&nbsp;in</div></li>
+<li><div class="src-line"><a name="a4571"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;string&nbsp;The&nbsp;path&nbsp;to&nbsp;the&nbsp;language&nbsp;files.&nbsp;You&nbsp;can&nbsp;leave&nbsp;this&nbsp;blank&nbsp;if&nbsp;you&nbsp;need</div></li>
+<li><div class="src-line"><a name="a4572"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;as&nbsp;from&nbsp;version&nbsp;1.0.7&nbsp;the&nbsp;path&nbsp;should&nbsp;be&nbsp;automatically&nbsp;detected</div></li>
+<li><div class="src-line"><a name="a4573"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;boolean&nbsp;Whether&nbsp;to&nbsp;return&nbsp;the&nbsp;result&nbsp;or&nbsp;to&nbsp;echo</div></li>
+<li><div class="src-line"><a name="a4574"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;string&nbsp;The&nbsp;code&nbsp;highlighted&nbsp;(if&nbsp;$return&nbsp;is&nbsp;true)</div></li>
+<li><div class="src-line"><a name="a4575"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@since&nbsp;1.0.2</div></li>
+<li><div class="src-line"><a name="a4576"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</div></li>
+<li><div class="src-line"><a name="a4577"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">function&nbsp;</span><a href="../geshi/core/_geshi.php.html#functiongeshi_highlight">geshi_highlight</a><span class="src-sym">(</span><span class="src-var">$string</span><span class="src-sym">,&nbsp;</span><span class="src-var">$language</span><span class="src-sym">,&nbsp;</span><span class="src-var">$path&nbsp;</span>=&nbsp;<span class="src-id">null</span><span class="src-sym">,&nbsp;</span><span class="src-var">$return&nbsp;</span>=&nbsp;<span class="src-id">false</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4578"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$geshi&nbsp;</span>=&nbsp;<span class="src-key">new&nbsp;</span><a href="../geshi/core/GeSHi.html#methodGeSHi">GeSHi</a><span class="src-sym">(</span><span class="src-var">$string</span><span class="src-sym">,&nbsp;</span><span class="src-var">$language</span><span class="src-sym">,&nbsp;</span><span class="src-var">$path</span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4579"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-var">$geshi</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodset_header_type">set_header_type</a><span class="src-sym">(</span><span class="src-id"><a href="../geshi/core/_geshi.php.html#defineGESHI_HEADER_NONE">GESHI_HEADER_NONE</a></span><span class="src-sym">)</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4580"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4581"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$return</span><span class="src-sym">)&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4582"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return&nbsp;</span><span class="src-str">'&lt;code&gt;'&nbsp;</span>.&nbsp;<span class="src-var">$geshi</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodparse_code">parse_code</a><span class="src-sym">(</span><span class="src-sym">)&nbsp;</span>.&nbsp;<span class="src-str">'&lt;/code&gt;'</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4583"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4584"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4585"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;<span class="src-str">'&lt;code&gt;'&nbsp;</span>.&nbsp;<span class="src-var">$geshi</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methodparse_code">parse_code</a><span class="src-sym">(</span><span class="src-sym">)&nbsp;</span>.&nbsp;<span class="src-str">'&lt;/code&gt;'</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4586"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4587"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">if&nbsp;</span><span class="src-sym">(</span><span class="src-var">$geshi</span><span class="src-sym">-&gt;</span><a href="../geshi/core/GeSHi.html#methoderror">error</a><span class="src-sym">(</span><span class="src-sym">))&nbsp;</span><span class="src-sym">{</span></div></li>
+<li><div class="src-line"><a name="a4588"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return&nbsp;</span><span class="src-id">false</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4589"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4590"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-key">return&nbsp;</span><span class="src-id">true</span><span class="src-sym">;</span></div></li>
+<li><div class="src-line"><a name="a4591"></a>&nbsp;&nbsp;&nbsp;&nbsp;<span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4592"></a><span class="src-sym">}</span></div></li>
+<li><div class="src-line"><a name="a4593"></a>&nbsp;</div></li>
+<li><div class="src-line"><a name="a4594"></a><span class="src-php">?&gt;</span></div></li>
+</ol></div>
+</div>
+       <p class="notes" id="credit">
+               Documentation generated on Thu, 25 Dec 2008 14:34:52 +0100 by <a href="http://www.phpdoc.org" target="_blank">phpDocumentor 1.4.2</a>
+       </p>
+       </body>
+</html>
\ No newline at end of file
diff --git a/examples/includes/geshi/docs/api/blank.html b/examples/includes/geshi/docs/api/blank.html
new file mode 100644 (file)
index 0000000..d44ac46
--- /dev/null
@@ -0,0 +1,13 @@
+<html>
+<head>
+       <title>GeSHi 1.0.8</title>
+                       <link rel="stylesheet" href="media/stylesheet.css" />
+                       <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
+</head>
+<body>
+<div align="center"><h1>GeSHi 1.0.8</h1></div>
+<b>Welcome to geshi!</b><br />
+<br />
+This documentation was generated by <a href="http://www.phpdoc.org">phpDocumentor v1.4.2</a><br />
+</body>
+</html>
\ No newline at end of file
diff --git a/examples/includes/geshi/docs/api/classtrees_geshi.html b/examples/includes/geshi/docs/api/classtrees_geshi.html
new file mode 100644 (file)
index 0000000..e5c3868
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+  <html xmlns="http://www.w3.org/1999/xhtml">
+               <head>
+                       <!-- template designed by Marco Von Ballmoos -->
+                       <title></title>
+                       <link rel="stylesheet" href="media/stylesheet.css" />
+                       <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
+               </head>
+               <body>
+                                               
+<!-- Start of Class Data -->
+<H2>
+       
+</H2>
+<h2>Root class GeSHi</h2>
+<ul>
+<li><a href="geshi/core/GeSHi.html">GeSHi</a></li></ul>
+
+       <p class="notes" id="credit">
+               Documentation generated on Thu, 25 Dec 2008 14:34:34 +0100 by <a href="http://www.phpdoc.org" target="_blank">phpDocumentor 1.4.2</a>
+       </p>
+       </body>
+</html>
\ No newline at end of file
diff --git a/examples/includes/geshi/docs/api/elementindex.html b/examples/includes/geshi/docs/api/elementindex.html
new file mode 100644 (file)
index 0000000..970ebd1
--- /dev/null
@@ -0,0 +1,867 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+  <html xmlns="http://www.w3.org/1999/xhtml">
+               <head>
+                       <!-- template designed by Marco Von Ballmoos -->
+                       <title></title>
+                       <link rel="stylesheet" href="media/stylesheet.css" />
+                       <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
+               </head>
+               <body>
+                                               <a name="top"></a>
+<h2>Full index</h2>
+<h3>Package indexes</h3>
+<ul>
+       <li><a href="elementindex_geshi.html">geshi</a></li>
+</ul>
+<br />
+<div class="index-letter-menu">
+       <a class="index-letter" href="elementindex.html#a">a</a>
+       <a class="index-letter" href="elementindex.html#d">d</a>
+       <a class="index-letter" href="elementindex.html#e">e</a>
+       <a class="index-letter" href="elementindex.html#g">g</a>
+       <a class="index-letter" href="elementindex.html#h">h</a>
+       <a class="index-letter" href="elementindex.html#l">l</a>
+       <a class="index-letter" href="elementindex.html#o">o</a>
+       <a class="index-letter" href="elementindex.html#p">p</a>
+       <a class="index-letter" href="elementindex.html#r">r</a>
+       <a class="index-letter" href="elementindex.html#s">s</a>
+</div>
+
+       <a name="a"></a>
+       <div class="index-letter-section">
+               <div style="float: left" class="index-letter-title">a</div>
+               <div style="float: right"><a href="#top">top</a></div>
+               <div style="clear: both"></div>
+       </div>
+       <dl>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">add_keyword</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodadd_keyword">GeSHi::add_keyword()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Adds a keyword to a keyword group for highlighting</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">add_keyword_group</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodadd_keyword_group">GeSHi::add_keyword_group()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Creates a new keyword group</div>
+                                       </dd>
+               </dl>
+       <a name="d"></a>
+       <div class="index-letter-section">
+               <div style="float: left" class="index-letter-title">d</div>
+               <div style="float: right"><a href="#top">top</a></div>
+               <div style="clear: both"></div>
+       </div>
+       <dl>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">disable_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methoddisable_highlighting">GeSHi::disable_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Disables all highlighting</div>
+                                       </dd>
+               </dl>
+       <a name="e"></a>
+       <div class="index-letter-section">
+               <div style="float: left" class="index-letter-title">e</div>
+               <div style="float: right"><a href="#top">top</a></div>
+               <div style="clear: both"></div>
+       </div>
+       <dl>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">enable_classes</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_classes">GeSHi::enable_classes()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets whether CSS classes should be used to highlight the source. Default  is off, calling this method with no arguments will turn it on</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">enable_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_highlighting">GeSHi::enable_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Enables all highlighting</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">enable_ids</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_ids">GeSHi::enable_ids()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Whether CSS IDs should be added to each line</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">enable_important_blocks</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_important_blocks">GeSHi::enable_important_blocks()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets whether context-important blocks are highlighted</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">enable_inner_code_block</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_inner_code_block">GeSHi::enable_inner_code_block()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets whether to force a surrounding block around  the highlighted code or not</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">enable_keyword_links</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_keyword_links">GeSHi::enable_keyword_links()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Turns linking of keywords on or off.</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">enable_line_numbers</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_line_numbers">GeSHi::enable_line_numbers()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets whether line numbers should be displayed.</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">enable_multiline_span</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_multiline_span">GeSHi::enable_multiline_span()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets wether spans and other HTML markup generated by GeSHi can  span over multiple lines or not. Defaults to true to reduce overhead.</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">enable_strict_mode</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_strict_mode">GeSHi::enable_strict_mode()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Enables/disables strict highlighting. Default is off, calling this  method without parameters will turn it on. See documentation  for more details on strict mode and where to use it.</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">error</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methoderror">GeSHi::error()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Returns an error message associated with the last GeSHi operation,  or false if no error has occured</div>
+                                       </dd>
+               </dl>
+       <a name="g"></a>
+       <div class="index-letter-section">
+               <div style="float: left" class="index-letter-title">g</div>
+               <div style="float: right"><a href="#top">top</a></div>
+               <div style="clear: both"></div>
+       </div>
+       <dl>
+                       <dt class="field">
+                                               <img src="media/images/Constructor.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">GeSHi</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodGeSHi">GeSHi::GeSHi()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Creates a new GeSHi object, with source and language</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Class.png" alt="Class" title="Class" /></title>
+                       GeSHi
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html">GeSHi</a> in geshi.php</div>
+                                                       <div class="index-item-description">The GeSHi Class.</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Page.png" alt="Page" title="Page" /></title>
+                       <span class="include-title">geshi.php</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html">geshi.php</a> in geshi.php</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_ACTIVE</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_ACTIVE">GESHI_ACTIVE</a> in geshi.php</div>
+                                                       <div class="index-item-description">Links in the source in the :active state</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_CAPS_LOWER</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_CAPS_LOWER">GESHI_CAPS_LOWER</a> in geshi.php</div>
+                                                       <div class="index-item-description">Leave keywords found as the case that they are</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_CAPS_NO_CHANGE</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_CAPS_NO_CHANGE">GESHI_CAPS_NO_CHANGE</a> in geshi.php</div>
+                                                       <div class="index-item-description">Lowercase keywords found</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_CAPS_UPPER</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_CAPS_UPPER">GESHI_CAPS_UPPER</a> in geshi.php</div>
+                                                       <div class="index-item-description">Uppercase keywords found</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_END_IMPORTANT</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_END_IMPORTANT">GESHI_END_IMPORTANT</a> in geshi.php</div>
+                                                       <div class="index-item-description">The ender for important parts of the source</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_FANCY_LINE_NUMBERS</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_FANCY_LINE_NUMBERS">GESHI_FANCY_LINE_NUMBERS</a> in geshi.php</div>
+                                                       <div class="index-item-description">Use fancy line numbers when building the result</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_HEADER_DIV</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HEADER_DIV">GESHI_HEADER_DIV</a> in geshi.php</div>
+                                                       <div class="index-item-description">Use a &quot;div&quot; to surround the source</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_HEADER_NONE</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HEADER_NONE">GESHI_HEADER_NONE</a> in geshi.php</div>
+                                                       <div class="index-item-description">Use nothing to surround the source</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_HEADER_PRE</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE">GESHI_HEADER_PRE</a> in geshi.php</div>
+                                                       <div class="index-item-description">Use a &quot;pre&quot; to surround the source</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_HEADER_PRE_TABLE</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_TABLE">GESHI_HEADER_PRE_TABLE</a> in geshi.php</div>
+                                                       <div class="index-item-description">Use a &quot;table&quot; to surround the source:</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_HEADER_PRE_VALID</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_VALID">GESHI_HEADER_PRE_VALID</a> in geshi.php</div>
+                                                       <div class="index-item-description">Use a pre to wrap lines when line numbers are enabled or to wrap the whole code.</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Function.png" alt="Function" title="Function" /></title>
+                       <span class="method-title">geshi_highlight</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#functiongeshi_highlight">geshi_highlight()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Easy way to highlight stuff. Behaves just like highlight_string</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_HOVER</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HOVER">GESHI_HOVER</a> in geshi.php</div>
+                                                       <div class="index-item-description">Links in the source in the :hover state</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_LANG_ROOT</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_LANG_ROOT">GESHI_LANG_ROOT</a> in geshi.php</div>
+                                                       <div class="index-item-description">The language file directory for GeSHi</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_LINK</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_LINK">GESHI_LINK</a> in geshi.php</div>
+                                                       <div class="index-item-description">Links in the source in the :link state</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_NORMAL_LINE_NUMBERS</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_NORMAL_LINE_NUMBERS">GESHI_NORMAL_LINE_NUMBERS</a> in geshi.php</div>
+                                                       <div class="index-item-description">Use normal line numbers when building the result</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_NO_LINE_NUMBERS</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_NO_LINE_NUMBERS">GESHI_NO_LINE_NUMBERS</a> in geshi.php</div>
+                                                       <div class="index-item-description">Use no line numbers when building the result</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_ROOT</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_ROOT">GESHI_ROOT</a> in geshi.php</div>
+                                                       <div class="index-item-description">The root directory for GeSHi</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_SECURITY_PARANOID</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_SECURITY_PARANOID">GESHI_SECURITY_PARANOID</a> in geshi.php</div>
+                                                       <div class="index-item-description">Tells GeSHi to be paranoid about security settings</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_START_IMPORTANT</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_START_IMPORTANT">GESHI_START_IMPORTANT</a> in geshi.php</div>
+                                                       <div class="index-item-description">The starter for important parts of the source</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_VERSION</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_VERSION">GESHI_VERSION</a> in geshi.php</div>
+                                                       <div class="index-item-description">The version of this GeSHi file</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_VISITED</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_VISITED">GESHI_VISITED</a> in geshi.php</div>
+                                                       <div class="index-item-description">Links in the source in the :visited state</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">get_language_name</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_language_name">GeSHi::get_language_name()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Gets a human-readable language name (thanks to Simon Patterson  for the idea :))</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">get_language_name_from_extension</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_language_name_from_extension">GeSHi::get_language_name_from_extension()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Given a file extension, this method returns either a valid geshi language  name, or the empty string if it couldn't be found</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">get_multiline_span</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_multiline_span">GeSHi::get_multiline_span()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Get current setting for multiline spans, see GeSHi-&gt;enable_multiline_span().</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">get_real_tab_width</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_real_tab_width">GeSHi::get_real_tab_width()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Returns the tab width to use, based on the current language and user  preference</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">get_stylesheet</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_stylesheet">GeSHi::get_stylesheet()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Returns a stylesheet for the highlighted code. If $economy mode  is true, we only return the stylesheet declarations that matter for  this code block instead of the whole thing</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">get_time</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_time">GeSHi::get_time()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Gets the time taken to parse the code</div>
+                                       </dd>
+               </dl>
+       <a name="h"></a>
+       <div class="index-letter-section">
+               <div style="float: left" class="index-letter-title">h</div>
+               <div style="float: right"><a href="#top">top</a></div>
+               <div style="clear: both"></div>
+       </div>
+       <dl>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">highlight_lines_extra</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodhighlight_lines_extra">GeSHi::highlight_lines_extra()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Specifies which lines to highlight extra</div>
+                                       </dd>
+               </dl>
+       <a name="l"></a>
+       <div class="index-letter-section">
+               <div style="float: left" class="index-letter-title">l</div>
+               <div style="float: right"><a href="#top">top</a></div>
+               <div style="clear: both"></div>
+       </div>
+       <dl>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">load_from_file</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodload_from_file">GeSHi::load_from_file()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Given a file name, this method loads its contents in, and attempts</div>
+                                       </dd>
+               </dl>
+       <a name="o"></a>
+       <div class="index-letter-section">
+               <div style="float: left" class="index-letter-title">o</div>
+               <div style="float: right"><a href="#top">top</a></div>
+               <div style="clear: both"></div>
+       </div>
+       <dl>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">optimize_keyword_group</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodoptimize_keyword_group">GeSHi::optimize_keyword_group()</a> in geshi.php</div>
+                                                       <div class="index-item-description">compile optimized regexp list for keyword group</div>
+                                       </dd>
+               </dl>
+       <a name="p"></a>
+       <div class="index-letter-section">
+               <div style="float: left" class="index-letter-title">p</div>
+               <div style="float: right"><a href="#top">top</a></div>
+               <div style="clear: both"></div>
+       </div>
+       <dl>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">parse_code</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodparse_code">GeSHi::parse_code()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Returns the code in $this-&gt;source, highlighted and surrounded by the  nessecary HTML.</div>
+                                       </dd>
+               </dl>
+       <a name="r"></a>
+       <div class="index-letter-section">
+               <div style="float: left" class="index-letter-title">r</div>
+               <div style="float: right"><a href="#top">top</a></div>
+               <div style="clear: both"></div>
+       </div>
+       <dl>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">remove_keyword</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodremove_keyword">GeSHi::remove_keyword()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Removes a keyword from a keyword group</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">remove_keyword_group</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodremove_keyword_group">GeSHi::remove_keyword_group()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Removes a keyword group</div>
+                                       </dd>
+               </dl>
+       <a name="s"></a>
+       <div class="index-letter-section">
+               <div style="float: left" class="index-letter-title">s</div>
+               <div style="float: right"><a href="#top">top</a></div>
+               <div style="clear: both"></div>
+       </div>
+       <dl>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_brackets_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_brackets_highlighting">GeSHi::set_brackets_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Turns highlighting on/off for brackets</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_brackets_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_brackets_style">GeSHi::set_brackets_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the styles for brackets. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_case_keywords</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_case_keywords">GeSHi::set_case_keywords()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the case that keywords should use when found. Use the constants:</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_case_sensitivity</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_case_sensitivity">GeSHi::set_case_sensitivity()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets whether a set of keywords are checked for in a case sensitive manner</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_code_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_code_style">GeSHi::set_code_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the style for the actual code. This should be a string</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_comments_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_comments_highlighting">GeSHi::set_comments_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Turns highlighting on/off for comment groups</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_comments_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_comments_style">GeSHi::set_comments_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the styles for comment groups.  If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_encoding</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_encoding">GeSHi::set_encoding()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the encoding used for htmlspecialchars(), for international  support.</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_escape_characters_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_escape_characters_highlighting">GeSHi::set_escape_characters_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Turns highlighting on/off for escaped characters</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_escape_characters_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_escape_characters_style">GeSHi::set_escape_characters_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the styles for escaped characters. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_footer_content</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_footer_content">GeSHi::set_footer_content()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the content of the footer block</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_footer_content_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_footer_content_style">GeSHi::set_footer_content_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the style for the footer content</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_header_content</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_header_content">GeSHi::set_header_content()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the content of the header block</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_header_content_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_header_content_style">GeSHi::set_header_content_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the style for the header content</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_header_type</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_header_type">GeSHi::set_header_type()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the type of header to be used.</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_highlight_lines_extra_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_highlight_lines_extra_style">GeSHi::set_highlight_lines_extra_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the style for extra-highlighted lines</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_important_styles</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_important_styles">GeSHi::set_important_styles()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets styles for important parts of the code</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_keyword_group_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_keyword_group_highlighting">GeSHi::set_keyword_group_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Turns highlighting on/off for a keyword group</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_keyword_group_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_keyword_group_style">GeSHi::set_keyword_group_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the style for a keyword group. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_language</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_language">GeSHi::set_language()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the language for this object</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_language_path</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_language_path">GeSHi::set_language_path()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the path to the directory containing the language files. Note  that this path is relative to the directory of the script that included  geshi.php, NOT geshi.php itself.</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_line_ending</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_line_ending">GeSHi::set_line_ending()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the line-ending</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_line_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_line_style">GeSHi::set_line_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the styles for the line numbers.</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_link_styles</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_link_styles">GeSHi::set_link_styles()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets styles for links in code</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_link_target</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_link_target">GeSHi::set_link_target()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the target for links in code</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_methods_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_methods_highlighting">GeSHi::set_methods_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Turns highlighting on/off for methods</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_methods_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_methods_style">GeSHi::set_methods_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the styles for methods. $key is a number that references the</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_numbers_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_numbers_highlighting">GeSHi::set_numbers_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Turns highlighting on/off for numbers</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_numbers_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_numbers_style">GeSHi::set_numbers_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the styles for numbers. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_overall_class</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_overall_class">GeSHi::set_overall_class()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the overall classname for this block of code. This  class can then be used in a stylesheet to style this object's  output</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_overall_id</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_overall_id">GeSHi::set_overall_id()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the overall id for this block of code. This id can then  be used in a stylesheet to style this object's output</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_overall_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_overall_style">GeSHi::set_overall_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the styles for the code that will be outputted  when this object is parsed. The style should be a  string of valid stylesheet declarations</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_regexps_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_regexps_highlighting">GeSHi::set_regexps_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Turns highlighting on/off for regexps</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_regexps_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_regexps_style">GeSHi::set_regexps_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the styles for regexps. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_source</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_source">GeSHi::set_source()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the source code for this object</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_strings_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_strings_highlighting">GeSHi::set_strings_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Turns highlighting on/off for strings</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_strings_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_strings_style">GeSHi::set_strings_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the styles for strings. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_symbols_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_symbols_highlighting">GeSHi::set_symbols_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Turns highlighting on/off for symbols</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_symbols_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_symbols_style">GeSHi::set_symbols_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the styles for symbols. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_tab_width</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_tab_width">GeSHi::set_tab_width()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets how many spaces a tab is substituted for</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_url_for_keyword_group</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_url_for_keyword_group">GeSHi::set_url_for_keyword_group()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the base URL to be used for keywords</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_use_language_tab_width</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_use_language_tab_width">GeSHi::set_use_language_tab_width()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets whether or not to use tab-stop width specifed by language</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">start_line_numbers_at</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodstart_line_numbers_at">GeSHi::start_line_numbers_at()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets what number line numbers should start at. Should  be a positive integer, and will be converted to one.</div>
+                                       </dd>
+               </dl>
+
+<div class="index-letter-menu">
+       <a class="index-letter" href="elementindex.html#a">a</a>
+       <a class="index-letter" href="elementindex.html#d">d</a>
+       <a class="index-letter" href="elementindex.html#e">e</a>
+       <a class="index-letter" href="elementindex.html#g">g</a>
+       <a class="index-letter" href="elementindex.html#h">h</a>
+       <a class="index-letter" href="elementindex.html#l">l</a>
+       <a class="index-letter" href="elementindex.html#o">o</a>
+       <a class="index-letter" href="elementindex.html#p">p</a>
+       <a class="index-letter" href="elementindex.html#r">r</a>
+       <a class="index-letter" href="elementindex.html#s">s</a>
+</div> </body>
+</html>
\ No newline at end of file
diff --git a/examples/includes/geshi/docs/api/elementindex_geshi.html b/examples/includes/geshi/docs/api/elementindex_geshi.html
new file mode 100644 (file)
index 0000000..f319396
--- /dev/null
@@ -0,0 +1,864 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+  <html xmlns="http://www.w3.org/1999/xhtml">
+               <head>
+                       <!-- template designed by Marco Von Ballmoos -->
+                       <title></title>
+                       <link rel="stylesheet" href="media/stylesheet.css" />
+                       <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
+               </head>
+               <body>
+                                               <a name="top"></a>
+<h2>[geshi] element index</h2>
+<a href="elementindex.html">All elements</a>
+<br />
+<div class="index-letter-menu">
+       <a class="index-letter" href="elementindex_geshi.html#a">a</a>
+       <a class="index-letter" href="elementindex_geshi.html#d">d</a>
+       <a class="index-letter" href="elementindex_geshi.html#e">e</a>
+       <a class="index-letter" href="elementindex_geshi.html#g">g</a>
+       <a class="index-letter" href="elementindex_geshi.html#h">h</a>
+       <a class="index-letter" href="elementindex_geshi.html#l">l</a>
+       <a class="index-letter" href="elementindex_geshi.html#o">o</a>
+       <a class="index-letter" href="elementindex_geshi.html#p">p</a>
+       <a class="index-letter" href="elementindex_geshi.html#r">r</a>
+       <a class="index-letter" href="elementindex_geshi.html#s">s</a>
+</div>
+
+       <a name="a"></a>
+       <div class="index-letter-section">
+               <div style="float: left" class="index-letter-title">a</div>
+               <div style="float: right"><a href="#top">top</a></div>
+               <div style="clear: both"></div>
+       </div>
+       <dl>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">add_keyword</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodadd_keyword">GeSHi::add_keyword()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Adds a keyword to a keyword group for highlighting</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">add_keyword_group</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodadd_keyword_group">GeSHi::add_keyword_group()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Creates a new keyword group</div>
+                                       </dd>
+               </dl>
+       <a name="d"></a>
+       <div class="index-letter-section">
+               <div style="float: left" class="index-letter-title">d</div>
+               <div style="float: right"><a href="#top">top</a></div>
+               <div style="clear: both"></div>
+       </div>
+       <dl>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">disable_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methoddisable_highlighting">GeSHi::disable_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Disables all highlighting</div>
+                                       </dd>
+               </dl>
+       <a name="e"></a>
+       <div class="index-letter-section">
+               <div style="float: left" class="index-letter-title">e</div>
+               <div style="float: right"><a href="#top">top</a></div>
+               <div style="clear: both"></div>
+       </div>
+       <dl>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">enable_classes</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_classes">GeSHi::enable_classes()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets whether CSS classes should be used to highlight the source. Default  is off, calling this method with no arguments will turn it on</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">enable_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_highlighting">GeSHi::enable_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Enables all highlighting</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">enable_ids</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_ids">GeSHi::enable_ids()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Whether CSS IDs should be added to each line</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">enable_important_blocks</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_important_blocks">GeSHi::enable_important_blocks()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets whether context-important blocks are highlighted</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">enable_inner_code_block</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_inner_code_block">GeSHi::enable_inner_code_block()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets whether to force a surrounding block around  the highlighted code or not</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">enable_keyword_links</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_keyword_links">GeSHi::enable_keyword_links()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Turns linking of keywords on or off.</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">enable_line_numbers</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_line_numbers">GeSHi::enable_line_numbers()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets whether line numbers should be displayed.</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">enable_multiline_span</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_multiline_span">GeSHi::enable_multiline_span()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets wether spans and other HTML markup generated by GeSHi can  span over multiple lines or not. Defaults to true to reduce overhead.</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">enable_strict_mode</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_strict_mode">GeSHi::enable_strict_mode()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Enables/disables strict highlighting. Default is off, calling this  method without parameters will turn it on. See documentation  for more details on strict mode and where to use it.</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">error</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methoderror">GeSHi::error()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Returns an error message associated with the last GeSHi operation,  or false if no error has occured</div>
+                                       </dd>
+               </dl>
+       <a name="g"></a>
+       <div class="index-letter-section">
+               <div style="float: left" class="index-letter-title">g</div>
+               <div style="float: right"><a href="#top">top</a></div>
+               <div style="clear: both"></div>
+       </div>
+       <dl>
+                       <dt class="field">
+                                               <img src="media/images/Constructor.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">GeSHi</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodGeSHi">GeSHi::GeSHi()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Creates a new GeSHi object, with source and language</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Class.png" alt="Class" title="Class" /></title>
+                       GeSHi
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html">GeSHi</a> in geshi.php</div>
+                                                       <div class="index-item-description">The GeSHi Class.</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Page.png" alt="Page" title="Page" /></title>
+                       <span class="include-title">geshi.php</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html">geshi.php</a> in geshi.php</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_ACTIVE</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_ACTIVE">GESHI_ACTIVE</a> in geshi.php</div>
+                                                       <div class="index-item-description">Links in the source in the :active state</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_CAPS_LOWER</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_CAPS_LOWER">GESHI_CAPS_LOWER</a> in geshi.php</div>
+                                                       <div class="index-item-description">Leave keywords found as the case that they are</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_CAPS_NO_CHANGE</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_CAPS_NO_CHANGE">GESHI_CAPS_NO_CHANGE</a> in geshi.php</div>
+                                                       <div class="index-item-description">Lowercase keywords found</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_CAPS_UPPER</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_CAPS_UPPER">GESHI_CAPS_UPPER</a> in geshi.php</div>
+                                                       <div class="index-item-description">Uppercase keywords found</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_END_IMPORTANT</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_END_IMPORTANT">GESHI_END_IMPORTANT</a> in geshi.php</div>
+                                                       <div class="index-item-description">The ender for important parts of the source</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_FANCY_LINE_NUMBERS</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_FANCY_LINE_NUMBERS">GESHI_FANCY_LINE_NUMBERS</a> in geshi.php</div>
+                                                       <div class="index-item-description">Use fancy line numbers when building the result</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_HEADER_DIV</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HEADER_DIV">GESHI_HEADER_DIV</a> in geshi.php</div>
+                                                       <div class="index-item-description">Use a &quot;div&quot; to surround the source</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_HEADER_NONE</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HEADER_NONE">GESHI_HEADER_NONE</a> in geshi.php</div>
+                                                       <div class="index-item-description">Use nothing to surround the source</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_HEADER_PRE</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE">GESHI_HEADER_PRE</a> in geshi.php</div>
+                                                       <div class="index-item-description">Use a &quot;pre&quot; to surround the source</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_HEADER_PRE_TABLE</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_TABLE">GESHI_HEADER_PRE_TABLE</a> in geshi.php</div>
+                                                       <div class="index-item-description">Use a &quot;table&quot; to surround the source:</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_HEADER_PRE_VALID</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_VALID">GESHI_HEADER_PRE_VALID</a> in geshi.php</div>
+                                                       <div class="index-item-description">Use a pre to wrap lines when line numbers are enabled or to wrap the whole code.</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Function.png" alt="Function" title="Function" /></title>
+                       <span class="method-title">geshi_highlight</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#functiongeshi_highlight">geshi_highlight()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Easy way to highlight stuff. Behaves just like highlight_string</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_HOVER</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HOVER">GESHI_HOVER</a> in geshi.php</div>
+                                                       <div class="index-item-description">Links in the source in the :hover state</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_LANG_ROOT</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_LANG_ROOT">GESHI_LANG_ROOT</a> in geshi.php</div>
+                                                       <div class="index-item-description">The language file directory for GeSHi</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_LINK</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_LINK">GESHI_LINK</a> in geshi.php</div>
+                                                       <div class="index-item-description">Links in the source in the :link state</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_NORMAL_LINE_NUMBERS</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_NORMAL_LINE_NUMBERS">GESHI_NORMAL_LINE_NUMBERS</a> in geshi.php</div>
+                                                       <div class="index-item-description">Use normal line numbers when building the result</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_NO_LINE_NUMBERS</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_NO_LINE_NUMBERS">GESHI_NO_LINE_NUMBERS</a> in geshi.php</div>
+                                                       <div class="index-item-description">Use no line numbers when building the result</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_ROOT</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_ROOT">GESHI_ROOT</a> in geshi.php</div>
+                                                       <div class="index-item-description">The root directory for GeSHi</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_SECURITY_PARANOID</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_SECURITY_PARANOID">GESHI_SECURITY_PARANOID</a> in geshi.php</div>
+                                                       <div class="index-item-description">Tells GeSHi to be paranoid about security settings</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_START_IMPORTANT</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_START_IMPORTANT">GESHI_START_IMPORTANT</a> in geshi.php</div>
+                                                       <div class="index-item-description">The starter for important parts of the source</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_VERSION</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_VERSION">GESHI_VERSION</a> in geshi.php</div>
+                                                       <div class="index-item-description">The version of this GeSHi file</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
+                       <span class="const-title">GESHI_VISITED</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_VISITED">GESHI_VISITED</a> in geshi.php</div>
+                                                       <div class="index-item-description">Links in the source in the :visited state</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">get_language_name</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_language_name">GeSHi::get_language_name()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Gets a human-readable language name (thanks to Simon Patterson  for the idea :))</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">get_language_name_from_extension</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_language_name_from_extension">GeSHi::get_language_name_from_extension()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Given a file extension, this method returns either a valid geshi language  name, or the empty string if it couldn't be found</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">get_multiline_span</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_multiline_span">GeSHi::get_multiline_span()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Get current setting for multiline spans, see GeSHi-&gt;enable_multiline_span().</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">get_real_tab_width</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_real_tab_width">GeSHi::get_real_tab_width()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Returns the tab width to use, based on the current language and user  preference</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">get_stylesheet</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_stylesheet">GeSHi::get_stylesheet()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Returns a stylesheet for the highlighted code. If $economy mode  is true, we only return the stylesheet declarations that matter for  this code block instead of the whole thing</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">get_time</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_time">GeSHi::get_time()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Gets the time taken to parse the code</div>
+                                       </dd>
+               </dl>
+       <a name="h"></a>
+       <div class="index-letter-section">
+               <div style="float: left" class="index-letter-title">h</div>
+               <div style="float: right"><a href="#top">top</a></div>
+               <div style="clear: both"></div>
+       </div>
+       <dl>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">highlight_lines_extra</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodhighlight_lines_extra">GeSHi::highlight_lines_extra()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Specifies which lines to highlight extra</div>
+                                       </dd>
+               </dl>
+       <a name="l"></a>
+       <div class="index-letter-section">
+               <div style="float: left" class="index-letter-title">l</div>
+               <div style="float: right"><a href="#top">top</a></div>
+               <div style="clear: both"></div>
+       </div>
+       <dl>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">load_from_file</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodload_from_file">GeSHi::load_from_file()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Given a file name, this method loads its contents in, and attempts</div>
+                                       </dd>
+               </dl>
+       <a name="o"></a>
+       <div class="index-letter-section">
+               <div style="float: left" class="index-letter-title">o</div>
+               <div style="float: right"><a href="#top">top</a></div>
+               <div style="clear: both"></div>
+       </div>
+       <dl>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">optimize_keyword_group</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodoptimize_keyword_group">GeSHi::optimize_keyword_group()</a> in geshi.php</div>
+                                                       <div class="index-item-description">compile optimized regexp list for keyword group</div>
+                                       </dd>
+               </dl>
+       <a name="p"></a>
+       <div class="index-letter-section">
+               <div style="float: left" class="index-letter-title">p</div>
+               <div style="float: right"><a href="#top">top</a></div>
+               <div style="clear: both"></div>
+       </div>
+       <dl>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">parse_code</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodparse_code">GeSHi::parse_code()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Returns the code in $this-&gt;source, highlighted and surrounded by the  nessecary HTML.</div>
+                                       </dd>
+               </dl>
+       <a name="r"></a>
+       <div class="index-letter-section">
+               <div style="float: left" class="index-letter-title">r</div>
+               <div style="float: right"><a href="#top">top</a></div>
+               <div style="clear: both"></div>
+       </div>
+       <dl>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">remove_keyword</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodremove_keyword">GeSHi::remove_keyword()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Removes a keyword from a keyword group</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">remove_keyword_group</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodremove_keyword_group">GeSHi::remove_keyword_group()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Removes a keyword group</div>
+                                       </dd>
+               </dl>
+       <a name="s"></a>
+       <div class="index-letter-section">
+               <div style="float: left" class="index-letter-title">s</div>
+               <div style="float: right"><a href="#top">top</a></div>
+               <div style="clear: both"></div>
+       </div>
+       <dl>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_brackets_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_brackets_highlighting">GeSHi::set_brackets_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Turns highlighting on/off for brackets</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_brackets_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_brackets_style">GeSHi::set_brackets_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the styles for brackets. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_case_keywords</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_case_keywords">GeSHi::set_case_keywords()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the case that keywords should use when found. Use the constants:</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_case_sensitivity</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_case_sensitivity">GeSHi::set_case_sensitivity()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets whether a set of keywords are checked for in a case sensitive manner</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_code_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_code_style">GeSHi::set_code_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the style for the actual code. This should be a string</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_comments_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_comments_highlighting">GeSHi::set_comments_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Turns highlighting on/off for comment groups</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_comments_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_comments_style">GeSHi::set_comments_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the styles for comment groups.  If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_encoding</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_encoding">GeSHi::set_encoding()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the encoding used for htmlspecialchars(), for international  support.</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_escape_characters_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_escape_characters_highlighting">GeSHi::set_escape_characters_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Turns highlighting on/off for escaped characters</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_escape_characters_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_escape_characters_style">GeSHi::set_escape_characters_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the styles for escaped characters. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_footer_content</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_footer_content">GeSHi::set_footer_content()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the content of the footer block</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_footer_content_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_footer_content_style">GeSHi::set_footer_content_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the style for the footer content</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_header_content</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_header_content">GeSHi::set_header_content()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the content of the header block</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_header_content_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_header_content_style">GeSHi::set_header_content_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the style for the header content</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_header_type</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_header_type">GeSHi::set_header_type()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the type of header to be used.</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_highlight_lines_extra_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_highlight_lines_extra_style">GeSHi::set_highlight_lines_extra_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the style for extra-highlighted lines</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_important_styles</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_important_styles">GeSHi::set_important_styles()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets styles for important parts of the code</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_keyword_group_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_keyword_group_highlighting">GeSHi::set_keyword_group_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Turns highlighting on/off for a keyword group</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_keyword_group_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_keyword_group_style">GeSHi::set_keyword_group_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the style for a keyword group. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_language</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_language">GeSHi::set_language()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the language for this object</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_language_path</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_language_path">GeSHi::set_language_path()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the path to the directory containing the language files. Note  that this path is relative to the directory of the script that included  geshi.php, NOT geshi.php itself.</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_line_ending</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_line_ending">GeSHi::set_line_ending()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the line-ending</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_line_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_line_style">GeSHi::set_line_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the styles for the line numbers.</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_link_styles</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_link_styles">GeSHi::set_link_styles()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets styles for links in code</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_link_target</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_link_target">GeSHi::set_link_target()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the target for links in code</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_methods_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_methods_highlighting">GeSHi::set_methods_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Turns highlighting on/off for methods</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_methods_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_methods_style">GeSHi::set_methods_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the styles for methods. $key is a number that references the</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_numbers_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_numbers_highlighting">GeSHi::set_numbers_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Turns highlighting on/off for numbers</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_numbers_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_numbers_style">GeSHi::set_numbers_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the styles for numbers. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_overall_class</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_overall_class">GeSHi::set_overall_class()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the overall classname for this block of code. This  class can then be used in a stylesheet to style this object's  output</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_overall_id</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_overall_id">GeSHi::set_overall_id()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the overall id for this block of code. This id can then  be used in a stylesheet to style this object's output</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_overall_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_overall_style">GeSHi::set_overall_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the styles for the code that will be outputted  when this object is parsed. The style should be a  string of valid stylesheet declarations</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_regexps_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_regexps_highlighting">GeSHi::set_regexps_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Turns highlighting on/off for regexps</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_regexps_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_regexps_style">GeSHi::set_regexps_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the styles for regexps. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_source</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_source">GeSHi::set_source()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the source code for this object</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_strings_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_strings_highlighting">GeSHi::set_strings_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Turns highlighting on/off for strings</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_strings_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_strings_style">GeSHi::set_strings_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the styles for strings. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_symbols_highlighting</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_symbols_highlighting">GeSHi::set_symbols_highlighting()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Turns highlighting on/off for symbols</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_symbols_style</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_symbols_style">GeSHi::set_symbols_style()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the styles for symbols. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_tab_width</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_tab_width">GeSHi::set_tab_width()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets how many spaces a tab is substituted for</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_url_for_keyword_group</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_url_for_keyword_group">GeSHi::set_url_for_keyword_group()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets the base URL to be used for keywords</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">set_use_language_tab_width</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_use_language_tab_width">GeSHi::set_use_language_tab_width()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets whether or not to use tab-stop width specifed by language</div>
+                                       </dd>
+                       <dt class="field">
+                                               <img src="media/images/Method.png" alt="Method" title="Method" /></title>
+                       <span class="method-title">start_line_numbers_at</span>
+                                       </dt>
+               <dd class="index-item-body">
+                       <div class="index-item-details"><a href="geshi/core/GeSHi.html#methodstart_line_numbers_at">GeSHi::start_line_numbers_at()</a> in geshi.php</div>
+                                                       <div class="index-item-description">Sets what number line numbers should start at. Should  be a positive integer, and will be converted to one.</div>
+                                       </dd>
+               </dl>
+
+<div class="index-letter-menu">
+       <a class="index-letter" href="elementindex_geshi.html#a">a</a>
+       <a class="index-letter" href="elementindex_geshi.html#d">d</a>
+       <a class="index-letter" href="elementindex_geshi.html#e">e</a>
+       <a class="index-letter" href="elementindex_geshi.html#g">g</a>
+       <a class="index-letter" href="elementindex_geshi.html#h">h</a>
+       <a class="index-letter" href="elementindex_geshi.html#l">l</a>
+       <a class="index-letter" href="elementindex_geshi.html#o">o</a>
+       <a class="index-letter" href="elementindex_geshi.html#p">p</a>
+       <a class="index-letter" href="elementindex_geshi.html#r">r</a>
+       <a class="index-letter" href="elementindex_geshi.html#s">s</a>
+</div> </body>
+</html>
\ No newline at end of file
diff --git a/examples/includes/geshi/docs/api/errors.html b/examples/includes/geshi/docs/api/errors.html
new file mode 100644 (file)
index 0000000..c917f03
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+  <html xmlns="http://www.w3.org/1999/xhtml">
+               <head>
+                       <!-- template designed by Marco Von Ballmoos -->
+                       <title>phpDocumentor Parser Errors and Warnings</title>
+                       <link rel="stylesheet" href="media/stylesheet.css" />
+                       <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
+               </head>
+               <body>
+                                               <a href="#Post-parsing">Post-parsing</a><br>
+<a name="geshi.php"></a>
+<h1>geshi.php</h1>
+<h2>Errors:</h2><br>
+<b>Error on line 569</b> - DocBlock has multiple @access tags, illegal. ignoring additional tag "@access private"<br>
+       <p class="notes" id="credit">
+               Documentation generated on Thu, 25 Dec 2008 14:34:53 +0100 by <a href="http://www.phpdoc.org" target="_blank">phpDocumentor 1.4.2</a>
+       </p>
+       </body>
+</html>
\ No newline at end of file
diff --git a/examples/includes/geshi/docs/api/geshi/core/GeSHi.html b/examples/includes/geshi/docs/api/geshi/core/GeSHi.html
new file mode 100644 (file)
index 0000000..a8ccc7d
--- /dev/null
@@ -0,0 +1,2676 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+  <html xmlns="http://www.w3.org/1999/xhtml">
+               <head>
+                       <!-- template designed by Marco Von Ballmoos -->
+                       <title>Docs For Class GeSHi</title>
+                       <link rel="stylesheet" href="../../media/stylesheet.css" />
+                       <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
+               </head>
+               <body>
+                       <div class="page-body">                 
+<h2 class="class-name"><img src="../../media/images/Class_logo.png"
+                                                                                                               alt=" Class"
+                                                                                                               title=" Class"
+                                                                                                               style="vertical-align: middle"> GeSHi</h2>
+
+<a name="sec-description"></a>
+<div class="info-box">
+       <div class="info-box-title">Description</div>
+       <div class="nav-bar">
+                                       <span class="disabled">Description</span> |
+                                                                                                                       <a href="#sec-method-summary">Methods</a> (<a href="#sec-methods">details</a>)
+                                               
+                                       </div>
+       <div class="info-box-body">
+                       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">The GeSHi Class.</p>
+<p class="description"><p>Please refer to the documentation for GeSHi 1.0.X that is available  at http://qbnz.com/highlighter/documentation.php for more information  about how to use this class.</p></p>
+       <ul class="tags">
+                               <li><span class="field">author:</span> Nigel McNie &lt;<a href="mailto:nigel@geshi.org">nigel@geshi.org</a>&gt;, Benny Baumann &lt;BenBE@omorphia.de&gt;</li>
+                               <li><span class="field">copyright:</span> (C) 2004 - 2007 Nigel McNie, (C) 2007 - 2008 Benny Baumann</li>
+                       </ul>
+               <p class="notes">
+                       Located in <a class="field" href="_geshi.php.html">/geshi.php</a> (line <span class="field"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a253">253</a></span>)
+               </p>
+               
+                               
+               <pre></pre>
+       
+                       </div>
+</div>
+
+
+
+
+       <a name="sec-method-summary"></a>
+       <div class="info-box">
+               <div class="info-box-title">Method Summary</span></div>
+               <div class="nav-bar">
+                       <a href="#sec-description">Description</a> |
+                                                                                               <span class="disabled">Methods</span> (<a href="#sec-methods">details</a>)
+               </div>
+               <div class="info-box-body">                     
+                       <div class="method-summary">
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Constructor.png" alt=" "/>
+                                                                                       <span class="method-result">GeSHi</span>
+                                                                               <a href="#GeSHi" title="details" class="method-name">GeSHi</a>
+                                                                                       ([<span class="var-type">string</span>&nbsp;<span class="var-name">$source</span> = <span class="var-default">''</span>], [<span class="var-type">string</span>&nbsp;<span class="var-name">$language</span> = <span class="var-default">''</span>], [<span class="var-type">string</span>&nbsp;<span class="var-name">$path</span> = <span class="var-default">''</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#add_keyword" title="details" class="method-name">add_keyword</a>
+                                                                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>, <span class="var-type">string</span>&nbsp;<span class="var-name">$word</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#add_keyword_group" title="details" class="method-name">add_keyword_group</a>
+                                                                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>, <span class="var-type">string</span>&nbsp;<span class="var-name">$styles</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$case_sensitive</span> = <span class="var-default">true</span>], [<span class="var-type">array</span>&nbsp;<span class="var-name">$words</span> = <span class="var-default">array()</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#disable_highlighting" title="details" class="method-name">disable_highlighting</a>
+                                                                               ()
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#enable_classes" title="details" class="method-name">enable_classes</a>
+                                                                                       ([<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span> = <span class="var-default">true</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#enable_highlighting" title="details" class="method-name">enable_highlighting</a>
+                                                                                       ([<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span> = <span class="var-default">true</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#enable_ids" title="details" class="method-name">enable_ids</a>
+                                                                                       ([<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span> = <span class="var-default">true</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#enable_important_blocks" title="details" class="method-name">enable_important_blocks</a>
+                                                                                       (<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#enable_inner_code_block" title="details" class="method-name">enable_inner_code_block</a>
+                                                                                       (<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#enable_keyword_links" title="details" class="method-name">enable_keyword_links</a>
+                                                                                       ([<span class="var-type">boolean</span>&nbsp;<span class="var-name">$enable</span> = <span class="var-default">true</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#enable_line_numbers" title="details" class="method-name">enable_line_numbers</a>
+                                                                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$flag</span>, [<span class="var-type">int</span>&nbsp;<span class="var-name">$nth_row</span> = <span class="var-default">5</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#enable_multiline_span" title="details" class="method-name">enable_multiline_span</a>
+                                                                                       (<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#enable_strict_mode" title="details" class="method-name">enable_strict_mode</a>
+                                                                                       ([<span class="var-type">boolean</span>&nbsp;<span class="var-name">$mode</span> = <span class="var-default">true</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">string|false</span>
+                                                                               <a href="#error" title="details" class="method-name">error</a>
+                                                                               ()
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">string</span>
+                                                                               <a href="#get_language_name" title="details" class="method-name">get_language_name</a>
+                                                                               ()
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#get_language_name_from_extension" title="details" class="method-name">get_language_name_from_extension</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$extension</span>, [<span class="var-type">array</span>&nbsp;<span class="var-name">$lookup</span> = <span class="var-default">array()</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">bool</span>
+                                                                               <a href="#get_multiline_span" title="details" class="method-name">get_multiline_span</a>
+                                                                               ()
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">int</span>
+                                                                               <a href="#get_real_tab_width" title="details" class="method-name">get_real_tab_width</a>
+                                                                               ()
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">string</span>
+                                                                               <a href="#get_stylesheet" title="details" class="method-name">get_stylesheet</a>
+                                                                                       ([<span class="var-type">boolean</span>&nbsp;<span class="var-name">$economy_mode</span> = <span class="var-default">true</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">double</span>
+                                                                               <a href="#get_time" title="details" class="method-name">get_time</a>
+                                                                               ()
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#highlight_lines_extra" title="details" class="method-name">highlight_lines_extra</a>
+                                                                                       (<span class="var-type">mixed</span>&nbsp;<span class="var-name">$lines</span>, [<span class="var-type">string</span>&nbsp;<span class="var-name">$style</span> = <span class="var-default">null</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#load_from_file" title="details" class="method-name">load_from_file</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$file_name</span>, [<span class="var-type">array</span>&nbsp;<span class="var-name">$lookup</span> = <span class="var-default">array()</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#optimize_keyword_group" title="details" class="method-name">optimize_keyword_group</a>
+                                                                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#parse_code" title="details" class="method-name">parse_code</a>
+                                                                               ()
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#remove_keyword" title="details" class="method-name">remove_keyword</a>
+                                                                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>, <span class="var-type">string</span>&nbsp;<span class="var-name">$word</span>, [<span class="var-type">bool</span>&nbsp;<span class="var-name">$recompile</span> = <span class="var-default">true</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#remove_keyword_group" title="details" class="method-name">remove_keyword_group</a>
+                                                                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_brackets_highlighting" title="details" class="method-name">set_brackets_highlighting</a>
+                                                                                       (<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_brackets_style" title="details" class="method-name">set_brackets_style</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_case_keywords" title="details" class="method-name">set_case_keywords</a>
+                                                                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$case</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_case_sensitivity" title="details" class="method-name">set_case_sensitivity</a>
+                                                                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>, <span class="var-type">boolean</span>&nbsp;<span class="var-name">$case</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_code_style" title="details" class="method-name">set_code_style</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_comments_highlighting" title="details" class="method-name">set_comments_highlighting</a>
+                                                                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span> = <span class="var-default">true</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_comments_style" title="details" class="method-name">set_comments_style</a>
+                                                                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>, <span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_encoding" title="details" class="method-name">set_encoding</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$encoding</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_escape_characters_highlighting" title="details" class="method-name">set_escape_characters_highlighting</a>
+                                                                                       ([<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span> = <span class="var-default">true</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_escape_characters_style" title="details" class="method-name">set_escape_characters_style</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_footer_content" title="details" class="method-name">set_footer_content</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$content</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_footer_content_style" title="details" class="method-name">set_footer_content_style</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_header_content" title="details" class="method-name">set_header_content</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$content</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_header_content_style" title="details" class="method-name">set_header_content_style</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_header_type" title="details" class="method-name">set_header_type</a>
+                                                                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$type</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_highlight_lines_extra_style" title="details" class="method-name">set_highlight_lines_extra_style</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$styles</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_important_styles" title="details" class="method-name">set_important_styles</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$styles</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_keyword_group_highlighting" title="details" class="method-name">set_keyword_group_highlighting</a>
+                                                                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span> = <span class="var-default">true</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_keyword_group_style" title="details" class="method-name">set_keyword_group_style</a>
+                                                                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>, <span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_language" title="details" class="method-name">set_language</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$language</span>, [<span class="var-type"></span>&nbsp;<span class="var-name">$force_reset</span> = <span class="var-default">false</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_language_path" title="details" class="method-name">set_language_path</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$path</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_line_ending" title="details" class="method-name">set_line_ending</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$line_ending</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_line_style" title="details" class="method-name">set_line_style</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$style1</span>, [<span class="var-type">string|boolean</span>&nbsp;<span class="var-name">$style2</span> = <span class="var-default">''</span>], [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_link_styles" title="details" class="method-name">set_link_styles</a>
+                                                                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$type</span>, <span class="var-type">string</span>&nbsp;<span class="var-name">$styles</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_link_target" title="details" class="method-name">set_link_target</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$target</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_methods_highlighting" title="details" class="method-name">set_methods_highlighting</a>
+                                                                                       (<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_methods_style" title="details" class="method-name">set_methods_style</a>
+                                                                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>, <span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_numbers_highlighting" title="details" class="method-name">set_numbers_highlighting</a>
+                                                                                       (<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_numbers_style" title="details" class="method-name">set_numbers_style</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_overall_class" title="details" class="method-name">set_overall_class</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$class</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_overall_id" title="details" class="method-name">set_overall_id</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$id</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_overall_style" title="details" class="method-name">set_overall_style</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_regexps_highlighting" title="details" class="method-name">set_regexps_highlighting</a>
+                                                                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>, <span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_regexps_style" title="details" class="method-name">set_regexps_style</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$key</span>, <span class="var-type">boolean</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type"></span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_source" title="details" class="method-name">set_source</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$source</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_strings_highlighting" title="details" class="method-name">set_strings_highlighting</a>
+                                                                                       (<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_strings_style" title="details" class="method-name">set_strings_style</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_symbols_highlighting" title="details" class="method-name">set_symbols_highlighting</a>
+                                                                                       (<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_symbols_style" title="details" class="method-name">set_symbols_style</a>
+                                                                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>], [<span class="var-type">int</span>&nbsp;<span class="var-name">$group</span> = <span class="var-default">0</span>])
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_tab_width" title="details" class="method-name">set_tab_width</a>
+                                                                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$width</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_url_for_keyword_group" title="details" class="method-name">set_url_for_keyword_group</a>
+                                                                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$group</span>, <span class="var-type">string</span>&nbsp;<span class="var-name">$url</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#set_use_language_tab_width" title="details" class="method-name">set_use_language_tab_width</a>
+                                                                                       (<span class="var-type">boolean</span>&nbsp;<span class="var-name">$use</span>)
+                                                                       </div>
+                                                                                                                               <div class="method-definition">
+                                       <img src="../../media/images/Method.png" alt=" "/>
+                                                                                       <span class="method-result">void</span>
+                                                                               <a href="#start_line_numbers_at" title="details" class="method-name">start_line_numbers_at</a>
+                                                                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$number</span>)
+                                                                       </div>
+                                                                                       </div>
+               </div>
+       </div>          
+
+       
+       <a name="sec-methods"></a>
+       <div class="info-box">
+               <div class="info-box-title">Methods</div>
+               <div class="nav-bar">
+                       <a href="#sec-description">Description</a> |
+                                                                                                       <a href="#sec-method-summary">Methods</a> (<span class="disabled">details</span>)
+                                               
+               </div>
+               <div class="info-box-body">
+                       <A NAME='method_detail'></A>
+<a name="methodGeSHi" id="GeSHi"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Constructor.png" />
+               <span class="method-title">Constructor GeSHi</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a591">591</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Creates a new GeSHi object, with source and language</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">GeSHi</span>
+               <span class="method-name">
+                       GeSHi
+               </span>
+                                       ([<span class="var-type">string</span>&nbsp;<span class="var-name">$source</span> = <span class="var-default">''</span>], [<span class="var-type">string</span>&nbsp;<span class="var-name">$language</span> = <span class="var-default">''</span>], [<span class="var-type">string</span>&nbsp;<span class="var-name">$path</span> = <span class="var-default">''</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$source</span><span class="var-description">: The source code to highlight</span>                        </li>
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$language</span><span class="var-description">: The language to highlight the source with</span>                 </li>
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$path</span><span class="var-description">: The path to the language file directory. <strong>This
+               is deprecated!</strong> I've backported the auto path                detection from the 1.1.X dev branch, so now it                should be automatically set correctly. If you have                renamed the language directory however, you will                still need to set the path using this parameter or                GeSHi->set_language_path()</span>                        </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodadd_keyword" id="add_keyword"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">add_keyword</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1441">1441</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Adds a keyword to a keyword group for highlighting</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       add_keyword
+               </span>
+                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>, <span class="var-type">string</span>&nbsp;<span class="var-name">$word</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$key</span><span class="var-description">: The key of the keyword group to add the keyword to</span>                     </li>
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$word</span><span class="var-description">: The word to add to the keyword group</span>                  </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodadd_keyword_group" id="add_keyword_group"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">add_keyword_group</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1487">1487</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Creates a new keyword group</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       add_keyword_group
+               </span>
+                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>, <span class="var-type">string</span>&nbsp;<span class="var-name">$styles</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$case_sensitive</span> = <span class="var-default">true</span>], [<span class="var-type">array</span>&nbsp;<span class="var-name">$words</span> = <span class="var-default">array()</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$key</span><span class="var-description">: The key of the keyword group to create</span>                 </li>
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$styles</span><span class="var-description">: The styles for the keyword group</span>                    </li>
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$case_sensitive</span><span class="var-description">: Whether the keyword group is case sensitive ornot</span>                   </li>
+                                       <li>
+                               <span class="var-type">array</span>
+                               <span class="var-name">$words</span><span class="var-description">: The words to use for the keyword group</span>                       </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methoddisable_highlighting" id="disable_highlighting"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">disable_highlighting</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1288">1288</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Disables all highlighting</p>
+       <ul class="tags">
+                               <li><span class="field">deprecated:</span> In favour of enable_highlighting</li>
+                               <li><span class="field">todo:</span> Rewrite with array traversal</li>
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       disable_highlighting
+               </span>
+                               ()
+                       </div>
+       
+               
+                       
+       </div>
+<a name="methodenable_classes" id="enable_classes"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">enable_classes</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a805">805</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets whether CSS classes should be used to highlight the source. Default  is off, calling this method with no arguments will turn it on</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       enable_classes
+               </span>
+                                       ([<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span> = <span class="var-default">true</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$flag</span><span class="var-description">: Whether to turn classes on or not</span>                     </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodenable_highlighting" id="enable_highlighting"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">enable_highlighting</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1302">1302</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Enables all highlighting</p>
+<p class="description"><p>The optional flag parameter was added in version 1.0.7.21 and can be used  to enable (true) or disable (false) all highlighting.</p></p>
+       <ul class="tags">
+                               <li><span class="field">todo:</span> Rewrite with array traversal</li>
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       enable_highlighting
+               </span>
+                                       ([<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span> = <span class="var-default">true</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$flag</span><span class="var-description">: A flag specifying whether to enable or disable all highlighting</span>                       </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodenable_ids" id="enable_ids"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">enable_ids</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1652">1652</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Whether CSS IDs should be added to each line</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.2</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       enable_ids
+               </span>
+                                       ([<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span> = <span class="var-default">true</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$flag</span><span class="var-description">: If true, IDs will be added to each line.</span>                      </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodenable_important_blocks" id="enable_important_blocks"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">enable_important_blocks</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1642">1642</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets whether context-important blocks are highlighted</p>
+       <ul class="tags">
+                               <li><span class="field">deprecated:</span> </li>
+                               <li><span class="field">todo:</span> REMOVE THIS SHIZ FROM GESHI!</li>
+                               <li><span class="field">since:</span> 1.0.2</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       enable_important_blocks
+               </span>
+                                       (<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$flag</span><span class="var-description">: Tells whether to enable or disable highlighting of important blocks</span>                   </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodenable_inner_code_block" id="enable_inner_code_block"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">enable_inner_code_block</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1581">1581</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets whether to force a surrounding block around  the highlighted code or not</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.7.20</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       enable_inner_code_block
+               </span>
+                                       (<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$flag</span><span class="var-description">: Tells whether to enable or disable this feature</span>                       </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodenable_keyword_links" id="enable_keyword_links"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">enable_keyword_links</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1756">1756</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Turns linking of keywords on or off.</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.2</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       enable_keyword_links
+               </span>
+                                       ([<span class="var-type">boolean</span>&nbsp;<span class="var-name">$enable</span> = <span class="var-default">true</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$enable</span><span class="var-description">: If true, links will be added to keywords</span>                    </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodenable_line_numbers" id="enable_line_numbers"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">enable_line_numbers</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a878">878</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets whether line numbers should be displayed.</p>
+<p class="description"><p>Valid values for the first parameter are:</p><p><ul><li>GESHI_NO_LINE_NUMBERS: Line numbers will not be displayed</li><li>GESHI_NORMAL_LINE_NUMBERS: Line numbers will be displayed</li><li>GESHI_FANCY_LINE_NUMBERS: Fancy line numbers will be displayed</li></ul>  For fancy line numbers, the second parameter is used to signal which lines  are to be fancy. For example, if the value of this parameter is 5 then every  5th line will be fancy.</p></p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       enable_line_numbers
+               </span>
+                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$flag</span>, [<span class="var-type">int</span>&nbsp;<span class="var-name">$nth_row</span> = <span class="var-default">5</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$flag</span><span class="var-description">: How line numbers should be displayed</span>                  </li>
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$nth_row</span><span class="var-description">: Defines which lines are fancy</span>                      </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodenable_multiline_span" id="enable_multiline_span"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">enable_multiline_span</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a896">896</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets wether spans and other HTML markup generated by GeSHi can  span over multiple lines or not. Defaults to true to reduce overhead.</p>
+<p class="description"><p>Set it to false if you want to manipulate the output or manually display  the code in an ordered list.</p></p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.7.22</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       enable_multiline_span
+               </span>
+                                       (<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$flag</span><span class="var-description">: Wether multiline spans are allowed or not</span>                     </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodenable_strict_mode" id="enable_strict_mode"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">enable_strict_mode</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1275">1275</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Enables/disables strict highlighting. Default is off, calling this  method without parameters will turn it on. See documentation  for more details on strict mode and where to use it.</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       enable_strict_mode
+               </span>
+                                       ([<span class="var-type">boolean</span>&nbsp;<span class="var-name">$mode</span> = <span class="var-default">true</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$mode</span><span class="var-description">: Whether to enable strict mode or not</span>                  </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methoderror" id="error"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">error</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a608">608</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Returns an error message associated with the last GeSHi operation,  or false if no error has occured</p>
+       <ul class="tags">
+                               <li><span class="field">return:</span> An error message if there has been an error, else false</li>
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">string|false</span>
+               <span class="method-name">
+                       error
+               </span>
+                               ()
+                       </div>
+       
+               
+                       
+       </div>
+<a name="methodget_language_name" id="get_language_name"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">get_language_name</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a632">632</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Gets a human-readable language name (thanks to Simon Patterson  for the idea :))</p>
+       <ul class="tags">
+                               <li><span class="field">return:</span> The name for the current language</li>
+                               <li><span class="field">since:</span> 1.0.2</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">string</span>
+               <span class="method-name">
+                       get_language_name
+               </span>
+                               ()
+                       </div>
+       
+               
+                       
+       </div>
+<a name="methodget_language_name_from_extension" id="get_language_name_from_extension"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">get_language_name_from_extension</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1329">1329</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Given a file extension, this method returns either a valid geshi language  name, or the empty string if it couldn't be found</p>
+       <ul class="tags">
+                               <li><span class="field">todo:</span> Re-think about how this method works (maybe make it private and/or make it        a extension-&gt;lang lookup?)</li>
+                               <li><span class="field">todo:</span> static?</li>
+                               <li><span class="field">since:</span> 1.0.5</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       get_language_name_from_extension
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$extension</span>, [<span class="var-type">array</span>&nbsp;<span class="var-name">$lookup</span> = <span class="var-default">array()</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$extension</span><span class="var-description">: The extension to get a language name for</span>                 </li>
+                                       <li>
+                               <span class="var-type">array</span>
+                               <span class="var-name">$lookup</span><span class="var-description">: A lookup array to use instead of the default one</span>                    </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodget_multiline_span" id="get_multiline_span"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">get_multiline_span</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a906">906</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Get current setting for multiline spans, see GeSHi-&gt;enable_multiline_span().</p>
+       <ul class="tags">
+                               <li><span class="field">see:</span> <a href="../../geshi/core/GeSHi.html#methodenable_multiline_span">GeSHi::enable_multiline_span()</a></li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">bool</span>
+               <span class="method-name">
+                       get_multiline_span
+               </span>
+                               ()
+                       </div>
+       
+               
+                       
+       </div>
+<a name="methodget_real_tab_width" id="get_real_tab_width"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">get_real_tab_width</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1258">1258</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Returns the tab width to use, based on the current language and user  preference</p>
+       <ul class="tags">
+                               <li><span class="field">return:</span> Tab width</li>
+                               <li><span class="field">since:</span> 1.0.7.20</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">int</span>
+               <span class="method-name">
+                       get_real_tab_width
+               </span>
+                               ()
+                       </div>
+       
+               
+                       
+       </div>
+<a name="methodget_stylesheet" id="get_stylesheet"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">get_stylesheet</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a4177">4177</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Returns a stylesheet for the highlighted code. If $economy mode  is true, we only return the stylesheet declarations that matter for  this code block instead of the whole thing</p>
+       <ul class="tags">
+                               <li><span class="field">return:</span> A stylesheet built on the data for the current language</li>
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">string</span>
+               <span class="method-name">
+                       get_stylesheet
+               </span>
+                                       ([<span class="var-type">boolean</span>&nbsp;<span class="var-name">$economy_mode</span> = <span class="var-default">true</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$economy_mode</span><span class="var-description">: Whether to use economy mode or not</span>                    </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodget_time" id="get_time"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">get_time</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a3524">3524</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Gets the time taken to parse the code</p>
+       <ul class="tags">
+                               <li><span class="field">return:</span> The time taken to parse the code</li>
+                               <li><span class="field">since:</span> 1.0.2</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">double</span>
+               <span class="method-name">
+                       get_time
+               </span>
+                               ()
+                       </div>
+       
+               
+                       
+       </div>
+<a name="methodhighlight_lines_extra" id="highlight_lines_extra"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">highlight_lines_extra</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1670">1670</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Specifies which lines to highlight extra</p>
+<p class="description"><p>The extra style parameter was added in 1.0.7.21.</p></p>
+       <ul class="tags">
+                               <li><span class="field">todo:</span> Some data replication here that could be cut down on</li>
+                               <li><span class="field">since:</span> 1.0.2</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       highlight_lines_extra
+               </span>
+                                       (<span class="var-type">mixed</span>&nbsp;<span class="var-name">$lines</span>, [<span class="var-type">string</span>&nbsp;<span class="var-name">$style</span> = <span class="var-default">null</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">mixed</span>
+                               <span class="var-name">$lines</span><span class="var-description">: An array of line numbers to highlight, or just a line               number on its own.</span>                       </li>
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$style</span><span class="var-description">: A string specifying the style to use for this line.               If null is specified, the default style is used.               If false is specified, the line will be removed from               special highlighting</span>                     </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodload_from_file" id="load_from_file"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">load_from_file</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1425">1425</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Given a file name, this method loads its contents in, and attempts</p>
+<p class="description"><p>to set the language automatically. An optional lookup table can be  passed for looking up the language name. If not specified a default  table is used</p><p>The language table is in the form  <pre>array(
+   'lang_name' => array('extension', 'extension', ...),
+   'lang_name' ...
+ );</pre></p></p>
+       <ul class="tags">
+                               <li><span class="field">todo:</span> Complete rethink of this and above method</li>
+                               <li><span class="field">since:</span> 1.0.5</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       load_from_file
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$file_name</span>, [<span class="var-type">array</span>&nbsp;<span class="var-name">$lookup</span> = <span class="var-default">array()</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$file_name</span><span class="var-description">: The filename to load the source from</span>                     </li>
+                                       <li>
+                               <span class="var-type">array</span>
+                               <span class="var-name">$lookup</span><span class="var-description">: A lookup array to use instead of the default one</span>                    </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodoptimize_keyword_group" id="optimize_keyword_group"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">optimize_keyword_group</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1529">1529</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">compile optimized regexp list for keyword group</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.8</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       optimize_keyword_group
+               </span>
+                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$key</span><span class="var-description">: The key of the keyword group to compile &amp; optimize</span>                 </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodparse_code" id="parse_code"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">parse_code</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1992">1992</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Returns the code in $this-&gt;source, highlighted and surrounded by the  nessecary HTML.</p>
+<p class="description"><p>This should only be called ONCE, cos it's SLOW! If you want to highlight  the same source multiple times, you're better off doing a whole lot of  str_replaces to replace the &amp;lt;span&amp;gt;s</p></p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       parse_code
+               </span>
+                               ()
+                       </div>
+       
+               
+                       
+       </div>
+<a name="methodremove_keyword" id="remove_keyword"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">remove_keyword</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1466">1466</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Removes a keyword from a keyword group</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       remove_keyword
+               </span>
+                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>, <span class="var-type">string</span>&nbsp;<span class="var-name">$word</span>, [<span class="var-type">bool</span>&nbsp;<span class="var-name">$recompile</span> = <span class="var-default">true</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$key</span><span class="var-description">: The key of the keyword group to remove the keyword from</span>                        </li>
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$word</span><span class="var-description">: The word to remove from the keyword group</span>                     </li>
+                                       <li>
+                               <span class="var-type">bool</span>
+                               <span class="var-name">$recompile</span><span class="var-description">: Wether to automatically recompile the optimized regexp list or not.                Note: if you set this to false and @see GeSHi-&gt;parse_code() was already called once,                for the current language, you have to manually call @see GeSHi-&gt;optimize_keyword_group()                or the removed keyword will stay in cache and still be highlighted! On the other hand                it might be too expensive to recompile the regexp list for every removal if you want to                remove a lot of keywords.</span>                       </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodremove_keyword_group" id="remove_keyword_group"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">remove_keyword_group</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1512">1512</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Removes a keyword group</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       remove_keyword_group
+               </span>
+                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$key</span><span class="var-description">: The key of the keyword group to remove</span>                 </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_brackets_highlighting" id="set_brackets_highlighting"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_brackets_highlighting</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1036">1036</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Turns highlighting on/off for brackets</p>
+<p class="description"><p>This method is DEPRECATED: use set_symbols_highlighting instead.  This method will be remove in 1.2.X</p></p>
+       <ul class="tags">
+                               <li><span class="field">deprecated:</span> In favour of set_symbols_highlighting</li>
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_brackets_highlighting
+               </span>
+                                       (<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$flag</span><span class="var-description">: Whether to turn highlighting for brackets on or off</span>                   </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_brackets_style" id="set_brackets_style"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_brackets_style</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1018">1018</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the styles for brackets. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</p>
+<p class="description"><p>This method is DEPRECATED: use set_symbols_style instead.  This method will be removed in 1.2.X</p></p>
+       <ul class="tags">
+                               <li><span class="field">deprecated:</span> In favour of set_symbols_style</li>
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_brackets_style
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$style</span><span class="var-description">: The style to make the brackets</span>                       </li>
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$preserve_defaults</span><span class="var-description">: Whether to merge the new styles with the old or just                 to overwrite them</span>                   </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_case_keywords" id="set_case_keywords"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_case_keywords</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1216">1216</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the case that keywords should use when found. Use the constants:</p>
+<p class="description"><p><ul><li>GESHI_CAPS_NO_CHANGE: leave keywords as-is</li><li>GESHI_CAPS_UPPER: convert all keywords to uppercase where found</li><li>GESHI_CAPS_LOWER: convert all keywords to lowercase where found</li></ul></p></p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.1</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_case_keywords
+               </span>
+                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$case</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$case</span><span class="var-description">: A constant specifying what to do with matched keywords</span>                        </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_case_sensitivity" id="set_case_sensitivity"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_case_sensitivity</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1202">1202</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets whether a set of keywords are checked for in a case sensitive manner</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_case_sensitivity
+               </span>
+                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>, <span class="var-type">boolean</span>&nbsp;<span class="var-name">$case</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$key</span><span class="var-description">: The key of the keyword group to change the case sensitivity of</span>                 </li>
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$case</span><span class="var-description">: Whether to check in a case sensitive manner or not</span>                    </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_code_style" id="set_code_style"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_code_style</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a824">824</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the style for the actual code. This should be a string</p>
+<p class="description"><p>containing valid stylesheet declarations. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</p><p>Note: Use this method to override any style changes you made to  the line numbers if you are using line numbers, else the line of  code will have the same style as the line number! Consult the  GeSHi documentation for more information about this.</p></p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.2</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_code_style
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$style</span><span class="var-description">: The style to use for actual code</span>                     </li>
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$preserve_defaults</span><span class="var-description">: Whether to merge the current styles with the new styles</span>                  </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_comments_highlighting" id="set_comments_highlighting"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_comments_highlighting</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a972">972</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Turns highlighting on/off for comment groups</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_comments_highlighting
+               </span>
+                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span> = <span class="var-default">true</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$key</span><span class="var-description">: The key of the comment group to turn on or off</span>                 </li>
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$flag</span><span class="var-description">: Whether to turn highlighting for that group on or off</span>                 </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_comments_style" id="set_comments_style"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_comments_style</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a957">957</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the styles for comment groups.  If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_comments_style
+               </span>
+                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>, <span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$key</span><span class="var-description">: The key of the comment group to change the styles of</span>                   </li>
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$style</span><span class="var-description">: The style to make the comments</span>                       </li>
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$preserve_defaults</span><span class="var-description">: Whether to merge the new styles with the old or just                 to overwrite them</span>                   </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_encoding" id="set_encoding"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_encoding</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1744">1744</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the encoding used for htmlspecialchars(), for international  support.</p>
+<p class="description"><p>NOTE: This is not needed for now because htmlspecialchars() is not  being used (it has a security hole in PHP4 that has not been patched).  Maybe in a future version it may make a return for speed reasons, but  I doubt it.</p></p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.3</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_encoding
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$encoding</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$encoding</span><span class="var-description">: The encoding to use for the source</span>                        </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_escape_characters_highlighting" id="set_escape_characters_highlighting"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_escape_characters_highlighting</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1000">1000</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Turns highlighting on/off for escaped characters</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_escape_characters_highlighting
+               </span>
+                                       ([<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span> = <span class="var-default">true</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$flag</span><span class="var-description">: Whether to turn highlighting for escape characters on or off</span>                  </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_escape_characters_style" id="set_escape_characters_style"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_escape_characters_style</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a986">986</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the styles for escaped characters. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_escape_characters_style
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$style</span><span class="var-description">: The style to make the escape characters</span>                      </li>
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$preserve_defaults</span><span class="var-description">: Whether to merge the new styles with the old or just                 to overwrite them</span>                   </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_footer_content" id="set_footer_content"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_footer_content</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1550">1550</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the content of the footer block</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.2</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_footer_content
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$content</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$content</span><span class="var-description">: The content of the footer block</span>                    </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_footer_content_style" id="set_footer_content_style"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_footer_content_style</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1570">1570</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the style for the footer content</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.2</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_footer_content_style
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$style</span><span class="var-description">: The style for the footer content</span>                     </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_header_content" id="set_header_content"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_header_content</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1540">1540</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the content of the header block</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.2</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_header_content
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$content</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$content</span><span class="var-description">: The content of the header block</span>                    </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_header_content_style" id="set_header_content_style"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_header_content_style</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1560">1560</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the style for the header content</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.2</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_header_content_style
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$style</span><span class="var-description">: The style for the header content</span>                     </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_header_type" id="set_header_type"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_header_type</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a746">746</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the type of header to be used.</p>
+<p class="description"><p>If GESHI_HEADER_DIV is used, the code is surrounded in a &quot;div&quot;.This  means more source code but more control over tab width and line-wrapping.  GESHI_HEADER_PRE means that a &quot;pre&quot; is used - less source, but less  control. Default is GESHI_HEADER_PRE.</p><p>From 1.0.7.2, you can use GESHI_HEADER_NONE to specify that no header code  should be outputted.</p></p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_header_type
+               </span>
+                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$type</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$type</span><span class="var-description">: The type of header to be used</span>                 </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_highlight_lines_extra_style" id="set_highlight_lines_extra_style"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_highlight_lines_extra_style</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1699">1699</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the style for extra-highlighted lines</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.2</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_highlight_lines_extra_style
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$styles</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$styles</span><span class="var-description">: The style for extra-highlighted lines</span>                       </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_important_styles" id="set_important_styles"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_important_styles</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1630">1630</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets styles for important parts of the code</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.2</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_important_styles
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$styles</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$styles</span><span class="var-description">: The styles to use on important parts of the code</span>                    </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_keyword_group_highlighting" id="set_keyword_group_highlighting"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_keyword_group_highlighting</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a942">942</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Turns highlighting on/off for a keyword group</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_keyword_group_highlighting
+               </span>
+                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span> = <span class="var-default">true</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$key</span><span class="var-description">: The key of the keyword group to turn on or off</span>                 </li>
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$flag</span><span class="var-description">: Whether to turn highlighting for that group on or off</span>                 </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_keyword_group_style" id="set_keyword_group_style"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_keyword_group_style</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a921">921</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the style for a keyword group. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_keyword_group_style
+               </span>
+                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>, <span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$key</span><span class="var-description">: The key of the keyword group to change the styles of</span>                   </li>
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$style</span><span class="var-description">: The style to make the keywords</span>                       </li>
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$preserve_defaults</span><span class="var-description">: Whether to merge the new styles with the old or just                 to overwrite them</span>                   </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_language" id="set_language"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_language</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a659">659</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the language for this object</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                               <li><span class="field">note:</span> since 1.0.8 this function won't reset language-settings by default anymore!        if you need this set $force_reset = true</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_language
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$language</span>, [<span class="var-type"></span>&nbsp;<span class="var-name">$force_reset</span> = <span class="var-default">false</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$language</span><span class="var-description">: The name of the language to use</span>                   </li>
+                                       <li>
+                               <span class="var-type"></span>
+                               <span class="var-name">$force_reset</span>                      </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_language_path" id="set_language_path"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_language_path</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a703">703</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the path to the directory containing the language files. Note  that this path is relative to the directory of the script that included  geshi.php, NOT geshi.php itself.</p>
+       <ul class="tags">
+                               <li><span class="field">deprecated:</span> The path to the language files should now be automatically              detected, so this method should no longer be needed. The              1.1.X branch handles manual setting of the path differently              so this method will disappear in 1.2.0.</li>
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_language_path
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$path</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$path</span><span class="var-description">: The path to the language directory</span>                    </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_line_ending" id="set_line_ending"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_line_ending</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1709">1709</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the line-ending</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.2</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_line_ending
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$line_ending</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$line_ending</span><span class="var-description">: The new line-ending</span>                    </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_line_style" id="set_line_style"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_line_style</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a844">844</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the styles for the line numbers.</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.2</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_line_style
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$style1</span>, [<span class="var-type">string|boolean</span>&nbsp;<span class="var-name">$style2</span> = <span class="var-default">''</span>], [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$style1</span><span class="var-description">: The style for the line numbers that are &quot;normal&quot;</span>                  </li>
+                                       <li>
+                               <span class="var-type">string|boolean</span>
+                               <span class="var-name">$style2</span><span class="var-description">: If a string, this is the style of the line         numbers that are &quot;fancy&quot;, otherwise if boolean then this         defines whether the normal styles should be merged with the         new normal styles or not</span>                  </li>
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$preserve_defaults</span><span class="var-description">: If set, is the flag for whether to merge the &quot;fancy&quot;         styles with the current styles or not</span>                     </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_link_styles" id="set_link_styles"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_link_styles</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1606">1606</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets styles for links in code</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.2</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_link_styles
+               </span>
+                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$type</span>, <span class="var-type">string</span>&nbsp;<span class="var-name">$styles</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$type</span><span class="var-description">: A constant that specifies what state the style is being             set for - e.g. :hover or :visited</span>                 </li>
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$styles</span><span class="var-description">: The styles to use for that state</span>                    </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_link_target" id="set_link_target"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_link_target</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1616">1616</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the target for links in code</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.3</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_link_target
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$target</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$target</span><span class="var-description">: The target for links in the code, e.g. _blank</span>                       </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_methods_highlighting" id="set_methods_highlighting"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_methods_highlighting</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1162">1162</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Turns highlighting on/off for methods</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_methods_highlighting
+               </span>
+                                       (<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$flag</span><span class="var-description">: Whether to turn highlighting for methods on or off</span>                    </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_methods_style" id="set_methods_style"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_methods_style</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1148">1148</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the styles for methods. $key is a number that references the</p>
+<p class="description"><p>appropriate &quot;object splitter&quot; - see the language file for the language  you are highlighting to get this number. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</p></p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_methods_style
+               </span>
+                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>, <span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$key</span><span class="var-description">: The key of the object splitter to change the styles of</span>                 </li>
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$style</span><span class="var-description">: The style to make the methods</span>                        </li>
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$preserve_defaults</span><span class="var-description">: Whether to merge the new styles with the old or just                 to overwrite them</span>                   </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_numbers_highlighting" id="set_numbers_highlighting"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_numbers_highlighting</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1131">1131</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Turns highlighting on/off for numbers</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_numbers_highlighting
+               </span>
+                                       (<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$flag</span><span class="var-description">: Whether to turn highlighting for numbers on or off</span>                    </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_numbers_style" id="set_numbers_style"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_numbers_style</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1117">1117</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the styles for numbers. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_numbers_style
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$style</span><span class="var-description">: The style to make the numbers</span>                        </li>
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$preserve_defaults</span><span class="var-description">: Whether to merge the new styles with the old or just                 to overwrite them</span>                   </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_overall_class" id="set_overall_class"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_overall_class</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a783">783</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the overall classname for this block of code. This  class can then be used in a stylesheet to style this object's  output</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_overall_class
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$class</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$class</span><span class="var-description">: The class name to use for this block of code</span>                 </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_overall_id" id="set_overall_id"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_overall_id</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a794">794</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the overall id for this block of code. This id can then  be used in a stylesheet to style this object's output</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_overall_id
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$id</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$id</span><span class="var-description">: The ID to use for this block of code</span>                    </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_overall_style" id="set_overall_style"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_overall_style</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a767">767</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the styles for the code that will be outputted  when this object is parsed. The style should be a  string of valid stylesheet declarations</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_overall_style
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$style</span><span class="var-description">: The overall style for the outputted code block</span>                       </li>
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$preserve_defaults</span><span class="var-description">: Whether to merge the styles with the current styles or not</span>                       </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_regexps_highlighting" id="set_regexps_highlighting"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_regexps_highlighting</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1191">1191</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Turns highlighting on/off for regexps</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_regexps_highlighting
+               </span>
+                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$key</span>, <span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$key</span><span class="var-description">: The key of the regular expression group to turn on or off</span>                      </li>
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$flag</span><span class="var-description">: Whether to turn highlighting for the regular expression group on or off</span>                       </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_regexps_style" id="set_regexps_style"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_regexps_style</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1176">1176</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the styles for regexps. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_regexps_style
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$key</span>, <span class="var-type">boolean</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type"></span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$key</span><span class="var-description">: The style to make the regular expression matches</span>                       </li>
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$style</span><span class="var-description">: Whether to merge the new styles with the old or just                 to overwrite them</span>                       </li>
+                                       <li>
+                               <span class="var-type"></span>
+                               <span class="var-name">$preserve_defaults</span>                        </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_source" id="set_source"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_source</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a645">645</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the source code for this object</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_source
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$source</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$source</span><span class="var-description">: The source code to highlight</span>                        </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_strings_highlighting" id="set_strings_highlighting"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_strings_highlighting</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1103">1103</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Turns highlighting on/off for strings</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_strings_highlighting
+               </span>
+                                       (<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$flag</span><span class="var-description">: Whether to turn highlighting for strings on or off</span>                    </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_strings_style" id="set_strings_style"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_strings_style</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1089">1089</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the styles for strings. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_strings_style
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$style</span><span class="var-description">: The style to make the escape characters</span>                      </li>
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$preserve_defaults</span><span class="var-description">: Whether to merge the new styles with the old or just                 to overwrite them</span>                   </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_symbols_highlighting" id="set_symbols_highlighting"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_symbols_highlighting</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1071">1071</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Turns highlighting on/off for symbols</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_symbols_highlighting
+               </span>
+                                       (<span class="var-type">boolean</span>&nbsp;<span class="var-name">$flag</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$flag</span><span class="var-description">: Whether to turn highlighting for symbols on or off</span>                    </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_symbols_style" id="set_symbols_style"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_symbols_style</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1051">1051</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the styles for symbols. If $preserve_defaults is  true, then styles are merged with the default styles, with the  user defined styles having priority</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.1</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_symbols_style
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$style</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$preserve_defaults</span> = <span class="var-default">false</span>], [<span class="var-type">int</span>&nbsp;<span class="var-name">$group</span> = <span class="var-default">0</span>])
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$style</span><span class="var-description">: The style to make the symbols</span>                        </li>
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$preserve_defaults</span><span class="var-description">: Whether to merge the new styles with the old or just                 to overwrite them</span>                   </li>
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$group</span><span class="var-description">: Tells the group of symbols for which style should be set.</span>                    </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_tab_width" id="set_tab_width"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_tab_width</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1231">1231</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets how many spaces a tab is substituted for</p>
+<p class="description"><p>Widths below zero are ignored</p></p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.0</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_tab_width
+               </span>
+                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$width</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$width</span><span class="var-description">: The tab width</span>                        </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_url_for_keyword_group" id="set_url_for_keyword_group"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_url_for_keyword_group</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1594">1594</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets the base URL to be used for keywords</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.2</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_url_for_keyword_group
+               </span>
+                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$group</span>, <span class="var-type">string</span>&nbsp;<span class="var-name">$url</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$group</span><span class="var-description">: The key of the keyword group to set the URL for</span>                      </li>
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$url</span><span class="var-description">: The URL to set for the group. If {FNAME} is in                the url somewhere, it is replaced by the keyword                that the URL is being made for</span>                   </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodset_use_language_tab_width" id="set_use_language_tab_width"><!-- --></a>
+<div class="oddrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">set_use_language_tab_width</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1247">1247</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets whether or not to use tab-stop width specifed by language</p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.7.20</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       set_use_language_tab_width
+               </span>
+                                       (<span class="var-type">boolean</span>&nbsp;<span class="var-name">$use</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$use</span><span class="var-description">: Whether to use language-specific tab-stop widths</span>                       </li>
+                               </ul>
+               
+                       
+       </div>
+<a name="methodstart_line_numbers_at" id="start_line_numbers_at"><!-- --></a>
+<div class="evenrow">
+       
+       <div class="method-header">
+               <img src="../../media/images/Method.png" />
+               <span class="method-title">start_line_numbers_at</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a1728">1728</a></span>)
+       </div> 
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Sets what number line numbers should start at. Should  be a positive integer, and will be converted to one.</p>
+<p class="description"><p><strong>Warning:</strong> Using this method will add the &quot;start&quot;  attribute to the &amp;lt;ol&amp;gt; that is used for line numbering.  This is <strong>not</strong> valid XHTML strict, so if that's what you  care about then don't use this method. Firefox is getting  support for the CSS method of doing this in 1.1 and Opera  has support for the CSS method, but (of course) IE doesn't  so it's not worth doing it the CSS way yet.</p></p>
+       <ul class="tags">
+                               <li><span class="field">since:</span> 1.0.2</li>
+                       </ul>
+       
+       <div class="method-signature">
+               <span class="method-result">void</span>
+               <span class="method-name">
+                       start_line_numbers_at
+               </span>
+                                       (<span class="var-type">int</span>&nbsp;<span class="var-name">$number</span>)
+                       </div>
+       
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">int</span>
+                               <span class="var-name">$number</span><span class="var-description">: The number to start line numbers at</span>                 </li>
+                               </ul>
+               
+                       
+       </div>
+                                               
+               </div>
+       </div>
+
+       
+       <p class="notes" id="credit">
+               Documentation generated on Thu, 25 Dec 2008 14:34:52 +0100 by <a href="http://www.phpdoc.org" target="_blank">phpDocumentor 1.4.2</a>
+       </p>
+       </div></body>
+</html>
\ No newline at end of file
diff --git a/examples/includes/geshi/docs/api/geshi/core/_geshi.php.html b/examples/includes/geshi/docs/api/geshi/core/_geshi.php.html
new file mode 100644 (file)
index 0000000..798f68f
--- /dev/null
@@ -0,0 +1,478 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+  <html xmlns="http://www.w3.org/1999/xhtml">
+               <head>
+                       <!-- template designed by Marco Von Ballmoos -->
+                       <title>Docs for page geshi.php</title>
+                       <link rel="stylesheet" href="../../media/stylesheet.css" />
+                       <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
+               </head>
+               <body>
+                       <div class="page-body">                 
+<h2 class="file-name"><img src="../../media/images/Page_logo.png" alt="File" style="vertical-align: middle">/geshi.php</h2>
+
+<a name="sec-description"></a>
+<div class="info-box">
+       <div class="info-box-title">Description</div>
+       <div class="nav-bar">
+                                       <span class="disabled">Description</span> |
+                                                       <a href="#sec-classes">Classes</a>
+                       |                                                                       <a href="#sec-constants">Constants</a>
+                       |                                                                       <a href="#sec-functions">Functions</a>
+                       </div>
+       <div class="info-box-body">     
+               <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">GeSHi - Generic Syntax Highlighter</p>
+<p class="description"><p>The GeSHi class for Generic Syntax Highlighting. Please refer to the  documentation at http://qbnz.com/highlighter/documentation.php for more  information about how to use this class.</p><p>For changes, release notes, TODOs etc, see the relevant files in the docs/  directory.</p><p>This file is part of GeSHi.</p><p>GeSHi 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.</p><p>GeSHi 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.</p><p>You should have received a copy of the GNU General Public License   along with GeSHi; if not, write to the Free Software   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA</p></p>
+       <ul class="tags">
+                               <li><span class="field">author:</span> Nigel McNie &lt;<a href="mailto:nigel@geshi.org">nigel@geshi.org</a>&gt;, Benny Baumann &lt;BenBE@omorphia.de&gt;</li>
+                               <li><span class="field">copyright:</span> (C) 2004 - 2007 Nigel McNie, (C) 2007 - 2008 Benny Baumann</li>
+                               <li><span class="field">filesource:</span> <a href="../../__filesource/fsource_geshi_core_geshi.php.html">Source Code for this file</a></li>
+                               <li><span class="field">license:</span> <a href="http://gnu.org/copyleft/gpl.html">GNU GPL</a></li>
+                       </ul>
+               
+                       </div>
+</div>
+               
+       <a name="sec-classes"></a>      
+       <div class="info-box">
+               <div class="info-box-title">Classes</div>
+               <div class="nav-bar">
+                       <a href="#sec-description">Description</a> |
+                       <span class="disabled">Classes</span>
+                       |                                                                               <a href="#sec-constants">Constants</a>
+                               |                                                                                                       <a href="#sec-functions">Functions</a>
+                                       </div>
+               <div class="info-box-body">     
+                       <table cellpadding="2" cellspacing="0" class="class-table">
+                               <tr>
+                                       <th class="class-table-header">Class</th>
+                                       <th class="class-table-header">Description</th>
+                               </tr>
+                                                               <tr>
+                                       <td style="padding-right: 2em; vertical-align: top; white-space: nowrap">
+                                               <img src="../../media/images/Class.png"
+                                                                alt=" class"
+                                                                title=" class"/>
+                                               <a href="../../geshi/core/GeSHi.html">GeSHi</a>
+                                       </td>
+                                       <td>
+                                                                                       The GeSHi Class.
+                                                                               </td>
+                               </tr>
+                                                       </table>
+               </div>
+       </div>
+
+       
+       <a name="sec-constants"></a>    
+       <div class="info-box">
+               <div class="info-box-title">Constants</div>
+               <div class="nav-bar">
+                       <a href="#sec-description">Description</a> |
+                                                       <a href="#sec-classes">Classes</a>
+                               |                                                                       <span class="disabled">Constants</span>
+                       |                                                                               <a href="#sec-functions">Functions</a>
+                                       </div>
+               <div class="info-box-body">     
+                       <a name="defineGESHI_ACTIVE"><!-- --></a>
+<div class="oddrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_ACTIVE</span> = 2
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a107">107</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Links in the source in the :active state</p>
+       
+               
+</div>
+<a name="defineGESHI_CAPS_LOWER"><!-- --></a>
+<div class="evenrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_CAPS_LOWER</span> = 2
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a99">99</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Leave keywords found as the case that they are</p>
+       
+               
+</div>
+<a name="defineGESHI_CAPS_NO_CHANGE"><!-- --></a>
+<div class="oddrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_CAPS_NO_CHANGE</span> = 0
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a95">95</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Lowercase keywords found</p>
+       
+               
+</div>
+<a name="defineGESHI_CAPS_UPPER"><!-- --></a>
+<div class="evenrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_CAPS_UPPER</span> = 1
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a97">97</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Uppercase keywords found</p>
+       
+               
+</div>
+<a name="defineGESHI_END_IMPORTANT"><!-- --></a>
+<div class="oddrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_END_IMPORTANT</span> = '&lt;END GeSHi&gt;'
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a117">117</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">The ender for important parts of the source</p>
+       
+               
+</div>
+<a name="defineGESHI_FANCY_LINE_NUMBERS"><!-- --></a>
+<div class="evenrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_FANCY_LINE_NUMBERS</span> = 2
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a67">67</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Use fancy line numbers when building the result</p>
+       
+               
+</div>
+<a name="defineGESHI_HEADER_DIV"><!-- --></a>
+<div class="oddrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_HEADER_DIV</span> = 1
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a73">73</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Use a &quot;div&quot; to surround the source</p>
+       
+               
+</div>
+<a name="defineGESHI_HEADER_NONE"><!-- --></a>
+<div class="evenrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_HEADER_NONE</span> = 0
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a71">71</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Use nothing to surround the source</p>
+       
+               
+</div>
+<a name="defineGESHI_HEADER_PRE"><!-- --></a>
+<div class="oddrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_HEADER_PRE</span> = 2
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a75">75</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Use a &quot;pre&quot; to surround the source</p>
+       
+               
+</div>
+<a name="defineGESHI_HEADER_PRE_TABLE"><!-- --></a>
+<div class="evenrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_HEADER_PRE_TABLE</span> = 4
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a91">91</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Use a &quot;table&quot; to surround the source:</p>
+<p class="description"><p>&lt;table&gt;     &lt;thead&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;$header&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;     &lt;tbody&gt;&lt;tr&gt;&lt;td&gt;<pre>$linenumbers</pre>&lt;/td&gt;&lt;td&gt;<pre>$code></pre>&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;     &lt;tfooter&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;$footer&lt;/td&gt;&lt;/tr&gt;&lt;/tfoot&gt;   &lt;/table&gt;</p><p>this is essentially only a workaround for Firefox, see sf#1651996 or take a look at  https://bugzilla.mozilla.org/show_bug.cgi?id=365805</p></p>
+       <ul class="tags">
+                               <li><span class="field">note:</span> when linenumbers are disabled this is essentially the same as GESHI_HEADER_PRE</li>
+                       </ul>
+       
+               
+</div>
+<a name="defineGESHI_HEADER_PRE_VALID"><!-- --></a>
+<div class="oddrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_HEADER_PRE_VALID</span> = 3
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a77">77</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Use a pre to wrap lines when line numbers are enabled or to wrap the whole code.</p>
+       
+               
+</div>
+<a name="defineGESHI_HOVER"><!-- --></a>
+<div class="evenrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_HOVER</span> = 1
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a105">105</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Links in the source in the :hover state</p>
+       
+               
+</div>
+<a name="defineGESHI_LANG_ROOT"><!-- --></a>
+<div class="oddrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_LANG_ROOT</span> = GESHI_ROOT.'geshi'.DIRECTORY_SEPARATOR
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a53">53</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">The language file directory for GeSHi</p>
+       
+               
+</div>
+<a name="defineGESHI_LINK"><!-- --></a>
+<div class="evenrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_LINK</span> = 0
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a103">103</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Links in the source in the :link state</p>
+       
+               
+</div>
+<a name="defineGESHI_NORMAL_LINE_NUMBERS"><!-- --></a>
+<div class="oddrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_NORMAL_LINE_NUMBERS</span> = 1
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a65">65</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Use normal line numbers when building the result</p>
+       
+               
+</div>
+<a name="defineGESHI_NO_LINE_NUMBERS"><!-- --></a>
+<div class="evenrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_NO_LINE_NUMBERS</span> = 0
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a63">63</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Use no line numbers when building the result</p>
+       
+               
+</div>
+<a name="defineGESHI_ROOT"><!-- --></a>
+<div class="oddrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_ROOT</span> = dirname(__FILE__).DIRECTORY_SEPARATOR
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a49">49</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">The root directory for GeSHi</p>
+       
+               
+</div>
+<a name="defineGESHI_SECURITY_PARANOID"><!-- --></a>
+<div class="evenrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_SECURITY_PARANOID</span> = false
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a58">58</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Tells GeSHi to be paranoid about security settings</p>
+       
+               
+</div>
+<a name="defineGESHI_START_IMPORTANT"><!-- --></a>
+<div class="oddrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_START_IMPORTANT</span> = '&lt;BEGIN GeSHi&gt;'
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a115">115</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">The starter for important parts of the source</p>
+       
+               
+</div>
+<a name="defineGESHI_VERSION"><!-- --></a>
+<div class="evenrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_VERSION</span> = '1.0.8.2',
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a44">44</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">The version of this GeSHi file</p>
+       
+               
+</div>
+<a name="defineGESHI_VISITED"><!-- --></a>
+<div class="oddrow">
+       
+       <div>
+               <img src="../../media/images/Constant.png" />
+               <span class="const-title">
+                       <span class="const-name">GESHI_VISITED</span> = 3
+                       (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a109">109</a></span>)
+               </span>
+       </div>
+       
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Links in the source in the :visited state</p>
+       
+               
+</div>
+               </div>
+       </div>
+       
+       
+       <a name="sec-functions"></a>    
+       <div class="info-box">
+               <div class="info-box-title">Functions</div>
+               <div class="nav-bar">
+                       <a href="#sec-description">Description</a> |
+                                                       <a href="#sec-classes">Classes</a>
+                               |                                                                                                       <a href="#sec-constants">Constants</a>
+                               |                                                                       <span class="disabled">Functions</span>
+               </div>
+               <div class="info-box-body">     
+                       <a name="functiongeshi_highlight" id="functiongeshi_highlight"><!-- --></a>
+<div class="evenrow">
+       
+       <div>
+               <img src="../../media/images/Function.png" />
+               <span class="method-title">geshi_highlight</span> (line <span class="line-number"><a href="../../__filesource/fsource_geshi_core_geshi.php.html#a4577">4577</a></span>)
+       </div> 
+
+       <!-- ========== Info from phpDoc block ========= -->
+<p class="short-description">Easy way to highlight stuff. Behaves just like highlight_string</p>
+       <ul class="tags">
+                               <li><span class="field">return:</span> The code highlighted (if $return is true)</li>
+                               <li><span class="field">since:</span> 1.0.2</li>
+                       </ul>
+       <div class="method-signature">
+               <span class="method-result">string</span>
+               <span class="method-name">
+                       geshi_highlight
+               </span>
+                                       (<span class="var-type">string</span>&nbsp;<span class="var-name">$string</span>, <span class="var-type">string</span>&nbsp;<span class="var-name">$language</span>, [<span class="var-type">string</span>&nbsp;<span class="var-name">$path</span> = <span class="var-default">null</span>], [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$return</span> = <span class="var-default">false</span>])
+                       </div>
+
+                       <ul class="parameters">
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$string</span><span class="var-description">: The code to highlight</span>                       </li>
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$language</span><span class="var-description">: The language to highlight the code in</span>                     </li>
+                                       <li>
+                               <span class="var-type">string</span>
+                               <span class="var-name">$path</span><span class="var-description">: The path to the language files. You can leave this blank if you need                as from version 1.0.7 the path should be automatically detected</span>                   </li>
+                                       <li>
+                               <span class="var-type">boolean</span>
+                               <span class="var-name">$return</span><span class="var-description">: Whether to return the result or to echo</span>                     </li>
+                               </ul>
+               
+       
+</div>
+               </div>
+       </div>
+       
+       <p class="notes" id="credit">
+               Documentation generated on Thu, 25 Dec 2008 14:34:34 +0100 by <a href="http://www.phpdoc.org" target="_blank">phpDocumentor 1.4.2</a>
+       </p>
+       </div></body>
+</html>
\ No newline at end of file
diff --git a/examples/includes/geshi/docs/api/index.html b/examples/includes/geshi/docs/api/index.html
new file mode 100644 (file)
index 0000000..f499a8f
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html 
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//FR"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
+   <html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+       <!-- Generated by phpDocumentor on Thu, 25 Dec 2008 14:34:34 +0100  -->
+  <title>GeSHi 1.0.8</title>
+  <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
+</head>
+
+<FRAMESET rows='120,*'>
+       <FRAME src='packages.html' name='left_top' frameborder="1" bordercolor="#999999">
+       <FRAMESET cols='25%,*'>
+               <FRAME src='li_geshi.html' name='left_bottom' frameborder="1" bordercolor="#999999">
+               <FRAME src='blank.html' name='right' frameborder="1" bordercolor="#999999">
+       </FRAMESET>
+       <NOFRAMES>
+               <H2>Frame Alert</H2>
+               <P>This document is designed to be viewed using the frames feature.
+               If you see this message, you are using a non-frame-capable web client.</P>
+       </NOFRAMES>
+</FRAMESET>
+</HTML>
\ No newline at end of file
diff --git a/examples/includes/geshi/docs/api/li_geshi.html b/examples/includes/geshi/docs/api/li_geshi.html
new file mode 100644 (file)
index 0000000..f074e37
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+  <html xmlns="http://www.w3.org/1999/xhtml">
+               <head>
+                       <!-- template designed by Marco Von Ballmoos -->
+                       <title></title>
+                       <link rel="stylesheet" href="media/stylesheet.css" />
+                       <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
+               </head>
+               <body>
+                                               <div class="package-title">geshi</div>
+<div class="package-details">
+                       
+       <dl class="tree">
+               
+               <dt class="folder-title">Description</dt>
+               <dd>
+                       <a href='classtrees_geshi.html' target='right'>Class trees</a><br />
+                       <a href='elementindex_geshi.html' target='right'>Index of elements</a><br />
+                                                       <a href="todolist.html" target="right">Todo List</a><br />
+                                       </dd>
+       
+                                                       
+                                                       
+                                                                                                                                                                                                                               
+                                               
+                                                       
+                                                                                       
+                               <dt class="sub-package"><img class="tree-icon" src="media/images/package.png" alt="Sub-package">core</dt>
+                               <dd>
+                                       <dl class="tree">
+                                                                                                                                                       <dt class="folder-title"><img class="tree-icon" src="media/images/class_folder.png" alt=" ">Classes</dt>
+                                                                                                                       <dd><img class="tree-icon" src="media/images/Class.png" alt="Class"><a href='geshi/core/GeSHi.html' target='right'>GeSHi</a></dd>
+                                                                                                                                                                                                               <dt class="folder-title"><img class="tree-icon" src="media/images/function_folder.png" alt=" ">Functions</dt>
+                                                                                                                       <dd><img class="tree-icon" src="media/images/Function.png" alt="Function"><a href='geshi/core/_geshi.php.html#functiongeshi_highlight' target='right'>geshi_highlight</a></dd>
+                                                                                                                                                                                                               <dt class="folder-title"><img class="tree-icon" src="media/images/folder.png" alt=" ">Files</dt>
+                                                                                                                       <dd><img class="tree-icon" src="media/images/Page.png" alt="File"><a href='geshi/core/_geshi.php.html' target='right'>geshi.php</a></dd>
+                                                                                                                                               </dl>
+                               </dd>
+                                                               
+                                               
+                       </dl>
+</div>
+<p class="notes"><a href="http://www.phpdoc.org" target="_blank">phpDocumentor v <span class="field">1.4.2</span></a></p>
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/examples/includes/geshi/docs/api/media/banner.css b/examples/includes/geshi/docs/api/media/banner.css
new file mode 100644 (file)
index 0000000..032b037
--- /dev/null
@@ -0,0 +1,33 @@
+body 
+{ 
+       background-color: #EEEEEE; 
+       margin: 0px; 
+       padding: 0px;
+}
+
+/* Banner (top bar) classes */
+
+.banner {  }
+
+.banner-menu 
+{
+       text-align: right;
+       clear: both;
+       padding: .5em;
+       border-top: 2px solid #AAAAAA;  
+}
+
+.banner-title 
+{ 
+       text-align: right; 
+       font-size: 20pt; 
+       font-weight: bold; 
+       margin: .2em;
+}
+
+.package-selector 
+{ 
+       background-color: #DDDDDD; 
+       border: 1px solid #AAAAAA; 
+       color: #000090;
+}
diff --git a/examples/includes/geshi/docs/api/media/images/AbstractClass.png b/examples/includes/geshi/docs/api/media/images/AbstractClass.png
new file mode 100644 (file)
index 0000000..afa9d1d
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/AbstractClass.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/AbstractClass_logo.png b/examples/includes/geshi/docs/api/media/images/AbstractClass_logo.png
new file mode 100644 (file)
index 0000000..8f65c39
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/AbstractClass_logo.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/AbstractMethod.png b/examples/includes/geshi/docs/api/media/images/AbstractMethod.png
new file mode 100644 (file)
index 0000000..605ccbe
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/AbstractMethod.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/AbstractPrivateClass.png b/examples/includes/geshi/docs/api/media/images/AbstractPrivateClass.png
new file mode 100644 (file)
index 0000000..53d76c6
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/AbstractPrivateClass.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/AbstractPrivateClass_logo.png b/examples/includes/geshi/docs/api/media/images/AbstractPrivateClass_logo.png
new file mode 100644 (file)
index 0000000..4e68f57
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/AbstractPrivateClass_logo.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/AbstractPrivateMethod.png b/examples/includes/geshi/docs/api/media/images/AbstractPrivateMethod.png
new file mode 100644 (file)
index 0000000..41cc9f0
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/AbstractPrivateMethod.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/Class.png b/examples/includes/geshi/docs/api/media/images/Class.png
new file mode 100644 (file)
index 0000000..cf548d2
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/Class.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/Class_logo.png b/examples/includes/geshi/docs/api/media/images/Class_logo.png
new file mode 100644 (file)
index 0000000..6f223c4
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/Class_logo.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/Constant.png b/examples/includes/geshi/docs/api/media/images/Constant.png
new file mode 100644 (file)
index 0000000..a9c6f28
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/Constant.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/Constructor.png b/examples/includes/geshi/docs/api/media/images/Constructor.png
new file mode 100644 (file)
index 0000000..3f16222
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/Constructor.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/Destructor.png b/examples/includes/geshi/docs/api/media/images/Destructor.png
new file mode 100644 (file)
index 0000000..f28528f
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/Destructor.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/Function.png b/examples/includes/geshi/docs/api/media/images/Function.png
new file mode 100644 (file)
index 0000000..902fe25
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/Function.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/Global.png b/examples/includes/geshi/docs/api/media/images/Global.png
new file mode 100644 (file)
index 0000000..7281bd2
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/Global.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/I.png b/examples/includes/geshi/docs/api/media/images/I.png
new file mode 100644 (file)
index 0000000..e8512fb
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/I.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/Index.png b/examples/includes/geshi/docs/api/media/images/Index.png
new file mode 100644 (file)
index 0000000..6558ec3
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/Index.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/Interface.png b/examples/includes/geshi/docs/api/media/images/Interface.png
new file mode 100644 (file)
index 0000000..e6cd51e
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/Interface.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/Interface_logo.png b/examples/includes/geshi/docs/api/media/images/Interface_logo.png
new file mode 100644 (file)
index 0000000..6f223c4
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/Interface_logo.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/L.png b/examples/includes/geshi/docs/api/media/images/L.png
new file mode 100644 (file)
index 0000000..eb334ed
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/L.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/Lminus.png b/examples/includes/geshi/docs/api/media/images/Lminus.png
new file mode 100644 (file)
index 0000000..f7c43c0
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/Lminus.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/Lplus.png b/examples/includes/geshi/docs/api/media/images/Lplus.png
new file mode 100644 (file)
index 0000000..848ec2f
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/Lplus.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/Method.png b/examples/includes/geshi/docs/api/media/images/Method.png
new file mode 100644 (file)
index 0000000..9b21578
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/Method.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/Page.png b/examples/includes/geshi/docs/api/media/images/Page.png
new file mode 100644 (file)
index 0000000..ffe7986
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/Page.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/Page_logo.png b/examples/includes/geshi/docs/api/media/images/Page_logo.png
new file mode 100644 (file)
index 0000000..44ce0b3
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/Page_logo.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/PrivateClass.png b/examples/includes/geshi/docs/api/media/images/PrivateClass.png
new file mode 100644 (file)
index 0000000..470e6d5
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/PrivateClass.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/PrivateClass_logo.png b/examples/includes/geshi/docs/api/media/images/PrivateClass_logo.png
new file mode 100644 (file)
index 0000000..590e006
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/PrivateClass_logo.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/PrivateMethod.png b/examples/includes/geshi/docs/api/media/images/PrivateMethod.png
new file mode 100644 (file)
index 0000000..d01f2b3
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/PrivateMethod.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/PrivateVariable.png b/examples/includes/geshi/docs/api/media/images/PrivateVariable.png
new file mode 100644 (file)
index 0000000..d76b21d
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/PrivateVariable.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/StaticMethod.png b/examples/includes/geshi/docs/api/media/images/StaticMethod.png
new file mode 100644 (file)
index 0000000..9b21578
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/StaticMethod.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/StaticVariable.png b/examples/includes/geshi/docs/api/media/images/StaticVariable.png
new file mode 100644 (file)
index 0000000..8e82019
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/StaticVariable.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/T.png b/examples/includes/geshi/docs/api/media/images/T.png
new file mode 100644 (file)
index 0000000..3017325
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/T.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/Tminus.png b/examples/includes/geshi/docs/api/media/images/Tminus.png
new file mode 100644 (file)
index 0000000..2260e42
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/Tminus.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/Tplus.png b/examples/includes/geshi/docs/api/media/images/Tplus.png
new file mode 100644 (file)
index 0000000..2c8d8f4
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/Tplus.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/Variable.png b/examples/includes/geshi/docs/api/media/images/Variable.png
new file mode 100644 (file)
index 0000000..8e82019
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/Variable.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/blank.png b/examples/includes/geshi/docs/api/media/images/blank.png
new file mode 100644 (file)
index 0000000..cee9cd3
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/blank.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/class_folder.png b/examples/includes/geshi/docs/api/media/images/class_folder.png
new file mode 100644 (file)
index 0000000..84e9587
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/class_folder.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/empty.png b/examples/includes/geshi/docs/api/media/images/empty.png
new file mode 100644 (file)
index 0000000..d568386
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/empty.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/file.png b/examples/includes/geshi/docs/api/media/images/file.png
new file mode 100644 (file)
index 0000000..0bb2427
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/file.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/folder.png b/examples/includes/geshi/docs/api/media/images/folder.png
new file mode 100644 (file)
index 0000000..a2d79f8
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/folder.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/function_folder.png b/examples/includes/geshi/docs/api/media/images/function_folder.png
new file mode 100644 (file)
index 0000000..8b3d6e3
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/function_folder.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/next_button.png b/examples/includes/geshi/docs/api/media/images/next_button.png
new file mode 100644 (file)
index 0000000..cdbc615
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/next_button.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/next_button_disabled.png b/examples/includes/geshi/docs/api/media/images/next_button_disabled.png
new file mode 100644 (file)
index 0000000..4a11780
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/next_button_disabled.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/package.png b/examples/includes/geshi/docs/api/media/images/package.png
new file mode 100644 (file)
index 0000000..b04cf56
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/package.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/package_folder.png b/examples/includes/geshi/docs/api/media/images/package_folder.png
new file mode 100644 (file)
index 0000000..6162baf
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/package_folder.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/previous_button.png b/examples/includes/geshi/docs/api/media/images/previous_button.png
new file mode 100644 (file)
index 0000000..327fdbc
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/previous_button.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/previous_button_disabled.png b/examples/includes/geshi/docs/api/media/images/previous_button_disabled.png
new file mode 100644 (file)
index 0000000..c02ff64
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/previous_button_disabled.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/private_class_logo.png b/examples/includes/geshi/docs/api/media/images/private_class_logo.png
new file mode 100644 (file)
index 0000000..590e006
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/private_class_logo.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/tutorial.png b/examples/includes/geshi/docs/api/media/images/tutorial.png
new file mode 100644 (file)
index 0000000..bc19737
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/tutorial.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/tutorial_folder.png b/examples/includes/geshi/docs/api/media/images/tutorial_folder.png
new file mode 100644 (file)
index 0000000..2a468b2
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/tutorial_folder.png differ
diff --git a/examples/includes/geshi/docs/api/media/images/up_button.png b/examples/includes/geshi/docs/api/media/images/up_button.png
new file mode 100644 (file)
index 0000000..ff36c59
Binary files /dev/null and b/examples/includes/geshi/docs/api/media/images/up_button.png differ
diff --git a/examples/includes/geshi/docs/api/media/stylesheet.css b/examples/includes/geshi/docs/api/media/stylesheet.css
new file mode 100644 (file)
index 0000000..ed3f0b2
--- /dev/null
@@ -0,0 +1,145 @@
+a { color: #000090; text-decoration: none; }
+a:hover, a:active, a:focus { color: highlighttext; background-color: highlight; text-decoration: none; }
+
+body { background: #FFFFFF; }
+body, table { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt; }
+
+a img { border: 0px; }
+
+/* Page layout/boxes */
+
+.info-box {  }
+.info-box-title { margin: 1em 0em 0em 0em; font-weight: normal; font-size: 14pt; color: #999999; border-bottom: 2px solid #999999; }
+.info-box-body { border: 1px solid #999999; padding: .5em; }
+.nav-bar { font-size: 8pt; white-space: nowrap; text-align: right; padding: .2em; margin: 0em 0em 1em 0em; }
+
+.oddrow { background-color: #F8F8F8; border: 1px solid #AAAAAA; padding: .5em; margin-bottom: 1em}
+.evenrow { border: 1px solid #AAAAAA; padding: .5em; margin-bottom: 1em}
+
+.page-body { max-width: 800px; margin: auto; }
+.tree { white-space: nowrap; font: icon }
+.tree dd { margin-left: 19px }
+.tree dl { margin: 0px }
+.tree-icon {   vertical-align: middle; border: 0px; margin-right: 3px }
+
+/* Index formatting classes */
+
+.index-item-body { margin-top: .5em; margin-bottom: .5em}
+.index-item-description { margin-top: .25em }
+.index-item-details { font-weight: normal; font-style: italic; font-size: 8pt }
+.index-letter-section { background-color: #EEEEEE; border: 1px dotted #999999; padding: .5em; margin-bottom: 1em}
+.index-letter-title { font-size: 12pt; font-weight: bold }
+.index-letter-menu { text-align: center; margin: 1em }
+.index-letter { font-size: 12pt }
+
+/* Docbook classes */
+
+.description {}
+.short-description { font-weight: bold; color: #666666; }
+.tags {        padding-left: 0em; margin-left: 3em; color: #666666; list-style-type: square; }
+.parameters {  padding-left: 0em; margin-left: 3em; color: #014fbe; list-style-type: square; }
+.redefinitions { font-size: 8pt; padding-left: 0em; margin-left: 2em; }
+.package { font-weight: bold; }
+.package-title { font-weight: bold; font-size: 14pt; border-bottom: 1px solid black }
+.package-details { font-size: 85%; }
+.sub-package { font-weight: bold; }
+.tutorial { border-width: thin; border-color: #0066ff; }
+.tutorial-nav-box { width: 100%; border: 1px solid #999999; background-color: #F8F8F8; }
+.folder-title { font-style: italic; font-family: Verdana, Arial, Helvetica, sans-serif }
+
+/* Generic formatting */
+
+.field { font-weight: bold; }
+.detail { font-size: 8pt; }
+.notes { font-style: italic; font-size: 8pt; }
+.separator { background-color: #999999; height: 2px; }
+.warning {  color: #FF6600; }
+.disabled { font-style: italic; color: #999999; }
+
+/* Code elements */
+
+.line-number {  }
+
+.class-table { width: 100%; }
+.class-table-header { border-bottom: 1px dotted #666666; text-align: left}
+.class-name { color: #0000AA; font-weight: bold; }
+
+.method-summary { color: #009000; padding-left: 1em; font-size: 8pt; }
+.method-header { }
+.method-definition { margin-bottom: .2em }
+.method-title { color: #009000; font-weight: bold; }
+.method-name { font-weight: bold; }
+.method-signature { font-size: 85%; color: #666666; margin: .5em 0em }
+.method-result { font-style: italic; }
+
+.var-summary { padding-left: 1em; font-size: 8pt; }
+.var-header { }
+.var-title { color: #014fbe; margin-bottom: .3em }
+.var-type { font-style: italic; }
+.var-name { font-weight: bold; }
+.var-default {}
+.var-description { font-weight: normal; color: #000000; }
+
+.include-title { color: #014fbe;}
+.include-type { font-style: italic; }
+.include-name { font-weight: bold; }
+
+.const-title { color: #FF6600; }
+.const-name { font-weight: bold; }
+
+/* Syntax highlighting */
+
+.src-code { font-family: 'Courier New', Courier, monospace; font-weight: normal; }
+.src-line { font-family: 'Courier New', Courier, monospace; font-weight: normal; }
+
+.src-code a:link { padding: 1px; text-decoration: underline; color: #0000DD; }
+.src-code a:visited { text-decoration: underline; color: #0000DD; }
+.src-code a:active { background-color: #FFFF66; color: #008000; }
+.src-code a:hover { background-color: #FFFF66; text-decoration: overline underline; color: #008000; }
+
+.src-comm { color: #666666; }
+.src-id { color: #FF6600; font-style: italic; }
+.src-inc { color: #0000AA; font-weight: bold; }
+.src-key { color: #0000AA; font-weight: bold; }
+.src-num { color: #CC0000; }
+.src-str { color: #CC0000; }
+.src-sym { }
+.src-var { }
+
+.src-php { font-weight: bold; }
+
+.src-doc { color: #666666; }
+.src-doc-close-template { color: #666666 }
+.src-doc-coretag { color: #008000; }
+.src-doc-inlinetag {}
+.src-doc-internal {}
+.src-doc-tag { color: #0080CC; }
+.src-doc-template { color: #666666 }
+.src-doc-type { font-style: italic; color: #444444 }
+.src-doc-var { color: #444444 }
+
+.tute-tag { color: #009999 }
+.tute-attribute-name { color: #0000FF }
+.tute-attribute-value { color: #0099FF }
+.tute-entity { font-weight: bold; }
+.tute-comment { font-style: italic }
+.tute-inline-tag { color: #636311; font-weight: bold }
+
+/* tutorial */
+
+.authors {  }
+.author { font-style: italic; font-weight: bold }
+.author-blurb { margin: .5em 0em .5em 2em; font-size: 85%; font-weight: normal; font-style: normal }
+.example { border: 1px dashed #999999; background-color: #EEEEEE; padding: .5em; }
+*[class="example"] { line-height : 1.0em; }
+.listing { border: 1px dashed #999999; background-color: #EEEEEE; padding: .5em; white-space: nowrap; }
+*[class="listing"] { line-height : 1.0em; }
+.release-info { font-size: 85%; font-style: italic; margin: 1em 0em }
+.ref-title-box {  }
+.ref-title {  }
+.ref-purpose { font-style: italic; color: #666666 }
+.ref-synopsis {  }
+.title { font-weight: bold; border-bottom: 1px solid #999999; color: #999999;  }
+.cmd-synopsis { margin: 1em 0em }
+.cmd-title { font-weight: bold }
+.toc { margin-left: 2em; padding-left: 0em }
diff --git a/examples/includes/geshi/docs/api/packages.html b/examples/includes/geshi/docs/api/packages.html
new file mode 100644 (file)
index 0000000..d8c4c04
--- /dev/null
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+  <html xmlns="http://www.w3.org/1999/xhtml">
+               <head>
+                       <!-- template designed by Marco Von Ballmoos -->
+                       <title></title>
+                       <link rel="stylesheet" href="media/stylesheet.css" />
+                       <link rel="stylesheet" href="media/banner.css" />
+                       <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
+               </head>
+               <body>
+                       <div class="banner">
+                               <div class="banner-title">geshi</div>
+                               <div class="banner-menu">
+                                       <form>
+                                               <table cellpadding="0" cellspacing="0" style="width: 100%">
+                                                       <tr>
+                                                               <td>
+                                                                                                                                       </td>
+                                                               <td style="width: 2em">&nbsp;</td>
+                                                               <td style="text-align: right">
+                                                                                                                                       </td>
+                                                       </tr>
+                                               </table>
+                                       </form>
+                               </div>
+                       </div>
+               </body>
+       </html>
\ No newline at end of file
diff --git a/examples/includes/geshi/docs/api/todolist.html b/examples/includes/geshi/docs/api/todolist.html
new file mode 100644 (file)
index 0000000..95177c1
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+  <html xmlns="http://www.w3.org/1999/xhtml">
+               <head>
+                       <!-- template designed by Marco Von Ballmoos -->
+                       <title>Todo List</title>
+                       <link rel="stylesheet" href="media/stylesheet.css" />
+                       <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
+               </head>
+               <body>
+                                               <div align="center"><h1>Todo List</h1></div>
+<h2>geshi</h2>
+<h3><a href="geshi/core/GeSHi.html#methoddisable_highlighting">GeSHi::disable_highlighting()</a></h3>
+<ul>
+    <li>Rewrite with array traversal</li>
+</ul>
+<h3><a href="geshi/core/GeSHi.html#methodenable_highlighting">GeSHi::enable_highlighting()</a></h3>
+<ul>
+    <li>Rewrite with array traversal</li>
+</ul>
+<h3><a href="geshi/core/GeSHi.html#methodenable_important_blocks">GeSHi::enable_important_blocks()</a></h3>
+<ul>
+    <li>REMOVE THIS SHIZ FROM GESHI!</li>
+</ul>
+<h3><a href="geshi/core/GeSHi.html#methodget_language_name_from_extension">GeSHi::get_language_name_from_extension()</a></h3>
+<ul>
+    <li>Re-think about how this method works (maybe make it private and/or make it        a extension-&gt;lang lookup?)</li>
+    <li>static?</li>
+</ul>
+<h3><a href="geshi/core/GeSHi.html#methodhighlight_lines_extra">GeSHi::highlight_lines_extra()</a></h3>
+<ul>
+    <li>Some data replication here that could be cut down on</li>
+</ul>
+<h3><a href="geshi/core/GeSHi.html#methodload_from_file">GeSHi::load_from_file()</a></h3>
+<ul>
+    <li>Complete rethink of this and above method</li>
+</ul>
+       <p class="notes" id="credit">
+               Documentation generated on Thu, 25 Dec 2008 14:34:53 +0100 by <a href="http://www.phpdoc.org" target="_blank">phpDocumentor 1.4.2</a>
+       </p>
+       </body>
+</html>
\ No newline at end of file
diff --git a/examples/includes/geshi/docs/geshi-doc.html b/examples/includes/geshi/docs/geshi-doc.html
new file mode 100644 (file)
index 0000000..fff5347
--- /dev/null
@@ -0,0 +1,4051 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+    <head>
+        <title>GeSHi Documentation 1.0.8.3</title>
+
+       <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+       <meta name="keywords" content="GeSHi, syntax, highlighter, colorizer, beautifier, code, generic, php, sql, css, html, syntax, highlighting, documentation" />
+       <meta name="description" content="GeSHi - Generic Syntax Highlighter for PHP. Highlight many languages, including PHP, CSS, HTML, SQL, Java and C for XHTML compliant output using this easy PHP Class. Every aspect of the highlighting is customisable, from colours and other styles to case-sensitivity checking and more. GeSHi - the best syntax highlighter in the world!" />
+
+        <style type="text/css">
+            html {
+                background-color: #e6e6e6;
+            }
+            body {
+                font-family: Verdana, Arial, sans-serif;
+                margin: 10px;
+                border: 2px solid #d0d0d0;
+                background-color: #f6f6f6;
+                padding: 10px;
+            }
+            p, ul, ol, div, blockquote, dt, dd {
+                font-size: 80%;
+                line-height: 140%;
+                letter-spacing: 1px;
+                color: #002;
+            }
+            dt {
+                font-weight: bold;
+            }
+            acronym {
+                border-bottom: 1px dotted #303030;
+                cursor: help;
+            }
+            blockquote {
+                font-weight: bold;
+            }
+            pre, .geshicode {
+                border: 1px solid #c0e6ff;
+                background-color: #e0e8ef;
+                color: #002;
+                margin:0;
+                font-size: 12px;
+                width:100%;
+            }
+            table {
+                border-collapse:collapse;
+            }
+            .geshicode pre {
+                border:none;
+                background-color:inherit;
+                font-weight:bold;
+            }
+            .geshicode .li2 td {
+                background-color:#eee;
+            }
+            .geshicode .li1 td {
+                background-color:#fff;
+            }
+            .geshicode td td {
+                padding:0 2px;
+            }
+            .geshicode td, .geshicode table {
+                width: 100%;
+            }
+            .geshicode td.ln {
+                border-right:2px solid #e0e8ef;
+            }
+            .geshicode .head {
+                text-align:center;
+                font-weight:bold;
+            }
+            code, tt, kbd {
+                font-size: 125%;
+                font-weight:normal;
+            }
+            hr {
+                height: 0;
+                border: none;
+                border-top: 1px dotted #404040;
+                width: 75%;
+            }
+            var {
+                color: blue; font-style: normal; font-family: monospace;
+            }
+            li {
+                padding-top: 2px;
+            }
+            ul ul, ol ol, div ul, div ol {
+                font-size:100%;
+            }
+            .note {
+                border: 1px solid yellow;
+                background-color: #ffc;
+                color: #220;
+                padding: 5px;
+                margin: 1em 0 0 .75em;
+            }
+            .caution {
+                border: 6px double red;
+                background-color: #fcc;
+                color: #200;
+                padding: 5px;
+                margin: 1em 0 0 .75em;
+            }
+            .caution p:first-child, .note p:first-child {
+                margin-top: 0;
+            }
+            .caution-header {
+                border: 1px solid red;
+                border-width: 1px 2px 2px 1px;
+                margin-top: -1.6em;
+                background-color: #fcc;
+                width: 10%;
+                font-weight: bold;
+                text-align: center;
+                color: #600;
+            }
+            .note-header {
+                border: 1px solid #ff0;
+                border-width: 1px 2px 2px 1px;
+                margin-top: -1.2em;
+                background-color: #ffc;
+                width: 10%;
+                font-weight: bold;
+                text-align: center;
+                color: #660;
+            }
+            .nav {
+                font-size: 70%;
+            }
+            .nav a {
+                color: #707070;
+                border: 1px solid #a0a0a0;
+                border-width: 0 1px 1px 1px;
+                border-top: 1px dotted #c0c0c0;
+                text-decoration: none;
+                padding: 1px 2px;
+                background-color: #e0e0e0;
+                -moz-border-radius-bottomleft: 3px;
+                -moz-border-radius-bottomright: 3px;
+            }
+            h1, #contents {
+                margin-top: 0;
+                margin-bottom: 0;
+                text-align: center;
+                color: #404060;
+            }
+            #contents {
+                text-align:left;
+                background:none;
+                border:none;
+            }
+            h2 {
+                border-bottom: 1px dotted #b0b0b0;
+                margin-top: 2em;
+                border-top: 1px dotted #b0b0b0;
+                background-color: #ddd;
+                margin-bottom: 0;
+            }
+            h3 {
+                margin-top: 1.6em;
+                border-bottom: 1px dotted #c0c0c0;
+                margin-bottom: 0;
+            }
+            h4 {
+                border-bottom: 1px dotted #d0d0d0;
+                margin-top: 1.2em;
+                margin-bottom: 0;
+            }
+            h2, h3, h4 {
+                color: #707070;
+                font-weight: normal;
+            }
+            a {
+                color: #7777ff;
+            }
+            sup a {
+                text-decoration: none;
+            }
+            abbr {
+                cursor: help;
+            }
+            .header p {
+                text-align: center;
+                border-bottom: 1px dotted #d0d0d0;
+            }
+
+            .header dl {
+                background-color: #e0e8ef;
+                color: #002;
+                padding: 5px;
+            }
+
+            .header img {
+                float: right;
+                margin:2.5em 1em 0 0;
+            }
+
+            /**
+ * GeSHi Dynamically Generated Stylesheet
+ * --------------------------------------
+ * Dynamically generated stylesheet for bash
+ * CSS class: , CSS id:
+ * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann
+ * (http://qbnz.com/highlighter/ and http://geshi.org/)
+ * --------------------------------------
+ */
+.bash .de1, .bash .de2 {font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;}
+.bash  {font-family:monospace;}
+.bash .imp {font-weight: bold; color: red;}
+.bash li, .bash .li1 {font-weight: normal; vertical-align:top;}
+.bash .ln {width:1px;text-align:right;margin:0;padding:0 2px;vertical-align:top;}
+.bash .li2 {font-weight: bold; vertical-align:top;}
+.bash .kw1 {color: #000000; font-weight: bold;}
+.bash .kw2 {color: #c20cb9; font-weight: bold;}
+.bash .kw3 {color: #7a0874; font-weight: bold;}
+.bash .co0 {color: #666666; font-style: italic;}
+.bash .co1 {color: #800000;}
+.bash .co2 {color: #cc0000; font-style: italic;}
+.bash .co3 {color: #000000; font-weight: bold;}
+.bash .es1 {color: #000099; font-weight: bold;}
+.bash .es2 {color: #007800;}
+.bash .es3 {color: #007800;}
+.bash .es4 {color: #007800;}
+.bash .es5 {color: #780078;}
+.bash .es_h {color: #000099; font-weight: bold;}
+.bash .br0 {color: #7a0874; font-weight: bold;}
+.bash .sy0 {color: #000000; font-weight: bold;}
+.bash .st0 {color: #ff0000;}
+.bash .st_h {color: #ff0000;}
+.bash .nu0 {color: #000000;}
+.bash .re0 {color: #007800;}
+.bash .re1 {color: #007800;}
+.bash .re2 {color: #007800;}
+.bash .re4 {color: #007800;}
+.bash .re5 {color: #660033;}
+.bash .ln-xtra, .bash li.ln-xtra, .bash div.ln-xtra {background-color: #ffc;}
+.bash span.xtra { display:block; }
+
+/**
+ * GeSHi Dynamically Generated Stylesheet
+ * --------------------------------------
+ * Dynamically generated stylesheet for php
+ * CSS class: , CSS id:
+ * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann
+ * (http://qbnz.com/highlighter/ and http://geshi.org/)
+ * --------------------------------------
+ */
+.php .de1, .php .de2 {font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;}
+.php  {font-family:monospace;}
+.php .imp {font-weight: bold; color: red;}
+.php li, .php .li1 {font-weight: normal; vertical-align:top;}
+.php .ln {width:1px;text-align:right;margin:0;padding:0 2px;vertical-align:top;}
+.php .li2 {font-weight: bold; vertical-align:top;}
+.php .kw1 {color: #b1b100;}
+.php .kw2 {color: #000000; font-weight: bold;}
+.php .kw3 {color: #990000;}
+.php .kw4 {color: #009900; font-weight: bold;}
+.php .co1 {color: #666666; font-style: italic;}
+.php .co2 {color: #666666; font-style: italic;}
+.php .co3 {color: #0000cc; font-style: italic;}
+.php .co4 {color: #009933; font-style: italic;}
+.php .coMULTI {color: #666666; font-style: italic;}
+.php .es0 {color: #000099; font-weight: bold;}
+.php .es1 {color: #000099; font-weight: bold;}
+.php .es2 {color: #660099; font-weight: bold;}
+.php .es3 {color: #660099; font-weight: bold;}
+.php .es4 {color: #006699; font-weight: bold;}
+.php .es5 {color: #006699; font-weight: bold; font-style: italic;}
+.php .es6 {color: #009933; font-weight: bold;}
+.php .es_h {color: #000099; font-weight: bold;}
+.php .br0 {color: #009900;}
+.php .sy0 {color: #339933;}
+.php .sy1 {color: #000000; font-weight: bold;}
+.php .st0 {color: #0000ff;}
+.php .st_h {color: #0000ff;}
+.php .nu0 {color: #cc66cc;}
+.php .nu8 {color: #208080;}
+.php .nu12 {color: #208080;}
+.php .nu19 {color:#800080;}
+.php .me1 {color: #004000;}
+.php .me2 {color: #004000;}
+.php .re0 {color: #000088;}
+.php .ln-xtra, .php li.ln-xtra, .php div.ln-xtra {background-color: #ffc;}
+.php span.xtra { display:block; }
+
+/**
+ * GeSHi Dynamically Generated Stylesheet
+ * --------------------------------------
+ * Dynamically generated stylesheet for html4strict
+ * CSS class: , CSS id:
+ * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann
+ * (http://qbnz.com/highlighter/ and http://geshi.org/)
+ * --------------------------------------
+ */
+.html4strict .de1, .html4strict .de2 {font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;}
+.html4strict  {font-family:monospace;}
+.html4strict .imp {font-weight: bold; color: red;}
+.html4strict li, .html4strict .li1 {font-weight: normal; vertical-align:top;}
+.html4strict .ln {width:1px;text-align:right;margin:0;padding:0 2px;vertical-align:top;}
+.html4strict .li2 {font-weight: bold; vertical-align:top;}
+.html4strict .kw2 {color: #000000; font-weight: bold;}
+.html4strict .kw3 {color: #000066;}
+.html4strict .es0 {color: #000099; font-weight: bold;}
+.html4strict .br0 {color: #66cc66;}
+.html4strict .sy0 {color: #66cc66;}
+.html4strict .st0 {color: #ff0000;}
+.html4strict .nu0 {color: #cc66cc;}
+.html4strict .sc-1 {color: #808080; font-style: italic;}
+.html4strict .sc0 {color: #00bbdd;}
+.html4strict .sc1 {color: #ddbb00;}
+.html4strict .sc2 {color: #009900;}
+.html4strict .ln-xtra, .html4strict li.ln-xtra, .html4strict div.ln-xtra {background-color: #ffc;}
+.html4strict span.xtra { display:block; }
+
+/**
+ * GeSHi Dynamically Generated Stylesheet
+ * --------------------------------------
+ * Dynamically generated stylesheet for css
+ * CSS class: , CSS id:
+ * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann
+ * (http://qbnz.com/highlighter/ and http://geshi.org/)
+ * --------------------------------------
+ */
+.css .de1, .css .de2 {font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;}
+.css  {font-family:monospace;}
+.css .imp {font-weight: bold; color: red;}
+.css li, .css .li1 {font-weight: normal; vertical-align:top;}
+.css .ln {width:1px;text-align:right;margin:0;padding:0 2px;vertical-align:top;}
+.css .li2 {font-weight: bold; vertical-align:top;}
+.css .kw1 {color: #000000; font-weight: bold;}
+.css .kw2 {color: #993333;}
+.css .co1 {color: #a1a100;}
+.css .co2 {color: #ff0000; font-style: italic;}
+.css .coMULTI {color: #808080; font-style: italic;}
+.css .es0 {color: #000099; font-weight: bold;}
+.css .br0 {color: #00AA00;}
+.css .sy0 {color: #00AA00;}
+.css .st0 {color: #ff0000;}
+.css .nu0 {color: #cc66cc;}
+.css .re0 {color: #cc00cc;}
+.css .re1 {color: #6666ff;}
+.css .re2 {color: #3333ff;}
+.css .re3 {color: #933;}
+.css .ln-xtra, .css li.ln-xtra, .css div.ln-xtra {background-color: #ffc;}
+.css span.xtra { display:block; }
+
+/**
+ * GeSHi Dynamically Generated Stylesheet
+ * --------------------------------------
+ * Dynamically generated stylesheet for java
+ * CSS class: , CSS id:
+ * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann
+ * (http://qbnz.com/highlighter/ and http://geshi.org/)
+ * --------------------------------------
+ */
+.java .de1, .java .de2 {font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;}
+.java  {font-family:monospace;}
+.java .imp {font-weight: bold; color: red;}
+.java li, .java .li1 {font-weight: normal; vertical-align:top;}
+.java .ln {width:1px;text-align:right;margin:0;padding:0 2px;vertical-align:top;}
+.java .li2 {font-weight: bold; vertical-align:top;}
+.java .kw1 {color: #000000; font-weight: bold;}
+.java .kw2 {color: #000066; font-weight: bold;}
+.java .kw3 {color: #003399;}
+.java .kw4 {color: #000066; font-weight: bold;}
+.java .co1 {color: #666666; font-style: italic;}
+.java .co2 {color: #006699;}
+.java .co3 {color: #008000; font-style: italic; font-weight: bold;}
+.java .coMULTI {color: #666666; font-style: italic;}
+.java .es0 {color: #000099; font-weight: bold;}
+.java .br0 {color: #009900;}
+.java .sy0 {color: #339933;}
+.java .st0 {color: #0000ff;}
+.java .nu0 {color: #cc66cc;}
+.java .me1 {color: #006633;}
+.java .me2 {color: #006633;}
+.java .ln-xtra, .java li.ln-xtra, .java div.ln-xtra {background-color: #ffc;}
+.java span.xtra { display:block; }
+
+
+        </style>
+    </head>
+    <body>
+    <h1 id="top"><abbr title="Generic Syntax Highlighter">GeSHi</abbr> Documentation</h1>
+
+<div class="header">
+
+<p>Version 1.0.8.3</p>
+
+<p><img src="http://qbnz.com/highlighter/images/geshi.png" alt="The GeSHi Logo" /></p>
+
+<dl>
+<dt>Authors:</dt>
+<dd>&copy; 2004 - 2007&#160;<a href="mailto:nigel@geshi.org">Nigel McNie</a></dd>
+
+<dd>&copy; 2007 - 2009&#160;<a href="mailto:BenBE@omorphia.de">Benny Baumann</a></dd>
+
+<dd>&copy; 2008 - 2009&#160;<a href="mailto:mail@milianw.de">Milian Wolff</a></dd>
+
+<dt><abbr title="Generic Syntax Highlighter">GeSHi</abbr> Website:</dt>
+<dd><a href="http://qbnz.com/highlighter">http://qbnz.com/highlighter</a></dd>
+</dl>
+
+</div>
+
+<p>This is the documentation for <abbr title="Generic Syntax Highlighter">GeSHi</abbr> - Generic Syntax Highlighter.</p>
+
+<p>The most modern version of this document is available on the web -
+go to <a href="http://qbnz.com/highlighter/documentation.php">http://qbnz.com/highlighter/documentation.php</a> to view it.</p>
+
+<p>Any comments, questions, confusing points? Please <a href="#feedback">get in contact</a> with the developers! We
+need all the information we can get to make the use of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> and everything related to it (including this documentation)
+a breeze.</p>
+
+<h2 id="contents">Contents</h2>
+
+<div id="toc"><ul>
+<li><a href="#introduction">1 Introduction</a><ul>
+<li><a href="#features">1.1 Features</a></li>
+<li><a href="#about-geshi">1.2 About <abbr title="Generic Syntax Highlighter">GeSHi</abbr></a></li>
+<li><a href="#credits">1.3 Credits</a></li>
+<li><a href="#feedback">1.4 Feedback</a></li>
+</ul></li>
+<li><a href="#the-basics">2 The Basics</a><ul>
+<li><a href="#getting-geshi">2.1 Getting <abbr title="Generic Syntax Highlighter">GeSHi</abbr> work</a><ul>
+<li><a href="#requirements">2.1.1 Requirements</a></li>
+<li><a href="#downloading-geshi">2.1.2 Downloading <abbr title="Generic Syntax Highlighter">GeSHi</abbr></a></li>
+<li><a href="#extracting-geshi">2.1.3 Extracting <abbr title="Generic Syntax Highlighter">GeSHi</abbr></a></li>
+<li><a href="#installing-geshi">2.1.4 Installing <abbr title="Generic Syntax Highlighter">GeSHi</abbr></a></li>
+</ul></li>
+<li><a href="#basic-usage">2.2 Basic Usage</a></li>
+</ul></li>
+<li><a href="#advanced-features">3 Advanced Features</a><ul>
+<li><a href="#the-code-container">3.1 The Code Container</a></li>
+<li><a href="#line-numbers">3.2 Line Numbers</a><ul>
+<li><a href="#enabling-line-numbers">3.2.1 Enabling Line Numbers</a></li>
+<li><a href="#styling-line-numbers">3.2.2 Styling Line Numbers</a></li>
+<li><a href="#starting-line-numbers">3.2.3 Choosing a Start Number</a></li>
+</ul></li>
+<li><a href="#using-css-classes">3.3 Using <abbr title="Cascading Style Sheets">CSS</abbr> Classes</a><ul>
+<li><a href="#enabling-css-classes">3.3.1 Enabling <abbr title="Cascading Style Sheets">CSS</abbr> Classes</a></li>
+<li><a href="#setting-css-class-id">3.3.2 Setting the <abbr title="Cascading Style Sheets">CSS</abbr> class and ID</a></li>
+<li><a href="#getting-stylesheet">3.3.3 Getting the stylesheet for your code</a></li>
+<li><a href="#using-an-external-stylesheet">3.3.4 Using an External Stylesheet</a></li>
+</ul></li>
+<li><a href="#changing-styles">3.4 Changing Styles</a><ul>
+<li><a href="#the-overall-styles">3.4.1 The Overall Styles</a></li>
+<li><a href="#line-number-styles">3.4.2 Line Number Styles</a></li>
+<li><a href="#setting-keyword-styles">3.4.3 Setting Keyword Styles</a></li>
+<li><a href="#setting-comment-styles">3.4.4 Setting Comment Styles</a></li>
+<li><a href="#setting-other-styles">3.4.5 Setting Other Styles</a></li>
+</ul></li>
+<li><a href="#case-caps">3.5 Case Sensitivity and Auto Casing</a><ul>
+<li><a href="#auto-caps-nocaps">3.5.1 Auto-Caps/NoCaps</a></li>
+<li><a href="#setting-case-sensitivity">3.5.2 Setting Case Sensitivity</a></li>
+</ul></li>
+<li><a href="#changing-config">3.6 Changing the Source, Language, Config Options</a><ul>
+<li><a href="#changing-the-source">3.6.1 Changing the Source Code</a></li>
+<li><a href="#changing-the-language">3.6.2 Changing the Language</a></li>
+<li><a href="#changing-the-path">3.6.3 Changing the Language Path</a></li>
+<li><a href="#changing-the-charset">3.6.4 Changing the Character Set</a></li>
+</ul></li>
+<li><a href="#error-handling">3.7 Error Handling</a></li>
+<li><a href="#disabling-lexics">3.8 Disabling styling of some Lexics</a></li>
+<li><a href="#setting-tab-width">3.9 Setting the Tab Width</a></li>
+<li><a href="#using-strict-mode">3.10 Using Strict Mode</a></li>
+<li><a href="#adding-removing-keywords">3.11 Adding/Removing Keywords</a><ul>
+<li><a href="#adding-a-keyword">3.11.1 Adding a Keyword</a></li>
+<li><a href="#removing-a-keyword">3.11.2 Removing a Keyword</a></li>
+<li><a href="#adding-a-keyword-group">3.11.3 Adding a Keyword Group</a></li>
+<li><a href="#removing-a-keyword-group">3.11.4 Removing a Keyword Group</a></li>
+</ul></li>
+<li><a href="#headers-and-footers">3.12 Headers and Footers for Your Code</a><ul>
+<li><a href="#keyword-substitution">3.12.1 Keyword Substitution</a></li>
+<li><a href="#setting-header-content">3.12.2 Setting Header Content</a></li>
+<li><a href="#setting-footer-content">3.12.3 Setting Footer Content</a></li>
+<li><a href="#styling-header-content">3.12.4 Styling Header Content</a></li>
+<li><a href="#styling-footer-content">3.12.5 Styling Footer Content</a></li>
+</ul></li>
+<li><a href="#keyword-urls">3.13 Keyword URLs</a><ul>
+<li><a href="#setting-a-url">3.13.1 Setting a URL for a Keyword Group</a></li>
+<li><a href="#disabling-urls">3.13.2 Disabling a URL for a Keyword Group</a></li>
+<li><a href="#disabling-all-urls">3.13.3 Disabling all URLs for Keywords</a></li>
+<li><a href="#styling-links">3.13.4 Styling Links</a></li>
+<li><a href="#using-targets">3.13.5 Setting the Link Target</a></li>
+</ul></li>
+<li><a href="#using-contextual-importance">3.14 Using Contextual Importance</a></li>
+<li><a href="#highlighting-special-lines-extra">3.15 Highlighting Special Lines &#8220;Extra&#8221;</a><ul>
+<li><a href="#specifying-lines-to-highlight-extra">3.15.1 Specifying the Lines to Highlight Extra</a></li>
+<li><a href="#styles-for-highlighted-lines">3.15.2 Styles for the Highlighted Lines</a></li>
+</ul></li>
+<li><a href="#adding-ids-to-each-line">3.16 Adding IDs to Each Line</a></li>
+<li><a href="#getting-the-time-of-styling">3.17 Getting the Time of Styling</a></li>
+</ul></li>
+<li><a href="#language-files">4 Language Files</a><ul>
+<li><a href="#language-file-example">4.1 An Example Language File</a></li>
+<li><a href="#language-file-conventions">4.2 Language File Conventions</a></li>
+<li><a href="#language-file-sections">4.3 Language File Sections</a><ul>
+<li><a href="#language-file-header">4.3.1 The Header</a></li>
+<li><a href="#language-file-start-indices">4.3.2 The First Indices</a></li>
+<li><a href="#language-file-keywords">4.3.3 Keywords</a></li>
+<li><a href="#language-file-symbols-case">4.3.4 Symbols and Case Sensitivity</a></li>
+<li><a href="#language-file-styles">4.3.5 Styles for your Language File</a></li>
+<li><a href="#language-file-urls">4.3.6 URLs for Functions</a></li>
+<li><a href="#language-file-numbers-support">4.3.7 Number Highlighting Support</a></li>
+<li><a href="#language-file-oo-support">4.3.8 Object Orientation Support</a></li>
+<li><a href="#language-file-regexps">4.3.9 Using Regular Expressions</a></li>
+<li><a href="#language-file-strict-mode">4.3.10 Contextual Highlighting and Strict Mode</a></li>
+<li><a href="#language-file-parser-control">4.3.11 Special Parser Settings (Experimental)</a></li>
+<li><a href="#language-file-tidying-up">4.3.12 Tidying Up</a></li>
+</ul></li>
+<li><a href="#lang-validation">4.4 Validating your language file</a></li>
+</ul></li>
+<li><a href="#method-constant-reference">5 Method/Constant Reference</a></li>
+</ul>
+</div>
+
+<h2 id="introduction">1 Introduction</h2><div class="nav"><a href="#features">Next</a></div>
+
+<p><abbr title="Generic Syntax Highlighter">GeSHi</abbr> is exactly what the acronym stands for: a <strong>Generic Syntax Highlighter</strong>. As long
+as you have a language file for almost any computer language - whether it be a
+scripting language, object orientated, markup or anything in between - <abbr title="Generic Syntax Highlighter">GeSHi</abbr> can
+highlight it! <abbr title="Generic Syntax Highlighter">GeSHi</abbr> is extremely customisable - the same source can be highlighted
+multiple times in multiple ways - the same source even with a different language.
+<abbr title="Generic Syntax Highlighter">GeSHi</abbr> outputs XHTML strict compliant code<sup id="fnref:xhtml-strict"><a href="#fn:xhtml-strict" rel="footnote">1</a></sup>, and can
+make use of <abbr title="Cascading Style Sheets">CSS</abbr> to save on the amount of output. And what is the cost for all of this? You need
+<a href="http://php.net"><abbr title="PHP: HTML Preprocessor">PHP</abbr></a>. That&#8217;s all!</p>
+
+<h3 id="features">1.1 Features</h3><div class="nav"><a href="#introduction">Previous</a> | <a href="#introduction">Top</a> | <a href="#about-geshi">Next</a></div>
+
+<p>Here are some of the standout features of <abbr title="Generic Syntax Highlighter">GeSHi</abbr>:</p>
+
+<dl>
+<dt>Programmed in <abbr title="PHP: HTML Preprocessor">PHP</abbr>:</dt>
+<dd><abbr title="Generic Syntax Highlighter">GeSHi</abbr> is coded entirely in <abbr title="PHP: HTML Preprocessor">PHP</abbr>. This means that where ever you have <abbr title="PHP: HTML Preprocessor">PHP</abbr>, you
+can have <abbr title="Generic Syntax Highlighter">GeSHi</abbr>! Almost any free webhost supports <abbr title="PHP: HTML Preprocessor">PHP</abbr>, and <abbr title="Generic Syntax Highlighter">GeSHi</abbr> works fine with <abbr title="PHP: HTML Preprocessor">PHP</abbr> > 4.3.0<sup id="fnref:php-version-note"><a href="#fn:php-version-note" rel="footnote">2</a></sup>.</dd>
+
+<dt>Support for many languages:</dt>
+<dd><abbr title="Generic Syntax Highlighter">GeSHi</abbr> comes with more than <em>100</em> languages, including <abbr title="PHP: HTML Preprocessor">PHP</abbr>, <abbr title="Hypertext Markup Language">HTML</abbr>, <abbr title="Cascading Style Sheets">CSS</abbr>, Java, C, Lisp, <abbr title="Extensible Markup Language">XML</abbr>, Perl, Python,
+<abbr title="Assembly language">ASM</abbr> and many more!</dd>
+
+<dt>XHTML compliant output:</dt>
+<dd><abbr title="Generic Syntax Highlighter">GeSHi</abbr> produces XHTML compliant output, using stylesheets, so you need not worry about
+<abbr title="Generic Syntax Highlighter">GeSHi</abbr> ruining your claims to perfection in the standards department ;)</dd>
+
+<dt>Highly customisable:</dt>
+<dd><abbr title="Generic Syntax Highlighter">GeSHi</abbr> allows you to change the style of the output on the fly, use <abbr title="Cascading Style Sheets">CSS</abbr> classes or not, use an external
+stylesheet or not, use line numbering, change the case of output keywords&#8230; the list goes on and on!</dd>
+
+<dt>Flexible:</dt>
+<dd>Unfortunately, <abbr title="Generic Syntax Highlighter">GeSHi</abbr> is quite load/time intensive for large blocks of code. However, you want speed?
+Turn off any features you don&#8217;t like, pre-make a stylesheet and use <abbr title="Cascading Style Sheets">CSS</abbr> classes to reduce the amount of output and more -
+it&#8217;s easy to strike a balance that suits you.</dd>
+</dl>
+
+<p>This is just a taste of what you get with <abbr title="Generic Syntax Highlighter">GeSHi</abbr> - the best syntax highlighter for the web in the world!</p>
+
+<h3 id="about-geshi">1.2 About <abbr title="Generic Syntax Highlighter">GeSHi</abbr></h3><div class="nav"><a href="#features">Previous</a> | <a href="#introduction">Top</a> | <a href="#credits">Next</a></div>
+
+<p><abbr title="Generic Syntax Highlighter">GeSHi</abbr> started as a mod for the <a href="http://phpbb.net"><abbr title="PHP Burning Board">phpBB</abbr></a> forum system, to enable highlighting of more
+languages than the available (which can be roughly estimated to exactly 0 ;)). However, it quickly spawned into an
+entire project on its own. But now it has been released, work continues on a mod
+for phpBB<sup id="fnref:phpbb-note"><a href="#fn:phpbb-note" rel="footnote">3</a></sup> - and hopefully for many forum systems, blogs and other web-based systems.</p>
+
+<p>Several systems are using <abbr title="Generic Syntax Highlighter">GeSHi</abbr> now, including:</p>
+
+<ul>
+<li><a href="http://www.splitbrain.org/docuwiki/">Dokuwiki</a> - An advanced wiki engine</li>
+<li><a href="http://gtk.php.net/">gtk.php.net</a> - Their manual uses <abbr title="Generic Syntax Highlighter">GeSHi</abbr> for syntax highlighting</li>
+<li><a href="http://www.wordpress.org/">WordPress</a> - A powerful blogging system<sup id="fnref:plugin-only"><a href="#fn:plugin-only" rel="footnote">4</a></sup></li>
+<li><a href="http://www.php-fusion.co.uk/"><abbr title="PHP: HTML Preprocessor">PHP</abbr>-Fusion</a> - A constantly evolving CMS</li>
+<li><a href="http://cypreess.dione.cc/sqlm">SQL Manager</a> - A Postgres DBAL</li>
+<li><a href="http://www.mamboserver.com/">Mambo</a> - A popular open source CMS</li>
+<li><a href="http://www.mediawiki.org/">MediaWiki</a> - A leader in Wikis[^plugin-only]</li>
+<li><a href="http://www.tikiwiki.org/">TikiWiki</a> - A megapowerful Wiki/CMS</li>
+<li><a href="http://www.tikipro.org/">TikiPro</a> - Another powerful Wiki based on TikiWiki</li>
+<li><a href="http://www.wikkawiki.org/">WikkaWiki</a> - A flexible and lightweight Wiki engine</li>
+<li><a href="http://robloach.net/projects/phpscripts/rweb/">RWeb</a> - A site-building tool</li>
+</ul>
+
+<p><abbr title="Generic Syntax Highlighter">GeSHi</abbr> is the original work of <a href="mailto:nigel@geshi.org">Nigel McNie</a>. The project was later handed over to <a href="mailto:BenBE@omorphia.de">Benny Baumann</a>.
+Others have helped with aspects of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> also, they&#8217;re mentioned in the <a href="THANKS"><code>THANKS</code></a> file.</p>
+
+<h3 id="credits">1.3 Credits</h3><div class="nav"><a href="#about-geshi">Previous</a> | <a href="#introduction">Top</a> | <a href="#feedback">Next</a></div>
+
+<p>Many people have helped out with <abbr title="Generic Syntax Highlighter">GeSHi</abbr>, whether by creating language files, submitting bug
+reports, suggesting new ideas or simply pointing out a new idea or something I&#8217;d missed. All
+of these people have helped to build a better <abbr title="Generic Syntax Highlighter">GeSHi</abbr>, you can see them in the <a href="THANKS"><code>THANKS</code></a>
+file.</p>
+
+<p>Do you want your name on this list? Why not make a language file, or submit a valid bug? Or perhaps help me with an
+added feature I can&#8217;t get my head around, or suggest a new feature, or even port
+<abbr title="Generic Syntax Highlighter">GeSHi</abbr> to anothe language? There&#8217;s lots you can do to help out, and I need it all :)</p>
+
+<h3 id="feedback">1.4 Feedback</h3><div class="nav"><a href="#credits">Previous</a> | <a href="#introduction">Top</a> | <a href="#the-basics">Next</a></div>
+
+<p>I need your feedback! <em>ANY</em>thing you have to say is fine, whether it be a query,
+congratulations, a bug report or complaint, I don&#8217;t care! I want to make this software
+the best it can be, and I need your help! You can contact me in the following ways:</p>
+
+<ul>
+<li><strong>E-mail:</strong>  <a href="mailto:nigel@geshi.org">Nigel McNie</a>, <a href="mailto:BenBE@omorphia.de">Benny Baumann</a> or better yet: use the <a href="http://lists.sourceforge.net/mailman/listinfo/geshi-users">geshi-users</a> mailinglist</li>
+<li><strong>Forums:</strong>  <a href="http://sourceforge.net/forum?group_id=114997">Sourceforge.net Forums</a></li>
+<li><strong>IRC:</strong> <a href="irc://irc.freenode.net/geshi">#geshi</a> on <a href="http://freenode.net">Freenode</a></li>
+</ul>
+
+<p>Remember, any help I am grateful for :)</p>
+
+<h2 id="the-basics">2 The Basics</h2><div class="nav"><a href="#feedback">Previous</a> | <a href="#getting-geshi">Next</a></div>
+
+<p>In this section, you&#8217;ll learn a bit about <abbr title="Generic Syntax Highlighter">GeSHi</abbr>, how it works and what it uses, how to install it and how to use
+it to perform basic highlighting.</p>
+
+<h3 id="getting-geshi">2.1 Getting <abbr title="Generic Syntax Highlighter">GeSHi</abbr> work</h3><div class="nav"><a href="#the-basics">Previous</a> | <a href="#the-basics">Top</a> | <a href="#requirements">Next</a></div>
+
+<p>If you&#8217;re reading this and don&#8217;t have <abbr title="Generic Syntax Highlighter">GeSHi</abbr>, that&#8217;s a problem ;). So, how do you get your hands on it?</p>
+
+<h4 id="requirements">2.1.1 Requirements</h4><div class="nav"><a href="#getting-geshi">Previous</a> | <a href="#getting-geshi">Top</a> | <a href="#downloading-geshi">Next</a></div>
+
+<p><abbr title="Generic Syntax Highlighter">GeSHi</abbr> requires the following to be installable:</p>
+
+<ul>
+<li><strong><a href="http://php.net"><abbr title="PHP: HTML Preprocessor">PHP</abbr></a></strong>. It&#8217;s untested with anything other below 4.4.X. I hope to extend this range soon. I see no reason why
+it won&#8217;t work with any version of <abbr title="PHP: HTML Preprocessor">PHP</abbr> above 4.3.0.</li>
+<li><strong>Approximately 2 megabytes of space</strong>. The actual script is small - around 150K - but most of the size comes
+from the large number of language files (over 100!). If you&#8217;re pushed for space, make sure you don&#8217;t upload to
+your server the <code>docs/</code> or <code>contrib/</code> directory, and you may want to leave out any language files that don&#8217;t
+take your fancy either.</li>
+</ul>
+
+<p>As you can see, the requirements are very small. If <abbr title="Generic Syntax Highlighter">GeSHi</abbr> does NOT work for you in a particular version of <abbr title="PHP: HTML Preprocessor">PHP</abbr>, let
+me know why and I&#8217;ll fix it.</p>
+
+<h4 id="downloading-geshi">2.1.2 Downloading <abbr title="Generic Syntax Highlighter">GeSHi</abbr></h4><div class="nav"><a href="#requirements">Previous</a> | <a href="#getting-geshi">Top</a> | <a href="#extracting-geshi">Next</a></div>
+
+<p>There are several ways to get a copy of <abbr title="Generic Syntax Highlighter">GeSHi</abbr>. The first and easiest way of all is
+visiting <a href="http://qbnz.com/highlighter/downloads.php">http://qbnz.com/highlighter/downloads.php</a> to obtain the latest version.
+This is suitable especially when you plan on using <abbr title="Generic Syntax Highlighter">GeSHi</abbr> on an production website
+or otherwise need a stable copy for flawless operation.</p>
+
+<p>If you are somewhat more sophisticated or need a feature just recently implemented
+you might consider getting <abbr title="Generic Syntax Highlighter">GeSHi</abbr> by downloading via SVN. There are multiple ways
+for doing so and each one has its own advantages and disadvantages. Let&#8217;s cover
+the various locations in the SVN you might download from:</p>
+
+<ul>
+<li><a href="https://geshi.svn.sourceforge.net/svnroot/geshi/tags/">https://geshi.svn.sourceforge.net/svnroot/geshi/tags/</a>:<br />
+This directory holds all previous releases of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> each as a subdirectory. By downloading from here you can test your code with various old versions
+in case something has been broken recently.</li>
+<li><a href="https://geshi.svn.sourceforge.net/svnroot/geshi/branches/RELEASE_1_0_X_STABLE/geshi-1.0.X/src/">https://geshi.svn.sourceforge.net/svnroot/geshi/branches/RELEASE_1_0_X_STABLE/geshi-1.0.X/src/</a>:<br />
+This directory is the right place for you if you want to have reasonably current versions of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> but need something that is stable. This directory
+is updated once in a while between updates whenever there&#8217;s something new but which is already reasonably stable. This branch is used to form the
+actual release once the work is done.</li>
+<li><a href="https://geshi.svn.sourceforge.net/svnroot/geshi/trunk/geshi-1.0.X/src/">https://geshi.svn.sourceforge.net/svnroot/geshi/trunk/geshi-1.0.X/src/</a>:<br />
+This directory is the working directory where every new feature, patch or improvement is committed to. This directory is updated regularly, but is not
+guaranteed to be tested and stable at all times. With this version you&#8217;ll always get the latest version of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> out there, but beware of bugs! There
+will be loads of them here! So this is absolutely <strong>not recommended</strong> for productive use!</li>
+</ul>
+
+<p>If you have choosen the right SVN directory for you do a quick
+<code class="highlighted bash"><span class="kw2">svn</span> <span class="kw2">co</span> <span class="re1">$SVNPATH</span> geshi</code> where <code class="highlighted bash"><span class="re1">$SVNPATH</span></code> is one of the above paths and your desired version of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> will be
+downloaded into an subdirectory called &#8220;geshi&#8221;. If you got a version of <abbr title="Generic Syntax Highlighter">GeSHi</abbr>
+you can go on installing as shown below.</p>
+
+<h4 id="extracting-geshi">2.1.3 Extracting <abbr title="Generic Syntax Highlighter">GeSHi</abbr></h4><div class="nav"><a href="#downloading-geshi">Previous</a> | <a href="#getting-geshi">Top</a> | <a href="#installing-geshi">Next</a></div>
+
+<p>Packages come in <code>.zip</code>, <code>.tar.gz</code> and <code>.tar.bz2</code> format, so there&#8217;s no complaining about whether it&#8217;s available for
+you. *nix users probably want <code>.tar.gz</code> or <code>.tar.bz2</code> and windows users probably want <code>.zip</code>.
+And those lucky to download it directly from SVN don&#8217;t even need to bother extracting <abbr title="Generic Syntax Highlighter">GeSHi</abbr>.</p>
+
+<p>To extract <abbr title="Generic Syntax Highlighter">GeSHi</abbr> in Linux (<code>.tar.gz</code>):</p>
+
+<ol>
+<li>Open a shell</li>
+<li><code class="highlighted bash"><span class="kw3">cd</span></code> to the directory where the archive lies</li>
+<li>Type <code class="highlighted bash"><span class="kw2">tar</span> <span class="re5">-xzvf</span> <span class="br0">&#91;</span>filename<span class="br0">&#93;</span></code> where <code>[filename]</code> is the name of the archive (typically <code>GeSHi-1.X.X.tar.gz</code>)</li>
+<li><abbr title="Generic Syntax Highlighter">GeSHi</abbr> will be extracted to its own directory</li>
+</ol>
+
+<p>To extract <abbr title="Generic Syntax Highlighter">GeSHi</abbr> in Windows (<code>.zip</code>):</p>
+
+<ol>
+<li>Open Explorer</li>
+<li>Navigate to the directory where the archive lies</li>
+<li>Extract the archive. The method you use will depend on your configuration. Some people can right-click upon
+the archive and select &#8220;Extract&#8221; from there, others may have to drag the archive and drop it upon an extraction program.</li>
+</ol>
+
+<p>To extract from <code>.zip</code> you&#8217;ll need an unzipping program - <code class="highlighted bash"><span class="kw2">unzip</span></code> in Linux, or 7-Zip, WinZip, WinRAR or similar for Windows.</p>
+
+<h4 id="installing-geshi">2.1.4 Installing <abbr title="Generic Syntax Highlighter">GeSHi</abbr></h4><div class="nav"><a href="#extracting-geshi">Previous</a> | <a href="#getting-geshi">Top</a> | <a href="#basic-usage">Next</a></div>
+
+<p>Installing <abbr title="Generic Syntax Highlighter">GeSHi</abbr> is a snap, even for those most new to <abbr title="PHP: HTML Preprocessor">PHP</abbr>. There&#8217;s no tricks involved. Honest!</p>
+
+<p><abbr title="Generic Syntax Highlighter">GeSHi</abbr> is nothing more than a <abbr title="PHP: HTML Preprocessor">PHP</abbr> class with related language support files. Those of you familiar with <abbr title="PHP: HTML Preprocessor">PHP</abbr> can then
+guess how easy the installation will be: simply copy it into your include path somewhere. You can put it wherever you
+like in this include path. I recommend that you put the language files in a subdirectory of your include path too -
+perhaps the same subdirectory that geshi.php is in. <strong>Remember this path</strong> for later.</p>
+
+<p>If you don&#8217;t know what an include path is, don&#8217;t worry. Simply copy <abbr title="Generic Syntax Highlighter">GeSHi</abbr> to your webserver. So for example, say your
+site is at <code>http://mysite.com/myfolder</code>, you can copy <abbr title="Generic Syntax Highlighter">GeSHi</abbr> to your site so the directory structure is like this:</p>
+
+<pre><code>http://mysite.com/myfolder/geshi/[language files]
+http://mysite.com/myfolder/geshi.php
+</code></pre>
+
+<p>Or you can put it in any subdirectory you like:</p>
+
+<pre><code>http://mysite.com/myfolder/includes/geshi/[language files]
+http://mysite.com/myfolder/includes/geshi.php
+</code></pre>
+
+<div class="caution">
+
+<div class="caution-header">Caution:</div>
+
+<p>When using <abbr title="Generic Syntax Highlighter">GeSHi</abbr> on a live site, the only directory required is the <code>geshi/</code> subdirectory. Both <code>contrib/</code> and <code>docs/</code> are
+worthless, and furthermore, as some people discovered, one of the files in contrib had a security hole (fixed as of 1.0.7.3).
+I suggest you delete these directories from any live site they are on.</p>
+
+</div>
+
+<h3 id="basic-usage">2.2 Basic Usage</h3><div class="nav"><a href="#installing-geshi">Previous</a> | <a href="#the-basics">Top</a> | <a href="#advanced-features">Next</a></div>
+
+<p>Use of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> is very easy. Here&#8217;s a simple example:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+<span class="xtra li2"><span class="de2">8</span></span>9
+<span class="xtra li2"><span class="de2">10</span></span>11
+<span class="xtra li2"><span class="de2">12</span></span>13
+<span class="xtra li2"><span class="de2">14</span></span>15
+<span class="xtra li2"><span class="de2">16</span></span>17
+<span class="xtra li2"><span class="de2">18</span></span>19
+<span class="xtra li2"><span class="de2">20</span></span>21
+<span class="xtra li2"><span class="de2">22</span></span>23
+<span class="xtra li2"><span class="de2">24</span></span>25
+<span class="xtra li2"><span class="de2">26</span></span>27
+<span class="xtra li2"><span class="de2">28</span></span></pre></td><td class="de1"><pre class="de1"><span class="co1">//</span>
+<span class="xtra li2"><span class="de2"><span class="co1">// Include the GeSHi library</span></span></span><span class="co1">//</span>
+<span class="xtra li2"><span class="de2"><span class="kw1">include_once</span> <span class="st_h">'geshi.php'</span><span class="sy0">;</span></span></span>&nbsp;
+<span class="xtra li2"><span class="de2"><span class="co1">//</span></span></span><span class="co1">// Define some source to highlight, a language to use</span>
+<span class="xtra li2"><span class="de2"><span class="co1">// and the path to the language files</span></span></span><span class="co1">//</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="re0">$source</span> <span class="sy0">=</span> <span class="st_h">'$foo = 45;</span>
+<span class="xtra li2"><span class="de2"><span class="st_h">for ( $i = 1; $i &lt; $foo; $i++ )</span></span></span><span class="st_h">{</span>
+<span class="xtra li2"><span class="de2"><span class="st_h"> &nbsp;echo &quot;$foo\n&quot;;</span></span></span><span class="st_h"> &nbsp;--$foo;</span>
+<span class="xtra li2"><span class="de2"><span class="st_h">}'</span><span class="sy0">;</span></span></span><span class="re0">$language</span> <span class="sy0">=</span> <span class="st_h">'php'</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="co1">//</span>
+<span class="xtra li2"><span class="de2"><span class="co1">// Create a GeSHi object</span></span></span><span class="co1">//</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="re0">$geshi</span> <span class="sy0">=</span> <span class="kw2">new</span> GeSHi<span class="br0">&#40;</span><span class="re0">$source</span><span class="sy0">,</span> <span class="re0">$language</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="co1">//</span>
+<span class="xtra li2"><span class="de2"><span class="co1">// And echo the result!</span></span></span><span class="co1">//</span>
+<span class="xtra li2"><span class="de2"><span class="kw1">echo</span> <span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">parse_code</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></span></span></pre></td></tr></tbody></table>
+
+<p>As you can see, there&#8217;s only three really important lines:</p>
+
+<p><code class="highlighted php"><span class="kw1">include_once</span><span class="br0">&#40;</span><span class="st_h">'geshi.php'</span><span class="br0">&#41;</span></code></p>
+
+<p>This line includes the <abbr title="Generic Syntax Highlighter">GeSHi</abbr> class for use</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span> <span class="sy0">=</span> <span class="kw2">new</span> GeSHi<span class="br0">&#40;</span><span class="re0">$source</span><span class="sy0">,</span> <span class="re0">$language</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>This line creates a new <abbr title="Generic Syntax Highlighter">GeSHi</abbr> object, holding the source and the language you want to use for highlighting.</p>
+
+<p><code class="highlighted php"><span class="kw1">echo</span> <span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">parse_code</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>This line spits out the result :)</p>
+
+<p>So as you can see, simple usage of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> is really easy. Just create a new <abbr title="Generic Syntax Highlighter">GeSHi</abbr> object and get the code!</p>
+
+<p>Since version 1.0.2, there is a function included with <abbr title="Generic Syntax Highlighter">GeSHi</abbr> called <code>geshi_highlight</code>. This behaves exactly as the php
+function <code class="highlighted php"><span class="kw3">highlight_string</span><span class="br0">&#40;</span><span class="br0">&#41;</span></code> behaves - all you do is pass it the language you want to use to highlight and the
+path to the language files as well as the source. Here are some examples:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+<span class="xtra li2"><span class="de2">8</span></span>9
+<span class="xtra li2"><span class="de2">10</span></span>11
+<span class="xtra li2"><span class="de2">12</span></span>13
+<span class="xtra li2"><span class="de2">14</span></span>15
+<span class="xtra li2"><span class="de2">16</span></span>17
+<span class="xtra li2"><span class="de2">18</span></span>19
+<span class="xtra li2"><span class="de2">20</span></span>21
+</pre></td><td class="de1"><pre class="de1"><span class="co1">// Simply echo the highlighted code</span>
+<span class="xtra li2"><span class="de2">geshi_highlight<span class="br0">&#40;</span><span class="re0">$source</span><span class="sy0">,</span> <span class="st_h">'php'</span><span class="sy0">,</span> <span class="re0">$path</span><span class="br0">&#41;</span><span class="sy0">;</span></span></span>&nbsp;
+<span class="xtra li2"><span class="de2"><span class="co1">// Get the code back, for use later</span></span></span><span class="re0">$code</span> <span class="sy0">=</span> geshi_highlight<span class="br0">&#40;</span><span class="re0">$source</span><span class="sy0">,</span> <span class="st_h">'java'</span><span class="sy0">,</span> <span class="re0">$path</span><span class="sy0">,</span> <span class="kw4">true</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="co1">// Check if there is an error with parsing this code</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><a href="http://www.php.net/ob_start"><span class="kw3">ob_start</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2"><span class="re0">$result</span> <span class="sy0">=</span> geshi_highlight<span class="br0">&#40;</span><span class="re0">$source</span><span class="sy0">,</span> <span class="st_h">'perl'</span><span class="sy0">,</span> <span class="re0">$path</span><span class="br0">&#41;</span><span class="sy0">;</span></span></span><span class="re0">$code</span> <span class="sy0">=</span> <a href="http://www.php.net/ob_get_contents"><span class="kw3">ob_get_contents</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><a href="http://www.php.net/ob_end_clean"><span class="kw3">ob_end_clean</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2"><span class="kw1">if</span> <span class="br0">&#40;</span> <span class="sy0">!</span><span class="re0">$result</span> <span class="br0">&#41;</span></span></span><span class="br0">&#123;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="co1">// There was an error with highlighting...</span></span></span><span class="br0">&#125;</span>
+<span class="xtra li2"><span class="de2"><span class="kw1">else</span></span></span><span class="br0">&#123;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="co1">// All OK :)</span></span></span><span class="br0">&#125;</span></pre></td></tr></tbody></table>
+
+<p>However, these are really simple examples and doesn&#8217;t even begin to cover all the advanced features of <abbr title="Generic Syntax Highlighter">GeSHi</abbr>.
+If you want to learn more, continue on to section 3: Advanced Features.</p>
+
+<h2 id="advanced-features">3 Advanced Features</h2><div class="nav"><a href="#basic-usage">Previous</a> | <a href="#the-code-container">Next</a></div>
+
+<p>This section documents the advanced features of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> - strict mode, using <abbr title="Cascading Style Sheets">CSS</abbr> classes, changing styles on the fly,
+disabling highlighting of some things and more.</p>
+
+<p>In this section there are many code snippets. For all of these, you should assume that the <abbr title="Generic Syntax Highlighter">GeSHi</abbr> library has been
+included, and a <abbr title="Generic Syntax Highlighter">GeSHi</abbr> object has been created and is referenced by the variable <code class="highlighted php"><span class="re0">$geshi</span></code>. Normally, the
+source, language and path used are arbitary.</p>
+
+<h3 id="the-code-container">3.1 The Code Container</h3><div class="nav"><a href="#advanced-features">Previous</a> | <a href="#advanced-features">Top</a> | <a href="#line-numbers">Next</a></div>
+
+<p>The <strong>Code Container</strong> has a fundamental effect on the layout of your code before you even begin to style. What is the
+Code Container? It&#8217;s the bit of markup that goes around your code to contain it. By default your code is surrounded
+by a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">pre</span>&gt;</span></code>, but you can also specify a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">div</span>&gt;</span></code>.</p>
+
+<p>The <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">pre</span>&gt;</span></code> header is the default. If you&#8217;re familiar with <abbr title="Hypertext Markup Language">HTML</abbr> you&#8217;ll know that whitespace is rendered
+&#8220;as is&#8221; by a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">pre</span>&gt;</span></code> element. The advantage for you is that if you use <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">pre</span>&gt;</span></code> the whitespace
+you use will appear pretty much exactly how it is in the source, and what&#8217;s more <abbr title="Generic Syntax Highlighter">GeSHi</abbr> won&#8217;t have to add a whole
+lot of <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">br</span> <span class="sy0">/</span>&gt;</span></code>&#8217;s and non-breaking spaces (<code class="highlighted html4strict"><span class="sc1">&amp;nbsp;</span></code>) to your code to indent it. This saves
+you source code (and your valuable visitors waiting time and your bandwidth).</p>
+
+<p>But if you don&#8217;t like <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">pre</span>&gt;</span></code> or it looks stupid in your browser no matter what styles you try to
+apply to it or something similar, you might want to use a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">div</span>&gt;</span></code> instead. A <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">div</span>&gt;</span></code> will
+result in more source - <abbr title="Generic Syntax Highlighter">GeSHi</abbr> will have to insert whitespace markup - but in return you can wrap long lines of code
+that would otherwise have your browser&#8217;s horizontal scrollbar appear. Of course with <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">div</span>&gt;</span></code> you can
+<em>not</em> wrap lines if you please. The highlighter demo at the <a href="http://qbnz.com/highlighter"><abbr title="Generic Syntax Highlighter">GeSHi</abbr> home page</a> uses the <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">div</span>&gt;</span></code>
+approach for this reason.</p>
+
+<p>At this stage there isn&#8217;t an option to wrap the code in <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">code</span>&gt;</span></code> tags (unless you use the function
+<code>geshi_highlight</code>), partly because of the inconsistent and unexpected ways stuff in <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">code</span>&gt;</span></code> tags is
+highlighted. Besides, <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">code</span>&gt;</span></code> is an inline element. But this may become an option in future versions.</p>
+
+<p>As of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> 1.0.7.2 there is a new header type, that specifies that the code should not be wrapped in anything at all.</p>
+
+<p>Another requested addition has been made in <abbr title="Generic Syntax Highlighter">GeSHi</abbr> 1.0.7.20 to force <abbr title="Generic Syntax Highlighter">GeSHi</abbr> to create a block around the highlighted
+source even if this wasn&#8217;t necessary, thus styles that are applied to the output of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> can directly influence
+the code only even if headers and footers are present.</p>
+
+<p>To change/set the header to use, you call the <strong><code class="highlighted php">set_header_type<span class="br0">&#40;</span><span class="br0">&#41;</span></code></strong> method. It has one required argument which
+defines the container type. Available are:</p>
+
+<dl>
+<dt><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_header_type</span><span class="br0">&#40;</span>GESHI_HEADER_DIV<span class="br0">&#41;</span><span class="sy0">;</span></code></dt>
+<dd>
+<p>Puts a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">div</span>&gt;</span></code> around both, code and linenumbers. Whitespace is converted to <code class="highlighted html4strict"><span class="sc1">&amp;nbsp;</span></code>
+sequences (i.e. one whitespace and the html entity of a non-breaking whitespace) to keep your indendation level
+in tact. Tabs are converted as well and you can manually <a href="#setting-tab-width">define the tab-width</a>. Lines are automatically wrapped.
+Linenumbers are created using an ordered list.</p>
+</dd>
+
+<dt><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_header_type</span><span class="br0">&#40;</span>GESHI_HEADER_PRE<span class="br0">&#41;</span><span class="sy0">;</span></code></dt>
+<dd>
+<p>Wraps code and linenumbers in a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">pre</span>&gt;</span></code> container. This way whitespace is kept as-is and thus
+this header produces less overhead then the <code>GESHI_HEADER_DIV</code> header type. Since linenumbers are still
+created using an ordered list this header type produces <strong>invalid <abbr title="Hypertext Markup Language">HTML</abbr></strong>.</p>
+</dd>
+
+<dt><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_header_type</span><span class="br0">&#40;</span>GESHI_HEADER_PRE_VALID<span class="br0">&#41;</span><span class="sy0">;</span></code></dt>
+<dd><em><small>Available since 1.0.8</small></em></dd>
+
+<dd>
+<p>When linenumbers are disabled, this behaves just like <code>GESHI_HEADER_PRE</code>. In the other case though, a
+<code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">div</span>&gt;</span></code> is used to wrap the code and linenumbers and the <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">pre</span>&gt;</span></code> is put inside the list
+items (<code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">li</span>&gt;</span></code>). This means slightly larger <abbr title="Hypertext Markup Language">HTML</abbr> output compared to <code>GESHI_HEADER_PRE</code>, but the
+output is <strong>valid <abbr title="Hypertext Markup Language">HTML</abbr></strong>.</p>
+</dd>
+
+<dt><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_header_type</span><span class="br0">&#40;</span>GESHI_HEADER_PRE_TABLE<span class="br0">&#41;</span><span class="sy0">;</span></code></dt>
+<dd><em><small>Available since 1.0.8</small></em></dd>
+
+<dd>
+<p>Once again a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">div</span>&gt;</span></code> tag wraps the output. This time though no ordered list is used to create an ordered list,
+but instead we use a table with two cells in a single row. The left cell contains a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">pre</span>&gt;</span></code> tag which holds all
+linenumbers. The second cell holds the highlighted code, also wrapped in a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">pre</span>&gt;</span></code> tag, just like with
+<code>GESHI_HEADER_PRE</code>.</p>
+</dd>
+
+<dd>
+<p>This produces <strong>valid <abbr title="Hypertext Markup Language">HTML</abbr></strong> and works around the nasty selection behaviour of Firefox and other Gecko based
+browsers, see <a href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1651996&amp;group_id=114997&amp;atid=670231">SF#1651996</a> for more information.</p>
+</dd>
+
+<dt><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_header_type</span><span class="br0">&#40;</span>GESHI_HEADER_NONE<span class="br0">&#41;</span><span class="sy0">;</span></code></dt>
+<dd><em><small>Available since 1.0.7.2</small></em></dd>
+
+<dd>
+<p>No wrapper is added.</p>
+</dd>
+</dl>
+
+<p>Those are the only arguments you should pass to <code class="highlighted php">set_header_type</code>. Passing anything else may cause inconsistencies
+in what is used as the Code Container (although it <em>should</em> simply use a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">pre</span>&gt;</span></code>). Better not to risk it.</p>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>GESHI_HEADER_DIV, GESHI_HEADER_PRE, etc. are <em>constants</em>, so don&#8217;t put them in strings!</p>
+
+</div>
+
+<div class="caution">
+
+<div class="caution-header">Caution:</div>
+
+<p>The default styles for the <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">pre</span>&gt;</span></code> and <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">div</span>&gt;</span></code> <em>will be different</em>, especially if you use
+  line numbers!</p>
+
+<p>I have found that a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">pre</span>&gt;</span></code> results in code that is smaller than for that of a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">div</span>&gt;</span></code>, you
+  should rectify this difference by using <strong><code class="highlighted php">set_overall_style<span class="br0">&#40;</span><span class="br0">&#41;</span></code></strong> if you need to. But be aware of this
+  difference for if you are changing the header type!</p>
+
+</div>
+
+<h3 id="line-numbers">3.2 Line Numbers</h3><div class="nav"><a href="#the-code-container">Previous</a> | <a href="#advanced-features">Top</a> | <a href="#enabling-line-numbers">Next</a></div>
+
+<p><abbr title="Generic Syntax Highlighter">GeSHi</abbr> has the ability to add line numbers to your code (see the demo available at <a href="http://qbnz.com/highlighter/demo.php">http://qbnz.com/highlighter/demo.php</a>
+to see what can be achieved). Line numbers are a great way to make your code look professional, especially if you use the
+fancy line numbers feature.</p>
+
+<p>There are multiple methods for highlighting line numbers, but none of them is perfect. Of the various ways to highlight
+line numbers <abbr title="Generic Syntax Highlighter">GeSHi</abbr> itself implements 2 different approaches, but allows you
+by the way it generates the code to do the line numbers yourself if necessary - but more on this case later.</p>
+
+<p>The easiest approach is using the <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">ol</span>&gt;</span></code>-tag for generating the line numbers, but
+even though this is the easiest one there&#8217;s a big drawback with this one when
+using Gecko-engine based browsers like Firefox or Konqueror. In these browsers
+this approach will select the line numbers along with the code or will include extra markup in the selection.</p>
+
+<p>The other approach has been implemented in the 1.0.8 release of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> with the <code class="highlighted php">GESHI_HEADER_PRE_TABLE</code> header type.
+When using this header type the line numbers are rendered apart from the source
+in a table cell while the actual source is formatted as if the <code class="highlighted php">GESHI_HEADER_PRE</code> header had been used.
+This approach works with Firefox and other Gecko-based browsers so far although extreme care
+has to be taken when applying styles to your source as Windows has some fonts
+where bold font is of different height than normal or italic text of the same fontface.</p>
+
+<h4 id="enabling-line-numbers">3.2.1 Enabling Line Numbers</h4><div class="nav"><a href="#line-numbers">Previous</a> | <a href="#line-numbers">Top</a> | <a href="#styling-line-numbers">Next</a></div>
+
+<p>To highlight a source with line numbers, you call the <code class="highlighted php">enable_line_numbers<span class="br0">&#40;</span><span class="br0">&#41;</span></code> method:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">enable_line_numbers</span><span class="br0">&#40;</span><span class="re0">$flag</span><span class="br0">&#41;</span><span class="sy0">;</span></code>
+Where <code class="highlighted php"><span class="re0">$flag</span></code> is one of the following:</p>
+
+<ul>
+<li><code>GESHI_NORMAL_LINE_NUMBERS</code> - Use normal line numbering</li>
+<li><code>GESHI_FANCY_LINE_NUMBERS</code> - Use fancy line numbering</li>
+<li><code>GESHI_NO_LINE_NUMBERS</code> - Disable line numbers (default)</li>
+</ul>
+
+<p>Normal line numbers means you specify a style for them, and that style gets applied to all of them. Fancy line numbers
+means that you can specify a different style for each n<sup>th</sup> line number. You change the value of n (default 5):</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">enable_line_numbers</span><span class="br0">&#40;</span>GESHI_FANCY_LINE_NUMBERS<span class="sy0">,</span> <span class="nu0">37</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>The second parameter is not used in any other mode. Setting it to <code>0</code> is the same as simply using normal line numbers.
+Setting it to <code>1</code> applies the fancy style to every line number.</p>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>The values above are CONSTANTS - so don&#8217;t put them in strings!</p>
+
+</div>
+
+<h4 id="styling-line-numbers">3.2.2 Styling Line Numbers</h4><div class="nav"><a href="#enabling-line-numbers">Previous</a> | <a href="#line-numbers">Top</a> | <a href="#starting-line-numbers">Next</a></div>
+
+<p>As of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> 1.0.2, line numbers are added by the use of ordered lists. This solves the old issues of line number
+styles inheriting from styles meant for the code. Also, this solves an important issue about selecting code. For
+example, line numbers look nice, but when you go to select the code in your browser to copy it? You got the line
+numbers too! Not such a good thing, but thankfully this issue is now solved. What is the price? Unfortunately the
+whole way that styles are inherited/used has changed for those of you who were familiar with 1.0.1, and there is
+quite a bit more <abbr title="Hypertext Markup Language">HTML</abbr> involved. So think carefully about these things before you enable line numbers.</p>
+
+<p>Now, onto how to style line numbers:</p>
+
+<p>Styles are set for line numbers using the <code class="highlighted php">set_line_style<span class="br0">&#40;</span><span class="br0">&#41;</span></code> method:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_line_style</span><span class="br0">&#40;</span><span class="st_h">'background: #fcfcfc;'</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>If you&#8217;re using Fancy Line Numbers mode, you pass a second string for the style of the n<sup>th</sup> line number:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_line_style</span><span class="br0">&#40;</span><span class="st_h">'background: #fcfcfc;'</span><span class="sy0">,</span> <span class="st_h">'background: #f0f0f0;'</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>The second style will have no effect if you&#8217;re not using Fancy Line Numbers mode.</p>
+
+<p>By default, the styles you pass overwrite the current styles. Add a boolean &#8220;true&#8221; after the styles you specify to combine them with the current styles:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span></pre></td><td class="de1"><pre class="de1"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_line_style</span><span class="br0">&#40;</span><span class="st_h">'background: red;'</span><span class="sy0">,</span> <span class="kw4">true</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="co1">// or, for fancy line numbers</span>
+<span class="xtra li2"><span class="de2"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_line_style</span><span class="br0">&#40;</span><span class="st_h">'background: red;'</span><span class="sy0">,</span> <span class="st_h">'background: blue;'</span><span class="sy0">,</span> <span class="kw4">true</span><span class="br0">&#41;</span><span class="sy0">;</span></span></span></pre></td></tr></tbody></table>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>Due to a bug with Firefox the issue that should have been fixed with 1.0.2 has reappeared in another form as Firefox
+  includes extra text\markup into plaintext versions of webpage copies. This can sometimes be useful (actually it&#8217;s
+  used to get the plaintext version of this documentation), but more often is quite annoying. Best practice so far is
+  to either not use line numbers, or offer the visitor of your page a plaintext version of your source. To learn more
+  have a look at the <a href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1651996&amp;group_id=114997&amp;atid=670231">SF.net BugTracker Issue #1651996</a>. This will hopefully be fixed in <abbr title="Generic Syntax Highlighter">GeSHi</abbr> version 1.2
+  or as soon as Firefox provides webdevelopers with adequate ways to control this feature - whichever comes first!</p>
+
+</div>
+
+<div class="caution">
+
+<div class="caution-header">Caution:</div>
+
+<p>When you set line number styles, the code will inherit those styles! This is the main issue to come out of the 1.0.2
+  release. If you want your code to be styled in a predictable manner, you&#8217;ll have to call the <code class="highlighted php">set_code_style<span class="br0">&#40;</span><span class="br0">&#41;</span></code>
+  method to rectify this problem.</p>
+
+<p>Note also that you cannot apply background colours to line numbers unless you use <code class="highlighted php">set_overall_style<span class="br0">&#40;</span><span class="br0">&#41;</span></code>.
+  Here&#8217;s how you&#8217;d style:</p>
+
+<ol>
+<li><p>Use <code class="highlighted php">set_overall_style<span class="br0">&#40;</span><span class="br0">&#41;</span></code> to style the overall code block. For example, you can set the border
+style/colour, any margins and padding etc. using this method. <strong>In addition:</strong> set the background colour for
+all the line numbers using this method.</p></li>
+<li><p>Use <code class="highlighted php">set_line_style<span class="br0">&#40;</span><span class="br0">&#41;</span></code> to style the foreground of the line numbers. For example, you can set the colour,
+weight, font, padding etc. of the line numbers using this method.</p></li>
+<li><p>Use <code class="highlighted php">set_code_style<span class="br0">&#40;</span><span class="br0">&#41;</span></code> to explicitly override the styles you set for line numbers using
+<code class="highlighted php">set_line_style</code>. For example, if you&#8217;d set the line numbers to be bold (or even if you&#8217;d only set
+the fancy line number style to be bold), and you didn&#8217;t actually want your code to be bold, you&#8217;d make sure
+that <code class="highlighted css"><span class="kw1">font-weight</span><span class="sy0">:</span> <span class="kw2">normal</span><span class="sy0">;</span></code> was in the stylesheet rule you passed to <code class="highlighted php">set_code_style<span class="br0">&#40;</span><span class="br0">&#41;</span></code>.</p>
+
+<p>This is the one major change from <abbr title="Generic Syntax Highlighter">GeSHi</abbr> 1.0.1 - make sure you become familiar with this, and make sure that you check
+any code you have already styled with 1.0.1 when you upgrade to make sure nothing bad happens to it.</p></li>
+</ol>
+
+</div>
+
+<h4 id="starting-line-numbers">3.2.3 Choosing a Start Number</h4><div class="nav"><a href="#styling-line-numbers">Previous</a> | <a href="#line-numbers">Top</a> | <a href="#using-css-classes">Next</a></div>
+
+<p>As of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> 1.0.2, you can now make the line numbers start at any number, rather than just 1. This feature is useful
+if you&#8217;re highlighting code from a file from around a certain line number in that file, as an additional guide to
+those who will view the code. You set the line numbers by calling the <code class="highlighted php">start_line_numbers_at<span class="br0">&#40;</span><span class="br0">&#41;</span></code> method:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">start_line_numbers_at</span><span class="br0">&#40;</span><span class="re0">$number</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p><code class="highlighted php"><span class="re0">$number</span></code> must be a positive integer (or zero). If it is not, <abbr title="Generic Syntax Highlighter">GeSHi</abbr> will convert it anyway.</p>
+
+<p>If you have not enabled line numbers, this will have no effect.</p>
+
+<div class="caution">
+
+<div class="caution-header">Caution:</div>
+
+<p>Although I&#8217;d like <abbr title="Generic Syntax Highlighter">GeSHi</abbr> to have XHTML strict compliance, this feature will break compliancy (however transitional
+  compliancy remains). This is because the only widely supported way to change the start value for line numbers is
+  by using the <strong>start=&#8221;number&#8221;</strong> attribute of the <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">ol</span>&gt;</span></code> tag. Although <abbr title="Cascading Style Sheets">CSS</abbr> does provide a mechanism for
+  doing this, it is only supported in Opera versions 7.5 and above (not even Firefox supports this).</p>
+
+</div>
+
+<h3 id="using-css-classes">3.3 Using <abbr title="Cascading Style Sheets">CSS</abbr> Classes</h3><div class="nav"><a href="#starting-line-numbers">Previous</a> | <a href="#advanced-features">Top</a> | <a href="#enabling-css-classes">Next</a></div>
+
+<p>Using <abbr title="Cascading Style Sheets">CSS</abbr> to highlight your code instead of in-lining the styles is a definate bonus. Not only is it more compliant
+(the w3c is deprecating the style attribute in XHTML 2.0) but it results in far less outputted code - up to a whopping
+90% saving - which makes a &#42;huge&#42; difference to those unlucky of us on modems!</p>
+
+<h4 id="enabling-css-classes">3.3.1 Enabling <abbr title="Cascading Style Sheets">CSS</abbr> Classes</h4><div class="nav"><a href="#using-css-classes">Previous</a> | <a href="#using-css-classes">Top</a> | <a href="#setting-css-class-id">Next</a></div>
+
+<p>By default, <abbr title="Generic Syntax Highlighter">GeSHi</abbr> doesn&#8217;t use the classes, so it&#8217;s easy just to whack out some highlighted code if you need without
+worrying about stylesheets. However, if you&#8217;re a bit more organised about it, you should use the classes ;). To turn
+the use of classes on, you call the <code class="highlighted php">enable_classes<span class="br0">&#40;</span><span class="br0">&#41;</span></code> method:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">enable_classes</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>If you want to turn classes OFF for some reason later:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">enable_classes</span><span class="br0">&#40;</span><span class="kw4">false</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>If classes are enabled when <code class="highlighted php">parse_code<span class="br0">&#40;</span><span class="br0">&#41;</span></code> is called, then the resultant source will use <abbr title="Cascading Style Sheets">CSS</abbr> classes in the
+output, otherwise it will in-line the styles. The advantages of using classes are great - the reduction in source will
+be very noticeable, and what&#8217;s more you can use one stylesheet for several different highlights on the same page. In
+fact, you can even use an external stylesheet and link to that, saving even more time and source (because stylesheets
+are cached by browsers).</p>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>There have been problems with inline styles and the Symbol Highlighting added in 1.0.7.21. If you can you should
+  therefore turn <abbr title="Cascading Style Sheets">CSS</abbr> classes ON to avoid those issues. Although latest reworks in 1.0.8 should fix most of those issues.</p>
+
+</div>
+
+<div class="caution">
+
+<div class="caution-header">Caution:</div>
+
+<p>This should be the very first method you call after creating a new <abbr title="Generic Syntax Highlighter">GeSHi</abbr> object! That way, various other methods
+  can act upon your choice to use classes correctly. In theory, you could call this method just before parsing the
+  code, but this may result in unexpected behaviour.</p>
+
+</div>
+
+<h4 id="setting-css-class-id">3.3.2 Setting the <abbr title="Cascading Style Sheets">CSS</abbr> class and ID</h4><div class="nav"><a href="#enabling-css-classes">Previous</a> | <a href="#using-css-classes">Top</a> | <a href="#getting-stylesheet">Next</a></div>
+
+<p>You can set an overall <abbr title="Cascading Style Sheets">CSS</abbr> class and id for the code. This is a good feature that allows you to use the same
+stylesheet for many different snippets of code. You call <code class="highlighted php">set_overall_class<span class="br0">&#40;</span><span class="br0">&#41;</span></code> and <code class="highlighted php">set_overall_id</code>
+to accomplish this:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span></pre></td><td class="de1"><pre class="de1"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_overall_class</span><span class="br0">&#40;</span><span class="st_h">'mycode'</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_overall_id</span><span class="br0">&#40;</span><span class="st_h">'dk48ck'</span><span class="br0">&#41;</span><span class="sy0">;</span></span></span></pre></td></tr></tbody></table>
+
+<p>The default classname is the name of the language being used. This means you can use just the one stylesheet for all
+sources that use the same language, and incidentally means that you probably won&#8217;t have to call these methods too often.</p>
+
+<p><abbr title="Cascading Style Sheets">CSS</abbr> IDs are supposed to be unique, and you should use them as such. Basically, you can specify an ID for your code
+and then use that ID to highlight that code in a unique way. You&#8217;d do this for a block of code that you expressly
+wanted to be highlighted in a different way (see the section below on gettting the stylesheet for your code for an example).</p>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>As of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> 1.0.8 the class name will always include the language name used for highlighting.</p>
+
+</div>
+
+<h4 id="getting-stylesheet">3.3.3 Getting the stylesheet for your code</h4><div class="nav"><a href="#setting-css-class-id">Previous</a> | <a href="#using-css-classes">Top</a> | <a href="#using-an-external-stylesheet">Next</a></div>
+
+<p>The other half of using <abbr title="Cascading Style Sheets">CSS</abbr> classes is getting the stylesheet for use with the classes. <abbr title="Generic Syntax Highlighter">GeSHi</abbr> makes it very easy to
+get a stylesheet for your code, with one easy method call:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+<span class="xtra li2"><span class="de2">8</span></span>9
+<span class="xtra li2"><span class="de2">10</span></span>11
+<span class="xtra li2"><span class="de2">12</span></span>13
+<span class="xtra li2"><span class="de2">14</span></span>15
+<span class="xtra li2"><span class="de2">16</span></span>17
+</pre></td><td class="de1"><pre class="de1"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">enable_classes</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="co1">// Here we have code that will spit out a header for</span>
+<span class="xtra li2"><span class="de2"><span class="co1">// a stylesheet. For example:</span></span></span>&nbsp;
+<span class="xtra li2"><span class="de2"><span class="kw1">echo</span> <span class="st_h">'&lt;html&gt;</span></span></span><span class="st_h">&lt;head&gt;&lt;title&gt;Code&lt;/title&gt;</span>
+<span class="xtra li2"><span class="de2"><span class="st_h">&lt;style type=&quot;text/css&quot;&gt;</span></span></span><span class="st_h">&lt;!--'</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2"><span class="co1">// Echo out the stylesheet for this code block</span></span></span><span class="kw1">echo</span> <span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">get_stylesheet</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="co1">// And continue echoing the page</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="kw1">echo</span> <span class="st_h">'--&gt;</span>
+<span class="xtra li2"><span class="de2"><span class="st_h">&lt;/style&gt;&lt;/head&gt;</span></span></span><span class="st_h">&lt;body&gt;'</span><span class="sy0">;</span></pre></td></tr></tbody></table>
+
+<p>The <code class="highlighted php">get_stylesheet<span class="br0">&#40;</span><span class="br0">&#41;</span></code> method gets the stylesheet for your code in one easy call. All you need to do
+is output it in the correct place. As you can also see, you don&#8217;t even have to enable class usage to get the
+stylesheet nessecary either - however not enabling classes but using the stylesheet may result in problems later.</p>
+
+<p>By default, <code class="highlighted php">get_stylesheet<span class="br0">&#40;</span><span class="br0">&#41;</span></code> tries to echo the least amount of code possible. Although currently it doesn&#8217;t
+check to see if a certain lexic is even in the source, you can expect this feature in the future. At least for the
+present however, if you explicitly disable the highlighting of a certain lexic, or disable line numbers, the related
+<abbr title="Cascading Style Sheets">CSS</abbr> will not be outputted. This may be a bad thing for you perhaps you&#8217;re going to use the stylesheet for many blocks
+of code, some with line numbers, others with some lexic enabled where this source has it disabled. Or perhaps you&#8217;re
+building an external stylesheet and want all lexics included. So to get around this problem, you do this:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">get_stylesheet</span><span class="br0">&#40;</span><span class="kw4">false</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>This turns economy mode off, and all of the stylesheet will be outputted regardless.</p>
+
+<p>Now lets say you have several snippets of code, using the same language. In most of them you don&#8217;t mind if they&#8217;re
+highlighted the same way (in fact, that&#8217;s exactly what you want) but in one of them you&#8217;d like the source to be
+highlighted differently. Here&#8217;s how you can do that:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+<span class="xtra li2"><span class="de2">8</span></span>9
+<span class="xtra li2"><span class="de2">10</span></span>11
+<span class="xtra li2"><span class="de2">12</span></span>13
+<span class="xtra li2"><span class="de2">14</span></span>15
+<span class="xtra li2"><span class="de2">16</span></span>17
+<span class="xtra li2"><span class="de2">18</span></span>19
+<span class="xtra li2"><span class="de2">20</span></span>21
+<span class="xtra li2"><span class="de2">22</span></span>23
+<span class="xtra li2"><span class="de2">24</span></span>25
+<span class="xtra li2"><span class="de2">26</span></span>27
+<span class="xtra li2"><span class="de2">28</span></span>29
+<span class="xtra li2"><span class="de2">30</span></span>31
+<span class="xtra li2"><span class="de2">32</span></span>33
+<span class="xtra li2"><span class="de2">34</span></span>35
+<span class="xtra li2"><span class="de2">36</span></span>37
+<span class="xtra li2"><span class="de2">38</span></span>39
+<span class="xtra li2"><span class="de2">40</span></span>41
+<span class="xtra li2"><span class="de2">42</span></span>43
+<span class="xtra li2"><span class="de2">44</span></span>45
+<span class="xtra li2"><span class="de2">46</span></span>47
+<span class="xtra li2"><span class="de2">48</span></span></pre></td><td class="de1"><pre class="de1"><span class="co1">// assume path is the default &quot;geshi/&quot; relative to the current directory</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="re0">$geshi1</span> <span class="sy0">=</span> <span class="kw2">new</span> GeSHi<span class="br0">&#40;</span><span class="re0">$source1</span><span class="sy0">,</span> <span class="re0">$lang</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2"><span class="re0">$geshi2</span> <span class="sy0">=</span> <span class="kw2">new</span> GeSHi<span class="br0">&#40;</span><span class="re0">$source2</span><span class="sy0">,</span> <span class="re0">$lang</span><span class="br0">&#41;</span><span class="sy0">;</span></span></span>&nbsp;
+<span class="xtra li2"><span class="de2"><span class="re0">$geshi3</span> <span class="sy0">=</span> <span class="kw2">new</span> GeSHi<span class="br0">&#40;</span><span class="re0">$source3</span><span class="sy0">,</span> <span class="re0">$lang</span><span class="br0">&#41;</span><span class="sy0">;</span></span></span>&nbsp;
+<span class="xtra li2"><span class="de2"><span class="co1">// Turn classes on for all sources</span></span></span><span class="re0">$geshi1</span><span class="sy0">-&gt;</span><span class="me1">enable_classes</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="re0">$geshi2</span><span class="sy0">-&gt;</span><span class="me1">enable_classes</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2"><span class="re0">$geshi3</span><span class="sy0">-&gt;</span><span class="me1">enable_classes</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></span></span>&nbsp;
+<span class="xtra li2"><span class="de2"><span class="co1">// Make $geshi3 unique</span></span></span><span class="re0">$geshi3</span><span class="sy0">-&gt;</span><span class="me1">set_overall_id</span><span class="br0">&#40;</span><span class="st_h">'different'</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span>&nbsp;
+<span class="xtra li2"><span class="de2"><span class="co1">//</span></span></span><span class="co1">// Methods are called on $geshi3 to change styles...</span>
+<span class="xtra li2"><span class="de2"><span class="co1">//</span></span></span>&nbsp;
+<span class="xtra li2"><span class="de2"><span class="kw1">echo</span> <span class="st_h">'&lt;html&gt;</span></span></span><span class="st_h">&lt;head&gt;&lt;title&gt;Code&lt;/title&gt;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="st_h">&lt;style type=&quot;text/css&quot;&gt;</span>
+<span class="xtra li2"><span class="de2"><span class="st_h">&lt;!--</span></span></span><span class="st_h">'</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="co1">// Get the nessecary stylesheets</span>
+<span class="xtra li2"><span class="de2"><span class="kw1">echo</span> <span class="re0">$geshi1</span><span class="sy0">-&gt;</span><span class="me1">get_stylesheet</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></span></span>&nbsp;
+<span class="xtra li2"><span class="de2"><span class="kw1">echo</span> <span class="re0">$geshi3</span><span class="sy0">-&gt;</span><span class="me1">get_stylesheet</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></span></span>&nbsp;
+<span class="xtra li2"><span class="de2"><span class="kw1">echo</span> <span class="st_h">'--&gt;</span></span></span><span class="st_h">&lt;/style&gt;&lt;/head&gt;</span>
+<span class="xtra li2"><span class="de2"><span class="st_h">&lt;body&gt;'</span><span class="sy0">;</span></span></span>&nbsp;
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="kw1">echo</span> <span class="st_h">'Code snippet 1:'</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2"><span class="kw1">echo</span> <span class="re0">$geshi1</span><span class="sy0">-&gt;</span><span class="me1">parse_code</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></span></span><span class="kw1">echo</span> <span class="st_h">'Code snippet 2 (same highlighting as 1):'</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="kw1">echo</span> <span class="re0">$geshi2</span><span class="sy0">-&gt;</span><span class="me1">parse_code</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2"><span class="kw1">echo</span> <span class="st_h">'Code snippet 3 (DIFFERENT highlighting):'</span><span class="sy0">;</span></span></span><span class="kw1">echo</span> <span class="re0">$geshi3</span><span class="sy0">-&gt;</span><span class="me1">parse_code</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span>&nbsp;
+<span class="xtra li2"><span class="de2"><span class="kw1">echo</span> <span class="st_h">'&lt;/body&gt;&lt;/html&gt;'</span><span class="sy0">;</span></span></span></pre></td></tr></tbody></table>
+
+<p>Before version 1.0.2, you needed to set the class of the code you wanted to be unique to the empty string. This
+limitation has been removed in version 1.0.2 - if you set the ID of a block of code, all styling will be done based
+on that ID alone.</p>
+
+<h4 id="using-an-external-stylesheet">3.3.4 Using an External Stylesheet</h4><div class="nav"><a href="#getting-stylesheet">Previous</a> | <a href="#using-css-classes">Top</a> | <a href="#changing-styles">Next</a></div>
+
+<p>An external stylesheet can reduce even more the amount of code needed to highlight some source. However there are some
+drawbacks with this. To use an external stylesheet, it&#8217;s up to you to link it in to your document, normally with
+the following <abbr title="Hypertext Markup Language">HTML</abbr>:</p>
+
+<table class="html4strict geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">HTML code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+</pre></td><td class="de1"><pre class="de1"><span class="sc2">&lt;<a href="http://december.com/html/4/element/html.html"><span class="kw2">html</span></a>&gt;</span>
+<span class="xtra li2"><span class="de2"><span class="sc2">&lt;<a href="http://december.com/html/4/element/head.html"><span class="kw2">head</span></a>&gt;</span></span></span><span class="sc2">&lt;<a href="http://december.com/html/4/element/link.html"><span class="kw2">link</span></a> <span class="kw3">rel</span><span class="sy0">=</span><span class="st0">&quot;stylesheet&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;text/css&quot;</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;url_to_stylesheet.css&quot;</span> <span class="sy0">/</span>&gt;</span></pre></td></tr></tbody></table>
+
+<p>In your external stylesheet you put <abbr title="Cascading Style Sheets">CSS</abbr> declarations for your code. Then just make sure you&#8217;re using the correct class (use
+<code class="highlighted php">set_overall_class<span class="br0">&#40;</span><span class="br0">&#41;</span></code> to ensure this) and this should work fine.</p>
+
+<p>This method is great if you don&#8217;t mind the source always being highlighted the same (in particular, if you&#8217;re making a
+plugin for a forum/wiki/other system, using an external stylesheet is a good idea!). It saves a small amount of code and
+your bandwidth, and it&#8217;s relatively easy to just change the stylesheet should you need to. However, using this will render
+the methods that change the styles of the code useless, because of course the stylesheet is no longer being dynamically
+generated. You can still disable highlighting of certain lexics dynamically, however.</p>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>As of version 1.0.2, <abbr title="Generic Syntax Highlighter">GeSHi</abbr> comes with a <code>contrib/</code> directory, which in it contains a &#8220;wizard&#8221; script for creating
+  a stylesheet. Although this script is by no means a complete solution, it will create the necessary rules for the
+  basic lexics - comments, strings for example. Things not included in the wizard include regular expressions for any
+  language that uses them (<abbr title="PHP: HTML Preprocessor">PHP</abbr> and <abbr title="Extensible Markup Language">XML</abbr> are two languages that use them), and keyword-link styles. However, this script
+  should take some of the tedium out of the job of making an external stylesheet. Expect a much better version of this
+  script in version 1.2!</p>
+
+</div>
+
+<h3 id="changing-styles">3.4 Changing Styles</h3><div class="nav"><a href="#using-an-external-stylesheet">Previous</a> | <a href="#advanced-features">Top</a> | <a href="#the-overall-styles">Next</a></div>
+
+<p>One of the more powerful features of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> is the ability to change the style of the output dynamically. Why be chained
+to the boring styles the language authors make up? You can change almost every single aspect of highlighted code - and
+can even say whether something is to be highlighted at all.</p>
+
+<p>If you&#8217;re confused about &#8220;styles&#8221;, you probably want to have a quick tutorial in them so you know what you can do with
+them. Checkout the homepage of <abbr title="Cascading Style Sheets">CSS</abbr> at <a href="http://www.w3.org/Style/CSS">http://www.w3.org/Style/CSS</a>.</p>
+
+<h4 id="the-overall-styles">3.4.1 The Overall Styles</h4><div class="nav"><a href="#changing-styles">Previous</a> | <a href="#changing-styles">Top</a> | <a href="#line-number-styles">Next</a></div>
+
+<p>The code outputted by <abbr title="Generic Syntax Highlighter">GeSHi</abbr> is either in a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">div</span>&gt;</span></code> or a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">pre</span>&gt;</span></code> (see the section entitled &#8220;The
+Code Container&#8221;), and this can be styled.</p>
+
+<p><code>$geshi-&gt;set_overall_style('... styles ...');</code>
+Where styles is a string containing valid <abbr title="Cascading Style Sheets">CSS</abbr> declarations. By default, these styles overwrite the current styles, but you can change this by adding a second parameter:</p>
+
+<p><code>$geshi-&gt;set_overall_style('color: blue;', true);</code>
+The default styles &#8220;shine through&#8221; wherever anything isn&#8217;t highlighted. Also, you can apply more advanced styles, like position: (fixed|relative) etc, because a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">div</span>&gt;</span></code>/<code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">pre</span>&gt;</span></code> is a block level element.</p>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>Remember that a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">div</span>&gt;</span></code> will by default have a larger font size than a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">pre</span>&gt;</span></code>, as discussed in the section <a href="#the-code-container">&#8220;The Code Container&#8221;</a>.</p>
+
+</div>
+
+<h4 id="line-number-styles">3.4.2 Line Number Styles</h4><div class="nav"><a href="#the-overall-styles">Previous</a> | <a href="#changing-styles">Top</a> | <a href="#setting-keyword-styles">Next</a></div>
+
+<p>You may wish to refer to the section [Styling Line Numbers][1] before reading this section.</p>
+
+<p>As of version 1.0.2, the way line numbers are generated is different, so therefore the way that they are styled is
+different. In particular, now you cannot set the background style of the fancy line numbers to be different from that
+of the normal line numbers.</p>
+
+<p>Line number styles are set by using the method <code class="highlighted php">set_line_style</code>:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_line_style</span><span class="br0">&#40;</span><span class="re0">$style1</span><span class="sy0">,</span> <span class="re0">$style2</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p><code class="highlighted php"><span class="re0">$style1</span></code> is the style of the line numbers by default, and <code class="highlighted php"><span class="re0">$style2</span></code> is the style of the fancy line numbers.</p>
+
+<div class="caution">
+
+<div class="caution-header">Caution:</div>
+
+<p>Things have changed since 1.0.1! This note is <strong>very</strong> important - please make sure you check this twice before
+  complaining about line numbers!</p>
+
+<p>Because of the way that ordered lists are done in <abbr title="Hypertext Markup Language">HTML</abbr>, there really isn&#8217;t normally a way to style the actual
+  <em>numbers</em> in the list. I&#8217;ve cheated somewhat with <abbr title="Generic Syntax Highlighter">GeSHi</abbr> - I&#8217;ve made it possible to use <abbr title="Cascading Style Sheets">CSS</abbr> to style the <em>foreground</em> of
+  the line numbers. So therefore, you can change the color, font size and type, and padding on them. If you want to
+  have a pretty background, you <strong>must</strong> use <code class="highlighted php">set_overall_style<span class="br0">&#40;</span><span class="br0">&#41;</span></code> to do this, and use <code class="highlighted php">set_code_style<span class="br0">&#40;</span><span class="br0">&#41;</span></code>
+  to style the actual code! This is explained in the section above: <a href="#styling-line-numbers">Styling Line Numbers</a>.</p>
+
+<p>In addition, the styles for fancy line numbers <em>is now the difference between the normal styles and the styles you want
+  to achieve</em>. For example, in <abbr title="Generic Syntax Highlighter">GeSHi</abbr> prior to 1.0.2 you may have done this to style line numbers:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_line_style</span><span class="br0">&#40;</span><span class="st_h">'color: red; font-weight: bold;'</span><span class="sy0">,</span> <span class="st_h">'color: green; font-weight: bold'</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Now you instead can do this:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_line_style</span><span class="br0">&#40;</span><span class="st_h">'color: red; font-weight: bold;'</span><span class="sy0">,</span> <span class="st_h">'color: green;'</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>The <code class="highlighted css"><span class="kw1">font-weight</span><span class="sy0">:</span> <span class="kw2">bold</span><span class="sy0">;</span></code> will automatically carry through to the fancy styles. This is actually a small
+  saving in code - but the difference may be confusing for anyone using 1.0.1 at first.</p>
+
+</div>
+
+<h4 id="setting-keyword-styles">3.4.3 Setting Keyword Styles</h4><div class="nav"><a href="#line-number-styles">Previous</a> | <a href="#changing-styles">Top</a> | <a href="#setting-comment-styles">Next</a></div>
+
+<p>Perhaps the most regular change you will make will be to the styles of a keyword set. In order to change the styles for
+a particular set, you&#8217;ll have to know what the set is called first. Sets are numbered from 1 up. Typically, set 1
+contains keywords like <code>if</code>, <code>while</code>, <code>do</code>, <code>for</code>, <code>switch</code> etc, set 2 contains <code>null</code>, <code>false</code>, <code>true</code> etc, set 3
+contains function inbuilt into the language (<code>echo</code>, <code>htmlspecialchars</code> etc. in <abbr title="PHP: HTML Preprocessor">PHP</abbr>) and set 4 contains data types and
+similar variable modifiers: <code>int</code>, <code>double</code>, <code>real</code>, <code>static</code> etc. However these things are not fixed, and you should
+check the language file to see what key you want. Having a familiarity with a language file is definately a plus for
+using it.</p>
+
+<p>To change the styles for a keyword set, call the <code class="highlighted php">set_keyword_group_style<span class="br0">&#40;</span><span class="br0">&#41;</span></code> method:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_keyword_group_style</span><span class="br0">&#40;</span><span class="re0">$group</span><span class="sy0">,</span> <span class="re0">$styles</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Where <code class="highlighted php"><span class="re0">$group</span></code> is the group to change the styles for and <code class="highlighted php"><span class="re0">$styles</span></code> is a string containing the styles
+to apply to that group.</p>
+
+<p>By default, the styles you pass overwrite the current styles. Add a boolean <code class="highlighted php"><span class="kw4">true</span></code> after the styles you specify to
+combine them with the current styles:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_keyword_group_style</span><span class="br0">&#40;</span><span class="nu0">3</span><span class="sy0">,</span> <span class="st_h">'color: white;'</span><span class="sy0">,</span> <span class="kw4">true</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<h4 id="setting-comment-styles">3.4.4 Setting Comment Styles</h4><div class="nav"><a href="#setting-keyword-styles">Previous</a> | <a href="#changing-styles">Top</a> | <a href="#setting-other-styles">Next</a></div>
+
+<p>To change the styles for a comment group, call the <code class="highlighted php">set_comments_style<span class="br0">&#40;</span><span class="br0">&#41;</span></code> method:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_comments_style</span><span class="br0">&#40;</span><span class="re0">$group</span><span class="sy0">,</span> <span class="re0">$styles</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Where <code class="highlighted php"><span class="re0">$group</span></code> is either a number corresponding to a single-line comment, or the string <code class="highlighted php"><span class="st_h">'MULTI'</span></code> to
+specify multiline comments:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span></pre></td><td class="de1"><pre class="de1"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_comments_style</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="sy0">,</span> <span class="st_h">'font-style: italic;'</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_comments_style</span><span class="br0">&#40;</span><span class="st_h">'MULTI'</span><span class="sy0">,</span> <span class="st_h">'display: hidden;'</span><span class="br0">&#41;</span><span class="sy0">;</span></span></span></pre></td></tr></tbody></table>
+
+<p>By default, the styles you pass overwrite the current styles. Add a boolean <code class="highlighted php"><span class="kw4">true</span></code> after the styles you specify to
+combine them with the current styles:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_comments_style</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="sy0">,</span> <span class="st_h">'font-weight: 100;'</span><span class="sy0">,</span> <span class="kw4">true</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>In 1.0.7.22 a new kind of Comments called &#8220;COMMENT_REGEXP&#8221; has been added. Those are handled by setting single
+  line comment styles.</p>
+
+</div>
+
+<h4 id="setting-other-styles">3.4.5 Setting Other Styles</h4><div class="nav"><a href="#setting-comment-styles">Previous</a> | <a href="#changing-styles">Top</a> | <a href="#case-caps">Next</a></div>
+
+<p><abbr title="Generic Syntax Highlighter">GeSHi</abbr> can highlight many other aspects of your source other than just keywords and comments. Strings, Numbers, Methods
+and Brackets among other things can all also be highlighted. Here are the related methods:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+</pre></td><td class="de1"><pre class="de1"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_escape_characters_style</span><span class="br0">&#40;</span><span class="re0">$styles</span><span class="br0">&#91;</span><span class="sy0">,</span> <span class="re0">$preserve_defaults</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_symbols_style</span><span class="br0">&#40;</span><span class="re0">$styles</span><span class="br0">&#91;</span><span class="sy0">,</span> <span class="re0">$preserve_defaults</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></span></span>&nbsp;
+<span class="xtra li2"><span class="de2"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_strings_style</span><span class="br0">&#40;</span><span class="re0">$styles</span><span class="br0">&#91;</span><span class="sy0">,</span> <span class="re0">$preserve_defaults</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></span></span><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_numbers_style</span><span class="br0">&#40;</span><span class="re0">$styles</span><span class="br0">&#91;</span><span class="sy0">,</span> <span class="re0">$preserve_defaults</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_methods_style</span><span class="br0">&#40;</span><span class="re0">$key</span><span class="sy0">,</span> <span class="re0">$styles</span><span class="br0">&#91;</span><span class="sy0">,</span> <span class="re0">$preserve_defaults</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></span></span><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_regexps_style</span><span class="br0">&#40;</span><span class="re0">$key</span><span class="sy0">,</span> <span class="re0">$styles</span><span class="br0">&#91;</span><span class="sy0">,</span> <span class="re0">$preserve_defaults</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></tbody></table>
+
+<p><code class="highlighted php"><span class="re0">$styles</span></code> is a string containing valid stylesheet declarations, while <code class="highlighted php"><span class="re0">$preserve_defaults</span></code> should be set
+to <code class="highlighted php"><span class="kw4">true</span></code> if you want your styles to be merged with the previous styles. In the case of <code class="highlighted php">set_methods_style<span class="br0">&#40;</span><span class="br0">&#41;</span></code>,
+you should select a group to set the styles of, check the language files for the number used for each &#8220;object splitter&#8221;.</p>
+
+<p>Like this was possible for <code class="highlighted php">set_method_style</code> a new parameter has been introduced for
+<code class="highlighted php">set_symbols_style</code> too which allows you to select the group of symbols for which you&#8217;d like to change your
+style. <code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_symbols_style</span><span class="br0">&#40;</span><span class="re0">$styles</span><span class="br0">&#91;</span><span class="sy0">,</span> <span class="re0">$preserve_defaults</span><span class="br0">&#91;</span><span class="sy0">,</span> <span class="re0">$group</span><span class="br0">&#93;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></code> If the third parameter is not
+given, group 0 is assumed. Furthermore you should note that any changes to group 0 are also reflected in the bracket
+style, i.e. a pass-through call to <code class="highlighted php">set_bracket_style</code> is made.</p>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>Since <abbr title="Generic Syntax Highlighter">GeSHi</abbr> 1.0.8 multiple styles for strings and numbers are supported, though the API doesn&#8217;t provide full access yet.</p>
+
+</div>
+
+<h3 id="case-caps">3.5 Case Sensitivity and Auto Casing</h3><div class="nav"><a href="#setting-other-styles">Previous</a> | <a href="#advanced-features">Top</a> | <a href="#auto-caps-nocaps">Next</a></div>
+
+<p>Controlling the case of the outputted source is an easy job with <abbr title="Generic Syntax Highlighter">GeSHi</abbr>. You can control which keywords are converted in
+case, and also control whether keywords are checked in a case sensitive manner.</p>
+
+<h4 id="auto-caps-nocaps">3.5.1 Auto-Caps/NoCaps</h4><div class="nav"><a href="#case-caps">Previous</a> | <a href="#case-caps">Top</a> | <a href="#setting-case-sensitivity">Next</a></div>
+
+<p>Auto-Caps/NoCaps is a nifty little feature that capitalises or lowercases automatically certain lexics when they are
+styled. I dabble in QuickBASIC, a dialect of BASIC which is well known for it&#8217;s capatalisation, and SQL is another
+language well known for using caps for readability.</p>
+
+<p>To change what case lexics are rendered in, you call the <code class="highlighted php">set_case_keywords<span class="br0">&#40;</span><span class="br0">&#41;</span></code> method:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_case_keywords</span><span class="br0">&#40;</span><span class="re0">$caps_modifier</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>The valid values to pass to this method are:</p>
+
+<ul>
+<li><code>GESHI_CAPS_NO_CHANGE</code> - Don&#8217;t change the case of any lexics, leave as they are found</li>
+<li><code>GESHI_CAPS_UPPER</code> - Uppercase all lexics found</li>
+<li><code>GESHI_CAPS_LOWER</code> - Lowercase all lexics found</li>
+</ul>
+
+<div class="caution">
+
+<div class="caution-header">Caution:</div>
+
+<p>When I say &#8220;lexic&#8221;, I mean &#8220;keywords&#8221;. <strong>Any</strong> keyword in <strong>any</strong> keyword array will be modified using this option!
+  This is one small area of inflexibility I hope to fix in 1.2.X.</p>
+
+</div>
+
+<p>I suspect this will only be used to specify <code>GESHI_CAPS_NO_CHANGE</code> to turn off autocaps for languages like SQL
+and BASIC variants, like so:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span></pre></td><td class="de1"><pre class="de1"><span class="re0">$geshi</span> <span class="sy0">=</span> <span class="kw2">new</span> GeSHi<span class="br0">&#40;</span><span class="re0">$source</span><span class="sy0">,</span> <span class="st_h">'sql'</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_case_keywords</span><span class="br0">&#40;</span>GESHI_CAPS_NO_CHANGE<span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// don't want keywords capatalised</span></span></span></pre></td></tr></tbody></table>
+
+<p>All the same, it can be used for some interesting effects:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span></pre></td><td class="de1"><pre class="de1"><span class="re0">$geshi</span> <span class="sy0">=</span> <span class="kw2">new</span> GeSHi<span class="br0">&#40;</span><span class="re0">$source</span><span class="sy0">,</span> <span class="st_h">'java'</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2"><span class="co1">// Anyone who's used java knows how picky it is about CapitalLetters...</span></span></span><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_case_keywords</span><span class="br0">&#40;</span>GESHI_CAPS_LOWER<span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2"><span class="co1">// No *way* the source will look right now ;)</span></span></span></pre></td></tr></tbody></table>
+
+<h4 id="setting-case-sensitivity">3.5.2 Setting Case Sensitivity</h4><div class="nav"><a href="#auto-caps-nocaps">Previous</a> | <a href="#case-caps">Top</a> | <a href="#changing-config">Next</a></div>
+
+<p>Some languages, like <abbr title="PHP: HTML Preprocessor">PHP</abbr>, don&#8217;t mind what case function names and keywords are in, while others, like Java, depend on
+such pickiness to maintain their bad reputations ;). In any event, you can use the <code class="highlighted php">set_case_sensitivity<span class="br0">&#40;</span><span class="br0">&#41;</span></code>
+to change the case sensitiveness of a particular keyword group from the default:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_case_sensitivity</span><span class="br0">&#40;</span><span class="re0">$key</span><span class="sy0">,</span> <span class="re0">$sensitivity</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Where <code class="highlighted php"><span class="re0">$key</span></code> is the key of the group for which you wish to change case sensitivness for (see the language file
+for that language), and <code class="highlighted php"><span class="re0">$sensitivity</span></code> is a boolean value - <code class="highlighted php"><span class="kw4">true</span></code> if the keyword is case sensitive, and
+<code class="highlighted php"><span class="kw4">false</span></code> if not.</p>
+
+<h3 id="changing-config">3.6 Changing the Source, Language, Config Options</h3><div class="nav"><a href="#setting-case-sensitivity">Previous</a> | <a href="#advanced-features">Top</a> | <a href="#changing-the-source">Next</a></div>
+
+<p>What happens if you want to change the source to be highlighted on the fly, or the language. Or if you want to specify
+any of those basic fields after you&#8217;ve created a <abbr title="Generic Syntax Highlighter">GeSHi</abbr> object? Well, that&#8217;s where these methods come in.</p>
+
+<h4 id="changing-the-source">3.6.1 Changing the Source Code</h4><div class="nav"><a href="#changing-config">Previous</a> | <a href="#changing-config">Top</a> | <a href="#changing-the-language">Next</a></div>
+
+<p>To change the source code, you call the <code class="highlighted php">set_source<span class="br0">&#40;</span><span class="br0">&#41;</span></code> method:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_source</span><span class="br0">&#40;</span><span class="re0">$newsource</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Example:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+<span class="xtra li2"><span class="de2">8</span></span></pre></td><td class="de1"><pre class="de1"><span class="re0">$geshi</span> <span class="sy0">=</span> <span class="kw2">new</span> GeSHi<span class="br0">&#40;</span><span class="re0">$source1</span><span class="sy0">,</span> <span class="st_h">'php'</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="co1">// Method calls to specify various options...</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="re0">$code1</span> <span class="sy0">=</span> <span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">parse_code</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_source</span><span class="br0">&#40;</span><span class="re0">$source2</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2"><span class="re0">$code2</span> <span class="sy0">=</span> <span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">parse_code</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></span></span></pre></td></tr></tbody></table>
+
+<h4 id="changing-the-language">3.6.2 Changing the Language</h4><div class="nav"><a href="#changing-the-source">Previous</a> | <a href="#changing-config">Top</a> | <a href="#changing-the-path">Next</a></div>
+
+<p>What happens if you want to change the language used for highlighting? Just call <code class="highlighted php">set_language<span class="br0">&#40;</span><span class="br0">&#41;</span></code>:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_language</span><span class="br0">&#40;</span><span class="st_h">'newlanguage'</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Example:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+<span class="xtra li2"><span class="de2">8</span></span>9
+<span class="xtra li2"><span class="de2">10</span></span></pre></td><td class="de1"><pre class="de1"><span class="re0">$geshi</span> <span class="sy0">=</span> <span class="kw2">new</span> GeSHi<span class="br0">&#40;</span><span class="re0">$source</span><span class="sy0">,</span> <span class="st_h">'php'</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="re0">$code</span> <span class="sy0">=</span> <span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">parse_code</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="co1">// Highlight GeSHi's output</span>
+<span class="xtra li2"><span class="de2"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_source</span><span class="br0">&#40;</span><span class="re0">$code</span><span class="br0">&#41;</span><span class="sy0">;</span></span></span>&nbsp;
+<span class="xtra li2"><span class="de2"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_language</span><span class="br0">&#40;</span><span class="st_h">'html4strict'</span><span class="br0">&#41;</span><span class="sy0">;</span></span></span><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">enable_classes</span><span class="br0">&#40;</span><span class="kw4">false</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2"><span class="kw1">echo</span> <span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">parse_code</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></span></span></pre></td></tr></tbody></table>
+
+<p>As of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> 1.0.5, you can use the method <code class="highlighted php">load_from_file<span class="br0">&#40;</span><span class="br0">&#41;</span></code> to load the source code and language from a file.
+Simply pass this method a file name and it will attempt to load the source and set the language.</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">load_from_file</span><span class="br0">&#40;</span><span class="re0">$file_name</span><span class="sy0">,</span> <span class="re0">$lookup</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p><code class="highlighted php"><span class="re0">$file_name</span></code> is the file name to use, and <code class="highlighted php"><span class="re0">$lookup</span></code> is an optional parameter that contains a lookup
+array to use for deciding which language to choose. You can use this to override <abbr title="Generic Syntax Highlighter">GeSHi</abbr>&#8217;s default lookup array, which
+may not contain the extension of the file you&#8217;re after, or perhaps does have your extension but under a different
+language. The lookup array is of the form:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span></pre></td><td class="de1"><pre class="de1"><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp;<span class="st_h">'lang_name'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'extension'</span><span class="sy0">,</span> <span class="st_h">'extension'</span><span class="sy0">,</span> <span class="sy0">...</span><span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp;<span class="st_h">'lang_name'</span> <span class="sy0">...</span>
+<span class="xtra li2"><span class="de2"><span class="br0">&#41;</span><span class="sy0">;</span></span></span></pre></td></tr></tbody></table>
+
+<p>Also, you can use the method <code class="highlighted php">get_language_name_from_extension<span class="br0">&#40;</span><span class="br0">&#41;</span></code> if you need to convert a file extension
+to a valid language name. This method will return the empty string if it could not find a match in the lookup, and
+like <code class="highlighted php">load_from_file</code> it accepts an optional second parameter that contains a lookup array.</p>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>Names are case-insensitive - they will be converted to lower case to match a language file however. So if you&#8217;re
+  making a language file, remember it should have a name in lower case.</p>
+
+</div>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>What you pass to this method is the name of a language file, minus the .php extension. If you&#8217;re writing a plugin
+  for a particular application, it&#8217;s up to you to somehow convert user input into a valid language name.</p>
+
+</div>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>Since <abbr title="Generic Syntax Highlighter">GeSHi</abbr> 1.0.8 this function does not reset language settings for an already loaded language. If you want
+  to highlight code in the same language with different settings add the optional
+  <code class="highlighted php"><span class="re0">$force_reset</span> parameter</code>:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_language</span><span class="br0">&#40;</span><span class="st_h">'language'</span><span class="sy0">,</span> <span class="kw4">true</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+</div>
+
+<div class="caution">
+
+<div class="caution-header">Caution:</div>
+
+<p><abbr title="Generic Syntax Highlighter">GeSHi</abbr> <code class="highlighted php"><span class="kw1">include</span><span class="br0">&#40;</span><span class="br0">&#41;</span></code>s the language file, so be careful to make sure that users can&#8217;t pass some wierd
+  language name to include any old script! <abbr title="Generic Syntax Highlighter">GeSHi</abbr> tries to strip non-valid characters out of a language name, but
+  you should always do this your self anyway. In particular, language files are always lower-case, with either
+  alphanumeric characters, dashes or underscores in their name.</p>
+
+<p>At the very least, strip &#8220;/&#8221; characters out of a language name.</p>
+
+</div>
+
+<h4 id="changing-the-path">3.6.3 Changing the Language Path</h4><div class="nav"><a href="#changing-the-language">Previous</a> | <a href="#changing-config">Top</a> | <a href="#changing-the-charset">Next</a></div>
+
+<p>What happens if all of a sudden you want to use language files from a different directory from the current
+language file location? You call the <code class="highlighted php">set_language_path<span class="br0">&#40;</span><span class="br0">&#41;</span></code> method:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_language_path</span><span class="br0">&#40;</span><span class="re0">$newpath</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>It doesn&#8217;t matter whether the path has a trailing slash after it or not - only that it points to a valid folder.
+If it doesn&#8217;t, that&#8217;s your tough luck ;)</p>
+
+<h4 id="changing-the-charset">3.6.4 Changing the Character Set</h4><div class="nav"><a href="#changing-the-path">Previous</a> | <a href="#changing-config">Top</a> | <a href="#error-handling">Next</a></div>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>Although <abbr title="Generic Syntax Highlighter">GeSHi</abbr> itself does not require to know the exact charset of your source you
+  will need to set this option when processing sources where multi-byte characters can occur.
+  As of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> 1.0.7.18 internally a rewrite of <code class="highlighted php"><span class="kw3">htmlspecialchars</span></code> is used
+  due to a security flaw in that function that is unpatched in even the most recent PHP4 versions and in PHP5 &lt; 5.2.
+  Although this does no longer explicitely require the charset it is required again
+  as of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> 1.0.8 to properly handle multi-byte characters (e.g. after an escape char).</p>
+
+</div>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>As of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> 1.0.8 the default charset has been changed to UTF-8.</p>
+
+</div>
+
+<p>As of version 1.0.3, you can use the method <code class="highlighted php">set_encoding<span class="br0">&#40;</span><span class="br0">&#41;</span></code> to specify the character set that your source
+is in. Valid names are those names that are valid for the <abbr title="PHP: HTML Preprocessor">PHP</abbr> mbstring library:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_encoding</span><span class="br0">&#40;</span><span class="re0">$encoding</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>There is a table of valid strings for <code class="highlighted php"><span class="re0">$encoding</span></code> at the php.net manual linked to above. If you do not
+specify an encoding, or specify an invalid encoding, the character set used is ISO-8859-1.</p>
+
+<h3 id="error-handling">3.7 Error Handling</h3><div class="nav"><a href="#changing-the-charset">Previous</a> | <a href="#advanced-features">Top</a> | <a href="#disabling-lexics">Next</a></div>
+
+<p>What happens if you try to highlight using a language that doesn&#8217;t exist? Or if <abbr title="Generic Syntax Highlighter">GeSHi</abbr> can&#8217;t read a required file?
+The results you get may be confusing. You may check your code over and over, and never find anything wrong. <abbr title="Generic Syntax Highlighter">GeSHi</abbr>
+provides ways of finding out if <abbr title="Generic Syntax Highlighter">GeSHi</abbr> itself found anything wrong with what you tried to do. After highlighting,
+you can call the <code class="highlighted php">error<span class="br0">&#40;</span><span class="br0">&#41;</span></code> method:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span> <span class="sy0">=</span> <span class="kw2">new</span> GeSHi<span class="br0">&#40;</span><span class="st_h">'hi'</span><span class="sy0">,</span> <span class="st_h">'thisLangIsNotSupported'</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p><code class="highlighted php"><span class="kw1">echo</span> <span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">error</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// echoes error message</span></code></p>
+
+<p>The error message you will get will look like this:</p>
+
+<blockquote>
+  <p><abbr title="Generic Syntax Highlighter">GeSHi</abbr> Error: <abbr title="Generic Syntax Highlighter">GeSHi</abbr> could not find the language thisLangIsNotSupported (using path geshi/) (code 2)</p>
+</blockquote>
+
+<p>The error outputted will be the last error <abbr title="Generic Syntax Highlighter">GeSHi</abbr> came across, just like how <code class="highlighted php"><span class="kw3">mysql_error</span><span class="br0">&#40;</span><span class="br0">&#41;</span></code> works.</p>
+
+<h3 id="disabling-lexics">3.8 Disabling styling of some Lexics</h3><div class="nav"><a href="#error-handling">Previous</a> | <a href="#advanced-features">Top</a> | <a href="#setting-tab-width">Next</a></div>
+
+<p>One disadvantage of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> is that for large source files using complex languages, it can be quite slow with
+every option turned on. Although future releases will concentrate on the speed/resource side of highlighting,
+you can gain speed by disabling some of the highlighting options. This is done by using a
+series of <code class="highlighted php">set_<span class="sy0">*</span>_highlighting</code> methods:</p>
+
+<dl>
+<dt><code class="highlighted php">set_keyword_group_highlighting<span class="br0">&#40;</span><span class="re0">$group</span><span class="sy0">,</span> <span class="re0">$flag</span><span class="br0">&#41;</span><span class="sy0">:</span></code></dt>
+<dd>Sets whether a particular <code class="highlighted php"><span class="re0">$group</span></code> of keywords is to be highlighted or not. Consult the necessary
+language file(s) to see what <code class="highlighted php"><span class="re0">$group</span></code> should be for each group (typically a positive integer).
+<code class="highlighted php"><span class="re0">$flag</span></code> is <code class="highlighted php"><span class="kw4">false</span></code> if you want to disable highlighting of this group, and <code class="highlighted php"><span class="kw4">true</span></code> if you want
+to re-enable higlighting of this group. If you disable a keyword group then even if the keyword group has a
+related URL one will not be generated for that keyword.</dd>
+
+<dt><code class="highlighted php">set_comments_highlighting<span class="br0">&#40;</span><span class="re0">$group</span><span class="sy0">,</span> <span class="re0">$flag</span><span class="br0">&#41;</span><span class="sy0">:</span></code></dt>
+<dd>Sets whether a particular <code class="highlighted php"><span class="re0">$group</span></code> of comments is to be highlighted or not. Consult the necessary
+language file(s) to see what <code class="highlighted php"><span class="re0">$group</span></code> should be for each group (typically a positive integer, or th
+string <code class="highlighted php"><span class="st_h">'MULTI'</span></code> for multiline comments. <code class="highlighted php"><span class="re0">$flag</span></code> is <code class="highlighted php"><span class="kw4">false</span></code> if you want to disable
+highlighting of this group, and <code class="highlighted php"><span class="kw4">true</span></code> if you want to re-enable highlighting of this group.</dd>
+
+<dt><code class="highlighted php">set_regexps_highlighting<span class="br0">&#40;</span><span class="re0">$regexp</span><span class="sy0">,</span> <span class="re0">$flag</span><span class="br0">&#41;</span><span class="sy0">:</span></code></dt>
+<dd>Sets whether a particular <code class="highlighted php"><span class="re0">$regexp</span></code> is to be highlighted or not. Consult the necessary language file(s)
+to see what <code class="highlighted php"><span class="re0">$regexp</span></code> should be for each regexp (typically a positive integer, or the string <code class="highlighted php"><span class="st_h">'MULTI'</span></code>
+for multiline comments. <code class="highlighted php"><span class="re0">$flag</span></code> is <code class="highlighted php"><span class="kw4">false</span></code> if you want to disable highlighting of this group,
+and <code class="highlighted php"><span class="kw4">true</span></code> if you want to re-enable highlighting of this group.</dd>
+</dl>
+
+<p>The following methods:</p>
+
+<ul>
+<li><code class="highlighted php">set_escape_characters_highlighting<span class="br0">&#40;</span><span class="re0">$flag</span><span class="br0">&#41;</span></code></li>
+<li><code class="highlighted php">set_symbols_highlighting<span class="br0">&#40;</span><span class="re0">$flag</span><span class="br0">&#41;</span></code></li>
+<li><code class="highlighted php">set_strings_highlighting<span class="br0">&#40;</span><span class="re0">$flag</span><span class="br0">&#41;</span></code></li>
+<li><code class="highlighted php">set_numbers_highlighting<span class="br0">&#40;</span><span class="re0">$flag</span><span class="br0">&#41;</span></code></li>
+<li><code class="highlighted php">set_methods_highlighting<span class="br0">&#40;</span><span class="re0">$flag</span><span class="br0">&#41;</span></code></li>
+</ul>
+
+<p>Work on their respective lexics (e.g. <code class="highlighted php">set_methods_highlighting<span class="br0">&#40;</span><span class="br0">&#41;</span></code> will disable/enable highlighting of methods).
+For each method, if <code class="highlighted php"><span class="re0">$flag</span></code> is <code class="highlighted php"><span class="kw4">false</span></code> then the related lexics will not be highlighted at all (this
+means no <abbr title="Hypertext Markup Language">HTML</abbr> will surround the lexic like usual, saving on time and bandwidth.</p>
+
+<p>In case all highlighting should be disabled or reenabled <abbr title="Generic Syntax Highlighter">GeSHi</abbr> provides two methods called <code class="highlighted php">disable_highlighting<span class="br0">&#40;</span><span class="br0">&#41;</span></code>
+and <code class="highlighted php">enable_highlighting<span class="br0">&#40;</span><span class="re0">$flag</span><span class="br0">&#41;</span></code>. The optional paramter <code class="highlighted php"><span class="re0">$flag</span></code> has been added in 1.0.7.21 and specifies
+the desired state, i.e. <code class="highlighted php"><span class="kw4">true</span></code> (default) to turn all highlighting on, or <code class="highlighted php"><span class="kw4">false</span></code> to turn all
+highlighting off. Since 1.0.7.21 the method <code class="highlighted php">disnable_highlighting<span class="br0">&#40;</span><span class="br0">&#41;</span></code> has become deprecated.</p>
+
+<h3 id="setting-tab-width">3.9 Setting the Tab Width</h3><div class="nav"><a href="#disabling-lexics">Previous</a> | <a href="#advanced-features">Top</a> | <a href="#using-strict-mode">Next</a></div>
+
+<p>If you&#8217;re using the <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">pre</span>&gt;</span></code> header, tabs are handled automatically by your browser, and in general you can
+count on good results. However, if you&#8217;re using the <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">div</span>&gt;</span></code> header, you may want to specify a tab
+width explicitly.</p>
+
+<p>Note that tabs created in this fashion won&#8217;t be like normal tabs - there won&#8217;t be &#8220;tab-stops&#8221; as such, instead
+tabs will be replaced with the specified number of spaces - just like most editors do.</p>
+
+<p>To change the tab width, you call the <code class="highlighted php">set_tab_width<span class="br0">&#40;</span><span class="br0">&#41;</span></code> method:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_tab_width</span><span class="br0">&#40;</span><span class="re0">$width</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Where <code class="highlighted php"><span class="re0">$width</span></code> is the width in spaces that you&#8217;d like tabs to be.</p>
+
+<h3 id="using-strict-mode">3.10 Using Strict Mode</h3><div class="nav"><a href="#setting-tab-width">Previous</a> | <a href="#advanced-features">Top</a> | <a href="#adding-removing-keywords">Next</a></div>
+
+<p>Some languages like to get tricky, and jump in and out of the file that they&#8217;re in. For example, the vast
+majority of you reading this will have used a <abbr title="PHP: HTML Preprocessor">PHP</abbr> file. And you know that <abbr title="PHP: HTML Preprocessor">PHP</abbr> code is only executed if it&#8217;s
+within delimiters like <code class="highlighted php"><span class="kw2">&lt;?php</span></code> and <code class="highlighted php"><span class="sy1">?&gt;</span></code> (there are others of course&#8230;). So what happens if you do the
+following in a php file?</p>
+
+<p><code class="highlighted php">&lt;img src=&quot;<span class="kw2">&lt;?php</span> <span class="kw1">echo</span> <span class="kw3">rand</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="sy0">,</span> <span class="nu0">100</span><span class="br0">&#41;</span> <span class="sy1">?&gt;</span>&quot; /&gt;</code></p>
+
+<p>When using <abbr title="Generic Syntax Highlighter">GeSHi</abbr> without strict mode, or using a bad highlighter, you&#8217;ll end up with scrambled crap,
+especially if you&#8217;re being slack about where you&#8217;re putting your quotes, you could end up with the rest
+of your file as bright blue. Fortunately, you can tell <abbr title="Generic Syntax Highlighter">GeSHi</abbr> to be &#8220;strict&#8221; about just when it highlights
+and when it does not, using the <code class="highlighted php">enable_strict_mode<span class="br0">&#40;</span><span class="br0">&#41;</span></code> method:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">enable_strict_mode</span><span class="br0">&#40;</span><span class="re0">$mode</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Where <code class="highlighted php"><span class="re0">$mode</span></code> is <code class="highlighted php"><span class="kw4">true</span></code> or not specified to enable strict mode, or <code class="highlighted php"><span class="kw4">false</span></code> to disable
+strict mode if you&#8217;ve already turned it and don&#8217;t want it now.</p>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>As of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> 1.0.8 there is a new way to tell <abbr title="Generic Syntax Highlighter">GeSHi</abbr> when to use Strict Mode
+  which is somewhat more intelligent than in previous releases. <abbr title="Generic Syntax Highlighter">GeSHi</abbr> now also
+  allows <code class="highlighted php">GESHI_MAYBE</code>, <code class="highlighted php">GESHI_NEVER</code> and <code class="highlighted php">GESHI_ALWAYS</code> instead of <code class="highlighted php"><span class="kw4">true</span></code> and <code class="highlighted php"><span class="kw4">false</span></code>.
+  Basically <code class="highlighted php">GESHI_ALWAYS</code> (<code class="highlighted php"><span class="kw4">true</span></code>) always enables strict mode,
+  whereas <code class="highlighted php">GESHI_NEVER</code> (<code class="highlighted php"><span class="kw4">false</span></code>) completely disables strict mode. The new thing is
+  <code class="highlighted php">GESHI_MAYBE</code> which enables strict mode if it finds any sequences of code
+  that look like strict block delimiters.</p>
+
+<p>By the way: That&#8217;s why this section had to be changed, as the new documentation
+  tool we now use, applies this feature and thus auto-detects when strict mode has to be used&#8230;</p>
+
+</div>
+
+<h3 id="adding-removing-keywords">3.11 Adding/Removing Keywords</h3><div class="nav"><a href="#using-strict-mode">Previous</a> | <a href="#advanced-features">Top</a> | <a href="#adding-a-keyword">Next</a></div>
+
+<p>Lets say that you&#8217;re working on a large project, with many files, many classes and many functions. Perhaps also you
+have the source code on the web and highlighted by <abbr title="Generic Syntax Highlighter">GeSHi</abbr>, perhaps as a front end to CVS, as a learning tool, something
+to refer to, whatever. Well, why not highlight the names of the functions and classes <em>your</em> project uses, as well
+as the standard functions and classes? Or perhaps you&#8217;re not interested in highlighting certain functions, and would
+like to remove them? Or maybe you don&#8217;t mind if an entire function group goes west in the interest of speed? <abbr title="Generic Syntax Highlighter">GeSHi</abbr>
+can handle all of this!</p>
+
+<h4 id="adding-a-keyword">3.11.1 Adding a Keyword</h4><div class="nav"><a href="#adding-removing-keywords">Previous</a> | <a href="#adding-removing-keywords">Top</a> | <a href="#removing-a-keyword">Next</a></div>
+
+<p>If you want to add a keyword to an existing keyword group, you use the <code class="highlighted php">add_keyword</code> method:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">add_keyword</span><span class="br0">&#40;</span><span class="re0">$key</span><span class="sy0">,</span> <span class="re0">$word</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Where <code class="highlighted php"><span class="re0">$key</span></code> is the index of the group of keywords you want to add this keyword to, and <code class="highlighted php"><span class="re0">$word</span></code> is
+the word to add.</p>
+
+<p>This implies knowledge of the language file to know the correct index.</p>
+
+<h4 id="removing-a-keyword">3.11.2 Removing a Keyword</h4><div class="nav"><a href="#adding-a-keyword">Previous</a> | <a href="#adding-removing-keywords">Top</a> | <a href="#adding-a-keyword-group">Next</a></div>
+
+<p>Perhaps you want to remove a keyword from an existing group. Maybe you don&#8217;t use it and want to save yourself some time. Whatever the reason, you can remove it using the <code class="highlighted php">remove_keyword</code> method:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">remove_keyword</span><span class="br0">&#40;</span><span class="re0">$key</span><span class="sy0">,</span> <span class="re0">$word</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Where <code class="highlighted php"><span class="re0">$key</span></code> is the index of the group of keywords that you want to remove this keyword from, and
+<code class="highlighted php"><span class="re0">$word</span></code> is the word to remove.</p>
+
+<p>This implies knowledge of the language file to know the correct index - most of the time the keywords you&#8217;ll
+want to remove will be in group 3, but this is not guaranteed and you should check the language file first.</p>
+
+<p>This function is silent - if the keyword is not in the group you specified, nothing awful will happen ;)</p>
+
+<h4 id="adding-a-keyword-group">3.11.3 Adding a Keyword Group</h4><div class="nav"><a href="#removing-a-keyword">Previous</a> | <a href="#adding-removing-keywords">Top</a> | <a href="#removing-a-keyword-group">Next</a></div>
+
+<p>Lets say for your big project you have several main functions and classes that you&#8217;d like highlighted. Why not
+add them as their own group instead of having them highlighted the same way as other keywords? Then you can make
+them stand out, and people can instantly see which functions and classes are user defined or inbuilt. Furthermore,
+you could set the URL for this group to point at the API documentation of your project.</p>
+
+<p>You add a keyword group by using the <code class="highlighted php">add_keyword_group</code> method:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">add_keyword_group</span><span class="br0">&#40;</span><span class="re0">$key</span><span class="sy0">,</span> <span class="re0">$styles</span><span class="sy0">,</span> <span class="re0">$case_sensitive</span><span class="sy0">,</span> <span class="re0">$words</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Where <code class="highlighted php"><span class="re0">$key</span></code> is the key that you want to use to refer to this group, <code class="highlighted php"><span class="re0">$styles</span></code> is the styles that
+you want to use to style this group, <code class="highlighted php"><span class="re0">$case_sensitive</span></code> is <strong>true</strong> or <strong>false</strong> depending on whether you want
+this group of keywords to be case sensitive or not and <code class="highlighted php"><span class="re0">$words</span></code> is an array of words (or a string) of which
+words to add to this group. For example:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">add_keyword_group</span><span class="br0">&#40;</span><span class="nu0">10</span><span class="sy0">,</span> <span class="st_h">'color: #600000;'</span><span class="sy0">,</span> <span class="kw4">false</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st_h">'myfunc_1'</span><span class="sy0">,</span> <span class="st_h">'myfunc_2'</span><span class="sy0">,</span> <span class="st_h">'myfunc_3'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Adds a keyword group referenced by index 10, of which all keywords in the group will be dark red, each keyword
+can be in any case and which contains the keywords &#8220;myfunc_1&#8221;, &#8220;myfunc_2&#8221; and &#8220;myfunc_3&#8221;.</p>
+
+<p>After creating such a keyword group, you may call other <abbr title="Generic Syntax Highlighter">GeSHi</abbr> methods on it, just as you would for any other keyword group.</p>
+
+<div class="caution">
+
+<div class="caution-header">Caution:</div>
+
+<p>If you specify a <code class="highlighted php"><span class="re0">$key</span></code> for which there is already a keyword group, the old keyword group will be
+  overwritten! Most language files don&#8217;t use numbers larger than 5, so I recommend you play it safe and use a number
+  like 10 or 42.</p>
+
+</div>
+
+<h4 id="removing-a-keyword-group">3.11.4 Removing a Keyword Group</h4><div class="nav"><a href="#adding-a-keyword-group">Previous</a> | <a href="#adding-removing-keywords">Top</a> | <a href="#headers-and-footers">Next</a></div>
+
+<p>Perhaps you <em>really</em> need speed? Why not just remove an entire keyword group? <abbr title="Generic Syntax Highlighter">GeSHi</abbr> won&#8217;t have to loop through
+each keyword checking for its existance, saving much time. You remove a keyword group by using the
+<code class="highlighted php">remove_keyword_group</code> method:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">remove_keyword_group</span><span class="br0">&#40;</span><span class="re0">$key</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Where <code class="highlighted php"><span class="re0">$key</span></code> is the key of the group you wish to remove. This implies knowleged of the language file.</p>
+
+<h3 id="headers-and-footers">3.12 Headers and Footers for Your Code</h3><div class="nav"><a href="#removing-a-keyword-group">Previous</a> | <a href="#advanced-features">Top</a> | <a href="#keyword-substitution">Next</a></div>
+
+<p>So you want to add some special information to the highlighted source? <abbr title="Generic Syntax Highlighter">GeSHi</abbr> can do that too! You can specify headers
+and footers for your code, style them, and insert information from the highlighted source into your header or footer.</p>
+
+<h4 id="keyword-substitution">3.12.1 Keyword Substitution</h4><div class="nav"><a href="#headers-and-footers">Previous</a> | <a href="#headers-and-footers">Top</a> | <a href="#setting-header-content">Next</a></div>
+
+<p>In your header and footer, you can put special keywords that will be replaced with actual configuration values for
+this <abbr title="Generic Syntax Highlighter">GeSHi</abbr> object. The keywords you can use are:</p>
+
+<ul>
+<li><strong><code>&lt;TIME&gt;</code></strong> or <strong><code>{TIME}</code></strong>: Is replaced by the time it took for the <code class="highlighted php">parse_code<span class="br0">&#40;</span><span class="br0">&#41;</span></code> method - i.e.,
+how long it took for your code to be highlighted. The time is returned to three decimal places.</li>
+<li><strong><code>&lt;LANGUAGE&gt;</code></strong> or <strong><code>{LANGUAGE}</code></strong>: Is replaced by a nice, friendly version of the language name used to
+highlight this code.</li>
+<li><strong><code>&lt;SPEED&gt;</code></strong> or <strong><code>{SPEED}</code></strong>: Is replaced by the speed at which your source has been processed.</li>
+<li><strong><code>&lt;VERSION&gt;</code></strong> or <strong><code>{VERSION}</code></strong>: The <abbr title="Generic Syntax Highlighter">GeSHi</abbr> version used to highlight the code.</li>
+</ul>
+
+<h4 id="setting-header-content">3.12.2 Setting Header Content</h4><div class="nav"><a href="#keyword-substitution">Previous</a> | <a href="#headers-and-footers">Top</a> | <a href="#setting-footer-content">Next</a></div>
+
+<p>The header for your code is a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">div</span>&gt;</span></code>, which is inside the containing block. Therefore, it is affected by
+the method <code class="highlighted php">set_overall_style</code>, and should contain the sort of <abbr title="Hypertext Markup Language">HTML</abbr> that belongs in a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">div</span>&gt;</span></code>.
+You may use any <abbr title="Hypertext Markup Language">HTML</abbr> you like, and format it as an <abbr title="Hypertext Markup Language">HTML</abbr> document. You should use valid <abbr title="Hypertext Markup Language">HTML</abbr> - convert to entities
+any quotemarks or angle brackets you want displayed. You set the header content using the method
+<code class="highlighted php">set_header_content<span class="br0">&#40;</span><span class="br0">&#41;</span></code>:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_header_content</span><span class="br0">&#40;</span><span class="re0">$content</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Where <code class="highlighted php"><span class="re0">$content</span></code> is the <abbr title="Hypertext Markup Language">HTML</abbr> you want to use for the header.</p>
+
+<h4 id="setting-footer-content">3.12.3 Setting Footer Content</h4><div class="nav"><a href="#setting-header-content">Previous</a> | <a href="#headers-and-footers">Top</a> | <a href="#styling-header-content">Next</a></div>
+
+<p>The footer for your code is a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">div</span>&gt;</span></code>, which is inside the containing block. Therefore, it is affected by
+the method <code class="highlighted php">set_overall_style</code>, and should contain the sort of <abbr title="Hypertext Markup Language">HTML</abbr> that belongs in a <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">div</span>&gt;</span></code>.
+You may use any <abbr title="Hypertext Markup Language">HTML</abbr> you like, and format it as an <abbr title="Hypertext Markup Language">HTML</abbr> document. You should use valid <abbr title="Hypertext Markup Language">HTML</abbr> - convert to entities
+any quotemarks or angle brackets you want displayed. You set the footer content using the method
+<code class="highlighted php">set_footer_content<span class="br0">&#40;</span><span class="br0">&#41;</span></code>:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_footer_content</span><span class="br0">&#40;</span><span class="re0">$content</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Where <code class="highlighted php"><span class="re0">$content</span></code> is the <abbr title="Hypertext Markup Language">HTML</abbr> you want to use for the footer.</p>
+
+<h4 id="styling-header-content">3.12.4 Styling Header Content</h4><div class="nav"><a href="#setting-footer-content">Previous</a> | <a href="#headers-and-footers">Top</a> | <a href="#styling-footer-content">Next</a></div>
+
+<p>You can apply styles to the header content you have set with the <code class="highlighted php">set_header_content_style</code>:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_header_content_style</span><span class="br0">&#40;</span><span class="re0">$styles</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Where <code class="highlighted php"><span class="re0">$styles</span></code> is the stylesheet declarations you want to use to style the header content.</p>
+
+<h4 id="styling-footer-content">3.12.5 Styling Footer Content</h4><div class="nav"><a href="#styling-header-content">Previous</a> | <a href="#headers-and-footers">Top</a> | <a href="#keyword-urls">Next</a></div>
+
+<p>You can apply styles to the footer content you have set with the <code class="highlighted php">set_footer_content_style</code>:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_footer_content_style</span><span class="br0">&#40;</span><span class="re0">$styles</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Where <code class="highlighted php"><span class="re0">$styles</span></code> is the stylesheet declarations you want to use to style the footer content.</p>
+
+<h3 id="keyword-urls">3.13 Keyword URLs</h3><div class="nav"><a href="#styling-footer-content">Previous</a> | <a href="#advanced-features">Top</a> | <a href="#setting-a-url">Next</a></div>
+
+<p>As of version 1.0.2, <abbr title="Generic Syntax Highlighter">GeSHi</abbr> allows you to specify a URL for keyword groups. This URL is used by <abbr title="Generic Syntax Highlighter">GeSHi</abbr> to convert
+the keywords in that group into URLs to appropriate documentation. And using <code class="highlighted php">add_keyword_group</code> you
+can add functions and classes from your own projects and use the URL functionality to provide a link to your
+own API documentation.</p>
+
+<h4 id="setting-a-url">3.13.1 Setting a URL for a Keyword Group</h4><div class="nav"><a href="#keyword-urls">Previous</a> | <a href="#keyword-urls">Top</a> | <a href="#disabling-urls">Next</a></div>
+
+<p>To set the URL to be used for a keyword group, you use the <code class="highlighted php">set_url_for_keyword_group<span class="br0">&#40;</span><span class="br0">&#41;</span></code> method:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_url_for_keyword_group</span><span class="br0">&#40;</span><span class="re0">$group</span><span class="sy0">,</span> <span class="re0">$url</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Where <code class="highlighted php"><span class="re0">$group</span></code> is the keyword group you want to assign the URL for, and <code class="highlighted php"><span class="re0">$url</span></code> is the URL for
+this group of keywords.</p>
+
+<p>You may be wondering how to make each keyword in the group point to the correct URL. You do this by putting
+<code>{FNAME}</code> in the URL at the correct place. For example, <abbr title="PHP: HTML Preprocessor">PHP</abbr> makes it easy by linking <code>www.php.net/function-name</code>
+to the documentation for that function, so the URL used is <code>http://www.php.net/{FNAME}</code>.</p>
+
+<p>Of course, when you get to a language like Java, that puts its class documentation in related folders, it gets a
+little trickier to work out an appropriate URL (see the Java language file!). I hope to provide some kind of
+redirection service at the <abbr title="Generic Syntax Highlighter">GeSHi</abbr> website in the future.</p>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>As of Version 1.0.7.21 there have been added two more symbols you can use to link to functions. <code>{FNAMEL}</code>
+  will generate the lowercase version of the keyword, <code>{FNAMEU}</code> will generate the uppercase version. <code>{FNAME}</code>
+  will provide the keyword as specified in the language file. <strong>Use one of these more specific placeholders
+  if possible</strong>, as they result in less overhead while linking for case insensitive languages.</p>
+
+</div>
+
+<h4 id="disabling-urls">3.13.2 Disabling a URL for a Keyword Group</h4><div class="nav"><a href="#setting-a-url">Previous</a> | <a href="#keyword-urls">Top</a> | <a href="#disabling-all-urls">Next</a></div>
+
+<p>It&#8217;s easy to disable a URL for a keyword group: Simply use the method <code class="highlighted php">set_url_for_keyword_group<span class="br0">&#40;</span><span class="br0">&#41;</span></code> to pass
+an empty string as the URL:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_url_for_keyword_group</span><span class="br0">&#40;</span><span class="re0">$group</span><span class="sy0">,</span> <span class="st_h">''</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<h4 id="disabling-all-urls">3.13.3 Disabling all URLs for Keywords</h4><div class="nav"><a href="#disabling-urls">Previous</a> | <a href="#keyword-urls">Top</a> | <a href="#styling-links">Next</a></div>
+
+<p>As of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> 1.0.7.18, you can disable all URL linking for keywords:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">enable_keyword_links</span><span class="br0">&#40;</span><span class="kw4">false</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<h4 id="styling-links">3.13.4 Styling Links</h4><div class="nav"><a href="#disabling-all-urls">Previous</a> | <a href="#keyword-urls">Top</a> | <a href="#using-targets">Next</a></div>
+
+<p>You can also style the function links. You can style their default status, hovered, active and visited status.
+All of this is controlled by one method, <code class="highlighted php">set_link_styles<span class="br0">&#40;</span><span class="br0">&#41;</span></code>:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_link_styles</span><span class="br0">&#40;</span><span class="re0">$mode</span><span class="sy0">,</span> <span class="re0">$styles</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Where <code class="highlighted php"><span class="re0">$mode</span></code> is one of four values:</p>
+
+<ul>
+<li><strong><code class="highlighted php">GESHI_LINK</code>:</strong> The default style of the links.</li>
+<li><strong><code class="highlighted php">GESHI_HOVER</code>:</strong> The style of the links when they have focus (the mouse is hovering over them).</li>
+<li><strong><code class="highlighted php">GESHI_ACTIVE</code>:</strong> The style of the links when they are being clicked.</li>
+<li><strong><code class="highlighted php">GESHI_VISITED</code>:</strong> The style of links that the user has already visited.</li>
+</ul>
+
+<p>And <code class="highlighted php"><span class="re0">$styles</span></code> is the stylesheet declarations to apply to the links.</p>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>The names <code class="highlighted php">GESHI_LINK</code>, <code class="highlighted php">GESHI_HOVER</code> &#8230; are constants. Don&#8217;t put them in quotes!</p>
+
+</div>
+
+<h4 id="using-targets">3.13.5 Setting the Link Target</h4><div class="nav"><a href="#styling-links">Previous</a> | <a href="#keyword-urls">Top</a> | <a href="#using-contextual-importance">Next</a></div>
+
+<p>Perhaps you want to set the target of link attributes, so the manual pages open in a new window? Use the
+<code class="highlighted php">set_link_target<span class="br0">&#40;</span><span class="br0">&#41;</span></code> method:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_link_target</span><span class="br0">&#40;</span><span class="re0">$target</span><span class="sy0">,</span> <span class="re0">$styles</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Where <code class="highlighted php"><span class="re0">$target</span></code> is any valid (X)<abbr title="Hypertext Markup Language">HTML</abbr> target value - <code>_blank</code> or <code>_top</code> for example.</p>
+
+<h3 id="using-contextual-importance">3.14 Using Contextual Importance</h3><div class="nav"><a href="#using-targets">Previous</a> | <a href="#advanced-features">Top</a> | <a href="#highlighting-special-lines-extra">Next</a></div>
+
+<div class="caution">
+
+<div class="caution-header">Caution:</div>
+
+<p>This functionality is not only buggy, but is proving very hard to implement in 1.1.X. Therefore, this
+  functionality may well be <strong>removed</strong> in 1.2.0. You are hereby warned!</p>
+
+</div>
+
+<p>This feature allows you to mark a part of your source as important. But as the
+implementation its use is deprecated and you should consider using
+the &#8220;Highlight Lines Extra&#8221; feature described below.</p>
+
+<h3 id="highlighting-special-lines-extra">3.15 Highlighting Special Lines &#8220;Extra&#8221;</h3><div class="nav"><a href="#using-contextual-importance">Previous</a> | <a href="#advanced-features">Top</a> | <a href="#specifying-lines-to-highlight-extra">Next</a></div>
+
+<p>An alternative (and more stable) method of highlighting code that is important
+is to use extra highlighting by line. Although you may not know what line numbers
+contain the important lines, if you do this method is a much more flexible way of
+making important lines stand out.</p>
+
+<h4 id="specifying-lines-to-highlight-extra">3.15.1 Specifying the Lines to Highlight Extra</h4><div class="nav"><a href="#highlighting-special-lines-extra">Previous</a> | <a href="#highlighting-special-lines-extra">Top</a> | <a href="#styles-for-highlighted-lines">Next</a></div>
+
+<p>To specify which lines to highlight extra, you pass an array containing the line numbers to <code class="highlighted php">highlight_lines_extra<span class="br0">&#40;</span><span class="br0">&#41;</span></code>:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">highlight_lines_extra</span><span class="br0">&#40;</span><span class="re0">$array</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>The array could be in the form <code class="highlighted php"><span class="kw3">array</span><span class="br0">&#40;</span><span class="nu0">2</span><span class="sy0">,</span> <span class="nu0">3</span><span class="sy0">,</span> <span class="nu0">4</span><span class="sy0">,</span> <span class="nu0">7</span><span class="sy0">,</span> <span class="nu0">12</span><span class="sy0">,</span> <span class="nu0">344</span><span class="sy0">,</span> <span class="nu0">4242</span><span class="br0">&#41;</span></code>, made from a DB query, generated
+from looking through the source for certain important things and working out what line those things are&#8230;
+However you get the line numbers, the array should simply be an array of integers.</p>
+
+<p>Here&#8217;s an example, using the same source as before:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+<span class="xtra li2"><span class="de2">8</span></span>9
+<span class="xtra li2"><span class="de2">10</span></span>11
+<span class="xtra li2"><span class="de2">12</span></span>13
+<span class="xtra li2"><span class="de2">14</span></span>15
+<span class="xtra li2"><span class="de2">16</span></span>17
+<span class="xtra li2"><span class="de2">18</span></span>19
+<span class="xtra li2"><span class="de2">20</span></span>21
+</pre></td><td class="de1"><pre class="de1"><span class="co1">//</span>
+<span class="xtra li2"><span class="de2"><span class="co1">// Here we go again! This time we'll simply highlight the 8th line</span></span></span><span class="co1">//</span>
+<span class="xtra li2"><span class="de2"><span class="re0">$source</span> <span class="sy0">=</span> <span class="st_h">'public int[][] product ( n, m )</span></span></span><span class="st_h">{</span>
+<span class="xtra li2"><span class="de2"><span class="st_h"> &nbsp;int [][] ans = new int[n][m];</span></span></span><span class="st_h"> &nbsp;for ( int i = 0; i &lt; n; i++ )</span>
+<span class="xtra li2"><span class="de2"><span class="st_h"> &nbsp;{</span></span></span><span class="st_h"> &nbsp; &nbsp;for ( int j = 0; i &lt; m; j++ )</span>
+<span class="xtra li2"><span class="de2"><span class="st_h"> &nbsp; &nbsp;{</span></span></span><span class="st_h"> &nbsp; &nbsp; &nbsp;ans[i][j] = i * j;</span>
+<span class="xtra li2"><span class="de2"><span class="st_h"> &nbsp; &nbsp;}</span></span></span><span class="st_h"> &nbsp;}</span>
+<span class="xtra li2"><span class="de2"><span class="st_h"> &nbsp;return ans;</span></span></span><span class="st_h">}'</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="re0">$geshi</span> <span class="sy0">=</span> <span class="kw2">new</span> GeSHi<span class="br0">&#40;</span><span class="re0">$source</span><span class="sy0">,</span> <span class="st_h">'java'</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">highlight_lines_extra</span><span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="nu0">8</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="kw1">echo</span> <span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">parse_code</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></tbody></table>
+
+<p>Which produces:</p>
+
+<table class="java geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">Java code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+<span class="xtra li2"><span class="de2"><span class="xtra ln-xtra">8</span></span></span>9
+<span class="xtra li2"><span class="de2">10</span></span>11
+<span class="xtra li2"><span class="de2">12</span></span></pre></td><td class="de1"><pre class="de1"><span class="kw1">public</span> <span class="kw4">int</span><span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="br0">&#93;</span> product <span class="br0">&#40;</span> n, m <span class="br0">&#41;</span>
+<span class="xtra li2"><span class="de2"><span class="br0">&#123;</span></span></span>&nbsp; <span class="kw4">int</span> <span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="br0">&#93;</span> ans <span class="sy0">=</span> <span class="kw1">new</span> <span class="kw4">int</span><span class="br0">&#91;</span>n<span class="br0">&#93;</span><span class="br0">&#91;</span>m<span class="br0">&#93;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span> <span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> n<span class="sy0">;</span> i<span class="sy0">++</span> <span class="br0">&#41;</span></span></span>&nbsp; <span class="br0">&#123;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span> <span class="kw4">int</span> j <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> m<span class="sy0">;</span> j<span class="sy0">++</span> <span class="br0">&#41;</span></span></span>&nbsp; &nbsp; <span class="br0">&#123;</span>
+<span class="xtra li2"><span class="de2"><span class="xtra ln-xtra">&nbsp; &nbsp; &nbsp; ans<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#91;</span>j<span class="br0">&#93;</span> <span class="sy0">=</span> i <span class="sy0">*</span> j<span class="sy0">;</span></span></span></span>&nbsp; &nbsp; <span class="br0">&#125;</span>
+<span class="xtra li2"><span class="de2">&nbsp; <span class="br0">&#125;</span></span></span>&nbsp; <span class="kw1">return</span> ans<span class="sy0">;</span>
+<span class="xtra li2"><span class="de2"><span class="br0">&#125;</span></span></span></pre></td></tr></tbody></table>
+
+<p>What&#8217;s more, as you can see the code on a highlighted line is still actually highlighted itself.</p>
+
+<h4 id="styles-for-highlighted-lines">3.15.2 Styles for the Highlighted Lines</h4><div class="nav"><a href="#specifying-lines-to-highlight-extra">Previous</a> | <a href="#highlighting-special-lines-extra">Top</a> | <a href="#adding-ids-to-each-line">Next</a></div>
+
+<p>Again as with contextual importance, you&#8217;re not chained to the yellow theme that is the default. You can
+use the <code class="highlighted php">set_highlight_lines_extra_style</code> method:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">set_highlight_lines_extra_style</span><span class="br0">&#40;</span><span class="re0">$styles</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Where <code class="highlighted php"><span class="re0">$styles</span></code> is the stylesheet declarations that you want to apply to highlighted lines.</p>
+
+<h3 id="adding-ids-to-each-line">3.16 Adding IDs to Each Line</h3><div class="nav"><a href="#styles-for-highlighted-lines">Previous</a> | <a href="#advanced-features">Top</a> | <a href="#getting-the-time-of-styling">Next</a></div>
+
+<p>Perhaps you&#8217;re a javascript junkie? <abbr title="Generic Syntax Highlighter">GeSHi</abbr> provides a way to give each line an ID so you can access that line with
+javascript, or perhaps just by plain <abbr title="Cascading Style Sheets">CSS</abbr> (though if you want to access lines by <abbr title="Cascading Style Sheets">CSS</abbr> you should use the method
+in the previous section). To enable IDs you call the <code class="highlighted php">enable_ids<span class="br0">&#40;</span><span class="br0">&#41;</span></code> method:</p>
+
+<p><code class="highlighted php"><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">enable_ids</span><span class="br0">&#40;</span><span class="re0">$flag</span><span class="br0">&#41;</span><span class="sy0">;</span></code></p>
+
+<p>Where <code class="highlighted php"><span class="re0">$flag</span></code> is <code class="highlighted php"><span class="kw4">true</span></code> or not present to enable IDs, and <code class="highlighted php"><span class="kw4">false</span></code> to disable them again if you need.</p>
+
+<p>The ID generated is in the form <code>{overall-css-id}-{line-number}</code>. So for example, if you set the overall <abbr title="Cascading Style Sheets">CSS</abbr> id to
+be &#8220;mycode&#8221;, then the IDs for each line would by &#8220;mycode-1&#8221;, &#8220;mycode-2&#8221; etc. If there is no <abbr title="Cascading Style Sheets">CSS</abbr> ID set, then one is
+made up in the form <code>geshi-[4 random characters]</code>, but this is not so useful for if you want to do javascript manipulation.</p>
+
+<h3 id="getting-the-time-of-styling">3.17 Getting the Time of Styling</h3><div class="nav"><a href="#adding-ids-to-each-line">Previous</a> | <a href="#advanced-features">Top</a> | <a href="#language-files">Next</a></div>
+
+<p>Once you&#8217;ve called <code class="highlighted php">parse_code<span class="br0">&#40;</span><span class="br0">&#41;</span></code>, you can get the time it took to run the highlighting by calling the
+<code class="highlighted php">get_time<span class="br0">&#40;</span><span class="br0">&#41;</span></code> method:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+</pre></td><td class="de1"><pre class="de1"><span class="re0">$geshi</span> <span class="sy0">=</span> <span class="kw2">new</span> GeSHi<span class="br0">&#40;</span><span class="re0">$source</span><span class="sy0">,</span> <span class="re0">$language</span><span class="sy0">,</span> <span class="re0">$path</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="re0">$code</span> <span class="sy0">=</span> <a href="http://www.php.net/mysql_real_escape_string"><span class="kw3">mysql_real_escape_string</span></a><span class="br0">&#40;</span><span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">parse_code</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2"><span class="re0">$time</span> <span class="sy0">=</span> <span class="re0">$geshi</span><span class="sy0">-&gt;</span><span class="me1">get_time</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></span></span>&nbsp;
+<span class="xtra li2"><span class="de2"><span class="co1">// do something with it</span></span></span><a href="http://www.php.net/mysql_query"><span class="kw3">mysql_query</span></a><span class="br0">&#40;</span><span class="st0">&quot;INSERT INTO code VALUES ('<span class="es4">$code</span>', '<span class="es4">$time</span>')&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></tbody></table>
+
+<h2 id="language-files">4 Language Files</h2><div class="nav"><a href="#getting-the-time-of-styling">Previous</a> | <a href="#language-file-example">Next</a></div>
+
+<p>So now you know what features <abbr title="Generic Syntax Highlighter">GeSHi</abbr> offers, and perhaps you&#8217;ve even meddled with the source. Or perhaps
+you&#8217;d like a language file for language X but it doesn&#8217;t seem to be supported? Rubbish! <abbr title="Generic Syntax Highlighter">GeSHi</abbr> will highlight
+anything, what do you think I coded this for? ^_^ You&#8217;ll just have to learn how to make a language file
+yourself. And I promise it&#8217;s not too hard - and if you&#8217;re here you&#8217;re in the right place!</p>
+
+<h3 id="language-file-example">4.1 An Example Language File</h3><div class="nav"><a href="#language-files">Previous</a> | <a href="#language-files">Top</a> | <a href="#language-file-conventions">Next</a></div>
+
+<p>Let&#8217;s begin by looking at an example language file - the language file for the first language ever supported,
+<abbr title="PHP: HTML Preprocessor">PHP</abbr>:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+<span class="xtra li2"><span class="de2">8</span></span>9
+<span class="xtra li2"><span class="de2">10</span></span>11
+<span class="xtra li2"><span class="de2">12</span></span>13
+<span class="xtra li2"><span class="de2">14</span></span>15
+<span class="xtra li2"><span class="de2">16</span></span>17
+<span class="xtra li2"><span class="de2">18</span></span>19
+<span class="xtra li2"><span class="de2">20</span></span>21
+<span class="xtra li2"><span class="de2">22</span></span>23
+<span class="xtra li2"><span class="de2">24</span></span>25
+<span class="xtra li2"><span class="de2">26</span></span>27
+<span class="xtra li2"><span class="de2">28</span></span>29
+<span class="xtra li2"><span class="de2">30</span></span>31
+<span class="xtra li2"><span class="de2">32</span></span>33
+<span class="xtra li2"><span class="de2">34</span></span>35
+<span class="xtra li2"><span class="de2">36</span></span>37
+<span class="xtra li2"><span class="de2">38</span></span>39
+<span class="xtra li2"><span class="de2">40</span></span>41
+<span class="xtra li2"><span class="de2">42</span></span>43
+<span class="xtra li2"><span class="de2">44</span></span>45
+<span class="xtra li2"><span class="de2">46</span></span>47
+<span class="xtra li2"><span class="de2">48</span></span>49
+<span class="xtra li2"><span class="de2">50</span></span>51
+<span class="xtra li2"><span class="de2">52</span></span>53
+<span class="xtra li2"><span class="de2">54</span></span>55
+<span class="xtra li2"><span class="de2">56</span></span>57
+<span class="xtra li2"><span class="de2">58</span></span>59
+<span class="xtra li2"><span class="de2">60</span></span>61
+<span class="xtra li2"><span class="de2">62</span></span>63
+<span class="xtra li2"><span class="de2">64</span></span>65
+<span class="xtra li2"><span class="de2">66</span></span>67
+<span class="xtra li2"><span class="de2">68</span></span>69
+<span class="xtra li2"><span class="de2">70</span></span>71
+<span class="xtra li2"><span class="de2">72</span></span>73
+<span class="xtra li2"><span class="de2">74</span></span>75
+<span class="xtra li2"><span class="de2">76</span></span>77
+<span class="xtra li2"><span class="de2">78</span></span>79
+<span class="xtra li2"><span class="de2">80</span></span>81
+<span class="xtra li2"><span class="de2">82</span></span>83
+<span class="xtra li2"><span class="de2">84</span></span>85
+<span class="xtra li2"><span class="de2">86</span></span>87
+<span class="xtra li2"><span class="de2">88</span></span>89
+<span class="xtra li2"><span class="de2">90</span></span>91
+<span class="xtra li2"><span class="de2">92</span></span>93
+<span class="xtra li2"><span class="de2">94</span></span>95
+<span class="xtra li2"><span class="de2">96</span></span>97
+<span class="xtra li2"><span class="de2">98</span></span>99
+<span class="xtra li2"><span class="de2">100</span></span>101
+<span class="xtra li2"><span class="de2">102</span></span>103
+<span class="xtra li2"><span class="de2">104</span></span>105
+<span class="xtra li2"><span class="de2">106</span></span>107
+<span class="xtra li2"><span class="de2">108</span></span>109
+<span class="xtra li2"><span class="de2">110</span></span>111
+<span class="xtra li2"><span class="de2">112</span></span>113
+<span class="xtra li2"><span class="de2">114</span></span>115
+<span class="xtra li2"><span class="de2">116</span></span>117
+<span class="xtra li2"><span class="de2">118</span></span>119
+<span class="xtra li2"><span class="de2">120</span></span>121
+<span class="xtra li2"><span class="de2">122</span></span>123
+<span class="xtra li2"><span class="de2">124</span></span>125
+<span class="xtra li2"><span class="de2">126</span></span>127
+<span class="xtra li2"><span class="de2">128</span></span>129
+<span class="xtra li2"><span class="de2">130</span></span>131
+<span class="xtra li2"><span class="de2">132</span></span>133
+<span class="xtra li2"><span class="de2">134</span></span>135
+<span class="xtra li2"><span class="de2">136</span></span>137
+<span class="xtra li2"><span class="de2">138</span></span>139
+<span class="xtra li2"><span class="de2">140</span></span>141
+<span class="xtra li2"><span class="de2">142</span></span>143
+<span class="xtra li2"><span class="de2">144</span></span>145
+<span class="xtra li2"><span class="de2">146</span></span>147
+<span class="xtra li2"><span class="de2">148</span></span>149
+<span class="xtra li2"><span class="de2">150</span></span>151
+<span class="xtra li2"><span class="de2">152</span></span>153
+<span class="xtra li2"><span class="de2">154</span></span>155
+<span class="xtra li2"><span class="de2">156</span></span>157
+<span class="xtra li2"><span class="de2">158</span></span>159
+<span class="xtra li2"><span class="de2">160</span></span>161
+<span class="xtra li2"><span class="de2">162</span></span>163
+<span class="xtra li2"><span class="de2">164</span></span>165
+<span class="xtra li2"><span class="de2">166</span></span>167
+<span class="xtra li2"><span class="de2">168</span></span>169
+<span class="xtra li2"><span class="de2">170</span></span>171
+<span class="xtra li2"><span class="de2">172</span></span>173
+<span class="xtra li2"><span class="de2">174</span></span>175
+<span class="xtra li2"><span class="de2">176</span></span>177
+<span class="xtra li2"><span class="de2">178</span></span>179
+<span class="xtra li2"><span class="de2">180</span></span>181
+<span class="xtra li2"><span class="de2">182</span></span>183
+<span class="xtra li2"><span class="de2">184</span></span>185
+<span class="xtra li2"><span class="de2">186</span></span>187
+<span class="xtra li2"><span class="de2">188</span></span>189
+<span class="xtra li2"><span class="de2">190</span></span>191
+<span class="xtra li2"><span class="de2">192</span></span>193
+<span class="xtra li2"><span class="de2">194</span></span>195
+<span class="xtra li2"><span class="de2">196</span></span>197
+<span class="xtra li2"><span class="de2">198</span></span>199
+<span class="xtra li2"><span class="de2">200</span></span>201
+<span class="xtra li2"><span class="de2">202</span></span>203
+<span class="xtra li2"><span class="de2">204</span></span>205
+<span class="xtra li2"><span class="de2">206</span></span>207
+<span class="xtra li2"><span class="de2">208</span></span>209
+<span class="xtra li2"><span class="de2">210</span></span>211
+<span class="xtra li2"><span class="de2">212</span></span>213
+<span class="xtra li2"><span class="de2">214</span></span>215
+<span class="xtra li2"><span class="de2">216</span></span>217
+<span class="xtra li2"><span class="de2">218</span></span>219
+<span class="xtra li2"><span class="de2">220</span></span>221
+<span class="xtra li2"><span class="de2">222</span></span>223
+<span class="xtra li2"><span class="de2">224</span></span>225
+<span class="xtra li2"><span class="de2">226</span></span>227
+<span class="xtra li2"><span class="de2">228</span></span>229
+<span class="xtra li2"><span class="de2">230</span></span>231
+<span class="xtra li2"><span class="de2">232</span></span>233
+<span class="xtra li2"><span class="de2">234</span></span>235
+<span class="xtra li2"><span class="de2">236</span></span>237
+<span class="xtra li2"><span class="de2">238</span></span>239
+<span class="xtra li2"><span class="de2">240</span></span>241
+<span class="xtra li2"><span class="de2">242</span></span>243
+<span class="xtra li2"><span class="de2">244</span></span>245
+<span class="xtra li2"><span class="de2">246</span></span>247
+<span class="xtra li2"><span class="de2">248</span></span>249
+<span class="xtra li2"><span class="de2">250</span></span>251
+<span class="xtra li2"><span class="de2">252</span></span>253
+<span class="xtra li2"><span class="de2">254</span></span>255
+<span class="xtra li2"><span class="de2">256</span></span>257
+<span class="xtra li2"><span class="de2">258</span></span>259
+<span class="xtra li2"><span class="de2">260</span></span>261
+<span class="xtra li2"><span class="de2">262</span></span>263
+<span class="xtra li2"><span class="de2">264</span></span>265
+<span class="xtra li2"><span class="de2">266</span></span>267
+<span class="xtra li2"><span class="de2">268</span></span>269
+<span class="xtra li2"><span class="de2">270</span></span>271
+<span class="xtra li2"><span class="de2">272</span></span>273
+<span class="xtra li2"><span class="de2">274</span></span>275
+<span class="xtra li2"><span class="de2">276</span></span>277
+<span class="xtra li2"><span class="de2">278</span></span>279
+<span class="xtra li2"><span class="de2">280</span></span>281
+<span class="xtra li2"><span class="de2">282</span></span>283
+<span class="xtra li2"><span class="de2">284</span></span>285
+<span class="xtra li2"><span class="de2">286</span></span>287
+<span class="xtra li2"><span class="de2">288</span></span>289
+<span class="xtra li2"><span class="de2">290</span></span>291
+<span class="xtra li2"><span class="de2">292</span></span>293
+<span class="xtra li2"><span class="de2">294</span></span>295
+<span class="xtra li2"><span class="de2">296</span></span>297
+<span class="xtra li2"><span class="de2">298</span></span>299
+<span class="xtra li2"><span class="de2">300</span></span>301
+<span class="xtra li2"><span class="de2">302</span></span>303
+<span class="xtra li2"><span class="de2">304</span></span>305
+<span class="xtra li2"><span class="de2">306</span></span>307
+<span class="xtra li2"><span class="de2">308</span></span>309
+<span class="xtra li2"><span class="de2">310</span></span>311
+<span class="xtra li2"><span class="de2">312</span></span>313
+<span class="xtra li2"><span class="de2">314</span></span>315
+<span class="xtra li2"><span class="de2">316</span></span>317
+<span class="xtra li2"><span class="de2">318</span></span>319
+<span class="xtra li2"><span class="de2">320</span></span>321
+<span class="xtra li2"><span class="de2">322</span></span>323
+<span class="xtra li2"><span class="de2">324</span></span>325
+<span class="xtra li2"><span class="de2">326</span></span>327
+<span class="xtra li2"><span class="de2">328</span></span>329
+<span class="xtra li2"><span class="de2">330</span></span>331
+<span class="xtra li2"><span class="de2">332</span></span>333
+<span class="xtra li2"><span class="de2">334</span></span>335
+<span class="xtra li2"><span class="de2">336</span></span>337
+<span class="xtra li2"><span class="de2">338</span></span>339
+<span class="xtra li2"><span class="de2">340</span></span>341
+<span class="xtra li2"><span class="de2">342</span></span>343
+<span class="xtra li2"><span class="de2">344</span></span>345
+<span class="xtra li2"><span class="de2">346</span></span>347
+<span class="xtra li2"><span class="de2">348</span></span>349
+<span class="xtra li2"><span class="de2">350</span></span>351
+<span class="xtra li2"><span class="de2">352</span></span>353
+<span class="xtra li2"><span class="de2">354</span></span>355
+<span class="xtra li2"><span class="de2">356</span></span>357
+<span class="xtra li2"><span class="de2">358</span></span>359
+<span class="xtra li2"><span class="de2">360</span></span>361
+<span class="xtra li2"><span class="de2">362</span></span>363
+<span class="xtra li2"><span class="de2">364</span></span>365
+<span class="xtra li2"><span class="de2">366</span></span>367
+<span class="xtra li2"><span class="de2">368</span></span>369
+<span class="xtra li2"><span class="de2">370</span></span>371
+<span class="xtra li2"><span class="de2">372</span></span>373
+<span class="xtra li2"><span class="de2">374</span></span>375
+<span class="xtra li2"><span class="de2">376</span></span>377
+<span class="xtra li2"><span class="de2">378</span></span>379
+<span class="xtra li2"><span class="de2">380</span></span>381
+<span class="xtra li2"><span class="de2">382</span></span>383
+<span class="xtra li2"><span class="de2">384</span></span>385
+<span class="xtra li2"><span class="de2">386</span></span>387
+<span class="xtra li2"><span class="de2">388</span></span>389
+<span class="xtra li2"><span class="de2">390</span></span>391
+<span class="xtra li2"><span class="de2">392</span></span>393
+<span class="xtra li2"><span class="de2">394</span></span>395
+<span class="xtra li2"><span class="de2">396</span></span>397
+<span class="xtra li2"><span class="de2">398</span></span>399
+<span class="xtra li2"><span class="de2">400</span></span>401
+<span class="xtra li2"><span class="de2">402</span></span>403
+<span class="xtra li2"><span class="de2">404</span></span>405
+<span class="xtra li2"><span class="de2">406</span></span>407
+<span class="xtra li2"><span class="de2">408</span></span>409
+<span class="xtra li2"><span class="de2">410</span></span>411
+<span class="xtra li2"><span class="de2">412</span></span>413
+<span class="xtra li2"><span class="de2">414</span></span>415
+<span class="xtra li2"><span class="de2">416</span></span>417
+<span class="xtra li2"><span class="de2">418</span></span>419
+<span class="xtra li2"><span class="de2">420</span></span>421
+<span class="xtra li2"><span class="de2">422</span></span>423
+<span class="xtra li2"><span class="de2">424</span></span>425
+<span class="xtra li2"><span class="de2">426</span></span>427
+<span class="xtra li2"><span class="de2">428</span></span>429
+<span class="xtra li2"><span class="de2">430</span></span>431
+<span class="xtra li2"><span class="de2">432</span></span>433
+<span class="xtra li2"><span class="de2">434</span></span>435
+<span class="xtra li2"><span class="de2">436</span></span>437
+<span class="xtra li2"><span class="de2">438</span></span>439
+<span class="xtra li2"><span class="de2">440</span></span>441
+<span class="xtra li2"><span class="de2">442</span></span>443
+<span class="xtra li2"><span class="de2">444</span></span>445
+<span class="xtra li2"><span class="de2">446</span></span>447
+<span class="xtra li2"><span class="de2">448</span></span>449
+<span class="xtra li2"><span class="de2">450</span></span>451
+<span class="xtra li2"><span class="de2">452</span></span>453
+<span class="xtra li2"><span class="de2">454</span></span>455
+<span class="xtra li2"><span class="de2">456</span></span>457
+<span class="xtra li2"><span class="de2">458</span></span>459
+<span class="xtra li2"><span class="de2">460</span></span>461
+<span class="xtra li2"><span class="de2">462</span></span>463
+<span class="xtra li2"><span class="de2">464</span></span>465
+<span class="xtra li2"><span class="de2">466</span></span>467
+<span class="xtra li2"><span class="de2">468</span></span>469
+<span class="xtra li2"><span class="de2">470</span></span>471
+<span class="xtra li2"><span class="de2">472</span></span>473
+<span class="xtra li2"><span class="de2">474</span></span>475
+<span class="xtra li2"><span class="de2">476</span></span>477
+<span class="xtra li2"><span class="de2">478</span></span>479
+<span class="xtra li2"><span class="de2">480</span></span>481
+<span class="xtra li2"><span class="de2">482</span></span>483
+<span class="xtra li2"><span class="de2">484</span></span>485
+<span class="xtra li2"><span class="de2">486</span></span>487
+<span class="xtra li2"><span class="de2">488</span></span>489
+<span class="xtra li2"><span class="de2">490</span></span>491
+<span class="xtra li2"><span class="de2">492</span></span>493
+<span class="xtra li2"><span class="de2">494</span></span>495
+<span class="xtra li2"><span class="de2">496</span></span>497
+<span class="xtra li2"><span class="de2">498</span></span>499
+<span class="xtra li2"><span class="de2">500</span></span>501
+<span class="xtra li2"><span class="de2">502</span></span>503
+<span class="xtra li2"><span class="de2">504</span></span>505
+<span class="xtra li2"><span class="de2">506</span></span>507
+<span class="xtra li2"><span class="de2">508</span></span>509
+<span class="xtra li2"><span class="de2">510</span></span>511
+<span class="xtra li2"><span class="de2">512</span></span>513
+<span class="xtra li2"><span class="de2">514</span></span>515
+<span class="xtra li2"><span class="de2">516</span></span>517
+<span class="xtra li2"><span class="de2">518</span></span>519
+<span class="xtra li2"><span class="de2">520</span></span>521
+<span class="xtra li2"><span class="de2">522</span></span>523
+<span class="xtra li2"><span class="de2">524</span></span>525
+<span class="xtra li2"><span class="de2">526</span></span>527
+<span class="xtra li2"><span class="de2">528</span></span>529
+<span class="xtra li2"><span class="de2">530</span></span>531
+<span class="xtra li2"><span class="de2">532</span></span>533
+<span class="xtra li2"><span class="de2">534</span></span>535
+<span class="xtra li2"><span class="de2">536</span></span>537
+<span class="xtra li2"><span class="de2">538</span></span>539
+<span class="xtra li2"><span class="de2">540</span></span>541
+<span class="xtra li2"><span class="de2">542</span></span>543
+<span class="xtra li2"><span class="de2">544</span></span>545
+<span class="xtra li2"><span class="de2">546</span></span>547
+<span class="xtra li2"><span class="de2">548</span></span>549
+<span class="xtra li2"><span class="de2">550</span></span>551
+<span class="xtra li2"><span class="de2">552</span></span>553
+<span class="xtra li2"><span class="de2">554</span></span>555
+<span class="xtra li2"><span class="de2">556</span></span>557
+<span class="xtra li2"><span class="de2">558</span></span>559
+<span class="xtra li2"><span class="de2">560</span></span>561
+<span class="xtra li2"><span class="de2">562</span></span>563
+<span class="xtra li2"><span class="de2">564</span></span>565
+<span class="xtra li2"><span class="de2">566</span></span>567
+<span class="xtra li2"><span class="de2">568</span></span>569
+<span class="xtra li2"><span class="de2">570</span></span>571
+<span class="xtra li2"><span class="de2">572</span></span>573
+<span class="xtra li2"><span class="de2">574</span></span>575
+<span class="xtra li2"><span class="de2">576</span></span>577
+<span class="xtra li2"><span class="de2">578</span></span>579
+<span class="xtra li2"><span class="de2">580</span></span>581
+<span class="xtra li2"><span class="de2">582</span></span>583
+<span class="xtra li2"><span class="de2">584</span></span>585
+<span class="xtra li2"><span class="de2">586</span></span>587
+<span class="xtra li2"><span class="de2">588</span></span>589
+<span class="xtra li2"><span class="de2">590</span></span>591
+<span class="xtra li2"><span class="de2">592</span></span>593
+<span class="xtra li2"><span class="de2">594</span></span>595
+<span class="xtra li2"><span class="de2">596</span></span>597
+<span class="xtra li2"><span class="de2">598</span></span>599
+<span class="xtra li2"><span class="de2">600</span></span>601
+<span class="xtra li2"><span class="de2">602</span></span>603
+<span class="xtra li2"><span class="de2">604</span></span>605
+<span class="xtra li2"><span class="de2">606</span></span>607
+<span class="xtra li2"><span class="de2">608</span></span>609
+<span class="xtra li2"><span class="de2">610</span></span>611
+<span class="xtra li2"><span class="de2">612</span></span>613
+<span class="xtra li2"><span class="de2">614</span></span>615
+<span class="xtra li2"><span class="de2">616</span></span>617
+<span class="xtra li2"><span class="de2">618</span></span>619
+<span class="xtra li2"><span class="de2">620</span></span>621
+<span class="xtra li2"><span class="de2">622</span></span>623
+<span class="xtra li2"><span class="de2">624</span></span>625
+<span class="xtra li2"><span class="de2">626</span></span>627
+<span class="xtra li2"><span class="de2">628</span></span>629
+<span class="xtra li2"><span class="de2">630</span></span>631
+<span class="xtra li2"><span class="de2">632</span></span>633
+<span class="xtra li2"><span class="de2">634</span></span>635
+<span class="xtra li2"><span class="de2">636</span></span>637
+<span class="xtra li2"><span class="de2">638</span></span>639
+<span class="xtra li2"><span class="de2">640</span></span>641
+<span class="xtra li2"><span class="de2">642</span></span>643
+<span class="xtra li2"><span class="de2">644</span></span>645
+<span class="xtra li2"><span class="de2">646</span></span>647
+<span class="xtra li2"><span class="de2">648</span></span>649
+<span class="xtra li2"><span class="de2">650</span></span>651
+<span class="xtra li2"><span class="de2">652</span></span>653
+<span class="xtra li2"><span class="de2">654</span></span>655
+<span class="xtra li2"><span class="de2">656</span></span>657
+<span class="xtra li2"><span class="de2">658</span></span>659
+<span class="xtra li2"><span class="de2">660</span></span>661
+<span class="xtra li2"><span class="de2">662</span></span>663
+<span class="xtra li2"><span class="de2">664</span></span>665
+<span class="xtra li2"><span class="de2">666</span></span>667
+<span class="xtra li2"><span class="de2">668</span></span>669
+<span class="xtra li2"><span class="de2">670</span></span>671
+<span class="xtra li2"><span class="de2">672</span></span>673
+<span class="xtra li2"><span class="de2">674</span></span>675
+<span class="xtra li2"><span class="de2">676</span></span>677
+<span class="xtra li2"><span class="de2">678</span></span>679
+<span class="xtra li2"><span class="de2">680</span></span>681
+<span class="xtra li2"><span class="de2">682</span></span>683
+<span class="xtra li2"><span class="de2">684</span></span>685
+<span class="xtra li2"><span class="de2">686</span></span>687
+<span class="xtra li2"><span class="de2">688</span></span>689
+<span class="xtra li2"><span class="de2">690</span></span>691
+<span class="xtra li2"><span class="de2">692</span></span>693
+<span class="xtra li2"><span class="de2">694</span></span>695
+<span class="xtra li2"><span class="de2">696</span></span>697
+<span class="xtra li2"><span class="de2">698</span></span>699
+<span class="xtra li2"><span class="de2">700</span></span>701
+<span class="xtra li2"><span class="de2">702</span></span>703
+<span class="xtra li2"><span class="de2">704</span></span>705
+<span class="xtra li2"><span class="de2">706</span></span>707
+<span class="xtra li2"><span class="de2">708</span></span>709
+<span class="xtra li2"><span class="de2">710</span></span>711
+<span class="xtra li2"><span class="de2">712</span></span>713
+<span class="xtra li2"><span class="de2">714</span></span>715
+<span class="xtra li2"><span class="de2">716</span></span>717
+<span class="xtra li2"><span class="de2">718</span></span>719
+<span class="xtra li2"><span class="de2">720</span></span>721
+<span class="xtra li2"><span class="de2">722</span></span>723
+<span class="xtra li2"><span class="de2">724</span></span>725
+<span class="xtra li2"><span class="de2">726</span></span>727
+<span class="xtra li2"><span class="de2">728</span></span>729
+<span class="xtra li2"><span class="de2">730</span></span>731
+<span class="xtra li2"><span class="de2">732</span></span>733
+<span class="xtra li2"><span class="de2">734</span></span>735
+<span class="xtra li2"><span class="de2">736</span></span>737
+<span class="xtra li2"><span class="de2">738</span></span>739
+<span class="xtra li2"><span class="de2">740</span></span>741
+<span class="xtra li2"><span class="de2">742</span></span>743
+<span class="xtra li2"><span class="de2">744</span></span>745
+<span class="xtra li2"><span class="de2">746</span></span>747
+<span class="xtra li2"><span class="de2">748</span></span>749
+<span class="xtra li2"><span class="de2">750</span></span>751
+<span class="xtra li2"><span class="de2">752</span></span>753
+<span class="xtra li2"><span class="de2">754</span></span>755
+<span class="xtra li2"><span class="de2">756</span></span>757
+<span class="xtra li2"><span class="de2">758</span></span>759
+<span class="xtra li2"><span class="de2">760</span></span>761
+<span class="xtra li2"><span class="de2">762</span></span>763
+<span class="xtra li2"><span class="de2">764</span></span>765
+<span class="xtra li2"><span class="de2">766</span></span>767
+<span class="xtra li2"><span class="de2">768</span></span>769
+<span class="xtra li2"><span class="de2">770</span></span>771
+<span class="xtra li2"><span class="de2">772</span></span>773
+<span class="xtra li2"><span class="de2">774</span></span>775
+<span class="xtra li2"><span class="de2">776</span></span>777
+<span class="xtra li2"><span class="de2">778</span></span>779
+<span class="xtra li2"><span class="de2">780</span></span>781
+<span class="xtra li2"><span class="de2">782</span></span>783
+<span class="xtra li2"><span class="de2">784</span></span>785
+<span class="xtra li2"><span class="de2">786</span></span>787
+<span class="xtra li2"><span class="de2">788</span></span>789
+<span class="xtra li2"><span class="de2">790</span></span>791
+<span class="xtra li2"><span class="de2">792</span></span>793
+<span class="xtra li2"><span class="de2">794</span></span>795
+<span class="xtra li2"><span class="de2">796</span></span>797
+<span class="xtra li2"><span class="de2">798</span></span>799
+<span class="xtra li2"><span class="de2">800</span></span>801
+<span class="xtra li2"><span class="de2">802</span></span>803
+<span class="xtra li2"><span class="de2">804</span></span>805
+<span class="xtra li2"><span class="de2">806</span></span>807
+<span class="xtra li2"><span class="de2">808</span></span>809
+<span class="xtra li2"><span class="de2">810</span></span>811
+<span class="xtra li2"><span class="de2">812</span></span>813
+<span class="xtra li2"><span class="de2">814</span></span>815
+<span class="xtra li2"><span class="de2">816</span></span>817
+<span class="xtra li2"><span class="de2">818</span></span>819
+<span class="xtra li2"><span class="de2">820</span></span>821
+<span class="xtra li2"><span class="de2">822</span></span>823
+<span class="xtra li2"><span class="de2">824</span></span>825
+<span class="xtra li2"><span class="de2">826</span></span>827
+<span class="xtra li2"><span class="de2">828</span></span>829
+<span class="xtra li2"><span class="de2">830</span></span>831
+<span class="xtra li2"><span class="de2">832</span></span>833
+<span class="xtra li2"><span class="de2">834</span></span>835
+<span class="xtra li2"><span class="de2">836</span></span>837
+<span class="xtra li2"><span class="de2">838</span></span>839
+<span class="xtra li2"><span class="de2">840</span></span>841
+<span class="xtra li2"><span class="de2">842</span></span>843
+<span class="xtra li2"><span class="de2">844</span></span>845
+<span class="xtra li2"><span class="de2">846</span></span>847
+<span class="xtra li2"><span class="de2">848</span></span>849
+<span class="xtra li2"><span class="de2">850</span></span>851
+<span class="xtra li2"><span class="de2">852</span></span>853
+<span class="xtra li2"><span class="de2">854</span></span>855
+<span class="xtra li2"><span class="de2">856</span></span>857
+<span class="xtra li2"><span class="de2">858</span></span>859
+<span class="xtra li2"><span class="de2">860</span></span>861
+<span class="xtra li2"><span class="de2">862</span></span>863
+<span class="xtra li2"><span class="de2">864</span></span>865
+<span class="xtra li2"><span class="de2">866</span></span>867
+<span class="xtra li2"><span class="de2">868</span></span>869
+<span class="xtra li2"><span class="de2">870</span></span>871
+<span class="xtra li2"><span class="de2">872</span></span>873
+<span class="xtra li2"><span class="de2">874</span></span>875
+<span class="xtra li2"><span class="de2">876</span></span>877
+<span class="xtra li2"><span class="de2">878</span></span>879
+<span class="xtra li2"><span class="de2">880</span></span>881
+<span class="xtra li2"><span class="de2">882</span></span>883
+<span class="xtra li2"><span class="de2">884</span></span>885
+<span class="xtra li2"><span class="de2">886</span></span>887
+<span class="xtra li2"><span class="de2">888</span></span>889
+<span class="xtra li2"><span class="de2">890</span></span>891
+<span class="xtra li2"><span class="de2">892</span></span>893
+<span class="xtra li2"><span class="de2">894</span></span>895
+<span class="xtra li2"><span class="de2">896</span></span>897
+<span class="xtra li2"><span class="de2">898</span></span>899
+<span class="xtra li2"><span class="de2">900</span></span>901
+<span class="xtra li2"><span class="de2">902</span></span>903
+<span class="xtra li2"><span class="de2">904</span></span>905
+<span class="xtra li2"><span class="de2">906</span></span>907
+<span class="xtra li2"><span class="de2">908</span></span>909
+<span class="xtra li2"><span class="de2">910</span></span>911
+<span class="xtra li2"><span class="de2">912</span></span>913
+<span class="xtra li2"><span class="de2">914</span></span>915
+<span class="xtra li2"><span class="de2">916</span></span>917
+<span class="xtra li2"><span class="de2">918</span></span>919
+<span class="xtra li2"><span class="de2">920</span></span>921
+<span class="xtra li2"><span class="de2">922</span></span>923
+<span class="xtra li2"><span class="de2">924</span></span>925
+<span class="xtra li2"><span class="de2">926</span></span>927
+<span class="xtra li2"><span class="de2">928</span></span>929
+<span class="xtra li2"><span class="de2">930</span></span>931
+<span class="xtra li2"><span class="de2">932</span></span>933
+<span class="xtra li2"><span class="de2">934</span></span>935
+<span class="xtra li2"><span class="de2">936</span></span>937
+<span class="xtra li2"><span class="de2">938</span></span>939
+<span class="xtra li2"><span class="de2">940</span></span>941
+<span class="xtra li2"><span class="de2">942</span></span>943
+<span class="xtra li2"><span class="de2">944</span></span>945
+<span class="xtra li2"><span class="de2">946</span></span>947
+<span class="xtra li2"><span class="de2">948</span></span>949
+<span class="xtra li2"><span class="de2">950</span></span>951
+<span class="xtra li2"><span class="de2">952</span></span>953
+<span class="xtra li2"><span class="de2">954</span></span>955
+<span class="xtra li2"><span class="de2">956</span></span>957
+<span class="xtra li2"><span class="de2">958</span></span>959
+<span class="xtra li2"><span class="de2">960</span></span>961
+<span class="xtra li2"><span class="de2">962</span></span>963
+<span class="xtra li2"><span class="de2">964</span></span>965
+<span class="xtra li2"><span class="de2">966</span></span>967
+<span class="xtra li2"><span class="de2">968</span></span>969
+<span class="xtra li2"><span class="de2">970</span></span>971
+<span class="xtra li2"><span class="de2">972</span></span>973
+<span class="xtra li2"><span class="de2">974</span></span>975
+<span class="xtra li2"><span class="de2">976</span></span>977
+<span class="xtra li2"><span class="de2">978</span></span>979
+<span class="xtra li2"><span class="de2">980</span></span>981
+<span class="xtra li2"><span class="de2">982</span></span>983
+<span class="xtra li2"><span class="de2">984</span></span>985
+<span class="xtra li2"><span class="de2">986</span></span>987
+<span class="xtra li2"><span class="de2">988</span></span>989
+<span class="xtra li2"><span class="de2">990</span></span>991
+<span class="xtra li2"><span class="de2">992</span></span>993
+<span class="xtra li2"><span class="de2">994</span></span>995
+<span class="xtra li2"><span class="de2">996</span></span>997
+<span class="xtra li2"><span class="de2">998</span></span>999
+<span class="xtra li2"><span class="de2">1000</span></span>1001
+<span class="xtra li2"><span class="de2">1002</span></span>1003
+<span class="xtra li2"><span class="de2">1004</span></span>1005
+<span class="xtra li2"><span class="de2">1006</span></span>1007
+<span class="xtra li2"><span class="de2">1008</span></span>1009
+<span class="xtra li2"><span class="de2">1010</span></span>1011
+<span class="xtra li2"><span class="de2">1012</span></span>1013
+<span class="xtra li2"><span class="de2">1014</span></span>1015
+<span class="xtra li2"><span class="de2">1016</span></span>1017
+<span class="xtra li2"><span class="de2">1018</span></span>1019
+<span class="xtra li2"><span class="de2">1020</span></span>1021
+<span class="xtra li2"><span class="de2">1022</span></span>1023
+<span class="xtra li2"><span class="de2">1024</span></span>1025
+<span class="xtra li2"><span class="de2">1026</span></span>1027
+<span class="xtra li2"><span class="de2">1028</span></span>1029
+<span class="xtra li2"><span class="de2">1030</span></span>1031
+<span class="xtra li2"><span class="de2">1032</span></span>1033
+<span class="xtra li2"><span class="de2">1034</span></span>1035
+<span class="xtra li2"><span class="de2">1036</span></span>1037
+<span class="xtra li2"><span class="de2">1038</span></span>1039
+<span class="xtra li2"><span class="de2">1040</span></span>1041
+<span class="xtra li2"><span class="de2">1042</span></span>1043
+<span class="xtra li2"><span class="de2">1044</span></span>1045
+<span class="xtra li2"><span class="de2">1046</span></span>1047
+<span class="xtra li2"><span class="de2">1048</span></span>1049
+<span class="xtra li2"><span class="de2">1050</span></span>1051
+<span class="xtra li2"><span class="de2">1052</span></span>1053
+<span class="xtra li2"><span class="de2">1054</span></span>1055
+<span class="xtra li2"><span class="de2">1056</span></span>1057
+<span class="xtra li2"><span class="de2">1058</span></span>1059
+<span class="xtra li2"><span class="de2">1060</span></span>1061
+<span class="xtra li2"><span class="de2">1062</span></span>1063
+<span class="xtra li2"><span class="de2">1064</span></span>1065
+<span class="xtra li2"><span class="de2">1066</span></span>1067
+<span class="xtra li2"><span class="de2">1068</span></span>1069
+<span class="xtra li2"><span class="de2">1070</span></span>1071
+<span class="xtra li2"><span class="de2">1072</span></span>1073
+<span class="xtra li2"><span class="de2">1074</span></span>1075
+<span class="xtra li2"><span class="de2">1076</span></span>1077
+<span class="xtra li2"><span class="de2">1078</span></span>1079
+<span class="xtra li2"><span class="de2">1080</span></span>1081
+<span class="xtra li2"><span class="de2">1082</span></span>1083
+<span class="xtra li2"><span class="de2">1084</span></span>1085
+<span class="xtra li2"><span class="de2">1086</span></span>1087
+<span class="xtra li2"><span class="de2">1088</span></span>1089
+<span class="xtra li2"><span class="de2">1090</span></span>1091
+<span class="xtra li2"><span class="de2">1092</span></span>1093
+<span class="xtra li2"><span class="de2">1094</span></span></pre></td><td class="de1"><pre class="de1"><span class="kw2">&lt;?php</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">/*************************************************************************************</span></span></span><span class="coMULTI">&nbsp;* php.php</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* --------</span></span></span><span class="coMULTI">&nbsp;* Author: Nigel McNie (nigel@geshi.org)</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)</span></span></span><span class="coMULTI">&nbsp;* Release Version: 1.0.8.3</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* Date Started: 2004/06/20</span></span></span><span class="coMULTI">&nbsp;*</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* PHP language file for GeSHi.</span></span></span><span class="coMULTI">&nbsp;*</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* CHANGES</span></span></span><span class="coMULTI">&nbsp;* -------</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* 2008/05/23 (1.0.7.22)</span></span></span><span class="coMULTI">&nbsp;* &nbsp;- &nbsp;Added description of extra language features (SF#1970248)</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* 2004/11/25 (1.0.3)</span></span></span><span class="coMULTI">&nbsp;* &nbsp;- &nbsp;Added support for multiple object splitters</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* &nbsp;- &nbsp;Fixed &amp;new problem</span></span></span><span class="coMULTI">&nbsp;* 2004/10/27 (1.0.2)</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* &nbsp;- &nbsp;Added URL support</span></span></span><span class="coMULTI">&nbsp;* &nbsp;- &nbsp;Added extra constants</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* 2004/08/05 (1.0.1)</span></span></span><span class="coMULTI">&nbsp;* &nbsp;- &nbsp;Added support for symbols</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* 2004/07/14 (1.0.0)</span></span></span><span class="coMULTI">&nbsp;* &nbsp;- &nbsp;First Release</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;*</span></span></span><span class="coMULTI">&nbsp;* TODO (updated 2004/07/14)</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* -------------------------</span></span></span><span class="coMULTI">&nbsp;* * Make sure the last few function I may have missed</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* &nbsp; (like eval()) are included for highlighting</span></span></span><span class="coMULTI">&nbsp;* * Split to several files - php4, php5 etc</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;*</span></span></span><span class="coMULTI">&nbsp;*************************************************************************************</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;*</span></span></span><span class="coMULTI">&nbsp;* &nbsp; &nbsp; This file is part of GeSHi.</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;*</span></span></span><span class="coMULTI">&nbsp;* &nbsp; GeSHi is free software; you can redistribute it and/or modify</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* &nbsp; it under the terms of the GNU General Public License as published by</span></span></span><span class="coMULTI">&nbsp;* &nbsp; the Free Software Foundation; either version 2 of the License, or</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* &nbsp; (at your option) any later version.</span></span></span><span class="coMULTI">&nbsp;*</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* &nbsp; GeSHi is distributed in the hope that it will be useful,</span></span></span><span class="coMULTI">&nbsp;* &nbsp; but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* &nbsp; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. &nbsp;See the</span></span></span><span class="coMULTI">&nbsp;* &nbsp; GNU General Public License for more details.</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;*</span></span></span><span class="coMULTI">&nbsp;* &nbsp; You should have received a copy of the GNU General Public License</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* &nbsp; along with GeSHi; if not, write to the Free Software</span></span></span><span class="coMULTI">&nbsp;* &nbsp; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA &nbsp;02111-1307 &nbsp;USA</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;*</span></span></span><span class="coMULTI">&nbsp;************************************************************************************/</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="re0">$language_data</span> <span class="sy0">=</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="st_h">'LANG_NAME'</span> <span class="sy0">=&gt;</span> <span class="st_h">'PHP'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="st_h">'COMMENT_SINGLE'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="nu0">1</span> <span class="sy0">=&gt;</span> <span class="st_h">'//'</span><span class="sy0">,</span> <span class="nu0">2</span> <span class="sy0">=&gt;</span> <span class="st_h">'#'</span><span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="st_h">'COMMENT_MULTI'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'/*'</span> <span class="sy0">=&gt;</span> <span class="st_h">'*/'</span><span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="st_h">'HARDQUOTE'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&quot;'&quot;</span><span class="sy0">,</span> <span class="st0">&quot;'&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="st_h">'HARDESCAPE'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&quot;'&quot;</span><span class="sy0">,</span> <span class="st0">&quot;<span class="es1">\\</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="st_h">'HARDCHAR'</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;<span class="es1">\\</span>&quot;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="st_h">'COMMENT_REGEXP'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//Heredoc and Nowdoc syntax</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">3</span> <span class="sy0">=&gt;</span> <span class="st_h">'/&lt;&lt;&lt;\s*?(\'?)([a-zA-Z0-9]+?)\1[^\n]*?\\n.*\\n\\2(?![a-zA-Z0-9])/siU'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// phpdoc comments</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">4</span> <span class="sy0">=&gt;</span> <span class="st_h">'#/\*\*(?![\*\/]).*\*/#sU'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Advanced # handling</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;/#.*?(?:(?=\?\&gt;)|^)/smi&quot;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="st_h">'CASE_KEYWORDS'</span> <span class="sy0">=&gt;</span> GESHI_CAPS_NO_CHANGE<span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="st_h">'QUOTEMARKS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'&quot;'</span><span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="st_h">'ESCAPE_CHAR'</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="st_h">'ESCAPE_REGEXP'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//Simple Single Char Escapes</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;#<span class="es1">\\</span><span class="es1">\\</span>[nfrtv<span class="es1">\$</span><span class="es1">\&quot;</span><span class="es1">\n</span><span class="es1">\\</span><span class="es1">\\</span>]#i&quot;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//Hexadecimal Char Specs</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;#<span class="es1">\\</span><span class="es1">\\</span>x[\da-fA-F]{1,2}#i&quot;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//Octal Char Specs</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">3</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;#<span class="es1">\\</span><span class="es1">\\</span>[0-7]{1,3}#&quot;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//String Parsing of Variable Names</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">4</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;#<span class="es1">\\</span>$[a-z0-9_]+(?:<span class="es1">\\</span>[[a-z0-9_]+<span class="es1">\\</span>]|-&gt;[a-z0-9_]+)?|(?:<span class="es1">\\</span>{<span class="es1">\\</span>$|<span class="es1">\\</span>$<span class="es1">\\</span>{)[a-z0-9_]+(?:<span class="es1">\\</span>[('?)[a-z0-9_]*<span class="es1">\\</span>1<span class="es1">\\</span>]|-&gt;[a-z0-9_]+)*<span class="es1">\\</span>}#i&quot;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//Experimental extension supporting cascaded {${$var}} syntax</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">5</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;#<span class="es1">\$</span>[a-z0-9_]+(?:\[[a-z0-9_]+\]|-&gt;[a-z0-9_]+)?|(?:\{<span class="es1">\$</span>|<span class="es1">\$</span>\{)[a-z0-9_]+(?:\[('?)[a-z0-9_]*<span class="es1">\\</span>1\]|-&gt;[a-z0-9_]+)*\}|\{<span class="es1">\$</span>(?R)\}#i&quot;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//Format String support in &quot;&quot;-Strings</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">6</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;#%(?:%|(?:\d+<span class="es1">\\</span><span class="es1">\\</span><span class="es1">\\</span><span class="es1">\$</span>)?<span class="es1">\\</span>+?(?:<span class="es2">\x20</span>|0|'.)?-?(?:\d+|<span class="es1">\\</span>*)?(?:\.\d+)?[bcdefFosuxX])#&quot;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="st_h">'NUMBERS'</span> <span class="sy0">=&gt;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; GESHI_NUMBER_INT_BASIC <span class="sy0">|</span> &nbsp;GESHI_NUMBER_OCT_PREFIX <span class="sy0">|</span> GESHI_NUMBER_HEX_PREFIX <span class="sy0">|</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; GESHI_NUMBER_FLT_SCI_ZERO<span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="st_h">'KEYWORDS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'as'</span><span class="sy0">,</span><span class="st_h">'break'</span><span class="sy0">,</span><span class="st_h">'case'</span><span class="sy0">,</span><span class="st_h">'continue'</span><span class="sy0">,</span><span class="st_h">'default'</span><span class="sy0">,</span><span class="st_h">'do'</span><span class="sy0">,</span><span class="st_h">'else'</span><span class="sy0">,</span><span class="st_h">'elseif'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'endfor'</span><span class="sy0">,</span><span class="st_h">'endforeach'</span><span class="sy0">,</span><span class="st_h">'endif'</span><span class="sy0">,</span><span class="st_h">'endswitch'</span><span class="sy0">,</span><span class="st_h">'endwhile'</span><span class="sy0">,</span><span class="st_h">'for'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'foreach'</span><span class="sy0">,</span><span class="st_h">'if'</span><span class="sy0">,</span><span class="st_h">'include'</span><span class="sy0">,</span><span class="st_h">'include_once'</span><span class="sy0">,</span><span class="st_h">'require'</span><span class="sy0">,</span><span class="st_h">'require_once'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'return'</span><span class="sy0">,</span><span class="st_h">'switch'</span><span class="sy0">,</span><span class="st_h">'while'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'echo'</span><span class="sy0">,</span><span class="st_h">'print'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'&amp;amp;new'</span><span class="sy0">,</span><span class="st_h">'&amp;lt;/script&amp;gt;'</span><span class="sy0">,</span><span class="st_h">'&amp;lt;?php'</span><span class="sy0">,</span><span class="st_h">'&amp;lt;script language'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'class'</span><span class="sy0">,</span><span class="st_h">'const'</span><span class="sy0">,</span><span class="st_h">'declare'</span><span class="sy0">,</span><span class="st_h">'extends'</span><span class="sy0">,</span><span class="st_h">'function'</span><span class="sy0">,</span><span class="st_h">'global'</span><span class="sy0">,</span><span class="st_h">'interface'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'namespace'</span><span class="sy0">,</span><span class="st_h">'new'</span><span class="sy0">,</span><span class="st_h">'private'</span><span class="sy0">,</span><span class="st_h">'public'</span><span class="sy0">,</span><span class="st_h">'self'</span><span class="sy0">,</span><span class="st_h">'var'</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">3</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'abs'</span><span class="sy0">,</span><span class="st_h">'acos'</span><span class="sy0">,</span><span class="st_h">'acosh'</span><span class="sy0">,</span><span class="st_h">'addcslashes'</span><span class="sy0">,</span><span class="st_h">'addslashes'</span><span class="sy0">,</span><span class="st_h">'aggregate'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'aggregate_methods'</span><span class="sy0">,</span><span class="st_h">'aggregate_methods_by_list'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'aggregate_methods_by_regexp'</span><span class="sy0">,</span><span class="st_h">'aggregate_properties'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'aggregate_properties_by_list'</span><span class="sy0">,</span><span class="st_h">'aggregate_properties_by_regexp'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'aggregation_info'</span><span class="sy0">,</span><span class="st_h">'apache_child_terminate'</span><span class="sy0">,</span><span class="st_h">'apache_get_modules'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'apache_get_version'</span><span class="sy0">,</span><span class="st_h">'apache_getenv'</span><span class="sy0">,</span><span class="st_h">'apache_lookup_uri'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'apache_note'</span><span class="sy0">,</span><span class="st_h">'apache_request_headers'</span><span class="sy0">,</span><span class="st_h">'apache_response_headers'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'apache_setenv'</span><span class="sy0">,</span><span class="st_h">'array'</span><span class="sy0">,</span><span class="st_h">'array_change_key_case'</span><span class="sy0">,</span><span class="st_h">'array_chunk'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'array_combine'</span><span class="sy0">,</span><span class="st_h">'array_count_values'</span><span class="sy0">,</span><span class="st_h">'array_diff'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'array_diff_assoc'</span><span class="sy0">,</span><span class="st_h">'array_diff_key'</span><span class="sy0">,</span><span class="st_h">'array_diff_uassoc'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'array_diff_ukey'</span><span class="sy0">,</span><span class="st_h">'array_fill'</span><span class="sy0">,</span><span class="st_h">'array_fill_keys'</span><span class="sy0">,</span><span class="st_h">'array_filter'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'array_flip'</span><span class="sy0">,</span><span class="st_h">'array_intersect'</span><span class="sy0">,</span><span class="st_h">'array_intersect_assoc'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'array_intersect_key'</span><span class="sy0">,</span><span class="st_h">'array_intersect_uassoc'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'array_intersect_ukey'</span><span class="sy0">,</span><span class="st_h">'array_key_exists'</span><span class="sy0">,</span><span class="st_h">'array_keys'</span><span class="sy0">,</span><span class="st_h">'array_map'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'array_merge'</span><span class="sy0">,</span><span class="st_h">'array_merge_recursive'</span><span class="sy0">,</span><span class="st_h">'array_multisort'</span><span class="sy0">,</span><span class="st_h">'array_pad'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'array_pop'</span><span class="sy0">,</span><span class="st_h">'array_product'</span><span class="sy0">,</span><span class="st_h">'array_push'</span><span class="sy0">,</span><span class="st_h">'array_rand'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'array_reduce'</span><span class="sy0">,</span><span class="st_h">'array_reverse'</span><span class="sy0">,</span><span class="st_h">'array_search'</span><span class="sy0">,</span><span class="st_h">'array_shift'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'array_slice'</span><span class="sy0">,</span><span class="st_h">'array_splice'</span><span class="sy0">,</span><span class="st_h">'array_sum'</span><span class="sy0">,</span><span class="st_h">'array_udiff'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'array_udiff_assoc'</span><span class="sy0">,</span><span class="st_h">'array_udiff_uassoc'</span><span class="sy0">,</span><span class="st_h">'array_uintersect'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'array_uintersect_assoc'</span><span class="sy0">,</span><span class="st_h">'array_uintersect_uassoc'</span><span class="sy0">,</span><span class="st_h">'array_unique'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'array_unshift'</span><span class="sy0">,</span><span class="st_h">'array_values'</span><span class="sy0">,</span><span class="st_h">'array_walk'</span><span class="sy0">,</span><span class="st_h">'array_walk_recursive'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'arsort'</span><span class="sy0">,</span><span class="st_h">'asin'</span><span class="sy0">,</span><span class="st_h">'asinh'</span><span class="sy0">,</span><span class="st_h">'asort'</span><span class="sy0">,</span><span class="st_h">'assert'</span><span class="sy0">,</span><span class="st_h">'assert_options'</span><span class="sy0">,</span><span class="st_h">'atan'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'atan2'</span><span class="sy0">,</span><span class="st_h">'atanh'</span><span class="sy0">,</span><span class="st_h">'base_convert'</span><span class="sy0">,</span><span class="st_h">'base64_decode'</span><span class="sy0">,</span><span class="st_h">'base64_encode'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'basename'</span><span class="sy0">,</span><span class="st_h">'bcadd'</span><span class="sy0">,</span><span class="st_h">'bccomp'</span><span class="sy0">,</span><span class="st_h">'bcdiv'</span><span class="sy0">,</span><span class="st_h">'bcmod'</span><span class="sy0">,</span><span class="st_h">'bcmul'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'bcompiler_load'</span><span class="sy0">,</span><span class="st_h">'bcompiler_load_exe'</span><span class="sy0">,</span><span class="st_h">'bcompiler_parse_class'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'bcompiler_read'</span><span class="sy0">,</span><span class="st_h">'bcompiler_write_class'</span><span class="sy0">,</span><span class="st_h">'bcompiler_write_constant'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'bcompiler_write_exe_footer'</span><span class="sy0">,</span><span class="st_h">'bcompiler_write_file'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'bcompiler_write_footer'</span><span class="sy0">,</span><span class="st_h">'bcompiler_write_function'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'bcompiler_write_functions_from_file'</span><span class="sy0">,</span><span class="st_h">'bcompiler_write_header'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'bcompiler_write_included_filename'</span><span class="sy0">,</span><span class="st_h">'bcpow'</span><span class="sy0">,</span><span class="st_h">'bcpowmod'</span><span class="sy0">,</span><span class="st_h">'bcscale'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'bcsqrt'</span><span class="sy0">,</span><span class="st_h">'bcsub'</span><span class="sy0">,</span><span class="st_h">'bin2hex'</span><span class="sy0">,</span><span class="st_h">'bindec'</span><span class="sy0">,</span><span class="st_h">'bindtextdomain'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'bind_textdomain_codeset'</span><span class="sy0">,</span><span class="st_h">'bitset_empty'</span><span class="sy0">,</span><span class="st_h">'bitset_equal'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'bitset_excl'</span><span class="sy0">,</span><span class="st_h">'bitset_fill'</span><span class="sy0">,</span><span class="st_h">'bitset_from_array'</span><span class="sy0">,</span><span class="st_h">'bitset_from_hash'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'bitset_from_string'</span><span class="sy0">,</span><span class="st_h">'bitset_in'</span><span class="sy0">,</span><span class="st_h">'bitset_incl'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'bitset_intersection'</span><span class="sy0">,</span><span class="st_h">'bitset_invert'</span><span class="sy0">,</span><span class="st_h">'bitset_is_empty'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'bitset_subset'</span><span class="sy0">,</span><span class="st_h">'bitset_to_array'</span><span class="sy0">,</span><span class="st_h">'bitset_to_hash'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'bitset_to_string'</span><span class="sy0">,</span><span class="st_h">'bitset_union'</span><span class="sy0">,</span><span class="st_h">'blenc_encrypt'</span><span class="sy0">,</span><span class="st_h">'bzclose'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'bzcompress'</span><span class="sy0">,</span><span class="st_h">'bzdecompress'</span><span class="sy0">,</span><span class="st_h">'bzerrno'</span><span class="sy0">,</span><span class="st_h">'bzerror'</span><span class="sy0">,</span><span class="st_h">'bzerrstr'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'bzflush'</span><span class="sy0">,</span><span class="st_h">'bzopen'</span><span class="sy0">,</span><span class="st_h">'bzread'</span><span class="sy0">,</span><span class="st_h">'bzwrite'</span><span class="sy0">,</span><span class="st_h">'cal_days_in_month'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cal_from_jd'</span><span class="sy0">,</span><span class="st_h">'cal_info'</span><span class="sy0">,</span><span class="st_h">'cal_to_jd'</span><span class="sy0">,</span><span class="st_h">'call_user_func'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'call_user_func_array'</span><span class="sy0">,</span><span class="st_h">'call_user_method'</span><span class="sy0">,</span><span class="st_h">'call_user_method_array'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ceil'</span><span class="sy0">,</span><span class="st_h">'chdir'</span><span class="sy0">,</span><span class="st_h">'checkdate'</span><span class="sy0">,</span><span class="st_h">'checkdnsrr'</span><span class="sy0">,</span><span class="st_h">'chgrp'</span><span class="sy0">,</span><span class="st_h">'chmod'</span><span class="sy0">,</span><span class="st_h">'chop'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'chown'</span><span class="sy0">,</span><span class="st_h">'chr'</span><span class="sy0">,</span><span class="st_h">'chunk_split'</span><span class="sy0">,</span><span class="st_h">'class_exists'</span><span class="sy0">,</span><span class="st_h">'class_implements'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'class_parents'</span><span class="sy0">,</span><span class="st_h">'classkit_aggregate_methods'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'classkit_doc_comments'</span><span class="sy0">,</span><span class="st_h">'classkit_import'</span><span class="sy0">,</span><span class="st_h">'classkit_method_add'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'classkit_method_copy'</span><span class="sy0">,</span><span class="st_h">'classkit_method_redefine'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'classkit_method_remove'</span><span class="sy0">,</span><span class="st_h">'classkit_method_rename'</span><span class="sy0">,</span><span class="st_h">'clearstatcache'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'closedir'</span><span class="sy0">,</span><span class="st_h">'closelog'</span><span class="sy0">,</span><span class="st_h">'com_create_guid'</span><span class="sy0">,</span><span class="st_h">'com_event_sink'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'com_get_active_object'</span><span class="sy0">,</span><span class="st_h">'com_load_typelib'</span><span class="sy0">,</span><span class="st_h">'com_message_pump'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'com_print_typeinfo'</span><span class="sy0">,</span><span class="st_h">'compact'</span><span class="sy0">,</span><span class="st_h">'confirm_phpdoc_compiled'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'connection_aborted'</span><span class="sy0">,</span><span class="st_h">'connection_status'</span><span class="sy0">,</span><span class="st_h">'constant'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'convert_cyr_string'</span><span class="sy0">,</span><span class="st_h">'convert_uudecode'</span><span class="sy0">,</span><span class="st_h">'convert_uuencode'</span><span class="sy0">,</span><span class="st_h">'copy'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cos'</span><span class="sy0">,</span><span class="st_h">'cosh'</span><span class="sy0">,</span><span class="st_h">'count'</span><span class="sy0">,</span><span class="st_h">'count_chars'</span><span class="sy0">,</span><span class="st_h">'cpdf_add_annotation'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_add_outline'</span><span class="sy0">,</span><span class="st_h">'cpdf_arc'</span><span class="sy0">,</span><span class="st_h">'cpdf_begin_text'</span><span class="sy0">,</span><span class="st_h">'cpdf_circle'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_clip'</span><span class="sy0">,</span><span class="st_h">'cpdf_close'</span><span class="sy0">,</span><span class="st_h">'cpdf_closepath'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_closepath_fill_stroke'</span><span class="sy0">,</span><span class="st_h">'cpdf_closepath_stroke'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_continue_text'</span><span class="sy0">,</span><span class="st_h">'cpdf_curveto'</span><span class="sy0">,</span><span class="st_h">'cpdf_end_text'</span><span class="sy0">,</span><span class="st_h">'cpdf_fill'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_fill_stroke'</span><span class="sy0">,</span><span class="st_h">'cpdf_finalize'</span><span class="sy0">,</span><span class="st_h">'cpdf_finalize_page'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_global_set_document_limits'</span><span class="sy0">,</span><span class="st_h">'cpdf_import_jpeg'</span><span class="sy0">,</span><span class="st_h">'cpdf_lineto'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_moveto'</span><span class="sy0">,</span><span class="st_h">'cpdf_newpath'</span><span class="sy0">,</span><span class="st_h">'cpdf_open'</span><span class="sy0">,</span><span class="st_h">'cpdf_output_buffer'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_page_init'</span><span class="sy0">,</span><span class="st_h">'cpdf_rect'</span><span class="sy0">,</span><span class="st_h">'cpdf_restore'</span><span class="sy0">,</span><span class="st_h">'cpdf_rlineto'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_rmoveto'</span><span class="sy0">,</span><span class="st_h">'cpdf_rotate'</span><span class="sy0">,</span><span class="st_h">'cpdf_rotate_text'</span><span class="sy0">,</span><span class="st_h">'cpdf_save'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_save_to_file'</span><span class="sy0">,</span><span class="st_h">'cpdf_scale'</span><span class="sy0">,</span><span class="st_h">'cpdf_set_action_url'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_set_char_spacing'</span><span class="sy0">,</span><span class="st_h">'cpdf_set_creator'</span><span class="sy0">,</span><span class="st_h">'cpdf_set_current_page'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_set_font'</span><span class="sy0">,</span><span class="st_h">'cpdf_set_font_directories'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_set_font_map_file'</span><span class="sy0">,</span><span class="st_h">'cpdf_set_horiz_scaling'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_set_keywords'</span><span class="sy0">,</span><span class="st_h">'cpdf_set_leading'</span><span class="sy0">,</span><span class="st_h">'cpdf_set_page_animation'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_set_subject'</span><span class="sy0">,</span><span class="st_h">'cpdf_set_text_matrix'</span><span class="sy0">,</span><span class="st_h">'cpdf_set_text_pos'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_set_text_rendering'</span><span class="sy0">,</span><span class="st_h">'cpdf_set_text_rise'</span><span class="sy0">,</span><span class="st_h">'cpdf_set_title'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_set_viewer_preferences'</span><span class="sy0">,</span><span class="st_h">'cpdf_set_word_spacing'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_setdash'</span><span class="sy0">,</span><span class="st_h">'cpdf_setflat'</span><span class="sy0">,</span><span class="st_h">'cpdf_setgray'</span><span class="sy0">,</span><span class="st_h">'cpdf_setgray_fill'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_setgray_stroke'</span><span class="sy0">,</span><span class="st_h">'cpdf_setlinecap'</span><span class="sy0">,</span><span class="st_h">'cpdf_setlinejoin'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_setlinewidth'</span><span class="sy0">,</span><span class="st_h">'cpdf_setmiterlimit'</span><span class="sy0">,</span><span class="st_h">'cpdf_setrgbcolor'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_setrgbcolor_fill'</span><span class="sy0">,</span><span class="st_h">'cpdf_setrgbcolor_stroke'</span><span class="sy0">,</span><span class="st_h">'cpdf_show'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_show_xy'</span><span class="sy0">,</span><span class="st_h">'cpdf_stringwidth'</span><span class="sy0">,</span><span class="st_h">'cpdf_stroke'</span><span class="sy0">,</span><span class="st_h">'cpdf_text'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cpdf_translate'</span><span class="sy0">,</span><span class="st_h">'crack_check'</span><span class="sy0">,</span><span class="st_h">'crack_closedict'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'crack_getlastmessage'</span><span class="sy0">,</span><span class="st_h">'crack_opendict'</span><span class="sy0">,</span><span class="st_h">'crc32'</span><span class="sy0">,</span><span class="st_h">'create_function'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'crypt'</span><span class="sy0">,</span><span class="st_h">'ctype_alnum'</span><span class="sy0">,</span><span class="st_h">'ctype_alpha'</span><span class="sy0">,</span><span class="st_h">'ctype_cntrl'</span><span class="sy0">,</span><span class="st_h">'ctype_digit'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ctype_graph'</span><span class="sy0">,</span><span class="st_h">'ctype_lower'</span><span class="sy0">,</span><span class="st_h">'ctype_print'</span><span class="sy0">,</span><span class="st_h">'ctype_punct'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ctype_space'</span><span class="sy0">,</span><span class="st_h">'ctype_upper'</span><span class="sy0">,</span><span class="st_h">'ctype_xdigit'</span><span class="sy0">,</span><span class="st_h">'curl_close'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'curl_copy_handle'</span><span class="sy0">,</span><span class="st_h">'curl_errno'</span><span class="sy0">,</span><span class="st_h">'curl_error'</span><span class="sy0">,</span><span class="st_h">'curl_exec'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'curl_getinfo'</span><span class="sy0">,</span><span class="st_h">'curl_init'</span><span class="sy0">,</span><span class="st_h">'curl_multi_add_handle'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'curl_multi_close'</span><span class="sy0">,</span><span class="st_h">'curl_multi_exec'</span><span class="sy0">,</span><span class="st_h">'curl_multi_getcontent'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'curl_multi_info_read'</span><span class="sy0">,</span><span class="st_h">'curl_multi_init'</span><span class="sy0">,</span><span class="st_h">'curl_multi_remove_handle'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'curl_multi_select'</span><span class="sy0">,</span><span class="st_h">'curl_setopt'</span><span class="sy0">,</span><span class="st_h">'curl_setopt_array'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'curl_version'</span><span class="sy0">,</span><span class="st_h">'current'</span><span class="sy0">,</span><span class="st_h">'cvsclient_connect'</span><span class="sy0">,</span><span class="st_h">'cvsclient_log'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'cvsclient_login'</span><span class="sy0">,</span><span class="st_h">'cvsclient_retrieve'</span><span class="sy0">,</span><span class="st_h">'date'</span><span class="sy0">,</span><span class="st_h">'date_create'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'date_date_set'</span><span class="sy0">,</span><span class="st_h">'date_default_timezone_get'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'date_default_timezone_set'</span><span class="sy0">,</span><span class="st_h">'date_format'</span><span class="sy0">,</span><span class="st_h">'date_isodate_set'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'date_modify'</span><span class="sy0">,</span><span class="st_h">'date_offset_get'</span><span class="sy0">,</span><span class="st_h">'date_parse'</span><span class="sy0">,</span><span class="st_h">'date_sun_info'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'date_sunrise'</span><span class="sy0">,</span><span class="st_h">'date_sunset'</span><span class="sy0">,</span><span class="st_h">'date_time_set'</span><span class="sy0">,</span><span class="st_h">'date_timezone_get'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'date_timezone_set'</span><span class="sy0">,</span><span class="st_h">'db_id_list'</span><span class="sy0">,</span><span class="st_h">'dba_close'</span><span class="sy0">,</span><span class="st_h">'dba_delete'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'dba_exists'</span><span class="sy0">,</span><span class="st_h">'dba_fetch'</span><span class="sy0">,</span><span class="st_h">'dba_firstkey'</span><span class="sy0">,</span><span class="st_h">'dba_handlers'</span><span class="sy0">,</span><span class="st_h">'dba_insert'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'dba_key_split'</span><span class="sy0">,</span><span class="st_h">'dba_list'</span><span class="sy0">,</span><span class="st_h">'dba_nextkey'</span><span class="sy0">,</span><span class="st_h">'dba_open'</span><span class="sy0">,</span><span class="st_h">'dba_optimize'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'dba_popen'</span><span class="sy0">,</span><span class="st_h">'dba_replace'</span><span class="sy0">,</span><span class="st_h">'dba_sync'</span><span class="sy0">,</span><span class="st_h">'dbase_add_record'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'dbase_close'</span><span class="sy0">,</span><span class="st_h">'dbase_create'</span><span class="sy0">,</span><span class="st_h">'dbase_delete_record'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'dbase_get_header_info'</span><span class="sy0">,</span><span class="st_h">'dbase_get_record'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'dbase_get_record_with_names'</span><span class="sy0">,</span><span class="st_h">'dbase_numfields'</span><span class="sy0">,</span><span class="st_h">'dbase_numrecords'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'dbase_open'</span><span class="sy0">,</span><span class="st_h">'dbase_pack'</span><span class="sy0">,</span><span class="st_h">'dbase_replace_record'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'dbg_get_all_contexts'</span><span class="sy0">,</span><span class="st_h">'dbg_get_all_module_names'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'dbg_get_all_source_lines'</span><span class="sy0">,</span><span class="st_h">'dbg_get_context_name'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'dbg_get_module_name'</span><span class="sy0">,</span><span class="st_h">'dbg_get_profiler_results'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'dbg_get_source_context'</span><span class="sy0">,</span><span class="st_h">'dblist'</span><span class="sy0">,</span><span class="st_h">'dbmclose'</span><span class="sy0">,</span><span class="st_h">'dbmdelete'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'dbmexists'</span><span class="sy0">,</span><span class="st_h">'dbmfetch'</span><span class="sy0">,</span><span class="st_h">'dbmfirstkey'</span><span class="sy0">,</span><span class="st_h">'dbminsert'</span><span class="sy0">,</span><span class="st_h">'dbmnextkey'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'dbmopen'</span><span class="sy0">,</span><span class="st_h">'dbmreplace'</span><span class="sy0">,</span><span class="st_h">'dbx_close'</span><span class="sy0">,</span><span class="st_h">'dbx_compare'</span><span class="sy0">,</span><span class="st_h">'dbx_connect'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'dbx_error'</span><span class="sy0">,</span><span class="st_h">'dbx_escape_string'</span><span class="sy0">,</span><span class="st_h">'dbx_fetch_row'</span><span class="sy0">,</span><span class="st_h">'dbx_query'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'dbx_sort'</span><span class="sy0">,</span><span class="st_h">'dcgettext'</span><span class="sy0">,</span><span class="st_h">'dcngettext'</span><span class="sy0">,</span><span class="st_h">'deaggregate'</span><span class="sy0">,</span><span class="st_h">'debug_backtrace'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'debug_zval_dump'</span><span class="sy0">,</span><span class="st_h">'debugbreak'</span><span class="sy0">,</span><span class="st_h">'decbin'</span><span class="sy0">,</span><span class="st_h">'dechex'</span><span class="sy0">,</span><span class="st_h">'decoct'</span><span class="sy0">,</span><span class="st_h">'define'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'defined'</span><span class="sy0">,</span><span class="st_h">'define_syslog_variables'</span><span class="sy0">,</span><span class="st_h">'deg2rad'</span><span class="sy0">,</span><span class="st_h">'dgettext'</span><span class="sy0">,</span><span class="st_h">'die'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'dio_close'</span><span class="sy0">,</span><span class="st_h">'dio_open'</span><span class="sy0">,</span><span class="st_h">'dio_read'</span><span class="sy0">,</span><span class="st_h">'dio_seek'</span><span class="sy0">,</span><span class="st_h">'dio_stat'</span><span class="sy0">,</span><span class="st_h">'dio_write'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'dir'</span><span class="sy0">,</span><span class="st_h">'dirname'</span><span class="sy0">,</span><span class="st_h">'disk_free_space'</span><span class="sy0">,</span><span class="st_h">'disk_total_space'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'diskfreespace'</span><span class="sy0">,</span><span class="st_h">'dl'</span><span class="sy0">,</span><span class="st_h">'dngettext'</span><span class="sy0">,</span><span class="st_h">'docblock_token_name'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'docblock_tokenize'</span><span class="sy0">,</span><span class="st_h">'dom_import_simplexml'</span><span class="sy0">,</span><span class="st_h">'domxml_add_root'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_attributes'</span><span class="sy0">,</span><span class="st_h">'domxml_children'</span><span class="sy0">,</span><span class="st_h">'domxml_doc_add_root'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_doc_document_element'</span><span class="sy0">,</span><span class="st_h">'domxml_doc_get_element_by_id'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_doc_get_elements_by_tagname'</span><span class="sy0">,</span><span class="st_h">'domxml_doc_get_root'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_doc_set_root'</span><span class="sy0">,</span><span class="st_h">'domxml_doc_validate'</span><span class="sy0">,</span><span class="st_h">'domxml_doc_xinclude'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_dump_mem'</span><span class="sy0">,</span><span class="st_h">'domxml_dump_mem_file'</span><span class="sy0">,</span><span class="st_h">'domxml_dump_node'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_dumpmem'</span><span class="sy0">,</span><span class="st_h">'domxml_elem_get_attribute'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_elem_set_attribute'</span><span class="sy0">,</span><span class="st_h">'domxml_get_attribute'</span><span class="sy0">,</span><span class="st_h">'domxml_getattr'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_html_dump_mem'</span><span class="sy0">,</span><span class="st_h">'domxml_new_child'</span><span class="sy0">,</span><span class="st_h">'domxml_new_doc'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_new_xmldoc'</span><span class="sy0">,</span><span class="st_h">'domxml_node'</span><span class="sy0">,</span><span class="st_h">'domxml_node_add_namespace'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_node_attributes'</span><span class="sy0">,</span><span class="st_h">'domxml_node_children'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_node_get_content'</span><span class="sy0">,</span><span class="st_h">'domxml_node_has_attributes'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_node_new_child'</span><span class="sy0">,</span><span class="st_h">'domxml_node_set_content'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_node_set_namespace'</span><span class="sy0">,</span><span class="st_h">'domxml_node_unlink_node'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_open_file'</span><span class="sy0">,</span><span class="st_h">'domxml_open_mem'</span><span class="sy0">,</span><span class="st_h">'domxml_parser'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_parser_add_chunk'</span><span class="sy0">,</span><span class="st_h">'domxml_parser_cdata_section'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_parser_characters'</span><span class="sy0">,</span><span class="st_h">'domxml_parser_comment'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_parser_end'</span><span class="sy0">,</span><span class="st_h">'domxml_parser_end_document'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_parser_end_element'</span><span class="sy0">,</span><span class="st_h">'domxml_parser_entity_reference'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_parser_get_document'</span><span class="sy0">,</span><span class="st_h">'domxml_parser_namespace_decl'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_parser_processing_instruction'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_parser_start_document'</span><span class="sy0">,</span><span class="st_h">'domxml_parser_start_element'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_root'</span><span class="sy0">,</span><span class="st_h">'domxml_set_attribute'</span><span class="sy0">,</span><span class="st_h">'domxml_setattr'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_substitute_entities_default'</span><span class="sy0">,</span><span class="st_h">'domxml_unlink_node'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'domxml_version'</span><span class="sy0">,</span><span class="st_h">'domxml_xmltree'</span><span class="sy0">,</span><span class="st_h">'doubleval'</span><span class="sy0">,</span><span class="st_h">'each'</span><span class="sy0">,</span><span class="st_h">'easter_date'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'easter_days'</span><span class="sy0">,</span><span class="st_h">'empty'</span><span class="sy0">,</span><span class="st_h">'end'</span><span class="sy0">,</span><span class="st_h">'ereg'</span><span class="sy0">,</span><span class="st_h">'ereg_replace'</span><span class="sy0">,</span><span class="st_h">'eregi'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'eregi_replace'</span><span class="sy0">,</span><span class="st_h">'error_get_last'</span><span class="sy0">,</span><span class="st_h">'error_log'</span><span class="sy0">,</span><span class="st_h">'error_reporting'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'escapeshellarg'</span><span class="sy0">,</span><span class="st_h">'escapeshellcmd'</span><span class="sy0">,</span><span class="st_h">'eval'</span><span class="sy0">,</span><span class="st_h">'event_deschedule'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'event_dispatch'</span><span class="sy0">,</span><span class="st_h">'event_free'</span><span class="sy0">,</span><span class="st_h">'event_handle_signal'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'event_have_events'</span><span class="sy0">,</span><span class="st_h">'event_init'</span><span class="sy0">,</span><span class="st_h">'event_new'</span><span class="sy0">,</span><span class="st_h">'event_pending'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'event_priority_set'</span><span class="sy0">,</span><span class="st_h">'event_schedule'</span><span class="sy0">,</span><span class="st_h">'event_set'</span><span class="sy0">,</span><span class="st_h">'event_timeout'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'exec'</span><span class="sy0">,</span><span class="st_h">'exif_imagetype'</span><span class="sy0">,</span><span class="st_h">'exif_read_data'</span><span class="sy0">,</span><span class="st_h">'exif_tagname'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'exif_thumbnail'</span><span class="sy0">,</span><span class="st_h">'exit'</span><span class="sy0">,</span><span class="st_h">'exp'</span><span class="sy0">,</span><span class="st_h">'explode'</span><span class="sy0">,</span><span class="st_h">'expm1'</span><span class="sy0">,</span><span class="st_h">'extension_loaded'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'extract'</span><span class="sy0">,</span><span class="st_h">'ezmlm_hash'</span><span class="sy0">,</span><span class="st_h">'fbird_add_user'</span><span class="sy0">,</span><span class="st_h">'fbird_affected_rows'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fbird_backup'</span><span class="sy0">,</span><span class="st_h">'fbird_blob_add'</span><span class="sy0">,</span><span class="st_h">'fbird_blob_cancel'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fbird_blob_close'</span><span class="sy0">,</span><span class="st_h">'fbird_blob_create'</span><span class="sy0">,</span><span class="st_h">'fbird_blob_echo'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fbird_blob_get'</span><span class="sy0">,</span><span class="st_h">'fbird_blob_import'</span><span class="sy0">,</span><span class="st_h">'fbird_blob_info'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fbird_blob_open'</span><span class="sy0">,</span><span class="st_h">'fbird_close'</span><span class="sy0">,</span><span class="st_h">'fbird_commit'</span><span class="sy0">,</span><span class="st_h">'fbird_commit_ret'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fbird_connect'</span><span class="sy0">,</span><span class="st_h">'fbird_db_info'</span><span class="sy0">,</span><span class="st_h">'fbird_delete_user'</span><span class="sy0">,</span><span class="st_h">'fbird_drop_db'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fbird_errcode'</span><span class="sy0">,</span><span class="st_h">'fbird_errmsg'</span><span class="sy0">,</span><span class="st_h">'fbird_execute'</span><span class="sy0">,</span><span class="st_h">'fbird_fetch_assoc'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fbird_fetch_object'</span><span class="sy0">,</span><span class="st_h">'fbird_fetch_row'</span><span class="sy0">,</span><span class="st_h">'fbird_field_info'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fbird_free_event_handler'</span><span class="sy0">,</span><span class="st_h">'fbird_free_query'</span><span class="sy0">,</span><span class="st_h">'fbird_free_result'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fbird_gen_id'</span><span class="sy0">,</span><span class="st_h">'fbird_maintain_db'</span><span class="sy0">,</span><span class="st_h">'fbird_modify_user'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fbird_name_result'</span><span class="sy0">,</span><span class="st_h">'fbird_num_fields'</span><span class="sy0">,</span><span class="st_h">'fbird_num_params'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fbird_param_info'</span><span class="sy0">,</span><span class="st_h">'fbird_pconnect'</span><span class="sy0">,</span><span class="st_h">'fbird_prepare'</span><span class="sy0">,</span><span class="st_h">'fbird_query'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fbird_restore'</span><span class="sy0">,</span><span class="st_h">'fbird_rollback'</span><span class="sy0">,</span><span class="st_h">'fbird_rollback_ret'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fbird_server_info'</span><span class="sy0">,</span><span class="st_h">'fbird_service_attach'</span><span class="sy0">,</span><span class="st_h">'fbird_service_detach'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fbird_set_event_handler'</span><span class="sy0">,</span><span class="st_h">'fbird_trans'</span><span class="sy0">,</span><span class="st_h">'fbird_wait_event'</span><span class="sy0">,</span><span class="st_h">'fclose'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fdf_add_doc_javascript'</span><span class="sy0">,</span><span class="st_h">'fdf_add_template'</span><span class="sy0">,</span><span class="st_h">'fdf_close'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fdf_create'</span><span class="sy0">,</span><span class="st_h">'fdf_enum_values'</span><span class="sy0">,</span><span class="st_h">'fdf_errno'</span><span class="sy0">,</span><span class="st_h">'fdf_error'</span><span class="sy0">,</span><span class="st_h">'fdf_get_ap'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fdf_get_attachment'</span><span class="sy0">,</span><span class="st_h">'fdf_get_encoding'</span><span class="sy0">,</span><span class="st_h">'fdf_get_file'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fdf_get_flags'</span><span class="sy0">,</span><span class="st_h">'fdf_get_opt'</span><span class="sy0">,</span><span class="st_h">'fdf_get_status'</span><span class="sy0">,</span><span class="st_h">'fdf_get_value'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fdf_get_version'</span><span class="sy0">,</span><span class="st_h">'fdf_header'</span><span class="sy0">,</span><span class="st_h">'fdf_next_field_name'</span><span class="sy0">,</span><span class="st_h">'fdf_open'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fdf_open_string'</span><span class="sy0">,</span><span class="st_h">'fdf_remove_item'</span><span class="sy0">,</span><span class="st_h">'fdf_save'</span><span class="sy0">,</span><span class="st_h">'fdf_save_string'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fdf_set_ap'</span><span class="sy0">,</span><span class="st_h">'fdf_set_encoding'</span><span class="sy0">,</span><span class="st_h">'fdf_set_file'</span><span class="sy0">,</span><span class="st_h">'fdf_set_flags'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fdf_set_javascript_action'</span><span class="sy0">,</span><span class="st_h">'fdf_set_on_import_javascript'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fdf_set_opt'</span><span class="sy0">,</span><span class="st_h">'fdf_set_status'</span><span class="sy0">,</span><span class="st_h">'fdf_set_submit_form_action'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fdf_set_target_frame'</span><span class="sy0">,</span><span class="st_h">'fdf_set_value'</span><span class="sy0">,</span><span class="st_h">'fdf_set_version'</span><span class="sy0">,</span><span class="st_h">'feof'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fflush'</span><span class="sy0">,</span><span class="st_h">'fgetc'</span><span class="sy0">,</span><span class="st_h">'fgetcsv'</span><span class="sy0">,</span><span class="st_h">'fgets'</span><span class="sy0">,</span><span class="st_h">'fgetss'</span><span class="sy0">,</span><span class="st_h">'file'</span><span class="sy0">,</span><span class="st_h">'file_exists'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'file_get_contents'</span><span class="sy0">,</span><span class="st_h">'file_put_contents'</span><span class="sy0">,</span><span class="st_h">'fileatime'</span><span class="sy0">,</span><span class="st_h">'filectime'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'filegroup'</span><span class="sy0">,</span><span class="st_h">'fileinode'</span><span class="sy0">,</span><span class="st_h">'filemtime'</span><span class="sy0">,</span><span class="st_h">'fileowner'</span><span class="sy0">,</span><span class="st_h">'fileperms'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'filepro'</span><span class="sy0">,</span><span class="st_h">'filepro_fieldcount'</span><span class="sy0">,</span><span class="st_h">'filepro_fieldname'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'filepro_fieldtype'</span><span class="sy0">,</span><span class="st_h">'filepro_fieldwidth'</span><span class="sy0">,</span><span class="st_h">'filepro_retrieve'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'filepro_rowcount'</span><span class="sy0">,</span><span class="st_h">'filesize'</span><span class="sy0">,</span><span class="st_h">'filetype'</span><span class="sy0">,</span><span class="st_h">'filter_has_var'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'filter_id'</span><span class="sy0">,</span><span class="st_h">'filter_input'</span><span class="sy0">,</span><span class="st_h">'filter_input_array'</span><span class="sy0">,</span><span class="st_h">'filter_list'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'filter_var'</span><span class="sy0">,</span><span class="st_h">'filter_var_array'</span><span class="sy0">,</span><span class="st_h">'finfo_buffer'</span><span class="sy0">,</span><span class="st_h">'finfo_close'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'finfo_file'</span><span class="sy0">,</span><span class="st_h">'finfo_open'</span><span class="sy0">,</span><span class="st_h">'finfo_set_flags'</span><span class="sy0">,</span><span class="st_h">'floatval'</span><span class="sy0">,</span><span class="st_h">'flock'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'floor'</span><span class="sy0">,</span><span class="st_h">'flush'</span><span class="sy0">,</span><span class="st_h">'fmod'</span><span class="sy0">,</span><span class="st_h">'fnmatch'</span><span class="sy0">,</span><span class="st_h">'fopen'</span><span class="sy0">,</span><span class="st_h">'fpassthru'</span><span class="sy0">,</span><span class="st_h">'fprintf'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fputcsv'</span><span class="sy0">,</span><span class="st_h">'fputs'</span><span class="sy0">,</span><span class="st_h">'fread'</span><span class="sy0">,</span><span class="st_h">'frenchtojd'</span><span class="sy0">,</span><span class="st_h">'fribidi_charset_info'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fribidi_get_charsets'</span><span class="sy0">,</span><span class="st_h">'fribidi_log2vis'</span><span class="sy0">,</span><span class="st_h">'fscanf'</span><span class="sy0">,</span><span class="st_h">'fseek'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'fsockopen'</span><span class="sy0">,</span><span class="st_h">'fstat'</span><span class="sy0">,</span><span class="st_h">'ftell'</span><span class="sy0">,</span><span class="st_h">'ftok'</span><span class="sy0">,</span><span class="st_h">'ftp_alloc'</span><span class="sy0">,</span><span class="st_h">'ftp_cdup'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ftp_chdir'</span><span class="sy0">,</span><span class="st_h">'ftp_chmod'</span><span class="sy0">,</span><span class="st_h">'ftp_close'</span><span class="sy0">,</span><span class="st_h">'ftp_connect'</span><span class="sy0">,</span><span class="st_h">'ftp_delete'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ftp_exec'</span><span class="sy0">,</span><span class="st_h">'ftp_fget'</span><span class="sy0">,</span><span class="st_h">'ftp_fput'</span><span class="sy0">,</span><span class="st_h">'ftp_get'</span><span class="sy0">,</span><span class="st_h">'ftp_get_option'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ftp_login'</span><span class="sy0">,</span><span class="st_h">'ftp_mdtm'</span><span class="sy0">,</span><span class="st_h">'ftp_mkdir'</span><span class="sy0">,</span><span class="st_h">'ftp_nb_continue'</span><span class="sy0">,</span><span class="st_h">'ftp_nb_fget'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ftp_nb_fput'</span><span class="sy0">,</span><span class="st_h">'ftp_nb_get'</span><span class="sy0">,</span><span class="st_h">'ftp_nb_put'</span><span class="sy0">,</span><span class="st_h">'ftp_nlist'</span><span class="sy0">,</span><span class="st_h">'ftp_pasv'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ftp_put'</span><span class="sy0">,</span><span class="st_h">'ftp_pwd'</span><span class="sy0">,</span><span class="st_h">'ftp_quit'</span><span class="sy0">,</span><span class="st_h">'ftp_raw'</span><span class="sy0">,</span><span class="st_h">'ftp_rawlist'</span><span class="sy0">,</span><span class="st_h">'ftp_rename'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ftp_rmdir'</span><span class="sy0">,</span><span class="st_h">'ftp_set_option'</span><span class="sy0">,</span><span class="st_h">'ftp_site'</span><span class="sy0">,</span><span class="st_h">'ftp_size'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ftp_ssl_connect'</span><span class="sy0">,</span><span class="st_h">'ftp_systype'</span><span class="sy0">,</span><span class="st_h">'ftruncate'</span><span class="sy0">,</span><span class="st_h">'function_exists'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'func_get_arg'</span><span class="sy0">,</span><span class="st_h">'func_get_args'</span><span class="sy0">,</span><span class="st_h">'func_num_args'</span><span class="sy0">,</span><span class="st_h">'fwrite'</span><span class="sy0">,</span><span class="st_h">'gd_info'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'getallheaders'</span><span class="sy0">,</span><span class="st_h">'getcwd'</span><span class="sy0">,</span><span class="st_h">'getdate'</span><span class="sy0">,</span><span class="st_h">'getenv'</span><span class="sy0">,</span><span class="st_h">'gethostbyaddr'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'gethostbyname'</span><span class="sy0">,</span><span class="st_h">'gethostbynamel'</span><span class="sy0">,</span><span class="st_h">'getimagesize'</span><span class="sy0">,</span><span class="st_h">'getlastmod'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'getmxrr'</span><span class="sy0">,</span><span class="st_h">'getmygid'</span><span class="sy0">,</span><span class="st_h">'getmyinode'</span><span class="sy0">,</span><span class="st_h">'getmypid'</span><span class="sy0">,</span><span class="st_h">'getmyuid'</span><span class="sy0">,</span><span class="st_h">'getopt'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'getprotobyname'</span><span class="sy0">,</span><span class="st_h">'getprotobynumber'</span><span class="sy0">,</span><span class="st_h">'getrandmax'</span><span class="sy0">,</span><span class="st_h">'getrusage'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'getservbyname'</span><span class="sy0">,</span><span class="st_h">'getservbyport'</span><span class="sy0">,</span><span class="st_h">'gettext'</span><span class="sy0">,</span><span class="st_h">'gettimeofday'</span><span class="sy0">,</span><span class="st_h">'gettype'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'get_browser'</span><span class="sy0">,</span><span class="st_h">'get_cfg_var'</span><span class="sy0">,</span><span class="st_h">'get_class'</span><span class="sy0">,</span><span class="st_h">'get_class_methods'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'get_class_vars'</span><span class="sy0">,</span><span class="st_h">'get_current_user'</span><span class="sy0">,</span><span class="st_h">'get_declared_classes'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'get_defined_constants'</span><span class="sy0">,</span><span class="st_h">'get_defined_functions'</span><span class="sy0">,</span><span class="st_h">'get_defined_vars'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'get_extension_funcs'</span><span class="sy0">,</span><span class="st_h">'get_headers'</span><span class="sy0">,</span><span class="st_h">'get_html_translation_table'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'get_included_files'</span><span class="sy0">,</span><span class="st_h">'get_include_path'</span><span class="sy0">,</span><span class="st_h">'get_loaded_extensions'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'get_magic_quotes_gpc'</span><span class="sy0">,</span><span class="st_h">'get_magic_quotes_runtime'</span><span class="sy0">,</span><span class="st_h">'get_meta_tags'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'get_object_vars'</span><span class="sy0">,</span><span class="st_h">'get_parent_class'</span><span class="sy0">,</span><span class="st_h">'get_required_files'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'get_resource_type'</span><span class="sy0">,</span><span class="st_h">'glob'</span><span class="sy0">,</span><span class="st_h">'gmdate'</span><span class="sy0">,</span><span class="st_h">'gmmktime'</span><span class="sy0">,</span><span class="st_h">'gmp_abs'</span><span class="sy0">,</span><span class="st_h">'gmp_add'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'gmp_and'</span><span class="sy0">,</span><span class="st_h">'gmp_clrbit'</span><span class="sy0">,</span><span class="st_h">'gmp_cmp'</span><span class="sy0">,</span><span class="st_h">'gmp_com'</span><span class="sy0">,</span><span class="st_h">'gmp_div'</span><span class="sy0">,</span><span class="st_h">'gmp_div_q'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'gmp_div_qr'</span><span class="sy0">,</span><span class="st_h">'gmp_div_r'</span><span class="sy0">,</span><span class="st_h">'gmp_divexact'</span><span class="sy0">,</span><span class="st_h">'gmp_fact'</span><span class="sy0">,</span><span class="st_h">'gmp_gcd'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'gmp_gcdext'</span><span class="sy0">,</span><span class="st_h">'gmp_hamdist'</span><span class="sy0">,</span><span class="st_h">'gmp_init'</span><span class="sy0">,</span><span class="st_h">'gmp_intval'</span><span class="sy0">,</span><span class="st_h">'gmp_invert'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'gmp_jacobi'</span><span class="sy0">,</span><span class="st_h">'gmp_legendre'</span><span class="sy0">,</span><span class="st_h">'gmp_mod'</span><span class="sy0">,</span><span class="st_h">'gmp_mul'</span><span class="sy0">,</span><span class="st_h">'gmp_neg'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'gmp_nextprime'</span><span class="sy0">,</span><span class="st_h">'gmp_or'</span><span class="sy0">,</span><span class="st_h">'gmp_perfect_square'</span><span class="sy0">,</span><span class="st_h">'gmp_popcount'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'gmp_pow'</span><span class="sy0">,</span><span class="st_h">'gmp_powm'</span><span class="sy0">,</span><span class="st_h">'gmp_prob_prime'</span><span class="sy0">,</span><span class="st_h">'gmp_random'</span><span class="sy0">,</span><span class="st_h">'gmp_scan0'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'gmp_scan1'</span><span class="sy0">,</span><span class="st_h">'gmp_setbit'</span><span class="sy0">,</span><span class="st_h">'gmp_sign'</span><span class="sy0">,</span><span class="st_h">'gmp_sqrt'</span><span class="sy0">,</span><span class="st_h">'gmp_sqrtrem'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'gmp_strval'</span><span class="sy0">,</span><span class="st_h">'gmp_sub'</span><span class="sy0">,</span><span class="st_h">'gmp_xor'</span><span class="sy0">,</span><span class="st_h">'gmstrftime'</span><span class="sy0">,</span><span class="st_h">'gopher_parsedir'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'gregoriantojd'</span><span class="sy0">,</span><span class="st_h">'gzclose'</span><span class="sy0">,</span><span class="st_h">'gzcompress'</span><span class="sy0">,</span><span class="st_h">'gzdeflate'</span><span class="sy0">,</span><span class="st_h">'gzencode'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'gzeof'</span><span class="sy0">,</span><span class="st_h">'gzfile'</span><span class="sy0">,</span><span class="st_h">'gzgetc'</span><span class="sy0">,</span><span class="st_h">'gzgets'</span><span class="sy0">,</span><span class="st_h">'gzgetss'</span><span class="sy0">,</span><span class="st_h">'gzinflate'</span><span class="sy0">,</span><span class="st_h">'gzopen'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'gzpassthru'</span><span class="sy0">,</span><span class="st_h">'gzputs'</span><span class="sy0">,</span><span class="st_h">'gzread'</span><span class="sy0">,</span><span class="st_h">'gzrewind'</span><span class="sy0">,</span><span class="st_h">'gzseek'</span><span class="sy0">,</span><span class="st_h">'gztell'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'gzuncompress'</span><span class="sy0">,</span><span class="st_h">'gzwrite'</span><span class="sy0">,</span><span class="st_h">'hash'</span><span class="sy0">,</span><span class="st_h">'hash_algos'</span><span class="sy0">,</span><span class="st_h">'hash_file'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'hash_final'</span><span class="sy0">,</span><span class="st_h">'hash_hmac'</span><span class="sy0">,</span><span class="st_h">'hash_hmac_file'</span><span class="sy0">,</span><span class="st_h">'hash_init'</span><span class="sy0">,</span><span class="st_h">'hash_update'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'hash_update_file'</span><span class="sy0">,</span><span class="st_h">'hash_update_stream'</span><span class="sy0">,</span><span class="st_h">'header'</span><span class="sy0">,</span><span class="st_h">'headers_list'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'headers_sent'</span><span class="sy0">,</span><span class="st_h">'hebrev'</span><span class="sy0">,</span><span class="st_h">'hebrevc'</span><span class="sy0">,</span><span class="st_h">'hexdec'</span><span class="sy0">,</span><span class="st_h">'highlight_file'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'highlight_string'</span><span class="sy0">,</span><span class="st_h">'html_doc'</span><span class="sy0">,</span><span class="st_h">'html_doc_file'</span><span class="sy0">,</span><span class="st_h">'html_entity_decode'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'htmlentities'</span><span class="sy0">,</span><span class="st_h">'htmlspecialchars'</span><span class="sy0">,</span><span class="st_h">'htmlspecialchars_decode'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'http_build_cookie'</span><span class="sy0">,</span><span class="st_h">'http_build_query'</span><span class="sy0">,</span><span class="st_h">'http_build_str'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'http_build_url'</span><span class="sy0">,</span><span class="st_h">'http_cache_etag'</span><span class="sy0">,</span><span class="st_h">'http_cache_last_modified'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'http_chunked_decode'</span><span class="sy0">,</span><span class="st_h">'http_date'</span><span class="sy0">,</span><span class="st_h">'http_deflate'</span><span class="sy0">,</span><span class="st_h">'http_get'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'http_get_request_body'</span><span class="sy0">,</span><span class="st_h">'http_get_request_body_stream'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'http_get_request_headers'</span><span class="sy0">,</span><span class="st_h">'http_head'</span><span class="sy0">,</span><span class="st_h">'http_inflate'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'http_match_etag'</span><span class="sy0">,</span><span class="st_h">'http_match_modified'</span><span class="sy0">,</span><span class="st_h">'http_match_request_header'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'http_negotiate_charset'</span><span class="sy0">,</span><span class="st_h">'http_negotiate_content_type'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'http_negotiate_language'</span><span class="sy0">,</span><span class="st_h">'http_parse_cookie'</span><span class="sy0">,</span><span class="st_h">'http_parse_headers'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'http_parse_message'</span><span class="sy0">,</span><span class="st_h">'http_parse_params'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'http_persistent_handles_clean'</span><span class="sy0">,</span><span class="st_h">'http_persistent_handles_count'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'http_persistent_handles_ident'</span><span class="sy0">,</span><span class="st_h">'http_post_data'</span><span class="sy0">,</span><span class="st_h">'http_post_fields'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'http_put_data'</span><span class="sy0">,</span><span class="st_h">'http_put_file'</span><span class="sy0">,</span><span class="st_h">'http_put_stream'</span><span class="sy0">,</span><span class="st_h">'http_redirect'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'http_request'</span><span class="sy0">,</span><span class="st_h">'http_request_body_encode'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'http_request_method_exists'</span><span class="sy0">,</span><span class="st_h">'http_request_method_name'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'http_request_method_register'</span><span class="sy0">,</span><span class="st_h">'http_request_method_unregister'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'http_send_content_disposition'</span><span class="sy0">,</span><span class="st_h">'http_send_content_type'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'http_send_data'</span><span class="sy0">,</span><span class="st_h">'http_send_file'</span><span class="sy0">,</span><span class="st_h">'http_send_last_modified'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'http_send_status'</span><span class="sy0">,</span><span class="st_h">'http_send_stream'</span><span class="sy0">,</span><span class="st_h">'http_support'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'http_throttle'</span><span class="sy0">,</span><span class="st_h">'hypot'</span><span class="sy0">,</span><span class="st_h">'i18n_convert'</span><span class="sy0">,</span><span class="st_h">'i18n_discover_encoding'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'i18n_http_input'</span><span class="sy0">,</span><span class="st_h">'i18n_http_output'</span><span class="sy0">,</span><span class="st_h">'i18n_internal_encoding'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'i18n_ja_jp_hantozen'</span><span class="sy0">,</span><span class="st_h">'i18n_mime_header_decode'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'i18n_mime_header_encode'</span><span class="sy0">,</span><span class="st_h">'ibase_add_user'</span><span class="sy0">,</span><span class="st_h">'ibase_affected_rows'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ibase_backup'</span><span class="sy0">,</span><span class="st_h">'ibase_blob_add'</span><span class="sy0">,</span><span class="st_h">'ibase_blob_cancel'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ibase_blob_close'</span><span class="sy0">,</span><span class="st_h">'ibase_blob_create'</span><span class="sy0">,</span><span class="st_h">'ibase_blob_echo'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ibase_blob_get'</span><span class="sy0">,</span><span class="st_h">'ibase_blob_import'</span><span class="sy0">,</span><span class="st_h">'ibase_blob_info'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ibase_blob_open'</span><span class="sy0">,</span><span class="st_h">'ibase_close'</span><span class="sy0">,</span><span class="st_h">'ibase_commit'</span><span class="sy0">,</span><span class="st_h">'ibase_commit_ret'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ibase_connect'</span><span class="sy0">,</span><span class="st_h">'ibase_db_info'</span><span class="sy0">,</span><span class="st_h">'ibase_delete_user'</span><span class="sy0">,</span><span class="st_h">'ibase_drop_db'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ibase_errcode'</span><span class="sy0">,</span><span class="st_h">'ibase_errmsg'</span><span class="sy0">,</span><span class="st_h">'ibase_execute'</span><span class="sy0">,</span><span class="st_h">'ibase_fetch_assoc'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ibase_fetch_object'</span><span class="sy0">,</span><span class="st_h">'ibase_fetch_row'</span><span class="sy0">,</span><span class="st_h">'ibase_field_info'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ibase_free_event_handler'</span><span class="sy0">,</span><span class="st_h">'ibase_free_query'</span><span class="sy0">,</span><span class="st_h">'ibase_free_result'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ibase_gen_id'</span><span class="sy0">,</span><span class="st_h">'ibase_maintain_db'</span><span class="sy0">,</span><span class="st_h">'ibase_modify_user'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ibase_name_result'</span><span class="sy0">,</span><span class="st_h">'ibase_num_fields'</span><span class="sy0">,</span><span class="st_h">'ibase_num_params'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ibase_param_info'</span><span class="sy0">,</span><span class="st_h">'ibase_pconnect'</span><span class="sy0">,</span><span class="st_h">'ibase_prepare'</span><span class="sy0">,</span><span class="st_h">'ibase_query'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ibase_restore'</span><span class="sy0">,</span><span class="st_h">'ibase_rollback'</span><span class="sy0">,</span><span class="st_h">'ibase_rollback_ret'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ibase_server_info'</span><span class="sy0">,</span><span class="st_h">'ibase_service_attach'</span><span class="sy0">,</span><span class="st_h">'ibase_service_detach'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ibase_set_event_handler'</span><span class="sy0">,</span><span class="st_h">'ibase_trans'</span><span class="sy0">,</span><span class="st_h">'ibase_wait_event'</span><span class="sy0">,</span><span class="st_h">'iconv'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'iconv_get_encoding'</span><span class="sy0">,</span><span class="st_h">'iconv_mime_decode'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'iconv_mime_decode_headers'</span><span class="sy0">,</span><span class="st_h">'iconv_mime_encode'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'iconv_set_encoding'</span><span class="sy0">,</span><span class="st_h">'iconv_strlen'</span><span class="sy0">,</span><span class="st_h">'iconv_strpos'</span><span class="sy0">,</span><span class="st_h">'iconv_strrpos'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'iconv_substr'</span><span class="sy0">,</span><span class="st_h">'id3_get_frame_long_name'</span><span class="sy0">,</span><span class="st_h">'id3_get_frame_short_name'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'id3_get_genre_id'</span><span class="sy0">,</span><span class="st_h">'id3_get_genre_list'</span><span class="sy0">,</span><span class="st_h">'id3_get_genre_name'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'id3_get_tag'</span><span class="sy0">,</span><span class="st_h">'id3_get_version'</span><span class="sy0">,</span><span class="st_h">'id3_remove_tag'</span><span class="sy0">,</span><span class="st_h">'id3_set_tag'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'idate'</span><span class="sy0">,</span><span class="st_h">'ignore_user_abort'</span><span class="sy0">,</span><span class="st_h">'image_type_to_extension'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'image_type_to_mime_type'</span><span class="sy0">,</span><span class="st_h">'image2wbmp'</span><span class="sy0">,</span><span class="st_h">'imagealphablending'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imageantialias'</span><span class="sy0">,</span><span class="st_h">'imagearc'</span><span class="sy0">,</span><span class="st_h">'imagechar'</span><span class="sy0">,</span><span class="st_h">'imagecharup'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagecolorallocate'</span><span class="sy0">,</span><span class="st_h">'imagecolorallocatealpha'</span><span class="sy0">,</span><span class="st_h">'imagecolorat'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagecolorclosest'</span><span class="sy0">,</span><span class="st_h">'imagecolorclosestalpha'</span><span class="sy0">,</span><span class="st_h">'imagecolordeallocate'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagecolorexact'</span><span class="sy0">,</span><span class="st_h">'imagecolorexactalpha'</span><span class="sy0">,</span><span class="st_h">'imagecolormatch'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagecolorresolve'</span><span class="sy0">,</span><span class="st_h">'imagecolorresolvealpha'</span><span class="sy0">,</span><span class="st_h">'imagecolorset'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagecolorsforindex'</span><span class="sy0">,</span><span class="st_h">'imagecolorstotal'</span><span class="sy0">,</span><span class="st_h">'imagecolortransparent'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imageconvolution'</span><span class="sy0">,</span><span class="st_h">'imagecopy'</span><span class="sy0">,</span><span class="st_h">'imagecopymerge'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagecopymergegray'</span><span class="sy0">,</span><span class="st_h">'imagecopyresampled'</span><span class="sy0">,</span><span class="st_h">'imagecopyresized'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagecreate'</span><span class="sy0">,</span><span class="st_h">'imagecreatefromgd'</span><span class="sy0">,</span><span class="st_h">'imagecreatefromgd2'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagecreatefromgd2part'</span><span class="sy0">,</span><span class="st_h">'imagecreatefromgif'</span><span class="sy0">,</span><span class="st_h">'imagecreatefromjpeg'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagecreatefrompng'</span><span class="sy0">,</span><span class="st_h">'imagecreatefromstring'</span><span class="sy0">,</span><span class="st_h">'imagecreatefromwbmp'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagecreatefromxbm'</span><span class="sy0">,</span><span class="st_h">'imagecreatetruecolor'</span><span class="sy0">,</span><span class="st_h">'imagedashedline'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagedestroy'</span><span class="sy0">,</span><span class="st_h">'imageellipse'</span><span class="sy0">,</span><span class="st_h">'imagefill'</span><span class="sy0">,</span><span class="st_h">'imagefilledarc'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagefilledellipse'</span><span class="sy0">,</span><span class="st_h">'imagefilledpolygon'</span><span class="sy0">,</span><span class="st_h">'imagefilledrectangle'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagefilltoborder'</span><span class="sy0">,</span><span class="st_h">'imagefilter'</span><span class="sy0">,</span><span class="st_h">'imagefontheight'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagefontwidth'</span><span class="sy0">,</span><span class="st_h">'imageftbbox'</span><span class="sy0">,</span><span class="st_h">'imagefttext'</span><span class="sy0">,</span><span class="st_h">'imagegammacorrect'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagegd'</span><span class="sy0">,</span><span class="st_h">'imagegd2'</span><span class="sy0">,</span><span class="st_h">'imagegif'</span><span class="sy0">,</span><span class="st_h">'imagegrabscreen'</span><span class="sy0">,</span><span class="st_h">'imagegrabwindow'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imageinterlace'</span><span class="sy0">,</span><span class="st_h">'imageistruecolor'</span><span class="sy0">,</span><span class="st_h">'imagejpeg'</span><span class="sy0">,</span><span class="st_h">'imagelayereffect'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imageline'</span><span class="sy0">,</span><span class="st_h">'imageloadfont'</span><span class="sy0">,</span><span class="st_h">'imagepalettecopy'</span><span class="sy0">,</span><span class="st_h">'imagepng'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagepolygon'</span><span class="sy0">,</span><span class="st_h">'imagepsbbox'</span><span class="sy0">,</span><span class="st_h">'imagepsencodefont'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagepsextendfont'</span><span class="sy0">,</span><span class="st_h">'imagepsfreefont'</span><span class="sy0">,</span><span class="st_h">'imagepsloadfont'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagepsslantfont'</span><span class="sy0">,</span><span class="st_h">'imagepstext'</span><span class="sy0">,</span><span class="st_h">'imagerectangle'</span><span class="sy0">,</span><span class="st_h">'imagerotate'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagesavealpha'</span><span class="sy0">,</span><span class="st_h">'imagesetbrush'</span><span class="sy0">,</span><span class="st_h">'imagesetpixel'</span><span class="sy0">,</span><span class="st_h">'imagesetstyle'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagesetthickness'</span><span class="sy0">,</span><span class="st_h">'imagesettile'</span><span class="sy0">,</span><span class="st_h">'imagestring'</span><span class="sy0">,</span><span class="st_h">'imagestringup'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagesx'</span><span class="sy0">,</span><span class="st_h">'imagesy'</span><span class="sy0">,</span><span class="st_h">'imagetruecolortopalette'</span><span class="sy0">,</span><span class="st_h">'imagettfbbox'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imagettftext'</span><span class="sy0">,</span><span class="st_h">'imagetypes'</span><span class="sy0">,</span><span class="st_h">'imagewbmp'</span><span class="sy0">,</span><span class="st_h">'imagexbm'</span><span class="sy0">,</span><span class="st_h">'imap_8bit'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_alerts'</span><span class="sy0">,</span><span class="st_h">'imap_append'</span><span class="sy0">,</span><span class="st_h">'imap_base64'</span><span class="sy0">,</span><span class="st_h">'imap_binary'</span><span class="sy0">,</span><span class="st_h">'imap_body'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_bodystruct'</span><span class="sy0">,</span><span class="st_h">'imap_check'</span><span class="sy0">,</span><span class="st_h">'imap_clearflag_full'</span><span class="sy0">,</span><span class="st_h">'imap_close'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_create'</span><span class="sy0">,</span><span class="st_h">'imap_createmailbox'</span><span class="sy0">,</span><span class="st_h">'imap_delete'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_deletemailbox'</span><span class="sy0">,</span><span class="st_h">'imap_errors'</span><span class="sy0">,</span><span class="st_h">'imap_expunge'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_fetch_overview'</span><span class="sy0">,</span><span class="st_h">'imap_fetchbody'</span><span class="sy0">,</span><span class="st_h">'imap_fetchheader'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_fetchstructure'</span><span class="sy0">,</span><span class="st_h">'imap_fetchtext'</span><span class="sy0">,</span><span class="st_h">'imap_get_quota'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_get_quotaroot'</span><span class="sy0">,</span><span class="st_h">'imap_getacl'</span><span class="sy0">,</span><span class="st_h">'imap_getmailboxes'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_getsubscribed'</span><span class="sy0">,</span><span class="st_h">'imap_header'</span><span class="sy0">,</span><span class="st_h">'imap_headerinfo'</span><span class="sy0">,</span><span class="st_h">'imap_headers'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_last_error'</span><span class="sy0">,</span><span class="st_h">'imap_list'</span><span class="sy0">,</span><span class="st_h">'imap_listmailbox'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_listsubscribed'</span><span class="sy0">,</span><span class="st_h">'imap_lsub'</span><span class="sy0">,</span><span class="st_h">'imap_mail'</span><span class="sy0">,</span><span class="st_h">'imap_mail_compose'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_mail_copy'</span><span class="sy0">,</span><span class="st_h">'imap_mail_move'</span><span class="sy0">,</span><span class="st_h">'imap_mailboxmsginfo'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_mime_header_decode'</span><span class="sy0">,</span><span class="st_h">'imap_msgno'</span><span class="sy0">,</span><span class="st_h">'imap_num_msg'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_num_recent'</span><span class="sy0">,</span><span class="st_h">'imap_open'</span><span class="sy0">,</span><span class="st_h">'imap_ping'</span><span class="sy0">,</span><span class="st_h">'imap_qprint'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_rename'</span><span class="sy0">,</span><span class="st_h">'imap_renamemailbox'</span><span class="sy0">,</span><span class="st_h">'imap_reopen'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_rfc822_parse_adrlist'</span><span class="sy0">,</span><span class="st_h">'imap_rfc822_parse_headers'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_rfc822_write_address'</span><span class="sy0">,</span><span class="st_h">'imap_savebody'</span><span class="sy0">,</span><span class="st_h">'imap_scan'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_scanmailbox'</span><span class="sy0">,</span><span class="st_h">'imap_search'</span><span class="sy0">,</span><span class="st_h">'imap_set_quota'</span><span class="sy0">,</span><span class="st_h">'imap_setacl'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_setflag_full'</span><span class="sy0">,</span><span class="st_h">'imap_sort'</span><span class="sy0">,</span><span class="st_h">'imap_status'</span><span class="sy0">,</span><span class="st_h">'imap_subscribe'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_thread'</span><span class="sy0">,</span><span class="st_h">'imap_timeout'</span><span class="sy0">,</span><span class="st_h">'imap_uid'</span><span class="sy0">,</span><span class="st_h">'imap_undelete'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_unsubscribe'</span><span class="sy0">,</span><span class="st_h">'imap_utf7_decode'</span><span class="sy0">,</span><span class="st_h">'imap_utf7_encode'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'imap_utf8'</span><span class="sy0">,</span><span class="st_h">'implode'</span><span class="sy0">,</span><span class="st_h">'import_request_variables'</span><span class="sy0">,</span><span class="st_h">'in_array'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ini_alter'</span><span class="sy0">,</span><span class="st_h">'ini_get'</span><span class="sy0">,</span><span class="st_h">'ini_get_all'</span><span class="sy0">,</span><span class="st_h">'ini_restore'</span><span class="sy0">,</span><span class="st_h">'ini_set'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'intval'</span><span class="sy0">,</span><span class="st_h">'ip2long'</span><span class="sy0">,</span><span class="st_h">'iptcembed'</span><span class="sy0">,</span><span class="st_h">'iptcparse'</span><span class="sy0">,</span><span class="st_h">'isset'</span><span class="sy0">,</span><span class="st_h">'is_a'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'is_array'</span><span class="sy0">,</span><span class="st_h">'is_bool'</span><span class="sy0">,</span><span class="st_h">'is_callable'</span><span class="sy0">,</span><span class="st_h">'is_dir'</span><span class="sy0">,</span><span class="st_h">'is_double'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'is_executable'</span><span class="sy0">,</span><span class="st_h">'is_file'</span><span class="sy0">,</span><span class="st_h">'is_finite'</span><span class="sy0">,</span><span class="st_h">'is_float'</span><span class="sy0">,</span><span class="st_h">'is_infinite'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'is_int'</span><span class="sy0">,</span><span class="st_h">'is_integer'</span><span class="sy0">,</span><span class="st_h">'is_link'</span><span class="sy0">,</span><span class="st_h">'is_long'</span><span class="sy0">,</span><span class="st_h">'is_nan'</span><span class="sy0">,</span><span class="st_h">'is_null'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'is_numeric'</span><span class="sy0">,</span><span class="st_h">'is_object'</span><span class="sy0">,</span><span class="st_h">'is_readable'</span><span class="sy0">,</span><span class="st_h">'is_real'</span><span class="sy0">,</span><span class="st_h">'is_resource'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'is_scalar'</span><span class="sy0">,</span><span class="st_h">'is_soap_fault'</span><span class="sy0">,</span><span class="st_h">'is_string'</span><span class="sy0">,</span><span class="st_h">'is_subclass_of'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'is_uploaded_file'</span><span class="sy0">,</span><span class="st_h">'is_writable'</span><span class="sy0">,</span><span class="st_h">'is_writeable'</span><span class="sy0">,</span><span class="st_h">'iterator_apply'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'iterator_count'</span><span class="sy0">,</span><span class="st_h">'iterator_to_array'</span><span class="sy0">,</span><span class="st_h">'java_last_exception_clear'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'java_last_exception_get'</span><span class="sy0">,</span><span class="st_h">'jddayofweek'</span><span class="sy0">,</span><span class="st_h">'jdmonthname'</span><span class="sy0">,</span><span class="st_h">'jdtofrench'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'jdtogregorian'</span><span class="sy0">,</span><span class="st_h">'jdtojewish'</span><span class="sy0">,</span><span class="st_h">'jdtojulian'</span><span class="sy0">,</span><span class="st_h">'jdtounix'</span><span class="sy0">,</span><span class="st_h">'jewishtojd'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'join'</span><span class="sy0">,</span><span class="st_h">'jpeg2wbmp'</span><span class="sy0">,</span><span class="st_h">'json_decode'</span><span class="sy0">,</span><span class="st_h">'json_encode'</span><span class="sy0">,</span><span class="st_h">'juliantojd'</span><span class="sy0">,</span><span class="st_h">'key'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'key_exists'</span><span class="sy0">,</span><span class="st_h">'krsort'</span><span class="sy0">,</span><span class="st_h">'ksort'</span><span class="sy0">,</span><span class="st_h">'lcg_value'</span><span class="sy0">,</span><span class="st_h">'ldap_add'</span><span class="sy0">,</span><span class="st_h">'ldap_bind'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ldap_close'</span><span class="sy0">,</span><span class="st_h">'ldap_compare'</span><span class="sy0">,</span><span class="st_h">'ldap_connect'</span><span class="sy0">,</span><span class="st_h">'ldap_count_entries'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ldap_delete'</span><span class="sy0">,</span><span class="st_h">'ldap_dn2ufn'</span><span class="sy0">,</span><span class="st_h">'ldap_err2str'</span><span class="sy0">,</span><span class="st_h">'ldap_errno'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ldap_error'</span><span class="sy0">,</span><span class="st_h">'ldap_explode_dn'</span><span class="sy0">,</span><span class="st_h">'ldap_first_attribute'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ldap_first_entry'</span><span class="sy0">,</span><span class="st_h">'ldap_first_reference'</span><span class="sy0">,</span><span class="st_h">'ldap_free_result'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ldap_get_attributes'</span><span class="sy0">,</span><span class="st_h">'ldap_get_dn'</span><span class="sy0">,</span><span class="st_h">'ldap_get_entries'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ldap_get_option'</span><span class="sy0">,</span><span class="st_h">'ldap_get_values'</span><span class="sy0">,</span><span class="st_h">'ldap_get_values_len'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ldap_list'</span><span class="sy0">,</span><span class="st_h">'ldap_mod_add'</span><span class="sy0">,</span><span class="st_h">'ldap_mod_del'</span><span class="sy0">,</span><span class="st_h">'ldap_mod_replace'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ldap_modify'</span><span class="sy0">,</span><span class="st_h">'ldap_next_attribute'</span><span class="sy0">,</span><span class="st_h">'ldap_next_entry'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ldap_next_reference'</span><span class="sy0">,</span><span class="st_h">'ldap_parse_reference'</span><span class="sy0">,</span><span class="st_h">'ldap_parse_result'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ldap_read'</span><span class="sy0">,</span><span class="st_h">'ldap_rename'</span><span class="sy0">,</span><span class="st_h">'ldap_search'</span><span class="sy0">,</span><span class="st_h">'ldap_set_option'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ldap_sort'</span><span class="sy0">,</span><span class="st_h">'ldap_start_tls'</span><span class="sy0">,</span><span class="st_h">'ldap_unbind'</span><span class="sy0">,</span><span class="st_h">'levenshtein'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'libxml_clear_errors'</span><span class="sy0">,</span><span class="st_h">'libxml_get_errors'</span><span class="sy0">,</span><span class="st_h">'libxml_get_last_error'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'libxml_set_streams_context'</span><span class="sy0">,</span><span class="st_h">'libxml_use_internal_errors'</span><span class="sy0">,</span><span class="st_h">'link'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'linkinfo'</span><span class="sy0">,</span><span class="st_h">'list'</span><span class="sy0">,</span><span class="st_h">'localeconv'</span><span class="sy0">,</span><span class="st_h">'localtime'</span><span class="sy0">,</span><span class="st_h">'log'</span><span class="sy0">,</span><span class="st_h">'log1p'</span><span class="sy0">,</span><span class="st_h">'log10'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'long2ip'</span><span class="sy0">,</span><span class="st_h">'lstat'</span><span class="sy0">,</span><span class="st_h">'ltrim'</span><span class="sy0">,</span><span class="st_h">'lzf_compress'</span><span class="sy0">,</span><span class="st_h">'lzf_decompress'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'lzf_optimized_for'</span><span class="sy0">,</span><span class="st_h">'magic_quotes_runtime'</span><span class="sy0">,</span><span class="st_h">'mail'</span><span class="sy0">,</span><span class="st_h">'max'</span><span class="sy0">,</span><span class="st_h">'mbereg'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mberegi'</span><span class="sy0">,</span><span class="st_h">'mberegi_replace'</span><span class="sy0">,</span><span class="st_h">'mbereg_match'</span><span class="sy0">,</span><span class="st_h">'mbereg_replace'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mbereg_search'</span><span class="sy0">,</span><span class="st_h">'mbereg_search_getpos'</span><span class="sy0">,</span><span class="st_h">'mbereg_search_getregs'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mbereg_search_init'</span><span class="sy0">,</span><span class="st_h">'mbereg_search_pos'</span><span class="sy0">,</span><span class="st_h">'mbereg_search_regs'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mbereg_search_setpos'</span><span class="sy0">,</span><span class="st_h">'mbregex_encoding'</span><span class="sy0">,</span><span class="st_h">'mbsplit'</span><span class="sy0">,</span><span class="st_h">'mbstrcut'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mbstrlen'</span><span class="sy0">,</span><span class="st_h">'mbstrpos'</span><span class="sy0">,</span><span class="st_h">'mbstrrpos'</span><span class="sy0">,</span><span class="st_h">'mbsubstr'</span><span class="sy0">,</span><span class="st_h">'mb_check_encoding'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mb_convert_case'</span><span class="sy0">,</span><span class="st_h">'mb_convert_encoding'</span><span class="sy0">,</span><span class="st_h">'mb_convert_kana'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mb_convert_variables'</span><span class="sy0">,</span><span class="st_h">'mb_decode_mimeheader'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mb_decode_numericentity'</span><span class="sy0">,</span><span class="st_h">'mb_detect_encoding'</span><span class="sy0">,</span><span class="st_h">'mb_detect_order'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mb_encode_mimeheader'</span><span class="sy0">,</span><span class="st_h">'mb_encode_numericentity'</span><span class="sy0">,</span><span class="st_h">'mb_ereg'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mb_eregi'</span><span class="sy0">,</span><span class="st_h">'mb_eregi_replace'</span><span class="sy0">,</span><span class="st_h">'mb_ereg_match'</span><span class="sy0">,</span><span class="st_h">'mb_ereg_replace'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mb_ereg_search'</span><span class="sy0">,</span><span class="st_h">'mb_ereg_search_getpos'</span><span class="sy0">,</span><span class="st_h">'mb_ereg_search_getregs'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mb_ereg_search_init'</span><span class="sy0">,</span><span class="st_h">'mb_ereg_search_pos'</span><span class="sy0">,</span><span class="st_h">'mb_ereg_search_regs'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mb_ereg_search_setpos'</span><span class="sy0">,</span><span class="st_h">'mb_get_info'</span><span class="sy0">,</span><span class="st_h">'mb_http_input'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mb_http_output'</span><span class="sy0">,</span><span class="st_h">'mb_internal_encoding'</span><span class="sy0">,</span><span class="st_h">'mb_language'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mb_list_encodings'</span><span class="sy0">,</span><span class="st_h">'mb_output_handler'</span><span class="sy0">,</span><span class="st_h">'mb_parse_str'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mb_preferred_mime_name'</span><span class="sy0">,</span><span class="st_h">'mb_regex_encoding'</span><span class="sy0">,</span><span class="st_h">'mb_regex_set_options'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mb_send_mail'</span><span class="sy0">,</span><span class="st_h">'mb_split'</span><span class="sy0">,</span><span class="st_h">'mb_strcut'</span><span class="sy0">,</span><span class="st_h">'mb_strimwidth'</span><span class="sy0">,</span><span class="st_h">'mb_stripos'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mb_stristr'</span><span class="sy0">,</span><span class="st_h">'mb_strlen'</span><span class="sy0">,</span><span class="st_h">'mb_strpos'</span><span class="sy0">,</span><span class="st_h">'mb_strrchr'</span><span class="sy0">,</span><span class="st_h">'mb_strrichr'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mb_strripos'</span><span class="sy0">,</span><span class="st_h">'mb_strrpos'</span><span class="sy0">,</span><span class="st_h">'mb_strstr'</span><span class="sy0">,</span><span class="st_h">'mb_strtolower'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mb_strtoupper'</span><span class="sy0">,</span><span class="st_h">'mb_strwidth'</span><span class="sy0">,</span><span class="st_h">'mb_substitute_character'</span><span class="sy0">,</span><span class="st_h">'mb_substr'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mb_substr_count'</span><span class="sy0">,</span><span class="st_h">'mcrypt_cbc'</span><span class="sy0">,</span><span class="st_h">'mcrypt_cfb'</span><span class="sy0">,</span><span class="st_h">'mcrypt_create_iv'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mcrypt_decrypt'</span><span class="sy0">,</span><span class="st_h">'mcrypt_ecb'</span><span class="sy0">,</span><span class="st_h">'mcrypt_enc_get_algorithms_name'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mcrypt_enc_get_block_size'</span><span class="sy0">,</span><span class="st_h">'mcrypt_enc_get_iv_size'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mcrypt_enc_get_key_size'</span><span class="sy0">,</span><span class="st_h">'mcrypt_enc_get_modes_name'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mcrypt_enc_get_supported_key_sizes'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mcrypt_enc_is_block_algorithm'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mcrypt_enc_is_block_algorithm_mode'</span><span class="sy0">,</span><span class="st_h">'mcrypt_enc_is_block_mode'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mcrypt_enc_self_test'</span><span class="sy0">,</span><span class="st_h">'mcrypt_encrypt'</span><span class="sy0">,</span><span class="st_h">'mcrypt_generic'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mcrypt_generic_deinit'</span><span class="sy0">,</span><span class="st_h">'mcrypt_generic_end'</span><span class="sy0">,</span><span class="st_h">'mcrypt_generic_init'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mcrypt_get_block_size'</span><span class="sy0">,</span><span class="st_h">'mcrypt_get_cipher_name'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mcrypt_get_iv_size'</span><span class="sy0">,</span><span class="st_h">'mcrypt_get_key_size'</span><span class="sy0">,</span><span class="st_h">'mcrypt_list_algorithms'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mcrypt_list_modes'</span><span class="sy0">,</span><span class="st_h">'mcrypt_module_close'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mcrypt_module_get_algo_block_size'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mcrypt_module_get_algo_key_size'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mcrypt_module_get_supported_key_sizes'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mcrypt_module_is_block_algorithm'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mcrypt_module_is_block_algorithm_mode'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mcrypt_module_is_block_mode'</span><span class="sy0">,</span><span class="st_h">'mcrypt_module_open'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mcrypt_module_self_test'</span><span class="sy0">,</span><span class="st_h">'mcrypt_ofb'</span><span class="sy0">,</span><span class="st_h">'md5'</span><span class="sy0">,</span><span class="st_h">'md5_file'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mdecrypt_generic'</span><span class="sy0">,</span><span class="st_h">'memcache_add'</span><span class="sy0">,</span><span class="st_h">'memcache_add_server'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'memcache_close'</span><span class="sy0">,</span><span class="st_h">'memcache_connect'</span><span class="sy0">,</span><span class="st_h">'memcache_debug'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'memcache_decrement'</span><span class="sy0">,</span><span class="st_h">'memcache_delete'</span><span class="sy0">,</span><span class="st_h">'memcache_flush'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'memcache_get'</span><span class="sy0">,</span><span class="st_h">'memcache_get_extended_stats'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'memcache_get_server_status'</span><span class="sy0">,</span><span class="st_h">'memcache_get_stats'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'memcache_get_version'</span><span class="sy0">,</span><span class="st_h">'memcache_increment'</span><span class="sy0">,</span><span class="st_h">'memcache_pconnect'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'memcache_replace'</span><span class="sy0">,</span><span class="st_h">'memcache_set'</span><span class="sy0">,</span><span class="st_h">'memcache_set_compress_threshold'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'memcache_set_server_params'</span><span class="sy0">,</span><span class="st_h">'memory_get_peak_usage'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'memory_get_usage'</span><span class="sy0">,</span><span class="st_h">'metaphone'</span><span class="sy0">,</span><span class="st_h">'mhash'</span><span class="sy0">,</span><span class="st_h">'mhash_count'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mhash_get_block_size'</span><span class="sy0">,</span><span class="st_h">'mhash_get_hash_name'</span><span class="sy0">,</span><span class="st_h">'mhash_keygen_s2k'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'method_exists'</span><span class="sy0">,</span><span class="st_h">'microtime'</span><span class="sy0">,</span><span class="st_h">'mime_content_type'</span><span class="sy0">,</span><span class="st_h">'min'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ming_keypress'</span><span class="sy0">,</span><span class="st_h">'ming_setcubicthreshold'</span><span class="sy0">,</span><span class="st_h">'ming_setscale'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ming_useconstants'</span><span class="sy0">,</span><span class="st_h">'ming_useswfversion'</span><span class="sy0">,</span><span class="st_h">'mkdir'</span><span class="sy0">,</span><span class="st_h">'mktime'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'money_format'</span><span class="sy0">,</span><span class="st_h">'move_uploaded_file'</span><span class="sy0">,</span><span class="st_h">'msql'</span><span class="sy0">,</span><span class="st_h">'msql_affected_rows'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'msql_close'</span><span class="sy0">,</span><span class="st_h">'msql_connect'</span><span class="sy0">,</span><span class="st_h">'msql_create_db'</span><span class="sy0">,</span><span class="st_h">'msql_createdb'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'msql_data_seek'</span><span class="sy0">,</span><span class="st_h">'msql_db_query'</span><span class="sy0">,</span><span class="st_h">'msql_dbname'</span><span class="sy0">,</span><span class="st_h">'msql_drop_db'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'msql_dropdb'</span><span class="sy0">,</span><span class="st_h">'msql_error'</span><span class="sy0">,</span><span class="st_h">'msql_fetch_array'</span><span class="sy0">,</span><span class="st_h">'msql_fetch_field'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'msql_fetch_object'</span><span class="sy0">,</span><span class="st_h">'msql_fetch_row'</span><span class="sy0">,</span><span class="st_h">'msql_field_flags'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'msql_field_len'</span><span class="sy0">,</span><span class="st_h">'msql_field_name'</span><span class="sy0">,</span><span class="st_h">'msql_field_seek'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'msql_field_table'</span><span class="sy0">,</span><span class="st_h">'msql_field_type'</span><span class="sy0">,</span><span class="st_h">'msql_fieldflags'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'msql_fieldlen'</span><span class="sy0">,</span><span class="st_h">'msql_fieldname'</span><span class="sy0">,</span><span class="st_h">'msql_fieldtable'</span><span class="sy0">,</span><span class="st_h">'msql_fieldtype'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'msql_free_result'</span><span class="sy0">,</span><span class="st_h">'msql_freeresult'</span><span class="sy0">,</span><span class="st_h">'msql_list_dbs'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'msql_list_fields'</span><span class="sy0">,</span><span class="st_h">'msql_list_tables'</span><span class="sy0">,</span><span class="st_h">'msql_listdbs'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'msql_listfields'</span><span class="sy0">,</span><span class="st_h">'msql_listtables'</span><span class="sy0">,</span><span class="st_h">'msql_num_fields'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'msql_num_rows'</span><span class="sy0">,</span><span class="st_h">'msql_numfields'</span><span class="sy0">,</span><span class="st_h">'msql_numrows'</span><span class="sy0">,</span><span class="st_h">'msql_pconnect'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'msql_query'</span><span class="sy0">,</span><span class="st_h">'msql_regcase'</span><span class="sy0">,</span><span class="st_h">'msql_result'</span><span class="sy0">,</span><span class="st_h">'msql_select_db'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'msql_selectdb'</span><span class="sy0">,</span><span class="st_h">'msql_tablename'</span><span class="sy0">,</span><span class="st_h">'mssql_bind'</span><span class="sy0">,</span><span class="st_h">'mssql_close'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mssql_connect'</span><span class="sy0">,</span><span class="st_h">'mssql_data_seek'</span><span class="sy0">,</span><span class="st_h">'mssql_execute'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mssql_fetch_array'</span><span class="sy0">,</span><span class="st_h">'mssql_fetch_assoc'</span><span class="sy0">,</span><span class="st_h">'mssql_fetch_batch'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mssql_fetch_field'</span><span class="sy0">,</span><span class="st_h">'mssql_fetch_object'</span><span class="sy0">,</span><span class="st_h">'mssql_fetch_row'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mssql_field_length'</span><span class="sy0">,</span><span class="st_h">'mssql_field_name'</span><span class="sy0">,</span><span class="st_h">'mssql_field_seek'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mssql_field_type'</span><span class="sy0">,</span><span class="st_h">'mssql_free_result'</span><span class="sy0">,</span><span class="st_h">'mssql_free_statement'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mssql_get_last_message'</span><span class="sy0">,</span><span class="st_h">'mssql_guid_string'</span><span class="sy0">,</span><span class="st_h">'mssql_init'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mssql_min_error_severity'</span><span class="sy0">,</span><span class="st_h">'mssql_min_message_severity'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mssql_next_result'</span><span class="sy0">,</span><span class="st_h">'mssql_num_fields'</span><span class="sy0">,</span><span class="st_h">'mssql_num_rows'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mssql_pconnect'</span><span class="sy0">,</span><span class="st_h">'mssql_query'</span><span class="sy0">,</span><span class="st_h">'mssql_result'</span><span class="sy0">,</span><span class="st_h">'mssql_rows_affected'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mssql_select_db'</span><span class="sy0">,</span><span class="st_h">'mt_getrandmax'</span><span class="sy0">,</span><span class="st_h">'mt_rand'</span><span class="sy0">,</span><span class="st_h">'mt_srand'</span><span class="sy0">,</span><span class="st_h">'mysql'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_affected_rows'</span><span class="sy0">,</span><span class="st_h">'mysql_client_encoding'</span><span class="sy0">,</span><span class="st_h">'mysql_close'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_connect'</span><span class="sy0">,</span><span class="st_h">'mysql_createdb'</span><span class="sy0">,</span><span class="st_h">'mysql_create_db'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_data_seek'</span><span class="sy0">,</span><span class="st_h">'mysql_dbname'</span><span class="sy0">,</span><span class="st_h">'mysql_db_name'</span><span class="sy0">,</span><span class="st_h">'mysql_db_query'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_dropdb'</span><span class="sy0">,</span><span class="st_h">'mysql_drop_db'</span><span class="sy0">,</span><span class="st_h">'mysql_errno'</span><span class="sy0">,</span><span class="st_h">'mysql_error'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_escape_string'</span><span class="sy0">,</span><span class="st_h">'mysql_fetch_array'</span><span class="sy0">,</span><span class="st_h">'mysql_fetch_assoc'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_fetch_field'</span><span class="sy0">,</span><span class="st_h">'mysql_fetch_lengths'</span><span class="sy0">,</span><span class="st_h">'mysql_fetch_object'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_fetch_row'</span><span class="sy0">,</span><span class="st_h">'mysql_fieldflags'</span><span class="sy0">,</span><span class="st_h">'mysql_fieldlen'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_fieldname'</span><span class="sy0">,</span><span class="st_h">'mysql_fieldtable'</span><span class="sy0">,</span><span class="st_h">'mysql_fieldtype'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_field_flags'</span><span class="sy0">,</span><span class="st_h">'mysql_field_len'</span><span class="sy0">,</span><span class="st_h">'mysql_field_name'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_field_seek'</span><span class="sy0">,</span><span class="st_h">'mysql_field_table'</span><span class="sy0">,</span><span class="st_h">'mysql_field_type'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_freeresult'</span><span class="sy0">,</span><span class="st_h">'mysql_free_result'</span><span class="sy0">,</span><span class="st_h">'mysql_get_client_info'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_get_host_info'</span><span class="sy0">,</span><span class="st_h">'mysql_get_proto_info'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_get_server_info'</span><span class="sy0">,</span><span class="st_h">'mysql_info'</span><span class="sy0">,</span><span class="st_h">'mysql_insert_id'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_listdbs'</span><span class="sy0">,</span><span class="st_h">'mysql_listfields'</span><span class="sy0">,</span><span class="st_h">'mysql_listtables'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_list_dbs'</span><span class="sy0">,</span><span class="st_h">'mysql_list_fields'</span><span class="sy0">,</span><span class="st_h">'mysql_list_processes'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_list_tables'</span><span class="sy0">,</span><span class="st_h">'mysql_numfields'</span><span class="sy0">,</span><span class="st_h">'mysql_numrows'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_num_fields'</span><span class="sy0">,</span><span class="st_h">'mysql_num_rows'</span><span class="sy0">,</span><span class="st_h">'mysql_pconnect'</span><span class="sy0">,</span><span class="st_h">'mysql_ping'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_query'</span><span class="sy0">,</span><span class="st_h">'mysql_real_escape_string'</span><span class="sy0">,</span><span class="st_h">'mysql_result'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_selectdb'</span><span class="sy0">,</span><span class="st_h">'mysql_select_db'</span><span class="sy0">,</span><span class="st_h">'mysql_set_charset'</span><span class="sy0">,</span><span class="st_h">'mysql_stat'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_tablename'</span><span class="sy0">,</span><span class="st_h">'mysql_table_name'</span><span class="sy0">,</span><span class="st_h">'mysql_thread_id'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysql_unbuffered_query'</span><span class="sy0">,</span><span class="st_h">'mysqli_affected_rows'</span><span class="sy0">,</span><span class="st_h">'mysqli_autocommit'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_bind_param'</span><span class="sy0">,</span><span class="st_h">'mysqli_bind_result'</span><span class="sy0">,</span><span class="st_h">'mysqli_change_user'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_character_set_name'</span><span class="sy0">,</span><span class="st_h">'mysqli_client_encoding'</span><span class="sy0">,</span><span class="st_h">'mysqli_close'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_commit'</span><span class="sy0">,</span><span class="st_h">'mysqli_connect'</span><span class="sy0">,</span><span class="st_h">'mysqli_connect_errno'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_connect_error'</span><span class="sy0">,</span><span class="st_h">'mysqli_data_seek'</span><span class="sy0">,</span><span class="st_h">'mysqli_debug'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_disable_reads_from_master'</span><span class="sy0">,</span><span class="st_h">'mysqli_disable_rpl_parse'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_dump_debug_info'</span><span class="sy0">,</span><span class="st_h">'mysqli_embedded_server_end'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_embedded_server_start'</span><span class="sy0">,</span><span class="st_h">'mysqli_enable_reads_from_master'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_enable_rpl_parse'</span><span class="sy0">,</span><span class="st_h">'mysqli_errno'</span><span class="sy0">,</span><span class="st_h">'mysqli_error'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_escape_string'</span><span class="sy0">,</span><span class="st_h">'mysqli_execute'</span><span class="sy0">,</span><span class="st_h">'mysqli_fetch'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_fetch_array'</span><span class="sy0">,</span><span class="st_h">'mysqli_fetch_assoc'</span><span class="sy0">,</span><span class="st_h">'mysqli_fetch_field'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_fetch_field_direct'</span><span class="sy0">,</span><span class="st_h">'mysqli_fetch_fields'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_fetch_lengths'</span><span class="sy0">,</span><span class="st_h">'mysqli_fetch_object'</span><span class="sy0">,</span><span class="st_h">'mysqli_fetch_row'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_field_count'</span><span class="sy0">,</span><span class="st_h">'mysqli_field_seek'</span><span class="sy0">,</span><span class="st_h">'mysqli_field_tell'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_free_result'</span><span class="sy0">,</span><span class="st_h">'mysqli_get_charset'</span><span class="sy0">,</span><span class="st_h">'mysqli_get_client_info'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_get_client_version'</span><span class="sy0">,</span><span class="st_h">'mysqli_get_host_info'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_get_metadata'</span><span class="sy0">,</span><span class="st_h">'mysqli_get_proto_info'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_get_server_info'</span><span class="sy0">,</span><span class="st_h">'mysqli_get_server_version'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_get_warnings'</span><span class="sy0">,</span><span class="st_h">'mysqli_info'</span><span class="sy0">,</span><span class="st_h">'mysqli_init'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_insert_id'</span><span class="sy0">,</span><span class="st_h">'mysqli_kill'</span><span class="sy0">,</span><span class="st_h">'mysqli_master_query'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_more_results'</span><span class="sy0">,</span><span class="st_h">'mysqli_multi_query'</span><span class="sy0">,</span><span class="st_h">'mysqli_next_result'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_num_fields'</span><span class="sy0">,</span><span class="st_h">'mysqli_num_rows'</span><span class="sy0">,</span><span class="st_h">'mysqli_options'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_param_count'</span><span class="sy0">,</span><span class="st_h">'mysqli_ping'</span><span class="sy0">,</span><span class="st_h">'mysqli_prepare'</span><span class="sy0">,</span><span class="st_h">'mysqli_query'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_real_connect'</span><span class="sy0">,</span><span class="st_h">'mysqli_real_escape_string'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_real_query'</span><span class="sy0">,</span><span class="st_h">'mysqli_report'</span><span class="sy0">,</span><span class="st_h">'mysqli_rollback'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_rpl_parse_enabled'</span><span class="sy0">,</span><span class="st_h">'mysqli_rpl_probe'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_rpl_query_type'</span><span class="sy0">,</span><span class="st_h">'mysqli_select_db'</span><span class="sy0">,</span><span class="st_h">'mysqli_send_long_data'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_send_query'</span><span class="sy0">,</span><span class="st_h">'mysqli_set_charset'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_set_local_infile_default'</span><span class="sy0">,</span><span class="st_h">'mysqli_set_local_infile_handler'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_set_opt'</span><span class="sy0">,</span><span class="st_h">'mysqli_slave_query'</span><span class="sy0">,</span><span class="st_h">'mysqli_sqlstate'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_ssl_set'</span><span class="sy0">,</span><span class="st_h">'mysqli_stat'</span><span class="sy0">,</span><span class="st_h">'mysqli_stmt_affected_rows'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_stmt_attr_get'</span><span class="sy0">,</span><span class="st_h">'mysqli_stmt_attr_set'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_stmt_bind_param'</span><span class="sy0">,</span><span class="st_h">'mysqli_stmt_bind_result'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_stmt_close'</span><span class="sy0">,</span><span class="st_h">'mysqli_stmt_data_seek'</span><span class="sy0">,</span><span class="st_h">'mysqli_stmt_errno'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_stmt_error'</span><span class="sy0">,</span><span class="st_h">'mysqli_stmt_execute'</span><span class="sy0">,</span><span class="st_h">'mysqli_stmt_fetch'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_stmt_field_count'</span><span class="sy0">,</span><span class="st_h">'mysqli_stmt_free_result'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_stmt_get_warnings'</span><span class="sy0">,</span><span class="st_h">'mysqli_stmt_init'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_stmt_insert_id'</span><span class="sy0">,</span><span class="st_h">'mysqli_stmt_num_rows'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_stmt_param_count'</span><span class="sy0">,</span><span class="st_h">'mysqli_stmt_prepare'</span><span class="sy0">,</span><span class="st_h">'mysqli_stmt_reset'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_stmt_result_metadata'</span><span class="sy0">,</span><span class="st_h">'mysqli_stmt_send_long_data'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_stmt_sqlstate'</span><span class="sy0">,</span><span class="st_h">'mysqli_stmt_store_result'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_store_result'</span><span class="sy0">,</span><span class="st_h">'mysqli_thread_id'</span><span class="sy0">,</span><span class="st_h">'mysqli_thread_safe'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'mysqli_use_result'</span><span class="sy0">,</span><span class="st_h">'mysqli_warning_count'</span><span class="sy0">,</span><span class="st_h">'natcasesort'</span><span class="sy0">,</span><span class="st_h">'natsort'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'new_xmldoc'</span><span class="sy0">,</span><span class="st_h">'next'</span><span class="sy0">,</span><span class="st_h">'ngettext'</span><span class="sy0">,</span><span class="st_h">'nl2br'</span><span class="sy0">,</span><span class="st_h">'nl_langinfo'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ntuser_getdomaincontroller'</span><span class="sy0">,</span><span class="st_h">'ntuser_getusergroups'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ntuser_getuserinfo'</span><span class="sy0">,</span><span class="st_h">'ntuser_getuserlist'</span><span class="sy0">,</span><span class="st_h">'number_format'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ob_clean'</span><span class="sy0">,</span><span class="st_h">'ob_deflatehandler'</span><span class="sy0">,</span><span class="st_h">'ob_end_clean'</span><span class="sy0">,</span><span class="st_h">'ob_end_flush'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ob_etaghandler'</span><span class="sy0">,</span><span class="st_h">'ob_flush'</span><span class="sy0">,</span><span class="st_h">'ob_get_clean'</span><span class="sy0">,</span><span class="st_h">'ob_get_contents'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ob_get_flush'</span><span class="sy0">,</span><span class="st_h">'ob_get_length'</span><span class="sy0">,</span><span class="st_h">'ob_get_level'</span><span class="sy0">,</span><span class="st_h">'ob_get_status'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ob_gzhandler'</span><span class="sy0">,</span><span class="st_h">'ob_iconv_handler'</span><span class="sy0">,</span><span class="st_h">'ob_implicit_flush'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ob_inflatehandler'</span><span class="sy0">,</span><span class="st_h">'ob_list_handlers'</span><span class="sy0">,</span><span class="st_h">'ob_start'</span><span class="sy0">,</span><span class="st_h">'ob_tidyhandler'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'octdec'</span><span class="sy0">,</span><span class="st_h">'odbc_autocommit'</span><span class="sy0">,</span><span class="st_h">'odbc_binmode'</span><span class="sy0">,</span><span class="st_h">'odbc_close'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'odbc_close_all'</span><span class="sy0">,</span><span class="st_h">'odbc_columnprivileges'</span><span class="sy0">,</span><span class="st_h">'odbc_columns'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'odbc_commit'</span><span class="sy0">,</span><span class="st_h">'odbc_connect'</span><span class="sy0">,</span><span class="st_h">'odbc_cursor'</span><span class="sy0">,</span><span class="st_h">'odbc_data_source'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'odbc_do'</span><span class="sy0">,</span><span class="st_h">'odbc_error'</span><span class="sy0">,</span><span class="st_h">'odbc_errormsg'</span><span class="sy0">,</span><span class="st_h">'odbc_exec'</span><span class="sy0">,</span><span class="st_h">'odbc_execute'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'odbc_fetch_array'</span><span class="sy0">,</span><span class="st_h">'odbc_fetch_into'</span><span class="sy0">,</span><span class="st_h">'odbc_fetch_object'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'odbc_fetch_row'</span><span class="sy0">,</span><span class="st_h">'odbc_field_len'</span><span class="sy0">,</span><span class="st_h">'odbc_field_name'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'odbc_field_num'</span><span class="sy0">,</span><span class="st_h">'odbc_field_precision'</span><span class="sy0">,</span><span class="st_h">'odbc_field_scale'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'odbc_field_type'</span><span class="sy0">,</span><span class="st_h">'odbc_foreignkeys'</span><span class="sy0">,</span><span class="st_h">'odbc_free_result'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'odbc_gettypeinfo'</span><span class="sy0">,</span><span class="st_h">'odbc_longreadlen'</span><span class="sy0">,</span><span class="st_h">'odbc_next_result'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'odbc_num_fields'</span><span class="sy0">,</span><span class="st_h">'odbc_num_rows'</span><span class="sy0">,</span><span class="st_h">'odbc_pconnect'</span><span class="sy0">,</span><span class="st_h">'odbc_prepare'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'odbc_primarykeys'</span><span class="sy0">,</span><span class="st_h">'odbc_procedurecolumns'</span><span class="sy0">,</span><span class="st_h">'odbc_procedures'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'odbc_result'</span><span class="sy0">,</span><span class="st_h">'odbc_result_all'</span><span class="sy0">,</span><span class="st_h">'odbc_rollback'</span><span class="sy0">,</span><span class="st_h">'odbc_setoption'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'odbc_specialcolumns'</span><span class="sy0">,</span><span class="st_h">'odbc_statistics'</span><span class="sy0">,</span><span class="st_h">'odbc_tableprivileges'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'odbc_tables'</span><span class="sy0">,</span><span class="st_h">'opendir'</span><span class="sy0">,</span><span class="st_h">'openlog'</span><span class="sy0">,</span><span class="st_h">'openssl_csr_export'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'openssl_csr_export_to_file'</span><span class="sy0">,</span><span class="st_h">'openssl_csr_get_public_key'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'openssl_csr_get_subject'</span><span class="sy0">,</span><span class="st_h">'openssl_csr_new'</span><span class="sy0">,</span><span class="st_h">'openssl_csr_sign'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'openssl_error_string'</span><span class="sy0">,</span><span class="st_h">'openssl_free_key'</span><span class="sy0">,</span><span class="st_h">'openssl_get_privatekey'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'openssl_get_publickey'</span><span class="sy0">,</span><span class="st_h">'openssl_open'</span><span class="sy0">,</span><span class="st_h">'openssl_pkcs12_export'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'openssl_pkcs12_export_to_file'</span><span class="sy0">,</span><span class="st_h">'openssl_pkcs12_read'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'openssl_pkcs7_decrypt'</span><span class="sy0">,</span><span class="st_h">'openssl_pkcs7_encrypt'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'openssl_pkcs7_sign'</span><span class="sy0">,</span><span class="st_h">'openssl_pkcs7_verify'</span><span class="sy0">,</span><span class="st_h">'openssl_pkey_export'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'openssl_pkey_export_to_file'</span><span class="sy0">,</span><span class="st_h">'openssl_pkey_free'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'openssl_pkey_get_details'</span><span class="sy0">,</span><span class="st_h">'openssl_pkey_get_private'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'openssl_pkey_get_public'</span><span class="sy0">,</span><span class="st_h">'openssl_pkey_new'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'openssl_private_decrypt'</span><span class="sy0">,</span><span class="st_h">'openssl_private_encrypt'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'openssl_public_decrypt'</span><span class="sy0">,</span><span class="st_h">'openssl_public_encrypt'</span><span class="sy0">,</span><span class="st_h">'openssl_seal'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'openssl_sign'</span><span class="sy0">,</span><span class="st_h">'openssl_verify'</span><span class="sy0">,</span><span class="st_h">'openssl_x509_checkpurpose'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'openssl_x509_check_private_key'</span><span class="sy0">,</span><span class="st_h">'openssl_x509_export'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'openssl_x509_export_to_file'</span><span class="sy0">,</span><span class="st_h">'openssl_x509_free'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'openssl_x509_parse'</span><span class="sy0">,</span><span class="st_h">'openssl_x509_read'</span><span class="sy0">,</span><span class="st_h">'ord'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'output_add_rewrite_var'</span><span class="sy0">,</span><span class="st_h">'output_reset_rewrite_vars'</span><span class="sy0">,</span><span class="st_h">'overload'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'outputdebugstring'</span><span class="sy0">,</span><span class="st_h">'pack'</span><span class="sy0">,</span><span class="st_h">'parse_ini_file'</span><span class="sy0">,</span><span class="st_h">'parse_str'</span><span class="sy0">,</span><span class="st_h">'parse_url'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'parsekit_compile_file'</span><span class="sy0">,</span><span class="st_h">'parsekit_compile_string'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'parsekit_func_arginfo'</span><span class="sy0">,</span><span class="st_h">'parsekit_opcode_flags'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'parsekit_opcode_name'</span><span class="sy0">,</span><span class="st_h">'passthru'</span><span class="sy0">,</span><span class="st_h">'pathinfo'</span><span class="sy0">,</span><span class="st_h">'pclose'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_add_bookmark'</span><span class="sy0">,</span><span class="st_h">'pdf_add_launchlink'</span><span class="sy0">,</span><span class="st_h">'pdf_add_locallink'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_add_nameddest'</span><span class="sy0">,</span><span class="st_h">'pdf_add_note'</span><span class="sy0">,</span><span class="st_h">'pdf_add_pdflink'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_add_thumbnail'</span><span class="sy0">,</span><span class="st_h">'pdf_add_weblink'</span><span class="sy0">,</span><span class="st_h">'pdf_arc'</span><span class="sy0">,</span><span class="st_h">'pdf_arcn'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_attach_file'</span><span class="sy0">,</span><span class="st_h">'pdf_begin_font'</span><span class="sy0">,</span><span class="st_h">'pdf_begin_glyph'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_begin_page'</span><span class="sy0">,</span><span class="st_h">'pdf_begin_pattern'</span><span class="sy0">,</span><span class="st_h">'pdf_begin_template'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_circle'</span><span class="sy0">,</span><span class="st_h">'pdf_clip'</span><span class="sy0">,</span><span class="st_h">'pdf_close'</span><span class="sy0">,</span><span class="st_h">'pdf_close_image'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_close_pdi'</span><span class="sy0">,</span><span class="st_h">'pdf_close_pdi_page'</span><span class="sy0">,</span><span class="st_h">'pdf_closepath'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_closepath_fill_stroke'</span><span class="sy0">,</span><span class="st_h">'pdf_closepath_stroke'</span><span class="sy0">,</span><span class="st_h">'pdf_concat'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_continue_text'</span><span class="sy0">,</span><span class="st_h">'pdf_create_gstate'</span><span class="sy0">,</span><span class="st_h">'pdf_create_pvf'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_curveto'</span><span class="sy0">,</span><span class="st_h">'pdf_delete'</span><span class="sy0">,</span><span class="st_h">'pdf_delete_pvf'</span><span class="sy0">,</span><span class="st_h">'pdf_encoding_set_char'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_end_font'</span><span class="sy0">,</span><span class="st_h">'pdf_end_glyph'</span><span class="sy0">,</span><span class="st_h">'pdf_end_page'</span><span class="sy0">,</span><span class="st_h">'pdf_end_pattern'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_end_template'</span><span class="sy0">,</span><span class="st_h">'pdf_endpath'</span><span class="sy0">,</span><span class="st_h">'pdf_fill'</span><span class="sy0">,</span><span class="st_h">'pdf_fill_imageblock'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_fill_pdfblock'</span><span class="sy0">,</span><span class="st_h">'pdf_fill_stroke'</span><span class="sy0">,</span><span class="st_h">'pdf_fill_textblock'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_findfont'</span><span class="sy0">,</span><span class="st_h">'pdf_fit_image'</span><span class="sy0">,</span><span class="st_h">'pdf_fit_pdi_page'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_fit_textline'</span><span class="sy0">,</span><span class="st_h">'pdf_get_apiname'</span><span class="sy0">,</span><span class="st_h">'pdf_get_buffer'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_get_errmsg'</span><span class="sy0">,</span><span class="st_h">'pdf_get_errnum'</span><span class="sy0">,</span><span class="st_h">'pdf_get_parameter'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_get_pdi_parameter'</span><span class="sy0">,</span><span class="st_h">'pdf_get_pdi_value'</span><span class="sy0">,</span><span class="st_h">'pdf_get_value'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_initgraphics'</span><span class="sy0">,</span><span class="st_h">'pdf_lineto'</span><span class="sy0">,</span><span class="st_h">'pdf_load_font'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_load_iccprofile'</span><span class="sy0">,</span><span class="st_h">'pdf_load_image'</span><span class="sy0">,</span><span class="st_h">'pdf_makespotcolor'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_moveto'</span><span class="sy0">,</span><span class="st_h">'pdf_new'</span><span class="sy0">,</span><span class="st_h">'pdf_open_ccitt'</span><span class="sy0">,</span><span class="st_h">'pdf_open_file'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_open_image'</span><span class="sy0">,</span><span class="st_h">'pdf_open_image_file'</span><span class="sy0">,</span><span class="st_h">'pdf_open_pdi'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_open_pdi_page'</span><span class="sy0">,</span><span class="st_h">'pdf_place_image'</span><span class="sy0">,</span><span class="st_h">'pdf_place_pdi_page'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_process_pdi'</span><span class="sy0">,</span><span class="st_h">'pdf_rect'</span><span class="sy0">,</span><span class="st_h">'pdf_restore'</span><span class="sy0">,</span><span class="st_h">'pdf_rotate'</span><span class="sy0">,</span><span class="st_h">'pdf_save'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_scale'</span><span class="sy0">,</span><span class="st_h">'pdf_set_border_color'</span><span class="sy0">,</span><span class="st_h">'pdf_set_border_dash'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_set_border_style'</span><span class="sy0">,</span><span class="st_h">'pdf_set_gstate'</span><span class="sy0">,</span><span class="st_h">'pdf_set_info'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_set_parameter'</span><span class="sy0">,</span><span class="st_h">'pdf_set_text_pos'</span><span class="sy0">,</span><span class="st_h">'pdf_set_value'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_setcolor'</span><span class="sy0">,</span><span class="st_h">'pdf_setdash'</span><span class="sy0">,</span><span class="st_h">'pdf_setdashpattern'</span><span class="sy0">,</span><span class="st_h">'pdf_setflat'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_setfont'</span><span class="sy0">,</span><span class="st_h">'pdf_setlinecap'</span><span class="sy0">,</span><span class="st_h">'pdf_setlinejoin'</span><span class="sy0">,</span><span class="st_h">'pdf_setlinewidth'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_setmatrix'</span><span class="sy0">,</span><span class="st_h">'pdf_setmiterlimit'</span><span class="sy0">,</span><span class="st_h">'pdf_setpolydash'</span><span class="sy0">,</span><span class="st_h">'pdf_shading'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_shading_pattern'</span><span class="sy0">,</span><span class="st_h">'pdf_shfill'</span><span class="sy0">,</span><span class="st_h">'pdf_show'</span><span class="sy0">,</span><span class="st_h">'pdf_show_boxed'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_show_xy'</span><span class="sy0">,</span><span class="st_h">'pdf_skew'</span><span class="sy0">,</span><span class="st_h">'pdf_stringwidth'</span><span class="sy0">,</span><span class="st_h">'pdf_stroke'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pdf_translate'</span><span class="sy0">,</span><span class="st_h">'pdo_drivers'</span><span class="sy0">,</span><span class="st_h">'pfsockopen'</span><span class="sy0">,</span><span class="st_h">'pg_affected_rows'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_cancel_query'</span><span class="sy0">,</span><span class="st_h">'pg_clientencoding'</span><span class="sy0">,</span><span class="st_h">'pg_client_encoding'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_close'</span><span class="sy0">,</span><span class="st_h">'pg_cmdtuples'</span><span class="sy0">,</span><span class="st_h">'pg_connect'</span><span class="sy0">,</span><span class="st_h">'pg_connection_busy'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_connection_reset'</span><span class="sy0">,</span><span class="st_h">'pg_connection_status'</span><span class="sy0">,</span><span class="st_h">'pg_convert'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_copy_from'</span><span class="sy0">,</span><span class="st_h">'pg_copy_to'</span><span class="sy0">,</span><span class="st_h">'pg_dbname'</span><span class="sy0">,</span><span class="st_h">'pg_delete'</span><span class="sy0">,</span><span class="st_h">'pg_end_copy'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_errormessage'</span><span class="sy0">,</span><span class="st_h">'pg_escape_bytea'</span><span class="sy0">,</span><span class="st_h">'pg_escape_string'</span><span class="sy0">,</span><span class="st_h">'pg_exec'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_execute'</span><span class="sy0">,</span><span class="st_h">'pg_fetch_all'</span><span class="sy0">,</span><span class="st_h">'pg_fetch_all_columns'</span><span class="sy0">,</span><span class="st_h">'pg_fetch_array'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_fetch_assoc'</span><span class="sy0">,</span><span class="st_h">'pg_fetch_object'</span><span class="sy0">,</span><span class="st_h">'pg_fetch_result'</span><span class="sy0">,</span><span class="st_h">'pg_fetch_row'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_fieldisnull'</span><span class="sy0">,</span><span class="st_h">'pg_fieldname'</span><span class="sy0">,</span><span class="st_h">'pg_fieldnum'</span><span class="sy0">,</span><span class="st_h">'pg_fieldprtlen'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_fieldsize'</span><span class="sy0">,</span><span class="st_h">'pg_fieldtype'</span><span class="sy0">,</span><span class="st_h">'pg_field_is_null'</span><span class="sy0">,</span><span class="st_h">'pg_field_name'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_field_num'</span><span class="sy0">,</span><span class="st_h">'pg_field_prtlen'</span><span class="sy0">,</span><span class="st_h">'pg_field_size'</span><span class="sy0">,</span><span class="st_h">'pg_field_table'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_field_type'</span><span class="sy0">,</span><span class="st_h">'pg_field_type_oid'</span><span class="sy0">,</span><span class="st_h">'pg_free_result'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_freeresult'</span><span class="sy0">,</span><span class="st_h">'pg_get_notify'</span><span class="sy0">,</span><span class="st_h">'pg_get_pid'</span><span class="sy0">,</span><span class="st_h">'pg_get_result'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_getlastoid'</span><span class="sy0">,</span><span class="st_h">'pg_host'</span><span class="sy0">,</span><span class="st_h">'pg_insert'</span><span class="sy0">,</span><span class="st_h">'pg_last_error'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_last_notice'</span><span class="sy0">,</span><span class="st_h">'pg_last_oid'</span><span class="sy0">,</span><span class="st_h">'pg_loclose'</span><span class="sy0">,</span><span class="st_h">'pg_locreate'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_loexport'</span><span class="sy0">,</span><span class="st_h">'pg_loimport'</span><span class="sy0">,</span><span class="st_h">'pg_loopen'</span><span class="sy0">,</span><span class="st_h">'pg_loread'</span><span class="sy0">,</span><span class="st_h">'pg_loreadall'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_lounlink'</span><span class="sy0">,</span><span class="st_h">'pg_lowrite'</span><span class="sy0">,</span><span class="st_h">'pg_lo_close'</span><span class="sy0">,</span><span class="st_h">'pg_lo_create'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_lo_export'</span><span class="sy0">,</span><span class="st_h">'pg_lo_import'</span><span class="sy0">,</span><span class="st_h">'pg_lo_open'</span><span class="sy0">,</span><span class="st_h">'pg_lo_read'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_lo_read_all'</span><span class="sy0">,</span><span class="st_h">'pg_lo_seek'</span><span class="sy0">,</span><span class="st_h">'pg_lo_tell'</span><span class="sy0">,</span><span class="st_h">'pg_lo_unlink'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_lo_write'</span><span class="sy0">,</span><span class="st_h">'pg_meta_data'</span><span class="sy0">,</span><span class="st_h">'pg_numfields'</span><span class="sy0">,</span><span class="st_h">'pg_numrows'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_num_fields'</span><span class="sy0">,</span><span class="st_h">'pg_num_rows'</span><span class="sy0">,</span><span class="st_h">'pg_options'</span><span class="sy0">,</span><span class="st_h">'pg_parameter_status'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_pconnect'</span><span class="sy0">,</span><span class="st_h">'pg_ping'</span><span class="sy0">,</span><span class="st_h">'pg_port'</span><span class="sy0">,</span><span class="st_h">'pg_prepare'</span><span class="sy0">,</span><span class="st_h">'pg_put_line'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_query'</span><span class="sy0">,</span><span class="st_h">'pg_query_params'</span><span class="sy0">,</span><span class="st_h">'pg_result'</span><span class="sy0">,</span><span class="st_h">'pg_result_error'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_result_error_field'</span><span class="sy0">,</span><span class="st_h">'pg_result_seek'</span><span class="sy0">,</span><span class="st_h">'pg_result_status'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_select'</span><span class="sy0">,</span><span class="st_h">'pg_send_execute'</span><span class="sy0">,</span><span class="st_h">'pg_send_prepare'</span><span class="sy0">,</span><span class="st_h">'pg_send_query'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_send_query_params'</span><span class="sy0">,</span><span class="st_h">'pg_set_client_encoding'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_set_error_verbosity'</span><span class="sy0">,</span><span class="st_h">'pg_setclientencoding'</span><span class="sy0">,</span><span class="st_h">'pg_trace'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_transaction_status'</span><span class="sy0">,</span><span class="st_h">'pg_tty'</span><span class="sy0">,</span><span class="st_h">'pg_unescape_bytea'</span><span class="sy0">,</span><span class="st_h">'pg_untrace'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pg_update'</span><span class="sy0">,</span><span class="st_h">'pg_version'</span><span class="sy0">,</span><span class="st_h">'php_egg_logo_guid'</span><span class="sy0">,</span><span class="st_h">'php_ini_loaded_file'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'php_ini_scanned_files'</span><span class="sy0">,</span><span class="st_h">'php_logo_guid'</span><span class="sy0">,</span><span class="st_h">'php_real_logo_guid'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'php_sapi_name'</span><span class="sy0">,</span><span class="st_h">'php_strip_whitespace'</span><span class="sy0">,</span><span class="st_h">'php_uname'</span><span class="sy0">,</span><span class="st_h">'phpcredits'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'phpdoc_xml_from_string'</span><span class="sy0">,</span><span class="st_h">'phpinfo'</span><span class="sy0">,</span><span class="st_h">'phpversion'</span><span class="sy0">,</span><span class="st_h">'pi'</span><span class="sy0">,</span><span class="st_h">'png2wbmp'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pop3_close'</span><span class="sy0">,</span><span class="st_h">'pop3_delete_message'</span><span class="sy0">,</span><span class="st_h">'pop3_get_account_size'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pop3_get_message'</span><span class="sy0">,</span><span class="st_h">'pop3_get_message_count'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pop3_get_message_header'</span><span class="sy0">,</span><span class="st_h">'pop3_get_message_ids'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pop3_get_message_size'</span><span class="sy0">,</span><span class="st_h">'pop3_get_message_sizes'</span><span class="sy0">,</span><span class="st_h">'pop3_open'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'pop3_undelete'</span><span class="sy0">,</span><span class="st_h">'popen'</span><span class="sy0">,</span><span class="st_h">'pos'</span><span class="sy0">,</span><span class="st_h">'posix_ctermid'</span><span class="sy0">,</span><span class="st_h">'posix_errno'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'posix_getcwd'</span><span class="sy0">,</span><span class="st_h">'posix_getegid'</span><span class="sy0">,</span><span class="st_h">'posix_geteuid'</span><span class="sy0">,</span><span class="st_h">'posix_getgid'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'posix_getgrgid'</span><span class="sy0">,</span><span class="st_h">'posix_getgrnam'</span><span class="sy0">,</span><span class="st_h">'posix_getgroups'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'posix_getlogin'</span><span class="sy0">,</span><span class="st_h">'posix_getpgid'</span><span class="sy0">,</span><span class="st_h">'posix_getpgrp'</span><span class="sy0">,</span><span class="st_h">'posix_getpid'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'posix_getppid'</span><span class="sy0">,</span><span class="st_h">'posix_getpwnam'</span><span class="sy0">,</span><span class="st_h">'posix_getpwuid'</span><span class="sy0">,</span><span class="st_h">'posix_getrlimit'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'posix_getsid'</span><span class="sy0">,</span><span class="st_h">'posix_getuid'</span><span class="sy0">,</span><span class="st_h">'posix_get_last_error'</span><span class="sy0">,</span><span class="st_h">'posix_isatty'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'posix_kill'</span><span class="sy0">,</span><span class="st_h">'posix_mkfifo'</span><span class="sy0">,</span><span class="st_h">'posix_setegid'</span><span class="sy0">,</span><span class="st_h">'posix_seteuid'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'posix_setgid'</span><span class="sy0">,</span><span class="st_h">'posix_setpgid'</span><span class="sy0">,</span><span class="st_h">'posix_setsid'</span><span class="sy0">,</span><span class="st_h">'posix_setuid'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'posix_strerror'</span><span class="sy0">,</span><span class="st_h">'posix_times'</span><span class="sy0">,</span><span class="st_h">'posix_ttyname'</span><span class="sy0">,</span><span class="st_h">'posix_uname'</span><span class="sy0">,</span><span class="st_h">'pow'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'preg_grep'</span><span class="sy0">,</span><span class="st_h">'preg_last_error'</span><span class="sy0">,</span><span class="st_h">'preg_match'</span><span class="sy0">,</span><span class="st_h">'preg_match_all'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'preg_quote'</span><span class="sy0">,</span><span class="st_h">'preg_replace'</span><span class="sy0">,</span><span class="st_h">'preg_replace_callback'</span><span class="sy0">,</span><span class="st_h">'preg_split'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'prev'</span><span class="sy0">,</span><span class="st_h">'print_r'</span><span class="sy0">,</span><span class="st_h">'printf'</span><span class="sy0">,</span><span class="st_h">'proc_close'</span><span class="sy0">,</span><span class="st_h">'proc_get_status'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'proc_open'</span><span class="sy0">,</span><span class="st_h">'proc_terminate'</span><span class="sy0">,</span><span class="st_h">'putenv'</span><span class="sy0">,</span><span class="st_h">'quoted_printable_decode'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'quotemeta'</span><span class="sy0">,</span><span class="st_h">'rad2deg'</span><span class="sy0">,</span><span class="st_h">'radius_acct_open'</span><span class="sy0">,</span><span class="st_h">'radius_add_server'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'radius_auth_open'</span><span class="sy0">,</span><span class="st_h">'radius_close'</span><span class="sy0">,</span><span class="st_h">'radius_config'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'radius_create_request'</span><span class="sy0">,</span><span class="st_h">'radius_cvt_addr'</span><span class="sy0">,</span><span class="st_h">'radius_cvt_int'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'radius_cvt_string'</span><span class="sy0">,</span><span class="st_h">'radius_demangle'</span><span class="sy0">,</span><span class="st_h">'radius_demangle_mppe_key'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'radius_get_attr'</span><span class="sy0">,</span><span class="st_h">'radius_get_vendor_attr'</span><span class="sy0">,</span><span class="st_h">'radius_put_addr'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'radius_put_attr'</span><span class="sy0">,</span><span class="st_h">'radius_put_int'</span><span class="sy0">,</span><span class="st_h">'radius_put_string'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'radius_put_vendor_addr'</span><span class="sy0">,</span><span class="st_h">'radius_put_vendor_attr'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'radius_put_vendor_int'</span><span class="sy0">,</span><span class="st_h">'radius_put_vendor_string'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'radius_request_authenticator'</span><span class="sy0">,</span><span class="st_h">'radius_send_request'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'radius_server_secret'</span><span class="sy0">,</span><span class="st_h">'radius_strerror'</span><span class="sy0">,</span><span class="st_h">'rand'</span><span class="sy0">,</span><span class="st_h">'range'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'rawurldecode'</span><span class="sy0">,</span><span class="st_h">'rawurlencode'</span><span class="sy0">,</span><span class="st_h">'read_exif_data'</span><span class="sy0">,</span><span class="st_h">'readdir'</span><span class="sy0">,</span><span class="st_h">'readfile'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'readgzfile'</span><span class="sy0">,</span><span class="st_h">'readlink'</span><span class="sy0">,</span><span class="st_h">'realpath'</span><span class="sy0">,</span><span class="st_h">'reg_close_key'</span><span class="sy0">,</span><span class="st_h">'reg_create_key'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'reg_enum_key'</span><span class="sy0">,</span><span class="st_h">'reg_enum_value'</span><span class="sy0">,</span><span class="st_h">'reg_get_value'</span><span class="sy0">,</span><span class="st_h">'reg_open_key'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'reg_set_value'</span><span class="sy0">,</span><span class="st_h">'register_shutdown_function'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'register_tick_function'</span><span class="sy0">,</span><span class="st_h">'rename'</span><span class="sy0">,</span><span class="st_h">'res_close'</span><span class="sy0">,</span><span class="st_h">'res_get'</span><span class="sy0">,</span><span class="st_h">'res_list'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'res_list_type'</span><span class="sy0">,</span><span class="st_h">'res_open'</span><span class="sy0">,</span><span class="st_h">'res_set'</span><span class="sy0">,</span><span class="st_h">'reset'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'restore_error_handler'</span><span class="sy0">,</span><span class="st_h">'restore_include_path'</span><span class="sy0">,</span><span class="st_h">'rewind'</span><span class="sy0">,</span><span class="st_h">'rewinddir'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'rmdir'</span><span class="sy0">,</span><span class="st_h">'round'</span><span class="sy0">,</span><span class="st_h">'rsort'</span><span class="sy0">,</span><span class="st_h">'rtrim'</span><span class="sy0">,</span><span class="st_h">'runkit_class_adopt'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'runkit_class_emancipate'</span><span class="sy0">,</span><span class="st_h">'runkit_constant_add'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'runkit_constant_redefine'</span><span class="sy0">,</span><span class="st_h">'runkit_constant_remove'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'runkit_default_property_add'</span><span class="sy0">,</span><span class="st_h">'runkit_function_add'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'runkit_function_copy'</span><span class="sy0">,</span><span class="st_h">'runkit_function_redefine'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'runkit_function_remove'</span><span class="sy0">,</span><span class="st_h">'runkit_function_rename'</span><span class="sy0">,</span><span class="st_h">'runkit_import'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'runkit_lint'</span><span class="sy0">,</span><span class="st_h">'runkit_lint_file'</span><span class="sy0">,</span><span class="st_h">'runkit_method_add'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'runkit_method_copy'</span><span class="sy0">,</span><span class="st_h">'runkit_method_redefine'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'runkit_method_remove'</span><span class="sy0">,</span><span class="st_h">'runkit_method_rename'</span><span class="sy0">,</span><span class="st_h">'runkit_object_id'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'runkit_return_value_used'</span><span class="sy0">,</span><span class="st_h">'runkit_sandbox_output_handler'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'runkit_superglobals'</span><span class="sy0">,</span><span class="st_h">'runkit_zval_inspect'</span><span class="sy0">,</span><span class="st_h">'scandir'</span><span class="sy0">,</span><span class="st_h">'sem_acquire'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'sem_get'</span><span class="sy0">,</span><span class="st_h">'sem_release'</span><span class="sy0">,</span><span class="st_h">'sem_remove'</span><span class="sy0">,</span><span class="st_h">'serialize'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'session_cache_expire'</span><span class="sy0">,</span><span class="st_h">'session_cache_limiter'</span><span class="sy0">,</span><span class="st_h">'session_commit'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'session_decode'</span><span class="sy0">,</span><span class="st_h">'session_destroy'</span><span class="sy0">,</span><span class="st_h">'session_encode'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'session_get_cookie_params'</span><span class="sy0">,</span><span class="st_h">'session_id'</span><span class="sy0">,</span><span class="st_h">'session_is_registered'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'session_module_name'</span><span class="sy0">,</span><span class="st_h">'session_name'</span><span class="sy0">,</span><span class="st_h">'session_regenerate_id'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'session_register'</span><span class="sy0">,</span><span class="st_h">'session_save_path'</span><span class="sy0">,</span><span class="st_h">'session_set_cookie_params'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'session_set_save_handler'</span><span class="sy0">,</span><span class="st_h">'session_start'</span><span class="sy0">,</span><span class="st_h">'session_unregister'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'session_unset'</span><span class="sy0">,</span><span class="st_h">'session_write_close'</span><span class="sy0">,</span><span class="st_h">'set_content'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'set_error_handler'</span><span class="sy0">,</span><span class="st_h">'set_file_buffer'</span><span class="sy0">,</span><span class="st_h">'set_include_path'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'set_magic_quotes_runtime'</span><span class="sy0">,</span><span class="st_h">'set_socket_blocking'</span><span class="sy0">,</span><span class="st_h">'set_time_limit'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'setcookie'</span><span class="sy0">,</span><span class="st_h">'setlocale'</span><span class="sy0">,</span><span class="st_h">'setrawcookie'</span><span class="sy0">,</span><span class="st_h">'settype'</span><span class="sy0">,</span><span class="st_h">'sha1'</span><span class="sy0">,</span><span class="st_h">'sha1_file'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'shell_exec'</span><span class="sy0">,</span><span class="st_h">'shmop_close'</span><span class="sy0">,</span><span class="st_h">'shmop_delete'</span><span class="sy0">,</span><span class="st_h">'shmop_open'</span><span class="sy0">,</span><span class="st_h">'shmop_read'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'shmop_size'</span><span class="sy0">,</span><span class="st_h">'shmop_write'</span><span class="sy0">,</span><span class="st_h">'shm_attach'</span><span class="sy0">,</span><span class="st_h">'shm_detach'</span><span class="sy0">,</span><span class="st_h">'shm_get_var'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'shm_put_var'</span><span class="sy0">,</span><span class="st_h">'shm_remove'</span><span class="sy0">,</span><span class="st_h">'shm_remove_var'</span><span class="sy0">,</span><span class="st_h">'show_source'</span><span class="sy0">,</span><span class="st_h">'shuffle'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'similar_text'</span><span class="sy0">,</span><span class="st_h">'simplexml_import_dom'</span><span class="sy0">,</span><span class="st_h">'simplexml_load_file'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'simplexml_load_string'</span><span class="sy0">,</span><span class="st_h">'sin'</span><span class="sy0">,</span><span class="st_h">'sinh'</span><span class="sy0">,</span><span class="st_h">'sizeof'</span><span class="sy0">,</span><span class="st_h">'sleep'</span><span class="sy0">,</span><span class="st_h">'smtp_close'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'smtp_cmd_data'</span><span class="sy0">,</span><span class="st_h">'smtp_cmd_mail'</span><span class="sy0">,</span><span class="st_h">'smtp_cmd_rcpt'</span><span class="sy0">,</span><span class="st_h">'smtp_connect'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'snmp_get_quick_print'</span><span class="sy0">,</span><span class="st_h">'snmp_get_valueretrieval'</span><span class="sy0">,</span><span class="st_h">'snmp_read_mib'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'snmp_set_quick_print'</span><span class="sy0">,</span><span class="st_h">'snmp_set_valueretrieval'</span><span class="sy0">,</span><span class="st_h">'snmp2_get'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'snmp2_getnext'</span><span class="sy0">,</span><span class="st_h">'snmp2_real_walk'</span><span class="sy0">,</span><span class="st_h">'snmp2_set'</span><span class="sy0">,</span><span class="st_h">'snmp2_walk'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'snmp3_get'</span><span class="sy0">,</span><span class="st_h">'snmp3_getnext'</span><span class="sy0">,</span><span class="st_h">'snmp3_real_walk'</span><span class="sy0">,</span><span class="st_h">'snmp3_set'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'snmp3_walk'</span><span class="sy0">,</span><span class="st_h">'snmpget'</span><span class="sy0">,</span><span class="st_h">'snmpgetnext'</span><span class="sy0">,</span><span class="st_h">'snmprealwalk'</span><span class="sy0">,</span><span class="st_h">'snmpset'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'snmpwalk'</span><span class="sy0">,</span><span class="st_h">'snmpwalkoid'</span><span class="sy0">,</span><span class="st_h">'socket_accept'</span><span class="sy0">,</span><span class="st_h">'socket_bind'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'socket_clear_error'</span><span class="sy0">,</span><span class="st_h">'socket_close'</span><span class="sy0">,</span><span class="st_h">'socket_connect'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'socket_create'</span><span class="sy0">,</span><span class="st_h">'socket_create_listen'</span><span class="sy0">,</span><span class="st_h">'socket_create_pair'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'socket_getopt'</span><span class="sy0">,</span><span class="st_h">'socket_getpeername'</span><span class="sy0">,</span><span class="st_h">'socket_getsockname'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'socket_get_option'</span><span class="sy0">,</span><span class="st_h">'socket_get_status'</span><span class="sy0">,</span><span class="st_h">'socket_iovec_add'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'socket_iovec_alloc'</span><span class="sy0">,</span><span class="st_h">'socket_iovec_delete'</span><span class="sy0">,</span><span class="st_h">'socket_iovec_fetch'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'socket_iovec_free'</span><span class="sy0">,</span><span class="st_h">'socket_iovec_set'</span><span class="sy0">,</span><span class="st_h">'socket_last_error'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'socket_listen'</span><span class="sy0">,</span><span class="st_h">'socket_read'</span><span class="sy0">,</span><span class="st_h">'socket_readv'</span><span class="sy0">,</span><span class="st_h">'socket_recv'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'socket_recvfrom'</span><span class="sy0">,</span><span class="st_h">'socket_recvmsg'</span><span class="sy0">,</span><span class="st_h">'socket_select'</span><span class="sy0">,</span><span class="st_h">'socket_send'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'socket_sendmsg'</span><span class="sy0">,</span><span class="st_h">'socket_sendto'</span><span class="sy0">,</span><span class="st_h">'socket_setopt'</span><span class="sy0">,</span><span class="st_h">'socket_set_block'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'socket_set_blocking'</span><span class="sy0">,</span><span class="st_h">'socket_set_nonblock'</span><span class="sy0">,</span><span class="st_h">'socket_set_option'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'socket_set_timeout'</span><span class="sy0">,</span><span class="st_h">'socket_shutdown'</span><span class="sy0">,</span><span class="st_h">'socket_strerror'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'socket_write'</span><span class="sy0">,</span><span class="st_h">'socket_writev'</span><span class="sy0">,</span><span class="st_h">'sort'</span><span class="sy0">,</span><span class="st_h">'soundex'</span><span class="sy0">,</span><span class="st_h">'spl_autoload'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'spl_autoload_call'</span><span class="sy0">,</span><span class="st_h">'spl_autoload_extensions'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'spl_autoload_functions'</span><span class="sy0">,</span><span class="st_h">'spl_autoload_register'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'spl_autoload_unregister'</span><span class="sy0">,</span><span class="st_h">'spl_classes'</span><span class="sy0">,</span><span class="st_h">'spl_object_hash'</span><span class="sy0">,</span><span class="st_h">'split'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'spliti'</span><span class="sy0">,</span><span class="st_h">'sprintf'</span><span class="sy0">,</span><span class="st_h">'sql_regcase'</span><span class="sy0">,</span><span class="st_h">'sqlite_array_query'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'sqlite_busy_timeout'</span><span class="sy0">,</span><span class="st_h">'sqlite_changes'</span><span class="sy0">,</span><span class="st_h">'sqlite_close'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'sqlite_column'</span><span class="sy0">,</span><span class="st_h">'sqlite_create_aggregate'</span><span class="sy0">,</span><span class="st_h">'sqlite_create_function'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'sqlite_current'</span><span class="sy0">,</span><span class="st_h">'sqlite_error_string'</span><span class="sy0">,</span><span class="st_h">'sqlite_escape_string'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'sqlite_exec'</span><span class="sy0">,</span><span class="st_h">'sqlite_factory'</span><span class="sy0">,</span><span class="st_h">'sqlite_fetch_all'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'sqlite_fetch_array'</span><span class="sy0">,</span><span class="st_h">'sqlite_fetch_column_types'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'sqlite_fetch_object'</span><span class="sy0">,</span><span class="st_h">'sqlite_fetch_single'</span><span class="sy0">,</span><span class="st_h">'sqlite_fetch_string'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'sqlite_field_name'</span><span class="sy0">,</span><span class="st_h">'sqlite_has_more'</span><span class="sy0">,</span><span class="st_h">'sqlite_has_prev'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'sqlite_last_error'</span><span class="sy0">,</span><span class="st_h">'sqlite_last_insert_rowid'</span><span class="sy0">,</span><span class="st_h">'sqlite_libencoding'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'sqlite_libversion'</span><span class="sy0">,</span><span class="st_h">'sqlite_next'</span><span class="sy0">,</span><span class="st_h">'sqlite_num_fields'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'sqlite_num_rows'</span><span class="sy0">,</span><span class="st_h">'sqlite_open'</span><span class="sy0">,</span><span class="st_h">'sqlite_popen'</span><span class="sy0">,</span><span class="st_h">'sqlite_prev'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'sqlite_query'</span><span class="sy0">,</span><span class="st_h">'sqlite_rewind'</span><span class="sy0">,</span><span class="st_h">'sqlite_seek'</span><span class="sy0">,</span><span class="st_h">'sqlite_single_query'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'sqlite_udf_decode_binary'</span><span class="sy0">,</span><span class="st_h">'sqlite_udf_encode_binary'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'sqlite_unbuffered_query'</span><span class="sy0">,</span><span class="st_h">'sqlite_valid'</span><span class="sy0">,</span><span class="st_h">'sqrt'</span><span class="sy0">,</span><span class="st_h">'srand'</span><span class="sy0">,</span><span class="st_h">'sscanf'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ssh2_auth_hostbased_file'</span><span class="sy0">,</span><span class="st_h">'ssh2_auth_none'</span><span class="sy0">,</span><span class="st_h">'ssh2_auth_password'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ssh2_auth_pubkey_file'</span><span class="sy0">,</span><span class="st_h">'ssh2_connect'</span><span class="sy0">,</span><span class="st_h">'ssh2_exec'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ssh2_fetch_stream'</span><span class="sy0">,</span><span class="st_h">'ssh2_fingerprint'</span><span class="sy0">,</span><span class="st_h">'ssh2_forward_accept'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ssh2_forward_listen'</span><span class="sy0">,</span><span class="st_h">'ssh2_methods_negotiated'</span><span class="sy0">,</span><span class="st_h">'ssh2_poll'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ssh2_publickey_add'</span><span class="sy0">,</span><span class="st_h">'ssh2_publickey_init'</span><span class="sy0">,</span><span class="st_h">'ssh2_publickey_list'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ssh2_publickey_remove'</span><span class="sy0">,</span><span class="st_h">'ssh2_scp_recv'</span><span class="sy0">,</span><span class="st_h">'ssh2_scp_send'</span><span class="sy0">,</span><span class="st_h">'ssh2_sftp'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ssh2_sftp_lstat'</span><span class="sy0">,</span><span class="st_h">'ssh2_sftp_mkdir'</span><span class="sy0">,</span><span class="st_h">'ssh2_sftp_readlink'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ssh2_sftp_realpath'</span><span class="sy0">,</span><span class="st_h">'ssh2_sftp_rename'</span><span class="sy0">,</span><span class="st_h">'ssh2_sftp_rmdir'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ssh2_sftp_stat'</span><span class="sy0">,</span><span class="st_h">'ssh2_sftp_symlink'</span><span class="sy0">,</span><span class="st_h">'ssh2_sftp_unlink'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ssh2_shell'</span><span class="sy0">,</span><span class="st_h">'ssh2_tunnel'</span><span class="sy0">,</span><span class="st_h">'stat'</span><span class="sy0">,</span><span class="st_h">'stats_absolute_deviation'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_cdf_beta'</span><span class="sy0">,</span><span class="st_h">'stats_cdf_binomial'</span><span class="sy0">,</span><span class="st_h">'stats_cdf_cauchy'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_cdf_chisquare'</span><span class="sy0">,</span><span class="st_h">'stats_cdf_exponential'</span><span class="sy0">,</span><span class="st_h">'stats_cdf_f'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_cdf_gamma'</span><span class="sy0">,</span><span class="st_h">'stats_cdf_laplace'</span><span class="sy0">,</span><span class="st_h">'stats_cdf_logistic'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_cdf_negative_binomial'</span><span class="sy0">,</span><span class="st_h">'stats_cdf_noncentral_chisquare'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_cdf_noncentral_f'</span><span class="sy0">,</span><span class="st_h">'stats_cdf_noncentral_t'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_cdf_normal'</span><span class="sy0">,</span><span class="st_h">'stats_cdf_poisson'</span><span class="sy0">,</span><span class="st_h">'stats_cdf_t'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_cdf_uniform'</span><span class="sy0">,</span><span class="st_h">'stats_cdf_weibull'</span><span class="sy0">,</span><span class="st_h">'stats_covariance'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_dens_beta'</span><span class="sy0">,</span><span class="st_h">'stats_dens_cauchy'</span><span class="sy0">,</span><span class="st_h">'stats_dens_chisquare'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_dens_exponential'</span><span class="sy0">,</span><span class="st_h">'stats_dens_f'</span><span class="sy0">,</span><span class="st_h">'stats_dens_gamma'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_dens_laplace'</span><span class="sy0">,</span><span class="st_h">'stats_dens_logistic'</span><span class="sy0">,</span><span class="st_h">'stats_dens_normal'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_dens_pmf_binomial'</span><span class="sy0">,</span><span class="st_h">'stats_dens_pmf_hypergeometric'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_dens_pmf_negative_binomial'</span><span class="sy0">,</span><span class="st_h">'stats_dens_pmf_poisson'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_dens_t'</span><span class="sy0">,</span><span class="st_h">'stats_dens_uniform'</span><span class="sy0">,</span><span class="st_h">'stats_dens_weibull'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_harmonic_mean'</span><span class="sy0">,</span><span class="st_h">'stats_kurtosis'</span><span class="sy0">,</span><span class="st_h">'stats_rand_gen_beta'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_rand_gen_chisquare'</span><span class="sy0">,</span><span class="st_h">'stats_rand_gen_exponential'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_rand_gen_f'</span><span class="sy0">,</span><span class="st_h">'stats_rand_gen_funiform'</span><span class="sy0">,</span><span class="st_h">'stats_rand_gen_gamma'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_rand_gen_ipoisson'</span><span class="sy0">,</span><span class="st_h">'stats_rand_gen_iuniform'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_rand_gen_noncenral_f'</span><span class="sy0">,</span><span class="st_h">'stats_rand_gen_noncentral_chisquare'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_rand_gen_noncentral_t'</span><span class="sy0">,</span><span class="st_h">'stats_rand_gen_normal'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_rand_gen_t'</span><span class="sy0">,</span><span class="st_h">'stats_rand_getsd'</span><span class="sy0">,</span><span class="st_h">'stats_rand_ibinomial'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_rand_ibinomial_negative'</span><span class="sy0">,</span><span class="st_h">'stats_rand_ignlgi'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_rand_phrase_to_seeds'</span><span class="sy0">,</span><span class="st_h">'stats_rand_ranf'</span><span class="sy0">,</span><span class="st_h">'stats_rand_setall'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_skew'</span><span class="sy0">,</span><span class="st_h">'stats_standard_deviation'</span><span class="sy0">,</span><span class="st_h">'stats_stat_binomial_coef'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_stat_correlation'</span><span class="sy0">,</span><span class="st_h">'stats_stat_factorial'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_stat_independent_t'</span><span class="sy0">,</span><span class="st_h">'stats_stat_innerproduct'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_stat_paired_t'</span><span class="sy0">,</span><span class="st_h">'stats_stat_percentile'</span><span class="sy0">,</span><span class="st_h">'stats_stat_powersum'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stats_variance'</span><span class="sy0">,</span><span class="st_h">'strcasecmp'</span><span class="sy0">,</span><span class="st_h">'strchr'</span><span class="sy0">,</span><span class="st_h">'strcmp'</span><span class="sy0">,</span><span class="st_h">'strcoll'</span><span class="sy0">,</span><span class="st_h">'strcspn'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stream_bucket_append'</span><span class="sy0">,</span><span class="st_h">'stream_bucket_make_writeable'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stream_bucket_new'</span><span class="sy0">,</span><span class="st_h">'stream_bucket_prepend'</span><span class="sy0">,</span><span class="st_h">'stream_context_create'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stream_context_get_default'</span><span class="sy0">,</span><span class="st_h">'stream_context_get_options'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stream_context_set_default'</span><span class="sy0">,</span><span class="st_h">'stream_context_set_option'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stream_context_set_params'</span><span class="sy0">,</span><span class="st_h">'stream_copy_to_stream'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stream_encoding'</span><span class="sy0">,</span><span class="st_h">'stream_filter_append'</span><span class="sy0">,</span><span class="st_h">'stream_filter_prepend'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stream_filter_register'</span><span class="sy0">,</span><span class="st_h">'stream_filter_remove'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stream_get_contents'</span><span class="sy0">,</span><span class="st_h">'stream_get_filters'</span><span class="sy0">,</span><span class="st_h">'stream_get_line'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stream_get_meta_data'</span><span class="sy0">,</span><span class="st_h">'stream_get_transports'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stream_get_wrappers'</span><span class="sy0">,</span><span class="st_h">'stream_is_local'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stream_notification_callback'</span><span class="sy0">,</span><span class="st_h">'stream_register_wrapper'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stream_resolve_include_path'</span><span class="sy0">,</span><span class="st_h">'stream_select'</span><span class="sy0">,</span><span class="st_h">'stream_set_blocking'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stream_set_timeout'</span><span class="sy0">,</span><span class="st_h">'stream_set_write_buffer'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stream_socket_accept'</span><span class="sy0">,</span><span class="st_h">'stream_socket_client'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stream_socket_enable_crypto'</span><span class="sy0">,</span><span class="st_h">'stream_socket_get_name'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stream_socket_pair'</span><span class="sy0">,</span><span class="st_h">'stream_socket_recvfrom'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stream_socket_sendto'</span><span class="sy0">,</span><span class="st_h">'stream_socket_server'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stream_socket_shutdown'</span><span class="sy0">,</span><span class="st_h">'stream_supports_lock'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stream_wrapper_register'</span><span class="sy0">,</span><span class="st_h">'stream_wrapper_restore'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stream_wrapper_unregister'</span><span class="sy0">,</span><span class="st_h">'strftime'</span><span class="sy0">,</span><span class="st_h">'stripcslashes'</span><span class="sy0">,</span><span class="st_h">'stripos'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'stripslashes'</span><span class="sy0">,</span><span class="st_h">'strip_tags'</span><span class="sy0">,</span><span class="st_h">'stristr'</span><span class="sy0">,</span><span class="st_h">'strlen'</span><span class="sy0">,</span><span class="st_h">'strnatcasecmp'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'strnatcmp'</span><span class="sy0">,</span><span class="st_h">'strpbrk'</span><span class="sy0">,</span><span class="st_h">'strncasecmp'</span><span class="sy0">,</span><span class="st_h">'strncmp'</span><span class="sy0">,</span><span class="st_h">'strpos'</span><span class="sy0">,</span><span class="st_h">'strrchr'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'strrev'</span><span class="sy0">,</span><span class="st_h">'strripos'</span><span class="sy0">,</span><span class="st_h">'strrpos'</span><span class="sy0">,</span><span class="st_h">'strspn'</span><span class="sy0">,</span><span class="st_h">'strstr'</span><span class="sy0">,</span><span class="st_h">'strtok'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'strtolower'</span><span class="sy0">,</span><span class="st_h">'strtotime'</span><span class="sy0">,</span><span class="st_h">'strtoupper'</span><span class="sy0">,</span><span class="st_h">'strtr'</span><span class="sy0">,</span><span class="st_h">'strval'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'str_ireplace'</span><span class="sy0">,</span><span class="st_h">'str_pad'</span><span class="sy0">,</span><span class="st_h">'str_repeat'</span><span class="sy0">,</span><span class="st_h">'str_replace'</span><span class="sy0">,</span><span class="st_h">'str_rot13'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'str_split'</span><span class="sy0">,</span><span class="st_h">'str_shuffle'</span><span class="sy0">,</span><span class="st_h">'str_word_count'</span><span class="sy0">,</span><span class="st_h">'substr'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'substr_compare'</span><span class="sy0">,</span><span class="st_h">'substr_count'</span><span class="sy0">,</span><span class="st_h">'substr_replace'</span><span class="sy0">,</span><span class="st_h">'svn_add'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'svn_auth_get_parameter'</span><span class="sy0">,</span><span class="st_h">'svn_auth_set_parameter'</span><span class="sy0">,</span><span class="st_h">'svn_cat'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'svn_checkout'</span><span class="sy0">,</span><span class="st_h">'svn_cleanup'</span><span class="sy0">,</span><span class="st_h">'svn_client_version'</span><span class="sy0">,</span><span class="st_h">'svn_commit'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'svn_diff'</span><span class="sy0">,</span><span class="st_h">'svn_export'</span><span class="sy0">,</span><span class="st_h">'svn_fs_abort_txn'</span><span class="sy0">,</span><span class="st_h">'svn_fs_apply_text'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'svn_fs_begin_txn2'</span><span class="sy0">,</span><span class="st_h">'svn_fs_change_node_prop'</span><span class="sy0">,</span><span class="st_h">'svn_fs_check_path'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'svn_fs_contents_changed'</span><span class="sy0">,</span><span class="st_h">'svn_fs_copy'</span><span class="sy0">,</span><span class="st_h">'svn_fs_delete'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'svn_fs_dir_entries'</span><span class="sy0">,</span><span class="st_h">'svn_fs_file_contents'</span><span class="sy0">,</span><span class="st_h">'svn_fs_file_length'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'svn_fs_is_dir'</span><span class="sy0">,</span><span class="st_h">'svn_fs_is_file'</span><span class="sy0">,</span><span class="st_h">'svn_fs_make_dir'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'svn_fs_make_file'</span><span class="sy0">,</span><span class="st_h">'svn_fs_node_created_rev'</span><span class="sy0">,</span><span class="st_h">'svn_fs_node_prop'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'svn_fs_props_changed'</span><span class="sy0">,</span><span class="st_h">'svn_fs_revision_prop'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'svn_fs_revision_root'</span><span class="sy0">,</span><span class="st_h">'svn_fs_txn_root'</span><span class="sy0">,</span><span class="st_h">'svn_fs_youngest_rev'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'svn_import'</span><span class="sy0">,</span><span class="st_h">'svn_info'</span><span class="sy0">,</span><span class="st_h">'svn_log'</span><span class="sy0">,</span><span class="st_h">'svn_ls'</span><span class="sy0">,</span><span class="st_h">'svn_repos_create'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'svn_repos_fs'</span><span class="sy0">,</span><span class="st_h">'svn_repos_fs_begin_txn_for_commit'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'svn_repos_fs_commit_txn'</span><span class="sy0">,</span><span class="st_h">'svn_repos_hotcopy'</span><span class="sy0">,</span><span class="st_h">'svn_repos_open'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'svn_repos_recover'</span><span class="sy0">,</span><span class="st_h">'svn_status'</span><span class="sy0">,</span><span class="st_h">'svn_update'</span><span class="sy0">,</span><span class="st_h">'symlink'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'sys_get_temp_dir'</span><span class="sy0">,</span><span class="st_h">'syslog'</span><span class="sy0">,</span><span class="st_h">'system'</span><span class="sy0">,</span><span class="st_h">'tan'</span><span class="sy0">,</span><span class="st_h">'tanh'</span><span class="sy0">,</span><span class="st_h">'tempnam'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'textdomain'</span><span class="sy0">,</span><span class="st_h">'thread_get'</span><span class="sy0">,</span><span class="st_h">'thread_include'</span><span class="sy0">,</span><span class="st_h">'thread_lock'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'thread_lock_try'</span><span class="sy0">,</span><span class="st_h">'thread_mutex_destroy'</span><span class="sy0">,</span><span class="st_h">'thread_mutex_init'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'thread_set'</span><span class="sy0">,</span><span class="st_h">'thread_start'</span><span class="sy0">,</span><span class="st_h">'thread_unlock'</span><span class="sy0">,</span><span class="st_h">'tidy_access_count'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'tidy_clean_repair'</span><span class="sy0">,</span><span class="st_h">'tidy_config_count'</span><span class="sy0">,</span><span class="st_h">'tidy_diagnose'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'tidy_error_count'</span><span class="sy0">,</span><span class="st_h">'tidy_get_body'</span><span class="sy0">,</span><span class="st_h">'tidy_get_config'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'tidy_get_error_buffer'</span><span class="sy0">,</span><span class="st_h">'tidy_get_head'</span><span class="sy0">,</span><span class="st_h">'tidy_get_html'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'tidy_get_html_ver'</span><span class="sy0">,</span><span class="st_h">'tidy_get_output'</span><span class="sy0">,</span><span class="st_h">'tidy_get_release'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'tidy_get_root'</span><span class="sy0">,</span><span class="st_h">'tidy_get_status'</span><span class="sy0">,</span><span class="st_h">'tidy_getopt'</span><span class="sy0">,</span><span class="st_h">'tidy_is_xhtml'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'tidy_is_xml'</span><span class="sy0">,</span><span class="st_h">'tidy_parse_file'</span><span class="sy0">,</span><span class="st_h">'tidy_parse_string'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'tidy_repair_file'</span><span class="sy0">,</span><span class="st_h">'tidy_repair_string'</span><span class="sy0">,</span><span class="st_h">'tidy_warning_count'</span><span class="sy0">,</span><span class="st_h">'time'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'timezone_abbreviations_list'</span><span class="sy0">,</span><span class="st_h">'timezone_identifiers_list'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'timezone_name_from_abbr'</span><span class="sy0">,</span><span class="st_h">'timezone_name_get'</span><span class="sy0">,</span><span class="st_h">'timezone_offset_get'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'timezone_open'</span><span class="sy0">,</span><span class="st_h">'timezone_transitions_get'</span><span class="sy0">,</span><span class="st_h">'tmpfile'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'token_get_all'</span><span class="sy0">,</span><span class="st_h">'token_name'</span><span class="sy0">,</span><span class="st_h">'touch'</span><span class="sy0">,</span><span class="st_h">'trigger_error'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'transliterate'</span><span class="sy0">,</span><span class="st_h">'transliterate_filters_get'</span><span class="sy0">,</span><span class="st_h">'trim'</span><span class="sy0">,</span><span class="st_h">'uasort'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ucfirst'</span><span class="sy0">,</span><span class="st_h">'ucwords'</span><span class="sy0">,</span><span class="st_h">'uksort'</span><span class="sy0">,</span><span class="st_h">'umask'</span><span class="sy0">,</span><span class="st_h">'uniqid'</span><span class="sy0">,</span><span class="st_h">'unixtojd'</span><span class="sy0">,</span><span class="st_h">'unlink'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'unpack'</span><span class="sy0">,</span><span class="st_h">'unregister_tick_function'</span><span class="sy0">,</span><span class="st_h">'unserialize'</span><span class="sy0">,</span><span class="st_h">'unset'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'urldecode'</span><span class="sy0">,</span><span class="st_h">'urlencode'</span><span class="sy0">,</span><span class="st_h">'user_error'</span><span class="sy0">,</span><span class="st_h">'use_soap_error_handler'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'usleep'</span><span class="sy0">,</span><span class="st_h">'usort'</span><span class="sy0">,</span><span class="st_h">'utf8_decode'</span><span class="sy0">,</span><span class="st_h">'utf8_encode'</span><span class="sy0">,</span><span class="st_h">'var_dump'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'var_export'</span><span class="sy0">,</span><span class="st_h">'variant_abs'</span><span class="sy0">,</span><span class="st_h">'variant_add'</span><span class="sy0">,</span><span class="st_h">'variant_and'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'variant_cast'</span><span class="sy0">,</span><span class="st_h">'variant_cat'</span><span class="sy0">,</span><span class="st_h">'variant_cmp'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'variant_date_from_timestamp'</span><span class="sy0">,</span><span class="st_h">'variant_date_to_timestamp'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'variant_div'</span><span class="sy0">,</span><span class="st_h">'variant_eqv'</span><span class="sy0">,</span><span class="st_h">'variant_fix'</span><span class="sy0">,</span><span class="st_h">'variant_get_type'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'variant_idiv'</span><span class="sy0">,</span><span class="st_h">'variant_imp'</span><span class="sy0">,</span><span class="st_h">'variant_int'</span><span class="sy0">,</span><span class="st_h">'variant_mod'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'variant_mul'</span><span class="sy0">,</span><span class="st_h">'variant_neg'</span><span class="sy0">,</span><span class="st_h">'variant_not'</span><span class="sy0">,</span><span class="st_h">'variant_or'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'variant_pow'</span><span class="sy0">,</span><span class="st_h">'variant_round'</span><span class="sy0">,</span><span class="st_h">'variant_set'</span><span class="sy0">,</span><span class="st_h">'variant_set_type'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'variant_sub'</span><span class="sy0">,</span><span class="st_h">'variant_xor'</span><span class="sy0">,</span><span class="st_h">'version_compare'</span><span class="sy0">,</span><span class="st_h">'virtual'</span><span class="sy0">,</span><span class="st_h">'vfprintf'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'vprintf'</span><span class="sy0">,</span><span class="st_h">'vsprintf'</span><span class="sy0">,</span><span class="st_h">'wddx_add_vars'</span><span class="sy0">,</span><span class="st_h">'wddx_deserialize'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'wddx_packet_end'</span><span class="sy0">,</span><span class="st_h">'wddx_packet_start'</span><span class="sy0">,</span><span class="st_h">'wddx_serialize_value'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'wddx_serialize_vars'</span><span class="sy0">,</span><span class="st_h">'win_beep'</span><span class="sy0">,</span><span class="st_h">'win_browse_file'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'win_browse_folder'</span><span class="sy0">,</span><span class="st_h">'win_create_link'</span><span class="sy0">,</span><span class="st_h">'win_message_box'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'win_play_wav'</span><span class="sy0">,</span><span class="st_h">'win_shell_execute'</span><span class="sy0">,</span><span class="st_h">'win32_create_service'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'win32_delete_service'</span><span class="sy0">,</span><span class="st_h">'win32_get_last_control_message'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'win32_ps_list_procs'</span><span class="sy0">,</span><span class="st_h">'win32_ps_stat_mem'</span><span class="sy0">,</span><span class="st_h">'win32_ps_stat_proc'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'win32_query_service_status'</span><span class="sy0">,</span><span class="st_h">'win32_scheduler_delete_task'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'win32_scheduler_enum_tasks'</span><span class="sy0">,</span><span class="st_h">'win32_scheduler_get_task_info'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'win32_scheduler_run'</span><span class="sy0">,</span><span class="st_h">'win32_scheduler_set_task_info'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'win32_set_service_status'</span><span class="sy0">,</span><span class="st_h">'win32_start_service'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'win32_start_service_ctrl_dispatcher'</span><span class="sy0">,</span><span class="st_h">'win32_stop_service'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'wordwrap'</span><span class="sy0">,</span><span class="st_h">'xml_error_string'</span><span class="sy0">,</span><span class="st_h">'xml_get_current_byte_index'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_get_current_column_number'</span><span class="sy0">,</span><span class="st_h">'xml_get_current_line_number'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_get_error_code'</span><span class="sy0">,</span><span class="st_h">'xml_parse'</span><span class="sy0">,</span><span class="st_h">'xml_parser_create'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_parser_create_ns'</span><span class="sy0">,</span><span class="st_h">'xml_parser_free'</span><span class="sy0">,</span><span class="st_h">'xml_parser_get_option'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_parser_set_option'</span><span class="sy0">,</span><span class="st_h">'xml_parse_into_struct'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_set_character_data_handler'</span><span class="sy0">,</span><span class="st_h">'xml_set_default_handler'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_set_element_handler'</span><span class="sy0">,</span><span class="st_h">'xml_set_end_namespace_decl_handler'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_set_external_entity_ref_handler'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_set_notation_decl_handler'</span><span class="sy0">,</span><span class="st_h">'xml_set_object'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_set_processing_instruction_handler'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_set_start_namespace_decl_handler'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_set_unparsed_entity_decl_handler'</span><span class="sy0">,</span><span class="st_h">'xmldoc'</span><span class="sy0">,</span><span class="st_h">'xmldocfile'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlrpc_decode'</span><span class="sy0">,</span><span class="st_h">'xmlrpc_decode_request'</span><span class="sy0">,</span><span class="st_h">'xmlrpc_encode'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlrpc_encode_request'</span><span class="sy0">,</span><span class="st_h">'xmlrpc_get_type'</span><span class="sy0">,</span><span class="st_h">'xmlrpc_is_fault'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlrpc_parse_method_descriptions'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlrpc_server_add_introspection_data'</span><span class="sy0">,</span><span class="st_h">'xmlrpc_server_call_method'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlrpc_server_create'</span><span class="sy0">,</span><span class="st_h">'xmlrpc_server_destroy'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlrpc_server_register_introspection_callback'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlrpc_server_register_method'</span><span class="sy0">,</span><span class="st_h">'xmlrpc_set_type'</span><span class="sy0">,</span><span class="st_h">'xmltree'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlwriter_end_attribute'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_end_cdata'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlwriter_end_comment'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_end_document'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlwriter_end_dtd'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_end_dtd_attlist'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlwriter_end_dtd_element'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_end_dtd_entity'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlwriter_end_element'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_end_pi'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_flush'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlwriter_full_end_element'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_open_memory'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlwriter_open_uri'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_output_memory'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlwriter_set_indent'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_set_indent_string'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlwriter_start_attribute'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_start_attribute_ns'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlwriter_start_cdata'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_start_comment'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlwriter_start_document'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_start_dtd'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlwriter_start_dtd_attlist'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_start_dtd_element'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlwriter_start_dtd_entity'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_start_element'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlwriter_start_element_ns'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_start_pi'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_text'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlwriter_write_attribute'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_write_attribute_ns'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlwriter_write_cdata'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_write_comment'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlwriter_write_dtd'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_write_dtd_attlist'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlwriter_write_dtd_element'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_write_dtd_entity'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlwriter_write_element'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_write_element_ns'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xmlwriter_write_pi'</span><span class="sy0">,</span><span class="st_h">'xmlwriter_write_raw'</span><span class="sy0">,</span><span class="st_h">'xpath_eval'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xpath_eval_expression'</span><span class="sy0">,</span><span class="st_h">'xpath_new_context'</span><span class="sy0">,</span><span class="st_h">'xpath_register_ns'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xpath_register_ns_auto'</span><span class="sy0">,</span><span class="st_h">'xptr_eval'</span><span class="sy0">,</span><span class="st_h">'xptr_new_context'</span><span class="sy0">,</span><span class="st_h">'yp_all'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'yp_cat'</span><span class="sy0">,</span><span class="st_h">'yp_errno'</span><span class="sy0">,</span><span class="st_h">'yp_err_string'</span><span class="sy0">,</span><span class="st_h">'yp_first'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'yp_get_default_domain'</span><span class="sy0">,</span><span class="st_h">'yp_master'</span><span class="sy0">,</span><span class="st_h">'yp_match'</span><span class="sy0">,</span><span class="st_h">'yp_next'</span><span class="sy0">,</span><span class="st_h">'yp_order'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'zend_current_obfuscation_level'</span><span class="sy0">,</span><span class="st_h">'zend_get_cfg_var'</span><span class="sy0">,</span><span class="st_h">'zend_get_id'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'zend_loader_current_file'</span><span class="sy0">,</span><span class="st_h">'zend_loader_enabled'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'zend_loader_file_encoded'</span><span class="sy0">,</span><span class="st_h">'zend_loader_file_licensed'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'zend_loader_install_license'</span><span class="sy0">,</span><span class="st_h">'zend_loader_version'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'zend_logo_guid'</span><span class="sy0">,</span><span class="st_h">'zend_match_hostmasks'</span><span class="sy0">,</span><span class="st_h">'zend_obfuscate_class_name'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'zend_obfuscate_function_name'</span><span class="sy0">,</span><span class="st_h">'zend_optimizer_version'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'zend_runtime_obfuscate'</span><span class="sy0">,</span><span class="st_h">'zend_version'</span><span class="sy0">,</span><span class="st_h">'zip_close'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'zip_entry_close'</span><span class="sy0">,</span><span class="st_h">'zip_entry_compressedsize'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'zip_entry_compressionmethod'</span><span class="sy0">,</span><span class="st_h">'zip_entry_filesize'</span><span class="sy0">,</span><span class="st_h">'zip_entry_name'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'zip_entry_open'</span><span class="sy0">,</span><span class="st_h">'zip_entry_read'</span><span class="sy0">,</span><span class="st_h">'zip_open'</span><span class="sy0">,</span><span class="st_h">'zip_read'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'zlib_get_coding_type'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">4</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'DEFAULT_INCLUDE_PATH'</span><span class="sy0">,</span> <span class="st_h">'DIRECTORY_SEPARATOR'</span><span class="sy0">,</span> <span class="st_h">'E_ALL'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'E_COMPILE_ERROR'</span><span class="sy0">,</span> <span class="st_h">'E_COMPILE_WARNING'</span><span class="sy0">,</span> <span class="st_h">'E_CORE_ERROR'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'E_CORE_WARNING'</span><span class="sy0">,</span> <span class="st_h">'E_ERROR'</span><span class="sy0">,</span> <span class="st_h">'E_NOTICE'</span><span class="sy0">,</span> <span class="st_h">'E_PARSE'</span><span class="sy0">,</span> <span class="st_h">'E_STRICT'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'E_USER_ERROR'</span><span class="sy0">,</span> <span class="st_h">'E_USER_NOTICE'</span><span class="sy0">,</span> <span class="st_h">'E_USER_WARNING'</span><span class="sy0">,</span> <span class="st_h">'E_WARNING'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ENT_COMPAT'</span><span class="sy0">,</span><span class="st_h">'ENT_QUOTES'</span><span class="sy0">,</span><span class="st_h">'ENT_NOQUOTES'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'false'</span><span class="sy0">,</span> <span class="st_h">'null'</span><span class="sy0">,</span> <span class="st_h">'PEAR_EXTENSION_DIR'</span><span class="sy0">,</span> <span class="st_h">'PEAR_INSTALL_DIR'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'PHP_BINDIR'</span><span class="sy0">,</span> <span class="st_h">'PHP_CONFIG_FILE_PATH'</span><span class="sy0">,</span> <span class="st_h">'PHP_DATADIR'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'PHP_EXTENSION_DIR'</span><span class="sy0">,</span> <span class="st_h">'PHP_LIBDIR'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'PHP_LOCALSTATEDIR'</span><span class="sy0">,</span> <span class="st_h">'PHP_OS'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'PHP_OUTPUT_HANDLER_CONT'</span><span class="sy0">,</span> <span class="st_h">'PHP_OUTPUT_HANDLER_END'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'PHP_OUTPUT_HANDLER_START'</span><span class="sy0">,</span> <span class="st_h">'PHP_SYSCONFDIR'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'PHP_VERSION'</span><span class="sy0">,</span> <span class="st_h">'true'</span><span class="sy0">,</span> <span class="st_h">'__CLASS__'</span><span class="sy0">,</span> <span class="st_h">'__FILE__'</span><span class="sy0">,</span> <span class="st_h">'__FUNCTION__'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'__LINE__'</span><span class="sy0">,</span> <span class="st_h">'__METHOD__'</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="st_h">'SYMBOLS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'&lt;%'</span><span class="sy0">,</span> <span class="st_h">'&lt;%='</span><span class="sy0">,</span> <span class="st_h">'%&gt;'</span><span class="sy0">,</span> <span class="st_h">'&lt;?'</span><span class="sy0">,</span> <span class="st_h">'&lt;?='</span><span class="sy0">,</span> <span class="st_h">'?&gt;'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'('</span><span class="sy0">,</span> <span class="st_h">')'</span><span class="sy0">,</span> <span class="st_h">'['</span><span class="sy0">,</span> <span class="st_h">']'</span><span class="sy0">,</span> <span class="st_h">'{'</span><span class="sy0">,</span> <span class="st_h">'}'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'!'</span><span class="sy0">,</span> <span class="st_h">'@'</span><span class="sy0">,</span> <span class="st_h">'%'</span><span class="sy0">,</span> <span class="st_h">'&amp;'</span><span class="sy0">,</span> <span class="st_h">'|'</span><span class="sy0">,</span> <span class="st_h">'/'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'&lt;'</span><span class="sy0">,</span> <span class="st_h">'&gt;'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'='</span><span class="sy0">,</span> <span class="st_h">'-'</span><span class="sy0">,</span> <span class="st_h">'+'</span><span class="sy0">,</span> <span class="st_h">'*'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'.'</span><span class="sy0">,</span> <span class="st_h">':'</span><span class="sy0">,</span> <span class="st_h">','</span><span class="sy0">,</span> <span class="st_h">';'</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="st_h">'CASE_SENSITIVE'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; GESHI_COMMENTS <span class="sy0">=&gt;</span> <span class="kw4">false</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <span class="kw4">false</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <span class="kw4">false</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">3</span> <span class="sy0">=&gt;</span> <span class="kw4">false</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">4</span> <span class="sy0">=&gt;</span> <span class="kw4">false</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="st_h">'STYLES'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'KEYWORDS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #b1b100;'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #000000; font-weight: bold;'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">3</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #990000;'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">4</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #009900; font-weight: bold;'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'COMMENTS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #666666; font-style: italic;'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #666666; font-style: italic;'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">3</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #0000cc; font-style: italic;'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">4</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #009933; font-style: italic;'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'MULTI'</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #666666; font-style: italic;'</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ESCAPE_CHAR'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #000099; font-weight: bold;'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #000099; font-weight: bold;'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #660099; font-weight: bold;'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">3</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #660099; font-weight: bold;'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">4</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #006699; font-weight: bold;'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">5</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #006699; font-weight: bold; font-style: italic;'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">6</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #009933; font-weight: bold;'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'HARD'</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #000099; font-weight: bold;'</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'BRACKETS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #009900;'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'STRINGS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #0000ff;'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'HARD'</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #0000ff;'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'NUMBERS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #cc66cc;'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GESHI_NUMBER_OCT_PREFIX <span class="sy0">=&gt;</span> <span class="st_h">'color: #208080;'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GESHI_NUMBER_HEX_PREFIX <span class="sy0">=&gt;</span> <span class="st_h">'color: #208080;'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GESHI_NUMBER_FLT_SCI_ZERO <span class="sy0">=&gt;</span> <span class="st_h">'color:#800080;'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'METHODS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #004000;'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #004000;'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'SYMBOLS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #339933;'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #000000; font-weight: bold;'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'REGEXPS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #000088;'</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'SCRIPT'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">3</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">4</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">5</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="st_h">'URLS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">3</span> <span class="sy0">=&gt;</span> <span class="st_h">'http://www.php.net/{FNAMEL}'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">4</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="st_h">'OOLANG'</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="st_h">'OBJECT_SPLITTERS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <span class="st_h">'-&amp;gt;'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <span class="st_h">'::'</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="st_h">'REGEXPS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//Variables</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;[<span class="es1">\\</span>$]{1,2}[a-zA-Z_][a-zA-Z0-9_]*&quot;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="st_h">'STRICT_MODE_APPLIES'</span> <span class="sy0">=&gt;</span> GESHI_MAYBE<span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="st_h">'SCRIPT_DELIMITERS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'&lt;?php'</span> <span class="sy0">=&gt;</span> <span class="st_h">'?&gt;'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'&lt;?'</span> <span class="sy0">=&gt;</span> <span class="st_h">'?&gt;'</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'&lt;%'</span> <span class="sy0">=&gt;</span> <span class="st_h">'%&gt;'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">3</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'&lt;script language=&quot;php&quot;&gt;'</span> <span class="sy0">=&gt;</span> <span class="st_h">'&lt;/script&gt;'</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">4</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;/(&lt;\?(?:php)?)(?:'(?:[^'<span class="es1">\\</span><span class="es1">\\</span>]|<span class="es1">\\</span><span class="es1">\\</span>.)*?'|<span class="es1">\&quot;</span>(?:[^<span class="es1">\&quot;</span><span class="es1">\\</span><span class="es1">\\</span>]|<span class="es1">\\</span><span class="es1">\\</span>.)*?<span class="es1">\&quot;</span>|\/\*(?!\*\/).*?\*\/|.)*?(\?&gt;|\Z)/sm&quot;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">5</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;/(&lt;%)(?:'(?:[^'<span class="es1">\\</span><span class="es1">\\</span>]|<span class="es1">\\</span><span class="es1">\\</span>.)*?'|<span class="es1">\&quot;</span>(?:[^<span class="es1">\&quot;</span><span class="es1">\\</span><span class="es1">\\</span>]|<span class="es1">\\</span><span class="es1">\\</span>.)*?<span class="es1">\&quot;</span>|\/\*(?!\*\/).*?\*\/|.)*?(%&gt;|\Z)/sm&quot;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="st_h">'HIGHLIGHT_STRICT_BLOCK'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">3</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">4</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">5</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="st_h">'TAB_WIDTH'</span> <span class="sy0">=&gt;</span> <span class="nu0">4</span>
+<span class="xtra li2"><span class="de2"><span class="br0">&#41;</span><span class="sy0">;</span></span></span>&nbsp;
+<span class="xtra li2"><span class="de2"><span class="sy1">?&gt;</span></span></span></pre></td></tr></tbody></table>
+
+<p>If you&#8217;re remotely familiar with <abbr title="PHP: HTML Preprocessor">PHP</abbr> (or even if you&#8217;re not), you can see that all that a language file consists of is
+a glorified variable assignment. Easy! All a language file does is assign a variable <code class="highlighted php"><span class="re0">$language_data</span></code>. Though
+still, there&#8217;s a lot of indices to that array&#8230; but this section is here to break each index down and explain it to you.</p>
+
+<h3 id="language-file-conventions">4.2 Language File Conventions</h3><div class="nav"><a href="#language-file-example">Previous</a> | <a href="#language-files">Top</a> | <a href="#language-file-sections">Next</a></div>
+
+<p>There are several conventions that are used in language files. For ease of use and readability, your language
+files should obey the following rules:</p>
+
+<ul>
+<li><strong>Indentation is <em>4 spaces</em>, not tabs:</strong> Use spaces! as editors continiously screw up tabs there should be
+no tabs in your documents since it would look differently on every computer otherwise.</li>
+<li><strong>Strings are in single quotes:</strong> Every string in a language file should be in single quotes (&#8216;), unless you are
+specifying a single quote as a quotemark or escape character, in which case they can be in double quotes for
+readability; or if you are specifying a REGEXP (see below). This ensures that the language file can be loaded
+as fast as possible by <abbr title="PHP: HTML Preprocessor">PHP</abbr> as unnecessary parsing can be avoided.</li>
+<li><strong>Large arrays are multi-lined:</strong> An array with more than three or four values should be broken into multiple
+lines. In any case, lines should not be wider than a full-screen window (about 100 chars per line max).
+Don&#8217;t break the keywords arrays after every keyword.</li>
+<li><strong>Ending brackets for multi-lined arrays on a new line:</strong> Also with a comma after them, unless the array is
+the last one in a parent array. See the <abbr title="PHP: HTML Preprocessor">PHP</abbr> language file for examples of where to use commas.</li>
+<li><strong>Use <abbr title="Generic Syntax Highlighter">GeSHi</abbr>&#8217;s constants:</strong> For capatalisation, regular expressions etc. use the <abbr title="Generic Syntax Highlighter">GeSHi</abbr> constants, <em>not</em>
+their actual values.</li>
+<li><strong>Verbatim header format:</strong> Copy the file header verbatim from other language files and modify the values
+afterwards. Don&#8217;t try to invent own header formats, as your languages else will fail validation!</li>
+</ul>
+
+<p>There are more notes on each convention where it may appear in the language file sections below.</p>
+
+<h3 id="language-file-sections">4.3 Language File Sections</h3><div class="nav"><a href="#language-file-conventions">Previous</a> | <a href="#language-files">Top</a> | <a href="#language-file-header">Next</a></div>
+
+<p>This section will look at all the sections of a language file, and how they relate to the final highlighting result.</p>
+
+<h4 id="language-file-header">4.3.1 The Header</h4><div class="nav"><a href="#language-file-sections">Previous</a> | <a href="#language-file-sections">Top</a> | <a href="#language-file-start-indices">Next</a></div>
+
+<p>The <em>header</em> of a language file is the first lines with the big comment and the start of the variable
+<code class="highlighted php"><span class="re0">$language_data</span></code>:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+<span class="xtra li2"><span class="de2">8</span></span>9
+<span class="xtra li2"><span class="de2">10</span></span>11
+<span class="xtra li2"><span class="de2">12</span></span>13
+<span class="xtra li2"><span class="de2">14</span></span>15
+<span class="xtra li2"><span class="de2">16</span></span>17
+<span class="xtra li2"><span class="de2">18</span></span>19
+<span class="xtra li2"><span class="de2">20</span></span>21
+<span class="xtra li2"><span class="de2">22</span></span>23
+<span class="xtra li2"><span class="de2">24</span></span>25
+<span class="xtra li2"><span class="de2">26</span></span>27
+<span class="xtra li2"><span class="de2">28</span></span>29
+<span class="xtra li2"><span class="de2">30</span></span>31
+<span class="xtra li2"><span class="de2">32</span></span>33
+<span class="xtra li2"><span class="de2">34</span></span>35
+<span class="xtra li2"><span class="de2">36</span></span>37
+<span class="xtra li2"><span class="de2">38</span></span>39
+<span class="xtra li2"><span class="de2">40</span></span>41
+<span class="xtra li2"><span class="de2">42</span></span>43
+</pre></td><td class="de1"><pre class="de1"><span class="kw2">&lt;?php</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">/*************************************************************************************</span></span></span><span class="coMULTI">&nbsp;* &lt;name-of-language-file.php&gt;</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* ---------------------------------</span></span></span><span class="coMULTI">&nbsp;* Author: &lt;name&gt; (&lt;e-mail address&gt;)</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* Copyright: (c) 2008 &lt;name&gt; (&lt;website URL&gt;)</span></span></span><span class="coMULTI">&nbsp;* Release Version: &lt;GeSHi release&gt;</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* Date Started: &lt;date started&gt;</span></span></span><span class="coMULTI">&nbsp;*</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* &lt;name-of-language&gt; language file for GeSHi.</span></span></span><span class="coMULTI">&nbsp;*</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* &lt;any-comments...&gt;</span></span></span><span class="coMULTI">&nbsp;*</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* CHANGES</span></span></span><span class="coMULTI">&nbsp;* -------</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* &lt;date-of-release&gt; (&lt;GeSHi release&gt;)</span></span></span><span class="coMULTI">&nbsp;* &nbsp;- &nbsp;First Release</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;*</span></span></span><span class="coMULTI">&nbsp;* TODO (updated &lt;date-of-release&gt;)</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* -------------------------</span></span></span><span class="coMULTI">&nbsp;* &lt;things-to-do&gt;</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;*</span></span></span><span class="coMULTI">&nbsp;*************************************************************************************</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;*</span></span></span><span class="coMULTI">&nbsp;* &nbsp; &nbsp; This file is part of GeSHi.</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;*</span></span></span><span class="coMULTI">&nbsp;* &nbsp; GeSHi is free software; you can redistribute it and/or modify</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* &nbsp; it under the terms of the GNU General Public License as published by</span></span></span><span class="coMULTI">&nbsp;* &nbsp; the Free Software Foundation; either version 2 of the License, or</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* &nbsp; (at your option) any later version.</span></span></span><span class="coMULTI">&nbsp;*</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* &nbsp; GeSHi is distributed in the hope that it will be useful,</span></span></span><span class="coMULTI">&nbsp;* &nbsp; but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* &nbsp; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. &nbsp;See the</span></span></span><span class="coMULTI">&nbsp;* &nbsp; GNU General Public License for more details.</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;*</span></span></span><span class="coMULTI">&nbsp;* &nbsp; You should have received a copy of the GNU General Public License</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;* &nbsp; along with GeSHi; if not, write to the Free Software</span></span></span><span class="coMULTI">&nbsp;* &nbsp; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA &nbsp;02111-1307 &nbsp;USA</span>
+<span class="xtra li2"><span class="de2"><span class="coMULTI">&nbsp;*</span></span></span><span class="coMULTI">&nbsp;************************************************************************************/</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="re0">$language_data</span> <span class="sy0">=</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a> <span class="br0">&#40;</span></pre></td></tr></tbody></table>
+
+<p>The parts in angle brackets are the parts that you change for your language file. <strong>Everything else <em>must</em> remain the same!</strong></p>
+
+<p>Here are the parts you should change:</p>
+
+<ul>
+<li><code>&lt;name-of-language-file.php&gt;</code> - This should become the name of your language file. Language file names are in
+lower case and contain only alphanumeric characters, dashes and underscores. Language files end with .php (which
+you should put with the name of your language file, eg language.php)</li>
+<li><code>&lt;name&gt;</code> - Your name, or alias.</li>
+<li><code>&lt;e-mail address&gt;</code> - Your e-mail address. If you want your language file included with <abbr title="Generic Syntax Highlighter">GeSHi</abbr> you <em>must</em>
+include an e-mail address that refers to an inbox controlled by you.</li>
+<li><code>&lt;website&gt;</code> - A URL of a website of yours (perhaps to a page that deals with your contribution to <abbr title="Generic Syntax Highlighter">GeSHi</abbr>, or
+your home page/blog)</li>
+<li><code>&lt;date-started&gt;</code> - The date you started working on the language file. If you can&#8217;t remember, guestimate.</li>
+<li><code>&lt;name-of-language&gt;</code> - The name of the language you made this language file for (probably similar to
+the language file name).</li>
+<li><code>&lt;any-comments&gt;</code> - Any comments you have to make about this language file, perhaps on where you got the keywords for,
+what dialect of the language this language file is for etc etc. If you don&#8217;t have any comments, remove the space for them.</li>
+<li><code>&lt;date-of-release</code> - The date you released the language file to the public. If you simply send it to me for inclusion
+in a new <abbr title="Generic Syntax Highlighter">GeSHi</abbr> and don&#8217;t release it, leave this blank, and I&#8217;ll replace it with the date of the <abbr title="Generic Syntax Highlighter">GeSHi</abbr> release that
+it is first added to.</li>
+<li><code>&lt;GeSHi release&gt;</code> - This is the version of the release that will contain the changes you made.
+So if you have version 1.0.8 of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> running this will be the next version to be released, e.g. 1.0.8.1.</li>
+</ul>
+
+<p>Everything should remain the same.</p>
+
+<p><strong>Also:</strong> I&#8217;m not sure about the copyright on a new language file. I&#8217;m not a lawyer, could someone contact me about
+whether the copyright for a new language file should be exclusivly the authors, or joint with me (if included in a
+<abbr title="Generic Syntax Highlighter">GeSHi</abbr> release)?</p>
+
+<h4 id="language-file-start-indices">4.3.2 The First Indices</h4><div class="nav"><a href="#language-file-header">Previous</a> | <a href="#language-file-sections">Top</a> | <a href="#language-file-keywords">Next</a></div>
+
+<p>Here is an example from the php language file of the first indices:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span></pre></td><td class="de1"><pre class="de1"><span class="st_h">'LANG_NAME'</span> <span class="sy0">=&gt;</span> <span class="st_h">'PHP'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2"><span class="st_h">'COMMENT_SINGLE'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="nu0">1</span> <span class="sy0">=&gt;</span> <span class="st_h">'//'</span><span class="sy0">,</span> <span class="nu0">2</span> <span class="sy0">=&gt;</span> <span class="st_h">'#'</span><span class="br0">&#41;</span><span class="sy0">,</span></span></span><span class="st_h">'COMMENT_MULTI'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'/*'</span> <span class="sy0">=&gt;</span> <span class="st_h">'*/'</span><span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2"><span class="st_h">'CASE_KEYWORDS'</span> <span class="sy0">=&gt;</span> GESHI_CAPS_NO_CHANGE<span class="sy0">,</span></span></span><span class="st_h">'QUOTEMARKS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">&quot;'&quot;</span><span class="sy0">,</span> <span class="st_h">'&quot;'</span><span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2"><span class="st_h">'ESCAPE_CHAR'</span> <span class="sy0">=&gt;</span> <span class="st_h">'\\'</span><span class="sy0">,</span></span></span></pre></td></tr></tbody></table>
+
+<p>The first indices are the first few lines of a language file before the KEYWORDS index. These indices specify:</p>
+
+<ul>
+<li><strong>&#8216;LANG_NAME&#8217;</strong>: The name of the language. This name should be a human-readable version of the name
+(e.g. <abbr title="Hypertext Markup Language">HTML</abbr> 4 (transitional) instead of html4trans)</li>
+<li><strong>&#8216;COMMENT_SINGLE&#8217;:</strong> An array of single-line comments in your language, indexed by integers starting
+from 1. A single line comment is a comment that starts at the marker and goes until the end of the line. These
+comments may be any length > 0, and since they can be styled individually, can be used for other things than comments
+(for example the Java language file defines &#8220;import&#8221; as a single line comment). If you are making a language that
+uses a &#8217; (apostrophe) as a comment (or in the comment marker somewhere), use double quotes. e.g.: &#8220;&#8217;&#8221;</li>
+<li><strong>&#8216;COMMENT_MULTI&#8217;:</strong> Used to specify multiline comments, an array in the form &#8216;OPEN&#8217; => &#8216;CLOSE&#8217;. Unfortunately,
+all of these comments you add here will be styled the same way (an area of improvement for <abbr title="Generic Syntax Highlighter">GeSHi</abbr> 1.2.X).
+These comment markers may be any length > 0.</li>
+<li><strong>&#8216;CASE_KEYWORDS&#8217;:</strong> Used to set whether the case of keywords should be changed automatically as they are found.
+For example, in an SQL or BASIC dialect you may want all keywords to be upper case. The accepted values for this are:</li>
+<li><code>GESHI_CAPS_UPPER</code>: Convert the case of all keywords to upper case.</li>
+<li><code>GESHI_CAPS_LOWER</code>: Convert the case of all keywords to lower case.</li>
+<li><code>GESHI_CAPS_NO_CHANGE</code>: Don&#8217;t change the case of any keyword.</li>
+<li><strong>&#8216;QUOTEMARKS&#8217;:</strong> Specifies the characters that mark the beginning and end of a string. This is another example
+where if your language includes the &#8217; string delimiter you should use double quotes around it.</li>
+<li><strong>&#8216;ESCAPE_CHAR&#8217;:</strong> Specifies the escape character used in all strings. If your language does not have an escape
+character then make this the empty string (<code>''</code>). This is not an array! If found, any character after an
+escape character and the escape character itself will be highlighted differently, and the character after the
+escape character cannot end a string.</li>
+</ul>
+
+<p>In some language files you might see here other indices too, but those are dealt with later on.</p>
+
+<h4 id="language-file-keywords">4.3.3 Keywords</h4><div class="nav"><a href="#language-file-start-indices">Previous</a> | <a href="#language-file-sections">Top</a> | <a href="#language-file-symbols-case">Next</a></div>
+
+<p>Keywords will make up the bulk of a language file. In this part you add keywords for your language, including
+inbuilt functions, data types, predefined constants etc etc.</p>
+
+<p>Here&#8217;s a (shortened) example from the php language file:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+<span class="xtra li2"><span class="de2">8</span></span>9
+<span class="xtra li2"><span class="de2">10</span></span>11
+<span class="xtra li2"><span class="de2">12</span></span>13
+<span class="xtra li2"><span class="de2">14</span></span>15
+<span class="xtra li2"><span class="de2">16</span></span>17
+<span class="xtra li2"><span class="de2">18</span></span>19
+<span class="xtra li2"><span class="de2">20</span></span>21
+<span class="xtra li2"><span class="de2">22</span></span>23
+<span class="xtra li2"><span class="de2">24</span></span>25
+<span class="xtra li2"><span class="de2">26</span></span>27
+<span class="xtra li2"><span class="de2">28</span></span>29
+<span class="xtra li2"><span class="de2">30</span></span>31
+<span class="xtra li2"><span class="de2">32</span></span>33
+<span class="xtra li2"><span class="de2">34</span></span>35
+<span class="xtra li2"><span class="de2">36</span></span>37
+<span class="xtra li2"><span class="de2">38</span></span>39
+<span class="xtra li2"><span class="de2">40</span></span></pre></td><td class="de1"><pre class="de1"><span class="st_h">'KEYWORDS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'as'</span><span class="sy0">,</span> <span class="st_h">'break'</span><span class="sy0">,</span> <span class="st_h">'case'</span><span class="sy0">,</span> <span class="st_h">'do'</span><span class="sy0">,</span> <span class="st_h">'else'</span><span class="sy0">,</span> <span class="st_h">'elseif'</span><span class="sy0">,</span> <span class="st_h">'endif'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'endswitch'</span><span class="sy0">,</span> <span class="st_h">'endwhile'</span><span class="sy0">,</span> <span class="st_h">'for'</span><span class="sy0">,</span> <span class="st_h">'foreach'</span><span class="sy0">,</span> <span class="st_h">'if'</span><span class="sy0">,</span> <span class="st_h">'include'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'include_once'</span><span class="sy0">,</span> <span class="st_h">'require'</span><span class="sy0">,</span> <span class="st_h">'require_once'</span><span class="sy0">,</span> <span class="st_h">'return'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'switch'</span><span class="sy0">,</span> <span class="st_h">'while'</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'&amp;lt;/script&gt;'</span><span class="sy0">,</span> <span class="st_h">'&amp;lt;?'</span><span class="sy0">,</span> <span class="st_h">'&amp;lt;?php'</span><span class="sy0">,</span> <span class="st_h">'&amp;lt;script language='</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'?&gt;'</span><span class="sy0">,</span> <span class="st_h">'class'</span><span class="sy0">,</span> <span class="st_h">'default'</span><span class="sy0">,</span> <span class="st_h">'DEFAULT_INCLUDE_PATH'</span><span class="sy0">,</span> <span class="st_h">'E_ALL'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'E_COMPILE_ERROR'</span><span class="sy0">,</span> <span class="st_h">'E_COMPILE_WARNING'</span><span class="sy0">,</span> <span class="st_h">'E_CORE_ERROR'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'E_CORE_WARNING'</span><span class="sy0">,</span> <span class="st_h">'E_ERROR'</span><span class="sy0">,</span> <span class="st_h">'E_NOTICE'</span><span class="sy0">,</span> <span class="st_h">'E_PARSE'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'E_USER_ERROR'</span><span class="sy0">,</span> <span class="st_h">'E_USER_NOTICE'</span><span class="sy0">,</span> <span class="st_h">'E_USER_WARNING'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'E_WARNING'</span><span class="sy0">,</span> <span class="st_h">'false'</span><span class="sy0">,</span> <span class="st_h">'function'</span><span class="sy0">,</span> <span class="st_h">'new'</span><span class="sy0">,</span> <span class="st_h">'null'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'PEAR_EXTENSION_DIR'</span><span class="sy0">,</span> <span class="st_h">'PEAR_INSTALL_DIR'</span><span class="sy0">,</span> <span class="st_h">'PHP_BINDIR'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'PHP_CONFIG_FILE_PATH'</span><span class="sy0">,</span> <span class="st_h">'PHP_DATADIR'</span><span class="sy0">,</span> <span class="st_h">'PHP_EXTENSION_DIR'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'PHP_LIBDIR'</span><span class="sy0">,</span> <span class="st_h">'PHP_LOCALSTATEDIR'</span><span class="sy0">,</span> <span class="st_h">'PHP_OS'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'PHP_OUTPUT_HANDLER_CONT'</span><span class="sy0">,</span> <span class="st_h">'PHP_OUTPUT_HANDLER_END'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'PHP_OUTPUT_HANDLER_START'</span><span class="sy0">,</span> <span class="st_h">'PHP_SYSCONFDIR'</span><span class="sy0">,</span> <span class="st_h">'PHP_VERSION'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'true'</span><span class="sy0">,</span> <span class="st_h">'var'</span><span class="sy0">,</span> <span class="st_h">'__CLASS__'</span><span class="sy0">,</span> <span class="st_h">'__FILE__'</span><span class="sy0">,</span> <span class="st_h">'__FUNCTION__'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'__LINE__'</span><span class="sy0">,</span> <span class="st_h">'__METHOD__'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="nu0">3</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_parser_create'</span><span class="sy0">,</span> <span class="st_h">'xml_parser_create_ns'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_parser_free'</span><span class="sy0">,</span> <span class="st_h">'xml_parser_get_option'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_parser_set_option'</span><span class="sy0">,</span> <span class="st_h">'xml_parse_into_struct'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_set_character_data_handler'</span><span class="sy0">,</span> <span class="st_h">'xml_set_default_handler'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_set_element_handler'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_set_end_namespace_decl_handler'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_set_external_entity_ref_handler'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_set_notation_decl_handler'</span><span class="sy0">,</span> <span class="st_h">'xml_set_object'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_set_processing_instruction_handler'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_set_start_namespace_decl_handler'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'xml_set_unparsed_entity_decl_handler'</span><span class="sy0">,</span> <span class="st_h">'yp_all'</span><span class="sy0">,</span> <span class="st_h">'yp_cat'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'yp_errno'</span><span class="sy0">,</span> <span class="st_h">'yp_err_string'</span><span class="sy0">,</span> <span class="st_h">'yp_first'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'yp_get_default_domain'</span><span class="sy0">,</span> <span class="st_h">'yp_master'</span><span class="sy0">,</span> <span class="st_h">'yp_match'</span><span class="sy0">,</span> <span class="st_h">'yp_next'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'yp_order'</span><span class="sy0">,</span> <span class="st_h">'zend_logo_guid'</span><span class="sy0">,</span> <span class="st_h">'zend_version'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'zlib_get_coding_type'</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span></pre></td></tr></tbody></table>
+
+<p>You can see that the index &#8216;KEYWORDS&#8217; refers to an array of arrays, indexed by positive integers. In each array,
+there are some keywords (in the actual php language file there is in fact many more keywords in the array indexed by 3).
+Here are some points to note about these keywords:</p>
+
+<ul>
+<li><strong>Indexed by positive integers:</strong> Use nothing else! I may change this in 1.2.X, but for the 1.0.X series,
+use positive integers only. Using strings here results in unnecessary overhead degrading performance when
+highlighting code with your language file!</li>
+<li><strong>Keywords sorted ascending:</strong> Keywords <em>should</em> be sorted in <em>ascending</em> order. This is mainly for
+readability. An issue with versions before 1.0.8 has been solved, so the reverse sorting order
+is no longer required and should thus be avoided. <abbr title="Generic Syntax Highlighter">GeSHi</abbr> itself sorts the keywords internally when
+building some of its caches, so the order doesn&#8217;t matter, but makes things easier to read and maintain.</li>
+<li><strong>Keywords are case sensitive (sometimes):</strong> If your language is case-sensitive, the correct casing of the
+keywords is defined as the case of the keywords in these keyword arrays. If you check the java language file you
+will see that everything is in exact casing. So if any of these keyword arrays are case sensitive, put the
+keywords in as their correct case! (note that which groups are case sensitive and which are not is configurable,
+see later on). If a keyword group is case insensitive, put the lowercase version of the keyword here
+<strong>OR</strong> in case documentation links require a special casing (other than all lowercase or all uppercase)
+the casing required for them use their casing.</li>
+<li><strong>Keywords must be in <code class="highlighted php"><span class="kw3">htmlentities</span><span class="br0">&#40;</span><span class="br0">&#41;</span></code> form:</strong> All keywords should be written as if they had been
+run through the php function <code class="highlighted php"><span class="kw3">htmlentities</span><span class="br0">&#40;</span><span class="br0">&#41;</span></code>. E.g, the keyword is <code class="highlighted html4strict"><span class="sc1">&amp;lt;</span>foo<span class="sc1">&amp;gt;</span></code>, not
+<code class="highlighted html4strict"><span class="sc2">&lt;foo&gt;</span></code></li>
+<li><strong>Don&#8217;t use keywords to highlight symbols:</strong> Just don&#8217;t!!! It doesn&#8217;t work, and there is seperate support
+for symbols since <abbr title="Generic Syntax Highlighter">GeSHi</abbr> 1.0.7.21.</li>
+<li><strong>Markup Languages are special cases:</strong> Check the html4strict language file for an example: You need to tweak
+the Parser control here to tell the surroundings of tagnames. In case of doubt, feel free to ask.</li>
+</ul>
+
+<h4 id="language-file-symbols-case">4.3.4 Symbols and Case Sensitivity</h4><div class="nav"><a href="#language-file-keywords">Previous</a> | <a href="#language-file-sections">Top</a> | <a href="#language-file-styles">Next</a></div>
+
+<p>So you&#8217;ve put all the keywords for your language in? Now for a breather before we style them :). Symbols define
+what symbols your language uses. These are things like colons, brackets/braces, and other such general punctuation.
+No alphanumeric stuff belongs here, just the same as no symbols belong into the keywords section.</p>
+
+<p>As of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> version 1.0.7.21 the symbols section can be used in two ways:</p>
+
+<dl>
+<dt>Flat usage:</dt>
+<dd>This mode is the suggested way for existing language files and languages that only need few symbols where no
+further differentiation is needed or desired. You simply put all the characters in an array under symbols as shown
+in the first example below. All symbols in flat usage belong to symbol style group 0.</dd>
+
+<dt>Group usage:</dt>
+<dd>This is a slightly more enhanced way to provide <abbr title="Generic Syntax Highlighter">GeSHi</abbr> symbol information. To use group you create several subarrays
+each containing only a subset of the symbols to highlight. Every array will need to have an unique index thus
+you can assign the appropriate styles later.</dd>
+</dl>
+
+<p>Here&#8217;s an example for flat symbol usage</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+</pre></td><td class="de1"><pre class="de1"><span class="st_h">'SYMBOLS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; <span class="st_h">'('</span><span class="sy0">,</span> <span class="st_h">')'</span><span class="sy0">,</span> <span class="st_h">'['</span><span class="sy0">,</span> <span class="st_h">']'</span><span class="sy0">,</span> <span class="st_h">'{'</span><span class="sy0">,</span> <span class="st_h">'}'</span><span class="sy0">,</span> <span class="st_h">'!'</span><span class="sy0">,</span> <span class="st_h">'@'</span><span class="sy0">,</span> <span class="st_h">'|'</span><span class="sy0">,</span> <span class="st_h">'&amp;'</span><span class="sy0">,</span> <span class="st_h">'+'</span><span class="sy0">,</span> <span class="st_h">'-'</span><span class="sy0">,</span> <span class="st_h">'*'</span><span class="sy0">,</span> <span class="st_h">'/'</span><span class="sy0">,</span> <span class="st_h">'%'</span><span class="sy0">,</span> <span class="st_h">'='</span><span class="sy0">,</span> <span class="st_h">'&lt;'</span><span class="sy0">,</span> <span class="st_h">'&gt;'</span></span></span><span class="br0">&#41;</span><span class="sy0">,</span></pre></td></tr></tbody></table>
+
+<p>which is not too different from the newly introduced group usage shown below:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span></pre></td><td class="de1"><pre class="de1"><span class="st_h">'SYMBOLS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'('</span><span class="sy0">,</span> <span class="st_h">')'</span><span class="sy0">,</span> <span class="st_h">'['</span><span class="sy0">,</span> <span class="st_h">']'</span><span class="sy0">,</span> <span class="st_h">'{'</span><span class="sy0">,</span> <span class="st_h">'}'</span><span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'!'</span><span class="sy0">,</span> <span class="st_h">'@'</span><span class="sy0">,</span> <span class="st_h">'|'</span><span class="sy0">,</span> <span class="st_h">'&amp;'</span><span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'+'</span><span class="sy0">,</span> <span class="st_h">'-'</span><span class="sy0">,</span> <span class="st_h">'*'</span><span class="sy0">,</span> <span class="st_h">'/'</span><span class="sy0">,</span> <span class="st_h">'%'</span><span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; <span class="nu0">3</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st_h">'='</span><span class="sy0">,</span> <span class="st_h">'&amp;lt;'</span><span class="sy0">,</span> <span class="st_h">'&gt;'</span><span class="br0">&#41;</span>
+<span class="xtra li2"><span class="de2"><span class="br0">&#41;</span><span class="sy0">,</span></span></span></pre></td></tr></tbody></table>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>Please note that versions before 1.0.7.21 will silently ignore this setting.</p>
+
+<p>Also note that <abbr title="Generic Syntax Highlighter">GeSHi</abbr> 1.0.7.21 itself had some bugs in Symbol highlighting that could cause
+  heavily scrambled code output.</p>
+
+</div>
+
+<p>The following case sensitivity group alludes to the keywords section: here you can set which keyword groups are case sensitive.</p>
+
+<p>In the <strong>&#8216;CASE_SENSITIVE&#8217;</strong> group there&#8217;s a special key <code>GESHI_COMMENTS</code> which is used to set whether comments are
+case sensitive or not (for example, BASIC has the REM statement which while not being case sensitive is still alphanumeric, and
+as in the example given before about the Java language file using &#8220;import&#8221; as a single line comment, this can be
+useful sometimes. <strong>true</strong> if comments are case sensitive, <strong>false</strong> otherwise. All of the other indices
+correspond to indices in the <code>'KEYWORDS'</code> section (see above).</p>
+
+<h4 id="language-file-styles">4.3.5 Styles for your Language File</h4><div class="nav"><a href="#language-file-symbols-case">Previous</a> | <a href="#language-file-sections">Top</a> | <a href="#language-file-urls">Next</a></div>
+
+<p>This is the fun part! Here you get to choose the colours, fonts, backgrounds and anything else you&#8217;d like for your
+language file.</p>
+
+<p>Here&#8217;s an example:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+<span class="xtra li2"><span class="de2">8</span></span>9
+<span class="xtra li2"><span class="de2">10</span></span>11
+<span class="xtra li2"><span class="de2">12</span></span>13
+<span class="xtra li2"><span class="de2">14</span></span>15
+<span class="xtra li2"><span class="de2">16</span></span>17
+<span class="xtra li2"><span class="de2">18</span></span>19
+<span class="xtra li2"><span class="de2">20</span></span>21
+<span class="xtra li2"><span class="de2">22</span></span>23
+<span class="xtra li2"><span class="de2">24</span></span>25
+<span class="xtra li2"><span class="de2">26</span></span>27
+<span class="xtra li2"><span class="de2">28</span></span>29
+<span class="xtra li2"><span class="de2">30</span></span>31
+<span class="xtra li2"><span class="de2">32</span></span>33
+<span class="xtra li2"><span class="de2">34</span></span>35
+<span class="xtra li2"><span class="de2">36</span></span>37
+<span class="xtra li2"><span class="de2">38</span></span>39
+</pre></td><td class="de1"><pre class="de1"><span class="st_h">'STYLES'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="st_h">'KEYWORDS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #b1b100;'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #000000; font-weight: bold;'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">3</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #000066;'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="st_h">'COMMENTS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #808080; font-style: italic;'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #808080; font-style: italic;'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'MULTI'</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #808080; font-style: italic;'</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="st_h">'ESCAPE_CHAR'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #000099; font-weight: bold;'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="st_h">'BRACKETS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #66cc66;'</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="st_h">'STRINGS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #ff0000;'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="st_h">'NUMBERS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #cc66cc;'</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="st_h">'METHODS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #006600;'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="st_h">'SYMBOLS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #66cc66;'</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="st_h">'REGEXPS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="st_h">'color: #0000ff;'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="st_h">'SCRIPT'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">3</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span></span></span>&nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></pre></td></tr></tbody></table>
+
+<p>Note that all style rules should end with a semi-colon! This is important: <abbr title="Generic Syntax Highlighter">GeSHi</abbr> may add extra rules to the rules you
+specify (and will do so if a user tries to change your styles on the fly), so the last semi-colon in any stylesheet
+rule is important!</p>
+
+<p>All strings here should contain valid stylesheet declarations (it&#8217;s also fine to have the empty string).</p>
+
+<ul>
+<li><strong>&#8216;KEYWORDS&#8217;:</strong> This is an array, from keyword index to style. The index you use is the index you used in
+the keywords section to specify the keywords belonging to that group.</li>
+<li><strong>&#8216;COMMENTS&#8217;:</strong> This is an array, from single-line comment index to style for that index. The index &#8216;MULTI&#8217; is
+used for multiline comments (and cannot be an array). COMMENT_REGEXP use the style given for their key as
+if they were single-line comments.</li>
+<li><strong>&#8216;ESCAPE_CHAR&#8217;, &#8216;BRACKETS&#8217; and &#8216;METHODS&#8217;:</strong> These are arrays with only one index: 0. You cannot add other indices to
+these arrays.</li>
+<li><strong>&#8216;STRINGS&#8217;:</strong> This defines the various styles for the Quotemarks you defined earlier. If you don&#8217;t use
+multiple styles for strings there&#8217;s only one index: 0. Please also add this index in case no strings are present.</li>
+<li><strong>&#8216;NUMBERS&#8217;:</strong> This sets the styles used to highlight numbers. The format used here depends on the format used to
+set the formats of numbers to highlight. If you just used an integer (bitmask) for numbers, you have to either
+specify one key with the respective constant, and\or include a key 0 as a default style. If you used an
+array for the number markup, copy the keys used there and assign the styles accordingly.</li>
+<li><strong>&#8216;SYMBOLS&#8217;:</strong> This provides one key for each symbol group you defined above. If you used the flat usage
+make sure you include a key for symbols group 0.</li>
+<li><strong>&#8216;REGEXPS&#8217;:</strong> This is an array with a style for each matching regex. Also, since 1.0.7.21, you can specify the
+name of a function to be called, that will be given the text matched by the regex, each time a match is found.
+Note that my testing found that <code>create_function</code> would not work with this due to a <abbr title="PHP: HTML Preprocessor">PHP</abbr> bug, so you have to
+put the function definition at the top of the language file. Be sure to prefix the function name
+with <code>geshi_[languagename]_</code> as to not conflict with other functions!</li>
+<li><strong>&#8216;SCRIPT&#8217;:</strong> For languages that use script delimiters, this is where you can style each block of script. For
+example, <abbr title="Hypertext Markup Language">HTML</abbr> and <abbr title="Extensible Markup Language">XML</abbr> have blocks that begin with &lt; and end with > (i.e. tags) and blocks that begin with &amp; and
+end with&#160;; (i.e. character entities), and you can set a style to apply to each whole block. You specify the
+delimiters for the blocks below. Note that many languages will not need this feature.</li>
+</ul>
+
+<h4 id="language-file-urls">4.3.6 URLs for Functions</h4><div class="nav"><a href="#language-file-styles">Previous</a> | <a href="#language-file-sections">Top</a> | <a href="#language-file-numbers-support">Next</a></div>
+
+<p>This section lets you specify a url to visit for each keyword group. Useful for pointing functions at their online
+manual entries.</p>
+
+<p>Here is an example:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span></pre></td><td class="de1"><pre class="de1"><span class="st_h">'URLS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="nu0">3</span> <span class="sy0">=&gt;</span> <span class="st_h">'http://www.php.net/{FNAME}'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="nu0">4</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span></pre></td></tr></tbody></table>
+
+<p>The indices of this array correspond to the keyword groups you specified in the keywords section. The string <code>{FNAME}</code>
+marks where the name of the function is substituted in. So for the example above, if the keyword being highlighted is
+&#8220;echo&#8221;, then the keyword will be a URL pointing to <code>http://www.php.net/echo</code>. Because some languages (Java!) don&#8217;t
+keep a uniform URL for functions/classes, you may have trouble in creating a URL for that language (though look in the
+java language file for a novel solution to it&#8217;s problem)</p>
+
+<h4 id="language-file-numbers-support">4.3.7 Number Highlighting Support</h4><div class="nav"><a href="#language-file-urls">Previous</a> | <a href="#language-file-sections">Top</a> | <a href="#language-file-oo-support">Next</a></div>
+
+<p>If your language supports different formats of numbers (e.g. integers and float representations) and you want
+<abbr title="Generic Syntax Highlighter">GeSHi</abbr> to handle them differently you can select from a set of predefined formats.</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span></pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="st_h">'NUMBERS'</span> <span class="sy0">=&gt;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; GESHI_NUMBER_INT_BASIC <span class="sy0">|</span> GESHI_NUMBER_INT_CSTYLE <span class="sy0">|</span> GESHI_NUMBER_BIN_PREFIX_0B <span class="sy0">|</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; GESHI_NUMBER_OCT_PREFIX <span class="sy0">|</span> GESHI_NUMBER_HEX_PREFIX <span class="sy0">|</span> GESHI_NUMBER_FLT_NONSCI <span class="sy0">|</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; GESHI_NUMBER_FLT_NONSCI_F <span class="sy0">|</span> GESHI_NUMBER_FLT_SCI_SHORT <span class="sy0">|</span> GESHI_NUMBER_FLT_SCI_ZERO<span class="sy0">,</span></span></span></pre></td></tr></tbody></table>
+
+<p>All the formats you want <abbr title="Generic Syntax Highlighter">GeSHi</abbr> to recognize are selected via a bitmask that is built by bitwise OR-ing the format constants.
+When styling you use these constants to assign the proper styles. A style not assigned will automatically fallback to style group 0.</p>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>For a complete list of formats supported by <abbr title="Generic Syntax Highlighter">GeSHi</abbr> have a look into the sources of geshi.php.</p>
+
+</div>
+
+<p>If you want to define your own formats for numbers or when you want to group the style for two or more formats you can use the array syntax.</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="st_h">'NUMBERS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> GESHI_NUMBER_INT_BASIC <span class="sy0">|</span> GESHI_NUMBER_INT_CSTYLE<span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> GESHI_NUMBER_BIN_PREFIX_0B<span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">3</span> <span class="sy0">=&gt;</span> GESHI_NUMBER_OCT_PREFIX<span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">4</span> <span class="sy0">=&gt;</span> GESHI_NUMBER_HEX_PREFIX<span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">5</span> <span class="sy0">=&gt;</span> GESHI_NUMBER_FLT_NONSCI <span class="sy0">|</span> GESHI_NUMBER_FLT_NONSCI_F <span class="sy0">|</span> GESHI_NUMBER_FLT_SCI_SHORT <span class="sy0">|</span> GESHI_NUMBER_FLT_SCI_ZERO</span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></pre></td></tr></tbody></table>
+
+<p>This creates 5 style groups 1..5 that will highlight each of the formats specified for each group.
+Styling of these groups doesn&#8217;t use the constants but uses the indices you just defined.</p>
+
+<p>Instead of using those predefined constants you also can assign a PCRE that matches a number when using this advanced format.</p>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>The extended format hasn&#8217;t been exhaustively been tested. So beware of bugs there.</p>
+
+</div>
+
+<h4 id="language-file-oo-support">4.3.8 Object Orientation Support</h4><div class="nav"><a href="#language-file-numbers-support">Previous</a> | <a href="#language-file-sections">Top</a> | <a href="#language-file-regexps">Next</a></div>
+
+<p>Now we&#8217;re reaching the most little-used section of a language file, which includes such goodies as object orientation
+support and context support. <abbr title="Generic Syntax Highlighter">GeSHi</abbr> can highlight methods and data fields of objects easily, all you need to do is to
+tell it to do so and what the &#8220;splitter&#8221; is between object/method etc.</p>
+
+<p>Here&#8217;s an example:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span></pre></td><td class="de1"><pre class="de1"><span class="st_h">'OOLANG'</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2"><span class="st_h">'OBJECT_SPLITTER'</span> <span class="sy0">=&gt;</span> <span class="st_h">'-&amp;gt;'</span><span class="sy0">,</span></span></span></pre></td></tr></tbody></table>
+
+<p>If your language has object orientation, the value of <code>'OOLANG'</code> is true, otherwise it is false. If it is object
+orientated, in the <code>'OBJECT_SPLITTER'</code> value you put the <code>htmlentities()</code> version of the &#8220;splitter&#8221; between
+objects and methods/fields. If it is not, then make this the empty string.</p>
+
+<h4 id="language-file-regexps">4.3.9 Using Regular Expressions</h4><div class="nav"><a href="#language-file-oo-support">Previous</a> | <a href="#language-file-sections">Top</a> | <a href="#language-file-strict-mode">Next</a></div>
+
+<p>Regular expressions are a good way to catch any other lexic that fits certain rules but can&#8217;t be listed as a keyword.
+A good example is variables in <abbr title="PHP: HTML Preprocessor">PHP</abbr>: variables always start with either one or two &#8220;$&#8221; signs, then alphanumeric
+characters (a simplification). This is easy to catch with regular expressions.</p>
+
+<p>And new to version 1.0.2, there is an advanced way of using regular expressions to catch certain things but highlight
+only part of those things. This is particularly useful for languages like <abbr title="Extensible Markup Language">XML</abbr>.</p>
+
+<div class="caution">
+
+<div class="caution-header">Caution:</div>
+
+<p>Regular expressions use the PCRE syntax (perl-style), <em>not</em> the <code class="highlighted php"><span class="kw3">ereg</span><span class="br0">&#40;</span><span class="br0">&#41;</span></code> style!</p>
+
+</div>
+
+<p>Here is an example (this time the <abbr title="PHP: HTML Preprocessor">PHP</abbr> file merged with the <abbr title="Extensible Markup Language">XML</abbr> file):</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+<span class="xtra li2"><span class="de2">8</span></span>9
+<span class="xtra li2"><span class="de2">10</span></span>11
+<span class="xtra li2"><span class="de2">12</span></span>13
+<span class="xtra li2"><span class="de2">14</span></span>15
+</pre></td><td class="de1"><pre class="de1"><span class="nu0">0</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; GESHI_SEARCH <span class="sy0">=&gt;</span> <span class="st_h">'(((xml:)?[a-z\-]+))(=)'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; GESHI_REPLACE <span class="sy0">=&gt;</span> <span class="st_h">'\\1'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; GESHI_MODIFIERS <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; GESHI_BEFORE <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; GESHI_AFTER <span class="sy0">=&gt;</span> <span class="st_h">'\\4'</span></span></span>&nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2"><span class="nu0">1</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; GESHI_SEARCH <span class="sy0">=&gt;</span> <span class="st_h">'(&gt;/?[a-z0-9]*(&gt;)?)'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; GESHI_REPLACE <span class="sy0">=&gt;</span> <span class="st_h">'\\1'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; GESHI_MODIFIERS <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; GESHI_BEFORE <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; GESHI_AFTER <span class="sy0">=&gt;</span> <span class="st_h">''</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span><span class="nu0">2</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;[<span class="es1">\\</span>$]{1,2}[a-zA-Z_][a-zA-Z0-9_]*&quot;</span></pre></td></tr></tbody></table>
+
+<p>As you can see there are two formats. One is the &#8220;simple&#8221; format used in <abbr title="Generic Syntax Highlighter">GeSHi</abbr> &lt; 1.0.2, and the other is a more
+advanced syntax. Firstly, the simple syntax:</p>
+
+<ul>
+<li><strong>May be in double quotes:</strong> To make it easier for those who always place their regular expressions in double quotes,
+you may place any regular expression here in double quotes if you wish.</li>
+<li><strong>Don&#8217;t use curly brackets where possible:</strong> If you want to use curly brackets (<code>()</code>) then by all means give it a try,
+but I&#8217;m not sure whether under some circumstances <abbr title="Generic Syntax Highlighter">GeSHi</abbr> may throw a wobbly. You have been warned! If you want to
+use brackets, it would be better to use the advanced syntax.</li>
+<li><strong>Don&#8217;t use the &#8220;everything&#8221; regex:</strong> (That&#8217;s the <code>.*?</code> regex). Use advanced syntax instead.</li>
+</ul>
+
+<p>And now for advanced syntax, which gives you much more control over exactly what is highlighted:</p>
+
+<ul>
+<li><strong>GESHI_SEARCH:</strong> This element specifies the regular expression to search for. If you plan to capture the output,
+use brackets (<code>()</code>). See how in the first example above, most of the regular expression is in one set of brackets
+(with the equals sign in other brackets). You should make sure that the part of the regular expression that is
+supposed to match what is highlighted is in brackets.</li>
+<li><strong>GESHI_REPLACE:</strong> This is what the stuff matched by the regular expression will be replaced with. If you&#8217;ve
+grouped the stuff you want highlighted into brackets in the GESHI_SEARCH element, then you can use <code>\\number</code>
+to match that group, where <code>number</code> is a number corresponding to how many open brackets are between the open
+bracket of the group you want highlighted and the start of the GESHI_SEARCH string + 1. This may sound confusing,
+and it probably is, but if you&#8217;re familiar with how <abbr title="PHP: HTML Preprocessor">PHP</abbr>&#8217;s regular expressions work you should understand. In the
+example above, the opening bracket for the stuff we want highlighted is the very first bracket in the string, so
+the number of brackets before that bracket and the start of the string is 0. So we add 1 and get our replacement
+string of <code>\\1</code> <small>(whew!)</small>.</li>
+</ul>
+
+<p>If you didn&#8217;t understand a word of that, make sure that there are brackets around the string in <code>GESHI_SEARCH</code>
+and use <code>\\1</code> for <code>GESHI_REPLACE</code> ;)</p>
+
+<ul>
+<li><strong>GESHI_MODIFIERS:</strong> Specify modifiers for your regular expression. If your regular expression includes the
+everything matcher (<code>.*?</code>), then your modifiers should include &#8220;s&#8221; and &#8220;i&#8221; (e.g. use &#8216;si&#8217; for this).</li>
+<li><strong>GESHI_BEFORE:</strong>Specifies a bracket group that should appear before the highlighted match (this bracketed group will
+not be highlighted). Use this if you had to match what you wanted by matching part of your regexp string to something
+before what you wanted to highlight, and you don&#8217;t want that part to disappear in the highlighted result.</li>
+<li><strong>GESHI_AFTER:</strong>Specifies a bracket group that should appear after the highlighted match (this bracketed group will
+not be highlighted). Use this if you had to match what you wanted by matching part of your regexp string to something
+after what you wanted to highlight, and you don&#8217;t want that part to disappear in the highlighted result.</li>
+</ul>
+
+<p>Is that totally confusing? Here&#8217;s the test for if you&#8217;re an android or not: If you found that perfectly understandable
+then you&#8217;re an android ;). Here&#8217;s a better example:</p>
+
+<p>Let&#8217;s say that I&#8217;m making a language, and variables in this language always start with a dollar sign ($), are always
+written in lowercase letters and always end with an ampersand (&amp;). eg:</p>
+
+<p><code class="highlighted php"><span class="re0">$foo</span><span class="sy0">&amp;</span> <span class="sy0">=</span> <span class="st_h">'bar'</span></code></p>
+
+<p>I want to highlight <em>only the text between the $ and the &amp;</em>. How do I do that? With simple regular expressions I can&#8217;t,
+but with advanced, it&#8217;s relatively easy:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+<span class="xtra li2"><span class="de2">8</span></span>9
+<span class="xtra li2"><span class="de2">10</span></span>11
+<span class="xtra li2"><span class="de2">12</span></span>13
+<span class="xtra li2"><span class="de2">14</span></span></pre></td><td class="de1"><pre class="de1"><span class="nu0">1</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="co1">// search for a dollar sign, then one or more of the characters a-z, then an ampersand</span></span></span>&nbsp; &nbsp; GESHI_SEARCH <span class="sy0">=&gt;</span> <span class="st_h">'(\$)([a-z]+)(&amp;)'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="co1">// we wanna highlight the characters, which are in the second bracketed group</span></span></span>&nbsp; &nbsp; GESHI_REPLACE <span class="sy0">=&gt;</span> <span class="st_h">'\\2'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="co1">// no modifiers, since we're not matching the &quot;anything&quot; regex</span></span></span>&nbsp; &nbsp; GESHI_MODIFIERS <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="co1">// before the highlighted characters should be the first</span></span></span>&nbsp; &nbsp; <span class="co1">// bracketed group (always a dollar sign in this example)</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; GESHI_BEFORE <span class="sy0">=&gt;</span> <span class="st_h">'\\1'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="co1">// after the highlighted characters should be the third</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="co1">// bracketed group (always an ampersand in this example)</span></span></span>&nbsp; &nbsp; GESHI_AFTER <span class="sy0">=&gt;</span> <span class="st_h">'\\3'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span></pre></td></tr></tbody></table>
+
+<p>So if someone tried to highlight using my language, all cases of <code>$foo&amp;</code> would turn into:</p>
+
+<p><code class="highlighted html4strict">$<span class="sc2">&lt;<span class="kw2">span</span> <span class="kw3">style</span><span class="sy0">=</span><span class="st0">&quot;color: blue;&quot;</span>&gt;</span>foo<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">span</span>&gt;&lt;<span class="kw2">span</span> <span class="kw3">style</span><span class="sy0">=</span><span class="st0">&quot;color: green;&quot;</span>&gt;</span><span class="sc1">&amp;amp;</span><span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">span</span>&gt;</span></code></p>
+
+<p>(which would of course be viewed in a browser to get something like <code class="highlighted php"><span class="re0">$foo</span><span class="sy0">&amp;</span></code>)</p>
+
+<h4 id="language-file-strict-mode">4.3.10 Contextual Highlighting and Strict Mode</h4><div class="nav"><a href="#language-file-regexps">Previous</a> | <a href="#language-file-sections">Top</a> | <a href="#language-file-parser-control">Next</a></div>
+
+<p>For languages like <abbr title="Hypertext Markup Language">HTML</abbr>, it&#8217;s good if we can highlight a tag (like <code class="highlighted html4strict"><span class="sc2">&lt;<span class="kw2">a</span>&gt;</span></code> for example). But how do we stop
+every single &#8220;a&#8221; in the source getting highlighted? What about for attributes? If I&#8217;ve got the word &#8220;colspan&#8221; in my
+text I don&#8217;t want that highlighted! So how do you tell <abbr title="Generic Syntax Highlighter">GeSHi</abbr> not to highlight in that case? You do it with &#8220;Strict Blocks&#8221;.</p>
+
+<p>Here is an example:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+<span class="xtra li2"><span class="de2">8</span></span>9
+<span class="xtra li2"><span class="de2">10</span></span>11
+<span class="xtra li2"><span class="de2">12</span></span>13
+<span class="xtra li2"><span class="de2">14</span></span>15
+<span class="xtra li2"><span class="de2">16</span></span>17
+<span class="xtra li2"><span class="de2">18</span></span>19
+<span class="xtra li2"><span class="de2">20</span></span>21
+<span class="xtra li2"><span class="de2">22</span></span>23
+<span class="xtra li2"><span class="de2">24</span></span>25
+<span class="xtra li2"><span class="de2">26</span></span>27
+</pre></td><td class="de1"><pre class="de1"><span class="sy1">&lt;?</span> <span class="coMULTI">/* ... */</span>
+<span class="xtra li2"><span class="de2"><span class="st_h">'STRICT_MODE_APPLIES'</span> <span class="sy0">=&gt;</span> GESHI_MAYBE<span class="sy0">,</span></span></span><span class="st_h">'SCRIPT_DELIMITERS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'&lt;?php'</span> <span class="sy0">=&gt;</span> <span class="st_h">'?&gt;'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'&lt;?'</span> <span class="sy0">=&gt;</span> <span class="st_h">'?&gt;'</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'&lt;%'</span> <span class="sy0">=&gt;</span> <span class="st_h">'%&gt;'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="nu0">3</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'&lt;script language=&quot;php&quot;&gt;'</span> <span class="sy0">=&gt;</span> <span class="st_h">'&lt;/script&gt;'</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="nu0">4</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;/(&lt;\?(?:php)?)(?:'(?:[^'<span class="es1">\\</span><span class="es1">\\</span>]|<span class="es1">\\</span><span class="es1">\\</span>.)*?'|<span class="es1">\&quot;</span>(?:[^<span class="es1">\&quot;</span><span class="es1">\\</span><span class="es1">\\</span>]|<span class="es1">\\</span><span class="es1">\\</span>.)*?<span class="es1">\&quot;</span>|\/\*(?!\*\/).*?\*\/|.)*?(\?&gt;|\Z)/sm&quot;</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="nu0">5</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;/(&lt;%)(?:'(?:[^'<span class="es1">\\</span><span class="es1">\\</span>]|<span class="es1">\\</span><span class="es1">\\</span>.)*?'|<span class="es1">\&quot;</span>(?:[^<span class="es1">\&quot;</span><span class="es1">\\</span><span class="es1">\\</span>]|<span class="es1">\\</span><span class="es1">\\</span>.)*?<span class="es1">\&quot;</span>|\/\*(?!\*\/).*?\*\/|.)*?(%&gt;|\Z)/sm&quot;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></span></span><span class="st_h">'HIGHLIGHT_STRICT_BLOCK'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="nu0">0</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="nu0">1</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="nu0">3</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="nu0">4</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; <span class="nu0">5</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="br0">&#41;</span></span></span><span class="coMULTI">/* ... */</span> <span class="sy1">?&gt;</span></pre></td></tr></tbody></table>
+
+<p>What is strict mode? Strict mode says that highlighting only occurs inside the blocks you specify. You can see from
+the example above that highlighting will only occur if the source is inside <code class="highlighted php"><span class="kw2">&lt;?php</span> <span class="sy0">...</span> <span class="sy1">?&gt;</span></code> (though note the
+<code>GESHI_MAYBE</code>!). Here are some points about strict highlighting:</p>
+
+<ul>
+<li><strong>&#8216;STRICT_MODE_APPLIES&#8217;:</strong> This takes three values (all constants):
+
+<ul>
+<li><code>GESHI_ALWAYS</code>: Strict mode always applies for all of the blocks you specify. Users of your language
+file cannot turn strict mode off. This should be used for markup languages.</li>
+<li><code>GESHI_NEVER</code>: Strict mode is never used. Users of your language file cannot turn strict mode on. Use this
+value if there is no such thing as a block of code that would not be highlighted in your language
+(most languages, like C, Java etc. use this because anything in a C file should be highlighted).</li>
+<li><code>GESHI_MAYBE</code>: Strict mode &#42;sometimes&#42; applies. It defaults to &#8220;off&#8221;. Users can turn strict mode on if
+they please. If strict mode is off then everything in the source will be highlighted, even things outside
+the strict block markers. If strict mode is on the nothing outside strict block markers will be highlighted.</li>
+</ul></li>
+<li><strong>&#8216;SCRIPT_DELIMITERS&#8217;:</strong> This is an array of script delimiters, in the format of the above. The indices are use in the
+&#8216;SCRIPT&#8217; part of the styles section for highlighting everything in a strict block in a certain way.
+For example, you could set up your language file to make the background yellow of any code inside a strict
+block this way. The delimiters are in the form <code class="highlighted php"><span class="st_h">'OPEN'</span> <span class="sy0">=&gt;</span> <span class="st_h">'CLOSE'</span></code>. Delimiters can be of any
+length > 0. Delimiters are <em>not</em> formatted as if they were run through <code class="highlighted php"><span class="kw3">htmlentities</span><span class="br0">&#40;</span><span class="br0">&#41;</span></code>!</li>
+<li><strong>&#8216;HIGHLIGHT_STRICT_BLOCK&#8217;:</strong> specifies whether any highlighting should go on inside each block. Most of
+the time this should be true, but for example, in the <abbr title="Extensible Markup Language">XML</abbr> language file highlighting is turned off for
+blocks beginning with <code class="highlighted html4strict"><span class="sc0">&lt;!DOCTYPE</span></code> and ending with <code class="highlighted html4strict">&gt;</code>. However, you can still
+style the overall block using the method described above, and the <abbr title="Extensible Markup Language">XML</abbr> language file does just that.</li>
+</ul>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>The delimiters should be in <em>reverse alphabetical order</em>. Note that in the above example, <code class="highlighted php"><span class="kw2">&lt;?php</span></code>
+  comes before <code class="highlighted php"><span class="sy1">&lt;?</span></code>.</p>
+
+</div>
+
+<p>Since <abbr title="Generic Syntax Highlighter">GeSHi</abbr> 1.0.8 instead of specifying an array with starter and ender you may also provide a regular expression
+that matches <em>the full block</em> you wish to highlight. If the regular expression match starts at the same position
+as a previous array declaration the Regexp match is taken. This is to allow for a fall-back when a preg_match
+doesn&#8217;t quite work as expected so you still get reasonably well results.</p>
+
+<p>If you didn&#8217;t get this, you might want to look into the <abbr title="PHP: HTML Preprocessor">PHP</abbr> or <abbr title="Hypertext Markup Language">HTML</abbr> language files as this feature is used there
+to fix some issues that have been there for about 3 years.</p>
+
+<div class="caution">
+
+<div class="caution-header">Caution:</div>
+
+<p>For <abbr title="PHP: HTML Preprocessor">PHP</abbr> versions &lt;4.3.3 Strict Block Regexps are completely ignored due to problems in those version
+  that would cause loads of warning messages otherwise.</p>
+
+</div>
+
+<h4 id="language-file-parser-control">4.3.11 Special Parser Settings (Experimental)</h4><div class="nav"><a href="#language-file-strict-mode">Previous</a> | <a href="#language-file-sections">Top</a> | <a href="#language-file-tidying-up">Next</a></div>
+
+<p>Sometimes it is necessary for a language to render correctly to tweak some of the assumptions <abbr title="Generic Syntax Highlighter">GeSHi</abbr> usually makes to match the behaviour your language expects.
+To achieve this there is an experimental section called <code class="highlighted php"><span class="st_h">'PARSER_CONTROL'</span></code> which is optional and should be used only if necessary.
+With the help of this section some internal parameters of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> can be set which are not overrideable by the API and thus their use should be limited as much as possible.</p>
+
+<p>The syntax of the <strong>PARSER_CONTROL</strong> basically resembles an array structure simular to the one found in the rest of the language file. All subsections of the <strong>PARSER_CONTROL</strong> are optional.
+If a given setting isn&#8217;t present the usual default values of <abbr title="Generic Syntax Highlighter">GeSHi</abbr> are used.
+No validation of settings is performed for these settings. Also note that unknown settings are silently ignored.</p>
+
+<div class="caution">
+
+<div class="caution-header">Caution:</div>
+
+<p>All <strong>PARSER_CONTROL</strong> settings are experimental and subject to change.
+  So if you need a special setting in a public language file you should consider requesting it upstream.
+  This is also the reason why documentation on these settings will only cover broad usage information as the underlying implementation might change without further notice.</p>
+
+</div>
+
+<p>One of the most common reasons why you might want to use the <strong>PARSER_CONTROL</strong> settings is to tweak what characters are allowed to surround a keyword.
+Usually <abbr title="Generic Syntax Highlighter">GeSHi</abbr> checks for a fixed set of characters like brackets and common symbols that denote the word boundary for a keyword.
+If this set conflicts with your language (e.g. - is allowed inside a keyword) or you want to limit the usage of a keyword to certain areas (e.g. for <abbr title="Hypertext Markup Language">HTML</abbr> tag names only match after &lt;) you can change those conditions here.</p>
+
+<p>Keyword boundary rules can either be set globally (directly within the PARSER_CONTROL&#8217;s KEYWORDS section or on a per-group basis.
+E.g. the following sample from the <abbr title="Hypertext Markup Language">HTML</abbr> language file sets different settings for keyword matching only for Keyword Group 2 and leaves the other groups alone.</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+<span class="xtra li2"><span class="de2">8</span></span></pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="st_h">'PARSER_CONTROL'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'KEYWORDS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">2</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'DISALLOWED_BEFORE'</span> <span class="sy0">=&gt;</span> <span class="st_h">'(?&lt;=&amp;lt;|&amp;lt;\/)'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'DISALLOWED_AFTER'</span> <span class="sy0">=&gt;</span> <span class="st_h">'(?=\s|\/|&amp;gt;)'</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="br0">&#41;</span></span></span></pre></td></tr></tbody></table>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>The name <code class="highlighted php"><span class="st_h">'DISALLOWED_BEFORE'</span></code> and <code class="highlighted php"><span class="st_h">'DISALLOWED_AFTER'</span></code> might sound confusing at first, since they don&#8217;t define what to prevent, but what to match in order to find a keyword.
+  The reason for this strange naming is based in the original implementation of this feature when Nigel implemented this in the old parser statically.
+  When this implementation was brought out via the <strong>PARSER_CONTROL</strong> settings the original naming wasn&#8217;t altered since at that time this really was a blacklist of characters.
+  Later on this implementation was changed from a blacklist of characters to a part of a PCRE regexp, but leaving the name.
+  The naming might be subject to change though.</p>
+
+</div>
+
+<p>Another option you can change since <abbr title="Generic Syntax Highlighter">GeSHi</abbr> 1.0.8.3 is whether to treat spaces within keywords as literals (only a single space as given) or if the space should match any whitespace at that location.
+The following code will enable this behaviour for the whole keyword set. As said above you can choose to enable this for single keyword groups only though.</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="st_h">'PARSER_CONTROL'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'KEYWORDS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'SPACE_AS_WHITESPACE'</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span></span></span>&nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">,</span></pre></td></tr></tbody></table>
+
+<p>Another option of interest might be disabling certain features for a given language.
+This might come in handy if the language file you are working on doesn&#8217;t support a given function or highlighting certain aspects won&#8217;t work properly or would interfere with custom implementations using regular expressions.</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+<span class="xtra li2"><span class="de2">8</span></span>9
+<span class="xtra li2"><span class="de2">10</span></span>11
+<span class="xtra li2"><span class="de2">12</span></span></pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="st_h">'PARSER_CONTROL'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ENABLE_FLAGS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ALL'</span> <span class="sy0">=&gt;</span> GESHI_NEVER<span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'NUMBERS'</span> <span class="sy0">=&gt;</span> GESHI_NEVER<span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'METHODS'</span> <span class="sy0">=&gt;</span> GESHI_NEVER<span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'SCRIPT'</span> <span class="sy0">=&gt;</span> GESHI_NEVER<span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'SYMBOLS'</span> <span class="sy0">=&gt;</span> GESHI_NEVER<span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'ESCAPE_CHAR'</span> <span class="sy0">=&gt;</span> GESHI_NEVER<span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'BRACKETS'</span> <span class="sy0">=&gt;</span> GESHI_NEVER<span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'STRINGS'</span> <span class="sy0">=&gt;</span> GESHI_NEVER<span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; <span class="br0">&#41;</span></span></span></pre></td></tr></tbody></table>
+
+<p>Inside the <code class="highlighted php"><span class="st_h">'ENABLE_FLAGS'</span></code> section follows an array of <code class="highlighted php"><span class="st_h">'name'</span><span class="sy0">=&gt;</span>value</code> pairs.
+Valid names are the sections below the <code class="highlighted php"><span class="st_h">'STYLES'</span></code> section (well, not exactly, but you can look there for what the features are called inside <abbr title="Generic Syntax Highlighter">GeSHi</abbr>).
+Valid values are the <abbr title="Generic Syntax Highlighter">GeSHi</abbr> constants <code class="highlighted php">GESHI_NEVER</code> (don&#8217;t process this feature), <code class="highlighted php">GESHI_ALWAYS</code> (always process this feature, ignore the user) and <code class="highlighted php">GESHI_MAYBE</code> (listen to the user if he want&#8217;s this highlighted).
+The value <code class="highlighted php">GESHI_MAYBE</code> is the default one and thus needs not to be set explicitely.</p>
+
+<p>Another setting available through the <strong>PARSER_CONTROL</strong> settings is the possibility to limit the allowed characters before an single line comment.</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="st_h">'PARSER_CONTROL'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'COMMENTS'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'DISALLOWED_BEFORE'</span> <span class="sy0">=&gt;</span> <span class="st_h">'$'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span></span></span>&nbsp; &nbsp; <span class="br0">&#41;</span></pre></td></tr></tbody></table>
+
+<p>With the current implementation the DISALLOWED_BEFORE COMMENT-specific setting is a list of characters. But this is subject to change.</p>
+
+<div class="note">
+
+<div class="note-header">Note:</div>
+
+<p>There is no <code class="highlighted php"><span class="st_h">'DISALLOWED_AFTER'</span></code> setting with the <code class="highlighted php"><span class="st_h">'COMMENTS'</span></code>-<strong>PARSER_CONTROL</strong>.</p>
+
+</div>
+
+<p>Another <strong>PARSER_CONTROL</strong> setting for the environment around certain syntactic constructs refers to the handling of object-oriented languages.</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+<span class="xtra li2"><span class="de2">4</span></span>5
+<span class="xtra li2"><span class="de2">6</span></span>7
+</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="st_h">'PARSER_CONTROL'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'OOLANG'</span> <span class="sy0">=&gt;</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'MATCH_BEFORE'</span> <span class="sy0">=&gt;</span> <span class="st_h">''</span><span class="sy0">,</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'MATCH_AFTER'</span> <span class="sy0">=&gt;</span> <span class="st_h">'[a-zA-Z_][a-zA-Z0-9_]*'</span><span class="sy0">,</span></span></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st_h">'MATCH_SPACES'</span> <span class="sy0">=&gt;</span> <span class="st_h">'[\s]*'</span>
+<span class="xtra li2"><span class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span></span></span>&nbsp; &nbsp; <span class="br0">&#41;</span></pre></td></tr></tbody></table>
+
+<div class="caution">
+
+<div class="caution-header">Caution:</div>
+
+<p>Please note that the settings discussed in this section are experimental and might be changed, removed or altered in their meaning at any time.</p>
+
+</div>
+
+<h4 id="language-file-tidying-up">4.3.12 Tidying Up</h4><div class="nav"><a href="#language-file-parser-control">Previous</a> | <a href="#language-file-sections">Top</a> | <a href="#lang-validation">Next</a></div>
+
+<p>All language files should end with:</p>
+
+<table class="php geshicode" style="font-family:monospace;"><thead><tr><td colspan="2"  class="head">PHP code</td></tr></thead><tbody><tr class="li1"><td class="ln"><pre class="de1">1
+<span class="xtra li2"><span class="de2">2</span></span>3
+</pre></td><td class="de1"><pre class="de1"><span class="br0">&#41;</span><span class="sy0">;</span>
+<span class="xtra li2"><span class="de2">&nbsp;</span></span><span class="sy1">?&gt;</span></pre></td></tr></tbody></table>
+
+<p>That is the string content <code class="highlighted php"><span class="st0">&quot;<span class="es1">\n</span>);<span class="es1">\n</span>?&gt;<span class="es1">\n</span>&quot;</span></code>.</p>
+
+<div class="caution">
+
+<div class="caution-header">Caution:</div>
+
+<p>Make sure that there is EXACTLY one linebreak character at the end. If you accidentially include more
+  you might end up with messages like &#8220;Headers already sent&#8221;.</p>
+
+</div>
+
+<h3 id="lang-validation">4.4 Validating your language file</h3><div class="nav"><a href="#language-file-tidying-up">Previous</a> | <a href="#language-files">Top</a> | <a href="#method-constant-reference">Next</a></div>
+
+<p>Since <abbr title="Generic Syntax Highlighter">GeSHi</abbr> 1.0.8 there is a new script <code>langcheck.php</code> in the contrib directory that scans all
+language files it finds in the geshi/ subdirectory of the <abbr title="Generic Syntax Highlighter">GeSHi</abbr> installation for mistakes.</p>
+
+<p>Please make sure that your language does not contain any mistakes that this script shows you when sending in
+your language file for inclusion into the official release as this saves work for us when including your file.
+Also you can be sure your language file will work as expected once your language file validates correctly.</p>
+
+<p>Please note that not all of the language files shipped with <abbr title="Generic Syntax Highlighter">GeSHi</abbr> are fully valid yet, but we&#8217;re working on it
+and are happy about every patch we get!</p>
+
+<h2 id="method-constant-reference">5 Method/Constant Reference</h2><div class="nav"><a href="#lang-validation">Previous</a></div>
+
+<p>I&#8217;m afraid I have been lying for a little while about this now! Since 1.0.7 I have been including a phpdoc API for
+the sourcecode in the <a href="api/index.html">api</a> directory, but have forgot to update the documentation! However, it is available,
+and may assist you in coding, especially for plugin coders.</p>
+
+<hr />
+
+<p>That&#8217;s all, folks!</p>
+
+<p>I&#8217;ve improved the documentation greatly from version 1.0.1, but there may still be problems with it, or it may still
+be confusing for you. Or perhaps I was just plain wrong about one point! If so, contact me and I&#8217;ll do my best to sort it out.</p>
+
+<p>In case you were wondering, I&#8217;ve finished development of the 1.0.X thread of <abbr title="Generic Syntax Highlighter">GeSHi</abbr>. The only releases I&#8217;ll make in this
+thread will be of the bug-fix/add language files type. In particular, version 1.0.2 was a &#8220;concept&#8221; release - testing
+how far I could take the highlighting idea (as well as ideas from others).</p>
+
+<p>I&#8217;m planning a code rewrite for 1.2.X, which will be based on a new engine - a &#8220;psuedo-tokenizer&#8221; engine. Hopefully
+it will massively reduce the server load and time taken (by almost eliminating regexps), while providing
+superior highlighting. But fear not! The interface and method names should all remain the same ^_^ (though I can&#8217;t
+say the same for language files!)</p>
+
+<p>And finally, a couple of people have been asking me: how did you generate that documentation? The amazing answer is: my
+brain. And yes, it took a long time, and I don&#8217;t recommend doing it this way. And yes, you can borrow the styles if
+you like, though flick me an e-mail if you do.</p>
+
+<p>Anyway, enough blather from me. Get <abbr title="Generic Syntax Highlighter">GeSHi</abbr> working for you already! :D</p>
+
+<div class="header">
+
+<dl>
+<dt>Authors:</dt>
+<dd>&copy; 2004 - 2007&#160;<a href="mailto:nigel@geshi.org">Nigel McNie</a></dd>
+
+<dd>&copy; 2007 - 2008&#160;<a href="mailto:BenBE@omorphia.de">Benny Baumann</a></dd>
+
+<dd>&copy; 2008&#160;<a href="mailto:mail@milianw.de">Milian Wolff</a></dd>
+
+<dt><abbr title="Generic Syntax Highlighter">GeSHi</abbr> Website:</dt>
+<dd><a href="http://qbnz.com/highlighter">http://qbnz.com/highlighter</a></dd>
+</dl>
+
+</div>
+
+<div class="footnotes">
+<hr />
+<ol>
+
+<li id="fn:xhtml-strict">
+<p>The PRE header (see <a href="#the-code-container">The Code Container</a>) is not valid <abbr title="Hypertext Markup Language">HTML</abbr>, you might want
+to use one of the other header types instead.&#160;<a href="#fnref:xhtml-strict" rev="footnote">&#8617;</a></p>
+</li>
+
+<li id="fn:php-version-note">
+<p>Support is granted for <abbr title="PHP: HTML Preprocessor">PHP</abbr> 4.3.0 and above, but especially 4.3.x cannot be guaranteed to
+work due to a lack of test systems. If you are forced to use such old <abbr title="PHP: HTML Preprocessor">PHP</abbr> versions complain at your hoster or
+contact us if you find compatibility issues so we can try to resolve them. It&#8217;s only <abbr title="PHP: HTML Preprocessor">PHP</abbr> 4.4.X and above that
+is verified to work.&#160;<a href="#fnref:php-version-note" rev="footnote">&#8617;</a></p>
+</li>
+
+<li id="fn:phpbb-note">
+<p>I am no longer working on this MOD, however if someone else wants to they can contact me for more
+information.&#160;<a href="#fnref:phpbb-note" rev="footnote">&#8617;</a></p>
+</li>
+
+<li id="fn:plugin-only">
+<p>Available as plugin only. In addition, some of the other entries mentioned
+here may only have <abbr title="Generic Syntax Highlighter">GeSHi</abbr> available as a plugin.&#160;<a href="#fnref:plugin-only" rev="footnote">&#8617;</a></p>
+</li>
+
+</ol>
+</div>
+    </body>
+</html>
\ No newline at end of file
diff --git a/examples/includes/geshi/docs/geshi-doc.txt b/examples/includes/geshi/docs/geshi-doc.txt
new file mode 100644 (file)
index 0000000..4aae137
--- /dev/null
@@ -0,0 +1,1740 @@
+[NOTE: This documentation has simply been copy-pasted from the HTML form and is NOT up to date, I recommend you
+read that instead]
+
+GeSHi Documentation
+Version 1.0.7.22
+
+Author:          Nigel McNie, Benny Baumann
+Copyright:       © 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann
+Email:           nigel@geshi.org, BenBE@omorphia.de
+GeSHi Website:   http://qbnz.com/highlighter
+
+This is the documentation for GeSHi - Generic Syntax Highlighter. The most modern version of this document is available on the web - go to http://qbnz.com/highlighter/documentation.php to view it.
+
+Any comments, questions, confusing points? Please contact me! I need all the information I can get to make the use of GeSHi and everything related to it (including this documentation) a breeze.
+Contents
+
+    * 1. Introduction
+          o 1.1 Features
+          o 1.2 About GeSHi
+          o 1.3 Credits
+          o 1.4 Feedback
+    * 2. The Basics
+          o 2.1 Getting GeSHi
+          o 2.2 Installing GeSHi
+                + 2.2.1 Requirements
+                + 2.2.2 Extracting GeSHi
+                + 2.2.3 Installation
+          o 2.3 Basic Usage
+    * 3. Advanced Features
+          o 3.1 The Code Container
+          o 3.2 Line Numbers
+                + 3.2.1 Enabling Line Numbers
+                + 3.2.2 Styling Line Numbers
+                + 3.2.3 Choosing a Start Number
+          o 3.3 Using CSS Classes
+                + 3.3.1 Enabling CSS Classes
+                + 3.3.2 Setting the CSS Class/ID
+                + 3.3.3 Getting the Stylesheet
+                + 3.3.4 Using an External Stylesheet
+          o 3.4 Changing Styles
+                + 3.4.1 The Overall Styles
+                + 3.4.2 Line Number Styles
+                + 3.4.3 Setting Keyword Styles
+                + 3.4.4 Setting Comment Styles
+                + 3.4.5 Setting Other Styles
+          o 3.5 Case Sensitivity and Auto Casing
+                + 3.5.1 Auto Caps/Nocaps
+                + 3.5.2 Setting Case Sensitivity
+          o 3.6 Changing the Source/Language/Path/Charset
+                + 3.6.1 Changing the Source Code
+                + 3.6.2 Changing the Language
+                + 3.6.3 Changing the Path
+                + 3.6.4 Changing the Character Set
+                + 3.6.5 Using load_from_file to change the language and source code
+          o 3.7 Error Handling
+          o 3.8 Disabling Styling of Some Lexics
+          o 3.9 Setting the Tab Width
+          o 3.10 Using Strict Mode
+          o 3.11 Adding/Removing Keywords
+                + 3.11.1 Adding a Keyword
+                + 3.11.2 Removing a Keyword
+                + 3.11.3 Adding a Keyword Group
+                + 3.11.4 Removing a Keyword Group
+          o 3.12 Headers and Footers for your code
+                + 3.12.1 Keyword Substitution
+                + 3.12.2 Setting Header Content
+                + 3.12.3 Setting Footer Content
+                + 3.12.4 Styling Header Content
+                + 3.12.5 Styling Footer Content
+          o 3.13 Keyword URLs
+                + 3.13.1 Setting a URL for a Keyword Group
+                + 3.13.2 Disabling URLs for a Keyword Group
+                + 3.13.3 Disabling all URLs for Keywords
+                + 3.13.4 Styling Links
+                + 3.13.5 Setting the Link Target
+          o 3.14 Using Contextual Importance
+          o 3.15 Highlighting Special Lines "Extra"
+                + Specifying the Lines to Highlight Extra
+                + Styles for the Highlighted Lines
+          o 3.16 Adding IDs to Each Line
+          o 3.17 Getting the Time of Styling
+    * 4 Language Files
+          o 4.1 An Example Language File
+          o 4.2 Language File Conventions
+          o 4.3 Language File Sections
+                + 4.3.1 The Header
+                + 4.3.2 The First Indices
+                + 4.3.3 Keywords
+                + 4.3.4 Symbols and Case Sensitivity
+                + 4.3.5 Styles for your Language Files
+                + 4.3.6 URLs for Functions
+                + 4.3.7 Object Orientation Support
+                + 4.3.8 Using Regular Expressions
+                + 4.3.9 Contextual Highlighting and Strict Mode
+                + 4.3.10 Tidying Up
+    * 5 Method/Constant Reference
+
+1: Introduction
+Top | Contents | Next | Previous
+
+GeSHi is exactly what the acronym stands for: a Generic Syntax Highlighter. As long as you have a language file for almost any computer language - whether it be a scripting language, object orientated, markup or anything in between - GeSHi can highlight it! GeSHi is extremely customisable - the same source can be highlighted multiple times in multiple ways - the same source even with a different language. GeSHi outputs XHTML strict compliant code*, and can make use of CSS to save on the amount of output. And what is the cost for all of this? You need PHP. That's all!
+
+*Most of the time. Some languages do not output XHTML strict code, and using line numbers with the PRE header is not legal either. These problems will be fixed in 1.2.
+1.1: Features
+Top | Contents | Next | Previous
+
+Here are some of the standout features of GeSHi:
+
+    * Programmed in PHP: GeSHi is coded entirely in PHP. This means that where ever you have PHP, you can have GeSHi! Almost any free webhost supports PHP, and GeSHi works fine with PHP > 4.3.0*.
+    * Support for many languages: GeSHi comes with about 100 languages, including PHP, HTML, CSS, Java, C, Lisp, XML, Perl, Python, ASM and many more!
+    * XHTML compliant output: GeSHi produces XHTML compliant output, using stylesheets, so you need not worry about GeSHi ruining your claims to perfection in the standards department ;)
+    * Highly customisable: GeSHi allows you to change the style of the output on the fly, use CSS classes or not, use an external stylesheet or not, use line numbering, change the case of output keywords... the list goes on and on!
+    * Flexible: Unfortunately, GeSHi is quite load/time intensive for large blocks of code. However, you want speed? Turn off any features you don't like, pre-make a stylesheet and use CSS classes to reduce the amount of output and more - it's easy to strike a balance that suits you.
+
+This is just a taste of what you get with GeSHi - the best syntax highlighter for the web in the world!
+
+*Support is granted for PHP 4.3.0 and above, but especially 4.3.x cannot be guaranteed to work due to a lack of test systems. If you are forced to use such old PHP versions complain at your hoster or contact us if you find compatibility issues so we can try to resolve them. It's only PHP 4.4.X and above that is verified to work.
+1.2: About GeSHi
+Top | Contents | Next | Previous
+
+GeSHi started as a mod for the phpBB forum system, to enable highlighting of more languages than the available (which can be roughly estimated to exactly 0 ;)). However, it quickly spawned into an entire project on its own. But now it has been released, work continues on a mod for phpBB* - and hopefully for many forum systems, blogs and other web-based systems.
+
+*I am no longer working on this MOD, however if someone else wants to they can contact me for more information.
+
+Several systems are using GeSHi now, including:
+
+    * Dokuwiki - An advanced wiki engine
+    * gtk.php.net - Their manual uses GeSHi for syntax highlighting
+    * WordPress - A powerful blogging system*
+    * PHP-Fusion - A constantly evovling CMS
+    * SQL Manager - A Postgres DBAL
+    * Mambo - A popular open source CMS
+    * MediaWiki - A leader in Wikis*
+    * TikiWiki - A megapowerful Wiki/CMS
+    * TikiPro - Another powerful Wiki based on Tikiwiki
+    * RWeb - A site-building tool
+
+* Available as plugin only. In addition, some of the other entries mentioned here may only have GeSHi available as a plugin.
+
+GeSHi is the original work of Nigel McNie. The project was later handed over to Benny Baumann. Others have helped with aspects of GeSHi also, they're mentioned in the THANKS file.
+1.3: Credits
+Top | Contents | Next | Previous
+
+Many people have helped out with GeSHi, whether by creating language files, submitting bug reports, suggesting new ideas or simply pointing out a new idea or something I'd missed. All of these people have helped to build a better GeSHi, you can see them in the THANKS file.
+
+Do you want your name on this list? Why not make a language file, or submit a valid bug? Or perhaps help me with an added feature I can't get my head around, or suggest a new feature, or even port GeSHi to anothe language? There's lots you can do to help out, and I need it all :)
+1.4: Feedback
+Top | Contents | Next | Previous
+
+I need your feedback! ANYthing you have to say is fine, whether it be a query, congratulations, a bug report or complaint, I don't care! I want to make this software the best it can be, and I need your help! You can contact me in the following ways:
+
+    * E-mail: nigel@geshi.org
+    * Forums: Sourceforge.net Forums or GeSHi home forums
+
+Remember, any help I am grateful for :)
+2: The Basics
+Top | Contents | Next | Previous
+
+In this section, you'll learn a bit about GeSHi, how it works and what it uses, how to install it and how to use it to perform basic highlighting.
+2.1: Getting GeSHi
+Top | Contents | Next | Previous
+
+If you're reading this and don't have GeSHi, that's a problem ;). So, how do you get your hands on it? Visit http://qbnz.com/highlighter/downloads.php to obtain the latest version.
+2.2: Installing GeSHi
+Top | Contents | Next | Previous
+
+Installing GeSHi is a snap, even for those most new to PHP. There's no tricks involved. Honest!
+2.2.1: Requirements
+Top | Contents | Next | Previous
+
+GeSHi requires the following to be installable:
+
+    * PHP. It's untested with anything other below 4.4.X. I hope to extend this range soon. I see no reason why it won't work with any version of PHP above 4.3.0.
+    * Approximately 2 megabytes of space. The actual script is small - around 150K - but most of the size comes from the large number of language files (over 100!). If you're pushed for space, make sure you don't upload to your server the docs/ or contrib/ directory, and you may want to leave out any language files that don't take your fancy either.
+
+As you can see, the requirements are very small. If GeSHi does NOT work for you in a particular version of PHP, let me know why and I'll fix it.
+
+Packages come in .zip, .tar.gz and .tar.bz2 format, so there's no complaining about whether it's available for you. *nix users probably want .tar.gz or .tar.bz2 and windows users probably want .zip.
+2.2.2: Extracting GeSHi
+Top | Contents | Next | Previous
+
+To extract GeSHi in Linux (.tar.gz):
+
+   1. Open a shell
+   2. cd to the directory where the archive lies
+   3. Type tar -xzvf [filename] where [filename] is the name of the archive (typically GeSHi-1.X.X.tar.gz)
+   4. GeSHi will be extracted to its own directory
+
+To extract GeSHi in Windows (.zip):
+
+   1. Open Explorer
+   2. Navigate to the directory where the archive lies
+   3. Extract the archive. The method you use will depend on your configuration. Some people can right-click upon the archive and select "Extract" from there, others may have to drag the archive and drop it upon an extraction program.
+
+To extract from .zip you'll need an unzipping program - unzip in Linux, or Winzip, Winrar or similar for Windows.
+2.2.3: Installation
+Top | Contents | Next | Previous
+
+GeSHi is nothing more than a PHP class with related language support files. Those of you familiar with PHP can then guess how easy the installation will be: simply copy it into your include path somewhere. You can put it wherever you like in this include path. I recommend that you put the language files in a subdirectory of your include path too - perhaps the same subdirectory that geshi.php is in. Remember this path for later.
+
+If you don't know what an include path is, don't worry. Simply copy GeSHi to your webserver. So for example, say your site is at http://mysite.com/myfolder, you can copy GeSHi to your site so the directory structure is like this:
+
+http://mysite.com/myfolder/geshi/[language files]
+http://mysite.com/myfolder/geshi.php
+
+Or you can put it in any subdirectory you like:
+
+http://mysite.com/myfolder/includes/geshi/[language files]
+http://mysite.com/myfolder/includes/geshi.php
+
+Caution:
+
+When using GeSHi on a live site, the only directory required is the geshi/ subdirectory. Both contrib/ and docs/ are worthless, and furthermore, as some people discovered, one of the files in contrib had a security hole (fixed as of 1.0.7.3). I suggest you delete these directories from any live site they are on.
+2.3: Basic Usage
+Top | Contents | Next | Previous
+
+Use of GeSHi is very easy. Here's a simple example:
+//
+// Include the GeSHi library
+//
+include_once('geshi.php');
+
+//
+// Define some source to highlight, a language to use
+// and the path to the language files
+//
+$source = '$foo = 45;
+for ( $i = 1; $i < $foo; $i++ )
+{
+  echo "$foo<br />\n";
+  --$foo;
+}';
+$language = 'php';
+//
+// Create a GeSHi object
+//
+$geshi =& new GeSHi($source, $language);
+
+//
+// And echo the result!
+//
+echo $geshi->parse_code();
+
+As you can see, there's only three really important lines:
+include_once('geshi.php');
+
+This line includes the GeSHi class for use
+$geshi = new GeSHi($source, $language);
+
+This line creates a new GeSHi object, holding the source and the language you want to use for highlighting.
+echo $geshi->parse_code();
+
+This line spits out the result :)
+
+So as you can see, simple usage of GeSHi is really easy. Just create a new GeSHi object and get the code!
+
+Since version 1.0.2, there is a function included with GeSHi called geshi_highlight. This behaves exactly as the php function highlight_string behaves - all you do is pass it the language you want to use to highlight and the path to the language files as well as the source. Here are some examples:
+// Simply echo the highlighted code
+geshi_highlight($source, 'php', $path);
+
+// Get the code back, for use later
+$code = geshi_highlight($source, 'java', $path, true)
+
+// Check if there is an error with parsing this code
+ob_start();
+$result = geshi_highlight($source, 'perl', $path);
+$code = ob_get_contents();
+ob_end_clean();
+if ( !$result )
+{
+        // There was an error with highlighting...
+}
+else
+{
+        // All OK :)
+}
+
+However, these are really simple examples and doesn't even begin to cover all the advanced features of GeSHi. If you want to learn more, continue on to section 3: Advanced Features.
+3: Advanced Features
+Top | Contents | Next | Previous
+
+This section documents the advanced features of GeSHi - strict mode, using CSS classes, changing styles on the fly, disabling highlighting of some things and more.
+
+In this section there are many code snippets. For all of these, you should assume that the GeSHi library has been included, and a GeSHi object has been created and is referenced by the variable $geshi. Normally, the source, language and path used are arbitary.
+3.1 The Code Container
+Top | Contents | Next | Previous
+
+The Code Container has a fundamental effect on the layout of your code before you even begin to style. What is the Code Container? It's the bit of markup that goes around your code to contain it. By default your code is surrounded by a <pre>, but you can also specify a <div>.
+
+The <pre> header is the default. If you're familiar with HTML you'll know that whitespace is rendered "as is" by a <pre> element. The advantage for you is that if you use <pre> the whitespace you use will appear pretty much exactly how it is in the source, and what's more GeSHi won't have to add a whole lot of <br />'s and non-breaking spaces (&nbsp;) to your code to indent it. This saves you source code (and your valuable visitors waiting time and your bandwidth).
+
+But if you don't like <pre> or it looks stupid in your browser no matter what styles you try to apply to it or something similar, you might want to use a <div> instead. A <div> will result in more source - GeSHi will have to insert whitespace markup - but in return you can wrap long lines of code that would otherwise have your browser's horizontal scrollbar appear. Of course with <div> you can *not* wrap lines if you please. The highlighter demo at the GeSHi home page uses the <div> approach for this reason.
+
+At this stage there isn't an option to wrap the code in <code> tags (unless you use the function geshi_highlight), partly because of the inconsistent and unexpected ways stuff in <code> tags is highlighted. Besides, <code> is an inline element. But this may become an option in future versions.
+
+As of GeSHi 1.0.7.2 there is a new header type, that specifies that the code should not be wrapped in anything at all.
+
+Another requested addition has been made in GeSHi 1.0.7.20 to force GeSHi to create a block around the highlighted source even if this wasn't necessary, thus styles that are applied to the output of GeSHi can directly influence the code only even if headers and footers are present.
+
+To change/set the header to use, you call the set_header_type() method:
+$geshi->set_header_type(GESHI_HEADER_DIV);
+// or...
+$geshi->set_header_type(GESHI_HEADER_PRE); // or...
+$geshi->set_header_type(GESHI_HEADER_NONE);
+
+Those are the only three arguments you should pass to set_header_type. Passing anything else may cause inconsistencies in what is used as the Code Container (although it *should* simply use a <pre>). Better not to risk it.
+Note:
+
+GESHI_HEADER_DIV, GESHI_HEADER_PRE and GESHI_HEADER_NONE are constants, so don't put them in strings!
+Caution:
+
+The default styles for the <pre> and <div> will be different, especially if you use line numbers!. I have found that a <pre> results in code that is smaller than for that of a <div>, you should rectify this difference by using set_overall_style() if you need to. But be aware of this difference for if you are changing the header type!
+3.2: Line Numbers
+Top | Contents | Next | Previous
+
+GeSHi has the ability to add line numbers to your code (see the demo available at http://qbnz.com/highlighter/demo.php to see what can be achieved). Line numbers are a great way to make your code look professional, especially if you use the fancy line numbers feature.
+3.2.1: Enabling Line Numbers
+Top | Contents | Next | Previous
+
+To highlight a source with line numbers, you call the enable_line_numbers() method:
+$geshi->enable_line_numbers($flag);
+
+Where $flag is one of the following:
+
+    * GESHI_NORMAL_LINE_NUMBERS - Use normal line numbering
+    * GESHI_FANCY_LINE_NUMBERS - Use fancy line numbering
+    * GESHI_NO_LINE_NUMBERS - Disable line numbers (default)
+
+Normal line numbers means you specify a style for them, and that style gets applied to all of them. Fancy line numbers means that you can specify a different style for each nth line number. You change the value of n (default 5):
+$geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS, 37);
+
+The second parameter is not used in any other mode. Setting it to 0 is the same as simply using normal line numbers. Setting it to 1 applies the fancy style to every line number.
+Note:
+
+The values above are CONSTANTS - so don't put them in strings!
+3.2.2 Styling Line Numbers
+Top | Contents | Next | Previous
+
+As of GeSHi 1.0.2, line numbers are added by the use of ordered lists. This solves the old issues of line number styles inheriting from styles meant for the code. Also, this solves an important issue about selecting code. For example, line numbers look nice, but when you go to select the code in your browser to copy it? You got the line numbers too! Not such a good thing, but thankfully this issue is now solved. What is the price? Unfortunately the whole way that styles are inherited/used has changed for those of you who were familiar with 1.0.1, and there is quite a bit more HTML involved. So think carefully about these things before you enable line numbers.
+
+Now, onto how to style line numbers:
+
+Styles are set for line numbers using the set_line_style() method:
+$geshi->set_line_style('background: #fcfcfc;');
+
+If you're using Fancy Line Numbers mode, you pass a second string for the style of the nth line number:
+$geshi->set_line_style('background: #fcfcfc;', 'background: #f0f0f0;');
+
+The second style will have no effect if you're not using Fancy Line Numbers mode.
+
+By default, the styles you pass overwrite the current styles. Add a boolean "true" after the styles you specify to combine them with the current styles:
+$geshi->set_line_style('background: red;', true);
+// or, for fancy line numbers
+$geshi->set_line_style('background: red;', 'background: blue;', true);
+Note:
+
+Due to a bug with Firefox the issue that should have been fixed with 1.0.2 has reappeared in another form as Firefox includes extra text\markup into plaintext versions of webpage copies. This can sometimes be useful (actually it's used to get the plaintext version of this documentation), but more often is quite annoying. Best practice so far is to either not use line numbers, or offer the visitor of your page a plaintext version of your source. To learn more have a look at the SF.net BugTracker Issue #1651996. This will hopefully be fixed in GeSHi version 1.2 or as soon as Firefox provides webdevelopers with adequate ways to control this feature - whichever comes first!
+Caution:
+
+When you set line number styles, the code will inherit those styles! This is the main issue to come out of the 1.0.2 release. If you want your code to be styled in a predictable manner, you'll have to call the set_code_style() method to rectify this problem.
+
+Note also that you cannot apply background colours to line numbers unless you use set_overall_style(). Here's how you'd style:
+
+   1. Use set_overall_style() to style the overall code block. For example, you can set the border style/colour, any margins and padding etc. using this method. In addition: set the background colour for all the line numbers using this method.
+   2. Use set_line_style() to style the foreground of the line numbers. For example, you can set the colour, weight, font, padding etc. of the line numbers using this method.
+   3. Use set_code_style() to explicitly override the styles you set for line numbers using set_line_style. For example, if you'd set the line numbers to be bold (or even if you'd only set the fancy line number style to be bold), and you didn't actually want your code to be bold, you'd make sure that font-weight: normal; was in the stylesheet rule you passed to set_code_style
+
+This is the one major change from GeSHi 1.0.1 - make sure you become familiar with this, and make sure that you check any code you have already styled with 1.0.1 when you upgrade to make sure nothing bad happens to it.
+3.2.3: Choosing a Start Number
+Top | Contents | Next | Previous
+
+As of GeSHi 1.0.2, you can now make the line numbers start at any number, rather than just 1. This feature is useful if you're highlighting code from a file from around a certain line number in that file, as an additional guide to those who will view the code. You set the line numbers by calling the start_line_numbers_at() method:
+$geshi->start_line_numbers_at($number);
+
+$number must be a positive integer (or zero). If it is not, GeSHi will convert it anyway.
+
+If you have not enabled line numbers, this will have no effect.
+Caution:
+
+Although I'd like GeSHi to have XHTML strict compliance, this feature will break compliancy (however transitional compliancy remains). This is because the only widely supported way to change the start value for line numbers is by using the start="number" attribute of the <ol> tag. Although CSS does provide a mechanism for doing this, it is only supported in Opera versions 7.5 and above (not even Firefox supports this).
+3.3: Using CSS Classes
+Top | Contents | Next | Previous
+
+Using CSS to highlight your code instead of in-lining the styles is a definate bonus. Not only is it more compliant (the w3c is deprecating the style attribute in XHTML 2.0) but it results in far less outputted code - up to a whopping 90% saving - which makes a *huge* difference to those unlucky of us on modems!
+3.3.1: Enabling CSS Classes
+Top | Contents | Next | Previous
+
+By default, GeSHi doesn't use the classes, so it's easy just to whack out some highlighted code if you need without worrying about stylesheets. However, if you're a bit more organised about it, you should use the classes ;). To turn the use of classes on, you call the enable_classes() method:
+$geshi->enable_classes();
+
+If you want to turn classes OFF for some reason later:
+$geshi->enable_classes(false);
+
+If classes are enabled when parse_code() is called, then the resultant source will use CSS classes in the output, otherwise it will in-line the styles. The advantages of using classes are great - the reduction in source will be very noticeable, and what's more you can use one stylesheet for several different highlights on the same page. In fact, you can even use an external stylesheet and link to that, saving even more time and source (because stylesheets are cached by browsers).
+Note:
+
+There have been problems with inline styles and the Symbol Highlighting added in 1.0.7.21. If you can you should therefore turn CSS classes ON to avoid those issues.
+Caution:
+
+This should be the very first method you call after creating a new GeSHi object! That way, various other methods can act upon your choice to use classes correctly. In theory, you could call this method just before parsing the code, but this may result in unexpected behaviour.
+3.3.2: Setting the CSS class and ID
+Top | Contents | Next | Previous
+
+You can set an overall CSS class and id for the code. This is a good feature that allows you to use the same stylesheet for many different snippets of code. You call set_overall_class() and set_overall_id to accomplish this:
+$geshi->set_overall_class('mycode');
+$geshi->set_overall_id('dk48ck');
+
+The default classname is the name of the language being used. This means you can use just the one stylesheet for all sources that use the same language, and incidentally means that you probably won't have to call these methods too often.
+
+CSS IDs are supposed to be unique, and you should use them as such. Basically, you can specify an ID for your code and then use that ID to highlight that code in a unique way. You'd do this for a block of code that you expressly wanted to be highlighted in a different way (see the section below on gettting the stylesheet for your code for an example).
+3.3.3: Getting the stylesheet for your code
+Top | Contents | Next | Previous
+
+The other half of using CSS classes is getting the stylesheet for use with the classes. GeSHi makes it very easy to get a stylesheet for your code, with one easy method call:
+$geshi->enable_classes();
+
+// Here we have code that will spit out a header for
+// a stylesheet. For example:
+
+echo '<html>
+<head><title>Code</title>
+<style type="text/css">
+<!--';
+
+// Echo out the stylesheet for this code block
+
+echo $geshi->get_stylesheet();
+
+// And continue echoing the page
+
+echo '-->
+</style></head>
+<body>';
+
+The get_stylesheet() method gets the stylesheet for your code in one easy call. All you need to do is output it in the correct place. As you can also see, you don't even have to enable class usage to get the stylesheet nessecary either - however not enabling classes but using the stylesheet may result in problems later.
+
+By default, get_stylesheet() tries to echo the least amount of code possible. Although currently it doesn't check to see if a certain lexic is even in the source, you can expect this feature in the future. At least for the present however, if you explicitly disable the highlighting of a certain lexic, or disable line numbers, the related CSS will not be outputted. This may be a bad thing for you perhaps you're going to use the stylesheet for many blocks of code, some with line numbers, others with some lexic enabled where this source has it disabled. Or perhaps you're building an external stylesheet and want all lexics included. So to get around this problem, you do this:
+$geshi->get_stylesheet(false);
+
+This turns economy mode off, and all of the stylesheet will be outputted regardless.
+
+Now lets say you have several snippets of code, using the same language. In most of them you don't mind if they're highlighted the same way (in fact, that's exactly what you want) but in one of them you'd like the source to be highlighted differently. Here's how you can do that:
+// assume path is the default "geshi/" relative to the current directory
+$geshi1 = new GeSHi($source1, $lang);
+$geshi2 = new GeSHi($source2, $lang);
+$geshi3 = new GeSHi($source3, $lang);
+
+// Turn classes on for all sources
+$geshi1->enable_classes();
+$geshi2->enable_classes();
+$geshi3->enable_classes();
+
+// Make $geshi3 unique
+$geshi3->set_overall_id('different');
+
+//
+// Methods are called on $geshi3 to change styles...
+//
+
+echo '<html>
+<head><title>Code</title>
+<style type="text/css">
+<!--
+';
+
+// Get the nessecary stylesheets
+echo $geshi1->get_stylesheet();
+echo $geshi3->get_stylesheet();
+
+echo '-->
+</style></head>
+<body>';
+
+
+echo 'Code snippet 1:';
+echo $geshi1->parse_code();
+echo 'Code snippet 2 (same highlighting as 1):';
+echo $geshi2->parse_code();
+echo 'Code snippet 3 (DIFFERENT highlighting):';
+echo $geshi3->parse_code();
+
+echo '</body></html>';
+
+Before version 1.0.2, you needed to set the class of the code you wanted to be unique to the empty string. This limitation has been removed in version 1.0.2 - if you set the ID of a block of code, all styling will be done based on that ID alone.
+3.3.4: Using an External Stylesheet
+Top | Contents | Next | Previous
+
+An external stylesheet can reduce even more the amount of code needed to highlight some source. However there are some drawbacks with this. To use an external stylesheet, it's up to you to link it in to your document, normally with the following HTML:
+<html>
+<head>
+<link rel="stylesheet" type="text/css" href="url_to_stylesheet.css" />
+
+In your external stylesheet you put CSS declarations for your code. Then just make sure you're using the correct class (use set_overall_class() to ensure this) and this should work fine.
+
+This method is great if you don't mind the source always being highlighted the same (in particular, if you're making a plugin for a forum/wiki/other system, using an external stylesheet is a good idea!). It saves a small amount of code and your bandwidth, and it's relatively easy to just change the stylesheet should you need to. However, using this will render the methods that change the styles of the code useless, because of course the stylesheet is no longer being dynamically generated. You can still disable highlighting of certain lexics dynamically, however.
+Note:
+
+As of version 1.0.2, GeSHi comes with a contrib/ directory, which in it contains a "wizard" script for creating a stylesheet. Although this script is by no means a complete solution, it will create the necessary rules for the basic lexics - comments, strings for example. Things not included in the wizard include regular expressions for any language that uses them (PHP and XML are two languages that use them), and keyword-link styles. However, this script should take some of the tedium out of the job of making an external stylesheet. Expect a much better version of this script in version 1.2!
+3.4: Changing Styles
+Top | Contents | Next | Previous
+
+One of the more powerful features of GeSHi is the ability to change the style of the output dynamically. Why be chained to the boring styles the language authors make up? You can change almost every single aspect of highlighted code - and can even say whether something is to be highlighted at all.
+
+If you're confused about "styles", you probably want to have a quick tutorial in them so you know what you can do with them. Checkout the homepage of CSS at http://www.w3.org/Style/CSS.
+3.4.1: The Overall Styles
+Top | Contents | Next | Previous
+
+The code outputted by GeSHi is either in a <div> or a <pre> (see the section entitled "The Code Container"), and this can be styled.
+$geshi->set_overall_style('... styles ...');
+
+Where styles is a string containing valid CSS declarations. By default, these styles overwrite the current styles, but you can change this by adding a second parameter:
+$geshi->set_overall_style('color: blue;', true);
+
+The default styles "shine through" wherever anything isn't highlighted. Also, you can apply more advanced styles, like position: (fixed|relative) etc, because a <div>/<pre> is a block level element.
+Note:
+
+Remember that a <div> will by default have a larger font size than a <pre>, as discussed in the section "The Code Container".
+3.4.2: Line Number Styles
+Top | Contents | Next | Previous
+
+You may wish to refer to the section Styling Line Numbers before reading this section.
+
+As of version 1.0.2, the way line numbers are generated is different, so therefore the way that they are styled is different. In particular, now you cannot set the background style of the fancy line numbers to be different from that of the normal line numbers.
+
+Line number styles are set by using the method set_line_style:
+$geshi->set_line_style($style1, $style2);
+
+$style1 is the style of the line numbers by default, and $style2 is the style of the fancy line numbers.
+Caution:
+
+Things have changed since 1.0.1! This note is very important - please make sure you check this twice before complaining about line numbers!
+
+Because of the way that ordered lists are done in HTML, there really isn't normally a way to style the actual numbers in the list. I've cheated somewhat with GeSHi - I've made it possible to use CSS to style the foreground of the line numbers. So therefore, you can change the color, font size and type, and padding on them. If you want to have a pretty background, you must use set_overall_style() to do this, and use set_code_style() to style the actual code! This is explained in the section above: Styling Line Numbers.
+
+In addition, the styles for fancy line numbers is now the difference between the normal styles and the styles you want to achieve. For example, in GeSHi prior to 1.0.2 you may have done this to style line numbers:
+$geshi->set_line_style('color: red; font-weight: bold;', 'color: green; font-weight: bold');
+
+Now you instead can do this:
+$geshi->set_line_style('color: red; font-weight: bold;', 'color: green;');
+
+The font-weight: bold; will automatically carry through to the fancy styles. This is actually a small saving in code - but the difference may be confusing for anyone using 1.0.1 at first.
+3.4.3: Setting Keyword Styles
+Top | Contents | Next | Previous
+
+Perhaps the most regular change you will make will be to the styles of a keyword set. In order to change the styles for a particular set, you'll have to know what the set is called first. Sets are numbered from 1 up. Typically, set 1 contains keywords like if, while, do, for, switch etc, set 2 contains null, false, true etc, set 3 contains function inbuilt into the language (echo, htmlspecialchars etc. in PHP) and set 4 contains data types and similar variable modifiers: int, double, real, static etc. However these things are not fixed, and you should check the language file to see what key you want. Having a familiarity with a language file is definately a plus for using it.
+
+To change the styles for a keyword set, call the set_keyword_group_style() method:
+$geshi->set_keyword_group_style($group, $styles);
+
+Where $group is the group to change the styles for and $styles is a string containing the styles to apply to that group.
+
+By default, the styles you pass overwrite the current styles. Add a boolean true after the styles you specify to combine them with the current styles:
+$geshi->set_keyword_group_style(3, 'color: white;', true);
+3.4.4: Setting Comment Styles
+Top | Contents | Next | Previous
+
+To change the styles for a comment group, call the set_comments_style() method:
+$geshi->set_comments_style($group, $styles);
+
+Where $group is either a number corresponding to a single-line comment, or the string 'MULTI' to specify multiline comments:
+$geshi->set_comments_style(1, 'font-style: italic;');
+$geshi->set_comments_style('MULTI', 'display: hidden;');
+
+By default, the styles you pass overwrite the current styles. Add a boolean true after the styles you specify to combine them with the current styles:
+$geshi->set_comments_style(1, 'font-weight: 100;', true);
+Note:
+
+In 1.0.7.22 a new kind of Comments called "COMMENT_REGEXP" has been added. Those are handled by setting single line comment styles.
+3.4.5: Setting Other Styles
+Top | Contents | Next | Previous
+
+GeSHi can highlight many other aspects of your source other than just keywords and comments. Strings, Numbers, Methods and Brackets among other things can all also be highlighted. Here are the related methods:
+$geshi->set_escape_characters_style($styles[, $preserve_defaults]);
+$geshi->set_symbols_style($styles[, $preserve_defaults]);
+$geshi->set_strings_style($styles[, $preserve_defaults]);
+$geshi->set_numbers_style($styles[, $preserve_defaults]);
+$geshi->set_methods_style($key, $styles[, $preserve_defaults]);
+$geshi->set_regexps_style($key, $styles[, $preserve_defaults]);
+
+$styles is a string containing valid stylesheet declarations, while $preserve_defaults should be set to true if you want your styles to be merged with the previous styles. In the case of set_methods_style, you should select a group to set the styles of, check the language files for the number used for each "object splitter".
+
+Like this was possible for set_method_style a new parameter has been introduced for set_symbols_style too which allows you to select the group of symbols for which you'd like to change your style. $geshi->set_symbols_style($styles[, $preserve_defaults[, $group]]);
+If the third parameter is not given, group 0 is assumed. Furthermore you should note that any changes to group 0 are also reflected in the bracket style, i.e. a pass-through call to set_bracket_style is made.
+3.5: Case Sensitivity and Auto Casing
+Top | Contents | Next | Previous
+
+Controlling the case of the outputted source is an easy job with GeSHi. You can control which keywords are converted in case, and also control whether keywords are checked in a case sensitive manner.
+3.5.1: Auto-Caps/Nocaps
+Top | Contents | Next | Previous
+
+Auto-Caps/Nocaps is a nifty little feature that capitalises or lowercases automatically certain lexics when they are styled. I dabble in QuickBASIC, a dialect of BASIC which is well known for it's capatalisation, and SQL is another language well known for using caps for readability.
+
+To change what case lexics are rendered in, you call the set_case_keywords() method:
+$geshi->set_case_keywords($caps_modifier);
+
+The valid values to pass to this method are:
+
+    * GESHI_CAPS_NO_CHANGE - Don't change the case of any lexics, leave as they are found
+    * GESHI_CAPS_UPPER - Uppercase all lexics found
+    * GESHI_CAPS_LOWER - Lowercase all lexics found
+
+Caution:
+
+When I say "lexic", I mean "keywords". Any keyword in any keyword array will be modified using this option! This is one small area of inflexibility I hope to fix in 1.2.X.
+
+I suspect this will only be used to specify GESHI_CAPS_NO_CHANGE to turn off autocaps for languages like SQL and BASIC variants, like so:
+$geshi = new GeSHi($source, 'sql');
+$geshi->set_case_keywords(GESHI_CAPS_NO_CHANGE); // don't want keywords capatalised
+
+All the same, it can be used for some interesting effects:
+$geshi = new GeSHi($source, 'java');
+// Anyone who's used java knows how picky it is about CapitalLetters...
+$geshi->set_case_keywords(GESHI_CAPS_LOWER);
+// No *way* the source will look right now ;)
+3.5.2: Setting Case Sensitivity
+Top | Contents | Next | Previous
+
+Some languages, like PHP, don't mind what case function names and keywords are in, while others, like Java, depend on such pickiness to maintain their bad reputations ;). In any event, you can use the set_case_sensitivity to change the case sensitiveness of a particular keyword group from the default:
+$geshi->set_case_sensitivity($key, $sensitivity);
+
+Where $key is the key of the group for which you wish to change case sensitivness for (see the language file for that language), and $sensitivity is a boolean value - true if the keyword is case sensitive, and false if not.
+3.6: Changing the Source, Language, Config Options
+Top | Contents | Next | Previous
+
+What happens if you want to change the source to be highlighted on the fly, or the language. Or if you want to specify any of those basic fields after you've created a GeSHi object? Well, that's where these methods come in.
+3.6.1: Changing the Source Code
+Top | Contents | Next | Previous
+
+To change the source code, you call the set_source() method:
+$geshi->set_source($newsource);
+
+Example:
+$geshi = new GeSHi($source1, 'php');
+
+// Method calls to specify various options...
+
+$code1 = $geshi->parse_code();
+
+$geshi->set_source($source2);
+$code2 = $geshi->parse_code();
+3.6.2: Changing the Language
+Top | Contents | Next | Previous
+
+What happens if you want to change the language used for highlighting? Just call set_language():
+$geshi->set_language('newlanguage');
+
+Example:
+$geshi = new GeSHi($source, 'php');
+
+$code = $geshi->parse_code();
+
+// Highlight GeSHi's output
+$geshi->set_source($code);
+$geshi->set_language('html4strict');
+$geshi->enable_classes(false);
+echo $geshi->parse_code();
+Note:
+
+Names are case-insensitive - they will be converted to lower case to match a language file however. So if you're making a language file, remember it should have a name in lower case.
+Note:
+
+What you pass to this method is the name of a language file, minus the .php extension. If you're writing a plugin for a particular application, it's up to you to somehow convert user input into a valid language name.
+Caution:
+
+GeSHi include()s the language file, so be careful to make sure that users can't pass some wierd language name to include any old script! GeSHi tries to strip non-valid characters out of a language name, but you should always do this your self anyway. In particular, language files are always lower-case, with either alphanumeric characters, dashes or underscores in their name.
+
+At the very least, strip "/" characters out of a language name.
+3.6.3: Changing the Language Path
+Top | Contents | Next | Previous
+
+What happens if all of a sudden you want to use language files from a different directory from the current language file location? You call the set_language_path() method:
+$geshi->set_language_path($newpath);
+
+It doesn't matter whether the path has a trailing slash after it or not - only that it points to a valid folder. If it doesn't, that's your tough luck ;)
+3.6.4: Changing the Character Set
+Top | Contents | Next | Previous
+Note:
+
+As of GeSHi 1.0.7.18, you don't need to use this, as htmlspecialchars is not being used due to a security flaw in it (that is unpatched in even the most recent PHP4 versions, and in PHP5 < 5.2). As long as you set the encoding properly with a php header() call, your foreign characters will be displayed correctly.
+
+As of version 1.0.3, you can use the method set_encoding to specify the character set that your source is in. Valid names are those names that are valid for the PHP function htmlentities():
+$geshi->set_encoding($encoding);
+
+There is a table of valid strings for $encoding at the php.net manual linked to above. If you do not specify an encoding, or specify an invalid encoding, the character set used is ISO-8859-1.
+Using load_from_file to Change the Language and Source Code
+Top | Contents | Next | Previous
+
+As of GeSHi 1.0.5, you can use the method load_from_file to load the source code and language from a file. Simply pass this method a file name and it will attempt to load the source and set the language.
+$geshi->load_from_file($file_name, $lookup);
+
+$file_name is the file name to use, and $lookup is an optional parameter that contains a lookup array to use for deciding which language to choose. You can use this to override GeSHi's default lookup array, which may not contain the extension of the file you're after, or perhaps does have your extension but under a different language. The lookup array is of the form:
+
+array(
+        *   'lang_name' => array('extension', 'extension', ...),
+        *   'lang_name' ...
+        * );
+
+Also, you can use the method get_language_name_from_extension if you need to convert a file extension to a valid language name. This method will return the empty string if it could not find a match in the lookup, and like load_from_file it accepts an optional second parameter that contains a lookup array.
+3.7: Error Handling
+Top | Contents | Next | Previous
+
+What happens if you try to highlight using a language that doesn't exist? Or if GeSHi can't read a required file? The results you get may be confusing. You may check your code over and over, and never find anything wrong. GeSHi provides ways of finding out if GeSHi itself found anything wrong with what you tried to do. After highlighting, you can call the error() method:
+$geshi = new GeSHi('hi', 'thisLangIsNotSupported');
+
+echo $geshi->error();  // echoes error message
+
+The error message you will get will look like this:
+
+    GeSHi Error: GeSHi could not find the language thisLangIsNotSupported (using path geshi/) (code 2)
+
+The error outputted will be the last error GeSHi came across, just like how mysql_error() works.
+3.8: Disabling styling of some Lexics
+Top | Contents | Next | Previous
+
+One disadvantage of GeSHi is that for large source files using complex languages, it can be quite slow with every option turned on. Although future releases will concentrate on the speed/resource side of highlighting, for now you can gain speed increases by disabling some of the highlighting options. This is done by using a series of set_*_highlighting methods:
+
+    * set_keyword_group_highlighting($group, $flag): Sets whether a particular $group of keywords is to be highlighted or not. Consult the necessary language file(s) to see what $group should be for each group (typically a positive integer). $flag is false if you want to disable highlighting of this group, and true if you want to re-enable higlighting of this group. If you disable a keyword group then even if the keyword group has a related URL one will not be generated for that keyword.
+    * set_comments_highlighting($group, $flag): Sets whether a particular $group of comments is to be highlighted or not. Consult the necessary language file(s) to see what $group should be for each group (typically a positive integer, or the string 'MULTI' for multiline comments. $flag is false if you want to disable highlighting of this group, and true if you want to re-enable highlighting of this group.
+    * set_regexps_highlighting($regexp, $flag): Sets whether a particular $regexp is to be highlighted or not. Consult the necessary language file(s) to see what $regexp should be for each regexp (typically a positive integer, or the string 'MULTI' for multiline comments. $flag is false if you want to disable highlighting of this group, and true if you want to re-enable highlighting of this group.
+    * The following methods:
+          o set_escape_characters_highlighting($flag)
+          o set_symbols_highlighting($flag)
+          o set_strings_highlighting($flag)
+          o set_numbers_highlighting($flag)
+          o set_methods_highlighting($flag)
+      Work on their respective lexics (e.g. set_methods_highlighting will disable/enable highlighting of methods). For each method, if $flag is false then the related lexics will not be highlighted at all (this means no HTML will surround the lexic like usual, saving on time and bandwidth.
+
+In case all highlighting should be disabled or reenabled GeSHi provides two methods called disable_highlighting() and enable_highlighting($flag). The optional paramter $flag has been added in 1.0.7.21 and specifies the desired state, i.e. true (default) to turn all highlighting on, or false to turn all highlighting off. Since 1.0.7.21 the method disnable_highlighting() has become deprecated.
+3.9: Setting the Tab Width
+Top | Contents | Next | Previous
+
+If you're using the <pre> header, tabs are handled automatically by your browser, and in general you can count on good results. However, if you're using the <div> header, you may want to specify a tab width explicitly.
+
+Note that tabs created in this fashion won't be like normal tabs - there won't be "tab-stops" as such, instead tabs will be replaced with the specified number of spaces.
+
+To change the tab width, you call the set_tab_width() method:
+$geshi->set_tab_width($width);
+
+Where $width is the width in spaces that you'd like tabs to be.
+3.10: Using Strict Mode
+Top | Contents | Next | Previous
+
+Some languages like to get tricky, and jump in and out of the file that they're in. For example, the vast majority of you reading this will have used a PHP file. And you know that PHP code is only executed if it's within delimiters like <?php and ?> (there are others of course...). So what happens if you do the following in a php file?
+<img src="<?php echo rand(1, 100) ?>" />
+
+Well normally using GeSHi with PHP, or using a bad highlighter, you'll end up with this:
+<img src="<?php echo rand(1, 100) ?>" />
+
+What a mess! Especially if you're being slack about where you're putting your quotes, you could end up with the rest of your file as bright red. Fortunately, you can tell GeSHi to be "strict" about just when it highlights and when it does not, using the enable_strict_mode method:
+$geshi->enable_strict_mode($mode);
+
+Where $mode is true or not specified to enable strict mode, or false to disable strict mode if you've already turned it and don't want it now.
+
+Here's the result: much better!
+<img src="<?php echo rand(1, 100) ?>" />
+3.11: Adding/Removing Keywords
+Top | Contents | Next | Previous
+
+Lets say that you're working on a large project, with many files, many classes and many functions. Perhaps also you have the source code on the web and highlighted by GeSHi, perhaps as a front end to CVS, as a learning tool, something to refer to, whatever. Well, why not highlight the names of the functions and classes *your* project uses, as well as the standard functions and classes? Or perhaps you're not interested in highlighting certain functions, and would like to remove them? Or maybe you don't mind if an entire function group goes west in the interest of speed? GeSHi can handle all of this!
+3.11.1: Adding a Keyword
+Top | Contents | Next | Previous
+
+If you want to add a keyword to an existing keyword group, you use the add_keyword method:
+$geshi->add_keyword($key, $word);
+
+Where $key is the index of the group of keywords you want to add this keyword to, and $word is the word to add.
+
+This implies knowledge of the language file to know the correct index.
+Note:
+
+Keywords should contain at least two alphabetical characters (lower or upper case letters only). This is to enable GeSHi to work much faster by not bothering to try to detect keywords in parts of your source where there is no alphabetical characters.
+3.11.2: Removing a Keyword
+Top | Contents | Next | Previous
+
+Perhaps you want to remove a keyword from an existing group. Maybe you don't use it and want to save yourself some time. Whatever the reason, you can remove it using the remove_keyword method:
+$geshi->remove_keyword($key, $word);
+
+Where $key is the index of the gropu of keywords that you want to remove this keyword from, and $word is the word to remove.
+
+This implies knowledge of the language file to know the correct index - most of the time the keywords you'll want to remove will be in group 3, but this is not guaranteed and you should check the language file first.
+
+This function is silent - if the keyword is not in the group you specified, nothing awful will happen ;)
+3.11.3: Adding a Keyword Group
+Top | Contents | Next | Previous
+
+Lets say for your big project you have several main functions and classes that you'd like highlighted. Why not add them as their own group instead of having them highlighted the same way as other keywords? Then you can make them stand out, and people can instantly see which functions and classes are user defined or inbuilt. Furthermore, you could set the URL for this group to point at the API documentation of your project.
+
+You add a keyword group by using the add_keyword_group method:
+$geshi->add_keyword_group($key, $styles, $case_sensitive, $words);
+
+Where $key is the key that you want to use to refer to this group, $styles is the styles that you want to use to style this group, $case_sensitive is true or false depending on whether you want this group of keywords to be case sensitive or not and $words is an array of words (or a string) of which words to add to this group. For example:
+$geshi->add_keyword_group(10, 'color: #600000;', false, array('myfunc_1', 'myfunc_2', 'myfunc_3'));
+
+Adds a keyword group referenced by index 10, of which all keywords in the group will be dark red, each keyword can be in any case and which contains the keywords "myfunc_1", "myfunc_2" and "myfunc_3".
+
+After creating such a keyword group, you may call other GeSHi methods on it, just as you would for any other keyword group.
+Caution:
+
+If you specify a $key for which there is already a keyword group, the old keyword group will be overwritten! Most language files don't use numbers larger than 5, so I recommend you play it safe and use a number like 10 or 42.
+3.11.4: Removing a Keyword Group
+Top | Contents | Next | Previous
+
+Perhaps you *really* need speed? Why not just remove an entire keyword group? GeSHi won't have to loop through each keyword checking for its existance, saving much time. You remove a keyword group by using the remove_keyword_group method:
+$geshi->remove_keyword_group($key);
+
+Where $key is the key of the group you wish to remove. This implies knowleged of the language file.
+3.12: Headers and Footers for Your Code
+Top | Contents | Next | Previous
+
+So you want to add some special information to the highlighted source? GeSHi can do that too! You can specify headers and footers for your code, style them, and insert information from the highlighted source into your header or footer.
+3.12.1: Keyword Substitution
+Top | Contents | Next | Previous
+
+In your header and footer, you can put special keywords that will be replaced with actual configuration values for this GeSHi object. The keywords you can use are:
+
+    * <TIME> or {TIME}: Is replaced by the time it took for the parse_code method - i.e., how long it took for your code to be highlighted. The time is returned to three decimal places.
+    * <LANGUAGE> or {LANGUAGE}: Is replaced by a nice, friendly version of the language name used to highlight this code.
+    * <VERSION> or {VERSION}: The GeSHi version used to highlight the code.
+
+3.12.2: Setting Header Content
+Top | Contents | Next | Previous
+
+The header for your code is a <div>, which is inside the containing block. Therefore, it is affected by the method set_overall_style, and should contain the sort of HTML that belongs in a <div>. You may use any HTML you like, and format it as an HTML document. You should use valid HTML - convert to entities any quotemarks or angle brackets you want displayed. You set the header content using the method set_header_content:
+$geshi->set_header_content($content);
+
+Where $content is the HTML you want to use for the header.
+3.12.3: Setting Footer Content
+Top | Contents | Next | Previous
+
+The footer for your code is a <div>, which is inside the containing block. Therefore, it is affected by the method set_overall_style, and should contain the sort of HTML that belongs in a <div>. You may use any HTML you like, and format it as an HTML document. You should use valid HTML - convert to entities any quotemarks or angle brackets you want displayed. You set the footer content using the method set_footer_content:
+$geshi->set_footer_content($content);
+
+Where $content is the HTML you want to use for the footer.
+3.12.4: Styling Header Content
+Top | Contents | Next | Previous
+
+You can apply styles to the header content you have set with the set_header_content_style:
+$geshi->set_header_content_style($styles);
+
+Where $styles is the stylesheet declarations you want to use to style the header content.
+3.12.5: Styling Footer Content
+Top | Contents | Next | Previous
+
+You can apply styles to the footer content you have set with the set_footer_content_style:
+$geshi->set_footer_content_style($styles);
+
+Where $styles is the stylesheet declarations you want to use to style the footer content.
+3.13: Keyword URLs
+Top | Contents | Next | Previous
+
+As of version 1.0.2, GeSHi allows you to specify a URL for keyword groups. This URL is used by GeSHi to convert the keywords in that group into URLs to appropriate documentation. And using add_keyword_group you can add functions and classes from your own projects and use the URL functionality to provide a link to your own API documentation.
+3.13.1: Setting a URL for a Keyword Group
+Top | Contents | Next | Previous
+
+To set the URL to be used for a keyword group, you use the set_url_for_keyword_group method:
+$geshi->set_url_for_keyword_group($group, $url);
+
+Where $group is the keyword group you want to assign the URL for, and $url is the URL for this group of keywords.
+
+You may be wondering how to make each keyword in the group point to the correct URL. You do this by putting {FNAME} in the URL at the correct place. For example, PHP makes it easy by linking www.php.net/function-name to the documentation for that function, so the URL used is http://www.php.net/{FNAME}.
+
+Of course, when you get to a language like Java, that puts its class documentation in related folders, it gets a little trickier to work out an appropriate URL (see the Java language file!). I hope to provide some kind of redirection service at the GeSHi website in the future.
+Note:
+
+As of Version 1.0.7.21 there have been added two more symbols you can use to link to functions. {FNAMEL} will generate the lowercase version of the keyword, {FNAMEU} will generate the upper-case version. {FNAME} will provide the keyword as specified in the language file.
+3.13.2: Disabling a URL for a Keyword Group
+Top | Contents | Next | Previous
+
+It's easy to disable a URL for a keyword group: Simply use the method set_url_for_keyword_group to pass an empty string as the URL:
+$geshi->set_url_for_keyword_group($group, '');
+3.13.3 Disabling all URLs for Keywords
+Top | Contents | Next | Previous
+
+As of GeSHi 1.0.7.18, you can disable all URL linking for keywords:
+$geshi->enable_keyword_links(false);
+3.13.4: Styling Links
+Top | Contents | Next | Previous
+
+You can also style the function links. You can style their default status, hovered, active and visited status. All of this is controlled by one method, set_link_styles:
+$geshi->set_link_styles($mode, $styles);
+
+Where $mode is one of four values:
+
+    * GESHI_LINK: The default style of the links.
+    * GESHI_HOVER: The style of the links when they have focus (the mouse is hovering over them).
+    * GESHI_ACTIVE: The style of the links when they are being clicked.
+    * GESHI_VISITED: The style of links that the user has already visited.
+
+And $styles is the stylesheet declarations to apply to the links.
+3.13.5: Setting the Link Target
+Top | Contents | Next | Previous
+
+Perhaps you want to set the target of link attributes, so the manual pages open in a new window? Use the set_link_target method:
+$geshi->set_link_target($target, $styles);
+
+Where $target is any valid (X)HTML target value - _blank or _top for example.
+3.14: Using Contextual Importance
+Top | Contents | Next | Previous
+Caution:
+
+This functionality is not only buggy, but is proving very hard to implement in 1.1.X. Therefore, this functionality may well be removed in 1.2.0. You are hereby warned!
+3.15: Highlighting Special Lines "Extra"
+Top | Contents | Next | Previous
+
+An alternative (and more stable) method of highlighting code that is important is to use extra highlighting by line. Although you may not know what line numbers contain the important lines, if you do this method is a much more flexible way of making important lines stand out.
+3.15.1: Specifying the Lines to Highlight Extra
+Top | Contents | Next | Previous
+
+To specify which lines to highlight extra, you past an array containing the line numbers to highlight_lines_extra:
+$geshi->highlight_lines_extra($array);
+
+The array could be in the form array(2, 3, 4, 7, 12, 344, 4242), made from a DB query, generated from looking through the source for certain important things and working out what line those things are... however you get the line numbers, the array should simply be an array of integers.
+
+Here's an example, using the same source as before:
+//
+// Here we go again! This time we'll simply highlight the 8th line
+//
+$source = 'public int[][] product ( n, m )
+{
+  int [][] ans = new int[n][m];
+  for ( int i = 0; i < n; i++ )
+  {
+    for ( int j = 0; i < m; j++ )
+    {
+      ans[i][j] = i * j;
+    }
+  }
+  return ans;
+}';
+
+$geshi = new GeSHi($source, 'java');
+
+$geshi->highlight_lines_extra(array(8));
+echo $geshi->parse_code();
+
+Which produces:
+public int[][] product ( n, m )
+{
+  int [][] ans = new int[n][m];
+  for ( int i = 0; i < n; i++ )
+  {
+    for ( int j = 0; i < m; j++ )
+    {
+      ans[i][j] = i * j;
+    }
+  }
+  return ans;
+}
+
+What's more, as you can see the code on a highlighted line is still actually highlighted itself.
+Note:
+
+As you can see, this is a little buggy, but that is because of HTML laws (code elements should not contain div elements). This works just fine if you use line numbers.
+3.15.2: Styles for the Highlighted Lines
+Top | Contents | Next | Previous
+
+Again as with contextual importance, you're not chained to the yellow theme that is the default. You can use the set_highlight_lines_extra_style method:
+$geshi->set_highlight_lines_extra_style($styles);
+
+Where $styles is the stylesheet declarations that you want to apply to highlighted lines.
+3.16: Adding IDs to Each Line
+Top | Contents | Next | Previous
+
+Perhaps you're a javascript junkie? GeSHi provides a way to give each line an ID so you can access that line with javascript, or perhaps just by plain CSS (though if you want to access lines by CSS you should use the method in the previous section). To enable IDs you call the enable_ids method:
+$geshi->enable_ids($flag);
+
+Where $flag is true or not present to enable IDs, and false to disable them again if you need.
+
+The ID generated is in the form {overall-css-id}-{line-number}. So for example, if you set the overall CSS id to be "mycode", then the IDs for each line would by "mycode-1", "mycode-2" etc. If there is no CSS ID set, then one is made up in the form geshi-[4 random characters], but this is not so useful for if you want to do javascript manipulation.
+3.17: Getting the Time of Styling
+Top | Contents | Next | Previous
+
+Once you've called parse_code, you can get the time it took to run the highlighting by calling the get_time method:
+$geshi = new GeSHi($source, $language, $path);
+
+$code = mysql_real_escape_string($geshi->parse_code());
+$time = $geshi->get_time();
+
+// do something with it
+mysql_query("INSERT INTO code VALUES ('$code', '$time')");
+4: Language Files
+Top | Contents | Next | Previous
+
+So now you know what features GeSHi offers, and perhaps you've even meddled with the source. Or perhaps you'd like a language file for language X but it doesn't seem to be supported? Rubbish! GeSHi will highlight anything, what do you think I coded this for? ^_^ You'll just have to learn how to make a language file yourself. And I promise it's not too hard - and if you're here you're in the right place!
+4.1: An Example Language File
+Top | Contents | Next | Previous
+
+Let's begin by looking at an example language file - the language file for the first language ever supported, PHP.
+
+<?php
+/*************************************************************************************
+ * php.php
+ * --------
+ * Author: Nigel McNie (nigel@geshi.org)
+ * Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.2
+ * CVS Revision Version: $Revision: 1196 $
+ * Date Started: 2004/06/20
+ * Last Modified: $Date: 2008-06-08 17:55:42 +0000 (So, 08. Jun 2008) $
+ *
+ * PHP language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2004/XX/XX (1.0.2)
+ *  -  Added URL support
+ *  -  Added extra constants
+ * 2004/08/05 (1.0.1)
+ *  -  Added support for symbols
+ * 2004/07/14 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2004/07/14)
+ * -------------------------
+ * * Make sure the last few function I may have missed
+ *   (like eval()) are included for highlighting
+ * * Split to several files - php4, php5 etc
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+       'LANG_NAME' => 'PHP',
+       'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
+       'COMMENT_MULTI' => array('/*' => '*/'),
+       'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+       'QUOTEMARKS' => array("'", '"'),
+       'ESCAPE_CHAR' => '\\',
+       'KEYWORDS' => array(
+               1 => array(
+                       'include', 'require', 'include_once', 'require_once',
+                       'for', 'foreach', 'as', 'if', 'elseif', 'else', 'while', 'do', 'endwhile', 'endif', 'switch', 'case', 'endswitch',
+                       'return', 'break'
+                       ),
+               2 => array(
+                       'null', '__LINE__', '__FILE__',
+                       'false', '&lt;?php', '?&gt;', '&lt;?',
+                       '&lt;script language=', '&lt;/script&gt;',
+                       'true', 'var', 'default',
+                       'function', 'class', 'new',
+                       '__FUNCTION__', '__CLASS__', '__METHOD__', 'PHP_VERSION',
+                       'PHP_OS', 'DEFAULT_INCLUDE_PATH', 'PEAR_INSTALL_DIR', 'PEAR_EXTENSION_DIR',
+                       'PHP_EXTENSION_DIR', 'PHP_BINDIR', 'PHP_LIBDIR', 'PHP_DATADIR', 'PHP_SYSCONFDIR',
+                       'PHP_LOCALSTATEDIR', 'PHP_CONFIG_FILE_PATH', 'PHP_OUTPUT_HANDLER_START', 'PHP_OUTPUT_HANDLER_CONT',
+                       'PHP_OUTPUT_HANDLER_END', 'E_ERROR', 'E_WARNING', 'E_PARSE', 'E_NOTICE',
+                       'E_CORE_ERROR', 'E_CORE_WARNING', 'E_COMPILE_ERROR', 'E_COMPILE_WARNING', 'E_USER_ERROR',
+                       'E_USER_WARNING', 'E_USER_NOTICE', 'E_ALL'
+                       ),
+               3 => array(
+                       'zlib_get_coding_type','zend_version','zend_logo_guid','yp_order','yp_next',
+                       'yp_match','yp_master','yp_get_default_domain','yp_first','yp_errno','yp_err_string',
+                       'yp_cat','yp_all','xml_set_unparsed_entity_decl_handler','xml_set_start_namespace_decl_handler','xml_set_processing_instruction_handler','xml_set_object',
+                       'xml_set_notation_decl_handler','xml_set_external_entity_ref_handler','xml_set_end_namespace_decl_handler','xml_set_element_handler','xml_set_default_handler','xml_set_character_data_handler',
+                       'xml_parser_set_option','xml_parser_get_option','xml_parser_free','xml_parser_create_ns','xml_parser_create','xml_parse_into_struct',
+                       'xml_parse','xml_get_error_code','xml_get_current_line_number','xml_get_current_column_number','xml_get_current_byte_index','xml_error_string',
+                       'wordwrap','wddx_serialize_vars','wddx_serialize_value','wddx_packet_start','wddx_packet_end','wddx_deserialize',
+                       'wddx_add_vars','vsprintf','vprintf','virtual','version_compare','var_export',
+                       'var_dump','utf8_encode','utf8_decode','usort','usleep','user_error',
+                       'urlencode','urldecode','unserialize','unregister_tick_function','unpack','unlink',
+                       'unixtojd','uniqid','umask','uksort','ucwords','ucfirst',
+                       'uasort','trim','trigger_error','touch','token_name','token_get_all',
+                       'tmpfile','time','textdomain','tempnam','tanh','tan',
+                       'system','syslog','symlink','substr_replace','substr_count','substr',
+                       'strval','strtr','strtoupper','strtotime','strtolower','strtok',
+                       'strstr','strspn','strrpos','strrev','strrchr','strpos',
+                       'strncmp','strncasecmp','strnatcmp','strnatcasecmp','strlen','stristr',
+                       'stripslashes','stripcslashes','strip_tags','strftime','stream_wrapper_register','stream_set_write_buffer',
+                       'stream_set_timeout','stream_set_blocking','stream_select','stream_register_wrapper','stream_get_meta_data','stream_filter_prepend',
+                       'stream_filter_append','stream_context_set_params','stream_context_set_option','stream_context_get_options','stream_context_create','strcspn',
+                       'strcoll','strcmp','strchr','strcasecmp','str_word_count','str_shuffle',
+                       'str_rot13','str_replace','str_repeat','str_pad','stat','sscanf',
+                       'srand','sqrt','sql_regcase','sprintf','spliti','split',
+                       'soundex','sort','socket_writev','socket_write','socket_strerror','socket_shutdown',
+                       'socket_setopt','socket_set_timeout','socket_set_option','socket_set_nonblock','socket_set_blocking','socket_set_block',
+                       'socket_sendto','socket_sendmsg','socket_send','socket_select','socket_recvmsg','socket_recvfrom',
+                       'socket_recv','socket_readv','socket_read','socket_listen','socket_last_error','socket_iovec_set',
+                       'socket_iovec_free','socket_iovec_fetch','socket_iovec_delete','socket_iovec_alloc','socket_iovec_add','socket_getsockname',
+                       'socket_getpeername','socket_getopt','socket_get_status','socket_get_option','socket_create_pair','socket_create_listen',
+                       'socket_create','socket_connect','socket_close','socket_clear_error','socket_bind','socket_accept',
+                       'sleep','sizeof','sinh','sin','similar_text','shuffle',
+                       'show_source','shmop_write','shmop_size','shmop_read','shmop_open','shmop_delete',
+                       'shmop_close','shm_remove_var','shm_remove','shm_put_var','shm_get_var','shm_detach',
+                       'shm_attach','shell_exec','sha1_file','sha1','settype','setlocale',
+                       'setcookie','set_time_limit','set_socket_blocking','set_magic_quotes_runtime','set_include_path','set_file_buffer',
+                       'set_error_handler','session_write_close','session_unset','session_unregister','session_start','session_set_save_handler',
+                       'session_set_cookie_params','session_save_path','session_register','session_regenerate_id','session_name','session_module_name',
+                       'session_is_registered','session_id','session_get_cookie_params','session_encode','session_destroy','session_decode',
+                       'session_cache_limiter','session_cache_expire','serialize','sem_remove','sem_release','sem_get',
+                       'sem_acquire','rtrim','rsort','round','rmdir','rewinddir',
+                       'rewind','restore_include_path','restore_error_handler','reset','rename','register_tick_function',
+                       'register_shutdown_function','realpath','readlink','readgzfile','readfile','readdir',
+                       'read_exif_data','rawurlencode','rawurldecode','range','rand','rad2deg',
+                       'quotemeta','quoted_printable_decode','putenv','proc_open','proc_close','printf',
+                       'print_r','prev','preg_split','preg_replace_callback','preg_replace','preg_quote',
+                       'preg_match_all','preg_match','preg_grep','pow','posix_uname','posix_ttyname',
+                       'posix_times','posix_strerror','posix_setuid','posix_setsid','posix_setpgid','posix_setgid',
+                       'posix_seteuid','posix_setegid','posix_mkfifo','posix_kill','posix_isatty','posix_getuid',
+                       'posix_getsid','posix_getrlimit','posix_getpwuid','posix_getpwnam','posix_getppid','posix_getpid',
+                       'posix_getpgrp','posix_getpgid','posix_getlogin','posix_getgroups','posix_getgrnam','posix_getgrgid',
+                       'posix_getgid','posix_geteuid','posix_getegid','posix_getcwd','posix_get_last_error','posix_errno',
+                       'posix_ctermid','pos','popen','pi','phpversion','phpinfo',
+                       'phpcredits','php_uname','php_sapi_name','php_logo_guid','php_ini_scanned_files','pg_update',
+                       'pg_untrace','pg_unescape_bytea','pg_tty','pg_trace','pg_setclientencoding','pg_set_client_encoding',
+                       'pg_send_query','pg_select','pg_result_status','pg_result_seek','pg_result_error','pg_result',
+                       'pg_query','pg_put_line','pg_port','pg_ping','pg_pconnect','pg_options',
+                       'pg_numrows','pg_numfields','pg_num_rows','pg_num_fields','pg_meta_data','pg_lowrite',
+                       'pg_lounlink','pg_loreadall','pg_loread','pg_loopen','pg_loimport','pg_loexport',
+                       'pg_locreate','pg_loclose','pg_lo_write','pg_lo_unlink','pg_lo_tell','pg_lo_seek',
+                       'pg_lo_read_all','pg_lo_read','pg_lo_open','pg_lo_import','pg_lo_export','pg_lo_create',
+                       'pg_lo_close','pg_last_oid','pg_last_notice','pg_last_error','pg_insert','pg_host',
+                       'pg_getlastoid','pg_get_result','pg_get_pid','pg_get_notify','pg_freeresult','pg_free_result',
+                       'pg_fieldtype','pg_fieldsize','pg_fieldprtlen','pg_fieldnum','pg_fieldname','pg_fieldisnull',
+                       'pg_field_type','pg_field_size','pg_field_prtlen','pg_field_num','pg_field_name','pg_field_is_null',
+                       'pg_fetch_row','pg_fetch_result','pg_fetch_object','pg_fetch_assoc','pg_fetch_array','pg_fetch_all',
+                       'pg_exec','pg_escape_string','pg_escape_bytea','pg_errormessage','pg_end_copy','pg_delete',
+                       'pg_dbname','pg_copy_to','pg_copy_from','pg_convert','pg_connection_status','pg_connection_reset',
+                       'pg_connection_busy','pg_connect','pg_cmdtuples','pg_close','pg_clientencoding','pg_client_encoding',
+                       'pg_cancel_query','pg_affected_rows','pfsockopen','pclose','pathinfo','passthru',
+                       'parse_url','parse_str','parse_ini_file','pack','overload','output_reset_rewrite_vars',
+                       'output_add_rewrite_var','ord','openssl_x509_read','openssl_x509_parse','openssl_x509_free','openssl_x509_export_to_file',
+                       'openssl_x509_export','openssl_x509_checkpurpose','openssl_x509_check_private_key','openssl_verify','openssl_sign','openssl_seal',
+                       'openssl_public_encrypt','openssl_public_decrypt','openssl_private_encrypt','openssl_private_decrypt','openssl_pkey_new','openssl_pkey_get_public',
+                       'openssl_pkey_get_private','openssl_pkey_free','openssl_pkey_export_to_file','openssl_pkey_export','openssl_pkcs7_verify','openssl_pkcs7_sign',
+                       'openssl_pkcs7_encrypt','openssl_pkcs7_decrypt','openssl_open','openssl_get_publickey','openssl_get_privatekey','openssl_free_key',
+                       'openssl_error_string','openssl_csr_sign','openssl_csr_new','openssl_csr_export_to_file','openssl_csr_export','openlog',
+                       'opendir','octdec','ob_start','ob_list_handlers','ob_implicit_flush','ob_iconv_handler',
+                       'ob_gzhandler','ob_get_status','ob_get_level','ob_get_length','ob_get_flush','ob_get_contents',
+                       'ob_get_clean','ob_flush','ob_end_flush','ob_end_clean','ob_clean','number_format',
+                       'nl_langinfo','nl2br','ngettext','next','natsort','natcasesort',
+                       'mysql_unbuffered_query','mysql_thread_id','mysql_tablename','mysql_table_name','mysql_stat','mysql_selectdb',
+                       'mysql_select_db','mysql_result','mysql_real_escape_string','mysql_query','mysql_ping','mysql_pconnect',
+                       'mysql_numrows','mysql_numfields','mysql_num_rows','mysql_num_fields','mysql_listtables','mysql_listfields',
+                       'mysql_listdbs','mysql_list_tables','mysql_list_processes','mysql_list_fields','mysql_list_dbs','mysql_insert_id',
+                       'mysql_info','mysql_get_server_info','mysql_get_proto_info','mysql_get_host_info','mysql_get_client_info','mysql_freeresult',
+                       'mysql_free_result','mysql_fieldtype','mysql_fieldtable','mysql_fieldname','mysql_fieldlen','mysql_fieldflags',
+                       'mysql_field_type','mysql_field_table','mysql_field_seek','mysql_field_name','mysql_field_len','mysql_field_flags',
+                       'mysql_fetch_row','mysql_fetch_object','mysql_fetch_lengths','mysql_fetch_field','mysql_fetch_assoc','mysql_fetch_array',
+                       'mysql_escape_string','mysql_error','mysql_errno','mysql_dropdb','mysql_drop_db','mysql_dbname',
+                       'mysql_db_query','mysql_db_name','mysql_data_seek','mysql_createdb','mysql_create_db','mysql_connect',
+                       'mysql_close','mysql_client_encoding','mysql_affected_rows','mysql','mt_srand','mt_rand',
+                       'mt_getrandmax','move_uploaded_file','money_format','mktime','mkdir','min',
+                       'microtime','method_exists','metaphone','memory_get_usage','md5_file','md5',
+                       'mbsubstr','mbstrrpos','mbstrpos','mbstrlen','mbstrcut','mbsplit',
+                       'mbregex_encoding','mberegi_replace','mberegi','mbereg_search_setpos','mbereg_search_regs','mbereg_search_pos',
+                       'mbereg_search_init','mbereg_search_getregs','mbereg_search_getpos','mbereg_search','mbereg_replace','mbereg_match',
+                       'mbereg','mb_substr_count','mb_substr','mb_substitute_character','mb_strwidth','mb_strtoupper',
+                       'mb_strtolower','mb_strrpos','mb_strpos','mb_strlen','mb_strimwidth','mb_strcut',
+                       'mb_split','mb_send_mail','mb_regex_set_options','mb_regex_encoding','mb_preferred_mime_name','mb_parse_str',
+                       'mb_output_handler','mb_language','mb_internal_encoding','mb_http_output','mb_http_input','mb_get_info',
+                       'mb_eregi_replace','mb_eregi','mb_ereg_search_setpos','mb_ereg_search_regs','mb_ereg_search_pos','mb_ereg_search_init',
+                       'mb_ereg_search_getregs','mb_ereg_search_getpos','mb_ereg_search','mb_ereg_replace','mb_ereg_match','mb_ereg',
+                       'mb_encode_numericentity','mb_encode_mimeheader','mb_detect_order','mb_detect_encoding','mb_decode_numericentity','mb_decode_mimeheader',
+                       'mb_convert_variables','mb_convert_kana','mb_convert_encoding','mb_convert_case','max','mail',
+                       'magic_quotes_runtime','ltrim','lstat','long2ip','log1p','log10',
+                       'log','localtime','localeconv','linkinfo','link','levenshtein',
+                       'lcg_value','ksort','krsort','key_exists','key','juliantojd',
+                       'join','jewishtojd','jdtounix','jdtojulian','jdtojewish','jdtogregorian',
+                       'jdtofrench','jdmonthname','jddayofweek','is_writeable','is_writable','is_uploaded_file',
+                       'is_subclass_of','is_string','is_scalar','is_resource','is_real','is_readable',
+                       'is_object','is_numeric','is_null','is_nan','is_long','is_link',
+                       'is_integer','is_int','is_infinite','is_float','is_finite','is_file',
+                       'is_executable','is_double','is_dir','is_callable','is_bool','is_array',
+                       'is_a','iptcparse','iptcembed','ip2long','intval','ini_set',
+                       'ini_restore','ini_get_all','ini_get','ini_alter','in_array','import_request_variables',
+                       'implode','image_type_to_mime_type','ignore_user_abort','iconv_set_encoding','iconv_get_encoding','iconv',
+                       'i18n_mime_header_encode','i18n_mime_header_decode','i18n_ja_jp_hantozen','i18n_internal_encoding','i18n_http_output','i18n_http_input',
+                       'i18n_discover_encoding','i18n_convert','hypot','htmlspecialchars','htmlentities','html_entity_decode',
+                       'highlight_string','highlight_file','hexdec','hebrevc','hebrev','headers_sent',
+                       'header','gzwrite','gzuncompress','gztell','gzseek','gzrewind',
+                       'gzread','gzputs','gzpassthru','gzopen','gzinflate','gzgetss',
+                       'gzgets','gzgetc','gzfile','gzeof','gzencode','gzdeflate',
+                       'gzcompress','gzclose','gregoriantojd','gmstrftime','gmmktime','gmdate',
+                       'glob','gettype','gettimeofday','gettext','getservbyport','getservbyname',
+                       'getrusage','getrandmax','getprotobynumber','getprotobyname','getopt','getmyuid',
+                       'getmypid','getmyinode','getmygid','getmxrr','getlastmod','getimagesize',
+                       'gethostbynamel','gethostbyname','gethostbyaddr','getenv','getdate','getcwd',
+                       'getallheaders','get_resource_type','get_required_files','get_parent_class','get_object_vars','get_meta_tags',
+                       'get_magic_quotes_runtime','get_magic_quotes_gpc','get_loaded_extensions','get_included_files','get_include_path','get_html_translation_table',
+                       'get_extension_funcs','get_defined_vars','get_defined_functions','get_defined_constants','get_declared_classes','get_current_user',
+                       'get_class_vars','get_class_methods','get_class','get_cfg_var','get_browser','fwrite',
+                       'function_exists','func_num_args','func_get_args','func_get_arg','ftruncate','ftp_systype',
+                       'ftp_ssl_connect','ftp_size','ftp_site','ftp_set_option','ftp_rmdir','ftp_rename',
+                       'ftp_rawlist','ftp_quit','ftp_pwd','ftp_put','ftp_pasv','ftp_nlist',
+                       'ftp_nb_put','ftp_nb_get','ftp_nb_fput','ftp_nb_fget','ftp_nb_continue','ftp_mkdir',
+                       'ftp_mdtm','ftp_login','ftp_get_option','ftp_get','ftp_fput','ftp_fget',
+                       'ftp_exec','ftp_delete','ftp_connect','ftp_close','ftp_chdir','ftp_cdup',
+                       'ftok','ftell','fstat','fsockopen','fseek','fscanf',
+                       'frenchtojd','fread','fputs','fpassthru','fopen','fnmatch',
+                       'fmod','flush','floor','flock','floatval','filetype',
+                       'filesize','filepro_rowcount','filepro_retrieve','filepro_fieldwidth','filepro_fieldtype','filepro_fieldname',
+                       'filepro_fieldcount','filepro','fileperms','fileowner','filemtime','fileinode',
+                       'filegroup','filectime','fileatime','file_get_contents','file_exists','file',
+                       'fgetss','fgets','fgetcsv','fgetc','fflush','feof',
+                       'fclose','ezmlm_hash','extract','extension_loaded','expm1','explode',
+                       'exp','exif_thumbnail','exif_tagname','exif_read_data','exif_imagetype','exec',
+                       'escapeshellcmd','escapeshellarg','error_reporting','error_log','eregi_replace','eregi',
+                       'ereg_replace','ereg','end','easter_days','easter_date','each',
+                       'doubleval','dngettext','dl','diskfreespace','disk_total_space','disk_free_space',
+                       'dirname','dir','dgettext','deg2rad','defined','define_syslog_variables',
+                       'define','decoct','dechex','decbin','debug_zval_dump','debug_backtrace',
+                       'deaggregate','dcngettext','dcgettext','dba_sync','dba_replace','dba_popen',
+                       'dba_optimize','dba_open','dba_nextkey','dba_list','dba_insert','dba_handlers',
+                       'dba_firstkey','dba_fetch','dba_exists','dba_delete','dba_close','date',
+                       'current','ctype_xdigit','ctype_upper','ctype_space','ctype_punct','ctype_print',
+                       'ctype_lower','ctype_graph','ctype_digit','ctype_cntrl','ctype_alpha','ctype_alnum',
+                       'crypt','create_function','crc32','count_chars','count','cosh',
+                       'cos','copy','convert_cyr_string','constant','connection_status','connection_aborted',
+                       'compact','closelog','closedir','clearstatcache','class_exists','chunk_split',
+                       'chr','chown','chop','chmod','chgrp','checkdnsrr',
+                       'checkdate','chdir','ceil','call_user_method_array','call_user_method','call_user_func_array',
+                       'call_user_func','cal_to_jd','cal_info','cal_from_jd','cal_days_in_month','bzwrite',
+                       'bzread','bzopen','bzflush','bzerrstr','bzerror','bzerrno',
+                       'bzdecompress','bzcompress','bzclose','bindtextdomain','bindec','bind_textdomain_codeset',
+                       'bin2hex','bcsub','bcsqrt','bcscale','bcpow','bcmul',
+                       'bcmod','bcdiv','bccomp','bcadd','basename','base_convert',
+                       'base64_encode','base64_decode','atanh','atan2','atan','assert_options',
+                       'assert','asort','asinh','asin','arsort','array_walk',
+                       'array_values','array_unshift','array_unique','array_sum','array_splice','array_slice',
+                       'array_shift','array_search','array_reverse','array_reduce','array_rand','array_push',
+                       'array_pop','array_pad','array_multisort','array_merge_recursive','array_merge','array_map',
+                       'array_keys','array_key_exists','array_intersect_assoc','array_intersect','array_flip','array_filter',
+                       'array_fill','array_diff_assoc','array_diff','array_count_values','array_chunk','array_change_key_case',
+                       'apache_setenv','apache_response_headers','apache_request_headers','apache_note','apache_lookup_uri','apache_get_version',
+                       'apache_child_terminate','aggregation_info','aggregate_properties_by_regexp','aggregate_properties_by_list','aggregate_properties','aggregate_methods_by_regexp',
+                       'aggregate_methods_by_list','aggregate_methods','aggregate','addslashes','addcslashes','acosh',
+                       'acos','abs','_','echo', 'print', 'global', 'static', 'exit', 'array', 'empty', 'eval', 'isset', 'unset', 'die'
+                       )
+               ),
+       'SYMBOLS' => array(
+               '(', ')', '[', ']', '{', '}', '!', '@', '%', '&', '*', '|', '/', '<', '>'
+               ),
+       'CASE_SENSITIVE' => array(
+               GESHI_COMMENTS => false,
+               1 => false,
+               2 => false,
+               3 => false,
+               ),
+       'STYLES' => array(
+               'KEYWORDS' => array(
+                       1 => 'color: #b1b100;',
+                       2 => 'color: #000000; font-weight: bold;',
+                       3 => 'color: #000066;'
+                       ),
+               'COMMENTS' => array(
+                       1 => 'color: #808080; font-style: italic;',
+                       2 => 'color: #808080; font-style: italic;',
+                       'MULTI' => 'color: #808080; font-style: italic;'
+                       ),
+               'ESCAPE_CHAR' => array(
+                       0 => 'color: #000099; font-weight: bold;'
+                       ),
+               'BRACKETS' => array(
+                       0 => 'color: #66cc66;'
+                       ),
+               'STRINGS' => array(
+                       0 => 'color: #ff0000;'
+                       ),
+               'NUMBERS' => array(
+                       0 => 'color: #cc66cc;'
+                       ),
+               'METHODS' => array(
+                       0 => 'color: #006600;'
+                       ),
+               'SYMBOLS' => array(
+                       0 => 'color: #66cc66;'
+                       ),
+               'REGEXPS' => array(
+                       0 => 'color: #0000ff;'
+                       ),
+               'SCRIPT' => array(
+                       0 => '',
+                       1 => '',
+                       2 => '',
+                       3 => ''
+                       )
+               ),
+       'URLS' => array(
+               1 => '',
+               2 => '',
+               3 => 'http://www.php.net/{FNAME}',
+               4 => ''
+               ),
+       'OOLANG' => true,
+       'OBJECT_SPLITTER' => '-&gt;',
+       'REGEXPS' => array(
+               0 => "[\\$]{1,2}[a-zA-Z_][a-zA-Z0-9_]*"
+               ),
+       'STRICT_MODE_APPLIES' => GESHI_MAYBE,
+       'SCRIPT_DELIMITERS' => array(
+               0 => array(
+                       '<?php' => '?>'
+                       ),
+               1 => array(
+                       '<?' => '?>'
+                       ),
+               2 => array(
+                       '<%' => '%>'
+                       ),
+               3 => array(
+                       '<script language="php">' => '</script>'
+                       )
+               ),
+       'HIGHLIGHT_STRICT_BLOCK' => array(
+               0 => true,
+               1 => true,
+               2 => true,
+               3 => true
+               )
+);
+
+?>
+
+If you're remotely familiar with PHP (or even if you're not), you can see that all that a language file consists of is a glorified variable assignment. Easy! All a language file does is assign a variable $language_data. Though still, there's a lot of indices to that array... but this section is here to break each index down and explain it to you.
+4.2: Language File Conventions
+Top | Contents | Next | Previous
+
+There are several conventions that are used in language files. For ease of use and readability, your language files should obey the following rules:
+
+    * Indentation is in tabs, not spaces: Use tabs! There's no excuse for using spaces in this day and age, where almost every good editor allows you to change the tab width. Tabs also take up less space, and ensure proper alignment. When you indent, use tabs, and if your editor converts tabs to spaces, tell it not to.
+    * Strings are in single quotes: Every string in a language file should be in single quotes ('), unless you are specifying a single quote as a quotemark or escape character, in which case they can be in double quotes for readability; or if you are specifying a REGEXP (see below)
+    * Large arrays are multi-lined: An array with more than three or four values should be broken into multiple lines. In any case, lines should not be wider than a full-screen window (about 100 chars per line max).
+    * Ending brackets for multi-lined arrays on a new line: Also with a comma after them, unless the array is the last one in a parent array. See the PHP language file for examples of where to use commas.
+    * Use GeSHi's constants: For capatalisation, regular expressions etc. use the GeSHi constants, not their actual values.
+
+There are more notes on each convention where it may appear in the language file sections below.
+4.3: Language File Sections
+Top | Contents | Next | Previous
+
+This section will look at all the sections of a language file, and how they relate to the final highlighting result.
+4.3.1: The Header
+Top | Contents | Next | Previous
+
+The header of a language file is the first lines with the big comment and the start of the variable $language_data:
+
+<?php
+/*************************************************************************************
+ * <name-of-language-file.php>
+ * ---------------------------------
+ * Author: <name> (<e-mail address>)
+ * Copyright: (c) 2004 <name> (<website URL>)
+ * Release Version: 1.0.0
+ * CVS Revision Version: $Revision: 1196 $
+ * Date Started: <date started>
+ * Last Modified: $Date: 2008-06-08 17:55:42 +0000 (So, 08. Jun 2008) $
+ *
+ * <name-of-language> language file for GeSHi.
+ *
+ * <any-comments...>
+ *
+ * CHANGES
+ * -------
+ * <date-of-release> (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated <date-of-release>)
+ * -------------------------
+ * <things-to-do>
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+
+The parts in angle brackets are the parts that you change for your language file. Everything else *must* remain the same!
+
+Here are the parts you should change:
+
+    * <name-of-language-file.php> - This should become the name of your language file. Language file names are in lower case and contain only alphanumeric characters, dashes and underscores. Language files end with .php (which you should put with the name of your language file, eg language.php)
+    * <name> - Your name, or alias.
+    * <e-mail address> - Your e-mail address. If you want your language file included with GeSHi you must include an e-mail address that refers to an inbox controlled by you.
+    * <website> - A URL of a website of yours (perhaps to a page that deals with your contribution to GeSHi, or your home page/blog)
+    * <date-started> - The date you started working on the language file. If you can't remember, guestimate.
+    * <name-of-language> - The name of the language you made this language file for (probably similar to the language file name).
+    * <any-comments> - Any comments you have to make about this language file, perhaps on where you got the keywords for, what dialect of the language this language file is for etc etc. If you don't have any comments, remove the space for them.
+    * <date-of-release - The date you released the language file to the public. If you simply send it to me for inclusion in a new GeSHi and don't release it, leave this blank, and I'll replace it with the date of the GeSHi release that it is first added to.
+
+Everything should remain the same, including $Revision: 1196 $ and $Date: 2008-06-08 17:55:42 +0000 (So, 08. Jun 2008) $ (I know these may look funny but they have their purpose for those of you who don't know about SVN).
+
+Also: I'm not sure about the copyright on a new language file. I'm not a lawyer, could someone contact me about whether the copyright for a new language file should be exclusivly the authors, or joint with me (if included in a GeSHi release)?
+4.3.2: The First Indices
+Top | Contents | Next | Previous
+
+Here is an example from the php language file of the first indices:
+
+       'LANG_NAME' => 'PHP',
+       'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
+       'COMMENT_MULTI' => array('/*' => '*/'),
+       'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+       'QUOTEMARKS' => array("'", '"'),
+       'ESCAPE_CHAR' => '\\',
+
+The first indices are the first few lines of a language file before the KEYWORDS index. These indices specify:
+
+    * 'LANG_NAME': The name of the language. This name should be a human-readable version of the name (e.g. HTML 4 (transitional) instead of html4trans)
+    * 'COMMENT_SINGLE': An array of single-line comments in your language, indexed by integers starting from 1. A single line comment is a comment that starts at the marker and goes until the end of the line. These comments may be any length > 0, and since they can be styled individually, can be used for other things than comments (for example the Java language file defines "import" as a single line comment). If you are making a language that uses a ' (apostrophe) as a comment (or in the comment marker somewhere), use double quotes. e.g.: "'"
+    * 'COMMENT_MULTI': Used to specify multiline comments, an array in the form 'OPEN' => 'CLOSE'. Unfortunately, all of these comments you add here will be styled the same way (an area of improvement for GeSHi 1.2.X). These comment markers may be any length > 0.
+    * 'CASE_KEYWORDS': Used to set whether the case of keywords should be changed automatically as they are found. For example, in an SQL or BASIC dialect you may want all keywords to be upper case. The accepted values for this are:
+          o GESHI_CAPS_UPPER: Convert the case of all keywords to upper case.
+          o GESHI_CAPS_LOWER: Convert the case of all keywords to lower case.
+          o GESHI_CAPS_NO_CHANGE: Don't change the case of any keyword.
+    * 'QUOTEMARKS': Specifies the characters that mark the beginning and end of a string. This is another example where if your language includes the ' string delimiter you should use double quotes around it.
+    * 'ESCAPE_CHAR': Specifies the escape character used in all strings. If your language does not have an escape character then make this the empty string (''). This is not an array! If found, any character after an escape character and the escape character itself will be highlighted differently, and the character after the escape character cannot end a string.
+
+4.3.3: Keywords
+Top | Contents | Next | Previous
+
+Keywords will make up the bulk of a language file. In this part you add keywords for your language, including inbuilt functions, data types, predefined constants etc etc.
+
+Here's a (shortened) example from the php language file:
+
+       'KEYWORDS' => array(
+               1 => array(
+                       'include', 'require', 'include_once', 'require_once',
+                       'for', 'foreach', 'as', 'if', 'elseif', 'else', 'while', 'do', 'endwhile', 'endif', 'switch', 'case', 'endswitch',
+                       'return', 'break'
+                       ),
+               2 => array(
+                       'null', '__LINE__', '__FILE__',
+                       'false', '<?php', '?>', '<?',
+                       '<script language=', '</script>',
+                       'true', 'var', 'default',
+                       'function', 'class', 'new',
+                       '__FUNCTION__', '__CLASS__', '__METHOD__', 'PHP_VERSION',
+                       'PHP_OS', 'DEFAULT_INCLUDE_PATH', 'PEAR_INSTALL_DIR', 'PEAR_EXTENSION_DIR',
+                       'PHP_EXTENSION_DIR', 'PHP_BINDIR', 'PHP_LIBDIR', 'PHP_DATADIR', 'PHP_SYSCONFDIR',
+                       'PHP_LOCALSTATEDIR', 'PHP_CONFIG_FILE_PATH', 'PHP_OUTPUT_HANDLER_START', 'PHP_OUTPUT_HANDLER_CONT',
+                       'PHP_OUTPUT_HANDLER_END', 'E_ERROR', 'E_WARNING', 'E_PARSE', 'E_NOTICE',
+                       'E_CORE_ERROR', 'E_CORE_WARNING', 'E_COMPILE_ERROR', 'E_COMPILE_WARNING', 'E_USER_ERROR',
+                       'E_USER_WARNING', 'E_USER_NOTICE', 'E_ALL'
+                       ),
+               3 => array(
+                       'zlib_get_coding_type','zend_version','zend_logo_guid','yp_order','yp_next',
+                       'yp_match','yp_master','yp_get_default_domain','yp_first','yp_errno','yp_err_string',
+                       'yp_cat','yp_all','xml_set_unparsed_entity_decl_handler','xml_set_start_namespace_decl_handler','xml_set_processing_instruction_handler','xml_set_object',
+                       'xml_set_notation_decl_handler','xml_set_external_entity_ref_handler','xml_set_end_namespace_decl_handler','xml_set_element_handler','xml_set_default_handler','xml_set_character_data_handler',
+                       'xml_parser_set_option','xml_parser_get_option','xml_parser_free','xml_parser_create_ns','xml_parser_create','xml_parse_into_struct'
+                       )
+               ),
+
+You can see that the index 'KEYWORDS' refers to an array of arrays, indexed by positive integers. In each array, there are some keywords (in the actual php language file there is in fact many more keywords in the array indexed by 3). Here are some points to note about these keywords:
+
+    * Indexed by positive integers: Use nothing else! I may change this in 1.2.X, but for the 1.0.X series, use positive integers only.
+    * Keywords sorted in reverse: Keywords *should* be sorted in reverse order. I know that many of the language files I've made do not follow this rule, but that's because I made the files before I discovered the following issue with GeSHi: If you have two keywords, as and ascfor example, then when GeSHi encounters the "as" keyword it will be highlighted even if the "as" is part of "asc". I would get GeSHi to reverse-sort keyword arrays, but there's no harm in you doing this yourself and saving some processing time. At the least (and in fact this is sufficient) you should swap any keywords you come across that would be caught by this issue.
+    * Keywords are case sensitive (sometimes): If your language is case-sensitive, the correct casing of the keywords is defined as the case of the keywords in these keyword arrays. If you check the java language file you will see that everything is in exact casing. So if any of these keyword arrays are case sensitive, put the keywords in as their correct case! (note that which groups are case sensitive and which are not is configurable, see later on)
+    * Keywords must be in htmlentities() form: All keywords should be written as if they had been run through the php function htmlentities(). E.g, the keyword is &lt;foo&gt;, not <foo>
+    * Don't use keywords to highlight symbols: Just don't. It doesn't work, and there will be seperate support for symbols later.
+    * Markup Languages are special cases: Check the html4strict language file for an example: keywords have to be specified twice for opening tags and twice for each closing tag.
+
+4.3.4: Symbols and Case Sensitivity
+Top | Contents | Next | Previous
+
+So you've put all the keywords for your language in? Now for a breather before we style them :). Symbols define what symbols your language uses, these are things like colons, brackets/braces, and other such general punctuation, and case sensitivity alludes to the previous section: here you can set which keyword groups are case sensitive.
+
+As of GeSHi version 1.0.7.21 the symbols section is used in two ways:
+
+    * Flat usage:
+      This mode is the suggested way for existing language files and languages that only need few symbols where no further differentiation is needed or desired. You simply put all the characters in an array under symbols as shown in the first example below. All symbols in flat usage belong to symbol style group 0.
+    * Group usage:
+      This is a slightly more enhanced way to provide GeSHi symbol information. To use group you create several subarrays each containing only a subset of the symbols to highlight. Every array will need to have an unique index thus you can assign the appropriate styles later.
+
+Here's an example for flat symbol usage
+
+       'SYMBOLS' => array(
+               '(', ')', '[', ']', '{', '}', '!', '@', '|', '&', '+', '-', '*', '/', '%', '=', '<', '>'
+               ),
+       'CASE_SENSITIVE' => array(
+               GESHI_COMMENTS => false,
+               1 => false,
+               2 => false,
+               3 => false,
+               ),
+
+which is not too different from the newly introduced group usage shown below:
+
+       'SYMBOLS' => array(
+               0 => array('(', ')', '[', ']', '{', '}'),
+               1 => array('!', '@', '|', '&'),
+               2 => array('+', '-', '*', '/', '%'),
+               3 => array('=', '<', '>')
+               ),
+       'CASE_SENSITIVE' => array(
+               GESHI_COMMENTS => false,
+               1 => false,
+               2 => false,
+               3 => false,
+               ),
+
+    * 'SYMBOLS': An array of the symbols, or - as of 1.0.7.21 - an array of symbol groups, used in your language. Please note that versions before 1.0.7.21 will silently ignore this setting.
+    * 'CASE_SENSITIVE': Note the GESHI_COMMENTS! This is used to set whether comments are case sensitive or not (for example, BASIC has the REM statement which while not being case sensitive is still alphanumeric, and as in the example given before about the Java language file using "import" as a single line comment, this can be useful sometimes. true if comments are case sensitive, false otherwise. All of the other indices correspond to indices in the 'KEYWORDS' section (see above).
+
+4.3.5: Styles for your Language File
+Top | Contents | Next | Previous
+
+This is the fun part! Here you get to choose the colours, fonts, backgrounds and anything else you'd like for your language file.
+
+Here's an example:
+
+       'STYLES' => array(
+               'KEYWORDS' => array(
+                       1 => 'color: #b1b100;',
+                       2 => 'color: #000000; font-weight: bold;',
+                       3 => 'color: #000066;'
+                       ),
+               'COMMENTS' => array(
+                       1 => 'color: #808080; font-style: italic;',
+                       2 => 'color: #808080; font-style: italic;',
+                       'MULTI' => 'color: #808080; font-style: italic;'
+                       ),
+               'ESCAPE_CHAR' => array(
+                       0 => 'color: #000099; font-weight: bold;'
+                       ),
+               'BRACKETS' => array(
+                       0 => 'color: #66cc66;'
+                       ),
+               'STRINGS' => array(
+                       0 => 'color: #ff0000;'
+                       ),
+               'NUMBERS' => array(
+                       0 => 'color: #cc66cc;'
+                       ),
+               'METHODS' => array(
+                       0 => 'color: #006600;'
+                       ),
+               'SYMBOLS' => array(
+                       0 => 'color: #66cc66;'
+                       ),
+               'REGEXPS' => array(
+                       0 => 'color: #0000ff;'
+                       ),
+               'SCRIPT' => array(
+                       0 => '',
+                       1 => '',
+                       2 => '',
+                       3 => ''
+                       )
+               ),
+
+Note that all style rules should end with a semi-colon! This is important: GeSHi may add extra rules to the rules you specify (and will do so if a user tries to change your styles on the fly), so the last semi-colon in any stylesheet rule is important.
+
+All strings here should contain valid stylesheet declarations (it's also find to have the empty string).
+
+    * 'KEYWORDS': This is an array, from keyword index to style. The index you use is the index you used in the keywords section to specify the keywords belonging to that group.
+    * 'COMMENTS': This is an array, from single-line comment index to style for that index. The index 'MULTI' is used for multiline comments (and cannot be an array)
+    * 'ESCAPE_CHAR' down to 'SYMBOLS': These are arrays with only one index: 0. You cannot add other indices to these arrays.
+    * 'REGEXPS':This is an array with a style for each matching regex. Also, since 1.0.7.21, you can specify the name of a function to be called, that will be given the text matched by the regex, each time a match is found. Note that my testing found that create_function would not work with this due to a PHP bug, so you have to put the function definition at the top of the language file. Be sure to prefix the function name with geshi_[languagename]_ as to not conflict with other functions!
+    * 'SCRIPT': For languages that use script delimiters, this is where you can style each block of script. For example, HTML and XML have blocks that begin with < and end with > (i.e. tags) and blocks that begin with & and end with ; (i.e. character entities), and you can set a style to apply to each whole block. You specify the delimiters for the blocks below. Note that many languages will not need this feature.
+
+4.3.6: URLs for Functions
+Top | Contents | Next | Previous
+
+This section lets you specify a url to visit for each keyword group. Useful for pointing functions at their online manual entries.
+
+Here is an example:
+
+       'URLS' => array(
+               1 => '',
+               2 => '',
+               3 => 'http://www.php.net/{FNAME}',
+               4 => ''
+               ),
+
+The indices of this array correspond to the keyword groups you specified in the keywords section. The string {FNAME} marks where the name of the function is substituted in. So for the example above, if the keyword being highlighted is "echo", then the keyword will be a URL pointing to http://www.php.net/echo. Because some languages (Java!) don't keep a uniform URL for functions/classes, you may have trouble in creating a URL for that language (though look in the java language file for a novel solution to it's problem)
+4.3.7: Object Orientation Support
+Top | Contents | Next | Previous
+
+Now we're reaching the most little-used section of a language file, which includes such goodies as object orientation support and context support. GeSHi can highlight methods and data fields of objects easily, all you need to do is to tell it to do so and what the "splitter" is between object/method etc.
+
+Here's an example:
+
+       'OOLANG' => true,
+       'OBJECT_SPLITTER' => '->',
+
+If your language has object orientation, the value of 'OOLANG' is true, otherwise it is false. If it is object orientated, in the 'OBJECT_SPLITTER' value you put the htmlentities() version of the "splitter" between objects and methods/fields. If it is not, then make this the empty string.
+4.3.8: Using Regular Expressions
+Top | Contents | Next | Previous
+
+Regular expressions are a good way to catch any other lexic that fits certain rules but can't be listed as a keyword. A good example is variables in PHP: variables always start with either one or two "$" signs, then alphanumeric characters (a simplification). This is easy to catch with regular expressions.
+
+And new to version 1.0.2, there is an advanced way of using regular expressions to catch certain things but highlight only part of those things. This is particularly useful for languages like XML.
+Caution:
+
+Regular expressions use the PCRE syntax (perl-style), not the ereg() style!
+
+Here is an example (this time the PHP file merged with the XML file):
+
+               0 => array(
+                       GESHI_SEARCH => '(((xml:)?[a-z\-]+))(=)',
+                       GESHI_REPLACE => '\\1',
+                       GESHI_MODIFIERS => '',
+                       GESHI_BEFORE => '',
+                       GESHI_AFTER => '\\4'
+                       ),
+               1 => array(
+                       GESHI_SEARCH => '(>/?[a-z0-9]*(>)?)',
+                       GESHI_REPLACE => '\\1',
+                       GESHI_MODIFIERS => '',
+                       GESHI_BEFORE => '',
+                       GESHI_AFTER => ''
+                       ),
+               2 => "[\\$]{1,2}[a-zA-Z_][a-zA-Z0-9_]*"
+
+As you can see there are two formats. One is the "simple" format used in GeSHi < 1.0.2, and the other is a more advanced syntax. Firstly, the simple syntax:
+
+    * May be in double quotes: To make it easier for those who always place their regular expressions in double quotes, you may place any regular expression here in double quotes if you wish.
+    * Don't use curly brackets where possible: If you want to use curly brackets (()) then by all means give it a try, but I'm not sure whether under some circumstances GeSHi may throw a wobbly. You have been warned! If you want to use brackets, it would be better to use the advanced syntax.
+    * Don't use the "everything" regex: (That's the .*? regex). Use advanced syntax instead.
+
+And now for advanced syntax, which gives you much more control over exactly what is highlighted:
+
+    * GESHI_SEARCH: This element specifies the regular expression to search for. If you plan to capture the output, use brackets (()). See how in the first example above, most of the regular expression is in one set of brackets (with the equals sign in other brackets). You should make sure that the part of the regular expression that is supposed to match what is highlighted is in brackets.
+    * GESHI_REPLACE: This is what the stuff matched by the regular expression will be replaced with. If you've grouped the stuff you want highlighted into brackets in the GESHI_SEARCH element, then you can use \\number to match that group, where number is a number corresponding to how many open brackets are between the open bracket of the group you want highlighted and the start of the GESHI_SEARCH string + 1. This may sound confusing, and it probably is, but if you're familiar with how PHP's regular expressions work you should understand. In the example above, the opening bracket for the stuff we want highlighted is the very first bracket in the string, so the number of brackets before that bracket and the start of the string is 0. So we add 1 and get our replacement string of \\1 (whew!).
+
+      If you didn't understand a word of that, make sure that there are brackets around the string in GESHI_SEARCH and use \\1 for GESHI_REPLACE ;)
+    * GESHI_MODIFIERS: Specify modifiers for your regular expression. If your regular expression includes the everything matcher (.*?), then your modifiers should include "s" and "i" (e.g. use 'si' for this).
+    * GESHI_BEFORE:Specifies a bracket group that should appear before the highlighted match (this bracketed group will not be highlighted). Use this if you had to match what you wanted by matching part of your regexp string to something before what you wanted to highlight, and you don't want that part to disappear in the highlighted result.
+    * GESHI_AFTER:Specifies a bracket group that should appear after the highlighted match (this bracketed group will not be highlighted). Use this if you had to match what you wanted by matching part of your regexp string to something after what you wanted to highlight, and you don't want that part to disappear in the highlighted result.
+
+Is that totally confusing? Here's the test for if you're an android or not: If you found that perfectly understandable then you're an android ;). Here's a better example:
+
+Let's say that I'm making a language, and variables in this language always start with a dollar sign ($), are always written in lowercase letters and always end with an ampersand (&). eg:
+$foo& = 'bar'
+
+I want to highlight only the text between the $ and the &. How do I do that? With simple regular expressions I can't, but with advanced, it's relatively easy:
+
+               1 => array(
+                       GESHI_SEARCH => '(\$)([a-z]+)(&)',   // search for a dollar sign, then one or more of the characters a-z, then an ampersand
+                       GESHI_REPLACE => '\\2',                  // we wanna highlight the characters, which are in the second bracketed group
+                       GESHI_MODIFIERS => '',                   // no modifiers, since we're not matching the "anything" regex
+                       GESHI_BEFORE => '\\1',                   // before the highlighted characters should be the first bracketed group (always a dollar sign in this example)
+                       GESHI_AFTER => '\\3'                     // after the highlighted characters should be the third bracketed group (always an ampersand in this example)
+                       ),
+
+So if someone tried to highlight using my language, all cases of $foo& would turn into:
+$<span style="color: blue;">foo</span>&
+
+(which would of course be viewed in a browser to get something like $foo&)
+4.3.9: Contextual Highlighting and Strict Mode
+Top | Contents | Next | Previous
+
+For languages like HTML, it's good if we can highlight a tag (like <a> for example). But how do we stop every single "a" in the source getting highlighted? What about for attributes? If I've got the word "colspan" in my text I don't want that highlighted! So how do you tell GeSHi not to highlight in that case? You do it with "Strict Blocks".
+
+Here is an example:
+
+       'STRICT_MODE_APPLIES' => GESHI_MAYBE,
+       'SCRIPT_DELIMITERS' => array(
+               0 => array(
+                       '<?php' => '?>'
+                       ),
+               1 => array(
+                       '<?' => '?>'
+                       ),
+               2 => array(
+                       '<%' => '%>'
+                       ),
+               3 => array(
+                       '<script language="php">' => '</script>'
+                       )
+               ),
+       'HIGHLIGHT_STRICT_BLOCK' => array(
+               0 => true,
+               1 => true,
+               2 => true,
+               3 => true
+               )
+
+What is strict mode? Strict mode says that highlighting only occurs inside the blocks you specify. You can see from the example above that highlighting will only occur if the source is inside <?php ... ?> (though note the GESHI_MAYBE!). Here are some points about strict highlighting:
+
+    * 'STRICT_MODE_APPLIES': This takes three values (all constants):
+          o GESHI_ALWAYS: Strict mode always applies for all of the blocks you specify. Users of your language file cannot turn strict mode off. This should be used for markup languages.
+          o GESHI_NEVER: Strict mode is never used. Users of your language file cannot turn strict mode on. Use this value if there is no such thing as a block of code that would not be highlighted in your language (most languages, like C, Java etc. use this because anything in a C file should be highlighted).
+          o GESHI_MAYBE: Strict mode *sometimes* applies. It defaults to "off". Users can turn strict mode on if they please. If strict mode is off then everything in the source will be highlighted, even things outside the strict block markers. If strict mode is on the nothing outside strict block markers will be highlighted.
+    * SCRIPT_DELIMITERS: This is an array of script delimiters, in the format of the above. The indices are use in the 'SCRIPT' part of the styles section for highlighting everything in a strict block in a certain way. For example, you could set up your language file to make the background yellow of any code inside a strict block this way. The delimiters are in the form 'OPEN' => 'CLOSE'. Delimiters can be of any length > 0. Delimiters are not formatted as if they were run through htmlentities()!
+    * 'HIGHLIGHT_STRICT_BLOCK': specifies whether any highlighting should go on inside each block. Most of the time this should be true, but for example, in the XML language file highlighting is turned off for blocks beginning with <!DOCTYPE and ending with >. However, you can still style the overall block using the method described above, and the XML language file does just that.
+
+Note:
+
+The delimiters should be in reverse alphabetical order. Note that in the above example, <?php comes before <?.
+4.3.10: Tidying Up
+Top | Contents | Next | Previous
+
+All language files should end with:
+
+);
+
+?>
+
+5: Method/Constant Reference
+Top | Contents | Next | Previous
+
+I'm afraid I have been lying for a little while about this now! Since 1.0.7 I have been including a phpdoc API for the sourcecode in the api directory, but have forgot to update the documentation! However, it is available, and may assist you in coding, especially for plugin coders.
+
+That's all, folks!
+
+I've improved the documentation greatly from version 1.0.1, but there may still be problems with it, or it may still be confusing for you. Or perhaps I was just plain wrong about one point! If so, contact me and I'll do my best to sort it out.
+
+In case you were wondering, I've finished development of the 1.0.X thread of GeSHi. The only releases I'll make in this thread will be of the bug-fix/add language files type. In particular, version 1.0.2 was a "concept" release - testing how far I could take the highlighting idea (as well as ideas from others).
+
+I'm planning a code rewrite for 1.2.X, which will be based on a new engine - a "psuedo-tokenizer" engine. Hopefully it will massively reduce the server load and time taken (by almost eliminating regexps), while providing superior highlighting. But fear not! The interface and method names should all remain the same ^_^ (though I can't say the same for language files!)
+
+And finally, a couple of people have been asking me: how did you generate that documentation? The amazing answer is: my brain. And yes, it took a long time, and I don't reccommend doing it this way. And yes, you can borrow the styles if you like, though flick me an e-mail if you do.
+
+Anyway, enough blather from me. Get GeSHi working for you already! :D
+
+Nigel McNie
+nigel@geshi.org
+http://qbnz.com/highlighter/
diff --git a/examples/includes/geshi/docs/phpdoc.ini b/examples/includes/geshi/docs/phpdoc.ini
new file mode 100644 (file)
index 0000000..a55bc33
--- /dev/null
@@ -0,0 +1,90 @@
+;; phpDocumentor parse configuration file
+;;
+;; This file is designed to cut down on repetitive typing on the command-line or web interface
+;; You can copy this file to create a number of configuration files that can be used with the
+;; command-line switch -c, as in phpdoc -c default.ini or phpdoc -c myini.ini.  The web
+;; interface will automatically generate a list of .ini files that can be used.
+;;
+;; default.ini is used to generate the online manual at http://www.phpdoc.org/docs
+;;
+;; ALL .ini files must be in the user subdirectory of phpDocumentor with an extension of .ini
+;;
+;; Copyright 2002, Greg Beaver <cellog@users.sourceforge.net>
+;;
+;; WARNING: do not change the name of any command-line parameters, phpDocumentor will ignore them
+
+[Parse Data]
+;; title of all the documentation
+;; legal values: any string
+title = GeSHi 1.0.8
+
+;; parse files that start with a . like .bash_profile
+;; legal values: true, false
+hidden = false
+
+;; show elements marked @access private in documentation by setting this to on
+;; legal values: on, off
+parseprivate = off
+
+;; parse with javadoc-like description (first sentence is always the short description)
+;; legal values: on, off
+javadocdesc = off
+
+;; add any custom @tags separated by commas here
+;; legal values: any legal tagname separated by commas.
+customtags = note
+
+;; This is only used by the XML:DocBook/peardoc2 converter
+defaultcategoryname = Documentation
+
+;; what is the main package?
+;; legal values: alphanumeric string plus - and _
+defaultpackagename = core
+
+;; output any parsing information?  set to on for cron jobs
+;; legal values: on
+;quiet = on
+
+;; parse a PEAR-style repository.  Do not turn this on if your project does
+;; not have a parent directory named "pear"
+;; legal values: on/off
+;pear = on
+
+;; where should the documentation be written?
+;; legal values: a legal path
+target = api
+
+;; limit output to the specified packages, even if others are parsed
+;; legal values: package names separated by commas
+;packageoutput = package1,package2
+
+;; comma-separated list of files to parse
+;; legal values: paths separated by commas
+filename = ../geshi.php
+
+;; comma-separated list of directories to parse
+;; legal values: directory paths separated by commas
+;directory = /path1,/path2,.,..,subdirectory
+;directory = /home/jeichorn/cvs/pear
+;directory = geshi
+
+;; template base directory (the equivalent directory of <installdir>/phpDocumentor)
+;templatebase = /path/to/my/templates
+
+;; comma-separated list of files, directories or wildcards ? and * (any wildcard) to ignore
+;; legal values: any wildcard strings separated by commas
+;ignore = /path/to/ignore*,*list.php,myfile.php,subdirectory/
+ignore = /*.svn/*
+
+;; comma-separated list of Converters to use in outputformat:Convertername:templatedirectory format
+;; legal values: HTML:frames:default,HTML:frames:l0l33t,HTML:frames:phpdoc.de,HTML:frames:phphtmllib,
+;;               HTML:frames:earthli,
+;;               HTML:frames:DOM/default,HTML:frames:DOM/l0l33t,HTML:frames:DOM/phpdoc.de,
+;;               HTML:frames:DOM/phphtmllib,HTML:frames:DOM/earthli
+;;               HTML:Smarty:default,HTML:Smarty:PHP,HTML:Smarty:HandS
+;;               PDF:default:default,CHM:default:default,XML:DocBook/peardoc2:default
+output=HTML:frames:earthli
+
+;; turn this option on if you want highlighted source code for every file
+;; legal values: on/off
+sourcecode = on
diff --git a/examples/includes/geshi/geshi.php b/examples/includes/geshi/geshi.php
new file mode 100644 (file)
index 0000000..8cf1f9a
--- /dev/null
@@ -0,0 +1,4619 @@
+<?php
+/**
+ * GeSHi - Generic Syntax Highlighter
+ *
+ * The GeSHi class for Generic Syntax Highlighting. Please refer to the
+ * documentation at http://qbnz.com/highlighter/documentation.php for more
+ * information about how to use this class.
+ *
+ * For changes, release notes, TODOs etc, see the relevant files in the docs/
+ * directory.
+ *
+ *   This file is part of GeSHi.
+ *
+ *  GeSHi 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.
+ *
+ *  GeSHi 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 GeSHi; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @package    geshi
+ * @subpackage core
+ * @author     Nigel McNie <nigel@geshi.org>, Benny Baumann <BenBE@omorphia.de>
+ * @copyright  (C) 2004 - 2007 Nigel McNie, (C) 2007 - 2008 Benny Baumann
+ * @license    http://gnu.org/copyleft/gpl.html GNU GPL
+ *
+ */
+
+//
+// GeSHi Constants
+// You should use these constant names in your programs instead of
+// their values - you never know when a value may change in a future
+// version
+//
+
+/** The version of this GeSHi file */
+define('GESHI_VERSION', '1.0.8.3');
+
+// Define the root directory for the GeSHi code tree
+if (!defined('GESHI_ROOT')) {
+    /** The root directory for GeSHi */
+    define('GESHI_ROOT', dirname(__FILE__) . DIRECTORY_SEPARATOR);
+}
+/** The language file directory for GeSHi
+    @access private */
+define('GESHI_LANG_ROOT', GESHI_ROOT . 'geshi' . DIRECTORY_SEPARATOR);
+
+// Define if GeSHi should be paranoid about security
+if (!defined('GESHI_SECURITY_PARANOID')) {
+    /** Tells GeSHi to be paranoid about security settings */
+    define('GESHI_SECURITY_PARANOID', false);
+}
+
+// Line numbers - use with enable_line_numbers()
+/** Use no line numbers when building the result */
+define('GESHI_NO_LINE_NUMBERS', 0);
+/** Use normal line numbers when building the result */
+define('GESHI_NORMAL_LINE_NUMBERS', 1);
+/** Use fancy line numbers when building the result */
+define('GESHI_FANCY_LINE_NUMBERS', 2);
+
+// Container HTML type
+/** Use nothing to surround the source */
+define('GESHI_HEADER_NONE', 0);
+/** Use a "div" to surround the source */
+define('GESHI_HEADER_DIV', 1);
+/** Use a "pre" to surround the source */
+define('GESHI_HEADER_PRE', 2);
+/** Use a pre to wrap lines when line numbers are enabled or to wrap the whole code. */
+define('GESHI_HEADER_PRE_VALID', 3);
+/**
+ * Use a "table" to surround the source:
+ *
+ *  <table>
+ *    <thead><tr><td colspan="2">$header</td></tr></thead>
+ *    <tbody><tr><td><pre>$linenumbers</pre></td><td><pre>$code></pre></td></tr></tbody>
+ *    <tfooter><tr><td colspan="2">$footer</td></tr></tfoot>
+ *  </table>
+ *
+ * this is essentially only a workaround for Firefox, see sf#1651996 or take a look at
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=365805
+ * @note when linenumbers are disabled this is essentially the same as GESHI_HEADER_PRE
+ */
+define('GESHI_HEADER_PRE_TABLE', 4);
+
+// Capatalisation constants
+/** Lowercase keywords found */
+define('GESHI_CAPS_NO_CHANGE', 0);
+/** Uppercase keywords found */
+define('GESHI_CAPS_UPPER', 1);
+/** Leave keywords found as the case that they are */
+define('GESHI_CAPS_LOWER', 2);
+
+// Link style constants
+/** Links in the source in the :link state */
+define('GESHI_LINK', 0);
+/** Links in the source in the :hover state */
+define('GESHI_HOVER', 1);
+/** Links in the source in the :active state */
+define('GESHI_ACTIVE', 2);
+/** Links in the source in the :visited state */
+define('GESHI_VISITED', 3);
+
+// Important string starter/finisher
+// Note that if you change these, they should be as-is: i.e., don't
+// write them as if they had been run through htmlentities()
+/** The starter for important parts of the source */
+define('GESHI_START_IMPORTANT', '<BEGIN GeSHi>');
+/** The ender for important parts of the source */
+define('GESHI_END_IMPORTANT', '<END GeSHi>');
+
+/**#@+
+ *  @access private
+ */
+// When strict mode applies for a language
+/** Strict mode never applies (this is the most common) */
+define('GESHI_NEVER', 0);
+/** Strict mode *might* apply, and can be enabled or
+    disabled by {@link GeSHi->enable_strict_mode()} */
+define('GESHI_MAYBE', 1);
+/** Strict mode always applies */
+define('GESHI_ALWAYS', 2);
+
+// Advanced regexp handling constants, used in language files
+/** The key of the regex array defining what to search for */
+define('GESHI_SEARCH', 0);
+/** The key of the regex array defining what bracket group in a
+    matched search to use as a replacement */
+define('GESHI_REPLACE', 1);
+/** The key of the regex array defining any modifiers to the regular expression */
+define('GESHI_MODIFIERS', 2);
+/** The key of the regex array defining what bracket group in a
+    matched search to put before the replacement */
+define('GESHI_BEFORE', 3);
+/** The key of the regex array defining what bracket group in a
+    matched search to put after the replacement */
+define('GESHI_AFTER', 4);
+/** The key of the regex array defining a custom keyword to use
+    for this regexp's html tag class */
+define('GESHI_CLASS', 5);
+
+/** Used in language files to mark comments */
+define('GESHI_COMMENTS', 0);
+
+/** Used to work around missing PHP features **/
+define('GESHI_PHP_PRE_433', !(version_compare(PHP_VERSION, '4.3.3') === 1));
+
+/** make sure we can call stripos **/
+if (!function_exists('stripos')) {
+    // the offset param of preg_match is not supported below PHP 4.3.3
+    if (GESHI_PHP_PRE_433) {
+        /**
+         * @ignore
+         */
+        function stripos($haystack, $needle, $offset = null) {
+            if (!is_null($offset)) {
+                $haystack = substr($haystack, $offset);
+            }
+            if (preg_match('/'. preg_quote($needle, '/') . '/', $haystack, $match, PREG_OFFSET_CAPTURE)) {
+                return $match[0][1];
+            }
+            return false;
+        }
+    }
+    else {
+        /**
+         * @ignore
+         */
+        function stripos($haystack, $needle, $offset = null) {
+            if (preg_match('/'. preg_quote($needle, '/') . '/', $haystack, $match, PREG_OFFSET_CAPTURE, $offset)) {
+                return $match[0][1];
+            }
+            return false;
+        }
+    }
+}
+
+/** some old PHP / PCRE subpatterns only support up to xxx subpatterns in
+    regular expressions. Set this to false if your PCRE lib is up to date
+    @see GeSHi->optimize_regexp_list()
+    **/
+define('GESHI_MAX_PCRE_SUBPATTERNS', 500);
+/** it's also important not to generate too long regular expressions
+    be generous here... but keep in mind, that when reaching this limit we
+    still have to close open patterns. 12k should do just fine on a 16k limit.
+    @see GeSHi->optimize_regexp_list()
+    **/
+define('GESHI_MAX_PCRE_LENGTH', 12288);
+
+//Number format specification
+/** Basic number format for integers */
+define('GESHI_NUMBER_INT_BASIC', 1);        //Default integers \d+
+/** Enhanced number format for integers like seen in C */
+define('GESHI_NUMBER_INT_CSTYLE', 2);       //Default C-Style \d+[lL]?
+/** Number format to highlight binary numbers with a suffix "b" */
+define('GESHI_NUMBER_BIN_SUFFIX', 16);           //[01]+[bB]
+/** Number format to highlight binary numbers with a prefix % */
+define('GESHI_NUMBER_BIN_PREFIX_PERCENT', 32);   //%[01]+
+/** Number format to highlight binary numbers with a prefix 0b (C) */
+define('GESHI_NUMBER_BIN_PREFIX_0B', 64);        //0b[01]+
+/** Number format to highlight octal numbers with a leading zero */
+define('GESHI_NUMBER_OCT_PREFIX', 256);           //0[0-7]+
+/** Number format to highlight octal numbers with a suffix of o */
+define('GESHI_NUMBER_OCT_SUFFIX', 512);           //[0-7]+[oO]
+/** Number format to highlight hex numbers with a prefix 0x */
+define('GESHI_NUMBER_HEX_PREFIX', 4096);           //0x[0-9a-fA-F]+
+/** Number format to highlight hex numbers with a suffix of h */
+define('GESHI_NUMBER_HEX_SUFFIX', 8192);           //[0-9][0-9a-fA-F]*h
+/** Number format to highlight floating-point numbers without support for scientific notation */
+define('GESHI_NUMBER_FLT_NONSCI', 65536);          //\d+\.\d+
+/** Number format to highlight floating-point numbers without support for scientific notation */
+define('GESHI_NUMBER_FLT_NONSCI_F', 131072);       //\d+(\.\d+)?f
+/** Number format to highlight floating-point numbers with support for scientific notation (E) and optional leading zero */
+define('GESHI_NUMBER_FLT_SCI_SHORT', 262144);      //\.\d+e\d+
+/** Number format to highlight floating-point numbers with support for scientific notation (E) and required leading digit */
+define('GESHI_NUMBER_FLT_SCI_ZERO', 524288);       //\d+(\.\d+)?e\d+
+//Custom formats are passed by RX array
+
+// Error detection - use these to analyse faults
+/** No sourcecode to highlight was specified
+ * @deprecated
+ */
+define('GESHI_ERROR_NO_INPUT', 1);
+/** The language specified does not exist */
+define('GESHI_ERROR_NO_SUCH_LANG', 2);
+/** GeSHi could not open a file for reading (generally a language file) */
+define('GESHI_ERROR_FILE_NOT_READABLE', 3);
+/** The header type passed to {@link GeSHi->set_header_type()} was invalid */
+define('GESHI_ERROR_INVALID_HEADER_TYPE', 4);
+/** The line number type passed to {@link GeSHi->enable_line_numbers()} was invalid */
+define('GESHI_ERROR_INVALID_LINE_NUMBER_TYPE', 5);
+/**#@-*/
+
+
+/**
+ * The GeSHi Class.
+ *
+ * Please refer to the documentation for GeSHi 1.0.X that is available
+ * at http://qbnz.com/highlighter/documentation.php for more information
+ * about how to use this class.
+ *
+ * @package   geshi
+ * @author    Nigel McNie <nigel@geshi.org>, Benny Baumann <BenBE@omorphia.de>
+ * @copyright (C) 2004 - 2007 Nigel McNie, (C) 2007 - 2008 Benny Baumann
+ */
+class GeSHi {
+    /**#@+
+     * @access private
+     */
+    /**
+     * The source code to highlight
+     * @var string
+     */
+    var $source = '';
+
+    /**
+     * The language to use when highlighting
+     * @var string
+     */
+    var $language = '';
+
+    /**
+     * The data for the language used
+     * @var array
+     */
+    var $language_data = array();
+
+    /**
+     * The path to the language files
+     * @var string
+     */
+    var $language_path = GESHI_LANG_ROOT;
+
+    /**
+     * The error message associated with an error
+     * @var string
+     * @todo check err reporting works
+     */
+    var $error = false;
+
+    /**
+     * Possible error messages
+     * @var array
+     */
+    var $error_messages = array(
+        GESHI_ERROR_NO_SUCH_LANG => 'GeSHi could not find the language {LANGUAGE} (using path {PATH})',
+        GESHI_ERROR_FILE_NOT_READABLE => 'The file specified for load_from_file was not readable',
+        GESHI_ERROR_INVALID_HEADER_TYPE => 'The header type specified is invalid',
+        GESHI_ERROR_INVALID_LINE_NUMBER_TYPE => 'The line number type specified is invalid'
+    );
+
+    /**
+     * Whether highlighting is strict or not
+     * @var boolean
+     */
+    var $strict_mode = false;
+
+    /**
+     * Whether to use CSS classes in output
+     * @var boolean
+     */
+    var $use_classes = false;
+
+    /**
+     * The type of header to use. Can be one of the following
+     * values:
+     *
+     * - GESHI_HEADER_PRE: Source is outputted in a "pre" HTML element.
+     * - GESHI_HEADER_DIV: Source is outputted in a "div" HTML element.
+     * - GESHI_HEADER_NONE: No header is outputted.
+     *
+     * @var int
+     */
+    var $header_type = GESHI_HEADER_PRE;
+
+    /**
+     * Array of permissions for which lexics should be highlighted
+     * @var array
+     */
+    var $lexic_permissions = array(
+        'KEYWORDS' =>    array(),
+        'COMMENTS' =>    array('MULTI' => true),
+        'REGEXPS' =>     array(),
+        'ESCAPE_CHAR' => true,
+        'BRACKETS' =>    true,
+        'SYMBOLS' =>     false,
+        'STRINGS' =>     true,
+        'NUMBERS' =>     true,
+        'METHODS' =>     true,
+        'SCRIPT' =>      true
+    );
+
+    /**
+     * The time it took to parse the code
+     * @var double
+     */
+    var $time = 0;
+
+    /**
+     * The content of the header block
+     * @var string
+     */
+    var $header_content = '';
+
+    /**
+     * The content of the footer block
+     * @var string
+     */
+    var $footer_content = '';
+
+    /**
+     * The style of the header block
+     * @var string
+     */
+    var $header_content_style = '';
+
+    /**
+     * The style of the footer block
+     * @var string
+     */
+    var $footer_content_style = '';
+
+    /**
+     * Tells if a block around the highlighted source should be forced
+     * if not using line numbering
+     * @var boolean
+     */
+    var $force_code_block = false;
+
+    /**
+     * The styles for hyperlinks in the code
+     * @var array
+     */
+    var $link_styles = array();
+
+    /**
+     * Whether important blocks should be recognised or not
+     * @var boolean
+     * @deprecated
+     * @todo REMOVE THIS FUNCTIONALITY!
+     */
+    var $enable_important_blocks = false;
+
+    /**
+     * Styles for important parts of the code
+     * @var string
+     * @deprecated
+     * @todo As above - rethink the whole idea of important blocks as it is buggy and
+     * will be hard to implement in 1.2
+     */
+    var $important_styles = 'font-weight: bold; color: red;'; // Styles for important parts of the code
+
+    /**
+     * Whether CSS IDs should be added to the code
+     * @var boolean
+     */
+    var $add_ids = false;
+
+    /**
+     * Lines that should be highlighted extra
+     * @var array
+     */
+    var $highlight_extra_lines = array();
+
+    /**
+     * Styles of lines that should be highlighted extra
+     * @var array
+     */
+    var $highlight_extra_lines_styles = array();
+
+    /**
+     * Styles of extra-highlighted lines
+     * @var string
+     */
+    var $highlight_extra_lines_style = 'background-color: #ffc;';
+
+    /**
+     * The line ending
+     * If null, nl2br() will be used on the result string.
+     * Otherwise, all instances of \n will be replaced with $line_ending
+     * @var string
+     */
+    var $line_ending = null;
+
+    /**
+     * Number at which line numbers should start at
+     * @var int
+     */
+    var $line_numbers_start = 1;
+
+    /**
+     * The overall style for this code block
+     * @var string
+     */
+    var $overall_style = 'font-family:monospace;';
+
+    /**
+     *  The style for the actual code
+     * @var string
+     */
+    var $code_style = 'font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;';
+
+    /**
+     * The overall class for this code block
+     * @var string
+     */
+    var $overall_class = '';
+
+    /**
+     * The overall ID for this code block
+     * @var string
+     */
+    var $overall_id = '';
+
+    /**
+     * Line number styles
+     * @var string
+     */
+    var $line_style1 = 'font-weight: normal; vertical-align:top;';
+
+    /**
+     * Line number styles for fancy lines
+     * @var string
+     */
+    var $line_style2 = 'font-weight: bold; vertical-align:top;';
+
+    /**
+     * Style for line numbers when GESHI_HEADER_PRE_TABLE is chosen
+     * @var string
+     */
+    var $table_linenumber_style = 'width:1px;text-align:right;margin:0;padding:0 2px;vertical-align:top;';
+
+    /**
+     * Flag for how line numbers are displayed
+     * @var boolean
+     */
+    var $line_numbers = GESHI_NO_LINE_NUMBERS;
+
+    /**
+     * Flag to decide if multi line spans are allowed. Set it to false to make sure
+     * each tag is closed before and reopened after each linefeed.
+     * @var boolean
+     */
+    var $allow_multiline_span = true;
+
+    /**
+     * The "nth" value for fancy line highlighting
+     * @var int
+     */
+    var $line_nth_row = 0;
+
+    /**
+     * The size of tab stops
+     * @var int
+     */
+    var $tab_width = 8;
+
+    /**
+     * Should we use language-defined tab stop widths?
+     * @var int
+     */
+    var $use_language_tab_width = false;
+
+    /**
+     * Default target for keyword links
+     * @var string
+     */
+    var $link_target = '';
+
+    /**
+     * The encoding to use for entity encoding
+     * NOTE: Used with Escape Char Sequences to fix UTF-8 handling (cf. SF#2037598)
+     * @var string
+     */
+    var $encoding = 'utf-8';
+
+    /**
+     * Should keywords be linked?
+     * @var boolean
+     */
+    var $keyword_links = true;
+
+    /**
+     * Currently loaded language file
+     * @var string
+     * @since 1.0.7.22
+     */
+    var $loaded_language = '';
+
+    /**
+     * Wether the caches needed for parsing are built or not
+     *
+     * @var bool
+     * @since 1.0.8
+     */
+    var $parse_cache_built = false;
+
+    /**
+     * Work around for Suhosin Patch with disabled /e modifier
+     *
+     * Note from suhosins author in config file:
+     * <blockquote>
+     *   The /e modifier inside <code>preg_replace()</code> allows code execution.
+     *   Often it is the cause for remote code execution exploits. It is wise to
+     *   deactivate this feature and test where in the application it is used.
+     *   The developer using the /e modifier should be made aware that he should
+     *   use <code>preg_replace_callback()</code> instead
+     * </blockquote>
+     *
+     * @var array
+     * @since 1.0.8
+     */
+    var $_kw_replace_group = 0;
+    var $_rx_key = 0;
+
+    /**
+     * some "callback parameters" for handle_multiline_regexps
+     *
+     * @since 1.0.8
+     * @access private
+     * @var string
+     */
+    var $_hmr_before = '';
+    var $_hmr_replace = '';
+    var $_hmr_after = '';
+    var $_hmr_key = 0;
+
+    /**#@-*/
+
+    /**
+     * Creates a new GeSHi object, with source and language
+     *
+     * @param string The source code to highlight
+     * @param string The language to highlight the source with
+     * @param string The path to the language file directory. <b>This
+     *               is deprecated!</b> I've backported the auto path
+     *               detection from the 1.1.X dev branch, so now it
+     *               should be automatically set correctly. If you have
+     *               renamed the language directory however, you will
+     *               still need to set the path using this parameter or
+     *               {@link GeSHi->set_language_path()}
+     * @since 1.0.0
+     */
+    function GeSHi($source = '', $language = '', $path = '') {
+        if (!empty($source)) {
+            $this->set_source($source);
+        }
+        if (!empty($language)) {
+            $this->set_language($language);
+        }
+        $this->set_language_path($path);
+    }
+
+    /**
+     * Returns an error message associated with the last GeSHi operation,
+     * or false if no error has occured
+     *
+     * @return string|false An error message if there has been an error, else false
+     * @since  1.0.0
+     */
+    function error() {
+        if ($this->error) {
+            //Put some template variables for debugging here ...
+            $debug_tpl_vars = array(
+                '{LANGUAGE}' => $this->language,
+                '{PATH}' => $this->language_path
+            );
+            $msg = str_replace(
+                array_keys($debug_tpl_vars),
+                array_values($debug_tpl_vars),
+                $this->error_messages[$this->error]);
+
+            return "<br /><strong>GeSHi Error:</strong> $msg (code {$this->error})<br />";
+        }
+        return false;
+    }
+
+    /**
+     * Gets a human-readable language name (thanks to Simon Patterson
+     * for the idea :))
+     *
+     * @return string The name for the current language
+     * @since  1.0.2
+     */
+    function get_language_name() {
+        if (GESHI_ERROR_NO_SUCH_LANG == $this->error) {
+            return $this->language_data['LANG_NAME'] . ' (Unknown Language)';
+        }
+        return $this->language_data['LANG_NAME'];
+    }
+
+    /**
+     * Sets the source code for this object
+     *
+     * @param string The source code to highlight
+     * @since 1.0.0
+     */
+    function set_source($source) {
+        $this->source = $source;
+        $this->highlight_extra_lines = array();
+    }
+
+    /**
+     * Sets the language for this object
+     *
+     * @note since 1.0.8 this function won't reset language-settings by default anymore!
+     *       if you need this set $force_reset = true
+     *
+     * @param string The name of the language to use
+     * @since 1.0.0
+     */
+    function set_language($language, $force_reset = false) {
+        if ($force_reset) {
+            $this->loaded_language = false;
+        }
+
+        //Clean up the language name to prevent malicious code injection
+        $language = preg_replace('#[^a-zA-Z0-9\-_]#', '', $language);
+
+        $language = strtolower($language);
+
+        //Retreive the full filename
+        $file_name = $this->language_path . $language . '.php';
+        if ($file_name == $this->loaded_language) {
+            // this language is already loaded!
+            return;
+        }
+
+        $this->language = $language;
+
+        $this->error = false;
+        $this->strict_mode = GESHI_NEVER;
+
+        //Check if we can read the desired file
+        if (!is_readable($file_name)) {
+            $this->error = GESHI_ERROR_NO_SUCH_LANG;
+            return;
+        }
+
+        // Load the language for parsing
+        $this->load_language($file_name);
+    }
+
+    /**
+     * Sets the path to the directory containing the language files. Note
+     * that this path is relative to the directory of the script that included
+     * geshi.php, NOT geshi.php itself.
+     *
+     * @param string The path to the language directory
+     * @since 1.0.0
+     * @deprecated The path to the language files should now be automatically
+     *             detected, so this method should no longer be needed. The
+     *             1.1.X branch handles manual setting of the path differently
+     *             so this method will disappear in 1.2.0.
+     */
+    function set_language_path($path) {
+        if(strpos($path,':')) {
+            //Security Fix to prevent external directories using fopen wrappers.
+            if(DIRECTORY_SEPARATOR == "\\") {
+                if(!preg_match('#^[a-zA-Z]:#', $path) || false !== strpos($path, ':', 2)) {
+                    return;
+                }
+            } else {
+                return;
+            }
+        }
+        if(preg_match('#[^/a-zA-Z0-9_\.\-\\\s:]#', $path)) {
+            //Security Fix to prevent external directories using fopen wrappers.
+            return;
+        }
+        if(GESHI_SECURITY_PARANOID && false !== strpos($path, '/.')) {
+            //Security Fix to prevent external directories using fopen wrappers.
+            return;
+        }
+        if(GESHI_SECURITY_PARANOID && false !== strpos($path, '..')) {
+            //Security Fix to prevent external directories using fopen wrappers.
+            return;
+        }
+        if ($path) {
+            $this->language_path = ('/' == $path[strlen($path) - 1]) ? $path : $path . '/';
+            $this->set_language($this->language); // otherwise set_language_path has no effect
+        }
+    }
+
+    /**
+     * Sets the type of header to be used.
+     *
+     * If GESHI_HEADER_DIV is used, the code is surrounded in a "div".This
+     * means more source code but more control over tab width and line-wrapping.
+     * GESHI_HEADER_PRE means that a "pre" is used - less source, but less
+     * control. Default is GESHI_HEADER_PRE.
+     *
+     * From 1.0.7.2, you can use GESHI_HEADER_NONE to specify that no header code
+     * should be outputted.
+     *
+     * @param int The type of header to be used
+     * @since 1.0.0
+     */
+    function set_header_type($type) {
+        //Check if we got a valid header type
+        if (!in_array($type, array(GESHI_HEADER_NONE, GESHI_HEADER_DIV,
+            GESHI_HEADER_PRE, GESHI_HEADER_PRE_VALID, GESHI_HEADER_PRE_TABLE))) {
+            $this->error = GESHI_ERROR_INVALID_HEADER_TYPE;
+            return;
+        }
+
+        //Set that new header type
+        $this->header_type = $type;
+    }
+
+    /**
+     * Sets the styles for the code that will be outputted
+     * when this object is parsed. The style should be a
+     * string of valid stylesheet declarations
+     *
+     * @param string  The overall style for the outputted code block
+     * @param boolean Whether to merge the styles with the current styles or not
+     * @since 1.0.0
+     */
+    function set_overall_style($style, $preserve_defaults = false) {
+        if (!$preserve_defaults) {
+            $this->overall_style = $style;
+        } else {
+            $this->overall_style .= $style;
+        }
+    }
+
+    /**
+     * Sets the overall classname for this block of code. This
+     * class can then be used in a stylesheet to style this object's
+     * output
+     *
+     * @param string The class name to use for this block of code
+     * @since 1.0.0
+     */
+    function set_overall_class($class) {
+        $this->overall_class = $class;
+    }
+
+    /**
+     * Sets the overall id for this block of code. This id can then
+     * be used in a stylesheet to style this object's output
+     *
+     * @param string The ID to use for this block of code
+     * @since 1.0.0
+     */
+    function set_overall_id($id) {
+        $this->overall_id = $id;
+    }
+
+    /**
+     * Sets whether CSS classes should be used to highlight the source. Default
+     * is off, calling this method with no arguments will turn it on
+     *
+     * @param boolean Whether to turn classes on or not
+     * @since 1.0.0
+     */
+    function enable_classes($flag = true) {
+        $this->use_classes = ($flag) ? true : false;
+    }
+
+    /**
+     * Sets the style for the actual code. This should be a string
+     * containing valid stylesheet declarations. If $preserve_defaults is
+     * true, then styles are merged with the default styles, with the
+     * user defined styles having priority
+     *
+     * Note: Use this method to override any style changes you made to
+     * the line numbers if you are using line numbers, else the line of
+     * code will have the same style as the line number! Consult the
+     * GeSHi documentation for more information about this.
+     *
+     * @param string  The style to use for actual code
+     * @param boolean Whether to merge the current styles with the new styles
+     * @since 1.0.2
+     */
+    function set_code_style($style, $preserve_defaults = false) {
+        if (!$preserve_defaults) {
+            $this->code_style = $style;
+        } else {
+            $this->code_style .= $style;
+        }
+    }
+
+    /**
+     * Sets the styles for the line numbers.
+     *
+     * @param string The style for the line numbers that are "normal"
+     * @param string|boolean If a string, this is the style of the line
+     *        numbers that are "fancy", otherwise if boolean then this
+     *        defines whether the normal styles should be merged with the
+     *        new normal styles or not
+     * @param boolean If set, is the flag for whether to merge the "fancy"
+     *        styles with the current styles or not
+     * @since 1.0.2
+     */
+    function set_line_style($style1, $style2 = '', $preserve_defaults = false) {
+        //Check if we got 2 or three parameters
+        if (is_bool($style2)) {
+            $preserve_defaults = $style2;
+            $style2 = '';
+        }
+
+        //Actually set the new styles
+        if (!$preserve_defaults) {
+            $this->line_style1 = $style1;
+            $this->line_style2 = $style2;
+        } else {
+            $this->line_style1 .= $style1;
+            $this->line_style2 .= $style2;
+        }
+    }
+
+    /**
+     * Sets whether line numbers should be displayed.
+     *
+     * Valid values for the first parameter are:
+     *
+     *  - GESHI_NO_LINE_NUMBERS: Line numbers will not be displayed
+     *  - GESHI_NORMAL_LINE_NUMBERS: Line numbers will be displayed
+     *  - GESHI_FANCY_LINE_NUMBERS: Fancy line numbers will be displayed
+     *
+     * For fancy line numbers, the second parameter is used to signal which lines
+     * are to be fancy. For example, if the value of this parameter is 5 then every
+     * 5th line will be fancy.
+     *
+     * @param int How line numbers should be displayed
+     * @param int Defines which lines are fancy
+     * @since 1.0.0
+     */
+    function enable_line_numbers($flag, $nth_row = 5) {
+        if (GESHI_NO_LINE_NUMBERS != $flag && GESHI_NORMAL_LINE_NUMBERS != $flag
+            && GESHI_FANCY_LINE_NUMBERS != $flag) {
+            $this->error = GESHI_ERROR_INVALID_LINE_NUMBER_TYPE;
+        }
+        $this->line_numbers = $flag;
+        $this->line_nth_row = $nth_row;
+    }
+
+    /**
+     * Sets wether spans and other HTML markup generated by GeSHi can
+     * span over multiple lines or not. Defaults to true to reduce overhead.
+     * Set it to false if you want to manipulate the output or manually display
+     * the code in an ordered list.
+     *
+     * @param boolean Wether multiline spans are allowed or not
+     * @since 1.0.7.22
+     */
+    function enable_multiline_span($flag) {
+        $this->allow_multiline_span = (bool) $flag;
+    }
+
+    /**
+     * Get current setting for multiline spans, see GeSHi->enable_multiline_span().
+     *
+     * @see enable_multiline_span
+     * @return bool
+     */
+    function get_multiline_span() {
+        return $this->allow_multiline_span;
+    }
+
+    /**
+     * Sets the style for a keyword group. If $preserve_defaults is
+     * true, then styles are merged with the default styles, with the
+     * user defined styles having priority
+     *
+     * @param int     The key of the keyword group to change the styles of
+     * @param string  The style to make the keywords
+     * @param boolean Whether to merge the new styles with the old or just
+     *                to overwrite them
+     * @since 1.0.0
+     */
+    function set_keyword_group_style($key, $style, $preserve_defaults = false) {
+        //Set the style for this keyword group
+        if (!$preserve_defaults) {
+            $this->language_data['STYLES']['KEYWORDS'][$key] = $style;
+        } else {
+            $this->language_data['STYLES']['KEYWORDS'][$key] .= $style;
+        }
+
+        //Update the lexic permissions
+        if (!isset($this->lexic_permissions['KEYWORDS'][$key])) {
+            $this->lexic_permissions['KEYWORDS'][$key] = true;
+        }
+    }
+
+    /**
+     * Turns highlighting on/off for a keyword group
+     *
+     * @param int     The key of the keyword group to turn on or off
+     * @param boolean Whether to turn highlighting for that group on or off
+     * @since 1.0.0
+     */
+    function set_keyword_group_highlighting($key, $flag = true) {
+        $this->lexic_permissions['KEYWORDS'][$key] = ($flag) ? true : false;
+    }
+
+    /**
+     * Sets the styles for comment groups.  If $preserve_defaults is
+     * true, then styles are merged with the default styles, with the
+     * user defined styles having priority
+     *
+     * @param int     The key of the comment group to change the styles of
+     * @param string  The style to make the comments
+     * @param boolean Whether to merge the new styles with the old or just
+     *                to overwrite them
+     * @since 1.0.0
+     */
+    function set_comments_style($key, $style, $preserve_defaults = false) {
+        if (!$preserve_defaults) {
+            $this->language_data['STYLES']['COMMENTS'][$key] = $style;
+        } else {
+            $this->language_data['STYLES']['COMMENTS'][$key] .= $style;
+        }
+    }
+
+    /**
+     * Turns highlighting on/off for comment groups
+     *
+     * @param int     The key of the comment group to turn on or off
+     * @param boolean Whether to turn highlighting for that group on or off
+     * @since 1.0.0
+     */
+    function set_comments_highlighting($key, $flag = true) {
+        $this->lexic_permissions['COMMENTS'][$key] = ($flag) ? true : false;
+    }
+
+    /**
+     * Sets the styles for escaped characters. If $preserve_defaults is
+     * true, then styles are merged with the default styles, with the
+     * user defined styles having priority
+     *
+     * @param string  The style to make the escape characters
+     * @param boolean Whether to merge the new styles with the old or just
+     *                to overwrite them
+     * @since 1.0.0
+     */
+    function set_escape_characters_style($style, $preserve_defaults = false, $group = 0) {
+        if (!$preserve_defaults) {
+            $this->language_data['STYLES']['ESCAPE_CHAR'][$group] = $style;
+        } else {
+            $this->language_data['STYLES']['ESCAPE_CHAR'][$group] .= $style;
+        }
+    }
+
+    /**
+     * Turns highlighting on/off for escaped characters
+     *
+     * @param boolean Whether to turn highlighting for escape characters on or off
+     * @since 1.0.0
+     */
+    function set_escape_characters_highlighting($flag = true) {
+        $this->lexic_permissions['ESCAPE_CHAR'] = ($flag) ? true : false;
+    }
+
+    /**
+     * Sets the styles for brackets. If $preserve_defaults is
+     * true, then styles are merged with the default styles, with the
+     * user defined styles having priority
+     *
+     * This method is DEPRECATED: use set_symbols_style instead.
+     * This method will be removed in 1.2.X
+     *
+     * @param string  The style to make the brackets
+     * @param boolean Whether to merge the new styles with the old or just
+     *                to overwrite them
+     * @since 1.0.0
+     * @deprecated In favour of set_symbols_style
+     */
+    function set_brackets_style($style, $preserve_defaults = false) {
+        if (!$preserve_defaults) {
+            $this->language_data['STYLES']['BRACKETS'][0] = $style;
+        } else {
+            $this->language_data['STYLES']['BRACKETS'][0] .= $style;
+        }
+    }
+
+    /**
+     * Turns highlighting on/off for brackets
+     *
+     * This method is DEPRECATED: use set_symbols_highlighting instead.
+     * This method will be remove in 1.2.X
+     *
+     * @param boolean Whether to turn highlighting for brackets on or off
+     * @since 1.0.0
+     * @deprecated In favour of set_symbols_highlighting
+     */
+    function set_brackets_highlighting($flag) {
+        $this->lexic_permissions['BRACKETS'] = ($flag) ? true : false;
+    }
+
+    /**
+     * Sets the styles for symbols. If $preserve_defaults is
+     * true, then styles are merged with the default styles, with the
+     * user defined styles having priority
+     *
+     * @param string  The style to make the symbols
+     * @param boolean Whether to merge the new styles with the old or just
+     *                to overwrite them
+     * @param int     Tells the group of symbols for which style should be set.
+     * @since 1.0.1
+     */
+    function set_symbols_style($style, $preserve_defaults = false, $group = 0) {
+        // Update the style of symbols
+        if (!$preserve_defaults) {
+            $this->language_data['STYLES']['SYMBOLS'][$group] = $style;
+        } else {
+            $this->language_data['STYLES']['SYMBOLS'][$group] .= $style;
+        }
+
+        // For backward compatibility
+        if (0 == $group) {
+            $this->set_brackets_style ($style, $preserve_defaults);
+        }
+    }
+
+    /**
+     * Turns highlighting on/off for symbols
+     *
+     * @param boolean Whether to turn highlighting for symbols on or off
+     * @since 1.0.0
+     */
+    function set_symbols_highlighting($flag) {
+        // Update lexic permissions for this symbol group
+        $this->lexic_permissions['SYMBOLS'] = ($flag) ? true : false;
+
+        // For backward compatibility
+        $this->set_brackets_highlighting ($flag);
+    }
+
+    /**
+     * Sets the styles for strings. If $preserve_defaults is
+     * true, then styles are merged with the default styles, with the
+     * user defined styles having priority
+     *
+     * @param string  The style to make the escape characters
+     * @param boolean Whether to merge the new styles with the old or just
+     *                to overwrite them
+     * @since 1.0.0
+     */
+    function set_strings_style($style, $preserve_defaults = false) {
+        if (!$preserve_defaults) {
+            $this->language_data['STYLES']['STRINGS'][0] = $style;
+        } else {
+            $this->language_data['STYLES']['STRINGS'][0] .= $style;
+        }
+    }
+
+    /**
+     * Turns highlighting on/off for strings
+     *
+     * @param boolean Whether to turn highlighting for strings on or off
+     * @since 1.0.0
+     */
+    function set_strings_highlighting($flag) {
+        $this->lexic_permissions['STRINGS'] = ($flag) ? true : false;
+    }
+
+    /**
+     * Sets the styles for numbers. If $preserve_defaults is
+     * true, then styles are merged with the default styles, with the
+     * user defined styles having priority
+     *
+     * @param string  The style to make the numbers
+     * @param boolean Whether to merge the new styles with the old or just
+     *                to overwrite them
+     * @since 1.0.0
+     */
+    function set_numbers_style($style, $preserve_defaults = false) {
+        if (!$preserve_defaults) {
+            $this->language_data['STYLES']['NUMBERS'][0] = $style;
+        } else {
+            $this->language_data['STYLES']['NUMBERS'][0] .= $style;
+        }
+    }
+
+    /**
+     * Turns highlighting on/off for numbers
+     *
+     * @param boolean Whether to turn highlighting for numbers on or off
+     * @since 1.0.0
+     */
+    function set_numbers_highlighting($flag) {
+        $this->lexic_permissions['NUMBERS'] = ($flag) ? true : false;
+    }
+
+    /**
+     * Sets the styles for methods. $key is a number that references the
+     * appropriate "object splitter" - see the language file for the language
+     * you are highlighting to get this number. If $preserve_defaults is
+     * true, then styles are merged with the default styles, with the
+     * user defined styles having priority
+     *
+     * @param int     The key of the object splitter to change the styles of
+     * @param string  The style to make the methods
+     * @param boolean Whether to merge the new styles with the old or just
+     *                to overwrite them
+     * @since 1.0.0
+     */
+    function set_methods_style($key, $style, $preserve_defaults = false) {
+        if (!$preserve_defaults) {
+            $this->language_data['STYLES']['METHODS'][$key] = $style;
+        } else {
+            $this->language_data['STYLES']['METHODS'][$key] .= $style;
+        }
+    }
+
+    /**
+     * Turns highlighting on/off for methods
+     *
+     * @param boolean Whether to turn highlighting for methods on or off
+     * @since 1.0.0
+     */
+    function set_methods_highlighting($flag) {
+        $this->lexic_permissions['METHODS'] = ($flag) ? true : false;
+    }
+
+    /**
+     * Sets the styles for regexps. If $preserve_defaults is
+     * true, then styles are merged with the default styles, with the
+     * user defined styles having priority
+     *
+     * @param string  The style to make the regular expression matches
+     * @param boolean Whether to merge the new styles with the old or just
+     *                to overwrite them
+     * @since 1.0.0
+     */
+    function set_regexps_style($key, $style, $preserve_defaults = false) {
+        if (!$preserve_defaults) {
+            $this->language_data['STYLES']['REGEXPS'][$key] = $style;
+        } else {
+            $this->language_data['STYLES']['REGEXPS'][$key] .= $style;
+        }
+    }
+
+    /**
+     * Turns highlighting on/off for regexps
+     *
+     * @param int     The key of the regular expression group to turn on or off
+     * @param boolean Whether to turn highlighting for the regular expression group on or off
+     * @since 1.0.0
+     */
+    function set_regexps_highlighting($key, $flag) {
+        $this->lexic_permissions['REGEXPS'][$key] = ($flag) ? true : false;
+    }
+
+    /**
+     * Sets whether a set of keywords are checked for in a case sensitive manner
+     *
+     * @param int The key of the keyword group to change the case sensitivity of
+     * @param boolean Whether to check in a case sensitive manner or not
+     * @since 1.0.0
+     */
+    function set_case_sensitivity($key, $case) {
+        $this->language_data['CASE_SENSITIVE'][$key] = ($case) ? true : false;
+    }
+
+    /**
+     * Sets the case that keywords should use when found. Use the constants:
+     *
+     *  - GESHI_CAPS_NO_CHANGE: leave keywords as-is
+     *  - GESHI_CAPS_UPPER: convert all keywords to uppercase where found
+     *  - GESHI_CAPS_LOWER: convert all keywords to lowercase where found
+     *
+     * @param int A constant specifying what to do with matched keywords
+     * @since 1.0.1
+     */
+    function set_case_keywords($case) {
+        if (in_array($case, array(
+            GESHI_CAPS_NO_CHANGE, GESHI_CAPS_UPPER, GESHI_CAPS_LOWER))) {
+            $this->language_data['CASE_KEYWORDS'] = $case;
+        }
+    }
+
+    /**
+     * Sets how many spaces a tab is substituted for
+     *
+     * Widths below zero are ignored
+     *
+     * @param int The tab width
+     * @since 1.0.0
+     */
+    function set_tab_width($width) {
+        $this->tab_width = intval($width);
+
+        //Check if it fit's the constraints:
+        if ($this->tab_width < 1) {
+            //Return it to the default
+            $this->tab_width = 8;
+        }
+    }
+
+    /**
+     * Sets whether or not to use tab-stop width specifed by language
+     *
+     * @param boolean Whether to use language-specific tab-stop widths
+     * @since 1.0.7.20
+     */
+    function set_use_language_tab_width($use) {
+        $this->use_language_tab_width = (bool) $use;
+    }
+
+    /**
+     * Returns the tab width to use, based on the current language and user
+     * preference
+     *
+     * @return int Tab width
+     * @since 1.0.7.20
+     */
+    function get_real_tab_width() {
+        if (!$this->use_language_tab_width ||
+            !isset($this->language_data['TAB_WIDTH'])) {
+            return $this->tab_width;
+        } else {
+            return $this->language_data['TAB_WIDTH'];
+        }
+    }
+
+    /**
+     * Enables/disables strict highlighting. Default is off, calling this
+     * method without parameters will turn it on. See documentation
+     * for more details on strict mode and where to use it.
+     *
+     * @param boolean Whether to enable strict mode or not
+     * @since 1.0.0
+     */
+    function enable_strict_mode($mode = true) {
+        if (GESHI_MAYBE == $this->language_data['STRICT_MODE_APPLIES']) {
+            $this->strict_mode = ($mode) ? GESHI_ALWAYS : GESHI_NEVER;
+        }
+    }
+
+    /**
+     * Disables all highlighting
+     *
+     * @since 1.0.0
+     * @todo  Rewrite with array traversal
+     * @deprecated In favour of enable_highlighting
+     */
+    function disable_highlighting() {
+        $this->enable_highlighting(false);
+    }
+
+    /**
+     * Enables all highlighting
+     *
+     * The optional flag parameter was added in version 1.0.7.21 and can be used
+     * to enable (true) or disable (false) all highlighting.
+     *
+     * @since 1.0.0
+     * @param boolean A flag specifying whether to enable or disable all highlighting
+     * @todo  Rewrite with array traversal
+     */
+    function enable_highlighting($flag = true) {
+        $flag = $flag ? true : false;
+        foreach ($this->lexic_permissions as $key => $value) {
+            if (is_array($value)) {
+                foreach ($value as $k => $v) {
+                    $this->lexic_permissions[$key][$k] = $flag;
+                }
+            } else {
+                $this->lexic_permissions[$key] = $flag;
+            }
+        }
+
+        // Context blocks
+        $this->enable_important_blocks = $flag;
+    }
+
+    /**
+     * Given a file extension, this method returns either a valid geshi language
+     * name, or the empty string if it couldn't be found
+     *
+     * @param string The extension to get a language name for
+     * @param array  A lookup array to use instead of the default one
+     * @since 1.0.5
+     * @todo Re-think about how this method works (maybe make it private and/or make it
+     *       a extension->lang lookup?)
+     * @todo static?
+     */
+    function get_language_name_from_extension( $extension, $lookup = array() ) {
+        if ( !is_array($lookup) || empty($lookup)) {
+            $lookup = array(
+                'actionscript' => array('as'),
+                'ada' => array('a', 'ada', 'adb', 'ads'),
+                'apache' => array('conf'),
+                'asm' => array('ash', 'asm', 'inc'),
+                'asp' => array('asp'),
+                'bash' => array('sh'),
+                'bf' => array('bf'),
+                'c' => array('c', 'h'),
+                'c_mac' => array('c', 'h'),
+                'caddcl' => array(),
+                'cadlisp' => array(),
+                'cdfg' => array('cdfg'),
+                'cobol' => array('cbl'),
+                'cpp' => array('cpp', 'hpp', 'C', 'H', 'CPP', 'HPP'),
+                'csharp' => array('cs'),
+                'css' => array('css'),
+                'd' => array('d'),
+                'delphi' => array('dpk', 'dpr', 'pp', 'pas'),
+                'diff' => array('diff', 'patch'),
+                'dos' => array('bat', 'cmd'),
+                'gettext' => array('po', 'pot'),
+                'gml' => array('gml'),
+                'gnuplot' => array('plt'),
+                'groovy' => array('groovy'),
+                'haskell' => array('hs'),
+                'html4strict' => array('html', 'htm'),
+                'ini' => array('ini', 'desktop'),
+                'java' => array('java'),
+                'javascript' => array('js'),
+                'klonec' => array('kl1'),
+                'klonecpp' => array('klx'),
+                'latex' => array('tex'),
+                'lisp' => array('lisp'),
+                'lua' => array('lua'),
+                'matlab' => array('m'),
+                'mpasm' => array(),
+                'mysql' => array('sql'),
+                'nsis' => array(),
+                'objc' => array(),
+                'oobas' => array(),
+                'oracle8' => array(),
+                'oracle10' => array(),
+                'pascal' => array('pas'),
+                'perl' => array('pl', 'pm'),
+                'php' => array('php', 'php5', 'phtml', 'phps'),
+                'povray' => array('pov'),
+                'providex' => array('pvc', 'pvx'),
+                'prolog' => array('pl'),
+                'python' => array('py'),
+                'qbasic' => array('bi'),
+                'reg' => array('reg'),
+                'ruby' => array('rb'),
+                'sas' => array('sas'),
+                'scala' => array('scala'),
+                'scheme' => array('scm'),
+                'scilab' => array('sci'),
+                'smalltalk' => array('st'),
+                'smarty' => array(),
+                'tcl' => array('tcl'),
+                'vb' => array('bas'),
+                'vbnet' => array(),
+                'visualfoxpro' => array(),
+                'whitespace' => array('ws'),
+                'xml' => array('xml', 'svg'),
+                'z80' => array('z80', 'asm', 'inc')
+            );
+        }
+
+        foreach ($lookup as $lang => $extensions) {
+            if (in_array($extension, $extensions)) {
+                return $lang;
+            }
+        }
+        return '';
+    }
+
+    /**
+     * Given a file name, this method loads its contents in, and attempts
+     * to set the language automatically. An optional lookup table can be
+     * passed for looking up the language name. If not specified a default
+     * table is used
+     *
+     * The language table is in the form
+     * <pre>array(
+     *   'lang_name' => array('extension', 'extension', ...),
+     *   'lang_name' ...
+     * );</pre>
+     *
+     * @param string The filename to load the source from
+     * @param array  A lookup array to use instead of the default one
+     * @todo Complete rethink of this and above method
+     * @since 1.0.5
+     */
+    function load_from_file($file_name, $lookup = array()) {
+        if (is_readable($file_name)) {
+            $this->set_source(file_get_contents($file_name));
+            $this->set_language($this->get_language_name_from_extension(substr(strrchr($file_name, '.'), 1), $lookup));
+        } else {
+            $this->error = GESHI_ERROR_FILE_NOT_READABLE;
+        }
+    }
+
+    /**
+     * Adds a keyword to a keyword group for highlighting
+     *
+     * @param int    The key of the keyword group to add the keyword to
+     * @param string The word to add to the keyword group
+     * @since 1.0.0
+     */
+    function add_keyword($key, $word) {
+        if (!in_array($word, $this->language_data['KEYWORDS'][$key])) {
+            $this->language_data['KEYWORDS'][$key][] = $word;
+
+            //NEW in 1.0.8 don't recompile the whole optimized regexp, simply append it
+            if ($this->parse_cache_built) {
+                $subkey = count($this->language_data['CACHED_KEYWORD_LISTS'][$key]) - 1;
+                $this->language_data['CACHED_KEYWORD_LISTS'][$key][$subkey] .= '|' . preg_quote($word, '/');
+            }
+        }
+    }
+
+    /**
+     * Removes a keyword from a keyword group
+     *
+     * @param int    The key of the keyword group to remove the keyword from
+     * @param string The word to remove from the keyword group
+     * @param bool   Wether to automatically recompile the optimized regexp list or not.
+     *               Note: if you set this to false and @see GeSHi->parse_code() was already called once,
+     *               for the current language, you have to manually call @see GeSHi->optimize_keyword_group()
+     *               or the removed keyword will stay in cache and still be highlighted! On the other hand
+     *               it might be too expensive to recompile the regexp list for every removal if you want to
+     *               remove a lot of keywords.
+     * @since 1.0.0
+     */
+    function remove_keyword($key, $word, $recompile = true) {
+        $key_to_remove = array_search($word, $this->language_data['KEYWORDS'][$key]);
+        if ($key_to_remove !== false) {
+            unset($this->language_data['KEYWORDS'][$key][$key_to_remove]);
+
+            //NEW in 1.0.8, optionally recompile keyword group
+            if ($recompile && $this->parse_cache_built) {
+                $this->optimize_keyword_group($key);
+            }
+        }
+    }
+
+    /**
+     * Creates a new keyword group
+     *
+     * @param int    The key of the keyword group to create
+     * @param string The styles for the keyword group
+     * @param boolean Whether the keyword group is case sensitive ornot
+     * @param array  The words to use for the keyword group
+     * @since 1.0.0
+     */
+    function add_keyword_group($key, $styles, $case_sensitive = true, $words = array()) {
+        $words = (array) $words;
+        if  (empty($words)) {
+            // empty word lists mess up highlighting
+            return false;
+        }
+
+        //Add the new keyword group internally
+        $this->language_data['KEYWORDS'][$key] = $words;
+        $this->lexic_permissions['KEYWORDS'][$key] = true;
+        $this->language_data['CASE_SENSITIVE'][$key] = $case_sensitive;
+        $this->language_data['STYLES']['KEYWORDS'][$key] = $styles;
+
+        //NEW in 1.0.8, cache keyword regexp
+        if ($this->parse_cache_built) {
+            $this->optimize_keyword_group($key);
+        }
+    }
+
+    /**
+     * Removes a keyword group
+     *
+     * @param int    The key of the keyword group to remove
+     * @since 1.0.0
+     */
+    function remove_keyword_group ($key) {
+        //Remove the keyword group internally
+        unset($this->language_data['KEYWORDS'][$key]);
+        unset($this->lexic_permissions['KEYWORDS'][$key]);
+        unset($this->language_data['CASE_SENSITIVE'][$key]);
+        unset($this->language_data['STYLES']['KEYWORDS'][$key]);
+
+        //NEW in 1.0.8
+        unset($this->language_data['CACHED_KEYWORD_LISTS'][$key]);
+    }
+
+    /**
+     * compile optimized regexp list for keyword group
+     *
+     * @param int   The key of the keyword group to compile & optimize
+     * @since 1.0.8
+     */
+    function optimize_keyword_group($key) {
+        $this->language_data['CACHED_KEYWORD_LISTS'][$key] =
+            $this->optimize_regexp_list($this->language_data['KEYWORDS'][$key]);
+        $space_as_whitespace = false;
+        if(isset($this->language_data['PARSER_CONTROL'])) {
+            if(isset($this->language_data['PARSER_CONTROL']['KEYWORDS'])) {
+                if(isset($this->language_data['PARSER_CONTROL']['KEYWORDS']['SPACE_AS_WHITESPACE'])) {
+                    $space_as_whitespace = $this->language_data['PARSER_CONTROL']['KEYWORDS']['SPACE_AS_WHITESPACE'];
+                }
+                if(isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$key]['SPACE_AS_WHITESPACE'])) {
+                    if(isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$key]['SPACE_AS_WHITESPACE'])) {
+                        $space_as_whitespace = $this->language_data['PARSER_CONTROL']['KEYWORDS'][$key]['SPACE_AS_WHITESPACE'];
+                    }
+                }
+            }
+        }
+        if($space_as_whitespace) {
+            foreach($this->language_data['CACHED_KEYWORD_LISTS'][$key] as $rxk => $rxv) {
+                $this->language_data['CACHED_KEYWORD_LISTS'][$key][$rxk] =
+                    str_replace(" ", "\\s+", $rxv);
+            }
+        }
+    }
+
+    /**
+     * Sets the content of the header block
+     *
+     * @param string The content of the header block
+     * @since 1.0.2
+     */
+    function set_header_content($content) {
+        $this->header_content = $content;
+    }
+
+    /**
+     * Sets the content of the footer block
+     *
+     * @param string The content of the footer block
+     * @since 1.0.2
+     */
+    function set_footer_content($content) {
+        $this->footer_content = $content;
+    }
+
+    /**
+     * Sets the style for the header content
+     *
+     * @param string The style for the header content
+     * @since 1.0.2
+     */
+    function set_header_content_style($style) {
+        $this->header_content_style = $style;
+    }
+
+    /**
+     * Sets the style for the footer content
+     *
+     * @param string The style for the footer content
+     * @since 1.0.2
+     */
+    function set_footer_content_style($style) {
+        $this->footer_content_style = $style;
+    }
+
+    /**
+     * Sets whether to force a surrounding block around
+     * the highlighted code or not
+     *
+     * @param boolean Tells whether to enable or disable this feature
+     * @since 1.0.7.20
+     */
+    function enable_inner_code_block($flag) {
+        $this->force_code_block = (bool)$flag;
+    }
+
+    /**
+     * Sets the base URL to be used for keywords
+     *
+     * @param int The key of the keyword group to set the URL for
+     * @param string The URL to set for the group. If {FNAME} is in
+     *               the url somewhere, it is replaced by the keyword
+     *               that the URL is being made for
+     * @since 1.0.2
+     */
+    function set_url_for_keyword_group($group, $url) {
+        $this->language_data['URLS'][$group] = $url;
+    }
+
+    /**
+     * Sets styles for links in code
+     *
+     * @param int A constant that specifies what state the style is being
+     *            set for - e.g. :hover or :visited
+     * @param string The styles to use for that state
+     * @since 1.0.2
+     */
+    function set_link_styles($type, $styles) {
+        $this->link_styles[$type] = $styles;
+    }
+
+    /**
+     * Sets the target for links in code
+     *
+     * @param string The target for links in the code, e.g. _blank
+     * @since 1.0.3
+     */
+    function set_link_target($target) {
+        if (!$target) {
+            $this->link_target = '';
+        } else {
+            $this->link_target = ' target="' . $target . '"';
+        }
+    }
+
+    /**
+     * Sets styles for important parts of the code
+     *
+     * @param string The styles to use on important parts of the code
+     * @since 1.0.2
+     */
+    function set_important_styles($styles) {
+        $this->important_styles = $styles;
+    }
+
+    /**
+     * Sets whether context-important blocks are highlighted
+     *
+     * @param boolean Tells whether to enable or disable highlighting of important blocks
+     * @todo REMOVE THIS SHIZ FROM GESHI!
+     * @deprecated
+     * @since 1.0.2
+     */
+    function enable_important_blocks($flag) {
+        $this->enable_important_blocks = ( $flag ) ? true : false;
+    }
+
+    /**
+     * Whether CSS IDs should be added to each line
+     *
+     * @param boolean If true, IDs will be added to each line.
+     * @since 1.0.2
+     */
+    function enable_ids($flag = true) {
+        $this->add_ids = ($flag) ? true : false;
+    }
+
+    /**
+     * Specifies which lines to highlight extra
+     *
+     * The extra style parameter was added in 1.0.7.21.
+     *
+     * @param mixed An array of line numbers to highlight, or just a line
+     *              number on its own.
+     * @param string A string specifying the style to use for this line.
+     *              If null is specified, the default style is used.
+     *              If false is specified, the line will be removed from
+     *              special highlighting
+     * @since 1.0.2
+     * @todo  Some data replication here that could be cut down on
+     */
+    function highlight_lines_extra($lines, $style = null) {
+        if (is_array($lines)) {
+            //Split up the job using single lines at a time
+            foreach ($lines as $line) {
+                $this->highlight_lines_extra($line, $style);
+            }
+        } else {
+            //Mark the line as being highlighted specially
+            $lines = intval($lines);
+            $this->highlight_extra_lines[$lines] = $lines;
+
+            //Decide on which style to use
+            if ($style === null) { //Check if we should use default style
+                unset($this->highlight_extra_lines_styles[$lines]);
+            } else if ($style === false) { //Check if to remove this line
+                unset($this->highlight_extra_lines[$lines]);
+                unset($this->highlight_extra_lines_styles[$lines]);
+            } else {
+                $this->highlight_extra_lines_styles[$lines] = $style;
+            }
+        }
+    }
+
+    /**
+     * Sets the style for extra-highlighted lines
+     *
+     * @param string The style for extra-highlighted lines
+     * @since 1.0.2
+     */
+    function set_highlight_lines_extra_style($styles) {
+        $this->highlight_extra_lines_style = $styles;
+    }
+
+    /**
+     * Sets the line-ending
+     *
+     * @param string The new line-ending
+     * @since 1.0.2
+     */
+    function set_line_ending($line_ending) {
+        $this->line_ending = (string)$line_ending;
+    }
+
+    /**
+     * Sets what number line numbers should start at. Should
+     * be a positive integer, and will be converted to one.
+     *
+     * <b>Warning:</b> Using this method will add the "start"
+     * attribute to the &lt;ol&gt; that is used for line numbering.
+     * This is <b>not</b> valid XHTML strict, so if that's what you
+     * care about then don't use this method. Firefox is getting
+     * support for the CSS method of doing this in 1.1 and Opera
+     * has support for the CSS method, but (of course) IE doesn't
+     * so it's not worth doing it the CSS way yet.
+     *
+     * @param int The number to start line numbers at
+     * @since 1.0.2
+     */
+    function start_line_numbers_at($number) {
+        $this->line_numbers_start = abs(intval($number));
+    }
+
+    /**
+     * Sets the encoding used for htmlspecialchars(), for international
+     * support.
+     *
+     * NOTE: This is not needed for now because htmlspecialchars() is not
+     * being used (it has a security hole in PHP4 that has not been patched).
+     * Maybe in a future version it may make a return for speed reasons, but
+     * I doubt it.
+     *
+     * @param string The encoding to use for the source
+     * @since 1.0.3
+     */
+    function set_encoding($encoding) {
+        if ($encoding) {
+          $this->encoding = strtolower($encoding);
+        }
+    }
+
+    /**
+     * Turns linking of keywords on or off.
+     *
+     * @param boolean If true, links will be added to keywords
+     * @since 1.0.2
+     */
+    function enable_keyword_links($enable = true) {
+        $this->keyword_links = (bool) $enable;
+    }
+
+    /**
+     * Setup caches needed for styling. This is automatically called in
+     * parse_code() and get_stylesheet() when appropriate. This function helps
+     * stylesheet generators as they rely on some style information being
+     * preprocessed
+     *
+     * @since 1.0.8
+     * @access private
+     */
+    function build_style_cache() {
+        //Build the style cache needed to highlight numbers appropriate
+        if($this->lexic_permissions['NUMBERS']) {
+            //First check what way highlighting information for numbers are given
+            if(!isset($this->language_data['NUMBERS'])) {
+                $this->language_data['NUMBERS'] = 0;
+            }
+
+            if(is_array($this->language_data['NUMBERS'])) {
+                $this->language_data['NUMBERS_CACHE'] = $this->language_data['NUMBERS'];
+            } else {
+                $this->language_data['NUMBERS_CACHE'] = array();
+                if(!$this->language_data['NUMBERS']) {
+                    $this->language_data['NUMBERS'] =
+                        GESHI_NUMBER_INT_BASIC |
+                        GESHI_NUMBER_FLT_NONSCI;
+                }
+
+                for($i = 0, $j = $this->language_data['NUMBERS']; $j > 0; ++$i, $j>>=1) {
+                    //Rearrange style indices if required ...
+                    if(isset($this->language_data['STYLES']['NUMBERS'][1<<$i])) {
+                        $this->language_data['STYLES']['NUMBERS'][$i] =
+                            $this->language_data['STYLES']['NUMBERS'][1<<$i];
+                        unset($this->language_data['STYLES']['NUMBERS'][1<<$i]);
+                    }
+
+                    //Check if this bit is set for highlighting
+                    if($j&1) {
+                        //So this bit is set ...
+                        //Check if it belongs to group 0 or the actual stylegroup
+                        if(isset($this->language_data['STYLES']['NUMBERS'][$i])) {
+                            $this->language_data['NUMBERS_CACHE'][$i] = 1 << $i;
+                        } else {
+                            if(!isset($this->language_data['NUMBERS_CACHE'][0])) {
+                                $this->language_data['NUMBERS_CACHE'][0] = 0;
+                            }
+                            $this->language_data['NUMBERS_CACHE'][0] |= 1 << $i;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Setup caches needed for parsing. This is automatically called in parse_code() when appropriate.
+     * This function makes stylesheet generators much faster as they do not need these caches.
+     *
+     * @since 1.0.8
+     * @access private
+     */
+    function build_parse_cache() {
+        // cache symbol regexp
+        //As this is a costy operation, we avoid doing it for multiple groups ...
+        //Instead we perform it for all symbols at once.
+        //
+        //For this to work, we need to reorganize the data arrays.
+        if ($this->lexic_permissions['SYMBOLS'] && !empty($this->language_data['SYMBOLS'])) {
+            $this->language_data['MULTIPLE_SYMBOL_GROUPS'] = count($this->language_data['STYLES']['SYMBOLS']) > 1;
+
+            $this->language_data['SYMBOL_DATA'] = array();
+            $symbol_preg_multi = array(); // multi char symbols
+            $symbol_preg_single = array(); // single char symbols
+            foreach ($this->language_data['SYMBOLS'] as $key => $symbols) {
+                if (is_array($symbols)) {
+                    foreach ($symbols as $sym) {
+                        $sym = $this->hsc($sym);
+                        if (!isset($this->language_data['SYMBOL_DATA'][$sym])) {
+                            $this->language_data['SYMBOL_DATA'][$sym] = $key;
+                            if (isset($sym[1])) { // multiple chars
+                                $symbol_preg_multi[] = preg_quote($sym, '/');
+                            } else { // single char
+                                if ($sym == '-') {
+                                    // don't trigger range out of order error
+                                    $symbol_preg_single[] = '\-';
+                                } else {
+                                    $symbol_preg_single[] = preg_quote($sym, '/');
+                                }
+                            }
+                        }
+                    }
+                } else {
+                    $symbols = $this->hsc($symbols);
+                    if (!isset($this->language_data['SYMBOL_DATA'][$symbols])) {
+                        $this->language_data['SYMBOL_DATA'][$symbols] = 0;
+                        if (isset($symbols[1])) { // multiple chars
+                            $symbol_preg_multi[] = preg_quote($symbols, '/');
+                        } else if ($symbols == '-') {
+                            // don't trigger range out of order error
+                            $symbol_preg_single[] = '\-';
+                        } else { // single char
+                            $symbol_preg_single[] = preg_quote($symbols, '/');
+                        }
+                    }
+                }
+            }
+
+            //Now we have an array with each possible symbol as the key and the style as the actual data.
+            //This way we can set the correct style just the moment we highlight ...
+            //
+            //Now we need to rewrite our array to get a search string that
+            $symbol_preg = array();
+            if (!empty($symbol_preg_multi)) {
+                rsort($symbol_preg_multi);
+                $symbol_preg[] = implode('|', $symbol_preg_multi);
+            }
+            if (!empty($symbol_preg_single)) {
+                rsort($symbol_preg_single);
+                $symbol_preg[] = '[' . implode('', $symbol_preg_single) . ']';
+            }
+            $this->language_data['SYMBOL_SEARCH'] = implode("|", $symbol_preg);
+        }
+
+        // cache optimized regexp for keyword matching
+        // remove old cache
+        $this->language_data['CACHED_KEYWORD_LISTS'] = array();
+        foreach (array_keys($this->language_data['KEYWORDS']) as $key) {
+            if (!isset($this->lexic_permissions['KEYWORDS'][$key]) ||
+                    $this->lexic_permissions['KEYWORDS'][$key]) {
+                $this->optimize_keyword_group($key);
+            }
+        }
+
+        // brackets
+        if ($this->lexic_permissions['BRACKETS']) {
+            $this->language_data['CACHE_BRACKET_MATCH'] = array('[', ']', '(', ')', '{', '}');
+            if (!$this->use_classes && isset($this->language_data['STYLES']['BRACKETS'][0])) {
+                $this->language_data['CACHE_BRACKET_REPLACE'] = array(
+                    '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">&#91;|>',
+                    '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">&#93;|>',
+                    '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">&#40;|>',
+                    '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">&#41;|>',
+                    '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">&#123;|>',
+                    '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">&#125;|>',
+                );
+            }
+            else {
+                $this->language_data['CACHE_BRACKET_REPLACE'] = array(
+                    '<| class="br0">&#91;|>',
+                    '<| class="br0">&#93;|>',
+                    '<| class="br0">&#40;|>',
+                    '<| class="br0">&#41;|>',
+                    '<| class="br0">&#123;|>',
+                    '<| class="br0">&#125;|>',
+                );
+            }
+        }
+
+        //Build the parse cache needed to highlight numbers appropriate
+        if($this->lexic_permissions['NUMBERS']) {
+            //Check if the style rearrangements have been processed ...
+            //This also does some preprocessing to check which style groups are useable ...
+            if(!isset($this->language_data['NUMBERS_CACHE'])) {
+                $this->build_style_cache();
+            }
+
+            //Number format specification
+            //All this formats are matched case-insensitively!
+            static $numbers_format = array(
+                GESHI_NUMBER_INT_BASIC =>
+                    '(?<![0-9a-z_\.%])(?<![\d\.]e[+\-])([1-9]\d*?|0)(?![0-9a-z\.])',
+                GESHI_NUMBER_INT_CSTYLE =>
+                    '(?<![0-9a-z_\.%])(?<![\d\.]e[+\-])([1-9]\d*?|0)l(?![0-9a-z\.])',
+                GESHI_NUMBER_BIN_SUFFIX =>
+                    '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])[01]+?b(?![0-9a-z\.])',
+                GESHI_NUMBER_BIN_PREFIX_PERCENT =>
+                    '(?<![0-9a-z_\.%])(?<![\d\.]e[+\-])%[01]+?(?![0-9a-z\.])',
+                GESHI_NUMBER_BIN_PREFIX_0B =>
+                    '(?<![0-9a-z_\.%])(?<![\d\.]e[+\-])0b[01]+?(?![0-9a-z\.])',
+                GESHI_NUMBER_OCT_PREFIX =>
+                    '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])0[0-7]+?(?![0-9a-z\.])',
+                GESHI_NUMBER_OCT_SUFFIX =>
+                    '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])[0-7]+?o(?![0-9a-z\.])',
+                GESHI_NUMBER_HEX_PREFIX =>
+                    '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])0x[0-9a-f]+?(?![0-9a-z\.])',
+                GESHI_NUMBER_HEX_SUFFIX =>
+                    '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])\d[0-9a-f]*?h(?![0-9a-z\.])',
+                GESHI_NUMBER_FLT_NONSCI =>
+                    '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])\d+?\.\d+?(?![0-9a-z\.])',
+                GESHI_NUMBER_FLT_NONSCI_F =>
+                    '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])(?:\d+?(?:\.\d*?)?|\.\d+?)f(?![0-9a-z\.])',
+                GESHI_NUMBER_FLT_SCI_SHORT =>
+                    '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])\.\d+?(?:e[+\-]?\d+?)?(?![0-9a-z\.])',
+                GESHI_NUMBER_FLT_SCI_ZERO =>
+                    '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])(?:\d+?(?:\.\d*?)?|\.\d+?)(?:e[+\-]?\d+?)?(?![0-9a-z\.])'
+                );
+
+            //At this step we have an associative array with flag groups for a
+            //specific style or an string denoting a regexp given its index.
+            $this->language_data['NUMBERS_RXCACHE'] = array();
+            foreach($this->language_data['NUMBERS_CACHE'] as $key => $rxdata) {
+                if(is_string($rxdata)) {
+                    $regexp = $rxdata;
+                } else {
+                    //This is a bitfield of number flags to highlight:
+                    //Build an array, implode them together and make this the actual RX
+                    $rxuse = array();
+                    for($i = 1; $i <= $rxdata; $i<<=1) {
+                        if($rxdata & $i) {
+                            $rxuse[] = $numbers_format[$i];
+                        }
+                    }
+                    $regexp = implode("|", $rxuse);
+                }
+
+                $this->language_data['NUMBERS_RXCACHE'][$key] =
+                    "/(?<!<\|\/NUM!)(?<!\d\/>)($regexp)(?!\|>)/i";
+            }
+        }
+
+        $this->parse_cache_built = true;
+    }
+
+    /**
+     * Returns the code in $this->source, highlighted and surrounded by the
+     * nessecary HTML.
+     *
+     * This should only be called ONCE, cos it's SLOW! If you want to highlight
+     * the same source multiple times, you're better off doing a whole lot of
+     * str_replaces to replace the &lt;span&gt;s
+     *
+     * @since 1.0.0
+     */
+    function parse_code () {
+        // Start the timer
+        $start_time = microtime();
+
+        // Firstly, if there is an error, we won't highlight
+        if ($this->error) {
+            //Escape the source for output
+            $result = $this->hsc($this->source);
+
+            //This fix is related to SF#1923020, but has to be applied regardless of
+            //actually highlighting symbols.
+            $result = str_replace(array('<SEMI>', '<PIPE>'), array(';', '|'), $result);
+
+            // Timing is irrelevant
+            $this->set_time($start_time, $start_time);
+            $this->finalise($result);
+            return $result;
+        }
+
+        // make sure the parse cache is up2date
+        if (!$this->parse_cache_built) {
+            $this->build_parse_cache();
+        }
+
+        // Replace all newlines to a common form.
+        $code = str_replace("\r\n", "\n", $this->source);
+        $code = str_replace("\r", "\n", $code);
+
+        // Add spaces for regular expression matching and line numbers
+//        $code = "\n" . $code . "\n";
+
+        // Initialise various stuff
+        $length           = strlen($code);
+        $COMMENT_MATCHED  = false;
+        $stuff_to_parse   = '';
+        $endresult        = '';
+
+        // "Important" selections are handled like multiline comments
+        // @todo GET RID OF THIS SHIZ
+        if ($this->enable_important_blocks) {
+            $this->language_data['COMMENT_MULTI'][GESHI_START_IMPORTANT] = GESHI_END_IMPORTANT;
+        }
+
+        if ($this->strict_mode) {
+            // Break the source into bits. Each bit will be a portion of the code
+            // within script delimiters - for example, HTML between < and >
+            $k = 0;
+            $parts = array();
+            $matches = array();
+            $next_match_pointer = null;
+            // we use a copy to unset delimiters on demand (when they are not found)
+            $delim_copy = $this->language_data['SCRIPT_DELIMITERS'];
+            $i = 0;
+            while ($i < $length) {
+                $next_match_pos = $length + 1; // never true
+                foreach ($delim_copy as $dk => $delimiters) {
+                    if(is_array($delimiters)) {
+                        foreach ($delimiters as $open => $close) {
+                            // make sure the cache is setup properly
+                            if (!isset($matches[$dk][$open])) {
+                                $matches[$dk][$open] = array(
+                                    'next_match' => -1,
+                                    'dk' => $dk,
+
+                                    'open' => $open, // needed for grouping of adjacent code blocks (see below)
+                                    'open_strlen' => strlen($open),
+
+                                    'close' => $close,
+                                    'close_strlen' => strlen($close),
+                                );
+                            }
+                            // Get the next little bit for this opening string
+                            if ($matches[$dk][$open]['next_match'] < $i) {
+                                // only find the next pos if it was not already cached
+                                $open_pos = strpos($code, $open, $i);
+                                if ($open_pos === false) {
+                                    // no match for this delimiter ever
+                                    unset($delim_copy[$dk][$open]);
+                                    continue;
+                                }
+                                $matches[$dk][$open]['next_match'] = $open_pos;
+                            }
+                            if ($matches[$dk][$open]['next_match'] < $next_match_pos) {
+                                //So we got a new match, update the close_pos
+                                $matches[$dk][$open]['close_pos'] =
+                                    strpos($code, $close, $matches[$dk][$open]['next_match']+1);
+
+                                $next_match_pointer =& $matches[$dk][$open];
+                                $next_match_pos = $matches[$dk][$open]['next_match'];
+                            }
+                        }
+                    } else {
+                        //So we should match an RegExp as Strict Block ...
+                        /**
+                         * The value in $delimiters is expected to be an RegExp
+                         * containing exactly 2 matching groups:
+                         *  - Group 1 is the opener
+                         *  - Group 2 is the closer
+                         */
+                        if(!GESHI_PHP_PRE_433 && //Needs proper rewrite to work with PHP >=4.3.0; 4.3.3 is guaranteed to work.
+                            preg_match($delimiters, $code, $matches_rx, PREG_OFFSET_CAPTURE, $i)) {
+                            //We got a match ...
+                            $matches[$dk] = array(
+                                'next_match' => $matches_rx[1][1],
+                                'dk' => $dk,
+
+                                'close_strlen' => strlen($matches_rx[2][0]),
+                                'close_pos' => $matches_rx[2][1],
+                                );
+                        } else {
+                            // no match for this delimiter ever
+                            unset($delim_copy[$dk]);
+                            continue;
+                        }
+
+                        if ($matches[$dk]['next_match'] <= $next_match_pos) {
+                            $next_match_pointer =& $matches[$dk];
+                            $next_match_pos = $matches[$dk]['next_match'];
+                        }
+                    }
+                }
+                // non-highlightable text
+                $parts[$k] = array(
+                    1 => substr($code, $i, $next_match_pos - $i)
+                );
+                ++$k;
+
+                if ($next_match_pos > $length) {
+                    // out of bounds means no next match was found
+                    break;
+                }
+
+                // highlightable code
+                $parts[$k][0] = $next_match_pointer['dk'];
+
+                //Only combine for non-rx script blocks
+                if(is_array($delim_copy[$next_match_pointer['dk']])) {
+                    // group adjacent script blocks, e.g. <foobar><asdf> should be one block, not three!
+                    $i = $next_match_pos + $next_match_pointer['open_strlen'];
+                    while (true) {
+                        $close_pos = strpos($code, $next_match_pointer['close'], $i);
+                        if ($close_pos == false) {
+                            break;
+                        }
+                        $i = $close_pos + $next_match_pointer['close_strlen'];
+                        if ($i == $length) {
+                            break;
+                        }
+                        if ($code[$i] == $next_match_pointer['open'][0] && ($next_match_pointer['open_strlen'] == 1 ||
+                            substr($code, $i, $next_match_pointer['open_strlen']) == $next_match_pointer['open'])) {
+                            // merge adjacent but make sure we don't merge things like <tag><!-- comment -->
+                            foreach ($matches as $submatches) {
+                                foreach ($submatches as $match) {
+                                    if ($match['next_match'] == $i) {
+                                        // a different block already matches here!
+                                        break 3;
+                                    }
+                                }
+                            }
+                        } else {
+                            break;
+                        }
+                    }
+                } else {
+                    $close_pos = $next_match_pointer['close_pos'] + $next_match_pointer['close_strlen'];
+                    $i = $close_pos;
+                }
+
+                if ($close_pos === false) {
+                    // no closing delimiter found!
+                    $parts[$k][1] = substr($code, $next_match_pos);
+                    ++$k;
+                    break;
+                } else {
+                    $parts[$k][1] = substr($code, $next_match_pos, $i - $next_match_pos);
+                    ++$k;
+                }
+            }
+            unset($delim_copy, $next_match_pointer, $next_match_pos, $matches);
+            $num_parts = $k;
+
+            if ($num_parts == 1 && $this->strict_mode == GESHI_MAYBE) {
+                // when we have only one part, we don't have anything to highlight at all.
+                // if we have a "maybe" strict language, this should be handled as highlightable code
+                $parts = array(
+                    0 => array(
+                        0 => '',
+                        1 => ''
+                    ),
+                    1 => array(
+                        0 => null,
+                        1 => $parts[0][1]
+                    )
+                );
+                $num_parts = 2;
+            }
+
+        } else {
+            // Not strict mode - simply dump the source into
+            // the array at index 1 (the first highlightable block)
+            $parts = array(
+                0 => array(
+                    0 => '',
+                    1 => ''
+                ),
+                1 => array(
+                    0 => null,
+                    1 => $code
+                )
+            );
+            $num_parts = 2;
+        }
+
+        //Unset variables we won't need any longer
+        unset($code);
+
+        //Preload some repeatedly used values regarding hardquotes ...
+        $hq = isset($this->language_data['HARDQUOTE']) ? $this->language_data['HARDQUOTE'][0] : false;
+        $hq_strlen = strlen($hq);
+
+        //Preload if line numbers are to be generated afterwards
+        //Added a check if line breaks should be forced even without line numbers, fixes SF#1727398
+        $check_linenumbers = $this->line_numbers != GESHI_NO_LINE_NUMBERS ||
+            !empty($this->highlight_extra_lines) || !$this->allow_multiline_span;
+
+        //preload the escape char for faster checking ...
+        $escaped_escape_char = $this->hsc($this->language_data['ESCAPE_CHAR']);
+
+        // this is used for single-line comments
+        $sc_disallowed_before = "";
+        $sc_disallowed_after = "";
+
+        if (isset($this->language_data['PARSER_CONTROL'])) {
+            if (isset($this->language_data['PARSER_CONTROL']['COMMENTS'])) {
+                if (isset($this->language_data['PARSER_CONTROL']['COMMENTS']['DISALLOWED_BEFORE'])) {
+                    $sc_disallowed_before = $this->language_data['PARSER_CONTROL']['COMMENTS']['DISALLOWED_BEFORE'];
+                }
+                if (isset($this->language_data['PARSER_CONTROL']['COMMENTS']['DISALLOWED_AFTER'])) {
+                    $sc_disallowed_after = $this->language_data['PARSER_CONTROL']['COMMENTS']['DISALLOWED_AFTER'];
+                }
+            }
+        }
+
+        //Fix for SF#1932083: Multichar Quotemarks unsupported
+        $is_string_starter = array();
+        if ($this->lexic_permissions['STRINGS']) {
+            foreach ($this->language_data['QUOTEMARKS'] as $quotemark) {
+                if (!isset($is_string_starter[$quotemark[0]])) {
+                    $is_string_starter[$quotemark[0]] = (string)$quotemark;
+                } else if (is_string($is_string_starter[$quotemark[0]])) {
+                    $is_string_starter[$quotemark[0]] = array(
+                        $is_string_starter[$quotemark[0]],
+                        $quotemark);
+                } else {
+                    $is_string_starter[$quotemark[0]][] = $quotemark;
+                }
+            }
+        }
+
+        // Now we go through each part. We know that even-indexed parts are
+        // code that shouldn't be highlighted, and odd-indexed parts should
+        // be highlighted
+        for ($key = 0; $key < $num_parts; ++$key) {
+            $STRICTATTRS = '';
+
+            // If this block should be highlighted...
+            if (!($key & 1)) {
+                // Else not a block to highlight
+                $endresult .= $this->hsc($parts[$key][1]);
+                unset($parts[$key]);
+                continue;
+            }
+
+            $result = '';
+            $part = $parts[$key][1];
+
+            $highlight_part = true;
+            if ($this->strict_mode && !is_null($parts[$key][0])) {
+                // get the class key for this block of code
+                $script_key = $parts[$key][0];
+                $highlight_part = $this->language_data['HIGHLIGHT_STRICT_BLOCK'][$script_key];
+                if ($this->language_data['STYLES']['SCRIPT'][$script_key] != '' &&
+                    $this->lexic_permissions['SCRIPT']) {
+                    // Add a span element around the source to
+                    // highlight the overall source block
+                    if (!$this->use_classes &&
+                        $this->language_data['STYLES']['SCRIPT'][$script_key] != '') {
+                        $attributes = ' style="' . $this->language_data['STYLES']['SCRIPT'][$script_key] . '"';
+                    } else {
+                        $attributes = ' class="sc' . $script_key . '"';
+                    }
+                    $result .= "<span$attributes>";
+                    $STRICTATTRS = $attributes;
+                }
+            }
+
+            if ($highlight_part) {
+                // Now, highlight the code in this block. This code
+                // is really the engine of GeSHi (along with the method
+                // parse_non_string_part).
+
+                // cache comment regexps incrementally
+                $next_comment_regexp_key = '';
+                $next_comment_regexp_pos = -1;
+                $next_comment_multi_pos = -1;
+                $next_comment_single_pos = -1;
+                $comment_regexp_cache_per_key = array();
+                $comment_multi_cache_per_key = array();
+                $comment_single_cache_per_key = array();
+                $next_open_comment_multi = '';
+                $next_comment_single_key = '';
+                $escape_regexp_cache_per_key = array();
+                $next_escape_regexp_key = '';
+                $next_escape_regexp_pos = -1;
+
+                $length = strlen($part);
+                for ($i = 0; $i < $length; ++$i) {
+                    // Get the next char
+                    $char = $part[$i];
+                    $char_len = 1;
+
+                    // update regexp comment cache if needed
+                    if (isset($this->language_data['COMMENT_REGEXP']) && $next_comment_regexp_pos < $i) {
+                        $next_comment_regexp_pos = $length;
+                        foreach ($this->language_data['COMMENT_REGEXP'] as $comment_key => $regexp) {
+                            $match_i = false;
+                            if (isset($comment_regexp_cache_per_key[$comment_key]) &&
+                                ($comment_regexp_cache_per_key[$comment_key]['pos'] >= $i ||
+                                 $comment_regexp_cache_per_key[$comment_key]['pos'] === false)) {
+                                // we have already matched something
+                                if ($comment_regexp_cache_per_key[$comment_key]['pos'] === false) {
+                                    // this comment is never matched
+                                    continue;
+                                }
+                                $match_i = $comment_regexp_cache_per_key[$comment_key]['pos'];
+                            } else if (
+                                //This is to allow use of the offset parameter in preg_match and stay as compatible with older PHP versions as possible
+                                (GESHI_PHP_PRE_433 && preg_match($regexp, substr($part, $i), $match, PREG_OFFSET_CAPTURE)) ||
+                                (!GESHI_PHP_PRE_433 && preg_match($regexp, $part, $match, PREG_OFFSET_CAPTURE, $i))
+                                ) {
+                                $match_i = $match[0][1];
+                                if (GESHI_PHP_PRE_433) {
+                                    $match_i += $i;
+                                }
+
+                                $comment_regexp_cache_per_key[$comment_key] = array(
+                                    'key' => $comment_key,
+                                    'length' => strlen($match[0][0]),
+                                    'pos' => $match_i
+                                );
+                            } else {
+                                $comment_regexp_cache_per_key[$comment_key]['pos'] = false;
+                                continue;
+                            }
+
+                            if ($match_i !== false && $match_i < $next_comment_regexp_pos) {
+                                $next_comment_regexp_pos = $match_i;
+                                $next_comment_regexp_key = $comment_key;
+                                if ($match_i === $i) {
+                                    break;
+                                }
+                            }
+                        }
+                    }
+
+                    $string_started = false;
+
+                    if (isset($is_string_starter[$char])) {
+                        // Possibly the start of a new string ...
+
+                        //Check which starter it was ...
+                        //Fix for SF#1932083: Multichar Quotemarks unsupported
+                        if (is_array($is_string_starter[$char])) {
+                            $char_new = '';
+                            foreach ($is_string_starter[$char] as $testchar) {
+                                if ($testchar === substr($part, $i, strlen($testchar)) &&
+                                    strlen($testchar) > strlen($char_new)) {
+                                    $char_new = $testchar;
+                                    $string_started = true;
+                                }
+                            }
+                            if ($string_started) {
+                                $char = $char_new;
+                            }
+                        } else {
+                            $testchar = $is_string_starter[$char];
+                            if ($testchar === substr($part, $i, strlen($testchar))) {
+                                $char = $testchar;
+                                $string_started = true;
+                            }
+                        }
+                        $char_len = strlen($char);
+                    }
+
+                    if ($string_started && $i != $next_comment_regexp_pos) {
+                        // Hand out the correct style information for this string
+                        $string_key = array_search($char, $this->language_data['QUOTEMARKS']);
+                        if (!isset($this->language_data['STYLES']['STRINGS'][$string_key]) ||
+                            !isset($this->language_data['STYLES']['ESCAPE_CHAR'][$string_key])) {
+                            $string_key = 0;
+                        }
+
+                        // parse the stuff before this
+                        $result .= $this->parse_non_string_part($stuff_to_parse);
+                        $stuff_to_parse = '';
+
+                        if (!$this->use_classes) {
+                            $string_attributes = ' style="' . $this->language_data['STYLES']['STRINGS'][$string_key] . '"';
+                        } else {
+                            $string_attributes = ' class="st'.$string_key.'"';
+                        }
+
+                        // now handle the string
+                        $string = "<span$string_attributes>" . GeSHi::hsc($char);
+                        $start = $i + $char_len;
+                        $string_open = true;
+
+                        if(empty($this->language_data['ESCAPE_REGEXP'])) {
+                            $next_escape_regexp_pos = $length;
+                        }
+
+                        do {
+                            //Get the regular ending pos ...
+                            $close_pos = strpos($part, $char, $start);
+                            if(false === $close_pos) {
+                                $close_pos = $length;
+                            }
+
+                            if($this->lexic_permissions['ESCAPE_CHAR']) {
+                                // update escape regexp cache if needed
+                                if (isset($this->language_data['ESCAPE_REGEXP']) && $next_escape_regexp_pos < $start) {
+                                    $next_escape_regexp_pos = $length;
+                                    foreach ($this->language_data['ESCAPE_REGEXP'] as $escape_key => $regexp) {
+                                        $match_i = false;
+                                        if (isset($escape_regexp_cache_per_key[$escape_key]) &&
+                                            ($escape_regexp_cache_per_key[$escape_key]['pos'] >= $start ||
+                                             $escape_regexp_cache_per_key[$escape_key]['pos'] === false)) {
+                                            // we have already matched something
+                                            if ($escape_regexp_cache_per_key[$escape_key]['pos'] === false) {
+                                                // this comment is never matched
+                                                continue;
+                                            }
+                                            $match_i = $escape_regexp_cache_per_key[$escape_key]['pos'];
+                                        } else if (
+                                            //This is to allow use of the offset parameter in preg_match and stay as compatible with older PHP versions as possible
+                                            (GESHI_PHP_PRE_433 && preg_match($regexp, substr($part, $start), $match, PREG_OFFSET_CAPTURE)) ||
+                                            (!GESHI_PHP_PRE_433 && preg_match($regexp, $part, $match, PREG_OFFSET_CAPTURE, $start))
+                                            ) {
+                                            $match_i = $match[0][1];
+                                            if (GESHI_PHP_PRE_433) {
+                                                $match_i += $start;
+                                            }
+
+                                            $escape_regexp_cache_per_key[$escape_key] = array(
+                                                'key' => $escape_key,
+                                                'length' => strlen($match[0][0]),
+                                                'pos' => $match_i
+                                            );
+                                        } else {
+                                            $escape_regexp_cache_per_key[$escape_key]['pos'] = false;
+                                            continue;
+                                        }
+
+                                        if ($match_i !== false && $match_i < $next_escape_regexp_pos) {
+                                            $next_escape_regexp_pos = $match_i;
+                                            $next_escape_regexp_key = $escape_key;
+                                            if ($match_i === $start) {
+                                                break;
+                                            }
+                                        }
+                                    }
+                                }
+
+                                //Find the next simple escape position
+                                if('' != $this->language_data['ESCAPE_CHAR']) {
+                                    $simple_escape = strpos($part, $this->language_data['ESCAPE_CHAR'], $start);
+                                    if(false === $simple_escape) {
+                                        $simple_escape = $length;
+                                    }
+                                } else {
+                                    $simple_escape = $length;
+                                }
+                            } else {
+                                $next_escape_regexp_pos = $length;
+                                $simple_escape = $length;
+                            }
+
+                            if($simple_escape < $next_escape_regexp_pos &&
+                                $simple_escape < $length &&
+                                $simple_escape < $close_pos) {
+                                //The nexxt escape sequence is a simple one ...
+                                $es_pos = $simple_escape;
+
+                                //Add the stuff not in the string yet ...
+                                $string .= $this->hsc(substr($part, $start, $es_pos - $start));
+
+                                //Get the style for this escaped char ...
+                                if (!$this->use_classes) {
+                                    $escape_char_attributes = ' style="' . $this->language_data['STYLES']['ESCAPE_CHAR'][0] . '"';
+                                } else {
+                                    $escape_char_attributes = ' class="es0"';
+                                }
+
+                                //Add the style for the escape char ...
+                                $string .= "<span$escape_char_attributes>" .
+                                    GeSHi::hsc($this->language_data['ESCAPE_CHAR']);
+
+                                //Get the byte AFTER the ESCAPE_CHAR we just found
+                                $es_char = $part[$es_pos + 1];
+                                if ($es_char == "\n") {
+                                    // don't put a newline around newlines
+                                    $string .= "</span>\n";
+                                    $start = $es_pos + 2;
+                                } else if (ord($es_char) >= 128) {
+                                    //This is an non-ASCII char (UTF8 or single byte)
+                                    //This code tries to work around SF#2037598 ...
+                                    if(function_exists('mb_substr')) {
+                                        $es_char_m = mb_substr(substr($part, $es_pos+1, 16), 0, 1, $this->encoding);
+                                        $string .= $es_char_m . '</span>';
+                                    } else if (!GESHI_PHP_PRE_433 && 'utf-8' == $this->encoding) {
+                                        if(preg_match("/[\xC2-\xDF][\x80-\xBF]".
+                                            "|\xE0[\xA0-\xBF][\x80-\xBF]".
+                                            "|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}".
+                                            "|\xED[\x80-\x9F][\x80-\xBF]".
+                                            "|\xF0[\x90-\xBF][\x80-\xBF]{2}".
+                                            "|[\xF1-\xF3][\x80-\xBF]{3}".
+                                            "|\xF4[\x80-\x8F][\x80-\xBF]{2}/s",
+                                            $part, $es_char_m, null, $es_pos + 1)) {
+                                            $es_char_m = $es_char_m[0];
+                                        } else {
+                                            $es_char_m = $es_char;
+                                        }
+                                        $string .= $this->hsc($es_char_m) . '</span>';
+                                    } else {
+                                        $es_char_m = $this->hsc($es_char);
+                                    }
+                                    $start = $es_pos + strlen($es_char_m) + 1;
+                                } else {
+                                    $string .= $this->hsc($es_char) . '</span>';
+                                    $start = $es_pos + 2;
+                                }
+                            } else if ($next_escape_regexp_pos < $length &&
+                                $next_escape_regexp_pos < $close_pos) {
+                                $es_pos = $next_escape_regexp_pos;
+                                //Add the stuff not in the string yet ...
+                                $string .= $this->hsc(substr($part, $start, $es_pos - $start));
+
+                                //Get the key and length of this match ...
+                                $escape = $escape_regexp_cache_per_key[$next_escape_regexp_key];
+                                $escape_str = substr($part, $es_pos, $escape['length']);
+                                $escape_key = $escape['key'];
+
+                                //Get the style for this escaped char ...
+                                if (!$this->use_classes) {
+                                    $escape_char_attributes = ' style="' . $this->language_data['STYLES']['ESCAPE_CHAR'][$escape_key] . '"';
+                                } else {
+                                    $escape_char_attributes = ' class="es' . $escape_key . '"';
+                                }
+
+                                //Add the style for the escape char ...
+                                $string .= "<span$escape_char_attributes>" .
+                                    $this->hsc($escape_str) . '</span>';
+
+                                $start = $es_pos + $escape['length'];
+                            } else {
+                                //Copy the remainder of the string ...
+                                $string .= $this->hsc(substr($part, $start, $close_pos - $start + $char_len)) . '</span>';
+                                $start = $close_pos + $char_len;
+                                $string_open = false;
+                            }
+                        } while($string_open);
+
+                        if ($check_linenumbers) {
+                            // Are line numbers used? If, we should end the string before
+                            // the newline and begin it again (so when <li>s are put in the source
+                            // remains XHTML compliant)
+                            // note to self: This opens up possibility of config files specifying
+                            // that languages can/cannot have multiline strings???
+                            $string = str_replace("\n", "</span>\n<span$string_attributes>", $string);
+                        }
+
+                        $result .= $string;
+                        $string = '';
+                        $i = $start - 1;
+                        continue;
+                    } else if ($this->lexic_permissions['STRINGS'] && $hq && $hq[0] == $char &&
+                        substr($part, $i, $hq_strlen) == $hq) {
+                        // The start of a hard quoted string
+                        if (!$this->use_classes) {
+                            $string_attributes = ' style="' . $this->language_data['STYLES']['STRINGS']['HARD'] . '"';
+                            $escape_char_attributes = ' style="' . $this->language_data['STYLES']['ESCAPE_CHAR']['HARD'] . '"';
+                        } else {
+                            $string_attributes = ' class="st_h"';
+                            $escape_char_attributes = ' class="es_h"';
+                        }
+                        // parse the stuff before this
+                        $result .= $this->parse_non_string_part($stuff_to_parse);
+                        $stuff_to_parse = '';
+
+                        // now handle the string
+                        $string = '';
+
+                        // look for closing quote
+                        $start = $i + $hq_strlen;
+                        while ($close_pos = strpos($part, $this->language_data['HARDQUOTE'][1], $start)) {
+                            $start = $close_pos + 1;
+                            if ($this->lexic_permissions['ESCAPE_CHAR'] && $part[$close_pos - 1] == $this->language_data['HARDCHAR']) {
+                                // make sure this quote is not escaped
+                                foreach ($this->language_data['HARDESCAPE'] as $hardescape) {
+                                    if (substr($part, $close_pos - 1, strlen($hardescape)) == $hardescape) {
+                                        // check wether this quote is escaped or if it is something like '\\'
+                                        $escape_char_pos = $close_pos - 1;
+                                        while ($escape_char_pos > 0
+                                                && $part[$escape_char_pos - 1] == $this->language_data['HARDCHAR']) {
+                                            --$escape_char_pos;
+                                        }
+                                        if (($close_pos - $escape_char_pos) & 1) {
+                                            // uneven number of escape chars => this quote is escaped
+                                            continue 2;
+                                        }
+                                    }
+                                }
+                            }
+
+                            // found closing quote
+                            break;
+                        }
+
+                        //Found the closing delimiter?
+                        if (!$close_pos) {
+                            // span till the end of this $part when no closing delimiter is found
+                            $close_pos = $length;
+                        }
+
+                        //Get the actual string
+                        $string = substr($part, $i, $close_pos - $i + 1);
+                        $i = $close_pos;
+
+                        // handle escape chars and encode html chars
+                        // (special because when we have escape chars within our string they may not be escaped)
+                        if ($this->lexic_permissions['ESCAPE_CHAR'] && $this->language_data['ESCAPE_CHAR']) {
+                            $start = 0;
+                            $new_string = '';
+                            while ($es_pos = strpos($string, $this->language_data['ESCAPE_CHAR'], $start)) {
+                                // hmtl escape stuff before
+                                $new_string .= $this->hsc(substr($string, $start, $es_pos - $start));
+                                // check if this is a hard escape
+                                foreach ($this->language_data['HARDESCAPE'] as $hardescape) {
+                                    if (substr($string, $es_pos, strlen($hardescape)) == $hardescape) {
+                                        // indeed, this is a hardescape
+                                        $new_string .= "<span$escape_char_attributes>" .
+                                            $this->hsc($hardescape) . '</span>';
+                                        $start = $es_pos + strlen($hardescape);
+                                        continue 2;
+                                    }
+                                }
+                                // not a hard escape, but a normal escape
+                                // they come in pairs of two
+                                $c = 0;
+                                while (isset($string[$es_pos + $c]) && isset($string[$es_pos + $c + 1])
+                                    && $string[$es_pos + $c] == $this->language_data['ESCAPE_CHAR']
+                                    && $string[$es_pos + $c + 1] == $this->language_data['ESCAPE_CHAR']) {
+                                    $c += 2;
+                                }
+                                if ($c) {
+                                    $new_string .= "<span$escape_char_attributes>" .
+                                        str_repeat($escaped_escape_char, $c) .
+                                        '</span>';
+                                    $start = $es_pos + $c;
+                                } else {
+                                    // this is just a single lonely escape char...
+                                    $new_string .= $escaped_escape_char;
+                                    $start = $es_pos + 1;
+                                }
+                            }
+                            $string = $new_string . $this->hsc(substr($string, $start));
+                        } else {
+                            $string = $this->hsc($string);
+                        }
+
+                        if ($check_linenumbers) {
+                            // Are line numbers used? If, we should end the string before
+                            // the newline and begin it again (so when <li>s are put in the source
+                            // remains XHTML compliant)
+                            // note to self: This opens up possibility of config files specifying
+                            // that languages can/cannot have multiline strings???
+                            $string = str_replace("\n", "</span>\n<span$string_attributes>", $string);
+                        }
+
+                        $result .= "<span$string_attributes>" . $string . '</span>';
+                        $string = '';
+                        continue;
+                    } else {
+                        //Have a look for regexp comments
+                        if ($i == $next_comment_regexp_pos) {
+                            $COMMENT_MATCHED = true;
+                            $comment = $comment_regexp_cache_per_key[$next_comment_regexp_key];
+                            $test_str = $this->hsc(substr($part, $i, $comment['length']));
+
+                            //@todo If remove important do remove here
+                            if ($this->lexic_permissions['COMMENTS']['MULTI']) {
+                                if (!$this->use_classes) {
+                                    $attributes = ' style="' . $this->language_data['STYLES']['COMMENTS'][$comment['key']] . '"';
+                                } else {
+                                    $attributes = ' class="co' . $comment['key'] . '"';
+                                }
+
+                                $test_str = "<span$attributes>" . $test_str . "</span>";
+
+                                // Short-cut through all the multiline code
+                                if ($check_linenumbers) {
+                                    // strreplace to put close span and open span around multiline newlines
+                                    $test_str = str_replace(
+                                        "\n", "</span>\n<span$attributes>",
+                                        str_replace("\n ", "\n&nbsp;", $test_str)
+                                    );
+                                }
+                            }
+
+                            $i += $comment['length'] - 1;
+
+                            // parse the rest
+                            $result .= $this->parse_non_string_part($stuff_to_parse);
+                            $stuff_to_parse = '';
+                        }
+
+                        // If we haven't matched a regexp comment, try multi-line comments
+                        if (!$COMMENT_MATCHED) {
+                            // Is this a multiline comment?
+                            if (!empty($this->language_data['COMMENT_MULTI']) && $next_comment_multi_pos < $i) {
+                                $next_comment_multi_pos = $length;
+                                foreach ($this->language_data['COMMENT_MULTI'] as $open => $close) {
+                                    $match_i = false;
+                                    if (isset($comment_multi_cache_per_key[$open]) &&
+                                        ($comment_multi_cache_per_key[$open] >= $i ||
+                                         $comment_multi_cache_per_key[$open] === false)) {
+                                        // we have already matched something
+                                        if ($comment_multi_cache_per_key[$open] === false) {
+                                            // this comment is never matched
+                                            continue;
+                                        }
+                                        $match_i = $comment_multi_cache_per_key[$open];
+                                    } else if (($match_i = stripos($part, $open, $i)) !== false) {
+                                        $comment_multi_cache_per_key[$open] = $match_i;
+                                    } else {
+                                        $comment_multi_cache_per_key[$open] = false;
+                                        continue;
+                                    }
+                                    if ($match_i !== false && $match_i < $next_comment_multi_pos) {
+                                        $next_comment_multi_pos = $match_i;
+                                        $next_open_comment_multi = $open;
+                                        if ($match_i === $i) {
+                                            break;
+                                        }
+                                    }
+                                }
+                            }
+                            if ($i == $next_comment_multi_pos) {
+                                $open = $next_open_comment_multi;
+                                $close = $this->language_data['COMMENT_MULTI'][$open];
+                                $open_strlen = strlen($open);
+                                $close_strlen = strlen($close);
+                                $COMMENT_MATCHED = true;
+                                $test_str_match = $open;
+                                //@todo If remove important do remove here
+                                if ($this->lexic_permissions['COMMENTS']['MULTI'] ||
+                                    $open == GESHI_START_IMPORTANT) {
+                                    if ($open != GESHI_START_IMPORTANT) {
+                                        if (!$this->use_classes) {
+                                            $attributes = ' style="' . $this->language_data['STYLES']['COMMENTS']['MULTI'] . '"';
+                                        } else {
+                                            $attributes = ' class="coMULTI"';
+                                        }
+                                        $test_str = "<span$attributes>" . $this->hsc($open);
+                                    } else {
+                                        if (!$this->use_classes) {
+                                            $attributes = ' style="' . $this->important_styles . '"';
+                                        } else {
+                                            $attributes = ' class="imp"';
+                                        }
+
+                                        // We don't include the start of the comment if it's an
+                                        // "important" part
+                                        $test_str = "<span$attributes>";
+                                    }
+                                } else {
+                                    $test_str = $this->hsc($open);
+                                }
+
+                                $close_pos = strpos( $part, $close, $i + $open_strlen );
+
+                                if ($close_pos === false) {
+                                    $close_pos = $length;
+                                }
+
+                                // Short-cut through all the multiline code
+                                $rest_of_comment = $this->hsc(substr($part, $i + $open_strlen, $close_pos - $i - $open_strlen + $close_strlen));
+                                if (($this->lexic_permissions['COMMENTS']['MULTI'] ||
+                                    $test_str_match == GESHI_START_IMPORTANT) &&
+                                    $check_linenumbers) {
+
+                                    // strreplace to put close span and open span around multiline newlines
+                                    $test_str .= str_replace(
+                                        "\n", "</span>\n<span$attributes>",
+                                        str_replace("\n ", "\n&nbsp;", $rest_of_comment)
+                                    );
+                                } else {
+                                    $test_str .= $rest_of_comment;
+                                }
+
+                                if ($this->lexic_permissions['COMMENTS']['MULTI'] ||
+                                    $test_str_match == GESHI_START_IMPORTANT) {
+                                    $test_str .= '</span>';
+                                }
+
+                                $i = $close_pos + $close_strlen - 1;
+
+                                // parse the rest
+                                $result .= $this->parse_non_string_part($stuff_to_parse);
+                                $stuff_to_parse = '';
+                            }
+                        }
+
+                        // If we haven't matched a multiline comment, try single-line comments
+                        if (!$COMMENT_MATCHED) {
+                            // cache potential single line comment occurances
+                            if (!empty($this->language_data['COMMENT_SINGLE']) && $next_comment_single_pos < $i) {
+                                $next_comment_single_pos = $length;
+                                foreach ($this->language_data['COMMENT_SINGLE'] as $comment_key => $comment_mark) {
+                                    $match_i = false;
+                                    if (isset($comment_single_cache_per_key[$comment_key]) &&
+                                        ($comment_single_cache_per_key[$comment_key] >= $i ||
+                                         $comment_single_cache_per_key[$comment_key] === false)) {
+                                        // we have already matched something
+                                        if ($comment_single_cache_per_key[$comment_key] === false) {
+                                            // this comment is never matched
+                                            continue;
+                                        }
+                                        $match_i = $comment_single_cache_per_key[$comment_key];
+                                    } else if (
+                                        // case sensitive comments
+                                        ($this->language_data['CASE_SENSITIVE'][GESHI_COMMENTS] &&
+                                        ($match_i = stripos($part, $comment_mark, $i)) !== false) ||
+                                        // non case sensitive
+                                        (!$this->language_data['CASE_SENSITIVE'][GESHI_COMMENTS] &&
+                                          (($match_i = strpos($part, $comment_mark, $i)) !== false))) {
+                                        $comment_single_cache_per_key[$comment_key] = $match_i;
+                                    } else {
+                                        $comment_single_cache_per_key[$comment_key] = false;
+                                        continue;
+                                    }
+                                    if ($match_i !== false && $match_i < $next_comment_single_pos) {
+                                        $next_comment_single_pos = $match_i;
+                                        $next_comment_single_key = $comment_key;
+                                        if ($match_i === $i) {
+                                            break;
+                                        }
+                                    }
+                                }
+                            }
+                            if ($next_comment_single_pos == $i) {
+                                $comment_key = $next_comment_single_key;
+                                $comment_mark = $this->language_data['COMMENT_SINGLE'][$comment_key];
+                                $com_len = strlen($comment_mark);
+
+                                // This check will find special variables like $# in bash
+                                // or compiler directives of Delphi beginning {$
+                                if ((empty($sc_disallowed_before) || ($i == 0) ||
+                                    (false === strpos($sc_disallowed_before, $part[$i-1]))) &&
+                                    (empty($sc_disallowed_after) || ($length <= $i + $com_len) ||
+                                    (false === strpos($sc_disallowed_after, $part[$i + $com_len]))))
+                                {
+                                    // this is a valid comment
+                                    $COMMENT_MATCHED = true;
+                                    if ($this->lexic_permissions['COMMENTS'][$comment_key]) {
+                                        if (!$this->use_classes) {
+                                            $attributes = ' style="' . $this->language_data['STYLES']['COMMENTS'][$comment_key] . '"';
+                                        } else {
+                                            $attributes = ' class="co' . $comment_key . '"';
+                                        }
+                                        $test_str = "<span$attributes>" . $this->hsc($this->change_case($comment_mark));
+                                    } else {
+                                        $test_str = $this->hsc($comment_mark);
+                                    }
+
+                                    //Check if this comment is the last in the source
+                                    $close_pos = strpos($part, "\n", $i);
+                                    $oops = false;
+                                    if ($close_pos === false) {
+                                        $close_pos = $length;
+                                        $oops = true;
+                                    }
+                                    $test_str .= $this->hsc(substr($part, $i + $com_len, $close_pos - $i - $com_len));
+                                    if ($this->lexic_permissions['COMMENTS'][$comment_key]) {
+                                        $test_str .= "</span>";
+                                    }
+
+                                    // Take into account that the comment might be the last in the source
+                                    if (!$oops) {
+                                      $test_str .= "\n";
+                                    }
+
+                                    $i = $close_pos;
+
+                                    // parse the rest
+                                    $result .= $this->parse_non_string_part($stuff_to_parse);
+                                    $stuff_to_parse = '';
+                                }
+                            }
+                        }
+                    }
+
+                    // Where are we adding this char?
+                    if (!$COMMENT_MATCHED) {
+                        $stuff_to_parse .= $char;
+                    } else {
+                        $result .= $test_str;
+                        unset($test_str);
+                        $COMMENT_MATCHED = false;
+                    }
+                }
+                // Parse the last bit
+                $result .= $this->parse_non_string_part($stuff_to_parse);
+                $stuff_to_parse = '';
+            } else {
+                $result .= $this->hsc($part);
+            }
+            // Close the <span> that surrounds the block
+            if ($STRICTATTRS != '') {
+                $result = str_replace("\n", "</span>\n<span$STRICTATTRS>", $result);
+                $result .= '</span>';
+            }
+
+            $endresult .= $result;
+            unset($part, $parts[$key], $result);
+        }
+
+        //This fix is related to SF#1923020, but has to be applied regardless of
+        //actually highlighting symbols.
+        /** NOTE: memorypeak #3 */
+        $endresult = str_replace(array('<SEMI>', '<PIPE>'), array(';', '|'), $endresult);
+
+//        // Parse the last stuff (redundant?)
+//        $result .= $this->parse_non_string_part($stuff_to_parse);
+
+        // Lop off the very first and last spaces
+//        $result = substr($result, 1, -1);
+
+        // We're finished: stop timing
+        $this->set_time($start_time, microtime());
+
+        $this->finalise($endresult);
+        return $endresult;
+    }
+
+    /**
+     * Swaps out spaces and tabs for HTML indentation. Not needed if
+     * the code is in a pre block...
+     *
+     * @param  string The source to indent (reference!)
+     * @since  1.0.0
+     * @access private
+     */
+    function indent(&$result) {
+        /// Replace tabs with the correct number of spaces
+        if (false !== strpos($result, "\t")) {
+            $lines = explode("\n", $result);
+            $result = null;//Save memory while we process the lines individually
+            $tab_width = $this->get_real_tab_width();
+            $tab_string = '&nbsp;' . str_repeat(' ', $tab_width);
+
+            for ($key = 0, $n = count($lines); $key < $n; $key++) {
+                $line = $lines[$key];
+                if (false === strpos($line, "\t")) {
+                    continue;
+                }
+
+                $pos = 0;
+                $length = strlen($line);
+                $lines[$key] = ''; // reduce memory
+
+                $IN_TAG = false;
+                for ($i = 0; $i < $length; ++$i) {
+                    $char = $line[$i];
+                    // Simple engine to work out whether we're in a tag.
+                    // If we are we modify $pos. This is so we ignore HTML
+                    // in the line and only workout the tab replacement
+                    // via the actual content of the string
+                    // This test could be improved to include strings in the
+                    // html so that < or > would be allowed in user's styles
+                    // (e.g. quotes: '<' '>'; or similar)
+                    if ($IN_TAG) {
+                        if ('>' == $char) {
+                            $IN_TAG = false;
+                        }
+                        $lines[$key] .= $char;
+                    } else if ('<' == $char) {
+                        $IN_TAG = true;
+                        $lines[$key] .= '<';
+                    } else if ('&' == $char) {
+                        $substr = substr($line, $i + 3, 5);
+                        $posi = strpos($substr, ';');
+                        if (false === $posi) {
+                            ++$pos;
+                        } else {
+                            $pos -= $posi+2;
+                        }
+                        $lines[$key] .= $char;
+                    } else if ("\t" == $char) {
+                        $str = '';
+                        // OPTIMISE - move $strs out. Make an array:
+                        // $tabs = array(
+                        //  1 => '&nbsp;',
+                        //  2 => '&nbsp; ',
+                        //  3 => '&nbsp; &nbsp;' etc etc
+                        // to use instead of building a string every time
+                        $tab_end_width = $tab_width - ($pos % $tab_width); //Moved out of the look as it doesn't change within the loop
+                        if (($pos & 1) || 1 == $tab_end_width) {
+                            $str .= substr($tab_string, 6, $tab_end_width);
+                        } else {
+                            $str .= substr($tab_string, 0, $tab_end_width+5);
+                        }
+                        $lines[$key] .= $str;
+                        $pos += $tab_end_width;
+
+                        if (false === strpos($line, "\t", $i + 1)) {
+                            $lines[$key] .= substr($line, $i + 1);
+                            break;
+                        }
+                    } else if (0 == $pos && ' ' == $char) {
+                        $lines[$key] .= '&nbsp;';
+                        ++$pos;
+                    } else {
+                        $lines[$key] .= $char;
+                        ++$pos;
+                    }
+                }
+            }
+            $result = implode("\n", $lines);
+            unset($lines);//We don't need the lines separated beyond this --- free them!
+        }
+        // Other whitespace
+        // BenBE: Fix to reduce the number of replacements to be done
+        $result = preg_replace('/^ /m', '&nbsp;', $result);
+        $result = str_replace('  ', ' &nbsp;', $result);
+
+        if ($this->line_numbers == GESHI_NO_LINE_NUMBERS) {
+            if ($this->line_ending === null) {
+                $result = nl2br($result);
+            } else {
+                $result = str_replace("\n", $this->line_ending, $result);
+            }
+        }
+    }
+
+    /**
+     * Changes the case of a keyword for those languages where a change is asked for
+     *
+     * @param  string The keyword to change the case of
+     * @return string The keyword with its case changed
+     * @since  1.0.0
+     * @access private
+     */
+    function change_case($instr) {
+        switch ($this->language_data['CASE_KEYWORDS']) {
+            case GESHI_CAPS_UPPER:
+                return strtoupper($instr);
+            case GESHI_CAPS_LOWER:
+                return strtolower($instr);
+            default:
+                return $instr;
+        }
+    }
+
+    /**
+     * Handles replacements of keywords to include markup and links if requested
+     *
+     * @param  string The keyword to add the Markup to
+     * @return The HTML for the match found
+     * @since  1.0.8
+     * @access private
+     *
+     * @todo   Get rid of ender in keyword links
+     */
+    function handle_keyword_replace($match) {
+        $k = $this->_kw_replace_group;
+        $keyword = $match[0];
+
+        $before = '';
+        $after = '';
+
+        if ($this->keyword_links) {
+            // Keyword links have been ebabled
+
+            if (isset($this->language_data['URLS'][$k]) &&
+                $this->language_data['URLS'][$k] != '') {
+                // There is a base group for this keyword
+
+                // Old system: strtolower
+                //$keyword = ( $this->language_data['CASE_SENSITIVE'][$group] ) ? $keyword : strtolower($keyword);
+                // New system: get keyword from language file to get correct case
+                if (!$this->language_data['CASE_SENSITIVE'][$k] &&
+                    strpos($this->language_data['URLS'][$k], '{FNAME}') !== false) {
+                    foreach ($this->language_data['KEYWORDS'][$k] as $word) {
+                        if (strcasecmp($word, $keyword) == 0) {
+                            break;
+                        }
+                    }
+                } else {
+                    $word = $keyword;
+                }
+
+                $before = '<|UR1|"' .
+                    str_replace(
+                        array(
+                            '{FNAME}',
+                            '{FNAMEL}',
+                            '{FNAMEU}',
+                            '.'),
+                        array(
+                            str_replace('+', '%20', urlencode($this->hsc($word))),
+                            str_replace('+', '%20', urlencode($this->hsc(strtolower($word)))),
+                            str_replace('+', '%20', urlencode($this->hsc(strtoupper($word)))),
+                            '<DOT>'),
+                        $this->language_data['URLS'][$k]
+                    ) . '">';
+                $after = '</a>';
+            }
+        }
+
+        return $before . '<|/'. $k .'/>' . $this->change_case($keyword) . '|>' . $after;
+    }
+
+    /**
+     * handles regular expressions highlighting-definitions with callback functions
+     *
+     * @note this is a callback, don't use it directly
+     *
+     * @param array the matches array
+     * @return The highlighted string
+     * @since 1.0.8
+     * @access private
+     */
+    function handle_regexps_callback($matches) {
+        // before: "' style=\"' . call_user_func(\"$func\", '\\1') . '\"\\1|>'",
+        return  ' style="' . call_user_func($this->language_data['STYLES']['REGEXPS'][$this->_rx_key], $matches[1]) . '"'. $matches[1] . '|>';
+    }
+
+    /**
+     * handles newlines in REGEXPS matches. Set the _hmr_* vars before calling this
+     *
+     * @note this is a callback, don't use it directly
+     *
+     * @param array the matches array
+     * @return string
+     * @since 1.0.8
+     * @access private
+     */
+    function handle_multiline_regexps($matches) {
+        $before = $this->_hmr_before;
+        $after = $this->_hmr_after;
+        if ($this->_hmr_replace) {
+            $replace = $this->_hmr_replace;
+            $search = array();
+
+            foreach (array_keys($matches) as $k) {
+                $search[] = '\\' . $k;
+            }
+
+            $before = str_replace($search, $matches, $before);
+            $after = str_replace($search, $matches, $after);
+            $replace = str_replace($search, $matches, $replace);
+        } else {
+            $replace = $matches[0];
+        }
+        return $before
+                    . '<|!REG3XP' . $this->_hmr_key .'!>'
+                        . str_replace("\n", "|>\n<|!REG3XP" . $this->_hmr_key . '!>', $replace)
+                    . '|>'
+              . $after;
+    }
+
+    /**
+     * Takes a string that has no strings or comments in it, and highlights
+     * stuff like keywords, numbers and methods.
+     *
+     * @param string The string to parse for keyword, numbers etc.
+     * @since 1.0.0
+     * @access private
+     * @todo BUGGY! Why? Why not build string and return?
+     */
+    function parse_non_string_part($stuff_to_parse) {
+        $stuff_to_parse = ' ' . $this->hsc($stuff_to_parse);
+
+        // Regular expressions
+        foreach ($this->language_data['REGEXPS'] as $key => $regexp) {
+            if ($this->lexic_permissions['REGEXPS'][$key]) {
+                if (is_array($regexp)) {
+                    if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+                        // produce valid HTML when we match multiple lines
+                        $this->_hmr_replace = $regexp[GESHI_REPLACE];
+                        $this->_hmr_before = $regexp[GESHI_BEFORE];
+                        $this->_hmr_key = $key;
+                        $this->_hmr_after = $regexp[GESHI_AFTER];
+                        $stuff_to_parse = preg_replace_callback(
+                            "/" . $regexp[GESHI_SEARCH] . "/{$regexp[GESHI_MODIFIERS]}",
+                            array($this, 'handle_multiline_regexps'),
+                            $stuff_to_parse);
+                        $this->_hmr_replace = false;
+                        $this->_hmr_before = '';
+                        $this->_hmr_after = '';
+                    } else {
+                        $stuff_to_parse = preg_replace(
+                            '/' . $regexp[GESHI_SEARCH] . '/' . $regexp[GESHI_MODIFIERS],
+                            $regexp[GESHI_BEFORE] . '<|!REG3XP'. $key .'!>' . $regexp[GESHI_REPLACE] . '|>' . $regexp[GESHI_AFTER],
+                            $stuff_to_parse);
+                    }
+                } else {
+                    if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+                        // produce valid HTML when we match multiple lines
+                        $this->_hmr_key = $key;
+                        $stuff_to_parse = preg_replace_callback( "/(" . $regexp . ")/",
+                                              array($this, 'handle_multiline_regexps'), $stuff_to_parse);
+                        $this->_hmr_key = '';
+                    } else {
+                        $stuff_to_parse = preg_replace( "/(" . $regexp . ")/", "<|!REG3XP$key!>\\1|>", $stuff_to_parse);
+                    }
+                }
+            }
+        }
+
+        // Highlight numbers. As of 1.0.8 we support diffent types of numbers
+        $numbers_found = false;
+        if ($this->lexic_permissions['NUMBERS'] && preg_match('#\d#', $stuff_to_parse )) {
+            $numbers_found = true;
+
+            //For each of the formats ...
+            foreach($this->language_data['NUMBERS_RXCACHE'] as $id => $regexp) {
+                //Check if it should be highlighted ...
+                $stuff_to_parse = preg_replace($regexp, "<|/NUM!$id/>\\1|>", $stuff_to_parse);
+            }
+        }
+
+        // Highlight keywords
+        $disallowed_before = "(?<![a-zA-Z0-9\$_\|\#;>|^&";
+        $disallowed_after = "(?![a-zA-Z0-9_\|%\\-&;";
+        if ($this->lexic_permissions['STRINGS']) {
+            $quotemarks = preg_quote(implode($this->language_data['QUOTEMARKS']), '/');
+            $disallowed_before .= $quotemarks;
+            $disallowed_after .= $quotemarks;
+        }
+        $disallowed_before .= "])";
+        $disallowed_after .= "])";
+
+        $parser_control_pergroup = false;
+        if (isset($this->language_data['PARSER_CONTROL'])) {
+            if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS'])) {
+                $x = 0; // check wether per-keyword-group parser_control is enabled
+                if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'])) {
+                    $disallowed_before = $this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'];
+                    ++$x;
+                }
+                if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'])) {
+                    $disallowed_after = $this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'];
+                    ++$x;
+                }
+                $parser_control_pergroup = (count($this->language_data['PARSER_CONTROL']['KEYWORDS']) - $x) > 0;
+            }
+        }
+
+        // if this is changed, don't forget to change it below
+//        if (!empty($disallowed_before)) {
+//            $disallowed_before = "(?<![$disallowed_before])";
+//        }
+//        if (!empty($disallowed_after)) {
+//            $disallowed_after = "(?![$disallowed_after])";
+//        }
+
+        foreach (array_keys($this->language_data['KEYWORDS']) as $k) {
+            if (!isset($this->lexic_permissions['KEYWORDS'][$k]) ||
+                $this->lexic_permissions['KEYWORDS'][$k]) {
+
+                $case_sensitive = $this->language_data['CASE_SENSITIVE'][$k];
+                $modifiers = $case_sensitive ? '' : 'i';
+
+                // NEW in 1.0.8 - per-keyword-group parser control
+                $disallowed_before_local = $disallowed_before;
+                $disallowed_after_local = $disallowed_after;
+                if ($parser_control_pergroup && isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$k])) {
+                    if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_BEFORE'])) {
+                        $disallowed_before_local =
+                            $this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_BEFORE'];
+                    }
+
+                    if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_AFTER'])) {
+                        $disallowed_after_local =
+                            $this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_AFTER'];
+                    }
+                }
+
+                $this->_kw_replace_group = $k;
+
+                //NEW in 1.0.8, the cached regexp list
+                // since we don't want PHP / PCRE to crash due to too large patterns we split them into smaller chunks
+                for ($set = 0, $set_length = count($this->language_data['CACHED_KEYWORD_LISTS'][$k]); $set <  $set_length; ++$set) {
+                    $keywordset =& $this->language_data['CACHED_KEYWORD_LISTS'][$k][$set];
+                    // Might make a more unique string for putting the number in soon
+                    // Basically, we don't put the styles in yet because then the styles themselves will
+                    // get highlighted if the language has a CSS keyword in it (like CSS, for example ;))
+                    $stuff_to_parse = preg_replace_callback(
+                        "/$disallowed_before_local({$keywordset})(?!\<DOT\>(?:htm|php))$disallowed_after_local/$modifiers",
+                        array($this, 'handle_keyword_replace'),
+                        $stuff_to_parse
+                        );
+                }
+            }
+        }
+
+        //
+        // Now that's all done, replace /[number]/ with the correct styles
+        //
+        foreach (array_keys($this->language_data['KEYWORDS']) as $k) {
+            if (!$this->use_classes) {
+                $attributes = ' style="' .
+                    (isset($this->language_data['STYLES']['KEYWORDS'][$k]) ?
+                    $this->language_data['STYLES']['KEYWORDS'][$k] : "") . '"';
+            } else {
+                $attributes = ' class="kw' . $k . '"';
+            }
+            $stuff_to_parse = str_replace("<|/$k/>", "<|$attributes>", $stuff_to_parse);
+        }
+
+        if ($numbers_found) {
+            // Put number styles in
+            foreach($this->language_data['NUMBERS_RXCACHE'] as $id => $regexp) {
+//Commented out for now, as this needs some review ...
+//                if ($numbers_permissions & $id) {
+                    //Get the appropriate style ...
+                        //Checking for unset styles is done by the style cache builder ...
+                    if (!$this->use_classes) {
+                        $attributes = ' style="' . $this->language_data['STYLES']['NUMBERS'][$id] . '"';
+                    } else {
+                        $attributes = ' class="nu'.$id.'"';
+                    }
+
+                    //Set in the correct styles ...
+                    $stuff_to_parse = str_replace("/NUM!$id/", $attributes, $stuff_to_parse);
+//                }
+            }
+        }
+
+        // Highlight methods and fields in objects
+        if ($this->lexic_permissions['METHODS'] && $this->language_data['OOLANG']) {
+            $oolang_spaces = "[\s]*";
+            $oolang_before = "";
+            $oolang_after = "[a-zA-Z][a-zA-Z0-9_]*";
+            if (isset($this->language_data['PARSER_CONTROL'])) {
+                if (isset($this->language_data['PARSER_CONTROL']['OOLANG'])) {
+                    if (isset($this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_BEFORE'])) {
+                        $oolang_before = $this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_BEFORE'];
+                    }
+                    if (isset($this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_AFTER'])) {
+                        $oolang_after = $this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_AFTER'];
+                    }
+                    if (isset($this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_SPACES'])) {
+                        $oolang_spaces = $this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_SPACES'];
+                    }
+                }
+            }
+
+            foreach ($this->language_data['OBJECT_SPLITTERS'] as $key => $splitter) {
+                if (false !== strpos($stuff_to_parse, $splitter)) {
+                    if (!$this->use_classes) {
+                        $attributes = ' style="' . $this->language_data['STYLES']['METHODS'][$key] . '"';
+                    } else {
+                        $attributes = ' class="me' . $key . '"';
+                    }
+                    $stuff_to_parse = preg_replace("/($oolang_before)(" . preg_quote($this->language_data['OBJECT_SPLITTERS'][$key], '/') . ")($oolang_spaces)($oolang_after)/", "\\1\\2\\3<|$attributes>\\4|>", $stuff_to_parse);
+                }
+            }
+        }
+
+        //
+        // Highlight brackets. Yes, I've tried adding a semi-colon to this list.
+        // You try it, and see what happens ;)
+        // TODO: Fix lexic permissions not converting entities if shouldn't
+        // be highlighting regardless
+        //
+        if ($this->lexic_permissions['BRACKETS']) {
+            $stuff_to_parse = str_replace( $this->language_data['CACHE_BRACKET_MATCH'],
+                              $this->language_data['CACHE_BRACKET_REPLACE'], $stuff_to_parse );
+        }
+
+
+        //FIX for symbol highlighting ...
+        if ($this->lexic_permissions['SYMBOLS'] && !empty($this->language_data['SYMBOLS'])) {
+            //Get all matches and throw away those witin a block that is already highlighted... (i.e. matched by a regexp)
+            $n_symbols = preg_match_all("/<\|(?:<DOT>|[^>])+>(?:(?!\|>).*?)\|>|<\/a>|(?:" . $this->language_data['SYMBOL_SEARCH'] . ")+/", $stuff_to_parse, $pot_symbols, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
+            $global_offset = 0;
+            for ($s_id = 0; $s_id < $n_symbols; ++$s_id) {
+                $symbol_match = $pot_symbols[$s_id][0][0];
+                if (strpos($symbol_match, '<') !== false || strpos($symbol_match, '>') !== false) {
+                    // already highlighted blocks _must_ include either < or >
+                    // so if this conditional applies, we have to skip this match
+                    // BenBE: UNLESS the block contains <SEMI> or <PIPE>
+                    if(strpos($symbol_match, '<SEMI>') === false &&
+                        strpos($symbol_match, '<PIPE>') === false) {
+                        continue;
+                    }
+                }
+
+                // if we reach this point, we have a valid match which needs to be highlighted
+
+                $symbol_length = strlen($symbol_match);
+                $symbol_offset = $pot_symbols[$s_id][0][1];
+                unset($pot_symbols[$s_id]);
+                $symbol_end = $symbol_length + $symbol_offset;
+                $symbol_hl = "";
+
+                // if we have multiple styles, we have to handle them properly
+                if ($this->language_data['MULTIPLE_SYMBOL_GROUPS']) {
+                    $old_sym = -1;
+                    // Split the current stuff to replace into its atomic symbols ...
+                    preg_match_all("/" . $this->language_data['SYMBOL_SEARCH'] . "/", $symbol_match, $sym_match_syms, PREG_PATTERN_ORDER);
+                    foreach ($sym_match_syms[0] as $sym_ms) {
+                        //Check if consequtive symbols belong to the same group to save output ...
+                        if (isset($this->language_data['SYMBOL_DATA'][$sym_ms])
+                            && ($this->language_data['SYMBOL_DATA'][$sym_ms] != $old_sym)) {
+                            if (-1 != $old_sym) {
+                                $symbol_hl .= "|>";
+                            }
+                            $old_sym = $this->language_data['SYMBOL_DATA'][$sym_ms];
+                            if (!$this->use_classes) {
+                                $symbol_hl .= '<| style="' . $this->language_data['STYLES']['SYMBOLS'][$old_sym] . '">';
+                            } else {
+                                $symbol_hl .= '<| class="sy' . $old_sym . '">';
+                            }
+                        }
+                        $symbol_hl .= $sym_ms;
+                    }
+                    unset($sym_match_syms);
+
+                    //Close remaining tags and insert the replacement at the right position ...
+                    //Take caution if symbol_hl is empty to avoid doubled closing spans.
+                    if (-1 != $old_sym) {
+                        $symbol_hl .= "|>";
+                    }
+                } else {
+                    if (!$this->use_classes) {
+                        $symbol_hl = '<| style="' . $this->language_data['STYLES']['SYMBOLS'][0] . '">';
+                    } else {
+                        $symbol_hl = '<| class="sy0">';
+                    }
+                    $symbol_hl .= $symbol_match . '|>';
+                }
+
+                $stuff_to_parse = substr_replace($stuff_to_parse, $symbol_hl, $symbol_offset + $global_offset, $symbol_length);
+
+                // since we replace old text with something of different size,
+                // we'll have to keep track of the differences
+                $global_offset += strlen($symbol_hl) - $symbol_length;
+            }
+        }
+        //FIX for symbol highlighting ...
+
+        // Add class/style for regexps
+        foreach (array_keys($this->language_data['REGEXPS']) as $key) {
+            if ($this->lexic_permissions['REGEXPS'][$key]) {
+                if (is_callable($this->language_data['STYLES']['REGEXPS'][$key])) {
+                    $this->_rx_key = $key;
+                    $stuff_to_parse = preg_replace_callback("/!REG3XP$key!(.*)\|>/U",
+                        array($this, 'handle_regexps_callback'),
+                        $stuff_to_parse);
+                } else {
+                    if (!$this->use_classes) {
+                        $attributes = ' style="' . $this->language_data['STYLES']['REGEXPS'][$key] . '"';
+                    } else {
+                        if (is_array($this->language_data['REGEXPS'][$key]) &&
+                            array_key_exists(GESHI_CLASS, $this->language_data['REGEXPS'][$key])) {
+                            $attributes = ' class="' .
+                                $this->language_data['REGEXPS'][$key][GESHI_CLASS] . '"';
+                        } else {
+                           $attributes = ' class="re' . $key . '"';
+                        }
+                    }
+                    $stuff_to_parse = str_replace("!REG3XP$key!", "$attributes", $stuff_to_parse);
+                }
+            }
+        }
+
+        // Replace <DOT> with . for urls
+        $stuff_to_parse = str_replace('<DOT>', '.', $stuff_to_parse);
+        // Replace <|UR1| with <a href= for urls also
+        if (isset($this->link_styles[GESHI_LINK])) {
+            if ($this->use_classes) {
+                $stuff_to_parse = str_replace('<|UR1|', '<a' . $this->link_target . ' href=', $stuff_to_parse);
+            } else {
+                $stuff_to_parse = str_replace('<|UR1|', '<a' . $this->link_target . ' style="' . $this->link_styles[GESHI_LINK] . '" href=', $stuff_to_parse);
+            }
+        } else {
+            $stuff_to_parse = str_replace('<|UR1|', '<a' . $this->link_target . ' href=', $stuff_to_parse);
+        }
+
+        //
+        // NOW we add the span thingy ;)
+        //
+
+        $stuff_to_parse = str_replace('<|', '<span', $stuff_to_parse);
+        $stuff_to_parse = str_replace ( '|>', '</span>', $stuff_to_parse );
+        return substr($stuff_to_parse, 1);
+    }
+
+    /**
+     * Sets the time taken to parse the code
+     *
+     * @param microtime The time when parsing started
+     * @param microtime The time when parsing ended
+     * @since 1.0.2
+     * @access private
+     */
+    function set_time($start_time, $end_time) {
+        $start = explode(' ', $start_time);
+        $end = explode(' ', $end_time);
+        $this->time = $end[0] + $end[1] - $start[0] - $start[1];
+    }
+
+    /**
+     * Gets the time taken to parse the code
+     *
+     * @return double The time taken to parse the code
+     * @since  1.0.2
+     */
+    function get_time() {
+        return $this->time;
+    }
+
+    /**
+     * Merges arrays recursively, overwriting values of the first array with values of later arrays
+     *
+     * @since 1.0.8
+     * @access private
+     */
+    function merge_arrays() {
+        $arrays = func_get_args();
+        $narrays = count($arrays);
+
+        // check arguments
+        // comment out if more performance is necessary (in this case the foreach loop will trigger a warning if the argument is not an array)
+        for ($i = 0; $i < $narrays; $i ++) {
+            if (!is_array($arrays[$i])) {
+                // also array_merge_recursive returns nothing in this case
+                trigger_error('Argument #' . ($i+1) . ' is not an array - trying to merge array with scalar! Returning false!', E_USER_WARNING);
+                return false;
+            }
+        }
+
+        // the first array is in the output set in every case
+        $ret = $arrays[0];
+
+        // merege $ret with the remaining arrays
+        for ($i = 1; $i < $narrays; $i ++) {
+            foreach ($arrays[$i] as $key => $value) {
+                if (is_array($value) && isset($ret[$key])) {
+                    // if $ret[$key] is not an array you try to merge an scalar value with an array - the result is not defined (incompatible arrays)
+                    // in this case the call will trigger an E_USER_WARNING and the $ret[$key] will be false.
+                    $ret[$key] = $this->merge_arrays($ret[$key], $value);
+                } else {
+                    $ret[$key] = $value;
+                }
+            }
+        }
+
+        return $ret;
+    }
+
+    /**
+     * Gets language information and stores it for later use
+     *
+     * @param string The filename of the language file you want to load
+     * @since 1.0.0
+     * @access private
+     * @todo Needs to load keys for lexic permissions for keywords, regexps etc
+     */
+    function load_language($file_name) {
+        if ($file_name == $this->loaded_language) {
+            // this file is already loaded!
+            return;
+        }
+
+        //Prepare some stuff before actually loading the language file
+        $this->loaded_language = $file_name;
+        $this->parse_cache_built = false;
+        $this->enable_highlighting();
+        $language_data = array();
+
+        //Load the language file
+        require $file_name;
+
+        // Perhaps some checking might be added here later to check that
+        // $language data is a valid thing but maybe not
+        $this->language_data = $language_data;
+
+        // Set strict mode if should be set
+        $this->strict_mode = $this->language_data['STRICT_MODE_APPLIES'];
+
+        // Set permissions for all lexics to true
+        // so they'll be highlighted by default
+        foreach (array_keys($this->language_data['KEYWORDS']) as $key) {
+            if (!empty($this->language_data['KEYWORDS'][$key])) {
+                $this->lexic_permissions['KEYWORDS'][$key] = true;
+            } else {
+                $this->lexic_permissions['KEYWORDS'][$key] = false;
+            }
+        }
+
+        foreach (array_keys($this->language_data['COMMENT_SINGLE']) as $key) {
+            $this->lexic_permissions['COMMENTS'][$key] = true;
+        }
+        foreach (array_keys($this->language_data['REGEXPS']) as $key) {
+            $this->lexic_permissions['REGEXPS'][$key] = true;
+        }
+
+        // for BenBE and future code reviews:
+        // we can use empty here since we only check for existance and emptiness of an array
+        // if it is not an array at all but rather false or null this will work as intended as well
+        // even if $this->language_data['PARSER_CONTROL'] is undefined this won't trigger a notice
+        if (!empty($this->language_data['PARSER_CONTROL']['ENABLE_FLAGS'])) {
+            foreach ($this->language_data['PARSER_CONTROL']['ENABLE_FLAGS'] as $flag => $value) {
+                // it's either true or false and maybe is true as well
+                $perm = $value !== GESHI_NEVER;
+                if ($flag == 'ALL') {
+                    $this->enable_highlighting($perm);
+                    continue;
+                }
+                if (!isset($this->lexic_permissions[$flag])) {
+                    // unknown lexic permission
+                    continue;
+                }
+                if (is_array($this->lexic_permissions[$flag])) {
+                    foreach ($this->lexic_permissions[$flag] as $key => $val) {
+                        $this->lexic_permissions[$flag][$key] = $perm;
+                    }
+                } else {
+                    $this->lexic_permissions[$flag] = $perm;
+                }
+            }
+            unset($this->language_data['PARSER_CONTROL']['ENABLE_FLAGS']);
+        }
+
+        //Fix: Problem where hardescapes weren't handled if no ESCAPE_CHAR was given
+        //You need to set one for HARDESCAPES only in this case.
+        if(!isset($this->language_data['HARDCHAR'])) {
+            $this->language_data['HARDCHAR'] = $this->language_data['ESCAPE_CHAR'];
+        }
+
+        //NEW in 1.0.8: Allow styles to be loaded from a separate file to override defaults
+        $style_filename = substr($file_name, 0, -4) . '.style.php';
+        if (is_readable($style_filename)) {
+            //Clear any style_data that could have been set before ...
+            if (isset($style_data)) {
+                unset($style_data);
+            }
+
+            //Read the Style Information from the style file
+            include $style_filename;
+
+            //Apply the new styles to our current language styles
+            if (isset($style_data) && is_array($style_data)) {
+                $this->language_data['STYLES'] =
+                    $this->merge_arrays($this->language_data['STYLES'], $style_data);
+            }
+        }
+    }
+
+    /**
+     * Takes the parsed code and various options, and creates the HTML
+     * surrounding it to make it look nice.
+     *
+     * @param  string The code already parsed (reference!)
+     * @since  1.0.0
+     * @access private
+     */
+    function finalise(&$parsed_code) {
+        // Remove end parts of important declarations
+        // This is BUGGY!! My fault for bad code: fix coming in 1.2
+        // @todo Remove this crap
+        if ($this->enable_important_blocks &&
+            (strpos($parsed_code, $this->hsc(GESHI_START_IMPORTANT)) === false)) {
+            $parsed_code = str_replace($this->hsc(GESHI_END_IMPORTANT), '', $parsed_code);
+        }
+
+        // Add HTML whitespace stuff if we're using the <div> header
+        if ($this->header_type != GESHI_HEADER_PRE && $this->header_type != GESHI_HEADER_PRE_VALID) {
+            $this->indent($parsed_code);
+        }
+
+        // purge some unnecessary stuff
+        /** NOTE: memorypeak #1 */
+        $parsed_code = preg_replace('#<span[^>]+>(\s*)</span>#', '\\1', $parsed_code);
+
+        // If we are using IDs for line numbers, there needs to be an overall
+        // ID set to prevent collisions.
+        if ($this->add_ids && !$this->overall_id) {
+            $this->overall_id = 'geshi-' . substr(md5(microtime()), 0, 4);
+        }
+
+        // Get code into lines
+        /** NOTE: memorypeak #2 */
+        $code = explode("\n", $parsed_code);
+        $parsed_code = $this->header();
+
+        // If we're using line numbers, we insert <li>s and appropriate
+        // markup to style them (otherwise we don't need to do anything)
+        if ($this->line_numbers != GESHI_NO_LINE_NUMBERS && $this->header_type != GESHI_HEADER_PRE_TABLE) {
+            // If we're using the <pre> header, we shouldn't add newlines because
+            // the <pre> will line-break them (and the <li>s already do this for us)
+            $ls = ($this->header_type != GESHI_HEADER_PRE && $this->header_type != GESHI_HEADER_PRE_VALID) ? "\n" : '';
+
+            // Set vars to defaults for following loop
+            $i = 0;
+
+            // Foreach line...
+            for ($i = 0, $n = count($code); $i < $n;) {
+                //Reset the attributes for a new line ...
+                $attrs = array();
+
+                // Make lines have at least one space in them if they're empty
+                // BenBE: Checking emptiness using trim instead of relying on blanks
+                if ('' == trim($code[$i])) {
+                    $code[$i] = '&nbsp;';
+                }
+
+                // If this is a "special line"...
+                if ($this->line_numbers == GESHI_FANCY_LINE_NUMBERS &&
+                    $i % $this->line_nth_row == ($this->line_nth_row - 1)) {
+                    // Set the attributes to style the line
+                    if ($this->use_classes) {
+                        //$attr = ' class="li2"';
+                        $attrs['class'][] = 'li2';
+                        $def_attr = ' class="de2"';
+                    } else {
+                        //$attr = ' style="' . $this->line_style2 . '"';
+                        $attrs['style'][] = $this->line_style2;
+                        // This style "covers up" the special styles set for special lines
+                        // so that styles applied to special lines don't apply to the actual
+                        // code on that line
+                        $def_attr = ' style="' . $this->code_style . '"';
+                    }
+                } else {
+                    if ($this->use_classes) {
+                        //$attr = ' class="li1"';
+                        $attrs['class'][] = 'li1';
+                        $def_attr = ' class="de1"';
+                    } else {
+                        //$attr = ' style="' . $this->line_style1 . '"';
+                        $attrs['style'][] = $this->line_style1;
+                        $def_attr = ' style="' . $this->code_style . '"';
+                    }
+                }
+
+                //Check which type of tag to insert for this line
+                if ($this->header_type == GESHI_HEADER_PRE_VALID) {
+                    $start = "<pre$def_attr>";
+                    $end = '</pre>';
+                } else {
+                    // Span or div?
+                    $start = "<div$def_attr>";
+                    $end = '</div>';
+                }
+
+                ++$i;
+
+                // Are we supposed to use ids? If so, add them
+                if ($this->add_ids) {
+                    $attrs['id'][] = "$this->overall_id-$i";
+                }
+
+                //Is this some line with extra styles???
+                if (in_array($i, $this->highlight_extra_lines)) {
+                    if ($this->use_classes) {
+                        if (isset($this->highlight_extra_lines_styles[$i])) {
+                            $attrs['class'][] = "lx$i";
+                        } else {
+                            $attrs['class'][] = "ln-xtra";
+                        }
+                    } else {
+                        array_push($attrs['style'], $this->get_line_style($i));
+                    }
+                }
+
+                // Add in the line surrounded by appropriate list HTML
+                $attr_string = '';
+                foreach ($attrs as $key => $attr) {
+                    $attr_string .= ' ' . $key . '="' . implode(' ', $attr) . '"';
+                }
+
+                $parsed_code .= "<li$attr_string>$start{$code[$i-1]}$end</li>$ls";
+                unset($code[$i - 1]);
+            }
+        } else {
+            $n = count($code);
+            if ($this->use_classes) {
+                $attributes = ' class="de1"';
+            } else {
+                $attributes = ' style="'. $this->code_style .'"';
+            }
+            if ($this->header_type == GESHI_HEADER_PRE_VALID) {
+                $parsed_code .= '<pre'. $attributes .'>';
+            } elseif ($this->header_type == GESHI_HEADER_PRE_TABLE) {
+                if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+                    if ($this->use_classes) {
+                        $attrs = ' class="ln"';
+                    } else {
+                        $attrs = ' style="'. $this->table_linenumber_style .'"';
+                    }
+                    $parsed_code .= '<td'.$attrs.'><pre'.$attributes.'>';
+                    // get linenumbers
+                    // we don't merge it with the for below, since it should be better for
+                    // memory consumption this way
+                    // @todo: but... actually it would still be somewhat nice to merge the two loops
+                    //        the mem peaks are at different positions
+                    for ($i = 0; $i < $n; ++$i) {
+                        $close = 0;
+                        // fancy lines
+                        if ($this->line_numbers == GESHI_FANCY_LINE_NUMBERS &&
+                            $i % $this->line_nth_row == ($this->line_nth_row - 1)) {
+                            // Set the attributes to style the line
+                            if ($this->use_classes) {
+                                $parsed_code .= '<span class="xtra li2"><span class="de2">';
+                            } else {
+                                // This style "covers up" the special styles set for special lines
+                                // so that styles applied to special lines don't apply to the actual
+                                // code on that line
+                                $parsed_code .= '<span style="display:block;' . $this->line_style2 . '">'
+                                                  .'<span style="' . $this->code_style .'">';
+                            }
+                            $close += 2;
+                        }
+                        //Is this some line with extra styles???
+                        if (in_array($i + 1, $this->highlight_extra_lines)) {
+                            if ($this->use_classes) {
+                                if (isset($this->highlight_extra_lines_styles[$i])) {
+                                    $parsed_code .= "<span class=\"xtra lx$i\">";
+                                } else {
+                                    $parsed_code .= "<span class=\"xtra ln-xtra\">";
+                                }
+                            } else {
+                                $parsed_code .= "<span style=\"display:block;" . $this->get_line_style($i) . "\">";
+                            }
+                            ++$close;
+                        }
+                        $parsed_code .= $this->line_numbers_start + $i;
+                        if ($close) {
+                            $parsed_code .= str_repeat('</span>', $close);
+                        } else if ($i != $n) {
+                            $parsed_code .= "\n";
+                        }
+                    }
+                    $parsed_code .= '</pre></td><td'.$attributes.'>';
+                }
+                $parsed_code .= '<pre'. $attributes .'>';
+            }
+            // No line numbers, but still need to handle highlighting lines extra.
+            // Have to use divs so the full width of the code is highlighted
+            $close = 0;
+            for ($i = 0; $i < $n; ++$i) {
+                // Make lines have at least one space in them if they're empty
+                // BenBE: Checking emptiness using trim instead of relying on blanks
+                if ('' == trim($code[$i])) {
+                    $code[$i] = '&nbsp;';
+                }
+                // fancy lines
+                if ($this->line_numbers == GESHI_FANCY_LINE_NUMBERS &&
+                    $i % $this->line_nth_row == ($this->line_nth_row - 1)) {
+                    // Set the attributes to style the line
+                    if ($this->use_classes) {
+                        $parsed_code .= '<span class="xtra li2"><span class="de2">';
+                    } else {
+                        // This style "covers up" the special styles set for special lines
+                        // so that styles applied to special lines don't apply to the actual
+                        // code on that line
+                        $parsed_code .= '<span style="display:block;' . $this->line_style2 . '">'
+                                          .'<span style="' . $this->code_style .'">';
+                    }
+                    $close += 2;
+                }
+                //Is this some line with extra styles???
+                if (in_array($i + 1, $this->highlight_extra_lines)) {
+                    if ($this->use_classes) {
+                        if (isset($this->highlight_extra_lines_styles[$i])) {
+                            $parsed_code .= "<span class=\"xtra lx$i\">";
+                        } else {
+                            $parsed_code .= "<span class=\"xtra ln-xtra\">";
+                        }
+                    } else {
+                        $parsed_code .= "<span style=\"display:block;" . $this->get_line_style($i) . "\">";
+                    }
+                    ++$close;
+                }
+
+                $parsed_code .= $code[$i];
+
+                if ($close) {
+                  $parsed_code .= str_repeat('</span>', $close);
+                  $close = 0;
+                }
+                elseif ($i + 1 < $n) {
+                    $parsed_code .= "\n";
+                }
+                unset($code[$i]);
+            }
+
+            if ($this->header_type == GESHI_HEADER_PRE_VALID || $this->header_type == GESHI_HEADER_PRE_TABLE) {
+                $parsed_code .= '</pre>';
+            }
+            if ($this->header_type == GESHI_HEADER_PRE_TABLE && $this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+                $parsed_code .= '</td>';
+            }
+        }
+
+        $parsed_code .= $this->footer();
+    }
+
+    /**
+     * Creates the header for the code block (with correct attributes)
+     *
+     * @return string The header for the code block
+     * @since  1.0.0
+     * @access private
+     */
+    function header() {
+        // Get attributes needed
+        /**
+         * @todo   Document behaviour change - class is outputted regardless of whether
+         *         we're using classes or not. Same with style
+         */
+        $attributes = ' class="' . $this->language;
+        if ($this->overall_class != '') {
+            $attributes .= " ".$this->overall_class;
+        }
+        $attributes .= '"';
+
+        if ($this->overall_id != '') {
+            $attributes .= " id=\"{$this->overall_id}\"";
+        }
+        if ($this->overall_style != '') {
+            $attributes .= ' style="' . $this->overall_style . '"';
+        }
+
+        $ol_attributes = '';
+
+        if ($this->line_numbers_start != 1) {
+            $ol_attributes .= ' start="' . $this->line_numbers_start . '"';
+        }
+
+        // Get the header HTML
+        $header = $this->header_content;
+        if ($header) {
+            if ($this->header_type == GESHI_HEADER_PRE || $this->header_type == GESHI_HEADER_PRE_VALID) {
+                $header = str_replace("\n", '', $header);
+            }
+            $header = $this->replace_keywords($header);
+
+            if ($this->use_classes) {
+                $attr = ' class="head"';
+            } else {
+                $attr = " style=\"{$this->header_content_style}\"";
+            }
+            if ($this->header_type == GESHI_HEADER_PRE_TABLE && $this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+                $header = "<thead><tr><td colspan=\"2\" $attr>$header</td></tr></thead>";
+            } else {
+                $header = "<div$attr>$header</div>";
+            }
+        }
+
+        if (GESHI_HEADER_NONE == $this->header_type) {
+            if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+                return "$header<ol$attributes$ol_attributes>";
+            }
+            return $header . ($this->force_code_block ? '<div>' : '');
+        }
+
+        // Work out what to return and do it
+        if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+            if ($this->header_type == GESHI_HEADER_PRE) {
+                return "<pre$attributes>$header<ol$ol_attributes>";
+            } else if ($this->header_type == GESHI_HEADER_DIV ||
+                $this->header_type == GESHI_HEADER_PRE_VALID) {
+                return "<div$attributes>$header<ol$ol_attributes>";
+            } else if ($this->header_type == GESHI_HEADER_PRE_TABLE) {
+                return "<table$attributes>$header<tbody><tr class=\"li1\">";
+            }
+        } else {
+            if ($this->header_type == GESHI_HEADER_PRE) {
+                return "<pre$attributes>$header"  .
+                    ($this->force_code_block ? '<div>' : '');
+            } else {
+                return "<div$attributes>$header" .
+                    ($this->force_code_block ? '<div>' : '');
+            }
+        }
+    }
+
+    /**
+     * Returns the footer for the code block.
+     *
+     * @return string The footer for the code block
+     * @since  1.0.0
+     * @access private
+     */
+    function footer() {
+        $footer = $this->footer_content;
+        if ($footer) {
+            if ($this->header_type == GESHI_HEADER_PRE) {
+                $footer = str_replace("\n", '', $footer);;
+            }
+            $footer = $this->replace_keywords($footer);
+
+            if ($this->use_classes) {
+                $attr = ' class="foot"';
+            } else {
+                $attr = " style=\"{$this->footer_content_style}\"";
+            }
+            if ($this->header_type == GESHI_HEADER_PRE_TABLE && $this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+                $footer = "<tfoot><tr><td colspan=\"2\">$footer</td></tr></tfoot>";
+            } else {
+                $footer = "<div$attr>$footer</div>";
+            }
+        }
+
+        if (GESHI_HEADER_NONE == $this->header_type) {
+            return ($this->line_numbers != GESHI_NO_LINE_NUMBERS) ? '</ol>' . $footer : $footer;
+        }
+
+        if ($this->header_type == GESHI_HEADER_DIV || $this->header_type == GESHI_HEADER_PRE_VALID) {
+            if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+                return "</ol>$footer</div>";
+            }
+            return ($this->force_code_block ? '</div>' : '') .
+                "$footer</div>";
+        }
+        elseif ($this->header_type == GESHI_HEADER_PRE_TABLE) {
+            if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+                return "</tr></tbody>$footer</table>";
+            }
+            return ($this->force_code_block ? '</div>' : '') .
+                "$footer</div>";
+        }
+        else {
+            if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+                return "</ol>$footer</pre>";
+            }
+            return ($this->force_code_block ? '</div>' : '') .
+                "$footer</pre>";
+        }
+    }
+
+    /**
+     * Replaces certain keywords in the header and footer with
+     * certain configuration values
+     *
+     * @param  string The header or footer content to do replacement on
+     * @return string The header or footer with replaced keywords
+     * @since  1.0.2
+     * @access private
+     */
+    function replace_keywords($instr) {
+        $keywords = $replacements = array();
+
+        $keywords[] = '<TIME>';
+        $keywords[] = '{TIME}';
+        $replacements[] = $replacements[] = number_format($time = $this->get_time(), 3);
+
+        $keywords[] = '<LANGUAGE>';
+        $keywords[] = '{LANGUAGE}';
+        $replacements[] = $replacements[] = $this->language_data['LANG_NAME'];
+
+        $keywords[] = '<VERSION>';
+        $keywords[] = '{VERSION}';
+        $replacements[] = $replacements[] = GESHI_VERSION;
+
+        $keywords[] = '<SPEED>';
+        $keywords[] = '{SPEED}';
+        if ($time <= 0) {
+            $speed = 'N/A';
+        } else {
+            $speed = strlen($this->source) / $time;
+            if ($speed >= 1024) {
+                $speed = sprintf("%.2f KB/s", $speed / 1024.0);
+            } else {
+                $speed = sprintf("%.0f B/s", $speed);
+            }
+        }
+        $replacements[] = $replacements[] = $speed;
+
+        return str_replace($keywords, $replacements, $instr);
+    }
+
+    /**
+     * Secure replacement for PHP built-in function htmlspecialchars().
+     *
+     * See ticket #427 (http://wush.net/trac/wikka/ticket/427) for the rationale
+     * for this replacement function.
+     *
+     * The INTERFACE for this function is almost the same as that for
+     * htmlspecialchars(), with the same default for quote style; however, there
+     * is no 'charset' parameter. The reason for this is as follows:
+     *
+     * The PHP docs say:
+     *      "The third argument charset defines character set used in conversion."
+     *
+     * I suspect PHP's htmlspecialchars() is working at the byte-value level and
+     * thus _needs_ to know (or asssume) a character set because the special
+     * characters to be replaced could exist at different code points in
+     * different character sets. (If indeed htmlspecialchars() works at
+     * byte-value level that goes some  way towards explaining why the
+     * vulnerability would exist in this function, too, and not only in
+     * htmlentities() which certainly is working at byte-value level.)
+     *
+     * This replacement function however works at character level and should
+     * therefore be "immune" to character set differences - so no charset
+     * parameter is needed or provided. If a third parameter is passed, it will
+     * be silently ignored.
+     *
+     * In the OUTPUT there is a minor difference in that we use '&#39;' instead
+     * of PHP's '&#039;' for a single quote: this provides compatibility with
+     *      get_html_translation_table(HTML_SPECIALCHARS, ENT_QUOTES)
+     * (see comment by mikiwoz at yahoo dot co dot uk on
+     * http://php.net/htmlspecialchars); it also matches the entity definition
+     * for XML 1.0
+     * (http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters).
+     * Like PHP we use a numeric character reference instead of '&apos;' for the
+     * single quote. For the other special characters we use the named entity
+     * references, as PHP is doing.
+     *
+     * @author      {@link http://wikkawiki.org/JavaWoman Marjolein Katsma}
+     *
+     * @license     http://www.gnu.org/copyleft/lgpl.html
+     *              GNU Lesser General Public License
+     * @copyright   Copyright 2007, {@link http://wikkawiki.org/CreditsPage
+     *              Wikka Development Team}
+     *
+     * @access      private
+     * @param       string  $string string to be converted
+     * @param       integer $quote_style
+     *                      - ENT_COMPAT:   escapes &, <, > and double quote (default)
+     *                      - ENT_NOQUOTES: escapes only &, < and >
+     *                      - ENT_QUOTES:   escapes &, <, >, double and single quotes
+     * @return      string  converted string
+     * @since       1.0.7.18
+     */
+    function hsc($string, $quote_style = ENT_COMPAT) {
+        // init
+        static $aTransSpecchar = array(
+            '&' => '&amp;',
+            '"' => '&quot;',
+            '<' => '&lt;',
+            '>' => '&gt;',
+
+            //This fix is related to SF#1923020, but has to be applied
+            //regardless of actually highlighting symbols.
+
+            //Circumvent a bug with symbol highlighting
+            //This is required as ; would produce undesirable side-effects if it
+            //was not to be processed as an entity.
+            ';' => '<SEMI>', // Force ; to be processed as entity
+            '|' => '<PIPE>' // Force | to be processed as entity
+            );                      // ENT_COMPAT set
+
+        switch ($quote_style) {
+            case ENT_NOQUOTES: // don't convert double quotes
+                unset($aTransSpecchar['"']);
+                break;
+            case ENT_QUOTES: // convert single quotes as well
+                $aTransSpecchar["'"] = '&#39;'; // (apos) htmlspecialchars() uses '&#039;'
+                break;
+        }
+
+        // return translated string
+        return strtr($string, $aTransSpecchar);
+    }
+
+    /**
+     * Returns a stylesheet for the highlighted code. If $economy mode
+     * is true, we only return the stylesheet declarations that matter for
+     * this code block instead of the whole thing
+     *
+     * @param  boolean Whether to use economy mode or not
+     * @return string A stylesheet built on the data for the current language
+     * @since  1.0.0
+     */
+    function get_stylesheet($economy_mode = true) {
+        // If there's an error, chances are that the language file
+        // won't have populated the language data file, so we can't
+        // risk getting a stylesheet...
+        if ($this->error) {
+            return '';
+        }
+
+        //Check if the style rearrangements have been processed ...
+        //This also does some preprocessing to check which style groups are useable ...
+        if(!isset($this->language_data['NUMBERS_CACHE'])) {
+            $this->build_style_cache();
+        }
+
+        // First, work out what the selector should be. If there's an ID,
+        // that should be used, the same for a class. Otherwise, a selector
+        // of '' means that these styles will be applied anywhere
+        if ($this->overall_id) {
+            $selector = '#' . $this->overall_id;
+        } else {
+            $selector = '.' . $this->language;
+            if ($this->overall_class) {
+                $selector .= '.' . $this->overall_class;
+            }
+        }
+        $selector .= ' ';
+
+        // Header of the stylesheet
+        if (!$economy_mode) {
+            $stylesheet = "/**\n".
+                " * GeSHi Dynamically Generated Stylesheet\n".
+                " * --------------------------------------\n".
+                " * Dynamically generated stylesheet for {$this->language}\n".
+                " * CSS class: {$this->overall_class}, CSS id: {$this->overall_id}\n".
+                " * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann\n" .
+                " * (http://qbnz.com/highlighter/ and http://geshi.org/)\n".
+                " * --------------------------------------\n".
+                " */\n";
+        } else {
+            $stylesheet = "/**\n".
+                " * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann\n" .
+                " * (http://qbnz.com/highlighter/ and http://geshi.org/)\n".
+                " */\n";
+        }
+
+        // Set the <ol> to have no effect at all if there are line numbers
+        // (<ol>s have margins that should be destroyed so all layout is
+        // controlled by the set_overall_style method, which works on the
+        // <pre> or <div> container). Additionally, set default styles for lines
+        if (!$economy_mode || $this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+            //$stylesheet .= "$selector, {$selector}ol, {$selector}ol li {margin: 0;}\n";
+            $stylesheet .= "$selector.de1, $selector.de2 {{$this->code_style}}\n";
+        }
+
+        // Add overall styles
+        // note: neglect economy_mode, empty styles are meaningless
+        if ($this->overall_style != '') {
+            $stylesheet .= "$selector {{$this->overall_style}}\n";
+        }
+
+        // Add styles for links
+        // note: economy mode does not make _any_ sense here
+        //       either the style is empty and thus no selector is needed
+        //       or the appropriate key is given.
+        foreach ($this->link_styles as $key => $style) {
+            if ($style != '') {
+                switch ($key) {
+                    case GESHI_LINK:
+                        $stylesheet .= "{$selector}a:link {{$style}}\n";
+                        break;
+                    case GESHI_HOVER:
+                        $stylesheet .= "{$selector}a:hover {{$style}}\n";
+                        break;
+                    case GESHI_ACTIVE:
+                        $stylesheet .= "{$selector}a:active {{$style}}\n";
+                        break;
+                    case GESHI_VISITED:
+                        $stylesheet .= "{$selector}a:visited {{$style}}\n";
+                        break;
+                }
+            }
+        }
+
+        // Header and footer
+        // note: neglect economy_mode, empty styles are meaningless
+        if ($this->header_content_style != '') {
+            $stylesheet .= "$selector.head {{$this->header_content_style}}\n";
+        }
+        if ($this->footer_content_style != '') {
+            $stylesheet .= "$selector.foot {{$this->footer_content_style}}\n";
+        }
+
+        // Styles for important stuff
+        // note: neglect economy_mode, empty styles are meaningless
+        if ($this->important_styles != '') {
+            $stylesheet .= "$selector.imp {{$this->important_styles}}\n";
+        }
+
+        // Simple line number styles
+        if ((!$economy_mode || $this->line_numbers != GESHI_NO_LINE_NUMBERS) && $this->line_style1 != '') {
+            $stylesheet .= "{$selector}li, {$selector}.li1 {{$this->line_style1}}\n";
+        }
+        if ((!$economy_mode || $this->line_numbers != GESHI_NO_LINE_NUMBERS) && $this->table_linenumber_style != '') {
+            $stylesheet .= "{$selector}.ln {{$this->table_linenumber_style}}\n";
+        }
+        // If there is a style set for fancy line numbers, echo it out
+        if ((!$economy_mode || $this->line_numbers == GESHI_FANCY_LINE_NUMBERS) && $this->line_style2 != '') {
+            $stylesheet .= "{$selector}.li2 {{$this->line_style2}}\n";
+        }
+
+        // note: empty styles are meaningless
+        foreach ($this->language_data['STYLES']['KEYWORDS'] as $group => $styles) {
+            if ($styles != '' && (!$economy_mode ||
+                (isset($this->lexic_permissions['KEYWORDS'][$group]) &&
+                $this->lexic_permissions['KEYWORDS'][$group]))) {
+                $stylesheet .= "$selector.kw$group {{$styles}}\n";
+            }
+        }
+        foreach ($this->language_data['STYLES']['COMMENTS'] as $group => $styles) {
+            if ($styles != '' && (!$economy_mode ||
+                (isset($this->lexic_permissions['COMMENTS'][$group]) &&
+                $this->lexic_permissions['COMMENTS'][$group]) ||
+                (!empty($this->language_data['COMMENT_REGEXP']) &&
+                !empty($this->language_data['COMMENT_REGEXP'][$group])))) {
+                $stylesheet .= "$selector.co$group {{$styles}}\n";
+            }
+        }
+        foreach ($this->language_data['STYLES']['ESCAPE_CHAR'] as $group => $styles) {
+            if ($styles != '' && (!$economy_mode || $this->lexic_permissions['ESCAPE_CHAR'])) {
+                // NEW: since 1.0.8 we have to handle hardescapes
+                if ($group === 'HARD') {
+                    $group = '_h';
+                }
+                $stylesheet .= "$selector.es$group {{$styles}}\n";
+            }
+        }
+        foreach ($this->language_data['STYLES']['BRACKETS'] as $group => $styles) {
+            if ($styles != '' && (!$economy_mode || $this->lexic_permissions['BRACKETS'])) {
+                $stylesheet .= "$selector.br$group {{$styles}}\n";
+            }
+        }
+        foreach ($this->language_data['STYLES']['SYMBOLS'] as $group => $styles) {
+            if ($styles != '' && (!$economy_mode || $this->lexic_permissions['SYMBOLS'])) {
+                $stylesheet .= "$selector.sy$group {{$styles}}\n";
+            }
+        }
+        foreach ($this->language_data['STYLES']['STRINGS'] as $group => $styles) {
+            if ($styles != '' && (!$economy_mode || $this->lexic_permissions['STRINGS'])) {
+                // NEW: since 1.0.8 we have to handle hardquotes
+                if ($group === 'HARD') {
+                    $group = '_h';
+                }
+                $stylesheet .= "$selector.st$group {{$styles}}\n";
+            }
+        }
+        foreach ($this->language_data['STYLES']['NUMBERS'] as $group => $styles) {
+            if ($styles != '' && (!$economy_mode || $this->lexic_permissions['NUMBERS'])) {
+                $stylesheet .= "$selector.nu$group {{$styles}}\n";
+            }
+        }
+        foreach ($this->language_data['STYLES']['METHODS'] as $group => $styles) {
+            if ($styles != '' && (!$economy_mode || $this->lexic_permissions['METHODS'])) {
+                $stylesheet .= "$selector.me$group {{$styles}}\n";
+            }
+        }
+        // note: neglect economy_mode, empty styles are meaningless
+        foreach ($this->language_data['STYLES']['SCRIPT'] as $group => $styles) {
+            if ($styles != '') {
+                $stylesheet .= "$selector.sc$group {{$styles}}\n";
+            }
+        }
+        foreach ($this->language_data['STYLES']['REGEXPS'] as $group => $styles) {
+            if ($styles != '' && (!$economy_mode ||
+                (isset($this->lexic_permissions['REGEXPS'][$group]) &&
+                $this->lexic_permissions['REGEXPS'][$group]))) {
+                if (is_array($this->language_data['REGEXPS'][$group]) &&
+                    array_key_exists(GESHI_CLASS, $this->language_data['REGEXPS'][$group])) {
+                    $stylesheet .= "$selector.";
+                    $stylesheet .= $this->language_data['REGEXPS'][$group][GESHI_CLASS];
+                    $stylesheet .= " {{$styles}}\n";
+                } else {
+                    $stylesheet .= "$selector.re$group {{$styles}}\n";
+                }
+            }
+        }
+        // Styles for lines being highlighted extra
+        if (!$economy_mode || (count($this->highlight_extra_lines)!=count($this->highlight_extra_lines_styles))) {
+            $stylesheet .= "{$selector}.ln-xtra, {$selector}li.ln-xtra, {$selector}div.ln-xtra {{$this->highlight_extra_lines_style}}\n";
+        }
+        $stylesheet .= "{$selector}span.xtra { display:block; }\n";
+        foreach ($this->highlight_extra_lines_styles as $lineid => $linestyle) {
+            $stylesheet .= "{$selector}.lx$lineid, {$selector}li.lx$lineid, {$selector}div.lx$lineid {{$linestyle}}\n";
+        }
+
+        return $stylesheet;
+    }
+
+    /**
+     * Get's the style that is used for the specified line
+     *
+     * @param int The line number information is requested for
+     * @access private
+     * @since 1.0.7.21
+     */
+    function get_line_style($line) {
+        //$style = null;
+        $style = null;
+        if (isset($this->highlight_extra_lines_styles[$line])) {
+            $style = $this->highlight_extra_lines_styles[$line];
+        } else { // if no "extra" style assigned
+            $style = $this->highlight_extra_lines_style;
+        }
+
+        return $style;
+    }
+
+    /**
+    * this functions creates an optimized regular expression list
+    * of an array of strings.
+    *
+    * Example:
+    * <code>$list = array('faa', 'foo', 'foobar');
+    *          => string 'f(aa|oo(bar)?)'</code>
+    *
+    * @param $list array of (unquoted) strings
+    * @param $regexp_delimiter your regular expression delimiter, @see preg_quote()
+    * @return string for regular expression
+    * @author Milian Wolff <mail@milianw.de>
+    * @since 1.0.8
+    * @access private
+    */
+    function optimize_regexp_list($list, $regexp_delimiter = '/') {
+        $regex_chars = array('.', '\\', '+', '*', '?', '[', '^', ']', '$',
+            '(', ')', '{', '}', '=', '!', '<', '>', '|', ':', $regexp_delimiter);
+        sort($list);
+        $regexp_list = array('');
+        $num_subpatterns = 0;
+        $list_key = 0;
+
+        // the tokens which we will use to generate the regexp list
+        $tokens = array();
+        $prev_keys = array();
+        // go through all entries of the list and generate the token list
+        $cur_len = 0;
+        for ($i = 0, $i_max = count($list); $i < $i_max; ++$i) {
+            if ($cur_len > GESHI_MAX_PCRE_LENGTH) {
+                // seems like the length of this pcre is growing exorbitantly
+                $regexp_list[++$list_key] = $this->_optimize_regexp_list_tokens_to_string($tokens);
+                $num_subpatterns = substr_count($regexp_list[$list_key], '(?:');
+                $tokens = array();
+                $cur_len = 0;
+            }
+            $level = 0;
+            $entry = preg_quote((string) $list[$i], $regexp_delimiter);
+            $pointer = &$tokens;
+            // properly assign the new entry to the correct position in the token array
+            // possibly generate smaller common denominator keys
+            while (true) {
+                // get the common denominator
+                if (isset($prev_keys[$level])) {
+                    if ($prev_keys[$level] == $entry) {
+                        // this is a duplicate entry, skip it
+                        continue 2;
+                    }
+                    $char = 0;
+                    while (isset($entry[$char]) && isset($prev_keys[$level][$char])
+                            && $entry[$char] == $prev_keys[$level][$char]) {
+                        ++$char;
+                    }
+                    if ($char > 0) {
+                        // this entry has at least some chars in common with the current key
+                        if ($char == strlen($prev_keys[$level])) {
+                            // current key is totally matched, i.e. this entry has just some bits appended
+                            $pointer = &$pointer[$prev_keys[$level]];
+                        } else {
+                            // only part of the keys match
+                            $new_key_part1 = substr($prev_keys[$level], 0, $char);
+                            $new_key_part2 = substr($prev_keys[$level], $char);
+
+                            if (in_array($new_key_part1[0], $regex_chars)
+                                || in_array($new_key_part2[0], $regex_chars)) {
+                                // this is bad, a regex char as first character
+                                $pointer[$entry] = array('' => true);
+                                array_splice($prev_keys, $level, count($prev_keys), $entry);
+                                $cur_len += strlen($entry);
+                                continue;
+                            } else {
+                                // relocate previous tokens
+                                $pointer[$new_key_part1] = array($new_key_part2 => $pointer[$prev_keys[$level]]);
+                                unset($pointer[$prev_keys[$level]]);
+                                $pointer = &$pointer[$new_key_part1];
+                                // recreate key index
+                                array_splice($prev_keys, $level, count($prev_keys), array($new_key_part1, $new_key_part2));
+                                $cur_len += strlen($new_key_part2);
+                            }
+                        }
+                        ++$level;
+                        $entry = substr($entry, $char);
+                        continue;
+                    }
+                    // else: fall trough, i.e. no common denominator was found
+                }
+                if ($level == 0 && !empty($tokens)) {
+                    // we can dump current tokens into the string and throw them away afterwards
+                    $new_entry = $this->_optimize_regexp_list_tokens_to_string($tokens);
+                    $new_subpatterns = substr_count($new_entry, '(?:');
+                    if (GESHI_MAX_PCRE_SUBPATTERNS && $num_subpatterns + $new_subpatterns > GESHI_MAX_PCRE_SUBPATTERNS) {
+                        $regexp_list[++$list_key] = $new_entry;
+                        $num_subpatterns = $new_subpatterns;
+                    } else {
+                        if (!empty($regexp_list[$list_key])) {
+                            $new_entry = '|' . $new_entry;
+                        }
+                        $regexp_list[$list_key] .= $new_entry;
+                        $num_subpatterns += $new_subpatterns;
+                    }
+                    $tokens = array();
+                    $cur_len = 0;
+                }
+                // no further common denominator found
+                $pointer[$entry] = array('' => true);
+                array_splice($prev_keys, $level, count($prev_keys), $entry);
+
+                $cur_len += strlen($entry);
+                break;
+            }
+            unset($list[$i]);
+        }
+        // make sure the last tokens get converted as well
+        $new_entry = $this->_optimize_regexp_list_tokens_to_string($tokens);
+        if (GESHI_MAX_PCRE_SUBPATTERNS && $num_subpatterns + substr_count($new_entry, '(?:') > GESHI_MAX_PCRE_SUBPATTERNS) {
+            $regexp_list[++$list_key] = $new_entry;
+        } else {
+            if (!empty($regexp_list[$list_key])) {
+                $new_entry = '|' . $new_entry;
+            }
+            $regexp_list[$list_key] .= $new_entry;
+        }
+        return $regexp_list;
+    }
+    /**
+    * this function creates the appropriate regexp string of an token array
+    * you should not call this function directly, @see $this->optimize_regexp_list().
+    *
+    * @param &$tokens array of tokens
+    * @param $recursed bool to know wether we recursed or not
+    * @return string
+    * @author Milian Wolff <mail@milianw.de>
+    * @since 1.0.8
+    * @access private
+    */
+    function _optimize_regexp_list_tokens_to_string(&$tokens, $recursed = false) {
+        $list = '';
+        foreach ($tokens as $token => $sub_tokens) {
+            $list .= $token;
+            $close_entry = isset($sub_tokens['']);
+            unset($sub_tokens['']);
+            if (!empty($sub_tokens)) {
+                $list .= '(?:' . $this->_optimize_regexp_list_tokens_to_string($sub_tokens, true) . ')';
+                if ($close_entry) {
+                    // make sub_tokens optional
+                    $list .= '?';
+                }
+            }
+            $list .= '|';
+        }
+        if (!$recursed) {
+            // do some optimizations
+            // common trailing strings
+            // BUGGY!
+            //$list = preg_replace_callback('#(?<=^|\:|\|)\w+?(\w+)(?:\|.+\1)+(?=\|)#', create_function(
+            //    '$matches', 'return "(?:" . preg_replace("#" . preg_quote($matches[1], "#") . "(?=\||$)#", "", $matches[0]) . ")" . $matches[1];'), $list);
+            // (?:p)? => p?
+            $list = preg_replace('#\(\?\:(.)\)\?#', '\1?', $list);
+            // (?:a|b|c|d|...)? => [abcd...]?
+            // TODO: a|bb|c => [ac]|bb
+            static $callback_2;
+            if (!isset($callback_2)) {
+                $callback_2 = create_function('$matches', 'return "[" . str_replace("|", "", $matches[1]) . "]";');
+            }
+            $list = preg_replace_callback('#\(\?\:((?:.\|)+.)\)#', $callback_2, $list);
+        }
+        // return $list without trailing pipe
+        return substr($list, 0, -1);
+    }
+} // End Class GeSHi
+
+
+if (!function_exists('geshi_highlight')) {
+    /**
+     * Easy way to highlight stuff. Behaves just like highlight_string
+     *
+     * @param string The code to highlight
+     * @param string The language to highlight the code in
+     * @param string The path to the language files. You can leave this blank if you need
+     *               as from version 1.0.7 the path should be automatically detected
+     * @param boolean Whether to return the result or to echo
+     * @return string The code highlighted (if $return is true)
+     * @since 1.0.2
+     */
+    function geshi_highlight($string, $language, $path = null, $return = false) {
+        $geshi = new GeSHi($string, $language, $path);
+        $geshi->set_header_type(GESHI_HEADER_NONE);
+
+        if ($return) {
+            return '<code>' . $geshi->parse_code() . '</code>';
+        }
+
+        echo '<code>' . $geshi->parse_code() . '</code>';
+
+        if ($geshi->error()) {
+            return false;
+        }
+        return true;
+    }
+}
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/abap.php b/examples/includes/geshi/geshi/abap.php
new file mode 100644 (file)
index 0000000..ffd8d10
--- /dev/null
@@ -0,0 +1,1419 @@
+<?php
+/*************************************************************************************
+ * abap.php
+ * --------
+ * Author: Andres Picazo (andres@andrespicazo.com)
+ * Contributors:
+ *  - Sandra Rossi (sandra.rossi@gmail.com)
+ *  - Jacob Laursen (jlu@kmd.dk)
+ * Copyright: (c) 2007 Andres Picazo
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/06/04
+ *
+ * ABAP language file for GeSHi.
+ *
+ * Reference abap language documentation (abap 7.1) : http://help.sap.com/abapdocu/en/ABENABAP_INDEX.htm
+ *
+ * ABAP syntax is highly complex, several problems could not be addressed, see TODO below if you dare ;-)
+ * Be aware that in ABAP language, keywords may be composed of several tokens,
+ *    separated by one or more spaces or carriage returns
+ *    (for example CONCATENATE 'hello' 'world' INTO string SEPARATED  BY ' ')
+ *    it's why we must decode them with REGEXPS. As there are many keywords with several tokens,
+ *    I had to create a separate section in the code to simplify the reading.
+ * Be aware that some words may be highlighted several times like for "ref to data", which is first
+ *    highlighted for "ref to data", then secondly for "ref to". It is very important to
+ *    position "ref to" after "ref to data" otherwise "data" wouldn't be highlighted because
+ *    of the previous highlight.
+ * Styles used : keywords are all displayed in upper case, and they are organized into 4 categories :
+ *    1) control statements (blue), 2) declarative statements (red-maroon),
+ *    3) other statements (blue-green), 4) keywords (violet).
+ *    + GeSHi : literals (red) + symbols (green) + methods/attributes (mauve)
+ *    + unchanged style for other words.
+ * Control, declarative and other statements are assigned URLs to sap documentation website:
+ *    http://help.sap.com/abapdocu/en/ABAP<statement_name>.htm
+ *
+ * CHANGES
+ * -------
+ * 2009/02/25 (1.0.8.3)
+ *   -  Some more rework of the language file
+ * 2009/01/04 (1.0.8.2)
+ *   -  Major Release, more than 1000 statements and keywords added = whole abap 7.1 (Sandra Rossi)
+ * 2007/06/27 (1.0.0)
+ *   -  First Release
+ *
+ * TODO
+ * ----
+ *   - in DATA data TYPE type, 2nd "data" and 2nd "type" are highlighted with data
+ *     style, but should be ignored. Same problem for all words!!! This is quite impossible to
+ *     solve it as we should define syntaxes of all statements (huge effort!) and use a lex
+ *     or something like that instead of regexp I guess.
+ *   - Some words are considered as being statement names (report, tables, etc.) though they
+ *     are used as keyword in some statements. For example: FORM xxxx TABLES itab. It was
+ *     arbitrary decided to define them as statement instead of keyword, because it may be
+ *     useful to have the URL to SAP help for some of them.
+ *   - if a comment is between 2 words of a keyword (for example SEPARATED "comment \n BY),
+ *     it is not considered as a keyword, but it should!
+ *   - for statements like "READ DATASET", GeSHi does not allow to set URLs because these
+ *     statements are determined by REGEXPS. For "READ DATASET", the URL should be
+ *     ABAPREAD_DATASET.htm. If a technical solution is found, be careful : URLs
+ *     are sometimes not valid because the URL does not exist. For example, for "AT NEW"
+ *     statement, the URL should be ABAPAT_ITAB.htm (not ABAPAT_NEW.htm).
+ *     There are many other exceptions.
+ *     Note: for adding this functionality within your php program, you can execute this code:
+ *       function add_urls_to_multi_tokens( $matches ) {
+ *           $url = preg_replace( "/[ \n]+/" , "_" , $matches[3] );
+ *           if( $url == $matches[3] ) return $matches[0] ;
+ *           else return $matches[1]."<a href=\"http://help.sap.com/abapdocu/en/ABAP".strtoupper($url).".htm\">".$matches[3]."</a>".$matches[4];
+ *           }
+ *       $html = $geshi->parse_code();
+ *       $html = preg_replace_callback( "£(zzz:(control|statement|data);\">)(.+?)(</span>)£s", "add_urls_to_multi_tokens", $html );
+ *       echo $html;
+ *   - Numbers followed by a dot terminating the statement are not properly recognized
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array(
+    'LANG_NAME' => 'ABAP',
+    'COMMENT_SINGLE' => array(
+        1 => '"'
+        ),
+    'COMMENT_MULTI' => array(),
+    'COMMENT_REGEXP' => array(
+        // lines beginning with star at 1st position are comments
+        // (star anywhere else is not a comment, especially be careful with
+        // "assign dref->* to <fs>" statement)
+        2 => '/^\*.*?$/m'
+        ),
+    'CASE_KEYWORDS' => 0,
+    'QUOTEMARKS' => array(
+        1 => "'",
+        2 => "`"
+        ),
+    'ESCAPE_CHAR' => '',
+
+    'KEYWORDS' => array(
+        //***********************************************
+        // Section 2 : process sequences of several tokens
+        //***********************************************
+
+        7 => array(
+            'at new',
+            'at end of',
+            'at first',
+            'at last',
+            'loop at',
+            'loop at screen',
+            ),
+
+        8 => array(
+            'private section',
+            'protected section',
+            'public section',
+            'at line-selection',
+            'at selection-screen',
+            'at user-command',
+            'assign component',
+            'assign table field',
+            'call badi',
+            'call customer-function',
+            'call customer subscreen',
+            'call dialog',
+            'call function',
+            'call method',
+            'call screen',
+            'call selection-screen',
+            'call transaction',
+            'call transformation',
+            'close cursor',
+            'close dataset',
+            'commit work',
+            'convert date',
+            'convert text',
+            'convert time stamp',
+            'create data',
+            'create object',
+            'delete dataset',
+            'delete from',
+            'describe distance',
+            'describe field',
+            'describe list',
+            'describe table',
+            'exec sql',
+            'exit from sql',
+            'exit from step-loop',
+            'export dynpro',
+            'export nametab',
+            'free memory',
+            'generate subroutine-pool',
+            'get badi',
+            'get bit',
+            'get cursor',
+            'get dataset',
+            'get locale',
+            'get parameter',
+            'get pf-status',
+            'get property',
+            'get reference',
+            'get run time',
+            'get time',
+            'get time stamp',
+            'import directory',
+            'insert report',
+            'insert text-pool',
+            'leave list-processing',
+            'leave program',
+            'leave screen',
+            'leave to list-processing',
+            'leave to transaction',
+            'modify line',
+            'modify screen',
+            'move percentage',
+            'open cursor',
+            'open dataset',
+            'raise event',
+            'raise exception',
+            'read dataset',
+            'read line',
+            'read report',
+            'read table',
+            'read textpool',
+            'receive results from function',
+            'refresh control',
+            'rollback work',
+            'set bit',
+            'set blank lines',
+            'set country',
+            'set cursor',
+            'set dataset',
+            'set extended check',
+            'set handler',
+            'set hold data',
+            'set language',
+            'set left scroll-boundary',
+            'set locale',
+            'set margin',
+            'set parameter',
+            'set pf-status',
+            'set property',
+            'set run time analyzer',
+            'set run time clock',
+            'set screen',
+            'set titlebar',
+            'set update task',
+            'set user-command',
+            'suppress dialog',
+            'truncate dataset',
+            'wait until',
+            'wait up to',
+            ),
+
+        9 => array(
+            'accepting duplicate keys',
+            'accepting padding',
+            'accepting truncation',
+            'according to',
+            'actual length',
+            'adjacent duplicates',
+            'after input',
+            'all blob columns',
+            'all clob columns',
+            'all fields',
+            'all methods',
+            'all other columns',
+            'and mark',
+            'and return to screen',
+            'and return',
+            'and skip first screen',
+            'and wait',
+            'any table',
+            'appendage type',
+            'archive mode',
+            'archiving parameters',
+            'area handle',
+            'as checkbox',
+            'as icon',
+            'as line',
+            'as listbox',
+            'as person table',
+            'as search patterns',
+            'as separate unit',
+            'as subscreen',
+            'as symbol',
+            'as text',
+            'as window',
+            'at cursor-selection',
+            'at exit-command',
+            'at next application statement',
+            'at position',
+
+            'backup into',
+            'before output',
+            'before unwind',
+            'begin of block',
+            'begin of common part',
+            'begin of line',
+            'begin of screen',
+            'begin of tabbed block',
+            'begin of version',
+            'begin of',
+            'big endian',
+            'binary mode',
+            'binary search',
+            'by kernel module',
+            'bypassing buffer',
+
+            'client specified',
+            'code page',
+            'code page hint',
+            'code page into',
+            'color black',
+            'color blue',
+            'color green',
+            'color pink',
+            'color red',
+            'color yellow',
+            'compression off',
+            'compression on',
+            'connect to',
+            'corresponding fields of table',
+            'corresponding fields of',
+            'cover page',
+            'cover text',
+            'create package',
+            'create private',
+            'create protected',
+            'create public',
+            'current position',
+
+            'data buffer',
+            'data values',
+            'dataset expiration',
+            'daylight saving time',
+            'default key',
+            'default program',
+            'default screen',
+            'defining database',
+            'deleting leading',
+            'deleting trailing',
+            'directory entry',
+            'display like',
+            'display offset',
+            'during line-selection',
+            'dynamic selections',
+
+            'edit mask',
+            'end of block',
+            'end of common part',
+            'end of file',
+            'end of line',
+            'end of screen',
+            'end of tabbed block',
+            'end of version',
+            'end of',
+            'endian into',
+            'ending at',
+            'enhancement options into',
+            'enhancement into',
+            'environment time format',
+            'execute procedure',
+            'exporting list to memory',
+            'extension type',
+
+            'field format',
+            'field selection',
+            'field value into',
+            'final methods',
+            'first occurrence of',
+            'fixed-point arithmetic',
+            'for all entries',
+            'for all instances',
+            'for appending',
+            'for columns',
+            'for event of',
+            'for field',
+            'for high',
+            'for input',
+            'for lines',
+            'for low',
+            'for node',
+            'for output',
+            'for select',
+            'for table',
+            'for testing',
+            'for update',
+            'for user',
+            'frame entry',
+            'frame program from',
+            'from code page',
+            'from context',
+            'from database',
+            'from logfile id',
+            'from number format',
+            'from screen',
+            'from table',
+            'function key',
+
+            'get connection',
+            'global friends',
+            'group by',
+
+            'hashed table of',
+            'hashed table',
+
+            'if found',
+            'ignoring case',
+            'ignoring conversion errors',
+            'ignoring structure boundaries',
+            'implementations from',
+            'in background',
+            'in background task',
+            'in background unit',
+            'in binary mode',
+            'in byte mode',
+            'in char-to-hex mode',
+            'in character mode',
+            'in group',
+            'in legacy binary mode',
+            'in legacy text mode',
+            'in program',
+            'in remote task',
+            'in text mode',
+            'in table',
+            'in update task',
+            'include bound',
+            'include into',
+            'include program from',
+            'include structure',
+            'include type',
+            'including gaps',
+            'index table',
+            'inheriting from',
+            'init destination',
+            'initial line of',
+            'initial line',
+            'initial size',
+            'internal table',
+            'into sortable code',
+
+            'keep in spool',
+            'keeping directory entry',
+            'keeping logical unit of work',
+            'keeping task',
+            'keywords from',
+
+            'left margin',
+            'left outer',
+            'levels into',
+            'line format',
+            'line into',
+            'line of',
+            'line page',
+            'line value from',
+            'line value into',
+            'lines of',
+            'list authority',
+            'list dataset',
+            'list name',
+            'little endian',
+            'lob handle for',
+            'local friends',
+            'locator for',
+            'lower case',
+
+            'main table field',
+            'match count',
+            'match length',
+            'match line',
+            'match offset',
+            'matchcode object',
+            'maximum length',
+            'maximum width into',
+            'memory id',
+            'message into',
+            'messages into',
+            'modif id',
+
+            'nesting level',
+            'new list identification',
+            'next cursor',
+            'no database selection',
+            'no dialog',
+            'no end of line',
+            'no fields',
+            'no flush',
+            'no intervals',
+            'no intervals off',
+            'no standard page heading',
+            'no-extension off',
+            'non-unique key',
+            'non-unique sorted key',
+            'not at end of mode',
+            'number of lines',
+            'number of pages',
+
+            'object key',
+            'obligatory off',
+            'of current page',
+            'of page',
+            'of program',
+            'offset into',
+            'on block',
+            'on commit',
+            'on end of task',
+            'on end of',
+            'on exit-command',
+            'on help-request for',
+            'on radiobutton group',
+            'on rollback',
+            'on value-request for',
+            'open for package',
+            'option class-coding',
+            'option class',
+            'option coding',
+            'option expand',
+            'option syncpoints',
+            'options from',
+            'order by',
+            'overflow into',
+
+            'package section',
+            'package size',
+            'preferred parameter',
+            'preserving identifier escaping',
+            'primary key',
+            'print off',
+            'print on',
+            'program from',
+            'program type',
+
+            'radiobutton groups',
+            'radiobutton group',
+            'range of',
+            'reader for',
+            'receive buffer',
+            'reduced functionality',
+            'ref to data',
+            'ref to object',
+            'ref to',
+
+            'reference into',
+            'renaming with suffix',
+            'replacement character',
+            'replacement count',
+            'replacement length',
+            'replacement line',
+            'replacement offset',
+            'respecting blanks',
+            'respecting case',
+            'result into',
+            'risk level',
+
+            'sap cover page',
+            'search fkeq',
+            'search fkge',
+            'search gkeq',
+            'search gkge',
+            'section of',
+            'send buffer',
+            'separated by',
+            'shared buffer',
+            'shared memory',
+            'shared memory enabled',
+            'skipping byte-order mark',
+            'sorted by',
+            'sorted table of',
+            'sorted table',
+            'spool parameters',
+            'standard table of',
+            'standard table',
+            'starting at',
+            'starting new task',
+            'statements into',
+            'structure default',
+            'structures into',
+
+            'table field',
+            'table of',
+            'text mode',
+            'time stamp',
+            'time zone',
+            'to code page',
+            'to column',
+            'to context',
+            'to first page',
+            'to last page',
+            'to last line',
+            'to line',
+            'to lower case',
+            'to number format',
+            'to page',
+            'to sap spool',
+            'to upper case',
+            'tokens into',
+            'transporting no fields',
+            'type tableview',
+            'type tabstrip',
+
+            'unicode enabling',
+            'up to',
+            'upper case',
+            'using edit mask',
+            'using key',
+            'using no edit mask',
+            'using screen',
+            'using selection-screen',
+            'using selection-set',
+            'using selection-sets of program',
+
+            'valid between',
+            'valid from',
+            'value check',
+            'via job',
+            'via selection-screen',
+            'visible length',
+
+            'whenever found',
+            'with analysis',
+            'with byte-order mark',
+            'with comments',
+            'with current switchstates',
+            'with explicit enhancements',
+            'with frame',
+            'with free selections',
+            'with further secondary keys',
+            'with header line',
+            'with hold',
+            'with implicit enhancements',
+            'with inactive enhancements',
+            'with includes',
+            'with key',
+            'with linefeed',
+            'with list tokenization',
+            'with native linefeed',
+            'with non-unique key',
+            'with null',
+            'with pragmas',
+            'with precompiled headers',
+            'with selection-table',
+            'with smart linefeed',
+            'with table key',
+            'with test code',
+            'with type-pools',
+            'with unique key',
+            'with unix linefeed',
+            'with windows linefeed',
+            'without further secondary keys',
+            'without selection-screen',
+            'without spool dynpro',
+            'without trmac',
+            'word into',
+            'writer for'
+            ),
+
+        //**********************************************************
+        // Other abap statements
+        //**********************************************************
+        3 => array(
+            'add',
+            'add-corresponding',
+            'aliases',
+            'append',
+            'assign',
+            'at',
+            'authority-check',
+
+            'break-point',
+
+            'clear',
+            'collect',
+            'compute',
+            'concatenate',
+            'condense',
+            'class',
+            'class-events',
+            'class-methods',
+            'class-pool',
+
+            'define',
+            'delete',
+            'demand',
+            'detail',
+            'divide',
+            'divide-corresponding',
+
+            'editor-call',
+            'end-of-file',
+            'end-enhancement-section',
+            'end-of-definition',
+            'end-of-page',
+            'end-of-selection',
+            'endclass',
+            'endenhancement',
+            'endexec',
+            'endform',
+            'endfunction',
+            'endinterface',
+            'endmethod',
+            'endmodule',
+            'endon',
+            'endprovide',
+            'endselect',
+            'enhancement',
+            'enhancement-point',
+            'enhancement-section',
+            'export',
+            'extract',
+            'events',
+
+            'fetch',
+            'field-groups',
+            'find',
+            'format',
+            'form',
+            'free',
+            'function-pool',
+            'function',
+
+            'get',
+
+            'hide',
+
+            'import',
+            'infotypes',
+            'input',
+            'insert',
+            'include',
+            'initialization',
+            'interface',
+            'interface-pool',
+            'interfaces',
+
+            'leave',
+            'load-of-program',
+            'log-point',
+
+            'maximum',
+            'message',
+            'methods',
+            'method',
+            'minimum',
+            'modify',
+            'move',
+            'move-corresponding',
+            'multiply',
+            'multiply-corresponding',
+
+            'new-line',
+            'new-page',
+            'new-section',
+
+            'overlay',
+
+            'pack',
+            'perform',
+            'position',
+            'print-control',
+            'program',
+            'provide',
+            'put',
+
+            'raise',
+            'refresh',
+            'reject',
+            'replace',
+            'report',
+            'reserve',
+
+            'scroll',
+            'search',
+            'select',
+            'selection-screen',
+            'shift',
+            'skip',
+            'sort',
+            'split',
+            'start-of-selection',
+            'submit',
+            'subtract',
+            'subtract-corresponding',
+            'sum',
+            'summary',
+            'summing',
+            'supply',
+            'syntax-check',
+
+            'top-of-page',
+            'transfer',
+            'translate',
+            'type-pool',
+
+            'uline',
+            'unpack',
+            'update',
+
+            'window',
+            'write'
+
+            ),
+
+        //**********************************************************
+        // keywords
+        //**********************************************************
+
+        4 => array(
+            'abbreviated',
+            'abstract',
+            'accept',
+            'acos',
+            'activation',
+            'alias',
+            'align',
+            'all',
+            'allocate',
+            'and',
+            'assigned',
+            'any',
+            'appending',
+            'area',
+            'as',
+            'ascending',
+            'asin',
+            'assigning',
+            'atan',
+            'attributes',
+            'avg',
+
+            'backward',
+            'between',
+            'bit-and',
+            'bit-not',
+            'bit-or',
+            'bit-set',
+            'bit-xor',
+            'boolc',
+            'boolx',
+            'bound',
+            'bt',
+            'blocks',
+            'bounds',
+            'boxed',
+            'by',
+            'byte-ca',
+            'byte-cn',
+            'byte-co',
+            'byte-cs',
+            'byte-na',
+            'byte-ns',
+
+            'c',
+            'ca',
+            'calling',
+            'casting',
+            'ceil',
+            'center',
+            'centered',
+            'changing',
+            'char_off',
+            'charlen',
+            'circular',
+            'class_constructor',
+            'client',
+            'clike',
+            'close',
+            'cmax',
+            'cmin',
+            'cn',
+            'cnt',
+            'co',
+            'col_background',
+            'col_group',
+            'col_heading',
+            'col_key',
+            'col_negative',
+            'col_normal',
+            'col_positive',
+            'col_total',
+            'color',
+            'column',
+            'comment',
+            'comparing',
+            'components',
+            'condition',
+            'constructor',
+            'context',
+            'copies',
+            'count',
+            'country',
+            'cpi',
+            'creating',
+            'critical',
+            'concat_lines_of',
+            'cos',
+            'cosh',
+            'count_any_not_of',
+            'count_any_of',
+            'cp',
+            'cs',
+            'csequence',
+            'currency',
+            'current',
+            'cx_static_check',
+            'cx_root',
+            'cx_dynamic_check',
+
+            'd',
+            'dangerous',
+            'database',
+            'datainfo',
+            'date',
+            'dbmaxlen',
+            'dd/mm/yy',
+            'dd/mm/yyyy',
+            'ddmmyy',
+            'deallocate',
+            'decfloat',
+            'decfloat16',
+            'decfloat34',
+            'decimals',
+            'default',
+            'deferred',
+            'definition',
+            'department',
+            'descending',
+            'destination',
+            'disconnect',
+            'display-mode',
+            'distance',
+            'distinct',
+            'div',
+            'dummy',
+
+            'e',
+            'encoding',
+            'end-lines',
+            'engineering',
+            'environment',
+            'eq',
+            'equiv',
+            'error_message',
+            'errormessage',
+            'escape',
+            'exact',
+            'exception-table',
+            'exceptions',
+            'exclude',
+            'excluding',
+            'exists',
+            'exp',
+            'exponent',
+            'exporting',
+            'extended_monetary',
+
+            'field',
+            'filter-table',
+            'filters',
+            'filter',
+            'final',
+            'find_any_not_of',
+            'find_any_of',
+            'find_end',
+            'floor',
+            'first-line',
+            'font',
+            'forward',
+            'for',
+            'frac',
+            'from_mixed',
+            'friends',
+            'from',
+            'f',
+
+            'giving',
+            'ge',
+            'gt',
+
+            'handle',
+            'harmless',
+            'having',
+            'head-lines',
+            'help-id',
+            'help-request',
+            'high',
+            'hold',
+            'hotspot',
+
+            'i',
+            'id',
+            'ids',
+            'immediately',
+            'implementation',
+            'importing',
+            'in',
+            'initial',
+            'incl',
+            'including',
+            'increment',
+            'index',
+            'index-line',
+            'inner',
+            'inout',
+            'intensified',
+            'into',
+            'inverse',
+            'is',
+            'iso',
+
+            'join',
+
+            'key',
+            'kind',
+
+            'log10',
+            'language',
+            'late',
+            'layout',
+            'le',
+            'lt',
+            'left-justified',
+            'leftplus',
+            'leftspace',
+            'left',
+            'length',
+            'level',
+            'like',
+            'line-count',
+            'line-size',
+            'lines',
+            'line',
+            'load',
+            'long',
+            'lower',
+            'low',
+            'lpi',
+
+            'matches',
+            'match',
+            'mail',
+            'major-id',
+            'max',
+            'medium',
+            'memory',
+            'message-id',
+            'module',
+            'minor-id',
+            'min',
+            'mm/dd/yyyy',
+            'mm/dd/yy',
+            'mmddyy',
+            'mode',
+            'modifier',
+            'mod',
+            'monetary',
+
+            'name',
+            'nb',
+            'ne',
+            'next',
+            'no-display',
+            'no-extension',
+            'no-gap',
+            'no-gaps',
+            'no-grouping',
+            'no-heading',
+            'no-scrolling',
+            'no-sign',
+            'no-title',
+            'no-topofpage',
+            'no-zero',
+            'nodes',
+            'non-unicode',
+            'no',
+            'number',
+            'n',
+            'nmax',
+            'nmin',
+            'not',
+            'null',
+            'numeric',
+            'numofchar',
+
+            'o',
+            'objects',
+            'obligatory',
+            'occurs',
+            'offset',
+            'off',
+            'of',
+            'only',
+            'open',
+            'option',
+            'optional',
+            'options',
+            'output-length',
+            'output',
+            'out',
+            'on change of',
+            'or',
+            'others',
+
+            'pad',
+            'page',
+            'pages',
+            'parameter-table',
+            'part',
+            'performing',
+            'pos_high',
+            'pos_low',
+            'priority',
+            'public',
+            'pushbutton',
+            'p',
+
+            'queue-only',
+            'quickinfo',
+
+            'raising',
+            'range',
+            'read-only',
+            'received',
+            'receiver',
+            'receiving',
+            'redefinition',
+            'reference',
+            'regex',
+            'replacing',
+            'reset',
+            'responsible',
+            'result',
+            'results',
+            'resumable',
+            'returncode',
+            'returning',
+            'right',
+            'right-specified',
+            'rightplus',
+            'rightspace',
+            'round',
+            'rows',
+            'repeat',
+            'requested',
+            'rescale',
+            'reverse',
+
+            'scale_preserving',
+            'scale_preserving_scientific',
+            'scientific',
+            'scientific_with_leading_zero',
+            'screen',
+            'scrolling',
+            'seconds',
+            'segment',
+            'shift_left',
+            'shift_right',
+            'sign',
+            'simple',
+            'sin',
+            'sinh',
+            'short',
+            'shortdump-id',
+            'sign_as_postfix',
+            'single',
+            'size',
+            'some',
+            'source',
+            'space',
+            'spots',
+            'stable',
+            'state',
+            'static',
+            'statusinfo',
+            'sqrt',
+            'string',
+            'strlen',
+            'structure',
+            'style',
+            'subkey',
+            'submatches',
+            'substring',
+            'substring_after',
+            'substring_before',
+            'substring_from',
+            'substring_to',
+            'super',
+            'supplied',
+            'switch',
+
+            't',
+            'tan',
+            'tanh',
+            'table_line',
+            'table',
+            'tab',
+            'then',
+            'timestamp',
+            'times',
+            'time',
+            'timezone',
+            'title-lines',
+            'title',
+            'top-lines',
+            'to',
+            'to_lower',
+            'to_mixed',
+            'to_upper',
+            'trace-file',
+            'trace-table',
+            'transporting',
+            'trunc',
+            'type',
+
+            'under',
+            'unique',
+            'unit',
+            'user-command',
+            'using',
+            'utf-8',
+
+            'valid',
+            'value',
+            'value-request',
+            'values',
+            'vary',
+            'varying',
+            'version',
+
+            'warning',
+            'where',
+            'width',
+            'with',
+            'word',
+            'with-heading',
+            'with-title',
+
+            'x',
+            'xsequence',
+            'xstring',
+            'xstrlen',
+
+            'yes',
+            'yymmdd',
+
+            'z',
+            'zero'
+
+            ),
+
+        //**********************************************************
+        // screen statements
+        //**********************************************************
+
+        5 => array(
+            'call subscreen',
+            'chain',
+            'endchain',
+            'on chain-input',
+            'on chain-request',
+            'on help-request',
+            'on input',
+            'on request',
+            'on value-request',
+            'process'
+            ),
+
+        //**********************************************************
+        // internal statements
+        //**********************************************************
+
+        6 => array(
+            'generate dynpro',
+            'generate report',
+            'import dynpro',
+            'import nametab',
+            'include methods',
+            'load report',
+            'scan abap-source',
+            'scan and check abap-source',
+            'syntax-check for dynpro',
+            'syntax-check for program',
+            'syntax-trace',
+            'system-call',
+            'system-exit',
+            'verification-message'
+            ),
+
+        //**********************************************************
+        // Control statements
+        //**********************************************************
+
+        1 => array(
+            'assert',
+            'case',
+            'catch',
+            'check',
+            'cleanup',
+            'continue',
+            'do',
+            'else',
+            'elseif',
+            'endat',
+            'endcase',
+            'endcatch',
+            'endif',
+            'enddo',
+            'endloop',
+            'endtry',
+            'endwhile',
+            'exit',
+            'if',
+            'loop',
+            'resume',
+            'retry',
+            'return',
+            'stop',
+            'try',
+            'when',
+            'while'
+
+            ),
+
+        //**********************************************************
+        // variable declaration statements
+        //**********************************************************
+
+        2 => array(
+            'class-data',
+            'controls',
+            'constants',
+            'data',
+            'field-symbols',
+            'fields',
+            'local',
+            'parameters',
+            'ranges',
+            'select-options',
+            'statics',
+            'tables',
+            'type-pools',
+            'types'
+            )
+        ),
+    'SYMBOLS' => array(
+        0 => array(
+            '='
+            ),
+        1 => array(
+            '(', ')', '{', '}', '[', ']', '+', '-', '*', '/', '!', '%', '^', '&', ':'
+            )
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        5 => false,
+        6 => false,
+        7 => false,
+        8 => false,
+        9 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000066; text-transform: uppercase; font-weight: bold; zzz:control;', //control statements
+            2 => 'color: #cc4050; text-transform: uppercase; font-weight: bold; zzz:data;', //data statements
+            3 => 'color: #005066; text-transform: uppercase; font-weight: bold; zzz:statement;', //first token of other statements
+            4 => 'color: #500066; text-transform: uppercase; font-weight: bold; zzz:keyword;', // next tokens of other statements ("keywords")
+            5 => 'color: #005066; text-transform: uppercase; font-weight: bold; zzz:statement;',
+            6 => 'color: #000066; text-transform: uppercase; font-weight: bold; zzz:control;',
+            7 => 'color: #000066; text-transform: uppercase; font-weight: bold; zzz:control;',
+            8 => 'color: #005066; text-transform: uppercase; font-weight: bold; zzz:statement;',
+            9 => 'color: #500066; text-transform: uppercase; font-weight: bold; zzz:keyword;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            2 => 'color: #339933;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #808080;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #4da619;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #3399ff;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #202020;',
+            2 => 'color: #202020;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #800080;',
+            1 => 'color: #808080;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => 'http://help.sap.com/abapdocu/en/ABAP{FNAMEU}.htm',
+        2 => 'http://help.sap.com/abapdocu/en/ABAP{FNAMEU}.htm',
+        3 => 'http://help.sap.com/abapdocu/en/ABAP{FNAMEU}.htm',
+        4 => '',
+        5 => '',
+        6 => '',
+        7 => '',
+        8 => '',
+        9 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '-&gt;',
+        2 => '=&gt;'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            7 => array(
+                'SPACE_AS_WHITESPACE' => true
+                ),
+            8 => array(
+                'SPACE_AS_WHITESPACE' => true
+                ),
+            9 => array(
+                'SPACE_AS_WHITESPACE' => true
+                )
+            )
+        ),
+    'TAB_WIDTH' => 4
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/actionscript.php b/examples/includes/geshi/geshi/actionscript.php
new file mode 100644 (file)
index 0000000..658491d
--- /dev/null
@@ -0,0 +1,197 @@
+<?php
+/*************************************************************************************
+ * actionscript.php
+ * ----------------
+ * Author: Steffen Krause (Steffen.krause@muse.de)
+ * Copyright: (c) 2004 Steffen Krause, Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/06/20
+ *
+ * Actionscript language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2004/11/27 (1.0.1)
+ *  -  Added support for multiple object splitters
+ * 2004/10/27 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'ActionScript',
+    'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            '#include', 'for', 'foreach', 'if', 'elseif', 'else', 'while', 'do', 'dowhile',
+            'endwhile', 'endif', 'switch', 'case', 'endswitch', 'return', 'break', 'continue', 'in'
+            ),
+        2 => array(
+            'null', 'false', 'true', 'var',
+            'default', 'function', 'class',
+            'new', '_global'
+            ),
+        3 => array(
+            '#endinitclip', '#initclip', '__proto__', '_accProps', '_alpha', '_currentframe',
+            '_droptarget', '_focusrect', '_framesloaded', '_height', '_highquality', '_lockroot',
+            '_name', '_parent', '_quality', '_root', '_rotation', '_soundbuftime', '_target', '_totalframes',
+            '_url', '_visible', '_width', '_x', '_xmouse', '_xscale', '_y', '_ymouse', '_yscale', 'abs',
+            'Accessibility', 'acos', 'activityLevel', 'add', 'addListener', 'addPage', 'addProperty',
+            'addRequestHeader', 'align', 'allowDomain', 'allowInsecureDomain', 'and', 'appendChild',
+            'apply', 'Arguments', 'Array', 'asfunction', 'asin', 'atan', 'atan2', 'attachAudio', 'attachMovie',
+            'attachSound', 'attachVideo', 'attributes', 'autosize', 'avHardwareDisable', 'background',
+            'backgroundColor', 'BACKSPACE', 'bandwidth', 'beginFill', 'beginGradientFill', 'blockIndent',
+            'bold', 'Boolean', 'border', 'borderColor', 'bottomScroll', 'bufferLength', 'bufferTime',
+            'builtInItems', 'bullet', 'Button', 'bytesLoaded', 'bytesTotal', 'call', 'callee', 'caller',
+            'Camera', 'capabilities', 'CAPSLOCK', 'caption', 'catch', 'ceil', 'charAt', 'charCodeAt',
+            'childNodes', 'chr', 'clear', 'clearInterval', 'cloneNode', 'close', 'Color', 'concat',
+            'connect', 'condenseWhite', 'constructor', 'contentType', 'ContextMenu', 'ContextMenuItem',
+            'CONTROL', 'copy', 'cos', 'createElement', 'createEmptyMovieClip', 'createTextField',
+            'createTextNode', 'currentFps', 'curveTo', 'CustomActions', 'customItems', 'data', 'Date',
+            'deblocking', 'delete', 'DELETEKEY', 'docTypeDecl', 'domain', 'DOWN',
+            'duplicateMovieClip', 'duration', 'dynamic', 'E', 'embedFonts', 'enabled',
+            'END', 'endFill', 'ENTER', 'eq', 'Error', 'ESCAPE(Konstante)', 'escape(Funktion)', 'eval',
+            'exactSettings', 'exp', 'extends', 'finally', 'findText', 'firstChild', 'floor',
+            'flush', 'focusEnabled', 'font', 'fps', 'fromCharCode', 'fscommand',
+            'gain', 'ge', 'get', 'getAscii', 'getBeginIndex', 'getBounds', 'getBytesLoaded', 'getBytesTotal',
+            'getCaretIndex', 'getCode', 'getCount', 'getDate', 'getDay', 'getDepth', 'getEndIndex', 'getFocus',
+            'getFontList', 'getFullYear', 'getHours', 'getInstanceAtDepth', 'getLocal', 'getMilliseconds',
+            'getMinutes', 'getMonth', 'getNewTextFormat', 'getNextHighestDepth', 'getPan', 'getProgress',
+            'getProperty', 'getRGB', 'getSeconds', 'getSelected', 'getSelectedText', 'getSize', 'getStyle',
+            'getStyleNames', 'getSWFVersion', 'getText', 'getTextExtent', 'getTextFormat', 'getTextSnapshot',
+            'getTime', 'getTimer', 'getTimezoneOffset', 'getTransform', 'getURL', 'getUTCDate', 'getUTCDay',
+            'getUTCFullYear', 'getUTCHours', 'getUTCMilliseconds', 'getUTCMinutes', 'getUTCMonth', 'getUTCSeconds',
+            'getVersion', 'getVolume', 'getYear', 'globalToLocal', 'goto', 'gotoAndPlay', 'gotoAndStop',
+            'hasAccessibility', 'hasAudio', 'hasAudioEncoder', 'hasChildNodes', 'hasEmbeddedVideo', 'hasMP3',
+            'hasPrinting', 'hasScreenBroadcast', 'hasScreenPlayback', 'hasStreamingAudio', 'hasStreamingVideo',
+            'hasVideoEncoder', 'height', 'hide', 'hideBuiltInItems', 'hitArea', 'hitTest', 'hitTestTextNearPos',
+            'HOME', 'hscroll', 'html', 'htmlText', 'ID3', 'ifFrameLoaded', 'ignoreWhite', 'implements',
+            'import', 'indent', 'index', 'indexOf', 'Infinity', '-Infinity', 'INSERT', 'insertBefore', 'install',
+            'instanceof', 'int', 'interface', 'isActive', 'isDebugger', 'isDown', 'isFinite', 'isNaN', 'isToggled',
+            'italic', 'join', 'Key', 'language', 'lastChild', 'lastIndexOf', 'le', 'leading', 'LEFT', 'leftMargin',
+            'length', 'level', 'lineStyle', 'lineTo', 'list', 'LN10', 'LN2', 'load', 'loadClip', 'loaded', 'loadMovie',
+            'loadMovieNum', 'loadSound', 'loadVariables', 'loadVariablesNum', 'LoadVars', 'LocalConnection',
+            'localFileReadDisable', 'localToGlobal', 'log', 'LOG10E', 'LOG2E', 'manufacturer', 'Math', 'max',
+            'MAX_VALUE', 'maxChars', 'maxhscroll', 'maxscroll', 'mbchr', 'mblength', 'mbord', 'mbsubstring', 'menu',
+            'message', 'Microphone', 'min', 'MIN_VALUE', 'MMExecute', 'motionLevel', 'motionTimeOut', 'Mouse',
+            'mouseWheelEnabled', 'moveTo', 'Movieclip', 'MovieClipLoader', 'multiline', 'muted', 'name', 'names', 'NaN',
+            'ne', 'NEGATIVE_INFINITY', 'NetConnection', 'NetStream', 'newline', 'nextFrame',
+            'nextScene', 'nextSibling', 'nodeName', 'nodeType', 'nodeValue', 'not', 'Number', 'Object',
+            'on', 'onActivity', 'onChanged', 'onClipEvent', 'onClose', 'onConnect', 'onData', 'onDragOut',
+            'onDragOver', 'onEnterFrame', 'onID3', 'onKeyDown', 'onKeyUp', 'onKillFocus', 'onLoad', 'onLoadComplete',
+            'onLoadError', 'onLoadInit', 'onLoadProgress', 'onLoadStart', 'onMouseDown', 'onMouseMove', 'onMouseUp',
+            'onMouseWheel', 'onPress', 'onRelease', 'onReleaseOutside', 'onResize', 'onRollOut', 'onRollOver',
+            'onScroller', 'onSelect', 'onSetFocus', 'onSoundComplete', 'onStatus', 'onUnload', 'onUpdate', 'onXML',
+            'or(logischesOR)', 'ord', 'os', 'parentNode', 'parseCSS', 'parseFloat', 'parseInt', 'parseXML', 'password',
+            'pause', 'PGDN', 'PGUP', 'PI', 'pixelAspectRatio', 'play', 'playerType', 'pop', 'position',
+            'POSITIVE_INFINITY', 'pow', 'prevFrame', 'previousSibling', 'prevScene', 'print', 'printAsBitmap',
+            'printAsBitmapNum', 'PrintJob', 'printNum', 'private', 'prototype', 'public', 'push', 'quality',
+            'random', 'rate', 'registerClass', 'removeListener', 'removeMovieClip', 'removeNode', 'removeTextField',
+            'replaceSel', 'replaceText', 'resolutionX', 'resolutionY', 'restrict', 'reverse', 'RIGHT',
+            'rightMargin', 'round', 'scaleMode', 'screenColor', 'screenDPI', 'screenResolutionX', 'screenResolutionY',
+            'scroll', 'seek', 'selectable', 'Selection', 'send', 'sendAndLoad', 'separatorBefore', 'serverString',
+            'set', 'setvariable', 'setBufferTime', 'setClipboard', 'setDate', 'setFocus', 'setFullYear', 'setGain',
+            'setHours', 'setInterval', 'setMask', 'setMilliseconds', 'setMinutes', 'setMode', 'setMonth',
+            'setMotionLevel', 'setNewTextFormat', 'setPan', 'setProperty', 'setQuality', 'setRate', 'setRGB',
+            'setSeconds', 'setSelectColor', 'setSelected', 'setSelection', 'setSilenceLevel', 'setStyle',
+            'setTextFormat', 'setTime', 'setTransform', 'setUseEchoSuppression', 'setUTCDate', 'setUTCFullYear',
+            'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds', 'setVolume',
+            'setYear', 'SharedObject', 'SHIFT(Konstante)', 'shift(Methode)', 'show', 'showMenu', 'showSettings',
+            'silenceLevel', 'silenceTimeout', 'sin', 'size', 'slice', 'smoothing', 'sort', 'sortOn', 'Sound', 'SPACE',
+            'splice', 'split', 'sqrt', 'SQRT1_2', 'SQRT2', 'Stage', 'start', 'startDrag', 'static', 'status', 'stop',
+            'stopAllSounds', 'stopDrag', 'String', 'StyleSheet(Klasse)', 'styleSheet(Eigenschaft)', 'substr',
+            'substring', 'super', 'swapDepths', 'System', 'TAB', 'tabChildren', 'tabEnabled', 'tabIndex',
+            'tabStops', 'tan', 'target', 'targetPath', 'tellTarget', 'text', 'textColor', 'TextField', 'TextFormat',
+            'textHeight', 'TextSnapshot', 'textWidth', 'this', 'throw', 'time', 'toggleHighQuality', 'toLowerCase',
+            'toString', 'toUpperCase', 'trace', 'trackAsMenu', 'try', 'type', 'typeof', 'undefined',
+            'underline', 'unescape', 'uninstall', 'unloadClip', 'unloadMovie', 'unLoadMovieNum', 'unshift', 'unwatch',
+            'UP', 'updateAfterEvent', 'updateProperties', 'url', 'useCodePage', 'useEchoSuppression', 'useHandCursor',
+            'UTC', 'valueOf', 'variable', 'version', 'Video', 'visible', 'void', 'watch', 'width',
+            'with', 'wordwrap', 'XML', 'xmlDecl', 'XMLNode', 'XMLSocket'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}', '!', '@', '%', '&', '*', '|', '/', '<', '>'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #0066CC;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            2 => 'color: #808080; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006600;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(),
+    'HIGHLIGHT_STRICT_BLOCK' => array()
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/actionscript3.php b/examples/includes/geshi/geshi/actionscript3.php
new file mode 100644 (file)
index 0000000..b98002f
--- /dev/null
@@ -0,0 +1,467 @@
+<?php
+/*************************************************************************************
+ * actionscript3.php
+ * ----------------
+ * Author: Jordi Boggiano (j.boggiano@seld.be)
+ * Copyright: (c) 2007 Jordi Boggiano (http://www.seld.be/), Benny Baumann (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2007/11/26
+ *
+ * ActionScript3 language file for GeSHi.
+ *
+ * All keywords scraped from the Flex 2.0.1 Documentation
+ *
+ * The default style is based on FlexBuilder2 coloring, with the addition of class, package, method and
+ * constant names that are highlighted to help identifying problem when used on public pastebins.
+ *
+ * For styling, keywords data from 0 to 1 (accessible through .kw1, etc.) are described here :
+ *
+ *   1 : operators
+ *   2 : 'var' keyword
+ *   3 : 'function' keyword
+ *   4 : 'class' and 'package' keywords
+ *   5 : all flash.* class names plus Top Level classes, mx are excluded
+ *   6 : all flash.* package names, mx are excluded
+ *   7 : valid flash method names and properties (there is no type checks sadly, for example String().x will be highlighted as 'x' is valid, but obviously strings don't have a x property)
+ *   8 : valid flash constant names (again, no type check)
+ *
+ *
+ * CHANGES
+ * -------
+ * 2007/12/06 (1.0.7.22)
+ *  -  Added the 'this' keyword (oops)
+ *
+ * TODO (updated 2007/11/30)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'ActionScript 3',
+    'COMMENT_SINGLE' => array(1 => '//'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'with', 'while', 'void', 'undefined', 'typeof', 'try', 'true',
+            'throw', 'this', 'switch', 'super', 'set', 'return', 'public', 'protected',
+            'private', 'null', 'new', 'is', 'internal', 'instanceof', 'in',
+            'import', 'if', 'get', 'for', 'false', 'else', 'each', 'do',
+            'delete', 'default', 'continue', 'catch', 'case', 'break', 'as'
+            ),
+        2 => array(
+            'var'
+            ),
+        3 => array(
+            'function'
+            ),
+        4 => array(
+            'class', 'package'
+            ),
+        6 => array(
+            'flash.xml', 'flash.utils', 'flash.ui', 'flash.text',
+            'flash.system', 'flash.profiler', 'flash.printing', 'flash.net',
+            'flash.media', 'flash.geom', 'flash.filters', 'flash.external',
+            'flash.events', 'flash.errors', 'flash.display',
+            'flash.accessibility'
+            ),
+        7 => array(
+            'zoom', 'year', 'y', 'xmlDecl', 'x', 'writeUnsignedInt',
+            'writeUTFBytes', 'writeUTF', 'writeShort', 'writeObject',
+            'writeMultiByte', 'writeInt', 'writeFloat', 'writeExternal',
+            'writeDynamicProperty', 'writeDynamicProperties', 'writeDouble',
+            'writeBytes', 'writeByte', 'writeBoolean', 'wordWrap',
+            'willTrigger', 'width', 'volume', 'visible', 'videoWidth',
+            'videoHeight', 'version', 'valueOf', 'value', 'usingTLS',
+            'useRichTextClipboard', 'useHandCursor', 'useEchoSuppression',
+            'useCodePage', 'url', 'uri', 'uploadCompleteData', 'upload',
+            'updateProperties', 'updateAfterEvent', 'upState', 'unshift',
+            'unlock', 'unload', 'union', 'unescapeMultiByte', 'unescape',
+            'underline', 'uncompress', 'type', 'ty', 'tx', 'transparent',
+            'translate', 'transformPoint', 'transform', 'trackAsMenu', 'track',
+            'trace', 'totalMemory', 'totalFrames', 'topLeft', 'top',
+            'togglePause', 'toXMLString', 'toUpperCase', 'toUTCString',
+            'toTimeString', 'toString', 'toPrecision', 'toLowerCase',
+            'toLocaleUpperCase', 'toLocaleTimeString', 'toLocaleString',
+            'toLocaleLowerCase', 'toLocaleDateString', 'toFixed',
+            'toExponential', 'toDateString', 'timezoneOffset', 'timerComplete',
+            'timer', 'time', 'threshold', 'thickness', 'textWidth',
+            'textSnapshot', 'textInput', 'textHeight', 'textColor', 'text',
+            'test', 'target', 'tan', 'tabStops', 'tabIndexChange', 'tabIndex',
+            'tabEnabledChange', 'tabEnabled', 'tabChildrenChange',
+            'tabChildren', 'sync', 'swfVersion', 'swapChildrenAt',
+            'swapChildren', 'subtract', 'substring', 'substr', 'styleSheet',
+            'styleNames', 'strength', 'stopPropagation',
+            'stopImmediatePropagation', 'stopDrag', 'stopAll', 'stop', 'status',
+            'startDrag', 'start', 'stageY', 'stageX', 'stageWidth',
+            'stageHeight', 'stageFocusRect', 'stage', 'sqrt', 'split', 'splice',
+            'source', 'soundTransform', 'soundComplete', 'sortOn', 'sort',
+            'songName', 'some', 'socketData', 'smoothing', 'slice', 'size',
+            'sin', 'silent', 'silenceTimeout', 'silenceLevel', 'showSettings',
+            'showRedrawRegions', 'showDefaultContextMenu', 'show', 'shortcut',
+            'shiftKey', 'shift', 'sharpness', 'sharedEvents', 'shadowColor',
+            'shadowAlpha', 'settings', 'setUseEchoSuppression', 'setUTCSeconds',
+            'setUTCMonth', 'setUTCMinutes', 'setUTCMilliseconds', 'setUTCHours',
+            'setUTCFullYear', 'setUTCDate', 'setTimeout', 'setTime',
+            'setTextFormat', 'setStyle', 'setSilenceLevel', 'setSettings',
+            'setSelection', 'setSelected', 'setSelectColor', 'setSeconds',
+            'setQuality', 'setPropertyIsEnumerable', 'setProperty', 'setPixels',
+            'setPixel32', 'setPixel', 'setNamespace', 'setName',
+            'setMotionLevel', 'setMonth', 'setMode', 'setMinutes',
+            'setMilliseconds', 'setLoopback', 'setLoopBack', 'setLocalName',
+            'setKeyFrameInterval', 'setInterval', 'setHours', 'setFullYear',
+            'setEmpty', 'setDirty', 'setDate', 'setCompositionString',
+            'setClipboard', 'setChildren', 'setChildIndex',
+            'setAdvancedAntiAliasingTable', 'serverString', 'separatorBefore',
+            'sendToURL', 'send', 'selectionEndIndex', 'selectionBeginIndex',
+            'selectable', 'select', 'seek', 'securityError', 'securityDomain',
+            'secondsUTC', 'seconds', 'search', 'scrollV', 'scrollRect',
+            'scrollH', 'scroll', 'screenResolutionY', 'screenResolutionX',
+            'screenDPI', 'screenColor', 'scenes', 'scaleY', 'scaleX',
+            'scaleMode', 'scale9Grid', 'scale', 'save', 'sandboxType',
+            'sameDomain', 'running', 'round', 'rotation', 'rotate', 'root',
+            'rollOver', 'rollOut', 'rightToRight', 'rightToLeft', 'rightPeak',
+            'rightMargin', 'right', 'rewind', 'reverse', 'resume', 'restrict',
+            'resize', 'reset', 'requestHeaders', 'replaceText',
+            'replaceSelectedText', 'replace', 'repeatCount', 'render',
+            'removedFromStage', 'removed', 'removeNode', 'removeNamespace',
+            'removeEventListener', 'removeChildAt', 'removeChild',
+            'relatedObject', 'registerFont', 'registerClassAlias', 'redOffset',
+            'redMultiplier', 'rect', 'receiveVideo', 'receiveAudio',
+            'readUnsignedShort', 'readUnsignedInt', 'readUnsignedByte',
+            'readUTFBytes', 'readUTF', 'readShort', 'readObject',
+            'readMultiByte', 'readInt', 'readFloat', 'readExternal',
+            'readDouble', 'readBytes', 'readByte', 'readBoolean', 'ratios',
+            'rate', 'random', 'quality', 'push', 'publish', 'proxyType',
+            'prototype', 'propertyIsEnumerable', 'progress',
+            'processingInstructions', 'printAsBitmap', 'print',
+            'previousSibling', 'preventDefault', 'prevScene', 'prevFrame',
+            'prettyPrinting', 'prettyIndent', 'preserveAlpha', 'prependChild',
+            'prefix', 'pow', 'position', 'pop', 'polar', 'playerType', 'play',
+            'pixelSnapping', 'pixelDissolve', 'pixelBounds', 'pixelAspectRatio',
+            'perlinNoise', 'pause', 'parseXML', 'parseInt', 'parseFloat',
+            'parseCSS', 'parse', 'parentNode', 'parentDomain',
+            'parentAllowsChild', 'parent', 'parameters', 'paperWidth',
+            'paperHeight', 'pan', 'paletteMap', 'pageWidth', 'pageHeight',
+            'overState', 'outsideCutoff', 'os', 'orientation', 'open',
+            'opaqueBackground', 'onPlayStatus', 'onMetaData', 'onCuePoint',
+            'offsetPoint', 'offset', 'objectID', 'objectEncoding', 'numLock',
+            'numLines', 'numFrames', 'numChildren', 'normalize', 'noise',
+            'nodeValue', 'nodeType', 'nodeName', 'nodeKind', 'noAutoLabeling',
+            'nextValue', 'nextSibling', 'nextScene', 'nextNameIndex',
+            'nextName', 'nextFrame', 'netStatus', 'navigateToURL',
+            'namespaceURI', 'namespaceDeclarations', 'namespace', 'names',
+            'name', 'muted', 'multiline', 'moveTo', 'mouseY', 'mouseX',
+            'mouseWheelEnabled', 'mouseWheel', 'mouseUp', 'mouseTarget',
+            'mouseOver', 'mouseOut', 'mouseMove', 'mouseLeave',
+            'mouseFocusChange', 'mouseEnabled', 'mouseDown', 'mouseChildren',
+            'motionTimeout', 'motionLevel', 'monthUTC', 'month',
+            'modificationDate', 'mode', 'minutesUTC', 'minutes', 'min',
+            'millisecondsUTC', 'milliseconds', 'method', 'message', 'merge',
+            'menuSelect', 'menuItemSelect', 'maxScrollV', 'maxScrollH',
+            'maxLevel', 'maxChars', 'max', 'matrixY', 'matrixX', 'matrix',
+            'match', 'mask', 'mapPoint', 'mapBitmap', 'map', 'manufacturer',
+            'macType', 'loopback', 'loop', 'log', 'lock', 'localeCompare',
+            'localY', 'localX', 'localToGlobal', 'localName',
+            'localFileReadDisable', 'loaderURL', 'loaderInfo', 'loader',
+            'loadPolicyFile', 'loadBytes', 'load', 'liveDelay', 'link',
+            'lineTo', 'lineStyle', 'lineGradientStyle', 'level',
+            'letterSpacing', 'length', 'leftToRight', 'leftToLeft', 'leftPeak',
+            'leftMargin', 'left', 'leading', 'lastIndexOf', 'lastIndex',
+            'lastChild', 'language', 'labels', 'knockout', 'keyUp',
+            'keyLocation', 'keyFrameInterval', 'keyFocusChange', 'keyDown',
+            'keyCode', 'kerning', 'join', 'italic', 'isXMLName',
+            'isPrototypeOf', 'isNaN', 'isFocusInaccessible', 'isFinite',
+            'isEmpty', 'isDefaultPrevented', 'isDebugger', 'isBuffering',
+            'isAttribute', 'isAccessible', 'ioError', 'invert', 'invalidate',
+            'intersects', 'intersection', 'interpolate', 'insideCutoff',
+            'insertChildBefore', 'insertChildAfter', 'insertBefore', 'inner',
+            'init', 'info', 'inflatePoint', 'inflate', 'indexOf', 'index',
+            'indent', 'inScopeNamespaces', 'imeComposition', 'ime',
+            'ignoreWhitespace', 'ignoreWhite', 'ignoreProcessingInstructions',
+            'ignoreComments', 'ignoreCase', 'identity', 'idMap', 'id3',
+            'httpStatus', 'htmlText', 'hoursUTC', 'hours', 'hitTestTextNearPos',
+            'hitTestState', 'hitTestPoint', 'hitTestObject', 'hitTest',
+            'hitArea', 'highlightColor', 'highlightAlpha', 'hideObject',
+            'hideBuiltInItems', 'hide', 'height', 'hasVideoEncoder', 'hasTLS',
+            'hasStreamingVideo', 'hasStreamingAudio', 'hasSimpleContent',
+            'hasScreenPlayback', 'hasScreenBroadcast', 'hasProperty',
+            'hasPrinting', 'hasOwnProperty', 'hasMP3', 'hasIME', 'hasGlyphs',
+            'hasEventListener', 'hasEmbeddedVideo', 'hasDefinition',
+            'hasComplexContent', 'hasChildNodes', 'hasAudioEncoder', 'hasAudio',
+            'hasAccessibility', 'gridFitType', 'greenOffset', 'greenMultiplier',
+            'graphics', 'gotoAndStop', 'gotoAndPlay', 'globalToLocal', 'global',
+            'getUTCSeconds', 'getUTCMonth', 'getUTCMinutes',
+            'getUTCMilliseconds', 'getUTCHours', 'getUTCFullYear', 'getUTCDay',
+            'getUTCDate', 'getTimezoneOffset', 'getTimer', 'getTime',
+            'getTextRunInfo', 'getTextFormat', 'getText', 'getStyle',
+            'getStackTrace', 'getSelectedText', 'getSelected', 'getSeconds',
+            'getRemote', 'getRect', 'getQualifiedSuperclassName',
+            'getQualifiedClassName', 'getProperty', 'getPrefixForNamespace',
+            'getPixels', 'getPixel32', 'getPixel', 'getParagraphLength',
+            'getObjectsUnderPoint', 'getNamespaceForPrefix', 'getMonth',
+            'getMinutes', 'getMilliseconds', 'getMicrophone', 'getLocal',
+            'getLineText', 'getLineOffset', 'getLineMetrics', 'getLineLength',
+            'getLineIndexOfChar', 'getLineIndexAtPoint', 'getImageReference',
+            'getHours', 'getFullYear', 'getFirstCharInParagraph',
+            'getDescendants', 'getDefinitionByName', 'getDefinition', 'getDay',
+            'getDate', 'getColorBoundsRect', 'getClassByAlias', 'getChildIndex',
+            'getChildByName', 'getChildAt', 'getCharIndexAtPoint',
+            'getCharBoundaries', 'getCamera', 'getBounds', 'genre',
+            'generateFilterRect', 'gain', 'fullYearUTC', 'fullYear',
+            'fullScreen', 'fscommand', 'fromCharCode', 'framesLoaded',
+            'frameRate', 'frame', 'fps', 'forwardAndBack', 'formatToString',
+            'forceSimple', 'forEach', 'fontType', 'fontStyle', 'fontSize',
+            'fontName', 'font', 'focusRect', 'focusOut', 'focusIn', 'focus',
+            'flush', 'floor', 'floodFill', 'firstChild', 'findText', 'filters',
+            'filter', 'fillRect', 'fileList', 'extension', 'extended', 'exp',
+            'exec', 'exactSettings', 'every', 'eventPhase', 'escapeMultiByte',
+            'escape', 'errorID', 'error', 'equals', 'enumerateFonts',
+            'enterFrame', 'endian', 'endFill', 'encodeURIComponent',
+            'encodeURI', 'enabled', 'embedFonts', 'elements',
+            'dynamicPropertyWriter', 'dropTarget', 'drawRoundRect', 'drawRect',
+            'drawEllipse', 'drawCircle', 'draw', 'download', 'downState',
+            'doubleClickEnabled', 'doubleClick', 'dotall', 'domain',
+            'docTypeDecl', 'doConversion', 'divisor', 'distance', 'dispose',
+            'displayState', 'displayMode', 'displayAsPassword', 'dispatchEvent',
+            'description', 'describeType', 'descent', 'descendants',
+            'deltaTransformPoint', 'delta', 'deleteProperty', 'delay',
+            'defaultTextFormat', 'defaultSettings', 'defaultObjectEncoding',
+            'decodeURIComponent', 'decodeURI', 'decode', 'deblocking',
+            'deactivate', 'dayUTC', 'day', 'dateUTC', 'date', 'dataFormat',
+            'data', 'd', 'customItems', 'curveTo', 'currentTarget',
+            'currentScene', 'currentLabels', 'currentLabel', 'currentFrame',
+            'currentFPS', 'currentDomain', 'currentCount', 'ctrlKey', 'creator',
+            'creationDate', 'createTextNode', 'createGradientBox',
+            'createElement', 'createBox', 'cos', 'copyPixels', 'copyChannel',
+            'copy', 'conversionMode', 'contextMenuOwner', 'contextMenu',
+            'contentType', 'contentLoaderInfo', 'content', 'containsRect',
+            'containsPoint', 'contains', 'constructor', 'connectedProxyType',
+            'connected', 'connect', 'condenseWhite', 'concatenatedMatrix',
+            'concatenatedColorTransform', 'concat', 'computeSpectrum',
+            'compress', 'componentY', 'componentX', 'complete', 'compare',
+            'comments', 'comment', 'colors', 'colorTransform', 'color', 'code',
+            'close', 'cloneNode', 'clone', 'client', 'click', 'clearTimeout',
+            'clearInterval', 'clear', 'clamp', 'children', 'childNodes',
+            'childIndex', 'childAllowsParent', 'child', 'checkPolicyFile',
+            'charCount', 'charCodeAt', 'charCode', 'charAt', 'changeList',
+            'change', 'ceil', 'caretIndex', 'caption', 'capsLock', 'cancelable',
+            'cancel', 'callee', 'callProperty', 'call', 'cacheAsBitmap', 'c',
+            'bytesTotal', 'bytesLoaded', 'bytesAvailable', 'buttonMode',
+            'buttonDown', 'bullet', 'builtInItems', 'bufferTime',
+            'bufferLength', 'bubbles', 'browse', 'bottomScrollV', 'bottomRight',
+            'bottom', 'borderColor', 'border', 'bold', 'blurY', 'blurX',
+            'blueOffset', 'blueMultiplier', 'blockIndent', 'blendMode',
+            'bitmapData', 'bias', 'beginGradientFill', 'beginFill',
+            'beginBitmapFill', 'bandwidth', 'backgroundColor', 'background',
+            'b', 'available', 'avHardwareDisable', 'autoSize', 'attributes',
+            'attribute', 'attachNetStream', 'attachCamera', 'attachAudio',
+            'atan2', 'atan', 'asyncError', 'asin', 'ascent', 'artist',
+            'areSoundsInaccessible', 'areInaccessibleObjectsUnderPoint',
+            'applyFilter', 'apply', 'applicationDomain', 'appendText',
+            'appendChild', 'antiAliasType', 'angle', 'alwaysShowSelection',
+            'altKey', 'alphas', 'alphaOffset', 'alphaMultiplier', 'alpha',
+            'allowInsecureDomain', 'allowDomain', 'align', 'album',
+            'addedToStage', 'added', 'addPage', 'addNamespace', 'addHeader',
+            'addEventListener', 'addChildAt', 'addChild', 'addCallback', 'add',
+            'activityLevel', 'activity', 'active', 'activating', 'activate',
+            'actionScriptVersion', 'acos', 'accessibilityProperties', 'abs'
+            ),
+        8 => array(
+            'WRAP', 'VERTICAL', 'VARIABLES',
+            'UTC', 'UPLOAD_COMPLETE_DATA', 'UP', 'UNLOAD', 'UNKNOWN',
+            'UNIQUESORT', 'TOP_RIGHT', 'TOP_LEFT', 'TOP', 'TIMER_COMPLETE',
+            'TIMER', 'TEXT_NODE', 'TEXT_INPUT', 'TEXT', 'TAB_INDEX_CHANGE',
+            'TAB_ENABLED_CHANGE', 'TAB_CHILDREN_CHANGE', 'TAB', 'SYNC',
+            'SUBTRACT', 'SUBPIXEL', 'STATUS', 'STANDARD', 'SQUARE', 'SQRT2',
+            'SQRT1_2', 'SPACE', 'SOUND_COMPLETE', 'SOCKET_DATA', 'SHOW_ALL',
+            'SHIFT', 'SETTINGS_MANAGER', 'SELECT', 'SECURITY_ERROR', 'SCROLL',
+            'SCREEN', 'ROUND', 'ROLL_OVER', 'ROLL_OUT', 'RIGHT', 'RGB',
+            'RETURNINDEXEDARRAY', 'RESIZE', 'REPEAT', 'RENDER',
+            'REMOVED_FROM_STAGE', 'REMOVED', 'REMOTE', 'REGULAR', 'REFLECT',
+            'RED', 'RADIAL', 'PROGRESS', 'PRIVACY', 'POST', 'POSITIVE_INFINITY',
+            'PORTRAIT', 'PIXEL', 'PI', 'PENDING', 'PAGE_UP', 'PAGE_DOWN', 'PAD',
+            'OVERLAY', 'OUTER', 'OPEN', 'NaN', 'NUM_PAD', 'NUMPAD_SUBTRACT',
+            'NUMPAD_MULTIPLY', 'NUMPAD_ENTER', 'NUMPAD_DIVIDE',
+            'NUMPAD_DECIMAL', 'NUMPAD_ADD', 'NUMPAD_9', 'NUMPAD_8', 'NUMPAD_7',
+            'NUMPAD_6', 'NUMPAD_5', 'NUMPAD_4', 'NUMPAD_3', 'NUMPAD_2',
+            'NUMPAD_1', 'NUMPAD_0', 'NUMERIC', 'NO_SCALE', 'NO_BORDER',
+            'NORMAL', 'NONE', 'NEVER', 'NET_STATUS', 'NEGATIVE_INFINITY',
+            'MULTIPLY', 'MOUSE_WHEEL', 'MOUSE_UP', 'MOUSE_OVER', 'MOUSE_OUT',
+            'MOUSE_MOVE', 'MOUSE_LEAVE', 'MOUSE_FOCUS_CHANGE', 'MOUSE_DOWN',
+            'MITER', 'MIN_VALUE', 'MICROPHONE', 'MENU_SELECT',
+            'MENU_ITEM_SELECT', 'MEDIUM', 'MAX_VALUE', 'LOW', 'LOG2E', 'LOG10E',
+            'LOCAL_WITH_NETWORK', 'LOCAL_WITH_FILE', 'LOCAL_TRUSTED',
+            'LOCAL_STORAGE', 'LN2', 'LN10', 'LITTLE_ENDIAN', 'LINK',
+            'LINEAR_RGB', 'LINEAR', 'LIGHT_COLOR', 'LIGHTEN', 'LEFT', 'LCD',
+            'LAYER', 'LANDSCAPE', 'KOREAN', 'KEY_UP', 'KEY_FOCUS_CHANGE',
+            'KEY_DOWN', 'JUSTIFY', 'JAPANESE_KATAKANA_HALF',
+            'JAPANESE_KATAKANA_FULL', 'JAPANESE_HIRAGANA', 'Infinity', 'ITALIC',
+            'IO_ERROR', 'INVERT', 'INSERT', 'INPUT', 'INNER', 'INIT',
+            'IME_COMPOSITION', 'IGNORE', 'ID3', 'HTTP_STATUS', 'HORIZONTAL',
+            'HOME', 'HIGH', 'HARDLIGHT', 'GREEN', 'GET', 'FULLSCREEN', 'FULL',
+            'FOCUS_OUT', 'FOCUS_IN', 'FLUSHED', 'FLASH9', 'FLASH8', 'FLASH7',
+            'FLASH6', 'FLASH5', 'FLASH4', 'FLASH3', 'FLASH2', 'FLASH1', 'F9',
+            'F8', 'F7', 'F6', 'F5', 'F4', 'F3', 'F2', 'F15', 'F14', 'F13',
+            'F12', 'F11', 'F10', 'F1', 'EXACT_FIT', 'ESCAPE', 'ERROR', 'ERASE',
+            'ENTER_FRAME', 'ENTER', 'END', 'EMBEDDED', 'ELEMENT_NODE', 'E',
+            'DYNAMIC', 'DOWN', 'DOUBLE_CLICK', 'DIFFERENCE', 'DEVICE',
+            'DESCENDING', 'DELETE', 'DEFAULT', 'DEACTIVATE', 'DATA',
+            'DARK_COLOR', 'DARKEN', 'CRT', 'CONTROL', 'CONNECT', 'COMPLETE',
+            'COLOR', 'CLOSE', 'CLICK', 'CLAMP', 'CHINESE', 'CHANGE', 'CENTER',
+            'CASEINSENSITIVE', 'CAPTURING_PHASE', 'CAPS_LOCK', 'CANCEL',
+            'CAMERA', 'BUBBLING_PHASE', 'BOTTOM_RIGHT', 'BOTTOM_LEFT', 'BOTTOM',
+            'BOLD_ITALIC', 'BOLD', 'BLUE', 'BINARY', 'BIG_ENDIAN', 'BEVEL',
+            'BEST', 'BACKSPACE', 'AUTO', 'AT_TARGET', 'ASYNC_ERROR', 'AMF3',
+            'AMF0', 'ALWAYS', 'ALPHANUMERIC_HALF', 'ALPHANUMERIC_FULL', 'ALPHA',
+            'ADVANCED', 'ADDED_TO_STAGE', 'ADDED', 'ADD', 'ACTIVITY',
+            'ACTIONSCRIPT3', 'ACTIONSCRIPT2'
+            ),
+        //FIX: Must be last in order to avoid conflicts with keywords present
+        //in other keyword groups, that might get highlighted as part of the URL.
+        //I know this is not a proper work-around, but should do just fine.
+        5 => array(
+            'uint', 'int', 'arguments', 'XMLSocket', 'XMLNodeType', 'XMLNode',
+            'XMLList', 'XMLDocument', 'XML', 'Video', 'VerifyError',
+            'URLVariables', 'URLStream', 'URLRequestMethod', 'URLRequestHeader',
+            'URLRequest', 'URLLoaderDataFormat', 'URLLoader', 'URIError',
+            'TypeError', 'Transform', 'TimerEvent', 'Timer', 'TextSnapshot',
+            'TextRenderer', 'TextLineMetrics', 'TextFormatAlign', 'TextFormat',
+            'TextFieldType', 'TextFieldAutoSize', 'TextField', 'TextEvent',
+            'TextDisplayMode', 'TextColorType', 'System', 'SyntaxError',
+            'SyncEvent', 'StyleSheet', 'String', 'StatusEvent', 'StaticText',
+            'StageScaleMode', 'StageQuality', 'StageAlign', 'Stage',
+            'StackOverflowError', 'Sprite', 'SpreadMethod', 'SoundTransform',
+            'SoundMixer', 'SoundLoaderContext', 'SoundChannel', 'Sound',
+            'Socket', 'SimpleButton', 'SharedObjectFlushStatus', 'SharedObject',
+            'Shape', 'SecurityPanel', 'SecurityErrorEvent', 'SecurityError',
+            'SecurityDomain', 'Security', 'ScriptTimeoutError', 'Scene',
+            'SWFVersion', 'Responder', 'RegExp', 'ReferenceError', 'Rectangle',
+            'RangeError', 'QName', 'Proxy', 'ProgressEvent',
+            'PrintJobOrientation', 'PrintJobOptions', 'PrintJob', 'Point',
+            'PixelSnapping', 'ObjectEncoding', 'Object', 'Number', 'NetStream',
+            'NetStatusEvent', 'NetConnection', 'Namespace', 'MovieClip',
+            'MouseEvent', 'Mouse', 'MorphShape', 'Microphone', 'MemoryError',
+            'Matrix', 'Math', 'LocalConnection', 'LoaderInfo', 'LoaderContext',
+            'Loader', 'LineScaleMode', 'KeyboardEvent', 'Keyboard',
+            'KeyLocation', 'JointStyle', 'InvalidSWFError',
+            'InterpolationMethod', 'InteractiveObject', 'IllegalOperationError',
+            'IOErrorEvent', 'IOError', 'IMEEvent', 'IMEConversionMode', 'IME',
+            'IExternalizable', 'IEventDispatcher', 'IDynamicPropertyWriter',
+            'IDynamicPropertyOutput', 'IDataOutput', 'IDataInput', 'ID3Info',
+            'IBitmapDrawable', 'HTTPStatusEvent', 'GridFitType', 'Graphics',
+            'GradientType', 'GradientGlowFilter', 'GradientBevelFilter',
+            'GlowFilter', 'Function', 'FrameLabel', 'FontType', 'FontStyle',
+            'Font', 'FocusEvent', 'FileReferenceList', 'FileReference',
+            'FileFilter', 'ExternalInterface', 'EventPhase', 'EventDispatcher',
+            'Event', 'EvalError', 'ErrorEvent', 'Error', 'Endian', 'EOFError',
+            'DropShadowFilter', 'DisplayObjectContainer', 'DisplayObject',
+            'DisplacementMapFilterMode', 'DisplacementMapFilter', 'Dictionary',
+            'DefinitionError', 'Date', 'DataEvent', 'ConvolutionFilter',
+            'ContextMenuItem', 'ContextMenuEvent', 'ContextMenuBuiltInItems',
+            'ContextMenu', 'ColorTransform', 'ColorMatrixFilter', 'Class',
+            'CapsStyle', 'Capabilities', 'Camera', 'CSMSettings', 'ByteArray',
+            'Boolean', 'BlurFilter', 'BlendMode', 'BitmapFilterType',
+            'BitmapFilterQuality', 'BitmapFilter', 'BitmapDataChannel',
+            'BitmapData', 'Bitmap', 'BevelFilter', 'AsyncErrorEvent', 'Array',
+            'ArgumentError', 'ApplicationDomain', 'AntiAliasType',
+            'ActivityEvent', 'ActionScriptVersion', 'AccessibilityProperties',
+            'Accessibility', 'AVM1Movie'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}', '!', '%', '&', '*', '|', '/', '<', '>', '^', '-', '+', '~', '?', ':'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true,
+        5 => true,
+        6 => true,
+        7 => true,
+        8 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0033ff; font-weight: bold;',
+            2 => 'color: #6699cc; font-weight: bold;',
+            3 => 'color: #339966; font-weight: bold;',
+            4 => 'color: #9900cc; font-weight: bold;',
+            5 => 'color: #004993;',
+            6 => 'color: #004993;',
+            7 => 'color: #004993;',
+            8 => 'color: #004993;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #009900;',
+            'MULTI' => 'color: #3f5fbf;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => ''
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000000;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #990000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #000000; font-weight:bold;'
+            ),
+        'METHODS' => array(
+            0 => 'color: #000000;',
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000000; font-weight: bold;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => '',
+        5 => 'http://www.google.com/search?q={FNAMEL}%20inurl:http://livedocs.adobe.com/flex/201/langref/%20inurl:{FNAMEL}.html&amp;filter=0&amp;num=100&amp;btnI=lucky',
+        6 => '',
+        7 => '',
+        8 => ''
+        ),
+    'OOLANG' => false,//Save some time as OO identifiers aren't used
+    'OBJECT_SPLITTERS' => array(
+        // commented out because it's not very relevant for AS, as all properties, methods and constants are dot-accessed.
+        // I believe it's preferable to have package highlighting for example, which is not possible with this enabled.
+        // 0 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(),
+    'HIGHLIGHT_STRICT_BLOCK' => array()
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/ada.php b/examples/includes/geshi/geshi/ada.php
new file mode 100644 (file)
index 0000000..1013883
--- /dev/null
@@ -0,0 +1,133 @@
+<?php
+/*************************************************************************************
+ * ada.php
+ * -------
+ * Author: Tux (tux@inmail.cz)
+ * Copyright: (c) 2004 Tux (http://tux.a4.cz/), Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/07/29
+ *
+ * Ada language file for GeSHi.
+ * Words are from SciTe configuration file
+ *
+ * CHANGES
+ * -------
+ * 2004/11/27 (1.0.2)
+ *  -  Added support for multiple object splitters
+ * 2004/10/27 (1.0.1)
+ *   -  Removed apostrophe as string delimiter
+ *   -  Added URL support
+ * 2004/08/05 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Ada',
+    'COMMENT_SINGLE' => array(1 => '--'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'begin', 'declare', 'do', 'else', 'elsif', 'exception', 'for', 'if',
+            'is', 'loop', 'while', 'then', 'end', 'select', 'case', 'until',
+            'goto', 'return'
+            ),
+        2 => array(
+            'abs', 'and', 'mod', 'not', 'or', 'rem', 'xor'
+            ),
+        3 => array(
+            'abort', 'abstract', 'accept', 'access', 'aliased', 'all', 'array', 'at', 'body',
+            'constant', 'delay', 'delta', 'digits', 'entry', 'exit',
+            'function', 'generic', 'in', 'limited', 'new', 'null', 'of', 'others', 'out', 'package', 'pragma',
+            'private', 'procedure', 'protected', 'raise', 'range', 'record', 'renames', 'requeue', 'reverse',
+            'separate', 'subtype', 'tagged', 'task', 'terminate', 'type', 'use', 'when', 'with'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #00007f;',
+            2 => 'color: #0000ff;',
+            3 => 'color: #46aa03; font-weight:bold;',
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #adadad; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #7f007f;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #202020;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/apache.php b/examples/includes/geshi/geshi/apache.php
new file mode 100644 (file)
index 0000000..fa06afe
--- /dev/null
@@ -0,0 +1,206 @@
+<?php
+/*************************************************************************************
+ * apache.php
+ * ----------
+ * Author: Tux (tux@inmail.cz)
+ * Copyright: (c) 2004 Tux (http://tux.a4.cz/), Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/29/07
+ *
+ * Apache language file for GeSHi.
+ * Words are from SciTe configuration file
+ *
+ * CHANGES
+ * -------
+ * 2008/17/06 (1.0.8)
+ *  -  Added support for apache configuration sections (milian)
+ *  -  Added missing php keywords (milian)
+ *  -  Added some more keywords
+ *  -  Disabled highlighting of brackets by default
+ * 2004/11/27 (1.0.2)
+ *  -  Added support for multiple object splitters
+ * 2004/10/27 (1.0.1)
+ *   -  Added support for URLs
+ * 2004/08/05 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2004/07/29)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Apache configuration',
+    'COMMENT_SINGLE' => array(1 => '#'),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        /*keywords*/
+        1 => array(
+            'accessconfig','accessfilename','action','addalt',
+            'addaltbyencoding','addaltbytype','addcharset',
+            'adddefaultcharset','adddescription',
+            'addencoding','addhandler','addicon','addiconbyencoding',
+            'addiconbytype','addlanguage','addmodule','addmoduleinfo',
+            'addtype','agentlog','alias','aliasmatch',
+            'allow','allowconnect','allowoverride','anonymous',
+            'anonymous_authoritative','anonymous_logemail','anonymous_mustgiveemail',
+            'anonymous_nouserid','anonymous_verifyemail','authauthoritative',
+            'authdbauthoritative','authdbgroupfile','authdbmauthoritative',
+            'authdbmgroupfile','authdbuserfile','authdbmuserfile',
+            'authdigestfile','authgroupfile','authname','authtype',
+            'authuserfile','bindaddress','browsermatch','browsermatchnocase',
+            'bs2000account','cachedefaultexpire','cachedirlength','cachedirlevels',
+            'cacheforcecompletion','cachegcinterval','cachelastmodifiedfactor','cachemaxexpire',
+            'cachenegotiateddocs','cacheroot','cachesize','checkspelling',
+            'clearmodulelist','contentdigest','cookieexpires','cookielog',
+            'cookietracking','coredumpdirectory','customlog',
+            'defaulticon','defaultlanguage','defaulttype','define',
+            'deny','directory','directorymatch','directoryindex',
+            'documentroot','errordocument','errorlog','example',
+            'expiresactive','expiresbytype','expiresdefault','extendedstatus',
+            'fancyindexing','files','filesmatch','forcetype',
+            'group','header','headername','hostnamelookups',
+            'identitycheck','ifdefine','ifmodule','imapbase',
+            'imapdefault','imapmenu','include','indexignore','indexorderdefault',
+            'indexoptions','keepalive','keepalivetimeout','languagepriority',
+            'limit','limitexcept','limitrequestbody','limitrequestfields',
+            'limitrequestfieldsize','limitrequestline','listen','listenbacklog',
+            'loadfile','loadmodule','location','locationmatch',
+            'lockfile','logformat','loglevel','maxclients',
+            'maxkeepaliverequests','maxrequestsperchild','maxspareservers','maxsparethreads','metadir',
+            'metafiles','metasuffix','mimemagicfile','minspareservers','minsparethreads',
+            'mmapfile','namevirtualhost','nocache','options','order',
+            'passenv','php_admin_value','php_admin_flag','php_value','pidfile','port','proxyblock','proxydomain',
+            'proxypass','proxypassreverse','proxyreceivebuffersize','proxyremote',
+            'proxyrequests','proxyvia','qsc','readmename',
+            'redirect','redirectmatch','redirectpermanent','redirecttemp',
+            'refererignore','refererlog','removehandler','require',
+            'resourceconfig','rewritebase','rewritecond','rewriteengine',
+            'rewritelock','rewritelog','rewriteloglevel','rewritemap',
+            'rewriteoptions','rewriterule','rlimitcpu','rlimitmem',
+            'rlimitnproc','satisfy','scoreboardfile','script',
+            'scriptalias','scriptaliasmatch','scriptinterpretersource','scriptlog',
+            'scriptlogbuffer','scriptloglength','sendbuffersize',
+            'serveradmin','serveralias','servername','serverpath',
+            'serverroot','serversignature','servertokens','servertype',
+            'setenv','setenvif','setenvifnocase','sethandler',
+            'singlelisten','startservers','threadsperchild','timeout',
+            'transferlog','typesconfig','unsetenv','usecanonicalname',
+            'user','userdir','virtualhost','virtualdocumentroot',
+            'virtualdocumentrootip','virtualscriptalias','virtualscriptaliasip',
+            'xbithack','from','all'
+            ),
+        /*keywords 2*/
+        2 => array(
+            'on','off','standalone','inetd','indexes',
+            'force-response-1.0','downgrade-1.0','nokeepalive',
+            'ndexes','includes','followsymlinks','none',
+            'x-compress','x-gzip'
+        ),
+        /*keywords 3*/
+        3 => array(
+            'Directory',
+            'DirectoryMatch',
+            'Files',
+            'FilesMatch',
+            'IfDefine',
+            'IfModule',
+            'IfVersion',
+            'Location',
+            'LocationMatch',
+            'Proxy',
+            'ProxyMatch',
+            'VirtualHost'
+        )
+    ),
+    'SYMBOLS' => array(
+        '+', '-'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #00007f;',
+            2 => 'color: #0000ff;',
+            3 => 'color: #000000; font-weight:bold;',
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #adadad; font-style: italic;',
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #339933;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #7f007f;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #008000;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'PARSER_CONTROL' => array(
+        'ENABLE_FLAGS' => array(
+            'BRACKETS' => GESHI_NEVER,
+            'SYMBOLS' => GESHI_NEVER
+        ),
+        'KEYWORDS' => array(
+            3 => array(
+                'DISALLOWED_BEFORE' => '(?<=&lt;|&lt;\/)',
+                'DISALLOWED_AFTER' => '(?=\s|\/|&gt;)',
+            )
+        )
+    )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/applescript.php b/examples/includes/geshi/geshi/applescript.php
new file mode 100644 (file)
index 0000000..395bba7
--- /dev/null
@@ -0,0 +1,157 @@
+<?php
+/*************************************************************************************
+ * applescript.php
+ * --------
+ * Author: Stephan Klimek (http://www.initware.org)
+ * Copyright: Stephan Klimek (http://www.initware.org)
+ * Release Version: 1.0.8.3
+ * Date Started: 2005/07/20
+ *
+ * AppleScript language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *  -  Added description of extra language features (SF#1970248)
+ *
+ * TODO
+ * -------------------------
+ * URL settings to references
+ *
+ **************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'AppleScript',
+    'COMMENT_SINGLE' => array(1 => '--'),
+    'COMMENT_MULTI' => array( '(*' => '*)'),
+    'COMMENT_REGEXP' => array(
+        2 => '/(?<=[a-z])\'/i',
+        3 => '/(?<![a-z])\'.*?\'/i',
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'application','close','count','delete','duplicate','exists','launch','make','move','open',
+            'print','quit','reopen','run','save','saving', 'idle', 'path to', 'number', 'alias', 'list', 'text', 'string',
+            'integer', 'it','me','version','pi','result','space','tab','anything','case','diacriticals','expansion',
+            'hyphens','punctuation','bold','condensed','expanded','hidden','italic','outline','plain',
+            'shadow','strikethrough','subscript','superscript','underline','ask','no','yes','false', 'id',
+            'true','weekday','monday','mon','tuesday','tue','wednesday','wed','thursday','thu','friday',
+            'fri','saturday','sat','sunday','sun','month','january','jan','february','feb','march',
+            'mar','april','apr','may','june','jun','july','jul','august','aug','september', 'quote', 'do JavaScript',
+            'sep','october','oct','november','nov','december','dec','minutes','hours', 'name', 'default answer',
+            'days','weeks', 'folder', 'folders', 'file', 'files', 'window', 'eject', 'disk', 'reveal', 'sleep',
+            'shut down', 'restart', 'display dialog', 'buttons', 'invisibles', 'item', 'items', 'delimiters', 'offset of',
+            'AppleScript\'s', 'choose file', 'choose folder', 'choose from list', 'beep', 'contents', 'do shell script',
+            'paragraph', 'paragraphs', 'missing value', 'quoted form', 'desktop', 'POSIX path', 'POSIX file',
+            'activate', 'document', 'adding', 'receiving', 'content', 'new', 'properties', 'info for', 'bounds',
+            'selection', 'extension', 'into', 'onto', 'by', 'between', 'against', 'set the clipboard to', 'the clipboard'
+            ),
+        2 => array(
+            'each','some','every','whose','where','index','first','second','third','fourth',
+            'fifth','sixth','seventh','eighth','ninth','tenth','last','front','back','st','nd',
+            'rd','th','middle','named','through','thru','before','after','beginning','the', 'as',
+            'div','mod','and','not','or','contains','equal','equals','isnt', 'less', 'greater'
+            ),
+        3 => array(
+            'script','property','prop','end','to','set','global','local','on','of',
+            'in','given','with','without','return','continue','tell','if','then','else','repeat',
+            'times','while','until','from','exit','try','error','considering','ignoring','timeout',
+            'transaction','my','get','put','is', 'copy'
+            )
+        ),
+    'SYMBOLS' => array(
+        ')','+','-','^','*','/','&','<','>=','<','<=','=','�'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0066ff;',
+            2 => 'color: #ff0033;',
+            3 => 'color: #ff0033; font-weight: bold;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            2 => '',
+            3 => 'color: #ff0000;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000000; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000000;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #009900;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #000000;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006600;',
+            2 => 'color: #006600;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000000;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #339933;',
+            4 => 'color: #0066ff;',
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => ',+-=&lt;&gt;/?^&amp;*'
+        ),
+    'REGEXPS' => array(
+        //Variables
+        0 => '[\\$%@]+[a-zA-Z_][a-zA-Z0-9_]*',
+        //File descriptors
+        4 => '&lt;[a-zA-Z_][a-zA-Z0-9_]*&gt;',
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            'SPACE_AS_WHITESPACE' => true
+            )
+        )
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/apt_sources.php b/examples/includes/geshi/geshi/apt_sources.php
new file mode 100644 (file)
index 0000000..1321032
--- /dev/null
@@ -0,0 +1,144 @@
+<?php
+/*************************************************************************************
+ * apt_sources.php
+ * ----------
+ * Author: Milian Wolff (mail@milianw.de)
+ * Copyright: (c) 2008 Milian Wolff (http://milianw.de)
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/06/17
+ *
+ * Apt sources.list language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/06/17 (1.0.8)
+ *  -  Initial import
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Apt sources',
+    'COMMENT_SINGLE' => array(1 => '#'),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array(),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        /*keywords*/
+        1 => array(
+            'deb-src', 'deb'
+            ),
+        2 => array(
+            //Generic
+            'stable', 'old-stable', 'testing', 'testing-proposed-updates',
+            'unstable', 'unstable-proposed-updates', 'experimental',
+            'non-US', 'security', 'volatile', 'volatile-sloppy',
+            'apt-build',
+            'stable/updates',
+            //Debian
+            'buzz', 'rex', 'bo', 'hamm', 'slink', 'potato', 'woody', 'sarge',
+            'etch', 'lenny', 'sid',
+            //Ubuntu
+            'warty', 'warty-updates', 'warty-security', 'warty-proposed', 'warty-backports',
+            'hoary', 'hoary-updates', 'hoary-security', 'hoary-proposed', 'hoary-backports',
+            'breezy', 'breezy-updates', 'breezy-security', 'breezy-proposed', 'breezy-backports',
+            'dapper', 'dapper-updates', 'dapper-security', 'dapper-proposed', 'dapper-backports',
+            'edgy', 'edgy-updates', 'edgy-security', 'edgy-proposed', 'edgy-backports',
+            'feisty', 'feisty-updates', 'feisty-security', 'feisty-proposed', 'feisty-backports',
+            'gutsy', 'gutsy-updates', 'gutsy-security', 'gutsy-proposed', 'gutsy-backports',
+            'hardy', 'hardy-updates', 'hardy-security', 'hardy-proposed', 'hardy-backports',
+            'intrepid', 'intrepid-updates', 'intrepid-security', 'intrepid-proposed', 'intrepid-backports'
+            ),
+        3 => array(
+            'main', 'restricted', 'preview', 'contrib', 'non-free',
+            'commercial', 'universe', 'multiverse'
+            )
+    ),
+    'REGEXPS' => array(
+        0 => "(((http|ftp):\/\/|file:\/)[^\s]+)|(cdrom:\[[^\]]*\][^\s]*)",
+        ),
+    'SYMBOLS' => array(
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => true,
+        3 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #00007f;',
+            2 => 'color: #b1b100;',
+            3 => 'color: #b16000;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #adadad; font-style: italic;',
+            ),
+        'ESCAPE_CHAR' => array(
+            ),
+        'BRACKETS' => array(
+            ),
+        'STRINGS' => array(
+            ),
+        'NUMBERS' => array(
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #009900;',
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'PARSER_CONTROL' => array(
+        'ENABLE_FLAGS' => array(
+            'NUMBERS' => GESHI_NEVER,
+            'METHODS' => GESHI_NEVER,
+            'SCRIPT' => GESHI_NEVER,
+            'SYMBOLS' => GESHI_NEVER,
+            'ESCAPE_CHAR' => GESHI_NEVER,
+            'BRACKETS' => GESHI_NEVER,
+            'STRINGS' => GESHI_NEVER,
+        ),
+        'KEYWORDS' => array(
+            'DISALLOWED_BEFORE' => '(?<![a-zA-Z0-9\$_\|\#;>|^\/])',
+            'DISALLOWED_AFTER' => '(?![a-zA-Z0-9_\|%\\-&\.])'
+        )
+    ),
+    'TAB_WIDTH' => 4
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/asm.php b/examples/includes/geshi/geshi/asm.php
new file mode 100644 (file)
index 0000000..af4eef7
--- /dev/null
@@ -0,0 +1,225 @@
+<?php
+/*************************************************************************************
+ * asm.php
+ * -------
+ * Author: Tux (tux@inmail.cz)
+ * Copyright: (c) 2004 Tux (http://tux.a4.cz/), Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/07/27
+ *
+ * x86 Assembler language file for GeSHi.
+ * Words are from SciTe configuration file (based on NASM syntax)
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *   -  Added description of extra language features (SF#1970248)
+ * 2004/11/27 (1.0.2)
+ *   -  Added support for multiple object splitters
+ * 2004/10/27 (1.0.1)
+ *   -  Added support for URLs
+ *   -  Added binary and hexadecimal regexps
+ * 2004/08/05 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'ASM',
+    'COMMENT_SINGLE' => array(1 => ';'),
+    'COMMENT_MULTI' => array(),
+    //Line address prefix suppression
+    'COMMENT_REGEXP' => array(2 => "/^(?:[0-9a-f]{0,4}:)?[0-9a-f]{4}(?:[0-9a-f]{4})?/mi"),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        /*CPU*/
+        1 => array(
+            'aaa','aad','aam','aas','adc','add','and','call','cbw','clc','cld','cli','cmc','cmp',
+            'cmps','cmpsb','cmpsw','cwd','daa','das','dec','div','esc','hlt','idiv','imul','in','inc',
+            'int','into','iret','ja','jae','jb','jbe','jc','jcxz','je','jg','jge','jl','jle','jmp',
+            'jna','jnae','jnb','jnbe','jnc','jne','jng','jnge','jnl','jnle','jno','jnp','jns','jnz',
+            'jo','jp','jpe','jpo','js','jz','lahf','lds','lea','les','lods','lodsb','lodsw','loop',
+            'loope','loopew','loopne','loopnew','loopnz','loopnzw','loopw','loopz','loopzw','mov',
+            'movs','movsb','movsw','mul','neg','nop','not','or','out','pop','popf','push','pushf',
+            'rcl','rcr','ret','retf','retn','rol','ror','sahf','sal','sar','sbb','scas','scasb','scasw',
+            'shl','shr','stc','std','sti','stos','stosb','stosw','sub','test','wait','xchg','xlat',
+            'xlatb','xor','bound','enter','ins','insb','insw','leave','outs','outsb','outsw','popa','pusha','pushw',
+            'arpl','lar','lsl','sgdt','sidt','sldt','smsw','str','verr','verw','clts','lgdt','lidt','lldt','lmsw','ltr',
+            'bsf','bsr','bt','btc','btr','bts','cdq','cmpsd','cwde','insd','iretd','iretdf','iretf',
+            'jecxz','lfs','lgs','lodsd','loopd','looped','loopned','loopnzd','loopzd','lss','movsd',
+            'movsx','movzx','outsd','popad','popfd','pushad','pushd','pushfd','scasd','seta','setae',
+            'setb','setbe','setc','sete','setg','setge','setl','setle','setna','setnae','setnb','setnbe',
+            'setnc','setne','setng','setnge','setnl','setnle','setno','setnp','setns','setnz','seto','setp',
+            'setpe','setpo','sets','setz','shld','shrd','stosd','bswap','cmpxchg','invd','invlpg','wbinvd','xadd','lock',
+            'rep','repe','repne','repnz','repz'
+            ),
+        /*FPU*/
+        2 => array(
+            'f2xm1','fabs','fadd','faddp','fbld','fbstp','fchs','fclex','fcom','fcomp','fcompp','fdecstp',
+            'fdisi','fdiv','fdivp','fdivr','fdivrp','feni','ffree','fiadd','ficom','ficomp','fidiv',
+            'fidivr','fild','fimul','fincstp','finit','fist','fistp','fisub','fisubr','fld','fld1',
+            'fldcw','fldenv','fldenvw','fldl2e','fldl2t','fldlg2','fldln2','fldpi','fldz','fmul',
+            'fmulp','fnclex','fndisi','fneni','fninit','fnop','fnsave','fnsavew','fnstcw','fnstenv',
+            'fnstenvw','fnstsw','fpatan','fprem','fptan','frndint','frstor','frstorw','fsave',
+            'fsavew','fscale','fsqrt','fst','fstcw','fstenv','fstenvw','fstp','fstsw','fsub','fsubp',
+            'fsubr','fsubrp','ftst','fwait','fxam','fxch','fxtract','fyl2x','fyl2xp1',
+            'fsetpm','fcos','fldenvd','fnsaved','fnstenvd','fprem1','frstord','fsaved','fsin','fsincos',
+            'fstenvd','fucom','fucomp','fucompp'
+            ),
+        /*registers*/
+        3 => array(
+            'ah','al','ax','bh','bl','bp','bx','ch','cl','cr0','cr2','cr3','cs','cx','dh','di','dl',
+            'dr0','dr1','dr2','dr3','dr6','dr7','ds','dx','eax','ebp','ebx','ecx','edi','edx',
+            'es','esi','esp','fs','gs','si','sp','ss','st','tr3','tr4','tr5','tr6','tr7'
+            ),
+        /*Directive*/
+        4 => array(
+            '186','286','286c','286p','287','386','386c','386p','387','486','486p',
+            '8086','8087','alpha','break','code','const','continue','cref','data','data?',
+            'dosseg','else','elseif','endif','endw','err','err1','err2','errb',
+            'errdef','errdif','errdifi','erre','erridn','erridni','errnb','errndef',
+            'errnz','exit','fardata','fardata?','if','lall','lfcond','list','listall',
+            'listif','listmacro','listmacroall',' model','no87','nocref','nolist',
+            'nolistif','nolistmacro','radix','repeat','sall','seq','sfcond','stack',
+            'startup','tfcond','type','until','untilcxz','while','xall','xcref',
+            'xlist','alias','align','assume','catstr','comm','comment','db','dd','df','dq',
+            'dt','dup','dw','echo','elseif1','elseif2','elseifb','elseifdef','elseifdif',
+            'elseifdifi','elseife','elseifidn','elseifidni','elseifnb','elseifndef','end',
+            'endm','endp','ends','eq',' equ','even','exitm','extern','externdef','extrn','for',
+            'forc','ge','goto','group','high','highword','if1','if2','ifb','ifdef','ifdif',
+            'ifdifi','ife',' ifidn','ifidni','ifnb','ifndef','include','includelib','instr','invoke',
+            'irp','irpc','label','le','length','lengthof','local','low','lowword','lroffset',
+            'macro','mask','mod','msfloat','name','ne','offset','opattr','option','org','%out',
+            'page','popcontext','private','proc','proto','ptr','public','purge','pushcontext','record',
+            'rept','seg','segment','short','size','sizeof','sizestr','struc','struct',
+            'substr','subtitle','subttl','textequ','this','title','typedef','union','width',
+            '.model', '.stack', '.code', '.data'
+            ),
+        /*Operands*/
+        5 => array(
+            '@b','@f','addr','basic','byte','c','carry?','dword',
+            'far','far16','fortran','fword','near','near16','overflow?','parity?','pascal','qword',
+            'real4',' real8','real10','sbyte','sdword','sign?','stdcall','sword','syscall','tbyte',
+            'vararg','word','zero?','flat','near32','far32',
+            'abs','all','assumes','at','casemap','common','compact',
+            'cpu','dotname','emulator','epilogue','error','export','expr16','expr32','farstack',
+            'forceframe','huge','language','large','listing','ljmp','loadds','m510','medium','memory',
+            'nearstack','nodotname','noemulator','nokeyword','noljmp','nom510','none','nonunique',
+            'nooldmacros','nooldstructs','noreadonly','noscoped','nosignextend','nothing',
+            'notpublic','oldmacros','oldstructs','os_dos','para','prologue',
+            'readonly','req','scoped','setif2','smallstack','tiny','use16','use32','uses'
+            )
+        ),
+    'SYMBOLS' => array(
+        '[', ']', '(', ')',
+        '+', '-', '*', '/', '%',
+        '.', ',', ';', ':'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        5 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #00007f; font-weight: bold;',
+            2 => 'color: #0000ff; font-weight: bold;',
+            3 => 'color: #00007f;',
+            4 => 'color: #000000; font-weight: bold;',
+            5 => 'color: #000000; font-weight: bold;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #666666; font-style: italic;',
+            2 => 'color: #adadad; font-style: italic;',
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #009900; font-weight: bold;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #7f007f;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #0000ff;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #339933;'
+            ),
+        'REGEXPS' => array(
+//            0 => 'color: #0000ff;',
+//            1 => 'color: #0000ff;'
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => '',
+        5 => ''
+        ),
+    'NUMBERS' =>
+        GESHI_NUMBER_BIN_PREFIX_PERCENT |
+        GESHI_NUMBER_BIN_SUFFIX |
+        GESHI_NUMBER_HEX_PREFIX |
+        GESHI_NUMBER_HEX_SUFFIX |
+        GESHI_NUMBER_OCT_SUFFIX |
+        GESHI_NUMBER_INT_BASIC |
+        GESHI_NUMBER_FLT_NONSCI |
+        GESHI_NUMBER_FLT_NONSCI_F |
+        GESHI_NUMBER_FLT_SCI_ZERO,
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        //Hex numbers
+//        0 => /*  */ "(?<=([\\s\\(\\)\\[\\],;.:+\\-\\/*]))(?:[0-9][0-9a-fA-F]{0,31}[hH]|0x[0-9a-fA-F]{1,32})(?=([\\s\\(\\)\\[\\],;.:+\\-\\/*]))",
+        //Binary numbers
+//        1 => "(?<=([\\s\\(\\)\\[\\],;.:+\\-\\/*]))[01]{1,64}[bB](?=([\\s\\(\\)\\[\\],;.:+\\-\\/*]))"
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 8,
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            'DISALLOWED_BEFORE' => "(?<![a-zA-Z0-9\$_\|\#>|^])",
+            'DISALLOWED_AFTER' => "(?![a-zA-Z0-9_<\|%])"
+        )
+    )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/asp.php b/examples/includes/geshi/geshi/asp.php
new file mode 100644 (file)
index 0000000..d2404bb
--- /dev/null
@@ -0,0 +1,164 @@
+<?php
+/*************************************************************************************
+ * asp.php
+ * --------
+ * Author: Amit Gupta (http://blog.igeek.info/)
+ * Copyright: (c) 2004 Amit Gupta (http://blog.igeek.info/), Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/08/13
+ *
+ * ASP language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2005/12/30 (1.0.3)
+ *   -  Strings only delimited by ", comments by '
+ * 2004/11/27 (1.0.2)
+ *   -  Added support for multiple object splitters
+ * 2004/10/27 (1.0.1)
+ *   -  Added support for URLs
+ * 2004/08/13 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ * * Include all the functions, keywords etc that I have missed
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'ASP',
+    'COMMENT_SINGLE' => array(1 => "'", 2 => '//'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            'include', 'file', 'Const', 'Dim', 'Option', 'Explicit', 'Implicit', 'Set', 'Select', 'ReDim', 'Preserve',
+            'ByVal', 'ByRef', 'End', 'Private', 'Public', 'If', 'Then', 'Else', 'ElseIf', 'Case', 'With', 'NOT',
+            'While', 'Wend', 'For', 'Loop', 'Do', 'Request', 'Response', 'Server', 'ADODB', 'Session', 'Application',
+            'Each', 'In', 'Get', 'Next', 'INT', 'CINT', 'CBOOL', 'CDATE', 'CBYTE', 'CCUR', 'CDBL', 'CLNG', 'CSNG',
+            'CSTR', 'Fix', 'Is', 'Sgn', 'String', 'Boolean', 'Currency', 'Me', 'Single', 'Long', 'Integer', 'Byte',
+            'Variant', 'Double', 'To', 'Let', 'Xor', 'Resume', 'On', 'Error', 'Imp', 'GoTo', 'Call', 'Global'
+            ),
+        2 => array(
+            'Null', 'Nothing', 'And',
+            'False',
+            'True', 'var', 'Or', 'BOF', 'EOF', 'xor',
+            'Function', 'Class', 'New', 'Sub'
+            ),
+        3 => array(
+            'CreateObject', 'Write', 'Redirect', 'Cookies', 'BinaryRead', 'ClientCertificate', 'Form', 'QueryString',
+            'ServerVariables', 'TotalBytes', 'AddHeader', 'AppendToLog', 'BinaryWrite', 'Buffer', 'CacheControl',
+            'Charset', 'Clear', 'ContentType', 'End()', 'Expires', 'ExpiresAbsolute', 'Flush()', 'IsClientConnected',
+            'PICS', 'Status', 'Connection', 'Recordset', 'Execute', 'Abandon', 'Lock', 'UnLock', 'Command', 'Fields',
+            'Properties', 'Property', 'Send', 'Replace', 'InStr', 'TRIM', 'NOW', 'Day', 'Month', 'Hour', 'Minute', 'Second',
+            'Year', 'MonthName', 'LCase', 'UCase', 'Abs', 'Array', 'As', 'LEN', 'MoveFirst', 'MoveLast', 'MovePrevious',
+            'MoveNext', 'LBound', 'UBound', 'Transfer', 'Open', 'Close', 'MapPath', 'FileExists', 'OpenTextFile', 'ReadAll'
+            )
+        ),
+    'SYMBOLS' => array(
+        1 => array(
+            '<%', '%>'
+            ),
+        0 => array(
+            '(', ')', '[', ']', '!', '@', '%', '&', '*', '|', '/', '<', '>',
+            ';', ':', '?', '='),
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #990099; font-weight: bold;',
+            2 => 'color: #0000ff; font-weight: bold;',
+            3 => 'color: #330066;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #008000;',
+            2 => 'color: #ff6600;',
+            'MULTI' => 'color: #008000;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #006600; font-weight:bold;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #cc0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #800000;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #9900cc;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #006600; font-weight: bold;',
+            1 => 'color: #000000; font-weight: bold;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            0 => '',
+            1 => '',
+            2 => '',
+            3 => ''
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_MAYBE,
+    'SCRIPT_DELIMITERS' => array(
+        0 => array(
+            '<%' => '%>'
+            ),
+        1 => array(
+            '<script language="vbscript" runat="server">' => '</script>'
+            ),
+        2 => array(
+            '<script language="javascript" runat="server">' => '</script>'
+            ),
+        3 => "/(<%=?)(?:\"[^\"]*?\"|\/\*(?!\*\/).*?\*\/|.)*?(%>|\Z)/sm"
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        0 => true,
+        1 => true,
+        2 => true,
+        3 => true
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/autoit.php b/examples/includes/geshi/geshi/autoit.php
new file mode 100644 (file)
index 0000000..259c822
--- /dev/null
@@ -0,0 +1,1171 @@
+<?php
+/*************************************************************************************
+ * autoit.php
+ * --------
+ * Author: big_daddy (robert.i.anthony@gmail.com)
+ * Copyright: (c) 2006 and to GESHi ;)
+ * Release Version: 1.0.8.3
+ * Date Started: 2006/01/26
+ *
+ * AutoIT language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * Release 1.0.8.1 (2008/09/15)
+ * - Updated on 22.03.2008 By Tlem (tlem@tuxolem.fr)
+ * - The link on functions will now correctly re-direct to
+ * - http://www.autoitscript.com/autoit3/docs/functions/{FNAME}.htm
+ * - Updated whith au3.api (09.02.2008).
+ * - Updated - 16 Mai 2008 - v3.2.12.0
+ * - Updated - 12 June 2008 - v3.2.12.1
+ * Release 1.0.7.20 (2006/01/26)
+ * - First Release
+ *
+ * Current bugs & todo:
+ * ----------
+ * - not sure how to get sendkeys to work " {!}, {SPACE} etc... "
+ * - just copyied the regexp for variable from php so this HAVE to be checked and fixed to a better one ;)
+ *
+ * Reference: http://www.autoitscript.com/autoit3/docs/
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not,
+write to the Free Software
+ *   Foundation,
+Inc.,
+59 Temple Place,
+Suite 330,
+Boston,
+MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'AutoIt',
+    'COMMENT_SINGLE' => array(';'),
+    'COMMENT_MULTI' => array(
+        '#comments-start' => '#comments-end',
+        '#cs' => '#ce'),
+    'COMMENT_REGEXP' => array(0 => '/(?<!#)#(\s.*)?$/m'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            'And','ByRef','Case','Const','ContinueCase','ContinueLoop',
+            'Default','Dim','Do','Else','ElseIf','EndFunc','EndIf','EndSelect',
+            'EndSwitch','EndWith','Enum','Exit','ExitLoop','False','For','Func',
+            'Global','If','In','Local','Next','Not','Or','ReDim','Return',
+            'Select','Step','Switch','Then','To','True','Until','WEnd','While',
+            'With'
+            ),
+        2 => array(
+            '@AppDataCommonDir','@AppDataDir','@AutoItExe','@AutoItPID',
+            '@AutoItUnicode','@AutoItVersion','@AutoItX64','@COM_EventObj',
+            '@CommonFilesDir','@Compiled','@ComputerName','@ComSpec','@CR',
+            '@CRLF','@DesktopCommonDir','@DesktopDepth','@DesktopDir',
+            '@DesktopHeight','@DesktopRefresh','@DesktopWidth',
+            '@DocumentsCommonDir','@error','@exitCode','@exitMethod',
+            '@extended','@FavoritesCommonDir','@FavoritesDir','@GUI_CtrlHandle',
+            '@GUI_CtrlId','@GUI_DragFile','@GUI_DragId','@GUI_DropId',
+            '@GUI_WinHandle','@HomeDrive','@HomePath','@HomeShare',
+            '@HotKeyPressed','@HOUR','@InetGetActive','@InetGetBytesRead',
+            '@IPAddress1','@IPAddress2','@IPAddress3','@IPAddress4','@KBLayout',
+            '@LF','@LogonDNSDomain','@LogonDomain','@LogonServer','@MDAY',
+            '@MIN','@MON','@MyDocumentsDir','@NumParams','@OSBuild','@OSLang',
+            '@OSServicePack','@OSTYPE','@OSVersion','@ProcessorArch',
+            '@ProgramFilesDir','@ProgramsCommonDir','@ProgramsDir','@ScriptDir',
+            '@ScriptFullPath','@ScriptLineNumber','@ScriptName','@SEC',
+            '@StartMenuCommonDir','@StartMenuDir','@StartupCommonDir',
+            '@StartupDir','@SW_DISABLE','@SW_ENABLE','@SW_HIDE','@SW_LOCK',
+            '@SW_MAXIMIZE','@SW_MINIMIZE','@SW_RESTORE','@SW_SHOW',
+            '@SW_SHOWDEFAULT','@SW_SHOWMAXIMIZED','@SW_SHOWMINIMIZED',
+            '@SW_SHOWMINNOACTIVE','@SW_SHOWNA','@SW_SHOWNOACTIVATE',
+            '@SW_SHOWNORMAL','@SW_UNLOCK','@SystemDir','@TAB','@TempDir',
+            '@TRAY_ID','@TrayIconFlashing','@TrayIconVisible','@UserName',
+            '@UserProfileDir','@WDAY','@WindowsDir','@WorkingDir','@YDAY',
+            '@YEAR'
+            ),
+        3 => array(
+            'Abs','ACos','AdlibDisable','AdlibEnable','Asc','AscW','ASin',
+            'Assign','ATan','AutoItSetOption','AutoItWinGetTitle',
+            'AutoItWinSetTitle','Beep','Binary','BinaryLen','BinaryMid',
+            'BinaryToString','BitAND','BitNOT','BitOR','BitRotate','BitShift',
+            'BitXOR','BlockInput','Break','Call','CDTray','Ceiling','Chr',
+            'ChrW','ClipGet','ClipPut','ConsoleRead','ConsoleWrite',
+            'ConsoleWriteError','ControlClick','ControlCommand',
+            'ControlDisable','ControlEnable','ControlFocus','ControlGetFocus',
+            'ControlGetHandle','ControlGetPos','ControlGetText','ControlHide',
+            'ControlListView','ControlMove','ControlSend','ControlSetText',
+            'ControlShow','ControlTreeView','Cos','Dec','DirCopy','DirCreate',
+            'DirGetSize','DirMove','DirRemove','DllCall','DllCallbackFree',
+            'DllCallbackGetPtr','DllCallbackRegister','DllClose','DllOpen',
+            'DllStructCreate','DllStructGetData','DllStructGetPtr',
+            'DllStructGetSize','DllStructSetData','DriveGetDrive',
+            'DriveGetFileSystem','DriveGetLabel','DriveGetSerial',
+            'DriveGetType','DriveMapAdd','DriveMapDel','DriveMapGet',
+            'DriveSetLabel','DriveSpaceFree','DriveSpaceTotal','DriveStatus',
+            'EnvGet','EnvSet','EnvUpdate','Eval','Execute','Exp',
+            'FileChangeDir','FileClose','FileCopy','FileCreateNTFSLink',
+            'FileCreateShortcut','FileDelete','FileExists','FileFindFirstFile',
+            'FileFindNextFile','FileGetAttrib','FileGetLongName',
+            'FileGetShortcut','FileGetShortName','FileGetSize','FileGetTime',
+            'FileGetVersion','FileInstall','FileMove','FileOpen',
+            'FileOpenDialog','FileRead','FileReadLine','FileRecycle',
+            'FileRecycleEmpty','FileSaveDialog','FileSelectFolder',
+            'FileSetAttrib','FileSetTime','FileWrite','FileWriteLine','Floor',
+            'FtpSetProxy','GUICreate','GUICtrlCreateAvi','GUICtrlCreateButton',
+            'GUICtrlCreateCheckbox','GUICtrlCreateCombo',
+            'GUICtrlCreateContextMenu','GUICtrlCreateDate','GUICtrlCreateDummy',
+            'GUICtrlCreateEdit','GUICtrlCreateGraphic','GUICtrlCreateGroup',
+            'GUICtrlCreateIcon','GUICtrlCreateInput','GUICtrlCreateLabel',
+            'GUICtrlCreateList','GUICtrlCreateListView',
+            'GUICtrlCreateListViewItem','GUICtrlCreateMenu',
+            'GUICtrlCreateMenuItem','GUICtrlCreateMonthCal','GUICtrlCreateObj',
+            'GUICtrlCreatePic','GUICtrlCreateProgress','GUICtrlCreateRadio',
+            'GUICtrlCreateSlider','GUICtrlCreateTab','GUICtrlCreateTabItem',
+            'GUICtrlCreateTreeView','GUICtrlCreateTreeViewItem',
+            'GUICtrlCreateUpdown','GUICtrlDelete','GUICtrlGetHandle',
+            'GUICtrlGetState','GUICtrlRead','GUICtrlRecvMsg',
+            'GUICtrlRegisterListViewSort','GUICtrlSendMsg','GUICtrlSendToDummy',
+            'GUICtrlSetBkColor','GUICtrlSetColor','GUICtrlSetCursor',
+            'GUICtrlSetData','GUICtrlSetFont','GUICtrlSetDefColor',
+            'GUICtrlSetDefBkColor','GUICtrlSetGraphic','GUICtrlSetImage',
+            'GUICtrlSetLimit','GUICtrlSetOnEvent','GUICtrlSetPos',
+            'GUICtrlSetResizing','GUICtrlSetState','GUICtrlSetStyle',
+            'GUICtrlSetTip','GUIDelete','GUIGetCursorInfo','GUIGetMsg',
+            'GUIGetStyle','GUIRegisterMsg','GUISetAccelerators()',
+            'GUISetBkColor','GUISetCoord','GUISetCursor','GUISetFont',
+            'GUISetHelp','GUISetIcon','GUISetOnEvent','GUISetState',
+            'GUISetStyle','GUIStartGroup','GUISwitch','Hex','HotKeySet',
+            'HttpSetProxy','HWnd','InetGet','InetGetSize','IniDelete','IniRead',
+            'IniReadSection','IniReadSectionNames','IniRenameSection',
+            'IniWrite','IniWriteSection','InputBox','Int','IsAdmin','IsArray',
+            'IsBinary','IsBool','IsDeclared','IsDllStruct','IsFloat','IsHWnd',
+            'IsInt','IsKeyword','IsNumber','IsObj','IsPtr','IsString','Log',
+            'MemGetStats','Mod','MouseClick','MouseClickDrag','MouseDown',
+            'MouseGetCursor','MouseGetPos','MouseMove','MouseUp','MouseWheel',
+            'MsgBox','Number','ObjCreate','ObjEvent','ObjGet','ObjName','Opt',
+            'Ping','PixelChecksum','PixelGetColor','PixelSearch','PluginClose',
+            'PluginOpen','ProcessClose','ProcessExists','ProcessGetStats',
+            'ProcessList','ProcessSetPriority','ProcessWait','ProcessWaitClose',
+            'ProgressOff','ProgressOn','ProgressSet','Ptr','Random','RegDelete',
+            'RegEnumKey','RegEnumVal','RegRead','RegWrite','Round','Run',
+            'RunAs','RunAsWait','RunWait','Send','SendKeepActive','SetError',
+            'SetExtended','ShellExecute','ShellExecuteWait','Shutdown','Sin',
+            'Sleep','SoundPlay','SoundSetWaveVolume','SplashImageOn',
+            'SplashOff','SplashTextOn','Sqrt','SRandom','StatusbarGetText',
+            'StderrRead','StdinWrite','StdioClose','StdoutRead','String',
+            'StringAddCR','StringCompare','StringFormat','StringInStr',
+            'StringIsAlNum','StringIsAlpha','StringIsASCII','StringIsDigit',
+            'StringIsFloat','StringIsInt','StringIsLower','StringIsSpace',
+            'StringIsUpper','StringIsXDigit','StringLeft','StringLen',
+            'StringLower','StringMid','StringRegExp','StringRegExpReplace',
+            'StringReplace','StringRight','StringSplit','StringStripCR',
+            'StringStripWS','StringToBinary','StringTrimLeft','StringTrimRight',
+            'StringUpper','Tan','TCPAccept','TCPCloseSocket','TCPConnect',
+            'TCPListen','TCPNameToIP','TCPRecv','TCPSend','TCPShutdown',
+            'TCPStartup','TimerDiff','TimerInit','ToolTip','TrayCreateItem',
+            'TrayCreateMenu','TrayGetMsg','TrayItemDelete','TrayItemGetHandle',
+            'TrayItemGetState','TrayItemGetText','TrayItemSetOnEvent',
+            'TrayItemSetState','TrayItemSetText','TraySetClick','TraySetIcon',
+            'TraySetOnEvent','TraySetPauseIcon','TraySetState','TraySetToolTip',
+            'TrayTip','UBound','UDPBind','UDPCloseSocket','UDPOpen','UDPRecv',
+            'UDPSend','UDPShutdown','UDPStartup','VarGetType','WinActivate',
+            'WinActive','WinClose','WinExists','WinFlash','WinGetCaretPos',
+            'WinGetClassList','WinGetClientSize','WinGetHandle','WinGetPos',
+            'WinGetProcess','WinGetState','WinGetText','WinGetTitle','WinKill',
+            'WinList','WinMenuSelectItem','WinMinimizeAll','WinMinimizeAllUndo',
+            'WinMove','WinSetOnTop','WinSetState','WinSetTitle','WinSetTrans',
+            'WinWait','WinWaitActive','WinWaitClose','WinWaitNotActive'
+            ),
+        4 => array(
+            'ArrayAdd','ArrayBinarySearch','ArrayConcatenate','ArrayDelete',
+            'ArrayDisplay','ArrayFindAll','ArrayInsert','ArrayMax',
+            'ArrayMaxIndex','ArrayMin','ArrayMinIndex','ArrayPop','ArrayPush',
+            'ArrayReverse','ArraySearch','ArraySort','ArraySwap','ArrayToClip',
+            'ArrayToString','ArrayTrim','ChooseColor','ChooseFont',
+            'ClipBoard_ChangeChain','ClipBoard_Close','ClipBoard_CountFormats',
+            'ClipBoard_Empty','ClipBoard_EnumFormats','ClipBoard_FormatStr',
+            'ClipBoard_GetData','ClipBoard_GetDataEx','ClipBoard_GetFormatName',
+            'ClipBoard_GetOpenWindow','ClipBoard_GetOwner',
+            'ClipBoard_GetPriorityFormat','ClipBoard_GetSequenceNumber',
+            'ClipBoard_GetViewer','ClipBoard_IsFormatAvailable',
+            'ClipBoard_Open','ClipBoard_RegisterFormat','ClipBoard_SetData',
+            'ClipBoard_SetDataEx','ClipBoard_SetViewer','ClipPutFile',
+            'ColorConvertHSLtoRGB','ColorConvertRGBtoHSL','ColorGetBlue',
+            'ColorGetGreen','ColorGetRed','Date_Time_CompareFileTime',
+            'Date_Time_DOSDateTimeToArray','Date_Time_DOSDateTimeToFileTime',
+            'Date_Time_DOSDateTimeToStr','Date_Time_DOSDateToArray',
+            'Date_Time_DOSDateToStr','Date_Time_DOSTimeToArray',
+            'Date_Time_DOSTimeToStr','Date_Time_EncodeFileTime',
+            'Date_Time_EncodeSystemTime','Date_Time_FileTimeToArray',
+            'Date_Time_FileTimeToDOSDateTime',
+            'Date_Time_FileTimeToLocalFileTime','Date_Time_FileTimeToStr',
+            'Date_Time_FileTimeToSystemTime','Date_Time_GetFileTime',
+            'Date_Time_GetLocalTime','Date_Time_GetSystemTime',
+            'Date_Time_GetSystemTimeAdjustment',
+            'Date_Time_GetSystemTimeAsFileTime',
+            'Date_Time_GetSystemTimes','Date_Time_GetTickCount',
+            'Date_Time_GetTimeZoneInformation',
+            'Date_Time_LocalFileTimeToFileTime','Date_Time_SetFileTime',
+            'Date_Time_SetLocalTime','Date_Time_SetSystemTime',
+            'Date_Time_SetSystemTimeAdjustment',
+            'Date_Time_SetTimeZoneInformation','Date_Time_SystemTimeToArray',
+            'Date_Time_SystemTimeToDateStr','Date_Time_SystemTimeToDateTimeStr',
+            'Date_Time_SystemTimeToFileTime','Date_Time_SystemTimeToTimeStr',
+            'Date_Time_SystemTimeToTzSpecificLocalTime',
+            'Date_Time_TzSpecificLocalTimeToSystemTime','DateAdd',
+            'DateDayOfWeek','DateDaysInMonth','DateDiff','DateIsLeapYear',
+            'DateIsValid','DateTimeFormat','DateTimeSplit','DateToDayOfWeek',
+            'DateToDayOfWeekISO','DateToDayValue','DateToMonth',
+            'DayValueToDate','DebugBugReportEnv','DebugOut','DebugSetup',
+            'Degree','EventLog__Backup','EventLog__Clear','EventLog__Close',
+            'EventLog__Count','EventLog__DeregisterSource','EventLog__Full',
+            'EventLog__Notify','EventLog__Oldest','EventLog__Open',
+            'EventLog__OpenBackup','EventLog__Read','EventLog__RegisterSource',
+            'EventLog__Report','FileCountLines','FileCreate','FileListToArray',
+            'FilePrint','FileReadToArray','FileWriteFromArray',
+            'FileWriteLog','FileWriteToLine','GDIPlus_ArrowCapCreate',
+            'GDIPlus_ArrowCapDispose','GDIPlus_ArrowCapGetFillState',
+            'GDIPlus_ArrowCapGetHeight','GDIPlus_ArrowCapGetMiddleInset',
+            'GDIPlus_ArrowCapGetWidth','GDIPlus_ArrowCapSetFillState',
+            'GDIPlus_ArrowCapSetHeight','GDIPlus_ArrowCapSetMiddleInset',
+            'GDIPlus_ArrowCapSetWidth','GDIPlus_BitmapCloneArea',
+            'GDIPlus_BitmapCreateFromFile','GDIPlus_BitmapCreateFromGraphics',
+            'GDIPlus_BitmapCreateFromHBITMAP',
+            'GDIPlus_BitmapCreateHBITMAPFromBitmap','GDIPlus_BitmapDispose',
+            'GDIPlus_BitmapLockBits','GDIPlus_BitmapUnlockBits',
+            'GDIPlus_BrushClone','GDIPlus_BrushCreateSolid',
+            'GDIPlus_BrushDispose','GDIPlus_BrushGetType',
+            'GDIPlus_CustomLineCapDispose','GDIPlus_Decoders',
+            'GDIPlus_DecodersGetCount','GDIPlus_DecodersGetSize',
+            'GDIPlus_Encoders','GDIPlus_EncodersGetCLSID',
+            'GDIPlus_EncodersGetCount','GDIPlus_EncodersGetParamList',
+            'GDIPlus_EncodersGetParamListSize','GDIPlus_EncodersGetSize',
+            'GDIPlus_FontCreate','GDIPlus_FontDispose',
+            'GDIPlus_FontFamilyCreate','GDIPlus_FontFamilyDispose',
+            'GDIPlus_GraphicsClear','GDIPlus_GraphicsCreateFromHDC',
+            'GDIPlus_GraphicsCreateFromHWND','GDIPlus_GraphicsDispose',
+            'GDIPlus_GraphicsDrawArc','GDIPlus_GraphicsDrawBezier',
+            'GDIPlus_GraphicsDrawClosedCurve','GDIPlus_GraphicsDrawCurve',
+            'GDIPlus_GraphicsDrawEllipse','GDIPlus_GraphicsDrawImage',
+            'GDIPlus_GraphicsDrawImageRect','GDIPlus_GraphicsDrawImageRectRect',
+            'GDIPlus_GraphicsDrawLine','GDIPlus_GraphicsDrawPie',
+            'GDIPlus_GraphicsDrawPolygon','GDIPlus_GraphicsDrawRect',
+            'GDIPlus_GraphicsDrawString','GDIPlus_GraphicsDrawStringEx',
+            'GDIPlus_GraphicsFillClosedCurve','GDIPlus_GraphicsFillEllipse',
+            'GDIPlus_GraphicsFillPie','GDIPlus_GraphicsFillRect',
+            'GDIPlus_GraphicsGetDC','GDIPlus_GraphicsGetSmoothingMode',
+            'GDIPlus_GraphicsMeasureString','GDIPlus_GraphicsReleaseDC',
+            'GDIPlus_GraphicsSetSmoothingMode','GDIPlus_GraphicsSetTransform',
+            'GDIPlus_ImageDispose','GDIPlus_ImageGetGraphicsContext',
+            'GDIPlus_ImageGetHeight','GDIPlus_ImageGetWidth',
+            'GDIPlus_ImageLoadFromFile','GDIPlus_ImageSaveToFile',
+            'GDIPlus_ImageSaveToFileEx','GDIPlus_MatrixCreate',
+            'GDIPlus_MatrixDispose','GDIPlus_MatrixRotate','GDIPlus_ParamAdd',
+            'GDIPlus_ParamInit','GDIPlus_PenCreate','GDIPlus_PenDispose',
+            'GDIPlus_PenGetAlignment','GDIPlus_PenGetColor',
+            'GDIPlus_PenGetCustomEndCap','GDIPlus_PenGetDashCap',
+            'GDIPlus_PenGetDashStyle','GDIPlus_PenGetEndCap',
+            'GDIPlus_PenGetWidth','GDIPlus_PenSetAlignment',
+            'GDIPlus_PenSetColor','GDIPlus_PenSetCustomEndCap',
+            'GDIPlus_PenSetDashCap','GDIPlus_PenSetDashStyle',
+            'GDIPlus_PenSetEndCap','GDIPlus_PenSetWidth','GDIPlus_RectFCreate',
+            'GDIPlus_Shutdown','GDIPlus_Startup','GDIPlus_StringFormatCreate',
+            'GDIPlus_StringFormatDispose','GetIP','GUICtrlAVI_Close',
+            'GUICtrlAVI_Create','GUICtrlAVI_Destroy','GUICtrlAVI_Open',
+            'GUICtrlAVI_OpenEx','GUICtrlAVI_Play','GUICtrlAVI_Seek',
+            'GUICtrlAVI_Show','GUICtrlAVI_Stop','GUICtrlButton_Click',
+            'GUICtrlButton_Create','GUICtrlButton_Destroy',
+            'GUICtrlButton_Enable','GUICtrlButton_GetCheck',
+            'GUICtrlButton_GetFocus','GUICtrlButton_GetIdealSize',
+            'GUICtrlButton_GetImage','GUICtrlButton_GetImageList',
+            'GUICtrlButton_GetState','GUICtrlButton_GetText',
+            'GUICtrlButton_GetTextMargin','GUICtrlButton_SetCheck',
+            'GUICtrlButton_SetFocus','GUICtrlButton_SetImage',
+            'GUICtrlButton_SetImageList','GUICtrlButton_SetSize',
+            'GUICtrlButton_SetState','GUICtrlButton_SetStyle',
+            'GUICtrlButton_SetText','GUICtrlButton_SetTextMargin',
+            'GUICtrlButton_Show','GUICtrlComboBox_AddDir',
+            'GUICtrlComboBox_AddString','GUICtrlComboBox_AutoComplete',
+            'GUICtrlComboBox_BeginUpdate','GUICtrlComboBox_Create',
+            'GUICtrlComboBox_DeleteString','GUICtrlComboBox_Destroy',
+            'GUICtrlComboBox_EndUpdate','GUICtrlComboBox_FindString',
+            'GUICtrlComboBox_FindStringExact','GUICtrlComboBox_GetComboBoxInfo',
+            'GUICtrlComboBox_GetCount','GUICtrlComboBox_GetCurSel',
+            'GUICtrlComboBox_GetDroppedControlRect',
+            'GUICtrlComboBox_GetDroppedControlRectEx',
+            'GUICtrlComboBox_GetDroppedState','GUICtrlComboBox_GetDroppedWidth',
+            'GUICtrlComboBox_GetEditSel','GUICtrlComboBox_GetEditText',
+            'GUICtrlComboBox_GetExtendedUI',
+            'GUICtrlComboBox_GetHorizontalExtent',
+            'GUICtrlComboBox_GetItemHeight','GUICtrlComboBox_GetLBText',
+            'GUICtrlComboBox_GetLBTextLen','GUICtrlComboBox_GetList',
+            'GUICtrlComboBox_GetListArray','GUICtrlComboBox_GetLocale',
+            'GUICtrlComboBox_GetLocaleCountry','GUICtrlComboBox_GetLocaleLang',
+            'GUICtrlComboBox_GetLocalePrimLang',
+            'GUICtrlComboBox_GetLocaleSubLang','GUICtrlComboBox_GetMinVisible',
+            'GUICtrlComboBox_GetTopIndex','GUICtrlComboBox_InitStorage',
+            'GUICtrlComboBox_InsertString','GUICtrlComboBox_LimitText',
+            'GUICtrlComboBox_ReplaceEditSel','GUICtrlComboBox_ResetContent',
+            'GUICtrlComboBox_SelectString','GUICtrlComboBox_SetCurSel',
+            'GUICtrlComboBox_SetDroppedWidth','GUICtrlComboBox_SetEditSel',
+            'GUICtrlComboBox_SetEditText','GUICtrlComboBox_SetExtendedUI',
+            'GUICtrlComboBox_SetHorizontalExtent',
+            'GUICtrlComboBox_SetItemHeight','GUICtrlComboBox_SetMinVisible',
+            'GUICtrlComboBox_SetTopIndex','GUICtrlComboBox_ShowDropDown',
+            'GUICtrlComboBoxEx_AddDir','GUICtrlComboBoxEx_AddString',
+            'GUICtrlComboBoxEx_BeginUpdate','GUICtrlComboBoxEx_Create',
+            'GUICtrlComboBoxEx_CreateSolidBitMap',
+            'GUICtrlComboBoxEx_DeleteString','GUICtrlComboBoxEx_Destroy',
+            'GUICtrlComboBoxEx_EndUpdate','GUICtrlComboBoxEx_FindStringExact',
+            'GUICtrlComboBoxEx_GetComboBoxInfo',
+            'GUICtrlComboBoxEx_GetComboControl','GUICtrlComboBoxEx_GetCount',
+            'GUICtrlComboBoxEx_GetCurSel',
+            'GUICtrlComboBoxEx_GetDroppedControlRect',
+            'GUICtrlComboBoxEx_GetDroppedControlRectEx',
+            'GUICtrlComboBoxEx_GetDroppedState',
+            'GUICtrlComboBoxEx_GetDroppedWidth',
+            'GUICtrlComboBoxEx_GetEditControl','GUICtrlComboBoxEx_GetEditSel',
+            'GUICtrlComboBoxEx_GetEditText',
+            'GUICtrlComboBoxEx_GetExtendedStyle',
+            'GUICtrlComboBoxEx_GetExtendedUI','GUICtrlComboBoxEx_GetImageList',
+            'GUICtrlComboBoxEx_GetItem','GUICtrlComboBoxEx_GetItemEx',
+            'GUICtrlComboBoxEx_GetItemHeight','GUICtrlComboBoxEx_GetItemImage',
+            'GUICtrlComboBoxEx_GetItemIndent',
+            'GUICtrlComboBoxEx_GetItemOverlayImage',
+            'GUICtrlComboBoxEx_GetItemParam',
+            'GUICtrlComboBoxEx_GetItemSelectedImage',
+            'GUICtrlComboBoxEx_GetItemText','GUICtrlComboBoxEx_GetItemTextLen',
+            'GUICtrlComboBoxEx_GetList','GUICtrlComboBoxEx_GetListArray',
+            'GUICtrlComboBoxEx_GetLocale','GUICtrlComboBoxEx_GetLocaleCountry',
+            'GUICtrlComboBoxEx_GetLocaleLang',
+            'GUICtrlComboBoxEx_GetLocalePrimLang',
+            'GUICtrlComboBoxEx_GetLocaleSubLang',
+            'GUICtrlComboBoxEx_GetMinVisible','GUICtrlComboBoxEx_GetTopIndex',
+            'GUICtrlComboBoxEx_InitStorage','GUICtrlComboBoxEx_InsertString',
+            'GUICtrlComboBoxEx_LimitText','GUICtrlComboBoxEx_ReplaceEditSel',
+            'GUICtrlComboBoxEx_ResetContent','GUICtrlComboBoxEx_SetCurSel',
+            'GUICtrlComboBoxEx_SetDroppedWidth','GUICtrlComboBoxEx_SetEditSel',
+            'GUICtrlComboBoxEx_SetEditText',
+            'GUICtrlComboBoxEx_SetExtendedStyle',
+            'GUICtrlComboBoxEx_SetExtendedUI','GUICtrlComboBoxEx_SetImageList',
+            'GUICtrlComboBoxEx_SetItem','GUICtrlComboBoxEx_SetItemEx',
+            'GUICtrlComboBoxEx_SetItemHeight','GUICtrlComboBoxEx_SetItemImage',
+            'GUICtrlComboBoxEx_SetItemIndent',
+            'GUICtrlComboBoxEx_SetItemOverlayImage',
+            'GUICtrlComboBoxEx_SetItemParam',
+            'GUICtrlComboBoxEx_SetItemSelectedImage',
+            'GUICtrlComboBoxEx_SetMinVisible','GUICtrlComboBoxEx_SetTopIndex',
+            'GUICtrlComboBoxEx_ShowDropDown','GUICtrlDTP_Create',
+            'GUICtrlDTP_Destroy','GUICtrlDTP_GetMCColor','GUICtrlDTP_GetMCFont',
+            'GUICtrlDTP_GetMonthCal','GUICtrlDTP_GetRange',
+            'GUICtrlDTP_GetRangeEx','GUICtrlDTP_GetSystemTime',
+            'GUICtrlDTP_GetSystemTimeEx','GUICtrlDTP_SetFormat',
+            'GUICtrlDTP_SetMCColor','GUICtrlDTP_SetMCFont',
+            'GUICtrlDTP_SetRange','GUICtrlDTP_SetRangeEx',
+            'GUICtrlDTP_SetSystemTime','GUICtrlDTP_SetSystemTimeEx',
+            'GUICtrlEdit_AppendText','GUICtrlEdit_BeginUpdate',
+            'GUICtrlEdit_CanUndo','GUICtrlEdit_CharFromPos',
+            'GUICtrlEdit_Create','GUICtrlEdit_Destroy',
+            'GUICtrlEdit_EmptyUndoBuffer','GUICtrlEdit_EndUpdate',
+            'GUICtrlEdit_Find','GUICtrlEdit_FmtLines',
+            'GUICtrlEdit_GetFirstVisibleLine','GUICtrlEdit_GetLimitText',
+            'GUICtrlEdit_GetLine','GUICtrlEdit_GetLineCount',
+            'GUICtrlEdit_GetMargins','GUICtrlEdit_GetModify',
+            'GUICtrlEdit_GetPasswordChar','GUICtrlEdit_GetRECT',
+            'GUICtrlEdit_GetRECTEx','GUICtrlEdit_GetSel','GUICtrlEdit_GetText',
+            'GUICtrlEdit_GetTextLen','GUICtrlEdit_HideBalloonTip',
+            'GUICtrlEdit_InsertText','GUICtrlEdit_LineFromChar',
+            'GUICtrlEdit_LineIndex','GUICtrlEdit_LineLength',
+            'GUICtrlEdit_LineScroll','GUICtrlEdit_PosFromChar',
+            'GUICtrlEdit_ReplaceSel','GUICtrlEdit_Scroll',
+            'GUICtrlEdit_SetLimitText','GUICtrlEdit_SetMargins',
+            'GUICtrlEdit_SetModify','GUICtrlEdit_SetPasswordChar',
+            'GUICtrlEdit_SetReadOnly','GUICtrlEdit_SetRECT',
+            'GUICtrlEdit_SetRECTEx','GUICtrlEdit_SetRECTNP',
+            'GUICtrlEdit_SetRectNPEx','GUICtrlEdit_SetSel',
+            'GUICtrlEdit_SetTabStops','GUICtrlEdit_SetText',
+            'GUICtrlEdit_ShowBalloonTip','GUICtrlEdit_Undo',
+            'GUICtrlHeader_AddItem','GUICtrlHeader_ClearFilter',
+            'GUICtrlHeader_ClearFilterAll','GUICtrlHeader_Create',
+            'GUICtrlHeader_CreateDragImage','GUICtrlHeader_DeleteItem',
+            'GUICtrlHeader_Destroy','GUICtrlHeader_EditFilter',
+            'GUICtrlHeader_GetBitmapMargin','GUICtrlHeader_GetImageList',
+            'GUICtrlHeader_GetItem','GUICtrlHeader_GetItemAlign',
+            'GUICtrlHeader_GetItemBitmap','GUICtrlHeader_GetItemCount',
+            'GUICtrlHeader_GetItemDisplay','GUICtrlHeader_GetItemFlags',
+            'GUICtrlHeader_GetItemFormat','GUICtrlHeader_GetItemImage',
+            'GUICtrlHeader_GetItemOrder','GUICtrlHeader_GetItemParam',
+            'GUICtrlHeader_GetItemRect','GUICtrlHeader_GetItemRectEx',
+            'GUICtrlHeader_GetItemText','GUICtrlHeader_GetItemWidth',
+            'GUICtrlHeader_GetOrderArray','GUICtrlHeader_GetUnicodeFormat',
+            'GUICtrlHeader_HitTest','GUICtrlHeader_InsertItem',
+            'GUICtrlHeader_Layout','GUICtrlHeader_OrderToIndex',
+            'GUICtrlHeader_SetBitmapMargin',
+            'GUICtrlHeader_SetFilterChangeTimeout',
+            'GUICtrlHeader_SetHotDivider','GUICtrlHeader_SetImageList',
+            'GUICtrlHeader_SetItem','GUICtrlHeader_SetItemAlign',
+            'GUICtrlHeader_SetItemBitmap','GUICtrlHeader_SetItemDisplay',
+            'GUICtrlHeader_SetItemFlags','GUICtrlHeader_SetItemFormat',
+            'GUICtrlHeader_SetItemImage','GUICtrlHeader_SetItemOrder',
+            'GUICtrlHeader_SetItemParam','GUICtrlHeader_SetItemText',
+            'GUICtrlHeader_SetItemWidth','GUICtrlHeader_SetOrderArray',
+            'GUICtrlHeader_SetUnicodeFormat','GUICtrlIpAddress_ClearAddress',
+            'GUICtrlIpAddress_Create','GUICtrlIpAddress_Destroy',
+            'GUICtrlIpAddress_Get','GUICtrlIpAddress_GetArray',
+            'GUICtrlIpAddress_GetEx','GUICtrlIpAddress_IsBlank',
+            'GUICtrlIpAddress_Set','GUICtrlIpAddress_SetArray',
+            'GUICtrlIpAddress_SetEx','GUICtrlIpAddress_SetFocus',
+            'GUICtrlIpAddress_SetFont','GUICtrlIpAddress_SetRange',
+            'GUICtrlIpAddress_ShowHide','GUICtrlListBox_AddFile',
+            'GUICtrlListBox_AddString','GUICtrlListBox_BeginUpdate',
+            'GUICtrlListBox_Create','GUICtrlListBox_DeleteString',
+            'GUICtrlListBox_Destroy','GUICtrlListBox_Dir',
+            'GUICtrlListBox_EndUpdate','GUICtrlListBox_FindInText',
+            'GUICtrlListBox_FindString','GUICtrlListBox_GetAnchorIndex',
+            'GUICtrlListBox_GetCaretIndex','GUICtrlListBox_GetCount',
+            'GUICtrlListBox_GetCurSel','GUICtrlListBox_GetHorizontalExtent',
+            'GUICtrlListBox_GetItemData','GUICtrlListBox_GetItemHeight',
+            'GUICtrlListBox_GetItemRect','GUICtrlListBox_GetItemRectEx',
+            'GUICtrlListBox_GetListBoxInfo','GUICtrlListBox_GetLocale',
+            'GUICtrlListBox_GetLocaleCountry','GUICtrlListBox_GetLocaleLang',
+            'GUICtrlListBox_GetLocalePrimLang',
+            'GUICtrlListBox_GetLocaleSubLang','GUICtrlListBox_GetSel',
+            'GUICtrlListBox_GetSelCount','GUICtrlListBox_GetSelItems',
+            'GUICtrlListBox_GetSelItemsText','GUICtrlListBox_GetText',
+            'GUICtrlListBox_GetTextLen','GUICtrlListBox_GetTopIndex',
+            'GUICtrlListBox_InitStorage','GUICtrlListBox_InsertString',
+            'GUICtrlListBox_ItemFromPoint','GUICtrlListBox_ReplaceString',
+            'GUICtrlListBox_ResetContent','GUICtrlListBox_SelectString',
+            'GUICtrlListBox_SelItemRange','GUICtrlListBox_SelItemRangeEx',
+            'GUICtrlListBox_SetAnchorIndex','GUICtrlListBox_SetCaretIndex',
+            'GUICtrlListBox_SetColumnWidth','GUICtrlListBox_SetCurSel',
+            'GUICtrlListBox_SetHorizontalExtent','GUICtrlListBox_SetItemData',
+            'GUICtrlListBox_SetItemHeight','GUICtrlListBox_SetLocale',
+            'GUICtrlListBox_SetSel','GUICtrlListBox_SetTabStops',
+            'GUICtrlListBox_SetTopIndex','GUICtrlListBox_Sort',
+            'GUICtrlListBox_SwapString','GUICtrlListBox_UpdateHScroll',
+            'GUICtrlListView_AddArray','GUICtrlListView_AddColumn',
+            'GUICtrlListView_AddItem','GUICtrlListView_AddSubItem',
+            'GUICtrlListView_ApproximateViewHeight',
+            'GUICtrlListView_ApproximateViewRect',
+            'GUICtrlListView_ApproximateViewWidth','GUICtrlListView_Arrange',
+            'GUICtrlListView_BeginUpdate','GUICtrlListView_CancelEditLabel',
+            'GUICtrlListView_ClickItem','GUICtrlListView_CopyItems',
+            'GUICtrlListView_Create','GUICtrlListView_CreateDragImage',
+            'GUICtrlListView_CreateSolidBitMap',
+            'GUICtrlListView_DeleteAllItems','GUICtrlListView_DeleteColumn',
+            'GUICtrlListView_DeleteItem','GUICtrlListView_DeleteItemsSelected',
+            'GUICtrlListView_Destroy','GUICtrlListView_DrawDragImage',
+            'GUICtrlListView_EditLabel','GUICtrlListView_EnableGroupView',
+            'GUICtrlListView_EndUpdate','GUICtrlListView_EnsureVisible',
+            'GUICtrlListView_FindInText','GUICtrlListView_FindItem',
+            'GUICtrlListView_FindNearest','GUICtrlListView_FindParam',
+            'GUICtrlListView_FindText','GUICtrlListView_GetBkColor',
+            'GUICtrlListView_GetBkImage','GUICtrlListView_GetCallbackMask',
+            'GUICtrlListView_GetColumn','GUICtrlListView_GetColumnCount',
+            'GUICtrlListView_GetColumnOrder',
+            'GUICtrlListView_GetColumnOrderArray',
+            'GUICtrlListView_GetColumnWidth','GUICtrlListView_GetCounterPage',
+            'GUICtrlListView_GetEditControl',
+            'GUICtrlListView_GetExtendedListViewStyle',
+            'GUICtrlListView_GetGroupInfo',
+            'GUICtrlListView_GetGroupViewEnabled','GUICtrlListView_GetHeader',
+            'GUICtrlListView_GetHotCursor','GUICtrlListView_GetHotItem',
+            'GUICtrlListView_GetHoverTime','GUICtrlListView_GetImageList',
+            'GUICtrlListView_GetISearchString','GUICtrlListView_GetItem',
+            'GUICtrlListView_GetItemChecked','GUICtrlListView_GetItemCount',
+            'GUICtrlListView_GetItemCut','GUICtrlListView_GetItemDropHilited',
+            'GUICtrlListView_GetItemEx','GUICtrlListView_GetItemFocused',
+            'GUICtrlListView_GetItemGroupID','GUICtrlListView_GetItemImage',
+            'GUICtrlListView_GetItemIndent','GUICtrlListView_GetItemParam',
+            'GUICtrlListView_GetItemPosition',
+            'GUICtrlListView_GetItemPositionX',
+            'GUICtrlListView_GetItemPositionY','GUICtrlListView_GetItemRect',
+            'GUICtrlListView_GetItemRectEx','GUICtrlListView_GetItemSelected',
+            'GUICtrlListView_GetItemSpacing','GUICtrlListView_GetItemSpacingX',
+            'GUICtrlListView_GetItemSpacingY','GUICtrlListView_GetItemState',
+            'GUICtrlListView_GetItemStateImage','GUICtrlListView_GetItemText',
+            'GUICtrlListView_GetItemTextArray',
+            'GUICtrlListView_GetItemTextString','GUICtrlListView_GetNextItem',
+            'GUICtrlListView_GetNumberOfWorkAreas','GUICtrlListView_GetOrigin',
+            'GUICtrlListView_GetOriginX','GUICtrlListView_GetOriginY',
+            'GUICtrlListView_GetOutlineColor',
+            'GUICtrlListView_GetSelectedColumn',
+            'GUICtrlListView_GetSelectedCount',
+            'GUICtrlListView_GetSelectedIndices',
+            'GUICtrlListView_GetSelectionMark','GUICtrlListView_GetStringWidth',
+            'GUICtrlListView_GetSubItemRect','GUICtrlListView_GetTextBkColor',
+            'GUICtrlListView_GetTextColor','GUICtrlListView_GetToolTips',
+            'GUICtrlListView_GetTopIndex','GUICtrlListView_GetUnicodeFormat',
+            'GUICtrlListView_GetView','GUICtrlListView_GetViewDetails',
+            'GUICtrlListView_GetViewLarge','GUICtrlListView_GetViewList',
+            'GUICtrlListView_GetViewRect','GUICtrlListView_GetViewSmall',
+            'GUICtrlListView_GetViewTile','GUICtrlListView_HideColumn',
+            'GUICtrlListView_HitTest','GUICtrlListView_InsertColumn',
+            'GUICtrlListView_InsertGroup','GUICtrlListView_InsertItem',
+            'GUICtrlListView_JustifyColumn','GUICtrlListView_MapIDToIndex',
+            'GUICtrlListView_MapIndexToID','GUICtrlListView_RedrawItems',
+            'GUICtrlListView_RegisterSortCallBack',
+            'GUICtrlListView_RemoveAllGroups','GUICtrlListView_RemoveGroup',
+            'GUICtrlListView_Scroll','GUICtrlListView_SetBkColor',
+            'GUICtrlListView_SetBkImage','GUICtrlListView_SetCallBackMask',
+            'GUICtrlListView_SetColumn','GUICtrlListView_SetColumnOrder',
+            'GUICtrlListView_SetColumnOrderArray',
+            'GUICtrlListView_SetColumnWidth',
+            'GUICtrlListView_SetExtendedListViewStyle',
+            'GUICtrlListView_SetGroupInfo','GUICtrlListView_SetHotItem',
+            'GUICtrlListView_SetHoverTime','GUICtrlListView_SetIconSpacing',
+            'GUICtrlListView_SetImageList','GUICtrlListView_SetItem',
+            'GUICtrlListView_SetItemChecked','GUICtrlListView_SetItemCount',
+            'GUICtrlListView_SetItemCut','GUICtrlListView_SetItemDropHilited',
+            'GUICtrlListView_SetItemEx','GUICtrlListView_SetItemFocused',
+            'GUICtrlListView_SetItemGroupID','GUICtrlListView_SetItemImage',
+            'GUICtrlListView_SetItemIndent','GUICtrlListView_SetItemParam',
+            'GUICtrlListView_SetItemPosition',
+            'GUICtrlListView_SetItemPosition32',
+            'GUICtrlListView_SetItemSelected','GUICtrlListView_SetItemState',
+            'GUICtrlListView_SetItemStateImage','GUICtrlListView_SetItemText',
+            'GUICtrlListView_SetOutlineColor',
+            'GUICtrlListView_SetSelectedColumn',
+            'GUICtrlListView_SetSelectionMark','GUICtrlListView_SetTextBkColor',
+            'GUICtrlListView_SetTextColor','GUICtrlListView_SetToolTips',
+            'GUICtrlListView_SetUnicodeFormat','GUICtrlListView_SetView',
+            'GUICtrlListView_SetWorkAreas','GUICtrlListView_SimpleSort',
+            'GUICtrlListView_SortItems','GUICtrlListView_SubItemHitTest',
+            'GUICtrlListView_UnRegisterSortCallBack',
+            'GUICtrlMenu_AddMenuItem','GUICtrlMenu_AppendMenu',
+            'GUICtrlMenu_CheckMenuItem','GUICtrlMenu_CheckRadioItem',
+            'GUICtrlMenu_CreateMenu','GUICtrlMenu_CreatePopup',
+            'GUICtrlMenu_DeleteMenu','GUICtrlMenu_DestroyMenu',
+            'GUICtrlMenu_DrawMenuBar','GUICtrlMenu_EnableMenuItem',
+            'GUICtrlMenu_FindItem','GUICtrlMenu_FindParent',
+            'GUICtrlMenu_GetItemBmp','GUICtrlMenu_GetItemBmpChecked',
+            'GUICtrlMenu_GetItemBmpUnchecked','GUICtrlMenu_GetItemChecked',
+            'GUICtrlMenu_GetItemCount','GUICtrlMenu_GetItemData',
+            'GUICtrlMenu_GetItemDefault','GUICtrlMenu_GetItemDisabled',
+            'GUICtrlMenu_GetItemEnabled','GUICtrlMenu_GetItemGrayed',
+            'GUICtrlMenu_GetItemHighlighted','GUICtrlMenu_GetItemID',
+            'GUICtrlMenu_GetItemInfo','GUICtrlMenu_GetItemRect',
+            'GUICtrlMenu_GetItemRectEx','GUICtrlMenu_GetItemState',
+            'GUICtrlMenu_GetItemStateEx','GUICtrlMenu_GetItemSubMenu',
+            'GUICtrlMenu_GetItemText','GUICtrlMenu_GetItemType',
+            'GUICtrlMenu_GetMenu','GUICtrlMenu_GetMenuBackground',
+            'GUICtrlMenu_GetMenuBarInfo','GUICtrlMenu_GetMenuContextHelpID',
+            'GUICtrlMenu_GetMenuData','GUICtrlMenu_GetMenuDefaultItem',
+            'GUICtrlMenu_GetMenuHeight','GUICtrlMenu_GetMenuInfo',
+            'GUICtrlMenu_GetMenuStyle','GUICtrlMenu_GetSystemMenu',
+            'GUICtrlMenu_InsertMenuItem','GUICtrlMenu_InsertMenuItemEx',
+            'GUICtrlMenu_IsMenu','GUICtrlMenu_LoadMenu',
+            'GUICtrlMenu_MapAccelerator','GUICtrlMenu_MenuItemFromPoint',
+            'GUICtrlMenu_RemoveMenu','GUICtrlMenu_SetItemBitmaps',
+            'GUICtrlMenu_SetItemBmp','GUICtrlMenu_SetItemBmpChecked',
+            'GUICtrlMenu_SetItemBmpUnchecked','GUICtrlMenu_SetItemChecked',
+            'GUICtrlMenu_SetItemData','GUICtrlMenu_SetItemDefault',
+            'GUICtrlMenu_SetItemDisabled','GUICtrlMenu_SetItemEnabled',
+            'GUICtrlMenu_SetItemGrayed','GUICtrlMenu_SetItemHighlighted',
+            'GUICtrlMenu_SetItemID','GUICtrlMenu_SetItemInfo',
+            'GUICtrlMenu_SetItemState','GUICtrlMenu_SetItemSubMenu',
+            'GUICtrlMenu_SetItemText','GUICtrlMenu_SetItemType',
+            'GUICtrlMenu_SetMenu','GUICtrlMenu_SetMenuBackground',
+            'GUICtrlMenu_SetMenuContextHelpID','GUICtrlMenu_SetMenuData',
+            'GUICtrlMenu_SetMenuDefaultItem','GUICtrlMenu_SetMenuHeight',
+            'GUICtrlMenu_SetMenuInfo','GUICtrlMenu_SetMenuStyle',
+            'GUICtrlMenu_TrackPopupMenu','GUICtrlMonthCal_Create',
+            'GUICtrlMonthCal_Destroy','GUICtrlMonthCal_GetColor',
+            'GUICtrlMonthCal_GetColorArray','GUICtrlMonthCal_GetCurSel',
+            'GUICtrlMonthCal_GetCurSelStr','GUICtrlMonthCal_GetFirstDOW',
+            'GUICtrlMonthCal_GetFirstDOWStr','GUICtrlMonthCal_GetMaxSelCount',
+            'GUICtrlMonthCal_GetMaxTodayWidth',
+            'GUICtrlMonthCal_GetMinReqHeight','GUICtrlMonthCal_GetMinReqRect',
+            'GUICtrlMonthCal_GetMinReqRectArray',
+            'GUICtrlMonthCal_GetMinReqWidth','GUICtrlMonthCal_GetMonthDelta',
+            'GUICtrlMonthCal_GetMonthRange','GUICtrlMonthCal_GetMonthRangeMax',
+            'GUICtrlMonthCal_GetMonthRangeMaxStr',
+            'GUICtrlMonthCal_GetMonthRangeMin',
+            'GUICtrlMonthCal_GetMonthRangeMinStr',
+            'GUICtrlMonthCal_GetMonthRangeSpan','GUICtrlMonthCal_GetRange',
+            'GUICtrlMonthCal_GetRangeMax','GUICtrlMonthCal_GetRangeMaxStr',
+            'GUICtrlMonthCal_GetRangeMin','GUICtrlMonthCal_GetRangeMinStr',
+            'GUICtrlMonthCal_GetSelRange','GUICtrlMonthCal_GetSelRangeMax',
+            'GUICtrlMonthCal_GetSelRangeMaxStr',
+            'GUICtrlMonthCal_GetSelRangeMin',
+            'GUICtrlMonthCal_GetSelRangeMinStr','GUICtrlMonthCal_GetToday',
+            'GUICtrlMonthCal_GetTodayStr','GUICtrlMonthCal_GetUnicodeFormat',
+            'GUICtrlMonthCal_HitTest','GUICtrlMonthCal_SetColor',
+            'GUICtrlMonthCal_SetCurSel','GUICtrlMonthCal_SetDayState',
+            'GUICtrlMonthCal_SetFirstDOW','GUICtrlMonthCal_SetMaxSelCount',
+            'GUICtrlMonthCal_SetMonthDelta','GUICtrlMonthCal_SetRange',
+            'GUICtrlMonthCal_SetSelRange','GUICtrlMonthCal_SetToday',
+            'GUICtrlMonthCal_SetUnicodeFormat','GUICtrlRebar_AddBand',
+            'GUICtrlRebar_AddToolBarBand','GUICtrlRebar_BeginDrag',
+            'GUICtrlRebar_Create','GUICtrlRebar_DeleteBand',
+            'GUICtrlRebar_Destroy','GUICtrlRebar_DragMove',
+            'GUICtrlRebar_EndDrag','GUICtrlRebar_GetBandBackColor',
+            'GUICtrlRebar_GetBandBorders','GUICtrlRebar_GetBandBordersEx',
+            'GUICtrlRebar_GetBandChildHandle','GUICtrlRebar_GetBandChildSize',
+            'GUICtrlRebar_GetBandCount','GUICtrlRebar_GetBandForeColor',
+            'GUICtrlRebar_GetBandHeaderSize','GUICtrlRebar_GetBandID',
+            'GUICtrlRebar_GetBandIdealSize','GUICtrlRebar_GetBandLength',
+            'GUICtrlRebar_GetBandLParam','GUICtrlRebar_GetBandMargins',
+            'GUICtrlRebar_GetBandMarginsEx','GUICtrlRebar_GetBandRect',
+            'GUICtrlRebar_GetBandRectEx','GUICtrlRebar_GetBandStyle',
+            'GUICtrlRebar_GetBandStyleBreak',
+            'GUICtrlRebar_GetBandStyleChildEdge',
+            'GUICtrlRebar_GetBandStyleFixedBMP',
+            'GUICtrlRebar_GetBandStyleFixedSize',
+            'GUICtrlRebar_GetBandStyleGripperAlways',
+            'GUICtrlRebar_GetBandStyleHidden',
+            'GUICtrlRebar_GetBandStyleHideTitle',
+            'GUICtrlRebar_GetBandStyleNoGripper',
+            'GUICtrlRebar_GetBandStyleTopAlign',
+            'GUICtrlRebar_GetBandStyleUseChevron',
+            'GUICtrlRebar_GetBandStyleVariableHeight',
+            'GUICtrlRebar_GetBandText','GUICtrlRebar_GetBarHeight',
+            'GUICtrlRebar_GetBKColor','GUICtrlRebar_GetColorScheme',
+            'GUICtrlRebar_GetRowCount','GUICtrlRebar_GetRowHeight',
+            'GUICtrlRebar_GetTextColor','GUICtrlRebar_GetToolTips',
+            'GUICtrlRebar_GetUnicodeFormat','GUICtrlRebar_HitTest',
+            'GUICtrlRebar_IDToIndex','GUICtrlRebar_MaximizeBand',
+            'GUICtrlRebar_MinimizeBand','GUICtrlRebar_MoveBand',
+            'GUICtrlRebar_SetBandBackColor','GUICtrlRebar_SetBandForeColor',
+            'GUICtrlRebar_SetBandHeaderSize','GUICtrlRebar_SetBandID',
+            'GUICtrlRebar_SetBandIdealSize','GUICtrlRebar_SetBandLength',
+            'GUICtrlRebar_SetBandLParam','GUICtrlRebar_SetBandStyle',
+            'GUICtrlRebar_SetBandStyleBreak',
+            'GUICtrlRebar_SetBandStyleChildEdge',
+            'GUICtrlRebar_SetBandStyleFixedBMP',
+            'GUICtrlRebar_SetBandStyleFixedSize',
+            'GUICtrlRebar_SetBandStyleGripperAlways',
+            'GUICtrlRebar_SetBandStyleHidden',
+            'GUICtrlRebar_SetBandStyleHideTitle',
+            'GUICtrlRebar_SetBandStyleNoGripper',
+            'GUICtrlRebar_SetBandStyleTopAlign',
+            'GUICtrlRebar_SetBandStyleUseChevron',
+            'GUICtrlRebar_SetBandStyleVariableHeight',
+            'GUICtrlRebar_SetBandText','GUICtrlRebar_SetBKColor',
+            'GUICtrlRebar_SetColorScheme','GUICtrlRebar_SetTextColor',
+            'GUICtrlRebar_SetToolTips','GUICtrlRebar_SetUnicodeFormat',
+            'GUICtrlRebar_ShowBand','GUICtrlSlider_ClearSel',
+            'GUICtrlSlider_ClearTics','GUICtrlSlider_Create',
+            'GUICtrlSlider_Destroy','GUICtrlSlider_GetBuddy',
+            'GUICtrlSlider_GetChannelRect','GUICtrlSlider_GetLineSize',
+            'GUICtrlSlider_GetNumTics','GUICtrlSlider_GetPageSize',
+            'GUICtrlSlider_GetPos','GUICtrlSlider_GetPTics',
+            'GUICtrlSlider_GetRange','GUICtrlSlider_GetRangeMax',
+            'GUICtrlSlider_GetRangeMin','GUICtrlSlider_GetSel',
+            'GUICtrlSlider_GetSelEnd','GUICtrlSlider_GetSelStart',
+            'GUICtrlSlider_GetThumbLength','GUICtrlSlider_GetThumbRect',
+            'GUICtrlSlider_GetThumbRectEx','GUICtrlSlider_GetTic',
+            'GUICtrlSlider_GetTicPos','GUICtrlSlider_GetToolTips',
+            'GUICtrlSlider_GetUnicodeFormat','GUICtrlSlider_SetBuddy',
+            'GUICtrlSlider_SetLineSize','GUICtrlSlider_SetPageSize',
+            'GUICtrlSlider_SetPos','GUICtrlSlider_SetRange',
+            'GUICtrlSlider_SetRangeMax','GUICtrlSlider_SetRangeMin',
+            'GUICtrlSlider_SetSel','GUICtrlSlider_SetSelEnd',
+            'GUICtrlSlider_SetSelStart','GUICtrlSlider_SetThumbLength',
+            'GUICtrlSlider_SetTic','GUICtrlSlider_SetTicFreq',
+            'GUICtrlSlider_SetTipSide','GUICtrlSlider_SetToolTips',
+            'GUICtrlSlider_SetUnicodeFormat','GUICtrlStatusBar_Create',
+            'GUICtrlStatusBar_Destroy','GUICtrlStatusBar_EmbedControl',
+            'GUICtrlStatusBar_GetBorders','GUICtrlStatusBar_GetBordersHorz',
+            'GUICtrlStatusBar_GetBordersRect','GUICtrlStatusBar_GetBordersVert',
+            'GUICtrlStatusBar_GetCount','GUICtrlStatusBar_GetHeight',
+            'GUICtrlStatusBar_GetIcon','GUICtrlStatusBar_GetParts',
+            'GUICtrlStatusBar_GetRect','GUICtrlStatusBar_GetRectEx',
+            'GUICtrlStatusBar_GetText','GUICtrlStatusBar_GetTextFlags',
+            'GUICtrlStatusBar_GetTextLength','GUICtrlStatusBar_GetTextLengthEx',
+            'GUICtrlStatusBar_GetTipText','GUICtrlStatusBar_GetUnicodeFormat',
+            'GUICtrlStatusBar_GetWidth','GUICtrlStatusBar_IsSimple',
+            'GUICtrlStatusBar_Resize','GUICtrlStatusBar_SetBkColor',
+            'GUICtrlStatusBar_SetIcon','GUICtrlStatusBar_SetMinHeight',
+            'GUICtrlStatusBar_SetParts','GUICtrlStatusBar_SetSimple',
+            'GUICtrlStatusBar_SetText','GUICtrlStatusBar_SetTipText',
+            'GUICtrlStatusBar_SetUnicodeFormat','GUICtrlStatusBar_ShowHide',
+            'GUICtrlTab_Create','GUICtrlTab_DeleteAllItems',
+            'GUICtrlTab_DeleteItem','GUICtrlTab_DeselectAll',
+            'GUICtrlTab_Destroy','GUICtrlTab_FindTab','GUICtrlTab_GetCurFocus',
+            'GUICtrlTab_GetCurSel','GUICtrlTab_GetDisplayRect',
+            'GUICtrlTab_GetDisplayRectEx','GUICtrlTab_GetExtendedStyle',
+            'GUICtrlTab_GetImageList','GUICtrlTab_GetItem',
+            'GUICtrlTab_GetItemCount','GUICtrlTab_GetItemImage',
+            'GUICtrlTab_GetItemParam','GUICtrlTab_GetItemRect',
+            'GUICtrlTab_GetItemRectEx','GUICtrlTab_GetItemState',
+            'GUICtrlTab_GetItemText','GUICtrlTab_GetRowCount',
+            'GUICtrlTab_GetToolTips','GUICtrlTab_GetUnicodeFormat',
+            'GUICtrlTab_HighlightItem','GUICtrlTab_HitTest',
+            'GUICtrlTab_InsertItem','GUICtrlTab_RemoveImage',
+            'GUICtrlTab_SetCurFocus','GUICtrlTab_SetCurSel',
+            'GUICtrlTab_SetExtendedStyle','GUICtrlTab_SetImageList',
+            'GUICtrlTab_SetItem','GUICtrlTab_SetItemImage',
+            'GUICtrlTab_SetItemParam','GUICtrlTab_SetItemSize',
+            'GUICtrlTab_SetItemState','GUICtrlTab_SetItemText',
+            'GUICtrlTab_SetMinTabWidth','GUICtrlTab_SetPadding',
+            'GUICtrlTab_SetToolTips','GUICtrlTab_SetUnicodeFormat',
+            'GUICtrlToolbar_AddBitmap','GUICtrlToolbar_AddButton',
+            'GUICtrlToolbar_AddButtonSep','GUICtrlToolbar_AddString',
+            'GUICtrlToolbar_ButtonCount','GUICtrlToolbar_CheckButton',
+            'GUICtrlToolbar_ClickAccel','GUICtrlToolbar_ClickButton',
+            'GUICtrlToolbar_ClickIndex','GUICtrlToolbar_CommandToIndex',
+            'GUICtrlToolbar_Create','GUICtrlToolbar_Customize',
+            'GUICtrlToolbar_DeleteButton','GUICtrlToolbar_Destroy',
+            'GUICtrlToolbar_EnableButton','GUICtrlToolbar_FindToolbar',
+            'GUICtrlToolbar_GetAnchorHighlight','GUICtrlToolbar_GetBitmapFlags',
+            'GUICtrlToolbar_GetButtonBitmap','GUICtrlToolbar_GetButtonInfo',
+            'GUICtrlToolbar_GetButtonInfoEx','GUICtrlToolbar_GetButtonParam',
+            'GUICtrlToolbar_GetButtonRect','GUICtrlToolbar_GetButtonRectEx',
+            'GUICtrlToolbar_GetButtonSize','GUICtrlToolbar_GetButtonState',
+            'GUICtrlToolbar_GetButtonStyle','GUICtrlToolbar_GetButtonText',
+            'GUICtrlToolbar_GetColorScheme',
+            'GUICtrlToolbar_GetDisabledImageList',
+            'GUICtrlToolbar_GetExtendedStyle','GUICtrlToolbar_GetHotImageList',
+            'GUICtrlToolbar_GetHotItem','GUICtrlToolbar_GetImageList',
+            'GUICtrlToolbar_GetInsertMark','GUICtrlToolbar_GetInsertMarkColor',
+            'GUICtrlToolbar_GetMaxSize','GUICtrlToolbar_GetMetrics',
+            'GUICtrlToolbar_GetPadding','GUICtrlToolbar_GetRows',
+            'GUICtrlToolbar_GetString','GUICtrlToolbar_GetStyle',
+            'GUICtrlToolbar_GetStyleAltDrag',
+            'GUICtrlToolbar_GetStyleCustomErase','GUICtrlToolbar_GetStyleFlat',
+            'GUICtrlToolbar_GetStyleList','GUICtrlToolbar_GetStyleRegisterDrop',
+            'GUICtrlToolbar_GetStyleToolTips',
+            'GUICtrlToolbar_GetStyleTransparent',
+            'GUICtrlToolbar_GetStyleWrapable','GUICtrlToolbar_GetTextRows',
+            'GUICtrlToolbar_GetToolTips','GUICtrlToolbar_GetUnicodeFormat',
+            'GUICtrlToolbar_HideButton','GUICtrlToolbar_HighlightButton',
+            'GUICtrlToolbar_HitTest','GUICtrlToolbar_IndexToCommand',
+            'GUICtrlToolbar_InsertButton','GUICtrlToolbar_InsertMarkHitTest',
+            'GUICtrlToolbar_IsButtonChecked','GUICtrlToolbar_IsButtonEnabled',
+            'GUICtrlToolbar_IsButtonHidden',
+            'GUICtrlToolbar_IsButtonHighlighted',
+            'GUICtrlToolbar_IsButtonIndeterminate',
+            'GUICtrlToolbar_IsButtonPressed','GUICtrlToolbar_LoadBitmap',
+            'GUICtrlToolbar_LoadImages','GUICtrlToolbar_MapAccelerator',
+            'GUICtrlToolbar_MoveButton','GUICtrlToolbar_PressButton',
+            'GUICtrlToolbar_SetAnchorHighlight','GUICtrlToolbar_SetBitmapSize',
+            'GUICtrlToolbar_SetButtonBitMap','GUICtrlToolbar_SetButtonInfo',
+            'GUICtrlToolbar_SetButtonInfoEx','GUICtrlToolbar_SetButtonParam',
+            'GUICtrlToolbar_SetButtonSize','GUICtrlToolbar_SetButtonState',
+            'GUICtrlToolbar_SetButtonStyle','GUICtrlToolbar_SetButtonText',
+            'GUICtrlToolbar_SetButtonWidth','GUICtrlToolbar_SetCmdID',
+            'GUICtrlToolbar_SetColorScheme',
+            'GUICtrlToolbar_SetDisabledImageList',
+            'GUICtrlToolbar_SetDrawTextFlags','GUICtrlToolbar_SetExtendedStyle',
+            'GUICtrlToolbar_SetHotImageList','GUICtrlToolbar_SetHotItem',
+            'GUICtrlToolbar_SetImageList','GUICtrlToolbar_SetIndent',
+            'GUICtrlToolbar_SetIndeterminate','GUICtrlToolbar_SetInsertMark',
+            'GUICtrlToolbar_SetInsertMarkColor','GUICtrlToolbar_SetMaxTextRows',
+            'GUICtrlToolbar_SetMetrics','GUICtrlToolbar_SetPadding',
+            'GUICtrlToolbar_SetParent','GUICtrlToolbar_SetRows',
+            'GUICtrlToolbar_SetStyle','GUICtrlToolbar_SetStyleAltDrag',
+            'GUICtrlToolbar_SetStyleCustomErase','GUICtrlToolbar_SetStyleFlat',
+            'GUICtrlToolbar_SetStyleList','GUICtrlToolbar_SetStyleRegisterDrop',
+            'GUICtrlToolbar_SetStyleToolTips',
+            'GUICtrlToolbar_SetStyleTransparent',
+            'GUICtrlToolbar_SetStyleWrapable','GUICtrlToolbar_SetToolTips',
+            'GUICtrlToolbar_SetUnicodeFormat','GUICtrlToolbar_SetWindowTheme',
+            'GUICtrlTreeView_Add','GUICtrlTreeView_AddChild',
+            'GUICtrlTreeView_AddChildFirst','GUICtrlTreeView_AddFirst',
+            'GUICtrlTreeView_BeginUpdate','GUICtrlTreeView_ClickItem',
+            'GUICtrlTreeView_Create','GUICtrlTreeView_CreateDragImage',
+            'GUICtrlTreeView_CreateSolidBitMap','GUICtrlTreeView_Delete',
+            'GUICtrlTreeView_DeleteAll','GUICtrlTreeView_DeleteChildren',
+            'GUICtrlTreeView_Destroy','GUICtrlTreeView_DisplayRect',
+            'GUICtrlTreeView_DisplayRectEx','GUICtrlTreeView_EditText',
+            'GUICtrlTreeView_EndEdit','GUICtrlTreeView_EndUpdate',
+            'GUICtrlTreeView_EnsureVisible','GUICtrlTreeView_Expand',
+            'GUICtrlTreeView_ExpandedOnce','GUICtrlTreeView_FindItem',
+            'GUICtrlTreeView_FindItemEx','GUICtrlTreeView_GetBkColor',
+            'GUICtrlTreeView_GetBold','GUICtrlTreeView_GetChecked',
+            'GUICtrlTreeView_GetChildCount','GUICtrlTreeView_GetChildren',
+            'GUICtrlTreeView_GetCount','GUICtrlTreeView_GetCut',
+            'GUICtrlTreeView_GetDropTarget','GUICtrlTreeView_GetEditControl',
+            'GUICtrlTreeView_GetExpanded','GUICtrlTreeView_GetFirstChild',
+            'GUICtrlTreeView_GetFirstItem','GUICtrlTreeView_GetFirstVisible',
+            'GUICtrlTreeView_GetFocused','GUICtrlTreeView_GetHeight',
+            'GUICtrlTreeView_GetImageIndex',
+            'GUICtrlTreeView_GetImageListIconHandle',
+            'GUICtrlTreeView_GetIndent','GUICtrlTreeView_GetInsertMarkColor',
+            'GUICtrlTreeView_GetISearchString','GUICtrlTreeView_GetItemByIndex',
+            'GUICtrlTreeView_GetItemHandle','GUICtrlTreeView_GetItemParam',
+            'GUICtrlTreeView_GetLastChild','GUICtrlTreeView_GetLineColor',
+            'GUICtrlTreeView_GetNext','GUICtrlTreeView_GetNextChild',
+            'GUICtrlTreeView_GetNextSibling','GUICtrlTreeView_GetNextVisible',
+            'GUICtrlTreeView_GetNormalImageList',
+            'GUICtrlTreeView_GetParentHandle','GUICtrlTreeView_GetParentParam',
+            'GUICtrlTreeView_GetPrev','GUICtrlTreeView_GetPrevChild',
+            'GUICtrlTreeView_GetPrevSibling','GUICtrlTreeView_GetPrevVisible',
+            'GUICtrlTreeView_GetScrollTime','GUICtrlTreeView_GetSelected',
+            'GUICtrlTreeView_GetSelectedImageIndex',
+            'GUICtrlTreeView_GetSelection','GUICtrlTreeView_GetSiblingCount',
+            'GUICtrlTreeView_GetState','GUICtrlTreeView_GetStateImageIndex',
+            'GUICtrlTreeView_GetStateImageList','GUICtrlTreeView_GetText',
+            'GUICtrlTreeView_GetTextColor','GUICtrlTreeView_GetToolTips',
+            'GUICtrlTreeView_GetTree','GUICtrlTreeView_GetUnicodeFormat',
+            'GUICtrlTreeView_GetVisible','GUICtrlTreeView_GetVisibleCount',
+            'GUICtrlTreeView_HitTest','GUICtrlTreeView_HitTestEx',
+            'GUICtrlTreeView_HitTestItem','GUICtrlTreeView_Index',
+            'GUICtrlTreeView_InsertItem','GUICtrlTreeView_IsFirstItem',
+            'GUICtrlTreeView_IsParent','GUICtrlTreeView_Level',
+            'GUICtrlTreeView_SelectItem','GUICtrlTreeView_SelectItemByIndex',
+            'GUICtrlTreeView_SetBkColor','GUICtrlTreeView_SetBold',
+            'GUICtrlTreeView_SetChecked','GUICtrlTreeView_SetCheckedByIndex',
+            'GUICtrlTreeView_SetChildren','GUICtrlTreeView_SetCut',
+            'GUICtrlTreeView_SetDropTarget','GUICtrlTreeView_SetFocused',
+            'GUICtrlTreeView_SetHeight','GUICtrlTreeView_SetIcon',
+            'GUICtrlTreeView_SetImageIndex','GUICtrlTreeView_SetIndent',
+            'GUICtrlTreeView_SetInsertMark',
+            'GUICtrlTreeView_SetInsertMarkColor',
+            'GUICtrlTreeView_SetItemHeight','GUICtrlTreeView_SetItemParam',
+            'GUICtrlTreeView_SetLineColor','GUICtrlTreeView_SetNormalImageList',
+            'GUICtrlTreeView_SetScrollTime','GUICtrlTreeView_SetSelected',
+            'GUICtrlTreeView_SetSelectedImageIndex','GUICtrlTreeView_SetState',
+            'GUICtrlTreeView_SetStateImageIndex',
+            'GUICtrlTreeView_SetStateImageList','GUICtrlTreeView_SetText',
+            'GUICtrlTreeView_SetTextColor','GUICtrlTreeView_SetToolTips',
+            'GUICtrlTreeView_SetUnicodeFormat','GUICtrlTreeView_Sort',
+            'GUIImageList_Add','GUIImageList_AddBitmap','GUIImageList_AddIcon',
+            'GUIImageList_AddMasked','GUIImageList_BeginDrag',
+            'GUIImageList_Copy','GUIImageList_Create','GUIImageList_Destroy',
+            'GUIImageList_DestroyIcon','GUIImageList_DragEnter',
+            'GUIImageList_DragLeave','GUIImageList_DragMove',
+            'GUIImageList_Draw','GUIImageList_DrawEx','GUIImageList_Duplicate',
+            'GUIImageList_EndDrag','GUIImageList_GetBkColor',
+            'GUIImageList_GetIcon','GUIImageList_GetIconHeight',
+            'GUIImageList_GetIconSize','GUIImageList_GetIconSizeEx',
+            'GUIImageList_GetIconWidth','GUIImageList_GetImageCount',
+            'GUIImageList_GetImageInfoEx','GUIImageList_Remove',
+            'GUIImageList_ReplaceIcon','GUIImageList_SetBkColor',
+            'GUIImageList_SetIconSize','GUIImageList_SetImageCount',
+            'GUIImageList_Swap','GUIScrollBars_EnableScrollBar',
+            'GUIScrollBars_GetScrollBarInfoEx','GUIScrollBars_GetScrollBarRect',
+            'GUIScrollBars_GetScrollBarRGState',
+            'GUIScrollBars_GetScrollBarXYLineButton',
+            'GUIScrollBars_GetScrollBarXYThumbBottom',
+            'GUIScrollBars_GetScrollBarXYThumbTop',
+            'GUIScrollBars_GetScrollInfo','GUIScrollBars_GetScrollInfoEx',
+            'GUIScrollBars_GetScrollInfoMax','GUIScrollBars_GetScrollInfoMin',
+            'GUIScrollBars_GetScrollInfoPage','GUIScrollBars_GetScrollInfoPos',
+            'GUIScrollBars_GetScrollInfoTrackPos','GUIScrollBars_GetScrollPos',
+            'GUIScrollBars_GetScrollRange','GUIScrollBars_Init',
+            'GUIScrollBars_ScrollWindow','GUIScrollBars_SetScrollInfo',
+            'GUIScrollBars_SetScrollInfoMax','GUIScrollBars_SetScrollInfoMin',
+            'GUIScrollBars_SetScrollInfoPage','GUIScrollBars_SetScrollInfoPos',
+            'GUIScrollBars_SetScrollRange','GUIScrollBars_ShowScrollBar',
+            'GUIToolTip_Activate','GUIToolTip_AddTool','GUIToolTip_AdjustRect',
+            'GUIToolTip_BitsToTTF','GUIToolTip_Create','GUIToolTip_DelTool',
+            'GUIToolTip_Destroy','GUIToolTip_EnumTools',
+            'GUIToolTip_GetBubbleHeight','GUIToolTip_GetBubbleSize',
+            'GUIToolTip_GetBubbleWidth','GUIToolTip_GetCurrentTool',
+            'GUIToolTip_GetDelayTime','GUIToolTip_GetMargin',
+            'GUIToolTip_GetMarginEx','GUIToolTip_GetMaxTipWidth',
+            'GUIToolTip_GetText','GUIToolTip_GetTipBkColor',
+            'GUIToolTip_GetTipTextColor','GUIToolTip_GetTitleBitMap',
+            'GUIToolTip_GetTitleText','GUIToolTip_GetToolCount',
+            'GUIToolTip_GetToolInfo','GUIToolTip_HitTest',
+            'GUIToolTip_NewToolRect','GUIToolTip_Pop','GUIToolTip_PopUp',
+            'GUIToolTip_SetDelayTime','GUIToolTip_SetMargin',
+            'GUIToolTip_SetMaxTipWidth','GUIToolTip_SetTipBkColor',
+            'GUIToolTip_SetTipTextColor','GUIToolTip_SetTitle',
+            'GUIToolTip_SetToolInfo','GUIToolTip_SetWindowTheme',
+            'GUIToolTip_ToolExists','GUIToolTip_ToolToArray',
+            'GUIToolTip_TrackActivate','GUIToolTip_TrackPosition',
+            'GUIToolTip_TTFToBits','GUIToolTip_Update',
+            'GUIToolTip_UpdateTipText','HexToString','IE_Example',
+            'IE_Introduction','IE_VersionInfo','IEAction','IEAttach',
+            'IEBodyReadHTML','IEBodyReadText','IEBodyWriteHTML','IECreate',
+            'IECreateEmbedded','IEDocGetObj','IEDocInsertHTML',
+            'IEDocInsertText','IEDocReadHTML','IEDocWriteHTML',
+            'IEErrorHandlerDeRegister','IEErrorHandlerRegister','IEErrorNotify',
+            'IEFormElementCheckBoxSelect','IEFormElementGetCollection',
+            'IEFormElementGetObjByName','IEFormElementGetValue',
+            'IEFormElementOptionSelect','IEFormElementRadioSelect',
+            'IEFormElementSetValue','IEFormGetCollection','IEFormGetObjByName',
+            'IEFormImageClick','IEFormReset','IEFormSubmit',
+            'IEFrameGetCollection','IEFrameGetObjByName','IEGetObjById',
+            'IEGetObjByName','IEHeadInsertEventScript','IEImgClick',
+            'IEImgGetCollection','IEIsFrameSet','IELinkClickByIndex',
+            'IELinkClickByText','IELinkGetCollection','IELoadWait',
+            'IELoadWaitTimeout','IENavigate','IEPropertyGet','IEPropertySet',
+            'IEQuit','IETableGetCollection','IETableWriteToArray',
+            'IETagNameAllGetCollection','IETagNameGetCollection','Iif',
+            'INetExplorerCapable','INetGetSource','INetMail','INetSmtpMail',
+            'IsPressed','MathCheckDiv','Max','MemGlobalAlloc','MemGlobalFree',
+            'MemGlobalLock','MemGlobalSize','MemGlobalUnlock','MemMoveMemory',
+            'MemMsgBox','MemShowError','MemVirtualAlloc','MemVirtualAllocEx',
+            'MemVirtualFree','MemVirtualFreeEx','Min','MouseTrap',
+            'NamedPipes_CallNamedPipe','NamedPipes_ConnectNamedPipe',
+            'NamedPipes_CreateNamedPipe','NamedPipes_CreatePipe',
+            'NamedPipes_DisconnectNamedPipe',
+            'NamedPipes_GetNamedPipeHandleState','NamedPipes_GetNamedPipeInfo',
+            'NamedPipes_PeekNamedPipe','NamedPipes_SetNamedPipeHandleState',
+            'NamedPipes_TransactNamedPipe','NamedPipes_WaitNamedPipe',
+            'Net_Share_ConnectionEnum','Net_Share_FileClose',
+            'Net_Share_FileEnum','Net_Share_FileGetInfo','Net_Share_PermStr',
+            'Net_Share_ResourceStr','Net_Share_SessionDel',
+            'Net_Share_SessionEnum','Net_Share_SessionGetInfo',
+            'Net_Share_ShareAdd','Net_Share_ShareCheck','Net_Share_ShareDel',
+            'Net_Share_ShareEnum','Net_Share_ShareGetInfo',
+            'Net_Share_ShareSetInfo','Net_Share_StatisticsGetSvr',
+            'Net_Share_StatisticsGetWrk','Now','NowCalc','NowCalcDate',
+            'NowDate','NowTime','PathFull','PathMake','PathSplit',
+            'ProcessGetName','ProcessGetPriority','Radian',
+            'ReplaceStringInFile','RunDOS','ScreenCapture_Capture',
+            'ScreenCapture_CaptureWnd','ScreenCapture_SaveImage',
+            'ScreenCapture_SetBMPFormat','ScreenCapture_SetJPGQuality',
+            'ScreenCapture_SetTIFColorDepth','ScreenCapture_SetTIFCompression',
+            'Security__AdjustTokenPrivileges','Security__GetAccountSid',
+            'Security__GetLengthSid','Security__GetTokenInformation',
+            'Security__ImpersonateSelf','Security__IsValidSid',
+            'Security__LookupAccountName','Security__LookupAccountSid',
+            'Security__LookupPrivilegeValue','Security__OpenProcessToken',
+            'Security__OpenThreadToken','Security__OpenThreadTokenEx',
+            'Security__SetPrivilege','Security__SidToStringSid',
+            'Security__SidTypeStr','Security__StringSidToSid','SendMessage',
+            'SendMessageA','SetDate','SetTime','Singleton','SoundClose',
+            'SoundLength','SoundOpen','SoundPause','SoundPlay','SoundPos',
+            'SoundResume','SoundSeek','SoundStatus','SoundStop',
+            'SQLite_Changes','SQLite_Close','SQLite_Display2DResult',
+            'SQLite_Encode','SQLite_ErrCode','SQLite_ErrMsg','SQLite_Escape',
+            'SQLite_Exec','SQLite_FetchData','SQLite_FetchNames',
+            'SQLite_GetTable','SQLite_GetTable2d','SQLite_LastInsertRowID',
+            'SQLite_LibVersion','SQLite_Open','SQLite_Query',
+            'SQLite_QueryFinalize','SQLite_QueryReset','SQLite_QuerySingleRow',
+            'SQLite_SaveMode','SQLite_SetTimeout','SQLite_Shutdown',
+            'SQLite_SQLiteExe','SQLite_Startup','SQLite_TotalChanges',
+            'StringAddComma','StringBetween','StringEncrypt','StringInsert',
+            'StringProper','StringRepeat','StringReverse','StringSplit',
+            'StringToHex','TCPIpToName','TempFile','TicksToTime','Timer_Diff',
+            'Timer_GetTimerID','Timer_Init','Timer_KillAllTimers',
+            'Timer_KillTimer','Timer_SetTimer','TimeToTicks','VersionCompare',
+            'viClose','viExecCommand','viFindGpib','viGpibBusReset','viGTL',
+            'viOpen','viSetAttribute','viSetTimeout','WeekNumberISO',
+            'WinAPI_AttachConsole','WinAPI_AttachThreadInput','WinAPI_Beep',
+            'WinAPI_BitBlt','WinAPI_CallNextHookEx','WinAPI_Check',
+            'WinAPI_ClientToScreen','WinAPI_CloseHandle',
+            'WinAPI_CommDlgExtendedError','WinAPI_CopyIcon',
+            'WinAPI_CreateBitmap','WinAPI_CreateCompatibleBitmap',
+            'WinAPI_CreateCompatibleDC','WinAPI_CreateEvent',
+            'WinAPI_CreateFile','WinAPI_CreateFont','WinAPI_CreateFontIndirect',
+            'WinAPI_CreateProcess','WinAPI_CreateSolidBitmap',
+            'WinAPI_CreateSolidBrush','WinAPI_CreateWindowEx',
+            'WinAPI_DefWindowProc','WinAPI_DeleteDC','WinAPI_DeleteObject',
+            'WinAPI_DestroyIcon','WinAPI_DestroyWindow','WinAPI_DrawEdge',
+            'WinAPI_DrawFrameControl','WinAPI_DrawIcon','WinAPI_DrawIconEx',
+            'WinAPI_DrawText','WinAPI_EnableWindow','WinAPI_EnumDisplayDevices',
+            'WinAPI_EnumWindows','WinAPI_EnumWindowsPopup',
+            'WinAPI_EnumWindowsTop','WinAPI_ExpandEnvironmentStrings',
+            'WinAPI_ExtractIconEx','WinAPI_FatalAppExit','WinAPI_FillRect',
+            'WinAPI_FindExecutable','WinAPI_FindWindow','WinAPI_FlashWindow',
+            'WinAPI_FlashWindowEx','WinAPI_FloatToInt',
+            'WinAPI_FlushFileBuffers','WinAPI_FormatMessage','WinAPI_FrameRect',
+            'WinAPI_FreeLibrary','WinAPI_GetAncestor','WinAPI_GetAsyncKeyState',
+            'WinAPI_GetClassName','WinAPI_GetClientHeight',
+            'WinAPI_GetClientRect','WinAPI_GetClientWidth',
+            'WinAPI_GetCurrentProcess','WinAPI_GetCurrentProcessID',
+            'WinAPI_GetCurrentThread','WinAPI_GetCurrentThreadId',
+            'WinAPI_GetCursorInfo','WinAPI_GetDC','WinAPI_GetDesktopWindow',
+            'WinAPI_GetDeviceCaps','WinAPI_GetDIBits','WinAPI_GetDlgCtrlID',
+            'WinAPI_GetDlgItem','WinAPI_GetFileSizeEx','WinAPI_GetFocus',
+            'WinAPI_GetForegroundWindow','WinAPI_GetIconInfo',
+            'WinAPI_GetLastError','WinAPI_GetLastErrorMessage',
+            'WinAPI_GetModuleHandle','WinAPI_GetMousePos','WinAPI_GetMousePosX',
+            'WinAPI_GetMousePosY','WinAPI_GetObject','WinAPI_GetOpenFileName',
+            'WinAPI_GetOverlappedResult','WinAPI_GetParent',
+            'WinAPI_GetProcessAffinityMask','WinAPI_GetSaveFileName',
+            'WinAPI_GetStdHandle','WinAPI_GetStockObject','WinAPI_GetSysColor',
+            'WinAPI_GetSysColorBrush','WinAPI_GetSystemMetrics',
+            'WinAPI_GetTextExtentPoint32','WinAPI_GetWindow',
+            'WinAPI_GetWindowDC','WinAPI_GetWindowHeight',
+            'WinAPI_GetWindowLong','WinAPI_GetWindowRect',
+            'WinAPI_GetWindowText','WinAPI_GetWindowThreadProcessId',
+            'WinAPI_GetWindowWidth','WinAPI_GetXYFromPoint',
+            'WinAPI_GlobalMemStatus','WinAPI_GUIDFromString',
+            'WinAPI_GUIDFromStringEx','WinAPI_HiWord','WinAPI_InProcess',
+            'WinAPI_IntToFloat','WinAPI_InvalidateRect','WinAPI_IsClassName',
+            'WinAPI_IsWindow','WinAPI_IsWindowVisible','WinAPI_LoadBitmap',
+            'WinAPI_LoadImage','WinAPI_LoadLibrary','WinAPI_LoadLibraryEx',
+            'WinAPI_LoadShell32Icon','WinAPI_LoadString','WinAPI_LocalFree',
+            'WinAPI_LoWord','WinAPI_MakeDWord','WinAPI_MAKELANGID',
+            'WinAPI_MAKELCID','WinAPI_MakeLong','WinAPI_MessageBeep',
+            'WinAPI_Mouse_Event','WinAPI_MoveWindow','WinAPI_MsgBox',
+            'WinAPI_MulDiv','WinAPI_MultiByteToWideChar',
+            'WinAPI_MultiByteToWideCharEx','WinAPI_OpenProcess',
+            'WinAPI_PointFromRect','WinAPI_PostMessage','WinAPI_PrimaryLangId',
+            'WinAPI_PtInRect','WinAPI_ReadFile','WinAPI_ReadProcessMemory',
+            'WinAPI_RectIsEmpty','WinAPI_RedrawWindow',
+            'WinAPI_RegisterWindowMessage','WinAPI_ReleaseCapture',
+            'WinAPI_ReleaseDC','WinAPI_ScreenToClient','WinAPI_SelectObject',
+            'WinAPI_SetBkColor','WinAPI_SetCapture','WinAPI_SetCursor',
+            'WinAPI_SetDefaultPrinter','WinAPI_SetDIBits','WinAPI_SetEvent',
+            'WinAPI_SetFocus','WinAPI_SetFont','WinAPI_SetHandleInformation',
+            'WinAPI_SetLastError','WinAPI_SetParent',
+            'WinAPI_SetProcessAffinityMask','WinAPI_SetSysColors',
+            'WinAPI_SetTextColor','WinAPI_SetWindowLong','WinAPI_SetWindowPos',
+            'WinAPI_SetWindowsHookEx','WinAPI_SetWindowText',
+            'WinAPI_ShowCursor','WinAPI_ShowError','WinAPI_ShowMsg',
+            'WinAPI_ShowWindow','WinAPI_StringFromGUID','WinAPI_SubLangId',
+            'WinAPI_SystemParametersInfo','WinAPI_TwipsPerPixelX',
+            'WinAPI_TwipsPerPixelY','WinAPI_UnhookWindowsHookEx',
+            'WinAPI_UpdateLayeredWindow','WinAPI_UpdateWindow',
+            'WinAPI_ValidateClassName','WinAPI_WaitForInputIdle',
+            'WinAPI_WaitForMultipleObjects','WinAPI_WaitForSingleObject',
+            'WinAPI_WideCharToMultiByte','WinAPI_WindowFromPoint',
+            'WinAPI_WriteConsole','WinAPI_WriteFile',
+            'WinAPI_WriteProcessMemory','WinNet_AddConnection',
+            'WinNet_AddConnection2','WinNet_AddConnection3',
+            'WinNet_CancelConnection','WinNet_CancelConnection2',
+            'WinNet_CloseEnum','WinNet_ConnectionDialog',
+            'WinNet_ConnectionDialog1','WinNet_DisconnectDialog',
+            'WinNet_DisconnectDialog1','WinNet_EnumResource',
+            'WinNet_GetConnection','WinNet_GetConnectionPerformance',
+            'WinNet_GetLastError','WinNet_GetNetworkInformation',
+            'WinNet_GetProviderName','WinNet_GetResourceInformation',
+            'WinNet_GetResourceParent','WinNet_GetUniversalName',
+            'WinNet_GetUser','WinNet_OpenEnum','WinNet_RestoreConnection',
+            'WinNet_UseConnection','Word_VersionInfo','WordAttach','WordCreate',
+            'WordDocAdd','WordDocAddLink','WordDocAddPicture','WordDocClose',
+            'WordDocFindReplace','WordDocGetCollection',
+            'WordDocLinkGetCollection','WordDocOpen','WordDocPrint',
+            'WordDocPropertyGet','WordDocPropertySet','WordDocSave',
+            'WordDocSaveAs','WordErrorHandlerDeRegister',
+            'WordErrorHandlerRegister','WordErrorNotify','WordMacroRun',
+            'WordPropertyGet','WordPropertySet','WordQuit'
+            ),
+        5 => array(
+            'ce','comments-end','comments-start','cs','include','include-once',
+            'NoTrayIcon','RequireAdmin'
+            ),
+        6 => array(
+            'AutoIt3Wrapper_Au3Check_Parameters',
+            'AutoIt3Wrapper_Au3Check_Stop_OnWarning',
+            'AutoIt3Wrapper_Change2CUI','AutoIt3Wrapper_Compression',
+            'AutoIt3Wrapper_cvsWrapper_Parameters','AutoIt3Wrapper_Icon',
+            'AutoIt3Wrapper_Outfile','AutoIt3Wrapper_Outfile_Type',
+            'AutoIt3Wrapper_Plugin_Funcs','AutoIt3Wrapper_Res_Comment',
+            'AutoIt3Wrapper_Res_Description','AutoIt3Wrapper_Res_Field',
+            'AutoIt3Wrapper_Res_File_Add','AutoIt3Wrapper_Res_Fileversion',
+            'AutoIt3Wrapper_Res_FileVersion_AutoIncrement',
+            'AutoIt3Wrapper_Res_Icon_Add','AutoIt3Wrapper_Res_Language',
+            'AutoIt3Wrapper_Res_LegalCopyright',
+            'AutoIt3Wrapper_res_requestedExecutionLevel',
+            'AutoIt3Wrapper_Res_SaveSource','AutoIt3Wrapper_Run_After',
+            'AutoIt3Wrapper_Run_Au3check','AutoIt3Wrapper_Run_Before',
+            'AutoIt3Wrapper_Run_cvsWrapper','AutoIt3Wrapper_Run_Debug_Mode',
+            'AutoIt3Wrapper_Run_Obfuscator','AutoIt3Wrapper_Run_Tidy',
+            'AutoIt3Wrapper_Tidy_Stop_OnError','AutoIt3Wrapper_UseAnsi',
+            'AutoIt3Wrapper_UseUpx','AutoIt3Wrapper_UseX64',
+            'AutoIt3Wrapper_Version','EndRegion','forceref',
+            'Obfuscator_Ignore_Funcs','Obfuscator_Ignore_Variables',
+            'Obfuscator_Parameters','Region','Tidy_Parameters'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(',')','[',']',
+        '+','-','*','/','&','^',
+        '=','+=','-=','*=','/=','&=',
+        '==','<','<=','>','>=',
+        ',','.'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        5 => false,
+        6 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0000FF; font-weight: bold;',
+            2 => 'color: #800000; font-weight: bold;',
+            3 => 'color: #000080; font-style: italic; font-weight: bold;',
+            4 => 'color: #0080FF; font-style: italic; font-weight: bold;',
+            5 => 'color: #F000FF; font-style: italic;',
+            6 => 'color: #A00FF0; font-style: italic;'
+            ),
+        'COMMENTS' => array(
+            0 => 'font-style: italic; color: #009933;',
+            'MULTI' => 'font-style: italic; color: #669900;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => ''
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #FF0000; font-weight: bold;'
+            ),
+        'STRINGS' => array(
+            0 => 'font-weight: bold; color: #008080;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #AC00A9; font-style: italic; font-weight: bold;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #0000FF; font-style: italic; font-weight: bold;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #FF0000; font-weight: bold;'
+            ),
+        'REGEXPS' => array(
+            0 => 'font-weight: bold; color: #AA0000;'
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => 'http://www.autoitscript.com/autoit3/docs/keywords.htm',
+        2 => 'http://www.autoitscript.com/autoit3/docs/macros.htm',
+        3 => 'http://www.autoitscript.com/autoit3/docs/functions/{FNAME}.htm',
+        4 => '',
+        5 => '',
+        6 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        //Variables
+        0 => '[\\$%@]+[a-zA-Z_][a-zA-Z0-9_]*'
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_MAYBE,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        0 => true,
+        1 => true,
+        2 => true,
+        3 => true
+        ),
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            4 => array(
+                'DISALLOWED_BEFORE' => '(?<!\w)\_'
+            ),
+            5 => array(
+                'DISALLOWED_BEFORE' => '(?<!\w)\#'
+            ),
+            6 => array(
+                'DISALLOWED_BEFORE' => '(?<!\w)\#'
+            )
+        )
+    )
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/avisynth.php b/examples/includes/geshi/geshi/avisynth.php
new file mode 100644 (file)
index 0000000..a3f60d0
--- /dev/null
@@ -0,0 +1,194 @@
+<?php
+/*************************************************************************************
+ * avisynth.php
+ * --------
+ * Author: Ryan Jones (sciguyryan@gmail.com)
+ * Copyright: (c) 2008 Ryan Jones
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/10/08
+ *
+ * AviSynth language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/10/08 (1.0.8.1)
+ *  -  First Release
+ *
+ * TODO (updated 2008/10/08)
+ * -------------------------
+ * * There are also some special words that can't currently be specified directly in GeSHi as they may
+ *      also be used as variables which would really mess things up.
+ * * Also there is an issue with the escape character as this language uses a muti-character escape system. Escape char should be """ but has been left
+ *      as empty due to this restiction.
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'AviSynth',
+    'COMMENT_SINGLE' => array(1 => '#'),
+    'COMMENT_MULTI' => array('/*' => '*/', '[*' => '*]'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        //  Reserved words.
+        1 => array(
+            'try', 'cache', 'function', 'global', 'return'
+            ),
+        // Constants / special variables.
+        2 => array(
+            'true', 'yes', 'false', 'no', '__END__'
+            ),
+        // Internal Filters.
+        3 => array(
+            'AviSource', 'AviFileSource', 'AddBorders', 'AlignedSplice', 'AssumeFPS', 'AssumeScaledFPS',
+            'AssumeFrameBased', 'AssumeFieldBased', 'AssumeBFF', 'AssumeTFF', 'Amplify', 'AmplifydB',
+            'AssumeSampleRate', 'AudioDub', 'AudioDubEx', 'Animate', 'ApplyRange',
+            'BicubicResize', 'BilinearResize', 'BlackmanResize', 'Blur', 'Bob', 'BlankClip', 'Blackness',
+            'ColorYUV', 'ConvertBackToYUY2', 'ConvertToRGB', 'ConvertToRGB24', 'ConvertToRGB32',
+            'ConvertToYUY2', 'ConvertToY8', 'ConvertToYV411', 'ConvertToYV12', 'ConvertToYV16', 'ConvertToYV24',
+            'ColorKeyMask', 'Crop', 'CropBottom', 'ChangeFPS', 'ConvertFPS', 'ComplementParity', 'ConvertAudioTo8bit',
+            'ConvertAudioTo16bit', 'ConvertAudioTo24bit', 'ConvertAudioTo32bit', 'ConvertAudioToFloat', 'ConvertToMono',
+            'ConditionalFilter', 'ConditionalReader', 'ColorBars', 'Compare',
+            'DirectShowSource', 'DeleteFrame', 'Dissolve', 'DuplicateFrame', 'DoubleWeave', 'DelayAudio',
+            'EnsureVBRMP3Sync',
+            'FixLuminance', 'FlipHorizontal', 'FlipVertical', 'FixBrokenChromaUpsampling', 'FadeIn0', 'FadeIn',
+            'FadeIn2', 'FadeOut0', 'FadeOut', 'FadeOut2', 'FadeIO0', 'FadeIO', 'FadeIO2', 'FreezeFrame', 'FrameEvaluate',
+            'GreyScale', 'GaussResize', 'GeneralConvolution', 'GetChannel', 'GetLeftChannel', 'GetRightChannel',
+            'HorizontalReduceBy2', 'Histogram',
+            'ImageReader', 'ImageSource', 'ImageWriter', 'Invert', 'Interleave', 'Info',
+            'KillAudio', 'KillVideo',
+            'Levels', 'Limiter', 'Layer', 'Letterbox', 'LanczosResize', 'Lanczos4Resize', 'Loop',
+            'MergeARGB', 'MergeRGB', 'MergeChroma', 'MergeLuma', 'Merge', 'Mask', 'MaskHS', 'MergeChannels', 'MixAudio',
+            'MonoToStereo', 'MessageClip',
+            'Normalize',
+            'OpenDMLSource', 'Overlay',
+            'PointResize', 'PeculiarBlend', 'Pulldown',
+            'RGBAdjust', 'ResetMask', 'Reverse', 'ResampleAudio', 'ReduceBy2',
+            'SegmentedAviSource', 'SegmentedDirectShowSource', 'SoundOut', 'ShowAlpha', 'ShowRed', 'ShowGreen',
+            'ShowBlue', 'SwapUV', 'Subtract', 'SincResize', 'Spline16Resize', 'Spline36Resize', 'Spline64Resize',
+            'SelectEven', 'SelectOdd', 'SelectEvery', 'SelectRangeEvery', 'Sharpen', 'SpatialSoften', 'SeparateFields',
+            'ShowFiveVersions', 'ShowFrameNumber', 'ShowSMPTE', 'ShowTime', 'StackHorizontal', 'StackVertical', 'Subtitle',
+            'SwapFields', 'SuperEQ', 'SSRC', 'ScriptClip',
+            'Tweak', 'TurnLeft', 'TurnRight', 'Turn180', 'TemporalSoften', 'TimeStretch', 'TCPServer', 'TCPSource', 'Trim',
+            'Tone',
+            'UToY', 'UToY8', 'UnalignedSplice',
+            'VToY', 'VToY8', 'VerticalReduceBy2', 'Version',
+            'WavSource', 'Weave', 'WriteFile', 'WriteFileIf', 'WriteFileStart', 'WriteFileEnd',
+            'YToUV'
+            ),
+        // Internal functions.
+        4 => array(
+            'Abs', 'Apply', 'Assert', 'AverageLuma', 'AverageChromaU', 'AverageChromaV',
+            'Ceil', 'Cos', 'Chr', 'ChromaUDifference', 'ChromaVDifference',
+            'Defined', 'Default',
+            'Exp', 'Exist', 'Eval',
+            'Floor', 'Frac', 'Float', 'Findstr', 'GetMTMode',
+            'HexValue',
+            'Int', 'IsBool', 'IsClip', 'IsFloat', 'IsInt', 'IsString', 'Import',
+            'LoadPlugin', 'Log', 'LCase', 'LeftStr', 'LumaDifference', 'LoadVirtualDubPlugin', 'LoadVFAPIPlugin',
+            'LoadCPlugin', 'Load_Stdcall_Plugin',
+            'Max', 'MulDiv', 'MidStr',
+            'NOP',
+            'OPT_AllowFloatAudio', 'OPT_UseWaveExtensible',
+            'Pi', 'Pow',
+            'Round', 'Rand', 'RevStr', 'RightStr', 'RGBDifference', 'RGBDifferenceFromPrevious', 'RGBDifferenceToNext',
+            'Sin', 'Sqrt', 'Sign', 'Spline', 'StrLen', 'String', 'Select', 'SetMemoryMax', 'SetWorkingDir', 'SetMTMode',
+            'SetPlanarLegacyAlignment',
+            'Time',
+            'UCase', 'UDifferenceFromPrevious', 'UDifferenceToNext', 'UPlaneMax', 'UPlaneMin', 'UPlaneMedian',
+            'UPlaneMinMaxDifference',
+            'Value', 'VersionNumber', 'VersionString', 'VDifferenceFromPrevious', 'VDifferenceToNext', 'VPlaneMax',
+            'VPlaneMin', 'VPlaneMedian', 'VPlaneMinMaxDifference',
+            'YDifferenceFromPrevious', 'YDifferenceToNext', 'YPlaneMax', 'YPlaneMin', 'YPlaneMedian',
+            'YPlaneMinMaxDifference'
+            )
+        ),
+    'SYMBOLS' => array(
+        '+', '++', '-', '--', '/', '*', '%',
+        '=', '==', '<', '<=', '>', '>=', '<>', '!=',
+        '!', '?', ':',
+        '|', '||', '&&',
+        '\\',
+        '(', ')', '{', '}',
+        '.', ','
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => true,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color:#9966CC; font-weight:bold;',
+            2 => 'color:#0000FF; font-weight:bold;',
+            3 => 'color:#CC3300; font-weight:bold;',
+            4 => 'color:#660000; font-weight:bold;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color:#008000; font-style:italic;',
+            'MULTI' => 'color:#000080; font-style:italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color:#000099;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color:#006600; font-weight:bold;'
+            ),
+        'STRINGS' => array(
+            0 => 'color:#996600;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color:#006666;'
+            ),
+        'METHODS' => array(
+            1 => 'color:#9900CC;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color:#006600; font-weight:bold;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => 'http://avisynth.org/mediawiki/{FNAME}',
+        4 => ''
+        ),
+    'REGEXPS' => array(
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_MAYBE,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4
+);
+?>
diff --git a/examples/includes/geshi/geshi/bash.php b/examples/includes/geshi/geshi/bash.php
new file mode 100644 (file)
index 0000000..b41f895
--- /dev/null
@@ -0,0 +1,282 @@
+<?php
+/*************************************************************************************
+ * bash.php
+ * --------
+ * Author: Andreas Gohr (andi@splitbrain.org)
+ * Copyright: (c) 2004 Andreas Gohr, Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/08/20
+ *
+ * BASH language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/06/21 (1.0.8)
+ *  -  Added loads of keywords and commands of GNU/Linux
+ *  -  Added support for parameters starting with a dash
+ * 2008/05/23 (1.0.7.22)
+ *  -  Added description of extra language features (SF#1970248)
+ * 2007/09/05 (1.0.7.21)
+ *  -  PARSER_CONTROL patch using SF #1788408 (BenBE)
+ * 2007/06/11 (1.0.7.20)
+ *  -  Added a lot of keywords (BenBE / Jan G)
+ * 2004/11/27 (1.0.2)
+ *  -  Added support for multiple object splitters
+ * 2004/10/27 (1.0.1)
+ *   -  Added support for URLs
+ * 2004/08/20 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ * * Get symbols working
+ * * Highlight builtin vars
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Bash',
+    // Bash DOES have single line comments with # markers. But bash also has
+    // the  $# variable, so comments need special handling (see sf.net
+    // 1564839)
+    'COMMENT_SINGLE' => array('#'),
+    'COMMENT_MULTI' => array(),
+    'COMMENT_REGEXP' => array(
+        //Variables
+        1 => "/\\$\\{[^\\n\\}]*?\\}/i",
+        //BASH-style Heredoc
+        2 => '/<<-?\s*?(\'?)([a-zA-Z0-9]+)\1\\n.*\\n\\2(?![a-zA-Z0-9])/siU',
+        //Escaped String Starters
+        3 => "/\\\\['\"]/siU"
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'HARDQUOTE' => array("'", "'"),
+    'HARDESCAPE' => array("\'"),
+    'ESCAPE_CHAR' => '',
+    'ESCAPE_REGEXP' => array(
+        //Simple Single Char Escapes
+        1 => "#\\\\[nfrtv\\$\\\"\n]#i",
+        // $var
+        2 => "#\\$[a-z_][a-z0-9_]*#i",
+        // ${...}
+        3 => "/\\$\\{[^\\n\\}]*?\\}/i",
+        // $(...)
+        4 => "/\\$\\([^\\n\\)]*?\\)/i",
+        // `...`
+        5 => "/`[^`]*`/"
+        ),
+    'KEYWORDS' => array(
+        1 => array(
+            'case', 'do', 'done', 'elif', 'else', 'esac', 'fi', 'for', 'function',
+            'if', 'in', 'select', 'set', 'then', 'until', 'while', 'time'
+            ),
+        2 => array(
+            'aclocal', 'aconnect', 'aplay', 'apm', 'apmsleep', 'apropos',
+            'apt-cache', 'apt-get', 'apt-key', 'aptitude',
+            'ar', 'arch', 'arecord', 'as', 'as86', 'ash', 'autoconf',
+            'autoheader', 'automake', 'awk',
+
+            'basename', 'bash', 'bc', 'bison', 'bunzip2', 'bzcat',
+            'bzcmp', 'bzdiff', 'bzegrep', 'bzfgrep', 'bzgrep',
+            'bzip2', 'bzip2recover', 'bzless', 'bzmore',
+
+            'c++', 'cal', 'cat', 'chattr', 'cc', 'cdda2wav', 'cdparanoia',
+            'cdrdao', 'cd-read', 'cdrecord', 'chfn', 'chgrp', 'chmod',
+            'chown', 'chroot', 'chsh', 'chvt', 'clear', 'cmp', 'comm', 'co',
+            'col', 'cp', 'cpio', 'cpp', 'csh', 'cut', 'cvs', 'cvs-pserver',
+
+            'dash', 'date', 'dd', 'dc', 'dcop', 'deallocvt', 'df', 'dialog',
+            'diff', 'diff3', 'dir', 'dircolors', 'directomatic', 'dirname',
+            'dmesg', 'dnsdomainname', 'domainname', 'dpkg', 'dselect', 'du',
+            'dumpkeys',
+
+            'ed', 'egrep', 'env', 'expr',
+
+            'false', 'fbset', 'ffmpeg', 'fgconsole','fgrep', 'file', 'find',
+            'flex', 'flex++', 'fmt', 'free', 'ftp', 'funzip', 'fuser',
+
+            'g++', 'gawk', 'gc','gcc', 'gdb', 'getent', 'getkeycodes',
+            'getopt', 'gettext', 'gettextize', 'gimp', 'gimp-remote',
+            'gimptool', 'gmake', 'gocr', 'grep', 'groups', 'gs', 'gunzip',
+            'gzexe', 'gzip',
+
+            'head', 'hexdump', 'hostname',
+
+            'id', 'ifconfig', 'igawk', 'install',
+
+            'join',
+
+            'kbd_mode','kbdrate', 'kdialog', 'kfile', 'kill', 'killall',
+
+            'lame', 'last', 'lastb', 'ld', 'ld86', 'ldd', 'less', 'lex', 'link',
+            'ln', 'loadkeys', 'loadunimap', 'locate', 'lockfile', 'login',
+            'logname', 'lp', 'lpr', 'ls', 'lsattr', 'lsmod', 'lsmod.old',
+            'lspci', 'ltrace', 'lynx',
+
+            'm4', 'make', 'man', 'mapscrn', 'mesg', 'mkdir', 'mkfifo',
+            'mknod', 'mktemp', 'more', 'mount', 'mplayer', 'msgfmt', 'mv',
+
+            'namei', 'nano', 'nasm', 'nawk', 'netstat', 'nice',
+            'nisdomainname', 'nl', 'nm', 'nm86', 'nmap', 'nohup', 'nop',
+
+            'od', 'openvt',
+
+            'passwd', 'patch', 'pcregrep', 'pcretest', 'perl', 'perror',
+            'pgawk', 'pidof', 'ping', 'pr', 'procmail', 'prune', 'ps', 'pstree',
+            'ps2ascii', 'ps2epsi', 'ps2frag', 'ps2pdf', 'ps2ps', 'psbook',
+            'psmerge', 'psnup', 'psresize', 'psselect', 'pstops',
+
+            'rbash', 'rcs', 'rcs2log', 'read', 'readlink', 'red', 'resizecons',
+            'rev', 'rm', 'rmdir', 'rsh', 'run-parts',
+
+            'sash', 'scp', 'screen', 'sed', 'seq', 'sendmail', 'setfont',
+            'setkeycodes', 'setleds', 'setmetamode', 'setserial', 'setterm',
+            'sh', 'showkey', 'shred', 'size', 'size86', 'skill', 'sleep',
+            'slogin', 'snice', 'sort', 'sox', 'split', 'ssed', 'ssh', 'ssh-add',
+            'ssh-agent', 'ssh-keygen', 'ssh-keyscan', 'stat', 'strace',
+            'strings', 'strip', 'stty', 'su', 'sudo', 'suidperl', 'sum', 'svn',
+            'svnadmin', 'svndumpfilter', 'svnlook', 'svnmerge', 'svnmucc',
+            'svnserve', 'svnshell', 'svnsync', 'svnversion', 'svnwrap', 'sync',
+
+            'tac', 'tail', 'tar', 'tee', 'tempfile', 'touch', 'tr', 'tree',
+            'true',
+
+            'umount', 'uname', 'unicode_start', 'unicode_stop', 'uniq',
+            'unlink', 'unzip', 'updatedb', 'updmap', 'uptime', 'users',
+            'utmpdump', 'uuidgen',
+
+            'valgrind', 'vdir', 'vi', 'vim', 'vmstat',
+
+            'w', 'wall', 'wc', 'wget', 'whatis', 'whereis', 'which', 'whiptail',
+            'who', 'whoami', 'write',
+
+            'xargs', 'xhost', 'xmodmap', 'xset',
+
+            'yacc', 'yes', 'ypdomainname',
+
+            'zcat', 'zcmp', 'zdiff', 'zdump', 'zegrep', 'zfgrep', 'zforce',
+            'zgrep', 'zip', 'zipgrep', 'zipinfo', 'zless', 'zmore', 'znew',
+            'zsh', 'zsoelim'
+            ),
+        3 => array(
+            'alias', 'bg', 'bind', 'break', 'builtin', 'cd', 'command',
+            'compgen', 'complete', 'continue', 'declare', 'dirs', 'disown',
+            'echo', 'enable', 'eval', 'exec', 'exit', 'export', 'fc',
+            'fg', 'getopts', 'hash', 'help', 'history', 'jobs', 'let',
+            'local', 'logout', 'popd', 'printf', 'pushd', 'pwd', 'readonly',
+            'return', 'shift', 'shopt', 'source', 'suspend', 'test', 'times',
+            'trap', 'type', 'typeset', 'ulimit', 'umask', 'unalias', 'unset',
+            'wait'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '!', '@', '%', '&', '*', '|', '/', '<', '>', ';;', '`'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000000; font-weight: bold;',
+            2 => 'color: #c20cb9; font-weight: bold;',
+            3 => 'color: #7a0874; font-weight: bold;'
+            ),
+        'COMMENTS' => array(
+            0 => 'color: #666666; font-style: italic;',
+            1 => 'color: #800000;',
+            2 => 'color: #cc0000; font-style: italic;',
+            3 => 'color: #000000; font-weight: bold;'
+            ),
+        'ESCAPE_CHAR' => array(
+            1 => 'color: #000099; font-weight: bold;',
+            2 => 'color: #007800;',
+            3 => 'color: #007800;',
+            4 => 'color: #007800;',
+            5 => 'color: #780078;',
+            'HARD' => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #7a0874; font-weight: bold;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;',
+            'HARD' => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #000000;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000000; font-weight: bold;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #007800;',
+            1 => 'color: #007800;',
+            2 => 'color: #007800;',
+            4 => 'color: #007800;',
+            5 => 'color: #660033;'
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        //Variables (will be handled by comment_regexps)
+        0 => "\\$\\{[a-zA-Z_][a-zA-Z0-9_]*?\\}",
+        //Variables without braces
+        1 => "\\$[a-zA-Z_][a-zA-Z0-9_]*",
+        //Variable assignment
+        2 => "(?<![\.a-zA-Z_\-])([a-zA-Z_][a-zA-Z0-9_]*?)(?==)",
+        //Shorthand shell variables
+        4 => "\\$[*#\$\\-\\?!]",
+        //Parameters of commands
+        5 => "(?<=\s)--?[0-9a-zA-Z\-]+(?=[\s=]|$)"
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4,
+    'PARSER_CONTROL' => array(
+        'COMMENTS' => array(
+            'DISALLOWED_BEFORE' => '$'
+        ),
+        'KEYWORDS' => array(
+            'DISALLOWED_BEFORE' => "(?<![\.\-a-zA-Z0-9_\$\#])",
+            'DISALLOWED_AFTER' =>  "(?![\.\-a-zA-Z0-9_%\\/])"
+        )
+    )
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/basic4gl.php b/examples/includes/geshi/geshi/basic4gl.php
new file mode 100644 (file)
index 0000000..a7b00b9
--- /dev/null
@@ -0,0 +1,341 @@
+<?php
+/*************************************************************************************
+ * basic4gl.php
+ * ---------------------------------
+ * Author: Matthew Webb (bmatthew1@blueyonder.co.uk)
+ * Copyright: (c) 2004 Matthew Webb (http://matthew-4gl.wikispaces.com)
+ * Release Version: 1.0.8.3
+ * Date Started: 2007/09/15
+ *
+ * Basic4GL language file for GeSHi.
+ *
+ * You can find the Basic4GL Website at (http://www.basic4gl.net/)
+ *
+ * CHANGES
+ * -------
+ * 2007/09/17 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2007/09/17)
+ * -------------------------
+ * Make sure all the OpenGL and Basic4GL commands have been added and are complete.
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Basic4GL',
+    'COMMENT_SINGLE' => array(1 => "'"),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+
+            // Navy Blue Bold Keywords
+
+            'true','rnd_max','m_pi','m_e','false','VK_ZOOM','VK_UP','VK_TAB','VK_SUBTRACT','VK_SPACE','VK_SNAPSHOT',
+            'VK_SHIFT','VK_SEPARATOR','VK_SELECT','VK_SCROLL','VK_RWIN','VK_RSHIFT','VK_RMENU','VK_RIGHT','VK_RETURN',
+            'VK_RCONTROL','VK_RBUTTON','VK_PROCESSKEY','VK_PRIOR','VK_PRINT','VK_PLAY','VK_PAUSE','VK_NUMPAD9','VK_NUMPAD8',
+            'VK_NUMPAD7','VK_NUMPAD6','VK_NUMPAD5','VK_NUMPAD4','VK_NUMPAD3','VK_NUMPAD2','VK_NUMPAD1','VK_NUMPAD0',
+            'VK_NUMLOCK','VK_NONCONVERT','VK_NEXT','VK_MULTIPLY','VK_MODECHANGE','VK_MENU','VK_MBUTTON','VK_LWIN',
+            'VK_LSHIFT','VK_LMENU','VK_LEFT','VK_LCONTROL','VK_LBUTTON','VK_KANJI','VK_KANA','VK_JUNJA','VK_INSERT',
+            'VK_HOME','VK_HELP','VK_HANJA','VK_HANGUL','VK_HANGEUL','VK_FINAL','VK_F9','VK_F8','VK_F7','VK_F6','VK_F5',
+            'VK_F4','VK_F3','VK_F24','VK_F23','VK_F22','VK_F21','VK_F20','VK_F2','VK_F19','VK_F18','VK_F17','VK_F16',
+            'VK_F15','VK_F14','VK_F13','VK_F12','VK_F11','VK_F10','VK_F1','VK_EXSEL','VK_EXECUTE','VK_ESCAPE','VK_EREOF',
+            'VK_END','VK_DOWN','VK_DIVIDE','VK_DELETE','VK_DECIMAL','VK_CRSEL','VK_CONVERT','VK_CONTROL','VK_CLEAR',
+            'VK_CAPITAL','VK_CANCEL','VK_BACK','VK_ATTN','VK_APPS','VK_ADD','VK_ACCEPT','TEXT_SIMPLE','TEXT_OVERLAID',
+            'TEXT_BUFFERED','SPR_TILEMAP','SPR_SPRITE','SPR_INVALID','MOUSE_RBUTTON','MOUSE_MBUTTON','MOUSE_LBUTTON',
+            'GL_ZOOM_Y','GL_ZOOM_X','GL_ZERO','GL_XOR','GL_WIN_swap_hint','GL_WIN_draw_range_elements','GL_VIEWPORT_BIT',
+            'GL_VIEWPORT','GL_VERTEX_ARRAY_TYPE_EXT','GL_VERTEX_ARRAY_TYPE','GL_VERTEX_ARRAY_STRIDE_EXT','GL_VERTEX_ARRAY_STRIDE',
+            'GL_VERTEX_ARRAY_SIZE_EXT','GL_VERTEX_ARRAY_SIZE','GL_VERTEX_ARRAY_POINTER_EXT','GL_VERTEX_ARRAY_POINTER',
+            'GL_VERTEX_ARRAY_EXT','GL_VERTEX_ARRAY_COUNT_EXT','GL_VERTEX_ARRAY','GL_VERSION_1_1','GL_VERSION','GL_VENDOR',
+            'GL_V3F','GL_V2F','GL_UNSIGNED_SHORT','GL_UNSIGNED_INT','GL_UNSIGNED_BYTE','GL_UNPACK_SWAP_BYTES','GL_UNPACK_SKIP_ROWS',
+            'GL_UNPACK_SKIP_PIXELS','GL_UNPACK_ROW_LENGTH','GL_UNPACK_LSB_FIRST','GL_UNPACK_ALIGNMENT','GL_TRUE','GL_TRIANGLE_STRIP',
+            'GL_TRIANGLE_FAN','GL_TRIANGLES','GL_TRANSFORM_BIT','GL_TEXTURE_WRAP_T','GL_TEXTURE_WRAP_S','GL_TEXTURE_WIDTH',
+            'GL_TEXTURE_STACK_DEPTH','GL_TEXTURE_RESIDENT','GL_TEXTURE_RED_SIZE','GL_TEXTURE_PRIORITY','GL_TEXTURE_MIN_FILTER',
+            'GL_TEXTURE_MATRIX','GL_TEXTURE_MAG_FILTER','GL_TEXTURE_LUMINANCE_SIZE','GL_TEXTURE_INTERNAL_FORMAT','GL_TEXTURE_INTENSITY_SIZE',
+            'GL_TEXTURE_HEIGHT','GL_TEXTURE_GREEN_SIZE','GL_TEXTURE_GEN_T','GL_TEXTURE_GEN_S','GL_TEXTURE_GEN_R','GL_TEXTURE_GEN_Q',
+            'GL_TEXTURE_GEN_MODE','GL_TEXTURE_ENV_MODE','GL_TEXTURE_ENV_COLOR','GL_TEXTURE_ENV','GL_TEXTURE_COORD_ARRAY_TYPE_EXT',
+            'GL_TEXTURE_COORD_ARRAY_TYPE','GL_TEXTURE_COORD_ARRAY_STRIDE_EXT','GL_TEXTURE_COORD_ARRAY_STRIDE','GL_TEXTURE_COORD_ARRAY_SIZE_EXT',
+            'GL_TEXTURE_COORD_ARRAY_SIZE','GL_TEXTURE_COORD_ARRAY_POINTER_EXT','GL_TEXTURE_COORD_ARRAY_POINTER','GL_TEXTURE_COORD_ARRAY_EXT',
+            'GL_TEXTURE_COORD_ARRAY_COUNT_EXT','GL_TEXTURE_COORD_ARRAY','GL_TEXTURE_COMPONENTS','GL_TEXTURE_BORDER_COLOR','GL_TEXTURE_BORDER',
+            'GL_TEXTURE_BLUE_SIZE','GL_TEXTURE_BIT','GL_TEXTURE_BINDING_2D','GL_TEXTURE_BINDING_1D','GL_TEXTURE_ALPHA_SIZE',
+            'GL_TEXTURE_2D','GL_TEXTURE_1D','GL_TEXTURE9_ARB','GL_TEXTURE9','GL_TEXTURE8_ARB','GL_TEXTURE8','GL_TEXTURE7_ARB',
+            'GL_TEXTURE7','GL_TEXTURE6_ARB','GL_TEXTURE6','GL_TEXTURE5_ARB','GL_TEXTURE5','GL_TEXTURE4_ARB','GL_TEXTURE4',
+            'GL_TEXTURE3_ARB','GL_TEXTURE31_ARB','GL_TEXTURE31','GL_TEXTURE30_ARB','GL_TEXTURE30','GL_TEXTURE3','GL_TEXTURE2_ARB',
+            'GL_TEXTURE29_ARB','GL_TEXTURE29','GL_TEXTURE28_ARB','GL_TEXTURE28','GL_TEXTURE27_ARB','GL_TEXTURE27','GL_TEXTURE26_ARB',
+            'GL_TEXTURE26','GL_TEXTURE25_ARB','GL_TEXTURE25','GL_TEXTURE24_ARB','GL_TEXTURE24','GL_TEXTURE23_ARB','GL_TEXTURE23',
+            'GL_TEXTURE22_ARB','GL_TEXTURE22','GL_TEXTURE21_ARB','GL_TEXTURE21','GL_TEXTURE20_ARB','GL_TEXTURE20','GL_TEXTURE2',
+            'GL_TEXTURE1_ARB','GL_TEXTURE19_ARB','GL_TEXTURE19','GL_TEXTURE18_ARB','GL_TEXTURE18','GL_TEXTURE17_ARB',
+            'GL_TEXTURE17','GL_TEXTURE16_ARB','GL_TEXTURE16','GL_TEXTURE15_ARB','GL_TEXTURE15','GL_TEXTURE14_ARB','GL_TEXTURE14',
+            'GL_TEXTURE13_ARB','GL_TEXTURE13','GL_TEXTURE12_ARB','GL_TEXTURE12','GL_TEXTURE11_ARB','GL_TEXTURE11','GL_TEXTURE10_ARB',
+            'GL_TEXTURE10','GL_TEXTURE1','GL_TEXTURE0_ARB','GL_TEXTURE0','GL_TEXTURE','GL_T4F_V4F','GL_T4F_C4F_N3F_V4F','GL_T2F_V3F',
+            'GL_T2F_N3F_V3F','GL_T2F_C4UB_V3F','GL_T2F_C4F_N3F_V3F','GL_T2F_C3F_V3F','GL_T','GL_SUBPIXEL_BITS','GL_STEREO',
+            'GL_STENCIL_WRITEMASK','GL_STENCIL_VALUE_MASK','GL_STENCIL_TEST','GL_STENCIL_REF','GL_STENCIL_PASS_DEPTH_PASS',
+            'GL_STENCIL_PASS_DEPTH_FAIL','GL_STENCIL_INDEX','GL_STENCIL_FUNC','GL_STENCIL_FAIL','GL_STENCIL_CLEAR_VALUE',
+            'GL_STENCIL_BUFFER_BIT','GL_STENCIL_BITS','GL_STENCIL','GL_STACK_UNDERFLOW','GL_STACK_OVERFLOW','GL_SRC_COLOR',
+            'GL_SRC_ALPHA_SATURATE','GL_SRC_ALPHA','GL_SPOT_EXPONENT','GL_SPOT_DIRECTION','GL_SPOT_CUTOFF','GL_SPHERE_MAP',
+            'GL_SPECULAR','GL_SOURCE2_RGB_EXT','GL_SOURCE2_RGB','GL_SOURCE2_ALPHA_EXT','GL_SOURCE2_ALPHA','GL_SOURCE1_RGB_EXT',
+            'GL_SOURCE1_RGB','GL_SOURCE1_ALPHA_EXT','GL_SOURCE1_ALPHA','GL_SOURCE0_RGB_EXT','GL_SOURCE0_RGB','GL_SOURCE0_ALPHA_EXT',
+            'GL_SOURCE0_ALPHA','GL_SMOOTH','GL_SHORT','GL_SHININESS','GL_SHADE_MODEL','GL_SET','GL_SELECTION_BUFFER_SIZE',
+            'GL_SELECTION_BUFFER_POINTER','GL_SELECT','GL_SCISSOR_TEST','GL_SCISSOR_BOX','GL_SCISSOR_BIT','GL_S','GL_RIGHT',
+            'GL_RGB_SCALE_EXT','GL_RGB_SCALE','GL_RGBA_MODE','GL_RGBA8','GL_RGBA4','GL_RGBA2','GL_RGBA16','GL_RGBA12','GL_RGBA',
+            'GL_RGB8','GL_RGB5_A1','GL_RGB5','GL_RGB4','GL_RGB16','GL_RGB12','GL_RGB10_A2','GL_RGB10','GL_RGB','GL_RETURN',
+            'GL_REPLACE','GL_REPEAT','GL_RENDER_MODE','GL_RENDERER','GL_RENDER','GL_RED_SCALE','GL_RED_BITS','GL_RED_BIAS',
+            'GL_RED','GL_READ_BUFFER','GL_R3_G3_B2','GL_R','GL_QUAD_STRIP','GL_QUADS','GL_QUADRATIC_ATTENUATION','GL_Q',
+            'GL_PROXY_TEXTURE_2D','GL_PROXY_TEXTURE_1D','GL_PROJECTION_STACK_DEPTH','GL_PROJECTION_MATRIX','GL_PROJECTION',
+            'GL_PRIMARY_COLOR_EXT','GL_PRIMARY_COLOR','GL_PREVIOUS_EXT','GL_PREVIOUS','GL_POSITION','GL_POLYGON_TOKEN',
+            'GL_POLYGON_STIPPLE_BIT','GL_POLYGON_STIPPLE','GL_POLYGON_SMOOTH_HINT','GL_POLYGON_SMOOTH','GL_POLYGON_OFFSET_UNITS',
+            'GL_POLYGON_OFFSET_POINT','GL_POLYGON_OFFSET_LINE','GL_POLYGON_OFFSET_FILL','GL_POLYGON_OFFSET_FACTOR','GL_POLYGON_MODE',
+            'GL_POLYGON_BIT','GL_POLYGON','GL_POINT_TOKEN','GL_POINT_SMOOTH_HINT','GL_POINT_SMOOTH','GL_POINT_SIZE_RANGE',
+            'GL_POINT_SIZE_GRANULARITY','GL_POINT_SIZE','GL_POINT_BIT','GL_POINTS','GL_POINT','GL_PIXEL_MODE_BIT',
+            'GL_PIXEL_MAP_S_TO_S_SIZE','GL_PIXEL_MAP_S_TO_S','GL_PIXEL_MAP_R_TO_R_SIZE','GL_PIXEL_MAP_R_TO_R','GL_PIXEL_MAP_I_TO_R_SIZE',
+            'GL_PIXEL_MAP_I_TO_R','GL_PIXEL_MAP_I_TO_I_SIZE','GL_PIXEL_MAP_I_TO_I','GL_PIXEL_MAP_I_TO_G_SIZE','GL_PIXEL_MAP_I_TO_G',
+            'GL_PIXEL_MAP_I_TO_B_SIZE','GL_PIXEL_MAP_I_TO_B','GL_PIXEL_MAP_I_TO_A_SIZE','GL_PIXEL_MAP_I_TO_A','GL_PIXEL_MAP_G_TO_G_SIZE',
+            'GL_PIXEL_MAP_G_TO_G','GL_PIXEL_MAP_B_TO_B_SIZE','GL_PIXEL_MAP_B_TO_B','GL_PIXEL_MAP_A_TO_A_SIZE','GL_PIXEL_MAP_A_TO_A',
+            'GL_PHONG_WIN','GL_PHONG_HINT_WIN','GL_PERSPECTIVE_CORRECTION_HINT','GL_PASS_THROUGH_TOKEN','GL_PACK_SWAP_BYTES',
+            'GL_PACK_SKIP_ROWS','GL_PACK_SKIP_PIXELS','GL_PACK_ROW_LENGTH','GL_PACK_LSB_FIRST','GL_PACK_ALIGNMENT','GL_OUT_OF_MEMORY',
+            'GL_OR_REVERSE','GL_OR_INVERTED','GL_ORDER','GL_OR','GL_OPERAND2_RGB_EXT','GL_OPERAND2_RGB','GL_OPERAND2_ALPHA_EXT',
+            'GL_OPERAND2_ALPHA','GL_OPERAND1_RGB_EXT','GL_OPERAND1_RGB','GL_OPERAND1_ALPHA_EXT','GL_OPERAND1_ALPHA','GL_OPERAND0_RGB_EXT',
+            'GL_OPERAND0_RGB','GL_OPERAND0_ALPHA_EXT','GL_OPERAND0_ALPHA','GL_ONE_MINUS_SRC_COLOR','GL_ONE_MINUS_SRC_ALPHA',
+            'GL_ONE_MINUS_DST_COLOR','GL_ONE_MINUS_DST_ALPHA','GL_ONE','GL_OBJECT_PLANE','GL_OBJECT_LINEAR','GL_NO_ERROR',
+            'GL_NOTEQUAL','GL_NORMAL_ARRAY_TYPE_EXT','GL_NORMAL_ARRAY_TYPE','GL_NORMAL_ARRAY_STRIDE_EXT','GL_NORMAL_ARRAY_STRIDE',
+            'GL_NORMAL_ARRAY_POINTER_EXT','GL_NORMAL_ARRAY_POINTER','GL_NORMAL_ARRAY_EXT','GL_NORMAL_ARRAY_COUNT_EXT',
+            'GL_NORMAL_ARRAY','GL_NORMALIZE','GL_NOR','GL_NOOP','GL_NONE','GL_NICEST','GL_NEVER','GL_NEAREST_MIPMAP_NEAREST','GL_NEAREST_MIPMAP_LINEAR',
+            'GL_NEAREST','GL_NAND','GL_NAME_STACK_DEPTH','GL_N3F_V3F','GL_MULT','GL_MODULATE','GL_MODELVIEW_STACK_DEPTH','GL_MODELVIEW_MATRIX',
+            'GL_MODELVIEW','GL_MAX_VIEWPORT_DIMS','GL_MAX_TEXTURE_UNITS_ARB','GL_MAX_TEXTURE_UNITS','GL_MAX_TEXTURE_STACK_DEPTH',
+            'GL_MAX_TEXTURE_SIZE','GL_MAX_PROJECTION_STACK_DEPTH','GL_MAX_PIXEL_MAP_TABLE','GL_MAX_NAME_STACK_DEPTH','GL_MAX_MODELVIEW_STACK_DEPTH',
+            'GL_MAX_LIST_NESTING','GL_MAX_LIGHTS','GL_MAX_EVAL_ORDER','GL_MAX_ELEMENTS_VERTICES_WIN','GL_MAX_ELEMENTS_INDICES_WIN',
+            'GL_MAX_CLIP_PLANES','GL_MAX_CLIENT_ATTRIB_STACK_DEPTH','GL_MAX_ATTRIB_STACK_DEPTH','GL_MATRIX_MODE','GL_MAP_STENCIL',
+            'GL_MAP_COLOR','GL_MAP2_VERTEX_4','GL_MAP2_VERTEX_3','GL_MAP2_TEXTURE_COORD_4','GL_MAP2_TEXTURE_COORD_3','GL_MAP2_TEXTURE_COORD_2',
+            'GL_MAP2_TEXTURE_COORD_1','GL_MAP2_NORMAL','GL_MAP2_INDEX','GL_MAP2_GRID_SEGMENTS','GL_MAP2_GRID_DOMAIN','GL_MAP2_COLOR_4',
+            'GL_MAP1_VERTEX_4','GL_MAP1_VERTEX_3','GL_MAP1_TEXTURE_COORD_4','GL_MAP1_TEXTURE_COORD_3','GL_MAP1_TEXTURE_COORD_2',
+            'GL_MAP1_TEXTURE_COORD_1','GL_MAP1_NORMAL','GL_MAP1_INDEX','GL_MAP1_GRID_SEGMENTS','GL_MAP1_GRID_DOMAIN',
+            'GL_MAP1_COLOR_4','GL_LUMINANCE_ALPHA','GL_LUMINANCE8_ALPHA8','GL_LUMINANCE8','GL_LUMINANCE6_ALPHA2','GL_LUMINANCE4_ALPHA4',
+            'GL_LUMINANCE4','GL_LUMINANCE16_ALPHA16','GL_LUMINANCE16','GL_LUMINANCE12_ALPHA4','GL_LUMINANCE12_ALPHA12','GL_LUMINANCE12',
+            'GL_LUMINANCE','GL_LOGIC_OP_MODE','GL_LOGIC_OP','GL_LOAD','GL_LIST_MODE','GL_LIST_INDEX','GL_LIST_BIT',
+            'GL_LIST_BASE','GL_LINE_WIDTH_RANGE','GL_LINE_WIDTH_GRANULARITY','GL_LINE_WIDTH','GL_LINE_TOKEN','GL_LINE_STRIP','GL_LINE_STIPPLE_REPEAT',
+            'GL_LINE_STIPPLE_PATTERN','GL_LINE_STIPPLE','GL_LINE_SMOOTH_HINT','GL_LINE_SMOOTH','GL_LINE_RESET_TOKEN','GL_LINE_LOOP',
+            'GL_LINE_BIT','GL_LINES','GL_LINEAR_MIPMAP_NEAREST','GL_LINEAR_MIPMAP_LINEAR','GL_LINEAR_ATTENUATION','GL_LINEAR',
+            'GL_LINE','GL_LIGHT_MODEL_TWO_SIDE','GL_LIGHT_MODEL_LOCAL_VIEWER','GL_LIGHT_MODEL_AMBIENT','GL_LIGHTING_BIT',
+            'GL_LIGHTING','GL_LIGHT7','GL_LIGHT6','GL_LIGHT5','GL_LIGHT4','GL_LIGHT3','GL_LIGHT2','GL_LIGHT1','GL_LIGHT0',
+            'GL_LESS','GL_LEQUAL','GL_LEFT','GL_KEEP','GL_INVERT','GL_INVALID_VALUE','GL_INVALID_OPERATION','GL_INVALID_ENUM','GL_INTERPOLATE_EXT',
+            'GL_INTERPOLATE','GL_INTENSITY8','GL_INTENSITY4','GL_INTENSITY16','GL_INTENSITY12','GL_INTENSITY','GL_INT',
+            'GL_INDEX_WRITEMASK','GL_INDEX_SHIFT','GL_INDEX_OFFSET','GL_INDEX_MODE','GL_INDEX_LOGIC_OP','GL_INDEX_CLEAR_VALUE','GL_INDEX_BITS',
+            'GL_INDEX_ARRAY_TYPE_EXT','GL_INDEX_ARRAY_TYPE','GL_INDEX_ARRAY_STRIDE_EXT','GL_INDEX_ARRAY_STRIDE','GL_INDEX_ARRAY_POINTER_EXT',
+            'GL_INDEX_ARRAY_POINTER','GL_INDEX_ARRAY_EXT','GL_INDEX_ARRAY_COUNT_EXT','GL_INDEX_ARRAY','GL_INCR','GL_HINT_BIT',
+            'GL_GREEN_SCALE','GL_GREEN_BITS','GL_GREEN_BIAS','GL_GREEN','GL_GREATER','GL_GEQUAL','GL_FRONT_RIGHT','GL_FRONT_LEFT',
+            'GL_FRONT_FACE','GL_FRONT_AND_BACK','GL_FRONT','GL_FOG_START','GL_FOG_SPECULAR_TEXTURE_WIN','GL_FOG_MODE','GL_FOG_INDEX',
+            'GL_FOG_HINT','GL_FOG_END','GL_FOG_DENSITY','GL_FOG_COLOR','GL_FOG_BIT','GL_FOG','GL_FLOAT','GL_FLAT','GL_FILL',
+            'GL_FEEDBACK_BUFFER_TYPE','GL_FEEDBACK_BUFFER_SIZE','GL_FEEDBACK_BUFFER_POINTER','GL_FEEDBACK','GL_FASTEST','GL_FALSE',
+            'GL_EYE_PLANE','GL_EYE_LINEAR','GL_EXT_vertex_array','GL_EXT_paletted_texture','GL_EXT_bgra','GL_EXTENSIONS','GL_EXP2',
+            'GL_EXP','GL_EVAL_BIT','GL_EQUIV','GL_EQUAL','GL_ENABLE_BIT','GL_EMISSION','GL_EDGE_FLAG_ARRAY_STRIDE_EXT','GL_EDGE_FLAG_ARRAY_STRIDE',
+            'GL_EDGE_FLAG_ARRAY_POINTER_EXT','GL_EDGE_FLAG_ARRAY_POINTER','GL_EDGE_FLAG_ARRAY_EXT','GL_EDGE_FLAG_ARRAY_COUNT_EXT','GL_EDGE_FLAG_ARRAY',
+            'GL_EDGE_FLAG','GL_DST_COLOR','GL_DST_ALPHA','GL_DRAW_PIXEL_TOKEN','GL_DRAW_BUFFER','GL_DOUBLE_EXT','GL_DOUBLEBUFFER',
+            'GL_DOUBLE','GL_DONT_CARE','GL_DOMAIN','GL_DITHER','GL_DIFFUSE','GL_DEPTH_WRITEMASK','GL_DEPTH_TEST','GL_DEPTH_SCALE',
+            'GL_DEPTH_RANGE','GL_DEPTH_FUNC','GL_DEPTH_COMPONENT','GL_DEPTH_CLEAR_VALUE','GL_DEPTH_BUFFER_BIT','GL_DEPTH_BITS',
+            'GL_DEPTH_BIAS','GL_DEPTH','GL_DECR','GL_DECAL','GL_CW','GL_CURRENT_TEXTURE_COORDS','GL_CURRENT_RASTER_TEXTURE_COORDS','GL_CURRENT_RASTER_POSITION_VALID',
+            'GL_CURRENT_RASTER_POSITION','GL_CURRENT_RASTER_INDEX','GL_CURRENT_RASTER_DISTANCE','GL_CURRENT_RASTER_COLOR','GL_CURRENT_NORMAL',
+            'GL_CURRENT_INDEX','GL_CURRENT_COLOR','GL_CURRENT_BIT','GL_CULL_FACE_MODE','GL_CULL_FACE','GL_COPY_PIXEL_TOKEN',
+            'GL_COPY_INVERTED','GL_COPY','GL_CONSTANT_EXT','GL_CONSTANT_ATTENUATION','GL_CONSTANT','GL_COMPILE_AND_EXECUTE','GL_COMPILE','GL_COMBINE_RGB_EXT',
+            'GL_COMBINE_RGB','GL_COMBINE_EXT','GL_COMBINE_ALPHA_EXT','GL_COMBINE_ALPHA','GL_COMBINE','GL_COLOR_WRITEMASK',
+            'GL_COLOR_TABLE_WIDTH_EXT','GL_COLOR_TABLE_RED_SIZE_EXT','GL_COLOR_TABLE_LUMINANCE_SIZE_EXT','GL_COLOR_TABLE_INTENSITY_SIZE_EXT',
+            'GL_COLOR_TABLE_GREEN_SIZE_EXT','GL_COLOR_TABLE_FORMAT_EXT','GL_COLOR_TABLE_BLUE_SIZE_EXT','GL_COLOR_TABLE_ALPHA_SIZE_EXT',
+            'GL_COLOR_MATERIAL_PARAMETER','GL_COLOR_MATERIAL_FACE','GL_COLOR_MATERIAL','GL_COLOR_LOGIC_OP','GL_COLOR_INDEXES',
+            'GL_COLOR_INDEX8_EXT','GL_COLOR_INDEX4_EXT','GL_COLOR_INDEX2_EXT','GL_COLOR_INDEX1_EXT','GL_COLOR_INDEX16_EXT',
+            'GL_COLOR_INDEX12_EXT','GL_COLOR_INDEX','GL_COLOR_CLEAR_VALUE','GL_COLOR_BUFFER_BIT','GL_COLOR_ARRAY_TYPE_EXT',
+            'GL_COLOR_ARRAY_TYPE','GL_COLOR_ARRAY_STRIDE_EXT','GL_COLOR_ARRAY_STRIDE','GL_COLOR_ARRAY_SIZE_EXT','GL_COLOR_ARRAY_SIZE',
+            'GL_COLOR_ARRAY_POINTER_EXT','GL_COLOR_ARRAY_POINTER','GL_COLOR_ARRAY_EXT','GL_COLOR_ARRAY_COUNT_EXT','GL_COLOR_ARRAY',
+            'GL_COLOR','GL_COEFF','GL_CLIP_PLANE5','GL_CLIP_PLANE4','GL_CLIP_PLANE3','GL_CLIP_PLANE2','GL_CLIP_PLANE1','GL_CLIP_PLANE0',
+            'GL_CLIENT_VERTEX_ARRAY_BIT','GL_CLIENT_PIXEL_STORE_BIT','GL_CLIENT_ATTRIB_STACK_DEPTH','GL_CLIENT_ALL_ATTRIB_BITS',
+            'GL_CLIENT_ACTIVE_TEXTURE_ARB','GL_CLIENT_ACTIVE_TEXTURE','GL_CLEAR','GL_CLAMP','GL_CCW','GL_C4UB_V3F','GL_C4UB_V2F',
+            'GL_C4F_N3F_V3F','GL_C3F_V3F','GL_BYTE','GL_BLUE_SCALE','GL_BLUE_BITS','GL_BLUE_BIAS','GL_BLUE','GL_BLEND_SRC','GL_BLEND_DST',
+            'GL_BLEND','GL_BITMAP_TOKEN','GL_BITMAP','GL_BGR_EXT','GL_BGRA_EXT','GL_BACK_RIGHT','GL_BACK_LEFT','GL_BACK',
+            'GL_AUX_BUFFERS','GL_AUX3','GL_AUX2','GL_AUX1','GL_AUX0','GL_AUTO_NORMAL','GL_ATTRIB_STACK_DEPTH','GL_AND_REVERSE',
+            'GL_AND_INVERTED','GL_AND','GL_AMBIENT_AND_DIFFUSE','GL_AMBIENT','GL_ALWAYS','GL_ALPHA_TEST_REF','GL_ALPHA_TEST_FUNC',
+            'GL_ALPHA_TEST','GL_ALPHA_SCALE','GL_ALPHA_BITS','GL_ALPHA_BIAS','GL_ALPHA8','GL_ALPHA4','GL_ALPHA16','GL_ALPHA12',
+            'GL_ALPHA','GL_ALL_ATTRIB_BITS','GL_ADD_SIGNED_EXT','GL_ADD_SIGNED','GL_ADD','GL_ACTIVE_TEXTURE_ARB','GL_ACTIVE_TEXTURE',
+            'GL_ACCUM_RED_BITS','GL_ACCUM_GREEN_BITS','GL_ACCUM_CLEAR_VALUE','GL_ACCUM_BUFFER_BIT','GL_ACCUM_BLUE_BITS','GL_ACCUM_ALPHA_BITS',
+            'GL_ACCUM','GL_4_BYTES','GL_4D_COLOR_TEXTURE','GL_3_BYTES','GL_3D_COLOR_TEXTURE','GL_3D_COLOR','GL_3D','GL_2_BYTES',
+            'GL_2D','GLU_V_STEP','GLU_VERTEX','GLU_VERSION_1_2','GLU_VERSION_1_1','GLU_VERSION','GLU_U_STEP','GLU_UNKNOWN','GLU_TRUE',
+            'GLU_TESS_WINDING_RULE','GLU_TESS_WINDING_POSITIVE','GLU_TESS_WINDING_ODD','GLU_TESS_WINDING_NONZERO','GLU_TESS_WINDING_NEGATIVE',
+            'GLU_TESS_WINDING_ABS_GEQ_TWO','GLU_TESS_VERTEX_DATA','GLU_TESS_VERTEX','GLU_TESS_TOLERANCE','GLU_TESS_NEED_COMBINE_CALLBACK','GLU_TESS_MISSING_END_POLYGON',
+            'GLU_TESS_MISSING_END_CONTOUR','GLU_TESS_MISSING_BEGIN_POLYGON','GLU_TESS_MISSING_BEGIN_CONTOUR','GLU_TESS_ERROR_DATA',
+            'GLU_TESS_ERROR8','GLU_TESS_ERROR7','GLU_TESS_ERROR6','GLU_TESS_ERROR5','GLU_TESS_ERROR4','GLU_TESS_ERROR3','GLU_TESS_ERROR2',
+            'GLU_TESS_ERROR1','GLU_TESS_ERROR','GLU_TESS_END_DATA','GLU_TESS_END','GLU_TESS_EDGE_FLAG_DATA','GLU_TESS_EDGE_FLAG',
+            'GLU_TESS_COORD_TOO_LARGE','GLU_TESS_COMBINE_DATA','GLU_TESS_COMBINE','GLU_TESS_BOUNDARY_ONLY','GLU_TESS_BEGIN_DATA',
+            'GLU_TESS_BEGIN','GLU_SMOOTH','GLU_SILHOUETTE','GLU_SAMPLING_TOLERANCE','GLU_SAMPLING_METHOD','GLU_POINT','GLU_PATH_LENGTH',
+            'GLU_PARAMETRIC_TOLERANCE','GLU_PARAMETRIC_ERROR','GLU_OUT_OF_MEMORY','GLU_OUTSIDE','GLU_OUTLINE_POLYGON','GLU_OUTLINE_PATCH',
+            'GLU_NURBS_ERROR9','GLU_NURBS_ERROR8','GLU_NURBS_ERROR7','GLU_NURBS_ERROR6','GLU_NURBS_ERROR5','GLU_NURBS_ERROR4',
+            'GLU_NURBS_ERROR37','GLU_NURBS_ERROR36','GLU_NURBS_ERROR35','GLU_NURBS_ERROR34','GLU_NURBS_ERROR33','GLU_NURBS_ERROR32',
+            'GLU_NURBS_ERROR31','GLU_NURBS_ERROR30','GLU_NURBS_ERROR3','GLU_NURBS_ERROR29','GLU_NURBS_ERROR28','GLU_NURBS_ERROR27','GLU_NURBS_ERROR26',
+            'GLU_NURBS_ERROR25','GLU_NURBS_ERROR24','GLU_NURBS_ERROR23','GLU_NURBS_ERROR22','GLU_NURBS_ERROR21','GLU_NURBS_ERROR20',
+            'GLU_NURBS_ERROR2','GLU_NURBS_ERROR19','GLU_NURBS_ERROR18','GLU_NURBS_ERROR17','GLU_NURBS_ERROR16','GLU_NURBS_ERROR15','GLU_NURBS_ERROR14',
+            'GLU_NURBS_ERROR13','GLU_NURBS_ERROR12','GLU_NURBS_ERROR11','GLU_NURBS_ERROR10','GLU_NURBS_ERROR1','GLU_NONE',
+            'GLU_MAP1_TRIM_3','GLU_MAP1_TRIM_2','GLU_LINE','GLU_INVALID_VALUE','GLU_INVALID_ENUM','GLU_INTERIOR','GLU_INSIDE','GLU_INCOMPATIBLE_GL_VERSION',
+            'GLU_FLAT','GLU_FILL','GLU_FALSE','GLU_EXTERIOR','GLU_EXTENSIONS','GLU_ERROR','GLU_END','GLU_EDGE_FLAG','GLU_DOMAIN_DISTANCE',
+            'GLU_DISPLAY_MODE','GLU_CW','GLU_CULLING','GLU_CCW','GLU_BEGIN','GLU_AUTO_LOAD_MATRIX','CHANNEL_UNORDERED','CHANNEL_ORDERED',
+            'CHANNEL_MAX'
+            ),
+        2 => array(
+
+            // Red Lowercase Keywords
+
+            'WriteWord','WriteString','WriteReal','WriteLine','WriteInt','WriteFloat','WriteDouble','WriteChar','WriteByte',
+            'windowwidth','windowheight','waittimer','Vec4','Vec3','Vec2','val','UpdateJoystick','ucase$','Transpose','tickcount',
+            'textscroll','textrows','textmode','textcols','tanh','tand','tan','synctimercatchup','synctimer','swapbuffers',
+            'str$','stopsoundvoice','stopsounds','stopmusic','sqrt','sqr','sprzorder','spryvel','sprytiles','sprysize','spryrepeat',
+            'spryflip','sprycentre','spry','sprxvel','sprxtiles','sprxsize','sprxrepeat','sprxflip','sprxcentre','sprx',
+            'sprvisible','sprvel','sprtype','sprtop','sprspin','sprsolid','sprsetzorder','sprsetyvel','sprsetysize','sprsetyrepeat',
+            'sprsetyflip','sprsetycentre','sprsety','sprsetxvel','sprsetxsize','sprsetxrepeat','sprsetxflip','sprsetxcentre',
+            'sprsetx','sprsetvisible','sprsetvel','sprsettiles','sprsettextures','sprsettexture','sprsetspin','sprsetsolid',
+            'sprsetsize','sprsetscale','sprsetpos','sprsetparallax','sprsetframe','sprsetcolor','sprsetanimspeed','sprsetanimloop',
+            'sprsetangle','sprsetalpha','sprscale','sprright','sprpos','sprparallax','sprleft','spriteareawidth','spriteareaheight',
+            'sprframe','sprcolor','sprcameraz','sprcameray','sprcamerax','sprcamerasetz','sprcamerasety','sprcamerasetx',
+            'sprcamerasetpos','sprcamerasetfov','sprcamerasetangle','sprcamerapos','sprcamerafov','sprcameraangle',
+            'sprbottom','spranimspeed','spranimloop','spranimdone','sprangle','spralpha','spraddtextures','spraddtexture',
+            'sounderror','sleep','sind','sin','showcursor','sgn','settextscroll','setmusicvolume','SendMessage','Seek',
+            'scankeydown','RTInvert','rnd','right$','resizetext','resizespritearea','RejectConnection','ReceiveMessage','ReadWord',
+            'ReadText','ReadReal','ReadLine','ReadInt','ReadFloat','ReadDouble','ReadChar','ReadByte','randomize','printr',
+            'print','pow','playsound','playmusic','performancecounter','Orthonormalize','OpenFileWrite','OpenFileRead','Normalize',
+            'newtilemap','newsprite','NewServer','NewConnection','musicplaying','mouse_yd','mouse_y','mouse_xd','mouse_x',
+            'mouse_wheel','mouse_button','mid$','MessageSmoothed','MessageReliable','MessagePending','MessageChannel','maxtextureunits',
+            'MatrixZero','MatrixTranslate','MatrixScale','MatrixRotateZ','MatrixRotateY','MatrixRotateX','MatrixRotate','MatrixIdentity',
+            'MatrixCrossProduct','MatrixBasis','log','locate','loadtexture','loadsound','loadmipmaptexture','loadmipmapimagestrip',
+            'loadimagestrip','loadimage','Length','len','left$','lcase$','keydown','Joy_Y','Joy_X','Joy_Up','Joy_Right','Joy_Left',
+            'Joy_Keys','Joy_Down','Joy_Button','Joy_3','Joy_2','Joy_1','Joy_0','int','inscankey','input$','inkey$','inittimer',
+            'imagewidth','imagestripframes','imageheight','imageformat','imagedatatype','hidecursor','glViewport','glVertex4sv',
+            'glVertex4s','glVertex4iv','glVertex4i','glVertex4fv','glVertex4f','glVertex4dv','glVertex4d','glVertex3sv','glVertex3s',
+            'glVertex3iv','glVertex3i','glVertex3fv','glVertex3f','glVertex3dv','glVertex3d','glVertex2sv','glVertex2s','glVertex2iv',
+            'glVertex2i','glVertex2fv','glVertex2f','glVertex2dv','glVertex2d','gluPerspective','gluOrtho2D','gluLookAt',
+            'glubuild2dmipmaps','glTranslatef','glTranslated','gltexsubimage2d','glTexParameteriv','glTexParameteri',
+            'glTexParameterfv','glTexParameterf','glteximage2d','glTexGeniv','glTexGeni','glTexGenfv','glTexGenf','glTexGendv',
+            'glTexGend','glTexEnviv','glTexEnvi','glTexEnvfv','glTexEnvf','glTexCoord4sv','glTexCoord4s','glTexCoord4iv','glTexCoord4i',
+            'glTexCoord4fv','glTexCoord4f','glTexCoord4dv','glTexCoord4d','glTexCoord3sv','glTexCoord3s','glTexCoord3iv','glTexCoord3i',
+            'glTexCoord3fv','glTexCoord3f','glTexCoord3dv','glTexCoord3d','glTexCoord2sv','glTexCoord2s','glTexCoord2iv','glTexCoord2i',
+            'glTexCoord2fv','glTexCoord2f','glTexCoord2dv','glTexCoord2d','glTexCoord1sv','glTexCoord1s','glTexCoord1iv','glTexCoord1i','glTexCoord1fv',
+            'glTexCoord1f','glTexCoord1dv','glTexCoord1d','glStencilOp','glStencilMask','glStencilFunc','glShadeModel','glSelectBuffer',
+            'glScissor','glScalef','glScaled','glRotatef','glRotated','glRenderMode','glRectsv','glRects','glRectiv','glRecti',
+            'glRectfv','glRectf','glRectdv','glRectd','glReadBuffer','glRasterPos4sv','glRasterPos4s','glRasterPos4iv',
+            'glRasterPos4i','glRasterPos4fv','glRasterPos4f','glRasterPos4dv','glRasterPos4d','glRasterPos3sv','glRasterPos3s',
+            'glRasterPos3iv','glRasterPos3i','glRasterPos3fv','glRasterPos3f','glRasterPos3dv','glRasterPos3d','glRasterPos2sv',
+            'glRasterPos2s','glRasterPos2iv','glRasterPos2i','glRasterPos2fv','glRasterPos2f','glRasterPos2dv','glRasterPos2d',
+            'glPushName','glPushMatrix','glPushClientAttrib','glPushAttrib','glPrioritizeTextures','glPopName','glPopMatrix',
+            'glPopClientAttrib','glPopAttrib','glpolygonstipple','glPolygonOffset','glPolygonMode','glPointSize','glPixelZoom',
+            'glPixelTransferi','glPixelTransferf','glPixelStorei','glPixelStoref','glPassThrough','glOrtho','glNormal3sv','glNormal3s',
+            'glNormal3iv','glNormal3i','glNormal3fv','glNormal3f','glNormal3dv','glNormal3d','glNormal3bv','glNormal3b','glNewList',
+            'glMultMatrixf','glMultMatrixd','glmultitexcoord2f','glmultitexcoord2d','glMatrixMode','glMaterialiv','glMateriali',
+            'glMaterialfv','glMaterialf','glMapGrid2f','glMapGrid2d','glMapGrid1f','glMapGrid1d','glLogicOp','glLoadName','glLoadMatrixf',
+            'glLoadMatrixd','glLoadIdentity','glListBase','glLineWidth','glLineStipple','glLightModeliv','glLightModeli','glLightModelfv',
+            'glLightModelf','glLightiv','glLighti','glLightfv','glLightf','glIsTexture','glIsList','glIsEnabled','glInitNames',
+            'glIndexubv','glIndexub','glIndexsv','glIndexs','glIndexMask','glIndexiv','glIndexi','glIndexfv','glIndexf','glIndexdv',
+            'glIndexd','glHint','glGetTexParameteriv','glGetTexParameterfv','glGetTexLevelParameteriv','glGetTexLevelParameterfv',
+            'glGetTexGeniv','glGetTexGenfv','glGetTexGendv','glGetTexEnviv','glGetTexEnvfv','glgetstring','glgetpolygonstipple','glGetPixelMapuiv',
+            'glGetMaterialiv','glGetMaterialfv','glGetLightiv','glGetLightfv','glGetIntegerv','glGetFloatv',
+            'glGetError','glGetDoublev','glGetClipPlane','glGetBooleanv','glgentextures','glgentexture',
+            'glgenlists','glFrustum','glFrontFace','glFogiv','glFogi','glFogfv','glFogf','glFlush','glFinish','glFeedbackBuffer',
+            'glEvalPoint2','glEvalPoint1','glEvalMesh2','glEvalMesh1','glEvalCoord2fv','glEvalCoord2f','glEvalCoord2dv','glEvalCoord2d',
+            'glEvalCoord1fv','glEvalCoord1f','glEvalCoord1dv','glEvalCoord1d','glEndList','glEnd','glEnableClientState','glEnable',
+            'glEdgeFlagv','glEdgeFlag','glDrawBuffer','glDrawArrays','glDisableClientState','glDisable','glDepthRange','glDepthMask',
+            'glDepthFunc','gldeletetextures','gldeletetexture','gldeletelists','glCullFace','glCopyTexSubImage2D','glCopyTexSubImage1D',
+            'glCopyTexImage2D','glCopyTexImage1D','glColorMaterial','glColorMask','glColor4usv','glColor4us','glColor4uiv','glColor4ui',
+            'glColor4ubv','glColor4ub','glColor4sv','glColor4s','glColor4iv','glColor4i','glColor4fv','glColor4f','glColor4dv',
+            'glColor4d','glColor4bv','glColor4b','glColor3usv','glColor3us','glColor3uiv','glColor3ui','glColor3ubv','glColor3ub',
+            'glColor3sv','glColor3s','glColor3iv','glColor3i','glColor3fv','glColor3f','glColor3dv','glColor3d','glColor3bv',
+            'glColor3b','glClipPlane','glClearStencil','glClearIndex','glClearDepth','glClearColor','glClearAccum','glClear',
+            'glcalllists','glCallList','glBlendFunc','glBindTexture','glBegin','glArrayElement','glAreTexturesResident',
+            'glAlphaFunc','glactivetexture','glAccum','font','FindNextFile','FindFirstFile','FindClose','FileError',
+            'extensionsupported','exp','execute','EndOfFile','drawtext','divbyzero','Determinant','deletesprite','deletesound',
+            'DeleteServer','deleteimage','DeleteConnection','defaultfont','CrossProduct','cosd','cos','copysprite','ConnectionPending',
+            'ConnectionHandShaking','ConnectionConnected','ConnectionAddress','compilererrorline','compilererrorcol','compilererror',
+            'compilefile','compile','color','cls','CloseFile','clearregion','clearline','clearkeys','chr$','charat$','bindsprite',
+            'beep','atnd','atn2d','atn2','atn','atand','asc','argcount','arg','animatesprites','AcceptConnection','abs'
+            ),
+        3 => array(
+
+            // Blue Lowercase Keywords
+
+            'xor','while','wend','until','type','traditional_print','traditional','to','then','struc','string','step','single',
+            'run','return','reset','read','or','null','not','next','lor','loop','language','land','integer','input','if',
+            'goto','gosub','for','endstruc','endif','end','elseif','else','double','do','dim','data','const','basic4gl','as',
+            'and','alloc'
+            )
+
+        ),
+    'SYMBOLS' => array(
+        '=', '<', '>', '>=', '<=', '+', '-', '*', '/', '%', '(', ')', '{', '}', '[', ']', '&', ';', ':', '$'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000080; font-weight: bold;',
+            2 => 'color: #FF0000;',
+            3 => 'color: #0000FF;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #657CC4; font-style: italic;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000080;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #008000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #000080; font-weight: bold;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #0000FF;'
+            ),
+        'ESCAPE_CHAR' => array(
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/bf.php b/examples/includes/geshi/geshi/bf.php
new file mode 100644 (file)
index 0000000..e5dcc42
--- /dev/null
@@ -0,0 +1,114 @@
+<?php
+/*************************************************************************************
+ * bf.php
+ * ----------
+ * Author: Benny Baumann (BenBE@geshi.org)
+ * Copyright: (c) 2008 Benny Baumann (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2009/10/31
+ *
+ * Brainfuck language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/10/31 (1.0.8.1)
+ *   -  First Release
+ *
+ * TODO
+ * ----
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+$language_data = array (
+    'LANG_NAME' => 'Brainfuck',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array(),
+    'COMMENT_REGEXP' => array(1 => '/[^\n+\-<>\[\]\.\,Y]+/s'),
+    'CASE_KEYWORDS' => GESHI_CAPS_UPPER,
+    'QUOTEMARKS' => array(),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        ),
+    'SYMBOLS' => array(
+        0 => array('+', '-'),
+        1 => array('[', ']'),
+        2 => array('<', '>'),
+        3 => array('.', ','),
+        4 => array('Y') //Brainfork Extension ;-)
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #666666; font-style: italic;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #006600;',
+            1 => 'color: #660000;',
+            2 => 'color: #000066;',
+            3 => 'color: #660066;',
+            4 => 'color: #666600;'
+            ),
+        'ESCAPE_CHAR' => array(
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4,
+    'PARSER_CONTROL' => array(
+        'ENABLE_FLAGS' => array(
+            'STRINGS' => GESHI_NEVER,
+            'NUMBERS' => GESHI_NEVER
+            ),
+        'KEYWORDS' => array(
+            'DISALLOW_BEFORE' => '',
+            'DISALLOW_AFTER' => ''
+            )
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/blitzbasic.php b/examples/includes/geshi/geshi/blitzbasic.php
new file mode 100644 (file)
index 0000000..a8c3259
--- /dev/null
@@ -0,0 +1,185 @@
+<?php
+/*************************************************************************************
+ * blitzbasic.php
+ * --------------
+ * Author: P�draig O`Connel (info@moonsword.info)
+ * Copyright: (c) 2005 P�draig O`Connel (http://moonsword.info)
+ * Release Version: 1.0.8.3
+ * Date Started: 16.10.2005
+ *
+ * BlitzBasic language file for GeSHi.
+ *
+ * It is a simple Basic dialect. Released for Games and Network Connections.
+ * In this Language File are all functions included (2D BB and 3D BB)
+ *
+ *
+ * CHANGES
+ * -------
+ * 2005/12/28 (1.0.1)
+ *   -  Remove unnecessary style index for regexps
+ * 2005/10/22 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2005/10/22)
+ * -------------------------
+ * * Sort out the Basic commands for splitting up.
+ * * To set up the right colors.
+ *      (the colors are ok, but not the correct ones)
+ * * Split to BlitzBasic 2D and BlitzBasic 3D.
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'BlitzBasic',
+    'COMMENT_SINGLE' => array(1 => ';'),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            'If','EndIf','ElseIf','Else If','Else','While','Wend','Return','Next','Include','End Type','End Select','End If','End Function','End','Select',
+            'Type','Forever','For','Or','And','AppTitle','Case','Goto','Gosub','Step','Stop','Int','Last','False','Then','To','True','Until','Float',
+            'String','Before','Not'
+            ),
+        2 => array(
+            // All Functions - 2D BB and 3D BB
+            'Xor','WriteString','WriteShort','WritePixelFast','WritePixel','WriteLine','WriteInt','WriteFloat','WriteFile','WriteBytes',
+            'WriteByte','Write','WaitTimer','WaitMouse','WaitKey','WaitJoy','VWait','Viewport',
+            'Upper','UpdateGamma','UnlockBuffer','UDPTimeouts','UDPStreamPort','UDPStreamIP','UDPMsgPort','UDPMsgIP',
+            'Trim','TotalVidMem','TileImage','TileBlock','TFormImage','TFormFilter','Text',
+            'TCPTimeouts','TCPStreamPort','TCPStreamIP','Tan','SystemProperty','StringWidth','StringHeight','Str','StopNetGame',
+            'StopChannel','StartNetGame','Sqr','SoundVolume','SoundPitch','SoundPan','Sin','Shr',
+            'ShowPointer','Shl','Sgn','SetGfxDriver','SetGamma','SetFont','SetEnv','SetBuffer','SendUDPMsg','SendNetMsg',
+            'SeekFile','SeedRnd','ScanLine','ScaleImage','SaveImage','SaveBuffer','Sar','RuntimeError','RSet',
+            'RotateImage','RndSeed','Rnd','Right','ResumeChannel','Restore','ResizeImage','ResizeBank','Replace',
+            'Repeat','RecvUDPMsg','RecvNetMsg','RectsOverlap','Rect','ReadString','ReadShort','ReadPixelFast','ReadPixel','ReadLine',
+            'ReadInt','ReadFloat','ReadFile','ReadDir','ReadBytes','ReadByte','ReadAvail','Read','Rand','Print',
+            'PokeShort','PokeInt','PokeFloat','PokeByte','Plot','PlaySound','PlayMusic','PlayCDTrack','Pi','PeekShort',
+            'PeekInt','PeekFloat','PeekByte','PauseChannel','Oval','Origin','OpenTCPStream','OpenMovie','OpenFile',
+            'Null','NextFile','New','NetPlayerName','NetPlayerLocal','NetMsgType','NetMsgTo','NetMsgFrom',
+            'NetMsgData','MovieWidth','MoviePlaying','MovieHeight','MoveMouse','MouseZSpeed','MouseZ','MouseYSpeed','MouseY','MouseXSpeed',
+            'MouseX','MouseHit','MouseDown','Mod','Millisecs','MidHandle','Mid','MaskImage','LSet','Lower',
+            'LoopSound','Log10','Log','LockBuffer','Locate','Local','LoadSound','LoadImage','LoadFont','LoadBuffer',
+            'LoadAnimImage','Line','Len','Left','KeyHit','KeyDown','JoyZDir','JoyZ','JoyYDir',
+            'JoyYaw','JoyY','JoyXDir','JoyX','JoyVDir','JoyV','JoyUDir','JoyU','JoyType','JoyRoll',
+            'JoyPitch','JoyHit','JoyHat','JoyDown','JoinNetGame','Instr','Insert','Input',
+            'ImageYHandle','ImageXHandle','ImageWidth','ImagesOverlap','ImagesCollide','ImageRectOverlap','ImageRectCollide','ImageHeight','ImageBuffer',
+            'HostNetGame','HostIP','HidePointer','Hex','HandleImage','GraphicsWidth','GraphicsHeight','GraphicsDepth','GraphicsBuffer','Graphics',
+            'GrabImage','Global','GFXModeWidth','GFXModeHeight','GfxModeExists','GFXModeDepth','GfxDriverName','GetMouse',
+            'GetKey','GetJoy','GetEnv','GetColor','GammaRed','GammaGreen','GammaBlue','Function','FrontBuffer','FreeTimer',
+            'FreeSound','FreeImage','FreeFont','FreeBank','FontWidth','FontHeight','FlushMouse','FlushKeys',
+            'FlushJoy','Floor','Flip','First','FileType','FileSize','FilePos','Field',
+            'Exp','Exit','ExecFile','Eof','EndGraphics','Each','DrawMovie','DrawImageRect','DrawImage','DrawBlockRect','DrawBlock',
+            'DottedIP','Dim','DeleteNetPlayer','DeleteFile','DeleteDir','Delete','Delay','Default','DebugLog','Data',
+            'CurrentTime','CurrentDir','CurrentDate','CreateUDPStream','CreateTimer','CreateTCPServer','CreateNetPlayer','CreateImage','CreateDir','CreateBank',
+            'CountHostIPs','CountGFXModes','CountGfxDrivers','Cos','CopyStream','CopyRect','CopyPixelFast','CopyPixel','CopyImage','CopyFile',
+            'CopyBank','Const','CommandLine','ColorRed','ColorGreen','ColorBlue','Color','ClsColor','Cls','CloseUDPStream',
+            'CloseTCPStream','CloseTCPServer','CloseMovie','CloseFile','CloseDir','Chr','ChannelVolume','ChannelPlaying','ChannelPitch','ChannelPan',
+            'ChangeDir','Ceil','CallDLL','Bin','BankSize','BackBuffer','AvailVidMem','AutoMidHandle',
+            'ATan2','ATan','ASin','Asc','After','ACos','AcceptTCPStream','Abs',
+            // 3D Commands
+            'Wireframe','Windowed3D','WBuffer','VertexZ','VertexY',
+            'VertexX','VertexW','VertexV','VertexU','VertexTexCoords','VertexRed','VertexNZ','VertexNY','VertexNX','VertexNormal',
+            'VertexGreen','VertexCoords','VertexColor','VertexBlue','VertexAlpha','VectorYaw','VectorPitch','UpdateWorld','UpdateNormals','TurnEntity',
+            'TrisRendered','TriangleVertex','TranslateEntity','TFormVector','TFormPoint','TFormNormal','TFormedZ','TFormedY','TFormedX','TextureWidth',
+            'TextureName','TextureHeight','TextureFilter','TextureCoords','TextureBuffer','TextureBlend','TerrainZ','TerrainY','TerrainX','TerrainSize',
+            'TerrainShading','TerrainHeight','TerrainDetail','SpriteViewMode','ShowEntity','SetCubeFace','SetAnimTime','SetAnimKey','ScaleTexture','ScaleSprite',
+            'ScaleMesh','ScaleEntity','RotateTexture','RotateSprite','RotateMesh','RotateEntity','ResetEntity','RenderWorld','ProjectedZ','ProjectedY',
+            'ProjectedX','PositionTexture','PositionMesh','PositionEntity','PointEntity','PickedZ','PickedY','PickedX','PickedTriangle','PickedTime',
+            'PickedSurface','PickedNZ','PickedNY','PickedNX','PickedEntity','PaintSurface','PaintMesh','PaintEntity','NameEntity','MoveEntity',
+            'ModifyTerrain','MeshWidth','MeshHeight','MeshesIntersect','MeshDepth','MD2AnimTime','MD2AnimLength','MD2Animating','LoadTexture','LoadTerrain',
+            'LoadSprite','LoadMesh','LoadMD2','LoaderMatrix','LoadBSP','LoadBrush','LoadAnimTexture','LoadAnimSeq','LoadAnimMesh','Load3DSound',
+            'LinePick','LightRange','LightMesh','LightConeAngles','LightColor','HWMultiTex','HideEntity','HandleSprite','Graphics3D','GfxMode3DExists',
+            'GfxMode3D','GfxDriverCaps3D','GfxDriver3D','GetSurfaceBrush','GetSurface','GetParent','GetMatElement','GetEntityType','GetEntityBrush','GetChild',
+            'GetBrushTexture','FreeTexture','FreeEntity','FreeBrush','FlipMesh','FitMesh','FindSurface','FindChild','ExtractAnimSeq','EntityZ',
+            'EntityYaw','EntityY','EntityX','EntityVisible','EntityType','EntityTexture','EntityShininess','EntityRoll','EntityRadius','EntityPitch',
+            'EntityPickMode','EntityPick','EntityParent','EntityOrder','EntityName','EntityInView','EntityFX','EntityDistance','EntityColor','EntityCollided',
+            'EntityBox','EntityBlend','EntityAutoFade','EntityAlpha','EmitSound','Dither','DeltaYaw','DeltaPitch','CreateTexture','CreateTerrain',
+            'CreateSurface','CreateSprite','CreateSphere','CreatePlane','CreatePivot','CreateMirror','CreateMesh','CreateListener','CreateLight','CreateCylinder',
+            'CreateCube','CreateCone','CreateCamera','CreateBrush','CountVertices','CountTriangles','CountSurfaces','CountGfxModes3D','CountCollisions','CountChildren',
+            'CopyMesh','CopyEntity','CollisionZ','CollisionY','CollisionX','CollisionTriangle','CollisionTime','CollisionSurface','Collisions','CollisionNZ',
+            'CollisionNY','CollisionNX','CollisionEntity','ClearWorld','ClearTextureFilters','ClearSurface','ClearCollisions','CaptureWorld','CameraZoom','CameraViewport',
+            'CameraRange','CameraProjMode','CameraProject','CameraPick','CameraFogRange','CameraFogMode','CameraFogColor','CameraClsMode','CameraClsColor','BSPLighting',
+            'BSPAmbientLight','BrushTexture','BrushShininess','BrushFX','BrushColor','BrushBlend','BrushAlpha','AntiAlias','AnimTime','AnimSeq',
+            'AnimLength','Animating','AnimateMD2','Animate','AmbientLight','AlignToVector','AddVertex','AddTriangle','AddMesh','AddAnimSeq',
+            )
+        ),
+    'SYMBOLS' => array(
+        '(',')'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000066; font-weight: bold;',
+            2 => 'color: #0000ff;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #D9D100; font-style: italic;',
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000066;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #009900;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #CC0000;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006600;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000066;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            0 => '',
+            1 => '',
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        1 => '\\'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        0 => false,
+        1 => false
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/bnf.php b/examples/includes/geshi/geshi/bnf.php
new file mode 100644 (file)
index 0000000..c9b3aae
--- /dev/null
@@ -0,0 +1,110 @@
+<?php
+/*************************************************************************************
+ * bnf.php
+ * --------
+ * Author: Rowan Rodrik van der Molen (rowan@bigsmoke.us)
+ * Copyright: (c) 2006 Rowan Rodrik van der Molen (http://www.bigsmoke.us/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2006/09/28
+ *
+ * BNF (Backus-Naur form) language file for GeSHi.
+ *
+ * See http://en.wikipedia.org/wiki/Backus-Naur_form for more info on BNF.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *  -  Added description of extra language features (SF#1970248)
+ *  -  Removed superflicious regexps
+ * 2006/09/18 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2006/09/18)
+ * -------------------------
+ * * Nothing I can think of
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'bnf',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"', "'"),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(),
+    'SYMBOLS' => array(
+        '(', ')', '<', '>', '::=', '|'
+    ),
+    'CASE_SENSITIVE' => array(
+        //GESHI_COMMENTS => false
+    ),
+    'STYLES' => array(
+        'KEYWORDS' => array(),
+        'COMMENTS' => array(
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => ''
+            ),
+        'BRACKETS' => array(
+            0 => ''
+            ),
+        'STRINGS' => array(
+            0 => 'color: #a00;',
+            1 => 'color: #a00;'
+            ),
+        'NUMBERS' => array(
+            0 => ''
+            ),
+        'METHODS' => array(
+            0 => ''
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000066; font-weight: bold;', // Unused
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #007;',
+            ),
+        'SCRIPT' => array(
+            0 => ''
+            )
+        ),
+    'URLS' => array(),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(),
+    'REGEXPS' => array(
+        //terminal symbols
+        0 => array(
+            GESHI_SEARCH => '(&lt;)([^&]+?)(&gt;)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => '\\3'
+            ),
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/boo.php b/examples/includes/geshi/geshi/boo.php
new file mode 100644 (file)
index 0000000..1741d2c
--- /dev/null
@@ -0,0 +1,217 @@
+<?php
+/*************************************************************************************
+ * boo.php
+ * --------
+ * Author: Marcus Griep (neoeinstein+GeSHi@gmail.com)
+ * Copyright: (c) 2007 Marcus Griep (http://www.xpdm.us)
+ * Release Version: 1.0.8.3
+ * Date Started: 2007/09/10
+ *
+ * Boo language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2004/09/10 (1.0.8)
+ *  -  First Release
+ *
+ * TODO (updated 2007/09/10)
+ * -------------------------
+ * Regular Expression Literal matching
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Boo',
+    'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'''", "'", '"""', '"'),
+    'HARDQUOTE' => array('"""', '"""'),
+    'HARDESCAPE' => array('\"""'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(//Namespace
+            'namespace', 'import', 'from'
+            ),
+        2 => array(//Jump
+            'yield', 'return', 'goto', 'continue', 'break'
+            ),
+        3 => array(//Conditional
+            'while', 'unless', 'then', 'in', 'if', 'for', 'else', 'elif'
+            ),
+        4 => array(//Property
+            'set', 'get'
+            ),
+        5 => array(//Exception
+            'try', 'raise', 'failure', 'except', 'ensure'
+            ),
+        6 => array(//Visibility
+            'public', 'private', 'protected', 'internal'
+            ),
+        7 => array(//Define
+            'struct', 'ref', 'of', 'interface', 'event', 'enum', 'do', 'destructor', 'def', 'constructor', 'class'
+            ),
+        8 => array(//Cast
+            'typeof', 'cast', 'as'
+            ),
+        9 => array(//BiMacro
+            'yieldAll', 'using', 'unchecked', 'rawArayIndexing', 'print', 'normalArrayIndexing', 'lock',
+            'debug', 'checked', 'assert'
+            ),
+        10 => array(//BiAttr
+            'required', 'property', 'meta', 'getter', 'default'
+            ),
+        11 => array(//BiFunc
+            'zip', 'shellp', 'shellm', 'shell', 'reversed', 'range', 'prompt',
+            'matrix', 'map', 'len', 'join', 'iterator', 'gets', 'enumerate', 'cat', 'array'
+            ),
+        12 => array(//HiFunc
+            '__switch__', '__initobj__', '__eval__', '__addressof__', 'quack'
+            ),
+        13 => array(//Primitive
+            'void', 'ushort', 'ulong', 'uint', 'true', 'timespan', 'string', 'single',
+            'short', 'sbyte', 'regex', 'object', 'null', 'long', 'int', 'false', 'duck',
+            'double', 'decimal', 'date', 'char', 'callable', 'byte', 'bool'
+            ),
+        14 => array(//Operator
+            'not', 'or', 'and', 'is', 'isa',
+            ),
+        15 => array(//Modifier
+            'virtual', 'transient', 'static', 'partial', 'override', 'final', 'abstract'
+            ),
+        16 => array(//Access
+            'super', 'self'
+            ),
+        17 => array(//Pass
+            'pass'
+            )
+        ),
+    'SYMBOLS' => array(
+        '[|', '|]', '${', '(', ')', '[', ']', '{', '}', '!', '@', '%', '&', '*', '|', '/', '<', '>', '+', '-', ';'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true,
+        5 => true,
+        6 => true,
+        7 => true,
+        8 => true,
+        9 => true,
+        10 => true,
+        11 => true,
+        12 => true,
+        13 => true,
+        14 => true,
+        15 => true,
+        16 => true,
+        17 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color:green;font-weight:bold;',
+            2 => 'color:navy;',
+            3 => 'color:blue;font-weight:bold;',
+            4 => 'color:#8B4513;',
+            5 => 'color:teal;font-weight:bold;',
+            6 => 'color:blue;font-weight:bold;',
+            7 => 'color:blue;font-weight:bold;',
+            8 => 'color:blue;font-weight:bold;',
+            9 => 'color:maroon;',
+            10 => 'color:maroon;',
+            11 => 'color:purple;',
+            12 => 'color:#4B0082;',
+            13 => 'color:purple;font-weight:bold;',
+            14 => 'color:#008B8B;font-weight:bold;',
+            15 => 'color:brown;',
+            16 => 'color:black;font-weight:bold;',
+            17 => 'color:gray;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #999999; font-style: italic;',
+            2 => 'color: #999999; font-style: italic;',
+            'MULTI' => 'color: #008000; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #0000FF; font-weight: bold;',
+            'HARD' => 'color: #0000FF; font-weight: bold;',
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #006400;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #008000;',
+            'HARD' => 'color: #008000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #00008B;'
+            ),
+        'METHODS' => array(
+            0 => 'color: 000000;',
+            1 => 'color: 000000;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #006400;'
+            ),
+        'REGEXPS' => array(
+            #0 => 'color: #0066ff;'
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => '',
+        5 => '',
+        6 => '',
+        7 => '',
+        8 => '',
+        9 => '',
+        10 => '',
+        11 => '',
+        12 => '',
+        13 => '',
+        14 => '',
+        15 => '',
+        16 => '',
+        17 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        0 => '.',
+        1 => '::'
+        ),
+    'REGEXPS' => array(
+        #0 => '%(@)?\/(?:(?(1)[^\/\\\\\r\n]+|[^\/\\\\\r\n \t]+)|\\\\[\/\\\\\w+()|.*?$^[\]{}\d])+\/%'
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/c.php b/examples/includes/geshi/geshi/c.php
new file mode 100644 (file)
index 0000000..272885a
--- /dev/null
@@ -0,0 +1,188 @@
+<?php
+/*************************************************************************************
+ * c.php
+ * -----
+ * Author: Nigel McNie (nigel@geshi.org)
+ * Contributors:
+ *  - Jack Lloyd (lloyd@randombit.net)
+ *  - Michael Mol (mikemol@gmail.com)
+ * Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/06/04
+ *
+ * C language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2009/01/22 (1.0.8.3)
+ *   -  Made keywords case-sensitive.
+ * 2008/05/23 (1.0.7.22)
+ *   -  Added description of extra language features (SF#1970248)
+ * 2004/XX/XX (1.0.4)
+ *   -  Added a couple of new keywords (Jack Lloyd)
+ * 2004/11/27 (1.0.3)
+ *   -  Added support for multiple object splitters
+ * 2004/10/27 (1.0.2)
+ *   -  Added support for URLs
+ * 2004/08/05 (1.0.1)
+ *   -  Added support for symbols
+ * 2004/07/14 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2009/02/08)
+ * -------------------------
+ *  -  Get a list of inbuilt functions to add (and explore C more
+ *     to complete this rather bare language file
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'C',
+    'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'COMMENT_REGEXP' => array(
+        //Multiline-continued single-line comments
+        1 => '/\/\/(?:\\\\\\\\|\\\\\\n|.)*$/m',
+        //Multiline-continued preprocessor define
+        2 => '/#(?:\\\\\\\\|\\\\\\n|.)*$/m'
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '',
+    'ESCAPE_REGEXP' => array(
+        //Simple Single Char Escapes
+        1 => "#\\\\[abfnrtv\\'\"?\n]#i",
+        //Hexadecimal Char Specs
+        2 => "#\\\\x[\da-fA-F]{2}#",
+        //Hexadecimal Char Specs
+        3 => "#\\\\u[\da-fA-F]{4}#",
+        //Hexadecimal Char Specs
+        4 => "#\\\\U[\da-fA-F]{8}#",
+        //Octal Char Specs
+        5 => "#\\\\[0-7]{1,3}#"
+        ),
+    'NUMBERS' =>
+        GESHI_NUMBER_INT_BASIC | GESHI_NUMBER_INT_CSTYLE | GESHI_NUMBER_BIN_PREFIX_0B |
+        GESHI_NUMBER_OCT_PREFIX | GESHI_NUMBER_HEX_PREFIX | GESHI_NUMBER_FLT_NONSCI |
+        GESHI_NUMBER_FLT_NONSCI_F | GESHI_NUMBER_FLT_SCI_SHORT | GESHI_NUMBER_FLT_SCI_ZERO,
+    'KEYWORDS' => array(
+        1 => array(
+            'if', 'return', 'while', 'case', 'continue', 'default',
+            'do', 'else', 'for', 'switch', 'goto'
+            ),
+        2 => array(
+            'null', 'false', 'break', 'true', 'function', 'enum', 'extern', 'inline'
+            ),
+        3 => array(
+            'printf', 'cout'
+            ),
+        4 => array(
+            'auto', 'char', 'const', 'double',  'float', 'int', 'long',
+            'register', 'short', 'signed', 'sizeof', 'static', 'string', 'struct',
+            'typedef', 'union', 'unsigned', 'void', 'volatile', 'wchar_t'
+            ),
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '{', '}', '[', ']',
+        '+', '-', '*', '/', '%',
+        '=', '<', '>',
+        '!', '^', '&', '|',
+        '?', ':',
+        ';', ','
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #000066;',
+            4 => 'color: #993333;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #666666; font-style: italic;',
+            2 => 'color: #339933;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;',
+            1 => 'color: #000099; font-weight: bold;',
+            2 => 'color: #660099; font-weight: bold;',
+            3 => 'color: #660099; font-weight: bold;',
+            4 => 'color: #660099; font-weight: bold;',
+            5 => 'color: #006699; font-weight: bold;',
+            'HARD' => '',
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #009900;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #0000dd;',
+            GESHI_NUMBER_BIN_PREFIX_0B => 'color: #208080;',
+            GESHI_NUMBER_OCT_PREFIX => 'color: #208080;',
+            GESHI_NUMBER_HEX_PREFIX => 'color: #208080;',
+            GESHI_NUMBER_FLT_SCI_SHORT => 'color:#800080;',
+            GESHI_NUMBER_FLT_SCI_ZERO => 'color:#800080;',
+            GESHI_NUMBER_FLT_NONSCI_F => 'color:#800080;',
+            GESHI_NUMBER_FLT_NONSCI => 'color:#800080;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #202020;',
+            2 => 'color: #202020;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #339933;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => 'http://www.opengroup.org/onlinepubs/009695399/functions/{FNAMEL}.html',
+        4 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.',
+        2 => '::'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/c_mac.php b/examples/includes/geshi/geshi/c_mac.php
new file mode 100644 (file)
index 0000000..3478fba
--- /dev/null
@@ -0,0 +1,212 @@
+<?php
+/*************************************************************************************
+ * c_mac.php
+ * ---------
+ * Author: M. Uli Kusterer (witness.of.teachtext@gmx.net)
+ * Copyright: (c) 2004 M. Uli Kusterer, Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/06/04
+ *
+ * C for Macs language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *   -  Added description of extra language features (SF#1970248)
+ * 2004/11/27
+ *   -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'C (Mac)',
+    'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'COMMENT_REGEXP' => array(
+        //Multiline-continued single-line comments
+        1 => '/\/\/(?:\\\\\\\\|\\\\\\n|.)*$/m',
+        //Multiline-continued preprocessor define
+        2 => '/#(?:\\\\\\\\|\\\\\\n|.)*$/m'
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '',
+    'ESCAPE_REGEXP' => array(
+        //Simple Single Char Escapes
+        1 => "#\\\\[abfnrtv\\'\"?\n]#i",
+        //Hexadecimal Char Specs
+        2 => "#\\\\x[\da-fA-F]{2}#",
+        //Hexadecimal Char Specs
+        3 => "#\\\\u[\da-fA-F]{4}#",
+        //Hexadecimal Char Specs
+        4 => "#\\\\U[\da-fA-F]{8}#",
+        //Octal Char Specs
+        5 => "#\\\\[0-7]{1,3}#"
+        ),
+    'NUMBERS' =>
+        GESHI_NUMBER_INT_BASIC | GESHI_NUMBER_INT_CSTYLE | GESHI_NUMBER_BIN_PREFIX_0B |
+        GESHI_NUMBER_OCT_PREFIX | GESHI_NUMBER_HEX_PREFIX | GESHI_NUMBER_FLT_NONSCI |
+        GESHI_NUMBER_FLT_NONSCI_F | GESHI_NUMBER_FLT_SCI_SHORT | GESHI_NUMBER_FLT_SCI_ZERO,
+    'KEYWORDS' => array(
+        1 => array(
+            'if', 'return', 'while', 'case', 'continue', 'default',
+            'do', 'else', 'for', 'switch', 'goto'
+            ),
+        2 => array(
+            'NULL', 'false', 'break', 'true', 'enum', 'errno', 'EDOM',
+            'ERANGE', 'FLT_RADIX', 'FLT_ROUNDS', 'FLT_DIG', 'DBL_DIG', 'LDBL_DIG',
+            'FLT_EPSILON', 'DBL_EPSILON', 'LDBL_EPSILON', 'FLT_MANT_DIG', 'DBL_MANT_DIG',
+            'LDBL_MANT_DIG', 'FLT_MAX', 'DBL_MAX', 'LDBL_MAX', 'FLT_MAX_EXP', 'DBL_MAX_EXP',
+            'LDBL_MAX_EXP', 'FLT_MIN', 'DBL_MIN', 'LDBL_MIN', 'FLT_MIN_EXP', 'DBL_MIN_EXP',
+            'LDBL_MIN_EXP', 'CHAR_BIT', 'CHAR_MAX', 'CHAR_MIN', 'SCHAR_MAX', 'SCHAR_MIN',
+            'UCHAR_MAX', 'SHRT_MAX', 'SHRT_MIN', 'USHRT_MAX', 'INT_MAX', 'INT_MIN',
+            'UINT_MAX', 'LONG_MAX', 'LONG_MIN', 'ULONG_MAX', 'HUGE_VAL', 'SIGABRT',
+            'SIGFPE', 'SIGILL', 'SIGINT', 'SIGSEGV', 'SIGTERM', 'SIG_DFL', 'SIG_ERR',
+            'SIG_IGN', 'BUFSIZ', 'EOF', 'FILENAME_MAX', 'FOPEN_MAX', 'L_tmpnam',
+            'SEEK_CUR', 'SEEK_END', 'SEEK_SET', 'TMP_MAX', 'stdin', 'stdout', 'stderr',
+            'EXIT_FAILURE', 'EXIT_SUCCESS', 'RAND_MAX', 'CLOCKS_PER_SEC',
+            // Mac-specific constants:
+            'kCFAllocatorDefault'
+            ),
+        3 => array(
+            'printf', 'fprintf', 'snprintf', 'sprintf', 'assert',
+            'isalnum', 'isalpha', 'isdigit', 'iscntrl', 'isgraph', 'islower', 'isprint',
+            'ispunct', 'isspace', 'isupper', 'isxdigit', 'tolower', 'toupper',
+            'exp', 'log', 'log10', 'pow', 'sqrt', 'ceil', 'floor', 'fabs', 'ldexp',
+            'frexp', 'modf', 'fmod', 'sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'atan2',
+            'sinh', 'cosh', 'tanh', 'setjmp', 'longjmp',
+            'va_start', 'va_arg', 'va_end', 'offsetof', 'sizeof', 'fopen', 'freopen',
+            'fflush', 'fclose', 'remove', 'rename', 'tmpfile', 'tmpname', 'setvbuf',
+            'setbuf', 'vfprintf', 'vprintf', 'vsprintf', 'fscanf', 'scanf', 'sscanf',
+            'fgetc', 'fgets', 'fputc', 'fputs', 'getc', 'getchar', 'gets', 'putc',
+            'putchar', 'puts', 'ungetc', 'fread', 'fwrite', 'fseek', 'ftell', 'rewind',
+            'fgetpos', 'fsetpos', 'clearerr', 'feof', 'ferror', 'perror', 'abs', 'labs',
+            'div', 'ldiv', 'atof', 'atoi', 'atol', 'strtod', 'strtol', 'strtoul', 'calloc',
+            'malloc', 'realloc', 'free', 'abort', 'exit', 'atexit', 'system', 'getenv',
+            'bsearch', 'qsort', 'rand', 'srand', 'strcpy', 'strncpy', 'strcat', 'strncat',
+            'strcmp', 'strncmp', 'strcoll', 'strchr', 'strrchr', 'strspn', 'strcspn',
+            'strpbrk', 'strstr', 'strlen', 'strerror', 'strtok', 'strxfrm', 'memcpy',
+            'memmove', 'memcmp', 'memchr', 'memset', 'clock', 'time', 'difftime', 'mktime',
+            'asctime', 'ctime', 'gmtime', 'localtime', 'strftime'
+            ),
+        4 => array(
+            'auto', 'char', 'const', 'double',  'float', 'int', 'long',
+            'register', 'short', 'signed', 'static', 'string', 'struct',
+            'typedef', 'union', 'unsigned', 'void', 'volatile', 'extern', 'jmp_buf',
+            'signal', 'raise', 'va_list', 'ptrdiff_t', 'size_t', 'FILE', 'fpos_t',
+            'div_t', 'ldiv_t', 'clock_t', 'time_t', 'tm',
+            // Mac-specific types:
+            'CFArrayRef', 'CFDictionaryRef', 'CFMutableDictionaryRef', 'CFBundleRef', 'CFSetRef', 'CFStringRef',
+            'CFURLRef', 'CFLocaleRef', 'CFDateFormatterRef', 'CFNumberFormatterRef', 'CFPropertyListRef',
+            'CFTreeRef', 'CFWriteStreamRef', 'CFCharacterSetRef', 'CFMutableStringRef', 'CFNotificationRef',
+            'CFReadStreamRef', 'CFNull', 'CFAllocatorRef', 'CFBagRef', 'CFBinaryHeapRef',
+            'CFBitVectorRef', 'CFBooleanRef', 'CFDataRef', 'CFDateRef', 'CFMachPortRef', 'CFMessagePortRef',
+            'CFMutableArrayRef', 'CFMutableBagRef', 'CFMutableBitVectorRef', 'CFMutableCharacterSetRef',
+            'CFMutableDataRef', 'CFMutableSetRef', 'CFNumberRef', 'CFPlugInRef', 'CFPlugInInstanceRef',
+            'CFRunLoopRef', 'CFRunLoopObserverRef', 'CFRunLoopSourceRef', 'CFRunLoopTimerRef', 'CFSocketRef',
+            'CFTimeZoneRef', 'CFTypeRef', 'CFUserNotificationRef', 'CFUUIDRef', 'CFXMLNodeRef', 'CFXMLParserRef',
+            'CFXMLTreeRef'
+            ),
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '{', '}', '[', ']', '=', '+', '-', '*', '/', '!', '%', '^', '&', ':'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0000ff;',
+            2 => 'color: #0000ff;',
+            3 => 'color: #0000dd;',
+            4 => 'color: #0000ff;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #ff0000;',
+            2 => 'color: #339900;',
+            'MULTI' => 'color: #ff0000; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;',
+            1 => 'color: #000099; font-weight: bold;',
+            2 => 'color: #660099; font-weight: bold;',
+            3 => 'color: #660099; font-weight: bold;',
+            4 => 'color: #660099; font-weight: bold;',
+            5 => 'color: #006699; font-weight: bold;',
+            'HARD' => '',
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000000;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #666666;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #0000dd;',
+            GESHI_NUMBER_BIN_PREFIX_0B => 'color: #208080;',
+            GESHI_NUMBER_OCT_PREFIX => 'color: #208080;',
+            GESHI_NUMBER_HEX_PREFIX => 'color: #208080;',
+            GESHI_NUMBER_FLT_SCI_SHORT => 'color:#800080;',
+            GESHI_NUMBER_FLT_SCI_ZERO => 'color:#800080;',
+            GESHI_NUMBER_FLT_NONSCI_F => 'color:#800080;',
+            GESHI_NUMBER_FLT_NONSCI => 'color:#800080;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #00eeff;',
+            2 => 'color: #00eeff;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000000;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => 'http://www.opengroup.org/onlinepubs/009695399/functions/{FNAMEL}.html',
+        4 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.',
+        2 => '::'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/caddcl.php b/examples/includes/geshi/geshi/caddcl.php
new file mode 100644 (file)
index 0000000..69d19dc
--- /dev/null
@@ -0,0 +1,126 @@
+<?php
+/*************************************************************************************
+ * caddcl.php
+ * ----------
+ * Author: Roberto Rossi (rsoftware@altervista.org)
+ * Copyright: (c) 2004 Roberto Rossi (http://rsoftware.altervista.org), Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/08/30
+ *
+ * CAD DCL (Dialog Control Language) language file for GeSHi.
+ *
+ * DCL for AutoCAD 12 or later and IntelliCAD all versions.
+ *
+ * CHANGES
+ * -------
+ * 2004/11/27 (1.0.1)
+ *  -  Added support for multiple object splitters
+ * 2004/1!/27 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'CAD DCL',
+    'COMMENT_SINGLE' => array(1 => '//'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'boxed_column','boxed_radio_column','boxed_radio_row','boxed_row',
+            'column','concatenation','button','dialog','edit_box','image','image_button',
+            'errtile','list_box','ok_cancel','ok_cancel_help','ok_cancel_help_errtile',
+            'ok_cancel_help_info','ok_only','paragraph','popup_list','radio_button',
+            'radio_column','radio_row','row','slider','spacer','spacer_0','spacer_1','text',
+            'text_part','toggle',
+            'action','alignment','allow_accept','aspect_ratio','big_increment',
+            'children_alignment','children_fixed_height',
+            'children_fixed_width','color',
+            'edit_limit','edit_width','fixed_height','fixed_width',
+            'height','initial_focus','is_cancel','is_default',
+            'is_enabled','is_tab_stop','is-bold','key','label','layout','list',
+            'max_value','min_value','mnemonic','multiple_select','password_char',
+            'small_increment','tabs','tab_truncate','value','width',
+            'false','true','left','right','centered','top','bottom',
+            'dialog_line','dialog_foreground','dialog_background',
+            'graphics_background','black','red','yellow','green','cyan',
+            'blue','magenta','whitegraphics_foreground',
+            'horizontal','vertical'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '{', '}', '[', ']', '=', '+', '-', '*', '/', '!', '%', '^', '&', ':'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/cadlisp.php b/examples/includes/geshi/geshi/cadlisp.php
new file mode 100644 (file)
index 0000000..9865840
--- /dev/null
@@ -0,0 +1,186 @@
+<?php
+/*************************************************************************************
+ * cadlisp.php
+ * -----------
+ * Author: Roberto Rossi (rsoftware@altervista.org)
+ * Copyright: (c) 2004 Roberto Rossi (http://rsoftware.altervista.org), Nigel McNie (http://qbnz.com/blog)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/08/30
+ *
+ * AutoCAD/IntelliCAD Lisp language file for GeSHi.
+ *
+ * For AutoCAD V.12..2005 and IntelliCAD all versions.
+ *
+ * CHANGES
+ * -------
+ * 2004/11/27 (1.0.1)
+ *  -  Added support for multiple object splitters
+ * 2004/10/27 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'CAD Lisp',
+    'COMMENT_SINGLE' => array(1 => ";"),
+    'COMMENT_MULTI' => array(";|" => "|;"),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'abs','acad_colordlg','acad_helpdlg','acad_strlsort','action_tile',
+            'add_list','alert','alloc','and','angle','angtof','angtos','append','apply',
+            'arx','arxload','arxunload','ascii','assoc','atan','atof','atoi','atom',
+            'atoms-family','autoarxload','autoload','Boole','boundp','caddr',
+            'cadr','car','cdr','chr','client_data_tile','close','command','cond',
+            'cons','cos','cvunit','defun','defun-q','defun-q-list-ref',
+            'defun-q-list-set','dictadd','dictnext','dictremove','dictrename',
+            'dictsearch','dimx_tile','dimy_tile','distance','distof','done_dialog',
+            'end_image','end_list','entdel','entget','entlast','entmake',
+            'entmakex','entmod','entnext','entsel','entupd','eq','equal','eval','exit',
+            'exp','expand','expt','fill_image','findfile','fix','float','foreach','function',
+            'gc','gcd','get_attr','get_tile','getangle','getcfg','getcname','getcorner',
+            'getdist','getenv','getfiled','getint','getkword','getorient','getpoint',
+            'getreal','getstring','getvar','graphscr','grclear','grdraw','grread','grtext',
+            'grvecs','handent','help','if','initdia','initget','inters','itoa','lambda','last',
+            'layoutlist','length','list','listp','load','load_dialog','log','logand','logior',
+            'lsh','mapcar','max','mem','member','menucmd','menugroup','min','minusp','mode_tile',
+            'namedobjdict','nentsel','nentselp','new_dialog','nil','not','nth','null',
+            'numberp','open','or','osnap','polar','prin1','princ','print','progn','prompt',
+            'quit','quote','read','read-char','read-line','redraw','regapp','rem','repeat',
+            'reverse','rtos','set','set_tile','setcfg','setenv','setfunhelp','setq','setvar',
+            'setview','sin','slide_image','snvalid','sqrt','ssadd','ssdel','ssget','ssgetfirst',
+            'sslength','ssmemb','ssname','ssnamex','sssetfirst','start_dialog','start_image',
+            'start_list','startapp','strcase','strcat','strlen','subst','substr','t','tablet',
+            'tblnext','tblobjname','tblsearch','term_dialog','terpri','textbox','textpage',
+            'textscr','trace','trans','type','unload_dialog','untrace','vector_image','ver',
+            'vports','wcmatch','while','write-char','write-line','xdroom','xdsize','zerop',
+            'vl-acad-defun','vl-acad-undefun','vl-arx-import','vlax-3D-point',
+            'vlax-add-cmd','vlax-create-object','vlax-curve-getArea',
+            'vlax-curve-getClosestPointTo','vlax-curve-getClosestPointToProjection',
+            'vlax-curve-getDistAtParam','vlax-curve-getDistAtPoint',
+            'vlax-curve-getEndParam','vlax-curve-getEndPoint',
+            'vlax-curve-getFirstDeriv','vlax-curve-getParamAtDist',
+            'vlax-curve-getParamAtPoint','vlax-curve-getPointAtDist',
+            'vlax-curve-getPointAtParam','vlax-curve-getSecondDeriv',
+            'vlax-curve-getStartParam','vlax-curve-getStartPoint',
+            'vlax-curve-isClosed','vlax-curve-isPeriodic','vlax-curve-isPlanar',
+            'vlax-dump-object','vlax-erased-p','vlax-for','vlax-get-acad-object',
+            'vlax-get-object','vlax-get-or-create-object','vlax-get-property',
+            'vlax-import-type-library','vlax-invoke-method','vlax-ldata-delete',
+            'vlax-ldata-get','vlax-ldata-list','vlax-ldata-put','vlax-ldata-test',
+            'vlax-make-safearray','vlax-make-variant','vlax-map-collection',
+            'vlax-method-applicable-p','vlax-object-released-p','vlax-product-key',
+            'vlax-property-available-p','vlax-put-property','vlax-read-enabled-p',
+            'vlax-release-object','vlax-remove-cmd','vlax-safearray-fill',
+            'vlax-safearray-get-dim','vlax-safearray-get-element',
+            'vlax-safearray-get-l-bound','vlax-safearray-get-u-bound',
+            'vlax-safearray-put-element','vlax-safearray-type','vlax-tmatrix',
+            'vlax-typeinfo-available-p','vlax-variant-change-type',
+            'vlax-variant-type','vlax-variant-value','vlax-write-enabled-p',
+            'vl-bb-ref','vl-bb-set','vl-catch-all-apply','vl-catch-all-error-message',
+            'vl-catch-all-error-p','vl-cmdf','vl-consp','vl-directory-files','vl-doc-export',
+            'vl-doc-import','vl-doc-ref','vl-doc-set','vl-every','vl-exit-with-error',
+            'vl-exit-with-value','vl-file-copy','vl-file-delete','vl-file-directory-p',
+            'vl-filename-base','vl-filename-directory','vl-filename-extension',
+            'vl-filename-mktemp','vl-file-rename','vl-file-size','vl-file-systime',
+            'vl-get-resource','vlisp-compile','vl-list-exported-functions',
+            'vl-list-length','vl-list-loaded-vlx','vl-load-all','vl-load-com',
+            'vl-load-reactors','vl-member-if','vl-member-if-not','vl-position',
+            'vl-prin1-to-string','vl-princ-to-string','vl-propagate','vlr-acdb-reactor',
+            'vlr-add','vlr-added-p','vlr-beep-reaction','vlr-command-reactor',
+            'vlr-current-reaction-name','vlr-data','vlr-data-set',
+            'vlr-deepclone-reactor','vlr-docmanager-reactor','vlr-dwg-reactor',
+            'vlr-dxf-reactor','vlr-editor-reactor','vl-registry-delete',
+            'vl-registry-descendents','vl-registry-read','vl-registry-write',
+            'vl-remove','vl-remove-if','vl-remove-if-not','vlr-insert-reactor',
+            'vlr-linker-reactor','vlr-lisp-reactor','vlr-miscellaneous-reactor',
+            'vlr-mouse-reactor','vlr-notification','vlr-object-reactor',
+            'vlr-owner-add','vlr-owner-remove','vlr-owners','vlr-pers','vlr-pers-list',
+            'vlr-pers-p','vlr-pers-release','vlr-reaction-names','vlr-reactions',
+            'vlr-reaction-set','vlr-reactors','vlr-remove','vlr-remove-all',
+            'vlr-set-notification','vlr-sysvar-reactor','vlr-toolbar-reactor',
+            'vlr-trace-reaction','vlr-type','vlr-types','vlr-undo-reactor',
+            'vlr-wblock-reactor','vlr-window-reactor','vlr-xref-reactor',
+            'vl-some','vl-sort','vl-sort-i','vl-string-elt','vl-string-left-trim',
+            'vl-string-mismatch','vl-string-position','vl-string-right-trim',
+            'vl-string-search','vl-string-subst','vl-string-translate','vl-string-trim',
+            'vl-symbol-name','vl-symbolp','vl-symbol-value','vl-unload-vlx','vl-vbaload',
+            'vl-vbarun','vl-vlx-loaded-p'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '{', '}', '[', ']', '!', '%', '^', '&', '/','+','-','*','=','<','>'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/cfdg.php b/examples/includes/geshi/geshi/cfdg.php
new file mode 100644 (file)
index 0000000..fc097ca
--- /dev/null
@@ -0,0 +1,124 @@
+<?php
+/*************************************************************************************
+ * cfdg.php
+ * --------
+ * Author: John Horigan <john@glyphic.com>
+ * Copyright: (c) 2006 John Horigan http://www.ozonehouse.com/john/
+ * Release Version: 1.0.8.3
+ * Date Started: 2006/03/11
+ *
+ * CFDG language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2006/03/11 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2006/03/11)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'CFDG',
+    'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            'include', 'startshape', 'rule', 'background'
+            ),
+        2 => array(
+            'SQUARE', 'CIRCLE', 'TRIANGLE',
+            ),
+        3 => array(
+            'b','brightness','h','hue','sat','saturation',
+            'a','alpha','x','y','z','s','size',
+            'r','rotate','f','flip','skew','xml_set_object'
+            )
+        ),
+    'SYMBOLS' => array(
+        '[', ']', '{', '}', '*', '|'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #717100;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #006666;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            2 => 'color: #808080; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006600;',
+            2 => 'color: #006600;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            0 => '',
+            1 => '',
+            2 => '',
+            3 => ''
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/cfm.php b/examples/includes/geshi/geshi/cfm.php
new file mode 100644 (file)
index 0000000..e900f46
--- /dev/null
@@ -0,0 +1,299 @@
+<?php
+/*************************************************************************************
+ * cfm.php
+ * -------
+ * Author: Diego
+ * Copyright: (c) 2006 Diego
+ * Release Version: 1.0.8.3
+ * Date Started: 2006/02/25
+ *
+ * ColdFusion language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2006/02/25 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2006/02/25)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'ColdFusion',
+    'COMMENT_SINGLE' => array(1 => '//'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        /* CFM Tags */
+        1 => array(
+            'cfabort', 'cfapplet', 'cfapplication', 'cfargument', 'cfassociate',
+            'cfbreak', 'cfcache', 'cfcase', 'cfcatch', 'cfchart', 'cfchartdata',
+            'cfchartseries', 'cfcol', 'cfcollection', 'cfcomponent',
+            'cfcontent', 'cfcookie', 'cfdefaultcase', 'cfdirectory',
+            'cfdocument', 'cfdocumentitem', 'cfdocumentsection', 'cfdump',
+            'cfelse', 'cfelseif', 'cferror', 'cfexecute', 'cfexit', 'cffile',
+            'cfflush', 'cfform', 'cfformgroup', 'cfformitem', 'cfftp',
+            'cffunction', 'cfgrid', 'cfgridcolumn', 'cfgridrow', 'cfgridupdate',
+            'cfheader', 'cfhtmlhead', 'cfhttp', 'cfhttpparam', 'cfif',
+            'cfimport', 'cfinclude', 'cfindex', 'cfinput', 'cfinsert',
+            'cfinvoke', 'cfinvokeargument', 'cfldap', 'cflocation', 'cflock',
+            'cflog', 'cflogin', 'cfloginuser', 'cflogout', 'cfloop', 'cfmail',
+            'cfmailparam', 'cfmailpart', 'cfmodule', 'cfNTauthenticate',
+            'cfobject', 'cfobjectcache', 'cfoutput', 'cfparam', 'cfpop',
+            'cfprocessingdirective', 'cfprocparam',
+            'cfprocresult', 'cfproperty', 'cfquery', 'cfqueryparam',
+            'cfregistry', 'cfreport', 'cfreportparam', 'cfrethrow', 'cfreturn',
+            'cfsavecontent', 'cfschedule', 'cfscript', 'cfsearch', 'cfselect',
+            'cfset', 'cfsetting', 'cfsilent', 'cfstoredproc',
+            'cfswitch', 'cftable', 'cftextarea', 'cfthrow', 'cftimer',
+            'cftrace', 'cftransaction', 'cftree', 'cftreeitem', 'cftry',
+            'cfupdate', 'cfwddx'
+            ),
+        /* HTML Tags */
+        2 => array(
+            'a', 'abbr', 'acronym', 'address', 'applet',
+
+            'base', 'basefont', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'b',
+
+            'caption', 'center', 'cite', 'code', 'colgroup', 'col',
+
+            'dd', 'del', 'dfn', 'dir', 'div', 'dl', 'dt',
+
+            'em',
+
+            'fieldset', 'font', 'form', 'frame', 'frameset',
+
+            'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'hr', 'html',
+
+            'iframe', 'ilayer', 'img', 'input', 'ins', 'isindex', 'i',
+
+            'kbd',
+
+            'label', 'legend', 'link', 'li',
+
+            'map', 'meta',
+
+            'noframes', 'noscript',
+
+            'object', 'ol', 'optgroup', 'option',
+
+            'param', 'pre', 'p',
+
+            'q',
+
+            'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'style', 'sub', 'sup', 's',
+
+            'table', 'tbody', 'td', 'textarea', 'text', 'tfoot', 'thead', 'th', 'title', 'tr', 'tt',
+
+            'ul', 'u',
+
+            'var',
+            ),
+        /* HTML attributes */
+        3 => array(
+            'abbr', 'accept-charset', 'accept', 'accesskey', 'action', 'align', 'alink', 'alt', 'archive', 'axis',
+            'background', 'bgcolor', 'border',
+            'cellpadding', 'cellspacing', 'char', 'charoff', 'charset', 'checked', 'cite', 'class', 'classid', 'clear', 'code', 'codebase', 'codetype', 'color', 'cols', 'colspan', 'compact', 'content', 'coords',
+            'data', 'datetime', 'declare', 'defer', 'dir', 'disabled',
+            'enctype',
+            'face', 'for', 'frame', 'frameborder',
+            'headers', 'height', 'href', 'hreflang', 'hspace', 'http-equiv',
+            'id', 'ismap',
+            'label', 'lang', 'language', 'link', 'longdesc',
+            'marginheight', 'marginwidth', 'maxlength', 'media', 'method', 'multiple',
+            'name', 'nohref', 'noresize', 'noshade', 'nowrap',
+            'object', 'onblur', 'onchange', 'onclick', 'ondblclick', 'onfocus', 'onkeydown', 'onkeypress', 'onkeyup', 'onload', 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onreset', 'onselect', 'onsubmit', 'onunload',
+            'profile', 'prompt',
+            'readonly', 'rel', 'rev', 'rowspan', 'rows', 'rules',
+            'scheme', 'scope', 'scrolling', 'selected', 'shape', 'size', 'span', 'src', 'standby', 'start', 'style', 'summary',
+            'tabindex', 'target', 'text', 'title', 'type',
+            'usemap',
+            'valign', 'value', 'valuetype', 'version', 'vlink', 'vspace',
+            'width'
+            ),
+        /* CFM Script delimeters */
+        4 => array(
+            'var', 'function', 'while', 'if','else'
+            ),
+        /* CFM Functions */
+        5 => array(
+            'Abs', 'GetFunctionList', 'LSTimeFormat','ACos','GetGatewayHelper','LTrim','AddSOAPRequestHeader','GetHttpRequestData',
+            'Max','AddSOAPResponseHeader','GetHttpTimeString','Mid','ArrayAppend','GetLocale','Min','ArrayAvg','GetLocaleDisplayName',
+            'Minute','ArrayClear','GetMetaData','Month','ArrayDeleteAt','GetMetricData','MonthAsString','ArrayInsertAt','GetPageContext',
+            'Now','ArrayIsEmpty','GetProfileSections','NumberFormat','ArrayLen','GetProfileString','ParagraphFormat','ArrayMax',
+            'GetLocalHostIP','ParseDateTime','ArrayMin','GetSOAPRequest','Pi','ArrayNew','GetSOAPRequestHeader','PreserveSingleQuotes',
+            'ArrayPrepend','GetSOAPResponse','Quarter','ArrayResize','GetSOAPResponseHeader','QueryAddColumn','ArraySet',
+            'GetTempDirectory','QueryAddRow','ArraySort','QueryNew','ArraySum','GetTempFile','QuerySetCell',
+            'ArraySwap','GetTickCount','QuotedValueList','ArrayToList','GetTimeZoneInfo','Rand','Asc','GetToken','Randomize',
+            'ASin','Hash','RandRange','Atn','Hour','REFind','BinaryDecode','HTMLCodeFormat','REFindNoCase','BinaryEncode',
+            'HTMLEditFormat','ReleaseComObject','BitAnd','IIf','RemoveChars','BitMaskClear','IncrementValue','RepeatString',
+            'BitMaskRead','InputBaseN','Replace','BitMaskSet','Insert','ReplaceList','BitNot','Int','ReplaceNoCase','BitOr',
+            'IsArray','REReplace','BitSHLN','IsBinary','REReplaceNoCase','BitSHRN','IsBoolean','Reverse','BitXor','IsCustomFunction',
+            'Right','Ceiling','IsDate','RJustify','CharsetDecode','IsDebugMode','Round','CharsetEncode','IsDefined','RTrim',
+            'Chr','IsLeapYear','Second','CJustify','IsLocalHost','SendGatewayMessage','Compare','IsNumeric','SetEncoding',
+            'CompareNoCase','IsNumericDate','SetLocale','Cos','IsObject','SetProfileString','CreateDate','IsQuery','SetVariable',
+            'CreateDateTime','IsSimpleValue','Sgn','CreateObject','IsSOAPRequest','Sin','CreateODBCDate','IsStruct','SpanExcluding',
+            'CreateODBCDateTime','IsUserInRole','SpanIncluding','CreateODBCTime','IsValid','Sqr','CreateTime','IsWDDX','StripCR',
+            'CreateTimeSpan','IsXML','StructAppend','CreateUUID','IsXmlAttribute','StructClear','DateAdd','IsXmlDoc','StructCopy',
+            'DateCompare','IsXmlElem','StructCount','DateConvert','IsXmlNode','StructDelete','DateDiff','IsXmlRoot','StructFind',
+            'DateFormat','JavaCast','StructFindKey','DatePart','JSStringFormat','StructFindValue','Day','LCase','StructGet',
+            'DayOfWeek','Left','StructInsert','DayOfWeekAsString','Len','StructIsEmpty','DayOfYear','ListAppend','StructKeyArray',
+            'DaysInMonth','ListChangeDelims','StructKeyExists','DaysInYear','ListContains','StructKeyList','DE','ListContainsNoCase',
+            'StructNew','DecimalFormat','ListDeleteAt','StructSort','DecrementValue','ListFind','StructUpdate','Decrypt','ListFindNoCase',
+            'Tan','DecryptBinary','ListFirst','TimeFormat','DeleteClientVariable','ListGetAt','ToBase64','DirectoryExists',
+            'ListInsertAt','ToBinary','DollarFormat','ListLast','ToScript','Duplicate','ListLen','ToString','Encrypt','ListPrepend',
+            'Trim','EncryptBinary','ListQualify','UCase','Evaluate','ListRest','URLDecode','Exp','ListSetAt','URLEncodedFormat',
+            'ExpandPath','ListSort','URLSessionFormat','FileExists','ListToArray','Val','Find','ListValueCount','ValueList',
+            'FindNoCase','ListValueCountNoCase','Week','FindOneOf','LJustify','Wrap','FirstDayOfMonth','Log','WriteOutput',
+            'Fix','Log10','XmlChildPos','FormatBaseN','LSCurrencyFormat','XmlElemNew','GetAuthUser','LSDateFormat','XmlFormat',
+            'GetBaseTagData','LSEuroCurrencyFormat','XmlGetNodeType','GetBaseTagList','LSIsCurrency','XmlNew','GetBaseTemplatePath',
+            'LSIsDate','XmlParse','GetClientVariablesList','LSIsNumeric','XmlSearch','GetCurrentTemplatePath','LSNumberFormat',
+            'XmlTransform','GetDirectoryFromPath','LSParseCurrency','XmlValidate','GetEncoding','LSParseDateTime','Year',
+            'GetException','LSParseEuroCurrency','YesNoFormat','GetFileFromPath','LSParseNumber'
+            ),
+        /* CFM Attributes */
+        6 => array(
+            'dbtype','connectstring','datasource','username','password','query','delimeter','description','required','hint','default','access','from','to','list','index'
+            ),
+        7 => array(
+            'EQ', 'GT', 'LT', 'GTE', 'LTE', 'IS', 'LIKE', 'NEQ'
+            )
+        ),
+    'SYMBOLS' => array(
+        '/', '=', '{', '}', '(', ')', '[', ']', '<', '>', '&'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        5 => false,
+        6 => false,
+        7 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #990000; font-weight: bold;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #0000FF;',
+            4 => 'color: #000000; font-weight: bold;',
+            5 => 'color: #0000FF;',
+            6 => 'color: #0000FF;',
+            7 => 'color: #0000FF;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #0000FF;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #009900;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #FF0000;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #0000FF;'
+            ),
+        'SCRIPT' => array(
+            0 => 'color: #808080; font-style: italic;',
+            1 => 'color: #00bbdd;',
+            2 => 'color: #0000FF;',
+            3 => 'color: #000099;',
+            4 => 'color: #333333;',
+            5 => 'color: #333333;'
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => 'http://december.com/html/4/element/{FNAMEL}.html',
+        3 => '',
+        4 => '',
+        5 => '',
+        6 => '',
+        7 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_ALWAYS,
+    'SCRIPT_DELIMITERS' => array(
+        0 => array(
+            '<!--' => '-->'
+            ),
+        1 => array(
+            '<!DOCTYPE' => '>'
+            ),
+        2 => "/(?!<#)(?:(?:##)*)(#)[a-zA-Z0-9_\.\(\)]+(#)/",
+        3 => array(
+            '<cfscript>' => '</cfscript>'
+            ),
+        4 => array(
+            '<' => '>'
+            ),
+        5 => '/((?!<!)<)(?:"[^"]*"|\'[^\']*\'|(?R)|[^">])+?(>)/si'
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        0 => false,
+        1 => false,
+        2 => true,
+        3 => true,
+        4 => true,
+        5 => true
+        ),
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            1 => array(
+                'DISALLOWED_BEFORE' => '(?<=&lt;|&lt;\/)',
+                'DISALLOWED_AFTER' => '(?=\s|\/|&gt;)',
+                ),
+            2 => array(
+                'DISALLOWED_BEFORE' => '(?<=&lt;|&lt;\/)',
+                'DISALLOWED_AFTER' => '(?=\s|\/|&gt;)',
+                ),
+            3 => array(
+                'DISALLOWED_BEFORE' => '(?<![a-zA-Z0-9\$_\|\#>|^])', // allow ; before keywords
+                'DISALLOWED_AFTER' => '(?![a-zA-Z0-9_\|%\\-])', // allow & after keywords
+                ),
+            7 => array(
+                'DISALLOWED_BEFORE' => '(?<![a-zA-Z0-9\$_\|\#>&|^])', // allow ; before keywords
+                'DISALLOWED_AFTER' => '(?![a-zA-Z0-9_\|%\\-])', // allow & after keywords
+                )
+            )
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/cil.php b/examples/includes/geshi/geshi/cil.php
new file mode 100644 (file)
index 0000000..41777d6
--- /dev/null
@@ -0,0 +1,196 @@
+<?php
+/*************************************************************************************
+ * cil.php
+ * --------
+ * Author: Marcus Griep (neoeinstein+GeSHi@gmail.com)
+ * Copyright: (c) 2007 Marcus Griep (http://www.xpdm.us)
+ * Release Version: 1.0.8.3
+ * Date Started: 2007/10/24
+ *
+ * CIL (Common Intermediate Language) language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2004/10/24 (1.0.8)
+ *  -  First Release
+ *
+ * TODO (updated 2007/10/24)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'CIL',
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'COMMENT_SINGLE' => array('//'),
+    'COMMENT_MULTI' => array(),
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(//Dotted
+            '.zeroinit', '.vtfixup', '.vtentry', '.vtable', '.ver', '.try', '.subsystem', '.size', '.set', '.removeon',
+            '.publickeytoken', '.publickey', '.property', '.permissionset', '.permission', '.pdirect', '.param', '.pack',
+            '.override', '.other', '.namespace', '.mresource', '.module', '.method', '.maxstack', '.manifestres', '.locals',
+            '.localized', '.locale', '.line', '.language', '.import', '.imagebase', '.hash', '.get', '.fire', '.file', '.field',
+            '.export', '.event', '.entrypoint', '.emitbyte', '.data', '.custom', '.culture', '.ctor', '.corflags', '.class',
+            '.cctor', '.assembly', '.addon'
+            ),
+        2 => array(//Attributes
+            'wrapper', 'with', 'winapi', 'virtual', 'vector', 'vararg', 'value', 'userdefined', 'unused', 'unmanagedexp',
+            'unmanaged', 'unicode', 'to', 'tls', 'thiscall', 'synchronized', 'struct', 'strict', 'storage', 'stdcall',
+            'static', 'specialname', 'special', 'serializable', 'sequential', 'sealed', 'runtime', 'rtspecialname', 'request',
+            'reqsecobj', 'reqrefuse', 'reqopt', 'reqmin', 'record', 'public', 'privatescope', 'private', 'preservesig',
+            'prejitgrant', 'prejitdeny', 'platformapi', 'pinvokeimpl', 'pinned', 'permitonly', 'out', 'optil', 'opt',
+            'notserialized', 'notremotable', 'not_in_gc_heap', 'noprocess', 'noncaslinkdemand', 'noncasinheritance',
+            'noncasdemand', 'nometadata', 'nomangle', 'nomachine', 'noinlining', 'noappdomain', 'newslot', 'nested', 'native',
+            'modreq', 'modopt', 'marshal', 'managed', 'literal', 'linkcheck', 'lcid', 'lasterr', 'internalcall', 'interface',
+            'instance', 'initonly', 'init', 'inheritcheck', 'in', 'import', 'implicitres', 'implicitcom', 'implements',
+            'illegal', 'il', 'hidebysig', 'handler', 'fromunmanaged', 'forwardref', 'fixed', 'finally', 'final', 'filter',
+            'filetime', 'field', 'fault', 'fastcall', 'famorassem', 'family', 'famandassem', 'extern', 'extends', 'explicit',
+            'error', 'enum', 'endmac', 'deny', 'demand', 'default', 'custom', 'compilercontrolled', 'clsid', 'class', 'cil',
+            'cf', 'cdecl', 'catch', 'beforefieldinit', 'autochar', 'auto', 'at', 'assert', 'assembly', 'as', 'any', 'ansi',
+            'alignment', 'algorithm', 'abstract'
+            ),
+        3 => array(//Types
+            'wchar', 'void', 'variant', 'unsigned', 'valuetype', 'typedref', 'tbstr', 'sysstring', 'syschar', 'string',
+            'streamed_object', 'stream', 'stored_object', 'safearray', 'objectref', 'object', 'nullref', 'method', 'lpwstr',
+            'lpvoid', 'lptstr', 'lpstruct', 'lpstr', 'iunknown', 'int64', 'int32', 'int16', 'int8', 'int', 'idispatch',
+            'hresult', 'float64', 'float32', 'float', 'decimal', 'date', 'currency', 'char', 'carray', 'byvalstr',
+            'bytearray', 'boxed', 'bool', 'blob_object', 'blob', 'array'
+            ),
+        4 => array(//Prefix
+            'volatile', 'unaligned', 'tail', 'readonly', 'no', 'constrained'
+            ),
+        5 => array(//Suffix
+            'un', 'u8', 'u4', 'u2', 'u1', 'u', 's', 'ref', 'r8', 'r4', 'm1', 'i8', 'i4', 'i2', 'i1', 'i'#, '.8', '.7', '.6', '.5', '.4', '.3', '.2', '.1', '.0'
+            ),
+        6 => array(//Base
+            'xor', 'switch', 'sub', 'stloc',
+            'stind', 'starg',
+            'shr', 'shl', 'ret', 'rem', 'pop', 'or', 'not', 'nop', 'neg', 'mul',
+            'localloc', 'leave', 'ldnull', 'ldloca',
+            'ldloc', 'ldind', 'ldftn', 'ldc', 'ldarga',
+            'ldarg', 'jmp', 'initblk', 'endfinally', 'endfilter',
+            'endfault', 'dup', 'div', 'cpblk', 'conv', 'clt', 'ckfinite', 'cgt', 'ceq', 'calli',
+            'call', 'brzero', 'brtrue', 'brnull', 'brinst',
+            'brfalse', 'break', 'br', 'bne', 'blt', 'ble', 'bgt', 'bge', 'beq', 'arglist',
+            'and', 'add'
+            ),
+        7 => array(//Object
+            'unbox.any', 'unbox', 'throw', 'stsfld', 'stobj', 'stfld', 'stelem', 'sizeof', 'rethrow', 'refanyval', 'refanytype', 'newobj',
+            'newarr', 'mkrefany', 'ldvirtftn', 'ldtoken', 'ldstr', 'ldsflda', 'ldsfld', 'ldobj', 'ldlen', 'ldflda', 'ldfld',
+            'ldelema', 'ldelem', 'isinst', 'initobj', 'cpobj', 'castclass',
+            'callvirt', 'callmostderived', 'box'
+            ),
+        8 => array(//Other
+            'prefixref', 'prefix7', 'prefix6', 'prefix5', 'prefix4', 'prefix3', 'prefix2', 'prefix1', 'prefix0'
+            ),
+        9 => array(//Literal
+            'true', 'null', 'false'
+            ),
+        10 => array(//Comment-like
+            '#line', '^THE_END^'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}', '!', '!!'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true,
+        5 => true,
+        6 => true,
+        7 => true,
+        8 => true,
+        9 => true,
+        10 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color:maroon;font-weight:bold;',
+            2 => 'color:blue;font-weight:bold;',
+            3 => 'color:purple;font-weight:bold;',
+            4 => 'color:teal;',
+            5 => 'color:blue;',
+            6 => 'color:blue;',
+            7 => 'color:blue;',
+            8 => 'color:blue;',
+            9 => 'color:00008B',
+            10 => 'color:gray'
+            ),
+        'COMMENTS' => array(
+            0 => 'color:gray;font-style:italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #008000; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #006400;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #008000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #00008B;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #000033;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #006400;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color:blue;'
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => '',
+        5 => '',
+        6 => '',
+        7 => '',
+        8 => '',
+        9 => '',
+        10 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '::'
+        ),
+    'REGEXPS' => array(
+        0 => '(?<=ldc\\.i4\\.)[0-8]|(?<=(?:ldarg|ldloc|stloc)\\.)[0-3]' # Pickup the opcodes that end with integers
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/cobol.php b/examples/includes/geshi/geshi/cobol.php
new file mode 100644 (file)
index 0000000..71f9828
--- /dev/null
@@ -0,0 +1,244 @@
+<?php
+/*************************************************************************************
+ * cobol.php
+ * ----------
+ * Author: BenBE (BenBE@omorphia.org)
+ * Copyright: (c) 2007-2008 BenBE (http://www.omorphia.de/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2007/07/02
+ *
+ * COBOL language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ *
+ * TODO (updated 2007/07/02)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'COBOL',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array(),
+    'COMMENT_REGEXP' => array(1 => '/^\*.*?$/m'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"', "'"),
+    'ESCAPE_CHAR' => '\\',
+    'NUMBERS' =>
+        GESHI_NUMBER_INT_BASIC |
+        GESHI_NUMBER_FLT_NONSCI |
+        GESHI_NUMBER_FLT_SCI_SHORT |
+        GESHI_NUMBER_FLT_SCI_ZERO,
+    'KEYWORDS' => array(
+        1 => array( //Compiler Directives
+            'ANSI', 'BLANK', 'NOBLANK', 'CALL-SHARED', 'CANCEL', 'NOCANCEL',
+            'CHECK', 'CODE', 'NOCODE', 'COLUMNS', 'COMPACT', 'NOCOMPACT',
+            'COMPILE', 'CONSULT', 'NOCONSULT', 'CROSSREF', 'NOCROSSREF',
+            'DIAGNOSE-74', 'NODIAGNOSE-74', 'DIAGNOSE-85', 'NODIAGNOSE-85',
+            'DIAGNOSEALL', 'NODIAGNOSEALL', 'ENDIF', 'ENDUNIT', 'ENV',
+            'ERRORFILE', 'ERRORS', 'FIPS', 'NOFIPS', 'FMAP', 'HEADING', 'HEAP',
+            'HIGHPIN', 'HIGHREQUESTERS', 'ICODE', 'NOICODE', 'IF', 'IFNOT',
+            'INNERLIST', 'NOINNERLIST', 'INSPECT', 'NOINSPECT', 'LARGEDATA',
+            'LD', 'LESS-CODE', 'LIBRARY', 'LINES', 'LIST', 'NOLIST', 'LMAP',
+            'NOLMAP', 'MAIN', 'MAP', 'NOMAP', 'NLD', 'NONSTOP', 'NON-SHARED',
+            'OPTIMIZE', 'PERFORM-TRACE', 'PORT', 'NOPORT', 'RESETTOG',
+            'RUNNABLE', 'RUNNAMED', 'SAVE', 'SAVEABEND', 'NOSAVEABEND',
+            'SEARCH', 'NOSEARCH', 'SECTION', 'SETTOG', 'SHARED', 'SHOWCOPY',
+            'NOSHOWCOPY', 'SHOWFILE', 'NOSHOWFILE', 'SOURCE', 'SQL', 'NOSQL',
+            'SQLMEM', 'SUBSET', 'SUBTYPE', 'SUPPRESS', 'NOSUPPRESS', 'SYMBOLS',
+            'NOSYMBOLS', 'SYNTAX', 'TANDEM', 'TRAP2', 'NOTRAP2', 'TRAP2-74',
+            'NOTRAP2-74', 'UL', 'WARN', 'NOWARN'
+            ),
+        2 => array( //Statement Keywords
+            'ACCEPT', 'ADD', 'TO', 'GIVING', 'CORRESPONDING', 'ALTER', 'CALL',
+            'CHECKPOINT', 'CLOSE', 'COMPUTE', 'CONTINUE', 'COPY',
+            'DELETE', 'DISPLAY', 'DIVIDE', 'INTO', 'REMAINDER', 'ENTER',
+            'COBOL', 'EVALUATE', 'EXIT', 'GO', 'INITIALIZE',
+            'TALLYING', 'REPLACING', 'CONVERTING', 'LOCKFILE', 'MERGE', 'MOVE',
+            'MULTIPLY', 'OPEN', 'PERFORM', 'TIMES',
+            'UNTIL', 'VARYING', 'RETURN',
+            ),
+        3 => array( //Reserved in some contexts
+            'ACCESS', 'ADDRESS', 'ADVANCING', 'AFTER', 'ALL',
+            'ALPHABET', 'ALPHABETIC', 'ALPHABETIC-LOWER', 'ALPHABETIC-UPPER',
+            'ALPHANUMERIC', 'ALPHANUMERIC-EDITED', 'ALSO', 'ALTERNATE',
+            'AND', 'ANY', 'APPROXIMATE', 'AREA', 'AREAS', 'ASCENDING', 'ASSIGN',
+            'AT', 'AUTHOR', 'BEFORE', 'BINARY', 'BLOCK', 'BOTTOM', 'BY',
+            'CD', 'CF', 'CH', 'CHARACTER', 'CHARACTERS',
+            'CHARACTER-SET', 'CLASS', 'CLOCK-UNITS',
+            'CODE-SET', 'COLLATING', 'COLUMN', 'COMMA',
+            'COMMON', 'COMMUNICATION', 'COMP', 'COMP-3', 'COMP-5',
+            'COMPUTATIONAL', 'COMPUTATIONAL-3', 'COMPUTATIONAL-5',
+            'CONFIGURATION', 'CONTAINS', 'CONTENT', 'CONTROL',
+            'CONTROLS', 'CORR', 'COUNT',
+            'CURRENCY', 'DATA', 'DATE', 'DATE-COMPILED', 'DATE-WRITTEN', 'DAY',
+            'DAY-OF-WEEK', 'DE', 'DEBUG-CONTENTS', 'DEBUG-ITEM', 'DEBUG-LINE',
+            'DEBUG-SUB-2', 'DEBUG-SUB-3', 'DEBUGGING', 'DECIMAL-POINT',
+            'DECLARATIVES', 'DEBUG-NAME', 'DEBUG-SUB-1', 'DELIMITED',
+            'DELIMITER', 'DEPENDING', 'DESCENDING', 'DESTINATION', 'DETAIL',
+            'DISABLE', 'DIVISION', 'DOWN', 'DUPLICATES',
+            'DYNAMIC', 'EGI', 'ELSE', 'EMI', 'ENABLE', 'END', 'END-ADD',
+            'END-COMPUTE', 'END-DELETE', 'END-DIVIDE', 'END-EVALUATE', 'END-IF',
+            'END-MULTIPLY', 'END-OF-PAGE', 'END-PERFORM', 'END-READ',
+            'END-RECEIVE', 'END-RETURN', 'END-REWRITE', 'END-SEARCH',
+            'END-START', 'END-STRING', 'END-SUBTRACT', 'END-UNSTRING',
+            'END-WRITE', 'EOP', 'EQUAL', 'ERROR', 'ESI',
+            'EVERY', 'EXCEPTION', 'EXCLUSIVE', 'EXTEND',
+            'EXTENDED-STORAGE', 'EXTERNAL', 'FALSE', 'FD', 'FILE',
+            'FILE-CONTROL', 'FILLER', 'FINAL', 'FIRST', 'FOOTING', 'FOR',
+            'FROM', 'FUNCTION', 'GENERATE', 'GENERIC', 'GLOBAL',
+            'GREATER', 'GROUP', 'GUARDIAN-ERR', 'HIGH-VALUE',
+            'HIGH-VALUES', 'I-O', 'I-O-CONTROL', 'IDENTIFICATION', 'IN',
+            'INDEX', 'INDEXED', 'INDICATE', 'INITIAL', 'INITIATE',
+            'INPUT', 'INPUT-OUTPUT', 'INSTALLATION',
+            'INVALID', 'IS', 'JUST', 'JUSTIFIED', 'KEY', 'LABEL', 'LAST',
+            'LEADING', 'LEFT', 'LESS', 'LIMIT', 'LIMITS', 'LINAGE',
+            'LINAGE-COUNTER', 'LINE', 'LINE-COUNTER', 'LINKAGE', 'LOCK',
+            'LOW-VALUE', 'LOW-VALUES', 'MEMORY', 'MESSAGE',
+            'MODE', 'MODULES', 'MULTIPLE', 'NATIVE',
+            'NEGATIVE', 'NEXT', 'NO', 'NOT', 'NULL', 'NULLS', 'NUMBER',
+            'NUMERIC', 'NUMERIC-EDITED', 'OBJECT-COMPUTER', 'OCCURS', 'OF',
+            'OFF', 'OMITTED', 'ON', 'OPTIONAL', 'OR', 'ORDER',
+            'ORGANIZATION', 'OTHER', 'OUTPUT', 'OVERFLOW', 'PACKED-DECIMAL',
+            'PADDING', 'PAGE', 'PAGE-COUNTER', 'PF', 'PH', 'PIC',
+            'PICTURE', 'PLUS', 'POINTER', 'POSITION', 'POSITIVE', 'PRINTING',
+            'PROCEDURE', 'PROCEDURES', 'PROCEED', 'PROGRAM', 'PROGRAM-ID',
+            'PROGRAM-STATUS', 'PROGRAM-STATUS-1', 'PROGRAM-STATUS-2', 'PROMPT',
+            'PROTECTED', 'PURGE', 'QUEUE', 'QUOTE', 'QUOTES', 'RD',
+            'RECEIVE', 'RECEIVE-CONTROL', 'RECORD', 'RECORDS',
+            'REDEFINES', 'REEL', 'REFERENCE', 'REFERENCES', 'RELATIVE',
+            'REMOVAL', 'RENAMES', 'REPLACE',
+            'REPLY', 'REPORT', 'REPORTING', 'REPORTS', 'RERUN',
+            'RESERVE', 'RESET', 'REVERSED', 'REWIND', 'REWRITE', 'RF',
+            'RH', 'RIGHT', 'ROUNDED', 'RUN', 'SAME', 'SD',
+            'SECURITY', 'SEGMENT', 'SEGMENT-LIMIT', 'SELECT', 'SEND',
+            'SENTENCE', 'SEPARATE', 'SEQUENCE', 'SEQUENTIAL', 'SET',
+            'SIGN', 'SIZE', 'SORT', 'SORT-MERGE', 'SOURCE-COMPUTER',
+            'SPACE', 'SPACES', 'SPECIAL-NAMES', 'STANDARD', 'STANDARD-1',
+            'STANDARD-2', 'START', 'STARTBACKUP', 'STATUS', 'STOP', 'STRING',
+            'SUB-QUEUE-1', 'SUB-QUEUE-2', 'SUB-QUEUE-3', 'SUBTRACT',
+            'SYMBOLIC', 'SYNC', 'SYNCDEPTH', 'SYNCHRONIZED',
+            'TABLE', 'TAL', 'TAPE', 'TERMINAL', 'TERMINATE', 'TEST',
+            'TEXT', 'THAN', 'THEN', 'THROUGH', 'THRU', 'TIME',
+            'TOP', 'TRAILING', 'TRUE', 'TYPE', 'UNIT', 'UNLOCK', 'UNLOCKFILE',
+            'UNLOCKRECORD', 'UNSTRING', 'UP', 'UPON', 'USAGE', 'USE',
+            'USING', 'VALUE', 'VALUES', 'WHEN', 'WITH', 'WORDS',
+            'WORKING-STORAGE', 'WRITE', 'ZERO', 'ZEROES'
+            ),
+        4 => array( //Standard functions
+            'ACOS', 'ANNUITY', 'ASIN', 'ATAN', 'CHAR', 'COS', 'CURRENT-DATE',
+            'DATE-OF-INTEGER', 'DAY-OF-INTEGER', 'FACTORIAL', 'INTEGER',
+            'INTEGER-OF-DATE', 'INTEGER-OF-DAY', 'INTEGER-PART', 'LENGTH',
+            'LOG', 'LOG10', 'LOWER-CASE', 'MAX', 'MEAN', 'MEDIAN', 'MIDRANGE',
+            'MIN', 'MOD', 'NUMVAL', 'NUMVAL-C', 'ORD', 'ORD-MAX', 'ORD-MIN',
+            'PRESENT-VALUE', 'RANDOM', 'RANGE', 'REM', 'REVERSE', 'SIN', 'SQRT',
+            'STANDARD-DEVIATION', 'SUM', 'TAN', 'UPPER-CASE', 'VARIANCE',
+            'WHEN-COMPILED'
+            ),
+        5 => array( //Privileged Built-in Functions
+            '#IN', '#OUT', '#TERM', '#TEMP', '#DYNAMIC', 'COBOL85^ARMTRAP',
+            'COBOL85^COMPLETION', 'COBOL_COMPLETION_', 'COBOL_CONTROL_',
+            'COBOL_GETENV_', 'COBOL_PUTENV_', 'COBOL85^RETURN^SORT^ERRORS',
+            'COBOL_RETURN_SORT_ERRORS_', 'COBOL85^REWIND^SEQUENTIAL',
+            'COBOL_REWIND_SEQUENTIAL_', 'COBOL85^SET^SORT^PARAM^TEXT',
+            'COBOL_SET_SORT_PARAM_TEXT_', 'COBOL85^SET^SORT^PARAM^VALUE',
+            'COBOL_SET_SORT_PARAM_VALUE_', 'COBOL_SET_MAX_RECORD_',
+            'COBOL_SETMODE_', 'COBOL85^SPECIAL^OPEN', 'COBOL_SPECIAL_OPEN_',
+            'COBOLASSIGN', 'COBOL_ASSIGN_', 'COBOLFILEINFO', 'COBOL_FILE_INFO_',
+            'COBOLSPOOLOPEN', 'CREATEPROCESS', 'ALTERPARAMTEXT',
+            'CHECKLOGICALNAME', 'CHECKMESSAGE', 'DELETEASSIGN', 'DELETEPARAM',
+            'DELETESTARTUP', 'GETASSIGNTEXT', 'GETASSIGNVALUE', 'GETBACKUPCPU',
+            'GETPARAMTEXT', 'GETSTARTUPTEXT', 'PUTASSIGNTEXT', 'PUTASSIGNVALUE',
+            'PUTPARAMTEXT', 'PUTSTARTUPTEXT'
+            )
+        ),
+    'SYMBOLS' => array(
+        //Avoid having - in identifiers marked as symbols
+        ' + ', ' - ', ' * ', ' / ', ' ** ',
+        '.', ',',
+        '=',
+        '(', ')', '[', ']'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        5 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000080; font-weight: bold;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #008000; font-weight: bold;',
+            4 => 'color: #000080;',
+            5 => 'color: #008000;',
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #a0a0a0; font-style: italic;',
+            'MULTI' => 'color: #a0a0a0; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #339933;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #993399;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #202020;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000066;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => '',
+        5 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4
+    );
+
+?>
diff --git a/examples/includes/geshi/geshi/cpp-qt.php b/examples/includes/geshi/geshi/cpp-qt.php
new file mode 100644 (file)
index 0000000..79ec3c6
--- /dev/null
@@ -0,0 +1,315 @@
+<?php
+/*************************************************************************************
+ * cpp.php
+ * -------
+ * Author: Iulian M
+ * Copyright: (c) 2006 Iulian M
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/09/27
+ *
+ * C++ (with QT extensions) language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *   -  Added description of extra language features (SF#1970248)
+ *
+ * TODO
+ * ----
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'C++ (QT)',
+    'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'COMMENT_REGEXP' => array(
+        //Multiline-continued single-line comments
+        1 => '/\/\/(?:\\\\\\\\|\\\\\\n|.)*$/m',
+        //Multiline-continued preprocessor define
+        2 => '/#(?:\\\\\\\\|\\\\\\n|.)*$/m'
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '',
+    'ESCAPE_REGEXP' => array(
+        //Simple Single Char Escapes
+        1 => "#\\\\[abfnrtv\\'\"?\n]#i",
+        //Hexadecimal Char Specs
+        2 => "#\\\\x[\da-fA-F]{2}#",
+        //Hexadecimal Char Specs
+        3 => "#\\\\u[\da-fA-F]{4}#",
+        //Hexadecimal Char Specs
+        4 => "#\\\\U[\da-fA-F]{8}#",
+        //Octal Char Specs
+        5 => "#\\\\[0-7]{1,3}#"
+        ),
+    'NUMBERS' =>
+        GESHI_NUMBER_INT_BASIC | GESHI_NUMBER_INT_CSTYLE | GESHI_NUMBER_BIN_PREFIX_0B |
+        GESHI_NUMBER_OCT_PREFIX | GESHI_NUMBER_HEX_PREFIX | GESHI_NUMBER_FLT_NONSCI |
+        GESHI_NUMBER_FLT_NONSCI_F | GESHI_NUMBER_FLT_SCI_SHORT | GESHI_NUMBER_FLT_SCI_ZERO,
+    'KEYWORDS' => array(
+        1 => array(
+            'case', 'continue', 'default', 'do', 'else', 'for', 'goto', 'if', 'return',
+            'switch', 'while', 'delete', 'new', 'this'
+            ),
+        2 => array(
+            'NULL', 'false', 'break', 'true', 'enum', 'errno', 'EDOM',
+            'ERANGE', 'FLT_RADIX', 'FLT_ROUNDS', 'FLT_DIG', 'DBL_DIG', 'LDBL_DIG',
+            'FLT_EPSILON', 'DBL_EPSILON', 'LDBL_EPSILON', 'FLT_MANT_DIG', 'DBL_MANT_DIG',
+            'LDBL_MANT_DIG', 'FLT_MAX', 'DBL_MAX', 'LDBL_MAX', 'FLT_MAX_EXP', 'DBL_MAX_EXP',
+            'LDBL_MAX_EXP', 'FLT_MIN', 'DBL_MIN', 'LDBL_MIN', 'FLT_MIN_EXP', 'DBL_MIN_EXP',
+            'LDBL_MIN_EXP', 'CHAR_BIT', 'CHAR_MAX', 'CHAR_MIN', 'SCHAR_MAX', 'SCHAR_MIN',
+            'UCHAR_MAX', 'SHRT_MAX', 'SHRT_MIN', 'USHRT_MAX', 'INT_MAX', 'INT_MIN',
+            'UINT_MAX', 'LONG_MAX', 'LONG_MIN', 'ULONG_MAX', 'HUGE_VAL', 'SIGABRT',
+            'SIGFPE', 'SIGILL', 'SIGINT', 'SIGSEGV', 'SIGTERM', 'SIG_DFL', 'SIG_ERR',
+            'SIG_IGN', 'BUFSIZ', 'EOF', 'FILENAME_MAX', 'FOPEN_MAX', 'L_tmpnam',
+            'SEEK_CUR', 'SEEK_END', 'SEEK_SET', 'TMP_MAX', 'stdin', 'stdout', 'stderr',
+            'EXIT_FAILURE', 'EXIT_SUCCESS', 'RAND_MAX', 'CLOCKS_PER_SEC',
+            'virtual', 'public', 'private', 'protected', 'template', 'using', 'namespace',
+            'try', 'catch', 'inline', 'dynamic_cast', 'const_cast', 'reinterpret_cast',
+            'static_cast', 'explicit', 'friend', 'wchar_t', 'typename', 'typeid', 'class' ,
+            'foreach','connect', 'Q_OBJECT' , 'slots' , 'signals'
+            ),
+        3 => array(
+            'cin', 'cerr', 'clog', 'cout',
+            'printf', 'fprintf', 'snprintf', 'sprintf', 'assert',
+            'isalnum', 'isalpha', 'isdigit', 'iscntrl', 'isgraph', 'islower', 'isprint',
+            'ispunct', 'isspace', 'isupper', 'isxdigit', 'tolower', 'toupper',
+            'exp', 'log', 'log10', 'pow', 'sqrt', 'ceil', 'floor', 'fabs', 'ldexp',
+            'frexp', 'modf', 'fmod', 'sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'atan2',
+            'sinh', 'cosh', 'tanh', 'setjmp', 'longjmp',
+            'va_start', 'va_arg', 'va_end', 'offsetof', 'sizeof', 'fopen', 'freopen',
+            'fflush', 'fclose', 'remove', 'rename', 'tmpfile', 'tmpname', 'setvbuf',
+            'setbuf', 'vfprintf', 'vprintf', 'vsprintf', 'fscanf', 'scanf', 'sscanf',
+            'fgetc', 'fgets', 'fputc', 'fputs', 'getc', 'getchar', 'gets', 'putc',
+            'putchar', 'puts', 'ungetc', 'fread', 'fwrite', 'fseek', 'ftell', 'rewind',
+            'fgetpos', 'fsetpos', 'clearerr', 'feof', 'ferror', 'perror', 'abs', 'labs',
+            'div', 'ldiv', 'atof', 'atoi', 'atol', 'strtod', 'strtol', 'strtoul', 'calloc',
+            'malloc', 'realloc', 'free', 'abort', 'exit', 'atexit', 'system', 'getenv',
+            'bsearch', 'qsort', 'rand', 'srand', 'strcpy', 'strncpy', 'strcat', 'strncat',
+            'strcmp', 'strncmp', 'strcoll', 'strchr', 'strrchr', 'strspn', 'strcspn',
+            'strpbrk', 'strstr', 'strlen', 'strerror', 'strtok', 'strxfrm', 'memcpy',
+            'memmove', 'memcmp', 'memchr', 'memset', 'clock', 'time', 'difftime', 'mktime',
+            'asctime', 'ctime', 'gmtime', 'localtime', 'strftime'
+            ),
+        4 => array(
+            'auto', 'bool', 'char', 'const', 'double', 'float', 'int', 'long', 'longint',
+            'register', 'short', 'shortint', 'signed', 'static', 'struct',
+            'typedef', 'union', 'unsigned', 'void', 'volatile', 'extern', 'jmp_buf',
+            'signal', 'raise', 'va_list', 'ptrdiff_t', 'size_t', 'FILE', 'fpos_t',
+            'div_t', 'ldiv_t', 'clock_t', 'time_t', 'tm',
+            ),
+        5 => array(
+            'QAbstractButton','QDir','QIntValidator','QRegExpValidator','QTabWidget','QAbstractEventDispatcher',
+            'QDirectPainter','QIODevice','QRegion','QTcpServer','QAbstractExtensionFactory','QDirModel',
+            'QItemDelegate','QResizeEvent','QTcpSocket','QAbstractExtensionManager','QDockWidget',
+            'QItemEditorCreatorBase','QResource','QTemporaryFile','QAbstractFileEngine','QDomAttr',
+            'QItemEditorFactory','QRubberBand','QTestEventList','QAbstractFileEngineHandler','QDomCDATASection',
+            'QItemSelection','QScreen','QTextBlock','QAbstractFormBuilder','QDomCharacterData','QItemSelectionModel',
+            'QScreenCursor','QTextBlockFormat','QAbstractGraphicsShapeItem','QDomComment','QItemSelectionRange',
+            'QScreenDriverFactory','QTextBlockGroup','QAbstractItemDelegate','QDomDocument','QKbdDriverFactory',
+            'QScreenDriverPlugin','QTextBlockUserData','QAbstractItemModel','QDomDocumentFragment','QKbdDriverPlugin',
+            'QScrollArea','QTextBrowser','QAbstractItemView','QDomDocumentType','QKeyEvent','QScrollBar',
+            'QTextCharFormat','QAbstractListModel','QDomElement','QKeySequence','QSemaphore','QTextCodec',
+            'QAbstractPrintDialog','QDomEntity','QLabel','QSessionManager','QTextCodecPlugin','QAbstractProxyModel',
+            'QDomEntityReference','QLatin1Char','QSet','QTextCursor','QAbstractScrollArea','QDomImplementation',
+            'QLatin1String','QSetIterator','QTextDecoder','QAbstractSlider','QDomNamedNodeMap','QLayout','QSettings',
+            'QTextDocument','QAbstractSocket','QDomNode','QLayoutItem','QSharedData','QTextDocumentFragment',
+            'QAbstractSpinBox','QDomNodeList','QLCDNumber','QSharedDataPointer','QTextEdit','QAbstractTableModel',
+            'QDomNotation','QLibrary','QShortcut','QTextEncoder','QAbstractTextDocumentLayout',
+            'QDomProcessingInstruction','QLibraryInfo','QShortcutEvent','QTextFormat','QAccessible','QDomText',
+            'QLine','QShowEvent','QTextFragment','QAccessibleBridge','QDoubleSpinBox','QLinearGradient',
+            'QSignalMapper','QTextFrame','QAccessibleBridgePlugin','QDoubleValidator','QLineEdit','QSignalSpy',
+            'QTextFrameFormat','QAccessibleEvent','QDrag','QLineF','QSize','QTextImageFormat','QAccessibleInterface',
+            'QDragEnterEvent','QLinkedList','QSizeF','QTextInlineObject','QAccessibleObject','QDragLeaveEvent',
+            'QLinkedListIterator','QSizeGrip','QTextLayout','QAccessiblePlugin','QDragMoveEvent','QLinuxFbScreen',
+            'QSizePolicy','QTextLength','QAccessibleWidget','QDropEvent','QList','QSlider','QTextLine','QAction',
+            'QDynamicPropertyChangeEvent','QListIterator','QSocketNotifier','QTextList','QActionEvent','QErrorMessage',
+            'QListView','QSortFilterProxyModel','QTextListFormat','QActionGroup','QEvent','QListWidget','QSound',
+            'QTextObject','QApplication','QEventLoop','QListWidgetItem','QSpacerItem','QTextOption','QAssistantClient',
+            'QExtensionFactory','QLocale','QSpinBox','QTextStream','QAxAggregated','QExtensionManager',
+            'QMacPasteboardMime','QSplashScreen','QTextTable','QAxBase','QFile','QMacStyle','QSplitter',
+            'QTextTableCell','QAxBindable','QFileDialog','QMainWindow','QSplitterHandle','QTextTableFormat',
+            'QAxFactory','QFileIconProvider','QMap','QSqlDatabase','QThread','QAxObject','QFileInfo','QMapIterator',
+            'QSqlDriver','QThreadStorage','QAxScript','QFileOpenEvent','QMatrix','QSqlDriverCreator','QTime',
+            'QAxScriptEngine','QFileSystemWatcher','QMenu','QSqlDriverCreatorBase','QTimeEdit','QAxScriptManager',
+            'QFlag','QMenuBar','QSqlDriverPlugin','QTimeLine','QAxWidget','QFlags','QMessageBox','QSqlError','QTimer',
+            'QBasicTimer','QFocusEvent','QMetaClassInfo','QSqlField','QTimerEvent','QBitArray','QFocusFrame',
+            'QMetaEnum','QSqlIndex','QToolBar','QBitmap','QFont','QMetaMethod','QSqlQuery','QToolBox','QBoxLayout',
+            'QFontComboBox','QMetaObject','QSqlQueryModel','QToolButton','QBrush','QFontDatabase','QMetaProperty',
+            'QSqlRecord','QToolTip','QBuffer','QFontDialog','QMetaType','QSqlRelation','QTransformedScreen',
+            'QButtonGroup','QFontInfo','QMimeData','QSqlRelationalDelegate','QTranslator','QByteArray','QFontMetrics',
+            'QMimeSource','QSqlRelationalTableModel','QTreeView','QByteArrayMatcher','QFontMetricsF','QModelIndex',
+            'QSqlResult','QTreeWidget','QCache','QFormBuilder','QMotifStyle','QSqlTableModel','QTreeWidgetItem',
+            'QCalendarWidget','QFrame','QMouseDriverFactory','QStack','QTreeWidgetItemIterator','QCDEStyle',
+            'QFSFileEngine','QMouseDriverPlugin','QStackedLayout','QUdpSocket','QChar','QFtp','QMouseEvent',
+            'QStackedWidget','QUiLoader','QCheckBox','QGenericArgument','QMoveEvent','QStandardItem','QUndoCommand',
+            'QChildEvent','QGenericReturnArgument','QMovie','QStandardItemEditorCreator','QUndoGroup',
+            'QCleanlooksStyle','QGLColormap','QMultiHash','QStandardItemModel','QUndoStack','QClipboard',
+            'QGLContext','QMultiMap','QStatusBar','QUndoView','QCloseEvent','QGLFormat','QMutableHashIterator',
+            'QStatusTipEvent','QUrl','QColor','QGLFramebufferObject','QMutableLinkedListIterator','QString',
+            'QUrlInfo','QColorDialog','QGLPixelBuffer','QMutableListIterator','QStringList','QUuid','QColormap',
+            'QGLWidget','QMutableMapIterator','QStringListModel','QValidator','QComboBox','QGradient',
+            'QMutableSetIterator','QStringMatcher','QVariant','QCommonStyle','QGraphicsEllipseItem',
+            'QMutableVectorIterator','QStyle','QVarLengthArray','QCompleter','QGraphicsItem','QMutex',
+            'QStyleFactory','QVBoxLayout','QConicalGradient','QGraphicsItemAnimation','QMutexLocker',
+            'QStyleHintReturn','QVector','QContextMenuEvent','QGraphicsItemGroup','QNetworkAddressEntry',
+            'QStyleHintReturnMask','QVectorIterator','QCopChannel','QGraphicsLineItem','QNetworkInterface',
+            'QStyleOption','QVFbScreen','QCoreApplication','QGraphicsPathItem','QNetworkProxy','QStyleOptionButton',
+            'QVNCScreen','QCursor','QGraphicsPixmapItem','QObject','QStyleOptionComboBox','QWaitCondition',
+            'QCustomRasterPaintDevice','QGraphicsPolygonItem','QObjectCleanupHandler','QStyleOptionComplex',
+            'QWhatsThis','QDataStream','QGraphicsRectItem','QPageSetupDialog','QStyleOptionDockWidget',
+            'QWhatsThisClickedEvent','QDataWidgetMapper','QGraphicsScene','QPaintDevice','QStyleOptionFocusRect',
+            'QWheelEvent','QDate','QGraphicsSceneContextMenuEvent','QPaintEngine','QStyleOptionFrame','QWidget',
+            'QDateEdit','QGraphicsSceneEvent','QPaintEngineState','QStyleOptionFrameV2','QWidgetAction','QDateTime',
+            'QGraphicsSceneHoverEvent','QPainter','QStyleOptionGraphicsItem','QWidgetItem','QDateTimeEdit',
+            'QGraphicsSceneMouseEvent','QPainterPath','QStyleOptionGroupBox','QWindowsMime','QDBusAbstractAdaptor',
+            'QGraphicsSceneWheelEvent','QPainterPathStroker','QStyleOptionHeader','QWindowsStyle',
+            'QDBusAbstractInterface','QGraphicsSimpleTextItem','QPaintEvent','QStyleOptionMenuItem',
+            'QWindowStateChangeEvent','QDBusArgument','QGraphicsSvgItem','QPair','QStyleOptionProgressBar',
+            'QWindowsXPStyle','QDBusConnection','QGraphicsTextItem','QPalette','QStyleOptionProgressBarV2',
+            'QWorkspace','QDBusConnectionInterface','QGraphicsView','QPen','QStyleOptionQ3DockWindow','QWriteLocker',
+            'QDBusError','QGridLayout','QPersistentModelIndex','QStyleOptionQ3ListView','QWSCalibratedMouseHandler',
+            'QDBusInterface','QGroupBox','QPicture','QStyleOptionQ3ListViewItem','QWSClient','QDBusMessage','QHash',
+            'QPictureFormatPlugin','QStyleOptionRubberBand','QWSEmbedWidget','QDBusObjectPath','QHashIterator',
+            'QPictureIO','QStyleOptionSizeGrip','QWSEvent','QDBusReply','QHBoxLayout','QPixmap','QStyleOptionSlider',
+            'QWSInputMethod','QDBusServer','QHeaderView','QPixmapCache','QStyleOptionSpinBox','QWSKeyboardHandler',
+            'QDBusSignature','QHelpEvent','QPlastiqueStyle','QStyleOptionTab','QWSMouseHandler','QDBusVariant',
+            'QHideEvent','QPluginLoader','QStyleOptionTabBarBase','QWSPointerCalibrationData','QDecoration',
+            'QHostAddress','QPoint','QStyleOptionTabV2','QWSScreenSaver','QDecorationFactory','QHostInfo','QPointer',
+            'QStyleOptionTabWidgetFrame','QWSServer','QDecorationPlugin','QHoverEvent','QPointF','QStyleOptionTitleBar',
+            'QWSTslibMouseHandler','QDesignerActionEditorInterface','QHttp','QPolygon','QStyleOptionToolBar','QWSWindow',
+            'QDesignerContainerExtension','QHttpHeader','QPolygonF','QStyleOptionToolBox','QWSWindowSurface',
+            'QDesignerCustomWidgetCollectionInterface','QHttpRequestHeader','QPrintDialog','QStyleOptionToolButton',
+            'QX11EmbedContainer','QDesignerCustomWidgetInterface','QHttpResponseHeader','QPrintEngine',
+            'QStyleOptionViewItem','QX11EmbedWidget','QDesignerFormEditorInterface','QIcon','QPrinter',
+            'QStyleOptionViewItemV2','QX11Info','QDesignerFormWindowCursorInterface','QIconDragEvent','QProcess',
+            'QStylePainter','QXmlAttributes','QDesignerFormWindowInterface','QIconEngine','QProgressBar',
+            'QStylePlugin','QXmlContentHandler','QDesignerFormWindowManagerInterface','QIconEnginePlugin',
+            'QProgressDialog','QSvgRenderer','QXmlDeclHandler','QDesignerMemberSheetExtension','QImage',
+            'QProxyModel','QSvgWidget','QXmlDefaultHandler','QDesignerObjectInspectorInterface','QImageIOHandler',
+            'QPushButton','QSyntaxHighlighter','QXmlDTDHandler','QDesignerPropertyEditorInterface','QImageIOPlugin',
+            'QQueue','QSysInfo','QXmlEntityResolver','QDesignerPropertySheetExtension','QImageReader','QRadialGradient',
+            'QSystemLocale','QXmlErrorHandler','QDesignerTaskMenuExtension','QImageWriter','QRadioButton',
+            'QSystemTrayIcon','QXmlInputSource','QDesignerWidgetBoxInterface','QInputContext','QRasterPaintEngine',
+            'QTabBar','QXmlLexicalHandler','QDesktopServices','QInputContextFactory','QReadLocker','QTabletEvent',
+            'QXmlLocator','QDesktopWidget','QInputContextPlugin','QReadWriteLock','QTableView','QXmlNamespaceSupport',
+            'QDial','QInputDialog','QRect','QTableWidget','QXmlParseException','QDialog','QInputEvent','QRectF',
+            'QTableWidgetItem','QXmlReader','QDialogButtonBox','QInputMethodEvent','QRegExp',
+            'QTableWidgetSelectionRange','QXmlSimpleReader'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '{', '}', '[', ']', '=', '+', '-', '*', '/', '!', '%', '^', '&', ':', ',', ';', '|', '<', '>'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true,
+        5 => true,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000000; font-weight:bold;',
+            2 => 'color: #0057AE;',
+            3 => 'color: #2B74C7;',
+            4 => 'color: #0057AE;',
+            5 => 'color: #22aadd;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #888888;',
+            2 => 'color: #006E28;',
+            'MULTI' => 'color: #888888; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;',
+            1 => 'color: #000099; font-weight: bold;',
+            2 => 'color: #660099; font-weight: bold;',
+            3 => 'color: #660099; font-weight: bold;',
+            4 => 'color: #660099; font-weight: bold;',
+            5 => 'color: #006699; font-weight: bold;',
+            'HARD' => '',
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #006E28;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #BF0303;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #B08000;',
+            GESHI_NUMBER_BIN_PREFIX_0B => 'color: #208080;',
+            GESHI_NUMBER_OCT_PREFIX => 'color: #208080;',
+            GESHI_NUMBER_HEX_PREFIX => 'color: #208080;',
+            GESHI_NUMBER_FLT_SCI_SHORT => 'color:#800080;',
+            GESHI_NUMBER_FLT_SCI_ZERO => 'color:#800080;',
+            GESHI_NUMBER_FLT_NONSCI_F => 'color:#800080;',
+            GESHI_NUMBER_FLT_NONSCI => 'color:#800080;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #2B74C7;',
+            2 => 'color: #2B74C7;',
+            3 => 'color: #2B74C7;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #006E28;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => '',
+        5 => 'http://doc.trolltech.com/latest/{FNAMEL}.html'
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.',
+        2 => '::',
+        3 => '-&gt;',
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4,
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            'DISALLOWED_BEFORE' => "(?<![a-zA-Z0-9\$_\|\#>|^])",
+            'DISALLOWED_AFTER' => "(?![a-zA-Z0-9_<\|%\\-])"
+        ),
+        'OOLANG' => array(
+            'MATCH_AFTER' => '~?[a-zA-Z][a-zA-Z0-9_]*',
+        )
+    )
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/cpp.php b/examples/includes/geshi/geshi/cpp.php
new file mode 100644 (file)
index 0000000..28b585d
--- /dev/null
@@ -0,0 +1,226 @@
+<?php
+/*************************************************************************************
+ * cpp.php
+ * -------
+ * Author: Dennis Bayer (Dennis.Bayer@mnifh-giessen.de)
+ * Contributors:
+ *  - M. Uli Kusterer (witness.of.teachtext@gmx.net)
+ *  - Jack Lloyd (lloyd@randombit.net)
+ * Copyright: (c) 2004 Dennis Bayer, Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/09/27
+ *
+ * C++ language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *  -  Added description of extra language features (SF#1970248)
+ * 2004/XX/XX (1.0.2)
+ *  -  Added several new keywords (Jack Lloyd)
+ * 2004/11/27 (1.0.1)
+ *  -  Added StdCLib function and constant names, changed color scheme to
+ *     a cleaner one. (M. Uli Kusterer)
+ *  -  Added support for multiple object splitters
+ * 2004/10/27 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'C++',
+    'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'COMMENT_REGEXP' => array(
+        //Multiline-continued single-line comments
+        1 => '/\/\/(?:\\\\\\\\|\\\\\\n|.)*$/m',
+        //Multiline-continued preprocessor define
+        2 => '/#(?:\\\\\\\\|\\\\\\n|.)*$/m'
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '',
+    'ESCAPE_REGEXP' => array(
+        //Simple Single Char Escapes
+        1 => "#\\\\[abfnrtv\\'\"?\n]#i",
+        //Hexadecimal Char Specs
+        2 => "#\\\\x[\da-fA-F]{2}#",
+        //Hexadecimal Char Specs
+        3 => "#\\\\u[\da-fA-F]{4}#",
+        //Hexadecimal Char Specs
+        4 => "#\\\\U[\da-fA-F]{8}#",
+        //Octal Char Specs
+        5 => "#\\\\[0-7]{1,3}#"
+        ),
+    'NUMBERS' =>
+        GESHI_NUMBER_INT_BASIC | GESHI_NUMBER_INT_CSTYLE | GESHI_NUMBER_BIN_PREFIX_0B |
+        GESHI_NUMBER_OCT_PREFIX | GESHI_NUMBER_HEX_PREFIX | GESHI_NUMBER_FLT_NONSCI |
+        GESHI_NUMBER_FLT_NONSCI_F | GESHI_NUMBER_FLT_SCI_SHORT | GESHI_NUMBER_FLT_SCI_ZERO,
+    'KEYWORDS' => array(
+        1 => array(
+            'break', 'case', 'continue', 'default', 'do', 'else', 'for', 'goto', 'if', 'return',
+            'switch', 'throw', 'while'
+            ),
+        2 => array(
+            'NULL', 'false', 'true', 'enum', 'errno', 'EDOM',
+            'ERANGE', 'FLT_RADIX', 'FLT_ROUNDS', 'FLT_DIG', 'DBL_DIG', 'LDBL_DIG',
+            'FLT_EPSILON', 'DBL_EPSILON', 'LDBL_EPSILON', 'FLT_MANT_DIG', 'DBL_MANT_DIG',
+            'LDBL_MANT_DIG', 'FLT_MAX', 'DBL_MAX', 'LDBL_MAX', 'FLT_MAX_EXP', 'DBL_MAX_EXP',
+            'LDBL_MAX_EXP', 'FLT_MIN', 'DBL_MIN', 'LDBL_MIN', 'FLT_MIN_EXP', 'DBL_MIN_EXP',
+            'LDBL_MIN_EXP', 'CHAR_BIT', 'CHAR_MAX', 'CHAR_MIN', 'SCHAR_MAX', 'SCHAR_MIN',
+            'UCHAR_MAX', 'SHRT_MAX', 'SHRT_MIN', 'USHRT_MAX', 'INT_MAX', 'INT_MIN',
+            'UINT_MAX', 'LONG_MAX', 'LONG_MIN', 'ULONG_MAX', 'HUGE_VAL', 'SIGABRT',
+            'SIGFPE', 'SIGILL', 'SIGINT', 'SIGSEGV', 'SIGTERM', 'SIG_DFL', 'SIG_ERR',
+            'SIG_IGN', 'BUFSIZ', 'EOF', 'FILENAME_MAX', 'FOPEN_MAX', 'L_tmpnam',
+            'SEEK_CUR', 'SEEK_END', 'SEEK_SET', 'TMP_MAX', 'stdin', 'stdout', 'stderr',
+            'EXIT_FAILURE', 'EXIT_SUCCESS', 'RAND_MAX', 'CLOCKS_PER_SEC',
+            'virtual', 'public', 'private', 'protected', 'template', 'using', 'namespace',
+            'try', 'catch', 'inline', 'dynamic_cast', 'const_cast', 'reinterpret_cast',
+            'static_cast', 'explicit', 'friend', 'wchar_t', 'typename', 'typeid', 'class'
+            ),
+        3 => array(
+            'cin', 'cerr', 'clog', 'cout', 'delete', 'new', 'this',
+            'printf', 'fprintf', 'snprintf', 'sprintf', 'assert',
+            'isalnum', 'isalpha', 'isdigit', 'iscntrl', 'isgraph', 'islower', 'isprint',
+            'ispunct', 'isspace', 'isupper', 'isxdigit', 'tolower', 'toupper',
+            'exp', 'log', 'log10', 'pow', 'sqrt', 'ceil', 'floor', 'fabs', 'ldexp',
+            'frexp', 'modf', 'fmod', 'sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'atan2',
+            'sinh', 'cosh', 'tanh', 'setjmp', 'longjmp',
+            'va_start', 'va_arg', 'va_end', 'offsetof', 'sizeof', 'fopen', 'freopen',
+            'fflush', 'fclose', 'remove', 'rename', 'tmpfile', 'tmpname', 'setvbuf',
+            'setbuf', 'vfprintf', 'vprintf', 'vsprintf', 'fscanf', 'scanf', 'sscanf',
+            'fgetc', 'fgets', 'fputc', 'fputs', 'getc', 'getchar', 'gets', 'putc',
+            'putchar', 'puts', 'ungetc', 'fread', 'fwrite', 'fseek', 'ftell', 'rewind',
+            'fgetpos', 'fsetpos', 'clearerr', 'feof', 'ferror', 'perror', 'abs', 'labs',
+            'div', 'ldiv', 'atof', 'atoi', 'atol', 'strtod', 'strtol', 'strtoul', 'calloc',
+            'malloc', 'realloc', 'free', 'abort', 'exit', 'atexit', 'system', 'getenv',
+            'bsearch', 'qsort', 'rand', 'srand', 'strcpy', 'strncpy', 'strcat', 'strncat',
+            'strcmp', 'strncmp', 'strcoll', 'strchr', 'strrchr', 'strspn', 'strcspn',
+            'strpbrk', 'strstr', 'strlen', 'strerror', 'strtok', 'strxfrm', 'memcpy',
+            'memmove', 'memcmp', 'memchr', 'memset', 'clock', 'time', 'difftime', 'mktime',
+            'asctime', 'ctime', 'gmtime', 'localtime', 'strftime'
+            ),
+        4 => array(
+            'auto', 'bool', 'char', 'const', 'double', 'float', 'int', 'long', 'longint',
+            'register', 'short', 'shortint', 'signed', 'static', 'struct',
+            'typedef', 'union', 'unsigned', 'void', 'volatile', 'extern', 'jmp_buf',
+            'signal', 'raise', 'va_list', 'ptrdiff_t', 'size_t', 'FILE', 'fpos_t',
+            'div_t', 'ldiv_t', 'clock_t', 'time_t', 'tm',
+            ),
+        ),
+    'SYMBOLS' => array(
+        0 => array('(', ')', '{', '}', '[', ']'),
+        1 => array('<', '>','='),
+        2 => array('+', '-', '*', '/', '%'),
+        3 => array('!', '^', '&', '|'),
+        4 => array('?', ':', ';')
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0000ff;',
+            2 => 'color: #0000ff;',
+            3 => 'color: #0000dd;',
+            4 => 'color: #0000ff;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #666666;',
+            2 => 'color: #339900;',
+            'MULTI' => 'color: #ff0000; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;',
+            1 => 'color: #000099; font-weight: bold;',
+            2 => 'color: #660099; font-weight: bold;',
+            3 => 'color: #660099; font-weight: bold;',
+            4 => 'color: #660099; font-weight: bold;',
+            5 => 'color: #006699; font-weight: bold;',
+            'HARD' => '',
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #008000;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #FF0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #0000dd;',
+            GESHI_NUMBER_BIN_PREFIX_0B => 'color: #208080;',
+            GESHI_NUMBER_OCT_PREFIX => 'color: #208080;',
+            GESHI_NUMBER_HEX_PREFIX => 'color: #208080;',
+            GESHI_NUMBER_FLT_SCI_SHORT => 'color:#800080;',
+            GESHI_NUMBER_FLT_SCI_ZERO => 'color:#800080;',
+            GESHI_NUMBER_FLT_NONSCI_F => 'color:#800080;',
+            GESHI_NUMBER_FLT_NONSCI => 'color:#800080;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #007788;',
+            2 => 'color: #007788;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #008000;',
+            1 => 'color: #000080;',
+            2 => 'color: #000040;',
+            3 => 'color: #000040;',
+            4 => 'color: #008080;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.',
+        2 => '::'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4,
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            'DISALLOWED_BEFORE' => "(?<![a-zA-Z0-9\$_\|\#])",
+            'DISALLOWED_AFTER' => "(?![a-zA-Z0-9_\|%\\-])"
+        )
+    )
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/csharp.php b/examples/includes/geshi/geshi/csharp.php
new file mode 100644 (file)
index 0000000..2d79ee2
--- /dev/null
@@ -0,0 +1,249 @@
+<?php
+/*************************************************************************************
+ * csharp.php
+ * ----------
+ * Author: Alan Juden (alan@judenware.org)
+ * Copyright: (c) 2004 Alan Juden, Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/06/04
+ *
+ * C# language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/25 (1.0.7.22)
+ *   -  Added highlighting of using and namespace directives as non-OOP
+ * 2005/01/05 (1.0.1)
+ *  -  Used hardquote support for @"..." strings (Cliff Stanford)
+ * 2004/11/27 (1.0.0)
+ *  -  Initial release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'C#',
+    'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'COMMENT_REGEXP' => array(
+        //Using and Namespace directives (basic support)
+        //Please note that the alias syntax for using is not supported
+        3 => '/(?:(?<=using[\\n\\s])|(?<=namespace[\\n\\s]))[\\n\\s]*([a-zA-Z0-9_]+\\.)*[a-zA-Z0-9_]+[\n\s]*(?=[;=])/i'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'HARDQUOTE' => array('@"', '"'),
+    'HARDESCAPE' => array('""'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'as', 'auto', 'base', 'break', 'case', 'catch', 'const', 'continue',
+            'default', 'do', 'else', 'event', 'explicit', 'extern', 'false',
+            'finally', 'fixed', 'for', 'foreach', 'goto', 'if', 'implicit',
+            'in', 'internal', 'lock', 'namespace', 'null', 'operator', 'out',
+            'override', 'params', 'partial', 'private', 'protected', 'public',
+            'readonly', 'ref', 'return', 'sealed', 'stackalloc', 'static',
+            'switch', 'this', 'throw', 'true', 'try', 'unsafe', 'using',
+            'virtual', 'void', 'while'
+            ),
+        2 => array(
+            '#elif', '#endif', '#endregion', '#else', '#error', '#define', '#if',
+            '#line', '#region', '#undef', '#warning'
+            ),
+        3 => array(
+            'checked', 'is', 'new', 'sizeof', 'typeof', 'unchecked'
+            ),
+        4 => array(
+            'bool', 'byte', 'char', 'class', 'decimal', 'delegate', 'double',
+            'enum', 'float', 'int', 'interface', 'long', 'object', 'sbyte',
+            'short', 'string', 'struct', 'uint', 'ulong', 'ushort'
+            ),
+        5 => array(
+            'Microsoft.Win32',
+            'System',
+            'System.CodeDOM',
+            'System.CodeDOM.Compiler',
+            'System.Collections',
+            'System.Collections.Bases',
+            'System.ComponentModel',
+            'System.ComponentModel.Design',
+            'System.ComponentModel.Design.CodeModel',
+            'System.Configuration',
+            'System.Configuration.Assemblies',
+            'System.Configuration.Core',
+            'System.Configuration.Install',
+            'System.Configuration.Interceptors',
+            'System.Configuration.Schema',
+            'System.Configuration.Web',
+            'System.Core',
+            'System.Data',
+            'System.Data.ADO',
+            'System.Data.Design',
+            'System.Data.Internal',
+            'System.Data.SQL',
+            'System.Data.SQLTypes',
+            'System.Data.XML',
+            'System.Data.XML.DOM',
+            'System.Data.XML.XPath',
+            'System.Data.XML.XSLT',
+            'System.Diagnostics',
+            'System.Diagnostics.SymbolStore',
+            'System.DirectoryServices',
+            'System.Drawing',
+            'System.Drawing.Design',
+            'System.Drawing.Drawing2D',
+            'System.Drawing.Imaging',
+            'System.Drawing.Printing',
+            'System.Drawing.Text',
+            'System.Globalization',
+            'System.IO',
+            'System.IO.IsolatedStorage',
+            'System.Messaging',
+            'System.Net',
+            'System.Net.Sockets',
+            'System.NewXml',
+            'System.NewXml.XPath',
+            'System.NewXml.Xsl',
+            'System.Reflection',
+            'System.Reflection.Emit',
+            'System.Resources',
+            'System.Runtime.InteropServices',
+            'System.Runtime.InteropServices.Expando',
+            'System.Runtime.Remoting',
+            'System.Runtime.Serialization',
+            'System.Runtime.Serialization.Formatters',
+            'System.Runtime.Serialization.Formatters.Binary',
+            'System.Security',
+            'System.Security.Cryptography',
+            'System.Security.Cryptography.X509Certificates',
+            'System.Security.Permissions',
+            'System.Security.Policy',
+            'System.Security.Principal',
+            'System.ServiceProcess',
+            'System.Text',
+            'System.Text.RegularExpressions',
+            'System.Threading',
+            'System.Timers',
+            'System.Web',
+            'System.Web.Caching',
+            'System.Web.Configuration',
+            'System.Web.Security',
+            'System.Web.Services',
+            'System.Web.Services.Description',
+            'System.Web.Services.Discovery',
+            'System.Web.Services.Protocols',
+            'System.Web.UI',
+            'System.Web.UI.Design',
+            'System.Web.UI.Design.WebControls',
+            'System.Web.UI.Design.WebControls.ListControls',
+            'System.Web.UI.HtmlControls',
+            'System.Web.UI.WebControls',
+            'System.WinForms',
+            'System.WinForms.ComponentModel',
+            'System.WinForms.Design',
+            'System.Xml',
+            'System.Xml.Serialization',
+            'System.Xml.Serialization.Code',
+            'System.Xml.Serialization.Schema'
+            ),
+        ),
+    'SYMBOLS' => array(
+        '+', '-', '*', '?', '=', '/', '%', '&', '>', '<', '^', '!', ':', ';',
+        '(', ')', '{', '}', '[', ']', '|'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        5 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0600FF;',
+            2 => 'color: #FF8000; font-weight: bold;',
+            3 => 'color: #008000;',
+            4 => 'color: #FF0000;',
+            5 => 'color: #000000;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #008080; font-style: italic;',
+            2 => 'color: #008080;',
+            3 => 'color: #008080;',
+            'MULTI' => 'color: #008080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #008080; font-weight: bold;',
+            'HARD' => 'color: #008080; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000000;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #666666;',
+            'HARD' => 'color: #666666;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #FF0000;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #0000FF;',
+            2 => 'color: #0000FF;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #008000;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => 'http://www.google.com/search?q={FNAMEL}+msdn.microsoft.com',
+        4 => '',
+        5 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.',
+        2 => '::'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4,
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            'DISALLOWED_BEFORE' => "(?<![a-zA-Z0-9\$_\|\#>|^])",
+            'DISALLOWED_AFTER' => "(?![a-zA-Z0-9_<\|%\\-])"
+        )
+    )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/css.php b/examples/includes/geshi/geshi/css.php
new file mode 100644 (file)
index 0000000..0080325
--- /dev/null
@@ -0,0 +1,212 @@
+<?php
+/*************************************************************************************
+ * css.php
+ * -------
+ * Author: Nigel McNie (nigel@geshi.org)
+ * Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/06/18
+ *
+ * CSS language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *  -  Added description of extra language features (SF#1970248)
+ * 2004/11/27 (1.0.3)
+ *  -  Added support for multiple object splitters
+ * 2004/10/27 (1.0.2)
+ *   -  Changed regexps to catch "-" symbols
+ *   -  Added support for URLs
+ * 2004/08/05 (1.0.1)
+ *   -  Added support for symbols
+ * 2004/07/14 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ * * Improve or drop regexps for class/id/psuedoclass highlighting
+ * * Re-look at keywords - possibly to make several CSS language
+ *   files, all with different versions of CSS in them
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'CSS',
+    'COMMENT_SINGLE' => array(1 => '@'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'COMMENT_REGEXP' => array(
+        2 => "/(?<=\\()\\s*(?:(?:[a-z0-9]+?:\\/\\/)?[a-z0-9_\\-\\.\\/:]+?)?[a-z]+?\\.[a-z]+?(\\?[^\)]+?)?\\s*?(?=\\))/i"
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"', "'"),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'aqua', 'azimuth', 'background-attachment', 'background-color',
+            'background-image', 'background-position', 'background-repeat',
+            'background', 'black', 'blue', 'border-bottom-color',
+            'border-bottom-style', 'border-bottom-width', 'border-left-color',
+            'border-left-style', 'border-left-width', 'border-right',
+            'border-right-color', 'border-right-style', 'border-right-width',
+            'border-top-color', 'border-top-style',
+            'border-top-width','border-bottom', 'border-collapse',
+            'border-left', 'border-width', 'border-color', 'border-spacing',
+            'border-style', 'border-top', 'border', 'caption-side', 'clear',
+            'clip', 'color', 'content', 'counter-increment', 'counter-reset',
+            'cue-after', 'cue-before', 'cue', 'cursor', 'direction', 'display',
+            'elevation', 'empty-cells', 'float', 'font-family', 'font-size',
+            'font-size-adjust', 'font-stretch', 'font-style', 'font-variant',
+            'font-weight', 'font', 'line-height', 'letter-spacing',
+            'list-style', 'list-style-image', 'list-style-position',
+            'list-style-type', 'margin-bottom', 'margin-left', 'margin-right',
+            'margin-top', 'margin', 'marker-offset', 'marks', 'max-height',
+            'max-width', 'min-height', 'min-width', 'orphans', 'outline',
+            'outline-color', 'outline-style', 'outline-width', 'overflow',
+            'padding-bottom', 'padding-left', 'padding-right', 'padding-top',
+            'padding', 'page', 'page-break-after', 'page-break-before',
+            'page-break-inside', 'pause-after', 'pause-before', 'pause',
+            'pitch', 'pitch-range', 'play-during', 'position', 'quotes',
+            'richness', 'right', 'size', 'speak-header', 'speak-numeral',
+            'speak-punctuation', 'speak', 'speech-rate', 'stress',
+            'table-layout', 'text-align', 'text-decoration', 'text-indent',
+            'text-shadow', 'text-transform', 'top', 'unicode-bidi',
+            'vertical-align', 'visibility', 'voice-family', 'volume',
+            'white-space', 'widows', 'width', 'word-spacing', 'z-index',
+            'bottom', 'left', 'height'
+            ),
+        2 => array(
+            'above', 'absolute', 'always', 'armenian', 'aural', 'auto',
+            'avoid', 'baseline', 'behind', 'below', 'bidi-override', 'blink',
+            'block', 'bold', 'bolder', 'both', 'capitalize', 'center-left',
+            'center-right', 'center', 'circle', 'cjk-ideographic',
+            'close-quote', 'collapse', 'condensed', 'continuous', 'crop',
+            'crosshair', 'cross', 'cursive', 'dashed', 'decimal-leading-zero',
+            'decimal', 'default', 'digits', 'disc', 'dotted', 'double',
+            'e-resize', 'embed', 'extra-condensed', 'extra-expanded',
+            'expanded', 'fantasy', 'far-left', 'far-right', 'faster', 'fast',
+            'fixed', 'fuchsia', 'georgian', 'gray', 'green', 'groove',
+            'hebrew', 'help', 'hidden', 'hide', 'higher', 'high',
+            'hiragana-iroha', 'hiragana', 'icon', 'inherit', 'inline-table',
+            'inline', 'inset', 'inside', 'invert', 'italic', 'justify',
+            'katakana-iroha', 'katakana', 'landscape', 'larger', 'large',
+            'left-side', 'leftwards', 'level', 'lighter', 'lime',
+            'line-through', 'list-item', 'loud', 'lower-alpha', 'lower-greek',
+            'lower-roman', 'lowercase', 'ltr', 'lower', 'low', 'maroon',
+            'medium', 'message-box', 'middle', 'mix', 'monospace', 'n-resize',
+            'narrower', 'navy', 'ne-resize', 'no-close-quote',
+            'no-open-quote', 'no-repeat', 'none', 'normal', 'nowrap',
+            'nw-resize', 'oblique', 'olive', 'once', 'open-quote', 'outset',
+            'outside', 'overline', 'pointer', 'portrait', 'purple', 'px',
+            'red', 'relative', 'repeat-x', 'repeat-y', 'repeat', 'rgb',
+            'ridge', 'right-side', 'rightwards', 's-resize', 'sans-serif',
+            'scroll', 'se-resize', 'semi-condensed', 'semi-expanded',
+            'separate', 'serif', 'show', 'silent', 'silver', 'slow', 'slower',
+            'small-caps', 'small-caption', 'smaller', 'soft', 'solid',
+            'spell-out', 'square', 'static', 'status-bar', 'super',
+            'sw-resize', 'table-caption', 'table-cell', 'table-column',
+            'table-column-group', 'table-footer-group', 'table-header-group',
+            'table-row', 'table-row-group', 'teal', 'text', 'text-bottom',
+            'text-top', 'thick', 'thin', 'transparent', 'ultra-condensed',
+            'ultra-expanded', 'underline', 'upper-alpha', 'upper-latin',
+            'upper-roman', 'uppercase', 'url', 'visible', 'w-resize', 'wait',
+            'white', 'wider', 'x-fast', 'x-high', 'x-large', 'x-loud',
+            'x-low', 'x-small', 'x-soft', 'xx-large', 'xx-small', 'yellow',
+            'yes'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '{', '}', ':', ';',
+        '>', '+', '*', ',', '^', '='
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000000; font-weight: bold;',
+            2 => 'color: #993333;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #a1a100;',
+            2 => 'color: #ff0000; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #00AA00;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #00AA00;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #cc00cc;',
+            1 => 'color: #6666ff;',
+            2 => 'color: #3333ff;',
+            3 => 'color: #933;'
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        //DOM Node ID
+        0 => '\#[a-zA-Z0-9\-_]+(?:\\\\:[a-zA-Z0-9\-_]+)*',
+        //CSS classname
+        1 => '\.(?!\d)[a-zA-Z0-9\-_]+(?:\\\\:[a-zA-Z0-9\-_]+)*\b(?=[\{\.#\s,:].|<\|)',
+        //CSS Pseudo classes
+        //note: & is needed for &gt; (i.e. > )
+        2 => '(?<!\\\\):(?!\d)[a-zA-Z0-9\-]+\b(?:\s*(?=[\{\.#a-zA-Z,:+*&](.|\n)|<\|))',
+        //Measurements
+        3 => '[+\-]?(\d+|(\d*\.\d+))(em|ex|pt|px|cm|in|%)',
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4,
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            'DISALLOWED_AFTER' => '(?![a-zA-Z0-9_\|%\\-&\.])'
+        )
+    )
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/d.php b/examples/includes/geshi/geshi/d.php
new file mode 100644 (file)
index 0000000..9711a6e
--- /dev/null
@@ -0,0 +1,272 @@
+<?php
+/*************************************************************************************
+ * d.php
+ * -----
+ * Author: Thomas Kuehne (thomas@kuehne.cn)
+ * Copyright: (c) 2005 Thomas Kuehne (http://thomas.kuehne.cn/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2005/04/22
+ *
+ * D language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2005/04/22 (0.0.2)
+ *  -  added _d_* and sizeof/ptrdiff_t
+ * 2005/04/20 (0.0.1)
+ *  -  First release
+ *
+ * TODO (updated 2005/04/22)
+ * -------------------------
+ * * nested comments
+ * * correct handling of r"" and ``
+ * * correct handling of ... and ..
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'D',
+    'COMMENT_SINGLE' => array(2 => '///', 1 => '//'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'COMMENT_REGEXP' => array(
+        // doxygen comments
+        3 => '#/\*\*(?![\*\/]).*\*/#sU',
+        // raw strings
+        4 => '#r"[^"]*"#s',
+        // Script Style interpreter comment
+        5 => "/\A#!(?=\\/).*?$/m"
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"', "'"),
+    'ESCAPE_CHAR' => '',
+    'ESCAPE_REGEXP' => array(
+        //Simple Single Char Escapes
+        1 => "#\\\\[abfnrtv\\'\"?\n\\\\]#i",
+        //Hexadecimal Char Specs
+        2 => "#\\\\x[\da-fA-F]{2}#",
+        //Hexadecimal Char Specs
+        3 => "#\\\\u[\da-fA-F]{4}#",
+        //Hexadecimal Char Specs
+        4 => "#\\\\U[\da-fA-F]{8}#",
+        //Octal Char Specs
+        5 => "#\\\\[0-7]{1,3}#",
+        //Named entity escapes
+        /*6 => "#\\\\&(?:quot|amp|lt|gt|OElig|oelig|Scaron|scaron|Yuml|circ|tilde|".
+            "ensp|emsp|thinsp|zwnj|zwj|lrm|rlm|ndash|mdash|lsquo|rsquo|sbquo|".
+            "ldquo|rdquo|bdquo|dagger|Dagger|permil|lsaquo|rsaquo|euro|nbsp|".
+            "iexcl|cent|pound|curren|yen|brvbar|sect|uml|copy|ordf|laquo|not|".
+            "shy|reg|macr|deg|plusmn|sup2|sup3|acute|micro|para|middot|cedil|".
+            "sup1|ordm|raquo|frac14|frac12|frac34|iquest|Agrave|Aacute|Acirc|".
+            "Atilde|Auml|Aring|AElig|Ccedil|Egrave|Eacute|Ecirc|Euml|Igrave|".
+            "Iacute|Icirc|Iuml|ETH|Ntilde|Ograve|Oacute|Ocirc|Otilde|Ouml|".
+            "times|Oslash|Ugrave|Uacute|Ucirc|Uuml|Yacute|THORN|szlig|agrave|".
+            "aacute|acirc|atilde|auml|aring|aelig|ccedil|egrave|eacute|ecirc|".
+            "euml|igrave|iacute|icirc|iuml|eth|ntilde|ograve|oacute|ocirc|".
+            "otilde|ouml|divide|oslash|ugrave|uacute|ucirc|uuml|yacute|thorn|".
+            "yuml|fnof|Alpha|Beta|Gamma|Delta|Epsilon|Zeta|Eta|Theta|Iota|".
+            "Kappa|Lambda|Mu|Nu|Xi|Omicron|Pi|Rho|Sigma|Tau|Upsilon|Phi|Chi|".
+            "Psi|Omega|alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|".
+            "kappa|lambda|mu|nu|xi|omicron|pi|rho|sigmaf|sigma|tau|upsilon|".
+            "phi|chi|psi|omega|thetasym|upsih|piv|bull|hellip|prime|Prime|".
+            "oline|frasl|weierp|image|real|trade|alefsym|larr|uarr|rarr|darr|".
+            "harr|crarr|lArr|uArr|rArr|dArr|hArr|forall|part|exist|empty|".
+            "nabla|isin|notin|ni|prod|sum|minus|lowast|radic|prop|infin|ang|".
+            "and|or|cap|cup|int|there4|sim|cong|asymp|ne|equiv|le|ge|sub|sup|".
+            "nsub|sube|supe|oplus|otimes|perp|sdot|lceil|rceil|lfloor|rfloor|".
+            "lang|rang|loz|spades|clubs|hearts|diams);#",*/
+        // optimized:
+        6 => "#\\\\&(?:A(?:Elig|acute|circ|grave|lpha|ring|tilde|uml)|Beta|".
+            "C(?:cedil|hi)|D(?:agger|elta)|E(?:TH|acute|circ|grave|psilon|ta|uml)|".
+            "Gamma|I(?:acute|circ|grave|ota|uml)|Kappa|Lambda|Mu|N(?:tilde|u)|".
+            "O(?:Elig|acute|circ|grave|m(?:ega|icron)|slash|tilde|uml)|".
+            "P(?:hi|i|rime|si)|Rho|S(?:caron|igma)|T(?:HORN|au|heta)|".
+            "U(?:acute|circ|grave|psilon|uml)|Xi|Y(?:acute|uml)|Zeta|".
+            "a(?:acute|c(?:irc|ute)|elig|grave|l(?:efsym|pha)|mp|n[dg]|ring|".
+            "symp|tilde|uml)|b(?:dquo|eta|rvbar|ull)|c(?:ap|cedil|e(?:dil|nt)|".
+            "hi|irc|lubs|o(?:ng|py)|rarr|u(?:p|rren))|d(?:Arr|a(?:gger|rr)|".
+            "e(?:g|lta)|i(?:ams|vide))|e(?:acute|circ|grave|m(?:pty|sp)|nsp|".
+            "psilon|quiv|t[ah]|u(?:ml|ro)|xist)|f(?:nof|orall|ra(?:c(?:1[24]|34)|sl))|".
+            "g(?:amma|e|t)|h(?:Arr|arr|e(?:arts|llip))|i(?:acute|circ|excl|grave|mage|".
+            "n(?:fin|t)|ota|quest|sin|uml)|kappa|l(?:Arr|a(?:mbda|ng|quo|rr)|ceil|".
+            "dquo|e|floor|o(?:wast|z)|rm|s(?:aquo|quo)|t)|m(?:acr|dash|".
+            "i(?:cro|ddot|nus)|u)|n(?:abla|bsp|dash|e|i|ot(?:in)?|sub|tilde|u)|".
+            "o(?:acute|circ|elig|grave|line|m(?:ega|icron)|plus|r(?:d[fm])?|".
+            "slash|ti(?:lde|mes)|uml)|p(?:ar[at]|er(?:mil|p)|hi|iv?|lusmn|ound|".
+            "r(?:ime|o[dp])|si)|quot|r(?:Arr|a(?:dic|ng|quo|rr)|ceil|dquo|e(?:al|g)|".
+            "floor|ho|lm|s(?:aquo|quo))|s(?:bquo|caron|dot|ect|hy|i(?:gmaf?|m)|".
+            "pades|u(?:be?|m|p[123e]?)|zlig)|t(?:au|h(?:e(?:re4|ta(?:sym)?)|insp|".
+            "orn)|i(?:lde|mes)|rade)|u(?:Arr|a(?:cute|rr)|circ|grave|ml|".
+            "psi(?:h|lon)|uml)|weierp|xi|y(?:acute|en|uml)|z(?:eta|w(?:j|nj)));#",
+        ),
+    'HARDQUOTE' => array('`', '`'),
+    'HARDESCAPE' => array(),
+    'NUMBERS' =>
+        GESHI_NUMBER_INT_BASIC | GESHI_NUMBER_INT_CSTYLE | GESHI_NUMBER_BIN_PREFIX_0B |
+        GESHI_NUMBER_OCT_PREFIX | GESHI_NUMBER_HEX_PREFIX | GESHI_NUMBER_FLT_NONSCI |
+        GESHI_NUMBER_FLT_NONSCI_F | GESHI_NUMBER_FLT_SCI_SHORT | GESHI_NUMBER_FLT_SCI_ZERO,
+    'KEYWORDS' => array(
+        1 => array(
+                'break', 'case', 'continue', 'do', 'else',
+                'for', 'foreach', 'goto', 'if', 'return',
+                'switch', 'while'
+            ),
+        2 => array(
+                'alias', 'asm', 'assert', 'body', 'cast',
+                'catch', 'default', 'delegate', 'delete',
+                'extern', 'false', 'finally', 'function',
+                'import', 'in', 'inout', 'interface',
+                'invariant', 'is', 'mixin', 'module', 'new',
+                'null', 'out', 'pragma', 'ref', 'super', 'this',
+                'throw', 'true', 'try', 'typedef', 'typeid',
+                'typeof', 'union', 'with'
+            ),
+        3 => array(
+                'ArrayBoundsError', 'AssertError',
+                'ClassInfo', 'Error', 'Exception',
+                'Interface', 'ModuleInfo', 'Object',
+                'OutOfMemoryException', 'SwitchError',
+                'TypeInfo', '_d_arrayappend',
+                '_d_arrayappendb', '_d_arrayappendc',
+                '_d_arrayappendcb', '_d_arraycast',
+                '_d_arraycast_frombit', '_d_arraycat',
+                '_d_arraycatb', '_d_arraycatn',
+                '_d_arraycopy', '_d_arraycopybit',
+                '_d_arraysetbit', '_d_arraysetbit2',
+                '_d_arraysetlength', '_d_arraysetlengthb',
+                '_d_callfinalizer',
+                '_d_create_exception_object',
+                '_d_criticalenter', '_d_criticalexit',
+                '_d_delarray', '_d_delclass',
+                '_d_delinterface', '_d_delmemory',
+                '_d_dynamic_cast', '_d_exception',
+                '_d_exception_filter', '_d_framehandler',
+                '_d_interface_cast', '_d_interface_vtbl',
+                '_d_invariant', '_d_isbaseof',
+                '_d_isbaseof2', '_d_local_unwind',
+                '_d_monitorenter', '_d_monitorexit',
+                '_d_monitorrelease', '_d_monitor_epilog',
+                '_d_monitor_handler', '_d_monitor_prolog',
+                '_d_new', '_d_newarrayi', '_d_newbitarray',
+                '_d_newclass', '_d_obj_cmp', '_d_obj_eq',
+                '_d_OutOfMemory', '_d_switch_dstring',
+                '_d_switch_string', '_d_switch_ustring',
+                '_d_throw',
+            ),
+        4 => array(
+                'abstract', 'align', 'auto', 'bit', 'bool',
+                'byte', 'cdouble', 'cent', 'cfloat', 'char',
+                'class', 'const', 'creal', 'dchar', 'debug',
+                'deprecated', 'double', 'enum', 'export',
+                'final', 'float', 'idouble', 'ifloat', 'int',
+                'ireal', 'long', 'override', 'package',
+                'private', 'protected', 'ptrdiff_t',
+                'public', 'real', 'short', 'size_t',
+                'static', 'struct', 'synchronized',
+                'template', 'ubyte', 'ucent', 'uint',
+                'ulong', 'unittest', 'ushort', 'version',
+                'void', 'volatile', 'wchar'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}', '?', '!', ';', ':', ',', '...', '..',
+        '+', '-', '*', '/', '%', '&', '|', '^', '<', '>', '=', '~',
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #aaaadd; font-weight: bold;',
+            4 => 'color: #993333;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            2 => 'color: #009933; font-style: italic;',
+            3 => 'color: #009933; font-style: italic;',
+            4 => 'color: #ff0000;',
+            5 => 'color: #0040ff;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;',
+            1 => 'color: #000099; font-weight: bold;',
+            2 => 'color: #660099; font-weight: bold;',
+            3 => 'color: #660099; font-weight: bold;',
+            4 => 'color: #660099; font-weight: bold;',
+            5 => 'color: #006699; font-weight: bold;',
+            6 => 'color: #666699; font-weight: bold; font-style: italic;',
+            'HARD' => '',
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;',
+            'HARD' => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #0000dd;',
+            GESHI_NUMBER_BIN_PREFIX_0B => 'color: #208080;',
+            GESHI_NUMBER_OCT_PREFIX => 'color: #208080;',
+            GESHI_NUMBER_HEX_PREFIX => 'color: #208080;',
+            GESHI_NUMBER_FLT_SCI_SHORT => 'color:#800080;',
+            GESHI_NUMBER_FLT_SCI_ZERO => 'color:#800080;',
+            GESHI_NUMBER_FLT_NONSCI_F => 'color:#800080;',
+            GESHI_NUMBER_FLT_NONSCI => 'color:#800080;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006600;',
+            2 => 'color: #006600;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.',
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/dcs.php b/examples/includes/geshi/geshi/dcs.php
new file mode 100644 (file)
index 0000000..b9fe581
--- /dev/null
@@ -0,0 +1,185 @@
+<?php
+/*************************************************************************************
+ * dcs.php
+ * ---------------------------------
+ * Author: Stelio Passaris (GeSHi@stelio.net)
+ * Copyright: (c) 2009 Stelio Passaris (http://stelio.net/stiki/GeSHi)
+ * Release Version: 1.0.8.3
+ * Date Started: 2009/01/20
+ *
+ * DCS language file for GeSHi.
+ *
+ * DCS (Data Conversion System) is part of Sungard iWorks' Prophet suite and is used
+ * to convert external data files into a format that Prophet and Glean can read.
+ * See http://www.prophet-web.com/Products/DCS for product information.
+ * This language file is current for DCS version 7.3.2.
+ *
+ * Note that the DCS IDE does not handle escape characters correctly. The IDE thinks
+ * that a backslash '\' is an escape character, but in practice the backslash does
+ * not escape the string delimiter character '"' when the program runs. A '\\' is
+ * escaped to '\' when the program runs, but '\"' is treated as '\' at the end of a
+ * string. Therefore in this language file, we do not recognise the backslash as an
+ * escape character. For the purposes of GeSHi, there is no character escaping.
+ *
+ * CHANGES
+ * -------
+ * 2009/02/21 (1.0.8.3)
+ *  -  First Release
+ *
+ * TODO (updated 2009/02/21)
+ * -------------------------
+ * * Add handling for embedded C code. Note that the DCS IDE does not highlight C code
+ *   correctly, but that doesn't mean that we can't! This will be included for a
+ *   stable release of GeSHi of version 1.1.x (or later) that allows for highlighting
+ *   embedded code using that code's appropriate language file.
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'DCS',
+    'COMMENT_SINGLE' => array(
+        1 => ';'
+        ),
+    'COMMENT_MULTI' => array(
+        ),
+    'HARDQUOTE' => array(
+        ),
+    'HARDESCAPE' => '',
+    'COMMENT_REGEXP' => array(
+        // Highlight embedded C code in a separate color:
+        2 => '/\bINSERT_C_CODE\b.*?\bEND_C_CODE\b/ims'
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_UPPER,
+    'QUOTEMARKS' => array(
+        '"'
+        ),
+    'ESCAPE_CHAR' => '',
+    'ESCAPE_REGEXP' => '',
+    'NUMBERS' =>
+        GESHI_NUMBER_INT_BASIC | GESHI_NUMBER_FLT_SCI_ZERO,
+    'KEYWORDS' => array(
+        1 => array(
+            'abs', 'ascii_value', 'bit_value', 'blank_date', 'calc_unit_values', 'cm',
+            'complete_months', 'complete_years', 'correct', 'create_input_file', 'cy',
+            'date_convert', 'day', 'del_output_separator',
+            'delete_existing_output_files', 'div', 'ex', 'exact_years', 'exp',
+            'extract_date', 'failed_validation', 'file_number', 'first_record',
+            'fract', 'fund_fac_a', 'fund_fac_b', 'fund_fac_c', 'fund_fac_d',
+            'fund_fac_e', 'fund_fac_f', 'fund_fac_g', 'fund_fac_h', 'fund_fac_i',
+            'fund_fac_j', 'fund_fac_k', 'fund_fac_l', 'fund_fac_m', 'fund_fac_n',
+            'fund_fac_o', 'fund_fac_p', 'fund_fac_q', 'fund_fac_r', 'fund_fac_s',
+            'fund_fac_t', 'fund_fac_u', 'fund_fac_v', 'fund_fac_w', 'fund_fac_x',
+            'fund_fac_y', 'fund_fac_z', 'group', 'group_record',
+            'input_file_date_time', 'input_file_extension', 'input_file_location',
+            'input_file_name', 'int', 'invalid', 'last_record', 'leap_year', 'len',
+            'ln', 'log', 'main_format_name', 'max', 'max_num_subrecords', 'message',
+            'min', 'mod', 'month', 'months_add', 'months_sub', 'nearest_months',
+            'nearest_years', 'next_record', 'nm', 'no_of_current_records',
+            'no_of_records', 'numval', 'ny', 'output', 'output_array_as_constants',
+            'output_file_path', 'output_record', 'pmdf_output', 'previous', 'rand',
+            're_start', 'read_generic_table', 'read_generic_table_text',
+            'read_input_footer', 'read_input_footer_text', 'read_input_header',
+            'read_input_header_text', 'record_count', 'record_suppressed', 'round',
+            'round_down', 'round_near', 'round_up', 'run_dcs_program', 'run_parameter',
+            'run_parameter_text', 'set_main_record', 'set_num_subrecords',
+            'sort_array', 'sort_current_records', 'sort_input', 'strval', 'substr',
+            'summarise', 'summarise_record', 'summarise_units',
+            'summarise_units_record', 'suppress_record', 'table_correct',
+            'table_validate', 'terminate', 'time', 'today', 'trim', 'ubound', 'year',
+            'years_add', 'years_sub'
+            ),
+        2 => array(
+            'and', 'as', 'begin', 'boolean', 'byref', 'byval', 'call', 'case', 'date',
+            'default', 'do', 'else', 'elseif', 'end_c_code', 'endfor', 'endfunction',
+            'endif', 'endproc', 'endswitch', 'endwhile', 'eq',
+            'explicit_declarations', 'false', 'for', 'from', 'function', 'ge', 'gt',
+            'if', 'insert_c_code', 'integer', 'le', 'loop', 'lt', 'ne', 'not',
+            'number', 'or', 'private', 'proc', 'public', 'quitloop', 'return',
+            'short', 'step', 'switch', 'text', 'then', 'to', 'true', 'while'
+            ),
+        3 => array(
+            // These keywords are not highlighted by the DCS IDE but we may as well
+            // keep track of them anyway:
+            'mp_file', 'odbc_file'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']',
+        '=', '<', '>',
+        '+', '-', '*', '/', '^',
+        ':', ','
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: red;',
+            2 => 'color: blue;',
+            3 => 'color: black;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: black; background-color: silver;',
+            // Colors for highlighting embedded C code:
+            2 => 'color: maroon; background-color: pink;'
+            ),
+        'ESCAPE_CHAR' => array(
+            ),
+        'BRACKETS' => array(
+            0 => 'color: black;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: green;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: green;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: black;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            ),
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/delphi.php b/examples/includes/geshi/geshi/delphi.php
new file mode 100644 (file)
index 0000000..7de1f8c
--- /dev/null
@@ -0,0 +1,289 @@
+<?php
+/*************************************************************************************
+ * delphi.php
+ * ----------
+ * Author: J�rja Norbert (jnorbi@vipmail.hu), Benny Baumann (BenBE@omorphia.de)
+ * Copyright: (c) 2004 J�rja Norbert, Benny Baumann (BenBE@omorphia.de), Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/07/26
+ *
+ * Delphi (Object Pascal) language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *   -  Added description of extra language features (SF#1970248)
+ * 2005/11/19 (1.0.3)
+ *   -  Updated the very incomplete keyword and type lists
+ * 2005/09/03 (1.0.2)
+ *   -  Added support for hex numbers and string entities
+ * 2004/11/27 (1.0.1)
+ *   -  Added support for multiple object splitters
+ * 2004/10/27 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *   This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Delphi',
+    'COMMENT_SINGLE' => array(1 => '//'),
+    'COMMENT_MULTI' => array('(*' => '*)', '{' => '}'),
+    //Compiler directives
+    'COMMENT_REGEXP' => array(2 => '/{\\$.*?}|\\(\\*\\$.*?\\*\\)/U'),
+    'CASE_KEYWORDS' => 0,
+    'QUOTEMARKS' => array("'"),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            'Abstract', 'And', 'Array', 'As', 'Asm', 'At', 'Begin', 'Case',
+            'Class', 'Const', 'Constructor', 'Contains', 'Destructor',
+            'DispInterface', 'Div', 'Do', 'DownTo', 'Else', 'End', 'Except',
+            'Export', 'Exports', 'External', 'File', 'Finalization', 'Finally',
+            'For', 'Function', 'Goto', 'If', 'Implementation', 'In', 'Inherited',
+            'Initialization', 'Inline', 'Interface', 'Is', 'Label', 'Library',
+            'Mod', 'Not', 'Object', 'Of', 'On', 'Or', 'Overload', 'Override',
+            'Package', 'Packed', 'Private', 'Procedure', 'Program', 'Property',
+            'Protected', 'Public', 'Published', 'Raise', 'Record', 'Register',
+            'Repeat', 'Requires', 'Resourcestring', 'Set', 'Shl', 'Shr', 'Then',
+            'ThreadVar', 'To', 'Try', 'Type', 'Unit', 'Until', 'Uses', 'Var',
+            'Virtual', 'While', 'With', 'Xor', 'assembler', 'far',
+            'near', 'pascal', 'register', 'cdecl', 'safecall', 'stdcall', 'varargs'
+            ),
+        2 => array(
+            'nil', 'false', 'self', 'true', 'var', 'type', 'const'
+            ),
+        3 => array(
+            'Abs', 'AcquireExceptionObject', 'Addr', 'AnsiToUtf8', 'Append', 'ArcTan',
+            'Assert', 'AssignFile', 'Assigned', 'BeginThread', 'BlockRead',
+            'BlockWrite', 'Break', 'ChDir', 'Chr', 'Close', 'CloseFile',
+            'CompToCurrency', 'CompToDouble', 'Concat', 'Continue', 'Copy', 'Cos',
+            'Dec', 'Delete', 'Dispose', 'DoubleToComp', 'EndThread', 'EnumModules',
+            'EnumResourceModules', 'Eof', 'Eoln', 'Erase', 'ExceptAddr',
+            'ExceptObject', 'Exclude', 'Exit', 'Exp', 'FilePos', 'FileSize',
+            'FillChar', 'Finalize', 'FindClassHInstance', 'FindHInstance',
+            'FindResourceHInstance', 'Flush', 'Frac', 'FreeMem', 'Get8087CW',
+            'GetDir', 'GetLastError', 'GetMem', 'GetMemoryManager',
+            'GetModuleFileName', 'GetVariantManager', 'Halt', 'Hi', 'High',
+            'IOResult', 'Inc', 'Include', 'Initialize', 'Insert', 'Int',
+            'IsMemoryManagerSet', 'IsVariantManagerSet', 'Length', 'Ln', 'Lo', 'Low',
+            'MkDir', 'Move', 'New', 'Odd', 'OleStrToStrVar', 'OleStrToString', 'Ord',
+            'PUCS4Chars', 'ParamCount', 'ParamStr', 'Pi', 'Pos', 'Pred', 'Ptr',
+            'Random', 'Randomize', 'Read', 'ReadLn', 'ReallocMem',
+            'ReleaseExceptionObject', 'Rename', 'Reset', 'Rewrite', 'RmDir', 'Round',
+            'RunError', 'Seek', 'SeekEof', 'SeekEoln', 'Set8087CW', 'SetLength',
+            'SetLineBreakStyle', 'SetMemoryManager', 'SetString', 'SetTextBuf',
+            'SetVariantManager', 'Sin', 'SizeOf', 'Slice', 'Sqr', 'Sqrt', 'Str',
+            'StringOfChar', 'StringToOleStr', 'StringToWideChar', 'Succ', 'Swap',
+            'Trunc', 'Truncate', 'TypeInfo', 'UCS4StringToWideString', 'UTF8Decode',
+            'UTF8Encode', 'UnicodeToUtf8', 'UniqueString', 'UpCase', 'Utf8ToAnsi',
+            'Utf8ToUnicode', 'Val', 'VarArrayRedim', 'VarClear',
+            'WideCharLenToStrVar', 'WideCharLenToString', 'WideCharToStrVar',
+            'WideCharToString', 'WideStringToUCS4String', 'Write', 'WriteLn',
+
+            'Abort', 'AddExitProc', 'AddTerminateProc', 'AdjustLineBreaks', 'AllocMem',
+            'AnsiCompareFileName', 'AnsiCompareStr', 'AnsiCompareText',
+            'AnsiDequotedStr', 'AnsiExtractQuotedStr', 'AnsiLastChar',
+            'AnsiLowerCase', 'AnsiLowerCaseFileName', 'AnsiPos', 'AnsiQuotedStr',
+            'AnsiSameStr', 'AnsiSameText', 'AnsiStrComp', 'AnsiStrIComp',
+            'AnsiStrLComp', 'AnsiStrLIComp', 'AnsiStrLastChar', 'AnsiStrLower',
+            'AnsiStrPos', 'AnsiStrRScan', 'AnsiStrScan', 'AnsiStrUpper',
+            'AnsiUpperCase', 'AnsiUpperCaseFileName', 'AppendStr', 'AssignStr',
+            'Beep', 'BoolToStr', 'ByteToCharIndex', 'ByteToCharLen', 'ByteType',
+            'CallTerminateProcs', 'ChangeFileExt', 'CharLength', 'CharToByteIndex',
+            'CharToByteLen', 'CompareMem', 'CompareStr', 'CompareText', 'CreateDir',
+            'CreateGUID', 'CurrToStr', 'CurrToStrF', 'CurrentYear', 'Date',
+            'DateTimeToFileDate', 'DateTimeToStr', 'DateTimeToString',
+            'DateTimeToSystemTime', 'DateTimeToTimeStamp', 'DateToStr', 'DayOfWeek',
+            'DecodeDate', 'DecodeDateFully', 'DecodeTime', 'DeleteFile',
+            'DirectoryExists', 'DiskFree', 'DiskSize', 'DisposeStr', 'EncodeDate',
+            'EncodeTime', 'ExceptionErrorMessage', 'ExcludeTrailingBackslash',
+            'ExcludeTrailingPathDelimiter', 'ExpandFileName', 'ExpandFileNameCase',
+            'ExpandUNCFileName', 'ExtractFileDir', 'ExtractFileDrive',
+            'ExtractFileExt', 'ExtractFileName', 'ExtractFilePath',
+            'ExtractRelativePath', 'ExtractShortPathName', 'FileAge', 'FileClose',
+            'FileCreate', 'FileDateToDateTime', 'FileExists', 'FileGetAttr',
+            'FileGetDate', 'FileIsReadOnly', 'FileOpen', 'FileRead', 'FileSearch',
+            'FileSeek', 'FileSetAttr', 'FileSetDate', 'FileSetReadOnly', 'FileWrite',
+            'FinalizePackage', 'FindClose', 'FindCmdLineSwitch', 'FindFirst',
+            'FindNext', 'FloatToCurr', 'FloatToDateTime', 'FloatToDecimal',
+            'FloatToStr', 'FloatToStrF', 'FloatToText', 'FloatToTextFmt',
+            'FmtLoadStr', 'FmtStr', 'ForceDirectories', 'Format', 'FormatBuf',
+            'FormatCurr', 'FormatDateTime', 'FormatFloat', 'FreeAndNil',
+            'GUIDToString', 'GetCurrentDir', 'GetEnvironmentVariable',
+            'GetFileVersion', 'GetFormatSettings', 'GetLocaleFormatSettings',
+            'GetModuleName', 'GetPackageDescription', 'GetPackageInfo', 'GetTime',
+            'IncAMonth', 'IncMonth', 'IncludeTrailingBackslash',
+            'IncludeTrailingPathDelimiter', 'InitializePackage', 'IntToHex',
+            'IntToStr', 'InterlockedDecrement', 'InterlockedExchange',
+            'InterlockedExchangeAdd', 'InterlockedIncrement', 'IsDelimiter',
+            'IsEqualGUID', 'IsLeapYear', 'IsPathDelimiter', 'IsValidIdent',
+            'Languages', 'LastDelimiter', 'LoadPackage', 'LoadStr', 'LowerCase',
+            'MSecsToTimeStamp', 'NewStr', 'NextCharIndex', 'Now', 'OutOfMemoryError',
+            'QuotedStr', 'RaiseLastOSError', 'RaiseLastWin32Error', 'RemoveDir',
+            'RenameFile', 'ReplaceDate', 'ReplaceTime', 'SafeLoadLibrary',
+            'SameFileName', 'SameText', 'SetCurrentDir', 'ShowException', 'Sleep',
+            'StrAlloc', 'StrBufSize', 'StrByteType', 'StrCat', 'StrCharLength',
+            'StrComp', 'StrCopy', 'StrDispose', 'StrECopy', 'StrEnd', 'StrFmt',
+            'StrIComp', 'StrLCat', 'StrLComp', 'StrLCopy', 'StrLFmt', 'StrLIComp',
+            'StrLen', 'StrLower', 'StrMove', 'StrNew', 'StrNextChar', 'StrPCopy',
+            'StrPLCopy', 'StrPas', 'StrPos', 'StrRScan', 'StrScan', 'StrToBool',
+            'StrToBoolDef', 'StrToCurr', 'StrToCurrDef', 'StrToDate', 'StrToDateDef',
+            'StrToDateTime', 'StrToDateTimeDef', 'StrToFloat', 'StrToFloatDef',
+            'StrToInt', 'StrToInt64', 'StrToInt64Def', 'StrToIntDef', 'StrToTime',
+            'StrToTimeDef', 'StrUpper', 'StringReplace', 'StringToGUID', 'Supports',
+            'SysErrorMessage', 'SystemTimeToDateTime', 'TextToFloat', 'Time',
+            'TimeStampToDateTime', 'TimeStampToMSecs', 'TimeToStr', 'Trim',
+            'TrimLeft', 'TrimRight', 'TryEncodeDate', 'TryEncodeTime',
+            'TryFloatToCurr', 'TryFloatToDateTime', 'TryStrToBool', 'TryStrToCurr',
+            'TryStrToDate', 'TryStrToDateTime', 'TryStrToFloat', 'TryStrToInt',
+            'TryStrToInt64', 'TryStrToTime', 'UnloadPackage', 'UpperCase',
+            'WideCompareStr', 'WideCompareText', 'WideFmtStr', 'WideFormat',
+            'WideFormatBuf', 'WideLowerCase', 'WideSameStr', 'WideSameText',
+            'WideUpperCase', 'Win32Check', 'WrapText',
+
+            'ActivateClassGroup', 'AllocateHwnd', 'BinToHex', 'CheckSynchronize',
+            'CollectionsEqual', 'CountGenerations', 'DeallocateHwnd', 'EqualRect',
+            'ExtractStrings', 'FindClass', 'FindGlobalComponent', 'GetClass',
+            'GroupDescendantsWith', 'HexToBin', 'IdentToInt',
+            'InitInheritedComponent', 'IntToIdent', 'InvalidPoint',
+            'IsUniqueGlobalComponentName', 'LineStart', 'ObjectBinaryToText',
+            'ObjectResourceToText', 'ObjectTextToBinary', 'ObjectTextToResource',
+            'PointsEqual', 'ReadComponentRes', 'ReadComponentResEx',
+            'ReadComponentResFile', 'Rect', 'RegisterClass', 'RegisterClassAlias',
+            'RegisterClasses', 'RegisterComponents', 'RegisterIntegerConsts',
+            'RegisterNoIcon', 'RegisterNonActiveX', 'SmallPoint', 'StartClassGroup',
+            'TestStreamFormat', 'UnregisterClass', 'UnregisterClasses',
+            'UnregisterIntegerConsts', 'UnregisterModuleClasses',
+            'WriteComponentResFile',
+
+            'ArcCos', 'ArcCosh', 'ArcCot', 'ArcCotH', 'ArcCsc', 'ArcCscH', 'ArcSec',
+            'ArcSecH', 'ArcSin', 'ArcSinh', 'ArcTan2', 'ArcTanh', 'Ceil',
+            'CompareValue', 'Cosecant', 'Cosh', 'Cot', 'CotH', 'Cotan', 'Csc', 'CscH',
+            'CycleToDeg', 'CycleToGrad', 'CycleToRad', 'DegToCycle', 'DegToGrad',
+            'DegToRad', 'DivMod', 'DoubleDecliningBalance', 'EnsureRange', 'Floor',
+            'Frexp', 'FutureValue', 'GetExceptionMask', 'GetPrecisionMode',
+            'GetRoundMode', 'GradToCycle', 'GradToDeg', 'GradToRad', 'Hypot',
+            'InRange', 'IntPower', 'InterestPayment', 'InterestRate',
+            'InternalRateOfReturn', 'IsInfinite', 'IsNan', 'IsZero', 'Ldexp', 'LnXP1',
+            'Log10', 'Log2', 'LogN', 'Max', 'MaxIntValue', 'MaxValue', 'Mean',
+            'MeanAndStdDev', 'Min', 'MinIntValue', 'MinValue', 'MomentSkewKurtosis',
+            'NetPresentValue', 'Norm', 'NumberOfPeriods', 'Payment', 'PeriodPayment',
+            'Poly', 'PopnStdDev', 'PopnVariance', 'Power', 'PresentValue',
+            'RadToCycle', 'RadToDeg', 'RadToGrad', 'RandG', 'RandomRange', 'RoundTo',
+            'SLNDepreciation', 'SYDDepreciation', 'SameValue', 'Sec', 'SecH',
+            'Secant', 'SetExceptionMask', 'SetPrecisionMode', 'SetRoundMode', 'Sign',
+            'SimpleRoundTo', 'SinCos', 'Sinh', 'StdDev', 'Sum', 'SumInt',
+            'SumOfSquares', 'SumsAndSquares', 'Tan', 'Tanh', 'TotalVariance',
+            'Variance'
+            ),
+        4 => array(
+            'AnsiChar', 'AnsiString', 'Bool', 'Boolean', 'Byte', 'ByteBool', 'Cardinal', 'Char',
+            'Comp', 'Currency', 'DWORD', 'Double', 'Extended', 'Int64', 'Integer', 'IUnknown',
+            'LongBool', 'LongInt', 'LongWord', 'PAnsiChar', 'PAnsiString', 'PBool', 'PBoolean', 'PByte',
+            'PByteArray', 'PCardinal', 'PChar', 'PComp', 'PCurrency', 'PDWORD', 'PDate', 'PDateTime',
+            'PDouble', 'PExtended', 'PInt64', 'PInteger', 'PLongInt', 'PLongWord', 'Pointer', 'PPointer',
+            'PShortInt', 'PShortString', 'PSingle', 'PSmallInt', 'PString', 'PHandle', 'PVariant', 'PWord',
+            'PWordArray', 'PWordBool', 'PWideChar', 'PWideString', 'Real', 'Real48', 'ShortInt', 'ShortString',
+            'Single', 'SmallInt', 'String', 'TClass', 'TDate', 'TDateTime', 'TextFile', 'THandle',
+            'TObject', 'TTime', 'Variant', 'WideChar', 'WideString', 'Word', 'WordBool'
+            ),
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        ),
+    'SYMBOLS' => array(
+        0 => array('(', ')', '[', ']'),
+        1 => array('.', ',', ':', ';'),
+        2 => array('@', '^'),
+        3 => array('=', '+', '-', '*', '/')
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000000; font-weight: bold;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #000066;',
+            4 => 'color: #000066; font-weight: bold;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            2 => 'color: #008000; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #ff0000; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000066;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #0000ff;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006600;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #9ac;',
+            1 => 'color: #ff0000;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000066;',
+            1 => 'color: #000066;',
+            2 => 'color: #000066;',
+            3 => 'color: #000066;'
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        //Hex numbers
+        0 => '\$[0-9a-fA-F]+',
+        //Characters
+        1 => '\#\$?[0-9]{1,3}'
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 2
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/diff.php b/examples/includes/geshi/geshi/diff.php
new file mode 100644 (file)
index 0000000..c82e65c
--- /dev/null
@@ -0,0 +1,196 @@
+<?php
+/*************************************************************************************
+ * diff.php
+ * --------
+ * Author: Conny Brunnkvist (conny@fuchsia.se), W. Tasin (tasin@fhm.edu)
+ * Copyright: (c) 2004 Fuchsia Open Source Solutions (http://www.fuchsia.se/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/12/29
+ *
+ * Diff-output language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *  -  Added description of extra language features (SF#1970248)
+ * 2006/02/27
+ *  -  changing language file to use matching of start (^) and end ($) (wt)
+ * 2004/12/29 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2006/02/27)
+ * -------------------------
+ *
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+
+$language_data = array (
+    'LANG_NAME' => 'Diff',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array(),
+    'ESCAPE_CHAR' => ' ',
+    'KEYWORDS' => array(
+            1 => array(
+                '\ No newline at end of file'
+            ),
+//            2 => array(
+//                '***************' /* This only seems to works in some cases? */
+//            ),
+        ),
+    'SYMBOLS' => array(
+        ),
+    'CASE_SENSITIVE' => array(
+        1 => false,
+//        2 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #aaaaaa; font-style: italic;',
+//            2 => 'color: #dd6611;',
+            ),
+        'COMMENTS' => array(
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => ''
+            ),
+        'BRACKETS' => array(
+            0 => ''
+            ),
+        'STRINGS' => array(
+            0 => ''
+            ),
+        'NUMBERS' => array(
+            0 => ''
+            ),
+        'METHODS' => array(
+            0 => ''
+            ),
+        'SYMBOLS' => array(
+            0 => ''
+            ),
+        'SCRIPT' => array(
+            0 => ''
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #440088;',
+            1 => 'color: #991111;',
+            2 => 'color: #00b000;',
+            3 => 'color: #888822;',
+            4 => 'color: #888822;',
+            5 => 'color: #0011dd;',
+            6 => 'color: #440088;',
+            7 => 'color: #991111;',
+            8 => 'color: #00b000;',
+            9 => 'color: #888822;',
+            ),
+        ),
+    'URLS' => array(
+        1 => '',
+//        2 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(),
+    'REGEXPS' => array(
+        0 => "[0-9,]+[acd][0-9,]+",
+        //Removed lines
+        1 => array(
+            GESHI_SEARCH => '^\\&lt;.*$',
+            GESHI_REPLACE => '\\0',
+            GESHI_MODIFIERS => 'm',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        //Inserted lines
+        2 => array(
+            GESHI_SEARCH => '^\\&gt;.*$',
+            GESHI_REPLACE => '\\0',
+            GESHI_MODIFIERS => 'm',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        //Location line
+        3 => array(
+            GESHI_SEARCH => '^[\\-]{3}\\s.*$',
+            GESHI_REPLACE => '\\0',
+            GESHI_MODIFIERS => 'm',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        //Inserted line
+        4 => array(
+            GESHI_SEARCH => '^(\\+){3}\\s.*$',
+            GESHI_REPLACE => '\\0',
+            GESHI_MODIFIERS => 'm',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        //Modified line
+        5 => array(
+            GESHI_SEARCH => '^\\!.*$',
+            GESHI_REPLACE => '\\0',
+            GESHI_MODIFIERS => 'm',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        //File specification
+        6 => array(
+            GESHI_SEARCH => '^[\\@]{2}.*$',
+            GESHI_REPLACE => '\\0',
+            GESHI_MODIFIERS => 'm',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        //Removed line
+        7 => array(
+            GESHI_SEARCH => '^\\-.*$',
+            GESHI_REPLACE => '\\0',
+            GESHI_MODIFIERS => 'm',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        //Inserted line
+        8 => array(
+            GESHI_SEARCH => '^\\+.*$',
+            GESHI_REPLACE => '\\0',
+            GESHI_MODIFIERS => 'm',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        //File specification
+        9 => array(
+            GESHI_SEARCH => '^(\\*){3}\\s.*$',
+            GESHI_REPLACE => '\\0',
+            GESHI_MODIFIERS => 'm',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/div.php b/examples/includes/geshi/geshi/div.php
new file mode 100644 (file)
index 0000000..d3d506d
--- /dev/null
@@ -0,0 +1,126 @@
+<?php
+/*************************************************************************************
+ * div.php
+ * ---------------------------------
+ * Author: Gabriel Lorenzo (ermakina@gmail.com)
+ * Copyright: (c) 2005 Gabriel Lorenzo (http://ermakina.gazpachito.net)
+ * Release Version: 1.0.8.3
+ * Date Started: 2005/06/19
+ *
+ * DIV language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2005/06/22 (1.0.0)
+ *  -  First Release, includes "2nd gen" ELSEIF statement
+ *
+ * TODO (updated 2005/06/22)
+ * -------------------------
+ *  -  I'm pretty satisfied with this, so nothing for now... :P
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'DIV',
+    'COMMENT_SINGLE' => array(1 => '//'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_UPPER,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            'while','until','to','switch','step','return','repeat','loop','if','from','frame','for','end','elseif',
+            'else','default','debug','continue','clone','case','break','begin'
+            ),
+        2 => array(
+            'xor','whoami','type','sizeof','pointer','or','offset','not','neg','mod','id','dup','and','_ne','_lt',
+            '_le','_gt','_ge','_eq'
+            ),
+        3 => array(
+            'setup_program','program','process','private','local','import','global','function','const',
+            'compiler_options'
+            ),
+        4 => array(
+            'word','struct','string','int','byte'
+            ),
+        ),
+    'SYMBOLS' => array(
+        '(',')','[',']','=','+','-','*','/','!','%','^','&',':',';',',','<','>'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0040b1;',
+            2 => 'color: #000000;',
+            3 => 'color: #000066; font-weight: bold;',
+            4 => 'color: #993333;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => ''
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #44aa44;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            0 => 'color: #202020;',
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #44aa44;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/dos.php b/examples/includes/geshi/geshi/dos.php
new file mode 100644 (file)
index 0000000..af8fdae
--- /dev/null
@@ -0,0 +1,198 @@
+<?php
+/*************************************************************************************
+ * dos.php
+ * -------
+ * Author: Alessandro Staltari (staltari@geocities.com)
+ * Copyright: (c) 2005 Alessandro Staltari (http://www.geocities.com/SiliconValley/Vista/8155/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2005/07/05
+ *
+ * DOS language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *   -  Added description of extra language features (SF#1970248)
+ * 2005/07/05 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2005/07/05)
+ * -------------------------
+ *
+ * - Highlight pipes and redirection (do we really need this?)
+ * - Add missing keywords.
+ * - Find a good hyperlink for keywords.
+ * - Improve styles.
+ *
+ * KNOWN ISSUES (updated 2005/07/07)
+ * ---------------------------------
+ *
+ * - Doesn't even try to handle spaces in variables name or labels (I can't
+ *   find a reliable way to establish if a sting is a name or not, in some
+ *   cases it depends on the contex or enviroment status).
+ * - Doesn't handle %%[letter] pseudo variable used inside FOR constructs
+ *   (it should be done only into its scope: how to handle variable it?).
+ * - Doesn't handle %~[something] pseudo arguments.
+ * - If the same keyword is placed at the end of the line and the
+ *   beginning of the next, the second occourrence is not highlighted
+ *   (this should be a GeSHi bug, not related to the language definition).
+ * - I can't avoid to have keyword highlighted even when they are not used
+ *   as keywords but, for example, as arguments to the echo command.
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'DOS',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array(),
+    //DOS comment lines
+    'COMMENT_REGEXP' => array(1 => "/^\s*@?REM.*$/mi"),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array(),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        /* Flow control keywords */
+        1 => array(
+            'if', 'else', 'goto', 'shift',
+            'for', 'in', 'do',
+            'call', 'exit'
+            ),
+        /* IF statement keywords */
+        2 => array(
+            'not', 'exist', 'errorlevel',
+            'defined',
+            'equ', 'neq', 'lss', 'leq', 'gtr', 'geq'
+            ),
+        /* Internal commands */
+        3 => array(
+            'cd', 'md', 'rd', 'chdir', 'mkdir', 'rmdir', 'dir',
+            'del', 'copy', 'move', 'ren', 'rename',
+            'echo',
+            'setlocal', 'endlocal', 'set',
+            'pause',
+            'pushd', 'popd', 'title', 'verify'
+            ),
+        /* Special files */
+        4 => array(
+            'prn', 'nul', 'lpt3', 'lpt2', 'lpt1', 'con',
+            'com4', 'com3', 'com2', 'com1', 'aux'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '@', '%'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #00b100; font-weight: bold;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #b1b100; font-weight: bold;',
+            4 => 'color: #0000ff; font-weight: bold;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #ff0000; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #33cc33;',
+            1 => 'color: #33cc33;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #b100b1; font-weight: bold;',
+            1 => 'color: #448844;',
+            2 => 'color: #448888;'
+            )
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'URLS' => array(
+        1 => 'http://www.ss64.com/nt/{FNAMEL}.html',
+        2 => 'http://www.ss64.com/nt/{FNAMEL}.html',
+        3 => 'http://www.ss64.com/nt/{FNAMEL}.html',
+        4 => 'http://www.ss64.com/nt/{FNAMEL}.html'
+        ),
+    'REGEXPS' => array(
+        /* Label */
+        0 => array(
+/*            GESHI_SEARCH => '((?si:[@\s]+GOTO\s+|\s+:)[\s]*)((?<!\n)[^\s\n]*)',*/
+            GESHI_SEARCH => '((?si:[@\s]+GOTO\s+|\s+:)[\s]*)((?<!\n)[^\n]*)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 'si',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => ''
+        ),
+        /* Variable assignement */
+        1 => array(
+/*            GESHI_SEARCH => '(SET[\s]+(?si:\/A[\s]+|\/P[\s]+|))([^=\s\n]+)([\s]*=)',*/
+            GESHI_SEARCH => '(SET[\s]+(?si:\/A[\s]+|\/P[\s]+|))([^=\n]+)([\s]*=)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 'si',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => '\\3'
+            ),
+        /* Arguments or variable evaluation */
+        2 => array(
+/*            GESHI_SEARCH => '(%)([\d*]|[^%\s]*(?=%))((?<!%\d)%|)',*/
+            GESHI_SEARCH => '(%(?:%(?=[a-z0-9]))?)([\d*]|(?:~[adfnpstxz]*(?:$\w+:)?)?[a-z0-9](?!\w)|[^%\n]*(?=%))((?<!%\d)%|)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 'si',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => '\\3'
+            )
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4,
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            4 => array(
+                'DISALLOWED_BEFORE' => '(?<!\w)'
+                )
+            )
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/dot.php b/examples/includes/geshi/geshi/dot.php
new file mode 100644 (file)
index 0000000..35d3d9b
--- /dev/null
@@ -0,0 +1,164 @@
+<?php
+/*************************************************************************************
+ * dot.php
+ * ---------------------------------
+ * Author: Adrien Friggeri (adrien@friggeri.net)
+ * Copyright: (c) 2007 Adrien Friggeri (http://www.friggeri.net)
+ * Release Version: 1.0.8.3
+ * Date Started: 2007/05/30
+ *
+ * dot language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2007/05/30 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2007/05/30)
+ * -------------------------
+ * Everything
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'dot',
+    'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'URL', 'arrowhead', 'arrowsize', 'arrowtail', 'bb', 'bgcolor', 'bottomlabel',
+            'center', 'clusterrank', 'color', 'comment', 'constraint', 'decorate',
+            'dir', 'distortion', 'fillcolor', 'fixedsize', 'fontcolor',
+            'fontname', 'fontsize', 'group', 'headclip', 'headlabel', 'headport',
+            'height', 'id', 'label', 'labelangle', 'labeldistance', 'labelfontcolor',
+            'labelfontname', 'labelfontsize', 'layer', 'layers', 'margin', 'mclimit',
+            'minlen', 'nodesep', 'nslimit', 'ordering', 'orientation', 'page',
+            'pagedir', 'peripheries', 'port_label_distance', 'quantum', 'rank', 'rankdir',
+            'ranksep', 'ratio', 'regular', 'rotate', 'samehead', 'sametail', 'searchsize',
+            'shape', 'shapefile', 'showboxes', 'sides', 'size', 'skew', 'style',
+            'tailclip', 'taillabel', 'tailport', 'toplabel', 'weight', 'width'
+            ),
+        2 => array(
+            'node', 'graph', 'digraph', 'strict', 'edge', 'subgraph'
+            ),
+        3 => array(
+            'Mcircle', 'Mdiamond', 'Mrecord', 'Msquare', 'TRUE', 'auto', 'back',
+            'bold', 'both', 'box', 'circle', 'compress', 'dashed', 'diamond', 'dot',
+            'dotted', 'doublecircle', 'doubleoctagon', 'egg', 'ellipse', 'epsf', 'false',
+            'fill', 'filled', 'forward', 'global', 'hexagon', 'house', 'inv', 'invdot',
+            'invhouse', 'invis', 'invodot', 'invtrapezium', 'invtriangle', 'local', 'max',
+            'min', 'none', 'normal', 'octagon', 'odot', 'out', 'parallelogram', 'plaintext',
+            'polygon', 'record', 'same', 'solid', 'trapezium', 'triangle', 'tripleoctagon',
+            'true'
+            ),
+        4 => array(
+            'aliceblue', 'antiquewhite', 'aquamarine', 'azure', 'beige', 'bisque', 'black',
+            'blanchedalmond', 'blue', 'blueviolet', 'brown', 'burlywood', 'cadetblue',
+            'chartreuse', 'chocolate', 'coral', 'cornflowerblue', 'cornsilk', 'crimson',
+            'cyan', 'darkgoldenrod', 'darkgreen', 'darkkhaki', 'darkolivegreen',
+            'darkorange', 'darkorchid', 'darksalmon', 'darkseagreen', 'darkslateblue',
+            'darkslategray', 'darkturquoise', 'darkviolet', 'deeppink', 'deepskyblue',
+            'dimgray', 'dodgerblue', 'firebrick', 'forestgreen', 'gainsboro', 'ghostwhite',
+            'gold', 'goldenrod', 'gray', 'green', 'greenyellow', 'honeydew', 'hotpink',
+            'indianred', 'indigo', 'ivory', 'khaki', 'lavender', 'lavenderblush',
+            'lawngreen', 'lemonchiffon', 'lightblue', 'lightcyan', 'lightgoldenrod',
+            'lightgoldenrodyellow', 'lightgray', 'lightpink', 'lightsalmon',
+            'lightseagreen', 'lightskyblue', 'lightslateblue', 'lightslategray',
+            'lightyellow', 'limegreen', 'linen', 'magenta', 'maroon', 'mediumaquamarine',
+            'mediumblue', 'mediumorchid', 'mediumpurple', 'mediumseagreen',
+            'mediumslateblue', 'mediumspringgreen', 'mediumturquoise', 'mediumvioletred',
+            'midnightblue', 'mintcream', 'mistyrose', 'moccasin', 'navajowhite', 'navy',
+            'navyblue', 'oldlace', 'olivedrab', 'oralwhite', 'orange', 'orangered',
+            'orchid', 'palegoldenrod', 'palegreen', 'paleturquoise', 'palevioletred',
+            'papayawhip', 'peachpuff', 'peru', 'pink', 'plum', 'powderblue', 'purple',
+            'red', 'rosybrown', 'royalblue', 'saddlebrown', 'salmon', 'salmon2', 'sandybrown',
+            'seagreen', 'seashell', 'sienna', 'skyblue', 'slateblue', 'slategray', 'snow',
+            'springgreen', 'steelblue', 'tan', 'thistle', 'tomato', 'turquoise', 'violet',
+            'violetred', 'wheat', 'white', 'whitesmoke', 'yellow', 'yellowgreen'
+            )
+        ),
+    'SYMBOLS' => array(
+        '[', ']', '{', '}', '-', '+', '*', '/', '<', '>', '!', '~', '%', '&', '|', '='
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000066;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #993333;',
+            4 => 'color: #b1b100;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            2 => 'color: #339933;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #af624d; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'METHODS' => array(
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            ),
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(),
+    'REGEXPS' => array(),
+    'STRICT_MODE_APPLIES' => GESHI_MAYBE,
+    'SCRIPT_DELIMITERS' => array(),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        0 => true,
+        1 => true,
+        2 => true,
+        3 => true
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/eiffel.php b/examples/includes/geshi/geshi/eiffel.php
new file mode 100644 (file)
index 0000000..7a9a61e
--- /dev/null
@@ -0,0 +1,395 @@
+<?php
+/*************************************************************************************
+ * eiffel.php
+ * ----------
+ * Author: Zoran Simic (zsimic@axarosenberg.com)
+ * Copyright: (c) 2005 Zoran Simic
+ * Release Version: 1.0.8.3
+ * Date Started: 2005/06/30
+ *
+ * Eiffel language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2005/06/30 (1.0.7)
+ *  -  Initial release
+ *
+ * TODO (updated 2005/06/30)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Eiffel',
+    'COMMENT_SINGLE' => array(1 => '--'),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '%',
+    'KEYWORDS' => array(
+        1 => array(
+            'separate',
+            'invariant',
+            'inherit',
+            'indexing',
+            'feature',
+            'expanded',
+            'deferred',
+            'class'
+            ),
+        2 => array(
+            'xor',
+            'when',
+            'variant',
+            'until',
+            'unique',
+            'undefine',
+            'then',
+            'strip',
+            'select',
+            'retry',
+            'rescue',
+            'require',
+            'rename',
+            'reference',
+            'redefine',
+            'prefix',
+            'or',
+            'once',
+            'old',
+            'obsolete',
+            'not',
+            'loop',
+            'local',
+            'like',
+            'is',
+            'inspect',
+            'infix',
+            'include',
+            'implies',
+            'if',
+            'frozen',
+            'from',
+            'external',
+            'export',
+            'ensure',
+            'end',
+            'elseif',
+            'else',
+            'do',
+            'creation',
+            'create',
+            'check',
+            'as',
+            'and',
+            'alias',
+            'agent'
+            ),
+        3 => array(
+            'Void',
+            'True',
+            'Result',
+            'Precursor',
+            'False',
+            'Current'
+            ),
+        4 => array(
+            'UNIX_SIGNALS',
+            'UNIX_FILE_INFO',
+            'UNBOUNDED',
+            'TWO_WAY_TREE_CURSOR',
+            'TWO_WAY_TREE',
+            'TWO_WAY_SORTED_SET',
+            'TWO_WAY_LIST',
+            'TWO_WAY_CURSOR_TREE',
+            'TWO_WAY_CIRCULAR',
+            'TWO_WAY_CHAIN_ITERATOR',
+            'TUPLE',
+            'TREE',
+            'TRAVERSABLE',
+            'TO_SPECIAL',
+            'THREAD_CONTROL',
+            'THREAD_ATTRIBUTES',
+            'THREAD',
+            'TABLE',
+            'SUBSET',
+            'STRING_HANDLER',
+            'STRING',
+            'STREAM',
+            'STORABLE',
+            'STD_FILES',
+            'STACK',
+            'SPECIAL',
+            'SORTED_TWO_WAY_LIST',
+            'SORTED_STRUCT',
+            'SORTED_LIST',
+            'SINGLE_MATH',
+            'SET',
+            'SEQUENCE',
+            'SEQ_STRING',
+            'SEMAPHORE',
+            'ROUTINE',
+            'RESIZABLE',
+            'RECURSIVE_TREE_CURSOR',
+            'RECURSIVE_CURSOR_TREE',
+            'REAL_REF',
+            'REAL',
+            'RAW_FILE',
+            'RANDOM',
+            'QUEUE',
+            'PROXY',
+            'PROFILING_SETTING',
+            'PROCEDURE',
+            'PRIORITY_QUEUE',
+            'PRIMES',
+            'PRECOMP',
+            'POINTER_REF',
+            'POINTER',
+            'PLATFORM',
+            'PLAIN_TEXT_FILE',
+            'PATH_NAME',
+            'PART_SORTED_TWO_WAY_LIST',
+            'PART_SORTED_SET',
+            'PART_SORTED_LIST',
+            'PART_COMPARABLE',
+            'OPERATING_ENVIRONMENT',
+            'ONCE_CONTROL',
+            'OBJECT_OWNER',
+            'OBJECT_CONTROL',
+            'NUMERIC',
+            'NONE',
+            'MUTEX',
+            'MULTI_ARRAY_LIST',
+            'MULTAR_LIST_CURSOR',
+            'MEMORY',
+            'MEM_INFO',
+            'MEM_CONST',
+            'MATH_CONST',
+            'LIST',
+            'LINKED_TREE_CURSOR',
+            'LINKED_TREE',
+            'LINKED_STACK',
+            'LINKED_SET',
+            'LINKED_QUEUE',
+            'LINKED_PRIORITY_QUEUE',
+            'LINKED_LIST_CURSOR',
+            'LINKED_LIST',
+            'LINKED_CURSOR_TREE',
+            'LINKED_CIRCULAR',
+            'LINKABLE',
+            'LINEAR_ITERATOR',
+            'LINEAR',
+            'ITERATOR',
+            'IO_MEDIUM',
+            'INTERNAL',
+            'INTEGER_REF',
+            'INTEGER_INTERVAL',
+            'INTEGER',
+            'INFINITE',
+            'INDEXABLE',
+            'IDENTIFIED_CONTROLLER',
+            'IDENTIFIED',
+            'HIERARCHICAL',
+            'HEAP_PRIORITY_QUEUE',
+            'HASHABLE',
+            'HASH_TABLE_CURSOR',
+            'HASH_TABLE',
+            'GENERAL',
+            'GC_INFO',
+            'FUNCTION',
+            'FORMAT_INTEGER',
+            'FORMAT_DOUBLE',
+            'FIXED_TREE',
+            'FIXED_LIST',
+            'FIXED',
+            'FINITE',
+            'FILE_NAME',
+            'FILE',
+            'FIBONACCI',
+            'EXECUTION_ENVIRONMENT',
+            'EXCEPTIONS',
+            'EXCEP_CONST',
+            'DYNAMIC_TREE',
+            'DYNAMIC_LIST',
+            'DYNAMIC_CIRCULAR',
+            'DYNAMIC_CHAIN',
+            'DOUBLE_REF',
+            'DOUBLE_MATH',
+            'DOUBLE',
+            'DISPENSER',
+            'DIRECTORY_NAME',
+            'DIRECTORY',
+            'DECLARATOR',
+            'DEBUG_OUTPUT',
+            'CURSOR_TREE_ITERATOR',
+            'CURSOR_TREE',
+            'CURSOR_STRUCTURE',
+            'CURSOR',
+            'COUNTABLE_SEQUENCE',
+            'COUNTABLE',
+            'CONTAINER',
+            'CONSOLE',
+            'CONDITION_VARIABLE',
+            'COMPARABLE_STRUCT',
+            'COMPARABLE_SET',
+            'COMPARABLE',
+            'COMPACT_TREE_CURSOR',
+            'COMPACT_CURSOR_TREE',
+            'COLLECTION',
+            'CIRCULAR_CURSOR',
+            'CIRCULAR',
+            'CHARACTER_REF',
+            'CHARACTER',
+            'CHAIN',
+            'CELL',
+            'BOX',
+            'BOUNDED_STACK',
+            'BOUNDED_QUEUE',
+            'BOUNDED',
+            'BOOLEAN_REF',
+            'BOOLEAN',
+            'BOOL_STRING',
+            'BIT_REF',
+            'BINARY_TREE',
+            'BINARY_SEARCH_TREE_SET',
+            'BINARY_SEARCH_TREE',
+            'BILINEAR',
+            'BI_LINKABLE',
+            'BASIC_ROUTINES',
+            'BAG',
+            'ASCII',
+            'ARRAYED_TREE',
+            'ARRAYED_STACK',
+            'ARRAYED_QUEUE',
+            'ARRAYED_LIST_CURSOR',
+            'ARRAYED_LIST',
+            'ARRAYED_CIRCULAR',
+            'ARRAY2',
+            'ARRAY',
+            'ARGUMENTS',
+            'ANY',
+            'ACTIVE'
+            ),
+        5 => array(
+            'yes',
+            'visible',
+            'trace',
+            'system',
+            'root',
+            'profile',
+            'override_cluster',
+            'object',
+            'no',
+            'multithreaded',
+            'msil_generation_type',
+            'line_generation',
+            'library',
+            'inlining_size',
+            'inlining',
+            'include_path',
+            'il_verifiable',
+            'exclude',
+            'exception_trace',
+            'dynamic_runtime',
+            'dotnet_naming_convention',
+            'disabled_debug',
+            'default',
+            'debug',
+            'dead_code_removal',
+            'console_application',
+            'cluster',
+            'cls_compliant',
+            'check_vape',
+            'assertion',
+            'array_optimization',
+            'all',
+            'address_expression'
+            ),
+        ),
+    'SYMBOLS' => array(
+        '+', '-', '*', '?', '=', '/', '%', '&', '>', '<', '^', '!', '|', ':',
+        '(', ')', '{', '}', '[', ']', '#'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => true,
+        5 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0600FF; font-weight: bold;',
+            2 => 'color: #0600FF; font-weight: bold;',
+            3 => 'color: #800080;',
+            4 => 'color: #800000',
+            5 => 'color: #603000;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #008000; font-style: italic;',
+            'MULTI' => ''
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #005070; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #FF0000;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #0080A0;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #FF0000;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #000060;',
+            2 => 'color: #000050;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #600000;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => 'http://www.google.com/search?q=site%3Ahttp%3A%2F%2Fdocs.eiffel.com%2Feiffelstudio%2Flibraries+{FNAMEL}&amp;btnI=I%27m+Feeling+Lucky',
+        5 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/email.php b/examples/includes/geshi/geshi/email.php
new file mode 100644 (file)
index 0000000..26466dc
--- /dev/null
@@ -0,0 +1,209 @@
+<?php
+/*************************************************************************************
+ * email.php
+ * ---------------
+ * Author: Benny Baumann (BenBE@geshi.org)
+ * Copyright: (c) 2008 Benny Baumann (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/10/19
+ *
+ * Email (mbox \ eml \ RFC format) language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/10/19 (1.0.8.1)
+ *   -  First Release
+ *
+ * TODO (updated 2008/10/19)
+ * -------------------------
+ * * Better checks when a header field should be expected
+ * * Fix the bound checks for kw groups 2 and 3, as well as rx group 1
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'eMail (mbox)',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            'HTTP', 'SMTP', 'ASMTP', 'ESMTP'
+            ),
+        2 => array(
+            'Content-Type','Content-Transfer-Encoding','Content-Disposition',
+            'Delivered-To','Dkim-Signature','Domainkey-Signature','In-Reply-To',
+            'Message-Id','MIME-Version','Received','Received-SPF','References',
+            'Resend-From','Resend-To','Return-Path'
+            ),
+        3 => array(
+            'Date','From','Subject','To',
+            ),
+        4 => array(
+            'by', 'for', 'from', 'id', 'with'
+            )
+        ),
+    'SYMBOLS' => array(
+        ':', ';', '<', '>', '[', ']'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => false,
+        3 => false,
+        4 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0000FF; font-weight: bold;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #800000; font-weight: bold;',
+            4 => 'font-weight: bold;',
+            ),
+        'COMMENTS' => array(
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'SCRIPT' => array(
+            0 => 'color: #000040;',
+            ),
+        'REGEXPS' => array(
+            1 => 'color: #000000; font-weight: bold;',
+            2 => 'color: #0000FF;',
+            3 => 'color: #008000;',
+            4 => 'color: #0000FF; font-weight: bold;',
+            5 => 'font-weight: bold;',
+            6 => 'color: #400080;'
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        // Non-Standard-Header
+        1 => array(
+            GESHI_SEARCH => "(?<=\A\x20|\n)x-[a-z0-9\-]*(?=\s*:|\s*<)",
+            GESHI_REPLACE => "\\0",
+            GESHI_MODIFIERS => "smi",
+            GESHI_BEFORE => "",
+            GESHI_AFTER => ""
+            ),
+        //Email-Adresses or Mail-IDs
+        2 => array(
+            GESHI_SEARCH => "\b[\w\.]+@\w+(?:(?:\.\w+)*\.\w{2,4})?",
+            GESHI_REPLACE => "\\0",
+            GESHI_MODIFIERS => "mi",
+            GESHI_BEFORE => "",
+            GESHI_AFTER => ""
+            ),
+        //Date values in RFC format
+        3 => array(
+            GESHI_SEARCH => "\b(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),\s+\d\d?\s+" .
+                "(?:Jan|Feb|Mar|apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+" .
+                "\d{4}\s+\d\d?:\d\d:\d\d\s+[+\-]\d{4}(?:\s+\(\w+\))?",
+            GESHI_REPLACE => "\\0",
+            GESHI_MODIFIERS => "mi",
+            GESHI_BEFORE => "",
+            GESHI_AFTER => ""
+            ),
+        //IP addresses
+        4 => array(
+            GESHI_SEARCH => "(?<=\s)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(?=\s)|".
+                "(?<=\[)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(?=\])|".
+                "(?<==)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(?=<)",
+            GESHI_REPLACE => "\\0",
+            GESHI_MODIFIERS => "i",
+            GESHI_BEFORE => "",
+            GESHI_AFTER => ""
+            ),
+        //Field-Assignments
+        5 => array(
+            GESHI_SEARCH => "(?<=\s)[A-Z0-9\-]+(?==(?!\s|$))",
+            GESHI_REPLACE => "\\0",
+            GESHI_MODIFIERS => "mi",
+            GESHI_BEFORE => "",
+            GESHI_AFTER => ""
+            ),
+        //MIME type
+        6 => array(
+            GESHI_SEARCH => "(?<=\s)(?:audio|application|image|multipart|text|".
+                "video|x-[a-z0-9\-]+)\/[a-z0-9][a-z0-9\-]*(?=\s|<|$)",
+            GESHI_REPLACE => "\\0",
+            GESHI_MODIFIERS => "m",
+            GESHI_BEFORE => "",
+            GESHI_AFTER => ""
+            )
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_ALWAYS,
+    'SCRIPT_DELIMITERS' => array(
+        0 => "/(^)[A-Z][a-zA-Z0-9\-]*\s*:\s*(?:.|(?=\n\s)\n)*($)/m"
+    ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        0 => true,
+        ),
+    'TAB_WIDTH' => 4,
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            2 => array(
+                'DISALLOWED_BEFORE' => '(?<=\A\x20|\n)',
+                'DISALLOWED_AFTER' => '(?=\s*:)',
+            ),
+            3 => array(
+                'DISALLOWED_BEFORE' => '(?<=\A\x20|\n)',
+                'DISALLOWED_AFTER' => '(?=\s*:)',
+            ),
+            4 => array(
+                'DISALLOWED_BEFORE' => '(?<=\s)',
+                'DISALLOWED_AFTER' => '(?=\s|\b)',
+            )
+        ),
+        'ENABLE_FLAGS' => array(
+            'BRACKETS' => GESHI_NEVER,
+            'COMMENTS' => GESHI_NEVER,
+            'NUMBERS' => GESHI_NEVER
+        )
+    )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/fortran.php b/examples/includes/geshi/geshi/fortran.php
new file mode 100644 (file)
index 0000000..1caf09d
--- /dev/null
@@ -0,0 +1,160 @@
+<?php
+/*************************************************************************************
+ * fortran.php
+ * -----------
+ * Author: Cedric Arrabie (cedric.arrabie@univ-pau.fr)
+ * Copyright: (C) 2006 Cetric Arrabie
+ * Release Version: 1.0.8.3
+ * Date Started: 2006/04/22
+ *
+ * Fortran language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *   -  Added description of extra language features (SF#1970248)
+ * 2006/04/20 (1.0.0)
+ *   -  First Release
+ *
+ * TODO
+ * -------------------------
+ *  -  Get a list of inbuilt functions to add (and explore fortran more
+ *     to complete this rather bare language file)
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME'=>'Fortran',
+    'COMMENT_SINGLE'=> array(1 =>'!',2=>'Cf2py'),
+    'COMMENT_MULTI'=> array(),
+    //Fortran Comments
+    'COMMENT_REGEXP' => array(1 => '/^C.*?$/mi'),
+    'CASE_KEYWORDS'=> GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS'=> array("'",'"'),
+    'ESCAPE_CHAR'=>'\\',
+    'KEYWORDS'=> array(
+        1 => array(
+            'allocate','block','call','case','contains','continue','cycle','deallocate',
+            'default','do','else','elseif','elsewhere','end','enddo','endif','endwhere',
+            'entry','exit','function','go','goto','if','interface','module','nullify','only',
+            'operator','procedure','program','recursive','return','select','stop',
+            'subroutine','then','to','where','while',
+            'access','action','advance','blank','blocksize','carriagecontrol',
+            'delim','direct','eor','err','exist','file','flen','fmt','form','formatted',
+            'iostat','name','named','nextrec','nml','number','opened','pad','position',
+            'readwrite','recl','sequential','status','unformatted','unit'
+            ),
+        2 => array(
+            '.AND.','.EQ.','.EQV.','.GE.','.GT.','.LE.','.LT.','.NE.','.NEQV.','.NOT.',
+            '.OR.','.TRUE.','.FALSE.'
+            ),
+        3 => array(
+            'allocatable','character','common','complex','data','dimension','double',
+            'equivalence','external','implicit','in','inout','integer','intent','intrinsic',
+            'kind','logical','namelist','none','optional','out','parameter','pointer',
+            'private','public','real','result','save','sequence','target','type','use'
+            ),
+        4 => array(
+            'abs','achar','acos','adjustl','adjustr','aimag','aint','all','allocated',
+            'anint','any','asin','atan','atan2','bit_size','break','btest','carg',
+            'ceiling','char','cmplx','conjg','cos','cosh','cpu_time','count','cshift',
+            'date_and_time','dble','digits','dim','dot_product','dprod dvchk',
+            'eoshift','epsilon','error','exp','exponent','floor','flush','fraction',
+            'getcl','huge','iachar','iand','ibclr','ibits','ibset','ichar','ieor','index',
+            'int','intrup','invalop','ior','iostat_msg','ishft','ishftc','lbound',
+            'len','len_trim','lge','lgt','lle','llt','log','log10','matmul','max','maxexponent',
+            'maxloc','maxval','merge','min','minexponent','minloc','minval','mod','modulo',
+            'mvbits','nbreak','ndperr','ndpexc','nearest','nint','not','offset','ovefl',
+            'pack','precfill','precision','present','product','prompt','radix',
+            'random_number','random_seed','range','repeat','reshape','rrspacing',
+            'scale','scan','segment','selected_int_kind','selected_real_kind',
+            'set_exponent','shape','sign','sin','sinh','size','spacing','spread','sqrt',
+            'sum system','system_clock','tan','tanh','timer','tiny','transfer','transpose',
+            'trim','ubound','undfl','unpack','val','verify'
+            ),
+        ),
+    'SYMBOLS'=> array(
+        '(',')','{','}','[',']','=','+','-','*','/','!','%','^','&',':'
+        ),
+    'CASE_SENSITIVE'=> array(
+        GESHI_COMMENTS => true,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        ),
+    'STYLES'=> array(
+        'KEYWORDS'=> array(
+            1 =>'color: #b1b100;',
+            2 =>'color: #000000; font-weight: bold;',
+            3 =>'color: #000066;',
+            4 =>'color: #993333;'
+            ),
+        'COMMENTS'=> array(
+            1 =>'color: #666666; font-style: italic;',
+            2 =>'color: #339933;',
+            'MULTI'=>'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR'=> array(
+            0 =>'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS'=> array(
+            0 =>'color: #009900;'
+            ),
+        'STRINGS'=> array(
+            0 =>'color: #ff0000;'
+            ),
+        'NUMBERS'=> array(
+            0 =>'color: #cc66cc;'
+            ),
+        'METHODS'=> array(
+            1 =>'color: #202020;',
+            2 =>'color: #202020;'
+            ),
+        'SYMBOLS'=> array(
+            0 =>'color: #339933;'
+            ),
+        'REGEXPS'=> array(
+            ),
+        'SCRIPT'=> array(
+            )
+        ),
+    'URLS'=> array(
+        1 =>'',
+        2 =>'',
+        3 =>'',
+        4 =>''
+        ),
+    'OOLANG'=> true,
+    'OBJECT_SPLITTERS'=> array(
+        1 =>'.',
+        2 =>'::'
+        ),
+    'REGEXPS'=> array(
+        ),
+    'STRICT_MODE_APPLIES'=> GESHI_NEVER,
+    'SCRIPT_DELIMITERS'=> array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK'=> array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/freebasic.php b/examples/includes/geshi/geshi/freebasic.php
new file mode 100644 (file)
index 0000000..0ddc46c
--- /dev/null
@@ -0,0 +1,141 @@
+<?php
+/*************************************************************************************
+ * freebasic.php
+ * -------------
+ * Author: Roberto Rossi
+ * Copyright: (c) 2005 Roberto Rossi (http://rsoftware.altervista.org)
+ * Release Version: 1.0.8.3
+ * Date Started: 2005/08/19
+ *
+ * FreeBasic (http://www.freebasic.net/) language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2005/08/19 (1.0.0)
+ *  -  First Release
+ *
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'FreeBasic',
+    'COMMENT_SINGLE' => array(1 => "'", 2 => '#'),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            "append", "as", "asc", "asin", "asm", "atan2", "atn", "beep", "bin", "binary", "bit",
+            "bitreset", "bitset", "bload", "bsave", "byref", "byte", "byval", "call",
+            "callocate", "case", "cbyte", "cdbl", "cdecl", "chain", "chdir", "chr", "cint",
+            "circle", "clear", "clng", "clngint", "close", "cls", "color", "command",
+            "common", "cons", "const", "continue", "cos", "cshort", "csign", "csng",
+            "csrlin", "cubyte", "cuint", "culngint", "cunsg", "curdir", "cushort", "custom",
+            "cvd", "cvi", "cvl", "cvlongint", "cvs", "cvshort", "data", "date",
+            "deallocate", "declare", "defbyte", "defdbl", "defined", "defint", "deflng",
+            "deflngint", "defshort", "defsng", "defstr", "defubyte", "defuint",
+            "defulngint", "defushort", "dim", "dir", "do", "double", "draw", "dylibload",
+            "dylibsymbol", "else", "elseif", "end", "enum", "environ", 'environ$', "eof",
+            "eqv", "erase", "err", "error", "exec", "exepath", "exit", "exp", "export",
+            "extern", "field", "fix", "flip", "for", "fre", "freefile", "function", "get",
+            "getjoystick", "getkey", "getmouse", "gosub", "goto", "hex", "hibyte", "hiword",
+            "if", "iif", "imagecreate", "imagedestroy", "imp", "inkey", "inp", "input",
+            "instr", "int", "integer", "is", "kill", "lbound", "lcase", "left", "len",
+            "let", "lib", "line", "lobyte", "loc", "local", "locate", "lock", "lof", "log",
+            "long", "longint", "loop", "loword", "lset", "ltrim", "mid", "mkd", "mkdir",
+            "mki", "mkl", "mklongint", "mks", "mkshort", "mod", "multikey", "mutexcreate",
+            "mutexdestroy", "mutexlock", "mutexunlock", "name", "next", "not", "oct", "on",
+            "once", "open", "option", "or", "out", "output", "overload", "paint", "palette",
+            "pascal", "pcopy", "peek", "peeki", "peeks", "pipe", "pmap", "point", "pointer",
+            "poke", "pokei", "pokes", "pos", "preserve", "preset", "print", "private",
+            "procptr", "pset", "ptr", "public", "put", "random", "randomize", "read",
+            "reallocate", "redim", "rem", "reset", "restore", "resume",
+            "return", "rgb", "rgba", "right", "rmdir", "rnd", "rset", "rtrim", "run",
+            "sadd", "screen", "screencopy", "screeninfo", "screenlock", "screenptr",
+            "screenres", "screenset", "screensync", "screenunlock", "seek", "statement",
+            "selectcase", "setdate", "setenviron", "setmouse",
+            "settime", "sgn", "shared", "shell", "shl", "short", "shr", "sin", "single",
+            "sizeof", "sleep", "space", "spc", "sqr", "static", "stdcall", "step", "stop",
+            "str", "string", "strptr", "sub", "swap", "system", "tab", "tan",
+            "then", "threadcreate", "threadwait", "time", "timer", "to", "trans",
+            "trim", "type", "ubound", "ubyte", "ucase", "uinteger", "ulongint", "union",
+            "unlock", "unsigned", "until", "ushort", "using", "va_arg", "va_first",
+            "va_next", "val", "val64", "valint", "varptr", "view", "viewprint", "wait",
+            "wend", "while", "width", "window", "windowtitle", "with", "write", "xor",
+            "zstring", "explicit", "escape", "true", "false"
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080;',
+            2 => 'color: #339933;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/genero.php b/examples/includes/geshi/geshi/genero.php
new file mode 100644 (file)
index 0000000..997e21f
--- /dev/null
@@ -0,0 +1,463 @@
+<?php
+/*************************************************************************************
+ * genero.php
+ * ----------
+ * Author: Lars Gersmann (lars.gersmann@gmail.com)
+ * Copyright: (c) 2007 Lars Gersmann, Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2007/07/01
+ *
+ * Genero (FOURJ's Genero 4GL) language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2007/07/01 (1.0.0)
+ *  -  Initial release
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'genero',
+    'COMMENT_SINGLE' => array(1 => '--', 2 => '#'),
+    'COMMENT_MULTI' => array('{' => '}'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            "ABSOLUTE",
+            "ACCEPT",
+            "ACTION",
+            "ADD",
+            "AFTER",
+            "ALL",
+            "ALTER",
+            "AND",
+            "ANY",
+            "APPEND",
+            "APPLICATION",
+            "AS",
+            "AT",
+            "ATTRIBUTE",
+            "ATTRIBUTES",
+            "AUDIT",
+            "AVG",
+            "BEFORE",
+            "BEGIN",
+            "BETWEEN",
+            "BORDER",
+            "BOTTOM",
+            "BREAKPOINT",
+            "BUFFER",
+            "BUFFERED",
+            "BY",
+            "CALL",
+            "CANCEL",
+            "CASE",
+            "CENTURY",
+            "CHANGE",
+            "CHECK",
+            "CLEAR",
+            "CLIPPED",
+            "CLOSE",
+            "CLUSTER",
+            "COLUMN",
+            "COLUMNS",
+            "COMMAND",
+            "COMMENT",
+            "COMMIT",
+            "COMMITTED",
+            "CONCURRENT ",
+            "CONNECT",
+            "CONNECTION",
+            "CONSTANT",
+            "CONSTRAINED",
+            "CONSTRAINT",
+            "CONSTRUCT",
+            "CONTINUE",
+            "CONTROL",
+            "COUNT",
+            "CREATE",
+            "CROSS",
+            "CURRENT",
+            "DATABASE",
+            "DBA",
+            "DEC",
+            "DECLARE",
+            "DEFAULT",
+            "DEFAULTS",
+            "DEFER",
+            "DEFINE",
+            "DELETE",
+            "DELIMITER",
+            "DESCRIBE",
+            "DESTINATION",
+            "DIM",
+            "DIALOG",
+            "DIMENSION",
+            "DIRTY",
+            "DISCONNECT",
+            "DISPLAY",
+            "DISTINCT",
+            "DORMANT",
+            "DOWN",
+            "DROP",
+            "DYNAMIC",
+            "ELSE",
+            "END",
+            "ERROR",
+            "ESCAPE",
+            "EVERY",
+            "EXCLUSIVE",
+            "EXECUTE",
+            "EXISTS",
+            "EXIT",
+            "EXPLAIN",
+            "EXTEND",
+            "EXTENT",
+            "EXTERNAL",
+            "FETCH",
+            "FGL_DRAWBOX",
+            "FIELD",
+            "FIELD_TOUCHED",
+            "FILE",
+            "FILL",
+            "FINISH",
+            "FIRST",
+            "FLOAT",
+            "FLUSH",
+            "FOR",
+            "FOREACH",
+            "FORM",
+            "FORMAT",
+            "FOUND",
+            "FRACTION",
+            "FREE",
+            "FROM",
+            "FULL",
+            "FUNCTION",
+            "GET_FLDBUF",
+            "GLOBALS",
+            "GO",
+            "GOTO",
+            "GRANT",
+            "GROUP",
+            "HAVING",
+            "HEADER",
+            "HELP",
+            "HIDE",
+            "HOLD",
+            "HOUR",
+            "IDLE",
+            "IF",
+            "IMAGE",
+            "IMMEDIATE",
+            "IN",
+            "INDEX",
+            "INFIELD",
+            "INITIALIZE",
+            "INNER",
+            "INPUT",
+            "INSERT",
+            "INTERRUPT",
+            "INTERVAL",
+            "INTO",
+            "INVISIBLE",
+            "IS",
+            "ISOLATION",
+            "JOIN",
+            "KEEP",
+            "KEY",
+            "LABEL",
+            "LAST",
+            "LEFT",
+            "LENGTH",
+            "LET",
+            "LIKE",
+            "LINE",
+            "LINENO",
+            "LINES",
+            "LOAD",
+            "LOCATE",
+            "LOCK",
+            "LOG",
+            "LSTR",
+            "MAIN",
+            "MARGIN",
+            "MATCHES",
+            "MAX",
+            "MAXCOUNT",
+            "MDY",
+            "MEMORY",
+            "MENU",
+            "MESSAGE",
+            "MIN",
+            "MINUTE",
+            "MOD",
+            "MODE",
+            "MODIFY",
+            "MONEY",
+            "NAME",
+            "NEED",
+            "NEXT",
+            "NO",
+            "NORMAL",
+            "NOT",
+            "NOTFOUND",
+            "NULL",
+            "NUMERIC",
+            "OF",
+            "ON",
+            "OPEN",
+            "OPTION",
+            "OPTIONS",
+            "OR",
+            "ORDER",
+            "OTHERWISE",
+            "OUTER",
+            "OUTPUT",
+            "PAGE",
+            "PAGENO",
+            "PAUSE",
+            "PERCENT",
+            "PICTURE",
+            "PIPE",
+            "PRECISION",
+            "PREPARE",
+            "PREVIOUS",
+            "PRINT",
+            "PRINTER",
+            "PRINTX",
+            "PRIOR",
+            "PRIVILEGES",
+            "PROCEDURE",
+            "PROGRAM",
+            "PROMPT",
+            "PUBLIC",
+            "PUT",
+            "QUIT",
+            "READ",
+            "REAL",
+            "RECORD",
+            "RECOVER",
+            "RED ",
+            "RELATIVE",
+            "RENAME",
+            "REOPTIMIZATION",
+            "REPEATABLE",
+            "REPORT",
+            "RESOURCE",
+            "RETURN",
+            "RETURNING",
+            "REVERSE",
+            "REVOKE",
+            "RIGHT",
+            "ROLLBACK",
+            "ROLLFORWARD",
+            "ROW",
+            "ROWS",
+            "RUN",
+            "SCHEMA",
+            "SCREEN",
+            "SCROLL",
+            "SECOND",
+            "SELECT",
+            "SERIAL",
+            "SET",
+            "SFMT",
+            "SHARE",
+            "SHIFT",
+            "SHOW",
+            "SIGNAL ",
+            "SIZE",
+            "SKIP",
+            "SLEEP",
+            "SOME",
+            "SPACE",
+            "SPACES",
+            "SQL",
+            "SQLERRMESSAGE",
+            "SQLERROR",
+            "SQLSTATE",
+            "STABILITY",
+            "START",
+            "STATISTICS",
+            "STEP",
+            "STOP",
+            "STYLE",
+            "SUM",
+            "SYNONYM",
+            "TABLE",
+            "TEMP",
+            "TERMINATE",
+            "TEXT",
+            "THEN",
+            "THROUGH",
+            "THRU",
+            "TO",
+            "TODAY",
+            "TOP",
+            "TRAILER",
+            "TRANSACTION ",
+            "UNBUFFERED",
+            "UNCONSTRAINED",
+            "UNDERLINE",
+            "UNION",
+            "UNIQUE",
+            "UNITS",
+            "UNLOAD",
+            "UNLOCK",
+            "UP",
+            "UPDATE",
+            "USE",
+            "USER",
+            "USING",
+            "VALIDATE",
+            "VALUE",
+            "VALUES",
+            "VARCHAR",
+            "VIEW",
+            "WAIT",
+            "WAITING",
+            "WARNING",
+            "WHEN",
+            "WHENEVER",
+            "WHERE",
+            "WHILE",
+            "WINDOW",
+            "WITH",
+            "WITHOUT",
+            "WORDWRAP",
+            "WORK",
+            "WRAP"
+            ),
+        2 => array(
+            '&amp;IFDEF', '&amp;ENDIF'
+            ),
+        3 => array(
+            "ARRAY",
+            "BYTE",
+            "CHAR",
+            "CHARACTER",
+            "CURSOR",
+            "DATE",
+            "DATETIME",
+            "DECIMAL",
+            "DOUBLE",
+            "FALSE",
+            "INT",
+            "INTEGER",
+            "SMALLFLOAT",
+            "SMALLINT",
+            "STRING",
+            "TIME",
+            "TRUE"
+            ),
+        4 => array(
+            "BLACK",
+            "BLINK",
+            "BLUE",
+            "BOLD",
+            "ANSI",
+            "ASC",
+            "ASCENDING",
+            "ASCII",
+            "CYAN",
+            "DESC",
+            "DESCENDING",
+            "GREEN",
+            "MAGENTA",
+            "OFF",
+            "WHITE",
+            "YELLOW",
+            "YEAR",
+            "DAY",
+            "MONTH",
+            "WEEKDAY"
+            ),
+        ),
+    'SYMBOLS' => array(
+        '+', '-', '*', '?', '=', '/', '%', '>', '<', '^', '!', '|', ':',
+        '(', ')', '[', ']'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0600FF;',
+            2 => 'color: #0000FF; font-weight: bold;',
+            3 => 'color: #008000;',
+            4 => 'color: #FF0000;',
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #008080; font-style: italic;',
+            2 => 'color: #008080;',
+            'MULTI' => 'color: #008080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #008080; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000000;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #808080;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #FF0000;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #0000FF;',
+            2 => 'color: #0000FF;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #008000;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/gettext.php b/examples/includes/geshi/geshi/gettext.php
new file mode 100644 (file)
index 0000000..78e8bff
--- /dev/null
@@ -0,0 +1,97 @@
+<?php
+/*************************************************************************************
+ * gettext.php
+ * --------
+ * Author: Milian Wolff (mail@milianw.de)
+ * Copyright: (c) 2008 Milian Wolff
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/05/25
+ *
+ * GNU Gettext .po/.pot language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/08/02 (1.0.8)
+ *  -  New comments: flags and previous-fields
+ *  -  New keywords: msgctxt, msgid_plural
+ *  -  Msgstr array indices
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'GNU Gettext',
+    'COMMENT_SINGLE' => array('#:', '#.', '#,', '#|', '#'),
+    'COMMENT_MULTI' => array(),
+    'COMMENT_REGEXP' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array('msgctxt', 'msgid_plural', 'msgid', 'msgstr'),
+    ),
+    'SYMBOLS' => array(),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+    ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000000; font-weight: bold;'
+        ),
+        'COMMENTS' => array(
+            0 => 'color: #000099;',
+            1 => 'color: #000099;',
+            2 => 'color: #000099;',
+            3 => 'color: #006666;',
+            4 => 'color: #666666; font-style: italic;',
+        ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+        ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+        ),
+        'REGEXPS' => array(),
+        'SYMBOLS' => array(),
+        'NUMBERS' => array(
+            0 => 'color: #000099;'
+        ),
+        'METHODS' => array(),
+        'SCRIPT' => array(),
+        'BRACKETS' => array(
+            0 => 'color: #000099;'
+        ),
+    ),
+    'URLS' => array(
+        1 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(),
+    'REGEXPS' => array(),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4,
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/glsl.php b/examples/includes/geshi/geshi/glsl.php
new file mode 100644 (file)
index 0000000..1f10cf8
--- /dev/null
@@ -0,0 +1,205 @@
+<?php
+/*************************************************************************************
+ * glsl.php
+ * -----
+ * Author: Benny Baumann (BenBE@omorphia.de)
+ * Copyright: (c) 2008 Benny Baumann (BenBE@omorphia.de)
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/03/20
+ *
+ * glSlang language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/03/20 (1.0.7.21)
+ *   -  First Release
+ *
+ * TODO
+ * ----
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'glSlang',
+    'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'COMMENT_REGEXP' => array(
+        //Multiline-continued single-line comments
+        1 => '/\/\/(?:\\\\\\\\|\\\\\\n|.)*$/m',
+        //Multiline-continued preprocessor define
+        2 => '/#(?:\\\\\\\\|\\\\\\n|.)*$/m'
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'if', 'else', 'for', 'while', 'do', 'break', 'continue', 'asm',
+            'switch', 'case', 'default', 'return', 'discard',
+            'namespace', 'using', 'sizeof', 'cast'
+            ),
+        2 => array(
+            'const', 'uniform', 'attribute', 'centroid', 'varying', 'invariant',
+            'in', 'out', 'inout', 'input', 'output', 'typedef', 'volatile',
+            'public', 'static', 'extern', 'external', 'packed',
+            'inline', 'noinline', 'noperspective', 'flat'
+            ),
+        3 => array(
+            'void', 'bool', 'int', 'long', 'short', 'float', 'half', 'fixed',
+            'unsigned', 'lowp', 'mediump', 'highp', 'precision',
+            'vec2', 'vec3', 'vec4', 'bvec2', 'bvec3', 'bvec4',
+            'dvec2', 'dvec3', 'dvec4', 'fvec2', 'fvec3', 'fvec4',
+            'hvec2', 'hvec3', 'hvec4', 'ivec2', 'ivec3', 'ivec4',
+            'mat2', 'mat3', 'mat4', 'mat2x2', 'mat3x2', 'mat4x2',
+            'mat2x3', 'mat3x3', 'mat4x3', 'mat2x4', 'mat3x4', 'mat4x4',
+            'sampler1D', 'sampler2D', 'sampler3D', 'samplerCube',
+            'sampler1DShadow', 'sampler2DShadow',
+            'struct', 'class', 'union', 'enum', 'interface', 'template'
+            ),
+        4 => array(
+            'this', 'false', 'true'
+            ),
+        5 => array(
+            'radians', 'degrees', 'sin', 'cos', 'tan', 'asin', 'acos', 'atan',
+            'pow', 'exp2', 'log2', 'sqrt', 'inversesqrt', 'abs', 'sign', 'ceil',
+            'floor', 'fract', 'mod', 'min', 'max', 'clamp', 'mix', 'step',
+            'smoothstep', 'length', 'distance', 'dot', 'cross', 'normalize',
+            'ftransform', 'faceforward', 'reflect', 'matrixCompMult', 'equal',
+            'lessThan', 'lessThanEqual', 'greaterThan', 'greaterThanEqual',
+            'notEqual', 'any', 'all', 'not', 'texture1D', 'texture1DProj',
+            'texture1DLod', 'texture1DProjLod', 'texture2D', 'texture2DProj',
+            'texture2DLod', 'texture2DProjLod', 'texture3D', 'texture3DProj',
+            'texture3DLod', 'texture3DProjLod', 'textureCube', 'textureCubeLod',
+            'shadow1D', 'shadow1DProj', 'shadow1DLod', 'shadow1DProjLod',
+            'shadow2D', 'shadow2DProj', 'shadow2DLod', 'shadow2DProjLod',
+            'noise1', 'noise2', 'noise3', 'noise4'
+            ),
+        6 => array(
+            'gl_Position', 'gl_PointSize', 'gl_ClipVertex', 'gl_FragColor',
+            'gl_FragData', 'gl_FragDepth', 'gl_FragCoord', 'gl_FrontFacing',
+            'gl_Color', 'gl_SecondaryColor', 'gl_Normal', 'gl_Vertex',
+            'gl_MultiTexCoord0', 'gl_MultiTexCoord1', 'gl_MultiTexCoord2',
+            'gl_MultiTexCoord3', 'gl_MultiTexCoord4', 'gl_MultiTexCoord5',
+            'gl_MultiTexCoord6', 'gl_MultiTexCoord7', 'gl_FogCoord',
+            'gl_MaxLights', 'gl_MaxClipPlanes', 'gl_MaxTextureUnits',
+            'gl_MaxTextureCoords', 'gl_MaxVertexAttribs', 'gl_MaxVaryingFloats',
+            'gl_MaxVertexUniformComponents', 'gl_MaxVertexTextureImageUnits',
+            'gl_MaxCombinedTextureImageUnits', 'gl_MaxTextureImageUnits',
+            'gl_MaxFragmentUniformComponents', 'gl_MaxDrawBuffers', 'gl_Point',
+            'gl_ModelViewMatrix', 'gl_ProjectionMatrix', 'gl_FrontMaterial',
+            'gl_ModelViewProjectionMatrix', 'gl_TextureMatrix', 'gl_ClipPlane',
+            'gl_NormalMatrix', 'gl_ModelViewMatrixInverse', 'gl_BackMaterial',
+            'gl_ProjectionMatrixInverse', 'gl_ModelViewProjectionMatrixInverse',
+            'gl_TextureMatrixInverse', 'gl_ModelViewMatrixTranspose', 'gl_Fog',
+            'gl_ProjectionMatrixTranspose', 'gl_NormalScale', 'gl_DepthRange',
+            'gl_odelViewProjectionMatrixTranspose', 'gl_TextureMatrixTranspose',
+            'gl_ModelViewMatrixInverseTranspose', 'gl_LightSource',
+            'gl_ProjectionMatrixInverseTranspose', 'gl_LightModel',
+            'gl_ModelViewProjectionMatrixInverseTranspose', 'gl_TexCoord',
+            'gl_TextureMatrixInverseTranspose', 'gl_TextureEnvColor',
+            'gl_FrontLightModelProduct', 'gl_BackLightModelProduct',
+            'gl_FrontLightProduct', 'gl_BackLightProduct', 'gl_ObjectPlaneS',
+            'gl_ObjectPlaneT', 'gl_ObjectPlaneR', 'gl_ObjectPlaneQ',
+            'gl_EyePlaneS', 'gl_EyePlaneT', 'gl_EyePlaneR', 'gl_EyePlaneQ',
+            'gl_FrontColor', 'gl_BackColor', 'gl_FrontSecondaryColor',
+            'gl_BackSecondaryColor', 'gl_FogFragCoord', 'gl_PointCoord'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '{', '}', '[', ']', '=', '+', '-', '*', '/', '!', '%', '^',
+        '&', '?', ':', '.', '|', ';', ',', '<', '>'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true,
+        5 => true,
+        6 => true,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000000; font-weight: bold;',
+            2 => 'color: #333399; font-weight: bold;',
+            3 => 'color: #000066; font-weight: bold;',
+            4 => 'color: #333399; font-weight: bold;',
+            5 => 'color: #993333; font-weight: bold;',
+            6 => 'color: #551111;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #666666; font-style: italic;',
+            2 => 'color: #009900;',
+            'MULTI' => 'color: #666666; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000066;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #0000ff;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006600;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000066;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => '',
+        5 => '',
+        6 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4,
+    'PARSER_CONTROL' => array(
+        'OOLANG' => array(
+            'MATCH_BEFORE' => '',
+            'MATCH_AFTER' => '[a-zA-Z_][a-zA-Z0-9_]*',
+            'MATCH_SPACES' => '[\s]*'
+        )
+    )
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/gml.php b/examples/includes/geshi/geshi/gml.php
new file mode 100644 (file)
index 0000000..77966bc
--- /dev/null
@@ -0,0 +1,506 @@
+<?php
+/*************************************************************************************
+ * gml.php
+ * --------
+ * Author: Jos� Jorge Enr�quez (jenriquez@users.sourceforge.net)
+ * Copyright: (c) 2005 Jos� Jorge Enr�quez Rodr�guez (http://www.zonamakers.com)
+ * Release Version: 1.0.8.3
+ * Date Started: 2005/06/21
+ *
+ * GML language file for GeSHi.
+ *
+ * GML (Game Maker Language) is a script language that is built-in into Game Maker,
+ * a game creation program, more info about Game Maker can be found at
+ * http://www.gamemaker.nl/
+ * All GML keywords were extracted from the Game Maker HTML Help file using a PHP
+ * script (one section at a time). I love PHP for saving me that bunch of work :P!.
+ * I think all GML functions have been indexed here, but I'm not sure about it, so
+ * please let me know of any issue you may find.
+ *
+ * CHANGES
+ * -------
+ * 2005/11/11
+ *  -  Changed 'CASE_KEYWORDS' fom 'GESHI_CAPS_LOWER' to 'GESHI_CAPS_NO_CHANGE',
+ *     so that MCI_command appears correctly (the only GML function using capitals).
+ *  -  Changed 'CASE_SENSITIVE' options, 'GESHI_COMMENTS' from true to false and all
+ *     of the others from false to true.
+ *  -  Deleted repeated entries.
+ *  -  div and mod are language keywords, moved (from symbols) to the appropiate section (1).
+ *  -  Moved self, other, all, noone and global identifiers to language keywords section 1.
+ *  -  Edited this file lines to a maximum width of 100 characters (as stated in
+ *     the GeSHi docs). Well, not strictly to 100 but around it.
+ *  -  Corrected some minor issues (the vk_f1...vk_f12 keys and similar).
+ *  -  Deleted the KEYWORDS=>5 and KEYWORDS=>6 sections (actually, they were empty).
+ *     I was planning of using those for the GML functions available only in the
+ *     registered version of the program, but not anymore.
+ *
+ * 2005/06/26 (1.0.3)
+ *  -  First Release.
+ *
+ * TODO (updated 2005/11/11)
+ * -------------------------
+ *  -  Test it for a while and make the appropiate corrections.
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'GML',
+    'COMMENT_SINGLE' => array(1 => '//'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'"),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        // language keywords
+        1 => array(
+            'break', 'continue', 'do', 'until', 'if', 'else',
+            'exit', 'for', 'repeat', 'return', 'switch',
+            'case', 'default', 'var', 'while', 'with', 'div', 'mod',
+            // GML Language overview
+            'self', 'other', 'all', 'noone', 'global',
+            ),
+        // modifiers and built-in variables
+        2 => array(
+            // Game play
+            'x','y','xprevious','yprevious','xstart','ystart','hspeed','vspeed','direction','speed',
+            'friction','gravity','gravity_direction',
+            'path_index','path_position','path_positionprevious','path_speed','path_orientation',
+            'path_endaction',
+            'object_index','id','mask_index','solid','persistent','instance_count','instance_id',
+            'room_speed','fps','current_time','current_year','current_month','current_day','current_weekday',
+            'current_hour','current_minute','current_second','alarm','timeline_index','timeline_position',
+            'timeline_speed',
+            'room','room_first','room_last','room_width','room_height','room_caption','room_persistent',
+            'score','lives','health','show_score','show_lives','show_health','caption_score','caption_lives',
+            'caption_health',
+            'event_type','event_number','event_object','event_action',
+            'error_occurred','error_last',
+            // User interaction
+            'keyboard_lastkey','keyboard_key','keyboard_lastchar','keyboard_string',
+            'mouse_x','mouse_y','mouse_button','mouse_lastbutton',
+            // Game Graphics
+            'sprite_index','sprite_width','sprite_height','sprite_xoffset','sprite_yoffset',
+            'image_number','image_index','image_speed','image_xscale','image_yscale','image_angle',
+            'image_alpha','image_blend','bbox_left','bbox_right','bbox_top','bbox_bottom',
+            'background_color','background_showcolor','background_visible','background_foreground',
+            'background_index','background_x','background_y','background_width','background_height',
+            'background_htiled','background_vtiled','background_xscale','background_yscale',
+            'background_hspeed','background_vspeed','background_blend','background_alpha',
+            'background','left, top, width, height','depth','visible','xscale','yscale','blend','alpha',
+            'view_enabled','view_current','view_visible','view_yview','view_wview','view_hview','view_xport',
+            'view_yport','view_wport','view_hport','view_angle','view_hborder','view_vborder','view_hspeed',
+            'view_vspeed','view_object',
+            'transition_kind',
+            // Files, registry and executing programs
+            'game_id','working_directory','temp_directory',
+            'secure_mode',
+            // Creating particles
+            'xmin', 'xmax', 'ymin', 'ymax','shape','distribution','particle type','number',
+            'force','dist','kind','additive', 'parttype1', 'parttype2'
+            ),
+        // functions
+        3 => array(
+            // Computing things
+            'random','choose','abs','sign','round','floor','ceil','frac','sqrt','sqr','power','exp','ln',
+            'log2','log10','logn','sin','cos','tan','arcsin','arccos','arctan','arctan2','degtorad',
+            'radtodeg','min','max','mean','median','point_distance','point_direction','lengthdir_x',
+            'lengthdir_y','is_real','is_string',
+            'chr','ord','real','string','string_format','string_length','string_pos','string_copy',
+            'string_char_at','string_delete','string_insert','string_replace','string_replace_all',
+            'string_count','string_lower','string_upper','string_repeat','string_letters','string_digits',
+            'string_lettersdigits','clipboard_has_text','clipboard_get_text','clipboard_set_text',
+            'date_current_datetime','date_current_date','date_current_time','date_create_datetime',
+            'date_create_date','date_create_time','date_valid_datetime','date_valid_date','date_valid_time',
+            'date_inc_year','date_inc_month','date_inc_week','date_inc_day','date_inc_hour',
+            'date_inc_minute','date_inc_second','date_get_year','date_get_month','date_get_week',
+            'date_get_day','date_get_hour', 'date_get_minute','date_get_second','date_get_weekday',
+            'date_get_day_of_year','date_get_hour_of_year','date_get_minute_of_year',
+            'date_get_second_of_year','date_year_span','date_month_span','date_week_span','date_day_span',
+            'date_hour_span','date_minute_span','date_second_span','date_compare_datetime',
+            'date_compare_date','date_compare_time','date_date_of','date_time_of','date_datetime_string',
+            'date_date_string','date_time_string','date_days_in_month','date_days_in_year','date_leap_year',
+            'date_is_today',
+            // Game play
+            'motion_set','motion_add','place_free','place_empty','place_meeting','place_snapped',
+            'move_random','move_snap','move_wrap','move_towards_point','move_bounce_solid','move_bounce_all',
+            'move_contact_solid','move_contact_all','move_outside_solid','move_outside_all',
+            'distance_to_point','distance_to_object','position_empty','position_meeting',
+            'path_start','path_end',
+            'mp_linear_step','mp_linear_step_object','mp_potential_step','mp_potential_step_object',
+            'mp_potential_settings','mp_linear_path','mp_linear_path_object', 'mp_potential_path',
+            'mp_potential_path_object','mp_grid_create','mp_grid_destroy','mp_grid_clear_all',
+            'mp_grid_clear_cell','mp_grid_clear_rectangle','mp_grid_add_cell','mp_grid_add_rectangle',
+            'mp_grid_add_instances','mp_grid_path','mp_grid_draw',
+            'collision_point','collision_rectangle','collision_circle','collision_ellipse','collision_line',
+            'instance_find','instance_exists','instance_number','instance_position','instance_nearest',
+            'instance_furthest','instance_place','instance_create','instance_copy','instance_destroy',
+            'instance_change','position_destroy','position_change',
+            'instance_deactivate_all','instance_deactivate_object','instance_deactivate_region',
+            'instance_activate_all','instance_activate_object','instance_activate_region',
+            'sleep',
+            'room_goto','room_goto_previous','room_goto_next','room_restart','room_previous','room_next',
+            'game_end','game_restart','game_save','game_load',
+            'event_perform', 'event_perform_object','event_user','event_inherited',
+            'show_debug_message','variable_global_exists','variable_local_exists','variable_global_get',
+            'variable_global_array_get','variable_global_array2_get','variable_local_get',
+            'variable_local_array_get','variable_local_array2_get','variable_global_set',
+            'variable_global_array_set','variable_global_array2_set','variable_local_set',
+            'variable_local_array_set','variable_local_array2_set','set_program_priority',
+            // User interaction
+            'keyboard_set_map','keyboard_get_map','keyboard_unset_map','keyboard_check',
+            'keyboard_check_pressed','keyboard_check_released','keyboard_check_direct',
+            'keyboard_get_numlock','keyboard_set_numlock','keyboard_key_press','keyboard_key_release',
+            'keyboard_clear','io_clear','io_handle','keyboard_wait',
+            'mouse_check_button','mouse_check_button_pressed','mouse_check_button_released','mouse_clear',
+            'mouse_wait',
+            'joystick_exists','joystick_name','joystick_axes','joystick_buttons','joystick_has_pov',
+            'joystick_direction','joystick_check_button','joystick_xpos','joystick_ypos','joystick_zpos',
+            'joystick_rpos','joystick_upos','joystick_vpos','joystick_pov',
+            // Game Graphics
+            'draw_sprite','draw_sprite_stretched','draw_sprite_tiled','draw_sprite_part','draw_background',
+            'draw_background_stretched','draw_background_tiled','draw_background_part','draw_sprite_ext',
+            'draw_sprite_stretched_ext','draw_sprite_tiled_ext','draw_sprite_part_ext','draw_sprite_general',
+            'draw_background_ext','draw_background_stretched_ext','draw_background_tiled_ext',
+            'draw_background_part_ext','draw_background_general',
+            'draw_clear','draw_clear_alpha','draw_point','draw_line','draw_rectangle','draw_roundrect',
+            'draw_triangle','draw_circle','draw_ellipse','draw_arrow','draw_button','draw_path',
+            'draw_healthbar','draw_set_color','draw_set_alpha','draw_get_color','draw_get_alpha',
+            'make_color_rgb','make_color_hsv','color_get_red','color_get_green','color_get_blue',
+            'color_get_hue','color_get_saturation','color_get_value','merge_color','draw_getpixel',
+            'screen_save','screen_save_part',
+            'draw_set_font','draw_set_halign','draw_set_valign','draw_text','draw_text_ext','string_width',
+            'string_height','string_width_ext','string_height_ext','draw_text_transformed',
+            'draw_text_ext_transformed','draw_text_color','draw_text_ext_color',
+            'draw_text_transformed_color','draw_text_ext_transformed_color',
+            'draw_point_color','draw_line_color','draw_rectangle_color','draw_roundrect_color',
+            'draw_triangle_color','draw_circle_color','draw_ellipse_color','draw_primitive_begin',
+            'draw_vertex','draw_vertex_color','draw_primitive_end','sprite_get_texture',
+            'background_get_texture','texture_preload','texture_set_priority',
+            'texture_get_width','texture_get_height','draw_primitive_begin_texture','draw_vertex_texture',
+            'draw_vertex_texture_color','texture_set_interpolation',
+            'texture_set_blending','texture_set_repeat','draw_set_blend_mode','draw_set_blend_mode_ext',
+            'surface_create','surface_free','surface_exists','surface_get_width','surface_get_height',
+            'surface_get_texture','surface_set_target','surface_reset_target','surface_getpixel',
+            'surface_save','surface_save_part','draw_surface','draw_surface_stretched','draw_surface_tiled',
+            'draw_surface_part','draw_surface_ext','draw_surface_stretched_ext','draw_surface_tiled_ext',
+            'draw_surface_part_ext','draw_surface_general','surface_copy','surface_copy_part',
+            'tile_add','tile_delete','tile_exists','tile_get_x','tile_get_y','tile_get_left','tile_get_top',
+            'tile_get_width','tile_get_height','tile_get_depth','tile_get_visible','tile_get_xscale',
+            'tile_get_yscale','tile_get_background','tile_get_blend','tile_get_alpha','tile_set_position',
+            'tile_set_region','tile_set_background','tile_set_visible','tile_set_depth','tile_set_scale',
+            'tile_set_blend','tile_set_alpha','tile_layer_hide','tile_layer_show','tile_layer_delete',
+            'tile_layer_shift','tile_layer_find','tile_layer_delete_at','tile_layer_depth',
+            'display_get_width','display_get_height','display_get_colordepth','display_get_frequency',
+            'display_set_size','display_set_colordepth','display_set_frequency','display_set_all',
+            'display_test_all','display_reset','display_mouse_get_x','display_mouse_get_y','display_mouse_set',
+            'window_set_visible','window_get_visible','window_set_fullscreen','window_get_fullscreen',
+            'window_set_showborder','window_get_showborder','window_set_showicons','window_get_showicons',
+            'window_set_stayontop','window_get_stayontop','window_set_sizeable','window_get_sizeable',
+            'window_set_caption','window_get_caption','window_set_cursor', 'window_get_cursor',
+            'window_set_color','window_get_color','window_set_region_scale','window_get_region_scale',
+            'window_set_position','window_set_size','window_set_rectangle','window_center','window_default',
+            'window_get_x','window_get_y','window_get_width','window_get_height','window_mouse_get_x',
+            'window_mouse_get_y','window_mouse_set',
+            'window_set_region_size','window_get_region_width','window_get_region_height',
+            'window_view_mouse_get_x','window_view_mouse_get_y','window_view_mouse_set',
+            'window_views_mouse_get_x','window_views_mouse_get_y','window_views_mouse_set',
+            'screen_redraw','screen_refresh','set_automatic_draw','set_synchronization','screen_wait_vsync',
+            // Sound and music)
+            'sound_play','sound_loop','sound_stop','sound_stop_all','sound_isplaying','sound_volume',
+            'sound_global_volume','sound_fade','sound_pan','sound_background_tempo','sound_set_search_directory',
+            'sound_effect_set','sound_effect_chorus','sound_effect_echo',    'sound_effect_flanger',
+            'sound_effect_gargle','sound_effect_reverb','sound_effect_compressor','sound_effect_equalizer',
+            'sound_3d_set_sound_position','sound_3d_set_sound_velocity','sound_3d_set_sound_distance',
+            'sound_3d_set_sound_cone',
+            'cd_init','cd_present','cd_number','cd_playing','cd_paused','cd_track','cd_length',
+            'cd_track_length','cd_position','cd_track_position','cd_play','cd_stop','cd_pause','cd_resume',
+            'cd_set_position','cd_set_track_position','cd_open_door','cd_close_door','MCI_command',
+            // Splash screens, highscores, and other pop-ups
+            'show_text','show_image','show_video','show_info','load_info',
+            'show_message','show_message_ext','show_question','get_integer','get_string',
+            'message_background','message_alpha','message_button','message_text_font','message_button_font',
+            'message_input_font','message_mouse_color','message_input_color','message_caption',
+            'message_position','message_size','show_menu','show_menu_pos','get_color','get_open_filename',
+            'get_save_filename','get_directory','get_directory_alt','show_error',
+            'highscore_show','highscore_set_background','highscore_set_border','highscore_set_font',
+            'highscore_set_colors','highscore_set_strings','highscore_show_ext','highscore_clear',
+            'highscore_add','highscore_add_current','highscore_value','highscore_name','draw_highscore',
+            // Resources
+            'sprite_exists','sprite_get_name','sprite_get_number','sprite_get_width','sprite_get_height',
+            'sprite_get_transparent','sprite_get_smooth','sprite_get_preload','sprite_get_xoffset',
+            'sprite_get_yoffset','sprite_get_bbox_left','sprite_get_bbox_right','sprite_get_bbox_top',
+            'sprite_get_bbox_bottom','sprite_get_bbox_mode','sprite_get_precise',
+            'sound_exists','sound_get_name','sound_get_kind','sound_get_preload','sound_discard',
+            'sound_restore',
+            'background_exists','background_get_name','background_get_width','background_get_height',
+            'background_get_transparent','background_get_smooth','background_get_preload',
+            'font_exists','font_get_name','font_get_fontname','font_get_bold','font_get_italic',
+            'font_get_first','font_get_last',
+            'path_exists','path_get_name','path_get_length','path_get_kind','path_get_closed',
+            'path_get_precision','path_get_number','path_get_point_x','path_get_point_y',
+            'path_get_point_speed','path_get_x','path_get_y','path_get_speed',
+            'script_exists','script_get_name','script_get_text',
+            'timeline_exists','timeline_get_name',
+            'object_exists','object_get_name','object_get_sprite','object_get_solid','object_get_visible',
+            'object_get_depth','object_get_persistent','object_get_mask','object_get_parent',
+            'object_is_ancestor',
+            'room_exists','room_get_name',
+            // Changing resources
+            'sprite_set_offset','sprite_set_bbox_mode','sprite_set_bbox','sprite_set_precise',
+            'sprite_duplicate','sprite_assign','sprite_merge','sprite_add','sprite_replace',
+            'sprite_create_from_screen','sprite_add_from_screen','sprite_create_from_surface',
+            'sprite_add_from_surface','sprite_delete','sprite_set_alpha_from_sprite',
+            'sound_add','sound_replace','sound_delete',
+            'background_duplicate','background_assign','background_add','background_replace',
+            'background_create_color','background_create_gradient','background_create_from_screen',
+            'background_create_from_surface','background_delete','background_set_alpha_from_background',
+            'font_add','font_add_sprite','font_replace_sprite','font_delete',
+            'path_set_kind','path_set_closed','path_set_precision','path_add','path_delete','path_duplicate',
+            'path_assign','path_append','path_add_point','path_insert_point','path_change_point',
+            'path_delete_point','path_clear_points','path_reverse','path_mirror','path_flip','path_rotate',
+            'path_scale','path_shift',
+            'execute_string','execute_file','script_execute',
+            'timeline_add','timeline_delete','timeline_moment_add','timeline_moment_clear',
+            'object_set_sprite','object_set_solid','object_set_visible','object_set_depth',
+            'object_set_persistent','object_set_mask','object_set_parent','object_add','object_delete',
+            'object_event_add','object_event_clear',
+            'room_set_width','room_set_height','room_set_caption','room_set_persistent','room_set_code',
+            'room_set_background_color','room_set_background','room_set_view','room_set_view_enabled',
+            'room_add','room_duplicate','room_assign','room_instance_add','room_instance_clear',
+            'room_tile_add','room_tile_add_ext','room_tile_clear',
+            // Files, registry and executing programs
+            'file_text_open_read','file_text_open_write','file_text_open_append','file_text_close',
+            'file_text_write_string','file_text_write_real','file_text_writeln','file_text_read_string',
+            'file_text_read_real','file_text_readln','file_text_eof','file_exists','file_delete',
+            'file_rename','file_copy','directory_exists','directory_create','file_find_first',
+            'file_find_next','file_find_close','file_attributes', 'filename_name','filename_path',
+            'filename_dir','filename_drive','filename_ext','filename_change_ext','file_bin_open',
+            'file_bin_rewrite','file_bin_close','file_bin_size','file_bin_position','file_bin_seek',
+            'file_bin_write_byte','file_bin_read_byte','parameter_count','parameter_string',
+            'environment_get_variable',
+            'registry_write_string','registry_write_real','registry_read_string','registry_read_real',
+            'registry_exists','registry_write_string_ext','registry_write_real_ext',
+            'registry_read_string_ext','registry_read_real_ext','registry_exists_ext','registry_set_root',
+            'ini_open','ini_close','ini_read_string','ini_read_real','ini_write_string','ini_write_real',
+            'ini_key_exists','ini_section_exists','ini_key_delete','ini_section_delete',
+            'execute_program','execute_shell',
+            // Data structures
+            'ds_stack_create','ds_stack_destroy','ds_stack_clear','ds_stack_size','ds_stack_empty',
+            'ds_stack_push','ds_stack_pop','ds_stack_top',
+            'ds_queue_create','ds_queue_destroy','ds_queue_clear','ds_queue_size','ds_queue_empty',
+            'ds_queue_enqueue','ds_queue_dequeue','ds_queue_head','ds_queue_tail',
+            'ds_list_create','ds_list_destroy','ds_list_clear','ds_list_size','ds_list_empty','ds_list_add',
+            'ds_list_insert','ds_list_replace','ds_list_delete','ds_list_find_index','ds_list_find_value',
+            'ds_list_sort',
+            'ds_map_create','ds_map_destroy','ds_map_clear','ds_map_size','ds_map_empty','ds_map_add',
+            'ds_map_replace','ds_map_delete','ds_map_exists','ds_map_find_value','ds_map_find_previous',
+            'ds_map_find_next','ds_map_find_first','ds_map_find_last',
+            'ds_priority_create','ds_priority_destroy','ds_priority_clear','ds_priority_size',
+            'ds_priority_empty','ds_priority_add','ds_priority_change_priority','ds_priority_find_priority',
+            'ds_priority_delete_value','ds_priority_delete_min','ds_priority_find_min',
+            'ds_priority_delete_max','ds_priority_find_max',
+            'ds_grid_create','ds_grid_destroy','ds_grid_resize','ds_grid_width','ds_grid_height',
+            'ds_grid_clear','ds_grid_set','ds_grid_add','ds_grid_multiply','ds_grid_set_region',
+            'ds_grid_add_region','ds_grid_multiply_region','ds_grid_set_disk','ds_grid_add_disk',
+            'ds_grid_multiply_disk','ds_grid_get','ds_grid_get_sum','ds_grid_get_max','ds_grid_get_min',
+            'ds_grid_get_mean','ds_grid_get_disk_sum','ds_grid_get_disk_min','ds_grid_get_disk_max',
+            'ds_grid_get_disk_mean','ds_grid_value_exists','ds_grid_value_x','ds_grid_value_y',
+            'ds_grid_value_disk_exists','ds_grid_value_disk_x','ds_grid_value_disk_y',
+            // Creating particles
+            'effect_create_below','effect_create_above','effect_clear',
+            'part_type_create','part_type_destroy','part_type_exists','part_type_clear','part_type_shape',
+            'part_type_sprite','part_type_size','part_type_scale',
+            'part_type_orientation','part_type_color1','part_type_color2','part_type_color3',
+            'part_type_color_mix','part_type_color_rgb','part_type_color_hsv',
+            'part_type_alpha1','part_type_alpha2','part_type_alpha3','part_type_blend','part_type_life',
+            'part_type_step','part_type_death','part_type_speed','part_type_direction','part_type_gravity',
+            'part_system_create','part_system_destroy','part_system_exists','part_system_clear',
+            'part_system_draw_order','part_system_depth','part_system_position',
+            'part_system_automatic_update','part_system_automatic_draw','part_system_update',
+            'part_system_drawit','part_particles_create','part_particles_create_color',
+            'part_particles_clear','part_particles_count',
+            'part_emitter_create','part_emitter_destroy','part_emitter_destroy_all','part_emitter_exists',
+            'part_emitter_clear','part_emitter_region','part_emitter_burst','part_emitter_stream',
+            'part_attractor_create','part_attractor_destroy','part_attractor_destroy_all',
+            'part_attractor_exists','part_attractor_clear','part_attractor_position','part_attractor_force',
+            'part_destroyer_create','part_destroyer_destroy','part_destroyer_destroy_all',
+            'part_destroyer_exists','part_destroyer_clear','part_destroyer_region',
+            'part_deflector_create','part_deflector_destroy','part_deflector_destroy_all',
+            'part_deflector_exists','part_deflector_clear','part_deflector_region','part_deflector_kind',
+            'part_deflector_friction',
+            'part_changer_create','part_changer_destroy','part_changer_destroy_all','part_changer_exists',
+            'part_changer_clear','part_changer_region','part_changer_types','part_changer_kind',
+            // Multiplayer games
+            'mplay_init_ipx','mplay_init_tcpip','mplay_init_modem','mplay_init_serial',
+            'mplay_connect_status','mplay_end','mplay_ipaddress',
+            'mplay_session_create','mplay_session_find','mplay_session_name','mplay_session_join',
+            'mplay_session_mode','mplay_session_status','mplay_session_end',
+            'mplay_player_find','mplay_player_name','mplay_player_id',
+            'mplay_data_write','mplay_data_read','mplay_data_mode',
+            'mplay_message_send','mplay_message_send_guaranteed','mplay_message_receive','mplay_message_id',
+            'mplay_message_value','mplay_message_player','mplay_message_name','mplay_message_count',
+            'mplay_message_clear',
+            // Using DLL's
+            'external_define','external_call','external_free','window_handle',
+            // 3D Graphics
+            'd3d_start','d3d_end','d3d_set_hidden','d3d_set_perspective',
+            'd3d_set_depth',
+            'd3d_primitive_begin','d3d_vertex','d3d_vertex_color','d3d_primitive_end',
+            'd3d_primitive_begin_texture','d3d_vertex_texture','d3d_vertex_texture_color','d3d_set_culling',
+            'd3d_draw_block','d3d_draw_cylinder','d3d_draw_cone','d3d_draw_ellipsoid','d3d_draw_wall',
+            'd3d_draw_floor',
+            'd3d_set_projection','d3d_set_projection_ext','d3d_set_projection_ortho',
+            'd3d_set_projection_perspective',
+            'd3d_transform_set_identity','d3d_transform_set_translation','d3d_transform_set_scaling',
+            'd3d_transform_set_rotation_x','d3d_transform_set_rotation_y','d3d_transform_set_rotation_z',
+            'd3d_transform_set_rotation_axis','d3d_transform_add_translation','d3d_transform_add_scaling',
+            'd3d_transform_add_rotation_x','d3d_transform_add_rotation_y','d3d_transform_add_rotation_z',
+            'd3d_transform_add_rotation_axis','d3d_transform_stack_clear','d3d_transform_stack_empty',
+            'd3d_transform_stack_push','d3d_transform_stack_pop','d3d_transform_stack_top',
+            'd3d_transform_stack_discard',
+            'd3d_set_fog',
+            'd3d_set_lighting','d3d_set_shading','d3d_light_define_direction','d3d_light_define_point',
+            'd3d_light_enable','d3d_vertex_normal','d3d_vertex_normal_color','d3d_vertex_normal_texture',
+            'd3d_vertex_normal_texture_color',
+            'd3d_model_create','d3d_model_destroy','d3d_model_clear','d3d_model_save','d3d_model_load',
+            'd3d_model_draw','d3d_model_primitive_begin','d3d_model_vertex','d3d_model_vertex_color',
+            'd3d_model_vertex_texture','d3d_model_vertex_texture_color','d3d_model_vertex_normal',
+            'd3d_model_vertex_normal_color','d3d_model_vertex_normal_texture',
+            'd3d_model_vertex_normal_texture_color','d3d_model_primitive_end','d3d_model_block',
+            'd3d_model_cylinder','d3d_model_cone','d3d_model_ellipsoid','d3d_model_wall','d3d_model_floor'
+            ),
+        // constants
+        4 => array(
+            'true', 'false', 'pi',
+            'ev_destroy','ev_step','ev_alarm','ev_keyboard','ev_mouse','ev_collision','ev_other','ev_draw',
+            'ev_keypress','ev_keyrelease','ev_left_button','ev_right_button','ev_middle_button',
+            'ev_no_button','ev_left_press','ev_right_press','ev_middle_press','ev_left_release',
+            'ev_right_release','ev_middle_release','ev_mouse_enter','ev_mouse_leave','ev_mouse_wheel_up',
+            'ev_mouse_wheel_down','ev_global_left_button','ev_global_right_button','ev_global_middle_button',
+            'ev_global_left_press','ev_global_right_press','ev_global_middle_press','ev_global_left_release',
+            'ev_global_right_release','ev_global_middle_release','ev_joystick1_left','ev_joystick1_right',
+            'ev_joystick1_up','ev_joystick1_down','ev_joystick1_button1','ev_joystick1_button2',
+            'ev_joystick1_button3','ev_joystick1_button4','ev_joystick1_button5','ev_joystick1_button6',
+            'ev_joystick1_button7','ev_joystick1_button8','ev_joystick2_left','ev_joystick2_right',
+            'ev_joystick2_up','ev_joystick2_down','ev_joystick2_button1','ev_joystick2_button2',
+            'ev_joystick2_button3','ev_joystick2_button4','ev_joystick2_button5','ev_joystick2_button6',
+            'ev_joystick2_button7','ev_joystick2_button8',
+            'ev_outside','ev_boundary','ev_game_start','ev_game_end','ev_room_start','ev_room_end',
+            'ev_no_more_lives','ev_no_more_health','ev_animation_end','ev_end_of_path','ev_user0','ev_user1',
+            'ev_user2','ev_user3','ev_user4','ev_user5','ev_user6','ev_user7','ev_user8','ev_user9',
+            'ev_user10','ev_user11','ev_user12','ev_user13','ev_user14','ev_user15','ev_step_normal',
+            'ev_step_begin','ev_step_end',
+            'vk_nokey','vk_anykey','vk_left','vk_right','vk_up','vk_down','vk_enter','vk_escape','vk_space',
+            'vk_shift','vk_control','vk_alt','vk_backspace','vk_tab','vk_home','vk_end','vk_delete',
+            'vk_insert','vk_pageup','vk_pagedown','vk_pause','vk_printscreen',
+            'vk_f1','vk_f2','vk_f3','vk_f4','vk_f5','vk_f6','vk_f7','vk_f8','vk_f9','vk_f10','vk_f11','vk_f12',
+            'vk_numpad0','vk_numpad1','vk_numpad2','vk_numpad3','vk_numpad4','vk_numpad5','vk_numpad6',
+            'vk_numpad7','vk_numpad8','vk_numpad9', 'vk_multiply','vk_divide','vk_add','vk_subtract',
+            'vk_decimal','vk_lshift','vk_lcontrol','vk_lalt','vk_rshift','vk_rcontrol','vk_ralt',
+            'c_aqua','c_black','c_blue','c_dkgray','c_fuchsia','c_gray','c_green','c_lime','c_ltgray',
+            'c_maroon','c_navy','c_olive','c_purple','c_red','c_silver','c_teal','c_white','c_yellow',
+            'fa_left', 'fa_center','fa_right','fa_top','fa_middle','fa_bottom',
+            'pr_pointlist','pr_linelist','pr_linestrip','pr_trianglelist','pr_trianglestrip',
+            'pr_trianglefan',
+            'cr_none','cr_arrow','cr_cross','cr_beam','cr_size_nesw','cr_size_ns','cr_size_nwse',
+            'cr_size_we','cr_uparrow','cr_hourglass','cr_drag','cr_nodrop','cr_hsplit','cr_vsplit',
+            'cr_multidrag','cr_sqlwait','cr_no','cr_appstart','cr_help','cr_handpoint','cr_size_all',
+            'se_chorus','se_echo','se_flanger','se_gargle','se_reverb','se_compressor','se_equalizer',
+            'fa_readonly','fa_hidden','fa_sysfile','fa_volumeid','fa_directory','fa_archive',
+            'pt_shape_pixel','pt_shape_disk','pt_shape_square','pt_shape_line','pt_shape_star',
+            'pt_shape_circle','pt_shape_ring','pt_shape_sphere','pt_shape_flare','pt_shape_spark',
+            'pt_shape_explosion','pt_shape_cloud','pt_shape_smoke','pt_shape_snow',
+            'ps_shape_rectangle','ps_shape_ellipse ','ps_shape_diamond','ps_shape_line',
+            'ps_distr_linear','ps_distr_gaussian','ps_force_constant','ps_force_linear','ps_force_quadratic',
+            'ps_deflect_horizontal', 'ps_deflect_vertical',
+            'ps_change_motion','ps_change_shape','ps_change_all'
+            ),
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '{', '}', '[', ']',
+        '&&', '||', '^^', '&', '|', '^',
+        '<', '<=', '==', '!=', '>', '>=', '=',
+        '<<', '>>',
+        '+=', '-=', '*=', '/=',
+        '+', '-', '*', '/',
+        '!', '~', ',', ';'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'font-weight: bold; color: #000000;',
+            2 => 'font-weight: bold; color: #000000;',
+            3 => 'color: navy;',
+            4 => 'color: #663300;',
+            ),
+        'COMMENTS' => array(
+            1 => 'font-style: italic; color: green;',
+            'MULTI' => 'font-style: italic; color: green;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000000;' //'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #202020;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66; font-weight: bold;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/gnuplot.php b/examples/includes/geshi/geshi/gnuplot.php
new file mode 100644 (file)
index 0000000..3b67fb6
--- /dev/null
@@ -0,0 +1,296 @@
+<?php
+/*************************************************************************************
+ * gnuplot.php
+ * ----------
+ * Author: Milian Wolff (mail@milianw.de)
+ * Copyright: (c) 2008 Milian Wolff (http://milianw.de)
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/07/07
+ *
+ * Gnuplot script language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/07/07 (1.0.8)
+ *  -  Initial import
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Gnuplot',
+    'COMMENT_SINGLE' => array(1 => '#'),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('`', '"', "'"),
+    'ESCAPE_CHAR' => '\\',
+    'NUMBERS' =>
+        GESHI_NUMBER_INT_BASIC |
+        GESHI_NUMBER_FLT_NONSCI |
+        GESHI_NUMBER_FLT_SCI_SHORT |
+        GESHI_NUMBER_FLT_SCI_ZERO,
+    'KEYWORDS' => array(
+        // copy output of help command, indent properly and use this replace regexp:
+        // ([a-z0-9_\-]+)(( )+|$)          =>     '\1',\3
+
+        // commands as found in `help commands`
+        1 => array(
+            'bind', 'call', 'cd', 'clear',
+            'exit', 'fit', 'help', 'history',
+            'if', 'load', 'lower', 'pause',
+            'plot', 'print', 'pwd', 'quit',
+            'raise', 'replot', 'reread', 'reset',
+            'save', 'set', 'shell', 'show',
+            'splot', 'system', 'test', 'unset',
+            'update'
+            ),
+        2 => array(
+            // set commands as returned by `help set`
+            'angles', 'arrow', 'autoscale', 'bars',
+            'bmargin', 'border', 'boxwidth', 'cbdata',
+            'cbdtics', 'cblabel', 'cbmtics', 'cbrange',
+            'cbtics', 'clabel', 'clip', 'cntrparam',
+            'colorbox', 'contour', 'datafile', 'date_specifiers',
+            'decimalsign', 'dgrid3d', 'dummy', 'encoding',
+            'fontpath', 'format', 'grid',
+            'hidden3d', 'historysize', 'isosamples', 'key',
+            'label', 'lmargin', 'loadpath', 'locale',
+            'log', 'logscale', 'macros', 'mapping',
+            'margin', 'missing', 'mouse', 'multiplot',
+            'mx2tics', 'mxtics', 'my2tics', 'mytics',
+            'mztics', 'object', 'offsets', 'origin',
+            'output', 'palette', 'parametric', 'pm3d',
+            'pointsize', 'polar', 'rmargin',
+            'rrange', 'samples', 'size', 'style',
+            'surface', 'table', 'term', 'terminal',
+            'termoption', 'tics', 'ticscale', 'ticslevel',
+            'time_specifiers', 'timefmt', 'timestamp', 'title',
+            'trange', 'urange', 'view',
+            'vrange', 'x2data', 'x2dtics', 'x2label',
+            'x2mtics', 'x2range', 'x2tics', 'x2zeroaxis',
+            'xdata', 'xdtics', 'xlabel', 'xmtics',
+            'xrange', 'xtics', 'xyplane', 'xzeroaxis',
+            'y2data', 'y2dtics', 'y2label', 'y2mtics',
+            'y2range', 'y2tics', 'y2zeroaxis', 'ydata',
+            'ydtics', 'ylabel', 'ymtics', 'yrange',
+            'ytics', 'yzeroaxis', 'zdata', 'zdtics',
+            'zero', 'zeroaxis', 'zlabel', 'zmtics',
+            'zrange', 'ztics', 'zzeroaxis',
+            // same but with leading no
+            'noangles', 'noarrow', 'noautoscale', 'nobars',
+            'nobmargin', 'noborder', 'noboxwidth', 'nocbdata',
+            'nocbdtics', 'nocblabel', 'nocbmtics', 'nocbrange',
+            'nocbtics', 'noclabel', 'noclip', 'nocntrparam',
+            'nocolorbox', 'nocontour', 'nodatafile', 'nodate_specifiers',
+            'nodecimalsign', 'nodgrid3d', 'nodummy', 'noencoding',
+            'nofit', 'nofontpath', 'noformat', 'nogrid',
+            'nohidden3d', 'nohistorysize', 'noisosamples', 'nokey',
+            'nolabel', 'nolmargin', 'noloadpath', 'nolocale',
+            'nolog', 'nologscale', 'nomacros', 'nomapping',
+            'nomargin', 'nomissing', 'nomouse', 'nomultiplot',
+            'nomx2tics', 'nomxtics', 'nomy2tics', 'nomytics',
+            'nomztics', 'noobject', 'nooffsets', 'noorigin',
+            'nooutput', 'nopalette', 'noparametric', 'nopm3d',
+            'nopointsize', 'nopolar', 'noprint', 'normargin',
+            'norrange', 'nosamples', 'nosize', 'nostyle',
+            'nosurface', 'notable', 'noterm', 'noterminal',
+            'notermoption', 'notics', 'noticscale', 'noticslevel',
+            'notime_specifiers', 'notimefmt', 'notimestamp', 'notitle',
+            'notmargin', 'notrange', 'nourange', 'noview',
+            'novrange', 'nox2data', 'nox2dtics', 'nox2label',
+            'nox2mtics', 'nox2range', 'nox2tics', 'nox2zeroaxis',
+            'noxdata', 'noxdtics', 'noxlabel', 'noxmtics',
+            'noxrange', 'noxtics', 'noxyplane', 'noxzeroaxis',
+            'noy2data', 'noy2dtics', 'noy2label', 'noy2mtics',
+            'noy2range', 'noy2tics', 'noy2zeroaxis', 'noydata',
+            'noydtics', 'noylabel', 'noymtics', 'noyrange',
+            'noytics', 'noyzeroaxis', 'nozdata', 'nozdtics',
+            'nozero', 'nozeroaxis', 'nozlabel', 'nozmtics',
+            'nozrange', 'noztics', 'nozzeroaxis',
+            ),
+        3 => array(
+            // predefined variables
+            'pi', 'NaN', 'GNUTERM',
+            'GPVAL_X_MIN', 'GPVAL_X_MAX', 'GPVAL_Y_MIN', 'GPVAL_Y_MAX',
+            'GPVAL_TERM', 'GPVAL_TERMOPTIONS', 'GPVAL_OUTPUT',
+            'GPVAL_VERSION', 'GPVAL_PATcHLEVEL', 'GPVAL_COMPILE_OPTIONS',
+            'MOUSE_KEY', 'MOUSE_X', 'MOUSE_X2', 'MOUSE_Y', 'MOUSE_Y2',
+            'MOUSE_BUTTON', 'MOUSE_SHIFT', 'MOUSE_ALT', 'MOUSE_CTRL'
+            ),
+        4 => array(
+            // predefined functions `help functions`
+            'abs', 'acos', 'acosh', 'arg',
+            'asin', 'asinh', 'atan', 'atan2',
+            'atanh', 'besj0', 'besj1', 'besy0',
+            'besy1', 'ceil', 'column', 'cos',
+            'cosh', 'defined', 'erf', 'erfc',
+            'exists', 'exp', 'floor', 'gamma',
+            'gprintf', 'ibeta', 'igamma', 'imag',
+            'int', 'inverf', 'invnorm', 'lambertw',
+            'lgamma', 'log10', 'norm',
+            'rand', 'random', 'real', 'sgn',
+            'sin', 'sinh', 'sprintf', 'sqrt',
+            'stringcolumn', 'strlen', 'strstrt', 'substr',
+            'tan', 'tanh', 'timecolumn',
+            'tm_hour', 'tm_mday', 'tm_min', 'tm_mon',
+            'tm_sec', 'tm_wday', 'tm_yday', 'tm_year',
+            'valid', 'word', 'words',
+            ),
+        5 => array(
+            // mixed arguments
+            // there is no sane way to get these ones easily...
+            'autofreq', 'x', 'y', 'z',
+            'lt', 'linetype', 'lw', 'linewidth', 'ls', 'linestyle',
+            'out', 'rotate by', 'screen',
+            'enhanced', 'via',
+            // `help set key`
+            'on', 'off', 'default', 'inside', 'outside', 'tmargin',
+            'at', 'left', 'right', 'center', 'top', 'bottom', 'vertical', 'horizontal', 'Left', 'Right',
+            'noreverse', 'reverse', 'noinvert', 'invert', 'samplen', 'spacing', 'width', 'height',
+            'noautotitle', 'autotitle', 'noenhanced', 'nobox', 'box',
+
+            // help set terminal postscript
+            'landscape', 'portrait', 'eps', 'defaultplex', 'simplex', 'duplex',
+            'fontfile', 'add', 'delete', 'nofontfiles', 'level1', 'leveldefault',
+            'color', 'colour', 'monochrome', 'solid', 'dashed', 'dashlength', 'dl',
+            'rounded', 'butt', 'palfuncparam', 'blacktext', 'colortext', 'colourtext',
+            'font',
+
+            // help set terminal png
+            'notransparent', 'transparent', 'nointerlace', 'interlace',
+            'notruecolor', 'truecolor', 'tiny', 'small', 'medium', 'large', 'giant',
+            'nocrop', 'crop',
+
+            // `help plot`
+            'acsplines', 'bezier', 'binary', 'csplines',
+            'every',
+            'example', 'frequency', 'index', 'matrix',
+            'ranges', 'sbezier', 'smooth',
+            'special-filenames', 'thru',
+            'unique', 'using', 'with',
+
+            // `help plotting styles`
+            'boxerrorbars', 'boxes', 'boxxyerrorbars', 'candlesticks',
+            'dots', 'errorbars', 'errorlines', 'filledcurves',
+            'financebars', 'fsteps', 'histeps', 'histograms',
+            'image', 'impulses', 'labels', 'lines',
+            'linespoints', 'points', 'rgbimage', 'steps',
+            'vectors', 'xerrorbars', 'xerrorlines', 'xyerrorbars',
+            'xyerrorlines', 'yerrorbars', 'yerrorlines',
+
+
+            // terminals `help terminals`
+            'aed512', 'aed767', 'aifm', 'bitgraph',
+            'cgm', 'corel', 'dumb', 'dxf',
+            'eepic', 'emf', 'emtex', 'epslatex',
+            'epson-180dpi', 'epson-60dpi', 'epson-lx800', 'fig',
+            'gif', 'gpic', 'hp2623a', 'hp2648',
+            'hp500c', 'hpdj', 'hpgl', 'hpljii',
+            'hppj', 'imagen', 'jpeg', 'kc-tek40xx',
+            'km-tek40xx', 'latex', 'mf', 'mif',
+            'mp', 'nec-cp6', 'okidata', 'pbm',
+            'pcl5', 'png', 'pop', 'postscript',
+            'pslatex', 'pstex', 'pstricks', 'push',
+            'qms', 'regis', 'selanar', 'starc',
+            'svg', 'tandy-60dpi', 'tek40xx', 'tek410x',
+            'texdraw', 'tgif', 'tkcanvas', 'tpic',
+            'vttek', 'x11', 'xlib',
+            )
+        ),
+    'REGEXPS' => array(
+        //Variable assignment
+        0 => "([a-zA-Z_][a-zA-Z0-9_]*)\s*=",
+        //Numbers with unit
+        1 => "(?<=^|\s)([0-9]*\.?[0-9]+\s*cm)"
+        ),
+    'SYMBOLS' => array(
+        '-', '+', '~', '!', '$',
+        '*', '/', '%', '=', '<', '>', '&',
+        '^', '|', '.', 'eq', 'ne', '?:', ':', '`', ','
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true,
+        5 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;',
+            2 => 'color: #990000;',
+            3 => 'color: #550000;',
+            4 => 'color: #7a0874;',
+            5 => 'color: #448888;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #adadad; font-style: italic;',
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight:bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000099; font-weight:bold;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #0000ff;',
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000; font-weight: bold;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #007800;',
+            1 => 'color: #cc66cc;'
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => 'http://www.google.com/search?q=%22set+{FNAME}%22+site%3Ahttp%3A%2F%2Fwww.gnuplot.info%2Fdocs%2F&amp;btnI=lucky',
+        3 => '',
+        4 => '',
+        5 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            4 => array(
+                'DISALLOWED_AFTER' =>  "(?![\.\-a-zA-Z0-9_%])"
+            )
+        )
+    ),
+    'TAB_WIDTH' => 4
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/groovy.php b/examples/includes/geshi/geshi/groovy.php
new file mode 100644 (file)
index 0000000..332f163
--- /dev/null
@@ -0,0 +1,1011 @@
+<?php
+/*************************************************************************************
+ * groovy.php
+ * ----------
+ * Author: Ivan F. Villanueva B. (geshi_groovy@artificialidea.com)
+ * Copyright: (c) 2006 Ivan F. Villanueva B.(http://www.artificialidea.com)
+ * Release Version: 1.0.8.3
+ * Date Started: 2006/04/29
+ *
+ * Groovy language file for GeSHi.
+ *
+ * Keywords from http: http://docs.codehaus.org/download/attachments/2715/groovy-reference-card.pdf?version=1
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *   -  Added description of extra language features (SF#1970248)
+ * 2006/04/29 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2006/04/29)
+ * -------------------------
+ * Testing
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Groovy',
+    'COMMENT_SINGLE' => array(1 => '//', 3 => '#'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'COMMENT_REGEXP' => array(
+        //Import and Package directives (Basic Support only)
+        2 => '/(?:(?<=import[\\n\\s])|(?<=package[\\n\\s]))[\\n\\s]*([a-zA-Z0-9_]+\\.)*([a-zA-Z0-9_]+|\*)(?=[\n\s;])/i',
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'''", '"""', "'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'case', 'do', 'else', 'for', 'foreach', 'if', 'in', 'switch',
+            'while',
+            ),
+        2 => array(
+            'abstract', 'as', 'assert', 'break', 'catch', 'class', 'const',
+            'continue', 'def', 'default', 'enum', 'extends',
+            'false', 'final', 'finally', 'goto', 'implements', 'import',
+            'instanceof', 'interface', 'native', 'new', 'null',
+            'package', 'private', 'property', 'protected',
+            'public', 'return', 'static', 'strictfp', 'super',
+            'synchronized', 'this', 'throw', 'throws',
+            'transient', 'true', 'try', 'volatile'
+            ),
+        3 => array(
+            'AbstractAction', 'AbstractBorder', 'AbstractButton',
+            'AbstractCellEditor', 'AbstractCollection',
+            'AbstractColorChooserPanel', 'AbstractDocument',
+            'AbstractDocument.AttributeContext',
+            'AbstractDocument.Content',
+            'AbstractDocument.ElementEdit',
+            'AbstractLayoutCache',
+            'AbstractLayoutCache.NodeDimensions', 'AbstractList',
+            'AbstractListModel', 'AbstractMap',
+            'AbstractMethodError', 'AbstractSequentialList',
+            'AbstractSet', 'AbstractTableModel',
+            'AbstractUndoableEdit', 'AbstractWriter',
+            'AccessControlContext', 'AccessControlException',
+            'AccessController', 'AccessException', 'Accessible',
+            'AccessibleAction', 'AccessibleBundle',
+            'AccessibleComponent', 'AccessibleContext',
+            'AccessibleHyperlink', 'AccessibleHypertext',
+            'AccessibleIcon', 'AccessibleObject',
+            'AccessibleRelation', 'AccessibleRelationSet',
+            'AccessibleResourceBundle', 'AccessibleRole',
+            'AccessibleSelection', 'AccessibleState',
+            'AccessibleStateSet', 'AccessibleTable',
+            'AccessibleTableModelChange', 'AccessibleText',
+            'AccessibleValue', 'Acl', 'AclEntry',
+            'AclNotFoundException', 'Action', 'ActionEvent',
+            'ActionListener', 'ActionMap', 'ActionMapUIResource',
+            'Activatable', 'ActivateFailedException',
+            'ActivationDesc', 'ActivationException',
+            'ActivationGroup', 'ActivationGroupDesc',
+            'ActivationGroupDesc.CommandEnvironment',
+            'ActivationGroupID', 'ActivationID',
+            'ActivationInstantiator', 'ActivationMonitor',
+            'ActivationSystem', 'Activator', 'ActiveEvent',
+            'Adjustable', 'AdjustmentEvent',
+            'AdjustmentListener', 'Adler32', 'AffineTransform',
+            'AffineTransformOp', 'AlgorithmParameterGenerator',
+            'AlgorithmParameterGeneratorSpi',
+            'AlgorithmParameters', 'AlgorithmParameterSpec',
+            'AlgorithmParametersSpi', 'AllPermission',
+            'AlphaComposite', 'AlreadyBound',
+            'AlreadyBoundException', 'AlreadyBoundHelper',
+            'AlreadyBoundHolder', 'AncestorEvent',
+            'AncestorListener', 'Annotation', 'Any', 'AnyHolder',
+            'AnySeqHelper', 'AnySeqHolder', 'Applet',
+            'AppletContext', 'AppletInitializer', 'AppletStub',
+            'ApplicationException', 'Arc2D', 'Arc2D.Double',
+            'Arc2D.Float', 'Area', 'AreaAveragingScaleFilter',
+            'ARG_IN', 'ARG_INOUT', 'ARG_OUT',
+            'ArithmeticException', 'Array',
+            'ArrayIndexOutOfBoundsException', 'ArrayList',
+            'Arrays', 'ArrayStoreException', 'AsyncBoxView',
+            'Attribute', 'AttributedCharacterIterator',
+            'AttributedCharacterIterator.Attribute',
+            'AttributedString', 'AttributeInUseException',
+            'AttributeList', 'AttributeModificationException',
+            'Attributes', 'Attributes.Name', 'AttributeSet',
+            'AttributeSet.CharacterAttribute',
+            'AttributeSet.ColorAttribute',
+            'AttributeSet.FontAttribute',
+            'AttributeSet.ParagraphAttribute', 'AudioClip',
+            'AudioFileFormat', 'AudioFileFormat.Type',
+            'AudioFileReader', 'AudioFileWriter', 'AudioFormat',
+            'AudioFormat.Encoding', 'AudioInputStream',
+            'AudioPermission', 'AudioSystem',
+            'AuthenticationException',
+            'AuthenticationNotSupportedException',
+            'Authenticator', 'Autoscroll', 'AWTError',
+            'AWTEvent', 'AWTEventListener',
+            'AWTEventMulticaster', 'AWTException',
+            'AWTPermission', 'BadKind', 'BadLocationException',
+            'BAD_CONTEXT', 'BAD_INV_ORDER', 'BAD_OPERATION',
+            'BAD_PARAM', 'BAD_POLICY', 'BAD_POLICY_TYPE',
+            'BAD_POLICY_VALUE', 'BAD_TYPECODE', 'BandCombineOp',
+            'BandedSampleModel', 'BasicArrowButton',
+            'BasicAttribute', 'BasicAttributes', 'BasicBorders',
+            'BasicBorders.ButtonBorder',
+            'BasicBorders.FieldBorder',
+            'BasicBorders.MarginBorder',
+            'BasicBorders.MenuBarBorder',
+            'BasicBorders.RadioButtonBorder',
+            'BasicBorders.SplitPaneBorder',
+            'BasicBorders.ToggleButtonBorder',
+            'BasicButtonListener', 'BasicButtonUI',
+            'BasicCheckBoxMenuItemUI', 'BasicCheckBoxUI',
+            'BasicColorChooserUI', 'BasicComboBoxEditor',
+            'BasicComboBoxEditor.UIResource',
+            'BasicComboBoxRenderer',
+            'BasicComboBoxRenderer.UIResource',
+            'BasicComboBoxUI', 'BasicComboPopup',
+            'BasicDesktopIconUI', 'BasicDesktopPaneUI',
+            'BasicDirectoryModel', 'BasicEditorPaneUI',
+            'BasicFileChooserUI', 'BasicGraphicsUtils',
+            'BasicHTML', 'BasicIconFactory',
+            'BasicInternalFrameTitlePane',
+            'BasicInternalFrameUI', 'BasicLabelUI',
+            'BasicListUI', 'BasicLookAndFeel', 'BasicMenuBarUI',
+            'BasicMenuItemUI', 'BasicMenuUI',
+            'BasicOptionPaneUI',
+            'BasicOptionPaneUI.ButtonAreaLayout', 'BasicPanelUI',
+            'BasicPasswordFieldUI', 'BasicPermission',
+            'BasicPopupMenuSeparatorUI', 'BasicPopupMenuUI',
+            'BasicProgressBarUI', 'BasicRadioButtonMenuItemUI',
+            'BasicRadioButtonUI', 'BasicRootPaneUI',
+            'BasicScrollBarUI', 'BasicScrollPaneUI',
+            'BasicSeparatorUI', 'BasicSliderUI',
+            'BasicSplitPaneDivider', 'BasicSplitPaneUI',
+            'BasicStroke', 'BasicTabbedPaneUI',
+            'BasicTableHeaderUI', 'BasicTableUI',
+            'BasicTextAreaUI', 'BasicTextFieldUI',
+            'BasicTextPaneUI', 'BasicTextUI',
+            'BasicTextUI.BasicCaret',
+            'BasicTextUI.BasicHighlighter',
+            'BasicToggleButtonUI', 'BasicToolBarSeparatorUI',
+            'BasicToolBarUI', 'BasicToolTipUI', 'BasicTreeUI',
+            'BasicViewportUI', 'BatchUpdateException',
+            'BeanContext', 'BeanContextChild',
+            'BeanContextChildComponentProxy',
+            'BeanContextChildSupport',
+            'BeanContextContainerProxy', 'BeanContextEvent',
+            'BeanContextMembershipEvent',
+            'BeanContextMembershipListener', 'BeanContextProxy',
+            'BeanContextServiceAvailableEvent',
+            'BeanContextServiceProvider',
+            'BeanContextServiceProviderBeanInfo',
+            'BeanContextServiceRevokedEvent',
+            'BeanContextServiceRevokedListener',
+            'BeanContextServices', 'BeanContextServicesListener',
+            'BeanContextServicesSupport',
+            'BeanContextServicesSupport.BCSSServiceProvider',
+            'BeanContextSupport',
+            'BeanContextSupport.BCSIterator', 'BeanDescriptor',
+            'BeanInfo', 'Beans', 'BevelBorder', 'BigDecimal',
+            'BigInteger', 'BinaryRefAddr', 'BindException',
+            'Binding', 'BindingHelper', 'BindingHolder',
+            'BindingIterator', 'BindingIteratorHelper',
+            'BindingIteratorHolder', 'BindingIteratorOperations',
+            'BindingListHelper', 'BindingListHolder',
+            'BindingType', 'BindingTypeHelper',
+            'BindingTypeHolder', 'BitSet', 'Blob', 'BlockView',
+            'Book', 'Boolean', 'BooleanControl',
+            'BooleanControl.Type', 'BooleanHolder',
+            'BooleanSeqHelper', 'BooleanSeqHolder', 'Border',
+            'BorderFactory', 'BorderLayout', 'BorderUIResource',
+            'BorderUIResource.BevelBorderUIResource',
+            'BorderUIResource.CompoundBorderUIResource',
+            'BorderUIResource.EmptyBorderUIResource',
+            'BorderUIResource.EtchedBorderUIResource',
+            'BorderUIResource.LineBorderUIResource',
+            'BorderUIResource.MatteBorderUIResource',
+            'BorderUIResource.TitledBorderUIResource',
+            'BoundedRangeModel', 'Bounds', 'Box', 'Box.Filler',
+            'BoxedValueHelper', 'BoxLayout', 'BoxView',
+            'BreakIterator', 'BufferedImage',
+            'BufferedImageFilter', 'BufferedImageOp',
+            'BufferedInputStream', 'BufferedOutputStream',
+            'BufferedReader', 'BufferedWriter', 'Button',
+            'ButtonGroup', 'ButtonModel', 'ButtonUI', 'Byte',
+            'ByteArrayInputStream', 'ByteArrayOutputStream',
+            'ByteHolder', 'ByteLookupTable', 'Calendar',
+            'CallableStatement', 'CannotProceed',
+            'CannotProceedException', 'CannotProceedHelper',
+            'CannotProceedHolder', 'CannotRedoException',
+            'CannotUndoException', 'Canvas', 'CardLayout',
+            'Caret', 'CaretEvent', 'CaretListener', 'CellEditor',
+            'CellEditorListener', 'CellRendererPane',
+            'Certificate', 'Certificate.CertificateRep',
+            'CertificateEncodingException',
+            'CertificateException',
+            'CertificateExpiredException', 'CertificateFactory',
+            'CertificateFactorySpi',
+            'CertificateNotYetValidException',
+            'CertificateParsingException',
+            'ChangedCharSetException', 'ChangeEvent',
+            'ChangeListener', 'Character', 'Character.Subset',
+            'Character.UnicodeBlock', 'CharacterIterator',
+            'CharArrayReader', 'CharArrayWriter',
+            'CharConversionException', 'CharHolder',
+            'CharSeqHelper', 'CharSeqHolder', 'Checkbox',
+            'CheckboxGroup', 'CheckboxMenuItem',
+            'CheckedInputStream', 'CheckedOutputStream',
+            'Checksum', 'Choice', 'ChoiceFormat', 'Class',
+            'ClassCastException', 'ClassCircularityError',
+            'ClassDesc', 'ClassFormatError', 'ClassLoader',
+            'ClassNotFoundException', 'Clip', 'Clipboard',
+            'ClipboardOwner', 'Clob', 'Cloneable',
+            'CloneNotSupportedException', 'CMMException',
+            'CodeSource', 'CollationElementIterator',
+            'CollationKey', 'Collator', 'Collection',
+            'Collections', 'Color',
+            'ColorChooserComponentFactory', 'ColorChooserUI',
+            'ColorConvertOp', 'ColorModel',
+            'ColorSelectionModel', 'ColorSpace',
+            'ColorUIResource', 'ComboBoxEditor', 'ComboBoxModel',
+            'ComboBoxUI', 'ComboPopup', 'CommunicationException',
+            'COMM_FAILURE', 'Comparable', 'Comparator',
+            'Compiler', 'CompletionStatus',
+            'CompletionStatusHelper', 'Component',
+            'ComponentAdapter', 'ComponentColorModel',
+            'ComponentEvent', 'ComponentInputMap',
+            'ComponentInputMapUIResource', 'ComponentListener',
+            'ComponentOrientation', 'ComponentSampleModel',
+            'ComponentUI', 'ComponentView', 'Composite',
+            'CompositeContext', 'CompositeName', 'CompositeView',
+            'CompoundBorder', 'CompoundControl',
+            'CompoundControl.Type', 'CompoundEdit',
+            'CompoundName', 'ConcurrentModificationException',
+            'ConfigurationException', 'ConnectException',
+            'ConnectIOException', 'Connection', 'Constructor',
+            'Container', 'ContainerAdapter', 'ContainerEvent',
+            'ContainerListener', 'ContentHandler',
+            'ContentHandlerFactory', 'ContentModel', 'Context',
+            'ContextList', 'ContextNotEmptyException',
+            'ContextualRenderedImageFactory', 'Control',
+            'Control.Type', 'ControlFactory',
+            'ControllerEventListener', 'ConvolveOp', 'CRC32',
+            'CRL', 'CRLException', 'CropImageFilter', 'CSS',
+            'CSS.Attribute', 'CTX_RESTRICT_SCOPE',
+            'CubicCurve2D', 'CubicCurve2D.Double',
+            'CubicCurve2D.Float', 'Current', 'CurrentHelper',
+            'CurrentHolder', 'CurrentOperations', 'Cursor',
+            'Customizer', 'CustomMarshal', 'CustomValue',
+            'DatabaseMetaData', 'DataBuffer', 'DataBufferByte',
+            'DataBufferInt', 'DataBufferShort',
+            'DataBufferUShort', 'DataFlavor',
+            'DataFormatException', 'DatagramPacket',
+            'DatagramSocket', 'DatagramSocketImpl',
+            'DatagramSocketImplFactory', 'DataInput',
+            'DataInputStream', 'DataLine', 'DataLine.Info',
+            'DataOutput', 'DataOutputStream', 'DataTruncation',
+            'DATA_CONVERSION', 'Date', 'DateFormat',
+            'DateFormatSymbols', 'DebugGraphics',
+            'DecimalFormat', 'DecimalFormatSymbols',
+            'DefaultBoundedRangeModel', 'DefaultButtonModel',
+            'DefaultCaret', 'DefaultCellEditor',
+            'DefaultColorSelectionModel', 'DefaultComboBoxModel',
+            'DefaultDesktopManager', 'DefaultEditorKit',
+            'DefaultEditorKit.BeepAction',
+            'DefaultEditorKit.CopyAction',
+            'DefaultEditorKit.CutAction',
+            'DefaultEditorKit.DefaultKeyTypedAction',
+            'DefaultEditorKit.InsertBreakAction',
+            'DefaultEditorKit.InsertContentAction',
+            'DefaultEditorKit.InsertTabAction',
+            'DefaultEditorKit.PasteAction,',
+            'DefaultFocusManager', 'DefaultHighlighter',
+            'DefaultHighlighter.DefaultHighlightPainter',
+            'DefaultListCellRenderer',
+            'DefaultListCellRenderer.UIResource',
+            'DefaultListModel', 'DefaultListSelectionModel',
+            'DefaultMenuLayout', 'DefaultMetalTheme',
+            'DefaultMutableTreeNode',
+            'DefaultSingleSelectionModel',
+            'DefaultStyledDocument',
+            'DefaultStyledDocument.AttributeUndoableEdit',
+            'DefaultStyledDocument.ElementSpec',
+            'DefaultTableCellRenderer',
+            'DefaultTableCellRenderer.UIResource',
+            'DefaultTableColumnModel', 'DefaultTableModel',
+            'DefaultTextUI', 'DefaultTreeCellEditor',
+            'DefaultTreeCellRenderer', 'DefaultTreeModel',
+            'DefaultTreeSelectionModel', 'DefinitionKind',
+            'DefinitionKindHelper', 'Deflater',
+            'DeflaterOutputStream', 'Delegate', 'DesignMode',
+            'DesktopIconUI', 'DesktopManager', 'DesktopPaneUI',
+            'DGC', 'Dialog', 'Dictionary', 'DigestException',
+            'DigestInputStream', 'DigestOutputStream',
+            'Dimension', 'Dimension2D', 'DimensionUIResource',
+            'DirContext', 'DirectColorModel', 'DirectoryManager',
+            'DirObjectFactory', 'DirStateFactory',
+            'DirStateFactory.Result', 'DnDConstants', 'Document',
+            'DocumentEvent', 'DocumentEvent.ElementChange',
+            'DocumentEvent.EventType', 'DocumentListener',
+            'DocumentParser', 'DomainCombiner', 'DomainManager',
+            'DomainManagerOperations', 'Double', 'DoubleHolder',
+            'DoubleSeqHelper', 'DoubleSeqHolder',
+            'DragGestureEvent', 'DragGestureListener',
+            'DragGestureRecognizer', 'DragSource',
+            'DragSourceContext', 'DragSourceDragEvent',
+            'DragSourceDropEvent', 'DragSourceEvent',
+            'DragSourceListener', 'Driver', 'DriverManager',
+            'DriverPropertyInfo', 'DropTarget',
+            'DropTarget.DropTargetAutoScroller',
+            'DropTargetContext', 'DropTargetDragEvent',
+            'DropTargetDropEvent', 'DropTargetEvent',
+            'DropTargetListener', 'DSAKey',
+            'DSAKeyPairGenerator', 'DSAParameterSpec',
+            'DSAParams', 'DSAPrivateKey', 'DSAPrivateKeySpec',
+            'DSAPublicKey', 'DSAPublicKeySpec', 'DTD',
+            'DTDConstants', 'DynamicImplementation', 'DynAny',
+            'DynArray', 'DynEnum', 'DynFixed', 'DynSequence',
+            'DynStruct', 'DynUnion', 'DynValue', 'EditorKit',
+            'Element', 'ElementIterator', 'Ellipse2D',
+            'Ellipse2D.Double', 'Ellipse2D.Float', 'EmptyBorder',
+            'EmptyStackException', 'EncodedKeySpec', 'Entity',
+            'EnumControl', 'EnumControl.Type', 'Enumeration',
+            'Environment', 'EOFException', 'Error',
+            'EtchedBorder', 'Event', 'EventContext',
+            'EventDirContext', 'EventListener',
+            'EventListenerList', 'EventObject', 'EventQueue',
+            'EventSetDescriptor', 'Exception',
+            'ExceptionInInitializerError', 'ExceptionList',
+            'ExpandVetoException', 'ExportException',
+            'ExtendedRequest', 'ExtendedResponse',
+            'Externalizable', 'FeatureDescriptor', 'Field',
+            'FieldNameHelper', 'FieldPosition', 'FieldView',
+            'File', 'FileChooserUI', 'FileDescriptor',
+            'FileDialog', 'FileFilter', 'FileInputStream',
+            'FilenameFilter', 'FileNameMap',
+            'FileNotFoundException', 'FileOutputStream',
+            'FilePermission', 'FileReader', 'FileSystemView',
+            'FileView', 'FileWriter', 'FilteredImageSource',
+            'FilterInputStream', 'FilterOutputStream',
+            'FilterReader', 'FilterWriter',
+            'FixedHeightLayoutCache', 'FixedHolder',
+            'FlatteningPathIterator', 'FlavorMap', 'Float',
+            'FloatControl', 'FloatControl.Type', 'FloatHolder',
+            'FloatSeqHelper', 'FloatSeqHolder', 'FlowLayout',
+            'FlowView', 'FlowView.FlowStrategy', 'FocusAdapter',
+            'FocusEvent', 'FocusListener', 'FocusManager',
+            'Font', 'FontFormatException', 'FontMetrics',
+            'FontRenderContext', 'FontUIResource', 'Format',
+            'FormatConversionProvider', 'FormView', 'Frame',
+            'FREE_MEM', 'GapContent', 'GeneralPath',
+            'GeneralSecurityException', 'GlyphJustificationInfo',
+            'GlyphMetrics', 'GlyphVector', 'GlyphView',
+            'GlyphView.GlyphPainter', 'GradientPaint',
+            'GraphicAttribute', 'Graphics', 'Graphics2D',
+            'GraphicsConfigTemplate', 'GraphicsConfiguration',
+            'GraphicsDevice', 'GraphicsEnvironment',
+            'GrayFilter', 'GregorianCalendar',
+            'GridBagConstraints', 'GridBagLayout', 'GridLayout',
+            'Group', 'Guard', 'GuardedObject', 'GZIPInputStream',
+            'GZIPOutputStream', 'HasControls', 'HashMap',
+            'HashSet', 'Hashtable', 'HierarchyBoundsAdapter',
+            'HierarchyBoundsListener', 'HierarchyEvent',
+            'HierarchyListener', 'Highlighter',
+            'Highlighter.Highlight',
+            'Highlighter.HighlightPainter', 'HTML',
+            'HTML.Attribute', 'HTML.Tag', 'HTML.UnknownTag',
+            'HTMLDocument', 'HTMLDocument.Iterator',
+            'HTMLEditorKit', 'HTMLEditorKit.HTMLFactory',
+            'HTMLEditorKit.HTMLTextAction',
+            'HTMLEditorKit.InsertHTMLTextAction',
+            'HTMLEditorKit.LinkController',
+            'HTMLEditorKit.Parser',
+            'HTMLEditorKit.ParserCallback',
+            'HTMLFrameHyperlinkEvent', 'HTMLWriter',
+            'HttpURLConnection', 'HyperlinkEvent',
+            'HyperlinkEvent.EventType', 'HyperlinkListener',
+            'ICC_ColorSpace', 'ICC_Profile', 'ICC_ProfileGray',
+            'ICC_ProfileRGB', 'Icon', 'IconUIResource',
+            'IconView', 'IdentifierHelper', 'Identity',
+            'IdentityScope', 'IDLEntity', 'IDLType',
+            'IDLTypeHelper', 'IDLTypeOperations',
+            'IllegalAccessError', 'IllegalAccessException',
+            'IllegalArgumentException',
+            'IllegalComponentStateException',
+            'IllegalMonitorStateException',
+            'IllegalPathStateException', 'IllegalStateException',
+            'IllegalThreadStateException', 'Image',
+            'ImageConsumer', 'ImageFilter',
+            'ImageGraphicAttribute', 'ImageIcon',
+            'ImageObserver', 'ImageProducer',
+            'ImagingOpException', 'IMP_LIMIT',
+            'IncompatibleClassChangeError',
+            'InconsistentTypeCode', 'IndexColorModel',
+            'IndexedPropertyDescriptor',
+            'IndexOutOfBoundsException', 'IndirectionException',
+            'InetAddress', 'Inflater', 'InflaterInputStream',
+            'InheritableThreadLocal', 'InitialContext',
+            'InitialContextFactory',
+            'InitialContextFactoryBuilder', 'InitialDirContext',
+            'INITIALIZE', 'Initializer', 'InitialLdapContext',
+            'InlineView', 'InputContext', 'InputEvent',
+            'InputMap', 'InputMapUIResource', 'InputMethod',
+            'InputMethodContext', 'InputMethodDescriptor',
+            'InputMethodEvent', 'InputMethodHighlight',
+            'InputMethodListener', 'InputMethodRequests',
+            'InputStream', 'InputStreamReader', 'InputSubset',
+            'InputVerifier', 'Insets', 'InsetsUIResource',
+            'InstantiationError', 'InstantiationException',
+            'Instrument', 'InsufficientResourcesException',
+            'Integer', 'INTERNAL', 'InternalError',
+            'InternalFrameAdapter', 'InternalFrameEvent',
+            'InternalFrameListener', 'InternalFrameUI',
+            'InterruptedException', 'InterruptedIOException',
+            'InterruptedNamingException', 'INTF_REPOS',
+            'IntHolder', 'IntrospectionException',
+            'Introspector', 'Invalid',
+            'InvalidAlgorithmParameterException',
+            'InvalidAttributeIdentifierException',
+            'InvalidAttributesException',
+            'InvalidAttributeValueException',
+            'InvalidClassException',
+            'InvalidDnDOperationException',
+            'InvalidKeyException', 'InvalidKeySpecException',
+            'InvalidMidiDataException', 'InvalidName',
+            'InvalidNameException', 'InvalidNameHelper',
+            'InvalidNameHolder', 'InvalidObjectException',
+            'InvalidParameterException',
+            'InvalidParameterSpecException',
+            'InvalidSearchControlsException',
+            'InvalidSearchFilterException', 'InvalidSeq',
+            'InvalidTransactionException', 'InvalidValue',
+            'INVALID_TRANSACTION', 'InvocationEvent',
+            'InvocationHandler', 'InvocationTargetException',
+            'InvokeHandler', 'INV_FLAG', 'INV_IDENT',
+            'INV_OBJREF', 'INV_POLICY', 'IOException',
+            'IRObject', 'IRObjectOperations', 'IstringHelper',
+            'ItemEvent', 'ItemListener', 'ItemSelectable',
+            'Iterator', 'JApplet', 'JarEntry', 'JarException',
+            'JarFile', 'JarInputStream', 'JarOutputStream',
+            'JarURLConnection', 'JButton', 'JCheckBox',
+            'JCheckBoxMenuItem', 'JColorChooser', 'JComboBox',
+            'JComboBox.KeySelectionManager', 'JComponent',
+            'JDesktopPane', 'JDialog', 'JEditorPane',
+            'JFileChooser', 'JFrame', 'JInternalFrame',
+            'JInternalFrame.JDesktopIcon', 'JLabel',
+            'JLayeredPane', 'JList', 'JMenu', 'JMenuBar',
+            'JMenuItem', 'JobAttributes',
+            'JobAttributes.DefaultSelectionType',
+            'JobAttributes.DestinationType',
+            'JobAttributes.DialogType',
+            'JobAttributes.MultipleDocumentHandlingType',
+            'JobAttributes.SidesType', 'JOptionPane', 'JPanel',
+            'JPasswordField', 'JPopupMenu',
+            'JPopupMenu.Separator', 'JProgressBar',
+            'JRadioButton', 'JRadioButtonMenuItem', 'JRootPane',
+            'JScrollBar', 'JScrollPane', 'JSeparator', 'JSlider',
+            'JSplitPane', 'JTabbedPane', 'JTable',
+            'JTableHeader', 'JTextArea', 'JTextComponent',
+            'JTextComponent.KeyBinding', 'JTextField',
+            'JTextPane', 'JToggleButton',
+            'JToggleButton.ToggleButtonModel', 'JToolBar',
+            'JToolBar.Separator', 'JToolTip', 'JTree',
+            'JTree.DynamicUtilTreeNode',
+            'JTree.EmptySelectionModel', 'JViewport', 'JWindow',
+            'Kernel', 'Key', 'KeyAdapter', 'KeyEvent',
+            'KeyException', 'KeyFactory', 'KeyFactorySpi',
+            'KeyListener', 'KeyManagementException', 'Keymap',
+            'KeyPair', 'KeyPairGenerator', 'KeyPairGeneratorSpi',
+            'KeySpec', 'KeyStore', 'KeyStoreException',
+            'KeyStoreSpi', 'KeyStroke', 'Label', 'LabelUI',
+            'LabelView', 'LastOwnerException',
+            'LayeredHighlighter',
+            'LayeredHighlighter.LayerPainter', 'LayoutManager',
+            'LayoutManager2', 'LayoutQueue', 'LdapContext',
+            'LdapReferralException', 'Lease',
+            'LimitExceededException', 'Line', 'Line.Info',
+            'Line2D', 'Line2D.Double', 'Line2D.Float',
+            'LineBorder', 'LineBreakMeasurer', 'LineEvent',
+            'LineEvent.Type', 'LineListener', 'LineMetrics',
+            'LineNumberInputStream', 'LineNumberReader',
+            'LineUnavailableException', 'LinkageError',
+            'LinkedList', 'LinkException', 'LinkLoopException',
+            'LinkRef', 'List', 'ListCellRenderer',
+            'ListDataEvent', 'ListDataListener', 'ListIterator',
+            'ListModel', 'ListResourceBundle',
+            'ListSelectionEvent', 'ListSelectionListener',
+            'ListSelectionModel', 'ListUI', 'ListView',
+            'LoaderHandler', 'Locale', 'LocateRegistry',
+            'LogStream', 'Long', 'LongHolder',
+            'LongLongSeqHelper', 'LongLongSeqHolder',
+            'LongSeqHelper', 'LongSeqHolder', 'LookAndFeel',
+            'LookupOp', 'LookupTable', 'MalformedLinkException',
+            'MalformedURLException', 'Manifest', 'Map',
+            'Map.Entry', 'MARSHAL', 'MarshalException',
+            'MarshalledObject', 'Math', 'MatteBorder',
+            'MediaTracker', 'Member', 'MemoryImageSource',
+            'Menu', 'MenuBar', 'MenuBarUI', 'MenuComponent',
+            'MenuContainer', 'MenuDragMouseEvent',
+            'MenuDragMouseListener', 'MenuElement', 'MenuEvent',
+            'MenuItem', 'MenuItemUI', 'MenuKeyEvent',
+            'MenuKeyListener', 'MenuListener',
+            'MenuSelectionManager', 'MenuShortcut',
+            'MessageDigest', 'MessageDigestSpi', 'MessageFormat',
+            'MetaEventListener', 'MetalBorders',
+            'MetalBorders.ButtonBorder',
+            'MetalBorders.Flush3DBorder',
+            'MetalBorders.InternalFrameBorder',
+            'MetalBorders.MenuBarBorder',
+            'MetalBorders.MenuItemBorder',
+            'MetalBorders.OptionDialogBorder',
+            'MetalBorders.PaletteBorder',
+            'MetalBorders.PopupMenuBorder',
+            'MetalBorders.RolloverButtonBorder',
+            'MetalBorders.ScrollPaneBorder',
+            'MetalBorders.TableHeaderBorder',
+            'MetalBorders.TextFieldBorder',
+            'MetalBorders.ToggleButtonBorder',
+            'MetalBorders.ToolBarBorder', 'MetalButtonUI',
+            'MetalCheckBoxIcon', 'MetalCheckBoxUI',
+            'MetalComboBoxButton', 'MetalComboBoxEditor',
+            'MetalComboBoxEditor.UIResource',
+            'MetalComboBoxIcon', 'MetalComboBoxUI',
+            'MetalDesktopIconUI', 'MetalFileChooserUI',
+            'MetalIconFactory', 'MetalIconFactory.FileIcon16',
+            'MetalIconFactory.FolderIcon16',
+            'MetalIconFactory.PaletteCloseIcon',
+            'MetalIconFactory.TreeControlIcon',
+            'MetalIconFactory.TreeFolderIcon',
+            'MetalIconFactory.TreeLeafIcon',
+            'MetalInternalFrameTitlePane',
+            'MetalInternalFrameUI', 'MetalLabelUI',
+            'MetalLookAndFeel', 'MetalPopupMenuSeparatorUI',
+            'MetalProgressBarUI', 'MetalRadioButtonUI',
+            'MetalScrollBarUI', 'MetalScrollButton',
+            'MetalScrollPaneUI', 'MetalSeparatorUI',
+            'MetalSliderUI', 'MetalSplitPaneUI',
+            'MetalTabbedPaneUI', 'MetalTextFieldUI',
+            'MetalTheme', 'MetalToggleButtonUI',
+            'MetalToolBarUI', 'MetalToolTipUI', 'MetalTreeUI',
+            'MetaMessage', 'Method', 'MethodDescriptor',
+            'MidiChannel', 'MidiDevice', 'MidiDevice.Info',
+            'MidiDeviceProvider', 'MidiEvent', 'MidiFileFormat',
+            'MidiFileReader', 'MidiFileWriter', 'MidiMessage',
+            'MidiSystem', 'MidiUnavailableException',
+            'MimeTypeParseException', 'MinimalHTMLWriter',
+            'MissingResourceException', 'Mixer', 'Mixer.Info',
+            'MixerProvider', 'ModificationItem', 'Modifier',
+            'MouseAdapter', 'MouseDragGestureRecognizer',
+            'MouseEvent', 'MouseInputAdapter',
+            'MouseInputListener', 'MouseListener',
+            'MouseMotionAdapter', 'MouseMotionListener',
+            'MultiButtonUI', 'MulticastSocket',
+            'MultiColorChooserUI', 'MultiComboBoxUI',
+            'MultiDesktopIconUI', 'MultiDesktopPaneUI',
+            'MultiFileChooserUI', 'MultiInternalFrameUI',
+            'MultiLabelUI', 'MultiListUI', 'MultiLookAndFeel',
+            'MultiMenuBarUI', 'MultiMenuItemUI',
+            'MultiOptionPaneUI', 'MultiPanelUI',
+            'MultiPixelPackedSampleModel', 'MultipleMaster',
+            'MultiPopupMenuUI', 'MultiProgressBarUI',
+            'MultiScrollBarUI', 'MultiScrollPaneUI',
+            'MultiSeparatorUI', 'MultiSliderUI',
+            'MultiSplitPaneUI', 'MultiTabbedPaneUI',
+            'MultiTableHeaderUI', 'MultiTableUI', 'MultiTextUI',
+            'MultiToolBarUI', 'MultiToolTipUI', 'MultiTreeUI',
+            'MultiViewportUI', 'MutableAttributeSet',
+            'MutableComboBoxModel', 'MutableTreeNode', 'Name',
+            'NameAlreadyBoundException', 'NameClassPair',
+            'NameComponent', 'NameComponentHelper',
+            'NameComponentHolder', 'NamedValue', 'NameHelper',
+            'NameHolder', 'NameNotFoundException', 'NameParser',
+            'NamespaceChangeListener', 'NameValuePair',
+            'NameValuePairHelper', 'Naming', 'NamingContext',
+            'NamingContextHelper', 'NamingContextHolder',
+            'NamingContextOperations', 'NamingEnumeration',
+            'NamingEvent', 'NamingException',
+            'NamingExceptionEvent', 'NamingListener',
+            'NamingManager', 'NamingSecurityException',
+            'NegativeArraySizeException', 'NetPermission',
+            'NoClassDefFoundError', 'NoInitialContextException',
+            'NoninvertibleTransformException',
+            'NoPermissionException', 'NoRouteToHostException',
+            'NoSuchAlgorithmException',
+            'NoSuchAttributeException', 'NoSuchElementException',
+            'NoSuchFieldError', 'NoSuchFieldException',
+            'NoSuchMethodError', 'NoSuchMethodException',
+            'NoSuchObjectException', 'NoSuchProviderException',
+            'NotActiveException', 'NotBoundException',
+            'NotContextException', 'NotEmpty', 'NotEmptyHelper',
+            'NotEmptyHolder', 'NotFound', 'NotFoundHelper',
+            'NotFoundHolder', 'NotFoundReason',
+            'NotFoundReasonHelper', 'NotFoundReasonHolder',
+            'NotOwnerException', 'NotSerializableException',
+            'NO_IMPLEMENT', 'NO_MEMORY', 'NO_PERMISSION',
+            'NO_RESOURCES', 'NO_RESPONSE',
+            'NullPointerException', 'Number', 'NumberFormat',
+            'NumberFormatException', 'NVList', 'Object',
+            'ObjectChangeListener', 'ObjectFactory',
+            'ObjectFactoryBuilder', 'ObjectHelper',
+            'ObjectHolder', 'ObjectImpl', 'ObjectInput',
+            'ObjectInputStream', 'ObjectInputStream.GetField',
+            'ObjectInputValidation', 'ObjectOutput',
+            'ObjectOutputStream', 'ObjectOutputStream.PutField',
+            'ObjectStreamClass', 'ObjectStreamConstants',
+            'ObjectStreamException', 'ObjectStreamField',
+            'ObjectView', 'OBJECT_NOT_EXIST', 'ObjID',
+            'OBJ_ADAPTER', 'Observable', 'Observer',
+            'OctetSeqHelper', 'OctetSeqHolder', 'OMGVMCID',
+            'OpenType', 'Operation',
+            'OperationNotSupportedException', 'Option',
+            'OptionalDataException', 'OptionPaneUI', 'ORB',
+            'OutOfMemoryError', 'OutputStream',
+            'OutputStreamWriter', 'OverlayLayout', 'Owner',
+            'Package', 'PackedColorModel', 'Pageable',
+            'PageAttributes', 'PageAttributes.ColorType',
+            'PageAttributes.MediaType',
+            'PageAttributes.OrientationRequestedType',
+            'PageAttributes.OriginType',
+            'PageAttributes.PrintQualityType', 'PageFormat',
+            'Paint', 'PaintContext', 'PaintEvent', 'Panel',
+            'PanelUI', 'Paper', 'ParagraphView',
+            'ParameterBlock', 'ParameterDescriptor',
+            'ParseException', 'ParsePosition', 'Parser',
+            'ParserDelegator', 'PartialResultException',
+            'PasswordAuthentication', 'PasswordView', 'Patch',
+            'PathIterator', 'Permission', 'PermissionCollection',
+            'Permissions', 'PERSIST_STORE', 'PhantomReference',
+            'PipedInputStream', 'PipedOutputStream',
+            'PipedReader', 'PipedWriter', 'PixelGrabber',
+            'PixelInterleavedSampleModel', 'PKCS8EncodedKeySpec',
+            'PlainDocument', 'PlainView', 'Point', 'Point2D',
+            'Point2D.Double', 'Point2D.Float', 'Policy',
+            'PolicyError', 'PolicyHelper', 'PolicyHolder',
+            'PolicyListHelper', 'PolicyListHolder',
+            'PolicyOperations', 'PolicyTypeHelper', 'Polygon',
+            'PopupMenu', 'PopupMenuEvent', 'PopupMenuListener',
+            'PopupMenuUI', 'Port', 'Port.Info',
+            'PortableRemoteObject',
+            'PortableRemoteObjectDelegate', 'Position',
+            'Position.Bias', 'PreparedStatement', 'Principal',
+            'PrincipalHolder', 'Printable',
+            'PrinterAbortException', 'PrinterException',
+            'PrinterGraphics', 'PrinterIOException',
+            'PrinterJob', 'PrintGraphics', 'PrintJob',
+            'PrintStream', 'PrintWriter', 'PrivateKey',
+            'PRIVATE_MEMBER', 'PrivilegedAction',
+            'PrivilegedActionException',
+            'PrivilegedExceptionAction', 'Process',
+            'ProfileDataException', 'ProgressBarUI',
+            'ProgressMonitor', 'ProgressMonitorInputStream',
+            'Properties', 'PropertyChangeEvent',
+            'PropertyChangeListener', 'PropertyChangeSupport',
+            'PropertyDescriptor', 'PropertyEditor',
+            'PropertyEditorManager', 'PropertyEditorSupport',
+            'PropertyPermission', 'PropertyResourceBundle',
+            'PropertyVetoException', 'ProtectionDomain',
+            'ProtocolException', 'Provider', 'ProviderException',
+            'Proxy', 'PublicKey', 'PUBLIC_MEMBER',
+            'PushbackInputStream', 'PushbackReader',
+            'QuadCurve2D', 'QuadCurve2D.Double',
+            'QuadCurve2D.Float', 'Random', 'RandomAccessFile',
+            'Raster', 'RasterFormatException', 'RasterOp',
+            'Reader', 'Receiver', 'Rectangle', 'Rectangle2D',
+            'Rectangle2D.Double', 'Rectangle2D.Float',
+            'RectangularShape', 'Ref', 'RefAddr', 'Reference',
+            'Referenceable', 'ReferenceQueue',
+            'ReferralException', 'ReflectPermission', 'Registry',
+            'RegistryHandler', 'RemarshalException', 'Remote',
+            'RemoteCall', 'RemoteException', 'RemoteObject',
+            'RemoteRef', 'RemoteServer', 'RemoteStub',
+            'RenderableImage', 'RenderableImageOp',
+            'RenderableImageProducer', 'RenderContext',
+            'RenderedImage', 'RenderedImageFactory', 'Renderer',
+            'RenderingHints', 'RenderingHints.Key',
+            'RepaintManager', 'ReplicateScaleFilter',
+            'Repository', 'RepositoryIdHelper', 'Request',
+            'RescaleOp', 'Resolver', 'ResolveResult',
+            'ResourceBundle', 'ResponseHandler', 'ResultSet',
+            'ResultSetMetaData', 'ReverbType', 'RGBImageFilter',
+            'RMIClassLoader', 'RMIClientSocketFactory',
+            'RMIFailureHandler', 'RMISecurityException',
+            'RMISecurityManager', 'RMIServerSocketFactory',
+            'RMISocketFactory', 'Robot', 'RootPaneContainer',
+            'RootPaneUI', 'RoundRectangle2D',
+            'RoundRectangle2D.Double', 'RoundRectangle2D.Float',
+            'RowMapper', 'RSAKey', 'RSAKeyGenParameterSpec',
+            'RSAPrivateCrtKey', 'RSAPrivateCrtKeySpec',
+            'RSAPrivateKey', 'RSAPrivateKeySpec', 'RSAPublicKey',
+            'RSAPublicKeySpec', 'RTFEditorKit',
+            'RuleBasedCollator', 'Runnable', 'Runtime',
+            'RunTime', 'RuntimeException', 'RunTimeOperations',
+            'RuntimePermission', 'SampleModel',
+            'SchemaViolationException', 'Scrollable',
+            'Scrollbar', 'ScrollBarUI', 'ScrollPane',
+            'ScrollPaneConstants', 'ScrollPaneLayout',
+            'ScrollPaneLayout.UIResource', 'ScrollPaneUI',
+            'SearchControls', 'SearchResult',
+            'SecureClassLoader', 'SecureRandom',
+            'SecureRandomSpi', 'Security', 'SecurityException',
+            'SecurityManager', 'SecurityPermission', 'Segment',
+            'SeparatorUI', 'Sequence', 'SequenceInputStream',
+            'Sequencer', 'Sequencer.SyncMode', 'Serializable',
+            'SerializablePermission', 'ServantObject',
+            'ServerCloneException', 'ServerError',
+            'ServerException', 'ServerNotActiveException',
+            'ServerRef', 'ServerRequest',
+            'ServerRuntimeException', 'ServerSocket',
+            'ServiceDetail', 'ServiceDetailHelper',
+            'ServiceInformation', 'ServiceInformationHelper',
+            'ServiceInformationHolder',
+            'ServiceUnavailableException', 'Set',
+            'SetOverrideType', 'SetOverrideTypeHelper', 'Shape',
+            'ShapeGraphicAttribute', 'Short', 'ShortHolder',
+            'ShortLookupTable', 'ShortMessage', 'ShortSeqHelper',
+            'ShortSeqHolder', 'Signature', 'SignatureException',
+            'SignatureSpi', 'SignedObject', 'Signer',
+            'SimpleAttributeSet', 'SimpleBeanInfo',
+            'SimpleDateFormat', 'SimpleTimeZone',
+            'SinglePixelPackedSampleModel',
+            'SingleSelectionModel', 'SizeLimitExceededException',
+            'SizeRequirements', 'SizeSequence', 'Skeleton',
+            'SkeletonMismatchException',
+            'SkeletonNotFoundException', 'SliderUI', 'Socket',
+            'SocketException', 'SocketImpl', 'SocketImplFactory',
+            'SocketOptions', 'SocketPermission',
+            'SocketSecurityException', 'SoftBevelBorder',
+            'SoftReference', 'SortedMap', 'SortedSet',
+            'Soundbank', 'SoundbankReader', 'SoundbankResource',
+            'SourceDataLine', 'SplitPaneUI', 'SQLData',
+            'SQLException', 'SQLInput', 'SQLOutput',
+            'SQLPermission', 'SQLWarning', 'Stack',
+            'StackOverflowError', 'StateEdit', 'StateEditable',
+            'StateFactory', 'Statement', 'Streamable',
+            'StreamableValue', 'StreamCorruptedException',
+            'StreamTokenizer', 'StrictMath', 'String',
+            'StringBuffer', 'StringBufferInputStream',
+            'StringCharacterIterator', 'StringContent',
+            'StringHolder', 'StringIndexOutOfBoundsException',
+            'StringReader', 'StringRefAddr', 'StringSelection',
+            'StringTokenizer', 'StringValueHelper',
+            'StringWriter', 'Stroke', 'Struct', 'StructMember',
+            'StructMemberHelper', 'Stub', 'StubDelegate',
+            'StubNotFoundException', 'Style', 'StyleConstants',
+            'StyleConstants.CharacterConstants',
+            'StyleConstants.ColorConstants',
+            'StyleConstants.FontConstants',
+            'StyleConstants.ParagraphConstants', 'StyleContext',
+            'StyledDocument', 'StyledEditorKit',
+            'StyledEditorKit.AlignmentAction',
+            'StyledEditorKit.BoldAction',
+            'StyledEditorKit.FontFamilyAction',
+            'StyledEditorKit.FontSizeAction',
+            'StyledEditorKit.ForegroundAction',
+            'StyledEditorKit.ItalicAction',
+            'StyledEditorKit.StyledTextAction',
+            'StyledEditorKit.UnderlineAction', 'StyleSheet',
+            'StyleSheet.BoxPainter', 'StyleSheet.ListPainter',
+            'SwingConstants', 'SwingPropertyChangeSupport',
+            'SwingUtilities', 'SyncFailedException',
+            'Synthesizer', 'SysexMessage', 'System',
+            'SystemColor', 'SystemException', 'SystemFlavorMap',
+            'TabableView', 'TabbedPaneUI', 'TabExpander',
+            'TableCellEditor', 'TableCellRenderer',
+            'TableColumn', 'TableColumnModel',
+            'TableColumnModelEvent', 'TableColumnModelListener',
+            'TableHeaderUI', 'TableModel', 'TableModelEvent',
+            'TableModelListener', 'TableUI', 'TableView',
+            'TabSet', 'TabStop', 'TagElement', 'TargetDataLine',
+            'TCKind', 'TextAction', 'TextArea', 'TextAttribute',
+            'TextComponent', 'TextEvent', 'TextField',
+            'TextHitInfo', 'TextLayout',
+            'TextLayout.CaretPolicy', 'TextListener',
+            'TextMeasurer', 'TextUI', 'TexturePaint', 'Thread',
+            'ThreadDeath', 'ThreadGroup', 'ThreadLocal',
+            'Throwable', 'Tie', 'TileObserver', 'Time',
+            'TimeLimitExceededException', 'Timer', 'TimerTask',
+            'Timestamp', 'TimeZone', 'TitledBorder', 'ToolBarUI',
+            'Toolkit', 'ToolTipManager', 'ToolTipUI',
+            'TooManyListenersException', 'Track',
+            'TransactionRequiredException',
+            'TransactionRolledbackException',
+            'TRANSACTION_REQUIRED', 'TRANSACTION_ROLLEDBACK',
+            'Transferable', 'TransformAttribute', 'TRANSIENT',
+            'Transmitter', 'Transparency', 'TreeCellEditor',
+            'TreeCellRenderer', 'TreeExpansionEvent',
+            'TreeExpansionListener', 'TreeMap', 'TreeModel',
+            'TreeModelEvent', 'TreeModelListener', 'TreeNode',
+            'TreePath', 'TreeSelectionEvent',
+            'TreeSelectionListener', 'TreeSelectionModel',
+            'TreeSet', 'TreeUI', 'TreeWillExpandListener',
+            'TypeCode', 'TypeCodeHolder', 'TypeMismatch',
+            'Types', 'UID', 'UIDefaults',
+            'UIDefaults.ActiveValue', 'UIDefaults.LazyInputMap',
+            'UIDefaults.LazyValue', 'UIDefaults.ProxyLazyValue',
+            'UIManager', 'UIManager.LookAndFeelInfo',
+            'UIResource', 'ULongLongSeqHelper',
+            'ULongLongSeqHolder', 'ULongSeqHelper',
+            'ULongSeqHolder', 'UndeclaredThrowableException',
+            'UndoableEdit', 'UndoableEditEvent',
+            'UndoableEditListener', 'UndoableEditSupport',
+            'UndoManager', 'UnexpectedException',
+            'UnicastRemoteObject', 'UnionMember',
+            'UnionMemberHelper', 'UNKNOWN', 'UnknownError',
+            'UnknownException', 'UnknownGroupException',
+            'UnknownHostException', 'UnknownObjectException',
+            'UnknownServiceException', 'UnknownUserException',
+            'UnmarshalException', 'UnrecoverableKeyException',
+            'Unreferenced', 'UnresolvedPermission',
+            'UnsatisfiedLinkError', 'UnsolicitedNotification',
+            'UnsolicitedNotificationEvent',
+            'UnsolicitedNotificationListener',
+            'UnsupportedAudioFileException',
+            'UnsupportedClassVersionError',
+            'UnsupportedEncodingException',
+            'UnsupportedFlavorException',
+            'UnsupportedLookAndFeelException',
+            'UnsupportedOperationException',
+            'UNSUPPORTED_POLICY', 'UNSUPPORTED_POLICY_VALUE',
+            'URL', 'URLClassLoader', 'URLConnection',
+            'URLDecoder', 'URLEncoder', 'URLStreamHandler',
+            'URLStreamHandlerFactory', 'UserException',
+            'UShortSeqHelper', 'UShortSeqHolder',
+            'UTFDataFormatException', 'Util', 'UtilDelegate',
+            'Utilities', 'ValueBase', 'ValueBaseHelper',
+            'ValueBaseHolder', 'ValueFactory', 'ValueHandler',
+            'ValueMember', 'ValueMemberHelper',
+            'VariableHeightLayoutCache', 'Vector', 'VerifyError',
+            'VersionSpecHelper', 'VetoableChangeListener',
+            'VetoableChangeSupport', 'View', 'ViewFactory',
+            'ViewportLayout', 'ViewportUI',
+            'VirtualMachineError', 'Visibility',
+            'VisibilityHelper', 'VMID', 'VM_ABSTRACT',
+            'VM_CUSTOM', 'VM_NONE', 'VM_TRUNCATABLE',
+            'VoiceStatus', 'Void', 'WCharSeqHelper',
+            'WCharSeqHolder', 'WeakHashMap', 'WeakReference',
+            'Window', 'WindowAdapter', 'WindowConstants',
+            'WindowEvent', 'WindowListener', 'WrappedPlainView',
+            'WritableRaster', 'WritableRenderedImage',
+            'WriteAbortedException', 'Writer',
+            'WrongTransaction', 'WStringValueHelper',
+            'X509Certificate', 'X509CRL', 'X509CRLEntry',
+            'X509EncodedKeySpec', 'X509Extension', 'ZipEntry',
+            'ZipException', 'ZipFile', 'ZipInputStream',
+            'ZipOutputStream', 'ZoneView',
+            '_BindingIteratorImplBase', '_BindingIteratorStub',
+            '_IDLTypeStub', '_NamingContextImplBase',
+            '_NamingContextStub', '_PolicyStub', '_Remote_Stub'
+            ),
+        4 => array(
+            'boolean', 'byte', 'char', 'double', 'float', 'int', 'long',
+            'short', 'void'
+            ),
+        5 => array(
+            'allProperties', 'asImmutable', 'asSynchronized', 'collect',
+            'count', 'each', 'eachProperty', 'eachPropertyName',
+            'eachWithIndex', 'find', 'findAll', 'findIndexOf',
+            'flatten', 'get', 'grep', 'inject', 'intersect',
+            'join', 'max', 'min', 'pop', 'reverse',
+            'reverseEach', 'size', 'sort', 'subMap', 'toList'
+            ),
+        6 => array(
+            'center', 'contains', 'eachMatch', 'padLeft', 'padRight',
+            'toCharacter', 'tokenize', 'toLong', 'toURL'
+            ),
+        7 => array(
+            'append', 'eachByte', 'eachFile', 'eachFileRecurse', 'eachLine',
+            'eachLines', 'encodeBase64', 'filterLine', 'getText',
+            'splitEachLine', 'transformChar', 'transformLine',
+            'withOutputStream', 'withPrintWriter', 'withReader',
+            'withStream', 'withStreams', 'withWriter',
+            'withWriterAppend', 'write', 'writeLine'
+            ),
+        8 => array(
+            'dump', 'getLastMatcher', 'inspect', 'invokeMethod', 'print',
+            'println', 'start', 'startDaemon', 'step', 'times',
+            'upto', 'use'
+            ),
+        9 => array(
+            'call', 'close', 'eachRow', 'execute', 'executeUpdate', 'Sql'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}', '*', '&', '%', '!', ';', '<', '>', '?', '|', '=',
+        '=>', '||', '-', '+', '<<', '<<<', '&&'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => true,
+        1 => false,
+        2 => false,
+        3 => true,
+        4 => true,
+        5 => true,
+        6 => true,
+        7 => true,
+        8 => true,
+        9 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #aaaadd; font-weight: bold;',
+            4 => 'color: #993333;',
+            5 => 'color: #663399;',
+            6 => 'color: #CC0099;',
+            7 => 'color: #FFCC33;',
+            8 => 'color: #993399;',
+            9 => 'color: #993399; font-weight: bold;'
+            ),
+        'COMMENTS' => array(
+            1=> 'color: #808080; font-style: italic;',
+            2=> 'color: #a1a100;',
+            3=> 'color: #808080; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006600;',
+            2 => 'color: #006600;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #0000ff;'
+            )
+        ),
+    'URLS' => array(
+        1 => 'http://www.google.de/search?q=site%3Adocs.codehaus.org/%20{FNAMEL}',
+        2 => 'http://www.google.de/search?q=site%3Adocs.codehaus.org/%20{FNAMEL}',
+        3 => 'http://www.google.de/search?as_q={FNAME}&amp;num=100&amp;hl=en&amp;as_occt=url&amp;as_sitesearch=java.sun.com%2Fj2se%2F1.5.0%2Fdocs%2Fapi%2F',
+        4 => 'http://www.google.de/search?q=site%3Adocs.codehaus.org/%20{FNAME}',
+        5 => 'http://www.google.de/search?q=site%3Adocs.codehaus.org/%20{FNAME}',
+        6 => 'http://www.google.de/search?q=site%3Adocs.codehaus.org/%20{FNAME}',
+        7 => 'http://www.google.de/search?q=site%3Adocs.codehaus.org/%20{FNAME}',
+        8 => 'http://www.google.de/search?q=site%3Adocs.codehaus.org/%20{FNAME}',
+        9 => 'http://www.google.de/search?q=site%3Adocs.codehaus.org/%20{FNAME}'
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        //Variables
+        0 => '\\$\\{[a-zA-Z_][a-zA-Z0-9_]*\\}'
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/haskell.php b/examples/includes/geshi/geshi/haskell.php
new file mode 100644 (file)
index 0000000..a6841dd
--- /dev/null
@@ -0,0 +1,198 @@
+<?php
+/*************************************************************************************
+ * haskell.php
+ * ----------
+ * Author: Jason Dagit (dagit@codersbase.com) based on ocaml.php by Flaie (fireflaie@gmail.com)
+ * Copyright: (c) 2005 Flaie, Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2005/08/27
+ *
+ * Haskell language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2005/08/27 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2005/08/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *   This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Haskell',
+    'COMMENT_SINGLE' => array( 1 => '--'),
+    'COMMENT_MULTI' => array('{-' => '-}'),
+    'COMMENT_REGEXP' => array(2 => "/-->/"),
+    'CASE_KEYWORDS' => 0,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => "\\",
+    'KEYWORDS' => array(
+        /* main haskell keywords */
+        1 => array(
+            'as',
+            'case', 'of', 'class', 'data', 'default',
+            'deriving', 'do', 'forall', 'hiding', 'if', 'then',
+            'else', 'import', 'infix', 'infixl', 'infixr',
+            'instance', 'let', 'in', 'module', 'newtype',
+            'qualified', 'type', 'where'
+            ),
+        /* define names of main librarys, so we can link to it */
+        2 => array(
+            'Foreign', 'Numeric', 'Prelude'
+            ),
+        /* just link to Prelude functions, cause it's the default opened library when starting Haskell */
+        3 => array(
+            'not', 'otherwise', 'maybe',
+            'either', 'fst', 'snd', 'curry', 'uncurry',
+            'compare',
+            'max', 'min', 'succ', 'pred', 'toEnum', 'fromEnum',
+            'enumFrom', 'enumFromThen', 'enumFromTo',
+            'enumFromThenTo', 'minBound', 'maxBound',
+            'negate', 'abs', 'signum',
+            'fromInteger', 'toRational', 'quot', 'rem',
+            'div', 'mod', 'quotRem', 'divMod', 'toInteger',
+            'recip', 'fromRational', 'pi', 'exp',
+            'log', 'sqrt', 'logBase', 'sin', 'cos',
+            'tan', 'asin', 'acos', 'atan', 'sinh', 'cosh',
+            'tanh', 'asinh', 'acosh', 'atanh',
+            'properFraction', 'truncate', 'round', 'ceiling',
+            'floor', 'floatRadix', 'floatDigits', 'floatRange',
+            'decodeFloat', 'encodeFloat', 'exponent',
+            'significand', 'scaleFloat', 'isNaN', 'isInfinite',
+            'isDenomalized', 'isNegativeZero', 'isIEEE',
+            'atan2', 'subtract', 'even', 'odd', 'gcd',
+            'lcm', 'fromIntegral', 'realToFrac',
+            'return', 'fail', 'fmap',
+            'mapM', 'mapM_', 'sequence', 'sequence_',
+            'id', 'const','flip',
+            'until', 'asTypeOf', 'error', 'undefined',
+            'seq','map','filter', 'head',
+            'last', 'tail', 'init', 'null', 'length',
+            'reverse', 'foldl', 'foldl1', 'foldr',
+            'foldr1', 'and', 'or', 'any', 'all', 'sum',
+            'product', 'concat', 'concatMap', 'maximum',
+            'minimum', 'scanl', 'scanl1', 'scanr', 'scanr1',
+            'iterate', 'repeat', 'cycle', 'take', 'drop',
+            'splitAt', 'teakWhile', 'dropWhile', 'span',
+            'break', 'elem', 'notElem', 'lookup', 'zip',
+            'zip3', 'zipWith', 'zipWith3', 'unzip', 'unzip3',
+            'lines', 'words', 'unlines',
+            'unwords', 'showPrec', 'show', 'showList',
+            'shows', 'showChar', 'showString', 'showParen',
+            'readsPrec', 'readList', 'reads', 'readParen',
+            'read', 'lex', 'putChar', 'putStr', 'putStrLn',
+            'print', 'getChar', 'getLine', 'getContents',
+            'interact', 'readFile', 'writeFile', 'appendFile',
+            'readIO', 'readLn', 'ioError', 'userError', 'catch'
+            ),
+        /* here Prelude Types */
+        4 => array (
+            'Bool', 'Maybe', 'Either', 'Ord', 'Ordering',
+            'Char', 'String', 'Eq', 'Enum', 'Bounded',
+            'Int', 'Integer', 'Float', 'Double', 'Rational',
+            'Num', 'Real', 'Integral', 'Fractional',
+            'Floating', 'RealFrac', 'RealFloat', 'Monad',
+            'Functor', 'Show', 'ShowS', 'Read', 'ReadS',
+            'IO'
+            ),
+        /* finally Prelude Exceptions */
+        5 => array (
+            'IOError', 'IOException'
+            )
+        ),
+    /* highlighting symbols is really important in Haskell */
+    'SYMBOLS' => array(
+        '|', '->', '<-', '@', '!', '::', '_', '~', '=', '?',
+        '&&', '||', '==', '/=', '<', '<=', '>',
+        '>=','+', '-', '*','/', '%', '**', '^', '^^',
+        '>>=', '>>', '=<<',  '$', '.', ',', '$!',
+        '++', '!!'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true, /* functions name are case seinsitive */
+        3 => true, /* types name too */
+        4 => true, /* finally exceptions too */
+        5 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #06c; font-weight: bold;', /* nice blue */
+            2 => 'color: #06c; font-weight: bold;', /* blue as well */
+            3 => 'font-weight: bold;', /* make the preduled functions bold */
+            4 => 'color: #cccc00; font-weight: bold;', /* give types a different bg */
+            5 => 'color: maroon;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #5d478b; font-style: italic;',
+            2 => 'color: #339933; font-weight: bold;',
+            'MULTI' => 'color: #5d478b; font-style: italic;' /* light purpHle */
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'background-color: #3cb371; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: green;'
+            ),
+        'STRINGS' => array(
+            0 => 'background-color: #3cb371;' /* nice green */
+            ),
+        'NUMBERS' => array(
+            0 => 'color: red;' /* pink */
+            ),
+        'METHODS' => array(
+            1 => 'color: #060;' /* dark green */
+            ),
+        'REGEXPS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #339933; font-weight: bold;'
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        /* some of keywords are Prelude functions */
+        1 => '',
+        /* link to the wanted library */
+        2 => 'http://haskell.org/ghc/docs/latest/html/libraries/base/{FNAME}.html',
+        /* link to Prelude functions */
+        3 => 'http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:{FNAME}',
+        /* link to Prelude types */
+        4 => 'http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:{FNAME}',
+        /* link to Prelude exceptions */
+        5 => 'http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:{FNAME}',
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/hq9plus.php b/examples/includes/geshi/geshi/hq9plus.php
new file mode 100644 (file)
index 0000000..89e0434
--- /dev/null
@@ -0,0 +1,104 @@
+<?php
+/*************************************************************************************
+ * hq9plus.php
+ * ----------
+ * Author: Benny Baumann (BenBE@geshi.org)
+ * Copyright: (c) 2008 Benny Baumann (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2009/10/31
+ *
+ * HQ9+ language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/10/31 (1.0.8.1)
+ *   -  First Release
+ *
+ * TODO
+ * ----
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+$language_data = array (
+    'LANG_NAME' => 'HQ9+',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array(),
+    'COMMENT_REGEXP' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_UPPER,
+    'QUOTEMARKS' => array(),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        ),
+    'SYMBOLS' => array(
+        'H', 'Q', '9', '+', 'h', 'q'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            ),
+        'COMMENTS' => array(
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #a16000;'
+            ),
+        'ESCAPE_CHAR' => array(
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4,
+    'PARSER_CONTROL' => array(
+        'ENABLE_FLAGS' => array(
+            'KEYWORDS' => GESHI_NEVER,
+            'COMMENTS' => GESHI_NEVER,
+            'STRINGS' => GESHI_NEVER,
+            'REGEXPS' => GESHI_NEVER,
+            'NUMBERS' => GESHI_NEVER
+            )
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/html4strict.php b/examples/includes/geshi/geshi/html4strict.php
new file mode 100644 (file)
index 0000000..68a0e51
--- /dev/null
@@ -0,0 +1,203 @@
+<?php
+/*************************************************************************************
+ * html4strict.php
+ * ---------------
+ * Author: Nigel McNie (nigel@geshi.org)
+ * Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/07/10
+ *
+ * HTML 4.01 strict language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2005/12/28 (1.0.4)
+ *   -  Removed escape character for strings
+ * 2004/11/27 (1.0.3)
+ *   -  Added support for multiple object splitters
+ * 2004/10/27 (1.0.2)
+ *   -  Added support for URLs
+ * 2004/08/05 (1.0.1)
+ *   -  Added INS and DEL
+ *   -  Removed the background colour from tags' styles
+ * 2004/07/14 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ * * Check that only HTML4 strict attributes are highlighted
+ * * Eliminate empty tags that aren't allowed in HTML4 strict
+ * * Split to several files - html4trans, xhtml1 etc
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'HTML',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        2 => array(
+            'a', 'abbr', 'acronym', 'address', 'applet',
+
+            'base', 'basefont', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'b',
+
+            'caption', 'center', 'cite', 'code', 'colgroup', 'col',
+
+            'dd', 'del', 'dfn', 'dir', 'div', 'dl', 'dt',
+
+            'em',
+
+            'fieldset', 'font', 'form', 'frame', 'frameset',
+
+            'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'hr', 'html',
+
+            'iframe', 'ilayer', 'img', 'input', 'ins', 'isindex', 'i',
+
+            'kbd',
+
+            'label', 'legend', 'link', 'li',
+
+            'map', 'meta',
+
+            'noframes', 'noscript',
+
+            'object', 'ol', 'optgroup', 'option',
+
+            'param', 'pre', 'p',
+
+            'q',
+
+            'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'style', 'sub', 'sup', 's',
+
+            'table', 'tbody', 'td', 'textarea', 'text', 'tfoot', 'thead', 'th', 'title', 'tr', 'tt',
+
+            'ul', 'u',
+
+            'var',
+            ),
+        3 => array(
+            'abbr', 'accept-charset', 'accept', 'accesskey', 'action', 'align', 'alink', 'alt', 'archive', 'axis',
+            'background', 'bgcolor', 'border',
+            'cellpadding', 'cellspacing', 'char', 'charoff', 'charset', 'checked', 'cite', 'class', 'classid', 'clear', 'code', 'codebase', 'codetype', 'color', 'cols', 'colspan', 'compact', 'content', 'coords',
+            'data', 'datetime', 'declare', 'defer', 'dir', 'disabled',
+            'enctype',
+            'face', 'for', 'frame', 'frameborder',
+            'headers', 'height', 'href', 'hreflang', 'hspace', 'http-equiv',
+            'id', 'ismap',
+            'label', 'lang', 'language', 'link', 'longdesc',
+            'marginheight', 'marginwidth', 'maxlength', 'media', 'method', 'multiple',
+            'name', 'nohref', 'noresize', 'noshade', 'nowrap',
+            'object', 'onblur', 'onchange', 'onclick', 'ondblclick', 'onfocus', 'onkeydown', 'onkeypress', 'onkeyup', 'onload', 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onreset', 'onselect', 'onsubmit', 'onunload',
+            'profile', 'prompt',
+            'readonly', 'rel', 'rev', 'rowspan', 'rows', 'rules',
+            'scheme', 'scope', 'scrolling', 'selected', 'shape', 'size', 'span', 'src', 'standby', 'start', 'style', 'summary',
+            'tabindex', 'target', 'text', 'title', 'type',
+            'usemap',
+            'valign', 'value', 'valuetype', 'version', 'vlink', 'vspace',
+            'width'
+            )
+        ),
+    'SYMBOLS' => array(
+        '/', '='
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        2 => false,
+        3 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #000066;'
+            ),
+        'COMMENTS' => array(
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'SCRIPT' => array(
+            -1 => 'color: #808080; font-style: italic;', // comments
+            0 => 'color: #00bbdd;',
+            1 => 'color: #ddbb00;',
+            2 => 'color: #009900;'
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        2 => 'http://december.com/html/4/element/{FNAMEL}.html',
+        3 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_ALWAYS,
+    'SCRIPT_DELIMITERS' => array(
+        -1 => array(
+            '<!--' => '-->'
+            ),
+        0 => array(
+            '<!DOCTYPE' => '>'
+            ),
+        1 => array(
+            '&' => ';'
+            ),
+        2 => array(
+            '<' => '>'
+            )
+    ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        -1 => false,
+        0 => false,
+        1 => false,
+        2 => true
+        ),
+    'TAB_WIDTH' => 4,
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            2 => array(
+                'DISALLOWED_BEFORE' => '(?<=&lt;|&lt;\/)',
+                'DISALLOWED_AFTER' => '(?=\s|\/|&gt;)',
+            )
+        )
+    )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/idl.php b/examples/includes/geshi/geshi/idl.php
new file mode 100644 (file)
index 0000000..a641554
--- /dev/null
@@ -0,0 +1,123 @@
+<?php
+/*************************************************************************************
+ * idl.php
+ * -------
+ * Author: Cedric Bosdonnat (cedricbosdo@openoffice.org)
+ * Copyright: (c) 2006 Cedric Bosdonnat
+ * Release Version: 1.0.8.3
+ * Date Started: 2006/08/20
+ *
+ * Unoidl language file for GeSHi.
+ *
+ * 2006/08/20 (1.0.0)
+ *  -  First Release
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+
+$language_data = array (
+    'LANG_NAME' => 'Uno Idl',
+    'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'published', 'get', 'set', 'service', 'singleton', 'type', 'module', 'interface', 'struct',
+            'const', 'constants', 'exception', 'enum', 'raises', 'typedef'
+            ),
+        2 => array(
+            'bound', 'maybeambiguous', 'maybedefault', 'maybevoid', 'oneway', 'optional',
+            'readonly', 'in', 'out', 'inout', 'attribute', 'transient', 'removable'
+            ),
+        3 => array(
+            'True', 'False', 'TRUE', 'FALSE'
+            ),
+        4 => array(
+            'string', 'long', 'byte', 'hyper', 'boolean', 'any', 'char', 'double',
+            'void', 'sequence', 'unsigned'
+            ),
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '{', '}', '[', ']', '=', '+', '-', '*', '/', '!', '%', '^', '&', ':', ';', '...'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #990078; font-weight: bold',
+            2 => 'color: #36dd1c;',
+            3 => 'color: #990078; font-weight: bold',
+            4 => 'color: #0000ec;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #3f7f5f;',
+            2 => 'color: #808080;',
+            'MULTI' => 'color: #4080ff; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #666666; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #808080;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #0000dd;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        1 => '::'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/ini.php b/examples/includes/geshi/geshi/ini.php
new file mode 100644 (file)
index 0000000..b6e3a38
--- /dev/null
@@ -0,0 +1,128 @@
+<?php
+/*************************************************************************************
+ * ini.php
+ * --------
+ * Author: deguix (cevo_deguix@yahoo.com.br)
+ * Copyright: (c) 2005 deguix
+ * Release Version: 1.0.8.3
+ * Date Started: 2005/03/27
+ *
+ * INI language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *   -  Added description of extra language features (SF#1970248)
+ * 2005/12/28 (1.0.1)
+ *   -  Removed unnecessary keyword style index
+ *   -  Added support for " strings
+ * 2005/04/05 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2005/03/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'INI',
+    'COMMENT_SINGLE' => array(0 => ';'),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        ),
+    'SYMBOLS' => array(
+        '[', ']', '='
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            ),
+        'COMMENTS' => array(
+            0 => 'color: #666666; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => ''
+            ),
+        'BRACKETS' => array(
+            0 => ''
+            ),
+        'STRINGS' => array(
+            0 => 'color: #933;'
+            ),
+        'NUMBERS' => array(
+            0 => ''
+            ),
+        'METHODS' => array(
+            0 => ''
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000066; font-weight:bold;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #000066; font-weight:bold;',
+            1 => 'color: #000099;',
+            2 => 'color: #660066;'
+            ),
+        'SCRIPT' => array(
+            0 => ''
+            )
+        ),
+    'URLS' => array(
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        //Section names
+        0 => '\[.+\]',
+        //Entry names
+        1 => array(
+            GESHI_SEARCH => '^(\s*)([a-zA-Z0-9_\-]+)(\s*=)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 'm',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => '\\3'
+            ),
+        //Entry values
+        2 => array(
+            // Evil hackery to get around GeSHi bug: <>" and ; are added so <span>s can be matched
+            // Explicit match on variable names because if a comment is before the first < of the span
+            // gets chewed up...
+            GESHI_SEARCH => '([<>";a-zA-Z0-9_]+\s*)=(.*)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '\\1=',
+            GESHI_AFTER => ''
+            )
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/inno.php b/examples/includes/geshi/geshi/inno.php
new file mode 100644 (file)
index 0000000..5cead10
--- /dev/null
@@ -0,0 +1,212 @@
+<?php
+/*************************************************************************************
+ * Inno.php
+ * ----------
+ * Author: Thomas Klingler (hotline@theratech.de) based on delphi.php from J�rja Norbert (jnorbi@vipmail.hu)
+ * Copyright: (c) 2004 J�rja Norbert, Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2005/07/29
+ *
+ * Inno Script language inkl. Delphi (Object Pascal) language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2005/09/03
+ *   -  First Release
+ *
+ * TODO (updated 2005/07/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *   This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Inno',
+    'COMMENT_SINGLE' => array(1 => '//'),
+    'COMMENT_MULTI' => array('(*' => '*)'),
+    'CASE_KEYWORDS' => 0,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            'Setup','Types','Components','Tasks','Dirs','Files','Icons','INI',
+            'InstallDelete','Languages','Messages','CustomMessage',
+            'LangOptions','Registry','RUN','UninstallDelete','UninstallRun',
+            'app','win','sys','syswow64','src','sd','pf','pf32','pf64','cf',
+            'cf32','cf64','tmp','fonts','dao','group','localappdata','sendto',
+            'userappdata','commonappdata','userdesktop','commondesktop',
+            'userdocs','commondocs','userfavorites','commonfavorites',
+            'userprograms','commonprograms','userstartmenu','commonstartmenu',
+            'userstartup','commonstartup','usertemplates','commontemplates'
+            ),
+        2 => array(
+            'nil', 'false', 'true', 'var', 'type', 'const','And', 'Array', 'As', 'Begin', 'Case', 'Class', 'Constructor', 'Destructor', 'Div', 'Do', 'DownTo', 'Else',
+            'End', 'Except', 'File', 'Finally', 'For', 'Function', 'Goto', 'If', 'Implementation', 'In', 'Inherited', 'Interface',
+            'Is', 'Mod', 'Not', 'Object', 'Of', 'On', 'Or', 'Packed', 'Procedure', 'Property', 'Raise', 'Record',
+            'Repeat', 'Set', 'Shl', 'Shr', 'Then', 'ThreadVar', 'To', 'Try', 'Unit', 'Until', 'Uses', 'While', 'With', 'Xor',
+
+            'HKCC','HKCR','HKCU','HKLM','HKU','alwaysoverwrite','alwaysskipifsameorolder','append',
+            'binary','classic','closeonexit','comparetimestamp','confirmoverwrite',
+            'createkeyifdoesntexist','createonlyiffileexists','createvalueifdoesntexist',
+            'deleteafterinstall','deletekey','deletevalue','dirifempty','dontcloseonexit',
+            'dontcopy','dontcreatekey','disablenouninstallwarning','dword','exclusive','expandsz',
+            'external','files','filesandordirs','fixed','fontisnttruetype','ignoreversion','iscustom','isreadme',
+            'modern','multisz','new','noerror','none','normal','nowait','onlyifdestfileexists',
+            'onlyifdoesntexist','onlyifnewer','overwrite','overwritereadonly','postinstall',
+            'preservestringtype','promptifolder','regserver','regtypelib','restart','restartreplace',
+            'runhidden','runmaximized','runminimized','sharedfile','shellexec','showcheckbox',
+            'skipifnotsilent','skipifsilent','silent','skipifdoesntexist',
+            'skipifsourcedoesntexist','sortfilesbyextension','unchecked','uninsalwaysuninstall',
+            'uninsclearvalue','uninsdeleteentry','uninsdeletekey','uninsdeletekeyifempty',
+            'uninsdeletesection','uninsdeletesectionifempty','uninsdeletevalue',
+            'uninsneveruninstall','useapppaths','verysilent','waituntilidle'
+            ),
+        3 => array(
+            'Abs', 'Addr', 'AnsiCompareStr', 'AnsiCompareText', 'AnsiContainsStr', 'AnsiEndsStr', 'AnsiIndexStr', 'AnsiLeftStr',
+            'AnsiLowerCase', 'AnsiMatchStr', 'AnsiMidStr', 'AnsiPos', 'AnsiReplaceStr', 'AnsiReverseString', 'AnsiRightStr',
+            'AnsiStartsStr', 'AnsiUpperCase', 'ArcCos', 'ArcSin', 'ArcTan', 'Assigned', 'BeginThread', 'Bounds', 'CelsiusToFahrenheit',
+            'ChangeFileExt', 'Chr', 'CompareStr', 'CompareText', 'Concat', 'Convert', 'Copy', 'Cos', 'CreateDir', 'CurrToStr',
+            'CurrToStrF', 'Date', 'DateTimeToFileDate', 'DateTimeToStr', 'DateToStr', 'DayOfTheMonth', 'DayOfTheWeek', 'DayOfTheYear',
+            'DayOfWeek', 'DaysBetween', 'DaysInAMonth', 'DaysInAYear', 'DaySpan', 'DegToRad', 'DeleteFile', 'DiskFree', 'DiskSize',
+            'DupeString', 'EncodeDate', 'EncodeDateTime', 'EncodeTime', 'EndOfADay', 'EndOfAMonth', 'Eof', 'Eoln', 'Exp', 'ExtractFileDir',
+            'ExtractFileDrive', 'ExtractFileExt', 'ExtractFileName', 'ExtractFilePath', 'FahrenheitToCelsius', 'FileAge',
+            'FileDateToDateTime', 'FileExists', 'FilePos', 'FileSearch', 'FileSetDate', 'FileSize', 'FindClose', 'FindCmdLineSwitch',
+            'FindFirst', 'FindNext', 'FloatToStr', 'FloatToStrF', 'Format', 'FormatCurr', 'FormatDateTime', 'FormatFloat', 'Frac',
+            'GetCurrentDir', 'GetLastError', 'GetMem', 'High', 'IncDay', 'IncMinute', 'IncMonth', 'IncYear', 'InputBox',
+            'InputQuery', 'Int', 'IntToHex', 'IntToStr', 'IOResult', 'IsInfinite', 'IsLeapYear', 'IsMultiThread', 'IsNaN',
+            'LastDelimiter', 'Length', 'Ln', 'Lo', 'Log10', 'Low', 'LowerCase', 'Max', 'Mean', 'MessageDlg', 'MessageDlgPos',
+            'MonthOfTheYear', 'Now', 'Odd', 'Ord', 'ParamCount', 'ParamStr', 'Pi', 'Point', 'PointsEqual', 'Pos', 'Pred',
+            'Printer', 'PromptForFileName', 'PtInRect', 'RadToDeg', 'Random', 'RandomRange', 'RecodeDate', 'RecodeTime', 'Rect',
+            'RemoveDir', 'RenameFile', 'Round', 'SeekEof', 'SeekEoln', 'SelectDirectory', 'SetCurrentDir', 'Sin', 'SizeOf',
+            'Slice', 'Sqr', 'Sqrt', 'StringOfChar', 'StringReplace', 'StringToWideChar', 'StrToCurr', 'StrToDate', 'StrToDateTime',
+            'StrToFloat', 'StrToInt', 'StrToInt64', 'StrToInt64Def', 'StrToIntDef', 'StrToTime', 'StuffString', 'Succ', 'Sum', 'Tan',
+            'Time', 'TimeToStr', 'Tomorrow', 'Trunc', 'UpCase', 'UpperCase', 'VarType', 'WideCharToString', 'WrapText', 'Yesterday',
+            'Append', 'AppendStr', 'Assign', 'AssignFile', 'AssignPrn', 'Beep', 'BlockRead', 'BlockWrite', 'Break',
+            'ChDir', 'Close', 'CloseFile', 'Continue', 'DateTimeToString', 'Dec', 'DecodeDate', 'DecodeDateTime',
+            'DecodeTime', 'Delete', 'Dispose', 'EndThread', 'Erase', 'Exclude', 'Exit', 'FillChar', 'Flush', 'FreeAndNil',
+            'FreeMem', 'GetDir', 'GetLocaleFormatSettings', 'Halt', 'Inc', 'Include', 'Insert', 'MkDir', 'Move', 'New',
+            'ProcessPath', 'Randomize', 'Read', 'ReadLn', 'ReallocMem', 'Rename', 'ReplaceDate', 'ReplaceTime',
+            'Reset', 'ReWrite', 'RmDir', 'RunError', 'Seek', 'SetLength', 'SetString', 'ShowMessage', 'ShowMessageFmt',
+            'ShowMessagePos', 'Str', 'Truncate', 'Val', 'Write', 'WriteLn',
+
+            'AdminPrivilegesRequired','AfterInstall','AllowCancelDuringInstall','AllowNoIcons','AllowRootDirectory','AllowUNCPath','AlwaysRestart','AlwaysShowComponentsList','AlwaysShowDirOnReadyPage','AlwaysShowGroupOnReadyPage ','AlwaysUsePersonalGroup','AppComments','AppContact','AppCopyright','AppendDefaultDirName',
+            'AppendDefaultGroupName','AppId','AppModifyPath','AppMutex','AppName','AppPublisher',
+            'AppPublisherURL','AppReadmeFile','AppSupportURL','AppUpdatesURL','AppVerName','AppVersion',
+            'Attribs','BackColor','BackColor2','BackColorDirection','BackSolid','BeforeInstall',
+            'ChangesAssociations','ChangesEnvironment','Check','CodeFile','Comment','Compression','CopyMode',
+            'CreateAppDir','CreateUninstallRegKey','DefaultDirName','DefaultGroupName',
+            'DefaultUserInfoName','DefaultUserInfoOrg','DefaultUserInfoSerial',
+            'Description','DestDir','DestName','DirExistsWarning',
+            'DisableDirPage','DisableFinishedPage',
+            'DisableProgramGroupPage','DisableReadyMemo','DisableReadyPage',
+            'DisableStartupPrompt','DiskClusterSize','DiskSliceSize','DiskSpaceMBLabel',
+            'DiskSpanning','DontMergeDuplicateFiles','EnableDirDoesntExistWarning','Encryption',
+            'Excludes','ExtraDiskSpaceRequired','Filename','Flags','FlatComponentsList','FontInstall',
+            'GroupDescription','HotKey','IconFilename','IconIndex','InfoAfterFile','InfoBeforeFile',
+            'InternalCompressLevel','Key','LanguageDetectionMethod',
+            'LicenseFile','MergeDuplicateFiles','MessagesFile','MinVersion','Name',
+            'OnlyBelowVersion','OutputBaseFilename','OutputManifestFile','OutputDir',
+            'Parameters','Password','Permissions','PrivilegesRequired','ReserveBytes',
+            'RestartIfNeededByRun','Root','RunOnceId','Section','SetupIconFile',
+            'ShowComponentSizes','ShowLanguageDialog','ShowTasksTreeLines','SlicesPerDisk',
+            'SolidCompression','Source','SourceDir','StatusMsg','Subkey',
+            'TimeStampRounding','TimeStampsInUTC','TouchDate','TouchTime','Type',
+            'UninstallDisplayIcon','UninstallDisplayName','UninstallFilesDir','UninstallIconFile',
+            'UninstallLogMode','UninstallRestartComputer','UninstallStyle','Uninstallable',
+            'UpdateUninstallLogAppName','UsePreviousAppDir','UsePreviousGroup',
+            'UsePreviousTasks','UsePreviousSetupType','UsePreviousUserInfo',
+            'UserInfoPage','UseSetupLdr','ValueData','ValueName','ValueType',
+            'VersionInfoVersion','VersionInfoCompany','VersionInfoDescription','VersionInfoTextVersion',
+            'WindowResizable','WindowShowCaption','WindowStartMaximized',
+            'WindowVisible','WizardImageBackColor','WizardImageFile','WizardImageStretch','WizardSmallImageBackColor','WizardSmallImageFile','WizardStyle','WorkingDir'
+            ),
+        4 => array(
+            'AnsiChar', 'AnsiString', 'Boolean', 'Byte', 'Cardinal', 'Char', 'Comp', 'Currency', 'Double', 'Extended',
+            'Int64', 'Integer', 'LongInt', 'LongWord', 'PAnsiChar', 'PAnsiString', 'PChar', 'PCurrency', 'PDateTime',
+            'PExtended', 'PInt64', 'Pointer', 'PShortString', 'PString', 'PVariant', 'PWideChar', 'PWideString',
+            'Real', 'Real48', 'ShortInt', 'ShortString', 'Single', 'SmallInt', 'String', 'TBits', 'TConvType', 'TDateTime',
+            'Text', 'TextFile', 'TFloatFormat', 'TFormatSettings', 'TList', 'TObject', 'TOpenDialog', 'TPoint',
+            'TPrintDialog', 'TRect', 'TReplaceFlags', 'TSaveDialog', 'TSearchRec', 'TStringList', 'TSysCharSet',
+            'TThreadFunc', 'Variant', 'WideChar', 'WideString', 'Word'
+            ),
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}', '@', '%', '&', '*', '|', '/', '<', '>'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000000; font-weight: bold;',/*bold Black*/
+            2 => 'color: #000000;font-style: italic;',/*Black*/
+            3 => 'color: #0000FF;',/*blue*/
+            4 => 'color: #CC0000;'/*red*/
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #33FF00; font-style: italic;',
+            'MULTI' => 'color: #33FF00; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006600;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000000; font-weight: bold;',
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/intercal.php b/examples/includes/geshi/geshi/intercal.php
new file mode 100644 (file)
index 0000000..b4ad049
--- /dev/null
@@ -0,0 +1,122 @@
+<?php
+/*************************************************************************************
+ * intercal.php
+ * ----------
+ * Author: Benny Baumann (BenBE@geshi.org)
+ * Copyright: (c) 2008 Benny Baumann (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2009/10/31
+ *
+ * INTERCAL language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/10/31 (1.0.8.1)
+ *   -  First Release
+ *
+ * TODO
+ * ----
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+$language_data = array (
+    'LANG_NAME' => 'INTERCAL',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array(),
+    'COMMENT_REGEXP' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_UPPER,
+    'QUOTEMARKS' => array(),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        //Politeness
+        1 => array(
+            'DO', 'DOES', 'DONT', 'DON\'T', 'NOT', 'PLEASE', 'PLEASENT', 'PLEASEN\'T', 'MAYBE'
+            ),
+        //Statements
+        2 => array(
+            'STASH', 'RETRIEVE', 'NEXT', 'RESUME', 'FORGET', 'ABSTAIN', 'ABSTAINING',
+            'COME', 'FROM', 'CALCULATING', 'REINSTATE', 'IGNORE', 'REMEMBER',
+            'WRITE', 'IN', 'READ', 'OUT', 'GIVE', 'UP'
+            )
+        ),
+    'SYMBOLS' => array(
+        '.', ',', ':', ';', '#',
+        '~', '$', '&', '?',
+        '\'', '"', '<-'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000080; font-weight: bold;',
+            2 => 'color: #000080; font-weight: bold;'
+            ),
+        'COMMENTS' => array(
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'ESCAPE_CHAR' => array(
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            1 => 'color: #808080; font-style: italic;'
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        1 => '^\(\d+\)'
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4,
+    'PARSER_CONTROL' => array(
+        'ENABLE_FLAGS' => array(
+            'COMMENTS' => GESHI_NEVER,
+            'STRINGS' => GESHI_NEVER,
+            'NUMBERS' => GESHI_NEVER
+            )
+        )
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/io.php b/examples/includes/geshi/geshi/io.php
new file mode 100644 (file)
index 0000000..e9117ab
--- /dev/null
@@ -0,0 +1,138 @@
+<?php
+/*************************************************************************************
+ * io.php
+ * -------
+ * Author: Nigel McNie (nigel@geshi.org)
+ * Copyright: (c) 2006 Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2006/09/23
+ *
+ * Io language file for GeSHi. Thanks to Johnathan Wright for the suggestion and help
+ * with this language :)
+ *
+ * CHANGES
+ * -------
+ * 2006/09/23(1.0.0)
+ *  -  First Release
+ *
+ * TODO
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Io',
+    'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'and', 'break', 'else', 'elseif', 'exit', 'for', 'foreach', 'if', 'ifFalse', 'ifNil',
+            'ifTrue', 'or', 'pass', 'raise', 'return', 'then', 'try', 'wait', 'while', 'yield'
+            ),
+        2 => array(
+            'activate', 'activeCoroCount', 'asString', 'block', 'catch', 'clone', 'collectGarbage',
+            'compileString', 'continue', 'do', 'doFile', 'doMessage', 'doString', 'forward',
+            'getSlot', 'getenv', 'hasSlot', 'isActive', 'isNil', 'isResumable', 'list', 'message',
+            'method', 'parent', 'pause', 'perform', 'performWithArgList', 'print', 'proto',
+            'raiseResumable', 'removeSlot', 'resend', 'resume', 'schedulerSleepSeconds', 'self',
+            'sender', 'setSchedulerSleepSeconds', 'setSlot', 'shallowCopy', 'slotNames', 'super',
+            'system', 'thisBlock', 'thisContext', 'thisMessage', 'type', 'uniqueId', 'updateSlot',
+            'write'
+            ),
+        3 => array(
+            'Array', 'AudioDevice', 'AudioMixer', 'Block', 'Box', 'Buffer', 'CFunction', 'CGI',
+            'Color', 'Curses', 'DBM', 'DNSResolver', 'DOConnection', 'DOProxy', 'DOServer',
+            'Date', 'Directory', 'Duration', 'DynLib', 'Error', 'Exception', 'FFT', 'File',
+            'Fnmatch', 'Font', 'Future', 'GL', 'GLE', 'GLScissor', 'GLU', 'GLUCylinder',
+            'GLUQuadric', 'GLUSphere', 'GLUT', 'Host', 'Image', 'Importer', 'LinkList', 'List',
+            'Lobby', 'Locals', 'MD5', 'MP3Decoder', 'MP3Encoder', 'Map', 'Message', 'Movie',
+            'NULL', 'Nil', 'Nop', 'Notifiction', 'Number', 'Object', 'OpenGL', 'Point', 'Protos',
+            'Regex', 'SGMLTag', 'SQLite', 'Server', 'ShowMessage', 'SleepyCat', 'SleepyCatCursor',
+            'Socket', 'SocketManager', 'Sound', 'Soup', 'Store', 'String', 'Tree', 'UDPSender',
+            'UDPReceiver', 'URL', 'User', 'Warning', 'WeakLink'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}', '!', '@', '%', '&', '*', '|', '/', '<', '>'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #000066;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            2 => 'color: #808080; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006600;',
+            2 => 'color: #006600;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            0 => ''
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/java.php b/examples/includes/geshi/geshi/java.php
new file mode 100644 (file)
index 0000000..7e5dc08
--- /dev/null
@@ -0,0 +1,983 @@
+<?php
+/*************************************************************************************
+ * java.php
+ * --------
+ * Author: Nigel McNie (nigel@geshi.org)
+ * Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/07/10
+ *
+ * Java language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/25 (1.0.7.22)
+ *   -  Added highlighting of import and package directives as non-OOP
+ * 2005/12/28 (1.0.4)
+ *   -  Added instanceof keyword
+ * 2004/11/27 (1.0.3)
+ *   -  Added support for multiple object splitters
+ * 2004/08/05 (1.0.2)
+ *   -  Added URL support
+ *   -  Added keyword "this", as bugs in GeSHi class ironed out
+ * 2004/08/05 (1.0.1)
+ *   -  Added support for symbols
+ *   -  Added extra missed keywords
+ * 2004/07/14 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ * * Compact the class names like the first few have been
+ *   and eliminate repeats
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Java',
+    'COMMENT_SINGLE' => array(1 => '//'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'COMMENT_REGEXP' => array(
+        //Import and Package directives (Basic Support only)
+        2 => '/(?:(?<=import[\\n\\s])|(?<=package[\\n\\s]))[\\n\\s]*([a-zA-Z0-9_]+\\.)*([a-zA-Z0-9_]+|\*)(?=[\n\s;])/i',
+        // javadoc comments
+        3 => '#/\*\*(?![\*\/]).*\*/#sU'
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'for', 'foreach', 'if', 'else', 'while', 'do',
+            'switch', 'case',  'return', 'public',
+            'private', 'protected', 'extends', 'break', 'class',
+            'new', 'try', 'catch', 'throws', 'finally', 'implements',
+            'interface', 'throw', 'final', 'native', 'synchronized', 'this',
+            'abstract', 'transient', 'instanceof', 'assert', 'continue',
+            'default', 'enum', 'package', 'static', 'strictfp', 'super',
+            'volatile', 'const', 'goto', 'import'
+            ),
+        2 => array(
+            'null', 'false', 'true'
+            ),
+        3 => array(
+            'AbstractAction', 'AbstractBorder', 'AbstractButton',
+            'AbstractCellEditor', 'AbstractCollection',
+            'AbstractColorChooserPanel', 'AbstractDocument',
+            'AbstractDocument.AttributeContext',
+            'AbstractDocument.Content',
+            'AbstractDocument.ElementEdit',
+            'AbstractLayoutCache',
+            'AbstractLayoutCache.NodeDimensions', 'AbstractList',
+            'AbstractListModel', 'AbstractMap',
+            'AbstractMethodError', 'AbstractSequentialList',
+            'AbstractSet', 'AbstractTableModel',
+            'AbstractUndoableEdit', 'AbstractWriter',
+            'AccessControlContext', 'AccessControlException',
+            'AccessController', 'AccessException', 'Accessible',
+            'AccessibleAction', 'AccessibleBundle',
+            'AccessibleComponent', 'AccessibleContext',
+            'AccessibleHyperlink', 'AccessibleHypertext',
+            'AccessibleIcon', 'AccessibleObject',
+            'AccessibleRelation', 'AccessibleRelationSet',
+            'AccessibleResourceBundle', 'AccessibleRole',
+            'AccessibleSelection', 'AccessibleState',
+            'AccessibleStateSet', 'AccessibleTable',
+            'AccessibleTableModelChange', 'AccessibleText',
+            'AccessibleValue', 'Acl', 'AclEntry',
+            'AclNotFoundException', 'Action', 'ActionEvent',
+            'ActionListener', 'ActionMap', 'ActionMapUIResource',
+            'Activatable', 'ActivateFailedException',
+            'ActivationDesc', 'ActivationException',
+            'ActivationGroup', 'ActivationGroupDesc',
+            'ActivationGroupDesc.CommandEnvironment',
+            'ActivationGroupID', 'ActivationID',
+            'ActivationInstantiator', 'ActivationMonitor',
+            'ActivationSystem', 'Activator', 'ActiveEvent',
+            'Adjustable', 'AdjustmentEvent',
+            'AdjustmentListener', 'Adler32', 'AffineTransform',
+            'AffineTransformOp', 'AlgorithmParameterGenerator',
+            'AlgorithmParameterGeneratorSpi',
+            'AlgorithmParameters', 'AlgorithmParameterSpec',
+            'AlgorithmParametersSpi', 'AllPermission',
+            'AlphaComposite', 'AlreadyBound',
+            'AlreadyBoundException', 'AlreadyBoundHelper',
+            'AlreadyBoundHolder', 'AncestorEvent',
+            'AncestorListener', 'Annotation', 'Any', 'AnyHolder',
+            'AnySeqHelper', 'AnySeqHolder', 'Applet',
+            'AppletContext', 'AppletInitializer', 'AppletStub',
+            'ApplicationException', 'Arc2D', 'Arc2D.Double',
+            'Arc2D.Float', 'Area', 'AreaAveragingScaleFilter',
+            'ARG_IN', 'ARG_INOUT', 'ARG_OUT',
+            'ArithmeticException', 'Array',
+            'ArrayIndexOutOfBoundsException', 'ArrayList',
+            'Arrays', 'ArrayStoreException', 'AsyncBoxView',
+            'Attribute', 'AttributedCharacterIterator',
+            'AttributedCharacterIterator.Attribute',
+            'AttributedString', 'AttributeInUseException',
+            'AttributeList', 'AttributeModificationException',
+            'Attributes', 'Attributes.Name', 'AttributeSet',
+            'AttributeSet.CharacterAttribute',
+            'AttributeSet.ColorAttribute',
+            'AttributeSet.FontAttribute',
+            'AttributeSet.ParagraphAttribute', 'AudioClip',
+            'AudioFileFormat', 'AudioFileFormat.Type',
+            'AudioFileReader', 'AudioFileWriter', 'AudioFormat',
+            'AudioFormat.Encoding', 'AudioInputStream',
+            'AudioPermission', 'AudioSystem',
+            'AuthenticationException',
+            'AuthenticationNotSupportedException',
+            'Authenticator', 'Autoscroll', 'AWTError',
+            'AWTEvent', 'AWTEventListener',
+            'AWTEventMulticaster', 'AWTException',
+            'AWTPermission', 'BadKind', 'BadLocationException',
+            'BAD_CONTEXT', 'BAD_INV_ORDER', 'BAD_OPERATION',
+            'BAD_PARAM', 'BAD_POLICY', 'BAD_POLICY_TYPE',
+            'BAD_POLICY_VALUE', 'BAD_TYPECODE', 'BandCombineOp',
+            'BandedSampleModel', 'BasicArrowButton',
+            'BasicAttribute', 'BasicAttributes', 'BasicBorders',
+            'BasicBorders.ButtonBorder',
+            'BasicBorders.FieldBorder',
+            'BasicBorders.MarginBorder',
+            'BasicBorders.MenuBarBorder',
+            'BasicBorders.RadioButtonBorder',
+            'BasicBorders.SplitPaneBorder',
+            'BasicBorders.ToggleButtonBorder',
+            'BasicButtonListener', 'BasicButtonUI',
+            'BasicCheckBoxMenuItemUI', 'BasicCheckBoxUI',
+            'BasicColorChooserUI', 'BasicComboBoxEditor',
+            'BasicComboBoxEditor.UIResource',
+            'BasicComboBoxRenderer',
+            'BasicComboBoxRenderer.UIResource',
+            'BasicComboBoxUI', 'BasicComboPopup',
+            'BasicDesktopIconUI', 'BasicDesktopPaneUI',
+            'BasicDirectoryModel', 'BasicEditorPaneUI',
+            'BasicFileChooserUI', 'BasicGraphicsUtils',
+            'BasicHTML', 'BasicIconFactory',
+            'BasicInternalFrameTitlePane',
+            'BasicInternalFrameUI', 'BasicLabelUI',
+            'BasicListUI', 'BasicLookAndFeel', 'BasicMenuBarUI',
+            'BasicMenuItemUI', 'BasicMenuUI',
+            'BasicOptionPaneUI',
+            'BasicOptionPaneUI.ButtonAreaLayout', 'BasicPanelUI',
+            'BasicPasswordFieldUI', 'BasicPermission',
+            'BasicPopupMenuSeparatorUI', 'BasicPopupMenuUI',
+            'BasicProgressBarUI', 'BasicRadioButtonMenuItemUI',
+            'BasicRadioButtonUI', 'BasicRootPaneUI',
+            'BasicScrollBarUI', 'BasicScrollPaneUI',
+            'BasicSeparatorUI', 'BasicSliderUI',
+            'BasicSplitPaneDivider', 'BasicSplitPaneUI',
+            'BasicStroke', 'BasicTabbedPaneUI',
+            'BasicTableHeaderUI', 'BasicTableUI',
+            'BasicTextAreaUI', 'BasicTextFieldUI',
+            'BasicTextPaneUI', 'BasicTextUI',
+            'BasicTextUI.BasicCaret',
+            'BasicTextUI.BasicHighlighter',
+            'BasicToggleButtonUI', 'BasicToolBarSeparatorUI',
+            'BasicToolBarUI', 'BasicToolTipUI', 'BasicTreeUI',
+            'BasicViewportUI', 'BatchUpdateException',
+            'BeanContext', 'BeanContextChild',
+            'BeanContextChildComponentProxy',
+            'BeanContextChildSupport',
+            'BeanContextContainerProxy', 'BeanContextEvent',
+            'BeanContextMembershipEvent',
+            'BeanContextMembershipListener', 'BeanContextProxy',
+            'BeanContextServiceAvailableEvent',
+            'BeanContextServiceProvider',
+            'BeanContextServiceProviderBeanInfo',
+            'BeanContextServiceRevokedEvent',
+            'BeanContextServiceRevokedListener',
+            'BeanContextServices', 'BeanContextServicesListener',
+            'BeanContextServicesSupport',
+            'BeanContextServicesSupport.BCSSServiceProvider',
+            'BeanContextSupport',
+            'BeanContextSupport.BCSIterator', 'BeanDescriptor',
+            'BeanInfo', 'Beans', 'BevelBorder', 'BigDecimal',
+            'BigInteger', 'BinaryRefAddr', 'BindException',
+            'Binding', 'BindingHelper', 'BindingHolder',
+            'BindingIterator', 'BindingIteratorHelper',
+            'BindingIteratorHolder', 'BindingIteratorOperations',
+            'BindingListHelper', 'BindingListHolder',
+            'BindingType', 'BindingTypeHelper',
+            'BindingTypeHolder', 'BitSet', 'Blob', 'BlockView',
+            'Book', 'Boolean', 'BooleanControl',
+            'BooleanControl.Type', 'BooleanHolder',
+            'BooleanSeqHelper', 'BooleanSeqHolder', 'Border',
+            'BorderFactory', 'BorderLayout', 'BorderUIResource',
+            'BorderUIResource.BevelBorderUIResource',
+            'BorderUIResource.CompoundBorderUIResource',
+            'BorderUIResource.EmptyBorderUIResource',
+            'BorderUIResource.EtchedBorderUIResource',
+            'BorderUIResource.LineBorderUIResource',
+            'BorderUIResource.MatteBorderUIResource',
+            'BorderUIResource.TitledBorderUIResource',
+            'BoundedRangeModel', 'Bounds', 'Box', 'Box.Filler',
+            'BoxedValueHelper', 'BoxLayout', 'BoxView',
+            'BreakIterator', 'BufferedImage',
+            'BufferedImageFilter', 'BufferedImageOp',
+            'BufferedInputStream', 'BufferedOutputStream',
+            'BufferedReader', 'BufferedWriter', 'Button',
+            'ButtonGroup', 'ButtonModel', 'ButtonUI', 'Byte',
+            'ByteArrayInputStream', 'ByteArrayOutputStream',
+            'ByteHolder', 'ByteLookupTable', 'Calendar',
+            'CallableStatement', 'CannotProceed',
+            'CannotProceedException', 'CannotProceedHelper',
+            'CannotProceedHolder', 'CannotRedoException',
+            'CannotUndoException', 'Canvas', 'CardLayout',
+            'Caret', 'CaretEvent', 'CaretListener', 'CellEditor',
+            'CellEditorListener', 'CellRendererPane',
+            'Certificate', 'Certificate.CertificateRep',
+            'CertificateEncodingException',
+            'CertificateException',
+            'CertificateExpiredException', 'CertificateFactory',
+            'CertificateFactorySpi',
+            'CertificateNotYetValidException',
+            'CertificateParsingException',
+            'ChangedCharSetException', 'ChangeEvent',
+            'ChangeListener', 'Character', 'Character.Subset',
+            'Character.UnicodeBlock', 'CharacterIterator',
+            'CharArrayReader', 'CharArrayWriter',
+            'CharConversionException', 'CharHolder',
+            'CharSeqHelper', 'CharSeqHolder', 'Checkbox',
+            'CheckboxGroup', 'CheckboxMenuItem',
+            'CheckedInputStream', 'CheckedOutputStream',
+            'Checksum', 'Choice', 'ChoiceFormat', 'Class',
+            'ClassCastException', 'ClassCircularityError',
+            'ClassDesc', 'ClassFormatError', 'ClassLoader',
+            'ClassNotFoundException', 'Clip', 'Clipboard',
+            'ClipboardOwner', 'Clob', 'Cloneable',
+            'CloneNotSupportedException', 'CMMException',
+            'CodeSource', 'CollationElementIterator',
+            'CollationKey', 'Collator', 'Collection',
+            'Collections', 'Color',
+            'ColorChooserComponentFactory', 'ColorChooserUI',
+            'ColorConvertOp', 'ColorModel',
+            'ColorSelectionModel', 'ColorSpace',
+            'ColorUIResource', 'ComboBoxEditor', 'ComboBoxModel',
+            'ComboBoxUI', 'ComboPopup', 'CommunicationException',
+            'COMM_FAILURE', 'Comparable', 'Comparator',
+            'Compiler', 'CompletionStatus',
+            'CompletionStatusHelper', 'Component',
+            'ComponentAdapter', 'ComponentColorModel',
+            'ComponentEvent', 'ComponentInputMap',
+            'ComponentInputMapUIResource', 'ComponentListener',
+            'ComponentOrientation', 'ComponentSampleModel',
+            'ComponentUI', 'ComponentView', 'Composite',
+            'CompositeContext', 'CompositeName', 'CompositeView',
+            'CompoundBorder', 'CompoundControl',
+            'CompoundControl.Type', 'CompoundEdit',
+            'CompoundName', 'ConcurrentModificationException',
+            'ConfigurationException', 'ConnectException',
+            'ConnectIOException', 'Connection', 'Constructor', 'Container',
+            'ContainerAdapter', 'ContainerEvent',
+            'ContainerListener', 'ContentHandler',
+            'ContentHandlerFactory', 'ContentModel', 'Context',
+            'ContextList', 'ContextNotEmptyException',
+            'ContextualRenderedImageFactory', 'Control',
+            'Control.Type', 'ControlFactory',
+            'ControllerEventListener', 'ConvolveOp', 'CRC32',
+            'CRL', 'CRLException', 'CropImageFilter', 'CSS',
+            'CSS.Attribute', 'CTX_RESTRICT_SCOPE',
+            'CubicCurve2D', 'CubicCurve2D.Double',
+            'CubicCurve2D.Float', 'Current', 'CurrentHelper',
+            'CurrentHolder', 'CurrentOperations', 'Cursor',
+            'Customizer', 'CustomMarshal', 'CustomValue',
+            'DatabaseMetaData', 'DataBuffer', 'DataBufferByte',
+            'DataBufferInt', 'DataBufferShort',
+            'DataBufferUShort', 'DataFlavor',
+            'DataFormatException', 'DatagramPacket',
+            'DatagramSocket', 'DatagramSocketImpl',
+            'DatagramSocketImplFactory', 'DataInput',
+            'DataInputStream', 'DataLine', 'DataLine.Info',
+            'DataOutput', 'DataOutputStream',
+            'DataTruncation', 'DATA_CONVERSION', 'Date',
+            'DateFormat', 'DateFormatSymbols', 'DebugGraphics',
+            'DecimalFormat', 'DecimalFormatSymbols',
+            'DefaultBoundedRangeModel', 'DefaultButtonModel',
+            'DefaultCaret', 'DefaultCellEditor',
+            'DefaultColorSelectionModel', 'DefaultComboBoxModel',
+            'DefaultDesktopManager', 'DefaultEditorKit',
+            'DefaultEditorKit.BeepAction',
+            'DefaultEditorKit.CopyAction',
+            'DefaultEditorKit.CutAction',
+            'DefaultEditorKit.DefaultKeyTypedAction',
+            'DefaultEditorKit.InsertBreakAction',
+            'DefaultEditorKit.InsertContentAction',
+            'DefaultEditorKit.InsertTabAction',
+            'DefaultEditorKit.PasteAction,',
+            'DefaultFocusManager', 'DefaultHighlighter',
+            'DefaultHighlighter.DefaultHighlightPainter',
+            'DefaultListCellRenderer',
+            'DefaultListCellRenderer.UIResource',
+            'DefaultListModel', 'DefaultListSelectionModel',
+            'DefaultMenuLayout', 'DefaultMetalTheme',
+            'DefaultMutableTreeNode',
+            'DefaultSingleSelectionModel',
+            'DefaultStyledDocument',
+            'DefaultStyledDocument.AttributeUndoableEdit',
+            'DefaultStyledDocument.ElementSpec',
+            'DefaultTableCellRenderer',
+            'DefaultTableCellRenderer.UIResource',
+            'DefaultTableColumnModel', 'DefaultTableModel',
+            'DefaultTextUI', 'DefaultTreeCellEditor',
+            'DefaultTreeCellRenderer', 'DefaultTreeModel',
+            'DefaultTreeSelectionModel', 'DefinitionKind',
+            'DefinitionKindHelper', 'Deflater',
+            'DeflaterOutputStream', 'Delegate', 'DesignMode',
+            'DesktopIconUI', 'DesktopManager', 'DesktopPaneUI',
+            'DGC', 'Dialog', 'Dictionary', 'DigestException',
+            'DigestInputStream', 'DigestOutputStream',
+            'Dimension', 'Dimension2D', 'DimensionUIResource',
+            'DirContext', 'DirectColorModel', 'DirectoryManager',
+            'DirObjectFactory', 'DirStateFactory',
+            'DirStateFactory.Result', 'DnDConstants', 'Document',
+            'DocumentEvent', 'DocumentEvent.ElementChange',
+            'DocumentEvent.EventType', 'DocumentListener',
+            'DocumentParser', 'DomainCombiner', 'DomainManager',
+            'DomainManagerOperations', 'Double', 'DoubleHolder',
+            'DoubleSeqHelper', 'DoubleSeqHolder',
+            'DragGestureEvent', 'DragGestureListener',
+            'DragGestureRecognizer', 'DragSource',
+            'DragSourceContext', 'DragSourceDragEvent',
+            'DragSourceDropEvent', 'DragSourceEvent',
+            'DragSourceListener', 'Driver', 'DriverManager',
+            'DriverPropertyInfo', 'DropTarget',
+            'DropTarget.DropTargetAutoScroller',
+            'DropTargetContext', 'DropTargetDragEvent',
+            'DropTargetDropEvent', 'DropTargetEvent',
+            'DropTargetListener', 'DSAKey',
+            'DSAKeyPairGenerator', 'DSAParameterSpec',
+            'DSAParams', 'DSAPrivateKey', 'DSAPrivateKeySpec',
+            'DSAPublicKey', 'DSAPublicKeySpec', 'DTD',
+            'DTDConstants', 'DynamicImplementation', 'DynAny',
+            'DynArray', 'DynEnum', 'DynFixed', 'DynSequence',
+            'DynStruct', 'DynUnion', 'DynValue', 'EditorKit',
+            'Element', 'ElementIterator', 'Ellipse2D',
+            'Ellipse2D.Double', 'Ellipse2D.Float', 'EmptyBorder',
+            'EmptyStackException', 'EncodedKeySpec', 'Entity',
+            'EnumControl', 'EnumControl.Type', 'Enumeration',
+            'Environment', 'EOFException', 'Error',
+            'EtchedBorder', 'Event', 'EventContext',
+            'EventDirContext', 'EventListener',
+            'EventListenerList', 'EventObject', 'EventQueue',
+            'EventSetDescriptor', 'Exception',
+            'ExceptionInInitializerError', 'ExceptionList',
+            'ExpandVetoException', 'ExportException',
+            'ExtendedRequest', 'ExtendedResponse',
+            'Externalizable', 'FeatureDescriptor', 'Field',
+            'FieldNameHelper', 'FieldPosition', 'FieldView',
+            'File', 'FileChooserUI', 'FileDescriptor',
+            'FileDialog', 'FileFilter',
+            'FileInputStream', 'FilenameFilter', 'FileNameMap',
+            'FileNotFoundException', 'FileOutputStream',
+            'FilePermission', 'FileReader', 'FileSystemView',
+            'FileView', 'FileWriter', 'FilteredImageSource',
+            'FilterInputStream', 'FilterOutputStream',
+            'FilterReader', 'FilterWriter',
+            'FixedHeightLayoutCache', 'FixedHolder',
+            'FlatteningPathIterator', 'FlavorMap', 'Float',
+            'FloatControl', 'FloatControl.Type', 'FloatHolder',
+            'FloatSeqHelper', 'FloatSeqHolder', 'FlowLayout',
+            'FlowView', 'FlowView.FlowStrategy', 'FocusAdapter',
+            'FocusEvent', 'FocusListener', 'FocusManager',
+            'Font', 'FontFormatException', 'FontMetrics',
+            'FontRenderContext', 'FontUIResource', 'Format',
+            'FormatConversionProvider', 'FormView', 'Frame',
+            'FREE_MEM', 'GapContent', 'GeneralPath',
+            'GeneralSecurityException', 'GlyphJustificationInfo',
+            'GlyphMetrics', 'GlyphVector', 'GlyphView',
+            'GlyphView.GlyphPainter', 'GradientPaint',
+            'GraphicAttribute', 'Graphics', 'Graphics2D',
+            'GraphicsConfigTemplate', 'GraphicsConfiguration',
+            'GraphicsDevice', 'GraphicsEnvironment',
+            'GrayFilter', 'GregorianCalendar',
+            'GridBagConstraints', 'GridBagLayout', 'GridLayout',
+            'Group', 'Guard', 'GuardedObject', 'GZIPInputStream',
+            'GZIPOutputStream', 'HasControls', 'HashMap',
+            'HashSet', 'Hashtable', 'HierarchyBoundsAdapter',
+            'HierarchyBoundsListener', 'HierarchyEvent',
+            'HierarchyListener', 'Highlighter',
+            'Highlighter.Highlight',
+            'Highlighter.HighlightPainter', 'HTML',
+            'HTML.Attribute', 'HTML.Tag', 'HTML.UnknownTag',
+            'HTMLDocument', 'HTMLDocument.Iterator',
+            'HTMLEditorKit', 'HTMLEditorKit.HTMLFactory',
+            'HTMLEditorKit.HTMLTextAction',
+            'HTMLEditorKit.InsertHTMLTextAction',
+            'HTMLEditorKit.LinkController',
+            'HTMLEditorKit.Parser',
+            'HTMLEditorKit.ParserCallback',
+            'HTMLFrameHyperlinkEvent', 'HTMLWriter',
+            'HttpURLConnection', 'HyperlinkEvent',
+            'HyperlinkEvent.EventType', 'HyperlinkListener',
+            'ICC_ColorSpace', 'ICC_Profile', 'ICC_ProfileGray',
+            'ICC_ProfileRGB', 'Icon', 'IconUIResource',
+            'IconView', 'IdentifierHelper', 'Identity',
+            'IdentityScope', 'IDLEntity', 'IDLType',
+            'IDLTypeHelper', 'IDLTypeOperations',
+            'IllegalAccessError', 'IllegalAccessException',
+            'IllegalArgumentException',
+            'IllegalComponentStateException',
+            'IllegalMonitorStateException',
+            'IllegalPathStateException', 'IllegalStateException',
+            'IllegalThreadStateException', 'Image',
+            'ImageConsumer', 'ImageFilter',
+            'ImageGraphicAttribute', 'ImageIcon',
+            'ImageObserver', 'ImageProducer',
+            'ImagingOpException', 'IMP_LIMIT',
+            'IncompatibleClassChangeError',
+            'InconsistentTypeCode', 'IndexColorModel',
+            'IndexedPropertyDescriptor',
+            'IndexOutOfBoundsException', 'IndirectionException',
+            'InetAddress', 'Inflater', 'InflaterInputStream',
+            'InheritableThreadLocal', 'InitialContext',
+            'InitialContextFactory',
+            'InitialContextFactoryBuilder', 'InitialDirContext',
+            'INITIALIZE', 'Initializer', 'InitialLdapContext',
+            'InlineView', 'InputContext', 'InputEvent',
+            'InputMap', 'InputMapUIResource', 'InputMethod',
+            'InputMethodContext', 'InputMethodDescriptor',
+            'InputMethodEvent', 'InputMethodHighlight',
+            'InputMethodListener', 'InputMethodRequests',
+            'InputStream',
+            'InputStreamReader', 'InputSubset', 'InputVerifier',
+            'Insets', 'InsetsUIResource', 'InstantiationError',
+            'InstantiationException', 'Instrument',
+            'InsufficientResourcesException', 'Integer',
+            'INTERNAL', 'InternalError', 'InternalFrameAdapter',
+            'InternalFrameEvent', 'InternalFrameListener',
+            'InternalFrameUI', 'InterruptedException',
+            'InterruptedIOException',
+            'InterruptedNamingException', 'INTF_REPOS',
+            'IntHolder', 'IntrospectionException',
+            'Introspector', 'Invalid',
+            'InvalidAlgorithmParameterException',
+            'InvalidAttributeIdentifierException',
+            'InvalidAttributesException',
+            'InvalidAttributeValueException',
+            'InvalidClassException',
+            'InvalidDnDOperationException',
+            'InvalidKeyException', 'InvalidKeySpecException',
+            'InvalidMidiDataException', 'InvalidName',
+            'InvalidNameException',
+            'InvalidNameHelper', 'InvalidNameHolder',
+            'InvalidObjectException',
+            'InvalidParameterException',
+            'InvalidParameterSpecException',
+            'InvalidSearchControlsException',
+            'InvalidSearchFilterException', 'InvalidSeq',
+            'InvalidTransactionException', 'InvalidValue',
+            'INVALID_TRANSACTION', 'InvocationEvent',
+            'InvocationHandler', 'InvocationTargetException',
+            'InvokeHandler', 'INV_FLAG', 'INV_IDENT',
+            'INV_OBJREF', 'INV_POLICY', 'IOException',
+            'IRObject', 'IRObjectOperations', 'IstringHelper',
+            'ItemEvent', 'ItemListener', 'ItemSelectable',
+            'Iterator', 'JApplet', 'JarEntry', 'JarException',
+            'JarFile', 'JarInputStream', 'JarOutputStream',
+            'JarURLConnection', 'JButton', 'JCheckBox',
+            'JCheckBoxMenuItem', 'JColorChooser', 'JComboBox',
+            'JComboBox.KeySelectionManager', 'JComponent',
+            'JDesktopPane', 'JDialog', 'JEditorPane',
+            'JFileChooser', 'JFrame', 'JInternalFrame',
+            'JInternalFrame.JDesktopIcon', 'JLabel',
+            'JLayeredPane', 'JList', 'JMenu', 'JMenuBar',
+            'JMenuItem', 'JobAttributes',
+            'JobAttributes.DefaultSelectionType',
+            'JobAttributes.DestinationType',
+            'JobAttributes.DialogType',
+            'JobAttributes.MultipleDocumentHandlingType',
+            'JobAttributes.SidesType', 'JOptionPane', 'JPanel',
+            'JPasswordField', 'JPopupMenu',
+            'JPopupMenu.Separator', 'JProgressBar',
+            'JRadioButton', 'JRadioButtonMenuItem', 'JRootPane',
+            'JScrollBar', 'JScrollPane', 'JSeparator', 'JSlider',
+            'JSplitPane', 'JTabbedPane', 'JTable',
+            'JTableHeader', 'JTextArea', 'JTextComponent',
+            'JTextComponent.KeyBinding', 'JTextField',
+            'JTextPane', 'JToggleButton',
+            'JToggleButton.ToggleButtonModel', 'JToolBar',
+            'JToolBar.Separator', 'JToolTip', 'JTree',
+            'JTree.DynamicUtilTreeNode',
+            'JTree.EmptySelectionModel', 'JViewport', 'JWindow',
+            'Kernel', 'Key', 'KeyAdapter', 'KeyEvent',
+            'KeyException', 'KeyFactory', 'KeyFactorySpi',
+            'KeyListener', 'KeyManagementException', 'Keymap',
+            'KeyPair', 'KeyPairGenerator', 'KeyPairGeneratorSpi',
+            'KeySpec', 'KeyStore', 'KeyStoreException',
+            'KeyStoreSpi', 'KeyStroke', 'Label', 'LabelUI',
+            'LabelView', 'LastOwnerException',
+            'LayeredHighlighter',
+            'LayeredHighlighter.LayerPainter', 'LayoutManager',
+            'LayoutManager2', 'LayoutQueue', 'LdapContext',
+            'LdapReferralException', 'Lease',
+            'LimitExceededException', 'Line', 'Line.Info',
+            'Line2D', 'Line2D.Double', 'Line2D.Float',
+            'LineBorder', 'LineBreakMeasurer', 'LineEvent',
+            'LineEvent.Type', 'LineListener', 'LineMetrics',
+            'LineNumberInputStream', 'LineNumberReader',
+            'LineUnavailableException', 'LinkageError',
+            'LinkedList', 'LinkException', 'LinkLoopException',
+            'LinkRef', 'List', 'ListCellRenderer',
+            'ListDataEvent', 'ListDataListener', 'ListIterator',
+            'ListModel', 'ListResourceBundle',
+            'ListSelectionEvent', 'ListSelectionListener',
+            'ListSelectionModel', 'ListUI', 'ListView',
+            'LoaderHandler', 'Locale', 'LocateRegistry',
+            'LogStream', 'Long', 'LongHolder',
+            'LongLongSeqHelper', 'LongLongSeqHolder',
+            'LongSeqHelper', 'LongSeqHolder', 'LookAndFeel',
+            'LookupOp', 'LookupTable', 'MalformedLinkException',
+            'MalformedURLException', 'Manifest', 'Map',
+            'Map.Entry', 'MARSHAL', 'MarshalException',
+            'MarshalledObject', 'Math', 'MatteBorder',
+            'MediaTracker', 'Member', 'MemoryImageSource',
+            'Menu', 'MenuBar', 'MenuBarUI', 'MenuComponent',
+            'MenuContainer', 'MenuDragMouseEvent',
+            'MenuDragMouseListener', 'MenuElement', 'MenuEvent',
+            'MenuItem', 'MenuItemUI', 'MenuKeyEvent',
+            'MenuKeyListener', 'MenuListener',
+            'MenuSelectionManager', 'MenuShortcut',
+            'MessageDigest', 'MessageDigestSpi', 'MessageFormat',
+            'MetaEventListener', 'MetalBorders',
+            'MetalBorders.ButtonBorder',
+            'MetalBorders.Flush3DBorder',
+            'MetalBorders.InternalFrameBorder',
+            'MetalBorders.MenuBarBorder',
+            'MetalBorders.MenuItemBorder',
+            'MetalBorders.OptionDialogBorder',
+            'MetalBorders.PaletteBorder',
+            'MetalBorders.PopupMenuBorder',
+            'MetalBorders.RolloverButtonBorder',
+            'MetalBorders.ScrollPaneBorder',
+            'MetalBorders.TableHeaderBorder',
+            'MetalBorders.TextFieldBorder',
+            'MetalBorders.ToggleButtonBorder',
+            'MetalBorders.ToolBarBorder', 'MetalButtonUI',
+            'MetalCheckBoxIcon', 'MetalCheckBoxUI',
+            'MetalComboBoxButton', 'MetalComboBoxEditor',
+            'MetalComboBoxEditor.UIResource',
+            'MetalComboBoxIcon', 'MetalComboBoxUI',
+            'MetalDesktopIconUI', 'MetalFileChooserUI',
+            'MetalIconFactory', 'MetalIconFactory.FileIcon16',
+            'MetalIconFactory.FolderIcon16',
+            'MetalIconFactory.PaletteCloseIcon',
+            'MetalIconFactory.TreeControlIcon',
+            'MetalIconFactory.TreeFolderIcon',
+            'MetalIconFactory.TreeLeafIcon',
+            'MetalInternalFrameTitlePane',
+            'MetalInternalFrameUI', 'MetalLabelUI',
+            'MetalLookAndFeel', 'MetalPopupMenuSeparatorUI',
+            'MetalProgressBarUI', 'MetalRadioButtonUI',
+            'MetalScrollBarUI', 'MetalScrollButton',
+            'MetalScrollPaneUI', 'MetalSeparatorUI',
+            'MetalSliderUI', 'MetalSplitPaneUI',
+            'MetalTabbedPaneUI', 'MetalTextFieldUI',
+            'MetalTheme', 'MetalToggleButtonUI',
+            'MetalToolBarUI', 'MetalToolTipUI', 'MetalTreeUI',
+            'MetaMessage', 'Method', 'MethodDescriptor',
+            'MidiChannel', 'MidiDevice', 'MidiDevice.Info',
+            'MidiDeviceProvider', 'MidiEvent', 'MidiFileFormat',
+            'MidiFileReader', 'MidiFileWriter', 'MidiMessage',
+            'MidiSystem', 'MidiUnavailableException',
+            'MimeTypeParseException', 'MinimalHTMLWriter',
+            'MissingResourceException', 'Mixer', 'Mixer.Info',
+            'MixerProvider', 'ModificationItem', 'Modifier',
+            'MouseAdapter', 'MouseDragGestureRecognizer',
+            'MouseEvent', 'MouseInputAdapter',
+            'MouseInputListener', 'MouseListener',
+            'MouseMotionAdapter', 'MouseMotionListener',
+            'MultiButtonUI', 'MulticastSocket',
+            'MultiColorChooserUI', 'MultiComboBoxUI',
+            'MultiDesktopIconUI', 'MultiDesktopPaneUI',
+            'MultiFileChooserUI', 'MultiInternalFrameUI',
+            'MultiLabelUI', 'MultiListUI', 'MultiLookAndFeel',
+            'MultiMenuBarUI', 'MultiMenuItemUI',
+            'MultiOptionPaneUI', 'MultiPanelUI',
+            'MultiPixelPackedSampleModel', 'MultipleMaster',
+            'MultiPopupMenuUI', 'MultiProgressBarUI',
+            'MultiScrollBarUI', 'MultiScrollPaneUI',
+            'MultiSeparatorUI', 'MultiSliderUI',
+            'MultiSplitPaneUI', 'MultiTabbedPaneUI',
+            'MultiTableHeaderUI', 'MultiTableUI', 'MultiTextUI',
+            'MultiToolBarUI', 'MultiToolTipUI', 'MultiTreeUI',
+            'MultiViewportUI', 'MutableAttributeSet',
+            'MutableComboBoxModel', 'MutableTreeNode', 'Name',
+            'NameAlreadyBoundException', 'NameClassPair',
+            'NameComponent', 'NameComponentHelper',
+            'NameComponentHolder', 'NamedValue', 'NameHelper',
+            'NameHolder', 'NameNotFoundException', 'NameParser',
+            'NamespaceChangeListener', 'NameValuePair',
+            'NameValuePairHelper', 'Naming', 'NamingContext',
+            'NamingContextHelper', 'NamingContextHolder',
+            'NamingContextOperations', 'NamingEnumeration',
+            'NamingEvent', 'NamingException',
+            'NamingExceptionEvent', 'NamingListener',
+            'NamingManager', 'NamingSecurityException',
+            'NegativeArraySizeException', 'NetPermission',
+            'NoClassDefFoundError', 'NoInitialContextException',
+            'NoninvertibleTransformException',
+            'NoPermissionException', 'NoRouteToHostException',
+            'NoSuchAlgorithmException',
+            'NoSuchAttributeException', 'NoSuchElementException',
+            'NoSuchFieldError', 'NoSuchFieldException',
+            'NoSuchMethodError', 'NoSuchMethodException',
+            'NoSuchObjectException', 'NoSuchProviderException',
+            'NotActiveException', 'NotBoundException',
+            'NotContextException', 'NotEmpty', 'NotEmptyHelper',
+            'NotEmptyHolder', 'NotFound', 'NotFoundHelper',
+            'NotFoundHolder', 'NotFoundReason',
+            'NotFoundReasonHelper', 'NotFoundReasonHolder',
+            'NotOwnerException', 'NotSerializableException',
+            'NO_IMPLEMENT', 'NO_MEMORY', 'NO_PERMISSION',
+            'NO_RESOURCES', 'NO_RESPONSE',
+            'NullPointerException', 'Number', 'NumberFormat',
+            'NumberFormatException', 'NVList', 'Object',
+            'ObjectChangeListener', 'ObjectFactory',
+            'ObjectFactoryBuilder', 'ObjectHelper',
+            'ObjectHolder', 'ObjectImpl',
+            'ObjectInput', 'ObjectInputStream',
+            'ObjectInputStream.GetField',
+            'ObjectInputValidation', 'ObjectOutput',
+            'ObjectOutputStream', 'ObjectOutputStream.PutField',
+            'ObjectStreamClass', 'ObjectStreamConstants',
+            'ObjectStreamException', 'ObjectStreamField',
+            'ObjectView', 'OBJECT_NOT_EXIST', 'ObjID',
+            'OBJ_ADAPTER', 'Observable', 'Observer',
+            'OctetSeqHelper', 'OctetSeqHolder', 'OMGVMCID',
+            'OpenType', 'Operation',
+            'OperationNotSupportedException', 'Option',
+            'OptionalDataException', 'OptionPaneUI', 'ORB',
+            'OutOfMemoryError', 'OutputStream',
+            'OutputStreamWriter', 'OverlayLayout', 'Owner',
+            'Package', 'PackedColorModel', 'Pageable',
+            'PageAttributes', 'PageAttributes.ColorType',
+            'PageAttributes.MediaType',
+            'PageAttributes.OrientationRequestedType',
+            'PageAttributes.OriginType',
+            'PageAttributes.PrintQualityType', 'PageFormat',
+            'Paint', 'PaintContext', 'PaintEvent', 'Panel',
+            'PanelUI', 'Paper', 'ParagraphView',
+            'ParameterBlock', 'ParameterDescriptor',
+            'ParseException', 'ParsePosition', 'Parser',
+            'ParserDelegator', 'PartialResultException',
+            'PasswordAuthentication', 'PasswordView', 'Patch',
+            'PathIterator', 'Permission',
+            'PermissionCollection', 'Permissions',
+            'PERSIST_STORE', 'PhantomReference',
+            'PipedInputStream', 'PipedOutputStream',
+            'PipedReader', 'PipedWriter', 'PixelGrabber',
+            'PixelInterleavedSampleModel', 'PKCS8EncodedKeySpec',
+            'PlainDocument', 'PlainView', 'Point', 'Point2D',
+            'Point2D.Double', 'Point2D.Float', 'Policy',
+            'PolicyError', 'PolicyHelper',
+            'PolicyHolder', 'PolicyListHelper',
+            'PolicyListHolder', 'PolicyOperations',
+            'PolicyTypeHelper', 'Polygon', 'PopupMenu',
+            'PopupMenuEvent', 'PopupMenuListener', 'PopupMenuUI',
+            'Port', 'Port.Info', 'PortableRemoteObject',
+            'PortableRemoteObjectDelegate', 'Position',
+            'Position.Bias', 'PreparedStatement', 'Principal',
+            'PrincipalHolder', 'Printable',
+            'PrinterAbortException', 'PrinterException',
+            'PrinterGraphics', 'PrinterIOException',
+            'PrinterJob', 'PrintGraphics', 'PrintJob',
+            'PrintStream', 'PrintWriter', 'PrivateKey',
+            'PRIVATE_MEMBER', 'PrivilegedAction',
+            'PrivilegedActionException',
+            'PrivilegedExceptionAction', 'Process',
+            'ProfileDataException', 'ProgressBarUI',
+            'ProgressMonitor', 'ProgressMonitorInputStream',
+            'Properties', 'PropertyChangeEvent',
+            'PropertyChangeListener', 'PropertyChangeSupport',
+            'PropertyDescriptor', 'PropertyEditor',
+            'PropertyEditorManager', 'PropertyEditorSupport',
+            'PropertyPermission', 'PropertyResourceBundle',
+            'PropertyVetoException', 'ProtectionDomain',
+            'ProtocolException', 'Provider', 'ProviderException',
+            'Proxy', 'PublicKey', 'PUBLIC_MEMBER',
+            'PushbackInputStream', 'PushbackReader',
+            'QuadCurve2D', 'QuadCurve2D.Double',
+            'QuadCurve2D.Float', 'Random', 'RandomAccessFile',
+            'Raster', 'RasterFormatException', 'RasterOp',
+            'Reader', 'Receiver', 'Rectangle', 'Rectangle2D',
+            'Rectangle2D.Double', 'Rectangle2D.Float',
+            'RectangularShape', 'Ref', 'RefAddr', 'Reference',
+            'Referenceable', 'ReferenceQueue',
+            'ReferralException', 'ReflectPermission', 'Registry',
+            'RegistryHandler', 'RemarshalException', 'Remote',
+            'RemoteCall', 'RemoteException', 'RemoteObject',
+            'RemoteRef', 'RemoteServer', 'RemoteStub',
+            'RenderableImage', 'RenderableImageOp',
+            'RenderableImageProducer', 'RenderContext',
+            'RenderedImage', 'RenderedImageFactory', 'Renderer',
+            'RenderingHints', 'RenderingHints.Key',
+            'RepaintManager', 'ReplicateScaleFilter',
+            'Repository', 'RepositoryIdHelper', 'Request',
+            'RescaleOp', 'Resolver', 'ResolveResult',
+            'ResourceBundle', 'ResponseHandler', 'ResultSet',
+            'ResultSetMetaData', 'ReverbType', 'RGBImageFilter',
+            'RMIClassLoader', 'RMIClientSocketFactory',
+            'RMIFailureHandler', 'RMISecurityException',
+            'RMISecurityManager', 'RMIServerSocketFactory',
+            'RMISocketFactory', 'Robot', 'RootPaneContainer',
+            'RootPaneUI', 'RoundRectangle2D',
+            'RoundRectangle2D.Double', 'RoundRectangle2D.Float',
+            'RowMapper', 'RSAKey', 'RSAKeyGenParameterSpec',
+            'RSAPrivateCrtKey', 'RSAPrivateCrtKeySpec',
+            'RSAPrivateKey', 'RSAPrivateKeySpec', 'RSAPublicKey',
+            'RSAPublicKeySpec', 'RTFEditorKit',
+            'RuleBasedCollator', 'Runnable', 'RunTime',
+            'Runtime', 'RuntimeException', 'RunTimeOperations',
+            'RuntimePermission', 'SampleModel',
+            'SchemaViolationException', 'Scrollable',
+            'Scrollbar', 'ScrollBarUI', 'ScrollPane',
+            'ScrollPaneConstants', 'ScrollPaneLayout',
+            'ScrollPaneLayout.UIResource', 'ScrollPaneUI',
+            'SearchControls', 'SearchResult',
+            'SecureClassLoader', 'SecureRandom',
+            'SecureRandomSpi', 'Security', 'SecurityException',
+            'SecurityManager', 'SecurityPermission', 'Segment',
+            'SeparatorUI', 'Sequence', 'SequenceInputStream',
+            'Sequencer', 'Sequencer.SyncMode', 'Serializable',
+            'SerializablePermission', 'ServantObject',
+            'ServerCloneException', 'ServerError',
+            'ServerException', 'ServerNotActiveException',
+            'ServerRef', 'ServerRequest',
+            'ServerRuntimeException', 'ServerSocket',
+            'ServiceDetail', 'ServiceDetailHelper',
+            'ServiceInformation', 'ServiceInformationHelper',
+            'ServiceInformationHolder',
+            'ServiceUnavailableException', 'Set',
+            'SetOverrideType', 'SetOverrideTypeHelper', 'Shape',
+            'ShapeGraphicAttribute', 'Short', 'ShortHolder',
+            'ShortLookupTable', 'ShortMessage', 'ShortSeqHelper',
+            'ShortSeqHolder', 'Signature', 'SignatureException',
+            'SignatureSpi', 'SignedObject', 'Signer',
+            'SimpleAttributeSet', 'SimpleBeanInfo',
+            'SimpleDateFormat', 'SimpleTimeZone',
+            'SinglePixelPackedSampleModel',
+            'SingleSelectionModel', 'SizeLimitExceededException',
+            'SizeRequirements', 'SizeSequence', 'Skeleton',
+            'SkeletonMismatchException',
+            'SkeletonNotFoundException', 'SliderUI', 'Socket',
+            'SocketException', 'SocketImpl', 'SocketImplFactory',
+            'SocketOptions', 'SocketPermission',
+            'SocketSecurityException', 'SoftBevelBorder',
+            'SoftReference', 'SortedMap', 'SortedSet',
+            'Soundbank', 'SoundbankReader', 'SoundbankResource',
+            'SourceDataLine', 'SplitPaneUI', 'SQLData',
+            'SQLException', 'SQLInput', 'SQLOutput',
+            'SQLPermission', 'SQLWarning', 'Stack',
+            'StackOverflowError', 'StateEdit', 'StateEditable',
+            'StateFactory', 'Statement', 'Streamable',
+            'StreamableValue', 'StreamCorruptedException',
+            'StreamTokenizer', 'StrictMath', 'String',
+            'StringBuffer', 'StringBufferInputStream',
+            'StringCharacterIterator', 'StringContent',
+            'StringHolder', 'StringIndexOutOfBoundsException',
+            'StringReader', 'StringRefAddr', 'StringSelection',
+            'StringTokenizer', 'StringValueHelper',
+            'StringWriter', 'Stroke', 'Struct', 'StructMember',
+            'StructMemberHelper', 'Stub', 'StubDelegate',
+            'StubNotFoundException', 'Style', 'StyleConstants',
+            'StyleConstants.CharacterConstants',
+            'StyleConstants.ColorConstants',
+            'StyleConstants.FontConstants',
+            'StyleConstants.ParagraphConstants', 'StyleContext',
+            'StyledDocument', 'StyledEditorKit',
+            'StyledEditorKit.AlignmentAction',
+            'StyledEditorKit.BoldAction',
+            'StyledEditorKit.FontFamilyAction',
+            'StyledEditorKit.FontSizeAction',
+            'StyledEditorKit.ForegroundAction',
+            'StyledEditorKit.ItalicAction',
+            'StyledEditorKit.StyledTextAction',
+            'StyledEditorKit.UnderlineAction', 'StyleSheet',
+            'StyleSheet.BoxPainter', 'StyleSheet.ListPainter',
+            'SwingConstants', 'SwingPropertyChangeSupport',
+            'SwingUtilities', 'SyncFailedException',
+            'Synthesizer', 'SysexMessage', 'System',
+            'SystemColor', 'SystemException', 'SystemFlavorMap',
+            'TabableView', 'TabbedPaneUI', 'TabExpander',
+            'TableCellEditor', 'TableCellRenderer',
+            'TableColumn', 'TableColumnModel',
+            'TableColumnModelEvent', 'TableColumnModelListener',
+            'TableHeaderUI', 'TableModel', 'TableModelEvent',
+            'TableModelListener', 'TableUI', 'TableView',
+            'TabSet', 'TabStop', 'TagElement', 'TargetDataLine',
+            'TCKind', 'TextAction', 'TextArea', 'TextAttribute',
+            'TextComponent', 'TextEvent', 'TextField',
+            'TextHitInfo', 'TextLayout',
+            'TextLayout.CaretPolicy', 'TextListener',
+            'TextMeasurer', 'TextUI', 'TexturePaint', 'Thread',
+            'ThreadDeath', 'ThreadGroup', 'ThreadLocal',
+            'Throwable', 'Tie', 'TileObserver', 'Time',
+            'TimeLimitExceededException', 'Timer',
+            'TimerTask', 'Timestamp', 'TimeZone', 'TitledBorder',
+            'ToolBarUI', 'Toolkit', 'ToolTipManager',
+            'ToolTipUI', 'TooManyListenersException', 'Track',
+            'TransactionRequiredException',
+            'TransactionRolledbackException',
+            'TRANSACTION_REQUIRED', 'TRANSACTION_ROLLEDBACK',
+            'Transferable', 'TransformAttribute', 'TRANSIENT',
+            'Transmitter', 'Transparency', 'TreeCellEditor',
+            'TreeCellRenderer', 'TreeExpansionEvent',
+            'TreeExpansionListener', 'TreeMap', 'TreeModel',
+            'TreeModelEvent', 'TreeModelListener', 'TreeNode',
+            'TreePath', 'TreeSelectionEvent',
+            'TreeSelectionListener', 'TreeSelectionModel',
+            'TreeSet', 'TreeUI', 'TreeWillExpandListener',
+            'TypeCode', 'TypeCodeHolder', 'TypeMismatch',
+            'Types', 'UID', 'UIDefaults',
+            'UIDefaults.ActiveValue', 'UIDefaults.LazyInputMap',
+            'UIDefaults.LazyValue', 'UIDefaults.ProxyLazyValue',
+            'UIManager', 'UIManager.LookAndFeelInfo',
+            'UIResource', 'ULongLongSeqHelper',
+            'ULongLongSeqHolder', 'ULongSeqHelper',
+            'ULongSeqHolder', 'UndeclaredThrowableException',
+            'UndoableEdit', 'UndoableEditEvent',
+            'UndoableEditListener', 'UndoableEditSupport',
+            'UndoManager', 'UnexpectedException',
+            'UnicastRemoteObject', 'UnionMember',
+            'UnionMemberHelper', 'UNKNOWN', 'UnknownError',
+            'UnknownException', 'UnknownGroupException',
+            'UnknownHostException',
+            'UnknownObjectException', 'UnknownServiceException',
+            'UnknownUserException', 'UnmarshalException',
+            'UnrecoverableKeyException', 'Unreferenced',
+            'UnresolvedPermission', 'UnsatisfiedLinkError',
+            'UnsolicitedNotification',
+            'UnsolicitedNotificationEvent',
+            'UnsolicitedNotificationListener',
+            'UnsupportedAudioFileException',
+            'UnsupportedClassVersionError',
+            'UnsupportedEncodingException',
+            'UnsupportedFlavorException',
+            'UnsupportedLookAndFeelException',
+            'UnsupportedOperationException',
+            'UNSUPPORTED_POLICY', 'UNSUPPORTED_POLICY_VALUE',
+            'URL', 'URLClassLoader', 'URLConnection',
+            'URLDecoder', 'URLEncoder', 'URLStreamHandler',
+            'URLStreamHandlerFactory', 'UserException',
+            'UShortSeqHelper', 'UShortSeqHolder',
+            'UTFDataFormatException', 'Util', 'UtilDelegate',
+            'Utilities', 'ValueBase', 'ValueBaseHelper',
+            'ValueBaseHolder', 'ValueFactory', 'ValueHandler',
+            'ValueMember', 'ValueMemberHelper',
+            'VariableHeightLayoutCache', 'Vector', 'VerifyError',
+            'VersionSpecHelper', 'VetoableChangeListener',
+            'VetoableChangeSupport', 'View', 'ViewFactory',
+            'ViewportLayout', 'ViewportUI',
+            'VirtualMachineError', 'Visibility',
+            'VisibilityHelper', 'VMID', 'VM_ABSTRACT',
+            'VM_CUSTOM', 'VM_NONE', 'VM_TRUNCATABLE',
+            'VoiceStatus', 'Void', 'WCharSeqHelper',
+            'WCharSeqHolder', 'WeakHashMap', 'WeakReference',
+            'Window', 'WindowAdapter', 'WindowConstants',
+            'WindowEvent', 'WindowListener', 'WrappedPlainView',
+            'WritableRaster', 'WritableRenderedImage',
+            'WriteAbortedException', 'Writer',
+            'WrongTransaction', 'WStringValueHelper',
+            'X509Certificate', 'X509CRL', 'X509CRLEntry',
+            'X509EncodedKeySpec', 'X509Extension', 'ZipEntry',
+            'ZipException', 'ZipFile', 'ZipInputStream',
+            'ZipOutputStream', 'ZoneView',
+            '_BindingIteratorImplBase', '_BindingIteratorStub',
+            '_IDLTypeStub', '_NamingContextImplBase',
+            '_NamingContextStub', '_PolicyStub', '_Remote_Stub'
+            ),
+        4 => array(
+            'void', 'double', 'int', 'boolean', 'byte', 'short', 'long', 'char', 'float'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}',
+        '+', '-', '*', '/', '%',
+        '!', '&', '|', '^',
+        '<', '>', '=',
+        '?', ':', ';',
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => true,
+        4 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000000; font-weight: bold;',
+            2 => 'color: #000066; font-weight: bold;',
+            3 => 'color: #003399;',
+            4 => 'color: #000066; font-weight: bold;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #666666; font-style: italic;',
+            2 => 'color: #006699;',
+            3 => 'color: #008000; font-style: italic; font-weight: bold;',
+            3 => 'color: #008000; font-style: italic; font-weight: bold;',
+            'MULTI' => 'color: #666666; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #009900;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #0000ff;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006633;',
+            2 => 'color: #006633;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #339933;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => 'http://www.google.com/search?hl=en&amp;q=allinurl%3A{FNAMEL}+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky',
+        4 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/java5.php b/examples/includes/geshi/geshi/java5.php
new file mode 100644 (file)
index 0000000..1766ef9
--- /dev/null
@@ -0,0 +1,1031 @@
+<?php
+/*************************************************************************************
+ * java.php
+ * --------
+ * Author: Nigel McNie (nigel@geshi.org)
+ * Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/07/10
+ *
+ * Java language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/25 (1.0.7.22)
+ *   -  Added highlighting of import and package directives as non-OOP
+ * 2005/12/28 (1.0.4)
+ *   -  Added instanceof keyword
+ * 2004/11/27 (1.0.3)
+ *   -  Added support for multiple object splitters
+ * 2004/08/05 (1.0.2)
+ *   -  Added URL support
+ *   -  Added keyword "this", as bugs in GeSHi class ironed out
+ * 2004/08/05 (1.0.1)
+ *   -  Added support for symbols
+ *   -  Added extra missed keywords
+ * 2004/07/14 (1.0.0)
+ *   -  First Release
+ *
+ * TODO
+ * -------------------------
+ * *
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Java(TM) 2 Platform Standard Edition 5.0',
+    'COMMENT_SINGLE' => array(1 => '//'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'COMMENT_REGEXP' => array(
+        //Import and Package directives (Basic Support only)
+        2 => '/(?:(?<=import[\\n\\s])|(?<=package[\\n\\s]))[\\n\\s]*([a-zA-Z0-9_]+\\.)*([a-zA-Z0-9_]+|\*)(?=[\n\s;])/i',
+        // javadoc comments
+        3 => '#/\*\*(?![\*\/]).*\*/#sU'
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            /* see the authoritative list of all 50 Java keywords at */
+            /* http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#229308 */
+
+            /* java keywords, part 1: control flow */
+            'case', 'default', 'do', 'else', 'for',
+            'goto', 'if', 'switch', 'while'
+
+            /* IMO 'break', 'continue', 'return' and 'throw' */
+                        /* should also be added to this group, as they   */
+            /* also manage the control flow,                 */
+            /* arguably 'try'/'catch'/'finally' as well      */
+            ),
+        2 => array(
+            /* java keywords, part 2 */
+
+            'break', 'continue', 'return', 'throw',
+            'try', 'catch', 'finally',
+
+            'abstract', 'assert', 'class', 'const', 'enum', 'extends',
+            'final', 'implements', 'import', 'instanceof', 'interface',
+            'native', 'new', 'package', 'private', 'protected',
+            'public', 'static', 'strictfp', 'super', 'synchronized',
+            'this', 'throws', 'transient', 'volatile'
+            ),
+        3 => array(
+            /* Java keywords, part 3: primitive data types and 'void' */
+            'boolean', 'byte', 'char', 'double',
+            'float', 'int', 'long', 'short', 'void'
+            ),
+        4 => array(
+            /* other reserved words in Java: literals */
+            /* should be styled to look similar to numbers and Strings */
+            'false', 'null', 'true'
+            ),
+        5 => array (
+            'Applet', 'AppletContext', 'AppletStub', 'AudioClip'
+            ),
+        6 => array (
+            'AWTError', 'AWTEvent', 'AWTEventMulticaster', 'AWTException', 'AWTKeyStroke', 'AWTPermission', 'ActiveEvent', 'Adjustable', 'AlphaComposite', 'BasicStroke', 'BorderLayout', 'BufferCapabilities', 'BufferCapabilities.FlipContents', 'Button', 'Canvas', 'CardLayout', 'Checkbox', 'CheckboxGroup', 'CheckboxMenuItem', 'Choice', 'Color', 'Component', 'ComponentOrientation', 'Composite', 'CompositeContext', 'Container', 'ContainerOrderFocusTraversalPolicy', 'Cursor', 'DefaultFocusTraversalPolicy', 'DefaultKeyboardFocusManager', 'Dialog', 'Dimension', 'DisplayMode', 'EventQueue', 'FileDialog', 'FlowLayout', 'FocusTraversalPolicy', 'Font', 'FontFormatException', 'FontMetrics', 'Frame', 'GradientPaint', 'Graphics', 'Graphics2D', 'GraphicsConfigTemplate', 'GraphicsConfiguration', 'GraphicsDevice', 'GraphicsEnvironment', 'GridBagConstraints', 'GridBagLayout', 'GridLayout', 'HeadlessException', 'IllegalComponentStateException', 'Image', 'ImageCapabilities', 'Insets', 'ItemSelectable', 'JobAttributes',
+            'JobAttributes.DefaultSelectionType', 'JobAttributes.DestinationType', 'JobAttributes.DialogType', 'JobAttributes.MultipleDocumentHandlingType', 'JobAttributes.SidesType', 'KeyEventDispatcher', 'KeyEventPostProcessor', 'KeyboardFocusManager', 'Label', 'LayoutManager', 'LayoutManager2', 'MediaTracker', 'Menu', 'MenuBar', 'MenuComponent', 'MenuContainer', 'MenuItem', 'MenuShortcut', 'MouseInfo', 'PageAttributes', 'PageAttributes.ColorType', 'PageAttributes.MediaType', 'PageAttributes.OrientationRequestedType', 'PageAttributes.OriginType', 'PageAttributes.PrintQualityType', 'Paint', 'PaintContext', 'Panel', 'Point', 'PointerInfo', 'Polygon', 'PopupMenu', 'PrintGraphics', 'PrintJob', 'Rectangle', 'RenderingHints', 'RenderingHints.Key', 'Robot', 'ScrollPane', 'ScrollPaneAdjustable', 'Scrollbar', 'Shape', 'Stroke', 'SystemColor', 'TextArea', 'TextComponent', 'TextField', 'TexturePaint', 'Toolkit', 'Transparency', 'Window'
+            ),
+        7 => array (
+            'CMMException', 'ColorSpace', 'ICC_ColorSpace', 'ICC_Profile', 'ICC_ProfileGray', 'ICC_ProfileRGB', 'ProfileDataException'
+            ),
+        8 => array (
+            'Clipboard', 'ClipboardOwner', 'DataFlavor', 'FlavorEvent', 'FlavorListener', 'FlavorMap', 'FlavorTable', 'MimeTypeParseException', 'StringSelection', 'SystemFlavorMap', 'Transferable', 'UnsupportedFlavorException'
+            ),
+        9 => array (
+            'Autoscroll', 'DnDConstants', 'DragGestureEvent', 'DragGestureListener', 'DragGestureRecognizer', 'DragSource', 'DragSourceAdapter', 'DragSourceContext', 'DragSourceDragEvent', 'DragSourceDropEvent', 'DragSourceEvent', 'DragSourceListener', 'DragSourceMotionListener', 'DropTarget', 'DropTarget.DropTargetAutoScroller', 'DropTargetAdapter', 'DropTargetContext', 'DropTargetDragEvent', 'DropTargetDropEvent', 'DropTargetEvent', 'DropTargetListener', 'InvalidDnDOperationException', 'MouseDragGestureRecognizer'
+            ),
+        10 => array (
+            'AWTEventListener', 'AWTEventListenerProxy', 'ActionEvent', 'ActionListener', 'AdjustmentEvent', 'AdjustmentListener', 'ComponentAdapter', 'ComponentEvent', 'ComponentListener', 'ContainerAdapter', 'ContainerEvent', 'ContainerListener', 'FocusAdapter', 'FocusEvent', 'FocusListener', 'HierarchyBoundsAdapter', 'HierarchyBoundsListener', 'HierarchyEvent', 'HierarchyListener', 'InputEvent', 'InputMethodEvent', 'InputMethodListener', 'InvocationEvent', 'ItemEvent', 'ItemListener', 'KeyAdapter', 'KeyEvent', 'KeyListener', 'MouseAdapter', 'MouseListener', 'MouseMotionAdapter', 'MouseMotionListener', 'MouseWheelEvent', 'MouseWheelListener', 'PaintEvent', 'TextEvent', 'TextListener', 'WindowAdapter', 'WindowEvent', 'WindowFocusListener', 'WindowListener', 'WindowStateListener'
+            ),
+        11 => array (
+            'FontRenderContext', 'GlyphJustificationInfo', 'GlyphMetrics', 'GlyphVector', 'GraphicAttribute', 'ImageGraphicAttribute', 'LineBreakMeasurer', 'LineMetrics', 'MultipleMaster', 'NumericShaper', 'ShapeGraphicAttribute', 'TextAttribute', 'TextHitInfo', 'TextLayout', 'TextLayout.CaretPolicy', 'TextMeasurer', 'TransformAttribute'
+            ),
+        12 => array (
+            'AffineTransform', 'Arc2D', 'Arc2D.Double', 'Arc2D.Float', 'Area', 'CubicCurve2D', 'CubicCurve2D.Double', 'CubicCurve2D.Float', 'Dimension2D', 'Ellipse2D', 'Ellipse2D.Double', 'Ellipse2D.Float', 'FlatteningPathIterator', 'GeneralPath', 'IllegalPathStateException', 'Line2D', 'Line2D.Double', 'Line2D.Float', 'NoninvertibleTransformException', 'PathIterator', 'Point2D', 'Point2D.Double', 'Point2D.Float', 'QuadCurve2D', 'QuadCurve2D.Double', 'QuadCurve2D.Float', 'Rectangle2D', 'Rectangle2D.Double', 'Rectangle2D.Float', 'RectangularShape', 'RoundRectangle2D', 'RoundRectangle2D.Double', 'RoundRectangle2D.Float'
+            ),
+        13 => array (
+            'InputContext', 'InputMethodHighlight', 'InputMethodRequests', 'InputSubset'
+            ),
+        14 => array (
+            'InputMethod', 'InputMethodContext', 'InputMethodDescriptor'
+            ),
+        15 => array (
+            'AffineTransformOp', 'AreaAveragingScaleFilter', 'BandCombineOp', 'BandedSampleModel', 'BufferStrategy', 'BufferedImage', 'BufferedImageFilter', 'BufferedImageOp', 'ByteLookupTable', 'ColorConvertOp', 'ColorModel', 'ComponentColorModel', 'ComponentSampleModel', 'ConvolveOp', 'CropImageFilter', 'DataBuffer', 'DataBufferByte', 'DataBufferDouble', 'DataBufferFloat', 'DataBufferInt', 'DataBufferShort', 'DataBufferUShort', 'DirectColorModel', 'FilteredImageSource', 'ImageConsumer', 'ImageFilter', 'ImageObserver', 'ImageProducer', 'ImagingOpException', 'IndexColorModel', 'Kernel', 'LookupOp', 'LookupTable', 'MemoryImageSource', 'MultiPixelPackedSampleModel', 'PackedColorModel', 'PixelGrabber', 'PixelInterleavedSampleModel', 'RGBImageFilter', 'Raster', 'RasterFormatException', 'RasterOp', 'RenderedImage', 'ReplicateScaleFilter', 'RescaleOp', 'SampleModel', 'ShortLookupTable', 'SinglePixelPackedSampleModel', 'TileObserver', 'VolatileImage', 'WritableRaster', 'WritableRenderedImage'
+            ),
+        16 => array (
+            'ContextualRenderedImageFactory', 'ParameterBlock', 'RenderContext', 'RenderableImage', 'RenderableImageOp', 'RenderableImageProducer', 'RenderedImageFactory'
+            ),
+        17 => array (
+            'Book', 'PageFormat', 'Pageable', 'Paper', 'Printable', 'PrinterAbortException', 'PrinterException', 'PrinterGraphics', 'PrinterIOException', 'PrinterJob'
+            ),
+        18 => array (
+            'AppletInitializer', 'BeanDescriptor', 'BeanInfo', 'Beans', 'Customizer', 'DefaultPersistenceDelegate', 'DesignMode', 'Encoder', 'EventHandler', 'EventSetDescriptor', 'ExceptionListener', 'Expression', 'FeatureDescriptor', 'IndexedPropertyChangeEvent', 'IndexedPropertyDescriptor', 'Introspector', 'MethodDescriptor', 'ParameterDescriptor', 'PersistenceDelegate', 'PropertyChangeEvent', 'PropertyChangeListener', 'PropertyChangeListenerProxy', 'PropertyChangeSupport', 'PropertyDescriptor', 'PropertyEditor', 'PropertyEditorManager', 'PropertyEditorSupport', 'PropertyVetoException', 'SimpleBeanInfo', 'VetoableChangeListener', 'VetoableChangeListenerProxy', 'VetoableChangeSupport', 'Visibility', 'XMLDecoder', 'XMLEncoder'
+            ),
+        19 => array (
+            'BeanContext', 'BeanContextChild', 'BeanContextChildComponentProxy', 'BeanContextChildSupport', 'BeanContextContainerProxy', 'BeanContextEvent', 'BeanContextMembershipEvent', 'BeanContextMembershipListener', 'BeanContextProxy', 'BeanContextServiceAvailableEvent', 'BeanContextServiceProvider', 'BeanContextServiceProviderBeanInfo', 'BeanContextServiceRevokedEvent', 'BeanContextServiceRevokedListener', 'BeanContextServices', 'BeanContextServicesListener', 'BeanContextServicesSupport', 'BeanContextServicesSupport.BCSSServiceProvider', 'BeanContextSupport', 'BeanContextSupport.BCSIterator'
+            ),
+        20 => array (
+            'BufferedInputStream', 'BufferedOutputStream', 'BufferedReader', 'BufferedWriter', 'ByteArrayInputStream', 'ByteArrayOutputStream', 'CharArrayReader', 'CharArrayWriter', 'CharConversionException', 'Closeable', 'DataInput', 'DataOutput', 'EOFException', 'Externalizable', 'File', 'FileDescriptor', 'FileInputStream', 'FileNotFoundException', 'FileOutputStream', 'FilePermission', 'FileReader', 'FileWriter', 'FilenameFilter', 'FilterInputStream', 'FilterOutputStream', 'FilterReader', 'FilterWriter', 'Flushable', 'IOException', 'InputStreamReader', 'InterruptedIOException', 'InvalidClassException', 'InvalidObjectException', 'LineNumberInputStream', 'LineNumberReader', 'NotActiveException', 'NotSerializableException', 'ObjectInput', 'ObjectInputStream', 'ObjectInputStream.GetField', 'ObjectInputValidation', 'ObjectOutput', 'ObjectOutputStream', 'ObjectOutputStream.PutField', 'ObjectStreamClass', 'ObjectStreamConstants', 'ObjectStreamException', 'ObjectStreamField', 'OptionalDataException', 'OutputStreamWriter',
+            'PipedInputStream', 'PipedOutputStream', 'PipedReader', 'PipedWriter', 'PrintStream', 'PrintWriter', 'PushbackInputStream', 'PushbackReader', 'RandomAccessFile', 'Reader', 'SequenceInputStream', 'Serializable', 'SerializablePermission', 'StreamCorruptedException', 'StreamTokenizer', 'StringBufferInputStream', 'StringReader', 'StringWriter', 'SyncFailedException', 'UTFDataFormatException', 'UnsupportedEncodingException', 'WriteAbortedException', 'Writer'
+            ),
+        21 => array (
+            'AbstractMethodError', 'Appendable', 'ArithmeticException', 'ArrayIndexOutOfBoundsException', 'ArrayStoreException', 'AssertionError', 'Boolean', 'Byte', 'CharSequence', 'Character', 'Character.Subset', 'Character.UnicodeBlock', 'Class', 'ClassCastException', 'ClassCircularityError', 'ClassFormatError', 'ClassLoader', 'ClassNotFoundException', 'CloneNotSupportedException', 'Cloneable', 'Comparable', 'Compiler', 'Deprecated', 'Double', 'Enum', 'EnumConstantNotPresentException', 'Error', 'Exception', 'ExceptionInInitializerError', 'Float', 'IllegalAccessError', 'IllegalAccessException', 'IllegalArgumentException', 'IllegalMonitorStateException', 'IllegalStateException', 'IllegalThreadStateException', 'IncompatibleClassChangeError', 'IndexOutOfBoundsException', 'InheritableThreadLocal', 'InstantiationError', 'InstantiationException', 'Integer', 'InternalError', 'InterruptedException', 'Iterable', 'LinkageError', 'Long', 'Math', 'NegativeArraySizeException', 'NoClassDefFoundError', 'NoSuchFieldError',
+            'NoSuchFieldException', 'NoSuchMethodError', 'NoSuchMethodException', 'NullPointerException', 'Number', 'NumberFormatException', 'OutOfMemoryError', 'Override', 'Package', 'Process', 'ProcessBuilder', 'Readable', 'Runnable', 'Runtime', 'RuntimeException', 'RuntimePermission', 'SecurityException', 'SecurityManager', 'Short', 'StackOverflowError', 'StackTraceElement', 'StrictMath', 'String', 'StringBuffer', 'StringBuilder', 'StringIndexOutOfBoundsException', 'SuppressWarnings', 'System', 'Thread', 'Thread.State', 'Thread.UncaughtExceptionHandler', 'ThreadDeath', 'ThreadGroup', 'ThreadLocal', 'Throwable', 'TypeNotPresentException', 'UnknownError', 'UnsatisfiedLinkError', 'UnsupportedClassVersionError', 'UnsupportedOperationException', 'VerifyError', 'VirtualMachineError', 'Void'
+            ),
+        22 => array (
+            'AnnotationFormatError', 'AnnotationTypeMismatchException', 'Documented', 'ElementType', 'IncompleteAnnotationException', 'Inherited', 'Retention', 'RetentionPolicy', 'Target'
+            ),
+        23 => array (
+            'ClassDefinition', 'ClassFileTransformer', 'IllegalClassFormatException', 'Instrumentation', 'UnmodifiableClassException'
+            ),
+        24 => array (
+            'ClassLoadingMXBean', 'CompilationMXBean', 'GarbageCollectorMXBean', 'ManagementFactory', 'ManagementPermission', 'MemoryMXBean', 'MemoryManagerMXBean', 'MemoryNotificationInfo', 'MemoryPoolMXBean', 'MemoryType', 'MemoryUsage', 'OperatingSystemMXBean', 'RuntimeMXBean', 'ThreadInfo', 'ThreadMXBean'
+            ),
+        25 => array (
+            'PhantomReference', 'ReferenceQueue', 'SoftReference', 'WeakReference'
+            ),
+        26 => array (
+            'AccessibleObject', 'AnnotatedElement', 'Constructor', 'Field', 'GenericArrayType', 'GenericDeclaration', 'GenericSignatureFormatError', 'InvocationHandler', 'InvocationTargetException', 'MalformedParameterizedTypeException', 'Member', 'Method', 'Modifier', 'ParameterizedType', 'ReflectPermission', 'Type', 'TypeVariable', 'UndeclaredThrowableException', 'WildcardType'
+            ),
+        27 => array (
+            'BigDecimal', 'BigInteger', 'MathContext', 'RoundingMode'
+            ),
+        28 => array (
+            'Authenticator', 'Authenticator.RequestorType', 'BindException', 'CacheRequest', 'CacheResponse', 'ContentHandlerFactory', 'CookieHandler', 'DatagramPacket', 'DatagramSocket', 'DatagramSocketImpl', 'DatagramSocketImplFactory', 'FileNameMap', 'HttpRetryException', 'HttpURLConnection', 'Inet4Address', 'Inet6Address', 'InetAddress', 'InetSocketAddress', 'JarURLConnection', 'MalformedURLException', 'MulticastSocket', 'NetPermission', 'NetworkInterface', 'NoRouteToHostException', 'PasswordAuthentication', 'PortUnreachableException', 'ProtocolException', 'Proxy.Type', 'ProxySelector', 'ResponseCache', 'SecureCacheResponse', 'ServerSocket', 'Socket', 'SocketAddress', 'SocketException', 'SocketImpl', 'SocketImplFactory', 'SocketOptions', 'SocketPermission', 'SocketTimeoutException', 'URI', 'URISyntaxException', 'URL', 'URLClassLoader', 'URLConnection', 'URLDecoder', 'URLEncoder', 'URLStreamHandler', 'URLStreamHandlerFactory', 'UnknownServiceException'
+            ),
+        29 => array (
+            'Buffer', 'BufferOverflowException', 'BufferUnderflowException', 'ByteBuffer', 'ByteOrder', 'CharBuffer', 'DoubleBuffer', 'FloatBuffer', 'IntBuffer', 'InvalidMarkException', 'LongBuffer', 'MappedByteBuffer', 'ReadOnlyBufferException', 'ShortBuffer'
+            ),
+        30 => array (
+            'AlreadyConnectedException', 'AsynchronousCloseException', 'ByteChannel', 'CancelledKeyException', 'Channel', 'Channels', 'ClosedByInterruptException', 'ClosedChannelException', 'ClosedSelectorException', 'ConnectionPendingException', 'DatagramChannel', 'FileChannel', 'FileChannel.MapMode', 'FileLock', 'FileLockInterruptionException', 'GatheringByteChannel', 'IllegalBlockingModeException', 'IllegalSelectorException', 'InterruptibleChannel', 'NoConnectionPendingException', 'NonReadableChannelException', 'NonWritableChannelException', 'NotYetBoundException', 'NotYetConnectedException', 'OverlappingFileLockException', 'Pipe', 'Pipe.SinkChannel', 'Pipe.SourceChannel', 'ReadableByteChannel', 'ScatteringByteChannel', 'SelectableChannel', 'SelectionKey', 'Selector', 'ServerSocketChannel', 'SocketChannel', 'UnresolvedAddressException', 'UnsupportedAddressTypeException', 'WritableByteChannel'
+            ),
+        31 => array (
+            'AbstractInterruptibleChannel', 'AbstractSelectableChannel', 'AbstractSelectionKey', 'AbstractSelector', 'SelectorProvider'
+            ),
+        32 => array (
+            'CharacterCodingException', 'Charset', 'CharsetDecoder', 'CharsetEncoder', 'CoderMalfunctionError', 'CoderResult', 'CodingErrorAction', 'IllegalCharsetNameException', 'MalformedInputException', 'UnmappableCharacterException', 'UnsupportedCharsetException'
+            ),
+        33 => array (
+            'CharsetProvider'
+            ),
+        34 => array (
+            'AccessException', 'AlreadyBoundException', 'ConnectIOException', 'MarshalException', 'MarshalledObject', 'Naming', 'NoSuchObjectException', 'NotBoundException', 'RMISecurityException', 'RMISecurityManager', 'Remote', 'RemoteException', 'ServerError', 'ServerException', 'ServerRuntimeException', 'StubNotFoundException', 'UnexpectedException', 'UnmarshalException'
+            ),
+        35 => array (
+            'Activatable', 'ActivateFailedException', 'ActivationDesc', 'ActivationException', 'ActivationGroup', 'ActivationGroupDesc', 'ActivationGroupDesc.CommandEnvironment', 'ActivationGroupID', 'ActivationGroup_Stub', 'ActivationID', 'ActivationInstantiator', 'ActivationMonitor', 'ActivationSystem', 'Activator', 'UnknownGroupException', 'UnknownObjectException'
+            ),
+        36 => array (
+            'DGC', 'Lease', 'VMID'
+            ),
+        37 => array (
+            'LocateRegistry', 'Registry', 'RegistryHandler'
+            ),
+        38 => array (
+            'ExportException', 'LoaderHandler', 'LogStream', 'ObjID', 'Operation', 'RMIClassLoader', 'RMIClassLoaderSpi', 'RMIClientSocketFactory', 'RMIFailureHandler', 'RMIServerSocketFactory', 'RMISocketFactory', 'RemoteCall', 'RemoteObject', 'RemoteObjectInvocationHandler', 'RemoteRef', 'RemoteServer', 'RemoteStub', 'ServerCloneException', 'ServerNotActiveException', 'ServerRef', 'Skeleton', 'SkeletonMismatchException', 'SkeletonNotFoundException', 'SocketSecurityException', 'UID', 'UnicastRemoteObject', 'Unreferenced'
+            ),
+        39 => array (
+            'AccessControlContext', 'AccessControlException', 'AccessController', 'AlgorithmParameterGenerator', 'AlgorithmParameterGeneratorSpi', 'AlgorithmParameters', 'AlgorithmParametersSpi', 'AllPermission', 'AuthProvider', 'BasicPermission', 'CodeSigner', 'CodeSource', 'DigestException', 'DigestInputStream', 'DigestOutputStream', 'DomainCombiner', 'GeneralSecurityException', 'Guard', 'GuardedObject', 'Identity', 'IdentityScope', 'InvalidAlgorithmParameterException', 'InvalidParameterException', 'Key', 'KeyException', 'KeyFactory', 'KeyFactorySpi', 'KeyManagementException', 'KeyPair', 'KeyPairGenerator', 'KeyPairGeneratorSpi', 'KeyRep', 'KeyRep.Type', 'KeyStore', 'KeyStore.Builder', 'KeyStore.CallbackHandlerProtection', 'KeyStore.Entry', 'KeyStore.LoadStoreParameter', 'KeyStore.PasswordProtection', 'KeyStore.PrivateKeyEntry', 'KeyStore.ProtectionParameter', 'KeyStore.SecretKeyEntry', 'KeyStore.TrustedCertificateEntry', 'KeyStoreException', 'KeyStoreSpi', 'MessageDigest', 'MessageDigestSpi',
+            'NoSuchAlgorithmException', 'NoSuchProviderException', 'PermissionCollection', 'Permissions', 'PrivateKey', 'PrivilegedAction', 'PrivilegedActionException', 'PrivilegedExceptionAction', 'ProtectionDomain', 'Provider', 'Provider.Service', 'ProviderException', 'PublicKey', 'SecureClassLoader', 'SecureRandom', 'SecureRandomSpi', 'Security', 'SecurityPermission', 'Signature', 'SignatureException', 'SignatureSpi', 'SignedObject', 'Signer', 'UnrecoverableEntryException', 'UnrecoverableKeyException', 'UnresolvedPermission'
+            ),
+        40 => array (
+            'Acl', 'AclEntry', 'AclNotFoundException', 'Group', 'LastOwnerException', 'NotOwnerException', 'Owner'
+            ),
+        41 => array (
+            'CRL', 'CRLException', 'CRLSelector', 'CertPath', 'CertPath.CertPathRep', 'CertPathBuilder', 'CertPathBuilderException', 'CertPathBuilderResult', 'CertPathBuilderSpi', 'CertPathParameters', 'CertPathValidator', 'CertPathValidatorException', 'CertPathValidatorResult', 'CertPathValidatorSpi', 'CertSelector', 'CertStore', 'CertStoreException', 'CertStoreParameters', 'CertStoreSpi', 'Certificate.CertificateRep', 'CertificateFactory', 'CertificateFactorySpi', 'CollectionCertStoreParameters', 'LDAPCertStoreParameters', 'PKIXBuilderParameters', 'PKIXCertPathBuilderResult', 'PKIXCertPathChecker', 'PKIXCertPathValidatorResult', 'PKIXParameters', 'PolicyNode', 'PolicyQualifierInfo', 'TrustAnchor', 'X509CRL', 'X509CRLEntry', 'X509CRLSelector', 'X509CertSelector', 'X509Extension'
+            ),
+        42 => array (
+            'DSAKey', 'DSAKeyPairGenerator', 'DSAParams', 'DSAPrivateKey', 'DSAPublicKey', 'ECKey', 'ECPrivateKey', 'ECPublicKey', 'RSAKey', 'RSAMultiPrimePrivateCrtKey', 'RSAPrivateCrtKey', 'RSAPrivateKey', 'RSAPublicKey'
+            ),
+        43 => array (
+            'AlgorithmParameterSpec', 'DSAParameterSpec', 'DSAPrivateKeySpec', 'DSAPublicKeySpec', 'ECField', 'ECFieldF2m', 'ECFieldFp', 'ECGenParameterSpec', 'ECParameterSpec', 'ECPoint', 'ECPrivateKeySpec', 'ECPublicKeySpec', 'EllipticCurve', 'EncodedKeySpec', 'InvalidKeySpecException', 'InvalidParameterSpecException', 'KeySpec', 'MGF1ParameterSpec', 'PKCS8EncodedKeySpec', 'PSSParameterSpec', 'RSAKeyGenParameterSpec', 'RSAMultiPrimePrivateCrtKeySpec', 'RSAOtherPrimeInfo', 'RSAPrivateCrtKeySpec', 'RSAPrivateKeySpec', 'RSAPublicKeySpec', 'X509EncodedKeySpec'
+            ),
+        44 => array (
+            'BatchUpdateException', 'Blob', 'CallableStatement', 'Clob', 'Connection', 'DataTruncation', 'DatabaseMetaData', 'Driver', 'DriverManager', 'DriverPropertyInfo', 'ParameterMetaData', 'PreparedStatement', 'Ref', 'ResultSet', 'ResultSetMetaData', 'SQLData', 'SQLException', 'SQLInput', 'SQLOutput', 'SQLPermission', 'SQLWarning', 'Savepoint', 'Struct', 'Time', 'Types'
+            ),
+        45 => array (
+            'AttributedCharacterIterator', 'AttributedCharacterIterator.Attribute', 'AttributedString', 'Bidi', 'BreakIterator', 'CharacterIterator', 'ChoiceFormat', 'CollationElementIterator', 'CollationKey', 'Collator', 'DateFormat', 'DateFormat.Field', 'DateFormatSymbols', 'DecimalFormat', 'DecimalFormatSymbols', 'FieldPosition', 'Format', 'Format.Field', 'MessageFormat', 'MessageFormat.Field', 'NumberFormat', 'NumberFormat.Field', 'ParseException', 'ParsePosition', 'RuleBasedCollator', 'SimpleDateFormat', 'StringCharacterIterator'
+            ),
+        46 => array (
+            'AbstractCollection', 'AbstractList', 'AbstractMap', 'AbstractQueue', 'AbstractSequentialList', 'AbstractSet', 'ArrayList', 'Arrays', 'BitSet', 'Calendar', 'Collection', 'Collections', 'Comparator', 'ConcurrentModificationException', 'Currency', 'Dictionary', 'DuplicateFormatFlagsException', 'EmptyStackException', 'EnumMap', 'EnumSet', 'Enumeration', 'EventListenerProxy', 'EventObject', 'FormatFlagsConversionMismatchException', 'Formattable', 'FormattableFlags', 'Formatter.BigDecimalLayoutForm', 'FormatterClosedException', 'GregorianCalendar', 'HashMap', 'HashSet', 'Hashtable', 'IdentityHashMap', 'IllegalFormatCodePointException', 'IllegalFormatConversionException', 'IllegalFormatException', 'IllegalFormatFlagsException', 'IllegalFormatPrecisionException', 'IllegalFormatWidthException', 'InputMismatchException', 'InvalidPropertiesFormatException', 'Iterator', 'LinkedHashMap', 'LinkedHashSet', 'LinkedList', 'ListIterator', 'ListResourceBundle', 'Locale', 'Map', 'Map.Entry', 'MissingFormatArgumentException',
+            'MissingFormatWidthException', 'MissingResourceException', 'NoSuchElementException', 'Observable', 'Observer', 'PriorityQueue', 'Properties', 'PropertyPermission', 'PropertyResourceBundle', 'Queue', 'Random', 'RandomAccess', 'ResourceBundle', 'Scanner', 'Set', 'SimpleTimeZone', 'SortedMap', 'SortedSet', 'Stack', 'StringTokenizer', 'TimeZone', 'TimerTask', 'TooManyListenersException', 'TreeMap', 'TreeSet', 'UUID', 'UnknownFormatConversionException', 'UnknownFormatFlagsException', 'Vector', 'WeakHashMap'
+            ),
+        47 => array (
+            'AbstractExecutorService', 'ArrayBlockingQueue', 'BlockingQueue', 'BrokenBarrierException', 'Callable', 'CancellationException', 'CompletionService', 'ConcurrentHashMap', 'ConcurrentLinkedQueue', 'ConcurrentMap', 'CopyOnWriteArrayList', 'CopyOnWriteArraySet', 'CountDownLatch', 'CyclicBarrier', 'DelayQueue', 'Delayed', 'Exchanger', 'ExecutionException', 'Executor', 'ExecutorCompletionService', 'ExecutorService', 'Executors', 'Future', 'FutureTask', 'LinkedBlockingQueue', 'PriorityBlockingQueue', 'RejectedExecutionException', 'RejectedExecutionHandler', 'ScheduledExecutorService', 'ScheduledFuture', 'ScheduledThreadPoolExecutor', 'Semaphore', 'SynchronousQueue', 'ThreadFactory', 'ThreadPoolExecutor', 'ThreadPoolExecutor.AbortPolicy', 'ThreadPoolExecutor.CallerRunsPolicy', 'ThreadPoolExecutor.DiscardOldestPolicy', 'ThreadPoolExecutor.DiscardPolicy', 'TimeUnit', 'TimeoutException'
+            ),
+        48 => array (
+            'AtomicBoolean', 'AtomicInteger', 'AtomicIntegerArray', 'AtomicIntegerFieldUpdater', 'AtomicLong', 'AtomicLongArray', 'AtomicLongFieldUpdater', 'AtomicMarkableReference', 'AtomicReference', 'AtomicReferenceArray', 'AtomicReferenceFieldUpdater', 'AtomicStampedReference'
+            ),
+        49 => array (
+            'AbstractQueuedSynchronizer', 'Condition', 'Lock', 'LockSupport', 'ReadWriteLock', 'ReentrantLock', 'ReentrantReadWriteLock', 'ReentrantReadWriteLock.ReadLock', 'ReentrantReadWriteLock.WriteLock'
+            ),
+        50 => array (
+            'Attributes.Name', 'JarEntry', 'JarException', 'JarFile', 'JarInputStream', 'JarOutputStream', 'Manifest', 'Pack200', 'Pack200.Packer', 'Pack200.Unpacker'
+            ),
+        51 => array (
+            'ConsoleHandler', 'ErrorManager', 'FileHandler', 'Filter', 'Handler', 'Level', 'LogManager', 'LogRecord', 'Logger', 'LoggingMXBean', 'LoggingPermission', 'MemoryHandler', 'SimpleFormatter', 'SocketHandler', 'StreamHandler', 'XMLFormatter'
+            ),
+        52 => array (
+            'AbstractPreferences', 'BackingStoreException', 'InvalidPreferencesFormatException', 'NodeChangeEvent', 'NodeChangeListener', 'PreferenceChangeEvent', 'PreferenceChangeListener', 'Preferences', 'PreferencesFactory'
+            ),
+        53 => array (
+            'MatchResult', 'Matcher', 'Pattern', 'PatternSyntaxException'
+            ),
+        54 => array (
+            'Adler32', 'CRC32', 'CheckedInputStream', 'CheckedOutputStream', 'Checksum', 'DataFormatException', 'Deflater', 'DeflaterOutputStream', 'GZIPInputStream', 'GZIPOutputStream', 'Inflater', 'InflaterInputStream', 'ZipEntry', 'ZipException', 'ZipFile', 'ZipInputStream', 'ZipOutputStream'
+            ),
+        55 => array (
+            'Accessible', 'AccessibleAction', 'AccessibleAttributeSequence', 'AccessibleBundle', 'AccessibleComponent', 'AccessibleContext', 'AccessibleEditableText', 'AccessibleExtendedComponent', 'AccessibleExtendedTable', 'AccessibleExtendedText', 'AccessibleHyperlink', 'AccessibleHypertext', 'AccessibleIcon', 'AccessibleKeyBinding', 'AccessibleRelation', 'AccessibleRelationSet', 'AccessibleResourceBundle', 'AccessibleRole', 'AccessibleSelection', 'AccessibleState', 'AccessibleStateSet', 'AccessibleStreamable', 'AccessibleTable', 'AccessibleTableModelChange', 'AccessibleText', 'AccessibleTextSequence', 'AccessibleValue'
+            ),
+        56 => array (
+            'ActivityCompletedException', 'ActivityRequiredException', 'InvalidActivityException'
+            ),
+        57 => array (
+            'BadPaddingException', 'Cipher', 'CipherInputStream', 'CipherOutputStream', 'CipherSpi', 'EncryptedPrivateKeyInfo', 'ExemptionMechanism', 'ExemptionMechanismException', 'ExemptionMechanismSpi', 'IllegalBlockSizeException', 'KeyAgreement', 'KeyAgreementSpi', 'KeyGenerator', 'KeyGeneratorSpi', 'Mac', 'MacSpi', 'NoSuchPaddingException', 'NullCipher', 'SealedObject', 'SecretKey', 'SecretKeyFactory', 'SecretKeyFactorySpi', 'ShortBufferException'
+            ),
+        58 => array (
+            'DHKey', 'DHPrivateKey', 'DHPublicKey', 'PBEKey'
+            ),
+        59 => array (
+            'DESKeySpec', 'DESedeKeySpec', 'DHGenParameterSpec', 'DHParameterSpec', 'DHPrivateKeySpec', 'DHPublicKeySpec', 'IvParameterSpec', 'OAEPParameterSpec', 'PBEKeySpec', 'PBEParameterSpec', 'PSource', 'PSource.PSpecified', 'RC2ParameterSpec', 'RC5ParameterSpec', 'SecretKeySpec'
+            ),
+        60 => array (
+            'IIOException', 'IIOImage', 'IIOParam', 'IIOParamController', 'ImageIO', 'ImageReadParam', 'ImageReader', 'ImageTranscoder', 'ImageTypeSpecifier', 'ImageWriteParam', 'ImageWriter'
+            ),
+        61 => array (
+            'IIOReadProgressListener', 'IIOReadUpdateListener', 'IIOReadWarningListener', 'IIOWriteProgressListener', 'IIOWriteWarningListener'
+            ),
+        62 => array (
+            'IIOInvalidTreeException', 'IIOMetadata', 'IIOMetadataController', 'IIOMetadataFormat', 'IIOMetadataFormatImpl', 'IIOMetadataNode'
+            ),
+        63 => array (
+            'BMPImageWriteParam'
+            ),
+        64 => array (
+            'JPEGHuffmanTable', 'JPEGImageReadParam', 'JPEGImageWriteParam', 'JPEGQTable'
+            ),
+        65 => array (
+            'IIORegistry', 'IIOServiceProvider', 'ImageInputStreamSpi', 'ImageOutputStreamSpi', 'ImageReaderSpi', 'ImageReaderWriterSpi', 'ImageTranscoderSpi', 'ImageWriterSpi', 'RegisterableService', 'ServiceRegistry', 'ServiceRegistry.Filter'
+            ),
+        66 => array (
+            'FileCacheImageInputStream', 'FileCacheImageOutputStream', 'FileImageInputStream', 'FileImageOutputStream', 'IIOByteBuffer', 'ImageInputStream', 'ImageInputStreamImpl', 'ImageOutputStream', 'ImageOutputStreamImpl', 'MemoryCacheImageInputStream', 'MemoryCacheImageOutputStream'
+            ),
+        67 => array (
+            'AttributeChangeNotification', 'AttributeChangeNotificationFilter', 'AttributeNotFoundException', 'AttributeValueExp', 'BadAttributeValueExpException', 'BadBinaryOpValueExpException', 'BadStringOperationException', 'Descriptor', 'DescriptorAccess', 'DynamicMBean', 'InstanceAlreadyExistsException', 'InstanceNotFoundException', 'InvalidApplicationException', 'JMException', 'JMRuntimeException', 'ListenerNotFoundException', 'MBeanAttributeInfo', 'MBeanConstructorInfo', 'MBeanException', 'MBeanFeatureInfo', 'MBeanInfo', 'MBeanNotificationInfo', 'MBeanOperationInfo', 'MBeanParameterInfo', 'MBeanPermission', 'MBeanRegistration', 'MBeanRegistrationException', 'MBeanServer', 'MBeanServerBuilder', 'MBeanServerConnection', 'MBeanServerDelegate', 'MBeanServerDelegateMBean', 'MBeanServerFactory', 'MBeanServerInvocationHandler', 'MBeanServerNotification', 'MBeanServerPermission', 'MBeanTrustPermission', 'MalformedObjectNameException', 'NotCompliantMBeanException', 'Notification', 'NotificationBroadcaster',
+            'NotificationBroadcasterSupport', 'NotificationEmitter', 'NotificationFilter', 'NotificationFilterSupport', 'NotificationListener', 'ObjectInstance', 'ObjectName', 'OperationsException', 'PersistentMBean', 'Query', 'QueryEval', 'QueryExp', 'ReflectionException', 'RuntimeErrorException', 'RuntimeMBeanException', 'RuntimeOperationsException', 'ServiceNotFoundException', 'StandardMBean', 'StringValueExp', 'ValueExp'
+            ),
+        68 => array (
+            'ClassLoaderRepository', 'MLet', 'MLetMBean', 'PrivateClassLoader', 'PrivateMLet'
+            ),
+        69 => array (
+            'DescriptorSupport', 'InvalidTargetObjectTypeException', 'ModelMBean', 'ModelMBeanAttributeInfo', 'ModelMBeanConstructorInfo', 'ModelMBeanInfo', 'ModelMBeanInfoSupport', 'ModelMBeanNotificationBroadcaster', 'ModelMBeanNotificationInfo', 'ModelMBeanOperationInfo', 'RequiredModelMBean', 'XMLParseException'
+            ),
+        70 => array (
+            'CounterMonitor', 'CounterMonitorMBean', 'GaugeMonitor', 'GaugeMonitorMBean', 'Monitor', 'MonitorMBean', 'MonitorNotification', 'MonitorSettingException', 'StringMonitor', 'StringMonitorMBean'
+            ),
+        71 => array (
+            'ArrayType', 'CompositeData', 'CompositeDataSupport', 'CompositeType', 'InvalidOpenTypeException', 'KeyAlreadyExistsException', 'OpenDataException', 'OpenMBeanAttributeInfo', 'OpenMBeanAttributeInfoSupport', 'OpenMBeanConstructorInfo', 'OpenMBeanConstructorInfoSupport', 'OpenMBeanInfo', 'OpenMBeanInfoSupport', 'OpenMBeanOperationInfo', 'OpenMBeanOperationInfoSupport', 'OpenMBeanParameterInfo', 'OpenMBeanParameterInfoSupport', 'SimpleType', 'TabularData', 'TabularDataSupport', 'TabularType'
+            ),
+        72 => array (
+            'InvalidRelationIdException', 'InvalidRelationServiceException', 'InvalidRelationTypeException', 'InvalidRoleInfoException', 'InvalidRoleValueException', 'MBeanServerNotificationFilter', 'Relation', 'RelationException', 'RelationNotFoundException', 'RelationNotification', 'RelationService', 'RelationServiceMBean', 'RelationServiceNotRegisteredException', 'RelationSupport', 'RelationSupportMBean', 'RelationType', 'RelationTypeNotFoundException', 'RelationTypeSupport', 'Role', 'RoleInfo', 'RoleInfoNotFoundException', 'RoleList', 'RoleNotFoundException', 'RoleResult', 'RoleStatus', 'RoleUnresolved', 'RoleUnresolvedList'
+            ),
+        73 => array (
+            'JMXAuthenticator', 'JMXConnectionNotification', 'JMXConnector', 'JMXConnectorFactory', 'JMXConnectorProvider', 'JMXConnectorServer', 'JMXConnectorServerFactory', 'JMXConnectorServerMBean', 'JMXConnectorServerProvider', 'JMXPrincipal', 'JMXProviderException', 'JMXServerErrorException', 'JMXServiceURL', 'MBeanServerForwarder', 'NotificationResult', 'SubjectDelegationPermission', 'TargetedNotification'
+            ),
+        74 => array (
+            'RMIConnection', 'RMIConnectionImpl', 'RMIConnectionImpl_Stub', 'RMIConnector', 'RMIConnectorServer', 'RMIIIOPServerImpl', 'RMIJRMPServerImpl', 'RMIServer', 'RMIServerImpl', 'RMIServerImpl_Stub'
+            ),
+        75 => array (
+            'TimerAlarmClockNotification', 'TimerMBean', 'TimerNotification'
+            ),
+        76 => array (
+            'AuthenticationNotSupportedException', 'BinaryRefAddr', 'CannotProceedException', 'CommunicationException', 'CompositeName', 'CompoundName', 'ConfigurationException', 'ContextNotEmptyException', 'InitialContext', 'InsufficientResourcesException', 'InterruptedNamingException', 'InvalidNameException', 'LimitExceededException', 'LinkException', 'LinkLoopException', 'LinkRef', 'MalformedLinkException', 'Name', 'NameAlreadyBoundException', 'NameClassPair', 'NameNotFoundException', 'NameParser', 'NamingEnumeration', 'NamingException', 'NamingSecurityException', 'NoInitialContextException', 'NoPermissionException', 'NotContextException', 'OperationNotSupportedException', 'PartialResultException', 'RefAddr', 'Referenceable', 'ReferralException', 'ServiceUnavailableException', 'SizeLimitExceededException', 'StringRefAddr', 'TimeLimitExceededException'
+            ),
+        77 => array (
+            'AttributeInUseException', 'AttributeModificationException', 'BasicAttribute', 'BasicAttributes', 'DirContext', 'InitialDirContext', 'InvalidAttributeIdentifierException', 'InvalidAttributesException', 'InvalidSearchControlsException', 'InvalidSearchFilterException', 'ModificationItem', 'NoSuchAttributeException', 'SchemaViolationException', 'SearchControls', 'SearchResult'
+            ),
+        78 => array (
+            'EventContext', 'EventDirContext', 'NamespaceChangeListener', 'NamingEvent', 'NamingExceptionEvent', 'NamingListener', 'ObjectChangeListener'
+            ),
+        79 => array (
+            'BasicControl', 'ControlFactory', 'ExtendedRequest', 'ExtendedResponse', 'HasControls', 'InitialLdapContext', 'LdapContext', 'LdapName', 'LdapReferralException', 'ManageReferralControl', 'PagedResultsControl', 'PagedResultsResponseControl', 'Rdn', 'SortControl', 'SortKey', 'SortResponseControl', 'StartTlsRequest', 'StartTlsResponse', 'UnsolicitedNotification', 'UnsolicitedNotificationEvent', 'UnsolicitedNotificationListener'
+            ),
+        80 => array (
+            'DirObjectFactory', 'DirStateFactory', 'DirStateFactory.Result', 'DirectoryManager', 'InitialContextFactory', 'InitialContextFactoryBuilder', 'NamingManager', 'ObjectFactory', 'ObjectFactoryBuilder', 'ResolveResult', 'Resolver', 'StateFactory'
+            ),
+        81 => array (
+            'ServerSocketFactory', 'SocketFactory'
+            ),
+        82 => array (
+            'CertPathTrustManagerParameters', 'HandshakeCompletedEvent', 'HandshakeCompletedListener', 'HostnameVerifier', 'HttpsURLConnection', 'KeyManager', 'KeyManagerFactory', 'KeyManagerFactorySpi', 'KeyStoreBuilderParameters', 'ManagerFactoryParameters', 'SSLContext', 'SSLContextSpi', 'SSLEngine', 'SSLEngineResult', 'SSLEngineResult.HandshakeStatus', 'SSLEngineResult.Status', 'SSLException', 'SSLHandshakeException', 'SSLKeyException', 'SSLPeerUnverifiedException', 'SSLPermission', 'SSLProtocolException', 'SSLServerSocket', 'SSLServerSocketFactory', 'SSLSession', 'SSLSessionBindingEvent', 'SSLSessionBindingListener', 'SSLSessionContext', 'SSLSocket', 'SSLSocketFactory', 'TrustManager', 'TrustManagerFactory', 'TrustManagerFactorySpi', 'X509ExtendedKeyManager', 'X509KeyManager', 'X509TrustManager'
+            ),
+        83 => array (
+            'AttributeException', 'CancelablePrintJob', 'Doc', 'DocFlavor', 'DocFlavor.BYTE_ARRAY', 'DocFlavor.CHAR_ARRAY', 'DocFlavor.INPUT_STREAM', 'DocFlavor.READER', 'DocFlavor.SERVICE_FORMATTED', 'DocFlavor.STRING', 'DocFlavor.URL', 'DocPrintJob', 'FlavorException', 'MultiDoc', 'MultiDocPrintJob', 'MultiDocPrintService', 'PrintException', 'PrintService', 'PrintServiceLookup', 'ServiceUI', 'ServiceUIFactory', 'SimpleDoc', 'StreamPrintService', 'StreamPrintServiceFactory', 'URIException'
+            ),
+        84 => array (
+            'AttributeSetUtilities', 'DateTimeSyntax', 'DocAttribute', 'DocAttributeSet', 'EnumSyntax', 'HashAttributeSet', 'HashDocAttributeSet', 'HashPrintJobAttributeSet', 'HashPrintRequestAttributeSet', 'HashPrintServiceAttributeSet', 'IntegerSyntax', 'PrintJobAttribute', 'PrintJobAttributeSet', 'PrintRequestAttribute', 'PrintRequestAttributeSet', 'PrintServiceAttribute', 'PrintServiceAttributeSet', 'ResolutionSyntax', 'SetOfIntegerSyntax', 'Size2DSyntax', 'SupportedValuesAttribute', 'TextSyntax', 'URISyntax', 'UnmodifiableSetException'
+            ),
+        85 => array (
+            'Chromaticity', 'ColorSupported', 'Compression', 'Copies', 'CopiesSupported', 'DateTimeAtCompleted', 'DateTimeAtCreation', 'DateTimeAtProcessing', 'Destination', 'DocumentName', 'Fidelity', 'Finishings', 'JobHoldUntil', 'JobImpressions', 'JobImpressionsCompleted', 'JobImpressionsSupported', 'JobKOctets', 'JobKOctetsProcessed', 'JobKOctetsSupported', 'JobMediaSheets', 'JobMediaSheetsCompleted', 'JobMediaSheetsSupported', 'JobMessageFromOperator', 'JobName', 'JobOriginatingUserName', 'JobPriority', 'JobPrioritySupported', 'JobSheets', 'JobState', 'JobStateReason', 'JobStateReasons', 'Media', 'MediaName', 'MediaPrintableArea', 'MediaSize', 'MediaSize.Engineering', 'MediaSize.ISO', 'MediaSize.JIS', 'MediaSize.NA', 'MediaSize.Other', 'MediaSizeName', 'MediaTray', 'MultipleDocumentHandling', 'NumberOfDocuments', 'NumberOfInterveningJobs', 'NumberUp', 'NumberUpSupported', 'OrientationRequested', 'OutputDeviceAssigned', 'PDLOverrideSupported', 'PageRanges', 'PagesPerMinute', 'PagesPerMinuteColor',
+            'PresentationDirection', 'PrintQuality', 'PrinterInfo', 'PrinterIsAcceptingJobs', 'PrinterLocation', 'PrinterMakeAndModel', 'PrinterMessageFromOperator', 'PrinterMoreInfo', 'PrinterMoreInfoManufacturer', 'PrinterName', 'PrinterResolution', 'PrinterState', 'PrinterStateReason', 'PrinterStateReasons', 'PrinterURI', 'QueuedJobCount', 'ReferenceUriSchemesSupported', 'RequestingUserName', 'Severity', 'SheetCollate', 'Sides'
+            ),
+        86 => array (
+            'PrintEvent', 'PrintJobAdapter', 'PrintJobAttributeEvent', 'PrintJobAttributeListener', 'PrintJobEvent', 'PrintJobListener', 'PrintServiceAttributeEvent', 'PrintServiceAttributeListener'
+            ),
+        87 => array (
+            'PortableRemoteObject'
+            ),
+        88 => array (
+            'ClassDesc', 'PortableRemoteObjectDelegate', 'Stub', 'StubDelegate', 'Tie', 'Util', 'UtilDelegate', 'ValueHandler', 'ValueHandlerMultiFormat'
+            ),
+        89 => array (
+            'SslRMIClientSocketFactory', 'SslRMIServerSocketFactory'
+            ),
+        90 => array (
+            'AuthPermission', 'DestroyFailedException', 'Destroyable', 'PrivateCredentialPermission', 'RefreshFailedException', 'Refreshable', 'Subject', 'SubjectDomainCombiner'
+            ),
+        91 => array (
+            'Callback', 'CallbackHandler', 'ChoiceCallback', 'ConfirmationCallback', 'LanguageCallback', 'NameCallback', 'PasswordCallback', 'TextInputCallback', 'TextOutputCallback', 'UnsupportedCallbackException'
+            ),
+        92 => array (
+            'DelegationPermission', 'KerberosKey', 'KerberosPrincipal', 'KerberosTicket', 'ServicePermission'
+            ),
+        93 => array (
+            'AccountException', 'AccountExpiredException', 'AccountLockedException', 'AccountNotFoundException', 'AppConfigurationEntry', 'AppConfigurationEntry.LoginModuleControlFlag', 'Configuration', 'CredentialException', 'CredentialExpiredException', 'CredentialNotFoundException', 'FailedLoginException', 'LoginContext', 'LoginException'
+            ),
+        94 => array (
+            'LoginModule'
+            ),
+        95 => array (
+            'X500Principal', 'X500PrivateCredential'
+            ),
+        96 => array (
+            'AuthorizeCallback', 'RealmCallback', 'RealmChoiceCallback', 'Sasl', 'SaslClient', 'SaslClientFactory', 'SaslException', 'SaslServer', 'SaslServerFactory'
+            ),
+        97 => array (
+            'ControllerEventListener', 'Instrument', 'InvalidMidiDataException', 'MetaEventListener', 'MetaMessage', 'MidiChannel', 'MidiDevice', 'MidiDevice.Info', 'MidiEvent', 'MidiFileFormat', 'MidiMessage', 'MidiSystem', 'MidiUnavailableException', 'Patch', 'Receiver', 'Sequence', 'Sequencer', 'Sequencer.SyncMode', 'ShortMessage', 'Soundbank', 'SoundbankResource', 'Synthesizer', 'SysexMessage', 'Track', 'Transmitter', 'VoiceStatus'
+            ),
+        98 => array (
+            'MidiDeviceProvider', 'MidiFileReader', 'MidiFileWriter', 'SoundbankReader'
+            ),
+        99 => array (
+            'AudioFileFormat', 'AudioFileFormat.Type', 'AudioFormat', 'AudioFormat.Encoding', 'AudioInputStream', 'AudioPermission', 'AudioSystem', 'BooleanControl', 'BooleanControl.Type', 'Clip', 'CompoundControl', 'CompoundControl.Type', 'Control.Type', 'DataLine', 'DataLine.Info', 'EnumControl', 'EnumControl.Type', 'FloatControl', 'FloatControl.Type', 'Line', 'Line.Info', 'LineEvent', 'LineEvent.Type', 'LineListener', 'LineUnavailableException', 'Mixer', 'Mixer.Info', 'Port', 'Port.Info', 'ReverbType', 'SourceDataLine', 'TargetDataLine', 'UnsupportedAudioFileException'
+            ),
+        100 => array (
+            'AudioFileReader', 'AudioFileWriter', 'FormatConversionProvider', 'MixerProvider'
+            ),
+        101 => array (
+            'ConnectionEvent', 'ConnectionEventListener', 'ConnectionPoolDataSource', 'DataSource', 'PooledConnection', 'RowSet', 'RowSetEvent', 'RowSetInternal', 'RowSetListener', 'RowSetMetaData', 'RowSetReader', 'RowSetWriter', 'XAConnection', 'XADataSource'
+            ),
+        102 => array (
+            'BaseRowSet', 'CachedRowSet', 'FilteredRowSet', 'JdbcRowSet', 'JoinRowSet', 'Joinable', 'Predicate', 'RowSetMetaDataImpl', 'RowSetWarning', 'WebRowSet'
+            ),
+        103 => array (
+            'SQLInputImpl', 'SQLOutputImpl', 'SerialArray', 'SerialBlob', 'SerialClob', 'SerialDatalink', 'SerialException', 'SerialJavaObject', 'SerialRef', 'SerialStruct'
+            ),
+        104 => array (
+            'SyncFactory', 'SyncFactoryException', 'SyncProvider', 'SyncProviderException', 'SyncResolver', 'TransactionalWriter', 'XmlReader', 'XmlWriter'
+            ),
+        105 => array (
+            'AbstractAction', 'AbstractButton', 'AbstractCellEditor', 'AbstractListModel', 'AbstractSpinnerModel', 'Action', 'ActionMap', 'BorderFactory', 'BoundedRangeModel', 'Box', 'Box.Filler', 'BoxLayout', 'ButtonGroup', 'ButtonModel', 'CellEditor', 'CellRendererPane', 'ComboBoxEditor', 'ComboBoxModel', 'ComponentInputMap', 'DebugGraphics', 'DefaultBoundedRangeModel', 'DefaultButtonModel', 'DefaultCellEditor', 'DefaultComboBoxModel', 'DefaultDesktopManager', 'DefaultFocusManager', 'DefaultListCellRenderer', 'DefaultListCellRenderer.UIResource', 'DefaultListModel', 'DefaultListSelectionModel', 'DefaultSingleSelectionModel', 'DesktopManager', 'FocusManager', 'GrayFilter', 'Icon', 'ImageIcon', 'InputMap', 'InputVerifier', 'InternalFrameFocusTraversalPolicy', 'JApplet', 'JButton', 'JCheckBox', 'JCheckBoxMenuItem', 'JColorChooser', 'JComboBox', 'JComboBox.KeySelectionManager', 'JComponent', 'JDesktopPane', 'JDialog', 'JEditorPane', 'JFileChooser', 'JFormattedTextField', 'JFormattedTextField.AbstractFormatter',
+            'JFormattedTextField.AbstractFormatterFactory', 'JFrame', 'JInternalFrame', 'JInternalFrame.JDesktopIcon', 'JLabel', 'JLayeredPane', 'JList', 'JMenu', 'JMenuBar', 'JMenuItem', 'JOptionPane', 'JPanel', 'JPasswordField', 'JPopupMenu', 'JPopupMenu.Separator', 'JProgressBar', 'JRadioButton', 'JRadioButtonMenuItem', 'JRootPane', 'JScrollBar', 'JScrollPane', 'JSeparator', 'JSlider', 'JSpinner', 'JSpinner.DateEditor', 'JSpinner.DefaultEditor', 'JSpinner.ListEditor', 'JSpinner.NumberEditor', 'JSplitPane', 'JTabbedPane', 'JTable', 'JTable.PrintMode', 'JTextArea', 'JTextField', 'JTextPane', 'JToggleButton', 'JToggleButton.ToggleButtonModel', 'JToolBar', 'JToolBar.Separator', 'JToolTip', 'JTree', 'JTree.DynamicUtilTreeNode', 'JTree.EmptySelectionModel', 'JViewport', 'JWindow', 'KeyStroke', 'LayoutFocusTraversalPolicy', 'ListCellRenderer', 'ListModel', 'ListSelectionModel', 'LookAndFeel', 'MenuElement', 'MenuSelectionManager', 'MutableComboBoxModel', 'OverlayLayout', 'Popup', 'PopupFactory', 'ProgressMonitor',
+            'ProgressMonitorInputStream', 'Renderer', 'RepaintManager', 'RootPaneContainer', 'ScrollPaneConstants', 'ScrollPaneLayout', 'ScrollPaneLayout.UIResource', 'Scrollable', 'SingleSelectionModel', 'SizeRequirements', 'SizeSequence', 'SortingFocusTraversalPolicy', 'SpinnerDateModel', 'SpinnerListModel', 'SpinnerModel', 'SpinnerNumberModel', 'Spring', 'SpringLayout', 'SpringLayout.Constraints', 'SwingConstants', 'SwingUtilities', 'ToolTipManager', 'TransferHandler', 'UIDefaults', 'UIDefaults.ActiveValue', 'UIDefaults.LazyInputMap', 'UIDefaults.LazyValue', 'UIDefaults.ProxyLazyValue', 'UIManager', 'UIManager.LookAndFeelInfo', 'UnsupportedLookAndFeelException', 'ViewportLayout', 'WindowConstants'
+            ),
+        106 => array (
+            'AbstractBorder', 'BevelBorder', 'Border', 'CompoundBorder', 'EmptyBorder', 'EtchedBorder', 'LineBorder', 'MatteBorder', 'SoftBevelBorder', 'TitledBorder'
+            ),
+        107 => array (
+            'AbstractColorChooserPanel', 'ColorChooserComponentFactory', 'ColorSelectionModel', 'DefaultColorSelectionModel'
+            ),
+        108 => array (
+            'AncestorEvent', 'AncestorListener', 'CaretEvent', 'CaretListener', 'CellEditorListener', 'ChangeEvent', 'ChangeListener', 'DocumentEvent.ElementChange', 'DocumentEvent.EventType', 'DocumentListener', 'EventListenerList', 'HyperlinkEvent', 'HyperlinkEvent.EventType', 'HyperlinkListener', 'InternalFrameAdapter', 'InternalFrameEvent', 'InternalFrameListener', 'ListDataEvent', 'ListDataListener', 'ListSelectionEvent', 'ListSelectionListener', 'MenuDragMouseEvent', 'MenuDragMouseListener', 'MenuEvent', 'MenuKeyEvent', 'MenuKeyListener', 'MenuListener', 'MouseInputAdapter', 'MouseInputListener', 'PopupMenuEvent', 'PopupMenuListener', 'SwingPropertyChangeSupport', 'TableColumnModelEvent', 'TableColumnModelListener', 'TableModelEvent', 'TableModelListener', 'TreeExpansionEvent', 'TreeExpansionListener', 'TreeModelEvent', 'TreeModelListener', 'TreeSelectionEvent', 'TreeSelectionListener', 'TreeWillExpandListener', 'UndoableEditEvent', 'UndoableEditListener'
+            ),
+        109 => array (
+            'FileSystemView', 'FileView'
+            ),
+        110 => array (
+            'ActionMapUIResource', 'BorderUIResource', 'BorderUIResource.BevelBorderUIResource', 'BorderUIResource.CompoundBorderUIResource', 'BorderUIResource.EmptyBorderUIResource', 'BorderUIResource.EtchedBorderUIResource', 'BorderUIResource.LineBorderUIResource', 'BorderUIResource.MatteBorderUIResource', 'BorderUIResource.TitledBorderUIResource', 'ButtonUI', 'ColorChooserUI', 'ColorUIResource', 'ComboBoxUI', 'ComponentInputMapUIResource', 'ComponentUI', 'DesktopIconUI', 'DesktopPaneUI', 'DimensionUIResource', 'FileChooserUI', 'FontUIResource', 'IconUIResource', 'InputMapUIResource', 'InsetsUIResource', 'InternalFrameUI', 'LabelUI', 'ListUI', 'MenuBarUI', 'MenuItemUI', 'OptionPaneUI', 'PanelUI', 'PopupMenuUI', 'ProgressBarUI', 'RootPaneUI', 'ScrollBarUI', 'ScrollPaneUI', 'SeparatorUI', 'SliderUI', 'SpinnerUI', 'SplitPaneUI', 'TabbedPaneUI', 'TableHeaderUI', 'TableUI', 'TextUI', 'ToolBarUI', 'ToolTipUI', 'TreeUI', 'UIResource', 'ViewportUI'
+            ),
+        111 => array (
+            'BasicArrowButton', 'BasicBorders', 'BasicBorders.ButtonBorder', 'BasicBorders.FieldBorder', 'BasicBorders.MarginBorder', 'BasicBorders.MenuBarBorder', 'BasicBorders.RadioButtonBorder', 'BasicBorders.RolloverButtonBorder', 'BasicBorders.SplitPaneBorder', 'BasicBorders.ToggleButtonBorder', 'BasicButtonListener', 'BasicButtonUI', 'BasicCheckBoxMenuItemUI', 'BasicCheckBoxUI', 'BasicColorChooserUI', 'BasicComboBoxEditor', 'BasicComboBoxEditor.UIResource', 'BasicComboBoxRenderer', 'BasicComboBoxRenderer.UIResource', 'BasicComboBoxUI', 'BasicComboPopup', 'BasicDesktopIconUI', 'BasicDesktopPaneUI', 'BasicDirectoryModel', 'BasicEditorPaneUI', 'BasicFileChooserUI', 'BasicFormattedTextFieldUI', 'BasicGraphicsUtils', 'BasicHTML', 'BasicIconFactory', 'BasicInternalFrameTitlePane', 'BasicInternalFrameUI', 'BasicLabelUI', 'BasicListUI', 'BasicLookAndFeel', 'BasicMenuBarUI', 'BasicMenuItemUI', 'BasicMenuUI', 'BasicOptionPaneUI', 'BasicOptionPaneUI.ButtonAreaLayout', 'BasicPanelUI', 'BasicPasswordFieldUI',
+            'BasicPopupMenuSeparatorUI', 'BasicPopupMenuUI', 'BasicProgressBarUI', 'BasicRadioButtonMenuItemUI', 'BasicRadioButtonUI', 'BasicRootPaneUI', 'BasicScrollBarUI', 'BasicScrollPaneUI', 'BasicSeparatorUI', 'BasicSliderUI', 'BasicSpinnerUI', 'BasicSplitPaneDivider', 'BasicSplitPaneUI', 'BasicTabbedPaneUI', 'BasicTableHeaderUI', 'BasicTableUI', 'BasicTextAreaUI', 'BasicTextFieldUI', 'BasicTextPaneUI', 'BasicTextUI', 'BasicTextUI.BasicCaret', 'BasicTextUI.BasicHighlighter', 'BasicToggleButtonUI', 'BasicToolBarSeparatorUI', 'BasicToolBarUI', 'BasicToolTipUI', 'BasicTreeUI', 'BasicViewportUI', 'ComboPopup', 'DefaultMenuLayout'
+            ),
+        112 => array (
+            'DefaultMetalTheme', 'MetalBorders', 'MetalBorders.ButtonBorder', 'MetalBorders.Flush3DBorder', 'MetalBorders.InternalFrameBorder', 'MetalBorders.MenuBarBorder', 'MetalBorders.MenuItemBorder', 'MetalBorders.OptionDialogBorder', 'MetalBorders.PaletteBorder', 'MetalBorders.PopupMenuBorder', 'MetalBorders.RolloverButtonBorder', 'MetalBorders.ScrollPaneBorder', 'MetalBorders.TableHeaderBorder', 'MetalBorders.TextFieldBorder', 'MetalBorders.ToggleButtonBorder', 'MetalBorders.ToolBarBorder', 'MetalButtonUI', 'MetalCheckBoxIcon', 'MetalCheckBoxUI', 'MetalComboBoxButton', 'MetalComboBoxEditor', 'MetalComboBoxEditor.UIResource', 'MetalComboBoxIcon', 'MetalComboBoxUI', 'MetalDesktopIconUI', 'MetalFileChooserUI', 'MetalIconFactory', 'MetalIconFactory.FileIcon16', 'MetalIconFactory.FolderIcon16', 'MetalIconFactory.PaletteCloseIcon', 'MetalIconFactory.TreeControlIcon', 'MetalIconFactory.TreeFolderIcon', 'MetalIconFactory.TreeLeafIcon', 'MetalInternalFrameTitlePane', 'MetalInternalFrameUI', 'MetalLabelUI',
+            'MetalLookAndFeel', 'MetalMenuBarUI', 'MetalPopupMenuSeparatorUI', 'MetalProgressBarUI', 'MetalRadioButtonUI', 'MetalRootPaneUI', 'MetalScrollBarUI', 'MetalScrollButton', 'MetalScrollPaneUI', 'MetalSeparatorUI', 'MetalSliderUI', 'MetalSplitPaneUI', 'MetalTabbedPaneUI', 'MetalTextFieldUI', 'MetalTheme', 'MetalToggleButtonUI', 'MetalToolBarUI', 'MetalToolTipUI', 'MetalTreeUI', 'OceanTheme'
+            ),
+        113 => array (
+            'MultiButtonUI', 'MultiColorChooserUI', 'MultiComboBoxUI', 'MultiDesktopIconUI', 'MultiDesktopPaneUI', 'MultiFileChooserUI', 'MultiInternalFrameUI', 'MultiLabelUI', 'MultiListUI', 'MultiLookAndFeel', 'MultiMenuBarUI', 'MultiMenuItemUI', 'MultiOptionPaneUI', 'MultiPanelUI', 'MultiPopupMenuUI', 'MultiProgressBarUI', 'MultiRootPaneUI', 'MultiScrollBarUI', 'MultiScrollPaneUI', 'MultiSeparatorUI', 'MultiSliderUI', 'MultiSpinnerUI', 'MultiSplitPaneUI', 'MultiTabbedPaneUI', 'MultiTableHeaderUI', 'MultiTableUI', 'MultiTextUI', 'MultiToolBarUI', 'MultiToolTipUI', 'MultiTreeUI', 'MultiViewportUI'
+            ),
+        114 => array (
+            'ColorType', 'Region', 'SynthConstants', 'SynthContext', 'SynthGraphicsUtils', 'SynthLookAndFeel', 'SynthPainter', 'SynthStyle', 'SynthStyleFactory'
+            ),
+        115 => array (
+            'AbstractTableModel', 'DefaultTableCellRenderer', 'DefaultTableCellRenderer.UIResource', 'DefaultTableColumnModel', 'DefaultTableModel', 'JTableHeader', 'TableCellEditor', 'TableCellRenderer', 'TableColumn', 'TableColumnModel', 'TableModel'
+            ),
+        116 => array (
+            'AbstractDocument', 'AbstractDocument.AttributeContext', 'AbstractDocument.Content', 'AbstractDocument.ElementEdit', 'AbstractWriter', 'AsyncBoxView', 'AttributeSet.CharacterAttribute', 'AttributeSet.ColorAttribute', 'AttributeSet.FontAttribute', 'AttributeSet.ParagraphAttribute', 'BadLocationException', 'BoxView', 'Caret', 'ChangedCharSetException', 'ComponentView', 'CompositeView', 'DateFormatter', 'DefaultCaret', 'DefaultEditorKit', 'DefaultEditorKit.BeepAction', 'DefaultEditorKit.CopyAction', 'DefaultEditorKit.CutAction', 'DefaultEditorKit.DefaultKeyTypedAction', 'DefaultEditorKit.InsertBreakAction', 'DefaultEditorKit.InsertContentAction', 'DefaultEditorKit.InsertTabAction', 'DefaultEditorKit.PasteAction', 'DefaultFormatter', 'DefaultFormatterFactory', 'DefaultHighlighter', 'DefaultHighlighter.DefaultHighlightPainter', 'DefaultStyledDocument', 'DefaultStyledDocument.AttributeUndoableEdit', 'DefaultStyledDocument.ElementSpec', 'DefaultTextUI', 'DocumentFilter', 'DocumentFilter.FilterBypass',
+            'EditorKit', 'ElementIterator', 'FieldView', 'FlowView', 'FlowView.FlowStrategy', 'GapContent', 'GlyphView', 'GlyphView.GlyphPainter', 'Highlighter', 'Highlighter.Highlight', 'Highlighter.HighlightPainter', 'IconView', 'InternationalFormatter', 'JTextComponent', 'JTextComponent.KeyBinding', 'Keymap', 'LabelView', 'LayeredHighlighter', 'LayeredHighlighter.LayerPainter', 'LayoutQueue', 'MaskFormatter', 'MutableAttributeSet', 'NavigationFilter', 'NavigationFilter.FilterBypass', 'NumberFormatter', 'PasswordView', 'PlainDocument', 'PlainView', 'Position', 'Position.Bias', 'Segment', 'SimpleAttributeSet', 'StringContent', 'Style', 'StyleConstants', 'StyleConstants.CharacterConstants', 'StyleConstants.ColorConstants', 'StyleConstants.FontConstants', 'StyleConstants.ParagraphConstants', 'StyleContext', 'StyledDocument', 'StyledEditorKit', 'StyledEditorKit.AlignmentAction', 'StyledEditorKit.BoldAction', 'StyledEditorKit.FontFamilyAction', 'StyledEditorKit.FontSizeAction', 'StyledEditorKit.ForegroundAction',
+            'StyledEditorKit.ItalicAction', 'StyledEditorKit.StyledTextAction', 'StyledEditorKit.UnderlineAction', 'TabExpander', 'TabSet', 'TabStop', 'TabableView', 'TableView', 'TextAction', 'Utilities', 'View', 'ViewFactory', 'WrappedPlainView', 'ZoneView'
+            ),
+        117 => array (
+            'BlockView', 'CSS', 'CSS.Attribute', 'FormSubmitEvent', 'FormSubmitEvent.MethodType', 'FormView', 'HTML', 'HTML.Attribute', 'HTML.Tag', 'HTML.UnknownTag', 'HTMLDocument', 'HTMLDocument.Iterator', 'HTMLEditorKit', 'HTMLEditorKit.HTMLFactory', 'HTMLEditorKit.HTMLTextAction', 'HTMLEditorKit.InsertHTMLTextAction', 'HTMLEditorKit.LinkController', 'HTMLEditorKit.Parser', 'HTMLEditorKit.ParserCallback', 'HTMLFrameHyperlinkEvent', 'HTMLWriter', 'ImageView', 'InlineView', 'ListView', 'MinimalHTMLWriter', 'ObjectView', 'Option', 'StyleSheet', 'StyleSheet.BoxPainter', 'StyleSheet.ListPainter'
+            ),
+        118 => array (
+            'ContentModel', 'DTD', 'DTDConstants', 'DocumentParser', 'ParserDelegator', 'TagElement'
+            ),
+        119 => array (
+            'RTFEditorKit'
+            ),
+        120 => array (
+            'AbstractLayoutCache', 'AbstractLayoutCache.NodeDimensions', 'DefaultMutableTreeNode', 'DefaultTreeCellEditor', 'DefaultTreeCellRenderer', 'DefaultTreeModel', 'DefaultTreeSelectionModel', 'ExpandVetoException', 'FixedHeightLayoutCache', 'MutableTreeNode', 'RowMapper', 'TreeCellEditor', 'TreeCellRenderer', 'TreeModel', 'TreeNode', 'TreePath', 'TreeSelectionModel', 'VariableHeightLayoutCache'
+            ),
+        121 => array (
+            'AbstractUndoableEdit', 'CannotRedoException', 'CannotUndoException', 'CompoundEdit', 'StateEdit', 'StateEditable', 'UndoManager', 'UndoableEdit', 'UndoableEditSupport'
+            ),
+        122 => array (
+            'InvalidTransactionException', 'TransactionRequiredException', 'TransactionRolledbackException'
+            ),
+        123 => array (
+            'XAException', 'XAResource', 'Xid'
+            ),
+        124 => array (
+            'XMLConstants'
+            ),
+        125 => array (
+            'DatatypeConfigurationException', 'DatatypeConstants', 'DatatypeConstants.Field', 'DatatypeFactory', 'Duration', 'XMLGregorianCalendar'
+            ),
+        126 => array (
+            'NamespaceContext', 'QName'
+            ),
+        127 => array (
+            'DocumentBuilder', 'DocumentBuilderFactory', 'FactoryConfigurationError', 'ParserConfigurationException', 'SAXParser', 'SAXParserFactory'
+            ),
+        128 => array (
+            'ErrorListener', 'OutputKeys', 'Result', 'Source', 'SourceLocator', 'Templates', 'Transformer', 'TransformerConfigurationException', 'TransformerException', 'TransformerFactory', 'TransformerFactoryConfigurationError', 'URIResolver'
+            ),
+        129 => array (
+            'DOMResult', 'DOMSource'
+            ),
+        130 => array (
+            'SAXResult', 'SAXSource', 'SAXTransformerFactory', 'TemplatesHandler', 'TransformerHandler'
+            ),
+        131 => array (
+            'StreamResult', 'StreamSource'
+            ),
+        132 => array (
+            'Schema', 'SchemaFactory', 'SchemaFactoryLoader', 'TypeInfoProvider', 'Validator', 'ValidatorHandler'
+            ),
+        133 => array (
+            'XPath', 'XPathConstants', 'XPathException', 'XPathExpression', 'XPathExpressionException', 'XPathFactory', 'XPathFactoryConfigurationException', 'XPathFunction', 'XPathFunctionException', 'XPathFunctionResolver', 'XPathVariableResolver'
+            ),
+        134 => array (
+            'ChannelBinding', 'GSSContext', 'GSSCredential', 'GSSException', 'GSSManager', 'GSSName', 'MessageProp', 'Oid'
+            ),
+        135 => array (
+            'ACTIVITY_COMPLETED', 'ACTIVITY_REQUIRED', 'ARG_IN', 'ARG_INOUT', 'ARG_OUT', 'Any', 'AnyHolder', 'AnySeqHolder', 'BAD_CONTEXT', 'BAD_INV_ORDER', 'BAD_OPERATION', 'BAD_PARAM', 'BAD_POLICY', 'BAD_POLICY_TYPE', 'BAD_POLICY_VALUE', 'BAD_QOS', 'BAD_TYPECODE', 'BooleanHolder', 'BooleanSeqHelper', 'BooleanSeqHolder', 'ByteHolder', 'CODESET_INCOMPATIBLE', 'COMM_FAILURE', 'CTX_RESTRICT_SCOPE', 'CharHolder', 'CharSeqHelper', 'CharSeqHolder', 'CompletionStatus', 'CompletionStatusHelper', 'ContextList', 'CurrentHolder', 'CustomMarshal', 'DATA_CONVERSION', 'DefinitionKind', 'DefinitionKindHelper', 'DomainManager', 'DomainManagerOperations', 'DoubleHolder', 'DoubleSeqHelper', 'DoubleSeqHolder', 'Environment', 'ExceptionList', 'FREE_MEM', 'FixedHolder', 'FloatHolder', 'FloatSeqHelper', 'FloatSeqHolder', 'IDLType', 'IDLTypeHelper', 'IDLTypeOperations', 'IMP_LIMIT', 'INITIALIZE', 'INTERNAL', 'INTF_REPOS', 'INVALID_ACTIVITY', 'INVALID_TRANSACTION', 'INV_FLAG', 'INV_IDENT', 'INV_OBJREF', 'INV_POLICY', 'IRObject',
+            'IRObjectOperations', 'IdentifierHelper', 'IntHolder', 'LocalObject', 'LongHolder', 'LongLongSeqHelper', 'LongLongSeqHolder', 'LongSeqHelper', 'LongSeqHolder', 'MARSHAL', 'NO_IMPLEMENT', 'NO_MEMORY', 'NO_PERMISSION', 'NO_RESOURCES', 'NO_RESPONSE', 'NVList', 'NamedValue', 'OBJECT_NOT_EXIST', 'OBJ_ADAPTER', 'OMGVMCID', 'ObjectHelper', 'ObjectHolder', 'OctetSeqHelper', 'OctetSeqHolder', 'PERSIST_STORE', 'PRIVATE_MEMBER', 'PUBLIC_MEMBER', 'ParameterMode', 'ParameterModeHelper', 'ParameterModeHolder', 'PolicyError', 'PolicyErrorCodeHelper', 'PolicyErrorHelper', 'PolicyErrorHolder', 'PolicyHelper', 'PolicyHolder', 'PolicyListHelper', 'PolicyListHolder', 'PolicyOperations', 'PolicyTypeHelper', 'PrincipalHolder', 'REBIND', 'RepositoryIdHelper', 'Request', 'ServerRequest', 'ServiceDetail', 'ServiceDetailHelper', 'ServiceInformation', 'ServiceInformationHelper', 'ServiceInformationHolder', 'SetOverrideType', 'SetOverrideTypeHelper', 'ShortHolder', 'ShortSeqHelper', 'ShortSeqHolder', 'StringHolder',
+            'StringSeqHelper', 'StringSeqHolder', 'StringValueHelper', 'StructMember', 'StructMemberHelper', 'SystemException', 'TCKind', 'TIMEOUT', 'TRANSACTION_MODE', 'TRANSACTION_REQUIRED', 'TRANSACTION_ROLLEDBACK', 'TRANSACTION_UNAVAILABLE', 'TRANSIENT', 'TypeCode', 'TypeCodeHolder', 'ULongLongSeqHelper', 'ULongLongSeqHolder', 'ULongSeqHelper', 'ULongSeqHolder', 'UNSUPPORTED_POLICY', 'UNSUPPORTED_POLICY_VALUE', 'UShortSeqHelper', 'UShortSeqHolder', 'UnionMember', 'UnionMemberHelper', 'UnknownUserException', 'UnknownUserExceptionHelper', 'UnknownUserExceptionHolder', 'UserException', 'VM_ABSTRACT', 'VM_CUSTOM', 'VM_NONE', 'VM_TRUNCATABLE', 'ValueBaseHelper', 'ValueBaseHolder', 'ValueMember', 'ValueMemberHelper', 'VersionSpecHelper', 'VisibilityHelper', 'WCharSeqHelper', 'WCharSeqHolder', 'WStringSeqHelper', 'WStringSeqHolder', 'WStringValueHelper', 'WrongTransaction', 'WrongTransactionHelper', 'WrongTransactionHolder', '_IDLTypeStub', '_PolicyStub'
+            ),
+        136 => array (
+            'Invalid', 'InvalidSeq'
+            ),
+        137 => array (
+            'BadKind'
+            ),
+        138 => array (
+            'ApplicationException', 'BoxedValueHelper', 'CustomValue', 'IDLEntity', 'IndirectionException', 'InvokeHandler', 'RemarshalException', 'ResponseHandler', 'ServantObject', 'Streamable', 'StreamableValue', 'UnknownException', 'ValueBase', 'ValueFactory', 'ValueInputStream', 'ValueOutputStream'
+            ),
+        139 => array (
+            'BindingHelper', 'BindingHolder', 'BindingIterator', 'BindingIteratorHelper', 'BindingIteratorHolder', 'BindingIteratorOperations', 'BindingIteratorPOA', 'BindingListHelper', 'BindingListHolder', 'BindingType', 'BindingTypeHelper', 'BindingTypeHolder', 'IstringHelper', 'NameComponent', 'NameComponentHelper', 'NameComponentHolder', 'NameHelper', 'NameHolder', 'NamingContext', 'NamingContextExt', 'NamingContextExtHelper', 'NamingContextExtHolder', 'NamingContextExtOperations', 'NamingContextExtPOA', 'NamingContextHelper', 'NamingContextHolder', 'NamingContextOperations', 'NamingContextPOA', '_BindingIteratorImplBase', '_BindingIteratorStub', '_NamingContextExtStub', '_NamingContextImplBase', '_NamingContextStub'
+            ),
+        140 => array (
+            'AddressHelper', 'InvalidAddress', 'InvalidAddressHelper', 'InvalidAddressHolder', 'StringNameHelper', 'URLStringHelper'
+            ),
+        141 => array (
+            'AlreadyBound', 'AlreadyBoundHelper', 'AlreadyBoundHolder', 'CannotProceed', 'CannotProceedHelper', 'CannotProceedHolder', 'InvalidNameHolder', 'NotEmpty', 'NotEmptyHelper', 'NotEmptyHolder', 'NotFound', 'NotFoundHelper', 'NotFoundHolder', 'NotFoundReason', 'NotFoundReasonHelper', 'NotFoundReasonHolder'
+            ),
+        142 => array (
+            'Parameter'
+            ),
+        143 => array (
+            'DynAnyFactory', 'DynAnyFactoryHelper', 'DynAnyFactoryOperations', 'DynAnyHelper', 'DynAnyOperations', 'DynAnySeqHelper', 'DynArrayHelper', 'DynArrayOperations', 'DynEnumHelper', 'DynEnumOperations', 'DynFixedHelper', 'DynFixedOperations', 'DynSequenceHelper', 'DynSequenceOperations', 'DynStructHelper', 'DynStructOperations', 'DynUnionHelper', 'DynUnionOperations', 'DynValueBox', 'DynValueBoxOperations', 'DynValueCommon', 'DynValueCommonOperations', 'DynValueHelper', 'DynValueOperations', 'NameDynAnyPair', 'NameDynAnyPairHelper', 'NameDynAnyPairSeqHelper', 'NameValuePairSeqHelper', '_DynAnyFactoryStub', '_DynAnyStub', '_DynArrayStub', '_DynEnumStub', '_DynFixedStub', '_DynSequenceStub', '_DynStructStub', '_DynUnionStub', '_DynValueStub'
+            ),
+        144 => array (
+            'InconsistentTypeCodeHelper'
+            ),
+        145 => array (
+            'InvalidValueHelper'
+            ),
+        146 => array (
+            'CodeSets', 'Codec', 'CodecFactory', 'CodecFactoryHelper', 'CodecFactoryOperations', 'CodecOperations', 'ComponentIdHelper', 'ENCODING_CDR_ENCAPS', 'Encoding', 'ExceptionDetailMessage', 'IOR', 'IORHelper', 'IORHolder', 'MultipleComponentProfileHelper', 'MultipleComponentProfileHolder', 'ProfileIdHelper', 'RMICustomMaxStreamFormat', 'ServiceContext', 'ServiceContextHelper', 'ServiceContextHolder', 'ServiceContextListHelper', 'ServiceContextListHolder', 'ServiceIdHelper', 'TAG_ALTERNATE_IIOP_ADDRESS', 'TAG_CODE_SETS', 'TAG_INTERNET_IOP', 'TAG_JAVA_CODEBASE', 'TAG_MULTIPLE_COMPONENTS', 'TAG_ORB_TYPE', 'TAG_POLICIES', 'TAG_RMI_CUSTOM_MAX_STREAM_FORMAT', 'TaggedComponent', 'TaggedComponentHelper', 'TaggedComponentHolder', 'TaggedProfile', 'TaggedProfileHelper', 'TaggedProfileHolder', 'TransactionService'
+            ),
+        147 => array (
+            'UnknownEncoding', 'UnknownEncodingHelper'
+            ),
+        148 => array (
+            'FormatMismatch', 'FormatMismatchHelper', 'InvalidTypeForEncoding', 'InvalidTypeForEncodingHelper'
+            ),
+        149 => array (
+            'SYNC_WITH_TRANSPORT', 'SyncScopeHelper'
+            ),
+        150 => array (
+            'ACTIVE', 'AdapterManagerIdHelper', 'AdapterNameHelper', 'AdapterStateHelper', 'ClientRequestInfo', 'ClientRequestInfoOperations', 'ClientRequestInterceptor', 'ClientRequestInterceptorOperations', 'DISCARDING', 'HOLDING', 'INACTIVE', 'IORInfo', 'IORInfoOperations', 'IORInterceptor', 'IORInterceptorOperations', 'IORInterceptor_3_0', 'IORInterceptor_3_0Helper', 'IORInterceptor_3_0Holder', 'IORInterceptor_3_0Operations', 'Interceptor', 'InterceptorOperations', 'InvalidSlot', 'InvalidSlotHelper', 'LOCATION_FORWARD', 'NON_EXISTENT', 'ORBIdHelper', 'ORBInitInfo', 'ORBInitInfoOperations', 'ORBInitializer', 'ORBInitializerOperations', 'ObjectReferenceFactory', 'ObjectReferenceFactoryHelper', 'ObjectReferenceFactoryHolder', 'ObjectReferenceTemplate', 'ObjectReferenceTemplateHelper', 'ObjectReferenceTemplateHolder', 'ObjectReferenceTemplateSeqHelper', 'ObjectReferenceTemplateSeqHolder', 'PolicyFactory', 'PolicyFactoryOperations', 'RequestInfo', 'RequestInfoOperations', 'SUCCESSFUL', 'SYSTEM_EXCEPTION',
+            'ServerIdHelper', 'ServerRequestInfo', 'ServerRequestInfoOperations', 'ServerRequestInterceptor', 'ServerRequestInterceptorOperations', 'TRANSPORT_RETRY', 'USER_EXCEPTION'
+            ),
+        151 => array (
+            'DuplicateName', 'DuplicateNameHelper'
+            ),
+        152 => array (
+            'AdapterActivator', 'AdapterActivatorOperations', 'ID_ASSIGNMENT_POLICY_ID', 'ID_UNIQUENESS_POLICY_ID', 'IMPLICIT_ACTIVATION_POLICY_ID', 'IdAssignmentPolicy', 'IdAssignmentPolicyOperations', 'IdAssignmentPolicyValue', 'IdUniquenessPolicy', 'IdUniquenessPolicyOperations', 'IdUniquenessPolicyValue', 'ImplicitActivationPolicy', 'ImplicitActivationPolicyOperations', 'ImplicitActivationPolicyValue', 'LIFESPAN_POLICY_ID', 'LifespanPolicy', 'LifespanPolicyOperations', 'LifespanPolicyValue', 'POA', 'POAHelper', 'POAManager', 'POAManagerOperations', 'POAOperations', 'REQUEST_PROCESSING_POLICY_ID', 'RequestProcessingPolicy', 'RequestProcessingPolicyOperations', 'RequestProcessingPolicyValue', 'SERVANT_RETENTION_POLICY_ID', 'Servant', 'ServantActivator', 'ServantActivatorHelper', 'ServantActivatorOperations', 'ServantActivatorPOA', 'ServantLocator', 'ServantLocatorHelper', 'ServantLocatorOperations', 'ServantLocatorPOA', 'ServantManager', 'ServantManagerOperations', 'ServantRetentionPolicy',
+            'ServantRetentionPolicyOperations', 'ServantRetentionPolicyValue', 'THREAD_POLICY_ID', 'ThreadPolicy', 'ThreadPolicyOperations', 'ThreadPolicyValue', '_ServantActivatorStub', '_ServantLocatorStub'
+            ),
+        153 => array (
+            'NoContext', 'NoContextHelper'
+            ),
+        154 => array (
+            'AdapterInactive', 'AdapterInactiveHelper', 'State'
+            ),
+        155 => array (
+            'AdapterAlreadyExists', 'AdapterAlreadyExistsHelper', 'AdapterNonExistent', 'AdapterNonExistentHelper', 'InvalidPolicy', 'InvalidPolicyHelper', 'NoServant', 'NoServantHelper', 'ObjectAlreadyActive', 'ObjectAlreadyActiveHelper', 'ObjectNotActive', 'ObjectNotActiveHelper', 'ServantAlreadyActive', 'ServantAlreadyActiveHelper', 'ServantNotActive', 'ServantNotActiveHelper', 'WrongAdapter', 'WrongAdapterHelper', 'WrongPolicy', 'WrongPolicyHelper'
+            ),
+        156 => array (
+            'CookieHolder'
+            ),
+        157 => array (
+            'RunTime', 'RunTimeOperations'
+            ),
+        158 => array (
+            '_Remote_Stub'
+            ),
+        159 => array (
+            'Attr', 'CDATASection', 'CharacterData', 'Comment', 'DOMConfiguration', 'DOMError', 'DOMErrorHandler', 'DOMException', 'DOMImplementation', 'DOMImplementationList', 'DOMImplementationSource', 'DOMStringList', 'DocumentFragment', 'DocumentType', 'EntityReference', 'NameList', 'NamedNodeMap', 'Node', 'NodeList', 'Notation', 'ProcessingInstruction', 'Text', 'TypeInfo', 'UserDataHandler'
+            ),
+        160 => array (
+            'DOMImplementationRegistry'
+            ),
+        161 => array (
+            'EventException', 'EventTarget', 'MutationEvent', 'UIEvent'
+            ),
+        162 => array (
+            'DOMImplementationLS', 'LSException', 'LSInput', 'LSLoadEvent', 'LSOutput', 'LSParser', 'LSParserFilter', 'LSProgressEvent', 'LSResourceResolver', 'LSSerializer', 'LSSerializerFilter'
+            ),
+        163 => array (
+            'DTDHandler', 'DocumentHandler', 'EntityResolver', 'ErrorHandler', 'HandlerBase', 'InputSource', 'Locator', 'SAXException', 'SAXNotRecognizedException', 'SAXNotSupportedException', 'SAXParseException', 'XMLFilter', 'XMLReader'
+            ),
+        164 => array (
+            'Attributes2', 'Attributes2Impl', 'DeclHandler', 'DefaultHandler2', 'EntityResolver2', 'LexicalHandler', 'Locator2', 'Locator2Impl'
+            ),
+        165 => array (
+            'AttributeListImpl', 'AttributesImpl', 'DefaultHandler', 'LocatorImpl', 'NamespaceSupport', 'ParserAdapter', 'ParserFactory', 'XMLFilterImpl', 'XMLReaderAdapter', 'XMLReaderFactory'
+            ),
+        /* ambiguous class names (appear in more than one package) */
+        166 => array (
+            'Annotation', 'AnySeqHelper', 'Array', 'Attribute', 'AttributeList', 'AttributeSet', 'Attributes', 'AuthenticationException', 'Binding', 'Bounds', 'Certificate', 'CertificateEncodingException', 'CertificateException', 'CertificateExpiredException', 'CertificateNotYetValidException', 'CertificateParsingException', 'ConnectException', 'ContentHandler', 'Context', 'Control', 'Current', 'CurrentHelper', 'CurrentOperations', 'DOMLocator', 'DataInputStream', 'DataOutputStream', 'Date', 'DefaultLoaderRepository', 'Delegate', 'Document', 'DocumentEvent', 'DynAny', 'DynArray', 'DynEnum', 'DynFixed', 'DynSequence', 'DynStruct', 'DynUnion', 'DynValue', 'DynamicImplementation', 'Element', 'Entity', 'Event', 'EventListener', 'FieldNameHelper', 'FileFilter', 'Formatter', 'ForwardRequest', 'ForwardRequestHelper', 'InconsistentTypeCode', 'InputStream', 'IntrospectionException', 'InvalidAttributeValueException', 'InvalidKeyException', 'InvalidName', 'InvalidNameHelper', 'InvalidValue', 'List', 'MouseEvent',
+            'NameValuePair', 'NameValuePairHelper', 'ORB', 'Object', 'ObjectIdHelper', 'ObjectImpl', 'OpenType', 'OutputStream', 'ParagraphView', 'Parser', 'Permission', 'Policy', 'Principal', 'Proxy', 'Reference', 'Statement', 'Timer', 'Timestamp', 'TypeMismatch', 'TypeMismatchHelper', 'UNKNOWN', 'UnknownHostException', 'X509Certificate'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}', '*', '&', '%', '!', ';', '<', '>', '?'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        /* all Java keywords are case sensitive */
+        1 => true, 2 => true, 3 => true, 4 => true,
+        5 => true, 6 => true, 7 => true, 8 => true, 9 => true,
+        10 => true, 11 => true, 12 => true, 13 => true, 14 => true,
+        15 => true, 16 => true, 17 => true, 18 => true, 19 => true,
+        20 => true, 21 => true, 22 => true, 23 => true, 24 => true,
+        25 => true, 26 => true, 27 => true, 28 => true, 29 => true,
+        30 => true, 31 => true, 32 => true, 33 => true, 34 => true,
+        35 => true, 36 => true, 37 => true, 38 => true, 39 => true,
+        40 => true, 41 => true, 42 => true, 43 => true, 44 => true,
+        45 => true, 46 => true, 47 => true, 48 => true, 49 => true,
+        50 => true, 51 => true, 52 => true, 53 => true, 54 => true,
+        55 => true, 56 => true, 57 => true, 58 => true, 59 => true,
+        60 => true, 61 => true, 62 => true, 63 => true, 64 => true,
+        65 => true, 66 => true, 67 => true, 68 => true, 69 => true,
+        70 => true, 71 => true, 72 => true, 73 => true, 74 => true,
+        75 => true, 76 => true, 77 => true, 78 => true, 79 => true,
+        80 => true, 81 => true, 82 => true, 83 => true, 84 => true,
+        85 => true, 86 => true, 87 => true, 88 => true, 89 => true,
+        90 => true, 91 => true, 92 => true, 93 => true, 94 => true,
+        95 => true, 96 => true, 97 => true, 98 => true, 99 => true,
+        100 => true, 101 => true, 102 => true, 103 => true, 104 => true,
+        105 => true, 106 => true, 107 => true, 108 => true, 109 => true,
+        110 => true, 111 => true, 112 => true, 113 => true, 114 => true,
+        115 => true, 116 => true, 117 => true, 118 => true, 119 => true,
+        120 => true, 121 => true, 122 => true, 123 => true, 124 => true,
+        125 => true, 126 => true, 127 => true, 128 => true, 129 => true,
+        130 => true, 131 => true, 132 => true, 133 => true, 134 => true,
+        135 => true, 136 => true, 137 => true, 138 => true, 139 => true,
+        140 => true, 141 => true, 142 => true, 143 => true, 144 => true,
+        145 => true, 146 => true, 147 => true, 148 => true, 149 => true,
+        150 => true, 151 => true, 152 => true, 153 => true, 154 => true,
+        155 => true, 156 => true, 157 => true, 158 => true, 159 => true,
+        160 => true, 161 => true, 162 => true, 163 => true, 164 => true,
+        165 => true, 166 => true
+    ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000000;  font-weight: bold;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #006600; font-weight: bold;',
+            4 => 'color: #006600; font-weight: bold;',
+            5 => 'color: #003399; font-weight: bold;',
+            6 => 'color: #003399; font-weight: bold;',
+            7 => 'color: #003399; font-weight: bold;',
+            8 => 'color: #003399; font-weight: bold;',
+            9 => 'color: #003399; font-weight: bold;',
+            10 => 'color: #003399; font-weight: bold;',
+            11 => 'color: #003399; font-weight: bold;',
+            12 => 'color: #003399; font-weight: bold;',
+            13 => 'color: #003399; font-weight: bold;',
+            14 => 'color: #003399; font-weight: bold;',
+            15 => 'color: #003399; font-weight: bold;',
+            16 => 'color: #003399; font-weight: bold;',
+            17 => 'color: #003399; font-weight: bold;',
+            18 => 'color: #003399; font-weight: bold;',
+            19 => 'color: #003399; font-weight: bold;',
+            20 => 'color: #003399; font-weight: bold;',
+            21 => 'color: #003399; font-weight: bold;',
+            22 => 'color: #003399; font-weight: bold;',
+            23 => 'color: #003399; font-weight: bold;',
+            24 => 'color: #003399; font-weight: bold;',
+            25 => 'color: #003399; font-weight: bold;',
+            26 => 'color: #003399; font-weight: bold;',
+            27 => 'color: #003399; font-weight: bold;',
+            28 => 'color: #003399; font-weight: bold;',
+            29 => 'color: #003399; font-weight: bold;',
+            30 => 'color: #003399; font-weight: bold;',
+            31 => 'color: #003399; font-weight: bold;',
+            32 => 'color: #003399; font-weight: bold;',
+            33 => 'color: #003399; font-weight: bold;',
+            34 => 'color: #003399; font-weight: bold;',
+            35 => 'color: #003399; font-weight: bold;',
+            36 => 'color: #003399; font-weight: bold;',
+            37 => 'color: #003399; font-weight: bold;',
+            38 => 'color: #003399; font-weight: bold;',
+            39 => 'color: #003399; font-weight: bold;',
+            40 => 'color: #003399; font-weight: bold;',
+            41 => 'color: #003399; font-weight: bold;',
+            42 => 'color: #003399; font-weight: bold;',
+            43 => 'color: #003399; font-weight: bold;',
+            44 => 'color: #003399; font-weight: bold;',
+            45 => 'color: #003399; font-weight: bold;',
+            46 => 'color: #003399; font-weight: bold;',
+            47 => 'color: #003399; font-weight: bold;',
+            48 => 'color: #003399; font-weight: bold;',
+            49 => 'color: #003399; font-weight: bold;',
+            50 => 'color: #003399; font-weight: bold;',
+            51 => 'color: #003399; font-weight: bold;',
+            52 => 'color: #003399; font-weight: bold;',
+            53 => 'color: #003399; font-weight: bold;',
+            54 => 'color: #003399; font-weight: bold;',
+            55 => 'color: #003399; font-weight: bold;',
+            56 => 'color: #003399; font-weight: bold;',
+            57 => 'color: #003399; font-weight: bold;',
+            58 => 'color: #003399; font-weight: bold;',
+            59 => 'color: #003399; font-weight: bold;',
+            60 => 'color: #003399; font-weight: bold;',
+            61 => 'color: #003399; font-weight: bold;',
+            62 => 'color: #003399; font-weight: bold;',
+            63 => 'color: #003399; font-weight: bold;',
+            64 => 'color: #003399; font-weight: bold;',
+            65 => 'color: #003399; font-weight: bold;',
+            66 => 'color: #003399; font-weight: bold;',
+            67 => 'color: #003399; font-weight: bold;',
+            68 => 'color: #003399; font-weight: bold;',
+            69 => 'color: #003399; font-weight: bold;',
+            70 => 'color: #003399; font-weight: bold;',
+            71 => 'color: #003399; font-weight: bold;',
+            72 => 'color: #003399; font-weight: bold;',
+            73 => 'color: #003399; font-weight: bold;',
+            74 => 'color: #003399; font-weight: bold;',
+            75 => 'color: #003399; font-weight: bold;',
+            76 => 'color: #003399; font-weight: bold;',
+            77 => 'color: #003399; font-weight: bold;',
+            78 => 'color: #003399; font-weight: bold;',
+            79 => 'color: #003399; font-weight: bold;',
+            80 => 'color: #003399; font-weight: bold;',
+            81 => 'color: #003399; font-weight: bold;',
+            82 => 'color: #003399; font-weight: bold;',
+            83 => 'color: #003399; font-weight: bold;',
+            84 => 'color: #003399; font-weight: bold;',
+            85 => 'color: #003399; font-weight: bold;',
+            86 => 'color: #003399; font-weight: bold;',
+            87 => 'color: #003399; font-weight: bold;',
+            88 => 'color: #003399; font-weight: bold;',
+            89 => 'color: #003399; font-weight: bold;',
+            90 => 'color: #003399; font-weight: bold;',
+            91 => 'color: #003399; font-weight: bold;',
+            92 => 'color: #003399; font-weight: bold;',
+            93 => 'color: #003399; font-weight: bold;',
+            94 => 'color: #003399; font-weight: bold;',
+            95 => 'color: #003399; font-weight: bold;',
+            96 => 'color: #003399; font-weight: bold;',
+            97 => 'color: #003399; font-weight: bold;',
+            98 => 'color: #003399; font-weight: bold;',
+            99 => 'color: #003399; font-weight: bold;',
+            100 => 'color: #003399; font-weight: bold;',
+            101 => 'color: #003399; font-weight: bold;',
+            102 => 'color: #003399; font-weight: bold;',
+            103 => 'color: #003399; font-weight: bold;',
+            104 => 'color: #003399; font-weight: bold;',
+            105 => 'color: #003399; font-weight: bold;',
+            106 => 'color: #003399; font-weight: bold;',
+            107 => 'color: #003399; font-weight: bold;',
+            108 => 'color: #003399; font-weight: bold;',
+            109 => 'color: #003399; font-weight: bold;',
+            110 => 'color: #003399; font-weight: bold;',
+            111 => 'color: #003399; font-weight: bold;',
+            112 => 'color: #003399; font-weight: bold;',
+            113 => 'color: #003399; font-weight: bold;',
+            114 => 'color: #003399; font-weight: bold;',
+            115 => 'color: #003399; font-weight: bold;',
+            116 => 'color: #003399; font-weight: bold;',
+            117 => 'color: #003399; font-weight: bold;',
+            118 => 'color: #003399; font-weight: bold;',
+            119 => 'color: #003399; font-weight: bold;',
+            120 => 'color: #003399; font-weight: bold;',
+            121 => 'color: #003399; font-weight: bold;',
+            122 => 'color: #003399; font-weight: bold;',
+            123 => 'color: #003399; font-weight: bold;',
+            124 => 'color: #003399; font-weight: bold;',
+            125 => 'color: #003399; font-weight: bold;',
+            126 => 'color: #003399; font-weight: bold;',
+            127 => 'color: #003399; font-weight: bold;',
+            128 => 'color: #003399; font-weight: bold;',
+            129 => 'color: #003399; font-weight: bold;',
+            130 => 'color: #003399; font-weight: bold;',
+            131 => 'color: #003399; font-weight: bold;',
+            132 => 'color: #003399; font-weight: bold;',
+            133 => 'color: #003399; font-weight: bold;',
+            134 => 'color: #003399; font-weight: bold;',
+            135 => 'color: #003399; font-weight: bold;',
+            136 => 'color: #003399; font-weight: bold;',
+            137 => 'color: #003399; font-weight: bold;',
+            138 => 'color: #003399; font-weight: bold;',
+            139 => 'color: #003399; font-weight: bold;',
+            140 => 'color: #003399; font-weight: bold;',
+            141 => 'color: #003399; font-weight: bold;',
+            142 => 'color: #003399; font-weight: bold;',
+            143 => 'color: #003399; font-weight: bold;',
+            144 => 'color: #003399; font-weight: bold;',
+            145 => 'color: #003399; font-weight: bold;',
+            146 => 'color: #003399; font-weight: bold;',
+            147 => 'color: #003399; font-weight: bold;',
+            148 => 'color: #003399; font-weight: bold;',
+            149 => 'color: #003399; font-weight: bold;',
+            150 => 'color: #003399; font-weight: bold;',
+            151 => 'color: #003399; font-weight: bold;',
+            152 => 'color: #003399; font-weight: bold;',
+            153 => 'color: #003399; font-weight: bold;',
+            154 => 'color: #003399; font-weight: bold;',
+            155 => 'color: #003399; font-weight: bold;',
+            156 => 'color: #003399; font-weight: bold;',
+            157 => 'color: #003399; font-weight: bold;',
+            158 => 'color: #003399; font-weight: bold;',
+            159 => 'color: #003399; font-weight: bold;',
+            160 => 'color: #003399; font-weight: bold;',
+            161 => 'color: #003399; font-weight: bold;',
+            162 => 'color: #003399; font-weight: bold;',
+            163 => 'color: #003399; font-weight: bold;',
+            164 => 'color: #003399; font-weight: bold;',
+            165 => 'color: #003399; font-weight: bold;',
+            166 => 'color: #003399; font-weight: bold;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #666666; font-style: italic;',
+            2 => 'color: #006699;',
+            3 => 'color: #008000; font-style: italic; font-weight: bold;',
+            'MULTI' => 'color: #666666; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #009900;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #0000ff;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006633;',
+            2 => 'color: #006633;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #339933;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => '',
+        5 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/applet/{FNAME}.html',
+        6 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/awt/{FNAME}.html',
+        7 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/awt/color/{FNAME}.html',
+        8 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/awt/datatransfer/{FNAME}.html',
+        9 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/awt/dnd/{FNAME}.html',
+        10 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/awt/event/{FNAME}.html',
+        11 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/awt/font/{FNAME}.html',
+        12 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/awt/geom/{FNAME}.html',
+        13 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/awt/im/{FNAME}.html',
+        14 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/awt/im/spi/{FNAME}.html',
+        15 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/awt/image/{FNAME}.html',
+        16 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/awt/image/renderable/{FNAME}.html',
+        17 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/awt/print/{FNAME}.html',
+        18 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/beans/{FNAME}.html',
+        19 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/beans/beancontext/{FNAME}.html',
+        20 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/io/{FNAME}.html',
+        21 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/lang/{FNAME}.html',
+        22 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/lang/annotation/{FNAME}.html',
+        23 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/lang/instrument/{FNAME}.html',
+        24 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/lang/management/{FNAME}.html',
+        25 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ref/{FNAME}.html',
+        26 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/{FNAME}.html',
+        27 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/math/{FNAME}.html',
+        28 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/net/{FNAME}.html',
+        29 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/nio/{FNAME}.html',
+        30 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/nio/channels/{FNAME}.html',
+        31 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/nio/channels/spi/{FNAME}.html',
+        32 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/nio/charset/{FNAME}.html',
+        33 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/nio/charset/spi/{FNAME}.html',
+        34 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/rmi/{FNAME}.html',
+        35 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/rmi/activation/{FNAME}.html',
+        36 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/rmi/dgc/{FNAME}.html',
+        37 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/rmi/registry/{FNAME}.html',
+        38 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/rmi/server/{FNAME}.html',
+        39 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/security/{FNAME}.html',
+        40 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/security/acl/{FNAME}.html',
+        41 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/security/cert/{FNAME}.html',
+        42 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/security/interfaces/{FNAME}.html',
+        43 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/security/spec/{FNAME}.html',
+        44 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/sql/{FNAME}.html',
+        45 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/text/{FNAME}.html',
+        46 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/util/{FNAME}.html',
+        47 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/{FNAME}.html',
+        48 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/atomic/{FNAME}.html',
+        49 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/locks/{FNAME}.html',
+        50 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/util/jar/{FNAME}.html',
+        51 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/util/logging/{FNAME}.html',
+        52 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/util/prefs/{FNAME}.html',
+        53 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/{FNAME}.html',
+        54 => 'http://java.sun.com/j2se/1.5.0/docs/api/java/util/zip/{FNAME}.html',
+        55 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/accessibility/{FNAME}.html',
+        56 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/activity/{FNAME}.html',
+        57 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/crypto/{FNAME}.html',
+        58 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/crypto/interfaces/{FNAME}.html',
+        59 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/crypto/spec/{FNAME}.html',
+        60 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/imageio/{FNAME}.html',
+        61 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/imageio/event/{FNAME}.html',
+        62 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/imageio/metadata/{FNAME}.html',
+        63 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/imageio/plugins/bmp/{FNAME}.html',
+        64 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/imageio/plugins/jpeg/{FNAME}.html',
+        65 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/imageio/spi/{FNAME}.html',
+        66 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/imageio/stream/{FNAME}.html',
+        67 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/management/{FNAME}.html',
+        68 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/management/loading/{FNAME}.html',
+        69 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/management/modelmbean/{FNAME}.html',
+        70 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/management/monitor/{FNAME}.html',
+        71 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/management/openmbean/{FNAME}.html',
+        72 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/management/relation/{FNAME}.html',
+        73 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/management/remote/{FNAME}.html',
+        74 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/management/remote/rmi/{FNAME}.html',
+        75 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/management/timer/{FNAME}.html',
+        76 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/naming/{FNAME}.html',
+        77 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/naming/directory/{FNAME}.html',
+        78 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/naming/event/{FNAME}.html',
+        79 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/naming/ldap/{FNAME}.html',
+        80 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/naming/spi/{FNAME}.html',
+        81 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/net/{FNAME}.html',
+        82 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/net/ssl/{FNAME}.html',
+        83 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/print/{FNAME}.html',
+        84 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/print/attribute/{FNAME}.html',
+        85 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/print/attribute/standard/{FNAME}.html',
+        86 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/print/event/{FNAME}.html',
+        87 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/rmi/{FNAME}.html',
+        88 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/rmi/CORBA/{FNAME}.html',
+        89 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/rmi/ssl/{FNAME}.html',
+        90 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/security/auth/{FNAME}.html',
+        91 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/security/auth/callback/{FNAME}.html',
+        92 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/security/auth/kerberos/{FNAME}.html',
+        93 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/security/auth/login/{FNAME}.html',
+        94 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/security/auth/spi/{FNAME}.html',
+        95 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/security/auth/x500/{FNAME}.html',
+        96 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/security/sasl/{FNAME}.html',
+        97 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/sound/midi/{FNAME}.html',
+        98 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/sound/midi/spi/{FNAME}.html',
+        99 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/sound/sampled/{FNAME}.html',
+        100 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/sound/sampled/spi/{FNAME}.html',
+        101 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/sql/{FNAME}.html',
+        102 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/sql/rowset/{FNAME}.html',
+        103 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/sql/rowset/serial/{FNAME}.html',
+        104 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/sql/rowset/spi/{FNAME}.html',
+        105 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/{FNAME}.html',
+        106 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/border/{FNAME}.html',
+        107 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/colorchooser/{FNAME}.html',
+        108 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/event/{FNAME}.html',
+        109 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/filechooser/{FNAME}.html',
+        110 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/plaf/{FNAME}.html',
+        111 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/plaf/basic/{FNAME}.html',
+        112 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/plaf/metal/{FNAME}.html',
+        113 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/plaf/multi/{FNAME}.html',
+        114 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/plaf/synth/{FNAME}.html',
+        115 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/table/{FNAME}.html',
+        116 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/text/{FNAME}.html',
+        117 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/text/html/{FNAME}.html',
+        118 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/text/html/parser/{FNAME}.html',
+        119 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/text/rtf/{FNAME}.html',
+        120 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/tree/{FNAME}.html',
+        121 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/undo/{FNAME}.html',
+        122 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/transaction/{FNAME}.html',
+        123 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/transaction/xa/{FNAME}.html',
+        124 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/xml/{FNAME}.html',
+        125 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/xml/datatype/{FNAME}.html',
+        126 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/xml/namespace/{FNAME}.html',
+        127 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/xml/parsers/{FNAME}.html',
+        128 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/xml/transform/{FNAME}.html',
+        129 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/xml/transform/dom/{FNAME}.html',
+        130 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/xml/transform/sax/{FNAME}.html',
+        131 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/xml/transform/stream/{FNAME}.html',
+        132 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/xml/validation/{FNAME}.html',
+        133 => 'http://java.sun.com/j2se/1.5.0/docs/api/javax/xml/xpath/{FNAME}.html',
+        134 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/ietf/jgss/{FNAME}.html',
+        135 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/CORBA/{FNAME}.html',
+        136 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/CORBA/DynAnyPackage/{FNAME}.html',
+        137 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/CORBA/TypeCodePackage/{FNAME}.html',
+        138 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/CORBA/portable/{FNAME}.html',
+        139 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/CosNaming/{FNAME}.html',
+        140 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/CosNaming/NamingContextExtPackage/{FNAME}.html',
+        141 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/CosNaming/NamingContextPackage/{FNAME}.html',
+        142 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/Dynamic/{FNAME}.html',
+        143 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/DynamicAny/{FNAME}.html',
+        144 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/DynamicAny/DynAnyFactoryPackage/{FNAME}.html',
+        145 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/DynamicAny/DynAnyPackage/{FNAME}.html',
+        146 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/IOP/{FNAME}.html',
+        147 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/IOP/CodecFactoryPackage/{FNAME}.html',
+        148 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/IOP/CodecPackage/{FNAME}.html',
+        149 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/Messaging/{FNAME}.html',
+        150 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/PortableInterceptor/{FNAME}.html',
+        151 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/PortableInterceptor/ORBInitInfoPackage/{FNAME}.html',
+        152 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/PortableServer/{FNAME}.html',
+        153 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/PortableServer/CurrentPackage/{FNAME}.html',
+        154 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/PortableServer/POAManagerPackage/{FNAME}.html',
+        155 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/PortableServer/POAPackage/{FNAME}.html',
+        156 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/PortableServer/ServantLocatorPackage/{FNAME}.html',
+        157 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/SendingContext/{FNAME}.html',
+        158 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/omg/stub/java/rmi/{FNAME}.html',
+        159 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/w3c/dom/{FNAME}.html',
+        160 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/w3c/dom/bootstrap/{FNAME}.html',
+        161 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/w3c/dom/events/{FNAME}.html',
+        162 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/w3c/dom/ls/{FNAME}.html',
+        163 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/xml/sax/{FNAME}.html',
+        164 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/xml/sax/ext/{FNAME}.html',
+        165 => 'http://java.sun.com/j2se/1.5.0/docs/api/org/xml/sax/helpers/{FNAME}.html',
+        /* ambiguous class names (appear in more than one package) */
+        166 => 'http://www.google.com/search?sitesearch=java.sun.com&amp;q=allinurl%3Aj2se%2F1+5+0%2Fdocs%2Fapi+{FNAME}'
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        /* Java does not use '::' */
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/javascript.php b/examples/includes/geshi/geshi/javascript.php
new file mode 100644 (file)
index 0000000..1232a8a
--- /dev/null
@@ -0,0 +1,150 @@
+<?php
+/*************************************************************************************
+ * javascript.php
+ * --------------
+ * Author: Ben Keen (ben.keen@gmail.com)
+ * Copyright: (c) 2004 Ben Keen (ben.keen@gmail.com), Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/06/20
+ *
+ * JavaScript language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *  -  Added description of extra language features (SF#1970248)
+ * 2004/11/27 (1.0.1)
+ *  -  Added support for multiple object splitters
+ * 2004/10/27 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Javascript',
+    'COMMENT_SINGLE' => array(1 => '//'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    //Regular Expressions
+    'COMMENT_REGEXP' => array(2 => "/(?<=[\\s^])s\\/(?:\\\\.|(?!\n)[^\\/\\\\])+\\/(?:\\\\.|(?!\n)[^\\/\\\\])+\\/[gimsu]*(?=[\\s$\\.\\;])|(?<=[\\s^(=])m?\\/(?:\\\\.|(?!\n)[^\\/\\\\])+\\/[gimsu]*(?=[\\s$\\.\\,\\;\\)])/iU"),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'as', 'break', 'case', 'catch', 'continue', 'decodeURI', 'delete', 'do',
+            'else', 'encodeURI', 'eval', 'finally', 'for', 'if', 'in', 'is', 'item',
+            'instanceof', 'return', 'switch', 'this', 'throw', 'try', 'typeof', 'void',
+            'while', 'write', 'with'
+            ),
+        2 => array(
+            'class', 'const', 'default', 'debugger', 'export', 'extends', 'false',
+            'function', 'import', 'namespace', 'new', 'null', 'package', 'private',
+            'protected', 'public', 'super', 'true', 'use', 'var'
+            ),
+        3 => array(
+            // common functions for Window object
+            'alert', 'back', 'blur', 'close', 'confirm', 'focus', 'forward', 'home',
+            'name', 'navigate', 'onblur', 'onerror', 'onfocus', 'onload', 'onmove',
+            'onresize', 'onunload', 'open', 'print', 'prompt', 'scroll', 'status',
+            'stop',
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}',
+        '+', '-', '*', '/', '%',
+        '!', '@', '&', '|', '^',
+        '<', '>', '=',
+        ',', ';', '?', ':'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000066; font-weight: bold;',
+            2 => 'color: #003366; font-weight: bold;',
+            3 => 'color: #000066;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #006600; font-style: italic;',
+            2 => 'color: #009966; font-style: italic;',
+            'MULTI' => 'color: #006600; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #009900;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #3366CC;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #CC0000;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #660066;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #339933;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            0 => '',
+            1 => '',
+            2 => '',
+            3 => ''
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_MAYBE,
+    'SCRIPT_DELIMITERS' => array(
+        0 => array(
+            '<script type="text/javascript">' => '</script>'
+            ),
+        1 => array(
+            '<script language="javascript">' => '</script>'
+            )
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        0 => true,
+        1 => true
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/kixtart.php b/examples/includes/geshi/geshi/kixtart.php
new file mode 100644 (file)
index 0000000..3b4dc4c
--- /dev/null
@@ -0,0 +1,329 @@
+<?php
+/*************************************************************************************
+ * kixtart.php
+ * --------
+ * Author: Riley McArdle (riley@glyff.net)
+ * Copyright: (c) 2007 Riley McArdle (http://www.glyff.net/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2007/08/31
+ *
+ * PHP language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2007/08/31 (1.0.7.22)
+ *  -  First Release
+ *
+ * TODO (updated 2007/08/31)
+ * -------------------------
+ * *
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'KiXtart',
+    'COMMENT_SINGLE' => array(1 => ';'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            'While', 'Loop',
+            'Use',
+            'Small',
+            'Sleep',
+            'Shell',
+            'SetTime',
+            'SetM',
+            'SetL',
+            'Set',
+            'Select', 'Case',
+            'Run',
+            'Return',
+            'Redim',
+            'RD',
+            'Quit',
+            'Play',
+            'Move',
+            'MD',
+            'Include',
+            'If', 'Else', 'Endif',
+            'GoTo',
+            'GoSub',
+            'Go',
+            'Global',
+            'GetS',
+            'Get',
+            'Function', 'Endfunction',
+            'For', 'Next',
+            'Each',
+            'FlushKb',
+            'Exit',
+            'Do', 'Until',
+            'Display',
+            'Dim',
+            'Del',
+            'Debug',
+            'Copy',
+            'Cookie1',
+            'Color',
+            'CLS',
+            'CD',
+            'Call',
+            'Break',
+            'Big',
+            'Beep',
+            ),
+        2 => array(
+            '@Address',
+            '@Build',
+            '@Color',
+            '@Comment',
+            '@CPU',
+            '@CRLF',
+            '@CSD',
+            '@CurDir',
+            '@Date',
+            '@Day',
+            '@Domain',
+            '@DOS',
+            '@Error',
+            '@FullName',
+            '@HomeDir',
+            '@HomeDrive',
+            '@HomeShr',
+            '@HostName',
+            '@InWin',
+            '@IPaddressX',
+            '@KiX',
+            '@LanRoot',
+            '@LDomain',
+            '@LDrive',
+            '@LM',
+            '@LogonMode',
+            '@LongHomeDir',
+            '@LServer',
+            '@MaxPWAge',
+            '@MDayNo',
+            '@MHz',
+            '@MonthNo',
+            '@Month',
+            '@MSecs',
+            '@OnWoW64',
+            '@PID',
+            '@PrimaryGroup',
+            '@Priv',
+            '@ProductSuite',
+            '@ProductType',
+            '@PWAge',
+            '@RAS',
+            '@Result',
+            '@RServer',
+            '@ScriptDir',
+            '@ScriptExe',
+            '@ScriptName',
+            '@SError',
+            '@SID',
+            '@Site',
+            '@StartDir',
+            '@SysLang',
+            '@Ticks',
+            '@Time',
+            '@TsSession',
+            '@UserID',
+            '@UserLang',
+            '@WDayNo',
+            '@Wksta',
+            '@WUserID',
+            '@YDayNo',
+            '@Year',
+            ),
+        3 => array(
+            'WriteValue',
+            'WriteProfileString',
+            'WriteLine',
+            'VarTypeName',
+            'VarType',
+            'Val',
+            'UnloadHive',
+            'UCase',
+            'Ubound',
+            'Trim',
+            'Substr',
+            'SRnd',
+            'Split',
+            'SidToName',
+            'ShutDown',
+            'ShowProgramGroup',
+            'SetWallpaper',
+            'SetTitle',
+            'SetSystemState',
+            'SetOption',
+            'SetFocus',
+            'SetFileAttr',
+            'SetDefaultPrinter',
+            'SetConsole',
+            'SetAscii',
+            'SendMessage',
+            'SendKeys',
+            'SaveKey',
+            'RTrim',
+            'Round',
+            'Rnd',
+            'Right',
+            'RedirectOutput',
+            'ReadValue',
+            'ReadType',
+            'ReadProfileString',
+            'ReadLine',
+            'Open',
+            'MessageBox',
+            'MemorySize',
+            'LTrim',
+            'Logoff',
+            'LogEvent',
+            'LoadKey',
+            'LoadHive',
+            'Len',
+            'Left',
+            'LCase',
+            'KeyExist',
+            'KbHit',
+            'Join',
+            'IsDeclared',
+            'Int',
+            'InStrRev',
+            'InStr',
+            'InGroup',
+            'IIF',
+            'GetObject',
+            'GetFileVersion',
+            'GetFileTime',
+            'GetFileSize',
+            'GetFileAttr',
+            'GetDiskSpace',
+            'FreeFileHandle',
+            'FormatNumber',
+            'Fix',
+            'ExpandEnvironmentVars',
+            'Exist',
+            'Execute',
+            'EnumValue',
+            'EnumLocalGroup',
+            'EnumKey',
+            'EnumIpInfo',
+            'EnumGroup',
+            'Dir',
+            'DelValue',
+            'DelTree',
+            'DelProgramItem',
+            'DelProgramGroup',
+            'DelPrinterConnection',
+            'DelKey',
+            'DecToHex',
+            'CStr',
+            'CreateObject',
+            'CompareFileTimes',
+            'Close',
+            'ClearEventLog',
+            'CInt',
+            'Chr',
+            'CDbl',
+            'Box',
+            'BackupEventLog',
+            'At',
+            'AScan',
+            'Asc',
+            'AddProgramItem',
+            'AddProgramGroup',
+            'AddPrinterConnection',
+            'AddKey',
+            'Abs'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '?', ':', '+', '-', '*', '/', '&', '|', '^', '~', '<', '>', '='
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #000066;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006600;',
+            2 => 'color: #006600;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => 'http://www.kixtart.org/manual/Commands/{FNAMEL}.htm',
+        2 => '',
+        3 => 'http://www.kixtart.org/manual/Functions/{FNAMEL}.htm'
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        0 => true,
+        1 => true,
+        2 => true,
+        3 => true
+        ),
+    'TAB_WIDTH' => 4
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/klonec.php b/examples/includes/geshi/geshi/klonec.php
new file mode 100644 (file)
index 0000000..599f56b
--- /dev/null
@@ -0,0 +1,282 @@
+<?php
+/*************************************************************************************
+ * klonec.php
+ * --------
+ * Author: AUGER Mickael
+ * Copyright: Synchronic
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/04/16
+ *
+ * KLone with C language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/04/16 (1.0.8)
+ *  -  First Release
+ *
+ * TODO (updated 2008/04/16)
+ * -------------------------
+ * A tester et a completer si besoin
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'KLone C',
+    'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),//#pour precede les include de C
+    'COMMENT_MULTI' => array('/*' => '*/', '<!--' => '-->' ),//comentaires C et KLone suivi de ceux pour HTML
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(//mots-cles C
+            'if', 'return', 'while', 'case', 'class', 'continue', 'default',
+            'do', 'else', 'for', 'switch', 'goto',
+            'null', 'break', 'true', 'enum', 'extern', 'inline', 'false'
+            ),
+        2 => array(//mots-cles KLone
+            'out', 'request', 'response',
+            ),
+        3 => array(//fonctions C usuelles
+            'printf', 'malloc', 'fopen', 'fclose', 'free', 'fputs', 'fgets', 'feof', 'fwrite',
+            'perror', 'ferror', 'qsort', 'stats', 'sscanf', 'scanf',
+            'strdup', 'strcpy', 'strcmp', 'strncpy', 'strcasecmp', 'cat', 'strcat', 'strstr',
+            'strlen', 'strtof', 'strtod', 'strtok', 'towlower', 'towupper',
+            'cd', 'system', 'exit', 'exec', 'fork', 'vfork', 'kill', 'signal', 'syslog',
+            'usleep', 'utime', 'wait', 'waitpid', 'waitid',
+            'ceil', 'eval', 'round', 'floor',
+            'atoi', 'atol', 'abs', 'cos', 'sin', 'tan', 'acos', 'asin', 'atan', 'exp',
+            'time', 'ctime', 'localtime', 'asctime', 'gmtime', 'difftime', 'date'
+            ),
+        4 => array(//fonctions KLone usuelles
+            'request_get_cookies', 'request_get_cookie', 'request_get_args', 'request_get_arg',
+            'request_io', 'request_get_uri', 'request_get_filename', 'request_get_query_string', 'request_get_path_info',
+            'request_get_if_modified_since', 'request_get_http', 'request_get_client_request',
+            'request_get_content_length', 'request_get_uploads', 'request_get_uploaded_file',
+            'request_get_method', 'request_get_protocol', 'request_get_resolved_filename',
+            'request_get_resolved_path_info', 'request_get_addr', 'request_get_peer_addr',
+            'request_get_header', 'request_get_field', 'request_get_field_value',
+            'response_set_content_encoding', 'response_disable_caching', 'response_enable_caching',
+            'response_set_cookie', 'response_set_method', 'response_get_method',
+            'response_print_header', 'response_set_field', 'response_del_field',
+            'response_set_content_type', 'response_set_date', 'response_set_last_modified',
+            'response_set_content_length', 'response_get_status', 'response_get_header',
+            'response_io', 'response_redirect', 'response_set_status',
+            'session_get_vars', 'session_get', 'session_set', 'session_age', 'session_clean', 'session_del',
+            'io_type', 'io_pipe', 'io_dup', 'io_copy', 'io_seek', 'io_tell', 'io_close',
+            'io_free', 'io_read', 'io_printf', 'io_flush', 'io_write', 'io_putc', 'io_getc',
+            'io_get_until', 'io_gets', 'io_codec_add_head', 'io_codec_add_tail',
+            'io_codecs_remove', 'io_name_set', 'io_name_get'
+            ),
+        5 => array(//types C
+            'auto', 'char', 'const', 'double',  'float', 'int', 'long',
+            'register', 'short', 'signed', 'sizeof', 'static', 'string', 'struct',
+            'typedef', 'union', 'unsigned', 'void', 'volatile',
+            'wchar_t', 'time_t', 'FILE'
+            ),
+        6 => array(//mots-cles HTML
+            'a', 'abbr', 'acronym', 'address', 'applet',
+
+            'base', 'basefont', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'b',
+
+            'caption', 'center', 'cite', 'code', 'colgroup', 'col',
+
+            'dd', 'del', 'dfn', 'dir', 'div', 'dl', 'dt',
+
+            'em',
+
+            'fieldset', 'font', 'form', 'frame', 'frameset',
+
+            'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'hr', 'html',
+
+            'iframe', 'ilayer', 'img', 'input', 'ins', 'isindex', 'i',
+
+            'kbd',
+
+            'label', 'legend', 'link', 'li',
+
+            'map', 'meta',
+
+            'noframes', 'noscript',
+
+            'object', 'ol', 'optgroup', 'option',
+
+            'param', 'pre', 'p',
+
+            'q',
+
+            'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'style', 'sub', 'sup', 's',
+
+            'table', 'tbody', 'td', 'textarea', 'text', 'tfoot', 'thead', 'th', 'title', 'tr', 'tt',
+
+            'ul', 'u',
+
+            'var',
+            ),
+        7 => array(//autres mots-cles HTML
+            'abbr', 'accept-charset', 'accept', 'accesskey', 'action', 'align', 'alink', 'alt', 'archive', 'axis',
+            'background', 'bgcolor', 'border',
+            'cellpadding', 'cellspacing', 'char', 'charoff', 'charset', 'checked', 'cite', 'class', 'classid', 'clear', 'code', 'codebase', 'codetype', 'color', 'cols', 'colspan', 'compact', 'content', 'coords',
+            'data', 'datetime', 'declare', 'defer', 'dir', 'disabled',
+            'enctype',
+            'face', 'for', 'frame', 'frameborder',
+            'headers', 'height', 'href', 'hreflang', 'hspace', 'http-equiv',
+            'id', 'ismap',
+            'label', 'lang', 'language', 'link', 'longdesc',
+            'marginheight', 'marginwidth', 'maxlength', 'media', 'method', 'multiple',
+            'name', 'nohref', 'noresize', 'noshade', 'nowrap',
+            'object', 'onblur', 'onchange', 'onclick', 'ondblclick', 'onfocus', 'onkeydown', 'onkeypress', 'onkeyup', 'onload', 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onreset', 'onselect', 'onsubmit', 'onunload',
+            'profile', 'prompt',
+            'readonly', 'rel', 'rev', 'rowspan', 'rows', 'rules',
+            'scheme', 'scope', 'scrolling', 'selected', 'shape', 'size', 'span', 'src', 'standby', 'start', 'style', 'summary',
+            'tabindex', 'target', 'text', 'title', 'type',
+            'usemap',
+            'valign', 'value', 'valuetype', 'version', 'vlink', 'vspace',
+            'width'
+            )
+        ),
+    'SYMBOLS' => array(
+        1 => array(
+            '<%=', '<%!', '<%', '%>'
+            ),
+        0 => array(
+            '(', ')', '[', ']', '{', '}',
+            '!', '%', '&', '|', '/',
+            '<', '>',
+            '=', '-', '+', '*',
+            '.', ':', ',', ';', '^'
+            )
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        5 => false,
+        6 => false,
+        7 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100; font-weight: bold;',//pour les mots-cles C
+            2 => 'color: #000000; font-weight: bold;',//pour les mots-cles KLone
+            3 => 'color: #6600FF;',//pour les fonctions C
+            4 => 'color: #6600FF;',//pour les fonctions Klone
+            5 => 'color: #0099FF; font-weight: bold;',//pour les types C
+            6 => 'color: #990099; font-weight: bold;',//pour les mots-cles HTML
+            7 => 'color: #000066;'//pour les autres mots-cles HTML
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',//commentaire sur une ligne C et KLone
+            2 => 'color: #339933;',//pour les #... en C
+            'MULTI' => 'color: #808080; font-style: italic;'//commentaire sur plusieurs lignes C et KLone
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000000;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006600;',
+            2 => 'color: #006600;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000000;',
+            1 => 'color: #000000; font-weight: bold;'
+            ),
+        'REGEXPS' => array(),
+        'SCRIPT' => array(
+            0 => 'background-color:#ffccff; font-weight: bold; color:#000000;',
+            1 => '',
+            2 => '',
+            3 => 'color: #00bbdd; font-weight: bold;',
+            4 => 'color: #ddbb00;',
+            5 => 'color: #009900;'
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => 'http://www.opengroup.org/onlinepubs/009695399/functions/{FNAMEL}.html',
+        4 => 'http://www.koanlogic.com/klone/api/html/globals.html',
+        5 => '',
+        6 => 'http://december.com/html/4/element/{FNAMEL}.html',
+        7 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.',
+        2 => '::'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_ALWAYS,
+    'SCRIPT_DELIMITERS' => array(
+        //delimiteurs pour KLone
+        0 => array(
+            '<%=' => '%>'
+            ),
+        1 => array(
+            '<%!' => '%>'
+            ),
+        2 => array(
+            '<%' => '%>'
+            ),
+        //delimiteur pour HTML
+        3 => array(
+            '<!DOCTYPE' => '>'
+            ),
+        4 => array(
+            '&' => ';'
+            ),
+        5 => array(
+            '<' => '>'
+            )
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        0 => false,
+        1 => true,
+        2 => true,
+        3 => false,
+        4 => false,
+        5 => true
+        ),
+    'TAB_WIDTH' => 4,
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            6 => array(
+                'DISALLOWED_BEFORE' => '(?<=&lt;|&lt;\/)',
+                'DISALLOWED_AFTER' => '(?=\s|\/|&gt;)',
+            ),
+            7 => array(
+                'DISALLOWED_AFTER' => '(?=\s*=)',
+            )
+        )
+    )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/klonecpp.php b/examples/includes/geshi/geshi/klonecpp.php
new file mode 100644 (file)
index 0000000..7be4f40
--- /dev/null
@@ -0,0 +1,310 @@
+<?php
+/*************************************************************************************
+ * klonecpp.php
+ * --------
+ * Author: AUGER Mickael
+ * Copyright: Synchronic
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/04/16
+ *
+ * KLone with C++ language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/04/16 (1.0.8)
+ *  -  First Release
+ *
+ * TODO (updated 2008/04/16)
+ * -------------------------
+ * A tester et a completer si besoin
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'KLone C++',
+    'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),//#pour precede les include de C
+    'COMMENT_MULTI' => array('/*' => '*/', '<!--' => '-->' ),//comentaires C et KLone suivi de ceux pour HTML
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(//mots-cles C++
+            'if', 'return', 'while', 'case', 'continue', 'default',
+            'do', 'else', 'for', 'switch', 'goto',
+            'break', 'true', 'enum', 'extern', 'inline', 'false',
+            'errno', 'stdin', 'stdout', 'stderr',
+            'virtual', 'public', 'private', 'protected', 'template', 'using', 'namespace',
+            'try', 'catch', 'dynamic_cast', 'const_cast', 'reinterpret_cast',
+            'static_cast', 'explicit', 'friend', 'typename', 'typeid', 'class',
+            'EDOM', 'ERANGE', 'FLT_RADIX', 'FLT_ROUNDS', 'FLT_DIG', 'DBL_DIG', 'LDBL_DIG',
+            'FLT_EPSILON', 'DBL_EPSILON', 'LDBL_EPSILON', 'FLT_MANT_DIG', 'DBL_MANT_DIG',
+            'LDBL_MANT_DIG', 'FLT_MAX', 'DBL_MAX', 'LDBL_MAX', 'FLT_MAX_EXP', 'DBL_MAX_EXP',
+            'LDBL_MAX_EXP', 'FLT_MIN', 'DBL_MIN', 'LDBL_MIN', 'FLT_MIN_EXP', 'DBL_MIN_EXP',
+            'LDBL_MIN_EXP', 'CHAR_BIT', 'CHAR_MAX', 'CHAR_MIN', 'SCHAR_MAX', 'SCHAR_MIN',
+            'UCHAR_MAX', 'SHRT_MAX', 'SHRT_MIN', 'USHRT_MAX', 'INT_MAX', 'INT_MIN',
+            'UINT_MAX', 'LONG_MAX', 'LONG_MIN', 'ULONG_MAX', 'HUGE_VAL', 'SIGABRT',
+            'SIGFPE', 'SIGILL', 'SIGINT', 'SIGSEGV', 'SIGTERM', 'SIG_DFL', 'SIG_ERR',
+            'SIG_IGN', 'BUFSIZ', 'EOF', 'FILENAME_MAX', 'FOPEN_MAX', 'L_tmpnam', 'NULL',
+            'SEEK_CUR', 'SEEK_END', 'SEEK_SET', 'TMP_MAX',
+            'EXIT_FAILURE', 'EXIT_SUCCESS', 'RAND_MAX', 'CLOCKS_PER_SEC'
+            ),
+        2 => array(//mots-cles KLone
+            'out', 'request', 'response',
+            ),
+        3 => array(//fonctions C++ usuelles
+            'cin', 'cerr', 'clog', 'cout', 'delete', 'new', 'this',
+            'printf', 'fprintf', 'snprintf', 'sprintf', 'assert',
+            'isalnum', 'isalpha', 'isdigit', 'iscntrl', 'isgraph', 'islower', 'isprint',
+            'ispunct', 'isspace', 'isupper', 'isxdigit', 'tolower', 'toupper',
+            'exp', 'log', 'log10', 'pow', 'sqrt', 'ceil', 'floor', 'fabs', 'ldexp',
+            'frexp', 'modf', 'fmod', 'sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'atan2',
+            'sinh', 'cosh', 'tanh', 'setjmp', 'longjmp',
+            'va_start', 'va_arg', 'va_end', 'offsetof', 'sizeof', 'fopen', 'freopen',
+            'fflush', 'fclose', 'remove', 'rename', 'tmpfile', 'tmpname', 'setvbuf',
+            'setbuf', 'vfprintf', 'vprintf', 'vsprintf', 'fscanf', 'scanf', 'sscanf',
+            'fgetc', 'fgets', 'fputc', 'fputs', 'getc', 'getchar', 'gets', 'putc',
+            'putchar', 'puts', 'ungetc', 'fread', 'fwrite', 'fseek', 'ftell', 'rewind',
+            'fgetpos', 'fsetpos', 'clearerr', 'feof', 'ferror', 'perror', 'abs', 'labs',
+            'div', 'ldiv', 'atof', 'atoi', 'atol', 'strtod', 'strtol', 'strtoul', 'calloc',
+            'malloc', 'realloc', 'free', 'abort', 'exit', 'atexit', 'system', 'getenv',
+            'bsearch', 'qsort', 'rand', 'srand', 'strcpy', 'strncpy', 'strcat', 'strncat',
+            'strcmp', 'strncmp', 'strcoll', 'strchr', 'strrchr', 'strspn', 'strcspn',
+            'strpbrk', 'strstr', 'strlen', 'strerror', 'strtok', 'strxfrm', 'memcpy',
+            'memmove', 'memcmp', 'memchr', 'memset', 'clock', 'time', 'difftime', 'mktime',
+            'asctime', 'ctime', 'gmtime', 'localtime', 'strftime'
+            ),
+        4 => array(//fonctions KLone usuelles
+            'request_get_cookies', 'request_get_cookie', 'request_get_args', 'request_get_arg',
+            'request_io', 'request_get_uri', 'request_get_filename', 'request_get_query_string', 'request_get_path_info',
+            'request_get_if_modified_since', 'request_get_http', 'request_get_client_request',
+            'request_get_content_length', 'request_get_uploads', 'request_get_uploaded_file',
+            'request_get_method', 'request_get_protocol', 'request_get_resolved_filename',
+            'request_get_resolved_path_info', 'request_get_addr', 'request_get_peer_addr',
+            'request_get_header', 'request_get_field', 'request_get_field_value',
+            'response_set_content_encoding', 'response_disable_caching', 'response_enable_caching',
+            'response_set_cookie', 'response_set_method', 'response_get_method',
+            'response_print_header', 'response_set_field', 'response_del_field',
+            'response_set_content_type', 'response_set_date', 'response_set_last_modified',
+            'response_set_content_length', 'response_get_status', 'response_get_header',
+            'response_io', 'response_redirect', 'response_set_status',
+            'session_get_vars', 'session_get', 'session_set', 'session_age', 'session_clean', 'session_del',
+            'io_type', 'io_pipe', 'io_dup', 'io_copy', 'io_seek', 'io_tell', 'io_close',
+            'io_free', 'io_read', 'io_printf', 'io_flush', 'io_write', 'io_putc', 'io_getc',
+            'io_get_until', 'io_gets', 'io_codec_add_head', 'io_codec_add_tail',
+            'io_codecs_remove', 'io_name_set', 'io_name_get'
+            ),
+        5 => array(//types C++
+            'auto', 'bool', 'char', 'const', 'double', 'float', 'int', 'long', 'longint',
+            'register', 'short', 'shortint', 'signed', 'static', 'struct',
+            'typedef', 'union', 'unsigned', 'void', 'volatile', 'jmp_buf',
+            'signal', 'raise', 'va_list', 'ptrdiff_t', 'size_t', 'FILE', 'fpos_t',
+            'div_t', 'ldiv_t', 'clock_t', 'time_t', 'tm',
+            'string', 'wchar_t'
+            ),
+        6 => array(//mots-cles HTML
+            'a', 'abbr', 'acronym', 'address', 'applet',
+
+            'base', 'basefont', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'b',
+
+            'caption', 'center', 'cite', 'code', 'colgroup', 'col',
+
+            'dd', 'del', 'dfn', 'dir', 'div', 'dl', 'dt',
+
+            'em',
+
+            'fieldset', 'font', 'form', 'frame', 'frameset',
+
+            'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'hr', 'html',
+
+            'iframe', 'ilayer', 'img', 'input', 'ins', 'isindex', 'i',
+
+            'kbd',
+
+            'label', 'legend', 'link', 'li',
+
+            'map', 'meta',
+
+            'noframes', 'noscript',
+
+            'object', 'ol', 'optgroup', 'option',
+
+            'param', 'pre', 'p',
+
+            'q',
+
+            'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'style', 'sub', 'sup', 's',
+
+            'table', 'tbody', 'td', 'textarea', 'text', 'tfoot', 'thead', 'th', 'title', 'tr', 'tt',
+
+            'ul', 'u',
+
+            'var',
+            ),
+        7 => array(//autres mots-cles HTML
+            'abbr', 'accept-charset', 'accept', 'accesskey', 'action', 'align', 'alink', 'alt', 'archive', 'axis',
+            'background', 'bgcolor', 'border',
+            'cellpadding', 'cellspacing', 'char', 'charoff', 'charset', 'checked', 'cite', 'class', 'classid', 'clear', 'code', 'codebase', 'codetype', 'color', 'cols', 'colspan', 'compact', 'content', 'coords',
+            'data', 'datetime', 'declare', 'defer', 'dir', 'disabled',
+            'enctype',
+            'face', 'for', 'frame', 'frameborder',
+            'headers', 'height', 'href', 'hreflang', 'hspace', 'http-equiv',
+            'id', 'ismap',
+            'label', 'lang', 'language', 'link', 'longdesc',
+            'marginheight', 'marginwidth', 'maxlength', 'media', 'method', 'multiple',
+            'name', 'nohref', 'noresize', 'noshade', 'nowrap',
+            'object', 'onblur', 'onchange', 'onclick', 'ondblclick', 'onfocus', 'onkeydown', 'onkeypress', 'onkeyup', 'onload', 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onreset', 'onselect', 'onsubmit', 'onunload',
+            'profile', 'prompt',
+            'readonly', 'rel', 'rev', 'rowspan', 'rows', 'rules',
+            'scheme', 'scope', 'scrolling', 'selected', 'shape', 'size', 'span', 'src', 'standby', 'start', 'style', 'summary',
+            'tabindex', 'target', 'text', 'title', 'type',
+            'usemap',
+            'valign', 'value', 'valuetype', 'version', 'vlink', 'vspace',
+            'width'
+            )
+        ),
+    'SYMBOLS' => array(
+        1 => array(
+            '<%=', '<%!', '<%', '%>'
+            ),
+        0 => array(
+            '(', ')', '[', ']', '{', '}',
+            '!', '%', '&', '|', '/',
+            '<', '>',
+            '=', '-', '+', '*',
+            '.', ':', ',', ';', '^'
+            )
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        5 => false,
+        6 => false,
+        7 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100; font-weight: bold;',//pour les mots-cles C++
+            2 => 'color: #000000; font-weight: bold;',//pour les mots-cles KLone
+            3 => 'color: #6600FF;',//pour les fonctions C++
+            4 => 'color: #6600FF;',//pour les fonctions Klone
+            5 => 'color: #0099FF; font-weight: bold;',//pour les types C++
+            6 => 'color: #990099; font-weight: bold;',//pour les mots-cles HTML
+            7 => 'color: #000066;'//pour les autres mots-cles HTML
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',//commentaire sur une ligne C++ et KLone
+            2 => 'color: #339933;',//pour les #... en C++
+            'MULTI' => 'color: #808080; font-style: italic;'//commentaire sur plusieurs lignes C++ et KLone
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000000;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006600;',
+            2 => 'color: #006600;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000000;',
+            1 => 'color: #000000; font-weight: bold;'
+            ),
+        'REGEXPS' => array(),
+        'SCRIPT' => array(
+            0 => 'background-color:#ffccff; font-weight: bold; color:#000000;',
+            1 => '',
+            2 => '',
+            3 => 'color: #00bbdd; font-weight: bold;',
+            4 => 'color: #ddbb00;',
+            5 => 'color: #009900;'
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => 'http://www.opengroup.org/onlinepubs/009695399/functions/{FNAMEL}.html',
+        4 => 'http://www.koanlogic.com/klone/api/html/globals.html',
+        5 => '',
+        6 => 'http://december.com/html/4/element/{FNAMEL}.html',
+        7 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.',
+        2 => '::'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_ALWAYS,
+    'SCRIPT_DELIMITERS' => array(
+        //delimiteurs pour KLone
+        0 => array(
+            '<%=' => '%>'
+            ),
+        1 => array(
+            '<%!' => '%>'
+            ),
+        2 => array(
+            '<%' => '%>'
+            ),
+        //delimiteur pour HTML
+        3 => array(
+            '<!DOCTYPE' => '>'
+            ),
+        4 => array(
+            '&' => ';'
+            ),
+        5 => array(
+            '<' => '>'
+            )
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        0 => false,
+        1 => true,
+        2 => true,
+        3 => false,
+        4 => false,
+        5 => true
+        ),
+    'TAB_WIDTH' => 4,
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            6 => array(
+                'DISALLOWED_BEFORE' => '(?<=&lt;|&lt;\/)',
+                'DISALLOWED_AFTER' => '(?=\s|\/|&gt;)',
+            ),
+            7 => array(
+                'DISALLOWED_AFTER' => '(?=\s*=)',
+            )
+        )
+    )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/latex.php b/examples/includes/geshi/geshi/latex.php
new file mode 100644 (file)
index 0000000..e4926d9
--- /dev/null
@@ -0,0 +1,209 @@
+<?php
+/*************************************************************************************
+ * latex.php
+ * -----
+ * Author: efi, Matthias Pospiech (matthias@pospiech.eu)
+ * Copyright: (c) 2006 efi, Matthias Pospiech (matthias@pospiech.eu), Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2006/09/23
+ *
+ * LaTeX language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/08/18 (1.0.8.1)
+ *  - Changes in color and some additional command recognition
+ *  - No special Color for Brackets, it is only distracting
+ *    if color should be reintroduced it should be less bright
+ *  - Math color changed from green to violett, since green is now used for comments
+ *  - Comments are now colored and the only green. The reason for coloring the comments
+ *    is that often important information is in the comments und was merely unvisible before.
+ *  - New Color for [Options]
+ *  - color for labels not specialised anymore. It makes sence in large documents but less in
+ *    small web examples.
+ *  - \@keyword introduced
+ *  - Fixed \& escaped ampersand
+ * 2006/09/23 (1.0.0)
+ *  -  First Release
+ *
+ * TODO
+ * -------------------------
+ * *
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'LaTeX',
+    'COMMENT_SINGLE' => array(
+        1 => '%'
+        ),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array(),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            'appendix','backmatter','caption','captionabove','captionbelow',
+            'def','documentclass','edef','equation','flushleft','flushright',
+            'footnote','frontmatter','hline','include','input','item','label',
+            'let','listfiles','listoffigures','listoftables','mainmatter',
+            'makeatletter','makeatother','makebox','mbox','par','raggedleft',
+            'raggedright','raisebox','ref','rule','table','tableofcontents',
+            'textbf','textit','texttt','today'
+            )
+        ),
+    'SYMBOLS' => array(
+        "&", "\\", "{", "}", "[", "]"
+        ),
+    'CASE_SENSITIVE' => array(
+        1 => true,
+        GESHI_COMMENTS => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #800000; font-weight: bold;',
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #2C922C; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 =>  'color: #000000; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            ),
+        'STRINGS' => array(
+            0 =>  'color: #000000;'
+            ),
+        'NUMBERS' => array(
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 =>  'color: #E02020; '
+            ),
+        'REGEXPS' => array(
+            1 => 'color: #8020E0; font-weight: normal;',  // Math inner
+            2 => 'color: #C08020; font-weight: normal;', // [Option]
+            3 => 'color: #8020E0; font-weight: normal;', // Maths
+            4 => 'color: #800000; font-weight: normal;', // Structure: Labels
+            5 => 'color: #00008B; font-weight: bold;',  // Structure (\section{->x<-})
+            6 => 'color: #800000; font-weight: normal;', // Structure (\section)
+            7 => 'color: #0000D0; font-weight: normal;', // Environment \end or \begin{->x<-} (brighter blue)
+            8 => 'color: #C00000; font-weight: normal;', // Structure \end or \begin
+            9 => 'color: #2020C0; font-weight: normal;', // {...}
+            10 => 'color: #800000; font-weight: normal;', // \%, \& etc.
+            11 => 'color: #E00000; font-weight: normal;', // \@keyword
+            12 => 'color: #800000; font-weight: normal;', // \keyword
+        ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => 'http://www.golatex.de/wiki/index.php?title=\\{FNAME}',
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        // Math inner
+        1 => array(
+            GESHI_SEARCH => "(\\\\begin\\{(equation|displaymath|eqnarray|subeqnarray|math|multline|gather|align|alignat|flalign)\\})(.*)(\\\\end\\{\\2\\})",
+            GESHI_REPLACE => '\3',
+            GESHI_MODIFIERS => 'Us',
+            GESHI_BEFORE => '\1',
+            GESHI_AFTER => '\4'
+            ),
+        // [options]
+        2 => array(
+            GESHI_SEARCH => "(?<=\[).+(?=\])",
+            GESHI_REPLACE => '\0',
+            GESHI_MODIFIERS => 'Us',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        // Math mode with $ ... $
+        3 => array(
+            GESHI_SEARCH => "\\$.+\\$",
+            GESHI_REPLACE => '\0',
+            GESHI_MODIFIERS => 'Us',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        // Structure: Label
+        4 => "\\\\(?:label|pageref|ref|cite)(?=[^a-zA-Z])",
+        // Structure: sections
+        5 => array(
+            GESHI_SEARCH => "(\\\\(?:part|chapter|(?:sub){0,2}section|(?:sub)?paragraph|addpart|addchap|addsec)\*?\\{)(.*)(?=\\})",
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 'U',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => ''
+            ),
+        // Structure: sections
+        6 => "\\\\(?:part|chapter|(?:sub){0,2}section|(?:sub)?paragraph|addpart|addchap|addsec)\*?(?=[^a-zA-Z])",
+        // environment \begin{} and \end{} (i.e. the things inside the {})
+        7 => array(
+            GESHI_SEARCH => "(\\\\(?:begin|end)\\{)(.*)(?=\\})",
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 'U',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => ''
+            ),
+        // Structure \begin and \end
+        8 => "\\\\(?:end|begin)(?=[^a-zA-Z])",
+        // {parameters}
+        9 => array(
+            GESHI_SEARCH => "(?<=\\{)(?!<\|!REG3XP5!>).*(?=\\})",
+            GESHI_REPLACE => '\0',
+            GESHI_MODIFIERS => 'Us',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        // \%, \& usw.
+        10 => "\\\\(?:[_$%]|&amp;)",
+        //  \@keywords
+        11 => "(?<!<\|!REG3XP[8]!>)\\\\@[a-zA-Z]+\*?",
+        // \keywords
+        12 => "(?<!<\|!REG3XP[468]!>)\\\\[a-zA-Z]+\*?",
+
+// ---------------------------------------------
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'PARSER_CONTROL' => array(
+        'COMMENTS' => array(
+            'DISALLOWED_BEFORE' => '\\'
+        ),
+        'KEYWORDS' => array(
+            'DISALLOWED_BEFORE' => "(?<=\\\\)",
+            'DISALLOWED_AFTER' => "(?=\b)(?!\w)"
+        ),
+        'ENABLE_FLAGS' => array(
+            'NUMBERS' => GESHI_NEVER,
+            'BRACKETS' => GESHI_NEVER
+        )
+    )
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/lisp.php b/examples/includes/geshi/geshi/lisp.php
new file mode 100644 (file)
index 0000000..de08d9c
--- /dev/null
@@ -0,0 +1,144 @@
+<?php
+/*************************************************************************************
+ * lisp.php
+ * --------
+ * Author: Roberto Rossi (rsoftware@altervista.org)
+ * Copyright: (c) 2004 Roberto Rossi (http://rsoftware.altervista.org), Nigel McNie (http://qbnz.com/highlighter
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/08/30
+ *
+ * Generic Lisp language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2005/12/9  (1.0.2)
+ *  -  Added support for :keywords and ::access (Denis Mashkevich)
+ * 2004/11/27 (1.0.1)
+ *  -  Added support for multiple object splitters
+ * 2004/08/30 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Lisp',
+    'COMMENT_SINGLE' => array(1 => ';'),
+    'COMMENT_MULTI' => array(';|' => '|;'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'not','defun','princ','when',
+            'eval','apply','funcall','quote','identity','function',
+            'complement','backquote','lambda','set','setq','setf',
+            'defmacro','gensym','make','symbol','intern',
+            'name','value','plist','get',
+            'getf','putprop','remprop','hash','array','aref',
+            'car','cdr','caar','cadr','cdar','cddr','caaar','caadr','cadar',
+            'caddr','cdaar','cdadr','cddar','cdddr','caaaar','caaadr',
+            'caadar','caaddr','cadaar','cadadr','caddar','cadddr',
+            'cdaaar','cdaadr','cdadar','cdaddr','cddaar','cddadr',
+            'cdddar','cddddr','cons','list','append','reverse','last','nth',
+            'nthcdr','member','assoc','subst','sublis','nsubst',
+            'nsublis','remove','length',
+            'mapc','mapcar','mapl','maplist','mapcan','mapcon','rplaca',
+            'rplacd','nconc','delete','atom','symbolp','numberp',
+            'boundp','null','listp','consp','minusp','zerop','plusp',
+            'evenp','oddp','eq','eql','equal','cond','case','and','or',
+            'let','l','if','prog','prog1','prog2','progn','go','return',
+            'do','dolist','dotimes','catch','throw','error','cerror','break',
+            'continue','errset','baktrace','evalhook','truncate','float',
+            'rem','min','max','abs','sin','cos','tan','expt','exp','sqrt',
+            'random','logand','logior','logxor','lognot','bignums','logeqv',
+            'lognand','lognor','logorc2','logtest','logbitp','logcount',
+            'integer','nil','parse-integer'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '{', '}', '[', ']',
+        '!', '%', '^', '&',
+        ' + ',' - ',' * ',' / ',
+        '=','<','>',
+        '.',':',',',';',
+        '|'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            0 => 'color: #555;',
+            1 => 'color: #555;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        '::', ':'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'PARSER_CONTROL' => array(
+        'OOLANG' => array(
+            'MATCH_AFTER' => '[a-zA-Z][a-zA-Z0-9_\-]*'
+            )
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/locobasic.php b/examples/includes/geshi/geshi/locobasic.php
new file mode 100644 (file)
index 0000000..02e6a7a
--- /dev/null
@@ -0,0 +1,130 @@
+<?php
+/*************************************************************************************
+ * locobasic.php
+ * -------------
+ * Author: Nacho Cabanes
+ * Copyright: (c) 2009 Nacho Cabanes (http://www.nachocabanes.com)
+ * Release Version: 1.0.8.3
+ * Date Started: 2009/03/22
+ *
+ * Locomotive Basic (Amstrad CPC series) language file for GeSHi.
+ *
+ * More details at http://en.wikipedia.org/wiki/Locomotive_BASIC
+ *
+ * CHANGES
+ * -------
+ * 2009/03/22 (1.0.8.3)
+ *  -  First Release
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Locomotive Basic',
+    'COMMENT_SINGLE' => array(1 => "'", 2 => 'REM'),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            "AFTER", "AND", "AUTO", "BORDER", "BREAK", "CALL", "CAT", "CHAIN",
+            "CLEAR", "CLG", "CLS", "CLOSEIN", "CLOSEOUT", "CONT", "CURSOR",
+            "DATA", "DEF", "DEFINT", "DEFREAL", "DEFSTR", "DEG", "DELETE",
+            "DERR", "DI", "DIM", "DRAW", "DRAWR", "EDIT", "EI", "ELSE", "END",
+            "ENV", "ENT", "EOF", "ERASE", "ERL", "ERR", "ERROR", "EVERY",
+            "FILL", "FN", "FOR", "FRAME", "GOSUB", "GOTO", "GRAPHICS", "HIMEM",
+            "IF", "INK", "INPUT", "KEY", "LET", "LINE", "LIST", "LOAD",
+            "LOCATE", "MASK", "MEMORY", "MERGE", "MODE", "MOVE", "MOVER", "NEW",
+            "NEXT", "NOT", "ON", "OPENIN", "OPENOUT", "OR", "ORIGIN", "PAPER",
+            "PEEK", "PEN", "PLOT", "PLOTR", "POKE", "PRINT", "RAD", "RANDOMIZE",
+            "READ", "RELEASE", "REMAIN", "RENUM", "RESTORE", "RESUME", "RETURN",
+            "RUN", "SAVE", "SPEED", "SOUND", "SPC", "SQ", "STEP", "STOP", "SWAP",
+            "SYMBOL", "TAB", "TAG", "TAGOFF", "TEST", "TESTR", "TIME", "TO",
+            "THEN", "TRON", "TROFF", "USING", "WAIT", "WEND", "WHILE", "WIDTH",
+            "WINDOW", "WRITE", "XOR", "ZONE"
+            ),
+        2 => array(
+            "ABS", "ASC", "ATN", "BIN", "CHR", "CINT", "COPYCHR", "COS",
+            "CREAL", "DEC", "FIX", "FRE", "EXP", "HEX", "INKEY", "INP", "INSTR",
+            "INT", "JOY", "LEFT", "LEN", "LOG", "LOG10", "LOWER", "MAX", "MID",
+            "MIN", "MOD", "OUT", "PI", "POS", "RIGHT", "RND", "ROUND", "SGN",
+            "SIN", "SPACE", "SQR", "STR", "STRING", "TAN", "UNT", "UPPER",
+            "VAL", "VPOS", "XPOS", "YPOS"
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0000ff; font-weight: bold;',
+            2 => 'color: #008888; font-weight: bold;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080;',
+            2 => 'color: #808080;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #0044ff;'
+            ),
+        'METHODS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/lolcode.php b/examples/includes/geshi/geshi/lolcode.php
new file mode 100644 (file)
index 0000000..19b42f5
--- /dev/null
@@ -0,0 +1,152 @@
+<?php
+/*************************************************************************************
+ * lolcode.php
+ * ----------
+ * Author: Benny Baumann (BenBE@geshi.org)
+ * Copyright: (c) 2008 Benny Baumann (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2009/10/31
+ *
+ * LOLcode language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/10/31 (1.0.8.1)
+ *   -  First Release
+ *
+ * TODO
+ * ----
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+$language_data = array (
+    'LANG_NAME' => 'LOLcode',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array(),
+    'COMMENT_REGEXP' => array(
+        1 => "/\bBTW\b.*$/im",
+        2 => "/(^|\b)(?:OBTW\b.+?\bTLDR|LOL\b.+?\/LOL)(\b|$)/si"
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_UPPER,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '',
+    'ESCAPE_REGEXP' => array(
+        1 => '/:[)>o":]/',
+        2 => '/:\([\da-f]+\)/i',
+        3 => '/:\{\w+\}/i',
+        4 => '/:\[\w+\]/i',
+        ),
+    'KEYWORDS' => array(
+        //Statements
+        1 => array(
+            'VISIBLE', 'HAI', 'KTHX', 'KTHXBYE', 'SMOOSH', 'GIMMEH', 'PLZ',
+            'ON', 'INVISIBLE', 'R', 'ITZ', 'GTFO', 'COMPLAIN', 'GIMME',
+
+            'OPEN', 'FILE', 'I HAS A', 'AWSUM THX', 'O NOES', 'CAN', 'HAS', 'HAZ',
+            'HOW DOES I', 'IF U SAY SO', 'FOUND YR', 'BORROW', 'OWN', 'ALONG',
+            'WITH', 'WIT', 'LOOK', 'AT', 'AWSUM', 'THX'
+            ),
+        //Conditionals
+        2 => array(
+            'IZ', 'YARLY', 'NOWAI', 'WTF?', 'MEBBE', 'OMG', 'OMGWTF',
+            'ORLY?', 'OF', 'NOPE', 'SO', 'IM', 'MAI',
+
+            'O RLY?', 'SUM', 'BOTH SAEM', 'DIFFRINT', 'BOTH', 'EITHER', 'WON',
+            'DIFF', 'PRODUKT', 'QUOSHUNT', 'MOD', 'MKAY', 'OK', 'THING',
+            'BIGNESS'
+            ),
+        //Repetition
+        3 => array(
+            'IN', 'OUTTA', 'LOOP', 'WHILE'
+            ),
+        //Operators \Math
+        4 => array(
+            'AN', 'AND', 'NOT', 'UP', 'YR', 'UPPIN', 'NERF', 'NERFIN', 'NERFZ',
+            'SMASHING', 'UR', 'KINDA', 'LIKE', 'SAEM', 'BIG', 'SMALL',
+            'BIGGR', 'SMALLR', 'BIGGER', 'SMALLER', 'GOOD', 'CUTE', 'THAN'
+            )
+        ),
+    'SYMBOLS' => array(
+        '.', ',', '?',
+        '!!'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #008000;',
+            2 => 'color: #000080;',
+            3 => 'color: #000080;',
+            4 => 'color: #800000;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #666666; style: italic;',
+            2 => 'color: #666666; style: italic;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'ESCAPE_CHAR' => array(
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            'SPACE_AS_WHITESPACE' => true
+            )
+        ),
+    'TAB_WIDTH' => 4
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/lotusformulas.php b/examples/includes/geshi/geshi/lotusformulas.php
new file mode 100644 (file)
index 0000000..010fb22
--- /dev/null
@@ -0,0 +1,318 @@
+<?php
+/*************************************************************************************
+ * lotusformulas.php
+ * ------------------------
+ * Author: Richard Civil (info@richardcivil.net)
+ * Copyright: (c) 2008 Richard Civil (info@richardcivil.net), Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/04/12
+ *
+ * @Formula/@Command language file for GeSHi.
+ *
+ * @Formula/@Command source: IBM Lotus Notes/Domino 8 Designer Help
+ *
+ * CHANGES
+ * -------
+ * 2008/04/12 (1.0.7.22)
+ *  -  First Release
+ *
+ * TODO (updated 2008/04/12)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Lotus Notes @Formulas',
+    'COMMENT_SINGLE' => array(1 => "'"),
+    'COMMENT_MULTI' => array('REM' => ';'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array (
+            '[ZoomPreview]', '[WorkspaceStackReplicaIcons]',
+            '[WorkspaceProperties]', '[WindowWorkspace]',
+            '[WindowTile]', '[WindowRestore]', '[WindowNext]',
+            '[WindowMinimizeAll]', '[WindowMinimize]', '[WindowMaximizeAll]',
+            '[WindowMaximize]', '[WindowCascade]', '[ViewSwitchForm]',
+            '[ViewShowUnread]', '[ViewShowServerNames]', '[ViewShowSearchBar]',
+            '[ViewShowRuler]', '[ViewShowPageBreaks]', '[ViewShowOnlyUnread]',
+            '[ViewShowOnlySelected]', '[ViewShowOnlySearchResults]',
+            '[ViewShowOnlyCategories]', '[ViewShowObject]',
+            '[ViewShowFieldHelp]', '[ViewRenamePerson]', '[ViewRefreshUnread]',
+            '[ViewRefreshFields]', '[ViewNavigatorsNone]',
+            '[ViewNavigatorsFolders]', '[ViewMoveName]', '[ViewHorizScrollbar]',
+            '[ViewExpandWithChildren]', '[ViewExpandAll]', '[ViewExpand]',
+            '[ViewCollapseAll]', '[ViewCollapse]', '[ViewChange]',
+            '[ViewCertify]', '[ViewBesideFolders]', '[ViewBelowFolders]',
+            '[ViewArrangeIcons]', '[V3EditPrevField]', '[V3EditNextField]',
+            '[UserIDSwitch]', '[UserIDSetPassword]', '[UserIDMergeCopy]',
+            '[UserIDInfo]', '[UserIDEncryptionKeys]', '[UserIDCreateSafeCopy]',
+            '[UserIDClearPassword]', '[UserIDCertificates]',
+            '[ToolsUserLogoff]', '[ToolsSpellCheck]', '[ToolsSmartIcons]',
+            '[ToolsSetupUserSetup]', '[ToolsSetupPorts]', '[ToolsSetupMail]',
+            '[ToolsSetupLocation]', '[ToolsScanUnreadSelected]',
+            '[ToolsScanUnreadPreferred]', '[ToolsScanUnreadChoose]',
+            '[ToolsRunMacro]', '[ToolsRunBackgroundMacros]', '[ToolsReplicate]',
+            '[ToolsRefreshSelectedDocs]', '[ToolsRefreshAllDocs]',
+            '[ToolsMarkSelectedUnread]', '[ToolsMarkSelectedRead]',
+            '[ToolsMarkAllUnread]', '[ToolsMarkAllRead]', '[ToolsHangUp]',
+            '[ToolsCategorize]', '[ToolsCall]', '[TextUnderline]',
+            '[TextSpacingSingle]', '[TextSpacingOneAndaHalf]',
+            '[TextSpacingDouble]', '[TextSetFontSize]', '[TextSetFontFace]',
+            '[TextSetFontColor]', '[TextReduceFont]', '[TextPermanentPen]',
+            '[TextParagraphStyles]', '[TextParagraph]', '[TextOutdent]',
+            '[TextNumbers]', '[TextNormal]', '[TextItalic]', '[TextFont]',
+            '[TextEnlargeFont]', '[TextCycleSpacing]', '[TextBullet]',
+            '[TextBold]', '[TextAlignRight]', '[TextAlignNone]',
+            '[TextAlignLeft]', '[TextAlignFull]', '[TextAlignCenter]',
+            '[SwitchView]', '[SwitchForm]', '[StyleCycleKey]',
+            '[SmartIconsNextSet]', '[SmartIconsFloating]', '[ShowProperties]',
+            '[ShowHidePreviewPane]', '[ShowHideParentPreview]',
+            '[ShowHideLinkPreview]', '[ShowHideIMContactList]',
+            '[SetCurrentLocation]', '[SendInstantMessage]',
+            '[SectionRemoveHeader]', '[SectionProperties]',
+            '[SectionExpandAll]', '[SectionExpand]', '[SectionDefineEditors]',
+            '[SectionCollapseAll]', '[SectionCollapse]', '[RunScheduledAgents]',
+            '[RunAgent]', '[ReplicatorStop]', '[ReplicatorStart]',
+            '[ReplicatorSendReceiveMail]', '[ReplicatorSendMail]',
+            '[ReplicatorReplicateWithServer]', '[ReplicatorReplicateSelected]',
+            '[ReplicatorReplicateNext]', '[ReplicatorReplicateHigh]',
+            '[Replicator]', '[RenameDatabase]', '[RemoveFromFolder]',
+            '[RemoteDebugLotusScript]', '[ReloadWindow]', '[RefreshWindow]',
+            '[RefreshParentNote]', '[RefreshHideFormulas]', '[RefreshFrame]',
+            '[PublishDatabase]', '[PictureProperties]', '[PasteBitmapAsObject]',
+            '[PasteBitmapAsBackground]', '[OpenView]', '[OpenPage]',
+            '[OpenNavigator]', '[OpenInNewWindow]', '[OpenHelpDocument]',
+            '[OpenFrameset]', '[OpenDocument]', '[OpenCalendar]',
+            '[ObjectProperties]', '[ObjectOpen]', '[ObjectDisplayAs]',
+            '[NavPrevUnread]', '[NavPrevSelected]', '[NavPrevMain]',
+            '[NavPrev]', '[NavNextUnread]', '[NavNextSelected]',
+            '[NavNextMain]', '[NavNext]', '[NavigatorTest]',
+            '[NavigatorProperties]', '[NavigateToBacklink]',
+            '[NavigatePrevUnread]', '[NavigatePrevSelected]',
+            '[NavigatePrevMain]', '[NavigatePrevHighlight]', '[NavigatePrev]',
+            '[NavigateNextUnread]', '[NavigateNextSelected]',
+            '[NavigateNextMain]', '[NavigateNextHighlight]', '[NavigateNext]',
+            '[MoveToTrash]', '[MailSendPublicKey]', '[MailSendEncryptionKey]',
+            '[MailSendCertificateRequest]', '[MailSend]', '[MailScanUnread]',
+            '[MailRequestNewPublicKey]', '[MailRequestNewName]',
+            '[MailRequestCrossCert]', '[MailOpen]', '[MailForwardAsAttachment]',
+            '[MailForward]', '[MailComposeMemo]', '[MailAddress]',
+            '[LayoutProperties]', '[LayoutElementSendToBack]',
+            '[LayoutElementProperties]', '[LayoutElementBringToFront]',
+            '[LayoutAddText]', '[LayoutAddGraphic]', '[InsertSubform]',
+            '[HotspotProperties]', '[HotspotClear]', '[HelpUsingDatabase]',
+            '[HelpAboutNotes]', '[HelpAboutDatabase]', '[GoUpLevel]',
+            '[FormTestDocument]', '[FormActions]', '[FolderRename]',
+            '[FolderProperties]', '[FolderMove]', '[FolderExpandWithChildren]',
+            '[FolderExpandAll]', '[FolderExpand]', '[FolderDocuments]',
+            '[FolderCustomize]', '[FolderCollapse]', '[Folder]',
+            '[FindFreeTimeDialog]', '[FileSaveNewVersion]', '[FileSave]',
+            '[FilePrintSetup]', '[FilePrint]', '[FilePageSetup]',
+            '[FileOpenDBRepID]', '[FileOpenDatabase]', '[FileNewReplica]',
+            '[FileNewDatabase]', '[FileImport]', '[FileFullTextUpdate]',
+            '[FileFullTextInfo]', '[FileFullTextDelete]',
+            '[FileFullTextCreate]', '[FileExport]', '[FileExit]',
+            '[FileDatabaseUseServer]', '[FileDatabaseRemove]',
+            '[FileDatabaseInfo]', '[FileDatabaseDelete]', '[FileDatabaseCopy]',
+            '[FileDatabaseCompact]', '[FileDatabaseACL]', '[FileCloseWindow]',
+            '[ExitNotes]', '[Execute]', '[ExchangeUnreadMarks]', '[EmptyTrash]',
+            '[EditUp]', '[EditUntruncate]', '[EditUndo]', '[EditTop]',
+            '[EditTableInsertRowColumn]', '[EditTableFormat]',
+            '[EditTableDeleteRowColumn]', '[EditShowHideHiddenChars]',
+            '[EditSelectByDate]', '[EditSelectAll]', '[EditRight]',
+            '[EditRestoreDocument]', '[EditResizePicture]',
+            '[EditQuoteSelection]', '[EditProfileDocument]', '[EditProfile]',
+            '[EditPrevField]', '[EditPhoneNumbers]', '[EditPasteSpecial]',
+            '[EditPaste]', '[EditOpenLink]', '[EditNextField]',
+            '[EditMakeDocLink]', '[EditLocations]', '[EditLinks]', '[EditLeft]',
+            '[EditInsertText]', '[EditInsertTable]', '[EditInsertPopup]',
+            '[EditInsertPageBreak]', '[EditInsertObject]',
+            '[EditInsertFileAttachment]', '[EditInsertButton]',
+            '[EditIndentFirstLine]', '[EditIndent]', '[EditHorizScrollbar]',
+            '[EditHeaderFooter]', '[EditGotoField]', '[EditFindNext]',
+            '[EditFindInPreview]', '[EditFind]', '[EditEncryptionKeys]',
+            '[EditDown]', '[EditDocument]', '[EditDetach]', '[EditDeselectAll]',
+            '[EditCut]', '[EditCopy]', '[EditClear]', '[EditButton]',
+            '[EditBottom]', '[DiscoverFolders]', '[Directories]',
+            '[DialingRules]', '[DesignViewSelectFormula]', '[DesignViews]',
+            '[DesignViewNewColumn]', '[DesignViewFormFormula]',
+            '[DesignViewEditActions]', '[DesignViewColumnDef]',
+            '[DesignViewAttributes]', '[DesignViewAppendColumn]',
+            '[DesignSynopsis]', '[DesignSharedFields]', '[DesignReplace]',
+            '[DesignRefresh]', '[DesignMacros]', '[DesignIcon]',
+            '[DesignHelpUsingDocument]', '[DesignHelpAboutDocument]',
+            '[DesignFormWindowTitle]', '[DesignFormUseField]',
+            '[DesignFormShareField]', '[DesignForms]', '[DesignFormNewField]',
+            '[DesignFormFieldDef]', '[DesignFormAttributes]',
+            '[DesignDocumentInfo]', '[DebugLotusScript]',
+            '[DatabaseReplSettings]', '[DatabaseDelete]', '[CreateView]',
+            '[CreateTextbox]', '[CreateSubForm]', '[CreateSection]',
+            '[CreateRectangularHotspot]', '[CreateRectangle]',
+            '[CreatePolyline]', '[CreatePolygon]', '[CreateNavigator]',
+            '[CreateLayoutRegion]', '[CreateForm]', '[CreateFolder]',
+            '[CreateEllipse]', '[CreateControlledAccessSection]',
+            '[CreateAgent]', '[CreateAction]', '[CopySelectedAsTable]',
+            '[ComposeWithReference]', '[Compose]', '[CloseWindow]', '[Clear]',
+            '[ChooseFolders]', '[CalendarGoTo]', '[CalendarFormat]',
+            '[AttachmentView]', '[AttachmentProperties]', '[AttachmentLaunch]',
+            '[AttachmentDetachAll]', '[AgentTestRun]', '[AgentSetServerName]',
+            '[AgentRun]', '[AgentLog]', '[AgentEnableDisable]', '[AgentEdit]',
+            '[AdminTraceConnection]', '[AdminStatisticsConfig]',
+            '[AdminSendMailTrace]', '[AdminRemoteConsole]',
+            '[AdminRegisterUser]', '[AdminRegisterServer]',
+            '[AdminRegisterFromFile]', '[AdminOutgoingMail]',
+            '[AdminOpenUsersView]', '[AdminOpenStatistics]',
+            '[AdminOpenServersView]', '[AdminOpenServerLog]',
+            '[AdminOpenGroupsView]', '[AdminOpenCertLog]', '[AdminOpenCatalog]',
+            '[AdminOpenAddressBook]', '[AdminNewOrgUnit]',
+            '[AdminNewOrganization]', '[Administration]',
+            '[AdminIDFileSetPassword]', '[AdminIDFileExamine]',
+            '[AdminIDFileClearPassword]', '[AdminDatabaseQuotas]',
+            '[AdminDatabaseAnalysis]', '[AdminCrossCertifyKey]',
+            '[AdminCrossCertifyIDFile]', '[AdminCreateGroup]', '[AdminCertify]',
+            '[AddToIMContactList]', '[AddDatabaseRepID]', '[AddDatabase]',
+            '[AddBookmark]'
+            ),
+        2 => array(
+            'SELECT', 'FIELD', 'ENVIRONMENT', 'DEFAULT', '@Zone ', '@Yesterday',
+            '@Yes', '@Year', '@Word', '@Wide', '@While', '@Weekday',
+            '@WebDbName', '@ViewTitle', '@ViewShowThisUnread', '@Version',
+            '@VerifyPassword', '@ValidateInternetAddress', '@V4UserAccess',
+            '@V3UserName', '@V2If', '@UserRoles', '@UserPrivileges',
+            '@UserNamesList', '@UserNameLanguage', '@UserName', '@UserAccess',
+            '@UrlQueryString', '@URLOpen', '@URLHistory', '@URLGetHeader',
+            '@URLEncode', '@URLDecode', '@UpperCase', '@UpdateFormulaContext',
+            '@Unique', '@UndeleteDocument', '@Unavailable', '@True', '@Trim',
+            '@Transform', '@ToTime', '@ToNumber', '@Tomorrow', '@Today',
+            '@TimeZoneToText', '@TimeToTextInZone', '@TimeMerge', '@Time',
+            '@ThisValue', '@ThisName', '@TextToTime', '@TextToNumber', '@Text',
+            '@TemplateVersion', '@Tan', '@Sum', '@Success', '@Subset',
+            '@StatusBar', '@Sqrt', '@Soundex', '@Sort', '@Sin', '@Sign',
+            '@SetViewInfo', '@SetTargetFrame', '@SetProfileField',
+            '@SetHTTPHeader', '@SetField', '@SetEnvironment', '@SetDocField',
+            '@Set', '@ServerName', '@ServerAccess', '@Select', '@Second',
+            '@Round', '@RightBack', '@Right', '@Return', '@Responses',
+            '@ReplicaID', '@ReplaceSubstring', '@Replace', '@Repeat',
+            '@RegQueryValue', '@RefreshECL', '@Random', '@ProperCase',
+            '@Prompt', '@Power', '@PostedCommand', '@PolicyIsFieldLocked',
+            '@Platform', '@PickList', '@Pi', '@PasswordQuality', '@Password',
+            '@OrgDir', '@OptimizeMailAddress', '@OpenInNewWindow', '@Now',
+            '@Nothing', '@NoteID', '@No', '@NewLine', '@Narrow', '@NameLookup',
+            '@Name', '@Month', '@Modulo', '@Modified', '@Minute', '@Min',
+            '@MiddleBack', '@Middle', '@Member', '@Max', '@Matches',
+            '@MailSignPreference', '@MailSend', '@MailSavePreference',
+            '@MailEncryptSentPreference', '@MailEncryptSavedPreference',
+            '@MailDbName', '@LowerCase', '@Log', '@Locale', '@Ln', '@Like',
+            '@Length', '@LeftBack', '@Left', '@LDAPServer', '@LaunchApp',
+            '@LanguagePreference', '@Keywords', '@IsVirtualizedDirectory',
+            '@IsValid', '@IsUsingJavaElement', '@IsUnavailable', '@IsTime',
+            '@IsText', '@IsResponseDoc', '@IsNumber', '@IsNull', '@IsNotMember',
+            '@IsNewDoc', '@IsModalHelp', '@IsMember', '@IsExpandable',
+            '@IsError', '@IsEmbeddedInsideWCT', '@IsDocTruncated',
+            '@IsDocBeingSaved', '@IsDocBeingRecalculated', '@IsDocBeingMailed',
+            '@IsDocBeingLoaded', '@IsDocBeingEdited', '@IsDB2', '@IsCategory',
+            '@IsAvailable', '@IsAppInstalled', '@IsAgentEnabled', '@Integer',
+            '@InheritedDocumentUniqueID', '@Implode', '@IfError', '@If',
+            '@Hour', '@HashPassword', '@HardDeleteDocument', '@GetViewInfo',
+            '@GetProfileField', '@GetPortsList', '@GetIMContactListGroupNames',
+            '@GetHTTPHeader', '@GetFocusTable', '@GetField', '@GetDocField',
+            '@GetCurrentTimeZone', '@GetAddressBooks', '@FormLanguage', '@For',
+            '@FontList', '@FloatEq', '@FileDir', '@False', '@Failure',
+            '@Explode', '@Exp', '@Eval', '@Error', '@Environment', '@Ends',
+            '@EnableAlarms', '@Elements', '@EditUserECL', '@EditECL',
+            '@DoWhile', '@Domain', '@DocumentUniqueID', '@DocSiblings',
+            '@DocParentNumber', '@DocOmmittedLength', '@DocNumber', '@DocMark',
+            '@DocLock', '@DocLevel', '@DocLength', '@DocFields',
+            '@DocDescendants', '@DocChildren', '@Do', '@DialogBox',
+            '@DeleteField', '@DeleteDocument', '@DDETerminate', '@DDEPoke',
+            '@DDEInitiate', '@DDEExecute', '@DbTitle', '@DbName', '@DbManager',
+            '@DbLookup', '@DbExists', '@DbCommand', '@DbColumn', '@DB2Schema',
+            '@Day', '@Date', '@Created', '@Count', '@Cos', '@Contains',
+            '@ConfigFile', '@Compare', '@Command', '@ClientType',
+            '@CheckFormulaSyntax', '@CheckAlarms', '@Char', '@Certificate',
+            '@BusinessDays', '@BrowserInfo', '@Begins', '@Author',
+            '@Attachments', '@AttachmentNames', '@AttachmentModifiedTimes',
+            '@AttachmentLengths', '@ATan2', '@ATan', '@ASin', '@Ascii',
+            '@AllDescendants', '@AllChildren', '@All', '@AdminECLIsLocked',
+            '@Adjust', '@AddToFolder', '@ACos', '@Accessed', '@AbstractSimple',
+            '@Abstract', '@Abs'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #800000;',
+            2 => 'color: #0000FF;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #008000;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000000;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #FF00FF;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #FF00FF;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #0000AA;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 2
+    );
+
+?>
diff --git a/examples/includes/geshi/geshi/lotusscript.php b/examples/includes/geshi/geshi/lotusscript.php
new file mode 100644 (file)
index 0000000..598da3b
--- /dev/null
@@ -0,0 +1,191 @@
+<?php
+/**
+ * lotusscript.php
+ * ------------------------
+ * Author: Richard Civil (info@richardcivil.net)
+ * Copyright: (c) 2008 Richard Civil (info@richardcivil.net), Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/04/12
+ *
+ * LotusScript language file for GeSHi.
+ *
+ * LotusScript source: IBM Lotus Notes/Domino 8 Designer Help
+ *
+ * CHANGES
+ * -------
+ * 2008/04/12 (1.0.7.22)
+ *     -  First Release
+ *
+ * TODO (2008/04/12)
+ * -----------------
+ *
+ *************************************************************************************
+ *
+ *   This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'LotusScript',
+    'COMMENT_SINGLE' => array(1 => "'"),
+    'COMMENT_MULTI' => array('%REM' => '%END REM'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"' , "|"),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array (
+            'Yield', 'Year', 'Xor', 'Write', 'With', 'Width', 'While', 'Wend',
+            'Weekday', 'VarType', 'Variant', 'Val', 'UString', 'UString$',
+            'UseLSX', 'Use', 'Until', 'Unlock', 'Unicode', 'Uni', 'UChr',
+            'UChr$', 'UCase', 'UCase$', 'UBound', 'TypeName', 'Type', 'TRUE',
+            'Trim', 'Trim$', 'Today', 'To', 'TimeValue', 'TimeSerial', 'Timer',
+            'TimeNumber', 'Time', 'Time$', 'Then', 'Text', 'Tan', 'Tab', 'Sub',
+            'StrToken', 'StrToken$', 'StrRightBack', 'StrRightBack$',
+            'StrRight', 'StrRight$', 'StrLeftBack', 'StrLeftBack$', 'StrLeft',
+            'StrLeft$', 'String', 'String$', 'StrConv', 'StrCompare', 'StrComp',
+            'Str', 'Str$', 'Stop', 'Step', 'Static', 'Sqr', 'Split', 'Spc',
+            'Space', 'Space$', 'Sleep', 'Single', 'Sin', 'Shell', 'Shared',
+            'Sgn', 'SetFileAttr', 'SetAttr', 'Set', 'SendKeys', 'Select',
+            'Seek', 'Second', 'RTrim', 'RTrim$', 'RSet', 'Round', 'Rnd',
+            'RmDir', 'RightC', 'RightC$', 'RightBP', 'RightBP$', 'RightB',
+            'RightB$', 'Right', 'Right$', 'Return', 'Resume', 'Reset',
+            'Replace', 'Remove', 'Rem', 'ReDim', 'Read', 'Randomize',
+            'Random', 'Put', 'Public', 'Property', 'Private', 'Print',
+            'Preserve', 'Pitch', 'PI', 'Output', 'Or', 'Option', 'Open', 'On',
+            'Oct', 'Oct$', 'NULL', 'Now', 'NOTHING', 'Not', 'NoPitch', 'NoCase',
+            'Next', 'New', 'Name', 'MsgBox', 'Month', 'Mod', 'MkDir', 'Minute',
+            'MidC', 'MidC$', 'MidBP', 'MidBP$', 'MidB', 'MidB$', 'Mid', 'Mid$',
+            'MessageBox', 'Me', 'LTrim', 'LTrim$', 'LSServer', 'LSI_Info',
+            'LSet', 'Loop', 'Long', 'Log', 'LOF', 'Lock', 'LOC', 'LMBCS',
+            'ListTag', 'List', 'Line', 'Like', 'Lib', 'Let', 'LenC', 'LenBP',
+            'LenB', 'Len', 'LeftC', 'LeftC$', 'LeftBP', 'LeftBP$', 'LeftB',
+            'LeftB$', 'Left', 'Left$', 'LCase', 'LCase$', 'LBound', 'Kill',
+            'Join', 'IsUnknown', 'IsScalar', 'IsObject', 'IsNumeric', 'IsNull',
+            'IsList', 'IsEmpty', 'IsElement', 'IsDate', 'IsArray', 'IsA', 'Is',
+            'Integer', 'Int', 'InStrC', 'InStrBP', 'InStrB', 'InStr', 'InputBP',
+            'InputBP$', 'InputBox', 'InputBox$', 'InputB', 'InputB$', 'Input',
+            'Input$', 'In', 'IMSetMode', 'Implode', 'Implode$', 'Imp',
+            'IMEStatus', 'If', 'Hour', 'Hex', 'Hex$', 'Goto', 'GoSub',
+            'GetThreadInfo', 'GetFileAttr', 'GetAttr', 'Get', 'Function',
+            'FullTrim', 'From', 'FreeFile', 'Fraction', 'Format', 'Format$',
+            'ForAll', 'For', 'Fix', 'FileLen', 'FileDateTime', 'FileCopy',
+            'FileAttr', 'FALSE', 'Explicit', 'Exp', 'Exit', 'Execute', 'Event',
+            'Evaluate', 'Error', 'Error$', 'Err', 'Erl', 'Erase', 'Eqv', 'EOF',
+            'Environ', 'Environ$', 'End', 'ElseIf', 'Else', 'Double', 'DoEvents',
+            'Do', 'Dir', 'Dir$', 'Dim', 'DestroyLock', 'Delete', 'DefVar',
+            'DefStr', 'DefSng', 'DefLng', 'DefInt', 'DefDbl', 'DefCur',
+            'DefByte', 'DefBool', 'Declare', 'Day', 'DateValue', 'DateSerial',
+            'DateNumber', 'Date', 'Date$', 'DataType', 'CVDate', 'CVar',
+            'Currency', 'CurDrive', 'CurDrive$', 'CurDir', 'CurDir$', 'CStr',
+            'CSng', 'CreateLock', 'Cos', 'Const', 'Compare', 'Command',
+            'Command$', 'CodeUnlock', 'CodeLockCheck', 'CodeLock', 'Close',
+            'CLng', 'Class', 'CInt', 'Chr', 'Chr$', 'ChDrive', 'ChDir', 'CDbl',
+            'CDat', 'CCur', 'CByte', 'CBool', 'Case', 'Call', 'ByVal', 'Byte',
+            'Boolean', 'Bind', 'Binary', 'Bin', 'Bin$', 'Beep', 'Base', 'Atn2',
+            'Atn', 'ASin', 'Asc', 'As', 'ArrayUnique', 'ArrayReplace',
+            'ArrayGetIndex', 'ArrayAppend', 'Append', 'AppActivate', 'Any',
+            'And', 'Alias', 'ActivateApp', 'ACos', 'Access', 'Abs', '%Include',
+            '%If', '%END', '%ElseIf', '%Else'
+            ),
+        2 => array (
+            'NotesXSLTransformer', 'NotesXMLProcessor', 'NotesViewNavigator',
+            'NotesViewEntryCollection', 'NotesViewEntry', 'NotesViewColumn',
+            'NotesView', 'NotesUIWorkspace', 'NotesUIView', 'NotesUIScheduler',
+            'NotesUIDocument', 'NotesUIDatabase', 'NotesTimer', 'NotesStream',
+            'NotesSession', 'NotesSAXParser', 'NotesSAXException',
+            'NotesSAXAttributeList', 'NotesRichTextTable', 'NotesRichTextTab',
+            'NotesRichTextStyle', 'NotesRichTextSection', 'NotesRichTextRange',
+            'NotesRichTextParagraphStyle', 'NotesRichTextNavigator',
+            'NotesRichTextItem', 'NotesRichTextDocLink',
+            'NotesReplicationEntry', 'NotesReplication', 'NotesRegistration',
+            'NotesOutlineEntry', 'NotesOutline', 'NotesNoteCollection',
+            'NotesNewsLetter', 'NotesName', 'NotesMIMEHeader',
+            'NotesMIMEEntity', 'NotesLog', 'NotesItem', 'NotesInternational',
+            'NotesForm', 'NotesEmbeddedObject', 'NotesDXLImporter',
+            'NotesDXLExporter', 'NotesDOMXMLDeclNode', 'NotesDOMTextNode',
+            'NotesDOMProcessingInstructionNode', 'NotesDOMParser',
+            'NotesDOMNotationNode', 'NotesDOMNodeList', 'NotesDOMNode',
+            'NotesDOMNamedNodeMap', 'NotesDOMEntityReferenceNode',
+            'NotesDOMEntityNode', 'NotesDOMElementNode',
+            'NotesDOMDocumentTypeNode', 'NotesDOMDocumentNode',
+            'NotesDOMDocumentFragmentNode', 'NotesDOMCommentNode',
+            'NotesDOMCharacterDataNote', 'NotesDOMCDATASectionNode',
+            'NotesDOMAttributeNode', 'NotesDocumentCollection', 'NotesDocument',
+            'NotesDbDirectory', 'NotesDateTime', 'NotesDateRange',
+            'NotesDatabase', 'NotesColorObject', 'NotesAgent',
+            'NotesAdministrationProcess', 'NotesACLEntry', 'NotesACL',
+            'Navigator', 'Field', 'Button'
+            )
+        ) ,
+    'SYMBOLS' => array(
+        '(', ')'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0000FF;',
+            2 => 'color: #0000EE;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #008000;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000000;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #000000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #FF00FF;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #0000AA;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #006600;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 2
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/lscript.php b/examples/includes/geshi/geshi/lscript.php
new file mode 100644 (file)
index 0000000..57bb2ba
--- /dev/null
@@ -0,0 +1,387 @@
+<?php
+/*************************************************************************************
+ * lscript.php
+ * ---------
+ * Author: Arendedwinter (admin@arendedwinter.com)
+ * Copyright: (c) 2008 Beau McGuigan (http://www.arendedwinter.com)
+ * Release Version: 1.0.8.3
+ * Date Started: 15/11/2008
+ *
+ * Lightwave Script language file for GeSHi.
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'LScript',
+    'COMMENT_SINGLE' => array(1 => '//'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+    //Yes, I'm aware these are out of order,
+    //I had to rearrange and couldn't be bothered changing the numbers...
+        7 => array(
+            '@data', '@define', '@else', '@end', '@fpdepth', '@if', '@include',
+            '@insert', '@library', '@localipc', '@name', '@save', '@script',
+            '@sequence', '@version', '@warnings'
+            ),
+        1 => array(
+            'break', 'case', 'continue', 'else', 'end', 'false', 'for',
+            'foreach', 'if', 'return', 'switch', 'true', 'while',
+            ),
+        3 => array(
+            'active', 'alertlevel', 'alpha', 'alphaprefix', 'animfilename', 'autokeycreate',
+            'backdroptype', 'blue', 'boxthreshold', 'button',
+            'channelsvisible', 'childrenvisible', 'compfg', 'compbg', 'compfgalpha',
+            'coneangles', 'cosine', 'count', 'ctl', 'curFilename', 'curFrame',
+            'currenttime', 'curTime', 'curType',
+            'depth', 'diffshade', 'diffuse', 'dimensions', 'displayopts', 'dynamicupdate',
+            'end', 'eta',
+            'filename', 'flags', 'fogtype', 'fps', 'frame', 'frameend', 'frameheight',
+            'framestart', 'framestep', 'framewidth',
+            'generalopts', 'genus', 'geometry', 'gNorm', 'goal', 'green',
+            'h', 'hasAlpha', 'height',
+            'id', 'innerlimit', 'isColor',
+            'keyCount', 'keys',
+            'limiteregion', 'locked', 'luminous',
+            'maxsamplesperpixel', 'minsamplesperpixel', 'mirror', 'motionx', 'motiony',
+            'name', 'newFilename', 'newFrame', 'newTime', 'newType', 'null', 'numthreads',
+            'objID', 'oPos', 'outerlimit', 'oXfrm',
+            'parent', 'pixel', 'pixelaspect', 'point', 'points', 'pointcount', 'polNum',
+            'polycount', 'polygon', 'polygons', 'postBehavior', 'preBehavior', 'previewend',
+            'previewstart', 'previewstep',
+            'range', 'rawblue', 'rawgreen', 'rawred', 'rayLength', 'raySource', 'red',
+            'reflectblue', 'reflectgreen', 'reflectred', 'recursiondepth', 'renderend',
+            'renderopts', 'renderstart', 'renderstep', 'rendertype', 'restlength',
+            'rgbprefix', 'roughness',
+            'selected', 'setColor', 'setPattern', 'shading', 'shadow', 'shadows',
+            'shadowtype', 'size', 'source', 'special', 'specshade', 'specular',
+            'spotsize', 'start', 'sx', 'sy', 'sz',
+            'target', 'totallayers', 'totalpoints', 'totalpolygons', 'trans', 'transparency',
+            'type',
+            'value', 'view', 'visible', 'visibility',
+            'w', 'width', 'wNorm', 'wPos', 'wXfrm',
+            'x', 'xoffset',
+            'y', 'yoffset',
+            'z'
+            ),
+        4 => array(
+            'addLayer', 'addParticle', 'alphaspot', 'ambient', 'asAsc', 'asBin',
+            'asInt', 'asNum', 'asStr', 'asVec', 'attach', 'axislocks',
+            'backdropColor', 'backdropRay', 'backdropSqueeze', 'bone', 'blurLength',
+            'close', 'color', 'contains', 'copy', 'createKey',
+            'deleteKey', 'detach', 'drawCircle', 'drawLine', 'drawPoint', 'drawText',
+            'drawTriangle',
+            'edit', 'eof', 'event',
+            'firstChannel', 'firstLayer', 'firstSelect', 'focalLength', 'fogColor',
+            'fogMaxAmount', 'fogMaxDist', 'fogMinAmount', 'fogMinDist',
+            'fovAngles', 'fStop', 'firstChild', 'focalDistance',
+            'get', 'getChannelGroup', 'getEnvelope', 'getForward', 'getKeyBias',
+            'getKeyContinuity', 'getKeyCurve', 'getKeyHermite', 'getKeyTension',
+            'getKeyTime', 'getKeyValue', 'getParticle', 'getPivot', 'getPosition',
+            'getRight', 'getRotation', 'getSelect', 'getScaling', 'getTag', 'getTexture',
+            'getUp', 'getValue', 'getWorldPosition', 'getWorldForward', 'getWorldRight',
+            'getWorldRotation', 'getWorldUp', 'globalBlur', 'globalMask', 'globalResolution',
+            'hasCCEnd', 'hasCCStart',
+            'illuminate', 'indexOf', 'isAscii', 'isAlnum', 'isAlpha', 'isBone',
+            'isCamera', 'isChannel', 'isChannelGroup', 'isCntrl', 'isCurve', 'isDigit',
+            'isEnvelope', 'isImage', 'isInt', 'isLight', 'isLower', 'isMapped', 'isMesh',
+            'isNil', 'isNum', 'IsOpen', 'isOriginal', 'isPrint', 'isPunct', 'isScene',
+            'isSpace', 'isStr', 'isUpper', 'isValid', 'isVMap', 'isVec', 'isXDigit',
+            'keyExists',
+            'layer', 'layerName', 'layerVisible', 'limits', 'line', 'linecount', 'load', 'luma',
+            'next', 'nextLayer', 'nextSelect', 'nextChannel', 'nextChild', 'nl',
+            'offset', 'open',
+            'pack', 'param', 'parse', 'paste', 'persist', 'polygonCount', 'position',
+            'rayCast', 'rayTrace', 'read', 'readByte', 'readInt', 'readNumber',
+            'readDouble', 'readShort', 'readString', 'readVector', 'reduce',
+            'remParticle', 'renderCamera', 'reopen', 'replace', 'reset', 'restParam',
+            'rewind', 'rgb', 'rgbambient', 'rgbcolor', 'rgbspot',
+            'save', 'schemaPosition', 'select', 'set', 'setChannelGroup', 'setKeyBias',
+            'setKeyContinuity', 'setKeyCurve',
+            'setKeyHermite', 'setKeyTension', 'setKeyValue', 'setParticle', 'setPoints',
+            'setTag', 'setValue', 'server', 'serverFlags', 'sortA', 'sortD', 'surface',
+            'trunc',
+            'write', 'writeln', 'writeByte', 'writeData', 'writeNumber', 'writeDouble',
+            'writeShort', 'writeString', 'writeVector',
+            'vertex', 'vertexCount',
+            'zoomFactor'
+            ),
+        2 => array(
+            'abs', 'acos', 'angle', 'append', 'ascii', 'asin', 'atan',
+            'binary',
+            'ceil', 'center', 'chdir', 'clearimage', 'cloned', 'comringattach',
+            'comringdecode', 'comringdetach', 'comringencode', 'comringmsg', 'cos',
+            'cosh', 'cot', 'cross2d', 'cross3d', 'csc', 'ctlstring', 'ctlinteger',
+            'ctlnumber', 'ctlvector', 'ctldistance', 'ctlchoice', 'ctltext',
+            'ctlcolor', 'ctlsurface', 'ctlfont', 'ctlpopup', 'ctledit', 'ctlpercent',
+            'ctlangle', 'ctlrgb', 'ctlhsv', 'ctlcheckbox', 'ctlstate', 'ctlfilename',
+            'ctlbutton', 'ctllistbox', 'ctlslider', 'ctlminislider', 'ctlsep', 'ctlimage',
+            'ctltab', 'ctlallitems', 'ctlmeshitems', 'ctlcameraitems', 'ctllightitems',
+            'ctlboneitems', 'ctlimageitems', 'ctlchannel', 'ctlviewport', 'Control_Management',
+            'ctlpage', 'ctlgroup', 'ctlposition', 'ctlactive', 'ctlvisible', 'ctlalign',
+            'ctlrefresh', 'ctlmenu', 'ctlinfo',
+            'date', 'debug', 'deg', 'dot2d', 'dot3d', 'drawborder', 'drawbox', 'drawcircle',
+            'drawelipse', 'drawerase', 'drawfillcircle', 'drawfillelipse', 'drawline',
+            'drawpixel', 'drawtext', 'drawtextwidth', 'drawtextheight', 'dump',
+            'error', 'exp', 'expose', 'extent',
+            'fac', 'filecrc', 'filedelete', 'fileexists', 'filefind', 'filerename',
+            'filestat', 'floor', 'format', 'frac', 'fullpath',
+            'gamma', 'getdir', 'getenv', 'getfile', 'getfirstitem', 'getsep', 'getvalue',
+            'globalrecall', 'globalstore',
+            'hash', 'hex', 'hostBuild', 'hostVersion', 'hypot',
+            'info', 'integer',
+            'library', 'licenseId', 'lscriptVersion', 'load', 'loadimage', 'log', 'log10',
+            'matchdirs', 'matchfiles', 'max', 'min', 'mkdir', 'mod', 'monend', 'moninit', 'monstep',
+            'nil', 'normalize', 'number',
+            'octal', 'overlayglyph',
+            'parse', 'platform', 'pow',
+            'rad', 'random', 'randu', 'range', 'read', 'readdouble', 'readInt', 'readNumber',
+            'readShort', 'recall', 'regexp', 'reqabort', 'reqbegin', 'reqend', 'reqisopen',
+            'reqkeyboard', 'reqopen', 'reqposition', 'reqpost', 'reqredraw',
+            'reqsize', 'reqresize', 'requpdate', 'rmdir', 'round', 'runningUnder',
+            'save', 'sec', 'select', 'selector', 'setdesc', 'setvalue', 'sin', 'sinh', 'size',
+            'sizeof', 'sleep', 'spawn', 'split', 'sqrt', 'step', 'store', 'string', 'strleft',
+            'strlower', 'strright', 'strsub', 'strupper',
+            'tan', 'tanh', 'targetobject', 'terminate', 'text', 'time',
+            'wait', 'warn', 'when', 'write', 'writeDouble', 'writeInt', 'writeNumber', 'writeShort',
+            'var', 'vector', 'visitnodes', 'vmag',
+            ),
+        5 => array(
+            'addcurve', 'addpoint', 'addpolygon', 'addquad', 'addtriangle', 'alignpols',
+            'autoflex', 'axisdrill',
+            'bend', 'bevel', 'boolean', 'boundingbox',
+            'changepart', 'changesurface', 'close', 'closeall', 'cmdseq', 'copy', 'copysurface',
+            'createsurface', 'cut',
+            'deformregion', 'delete',
+            'editbegin', 'editend', 'exit', 'extrude',
+            'fixedflex', 'flip', 'fontclear', 'fontcount', 'fontindex', 'fontload',
+            'fontname', 'fracsubdivide', 'freezecurves',
+            'getdefaultsurface',
+            'jitter',
+            'lathe', 'layerName', 'layerVisible', 'lyrbg', 'lyrdata', 'lyrempty', 'lyremptybg',
+            'lyremptyfg', 'lyrfg', 'lyrsetbg', 'lyrsetfg', 'lyrswap',
+            'magnet', 'make4patch', 'makeball', 'makebox', 'makecone', 'makedisc',
+            'maketesball', 'maketext', 'mergepoints', 'mergepols', 'meshedit', 'mirror',
+            'morphpols', 'move',
+            'new', 'nextsurface',
+            'paste', 'pathclone', 'pathextrude', 'pixel', 'pointcount', 'pointinfo',
+            'pointmove', 'pole', 'polycount', 'polyinfo', 'polynormal', 'polypointcount',
+            'polypoints', 'polysurface',
+            'quantize',
+            'railclone', 'railextrude', 'redo', 'removepols', 'rempoint', 'rempoly',
+            'renamesurface', 'revert', 'rotate',
+            'scale', 'selhide', 'selinvert', 'selmode', 'selpoint', 'selpolygon', 'selunhide',
+            'selectvmap', 'setlayername', 'setobject', 'setpivot', 'setsurface', 'shapebevel',
+            'shear', 'skinpols', 'smooth', 'smoothcurves', 'smoothscale', 'smoothshift',
+            'soliddrill', 'splitpols', 'subdivide', 'swaphidden',
+            'taper', 'triple', 'toggleCCend', 'toggleCCstart', 'togglepatches', 'twist',
+            'undo', 'undogroupend', 'undogroupbegin', 'unifypols', 'unweld',
+            'vortex',
+            'weldaverage', 'weldpoints'
+            ),
+        6 => array(
+            'About', 'AboutOpenGL', 'AdaptiveSampling', 'AdaptiveThreshold',
+            'AddAreaLight', 'AddBone', 'AddButton', 'AddCamera', 'AddChildBone',
+            'AddDistantLight', 'AddEnvelope', 'AddLinearLight', 'AddNull',
+            'AddPartigon', 'AddPlugins', 'AddPointLight', 'AddPosition',
+            'AddRotation', 'AddScale', 'AddSpotlight', 'AddToSelection',
+            'AdjustRegionTool', 'AffectCaustics', 'AffectDiffuse', 'AffectOpenGL',
+            'AffectSpecular', 'AlertLevel', 'AmbientColor', 'AmbientIntensity',
+            'Antialiasing', 'ApertureHeight', 'ApplyServer', 'AreaLight',
+            'AutoConfirm', 'AutoFrameAdvance', 'AutoKey',
+            'BackdropColor', 'BackView', 'BController', 'BLimits', 'BLurLength', 'BoneActive',
+            'BoneFalloffType', 'BoneJointComp', 'BoneJointCompAmounts', 'BoneJointCompParent',
+            'BoneLimitedRange', 'BoneMaxRange', 'BoneMinRange', 'BoneMuscleFlex',
+            'BoneMuscleFlexAmounts', 'BoneMuscleFlexParent', 'BoneNormalization',
+            'BoneRestLength', 'BoneRestPosition', 'BoneRestRotation', 'BoneSource',
+            'BoneStrength', 'BoneStrengthMultiply', 'BoneWeightMapName', 'BoneWeightMapOnly',
+            'BoneWeightShade', 'BoneXRay', 'BottomView', 'BoundingBoxThreshold',
+            'BStiffness',
+            'CacheCaustics', 'CacheRadiosity', 'CacheShadowMap',
+            'CameraMask', 'CameraView', 'CameraZoomTool', 'CastShadow', 'CausticIntensity',
+            'CenterItem', 'CenterMouse', 'ChangeTool', 'ClearAllBones', 'ClearAllCameras',
+            'ClearAllLights', 'ClearAllObjects', 'ClearAudio', 'ClearScene', 'ClearSelected',
+            'Clone', 'CommandHistory', 'CommandInput', 'Compositing', 'ConeAngleTool',
+            'ContentDirectory', 'CreateKey',
+            'DecreaseGrid', 'DeleteKey', 'DepthBufferAA', 'DepthOfField', 'DisplayOptions',
+            'DistantLight', 'DrawAntialiasing', 'DrawBones', 'DrawChildBones', 'DynamicUpdate',
+            'EditBones', 'EditCameras', 'EditKeys', 'EditLights',
+            'EditMenus', 'EditObjects', 'EditPlugins', 'EditServer', 'EnableCaustics',
+            'EnableDeformations', 'EnableIK', 'EnableLensFlares', 'EnableRadiosity', 'EnableServer',
+            'EnableShadowMaps', 'EnableVIPER', 'EnableVolumetricLights', 'EnableXH',
+            'EnableYP', 'EnableZB', 'EnahancedAA', 'ExcludeLight', 'ExcludeObject',
+            'EyeSeparation',
+            'FasterBones', 'FirstFrame', 'FirstItem', 'FitAll', 'FitSelected',
+            'FlareIntensity', 'FlareOptions', 'FocalDistance', 'FogColor', 'FogMaxAmount',
+            'FogMaxDistance', 'FogMinAmount', 'FogMinDistance', 'FogType', 'FractionalFrames',
+            'FrameSize', 'FramesPerSecond', 'FrameStep', 'FreePreview', 'FrontView', 'FullTimeIK',
+            'GeneralOptions', 'Generics', 'GlobalApertureHeight', 'GlobalBlurLength',
+            'GlobalFrameSize', 'GlobalIllumination', 'GlobalMaskPosition', 'GlobalMotionBlur',
+            'GlobalParticleBlur', 'GlobalPixelAspect', 'GlobalResolutionMulitplier', 'GoalItem',
+            'GoalStrength', 'GoToFrame', 'GradientBackdrop', 'GraphEditor', 'GridSize', 'GroundColor',
+            'HController', 'HideToolbar', 'HideWindows', 'HLimits', 'HStiffness',
+            'ImageEditor', 'ImageProcessing', 'IncludeLight', 'IncludeObject', 'IncreaseGrid',
+            'IndirectBounces', 'Item_SetWindowPos', 'ItemActive', 'ItemColor', 'ItemLock',
+            'ItemProperties', 'ItemVisibilty',
+            'KeepGoalWithinReach',
+            'LastFrame', 'LastItem', 'LastPluginInterface', 'Layout_SetWindowPos',
+            'Layout_SetWindowSize', 'LeftView', 'LensFlare', 'LensFStop', 'LightColor',
+            'LightConeAngle', 'LightEdgeAngle', 'LightFalloffType', 'LightIntensity',
+            'LightIntensityTool', 'LightQuality', 'LightRange', 'LightView', 'LimitB',
+            'LimitDynamicRange', 'LimitedRegion', 'LimitH', 'LimitP', 'LinearLight',
+            'LoadAudio', 'LoadFromScene', 'LoadMotion', 'LoadObject', 'LoadObjectLayer',
+            'LoadPreview', 'LoadScene', 'LocalCoordinateSystem',
+            'MakePreview', 'MaskColor', 'MaskPosition', 'MasterPlugins', 'MatchGoalOrientation',
+            'MatteColor', 'MatteObject', 'MetaballResolution', 'Model', 'MorphAmount',
+            'MorphAmountTool', 'MorphMTSE', 'MorphSurfaces', 'MorphTarget', 'MotionBlur',
+            'MotionBlurDOFPreview', 'MotionOptions', 'MovePathTool', 'MovePivotTool', 'MoveTool',
+            'NadirColor', 'NetRender', 'NextFrame', 'NextItem', 'NextKey', 'NextSibling',
+            'NextViewLayout', 'NoiseReduction', 'Numeric',
+            'ObjectDissolve',
+            'ParentCoordinateSystem', 'ParentInPlace', 'ParentItem',
+            'ParticleBlur', 'PathAlignLookAhead', 'PathAlignMaxLookSteps', 'PathAlignReliableDist',
+            'Pause', 'PController', 'PerspectiveView',
+            'PivotPosition', 'PivotRotation', 'PixelAspect', 'PlayAudio', 'PlayBackward',
+            'PlayForward', 'PlayPreview', 'PLimits', 'PointLight', 'PolygonEdgeColor',
+            'PolygonEdgeFlags', 'PolygonEdgeThickness', 'PolygonEdgeZScale', 'PolygonSize',
+            'Position', 'Presets', 'PreviewFirstFrame', 'PreviewFrameStep', 'PreviewLastFrame',
+            'PreviewOptions', 'PreviousFrame', 'PreviousItem', 'PreviousKey', 'PreviousSibling',
+            'PreviousViewLayout', 'PStiffness',
+            'Quit',
+            'RadiosityIntensity', 'RadiosityTolerance', 'RadiosityType', 'RayRecursionLimit',
+            'RayTraceReflection', 'RayTraceShadows',
+            'RayTraceTransparency', 'ReceiveShadow', 'RecentContentDirs', 'RecentScenes',
+            'ReconstructionFilter', 'RecordMaxAngles', 'RecordMinAngles', 'RecordPivotRotation',
+            'RecordRestPosition', 'Redraw', 'RedrawNow', 'Refresh', 'RefreshNow', 'RegionPosition',
+            'RemoveEnvelope', 'RemoveFromSelection', 'RemoveServer', 'Rename', 'RenderFrame',
+            'RenderOptions', 'RenderScene', 'RenderSelected', 'RenderThreads',
+            'ReplaceObjectLayer', 'ReplaceWithNull', 'ReplaceWithObject', 'Reset',
+            'ResolutionMultiplier', 'RestLengthTool', 'RightView', 'RotatePivotTool',
+            'RotateTool', 'Rotation',
+            'SaveAllObjects', 'SaveCommandList', 'SaveCommandMessages',
+            'SaveEndomorph', 'SaveLight', 'SaveLWSC1', 'SaveMotion', 'SaveObject', 'SaveObjectCopy',
+            'SavePreview', 'SaveScene', 'SaveSceneAs', 'SaveSceneCopy', 'SaveTransformed',
+            'SaveViewLayout', 'Scale', 'Scene_SetWindowPos', 'Scene_SetWindowSize',
+            'SceneEditor', 'SchematicPosition', 'SchematicView', 'SelectAllBones',
+            'SelectAllCameras', 'SelectAllLights', 'SelectAllObjects', 'SelectByName',
+            'SelectChild', 'SelectItem', 'SelectParent', 'SelfShadow', 'ShadowColor',
+            'ShadowExclusion', 'ShadowMapAngle', 'ShadowMapFitCone', 'ShadowMapFuzziness',
+            'ShadowMapSize', 'ShadowType', 'ShowCages', 'ShowFieldChart', 'ShowHandles',
+            'ShowIKChains', 'ShowMotionPaths', 'ShowSafeAreas', 'ShowTargetLines',
+            'ShrinkEdgesWithDistance', 'SingleView', 'SizeTool', 'SkelegonsToBones', 'SkyColor',
+            'Spotlight', 'SquashTool', 'Statistics', 'StatusMsg', 'Stereoscopic', 'StretchTool',
+            'SubdivisionOrder', 'SubPatchLevel', 'SurfaceEditor', 'Synchronize',
+            'TargetItem', 'TopView',
+            'UnaffectedByFog', 'UnaffectedByIK', 'Undo', 'UnseenByAlphaChannel', 'UnseenByCamera',
+            'UnseenByRays', 'UseGlobalResolution', 'UseGlobalBlur', 'UseGlobalMask',
+            'UseMorphedPositions',
+            'ViewLayout', 'VIPER', 'VolumetricLighting',
+            'VolumetricLightingOptions', 'VolumetricRadiosity', 'Volumetrics',
+            'WorldCoordinateSystem',
+            'XYView', 'XZView',
+            'ZenithColor', 'ZoomFactor', 'ZoomIn', 'ZoomInX2', 'ZoomOut', 'ZoomOutX2', 'ZYView',
+            'Camera', 'Channel', 'ChannelGroup', 'Envelope', 'File', 'Glyph', 'Icon', 'Image',
+            'Light', 'Mesh', 'Scene', 'Surface', 'VMap'
+            ),
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '{', '}', '[', ']', '=', '<', '>', '+', '-', '*', '/', '!', '%', '&', '@'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => true,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        5 => false,
+        6 => false,
+        7 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000000; font-weight: bold;',
+            2 => 'color: #FF6820; font-weight: bold;', //LS_COMMANDS
+            3 => 'color: #007F7F; font-weight: bold;', //LS_MEMBERS
+            4 => 'color: #800080; font-weight: bold;', //LS_METHODS
+            5 => 'color: #51BD95; font-weight: bold;', //LS_MODELER
+            6 => 'color: #416F85; font-weight: bold;', //LS_GENERAL
+            7 => 'color: #C92929; font-weight: bold;'  //LS_COMMANDS (cont)
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #7F7F7F;',
+            'MULTI' => 'color: #7F7F7F;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #0040A0;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #00C800;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #6953AC;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #0040A0;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            ),
+        'ESCAPE_CHAR' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => '',
+        5 => '',
+        6 => '',
+        7 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4,
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            3 => array(
+                'DISALLOWED_BEFORE' => '(?<=\.)'
+                ),
+            4 => array(
+                'DISALLOWED_BEFORE' => '(?<=\.)'
+                )
+            )
+        )
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/lsl2.php b/examples/includes/geshi/geshi/lsl2.php
new file mode 100644 (file)
index 0000000..27c5580
--- /dev/null
@@ -0,0 +1,898 @@
+<?php
+/*************************************************************************************
+ * lsl2.php
+ * --------
+ * Author: William Fry (william.fry@nyu.edu)
+ * Copyright: (c) 2009 William Fry
+ * Release Version: 1.0.8.3
+ * Date Started: 2009/02/04
+ *
+ * Linden Scripting Language (LSL2) language file for GeSHi.
+ *
+ *   Data derived and validated against the following:
+ *      http://wiki.secondlife.com/wiki/LSL_Portal
+ *      http://www.lslwiki.net/lslwiki/wakka.php?wakka=HomePage
+ *      http://rpgstats.com/wiki/index.php?title=Main_Page
+ *
+ * CHANGES
+ * -------
+ * 2009/02/05 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2009/02/05)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'LSL2',
+    'COMMENT_SINGLE' => array(1 => '//'),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array( // flow control
+            'do',
+            'else',
+            'for',
+            'if',
+            'jump',
+            'return',
+            'state',
+            'while',
+            ),
+        2 => array( // manifest constants
+            'ACTIVE',
+            'AGENT',
+            'AGENT_ALWAYS_RUN',
+            'AGENT_ATTACHMENTS',
+            'AGENT_AWAY',
+            'AGENT_BUSY',
+            'AGENT_CROUCHING',
+            'AGENT_FLYING',
+            'AGENT_IN_AIR',
+            'AGENT_MOUSELOOK',
+            'AGENT_ON_OBJECT',
+            'AGENT_SCRIPTED',
+            'AGENT_SITTING',
+            'AGENT_TYPING',
+            'AGENT_WALKING',
+            'ALL_SIDES',
+            'ANIM_ON',
+            'ATTACH_BACK',
+            'ATTACH_BELLY',
+            'ATTACH_CHEST',
+            'ATTACH_CHIN',
+            'ATTACH_HEAD',
+            'ATTACH_HUD_BOTTOM',
+            'ATTACH_HUD_BOTTOM_LEFT',
+            'ATTACH_HUD_BOTTOM_RIGHT',
+            'ATTACH_HUD_CENTER_1',
+            'ATTACH_HUD_CENTER_2',
+            'ATTACH_HUD_TOP_CENTER',
+            'ATTACH_HUD_TOP_LEFT',
+            'ATTACH_HUD_TOP_RIGHT',
+            'ATTACH_LEAR',
+            'ATTACH_LEYE',
+            'ATTACH_LFOOT',
+            'ATTACH_LHAND',
+            'ATTACH_LHIP',
+            'ATTACH_LLARM',
+            'ATTACH_LLLEG',
+            'ATTACH_LPEC',
+            'ATTACH_LSHOULDER',
+            'ATTACH_LUARM',
+            'ATTACH_LULEG',
+            'ATTACH_MOUTH',
+            'ATTACH_NOSE',
+            'ATTACH_PELVIS',
+            'ATTACH_REAR',
+            'ATTACH_REYE',
+            'ATTACH_RFOOT',
+            'ATTACH_RHAND',
+            'ATTACH_RHIP',
+            'ATTACH_RLARM',
+            'ATTACH_RLLEG',
+            'ATTACH_RPEC',
+            'ATTACH_RSHOULDER',
+            'ATTACH_RUARM',
+            'ATTACH_RULEG',
+            'CAMERA_ACTIVE',
+            'CAMERA_BEHINDNESS_ANGLE',
+            'CAMERA_BEHINDNESS_LAG',
+            'CAMERA_DISTANCE',
+            'CAMERA_FOCUS',
+            'CAMERA_FOCUS_LAG',
+            'CAMERA_FOCUS_LOCKED',
+            'CAMERA_FOCUS_OFFSET',
+            'CAMERA_FOCUS_THRESHOLD',
+            'CAMERA_PITCH',
+            'CAMERA_POSITION',
+            'CAMERA_POSITION_LAG',
+            'CAMERA_POSITION_LOCKED',
+            'CAMERA_POSITION_THRESHOLD',
+            'CHANGED_ALLOWED_DROP',
+            'CHANGED_COLOR',
+            'CHANGED_INVENTORY',
+            'CHANGED_LINK',
+            'CHANGED_OWNER',
+            'CHANGED_REGION',
+            'CHANGED_SCALE',
+            'CHANGED_SHAPE',
+            'CHANGED_TELEPORT',
+            'CHANGED_TEXTURE',
+            'CLICK_ACTION_NONE',
+            'CLICK_ACTION_OPEN',
+            'CLICK_ACTION_OPEN_MEDIA',
+            'CLICK_ACTION_PAY',
+            'CLICK_ACTION_SIT',
+            'CLICK_ACTION_TOUCH',
+            'CONTROL_BACK',
+            'CONTROL_DOWN',
+            'CONTROL_FWD',
+            'CONTROL_LBUTTON',
+            'CONTROL_LEFT',
+            'CONTROL_ML_LBUTTON',
+            'CONTROL_RIGHT',
+            'CONTROL_ROT_LEFT',
+            'CONTROL_ROT_RIGHT',
+            'CONTROL_UP',
+            'DATA_BORN',
+            'DATA_NAME',
+            'DATA_ONLINE',
+            'DATA_PAYINFO',
+            'DATA_RATING',
+            'DATA_SIM_POS',
+            'DATA_SIM_RATING',
+            'DATA_SIM_STATUS',
+            'DEBUG_CHANNEL',
+            'DEG_TO_RAD',
+            'EOF',
+            'FALSE',
+            'HTTP_BODY_MAXLENGTH',
+            'HTTP_BODY_TRUNCATED',
+            'HTTP_METHOD',
+            'HTTP_MIMETYPE',
+            'HTTP_VERIFY_CERT',
+            'INVENTORY_ALL',
+            'INVENTORY_ANIMATION',
+            'INVENTORY_BODYPART',
+            'INVENTORY_CLOTHING',
+            'INVENTORY_GESTURE',
+            'INVENTORY_LANDMARK',
+            'INVENTORY_NONE',
+            'INVENTORY_NOTECARD',
+            'INVENTORY_OBJECT',
+            'INVENTORY_SCRIPT',
+            'INVENTORY_SOUND',
+            'INVENTORY_TEXTURE',
+            'LAND_LEVEL',
+            'LAND_LOWER',
+            'LAND_NOISE',
+            'LAND_RAISE',
+            'LAND_REVERT',
+            'LAND_SMOOTH',
+            'LINK_ALL_CHILDREN',
+            'LINK_ALL_OTHERS',
+            'LINK_ROOT',
+            'LINK_SET',
+            'LINK_THIS',
+            'LIST_STAT_GEOMETRIC_MEAN',
+            'LIST_STAT_MAX',
+            'LIST_STAT_MEAN',
+            'LIST_STAT_MEDIAN',
+            'LIST_STAT_MIN',
+            'LIST_STAT_NUM_COUNT',
+            'LIST_STAT_RANGE',
+            'LIST_STAT_STD_DEV',
+            'LIST_STAT_SUM',
+            'LIST_STAT_SUM_SQUARES',
+            'LOOP',
+            'MASK_BASE',
+            'MASK_EVERYONE',
+            'MASK_GROUP',
+            'MASK_NEXT',
+            'MASK_OWNER',
+            'NULL_KEY',
+            'OBJECT_CREATOR',
+            'OBJECT_DESC',
+            'OBJECT_GROUP',
+            'OBJECT_NAME',
+            'OBJECT_OWNER',
+            'OBJECT_POS',
+            'OBJECT_ROT',
+            'OBJECT_UNKNOWN_DETAIL',
+            'OBJECT_VELOCITY',
+            'PARCEL_DETAILS_AREA',
+            'PARCEL_DETAILS_DESC',
+            'PARCEL_DETAILS_GROUP',
+            'PARCEL_DETAILS_NAME',
+            'PARCEL_DETAILS_OWNER',
+            'PARCEL_FLAG_ALLOW_ALL_OBJECT_ENTRY',
+            'PARCEL_FLAG_ALLOW_CREATE_GROUP_OBJECTS',
+            'PARCEL_FLAG_ALLOW_CREATE_OBJECTS',
+            'PARCEL_FLAG_ALLOW_DAMAGE',
+            'PARCEL_FLAG_ALLOW_FLY',
+            'PARCEL_FLAG_ALLOW_GROUP_OBJECT_ENTRY',
+            'PARCEL_FLAG_ALLOW_GROUP_SCRIPTS',
+            'PARCEL_FLAG_ALLOW_LANDMARK',
+            'PARCEL_FLAG_ALLOW_SCRIPTS',
+            'PARCEL_FLAG_ALLOW_TERRAFORM',
+            'PARCEL_FLAG_LOCAL_SOUND_ONLY',
+            'PARCEL_FLAG_RESTRICT_PUSHOBJECT',
+            'PARCEL_FLAG_USE_ACCESS_GROUP',
+            'PARCEL_FLAG_USE_ACCESS_LIST',
+            'PARCEL_FLAG_USE_BAN_LIST',
+            'PARCEL_FLAG_USE_LAND_PASS_LIST',
+            'PARCEL_MEDIA_COMMAND_AGENT',
+            'PARCEL_MEDIA_COMMAND_AUTO_ALIGN',
+            'PARCEL_MEDIA_COMMAND_DESC',
+            'PARCEL_MEDIA_COMMAND_LOOP_SET',
+            'PARCEL_MEDIA_COMMAND_PAUSE',
+            'PARCEL_MEDIA_COMMAND_PLAY',
+            'PARCEL_MEDIA_COMMAND_SIZE',
+            'PARCEL_MEDIA_COMMAND_STOP',
+            'PARCEL_MEDIA_COMMAND_TEXTURE',
+            'PARCEL_MEDIA_COMMAND_TIME',
+            'PARCEL_MEDIA_COMMAND_TYPE',
+            'PARCEL_MEDIA_COMMAND_URL',
+            'PASSIVE',
+            'PAYMENT_INFO_ON_FILE',
+            'PAYMENT_INFO_USED',
+            'PAY_DEFAULT',
+            'PAY_HIDE',
+            'PERMISSION_ATTACH',
+            'PERMISSION_CHANGE_LINKS',
+            'PERMISSION_CONTROL_CAMERA',
+            'PERMISSION_DEBIT',
+            'PERMISSION_TAKE_CONTROLS',
+            'PERMISSION_TRACK_CAMERA',
+            'PERMISSION_TRIGGER_ANIMATION',
+            'PERM_ALL',
+            'PERM_COPY',
+            'PERM_MODIFY',
+            'PERM_MOVE',
+            'PERM_TRANSFER',
+            'PI',
+            'PI_BY_TWO',
+            'PRIM_BUMP_BARK',
+            'PRIM_BUMP_BLOBS',
+            'PRIM_BUMP_BRICKS',
+            'PRIM_BUMP_BRIGHT',
+            'PRIM_BUMP_CHECKER',
+            'PRIM_BUMP_CONCRETE',
+            'PRIM_BUMP_DARK',
+            'PRIM_BUMP_DISKS',
+            'PRIM_BUMP_GRAVEL',
+            'PRIM_BUMP_LARGETILE',
+            'PRIM_BUMP_NONE',
+            'PRIM_BUMP_SHINY',
+            'PRIM_BUMP_SIDING',
+            'PRIM_BUMP_STONE',
+            'PRIM_BUMP_STUCCO',
+            'PRIM_BUMP_SUCTION',
+            'PRIM_BUMP_TILE',
+            'PRIM_BUMP_WEAVE',
+            'PRIM_BUMP_WOOD',
+            'PRIM_COLOR',
+            'PRIM_FULLBRIGHT',
+            'PRIM_HOLE_CIRCLE',
+            'PRIM_HOLE_DEFAULT',
+            'PRIM_HOLE_SQUARE',
+            'PRIM_HOLE_TRIANGLE',
+            'PRIM_MATERIAL',
+            'PRIM_MATERIAL_FLESH',
+            'PRIM_MATERIAL_GLASS',
+            'PRIM_MATERIAL_LIGHT',
+            'PRIM_MATERIAL_METAL',
+            'PRIM_MATERIAL_PLASTIC',
+            'PRIM_MATERIAL_RUBBER',
+            'PRIM_MATERIAL_STONE',
+            'PRIM_MATERIAL_WOOD',
+            'PRIM_PHANTOM',
+            'PRIM_PHYSICS',
+            'PRIM_POSITION',
+            'PRIM_ROTATION',
+            'PRIM_SHINY_HIGH',
+            'PRIM_SHINY_LOW',
+            'PRIM_SHINY_MEDIUM',
+            'PRIM_SHINY_NONE',
+            'PRIM_SIZE',
+            'PRIM_TEMP_ON_REZ',
+            'PRIM_TEXTURE',
+            'PRIM_TYPE',
+            'PRIM_TYPE_BOX',
+            'PRIM_TYPE_CYLINDER',
+            'PRIM_TYPE_PRISM',
+            'PRIM_TYPE_RING',
+            'PRIM_TYPE_SPHERE',
+            'PRIM_TYPE_TORUS',
+            'PRIM_TYPE_TUBE',
+            'PSYS_PART_BOUNCE_MASK',
+            'PSYS_PART_EMISSIVE_MASK',
+            'PSYS_PART_END_ALPHA',
+            'PSYS_PART_END_COLOR',
+            'PSYS_PART_END_SCALE',
+            'PSYS_PART_FLAGS',
+            'PSYS_PART_FOLLOW_SRC_MASK',
+            'PSYS_PART_FOLLOW_VELOCITY_MASK',
+            'PSYS_PART_INTERP_COLOR_MASK',
+            'PSYS_PART_INTERP_SCALE_MASK',
+            'PSYS_PART_MAX_AGE',
+            'PSYS_PART_START_ALPHA',
+            'PSYS_PART_START_COLOR',
+            'PSYS_PART_START_SCALE',
+            'PSYS_PART_TARGET_LINEAR_MASK',
+            'PSYS_PART_TARGET_POS_MASK',
+            'PSYS_PART_WIND_MASK',
+            'PSYS_SRC_ACCEL',
+            'PSYS_SRC_ANGLE_BEGIN',
+            'PSYS_SRC_ANGLE_END',
+            'PSYS_SRC_BURST_PART_COUNT',
+            'PSYS_SRC_BURST_RADIUS',
+            'PSYS_SRC_BURST_RATE',
+            'PSYS_SRC_BURST_SPEED_MAX',
+            'PSYS_SRC_BURST_SPEED_MIN',
+            'PSYS_SRC_INNERANGLE',
+            'PSYS_SRC_MAX_AGE',
+            'PSYS_SRC_OMEGA',
+            'PSYS_SRC_OUTERANGLE',
+            'PSYS_SRC_PATTERN',
+            'PSYS_SRC_PATTERN_ANGLE',
+            'PSYS_SRC_PATTERN_ANGLE_CONE',
+            'PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY',
+            'PSYS_SRC_PATTERN_DROP',
+            'PSYS_SRC_PATTERN_EXPLODE',
+            'PSYS_SRC_TARGET_KEY',
+            'PSYS_SRC_TEXTURE',
+            'RAD_TO_DEG',
+            'REMOTE_DATA_CHANNEL',
+            'REMOTE_DATA_REQUEST',
+            'SCRIPTED',
+            'SQRT2',
+            'STATUS_BLOCK_GRAB',
+            'STATUS_DIE_AT_EDGE',
+            'STATUS_PHANTOM',
+            'STATUS_PHYSICS',
+            'STATUS_RETURN_AT_EDGE',
+            'STATUS_ROTATE_X',
+            'STATUS_ROTATE_Y',
+            'STATUS_ROTATE_Z',
+            'STATUS_SANDBOX',
+            'TRUE',
+            'TWO_PI',
+            'VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY',
+            'VEHICLE_ANGULAR_DEFLECTION_TIMESCALE',
+            'VEHICLE_ANGULAR_FRICTION_TIMESCALE',
+            'VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE',
+            'VEHICLE_ANGULAR_MOTOR_DIRECTION',
+            'VEHICLE_ANGULAR_MOTOR_TIMESCALE',
+            'VEHICLE_BANKING_EFFICIENCY',
+            'VEHICLE_BANKING_MIX',
+            'VEHICLE_BANKING_TIMESCALE',
+            'VEHICLE_BUOYANCY',
+            'VEHICLE_FLAG_CAMERA_DECOUPLED',
+            'VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT',
+            'VEHICLE_FLAG_HOVER_TERRAIN_ONLY',
+            'VEHICLE_FLAG_HOVER_UP_ONLY',
+            'VEHICLE_FLAG_HOVER_WATER_ONLY',
+            'VEHICLE_FLAG_LIMIT_MOTOR_UP',
+            'VEHICLE_FLAG_LIMIT_ROLL_ONLY',
+            'VEHICLE_FLAG_MOUSELOOK_BANK',
+            'VEHICLE_FLAG_MOUSELOOK_STEER',
+            'VEHICLE_FLAG_NO_DEFLECTION_UP',
+            'VEHICLE_HOVER_EFFICIENCY',
+            'VEHICLE_HOVER_HEIGHT',
+            'VEHICLE_HOVER_TIMESCALE',
+            'VEHICLE_LINEAR_DEFLECTION_EFFICIENCY',
+            'VEHICLE_LINEAR_DEFLECTION_TIMESCALE',
+            'VEHICLE_LINEAR_FRICTION_TIMESCALE',
+            'VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE',
+            'VEHICLE_LINEAR_MOTOR_DIRECTION',
+            'VEHICLE_LINEAR_MOTOR_OFFSET',
+            'VEHICLE_LINEAR_MOTOR_TIMESCALE',
+            'VEHICLE_REFERENCE_FRAME',
+            'VEHICLE_TYPE_AIRPLANE',
+            'VEHICLE_TYPE_BALLOON',
+            'VEHICLE_TYPE_BOAT',
+            'VEHICLE_TYPE_CAR',
+            'VEHICLE_TYPE_NONE',
+            'VEHICLE_TYPE_SLED',
+            'VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY',
+            'VEHICLE_VERTICAL_ATTRACTION_TIMESCALE',
+            'ZERO_ROTATION',
+            'ZERO_VECTOR',
+            ),
+        3 => array( // handlers
+            'at_rot_target',
+            'at_target',
+            'attached',
+            'changed',
+            'collision',
+            'collision_end',
+            'collision_start',
+            'control',
+            'dataserver',
+            'email',
+            'http_response',
+            'land_collision',
+            'land_collision_end',
+            'land_collision_start',
+            'link_message',
+            'listen',
+            'money',
+            'moving_end',
+            'moving_start',
+            'no_sensor',
+            'not_at_rot_target',
+            'not_at_target',
+            'object_rez',
+            'on_rez',
+            'remote_data',
+            'run_time_permissions',
+            'sensor',
+            'state_entry',
+            'state_exit',
+            'timer',
+            'touch',
+            'touch_end',
+            'touch_start',
+            ),
+        4 => array( // data types
+            'float',
+            'integer',
+            'key',
+            'list',
+            'rotation',
+            'string',
+            'vector',
+            ),
+        5 => array( // library
+            'default',
+            'llAbs',
+            'llAcos',
+            'llAddToLandBanList',
+            'llAddToLandPassList',
+            'llAdjustSoundVolume',
+            'llAllowInventoryDrop',
+            'llAngleBetween',
+            'llApplyImpulse',
+            'llApplyRotationalImpulse',
+            'llAsin',
+            'llAtan2',
+            'llAttachToAvatar',
+            'llAvatarOnSitTarget',
+            'llAxes2Rot',
+            'llAxisAngle2Rot',
+            'llBase64ToInteger',
+            'llBase64ToString',
+            'llBreakAllLinks',
+            'llBreakLink',
+            'llCeil',
+            'llClearCameraParams',
+            'llCloseRemoteDataChannel',
+            'llCloud',
+            'llCollisionFilter',
+            'llCollisionSound',
+            'llCollisionSprite',
+            'llCos',
+            'llCreateLink',
+            'llCSV2List',
+            'llDeleteSubList',
+            'llDeleteSubString',
+            'llDetachFromAvatar',
+            'llDetectedGrab',
+            'llDetectedGroup',
+            'llDetectedKey',
+            'llDetectedLinkNumber',
+            'llDetectedName',
+            'llDetectedOwner',
+            'llDetectedPos',
+            'llDetectedRot',
+            'llDetectedTouchBinormal',
+            'llDetectedTouchFace',
+            'llDetectedTouchNormal',
+            'llDetectedTouchPos',
+            'llDetectedTouchST',
+            'llDetectedTouchUV',
+            'llDetectedType',
+            'llDetectedVel',
+            'llDialog',
+            'llDie',
+            'llDumpList2String',
+            'llEdgeOfWorld',
+            'llEjectFromLand',
+            'llEmail',
+            'llEscapeURL',
+            'llEuler2Rot',
+            'llFabs',
+            'llFloor',
+            'llForceMouselook',
+            'llFrand',
+            'llGetAccel',
+            'llGetAgentInfo',
+            'llGetAgentLanguage',
+            'llGetAgentSize',
+            'llGetAlpha',
+            'llGetAndResetTime',
+            'llGetAnimation',
+            'llGetAnimationList',
+            'llGetAttached',
+            'llGetBoundingBox',
+            'llGetCameraPos',
+            'llGetCameraRot',
+            'llGetCenterOfMass',
+            'llGetColor',
+            'llGetCreator',
+            'llGetDate',
+            'llGetEnergy',
+            'llGetForce',
+            'llGetFreeMemory',
+            'llGetGeometricCenter',
+            'llGetGMTclock',
+            'llGetInventoryCreator',
+            'llGetInventoryKey',
+            'llGetInventoryName',
+            'llGetInventoryNumber',
+            'llGetInventoryPermMask',
+            'llGetInventoryType',
+            'llGetKey',
+            'llGetLandOwnerAt',
+            'llGetLinkKey',
+            'llGetLinkName',
+            'llGetLinkNumber',
+            'llGetListEntryType',
+            'llGetListLength',
+            'llGetLocalPos',
+            'llGetLocalRot',
+            'llGetMass',
+            'llGetNextEmail',
+            'llGetNotecardLine',
+            'llGetNumberOfNotecardLines',
+            'llGetNumberOfPrims',
+            'llGetNumberOfSides',
+            'llGetObjectDesc',
+            'llGetObjectDetails',
+            'llGetObjectMass',
+            'llGetObjectName',
+            'llGetObjectPermMask',
+            'llGetObjectPrimCount',
+            'llGetOmega',
+            'llGetOwner',
+            'llGetOwnerKey',
+            'llGetParcelDetails',
+            'llGetParcelFlags',
+            'llGetParcelMaxPrims',
+            'llGetParcelPrimCount',
+            'llGetParcelPrimOwners',
+            'llGetPermissions',
+            'llGetPermissionsKey',
+            'llGetPos',
+            'llGetPrimitiveParams',
+            'llGetRegionAgentCount',
+            'llGetRegionCorner',
+            'llGetRegionFlags',
+            'llGetRegionFPS',
+            'llGetRegionName',
+            'llGetRegionTimeDilation',
+            'llGetRootPosition',
+            'llGetRootRotation',
+            'llGetRot',
+            'llGetScale',
+            'llGetScriptName',
+            'llGetScriptState',
+            'llGetSimulatorHostname',
+            'llGetStartParameter',
+            'llGetStatus',
+            'llGetSubString',
+            'llGetSunDirection',
+            'llGetTexture',
+            'llGetTextureOffset',
+            'llGetTextureRot',
+            'llGetTextureScale',
+            'llGetTime',
+            'llGetTimeOfDay',
+            'llGetTimestamp',
+            'llGetTorque',
+            'llGetUnixTime',
+            'llGetVel',
+            'llGetWallclock',
+            'llGiveInventory',
+            'llGiveInventoryList',
+            'llGiveMoney',
+            'llGround',
+            'llGroundContour',
+            'llGroundNormal',
+            'llGroundRepel',
+            'llGroundSlope',
+            'llHTTPRequest',
+            'llInsertString',
+            'llInstantMessage',
+            'llIntegerToBase64',
+            'llKey2Name',
+            'llList2CSV',
+            'llList2Float',
+            'llList2Integer',
+            'llList2Key',
+            'llList2List',
+            'llList2ListStrided',
+            'llList2Rot',
+            'llList2String',
+            'llList2Vector',
+            'llListen',
+            'llListenControl',
+            'llListenRemove',
+            'llListFindList',
+            'llListInsertList',
+            'llListRandomize',
+            'llListReplaceList',
+            'llListSort',
+            'llListStatistics',
+            'llLoadURL',
+            'llLog',
+            'llLog10',
+            'llLookAt',
+            'llLoopSound',
+            'llLoopSoundMaster',
+            'llLoopSoundSlave',
+            'llMapDestination',
+            'llMD5String',
+            'llMessageLinked',
+            'llMinEventDelay',
+            'llModifyLand',
+            'llModPow',
+            'llMoveToTarget',
+            'llOffsetTexture',
+            'llOpenRemoteDataChannel',
+            'llOverMyLand',
+            'llOwnerSay',
+            'llParcelMediaCommandList',
+            'llParcelMediaQuery',
+            'llParseString2List',
+            'llParseStringKeepNulls',
+            'llParticleSystem',
+            'llPassCollisions',
+            'llPassTouches',
+            'llPlaySound',
+            'llPlaySoundSlave',
+            'llPow',
+            'llPreloadSound',
+            'llPushObject',
+            'llRegionSay',
+            'llReleaseControls',
+            'llRemoteDataReply',
+            'llRemoteDataSetRegion',
+            'llRemoteLoadScriptPin',
+            'llRemoveFromLandBanList',
+            'llRemoveFromLandPassList',
+            'llRemoveInventory',
+            'llRemoveVehicleFlags',
+            'llRequestAgentData',
+            'llRequestInventoryData',
+            'llRequestPermissions',
+            'llRequestSimulatorData',
+            'llResetLandBanList',
+            'llResetLandPassList',
+            'llResetOtherScript',
+            'llResetScript',
+            'llResetTime',
+            'llRezAtRoot',
+            'llRezObject',
+            'llRot2Angle',
+            'llRot2Axis',
+            'llRot2Euler',
+            'llRot2Fwd',
+            'llRot2Left',
+            'llRot2Up',
+            'llRotateTexture',
+            'llRotBetween',
+            'llRotLookAt',
+            'llRotTarget',
+            'llRotTargetRemove',
+            'llRound',
+            'llSameGroup',
+            'llSay',
+            'llScaleTexture',
+            'llScriptDanger',
+            'llSendRemoteData',
+            'llSensor',
+            'llSensorRemove',
+            'llSensorRepeat',
+            'llSetAlpha',
+            'llSetBuoyancy',
+            'llSetCameraAtOffset',
+            'llSetCameraEyeOffset',
+            'llSetCameraParams',
+            'llSetClickAction',
+            'llSetColor',
+            'llSetDamage',
+            'llSetForce',
+            'llSetForceAndTorque',
+            'llSetHoverHeight',
+            'llSetLinkAlpha',
+            'llSetLinkColor',
+            'llSetLinkPrimitiveParams',
+            'llSetLinkTexture',
+            'llSetLocalRot',
+            'llSetObjectDesc',
+            'llSetObjectName',
+            'llSetParcelMusicURL',
+            'llSetPayPrice',
+            'llSetPos',
+            'llSetPrimitiveParams',
+            'llSetRemoteScriptAccessPin',
+            'llSetRot',
+            'llSetScale',
+            'llSetScriptState',
+            'llSetSitText',
+            'llSetSoundQueueing',
+            'llSetSoundRadius',
+            'llSetStatus',
+            'llSetText',
+            'llSetTexture',
+            'llSetTextureAnim',
+            'llSetTimerEvent',
+            'llSetTorque',
+            'llSetTouchText',
+            'llSetVehicleFlags',
+            'llSetVehicleFloatParam',
+            'llSetVehicleRotationParam',
+            'llSetVehicleType',
+            'llSetVehicleVectorParam',
+            'llSHA1String',
+            'llShout',
+            'llSin',
+            'llSitTarget',
+            'llSleep',
+            'llSqrt',
+            'llStartAnimation',
+            'llStopAnimation',
+            'llStopHover',
+            'llStopLookAt',
+            'llStopMoveToTarget',
+            'llStopSound',
+            'llStringLength',
+            'llStringToBase64',
+            'llStringTrim',
+            'llSubStringIndex',
+            'llTakeControls',
+            'llTan',
+            'llTarget',
+            'llTargetOmega',
+            'llTargetRemove',
+            'llTeleportAgentHome',
+            'llToLower',
+            'llToUpper',
+            'llTriggerSound',
+            'llTriggerSoundLimited',
+            'llUnescapeURL',
+            'llUnSit',
+            'llVecDist',
+            'llVecMag',
+            'llVecNorm',
+            'llVolumeDetect',
+            'llWater',
+            'llWhisper',
+            'llWind',
+            'llXorBase64StringsCorrect',
+            ),
+        6 => array( // deprecated
+            'llMakeExplosion',
+            'llMakeFire',
+            'llMakeFountain',
+            'llMakeSmoke',
+            'llSound',
+            'llSoundPreload',
+            'llXorBase64Strings',
+            ),
+        7 => array( // unimplemented
+            'llPointAt',
+            'llRefreshPrimURL',
+            'llReleaseCamera',
+            'llRemoteLoadScript',
+            'llSetPrimURL',
+            'llStopPointAt',
+            'llTakeCamera',
+            'llTextBox',
+            ),
+        8 => array( // God mode
+            'llGodLikeRezObject',
+            'llSetInventoryPermMask',
+            'llSetObjectPermMask',
+            ),
+        ),
+    'SYMBOLS' => array(
+        '{', '}', '(', ')', '[', ']',
+        '=', '+', '-', '*', '/',
+        '+=', '-=', '*=', '/=', '++', '--',
+        '!', '%', '&amp;', '|', '&amp;&amp;', '||',
+        '==', '!=', '&lt;', '&gt;', '&lt;=', '&gt;=',
+        '~', '&lt;&lt;', '&gt;&gt;', '^', ':',
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => true,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true,
+        5 => true,
+        6 => true,
+        7 => true,
+        8 => true,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0000ff;',
+            2 => 'color: #000080;',
+            3 => 'color: #008080;',
+            4 => 'color: #228b22;',
+            5 => 'color: #b22222;',
+            6 => 'color: #8b0000; background-color: #ffff00;',
+            7 => 'color: #8b0000; background-color: #fa8072;',
+            8 => 'color: #000000; background-color: #ba55d3;',
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #ff7f50; font-style: italic;',
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000000;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #006400;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #000000;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000000;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => 'http://www.lslwiki.net/lslwiki/wakka.php?wakka={FNAME}', // http://wiki.secondlife.com/wiki/{FNAME}
+        4 => 'http://www.lslwiki.net/lslwiki/wakka.php?wakka={FNAME}', // http://wiki.secondlife.com/wiki/{FNAME}
+        5 => 'http://www.lslwiki.net/lslwiki/wakka.php?wakka={FNAME}', // http://wiki.secondlife.com/wiki/{FNAME}
+        6 => 'http://www.lslwiki.net/lslwiki/wakka.php?wakka={FNAME}', // http://wiki.secondlife.com/wiki/{FNAME}
+        7 => 'http://www.lslwiki.net/lslwiki/wakka.php?wakka={FNAME}', // http://wiki.secondlife.com/wiki/{FNAME}
+        8 => 'http://www.lslwiki.net/lslwiki/wakka.php?wakka={FNAME}', // http://wiki.secondlife.com/wiki/{FNAME}
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/lua.php b/examples/includes/geshi/geshi/lua.php
new file mode 100644 (file)
index 0000000..58ed30a
--- /dev/null
@@ -0,0 +1,137 @@
+<?php
+/*************************************************************************************
+ * lua.php
+ * -------
+ * Author: Roberto Rossi (rsoftware@altervista.org)
+ * Copyright: (c) 2004 Roberto Rossi (http://rsoftware.altervista.org), Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/07/10
+ *
+ * LUA language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2005/08/26 (1.0.2)
+ *  -  Added support for objects and methods
+ *  -  Removed unusable keywords
+ * 2004/11/27 (1.0.1)
+ *  -  Added support for multiple object splitters
+ * 2004/10/27 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Lua',
+    'COMMENT_SINGLE' => array(1 => "--"),
+    'COMMENT_MULTI' => array('--[[' => ']]'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'and','break','do','else','elseif','end','false','for','function','if',
+            'in','local','nil','not','or','repeat','return','then','true','until','while',
+            '_VERSION','assert','collectgarbage','dofile','error','gcinfo','loadfile','loadstring',
+            'print','tonumber','tostring','type','unpack',
+            '_ALERT','_ERRORMESSAGE','_INPUT','_PROMPT','_OUTPUT',
+            '_STDERR','_STDIN','_STDOUT','call','dostring','foreach','foreachi','getn','globals','newtype',
+            'rawget','rawset','require','sort','tinsert','tremove',
+            'abs','acos','asin','atan','atan2','ceil','cos','deg','exp',
+            'floor','format','frexp','gsub','ldexp','log','log10','max','min','mod','rad','random','randomseed',
+            'sin','sqrt','strbyte','strchar','strfind','strlen','strlower','strrep','strsub','strupper','tan',
+            'openfile','closefile','readfrom','writeto','appendto',
+            'remove','rename','flush','seek','tmpfile','tmpname','read','write',
+            'clock','date','difftime','execute','exit','getenv','setlocale','time',
+            '_G','getfenv','getmetatable','ipairs','loadlib','next','pairs','pcall',
+            'rawegal','setfenv','setmetatable','xpcall',
+            'string.byte','string.char','string.dump','string.find','string.len',
+            'string.lower','string.rep','string.sub','string.upper','string.format','string.gfind','string.gsub',
+            'table.concat','table.foreach','table.foreachi','table.getn','table.sort','table.insert','table.remove','table.setn',
+            'math.abs','math.acos','math.asin','math.atan','math.atan2','math.ceil','math.cos','math.deg','math.exp',
+            'math.floor','math.frexp','math.ldexp','math.log','math.log10','math.max','math.min','math.mod',
+            'math.pi','math.rad','math.random','math.randomseed','math.sin','math.sqrt','math.tan',
+            'coroutine.create','coroutine.resume','coroutine.status',
+            'coroutine.wrap','coroutine.yield',
+            'io.close','io.flush','io.input','io.lines','io.open','io.output','io.read','io.tmpfile','io.type','io.write',
+            'io.stdin','io.stdout','io.stderr',
+            'os.clock','os.date','os.difftime','os.execute','os.exit','os.getenv','os.remove','os.rename',
+            'os.setlocale','os.time','os.tmpname',
+            'string','table','math','coroutine','io','os','debug'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '{', '}', '!', '@', '%', '&', '*', '|', '/', '<', '>', '=', ';'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            0 => 'color: #b1b100;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/m68k.php b/examples/includes/geshi/geshi/m68k.php
new file mode 100644 (file)
index 0000000..9c16d7d
--- /dev/null
@@ -0,0 +1,143 @@
+<?php
+/*************************************************************************************
+ * m68k.php
+ * --------
+ * Author: Benny Baumann (BenBE@omorphia.de)
+ * Copyright: (c) 2007 Benny Baumann (http://www.omorphia.de/), Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2007/02/06
+ *
+ * Motorola 68000 Assembler language file for GeSHi.
+ *
+ * Syntax definition as commonly used by the motorola documentation for the
+ * MC68HC908GP32 Microcontroller (and maybe others).
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *   -  Added description of extra language features (SF#1970248)
+ * 2007/06/02 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2007/06/02)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Motorola 68000 Assembler',
+    'COMMENT_SINGLE' => array(1 => ';'),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        /*CPU*/
+        1 => array(
+            'adc','add','ais','aix','and','asl','asr','bcc','bclr','bcs','beq',
+            'bge','bgt','bhcc','bhcs','bhi','bhs','bih','bil','bit','ble','blo',
+            'bls','blt','bmc','bmi','bms','bne','bpl','bra','brclr','brn',
+            'brset','bset','bsr','cbeq','clc','cli','clr','cmp','com','cphx',
+            'cpx','daa','dbnz','dec','div','eor','inc','jmp','jsr','lda','ldhx',
+            'ldx','lsl','lsr','mov','mul','neg','nop','nsa','ora','psha','pshh',
+            'pshx','pula','pulh','pulx','rol','ror','rsp','rti','rts','sbc',
+            'sec','sei','sta','sthx','stop','stx','sub','swi','tap','tax','tpa',
+            'tst','tsx','txa','txs','wait'
+        ),
+        /*registers*/
+        2 => array(
+            'a','h','x',
+            'hx','sp'
+            ),
+        /*Directive*/
+        3 => array(
+            '#define','#endif','#else','#ifdef','#ifndef','#include','#undef',
+            '.db','.dd','.df','.dq','.dt','.dw','.end','.org','equ'
+            ),
+        ),
+    'SYMBOLS' => array(
+        ','
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0000ff; font-weight:bold;',
+            2 => 'color: #0000ff;',
+            3 => 'color: #46aa03; font-weight:bold;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #adadad; font-style: italic;',
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #0000ff;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #7f007f;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #dd22dd;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #008000;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #22bbff;',
+            1 => 'color: #22bbff;',
+            2 => 'color: #993333;'
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        //Hex numbers
+        0 => '#?0[0-9a-fA-F]{1,32}[hH]',
+        //Binary numbers
+        1 => '\%[01]{1,64}[bB]',
+        //Labels
+        2 => '^[_a-zA-Z][_a-zA-Z0-9]*?\:'
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 8
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/make.php b/examples/includes/geshi/geshi/make.php
new file mode 100644 (file)
index 0000000..b15f459
--- /dev/null
@@ -0,0 +1,151 @@
+<?php
+/*************************************************************************************
+ * make.php
+ * --------
+ * Author: Neil Bird <phoenix@fnxweb.com>
+ * Copyright: (c) 2008 Neil Bird
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/08/26
+ *
+ * make language file for GeSHi.
+ *
+ * (GNU make specific)
+ *
+ * CHANGES
+ * -------
+ * 2008/09/05 (1.0.0)
+ *  -  First Release
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'GNU make',
+    'COMMENT_SINGLE' => array(1 => '#'),
+    'COMMENT_REGEXP' => array(
+        //Escaped String Starters
+        2 => "/\\\\['\"]/siU"
+        ),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            // core
+            'ifeq', 'else', 'endif', 'ifneq', 'ifdef', 'ifndef',
+            'include', 'vpath', 'export', 'unexport', 'override',
+            'info', 'warning', 'error'
+            ),
+        2 => array(
+            // macros, literals
+            '.SUFFIXES', '.PHONY', '.DEFAULT', '.PRECIOUS', '.IGNORE', '.SILENT', '.EXPORT_ALL_VARIABLES', '.KEEP_STATE',
+            '.LIBPATTERNS', '.NOTPARALLEL', '.DELETE_ON_ERROR', '.INTERMEDIATE', '.POSIX', '.SECONDARY'
+            ),
+        /*
+        3 => array(
+            // funcs - see regex
+            //'subst', 'addprefix', 'addsuffix', 'basename', 'call', 'dir', 'error', 'eval', 'filter-out', 'filter',
+            //'findstring', 'firstword', 'foreach', 'if', 'join', 'notdir', 'origin', 'patsubst', 'shell', 'sort', 'strip',
+            //'suffix', 'warning', 'wildcard', 'word', 'wordlist', 'words'
+            )*/
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}',
+        '!', '@', '%', '&', '|', '/',
+        '<', '>',
+        '=', '-', '+', '*',
+        '.', ':', ',', ';',
+        '$'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        //3 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #666622; font-weight: bold;',
+            2 => 'color: #990000;',
+            //3 => 'color: #000000; font-weight: bold;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #339900; font-style: italic;',
+            2 => 'color: #000099; font-weight: bold;',
+            'MULTI' => ''
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(  # keep same as symbols so as to make ${} and $() equiv.
+            0 => 'color: #004400;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #CC2200;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #CC2200;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #004400;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #000088; font-weight: bold;',
+            1 => 'color: #0000CC; font-weight: bold;',
+            2 => 'color: #000088;'
+            ),
+        'SCRIPT' => array(),
+        'METHODS' => array()
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        //3 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(),
+    'REGEXPS' => array(
+        //Simple variables
+        0 => "\\$(?:[^{(&]|&(?:amp|lt|gt);)",
+        //Complex variables/functions [built-ins]
+        1 => array(
+            GESHI_SEARCH => '(\\$[({])(subst|addprefix|addsuffix|basename|call|dir|error|eval|filter-out|filter,|findstring|firstword|foreach|if|join|notdir|origin|patsubst|shell|sort|strip,|suffix|warning|wildcard|word|wordlist|words)([ })])',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => '\\3'
+            ),
+            //Complex variables/functions [others]
+        2 => array(
+            GESHI_SEARCH => '(\\$[({])([A-Za-z_][A-Za-z_0-9]*)([ })])',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => '\\3'
+            ),
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(),
+    'HIGHLIGHT_STRICT_BLOCK' => array(),
+    'TAB_WIDTH' => 8
+// vim: set sw=4 sts=4 :
+);
+?>
diff --git a/examples/includes/geshi/geshi/matlab.php b/examples/includes/geshi/geshi/matlab.php
new file mode 100644 (file)
index 0000000..d3963ef
--- /dev/null
@@ -0,0 +1,227 @@
+<?php
+/*************************************************************************************
+ * matlab.php
+ * -----------
+ * Author: Florian Knorn (floz@gmx.de)
+ * Copyright: (c) 2004 Florian Knorn (http://www.florian-knorn.com)
+ * Release Version: 1.0.8.3
+ * Date Started: 2005/02/09
+ *
+ * Matlab M-file language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2006-03-25 (1.0.7.22)
+ *   - support for the transpose operator
+ *   - many keywords added
+ *   - links to the matlab documentation at mathworks
+ *      by: Olivier Verdier (olivier.verdier@free.fr)
+ * 2005/05/07 (1.0.0)
+ *   -  First Release
+ *
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Matlab M',
+    'COMMENT_SINGLE' => array(1 => '%'),
+    'COMMENT_MULTI' => array(),
+    //Matlab Strings
+    'COMMENT_REGEXP' => array(
+        2 => "/(?<![\\w\\)\\]\\}\\.])('[^\\n']*?')/"
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array(),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            'break', 'case', 'catch', 'continue', 'elseif', 'else', 'end', 'for',
+            'function', 'global', 'if', 'otherwise', 'persistent', 'return',
+            'switch', 'try', 'while'
+            ),
+        2 => array(
+            'all','any','exist','is','logical','mislocked',
+
+            'abs','acos','acosh','acot','acoth','acsc','acsch','airy','angle',
+            'ans','area','asec','asech','asin','asinh','atan','atan2','atanh',
+            'auread','autumn','auwrite','axes','axis','balance','bar','bar3',
+            'bar3h','barh','besselh','besseli','besselj','besselk','Bessely',
+            'beta','betainc','betaln','bicg','bicgstab','bin2dec','bitand',
+            'bitcmp','bitget','bitmax','bitor','bitset','bitshift','bitxor',
+            'blkdiag','bone','box','brighten','builtin','bwcontr','calendar',
+            'camdolly','camlight','camlookat','camorbit','campan','campos',
+            'camproj','camroll','camtarget','camup','camva','camzoom','capture',
+            'cart2pol','cart2sph','cat','caxis','cdf2rdf','ceil','cell',
+            'cell2struct','celldisp','cellfun','cellplot','cellstr','cgs',
+            'char','chol','cholinc','cholupdate','cla','clabel','class','clc',
+            'clf','clg','clock','close','colmmd','colorbar','colorcube',
+            'colordef','colormap','colperm','comet','comet3','compan','compass',
+            'complex','computer','cond','condeig','condest','coneplot','conj',
+            'contour','contourc','contourf','contourslice','contrast','conv',
+            'conv2','convhull','cool','copper','copyobj','corrcoef','cos',
+            'cosh','cot','coth','cov','cplxpair','cputime','cross','csc','csch',
+            'cumprod','cumsum','cumtrapz','cylinder','daspect','date','datenum',
+            'datestr','datetick','datevec','dbclear','dbcont','dbdown',
+            'dblquad','dbmex','dbquit','dbstack','dbstatus','dbstep','dbstop',
+            'dbtype','dbup','deblank','dec2bin','dec2hex','deconv','del2',
+            'delaunay','det','diag','dialog','diff','diffuse','dlmread',
+            'dlmwrite','dmperm','double','dragrect','drawnow','dsearch','eig',
+            'eigs','ellipj','ellipke','eomday','eps','erf','erfc','erfcx',
+            'erfiny','error','errorbar','errordlg','etime','eval','evalc',
+            'evalin','exp','expint','expm','eye','ezcontour','ezcontourf',
+            'ezmesh','ezmeshc','ezplot','ezplot3','ezpolar','ezsurf','ezsurfc',
+            'factor','factorial','fclose','feather','feof','ferror','feval',
+            'fft','fft2','fftshift','fgetl','fgets','fieldnames','figure',
+            'fill','fill3','filter','filter2','find','findfigs','findobj',
+            'findstr','fix','flag','flipdim','fliplr','flipud','floor','flops',
+            'fmin','fmins','fopen','fplot','fprintf','fread','frewind','fscanf',
+            'fseek','ftell','full','funm','fwrite','fzero','gallery','gamma',
+            'gammainc','gammaln','gca','gcbo','gcd','gcf','gco','get',
+            'getfield','ginput','gmres','gradient','gray','graymon','grid',
+            'griddata','gsvd','gtext','hadamard','hankel','hdf','helpdlg',
+            'hess','hex2dec','hex2num','hidden','hilb','hist','hold','hot',
+            'hsv','hsv2rgb','i','ifft','ifft2','ifftn','ifftshift','imag',
+            'image','imfinfo','imread','imwrite','ind2sub','Inf','inferiorto',
+            'inline','inpolygon','input','inputdlg','inputname','int16',
+            'int2str','int32','int8','interp1','interp2','interp3','interpft',
+            'interpn','intersect','inv','invhilb','ipermute','isa','ishandle',
+            'ismember','isocaps','isonormals','isosurface','j','jet','keyboard',
+            'lcm','legend','legendre','light','lighting','lightingangle',
+            'lin2mu','line','lines','linspace','listdlg','loadobj','log',
+            'log10','log2','loglog','logm','logspace','lower','lscov','lu',
+            'luinc','magic','mat2str','material','max','mean','median','menu',
+            'menuedit','mesh','meshc','meshgrid','min','mod','msgbox','mu2lin',
+            'NaN','nargchk','nargin','nargout','nchoosek','ndgrid','ndims',
+            'newplot','nextpow2','nnls','nnz','nonzeros','norm','normest','now',
+            'null','num2cell','num2str','nzmax','ode113,','ode15s,','ode23s,',
+            'ode23t,','ode23tb','ode45,','odefile','odeget','odeset','ones',
+            'orient','orth','pagedlg','pareto','pascal','patch','pause',
+            'pbaspect','pcg','pcolor','peaks','perms','permute','pi','pie',
+            'pie3','pinv','plot','plot3','plotmatrix','plotyy','pol2cart',
+            'polar','poly','polyarea','polyder','polyeig','polyfit','polyval',
+            'polyvalm','pow2','primes','print','printdlg','printopt','prism',
+            'prod','propedit','qmr','qr','qrdelete','qrinsert','qrupdate',
+            'quad','questdlg','quiver','quiver3','qz','rand','randn','randperm',
+            'rank','rat','rats','rbbox','rcond','real','realmax','realmin',
+            'rectangle','reducepatch','reducevolume','refresh','rem','repmat',
+            'reset','reshape','residue','rgb2hsv','rgbplot','ribbon','rmfield',
+            'roots','rose','rot90','rotate','rotate3d','round','rref',
+            'rrefmovie','rsf2csf','saveobj','scatter','scatter3','schur',
+            'script','sec','sech','selectmoveresize','semilogx','semilogy',
+            'set','setdiff','setfield','setxor','shading','shg','shiftdim',
+            'shrinkfaces','sign','sin','single','sinh','slice','smooth3','sort',
+            'sortrows','sound','soundsc','spalloc','sparse','spconvert',
+            'spdiags','specular','speye','spfun','sph2cart','sphere','spinmap',
+            'spline','spones','spparms','sprand','sprandn','sprandsym','spring',
+            'sprintf','sqrt','sqrtm','squeeze','sscanf','stairs','std','stem',
+            'stem3','str2double','str2num','strcat','strcmp','strcmpi',
+            'stream2','stream3','streamline','strings','strjust','strmatch',
+            'strncmp','strrep','strtok','struct','struct2cell','strvcat',
+            'sub2ind','subplot','subspace','subvolume','sum','summer',
+            'superiorto','surf','surf2patch','surface','surfc','surfl',
+            'surfnorm','svd','svds','symmmd','symrcm','symvar','tan','tanh',
+            'texlabel','text Create','textread','textwrap','tic','title','toc',
+            'toeplitz','trace','trapz','tril','trimesh','trisurf','triu',
+            'tsearch','uicontext Create','uicontextmenu','uicontrol',
+            'uigetfile','uimenu','uint32','uint8','uiputfile','uiresume',
+            'uisetcolor','uisetfont','uiwait Used','union','unique','unwrap',
+            'upper','var','varargin','varargout','vectorize','view','viewmtx',
+            'voronoi','waitbar','waitforbuttonpress','warndlg','warning',
+            'waterfall','wavread','wavwrite','weekday','whitebg','wilkinson',
+            'winter','wk1read','wk1write','xlabel','xlim','ylabel','ylim',
+            'zeros','zlabel','zlim','zoom',
+            //'[Keywords 6]',
+            'addpath','cd','clear','copyfile','delete','diary','dir','disp',
+            'doc','docopt','echo','edit','fileparts','format','fullfile','help',
+            'helpdesk','helpwin','home','inmem','lasterr','lastwarn','length',
+            'load','lookfor','ls','matlabrc','matlabroot','mkdir','mlock',
+            'more','munlock','open','openvar','pack','partialpath','path',
+            'pathtool','profile','profreport','pwd','quit','rmpath','save',
+            'saveas','size','tempdir','tempname','type','ver','version','web',
+            'what','whatsnew','which','who','whos','workspace'
+            )
+        ),
+    'SYMBOLS' => array(
+        '...'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        //3 => false,
+        //4 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0000FF;',
+            2 => 'color: #0000FF;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #228B22;',
+            2 => 'color:#A020F0;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => ''
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #080;'
+            ),
+        'STRINGS' => array(
+            //0 => 'color: #A020F0;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #33f;'
+            ),
+        'METHODS' => array(
+            1 => '',
+            2 => ''
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #080;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #33f;'
+            ),
+        'SCRIPT' => array(
+            0 => ''
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => 'http://www.mathworks.com/access/helpdesk/help/techdoc/ref/{FNAMEL}.html'
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.',
+        2 => '::'
+        ),
+    'REGEXPS' => array(
+        //Complex numbers
+        0 => '(?<![\\w])[+-]?[\\d]*([\\d]\\.|\\.[\\d])?[\\d]*[ij](?![\\w])'
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/mirc.php b/examples/includes/geshi/geshi/mirc.php
new file mode 100644 (file)
index 0000000..1547ff4
--- /dev/null
@@ -0,0 +1,173 @@
+<?php
+/*************************************************************************************
+ * mirc.php
+ * -----
+ * Author: Alberto 'Birckin' de Areba (Birckin@hotmail.com)
+ * Copyright: (c) 2006 Alberto de Areba
+ * Release Version: 1.0.8.3
+ * Date Started: 2006/05/29
+ *
+ * mIRC Scripting language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *   -  Added description of extra language features (SF#1970248)
+ * 2006/05/29 (1.0.0)
+ *   -  First Release
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'mIRC Scripting',
+    'COMMENT_SINGLE' => array(1 => ';'),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array(),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            'alias', 'menu', 'dialog',
+            ),
+        2 => array(
+            'if', 'elseif', 'else', 'while', 'return', 'goto','var'
+            ),
+        3 => array(
+            'action','ajinvite','amsg','ame','anick','aop','auser',
+            'avoice','auto','autojoin','away','background','ban','beep',
+            'channel','clear','clearall','clipboard','close','closemsg','color',
+            'copy','creq','ctcp','ctcpreply','ctcps','dcc','dde','ddeserver',
+            'debug','describe','disable','disconnect','dlevel','dll','dns',
+            'dqwindow','ebeeps','echo','editbox','emailaddr','enable','events',
+            'exit','filter','findtext','finger','flash','flood','flush',
+            'flushini','font','fsend','fserve','fullname','ghide','gload',
+            'gmove','gopts','gplay','gpoint','gqreq','groups','gshow','gsize',
+            'gstop','gtalk','gunload','guser','help','hop','ignore','invite',
+            'join','kick','linesep','links','list','load','loadbuf','localinfo',
+            'log','me','mdi','mkdir','mnick','mode','msg','names','nick','noop',
+            'notice','notify','omsg','onotice','part','partall','pdcc',
+            'perform','ping','play','pop','protect','pvoice','qmsg','qme',
+            'query','queryrn','quit','raw','remini','remote','remove','rename',
+            'enwin','resetidle','rlevel','rmdir','run','ruser','save','savebuf',
+            'saveini','say','server','showmirc','sline','sound','speak','splay',
+            'sreq','strip','time',
+            //'timer[N/name]', //Handled as a regular expression below ...
+            'timers','timestamp','titlebar','tnick','tokenize','topic','ulist',
+            'unload','updatenl','url','uwho','window','winhelp','write',
+            'writeini','who','whois','whowas'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '{', '}', '[', ']'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #994444;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #990000; font-weight: bold;',
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            ),
+        'ESCAPE_CHAR' => array(
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #FF0000;',
+            ),
+        'STRINGS' => array(
+            ),
+        'NUMBERS' => array(
+            0 => '',
+            ),
+        'METHODS' => array(
+            0 => 'color: #008000;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #FF0000;',
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #000099;',
+            1 => 'color: #990000;',
+            2 => 'color: #000099;',
+            3 => 'color: #888800;',
+            4 => 'color: #888800;',
+            5 => 'color: #000099;',
+            6 => 'color: #990000; font-weight: bold;',
+            7 => 'color: #990000; font-weight: bold;'
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => 'http://www.mirc.com/{FNAMEL}'
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array('.'),
+    'REGEXPS' => array(
+        //Variable names
+        0 => '\$[a-zA-Z0-9]+',
+        //Variable names
+        1 => '(%|&amp;)[a-zA-Z0-9äöü]+',
+        //Client to Client Protocol handling
+        2 => '(on|ctcp) (!|@|&amp;)?(\d|\*):[a-zA-Z]+:',
+        /*4 => array(
+            GESHI_SEARCH => '((on|ctcp) (!|@|&)?(\d|\*):(Action|Active|Agent|AppActive|Ban|Chat|Close|Connect|Ctcp|CtcpReply|DccServer|DeHelp|DeOp|DeVoice|Dialog|Dns|Error|Exit|FileRcvd|FileSent|GetFail|Help|Hotlink|Input|Invite|Join|KeyDown|KeyUp|Kick|Load|Logon|MidiEnd|Mode|Mp3End|Nick|NoSound|Notice|Notify|Op|Open|Part|Ping|Pong|PlayEnd|Quit|Raw|RawMode|SendFail|Serv|ServerMode|ServerOp|Signal|Snotice|Start|Text|Topic|UnBan|Unload|Unotify|User|Mode|Voice|Wallops|WaveEnd):)',
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => 'i',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),*/
+        //Channel names
+        3 => '(#|@)[a-zA-Z0-9]+',
+        4 => '-[a-z\d]+',
+        //Raw protocol handling
+        5 => 'raw (\d|\*):',
+        //Timer handling
+        6 => '\/timer(?!s\b)[0-9a-zA-Z_]+',
+        // /...
+        7 => '\/[a-zA-Z0-9]+'
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'PARSER_CONTROL' => array(
+        'ENABLE_FLAGS' => array(
+            'NUMBERS' => GESHI_NEVER
+            ),
+        'KEYWORDS' => array(
+            2 => array(
+                'DISALLOWED_BEFORE' => '(?<![a-zA-Z0-9\$_\|\#;>^&\/])'
+            )
+        )
+    )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/modula3.php b/examples/includes/geshi/geshi/modula3.php
new file mode 100644 (file)
index 0000000..a136442
--- /dev/null
@@ -0,0 +1,135 @@
+<?php
+/*************************************************************************************
+ * modula3.php
+ * ----------
+ * Author: mbishop (mbishop@esoteriq.org)
+ * Copyright: (c) 2009 mbishop (mbishop@esoteriq.org)
+ * Release Version: 1.0.8.3
+ * Date Started: 2009/01/21
+ *
+ * Modula-3 language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ *
+ * TODO
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Modula-3',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array('(*' => '*)'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'HARDQUOTE' => array("'", "'"),
+    'HARDESCAPE' => array("''"),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'AND', 'ANY', 'ARRAY', 'AS', 'BEGIN', 'BITS', 'BRANDED', 'BY', 'CASE',
+            'CONST', 'DIV', 'DO', 'ELSE', 'ELSIF', 'END', 'EVAL', 'EXCEPT', 'EXCEPTION',
+            'EXIT', 'EXPORTS', 'FINALLY', 'FOR', 'FROM', 'GENERIC', 'IF', 'IMPORT', 'IN',
+            'INTERFACE', 'LOCK', 'LOOP', 'METHODS', 'MOD', 'MODULE', 'NOT', 'OBJECT', 'OF',
+            'OR', 'OVERRIDE', 'PROCEDURE', 'RAISE', 'RAISES', 'READONLY', 'RECORD', 'REF',
+            'REPEAT', 'RETURN', 'REVEAL', 'ROOT', 'SET', 'THEN', 'TO', 'TRY', 'TYPE', 'TYPECASE',
+            'UNSAFE', 'UNTIL', 'UNTRACED', 'VALUE', 'VAR', 'WHILE', 'WITH'
+            ),
+        2 => array(
+            'NIL', 'NULL', 'FALSE', 'TRUE',
+            ),
+        3 => array(
+            'ABS','ADR','ADRSIZE','BITSIZE','BYTESIZE','CEILING','DEC','DISPOSE',
+            'EXTENDED','FIRST','FLOAT','FLOOR','INC','ISTYPE','LAST','LOOPHOLE','MAX','MIN',
+            'NARROW','NEW','NUMBER','ORD','ROUND','SUBARRAY','TRUNC','TYPECODE', 'VAL'
+            ),
+        4 => array(
+            'ADDRESS', 'BOOLEAN', 'CARDINAL', 'CHAR', 'INTEGER',
+            'LONGREAL', 'MUTEX', 'REAL', 'REFANY', 'TEXT'
+            ),
+        ),
+    'SYMBOLS' => array(
+        ',', ':', '=', '+', '-', '*', '/', '#'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000000; font-weight: bold;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #000066;',
+            4 => 'color: #000066; font-weight: bold;'
+            ),
+        'COMMENTS' => array(
+            'MULTI' => 'color: #666666; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;',
+            'HARD' => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #009900;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;',
+            'HARD' => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #0066ee;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #339933;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/mpasm.php b/examples/includes/geshi/geshi/mpasm.php
new file mode 100644 (file)
index 0000000..30b192c
--- /dev/null
@@ -0,0 +1,164 @@
+<?php
+/*************************************************************************************
+ * mpasm.php
+ * ---------
+ * Author: Bakalex (bakalex@gmail.com)
+ * Copyright: (c) 2004 Bakalex, Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/12/6
+ *
+ * Microchip Assembler language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *  - Added description of extra language features (SF#1970248)
+ * 2005/01/29 (1.0.0)
+ *  - First Release
+ *
+ * TODO (updated 2005/12/6)
+ * -------------------------
+ *
+ * For the moment, i've only added PIC16C6X registers. We need more (PIC16F/C7x/8x,
+ * PIC10, PIC18 and dsPIC registers).
+ * Must take a look to dsPIC instructions.
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Microchip Assembler',
+    'COMMENT_SINGLE' => array(1 => ';'),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        /*Directive Language*/
+        4 => array(
+            'CONSTANT', '#DEFINE', 'END', 'EQU', 'ERROR', 'ERROR-LEVEL', '#INCLUDE', 'LIST',
+            'MESSG', 'NOLIST', 'ORG', 'PAGE', 'PROCESSOR', 'RADIX', 'SET', 'SPACE', 'SUBTITLE',
+            'TITLE', '#UNDEFINE', 'VARIABLE', 'ELSE', 'ENDIF', 'ENDW', 'IF', 'IFDEF', 'IFNDEF',
+            'WHILE', '__BADRAM', 'CBLOCK', '__CONFIG', 'DA', 'DATA', 'DB', 'DE', 'DT', 'DW',
+            'ENDC', 'FILL', '__IDLOCS', '__MAXRAM', 'RES', 'ENDM', 'EXITM', 'EXPAND', 'LOCAL',
+            'MACRO', 'NOEXPAND', 'BANKISEL', 'BANKSEL', 'CODE', 'EXTERN', 'GLOBAL', 'IDATA',
+            'PAGESEL', 'UDATA', 'UDATA_ACS', 'UDATA_OVR', 'UDATA_SHR'
+            ),
+        /* 12&14-bit Specific Instruction Set*/
+        1 => array(
+            'andlw', 'call', 'clrwdt', 'goto', 'iorlw', 'movlw', 'option', 'retlw', 'sleep',
+            'tris', 'xorlw', 'addwf', 'andwf', 'clrf', 'clrw', 'comf', 'decf', 'decfsz', 'incf',
+            'incfsz', 'iorwf', 'movf', 'nop', 'rlf', 'rrf', 'subwf', 'swapf', 'xorwf',
+            'bcf', 'bsf', 'btfsc', 'btfss',
+            'addlw', 'retfie', 'return', 'sublw', 'addcf', 'adddcf', 'b', 'bc', 'bdc',
+            'bnc', 'bndc', 'bnz', 'bz', 'clrc', 'clrdc', 'clrz', 'lcall', 'lgoto', 'movfw',
+            'negf', 'setc', 'setdc', 'setz', 'skpc', 'skpdc', 'skpnc', 'skpndc', 'skpnz', 'skpz',
+            'subcf', 'subdcf', 'tstf'
+            ),
+        /* 16-bit Specific Instructiob Set */
+        2 => array (
+            'movfp', 'movlb', 'movlp', 'movpf', 'movwf', 'tablrd', 'tablwt', 'tlrd', 'tlwt',
+            'addwfc', 'daw', 'mullw', 'negw', 'rlcf', 'rlncf', 'rrcf', 'rrncf', 'setf', 'subwfb',
+            'btg', 'cpfseq', 'cpfsgt', 'cpfslt', 'dcfsnz', 'infsnz', 'tstfsz', 'lfsr', 'bnn',
+            'bnov', 'bra', 'pop', 'push', 'rcall', 'reset'
+            ),
+        /* Registers */
+        3 => array(
+            'INDF', 'TMR0', 'PCL', 'STATUS', 'FSR', 'PORTA', 'PORTB', 'PORTC', 'PORTD', 'PORTE',
+            'PCLATH', 'INTCON', 'PIR1', 'PIR2', 'TMR1L', 'TMR1H', 'T1CON', 'TMR2', 'T2CON', 'TMR2L',
+            'TMR2H', 'TMR0H', 'TMR0L', 'SSPBUF', 'SSPCON', 'CCPR1L', 'CCPR1H', 'CCP1CON', 'RCSTA',
+            'TXREG', 'RCREG', 'CCPR2L', 'CCPR2H', 'CCP2CON', 'OPTION', 'TRISA', 'TRISB', 'TRISC',
+            'TRISD', 'TRISE', 'PIE2', 'PIE1', 'PR2', 'SSPADD', 'SSPSTAT', 'TXSTA', 'SPBRG'
+            ),
+        /*Operands*/
+        5 => array(
+            'high','low'
+            )
+        ),
+    'SYMBOLS' => array(
+        '[', ']', '(', ')'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        5 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #00007f;',
+            2 => 'color: #0000ff;',
+            3 => 'color: #007f00;',
+            4 => 'color: #46aa03; font-weight:bold;',
+            5 => 'color: #7f0000;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #adadad; font-style: italic;',
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #7f007f;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #ff0000;',
+            1 => 'color: #ff0000;'
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => '',
+        5 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        //Hex numbers
+        0 => '[0-9a-fA-F]{1,32}[hH]',
+        //Binary numbers
+        1 => '[01]{1,64}[bB]'
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/mxml.php b/examples/includes/geshi/geshi/mxml.php
new file mode 100644 (file)
index 0000000..939632b
--- /dev/null
@@ -0,0 +1,145 @@
+<?php
+/*************************************************************************************
+ * mxml.php
+ * -------
+ * Author: David Spurr
+ * Copyright: (c) 2007 David Spurr (http://www.defusion.org.uk/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2007/10/04
+ *
+ * MXML language file for GeSHi. Based on the XML file by Nigel McNie
+ *
+ * CHANGES
+ * -------
+ * 2007/10/04 (1.0.7.22)
+ *   -  First Release
+ *
+ * TODO
+ * ----
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'MXML',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array('<!--' => '-->'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        ),
+    'SYMBOLS' => array(
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            ),
+        'COMMENTS' => array(
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'SCRIPT' => array(
+            0 => 'color: #00bbdd;',
+            1 => 'color: #ddbb00;',
+            2 => 'color: #339933;',
+            3 => 'color: #000000;'
+            ),
+        'REGEXPS' => array(
+            0 => 'font-weight: bold; color: black;',
+            1 => 'color: #7400FF;',
+            2 => 'color: #7400FF;'
+            )
+        ),
+    'URLS' => array(
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        // xml declaration
+        0 => array(
+            GESHI_SEARCH => '(&lt;[\/?|(\?xml)]?[a-z0-9_\-:]*(\?&gt;))',
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => 'i',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        // opening tags
+        1 => array(
+            GESHI_SEARCH => '(&lt;\/?[a-z]+:[a-z]+)',
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => 'i',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        // closing tags
+        2 => array(
+            GESHI_SEARCH => '(\/?&gt;)',
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => 'i',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            )
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_ALWAYS,
+    'SCRIPT_DELIMITERS' => array(
+        0 => array(
+            '<!DOCTYPE' => '>'
+            ),
+        1 => array(
+            '&' => ';'
+            ),
+        2 => array(
+            //'<![CDATA[' => ']]>'
+            '<mx:Script>' => '</mx:Script>'
+            ),
+        3 => array(
+            '<' => '>'
+            )
+    ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        0 => false,
+        1 => false,
+        2 => false,
+        3 => true
+        ),
+    'TAB_WIDTH' => 4
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/mysql.php b/examples/includes/geshi/geshi/mysql.php
new file mode 100644 (file)
index 0000000..0017eef
--- /dev/null
@@ -0,0 +1,475 @@
+<?php
+/*************************************************************************************
+ * mysql.php
+ * ---------
+ * Author: Marjolein Katsma (marjolein.is.back@gmail.com)
+ * Copyright: (c) 2008 Marjolein Katsma (http://blog.marjoleinkatsma.com/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2008-12-12
+ *
+ * MySQL language file for GeSHi.
+ *
+ * Based on original MySQL language file by Carl Fürstenberg (2004); brought
+ * up-to-date for current MySQL versions, and with more classes for different
+ * types of keywords; several minor errors were corrected as well.
+ *
+ * Some "classes" have two groups here: this is to allow for the fact that some
+ * keywords in MySQL have a double function: many of those are either a function
+ * (must be immediately followed by an opening bracket) or some other keyword:
+ * so they can be distinguished by the presence (or not) of that opening bracket.
+ * (An immediately following opening bracket is a default rule for functions in
+ * MySQL, though this may be overridden; because it's only a default, we use a
+ * regex lookahead only where necessary to distinguish homonyms, not generally
+ * to match any function.)
+ * Other keywords with double usage cannot be distinguished and are classified
+ * in the "Mix" category.
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi 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.
+ *
+ * GeSHi 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 GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'MySQL',
+    //'COMMENT_SINGLE' => array(1 =>'--', 2 => '#'),    // '--' MUST be folowed by whitespace,not necessarily a space
+    'COMMENT_SINGLE' => array(
+        1 =>'-- ',
+        2 => '#'
+        ),
+    'COMMENT_REGEXP' => array(
+        1 => "/(?:--\s).*?$/",                          // double dash followed by any whitespace
+        ),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,            // @@@ would be nice if this could be defined per group!
+    'QUOTEMARKS' => array("'", '"', '`'),
+    'ESCAPE_CHAR' => '\\',                              // by default only, can be specified
+    'ESCAPE_REGEXP' => array(
+        1 => "/[_%]/",                                  // search wildcards
+        ),
+    'NUMBERS' =>
+        GESHI_NUMBER_INT_BASIC |
+        GESHI_NUMBER_OCT_PREFIX |
+        GESHI_NUMBER_HEX_PREFIX |
+        GESHI_NUMBER_FLT_NONSCI |
+        GESHI_NUMBER_FLT_SCI_SHORT |
+        GESHI_NUMBER_FLT_SCI_ZERO,
+    'KEYWORDS' => array(
+        1 => array(
+            // Mix: statement keywords and keywords that don't fit in any other
+            // category, or have multiple usage/meanings
+            'ACTION','ADD','AFTER','ALGORITHM','ALL','ALTER','ANALYZE','ANY',
+            'ASC','AS','BDB','BEGIN','BERKELEYDB','BINARY','BTREE','CALL',
+            'CASCADED','CASCADE','CHAIN','CHECK','COLUMNS','COLUMN','COMMENT',
+            'COMMIT','COMMITTED','CONSTRAINT','CONTAINS SQL','CONSISTENT',
+            'CONVERT','CREATE','CROSS','DATA','DATABASES',
+            'DECLARE','DEFINER','DELAYED','DELETE','DESCRIBE','DESC',
+            'DETERMINISTIC','DISABLE','DISCARD','DISTINCTROW','DISTINCT','DO',
+            'DROP','DUMPFILE','DUPLICATE KEY','ENABLE','ENCLOSED BY','ENGINE',
+            'ERRORS','ESCAPED BY','EXISTS','EXPLAIN','EXTENDED','FIELDS',
+            'FIRST','FOR EACH ROW','FORCE','FOREIGN KEY','FROM','FULL',
+            'FUNCTION','GLOBAL','GRANT','GROUP BY','HANDLER','HASH','HAVING',
+            'HELP','HIGH_PRIORITY','IF NOT EXISTS','IGNORE','IMPORT','INDEX',
+            'INFILE','INNER','INNODB','INOUT','INTO','INVOKER',
+            'ISOLATION LEVEL','JOIN','KEYS','KEY','KILL','LANGUAGE SQL','LAST',
+            'LIMIT','LINES','LOAD','LOCAL','LOCK','LOW_PRIORITY',
+            'MASTER_SERVER_ID','MATCH','MERGE','MIDDLEINT','MODIFIES SQL DATA',
+            'MODIFY','MRG_MYISAM','NATURAL','NEXT','NO SQL','NO','ON',
+            'OPTIMIZE','OPTIONALLY','OPTION','ORDER BY','OUTER','OUTFILE','OUT',
+            'PARTIAL','PREV','PRIMARY KEY','PRIVILEGES','PROCEDURE','PURGE',
+            'QUICK','READS SQL DATA','READ','REFERENCES','RELEASE','RENAME',
+            'REPEATABLE','REQUIRE','RESTRICT','RETURNS','REVOKE',
+            'ROLLBACK','ROUTINE','RTREE','SAVEPOINT','SELECT',
+            'SERIALIZABLE','SESSION','SET','SHARE MODE','SHOW','SIMPLE',
+            'SNAPSHOT','SOME','SONAME','SQL SECURITY','SQL_BIG_RESULT',
+            'SQL_BUFFER_RESULT','SQL_CACHE','SQL_CALC_FOUND_ROWS',
+            'SQL_NO_CACHE','SQL_SMALL_RESULT','SSL','START','STARTING BY',
+            'STATUS','STRAIGHT_JOIN','STRIPED','TABLESPACE','TABLES','TABLE',
+            'TEMPORARY','TEMPTABLE','TERMINATED BY','TO','TRANSACTIONS',
+            'TRANSACTION','TRIGGER','TYPES','TYPE','UNCOMMITTED','UNDEFINED',
+            'UNION','UNLOCK_TABLES','UPDATE','USAGE','USE','USER_RESOURCES',
+            'USING','VALUES','VALUE','VIEW','WARNINGS','WHERE','WITH ROLLUP',
+            'WITH','WORK','WRITE',
+            ),
+        2 => array(     //No ( must follow
+            // Mix: statement keywords distinguished from functions by the same name
+            "CURRENT_USER", "DATABASE", "IN", "INSERT", "DEFAULT", "REPLACE", "SCHEMA", "TRUNCATE"
+            ),
+        3 => array(
+            // Values (Constants)
+            'FALSE','NULL','TRUE',
+            ),
+        4 => array(
+            // Column Data Types
+            'BIGINT','BIT','BLOB','BOOLEAN','BOOL','CHARACTER VARYING',
+            'CHAR VARYING','DATETIME','DECIMAL','DEC','DOUBLE PRECISION',
+            'DOUBLE','ENUM','FIXED','FLOAT','GEOMETRYCOLLECTION','GEOMETRY',
+            'INTEGER','INT','LINESTRING','LONGBLOB','LONGTEXT','MEDIUMBLOB',
+            'MEDIUMINT','MEDIUMTEXT','MULTIPOINT','MULTILINESTRING',
+            'MULTIPOLYGON','NATIONAL CHARACTER','NATIONAL CHARACTER VARYING',
+            'NATIONAL CHAR VARYING','NATIONAL VARCHAR','NCHAR VARCHAR','NCHAR',
+            'NUMERIC','POINT','POLYGON','REAL','SERIAL',
+            'SMALLINT','TEXT','TIMESTAMP','TINYBLOB','TINYINT',
+            'TINYTEXT','VARBINARY','VARCHARACTER','VARCHAR',
+            ),
+        5 => array(     //No ( must follow
+            // Column data types distinguished from functions by the same name
+            "CHAR", "DATE", "TIME"
+            ),
+        6 => array(
+            // Table, Column & Index Attributes
+            'AUTO_INCREMENT','AVG_ROW_LENGTH','BOTH','CHECKSUM','CONNECTION',
+            'DATA DIRECTORY','DEFAULT NULL','DELAY_KEY_WRITE','FULLTEXT',
+            'INDEX DIRECTORY','INSERT_METHOD','LEADING','MAX_ROWS','MIN_ROWS',
+            'NOT NULL','PACK_KEYS','ROW_FORMAT','SERIAL DEFAULT VALUE','SIGNED',
+            'SPATIAL','TRAILING','UNIQUE','UNSIGNED','ZEROFILL'
+            ),
+        7 => array(     //No ( must follow
+            // Column attribute distinguished from function by the same name
+            "CHARSET"
+            ),
+        8 => array(
+            // Date and Time Unit Specifiers
+            'DAY_HOUR','DAY_MICROSECOND','DAY_MINUTE','DAY_SECOND',
+            'HOUR_MICROSECOND','HOUR_MINUTE','HOUR_SECOND',
+            'MINUTE_MICROSECOND','MINUTE_SECOND',
+            'SECOND_MICROSECOND','YEAR_MONTH'
+            ),
+        9 => array(     //No ( must follow
+            // Date-time unit specifiers distinguished from functions by the same name
+            "DAY", "HOUR", "MICROSECOND", "MINUTE", "MONTH", "QUARTER", "SECOND", "WEEK", "YEAR"
+            ),
+        10 => array(
+            // Operators (see also Symbols)
+            'AND','BETWEEN','CHARACTER SET','COLLATE','DIV','IS NOT NULL',
+            'IS NOT','IS NULL','IS','LIKE','NOT','OFFSET','OR','REGEXP','RLIKE',
+            'SOUNDS LIKE','XOR'
+            ),
+        11 => array(     //No ( must follow
+            // Operator distinghuished from function by the same name
+            "INTERVAL"
+            ),
+        12 => array(
+            // Control Flow (functions)
+            'CASE','ELSE','END','IFNULL','IF','NULLIF','THEN','WHEN',
+            ),
+        13 => array(
+            // String Functions
+            'ASCII','BIN','BIT_LENGTH','CHAR_LENGTH','CHARACTER_LENGTH',
+            'CONCAT_WS','CONCAT','ELT','EXPORT_SET','FIELD',
+            'FIND_IN_SET','FORMAT','HEX','INSTR','LCASE','LEFT','LENGTH',
+            'LOAD_FILE','LOCATE','LOWER','LPAD','LTRIM','MAKE_SET','MID',
+            'OCTET_LENGTH','ORD','POSITION','QUOTE','REPEAT','REVERSE',
+            'RIGHT','RPAD','RTRIM','SOUNDEX','SPACE','STRCMP','SUBSTRING_INDEX',
+            'SUBSTRING','TRIM','UCASE','UNHEX','UPPER',
+            ),
+        14 => array(     //A ( must follow
+            // String functions distinguished from other keywords by the same name
+            "INSERT", "REPLACE", "CHAR"
+            ),
+        15 => array(
+            // Numeric Functions
+            'ABS','ACOS','ASIN','ATAN2','ATAN','CEILING','CEIL',
+            'CONV','COS','COT','CRC32','DEGREES','EXP','FLOOR','LN','LOG10',
+            'LOG2','LOG','MOD','OCT','PI','POWER','POW','RADIANS','RAND',
+            'ROUND','SIGN','SIN','SQRT','TAN',
+            ),
+        16 => array(     //A ( must follow
+            // Numeric function distinguished from other keyword by the same name
+            "TRUNCATE"
+            ),
+        17 => array(
+            // Date and Time Functions
+            'ADDDATE','ADDTIME','CONVERT_TZ','CURDATE','CURRENT_DATE',
+            'CURRENT_TIME','CURRENT_TIMESTAMP','CURTIME','DATE_ADD',
+            'DATE_FORMAT','DATE_SUB','DATEDIFF','DAYNAME','DAYOFMONTH',
+            'DAYOFWEEK','DAYOFYEAR','EXTRACT','FROM_DAYS','FROM_UNIXTIME',
+            'GET_FORMAT','LAST_DAY','LOCALTIME','LOCALTIMESTAMP','MAKEDATE',
+            'MAKETIME','MONTHNAME','NOW','PERIOD_ADD',
+            'PERIOD_DIFF','SEC_TO_TIME','STR_TO_DATE','SUBDATE','SUBTIME',
+            'SYSDATE','TIME_FORMAT','TIME_TO_SEC',
+            'TIMESTAMPADD','TIMESTAMPDIFF','TO_DAYS',
+            'UNIX_TIMESTAMP','UTC_DATE','UTC_TIME','UTC_TIMESTAMP','WEEKDAY',
+            'WEEKOFYEAR','YEARWEEK',
+            ),
+        18 => array(     //A ( must follow
+            // Date-time functions distinguished from other keywords by the same name
+            "DATE", "DAY", "HOUR", "MICROSECOND", "MINUTE", "MONTH", "QUARTER",
+            "SECOND", "TIME", "WEEK", "YEAR"
+            ),
+        19 => array(
+            // Comparison Functions
+            'COALESCE','GREATEST','ISNULL','LEAST',
+            ),
+        20 => array(     //A ( must follow
+            // Comparison functions distinguished from other keywords by the same name
+            "IN", "INTERVAL"
+            ),
+        21 => array(
+            // Encryption and Compression Functions
+            'AES_DECRYPT','AES_ENCRYPT','COMPRESS','DECODE','DES_DECRYPT',
+            'DES_ENCRYPT','ENCODE','ENCRYPT','MD5','OLD_PASSWORD','PASSWORD',
+            'SHA1','SHA','UNCOMPRESS','UNCOMPRESSED_LENGTH',
+            ),
+        22 => array(
+            // GROUP BY (aggregate) Functions
+            'AVG','BIT_AND','BIT_OR','BIT_XOR','COUNT','GROUP_CONCAT',
+            'MAX','MIN','STDDEV_POP','STDDEV_SAMP','STDDEV','STD','SUM',
+            'VAR_POP','VAR_SAMP','VARIANCE',
+            ),
+        23 => array(
+            // Information Functions
+            'BENCHMARK','COERCIBILITY','COLLATION','CONNECTION_ID',
+            'FOUND_ROWS','LAST_INSERT_ID','ROW_COUNT',
+            'SESSION_USER','SYSTEM_USER','USER','VERSION',
+            ),
+        24 => array(     //A ( must follow
+            // Information functions distinguished from other keywords by the same name
+            "CURRENT_USER", "DATABASE", "SCHEMA", "CHARSET"
+            ),
+        25 => array(
+            // Miscellaneous Functions
+            'ExtractValue','BIT_COUNT','GET_LOCK','INET_ATON','INET_NTOA',
+            'IS_FREE_LOCK','IS_USED_LOCK','MASTER_POS_WAIT','NAME_CONST',
+            'RELEASE_LOCK','SLEEP','UpdateXML','UUID',
+            ),
+        26 => array(     //A ( must follow
+            // Miscellaneous function distinguished from other keyword by the same name
+            "DEFAULT"
+            ),
+        27 => array(
+            // Geometry Functions
+            'Area','AsBinary','AsText','AsWKB','AsWKT','Boundary','Buffer',
+            'Centroid','Contains','ConvexHull','Crosses',
+            'Difference','Dimension','Disjoint','Distance',
+            'EndPoint','Envelope','Equals','ExteriorRing',
+            'GLength','GeomCollFromText','GeomCollFromWKB','GeomFromText',
+            'GeomFromWKB','GeometryCollectionFromText',
+            'GeometryCollectionFromWKB','GeometryFromText','GeometryFromWKB',
+            'GeometryN','GeometryType',
+            'InteriorRingN','Intersection','Intersects','IsClosed','IsEmpty',
+            'IsRing','IsSimple',
+            'LineFromText','LineFromWKB','LineStringFromText',
+            'LineStringFromWKB',
+            'MBRContains','MBRDisjoint','MBREqual','MBRIntersects',
+            'MBROverlaps','MBRTouches','MBRWithin','MLineFromText',
+            'MLineFromWKB','MPointFromText','MPointFromWKB','MPolyFromText',
+            'MPolyFromWKB','MultiLineStringFromText','MultiLineStringFromWKB',
+            'MultiPointFromText','MultiPointFromWKB','MultiPolygonFromText',
+            'MultiPolygonFromWKB',
+            'NumGeometries','NumInteriorRings','NumPoints',
+            'Overlaps',
+            'PointFromText','PointFromWKB','PointN','PointOnSurface',
+            'PolyFromText','PolyFromWKB','PolygonFromText','PolygonFromWKB',
+            'Related','SRID','StartPoint','SymDifference',
+            'Touches',
+            'Union',
+            'Within',
+            'X',
+            'Y',
+            ),
+        ),
+    'SYMBOLS' => array(
+        1 => array(
+            /* Operators */
+            '=', ':=',                                      // assignment operators
+            '||', '&&', '!',                                // locical operators
+            '=', '<=>', '>=', '>', '<=', '<', '<>', '!=',   // comparison operators
+            '|', '&', '^', '~', '<<', '>>',                 // bitwise operators
+            '-', '+', '*', '/', '%',                        // numerical operators
+            ),
+        2 => array(
+            /* Other syntactical symbols */
+            '(', ')',
+            ',', ';',
+            ),
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        5 => false,
+        6 => false,
+        7 => false,
+        8 => false,
+        9 => false,
+        10 => false,
+        11 => false,
+        12 => false,
+        13 => false,
+        13 => false,
+        14 => false,
+        15 => false,
+        16 => false,
+        17 => false,
+        18 => false,
+        19 => false,
+        20 => false,
+        21 => false,
+        22 => false,
+        23 => false,
+        24 => false,
+        25 => false,
+        26 => false,
+        27 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #990099; font-weight: bold;',      // mix
+            2 => 'color: #990099; font-weight: bold;',      // mix
+            3 => 'color: #9900FF; font-weight: bold;',      // constants
+            4 => 'color: #999900; font-weight: bold;',      // column data types
+            5 => 'color: #999900; font-weight: bold;',      // column data types
+            6 => 'color: #FF9900; font-weight: bold;',      // attributes
+            7 => 'color: #FF9900; font-weight: bold;',      // attributes
+            8 => 'color: #9900FF; font-weight: bold;',      // date-time units
+            9 => 'color: #9900FF; font-weight: bold;',      // date-time units
+
+            10 => 'color: #CC0099; font-weight: bold;',      // operators
+            11 => 'color: #CC0099; font-weight: bold;',      // operators
+
+            12 => 'color: #009900;',     // control flow (functions)
+            13 => 'color: #000099;',     // string functions
+            14 => 'color: #000099;',     // string functions
+            15 => 'color: #000099;',     // numeric functions
+            16 => 'color: #000099;',     // numeric functions
+            17 => 'color: #000099;',     // date-time functions
+            18 => 'color: #000099;',     // date-time functions
+            19 => 'color: #000099;',     // comparison functions
+            20 => 'color: #000099;',     // comparison functions
+            21 => 'color: #000099;',     // encryption functions
+            22 => 'color: #000099;',     // aggregate functions
+            23 => 'color: #000099;',     // information functions
+            24 => 'color: #000099;',     // information functions
+            25 => 'color: #000099;',     // miscellaneous functions
+            26 => 'color: #000099;',     // miscellaneous functions
+            27 => 'color: #00CC00;',     // geometry functions
+            ),
+        'COMMENTS' => array(
+            'MULTI' => 'color: #808000; font-style: italic;',
+            1 => 'color: #808080; font-style: italic;',
+            2 => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #004000; font-weight: bold;',
+            1 => 'color: #008080; font-weight: bold;'       // search wildcards
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #FF00FF;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #008000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #008080;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            1 => 'color: #CC0099;',         // operators
+            2 => 'color: #000033;',         // syntax
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => 'http://search.mysql.com/search?site=refman-51&amp;q={FNAME}&amp;lr=lang_en',
+        2 => 'http://search.mysql.com/search?site=refman-51&amp;q={FNAME}&amp;lr=lang_en',
+        3 => 'http://search.mysql.com/search?site=refman-51&amp;q={FNAME}&amp;lr=lang_en',
+        4 => 'http://search.mysql.com/search?site=refman-51&amp;q={FNAME}&amp;lr=lang_en',
+        5 => 'http://search.mysql.com/search?site=refman-51&amp;q={FNAME}&amp;lr=lang_en',
+        6 => 'http://search.mysql.com/search?site=refman-51&amp;q={FNAME}&amp;lr=lang_en',
+        7 => 'http://search.mysql.com/search?site=refman-51&amp;q={FNAME}&amp;lr=lang_en',
+        8 => 'http://search.mysql.com/search?site=refman-51&amp;q={FNAME}&amp;lr=lang_en',
+        9 => 'http://search.mysql.com/search?site=refman-51&amp;q={FNAME}&amp;lr=lang_en',
+
+        10 => 'http://dev.mysql.com/doc/refman/5.1/en/non-typed-operators.html',
+        11 => 'http://dev.mysql.com/doc/refman/5.1/en/non-typed-operators.html',
+
+        12 => 'http://dev.mysql.com/doc/refman/5.1/en/control-flow-functions.html',
+        13 => 'http://dev.mysql.com/doc/refman/5.1/en/string-functions.html',
+        14 => 'http://dev.mysql.com/doc/refman/5.1/en/string-functions.html',
+        15 => 'http://dev.mysql.com/doc/refman/5.1/en/numeric-functions.html',
+        16 => 'http://dev.mysql.com/doc/refman/5.1/en/numeric-functions.html',
+        17 => 'http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html',
+        18 => 'http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html',
+        19 => 'http://dev.mysql.com/doc/refman/5.1/en/comparison-operators.html',
+        20 => 'http://dev.mysql.com/doc/refman/5.1/en/comparison-operators.html',
+        21 => 'http://dev.mysql.com/doc/refman/5.1/en/encryption-functions.html',
+        22 => 'http://dev.mysql.com/doc/refman/5.1/en/group-by-functions-and-modifiers.html',
+        23 => 'http://dev.mysql.com/doc/refman/5.1/en/information-functions.html',
+        24 => 'http://dev.mysql.com/doc/refman/5.1/en/information-functions.html',
+        25 => 'http://dev.mysql.com/doc/refman/5.1/en/func-op-summary-ref.html',
+        26 => 'http://dev.mysql.com/doc/refman/5.1/en/func-op-summary-ref.html',
+        27 => 'http://dev.mysql.com/doc/refman/5.1/en/analysing-spatial-information.html',
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4,
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            2 => array(
+                'DISALLOWED_AFTER' => '(?![\(\w])'
+                ),
+            5 => array(
+                'DISALLOWED_AFTER' => '(?![\(\w])'
+                ),
+            7 => array(
+                'DISALLOWED_AFTER' => '(?![\(\w])'
+                ),
+            9 => array(
+                'DISALLOWED_AFTER' => '(?![\(\w])'
+                ),
+            11 => array(
+                'DISALLOWED_AFTER' => '(?![\(\w])'
+                ),
+
+            14 => array(
+                'DISALLOWED_AFTER' => '(?=\()'
+                ),
+            16 => array(
+                'DISALLOWED_AFTER' => '(?=\()'
+                ),
+            18 => array(
+                'DISALLOWED_AFTER' => '(?=\()'
+                ),
+            20 => array(
+                'DISALLOWED_AFTER' => '(?=\()'
+                ),
+            24 => array(
+                'DISALLOWED_AFTER' => '(?=\()'
+                ),
+            26 => array(
+                'DISALLOWED_AFTER' => '(?=\()'
+                )
+            )
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/nsis.php b/examples/includes/geshi/geshi/nsis.php
new file mode 100644 (file)
index 0000000..9f3e1cc
--- /dev/null
@@ -0,0 +1,351 @@
+<?php
+/*************************************************************************************
+ * nsis.php
+ * --------
+ * Author: deguix (cevo_deguix@yahoo.com.br), Tux (http://tux.a4.cz/)
+ * Copyright: (c) 2005 deguix, 2004 Tux (http://tux.a4.cz/), Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2005/12/03
+ *
+ * Nullsoft Scriptable Install System language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2005/12/03 (2.0.2)
+ *   - Updated to NSIS 2.11.
+ * 2005/06/17 (2.0.1)
+ *   - Updated to NSIS 2.07b0.
+ * 2005/04/05 (2.0.0)
+ *   - Updated to NSIS 2.06.
+ * 2004/11/27 (1.0.2)
+ *   - Added support for multiple object splitters
+ * 2004/10/27 (1.0.1)
+ *   - Added support for URLs
+ * 2004/08/05 (1.0.0)
+ *   - First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'NSIS',
+    'COMMENT_SINGLE' => array(1 => ';', 2 => '#'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'",'"','`'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            '!appendfile', '!addIncludeDir', '!addplugindir', '!cd', '!define', '!delfile', '!echo', '!else',
+            '!endif', '!error', '!execute', '!ifdef', '!ifmacrodef', '!ifmacrondef', '!ifndef', '!include',
+            '!insertmacro', '!macro', '!macroend', '!packhdr', '!tempfile', '!system', '!undef', '!verbose',
+            '!warning'
+            ),
+        2 => array(
+            'AddBrandingImage', 'AllowRootDirInstall', 'AutoCloseWindow', 'BGFont',
+            'BGGradient', 'BrandingText', 'Caption', 'ChangeUI', 'CheckBitmap', 'CompletedText', 'ComponentText',
+            'CRCCheck', 'DetailsButtonText', 'DirShow', 'DirText', 'DirVar', 'DirVerify', 'FileErrorText',
+            'Function', 'FunctionEnd', 'Icon', 'InstallButtonText', 'InstallColors', 'InstallDir',
+            'InstallDirRegKey', 'InstProgressFlags', 'InstType', 'LangString', 'LangStringUP', 'LicenseBkColor',
+            'LicenseData', 'LicenseForceSelection', 'LicenseLangString', 'LicenseText', 'LoadLanguageFile',
+            'MiscButtonText', 'Name', 'OutFile', 'Page', 'PageEx', 'PageExEnd', 'Section',
+            'SectionEnd', 'SectionGroup', 'SectionGroupEnd', 'SetCompressor', 'SetFont', 'ShowInstDetails',
+            'ShowUninstDetails', 'SilentInstall', 'SilentUnInstall', 'SpaceTexts', 'SubCaption', 'SubSection',
+            'SubSectionEnd', 'UninstallButtonText', 'UninstallCaption', 'UninstallIcon', 'UninstallSubCaption',
+            'UninstallText', 'UninstPage', 'Var', 'VIAddVersionKey', 'VIProductVersion', 'WindowIcon', 'XPStyle'
+            ),
+        3 => array(
+            'AddSize', 'AllowSkipFiles', 'FileBufSize', 'GetInstDirError', 'PageCallbacks',
+            'SectionIn', 'SetCompress', 'SetCompressionLevel', 'SetCompressorDictSize',
+            'SetDatablockOptimize', 'SetDateSave', 'SetOverwrite', 'SetPluginUnload'
+            ),
+        4 => array(
+            'Abort', 'BringToFront', 'Call', 'CallInstDLL', 'ClearErrors', 'CopyFiles','CreateDirectory',
+            'CreateFont', 'CreateShortCut', 'Delete', 'DeleteINISec', 'DeleteINIStr', 'DeleteRegKey',
+            'DeleteRegValue', 'DetailPrint', 'EnableWindow', 'EnumRegKey', 'EnumRegValue', 'Exch', 'Exec',
+            'ExecShell', 'ExecWait', 'ExpandEnvStrings', 'File', 'FileClose', 'FileOpen', 'FileRead',
+            'FileReadByte', 'FileSeek', 'FileWrite', 'FileWriteByte', 'FindClose', 'FindFirst', 'FindNext',
+            'FindWindow', 'FlushINI', 'GetCurInstType', 'GetCurrentAddress', 'GetDlgItem', 'GetDLLVersion',
+            'GetDLLVersionLocal', 'GetErrorLevel', 'GetFileTime', 'GetFileTimeLocal', 'GetFullPathName',
+            'GetFunctionAddress', 'GetLabelAddress', 'GetTempFileName', 'GetWindowText', 'Goto', 'HideWindow',
+            'IfAbort', 'IfErrors', 'IfFileExists', 'IfRebootFlag', 'IfSilent', 'InitPluginsDir', 'InstTypeGetText',
+            'InstTypeSetText', 'IntCmp', 'IntCmpU', 'IntFmt', 'IntOp', 'IsWindow', 'LockWindow', 'LogSet', 'LogText',
+            'MessageBox', 'Nop', 'Pop', 'Push', 'Quit', 'ReadEnvStr', 'ReadIniStr', 'ReadRegDWORD', 'ReadRegStr',
+            'Reboot', 'RegDLL', 'Rename', 'ReserveFile', 'Return', 'RMDir', 'SearchPath', 'SectionGetFlags',
+            'SectionGetInstTypes', 'SectionGetSize', 'SectionGetText', 'SectionSetFlags', 'SectionSetInstTypes',
+            'SectionSetSize', 'SectionSetText', 'SendMessage', 'SetAutoClose', 'SetBrandingImage', 'SetCtlColors',
+            'SetCurInstType', 'SetDetailsPrint', 'SetDetailsView', 'SetErrorLevel', 'SetErrors', 'SetFileAttributes',
+            'SetOutPath', 'SetRebootFlag', 'SetShellVarContext', 'SetSilent', 'ShowWindow', 'Sleep', 'StrCmp',
+            'StrCpy', 'StrLen', 'UnRegDLL', 'WriteINIStr', 'WriteRegBin', 'WriteRegDWORD', 'WriteRegExpandStr',
+            'WriteRegStr', 'WriteUninstaller'
+            ),
+        5 => array(
+            'all', 'alwaysoff', 'ARCHIVE', 'auto', 'both', 'bzip2', 'checkbox', 'components', 'current',
+            'custom', 'directory', 'false', 'FILE_ATTRIBUTE_ARCHIVE', 'FILE_ATTRIBUTE_HIDDEN', 'FILE_ATTRIBUTE_NORMAL',
+            'FILE_ATTRIBUTE_OFFLINE', 'FILE_ATTRIBUTE_READONLY', 'FILE_ATTRIBUTE_SYSTEM,TEMPORARY',
+            'FILE_ATTRIBUTE_TEMPORARY', 'force', 'HIDDEN', 'hide', 'HKCC', 'HKCR', 'HKCU', 'HKDD', 'HKEY_CLASSES_ROOT',
+            'HKEY_CURRENT_CONFIG', 'HKEY_CURRENT_USER', 'HKEY_DYN_DATA', 'HKEY_LOCAL_MACHINE', 'HKEY_PERFORMANCE_DATA',
+            'HKEY_USERS', 'HKLM', 'HKPD', 'HKU', 'IDABORT', 'IDCANCEL', 'IDIGNORE', 'IDNO', 'IDOK', 'IDRETRY', 'IDYES',
+            'ifdiff', 'ifnewer', 'instfiles', 'lastused', 'leave', 'license', 'listonly', 'lzma', 'manual',
+            'MB_ABORTRETRYIGNORE', 'MB_DEFBUTTON1', 'MB_DEFBUTTON2', 'MB_DEFBUTTON3', 'MB_DEFBUTTON4',
+            'MB_ICONEXCLAMATION', 'MB_ICONINFORMATION', 'MB_ICONQUESTION', 'MB_ICONSTOP', 'MB_OK', 'MB_OKCANCEL',
+            'MB_RETRYCANCEL', 'MB_RIGHT', 'MB_SETFOREGROUND', 'MB_TOPMOST', 'MB_YESNO', 'MB_YESNOCANCEL', 'nevershow',
+            'none', 'normal', 'off', 'OFFLINE', 'on', 'radiobuttons', 'READONLY', 'RO', 'SHCTX', 'SHELL_CONTEXT', 'show',
+            'silent', 'silentlog', 'SW_HIDE', 'SW_SHOWMAXIMIZED', 'SW_SHOWMINIMIZED', 'SW_SHOWNORMAL', 'SYSTEM',
+            'textonly', 'true', 'try', 'uninstConfirm', 'zlib'
+            ),
+        6 => array(
+            '/a', '/components', '/COMPONENTSONLYONCUSTOM', '/CUSTOMSTRING', '/e', '/FILESONLY', '/FINAL', '/gray', '/GLOBAL',
+            '/ifempty', '/IMGID', '/ITALIC', '/lang', '/NOCUSTOM', '/nonfatal', '/NOUNLOAD', '/oname', '/r', '/REBOOTOK',
+            '/RESIZETOFIT', '/SOLID', '/SD', '/SHORT', '/silent', '/STRIKE', '/TIMEOUT', '/TRIMCENTER', '/TRIMLEFT',
+            '/TRIMRIGHT', '/UNDERLINE', '/windows', '/x'
+            ),
+        7 => array(
+            '.onGUIEnd', '.onGUIInit', '.onInit', '.onInstFailed', '.onInstSuccess', '.onMouseOverSection',
+            '.onRebootFailed', '.onSelChange', '.onUserAbort', '.onVerifyInstDir', 'un.onGUIEnd', 'un.onGUIInit',
+            'un.onInit', 'un.onRebootFailed', 'un.onUninstFailed', 'un.onUninstSuccess', 'un.onUserAbort'
+            ),
+        8 => array(
+            'MUI.nsh', '"${NSISDIR}\Contrib\Modern UI\System.nsh"', 'MUI_SYSVERSION', 'MUI_ICON', 'MUI_UNICON',
+            'MUI_HEADERIMAGE', 'MUI_HEADERIMAGE_BITMAP', 'MUI_HEADERIMAGE_BITMAP_NOSTRETCH', 'MUI_HEADERIMAGE_BITMAP_RTL',
+            'MUI_HEADERIMAGE_BITMAP_RTL_NOSTRETCH', 'MUI_HEADERIMAGE_UNBITMAP', 'MUI_HEADERIMAGE_UNBITMAP_NOSTRETCH',
+            'MUI_HEADERIMAGE_UNBITMAP_RTL', 'MUI_HEADERIMAGE_UNBITMAP_RTL_NOSTRETCH', 'MUI_HEADERIMAGE_RIGHT', 'MUI_BGCOLOR',
+            'MUI_UI', 'MUI_UI_HEADERIMAGE', 'MUI_UI_HEADERIMAGE_RIGHT', 'MUI_UI_COMPONENTSPAGE_SMALLDESC',
+            'MUI_UI_COMPONENTSPAGE_NODESC', 'MUI_WELCOMEFINISHPAGE_BITMAP', 'MUI_WELCOMEFINISHPAGE_BITMAP_NOSTRETCH',
+            'MUI_WELCOMEFINISHPAGE_INI', 'MUI_UNWELCOMEFINISHPAGE_BITMAP', 'MUI_UNWELCOMEFINISHPAGE_BITMAP_NOSTRETCH',
+            'MUI_UNWELCOMEFINISHPAGE_INI', 'MUI_LICENSEPAGE_BGCOLOR', 'MUI_COMPONENTSPAGE_CHECKBITMAP',
+            'MUI_COMPONENTSPAGE_SMALLDESC', 'MUI_COMPONENTSPAGE_NODESC', 'MUI_INSTFILESPAGE_COLORS',
+            'MUI_INSTFILESPAGE_PROGRESSBAR', 'MUI_FINISHPAGE_NOAUTOCLOSE', 'MUI_UNFINISHPAGE_NOAUTOCLOSE',
+            'MUI_ABORTWARNING', 'MUI_ABORTWARNING_TEXT', 'MUI_UNABORTWARNING', 'MUI_UNABORTWARNING_TEXT',
+            'MUI_PAGE_WELCOME', 'MUI_PAGE_LICENSE', 'MUI_PAGE_COMPONENTS', 'MUI_PAGE_DIRECTORY',
+            'MUI_PAGE_STARTMENU', 'MUI_PAGE_INSTFILES', 'MUI_PAGE_FINISH', 'MUI_UNPAGE_WELCOME',
+            'MUI_UNPAGE_CONFIRM', 'MUI_UNPAGE_LICENSE', 'MUI_UNPAGE_COMPONENTS', 'MUI_UNPAGE_DIRECTORY',
+            'MUI_UNPAGE_INSTFILES', 'MUI_UNPAGE_FINISH', 'MUI_PAGE_HEADER_TEXT', 'MUI_PAGE_HEADER_SUBTEXT',
+            'MUI_WELCOMEPAGE_TITLE', 'MUI_WELCOMEPAGE_TITLE_3LINES', 'MUI_WELCOMEPAGE_TEXT',
+            'MUI_LICENSEPAGE_TEXT_TOP', 'MUI_LICENSEPAGE_TEXT_BOTTOM', 'MUI_LICENSEPAGE_BUTTON',
+            'MUI_LICENSEPAGE_CHECKBOX', 'MUI_LICENSEPAGE_CHECKBOX_TEXT', 'MUI_LICENSEPAGE_RADIOBUTTONS',
+            'MUI_LICENSEPAGE_RADIOBUTTONS_TEXT_ACCEPT', 'MUI_LICENSEPAGE_RADIOBUTTONS_TEXT_DECLINE',
+            'MUI_COMPONENTSPAGE_TEXT_TOP', 'MUI_COMPONENTSPAGE_TEXT_COMPLIST', 'MUI_COMPONENTSPAGE_TEXT_INSTTYPE',
+            'MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_TITLE', 'MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_INFO',
+            'MUI_DIRECTORYPAGE_TEXT_TOP', 'MUI_DIRECTORYPAGE_TEXT_DESTINATION', 'MUI_DIRECTORYPAGE_VARIABLE',
+            'MUI_DIRECTORYPAGE_VERIFYONLEAVE', 'MUI_STARTMENU_WRITE_BEGIN', 'MUI_STARTMENU_WRITE_END',
+            'MUI_STARTMENUPAGE_TEXT_TOP', 'MUI_STARTMENUPAGE_TEXT_CHECKBOX', 'MUI_STARTMENUPAGE_DEFAULTFOLDER',
+            'MUI_STARTMENUPAGE_NODISABLE', 'MUI_STARTMENUPAGE_REGISTRY_ROOT', 'MUI_STARTMENUPAGE_REGISTRY_KEY',
+            'MUI_STARTMENUPAGE_REGISTRY_VALUENAME', 'MUI_INSTFILESPAGE_FINISHHEADER_TEXT',
+            'MUI_INSTFILESPAGE_FINISHHEADER_SUBTEXT', 'MUI_INSTFILESPAGE_ABORTHEADER_TEXT',
+            'MUI_INSTFILESPAGE_ABORTHEADER_SUBTEXT', 'MUI_FINISHPAGE_TITLE', 'MUI_FINISHPAGE_TITLE_3LINES',
+            'MUI_FINISHPAGE_TEXT', 'MUI_FINISHPAGE_TEXT_LARGE', 'MUI_FINISHPAGE_BUTTON',
+            'MUI_FINISHPAGE_TEXT_REBOOT', 'MUI_FINISHPAGE_TEXT_REBOOTNOW', 'MUI_FINISHPAGE_TEXT_REBOOTLATER',
+            'MUI_FINISHPAGE_RUN', 'MUI_FINISHPAGE_RUN_TEXT', 'MUI_FINISHPAGE_RUN_PARAMETERS',
+            'MUI_FINISHPAGE_RUN_NOTCHECKED', 'MUI_FINISHPAGE_RUN_FUNCTION', 'MUI_FINISHPAGE_SHOWREADME',
+            'MUI_FINISHPAGE_SHOWREADME_TEXT', 'MUI_FINISHPAGE_SHOWREADME_NOTCHECKED',
+            'MUI_FINISHPAGE_SHOWREADME_FUNCTION', 'MUI_FINISHPAGE_LINK', 'MUI_FINISHPAGE_LINK_LOCATION',
+            'MUI_FINISHPAGE_LINK_COLOR', 'MUI_FINISHPAGE_NOREBOOTSUPPORT', 'MUI_UNCONFIRMPAGE_TEXT_TOP',
+            'MUI_UNCONFIRMPAGE_TEXT_LOCATION', 'MUI_LANGUAGE', 'MUI_LANGDLL_DISPLAY',
+            'MUI_LANGDLL_REGISTRY_ROOT', 'MUI_LANGDLL_REGISTRY_KEY', 'MUI_LANGDLL_REGISTRY_VALUENAME',
+            'MUI_LANGDLL_WINDOWTITLE', 'MUI_LANGDLL_INFO', 'MUI_LANGDLL_ALWAYSSHOW',
+            'MUI_RESERVEFILE_INSTALLOPTIONS', 'MUI_RESERVEFILE_LANGDLL', 'MUI_FUNCTION_DESCRIPTION_BEGIN',
+            'MUI_DESCRIPTION_TEXT', 'MUI_FUNCTION_DESCRIPTION_END', 'MUI_INSTALLOPTIONS_EXTRACT',
+            'MUI_INSTALLOPTIONS_EXTRACT_AS', 'MUI_HEADER_TEXT', 'MUI_INSTALLOPTIONS_DISPLAY',
+            'MUI_INSTALLOPTIONS_INITDIALOG', 'MUI_INSTALLOPTIONS_SHOW',
+            'MUI_INSTALLOPTIONS_DISPLAY_RETURN', 'MUI_INSTALLOPTIONS_SHOW_RETURN',
+            'MUI_INSTALLOPTIONS_READ', 'MUI_INSTALLOPTIONS_WRITE',
+            'MUI_CUSTOMFUNCTION_GUIINIT', 'MUI_CUSTOMFUNCTION_UNGUIINIT',
+            'MUI_CUSTOMFUNCTION_ABORT', 'MUI_CUSTOMFUNCTION_UNABORT',
+            'MUI_PAGE_CUSTOMFUNCTION_PRE', 'MUI_PAGE_CUSTOMFUNCTION_SHOW', 'MUI_PAGE_CUSTOMFUNCTION_LEAVE',
+            'MUI_WELCOMEFINISHPAGE_CUSTOMFUNCTION_INIT'
+            ),
+        9 => array(
+            'LogicLib.nsh', '${LOGICLIB}', 'LOGICLIB_STRCMP', 'LOGICLIB_INT64CMP', 'LOGICLIB_SECTIONCMP', '${If}', '${Unless}',
+            '${ElseIf}', '${ElseUnless}', '${Else}', '${EndIf}', '${EndUnless}', '${AndIf}', '${AndUnless}',
+            '${OrIf}', '${OrUnless}', '${IfThen}', '${IfCmd}', '${Select}', '${Case2}', '${Case3}',
+            '${Case4}', '${Case5}', '${CaseElse}', '${Default}', '${EndSelect}', '${Switch}',
+            '${Case}', '${EndSwitch}', '${Do}', '${DoWhile}', '${UntilWhile}', '${Continue}', '${Break}',
+            '${Loop}', '${LoopWhile}', '${LoopUntil}', '${While}', '${ExitWhile}', '${EndWhile}', '${For}',
+            '${ForEach}', '${ExitFor}', '${Next}', '${Abort}', '${Errors}', '${RebootFlag}', '${Silent}',
+            '${FileExists}', '${Cmd}', '${SectionIsSelected}', '${SectionIsSectionGroup}',
+            '${SectionIsSectionGroupEnd}', '${SectionIsBold}', '${SectionIsReadOnly}',
+            '${SectionIsExpanded}', '${SectionIsPartiallySelected}'
+            ),
+        10 => array(
+            'StrFunc.nsh', '${STRFUNC}', '${StrCase}', '${StrClb}', '${StrIOToNSIS}', '${StrLoc}', '${StrNSISToIO}', '${StrRep}',
+            '${StrSort}', '${StrStr}', '${StrStrAdv}', '${StrTok}', '${StrTrimNewLines}'
+            ),
+        11 => array(
+            'UpgradeDLL.nsh', 'UPGRADEDLL_INCLUDED', 'UpgradeDLL'
+            ),
+        12 => array(
+            'Sections.nsh', 'SECTIONS_INCLUDED', '${SF_SELECTED}', '${SF_SECGRP}', '${SF_SUBSEC}', '${SF_SECGRPEND}',
+            '${SF_SUBSECEND}', '${SF_BOLD}', '${SF_RO}', '${SF_EXPAND}', '${SF_PSELECTED}', '${SF_TOGGLED}',
+            '${SF_NAMECHG}', '${SECTION_OFF}', 'SelectSection', 'UnselectSection', 'ReverseSection',
+            'StartRadioButtons', 'RadioButton', 'EndRadioButtons', '${INSTTYPE_0}', '${INSTTYPE_1}', '${INSTTYPE_2}',
+            '${INSTTYPE_3}', '${INSTTYPE_4}', '${INSTTYPE_5}', '${INSTTYPE_6}', '${INSTTYPE_7}', '${INSTTYPE_8}',
+            '${INSTTYPE_9}', '${INSTTYPE_10}', '${INSTTYPE_11}', '${INSTTYPE_12}', '${INSTTYPE_13}', '${INSTTYPE_14}',
+            '${INSTTYPE_15}', '${INSTTYPE_16}', '${INSTTYPE_17}', '${INSTTYPE_18}', '${INSTTYPE_19}', '${INSTTYPE_20}',
+            '${INSTTYPE_21}', '${INSTTYPE_22}', '${INSTTYPE_23}', '${INSTTYPE_24}', '${INSTTYPE_25}', '${INSTTYPE_26}',
+            '${INSTTYPE_27}', '${INSTTYPE_28}', '${INSTTYPE_29}', '${INSTTYPE_30}', '${INSTTYPE_31}', '${INSTTYPE_32}',
+            'SetSectionInInstType', 'ClearSectionInInstType', 'SetSectionFlag', 'ClearSectionFlag', 'SectionFlagIsSet'
+            ),
+        13 => array(
+            'Colors.nsh', 'WHITE', 'BLACK', 'YELLOW', 'RED', 'GREEN', 'BLUE', 'MAGENTA', 'CYAN', 'rgb2hex'
+            ),
+        14 => array(
+            'FileFunc.nsh', '${Locate}', '${GetSize}', '${DriveSpace}', '${GetDrives}', '${GetTime}', '${GetFileAttributes}', '${GetFileVersion}', '${GetExeName}', '${GetExePath}', '${GetParameters}', '${GetOptions}', '${GetRoot}', '${GetParent}', '${GetFileName}', '${GetBaseName}', '${GetFileExt}', '${BannerTrimPath}', '${DirState}', '${RefreshShellIcons}'
+            ),
+        15 => array(
+            'TextFunc.nsh', '${LineFind}', '${LineRead}', '${FileReadFromEnd}', '${LineSum}', '${FileJoin}', '${TextCompare}', '${ConfigRead}', '${ConfigWrite}', '${FileRecode}', '${TrimNewLines}'
+            ),
+        16 => array(
+            'WordFunc.nsh', '${WordFind}', '${WordFind2X}', '${WordFind3X}', '${WordReplace}', '${WordAdd}', '${WordInsert}', '${StrFilter}', '${VersionCompare}', '${VersionConvert}'
+            )
+        ),
+    'SYMBOLS' => array(
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        5 => false,
+        6 => false,
+        7 => false,
+        8 => false,
+        9 => false,
+        10 => false,
+        11 => false,
+        12 => false,
+        13 => false,
+        14 => false,
+        15 => false,
+        16 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000066; font-weight:bold;',
+            2 => 'color: #000066;',
+            3 => 'color: #003366;',
+            4 => 'color: #000099;',
+            5 => 'color: #ff6600;',
+            6 => 'color: #ff6600;',
+            7 => 'color: #006600;',
+            8 => 'color: #006600;',
+            9 => 'color: #006600;',
+            10 => 'color: #006600;',
+            11 => 'color: #006600;',
+            12 => 'color: #006600;',
+            13 => 'color: #006600;',
+            14 => 'color: #006600;',
+            15 => 'color: #006600;',
+            16 => 'color: #006600;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #666666; font-style: italic;',
+            2 => 'color: #666666; font-style: italic;',
+            'MULTI' => 'color: #666666; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #660066; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => ''
+            ),
+        'STRINGS' => array(
+            0 => 'color: #660066;'
+            ),
+        'NUMBERS' => array(
+            0 => ''
+            ),
+        'METHODS' => array(
+            0 => ''
+            ),
+        'SYMBOLS' => array(
+            0 => ''
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #660000;',
+            1 => 'color: #660000;',
+            2 => 'color: #660000;',
+            3 => 'color: #660000;',
+            4 => 'color: #660000;',
+            5 => 'color: #660000;',
+            6 => 'color: #660000;',
+            7 => 'color: #000099;',
+            8 => 'color: #003399;'
+            ),
+        'SCRIPT' => array(
+            0 => ''
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => '',
+        5 => '',
+        6 => '',
+        7 => '',
+        8 => '',
+        9 => '',
+        10 => '',
+        11 => '',
+        12 => '',
+        13 => '',
+        14 => '',
+        15 => '',
+        16 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        0 => '\$\$',
+        1 => '\$\\r',
+        2 => '\$\\n',
+        3 => '\$\\t',
+        4 => '\$[a-zA-Z0-9_]+',
+        5 => '\$\{.{1,256}\}',
+        6 => '\$\\\(.{1,256}\\\)',
+        7 => array(
+            GESHI_SEARCH => '([^:\/\\\*\?\"\<\>(?:<PIPE>)\s]*?)(::)([^:\/\\\*\?\"\<\>(?:<PIPE>)\s]*?)',
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => '\\2\\3'
+            ),
+        8 => array(
+            GESHI_SEARCH => '([^:\/\\\*\?\"\<\>(?:<PIPE>)\s]*?)(::)([^:\/\\\*\?\"\<\>(?:<PIPE>)]*?\s)',
+            GESHI_REPLACE => '\\3',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '\\1\\2',
+            GESHI_AFTER => ''
+            )
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/objc.php b/examples/includes/geshi/geshi/objc.php
new file mode 100644 (file)
index 0000000..668f14b
--- /dev/null
@@ -0,0 +1,358 @@
+<?php
+/*************************************************************************************
+ * objc.php
+ * --------
+ * Author: M. Uli Kusterer (witness.of.teachtext@gmx.net)
+ * Contributors: Quinn Taylor (quinntaylor@mac.com)
+ * Copyright: (c) 2008 Quinn Taylor, 2004 M. Uli Kusterer, Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/06/04
+ *
+ * Objective-C language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/07/11 (1.0.8)
+ *   -  Added support for @ before strings being highlighted
+ * 2008/06/10 (1.0.7.22)
+ *   -  Added keywords for Objective-C 2.0 (Leopard+).
+ *   -  Changed colors to match Xcode 3 highlighting more closely.
+ *   -  Updated API for AppKit and Foundation; added CoreData classes.
+ *   -  Updated URLs for AppKit and Foundation; split classes and protocols.
+ *   -  Sorted all keyword group in reverse-alpha order for correct matching.
+ *   -  Changed all keyword groups to be case-sensitive.
+ * 2004/11/27 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Objective-C',
+    'COMMENT_SINGLE' => array(
+        //Compiler directives
+        1 => '#',
+        //Single line C-Comments
+        2 => '//'
+        ),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'COMMENT_REGEXP' => array(
+        //Multiline Continuation for single-line comment
+        2 => '/\/\/(?:\\\\\\\\|\\\\\\n|.)*$/m',
+        //Pseudo-Highlighting of the @-sign before strings
+        3 => "/@(?=\")/"
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"', "'"),
+    'ESCAPE_CHAR' => '\\',
+
+    'KEYWORDS' => array(
+        // Objective-C keywords
+        1 => array(
+            'while', 'switch', 'return', 'in', 'if', 'goto', 'foreach', 'for',
+            'else', 'do', 'default', 'continue', 'case', '@try', '@throw',
+            '@synthesize', '@synchronized', '@selector', '@public', '@protocol',
+            '@protected', '@property', '@private', '@interface',
+            '@implementation', '@finally', '@end', '@encode', '@defs', '@class',
+            '@catch'
+            ),
+        // Macros and constants
+        2 => array(
+            'YES', 'USHRT_MAX', 'ULONG_MAX', 'UINT_MAX', 'UCHAR_MAX', 'true',
+            'TMP_MAX', 'stdout', 'stdin', 'stderr', 'SIGTERM', 'SIGSEGV',
+            'SIGINT', 'SIGILL', 'SIG_IGN', 'SIGFPE', 'SIG_ERR', 'SIG_DFL',
+            'SIGABRT', 'SHRT_MIN', 'SHRT_MAX', 'SEEK_SET', 'SEEK_END',
+            'SEEK_CUR', 'SCHAR_MIN', 'SCHAR_MAX', 'RAND_MAX', 'NULL',
+            'NO', 'nil', 'Nil', 'L_tmpnam', 'LONG_MIN', 'LONG_MAX',
+            'LDBL_MIN_EXP', 'LDBL_MIN', 'LDBL_MAX_EXP', 'LDBL_MAX',
+            'LDBL_MANT_DIG', 'LDBL_EPSILON', 'LDBL_DIG', 'INT_MIN', 'INT_MAX',
+            'HUGE_VAL', 'FOPEN_MAX', 'FLT_ROUNDS', 'FLT_RADIX', 'FLT_MIN_EXP',
+            'FLT_MIN', 'FLT_MAX_EXP', 'FLT_MAX', 'FLT_MANT_DIG', 'FLT_EPSILON',
+            'FLT_DIG', 'FILENAME_MAX', 'false', 'EXIT_SUCCESS', 'EXIT_FAILURE',
+            'errno', 'ERANGE', 'EOF', 'enum', 'EDOM', 'DBL_MIN_EXP', 'DBL_MIN',
+            'DBL_MAX_EXP', 'DBL_MAX', 'DBL_MANT_DIG', 'DBL_EPSILON', 'DBL_DIG',
+            'CLOCKS_PER_SEC', 'CHAR_MIN', 'CHAR_MAX', 'CHAR_BIT', 'BUFSIZ',
+            'break'
+            ),
+        // C standard library functions
+        3 => array(
+            'vsprintf', 'vprintf', 'vfprintf', 'va_start', 'va_end', 'va_arg',
+            'ungetc', 'toupper', 'tolower', 'tmpname', 'tmpfile', 'time',
+            'tanh', 'tan', 'system', 'strxfrm', 'strtoul', 'strtol', 'strtok',
+            'strtod', 'strstr', 'strspn', 'strrchr', 'strpbrk', 'strncpy',
+            'strncmp', 'strncat', 'strlen', 'strftime', 'strerror', 'strcspn',
+            'strcpy', 'strcoll', 'strcmp', 'strchr', 'strcat', 'sscanf',
+            'srand', 'sqrt', 'sprintf', 'snprintf', 'sizeof', 'sinh', 'sin',
+            'setvbuf', 'setjmp', 'setbuf', 'scanf', 'rewind', 'rename',
+            'remove', 'realloc', 'rand', 'qsort', 'puts', 'putchar', 'putc',
+            'printf', 'pow', 'perror', 'offsetof', 'modf', 'mktime', 'memset',
+            'memmove', 'memcpy', 'memcmp', 'memchr', 'malloc', 'longjmp',
+            'log10', 'log', 'localtime', 'ldiv', 'ldexp', 'labs', 'isxdigit',
+            'isupper', 'isspace', 'ispunct', 'isprint', 'islower',
+            'isgraph', 'isdigit', 'iscntrl', 'isalpha', 'isalnum', 'gmtime',
+            'gets', 'getenv', 'getchar', 'getc', 'fwrite', 'ftell', 'fsetpos',
+            'fseek', 'fscanf', 'frexp', 'freopen', 'free', 'fread', 'fputs',
+            'fputc', 'fprintf', 'fopen', 'fmod', 'floor', 'fgets', 'fgetpos',
+            'fgetc', 'fflush', 'ferror', 'feof', 'fclose', 'fabs', 'exp',
+            'exit', 'div', 'difftime', 'ctime', 'cosh', 'cos', 'clock',
+            'clearerr', 'ceil', 'calloc', 'bsearch', 'atol', 'atoi', 'atof',
+            'atexit', 'atan2', 'atan', 'assert', 'asin', 'asctime', 'acos',
+            'abs', 'abort'
+            ),
+        // Data types (C, Objective-C, Cocoa)
+        4 => array(
+            'volatile', 'void', 'va_list', 'unsigned', 'union', 'typedef', 'tm',
+            'time_t', 'struct', 'string', 'static', 'size_t',
+            'signed', 'signal', 'short', 'SEL', 'register', 'raise',
+            'ptrdiff_t', 'NSZone', 'NSRect', 'NSRange', 'NSPoint', 'long',
+            'ldiv_t', 'jmp_buf', 'int', 'IMP', 'id', 'fpos_t', 'float', 'FILE',
+            'extern', 'double', 'div_t', 'const', 'clock_t', 'Class', 'char',
+            'BOOL', 'auto'
+            ),
+        // Foundation classes
+        5 => array(
+            'NSXMLParser', 'NSXMLNode', 'NSXMLElement', 'NSXMLDTDNode',
+            'NSXMLDTD', 'NSXMLDocument', 'NSWhoseSpecifier',
+            'NSValueTransformer', 'NSValue', 'NSUserDefaults', 'NSURLResponse',
+            'NSURLRequest', 'NSURLProtocol', 'NSURLProtectionSpace',
+            'NSURLHandle', 'NSURLDownload', 'NSURLCredentialStorage',
+            'NSURLCredential', 'NSURLConnection', 'NSURLCache',
+            'NSURLAuthenticationChallenge', 'NSURL', 'NSUniqueIDSpecifier',
+            'NSUndoManager', 'NSUnarchiver', 'NSTimeZone', 'NSTimer',
+            'NSThread', 'NSTask', 'NSString', 'NSStream', 'NSSpellServer',
+            'NSSpecifierTest', 'NSSortDescriptor', 'NSSocketPortNameServer',
+            'NSSocketPort', 'NSSetCommand', 'NSSet', 'NSSerializer',
+            'NSScriptWhoseTest', 'NSScriptSuiteRegistry',
+            'NSScriptObjectSpecifier', 'NSScriptExecutionContext',
+            'NSScriptCommandDescription', 'NSScriptCommand',
+            'NSScriptCoercionHandler', 'NSScriptClassDescription', 'NSScanner',
+            'NSRunLoop', 'NSRelativeSpecifier', 'NSRecursiveLock',
+            'NSRangeSpecifier', 'NSRandomSpecifier', 'NSQuitCommand', 'NSProxy',
+            'NSProtocolChecker', 'NSPropertySpecifier',
+            'NSPropertyListSerialization', 'NSProcessInfo', 'NSPredicate',
+            'NSPositionalSpecifier', 'NSPortNameServer', 'NSPortMessage',
+            'NSPortCoder', 'NSPort', 'NSPointerFunctions', 'NSPointerArray',
+            'NSPipe', 'NSOutputStream', 'NSOperationQueue', 'NSOperation',
+            'NSObject', 'NSNumberFormatter', 'NSNumber', 'NSNull',
+            'NSNotificationQueue', 'NSNotificationCenter', 'NSNotification',
+            'NSNetServiceBrowser', 'NSNetService', 'NSNameSpecifier',
+            'NSMutableURLRequest', 'NSMutableString', 'NSMutableSet',
+            'NSMutableIndexSet', 'NSMutableDictionary', 'NSMutableData',
+            'NSMutableCharacterSet', 'NSMutableAttributedString',
+            'NSMutableArray', 'NSMoveCommand', 'NSMiddleSpecifier',
+            'NSMethodSignature', 'NSMetadataQueryResultGroup',
+            'NSMetadataQueryAttributeValueTuple', 'NSMetadataQuery',
+            'NSMetadataItem', 'NSMessagePortNameServer', 'NSMessagePort',
+            'NSMapTable', 'NSMachPort', 'NSMachBootstrapServer',
+            'NSLogicalTest', 'NSLock', 'NSLocale', 'NSKeyedUnarchiver',
+            'NSKeyedArchiver', 'NSInvocationOperation', 'NSInvocation',
+            'NSInputStream', 'NSIndexSpecifier', 'NSIndexSet', 'NSIndexPath',
+            'NSHTTPURLResponse', 'NSHTTPCookieStorage', 'NSHTTPCookie',
+            'NSHost', 'NSHashTable', 'NSGetCommand', 'NSGarbageCollector',
+            'NSFormatter', 'NSFileManager', 'NSFileHandle', 'NSExpression',
+            'NSExistsCommand', 'NSException', 'NSError', 'NSEnumerator',
+            'NSDistributedNotificationCenter', 'NSDistributedLock',
+            'NSDistantObjectRequest', 'NSDistantObject',
+            'NSDirectoryEnumerator', 'NSDictionary', 'NSDeserializer',
+            'NSDeleteCommand', 'NSDecimalNumberHandler', 'NSDecimalNumber',
+            'NSDateFormatter', 'NSDateComponents', 'NSDate', 'NSData',
+            'NSCreateCommand', 'NSCountedSet', 'NSCountCommand', 'NSConnection',
+            'NSConditionLock', 'NSCondition', 'NSCompoundPredicate',
+            'NSComparisonPredicate', 'NSCoder', 'NSCloseCommand',
+            'NSCloneCommand', 'NSClassDescription', 'NSCharacterSet',
+            'NSCalendarDate', 'NSCalendar', 'NSCachedURLResponse', 'NSBundle',
+            'NSAutoreleasePool', 'NSAttributedString', 'NSAssertionHandler',
+            'NSArray', 'NSArchiver', 'NSAppleScript', 'NSAppleEventManager',
+            'NSAppleEventDescriptor', 'NSAffineTransform'
+            ),
+        // Foundation protocols
+        6 => array(
+            'NSURLProtocolClient', 'NSURLHandleClient', 'NSURLClient',
+            'NSURLAuthenticationChallengeSender', 'NSScriptObjectSpecifiers',
+            'NSScriptKeyValueCoding', 'NSScriptingComparisonMethods',
+            'NSObjCTypeSerializationCallBack', 'NSMutableCopying',
+            'NSLocking', 'NSKeyValueObserving', 'NSKeyValueCoding',
+            'NSFastEnumeration', 'NSErrorRecoveryAttempting',
+            'NSDecimalNumberBehaviors', 'NSCopying', 'NSComparisonMethods',
+            'NSCoding'
+            ),
+        // AppKit classes
+        7 => array(
+            'NSWorkspace', 'NSWindowController', 'NSWindow', 'NSViewController',
+            'NSViewAnimation', 'NSView', 'NSUserDefaultsController',
+            'NSTypesetter', 'NSTreeNode', 'NSTreeController', 'NSTrackingArea',
+            'NSToolbarItemGroup', 'NSToolbarItem', 'NSToolbar',
+            'NSTokenFieldCell', 'NSTokenField', 'NSTextView',
+            'NSTextTableBlock', 'NSTextTable', 'NSTextTab', 'NSTextStorage',
+            'NSTextList', 'NSTextFieldCell', 'NSTextField', 'NSTextContainer',
+            'NSTextBlock', 'NSTextAttachmentCell', 'NSTextAttachment', 'NSText',
+            'NSTabViewItem', 'NSTabView', 'NSTableView', 'NSTableHeaderView',
+            'NSTableHeaderCell', 'NSTableColumn', 'NSStepperCell', 'NSStepper',
+            'NSStatusItem', 'NSStatusBar', 'NSSplitView', 'NSSpellChecker',
+            'NSSpeechSynthesizer', 'NSSpeechRecognizer', 'NSSound',
+            'NSSliderCell', 'NSSlider', 'NSSimpleHorizontalTypesetter',
+            'NSShadow', 'NSSegmentedControl', 'NSSegmentedCell',
+            'NSSecureTextFieldCell', 'NSSecureTextField', 'NSSearchFieldCell',
+            'NSSearchField', 'NSScrollView', 'NSScroller', 'NSScreen',
+            'NSSavePanel', 'NSRulerView', 'NSRulerMarker', 'NSRuleEditor',
+            'NSResponder', 'NSQuickDrawView', 'NSProgressIndicator',
+            'NSPrintPanel', 'NSPrintOperation', 'NSPrintInfo', 'NSPrinter',
+            'NSPredicateEditorRowTemplate', 'NSPredicateEditor',
+            'NSPopUpButtonCell', 'NSPopUpButton', 'NSPICTImageRep',
+            'NSPersistentDocument', 'NSPDFImageRep', 'NSPathControl',
+            'NSPathComponentCell', 'NSPathCell', 'NSPasteboard',
+            'NSParagraphStyle', 'NSPanel', 'NSPageLayout', 'NSOutlineView',
+            'NSOpenPanel', 'NSOpenGLView', 'NSOpenGLPixelFormat',
+            'NSOpenGLPixelBuffer', 'NSOpenGLContext', 'NSObjectController',
+            'NSNibOutletConnector', 'NSNibControlConnector', 'NSNibConnector',
+            'NSNib', 'NSMutableParagraphStyle', 'NSMovieView', 'NSMovie',
+            'NSMenuView', 'NSMenuItemCell', 'NSMenuItem', 'NSMenu', 'NSMatrix',
+            'NSLevelIndicatorCell', 'NSLevelIndicator', 'NSLayoutManager',
+            'NSInputServer', 'NSInputManager', 'NSImageView', 'NSImageRep',
+            'NSImageCell', 'NSImage', 'NSHelpManager', 'NSGraphicsContext',
+            'NSGradient', 'NSGlyphInfo', 'NSGlyphGenerator', 'NSFormCell',
+            'NSForm', 'NSFontPanel', 'NSFontManager', 'NSFontDescriptor',
+            'NSFont', 'NSFileWrapper', 'NSEvent', 'NSEPSImageRep', 'NSDrawer',
+            'NSDocumentController', 'NSDocument', 'NSDockTile',
+            'NSDictionaryController', 'NSDatePickerCell', 'NSDatePicker',
+            'NSCustomImageRep', 'NSCursor', 'NSController', 'NSControl',
+            'NSComboBoxCell', 'NSComboBox', 'NSColorWell', 'NSColorSpace',
+            'NSColorPicker', 'NSColorPanel', 'NSColorList', 'NSColor',
+            'NSCollectionViewItem', 'NSCollectionView', 'NSClipView',
+            'NSCIImageRep', 'NSCell', 'NSCachedImageRep', 'NSButtonCell',
+            'NSButton', 'NSBrowserCell', 'NSBrowser', 'NSBox',
+            'NSBitmapImageRep', 'NSBezierPath', 'NSATSTypesetter',
+            'NSArrayController', 'NSApplication', 'NSAnimationContext',
+            'NSAnimation', 'NSAlert', 'NSActionCell'
+            ),
+        // AppKit protocols
+        8 => array(
+            'NSWindowScripting', 'NSValidatedUserInterfaceItem',
+            'NSUserInterfaceValidations', 'NSToolTipOwner',
+            'NSToolbarItemValidation', 'NSTextInput',
+            'NSTableDataSource', 'NSServicesRequests',
+            'NSPrintPanelAccessorizing', 'NSPlaceholders',
+            'NSPathControlDelegate', 'NSPathCellDelegate',
+            'NSOutlineViewDataSource', 'NSNibAwaking', 'NSMenuValidation',
+            'NSKeyValueBindingCreation', 'NSInputServiceProvider',
+            'NSInputServerMouseTracker', 'NSIgnoreMisspelledWords',
+            'NSGlyphStorage', 'NSFontPanelValidation', 'NSEditorRegistration',
+            'NSEditor', 'NSDraggingSource', 'NSDraggingInfo',
+            'NSDraggingDestination', 'NSDictionaryControllerKeyValuePair',
+            'NSComboBoxDataSource', 'NSComboBoxCellDataSource',
+            'NSColorPickingDefault', 'NSColorPickingCustom', 'NSChangeSpelling',
+            'NSAnimatablePropertyContainer', 'NSAccessibility'
+            ),
+        // CoreData classes
+        9 => array(
+            'NSRelationshipDescription', 'NSPropertyMapping',
+            'NSPropertyDescription', 'NSPersistentStoreCoordinator',
+            'NSPersistentStore', 'NSMigrationManager', 'NSMappingModel',
+            'NSManagedObjectModel', 'NSManagedObjectID',
+            'NSManagedObjectContext', 'NSManagedObject',
+            'NSFetchRequestExpression', 'NSFetchRequest',
+            'NSFetchedPropertyDescription', 'NSEntityMigrationPolicy',
+            'NSEntityMapping', 'NSEntityDescription', 'NSAttributeDescription',
+            'NSAtomicStoreCacheNode', 'NSAtomicStore'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '{', '}', '[', ']', '=', '+', '-', '*', '/', '!', '%', '^', '&', ':'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => true,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true,
+        5 => true,
+        6 => true,
+        7 => true,
+        8 => true,
+        9 => true
+        ),
+    // Define the colors for the groups listed above
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #a61390;', // Objective-C keywords
+            2 => 'color: #a61390;', // Macros and constants
+            3 => 'color: #a61390;', // C standard library functions
+            4 => 'color: #a61390;', // data types
+            5 => 'color: #400080;', // Foundation classes
+            6 => 'color: #2a6f76;', // Foundation protocols
+            7 => 'color: #400080;', // AppKit classes
+            8 => 'color: #2a6f76;', // AppKit protocols
+            9 => 'color: #400080;' // CoreData classes
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #6e371a;', // Preprocessor directives
+            2 => 'color: #11740a; font-style: italic;', // Normal C single-line comments
+            3 => 'color: #bf1d1a;', // Q-sign in front of Strings
+            'MULTI' => 'color: #11740a; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #2400d9;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #002200;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #bf1d1a;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #2400d9;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #002200;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => 'http://www.opengroup.org/onlinepubs/009695399/functions/{FNAME}.html',
+        4 => '',
+        5 => 'http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/{FNAME}_Class/',
+        6 => 'http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Protocols/{FNAME}_Protocol/',
+        7 => 'http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/{FNAME}_Class/',
+        8 => 'http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Protocols/{FNAME}_Protocol/',
+        9 => 'http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/{FNAME}_Class/'
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/ocaml-brief.php b/examples/includes/geshi/geshi/ocaml-brief.php
new file mode 100644 (file)
index 0000000..8c15519
--- /dev/null
@@ -0,0 +1,112 @@
+<?php
+/*************************************************************************************
+ * ocaml.php
+ * ----------
+ * Author: Flaie (fireflaie@gmail.com)
+ * Copyright: (c) 2005 Flaie, Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2005/08/27
+ *
+ * OCaml (Objective Caml) language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2005/08/27 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2005/08/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *   This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'OCaml (brief)',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array('(*' => '*)'),
+    'CASE_KEYWORDS' => 0,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => "",
+    'KEYWORDS' => array(
+        /* main OCaml keywords */
+        1 => array(
+            'and', 'as', 'asr', 'begin', 'class', 'closed', 'constraint', 'do', 'done', 'downto', 'else',
+            'end', 'exception', 'external', 'failwith', 'false', 'flush', 'for', 'fun', 'function', 'functor',
+            'if', 'in', 'include', 'inherit',  'incr', 'land', 'let', 'load', 'los', 'lsl', 'lsr', 'lxor',
+            'match', 'method', 'mod', 'module', 'mutable', 'new', 'not', 'of', 'open', 'option', 'or', 'parser',
+            'private', 'ref', 'rec', 'raise', 'regexp', 'sig', 'struct', 'stdout', 'stdin', 'stderr', 'then',
+            'to', 'true', 'try', 'type', 'val', 'virtual', 'when', 'while', 'with'
+            )
+        ),
+    /* highlighting symbols is really important in OCaml */
+    'SYMBOLS' => array(
+        ';', '!', ':', '.', '=', '%', '^', '*', '-', '/', '+',
+        '>', '<', '(', ')', '[', ']', '&', '|', '#', "'"
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #06c; font-weight: bold;' /* nice blue */
+            ),
+        'COMMENTS' => array(
+            'MULTI' => 'color: #5d478b; font-style: italic;' /* light purple */
+            ),
+        'ESCAPE_CHAR' => array(
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #6c6;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #3cb371;' /* nice green */
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #c6c;' /* pink */
+            ),
+        'METHODS' => array(
+            1 => 'color: #060;' /* dark green */
+            ),
+        'REGEXPS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #a52a2a;' /* maroon */
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/ocaml.php b/examples/includes/geshi/geshi/ocaml.php
new file mode 100644 (file)
index 0000000..e21ca7f
--- /dev/null
@@ -0,0 +1,174 @@
+<?php
+/*************************************************************************************
+ * ocaml.php
+ * ----------
+ * Author: Flaie (fireflaie@gmail.com)
+ * Copyright: (c) 2005 Flaie, Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2005/08/27
+ *
+ * OCaml (Objective Caml) language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/03/29 (1.0.7.22)
+ *   -  Fixed warnings resulting from missing style information
+ * 2005/08/27 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2005/08/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *   This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'OCaml',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array('(*' => '*)'),
+    'CASE_KEYWORDS' => 0,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => "",
+    'KEYWORDS' => array(
+        /* main OCaml keywords */
+        1 => array(
+            'and', 'as', 'asr', 'begin', 'class', 'closed', 'constraint', 'do', 'done', 'downto', 'else',
+            'end', 'exception', 'external', 'failwith', 'false', 'for', 'fun', 'function', 'functor',
+            'if', 'in', 'include', 'inherit',  'incr', 'land', 'let', 'load', 'los', 'lsl', 'lsr', 'lxor',
+            'match', 'method', 'mod', 'module', 'mutable', 'new', 'not', 'of', 'open', 'option', 'or', 'parser',
+            'private', 'ref', 'rec', 'raise', 'regexp', 'sig', 'struct', 'stdout', 'stdin', 'stderr', 'then',
+            'to', 'true', 'try', 'type', 'val', 'virtual', 'when', 'while', 'with'
+            ),
+        /* define names of main librarys, so we can link to it */
+        2 => array(
+            'Arg', 'Arith_status', 'Array', 'ArrayLabels', 'Big_int', 'Bigarray', 'Buffer', 'Callback',
+            'CamlinternalOO', 'Char', 'Complex', 'Condition', 'Dbm', 'Digest', 'Dynlink', 'Event',
+            'Filename', 'Format', 'Gc', 'Genlex', 'Graphics', 'GraphicsX11', 'Hashtbl', 'Int32', 'Int64',
+            'Lazy', 'Lexing', 'List', 'ListLabels', 'Map', 'Marshal', 'MoreLabels', 'Mutex', 'Nativeint',
+            'Num', 'Obj', 'Oo', 'Parsing', 'Pervasives', 'Printexc', 'Printf', 'Queue', 'Random', 'Scanf',
+            'Set', 'Sort', 'Stack', 'StdLabels', 'Str', 'Stream', 'String', 'StringLabels', 'Sys', 'Thread',
+            'ThreadUnix', 'Tk'
+            ),
+        /* just link to the Pervasives functions library, cause it's the default opened library when starting OCaml */
+        3 => array(
+            'abs', 'abs_float', 'acos', 'asin', 'at_exit', 'atan', 'atan2',
+            'bool_of_string', 'ceil', 'char_of_int', 'classify_float',
+            'close_in', 'close_in_noerr', 'close_out', 'close_out_noerr',
+            'compare', 'cos', 'cosh', 'decr', 'epsilon_float', 'exit', 'exp',
+            'float', 'float_of_int', 'float_of_string', 'floor', 'flush',
+            'flush_all', 'format_of_string', 'frexp', 'fst', 'ignore',
+            'in_channel_length', 'infinity', 'input', 'input_binary_int',
+            'input_byte', 'input_char', 'input_line', 'input_value',
+            'int_of_char', 'int_of_float', 'int_of_string', 'invalid_arg',
+            'ldexp', 'log', 'log10', 'max', 'max_float', 'max_int', 'min',
+            'min_float', 'min_int', 'mod_float', 'modf', 'nan', 'open_in',
+            'open_in_bin', 'open_in_gen', 'open_out', 'open_out_bin',
+            'open_out_gen', 'out_channel_length', 'output', 'output_binary_int',
+            'output_byte', 'output_char', 'output_string', 'output_value',
+            'pos_in', 'pos_out',  'pred', 'prerr_char', 'prerr_endline',
+            'prerr_float', 'prerr_int', 'prerr_newline', 'prerr_string',
+            'print_char', 'print_endline', 'print_float', 'print_int',
+            'print_newline', 'print_string', 'read_float', 'read_int',
+            'read_line', 'really_input', 'seek_in', 'seek_out',
+            'set_binary_mode_in', 'set_binary_mode_out', 'sin', 'sinh', 'snd',
+            'sqrt', 'string_of_bool', 'string_of_float', 'string_of_format',
+            'string_of_int', 'succ', 'tan', 'tanh', 'truncate'
+            ),
+        /* here Pervasives Types */
+        4 => array (
+            'fpclass', 'in_channel', 'out_channel', 'open_flag', 'Sys_error', 'format'
+            ),
+        /* finally Pervasives Exceptions */
+        5 => array (
+            'Exit', 'Invalid_Argument', 'Failure', 'Division_by_zero'
+            )
+        ),
+    /* highlighting symbols is really important in OCaml */
+    'SYMBOLS' => array(
+        ';', '!', ':', '.', '=', '%', '^', '*', '-', '/', '+',
+        '>', '<', '(', ')', '[', ']', '&', '|', '#', "'"
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => true, /* functions name are case sensitive */
+        3 => true, /* types name too */
+        4 => true, /* pervasives types */
+        5 => true  /* pervasives exceptions */
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #06c; font-weight: bold;', /* nice blue */
+            2 => 'color: #06c; font-weight: bold;', /* nice blue */
+            3 => 'color: #06c; font-weight: bold;', /* nice blue */
+            4 => 'color: #06c; font-weight: bold;', /* nice blue */
+            5 => 'color: #06c; font-weight: bold;' /* nice blue */
+            ),
+        'COMMENTS' => array(
+            'MULTI' => 'color: #5d478b; font-style: italic;' /* light purple */
+            ),
+        'ESCAPE_CHAR' => array(
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #6c6;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #3cb371;' /* nice green */
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #c6c;' /* pink */
+            ),
+        'METHODS' => array(
+            1 => 'color: #060;' /* dark green */
+            ),
+        'REGEXPS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #a52a2a;' /* maroon */
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        /* some of keywords are Pervasives functions (land, lxor, asr, ...) */
+        1 => '',
+        /* link to the wanted library */
+        2 => 'http://caml.inria.fr/pub/docs/manual-ocaml/libref/{FNAME}.html',
+        /* link to Pervasives functions */
+        3 => 'http://caml.inria.fr/pub/docs/manual-ocaml/libref/Pervasives.html#VAL{FNAME}',
+        /* link to Pervasives type */
+        4 => 'http://caml.inria.fr/pub/docs/manual-ocaml/libref/Pervasives.html#TYPE{FNAME}',
+        /* link to Pervasives exceptions */
+        5 => 'http://caml.inria.fr/pub/docs/manual-ocaml/libref/Pervasives.html#EXCEPTION{FNAME}'
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/oobas.php b/examples/includes/geshi/geshi/oobas.php
new file mode 100644 (file)
index 0000000..5ca65cd
--- /dev/null
@@ -0,0 +1,135 @@
+<?php
+/*************************************************************************************
+ * oobas.php
+ * ---------
+ * Author: Roberto Rossi (rsoftware@altervista.org)
+ * Copyright: (c) 2004 Roberto Rossi (http://rsoftware.altervista.org), Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/08/30
+ *
+ * OpenOffice.org Basic language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *  -  Added description of extra language features (SF#1970248)
+ * 2004/11/27 (1.0.1)
+ *  -  Added support for multiple object splitters
+ * 2004/10/27 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'OpenOffice.org Basic',
+    'COMMENT_SINGLE' => array(1 => "'"),
+    'COMMENT_MULTI' => array(),
+    //Single-Line comments using REM keyword
+    'COMMENT_REGEXP' => array(2 => '/\bREM.*?$/i'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            'dim','private','public','global','as','if','redim','true','set','byval',
+            'false','bool','double','integer','long','object','single','variant',
+            'msgbox','print','inputbox','green','blue','red','qbcolor',
+            'rgb','open','close','reset','freefile','get','input','line',
+            'put','write','loc','seek','eof','lof','chdir','chdrive',
+            'curdir','dir','fileattr','filecopy','filedatetime','fileexists',
+            'filelen','getattr','kill','mkdir','name','rmdir','setattr',
+            'dateserial','datevalue','day','month','weekday','year','cdatetoiso',
+            'cdatefromiso','hour','minute','second','timeserial','timevalue',
+            'date','now','time','timer','erl','err','error','on','goto','resume',
+            'and','eqv','imp','not','or','xor','mod','atn','cos','sin','tan','log',
+            'exp','rnd','randomize','sqr','fix','int','abs','sgn','hex','oct',
+            'it','then','else','select','case','iif','do','loop','for','next','to',
+            'while','wend','gosub','return','call','choose','declare',
+            'end','exit','freelibrary','function','rem','stop','sub','switch','with',
+            'cbool','cdate','cdbl','cint','clng','const','csng','cstr','defbool',
+            'defdate','defdbl','defint','deflng','asc','chr','str','val','cbyte',
+            'space','string','format','lcase','left','lset','ltrim','mid','right',
+            'rset','rtrim','trim','ucase','split','join','converttourl','convertfromurl',
+            'instr','len','strcomp','beep','shell','wait','getsystemticks','environ',
+            'getsolarversion','getguitype','twipsperpixelx','twipsperpixely',
+            'createunostruct','createunoservice','getprocessservicemanager',
+            'createunodialog','createunolistener','createunovalue','thiscomponent',
+            'globalscope'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '='
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080;',
+            2 => 'color: #808080;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006600;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/oracle11.php b/examples/includes/geshi/geshi/oracle11.php
new file mode 100644 (file)
index 0000000..7d267b1
--- /dev/null
@@ -0,0 +1,614 @@
+<?php
+/*************************************************************************************
+ * oracle11.php
+ * -----------
+ * Author: Guy Wicks (Guy.Wicks@rbs.co.uk)
+ * Contributions:
+ * - Updated for 11i by Simon Redhead
+ * Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/06/04
+ *
+ * Oracle 11i language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/04/08 (1.0.8)
+ *  -  SR changes to oracle8.php to support Oracle 11i reserved words.
+ * 2005/01/29 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Oracle 11 SQL',
+    'COMMENT_SINGLE' => array(1 => '--'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_UPPER,
+    'QUOTEMARKS' => array("'", '"', '`'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+//Put your package names here - e.g. select distinct ''''|| lower(name) || ''',' from user_source;
+//        6 => array(
+//            ),
+
+//Put your table names here - e.g. select distinct ''''|| lower(table_name) || ''',' from user_tables;
+//        5 => array(
+//            ),
+
+//Put your view names here - e.g. select distinct ''''|| lower(view_name) || ''',' from user_views;
+//        4 => array(
+//            ),
+
+//Put your table field names here - e.g. select distinct ''''|| lower(column_name) || ''',' from user_tab_columns;
+//        3 => array(
+//            ),
+
+        //Put ORACLE reserved keywords here (11i).  I like mine uppercase.
+        1 => array(
+            'ABS',
+            'ACCESS',
+            'ACOS',
+            'ADD',
+            'ADD_MONTHS',
+            'ALL',
+            'ALTER',
+            'ANALYZE',
+            'AND',
+            'ANY',
+            'APPENDCHILDXML',
+            'ARRAY',
+            'AS',
+            'ASC',
+            'ASCII',
+            'ASCIISTR',
+            'ASIN',
+            'ASSOCIATE',
+            'AT',
+            'ATAN',
+            'ATAN2',
+            'AUDIT',
+            'AUTHID',
+            'AVG',
+            'BEGIN',
+            'BETWEEN',
+            'BFILENAME',
+            'BIN_TO_NUM',
+            'BINARY_INTEGER',
+            'BITAND',
+            'BODY',
+            'BOOLEAN',
+            'BULK',
+            'BY',
+            'CALL',
+            'CARDINALITY',
+            'CASCADE',
+            'CASE',
+            'CAST',
+            'CEIL',
+            'CHAR',
+            'CHAR_BASE',
+            'CHARTOROWID',
+            'CHECK',
+            'CHR',
+            'CLOSE',
+            'CLUSTER',
+            'CLUSTER_ID',
+            'CLUSTER_PROBABILITY',
+            'CLUSTER_SET',
+            'COALESCE',
+            'COLLECT',
+            'COLUMN',
+            'COMMENT',
+            'COMMIT',
+            'COMPOSE',
+            'COMPRESS',
+            'CONCAT',
+            'CONNECT',
+            'CONSTANT',
+            'CONSTRAINT',
+            'CONSTRAINTS',
+            'CONTEXT',
+            'CONTROLFILE',
+            'CONVERT',
+            'CORR',
+            'CORR_K',
+            'CORR_S',
+            'COS',
+            'COSH',
+            'COST',
+            'COUNT',
+            'COVAR_POP',
+            'COVAR_SAMP',
+            'CREATE',
+            'CUBE_TABLE',
+            'CUME_DIST',
+            'CURRENT',
+            'CURRENT_DATE',
+            'CURRENT_TIMESTAMP',
+            'CURRVAL',
+            'CURSOR',
+            'CV',
+            'DATABASE',
+            'DATAOBJ_TO_PARTITION',
+            'DATE',
+            'DAY',
+            'DBTIMEZONE',
+            'DECIMAL',
+            'DECLARE',
+            'DECODE',
+            'DECOMPOSE',
+            'DEFAULT',
+            'DELETE',
+            'DELETEXML',
+            'DENSE_RANK',
+            'DEPTH',
+            'DEREF',
+            'DESC',
+            'DIMENSION',
+            'DIRECTORY',
+            'DISASSOCIATE',
+            'DISTINCT',
+            'DO',
+            'DROP',
+            'DUMP',
+            'ELSE',
+            'ELSIF',
+            'EMPTY_BLOB',
+            'EMPTY_CLOB',
+            'END',
+            'EXCEPTION',
+            'EXCLUSIVE',
+            'EXEC',
+            'EXECUTE',
+            'EXISTS',
+            'EXISTSNODE',
+            'EXIT',
+            'EXP',
+            'EXPLAIN',
+            'EXTENDS',
+            'EXTRACT',
+            'EXTRACTVALUE',
+            'FALSE',
+            'FEATURE_ID',
+            'FEATURE_SET',
+            'FEATURE_VALUE',
+            'FETCH',
+            'FILE',
+            'FIRST',
+            'FIRST_VALUE',
+            'FLOAT',
+            'FLOOR',
+            'FOR',
+            'FORALL',
+            'FROM',
+            'FROM_TZ',
+            'FUNCTION',
+            'GOTO',
+            'GRANT',
+            'GREATEST',
+            'GROUP',
+            'GROUP_ID',
+            'GROUPING',
+            'GROUPING_ID',
+            'HAVING',
+            'HEAP',
+            'HEXTORAW',
+            'HOUR',
+            'IDENTIFIED',
+            'IF',
+            'IMMEDIATE',
+            'IN',
+            'INCREMENT',
+            'INDEX',
+            'INDEXTYPE',
+            'INDICATOR',
+            'INITCAP',
+            'INITIAL',
+            'INSERT',
+            'INSERTCHILDXML',
+            'INSERTXMLBEFORE',
+            'INSTR',
+            'INSTRB',
+            'INTEGER',
+            'INTERFACE',
+            'INTERSECT',
+            'INTERVAL',
+            'INTO',
+            'IS',
+            'ISOLATION',
+            'ITERATION_NUMBER',
+            'JAVA',
+            'KEY',
+            'LAG',
+            'LAST',
+            'LAST_DAY',
+            'LAST_VALUE',
+            'LEAD',
+            'LEAST',
+            'LENGTH',
+            'LENGTHB',
+            'LEVEL',
+            'LIBRARY',
+            'LIKE',
+            'LIMITED',
+            'LINK',
+            'LN',
+            'LNNVL',
+            'LOCALTIMESTAMP',
+            'LOCK',
+            'LOG',
+            'LONG',
+            'LOOP',
+            'LOWER',
+            'LPAD',
+            'LTRIM',
+            'MAKE_REF',
+            'MATERIALIZED',
+            'MAX',
+            'MAXEXTENTS',
+            'MEDIAN',
+            'MIN',
+            'MINUS',
+            'MINUTE',
+            'MLSLABEL',
+            'MOD',
+            'MODE',
+            'MODIFY',
+            'MONTH',
+            'MONTHS_BETWEEN',
+            'NANVL',
+            'NATURAL',
+            'NATURALN',
+            'NCHR',
+            'NEW',
+            'NEW_TIME',
+            'NEXT_DAY',
+            'NEXTVAL',
+            'NLS_CHARSET_DECL_LEN',
+            'NLS_CHARSET_ID',
+            'NLS_CHARSET_NAME',
+            'NLS_INITCAP',
+            'NLS_LOWER',
+            'NLS_UPPER',
+            'NLSSORT',
+            'NOAUDIT',
+            'NOCOMPRESS',
+            'NOCOPY',
+            'NOT',
+            'NOWAIT',
+            'NTILE',
+            'NULL',
+            'NULLIF',
+            'NUMBER',
+            'NUMBER_BASE',
+            'NUMTODSINTERVAL',
+            'NUMTOYMINTERVAL',
+            'NVL',
+            'NVL2',
+            'OCIROWID',
+            'OF',
+            'OFFLINE',
+            'ON',
+            'ONLINE',
+            'OPAQUE',
+            'OPEN',
+            'OPERATOR',
+            'OPTION',
+            'OR',
+            'ORA_HASH',
+            'ORDER',
+            'ORGANIZATION',
+            'OTHERS',
+            'OUT',
+            'OUTLINE',
+            'PACKAGE',
+            'PARTITION',
+            'PATH',
+            'PCTFREE',
+            'PERCENT_RANK',
+            'PERCENTILE_CONT',
+            'PERCENTILE_DISC',
+            'PLAN',
+            'PLS_INTEGER',
+            'POSITIVE',
+            'POSITIVEN',
+            'POWER',
+            'POWERMULTISET',
+            'POWERMULTISET_BY_CARDINALITY',
+            'PRAGMA',
+            'PREDICTION',
+            'PREDICTION_BOUNDS',
+            'PREDICTION_COST',
+            'PREDICTION_DETAILS',
+            'PREDICTION_PROBABILITY',
+            'PREDICTION_SET',
+            'PRESENTNNV',
+            'PRESENTV',
+            'PREVIOUS',
+            'PRIMARY',
+            'PRIOR',
+            'PRIVATE',
+            'PRIVILEGES',
+            'PROCEDURE',
+            'PROFILE',
+            'PUBLIC',
+            'RAISE',
+            'RANGE',
+            'RANK',
+            'RATIO_TO_REPORT',
+            'RAW',
+            'RAWTOHEX',
+            'RAWTONHEX',
+            'REAL',
+            'RECORD',
+            'REF',
+            'REFTOHEX',
+            'REGEXP_COUNT',
+            'REGEXP_INSTR',
+            'REGEXP_REPLACE',
+            'REGEXP_SUBSTR',
+            'REGR_AVGX',
+            'REGR_AVGY',
+            'REGR_COUNT',
+            'REGR_INTERCEPT',
+            'REGR_R2',
+            'REGR_SLOPE',
+            'REGR_SXX',
+            'REGR_SXY',
+            'REGR_SYY',
+            'RELEASE',
+            'REMAINDER',
+            'RENAME',
+            'REPLACE',
+            'RESOURCE',
+            'RETURN',
+            'RETURNING',
+            'REVERSE',
+            'REVOKE',
+            'ROLE',
+            'ROLLBACK',
+            'ROUND',
+            'ROW',
+            'ROW_NUMBER',
+            'ROWID',
+            'ROWIDTOCHAR',
+            'ROWIDTONCHAR',
+            'ROWNUM',
+            'ROWS',
+            'ROWTYPE',
+            'RPAD',
+            'RTRIM',
+            'SAVEPOINT',
+            'SCHEMA',
+            'SCN_TO_TIMESTAMP',
+            'SECOND',
+            'SEGMENT',
+            'SELECT',
+            'SEPERATE',
+            'SEQUENCE',
+            'SESSION',
+            'SESSIONTIMEZONE',
+            'SET',
+            'SHARE',
+            'SIGN',
+            'SIN',
+            'SINH',
+            'SIZE',
+            'SMALLINT',
+            'SOUNDEX',
+            'SPACE',
+            'SQL',
+            'SQLCODE',
+            'SQLERRM',
+            'SQRT',
+            'START',
+            'STATISTICS',
+            'STATS_BINOMIAL_TEST',
+            'STATS_CROSSTAB',
+            'STATS_F_TEST',
+            'STATS_KS_TEST',
+            'STATS_MODE',
+            'STATS_MW_TEST',
+            'STATS_ONE_WAY_ANOVA',
+            'STATS_T_TEST_INDEP',
+            'STATS_T_TEST_INDEPU',
+            'STATS_T_TEST_ONE',
+            'STATS_T_TEST_PAIRED',
+            'STATS_WSR_TEST',
+            'STDDEV',
+            'STDDEV_POP',
+            'STDDEV_SAMP',
+            'STOP',
+            'SUBSTR',
+            'SUBSTRB',
+            'SUBTYPE',
+            'SUCCESSFUL',
+            'SUM',
+            'SYNONYM',
+            'SYS_CONNECT_BY_PATH',
+            'SYS_CONTEXT',
+            'SYS_DBURIGEN',
+            'SYS_EXTRACT_UTC',
+            'SYS_GUID',
+            'SYS_TYPEID',
+            'SYS_XMLAGG',
+            'SYS_XMLGEN',
+            'SYSDATE',
+            'SYSTEM',
+            'SYSTIMESTAMP',
+            'TABLE',
+            'TABLESPACE',
+            'TAN',
+            'TANH',
+            'TEMPORARY',
+            'THEN',
+            'TIME',
+            'TIMESTAMP',
+            'TIMESTAMP_TO_SCN',
+            'TIMEZONE_ABBR',
+            'TIMEZONE_HOUR',
+            'TIMEZONE_MINUTE',
+            'TIMEZONE_REGION',
+            'TIMING',
+            'TO',
+            'TO_BINARY_DOUBLE',
+            'TO_BINARY_FLOAT',
+            'TO_CHAR',
+            'TO_CLOB',
+            'TO_DATE',
+            'TO_DSINTERVAL',
+            'TO_LOB',
+            'TO_MULTI_BYTE',
+            'TO_NCHAR',
+            'TO_NCLOB',
+            'TO_NUMBER',
+            'TO_SINGLE_BYTE',
+            'TO_TIMESTAMP',
+            'TO_TIMESTAMP_TZ',
+            'TO_YMINTERVAL',
+            'TRANSACTION',
+            'TRANSLATE',
+            'TREAT',
+            'TRIGGER',
+            'TRIM',
+            'TRUE',
+            'TRUNC',
+            'TRUNCATE',
+            'TYPE',
+            'TZ_OFFSET',
+            'UI',
+            'UID',
+            'UNION',
+            'UNIQUE',
+            'UNISTR',
+            'UPDATE',
+            'UPDATEXML',
+            'UPPER',
+            'USE',
+            'USER',
+            'USERENV',
+            'USING',
+            'VALIDATE',
+            'VALUE',
+            'VALUES',
+            'VAR_POP',
+            'VAR_SAMP',
+            'VARCHAR',
+            'VARCHAR2',
+            'VARIANCE',
+            'VIEW',
+            'VSIZE',
+            'WHEN',
+            'WHENEVER',
+            'WHERE',
+            'WHILE',
+            'WIDTH_BUCKET',
+            'WITH',
+            'WORK',
+            'WRITE',
+            'XMLAGG',
+            'XMLCAST',
+            'XMLCDATA',
+            'XMLCOLATTVAL',
+            'XMLCOMMENT',
+            'XMLCONCAT',
+            'XMLDIFF',
+            'XMLELEMENT',
+            'XMLEXISTS',
+            'XMLFOREST',
+            'XMLPARSE',
+            'XMLPATCH',
+            'XMLPI',
+            'XMLQUERY',
+            'XMLROOT',
+            'XMLSEQUENCE',
+            'XMLSERIALIZE',
+            'XMLTABLE',
+            'XMLTRANSFORM',
+            'YEAR',
+            'ZONE'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '=', '<', '>', '|', '+', '-', '*', '/', ','
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+//        3 => false,
+//        4 => false,
+//        5 => false,
+//        6 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #993333; font-weight: bold; text-transform: uppercase;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #ff0000;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+//        3 => '',
+//        4 => '',
+//        5 => '',
+//        6 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/oracle8.php b/examples/includes/geshi/geshi/oracle8.php
new file mode 100644 (file)
index 0000000..d54b1e3
--- /dev/null
@@ -0,0 +1,496 @@
+<?php
+/*************************************************************************************
+ * oracle8.php
+ * -----------
+ * Author: Guy Wicks (Guy.Wicks@rbs.co.uk)
+ * Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/06/04
+ *
+ * Oracle 8 language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2005/01/29 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Oracle 8 SQL',
+    'COMMENT_SINGLE' => array(1 => '--'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_UPPER,
+    'QUOTEMARKS' => array("'", '"', '`'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+//Put your package names here - e.g. select distinct ''''|| lower(name) || ''',' from user_source;
+//        6 => array(
+//            ),
+
+//Put your table names here - e.g. select distinct ''''|| lower(table_name) || ''',' from user_tables;
+//        5 => array(
+//            ),
+
+//Put your view names here - e.g. select distinct ''''|| lower(view_name) || ''',' from user_views;
+//        4 => array(
+//            ),
+
+//Put your table field names here - e.g. select distinct ''''|| lower(column_name) || ''',' from user_tab_columns;
+//        3 => array(
+//            ),
+
+//Put ORACLE reserved keywords here (8.1.7).  I like mine uppercase.
+        1 => array(
+            'ABS',
+            'ACCESS',
+            'ACOS',
+            'ADD',
+            'ADD_MONTHS',
+            'ALL',
+            'ALTER',
+            'ANALYZE',
+            'AND',
+            'ANY',
+            'ARRAY',
+            'AS',
+            'ASC',
+            'ASCII',
+            'ASIN',
+            'ASSOCIATE',
+            'AT',
+            'ATAN',
+            'ATAN2',
+            'AUDIT',
+            'AUTHID',
+            'AVG',
+            'BEGIN',
+            'BETWEEN',
+            'BFILENAME',
+            'BINARY_INTEGER',
+            'BITAND',
+            'BODY',
+            'BOOLEAN',
+            'BULK',
+            'BY',
+            'CALL',
+            'CASCADE',
+            'CASE',
+            'CEIL',
+            'CHAR',
+            'CHAR_BASE',
+            'CHARTOROWID',
+            'CHECK',
+            'CHR',
+            'CLOSE',
+            'CLUSTER',
+            'COALESCE',
+            'COLLECT',
+            'COLUMN',
+            'COMMENT',
+            'COMMIT',
+            'COMPRESS',
+            'CONCAT',
+            'CONNECT',
+            'CONSTANT',
+            'CONSTRAINT',
+            'CONSTRAINTS',
+            'CONTEXT',
+            'CONTROLFILE',
+            'CONVERT',
+            'CORR',
+            'COS',
+            'COSH',
+            'COST',
+            'COUNT',
+            'COVAR_POP',
+            'COVAR_SAMP',
+            'CREATE',
+            'CUME_DIST',
+            'CURRENT',
+            'CURRVAL',
+            'CURSOR',
+            'DATABASE',
+            'DATE',
+            'DAY',
+            'DECIMAL',
+            'DECLARE',
+            'DECODE',
+            'DEFAULT',
+            'DELETE',
+            'DENSE_RANK',
+            'DEREF',
+            'DESC',
+            'DIMENSION',
+            'DIRECTORY',
+            'DISASSOCIATE',
+            'DISTINCT',
+            'DO',
+            'DROP',
+            'DUMP',
+            'ELSE',
+            'ELSIF',
+            'EMPTY_BLOB',
+            'EMPTY_CLOB',
+            'END',
+            'EXCEPTION',
+            'EXCLUSIVE',
+            'EXEC',
+            'EXECUTE',
+            'EXISTS',
+            'EXIT',
+            'EXP',
+            'EXPLAIN',
+            'EXTENDS',
+            'EXTRACT',
+            'FALSE',
+            'FETCH',
+            'FILE',
+            'FIRST_VALUE',
+            'FLOAT',
+            'FLOOR',
+            'FOR',
+            'FORALL',
+            'FROM',
+            'FUNCTION',
+            'GOTO',
+            'GRANT',
+            'GREATEST',
+            'GROUP',
+            'GROUPING',
+            'HAVING',
+            'HEAP',
+            'HEXTORAW',
+            'HOUR',
+            'IDENTIFIED',
+            'IF',
+            'IMMEDIATE',
+            'IN',
+            'INCREMENT',
+            'INDEX',
+            'INDEXTYPE',
+            'INDICATOR',
+            'INITCAP',
+            'INITIAL',
+            'INSERT',
+            'INSTR',
+            'INSTRB',
+            'INTEGER',
+            'INTERFACE',
+            'INTERSECT',
+            'INTERVAL',
+            'INTO',
+            'IS',
+            'ISOLATION',
+            'JAVA',
+            'KEY',
+            'LAG',
+            'LAST_DAY',
+            'LAST_VALUE',
+            'LEAD',
+            'LEAST',
+            'LENGTH',
+            'LENGTHB',
+            'LEVEL',
+            'LIBRARY',
+            'LIKE',
+            'LIMITED',
+            'LINK',
+            'LN',
+            'LOCK',
+            'LOG',
+            'LONG',
+            'LOOP',
+            'LOWER',
+            'LPAD',
+            'LTRIM',
+            'MAKE_REF',
+            'MATERIALIZED',
+            'MAX',
+            'MAXEXTENTS',
+            'MIN',
+            'MINUS',
+            'MINUTE',
+            'MLSLABEL',
+            'MOD',
+            'MODE',
+            'MODIFY',
+            'MONTH',
+            'MONTHS_BETWEEN',
+            'NATURAL',
+            'NATURALN',
+            'NEW',
+            'NEW_TIME',
+            'NEXT_DAY',
+            'NEXTVAL',
+            'NLS_CHARSET_DECL_LEN',
+            'NLS_CHARSET_ID',
+            'NLS_CHARSET_NAME',
+            'NLS_INITCAP',
+            'NLS_LOWER',
+            'NLS_UPPER',
+            'NLSSORT',
+            'NOAUDIT',
+            'NOCOMPRESS',
+            'NOCOPY',
+            'NOT',
+            'NOWAIT',
+            'NTILE',
+            'NULL',
+            'NULLIF',
+            'NUMBER',
+            'NUMBER_BASE',
+            'NUMTODSINTERVAL',
+            'NUMTOYMINTERVAL',
+            'NVL',
+            'NVL2',
+            'OCIROWID',
+            'OF',
+            'OFFLINE',
+            'ON',
+            'ONLINE',
+            'OPAQUE',
+            'OPEN',
+            'OPERATOR',
+            'OPTION',
+            'OR',
+            'ORDER',
+            'ORGANIZATION',
+            'OTHERS',
+            'OUT',
+            'OUTLINE',
+            'PACKAGE',
+            'PARTITION',
+            'PCTFREE',
+            'PERCENT_RANK',
+            'PLAN',
+            'PLS_INTEGER',
+            'POSITIVE',
+            'POSITIVEN',
+            'POWER',
+            'PRAGMA',
+            'PRIMARY',
+            'PRIOR',
+            'PRIVATE',
+            'PRIVILEGES',
+            'PROCEDURE',
+            'PROFILE',
+            'PUBLIC',
+            'RAISE',
+            'RANGE',
+            'RANK',
+            'RATIO_TO_REPORT',
+            'RAW',
+            'RAWTOHEX',
+            'REAL',
+            'RECORD',
+            'REF',
+            'REFTOHEX',
+            'REGR_AVGX',
+            'REGR_AVGY',
+            'REGR_COUNT',
+            'REGR_INTERCEPT',
+            'REGR_R2',
+            'REGR_SLOPE',
+            'REGR_SXX',
+            'REGR_SXY',
+            'REGR_SYY',
+            'RELEASE',
+            'RENAME',
+            'REPLACE',
+            'RESOURCE',
+            'RETURN',
+            'RETURNING',
+            'REVERSE',
+            'REVOKE',
+            'ROLE',
+            'ROLLBACK',
+            'ROUND',
+            'ROW',
+            'ROW_NUMBER',
+            'ROWID',
+            'ROWIDTOCHAR',
+            'ROWNUM',
+            'ROWS',
+            'ROWTYPE',
+            'RPAD',
+            'RTRIM',
+            'SAVEPOINT',
+            'SCHEMA',
+            'SECOND',
+            'SEGMENT',
+            'SELECT',
+            'SEPERATE',
+            'SEQUENCE',
+            'SESSION',
+            'SET',
+            'SHARE',
+            'SIGN',
+            'SIN',
+            'SINH',
+            'SIZE',
+            'SMALLINT',
+            'SOUNDEX',
+            'SPACE',
+            'SQL',
+            'SQLCODE',
+            'SQLERRM',
+            'SQRT',
+            'START',
+            'STATISTICS',
+            'STDDEV',
+            'STDDEV_POP',
+            'STDDEV_SAMP',
+            'STOP',
+            'SUBSTR',
+            'SUBSTRB',
+            'SUBTYPE',
+            'SUCCESSFUL',
+            'SUM',
+            'SYNONYM',
+            'SYS_CONTEXT',
+            'SYS_GUID',
+            'SYSDATE',
+            'SYSTEM',
+            'TABLE',
+            'TABLESPACE',
+            'TAN',
+            'TANH',
+            'TEMPORARY',
+            'THEN',
+            'TIME',
+            'TIMESTAMP',
+            'TIMEZONE_ABBR',
+            'TIMEZONE_HOUR',
+            'TIMEZONE_MINUTE',
+            'TIMEZONE_REGION',
+            'TIMING',
+            'TO',
+            'TO_CHAR',
+            'TO_DATE',
+            'TO_LOB',
+            'TO_MULTI_BYTE',
+            'TO_NUMBER',
+            'TO_SINGLE_BYTE',
+            'TRANSACTION',
+            'TRANSLATE',
+            'TRIGGER',
+            'TRIM',
+            'TRUE',
+            'TRUNC',
+            'TRUNCATE',
+            'TYPE',
+            'UI',
+            'UID',
+            'UNION',
+            'UNIQUE',
+            'UPDATE',
+            'UPPER',
+            'USE',
+            'USER',
+            'USERENV',
+            'USING',
+            'VALIDATE',
+            'VALUE',
+            'VALUES',
+            'VAR_POP',
+            'VAR_SAMP',
+            'VARCHAR',
+            'VARCHAR2',
+            'VARIANCE',
+            'VIEW',
+            'VSIZE',
+            'WHEN',
+            'WHENEVER',
+            'WHERE',
+            'WHILE',
+            'WITH',
+            'WORK',
+            'WRITE',
+            'YEAR',
+            'ZONE'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '=', '<', '>', '|', '+', '-', '*', '/', ','
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+//        3 => false,
+//        4 => false,
+//        5 => false,
+//        6 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #993333; font-weight: bold; text-transform: uppercase;'
+//Add the styles for groups 3-6 here when used
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #ff0000;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+//        3 => '',
+//        4 => '',
+//        5 => '',
+//        6 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/pascal.php b/examples/includes/geshi/geshi/pascal.php
new file mode 100644 (file)
index 0000000..d2acd0f
--- /dev/null
@@ -0,0 +1,152 @@
+<?php
+/*************************************************************************************
+ * pascal.php
+ * ----------
+ * Author: Tux (tux@inamil.cz)
+ * Copyright: (c) 2004 Tux (http://tux.a4.cz/), Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/07/26
+ *
+ * Pascal language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *   -  Added description of extra language features (SF#1970248)
+ * 2004/11/27 (1.0.2)
+ *  -  Added support for multiple object splitters
+ * 2004/10/27 (1.0.1)
+ *   -  Added support for URLs
+ * 2004/08/05 (1.0.0)
+ *   -  Added support for symbols
+ * 2004/07/27 (0.9.1)
+ *   -  Pascal is OO language. Some new words.
+ * 2004/07/26 (0.9.0)
+ *   -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Pascal',
+    'COMMENT_SINGLE' => array(1 => '//'),
+    'COMMENT_MULTI' => array('{' => '}','(*' => '*)'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'HARDQUOTE' => array("'", "'"),
+    'HARDESCAPE' => array("''"),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'absolute','asm','assembler','begin','break','case','catch','cdecl',
+            'const','constructor','default','destructor','div','do','downto',
+            'else','end','except','export','exports','external','far',
+            'finalization','finally','for','forward','function','goto','if',
+            'implementation','in','index','inherited','initialization','inline',
+            'interface','interrupt','label','library','mod','name','not','of',
+            'or','overload','override','private','procedure','program',
+            'property','protected','public','published','raise','repeat',
+            'resourcestring','shl','shr','stdcall','stored','switch','then',
+            'to','try','type','unit','until','uses','var','while','xor'
+            ),
+        2 => array(
+            'nil', 'false', 'true',
+            ),
+        3 => array(
+            'abs','and','arc','arctan','blockread','blockwrite','chr','dispose',
+            'cos','eof','eoln','exp','get','ln','new','odd','ord','ordinal',
+            'pred','read','readln','sin','sqrt','succ','write','writeln'
+            ),
+        4 => array(
+            'ansistring','array','boolean','byte','bytebool','char','file',
+            'integer','longbool','longint','object','packed','pointer','real',
+            'record','set','shortint','smallint','string','union','word'
+            ),
+        ),
+    'SYMBOLS' => array(
+        ',', ':', '=', '+', '-', '*', '/'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000000; font-weight: bold;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #000066;',
+            4 => 'color: #000066; font-weight: bold;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #666666; font-style: italic;',
+            'MULTI' => 'color: #666666; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;',
+            'HARD' => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #009900;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;',
+            'HARD' => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #0066ee;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #339933;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/per.php b/examples/includes/geshi/geshi/per.php
new file mode 100644 (file)
index 0000000..092aae0
--- /dev/null
@@ -0,0 +1,302 @@
+<?php
+/*************************************************************************************
+ * per.php
+ * --------
+ * Author: Lars Gersmann (lars.gersmann@gmail.com)
+ * Copyright: (c) 2007 Lars Gersmann
+ * Release Version: 1.0.8.3
+ * Date Started: 2007/06/03
+ *
+ * Per (forms) (FOURJ's Genero 4GL) language file for GeSHi.
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'per',
+    'COMMENT_SINGLE' => array(1 => '--', 2 => '#'),
+    'COMMENT_MULTI' => array('{' => '}'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            "ACCELERATOR",
+            "ACCELERATOR2",
+            "ACTION",
+            "ALT",
+            "AND",
+            "AUTO",
+            "AUTONEXT",
+            "AUTOSCALE",
+            "BETWEEN",
+            "BOTH",
+            "BUTTON",
+            "BUTTONEDIT",
+            "BUTTONTEXTHIDDEN",
+            "BY",
+            "BYTE",
+            "CANVAS",
+            "CENTER",
+            "CHECKBOX",
+            "CLASS",
+            "COLOR",
+            "COLUMNS",
+            "COMBOBOX",
+            "COMMAND",
+            "COMMENT",
+            "COMMENTS",
+            "COMPACT",
+            "COMPRESS",
+            "CONFIG",
+            "CONTROL",
+            "CURRENT",
+            "DATABASE",
+            "DATEEDIT",
+            "DEC",
+            "DEFAULT",
+            "DEFAULTS",
+            "DELIMITERS",
+            "DISPLAY",
+            "DISPLAYONLY",
+            "DOWNSHIFT",
+            "DYNAMIC",
+            "EDIT",
+            "FIXED",
+            "FOLDER",
+            "FONTPITCH",
+            "FORMAT",
+            "FORMONLY",
+            "GRID",
+            "GRIDCHILDRENINPARENT",
+            "GROUP",
+            "HBOX",
+            "HEIGHT",
+            "HIDDEN",
+            "HORIZONTAL",
+            "INCLUDE",
+            "INITIAL",
+            "INITIALIZER",
+            "INPUT",
+            "INSTRUCTIONS",
+            "INTERVAL",
+            "INVISIBLE",
+            "IS",
+            "ITEM",
+            "ITEMS",
+            "JUSTIFY",
+            "KEY",
+            "KEYS",
+            "LABEL",
+            "LEFT",
+            "LIKE",
+            "LINES",
+            "MATCHES",
+            "NAME",
+            "NOENTRY",
+            "NONCOMPRESS",
+            "NORMAL",
+            "NOT",
+            "NOUPDATE",
+            "OPTIONS",
+            "OR",
+            "ORIENTATION",
+            "PACKED",
+            "PAGE",
+            "PICTURE",
+            "PIXELHEIGHT",
+            "PIXELS",
+            "PIXELWIDTH",
+            "POINTS",
+            "PROGRAM",
+            "PROGRESSBAR",
+            "QUERYCLEAR",
+            "QUERYEDITABLE",
+            "RADIOGROUP",
+            "RECORD",
+            "REQUIRED",
+            "REVERSE",
+            "RIGHT",
+            "SAMPLE",
+            "SCREEN",
+            "SCROLL",
+            "SCROLLBARS",
+            "SCROLLGRID",
+            "SECOND",
+            "SEPARATOR",
+            "SHIFT",
+            "SIZE",
+            "SIZEPOLICY",
+            "SMALLFLOAT",
+            "SMALLINT",
+            "SPACING",
+            "STRETCH",
+            "STYLE",
+            "TABINDEX",
+            "TABLE",
+            "TAG",
+            "TEXT",
+            "TEXTEDIT",
+            "THROUGH",
+            "THRU",
+            "TITLE",
+            "TO",
+            "TOOLBAR",
+            "TOPMENU",
+            "TYPE",
+            "UNHIDABLE",
+            "UNHIDABLECOLUMNS",
+            "UNMOVABLE",
+            "UNMOVABLECOLUMNS",
+            "UNSIZABLE",
+            "UNSIZABLECOLUMNS",
+            "UNSORTABLE",
+            "UNSORTABLECOLUMNS",
+            "UPSHIFT",
+            "USER",
+            "VALIDATE",
+            "VALUECHECKED",
+            "VALUEMAX",
+            "VALUEMIN",
+            "VALUEUNCHECKED",
+            "VARCHAR",
+            "VARIABLE",
+            "VBOX",
+            "VERIFY",
+            "VERSION",
+            "VERTICAL",
+            "TIMESTAMP",
+            "WANTCOLUMNSANCHORED", /* to be removed! */
+            "WANTFIXEDPAGESIZE",
+            "WANTNORETURNS",
+            "WANTTABS",
+            "WHERE",
+            "WIDGET",
+            "WIDTH",
+            "WINDOWSTYLE",
+            "WITHOUT",
+            "WORDWRAP",
+            "X",
+            "Y",
+            "ZEROFILL",
+            "SCHEMA",
+            "ATTRIBUTES",
+            "TABLES",
+            "LAYOUT",
+            "END"
+            ),
+        2 => array(
+            "YEAR",
+            "BLACK",
+            "BLINK",
+            "BLUE",
+            "YELLOW",
+            "WHITE",
+            "UNDERLINE",
+            "CENTURY",
+            "FRACTION",
+            "CHAR",
+            "CHARACTER",
+            "CHARACTERS",
+            "CYAN",
+            "DATE",
+            "DATETIME",
+            "DAY",
+            "DECIMAL",
+            "FALSE",
+            "FLOAT",
+            "GREEN",
+            "HOUR",
+            "INT",
+            "INTEGER",
+            "MAGENTA",
+            "MINUTE",
+            "MONEY",
+            "NONE",
+            "NULL",
+            "REAL",
+            "RED",
+            "TRUE",
+            "TODAY",
+            "MONTH",
+            "IMAGE"
+            ),
+        ),
+    'SYMBOLS' => array(
+        '+', '-', '*', '?', '=', '/', '%', '>', '<', '^', '!', '|', ':',
+        '(', ')', '[', ']'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0600FF;',
+            2 => 'color: #0000FF; font-weight: bold;',
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #008080; font-style: italic;',
+            2 => 'color: #008080;',
+            'MULTI' => 'color: green'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #008080; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000000;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #808080;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #FF0000;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #0000FF;',
+            2 => 'color: #0000FF;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #008000;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/perl.php b/examples/includes/geshi/geshi/perl.php
new file mode 100644 (file)
index 0000000..f8ac096
--- /dev/null
@@ -0,0 +1,213 @@
+<?php
+/*************************************************************************************
+ * perl.php
+ * --------
+ * Author: Andreas Gohr (andi@splitbrain.org), Ben Keen (ben.keen@gmail.com)
+ * Copyright: (c) 2004 Andreas Gohr, Ben Keen (http://www.benjaminkeen.org/), Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/08/20
+ *
+ * Perl language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/06/22 (1.0.8)
+ *   -  Added support for system calls in backticks (Corley Kinnane)
+ * 2008/05/23 (1.0.7.22)
+ *   -  Added description of extra language features (SF#1970248)
+ *   -  Added comment_regexp for predefined variables
+ * 2008/02/15 (1.003)
+ *   -  Fixed SF#1891630 with placebo patch
+ * 2006/01/05 (1.0.2)
+ *   -  Used hardescape feature for ' strings (Cliff Stanford)
+ * 2004/11/27 (1.0.1)
+ *   -  Added support for multiple object splitters
+ * 2004/08/20 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ * * LABEL:
+ * * string comparison operators
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Perl',
+    'COMMENT_SINGLE' => array(1 => '#'),
+    'COMMENT_MULTI' => array(
+        '=back' => '=cut',
+        '=head' => '=cut',
+        '=item' => '=cut',
+        '=over' => '=cut',
+        '=begin' => '=cut',
+        '=end' => '=cut',
+        '=for' => '=cut',
+        '=encoding' => '=cut',
+        '=pod' => '=cut'
+        ),
+    'COMMENT_REGEXP' => array(
+        //Regular expressions
+        2 => "/(?<=[\\s^])(s|tr|y)\\/(?:\\\\.|(?!\n)[^\\/\\\\])+\\/(?:\\\\.|(?!\n)[^\\/\\\\])*\\/[msixpogcde]*(?=[\\s$\\.\\;])|(?<=[\\s^(=])(m|q[qrwx]?)?\\/(?:\\\\.|(?!\n)[^\\/\\\\])+\\/[msixpogc]*(?=[\\s$\\.\\,\\;\\)])/iU",
+        //Regular expression match variables
+        3 => '/\$\d+/',
+        //Heredoc
+        4 => '/<<\s*?([\'"]?)([a-zA-Z0-9]+)\1;[^\n]*?\\n.*\\n\\2(?![a-zA-Z0-9])/siU',
+        //Predefined variables
+        5 => '/\$(\^[a-zA-Z]?|[\*\$`\'&_\.,+\-~:;\\\\\/"\|%=\?!@#<>\(\)\[\]])(?!\w)|@[_+\-]|%[!]|\$(?=\{)/',
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"','`'),
+    'HARDQUOTE' => array("'", "'"),            // An optional 2-element array defining the beginning and end of a hard-quoted string
+    'HARDESCAPE' => array('\\\'',),
+        // Things that must still be escaped inside a hard-quoted string
+        // If HARDQUOTE is defined, HARDESCAPE must be defined
+        // This will not work unless the first character of each element is either in the
+        // QUOTEMARKS array or is the ESCAPE_CHAR
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'case', 'do', 'else', 'elsif', 'for', 'if', 'then', 'until', 'while', 'foreach', 'my',
+            'xor', 'or', 'and', 'unless', 'next', 'last', 'redo', 'not', 'our',
+            'reset', 'continue', 'cmp', 'ne', 'eq', 'lt', 'gt', 'le', 'ge',
+            ),
+        2 => array(
+            'use', 'sub', 'new', '__END__', '__DATA__', '__DIE__', '__WARN__', 'BEGIN',
+            'STDIN', 'STDOUT', 'STDERR', 'ARGV', 'ARGVOUT'
+            ),
+        3 => array(
+            'abs', 'accept', 'alarm', 'atan2', 'bind', 'binmode', 'bless',
+            'caller', 'chdir', 'chmod', 'chomp', 'chop', 'chown', 'chr',
+            'chroot', 'close', 'closedir', 'connect', 'cos',
+            'crypt', 'dbmclose', 'dbmopen', 'defined', 'delete', 'die',
+            'dump', 'each', 'endgrent', 'endhostent', 'endnetent', 'endprotoent',
+            'endpwent', 'endservent', 'eof', 'eval', 'exec', 'exists', 'exit',
+            'exp', 'fcntl', 'fileno', 'flock', 'fork', 'format', 'formline',
+            'getc', 'getgrent', 'getgrgid', 'getgrnam', 'gethostbyaddr',
+            'gethostbyname', 'gethostent', 'getlogin', 'getnetbyaddr', 'getnetbyname',
+            'getnetent', 'getpeername', 'getpgrp', 'getppid', 'getpriority',
+            'getprotobyname', 'getprotobynumber', 'getprotoent', 'getpwent',
+            'getpwnam', 'getpwuid', 'getservbyname', 'getservbyport', 'getservent',
+            'getsockname', 'getsockopt', 'glob', 'gmtime', 'goto', 'grep',
+            'hex', 'import', 'index', 'int', 'ioctl', 'join', 'keys', 'kill',
+            'lc', 'lcfirst', 'length', 'link', 'listen', 'local',
+            'localtime', 'log', 'lstat', 'm', 'map', 'mkdir', 'msgctl', 'msgget',
+            'msgrcv', 'msgsnd', 'no', 'oct', 'open', 'opendir',
+            'ord', 'pack', 'package', 'pipe', 'pop', 'pos', 'print',
+            'printf', 'prototype', 'push', 'qq', 'qr', 'quotemeta', 'qw',
+            'qx', 'q', 'rand', 'read', 'readdir', 'readline', 'readlink', 'readpipe',
+            'recv', 'ref', 'rename', 'require', 'return',
+            'reverse', 'rewinddir', 'rindex', 'rmdir', 's', 'scalar', 'seek',
+            'seekdir', 'select', 'semctl', 'semget', 'semop', 'send', 'setgrent',
+            'sethostent', 'setnetent', 'setpgrp', 'setpriority', 'setprotoent',
+            'setpwent', 'setservent', 'setsockopt', 'shift', 'shmctl', 'shmget',
+            'shmread', 'shmwrite', 'shutdown', 'sin', 'sleep', 'socket', 'socketpair',
+            'sort', 'splice', 'split', 'sprintf', 'sqrt', 'srand', 'stat',
+            'study', 'substr', 'symlink', 'syscall', 'sysopen', 'sysread',
+            'sysseek', 'system', 'syswrite', 'tell', 'telldir', 'tie', 'tied',
+            'time', 'times', 'tr', 'truncate', 'uc', 'ucfirst', 'umask', 'undef',
+            'unlink', 'unpack', 'unshift', 'untie', 'utime', 'values',
+            'vec', 'wait', 'waitpid', 'wantarray', 'warn', 'write', 'y'
+            )
+        ),
+    'SYMBOLS' => array(
+        '<', '>', '=',
+        '!', '@', '~', '&', '|', '^',
+        '+','-', '*', '/', '%',
+        ',', ';', '?', '.', ':'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #000066;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #666666; font-style: italic;',
+            2 => 'color: #009966; font-style: italic;',
+            3 => 'color: #0000ff;',
+            4 => 'color: #cc0000; font-style: italic;',
+            5 => 'color: #0000ff;',
+            'MULTI' => 'color: #666666; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;',
+            'HARD' => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #009900;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;',
+            'HARD' => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006600;',
+            2 => 'color: #006600;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #339933;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #0000ff;',
+            4 => 'color: #009999;',
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => 'http://perldoc.perl.org/functions/{FNAMEL}.html'
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '-&gt;',
+        2 => '::'
+        ),
+    'REGEXPS' => array(
+        //Variable
+        0 => '(?:\$[\$#]?|\\\\(?:[@%*]?|\\\\*\$|&amp;)|%[$]?|@[$]?|\*[$]?|&amp;[$]?)[a-zA-Z_][a-zA-Z0-9_]*',
+        //File Descriptor
+        4 => '&lt;[a-zA-Z_][a-zA-Z0-9_]*&gt;',
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'PARSER_CONTROL' => array(
+        'COMMENTS' => array(
+            'DISALLOWED_BEFORE' => '$'
+        )
+    )
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/php-brief.php b/examples/includes/geshi/geshi/php-brief.php
new file mode 100644 (file)
index 0000000..dd6781d
--- /dev/null
@@ -0,0 +1,202 @@
+<?php
+/*************************************************************************************
+ * php-brief.php
+ * -------------
+ * Author: Nigel McNie (nigel@geshi.org)
+ * Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/06/02
+ *
+ * PHP (brief version) language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *  -  Added description of extra language features (SF#1970248)
+ * 2004/11/27 (1.0.3)
+ *  -  Added support for multiple object splitters
+ *  -  Fixed &new problem
+ * 2004/10/27 (1.0.2)
+ *   -  Added support for URLs
+ * 2004/08/05 (1.0.1)
+ *   -  Added support for symbols
+ * 2004/07/14 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2004/07/14)
+ * -------------------------
+ * * Remove more functions that are hardly used
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'PHP (brief)',
+    'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    //Heredoc and Nowdoc syntax
+    'COMMENT_REGEXP' => array(3 => '/<<<\s*?(\'?)([a-zA-Z0-9]+)\1[^\n]*?\\n.*\\n\\2(?![a-zA-Z0-9])/siU'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'HARDQUOTE' => array("'", "'"),
+    'HARDESCAPE' => array("\'"),
+    'NUMBERS' =>
+        GESHI_NUMBER_INT_BASIC |  GESHI_NUMBER_OCT_PREFIX | GESHI_NUMBER_HEX_PREFIX |
+        GESHI_NUMBER_FLT_SCI_ZERO,
+    'KEYWORDS' => array(
+        1 => array(
+            'include', 'require', 'include_once', 'require_once',
+            'for', 'as', 'foreach', 'if', 'elseif', 'else', 'while', 'do', 'endwhile', 'endif', 'switch', 'case', 'endswitch',
+            'return', 'break'
+            ),
+        2 => array(
+            'null', '__LINE__', '__FILE__',
+            'false', '&lt;?php',
+            'true', 'var', 'default',
+            'function', 'class', 'new', '&amp;new', 'public', 'private', 'interface', 'extends',
+            'const', 'self'
+            ),
+        3 => array(
+            'func_num_args', 'func_get_arg', 'func_get_args', 'strlen', 'strcmp', 'strncmp', 'strcasecmp', 'strncasecmp', 'each', 'error_reporting', 'define', 'defined',
+            'trigger_error', 'user_error', 'set_error_handler', 'restore_error_handler', 'get_declared_classes', 'get_loaded_extensions',
+            'extension_loaded', 'get_extension_funcs', 'debug_backtrace',
+            'constant', 'bin2hex', 'sleep', 'usleep', 'time', 'mktime', 'gmmktime', 'strftime', 'gmstrftime', 'strtotime', 'date', 'gmdate', 'getdate', 'localtime', 'checkdate', 'flush', 'wordwrap', 'htmlspecialchars', 'htmlentities', 'html_entity_decode', 'md5', 'md5_file', 'crc32', 'getimagesize', 'image_type_to_mime_type', 'phpinfo', 'phpversion', 'phpcredits', 'strnatcmp', 'strnatcasecmp', 'substr_count', 'strspn', 'strcspn', 'strtok', 'strtoupper', 'strtolower', 'strpos', 'strrpos', 'strrev', 'hebrev', 'hebrevc', 'nl2br', 'basename', 'dirname', 'pathinfo', 'stripslashes', 'stripcslashes', 'strstr', 'stristr', 'strrchr', 'str_shuffle', 'str_word_count', 'strcoll', 'substr', 'substr_replace', 'quotemeta', 'ucfirst', 'ucwords', 'strtr', 'addslashes', 'addcslashes', 'rtrim', 'str_replace', 'str_repeat', 'count_chars', 'chunk_split', 'trim', 'ltrim', 'strip_tags', 'similar_text', 'explode', 'implode', 'setlocale', 'localeconv',
+            'parse_str', 'str_pad', 'chop', 'strchr', 'sprintf', 'printf', 'vprintf', 'vsprintf', 'sscanf', 'fscanf', 'parse_url', 'urlencode', 'urldecode', 'rawurlencode', 'rawurldecode', 'readlink', 'linkinfo', 'link', 'unlink', 'exec', 'system', 'escapeshellcmd', 'escapeshellarg', 'passthru', 'shell_exec', 'proc_open', 'proc_close', 'rand', 'srand', 'getrandmax', 'mt_rand', 'mt_srand', 'mt_getrandmax', 'base64_decode', 'base64_encode', 'abs', 'ceil', 'floor', 'round', 'is_finite', 'is_nan', 'is_infinite', 'bindec', 'hexdec', 'octdec', 'decbin', 'decoct', 'dechex', 'base_convert', 'number_format', 'fmod', 'ip2long', 'long2ip', 'getenv', 'putenv', 'getopt', 'microtime', 'gettimeofday', 'getrusage', 'uniqid', 'quoted_printable_decode', 'set_time_limit', 'get_cfg_var', 'magic_quotes_runtime', 'set_magic_quotes_runtime', 'get_magic_quotes_gpc', 'get_magic_quotes_runtime',
+            'import_request_variables', 'error_log', 'serialize', 'unserialize', 'memory_get_usage', 'var_dump', 'var_export', 'debug_zval_dump', 'print_r','highlight_file', 'show_source', 'highlight_string', 'ini_get', 'ini_get_all', 'ini_set', 'ini_alter', 'ini_restore', 'get_include_path', 'set_include_path', 'restore_include_path', 'setcookie', 'header', 'headers_sent', 'connection_aborted', 'connection_status', 'ignore_user_abort', 'parse_ini_file', 'is_uploaded_file', 'move_uploaded_file', 'intval', 'floatval', 'doubleval', 'strval', 'gettype', 'settype', 'is_null', 'is_resource', 'is_bool', 'is_long', 'is_float', 'is_int', 'is_integer', 'is_double', 'is_real', 'is_numeric', 'is_string', 'is_array', 'is_object', 'is_scalar',
+            'ereg', 'ereg_replace', 'eregi', 'eregi_replace', 'split', 'spliti', 'join', 'sql_regcase', 'dl', 'pclose', 'popen', 'readfile', 'rewind', 'rmdir', 'umask', 'fclose', 'feof', 'fgetc', 'fgets', 'fgetss', 'fread', 'fopen', 'fpassthru', 'ftruncate', 'fstat', 'fseek', 'ftell', 'fflush', 'fwrite', 'fputs', 'mkdir', 'rename', 'copy', 'tempnam', 'tmpfile', 'file', 'file_get_contents', 'stream_select', 'stream_context_create', 'stream_context_set_params', 'stream_context_set_option', 'stream_context_get_options', 'stream_filter_prepend', 'stream_filter_append', 'fgetcsv', 'flock', 'get_meta_tags', 'stream_set_write_buffer', 'set_file_buffer', 'set_socket_blocking', 'stream_set_blocking', 'socket_set_blocking', 'stream_get_meta_data', 'stream_register_wrapper', 'stream_wrapper_register', 'stream_set_timeout', 'socket_set_timeout', 'socket_get_status', 'realpath', 'fnmatch', 'fsockopen', 'pfsockopen', 'pack', 'unpack', 'get_browser', 'crypt', 'opendir', 'closedir', 'chdir', 'getcwd', 'rewinddir', 'readdir', 'dir', 'glob', 'fileatime', 'filectime', 'filegroup', 'fileinode', 'filemtime', 'fileowner', 'fileperms', 'filesize', 'filetype', 'file_exists', 'is_writable', 'is_writeable', 'is_readable', 'is_executable', 'is_file', 'is_dir', 'is_link', 'stat', 'lstat', 'chown',
+            'touch', 'clearstatcache', 'mail', 'ob_start', 'ob_flush', 'ob_clean', 'ob_end_flush', 'ob_end_clean', 'ob_get_flush', 'ob_get_clean', 'ob_get_length', 'ob_get_level', 'ob_get_status', 'ob_get_contents', 'ob_implicit_flush', 'ob_list_handlers', 'ksort', 'krsort', 'natsort', 'natcasesort', 'asort', 'arsort', 'sort', 'rsort', 'usort', 'uasort', 'uksort', 'shuffle', 'array_walk', 'count', 'end', 'prev', 'next', 'reset', 'current', 'key', 'min', 'max', 'in_array', 'array_search', 'extract', 'compact', 'array_fill', 'range', 'array_multisort', 'array_push', 'array_pop', 'array_shift', 'array_unshift', 'array_splice', 'array_slice', 'array_merge', 'array_merge_recursive', 'array_keys', 'array_values', 'array_count_values', 'array_reverse', 'array_reduce', 'array_pad', 'array_flip', 'array_change_key_case', 'array_rand', 'array_unique', 'array_intersect', 'array_intersect_assoc', 'array_diff', 'array_diff_assoc', 'array_sum', 'array_filter', 'array_map', 'array_chunk', 'array_key_exists', 'pos', 'sizeof', 'key_exists', 'assert', 'assert_options', 'version_compare', 'ftok', 'str_rot13', 'aggregate',
+            'session_name', 'session_module_name', 'session_save_path', 'session_id', 'session_regenerate_id', 'session_decode', 'session_register', 'session_unregister', 'session_is_registered', 'session_encode',
+            'session_start', 'session_destroy', 'session_unset', 'session_set_save_handler', 'session_cache_limiter', 'session_cache_expire', 'session_set_cookie_params', 'session_get_cookie_params', 'session_write_close', 'preg_match', 'preg_match_all', 'preg_replace', 'preg_replace_callback', 'preg_split', 'preg_quote', 'preg_grep', 'overload', 'ctype_alnum', 'ctype_alpha', 'ctype_cntrl', 'ctype_digit', 'ctype_lower', 'ctype_graph', 'ctype_print', 'ctype_punct', 'ctype_space', 'ctype_upper', 'ctype_xdigit', 'virtual', 'apache_request_headers', 'apache_note', 'apache_lookup_uri', 'apache_child_terminate', 'apache_setenv', 'apache_response_headers', 'apache_get_version', 'getallheaders', 'mysql_connect', 'mysql_pconnect', 'mysql_close', 'mysql_select_db', 'mysql_create_db', 'mysql_drop_db', 'mysql_query', 'mysql_unbuffered_query', 'mysql_db_query', 'mysql_list_dbs', 'mysql_list_tables', 'mysql_list_fields', 'mysql_list_processes', 'mysql_error', 'mysql_errno', 'mysql_affected_rows', 'mysql_insert_id', 'mysql_result', 'mysql_num_rows', 'mysql_num_fields', 'mysql_fetch_row', 'mysql_fetch_array', 'mysql_fetch_assoc', 'mysql_fetch_object', 'mysql_data_seek', 'mysql_fetch_lengths', 'mysql_fetch_field', 'mysql_field_seek', 'mysql_free_result', 'mysql_field_name', 'mysql_field_table', 'mysql_field_len', 'mysql_field_type', 'mysql_field_flags', 'mysql_escape_string', 'mysql_real_escape_string', 'mysql_stat',
+            'mysql_thread_id', 'mysql_client_encoding', 'mysql_get_client_info', 'mysql_get_host_info', 'mysql_get_proto_info', 'mysql_get_server_info', 'mysql_info', 'mysql', 'mysql_fieldname', 'mysql_fieldtable', 'mysql_fieldlen', 'mysql_fieldtype', 'mysql_fieldflags', 'mysql_selectdb', 'mysql_createdb', 'mysql_dropdb', 'mysql_freeresult', 'mysql_numfields', 'mysql_numrows', 'mysql_listdbs', 'mysql_listtables', 'mysql_listfields', 'mysql_db_name', 'mysql_dbname', 'mysql_tablename', 'mysql_table_name', 'pg_connect', 'pg_pconnect', 'pg_close', 'pg_connection_status', 'pg_connection_busy', 'pg_connection_reset', 'pg_host', 'pg_dbname', 'pg_port', 'pg_tty', 'pg_options', 'pg_ping', 'pg_query', 'pg_send_query', 'pg_cancel_query', 'pg_fetch_result', 'pg_fetch_row', 'pg_fetch_assoc', 'pg_fetch_array', 'pg_fetch_object', 'pg_fetch_all', 'pg_affected_rows', 'pg_get_result', 'pg_result_seek', 'pg_result_status', 'pg_free_result', 'pg_last_oid', 'pg_num_rows', 'pg_num_fields', 'pg_field_name', 'pg_field_num', 'pg_field_size', 'pg_field_type', 'pg_field_prtlen', 'pg_field_is_null', 'pg_get_notify', 'pg_get_pid', 'pg_result_error', 'pg_last_error', 'pg_last_notice', 'pg_put_line', 'pg_end_copy', 'pg_copy_to', 'pg_copy_from',
+            'pg_trace', 'pg_untrace', 'pg_lo_create', 'pg_lo_unlink', 'pg_lo_open', 'pg_lo_close', 'pg_lo_read', 'pg_lo_write', 'pg_lo_read_all', 'pg_lo_import', 'pg_lo_export', 'pg_lo_seek', 'pg_lo_tell', 'pg_escape_string', 'pg_escape_bytea', 'pg_unescape_bytea', 'pg_client_encoding', 'pg_set_client_encoding', 'pg_meta_data', 'pg_convert', 'pg_insert', 'pg_update', 'pg_delete', 'pg_select', 'pg_exec', 'pg_getlastoid', 'pg_cmdtuples', 'pg_errormessage', 'pg_numrows', 'pg_numfields', 'pg_fieldname', 'pg_fieldsize', 'pg_fieldtype', 'pg_fieldnum', 'pg_fieldprtlen', 'pg_fieldisnull', 'pg_freeresult', 'pg_result', 'pg_loreadall', 'pg_locreate', 'pg_lounlink', 'pg_loopen', 'pg_loclose', 'pg_loread', 'pg_lowrite', 'pg_loimport', 'pg_loexport',
+            'echo', 'print', 'global', 'static', 'exit', 'array', 'empty', 'eval', 'isset', 'unset', 'die'
+            )
+        ),
+    'SYMBOLS' => array(
+        1 => array(
+            '<%', '<%=', '%>', '<?', '<?=', '?>'
+            ),
+        0 => array(
+            '(', ')', '[', ']', '{', '}',
+            '!', '@', '%', '&', '|', '/',
+            '<', '>',
+            '=', '-', '+', '*',
+            '.', ':', ',', ';'
+            )
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #990000;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #666666; font-style: italic;',
+            2 => 'color: #666666; font-style: italic;',
+            3 => 'color: #0000cc; font-style: italic;',
+            'MULTI' => 'color: #666666; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;',
+            'HARD' => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #009900;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #0000ff;',
+            'HARD' => 'color: #0000ff;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;',
+            GESHI_NUMBER_OCT_PREFIX => 'color: #208080;',
+            GESHI_NUMBER_HEX_PREFIX => 'color: #208080;',
+            GESHI_NUMBER_FLT_SCI_ZERO => 'color:#800080;',
+            ),
+        'METHODS' => array(
+            1 => 'color: #004000;',
+            2 => 'color: #004000;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #339933;',
+            1 => 'color: #000000; font-weight: bold;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #0000ff;'
+            ),
+        'SCRIPT' => array(
+            0 => '',
+            1 => '',
+            2 => '',
+            3 => '',
+            4 => '',
+            5 => ''
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => 'http://www.php.net/{FNAMEL}'
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '-&gt;',
+        2 => '::'
+        ),
+    'REGEXPS' => array(
+        //Variables
+        0 => "[\\$]{1,2}[a-zA-Z_][a-zA-Z0-9_]*"
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_MAYBE,
+    'SCRIPT_DELIMITERS' => array(
+        0 => array(
+            '<?php' => '?>'
+            ),
+        1 => array(
+            '<?' => '?>'
+            ),
+        2 => array(
+            '<%' => '%>'
+            ),
+        3 => array(
+            '<script language="php">' => '</script>'
+            ),
+        4 => "/(<\?(?:php)?)(?:'(?:[^'\\\\]|\\\\.)*?'|\"(?:[^\"\\\\]|\\\\.)*?\"|\/\*(?!\*\/).*?\*\/|.)*?(\?>|\Z)/sm",
+        5 => "/(<%)(?:'(?:[^'\\\\]|\\\\.)*?'|\"(?:[^\"\\\\]|\\\\.)*?\"|\/\*(?!\*\/).*?\*\/|.)*?(%>|\Z)/sm"
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        0 => true,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true,
+        5 => true
+        ),
+    'TAB_WIDTH' => 4
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/php.php b/examples/includes/geshi/geshi/php.php
new file mode 100644 (file)
index 0000000..fc6be6c
--- /dev/null
@@ -0,0 +1,1094 @@
+<?php
+/*************************************************************************************
+ * php.php
+ * --------
+ * Author: Nigel McNie (nigel@geshi.org)
+ * Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/06/20
+ *
+ * PHP language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *  -  Added description of extra language features (SF#1970248)
+ * 2004/11/25 (1.0.3)
+ *  -  Added support for multiple object splitters
+ *  -  Fixed &new problem
+ * 2004/10/27 (1.0.2)
+ *  -  Added URL support
+ *  -  Added extra constants
+ * 2004/08/05 (1.0.1)
+ *  -  Added support for symbols
+ * 2004/07/14 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2004/07/14)
+ * -------------------------
+ * * Make sure the last few function I may have missed
+ *   (like eval()) are included for highlighting
+ * * Split to several files - php4, php5 etc
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array(
+    'LANG_NAME' => 'PHP',
+    'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'HARDQUOTE' => array("'", "'"),
+    'HARDESCAPE' => array("'", "\\"),
+    'HARDCHAR' => "\\",
+    'COMMENT_REGEXP' => array(
+        //Heredoc and Nowdoc syntax
+        3 => '/<<<\s*?(\'?)([a-zA-Z0-9]+?)\1[^\n]*?\\n.*\\n\\2(?![a-zA-Z0-9])/siU',
+        // phpdoc comments
+        4 => '#/\*\*(?![\*\/]).*\*/#sU',
+        // Advanced # handling
+        2 => "/#.*?(?:(?=\?\>)|^)/smi"
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '',
+    'ESCAPE_REGEXP' => array(
+        //Simple Single Char Escapes
+        1 => "#\\\\[nfrtv\$\"\n\\\\]#i",
+        //Hexadecimal Char Specs
+        2 => "#\\\\x[\da-fA-F]{1,2}#i",
+        //Octal Char Specs
+        3 => "#\\\\[0-7]{1,3}#",
+        //String Parsing of Variable Names
+        4 => "#\\$[a-z0-9_]+(?:\\[[a-z0-9_]+\\]|->[a-z0-9_]+)?|(?:\\{\\$|\\$\\{)[a-z0-9_]+(?:\\[('?)[a-z0-9_]*\\1\\]|->[a-z0-9_]+)*\\}#i",
+        //Experimental extension supporting cascaded {${$var}} syntax
+        5 => "#\$[a-z0-9_]+(?:\[[a-z0-9_]+\]|->[a-z0-9_]+)?|(?:\{\$|\$\{)[a-z0-9_]+(?:\[('?)[a-z0-9_]*\\1\]|->[a-z0-9_]+)*\}|\{\$(?R)\}#i",
+        //Format String support in ""-Strings
+        6 => "#%(?:%|(?:\d+\\\\\\\$)?\\+?(?:\x20|0|'.)?-?(?:\d+|\\*)?(?:\.\d+)?[bcdefFosuxX])#"
+        ),
+    'NUMBERS' =>
+        GESHI_NUMBER_INT_BASIC |  GESHI_NUMBER_OCT_PREFIX | GESHI_NUMBER_HEX_PREFIX |
+        GESHI_NUMBER_FLT_SCI_ZERO,
+    'KEYWORDS' => array(
+        1 => array(
+            'as','break','case','continue','default','do','else','elseif',
+            'endfor','endforeach','endif','endswitch','endwhile','for',
+            'foreach','if','include','include_once','require','require_once',
+            'return','switch','while',
+
+            'echo','print'
+            ),
+        2 => array(
+            '&amp;new','&lt;/script&gt;','&lt;?php','&lt;script language',
+            'class','const','declare','extends','function','global','interface',
+            'namespace','new','private','public','self','var'
+            ),
+        3 => array(
+            'abs','acos','acosh','addcslashes','addslashes','aggregate',
+            'aggregate_methods','aggregate_methods_by_list',
+            'aggregate_methods_by_regexp','aggregate_properties',
+            'aggregate_properties_by_list','aggregate_properties_by_regexp',
+            'aggregation_info','apache_child_terminate','apache_get_modules',
+            'apache_get_version','apache_getenv','apache_lookup_uri',
+            'apache_note','apache_request_headers','apache_response_headers',
+            'apache_setenv','array','array_change_key_case','array_chunk',
+            'array_combine','array_count_values','array_diff',
+            'array_diff_assoc','array_diff_key','array_diff_uassoc',
+            'array_diff_ukey','array_fill','array_fill_keys','array_filter',
+            'array_flip','array_intersect','array_intersect_assoc',
+            'array_intersect_key','array_intersect_uassoc',
+            'array_intersect_ukey','array_key_exists','array_keys','array_map',
+            'array_merge','array_merge_recursive','array_multisort','array_pad',
+            'array_pop','array_product','array_push','array_rand',
+            'array_reduce','array_reverse','array_search','array_shift',
+            'array_slice','array_splice','array_sum','array_udiff',
+            'array_udiff_assoc','array_udiff_uassoc','array_uintersect',
+            'array_uintersect_assoc','array_uintersect_uassoc','array_unique',
+            'array_unshift','array_values','array_walk','array_walk_recursive',
+            'arsort','asin','asinh','asort','assert','assert_options','atan',
+            'atan2','atanh','base_convert','base64_decode','base64_encode',
+            'basename','bcadd','bccomp','bcdiv','bcmod','bcmul',
+            'bcompiler_load','bcompiler_load_exe','bcompiler_parse_class',
+            'bcompiler_read','bcompiler_write_class','bcompiler_write_constant',
+            'bcompiler_write_exe_footer','bcompiler_write_file',
+            'bcompiler_write_footer','bcompiler_write_function',
+            'bcompiler_write_functions_from_file','bcompiler_write_header',
+            'bcompiler_write_included_filename','bcpow','bcpowmod','bcscale',
+            'bcsqrt','bcsub','bin2hex','bindec','bindtextdomain',
+            'bind_textdomain_codeset','bitset_empty','bitset_equal',
+            'bitset_excl','bitset_fill','bitset_from_array','bitset_from_hash',
+            'bitset_from_string','bitset_in','bitset_incl',
+            'bitset_intersection','bitset_invert','bitset_is_empty',
+            'bitset_subset','bitset_to_array','bitset_to_hash',
+            'bitset_to_string','bitset_union','blenc_encrypt','bzclose',
+            'bzcompress','bzdecompress','bzerrno','bzerror','bzerrstr',
+            'bzflush','bzopen','bzread','bzwrite','cal_days_in_month',
+            'cal_from_jd','cal_info','cal_to_jd','call_user_func',
+            'call_user_func_array','call_user_method','call_user_method_array',
+            'ceil','chdir','checkdate','checkdnsrr','chgrp','chmod','chop',
+            'chown','chr','chunk_split','class_exists','class_implements',
+            'class_parents','classkit_aggregate_methods',
+            'classkit_doc_comments','classkit_import','classkit_method_add',
+            'classkit_method_copy','classkit_method_redefine',
+            'classkit_method_remove','classkit_method_rename','clearstatcache',
+            'closedir','closelog','com_create_guid','com_event_sink',
+            'com_get_active_object','com_load_typelib','com_message_pump',
+            'com_print_typeinfo','compact','confirm_phpdoc_compiled',
+            'connection_aborted','connection_status','constant',
+            'convert_cyr_string','convert_uudecode','convert_uuencode','copy',
+            'cos','cosh','count','count_chars','cpdf_add_annotation',
+            'cpdf_add_outline','cpdf_arc','cpdf_begin_text','cpdf_circle',
+            'cpdf_clip','cpdf_close','cpdf_closepath',
+            'cpdf_closepath_fill_stroke','cpdf_closepath_stroke',
+            'cpdf_continue_text','cpdf_curveto','cpdf_end_text','cpdf_fill',
+            'cpdf_fill_stroke','cpdf_finalize','cpdf_finalize_page',
+            'cpdf_global_set_document_limits','cpdf_import_jpeg','cpdf_lineto',
+            'cpdf_moveto','cpdf_newpath','cpdf_open','cpdf_output_buffer',
+            'cpdf_page_init','cpdf_rect','cpdf_restore','cpdf_rlineto',
+            'cpdf_rmoveto','cpdf_rotate','cpdf_rotate_text','cpdf_save',
+            'cpdf_save_to_file','cpdf_scale','cpdf_set_action_url',
+            'cpdf_set_char_spacing','cpdf_set_creator','cpdf_set_current_page',
+            'cpdf_set_font','cpdf_set_font_directories',
+            'cpdf_set_font_map_file','cpdf_set_horiz_scaling',
+            'cpdf_set_keywords','cpdf_set_leading','cpdf_set_page_animation',
+            'cpdf_set_subject','cpdf_set_text_matrix','cpdf_set_text_pos',
+            'cpdf_set_text_rendering','cpdf_set_text_rise','cpdf_set_title',
+            'cpdf_set_viewer_preferences','cpdf_set_word_spacing',
+            'cpdf_setdash','cpdf_setflat','cpdf_setgray','cpdf_setgray_fill',
+            'cpdf_setgray_stroke','cpdf_setlinecap','cpdf_setlinejoin',
+            'cpdf_setlinewidth','cpdf_setmiterlimit','cpdf_setrgbcolor',
+            'cpdf_setrgbcolor_fill','cpdf_setrgbcolor_stroke','cpdf_show',
+            'cpdf_show_xy','cpdf_stringwidth','cpdf_stroke','cpdf_text',
+            'cpdf_translate','crack_check','crack_closedict',
+            'crack_getlastmessage','crack_opendict','crc32','create_function',
+            'crypt','ctype_alnum','ctype_alpha','ctype_cntrl','ctype_digit',
+            'ctype_graph','ctype_lower','ctype_print','ctype_punct',
+            'ctype_space','ctype_upper','ctype_xdigit','curl_close',
+            'curl_copy_handle','curl_errno','curl_error','curl_exec',
+            'curl_getinfo','curl_init','curl_multi_add_handle',
+            'curl_multi_close','curl_multi_exec','curl_multi_getcontent',
+            'curl_multi_info_read','curl_multi_init','curl_multi_remove_handle',
+            'curl_multi_select','curl_setopt','curl_setopt_array',
+            'curl_version','current','cvsclient_connect','cvsclient_log',
+            'cvsclient_login','cvsclient_retrieve','date','date_create',
+            'date_date_set','date_default_timezone_get',
+            'date_default_timezone_set','date_format','date_isodate_set',
+            'date_modify','date_offset_get','date_parse','date_sun_info',
+            'date_sunrise','date_sunset','date_time_set','date_timezone_get',
+            'date_timezone_set','db_id_list','dba_close','dba_delete',
+            'dba_exists','dba_fetch','dba_firstkey','dba_handlers','dba_insert',
+            'dba_key_split','dba_list','dba_nextkey','dba_open','dba_optimize',
+            'dba_popen','dba_replace','dba_sync','dbase_add_record',
+            'dbase_close','dbase_create','dbase_delete_record',
+            'dbase_get_header_info','dbase_get_record',
+            'dbase_get_record_with_names','dbase_numfields','dbase_numrecords',
+            'dbase_open','dbase_pack','dbase_replace_record',
+            'dbg_get_all_contexts','dbg_get_all_module_names',
+            'dbg_get_all_source_lines','dbg_get_context_name',
+            'dbg_get_module_name','dbg_get_profiler_results',
+            'dbg_get_source_context','dblist','dbmclose','dbmdelete',
+            'dbmexists','dbmfetch','dbmfirstkey','dbminsert','dbmnextkey',
+            'dbmopen','dbmreplace','dbx_close','dbx_compare','dbx_connect',
+            'dbx_error','dbx_escape_string','dbx_fetch_row','dbx_query',
+            'dbx_sort','dcgettext','dcngettext','deaggregate','debug_backtrace',
+            'debug_zval_dump','debugbreak','decbin','dechex','decoct','define',
+            'defined','define_syslog_variables','deg2rad','dgettext','die',
+            'dio_close','dio_open','dio_read','dio_seek','dio_stat','dio_write',
+            'dir','dirname','disk_free_space','disk_total_space',
+            'diskfreespace','dl','dngettext','docblock_token_name',
+            'docblock_tokenize','dom_import_simplexml','domxml_add_root',
+            'domxml_attributes','domxml_children','domxml_doc_add_root',
+            'domxml_doc_document_element','domxml_doc_get_element_by_id',
+            'domxml_doc_get_elements_by_tagname','domxml_doc_get_root',
+            'domxml_doc_set_root','domxml_doc_validate','domxml_doc_xinclude',
+            'domxml_dump_mem','domxml_dump_mem_file','domxml_dump_node',
+            'domxml_dumpmem','domxml_elem_get_attribute',
+            'domxml_elem_set_attribute','domxml_get_attribute','domxml_getattr',
+            'domxml_html_dump_mem','domxml_new_child','domxml_new_doc',
+            'domxml_new_xmldoc','domxml_node','domxml_node_add_namespace',
+            'domxml_node_attributes','domxml_node_children',
+            'domxml_node_get_content','domxml_node_has_attributes',
+            'domxml_node_new_child','domxml_node_set_content',
+            'domxml_node_set_namespace','domxml_node_unlink_node',
+            'domxml_open_file','domxml_open_mem','domxml_parser',
+            'domxml_parser_add_chunk','domxml_parser_cdata_section',
+            'domxml_parser_characters','domxml_parser_comment',
+            'domxml_parser_end','domxml_parser_end_document',
+            'domxml_parser_end_element','domxml_parser_entity_reference',
+            'domxml_parser_get_document','domxml_parser_namespace_decl',
+            'domxml_parser_processing_instruction',
+            'domxml_parser_start_document','domxml_parser_start_element',
+            'domxml_root','domxml_set_attribute','domxml_setattr',
+            'domxml_substitute_entities_default','domxml_unlink_node',
+            'domxml_version','domxml_xmltree','doubleval','each','easter_date',
+            'easter_days','empty','end','ereg','ereg_replace','eregi',
+            'eregi_replace','error_get_last','error_log','error_reporting',
+            'escapeshellarg','escapeshellcmd','eval','event_deschedule',
+            'event_dispatch','event_free','event_handle_signal',
+            'event_have_events','event_init','event_new','event_pending',
+            'event_priority_set','event_schedule','event_set','event_timeout',
+            'exec','exif_imagetype','exif_read_data','exif_tagname',
+            'exif_thumbnail','exit','exp','explode','expm1','extension_loaded',
+            'extract','ezmlm_hash','fbird_add_user','fbird_affected_rows',
+            'fbird_backup','fbird_blob_add','fbird_blob_cancel',
+            'fbird_blob_close','fbird_blob_create','fbird_blob_echo',
+            'fbird_blob_get','fbird_blob_import','fbird_blob_info',
+            'fbird_blob_open','fbird_close','fbird_commit','fbird_commit_ret',
+            'fbird_connect','fbird_db_info','fbird_delete_user','fbird_drop_db',
+            'fbird_errcode','fbird_errmsg','fbird_execute','fbird_fetch_assoc',
+            'fbird_fetch_object','fbird_fetch_row','fbird_field_info',
+            'fbird_free_event_handler','fbird_free_query','fbird_free_result',
+            'fbird_gen_id','fbird_maintain_db','fbird_modify_user',
+            'fbird_name_result','fbird_num_fields','fbird_num_params',
+            'fbird_param_info','fbird_pconnect','fbird_prepare','fbird_query',
+            'fbird_restore','fbird_rollback','fbird_rollback_ret',
+            'fbird_server_info','fbird_service_attach','fbird_service_detach',
+            'fbird_set_event_handler','fbird_trans','fbird_wait_event','fclose',
+            'fdf_add_doc_javascript','fdf_add_template','fdf_close',
+            'fdf_create','fdf_enum_values','fdf_errno','fdf_error','fdf_get_ap',
+            'fdf_get_attachment','fdf_get_encoding','fdf_get_file',
+            'fdf_get_flags','fdf_get_opt','fdf_get_status','fdf_get_value',
+            'fdf_get_version','fdf_header','fdf_next_field_name','fdf_open',
+            'fdf_open_string','fdf_remove_item','fdf_save','fdf_save_string',
+            'fdf_set_ap','fdf_set_encoding','fdf_set_file','fdf_set_flags',
+            'fdf_set_javascript_action','fdf_set_on_import_javascript',
+            'fdf_set_opt','fdf_set_status','fdf_set_submit_form_action',
+            'fdf_set_target_frame','fdf_set_value','fdf_set_version','feof',
+            'fflush','fgetc','fgetcsv','fgets','fgetss','file','file_exists',
+            'file_get_contents','file_put_contents','fileatime','filectime',
+            'filegroup','fileinode','filemtime','fileowner','fileperms',
+            'filepro','filepro_fieldcount','filepro_fieldname',
+            'filepro_fieldtype','filepro_fieldwidth','filepro_retrieve',
+            'filepro_rowcount','filesize','filetype','filter_has_var',
+            'filter_id','filter_input','filter_input_array','filter_list',
+            'filter_var','filter_var_array','finfo_buffer','finfo_close',
+            'finfo_file','finfo_open','finfo_set_flags','floatval','flock',
+            'floor','flush','fmod','fnmatch','fopen','fpassthru','fprintf',
+            'fputcsv','fputs','fread','frenchtojd','fribidi_charset_info',
+            'fribidi_get_charsets','fribidi_log2vis','fscanf','fseek',
+            'fsockopen','fstat','ftell','ftok','ftp_alloc','ftp_cdup',
+            'ftp_chdir','ftp_chmod','ftp_close','ftp_connect','ftp_delete',
+            'ftp_exec','ftp_fget','ftp_fput','ftp_get','ftp_get_option',
+            'ftp_login','ftp_mdtm','ftp_mkdir','ftp_nb_continue','ftp_nb_fget',
+            'ftp_nb_fput','ftp_nb_get','ftp_nb_put','ftp_nlist','ftp_pasv',
+            'ftp_put','ftp_pwd','ftp_quit','ftp_raw','ftp_rawlist','ftp_rename',
+            'ftp_rmdir','ftp_set_option','ftp_site','ftp_size',
+            'ftp_ssl_connect','ftp_systype','ftruncate','function_exists',
+            'func_get_arg','func_get_args','func_num_args','fwrite','gd_info',
+            'getallheaders','getcwd','getdate','getenv','gethostbyaddr',
+            'gethostbyname','gethostbynamel','getimagesize','getlastmod',
+            'getmxrr','getmygid','getmyinode','getmypid','getmyuid','getopt',
+            'getprotobyname','getprotobynumber','getrandmax','getrusage',
+            'getservbyname','getservbyport','gettext','gettimeofday','gettype',
+            'get_browser','get_cfg_var','get_class','get_class_methods',
+            'get_class_vars','get_current_user','get_declared_classes',
+            'get_defined_constants','get_defined_functions','get_defined_vars',
+            'get_extension_funcs','get_headers','get_html_translation_table',
+            'get_included_files','get_include_path','get_loaded_extensions',
+            'get_magic_quotes_gpc','get_magic_quotes_runtime','get_meta_tags',
+            'get_object_vars','get_parent_class','get_required_files',
+            'get_resource_type','glob','gmdate','gmmktime','gmp_abs','gmp_add',
+            'gmp_and','gmp_clrbit','gmp_cmp','gmp_com','gmp_div','gmp_div_q',
+            'gmp_div_qr','gmp_div_r','gmp_divexact','gmp_fact','gmp_gcd',
+            'gmp_gcdext','gmp_hamdist','gmp_init','gmp_intval','gmp_invert',
+            'gmp_jacobi','gmp_legendre','gmp_mod','gmp_mul','gmp_neg',
+            'gmp_nextprime','gmp_or','gmp_perfect_square','gmp_popcount',
+            'gmp_pow','gmp_powm','gmp_prob_prime','gmp_random','gmp_scan0',
+            'gmp_scan1','gmp_setbit','gmp_sign','gmp_sqrt','gmp_sqrtrem',
+            'gmp_strval','gmp_sub','gmp_xor','gmstrftime','gopher_parsedir',
+            'gregoriantojd','gzclose','gzcompress','gzdeflate','gzencode',
+            'gzeof','gzfile','gzgetc','gzgets','gzgetss','gzinflate','gzopen',
+            'gzpassthru','gzputs','gzread','gzrewind','gzseek','gztell',
+            'gzuncompress','gzwrite','hash','hash_algos','hash_file',
+            'hash_final','hash_hmac','hash_hmac_file','hash_init','hash_update',
+            'hash_update_file','hash_update_stream','header','headers_list',
+            'headers_sent','hebrev','hebrevc','hexdec','highlight_file',
+            'highlight_string','html_doc','html_doc_file','html_entity_decode',
+            'htmlentities','htmlspecialchars','htmlspecialchars_decode',
+            'http_build_cookie','http_build_query','http_build_str',
+            'http_build_url','http_cache_etag','http_cache_last_modified',
+            'http_chunked_decode','http_date','http_deflate','http_get',
+            'http_get_request_body','http_get_request_body_stream',
+            'http_get_request_headers','http_head','http_inflate',
+            'http_match_etag','http_match_modified','http_match_request_header',
+            'http_negotiate_charset','http_negotiate_content_type',
+            'http_negotiate_language','http_parse_cookie','http_parse_headers',
+            'http_parse_message','http_parse_params',
+            'http_persistent_handles_clean','http_persistent_handles_count',
+            'http_persistent_handles_ident','http_post_data','http_post_fields',
+            'http_put_data','http_put_file','http_put_stream','http_redirect',
+            'http_request','http_request_body_encode',
+            'http_request_method_exists','http_request_method_name',
+            'http_request_method_register','http_request_method_unregister',
+            'http_send_content_disposition','http_send_content_type',
+            'http_send_data','http_send_file','http_send_last_modified',
+            'http_send_status','http_send_stream','http_support',
+            'http_throttle','hypot','i18n_convert','i18n_discover_encoding',
+            'i18n_http_input','i18n_http_output','i18n_internal_encoding',
+            'i18n_ja_jp_hantozen','i18n_mime_header_decode',
+            'i18n_mime_header_encode','ibase_add_user','ibase_affected_rows',
+            'ibase_backup','ibase_blob_add','ibase_blob_cancel',
+            'ibase_blob_close','ibase_blob_create','ibase_blob_echo',
+            'ibase_blob_get','ibase_blob_import','ibase_blob_info',
+            'ibase_blob_open','ibase_close','ibase_commit','ibase_commit_ret',
+            'ibase_connect','ibase_db_info','ibase_delete_user','ibase_drop_db',
+            'ibase_errcode','ibase_errmsg','ibase_execute','ibase_fetch_assoc',
+            'ibase_fetch_object','ibase_fetch_row','ibase_field_info',
+            'ibase_free_event_handler','ibase_free_query','ibase_free_result',
+            'ibase_gen_id','ibase_maintain_db','ibase_modify_user',
+            'ibase_name_result','ibase_num_fields','ibase_num_params',
+            'ibase_param_info','ibase_pconnect','ibase_prepare','ibase_query',
+            'ibase_restore','ibase_rollback','ibase_rollback_ret',
+            'ibase_server_info','ibase_service_attach','ibase_service_detach',
+            'ibase_set_event_handler','ibase_trans','ibase_wait_event','iconv',
+            'iconv_get_encoding','iconv_mime_decode',
+            'iconv_mime_decode_headers','iconv_mime_encode',
+            'iconv_set_encoding','iconv_strlen','iconv_strpos','iconv_strrpos',
+            'iconv_substr','id3_get_frame_long_name','id3_get_frame_short_name',
+            'id3_get_genre_id','id3_get_genre_list','id3_get_genre_name',
+            'id3_get_tag','id3_get_version','id3_remove_tag','id3_set_tag',
+            'idate','ignore_user_abort','image_type_to_extension',
+            'image_type_to_mime_type','image2wbmp','imagealphablending',
+            'imageantialias','imagearc','imagechar','imagecharup',
+            'imagecolorallocate','imagecolorallocatealpha','imagecolorat',
+            'imagecolorclosest','imagecolorclosestalpha','imagecolordeallocate',
+            'imagecolorexact','imagecolorexactalpha','imagecolormatch',
+            'imagecolorresolve','imagecolorresolvealpha','imagecolorset',
+            'imagecolorsforindex','imagecolorstotal','imagecolortransparent',
+            'imageconvolution','imagecopy','imagecopymerge',
+            'imagecopymergegray','imagecopyresampled','imagecopyresized',
+            'imagecreate','imagecreatefromgd','imagecreatefromgd2',
+            'imagecreatefromgd2part','imagecreatefromgif','imagecreatefromjpeg',
+            'imagecreatefrompng','imagecreatefromstring','imagecreatefromwbmp',
+            'imagecreatefromxbm','imagecreatetruecolor','imagedashedline',
+            'imagedestroy','imageellipse','imagefill','imagefilledarc',
+            'imagefilledellipse','imagefilledpolygon','imagefilledrectangle',
+            'imagefilltoborder','imagefilter','imagefontheight',
+            'imagefontwidth','imageftbbox','imagefttext','imagegammacorrect',
+            'imagegd','imagegd2','imagegif','imagegrabscreen','imagegrabwindow',
+            'imageinterlace','imageistruecolor','imagejpeg','imagelayereffect',
+            'imageline','imageloadfont','imagepalettecopy','imagepng',
+            'imagepolygon','imagepsbbox','imagepsencodefont',
+            'imagepsextendfont','imagepsfreefont','imagepsloadfont',
+            'imagepsslantfont','imagepstext','imagerectangle','imagerotate',
+            'imagesavealpha','imagesetbrush','imagesetpixel','imagesetstyle',
+            'imagesetthickness','imagesettile','imagestring','imagestringup',
+            'imagesx','imagesy','imagetruecolortopalette','imagettfbbox',
+            'imagettftext','imagetypes','imagewbmp','imagexbm','imap_8bit',
+            'imap_alerts','imap_append','imap_base64','imap_binary','imap_body',
+            'imap_bodystruct','imap_check','imap_clearflag_full','imap_close',
+            'imap_create','imap_createmailbox','imap_delete',
+            'imap_deletemailbox','imap_errors','imap_expunge',
+            'imap_fetch_overview','imap_fetchbody','imap_fetchheader',
+            'imap_fetchstructure','imap_fetchtext','imap_get_quota',
+            'imap_get_quotaroot','imap_getacl','imap_getmailboxes',
+            'imap_getsubscribed','imap_header','imap_headerinfo','imap_headers',
+            'imap_last_error','imap_list','imap_listmailbox',
+            'imap_listsubscribed','imap_lsub','imap_mail','imap_mail_compose',
+            'imap_mail_copy','imap_mail_move','imap_mailboxmsginfo',
+            'imap_mime_header_decode','imap_msgno','imap_num_msg',
+            'imap_num_recent','imap_open','imap_ping','imap_qprint',
+            'imap_rename','imap_renamemailbox','imap_reopen',
+            'imap_rfc822_parse_adrlist','imap_rfc822_parse_headers',
+            'imap_rfc822_write_address','imap_savebody','imap_scan',
+            'imap_scanmailbox','imap_search','imap_set_quota','imap_setacl',
+            'imap_setflag_full','imap_sort','imap_status','imap_subscribe',
+            'imap_thread','imap_timeout','imap_uid','imap_undelete',
+            'imap_unsubscribe','imap_utf7_decode','imap_utf7_encode',
+            'imap_utf8','implode','import_request_variables','in_array',
+            'ini_alter','ini_get','ini_get_all','ini_restore','ini_set',
+            'intval','ip2long','iptcembed','iptcparse','isset','is_a',
+            'is_array','is_bool','is_callable','is_dir','is_double',
+            'is_executable','is_file','is_finite','is_float','is_infinite',
+            'is_int','is_integer','is_link','is_long','is_nan','is_null',
+            'is_numeric','is_object','is_readable','is_real','is_resource',
+            'is_scalar','is_soap_fault','is_string','is_subclass_of',
+            'is_uploaded_file','is_writable','is_writeable','iterator_apply',
+            'iterator_count','iterator_to_array','java_last_exception_clear',
+            'java_last_exception_get','jddayofweek','jdmonthname','jdtofrench',
+            'jdtogregorian','jdtojewish','jdtojulian','jdtounix','jewishtojd',
+            'join','jpeg2wbmp','json_decode','json_encode','juliantojd','key',
+            'key_exists','krsort','ksort','lcg_value','ldap_add','ldap_bind',
+            'ldap_close','ldap_compare','ldap_connect','ldap_count_entries',
+            'ldap_delete','ldap_dn2ufn','ldap_err2str','ldap_errno',
+            'ldap_error','ldap_explode_dn','ldap_first_attribute',
+            'ldap_first_entry','ldap_first_reference','ldap_free_result',
+            'ldap_get_attributes','ldap_get_dn','ldap_get_entries',
+            'ldap_get_option','ldap_get_values','ldap_get_values_len',
+            'ldap_list','ldap_mod_add','ldap_mod_del','ldap_mod_replace',
+            'ldap_modify','ldap_next_attribute','ldap_next_entry',
+            'ldap_next_reference','ldap_parse_reference','ldap_parse_result',
+            'ldap_read','ldap_rename','ldap_search','ldap_set_option',
+            'ldap_sort','ldap_start_tls','ldap_unbind','levenshtein',
+            'libxml_clear_errors','libxml_get_errors','libxml_get_last_error',
+            'libxml_set_streams_context','libxml_use_internal_errors','link',
+            'linkinfo','list','localeconv','localtime','log','log1p','log10',
+            'long2ip','lstat','ltrim','lzf_compress','lzf_decompress',
+            'lzf_optimized_for','magic_quotes_runtime','mail','max','mbereg',
+            'mberegi','mberegi_replace','mbereg_match','mbereg_replace',
+            'mbereg_search','mbereg_search_getpos','mbereg_search_getregs',
+            'mbereg_search_init','mbereg_search_pos','mbereg_search_regs',
+            'mbereg_search_setpos','mbregex_encoding','mbsplit','mbstrcut',
+            'mbstrlen','mbstrpos','mbstrrpos','mbsubstr','mb_check_encoding',
+            'mb_convert_case','mb_convert_encoding','mb_convert_kana',
+            'mb_convert_variables','mb_decode_mimeheader',
+            'mb_decode_numericentity','mb_detect_encoding','mb_detect_order',
+            'mb_encode_mimeheader','mb_encode_numericentity','mb_ereg',
+            'mb_eregi','mb_eregi_replace','mb_ereg_match','mb_ereg_replace',
+            'mb_ereg_search','mb_ereg_search_getpos','mb_ereg_search_getregs',
+            'mb_ereg_search_init','mb_ereg_search_pos','mb_ereg_search_regs',
+            'mb_ereg_search_setpos','mb_get_info','mb_http_input',
+            'mb_http_output','mb_internal_encoding','mb_language',
+            'mb_list_encodings','mb_output_handler','mb_parse_str',
+            'mb_preferred_mime_name','mb_regex_encoding','mb_regex_set_options',
+            'mb_send_mail','mb_split','mb_strcut','mb_strimwidth','mb_stripos',
+            'mb_stristr','mb_strlen','mb_strpos','mb_strrchr','mb_strrichr',
+            'mb_strripos','mb_strrpos','mb_strstr','mb_strtolower',
+            'mb_strtoupper','mb_strwidth','mb_substitute_character','mb_substr',
+            'mb_substr_count','mcrypt_cbc','mcrypt_cfb','mcrypt_create_iv',
+            'mcrypt_decrypt','mcrypt_ecb','mcrypt_enc_get_algorithms_name',
+            'mcrypt_enc_get_block_size','mcrypt_enc_get_iv_size',
+            'mcrypt_enc_get_key_size','mcrypt_enc_get_modes_name',
+            'mcrypt_enc_get_supported_key_sizes',
+            'mcrypt_enc_is_block_algorithm',
+            'mcrypt_enc_is_block_algorithm_mode','mcrypt_enc_is_block_mode',
+            'mcrypt_enc_self_test','mcrypt_encrypt','mcrypt_generic',
+            'mcrypt_generic_deinit','mcrypt_generic_end','mcrypt_generic_init',
+            'mcrypt_get_block_size','mcrypt_get_cipher_name',
+            'mcrypt_get_iv_size','mcrypt_get_key_size','mcrypt_list_algorithms',
+            'mcrypt_list_modes','mcrypt_module_close',
+            'mcrypt_module_get_algo_block_size',
+            'mcrypt_module_get_algo_key_size',
+            'mcrypt_module_get_supported_key_sizes',
+            'mcrypt_module_is_block_algorithm',
+            'mcrypt_module_is_block_algorithm_mode',
+            'mcrypt_module_is_block_mode','mcrypt_module_open',
+            'mcrypt_module_self_test','mcrypt_ofb','md5','md5_file',
+            'mdecrypt_generic','memcache_add','memcache_add_server',
+            'memcache_close','memcache_connect','memcache_debug',
+            'memcache_decrement','memcache_delete','memcache_flush',
+            'memcache_get','memcache_get_extended_stats',
+            'memcache_get_server_status','memcache_get_stats',
+            'memcache_get_version','memcache_increment','memcache_pconnect',
+            'memcache_replace','memcache_set','memcache_set_compress_threshold',
+            'memcache_set_server_params','memory_get_peak_usage',
+            'memory_get_usage','metaphone','mhash','mhash_count',
+            'mhash_get_block_size','mhash_get_hash_name','mhash_keygen_s2k',
+            'method_exists','microtime','mime_content_type','min',
+            'ming_keypress','ming_setcubicthreshold','ming_setscale',
+            'ming_useconstants','ming_useswfversion','mkdir','mktime',
+            'money_format','move_uploaded_file','msql','msql_affected_rows',
+            'msql_close','msql_connect','msql_create_db','msql_createdb',
+            'msql_data_seek','msql_db_query','msql_dbname','msql_drop_db',
+            'msql_dropdb','msql_error','msql_fetch_array','msql_fetch_field',
+            'msql_fetch_object','msql_fetch_row','msql_field_flags',
+            'msql_field_len','msql_field_name','msql_field_seek',
+            'msql_field_table','msql_field_type','msql_fieldflags',
+            'msql_fieldlen','msql_fieldname','msql_fieldtable','msql_fieldtype',
+            'msql_free_result','msql_freeresult','msql_list_dbs',
+            'msql_list_fields','msql_list_tables','msql_listdbs',
+            'msql_listfields','msql_listtables','msql_num_fields',
+            'msql_num_rows','msql_numfields','msql_numrows','msql_pconnect',
+            'msql_query','msql_regcase','msql_result','msql_select_db',
+            'msql_selectdb','msql_tablename','mssql_bind','mssql_close',
+            'mssql_connect','mssql_data_seek','mssql_execute',
+            'mssql_fetch_array','mssql_fetch_assoc','mssql_fetch_batch',
+            'mssql_fetch_field','mssql_fetch_object','mssql_fetch_row',
+            'mssql_field_length','mssql_field_name','mssql_field_seek',
+            'mssql_field_type','mssql_free_result','mssql_free_statement',
+            'mssql_get_last_message','mssql_guid_string','mssql_init',
+            'mssql_min_error_severity','mssql_min_message_severity',
+            'mssql_next_result','mssql_num_fields','mssql_num_rows',
+            'mssql_pconnect','mssql_query','mssql_result','mssql_rows_affected',
+            'mssql_select_db','mt_getrandmax','mt_rand','mt_srand','mysql',
+            'mysql_affected_rows','mysql_client_encoding','mysql_close',
+            'mysql_connect','mysql_createdb','mysql_create_db',
+            'mysql_data_seek','mysql_dbname','mysql_db_name','mysql_db_query',
+            'mysql_dropdb','mysql_drop_db','mysql_errno','mysql_error',
+            'mysql_escape_string','mysql_fetch_array','mysql_fetch_assoc',
+            'mysql_fetch_field','mysql_fetch_lengths','mysql_fetch_object',
+            'mysql_fetch_row','mysql_fieldflags','mysql_fieldlen',
+            'mysql_fieldname','mysql_fieldtable','mysql_fieldtype',
+            'mysql_field_flags','mysql_field_len','mysql_field_name',
+            'mysql_field_seek','mysql_field_table','mysql_field_type',
+            'mysql_freeresult','mysql_free_result','mysql_get_client_info',
+            'mysql_get_host_info','mysql_get_proto_info',
+            'mysql_get_server_info','mysql_info','mysql_insert_id',
+            'mysql_listdbs','mysql_listfields','mysql_listtables',
+            'mysql_list_dbs','mysql_list_fields','mysql_list_processes',
+            'mysql_list_tables','mysql_numfields','mysql_numrows',
+            'mysql_num_fields','mysql_num_rows','mysql_pconnect','mysql_ping',
+            'mysql_query','mysql_real_escape_string','mysql_result',
+            'mysql_selectdb','mysql_select_db','mysql_set_charset','mysql_stat',
+            'mysql_tablename','mysql_table_name','mysql_thread_id',
+            'mysql_unbuffered_query','mysqli_affected_rows','mysqli_autocommit',
+            'mysqli_bind_param','mysqli_bind_result','mysqli_change_user',
+            'mysqli_character_set_name','mysqli_client_encoding','mysqli_close',
+            'mysqli_commit','mysqli_connect','mysqli_connect_errno',
+            'mysqli_connect_error','mysqli_data_seek','mysqli_debug',
+            'mysqli_disable_reads_from_master','mysqli_disable_rpl_parse',
+            'mysqli_dump_debug_info','mysqli_embedded_server_end',
+            'mysqli_embedded_server_start','mysqli_enable_reads_from_master',
+            'mysqli_enable_rpl_parse','mysqli_errno','mysqli_error',
+            'mysqli_escape_string','mysqli_execute','mysqli_fetch',
+            'mysqli_fetch_array','mysqli_fetch_assoc','mysqli_fetch_field',
+            'mysqli_fetch_field_direct','mysqli_fetch_fields',
+            'mysqli_fetch_lengths','mysqli_fetch_object','mysqli_fetch_row',
+            'mysqli_field_count','mysqli_field_seek','mysqli_field_tell',
+            'mysqli_free_result','mysqli_get_charset','mysqli_get_client_info',
+            'mysqli_get_client_version','mysqli_get_host_info',
+            'mysqli_get_metadata','mysqli_get_proto_info',
+            'mysqli_get_server_info','mysqli_get_server_version',
+            'mysqli_get_warnings','mysqli_info','mysqli_init',
+            'mysqli_insert_id','mysqli_kill','mysqli_master_query',
+            'mysqli_more_results','mysqli_multi_query','mysqli_next_result',
+            'mysqli_num_fields','mysqli_num_rows','mysqli_options',
+            'mysqli_param_count','mysqli_ping','mysqli_prepare','mysqli_query',
+            'mysqli_real_connect','mysqli_real_escape_string',
+            'mysqli_real_query','mysqli_report','mysqli_rollback',
+            'mysqli_rpl_parse_enabled','mysqli_rpl_probe',
+            'mysqli_rpl_query_type','mysqli_select_db','mysqli_send_long_data',
+            'mysqli_send_query','mysqli_set_charset',
+            'mysqli_set_local_infile_default','mysqli_set_local_infile_handler',
+            'mysqli_set_opt','mysqli_slave_query','mysqli_sqlstate',
+            'mysqli_ssl_set','mysqli_stat','mysqli_stmt_affected_rows',
+            'mysqli_stmt_attr_get','mysqli_stmt_attr_set',
+            'mysqli_stmt_bind_param','mysqli_stmt_bind_result',
+            'mysqli_stmt_close','mysqli_stmt_data_seek','mysqli_stmt_errno',
+            'mysqli_stmt_error','mysqli_stmt_execute','mysqli_stmt_fetch',
+            'mysqli_stmt_field_count','mysqli_stmt_free_result',
+            'mysqli_stmt_get_warnings','mysqli_stmt_init',
+            'mysqli_stmt_insert_id','mysqli_stmt_num_rows',
+            'mysqli_stmt_param_count','mysqli_stmt_prepare','mysqli_stmt_reset',
+            'mysqli_stmt_result_metadata','mysqli_stmt_send_long_data',
+            'mysqli_stmt_sqlstate','mysqli_stmt_store_result',
+            'mysqli_store_result','mysqli_thread_id','mysqli_thread_safe',
+            'mysqli_use_result','mysqli_warning_count','natcasesort','natsort',
+            'new_xmldoc','next','ngettext','nl2br','nl_langinfo',
+            'ntuser_getdomaincontroller','ntuser_getusergroups',
+            'ntuser_getuserinfo','ntuser_getuserlist','number_format',
+            'ob_clean','ob_deflatehandler','ob_end_clean','ob_end_flush',
+            'ob_etaghandler','ob_flush','ob_get_clean','ob_get_contents',
+            'ob_get_flush','ob_get_length','ob_get_level','ob_get_status',
+            'ob_gzhandler','ob_iconv_handler','ob_implicit_flush',
+            'ob_inflatehandler','ob_list_handlers','ob_start','ob_tidyhandler',
+            'octdec','odbc_autocommit','odbc_binmode','odbc_close',
+            'odbc_close_all','odbc_columnprivileges','odbc_columns',
+            'odbc_commit','odbc_connect','odbc_cursor','odbc_data_source',
+            'odbc_do','odbc_error','odbc_errormsg','odbc_exec','odbc_execute',
+            'odbc_fetch_array','odbc_fetch_into','odbc_fetch_object',
+            'odbc_fetch_row','odbc_field_len','odbc_field_name',
+            'odbc_field_num','odbc_field_precision','odbc_field_scale',
+            'odbc_field_type','odbc_foreignkeys','odbc_free_result',
+            'odbc_gettypeinfo','odbc_longreadlen','odbc_next_result',
+            'odbc_num_fields','odbc_num_rows','odbc_pconnect','odbc_prepare',
+            'odbc_primarykeys','odbc_procedurecolumns','odbc_procedures',
+            'odbc_result','odbc_result_all','odbc_rollback','odbc_setoption',
+            'odbc_specialcolumns','odbc_statistics','odbc_tableprivileges',
+            'odbc_tables','opendir','openlog','openssl_csr_export',
+            'openssl_csr_export_to_file','openssl_csr_get_public_key',
+            'openssl_csr_get_subject','openssl_csr_new','openssl_csr_sign',
+            'openssl_error_string','openssl_free_key','openssl_get_privatekey',
+            'openssl_get_publickey','openssl_open','openssl_pkcs12_export',
+            'openssl_pkcs12_export_to_file','openssl_pkcs12_read',
+            'openssl_pkcs7_decrypt','openssl_pkcs7_encrypt',
+            'openssl_pkcs7_sign','openssl_pkcs7_verify','openssl_pkey_export',
+            'openssl_pkey_export_to_file','openssl_pkey_free',
+            'openssl_pkey_get_details','openssl_pkey_get_private',
+            'openssl_pkey_get_public','openssl_pkey_new',
+            'openssl_private_decrypt','openssl_private_encrypt',
+            'openssl_public_decrypt','openssl_public_encrypt','openssl_seal',
+            'openssl_sign','openssl_verify','openssl_x509_checkpurpose',
+            'openssl_x509_check_private_key','openssl_x509_export',
+            'openssl_x509_export_to_file','openssl_x509_free',
+            'openssl_x509_parse','openssl_x509_read','ord',
+            'output_add_rewrite_var','output_reset_rewrite_vars','overload',
+            'outputdebugstring','pack','parse_ini_file','parse_str','parse_url',
+            'parsekit_compile_file','parsekit_compile_string',
+            'parsekit_func_arginfo','parsekit_opcode_flags',
+            'parsekit_opcode_name','passthru','pathinfo','pclose',
+            'pdf_add_bookmark','pdf_add_launchlink','pdf_add_locallink',
+            'pdf_add_nameddest','pdf_add_note','pdf_add_pdflink',
+            'pdf_add_thumbnail','pdf_add_weblink','pdf_arc','pdf_arcn',
+            'pdf_attach_file','pdf_begin_font','pdf_begin_glyph',
+            'pdf_begin_page','pdf_begin_pattern','pdf_begin_template',
+            'pdf_circle','pdf_clip','pdf_close','pdf_close_image',
+            'pdf_close_pdi','pdf_close_pdi_page','pdf_closepath',
+            'pdf_closepath_fill_stroke','pdf_closepath_stroke','pdf_concat',
+            'pdf_continue_text','pdf_create_gstate','pdf_create_pvf',
+            'pdf_curveto','pdf_delete','pdf_delete_pvf','pdf_encoding_set_char',
+            'pdf_end_font','pdf_end_glyph','pdf_end_page','pdf_end_pattern',
+            'pdf_end_template','pdf_endpath','pdf_fill','pdf_fill_imageblock',
+            'pdf_fill_pdfblock','pdf_fill_stroke','pdf_fill_textblock',
+            'pdf_findfont','pdf_fit_image','pdf_fit_pdi_page',
+            'pdf_fit_textline','pdf_get_apiname','pdf_get_buffer',
+            'pdf_get_errmsg','pdf_get_errnum','pdf_get_parameter',
+            'pdf_get_pdi_parameter','pdf_get_pdi_value','pdf_get_value',
+            'pdf_initgraphics','pdf_lineto','pdf_load_font',
+            'pdf_load_iccprofile','pdf_load_image','pdf_makespotcolor',
+            'pdf_moveto','pdf_new','pdf_open_ccitt','pdf_open_file',
+            'pdf_open_image','pdf_open_image_file','pdf_open_pdi',
+            'pdf_open_pdi_page','pdf_place_image','pdf_place_pdi_page',
+            'pdf_process_pdi','pdf_rect','pdf_restore','pdf_rotate','pdf_save',
+            'pdf_scale','pdf_set_border_color','pdf_set_border_dash',
+            'pdf_set_border_style','pdf_set_gstate','pdf_set_info',
+            'pdf_set_parameter','pdf_set_text_pos','pdf_set_value',
+            'pdf_setcolor','pdf_setdash','pdf_setdashpattern','pdf_setflat',
+            'pdf_setfont','pdf_setlinecap','pdf_setlinejoin','pdf_setlinewidth',
+            'pdf_setmatrix','pdf_setmiterlimit','pdf_setpolydash','pdf_shading',
+            'pdf_shading_pattern','pdf_shfill','pdf_show','pdf_show_boxed',
+            'pdf_show_xy','pdf_skew','pdf_stringwidth','pdf_stroke',
+            'pdf_translate','pdo_drivers','pfsockopen','pg_affected_rows',
+            'pg_cancel_query','pg_clientencoding','pg_client_encoding',
+            'pg_close','pg_cmdtuples','pg_connect','pg_connection_busy',
+            'pg_connection_reset','pg_connection_status','pg_convert',
+            'pg_copy_from','pg_copy_to','pg_dbname','pg_delete','pg_end_copy',
+            'pg_errormessage','pg_escape_bytea','pg_escape_string','pg_exec',
+            'pg_execute','pg_fetch_all','pg_fetch_all_columns','pg_fetch_array',
+            'pg_fetch_assoc','pg_fetch_object','pg_fetch_result','pg_fetch_row',
+            'pg_fieldisnull','pg_fieldname','pg_fieldnum','pg_fieldprtlen',
+            'pg_fieldsize','pg_fieldtype','pg_field_is_null','pg_field_name',
+            'pg_field_num','pg_field_prtlen','pg_field_size','pg_field_table',
+            'pg_field_type','pg_field_type_oid','pg_free_result',
+            'pg_freeresult','pg_get_notify','pg_get_pid','pg_get_result',
+            'pg_getlastoid','pg_host','pg_insert','pg_last_error',
+            'pg_last_notice','pg_last_oid','pg_loclose','pg_locreate',
+            'pg_loexport','pg_loimport','pg_loopen','pg_loread','pg_loreadall',
+            'pg_lounlink','pg_lowrite','pg_lo_close','pg_lo_create',
+            'pg_lo_export','pg_lo_import','pg_lo_open','pg_lo_read',
+            'pg_lo_read_all','pg_lo_seek','pg_lo_tell','pg_lo_unlink',
+            'pg_lo_write','pg_meta_data','pg_numfields','pg_numrows',
+            'pg_num_fields','pg_num_rows','pg_options','pg_parameter_status',
+            'pg_pconnect','pg_ping','pg_port','pg_prepare','pg_put_line',
+            'pg_query','pg_query_params','pg_result','pg_result_error',
+            'pg_result_error_field','pg_result_seek','pg_result_status',
+            'pg_select','pg_send_execute','pg_send_prepare','pg_send_query',
+            'pg_send_query_params','pg_set_client_encoding',
+            'pg_set_error_verbosity','pg_setclientencoding','pg_trace',
+            'pg_transaction_status','pg_tty','pg_unescape_bytea','pg_untrace',
+            'pg_update','pg_version','php_egg_logo_guid','php_ini_loaded_file',
+            'php_ini_scanned_files','php_logo_guid','php_real_logo_guid',
+            'php_sapi_name','php_strip_whitespace','php_uname','phpcredits',
+            'phpdoc_xml_from_string','phpinfo','phpversion','pi','png2wbmp',
+            'pop3_close','pop3_delete_message','pop3_get_account_size',
+            'pop3_get_message','pop3_get_message_count',
+            'pop3_get_message_header','pop3_get_message_ids',
+            'pop3_get_message_size','pop3_get_message_sizes','pop3_open',
+            'pop3_undelete','popen','pos','posix_ctermid','posix_errno',
+            'posix_getcwd','posix_getegid','posix_geteuid','posix_getgid',
+            'posix_getgrgid','posix_getgrnam','posix_getgroups',
+            'posix_getlogin','posix_getpgid','posix_getpgrp','posix_getpid',
+            'posix_getppid','posix_getpwnam','posix_getpwuid','posix_getrlimit',
+            'posix_getsid','posix_getuid','posix_get_last_error','posix_isatty',
+            'posix_kill','posix_mkfifo','posix_setegid','posix_seteuid',
+            'posix_setgid','posix_setpgid','posix_setsid','posix_setuid',
+            'posix_strerror','posix_times','posix_ttyname','posix_uname','pow',
+            'preg_grep','preg_last_error','preg_match','preg_match_all',
+            'preg_quote','preg_replace','preg_replace_callback','preg_split',
+            'prev','print_r','printf','proc_close','proc_get_status',
+            'proc_open','proc_terminate','putenv','quoted_printable_decode',
+            'quotemeta','rad2deg','radius_acct_open','radius_add_server',
+            'radius_auth_open','radius_close','radius_config',
+            'radius_create_request','radius_cvt_addr','radius_cvt_int',
+            'radius_cvt_string','radius_demangle','radius_demangle_mppe_key',
+            'radius_get_attr','radius_get_vendor_attr','radius_put_addr',
+            'radius_put_attr','radius_put_int','radius_put_string',
+            'radius_put_vendor_addr','radius_put_vendor_attr',
+            'radius_put_vendor_int','radius_put_vendor_string',
+            'radius_request_authenticator','radius_send_request',
+            'radius_server_secret','radius_strerror','rand','range',
+            'rawurldecode','rawurlencode','read_exif_data','readdir','readfile',
+            'readgzfile','readlink','realpath','reg_close_key','reg_create_key',
+            'reg_enum_key','reg_enum_value','reg_get_value','reg_open_key',
+            'reg_set_value','register_shutdown_function',
+            'register_tick_function','rename','res_close','res_get','res_list',
+            'res_list_type','res_open','res_set','reset',
+            'restore_error_handler','restore_include_path','rewind','rewinddir',
+            'rmdir','round','rsort','rtrim','runkit_class_adopt',
+            'runkit_class_emancipate','runkit_constant_add',
+            'runkit_constant_redefine','runkit_constant_remove',
+            'runkit_default_property_add','runkit_function_add',
+            'runkit_function_copy','runkit_function_redefine',
+            'runkit_function_remove','runkit_function_rename','runkit_import',
+            'runkit_lint','runkit_lint_file','runkit_method_add',
+            'runkit_method_copy','runkit_method_redefine',
+            'runkit_method_remove','runkit_method_rename','runkit_object_id',
+            'runkit_return_value_used','runkit_sandbox_output_handler',
+            'runkit_superglobals','runkit_zval_inspect','scandir','sem_acquire',
+            'sem_get','sem_release','sem_remove','serialize',
+            'session_cache_expire','session_cache_limiter','session_commit',
+            'session_decode','session_destroy','session_encode',
+            'session_get_cookie_params','session_id','session_is_registered',
+            'session_module_name','session_name','session_regenerate_id',
+            'session_register','session_save_path','session_set_cookie_params',
+            'session_set_save_handler','session_start','session_unregister',
+            'session_unset','session_write_close','set_content',
+            'set_error_handler','set_file_buffer','set_include_path',
+            'set_magic_quotes_runtime','set_socket_blocking','set_time_limit',
+            'setcookie','setlocale','setrawcookie','settype','sha1','sha1_file',
+            'shell_exec','shmop_close','shmop_delete','shmop_open','shmop_read',
+            'shmop_size','shmop_write','shm_attach','shm_detach','shm_get_var',
+            'shm_put_var','shm_remove','shm_remove_var','show_source','shuffle',
+            'similar_text','simplexml_import_dom','simplexml_load_file',
+            'simplexml_load_string','sin','sinh','sizeof','sleep','smtp_close',
+            'smtp_cmd_data','smtp_cmd_mail','smtp_cmd_rcpt','smtp_connect',
+            'snmp_get_quick_print','snmp_get_valueretrieval','snmp_read_mib',
+            'snmp_set_quick_print','snmp_set_valueretrieval','snmp2_get',
+            'snmp2_getnext','snmp2_real_walk','snmp2_set','snmp2_walk',
+            'snmp3_get','snmp3_getnext','snmp3_real_walk','snmp3_set',
+            'snmp3_walk','snmpget','snmpgetnext','snmprealwalk','snmpset',
+            'snmpwalk','snmpwalkoid','socket_accept','socket_bind',
+            'socket_clear_error','socket_close','socket_connect',
+            'socket_create','socket_create_listen','socket_create_pair',
+            'socket_getopt','socket_getpeername','socket_getsockname',
+            'socket_get_option','socket_get_status','socket_iovec_add',
+            'socket_iovec_alloc','socket_iovec_delete','socket_iovec_fetch',
+            'socket_iovec_free','socket_iovec_set','socket_last_error',
+            'socket_listen','socket_read','socket_readv','socket_recv',
+            'socket_recvfrom','socket_recvmsg','socket_select','socket_send',
+            'socket_sendmsg','socket_sendto','socket_setopt','socket_set_block',
+            'socket_set_blocking','socket_set_nonblock','socket_set_option',
+            'socket_set_timeout','socket_shutdown','socket_strerror',
+            'socket_write','socket_writev','sort','soundex','spl_autoload',
+            'spl_autoload_call','spl_autoload_extensions',
+            'spl_autoload_functions','spl_autoload_register',
+            'spl_autoload_unregister','spl_classes','spl_object_hash','split',
+            'spliti','sprintf','sql_regcase','sqlite_array_query',
+            'sqlite_busy_timeout','sqlite_changes','sqlite_close',
+            'sqlite_column','sqlite_create_aggregate','sqlite_create_function',
+            'sqlite_current','sqlite_error_string','sqlite_escape_string',
+            'sqlite_exec','sqlite_factory','sqlite_fetch_all',
+            'sqlite_fetch_array','sqlite_fetch_column_types',
+            'sqlite_fetch_object','sqlite_fetch_single','sqlite_fetch_string',
+            'sqlite_field_name','sqlite_has_more','sqlite_has_prev',
+            'sqlite_last_error','sqlite_last_insert_rowid','sqlite_libencoding',
+            'sqlite_libversion','sqlite_next','sqlite_num_fields',
+            'sqlite_num_rows','sqlite_open','sqlite_popen','sqlite_prev',
+            'sqlite_query','sqlite_rewind','sqlite_seek','sqlite_single_query',
+            'sqlite_udf_decode_binary','sqlite_udf_encode_binary',
+            'sqlite_unbuffered_query','sqlite_valid','sqrt','srand','sscanf',
+            'ssh2_auth_hostbased_file','ssh2_auth_none','ssh2_auth_password',
+            'ssh2_auth_pubkey_file','ssh2_connect','ssh2_exec',
+            'ssh2_fetch_stream','ssh2_fingerprint','ssh2_forward_accept',
+            'ssh2_forward_listen','ssh2_methods_negotiated','ssh2_poll',
+            'ssh2_publickey_add','ssh2_publickey_init','ssh2_publickey_list',
+            'ssh2_publickey_remove','ssh2_scp_recv','ssh2_scp_send','ssh2_sftp',
+            'ssh2_sftp_lstat','ssh2_sftp_mkdir','ssh2_sftp_readlink',
+            'ssh2_sftp_realpath','ssh2_sftp_rename','ssh2_sftp_rmdir',
+            'ssh2_sftp_stat','ssh2_sftp_symlink','ssh2_sftp_unlink',
+            'ssh2_shell','ssh2_tunnel','stat','stats_absolute_deviation',
+            'stats_cdf_beta','stats_cdf_binomial','stats_cdf_cauchy',
+            'stats_cdf_chisquare','stats_cdf_exponential','stats_cdf_f',
+            'stats_cdf_gamma','stats_cdf_laplace','stats_cdf_logistic',
+            'stats_cdf_negative_binomial','stats_cdf_noncentral_chisquare',
+            'stats_cdf_noncentral_f','stats_cdf_noncentral_t',
+            'stats_cdf_normal','stats_cdf_poisson','stats_cdf_t',
+            'stats_cdf_uniform','stats_cdf_weibull','stats_covariance',
+            'stats_dens_beta','stats_dens_cauchy','stats_dens_chisquare',
+            'stats_dens_exponential','stats_dens_f','stats_dens_gamma',
+            'stats_dens_laplace','stats_dens_logistic','stats_dens_normal',
+            'stats_dens_pmf_binomial','stats_dens_pmf_hypergeometric',
+            'stats_dens_pmf_negative_binomial','stats_dens_pmf_poisson',
+            'stats_dens_t','stats_dens_uniform','stats_dens_weibull',
+            'stats_harmonic_mean','stats_kurtosis','stats_rand_gen_beta',
+            'stats_rand_gen_chisquare','stats_rand_gen_exponential',
+            'stats_rand_gen_f','stats_rand_gen_funiform','stats_rand_gen_gamma',
+            'stats_rand_gen_ipoisson','stats_rand_gen_iuniform',
+            'stats_rand_gen_noncenral_f','stats_rand_gen_noncentral_chisquare',
+            'stats_rand_gen_noncentral_t','stats_rand_gen_normal',
+            'stats_rand_gen_t','stats_rand_getsd','stats_rand_ibinomial',
+            'stats_rand_ibinomial_negative','stats_rand_ignlgi',
+            'stats_rand_phrase_to_seeds','stats_rand_ranf','stats_rand_setall',
+            'stats_skew','stats_standard_deviation','stats_stat_binomial_coef',
+            'stats_stat_correlation','stats_stat_factorial',
+            'stats_stat_independent_t','stats_stat_innerproduct',
+            'stats_stat_paired_t','stats_stat_percentile','stats_stat_powersum',
+            'stats_variance','strcasecmp','strchr','strcmp','strcoll','strcspn',
+            'stream_bucket_append','stream_bucket_make_writeable',
+            'stream_bucket_new','stream_bucket_prepend','stream_context_create',
+            'stream_context_get_default','stream_context_get_options',
+            'stream_context_set_default','stream_context_set_option',
+            'stream_context_set_params','stream_copy_to_stream',
+            'stream_encoding','stream_filter_append','stream_filter_prepend',
+            'stream_filter_register','stream_filter_remove',
+            'stream_get_contents','stream_get_filters','stream_get_line',
+            'stream_get_meta_data','stream_get_transports',
+            'stream_get_wrappers','stream_is_local',
+            'stream_notification_callback','stream_register_wrapper',
+            'stream_resolve_include_path','stream_select','stream_set_blocking',
+            'stream_set_timeout','stream_set_write_buffer',
+            'stream_socket_accept','stream_socket_client',
+            'stream_socket_enable_crypto','stream_socket_get_name',
+            'stream_socket_pair','stream_socket_recvfrom',
+            'stream_socket_sendto','stream_socket_server',
+            'stream_socket_shutdown','stream_supports_lock',
+            'stream_wrapper_register','stream_wrapper_restore',
+            'stream_wrapper_unregister','strftime','stripcslashes','stripos',
+            'stripslashes','strip_tags','stristr','strlen','strnatcasecmp',
+            'strnatcmp','strpbrk','strncasecmp','strncmp','strpos','strrchr',
+            'strrev','strripos','strrpos','strspn','strstr','strtok',
+            'strtolower','strtotime','strtoupper','strtr','strval',
+            'str_ireplace','str_pad','str_repeat','str_replace','str_rot13',
+            'str_split','str_shuffle','str_word_count','substr',
+            'substr_compare','substr_count','substr_replace','svn_add',
+            'svn_auth_get_parameter','svn_auth_set_parameter','svn_cat',
+            'svn_checkout','svn_cleanup','svn_client_version','svn_commit',
+            'svn_diff','svn_export','svn_fs_abort_txn','svn_fs_apply_text',
+            'svn_fs_begin_txn2','svn_fs_change_node_prop','svn_fs_check_path',
+            'svn_fs_contents_changed','svn_fs_copy','svn_fs_delete',
+            'svn_fs_dir_entries','svn_fs_file_contents','svn_fs_file_length',
+            'svn_fs_is_dir','svn_fs_is_file','svn_fs_make_dir',
+            'svn_fs_make_file','svn_fs_node_created_rev','svn_fs_node_prop',
+            'svn_fs_props_changed','svn_fs_revision_prop',
+            'svn_fs_revision_root','svn_fs_txn_root','svn_fs_youngest_rev',
+            'svn_import','svn_info','svn_log','svn_ls','svn_repos_create',
+            'svn_repos_fs','svn_repos_fs_begin_txn_for_commit',
+            'svn_repos_fs_commit_txn','svn_repos_hotcopy','svn_repos_open',
+            'svn_repos_recover','svn_status','svn_update','symlink',
+            'sys_get_temp_dir','syslog','system','tan','tanh','tempnam',
+            'textdomain','thread_get','thread_include','thread_lock',
+            'thread_lock_try','thread_mutex_destroy','thread_mutex_init',
+            'thread_set','thread_start','thread_unlock','tidy_access_count',
+            'tidy_clean_repair','tidy_config_count','tidy_diagnose',
+            'tidy_error_count','tidy_get_body','tidy_get_config',
+            'tidy_get_error_buffer','tidy_get_head','tidy_get_html',
+            'tidy_get_html_ver','tidy_get_output','tidy_get_release',
+            'tidy_get_root','tidy_get_status','tidy_getopt','tidy_is_xhtml',
+            'tidy_is_xml','tidy_parse_file','tidy_parse_string',
+            'tidy_repair_file','tidy_repair_string','tidy_warning_count','time',
+            'timezone_abbreviations_list','timezone_identifiers_list',
+            'timezone_name_from_abbr','timezone_name_get','timezone_offset_get',
+            'timezone_open','timezone_transitions_get','tmpfile',
+            'token_get_all','token_name','touch','trigger_error',
+            'transliterate','transliterate_filters_get','trim','uasort',
+            'ucfirst','ucwords','uksort','umask','uniqid','unixtojd','unlink',
+            'unpack','unregister_tick_function','unserialize','unset',
+            'urldecode','urlencode','user_error','use_soap_error_handler',
+            'usleep','usort','utf8_decode','utf8_encode','var_dump',
+            'var_export','variant_abs','variant_add','variant_and',
+            'variant_cast','variant_cat','variant_cmp',
+            'variant_date_from_timestamp','variant_date_to_timestamp',
+            'variant_div','variant_eqv','variant_fix','variant_get_type',
+            'variant_idiv','variant_imp','variant_int','variant_mod',
+            'variant_mul','variant_neg','variant_not','variant_or',
+            'variant_pow','variant_round','variant_set','variant_set_type',
+            'variant_sub','variant_xor','version_compare','virtual','vfprintf',
+            'vprintf','vsprintf','wddx_add_vars','wddx_deserialize',
+            'wddx_packet_end','wddx_packet_start','wddx_serialize_value',
+            'wddx_serialize_vars','win_beep','win_browse_file',
+            'win_browse_folder','win_create_link','win_message_box',
+            'win_play_wav','win_shell_execute','win32_create_service',
+            'win32_delete_service','win32_get_last_control_message',
+            'win32_ps_list_procs','win32_ps_stat_mem','win32_ps_stat_proc',
+            'win32_query_service_status','win32_scheduler_delete_task',
+            'win32_scheduler_enum_tasks','win32_scheduler_get_task_info',
+            'win32_scheduler_run','win32_scheduler_set_task_info',
+            'win32_set_service_status','win32_start_service',
+            'win32_start_service_ctrl_dispatcher','win32_stop_service',
+            'wordwrap','xml_error_string','xml_get_current_byte_index',
+            'xml_get_current_column_number','xml_get_current_line_number',
+            'xml_get_error_code','xml_parse','xml_parser_create',
+            'xml_parser_create_ns','xml_parser_free','xml_parser_get_option',
+            'xml_parser_set_option','xml_parse_into_struct',
+            'xml_set_character_data_handler','xml_set_default_handler',
+            'xml_set_element_handler','xml_set_end_namespace_decl_handler',
+            'xml_set_external_entity_ref_handler',
+            'xml_set_notation_decl_handler','xml_set_object',
+            'xml_set_processing_instruction_handler',
+            'xml_set_start_namespace_decl_handler',
+            'xml_set_unparsed_entity_decl_handler','xmldoc','xmldocfile',
+            'xmlrpc_decode','xmlrpc_decode_request','xmlrpc_encode',
+            'xmlrpc_encode_request','xmlrpc_get_type','xmlrpc_is_fault',
+            'xmlrpc_parse_method_descriptions',
+            'xmlrpc_server_add_introspection_data','xmlrpc_server_call_method',
+            'xmlrpc_server_create','xmlrpc_server_destroy',
+            'xmlrpc_server_register_introspection_callback',
+            'xmlrpc_server_register_method','xmlrpc_set_type','xmltree',
+            'xmlwriter_end_attribute','xmlwriter_end_cdata',
+            'xmlwriter_end_comment','xmlwriter_end_document',
+            'xmlwriter_end_dtd','xmlwriter_end_dtd_attlist',
+            'xmlwriter_end_dtd_element','xmlwriter_end_dtd_entity',
+            'xmlwriter_end_element','xmlwriter_end_pi','xmlwriter_flush',
+            'xmlwriter_full_end_element','xmlwriter_open_memory',
+            'xmlwriter_open_uri','xmlwriter_output_memory',
+            'xmlwriter_set_indent','xmlwriter_set_indent_string',
+            'xmlwriter_start_attribute','xmlwriter_start_attribute_ns',
+            'xmlwriter_start_cdata','xmlwriter_start_comment',
+            'xmlwriter_start_document','xmlwriter_start_dtd',
+            'xmlwriter_start_dtd_attlist','xmlwriter_start_dtd_element',
+            'xmlwriter_start_dtd_entity','xmlwriter_start_element',
+            'xmlwriter_start_element_ns','xmlwriter_start_pi','xmlwriter_text',
+            'xmlwriter_write_attribute','xmlwriter_write_attribute_ns',
+            'xmlwriter_write_cdata','xmlwriter_write_comment',
+            'xmlwriter_write_dtd','xmlwriter_write_dtd_attlist',
+            'xmlwriter_write_dtd_element','xmlwriter_write_dtd_entity',
+            'xmlwriter_write_element','xmlwriter_write_element_ns',
+            'xmlwriter_write_pi','xmlwriter_write_raw','xpath_eval',
+            'xpath_eval_expression','xpath_new_context','xpath_register_ns',
+            'xpath_register_ns_auto','xptr_eval','xptr_new_context','yp_all',
+            'yp_cat','yp_errno','yp_err_string','yp_first',
+            'yp_get_default_domain','yp_master','yp_match','yp_next','yp_order',
+            'zend_current_obfuscation_level','zend_get_cfg_var','zend_get_id',
+            'zend_loader_current_file','zend_loader_enabled',
+            'zend_loader_file_encoded','zend_loader_file_licensed',
+            'zend_loader_install_license','zend_loader_version',
+            'zend_logo_guid','zend_match_hostmasks','zend_obfuscate_class_name',
+            'zend_obfuscate_function_name','zend_optimizer_version',
+            'zend_runtime_obfuscate','zend_version','zip_close',
+            'zip_entry_close','zip_entry_compressedsize',
+            'zip_entry_compressionmethod','zip_entry_filesize','zip_entry_name',
+            'zip_entry_open','zip_entry_read','zip_open','zip_read',
+            'zlib_get_coding_type'
+            ),
+        4 => array(
+            'DEFAULT_INCLUDE_PATH', 'DIRECTORY_SEPARATOR', 'E_ALL',
+            'E_COMPILE_ERROR', 'E_COMPILE_WARNING', 'E_CORE_ERROR',
+            'E_CORE_WARNING', 'E_ERROR', 'E_NOTICE', 'E_PARSE', 'E_STRICT',
+            'E_USER_ERROR', 'E_USER_NOTICE', 'E_USER_WARNING', 'E_WARNING',
+            'ENT_COMPAT','ENT_QUOTES','ENT_NOQUOTES',
+            'false', 'null', 'PEAR_EXTENSION_DIR', 'PEAR_INSTALL_DIR',
+            'PHP_BINDIR', 'PHP_CONFIG_FILE_PATH', 'PHP_DATADIR',
+            'PHP_EXTENSION_DIR', 'PHP_LIBDIR',
+            'PHP_LOCALSTATEDIR', 'PHP_OS',
+            'PHP_OUTPUT_HANDLER_CONT', 'PHP_OUTPUT_HANDLER_END',
+            'PHP_OUTPUT_HANDLER_START', 'PHP_SYSCONFDIR',
+            'PHP_VERSION', 'true', '__CLASS__', '__FILE__', '__FUNCTION__',
+            '__LINE__', '__METHOD__'
+            )
+        ),
+    'SYMBOLS' => array(
+        1 => array(
+            '<%', '<%=', '%>', '<?', '<?=', '?>'
+            ),
+        0 => array(
+            '(', ')', '[', ']', '{', '}',
+            '!', '@', '%', '&', '|', '/',
+            '<', '>',
+            '=', '-', '+', '*',
+            '.', ':', ',', ';'
+            )
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #990000;',
+            4 => 'color: #009900; font-weight: bold;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #666666; font-style: italic;',
+            2 => 'color: #666666; font-style: italic;',
+            3 => 'color: #0000cc; font-style: italic;',
+            4 => 'color: #009933; font-style: italic;',
+            'MULTI' => 'color: #666666; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;',
+            1 => 'color: #000099; font-weight: bold;',
+            2 => 'color: #660099; font-weight: bold;',
+            3 => 'color: #660099; font-weight: bold;',
+            4 => 'color: #006699; font-weight: bold;',
+            5 => 'color: #006699; font-weight: bold; font-style: italic;',
+            6 => 'color: #009933; font-weight: bold;',
+            'HARD' => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #009900;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #0000ff;',
+            'HARD' => 'color: #0000ff;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;',
+            GESHI_NUMBER_OCT_PREFIX => 'color: #208080;',
+            GESHI_NUMBER_HEX_PREFIX => 'color: #208080;',
+            GESHI_NUMBER_FLT_SCI_ZERO => 'color:#800080;',
+            ),
+        'METHODS' => array(
+            1 => 'color: #004000;',
+            2 => 'color: #004000;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #339933;',
+            1 => 'color: #000000; font-weight: bold;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #000088;'
+            ),
+        'SCRIPT' => array(
+            0 => '',
+            1 => '',
+            2 => '',
+            3 => '',
+            4 => '',
+            5 => ''
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => 'http://www.php.net/{FNAMEL}',
+        4 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '-&gt;',
+        2 => '::'
+        ),
+    'REGEXPS' => array(
+        //Variables
+        0 => "[\\$]{1,2}[a-zA-Z_][a-zA-Z0-9_]*"
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_MAYBE,
+    'SCRIPT_DELIMITERS' => array(
+        0 => array(
+            '<?php' => '?>'
+            ),
+        1 => array(
+            '<?' => '?>'
+            ),
+        2 => array(
+            '<%' => '%>'
+            ),
+        3 => array(
+            '<script language="php">' => '</script>'
+            ),
+        4 => "/(<\?(?:php)?)(?:'(?:[^'\\\\]|\\\\.)*?'|\"(?:[^\"\\\\]|\\\\.)*?\"|\/\*(?!\*\/).*?\*\/|.)*?(\?>|\Z)/sm",
+        5 => "/(<%)(?:'(?:[^'\\\\]|\\\\.)*?'|\"(?:[^\"\\\\]|\\\\.)*?\"|\/\*(?!\*\/).*?\*\/|.)*?(%>|\Z)/sm"
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        0 => true,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true,
+        5 => true
+        ),
+    'TAB_WIDTH' => 4
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/pic16.php b/examples/includes/geshi/geshi/pic16.php
new file mode 100644 (file)
index 0000000..2679788
--- /dev/null
@@ -0,0 +1,141 @@
+<?php
+/*************************************************************************************
+ * pic16.php
+ * -------
+ * Author: Phil Mattison (mattison@ohmikron.com)
+ * Copyright: (c) 2008 Ohmikron Corp. (http://www.ohmikron.com/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/07/30
+ *
+ * PIC16 Assembler language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/07/30 (1.0.8)
+ *   -  First Release
+ *
+ * TODO (updated 2008/07/30)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *   This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'PIC16',
+    'COMMENT_SINGLE' => array(1 => ';'),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        /*Instructions*/
+        1 => array(
+            'addcf','adddcf','addlw','addwf','andlw','andwf','bc','bcf','bdc',
+            'bnc','bndc','bnz','bsf','btfsc','btfss','bz','call','clrc','clrdc',
+            'clrf','clrw','clrwdt','clrz','comf','decf','goto','incf','incfsz',
+            'iorlw','iorwf','lcall','lgoto','movf','movfw','movlw','movwf',
+            'option','negf','nop','retfie','retlw','return','rlf','rrf','setc',
+            'setdc','setz','skpc','skpdc','skpnc','skpndc','skpnz','skpz',
+            'sleep','subcf','subdcf','sublw','subwf','swapf','tris','tstf',
+            'xorlw','xorwf'
+            ),
+        /*Registers*/
+        2 => array(
+            'INDF','TMR0','OPTION','PCL','STATUS','FSR','PORTA','PORTB','PORTC',
+            'PORTD','PORTE','PORTF','TRISA','TRISB','TRISC','TRISD','TRISE',
+            'TRISF','PCLATH','INTCON','PIR1','PIE1','PCON','CMCON','VRCON',
+            'F','W'
+            ),
+        /*Directives*/
+        3 => array(
+            '_BADRAM','BANKISEL','BANKSEL','CBLOCK','CODE','_CONFIG','CONSTANT',
+            'DA','DATA','DB','DE','#DEFINE','DT','DW','ELSE','END','ENDC',
+            'ENDIF','ENDM','ENDW','EQU','ERROR','ERRORLEVEL','EXITM','EXPAND',
+            'EXTERN','FILL','GLOBAL','IDATA','_IDLOCS','IF','IFDEF','IFNDEF',
+            'INCLUDE','#INCLUDE','LIST','LOCAL','MACRO','_MAXRAM','MESSG',
+            'NOEXPAND','NOLIST','ORG','PAGE','PAGESEL','PROCESSOR','RADIX',
+            'RES','SET','SPACE','SUBTITLE','TITLE','UDATA','UDATA_ACS',
+            'UDATA_OVR','UDATA_SHR','#UNDEFINE','VARIABLE','WHILE',
+            'D','H','O','B','A'
+            ),
+        ),
+    'SYMBOLS' => array('=','.',',',':'),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0000a0; font-weight: bold;',
+            2 => 'color: #aa3300; font-weight: bold;',
+            3 => 'color: #0000ff;',
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #00a000;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #0000ff;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff7700;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #ff7700;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #7777ff;'
+            ),
+        'REGEXPS' => array(),
+        'SCRIPT' => array()
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(),
+    'NUMBERS' =>
+        GESHI_NUMBER_INT_BASIC |
+        GESHI_NUMBER_BIN_SUFFIX |
+        GESHI_NUMBER_HEX_PREFIX |
+        GESHI_NUMBER_HEX_SUFFIX,
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(),
+    'HIGHLIGHT_STRICT_BLOCK' => array(),
+    'TAB_WIDTH' => 4,
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            'DISALLOWED_BEFORE' => "a-zA-Z0-9\$_\|\#>|^",
+            'DISALLOWED_AFTER' => "a-zA-Z0-9_<\|%"
+            )
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/pixelbender.php b/examples/includes/geshi/geshi/pixelbender.php
new file mode 100644 (file)
index 0000000..93da0df
--- /dev/null
@@ -0,0 +1,176 @@
+<?php
+/*************************************************************************************
+ * pixelbender.php
+ * ----------------
+ * Author: Richard Olsson (r@richardolsson.se)
+ * Copyright: (c) 2008 Richard Olsson (richardolsson.se)
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/11/16
+ *
+ * Pixel Bender 1.0 language file for GeSHi.
+ *
+ *
+ * Please feel free to modify this file, although I would greatly appreciate
+ * it if you would then send some feedback on why the file needed to be
+ * changed, using the e-mail address above.
+ *
+ *
+ * The colors are inspired by those used in the Pixel Bender Toolkit, with
+ * some slight modifications.
+ *
+ * For more info on Pixel Bender, see the Adobe Labs Wiki article at
+ * http://labs.adobe.com/wiki/index.php/Pixel_Bender_Toolkit.
+ *
+ * Keyword groups are defined as follows (groups marked with an asterisk
+ * inherit their names from terminology used in the language specification
+ * included with the Pixel Bender Toolkit, see URL above.)
+ *
+ *  1. languageVersion & kernel keywords
+ *  2. Kernel Members *
+ *  3. Types *
+ *  4. Statements * & qualifiers (in, out, inout)
+ *  5. Built-in functions *
+ *  6. Meta-data names
+ *  7. Preprocessor & Pre-defined symbols *
+ *
+ *
+ * CHANGES
+ * -------
+ * 2008/11/16 (1.0.8.2)
+ *  - Initial release
+ *
+ * TODO (updated 2008/11/16)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array(
+    'LANG_NAME' => 'Pixel Bender 1.0',
+    'COMMENT_SINGLE' => array(1 => '//'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'languageVersion', 'kernel'
+            ),
+        2 => array(
+            'import', 'parameter', 'dependent', 'const', 'input', 'output',
+            'evaluatePixel', 'evaluateDependents', 'needed', 'changed', 'generated'
+            ),
+        3 => array(
+            'bool', 'bool2', 'bool3', 'bool4', 'int', 'int2', 'int3', 'int4',
+            'float', 'float2', 'float3', 'float4', 'float2x2', 'float3x3', 'float4x4',
+            'pixel2', 'pixel3', 'pixel4', 'region', 'image1', 'image2', 'image3', 'image4',
+            'imageRef', 'void'
+            ),
+        4 => array(
+            'in', 'out', 'inout', 'if', 'else', 'for', 'while', 'do', 'break',
+            'continue', 'return'
+            ),
+        5 => array(
+            'radians', 'degrees', 'sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'pow',
+            'exp', 'exp2', 'log', 'log2', 'sqrt', 'inverseSqrt', 'abs', 'sign', 'floor',
+            'ceil', 'fract', 'mod', 'min', 'max', 'step', 'clamp', 'mix', 'smoothStep',
+            'length', 'distance', 'dot', 'cross', 'normalize', 'matrixCompMult', 'lessThan',
+            'lessThanEqual', 'greaterThan', 'greaterThanEqual', 'equal', 'notEqual', 'any',
+            'all', 'not', 'nowhere', 'everywhere', 'transform', 'union', 'intersect',
+            'outset', 'inset', 'bounds', 'isEmpty', 'sample', 'sampleLinear', 'sampleNearest',
+            'outCoord', 'dod', 'pixelSize', 'pixelAspectRatio'
+            ),
+        6 => array(
+            'namespace', 'vendor', 'version', 'minValue', 'maxValue', 'defaultValue', 'description'
+            ),
+        7 => array(
+            '#if', '#endif', '#ifdef', '#elif', 'defined', '#define',
+            'AIF_ATI', 'AIF_NVIDIA', 'AIF_FLASH_TARGET'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}', '!', '%', '&', '|', '+', '-', '*', '/', '=', '<', '>', '?', ':'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true,
+        5 => true,
+        6 => true,
+        7 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0033ff;',
+            2 => 'color: #0033ff; font-weight: bold;',
+            3 => 'color: #0033ff;',
+            4 => 'color: #9900cc; font-weight: bold;',
+            5 => 'color: #333333;',
+            6 => 'color: #666666;',
+            7 => 'color: #990000;',
+        ),
+        'COMMENTS' => array(
+            1 => 'color: #009900;',
+            'MULTI' => 'color: #3f5fbf;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => ''
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000000;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #990000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #000000; font-weight:bold;'
+            ),
+        'METHODS' => array(
+            0 => 'color: #000000;',
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000000; font-weight: bold;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => '',
+        5 => '',
+        6 => '',
+        7 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array('.'),
+    'REGEXPS' => array(),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(),
+    'HIGHLIGHT_STRICT_BLOCK' => array()
+);
+
+
+?>
diff --git a/examples/includes/geshi/geshi/plsql.php b/examples/includes/geshi/geshi/plsql.php
new file mode 100644 (file)
index 0000000..2f3a2b6
--- /dev/null
@@ -0,0 +1,256 @@
+<?php
+/*************************************************************************************
+ * plsql.php
+ * -------
+ * Author: Victor Engmark <victor.engmark@gmail.com>
+ * Copyright: (c) 2006 Victor Engmark (http://l0b0.net/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2006/10/26
+ *
+ * Oracle 9.2 PL/SQL language file for GeSHi.
+ * Formatting is based on the default setup of TOAD 8.6.
+ *
+ * CHANGES
+ * -------
+ * 2006/10/27 (1.0.0)
+ *    -    First Release
+ *
+ * TODO (updated 2006/10/27)
+ * -------------------------
+ * * Add < and > to brackets
+ * * Remove symbols which are also comment delimiters / quote marks?
+ *
+ *************************************************************************************
+ *
+ *         This file is part of GeSHi.
+ *
+ *     GeSHi 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.
+ *
+ *     GeSHi 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 GeSHi; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA    02111-1307    USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'PL/SQL',
+    'COMMENT_SINGLE' => array(1 =>'--'), //http://download-uk.oracle.com/docs/cd/B10501_01/appdev.920/a96624/02_funds.htm#2930
+    'COMMENT_MULTI' => array('/*' => '*/'), //http://download-uk.oracle.com/docs/cd/B10501_01/appdev.920/a96624/02_funds.htm#2950
+    'CASE_KEYWORDS' => GESHI_CAPS_UPPER,
+    'QUOTEMARKS' => array("'", '"'), //http://download-uk.oracle.com/docs/cd/B10501_01/appdev.920/a96624/02_funds.htm
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        //PL/SQL reserved keywords (http://download-uk.oracle.com/docs/cd/B10501_01/appdev.920/a96624/f_words.htm#LNPLS019)
+        1 => array('ZONE', 'YEAR', 'WRITE', 'WORK', 'WITH', 'WHILE', 'WHERE',
+        'WHENEVER', 'WHEN', 'VIEW', 'VARCHAR2', 'VARCHAR', 'VALUES',
+        'VALIDATE', 'USE', 'UPDATE', 'UNIQUE', 'UNION', 'TYPE', 'TRUE',
+        'TRIGGER', 'TO', 'TIMEZONE_REGION', 'TIMEZONE_MINUTE', 'TIMEZONE_HOUR',
+        'TIMEZONE_ABBR', 'TIMESTAMP', 'TIME', 'THEN', 'TABLE', 'SYNONYM',
+        'SUCCESSFUL', 'SUBTYPE', 'START', 'SQLERRM', 'SQLCODE', 'SQL', 'SPACE',
+        'SMALLINT', 'SHARE', 'SET', 'SEPARATE', 'SELECT', 'SECOND',
+        'SAVEPOINT', 'ROWTYPE', 'ROWNUM', 'ROWID', 'ROW', 'ROLLBACK',
+        'REVERSE', 'RETURN', 'RELEASE', 'RECORD', 'REAL', 'RAW', 'RANGE',
+        'RAISE', 'PUBLIC', 'PROCEDURE', 'PRIVATE', 'PRIOR', 'PRAGMA',
+        'POSITIVEN', 'POSITIVE', 'PLS_INTEGER', 'PCTFREE', 'PARTITION',
+        'PACKAGE', 'OUT', 'OTHERS', 'ORGANIZATION', 'ORDER', 'OR', 'OPTION',
+        'OPERATOR', 'OPEN', 'OPAQUE', 'ON', 'OF', 'OCIROWID', 'NUMBER_BASE',
+        'NUMBER', 'NULL', 'NOWAIT', 'NOT', 'NOCOPY', 'NEXTVAL', 'NEW',
+        'NATURALN', 'NATURAL', 'MONTH', 'MODE', 'MLSLABEL', 'MINUTE', 'MINUS',
+        'LOOP', 'LONG', 'LOCK', 'LIMITED', 'LIKE', 'LEVEL', 'JAVA',
+        'ISOLATION', 'IS', 'INTO', 'INTERVAL', 'INTERSECT', 'INTERFACE',
+        'INTEGER', 'INSERT', 'INDICATOR', 'INDEX', 'IN', 'IMMEDIATE', 'IF',
+        'HOUR', 'HEAP', 'HAVING', 'GROUP', 'GOTO', 'FUNCTION', 'FROM',
+        'FORALL', 'FOR', 'FLOAT', 'FETCH', 'FALSE', 'EXTENDS', 'EXIT',
+        'EXISTS', 'EXECUTE', 'EXCLUSIVE', 'EXCEPTION', 'END', 'ELSIF', 'ELSE',
+        'DROP', 'DO', 'DISTINCT', 'DESC', 'DELETE', 'DEFAULT', 'DECLARE',
+        'DECIMAL', 'DAY', 'DATE', 'CURSOR', 'CURRVAL', 'CURRENT', 'CREATE',
+        'CONSTANT', 'CONNECT', 'COMPRESS', 'COMMIT', 'COMMENT', 'COLLECT',
+        'CLUSTER', 'CLOSE', 'CHECK', 'CHAR_BASE', 'CHAR', 'CASE', 'BY', 'BULK',
+        'BOOLEAN', 'BODY', 'BINARY_INTEGER', 'BETWEEN', 'BEGIN', 'AUTHID',
+        'AT', 'ASC', 'AS', 'ARRAY', 'ANY', 'AND', 'ALTER', 'ALL'),
+        //SQL functions (http://download-uk.oracle.com/docs/cd/B10501_01/server.920/a96540/toc.htm & http://download-uk.oracle.com/docs/cd/B10501_01/server.920/a96540/functions101a.htm#85925)
+        2 => array('XMLTRANSFORM', 'XMLSEQUENCE', 'XMLFOREST', 'XMLELEMENT',
+        'XMLCONCAT', 'XMLCOLATTVAL', 'XMLAGG', 'WIDTH_BUCKET', 'VSIZE',
+        'VARIANCE', 'VAR_SAMP', 'VAR_POP', 'VALUE', 'USERENV', 'USER', 'UPPER',
+        'UPDATEXML', 'UNISTR', 'UID', 'TZ_OFFSET', 'TRUNC', 'TRIM', 'TREAT',
+        'TRANSLATE', 'TO_YMINTERVAL', 'TO_TIMESTAMP_TZ', 'TO_TIMESTAMP',
+        'TO_SINGLE_BYTE', 'TO_NUMBER', 'TO_NCLOB', 'TO_NCHAR', 'TO_MULTI_BYTE',
+        'TO_LOB', 'TO_DSINTERVAL', 'TO_DATE', 'TO_CLOB', 'TO_CHAR', 'TANH',
+        'TAN', 'SYSTIMESTAMP', 'SYSDATE', 'SYS_XMLGEN', 'SYS_XMLAGG',
+        'SYS_TYPEID', 'SYS_GUID', 'SYS_EXTRACT_UTC', 'SYS_DBURIGEN',
+        'SYS_CONTEXT', 'SYS_CONNECT_BY_PATH', 'SUM', 'SUBSTR', 'STDDEV_SAMP',
+        'STDDEV_POP', 'STDDEV', 'SQRT', 'SOUNDEX', 'SINH', 'SIN', 'SIGN',
+        'SESSIONTIMEZONE', 'RTRIM', 'RPAD', 'ROWIDTONCHAR', 'ROWIDTOCHAR',
+        'ROW_NUMBER', 'ROUND', 'REPLACE', 'REGR_SYY', 'REGR_SXY', 'REGR_SXX',
+        'REGR_SLOPE', 'REGR_R2', 'REGR_INTERCEPT', 'REGR_COUNT', 'REGR_AVGY',
+        'REGR_AVGX', 'REFTOHEX', 'REF', 'RAWTONHEX', 'RAWTOHEX',
+        'RATIO_TO_REPORT', 'RANK', 'POWER', 'PERCENTILE_DISC',
+        'PERCENTILE_CONT', 'PERCENT_RANK', 'PATH', 'NVL2', 'NVL',
+        'NUMTOYMINTERVAL', 'NUMTODSINTERVAL', 'NULLIF', 'NTILE', 'NLSSORT',
+        'NLS_UPPER', 'NLS_LOWER', 'NLS_INITCAP', 'NLS_CHARSET_NAME',
+        'NLS_CHARSET_ID', 'NLS_CHARSET_DECL_LEN', 'NEXT_DAY', 'NEW_TIME',
+        'NCHR', 'MONTHS_BETWEEN', 'MOD', 'MIN', 'MAX', 'MAKE_REF', 'LTRIM',
+        'LPAD', 'LOWER', 'LOG', 'LOCALTIMESTAMP', 'LN', 'LENGTH', 'LEAST',
+        'LEAD', 'LAST_VALUE', 'LAST_DAY', 'LAST', 'LAG', 'INSTR', 'INITCAP',
+        'HEXTORAW', 'GROUPING_ID', 'GROUPING', 'GROUP_ID', 'GREATEST',
+        'FROM_TZ', 'FLOOR', 'FIRST_VALUE', 'FIRST', 'EXTRACTVALUE', 'EXTRACT',
+        'EXP', 'EXISTSNODE', 'EMPTY_CLOB', 'EMPTY_BLOB', 'DUMP', 'DEREF',
+        'DEPTH', 'DENSE_RANK', 'DECOMPOSE', 'DECODE', 'DBTIMEZONE',
+        'CURRENT_TIMESTAMP', 'CURRENT_DATE', 'CUME_DIST', 'COVAR_SAMP',
+        'COVAR_POP', 'COUNT', 'COSH', 'COS', 'CORR', 'CONVERT', 'CONCAT',
+        'COMPOSE', 'COALESCE', 'CHR', 'CHARTOROWID', 'CEIL', 'CAST', 'BITAND',
+        'BIN_TO_NUM', 'BFILENAME', 'AVG', 'ATAN2', 'ATAN', 'ASIN', 'ASCIISTR',
+        'ASCII', 'ADD_MONTHS', 'ACOS', 'ABS'),
+        //PL/SQL packages (http://download-uk.oracle.com/docs/cd/B10501_01/appdev.920/a96612/intro2.htm#1025672)
+        3 => array('UTL_URL', 'UTL_TCP', 'UTL_SMTP', 'UTL_REF', 'UTL_RAW',
+        'UTL_PG', 'UTL_INADDR', 'UTL_HTTP', 'UTL_FILE', 'UTL_ENCODE',
+        'UTL_COLL', 'SDO_UTIL', 'SDO_TUNE', 'SDO_MIGRATE', 'SDO_LRS',
+        'SDO_GEOM', 'SDO_CS', 'DMBS_XMLQUERY', 'DMBS_FLASHBACK',
+        'DMBS_DEFER_SYS', 'DEBUG_EXTPROC', 'DBMS_XSLPROCESSOR', 'DBMS_XPLAN',
+        'DBMS_XMLSCHEMA', 'DBMS_XMLSAVE', 'DBMS_XMLPARSER', 'DBMS_XMLGEN',
+        'DBMS_XMLDOM', 'DBMS_XDBT', 'DBMS_XDB_VERSION', 'DBMS_XDB', 'DBMS_WM',
+        'DBMS_UTILITY', 'DBMS_TYPES', 'DBMS_TTS', 'DBMS_TRANSFORM',
+        'DBMS_TRANSACTION', 'DBMS_TRACE', 'DBMS_STRM_A', 'DBMS_STRM',
+        'DBMS_STORAGE_MAP', 'DBMS_STATS', 'DBMS_SQL', 'DBMS_SPACE_ADMIN',
+        'DBMS_SPACE', 'DBMS_SHARED_POOL', 'DBMS_SESSION', 'DBMS_RULE_ADM',
+        'DBMS_RULE', 'DBMS_ROWID', 'DBMS_RLS', 'DBMS_RESUMABLE',
+        'DBMS_RESOURCE_MANAGER_PRIVS', 'DBMS_RESOURCE_MANAGER', 'DBMS_REPUTIL',
+        'DBMS_REPCAT_RGT', 'DBMS_REPCAT_INSTATIATE', 'DBMS_REPCAT_ADMIN',
+        'DBMS_REPCAT', 'DBMS_REPAIR', 'DBMS_REFRESH', 'DBMS_REDEFINITION',
+        'DBMS_RECTIFIER_DIFF', 'DBMS_RANDOM', 'DBMS_PROPAGATION_ADM',
+        'DBMS_PROFILER', 'DBMS_PIPE', 'DBMS_PCLXUTIL', 'DBMS_OUTPUT',
+        'DBMS_OUTLN_EDIT', 'DBMS_OUTLN', 'DBMS_ORACLE_TRACE_USER',
+        'DBMS_ORACLE_TRACE_AGENT', 'DBMS_OLAP', 'DBMS_OFFLINE_SNAPSHOT',
+        'DBMS_OFFLINE_OG', 'DBMS_ODCI', 'DBMS_OBFUSCATION_TOOLKIT',
+        'DBMS_MVIEW', 'DBMS_MGWMSG', 'DBMS_MGWADM', 'DBMS_METADATA',
+        'DBMS_LOGSTDBY', 'DBMS_LOGMNR_D', 'DBMS_LOGMNR_CDC_SUBSCRIBE',
+        'DBMS_LOGMNR_CDC_PUBLISH', 'DBMS_LOGMNR', 'DBMS_LOCK', 'DBMS_LOB',
+        'DBMS_LIBCACHE', 'DBMS_LDAP', 'DBMS_JOB', 'DBMS_IOT',
+        'DBMS_HS_PASSTHROUGH', 'DBMS_FGA', 'DBMS_DISTRIBUTED_TRUST_ADMIN',
+        'DBMS_DESCRIBE', 'DBMS_DEFER_QUERY', 'DBMS_DEFER', 'DBMS_DEBUG',
+        'DBMS_DDL', 'DBMS_CAPTURE_ADM', 'DBMS_AW', 'DBMS_AQELM', 'DBMS_AQADM',
+        'DBMS_AQ', 'DBMS_APPLY_ADM', 'DBMS_APPLICATION_INFO', 'DBMS_ALERT',
+        'CWM2_OLAP_AW_ACCESS'),
+        //PL/SQL predefined exceptions (http://download-uk.oracle.com/docs/cd/B10501_01/appdev.920/a96624/07_errs.htm#784)
+        4 => array('ZERO_DIVIDE', 'VALUE_ERROR', 'TOO_MANY_ROWS',
+        'TIMEOUT_ON_RESOURCE', 'SYS_INVALID_ROWID', 'SUBSCRIPT_OUTSIDE_LIMIT',
+        'SUBSCRIPT_BEYOND_COUNT', 'STORAGE_ERROR', 'SELF_IS_NULL',
+        'ROWTYPE_MISMATCH', 'PROGRAM_ERROR', 'NOT_LOGGED_ON', 'NO_DATA_FOUND',
+        'LOGIN_DENIED', 'INVALID_NUMBER', 'INVALID_CURSOR', 'DUP_VAL_ON_INDEX',
+        'CURSOR_ALREADY_OPEN', 'COLLECTION_IS_NULL', 'CASE_NOT_FOUND',
+        'ACCESS_INTO_NULL'),
+        //Static data dictionary views (http://download-uk.oracle.com/docs/cd/B10501_01/server.920/a96536/ch2.htm)
+        5 => array('USER_REPSITES', 'USER_REPSCHEMA',
+        'USER_REPRESOLUTION_STATISTICS', 'USER_REPRESOLUTION_METHOD',
+        'USER_REPRESOLUTION', 'USER_REPRESOL_STATS_CONTROL', 'USER_REPPROP',
+        'USER_REPPRIORITY_GROUP', 'USER_REPPRIORITY',
+        'USER_REPPARAMETER_COLUMN', 'USER_REPOBJECT', 'USER_REPKEY_COLUMNS',
+        'USER_REPGROUPED_COLUMN', 'USER_REPGROUP_PRIVILEGES', 'USER_REPGROUP',
+        'USER_REPGENOBJECTS', 'USER_REPGENERATED', 'USER_REPFLAVORS',
+        'USER_REPFLAVOR_OBJECTS', 'USER_REPFLAVOR_COLUMNS', 'USER_REPDDL',
+        'USER_REPCONFLICT', 'USER_REPCOLUMN_GROUP', 'USER_REPCOLUMN',
+        'USER_REPCATLOG', 'USER_REPCAT_USER_PARM_VALUES',
+        'USER_REPCAT_USER_AUTHORIZATIONS', 'USER_REPCAT_TEMPLATE_SITES',
+        'USER_REPCAT_TEMPLATE_PARMS', 'USER_REPCAT_TEMPLATE_OBJECTS',
+        'USER_REPCAT_REFRESH_TEMPLATES', 'USER_REPCAT', 'USER_REPAUDIT_COLUMN',
+        'USER_REPAUDIT_ATTRIBUTE', 'DBA_REPSITES_NEW', 'DBA_REPSITES',
+        'DBA_REPSCHEMA', 'DBA_REPRESOLUTION_STATISTICS',
+        'DBA_REPRESOLUTION_METHOD', 'DBA_REPRESOLUTION',
+        'DBA_REPRESOL_STATS_CONTROL', 'DBA_REPPROP', 'DBA_REPPRIORITY_GROUP',
+        'DBA_REPPRIORITY', 'DBA_REPPARAMETER_COLUMN', 'DBA_REPOBJECT',
+        'DBA_REPKEY_COLUMNS', 'DBA_REPGROUPED_COLUMN',
+        'DBA_REPGROUP_PRIVILEGES', 'DBA_REPGROUP', 'DBA_REPGENOBJECTS',
+        'DBA_REPGENERATED', 'DBA_REPFLAVORS', 'DBA_REPFLAVOR_OBJECTS',
+        'DBA_REPFLAVOR_COLUMNS', 'DBA_REPEXTENSIONS', 'DBA_REPDDL',
+        'DBA_REPCONFLICT', 'DBA_REPCOLUMN_GROUP', 'DBA_REPCOLUMN',
+        'DBA_REPCATLOG', 'DBA_REPCAT_USER_PARM_VALUES',
+        'DBA_REPCAT_USER_AUTHORIZATIONS', 'DBA_REPCAT_TEMPLATE_SITES',
+        'DBA_REPCAT_TEMPLATE_PARMS', 'DBA_REPCAT_TEMPLATE_OBJECTS',
+        'DBA_REPCAT_REFRESH_TEMPLATES', 'DBA_REPCAT_EXCEPTIONS', 'DBA_REPCAT',
+        'DBA_REPAUDIT_COLUMN', 'DBA_REPAUDIT_ATTRIBUTE', 'ALL_REPSITES',
+        'ALL_REPSCHEMA', 'ALL_REPRESOLUTION_STATISTICS',
+        'ALL_REPRESOLUTION_METHOD', 'ALL_REPRESOLUTION',
+        'ALL_REPRESOL_STATS_CONTROL', 'ALL_REPPROP', 'ALL_REPPRIORITY_GROUP',
+        'ALL_REPPRIORITY', 'ALL_REPPARAMETER_COLUMN', 'ALL_REPOBJECT',
+        'ALL_REPKEY_COLUMNS', 'ALL_REPGROUPED_COLUMN',
+        'ALL_REPGROUP_PRIVILEGES', 'ALL_REPGROUP', 'ALL_REPGENOBJECTS',
+        'ALL_REPGENERATED', 'ALL_REPFLAVORS', 'ALL_REPFLAVOR_OBJECTS',
+        'ALL_REPFLAVOR_COLUMNS', 'ALL_REPDDL', 'ALL_REPCONFLICT',
+        'ALL_REPCOLUMN_GROUP', 'ALL_REPCOLUMN', 'ALL_REPCATLOG',
+        'ALL_REPCAT_USER_PARM_VALUES', 'ALL_REPCAT_USER_AUTHORIZATIONS',
+        'ALL_REPCAT_TEMPLATE_SITES', 'ALL_REPCAT_TEMPLATE_PARMS',
+        'ALL_REPCAT_TEMPLATE_OBJECTS', 'ALL_REPCAT_REFRESH_TEMPLATES',
+        'ALL_REPCAT', 'ALL_REPAUDIT_COLUMN', 'ALL_REPAUDIT_ATTRIBUTE')
+        ),
+    'SYMBOLS' => array(
+        //PL/SQL delimiters (http://download-uk.oracle.com/docs/cd/B10501_01/appdev.920/a96624/02_funds.htm#2732)
+        '+', '%', "'", '.', '/', '(', ')', ':', ',', '*', '"', '=', '<', '>', '@', ';', '-', ':=', '=>', '||', '**', '<<', '>>', '/*', '*/', '..', '<>', '!=', '~=', '^=', '<=', '>='
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        5 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #00F;',
+            2 => 'color: #000;',
+            3 => 'color: #00F;',
+            4 => 'color: #F00;',
+            5 => 'color: #800;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #080; font-style: italic;',
+            'MULTI' => 'color: #080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #00F;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #F00;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #800;'
+            ),
+        'METHODS' => array(
+            0 => 'color: #0F0;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #00F;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            0 => 'color: #0F0;'
+            )
+        ),
+        'URLS' => array(
+            1 => 'http://www.oracle.com/pls/db92/db92.drilldown?word={FNAMEU}',
+            2 => 'http://www.oracle.com/pls/db92/db92.drilldown?word={FNAMEU}',
+            3 => 'http://www.oracle.com/pls/db92/db92.drilldown?word={FNAMEU}',
+            4 => 'http://www.oracle.com/pls/db92/db92.drilldown?word={FNAMEU}',
+            5 => 'http://www.oracle.com/pls/db92/db92.drilldown?word={FNAMEU}'
+            ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(),
+    'REGEXPS' => array(),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(),
+    'HIGHLIGHT_STRICT_BLOCK' => array()
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/povray.php b/examples/includes/geshi/geshi/povray.php
new file mode 100644 (file)
index 0000000..09a8b01
--- /dev/null
@@ -0,0 +1,199 @@
+<?php
+/*************************************************************************************
+ * povray.php
+ * --------
+ * Author: Carl Fürstenberg (azatoth@gmail.com)
+ * Copyright: © 2007 Carl Fürstenberg
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/07/11
+ *
+ * Povray language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/07/11 (1.0.8)
+ *   -  initial import to GeSHi SVN
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'POVRAY',
+    'COMMENT_SINGLE' => array(1 => '//'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'yes', 'wrinkles', 'wood', 'width', 'waves', 'water_level', 'warp', 'vturbulence',
+            'vstr', 'vrotate', 'vnormalize', 'vlength', 'vcross', 'vaxis_rotate', 'variance', 'v_steps',
+            'uv_mapping', 'utf8', 'use_index', 'use_colour', 'use_color', 'use_alpha', 'up', 'undef',
+            'ultra_wide_angle', 'u_steps', 'type', 'turbulence', 'turb_depth', 'ttf', 'true', 'triangle_wave',
+            'translate', 'transform', 'trace', 'toroidal', 'tolerance', 'tiles', 'tile2', 'tightness',
+            'tiff', 'threshold', 'thickness', 'tga', 'texture_map', 'target', 'sys', 'sum',
+            'substr', 'sturm', 'strupr', 'strlwr', 'strength', 'str', 'statistics', 'sqr',
+            'spotted', 'spotlight', 'split_union', 'spline', 'spiral2', 'spiral1', 'spherical', 'specular',
+            'spacing', 'solid', 'smooth', 'slope', 'slice', 'sky', 'size', 'sine_wave',
+            'shadowless', 'scattering', 'scallop_wave', 'scale', 'save_file', 'samples', 'roughness', 'rotate',
+            'ripples', 'right', 'rgbt', 'rgbft', 'rgbf', 'rgb', 'repeat', 'render',
+            'refraction', 'reflection_exponent', 'recursion_limit', 'reciprocal', 'ratio', 'ramp_wave', 'radius', 'radial',
+            'quilted', 'quick_colour', 'quick_color', 'quaternion', 'quadratic_spline', 'pwr', 'projected_through', 'prod',
+            'pretrace_start', 'pretrace_end', 'precompute', 'precision', 'ppm', 'pow', 'pot', 'poly_wave',
+            'point_at', 'png', 'planar', 'pigment_pattern', 'pi', 'phong_size', 'phong', 'phase',
+            'pgm', 'perspective', 'pattern', 'pass_through', 'parallel', 'panoramic', 'orthographic', 'orientation',
+            'orient', 'open', 'onion', 'once', 'on', 'omnimax', 'omega', 'offset',
+            'off', 'octaves', 'number_of_waves', 'noise_generator', 'no_shadow', 'no_reflection', 'no_image', 'no_bump_scale',
+            'no', 'nearest_count', 'natural_spline', 'mortar', 'minimum_reuse', 'min_extent', 'metric', 'method',
+            'metallic', 'media_interaction', 'media_attenuation', 'media', 'max_trace_level', 'max_trace', 'max_sample', 'max_iteration',
+            'max_intersections', 'max_gradient', 'max_extent', 'matrix', 'material_map', 'marble', 'map_type', 'mandel',
+            'major_radius', 'magnet', 'low_error_factor', 'look_at', 'location', 'load_file', 'linear_sweep', 'linear_spline',
+            'leopard', 'lambda', 'julia', 'jpeg', 'jitter', 'irid_wavelength', 'ior', 'inverse',
+            'intervals', 'interpolate', 'internal', 'inside_vector', 'inside', 'initial_frame', 'initial_clock', 'image_width',
+            'image_pattern', 'image_height', 'iff', 'hypercomplex', 'hollow', 'hierarchy', 'hf_gray_16', 'hexagon',
+            'gray_threshold', 'granite', 'gradient', 'global_lights', 'gif', 'gather', 'fresnel', 'frequency',
+            'frame_number', 'form', 'fog_type', 'fog_offset', 'fog_alt', 'focal_point', 'flip', 'flatness',
+            'fisheye', 'final_frame', 'final_clock', 'false', 'falloff_angle', 'falloff', 'fade_power', 'fade_distance',
+            'fade_colour', 'fade_color', 'facets', 'extinction', 'exterior', 'exponent', 'expand_thresholds', 'evaluate',
+            'error_bound', 'emission', 'eccentricity', 'double_illuminate', 'distance', 'dist_exp', 'dispersion_samples', 'dispersion',
+            'direction', 'diffuse', 'df3', 'dents', 'density_map', 'density_file', 'density', 'cylindrical',
+            'cutaway_textures', 'cubic_wave', 'cubic_spline', 'cube', 'crand', 'crackle', 'count', 'coords',
+            'control1', 'control0', 'conserve_energy', 'conic_sweep', 'confidence', 'concat', 'composite', 'component',
+            'colour_map', 'colour', 'color', 'collect', 'clock_on', 'clock_delta', 'clock', 'circular',
+            'chr', 'checker', 'charset', 'cells', 'caustics', 'bumps', 'bump_size', 'brilliance',
+            'brightness', 'brick_size', 'brick', 'bozo', 'boxed', 'blur_samples', 'black_hole', 'bezier_spline',
+            'b_spline', 'average', 'autostop', 'assumed_gamma', 'ascii', 'array', 'area_light', 'arc_angle',
+            'append', 'aperture', 'angle', 'ambient_light', 'ambient', 'always_sample', 'altitude', 'alpha',
+            'all_intersections', 'all', 'agate_turb', 'agate', 'adc_bailout', 'adaptive', 'accuracy', 'absorption',
+            'aa_threshold', 'aa_level', 'reflection'
+            ),
+        2 => array(
+            'abs', 'acos', 'acosh', 'asc', 'asin', 'asinh', 'atan', 'atanh',
+            'atan2', 'ceil', 'cos', 'cosh', 'defined', 'degrees', 'dimensions', 'dimension_size',
+            'div', 'exp', 'file_exists', 'floor', 'int', 'ln', 'log', 'max',
+            'min', 'mod', 'pov', 'radians', 'rand', 'seed', 'select', 'sin',
+            'sinh', 'sqrt', 'strcmp', 'strlen', 'tan', 'tanh', 'val', 'vdot',
+            'vlenght',
+            ),
+        3 => array (
+            'x', 'y', 'z', 't', 'u', 'v', 'red', 'blue',
+            'green', 'filter', 'transmit', 'gray', 'e',
+            ),
+        4 => array (
+            'camera', 'background', 'fog', 'sky_sphere', 'rainbow', 'global_settings', 'radiosity', 'photon',
+            'object', 'blob', 'sphere', 'cylinder', 'box', 'cone', 'height_field', 'julia_fractal',
+            'lathe', 'prism', 'sphere_sweep', 'superellipsoid', 'sor', 'text', 'torus', 'bicubic_patch',
+            'disc', 'mesh', 'triangle', 'smooth_triangle', 'mesh2', 'vertex_vectors', 'normal_vectors', 'uv_vectors',
+            'texture_list', 'face_indices', 'normal_indices', 'uv_indices', 'texture', 'polygon', 'plane', 'poly',
+            'cubic', 'quartic', 'quadric', 'isosurface', 'function', 'contained_by', 'parametric', 'pigment',
+            'union', 'intersection', 'difference', 'merge', 'light_source', 'looks_like', 'light_group', 'clipped_by',
+            'bounded_by', 'interior', 'material', 'interior_texture', 'normal', 'finish', 'color_map', 'pigment_map',
+            'image_map', 'bump_map', 'slope_map', 'normal_map', 'irid', 'photons',
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}', '!',
+        '@', '%', '&', '*', '|', '/', '<',
+        '>', '+', '-', '.', '=', '<=', '>=',
+        '!=',
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #a63123;',
+            2 => 'color: #2312bc;',
+            3 => 'color: #cc1122; font-weight: bold;',
+            4 => 'color: #116688; font-weight: bold;',
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+//            2 => 'color: #808080; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66aa;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006600;',
+            2 => 'color: #006600;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #6666cc; font-weight: bold;',
+            1 => 'color: #66cc66; font-weight: bold;',
+            2 => 'color: #66cc66; font-weight: bold;'
+            ),
+        'SCRIPT' => array(
+            0 => '',
+            1 => '',
+            2 => '',
+            3 => ''
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        # normal hash lines
+        0 => '\#(?!(include|declare|local|fopen|fclose|read|write|default|version|if|else|end|ifdef|ifndef|switch|case|range|break|while|debug|error|warning|macro) )[[:word:]]*',
+        # syntax functions hash thingis
+        1 => "\#(include|declare|local|fopen|fclose|read|write|default|version|if|else|end|ifdef|ifndef|switch|case|range|break|while|debug|error|warning|macro)",
+        2 => array(
+            GESHI_SEARCH  => "([a-zA-Z]+)(\n)(.*)(\n)(\\1;?)",
+            GESHI_REPLACE => '\3',
+            GESHI_BEFORE => '\1\2',
+            GESHI_AFTER => '\4\5',
+            GESHI_MODIFIERS => 'siU'
+            )
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_MAYBE,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        0 => true,
+        1 => true,
+        2 => true,
+        3 => true
+        ),
+    'TAB_WIDTH' => 4
+);
+?>
diff --git a/examples/includes/geshi/geshi/powershell.php b/examples/includes/geshi/geshi/powershell.php
new file mode 100644 (file)
index 0000000..5b9e16b
--- /dev/null
@@ -0,0 +1,279 @@
+<?php
+/*************************************************************************************
+ * powershell.php
+ * ---------------------------------
+ * Author: Frode Aarebrot (frode@aarebrot.net)
+ * Copyright: (c) 2008 Frode Aarebrot (http://www.aarebrot.net)
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/06/20
+ *
+ * PowerShell language file for GeSHi.
+ *
+ * I've tried to make this language file as true to the highlighting in PowerGUI as
+ * possible. Unfortunately it's not 100% complete, although it is pretty close.
+ *
+ * I've included some classes and their members, but there's tons and tons of these.
+ * I suggest you add the ones you need yourself. I've included a few Sharepoint ones
+ * in this language file.
+ *
+ * CHANGES
+ * -------
+ * 2008/06/20 (1.0.8)
+ *  -  First Release
+ *
+ * TODO (updated 2008/06/20)
+ * -------------------------
+ * - Color text between Cmdlets/Aliases and pipe/end-of-line
+ * - Try and get -- and ++ to work in the KEYWORDS array with the other operators
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'posh',
+    'COMMENT_SINGLE' => array(1 => '#'),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '`',
+    'KEYWORDS' => array(
+        1 => array(
+            // Cmdlets
+            'Add-Content', 'Add-History', 'Add-Member', 'Add-PSSnapin', 'Clear-Content', 'Clear-Item',
+            'Clear-ItemProperty', 'Clear-Variable', 'Compare-Object', 'ConvertFrom-SecureString',
+            'Convert-Path', 'ConvertTo-Html', 'ConvertTo-SecureString', 'Copy-Item', 'Copy-ItemProperty',
+            'Export-Alias', 'Export-Clixml', 'Export-Console', 'Export-Csv', 'ForEach-Object',
+            'Format-Custom', 'Format-List', 'Format-Table', 'Format-Wide', 'Get-Acl', 'Get-Alias',
+            'Get-AuthenticodeSignature', 'Get-ChildItem', 'Get-Command', 'Get-Content', 'Get-Credential',
+            'Get-Culture', 'Get-Date', 'Get-EventLog', 'Get-ExecutionPolicy', 'Get-Help', 'Get-History',
+            'Get-Host', 'Get-Item', 'Get-ItemProperty', 'Get-Location', 'Get-Member',
+            'Get-PfxCertificate', 'Get-Process', 'Get-PSDrive', 'Get-PSProvider', 'Get-PSSnapin',
+            'Get-Service', 'Get-TraceSource', 'Get-UICulture', 'Get-Unique', 'Get-Variable',
+            'Get-WmiObject', 'Group-Object', 'Import-Alias', 'Import-Clixml', 'Import-Csv',
+            'Invoke-Expression', 'Invoke-History', 'Invoke-Item', 'Join-Path', 'Measure-Command',
+            'Measure-Object', 'Move-Item', 'Move-ItemProperty', 'New-Alias', 'New-Item',
+            'New-ItemProperty', 'New-Object', 'New-PSDrive', 'New-Service', 'New-TimeSpan',
+            'New-Variable', 'Out-Default', 'Out-File', 'Out-Host', 'Out-Null', 'Out-Printer',
+            'Out-String', 'Pop-Location', 'Push-Location', 'Read-Host', 'Remove-Item',
+            'Remove-ItemProperty', 'Remove-PSDrive', 'Remove-PSSnapin', 'Remove-Variable', 'Rename-Item',
+            'Rename-ItemProperty', 'Resolve-Path', 'Restart-Service', 'Resume-Service', 'Select-Object',
+            'Select-String', 'Set-Acl', 'Set-Alias', 'Set-AuthenticodeSignature', 'Set-Content',
+            'Set-Date', 'Set-ExecutionPolicy', 'Set-Item', 'Set-ItemProperty', 'Set-Location',
+            'Set-PSDebug', 'Set-Service', 'Set-TraceSource', 'Set-Variable', 'Sort-Object', 'Split-Path',
+            'Start-Service', 'Start-Sleep', 'Start-Transcript', 'Stop-Process', 'Stop-Service',
+            'Stop-Transcript', 'Suspend-Service', 'Tee-Object', 'Test-Path', 'Trace-Command',
+            'Update-FormatData', 'Update-TypeData', 'Where-Object', 'Write-Debug', 'Write-Error',
+            'Write-Host', 'Write-Output', 'Write-Progress', 'Write-Verbose', 'Write-Warning'
+            ),
+        2 => array(
+            // Aliases
+            'ac', 'asnp', 'clc', 'cli', 'clp', 'clv', 'cpi', 'cpp', 'cvpa', 'diff', 'epal', 'epcsv', 'fc',
+            'fl', 'ft', 'fw', 'gal', 'gc', 'gci', 'gcm', 'gdr', 'ghy', 'gi', 'gl', 'gm',
+            'gp', 'gps', 'group', 'gsv', 'gsnp', 'gu', 'gv', 'gwmi', 'iex', 'ihy', 'ii', 'ipal', 'ipcsv',
+            'mi', 'mp', 'nal', 'ndr', 'ni', 'nv', 'oh', 'rdr', 'ri', 'rni', 'rnp', 'rp', 'rsnp', 'rv',
+            'rvpa', 'sal', 'sasv', 'sc', 'select', 'si', 'sl', 'sleep', 'sort', 'sp', 'spps', 'spsv', 'sv',
+            'tee', 'write', 'cat', 'cd', 'clear', 'cp', 'h', 'history', 'kill', 'lp', 'ls',
+            'mount', 'mv', 'popd', 'ps', 'pushd', 'pwd', 'r', 'rm', 'rmdir', 'echo', 'cls', 'chdir',
+            'copy', 'del', 'dir', 'erase', 'move', 'rd', 'ren', 'set', 'type'
+            ),
+        3 => array(
+            // Reserved words
+            'break', 'continue', 'do', 'for', 'foreach', 'while', 'if', 'switch', 'until', 'where',
+            'function', 'filter', 'else', 'elseif', 'in', 'return', 'param', 'throw', 'trap'
+            ),
+        4 => array(
+            // Operators
+            '-eq', '-ne', '-gt', '-ge', '-lt', '-le', '-ieq', '-ine', '-igt', '-ige', '-ilt', '-ile',
+            '-ceq', '-cne', '-cgt', '-cge', '-clt', '-cle', '-like', '-notlike', '-match', '-notmatch',
+            '-ilike', '-inotlike', '-imatch', '-inotmatch', '-clike', '-cnotlike', '-cmatch', '-cnotmatch',
+            '-contains', '-notcontains', '-icontains', '-inotcontains', '-ccontains', '-cnotcontains',
+            '-isnot', '-is', '-as', '-replace', '-ireplace', '-creplace', '-and', '-or', '-band', '-bor',
+            '-not', '-bnot', '-f', '-casesensitive', '-exact', '-file', '-regex', '-wildcard'
+            ),
+        5 => array(
+            // Options
+            '-Year', '-Wrap', '-Word', '-Width', '-WhatIf', '-Wait', '-View', '-Verbose', '-Verb',
+            '-Variable', '-ValueOnly', '-Value', '-Unique', '-UFormat', '-TypeName', '-Trace', '-TotalCount',
+            '-Title', '-TimestampServer', '-TargetObject', '-Syntax', '-SyncWindow', '-Sum', '-String',
+            '-Strict', '-Stream', '-Step', '-Status', '-Static', '-StartupType', '-Start', '-StackName',
+            '-Stack', '-SourceId', '-SimpleMatch', '-ShowError', '-Separator', '-SecureString', '-SecureKey',
+            '-SecondValue', '-SecondsRemaining', '-Seconds', '-Second', '-Scope', '-Root', '-Role',
+            '-Resolve', '-RemoveListener', '-RemoveFileListener', '-Registered', '-ReferenceObject',
+            '-Recurse', '-RecommendedAction', '-ReadCount', '-Quiet', '-Query', '-Qualifier', '-PSSnapin',
+            '-PSProvider', '-PSHost', '-PSDrive', '-PropertyType', '-Property', '-Prompt', '-Process',
+            '-PrependPath', '-PercentComplete', '-Pattern', '-PathType', '-Path', '-PassThru', '-ParentId',
+            '-Parent', '-Parameter', '-Paging', '-OutVariable', '-OutBuffer', '-Option', '-OnType', '-Off',
+            '-Object', '-Noun', '-NoTypeInformation', '-NoQualifier', '-NoNewline', '-NoElement',
+            '-NoClobber', '-NewName', '-Newest', '-Namespace', '-Name', '-Month', '-Minutes', '-Minute',
+            '-Minimum', '-Milliseconds', '-Message', '-MemberType', '-Maximum', '-LogName', '-LiteralPath',
+            '-LiteralName', '-ListenerOption', '-List', '-Line', '-Leaf', '-Last', '-Key', '-ItemType',
+            '-IsValid', '-IsAbsolute', '-InputObject', '-IncludeEqual', '-IncludeChain', '-Include',
+            '-IgnoreWhiteSpace', '-Id', '-Hours', '-Hour', '-HideTableHeaders', '-Head', '-GroupBy',
+            '-Functionality', '-Full', '-Format', '-ForegroundColor', '-Force', '-First', '-FilterScript',
+            '-Filter', '-FilePath', '-Expression', '-ExpandProperty', '-Expand', '-ExecutionPolicy',
+            '-ExcludeProperty', '-ExcludeDifferent', '-Exclude', '-Exception', '-Examples', '-ErrorVariable',
+            '-ErrorRecord', '-ErrorId', '-ErrorAction', '-End', '-Encoding', '-DisplayName', '-DisplayHint',
+            '-DisplayError', '-DifferenceObject', '-Detailed', '-Destination', '-Description', '-Descending',
+            '-Depth', '-DependsOn', '-Delimiter', '-Debugger', '-Debug', '-Days', '-Day', '-Date',
+            '-CurrentOperation', '-Culture', '-Credential', '-Count', '-Container', '-Confirm',
+            '-ComputerName', '-Component', '-Completed', '-ComObject', '-CommandType', '-Command',
+            '-Column', '-Class', '-ChildPath', '-Character', '-Certificate', '-CategoryTargetType',
+            '-CategoryTargetName', '-CategoryReason', '-CategoryActivity', '-Category', '-CaseSensitive',
+            '-Body', '-BinaryPathName', '-Begin', '-BackgroundColor', '-Average', '-AutoSize', '-Audit',
+            '-AsString', '-AsSecureString', '-AsPlainText', '-As', '-ArgumentList', '-AppendPath', '-Append',
+            '-Adjust', '-Activity', '-AclObject'
+            ),
+        6 => array(
+            '_','args','DebugPreference','Error','ErrorActionPreference',
+            'foreach','Home','Host','Input','LASTEXITCODE','MaximumAliasCount',
+            'MaximumDriveCount','MaximumFunctionCount','MaximumHistoryCount',
+            'MaximumVariableCount','OFS','PsHome',
+            'ReportErrorShowExceptionClass','ReportErrorShowInnerException',
+            'ReportErrorShowSource','ReportErrorShowStackTrace',
+            'ShouldProcessPreference','ShouldProcessReturnPreference',
+            'StackTrace','VerbosePreference','WarningPreference','PWD'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}', '=', '<', '>', '@', '|', '&', ',', '?',
+        '+=', '-=', '*=', '/=', '%=', '*', '/', '%', '!', '+', '-', '++', '--'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        5 => false,
+        6 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #008080; font-weight: bold;',
+            2 => 'color: #008080; font-weight: bold;',
+            3 => 'color: #0000FF;',
+            4 => 'color: #FF0000;',
+            5 => 'color: #008080; font-style: italic;',
+            6 => 'color: #000080;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #008000;',
+            'MULTI' => 'color: #008000;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #008080; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000000;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #800000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #000000;'
+            ),
+        'METHODS' => array(
+            0 => 'color: pink;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: pink;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #800080;',
+            3 => 'color: #008080;',
+            4 => 'color: #008080;',
+            5 => 'color: #800000;',
+            6 => 'color: #000080;'
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => '',
+        5 => '',
+        6 => '',
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        // special after pipe
+        3 => array(
+            GESHI_SEARCH => '(\[)(int|long|string|char|bool|byte|double|decimal|float|single|regex|array|xml|scriptblock|switch|hashtable|type|ref|psobject|wmi|wmisearcher|wmiclass|object)((\[.*\])?\])',
+            GESHI_REPLACE => '\2',
+            GESHI_MODIFIERS => 'si',
+            GESHI_BEFORE => '\1',
+            GESHI_AFTER => '\3'
+            ),
+        // Classes
+        4 => array(
+            GESHI_SEARCH => '(\[)(System\.Reflection\.Assembly|System\.Net\.CredentialCache|Microsoft\.SharePoint\.SPFileLevel|Microsoft\.SharePoint\.Publishing\.PublishingWeb|Microsoft\.SharePoint\.Publishing|Microsoft\.SharePoint\.SPWeb)(\])',
+            GESHI_REPLACE => '\2',
+            GESHI_MODIFIERS => 'i',
+            GESHI_BEFORE => '\1',
+            GESHI_AFTER => '\3'
+            ),
+        // Members
+        // There's about a hundred million of these, add the ones you need as you need them
+        5 => array (
+            GESHI_SEARCH => '(::)(ReflectionOnlyLoadFrom|ReflectionOnlyLoad|ReferenceEquals|LoadWithPartialName|LoadFrom|LoadFile|Load|GetExecutingAssembly|GetEntryAssembly|GetCallingAssembly|GetAssembly|Equals|DefaultNetworkCredentials|DefaultCredentials|CreateQualifiedName|Checkout|Draft|Published|IsPublishingWeb)',
+            GESHI_REPLACE => '\2',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '\1',
+            GESHI_AFTER => ''
+            ),
+        // Special variables
+        6 => array(
+            GESHI_SEARCH => '(\$)(\$[_\^]?|\?)(?!\w)',
+            GESHI_REPLACE => '\1\2',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        // variables
+        //BenBE: Please note that changes here and in Keyword group 6 have to be synchronized in order to work properly.
+        //This Regexp must only match, if keyword group 6 doesn't. If this assumption fails
+        //Highlighting of the keywords will be incomplete or incorrect!
+        0 => "(?<!\\\$|>)[\\\$](?!(?:DebugPreference|Error(?:ActionPreference)?|".
+            "Ho(?:me|st)|Input|LASTEXITCODE|Maximum(?:AliasCount|DriveCount|".
+            "FunctionCount|HistoryCount|VariableCount)|OFS|P(?:WD|sHome)|".
+            "ReportErrorShow(?:ExceptionClass|InnerException|S(?:ource|".
+            "tackTrace))|S(?:houldProcess(?:Preference|ReturnPreference)|".
+            "tackTrace)|VerbosePreference|WarningPreference|_|args|foreach)\W)".
+            "(\w+)(?=[^|\w])",
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            6 => array(
+                'DISALLOWED_BEFORE' => '(?<!\$)\$'
+                )
+            )
+        )
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/progress.php b/examples/includes/geshi/geshi/progress.php
new file mode 100644 (file)
index 0000000..abd5bcb
--- /dev/null
@@ -0,0 +1,479 @@
+<?php
+/*************************************************************************************
+ * progress.php
+ * --------
+ * Author: Marco Aurelio de Pasqual (marcop@hdi.com.br)
+ * Copyright: (c) 2008 Marco Aurelio de Pasqual, Benny Baumann (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/07/11
+ *
+ * Progress language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/07/11 (1.0.8)
+ *   -  First Release
+ *
+ * TODO (updated 2008/07/11)
+ * -------------------------
+ * * Clean up the keyword list
+ * * Sort Keyword lists by Control Structures, Predefined functions and other important keywords
+ * * Complete language support
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array(
+    'LANG_NAME' => 'Progress',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_UPPER,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array (
+        1 => array(
+            'ACCUMULATE','APPLY','ASSIGN','BELL','QUERY',
+            'BUFFER-COMPARE','BUFFER-COPY','CALL','CASE',
+            'CHOOSE','CLASS','CLEAR','CLOSE QUERY','each','WHERE',
+            'CLOSE STORED-PROCEDURE','COLOR','COMPILE','CONNECT',
+            'CONSTRUCTOR','COPY-LOB','CREATE','CREATE ALIAS',
+            'CREATE BROWSE','CREATE BUFFER','CREATE CALL','CREATE CLIENT-PRINCIPAL',
+            'CREATE DATABASE','CREATE DATASET','CREATE DATA-SOURCE','CREATE QUERY',
+            'CREATE SAX-attributeS','CREATE SAX-READER','CREATE SAX-WRITER','CREATE SERVER',
+            'CREATE SERVER-SOCKET','CREATE SOAP-HEADER','CREATE SOAP-HEADER-ENTRYREF','CREATE SOCKET',
+            'CREATE TEMP-TABLE','CREATE WIDGET','CREATE widget-POOL','CREATE X-DOCUMENT',
+            'CREATE X-NODEREF','CURRENT-LANGUAGE','CURRENT-VALUE','DDE ADVISE',
+            'DDE EXECUTE','DDE GET','DDE INITIATE','DDE REQUEST',
+            'DDE SEND','DDE TERMINATE','DEFINE BROWSE','DEFINE BUFFER','DEFINE',
+            'DEFINE BUTTON','DEFINE DATASET','DEFINE DATA-SOURCE','DEFINE FRAME','DEF','VAR',
+            'DEFINE IMAGE','DEFINE MENU','DEFINE PARAMETER','DEFINE property','PARAM',
+            'DEFINE QUERY','DEFINE RECTANGLE','DEFINE STREAM','DEFINE SUB-MENU',
+            'DEFINE TEMP-TABLE','DEFINE WORKFILE','DEFINE WORK-TABLE',
+            'DELETE','DELETE ALIAS','DELETE object','DELETE PROCEDURE',
+            'DELETE widget','DELETE widget-POOL','DESTRUCTOR','DICTIONARY',
+            'DISABLE','DISABLE TRIGGERS','DISCONNECT','DISPLAY',
+            'DO','DOS','DOWN','DYNAMIC-CURRENT-VALUE',
+            'ELSE','EMPTY TEMP-TABLE','ENABLE','END',
+            'ENTRY','EXPORT','FIND','AND',
+            'FIX-CODEPAGE','FOR','FORM','FRAME-VALUE',
+            'GET','GET-KEY-VALUE','HIDE','IF',
+            'IMPORT','INPUT CLEAR','INPUT CLOSE','INPUT FROM','input',
+            'INPUT THROUGH','INPUT-OUTPUT CLOSE','INPUT-OUTPUT THROUGH','INSERT',
+            'INTERFACE','LEAVE','LOAD','BREAK',
+            'LOAD-PICTURE','MESSAGE','method','NEXT','prev',
+            'NEXT-PROMPT','ON','OPEN QUERY','OS-APPEND',
+            'OS-COMMAND','OS-COPY','OS-CREATE-DIR','OS-DELETE',
+            'OS-RENAME','OUTPUT CLOSE','OUTPUT THROUGH','OUTPUT TO',
+            'OVERLAY','PAGE','PAUSE','PROCEDURE',
+            'PROCESS EVENTS','PROMPT-FOR','PROMSGS','PROPATH',
+            'PUBLISH','PUT','PUT CURSOR','PUT SCREEN',
+            'PUT-BITS','PUT-BYTE','PUT-BYTES','PUT-DOUBLE',
+            'PUT-FLOAT','PUT-INT64','PUT-KEY-VALUE','PUT-LONG',
+            'PUT-SHORT','PUT-STRING','PUT-UNSIGNED-LONG','PUT-UNSIGNED-SHORT',
+            'QUIT','RAW-TRANSFER','READKEY','RELEASE',
+            'RELEASE EXTERNAL','RELEASE object','REPEAT','REPOSITION',
+            'RUN','RUN STORED-PROCEDURE','RUN SUPER',
+            'SAVE CACHE','SCROLL','SEEK','SET',
+            'SET-BYTE-ORDER','SET-POINTER-VALUE','SET-SIZE','SHOW-STATS',
+            'STATUS','STOP','SUBSCRIBE','SUBSTRING',
+            'system-DIALOG COLOR','system-DIALOG FONT','system-DIALOG GET-DIR','system-DIALOG GET-FILE',
+            'system-DIALOG PRINTER-SETUP','system-HELP','THEN','THIS-object',
+            'TRANSACTION-MODE AUTOMATIC','TRIGGER PROCEDURE','UNDERLINE','UNDO',
+            'UNIX','UNLOAD','UNSUBSCRIBE','UP','STRING',
+            'UPDATE','USE','USING','VALIDATE','substr','SKIP','CLOSE',
+            'VIEW','WAIT-FOR','MODULO','NE','AVAIL',
+            'NOT','OR','&GLOBAL-DEFINE','&IF','UNFORMATTED','NO-PAUSE',
+            '&THEN','&ELSEIF','&ELSE','&ENDIF','OPEN','NO-WAIT',
+            '&MESSAGE','&SCOPED-DEFINE','&UNDEFINE','DEFINED',
+            'BROWSE','BUTTON','COMBO-BOX','CONTROL-FRAME',
+            'DIALOG-BOX','EDITOR','FIELD-GROUP','FILL-IN',
+            'FRAME','IMAGE','LITERAL','MENU',
+            'MENU-ITEM','RADIO-SET','RECTANGLE','SELECTION-LIST',
+            'SLIDER','SUB-MENU','TEXT','TOGGLE-BOX',
+            'WINDOW','WITH','AT','OF','EDITING','ON ENDKEY','output',
+            'ON ERROR','ON QUIT','ON STOP','PRESELECT',
+            'QUERY-TUNING','SIZE','Trigger','VIEW-AS','ALERT-BOX',
+            'Buffer','Data-relation','ProDataSet','SAX-attributes',
+            'SAX-reader','SAX-writer','Server socket','SOAP-fault',
+            'SOAP-header','SOAP-header-entryref','Socket','Temp-table',
+            'X-noderef','Height','Left','Top','TO',
+            'Width','ACTIVE-WINDOW','AUDIT-CONTROL','FIRST','LAST',
+            'AUDIT-POLICY','CLIPBOARD','CODEBASE-LOCATOR','COLOR-TABLE',
+            'COMPILER','COM-SELF','DEBUGGER','DEFAULT-WINDOW',
+            'ERROR-STATUS','FILE-INFO','FOCUS','FONT-TABLE',
+            'LAST-EVENT','LOG-MANAGER','RCODE-INFO','SECURITY-POLICY',
+            'SELF','SESSION','SOURCE-PROCEDURE','TARGET-PROCEDURE','NO-LOCK','NO-error',
+            'THIS-PROCEDURE','WEB-CONTEXT','FUNCTION','RETURNS','NO-UNDO'
+            ),
+        2 => array(
+            'ACCEPT-CHANGES','ACCEPT-ROW-CHANGES','ADD-BUFFER','ADD-CALC-COLUMN',
+            'ADD-COLUMNS-FROM','ADD-EVENTS-PROCEDURE','ADD-FIELDS-FROM','ADD-FIRST',
+            'ADD-HEADER-ENTRY','ADD-INDEX-FIELD','ADD-LAST','ADD-LIKE-COLUMN',
+            'ADD-LIKE-FIELD','ADD-LIKE-INDEX','ADD-NEW-FIELD','ADD-NEW-INDEX',
+            'ADD-RELATION','ADD-SCHEMA-LOCATION','ADD-SOURCE-BUFFER','ADD-SUPER-PROCEDURE',
+            'APPEND-CHILD','APPLY-CALLBACK','ATTACH-DATA-SOURCE','AUTHENTICATION-FAILED',
+            'BEGIN-EVENT-GROUP','BUFFER-COMPARE','BUFFER-COPY','BUFFER-CREATE',
+            'BUFFER-DELETE','BUFFER-FIELD','BUFFER-RELEASE','BUFFER-VALIDATE',
+            'CANCEL-BREAK','CANCEL-REQUESTS','CLEAR','CLEAR-APPL-CONTEXT',
+            'CLEAR-LOG','CLEAR-SELECTION','CLEAR-SORT-ARROWS','CLONE-NODE',
+            'CLOSE-LOG','CONNECT','CONNECTED','CONVERT-TO-OFFSET',
+            'COPY-DATASET','COPY-SAX-attributeS','COPY-TEMP-TABLE','CREATE-LIKE',
+            'CREATE-NODE','CREATE-NODE-NAMESPACE','CREATE-RESULT-LIST-ENTRY','DEBUG',
+            'DECLARE-NAMESPACE','DELETE-CHAR','DELETE-CURRENT-ROW',
+            'DELETE-HEADER-ENTRY','DELETE-LINE','DELETE-NODE','DELETE-RESULT-LIST-ENTRY',
+            'DELETE-SELECTED-ROW','DELETE-SELECTED-ROWS','DESELECT-FOCUSED-ROW','DESELECT-ROWS',
+            'DESELECT-SELECTED-ROW','DETACH-DATA-SOURCE','DISABLE','DISABLE-CONNECTIONS',
+            'DISABLE-DUMP-TRIGGERS','DISABLE-LOAD-TRIGGERS','DISCONNECT','DISPLAY-MESSAGE',
+            'DUMP-LOGGING-NOW','EDIT-CLEAR','EDIT-COPY','EDIT-CUT',
+            'EDIT-PASTE','EDIT-UNDO','EMPTY-DATASET','EMPTY-TEMP-TABLE',
+            'ENABLE','ENABLE-CONNECTIONS','ENABLE-EVENTS','ENCRYPT-AUDIT-MAC-KEY',
+            'END-DOCUMENT','END-ELEMENT','END-EVENT-GROUP','END-FILE-DROP',
+            'EXPORT','EXPORT-PRINCIPAL','FETCH-SELECTED-ROW',
+            'FILL','FIND-BY-ROWID','FIND-CURRENT','FIND-FIRST',
+            'FIND-LAST','FIND-UNIQUE','GET-attribute','GET-attribute-NODE',
+            'GET-BINARY-DATA','GET-BLUE-VALUE','GET-BROWSE-COLUMN','GET-BUFFER-HANDLE',
+            'GET-BYTES-AVAILABLE','GET-CALLBACK-PROC-CONTEXT','GET-CALLBACK-PROC-NAME','GET-CGI-LIST',
+            'GET-CGI-LONG-VALUE','GET-CGI-VALUE','GET-CHANGES','GET-CHILD',
+            'GET-CHILD-RELATION','GET-CONFIG-VALUE','GET-CURRENT','GET-DATASET-BUFFER',
+            'GET-DOCUMENT-ELEMENT','GET-DROPPED-FILE','GET-DYNAMIC','GET-ERROR-COLUMN ',
+            'GET-ERROR-ROW ','GET-FILE-NAME ','GET-FILE-OFFSET ','GET-FIRST',
+            'GET-GREEN-VALUE','GET-HEADER-ENTRY','GET-INDEX-BY-NAMESPACE-NAME','GET-INDEX-BY-QNAME',
+            'GET-ITERATION','GET-LAST','GET-LOCALNAME-BY-INDEX','GET-MESSAGE',
+            'GET-NEXT','GET-NODE','GET-NUMBER','GET-PARENT',
+            'GET-PREV','GET-PRINTERS','GET-property','GET-QNAME-BY-INDEX',
+            'GET-RED-VALUE','GET-RELATION','GET-REPOSITIONED-ROW','GET-RGB-VALUE',
+            'GET-SELECTED-widget','GET-SERIALIZED','GET-SIGNATURE','GET-SOCKET-OPTION',
+            'GET-SOURCE-BUFFER','GET-TAB-ITEM','GET-TEXT-HEIGHT-CHARS','GET-TEXT-HEIGHT-PIXELS',
+            'GET-TEXT-WIDTH-CHARS','GET-TEXT-WIDTH-PIXELS','GET-TOP-BUFFER','GET-TYPE-BY-INDEX',
+            'GET-TYPE-BY-NAMESPACE-NAME','GET-TYPE-BY-QNAME','GET-URI-BY-INDEX','GET-VALUE-BY-INDEX',
+            'GET-VALUE-BY-NAMESPACE-NAME','GET-VALUE-BY-QNAME','GET-WAIT-STATE','IMPORT-NODE',
+            'IMPORT-PRINCIPAL','INCREMENT-EXCLUSIVE-ID','INDEX-INFORMATION','INITIALIZE-DOCUMENT-TYPE',
+            'INITIATE','INSERT','INSERT-attribute','INSERT-BACKTAB',
+            'INSERT-BEFORE','INSERT-FILE','INSERT-ROW','INSERT-STRING',
+            'INSERT-TAB','INVOKE','IS-ROW-SELECTED','IS-SELECTED',
+            'LIST-property-NAMES','LOAD','LoadControls','LOAD-DOMAINS',
+            'LOAD-ICON','LOAD-IMAGE','LOAD-IMAGE-DOWN','LOAD-IMAGE-INSENSITIVE',
+            'LOAD-IMAGE-UP','LOAD-MOUSE-POINTER','LOAD-SMALL-ICON','LOCK-REGISTRATION',
+            'LOG-AUDIT-EVENT','LOGOUT','LONGCHAR-TO-NODE-VALUE','LOOKUP',
+            'MEMPTR-TO-NODE-VALUE','MERGE-CHANGES','MERGE-ROW-CHANGES','MOVE-AFTER-TAB-ITEM',
+            'MOVE-BEFORE-TAB-ITEM','MOVE-COLUMN','MOVE-TO-BOTTOM','MOVE-TO-EOF',
+            'MOVE-TO-TOP','NODE-VALUE-TO-LONGCHAR','NODE-VALUE-TO-MEMPTR','NORMALIZE',
+            'QUERY-CLOSE','QUERY-OPEN','QUERY-PREPARE','RAW-TRANSFER',
+            'READ','READ-FILE','READ-XML','READ-XMLSCHEMA',
+            'REFRESH','REFRESH-AUDIT-POLICY','REGISTER-DOMAIN','REJECT-CHANGES',
+            'REJECT-ROW-CHANGES','REMOVE-attribute','REMOVE-CHILD','REMOVE-EVENTS-PROCEDURE',
+            'REMOVE-SUPER-PROCEDURE','REPLACE','REPLACE-CHILD','REPLACE-SELECTION-TEXT',
+            'REPOSITION-BACKWARD','REPOSITION-FORWARD','REPOSITION-TO-ROW','REPOSITION-TO-ROWID',
+            'RESET','SAVE','SAVE-FILE','SAVE-ROW-CHANGES',
+            'SAX-PARSE','SAX-PARSE-FIRST','SAX-PARSE-NEXT','SCROLL-TO-CURRENT-ROW',
+            'SCROLL-TO-ITEM','SCROLL-TO-SELECTED-ROW','SEAL','SEARCH',
+            'SELECT-ALL','SELECT-FOCUSED-ROW','SELECT-NEXT-ROW','SELECT-PREV-ROW',
+            'SELECT-ROW','SET-ACTOR','SET-APPL-CONTEXT','SET-attribute',
+            'SET-attribute-NODE','SET-BLUE-VALUE','SET-BREAK','SET-BUFFERS',
+            'SET-CALLBACK','SET-CALLBACK-PROCEDURE','SET-CLIENT','SET-COMMIT',
+            'SET-CONNECT-PROCEDURE','SET-DYNAMIC','SET-GREEN-VALUE','SET-INPUT-SOURCE',
+            'SET-MUST-UNDERSTAND','SET-NODE','SET-NUMERIC-FORMAT','SET-OUTPUT-DESTINATION',
+            'SET-PARAMETER','SET-property','SET-READ-RESPONSE-PROCEDURE','SET-RED-VALUE',
+            'SET-REPOSITIONED-ROW','SET-RGB-VALUE','SET-ROLLBACK','SET-SELECTION',
+            'SET-SERIALIZED','SET-SOCKET-OPTION','SET-SORT-ARROW','SET-WAIT-STATE',
+            'START-DOCUMENT','START-ELEMENT','STOP-PARSING','SYNCHRONIZE',
+            'TEMP-TABLE-PREPARE','UPDATE-attribute','URL-DECODE','URL-ENCODE',
+            'VALIDATE','VALIDATE-SEAL','WRITE','WRITE-CDATA','USE-INDEX',
+            'WRITE-CHARACTERS','WRITE-COMMENT','WRITE-DATA-ELEMENT','WRITE-EMPTY-ELEMENT',
+            'WRITE-ENTITY-REF','WRITE-EXTERNAL-DTD','WRITE-FRAGMENT','WRITE-MESSAGE',
+            'WRITE-PROCESSING-INSTRUCTION','WRITE-XML','WRITE-XMLSCHEMA','FALSE','true'
+            ),
+        3 => array(
+            'ABSOLUTE','ACCUM','ADD-INTERVAL','ALIAS','mod',
+            'AMBIGUOUS','ASC','AUDIT-ENABLED','AVAILABLE',
+            'BASE64-DECODE','BASE64-ENCODE','CAN-DO','CAN-FIND',
+            'CAN-QUERY','CAN-SET','CAPS','CAST','OS-DIR',
+            'CHR','CODEPAGE-CONVERT','COMPARE','CONNECTED',
+            'COUNT-OF','CURRENT-CHANGED','CURRENT-RESULT-ROW','DATASERVERS',
+            'DATA-SOURCE-MODIFIED','DATETIME','DATETIME-TZ',
+            'DAY','DBCODEPAGE','DBCOLLATION','DBNAME',
+            'DBPARAM','DBRESTRICTIONS','DBTASKID','DBTYPE',
+            'DBVERSION','DECIMAL','DECRYPT','DYNAMIC-function',
+            'DYNAMIC-NEXT-VALUE','ENCODE','ENCRYPT','ENTERED',
+            'ERROR','ETIME','EXP','FILL','ENDKEY','END-error',
+            'FIRST-OF','FRAME-DB','FRAME-DOWN',
+            'FRAME-FIELD','FRAME-FILE','FRAME-INDEX','FRAME-LINE',
+            'GATEWAYS','GENERATE-PBE-KEY','GENERATE-PBE-SALT','GENERATE-RANDOM-KEY',
+            'GENERATE-UUID','GET-BITS','GET-BYTE','GET-BYTE-ORDER',
+            'GET-BYTES','GET-CODEPAGE','GET-CODEPAGES','GET-COLLATION',
+            'GET-COLLATIONS','GET-DOUBLE','GET-FLOAT','GET-INT64',
+            'GET-LONG','GET-POINTER-VALUE','GET-SHORT','GET-SIZE',
+            'GET-STRING','GET-UNSIGNED-LONG','GET-UNSIGNED-SHORT','GO-PENDING',
+            'GUID','HEX-DECODE','INDEX',
+            'INT64','INTEGER','INTERVAL','IS-ATTR-SPACE',
+            'IS-CODEPAGE-FIXED','IS-COLUMN-CODEPAGE','IS-LEAD-BYTE','ISO-DATE',
+            'KBLABEL','KEYCODE','KEYFUNCTION','KEYLABEL',
+            'KEYWORD','KEYWORD-ALL','LASTKEY',
+            'LAST-OF','LC','LDBNAME','LEFT-TRIM',
+            'LIBRARY','LINE-COUNTER','LIST-EVENTS','LIST-QUERY-ATTRS',
+            'LIST-SET-ATTRS','LIST-widgetS','LOCKED','LOG',
+            'LOGICAL','LOOKUP','MAXIMUM','MD5-DIGEST',
+            'MEMBER','MESSAGE-LINES','MINIMUM','MONTH',
+            'MTIME','NEW','NEXT-VALUE','NORMALIZE','SHARED',
+            'NOT ENTERED','NOW','NUM-ALIASES','NUM-DBS',
+            'NUM-ENTRIES','NUM-RESULTS','OPSYS','OS-DRIVES',
+            'OS-ERROR','OS-GETENV','PAGE-NUMBER','PAGE-SIZE',
+            'PDBNAME','PROC-HANDLE','PROC-STATUS','PROGRAM-NAME',
+            'PROGRESS','PROVERSION','QUERY-OFF-END','QUOTER',
+            'RANDOM','RAW','RECID','REJECTED',
+            'REPLACE','RETRY','RETURN-VALUE','RGB-VALUE',
+            'RIGHT-TRIM','R-INDEX','ROUND','ROWID','LENGTH',
+            'SDBNAME','SEARCH','SET-DB-CLIENT','SETUSERID',
+            'SHA1-DIGEST','SQRT','SUBSTITUTE','VARIABLE',
+            'SUPER','TERMINAL','TIME','TIMEZONE','external','ENTRY',
+            'TODAY','TO-ROWID','TRIM','TRUNCATE','return',
+            'TYPE-OF','USERID','VALID-EVENT','VALID-HANDLE',
+            'VALID-object','WEEKDAY','YEAR','BEGINS','VALUE',
+            'EQ','GE','GT','LE','LT','MATCHES','AS','BY','LIKE'
+            ),
+        4 => array(
+            'ACCELERATOR','ACTIVE','ACTOR','ADM-DATA',
+            'AFTER-BUFFER','AFTER-ROWID','AFTER-TABLE','ALLOW-COLUMN-SEARCHING',
+            'ALWAYS-ON-TOP','APPL-ALERT-BOXES','APPL-CONTEXT-ID','APPSERVER-INFO',
+            'APPSERVER-PASSWORD','APPSERVER-USERID','ASYNCHRONOUS','ASYNC-REQUEST-COUNT',
+            'ASYNC-REQUEST-HANDLE','ATTACHED-PAIRLIST','attribute-NAMES','ATTR-SPACE',
+            'AUDIT-EVENT-CONTEXT','AUTO-COMPLETION','AUTO-DELETE','AUTO-DELETE-XML',
+            'AUTO-END-KEY','AUTO-GO','AUTO-INDENT','AUTO-RESIZE',
+            'AUTO-RETURN','AUTO-SYNCHRONIZE','AUTO-VALIDATE','AUTO-ZAP',
+            'AVAILABLE-FORMATS','BACKGROUND','BASE-ADE','BASIC-LOGGING',
+            'BATCH-MODE','BATCH-SIZE','BEFORE-BUFFER','BEFORE-ROWID',
+            'BEFORE-TABLE','BGCOLOR','BLANK','BLOCK-ITERATION-DISPLAY',
+            'BORDER-BOTTOM-CHARS','BORDER-BOTTOM-PIXELS','BORDER-LEFT-CHARS','BORDER-LEFT-PIXELS',
+            'BORDER-RIGHT-CHARS','BORDER-RIGHT-PIXELS','BORDER-TOP-CHARS','BORDER-TOP-PIXELS',
+            'BOX','BOX-SELECTABLE','BUFFER-CHARS','BUFFER-FIELD',
+            'BUFFER-HANDLE','BUFFER-LINES','BUFFER-NAME','BUFFER-VALUE',
+            'BYTES-READ','BYTES-WRITTEN','CACHE','CALL-NAME',
+            'CALL-TYPE','CANCEL-BUTTON','CANCELLED','CAN-CREATE',
+            'CAN-DELETE','CAN-READ','CAN-WRITE','CAREFUL-PAINT',
+            'CASE-SENSITIVE','CENTERED','CHARSET','CHECKED',
+            'CHILD-BUFFER','CHILD-NUM','CLASS-TYPE','CLIENT-CONNECTION-ID',
+            'CLIENT-TTY','CLIENT-TYPE','CLIENT-WORKSTATION','CODE',
+            'CODEPAGE','COLUMN','COLUMN-BGCOLOR','COLUMN-DCOLOR',
+            'COLUMN-FGCOLOR','COLUMN-FONT','COLUMN-LABEL','COLUMN-MOVABLE',
+            'COLUMN-PFCOLOR','COLUMN-READ-ONLY','COLUMN-RESIZABLE','COLUMN-SCROLLING',
+            'COM-HANDLE','COMPLETE','CONFIG-NAME','CONTEXT-HELP',
+            'CONTEXT-HELP-FILE','CONTEXT-HELP-ID','CONTROL-BOX','CONVERT-3D-COLORS',
+            'CPCASE','CPCOLL','CPINTERNAL','CPLOG',
+            'CPPRINT','CPRCODEIN','CPRCODEOUT','CPSTREAM',
+            'CPTERM','CRC-VALUE','CURRENT-COLUMN','CURRENT-ENVIRONMENT',
+            'CURRENT-ITERATION','CURRENT-ROW-MODIFIED','CURRENT-WINDOW','CURSOR-CHAR',
+            'CURSOR-LINE','CURSOR-OFFSET','DATA-ENTRY-RETURN','DATASET',
+            'DATA-SOURCE','DATA-SOURCE-COMPLETE-MAP','DATA-TYPE','DATE-FORMAT',
+            'DB-REFERENCES','DCOLOR','DDE-ERROR','DDE-ID',
+            'DDE-ITEM','DDE-NAME','DDE-TOPIC','DEBLANK',
+            'DEBUG-ALERT','DECIMALS','DEFAULT','DEFAULT-BUFFER-HANDLE',
+            'DEFAULT-BUTTON','DEFAULT-COMMIT','DELIMITER','DISABLE-AUTO-ZAP',
+            'DISPLAY-TIMEZONE','DISPLAY-TYPE','DOMAIN-DESCRIPTION','DOMAIN-NAME',
+            'DOMAIN-TYPE','DRAG-ENABLED','DROP-TARGET','DYNAMIC',
+            'EDGE-CHARS','EDGE-PIXELS','EDIT-CAN-PASTE','EDIT-CAN-UNDO',
+            'EMPTY','ENCODING','ENCRYPTION-SALT','END-USER-PROMPT',
+            'ENTRY-TYPES-LIST','ERROR-COLUMN','ERROR-object-DETAIL','ERROR-ROW',
+            'ERROR-STRING','EVENT-GROUP-ID','EVENT-PROCEDURE','EVENT-PROCEDURE-CONTEXT',
+            'EVENT-TYPE','EXCLUSIVE-ID','EXECUTION-LOG','EXPAND',
+            'EXPANDABLE','FGCOLOR','FILE-CREATE-DATE','FILE-CREATE-TIME',
+            'FILE-MOD-DATE','FILE-MOD-TIME','FILE-NAME','FILE-OFFSET',
+            'FILE-SIZE','FILE-TYPE','FILLED','FILL-MODE',
+            'FILL-WHERE-STRING','FIRST-ASYNC-REQUEST','FIRST-BUFFER','FIRST-CHILD',
+            'FIRST-COLUMN','FIRST-DATASET','FIRST-DATA-SOURCE','FIRST-object',
+            'FIRST-PROCEDURE','FIRST-QUERY','FIRST-SERVER','FIRST-SERVER-SOCKET',
+            'FIRST-SOCKET','FIRST-TAB-ITEM','FIT-LAST-COLUMN','FLAT-BUTTON',
+            'FOCUSED-ROW','FOCUSED-ROW-SELECTED','FONT','FOREGROUND',
+            'FORMAT','FORMATTED','FORM-INPUT','FORM-LONG-INPUT',
+            'FORWARD-ONLY','FRAGMENT','FRAME-COL','FRAME-NAME',
+            'FRAME-ROW','FRAME-SPACING','FRAME-X','FRAME-Y',
+            'FREQUENCY','FULL-HEIGHT-CHARS','FULL-HEIGHT-PIXELS','FULL-PATHNAME',
+            'FULL-WIDTH-CHARS','FULL-WIDTH-PIXELS','GRAPHIC-EDGE',
+            'GRID-FACTOR-HORIZONTAL','GRID-FACTOR-VERTICAL','GRID-SNAP','GRID-UNIT-HEIGHT-CHARS',
+            'GRID-UNIT-HEIGHT-PIXELS','GRID-UNIT-WIDTH-CHARS','GRID-UNIT-WIDTH-PIXELS','GRID-VISIBLE',
+            'GROUP-BOX','HANDLE','HANDLER','HAS-LOBS',
+            'HAS-RECORDS','HEIGHT-CHARS','HEIGHT-PIXELS','HELP',
+            'HIDDEN','HORIZONTAL','HTML-CHARSET','HTML-END-OF-LINE',
+            'HTML-END-OF-PAGE','HTML-FRAME-BEGIN','HTML-FRAME-END','HTML-HEADER-BEGIN',
+            'HTML-HEADER-END','HTML-TITLE-BEGIN','HTML-TITLE-END','HWND',
+            'ICFPARAMETER','ICON','IGNORE-CURRENT-MODIFIED','IMAGE-DOWN',
+            'IMAGE-INSENSITIVE','IMAGE-UP','IMMEDIATE-DISPLAY','INDEX-INFORMATION',
+            'IN-HANDLE','INHERIT-BGCOLOR','INHERIT-FGCOLOR','INITIAL','INIT',
+            'INNER-CHARS','INNER-LINES','INPUT-VALUE','INSTANTIATING-PROCEDURE',
+            'INTERNAL-ENTRIES','IS-CLASS','IS-OPEN','IS-PARAMETER-SET',
+            'IS-XML','ITEMS-PER-ROW','KEEP-CONNECTION-OPEN','KEEP-FRAME-Z-ORDER',
+            'KEEP-SECURITY-CACHE','KEY','KEYS','LABEL',
+            'LABEL-BGCOLOR','LABEL-DCOLOR','LABEL-FGCOLOR','LABEL-FONT',
+            'LABELS','LANGUAGES','LARGE','LARGE-TO-SMALL',
+            'LAST-ASYNC-REQUEST','LAST-BATCH','LAST-CHILD','LAST-object',
+            'LAST-PROCEDURE','LAST-SERVER','LAST-SERVER-SOCKET','LAST-SOCKET',
+            'LAST-TAB-ITEM','LINE','LIST-ITEM-PAIRS','LIST-ITEMS',
+            'LITERAL-QUESTION','LOCAL-HOST','LOCAL-NAME','LOCAL-PORT',
+            'LOCATOR-COLUMN-NUMBER','LOCATOR-LINE-NUMBER','LOCATOR-PUBLIC-ID','LOCATOR-system-ID',
+            'LOCATOR-TYPE','LOG-ENTRY-TYPES','LOGFILE-NAME','LOGGING-LEVEL',
+            'LOGIN-EXPIRATION-TIMESTAMP','LOGIN-HOST','LOGIN-STATE','LOG-THRESHOLD',
+            'MANDATORY','MANUAL-HIGHLIGHT','MAX-BUTTON','MAX-CHARS',
+            'MAX-DATA-GUESS','MAX-HEIGHT-CHARS','MAX-HEIGHT-PIXELS','MAX-VALUE',
+            'MAX-WIDTH-CHARS','MAX-WIDTH-PIXELS','MD5-VALUE','MENU-BAR',
+            'MENU-KEY','MENU-MOUSE','MERGE-BY-FIELD','MESSAGE-AREA',
+            'MESSAGE-AREA-FONT','MIN-BUTTON','MIN-COLUMN-WIDTH-CHARS','MIN-COLUMN-WIDTH-PIXELS',
+            'MIN-HEIGHT-CHARS','MIN-HEIGHT-PIXELS','MIN-SCHEMA-MARSHAL','MIN-VALUE',
+            'MIN-WIDTH-CHARS','MIN-WIDTH-PIXELS','MODIFIED','MOUSE-POINTER',
+            'MOVABLE','MULTI-COMPILE','MULTIPLE','MULTITASKING-INTERVAL',
+            'MUST-UNDERSTAND','NAME','NAMESPACE-PREFIX','NAMESPACE-URI',
+            'NEEDS-APPSERVER-PROMPT','NEEDS-PROMPT','NESTED','NEW-ROW',
+            'NEXT-COLUMN','NEXT-ROWID','NEXT-SIBLING','NEXT-TAB-ITEM', 'NO-BOX',
+            'NO-CURRENT-VALUE','NODE-VALUE','NO-EMPTY-SPACE','NO-FOCUS',
+            'NONAMESPACE-SCHEMA-LOCATION','NO-SCHEMA-MARSHAL','NO-VALIDATE','NUM-BUFFERS',
+            'NUM-BUTTONS','NUM-CHILD-RELATIONS','NUM-CHILDREN','NUM-COLUMNS',
+            'NUM-DROPPED-FILES','NUMERIC-DECIMAL-POINT','NUMERIC-FORMAT','NUMERIC-SEPARATOR',
+            'NUM-FIELDS','NUM-FORMATS','NUM-HEADER-ENTRIES','NUM-ITEMS',
+            'NUM-ITERATIONS','NUM-LINES','NUM-LOCKED-COLUMNS','NUM-LOG-FILES',
+            'NUM-MESSAGES','NUM-PARAMETERS','NUM-REFERENCES','NUM-RELATIONS',
+            'NUM-REPLACED','NUM-SELECTED-ROWS','NUM-SELECTED-WIDGETS','NUM-SOURCE-BUFFERS',
+            'NUM-TABS','NUM-TOP-BUFFERS','NUM-TO-RETAIN','NUM-VISIBLE-COLUMNS',
+            'ON-FRAME-BORDER','ORIGIN-HANDLE','ORIGIN-ROWID','OWNER',
+            'OWNER-DOCUMENT','PAGE-BOTTOM','PAGE-TOP','PARAMETER',
+            'PARENT','PARENT-BUFFER','PARENT-RELATION','PARSE-STATUS',
+            'PASSWORD-FIELD','PATHNAME','PBE-HASH-ALGORITHM','PBE-KEY-ROUNDS',
+            'PERSISTENT','PERSISTENT-CACHE-DISABLED','PERSISTENT-PROCEDURE','PFCOLOR',
+            'PIXELS-PER-COLUMN','PIXELS-PER-ROW','POPUP-MENU','POPUP-ONLY',
+            'POSITION','PREFER-DATASET','PREPARED','PREPARE-STRING',
+            'PREV-COLUMN','PREV-SIBLING','PREV-TAB-ITEM','PRIMARY',
+            'PRINTER-CONTROL-HANDLE','PRINTER-HDC','PRINTER-NAME','PRINTER-PORT',
+            'PRIVATE-DATA','PROCEDURE-NAME','PROGRESS-SOURCE','PROXY',
+            'PROXY-PASSWORD','PROXY-USERID','PUBLIC-ID','PUBLISHED-EVENTS',
+            'RADIO-BUTTONS','READ-ONLY','RECORD-LENGTH',
+            'REFRESHABLE','RELATION-FIELDS','RELATIONS-ACTIVE','REMOTE',
+            'REMOTE-HOST','REMOTE-PORT','RESIZABLE','RESIZE',
+            'RESTART-ROWID','RETAIN-SHAPE','RETURN-INSERTED','RETURN-VALUE-DATA-TYPE',
+            'ROLES','ROUNDED','COL','ROW','ROW-HEIGHT-CHARS',
+            'ROW-HEIGHT-PIXELS','ROW-MARKERS','ROW-RESIZABLE','ROW-STATE',
+            'SAVE-WHERE-STRING','SCHEMA-CHANGE','SCHEMA-LOCATION','SCHEMA-MARSHAL',
+            'SCHEMA-PATH','SCREEN-LINES','SCREEN-VALUE','SCROLLABLE',
+            'SCROLLBAR-HORIZONTAL','SCROLL-BARS','SCROLLBAR-VERTICAL','SEAL-TIMESTAMP',
+            'SELECTABLE','SELECTED','SELECTION-END','SELECTION-START',
+            'SELECTION-TEXT','SENSITIVE','SEPARATOR-FGCOLOR','SEPARATORS',
+            'SERVER','SERVER-CONNECTION-BOUND','SERVER-CONNECTION-BOUND-REQUEST','SERVER-CONNECTION-CONTEXT',
+            'SERVER-CONNECTION-ID','SERVER-OPERATING-MODE','SESSION-END','SESSION-ID',
+            'SHOW-IN-TASKBAR','SIDE-LABEL-HANDLE','SIDE-LABELS','SKIP-DELETED-RECORD',
+            'SMALL-ICON','SMALL-TITLE','SOAP-FAULT-ACTOR','SOAP-FAULT-CODE',
+            'SOAP-FAULT-DETAIL','SOAP-FAULT-STRING','SORT','SORT-ASCENDING',
+            'SORT-NUMBER','SSL-SERVER-NAME','STANDALONE','STARTUP-PARAMETERS',
+            'STATE-DETAIL','STATUS-AREA','STATUS-AREA-FONT','STOPPED',
+            'STREAM','STRETCH-TO-FIT','STRICT','STRING-VALUE',
+            'SUBTYPE','SUPER-PROCEDURES','SUPPRESS-NAMESPACE-PROCESSING','SUPPRESS-WARNINGS',
+            'SYMMETRIC-ENCRYPTION-ALGORITHM','SYMMETRIC-ENCRYPTION-IV','SYMMETRIC-ENCRYPTION-KEY','SYMMETRIC-SUPPORT',
+            'system-ALERT-BOXES','system-ID','TABLE','TABLE-CRC-LIST',
+            'TABLE-HANDLE','TABLE-LIST','TABLE-NUMBER','TAB-POSITION',
+            'TAB-STOP','TEMP-DIRECTORY','TEXT-SELECTED','THREE-D',
+            'TIC-MARKS','TIME-SOURCE','TITLE','TITLE-BGCOLOR','FIELD',
+            'TITLE-DCOLOR','TITLE-FGCOLOR','TITLE-FONT','TOOLTIP',
+            'TOOLTIPS','TOP-ONLY','TRACKING-CHANGES','TRANSACTION',
+            'TRANS-INIT-PROCEDURE','TRANSPARENT','TYPE','UNIQUE-ID',
+            'UNIQUE-MATCH','URL','URL-PASSWORD','URL-USERID','EXTENT',
+            'USER-ID','V6DISPLAY','VALIDATE-EXPRESSION','VALIDATE-MESSAGE',
+            'VALIDATE-XML','VALIDATION-ENABLED','VIEW-FIRST-COLUMN-ON-REOPEN',
+            'VIRTUAL-HEIGHT-CHARS','VIRTUAL-HEIGHT-PIXELS','VIRTUAL-WIDTH-CHARS','VIRTUAL-WIDTH-PIXELS',
+            'VISIBLE','WARNING','WHERE-STRING','widget-ENTER','DATE',
+            'widget-LEAVE','WIDTH-CHARS','WIDTH-PIXELS','WINDOW-STATE',
+            'WINDOW-system','WORD-WRAP','WORK-AREA-HEIGHT-PIXELS','WORK-AREA-WIDTH-PIXELS',
+            'WORK-AREA-X','WORK-AREA-Y','WRITE-STATUS','X','widget-Handle',
+            'X-DOCUMENT','XML-DATA-TYPE','XML-NODE-TYPE','XML-SCHEMA-PATH',
+            'XML-SUPPRESS-NAMESPACE-PROCESSING','Y','YEAR-OFFSET','CHARACTER','INTEGER','LOGICAL',
+            'LONGCHAR','MEMPTR','DECIMAL','CHAR','DEC','INT','LOG','DECI','INTE','LOGI','long'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}',
+        '<', '>', '=',
+        '+', '-', '*', '/',
+        '!', '@', '%', '|', '$',
+        ':', '.', ';', ',',
+        '?', '<=','<>','>=', '\\'
+        ),
+    'CASE_SENSITIVE' => array (
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false
+        ),
+    'STYLES' => array (
+        'KEYWORDS' => array (
+            1 => 'color: #0000ff; font-weight: bold;',
+            2 => 'color: #1D16B2;',
+            3 => 'color: #993333;',
+            4 => 'color: #0000ff;'
+            ),
+        'COMMENTS' => array (
+//            1 => 'color: #808080; font-style: italic;',
+//            2 => 'color: #808080; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array (
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array (
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array (
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array (
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array (
+            0 => 'color: #006600;'
+            ),
+        'SYMBOLS' => array (
+            0 => 'color: #66cc66;'
+            ),
+        'REGEXPS' => array (
+            ),
+        'SCRIPT' => array (
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        0 => ':'
+        ),
+    'REGEXPS' => array (
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array (
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array (
+        ),
+    'TAB_WIDTH' => 4,
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            'DISALLOWED_BEFORE' => "(?<![\.\-a-zA-Z0-9_\$\#&])",
+            'DISALLOWED_AFTER' =>  "(?![\-a-zA-Z0-9_%])"
+        )
+    )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/prolog.php b/examples/includes/geshi/geshi/prolog.php
new file mode 100644 (file)
index 0000000..e3a07c1
--- /dev/null
@@ -0,0 +1,143 @@
+<?php
+/*************************************************************************************
+ * prolog.php
+ * --------
+ * Author: Benny Baumann (BenBE@geshi.org)
+ * Copyright: (c) 2008 Benny Baumann (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/10/02
+ *
+ * Prolog language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/10/02 (1.0.8.1)
+ *  -  First Release
+ *
+ * TODO (updated 2008/10/02)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Prolog',
+    'COMMENT_SINGLE' => array(1 => '%'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'HARDQUOTE' => array("'", "'"),
+    'HARDESCAPE' => array("\'"),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array(),
+    'ESCAPE_CHAR' => '',
+    'NUMBERS' =>
+        GESHI_NUMBER_INT_BASIC | GESHI_NUMBER_FLT_SCI_ZERO,
+    'KEYWORDS' => array(
+        1 => array(
+            'abolish','abs','arg','asserta','assertz','at_end_of_stream','atan',
+            'atom','atom_chars','atom_codes','atom_concat','atom_length',
+            'atomic','bagof','call','catch','ceiling','char_code',
+            'char_conversion','clause','close','compound','consult','copy_term',
+            'cos','current_char_conversion','current_input','current_op',
+            'current_output','current_predicate','current_prolog_flag',
+            'discontiguous','dynamic','ensure_loaded','exp','fail','findall',
+            'float','float_fractional_part','float_integer_part','floor',
+            'flush_output','functor','get_byte','get_char','get_code','halt',
+            'include','initialization','integer','is','listing','log','mod',
+            'multifile','nl','nonvar','notrace','number','number_chars',
+            'number_codes','once','op','open','peek_byte','peek_char',
+            'peek_code','put_byte','put_char','put_code','read','read_term',
+            'rem','repeat','retract','round','set_input','set_output',
+            'set_prolog_flag','set_stream_position','setof','sign','sin','sqrt',
+            'stream_property','sub_atom','throw','trace','true','truncate',
+            'unify_with_occurs_check','univ','var','write','write_canonical',
+            'write_term','writeq'
+            )
+        ),
+    'SYMBOLS' => array(
+        0 => array('(', ')', '[', ']', '{', '}',),
+        1 => array('?-', ':-', '=:='),
+        2 => array('\-', '\+', '\*', '\/'),
+        3 => array('-', '+', '*', '/'),
+        4 => array('.', ':', ',', ';'),
+        5 => array('!', '@', '&', '|'),
+        6 => array('<', '>', '=')
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #990000;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #666666; font-style: italic;',
+            'MULTI' => 'color: #666666; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;',
+            'HARD' => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #009900;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #0000ff;',
+            'HARD' => 'color: #0000ff;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #800080;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #339933;',
+            1 => 'color: #339933;',
+            2 => 'color: #339933;',
+            3 => 'color: #339933;',
+            4 => 'color: #339933;',
+            5 => 'color: #339933;',
+            6 => 'color: #339933;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #008080;'
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => 'http://pauillac.inria.fr/~deransar/prolog/bips.html'
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        //Variables
+        0 => "(?<![A-Z_])(?!(?:PIPE|SEMI)[^a-zA-Z0-9_])[A-Z_][a-zA-Z0-9_]*(?![a-zA-Z0-9_])"
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/providex.php b/examples/includes/geshi/geshi/providex.php
new file mode 100644 (file)
index 0000000..d8b918e
--- /dev/null
@@ -0,0 +1,299 @@
+<?php
+/******************************************************************************
+ * providex.php
+ * ----------
+ * Author: Jeff Wilder (jeff@coastallogix.com)
+ * Copyright:  (c) 2008 Coastal Logix (http://www.coastallogix.com)
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/10/18
+ *
+ * ProvideX language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/10/21 (1.0.0)
+ *  - First Release
+ *
+ * TODO
+ * -------------------------
+ * 1. Create a regexp for numeric global variables (ex: %VarName = 3)
+ * 2. Add standard object control properties
+ *
+ ******************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *****************************************************************************/
+$language_data = array (
+    'LANG_NAME' => 'ProvideX',
+    'COMMENT_SINGLE' => array(1 => '!'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'COMMENT_REGEXP' => array(
+        // Single-Line Comments using REM command
+        2 => "/\bREM\b.*?$/i"
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            // Directives
+            '*break', '*continue', '*end', '*escape', '*next', '*proceed',
+            '*retry', '*return', '*same', 'accept', 'add index', 'addr',
+            'auto', 'begin', 'break', 'button', 'bye', 'call', 'case',
+            'chart', 'check_box', 'class', 'clear', 'clip_board', 'close',
+            'continue', 'control', 'create required', 'create table',
+            'cwdir', 'data', 'day_format', 'def', 'default', 'defctl',
+            'defprt', 'deftty', 'delete required', 'dictionary', 'dim', 'direct',
+            'directory', 'disable', 'drop', 'drop_box', 'dump', 'edit',
+            'else', 'enable', 'end switch', 'end', 'end_if', 'endtrace',
+            'enter', 'erase', 'error_handler', 'escape', 'event', 'execute',
+            'exit', 'exitto', 'extract', 'file', 'find', 'floating point',
+            'for', 'function', 'get_file_box', 'gosub', 'goto', 'grid',
+            'h_scrollbar', 'hide', 'if', 'index', 'indexed', 'input',
+            'insert', 'invoke', 'iolist', 'keyed', 'let', 'like',
+            'line_switch', 'list', 'list_box', 'load', 'local', 'lock',
+            'long_form', 'menu_bar', 'merge', 'message_lib', 'mnemonic',
+            'msgbox', 'multi_line', 'multi_media', 'next', 'object', 'obtain',
+            'on', 'open', 'password', 'perform', 'pop', 'popup_menu',
+            'precision', 'prefix', 'preinput', 'print', 'process', 'program',
+            'property', 'purge', 'quit', 'radio_button', 'randomize',
+            'read', 'record', 'redim', 'refile', 'release', 'rem', 'remove',
+            'rename', 'renumber', 'repeat', 'reset', 'restore', 'retry',
+            'return', 'round', 'run', 'save', 'select', 'serial', 'server',
+            'set_focus', 'set_nbf', 'set_param', 'setctl', 'setday', 'setdev',
+            'setdrive', 'seterr', 'setesc', 'setfid', 'setmouse', 'settime',
+            'settrace', 'short_form', 'show', 'sort', 'start', 'static',
+            'step', 'stop', 'switch', 'system_help', 'system_jrnl', 'table',
+            'then', 'to', 'translate', 'tristate_box', 'unlock', 'until',
+            'update', 'user_lex', 'v_scrollbar', 'vardrop_box', 'varlist_box',
+            'via', 'video_palette', 'wait', 'wend', 'while', 'winprt_setup',
+            'with', 'write'
+            ),
+        2 => array(
+            // System Functions
+            '@x', '@y', 'abs', 'acs', 'and', 'arg', 'asc', 'asn', 'ath',
+            'atn', 'bin', 'bsz', 'chg', 'chr', 'cmp', 'cos', 'cpl',
+            'crc', 'cse', 'ctl', 'cvs', 'dec', 'dir', 'dll', 'dsk',
+            'dte', 'env', 'ept', 'err', 'evn', 'evs', 'exp', 'ffn',
+            'fib', 'fid', 'fin', 'fpt', 'gap', 'gbl', 'gep', 'hsa',
+            'hsh', 'hta', 'hwn', 'i3e', 'ind', 'int', 'iol', 'ior',
+            'jul', 'jst', 'kec', 'kef', 'kel', 'ken', 'kep', 'key',
+            'kgn', 'lcs', 'len', 'lno', 'log', 'lrc', 'lst', 'max',
+            'mem', 'mid', 'min', 'mnm', 'mod', 'msg', 'msk', 'mxc',
+            'mxl', 'new', 'not', 'nul', 'num', 'obj', 'opt', 'pad',
+            'pck', 'pfx', 'pgm', 'pos', 'prc', 'prm', 'pth', 'pub',
+            'rcd', 'rdx', 'rec', 'ref', 'rnd', 'rno', 'sep', 'sgn',
+            'sin', 'sqr', 'srt', 'ssz', 'stk', 'stp', 'str', 'sub',
+            'swp', 'sys', 'tan', 'tbl', 'tcb', 'tmr', 'trx', 'tsk',
+            'txh', 'txw', 'ucp', 'ucs', 'upk', 'vin', 'vis', 'xeq',
+            'xfa', 'xor', '_obj'
+            ),
+        3 => array(
+            // System Variables
+            // Vars that are duplicates of functions
+            // 'ctl', 'err', 'pfx', 'prm', 'rnd', 'sep', 'sys',
+            'bkg', 'chn', 'day', 'dlm', 'dsz', 'eom', 'ers', 'esc',
+            'gfn', 'gid', 'hfn', 'hlp', 'hwd', 'lfa', 'lfo', 'lip',
+            'lpg', 'lwd', 'mse', 'msl', 'nar', 'nid', 'pgn', 'psz',
+            'quo', 'ret', 'sid', 'ssn', 'tim', 'tme', 'tms', 'tsm',
+            'uid', 'unt', 'who'
+
+            ),
+        4 => array(
+            // Nomads Variables
+            '%Flmaint_Lib$', '%Flmaint_Msg$', '%Nomads_Activation_Ok',
+            '%Nomads_Auto_Qry', '%Nomads_Disable_Debug',
+            '%Nomads_Disable_Trace', '%Nomads_Fkey_Handler$',
+            '%Nomads_Fkey_Tbl$', '%Nomads_Notest', '%Nomads_Onexit$',
+            '%Nomads_Post_Display', '%Nomads_Pre_Display$',
+            '%Nomads_Process$', '%Nomads_Trace_File$',
+            '%Nomad_Actv_Folder_Colors$', '%Nomad_Automation_Enabled',
+            '%Nomad_Auto_Close', '%Nomad_Center_Wdw', '%Nomad_Concurrent_Wdw',
+            '%Nomad_Custom_Define', '%Nomad_Custom_Dir$',
+            '%Nomad_Custom_Genmtc', '%Nomad_Custom_Skip_Definition',
+            '%Nomad_Def_Sfx$', '%Nomad_Enter_Tab', '%Nomad_Esc_Sel',
+            '%Nomad_Isjavx', '%Nomad_Iswindx', '%Nomad_Iswindx$',
+            '%Nomad_Menu$', '%Nomad_Menu_Leftedge_Clr$',
+            '%Nomad_Menu_Textbackground_Clr$', '%Nomad_Mln_Sep$',
+            '%Nomad_Msgmnt$', '%Nomad_Noplusw', '%Nomad_No_Customize',
+            '%Nomad_Object_Persistence', '%Nomad_Object_Resize',
+            '%Nomad_Open_Load', '%Nomad_Override_Font$',
+            '%Nomad_Palette_Loaded', '%Nomad_Panel_Info_Force',
+            '%Nomad_Panel_Info_Prog$', '%Nomad_Pnl_Def_Colour$',
+            '%Nomad_Pnl_Def_Font$', '%Nomad_Prg_Cache', '%Nomad_Qry_Attr$',
+            '%Nomad_Qry_Btn$', '%Nomad_Qry_Clear_Start', '%Nomad_Qry_Tip$',
+            '%Nomad_Qry_Wide', '%Nomad_Query_Clear_Status', '%Nomad_Query_Kno',
+            '%Nomad_Query_No_Gray', '%Nomad_Query_Odb_Ignore',
+            '%Nomad_Query_Retkno', '%Nomad_Query_Sbar_Max',
+            '%Nomad_Relative_Wdw', '%Nomad_Save_Qry_Path', '%Nomad_Script_Fn',
+            '%Nomad_Script_Log', '%Nomad_Script_Wdw',
+            '%Nomad_Skip_Change_Logic', '%Nomad_Skip_Onselect_Logic',
+            '%Nomad_Stk$', '%Nomad_Tab_Dir', '%Nomad_Timeout',
+            '%Nomad_Turbo_Off', '%Nomad_Visual_Effect',
+            '%Nomad_Visual_Override', '%Nomad_Win_Ver', '%Nomad_Xchar',
+            '%Nomad_Xmax', '%Nomad_Ychar', '%Nomad_Ymax', '%Scr_Def_Attr$',
+            '%Scr_Def_H_Fl$', '%Scr_Def_H_Id$', '%Scr_Lib', '%Scr_Lib$',
+            '%Z__Usr_Sec$', 'Alternate_Panel$', 'Alternate_Panel_Type$',
+            'Arg_1$', 'Arg_10$', 'Arg_11$', 'Arg_12$', 'Arg_13$', 'Arg_14$',
+            'Arg_15$', 'Arg_16$', 'Arg_17$', 'Arg_18$', 'Arg_19$', 'Arg_2$',
+            'Arg_20$', 'Arg_3$', 'Arg_4$', 'Arg_5$', 'Arg_6$', 'Arg_7$',
+            'Arg_8$', 'Arg_9$', 'Change_Flg', 'Cmd_Str$', 'Default_Prog$',
+            'Disp_Cmd$', 'Entire_Record$', 'Exit_Cmd$', 'Fldr_Default_Prog$',
+            'Folder_Id$', 'Id', 'Id$', 'Ignore_Exit', 'Initialize_Flg',
+            'Init_Text$', 'Init_Val$', 'Main_Scrn_K$', 'Mnu_Ln$',
+            'Next_Folder', 'Next_Id', 'Next_Id$', 'No_Flush', 'Prime_Key$',
+            'Prior_Val', 'Prior_Val$', 'Qry_Val$', 'Refresh_Flg',
+            'Replacement_Folder$', 'Replacement_Lib$', 'Replacement_Scrn$',
+            'Scrn_Id$', 'Scrn_K$', 'Scrn_Lib$', 'Tab_Table$', '_Eom$'
+            ),
+        5 => array(
+            // Mnemonics
+            "'!w'", "'*c'", "'*h'", "'*i'", "'*o'", "'*r'", "'*x'",
+            "'+b'", "'+d'", "'+e'", "'+f'", "'+i'", "'+n'",
+            "'+p'", "'+s'", "'+t'", "'+u'", "'+v'", "'+w'", "'+x'",
+            "'+z'", "'-b'", "'-d'", "'-e'", "'-f'", "'-i'",
+            "'-n'", "'-p'", "'-s'", "'-t'", "'-u'", "'-v'", "'-w'",
+            "'-x'", "'-z'", "'2d'", "'3d'", "'4d'", "'@@'", "'ab'",
+            "'arc'", "'at'", "'backgr'", "'bb'", "'be'", "'beep'",
+            "'bg'", "'bi'", "'bj'", "'bk'", "'black'", "'blue'",
+            "'bm'", "'bo'", "'box'", "'br'", "'bs'", "'bt'", "'bu'",
+            "'bw'", "'bx'", "'caption'", "'ce'", "'cf'", "'ch'",
+            "'ci'", "'circle'", "'cl'", "'colour'", "'cp'", "'cpi'",
+            "'cr'", "'cs'", "'cursor'", "'cyan''_cyan'", "'dc'",
+            "'default'", "'df'", "'dialogue'", "'dn'", "'do'",
+            "'drop'", "'eb'", "'ee'", "'ef'", "'eg'", "'ei'", "'ej'",
+            "'el'", "'em'", "'eo'", "'ep'", "'er'", "'es'", "'et'",
+            "'eu'", "'ew'", "'ff'", "'fill'", "'fl'", "'font'",
+            "'frame'", "'gd'", "'ge'", "'gf'", "'goto'", "'green'",
+            "'gs'", "'hide'", "'ic'", "'image'", "'jc'",
+            "'jd'", "'jl'", "'jn'", "'jr'", "'js'", "'l6'", "'l8'",
+            "'lc'", "'ld'", "'lf'", "'li'", "'line'", "'lm'",
+            "'lpi'", "'lt'", "'magenta'", "'maxsize'", "'me'",
+            "'message'", "'minsize'", "'mn'", "'mode'",
+            "'move'", "'mp'", "'ms'", "'ni'", "'offset'", "'option'",
+            "'pe'", "'pen'", "'picture'", "'pie'", "'pm'", "'polygon'",
+            "'pop'", "'ps'", "'push'", "'rb'", "'rc'", "'rectangle'",
+            "'red'", "'rl'", "'rm'", "'rp'", "'rs'", "'rt'", "'sb'",
+            "'scroll'", "'sd'", "'se'", "'sf'", "'show'", "'size'",
+            "'sl'", "'sn'", "'sp'", "'sr'", "'swap'", "'sx'", "'text'",
+            "'textwdw'", "'tr'", "'tw'", "'uc'", "'up'", "'vt'", "'wa'",
+            "'wc'", "'wd'", "'wg'", "'white'", "'window'", "'wm'",
+            "'wp'", "'wr'", "'wrap'", "'ws'", "'wx'", "'xp'", "'yellow'",
+            "'zx'", "'_black'", "'_blue'", "'_colour'", "'_green'",
+            "'_magenta'", "'_red'", "'_white'", "'_yellow'"
+            ),
+        ),
+    'SYMBOLS' => array(
+        0 => array('+', '-', '*', '/', '^', '|'),
+        1 => array('++', '--', '+=', '-=', '*=', '/=', '^=', '|='),
+        2 => array('&lt;', '&gt;', '='),
+        3 => array('(', ')', '[', ']', '{', '}'),
+        4 => array(',', '@', ';', '\\')
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        5 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: navy;', // Directives
+            2 => 'color: blue;', // System Functions
+            3 => 'color: blue;', // System Variables
+            4 => 'color: #6A5ACD; font-style: italic;', // Nomads Global Variables
+            5 => 'color: #BDB76B;', // Mnemonics
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #008080; font-style: italic;',
+            2 => 'color: #008080;',
+            'MULTI' => 'color: #008080; font-style: italic;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000066;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: green;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #00008B;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #008000;',
+            1 => 'color: #000099;',
+            2 => 'color: #000099;',
+            3 => 'color: #0000C9;',
+            4 => 'color: #000099;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            1 => 'color: #006400; font-weight: bold',
+            2 => 'color: #6A5ACD;'
+            )
+        ),
+    'URLS' => array(
+        1 => 'http://www.allbasic.info./wiki/index.php/PX:Directive_{FNAME}',
+        2 => 'http://www.allbasic.info./wiki/index.php/PX:System_function_{FNAME}',
+        3 => 'http://www.allbasic.info./wiki/index.php/PX:System_variable_{FNAME}',
+        4 => 'http://www.allbasic.info./wiki/index.php/PX:Nomads_{FNAME}',
+        5 => 'http://www.allbasic.info./wiki/index.php/PX:Mnemonic_{FNAMEU}'
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => "'"
+        ),
+    'REGEXPS' => array(
+        1 => array(
+            // Line Labels
+            GESHI_SEARCH => '([[:space:]])([a-zA-Z_][a-zA-Z0-9_]+)(:)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => '\\3'
+            ),
+        2 => array(
+            // Global String Variables
+            GESHI_SEARCH => '(\%)([a-zA-Z_][a-zA-Z0-9_]+)(\$)',
+            GESHI_REPLACE => '\\1\\2\\3',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            )
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'PARSER_CONTROL' => array(
+        'ENABLE_FLAGS' => array(
+            'NUMBERS' => GESHI_NEVER
+            )
+        ),
+    'TAB_WIDTH' => 4
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/python.php b/examples/includes/geshi/geshi/python.php
new file mode 100644 (file)
index 0000000..fbc6cab
--- /dev/null
@@ -0,0 +1,237 @@
+<?php
+/*************************************************************************************
+ * python.php
+ * ----------
+ * Author: Roberto Rossi (rsoftware@altervista.org)
+ * Copyright: (c) 2004 Roberto Rossi (http://rsoftware.altervista.org), Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/08/30
+ *
+ * Python language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/12/18
+ *  -  Added missing functions and keywords. Also added two new Python 3.0 types. SF#2441839
+ * 2005/05/26
+ *  -  Modifications by Tim (tim@skreak.com): added more keyword categories, tweaked colors
+ * 2004/11/27 (1.0.1)
+ *  -  Added support for multiple object splitters
+ * 2004/08/30 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Python',
+    'COMMENT_SINGLE' => array(1 => '#'),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    //Longest quotemarks ALWAYS first
+    'QUOTEMARKS' => array('"""', '"', "'"),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+
+        /*
+        ** Set 1: reserved words
+        ** http://python.org/doc/current/ref/keywords.html
+        */
+        1 => array(
+            'and', 'del', 'for', 'is', 'raise', 'assert', 'elif', 'from', 'lambda', 'return', 'break',
+            'else', 'global', 'not', 'try', 'class', 'except', 'if', 'or', 'while', 'continue', 'exec',
+            'import', 'pass', 'yield', 'def', 'finally', 'in', 'print', 'with', 'as'
+            ),
+
+        /*
+        ** Set 2: builtins
+        ** http://python.org/doc/current/lib/built-in-funcs.html
+        */
+        2 => array(
+            '__import__', 'abs', 'basestring', 'bool', 'callable', 'chr', 'classmethod', 'cmp',
+            'compile', 'complex', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'execfile',
+            'file', 'filter', 'float', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help',
+            'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'list', 'locals',
+            'long', 'map', 'max', 'min', 'object', 'oct', 'open', 'ord', 'pow', 'property', 'range',
+            'raw_input', 'reduce', 'reload', 'reversed', 'round', 'set', 'setattr', 'slice',
+            'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'unichr', 'unicode',
+            'vars', 'xrange', 'zip',
+            // Built-in constants: http://python.org/doc/current/lib/node35.html
+            'False', 'True', 'None', 'NotImplemented', 'Ellipsis',
+            // Built-in Exceptions: http://python.org/doc/current/lib/module-exceptions.html
+            'Exception', 'StandardError', 'ArithmeticError', 'LookupError', 'EnvironmentError',
+            'AssertionError', 'AttributeError', 'EOFError', 'FloatingPointError', 'IOError',
+            'ImportError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'MemoryError', 'NameError',
+            'NotImplementedError', 'OSError', 'OverflowError', 'ReferenceError', 'RuntimeError',
+            'StopIteration', 'SyntaxError', 'SystemError', 'SystemExit', 'TypeError',
+            'UnboundlocalError', 'UnicodeError', 'UnicodeEncodeError', 'UnicodeDecodeError',
+            'UnicodeTranslateError', 'ValueError', 'WindowsError', 'ZeroDivisionError', 'Warning',
+            'UserWarning', 'DeprecationWarning', 'PendingDeprecationWarning', 'SyntaxWarning',
+            'RuntimeWarning', 'FutureWarning',
+            // self: this is a common python convention (but not a reserved word)
+            'self',
+            // other
+            'any', 'all'
+            ),
+
+        /*
+        ** Set 3: standard library
+        ** http://python.org/doc/current/lib/modindex.html
+        */
+        3 => array(
+            '__builtin__', '__future__', '__main__', '_winreg', 'aifc', 'AL', 'al', 'anydbm',
+            'array', 'asynchat', 'asyncore', 'atexit', 'audioop', 'base64', 'BaseHTTPServer',
+            'Bastion', 'binascii', 'binhex', 'bisect', 'bsddb', 'bz2', 'calendar', 'cd', 'cgi',
+            'CGIHTTPServer', 'cgitb', 'chunk', 'cmath', 'cmd', 'code', 'codecs', 'codeop',
+            'collections', 'colorsys', 'commands', 'compileall', 'compiler',
+            'ConfigParser', 'Cookie', 'cookielib', 'copy', 'copy_reg', 'cPickle', 'crypt',
+            'cStringIO', 'csv', 'curses', 'datetime', 'dbhash', 'dbm', 'decimal', 'DEVICE',
+            'difflib', 'dircache', 'dis', 'distutils', 'dl', 'doctest', 'DocXMLRPCServer', 'dumbdbm',
+            'dummy_thread', 'dummy_threading', 'email', 'encodings', 'errno', 'exceptions', 'fcntl',
+            'filecmp', 'fileinput', 'FL', 'fl', 'flp', 'fm', 'fnmatch', 'formatter', 'fpectl',
+            'fpformat', 'ftplib', 'gc', 'gdbm', 'getopt', 'getpass', 'gettext', 'GL', 'gl', 'glob',
+            'gopherlib', 'grp', 'gzip', 'heapq', 'hmac', 'hotshot', 'htmlentitydefs', 'htmllib',
+            'HTMLParser', 'httplib', 'imageop', 'imaplib', 'imgfile', 'imghdr', 'imp', 'inspect',
+            'itertools', 'jpeg', 'keyword', 'linecache', 'locale', 'logging', 'mailbox', 'mailcap',
+            'marshal', 'math', 'md5', 'mhlib', 'mimetools', 'mimetypes', 'MimeWriter', 'mimify',
+            'mmap', 'msvcrt', 'multifile', 'mutex', 'netrc', 'new', 'nis', 'nntplib', 'operator',
+            'optparse', 'os', 'ossaudiodev', 'parser', 'pdb', 'pickle', 'pickletools', 'pipes',
+            'pkgutil', 'platform', 'popen2', 'poplib', 'posix', 'posixfile', 'pprint', 'profile',
+            'pstats', 'pty', 'pwd', 'py_compile', 'pyclbr', 'pydoc', 'Queue', 'quopri', 'random',
+            're', 'readline', 'repr', 'resource', 'rexec', 'rfc822', 'rgbimg', 'rlcompleter',
+            'robotparser', 'sched', 'ScrolledText', 'select', 'sets', 'sgmllib', 'sha', 'shelve',
+            'shlex', 'shutil', 'signal', 'SimpleHTTPServer', 'SimpleXMLRPCServer', 'site', 'smtpd',
+            'smtplib', 'sndhdr', 'socket', 'SocketServer', 'stat', 'statcache', 'statvfs', 'string',
+            'StringIO', 'stringprep', 'struct', 'subprocess', 'sunau', 'SUNAUDIODEV', 'sunaudiodev',
+            'symbol', 'sys', 'syslog', 'tabnanny', 'tarfile', 'telnetlib', 'tempfile', 'termios',
+            'test', 'textwrap', 'thread', 'threading', 'time', 'timeit', 'Tix', 'Tkinter', 'token',
+            'tokenize', 'traceback', 'tty', 'turtle', 'types', 'unicodedata', 'unittest', 'urllib2',
+            'urllib', 'urlparse', 'user', 'UserDict', 'UserList', 'UserString', 'uu', 'warnings',
+            'wave', 'weakref', 'webbrowser', 'whichdb', 'whrandom', 'winsound', 'xdrlib', 'xml',
+            'xmllib', 'xmlrpclib', 'zipfile', 'zipimport', 'zlib',
+            // Python 3.0
+            'bytes', 'bytearray'
+            ),
+
+        /*
+        ** Set 4: special methods
+        ** http://python.org/doc/current/ref/specialnames.html
+        */
+        4 => array(
+            /*
+            // Iterator types: http://python.org/doc/current/lib/typeiter.html
+            '__iter__', 'next',
+            // String types: http://python.org/doc/current/lib/string-methods.html
+            'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs',
+            'find', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle',
+            'isupper', 'join', 'ljust', 'lower', 'lstrip', 'replace', 'rfind', 'rindex', 'rjust',
+            'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title',
+            'translate', 'upper', 'zfill',
+            */
+            // Basic customization: http://python.org/doc/current/ref/customization.html
+            '__new__', '__init__', '__del__', '__repr__', '__str__',
+            '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__cmp__', '__rcmp__',
+            '__hash__', '__nonzero__', '__unicode__', '__dict__',
+            // Attribute access: http://python.org/doc/current/ref/attribute-access.html
+            '__setattr__', '__delattr__', '__getattr__', '__getattribute__', '__get__', '__set__',
+            '__delete__', '__slots__',
+            // Class creation, callable objects
+            '__metaclass__', '__call__',
+            // Container types: http://python.org/doc/current/ref/sequence-types.html
+            '__len__', '__getitem__', '__setitem__', '__delitem__', '__iter__', '__contains__',
+            '__getslice__', '__setslice__', '__delslice__',
+            // Numeric types: http://python.org/doc/current/ref/numeric-types.html
+            '__abs__','__add__','__and__','__coerce__','__div__','__divmod__','__float__',
+            '__hex__','__iadd__','__isub__','__imod__','__idiv__','__ipow__','__iand__',
+            '__ior__','__ixor__', '__ilshift__','__irshift__','__invert__','__int__',
+            '__long__','__lshift__',
+            '__mod__','__mul__','__neg__','__oct__','__or__','__pos__','__pow__',
+            '__radd__','__rdiv__','__rdivmod__','__rmod__','__rpow__','__rlshift__','__rrshift__',
+            '__rshift__','__rsub__','__rmul__','__rand__','__rxor__','__ror__',
+            '__sub__','__xor__'
+            )
+        ),
+    'SYMBOLS' => array(
+            '(', ')', '[', ']', '{', '}', '*', '&', '%', '!', ';', '<', '>', '?', '`'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #ff7700;font-weight:bold;',    // Reserved
+            2 => 'color: #008000;',                        // Built-ins + self
+            3 => 'color: #dc143c;',                        // Standard lib
+            4 => 'color: #0000cd;'                        // Special methods
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: black;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #483d8b;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #ff4500;'
+            ),
+        'METHODS' => array(
+            1 => 'color: black;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/qbasic.php b/examples/includes/geshi/geshi/qbasic.php
new file mode 100644 (file)
index 0000000..f6531f7
--- /dev/null
@@ -0,0 +1,151 @@
+<?php
+/*************************************************************************************
+ * qbasic.php
+ * ----------
+ * Author: Nigel McNie (nigel@geshi.org)
+ * Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/06/20
+ *
+ * QBasic/QuickBASIC language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *  -  Added description of extra language features (SF#1970248)
+ * 2004/11/27 (1.0.3)
+ *  -  Added support for multiple object splitters
+ * 2004/10/27 (1.0.2)
+ *   -  Added support for URLs
+ * 2004/08/05 (1.0.1)
+ *   -  Added support for symbols
+ *   -  Removed unnessecary slashes from some keywords
+ * 2004/07/14 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ * * Make sure all possible combinations of keywords with
+ *   a space in them (EXIT FOR, END SELECT) are added
+ *   to the first keyword group
+ * * Update colours, especially for the first keyword group
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+$language_data = array (
+    'LANG_NAME' => 'QBasic/QuickBASIC',
+    'COMMENT_SINGLE' => array(1 => "'"),
+    'COMMENT_MULTI' => array(),
+    'COMMENT_REGEXP' => array(
+        //Single-Line Comments using REM command
+        2 => "/\bREM.*?$/i"
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_UPPER,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            'DO', 'LOOP', 'WHILE', 'WEND', 'THEN', 'ELSE', 'ELSEIF', 'IF',
+            'FOR', 'TO', 'NEXT', 'STEP', 'GOTO', 'GOSUB', 'CALL', 'CALLS',
+            'SUB', 'FUNCTION', 'RETURN', 'RESUME', 'SELECT', 'CASE', 'UNTIL'
+            ),
+        3 => array(
+            'ABS', 'ABSOLUTE', 'ACCESS', 'ALIAS', 'AND', 'ANY', 'APPEND', 'AS', 'ASC', 'ATN',
+            'BASE', 'BEEP', 'BINARY', 'BLOAD', 'BSAVE', 'BYVAL',
+            'CDBL', 'CDECL', 'CHAIN', 'CHDIR', 'CHR$', 'CINT', 'CIRCLE', 'CLEAR',
+            'CLNG', 'CLOSE', 'CLS', 'COM', 'COMMAND$', 'COMMON', 'CONST', 'COS', 'CSNG',
+            'CSRLIN', 'CVD', 'CVDMBF', 'CVI', 'CVL', 'CVS', 'CVSMDF', 'DATA', 'DATE$',
+            'DECLARE', 'DEF', 'FN', 'SEG', 'DEFDBL', 'DEFINT', 'DEFLNG', 'DEFSNG', 'DEFSTR',
+            'DIM', 'DOUBLE', 'DRAW', 'END', 'ENVIRON', 'ENVIRON$', 'EOF', 'EQV', 'ERASE',
+            'ERDEV', 'ERDEV$', 'ERL', 'ERR', 'ERROR', 'EXIT', 'EXP', 'FIELD', 'FILEATTR',
+            'FILES', 'FIX', 'FRE', 'FREEFILE', 'GET', 'HEX$', 'IMP', 'INKEY$',
+            'INP', 'INPUT', 'INPUT$', 'INSTR', 'INT', 'INTEGER', 'IOCTL', 'IOCTL$', 'IS',
+            'KEY', 'KILL', 'LBOUND', 'LCASE$', 'LEFT$', 'LEN', 'LET', 'LINE', 'LIST', 'LOC',
+            'LOCAL', 'LOCATE', 'LOCK', 'LOF', 'LOG', 'LONG', 'LPOS', 'LPRINT',
+            'LSET', 'LTRIM$', 'MID$', 'MKD$', 'MKDIR', 'MKDMBF$', 'MKI$', 'MKL$',
+            'MKS$', 'MKSMBF$', 'MOD', 'NAME', 'NOT', 'OCT$', 'OFF', 'ON', 'PEN', 'PLAY',
+            'OPEN', 'OPTION', 'OR', 'OUT', 'OUTPUT',
+            'PAINT', 'PALETTE', 'PCOPY', 'PEEK', 'PMAP', 'POINT', 'POKE', 'POS', 'PRESET',
+            'PRINT', 'PSET', 'PUT', 'RANDOM', 'RANDOMIZE', 'READ', 'REDIM', 'RESET',
+            'RESTORE', 'RIGHT$', 'RMDIR', 'RND', 'RSET', 'RTRIM$', 'RUN', 'SADD', 'SCREEN',
+            'SEEK', 'SETMEM', 'SGN', 'SHARED', 'SHELL', 'SIGNAL', 'SIN', 'SINGLE', 'SLEEP',
+            'SOUND', 'SPACE$', 'SPC', 'SQR', 'STATIC', 'STICK', 'STOP', 'STR$', 'STRIG',
+            'STRING', 'STRING$', 'SWAP', 'SYSTEM', 'TAB', 'TAN', 'TIME$', 'TIMER',
+            'TROFF', 'TRON', 'TYPE', 'UBOUND', 'UCASE$', 'UEVENT', 'UNLOCK', 'USING', 'VAL',
+            'VARPTR', 'VARPTR$', 'VARSEG', 'VIEW', 'WAIT', 'WIDTH', 'WINDOW', 'WRITE', 'XOR'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', ',', '+', '-', '*', '/', '=', '<', '>'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        3 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #a1a100;',
+            3 => 'color: #000066;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080;',
+            2 => 'color: #808080;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        3 => 'http://www.qbasicnews.com/qboho/qck{FNAMEL}.shtml'
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 8
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/rails.php b/examples/includes/geshi/geshi/rails.php
new file mode 100644 (file)
index 0000000..52c70a6
--- /dev/null
@@ -0,0 +1,406 @@
+<?php
+/*************************************************************************************
+ * rails.php
+ * ---------
+ * Author: Moises Deniz
+ * Copyright: (c) 2005 Moises Deniz
+ * Release Version: 1.0.8.3
+ * Date Started: 2007/03/21
+ *
+ * Ruby (with Ruby on Rails Framework) language file for GeSHi.
+ *
+ *************************************************************************************
+ *
+ *   This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Rails',
+    'COMMENT_SINGLE' => array(1 => "#"),
+    'COMMENT_MULTI' => array("=begin" => "=end"),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"', '`','\''),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'alias', 'and', 'begin', 'break', 'case', 'class',
+            'def', 'defined', 'do', 'else', 'elsif', 'end',
+            'ensure', 'for', 'if', 'in', 'module', 'while',
+            'next', 'not', 'or', 'redo', 'rescue', 'yield',
+            'retry', 'super', 'then', 'undef', 'unless',
+            'until', 'when', 'BEGIN', 'END', 'include'
+            ),
+        2 => array(
+            '__FILE__', '__LINE__', 'false', 'nil', 'self', 'true',
+            'return'
+            ),
+        3 => array(
+            'Array', 'Float', 'Integer', 'String', 'at_exit',
+            'autoload', 'binding', 'caller', 'catch', 'chop', 'chop!',
+            'chomp', 'chomp!', 'eval', 'exec', 'exit', 'exit!', 'fail',
+            'fork', 'format', 'gets', 'global_variables', 'gsub', 'gsub!',
+            'iterator?', 'lambda', 'load', 'local_variables', 'loop',
+            'open', 'p', 'print', 'printf', 'proc', 'putc', 'puts',
+            'raise', 'rand', 'readline', 'readlines', 'require', 'select',
+            'sleep', 'split', 'sprintf', 'srand', 'sub', 'sub!', 'syscall',
+            'system', 'trace_var', 'trap', 'untrace_var'
+            ),
+        4 => array(
+            'Abbrev', 'ArgumentError', 'Base64', 'Benchmark',
+            'Benchmark::Tms', 'Bignum', 'Binding', 'CGI', 'CGI::Cookie',
+            'CGI::HtmlExtension', 'CGI::QueryExtension',
+            'CGI::Session', 'CGI::Session::FileStore',
+            'CGI::Session::MemoryStore', 'Class', 'Comparable', 'Complex',
+            'ConditionVariable', 'Continuation', 'Data',
+            'Date', 'DateTime', 'Delegator', 'Dir', 'EOFError', 'ERB',
+            'ERB::Util', 'Enumerable', 'Enumerable::Enumerator', 'Errno',
+            'Exception', 'FalseClass', 'File',
+            'File::Constants', 'File::Stat', 'FileTest', 'FileUtils',
+            'FileUtils::DryRun', 'FileUtils::NoWrite',
+            'FileUtils::StreamUtils_', 'FileUtils::Verbose', 'Find',
+            'Fixnum', 'FloatDomainError', 'Forwardable', 'GC', 'Generator',
+            'Hash', 'IO', 'IOError', 'Iconv', 'Iconv::BrokenLibrary',
+            'Iconv::Failure', 'Iconv::IllegalSequence',
+            'Iconv::InvalidCharacter', 'Iconv::InvalidEncoding',
+            'Iconv::OutOfRange', 'IndexError', 'Interrupt', 'Kernel',
+            'LoadError', 'LocalJumpError', 'Logger', 'Logger::Application',
+            'Logger::Error', 'Logger::Formatter', 'Logger::LogDevice',
+            'Logger::LogDevice::LogDeviceMutex', 'Logger::Severity',
+            'Logger::ShiftingError', 'Marshal', 'MatchData',
+            'Math', 'Matrix', 'Method', 'Module', 'Mutex', 'NameError',
+            'NameError::message', 'NilClass', 'NoMemoryError',
+            'NoMethodError', 'NotImplementedError', 'Numeric', 'Object',
+            'ObjectSpace', 'Observable', 'PStore', 'PStore::Error',
+            'Pathname', 'Precision', 'Proc', 'Process', 'Process::GID',
+            'Process::Status', 'Process::Sys', 'Process::UID', 'Queue',
+            'Range', 'RangeError', 'Rational', 'Regexp', 'RegexpError',
+            'RuntimeError', 'ScriptError', 'SecurityError', 'Set',
+            'Shellwords', 'Signal', 'SignalException', 'SimpleDelegator',
+            'SingleForwardable', 'Singleton', 'SingletonClassMethods',
+            'SizedQueue', 'SortedSet', 'StandardError', 'StringIO',
+            'StringScanner', 'StringScanner::Error', 'Struct', 'Symbol',
+            'SyncEnumerator', 'SyntaxError', 'SystemCallError',
+            'SystemExit', 'SystemStackError', 'Tempfile',
+            'Test::Unit::TestCase', 'Test::Unit', 'Test', 'Thread',
+            'ThreadError', 'ThreadGroup',
+            'ThreadsWait', 'Time', 'TrueClass', 'TypeError', 'URI',
+            'URI::BadURIError', 'URI::Error', 'URI::Escape', 'URI::FTP',
+            'URI::Generic', 'URI::HTTP', 'URI::HTTPS',
+            'URI::InvalidComponentError', 'URI::InvalidURIError',
+            'URI::LDAP', 'URI::MailTo', 'URI::REGEXP',
+            'URI::REGEXP::PATTERN', 'UnboundMethod', 'Vector', 'YAML',
+            'ZeroDivisionError', 'Zlib',
+            'Zlib::BufError', 'Zlib::DataError', 'Zlib::Deflate',
+            'Zlib::Error', 'Zlib::GzipFile', 'Zlib::GzipFile::CRCError',
+            'Zlib::GzipFile::Error', 'Zlib::GzipFile::LengthError',
+            'Zlib::GzipFile::NoFooter', 'Zlib::GzipReader',
+            'Zlib::GzipWriter', 'Zlib::Inflate', 'Zlib::MemError',
+            'Zlib::NeedDict', 'Zlib::StreamEnd', 'Zlib::StreamError',
+            'Zlib::VersionError',
+            'Zlib::ZStream',
+            'ActionController::AbstractRequest',
+            'ActionController::Assertions::DomAssertions',
+            'ActionController::Assertions::ModelAssertions',
+            'ActionController::Assertions::ResponseAssertions',
+            'ActionController::Assertions::RoutingAssertions',
+            'ActionController::Assertions::SelectorAssertions',
+            'ActionController::Assertions::TagAssertions',
+            'ActionController::Base',
+            'ActionController::Benchmarking::ClassMethods',
+            'ActionController::Caching',
+            'ActionController::Caching::Actions',
+            'ActionController::Caching::Actions::ActionCachePath',
+            'ActionController::Caching::Fragments',
+            'ActionController::Caching::Pages',
+            'ActionController::Caching::Pages::ClassMethods',
+            'ActionController::Caching::Sweeping',
+            'ActionController::Components',
+            'ActionController::Components::ClassMethods',
+            'ActionController::Components::InstanceMethods',
+            'ActionController::Cookies',
+            'ActionController::Filters::ClassMethods',
+            'ActionController::Flash',
+            'ActionController::Flash::FlashHash',
+            'ActionController::Helpers::ClassMethods',
+            'ActionController::Integration::Session',
+            'ActionController::IntegrationTest',
+            'ActionController::Layout::ClassMethods',
+            'ActionController::Macros',
+            'ActionController::Macros::AutoComplete::ClassMethods',
+            'ActionController::Macros::InPlaceEditing::ClassMethods',
+            'ActionController::MimeResponds::InstanceMethods',
+            'ActionController::Pagination',
+            'ActionController::Pagination::ClassMethods',
+            'ActionController::Pagination::Paginator',
+            'ActionController::Pagination::Paginator::Page',
+            'ActionController::Pagination::Paginator::Window',
+            'ActionController::Rescue', 'ActionController::Resources',
+            'ActionController::Routing',
+            'ActionController::Scaffolding::ClassMethods',
+            'ActionController::SessionManagement::ClassMethods',
+            'ActionController::Streaming', 'ActionController::TestProcess',
+            'ActionController::TestUploadedFile',
+            'ActionController::UrlWriter',
+            'ActionController::Verification::ClassMethods',
+            'ActionMailer::Base', 'ActionView::Base',
+            'ActionView::Helpers::ActiveRecordHelper',
+            'ActionView::Helpers::AssetTagHelper',
+            'ActionView::Helpers::BenchmarkHelper',
+            'ActionView::Helpers::CacheHelper',
+            'ActionView::Helpers::CaptureHelper',
+            'ActionView::Helpers::DateHelper',
+            'ActionView::Helpers::DebugHelper',
+            'ActionView::Helpers::FormHelper',
+            'ActionView::Helpers::FormOptionsHelper',
+            'ActionView::Helpers::FormTagHelper',
+            'ActionView::Helpers::JavaScriptHelper',
+            'ActionView::Helpers::JavaScriptMacrosHelper',
+            'ActionView::Helpers::NumberHelper',
+            'ActionView::Helpers::PaginationHelper',
+            'ActionView::Helpers::PrototypeHelper',
+            'ActionView::Helpers::PrototypeHelper::JavaScriptGenerator::GeneratorMethods',
+            'ActionView::Helpers::ScriptaculousHelper',
+            'ActionView::Helpers::TagHelper',
+            'ActionView::Helpers::TextHelper',
+            'ActionView::Helpers::UrlHelper', 'ActionView::Partials',
+            'ActionWebService::API::Method', 'ActionWebService::Base',
+            'ActionWebService::Client::Soap',
+            'ActionWebService::Client::XmlRpc',
+            'ActionWebService::Container::ActionController::ClassMethods',
+            'ActionWebService::Container::Delegated::ClassMethods',
+            'ActionWebService::Container::Direct::ClassMethods',
+            'ActionWebService::Invocation::ClassMethods',
+            'ActionWebService::Scaffolding::ClassMethods',
+            'ActionWebService::SignatureTypes', 'ActionWebService::Struct',
+            'ActiveRecord::Acts::List::ClassMethods',
+            'ActiveRecord::Acts::List::InstanceMethods',
+            'ActiveRecord::Acts::NestedSet::ClassMethods',
+            'ActiveRecord::Acts::NestedSet::InstanceMethods',
+            'ActiveRecord::Acts::Tree::ClassMethods',
+            'ActiveRecord::Acts::Tree::InstanceMethods',
+            'ActiveRecord::Aggregations::ClassMethods',
+            'ActiveRecord::Associations::ClassMethods',
+            'ActiveRecord::AttributeMethods::ClassMethods',
+            'ActiveRecord::Base',
+            'ActiveRecord::Calculations::ClassMethods',
+            'ActiveRecord::Callbacks',
+            'ActiveRecord::ConnectionAdapters::AbstractAdapter',
+            'ActiveRecord::ConnectionAdapters::Column',
+            'ActiveRecord::ConnectionAdapters::DB2Adapter',
+            'ActiveRecord::ConnectionAdapters::DatabaseStatements',
+            'ActiveRecord::ConnectionAdapters::FirebirdAdapter',
+            'ActiveRecord::ConnectionAdapters::FrontBaseAdapter',
+            'ActiveRecord::ConnectionAdapters::MysqlAdapter',
+            'ActiveRecord::ConnectionAdapters::OpenBaseAdapter',
+            'ActiveRecord::ConnectionAdapters::OracleAdapter',
+            'ActiveRecord::ConnectionAdapters::PostgreSQLAdapter',
+            'ActiveRecord::ConnectionAdapters::Quoting',
+            'ActiveRecord::ConnectionAdapters::SQLServerAdapter',
+            'ActiveRecord::ConnectionAdapters::SQLiteAdapter',
+            'ActiveRecord::ConnectionAdapters::SchemaStatements',
+            'ActiveRecord::ConnectionAdapters::SybaseAdapter::ColumnWithIdentity',
+            'ActiveRecord::ConnectionAdapters::SybaseAdapterContext',
+            'ActiveRecord::ConnectionAdapters::TableDefinition',
+            'ActiveRecord::Errors', 'ActiveRecord::Locking',
+            'ActiveRecord::Locking::Optimistic',
+            'ActiveRecord::Locking::Optimistic::ClassMethods',
+            'ActiveRecord::Locking::Pessimistic',
+            'ActiveRecord::Migration', 'ActiveRecord::Observer',
+            'ActiveRecord::Observing::ClassMethods',
+            'ActiveRecord::Reflection::ClassMethods',
+            'ActiveRecord::Reflection::MacroReflection',
+            'ActiveRecord::Schema', 'ActiveRecord::Timestamp',
+            'ActiveRecord::Transactions::ClassMethods',
+            'ActiveRecord::Validations',
+            'ActiveRecord::Validations::ClassMethods',
+            'ActiveRecord::XmlSerialization',
+            'ActiveSupport::CachingTools::HashCaching',
+            'ActiveSupport::CoreExtensions::Array::Conversions',
+            'ActiveSupport::CoreExtensions::Array::Grouping',
+            'ActiveSupport::CoreExtensions::Date::Conversions',
+            'ActiveSupport::CoreExtensions::Hash::Conversions',
+            'ActiveSupport::CoreExtensions::Hash::Conversions::ClassMethods',
+            'ActiveSupport::CoreExtensions::Hash::Diff',
+            'ActiveSupport::CoreExtensions::Hash::Keys',
+            'ActiveSupport::CoreExtensions::Hash::ReverseMerge',
+            'ActiveSupport::CoreExtensions::Integer::EvenOdd',
+            'ActiveSupport::CoreExtensions::Integer::Inflections',
+            'ActiveSupport::CoreExtensions::Numeric::Bytes',
+            'ActiveSupport::CoreExtensions::Numeric::Time',
+            'ActiveSupport::CoreExtensions::Pathname::CleanWithin',
+            'ActiveSupport::CoreExtensions::Range::Conversions',
+            'ActiveSupport::CoreExtensions::String::Access',
+            'ActiveSupport::CoreExtensions::String::Conversions',
+            'ActiveSupport::CoreExtensions::String::Inflections',
+            'ActiveSupport::CoreExtensions::String::Iterators',
+            'ActiveSupport::CoreExtensions::String::StartsEndsWith',
+            'ActiveSupport::CoreExtensions::String::Unicode',
+            'ActiveSupport::CoreExtensions::Time::Calculations',
+            'ActiveSupport::CoreExtensions::Time::Calculations::ClassMethods',
+            'ActiveSupport::CoreExtensions::Time::Conversions',
+            'ActiveSupport::Multibyte::Chars',
+            'ActiveSupport::Multibyte::Handlers::UTF8Handler',
+            'Breakpoint', 'Builder::BlankSlate', 'Builder::XmlMarkup',
+            'Fixtures',
+            'HTML::Selector', 'HashWithIndifferentAccess', 'Inflector',
+            'Inflector::Inflections', 'Mime', 'Mime::Type',
+            'OCI8AutoRecover', 'TimeZone', 'XmlSimple'
+            ),
+        5 => array(
+            'image_tag', 'link_to', 'link_to_remote', 'javascript_include_tag',
+            'assert_equal', 'assert_not_equal', 'before_filter',
+            'after_filter', 'render', 'redirect_to', 'hide_action',
+            'render_to_string', 'url_for', 'controller_name',
+            'controller_class_name', 'controller_path', 'session',
+            'render_component', 'render_component_as_string', 'cookie',
+            'layout', 'flash', 'auto_complete_for', 'in_place_editor_for',
+            'respond_to', 'paginate', 'current_page', 'each', 'first',
+            'first_page', 'last_page', 'last', 'length', 'new', 'page_count',
+            'previous', 'scaffold', 'send_data',
+            'send_file', 'deliver', 'receive', 'error_messages_for',
+            'error_message_on', 'form', 'input', 'stylesheet_link_tag',
+            'stylesheet_path', 'content_for', 'select_date', 'ago',
+            'month', 'day', 'check_box', 'fields_for', 'file_field',
+            'form_for', 'hidden_field', 'text_area', 'password_field',
+            'collection_select', 'options_for_select',
+            'options_from_collection_for_select', 'file_field_tag',
+            'form_for_tag', 'hidden_field_tag', 'text_area_tag',
+            'password_field_tag', 'link_to_function', 'javascript_tag',
+            'human_size', 'number_to_currency', 'pagination_links',
+            'form_remote_tag', 'form_remote_for',
+            'submit_to_remote', 'remote_function', 'observe_form',
+            'observe_field', 'remote_form_for', 'options_for_ajax', 'alert',
+            'call', 'assign', 'show', 'hide', 'insert_html', 'sortable',
+            'toggle', 'visual_effect', 'replace', 'replace_html', 'remove',
+            'save', 'save!', 'draggable', 'drop_receiving', 'literal',
+            'draggable_element', 'drop_receiving_element', 'sortable_element',
+            'content_tag', 'tag', 'link_to_image', 'link_to_if',
+            'link_to_unless', 'mail_to', 'link_image_to', 'button_to',
+            'current_page?', 'act_as_list', 'act_as_nested', 'act_as_tree',
+            'has_many', 'has_one', 'belongs_to', 'has_many_and_belogns_to',
+            'delete', 'destroy', 'destroy_all', 'clone', 'deep_clone', 'copy',
+            'update', 'table_name', 'primary_key', 'sum', 'maximun', 'minimum',
+            'count', 'size', 'after_save', 'after_create', 'before_save',
+            'before_create', 'add_to_base', 'errors', 'add', 'validate',
+            'validates_presence_of', 'validates_numericality_of',
+            'validates_uniqueness_of', 'validates_length_of',
+            'validates_format_of', 'validates_size_of', 'to_a', 'to_s',
+            'to_xml', 'to_i'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}', '%', '&', '*', '|', '/', '<', '>',
+        '+', '-', '=>', '<<'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true,
+        5 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color:#9966CC; font-weight:bold;',
+            2 => 'color:#0000FF; font-weight:bold;',
+            3 => 'color:#CC0066; font-weight:bold;',
+            4 => 'color:#CC00FF; font-weight:bold;',
+            5 => 'color:#5A0A0A; font-weight:bold;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color:#008000; font-style:italic;',
+                    'MULTI' => 'color:#000080; font-style:italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color:#000099;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color:#006600; font-weight:bold;'
+            ),
+        'STRINGS' => array(
+            0 => 'color:#996600;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color:#006666;'
+            ),
+        'METHODS' => array(
+            1 => 'color:#9900CC;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color:#006600; font-weight:bold;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color:#ff6633; font-weight:bold;',
+            1 => 'color:#0066ff; font-weight:bold;',
+            2 => 'color:#6666ff; font-weight:bold;',
+            3 => 'color:#ff3333; font-weight:bold;'
+            ),
+        'SCRIPT' => array(
+            0 => '',
+            1 => '',
+            2 => '',
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => '',
+        5 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        0 => array(
+            GESHI_SEARCH => "([[:space:]])(\\$[a-zA-Z_][a-zA-Z0-9_]*)",
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => ''
+            ),
+        1 => array(
+            GESHI_SEARCH => "([[:space:]])(@[a-zA-Z_][a-zA-Z0-9_]*)",
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => ''
+            ),
+        2 => "([A-Z][a-zA-Z0-9_]*::)+[A-Z][a-zA-Z0-9_]*", //Static OOP References
+        3 => array(
+            GESHI_SEARCH => "([[:space:]]|\[|\()(:[a-zA-Z_][a-zA-Z0-9_]*)",
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => ''
+            )
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_MAYBE,
+    'SCRIPT_DELIMITERS' => array(
+        0 => array(
+            '<%' => '%>'
+            )
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        0 => true,
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/rebol.php b/examples/includes/geshi/geshi/rebol.php
new file mode 100644 (file)
index 0000000..6f57137
--- /dev/null
@@ -0,0 +1,196 @@
+<?php
+/*************************************************************************************
+ * rebol.php
+ * --------
+ * Author: Lecanu Guillaume (Guillaume@LyA.fr)
+ * Copyright: (c) 2004-2005 Lecanu Guillaume (Guillaume@LyA.fr)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/12/22
+ *
+ * Rebol language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2009/01/26 (1.0.8.3)
+ *  -  Adapted language file to comply to GeSHi language file guidelines
+ * 2004/11/25 (1.0.3)
+ *  -  Added support for multiple object splitters
+ *  -  Fixed &new problem
+ * 2004/10/27 (1.0.2)
+ *  -  Added URL support
+ *  -  Added extra constants
+ * 2004/08/05 (1.0.1)
+ *  -  Added support for symbols
+ * 2004/07/14 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2004/07/14)
+ * -------------------------
+ * * Make sure the last few function I may have missed
+ *   (like eval()) are included for highlighting
+ * * Split to several files - php4, php5 etc
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'REBOL',
+    'COMMENT_SINGLE' => array(1 => ';'),
+    'COMMENT_MULTI' => array('rebol [' => ']', 'comment [' => ']'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            'binary!','block!','char!','date!','decimal!','email!','file!',
+            'hash!','integer!','issue!','list!','logic!','money!','none!',
+            'object!','paren!','pair!','path!','string!','tag!','time!',
+            'tuple!','url!',
+            ),
+        2 => array(
+            'all','any','attempt','break','catch','compose','disarm','dispatch',
+            'do','do-events','does','either','else','exit','for','forall',
+            'foreach','forever','forskip','func','function','halt','has','if',
+            'launch','loop','next','quit','reduce','remove-each','repeat',
+            'return','secure','switch','throw','try','until','wait','while',
+            ),
+        3 => array(
+            'about','abs','absolute','add','alert','alias','alter','and',
+            'any-block?','any-function?','any-string?','any-type?','any-word?',
+            'append','arccosine','arcsine','arctangent','array','as-pair',
+            'ask','at','back','binary?','bind','bitset?','block?','brightness?',
+            'browse','build-tag','caret-to-offset','center-face','change',
+            'change-dir','char?','charset','checksum','choose','clean-path',
+            'clear','clear-fields','close','comment','complement','component?',
+            'compress','confirm','connected?','construct','context','copy',
+            'cosine','datatype?','date?','debase','decimal?','decode-cgi',
+            'decompress','dehex','delete','detab','difference','dir?','dirize',
+            'divide','dump-face','dump-obj','echo','email?','empty?','enbase',
+            'entab','equal?','error?','even?','event?','exclude','exists?',
+            'exp','extract','fifth','file?','find','first','flash','focus',
+            'form','found?','fourth','free','function?','get','get-modes',
+            'get-word?','greater-or-equal?','greater?','hash?','head','head?',
+            'help','hide','hide-popup','image?','import-email','in',
+            'in-window?','index?','info?','inform','input','input?','insert',
+            'integer?','intersect','issue?','join','last','layout','length?',
+            'lesser-or-equal?','lesser?','library?','license','link?',
+            'list-dir','list?','lit-path?','lit-word?','load','load-image',
+            'log-10','log-2','log-e','logic?','lowercase','make','make-dir',
+            'make-face','max','maximum','maximum-of','min','minimum',
+            'minimum-of','modified?','mold','money?','multiply','native?',
+            'negate','negative?','none?','not','not-equal?','now','number?',
+            'object?','odd?','offset-to-caret','offset?','op?','open','or',
+            'pair?','paren?','parse','parse-xml','path?','pick','poke','port?',
+            'positive?','power','prin','print','probe','protect',
+            'protect-system','query','random','read','read-io','recycle',
+            'refinement?','reform','rejoin','remainder','remold','remove',
+            'rename',
+            //'repeat',
+            'repend','replace','request','request-color','request-date',
+            'request-download','request-file','request-list','request-pass',
+            'request-text','resend','reverse','routine?','same?','save',
+            'script?','second','select','send','series?','set','set-modes',
+            'set-net','set-path?','set-word?','show','show-popup','sign?',
+            'sine','size-text','size?','skip','sort','source','span?',
+            'split-path','square-root','strict-equal?','strict-not-equal?',
+            'string?','struct?','stylize','subtract','suffix?','tag?','tail',
+            'tail?','tangent','third','time?','to','to-binary','to-bitset',
+            'to-block','to-char','to-date','to-decimal','to-email','to-file',
+            'to-get-word','to-hash','to-hex','to-idate','to-image','to-integer',
+            'to-issue','to-list','to-lit-path','to-lit-word','to-local-file',
+            'to-logic','to-money','to-pair','to-paren','to-path',
+            'to-rebol-file','to-refinement','to-set-path','to-set-word',
+            'to-string','to-tag','to-time','to-tuple','to-url','to-word',
+            'trace','trim','tuple?','type?','unfocus','union','unique',
+            'unprotect','unset','unset?','unview','update','upgrade',
+            'uppercase','url?','usage','use','value?','view','viewed?','what',
+            'what-dir','within?','word?','write','write-io','xor','zero?',
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}', '!', '@', '%', '&', '*', '|', '/', '<', '>'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #000066;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+//            2 => 'color: #808080; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006600;',
+            2 => 'color: #006600;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #0000ff;'
+            ),
+        'SCRIPT' => array(
+            0 => '',
+            1 => '',
+            2 => '',
+            3 => ''
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => ''
+//        2 => 'includes/dico_rebol.php?word={FNAME}',
+//        3 => 'includes/dico_rebol.php?word={FNAME}'
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        0 => "[\\$]{1,2}[a-zA-Z_][a-zA-Z0-9_]*",
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/reg.php b/examples/includes/geshi/geshi/reg.php
new file mode 100644 (file)
index 0000000..9c85a15
--- /dev/null
@@ -0,0 +1,233 @@
+<?php
+/*************************************************************************************
+ * reg.php
+ * -------
+ * Author: Sean Hanna (smokingrope@gmail.com)
+ * Copyright: (c) 2006 Sean Hanna
+ * Release Version: 1.0.8.3
+ * Date Started: 03/15/2006
+ *
+ * Microsoft Registry Editor language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *  -  Added description of extra language features (SF#1970248)
+ *  -  Updated and optimized most regular expressions
+ * 03/15/2006 (0.5.0)
+ *  -  Syntax File Created
+ * 04/27/2006 (0.9.5)
+ *  -  Syntax Coloring Cleaned Up
+ *  -  First Release
+ * 04/29/2006 (1.0.0)
+ *  -  Updated a few coloring settings
+ *
+ * TODO (updated 4/27/2006)
+ * -------------------------
+ * - Add a verification to the multi-line portion of the hex field regex
+ *    for a '\' character on the line preceding the line of the multi-line
+ *    hex field.
+ *
+ * KNOWN ISSUES (updated 4/27/2006)
+ * ---------------------------------
+ *
+ * - There are two regexes for the multiline hex value regex. The regex for
+ *        all lines after the first does not verify that the previous line contains
+ *        a line continuation character '\'. This regex also does not check for
+ *        end of line as it should.
+ *
+ * - If number_highlighting is enabled during processing of this syntax file
+ *    many of the regexps used will appear slightly incorrect.
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+
+ ************************************************************************************/
+$language_data = array (
+    'LANG_NAME' => 'Microsoft Registry',
+    'COMMENT_SINGLE' => array(1 =>';'),
+    'COMMENT_MULTI' => array( ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array(),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+//        1 => array(),
+//        2 => array(),
+        /* Registry Key Constants Not Used */
+        3 => array(
+            'HKEY_LOCAL_MACHINE',
+            'HKEY_CLASSES_ROOT',
+            'HKEY_CURRENT_USER',
+            'HKEY_USERS',
+            'HKEY_CURRENT_CONFIG',
+            'HKEY_DYN_DATA',
+            'HKLM', 'HKCR', 'HKCU', 'HKU', 'HKCC', 'HKDD'
+            )
+        ),
+    'SYMBOLS' => array(
+        '='
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+//        1 => false,
+//        2 => false,
+        3 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+//            1 => 'color: #00CCFF;',
+//            2 => 'color: #0000FF;',
+            3 => 'color: #800000;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #009900;'
+            ),
+        'ESCAPE_CHAR' => array(
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000000;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #009900;'
+            ),
+        'NUMBERS' => array(
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000000;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #00CCFF;',
+            1 => 'color: #0000FF;',
+            2 => '',
+            3 => 'color: #0000FF;',
+            4 => 'color: #0000FF;',
+            5 => '',
+            6 => '',
+            7 => '',
+            8 => 'color: #FF6600;',
+            )
+        ),
+    'URLS' => array(
+//        1 => '',
+//        2 => '',
+        3 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        // Highlight Key Delimiters
+        0 => array(
+            GESHI_SEARCH => '((^|\\n)\\s*)(\\\\\\[(.*)\\\\\\])(\\s*(\\n|$))',
+            GESHI_REPLACE => '\\3',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => '\\5'
+//            GESHI_CLASS => 'kw1'
+            ),
+        // Highlight File Format Header Version 5
+        1 => array(
+            GESHI_SEARCH => '(^\s*)(Windows Registry Editor Version \d+\.\d+)(\s*$)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 'm',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => '\\3',
+            GESHI_CLASS => 'geshi_registry_header'
+            ),
+        // Highlight File Format Header Version 4
+        2 => array(
+            GESHI_SEARCH => '(^\\s*)(REGEDIT\s?\d+)(\s*$)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 'm',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => '\\3',
+            GESHI_CLASS => 'geshi_registry_header'
+            ),
+        // Highlight dword: 32 bit integer values
+        3 => array(
+            GESHI_SEARCH => '(=\s*)(dword:[0-9a-fA-F]{8})(\s*$)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 'm',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => '\\3'
+//            GESHI_CLASS => 'kw2'
+            ),
+        // Highlight variable names
+        4 => array(
+            GESHI_SEARCH => '(^\s*)(\&quot;.*?\&quot;)(\s*=)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 'm',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => '\\3',
+            GESHI_CLASS => 'geshi_variable'
+            ),
+        // Highlight String Values
+        5 => array(
+            GESHI_SEARCH => '(=\s*)(\&quot;.*?\&quot;)(\s*$)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 'm',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => '\\3',
+            GESHI_CLASS => 'st0'
+            ),
+        // Highlight Hexadecimal Values (Single-Line and Multi-Line)
+        6 => array(
+            GESHI_SEARCH => '(=\s*\n?\s*)(hex:[0-9a-fA-F]{2}(,(\\\s*\n\s*)?[0-9a-fA-F]{2})*)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 'm',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => '',
+            GESHI_CLASS => 'kw2'
+            ),
+        // Highlight Default Variable
+        7 => array(
+            GESHI_SEARCH => '(^\s*)(@)(\s*=)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 'm',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => '\\3',
+            GESHI_CLASS => 'geshi_variable'
+            ),
+        // Highlight GUID's found anywhere.
+        8 => array(
+            GESHI_SEARCH => '(\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\})',
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => 'i',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => '',
+            GESHI_CLASS => 'geshi_guid'
+            )
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'PARSER_CONTROL' => array(
+        'ENABLE_FLAGS' => array(
+            'NUMBERS' => GESHI_NEVER,
+        )
+    )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/robots.php b/examples/includes/geshi/geshi/robots.php
new file mode 100644 (file)
index 0000000..7bb2b20
--- /dev/null
@@ -0,0 +1,98 @@
+<?php
+/*************************************************************************************
+ * robots.php
+ * --------
+ * Author: Christian Lescuyer (cl@goelette.net)
+ * Copyright: (c) 2006 Christian Lescuyer http://xtian.goelette.info
+ * Release Version: 1.0.8.3
+ * Date Started: 2006/02/17
+ *
+ * robots.txt language file for GeSHi.
+ *
+ * 2006/02/17 (1.0.0)
+ *   -  First Release
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'robots.txt',
+    'COMMENT_SINGLE' => array(1 => '#'),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array(),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            'User-agent', 'Disallow'
+            )
+        ),
+    'SYMBOLS' => array(
+        ':'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => 'http://www.robotstxt.org/wc/norobots.html'
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/ruby.php b/examples/includes/geshi/geshi/ruby.php
new file mode 100644 (file)
index 0000000..8928557
--- /dev/null
@@ -0,0 +1,226 @@
+<?php
+/*************************************************************************************
+ * ruby.php
+ * --------
+ * Author: Moises Deniz
+ * Copyright: (c) 2007 Moises Deniz
+ * Release Version: 1.0.8.3
+ * Date Started: 2007/03/21
+ *
+ * Ruby language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *   -  Added description of extra language features (SF#1970248)
+ * 2007/03/21 (1.0.7.19)
+ *   -  Initial release
+ *
+ *************************************************************************************
+ *
+ *   This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Ruby',
+    'COMMENT_SINGLE' => array(1 => "#"),
+    'COMMENT_MULTI' => array("=begin" => "=end"),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"', '`','\''),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+                'alias', 'and', 'begin', 'break', 'case', 'class',
+                'def', 'defined', 'do', 'else', 'elsif', 'end',
+                'ensure', 'for', 'if', 'in', 'module', 'while',
+                'next', 'not', 'or', 'redo', 'rescue', 'yield',
+                'retry', 'super', 'then', 'undef', 'unless',
+                'until', 'when', 'BEGIN', 'END', 'include'
+            ),
+        2 => array(
+                '__FILE__', '__LINE__', 'false', 'nil', 'self', 'true',
+                'return'
+            ),
+        3 => array(
+                'Array', 'Float', 'Integer', 'String', 'at_exit',
+                'autoload', 'binding', 'caller', 'catch', 'chop', 'chop!',
+                'chomp', 'chomp!', 'eval', 'exec', 'exit', 'exit!', 'fail',
+                'fork', 'format', 'gets', 'global_variables', 'gsub', 'gsub!',
+                'iterator?', 'lambda', 'load', 'local_variables', 'loop',
+                'open', 'p', 'print', 'printf', 'proc', 'putc', 'puts',
+                'raise', 'rand', 'readline', 'readlines', 'require', 'select',
+                'sleep', 'split', 'sprintf', 'srand', 'sub', 'sub!', 'syscall',
+                'system', 'trace_var', 'trap', 'untrace_var'
+            ),
+        4 => array(
+                'Abbrev', 'ArgumentError', 'Base64', 'Benchmark',
+                'Benchmark::Tms', 'Bignum', 'Binding', 'CGI', 'CGI::Cookie',
+                'CGI::HtmlExtension', 'CGI::QueryExtension',
+                'CGI::Session', 'CGI::Session::FileStore',
+                'CGI::Session::MemoryStore', 'Class', 'Comparable', 'Complex',
+                'ConditionVariable', 'Continuation', 'Data',
+                'Date', 'DateTime', 'Delegator', 'Dir', 'EOFError', 'ERB',
+                'ERB::Util', 'Enumerable', 'Enumerable::Enumerator', 'Errno',
+                'Exception', 'FalseClass', 'File',
+                'File::Constants', 'File::Stat', 'FileTest', 'FileUtils',
+                'FileUtils::DryRun', 'FileUtils::NoWrite',
+                'FileUtils::StreamUtils_', 'FileUtils::Verbose', 'Find',
+                'Fixnum', 'FloatDomainError', 'Forwardable', 'GC', 'Generator',
+                'Hash', 'IO', 'IOError', 'Iconv', 'Iconv::BrokenLibrary',
+                'Iconv::Failure', 'Iconv::IllegalSequence',
+                'Iconv::InvalidCharacter', 'Iconv::InvalidEncoding',
+                'Iconv::OutOfRange', 'IndexError', 'Interrupt', 'Kernel',
+                'LoadError', 'LocalJumpError', 'Logger', 'Logger::Application',
+                'Logger::Error', 'Logger::Formatter', 'Logger::LogDevice',
+                'Logger::LogDevice::LogDeviceMutex', 'Logger::Severity',
+                'Logger::ShiftingError', 'Marshal', 'MatchData',
+                'Math', 'Matrix', 'Method', 'Module', 'Mutex', 'NameError',
+                'NameError::message', 'NilClass', 'NoMemoryError',
+                'NoMethodError', 'NotImplementedError', 'Numeric', 'Object',
+                'ObjectSpace', 'Observable', 'PStore', 'PStore::Error',
+                'Pathname', 'Precision', 'Proc', 'Process', 'Process::GID',
+                'Process::Status', 'Process::Sys', 'Process::UID', 'Queue',
+                'Range', 'RangeError', 'Rational', 'Regexp', 'RegexpError',
+                'RuntimeError', 'ScriptError', 'SecurityError', 'Set',
+                'Shellwords', 'Signal', 'SignalException', 'SimpleDelegator',
+                'SingleForwardable', 'Singleton', 'SingletonClassMethods',
+                'SizedQueue', 'SortedSet', 'StandardError', 'StringIO',
+                'StringScanner', 'StringScanner::Error', 'Struct', 'Symbol',
+                'SyncEnumerator', 'SyntaxError', 'SystemCallError',
+                'SystemExit', 'SystemStackError', 'Tempfile',
+                'Test::Unit::TestCase', 'Test::Unit', 'Test', 'Thread',
+                'ThreadError', 'ThreadGroup',
+                'ThreadsWait', 'Time', 'TrueClass', 'TypeError', 'URI',
+                'URI::BadURIError', 'URI::Error', 'URI::Escape', 'URI::FTP',
+                'URI::Generic', 'URI::HTTP', 'URI::HTTPS',
+                'URI::InvalidComponentError', 'URI::InvalidURIError',
+                'URI::LDAP', 'URI::MailTo', 'URI::REGEXP',
+                'URI::REGEXP::PATTERN', 'UnboundMethod', 'Vector', 'YAML',
+                'ZeroDivisionError', 'Zlib',
+                'Zlib::BufError', 'Zlib::DataError', 'Zlib::Deflate',
+                'Zlib::Error', 'Zlib::GzipFile', 'Zlib::GzipFile::CRCError',
+                'Zlib::GzipFile::Error', 'Zlib::GzipFile::LengthError',
+                'Zlib::GzipFile::NoFooter', 'Zlib::GzipReader',
+                'Zlib::GzipWriter', 'Zlib::Inflate', 'Zlib::MemError',
+                'Zlib::NeedDict', 'Zlib::StreamEnd', 'Zlib::StreamError',
+                'Zlib::VersionError',
+                'Zlib::ZStream',
+                'HTML::Selector', 'HashWithIndifferentAccess', 'Inflector',
+                'Inflector::Inflections', 'Mime', 'Mime::Type',
+                'OCI8AutoRecover', 'TimeZone', 'XmlSimple'
+            ),
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}', '%', '&', '*', '|', '/', '<', '>',
+        '+', '-', '=>', '<<'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => true,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color:#9966CC; font-weight:bold;',
+            2 => 'color:#0000FF; font-weight:bold;',
+            3 => 'color:#CC0066; font-weight:bold;',
+            4 => 'color:#CC00FF; font-weight:bold;',
+            ),
+        'COMMENTS' => array(
+            1 => 'color:#008000; font-style:italic;',
+            'MULTI' => 'color:#000080; font-style:italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color:#000099;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color:#006600; font-weight:bold;'
+            ),
+        'STRINGS' => array(
+            0 => 'color:#996600;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color:#006666;'
+            ),
+        'METHODS' => array(
+            1 => 'color:#9900CC;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color:#006600; font-weight:bold;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color:#ff6633; font-weight:bold;',
+            1 => 'color:#0066ff; font-weight:bold;',
+            2 => 'color:#6666ff; font-weight:bold;',
+            3 => 'color:#ff3333; font-weight:bold;'
+            ),
+        'SCRIPT' => array(
+            0 => '',
+            1 => '',
+            2 => '',
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        0 => array(//Variables
+            GESHI_SEARCH => "([[:space:]])(\\$[a-zA-Z_][a-zA-Z0-9_]*)",
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => ''
+            ),
+        1 => array(//Arrays
+            GESHI_SEARCH => "([[:space:]])(@[a-zA-Z_][a-zA-Z0-9_]*)",
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => ''
+            ),
+        2 => "([A-Z][a-zA-Z0-9_]*::)+[A-Z][a-zA-Z0-9_]*",//Static OOP symbols
+        3 => array(
+            GESHI_SEARCH => "([[:space:]]|\[|\()(:[a-zA-Z_][a-zA-Z0-9_]*)",
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => ''
+            )
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_MAYBE,
+    'SCRIPT_DELIMITERS' => array(
+        0 => array(
+            '<%' => '%>'
+            )
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        0 => true,
+        ),
+    'TAB_WIDTH' => 2
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/sas.php b/examples/includes/geshi/geshi/sas.php
new file mode 100644 (file)
index 0000000..d4ee828
--- /dev/null
@@ -0,0 +1,290 @@
+<?php
+/*************************************************************************************
+ * sas.php
+ * -------
+ * Author: Galen Johnson (solitaryr@gmail.com)
+ * Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2005/12/27
+ *
+ * SAS language file for GeSHi. Based on the sas vim file.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *   -  Added description of extra language features (SF#1970248)
+ *   -  Cleaned up code style
+ * 2005/12/27 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2005/12/27)
+ * -------------------------
+ * * Check highlighting stuff works
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'SAS',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            '_ALL_','_CHARACTER_','_INFILE_','_N_','_NULL_','_NUMERIC_',
+            '_WEBOUT_'
+            ),
+        2 => array(
+            '%BQUOTE','%CMPRES','%COMPSTOR','%DATATYP','%DISPLAY','%DO','%ELSE',
+            '%END','%EVAL','%GLOBAL','%GOTO','%IF','%INDEX','%INPUT','%KEYDEF',
+            '%LABEL','%LEFT','%LENGTH','%LET','%LOCAL','%LOWCASE','%MACRO',
+            '%MEND','%NRBQUOTE','%NRQUOTE','%NRSTR','%PUT','%QCMPRES','%QLEFT',
+            '%QLOWCASE','%QSCAN','%QSUBSTR','%QSYSFUNC','%QTRIM','%QUOTE',
+            '%QUPCASE','%SCAN','%STR','%SUBSTR','%SUPERQ','%SYSCALL',
+            '%SYSEVALF','%SYSEXEC','%SYSFUNC','%SYSGET','%SYSLPUT','%SYSPROD',
+            '%SYSRC','%SYSRPUT','%THEN','%TO','%TRIM','%UNQUOTE','%UNTIL',
+            '%UPCASE','%VERIFY','%WHILE','%WINDOW'
+            ),
+        3 => array(
+            'ABS','ADDR','AIRY','ARCOS','ARSIN','ATAN','ATTRC','ATTRN','BAND',
+            'BETAINV','BLSHIFT','BNOT','BOR','BRSHIFT','BXOR','BYTE','CDF',
+            'CEIL','CEXIST','CINV','CLOSE','CNONCT','COLLATE','COMPBL',
+            'COMPOUND','COMPRESS','COSH','COS','CSS','CUROBS','CV','DACCDBSL',
+            'DACCDB','DACCSL','DACCSYD','DACCTAB','DAIRY','DATETIME','DATEJUL',
+            'DATEPART','DATE','DAY','DCLOSE','DEPDBSL','DEPDB','DEPSL','DEPSYD',
+            'DEPTAB','DEQUOTE','DHMS','DIF','DIGAMMA','DIM','DINFO','DNUM',
+            'DOPEN','DOPTNAME','DOPTNUM','DREAD','DROPNOTE','DSNAME','ERFC',
+            'ERF','EXIST','EXP','FAPPEND','FCLOSE','FCOL','FDELETE','FETCHOBS',
+            'FETCH','FEXIST','FGET','FILEEXIST','FILENAME','FILEREF','FINFO',
+            'FINV','FIPNAMEL','FIPNAME','FIPSTATE','FLOOR','FNONCT','FNOTE',
+            'FOPEN','FOPTNAME','FOPTNUM','FPOINT','FPOS','FPUT','FREAD',
+            'FREWIND','FRLEN','FSEP','FUZZ','FWRITE','GAMINV','GAMMA',
+            'GETOPTION','GETVARC','GETVARN','HBOUND','HMS','HOSTHELP','HOUR',
+            'IBESSEL','INDEXW','INDEXC','INDEX','INPUTN','INPUTC','INPUT',
+            'INTRR','INTCK','INTNX','INT','IRR','JBESSEL','JULDATE','KURTOSIS',
+            'LAG','LBOUND','LEFT','LENGTH','LGAMMA','LIBNAME','LIBREF','LOG10',
+            'LOG2','LOGPDF','LOGPMF','LOGSDF','LOG','LOWCASE','MAX','MDY',
+            'MEAN','MINUTE','MIN','MOD','MONTH','MOPEN','MORT','NETPV','NMISS',
+            'NORMAL','NPV','N','OPEN','ORDINAL','PATHNAME','PDF','PEEKC','PEEK',
+            'PMF','POINT','POISSON','POKE','PROBBETA','PROBBNML','PROBCHI',
+            'PROBF','PROBGAM','PROBHYPR','PROBIT','PROBNEGB','PROBNORM','PROBT',
+            'PUTN','PUTC','PUT','QTR','QUOTE','RANBIN','RANCAU','RANEXP',
+            'RANGAM','RANGE','RANK','RANNOR','RANPOI','RANTBL','RANTRI',
+            'RANUNI','REPEAT','RESOLVE','REVERSE','REWIND','RIGHT','ROUND',
+            'SAVING','SCAN','SDF','SECOND','SIGN','SINH','SIN','SKEWNESS',
+            'SOUNDEX','SPEDIS','SQRT','STDERR','STD','STFIPS','STNAME',
+            'STNAMEL','SUBSTR','SUM','SYMGET','SYSGET','SYSMSG','SYSPROD',
+            'SYSRC','SYSTEM','TANH','TAN','TIMEPART','TIME','TINV','TNONCT',
+            'TODAY','TRANSLATE','TRANWRD','TRIGAMMA','TRIMN','TRIM','TRUNC',
+            'UNIFORM','UPCASE','USS','VARFMT','VARINFMT','VARLABEL','VARLEN',
+            'VARNAME','VARNUM','VARRAYX','VARRAY','VARTYPE','VAR','VERIFY',
+            'VFORMATX','VFORMATDX','VFORMATD','VFORMATNX','VFORMATN',
+            'VFORMATWX','VFORMATW','VFORMAT','VINARRAYX','VINARRAY',
+            'VINFORMATX','VINFORMATDX','VINFORMATD','VINFORMATNX','VINFORMATN',
+            'VINFORMATWX','VINFORMATW','VINFORMAT','VLABELX','VLABEL',
+            'VLENGTHX','VLENGTH','VNAMEX','VNAME','VTYPEX','VTYPE','WEEKDAY',
+            'YEAR','YYQ','ZIPFIPS','ZIPNAME','ZIPNAMEL','ZIPSTATE'
+            ),
+        4 => array(
+            'ABORT','ADD','ALTER','AND','ARRAY','AS','ATTRIB','BY','CALL',
+            'CARDS4','CASCADE','CATNAME','CHECK','CONTINUE','CREATE',
+            'DATALINES4','DELETE','DESCRIBE','DISPLAY','DISTINCT','DM','DROP',
+            'ENDSAS','FILE','FOOTNOTE','FOREIGN','FORMAT','FROM',
+            'GOTO','GROUP','HAVING','IN','INFILE','INFORMAT',
+            'INSERT','INTO','KEEP','KEY','LABEL','LEAVE',
+            'LIKE','LINK','LIST','LOSTCARD','MERGE','MESSAGE','MISSING',
+            'MODIFY','MSGTYPE','NOT','NULL','ON','OPTIONS','OR','ORDER',
+            'OUTPUT','PAGE','PRIMARY','REDIRECT','REFERENCES','REMOVE',
+            'RENAME','REPLACE','RESET','RESTRICT','RETAIN','RETURN','SELECT',
+            'SET','SKIP','STARTSAS','STOP','SYSTASK','TABLE','TITLE','UNIQUE',
+            'UPDATE','VALIDATE','VIEW','WAITSAS','WHERE','WINDOW','X'
+            ),
+        5 => array(
+            'DO','ELSE','END','IF','THEN','UNTIL','WHILE'
+            ),
+        6 => array(
+            'RUN','QUIT','DATA'
+            ),
+        7 => array(
+            'ERROR'
+            ),
+        8 => array(
+            'WARNING'
+            ),
+        9 => array(
+            'NOTE'
+            )
+        ),
+    'SYMBOLS' => array(
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        5 => false,
+        6 => false,
+        7 => false,
+        8 => false,
+        9 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0000ff;',
+            2 => 'color: #0000ff;',
+            3 => 'color: #0000ff;',
+            4 => 'color: #0000ff;',
+            5 => 'color: #0000ff;',
+            6 => 'color: #000080; font-weight: bold;',
+            7 => 'color: #ff0000;',
+            8 => 'color: #00ff00;',
+            9 => 'color: #0000ff;'
+            ),
+        'COMMENTS' => array(
+//            1 => 'color: #006400; font-style: italic;',
+            'MULTI' => 'color: #006400; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #a020f0;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #2e8b57; font-weight: bold;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'SCRIPT' => array(
+            0 => '',
+            1 => '',
+            2 => '',
+            3 => ''
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #0000ff; font-weight: bold;',
+            1 => 'color: #000080; font-weight: bold;',
+            2 => 'color: #006400; font-style: italic;',
+            3 => 'color: #006400; font-style: italic;',
+            4 => 'color: #006400; font-style: italic;',
+            5 => 'color: #ff0000; font-weight: bold;',
+            6 => 'color: #00ff00; font-style: italic;',
+            7 => 'color: #0000ff; font-style: normal;',
+            8 => 'color: #b218b2; font-weight: bold;',
+            9 => 'color: #b218b2; font-weight: bold;'
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => '',
+        5 => '',
+        6 => '',
+        7 => '',
+        8 => '',
+        9 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        0 => "&amp;[a-zA-Z_][a-zA-Z0-9_]*",
+        1 => array(//Procedures
+            GESHI_SEARCH => '(^\\s*)(PROC \\w+)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 'im',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => ''
+            ),
+        2 => array(
+            GESHI_SEARCH => '(^\\s*)(\\*.*;)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 'im',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => ''
+            ),
+        3 => array(
+            GESHI_SEARCH => '(.*;\\s*)(\\*.*;)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 'im',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => ''
+            ),
+        4 => array(
+            GESHI_SEARCH => '(^\\s*)(%\\*.*;)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 'im',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => ''
+            ),
+        5 => array(//Error messages
+            GESHI_SEARCH => '(^ERROR.*)',
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => 'im',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        6 => array(//Warning messages
+            GESHI_SEARCH => '(^WARNING.*)',
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => 'im',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        7 => array(//Notice messages
+            GESHI_SEARCH => '(^NOTE.*)',
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => 'im',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        8 => array(
+            GESHI_SEARCH => '(^\\s*)(CARDS.*)(^\\s*;\\s*$)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 'sim',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => '\\3'
+            ),
+        9 => array(
+            GESHI_SEARCH => '(^\\s*)(DATALINES.*)(^\\s*;\\s*$)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 'sim',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => '\\3'
+            )
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_MAYBE,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/scala.php b/examples/includes/geshi/geshi/scala.php
new file mode 100644 (file)
index 0000000..c72de33
--- /dev/null
@@ -0,0 +1,122 @@
+<?php
+/*************************************************************************************
+ * scala.php
+ * ----------
+ * Author: Franco Lombardo (franco@francolombardo.net)
+ * Copyright: (c) 2008 Franco Lombardo, Benny Baumann
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/02/08
+ *
+ * Scala language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/02/08 (1.0.7.22)
+ *   -  First Release
+ *
+ * TODO (updated 2007/04/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Scala',
+    'COMMENT_SINGLE' => array(1 => '//'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'abstract', 'case', 'catch', 'class', 'def',
+            'do', 'else', 'extends', 'false', 'final',
+            'finally', 'for', 'forSome', 'if', 'implicit',
+            'import', 'match', 'new', 'null', 'object',
+            'override', 'package', 'private', 'protected', 'requires',
+            'return', 'sealed', 'super', 'this', 'throw',
+            'trait', 'try', 'true', 'type', 'val',
+            'var', 'while', 'with', 'yield'
+            ),
+        2 => array(
+            'void', 'double', 'int', 'boolean', 'byte', 'short', 'long', 'char', 'float'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}', '*', '&', '%', '!', ';', '<', '>', '?',
+        '_', ':', '=', '=>', '<<:',
+        '<%', '>:', '#', '@'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0000ff; font-weight: bold;',
+            2 => 'color: #9999cc; font-weight: bold;',
+            ),
+        'COMMENTS' => array(
+            1=> 'color: #008000; font-style: italic;',
+            'MULTI' => 'color: #00ff00; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #0000ff; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #F78811;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #6666FF;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #F78811;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #000000;',
+            2 => 'color: #000000;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000080;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => 'http://scala-lang.org',
+        2 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/scheme.php b/examples/includes/geshi/geshi/scheme.php
new file mode 100644 (file)
index 0000000..1c85f80
--- /dev/null
@@ -0,0 +1,170 @@
+<?php
+/*************************************************************************************
+ * scheme.php
+ * ----------
+ * Author: Jon Raphaelson (jonraphaelson@gmail.com)
+ * Copyright: (c) 2005 Jon Raphaelson, Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/08/30
+ *
+ * Scheme language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2005/09/22 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2005/09/22)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Scheme',
+    'COMMENT_SINGLE' => array(1 => ';'),
+    'COMMENT_MULTI' => array('#|' => '|#'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'abs', 'acos', 'and', 'angle', 'append', 'appply', 'approximate',
+            'asin', 'assoc', 'assq', 'assv', 'atan',
+
+            'begin', 'boolean?', 'bound-identifier=?',
+
+            'caar', 'caddr', 'cadr', 'call-with-current-continuation',
+            'call-with-input-file', 'call-with-output-file', 'call/cc', 'car',
+            'case', 'catch', 'cdddar', 'cddddr', 'cdr', 'ceiling', 'char->integer',
+            'char-alphabetic?', 'char-ci<=?', 'char-ci<?', 'char-ci?', 'char-ci>=?',
+            'char-ci>?', 'char-ci=?', 'char-downcase', 'char-lower-case?',
+            'char-numeric', 'char-ready', 'char-ready?', 'char-upcase',
+            'char-upper-case?', 'char-whitespace?', 'char<=?', 'char<?', 'char=?',
+            'char>=?', 'char>?', 'char?', 'close-input-port', 'close-output-port',
+            'complex?', 'cond', 'cons', 'construct-identifier', 'cos',
+            'current-input-port', 'current-output-port',
+
+            'd', 'define', 'define-syntax', 'delay', 'denominator', 'display', 'do',
+
+            'e', 'eof-object?', 'eq?', 'equal?', 'eqv?', 'even?', 'exact->inexact',
+            'exact?', 'exp', 'expt', 'else',
+
+            'f', 'floor', 'for-each', 'force', 'free-identifer=?',
+
+            'gcd', 'gen-counter', 'gen-loser', 'generate-identifier',
+
+            'identifier->symbol', 'identifier', 'if', 'imag-part', 'inexact->exact',
+            'inexact?', 'input-port?', 'integer->char', 'integer?', 'integrate-system',
+
+            'l', 'lambda', 'last-pair', 'lcm', 'length', 'let', 'let*', 'letrec',
+            'list', 'list->string', 'list->vector', 'list-ref', 'list-tail', 'list?',
+            'load', 'log',
+
+            'magnitude', 'make-polar', 'make-promise', 'make-rectangular',
+            'make-string', 'make-vector', 'map', 'map-streams', 'max', 'member',
+            'memq', 'memv', 'min', 'modulo',
+
+            'negative', 'newline', 'nil', 'not', 'null?', 'number->string', 'number?',
+            'numerator',
+
+            'odd?', 'open-input-file', 'open-output-file', 'or', 'output-port',
+
+            'pair?', 'peek-char', 'positive?', 'procedure?',
+
+            'quasiquote', 'quote', 'quotient',
+
+            'rational', 'rationalize', 'read', 'read-char', 'real-part', 'real?',
+            'remainder', 'return', 'reverse',
+
+            's', 'sequence', 'set!', 'set-char!', 'set-cdr!', 'sin', 'sqrt', 'string',
+            'string->list', 'string->number', 'string->symbol', 'string-append',
+            'string-ci<=?', 'string-ci<?', 'string-ci=?', 'string-ci>=?',
+            'string-ci>?', 'string-copy', 'string-fill!', 'string-length',
+            'string-ref', 'string-set!', 'string<=?', 'string<?', 'string=?',
+            'string>=?', 'string>?', 'string?', 'substring', 'symbol->string',
+            'symbol?', 'syntax', 'syntax-rules',
+
+            't', 'tan', 'template', 'transcript-off', 'transcript-on', 'truncate',
+
+            'unquote', 'unquote-splicing', 'unwrap-syntax',
+
+            'vector', 'vector->list', 'vector-fill!', 'vector-length', 'vector-ref',
+            'vector-set!', 'vector?',
+
+            'with-input-from-file', 'with-output-to-file', 'write', 'write-char',
+
+            'zero?'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '{', '}', '[', ']', '!', '%', '^', '&', '/','+','-','*','=','<','>',';','|'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            0 => 'color: #202020;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/scilab.php b/examples/includes/geshi/geshi/scilab.php
new file mode 100644 (file)
index 0000000..bfe72ad
--- /dev/null
@@ -0,0 +1,295 @@
+<?php
+/*************************************************************************************
+ * scilab.php
+ * --------
+ * Author: Christophe David (geshi@christophedavid.org)
+ * Copyright: (c) 2008 Christophe David (geshi@christophedavid.org)
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/08/04
+ *
+ * SciLab language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/08/25 (1.0.8.1)
+ *   - Corrected with the help of Benny Baumann (BenBE@geshi.org)
+ * 2008/08/04 (0.0.0.1)
+ *   - First beta Release - known problem with ' used to transpose matrices considered as start of strings
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'SciLab',
+    'COMMENT_SINGLE' => array(1 => '//'),
+    'COMMENT_MULTI' => array(),
+    'COMMENT_REGEXP' => array(
+        2 => "/\w+'/"
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '\\',
+    'HARDQUOTE' => array("'", "'"),
+    'HARDESCAPE' => array(),
+    'KEYWORDS' => array(
+        1 => array(
+            'if', 'else', 'elseif', 'end', 'select', 'case', 'for', 'while', 'break'
+            ),
+        2 => array(
+            'STDIN', 'STDOUT', 'STDERR',
+            '%i', '%pi', '%e', '%eps', '%nan', '%inf', '%s', '%t', '%f',
+            'usual', 'polynomial', 'boolean', 'character', 'function', 'rational', 'state-space',
+            'sparse', 'boolean sparse', 'list', 'tlist', 'library', 'endfunction'
+            ),
+        3 => array(
+            '%asn', '%helps', '%k', '%sn', 'abcd', 'abinv', 'abort', 'about', 'About_M2SCI_tools',
+            'abs', 'acos', 'acosh', 'acoshm', 'acosm', 'AdCommunications', 'add_demo', 'add_edge',
+            'add_help_chapter', 'add_node', 'add_palette', 'addcolor', 'addf', 'addinter', 'addmenu',
+            'adj_lists', 'adj2sp', 'aff2ab', 'alufunctions', 'amell', 'analpf', 'analyze', 'and',
+            'ans', 'apropos', 'arc_graph', 'arc_number', 'arc_properties', 'argn', 'arhnk', 'arl2',
+            'arma', 'arma2p', 'armac', 'armax', 'armax1', 'arsimul', 'artest', 'articul', 'ascii',
+            'asciimat', 'asin', 'asinh', 'asinhm', 'asinm', 'assignation', 'atan', 'atanh', 'atanhm',
+            'atanm', 'augment', 'auread', 'auwrite', 'axes_properties', 'axis_properties', 'backslash',
+            'balanc', 'balreal', 'bandwr', 'banner','bar', 'barh', 'barhomogenize', 'basename', 'bdiag',
+            'beep', 'besselh', 'besseli', 'besselj', 'besselk', 'bessely', 'best_match', 'beta','bezout',
+            'bifish', 'bilin', 'binomial', 'black', 'bloc2exp', 'bloc2ss', 'bode', 'bool2s',
+            'boucle', 'brackets', 'browsevar', 'bsplin3val', 'bstap', 'buttmag', 'buttondialog',
+            'bvode', 'bvodeS', 'c_link', 'cainv', 'calendar', 'calerf', 'calfrq', 'call', 'canon', 'casc',
+            'cat', 'catch', 'ccontrg', 'cd', 'cdfbet', 'cdfbin', 'cdfchi', 'cdfchn', 'cdff', 'cdffnc',
+            'cdfgam', 'cdfnbn', 'cdfnor', 'cdfpoi', 'cdft', 'ceil', 'cell', 'cell2mat', 'cellstr', 'center',
+            'cepstrum', 'chain_struct', 'chaintest', 'champ', 'champ_properties', 'champ1', 'char', 'chart',
+            'chartooem', 'chdir', 'cheb1mag', 'cheb2mag', 'check_graph', 'chepol', 'chfact', 'chol', 'chsolve',
+            'circuit', 'classmarkov', 'clc', 'clean', 'clear', 'clear_pixmap', 'clearfun', 'clearglobal','clf',
+            'clipboard', 'close', 'cls2dls', 'cmb_lin', 'cmndred', 'cmoment', 'code2str', 'coeff', 'coff', 'coffg',
+            'colcomp', 'colcompr', 'colinout', 'colon', 'color', 'color_list', 'colorbar', 'colordef', 'colormap',
+            'colregul', 'comma', 'comments', 'comp', 'companion', 'comparison', 'Compound_properties', 'con_nodes',
+            'cond', 'config', 'configure_msvc', 'conj', 'connex', 'console', 'cont_frm', 'cont_mat', 'Contents',
+            'continue', 'contour', 'contour2d', 'contour2di', 'contourf', 'contr', 'contract_edge', 'contrss',
+            'convex_hull', 'convol', 'convstr', 'copfac', 'copy', 'corr', 'correl', 'cos', 'cosh', 'coshm',
+            'cosm', 'cotg', 'coth', 'cothm', 'covar', 'create_palette', 'cshep2d', 'csim', 'cspect', 'Cste',
+            'ctr_gram', 'cumprod', 'cumsum', 'cycle_basis', 'czt', 'dasrt', 'dassl', 'datafit', 'date', 'datenum',
+            'datevec', 'dbphi', 'dcf', 'ddp', 'debug', 'dec2hex', 'deff', 'definedfields', 'degree', 'delbpt',
+            'delete', 'delete_arcs', 'delete_nodes', 'delip', 'delmenu', 'demoplay', 'denom', 'derivat', 'derivative',
+            'des2ss', 'des2tf', 'det', 'determ', 'detr', 'detrend', 'dft', 'dhinf', 'dhnorm', 'diag', 'diary',
+            'diff', 'diophant', 'dir', 'dirname', 'disp', 'dispbpt', 'dispfiles', 'dlgamma', 'dnaupd', 'do', 'dot',
+            'double', 'dragrect', 'draw', 'drawaxis', 'drawlater', 'drawnow', 'driver', 'dsaupd', 'dscr',
+            'dsearch', 'dsimul', 'dt_ility', 'dtsi', 'edge_number', 'edit', 'edit_curv', 'edit_error',
+            'edit_graph', 'edit_graph_menus', 'editvar', 'eigenmarkov', 'ell1mag',
+            'empty', 'emptystr', 'eqfir', 'eqiir', 'equal', 'Equal', 'equil', 'equil1',
+            'ereduc', 'erf', 'erfc', 'erfcx', 'errbar', 'errcatch', 'errclear', 'error', 'error_table', 'etime',
+            'eval', 'eval_cshep2d', 'eval3d', 'eval3dp', 'evans', 'evstr', 'excel2sci', 'exec', 'execstr', 'exists',
+            'exit', 'exp', 'expm', 'external', 'extraction', 'eye', 'fac3d', 'factorial', 'factors', 'faurre', 'fchamp',
+            'fcontour', 'fcontour2d', 'fec', 'fec_properties', 'feedback', 'feval', 'ffilt', 'fft', 'fft2', 'fftshift',
+            'fgrayplot', 'figure', 'figure_properties', 'figure_style', 'file', 'fileinfo', 'fileparts', 'filter', 'find',
+            'find_freq', 'find_path', 'findABCD', 'findAC', 'findBD', 'findBDK', 'findm', 'findmsvccompiler', 'findobj',
+            'findR', 'findx0BD', 'firstnonsingleton', 'fit_dat', 'fix', 'floor', 'flts', 'foo', 'format',
+            'formatman', 'fort', 'fourplan', 'fplot2d', 'fplot3d', 'fplot3d1', 'fprintf', 'fprintfMat', 'frep2tf',
+            'freq', 'freson', 'frexp', 'frfit', 'frmag', 'fscanf', 'fscanfMat', 'fsfirlin', 'fsolve', 'fspecg',
+            'fstabst', 'fstair', 'ftest', 'ftuneq', 'full', 'fullfile', 'fullrf', 'fullrfk', 'fun2string', 'Funcall',
+            'funcprot', 'functions', 'funptr', 'fusee', 'G_make', 'g_margin', 'gainplot', 'gamitg',
+            'gamma', 'gammaln', 'gca', 'gcare', 'gcd', 'gce', 'gcf', 'gda', 'gdf', 'gen_net', 'genfac3d', 'genlib',
+            'genmarkov', 'geom3d', 'geomean', 'get', 'get_contents_infer', 'get_function_path', 'getcolor', 'getcwd',
+            'getd', 'getdate', 'getenv', 'getf', 'getfield', 'getfont', 'gethistory', 'getio', 'getlinestyle',
+            'getlongpathname', 'getmark', 'getmemory', 'getos', 'getpid', 'getscilabkeywords', 'getshell',
+            'getshortpathname', 'getsymbol', 'getvalue', 'getversion', 'gfare', 'gfrancis', 'girth', 'givens',
+            'glever', 'glist', 'global', 'GlobalProperty', 'glue', 'gmres', 'gpeche', 'gr_menu', 'graduate', 'grand',
+            'graph_2_mat', 'graph_center', 'graph_complement', 'graph_diameter', 'graph_power', 'graph_simp', 'graph_sum',
+            'graph_union', 'graphic', 'Graphics', 'graphics_entities', 'graph-list', 'graycolormap', 'grayplot',
+            'grayplot_properties', 'graypolarplot', 'great', 'grep', 'group', 'gschur', 'gsort', 'gspec', 'gstacksize',
+            'gtild', 'h_cl', 'h_inf', 'h_inf_st', 'h_norm', 'h2norm', 'halt', 'hamilton', 'hank', 'hankelsv', 'harmean',
+            'hat', 'havewindow', 'head_comments', 'help', 'help_skeleton', 'hermit', 'hess', 'hex2dec', 'hilb', 'hinf',
+            'hist3d', 'histplot', 'horner', 'host', 'hotcolormap', 'householder', 'hrmt', 'hsv2rgb', 'hsvcolormap',
+            'htrianr', 'hypermat', 'hypermatrices', 'iconvert', 'ieee', 'ifft', 'iir', 'iirgroup', 'iirlp',
+            'ilib_build', 'ilib_compile', 'ilib_for_link', 'ilib_gen_gateway', 'ilib_gen_loader', 'ilib_gen_Make',
+            'im_inv', 'imag', 'impl', 'imrep2ss', 'imult', 'ind2sub', 'Infer', 'inistate', 'input', 'insertion', 'int',
+            'int16', 'int2d', 'int32', 'int3d', 'int8', 'intc', 'intdec', 'integrate', 'interp', 'interp1', 'interp2d',
+            'interp3d', 'interpln', 'intersci', 'intersect', 'intg', 'intl', 'intppty', 'intsplin', 'inttrap', 'inttype',
+            'inv', 'inv_coeff', 'invr', 'invsyslin', 'iqr', 'is_connex', 'iscellstr', 'isdef', 'isdir', 'isempty',
+            'isequal', 'isequalbitwise', 'iserror', 'isglobal', 'isinf', 'isnan', 'isoview', 'isreal', 'javasci',
+            'jetcolormap', 'jmat', 'justify', 'kalm', 'karmarkar', 'kernel', 'keyboard', 'knapsack', 'kpure', 'krac2',
+            'kron', 'kroneck', 'label_properties', 'labostat', 'LANGUAGE', 'lasterror', 'lattn', 'lattp', 'lcf', 'lcm',
+            'lcmdiag', 'ldiv', 'ldivf', 'leastsq', 'left', 'legend', 'legend_properties', 'legendre', 'legends', 'length',
+            'leqr', 'less', 'lev', 'levin', 'lex_sort', 'lft', 'lgfft', 'lib', 'lin', 'lin2mu', 'lindquist',
+            'line_graph', 'linear_interpn', 'lines', 'LineSpec', 'linf', 'linfn', 'link', 'linmeq', 'linpro', 'linsolve',
+            'linspace', 'listfiles', 'listvarinfile', 'lmisolver', 'lmitool', 'load', 'load_graph', 'loadhistory',
+            'loadmatfile', 'loadplots', 'loadwave', 'locate', 'log', 'log10', 'log1p', 'log2', 'logm', 'logspace',
+            'lotest', 'lqe', 'lqg', 'lqg_ltr', 'lqg2stan', 'lqr', 'ls', 'lsq', 'lsq_splin', 'lsqrsolve', 'lsslist',
+            'lstcat', 'lstsize', 'ltitr', 'lu', 'ludel', 'lufact', 'luget', 'lusolve', 'lyap', 'm_circle', 'm2scideclare',
+            'macglov', 'macr2lst', 'macr2tree', 'macro', 'macrovar', 'mad', 'make_graph', 'make_index', 'makecell', 'man',
+            'manedit', 'mapsound', 'markp2ss', 'mat_2_graph', 'matfile2sci', 'Matlab-Scilab_character_strings', 'Matplot',
+            'Matplot_properties', 'Matplot1', 'matrices', 'matrix', 'max', 'max_cap_path', 'max_clique', 'max_flow',
+            'maxi', 'mcisendstring', 'mclearerr', 'mclose', 'mdelete', 'mean', 'meanf', 'median', 'menus', 'meof',
+            'merror', 'mese', 'mesh', 'mesh2d', 'meshgrid', 'mfft', 'mfile2sci', 'mfprintf', 'mfscanf', 'mget', 'mgeti',
+            'mgetl', 'mgetstr', 'milk_drop', 'min', 'min_lcost_cflow', 'min_lcost_flow1', 'min_lcost_flow2',
+            'min_qcost_flow', 'min_weight_tree', 'mine', 'mini', 'minreal', 'minss', 'minus', 'mkdir', 'mlist', 'mode',
+            'modulo', 'moment', 'mopen', 'move', 'mprintf', 'mps2linpro', 'mput', 'mputl', 'mputstr', 'mrfit', 'mscanf',
+            'msd', 'mseek', 'msprintf', 'msscanf', 'mstr2sci', 'mtell', 'mtlb_0', 'mtlb_a', 'mtlb_all', 'mtlb_any',
+            'mtlb_axis', 'mtlb_beta', 'mtlb_box', 'mtlb_close', 'mtlb_colordef', 'mtlb_conv', 'mtlb_cumprod', 'mtlb_cumsum',
+            'mtlb_dec2hex', 'mtlb_delete', 'mtlb_diag', 'mtlb_diff', 'mtlb_dir', 'mtlb_double', 'mtlb_e', 'mtlb_echo',
+            'mtlb_eig', 'mtlb_eval', 'mtlb_exist', 'mtlb_eye', 'mtlb_false', 'mtlb_fft', 'mtlb_fftshift', 'mtlb_find',
+            'mtlb_findstr', 'mtlb_fliplr', 'mtlb_fopen', 'mtlb_format', 'mtlb_fprintf', 'mtlb_fread', 'mtlb_fscanf',
+            'mtlb_full', 'mtlb_fwrite', 'mtlb_grid', 'mtlb_hold', 'mtlb_i', 'mtlb_ifft', 'mtlb_imp', 'mtlb_int16',
+            'mtlb_int32', 'mtlb_int8', 'mtlb_is', 'mtlb_isa', 'mtlb_isfield', 'mtlb_isletter', 'mtlb_isspace', 'mtlb_l',
+            'mtlb_legendre', 'mtlb_linspace', 'mtlb_load', 'mtlb_logic', 'mtlb_logical', 'mtlb_lower', 'mtlb_max',
+            'mtlb_min', 'mtlb_mode', 'mtlb_more', 'mtlb_num2str', 'mtlb_ones', 'mtlb_plot', 'mtlb_prod', 'mtlb_rand',
+            'mtlb_randn', 'mtlb_rcond', 'mtlb_realmax', 'mtlb_realmin', 'mtlb_repmat', 'mtlb_s', 'mtlb_save',
+            'mtlb_setstr', 'mtlb_size', 'mtlb_sort', 'mtlb_sparse', 'mtlb_strcmp', 'mtlb_strcmpi', 'mtlb_strfind',
+            'mtlb_strrep', 'mtlb_sum', 'mtlb_t', 'mtlb_toeplitz', 'mtlb_tril', 'mtlb_triu', 'mtlb_true', 'mtlb_uint16',
+            'mtlb_uint32', 'mtlb_uint8', 'mtlb_upper', 'mtlb_zeros', 'mu2lin', 'mucomp', 'mulf', 'mvvacov', 'name2rgb',
+            'names', 'nancumsum', 'nand2mean', 'nanmax', 'nanmean', 'nanmeanf', 'nanmedian', 'nanmin', 'nanstdev',
+            'nansum', 'narsimul', 'NDcost', 'ndgrid', 'ndims', 'nearfloat', 'nehari', 'neighbors', 'netclose', 'netwindow',
+            'netwindows', 'new', 'newaxes', 'newest', 'newfun', 'nextpow2', 'nf3d', 'nfreq', 'nlev', 'nnz', 'node_number',
+            'nodes_2_path', 'nodes_degrees', 'noisegen', 'norm', 'not', 'null', 'number_properties', 'numdiff', 'numer',
+            'nyquist', 'object_editor', 'obs_gram', 'obscont', 'obscont1', 'observer', 'obsv_mat', 'obsvss', 'ode',
+            'ode_discrete', 'ode_optional_output', 'ode_root', 'odedc', 'odeoptions', 'oemtochar', 'old_style',
+            'oldbesseli', 'oldbesselj', 'oldbesselk', 'oldbessely', 'oldload', 'oldplot', 'oldsave', 'ones',
+            'Operation', 'optim', 'or', 'orth', 'overloading', 'p_margin', 'param3d', 'param3d_properties',
+            'param3d1', 'paramfplot2d', 'parents', 'parrot', 'part', 'path_2_nodes', 'pathconvert', 'pause', 'pbig',
+            'pca', 'pcg', 'pdiv', 'pen2ea', 'pencan', 'penlaur', 'percent', 'perctl', 'perfect_match', 'perl',
+            'perms', 'permute', 'pertrans', 'pfss', 'phasemag', 'phc', 'pie', 'pinv', 'pipe_network', 'playsnd', 'plot',
+            'plot_graph', 'plot2d', 'plot2d_old_version', 'plot2d1', 'plot2d2', 'plot2d3', 'plot2d4', 'plot3d',
+            'plot3d_old_version', 'plot3d1', 'plot3d2', 'plot3d3', 'plotframe', 'plotprofile', 'plus', 'plzr',
+            'pmodulo', 'pol2des', 'pol2str', 'pol2tex', 'polar', 'polarplot', 'polfact', 'poly', 'polyline_properties',
+            'portr3d', 'portrait', 'power', 'ppol', 'prbs_a', 'predecessors', 'predef', 'print', 'printf',
+            'printf_conversion', 'printing', 'printsetupbox', 'prod', 'profile', 'progressionbar', 'proj', 'projsl',
+            'projspec', 'psmall', 'pspect', 'pvm', 'pvm_addhosts', 'pvm_barrier', 'pvm_bcast', 'pvm_bufinfo', 'pvm_config',
+            'pvm_delhosts', 'pvm_error', 'pvm_exit', 'pvm_f772sci', 'pvm_get_timer', 'pvm_getinst', 'pvm_gettid',
+            'pvm_gsize', 'pvm_halt', 'pvm_joingroup', 'pvm_kill', 'pvm_lvgroup', 'pvm_mytid', 'pvm_parent', 'pvm_probe',
+            'pvm_recv', 'pvm_reduce', 'pvm_sci2f77', 'pvm_send', 'pvm_set_timer', 'pvm_spawn', 'pvm_spawn_independent',
+            'pvm_start', 'pvm_tasks', 'pvm_tidtohost', 'pvmd3', 'pwd', 'qassign', 'qld', 'qmr', 'qr', 'quapro', 'quart',
+            'quaskro', 'quit', 'quote', 'rand', 'randpencil', 'range', 'rank', 'rankqr', 'rat',  'rcond',
+            'rdivf', 'read', 'read4b', 'readb', 'readc_', 'readmps', 'readxls', 'real', 'realtime', 'realtimeinit',
+            'rectangle_properties', 'recur', 'reglin', 'regress', 'remez', 'remezb', 'repfreq', 'replot', 'resethistory',
+            'residu', 'resume', 'return', 'rgb2name', 'ric_desc', 'ricc', 'riccati', 'rlist', 'rmdir', 'roots', 'rotate',
+            'round', 'routh_t', 'rowcomp', 'rowcompr', 'rowinout', 'rowregul', 'rowshuff', 'rpem', 'rref', 'rtitr',
+            'rubberbox', 'salesman', 'sample', 'samplef', 'samwr', 'save', 'save_format', 'save_graph', 'savehistory',
+            'savematfile', 'savewave', 'sca', 'scaling', 'scanf', 'scanf_conversion', 'scf', 'schur', 'sci_files',
+            'sci2exp', 'sci2for', 'sci2map', 'sciargs', 'SciComplex', 'SciComplexArray', 'SciDouble', 'SciDoubleArray',
+            'scilab', 'Scilab', 'ScilabEval', 'scilink', 'scipad', 'SciString', 'SciStringArray', 'sd2sci', 'sda', 'sdf',
+            'secto3d', 'segs_properties', 'semi', 'semicolon', 'semidef', 'sensi', 'set', 'set_posfig_dim',
+            'setbpt', 'setdiff', 'setenv', 'seteventhandler', 'setfield', 'sethomedirectory', 'setlanguage', 'setmenu',
+            'sfact', 'Sfgrayplot', 'Sgrayplot', 'sgrid', 'shortest_path', 'show_arcs', 'show_graph', 'show_nodes',
+            'show_pixmap', 'showprofile', 'sident', 'sign', 'Signal', 'signm', 'simp', 'simp_mode', 'sin', 'sinc',
+            'sincd', 'sinh', 'sinhm', 'sinm', 'size', 'slash', 'sleep', 'sm2des', 'sm2ss', 'smooth', 'solve',
+            'sorder', 'sort', 'sound', 'soundsec', 'sp2adj', 'spaninter', 'spanplus', 'spantwo', 'spchol',
+            'spcompack', 'spec', 'specfact', 'speye', 'spget', 'splin', 'splin2d', 'splin3d', 'split_edge', 'spones',
+            'sprand', 'sprintf', 'spzeros', 'sqroot', 'sqrt', 'sqrtm', 'square', 'squarewave', 'srfaur', 'srkf', 'ss2des',
+            'ss2ss', 'ss2tf', 'sscanf', 'sskf', 'ssprint', 'ssrand', 'st_deviation', 'st_ility', 'stabil', 'stacksize',
+            'star', 'startup', 'stdev', 'stdevf', 'str2code', 'strange', 'strcat', 'strindex', 'string', 'stringbox',
+            'strings', 'stripblanks', 'strong_con_nodes', 'strong_connex', 'strsplit', 'strsubst', 'struct', 'sub2ind',
+            'subf', 'subgraph', 'subplot', 'successors', 'sum', 'supernode', 'surf', 'surface_properties', 'sva',
+            'svd', 'svplot', 'sylm', 'sylv', 'symbols', 'sysconv', 'sysdiag', 'sysfact', 'syslin', 'syssize', 'system',
+            'systems', 'systmat', 'tabul', 'tan', 'tangent', 'tanh', 'tanhm', 'tanm', 'TCL_CreateSlave', 'TCL_DeleteInterp',
+            'TCL_EvalFile', 'TCL_EvalStr', 'TCL_ExistInterp', 'TCL_ExistVar', 'TCL_GetVar', 'TCL_GetVersion', 'TCL_SetVar',
+            'TCL_UnsetVar', 'TCL_UpVar', 'tdinit', 'testmatrix', 'texprint', 'text_properties', 'tf2des', 'tf2ss', 'then',
+            'thrownan', 'tic', 'tilda', 'time_id', 'timer', 'title', 'titlepage', 'TK_EvalFile', 'TK_EvalStr', 'tk_getdir',
+            'tk_getfile', 'TK_GetVar', 'tk_savefile', 'TK_SetVar',  'toc', 'toeplitz', 'tohome', 'tokenpos',
+            'tokens', 'toolbar', 'toprint', 'trace', 'trans', 'trans_closure', 'translatepaths', 'tree2code', 'trfmod',
+            'trianfml', 'tril', 'trimmean', 'trisolve', 'triu', 'try', 'trzeros', 'twinkle', 'type', 'Type', 'typename',
+            'typeof', 'ui_observer', 'uicontrol', 'uimenu', 'uint16', 'uint32', 'uint8', 'ulink', 'unglue', 'union',
+            'unique', 'unix', 'unix_g', 'unix_s', 'unix_w', 'unix_x', 'unobs', 'unsetmenu', 'unzoom', 'user', 'varargin',
+            'varargout', 'Variable', 'variance', 'variancef', 'varn', 'vectorfind', 'waitbar', 'warning', 'wavread',
+            'wavwrite', 'wcenter', 'wfir', 'what', 'where', 'whereami', 'whereis', 'who', 'who_user', 'whos',
+            'wiener', 'wigner', 'winclose', 'window', 'winlist', 'winopen', 'winqueryreg', 'winsid', 'with_atlas',
+            'with_gtk', 'with_javasci', 'with_pvm', 'with_texmacs', 'with_tk', 'writb', 'write', 'write4b', 'x_choices',
+            'x_choose', 'x_dialog', 'x_matrix', 'x_mdialog', 'x_message', 'x_message_modeless', 'xarc', 'xarcs', 'xarrows',
+            'xaxis', 'xbasc', 'xbasimp', 'xbasr', 'xchange', 'xclea', 'xclear', 'xclick', 'xclip', 'xdel', 'xend',
+            'xfarc', 'xfarcs', 'xfpoly', 'xfpolys', 'xfrect', 'xget', 'xgetech', 'xgetfile', 'xgetmouse', 'xgraduate',
+            'xgrid', 'xinfo', 'xinit', 'xlfont', 'xload', 'xls_open', 'xls_read', 'xmltohtml', 'xname', 'xnumb', 'xpause',
+            'xpoly', 'xpolys', 'xrect', 'xrects', 'xrpoly', 'xs2bmp', 'xs2emf', 'xs2eps', 'xs2fig', 'xs2gif', 'xs2ppm',
+            'xs2ps', 'xsave', 'xsegs', 'xselect', 'xset', 'xsetech', 'xsetm', 'xstring', 'xstringb', 'xstringl', 'xtape',
+            'xtitle', 'yulewalk', 'zeropen', 'zeros', 'zgrid', 'zoom_rect', 'zpbutt', 'zpch1', 'zpch2', 'zpell'
+            )
+        ),
+    'SYMBOLS' => array(
+        '<', '>', '=',
+        '!', '@', '~', '&', '|',
+        '+','-', '*', '/', '%',
+        ',', ';', '?', ':', "'"
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => true,
+        1 => true,
+        2 => true,
+        3 => true,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;',
+            2 => 'color: #000000; font-weight: bold;',
+            3 => 'color: #000066;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #666666; font-style: italic;',
+            2 => '',
+            'MULTI' => 'color: #666666; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;',
+            'HARD' => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #009900;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;',
+            'HARD' => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006600;',
+            2 => 'color: #006600;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #339933;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #0000ff;',
+            4 => 'color: #009999;',
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => 'http://www.scilab.org/product/dic-mat-sci/M2SCI_doc.htm',
+        2 => 'http://www.scilab.org/product/dic-mat-sci/M2SCI_doc.htm',
+        3 => 'http://www.scilab.org/product/dic-mat-sci/M2SCI_doc.htm'
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '-&gt;',
+        2 => '::'
+        ),
+    'REGEXPS' => array(
+        //Variable
+        0 => '[\\$%@]+[a-zA-Z_][a-zA-Z0-9_]*',
+        //File Descriptor
+        4 => '&lt;[a-zA-Z_][a-zA-Z0-9_]*&gt;',
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/sdlbasic.php b/examples/includes/geshi/geshi/sdlbasic.php
new file mode 100644 (file)
index 0000000..2e85964
--- /dev/null
@@ -0,0 +1,165 @@
+<?php
+/*************************************************************************************
+ * sdlbasic.php
+ * ------------
+ * Author: Roberto Rossi
+ * Copyright: (c) 2005 Roberto Rossi (http://rsoftware.altervista.org)
+ * Release Version: 1.0.8.3
+ * Date Started: 2005/08/19
+ *
+ * sdlBasic (http://sdlbasic.sf.net) language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2005/08/19 (1.0.0)
+ *  -  First Release
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'sdlBasic',
+    'COMMENT_SINGLE' => array(1 => "'", 2 => "rem", 3 => "!", 4 => "#"),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            'const', 'option', 'explicit', 'qbasic', 'include', 'argc',
+            'argv', 'command', 'command$', 'run', 'shell', 'os', 'declare',
+            'sub', 'function', 'return', 'while', 'wend', 'exit', 'end',
+            'continue', 'if', 'then', 'else', 'elseif',
+            'select', 'case', 'for', 'each', 'step',
+            'next', 'to', 'dim', 'shared', 'common', 'lbound', 'bound',
+            'erase', 'asc', 'chr', 'chr$', 'insert', 'insert$', 'instr', 'lcase',
+            'lcase$', 'left', 'left$', 'len', 'length', 'ltrim', 'ltrim$', 'mid',
+            'mid$', 'replace', 'replace$', 'replacesubstr', 'replacesubstr$',
+            'reverse', 'reverse$', 'right', 'right$', 'rinstr', 'rtrim', 'rtrim$',
+            'space', 'space$', 'str', 'str$', 'strf', 'strf$', 'string', 'string$',
+            'tally', 'trim', 'trim$', 'typeof', 'typeof$', 'ucase', 'ucase$', 'val',
+            'abs', 'acos', 'andbit', 'asin', 'atan', 'bitwiseand', 'bitwiseor',
+            'bitwisexor', 'cos', 'exp', 'fix', 'floor', 'frac', 'hex', 'hex$', 'int',
+            'log', 'min', 'max', 'orbit', 'randomize', 'rnd', 'round', 'sgn', 'sin',
+            'sqr', 'tan', 'xorbit', 'open', 'as', 'file', 'input', 'close', 'output',
+            'append', 'eof', 'fileexists', 'filecopy', 'filemove', 'filerename',
+            'freefile', 'kill', 'loc', 'lof', 'readbyte', 'rename', 'seek',
+            'writebyte', 'chdir', 'dir', 'dir$', 'direxists', 'dirfirst', 'dirnext',
+            'mkdir', 'rmdir', 'print', 'date', 'date$', 'time', 'time$', 'ticks',
+            'data', 'read', 'reservebank', 'freebank', 'copybank', 'loadbank',
+            'savebank', 'setbank', 'sizebank', 'poke', 'doke', 'loke', 'peek', 'deek',
+            'leek', 'memcopy', 'setdisplay', 'setcaption', 'caption', 'displaywidth',
+            'displayheight', 'displaybpp', 'screen', 'directscreen', 'screenopen',
+            'screenclose', 'screenclone', 'screencopy', 'screenfade', 'screenfadein',
+            'screencrossfade', 'screenalpha', 'screenlock', 'screenunlock',
+            'screenrect', 'xscreenrect', 'yscreenrect', 'wscreenrect', 'hscreenrect',
+            'flagscreenrect', 'screenwidth', 'screenheight', 'offset', 'xoffset',
+            'yoffset', 'cls', 'screenswap', 'autoback', 'setautoback',
+            'dualplayfield', 'waitvbl', 'fps', 'rgb', 'enablepalette', 'color',
+            'palette', 'colorcycling', 'ink', 'point', 'dot', 'plot', 'line', 'box',
+            'bar', 'circle', 'fillcircle', 'ellipse', 'fillellipse', 'paint',
+            'loadimage', 'saveimage', 'loadsound', 'savesound', 'loadmusic',
+            'hotspot', 'setcolorkey', 'imageexists', 'imagewidth', 'imageheight',
+            'deleteimage', 'copyimage', 'setalpha', 'zoomimage', 'rotateimage',
+            'rotozoomimage', 'blt', 'pastebob', 'pasteicon', 'grab', 'spriteclip',
+            'sprite', 'deletesprite', 'xsprite', 'ysprite', 'spritewidth',
+            'spriteheight', 'frsprite', 'livesprite', 'spritehit', 'autoupdatesprite',
+            'updatesprite', 'setbob', 'bob', 'deletebob', 'xbob', 'ybob', 'bobwidth',
+            'bobheight', 'frbob', 'livebob', 'bobhit', 'autoupdatebob', 'updatebob',
+            'text', 'setfont', 'textrender', 'pen', 'paper', 'prints', 'locate',
+            'atx', 'aty', 'curson', 'cursoff', 'inputs', 'zoneinputs',
+            'isenabledsound', 'soundexists', 'deletesound', 'copysound',
+            'musicexists', 'playsound', 'volumesound', 'stopsound', 'pausesound',
+            'resumesound', 'vumetersound', 'positionsound', 'soundchannels',
+            'playmusic', 'positionmusic', 'stopmusic', 'fademusic', 'pausemusic',
+            'resumemusic', 'rewindmusic', 'volumemusic', 'speedmusic', 'numdrivescd',
+            'namecd', 'getfreecd', 'opencd', 'indrivecd', 'trackscd', 'curtrackcd',
+            'curframecd', 'playcd', 'playtrackscd',
+            'pausecd', 'resumecd', 'stopcd', 'ejectcd', 'closecd', 'tracktypecd',
+            'tracklengthcd', 'trackoffsetcd', 'key', 'inkey', 'waitkey', 'xmouse',
+            'ymouse', 'xmousescreen', 'ymousescreen', 'bmouse', 'changemouse',
+            'locatemouse', 'mouseshow', 'mousehide', 'mousezone', 'numjoysticks',
+            'namejoystick', 'numaxesjoystick', 'numballsjoystick', 'numhatsjoystick',
+            'numbuttonsjoystick', 'getaxisjoystick', 'gethatjoystick',
+            'getbuttonjoystick', 'xgetballjoystick', 'ygetballjoystick', 'joy',
+            'bjoy', 'wait', 'timer', 'isenabledsock', 'getfreesock', 'opensock',
+            'acceptsock', 'isserverready', 'connectsock', 'connectionreadysock',
+            'isclientready', 'losesock', 'peeksock', 'readsock', 'readbytesock',
+            'readlinesock', 'writesock', 'writebytesock', 'writelinesock',
+            'getremoteip', 'getremoteport', 'getlocalip'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080;',
+            2 => 'color: #808080;',
+            3 => 'color: #808080;',
+            4 => 'color: #808080;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/smalltalk.php b/examples/includes/geshi/geshi/smalltalk.php
new file mode 100644 (file)
index 0000000..9316773
--- /dev/null
@@ -0,0 +1,160 @@
+<?php
+/*************************************************************************************
+ * smalltalk.php
+ * --------
+ * Author: Bananeweizen (Bananeweizen@gmx.de)
+ * Copyright: (c) 2005 Bananeweizen (www.bananeweizen.de)
+ * Release Version: 1.0.8.3
+ * Date Started: 2005/03/27
+ *
+ * Smalltalk language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2006-05-24 (1.0.0)
+ *   -  First Release
+ *
+ * TODO
+ * -------------------------
+ * * recognize nested array symbols correctly
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Smalltalk',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array('"' => '"'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'"),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array('self','super','true','false','nil')
+        ),
+    'SYMBOLS' => array(
+        '[', ']', '=' , ':=', '(', ')', '#'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #7f007f;'
+            ),
+        'COMMENTS' => array(
+            'MULTI' => 'color: #007f00; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => ''
+            ),
+        'BRACKETS' => array(
+            0 => ''
+            ),
+        'STRINGS' => array(
+            0 => 'color: #7f0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #7f0000;'
+            ),
+        'METHODS' => array(
+            0 => ''
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000066; font-weight:bold;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #0000ff;',
+            1 => 'color: #7f0000;',
+            2 => 'color: #7f0000;',
+            3 => 'color: #00007f;',
+            4 => 'color: #7f007f;',
+            5 => 'color: #00007f;',
+            6 => 'color: #00007f;'
+            ),
+        'SCRIPT' => array(
+            0 => ''
+            )
+        ),
+    'URLS' => array(
+        1 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        0 => array(
+            GESHI_SEARCH => '([^a-zA-Z0-9_#<])([A-Z]+[a-zA-Z0-9_]*)(?!>)', //class names
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => ''
+            ),
+        1 => array(
+            GESHI_SEARCH => '(#+)([a-zA-Z0-9_]+)', //symbols
+            GESHI_REPLACE => '\\1\\2',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        2 => array(
+            GESHI_SEARCH => '(#\s*\([^)]*\))', //array symbols
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        3 => array(
+            GESHI_SEARCH => '<PIPE>([a-zA-Z0-9_\s]+)<PIPE>', //temporary variables
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '|',
+            GESHI_AFTER => '|'
+            ),
+        4 => array(
+            GESHI_SEARCH => '(self|super|true|false|nil)', //keywords again (to avoid matching in next regexp)
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        5 => array(
+            GESHI_SEARCH => '([:(,=[.*\/+-]\s*)([a-zA-Z0-9_]+)', //message parameters, message receivers
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 's',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => ''
+            ),
+        6 => array(
+            GESHI_SEARCH => '([a-zA-Z0-9_]+)(\s*:=)', //assignment targets
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => '\\2'
+            )
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/smarty.php b/examples/includes/geshi/geshi/smarty.php
new file mode 100644 (file)
index 0000000..112ab5a
--- /dev/null
@@ -0,0 +1,192 @@
+<?php
+/*************************************************************************************
+ * smarty.php
+ * ----------
+ * Author: Alan Juden (alan@judenware.org)
+ * Copyright: (c) 2004 Alan Juden, Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/07/10
+ *
+ * Smarty template language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2004/11/27 (1.0.0)
+ *  -  Initial Release
+ *
+ * TODO
+ * ----
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Smarty',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array('{*' => '*}'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            '$smarty', 'now', 'const', 'capture', 'config', 'section', 'foreach', 'template', 'version', 'ldelim', 'rdelim',
+            'foreachelse', 'include', 'include_php', 'insert', 'if', 'elseif', 'else', 'php',
+            'sectionelse', 'is_cached',
+            ),
+        2 => array(
+            'capitalize', 'count_characters', 'cat', 'count_paragraphs', 'count_sentences', 'count_words', 'date_format',
+            'default', 'escape', 'indent', 'lower', 'nl2br', 'regex_replace', 'replace', 'spacify', 'string_format',
+            'strip', 'strip_tags', 'truncate', 'upper', 'wordwrap',
+            ),
+        3 => array(
+            'counter', 'cycle', 'debug', 'eval', 'html_checkboxes', 'html_image', 'html_options',
+            'html_radios', 'html_select_date', 'html_select_time', 'html_table', 'math', 'mailto', 'popup_init',
+            'popup', 'textformat'
+            ),
+        4 => array(
+            '$template_dir', '$compile_dir', '$config_dir', '$plugins_dir', '$debugging', '$debug_tpl',
+            '$debugging_ctrl', '$autoload_filters', '$compile_check', '$force_compile', '$caching', '$cache_dir',
+            '$cache_lifetime', '$cache_handler_func', '$cache_modified_check', '$config_overwrite',
+            '$config_booleanize', '$config_read_hidden', '$config_fix_newlines', '$default_template_handler_func',
+            '$php_handling', '$security', '$secure_dir', '$security_settings', '$trusted_dir', '$left_delimiter',
+            '$right_delimiter', '$compiler_class', '$request_vars_order', '$request_use_auto_globals',
+            '$error_reporting', '$compile_id', '$use_sub_dirs', '$default_modifiers', '$default_resource_type'
+            ),
+        5 => array(
+            'append', 'append_by_ref', 'assign', 'assign_by_ref', 'clear_all_assign', 'clear_all_cache',
+            'clear_assign', 'clear_cache', 'clear_compiled_tpl', 'clear_config', 'config_load', 'display',
+            'fetch', 'get_config_vars', 'get_registered_object', 'get_template_vars',
+            'load_filter', 'register_block', 'register_compiler_function', 'register_function',
+            'register_modifier', 'register_object', 'register_outputfilter', 'register_postfilter',
+            'register_prefilter', 'register_resource', 'trigger_error', 'template_exists', 'unregister_block',
+            'unregister_compiler_function', 'unregister_function', 'unregister_modifier', 'unregister_object',
+            'unregister_outputfilter', 'unregister_postfilter', 'unregister_prefilter', 'unregister_resource'
+            ),
+        6 => array(
+            'name', 'file', 'scope', 'global', 'key', 'once', 'script',
+            'loop', 'start', 'step', 'max', 'show', 'values', 'value', 'from', 'item'
+            ),
+        7 => array(
+            'eq', 'neq', 'ne', 'lte', 'gte', 'ge', 'le', 'not', 'mod'
+            ),
+        8 => array(
+            // some common php functions
+            'isset', 'is_array', 'empty', 'count', 'sizeof'
+            )
+        ),
+    'SYMBOLS' => array(
+        '/', '=', '==', '!=', '>', '<', '>=', '<=', '!', '%'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        5 => false,
+        6 => false,
+        7 => false,
+        8 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0600FF;',        //Functions
+            2 => 'color: #008000;',        //Modifiers
+            3 => 'color: #0600FF;',        //Custom Functions
+            4 => 'color: #804040;',        //Variables
+            5 => 'color: #008000;',        //Methods
+            6 => 'color: #6A0A0A;',        //Attributes
+            7 => 'color: #D36900;',        //Text-based symbols
+            8 => 'color: #0600FF;'        //php functions
+            ),
+        'COMMENTS' => array(
+            'MULTI' => 'color: #008080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #D36900;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006600;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #D36900;'
+            ),
+        'SCRIPT' => array(
+            0 => '',
+            1 => 'color: #808080; font-style: italic;',
+            2 => 'color: #009000;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #00aaff;'
+            )
+        ),
+    'URLS' => array(
+        1 => 'http://smarty.php.net/{FNAMEL}',
+        2 => 'http://smarty.php.net/{FNAMEL}',
+        3 => 'http://smarty.php.net/{FNAMEL}',
+        4 => 'http://smarty.php.net/{FNAMEL}',
+        5 => 'http://smarty.php.net/{FNAMEL}',
+        6 => '',
+        7 => 'http://smarty.php.net/{FNAMEL}',
+        8 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        // variables
+        0 => '\$[a-zA-Z][a-zA-Z0-9_]*'
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_ALWAYS,
+    'SCRIPT_DELIMITERS' => array(
+        0 => array(
+            '{' => '}'
+            ),
+        1 => array(
+            '<!--' => '-->',
+        ),
+        2 => array(
+            '<' => '>'
+            )
+    ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        0 => true,
+        1 => false,
+        2 => false
+    ),
+    'PARSER_CONTROL' => array(
+        'KEYWORDS' => array(
+            'DISALLOWED_BEFORE' => "(?<![a-zA-Z0-9\$_\|\#;>|^])",
+            'DISALLOWED_AFTER' => "(?![a-zA-Z0-9_<\|%\\-&])"
+        )
+    )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/sql.php b/examples/includes/geshi/geshi/sql.php
new file mode 100644 (file)
index 0000000..00e4fd2
--- /dev/null
@@ -0,0 +1,140 @@
+<?php
+/*************************************************************************************
+ * sql.php
+ * -------
+ * Author: Nigel McNie (nigel@geshi.org)
+ * Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/06/04
+ *
+ * SQL language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *  -  Added additional symbols for highlighting
+ * 2004/11/27 (1.0.3)
+ *  -  Added support for multiple object splitters
+ * 2004/10/27 (1.0.2)
+ *  -  Added "`" string delimiter
+ *  -  Added "#" single comment starter
+ * 2004/08/05 (1.0.1)
+ *  -  Added support for symbols
+ *  -  Added many more keywords (mostly MYSQL keywords)
+ * 2004/07/14 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ * * Add all keywords
+ * * Split this to several sql files - mysql-sql, ansi-sql etc
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'SQL',
+    'COMMENT_SINGLE' => array(1 =>'--', 2 => '#'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => 1,
+    'QUOTEMARKS' => array("'", '"', '`'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'ADD', 'ALL', 'ALTER', 'AND', 'AS', 'ASC',
+            'AUTO_INCREMENT', 'BETWEEN', 'BINARY', 'BOOLEAN',
+            'BOTH', 'BY', 'CHANGE', 'CHECK', 'COLUMN', 'COLUMNS',
+            'CREATE', 'CROSS', 'DATA', 'DATABASE', 'DATABASES',
+            'DEFAULT', 'DELAYED', 'DELETE', 'DESC', 'DESCRIBE',
+            'DISTINCT', 'DROP', 'ENCLOSED', 'ESCAPED', 'EXISTS',
+            'EXPLAIN', 'FIELD', 'FIELDS', 'FLUSH', 'FOR',
+            'FOREIGN', 'FROM', 'FULL', 'FUNCTION', 'GRANT',
+            'GROUP', 'HAVING', 'IDENTIFIED', 'IF', 'IGNORE',
+            'IN', 'INDEX', 'INFILE', 'INNER', 'INSERT', 'INTO',
+            'IS', 'JOIN', 'KEY', 'KEYS', 'KILL', 'LANGUAGE',
+            'LEADING', 'LEFT', 'LIKE', 'LIMIT', 'LINES', 'LOAD',
+            'LOCAL', 'LOCK', 'LOW_PRIORITY', 'MODIFY', 'NATURAL',
+            'NEXTVAL', 'NOT', 'NULL', 'ON', 'OPTIMIZE', 'OPTION',
+            'OPTIONALLY', 'OR', 'ORDER', 'OUTER', 'OUTFILE',
+            'PRIMARY', 'PROCEDURAL', 'PROCEEDURE', 'READ',
+            'REFERENCES', 'REGEXP', 'RENAME', 'REPLACE',
+            'RETURN', 'REVOKE', 'RIGHT', 'RLIKE', 'SELECT',
+            'SET', 'SETVAL', 'SHOW', 'SONAME', 'STATUS',
+            'STRAIGHT_JOIN', 'TABLE', 'TABLES', 'TEMINATED',
+            'TEMPORARY', 'TO', 'TRAILING', 'TRIGGER', 'TRUNCATE',
+            'TRUSTED', 'UNION', 'UNIQUE', 'UNLOCK', 'UNSIGNED',
+            'UPDATE', 'USE', 'USING', 'VALUES', 'VARIABLES',
+            'VIEW', 'WHERE', 'WITH', 'WRITE', 'XOR', 'ZEROFILL'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '=', '<', '>', '|', ',', '.', '+', '-', '*', '/'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #993333; font-weight: bold;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            2 => 'color: #808080; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/tcl.php b/examples/includes/geshi/geshi/tcl.php
new file mode 100644 (file)
index 0000000..9badb21
--- /dev/null
@@ -0,0 +1,194 @@
+<?php
+/*************************************************************************************
+ * tcl.php
+ * ---------------------------------
+ * Author: Reid van Melle (rvanmelle@gmail.com)
+ * Copyright: (c) 2004 Reid van Melle (sorry@nowhere)
+ * Release Version: 1.0.8.3
+ * Date Started: 2006/05/05
+ *
+ * TCL/iTCL language file for GeSHi.
+ *
+ * This was thrown together in about an hour so I don't expect
+ * really great things.  However, it is a good start.  I never
+ * got a change to try out the iTCL or object-based support but
+ * this is not widely used anyway.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *  -  Added description of extra language features (SF#1970248)
+ * 2006/05/05 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2006/05/05)
+ * -------------------------
+ * - Get TCL built-in special variables highlighted with a new color..
+ *   currently, these are listed in //special variables in the keywords
+ *   section, but they get covered by the general REGEXP for symbols
+ * - General cleanup, testing, and verification
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'TCL',
+    'COMMENT_SINGLE' => array(1 => '#'),
+    'COMMENT_MULTI' => array(),
+    'COMMENT_REGEXP' => array(
+        1 => '/(?<!\\\\)#(?:\\\\\\\\|\\\\\\n|.)*$/m',
+        2 => '/{[^}\n]+}/'
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"', "'"),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        /*
+         * Set 1: reserved words
+         * http://python.org/doc/current/ref/keywords.html
+         */
+        1 => array(
+            'proc', 'global', 'upvar', 'if', 'then', 'else', 'elseif', 'for', 'foreach',
+            'break', 'continue', 'while', 'set', 'eval', 'case', 'in', 'switch',
+            'default', 'exit', 'error', 'return', 'uplevel', 'loop',
+            'for_array_keys', 'for_recursive_glob', 'for_file', 'unwind_protect',
+            'expr', 'catch', 'namespace', 'rename', 'variable',
+            // itcl
+            'method', 'itcl_class', 'public', 'protected'),
+
+        /*
+         * Set 2: builtins
+         * http://asps.activatestate.com/ASPN/docs/ActiveTcl/8.4/tcl/tcl_2_contents.htm
+         */
+        2 => array(
+            // string handling
+            'append', 'binary', 'format', 're_syntax', 'regexp', 'regsub',
+            'scan', 'string', 'subst',
+            // list handling
+            'concat', 'join', 'lappend', 'lindex', 'list', 'llength', 'lrange',
+            'lreplace', 'lsearch', 'lset', 'lsort', 'split',
+            // procedures and output
+            'incr', 'close', 'eof', 'fblocked', 'fconfigure', 'fcopy', 'file',
+            'fileevent', 'flush', 'gets', 'open', 'puts', 'read', 'seek',
+            'socket', 'tell',
+            // packages and source files
+            'load', 'loadTk', 'package', 'pgk::create', 'pgk_mkIndex', 'source',
+            // interpreter routines
+            'bgerror', 'history', 'info', 'interp', 'memory', 'unknown',
+            // library routines
+            'enconding', 'http', 'msgcat',
+            // system related
+            'cd', 'clock', 'exec', 'glob', 'pid', 'pwd', 'time',
+            // platform specified
+            'dde', 'registry', 'resource',
+            // special variables
+            '$argc', '$argv', '$errorCode', '$errorInfo', '$argv0',
+            '$auto_index', '$auto_oldpath', '$auto_path', '$env',
+            '$tcl_interactive', '$tcl_libpath', '$tcl_library',
+            '$tcl_pkgPath', '$tcl_platform', '$tcl_precision', '$tcl_traceExec',
+            ),
+
+        /*
+         * Set 3: standard library
+         */
+        3 => array(
+            'comment', 'filename', 'library', 'packagens', 'tcltest', 'tclvars',
+            ),
+
+        /*
+         * Set 4: special methods
+         */
+//        4 => array(
+//            )
+
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}', '$', '*', '&', '%', '!', ';', '<', '>', '?'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true,
+//        4 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #ff7700;font-weight:bold;',    // Reserved
+            2 => 'color: #008000;',                        // Built-ins + self
+            3 => 'color: #dc143c;',                        // Standard lib
+//            4 => 'color: #0000cd;'                        // Special methods
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #808080; font-style: italic;',
+            2 => 'color: #483d8b;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: black;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #483d8b;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #ff4500;'
+            ),
+        'METHODS' => array(
+            1 => 'color: black;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #ff3333;'
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+//        4 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '::'
+        ),
+    'REGEXPS' => array(
+        //Special variables
+        0 => '[\\$]+[a-zA-Z_][a-zA-Z0-9_]*',
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'PARSER_CONTROL' => array(
+        'COMMENTS' => array(
+            'DISALLOWED_BEFORE' => '\\'
+        )
+    )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/teraterm.php b/examples/includes/geshi/geshi/teraterm.php
new file mode 100644 (file)
index 0000000..f2938ca
--- /dev/null
@@ -0,0 +1,317 @@
+<?php
+/*************************************************************************************
+ * teraterm.php
+ * --------
+ * Author: Boris Maisuradze (boris at logmett.com)
+ * Copyright: (c) 2008 Boris Maisuradze (http://logmett.com)
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/09/26
+ *
+ * Tera Term Macro language file for GeSHi.
+ *
+ *
+ * This version of ttl.php was created for Tera Term 4.60 and LogMeTT 2.9.4.
+ * Newer versions of these application can contain additional Macro commands
+ * and/or keywords that are not listed here. The latest release of ttl.php
+ * can be downloaded from Download section of LogMeTT.com
+ *
+ * CHANGES
+ * -------
+ * 2008/09/26 (1.0.8)
+ *   -  First Release for Tera Term 4.60 and below.
+ *
+ * TODO (updated 2008/09/26)
+ * -------------------------
+ * *
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Tera Term Macro',
+    'COMMENT_SINGLE' => array(1 => ';'),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        /* Commands */
+        1 => array(
+            'Beep',
+            'BplusRecv',
+            'BplusSend',
+            'Break',            // (version 4.53 or later)
+            'Call',
+            'CallMenu',         // (version 4.56 or later)
+            'ChangeDir',
+            'ClearScreen',
+            'Clipb2Var',        //(version 4.46 or later)
+            'ClosesBox',
+            'CloseTT',
+            'Code2Str',
+            'Connect',
+            'CRC32',            // (version 4.60 or later)
+            'CRC32File',        // (version 4.60 or later)
+            'CygConnect',       // (version 4.57 or later)
+            'DelPassword',
+            'Disconnect',
+            'Do',               // (version 4.56 or later)
+            'Else',
+            'EnableKeyb',
+            'End',
+            'EndIf',
+            'EndUntil',         // (version 4.56 or later)
+            'EndWhile',
+            'Exec',
+            'ExecCmnd',
+            'Exit',
+            'FileClose',
+            'FileConcat',
+            'FileCopy',
+            'FileCreate',
+            'FileDelete',
+            'FileMarkPtr',
+            'FilenameBox',      //(version 4.54 or later)
+            'FileOpen',
+            'FileRead',
+            'FileReadln',       // (version 4.48 or later)
+            'FileRename',
+            'FileSearch',
+            'FileSeek',
+            'FileSeekBack',
+            'FileStrSeek',
+            'FileStrSeek2',
+            'FileWrite',
+            'FileWriteln',
+            'FindOperations',
+            'FlushRecv',
+            'ForNext',
+            'GetDate',
+            'GetDir',           //(version 4.46 or later)
+            'GetEnv',
+            'GetPassword',
+            'GetTime',
+            'GetTitle',
+            'GetVer',           //(version 4.58 or later)
+            'GoTo',
+            'If',
+            'IfDefined',        // (version 4.46 or later)
+            'IfThenElseIf',
+            'Include',
+            'InputBox',
+            'Int2Str',
+            'KmtFinish',
+            'KmtGet',
+            'KmtRecv',
+            'KmtSend',
+            'LoadKeyMap',
+            'LogClose',
+            'LogOpen',
+            'LogPause',
+            'LogStart',
+            'LogWrite',
+            'Loop',             // (version 4.56 or later)
+            'MakePath',
+            'MessageBox',
+            'MPause',           // (version 4.27 or later)
+            'PasswordBox',
+            'Pause',
+            'QuickvanRecv',
+            'QuickvanSend',
+            'Random',           //(version 4.27 or later)
+            'Recvln',
+            'RestoreSetup',
+            'Return',
+            'RotateLeft',       //(version 4.54 or later)
+            'RotateRight',      //(version 4.54 or later)
+            'ScpRecv',          // (version 4.57 or later)
+            'ScpSend',          // (version 4.57 or later)
+            'Send',
+            'SendBreak',
+            'SendFile',
+            'SendKcode',
+            'Sendln',
+            'SetBaud',          // (version 4.58 or later)
+            'SetDate',
+            'SetDir',
+            'SetDlgPos',
+            'SetDTR',           // (version 4.59 or later)
+            'SetRTS',           // (version 4.59 or later)
+            'SetEnv',           // (version 4.54 or later)
+            'SetEcho',
+            'SetExitCode',
+            'SetSync',
+            'SetTime',
+            'SetTitle',
+            'Show',
+            'ShowTT',
+            'Sprintf',          // (version 4.52 or later)
+            'StatusBox',
+            'Str2Code',
+            'Str2Int',
+            'StrCompare',
+            'StrConcat',
+            'StrCopy',
+            'StrLen',
+            'StrMatch',         // (version 4.59 or later)
+            'StrScan',
+            'Testlink',
+            'Then',
+            'ToLower',          //(version 4.53 or later)
+            'ToUpper',          //(version 4.53 or later)
+            'Unlink',
+            'Until',            // (version 4.56 or later)
+            'Var2Clipb',        //(version 4.46 or later)
+            'Wait',
+            'WaitEvent',
+            'Waitln',
+            'WaitRecv',
+            'WaitRegex',        // (version 4.21 or later)
+            'While',
+            'XmodemRecv',
+            'XmodemSend',
+            'YesNoBox',
+            'ZmodemRecv',
+            'ZmodemSend'
+            ),
+        /* System Variables */
+        2 => array(
+            'groupmatchstr1',
+            'groupmatchstr2',
+            'groupmatchstr3',
+            'groupmatchstr4',
+            'groupmatchstr5',
+            'groupmatchstr6',
+            'groupmatchstr7',
+            'groupmatchstr8',
+            'groupmatchstr9',
+            'inputstr',
+            'matchstr',
+            'param2',
+            'param3',
+            'param4',
+            'param5',
+            'param6',
+            'param7',
+            'param8',
+            'param9',
+            'result',
+            'timeout'
+            ),
+        /* LogMeTT Key Words */
+        3 => array(
+            '$[1]',
+            '$[2]',
+            '$[3]',
+            '$[4]',
+            '$[5]',
+            '$[6]',
+            '$[7]',
+            '$[8]',
+            '$connection$',
+            '$email$',
+            '$logdir$',
+            '$logfilename$',
+            '$logit$',
+            '$mobile$',
+            '$name$',
+            '$pager$',
+            '$parent$',
+            '$phone$',
+            '$snippet$',
+            '$ttdir$',
+            '$user$',
+            '$windir$',
+            ),
+        /* Keyword Symbols */
+        4 => array(
+            'and',
+            'not',
+            'or',
+            'xor'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']',
+        '~', '!', '+', '-', '*', '/', '%', '>>', '<<', '<<<', '>>>', '&', '^', '|',
+        '<>', '<=', '>=', '=', '==', '<>', '!=', '&&', '||'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000080; font-weight: bold!important;',
+            2 => 'color: #808000; font-weight: bold;',  // System Variables
+            3 => 'color: #ff0000; font-weight: bold;',  // LogMeTT Key Words
+            4 => 'color: #ff00ff; font-weight: bold;'   // Keyword Symbols
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #008000; font-style: italic;',
+            ),
+        'ESCAPE_CHAR' => array(),
+        'BRACKETS' => array(
+            0 => 'color: #ff00ff; font-weight: bold;'
+        ),
+        'STRINGS' => array(
+            0 => 'color: #800080;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #008080;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #ff00ff; font-weight: bold;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #0000ff; font-weight: bold;'
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(),
+    'REGEXPS' => array(
+        0 => array (
+            GESHI_SEARCH => '(\:[_a-zA-Z][_a-zA-Z0-9]+)',
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            )
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(),
+    'HIGHLIGHT_STRICT_BLOCK' => array(),
+    'TAB_WIDTH' => 4
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/text.php b/examples/includes/geshi/geshi/text.php
new file mode 100644 (file)
index 0000000..6c6e260
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+/*************************************************************************************
+ * text.php
+ * --------
+ * Author: Sean Hanna (smokingrope@gmail.com)
+ * Copyright: (c) 2006 Sean Hanna
+ * Release Version: 1.0.8.3
+ * Date Started: 04/23/2006
+ *
+ * Standard Text File (No Syntax Highlighting).
+ * Plaintext language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 04/23/2006 (0.5.0)
+ * - Syntax File Created
+ *
+ * 04/27/2006 (1.0.0)
+ * - Documentation Cleaned Up
+ * - First Release
+ *
+ * TODO (updated 04/27/2006)
+ * -------------------------
+ *
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Text',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array(),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(),
+    'SYMBOLS' => array(),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(),
+        'COMMENTS' => array(),
+        'ESCAPE_CHAR' => array(),
+        'BRACKETS' => array(),
+        'STRINGS' => array(),
+        'NUMBERS' => array(),
+        'METHODS' => array(),
+        'SYMBOLS' => array(),
+        'SCRIPT' => array(),
+        'REGEXPS' => array()
+        ),
+    'URLS' => array(),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(),
+    'REGEXPS' => array(),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(),
+    'HIGHLIGHT_STRICT_BLOCK' => array(),
+    'PARSER_CONTROL' => array(
+        'ENABLE_FLAGS' => array(
+            'ALL' => GESHI_NEVER
+        ),
+    )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/thinbasic.php b/examples/includes/geshi/geshi/thinbasic.php
new file mode 100644 (file)
index 0000000..caa6edf
--- /dev/null
@@ -0,0 +1,868 @@
+<?php
+/*************************************************************************************
+ * thinbasic.php
+ * ------
+ * Author: Eros Olmi (eros.olmi@thinbasic.com)
+ * Copyright: (c) 2006 Eros Olmi (http://www.thinbasic.com), Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2006/05/12
+ *
+ * thinBasic language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2006/05/12 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2006/05/12)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'thinBasic',
+    'COMMENT_SINGLE' => array(1 => "'"),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            'XOR','XML_TREETOSTRING','XML_PARSEFILE','XML_PARSE','XML_PARENT','XML_NODETYPE','XML_NODETOSTRING','XML_NEXTSIBLING',
+            'XML_LASTERROR','XML_GETTAG','XML_FREE','XML_FINDNODE','XML_DECODEPARAM','XML_CHILDDATA','XML_CHILD','XML_ATTRIBVALUE',
+            'XML_ATTRIBNAME','XML_ATTRIBCOUNT','WORD','WITH','WIN_SHOW','WIN_SETTITLE','WIN_SETFOREGROUND','WIN_ISZOOMED',
+            'WIN_ISVISIBLE','WIN_ISICONIC','WIN_GETTITLE','WIN_GETFOREGROUND','WIN_GETCLASS','WIN_GETACTIVE','WIN_FLASH','WIN_FINDBYTITLE',
+            'WIN_FINDBYCLASS','WHILE','WEND','VERIFY','VARPTR','VARIANTVT$','VARIANTVT','VARIANT',
+            'VARIABLE_GETINFO','VARIABLE_EXISTS','VARIABLE_EXIST','VALUE','VAL','USING$','USING','USES',
+            'USER','UNTIL','UNITS','UNION','UNICODE2ASCII','UDP_SEND','UDP_RECV','UDP_OPENSERVER',
+            'UDP_OPEN','UDP_FREEFILE','UDP_CLOSE','UCODE$','UCASE$','UBOUND','TYPE','TRIMFULL$',
+            'TRIM$','TOOLTIP','TOKENIZER_MOVETOEOL','TOKENIZER_KEYSETUSERSTRING','TOKENIZER_KEYSETUSERNUMBER','TOKENIZER_KEYGETUSERSTRING','TOKENIZER_KEYGETUSERNUMBER','TOKENIZER_KEYGETSUBTYPE',
+            'TOKENIZER_KEYGETNAME','TOKENIZER_KEYGETMAINTYPE','TOKENIZER_KEYFIND','TOKENIZER_KEYADD','TOKENIZER_GETNEXTTOKEN','TOKENIZER_DEFAULT_SET','TOKENIZER_DEFAULT_GET','TOKENIZER_DEFAULT_CODE',
+            'TOKENIZER_DEFAULT_CHAR','TO','TIMER','TIME$','THEN','TEXTBOX','TEXT','TCP_SEND',
+            'TCP_RECV','TCP_PRINT','TCP_OPEN','TCP_LINEINPUT','TCP_FREEFILE','TCP_CLOSE','TB_IMGCTX_SETIMAGEADJUSTMENT','TB_IMGCTX_LOADIMAGE',
+            'TB_IMGCTX_GETIMAGEADJUSTMENT','TBGL_VIEWPORT','TBGL_VERTEX','TBGL_USETEXTUREFLAG','TBGL_USETEXTURE','TBGL_USELINESTIPPLEFLAG','TBGL_USELINESTIPPLE','TBGL_USELIGHTSOURCEFLAG',
+            'TBGL_USELIGHTSOURCE','TBGL_USELIGHTINGFLAG','TBGL_USELIGHTING','TBGL_USEFOGFLAG','TBGL_USEFOG','TBGL_USEDEPTHMASK','TBGL_USEDEPTHFLAG','TBGL_USEDEPTH',
+            'TBGL_USECLIPPLANEFLAG','TBGL_USECLIPPLANE','TBGL_USEBLENDFLAG','TBGL_USEBLEND','TBGL_USEALPHATEST','TBGL_TRANSLATE','TBGL_TORUS','TBGL_TEXCOORD2D',
+            'TBGL_SPHERE','TBGL_SHOWWINDOW','TBGL_SHOWCURSOR','TBGL_SETWINDOWTITLE','TBGL_SETUPLIGHTSOURCE','TBGL_SETUPFOG','TBGL_SETUPCLIPPLANE','TBGL_SETPRIMITIVEQUALITY',
+            'TBGL_SETLIGHTPARAMETER','TBGL_SETDRAWDISTANCE','TBGL_SCALE','TBGL_SAVESCREENSHOT','TBGL_ROTATEXYZ','TBGL_ROTATE','TBGL_RESETMATRIX','TBGL_RENDERTOTEXTURE',
+            'TBGL_RENDERMATRIX3D','TBGL_RENDERMATRIX2D','TBGL_PUSHMATRIX','TBGL_PRINTFONT','TBGL_PRINTBMP','TBGL_PRINT','TBGL_POS3DTOPOS2D','TBGL_POPMATRIX',
+            'TBGL_POLYGONLOOK','TBGL_POINTSIZE','TBGL_POINTINSIDE3D','TBGL_NORMAL','TBGL_NEWLIST','TBGL_MOUSEGETWHEELDELTA','TBGL_MOUSEGETRBUTTON','TBGL_MOUSEGETPOSY',
+            'TBGL_MOUSEGETPOSX','TBGL_MOUSEGETMBUTTON','TBGL_MOUSEGETLBUTTON','TBGL_M15SETVERTEXZ','TBGL_M15SETVERTEXY','TBGL_M15SETVERTEXXYZ','TBGL_M15SETVERTEXX','TBGL_M15SETVERTEXTEXY',
+            'TBGL_M15SETVERTEXTEXXY','TBGL_M15SETVERTEXTEXX','TBGL_M15SETVERTEXTEXN','TBGL_M15SETVERTEXRGB','TBGL_M15SETVERTEXR','TBGL_M15SETVERTEXPSTOP','TBGL_M15SETVERTEXPARAM','TBGL_M15SETVERTEXLAYER',
+            'TBGL_M15SETVERTEXG','TBGL_M15SETVERTEXB','TBGL_M15SETMODELVERTEXCOUNT','TBGL_M15SETBONECHILD','TBGL_M15ROTBONEZ','TBGL_M15ROTBONEY','TBGL_M15ROTBONEX','TBGL_M15ROTBONE',
+            'TBGL_M15RESETBONES','TBGL_M15RECALCNORMALS','TBGL_M15LOADMODEL','TBGL_M15INITMODELBUFFERS','TBGL_M15GETVERTEXZ','TBGL_M15GETVERTEXY','TBGL_M15GETVERTEXXYZ','TBGL_M15GETVERTEXX',
+            'TBGL_M15GETVERTEXTEXY','TBGL_M15GETVERTEXTEXXY','TBGL_M15GETVERTEXTEXX','TBGL_M15GETVERTEXTEXN','TBGL_M15GETVERTEXRGB','TBGL_M15GETVERTEXR','TBGL_M15GETVERTEXPSTOP','TBGL_M15GETVERTEXPARAM',
+            'TBGL_M15GETVERTEXLAYER','TBGL_M15GETVERTEXG','TBGL_M15GETVERTEXB','TBGL_M15GETMODELVERTEXCOUNT','TBGL_M15GETMODELPOLYCOUNT','TBGL_M15ERASECHILDBONES','TBGL_M15DRAWMODEL','TBGL_M15DEFBONERESET',
+            'TBGL_M15DEFBONELAYER','TBGL_M15DEFBONEBOX','TBGL_M15DEFBONEANCHOR','TBGL_M15DEFBONEADDVERTEX','TBGL_M15CLEARMODEL','TBGL_M15APPLYBONES','TBGL_M15ADDBONETREEITEM','TBGL_LOADTEXTURE',
+            'TBGL_LOADFONT','TBGL_LOADBMPFONT','TBGL_LINEWIDTH','TBGL_LINESTIPPLE','TBGL_KILLFONT','TBGL_ISWINDOW','TBGL_ISPOINTVISIBLE','TBGL_ISPOINTBEHINDVIEW',
+            'TBGL_GETWINDOWMULTIKEYSTATE','TBGL_GETWINDOWKEYSTATE','TBGL_GETWINDOWKEYONCE','TBGL_GETWINDOWCLIENT','TBGL_GETTEXTURENAME','TBGL_GETTEXTURELIST','TBGL_GETPIXELINFO','TBGL_GETMULTIASYNCKEYSTATE',
+            'TBGL_GETLASTGLERROR','TBGL_GETFRAMERATE','TBGL_GETDESKTOPINFO','TBGL_GETASYNCKEYSTATE','TBGL_ERRORMESSAGES','TBGL_ENDPOLY','TBGL_ENDLIST','TBGL_DRAWFRAME',
+            'TBGL_DESTROYWINDOW','TBGL_DELETELIST','TBGL_CYLINDER','TBGL_CREATEWINDOWEX','TBGL_CREATEWINDOW','TBGL_COLORALPHA','TBGL_COLOR','TBGL_CLEARFRAME',
+            'TBGL_CAMERA','TBGL_CALLLIST','TBGL_BUILDFONT','TBGL_BOX','TBGL_BLENDFUNC','TBGL_BINDTEXTURE','TBGL_BEGINPOLY','TBGL_BACKCOLOR',
+            'TBGL_ALPHAFUNC','TBDI_JOYZ','TBDI_JOYY','TBDI_JOYX','TBDI_JOYSTOPEFFECT','TBDI_JOYSLIDER','TBDI_JOYSETRANGEZ','TBDI_JOYSETRANGEY',
+            'TBDI_JOYSETRANGEXYZ','TBDI_JOYSETRANGEX','TBDI_JOYSETDEADZONEZ','TBDI_JOYSETDEADZONEY','TBDI_JOYSETDEADZONEXYZ','TBDI_JOYSETDEADZONEX','TBDI_JOYSETAUTOCENTER','TBDI_JOYRZ',
+            'TBDI_JOYRY','TBDI_JOYRX','TBDI_JOYPOV','TBDI_JOYPLAYEFFECT','TBDI_JOYLOADEFFECT','TBDI_JOYHASFF','TBDI_JOYHASEFFECT','TBDI_JOYGETEFFECTNAME',
+            'TBDI_JOYGETEFFECTGUID','TBDI_JOYCREATEEFFECT','TBDI_JOYCOUNTPOV','TBDI_JOYCOUNTEFFECTS','TBDI_JOYCOUNTBTN','TBDI_JOYCOUNTAXES','TBDI_JOYBUTTON','TBDI_JOYAVAIL',
+            'TBDI_INIT','TBASS_STREAMFREE','TBASS_STREAMCREATEFILE','TBASS_SETVOLUME','TBASS_SETEAXPRESET','TBASS_SETEAXPARAMETERS','TBASS_SETCONFIG','TBASS_SET3DPOSITION',
+            'TBASS_SET3DFACTORS','TBASS_SAMPLELOAD','TBASS_SAMPLEGETCHANNEL','TBASS_MUSICLOAD','TBASS_MUSICFREE','TBASS_INIT','TBASS_GETVOLUME','TBASS_GETVERSION',
+            'TBASS_GETCONFIG','TBASS_FREE','TBASS_ERRORGETCODE','TBASS_CHANNELSTOP','TBASS_CHANNELSETPOSITION','TBASS_CHANNELSETATTRIBUTES','TBASS_CHANNELSET3DPOSITION','TBASS_CHANNELPLAY',
+            'TBASS_CHANNELPAUSE','TBASS_CHANNELISACTIVE','TBASS_CHANNELGETPOSITION','TBASS_CHANNELGETLENGTH','TBASS_CHANNELGETATTRIBUTES','TBASS_APPLY3D','TANH','TANGENT',
+            'TAN','TALLY','TABCTRL_ONNOTIFY','TABCTRL_INSERTITEM','TABCTRL_GETCURSEL','SWAP','SUB','STRZIP$',
+            'STRUNZIP$','STRREVERSE$','STRPTRLEN','STRPTR','STRINSERT$','STRING$','STRING','STRDELETE$',
+            'STR$','STOP','STEP','STDOUT','STDIN','STAT_SUM','STAT_STDERROR','STAT_STDDEVIATION',
+            'STAT_RANDOM','STAT_PRODUCT','STAT_MIN','STAT_MEDIAN','STAT_MEANHARMONIC','STAT_MEANGEOMETRIC','STAT_MEANARITHMETIC','STAT_MAX',
+            'STAT_INVERSESUM','STAT_HISTOGRAM','STAT_FILLARRAY','STAT_COUNT','STAT_COPYARRAY','STAT_CLONEARRAY','STAT_CHISQUARE','STATIC',
+            'STATE','SQR','SPLIT','SORT','SMTP_STATISTICS','SMTP_SETOPTION','SMTP_SETLOGFILE','SMTP_SENDHTML',
+            'SMTP_SENDEMAIL','SMTP_GETERROR','SMTP_FINISHED','SMTP_DEBUG','SMTP_CONNECT','SMTP_CLOSE','SLEEP','SIZEOF',
+            'SIZE','SINH','SINGLE','SIN','SIGNED','SHOW','SHIFT','SHAPETOBMP',
+            'SGN','SETAT','SET','SENDMESSAGE','SENDKEYSBULK','SENDKEYS','SEND','SELECTEXPRESSION',
+            'SELECT','SECH','SEC','SCAN','SAPI_SPEAK','SAPI_SETVOLUME','SAPI_SETRATE','SAPI_MODULELOADED',
+            'SAPI_GETVOLUME','SAPI_GETRATE','RTRIM$','RTF_SETTEXT','RTF_SETFONTSIZE','RTF_SETFONTNAME','RTF_SETFGCOLOR','RTF_SETEFFECT',
+            'RTF_SETBGCOLOR','RTF_SETALIGN','RTF_SAVETOFILE','RTF_LOADFROMFILE','RTF_GETTEXT','RTF_GETFONTSIZE','RTF_GETFONTNAME','RTF_GETEFFECT',
+            'RTF_GETCLASS','RTF_APPENDTEXT','RSET$','ROUND','RNDF','RND','RIGHT$','RIGHT',
+            'RGB','RESOURCE','RESIZE','RESET','REPLACE$','REPEAT$','REMOVE$','REM',
+            'REGISTRY_SETVALUE','REGISTRY_SETTXTNUM','REGISTRY_SETTXTBOOL','REGISTRY_SETDWORD','REGISTRY_GETVALUE','REGISTRY_GETTXTNUM','REGISTRY_GETTXTBOOL','REGISTRY_GETDWORD',
+            'REGISTRY_GETALLKEYS','REGISTRY_DELVALUE','REGISTRY_DELKEY','REFERENCE','REF','REDRAW','REDIM','RAS_SETPARAMS',
+            'RAS_OPENDIALUPDIALOG','RAS_LOADENTRIES','RAS_HANGUPALL','RAS_HANGUP','RAS_GETENTRY','RAS_BEGINDIAL','RANDOMIZE','RADTODEG',
+            'QUERYPERFORMANCEFREQUENCY','QUERYPERFORMANCECOUNTER','QUAD','PTR','PRESERVE','POST','POPUP','POKE$',
+            'POKE','PIXELS','PI','PERMUTATIONS','PEEKMESSAGE','PEEK$','PEEK','PC_SYSTEMUPFROM',
+            'PC_SUSPENDSTATE','PC_SHUTDOWN','PC_SHOWCARET','PC_SETCARETBLINKTIME','PC_RESTARTDIALOG','PC_PREVENTSHUTDOWN','PC_LOCK','PC_INSERTCD',
+            'PC_HIDECARET','PC_GETSTATEONOFF','PC_GETSCROLLLOCKKEYSTATE','PC_GETNUMLOCKKEYSTATE','PC_GETCARETBLINKTIME','PC_GETCAPSLOCKKEYSTATE','PC_EMPTYBIN','PC_EJECTCD',
+            'PC_DECODECDERROR','PCT','PARSESET$','PARSECOUNT','PARSE$','PARSE','PARAMETERS','OUTSIDE',
+            'OS_WINVERSIONTEXT','OS_WINGETVERSIONTIMELINE','OS_SHELLEXECUTE','OS_SHELLABOUT','OS_SHELL','OS_SETLASTCALLDLLERROR','OS_SERVICESTOP','OS_SERVICESTATUSDESCRIPTION',
+            'OS_SERVICESTARTTYPEDESCRIPTION','OS_SERVICESTART','OS_SERVICESETSTARTTYPE','OS_SERVICEQUERY','OS_SERVICEGETSTARTTYPE','OS_SERVICEGETLIST','OS_PROCESSKILLBYNAME','OS_PROCESSKILLBYID',
+            'OS_PROCESSISRUNNING','OS_PROCESSGETLIST','OS_PROCESSGETID','OS_PROCESSARERUNNING','OS_MESSAGEBEEP','OS_ISWOW64','OS_ISFEATUREPRESENT','OS_IEVERSION',
+            'OS_GETWINDOWSDIR','OS_GETUSERNAME','OS_GETTEMPDIR','OS_GETSYSTEMDIR','OS_GETSPECIALFOLDER','OS_GETLASTCALLDLLSTATUS','OS_GETLASTCALLDLLERROR','OS_GETCURRENTTHREADID',
+            'OS_GETCURRENTPROCESSID','OS_GETCOMPUTERNAME','OS_GETCOMMANDS','OS_GETCOMMAND','OS_FLASHWINDOW','OS_FATALAPPEXIT','OS_ENVIRON','OS_CALLDLL',
+            'OR','OPTIONAL','OPTION','OPT','ONCE','ON','OFF','NUMBER',
+            'NOT','NEXT','NEW','MSGBOX','MOUSEPTR','MODULE','MODELESS','MODAL',
+            'MOD','MKWRD$','MKS$','MKQ$','MKL$','MKI$','MKE$','MKDWD$',
+            'MKD$','MKCUX$','MKCUR$','MKBYT$','MIN$','MIN','MID$','MENU',
+            'MDI_CREATE','MCASE$','MAX$','MAX','MAKWRD','MAKLNG','MAKINT','MAKDWR',
+            'LTRIM$','LSET$','LOWRD','LOOP','LONG','LOINT','LOG_WRITE','LOGB',
+            'LOG2','LOG10','LOG','LOCAL','LOC','LL_UPDATEBYNAME','LL_UPDATE','LL_TOSTRING',
+            'LL_TOFILE','LL_NAME','LL_GETITEM','LL_GETBYNUMBER','LL_FROMFILE','LL_FREE','LL_FINDLAST','LL_FINDBYNAME',
+            'LL_FINDBYDATA','LL_DELETELIKE','LL_DELETEBYNAME','LL_DELETE','LL_DATABYNAME','LL_DATA','LL_COUNT','LL_ADD',
+            'LISTBOX','LINE','LIBRARY_EXISTS','LIB','LEN','LEFT$','LEFT','LCASE$',
+            'LBOUND','LABEL','KILL','JOIN$','ITERATE','ISWINDOW','ISUNICODE','ISTRUE',
+            'ISODD','ISLIKE','ISFALSE','ISEVEN','IP_TOSTRING','IP_ADDR','INTERNALINFO','INTEGER',
+            'INT','INSTR','INSIDE','INPUTBOX$','INI_SETKEY','INI_GETSECTIONSLIST','INI_GETSECTIONKEYLIST','INI_GETKEY',
+            'INET_URLDOWNLOAD','INET_PING','INET_OPENDIALUPDIALOG','INET_GETSTATE','INET_GETREMOTEMACADDRESS','INET_GETIP','INET_GETCONNECTIONMODE','INCR',
+            'IN','IMAGE','IIF$','IIF','IF','ICRYPTO_TESTSHA1','ICRYPTO_TESTMD5','ICRYPTO_TESTCRC32',
+            'ICRYPTO_TESTCRC16','ICRYPTO_STRING2ASCII','ICRYPTO_SHA1','ICRYPTO_MD5','ICRYPTO_ENCRYPTRIJNDAEL','ICRYPTO_ENCRYPTRC4','ICRYPTO_DECRYPTRIJNDAEL','ICRYPTO_DECRYPTRC4',
+            'ICRYPTO_CRC32','ICRYPTO_CRC16','ICRYPTO_BYTEXOR','ICRYPTO_BIN2ASCII','ICRYPTO_ASCII2STRING','ICRYPTO_ASCII2BIN','HOST_ADDR','HOSTNAME_TOIP',
+            'HOSTIP_TONAME','HIWRD','HIINT','HEX$','HASH','HANDLE','GUIDTXT$','GUID$',
+            'GRAPHIC','GLVOID','GLUSHORT','GLUINT','GLUBYTE','GLSIZEI','GLSHORT','GLOBAL',
+            'GLINT','GLFLOAT','GLENUM','GLDOUBLE','GLCLAMPF','GLCLAMPD','GLBYTE','GLBOOLEAN',
+            'GLBITFIELD','GETWINDOWMULTIKEYSTATE','GETWINDOWKEYSTATE','GETTICKCOUNT','GETS','GETMULTIASYNCKEYSTATE','GETMESSAGE','GETCURRENTINSTANCE',
+            'GETAT','GETASYNCKEYSTATE','GET','FUNCTION_NPARAMS','FUNCTION_EXISTS','FUNCTION_CPARAMS','FUNCTION','FTP_SETSTRING',
+            'FTP_SETSERVERDIR','FTP_SETNUMBER','FTP_SETMODE','FTP_SETLOGFILE','FTP_SETLOCALDIR','FTP_QUIT','FTP_PUTFILE','FTP_GETSTRING',
+            'FTP_GETSERVERDIR','FTP_GETNUMBER','FTP_GETLOCALDIR','FTP_GETLIST','FTP_GETFILE','FTP_GETERRORSTRING','FTP_GETERRORNUMBER','FTP_FINISHED',
+            'FTP_EXTRACT','FTP_DELFILE','FTP_CONNECT','FTP_COMMAND','FRAME','FRAC','FORMAT$','FOR',
+            'FONT_LIST','FONT_CREATE','FONT','FOCUS','FLUSH','FIX','FILE_SIZE','FILE_SHELLDELETE',
+            'FILE_SHELLCOPY','FILE_SETDATETIME','FILE_SEEK','FILE_SAVE','FILE_RENAME','FILE_PUT','FILE_PATHSPLIT','FILE_OPEN',
+            'FILE_LOF','FILE_LOAD','FILE_LINEPRINT','FILE_LINEINPUT','FILE_KILL','FILE_GETVERSIONSTRING','FILE_GETVERSION','FILE_GETTIME',
+            'FILE_GETDATETIMESTAMP','FILE_GETDATETIME','FILE_GETDATE','FILE_GET','FILE_EXISTS','FILE_EOF','FILE_COPY','FILE_CLOSE',
+            'FILE_CHANGED','FILE_APPEND','FACTORIAL','EXTRACT$','EXT','EXPORT','EXP2','EXP10',
+            'EXP','EXIT','EVAL_STRING','EVAL_SETSTRING','EVAL_SETNUMBER','EVAL_MATH','EVAL_LINKEXT','EVAL_GETSTRING',
+            'EVAL_GETNUMBER','EVAL_ERRORGETTOKEN','EVAL_ERRORDESCRIPTION','EVAL_ERRORCLEAR','EVAL','ERRCLEAR','ERR','ENGINE_GETCURRENTTOKEN',
+            'ENDIF','END','ENABLE','ELSEIF','ELSE','ECHO','DWORD','DT_YEAR',
+            'DT_TIMETOSEC','DT_TIMESUBSECONDS','DT_TIMEFORMAT','DT_TIMEADDSECONDS','DT_SETTIMESEPARATOR','DT_SETDATESEPARATOR','DT_SETDATECENTURY','DT_SECTOTIME',
+            'DT_SECTODATE','DT_SECOND','DT_MONTH','DT_MINUTE','DT_LASTDAYOFMONTH','DT_ISVALIDDATE','DT_ISLEAPYEAR','DT_HOUR',
+            'DT_GETWEEKDAYNAME','DT_GETWEEKDAY','DT_GETTIMESTAMP','DT_GETTIMESEPARATOR','DT_GETMONTHNAME','DT_GETDATESEPARATOR','DT_GETDATECENTURY','DT_DAY',
+            'DT_DATETOSEC','DT_DATETIMESUBSECONDS','DT_DATETIMEADDSECONDS','DT_DATESUBDAYS','DT_DATEFORMAT','DT_DATEDIFF','DT_DATEADDDAYS','DT_COOKIEDATE',
+            'DRAW','DOUBLE','DOEVENTS','DO','DISABLE','DIR_REMOVE','DIR_MAKEALL','DIR_MAKE',
+            'DIR_LISTARRAY','DIR_LIST','DIR_ISEMPTY','DIR_ISDIR','DIR_GETCURRENT','DIR_EXISTS','DIR_CHANGEDRIVE','DIR_CHANGE',
+            'DIM','DICTIONARY_MEMINFO','DICTIONARY_LISTKEYS','DICTIONARY_FREE','DICTIONARY_FIND','DICTIONARY_EXISTS','DICTIONARY_CREATE','DICTIONARY_COUNT',
+            'DICTIONARY_ADD','DIALOG_STOPEVENTS','DIALOG_SAVEFILE','DIALOG_OPENFILE','DIALOG_GETCONTROL','DIALOG_CHOOSECOLOR','DIALOG_BROWSEFORFOLDER','DIALOG',
+            'DESKTOP','DESCENDING','DESCEND','DELETEOBJECT','DELETE','DEGTORAD','DECR','DECLARE',
+            'DATE$','CVWRD','CVS','CVQ','CVL','CVI','CVE','CVDWD',
+            'CVD','CVCUX','CVCUR','CVBYT','CURRENCY','CUR','CSET$','CSCH',
+            'CSC','CRYPTO_GETPROVIDERTYPESCOUNT','CRYPTO_GETPROVIDERSCOUNT','CRYPTO_GETDEFAULTPROVIDER','CRYPTO_GENRANDOMSTRING','CRYPTO_ENUMPROVIDERTYPES','CRYPTO_ENUMPROVIDERS','CRYPTO_ENCRYPT',
+            'CRYPTO_DECRYPT','CREATEFONT','COTH','COTAN','COSH','COS','CONTROL_SETTEXT','CONTROL_GETTEXT',
+            'CONTROL_GETNUMBER','CONTROL','CONST','CONSOLE_WRITELINE','CONSOLE_WRITE','CONSOLE_WAITKEY','CONSOLE_SHOWWINDOW','CONSOLE_SHOWCURSOR',
+            'CONSOLE_SETTITLE','CONSOLE_SETTEXTATTRIBUTE','CONSOLE_SETSTDHANDLE','CONSOLE_SETSCREENBUFFERSIZE','CONSOLE_SETPROGRESSBARCHAR','CONSOLE_SETOUTPUTMODE','CONSOLE_SETOUTPUTCP','CONSOLE_SETINPUTMODE',
+            'CONSOLE_SETFILEAPISTOOEM','CONSOLE_SETFILEAPISTOANSI','CONSOLE_SETCURSORSIZE','CONSOLE_SETCURSORPOSITION','CONSOLE_SETCP','CONSOLE_SETACTIVESCREENBUFFER','CONSOLE_SCROLLWINDOW','CONSOLE_SCROLLBUFFERONEROW',
+            'CONSOLE_SCROLLBUFFER','CONSOLE_SAVESCREEN','CONSOLE_RESTORESCREEN','CONSOLE_READLINE','CONSOLE_READ','CONSOLE_PROGRESSBAR','CONSOLE_PRINTLINE','CONSOLE_PRINTAT',
+            'CONSOLE_PRINT','CONSOLE_NORMALSCREEN','CONSOLE_LINE','CONSOLE_INKEYB','CONSOLE_INKEY','CONSOLE_HIDECURSOR','CONSOLE_GETTITLE','CONSOLE_GETTEXTATTRIBUTE',
+            'CONSOLE_GETSTDHANDLE','CONSOLE_GETSIZEY','CONSOLE_GETSIZEX','CONSOLE_GETPROGRESSBARCHAR','CONSOLE_GETOUTPUTMODE','CONSOLE_GETOUTPUTCP','CONSOLE_GETNUMBEROFMOUSEBUTTONS','CONSOLE_GETINPUTMODE',
+            'CONSOLE_GETCURSORY','CONSOLE_GETCURSORX','CONSOLE_GETCURSORSIZE','CONSOLE_GETCURRENTFONTINDEX','CONSOLE_GETCP','CONSOLE_GENERATECTRLEVENT','CONSOLE_FULLSCREEN','CONSOLE_FREE',
+            'CONSOLE_FOREGROUNDRGB','CONSOLE_ENABLECTRLC','CONSOLE_DISABLECTRLC','CONSOLE_CREATESCREENBUFFER','CONSOLE_COLORAT','CONSOLE_CLS','CONSOLE_BOX','CONSOLE_BACKGROUNDRGB',
+            'CONSOLE_ATTACH','CONSOLE_AREFILEAPISANSI','CONSOLE_ALLOC','COM_VARIANTINIT','COM_VARIANTCOPY','COM_VARIANTCLEAR','COM_SUCCEEDED','COM_STRINGFROMCLSID',
+            'COM_RELEASE','COM_QUERYINTERFACE','COM_PROGIDFROMCLSID','COM_ISEQUALIID','COM_ISEQUALGUID','COM_ISEQUALCLSID','COM_GETOBJECT','COM_GETENGINEGUID',
+            'COM_EXECUTE','COM_DISPLAYERROR','COM_CREATEOBJECT','COM_CLSIDFROMSTRING','COM_CLSIDFROMPROGID','COM_BUILDVARIANT','COMBOBOX','COMBINATIONS',
+            'COLOR','CLIPBOARD_SETTEXT','CLIPBOARD_GETTEXT','CLIENT','CLEARMESSAGES','CHR$','CHOOSE$','CHOOSE',
+            'CHECKBOX','CHECK3STATE','CHECK','CGI_WRITELOGFILE','CGI_WRITE','CGI_URLDECODESTRING','CGI_UPLOADFILESTIME','CGI_UPLOADFILESNUMBER',
+            'CGI_UPLOADFILESIZE','CGI_STARTSESSION','CGI_SETSESSIONVARIABLE','CGI_RESETDEFAULTSETTINGS','CGI_REMOVESPECIALCHARSPREFIX','CGI_REMOVEQUOTE','CGI_READ','CGI_LOADCONFIGFILE',
+            'CGI_HEADER','CGI_GETSESSIONVARIABLE','CGI_GETREQUESTMETHOD','CGI_GETQUERYVALUE','CGI_GETCURRENTSESSION','CGI_GETCURRENTGUID','CGI_ENVIRON','CGI_CFGSETOPTION',
+            'CGI_CFGGETOPTION','CGI_ADDSPECIALCHARSPREFIX','CGI_ADDQUOTE','CEIL','CASE','CALL','BYVAL','BYTE',
+            'BYREF','BYCMD','BUTTON','BUNDLE_SETSCRIPTPARAMETERS','BUNDLE_SETSCRIPTNAME','BUNDLE_SETFLAGOBFUSCATEMAINSCRIPT','BUNDLE_SETFLAGDELETEAFTERRUN','BUNDLE_SETFLAGCOMPRESSALLFILES',
+            'BUNDLE_SETFLAGASKBEFOREEXTRACT','BUNDLE_SETEXTRACTIONFOLDER','BUNDLE_SETCREATIONFOLDER','BUNDLE_SETBUNDLENAME','BUNDLE_RESET','BUNDLE_MAKE','BUNDLE_BUILDER','BUNDLE_ADDFOLDER',
+            'BUNDLE_ADDFILE','BOUNDCHECK','BIN$','BIFF_WRITETEXT','BIFF_WRITENUMBER','BIFF_WRITEDATE','BIFF_SETROWHEIGHT','BIFF_SETCOLWIDTH',
+            'BIFF_SETBUFFER','BIFF_CREATEFILE','BIFF_CLOSEFILE','BETWEEN','BEEP','BAR','ATTACH','ATN',
+            'AT','ASSIGN','ASCIZ','ASCIIZ','ASCII2UNICODE','ASCENDING','ASCEND','ASC',
+            'AS','ARRAY','ARCTANH','ARCSINH','ARCSIN','ARCSECH','ARCSEC','ARCCSCH',
+            'ARCCSC','ARCCOTH','ARCCOT','ARCCOSH','ARCCOS','APP_TIMER','APP_SOURCEPATH','APP_SOURCENAME',
+            'APP_SOURCEFULLNAME','APP_PATH','APP_NAME','APP_LISTVARIABLES','APP_LISTKEYWORDS','APP_LISTFUNCTIONS','APP_LISTEQUATES','APP_INCLUDEPATH',
+            'APP_GETMODULEFULLPATH','APP_COUNTER','APPEND','ANY','ANIMATE_STOP','ANIMATE_PLAY','ANIMATE_OPEN','AND',
+            'ALIAS','ALERT','ADD','ACODE$','ABS','%DEF','#MINVERSION','#IF',
+            '#ENDIF','#ELSEIF','#ELSE','#DEFAULT','#DEF','SQLWRITEPRIVATEPROFILESTRING','SQLWRITEFILEDSN','SQLWRITEDSNTOINI',
+            'SQLVALIDDSN','SQLTRANSACT','SQLTABLES','SQLTABLEPRIVILEGES','SQLSTATISTICS','SQLSPECIALCOLUMNS','SQLSETSTMTOPTION','SQLSETSTMTATTR',
+            'SQLSETSCROLLOPTIONS','SQLSETPOS','SQLSETPARAM','SQLSETENVATTR','SQLSETDESCREC','SQLSETDESCFIELD','SQLSETCURSORNAME','SQLSETCONNECTOPTION',
+            'SQLSETCONNECTATTR','SQLSETCONFIGMODE','SQLROWCOUNT','SQLREMOVETRANSLATOR','SQLREMOVEDSNFROMINI','SQLREMOVEDRIVERMANAGER','SQLREMOVEDRIVER','SQLREADFILEDSN',
+            'SQLPUTDATA','SQLPROCEDURES','SQLPROCEDURECOLUMNS','SQLPRIMARYKEYS','SQLPREPARE','SQLPOSTINSTALLERERROR','SQLPARAMOPTIONS','SQLPARAMDATA',
+            'SQLNUMRESULTCOLS','SQLNUMPARAMS','SQLNATIVESQL','SQLMORERESULTS','SQLMANAGEDATASOURCES','SQLINSTALLTRANSLATOREX','SQLINSTALLERERROR','SQLINSTALLDRIVERMANAGER',
+            'SQLINSTALLDRIVEREX','SQLGETTYPEINFO','SQLGETTRANSLATOR','SQLGETSTMTOPTION','SQLGETSTMTATTR','SQLGETPRIVATEPROFILESTRING','SQLGETINSTALLEDDRIVERS','SQLGETINFO',
+            'SQLGETFUNCTIONS','SQLGETENVATTR','SQLGETDIAGREC','SQLGETDIAGFIELD','SQLGETDESCREC','SQLGETDESCFIELD','SQLGETDATA','SQLGETCURSORNAME',
+            'SQLGETCONNECTOPTION','SQLGETCONNECTATTR','SQLGETCONFIGMODE','SQLFREESTMT','SQLFREEHANDLE','SQLFREEENV','SQLFREECONNECT','SQLFOREIGNKEYS',
+            'SQLFETCHSCROLL','SQLFETCH','SQLEXTENDEDFETCH','SQLEXECUTE','SQLEXECDIRECT','SQLERROR','SQLENDTRAN','SQLDRIVERS',
+            'SQLDRIVERCONNECT','SQLDISCONNECT','SQLDESCRIBEPARAM','SQLDESCRIBECOL','SQLDATASOURCES','SQLCREATEDATASOURCE','SQLCOPYDESC','SQLCONNECT',
+            'SQLCONFIGDRIVER','SQLCONFIGDATASOURCE','SQLCOLUMNS','SQLCOLUMNPRIVILEGES','SQLCOLATTRIBUTES','SQLCOLATTRIBUTE','SQLCLOSECURSOR','SQLCANCEL',
+            'SQLBULKOPERATIONS','SQLBROWSECONNECT','SQLBINDPARAMETER','SQLBINDPARAM','SQLBINDCOL','SQLALLOCSTMT','SQLALLOCHANDLE','SQLALLOCENV',
+            'SQLALLOCCONNECT','ODBCWRONGDRIVER','ODBCWRITEPRIVATEPROFILESTRING','ODBCWRITEFILEDSN','ODBCWRITEDSNTOINI','ODBCVALIDDSN','ODBCUPDATERECORD','ODBCUPDATEBYBOOKMARK',
+            'ODBCUNLOCKRECORD','ODBCUNBINDCOLUMNS','ODBCUNBINDCOL','ODBCTABLESCOUNT','ODBCTABLES','ODBCTABLEPRIVILEGESCOUNT','ODBCTABLEPRIVILEGES','ODBCSUPPORTS',
+            'ODBCSTATTABLESCHEMANAME','ODBCSTATTABLEPAGES','ODBCSTATTABLECATALOGNAME','ODBCSTATTABLECARDINALITY','ODBCSTATISTICSCOUNT','ODBCSTATISTICS','ODBCSTATINDEXSORTSEQUENCE','ODBCSTATINDEXSCHEMANAME',
+            'ODBCSTATINDEXQUALIFIER','ODBCSTATINDEXPAGES','ODBCSTATINDEXFILTERCONDITION','ODBCSTATINDEXCOLUMNORDINALPOSITION','ODBCSTATINDEXCOLUMNNAME','ODBCSTATINDEXCATALOGNAME','ODBCSTATINDEXCARDINALITY','ODBCSTATINDEXALLOWDUPLICATES',
+            'ODBCSPECIALCOLUMNSCOUNT','ODBCSPECIALCOLUMNS','ODBCSETTXNISOLATION','ODBCSETTRANSLATELIB','ODBCSETTRACEFILE','ODBCSETTRACE','ODBCSETSTMTUSEBOOKMARKS','ODBCSETSTMTSIMULATECURSOR',
+            'ODBCSETSTMTROWSTATUSPTR','ODBCSETSTMTROWSFETCHEDPTR','ODBCSETSTMTROWOPERATIONPTR','ODBCSETSTMTROWBINDTYPE','ODBCSETSTMTROWBINDOFFSETPTR','ODBCSETSTMTROWARRAYSIZE','ODBCSETSTMTRETRIEVEDATA','ODBCSETSTMTQUERYTIMEOUT',
+            'ODBCSETSTMTPARAMSTATUSPTR','ODBCSETSTMTPARAMSPROCESSEDPTR','ODBCSETSTMTPARAMSETSIZE','ODBCSETSTMTPARAMOPERATIONPTR','ODBCSETSTMTPARAMBINDTYPE','ODBCSETSTMTPARAMBINDOFFSETPTR','ODBCSETSTMTNOSCAN','ODBCSETSTMTMETADATAID',
+            'ODBCSETSTMTMAXROWS','ODBCSETSTMTMAXLENGTH','ODBCSETSTMTKEYSETSIZE','ODBCSETSTMTFETCHBOOKMARKPTR','ODBCSETSTMTENABLEAUTOIPD','ODBCSETSTMTCURSORTYPE','ODBCSETSTMTCURSORSENSITIVITY','ODBCSETSTMTCURSORSCROLLABLE',
+            'ODBCSETSTMTCONCURRENCY','ODBCSETSTMTATTR','ODBCSETSTMTASYNCENABLE','ODBCSETSTMTAPPROWDESC','ODBCSETSTMTAPPPARAMDESC','ODBCSETSTATICCURSOR','ODBCSETROWVERCONCURRENCY','ODBCSETRESULT',
+            'ODBCSETRELATIVEPOSITION','ODBCSETREADONLYCONCURRENCY','ODBCSETQUIETMODE','ODBCSETPOSITION','ODBCSETPOS','ODBCSETPACKETMODE','ODBCSETOPTIMISTICCONCURRENCY','ODBCSETODBCCURSORS',
+            'ODBCSETMULTIUSERKEYSETCURSOR','ODBCSETMETADATAID','ODBCSETLOGINTIMEOUT','ODBCSETLOCKCONCURRENCY','ODBCSETKEYSETDRIVENCURSOR','ODBCSETFORWARDONLYCURSOR','ODBCSETENVOUTPUTNTS','ODBCSETENVODBCVERSION',
+            'ODBCSETENVCPMATCH','ODBCSETENVCONNECTIONPOOLING','ODBCSETENVATTR','ODBCSETDYNAMICCURSOR','ODBCSETDESCREC','ODBCSETDESCFIELD','ODBCSETCURSORTYPE','ODBCSETCURSORSENSITIVITY',
+            'ODBCSETCURSORSCROLLABILITY','ODBCSETCURSORNAME','ODBCSETCURSORLOCKTYPE','ODBCSETCURSORKEYSETSIZE','ODBCSETCURSORCONCURRENCY','ODBCSETCURRENTCATALOG','ODBCSETCONNECTIONTIMEOUT','ODBCSETCONNECTATTR',
+            'ODBCSETCONFIGMODE','ODBCSETCONCURVALUESCONCURRENCY','ODBCSETAUTOCOMMITON','ODBCSETAUTOCOMMITOFF','ODBCSETAUTOCOMMIT','ODBCSETASYNCENABLE','ODBCSETACCESSMODE','ODBCSETABSOLUTEPOSITION',
+            'ODBCROWCOUNT','ODBCROLLBACKTRAN','ODBCROLLBACKENVTRAN','ODBCROLLBACKDBCTRAN','ODBCRESULT','ODBCRESETPARAMS','ODBCREMOVETRANSLATOR','ODBCREMOVEDSNFROMINI',
+            'ODBCREMOVEDRIVERMANAGER','ODBCREMOVEDRIVER','ODBCREFRESHRECORD','ODBCRECORDCOUNT','ODBCREADFILEDSN','ODBCQUOTEDIDENTIFIERCASE','ODBCPUTDATA','ODBCPROCEDURESCOUNT',
+            'ODBCPROCEDURES','ODBCPROCEDURECOLUMNSCOUNT','ODBCPROCEDURECOLUMNS','ODBCPRIMARYKEYSCOUNT','ODBCPRIMARYKEYS','ODBCPREPARE','ODBCPOSTINSTALLERERROR','ODBCPARAMDATA',
+            'ODBCOPENSTMT','ODBCOPENCONNECTION','ODBCNUMRESULTCOLS','ODBCNUMPARAMS','ODBCNATIVESQL','ODBCMOVEPREVIOUS','ODBCMOVENEXT','ODBCMOVELAST',
+            'ODBCMOVEFIRST','ODBCMOVE','ODBCMORERESULTS','ODBCMANAGEDATASOURCES','ODBCLOCKRECORD','ODBCINSTALLTRANSLATOREX','ODBCINSTALLERERROR','ODBCINSTALLDRIVERMANAGER',
+            'ODBCINSTALLDRIVEREX','ODBCGETXOPENCLIYEAR','ODBCGETUSERNAME','ODBCGETUNION','ODBCGETTYPEINFOCOUNT','ODBCGETTYPEINFO','ODBCGETTXNISOLATIONOPTION','ODBCGETTXNISOLATION',
+            'ODBCGETTXNCAPABLE','ODBCGETTRANSLATOR','ODBCGETTRANSLATELIB','ODBCGETTRACEFILE','ODBCGETTRACE','ODBCGETTIMEDATEFUNCTIONS','ODBCGETTIMEDATEDIFFINTERVALS','ODBCGETTIMEDATEADDINTERVALS',
+            'ODBCGETTABLETERM','ODBCGETSYSTEMFUNCTIONS','ODBCGETSUBQUERIES','ODBCGETSTRINGFUNCTIONS','ODBCGETSTMTUSEBOOKMARKS','ODBCGETSTMTSQLSTATE','ODBCGETSTMTSIMULATECURSOR','ODBCGETSTMTROWSTATUSPTR',
+            'ODBCGETSTMTROWSFETCHEDPTR','ODBCGETSTMTROWOPERATIONPTR','ODBCGETSTMTROWNUMBER','ODBCGETSTMTROWBINDTYPE','ODBCGETSTMTROWBINDOFFSETPTR','ODBCGETSTMTROWARRAYSIZE','ODBCGETSTMTRETRIEVEDATA','ODBCGETSTMTQUERYTIMEOUT',
+            'ODBCGETSTMTPARAMSTATUSPTR','ODBCGETSTMTPARAMSPROCESSEDPTR','ODBCGETSTMTPARAMSETSIZE','ODBCGETSTMTPARAMOPERATIONPTR','ODBCGETSTMTPARAMBINDTYPE','ODBCGETSTMTPARAMBINDOFFSETPTR','ODBCGETSTMTNOSCAN','ODBCGETSTMTMETADATAID',
+            'ODBCGETSTMTMAXROWS','ODBCGETSTMTMAXLENGTH','ODBCGETSTMTKEYSETSIZE','ODBCGETSTMTIMPROWDESC','ODBCGETSTMTIMPPARAMDESC','ODBCGETSTMTFETCHBOOKMARKPTR','ODBCGETSTMTERRORINFO','ODBCGETSTMTENABLEAUTOIPD',
+            'ODBCGETSTMTCURSORTYPE','ODBCGETSTMTCURSORSENSITIVITY','ODBCGETSTMTCURSORSCROLLABLE','ODBCGETSTMTCONCURRENCY','ODBCGETSTMTATTR','ODBCGETSTMTASYNCENABLE','ODBCGETSTMTAPPROWDESC','ODBCGETSTMTAPPPARAMDESC',
+            'ODBCGETSTATICCURSORATTRIBUTES2','ODBCGETSTATICCURSORATTRIBUTES1','ODBCGETSTATEMENTSQLSTATE','ODBCGETSTATEMENTERRORINFO','ODBCGETSTANDARDCLICONFORMANCE','ODBCGETSQLSTATE','ODBCGETSQLCONFORMANCE','ODBCGETSQL92VALUEEXPRESSIONS',
+            'ODBCGETSQL92STRINGFUNCTIONS','ODBCGETSQL92ROWVALUECONSTRUCTOR','ODBCGETSQL92REVOKE','ODBCGETSQL92RELATIONALJOINOPERATORS','ODBCGETSQL92PREDICATES','ODBCGETSQL92NUMERICVALUEFUNCTIONS','ODBCGETSQL92GRANT','ODBCGETSQL92FOREIGNKEYUPDATERULE',
+            'ODBCGETSQL92FOREIGNKEYDELETERULE','ODBCGETSQL92DATETIMEFUNCTIONS','ODBCGETSPECIALCHARACTERS','ODBCGETSERVERNAME','ODBCGETSEARCHPATTERNESCAPE','ODBCGETSCROLLOPTIONS','ODBCGETSCHEMAUSAGE','ODBCGETSCHEMATERM',
+            'ODBCGETROWUPDATES','ODBCGETQUIETMODE','ODBCGETPROCEDURETERM','ODBCGETPROCEDURESSUPPORT','ODBCGETPRIVATEPROFILESTRING','ODBCGETPOSOPERATIONS','ODBCGETPARAMARRAYSELECTS','ODBCGETPARAMARRAYROWCOUNTS',
+            'ODBCGETPACKETMODE','ODBCGETOUTERJOINS','ODBCGETORDERBYCOLUMNSINSELECT','ODBCGETOJCAPABILITIES','ODBCGETODBCVER','ODBCGETODBCINTERFACECONFORMANCE','ODBCGETODBCCURSORS','ODBCGETNUMERICFUNCTIONS',
+            'ODBCGETNULLCOLLATION','ODBCGETNONNULLABLECOLUMNS','ODBCGETNEEDLONGDATALEN','ODBCGETMULTRESULTSETS','ODBCGETMULTIPLEACTIVETXN','ODBCGETMETADATAID','ODBCGETMAXUSERNAMELEN','ODBCGETMAXTABLESINSELECT',
+            'ODBCGETMAXTABLENAMELEN','ODBCGETMAXSTATEMENTLEN','ODBCGETMAXSCHEMANAMELEN','ODBCGETMAXROWSIZEINCLUDESLONG','ODBCGETMAXROWSIZE','ODBCGETMAXPROCEDURENAMELEN','ODBCGETMAXINDEXSIZE','ODBCGETMAXIDENTIFIERLEN',
+            'ODBCGETMAXDRIVERCONNECTIONS','ODBCGETMAXCURSORNAMELEN','ODBCGETMAXCONCURRENTACTIVITIES','ODBCGETMAXCOLUMNSINTABLE','ODBCGETMAXCOLUMNSINSELECT','ODBCGETMAXCOLUMNSINORDERBY','ODBCGETMAXCOLUMNSININDEX','ODBCGETMAXCOLUMNSINGROUPBY',
+            'ODBCGETMAXCOLUMNNAMELEN','ODBCGETMAXCHARLITERALLEN','ODBCGETMAXCATALOGNAMELEN','ODBCGETMAXBINARYLITERALLEN','ODBCGETMAXASYNCCONCURRENTSTATEMENTS','ODBCGETLONGVARCHARDATABYCOLNAME','ODBCGETLONGVARCHARDATA','ODBCGETLOGINTIMEOUT',
+            'ODBCGETLIKEESCAPECLAUSE','ODBCGETKEYWORDS','ODBCGETKEYSETCURSORATTRIBUTES2','ODBCGETKEYSETCURSORATTRIBUTES1','ODBCGETINTEGRITY','ODBCGETINSTALLERERRORMESSAGE','ODBCGETINSTALLERERRORCODE','ODBCGETINSTALLEDDRIVERS',
+            'ODBCGETINSERTSTATEMENT','ODBCGETINFOSTR','ODBCGETINFOSCHEMAVIEWS','ODBCGETINFOLONG','ODBCGETINFOINT','ODBCGETINFO','ODBCGETINDEXKEYWORDS','ODBCGETIMPROWDESCREC',
+            'ODBCGETIMPROWDESCFIELDTYPE','ODBCGETIMPROWDESCFIELDSCALE','ODBCGETIMPROWDESCFIELDPRECISION','ODBCGETIMPROWDESCFIELDOCTETLENGTH','ODBCGETIMPROWDESCFIELDNULLABLE','ODBCGETIMPROWDESCFIELDNAME','ODBCGETIMPROWDESCFIELD','ODBCGETIMPPARAMDESCREC',
+            'ODBCGETIMPPARAMDESCFIELDTYPE','ODBCGETIMPPARAMDESCFIELDSCALE','ODBCGETIMPPARAMDESCFIELDPRECISION','ODBCGETIMPPARAMDESCFIELDOCTETLENGTH','ODBCGETIMPPARAMDESCFIELDNULLABLE','ODBCGETIMPPARAMDESCFIELDNAME','ODBCGETIMPPARAMDESCFIELD','ODBCGETIDENTIFIERQUOTECHAR',
+            'ODBCGETIDENTIFIERCASE','ODBCGETGROUPBY','ODBCGETFUNCTIONS','ODBCGETFORWARDONLYCURSORATTRIBUTES2','ODBCGETFORWARDONLYCURSORATTRIBUTES1','ODBCGETFILEUSAGE','ODBCGETEXPRESSIONSINORDERBY','ODBCGETERRORINFO',
+            'ODBCGETENVSQLSTATE','ODBCGETENVOUTPUTNTS','ODBCGETENVODBCVERSION','ODBCGETENVIRONMENTSQLSTATE','ODBCGETENVIRONMENTERRORINFO','ODBCGETENVERRORINFO','ODBCGETENVCPMATCH','ODBCGETENVCONNECTIONPOOLING',
+            'ODBCGETENVATTR','ODBCGETDYNAMICCURSORATTRIBUTES2','ODBCGETDYNAMICCURSORATTRIBUTES1','ODBCGETDROPVIEW','ODBCGETDROPTRANSLATION','ODBCGETDROPTABLE','ODBCGETDROPSCHEMA','ODBCGETDROPDOMAIN',
+            'ODBCGETDROPCOLLATION','ODBCGETDROPCHARACTERSET','ODBCGETDROPASSERTION','ODBCGETDRIVERVER','ODBCGETDRIVERODBCVER','ODBCGETDRIVERNAME','ODBCGETDRIVERMANAGERINSTALLPATH','ODBCGETDRIVERHLIB',
+            'ODBCGETDRIVERHENV','ODBCGETDRIVERHDBC','ODBCGETDMVERMINOR','ODBCGETDMVERMAJOR','ODBCGETDMVER','ODBCGETDIAGREC','ODBCGETDIAGFIELD','ODBCGETDESCSQLSTATE',
+            'ODBCGETDESCRIPTORSQLSTATE','ODBCGETDESCRIPTORERRORINFO','ODBCGETDESCRIBEPARAMETER','ODBCGETDESCREC','ODBCGETDESCFIELD','ODBCGETDESCERRORINFO','ODBCGETDEFAULTTXNISOLATION','ODBCGETDDLINDEX',
+            'ODBCGETDBMSVER','ODBCGETDBMSNAME','ODBCGETDBCSQLSTATE','ODBCGETDBCERRORINFO','ODBCGETDATETIMELITERALS','ODBCGETDATASTRINGBYCOLNAME','ODBCGETDATASTRING','ODBCGETDATASOURCEREADONLY',
+            'ODBCGETDATASOURCENAME','ODBCGETDATAEXTENSIONS','ODBCGETDATABASENAME','ODBCGETDATA','ODBCGETCURSORTYPE','ODBCGETCURSORSENSITIVITYSUPPORT','ODBCGETCURSORSENSITIVITY','ODBCGETCURSORSCROLLABILITY',
+            'ODBCGETCURSORROLLBACKBEHAVIOR','ODBCGETCURSORNAME','ODBCGETCURSORLOCKTYPE','ODBCGETCURSORKEYSETSIZE','ODBCGETCURSORCONCURRENCY','ODBCGETCURSORCOMMITBEHAVIOR','ODBCGETCURRENTCATALOG','ODBCGETCREATEVIEW',
+            'ODBCGETCREATETRANSLATION','ODBCGETCREATETABLE','ODBCGETCREATESCHEMA','ODBCGETCREATEDOMAIN','ODBCGETCREATECOLLATION','ODBCGETCREATECHARACTERSET','ODBCGETCREATEASSERTION','ODBCGETCORRELATIONNAME',
+            'ODBCGETCONVERTVARCHAR','ODBCGETCONVERTVARBINARY','ODBCGETCONVERTTINYINT','ODBCGETCONVERTTIMESTAMP','ODBCGETCONVERTTIME','ODBCGETCONVERTSMALLINT','ODBCGETCONVERTREAL','ODBCGETCONVERTNUMERIC',
+            'ODBCGETCONVERTLONGVARCHAR','ODBCGETCONVERTLONGVARBINARY','ODBCGETCONVERTINTERVALYEARMONTH','ODBCGETCONVERTINTERVALDAYTIME','ODBCGETCONVERTINTEGER','ODBCGETCONVERTFUNCTIONS','ODBCGETCONVERTFLOAT','ODBCGETCONVERTDOUBLE',
+            'ODBCGETCONVERTDECIMAL','ODBCGETCONVERTDATE','ODBCGETCONVERTCHAR','ODBCGETCONVERTBIT','ODBCGETCONVERTBINARY','ODBCGETCONVERTBIGINT','ODBCGETCONNECTIONTIMEOUT','ODBCGETCONNECTIONSQLSTATE',
+            'ODBCGETCONNECTIONERRORINFO','ODBCGETCONNECTIONDEAD','ODBCGETCONNECTATTR','ODBCGETCONFIGMODE','ODBCGETCONCATNULLBEHAVIOR','ODBCGETCOLUMNALIAS','ODBCGETCOLLATIONSEQ','ODBCGETCATALOGUSAGE',
+            'ODBCGETCATALOGTERM','ODBCGETCATALOGNAMESEPARATOR','ODBCGETCATALOGNAME','ODBCGETCATALOGLOCATION','ODBCGETBOOKMARKPERSISTENCE','ODBCGETBATCHSUPPORT','ODBCGETBATCHROWCOUNT','ODBCGETAUTOIPD',
+            'ODBCGETAUTOCOMMIT','ODBCGETASYNCMODE','ODBCGETASYNCENABLE','ODBCGETALTERTABLE','ODBCGETALTERDOMAIN','ODBCGETAGGREGATEFUNCTIONS','ODBCGETACTIVEENVIRONMENTS','ODBCGETACCESSMODE',
+            'ODBCGETACCESSIBLETABLES','ODBCGETACCESSIBLEPROCEDURES','ODBCFREESTMT','ODBCFREEHANDLE','ODBCFREEENV','ODBCFREEDESC','ODBCFREEDBC','ODBCFREECONNECT',
+            'ODBCFOREIGNKEYSCOUNT','ODBCFOREIGNKEYS','ODBCFETCHSCROLL','ODBCFETCHBYBOOKMARK','ODBCFETCH','ODBCEXTENDEDFETCH','ODBCEXECUTE','ODBCEXECDIRECT',
+            'ODBCERROR','ODBCEOF','ODBCENDTRAN','ODBCDRIVERSCOUNT','ODBCDRIVERS','ODBCDRIVERCONNECT','ODBCDISCONNECT','ODBCDESCRIBEPARAM',
+            'ODBCDESCRIBECOL','ODBCDELETERECORD','ODBCDELETEBYBOOKMARK','ODBCDATASOURCES','ODBCCREATEDATASOURCE','ODBCCOPYDESC','ODBCCONNECTIONISDEAD','ODBCCONNECTIONISALIVE',
+            'ODBCCONNECT','ODBCCONFIGDRIVER','ODBCCONFIGDATASOURCE','ODBCCOMMITTRAN','ODBCCOMMITENVTRAN','ODBCCOMMITDBCTRAN','ODBCCOLUPDATABLE','ODBCCOLUNSIGNED',
+            'ODBCCOLUNNAMED','ODBCCOLUMNSCOUNT','ODBCCOLUMNS','ODBCCOLUMNPRIVILEGESCOUNT','ODBCCOLUMNPRIVILEGES','ODBCCOLUMN','ODBCCOLTYPENAME','ODBCCOLTYPE',
+            'ODBCCOLTABLENAME','ODBCCOLSEARCHABLE','ODBCCOLSCHEMANAME','ODBCCOLSCALE','ODBCCOLPRECISION','ODBCCOLOCTETLENGTH','ODBCCOLNUMPRECRADIX','ODBCCOLNULLABLE',
+            'ODBCCOLNAME','ODBCCOLLOCALTYPENAME','ODBCCOLLITERALSUFFIX','ODBCCOLLITERALPREFIX','ODBCCOLLENGTH','ODBCCOLLABEL','ODBCCOLISNULL','ODBCCOLFIXEDPRECSCALE',
+            'ODBCCOLDISPLAYSIZE','ODBCCOLCOUNT','ODBCCOLCONCISETYPE','ODBCCOLCATALOGNAME','ODBCCOLCASESENSITIVE','ODBCCOLBASETABLENAME','ODBCCOLBASECOLUMNNAME','ODBCCOLAUTOUNIQUEVALUE',
+            'ODBCCOLATTRIBUTE','ODBCCLOSESTMTCURSOR','ODBCCLOSESTMT','ODBCCLOSECURSOR','ODBCCLOSECONNECTION','ODBCCLEARRESULT','ODBCCANCEL','ODBCBULKOPERATIONS',
+            'ODBCBROWSECONNECT','ODBCBINDPARAMETER','ODBCBINDCOLTOWORD','ODBCBINDCOLTOTIMESTAMP','ODBCBINDCOLTOTIME','ODBCBINDCOLTOSTRING','ODBCBINDCOLTOSINGLE','ODBCBINDCOLTOQUAD',
+            'ODBCBINDCOLTONUMERIC','ODBCBINDCOLTOLONG','ODBCBINDCOLTOINTEGER','ODBCBINDCOLTODWORD','ODBCBINDCOLTODOUBLE','ODBCBINDCOLTODECIMAL','ODBCBINDCOLTODATE','ODBCBINDCOLTOCURRENCY',
+            'ODBCBINDCOLTOBYTE','ODBCBINDCOLTOBIT','ODBCBINDCOLTOBINARY','ODBCBINDCOL','ODBCALLOCSTMT','ODBCALLOCHANDLE','ODBCALLOCENV','ODBCALLOCDESC',
+            'ODBCALLOCDBC','ODBCALLOCCONNECT','ODBCADDRECORD','GLVIEWPORT','GLVERTEXPOINTER','GLVERTEX4SV','GLVERTEX4S','GLVERTEX4IV',
+            'GLVERTEX4I','GLVERTEX4FV','GLVERTEX4F','GLVERTEX4DV','GLVERTEX4D','GLVERTEX3SV','GLVERTEX3S','GLVERTEX3IV',
+            'GLVERTEX3I','GLVERTEX3FV','GLVERTEX3F','GLVERTEX3DV','GLVERTEX3D','GLVERTEX2SV','GLVERTEX2S','GLVERTEX2IV',
+            'GLVERTEX2I','GLVERTEX2FV','GLVERTEX2F','GLVERTEX2DV','GLVERTEX2D','GLUUNPROJECT','GLUTESSVERTEX','GLUTESSPROPERTY',
+            'GLUTESSNORMAL','GLUTESSENDPOLYGON','GLUTESSENDCONTOUR','GLUTESSCALLBACK','GLUTESSBEGINPOLYGON','GLUTESSBEGINCONTOUR','GLUSPHERE','GLUSCALEIMAGE',
+            'GLUQUADRICTEXTURE','GLUQUADRICORIENTATION','GLUQUADRICNORMALS','GLUQUADRICDRAWSTYLE','GLUQUADRICCALLBACK','GLUPWLCURVE','GLUPROJECT','GLUPICKMATRIX',
+            'GLUPERSPECTIVE','GLUPARTIALDISK','GLUORTHO2D','GLUNURBSSURFACE','GLUNURBSPROPERTY','GLUNURBSCURVE','GLUNURBSCALLBACK','GLUNEXTCONTOUR',
+            'GLUNEWTESS','GLUNEWQUADRIC','GLUNEWNURBSRENDERER','GLULOOKAT','GLULOADSAMPLINGMATRICES','GLUGETTESSPROPERTY','GLUGETSTRING','GLUGETNURBSPROPERTY',
+            'GLUERRORSTRING','GLUENDTRIM','GLUENDSURFACE','GLUENDPOLYGON','GLUENDCURVE','GLUDISK','GLUDELETETESS','GLUDELETEQUADRIC',
+            'GLUDELETENURBSRENDERER','GLUCYLINDER','GLUBUILD2DMIPMAPS','GLUBUILD1DMIPMAPS','GLUBEGINTRIM','GLUBEGINSURFACE','GLUBEGINPOLYGON','GLUBEGINCURVE',
+            'GLTRANSLATEF','GLTRANSLATED','GLTEXSUBIMAGE2D','GLTEXSUBIMAGE1D','GLTEXPARAMETERIV','GLTEXPARAMETERI','GLTEXPARAMETERFV','GLTEXPARAMETERF',
+            'GLTEXIMAGE2D','GLTEXIMAGE1D','GLTEXGENIV','GLTEXGENI','GLTEXGENFV','GLTEXGENF','GLTEXGENDV','GLTEXGEND',
+            'GLTEXENVIV','GLTEXENVI','GLTEXENVFV','GLTEXENVF','GLTEXCOORDPOINTER','GLTEXCOORD4SV','GLTEXCOORD4S','GLTEXCOORD4IV',
+            'GLTEXCOORD4I','GLTEXCOORD4FV','GLTEXCOORD4F','GLTEXCOORD4DV','GLTEXCOORD4D','GLTEXCOORD3SV','GLTEXCOORD3S','GLTEXCOORD3IV',
+            'GLTEXCOORD3I','GLTEXCOORD3FV','GLTEXCOORD3F','GLTEXCOORD3DV','GLTEXCOORD3D','GLTEXCOORD2SV','GLTEXCOORD2S','GLTEXCOORD2IV',
+            'GLTEXCOORD2I','GLTEXCOORD2FV','GLTEXCOORD2F','GLTEXCOORD2DV','GLTEXCOORD2D','GLTEXCOORD1SV','GLTEXCOORD1S','GLTEXCOORD1IV',
+            'GLTEXCOORD1I','GLTEXCOORD1FV','GLTEXCOORD1F','GLTEXCOORD1DV','GLTEXCOORD1D','GLSTENCILOP','GLSTENCILMASK','GLSTENCILFUNC',
+            'GLSHADEMODEL','GLSELECTBUFFER','GLSCISSOR','GLSCALEF','GLSCALED','GLROTATEF','GLROTATED','GLRENDERMODE',
+            'GLRECTSV','GLRECTS','GLRECTIV','GLRECTI','GLRECTFV','GLRECTF','GLRECTDV','GLRECTD',
+            'GLREADPIXELS','GLREADBUFFER','GLRASTERPOS4SV','GLRASTERPOS4S','GLRASTERPOS4IV','GLRASTERPOS4I','GLRASTERPOS4FV','GLRASTERPOS4F',
+            'GLRASTERPOS4DV','GLRASTERPOS4D','GLRASTERPOS3SV','GLRASTERPOS3S','GLRASTERPOS3IV','GLRASTERPOS3I','GLRASTERPOS3FV','GLRASTERPOS3F',
+            'GLRASTERPOS3DV','GLRASTERPOS3D','GLRASTERPOS2SV','GLRASTERPOS2S','GLRASTERPOS2IV','GLRASTERPOS2I','GLRASTERPOS2FV','GLRASTERPOS2F',
+            'GLRASTERPOS2DV','GLRASTERPOS2D','GLPUSHNAME','GLPUSHMATRIX','GLPUSHCLIENTATTRIB','GLPUSHATTRIB','GLPRIORITIZETEXTURES','GLPOPNAME',
+            'GLPOPMATRIX','GLPOPCLIENTATTRIB','GLPOPATTRIB','GLPOLYGONSTIPPLE','GLPOLYGONOFFSET','GLPOLYGONMODE','GLPOINTSIZE','GLPIXELZOOM',
+            'GLPIXELTRANSFERI','GLPIXELTRANSFERF','GLPIXELSTOREI','GLPIXELSTOREF','GLPIXELMAPUSV','GLPIXELMAPUIV','GLPIXELMAPFV','GLPASSTHROUGH',
+            'GLORTHO','GLNORMALPOINTER','GLNORMAL3SV','GLNORMAL3S','GLNORMAL3IV','GLNORMAL3I','GLNORMAL3FV','GLNORMAL3F',
+            'GLNORMAL3DV','GLNORMAL3D','GLNORMAL3BV','GLNORMAL3B','GLNEWLIST','GLMULTMATRIXF','GLMULTMATRIXD','GLMATRIXMODE',
+            'GLMATERIALIV','GLMATERIALI','GLMATERIALFV','GLMATERIALF','GLMAPGRID2F','GLMAPGRID2D','GLMAPGRID1F','GLMAPGRID1D',
+            'GLMAP2F','GLMAP2D','GLMAP1F','GLMAP1D','GLLOGICOP','GLLOADNAME','GLLOADMATRIXF','GLLOADMATRIXD',
+            'GLLOADIDENTITY','GLLISTBASE','GLLINEWIDTH','GLLINESTIPPLE','GLLIGHTMODELIV','GLLIGHTMODELI','GLLIGHTMODELFV','GLLIGHTMODELF',
+            'GLLIGHTIV','GLLIGHTI','GLLIGHTFV','GLLIGHTF','GLISTEXTURE','GLISLIST','GLISENABLED','GLINTERLEAVEDARRAYS',
+            'GLINITNAMES','GLINDEXUBV','GLINDEXUB','GLINDEXSV','GLINDEXS','GLINDEXPOINTER','GLINDEXMASK','GLINDEXIV',
+            'GLINDEXI','GLINDEXFV','GLINDEXF','GLINDEXDV','GLINDEXD','GLHINT','GLGETTEXPARAMETERIV','GLGETTEXPARAMETERFV',
+            'GLGETTEXLEVELPARAMETERIV','GLGETTEXLEVELPARAMETERFV','GLGETTEXIMAGE','GLGETTEXGENIV','GLGETTEXGENFV','GLGETTEXGENDV','GLGETTEXENVIV','GLGETTEXENVFV',
+            'GLGETSTRING','GLGETPOLYGONSTIPPLE','GLGETPOINTERV','GLGETPIXELMAPUSV','GLGETPIXELMAPUIV','GLGETPIXELMAPFV','GLGETMATERIALIV','GLGETMATERIALFV',
+            'GLGETMAPIV','GLGETMAPFV','GLGETMAPDV','GLGETLIGHTIV','GLGETLIGHTFV','GLGETINTEGERV','GLGETFLOATV','GLGETERROR',
+            'GLGETDOUBLEV','GLGETCLIPPLANE','GLGETBOOLEANV','GLGENTEXTURES','GLGENLISTS','GLFRUSTUM','GLFRONTFACE','GLFOGIV',
+            'GLFOGI','GLFOGFV','GLFOGF','GLFLUSH','GLFINISH','GLFEEDBACKBUFFER','GLEVALPOINT2','GLEVALPOINT1',
+            'GLEVALMESH2','GLEVALMESH1','GLEVALCOORD2FV','GLEVALCOORD2F','GLEVALCOORD2DV','GLEVALCOORD2D','GLEVALCOORD1FV','GLEVALCOORD1F',
+            'GLEVALCOORD1DV','GLEVALCOORD1D','GLENDLIST','GLEND','GLENABLECLIENTSTATE','GLENABLE','GLEDGEFLAGV','GLEDGEFLAGPOINTER',
+            'GLEDGEFLAG','GLDRAWPIXELS','GLDRAWELEMENTS','GLDRAWBUFFER','GLDRAWARRAYS','GLDISABLECLIENTSTATE','GLDISABLE','GLDEPTHRANGE',
+            'GLDEPTHMASK','GLDEPTHFUNC','GLDELETETEXTURES','GLDELETELISTS','GLCULLFACE','GLCOPYTEXSUBIMAGE2D','GLCOPYTEXSUBIMAGE1D','GLCOPYTEXIMAGE2D',
+            'GLCOPYTEXIMAGE1D','GLCOPYPIXELS','GLCOLORPOINTER','GLCOLORMATERIAL','GLCOLORMASK','GLCOLOR4USV','GLCOLOR4US','GLCOLOR4UIV',
+            'GLCOLOR4UI','GLCOLOR4UBV','GLCOLOR4UB','GLCOLOR4SV','GLCOLOR4S','GLCOLOR4IV','GLCOLOR4I','GLCOLOR4FV',
+            'GLCOLOR4F','GLCOLOR4DV','GLCOLOR4D','GLCOLOR4BV','GLCOLOR4B','GLCOLOR3USV','GLCOLOR3US','GLCOLOR3UIV',
+            'GLCOLOR3UI','GLCOLOR3UBV','GLCOLOR3UB','GLCOLOR3SV','GLCOLOR3S','GLCOLOR3IV','GLCOLOR3I','GLCOLOR3FV',
+            'GLCOLOR3F','GLCOLOR3DV','GLCOLOR3D','GLCOLOR3BV','GLCOLOR3B','GLCLIPPLANE','GLCLEARSTENCIL','GLCLEARINDEX',
+            'GLCLEARDEPTH','GLCLEARCOLOR','GLCLEARACCUM','GLCLEAR','GLCALLLISTS','GLCALLLIST','GLBLENDFUNC','GLBITMAP',
+            'GLBINDTEXTURE','GLBEGIN','GLARRAYELEMENT','GLARETEXTURESRESIDENT','GLALPHAFUNC','GLACCUM'),
+        2 => array(
+            '$BEL','$BS','$CR','$CRLF','$DQ','$DT_DATE_SEPARATOR','$DT_LANGUAGE','$DT_TIME_SEPARATOR',
+            '$ESC','$FF','$LF','$NUL','$PC_SD_MY_PC','$SPC','$SQL_OPT_TRACE_FILE_DEFAULT','$SQL_SPEC_STRING',
+            '$TAB','$TRACKBAR_CLASS','$VT','%ACM_OPEN','%ACM_OPENW','%ACM_PLAY','%ACM_STOP','%ACN_START',
+            '%ACN_STOP','%ACS_AUTOPLAY','%ACS_CENTER','%ACS_TIMER','%ACS_TRANSPARENT','%APP_COUNTER_FUNLOOKUP','%APP_COUNTER_KEYLOOKUP','%APP_COUNTER_LOOKUP',
+            '%APP_COUNTER_TESTALPHA','%APP_COUNTER_UDTLOOKUP','%APP_COUNTER_VARLOOKUP','%APP_TIMER_EXECTOTAL','%APP_TIMER_INIT','%APP_TIMER_LOAD','%APP_TIMER_PREPROCESSOR','%AW_ACTIVATE',
+            '%AW_BLEND','%AW_CENTER','%AW_HIDE','%AW_HOR_NEGATIVE','%AW_HOR_POSITIVE','%AW_SLIDE','%AW_VER_NEGATIVE','%AW_VER_POSITIVE',
+            '%BCM_FIRST','%BLACK','%BLUE','%BM_GETCHECK','%BM_SETCHECK','%BST_CHECKED','%BST_UNCHECKED','%BS_AUTOCHECKBOX',
+            '%BS_BOTTOM','%BS_CENTER','%BS_DEFAULT','%BS_DEFPUSHBUTTON','%BS_FLAT','%BS_LEFT','%BS_LEFTTEXT','%BS_MULTILINE',
+            '%BS_NOTIFY','%BS_OWNERDRAW','%BS_PUSHLIKE','%BS_RIGHT','%BS_TOP','%BS_VCENTER','%BUNDLE_BUILDER_CANCELLED','%CBM_FIRST',
+            '%CBN_CLOSEUP','%CBN_DBLCLK','%CBN_DROPDOWN','%CBN_EDITCHANGE','%CBN_EDITUPDATE','%CBN_ERRSPACE','%CBN_KILLFOCUS','%CBN_SELCANCEL',
+            '%CBN_SELCHANGE','%CBN_SELENDCANCEL','%CBN_SELENDOK','%CBN_SETFOCUS','%CBS_AUTOHSCROLL','%CBS_DISABLENOSCROLL','%CBS_DROPDOWN','%CBS_DROPDOWNLIST',
+            '%CBS_HASSTRINGS','%CBS_LOWERCASE','%CBS_NOINTEGRALHEIGHT','%CBS_SIMPLE','%CBS_SORT','%CBS_UPPERCASE','%CB_SELECTSTRING','%CCM_FIRST',
+            '%CC_ANYCOLOR','%CC_ENABLEHOOK','%CC_ENABLETEMPLATE','%CC_ENABLETEMPLATEHANDLE','%CC_FULLOPEN','%CC_PREVENTFULLOPEN','%CC_RGBINIT','%CC_SHOWHELP',
+            '%CC_SOLIDCOLOR','%CFE_BOLD','%CFE_ITALIC','%CFE_LINK','%CFE_PROTECTED','%CFE_STRIKEOUT','%CFE_UNDERLINE','%CFM_ANIMATION',
+            '%CFM_BACKCOLOR','%CFM_BOLD','%CFM_CHARSET','%CFM_COLOR','%CFM_FACE','%CFM_ITALIC','%CFM_KERNING','%CFM_LCID',
+            '%CFM_LINK','%CFM_OFFSET','%CFM_PROTECTED','%CFM_REVAUTHOR','%CFM_SIZE','%CFM_SPACING','%CFM_STRIKEOUT','%CFM_STYLE',
+            '%CFM_UNDERLINE','%CFM_UNDERLINETYPE','%CFM_WEIGHT','%CGI_ACCEPT_FILE_UPLOAD','%CGI_AUTO_ADD_SPECIAL_CHARS_PREFIX','%CGI_AUTO_CREATE_VARS','%CGI_BUFFERIZE_OUTPUT','%CGI_DOUBLE_QUOTE',
+            '%CGI_FILE_UPLOAD_BASEPATH','%CGI_FORCE_SESSION_VALIDATION','%CGI_MAX_BYTE_FROM_STD_IN','%CGI_REQUEST_METHOD_GET','%CGI_REQUEST_METHOD_POST','%CGI_SESSION_FILE_BASEPATH','%CGI_SINGLE_QUOTE','%CGI_SPECIAL_CHARS_PREFIX',
+            '%CGI_TEMPORARY_UPLOAD_PATH','%CGI_UPLOAD_CAN_OVERWRITE','%CGI_WRITE_LOG_FILE','%CGI_WRITE_VARS_INTO_LOG_FILE','%CONOLE_ATTACH_PARENT_PROCESS','%CONSOLE_BACKGROUND_BLUE','%CONSOLE_BACKGROUND_GREEN','%CONSOLE_BACKGROUND_INTENSITY',
+            '%CONSOLE_BACKGROUND_RED','%CONSOLE_BOX_FLAG_3DOFF','%CONSOLE_BOX_FLAG_3DON','%CONSOLE_BOX_FLAG_SHADOW','%CONSOLE_COMMON_LVB_GRID_HORIZONTAL','%CONSOLE_COMMON_LVB_GRID_LVERTICAL','%CONSOLE_COMMON_LVB_GRID_RVERTICAL','%CONSOLE_COMMON_LVB_LEADING_BYTE',
+            '%CONSOLE_COMMON_LVB_REVERSE_VIDEO','%CONSOLE_COMMON_LVB_TRAILING_BYTE','%CONSOLE_COMMON_LVB_UNDERSCORE','%CONSOLE_CTRL_BREAK_EVENT','%CONSOLE_CTRL_C_EVENT','%CONSOLE_DOUBLE_CLICK','%CONSOLE_ENABLE_AUTO_POSITION','%CONSOLE_ENABLE_ECHO_INPUT',
+            '%CONSOLE_ENABLE_EXTENDED_FLAGS','%CONSOLE_ENABLE_INSERT_MODE','%CONSOLE_ENABLE_LINE_INPUT','%CONSOLE_ENABLE_MOUSE_INPUT','%CONSOLE_ENABLE_PROCESSED_INPUT','%CONSOLE_ENABLE_PROCESSED_OUTPUT','%CONSOLE_ENABLE_QUICK_EDIT_MODE','%CONSOLE_ENABLE_WINDOW_INPUT',
+            '%CONSOLE_ENABLE_WRAP_AT_EOL_OUTPUT','%CONSOLE_FOREGROUND_BLUE','%CONSOLE_FOREGROUND_GREEN','%CONSOLE_FOREGROUND_INTENSITY','%CONSOLE_FOREGROUND_RED','%CONSOLE_LBUTTON','%CONSOLE_LINE_HORIZONTAL','%CONSOLE_LINE_VERTICAL',
+            '%CONSOLE_MBUTTON','%CONSOLE_MOUSE_MOVED','%CONSOLE_MOUSE_WHEELED','%CONSOLE_RBUTTON','%CONSOLE_SCROLLBUF_DOWN','%CONSOLE_SCROLLBUF_UP','%CONSOLE_SCROLLWND_ABSOLUTE','%CONSOLE_SCROLLWND_RELATIVE',
+            '%CONSOLE_STD_ERROR_HANDLE','%CONSOLE_STD_INPUT_HANDLE','%CONSOLE_STD_OUTPUT_HANDLE','%CONSOLE_SW_FORCEMINIMIZE','%CONSOLE_SW_HIDE','%CONSOLE_SW_MAXIMIZE','%CONSOLE_SW_MINIMIZE','%CONSOLE_SW_RESTORE',
+            '%CONSOLE_SW_SHOW','%CONSOLE_SW_SHOWDEFAULT','%CONSOLE_SW_SHOWMAXIMIZED','%CONSOLE_SW_SHOWMINIMIZED','%CONSOLE_SW_SHOWMINNOACTIVE','%CONSOLE_SW_SHOWNA','%CONSOLE_SW_SHOWNOACTIVATE','%CONSOLE_SW_SHOWNORMAL',
+            '%CONSOLE_UNAVAILABLE','%CRYPTO_CALG_DES','%CRYPTO_CALG_RC2','%CRYPTO_CALG_RC4','%CRYPTO_PROV_DH_SCHANNEL','%CRYPTO_PROV_DSS','%CRYPTO_PROV_DSS_DH','%CRYPTO_PROV_FORTEZZA',
+            '%CRYPTO_PROV_MS_EXCHANGE','%CRYPTO_PROV_RSA_FULL','%CRYPTO_PROV_RSA_SCHANNEL','%CRYPTO_PROV_RSA_SIG','%CRYPTO_PROV_SSL','%CSIDL_ADMINTOOLS','%CSIDL_ALTSTARTUP','%CSIDL_APPDATA',
+            '%CSIDL_BITBUCKET','%CSIDL_CDBURN_AREA','%CSIDL_COMMON_ADMINTOOLS','%CSIDL_COMMON_ALTSTARTUP','%CSIDL_COMMON_APPDATA','%CSIDL_COMMON_DESKTOPDIRECTORY','%CSIDL_COMMON_DOCUMENTS','%CSIDL_COMMON_FAVORITES',
+            '%CSIDL_COMMON_MUSIC','%CSIDL_COMMON_PICTURES','%CSIDL_COMMON_PROGRAMS','%CSIDL_COMMON_STARTMENU','%CSIDL_COMMON_STARTUP','%CSIDL_COMMON_TEMPLATES','%CSIDL_COMMON_VIDEO','%CSIDL_CONTROLS',
+            '%CSIDL_COOKIES','%CSIDL_DESKTOP','%CSIDL_DESKTOPDIRECTORY','%CSIDL_DRIVES','%CSIDL_FAVORITES','%CSIDL_FLAG_CREATE','%CSIDL_FONTS','%CSIDL_HISTORY',
+            '%CSIDL_INTERNET','%CSIDL_INTERNET_CACHE','%CSIDL_LOCAL_APPDATA','%CSIDL_MYDOCUMENTS','%CSIDL_MYMUSIC','%CSIDL_MYPICTURES','%CSIDL_MYVIDEO','%CSIDL_NETHOOD',
+            '%CSIDL_NETWORK','%CSIDL_PERSONAL','%CSIDL_PRINTERS','%CSIDL_PRINTHOOD','%CSIDL_PROFILE','%CSIDL_PROGRAMS','%CSIDL_PROGRAM_FILES','%CSIDL_PROGRAM_FILES_COMMON',
+            '%CSIDL_RECENT','%CSIDL_SENDTO','%CSIDL_STARTMENU','%CSIDL_STARTUP','%CSIDL_SYSTEM','%CSIDL_TEMPLATES','%CSIDL_WINDOWS','%CW_USEDEFAULT',
+            '%CYAN','%DATE_TIME_FILE_CREATION','%DATE_TIME_LAST_FILE_ACCESS','%DATE_TIME_LAST_FILE_WRITE','%DICTIONARY_MEMINFO_DATA','%DICTIONARY_MEMINFO_KEYS','%DICTIONARY_MEMINFO_TOTAL','%DICTIONARY_SORTDESCENDING',
+            '%DICTIONARY_SORTKEYS','%DSCAPS_CERTIFIED','%DSCAPS_CONTINUOUSRATE','%DSCAPS_EMULDRIVER','%DSCAPS_SECONDARY16BIT','%DSCAPS_SECONDARY8BIT','%DSCAPS_SECONDARYMONO','%DSCAPS_SECONDARYSTEREO',
+            '%DSCCAPS_CERTIFIED','%DSCCAPS_EMULDRIVER','%DS_3DLOOK','%DS_ABSALIGN','%DS_CENTER','%DS_CENTERMOUSE','%DS_CONTEXTHELP','%DS_CONTROL',
+            '%DS_MODALFRAME','%DS_NOFAILCREATE','%DS_SETFONT','%DS_SETFOREGROUND','%DS_SYSMODAL','%DTM_FIRST','%DTM_GETMCCOLOR','%DTM_GETMCFONT',
+            '%DTM_GETMONTHCAL','%DTM_GETRANGE','%DTM_GETSYSTEMTIME','%DTM_SETFORMAT','%DTM_SETFORMATW','%DTM_SETMCCOLOR','%DTM_SETMCFONT','%DTM_SETRANGE',
+            '%DTM_SETSYSTEMTIME','%DTN_CLOSEUP','%DTN_DATETIMECHANGE','%DTN_DROPDOWN','%DTN_FORMAT','%DTN_FORMATQUERY','%DTN_FORMATQUERYW','%DTN_FORMATW',
+            '%DTN_USERSTRING','%DTN_USERSTRINGW','%DTN_WMKEYDOWN','%DTN_WMKEYDOWNW','%DTS_APPCANPARSE','%DTS_LONGDATEFORMAT','%DTS_RIGHTALIGN','%DTS_SHORTDATECENTURYFORMAT',
+            '%DTS_SHORTDATEFORMAT','%DTS_SHOWNONE','%DTS_TIMEFORMAT','%DTS_UPDOWN','%DT_DATE_CENTURY','%DT_DATE_OK','%DT_DAY_IN_YEAR','%DT_DIFF_IN_DAYS',
+            '%DT_DIFF_IN_HOURS','%DT_DIFF_IN_MINUTES','%DT_DIFF_IN_SECONDS','%DT_HOURS_IN_DAY','%DT_MINUTES_IN_HOUR','%DT_SECONDS_IN_DAY','%DT_SECONDS_IN_HOUR','%DT_SECONDS_IN_MINUTE',
+            '%DT_SECONDS_IN_YEAR','%DT_USE_LONG_FORM','%DT_USE_SHORT_FORM','%DT_WRONG_DATE','%DT_WRONG_DAY','%DT_WRONG_MONTH','%ECM_FIRST','%ECOOP_AND',
+            '%ECOOP_OR','%ECOOP_SET','%ECOOP_XOR','%ECO_AUTOHSCROLL','%ECO_AUTOVSCROLL','%ECO_AUTOWORDSELECTION','%ECO_NOHIDESEL','%ECO_READONLY',
+            '%ECO_SELECTIONBAR','%ECO_WANTRETURN','%EM_AUTOURLDETECT','%EM_CANPASTE','%EM_CANREDO','%EM_CANUNDO','%EM_CHARFROMPOS','%EM_DISPLAYBAND',
+            '%EM_EMPTYUNDOBUFFER','%EM_EXGETSEL','%EM_EXLIMITTEXT','%EM_EXLINEFROMCHAR','%EM_EXSETSEL','%EM_FINDTEXT','%EM_FINDTEXTEX','%EM_FINDWORDBREAK',
+            '%EM_FMTLINES','%EM_FORMATRANGE','%EM_GETAUTOURLDETECT','%EM_GETCHARFORMAT','%EM_GETEDITSTYLE','%EM_GETEVENTMASK','%EM_GETFIRSTVISIBLELINE','%EM_GETHANDLE',
+            '%EM_GETIMESTATUS','%EM_GETLIMITTEXT','%EM_GETLINE','%EM_GETLINECOUNT','%EM_GETMARGINS','%EM_GETMODIFY','%EM_GETOLEINTERFACE','%EM_GETOPTIONS',
+            '%EM_GETPARAFORMAT','%EM_GETPASSWORDCHAR','%EM_GETRECT','%EM_GETREDONAME','%EM_GETSCROLLPOS','%EM_GETSEL','%EM_GETSELTEXT','%EM_GETTEXTMODE',
+            '%EM_GETTEXTRANGE','%EM_GETTHUMB','%EM_GETUNDONAME','%EM_GETWORDBREAKPROC','%EM_GETWORDBREAKPROCEX','%EM_HIDESELECTION','%EM_LIMITTEXT','%EM_LINEFROMCHAR',
+            '%EM_LINEINDEX','%EM_LINELENGTH','%EM_LINESCROLL','%EM_PASTESPECIAL','%EM_POSFROMCHAR','%EM_REDO','%EM_REPLACESEL','%EM_REQUESTRESIZE',
+            '%EM_SCROLL','%EM_SCROLLCARET','%EM_SELECTIONTYPE','%EM_SETBKGNDCOLOR','%EM_SETCHARFORMAT','%EM_SETEDITSTYLE','%EM_SETEVENTMASK','%EM_SETHANDLE',
+            '%EM_SETIMESTATUS','%EM_SETLIMITTEXT','%EM_SETMARGINS','%EM_SETMODIFY','%EM_SETOLECALLBACK','%EM_SETOPTIONS','%EM_SETPARAFORMAT','%EM_SETPASSWORDCHAR',
+            '%EM_SETREADONLY','%EM_SETRECT','%EM_SETRECTNP','%EM_SETSCROLLPOS','%EM_SETSEL','%EM_SETTABSTOPS','%EM_SETTARGETDEVICE','%EM_SETTEXTMODE',
+            '%EM_SETUNDOLIMIT','%EM_SETWORDBREAKPROC','%EM_SETWORDBREAKPROCEX','%EM_SETWORDWRAPMODE','%EM_SETZOOM','%EM_STOPGROUPTYPING','%EM_STREAMIN','%EM_STREAMOUT',
+            '%EM_UNDO','%ENM_CHANGE','%ENM_CORRECTTEXT','%ENM_DRAGDROPDONE','%ENM_DROPFILES','%ENM_KEYEVENTS','%ENM_MOUSEEVENTS','%ENM_NONE',
+            '%ENM_PARAGRAPHEXPANDED','%ENM_PROTECTED','%ENM_REQUESTRESIZE','%ENM_SCROLL','%ENM_SCROLLEVENTS','%ENM_SELCHANGE','%ENM_UPDATE','%EN_CHANGE',
+            '%EN_MSGFILTER','%EN_SELCHANGE','%EN_UPDATE','%ES_AUTOHSCROLL','%ES_AUTOVSCROLL','%ES_CENTER','%ES_DISABLENOSCROLL','%ES_EX_NOCALLOLEINIT',
+            '%ES_LEFT','%ES_LOWERCASE','%ES_MULTILINE','%ES_NOHIDESEL','%ES_NOOLEDRAGDROP','%ES_NUMBER','%ES_OEMCONVERT','%ES_PASSWORD',
+            '%ES_READONLY','%ES_RIGHT','%ES_SAVESEL','%ES_SELECTIONBAR','%ES_SUNKEN','%ES_UPPERCASE','%ES_WANTRETURN','%EVAL_EXEC_STRING',
+            '%FALSE','%FILE_ADDPATH','%FILE_ARCHIVE','%FILE_BUILDVERSION','%FILE_HIDDEN','%FILE_MAJORVERSION','%FILE_MINORVERSION','%FILE_NORMAL',
+            '%FILE_READONLY','%FILE_REVISIONVERSION','%FILE_SUBDIR','%FILE_SYSTEM','%FILE_VLABEL','%FTP_GET_CONNECT_STATUS','%FTP_GET_FILE_BYTES_RCVD','%FTP_GET_FILE_BYTES_SENT',
+            '%FTP_GET_LAST_RESPONSE','%FTP_GET_LOCAL_IP','%FTP_GET_SERVER_IP','%FTP_GET_TOTAL_BYTES_RCVD','%FTP_GET_TOTAL_BYTES_SENT','%FTP_LIST_FULLLIST','%FTP_LIST_FULLLISTDIR','%FTP_LIST_FULLLISTFILE',
+            '%FTP_SET_ASYNC','%FTP_SET_CONNECT_WAIT','%FTP_SET_MAX_LISTEN_WAIT','%FTP_SET_MAX_RESPONSE_WAIT','%FTP_SET_PASSIVE','%FTP_SET_SYNC','%FW_BLACK','%FW_BOLD',
+            '%FW_DEMIBOLD','%FW_DONTCARE','%FW_EXTRABOLD','%FW_EXTRALIGHT','%FW_HEAVY','%FW_LIGHT','%FW_MEDIUM','%FW_NORMAL',
+            '%FW_REGULAR','%FW_SEMIBOLD','%FW_THIN','%FW_ULTRABOLD','%FW_ULTRALIGHT','%GDTR_MAX','%GDTR_MIN','%GLU_AUTO_LOAD_MATRIX',
+            '%GLU_BEGIN','%GLU_CCW','%GLU_CULLING','%GLU_CW','%GLU_DISPLAY_MODE','%GLU_DOMAIN_DISTANCE','%GLU_EDGE_FLAG','%GLU_END',
+            '%GLU_ERROR','%GLU_EXTENSIONS','%GLU_EXTERIOR','%GLU_FALSE','%GLU_FILL','%GLU_FLAT','%GLU_INCOMPATIBLE_GL_VERSION','%GLU_INSIDE',
+            '%GLU_INTERIOR','%GLU_INVALID_ENUM','%GLU_INVALID_VALUE','%GLU_LINE','%GLU_MAP1_TRIM_2','%GLU_MAP1_TRIM_3','%GLU_NONE','%GLU_NURBS_ERROR1',
+            '%GLU_NURBS_ERROR10','%GLU_NURBS_ERROR11','%GLU_NURBS_ERROR12','%GLU_NURBS_ERROR13','%GLU_NURBS_ERROR14','%GLU_NURBS_ERROR15','%GLU_NURBS_ERROR16','%GLU_NURBS_ERROR17',
+            '%GLU_NURBS_ERROR18','%GLU_NURBS_ERROR19','%GLU_NURBS_ERROR2','%GLU_NURBS_ERROR20','%GLU_NURBS_ERROR21','%GLU_NURBS_ERROR22','%GLU_NURBS_ERROR23','%GLU_NURBS_ERROR24',
+            '%GLU_NURBS_ERROR25','%GLU_NURBS_ERROR26','%GLU_NURBS_ERROR27','%GLU_NURBS_ERROR28','%GLU_NURBS_ERROR29','%GLU_NURBS_ERROR3','%GLU_NURBS_ERROR30','%GLU_NURBS_ERROR31',
+            '%GLU_NURBS_ERROR32','%GLU_NURBS_ERROR33','%GLU_NURBS_ERROR34','%GLU_NURBS_ERROR35','%GLU_NURBS_ERROR36','%GLU_NURBS_ERROR37','%GLU_NURBS_ERROR4','%GLU_NURBS_ERROR5',
+            '%GLU_NURBS_ERROR6','%GLU_NURBS_ERROR7','%GLU_NURBS_ERROR8','%GLU_NURBS_ERROR9','%GLU_OUTLINE_PATCH','%GLU_OUTLINE_POLYGON','%GLU_OUTSIDE','%GLU_OUT_OF_MEMORY',
+            '%GLU_PARAMETRIC_ERROR','%GLU_PARAMETRIC_TOLERANCE','%GLU_PATH_LENGTH','%GLU_POINT','%GLU_SAMPLING_METHOD','%GLU_SAMPLING_TOLERANCE','%GLU_SILHOUETTE','%GLU_SMOOTH',
+            '%GLU_TESS_BEGIN','%GLU_TESS_BEGIN_DATA','%GLU_TESS_BOUNDARY_ONLY','%GLU_TESS_COMBINE','%GLU_TESS_COMBINE_DATA','%GLU_TESS_COORD_TOO_LARGE','%GLU_TESS_EDGE_FLAG','%GLU_TESS_EDGE_FLAG_DATA',
+            '%GLU_TESS_END','%GLU_TESS_END_DATA','%GLU_TESS_ERROR','%GLU_TESS_ERROR1','%GLU_TESS_ERROR2','%GLU_TESS_ERROR3','%GLU_TESS_ERROR4','%GLU_TESS_ERROR5',
+            '%GLU_TESS_ERROR6','%GLU_TESS_ERROR7','%GLU_TESS_ERROR8','%GLU_TESS_ERROR_DATA','%GLU_TESS_MISSING_BEGIN_CONTOUR','%GLU_TESS_MISSING_BEGIN_POLYGON','%GLU_TESS_MISSING_END_CONTOUR','%GLU_TESS_MISSING_END_POLYGON',
+            '%GLU_TESS_NEED_COMBINE_CALLBACK','%GLU_TESS_TOLERANCE','%GLU_TESS_VERTEX','%GLU_TESS_VERTEX_DATA','%GLU_TESS_WINDING_ABS_GEQ_TWO','%GLU_TESS_WINDING_NEGATIVE','%GLU_TESS_WINDING_NONZERO','%GLU_TESS_WINDING_ODD',
+            '%GLU_TESS_WINDING_POSITIVE','%GLU_TESS_WINDING_RULE','%GLU_TRUE','%GLU_UNKNOWN','%GLU_U_STEP','%GLU_VERSION','%GLU_VERSION_1_1','%GLU_VERSION_1_2',
+            '%GLU_VERTEX','%GLU_V_STEP','%GL_2D','%GL_2_BYTES','%GL_3D','%GL_3D_COLOR','%GL_3D_COLOR_TEXTURE','%GL_3_BYTES',
+            '%GL_4D_COLOR_TEXTURE','%GL_4_BYTES','%GL_ABGR_EXT','%GL_ACCUM','%GL_ACCUM_ALPHA_BITS','%GL_ACCUM_BLUE_BITS','%GL_ACCUM_BUFFER_BIT','%GL_ACCUM_CLEAR_VALUE',
+            '%GL_ACCUM_GREEN_BITS','%GL_ACCUM_RED_BITS','%GL_ADD','%GL_ALL_ATTRIB_BITS','%GL_ALPHA','%GL_ALPHA12','%GL_ALPHA16','%GL_ALPHA4',
+            '%GL_ALPHA8','%GL_ALPHA_BIAS','%GL_ALPHA_BITS','%GL_ALPHA_SCALE','%GL_ALPHA_TEST','%GL_ALPHA_TEST_FUNC','%GL_ALPHA_TEST_REF','%GL_ALWAYS',
+            '%GL_AMBIENT','%GL_AMBIENT_AND_DIFFUSE','%GL_AND','%GL_AND_INVERTED','%GL_AND_REVERSE','%GL_ARRAY_ELEMENT_LOCK_COUNT_EXT','%GL_ARRAY_ELEMENT_LOCK_FIRST_EXT','%GL_ATTRIB_STACK_DEPTH',
+            '%GL_AUTO_NORMAL','%GL_AUX0','%GL_AUX1','%GL_AUX2','%GL_AUX3','%GL_AUX_BUFFERS','%GL_BACK','%GL_BACK_LEFT',
+            '%GL_BACK_RIGHT','%GL_BGRA_EXT','%GL_BGR_EXT','%GL_BITMAP','%GL_BITMAP_TOKEN','%GL_BLEND','%GL_BLEND_COLOR_EXT','%GL_BLEND_DST',
+            '%GL_BLEND_EQUATION_EXT','%GL_BLEND_SRC','%GL_BLUE','%GL_BLUE_BIAS','%GL_BLUE_BITS','%GL_BLUE_SCALE','%GL_BYTE','%GL_C3F_V3F',
+            '%GL_C4F_N3F_V3F','%GL_C4UB_V2F','%GL_C4UB_V3F','%GL_CCW','%GL_CLAMP','%GL_CLEAR','%GL_CLIENT_ALL_ATTRIB_BITS','%GL_CLIENT_ATTRIB_STACK_DEPTH',
+            '%GL_CLIENT_PIXEL_STORE_BIT','%GL_CLIENT_VERTEX_ARRAY_BIT','%GL_CLIP_PLANE0','%GL_CLIP_PLANE1','%GL_CLIP_PLANE2','%GL_CLIP_PLANE3','%GL_CLIP_PLANE4','%GL_CLIP_PLANE5',
+            '%GL_CLIP_VOLUME_CLIPPING_HINT_EXT','%GL_COEFF','%GL_COLOR','%GL_COLOR_ARRAY','%GL_COLOR_ARRAY_COUNT_EXT','%GL_COLOR_ARRAY_EXT','%GL_COLOR_ARRAY_POINTER','%GL_COLOR_ARRAY_POINTER_EXT',
+            '%GL_COLOR_ARRAY_SIZE','%GL_COLOR_ARRAY_SIZE_EXT','%GL_COLOR_ARRAY_STRIDE','%GL_COLOR_ARRAY_STRIDE_EXT','%GL_COLOR_ARRAY_TYPE','%GL_COLOR_ARRAY_TYPE_EXT','%GL_COLOR_BUFFER_BIT','%GL_COLOR_CLEAR_VALUE',
+            '%GL_COLOR_INDEX','%GL_COLOR_INDEX12_EXT','%GL_COLOR_INDEX16_EXT','%GL_COLOR_INDEX1_EXT','%GL_COLOR_INDEX2_EXT','%GL_COLOR_INDEX4_EXT','%GL_COLOR_INDEX8_EXT','%GL_COLOR_INDEXES',
+            '%GL_COLOR_LOGIC_OP','%GL_COLOR_MATERIAL','%GL_COLOR_MATERIAL_FACE','%GL_COLOR_MATERIAL_PARAMETER','%GL_COLOR_SUM_EXT','%GL_COLOR_TABLE_ALPHA_SIZE_EXT','%GL_COLOR_TABLE_BIAS_EXT','%GL_COLOR_TABLE_BLUE_SIZE_EXT',
+            '%GL_COLOR_TABLE_EXT','%GL_COLOR_TABLE_FORMAT_EXT','%GL_COLOR_TABLE_GREEN_SIZE_EXT','%GL_COLOR_TABLE_INTENSITY_SIZE_EXT','%GL_COLOR_TABLE_LUMINANCE_SIZE_EXT','%GL_COLOR_TABLE_RED_SIZE_EXT','%GL_COLOR_TABLE_SCALE_EXT','%GL_COLOR_TABLE_WIDTH_EXT',
+            '%GL_COLOR_WRITEMASK','%GL_COMPILE','%GL_COMPILE_AND_EXECUTE','%GL_CONSTANT_ALPHA_EXT','%GL_CONSTANT_ATTENUATION','%GL_CONSTANT_COLOR_EXT','%GL_CONVOLUTION_1D_EXT','%GL_CONVOLUTION_2D_EXT',
+            '%GL_CONVOLUTION_BORDER_MODE_EXT','%GL_CONVOLUTION_FILTER_BIAS_EXT','%GL_CONVOLUTION_FILTER_SCALE_EXT','%GL_CONVOLUTION_FORMAT_EXT','%GL_CONVOLUTION_HEIGHT_EXT','%GL_CONVOLUTION_WIDTH_EXT','%GL_COPY','%GL_COPY_INVERTED',
+            '%GL_COPY_PIXEL_TOKEN','%GL_CULL_FACE','%GL_CULL_FACE_MODE','%GL_CULL_VERTEX_EXT','%GL_CULL_VERTEX_EYE_POSITION_EXT','%GL_CULL_VERTEX_OBJECT_POSITION_EXT','%GL_CURRENT_BIT','%GL_CURRENT_COLOR',
+            '%GL_CURRENT_INDEX','%GL_CURRENT_NORMAL','%GL_CURRENT_RASTER_COLOR','%GL_CURRENT_RASTER_DISTANCE','%GL_CURRENT_RASTER_INDEX','%GL_CURRENT_RASTER_POSITION','%GL_CURRENT_RASTER_POSITION_VALID','%GL_CURRENT_RASTER_TEXTURE_COORDS',
+            '%GL_CURRENT_SECONDARY_COLOR_EXT','%GL_CURRENT_TEXTURE_COORDS','%GL_CW','%GL_DECAL','%GL_DECR','%GL_DEPTH','%GL_DEPTH_BIAS','%GL_DEPTH_BITS',
+            '%GL_DEPTH_BUFFER_BIT','%GL_DEPTH_CLEAR_VALUE','%GL_DEPTH_COMPONENT','%GL_DEPTH_FUNC','%GL_DEPTH_RANGE','%GL_DEPTH_SCALE','%GL_DEPTH_TEST','%GL_DEPTH_WRITEMASK',
+            '%GL_DIFFUSE','%GL_DITHER','%GL_DOMAIN','%GL_DONT_CARE','%GL_DOUBLE','%GL_DOUBLEBUFFER','%GL_DOUBLE_EXT','%GL_DRAW_BUFFER',
+            '%GL_DRAW_PIXEL_TOKEN','%GL_DST_ALPHA','%GL_DST_COLOR','%GL_EDGE_FLAG','%GL_EDGE_FLAG_ARRAY','%GL_EDGE_FLAG_ARRAY_COUNT_EXT','%GL_EDGE_FLAG_ARRAY_EXT','%GL_EDGE_FLAG_ARRAY_POINTER',
+            '%GL_EDGE_FLAG_ARRAY_POINTER_EXT','%GL_EDGE_FLAG_ARRAY_STRIDE','%GL_EDGE_FLAG_ARRAY_STRIDE_EXT','%GL_EMISSION','%GL_ENABLE_BIT','%GL_EQUAL','%GL_EQUIV','%GL_EVAL_BIT',
+            '%GL_EXP','%GL_EXP2','%GL_EXTENSIONS','%GL_EXT_ABGR','%GL_EXT_BGRA','%GL_EXT_BLEND_COLOR','%GL_EXT_BLEND_MINMAX','%GL_EXT_BLEND_SUBTRACT',
+            '%GL_EXT_CLIP_VOLUME_HINT','%GL_EXT_COLOR_TABLE','%GL_EXT_COMPILED_VERTEX_ARRAY','%GL_EXT_CONVOLUTION','%GL_EXT_CULL_VERTEX','%GL_EXT_HISTOGRAM','%GL_EXT_PACKED_PIXELS','%GL_EXT_PALETTED_TEXTURE',
+            '%GL_EXT_POLYGON_OFFSET','%GL_EXT_SECONDARY_COLOR','%GL_EXT_SEPARATE_SPECULAR_COLOR','%GL_EXT_VERTEX_ARRAY','%GL_EYE_LINEAR','%GL_EYE_PLANE','%GL_FALSE','%GL_FASTEST',
+            '%GL_FEEDBACK','%GL_FEEDBACK_BUFFER_POINTER','%GL_FEEDBACK_BUFFER_SIZE','%GL_FEEDBACK_BUFFER_TYPE','%GL_FILL','%GL_FLAT','%GL_FLOAT','%GL_FOG',
+            '%GL_FOG_BIT','%GL_FOG_COLOR','%GL_FOG_DENSITY','%GL_FOG_END','%GL_FOG_HINT','%GL_FOG_INDEX','%GL_FOG_MODE','%GL_FOG_START',
+            '%GL_FRONT','%GL_FRONT_AND_BACK','%GL_FRONT_FACE','%GL_FRONT_LEFT','%GL_FRONT_RIGHT','%GL_FUNC_ADD_EXT','%GL_FUNC_REVERSE_SUBTRACT_EXT','%GL_FUNC_SUBTRACT_EXT',
+            '%GL_GEQUAL','%GL_GREATER','%GL_GREEN','%GL_GREEN_BIAS','%GL_GREEN_BITS','%GL_GREEN_SCALE','%GL_HINT_BIT','%GL_HISTOGRAM_ALPHA_SIZE_EXT',
+            '%GL_HISTOGRAM_BLUE_SIZE_EXT','%GL_HISTOGRAM_EXT','%GL_HISTOGRAM_FORMAT_EXT','%GL_HISTOGRAM_GREEN_SIZE_EXT','%GL_HISTOGRAM_LUMINANCE_SIZE_EXT','%GL_HISTOGRAM_RED_SIZE_EXT','%GL_HISTOGRAM_SINK_EXT','%GL_HISTOGRAM_WIDTH_EXT',
+            '%GL_INCR','%GL_INDEX_ARRAY','%GL_INDEX_ARRAY_COUNT_EXT','%GL_INDEX_ARRAY_EXT','%GL_INDEX_ARRAY_POINTER','%GL_INDEX_ARRAY_POINTER_EXT','%GL_INDEX_ARRAY_STRIDE','%GL_INDEX_ARRAY_STRIDE_EXT',
+            '%GL_INDEX_ARRAY_TYPE','%GL_INDEX_ARRAY_TYPE_EXT','%GL_INDEX_BITS','%GL_INDEX_CLEAR_VALUE','%GL_INDEX_LOGIC_OP','%GL_INDEX_MODE','%GL_INDEX_OFFSET','%GL_INDEX_SHIFT',
+            '%GL_INDEX_WRITEMASK','%GL_INT','%GL_INTENSITY','%GL_INTENSITY12','%GL_INTENSITY16','%GL_INTENSITY4','%GL_INTENSITY8','%GL_INVALID_ENUM',
+            '%GL_INVALID_OPERATION','%GL_INVALID_VALUE','%GL_INVERT','%GL_KEEP','%GL_LEFT','%GL_LEQUAL','%GL_LESS','%GL_LIGHT0',
+            '%GL_LIGHT1','%GL_LIGHT2','%GL_LIGHT3','%GL_LIGHT4','%GL_LIGHT5','%GL_LIGHT6','%GL_LIGHT7','%GL_LIGHTING',
+            '%GL_LIGHTING_BIT','%GL_LIGHT_MODEL_AMBIENT','%GL_LIGHT_MODEL_COLOR_CONTROL_EXT','%GL_LIGHT_MODEL_LOCAL_VIEWER','%GL_LIGHT_MODEL_TWO_SIDE','%GL_LINE','%GL_LINEAR','%GL_LINEAR_ATTENUATION',
+            '%GL_LINEAR_MIPMAP_LINEAR','%GL_LINEAR_MIPMAP_NEAREST','%GL_LINES','%GL_LINE_BIT','%GL_LINE_LOOP','%GL_LINE_RESET_TOKEN','%GL_LINE_SMOOTH','%GL_LINE_SMOOTH_HINT',
+            '%GL_LINE_STIPPLE','%GL_LINE_STIPPLE_PATTERN','%GL_LINE_STIPPLE_REPEAT','%GL_LINE_STRIP','%GL_LINE_TOKEN','%GL_LINE_WIDTH','%GL_LINE_WIDTH_GRANULARITY','%GL_LINE_WIDTH_RANGE',
+            '%GL_LIST_BASE','%GL_LIST_BIT','%GL_LIST_INDEX','%GL_LIST_MODE','%GL_LOAD','%GL_LOGIC_OP','%GL_LOGIC_OP_MODE','%GL_LUMINANCE',
+            '%GL_LUMINANCE12','%GL_LUMINANCE12_ALPHA12','%GL_LUMINANCE12_ALPHA4','%GL_LUMINANCE16','%GL_LUMINANCE16_ALPHA16','%GL_LUMINANCE4','%GL_LUMINANCE4_ALPHA4','%GL_LUMINANCE6_ALPHA2',
+            '%GL_LUMINANCE8','%GL_LUMINANCE8_ALPHA8','%GL_LUMINANCE_ALPHA','%GL_MAP1_COLOR_4','%GL_MAP1_GRID_DOMAIN','%GL_MAP1_GRID_SEGMENTS','%GL_MAP1_INDEX','%GL_MAP1_NORMAL',
+            '%GL_MAP1_TEXTURE_COORD_1','%GL_MAP1_TEXTURE_COORD_2','%GL_MAP1_TEXTURE_COORD_3','%GL_MAP1_TEXTURE_COORD_4','%GL_MAP1_VERTEX_3','%GL_MAP1_VERTEX_4','%GL_MAP2_COLOR_4','%GL_MAP2_GRID_DOMAIN',
+            '%GL_MAP2_GRID_SEGMENTS','%GL_MAP2_INDEX','%GL_MAP2_NORMAL','%GL_MAP2_TEXTURE_COORD_1','%GL_MAP2_TEXTURE_COORD_2','%GL_MAP2_TEXTURE_COORD_3','%GL_MAP2_TEXTURE_COORD_4','%GL_MAP2_VERTEX_3',
+            '%GL_MAP2_VERTEX_4','%GL_MAP_COLOR','%GL_MAP_STENCIL','%GL_MATRIX_MODE','%GL_MAX_ATTRIB_STACK_DEPTH','%GL_MAX_CLIENT_ATTRIB_STACK_DEPTH','%GL_MAX_CLIP_PLANES','%GL_MAX_CONVOLUTION_HEIGHT_EXT',
+            '%GL_MAX_CONVOLUTION_WIDTH_EXT','%GL_MAX_EVAL_ORDER','%GL_MAX_EXT','%GL_MAX_LIGHTS','%GL_MAX_LIST_NESTING','%GL_MAX_MODELVIEW_STACK_DEPTH','%GL_MAX_NAME_STACK_DEPTH','%GL_MAX_PIXEL_MAP_TABLE',
+            '%GL_MAX_PROJECTION_STACK_DEPTH','%GL_MAX_TEXTURE_SIZE','%GL_MAX_TEXTURE_STACK_DEPTH','%GL_MAX_VIEWPORT_DIMS','%GL_MINMAX_EXT','%GL_MINMAX_FORMAT_EXT','%GL_MINMAX_SINK_EXT','%GL_MIN_EXT',
+            '%GL_MODELVIEW','%GL_MODELVIEW_MATRIX','%GL_MODELVIEW_STACK_DEPTH','%GL_MODULATE','%GL_MULT','%GL_N3F_V3F','%GL_NAME_STACK_DEPTH','%GL_NAND',
+            '%GL_NEAREST','%GL_NEAREST_MIPMAP_LINEAR','%GL_NEAREST_MIPMAP_NEAREST','%GL_NEVER','%GL_NICEST','%GL_NONE','%GL_NOOP','%GL_NOR',
+            '%GL_NORMALIZE','%GL_NORMAL_ARRAY','%GL_NORMAL_ARRAY_COUNT_EXT','%GL_NORMAL_ARRAY_EXT','%GL_NORMAL_ARRAY_POINTER','%GL_NORMAL_ARRAY_POINTER_EXT','%GL_NORMAL_ARRAY_STRIDE','%GL_NORMAL_ARRAY_STRIDE_EXT',
+            '%GL_NORMAL_ARRAY_TYPE','%GL_NORMAL_ARRAY_TYPE_EXT','%GL_NOTEQUAL','%GL_NO_ERROR','%GL_OBJECT_LINEAR','%GL_OBJECT_PLANE','%GL_ONE','%GL_ONE_MINUS_CONSTANT_ALPHA_EXT',
+            '%GL_ONE_MINUS_CONSTANT_COLOR_EXT','%GL_ONE_MINUS_DST_ALPHA','%GL_ONE_MINUS_DST_COLOR','%GL_ONE_MINUS_SRC_ALPHA','%GL_ONE_MINUS_SRC_COLOR','%GL_OR','%GL_ORDER','%GL_OR_INVERTED',
+            '%GL_OR_REVERSE','%GL_OUT_OF_MEMORY','%GL_PACK_ALIGNMENT','%GL_PACK_LSB_FIRST','%GL_PACK_ROW_LENGTH','%GL_PACK_SKIP_PIXELS','%GL_PACK_SKIP_ROWS','%GL_PACK_SWAP_BYTES',
+            '%GL_PASS_THROUGH_TOKEN','%GL_PERSPECTIVE_CORRECTION_HINT','%GL_PIXEL_MAP_A_TO_A','%GL_PIXEL_MAP_A_TO_A_SIZE','%GL_PIXEL_MAP_B_TO_B','%GL_PIXEL_MAP_B_TO_B_SIZE','%GL_PIXEL_MAP_G_TO_G','%GL_PIXEL_MAP_G_TO_G_SIZE',
+            '%GL_PIXEL_MAP_I_TO_A','%GL_PIXEL_MAP_I_TO_A_SIZE','%GL_PIXEL_MAP_I_TO_B','%GL_PIXEL_MAP_I_TO_B_SIZE','%GL_PIXEL_MAP_I_TO_G','%GL_PIXEL_MAP_I_TO_G_SIZE','%GL_PIXEL_MAP_I_TO_I','%GL_PIXEL_MAP_I_TO_I_SIZE',
+            '%GL_PIXEL_MAP_I_TO_R','%GL_PIXEL_MAP_I_TO_R_SIZE','%GL_PIXEL_MAP_R_TO_R','%GL_PIXEL_MAP_R_TO_R_SIZE','%GL_PIXEL_MAP_S_TO_S','%GL_PIXEL_MAP_S_TO_S_SIZE','%GL_PIXEL_MODE_BIT','%GL_POINT',
+            '%GL_POINTS','%GL_POINT_BIT','%GL_POINT_SIZE','%GL_POINT_SIZE_GRANULARITY','%GL_POINT_SIZE_RANGE','%GL_POINT_SMOOTH','%GL_POINT_SMOOTH_HINT','%GL_POINT_TOKEN',
+            '%GL_POLYGON','%GL_POLYGON_BIT','%GL_POLYGON_MODE','%GL_POLYGON_OFFSET_BIAS_EXT','%GL_POLYGON_OFFSET_EXT','%GL_POLYGON_OFFSET_FACTOR','%GL_POLYGON_OFFSET_FACTOR_EXT','%GL_POLYGON_OFFSET_FILL',
+            '%GL_POLYGON_OFFSET_LINE','%GL_POLYGON_OFFSET_POINT','%GL_POLYGON_OFFSET_UNITS','%GL_POLYGON_SMOOTH','%GL_POLYGON_SMOOTH_HINT','%GL_POLYGON_STIPPLE','%GL_POLYGON_STIPPLE_BIT','%GL_POLYGON_TOKEN',
+            '%GL_POSITION','%GL_POST_COLOR_MATRIX_COLOR_TABLE_EXT','%GL_POST_CONVOLUTION_ALPHA_BIAS_EXT','%GL_POST_CONVOLUTION_ALPHA_SCALE_EXT','%GL_POST_CONVOLUTION_BLUE_BIAS_EXT','%GL_POST_CONVOLUTION_BLUE_SCALE_EXT','%GL_POST_CONVOLUTION_COLOR_TABLE_EXT','%GL_POST_CONVOLUTION_GREEN_BIAS_EXT',
+            '%GL_POST_CONVOLUTION_GREEN_SCALE_EXT','%GL_POST_CONVOLUTION_RED_BIAS_EXT','%GL_POST_CONVOLUTION_RED_SCALE_EXT','%GL_PROJECTION','%GL_PROJECTION_MATRIX','%GL_PROJECTION_STACK_DEPTH','%GL_PROXY_COLOR_TABLE_EXT','%GL_PROXY_HISTOGRAM_EXT',
+            '%GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_EXT','%GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_EXT','%GL_PROXY_TEXTURE_1D','%GL_PROXY_TEXTURE_2D','%GL_Q','%GL_QUADRATIC_ATTENUATION','%GL_QUADS','%GL_QUAD_STRIP',
+            '%GL_R','%GL_R3_G3_B2','%GL_READ_BUFFER','%GL_RED','%GL_REDUCE_EXT','%GL_RED_BIAS','%GL_RED_BITS','%GL_RED_SCALE',
+            '%GL_RENDER','%GL_RENDERER','%GL_RENDER_MODE','%GL_REPEAT','%GL_REPLACE','%GL_RETURN','%GL_RGB','%GL_RGB10',
+            '%GL_RGB10_A2','%GL_RGB12','%GL_RGB16','%GL_RGB4','%GL_RGB5','%GL_RGB5_A1','%GL_RGB8','%GL_RGBA',
+            '%GL_RGBA12','%GL_RGBA16','%GL_RGBA2','%GL_RGBA4','%GL_RGBA8','%GL_RGBA_MODE','%GL_RIGHT','%GL_S',
+            '%GL_SCISSOR_BIT','%GL_SCISSOR_BOX','%GL_SCISSOR_TEST','%GL_SECONDARY_COLOR_ARRAY_EXT','%GL_SECONDARY_COLOR_ARRAY_POINTER_EXT','%GL_SECONDARY_COLOR_ARRAY_SIZE_EXT','%GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT','%GL_SECONDARY_COLOR_ARRAY_TYPE_EXT',
+            '%GL_SELECT','%GL_SELECTION_BUFFER_POINTER','%GL_SELECTION_BUFFER_SIZE','%GL_SEPARABLE_2D_EXT','%GL_SEPARATE_SPECULAR_COLOR_EXT','%GL_SET','%GL_SHADE_MODEL','%GL_SHININESS',
+            '%GL_SHORT','%GL_SINGLE_COLOR_EXT','%GL_SMOOTH','%GL_SPECULAR','%GL_SPHERE_MAP','%GL_SPOT_CUTOFF','%GL_SPOT_DIRECTION','%GL_SPOT_EXPONENT',
+            '%GL_SRC_ALPHA','%GL_SRC_ALPHA_SATURATE','%GL_SRC_COLOR','%GL_STACK_OVERFLOW','%GL_STACK_UNDERFLOW','%GL_STENCIL','%GL_STENCIL_BITS','%GL_STENCIL_BUFFER_BIT',
+            '%GL_STENCIL_CLEAR_VALUE','%GL_STENCIL_FAIL','%GL_STENCIL_FUNC','%GL_STENCIL_INDEX','%GL_STENCIL_PASS_DEPTH_FAIL','%GL_STENCIL_PASS_DEPTH_PASS','%GL_STENCIL_REF','%GL_STENCIL_TEST',
+            '%GL_STENCIL_VALUE_MASK','%GL_STENCIL_WRITEMASK','%GL_STEREO','%GL_SUBPIXEL_BITS','%GL_T','%GL_T2F_C3F_V3F','%GL_T2F_C4F_N3F_V3F','%GL_T2F_C4UB_V3F',
+            '%GL_T2F_N3F_V3F','%GL_T2F_V3F','%GL_T4F_C4F_N3F_V4F','%GL_T4F_V4F','%GL_TABLE_TOO_LARGE_EXT','%GL_TEXTURE','%GL_TEXTURE_1D','%GL_TEXTURE_2D',
+            '%GL_TEXTURE_ALPHA_SIZE','%GL_TEXTURE_BINDING_1D','%GL_TEXTURE_BINDING_2D','%GL_TEXTURE_BIT','%GL_TEXTURE_BLUE_SIZE','%GL_TEXTURE_BORDER','%GL_TEXTURE_BORDER_COLOR','%GL_TEXTURE_COMPONENTS',
+            '%GL_TEXTURE_COORD_ARRAY','%GL_TEXTURE_COORD_ARRAY_COUNT_EXT','%GL_TEXTURE_COORD_ARRAY_EXT','%GL_TEXTURE_COORD_ARRAY_POINTER','%GL_TEXTURE_COORD_ARRAY_POINTER_EXT','%GL_TEXTURE_COORD_ARRAY_SIZE','%GL_TEXTURE_COORD_ARRAY_SIZE_EXT','%GL_TEXTURE_COORD_ARRAY_STRIDE',
+            '%GL_TEXTURE_COORD_ARRAY_STRIDE_EXT','%GL_TEXTURE_COORD_ARRAY_TYPE','%GL_TEXTURE_COORD_ARRAY_TYPE_EXT','%GL_TEXTURE_ENV','%GL_TEXTURE_ENV_COLOR','%GL_TEXTURE_ENV_MODE','%GL_TEXTURE_GEN_MODE','%GL_TEXTURE_GEN_Q',
+            '%GL_TEXTURE_GEN_R','%GL_TEXTURE_GEN_S','%GL_TEXTURE_GEN_T','%GL_TEXTURE_GREEN_SIZE','%GL_TEXTURE_HEIGHT','%GL_TEXTURE_INTENSITY_SIZE','%GL_TEXTURE_INTERNAL_FORMAT','%GL_TEXTURE_LUMINANCE_SIZE',
+            '%GL_TEXTURE_MAG_FILTER','%GL_TEXTURE_MATRIX','%GL_TEXTURE_MIN_FILTER','%GL_TEXTURE_PRIORITY','%GL_TEXTURE_RED_SIZE','%GL_TEXTURE_RESIDENT','%GL_TEXTURE_STACK_DEPTH','%GL_TEXTURE_WIDTH',
+            '%GL_TEXTURE_WRAP_S','%GL_TEXTURE_WRAP_T','%GL_TRANSFORM_BIT','%GL_TRIANGLES','%GL_TRIANGLE_FAN','%GL_TRIANGLE_STRIP','%GL_TRUE','%GL_UNPACK_ALIGNMENT',
+            '%GL_UNPACK_LSB_FIRST','%GL_UNPACK_ROW_LENGTH','%GL_UNPACK_SKIP_PIXELS','%GL_UNPACK_SKIP_ROWS','%GL_UNPACK_SWAP_BYTES','%GL_UNSIGNED_BYTE','%GL_UNSIGNED_BYTE_3_3_2_EXT','%GL_UNSIGNED_INT',
+            '%GL_UNSIGNED_INT_10_10_10_2_EXT','%GL_UNSIGNED_INT_8_8_8_8_EXT','%GL_UNSIGNED_SHORT','%GL_UNSIGNED_SHORT_4_4_4_4_EXT','%GL_UNSIGNED_SHORT_5_5_5_1_EXT','%GL_V2F','%GL_V3F','%GL_VENDOR',
+            '%GL_VERSION','%GL_VERSION_1_1','%GL_VERTEX_ARRAY','%GL_VERTEX_ARRAY_COUNT_EXT','%GL_VERTEX_ARRAY_EXT','%GL_VERTEX_ARRAY_POINTER','%GL_VERTEX_ARRAY_POINTER_EXT','%GL_VERTEX_ARRAY_SIZE',
+            '%GL_VERTEX_ARRAY_SIZE_EXT','%GL_VERTEX_ARRAY_STRIDE','%GL_VERTEX_ARRAY_STRIDE_EXT','%GL_VERTEX_ARRAY_TYPE','%GL_VERTEX_ARRAY_TYPE_EXT','%GL_VIEWPORT','%GL_VIEWPORT_BIT','%GL_WIN_SWAP_HINT',
+            '%GL_XOR','%GL_ZERO','%GL_ZOOM_X','%GL_ZOOM_Y','%GRAY','%GREEN','%GWLP_HINSTANCE','%GWLP_HWNDPARENT',
+            '%GWLP_ID','%GWLP_USERDATA','%GWLP_WNDPROC','%GWL_EXSTYLE','%GWL_HINSTANCE','%GWL_HWNDPARENT','%GWL_ID','%GWL_STYLE',
+            '%GWL_USERDATA','%GWL_WNDPROC','%HDM_FIRST','%HTCAPTION','%HWND_BOTTOM','%HWND_DESKTOP','%HWND_MESSAGE','%HWND_NOTOPMOST',
+            '%HWND_TOP','%HWND_TOPMOST','%ICRYPTO_XOR_DECREASE','%ICRYPTO_XOR_INCREASE','%ICRYPTO_XOR_NORMAL','%IDABORT','%IDCANCEL','%IDCONTINUE',
+            '%IDIGNORE','%IDNO','%IDOK','%IDRETRY','%IDTIMEOUT','%IDTRYAGAIN','%IDYES','%INTERNET_CONNECTION_CONFIGURED',
+            '%INTERNET_CONNECTION_LAN','%INTERNET_CONNECTION_MODEM','%INTERNET_CONNECTION_MODEM_BUSY','%INTERNET_CONNECTION_OFFLINE','%INTERNET_CONNECTION_PROXY','%INTERNET_RAS_INSTALLED','%LBN_DBLCLK','%LBN_KILLFOCUS',
+            '%LBN_SELCANCEL','%LBN_SELCHANGE','%LBN_SETFOCUS','%LBS_DISABLENOSCROLL','%LBS_EXTENDEDSEL','%LBS_MULTICOLUMN','%LBS_MULTIPLESEL','%LBS_NOINTEGRALHEIGHT',
+            '%LBS_NOSEL','%LBS_NOTIFY','%LBS_SORT','%LBS_STANDARD','%LBS_USETABSTOPS','%LB_ADDFILE','%LB_ADDSTRING','%LB_DELETESTRING',
+            '%LB_DIR','%LB_FINDSTRING','%LB_FINDSTRINGEXACT','%LB_GETANCHORINDEX','%LB_GETCARETINDEX','%LB_GETCOUNT','%LB_GETCURSEL','%LB_GETHORIZONTALEXTENT',
+            '%LB_GETITEMDATA','%LB_GETITEMHEIGHT','%LB_GETITEMRECT','%LB_GETLISTBOXINFO','%LB_GETLOCALE','%LB_GETSEL','%LB_GETSELCOUNT','%LB_GETSELITEMS',
+            '%LB_GETTEXT','%LB_GETTEXTLEN','%LB_GETTOPINDEX','%LB_INITSTORAGE','%LB_INSERTSTRING','%LB_ITEMFROMPOINT','%LB_MULTIPLEADDSTRING','%LB_RESETCONTENT',
+            '%LB_SELECTSTRING','%LB_SELITEMRANGE','%LB_SELITEMRANGEEX','%LB_SETANCHORINDEX','%LB_SETCARETINDEX','%LB_SETCOLUMNWIDTH','%LB_SETCOUNT','%LB_SETCURSEL',
+            '%LB_SETHORIZONTALEXTENT','%LB_SETITEMDATA','%LB_SETITEMHEIGHT','%LB_SETLOCALE','%LB_SETSEL','%LB_SETTABSTOPS','%LB_SETTOPINDEX','%LF_FACESIZE',
+            '%LTGRAY','%LVM_FIRST','%LWA_ALPHA','%LWA_COLORKEY','%MAGENTA','%MAXBYTE','%MAXCHAR','%MAXDWORD',
+            '%MAXSHORT','%MAXWORD','%MAX_PATH','%MB_ABORTRETRYIGNORE','%MB_APPLMODAL','%MB_CANCELTRYCONTINUE','%MB_DEFBUTTON1','%MB_DEFBUTTON2',
+            '%MB_DEFBUTTON3','%MB_HELP','%MB_ICONASTERISK','%MB_ICONERROR','%MB_ICONEXCLAMATION','%MB_ICONHAND','%MB_ICONINFORMATION','%MB_ICONQUESTION',
+            '%MB_ICONSTOP','%MB_ICONWARNING','%MB_OK','%MB_OKCANCEL','%MB_RETRYCANCEL','%MB_SIMPLE','%MB_SYSTEMMODAL','%MB_TOPMOST',
+            '%MB_YESNO','%MB_YESNOCANCEL','%MF_CHECKED','%MF_DISABLED','%MF_ENABLED','%MF_GRAYED','%MF_SEPARATOR','%MF_UNCHECKED',
+            '%MINCHAR','%MINLONG','%MINSHORT','%NULL','%ODBC352_INC','%ODBCVER','%ODBC_ADD_DSN','%ODBC_ADD_SYS_DSN',
+            '%ODBC_BOTH_DSN','%ODBC_CONFIG_DRIVER','%ODBC_CONFIG_DRIVER_MAX','%ODBC_CONFIG_DSN','%ODBC_CONFIG_SYS_DSN','%ODBC_DRIVER_VERSION','%ODBC_ERROR_COMPONENT_NOT_FOUND','%ODBC_ERROR_CREATE_DSN_FAILED',
+            '%ODBC_ERROR_GENERAL_ERR','%ODBC_ERROR_INVALID_BUFF_LEN','%ODBC_ERROR_INVALID_DSN','%ODBC_ERROR_INVALID_HWND','%ODBC_ERROR_INVALID_INF','%ODBC_ERROR_INVALID_KEYWORD_VALUE','%ODBC_ERROR_INVALID_LOG_FILE','%ODBC_ERROR_INVALID_NAME',
+            '%ODBC_ERROR_INVALID_PARAM_SEQUENCE','%ODBC_ERROR_INVALID_PATH','%ODBC_ERROR_INVALID_REQUEST_TYPE','%ODBC_ERROR_INVALID_STR','%ODBC_ERROR_LOAD_LIB_FAILED','%ODBC_ERROR_OUTPUT_STRING_TRUNCATED','%ODBC_ERROR_OUT_OF_MEM','%ODBC_ERROR_REMOVE_DSN_FAILED',
+            '%ODBC_ERROR_REQUEST_FAILED','%ODBC_ERROR_USAGE_UPDATE_FAILED','%ODBC_ERROR_USER_CANCELED','%ODBC_ERROR_WRITING_SYSINFO_FAILED','%ODBC_INSTALL_COMPLETE','%ODBC_INSTALL_DRIVER','%ODBC_INSTALL_INQUIRY','%ODBC_REMOVE_DEFAULT_DSN',
+            '%ODBC_REMOVE_DRIVER','%ODBC_REMOVE_DSN','%ODBC_REMOVE_SYS_DSN','%ODBC_SYSTEM_DSN','%ODBC_USER_DSN','%OFN_ALLOWMULTISELECT','%OFN_CREATEPROMPT','%OFN_ENABLEHOOK',
+            '%OFN_ENABLEINCLUDENOTIFY','%OFN_ENABLESIZING','%OFN_ENABLETEMPLATE','%OFN_ENABLETEMPLATEHANDLE','%OFN_EXPLORER','%OFN_EXTENSIONDIFFERENT','%OFN_FILEMUSTEXIST','%OFN_HIDEREADONLY',
+            '%OFN_LONGNAMES','%OFN_NOCHANGEDIR','%OFN_NODEREFERENCELINKS','%OFN_NOLONGNAMES','%OFN_NONETWORKBUTTON','%OFN_NOREADONLYRETURN','%OFN_NOTESTFILECREATE','%OFN_NOVALIDATE',
+            '%OFN_OVERWRITEPROMPT','%OFN_PATHMUSTEXIST','%OFN_READONLY','%OFN_SHAREAWARE','%OFN_SHOWHELP','%OS_ERROR_CALLFUNCTION','%OS_ERROR_EMPTYSTRING','%OS_ERROR_LOADLIBRARY',
+            '%OS_ERROR_SUCCESS','%OS_ERROR_WRONGPARAMETER','%OS_SHELL_ASYNC','%OS_SHELL_SYNC','%OS_WINDOWS_2K','%OS_WINDOWS_95','%OS_WINDOWS_95_OSR2','%OS_WINDOWS_98',
+            '%OS_WINDOWS_98_SE','%OS_WINDOWS_ME','%OS_WINDOWS_NT','%OS_WINDOWS_SERVER_2003','%OS_WINDOWS_SERVER_LONGHORN','%OS_WINDOWS_SERVER_LONGHORN_DC','%OS_WINDOWS_VISTA','%OS_WINDOWS_XP',
+            '%OS_WNDSTYLE_HIDE','%OS_WNDSTYLE_MAXIMIZED','%OS_WNDSTYLE_MINIMIZED','%OS_WNDSTYLE_MINIMIZEDNOFOCUS','%OS_WNDSTYLE_NORMAL','%OS_WNDSTYLE_NORMALNOFOCUS','%PATH_EXT','%PATH_FILE',
+            '%PATH_FILEEXT','%PATH_ROOT','%PATH_ROOTPATH','%PATH_ROOTPATHPROG','%PATH_ROOTPATHPROGEXT','%PBM_DELTAPOS','%PBM_GETPOS','%PBM_GETRANGE',
+            '%PBM_SETBARCOLOR','%PBM_SETBKCOLOR','%PBM_SETPOS','%PBM_SETRANGE','%PBM_SETRANGE32','%PBM_SETSTEP','%PBM_STEPIT','%PBS_SMOOTH',
+            '%PBS_VERTICAL','%PC_DISABLEWAKEEVENT_OFF','%PC_DISABLEWAKEEVENT_ON','%PC_EB_NOCONFIRMATION','%PC_EB_NOPROGRESSUI','%PC_EB_NORMAL','%PC_EB_NOSOUND','%PC_FORCECRITICAL_OFF',
+            '%PC_FORCECRITICAL_ON','%PC_HIBERNATE_OFF','%PC_HIBERNATE_ON','%PC_RD_FORCE','%PC_RD_FORCEIFHUNG','%PC_RD_LOGOFF','%PC_RD_POWEROFF','%PC_RD_REBOOT',
+            '%PC_RD_SHUTDOWN','%PC_SD_DONOT_FORCE','%PC_SD_DONOT_REBOOT','%PC_SD_FORCE','%PC_SD_REBOOT','%PFA_CENTER','%PFA_LEFT','%PFA_RIGHT',
+            '%PF_3DNOW_INSTRUCTIONS_AVAILABLE','%PF_CHANNELS_ENABLED','%PF_COMPARE64_EXCHANGE128','%PF_COMPARE_EXCHANGE128','%PF_COMPARE_EXCHANGE_DOUBLE','%PF_FLOATING_POINT_EMULATED','%PF_FLOATING_POINT_PRECISION_ERRATA','%PF_MMX_INSTRUCTIONS_AVAILABLE',
+            '%PF_NX_ENABLED','%PF_PAE_ENABLED','%PF_RDTSC_INSTRUCTION_AVAILABLE','%PF_SSE3_INSTRUCTIONS_AVAILABLE','%PF_XMMI64_INSTRUCTIONS_AVAILABLE','%PF_XMMI_INSTRUCTIONS_AVAILABLE','%PGM_FIRST','%RED',
+            '%RTF_UBB','%SAPI_SVSFDEFAULT','%SAPI_SVSFISFILENAME','%SAPI_SVSFISNOTXML','%SAPI_SVSFISXML','%SAPI_SVSFLAGSASYNC','%SAPI_SVSFNLPMASK','%SAPI_SVSFNLPSPEAKPUNC',
+            '%SAPI_SVSFPERSISTXML','%SAPI_SVSFPURGEBEFORESPEAK','%SAPI_SVSFUNUSEDFLAGS','%SAPI_SVSFVOICEMASK','%SBS_SIZEGRIP','%SB_BOTTOM','%SB_ENDSCROLL','%SB_LEFT',
+            '%SB_LINEDOWN','%SB_LINELEFT','%SB_LINERIGHT','%SB_LINEUP','%SB_PAGEDOWN','%SB_PAGELEFT','%SB_PAGERIGHT','%SB_PAGEUP',
+            '%SB_RIGHT','%SB_SETPARTS','%SB_SETTEXT','%SB_THUMBPOSITION','%SB_THUMBTRACK','%SB_TOP','%SCF_ALL','%SCF_ASSOCIATEFONT',
+            '%SCF_DEFAULT','%SCF_NOKBUPDATE','%SCF_SELECTION','%SCF_USEUIRULES','%SCF_WORD','%SC_CLOSE','%SC_CONTEXTHELP','%SC_HOTKEY',
+            '%SC_HSCROLL','%SC_KEYMENU','%SC_MAXIMIZE','%SC_MINIMIZE','%SC_MONITORPOWER','%SC_MOUSEMENU','%SC_MOVE','%SC_NEXTWINDOW',
+            '%SC_PREVWINDOW','%SC_RESTORE','%SC_SCREENSAVE','%SC_SIZE','%SC_TASKLIST','%SC_VSCROLL','%SERVICE_ACTIVE','%SERVICE_AUTO_START',
+            '%SERVICE_BOOT_START','%SERVICE_CONTINUE_PENDING','%SERVICE_DEMAND_START','%SERVICE_DISABLED','%SERVICE_DRIVER','%SERVICE_INACTIVE','%SERVICE_INFO_DISPLAY_NAME','%SERVICE_INFO_NAME',
+            '%SERVICE_PAUSED','%SERVICE_PAUSE_PENDING','%SERVICE_RUNNING','%SERVICE_START_PENDING','%SERVICE_STATE_ALL','%SERVICE_STOPPED','%SERVICE_STOP_PENDING','%SERVICE_SYSTEM_START',
+            '%SERVICE_TYPE_ALL','%SERVICE_WIN32','%SES_ALLOWBEEPS','%SES_BEEPONMAXTEXT','%SES_BIDI','%SES_EMULATE10','%SES_EMULATESYSEDIT','%SES_EXTENDBACKCOLOR',
+            '%SES_LOWERCASE','%SES_MAPCPS','%SES_NOIME','%SES_NOINPUTSEQUENCECHK','%SES_SCROLLONKILLFOCUS','%SES_UPPERCASE','%SES_USEAIMM','%SES_USECRLF',
+            '%SES_XLTCRCRLFTOCR','%SF_RTF','%SF_TEXT','%SMTP_SET_ATTACH_CONTENT_TYPE','%SMTP_SET_CONTENT_TYPE_PREFIX','%SQL_AA_FALSE','%SQL_AA_TRUE','%SQL_ACCESSIBLE_PROCEDURES',
+            '%SQL_ACCESSIBLE_TABLES','%SQL_ACCESS_MODE','%SQL_ACTIVE_CONNECTIONS','%SQL_ACTIVE_ENVIRONMENTS','%SQL_ACTIVE_STATEMENTS','%SQL_ADD','%SQL_AD_ADD_CONSTRAINT_DEFERRABLE','%SQL_AD_ADD_CONSTRAINT_INITIALLY_DEFERRED',
+            '%SQL_AD_ADD_CONSTRAINT_INITIALLY_IMMEDIATE','%SQL_AD_ADD_CONSTRAINT_NON_DEFERRABLE','%SQL_AD_ADD_DOMAIN_CONSTRAINT','%SQL_AD_ADD_DOMAIN_DEFAULT','%SQL_AD_CONSTRAINT_NAME_DEFINITION','%SQL_AD_DROP_DOMAIN_CONSTRAINT','%SQL_AD_DROP_DOMAIN_DEFAULT','%SQL_AF_ALL',
+            '%SQL_AF_AVG','%SQL_AF_COUNT','%SQL_AF_DISTINCT','%SQL_AF_MAX','%SQL_AF_MIN','%SQL_AF_SUM','%SQL_AGGREGATE_FUNCTIONS','%SQL_ALL_EXCEPT_LIKE',
+            '%SQL_ALL_TYPES','%SQL_ALTER_DOMAIN','%SQL_ALTER_TABLE','%SQL_AM_CONNECTION','%SQL_AM_NONE','%SQL_AM_STATEMENT','%SQL_API_ALL_FUNCTIONS','%SQL_API_LOADBYORDINAL',
+            '%SQL_API_ODBC3_ALL_FUNCTIONS','%SQL_API_ODBC3_ALL_FUNCTIONS_SIZE','%SQL_API_SQLALLOCCONNECT','%SQL_API_SQLALLOCENV','%SQL_API_SQLALLOCHANDLE','%SQL_API_SQLALLOCHANDLESTD','%SQL_API_SQLALLOCSTMT','%SQL_API_SQLBINDCOL',
+            '%SQL_API_SQLBINDPARAM','%SQL_API_SQLBINDPARAMETER','%SQL_API_SQLBROWSECONNECT','%SQL_API_SQLBULKOPERATIONS','%SQL_API_SQLCANCEL','%SQL_API_SQLCLOSECURSOR','%SQL_API_SQLCOLATTRIBUTE','%SQL_API_SQLCOLATTRIBUTES',
+            '%SQL_API_SQLCOLUMNPRIVILEGES','%SQL_API_SQLCOLUMNS','%SQL_API_SQLCONNECT','%SQL_API_SQLCOPYDESC','%SQL_API_SQLDATASOURCES','%SQL_API_SQLDESCRIBECOL','%SQL_API_SQLDESCRIBEPARAM','%SQL_API_SQLDISCONNECT',
+            '%SQL_API_SQLDRIVERCONNECT','%SQL_API_SQLDRIVERS','%SQL_API_SQLENDTRAN','%SQL_API_SQLERROR','%SQL_API_SQLEXECDIRECT','%SQL_API_SQLEXECUTE','%SQL_API_SQLEXTENDEDFETCH','%SQL_API_SQLFETCH',
+            '%SQL_API_SQLFETCHSCROLL','%SQL_API_SQLFOREIGNKEYS','%SQL_API_SQLFREECONNECT','%SQL_API_SQLFREEENV','%SQL_API_SQLFREEHANDLE','%SQL_API_SQLFREESTMT','%SQL_API_SQLGETCONNECTATTR','%SQL_API_SQLGETCONNECTOPTION',
+            '%SQL_API_SQLGETCURSORNAME','%SQL_API_SQLGETDATA','%SQL_API_SQLGETDESCFIELD','%SQL_API_SQLGETDESCREC','%SQL_API_SQLGETDIAGFIELD','%SQL_API_SQLGETDIAGREC','%SQL_API_SQLGETENVATTR','%SQL_API_SQLGETFUNCTIONS',
+            '%SQL_API_SQLGETINFO','%SQL_API_SQLGETSTMTATTR','%SQL_API_SQLGETSTMTOPTION','%SQL_API_SQLGETTYPEINFO','%SQL_API_SQLMORERESULTS','%SQL_API_SQLNATIVESQL','%SQL_API_SQLNUMPARAMS','%SQL_API_SQLNUMRESULTCOLS',
+            '%SQL_API_SQLPARAMDATA','%SQL_API_SQLPARAMOPTIONS','%SQL_API_SQLPREPARE','%SQL_API_SQLPRIMARYKEYS','%SQL_API_SQLPROCEDURECOLUMNS','%SQL_API_SQLPROCEDURES','%SQL_API_SQLPUTDATA','%SQL_API_SQLROWCOUNT',
+            '%SQL_API_SQLSETCONNECTATTR','%SQL_API_SQLSETCONNECTOPTION','%SQL_API_SQLSETCURSORNAME','%SQL_API_SQLSETDESCFIELD','%SQL_API_SQLSETDESCREC','%SQL_API_SQLSETENVATTR','%SQL_API_SQLSETPARAM','%SQL_API_SQLSETPOS',
+            '%SQL_API_SQLSETSCROLLOPTIONS','%SQL_API_SQLSETSTMTATTR','%SQL_API_SQLSETSTMTOPTION','%SQL_API_SQLSPECIALCOLUMNS','%SQL_API_SQLSTATISTICS','%SQL_API_SQLTABLEPRIVILEGES','%SQL_API_SQLTABLES','%SQL_API_SQLTRANSACT',
+            '%SQL_ARD_TYPE','%SQL_ASYNC_ENABLE','%SQL_ASYNC_ENABLE_DEFAULT','%SQL_ASYNC_ENABLE_OFF','%SQL_ASYNC_ENABLE_ON','%SQL_ASYNC_MODE','%SQL_ATTR_ACCESS_MODE','%SQL_ATTR_ANSI_APP',
+            '%SQL_ATTR_APP_PARAM_DESC','%SQL_ATTR_APP_ROW_DESC','%SQL_ATTR_ASYNC_ENABLE','%SQL_ATTR_AUTOCOMMIT','%SQL_ATTR_AUTO_IPD','%SQL_ATTR_CONCURRENCY','%SQL_ATTR_CONNECTION_DEAD','%SQL_ATTR_CONNECTION_POOLING',
+            '%SQL_ATTR_CONNECTION_TIMEOUT','%SQL_ATTR_CP_MATCH','%SQL_ATTR_CURRENT_CATALOG','%SQL_ATTR_CURSOR_SCROLLABLE','%SQL_ATTR_CURSOR_SENSITIVITY','%SQL_ATTR_CURSOR_TYPE','%SQL_ATTR_DISCONNECT_BEHAVIOR','%SQL_ATTR_ENABLE_AUTO_IPD',
+            '%SQL_ATTR_ENLIST_IN_DTC','%SQL_ATTR_ENLIST_IN_XA','%SQL_ATTR_FETCH_BOOKMARK_PTR','%SQL_ATTR_IMP_PARAM_DESC','%SQL_ATTR_IMP_ROW_DESC','%SQL_ATTR_KEYSET_SIZE','%SQL_ATTR_LOGIN_TIMEOUT','%SQL_ATTR_MAX_LENGTH',
+            '%SQL_ATTR_MAX_ROWS','%SQL_ATTR_METADATA_ID','%SQL_ATTR_NOSCAN','%SQL_ATTR_ODBC_CURSORS','%SQL_ATTR_ODBC_VERSION','%SQL_ATTR_OUTPUT_NTS','%SQL_ATTR_PACKET_SIZE','%SQL_ATTR_PARAMSET_SIZE',
+            '%SQL_ATTR_PARAMS_PROCESSED_PTR','%SQL_ATTR_PARAM_BIND_OFFSET_PTR','%SQL_ATTR_PARAM_BIND_TYPE','%SQL_ATTR_PARAM_OPERATION_PTR','%SQL_ATTR_PARAM_STATUS_PTR','%SQL_ATTR_QUERY_TIMEOUT','%SQL_ATTR_QUIET_MODE','%SQL_ATTR_READONLY',
+            '%SQL_ATTR_READWRITE_UNKNOWN','%SQL_ATTR_RETRIEVE_DATA','%SQL_ATTR_ROWS_FETCHED_PTR','%SQL_ATTR_ROW_ARRAY_SIZE','%SQL_ATTR_ROW_BIND_OFFSET_PTR','%SQL_ATTR_ROW_BIND_TYPE','%SQL_ATTR_ROW_NUMBER','%SQL_ATTR_ROW_OPERATION_PTR',
+            '%SQL_ATTR_ROW_STATUS_PTR','%SQL_ATTR_SIMULATE_CURSOR','%SQL_ATTR_TRACE','%SQL_ATTR_TRACEFILE','%SQL_ATTR_TRANSLATE_LIB','%SQL_ATTR_TRANSLATE_OPTION','%SQL_ATTR_TXN_ISOLATION','%SQL_ATTR_USE_BOOKMARKS',
+            '%SQL_ATTR_WRITE','%SQL_AT_ADD_COLUMN','%SQL_AT_ADD_COLUMN_COLLATION','%SQL_AT_ADD_COLUMN_DEFAULT','%SQL_AT_ADD_COLUMN_SINGLE','%SQL_AT_ADD_CONSTRAINT','%SQL_AT_ADD_TABLE_CONSTRAINT','%SQL_AT_CONSTRAINT_DEFERRABLE',
+            '%SQL_AT_CONSTRAINT_INITIALLY_DEFERRED','%SQL_AT_CONSTRAINT_INITIALLY_IMMEDIATE','%SQL_AT_CONSTRAINT_NAME_DEFINITION','%SQL_AT_CONSTRAINT_NON_DEFERRABLE','%SQL_AT_DROP_COLUMN','%SQL_AT_DROP_COLUMN_CASCADE','%SQL_AT_DROP_COLUMN_DEFAULT','%SQL_AT_DROP_COLUMN_RESTRICT',
+            '%SQL_AT_DROP_TABLE_CONSTRAINT_CASCADE','%SQL_AT_DROP_TABLE_CONSTRAINT_RESTRICT','%SQL_AT_SET_COLUMN_DEFAULT','%SQL_AUTOCOMMIT','%SQL_AUTOCOMMIT_DEFAULT','%SQL_AUTOCOMMIT_OFF','%SQL_AUTOCOMMIT_ON','%SQL_BATCH_ROW_COUNT',
+            '%SQL_BATCH_SUPPORT','%SQL_BEST_ROWID','%SQL_BIGINT','%SQL_BINARY','%SQL_BIND_BY_COLUMN','%SQL_BIND_TYPE','%SQL_BIND_TYPE_DEFAULT','%SQL_BIT',
+            '%SQL_BOOKMARK_PERSISTENCE','%SQL_BP_CLOSE','%SQL_BP_DELETE','%SQL_BP_DROP','%SQL_BP_OTHER_HSTMT','%SQL_BP_SCROLL','%SQL_BP_TRANSACTION','%SQL_BP_UPDATE',
+            '%SQL_BRC_EXPLICIT','%SQL_BRC_PROCEDURES','%SQL_BRC_ROLLED_UP','%SQL_BS_ROW_COUNT_EXPLICIT','%SQL_BS_ROW_COUNT_PROC','%SQL_BS_SELECT_EXPLICIT','%SQL_BS_SELECT_PROC','%SQL_CA1_ABSOLUTE',
+            '%SQL_CA1_BOOKMARK','%SQL_CA1_BULK_ADD','%SQL_CA1_BULK_DELETE_BY_BOOKMARK','%SQL_CA1_BULK_FETCH_BY_BOOKMARK','%SQL_CA1_BULK_UPDATE_BY_BOOKMARK','%SQL_CA1_LOCK_EXCLUSIVE','%SQL_CA1_LOCK_NO_CHANGE','%SQL_CA1_LOCK_UNLOCK',
+            '%SQL_CA1_NEXT','%SQL_CA1_POSITIONED_DELETE','%SQL_CA1_POSITIONED_UPDATE','%SQL_CA1_POS_DELETE','%SQL_CA1_POS_POSITION','%SQL_CA1_POS_REFRESH','%SQL_CA1_POS_UPDATE','%SQL_CA1_RELATIVE',
+            '%SQL_CA1_SELECT_FOR_UPDATE','%SQL_CA2_CRC_APPROXIMATE','%SQL_CA2_CRC_EXACT','%SQL_CA2_LOCK_CONCURRENCY','%SQL_CA2_MAX_ROWS_AFFECTS_ALL','%SQL_CA2_MAX_ROWS_CATALOG','%SQL_CA2_MAX_ROWS_DELETE','%SQL_CA2_MAX_ROWS_INSERT',
+            '%SQL_CA2_MAX_ROWS_SELECT','%SQL_CA2_MAX_ROWS_UPDATE','%SQL_CA2_OPT_ROWVER_CONCURRENCY','%SQL_CA2_OPT_VALUES_CONCURRENCY','%SQL_CA2_READ_ONLY_CONCURRENCY','%SQL_CA2_SENSITIVITY_ADDITIONS','%SQL_CA2_SENSITIVITY_DELETIONS','%SQL_CA2_SENSITIVITY_UPDATES',
+            '%SQL_CA2_SIMULATE_NON_UNIQUE','%SQL_CA2_SIMULATE_TRY_UNIQUE','%SQL_CA2_SIMULATE_UNIQUE','%SQL_CASCADE','%SQL_CATALOG_LOCATION','%SQL_CATALOG_NAME','%SQL_CATALOG_NAME_SEPARATOR','%SQL_CATALOG_TERM',
+            '%SQL_CATALOG_USAGE','%SQL_CA_CONSTRAINT_DEFERRABLE','%SQL_CA_CONSTRAINT_INITIALLY_DEFERRED','%SQL_CA_CONSTRAINT_INITIALLY_IMMEDIATE','%SQL_CA_CONSTRAINT_NON_DEFERRABLE','%SQL_CA_CREATE_ASSERTION','%SQL_CB_CLOSE','%SQL_CB_DELETE',
+            '%SQL_CB_NON_NULL','%SQL_CB_NULL','%SQL_CB_PRESERVE','%SQL_CCOL_CREATE_COLLATION','%SQL_CCS_COLLATE_CLAUSE','%SQL_CCS_CREATE_CHARACTER_SET','%SQL_CCS_LIMITED_COLLATION','%SQL_CC_CLOSE',
+            '%SQL_CC_DELETE','%SQL_CC_PRESERVE','%SQL_CDO_COLLATION','%SQL_CDO_CONSTRAINT','%SQL_CDO_CONSTRAINT_DEFERRABLE','%SQL_CDO_CONSTRAINT_INITIALLY_DEFERRED','%SQL_CDO_CONSTRAINT_INITIALLY_IMMEDIATE','%SQL_CDO_CONSTRAINT_NAME_DEFINITION',
+            '%SQL_CDO_CONSTRAINT_NON_DEFERRABLE','%SQL_CDO_CREATE_DOMAIN','%SQL_CDO_DEFAULT','%SQL_CD_FALSE','%SQL_CD_TRUE','%SQL_CHAR','%SQL_CLOSE','%SQL_CL_END',
+            '%SQL_CL_START','%SQL_CN_ANY','%SQL_CN_DIFFERENT','%SQL_CN_NONE','%SQL_CODE_DATE','%SQL_CODE_DAY','%SQL_CODE_DAY_TO_HOUR','%SQL_CODE_DAY_TO_MINUTE',
+            '%SQL_CODE_DAY_TO_SECOND','%SQL_CODE_HOUR','%SQL_CODE_HOUR_TO_MINUTE','%SQL_CODE_HOUR_TO_SECOND','%SQL_CODE_MINUTE','%SQL_CODE_MINUTE_TO_SECOND','%SQL_CODE_MONTH','%SQL_CODE_SECOND',
+            '%SQL_CODE_TIME','%SQL_CODE_TIMESTAMP','%SQL_CODE_YEAR','%SQL_CODE_YEAR_TO_MONTH','%SQL_COLATT_OPT_MAX','%SQL_COLATT_OPT_MIN','%SQL_COLLATION_SEQ','%SQL_COLUMN_ALIAS',
+            '%SQL_COLUMN_AUTO_INCREMENT','%SQL_COLUMN_CASE_SENSITIVE','%SQL_COLUMN_COUNT','%SQL_COLUMN_DISPLAY_SIZE','%SQL_COLUMN_IGNORE','%SQL_COLUMN_LABEL','%SQL_COLUMN_LENGTH','%SQL_COLUMN_MONEY',
+            '%SQL_COLUMN_NAME','%SQL_COLUMN_NULLABLE','%SQL_COLUMN_NUMBER_UNKNOWN','%SQL_COLUMN_OWNER_NAME','%SQL_COLUMN_PRECISION','%SQL_COLUMN_QUALIFIER_NAME','%SQL_COLUMN_SCALE','%SQL_COLUMN_SEARCHABLE',
+            '%SQL_COLUMN_TABLE_NAME','%SQL_COLUMN_TYPE','%SQL_COLUMN_TYPE_NAME','%SQL_COLUMN_UNSIGNED','%SQL_COLUMN_UPDATABLE','%SQL_COL_PRED_BASIC','%SQL_COL_PRED_CHAR','%SQL_COMMIT',
+            '%SQL_CONCAT_NULL_BEHAVIOR','%SQL_CONCURRENCY','%SQL_CONCUR_DEFAULT','%SQL_CONCUR_LOCK','%SQL_CONCUR_READ_ONLY','%SQL_CONCUR_ROWVER','%SQL_CONCUR_TIMESTAMP','%SQL_CONCUR_VALUES',
+            '%SQL_CONVERT_BIGINT','%SQL_CONVERT_BINARY','%SQL_CONVERT_BIT','%SQL_CONVERT_CHAR','%SQL_CONVERT_DATE','%SQL_CONVERT_DECIMAL','%SQL_CONVERT_DOUBLE','%SQL_CONVERT_FLOAT',
+            '%SQL_CONVERT_FUNCTIONS','%SQL_CONVERT_GUID','%SQL_CONVERT_INTEGER','%SQL_CONVERT_INTERVAL_DAY_TIME','%SQL_CONVERT_INTERVAL_YEAR_MONTH','%SQL_CONVERT_LONGVARBINARY','%SQL_CONVERT_LONGVARCHAR','%SQL_CONVERT_NUMERIC',
+            '%SQL_CONVERT_REAL','%SQL_CONVERT_SMALLINT','%SQL_CONVERT_TIME','%SQL_CONVERT_TIMESTAMP','%SQL_CONVERT_TINYINT','%SQL_CONVERT_VARBINARY','%SQL_CONVERT_VARCHAR','%SQL_CONVERT_WCHAR',
+            '%SQL_CONVERT_WLONGVARCHAR','%SQL_CONVERT_WVARCHAR','%SQL_CORRELATION_NAME','%SQL_CP_DEFAULT','%SQL_CP_MATCH_DEFAULT','%SQL_CP_OFF','%SQL_CP_ONE_PER_DRIVER','%SQL_CP_ONE_PER_HENV',
+            '%SQL_CP_RELAXED_MATCH','%SQL_CP_STRICT_MATCH','%SQL_CREATE_ASSERTION','%SQL_CREATE_CHARACTER_SET','%SQL_CREATE_COLLATION','%SQL_CREATE_DOMAIN','%SQL_CREATE_SCHEMA','%SQL_CREATE_TABLE',
+            '%SQL_CREATE_TRANSLATION','%SQL_CREATE_VIEW','%SQL_CR_CLOSE','%SQL_CR_DELETE','%SQL_CR_PRESERVE','%SQL_CS_AUTHORIZATION','%SQL_CS_CREATE_SCHEMA','%SQL_CS_DEFAULT_CHARACTER_SET',
+            '%SQL_CTR_CREATE_TRANSLATION','%SQL_CT_COLUMN_COLLATION','%SQL_CT_COLUMN_CONSTRAINT','%SQL_CT_COLUMN_DEFAULT','%SQL_CT_COMMIT_DELETE','%SQL_CT_COMMIT_PRESERVE','%SQL_CT_CONSTRAINT_DEFERRABLE','%SQL_CT_CONSTRAINT_INITIALLY_DEFERRED',
+            '%SQL_CT_CONSTRAINT_INITIALLY_IMMEDIATE','%SQL_CT_CONSTRAINT_NAME_DEFINITION','%SQL_CT_CONSTRAINT_NON_DEFERRABLE','%SQL_CT_CREATE_TABLE','%SQL_CT_GLOBAL_TEMPORARY','%SQL_CT_LOCAL_TEMPORARY','%SQL_CT_TABLE_CONSTRAINT','%SQL_CURRENT_QUALIFIER',
+            '%SQL_CURSOR_COMMIT_BEHAVIOR','%SQL_CURSOR_DYNAMIC','%SQL_CURSOR_FORWARD_ONLY','%SQL_CURSOR_KEYSET_DRIVEN','%SQL_CURSOR_ROLLBACK_BEHAVIOR','%SQL_CURSOR_SENSITIVITY','%SQL_CURSOR_STATIC','%SQL_CURSOR_TYPE',
+            '%SQL_CURSOR_TYPE_DEFAULT','%SQL_CUR_DEFAULT','%SQL_CUR_USE_DRIVER','%SQL_CUR_USE_IF_NEEDED','%SQL_CUR_USE_ODBC','%SQL_CU_DML_STATEMENTS','%SQL_CU_INDEX_DEFINITION','%SQL_CU_PRIVILEGE_DEFINITION',
+            '%SQL_CU_PROCEDURE_INVOCATION','%SQL_CU_TABLE_DEFINITION','%SQL_CVT_BIGINT','%SQL_CVT_BINARY','%SQL_CVT_BIT','%SQL_CVT_CHAR','%SQL_CVT_DATE','%SQL_CVT_DECIMAL',
+            '%SQL_CVT_DOUBLE','%SQL_CVT_FLOAT','%SQL_CVT_GUID','%SQL_CVT_INTEGER','%SQL_CVT_INTERVAL_DAY_TIME','%SQL_CVT_INTERVAL_YEAR_MONTH','%SQL_CVT_LONGVARBINARY','%SQL_CVT_LONGVARCHAR',
+            '%SQL_CVT_NUMERIC','%SQL_CVT_REAL','%SQL_CVT_SMALLINT','%SQL_CVT_TIME','%SQL_CVT_TIMESTAMP','%SQL_CVT_TINYINT','%SQL_CVT_VARBINARY','%SQL_CVT_VARCHAR',
+            '%SQL_CVT_WCHAR','%SQL_CVT_WLONGVARCHAR','%SQL_CVT_WVARCHAR','%SQL_CV_CASCADED','%SQL_CV_CHECK_OPTION','%SQL_CV_CREATE_VIEW','%SQL_CV_LOCAL','%SQL_C_BINARY',
+            '%SQL_C_BIT','%SQL_C_BOOKMARK','%SQL_C_CHAR','%SQL_C_DATE','%SQL_C_DEFAULT','%SQL_C_DOUBLE','%SQL_C_FLOAT','%SQL_C_GUID',
+            '%SQL_C_INTERVAL_DAY','%SQL_C_INTERVAL_DAY_TO_HOUR','%SQL_C_INTERVAL_DAY_TO_MINUTE','%SQL_C_INTERVAL_DAY_TO_SECOND','%SQL_C_INTERVAL_HOUR','%SQL_C_INTERVAL_HOUR_TO_MINUTE','%SQL_C_INTERVAL_HOUR_TO_SECOND','%SQL_C_INTERVAL_MINUTE',
+            '%SQL_C_INTERVAL_MINUTE_TO_SECOND','%SQL_C_INTERVAL_MONTH','%SQL_C_INTERVAL_SECOND','%SQL_C_INTERVAL_YEAR','%SQL_C_INTERVAL_YEAR_TO_MONTH','%SQL_C_LONG','%SQL_C_NUMERIC','%SQL_C_SBIGINT',
+            '%SQL_C_SHORT','%SQL_C_SLONG','%SQL_C_SSHORT','%SQL_C_STINYINT','%SQL_C_TIME','%SQL_C_TIMESTAMP','%SQL_C_TINYINT','%SQL_C_TYPE_DATE',
+            '%SQL_C_TYPE_TIME','%SQL_C_TYPE_TIMESTAMP','%SQL_C_UBIGINT','%SQL_C_ULONG','%SQL_C_USHORT','%SQL_C_UTINYINT','%SQL_C_VARBOOKMARK','%SQL_DATABASE_NAME',
+            '%SQL_DATA_AT_EXEC','%SQL_DATA_SOURCE_NAME','%SQL_DATA_SOURCE_READ_ONLY','%SQL_DATE','%SQL_DATETIME','%SQL_DATETIME_LITERALS','%SQL_DATE_LEN','%SQL_DAY',
+            '%SQL_DAY_TO_HOUR','%SQL_DAY_TO_MINUTE','%SQL_DAY_TO_SECOND','%SQL_DA_DROP_ASSERTION','%SQL_DBMS_NAME','%SQL_DBMS_VER','%SQL_DB_DEFAULT','%SQL_DB_DISCONNECT',
+            '%SQL_DB_RETURN_TO_POOL','%SQL_DCS_DROP_CHARACTER_SET','%SQL_DC_DROP_COLLATION','%SQL_DDL_INDEX','%SQL_DD_CASCADE','%SQL_DD_DROP_DOMAIN','%SQL_DD_RESTRICT','%SQL_DECIMAL',
+            '%SQL_DEFAULT','%SQL_DEFAULT_PARAM','%SQL_DEFAULT_TXN_ISOLATION','%SQL_DELETE','%SQL_DELETE_BY_BOOKMARK','%SQL_DESCRIBE_PARAMETER','%SQL_DESC_ALLOC_AUTO','%SQL_DESC_ALLOC_TYPE',
+            '%SQL_DESC_ALLOC_USER','%SQL_DESC_ARRAY_SIZE','%SQL_DESC_ARRAY_STATUS_PTR','%SQL_DESC_AUTO_UNIQUE_VALUE','%SQL_DESC_BASE_COLUMN_NAME','%SQL_DESC_BASE_TABLE_NAME','%SQL_DESC_BIND_OFFSET_PTR','%SQL_DESC_BIND_TYPE',
+            '%SQL_DESC_CASE_SENSITIVE','%SQL_DESC_CATALOG_NAME','%SQL_DESC_CONCISE_TYPE','%SQL_DESC_COUNT','%SQL_DESC_DATA_PTR','%SQL_DESC_DATETIME_INTERVAL_CODE','%SQL_DESC_DATETIME_INTERVAL_PRECISION','%SQL_DESC_DISPLAY_SIZE',
+            '%SQL_DESC_FIXED_PREC_SCALE','%SQL_DESC_INDICATOR_PTR','%SQL_DESC_LABEL','%SQL_DESC_LENGTH','%SQL_DESC_LITERAL_PREFIX','%SQL_DESC_LITERAL_SUFFIX','%SQL_DESC_LOCAL_TYPE_NAME','%SQL_DESC_MAXIMUM_SCALE',
+            '%SQL_DESC_MINIMUM_SCALE','%SQL_DESC_NAME','%SQL_DESC_NULLABLE','%SQL_DESC_NUM_PREC_RADIX','%SQL_DESC_OCTET_LENGTH','%SQL_DESC_OCTET_LENGTH_PTR','%SQL_DESC_PARAMETER_TYPE','%SQL_DESC_PRECISION',
+            '%SQL_DESC_ROWS_PROCESSED_PTR','%SQL_DESC_SCALE','%SQL_DESC_SCHEMA_NAME','%SQL_DESC_SEARCHABLE','%SQL_DESC_TABLE_NAME','%SQL_DESC_TYPE','%SQL_DESC_TYPE_NAME','%SQL_DESC_UNNAMED',
+            '%SQL_DESC_UNSIGNED','%SQL_DESC_UPDATABLE','%SQL_DIAG_ALTER_TABLE','%SQL_DIAG_CALL','%SQL_DIAG_CLASS_ORIGIN','%SQL_DIAG_COLUMN_NUMBER','%SQL_DIAG_CONNECTION_NAME','%SQL_DIAG_CREATE_INDEX',
+            '%SQL_DIAG_CREATE_TABLE','%SQL_DIAG_CREATE_VIEW','%SQL_DIAG_CURSOR_ROW_COUNT','%SQL_DIAG_DELETE_WHERE','%SQL_DIAG_DROP_INDEX','%SQL_DIAG_DROP_TABLE','%SQL_DIAG_DROP_VIEW','%SQL_DIAG_DYNAMIC_DELETE_CURSOR',
+            '%SQL_DIAG_DYNAMIC_FUNCTION','%SQL_DIAG_DYNAMIC_FUNCTION_CODE','%SQL_DIAG_DYNAMIC_UPDATE_CURSOR','%SQL_DIAG_GRANT','%SQL_DIAG_INSERT','%SQL_DIAG_MESSAGE_TEXT','%SQL_DIAG_NATIVE','%SQL_DIAG_NUMBER',
+            '%SQL_DIAG_RETURNCODE','%SQL_DIAG_REVOKE','%SQL_DIAG_ROW_COUNT','%SQL_DIAG_ROW_NUMBER','%SQL_DIAG_SELECT_CURSOR','%SQL_DIAG_SERVER_NAME','%SQL_DIAG_SQLSTATE','%SQL_DIAG_SUBCLASS_ORIGIN',
+            '%SQL_DIAG_UNKNOWN_STATEMENT','%SQL_DIAG_UPDATE_WHERE','%SQL_DI_CREATE_INDEX','%SQL_DI_DROP_INDEX','%SQL_DL_SQL92_DATE','%SQL_DL_SQL92_INTERVAL_DAY','%SQL_DL_SQL92_INTERVAL_DAY_TO_HOUR','%SQL_DL_SQL92_INTERVAL_DAY_TO_MINUTE',
+            '%SQL_DL_SQL92_INTERVAL_DAY_TO_SECOND','%SQL_DL_SQL92_INTERVAL_HOUR','%SQL_DL_SQL92_INTERVAL_HOUR_TO_MINUTE','%SQL_DL_SQL92_INTERVAL_HOUR_TO_SECOND','%SQL_DL_SQL92_INTERVAL_MINUTE','%SQL_DL_SQL92_INTERVAL_MINUTE_TO_SECOND','%SQL_DL_SQL92_INTERVAL_MONTH','%SQL_DL_SQL92_INTERVAL_SECOND',
+            '%SQL_DL_SQL92_INTERVAL_YEAR','%SQL_DL_SQL92_INTERVAL_YEAR_TO_MONTH','%SQL_DL_SQL92_TIME','%SQL_DL_SQL92_TIMESTAMP','%SQL_DM_VER','%SQL_DOUBLE','%SQL_DRIVER_COMPLETE','%SQL_DRIVER_COMPLETE_REQUIRED',
+            '%SQL_DRIVER_HDBC','%SQL_DRIVER_HDESC','%SQL_DRIVER_HENV','%SQL_DRIVER_HLIB','%SQL_DRIVER_HSTMT','%SQL_DRIVER_NAME','%SQL_DRIVER_NOPROMPT','%SQL_DRIVER_ODBC_VER',
+            '%SQL_DRIVER_PROMPT','%SQL_DRIVER_VER','%SQL_DROP','%SQL_DROP_ASSERTION','%SQL_DROP_CHARACTER_SET','%SQL_DROP_COLLATION','%SQL_DROP_DOMAIN','%SQL_DROP_SCHEMA',
+            '%SQL_DROP_TABLE','%SQL_DROP_TRANSLATION','%SQL_DROP_VIEW','%SQL_DS_CASCADE','%SQL_DS_DROP_SCHEMA','%SQL_DS_RESTRICT','%SQL_DTC_DONE','%SQL_DTC_ENLIST_EXPENSIVE',
+            '%SQL_DTC_TRANSITION_COST','%SQL_DTC_UNENLIST_EXPENSIVE','%SQL_DTR_DROP_TRANSLATION','%SQL_DT_CASCADE','%SQL_DT_DROP_TABLE','%SQL_DT_RESTRICT','%SQL_DV_CASCADE','%SQL_DV_DROP_VIEW',
+            '%SQL_DV_RESTRICT','%SQL_DYNAMIC_CURSOR_ATTRIBUTES1','%SQL_DYNAMIC_CURSOR_ATTRIBUTES2','%SQL_ENSURE','%SQL_ENTIRE_ROWSET','%SQL_ERROR','%SQL_EXPRESSIONS_IN_ORDERBY','%SQL_FALSE',
+            '%SQL_FD_FETCH_ABSOLUTE','%SQL_FD_FETCH_BOOKMARK','%SQL_FD_FETCH_FIRST','%SQL_FD_FETCH_LAST','%SQL_FD_FETCH_NEXT','%SQL_FD_FETCH_PREV','%SQL_FD_FETCH_PRIOR','%SQL_FD_FETCH_RELATIVE',
+            '%SQL_FETCH_ABSOLUTE','%SQL_FETCH_BOOKMARK','%SQL_FETCH_BY_BOOKMARK','%SQL_FETCH_DIRECTION','%SQL_FETCH_FIRST','%SQL_FETCH_FIRST_SYSTEM','%SQL_FETCH_FIRST_USER','%SQL_FETCH_LAST',
+            '%SQL_FETCH_NEXT','%SQL_FETCH_PREV','%SQL_FETCH_PRIOR','%SQL_FETCH_RELATIVE','%SQL_FILE_CATALOG','%SQL_FILE_NOT_SUPPORTED','%SQL_FILE_QUALIFIER','%SQL_FILE_TABLE',
+            '%SQL_FILE_USAGE','%SQL_FLOAT','%SQL_FN_CVT_CAST','%SQL_FN_CVT_CONVERT','%SQL_FN_NUM_ABS','%SQL_FN_NUM_ACOS','%SQL_FN_NUM_ASIN','%SQL_FN_NUM_ATAN',
+            '%SQL_FN_NUM_ATAN2','%SQL_FN_NUM_CEILING','%SQL_FN_NUM_COS','%SQL_FN_NUM_COT','%SQL_FN_NUM_DEGREES','%SQL_FN_NUM_EXP','%SQL_FN_NUM_FLOOR','%SQL_FN_NUM_LOG',
+            '%SQL_FN_NUM_LOG10','%SQL_FN_NUM_MOD','%SQL_FN_NUM_PI','%SQL_FN_NUM_POWER','%SQL_FN_NUM_RADIANS','%SQL_FN_NUM_RAND','%SQL_FN_NUM_ROUND','%SQL_FN_NUM_SIGN',
+            '%SQL_FN_NUM_SIN','%SQL_FN_NUM_SQRT','%SQL_FN_NUM_TAN','%SQL_FN_NUM_TRUNCATE','%SQL_FN_STR_ASCII','%SQL_FN_STR_BIT_LENGTH','%SQL_FN_STR_CHAR','%SQL_FN_STR_CHARACTER_LENGTH',
+            '%SQL_FN_STR_CHAR_LENGTH','%SQL_FN_STR_CONCAT','%SQL_FN_STR_DIFFERENCE','%SQL_FN_STR_INSERT','%SQL_FN_STR_LCASE','%SQL_FN_STR_LEFT','%SQL_FN_STR_LENGTH','%SQL_FN_STR_LOCATE',
+            '%SQL_FN_STR_LOCATE_2','%SQL_FN_STR_LTRIM','%SQL_FN_STR_OCTET_LENGTH','%SQL_FN_STR_POSITION','%SQL_FN_STR_REPEAT','%SQL_FN_STR_REPLACE','%SQL_FN_STR_RIGHT','%SQL_FN_STR_RTRIM',
+            '%SQL_FN_STR_SOUNDEX','%SQL_FN_STR_SPACE','%SQL_FN_STR_SUBSTRING','%SQL_FN_STR_UCASE','%SQL_FN_SYS_DBNAME','%SQL_FN_SYS_IFNULL','%SQL_FN_SYS_USERNAME','%SQL_FN_TD_CURDATE',
+            '%SQL_FN_TD_CURRENT_DATE','%SQL_FN_TD_CURRENT_TIME','%SQL_FN_TD_CURRENT_TIMESTAMP','%SQL_FN_TD_CURTIME','%SQL_FN_TD_DAYNAME','%SQL_FN_TD_DAYOFMONTH','%SQL_FN_TD_DAYOFWEEK','%SQL_FN_TD_DAYOFYEAR',
+            '%SQL_FN_TD_EXTRACT','%SQL_FN_TD_HOUR','%SQL_FN_TD_MINUTE','%SQL_FN_TD_MONTH','%SQL_FN_TD_MONTHNAME','%SQL_FN_TD_NOW','%SQL_FN_TD_QUARTER','%SQL_FN_TD_SECOND',
+            '%SQL_FN_TD_TIMESTAMPADD','%SQL_FN_TD_TIMESTAMPDIFF','%SQL_FN_TD_WEEK','%SQL_FN_TD_YEAR','%SQL_FN_TSI_DAY','%SQL_FN_TSI_FRAC_SECOND','%SQL_FN_TSI_HOUR','%SQL_FN_TSI_MINUTE',
+            '%SQL_FN_TSI_MONTH','%SQL_FN_TSI_QUARTER','%SQL_FN_TSI_SECOND','%SQL_FN_TSI_WEEK','%SQL_FN_TSI_YEAR','%SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1','%SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2','%SQL_GB_COLLATE',
+            '%SQL_GB_GROUP_BY_CONTAINS_SELECT','%SQL_GB_GROUP_BY_EQUALS_SELECT','%SQL_GB_NOT_SUPPORTED','%SQL_GB_NO_RELATION','%SQL_GD_ANY_COLUMN','%SQL_GD_ANY_ORDER','%SQL_GD_BLOCK','%SQL_GD_BOUND',
+            '%SQL_GETDATA_EXTENSIONS','%SQL_GET_BOOKMARK','%SQL_GROUP_BY','%SQL_GUID','%SQL_HANDLE_DBC','%SQL_HANDLE_DESC','%SQL_HANDLE_ENV','%SQL_HANDLE_SENV',
+            '%SQL_HANDLE_STMT','%SQL_HOUR','%SQL_HOUR_TO_MINUTE','%SQL_HOUR_TO_SECOND','%SQL_IC_LOWER','%SQL_IC_MIXED','%SQL_IC_SENSITIVE','%SQL_IC_UPPER',
+            '%SQL_IDENTIFIER_CASE','%SQL_IDENTIFIER_QUOTE_CHAR','%SQL_IGNORE','%SQL_IK_ALL','%SQL_IK_ASC','%SQL_IK_DESC','%SQL_IK_NONE','%SQL_INDEX_ALL',
+            '%SQL_INDEX_CLUSTERED','%SQL_INDEX_HASHED','%SQL_INDEX_KEYWORDS','%SQL_INDEX_OTHER','%SQL_INDEX_UNIQUE','%SQL_INFO_FIRST','%SQL_INFO_SCHEMA_VIEWS','%SQL_INITIALLY_DEFERRED',
+            '%SQL_INITIALLY_IMMEDIATE','%SQL_INSENSITIVE','%SQL_INSERT_STATEMENT','%SQL_INTEGER','%SQL_INTEGRITY','%SQL_INTERVAL','%SQL_INTERVAL_DAY','%SQL_INTERVAL_DAY_TO_HOUR',
+            '%SQL_INTERVAL_DAY_TO_MINUTE','%SQL_INTERVAL_DAY_TO_SECOND','%SQL_INTERVAL_HOUR','%SQL_INTERVAL_HOUR_TO_MINUTE','%SQL_INTERVAL_HOUR_TO_SECOND','%SQL_INTERVAL_MINUTE','%SQL_INTERVAL_MINUTE_TO_SECOND','%SQL_INTERVAL_MONTH',
+            '%SQL_INTERVAL_SECOND','%SQL_INTERVAL_YEAR','%SQL_INTERVAL_YEAR_TO_MONTH','%SQL_INVALID_HANDLE','%SQL_ISV_ASSERTIONS','%SQL_ISV_CHARACTER_SETS','%SQL_ISV_CHECK_CONSTRAINTS','%SQL_ISV_COLLATIONS',
+            '%SQL_ISV_COLUMNS','%SQL_ISV_COLUMN_DOMAIN_USAGE','%SQL_ISV_COLUMN_PRIVILEGES','%SQL_ISV_CONSTRAINT_COLUMN_USAGE','%SQL_ISV_CONSTRAINT_TABLE_USAGE','%SQL_ISV_DOMAINS','%SQL_ISV_DOMAIN_CONSTRAINTS','%SQL_ISV_KEY_COLUMN_USAGE',
+            '%SQL_ISV_REFERENTIAL_CONSTRAINTS','%SQL_ISV_SCHEMATA','%SQL_ISV_SQL_LANGUAGES','%SQL_ISV_TABLES','%SQL_ISV_TABLE_CONSTRAINTS','%SQL_ISV_TABLE_PRIVILEGES','%SQL_ISV_TRANSLATIONS','%SQL_ISV_USAGE_PRIVILEGES',
+            '%SQL_ISV_VIEWS','%SQL_ISV_VIEW_COLUMN_USAGE','%SQL_ISV_VIEW_TABLE_USAGE','%SQL_IS_DAY','%SQL_IS_DAY_TO_HOUR','%SQL_IS_DAY_TO_MINUTE','%SQL_IS_DAY_TO_SECOND','%SQL_IS_HOUR',
+            '%SQL_IS_HOUR_TO_MINUTE','%SQL_IS_HOUR_TO_SECOND','%SQL_IS_INSERT_LITERALS','%SQL_IS_INSERT_SEARCHED','%SQL_IS_INTEGER','%SQL_IS_MINUTE','%SQL_IS_MINUTE_TO_SECOND','%SQL_IS_MONTH',
+            '%SQL_IS_POINTER','%SQL_IS_SECOND','%SQL_IS_SELECT_INTO','%SQL_IS_SMALLINT','%SQL_IS_UINTEGER','%SQL_IS_USMALLINT','%SQL_IS_YEAR','%SQL_IS_YEAR_TO_MONTH',
+            '%SQL_KEYSET_CURSOR_ATTRIBUTES1','%SQL_KEYSET_CURSOR_ATTRIBUTES2','%SQL_KEYSET_SIZE','%SQL_KEYSET_SIZE_DEFAULT','%SQL_KEYWORDS','%SQL_LCK_EXCLUSIVE','%SQL_LCK_NO_CHANGE','%SQL_LCK_UNLOCK',
+            '%SQL_LEN_BINARY_ATTR_OFFSET','%SQL_LEN_DATA_AT_EXEC_OFFSET','%SQL_LIKE_ESCAPE_CLAUSE','%SQL_LIKE_ONLY','%SQL_LOCK_EXCLUSIVE','%SQL_LOCK_NO_CHANGE','%SQL_LOCK_TYPES','%SQL_LOCK_UNLOCK',
+            '%SQL_LOGIN_TIMEOUT','%SQL_LOGIN_TIMEOUT_DEFAULT','%SQL_LONGVARBINARY','%SQL_LONGVARCHAR','%SQL_MAXIMUM_CATALOG_NAME_LENGTH','%SQL_MAXIMUM_COLUMNS_IN_GROUP_BY','%SQL_MAXIMUM_COLUMNS_IN_INDEX','%SQL_MAXIMUM_COLUMNS_IN_ORDER_BY',
+            '%SQL_MAXIMUM_COLUMNS_IN_SELECT','%SQL_MAXIMUM_COLUMN_NAME_LENGTH','%SQL_MAXIMUM_CONCURRENT_ACTIVITIES','%SQL_MAXIMUM_CURSOR_NAME_LENGTH','%SQL_MAXIMUM_DRIVER_CONNECTIONS','%SQL_MAXIMUM_IDENTIFIER_LENGTH','%SQL_MAXIMUM_INDEX_SIZE','%SQL_MAXIMUM_ROW_SIZE',
+            '%SQL_MAXIMUM_SCHEMA_NAME_LENGTH','%SQL_MAXIMUM_STATEMENT_LENGTH','%SQL_MAXIMUM_TABLES_IN_SELECT','%SQL_MAXIMUM_USER_NAME_LENGTH','%SQL_MAX_ASYNC_CONCURRENT_STATEMENTS','%SQL_MAX_BINARY_LITERAL_LEN','%SQL_MAX_CATALOG_NAME_LEN','%SQL_MAX_CHAR_LITERAL_LEN',
+            '%SQL_MAX_COLUMNS_IN_GROUP_BY','%SQL_MAX_COLUMNS_IN_INDEX','%SQL_MAX_COLUMNS_IN_ORDER_BY','%SQL_MAX_COLUMNS_IN_SELECT','%SQL_MAX_COLUMNS_IN_TABLE','%SQL_MAX_COLUMN_NAME_LEN','%SQL_MAX_CONCURRENT_ACTIVITIES','%SQL_MAX_CURSOR_NAME_LEN',
+            '%SQL_MAX_DRIVER_CONNECTIONS','%SQL_MAX_DSN_LENGTH','%SQL_MAX_IDENTIFIER_LEN','%SQL_MAX_INDEX_SIZE','%SQL_MAX_LENGTH','%SQL_MAX_LENGTH_DEFAULT','%SQL_MAX_MESSAGE_LENGTH','%SQL_MAX_NUMERIC_LEN',
+            '%SQL_MAX_OPTION_STRING_LENGTH','%SQL_MAX_OWNER_NAME_LEN','%SQL_MAX_PROCEDURE_NAME_LEN','%SQL_MAX_QUALIFIER_NAME_LEN','%SQL_MAX_ROWS','%SQL_MAX_ROWS_DEFAULT','%SQL_MAX_ROW_SIZE','%SQL_MAX_ROW_SIZE_INCLUDES_LONG',
+            '%SQL_MAX_SCHEMA_NAME_LEN','%SQL_MAX_STATEMENT_LEN','%SQL_MAX_TABLES_IN_SELECT','%SQL_MAX_TABLE_NAME_LEN','%SQL_MAX_USER_NAME_LEN','%SQL_MINUTE','%SQL_MINUTE_TO_SECOND','%SQL_MODE_DEFAULT',
+            '%SQL_MODE_READ_ONLY','%SQL_MODE_READ_WRITE','%SQL_MONTH','%SQL_MULTIPLE_ACTIVE_TXN','%SQL_MULT_RESULT_SETS','%SQL_NAMED','%SQL_NC_END','%SQL_NC_HIGH',
+            '%SQL_NC_LOW','%SQL_NC_START','%SQL_NEED_DATA','%SQL_NEED_LONG_DATA_LEN','%SQL_NNC_NON_NULL','%SQL_NNC_NULL','%SQL_NONSCROLLABLE','%SQL_NON_NULLABLE_COLUMNS',
+            '%SQL_NOSCAN','%SQL_NOSCAN_DEFAULT','%SQL_NOSCAN_OFF','%SQL_NOSCAN_ON','%SQL_NOT_DEFERRABLE','%SQL_NO_ACTION','%SQL_NO_COLUMN_NUMBER','%SQL_NO_DATA',
+            '%SQL_NO_DATA_FOUND','%SQL_NO_NULLS','%SQL_NO_ROW_NUMBER','%SQL_NO_TOTAL','%SQL_NTS','%SQL_NTSL','%SQL_NULLABLE','%SQL_NULLABLE_UNKNOWN',
+            '%SQL_NULL_COLLATION','%SQL_NULL_DATA','%SQL_NULL_HANDLE','%SQL_NULL_HDBC','%SQL_NULL_HDESC','%SQL_NULL_HENV','%SQL_NULL_HSTMT','%SQL_NUMERIC',
+            '%SQL_NUMERIC_FUNCTIONS','%SQL_OAC_LEVEL1','%SQL_OAC_LEVEL2','%SQL_OAC_NONE','%SQL_ODBC_API_CONFORMANCE','%SQL_ODBC_CURSORS','%SQL_ODBC_INTERFACE_CONFORMANCE','%SQL_ODBC_SAG_CLI_CONFORMANCE',
+            '%SQL_ODBC_SQL_CONFORMANCE','%SQL_ODBC_SQL_OPT_IEF','%SQL_ODBC_VER','%SQL_OIC_CORE','%SQL_OIC_LEVEL1','%SQL_OIC_LEVEL2','%SQL_OJ_ALL_COMPARISON_OPS','%SQL_OJ_CAPABILITIES',
+            '%SQL_OJ_FULL','%SQL_OJ_INNER','%SQL_OJ_LEFT','%SQL_OJ_NESTED','%SQL_OJ_NOT_ORDERED','%SQL_OJ_RIGHT','%SQL_OPT_TRACE','%SQL_OPT_TRACEFILE',
+            '%SQL_OPT_TRACE_DEFAULT','%SQL_OPT_TRACE_OFF','%SQL_OPT_TRACE_ON','%SQL_ORDER_BY_COLUMNS_IN_SELECT','%SQL_OSCC_COMPLIANT','%SQL_OSCC_NOT_COMPLIANT','%SQL_OSC_CORE','%SQL_OSC_EXTENDED',
+            '%SQL_OSC_MINIMUM','%SQL_OUTER_JOINS','%SQL_OUTER_JOIN_CAPABILITIES','%SQL_OU_DML_STATEMENTS','%SQL_OU_INDEX_DEFINITION','%SQL_OU_PRIVILEGE_DEFINITION','%SQL_OU_PROCEDURE_INVOCATION','%SQL_OU_TABLE_DEFINITION',
+            '%SQL_OV_ODBC2','%SQL_OV_ODBC3','%SQL_OWNER_TERM','%SQL_OWNER_USAGE','%SQL_PACKET_SIZE','%SQL_PARAM_ARRAY_ROW_COUNTS','%SQL_PARAM_ARRAY_SELECTS','%SQL_PARAM_BIND_BY_COLUMN',
+            '%SQL_PARAM_BIND_TYPE_DEFAULT','%SQL_PARAM_DIAG_UNAVAILABLE','%SQL_PARAM_ERROR','%SQL_PARAM_IGNORE','%SQL_PARAM_INPUT','%SQL_PARAM_INPUT_OUTPUT','%SQL_PARAM_OUTPUT','%SQL_PARAM_PROCEED',
+            '%SQL_PARAM_SUCCESS','%SQL_PARAM_SUCCESS_WITH_INFO','%SQL_PARAM_TYPE_DEFAULT','%SQL_PARAM_TYPE_UNKNOWN','%SQL_PARAM_UNUSED','%SQL_PARC_BATCH','%SQL_PARC_NO_BATCH','%SQL_PAS_BATCH',
+            '%SQL_PAS_NO_BATCH','%SQL_PAS_NO_SELECT','%SQL_PC_NON_PSEUDO','%SQL_PC_NOT_PSEUDO','%SQL_PC_PSEUDO','%SQL_PC_UNKNOWN','%SQL_POSITION','%SQL_POSITIONED_STATEMENTS',
+            '%SQL_POS_ADD','%SQL_POS_DELETE','%SQL_POS_OPERATIONS','%SQL_POS_POSITION','%SQL_POS_REFRESH','%SQL_POS_UPDATE','%SQL_PRED_BASIC','%SQL_PRED_CHAR',
+            '%SQL_PRED_NONE','%SQL_PRED_SEARCHABLE','%SQL_PROCEDURES','%SQL_PROCEDURE_TERM','%SQL_PS_POSITIONED_DELETE','%SQL_PS_POSITIONED_UPDATE','%SQL_PS_SELECT_FOR_UPDATE','%SQL_PT_FUNCTION',
+            '%SQL_PT_PROCEDURE','%SQL_PT_UNKNOWN','%SQL_QL_END','%SQL_QL_START','%SQL_QUALIFIER_LOCATION','%SQL_QUALIFIER_NAME_SEPARATOR','%SQL_QUALIFIER_TERM','%SQL_QUALIFIER_USAGE',
+            '%SQL_QUERY_TIMEOUT','%SQL_QUERY_TIMEOUT_DEFAULT','%SQL_QUICK','%SQL_QUIET_MODE','%SQL_QUOTED_IDENTIFIER_CASE','%SQL_QU_DML_STATEMENTS','%SQL_QU_INDEX_DEFINITION','%SQL_QU_PRIVILEGE_DEFINITION',
+            '%SQL_QU_PROCEDURE_INVOCATION','%SQL_QU_TABLE_DEFINITION','%SQL_RD_DEFAULT','%SQL_RD_OFF','%SQL_RD_ON','%SQL_REAL','%SQL_REFRESH','%SQL_RESET_PARAMS',
+            '%SQL_RESTRICT','%SQL_RESULT_COL','%SQL_RETRIEVE_DATA','%SQL_RETURN_VALUE','%SQL_ROLLBACK','%SQL_ROWSET_SIZE','%SQL_ROWSET_SIZE_DEFAULT','%SQL_ROWVER',
+            '%SQL_ROW_ADDED','%SQL_ROW_DELETED','%SQL_ROW_ERROR','%SQL_ROW_IDENTIFIER','%SQL_ROW_IGNORE','%SQL_ROW_NOROW','%SQL_ROW_NUMBER','%SQL_ROW_NUMBER_UNKNOWN',
+            '%SQL_ROW_PROCEED','%SQL_ROW_SUCCESS','%SQL_ROW_SUCCESS_WITH_INFO','%SQL_ROW_UPDATED','%SQL_ROW_UPDATES','%SQL_SCCO_LOCK','%SQL_SCCO_OPT_ROWVER','%SQL_SCCO_OPT_TIMESTAMP',
+            '%SQL_SCCO_OPT_VALUES','%SQL_SCCO_READ_ONLY','%SQL_SCC_ISO92_CLI','%SQL_SCC_XOPEN_CLI_VERSION1','%SQL_SCHEMA_TERM','%SQL_SCHEMA_USAGE','%SQL_SCOPE_CURROW','%SQL_SCOPE_SESSION',
+            '%SQL_SCOPE_TRANSACTION','%SQL_SCROLLABLE','%SQL_SCROLL_CONCURRENCY','%SQL_SCROLL_DYNAMIC','%SQL_SCROLL_FORWARD_ONLY','%SQL_SCROLL_KEYSET_DRIVEN','%SQL_SCROLL_OPTIONS','%SQL_SCROLL_STATIC',
+            '%SQL_SC_FIPS127_2_TRANSITIONAL','%SQL_SC_NON_UNIQUE','%SQL_SC_SQL92_ENTRY','%SQL_SC_SQL92_FULL','%SQL_SC_SQL92_INTERMEDIATE','%SQL_SC_TRY_UNIQUE','%SQL_SC_UNIQUE','%SQL_SDF_CURRENT_DATE',
+            '%SQL_SDF_CURRENT_TIME','%SQL_SDF_CURRENT_TIMESTAMP','%SQL_SEARCHABLE','%SQL_SEARCH_PATTERN_ESCAPE','%SQL_SECOND','%SQL_SENSITIVE','%SQL_SERVER_NAME','%SQL_SETPARAM_VALUE_MAX',
+            '%SQL_SETPOS_MAX_LOCK_VALUE','%SQL_SETPOS_MAX_OPTION_VALUE','%SQL_SET_DEFAULT','%SQL_SET_NULL','%SQL_SFKD_CASCADE','%SQL_SFKD_NO_ACTION','%SQL_SFKD_SET_DEFAULT','%SQL_SFKD_SET_NULL',
+            '%SQL_SFKU_CASCADE','%SQL_SFKU_NO_ACTION','%SQL_SFKU_SET_DEFAULT','%SQL_SFKU_SET_NULL','%SQL_SG_DELETE_TABLE','%SQL_SG_INSERT_COLUMN','%SQL_SG_INSERT_TABLE','%SQL_SG_REFERENCES_COLUMN',
+            '%SQL_SG_REFERENCES_TABLE','%SQL_SG_SELECT_TABLE','%SQL_SG_UPDATE_COLUMN','%SQL_SG_UPDATE_TABLE','%SQL_SG_USAGE_ON_CHARACTER_SET','%SQL_SG_USAGE_ON_COLLATION','%SQL_SG_USAGE_ON_DOMAIN','%SQL_SG_USAGE_ON_TRANSLATION',
+            '%SQL_SG_WITH_GRANT_OPTION','%SQL_SIGNED_OFFSET','%SQL_SIMULATE_CURSOR','%SQL_SMALLINT','%SQL_SNVF_BIT_LENGTH','%SQL_SNVF_CHARACTER_LENGTH','%SQL_SNVF_CHAR_LENGTH','%SQL_SNVF_EXTRACT',
+            '%SQL_SNVF_OCTET_LENGTH','%SQL_SNVF_POSITION','%SQL_SO_DYNAMIC','%SQL_SO_FORWARD_ONLY','%SQL_SO_KEYSET_DRIVEN','%SQL_SO_MIXED','%SQL_SO_STATIC','%SQL_SPECIAL_CHARACTERS',
+            '%SQL_SPEC_MAJOR','%SQL_SPEC_MINOR','%SQL_SP_BETWEEN','%SQL_SP_COMPARISON','%SQL_SP_EXISTS','%SQL_SP_IN','%SQL_SP_ISNOTNULL','%SQL_SP_ISNULL',
+            '%SQL_SP_LIKE','%SQL_SP_MATCH_FULL','%SQL_SP_MATCH_PARTIAL','%SQL_SP_MATCH_UNIQUE_FULL','%SQL_SP_MATCH_UNIQUE_PARTIAL','%SQL_SP_OVERLAPS','%SQL_SP_QUANTIFIED_COMPARISON','%SQL_SP_UNIQUE',
+            '%SQL_SQL92_DATETIME_FUNCTIONS','%SQL_SQL92_FOREIGN_KEY_DELETE_RULE','%SQL_SQL92_FOREIGN_KEY_UPDATE_RULE','%SQL_SQL92_GRANT','%SQL_SQL92_NUMERIC_VALUE_FUNCTIONS','%SQL_SQL92_PREDICATES','%SQL_SQL92_RELATIONAL_JOIN_OPERATORS','%SQL_SQL92_REVOKE',
+            '%SQL_SQL92_ROW_VALUE_CONSTRUCTOR','%SQL_SQL92_STRING_FUNCTIONS','%SQL_SQL92_VALUE_EXPRESSIONS','%SQL_SQLSTATE_SIZE','%SQL_SQL_CONFORMANCE','%SQL_SQ_COMPARISON','%SQL_SQ_CORRELATED_SUBQUERIES','%SQL_SQ_EXISTS',
+            '%SQL_SQ_IN','%SQL_SQ_QUANTIFIED','%SQL_SRJO_CORRESPONDING_CLAUSE','%SQL_SRJO_CROSS_JOIN','%SQL_SRJO_EXCEPT_JOIN','%SQL_SRJO_FULL_OUTER_JOIN','%SQL_SRJO_INNER_JOIN','%SQL_SRJO_INTERSECT_JOIN',
+            '%SQL_SRJO_LEFT_OUTER_JOIN','%SQL_SRJO_NATURAL_JOIN','%SQL_SRJO_RIGHT_OUTER_JOIN','%SQL_SRJO_UNION_JOIN','%SQL_SRVC_DEFAULT','%SQL_SRVC_NULL','%SQL_SRVC_ROW_SUBQUERY','%SQL_SRVC_VALUE_EXPRESSION',
+            '%SQL_SR_CASCADE','%SQL_SR_DELETE_TABLE','%SQL_SR_GRANT_OPTION_FOR','%SQL_SR_INSERT_COLUMN','%SQL_SR_INSERT_TABLE','%SQL_SR_REFERENCES_COLUMN','%SQL_SR_REFERENCES_TABLE','%SQL_SR_RESTRICT',
+            '%SQL_SR_SELECT_TABLE','%SQL_SR_UPDATE_COLUMN','%SQL_SR_UPDATE_TABLE','%SQL_SR_USAGE_ON_CHARACTER_SET','%SQL_SR_USAGE_ON_COLLATION','%SQL_SR_USAGE_ON_DOMAIN','%SQL_SR_USAGE_ON_TRANSLATION','%SQL_SSF_CONVERT',
+            '%SQL_SSF_LOWER','%SQL_SSF_SUBSTRING','%SQL_SSF_TRANSLATE','%SQL_SSF_TRIM_BOTH','%SQL_SSF_TRIM_LEADING','%SQL_SSF_TRIM_TRAILING','%SQL_SSF_UPPER','%SQL_SS_ADDITIONS',
+            '%SQL_SS_DELETIONS','%SQL_SS_UPDATES','%SQL_STANDARD_CLI_CONFORMANCE','%SQL_STATIC_CURSOR_ATTRIBUTES1','%SQL_STATIC_CURSOR_ATTRIBUTES2','%SQL_STATIC_SENSITIVITY','%SQL_STILL_EXECUTING','%SQL_STRING_FUNCTIONS',
+            '%SQL_SUBQUERIES','%SQL_SUCCESS','%SQL_SUCCESS_WITH_INFO','%SQL_SU_DML_STATEMENTS','%SQL_SU_INDEX_DEFINITION','%SQL_SU_PRIVILEGE_DEFINITION','%SQL_SU_PROCEDURE_INVOCATION','%SQL_SU_TABLE_DEFINITION',
+            '%SQL_SVE_CASE','%SQL_SVE_CAST','%SQL_SVE_COALESCE','%SQL_SVE_NULLIF','%SQL_SYSTEM_FUNCTIONS','%SQL_TABLE_STAT','%SQL_TABLE_TERM','%SQL_TC_ALL',
+            '%SQL_TC_DDL_COMMIT','%SQL_TC_DDL_IGNORE','%SQL_TC_DML','%SQL_TC_NONE','%SQL_TIME','%SQL_TIMEDATE_ADD_INTERVALS','%SQL_TIMEDATE_DIFF_INTERVALS','%SQL_TIMEDATE_FUNCTIONS',
+            '%SQL_TIMESTAMP','%SQL_TIMESTAMP_LEN','%SQL_TIME_LEN','%SQL_TINYINT','%SQL_TRANSACTION_CAPABLE','%SQL_TRANSACTION_ISOLATION_OPTION','%SQL_TRANSACTION_READ_COMMITTED','%SQL_TRANSACTION_READ_UNCOMMITTED',
+            '%SQL_TRANSACTION_REPEATABLE_READ','%SQL_TRANSACTION_SERIALIZABLE','%SQL_TRANSLATE_DLL','%SQL_TRANSLATE_OPTION','%SQL_TRUE','%SQL_TXN_CAPABLE','%SQL_TXN_ISOLATION','%SQL_TXN_ISOLATION_OPTION',
+            '%SQL_TXN_READ_COMMITTED','%SQL_TXN_READ_UNCOMMITTED','%SQL_TXN_REPEATABLE_READ','%SQL_TXN_SERIALIZABLE','%SQL_TYPE_DATE','%SQL_TYPE_NULL','%SQL_TYPE_TIME','%SQL_TYPE_TIMESTAMP',
+            '%SQL_UB_DEFAULT','%SQL_UB_FIXED','%SQL_UB_OFF','%SQL_UB_ON','%SQL_UB_VARIABLE','%SQL_UNBIND','%SQL_UNICODE','%SQL_UNICODE_CHAR',
+            '%SQL_UNICODE_LONGVARCHAR','%SQL_UNICODE_VARCHAR','%SQL_UNION','%SQL_UNION_STATEMENT','%SQL_UNKNOWN_TYPE','%SQL_UNNAMED','%SQL_UNSEARCHABLE','%SQL_UNSIGNED_OFFSET',
+            '%SQL_UNSPECIFIED','%SQL_UPDATE','%SQL_UPDATE_BY_BOOKMARK','%SQL_USER_NAME','%SQL_USE_BOOKMARKS','%SQL_US_UNION','%SQL_US_UNION_ALL','%SQL_U_UNION',
+            '%SQL_U_UNION_ALL','%SQL_VARBINARY','%SQL_VARCHAR','%SQL_XOPEN_CLI_YEAR','%SQL_YEAR','%SQL_YEAR_TO_MONTH','%SRCCOPY','%SS_BITMAP',
+            '%SS_BLACKFRAME','%SS_BLACKRECT','%SS_CENTER','%SS_CENTERIMAGE','%SS_ENDELLIPSIS','%SS_ETCHEDFRAME','%SS_ETCHEDHORZ','%SS_ETCHEDVERT',
+            '%SS_GRAYFRAME','%SS_GRAYRECT','%SS_LEFT','%SS_NOPREFIX','%SS_NOTIFY','%SS_NOWORDWRAP','%SS_PATHELLIPSIS','%SS_RIGHT',
+            '%SS_RIGHTJUST','%SS_SIMPLE','%SS_SUNKEN','%SS_WHITEFRAME','%SS_WHITERECT','%SS_WORDELLIPSIS','%STAT_FILL_FROM_MEMORY','%STAT_FILL_NATURAL',
+            '%STAT_FILL_NATURAL_ERASTONE','%STAT_FILL_NATURAL_EVEN','%STAT_FILL_NATURAL_FIBONACCI','%STAT_FILL_NATURAL_ODD','%STAT_FILL_WITH_NUMBER','%STAT_MINMAX_INDEX','%STAT_MINMAX_VALUE','%STAT_TYPE_BYTE',
+            '%STAT_TYPE_CURRENCY','%STAT_TYPE_DOUBLE','%STAT_TYPE_DWORD','%STAT_TYPE_EXT','%STAT_TYPE_INTEGER','%STAT_TYPE_LONG','%STAT_TYPE_QUAD','%STAT_TYPE_SINGLE',
+            '%STAT_TYPE_WORD','%SWP_ASYNCWINDOWPOS','%SWP_DEFERERASE','%SWP_DRAWFRAME','%SWP_FRAMECHANGED','%SWP_HIDEWINDOW','%SWP_NOACTIVATE','%SWP_NOCOPYBITS',
+            '%SWP_NOMOVE','%SWP_NOOWNERZORDER','%SWP_NOREDRAW','%SWP_NOREPOSITION','%SWP_NOSENDCHANGING','%SWP_NOSIZE','%SWP_NOZORDER','%SWP_SHOWWINDOW',
+            '%SW_FORCEMINIMIZE','%SW_HIDE','%SW_MAXIMIZE','%SW_MINIMIZE','%SW_NORMAL','%SW_RESTORE','%SW_SHOW','%SW_SHOWDEFAULT',
+            '%SW_SHOWMAXIMIZED','%SW_SHOWMINIMIZED','%SW_SHOWMINNOACTIVE','%SW_SHOWNA','%SW_SHOWNOACTIVATE','%SW_SHOWNORMAL','%TBASS_3DALG_DEFAULT','%TBASS_3DALG_FULL',
+            '%TBASS_3DALG_LIGHT','%TBASS_3DALG_OFF','%TBASS_3DMODE_NORMAL','%TBASS_3DMODE_OFF','%TBASS_3DMODE_RELATIVE','%TBASS_ACTIVE_PAUSED','%TBASS_ACTIVE_PLAYING','%TBASS_ACTIVE_STALLED',
+            '%TBASS_ACTIVE_STOPPED','%TBASS_CONFIG_3DALGORITHM','%TBASS_CONFIG_BUFFER','%TBASS_CONFIG_CURVE_PAN','%TBASS_CONFIG_CURVE_VOL','%TBASS_CONFIG_FLOATDSP','%TBASS_CONFIG_GVOL_MUSIC','%TBASS_CONFIG_GVOL_SAMPLE',
+            '%TBASS_CONFIG_GVOL_STREAM','%TBASS_CONFIG_MAXVOL','%TBASS_CONFIG_MP3_CODEC','%TBASS_CONFIG_NET_AGENT','%TBASS_CONFIG_NET_BUFFER','%TBASS_CONFIG_NET_PASSIVE','%TBASS_CONFIG_NET_PREBUF','%TBASS_CONFIG_NET_PROXY',
+            '%TBASS_CONFIG_NET_TIMEOUT','%TBASS_CONFIG_PAUSE_NOPLAY','%TBASS_CONFIG_UPDATEPERIOD','%TBASS_CTYPE_MUSIC_IT','%TBASS_CTYPE_MUSIC_MO3','%TBASS_CTYPE_MUSIC_MOD','%TBASS_CTYPE_MUSIC_MTM','%TBASS_CTYPE_MUSIC_S3M',
+            '%TBASS_CTYPE_MUSIC_XM','%TBASS_CTYPE_RECORD','%TBASS_CTYPE_SAMPLE','%TBASS_CTYPE_STREAM','%TBASS_CTYPE_STREAM_AIFF','%TBASS_CTYPE_STREAM_MP1','%TBASS_CTYPE_STREAM_MP2','%TBASS_CTYPE_STREAM_MP3',
+            '%TBASS_CTYPE_STREAM_OGG','%TBASS_CTYPE_STREAM_WAV','%TBASS_CTYPE_STREAM_WAV_FLOAT','%TBASS_CTYPE_STREAM_WAV_PCM','%TBASS_DATA_AVAILABLE','%TBASS_DATA_FFT1024','%TBASS_DATA_FFT2048','%TBASS_DATA_FFT4096',
+            '%TBASS_DATA_FFT512','%TBASS_DATA_FFT_INDIVIDUAL','%TBASS_DATA_FFT_NOWINDOW','%TBASS_DATA_FLOAT','%TBASS_DEVICE_3D','%TBASS_DEVICE_8BITS','%TBASS_DEVICE_LATENCY','%TBASS_DEVICE_MONO',
+            '%TBASS_DEVICE_NOSPEAKER','%TBASS_DEVICE_SPEAKERS','%TBASS_EAX_ENVIRONMENT_ALLEY','%TBASS_EAX_ENVIRONMENT_ARENA','%TBASS_EAX_ENVIRONMENT_AUDITORIUM','%TBASS_EAX_ENVIRONMENT_BATHROOM','%TBASS_EAX_ENVIRONMENT_CARPETEDHALLWAY','%TBASS_EAX_ENVIRONMENT_CAVE',
+            '%TBASS_EAX_ENVIRONMENT_CITY','%TBASS_EAX_ENVIRONMENT_CONCERTHALL','%TBASS_EAX_ENVIRONMENT_COUNT','%TBASS_EAX_ENVIRONMENT_DIZZY','%TBASS_EAX_ENVIRONMENT_DRUGGED','%TBASS_EAX_ENVIRONMENT_FOREST','%TBASS_EAX_ENVIRONMENT_GENERIC','%TBASS_EAX_ENVIRONMENT_HALLWAY',
+            '%TBASS_EAX_ENVIRONMENT_HANGAR','%TBASS_EAX_ENVIRONMENT_LIVINGROOM','%TBASS_EAX_ENVIRONMENT_MOUNTAINS','%TBASS_EAX_ENVIRONMENT_PADDEDCELL','%TBASS_EAX_ENVIRONMENT_PARKINGLOT','%TBASS_EAX_ENVIRONMENT_PLAIN','%TBASS_EAX_ENVIRONMENT_PSYCHOTIC','%TBASS_EAX_ENVIRONMENT_QUARRY',
+            '%TBASS_EAX_ENVIRONMENT_ROOM','%TBASS_EAX_ENVIRONMENT_SEWERPIPE','%TBASS_EAX_ENVIRONMENT_STONECORRIDOR','%TBASS_EAX_ENVIRONMENT_STONEROOM','%TBASS_EAX_ENVIRONMENT_UNDERWATER','%TBASS_ERROR_ALREADY','%TBASS_ERROR_BUFLOST','%TBASS_ERROR_CODEC',
+            '%TBASS_ERROR_CREATE','%TBASS_ERROR_DECODE','%TBASS_ERROR_DEVICE','%TBASS_ERROR_DRIVER','%TBASS_ERROR_DX','%TBASS_ERROR_EMPTY','%TBASS_ERROR_FILEFORM','%TBASS_ERROR_FILEOPEN',
+            '%TBASS_ERROR_FORMAT','%TBASS_ERROR_FREQ','%TBASS_ERROR_HANDLE','%TBASS_ERROR_ILLPARAM','%TBASS_ERROR_ILLTYPE','%TBASS_ERROR_INIT','%TBASS_ERROR_MEM','%TBASS_ERROR_NO3D',
+            '%TBASS_ERROR_NOCHAN','%TBASS_ERROR_NOEAX','%TBASS_ERROR_NOFX','%TBASS_ERROR_NOHW','%TBASS_ERROR_NONET','%TBASS_ERROR_NOPAUSE','%TBASS_ERROR_NOPLAY','%TBASS_ERROR_NOTAVAIL',
+            '%TBASS_ERROR_NOTFILE','%TBASS_ERROR_PLAYING','%TBASS_ERROR_POSITION','%TBASS_ERROR_SPEAKER','%TBASS_ERROR_START','%TBASS_ERROR_TIMEOUT','%TBASS_ERROR_UNKNOWN','%TBASS_ERROR_VERSION',
+            '%TBASS_FALSE','%TBASS_FILEPOS_CURRENT','%TBASS_FILEPOS_DECODE','%TBASS_FILEPOS_DOWNLOAD','%TBASS_FILEPOS_END','%TBASS_FILEPOS_START','%TBASS_FILE_CLOSE','%TBASS_FILE_LEN',
+            '%TBASS_FILE_READ','%TBASS_FILE_SEEK','%TBASS_FX_CHORUS','%TBASS_FX_COMPRESSOR','%TBASS_FX_DISTORTION','%TBASS_FX_ECHO','%TBASS_FX_FLANGER','%TBASS_FX_GARGLE',
+            '%TBASS_FX_I3DL2REVERB','%TBASS_FX_PARAMEQ','%TBASS_FX_PHASE_180','%TBASS_FX_PHASE_90','%TBASS_FX_PHASE_NEG_180','%TBASS_FX_PHASE_NEG_90','%TBASS_FX_PHASE_ZERO','%TBASS_FX_REVERB',
+            '%TBASS_INPUT_LEVEL','%TBASS_INPUT_OFF','%TBASS_INPUT_ON','%TBASS_INPUT_TYPE_ANALOG','%TBASS_INPUT_TYPE_AUX','%TBASS_INPUT_TYPE_CD','%TBASS_INPUT_TYPE_DIGITAL','%TBASS_INPUT_TYPE_LINE',
+            '%TBASS_INPUT_TYPE_MASK','%TBASS_INPUT_TYPE_MIC','%TBASS_INPUT_TYPE_PHONE','%TBASS_INPUT_TYPE_SPEAKER','%TBASS_INPUT_TYPE_SYNTH','%TBASS_INPUT_TYPE_UNDEF','%TBASS_INPUT_TYPE_WAVE','%TBASS_MP3_SETPOS',
+            '%TBASS_MUSIC_3D','%TBASS_MUSIC_ATTRIB_AMPLIFY','%TBASS_MUSIC_ATTRIB_BPM','%TBASS_MUSIC_ATTRIB_PANSEP','%TBASS_MUSIC_ATTRIB_PSCALER','%TBASS_MUSIC_ATTRIB_SPEED','%TBASS_MUSIC_ATTRIB_VOL_CHAN','%TBASS_MUSIC_ATTRIB_VOL_GLOBAL',
+            '%TBASS_MUSIC_ATTRIB_VOL_INST','%TBASS_MUSIC_AUTOFREE','%TBASS_MUSIC_CALCLEN','%TBASS_MUSIC_DECODE','%TBASS_MUSIC_FLOAT','%TBASS_MUSIC_FT2MOD','%TBASS_MUSIC_FX','%TBASS_MUSIC_LOOP',
+            '%TBASS_MUSIC_MONO','%TBASS_MUSIC_NONINTER','%TBASS_MUSIC_NOSAMPLE','%TBASS_MUSIC_POSRESET','%TBASS_MUSIC_POSRESETEX','%TBASS_MUSIC_PRESCAN','%TBASS_MUSIC_PT1MOD','%TBASS_MUSIC_RAMP',
+            '%TBASS_MUSIC_RAMPS','%TBASS_MUSIC_STOPBACK','%TBASS_MUSIC_SURROUND','%TBASS_MUSIC_SURROUND2','%TBASS_OBJECT_DS','%TBASS_OBJECT_DS3DL','%TBASS_OK','%TBASS_RECORD_PAUSE',
+            '%TBASS_SAMPLE_3D','%TBASS_SAMPLE_8BITS','%TBASS_SAMPLE_FLOAT','%TBASS_SAMPLE_FX','%TBASS_SAMPLE_LOOP','%TBASS_SAMPLE_MONO','%TBASS_SAMPLE_MUTEMAX','%TBASS_SAMPLE_OVER_DIST',
+            '%TBASS_SAMPLE_OVER_POS','%TBASS_SAMPLE_OVER_VOL','%TBASS_SAMPLE_SOFTWARE','%TBASS_SAMPLE_VAM','%TBASS_SLIDE_FREQ','%TBASS_SLIDE_PAN','%TBASS_SLIDE_VOL','%TBASS_SPEAKER_CENLFE',
+            '%TBASS_SPEAKER_CENTER','%TBASS_SPEAKER_FRONT','%TBASS_SPEAKER_FRONTLEFT','%TBASS_SPEAKER_FRONTRIGHT','%TBASS_SPEAKER_LEFT','%TBASS_SPEAKER_LFE','%TBASS_SPEAKER_REAR','%TBASS_SPEAKER_REAR2',
+            '%TBASS_SPEAKER_REAR2LEFT','%TBASS_SPEAKER_REAR2RIGHT','%TBASS_SPEAKER_REARLEFT','%TBASS_SPEAKER_REARRIGHT','%TBASS_SPEAKER_RIGHT','%TBASS_STREAMPROC_END','%TBASS_STREAM_AUTOFREE','%TBASS_STREAM_BLOCK',
+            '%TBASS_STREAM_DECODE','%TBASS_STREAM_PRESCAN','%TBASS_STREAM_RESTRATE','%TBASS_STREAM_STATUS','%TBASS_SYNC_DOWNLOAD','%TBASS_SYNC_END','%TBASS_SYNC_FREE','%TBASS_SYNC_MESSAGE',
+            '%TBASS_SYNC_META','%TBASS_SYNC_MIXTIME','%TBASS_SYNC_MUSICFX','%TBASS_SYNC_MUSICINST','%TBASS_SYNC_MUSICPOS','%TBASS_SYNC_ONETIME','%TBASS_SYNC_POS','%TBASS_SYNC_SLIDE',
+            '%TBASS_SYNC_STALL','%TBASS_TAG_HTTP','%TBASS_TAG_ICY','%TBASS_TAG_ID3','%TBASS_TAG_ID3V2','%TBASS_TAG_META','%TBASS_TAG_MUSIC_INST','%TBASS_TAG_MUSIC_MESSAGE',
+            '%TBASS_TAG_MUSIC_NAME','%TBASS_TAG_MUSIC_SAMPLE','%TBASS_TAG_OGG','%TBASS_TAG_RIFF_INFO','%TBASS_TAG_VENDOR','%TBASS_TRUE','%TBASS_UNICODE','%TBASS_VAM_HARDWARE',
+            '%TBASS_VAM_SOFTWARE','%TBASS_VAM_TERM_DIST','%TBASS_VAM_TERM_PRIO','%TBASS_VAM_TERM_TIME','%TBASS_VERSION','%TBCD_CHANNEL','%TBCD_THUMB','%TBCD_TICS',
+            '%TBGL_ALIGN_CENTER','%TBGL_ALIGN_CENTER_CENTER','%TBGL_ALIGN_CENTER_DOWN','%TBGL_ALIGN_CENTER_UP','%TBGL_ALIGN_LEFT','%TBGL_ALIGN_LEFT_CENTER','%TBGL_ALIGN_LEFT_DOWN','%TBGL_ALIGN_LEFT_UP',
+            '%TBGL_ALIGN_RIGHT','%TBGL_ALIGN_RIGHT_CENTER','%TBGL_ALIGN_RIGHT_DOWN','%TBGL_ALIGN_RIGHT_UP','%TBGL_ALWAYS','%TBGL_EQUAL','%TBGL_ERROR_FILE','%TBGL_ERROR_MSGBOX',
+            '%TBGL_ERROR_NONE','%TBGL_GEQUAL','%TBGL_GREATER','%TBGL_LEQUAL','%TBGL_LESS','%TBGL_LIGHT_AMBIENT','%TBGL_LIGHT_CONSTANT_ATTENUATION','%TBGL_LIGHT_DIFFUSE',
+            '%TBGL_LIGHT_LINEAR_ATTENUATION','%TBGL_LIGHT_POSITION','%TBGL_LIGHT_QUADRATIC_ATTENUATION','%TBGL_LIGHT_SPECULAR','%TBGL_LIGHT_SPOT_CUTOFF','%TBGL_LIGHT_SPOT_DIRECTION','%TBGL_LIGHT_SPOT_EXPONENT','%TBGL_M15B',
+            '%TBGL_M15G','%TBGL_M15LAYER','%TBGL_M15PSTOP','%TBGL_M15R','%TBGL_M15TEXN','%TBGL_M15TEXX','%TBGL_M15TEXY','%TBGL_M15X',
+            '%TBGL_M15Y','%TBGL_M15Z','%TBGL_NEVER','%TBGL_NORMAL_NONE','%TBGL_NORMAL_PRECISE','%TBGL_NORMAL_SMOOTH','%TBGL_NOTEQUAL','%TBGL_OBJ_CUBE',
+            '%TBGL_OBJ_CUBE3','%TBGL_OBJ_CYLINDER','%TBGL_OBJ_SPHERE','%TBGL_PINFO_RGB','%TBGL_PINFO_XYZ','%TBGL_TEX_LINEAR','%TBGL_TEX_MIPMAP','%TBGL_TEX_NEAREST',
+            '%TBM_CLEARSEL','%TBM_CLEARTICS','%TBM_GETBUDDY','%TBM_GETCHANNELRECT','%TBM_GETLINESIZE','%TBM_GETNUMTICS','%TBM_GETPAGESIZE','%TBM_GETPOS',
+            '%TBM_GETPTICS','%TBM_GETRANGEMAX','%TBM_GETRANGEMIN','%TBM_GETSELEND','%TBM_GETSELSTART','%TBM_GETTHUMBLENGTH','%TBM_GETTHUMBRECT','%TBM_GETTIC',
+            '%TBM_GETTICPOS','%TBM_GETTOOLTIPS','%TBM_GETUNICODEFORMAT','%TBM_SETBUDDY','%TBM_SETLINESIZE','%TBM_SETPAGESIZE','%TBM_SETPOS','%TBM_SETRANGE',
+            '%TBM_SETRANGEMAX','%TBM_SETRANGEMIN','%TBM_SETSEL','%TBM_SETSELEND','%TBM_SETSELSTART','%TBM_SETTHUMBLENGTH','%TBM_SETTIC','%TBM_SETTICFREQ',
+            '%TBM_SETTIPSIDE','%TBM_SETTOOLTIPS','%TBM_SETUNICODEFORMAT','%TBS_AUTOTICKS','%TBS_BOTH','%TBS_BOTTOM','%TBS_DOWNISLEFT','%TBS_ENABLESELRANGE',
+            '%TBS_FIXEDLENGTH','%TBS_HORZ','%TBS_LEFT','%TBS_NOTHUMB','%TBS_NOTICKS','%TBS_REVERSED','%TBS_RIGHT','%TBS_TOOLTIPS',
+            '%TBS_TOP','%TBS_VERT','%TBTS_BOTTOM','%TBTS_LEFT','%TBTS_RIGHT','%TBTS_TOP','%TB_%VT_BSTR','%TB_%VT_CY',
+            '%TB_%VT_DATE','%TB_%VT_EMPTY','%TB_%VT_I2','%TB_%VT_I4','%TB_%VT_NULL','%TB_%VT_R4','%TB_%VT_R8','%TB_BOTTOM',
+            '%TB_CLASS_E_NOAGGREGATION','%TB_CO_E_CLASSSTRING','%TB_DISPATCH_METHOD','%TB_DISPATCH_PROPERTYGET','%TB_DISPATCH_PROPERTYPUT','%TB_DISPATCH_PROPERTYPUTREF','%TB_ENDTRACK','%TB_E_INVALIDARG',
+            '%TB_E_NOINTERFACE','%TB_E_OUTOFMEMORY','%TB_IMGCTX_ACTUALSIZE','%TB_IMGCTX_AUTOSIZE','%TB_IMGCTX_FITTOHEIGHT','%TB_IMGCTX_FITTOWIDTH','%TB_IMGCTX_STRETCH','%TB_LINEDOWN',
+            '%TB_LINEUP','%TB_MK_E_CONNECTMANUALLY','%TB_MK_E_EXCEEDEDDEADLINE','%TB_MK_E_INTERMEDIATEINTERFACENOTSUPPORTED','%TB_MK_E_NOOBJECT','%TB_MK_E_SYNTAX','%TB_PAGEDOWN','%TB_PAGEUP',
+            '%TB_REGDB_E_CLASSNOTREG','%TB_REGDB_E_WRITEREGDB','%TB_SIZEOF_TBVARIANT','%TB_S_FALSE','%TB_S_OK','%TB_THUMBPOSITION','%TB_THUMBTRACK','%TB_TOP',
+            '%TCM_FIRST','%TCM_GETCURSEL','%TCN_FOCUSCHANGE','%TCN_GETOBJECT','%TCN_SELCHANGE','%TCN_SELCHANGING','%TCS_BOTTOM','%TCS_BUTTONS',
+            '%TCS_EX_FLATSEPARATORS','%TCS_EX_REGISTERDROP','%TCS_FIXEDWIDTH','%TCS_FLATBUTTONS','%TCS_FOCUSNEVER','%TCS_FOCUSONBUTTONDOWN','%TCS_FORCEICONLEFT','%TCS_FORCELABELLEFT',
+            '%TCS_HOTTRACK','%TCS_MULTILINE','%TCS_MULTISELECT','%TCS_OWNERDRAWFIXED','%TCS_RAGGEDRIGHT','%TCS_RIGHT','%TCS_RIGHTJUSTIFY','%TCS_SCROLLOPPOSITE',
+            '%TCS_SINGLELINE','%TCS_TABS','%TCS_TOOLTIPS','%TCS_VERTICAL','%TM_PLAINTEXT','%TM_RICHTEXT','%TOKENIZER_DEFAULT_ALPHA','%TOKENIZER_DEFAULT_DELIM',
+            '%TOKENIZER_DEFAULT_DQUOTE','%TOKENIZER_DEFAULT_NEWLINE','%TOKENIZER_DEFAULT_NUMERIC','%TOKENIZER_DEFAULT_SPACE','%TOKENIZER_DELIMITER','%TOKENIZER_EOL','%TOKENIZER_ERROR','%TOKENIZER_FINISHED',
+            '%TOKENIZER_NUMBER','%TOKENIZER_QUOTE','%TOKENIZER_STRING','%TOKENIZER_UNDEFTOK','%TRUE','%TV_FIRST','%UDM_GETACCEL','%UDM_GETBASE',
+            '%UDM_GETBUDDY','%UDM_GETPOS','%UDM_GETPOS32','%UDM_GETRANGE','%UDM_GETRANGE32','%UDM_GETUNICODEFORMAT','%UDM_SETACCEL','%UDM_SETBASE',
+            '%UDM_SETBUDDY','%UDM_SETPOS','%UDM_SETPOS32','%UDM_SETRANGE','%UDM_SETRANGE32','%UDM_SETUNICODEFORMAT','%UDS_ALIGNLEFT','%UDS_ALIGNRIGHT',
+            '%UDS_ARROWKEYS','%UDS_AUTOBUDDY','%UDS_HORZ','%UDS_HOTTRACK','%UDS_NOTHOUSANDS','%UDS_SETBUDDYINT','%UDS_WRAP','%UD_MAXVAL',
+            '%UD_MINVAL','%VK_0','%VK_1','%VK_2','%VK_3','%VK_4','%VK_5','%VK_6',
+            '%VK_7','%VK_8','%VK_9','%VK_A','%VK_ACCEPT','%VK_ADD','%VK_APPS','%VK_B',
+            '%VK_BACK','%VK_C','%VK_CANCEL','%VK_CAPITAL','%VK_CLEAR','%VK_CONTROL','%VK_CONVERT','%VK_D',
+            '%VK_DECIMAL','%VK_DELETE','%VK_DIVIDE','%VK_DOWN','%VK_E','%VK_END','%VK_ESCAPE','%VK_EXECUTE',
+            '%VK_F','%VK_F1','%VK_F10','%VK_F11','%VK_F12','%VK_F13','%VK_F14','%VK_F15',
+            '%VK_F16','%VK_F17','%VK_F18','%VK_F19','%VK_F2','%VK_F20','%VK_F21','%VK_F22',
+            '%VK_F23','%VK_F24','%VK_F3','%VK_F4','%VK_F5','%VK_F6','%VK_F7','%VK_F8',
+            '%VK_F9','%VK_FINAL','%VK_G','%VK_H','%VK_HANGEUL','%VK_HANGUL','%VK_HANJA','%VK_HELP',
+            '%VK_HOME','%VK_I','%VK_INSERT','%VK_J','%VK_JUNJA','%VK_K','%VK_KANA','%VK_KANJI',
+            '%VK_L','%VK_LBUTTON','%VK_LEFT','%VK_LINEFEED','%VK_LWIN','%VK_M','%VK_MBUTTON','%VK_MENU',
+            '%VK_MODECHANGE','%VK_MULTIPLY','%VK_N','%VK_NEXT','%VK_NONCONVERT','%VK_NUMLOCK','%VK_NUMPAD0','%VK_NUMPAD1',
+            '%VK_NUMPAD2','%VK_NUMPAD3','%VK_NUMPAD4','%VK_NUMPAD5','%VK_NUMPAD6','%VK_NUMPAD7','%VK_NUMPAD8','%VK_NUMPAD9',
+            '%VK_O','%VK_P','%VK_PAUSE','%VK_PGDN','%VK_PGUP','%VK_PRINT','%VK_PRIOR','%VK_Q',
+            '%VK_R','%VK_RBUTTON','%VK_RETURN','%VK_RIGHT','%VK_RWIN','%VK_S','%VK_SCROLL','%VK_SELECT',
+            '%VK_SEPARATOR','%VK_SHIFT','%VK_SLEEP','%VK_SNAPSHOT','%VK_SPACE','%VK_SUBTRACT','%VK_T','%VK_TAB',
+            '%VK_U','%VK_UP','%VK_V','%VK_W','%VK_X','%VK_XBUTTON1','%VK_XBUTTON2','%VK_Y',
+            '%VK_Z','%VT_ARRAY','%VT_BLOB','%VT_BLOB_OBJECT','%VT_BOOL','%VT_BSTR','%VT_BYREF','%VT_CARRAY',
+            '%VT_CF','%VT_CLSID','%VT_CY','%VT_DATE','%VT_DISPATCH','%VT_EMPTY','%VT_ERROR','%VT_FILETIME',
+            '%VT_HRESULT','%VT_I1','%VT_I2','%VT_I4','%VT_I8','%VT_INT','%VT_LPSTR','%VT_LPWSTR',
+            '%VT_NULL','%VT_PTR','%VT_R4','%VT_R8','%VT_RECORD','%VT_RESERVED','%VT_SAFEARRAY','%VT_STORAGE',
+            '%VT_STORED_OBJECT','%VT_STREAM','%VT_STREAMED_OBJECT','%VT_UI1','%VT_UI2','%VT_UI4','%VT_UI8','%VT_UINT',
+            '%VT_UNKNOWN','%VT_USERDEFINED','%VT_VARIANT','%VT_VECTOR','%VT_VOID','%WAVE_FORMAT_1M08','%WAVE_FORMAT_1M16','%WAVE_FORMAT_1S08',
+            '%WAVE_FORMAT_1S16','%WAVE_FORMAT_2M08','%WAVE_FORMAT_2M16','%WAVE_FORMAT_2S08','%WAVE_FORMAT_2S16','%WAVE_FORMAT_4M08','%WAVE_FORMAT_4M16','%WAVE_FORMAT_4S08',
+            '%WAVE_FORMAT_4S16','%WBF_CUSTOM','%WBF_LEVEL1','%WBF_LEVEL2','%WBF_OVERFLOW','%WBF_WORDBREAK','%WBF_WORDWRAP','%WHITE',
+            '%WIN_FINDTITLECONTAIN','%WIN_FINDTITLEEND','%WIN_FINDTITLEEQUAL','%WIN_FINDTITLESTART','%WM_ACTIVATE','%WM_ACTIVATEAPP','%WM_CAPTURECHANGED','%WM_CHAR',
+            '%WM_CLOSE','%WM_COMMAND','%WM_DESTROY','%WM_DROPFILES','%WM_ERASEBKGND','%WM_GETTEXTLENGTH','%WM_HOTKEY','%WM_HSCROLL',
+            '%WM_IDLE','%WM_INITDIALOG','%WM_KEYDOWN','%WM_KEYUP','%WM_KILLFOCUS','%WM_LBUTTONDBLCLK','%WM_LBUTTONDOWN','%WM_LBUTTONUP',
+            '%WM_MBUTTONDBLCLK','%WM_MBUTTONDOWN','%WM_MBUTTONUP','%WM_MOUSEFIRST','%WM_MOUSEMOVE','%WM_MOUSEWHEEL','%WM_MOVE','%WM_MOVING',
+            '%WM_NCLBUTTONDOWN','%WM_NCRBUTTONDOWN','%WM_NEXTDLGCTL','%WM_NOTIFY','%WM_PAINT','%WM_QUIT','%WM_RBUTTONDBLCLK','%WM_RBUTTONDOWN',
+            '%WM_RBUTTONUP','%WM_SETFOCUS','%WM_SETFONT','%WM_SETTEXT','%WM_SIZE','%WM_SIZING','%WM_SYSCOMMAND','%WM_TIMER',
+            '%WM_USER','%WM_VSCROLL','%WS_BORDER','%WS_CAPTION','%WS_CHILD','%WS_CLIPCHILDREN','%WS_CLIPSIBLINGS','%WS_DISABLED',
+            '%WS_DLGFRAME','%WS_EX_ACCEPTFILES','%WS_EX_APPWINDOW','%WS_EX_CLIENTEDGE','%WS_EX_CONTEXTHELP','%WS_EX_CONTROLPARENT','%WS_EX_LAYERED','%WS_EX_LEFT',
+            '%WS_EX_LEFTSCROLLBAR','%WS_EX_LTRREADING','%WS_EX_MDICHILD','%WS_EX_NOPARENTNOTIFY','%WS_EX_OVERLAPPEDWINDOW','%WS_EX_PALETTEWINDOW','%WS_EX_RIGHT','%WS_EX_RIGHTSCROLLBAR',
+            '%WS_EX_RTLREADING','%WS_EX_STATICEDGE','%WS_EX_TOOLWINDOW','%WS_EX_TOPMOST','%WS_EX_TRANSPARENT','%WS_EX_WINDOWEDGE','%WS_GROUP','%WS_HSCROLL',
+            '%WS_ICONIC','%WS_MAXIMIZE','%WS_MAXIMIZEBOX','%WS_MINIMIZE','%WS_MINIMIZEBOX','%WS_OVERLAPPEDWINDOW','%WS_POPUP','%WS_POPUPWINDOW',
+            '%WS_SYSMENU','%WS_TABSTOP','%WS_THICKFRAME','%WS_VISIBLE','%WS_VSCROLL','%YELLOW','%ZERO','CRLF',
+            'FALSE','M_E','M_PI','NULL','TAB','TRUE'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '{', '}', '[', ']', '=', '+', '-', '*', '/', '!', '%', '^', '&', ':'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0000FF; font-weight: bold;',
+            2 => 'color: #993333; font-style: italic; font-weight: bold;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #008000;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #333333;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #800080;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #CC0000;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #66cc66;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #333333;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        1 => '_'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/tsql.php b/examples/includes/geshi/geshi/tsql.php
new file mode 100644 (file)
index 0000000..dd6b0cc
--- /dev/null
@@ -0,0 +1,378 @@
+<?php
+/*************************************************************************************
+ * tsql.php
+ * --------
+ * Author: Duncan Lock (dunc@dflock.co.uk)
+ * Copyright: (c) 2006 Duncan Lock (http://dflock.co.uk/), Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2005/11/22
+ *
+ * T-SQL language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2004/01/23 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2006/01/23)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'T-SQL',
+    'COMMENT_SINGLE' => array(1 => '--'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_UPPER,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            // Datatypes
+            'bigint', 'int', 'smallint', 'tinyint', 'bit', 'decimal', 'numeric', 'money',
+            'smallmoney', 'float', 'real', 'datetime', 'smalldatetime', 'char', 'varchar',
+            'text', 'nchar', 'nvarchar', 'ntext', 'binary', 'varbinary', 'image', 'cursor',
+            'sql_variant', 'table', 'timestamp', 'uniqueidentifier',
+
+            // Keywords
+            'ABSOLUTE', 'ACTION', 'ADD', 'ADMIN', 'AFTER', 'AGGREGATE', 'ALIAS', 'ALLOCATE', 'ALTER', 'ARE', 'ARRAY', 'AS',
+            'ASC', 'ASSERTION', 'AT', 'AUTHORIZATION', 'BACKUP', 'BEFORE', 'BEGIN', 'BINARY', 'BIT', 'BLOB', 'BOOLEAN', 'BOTH', 'BREADTH',
+            'BREAK', 'BROWSE', 'BULK', 'BY', 'CALL', 'CASCADE', 'CASCADED', 'CASE', 'CAST', 'CATALOG', 'CHAR', 'CHARACTER', 'CHECK', 'CHECKPOINT',
+            'CLASS', 'CLOB', 'CLOSE', 'CLUSTERED', 'COALESCE', 'COLLATE', 'COLLATION', 'COLUMN', 'COMMIT', 'COMPLETION', 'COMPUTE', 'CONNECT',
+            'CONNECTION', 'CONSTRAINT', 'CONSTRAINTS', 'CONSTRUCTOR', 'CONTAINS', 'CONTAINSTABLE', 'CONTINUE', 'CONVERT', 'CORRESPONDING', 'CREATE',
+            'CUBE', 'CURRENT', 'CURRENT_DATE', 'CURRENT_PATH', 'CURRENT_ROLE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURRENT_USER',
+            'CURSOR', 'CYCLE', 'DATA', 'DATABASE', 'DATE', 'DAY', 'DBCC', 'DEALLOCATE', 'DEC', 'DECIMAL', 'DECLARE', 'DEFAULT', 'DEFERRABLE',
+            'DEFERRED', 'DELETE', 'DENY', 'DEPTH', 'DEREF', 'DESC', 'DESCRIBE', 'DESCRIPTOR', 'DESTROY', 'DESTRUCTOR', 'DETERMINISTIC',
+            'DIAGNOSTICS', 'DICTIONARY', 'DISCONNECT', 'DISK', 'DISTINCT', 'DISTRIBUTED', 'DOMAIN', 'DOUBLE', 'DROP', 'DUMMY', 'DUMP', 'DYNAMIC',
+            'EACH', 'ELSE', 'END', 'END-EXEC', 'EQUALS', 'ERRLVL', 'ESCAPE', 'EVERY', 'EXCEPT', 'EXCEPTION', 'EXEC', 'EXECUTE', 'EXIT',
+            'EXTERNAL', 'FALSE', 'FETCH', 'FILE', 'FILLFACTOR', 'FIRST', 'FLOAT', 'FOR', 'FOREIGN', 'FOUND', 'FREE', 'FREETEXT', 'FREETEXTTABLE',
+            'FROM', 'FULL', 'FUNCTION', 'GENERAL', 'GET', 'GLOBAL', 'GOTO', 'GRANT', 'GROUP', 'GROUPING', 'HAVING', 'HOLDLOCK', 'HOST', 'HOUR',
+            'IDENTITY', 'IDENTITY_INSERT', 'IDENTITYCOL', 'IF', 'IGNORE', 'IMMEDIATE', 'INDEX', 'INDICATOR', 'INITIALIZE', 'INITIALLY',
+            'INNER', 'INOUT', 'INPUT', 'INSERT', 'INT', 'INTEGER', 'INTERSECT', 'INTERVAL', 'INTO', 'IS', 'ISOLATION', 'ITERATE', 'KEY',
+            'KILL', 'LANGUAGE', 'LARGE', 'LAST', 'LATERAL', 'LEADING', 'LEFT', 'LESS', 'LEVEL', 'LIMIT', 'LINENO', 'LOAD', 'LOCAL',
+            'LOCALTIME', 'LOCALTIMESTAMP', 'LOCATOR', 'MAP', 'MATCH', 'MINUTE', 'MODIFIES', 'MODIFY', 'MODULE', 'MONTH', 'NAMES', 'NATIONAL',
+            'NATURAL', 'NCHAR', 'NCLOB', 'NEW', 'NEXT', 'NO', 'NOCHECK', 'NONCLUSTERED', 'NONE', 'NULLIF', 'NUMERIC', 'OBJECT', 'OF',
+            'OFF', 'OFFSETS', 'OLD', 'ON', 'ONLY', 'OPEN', 'OPENDATASOURCE', 'OPENQUERY', 'OPENROWSET', 'OPENXML', 'OPERATION', 'OPTION',
+            'ORDER', 'ORDINALITY', 'OUT', 'OUTPUT', 'OVER', 'PAD', 'PARAMETER', 'PARAMETERS', 'PARTIAL', 'PATH', 'PERCENT', 'PLAN',
+            'POSTFIX', 'PRECISION', 'PREFIX', 'PREORDER', 'PREPARE', 'PRESERVE', 'PRIMARY', 'PRINT', 'PRIOR', 'PRIVILEGES', 'PROC', 'PROCEDURE',
+            'PUBLIC', 'RAISERROR', 'READ', 'READS', 'READTEXT', 'REAL', 'RECONFIGURE', 'RECURSIVE', 'REF', 'REFERENCES', 'REFERENCING', 'RELATIVE',
+            'REPLICATION', 'RESTORE', 'RESTRICT', 'RESULT', 'RETURN', 'RETURNS', 'REVOKE', 'RIGHT', 'ROLE', 'ROLLBACK', 'ROLLUP', 'ROUTINE', 'ROW',
+            'ROWGUIDCOL', 'ROWS', 'RULE', 'SAVE', 'SAVEPOINT', 'SCHEMA', 'SCOPE', 'SCROLL', 'SEARCH', 'SECOND', 'SECTION', 'SELECT',
+            'SEQUENCE', 'SESSION', 'SESSION_USER', 'SET', 'SETS', 'SETUSER', 'SHUTDOWN', 'SIZE', 'SMALLINT', 'SPACE', 'SPECIFIC',
+            'SPECIFICTYPE', 'SQL', 'SQLEXCEPTION', 'SQLSTATE', 'SQLWARNING', 'START', 'STATE', 'STATEMENT', 'STATIC', 'STATISTICS', 'STRUCTURE',
+            'SYSTEM_USER', 'TABLE', 'TEMPORARY', 'TERMINATE', 'TEXTSIZE', 'THAN', 'THEN', 'TIME', 'TIMESTAMP', 'TIMEZONE_HOUR', 'TIMEZONE_MINUTE',
+            'TO', 'TOP', 'TRAILING', 'TRAN', 'TRANSACTION', 'TRANSLATION', 'TREAT', 'TRIGGER', 'TRUE', 'TRUNCATE', 'TSEQUAL', 'UNDER', 'UNION',
+            'UNIQUE', 'UNKNOWN', 'UNNEST', 'UPDATE', 'UPDATETEXT', 'USAGE', 'USE', 'USER', 'USING', 'VALUE', 'VALUES', 'VARCHAR', 'VARIABLE',
+            'VARYING', 'VIEW', 'WAITFOR', 'WHEN', 'WHENEVER', 'WHERE', 'WHILE', 'WITH', 'WITHOUT', 'WORK', 'WRITE', 'WRITETEXT', 'YEAR', 'ZONE',
+            'UNCOMMITTED', 'NOCOUNT',
+            ),
+        2 => array(
+            /*
+                Built-in functions
+                Highlighted in pink.
+            */
+
+            //Configuration Functions
+            '@@DATEFIRST','@@OPTIONS','@@DBTS','@@REMSERVER','@@LANGID','@@SERVERNAME',
+            '@@LANGUAGE','@@SERVICENAME','@@LOCK_TIMEOUT','@@SPID','@@MAX_CONNECTIONS','@@TEXTSIZE',
+            '@@MAX_PRECISION','@@VERSION','@@NESTLEVEL',
+
+            //Cursor Functions
+            '@@CURSOR_ROWS','@@FETCH_STATUS',
+
+            //Date and Time Functions
+            'DATEADD','DATEDIFF','DATENAME','DATEPART','DAY','GETDATE','GETUTCDATE','MONTH','YEAR',
+
+            //Mathematical Functions
+            'ABS','DEGREES','RAND','ACOS','EXP','ROUND','ASIN','FLOOR','SIGN',
+            'ATAN','LOG','SIN','ATN2','LOG10','SQUARE','CEILING','PI','SQRT','COS',
+            'POWER','TAN','COT','RADIANS',
+
+            //Meta Data Functions
+            'COL_LENGTH','fn_listextendedproperty','COL_NAME','FULLTEXTCATALOGPROPERTY',
+            'COLUMNPROPERTY','FULLTEXTSERVICEPROPERTY','DATABASEPROPERTY','INDEX_COL',
+            'DATABASEPROPERTYEX','INDEXKEY_PROPERTY','DB_ID','INDEXPROPERTY','DB_NAME',
+            'OBJECT_ID','FILE_ID','OBJECT_NAME','FILE_NAME','OBJECTPROPERTY','FILEGROUP_ID',
+            '@@PROCID','FILEGROUP_NAME','SQL_VARIANT_PROPERTY','FILEGROUPPROPERTY',
+            'TYPEPROPERTY','FILEPROPERTY',
+
+            //Security Functions
+            'fn_trace_geteventinfo','IS_SRVROLEMEMBER','fn_trace_getfilterinfo','SUSER_SID',
+            'fn_trace_getinfo','SUSER_SNAME','fn_trace_gettable','USER_ID','HAS_DBACCESS',
+            'IS_MEMBER',
+
+            //String Functions
+            'ASCII','NCHAR','SOUNDEX','CHAR','PATINDEX','SPACE','CHARINDEX',
+            'REPLACE','STR','DIFFERENCE','QUOTENAME','STUFF','LEFT','REPLICATE',
+            'SUBSTRING','LEN','REVERSE','UNICODE','LOWER','RIGHT','UPPER','LTRIM',
+            'RTRIM',
+
+            //System Functions
+            'APP_NAME','COLLATIONPROPERTY','@@ERROR','fn_helpcollations',
+            'fn_servershareddrives','fn_virtualfilestats','FORMATMESSAGE',
+            'GETANSINULL','HOST_ID','HOST_NAME','IDENT_CURRENT','IDENT_INCR',
+            'IDENT_SEED','@@IDENTITY','ISDATE','ISNUMERIC','PARSENAME','PERMISSIONS',
+            '@@ROWCOUNT','ROWCOUNT_BIG','SCOPE_IDENTITY','SERVERPROPERTY','SESSIONPROPERTY',
+            'STATS_DATE','@@TRANCOUNT','USER_NAME',
+
+            //System Statistical Functions
+            '@@CONNECTIONS','@@PACK_RECEIVED','@@CPU_BUSY','@@PACK_SENT',
+            '@@TIMETICKS','@@IDLE','@@TOTAL_ERRORS','@@IO_BUSY',
+            '@@TOTAL_READ','@@PACKET_ERRORS','@@TOTAL_WRITE',
+
+            //Text and Image Functions
+            'TEXTPTR','TEXTVALID',
+
+            //Aggregate functions
+            'AVG', 'MAX', 'BINARY_CHECKSUM', 'MIN', 'CHECKSUM', 'SUM', 'CHECKSUM_AGG',
+            'STDEV', 'COUNT', 'STDEVP', 'COUNT_BIG', 'VAR', 'GROUPING', 'VARP'
+            ),
+        3 => array(
+            /*
+                System stored procedures
+                Higlighted dark brown
+            */
+
+            //Active Directory Procedures
+            'sp_ActiveDirectory_Obj', 'sp_ActiveDirectory_SCP',
+
+            //Catalog Procedures
+            'sp_column_privileges', 'sp_special_columns', 'sp_columns', 'sp_sproc_columns',
+            'sp_databases', 'sp_statistics', 'sp_fkeys', 'sp_stored_procedures', 'sp_pkeys',
+            'sp_table_privileges', 'sp_server_info', 'sp_tables',
+
+            //Cursor Procedures
+            'sp_cursor_list', 'sp_describe_cursor_columns', 'sp_describe_cursor', 'sp_describe_cursor_tables',
+
+            //Database Maintenance Plan Procedures
+            'sp_add_maintenance_plan', 'sp_delete_maintenance_plan_db', 'sp_add_maintenance_plan_db',
+            'sp_delete_maintenance_plan_job', 'sp_add_maintenance_plan_job', 'sp_help_maintenance_plan',
+            'sp_delete_maintenance_plan',
+
+            //Distributed Queries Procedures
+            'sp_addlinkedserver', 'sp_indexes', 'sp_addlinkedsrvlogin', 'sp_linkedservers', 'sp_catalogs',
+            'sp_primarykeys', 'sp_column_privileges_ex', 'sp_columns_ex',
+            'sp_table_privileges_ex', 'sp_tables_ex', 'sp_foreignkeys',
+
+            //Full-Text Search Procedures
+            'sp_fulltext_catalog', 'sp_help_fulltext_catalogs_cursor', 'sp_fulltext_column',
+            'sp_help_fulltext_columns', 'sp_fulltext_database', 'sp_help_fulltext_columns_cursor',
+            'sp_fulltext_service', 'sp_help_fulltext_tables', 'sp_fulltext_table',
+            'sp_help_fulltext_tables_cursor', 'sp_help_fulltext_catalogs',
+
+            //Log Shipping Procedures
+            'sp_add_log_shipping_database', 'sp_delete_log_shipping_database', 'sp_add_log_shipping_plan',
+            'sp_delete_log_shipping_plan', 'sp_add_log_shipping_plan_database',
+            'sp_delete_log_shipping_plan_database', 'sp_add_log_shipping_primary',
+            'sp_delete_log_shipping_primary', 'sp_add_log_shipping_secondary',
+            'sp_delete_log_shipping_secondary', 'sp_can_tlog_be_applied', 'sp_get_log_shipping_monitor_info',
+            'sp_change_monitor_role', 'sp_remove_log_shipping_monitor', 'sp_change_primary_role',
+            'sp_resolve_logins', 'sp_change_secondary_role', 'sp_update_log_shipping_monitor_info',
+            'sp_create_log_shipping_monitor_account', 'sp_update_log_shipping_plan',
+            'sp_define_log_shipping_monitor', 'sp_update_log_shipping_plan_database',
+
+            //OLE Automation Extended Stored Procedures
+            'sp_OACreate', 'sp_OAMethod', 'sp_OADestroy', 'sp_OASetProperty', 'sp_OAGetErrorInfo',
+            'sp_OAStop', 'sp_OAGetProperty',
+
+            //Replication Procedures
+            'sp_add_agent_parameter', 'sp_enableagentoffload', 'sp_add_agent_profile',
+            'sp_enumcustomresolvers', 'sp_addarticle', 'sp_enumdsn', 'sp_adddistpublisher',
+            'sp_enumfullsubscribers', 'sp_adddistributiondb', 'sp_expired_subscription_cleanup',
+            'sp_adddistributor', 'sp_generatefilters', 'sp_addmergealternatepublisher',
+            'sp_getagentoffloadinfo', 'sp_addmergearticle', 'sp_getmergedeletetype', 'sp_addmergefilter',
+            'sp_get_distributor', 'sp_addmergepublication', 'sp_getqueuedrows', 'sp_addmergepullsubscription',
+            'sp_getsubscriptiondtspackagename', 'sp_addmergepullsubscription_agent', 'sp_grant_publication_access',
+            'sp_addmergesubscription', 'sp_help_agent_default', 'sp_addpublication', 'sp_help_agent_parameter',
+            'sp_addpublication_snapshot', 'sp_help_agent_profile', 'sp_addpublisher70', 'sp_helparticle',
+            'sp_addpullsubscription', 'sp_helparticlecolumns', 'sp_addpullsubscription_agent', 'sp_helparticledts',
+            'sp_addscriptexec', 'sp_helpdistpublisher', 'sp_addsubscriber', 'sp_helpdistributiondb',
+            'sp_addsubscriber_schedule', 'sp_helpdistributor', 'sp_addsubscription', 'sp_helpmergealternatepublisher',
+            'sp_addsynctriggers', 'sp_helpmergearticle', 'sp_addtabletocontents', 'sp_helpmergearticlecolumn',
+            'sp_adjustpublisheridentityrange', 'sp_helpmergearticleconflicts', 'sp_article_validation',
+            'sp_helpmergeconflictrows', 'sp_articlecolumn', 'sp_helpmergedeleteconflictrows', 'sp_articlefilter',
+            'sp_helpmergefilter', 'sp_articlesynctranprocs', 'sp_helpmergepublication', 'sp_articleview',
+            'sp_helpmergepullsubscription', 'sp_attachsubscription', 'sp_helpmergesubscription', 'sp_browsesnapshotfolder',
+            'sp_helppublication', 'sp_browsemergesnapshotfolder', 'sp_help_publication_access', 'sp_browsereplcmds',
+            'sp_helppullsubscription', 'sp_change_agent_parameter', 'sp_helpreplfailovermode', 'sp_change_agent_profile',
+            'sp_helpreplicationdboption', 'sp_changearticle', 'sp_helpreplicationoption', 'sp_changedistpublisher',
+            'sp_helpsubscriberinfo', 'sp_changedistributiondb', 'sp_helpsubscription', 'sp_changedistributor_password',
+            'sp_ivindexhasnullcols', 'sp_changedistributor_property', 'sp_helpsubscription_properties', 'sp_changemergearticle',
+            'sp_link_publication', 'sp_changemergefilter', 'sp_marksubscriptionvalidation', 'sp_changemergepublication',
+            'sp_mergearticlecolumn', 'sp_changemergepullsubscription', 'sp_mergecleanupmetadata', 'sp_changemergesubscription',
+            'sp_mergedummyupdate', 'sp_changepublication', 'sp_mergesubscription_cleanup', 'sp_changesubscriber',
+            'sp_publication_validation', 'sp_changesubscriber_schedule', 'sp_refreshsubscriptions', 'sp_changesubscriptiondtsinfo',
+            'sp_reinitmergepullsubscription', 'sp_changesubstatus', 'sp_reinitmergesubscription', 'sp_change_subscription_properties',
+            'sp_reinitpullsubscription', 'sp_check_for_sync_trigger', 'sp_reinitsubscription', 'sp_copymergesnapshot',
+            'sp_removedbreplication', 'sp_copysnapshot', 'sp_repladdcolumn', 'sp_copysubscription', 'sp_replcmds',
+            'sp_deletemergeconflictrow', 'sp_replcounters', 'sp_disableagentoffload', 'sp_repldone', 'sp_drop_agent_parameter',
+            'sp_repldropcolumn', 'sp_drop_agent_profile', 'sp_replflush', 'sp_droparticle', 'sp_replicationdboption',
+            'sp_dropanonymouseagent', 'sp_replication_agent_checkup', 'sp_dropdistpublisher', 'sp_replqueuemonitor',
+            'sp_dropdistributiondb', 'sp_replsetoriginator', 'sp_dropmergealternatepublisher', 'sp_replshowcmds',
+            'sp_dropdistributor', 'sp_repltrans', 'sp_dropmergearticle', 'sp_restoredbreplication', 'sp_dropmergefilter',
+            'sp_revoke_publication_access', 'sp_scriptsubconflicttable', 'sp_dropmergepublication', 'sp_script_synctran_commands',
+            'sp_dropmergepullsubscription', 'sp_setreplfailovermode', 'sp_showrowreplicainfo', 'sp_dropmergesubscription',
+            'sp_subscription_cleanup', 'sp_droppublication', 'sp_table_validation', 'sp_droppullsubscription',
+            'sp_update_agent_profile', 'sp_dropsubscriber', 'sp_validatemergepublication', 'sp_dropsubscription',
+            'sp_validatemergesubscription', 'sp_dsninfo', 'sp_vupgrade_replication', 'sp_dumpparamcmd',
+
+            //Security Procedures
+            'sp_addalias', 'sp_droprolemember', 'sp_addapprole', 'sp_dropserver', 'sp_addgroup', 'sp_dropsrvrolemember',
+            'sp_dropuser', 'sp_addlogin', 'sp_grantdbaccess', 'sp_addremotelogin',
+            'sp_grantlogin', 'sp_addrole', 'sp_helpdbfixedrole', 'sp_addrolemember', 'sp_helpgroup',
+            'sp_addserver', 'sp_helplinkedsrvlogin', 'sp_addsrvrolemember', 'sp_helplogins', 'sp_adduser',
+            'sp_helpntgroup', 'sp_approlepassword', 'sp_helpremotelogin', 'sp_changedbowner', 'sp_helprole',
+            'sp_changegroup', 'sp_helprolemember', 'sp_changeobjectowner', 'sp_helprotect', 'sp_change_users_login',
+            'sp_helpsrvrole', 'sp_dbfixedrolepermission', 'sp_helpsrvrolemember', 'sp_defaultdb', 'sp_helpuser',
+            'sp_defaultlanguage', 'sp_MShasdbaccess', 'sp_denylogin', 'sp_password', 'sp_dropalias', 'sp_remoteoption',
+            'sp_dropapprole', 'sp_revokedbaccess', 'sp_dropgroup', 'sp_revokelogin', 'sp_droplinkedsrvlogin',
+            'sp_setapprole', 'sp_droplogin', 'sp_srvrolepermission', 'sp_dropremotelogin', 'sp_validatelogins', 'sp_droprole',
+
+            //SQL Mail Procedures
+            'sp_processmail', 'xp_sendmail', 'xp_deletemail', 'xp_startmail', 'xp_findnextmsg', 'xp_stopmail', 'xp_readmail',
+
+            //SQL Profiler Procedures
+            'sp_trace_create', 'sp_trace_setfilter', 'sp_trace_generateevent', 'sp_trace_setstatus', 'sp_trace_setevent',
+
+            //SQL Server Agent Procedures
+            'sp_add_alert', 'sp_help_jobhistory', 'sp_add_category', 'sp_help_jobschedule', 'sp_add_job',
+            'sp_help_jobserver', 'sp_add_jobschedule', 'sp_help_jobstep', 'sp_add_jobserver', 'sp_help_notification',
+            'sp_add_jobstep', 'sp_help_operator', 'sp_add_notification', 'sp_help_targetserver',
+            'sp_add_operator', 'sp_help_targetservergroup', 'sp_add_targetservergroup', 'sp_helptask',
+            'sp_add_targetsvrgrp_member', 'sp_manage_jobs_by_login', 'sp_addtask', 'sp_msx_defect',
+            'sp_apply_job_to_targets', 'sp_msx_enlist', 'sp_delete_alert', 'sp_post_msx_operation',
+            'sp_delete_category', 'sp_purgehistory', 'sp_delete_job', 'sp_purge_jobhistory', 'sp_delete_jobschedule',
+            'sp_reassigntask', 'sp_delete_jobserver', 'sp_remove_job_from_targets', 'sp_delete_jobstep',
+            'sp_resync_targetserver', 'sp_delete_notification', 'sp_start_job', 'sp_delete_operator',
+            'sp_stop_job', 'sp_delete_targetserver', 'sp_update_alert', 'sp_delete_targetservergroup',
+            'sp_update_category', 'sp_delete_targetsvrgrp_member', 'sp_update_job', 'sp_droptask',
+            'sp_update_jobschedule', 'sp_help_alert', 'sp_update_jobstep', 'sp_help_category',
+            'sp_update_notification', 'sp_help_downloadlist', 'sp_update_operator', 'sp_helphistory',
+            'sp_update_targetservergroup', 'sp_help_job', 'sp_updatetask', 'xp_sqlagent_proxy_account',
+
+            //System Procedures
+            'sp_add_data_file_recover_suspect_db', 'sp_helpconstraint', 'sp_addextendedproc',
+            'sp_helpdb', 'sp_addextendedproperty', 'sp_helpdevice', 'sp_add_log_file_recover_suspect_db',
+            'sp_helpextendedproc', 'sp_addmessage', 'sp_helpfile', 'sp_addtype', 'sp_helpfilegroup',
+            'sp_addumpdevice', 'sp_helpindex', 'sp_altermessage', 'sp_helplanguage', 'sp_autostats',
+            'sp_helpserver', 'sp_attach_db', 'sp_helpsort', 'sp_attach_single_file_db', 'sp_helpstats',
+            'sp_bindefault', 'sp_helptext', 'sp_bindrule', 'sp_helptrigger', 'sp_bindsession',
+            'sp_indexoption', 'sp_certify_removable', 'sp_invalidate_textptr', 'sp_configure',
+            'sp_lock', 'sp_create_removable', 'sp_monitor', 'sp_createstats', 'sp_procoption',
+            'sp_cycle_errorlog', 'sp_recompile', 'sp_datatype_info', 'sp_refreshview', 'sp_dbcmptlevel',
+            'sp_releaseapplock', 'sp_dboption', 'sp_rename', 'sp_dbremove', 'sp_renamedb',
+            'sp_delete_backuphistory', 'sp_resetstatus', 'sp_depends', 'sp_serveroption', 'sp_detach_db',
+            'sp_setnetname', 'sp_dropdevice', 'sp_settriggerorder', 'sp_dropextendedproc', 'sp_spaceused',
+            'sp_dropextendedproperty', 'sp_tableoption', 'sp_dropmessage', 'sp_unbindefault', 'sp_droptype',
+            'sp_unbindrule', 'sp_executesql', 'sp_updateextendedproperty', 'sp_getapplock', 'sp_updatestats',
+            'sp_getbindtoken', 'sp_validname', 'sp_help', 'sp_who',
+
+            //Web Assistant Procedures
+            'sp_dropwebtask', 'sp_makewebtask', 'sp_enumcodepages', 'sp_runwebtask',
+
+            //XML Procedures
+            'sp_xml_preparedocument', 'sp_xml_removedocument',
+
+            //General Extended Procedures
+            'xp_cmdshellxp_logininfo', 'xp_enumgroups', 'xp_msver', 'xp_findnextmsgxp_revokelogin',
+            'xp_grantlogin', 'xp_sprintf', 'xp_logevent', 'xp_sqlmaint', 'xp_loginconfig', 'xp_sscanf',
+
+            //API System Stored Procedures
+            'sp_cursor', 'sp_cursorclose', 'sp_cursorexecute', 'sp_cursorfetch', 'sp_cursoropen',
+            'sp_cursoroption', 'sp_cursorprepare', 'sp_cursorunprepare', 'sp_execute', 'sp_prepare', 'sp_unprepare',
+
+            //Misc
+            'sp_createorphan', 'sp_droporphans', 'sp_reset_connection', 'sp_sdidebug'
+            ),
+        4 => array(
+            //Function/sp's higlighted brown.
+            'fn_helpcollations', 'fn_listextendedproperty ', 'fn_servershareddrives',
+            'fn_trace_geteventinfo', 'fn_trace_getfilterinfo', 'fn_trace_getinfo',
+            'fn_trace_gettable', 'fn_virtualfilestats',
+            ),
+        ),
+    'SYMBOLS' => array(
+        '!', '!=', '%', '&', '&&', '(', ')', '*', '+', '-', '/', '<', '<<', '<=',
+        '<=>', '<>', '=', '>', '>=', '>>', '^', 'ALL', 'AND', 'ANY', 'BETWEEN', 'CROSS',
+        'EXISTS', 'IN', 'JOIN', 'LIKE', 'NOT', 'NULL', 'OR', 'OUTER', 'SOME', '|', '||', '~'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0000FF;',
+            2 => 'color: #FF00FF;',
+            3 => 'color: #AF0000;',
+            4 => 'color: #AF0000;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #008080;',
+            'MULTI' => 'color: #008080;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #808080;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #FF0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #000;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #202020;',
+            2 => 'color: #202020;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #808080;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/typoscript.php b/examples/includes/geshi/geshi/typoscript.php
new file mode 100644 (file)
index 0000000..b0ae753
--- /dev/null
@@ -0,0 +1,300 @@
+<?php
+/*************************************************************************************
+ * typoscript.php
+ * --------
+ * Author: Jan-Philipp Halle (typo3@jphalle.de)
+ * Copyright: (c) 2005 Jan-Philipp Halle (http://www.jphalle.de/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2005/07/29
+ *
+ * TypoScript language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/07/11 (1.0.8)
+ * - Michiel Roos <geshi@typofree.org> Complete rewrite
+ * 2005/07/29 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2004/07/14)
+ * -------------------------
+ * <things-to-do>
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'TypoScript',
+    'COMMENT_SINGLE' => array(1  => '//'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'COMMENT_REGEXP' => array(2 => '/(?<!(#|\'|"))(?:#(?!(?:[a-fA-F0-9]{6}|[a-fA-F0-9]{3}))[^\n#]+|#{2}[^\n#]+|#{7,999}[^\n]+)/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array(),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        // Conditions: http://documentation.typo3.org/documentation/tsref/conditions/
+        1 => array(
+            'browser', 'compatVersion', 'dayofmonth', 'dayofweek', 'device',
+            'globalString', 'globalVars', 'hostname', 'hour',
+            'ip', 'language', 'loginUser', 'loginuser', 'minute',
+            'month', 'PIDinRootline', 'PIDupinRootline',
+            'system', 'treelevel', 'useragent', 'userFunc',
+            'usergroup', 'version'
+            ),
+
+        // Functions: http://documentation.typo3.org/documentation/tsref/functions/
+        2 => array(
+            'addParams', 'encapsLines', 'filelink', 'HTMLparser',
+            'HTMLparser_tags', 'if', 'imageLinkWrap',
+            'imgResource', 'makelinks', 'numRows', 'parseFunc',
+            'select', 'split', 'stdWrap', 'tableStyle', 'tags',
+            'textStyle', 'typolink'
+            ),
+
+        // Toplevel objects: http://documentation.typo3.org/documentation/tsref/tlo-objects/
+        3 => array(
+            'CARRAY', 'CONFIG', 'CONSTANTS', 'FE_DATA', 'FE_TABLE', 'FRAME',
+            'FRAMESET', 'META', 'PAGE', 'plugin'
+            ),
+
+        // Content Objects (cObject) : http://documentation.typo3.org/documentation/tsref/cobjects/
+        4 => array(
+            'CASE', 'CLEARGIF', 'COA', 'COA_INT', 'COBJ_ARRAY', 'COLUMNS',
+            'CONTENT', 'CTABLE', 'EDITPANEL', 'FILE', 'FORM',
+            'HMENU', 'HRULER', 'HTML', 'IMAGE', 'IMGTEXT',
+            'IMG_RESOURCE', 'LOAD_REGISTER', 'MULTIMEDIA',
+            'OTABLE', 'PHP_SCRIPT', 'PHP_SCRIPT_EXT',
+            'PHP_SCRIPT_INT', 'RECORDS', 'RESTORE_REGISTER',
+            'SEARCHRESULT', 'TEMPLATE', 'TEXT', 'USER',
+            'USER_INT'
+            ),
+
+        // GIFBUILDER toplevel link: http://documentation.typo3.org/documentation/tsref/gifbuilder/
+        5 => array(
+            'GIFBUILDER',
+            ),
+
+        // GIFBUILDER: http://documentation.typo3.org/documentation/tsref/gifbuilder/
+        // skipped fields: IMAGE, TEXT
+        // NOTE! the IMAGE and TEXT field already are linked in group 4, they
+        // cannot be linked twice . . . . unfortunately
+        6 => array(
+            'ADJUST', 'BOX', 'CROP', 'EFFECT', 'EMBOSS',
+            'IMGMAP', 'OUTLINE', 'SCALE', 'SHADOW',
+            'WORKAREA'
+            ),
+
+        // MENU Objects: http://documentation.typo3.org/documentation/tsref/menu/
+        7 => array(
+            'GMENU', 'GMENU_FOLDOUT', 'GMENU_LAYERS', 'IMGMENU',
+            'IMGMENUITEM', 'JSMENU', 'JSMENUITEM', 'TMENU',
+            'TMENUITEM', 'TMENU_LAYERS'
+            ),
+
+        // MENU common properties: http://documentation.typo3.org/documentation/tsref/menu/common-properties/
+        8 => array(
+            'alternativeSortingField', 'begin', 'debugItemConf',
+            'imgNameNotRandom', 'imgNamePrefix',
+            'itemArrayProcFunc', 'JSWindow', 'maxItems',
+            'minItems', 'overrideId', 'sectionIndex',
+            'showAccessRestrictedPages', 'submenuObjSuffixes'
+            ),
+
+        // MENU item states: http://documentation.typo3.org/documentation/tsref/menu/item-states/
+        9 => array(
+            'ACT', 'ACTIFSUB', 'ACTIFSUBRO', 'ACTRO', 'CUR', 'CURIFSUB',
+            'CURIFSUBRO', 'CURRO', 'IFSUB', 'IFSUBRO', 'NO',
+            'SPC', 'USERDEF1', 'USERDEF1RO', 'USERDEF2',
+            'USERDEF2RO', 'USR', 'USRRO'
+            ),
+        ),
+
+    // Does not include '-' because of stuff like htmlTag_langKey = en-GB and
+    // lib.nav-sub
+    'SYMBOLS' => array(
+        0 => array(
+            '|',
+            '+', '*', '/', '%',
+            '!', '&&', '^',
+            '<', '>', '=',
+            '?', ':',
+            '.'
+            ),
+        1 => array(
+            '(', ')', '{', '}', '[', ']'
+            )
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true,
+        4 => true,
+        5 => true,
+        6 => true,
+        7 => true,
+        8 => true,
+        9 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #ed7d14;',
+            2 => 'font-weight: bold;',
+            3 => 'color: #990000; font-weight: bold;',
+            4 => 'color: #990000; font-weight: bold;',
+            5 => 'color: #990000; font-weight: bold;',
+            6 => 'color: #990000; font-weight: bold;',
+            7 => 'color: #990000; font-weight: bold;',
+            8 => 'font-weight: bold;',
+            9 => 'color: #990000; font-weight: bold;',
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #aaa; font-style: italic;',
+            2 => 'color: #aaa; font-style: italic;',
+            'MULTI' => 'color: #aaa; font-style: italic;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ac14aa;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc0000;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #0000e0; font-weight: bold;',
+            2 => 'color: #0000e0; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #009900;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #339933; font-weight: bold;',
+                // Set this to the same value as brackets above
+            1 => 'color: #009900; font-weight: bold;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #009900;',
+            1 => 'color: #009900; font-weight: bold;',
+            2 => 'color: #3366CC;',
+            3 => 'color: #000066; font-weight: bold;',
+            4 => 'color: #ed7d14;',
+            5 => 'color: #000066; font-weight: bold;',
+            6 => 'color: #009900;',
+            7 => 'color: #3366CC;'
+            ),
+        'ESCAPE_CHAR' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => 'http://documentation.typo3.org/documentation/tsref/conditions/{FNAME}/',
+        2 => 'http://documentation.typo3.org/documentation/tsref/functions/{FNAME}/',
+        3 => 'http://documentation.typo3.org/documentation/tsref/tlo-objects/{FNAME}/',
+        4 => 'http://documentation.typo3.org/documentation/tsref/cobjects/{FNAME}/',
+        5 => 'http://documentation.typo3.org/documentation/tsref/gifbuilder/',
+        6 => 'http://documentation.typo3.org/documentation/tsref/gifbuilder/{FNAME}/',
+        7 => 'http://documentation.typo3.org/documentation/tsref/menu/{FNAME}/',
+        8 => 'http://documentation.typo3.org/documentation/tsref/menu/common-properties/',
+        9 => 'http://documentation.typo3.org/documentation/tsref/menu/item-states/'
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+            // Constant
+        0 => array(
+            GESHI_SEARCH => '(\{)(\$[a-zA-Z_\.]+[a-zA-Z0-9_\.]*)(\})',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => '\\3'
+            ),
+
+            // Constant dollar sign
+        1 => array(
+            GESHI_SEARCH => '(\$)([a-zA-Z_\.]+[a-zA-Z0-9_\.]*)',
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => '\\2'
+            ),
+
+            // xhtml tag
+        2 => array(
+            GESHI_SEARCH => '(&lt;[a-zA-Z\!\/].*?&gt;)',
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => 's',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+
+            // extension keys / tables: (static|user|ttx|tx|tt|fe)_something[_something]
+        3 => array(
+            GESHI_SEARCH => '(plugin\.|[^\.]\b)((?:static|user|ttx|tx|tt|fe)(?:_[0-9A-Za-z_]+?)\b)',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => ''
+            ),
+
+            // conditions and controls
+        4 => array(
+            GESHI_SEARCH => '(\[)(globalVar|global|end)\b',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => 'i',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => ''
+            ),
+
+            // lowlevel setup and constant objects
+        5 => array(
+            GESHI_SEARCH => '([^\.\$-\{]\b)(cObj|field|config|content|file|frameset|includeLibs|lib|page|plugin|register|resources|sitemap|sitetitle|styles|temp|tt_content|tt_news|types|xmlnews)\b',
+            GESHI_REPLACE => '\\2',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '\\1',
+            GESHI_AFTER => ''
+            ),
+
+            // markers
+        6 => array(
+            GESHI_SEARCH => '(###[^#]+###)',
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+
+            // hex color codes
+        7 => array(
+            GESHI_SEARCH => '(#[a-fA-F0-9]{6}\b|#[a-fA-F0-9]{3}\b)',
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            )
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/vb.php b/examples/includes/geshi/geshi/vb.php
new file mode 100644 (file)
index 0000000..0409058
--- /dev/null
@@ -0,0 +1,133 @@
+<?php
+/*************************************************************************************
+ * vb.php
+ * ------
+ * Author: Roberto Rossi (rsoftware@altervista.org)
+ * Copyright: (c) 2004 Roberto Rossi (http://rsoftware.altervista.org),
+ *                     Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/08/30
+ *
+ * Visual Basic language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/08/27 (1.0.8.1)
+ *  -  changed keyword list for better Visual Studio compliance
+ * 2008/08/26 (1.0.8.1)
+ *  -  Fixed multiline comments
+ * 2004/11/27 (1.0.1)
+ *  -  Added support for multiple object splitters
+ * 2004/08/30 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Visual Basic',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array(),
+    'COMMENT_REGEXP' => array(
+        // Comments (either single or multiline with _
+        1 => '/\'.*(?<! _)\n/sU',
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            'AddressOf', 'Alias', 'And', 'Append', 'As', 'BF', 'Binary',
+            'Boolean', 'ByRef', 'Byte', 'ByVal', 'Call', 'Case', 'CBool',
+            'CByte', 'CCur', 'CDate', 'CDbl', 'CDec', 'CInt', 'CLng',
+            'Close', 'Collection', 'Const', 'Control', 'CSng', 'CStr',
+            'Currency', 'CVar', 'Date', 'Declare', 'Dim', 'Do', 'Double',
+            'Each', 'Else', 'ElseIf', 'End', 'Enum', 'Erase', 'Error',
+            'Event', 'Exit', 'Explicit', 'False', 'For', 'Friend',
+            'Function', 'Get', 'GoSub', 'Goto', 'If', 'Implements', 'In',
+            'Input', 'Integer', 'Is', 'LBound', 'Let', 'Lib', 'Like',
+            'Line', 'Long', 'Loop', 'Mod', 'New', 'Next', 'Not',
+            'Nothing', 'Object', 'On', 'Open', 'Option', 'Optional',
+            'Or', 'Output', 'ParamArray', 'Preserve', 'Print', 'Private',
+            'Property', 'Public', 'RaiseEvent', 'Random', 'ReDim',
+            'Resume', 'Select', 'Set', 'Single', 'Static', 'Step',
+            'Stop', 'String', 'Sub', 'Then', 'To', 'True', 'Type',
+            'TypeOf', 'UBound', 'Until', 'Variant', 'While', 'With',
+            'WithEvents', 'Xor'
+            )
+        ),
+    'SYMBOLS' => array(
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000080;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #008000;'
+            ),
+        'BRACKETS' => array(
+            ),
+        'STRINGS' => array(
+            0 => 'color: #800000;'
+            ),
+        'NUMBERS' => array(
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #800000; font-weight: bold;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'PARSER_CONTROL' => array(
+        'ENABLE_FLAGS' => array(
+            'BRACKETS' => GESHI_NEVER,
+            'SYMBOLS' => GESHI_NEVER,
+            'NUMBERS' => GESHI_NEVER
+            )
+        )
+);
+
+?>
\ No newline at end of file
diff --git a/examples/includes/geshi/geshi/vbnet.php b/examples/includes/geshi/geshi/vbnet.php
new file mode 100644 (file)
index 0000000..4a0f000
--- /dev/null
@@ -0,0 +1,201 @@
+<?php
+/*************************************************************************************
+ * vbnet.php
+ * ---------
+ * Author: Alan Juden (alan@judenware.org)
+ * Copyright: (c) 2004 Alan Juden, Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/06/04
+ *
+ * VB.NET language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2004/11/27 (1.0.0)
+ *  -  Initial release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'vb.net',
+    'COMMENT_SINGLE' => array(1 => "'"),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            '3DDKSHADOW', '3DHIGHLIGHT', '3DLIGHT', 'ABORT', 'ABORTRETRYIGNORE', 'ACTIVEBORDER',
+            'ACTIVETITLEBAR', 'ALIAS', 'APPLICATIONMODAL', 'APPLICATIONWORKSPACE', 'ARCHIVE',
+            'BACK', 'BINARYCOMPARE', 'BLACK', 'BLUE', 'BUTTONFACE', 'BUTTONSHADOW', 'BUTTONTEXT',
+            'CANCEL', 'CDROM', 'CR', 'CRITICAL', 'CRLF', 'CYAN', 'DEFAULT', 'DEFAULTBUTTON1',
+            'DEFAULTBUTTON2', 'DEFAULTBUTTON3', 'DESKTOP', 'DIRECTORY', 'EXCLAMATION', 'FALSE',
+            'FIXED', 'FORAPPENDING', 'FORMFEED', 'FORREADING', 'FORWRITING', 'FROMUNICODE',
+            'GRAYTEXT', 'GREEN', 'HIDDEN', 'HIDE', 'HIGHLIGHT', 'HIGHLIGHTTEXT', 'HIRAGANA',
+            'IGNORE', 'INACTIVEBORDER', 'INACTIVECAPTIONTEXT', 'INACTIVETITLEBAR', 'INFOBACKGROUND',
+            'INFORMATION', 'INFOTEXT', 'KATAKANALF', 'LOWERCASE', 'MAGENTA', 'MAXIMIZEDFOCUS',
+            'MENUBAR', 'MENUTEXT', 'METHOD', 'MINIMIZEDFOCUS', 'MINIMIZEDNOFOCUS', 'MSGBOXRIGHT',
+            'MSGBOXRTLREADING', 'MSGBOXSETFOREGROUND', 'NARROW', 'NEWLINE', 'NO', 'NORMAL',
+            'NORMALFOCUS', 'NORMALNOFOCUS', 'NULLSTRING', 'OBJECTERROR', 'OK', 'OKCANCEL', 'OKONLY',
+            'PROPERCASE', 'QUESTION', 'RAMDISK', 'READONLY', 'RED', 'REMOTE', 'REMOVABLE', 'RETRY',
+            'RETRYCANCEL', 'SCROLLBARS', 'SYSTEMFOLDER', 'SYSTEMMODAL', 'TEMPORARYFOLDER',
+            'TEXTCOMPARE', 'TITLEBARTEXT', 'TRUE', 'UNICODE', 'UNKNOWN', 'UPPERCASE', 'VERTICALTAB',
+            'VOLUME', 'WHITE', 'WIDE', 'WIN16', 'WIN32', 'WINDOWBACKGROUND', 'WINDOWFRAME',
+            'WINDOWSFOLDER', 'WINDOWTEXT', 'YELLOW', 'YES', 'YESNO', 'YESNOCANCEL'
+            ),
+        2 => array(
+            'AndAlso', 'As', 'ADDHANDLER', 'ASSEMBLY', 'AUTO', 'Binary', 'ByRef', 'ByVal', 'BEGINEPILOGUE',
+            'Else', 'ElseIf', 'Empty', 'Error', 'ENDPROLOGUE', 'EXTERNALSOURCE', 'ENVIRON', 'For',
+            'Friend', 'GET', 'HANDLES', 'Input', 'Is', 'IsNot', 'Len', 'Lock', 'Me', 'Mid', 'MUSTINHERIT', 'MustOverride',
+            'MYBASE', 'MYCLASS', 'New', 'Next', 'Nothing', 'Null', 'NOTINHERITABLE',
+            'NOTOVERRIDABLE', 'OFF', 'On', 'Option', 'Optional', 'Overloads', 'OVERRIDABLE', 'Overrides', 'ParamArray',
+            'Print', 'Private', 'Property', 'Public', 'Resume', 'Return', 'Seek', 'Static', 'Step',
+            'String', 'SHELL', 'SENDKEYS', 'SET', 'Shared', 'Then', 'Time', 'To', 'THROW', 'WithEvents'
+            ),
+        3 => array(
+            'COLLECTION', 'DEBUG', 'DICTIONARY', 'DRIVE', 'DRIVES', 'ERR', 'FILE', 'FILES',
+            'FILESYSTEMOBJECT', 'FOLDER', 'FOLDERS', 'TEXTSTREAM'
+            ),
+        4 => array(
+            'BOOLEAN', 'BYTE', 'DATE', 'DECIMIAL', 'DOUBLE', 'INTEGER', 'LONG', 'OBJECT',
+            'SINGLE STRING'
+            ),
+        5 => array(
+            'ADDRESSOF', 'AND', 'BITAND', 'BITNOT', 'BITOR', 'BITXOR',
+            'GETTYPE', 'LIKE', 'MOD', 'NOT', 'ORXOR'
+            ),
+        6 => array(
+            'APPACTIVATE', 'BEEP', 'CALL', 'CHDIR', 'CHDRIVE', 'CLASS', 'CASE', 'CATCH', 'CONST',
+            'DECLARE', 'DELEGATE', 'DELETESETTING', 'DIM', 'DO', 'DOEVENTS', 'END', 'ENUM',
+            'EVENT', 'EXIT', 'EACH', 'FUNCTION', 'FINALLY', 'IF', 'IMPORTS', 'INHERITS',
+            'INTERFACE', 'IMPLEMENTS', 'KILL', 'LOOP', 'NAMESPACE', 'OPEN', 'PUT',
+            'RAISEEVENT', 'RANDOMIZE', 'REDIM', 'REM', 'RESET', 'SAVESETTING', 'SELECT',
+            'SETATTR', 'STOP', 'SUB', 'SYNCLOCK', 'STRUCTURE', 'SHADOWS', 'SWITCH',
+            'TRY', 'WIDTH', 'WITH', 'WRITE', 'WHILE'
+            ),
+        7 => array(
+            'ABS', 'ARRAY', 'ASC', 'ASCB', 'ASCW', 'CALLBYNAME', 'CBOOL', 'CBYTE', 'CCHAR',
+            'CCHR', 'CDATE', 'CDBL', 'CDEC', 'CHOOSE', 'CHR', 'CHR$', 'CHRB', 'CHRB$', 'CHRW',
+            'CINT', 'CLNG', 'CLNG8', 'CLOSE', 'COBJ', 'COMMAND', 'COMMAND$', 'CONVERSION',
+            'COS', 'CREATEOBJECT', 'CSHORT', 'CSTR', 'CURDIR', 'CTYPE', 'CVDATE', 'DATEADD',
+            'DATEDIFF', 'DATEPART', 'DATESERIAL', 'DATEVALUE', 'DAY', 'DDB', 'DIR', 'DIR$',
+            'EOF', 'ERROR$', 'EXP', 'FILEATTR', 'FILECOPY', 'FILEDATATIME', 'FILELEN', 'FILTER',
+            'FIX', 'FORMAT', 'FORMAT$', 'FORMATCURRENCY', 'FORMATDATETIME', 'FORMATNUMBER',
+            'FORMATPERCENT', 'FREEFILE', 'FV', 'GETALLSETTINGS', 'GETATTRGETOBJECT', 'GETSETTING',
+            'HEX', 'HEX$', 'HOUR', 'IIF', 'IMESTATUS', 'INPUT$', 'INPUTB', 'INPUTB$', 'INPUTBOX',
+            'INSTR', 'INSTRB', 'INSTRREV', 'INT', 'IPMT', 'IRR', 'ISARRAY', 'ISDATE', 'ISEMPTY',
+            'ISERROR', 'ISNULL', 'ISNUMERIC', 'ISOBJECT', 'JOIN', 'LBOUND', 'LCASE', 'LCASE$',
+            'LEFT', 'LEFT$', 'LEFTB', 'LEFTB$', 'LENB', 'LINEINPUT', 'LOC', 'LOF', 'LOG', 'LTRIM',
+            'LTRIM$', 'MID$', 'MIDB', 'MIDB$', 'MINUTE', 'MIRR', 'MKDIR', 'MONTH', 'MONTHNAME',
+            'MSGBOX', 'NOW', 'NPER', 'NPV', 'OCT', 'OCT$', 'PARTITION', 'PMT', 'PPMT', 'PV',
+            'RATE', 'REPLACE', 'RIGHT', 'RIGHT$', 'RIGHTB', 'RIGHTB$', 'RMDIR', 'RND', 'RTRIM',
+            'RTRIM$', 'SECOND', 'SIN', 'SLN', 'SPACE', 'SPACE$', 'SPC', 'SPLIT', 'SQRT', 'STR', 'STR$',
+            'STRCOMP', 'STRCONV', 'STRING$', 'STRREVERSE', 'SYD', 'TAB', 'TAN', 'TIMEOFDAY',
+            'TIMER', 'TIMESERIAL', 'TIMEVALUE', 'TODAY', 'TRIM', 'TRIM$', 'TYPENAME', 'UBOUND',
+            'UCASE', 'UCASE$', 'VAL', 'WEEKDAY', 'WEEKDAYNAME', 'YEAR'
+            ),
+        8 => array(
+            'ANY', 'ATN', 'CALENDAR', 'CIRCLE', 'CURRENCY', 'DEFBOOL', 'DEFBYTE', 'DEFCUR',
+            'DEFDATE', 'DEFDBL', 'DEFDEC', 'DEFINT', 'DEFLNG', 'DEFOBJ', 'DEFSNG', 'DEFSTR',
+            'DEFVAR', 'EQV', 'GOSUB', 'IMP', 'INITIALIZE', 'ISMISSING', 'LET', 'LINE', 'LSET',
+            'RSET', 'SGN', 'SQR', 'TERMINATE', 'VARIANT', 'VARTYPE', 'WEND'
+            ),
+        ),
+    'SYMBOLS' => array(
+        '&', '&=', '*', '*=', '+', '+=', '-', '-=', '//', '/', '/=', '=', '\\', '\\=',
+        '^', '^='
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        5 => false,
+        6 => false,
+        7 => false,
+        8 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0600FF;',        //Constants
+            2 => 'color: #FF8000;',        //Keywords
+            3 => 'color: #008000;',        //Data Types
+            4 => 'color: #FF0000;',        //Objects
+            5 => 'color: #804040;',        //Operators
+            6 => 'color: #0600FF;',        //Statements
+            7 => 'color: #0600FF;',        //Functions
+            8 => 'color: #0600FF;'        //Deprecated
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #008080; font-style: italic;',
+            'MULTI' => 'color: #008080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #008080; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000000;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #808080;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #FF0000;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #0000FF;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #008000;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => 'http://www.google.com/search?q={FNAMEU}+site:msdn.microsoft.com',
+        4 => '',
+        5 => '',
+        6 => '',
+        7 => '',
+        8 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 =>'.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/verilog.php b/examples/includes/geshi/geshi/verilog.php
new file mode 100644 (file)
index 0000000..57d268e
--- /dev/null
@@ -0,0 +1,173 @@
+<?php
+/**
+ * verilog.php
+ * -----------
+ * Author: G�nter Dannoritzer <dannoritzer@web.de>
+ * Copyright: (C) 2008 Guenter Dannoritzer
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/05/28
+ *
+ * Verilog language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/29
+ *   -  added regular expression to find numbers of the form 4'b001xz
+ *   -  added regular expression to find values for `timescale command
+ *   -  extended macro keywords
+ *
+ * TODO (updated 2008/05/29)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Verilog',
+    'COMMENT_SINGLE' => array(1 => '//'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'COMMENT_REGEXP' => array(1 => '/\/\/(?:\\\\\\\\|\\\\\\n|.)*$/m'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        // keywords
+        1 => array('always', 'and', 'assign', 'begin', 'buf', 'bufif0', 'bufif1', 'case',
+            'casex', 'casez', 'cmos', 'deassign', 'default', 'defparam',
+            'disable', 'edge', 'else', 'end', 'endcase', 'endfunction',
+            'endmodule', 'endprimitive', 'endspecify', 'endtable', 'endtask',
+            'event', 'for', 'force', 'forever', 'function', 'highz0',
+            'highz1', 'if', 'ifnone', 'initial', 'inout', 'input', 'integer',
+            'join', 'large', 'macromodule', 'medium', 'module', 'nand',
+            'negedge', 'nmos', 'nor', 'not', 'notif0', 'notif1', 'or',
+            'output', 'parameter', 'pmos', 'posedge', 'primitive', 'pull0',
+            'pull1', 'pulldown', 'pullup', 'rcmos', 'real', 'realtime', 'reg',
+            'release', 'repeat', 'rnmos', 'rpmos', 'rtran', 'rtranif0',
+            'rtranif1', 'scalared', 'small', 'specify', 'specparam',
+            'strong0', 'strong1', 'supply0', 'supply1', 'table', 'task',
+            'time', 'tran', 'tranif0', 'tranif1', 'tri', 'tri0', 'tri1',
+            'triand', 'trior', 'trireg', 'vectored', 'wait', 'wand', 'weak0',
+            'weak1', 'while', 'wire', 'wor', 'xnor', 'xor'
+            ),
+        // system tasks
+        2 => array(
+            '$display', '$monitor',
+            '$dumpall', '$dumpfile', '$dumpflush', '$dumplimit', '$dumpoff',
+            '$dumpon', '$dumpvars',
+            '$fclose', '$fdisplay', '$fopen',
+            '$finish', '$fmonitor', '$fstrobe', '$fwrite',
+            '$fgetc', '$ungetc', '$fgets', '$fscanf', '$fread', '$ftell',
+            '$fseek', '$frewind', '$ferror', '$fflush', '$feof',
+            '$random',
+            '$readmemb', '$readmemh', '$readmemx',
+            '$signed', '$stime', '$stop',
+            '$strobe', '$time', '$unsigned', '$write'
+            ),
+        // macros
+        3 => array(
+            '`default-net', '`define',
+            '`celldefine', '`default_nettype', '`else', '`elsif', '`endcelldefine',
+            '`endif', '`ifdef', '`ifndef', '`include', '`line', '`nounconnected_drive',
+            '`resetall', '`timescale', '`unconnected_drive', '`undef'
+            ),
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '{', '}', '[', ']', '=', '+', '-', '*', '/', '!', '%',
+        '^', '&', '|', '~',
+        '?', ':',
+        '#', '<<', '<<<',
+        '>', '<', '>=', '<=',
+        '@', ';', ','
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #A52A2A; font-weight: bold;',
+            2 => 'color: #9932CC;',
+            3 => 'color: #008800;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #00008B; font-style: italic;',
+            'MULTI' => 'color: #00008B; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #9F79EE'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #9F79EE;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #FF00FF;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #ff0055;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #202020;',
+            2 => 'color: #202020;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #5D478B;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #ff0055;',
+            1 => 'color: #ff0055;',
+            ),
+        'SCRIPT' => array(
+            0 => '',
+            1 => '',
+            2 => '',
+            3 => ''
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        1 => ''
+        ),
+    'REGEXPS' => array(
+        // numbers
+        0 => "\d'[bdh][0-9_a-fA-FxXzZ]+",
+        // time -> 1, 10, or 100; s, ms, us, ns, ps, of fs
+        1 => "1[0]{0,2}[munpf]?s"
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        1 => ''
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        0 => true,
+        1 => true,
+        2 => true,
+        3 => true
+        ),
+    'TAB_WIDTH' => 4
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/vhdl.php b/examples/includes/geshi/geshi/vhdl.php
new file mode 100644 (file)
index 0000000..6fd537e
--- /dev/null
@@ -0,0 +1,144 @@
+<?php
+/*************************************************************************************
+ * vhdl.php
+ * --------
+ * Author: Alexander 'E-Razor' Krause (admin@erazor-zone.de)
+ * Copyright: (c) 2005 Alexander Krause
+ * Release Version: 1.0.8.3
+ * Date Started: 2005/06/15
+ *
+ * VHDL (VHSICADL, very high speed integrated circuit HDL) language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *  -  Added description of extra language features (SF#1970248)
+ *  -  Optimized regexp group 0 somewhat
+ * 2006/06/15 (1.0.0)
+ *  -  First Release
+ *
+ * TODO
+ * ----
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'VHDL',
+    'COMMENT_SINGLE' => array(1 => '--'),
+    'COMMENT_MULTI' => array('%' => '%'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        /*keywords*/
+        1 => array(
+            'access','after','alias','all','assert','attribute','architecture','begin',
+            'block','body','buffer','bus','case','component','configuration','constant',
+            'disconnect','downto','else','elsif','end','entity','exit','file','for',
+            'function','generate','generic','group','guarded','if','impure','in',
+            'inertial','inout','is','label','library','linkage','literal','loop',
+            'map','new','next','null','of','on','open','others','out','package',
+            'port','postponed','procedure','process','pure','range','record','register',
+            'reject','report','return','select','severity','signal','shared','subtype',
+            'then','to','transport','type','unaffected','units','until','use','variable',
+            'wait','when','while','with','note','warning','error','failure','and',
+            'or','xor','not','nor','used','memory','segments','dff','dffe','help_id',
+            'mod','info','latch','rising_edge','falling_edge'
+        ),
+        /*types*/
+        2 => array(
+            'bit','bit_vector','character','boolean','integer','real','time','string',
+            'severity_level','positive','natural','signed','unsigned','line','text',
+            'std_logic','std_logic_vector','std_ulogic','std_ulogic_vector','qsim_state',
+            'qsim_state_vector','qsim_12state','qsim_12state_vector','qsim_strength',
+            'mux_bit','mux_vector','reg_bit','reg_vector','wor_bit','wor_vector',
+            'work','ieee','std_logic_signed','std_logic_1164','std_logic_arith',
+            'numeric_std'
+
+        ),
+        /*operators*/
+    ),
+    'SYMBOLS' => array(
+        '[', ']', '(', ')',
+        ';',':',
+        '<','>','=','<=',':=','=>','=='
+    ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #000080; font-weight: bold;',
+            2 => 'color: #0000ff;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #008000; font-style: italic;',
+            'MULTI' => 'color: #008000; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000066;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #7f007f;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000066;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #ff0000;',
+            1 => 'color: #ff0000;'
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => ''
+    ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        //Hex numbers and scientific notation for numbers
+        0 => '(\b0x[0-9a-fA-F]+|\b\d[0-9a-fA-F]+[hH])|'.
+            '(\b\d+?(\.\d+?)?E[+\-]?\d+)|(\bns)|'.
+            "('[0-9a-zA-Z]+(?!'))",
+        //Number characters?
+        1 => "\b(''\d'')"
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/vim.php b/examples/includes/geshi/geshi/vim.php
new file mode 100644 (file)
index 0000000..94927ea
--- /dev/null
@@ -0,0 +1,185 @@
+<?php
+
+/*************************************************************************************
+ * vim.php
+ * ----------------
+ * Author: Swaroop C H (swaroop@swaroopch.com)
+ * Copyright: (c) 2008 Swaroop C H (http://www.swaroopch.com)
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/10/19
+ *
+ * Vim scripting language file for GeSHi.
+ *
+ * Reference: http://qbnz.com/highlighter/geshi-doc.html#language-files
+ * All keywords scraped from `:help expression-commands`.
+ * All method names scraped from `:help function-list`.
+ *
+ * CHANGES
+ * -------
+ * 2008/10/19 (1.0.8.2)
+ * - Started.
+ *
+ * TODO (updated 2008/10/19)
+ * -------------------------
+ * - Fill out list of zillion commands
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array(
+    'LANG_NAME' => 'Vim Script',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_REGEXP' => array(
+        1 => "/^\".*$/m"
+        ),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'brea', 'break', 'call', 'cat', 'catc',
+            'catch', 'con', 'cont', 'conti',
+            'contin', 'continu', 'continue', 'ec', 'echo',
+            'echoe', 'echoer', 'echoerr', 'echoh',
+            'echohl', 'echom', 'echoms', 'echomsg', 'echon',
+            'el', 'els', 'else', 'elsei', 'elseif',
+            'en', 'end', 'endi', 'endif', 'endfo',
+            'endfor', 'endt', 'endtr', 'endtry', 'endw',
+            'endwh', 'endwhi', 'endwhil', 'endwhile', 'exe', 'exec', 'execu',
+            'execut', 'execute', 'fina', 'final', 'finall', 'finally', 'for',
+            'fun', 'func', 'funct', 'functi', 'functio', 'function', 'if', 'in',
+            'let', 'lockv', 'lockva', 'lockvar', 'retu', 'retur', 'return', 'th',
+            'thr', 'thro', 'throw', 'try', 'unl', 'unle', 'unlet', 'unlo', 'unloc',
+            'unlock', 'unlockv', 'unlockva', 'unlockvar', 'wh', 'whi', 'whil',
+            'while'
+            ),
+        2 => array(
+            'autocmd', 'com', 'comm', 'comma', 'comman', 'command', 'comc',
+            'comcl', 'comcle', 'comclea', 'comclear', 'delc', 'delco',
+            'delcom', 'delcomm', 'delcomma', 'delcomman', 'delcommand',
+            '-nargs' # TODO There are zillions of commands to be added here from http://vimdoc.sourceforge.net/htmldoc/usr_toc.html
+            ),
+        3 => array(
+            'abs', 'add', 'append', 'argc', 'argidx', 'argv', 'atan',
+            'browse', 'browsedir', 'bufexists', 'buflisted', 'bufloaded',
+            'bufname', 'bufnr', 'bufwinnr', 'byte2line', 'byteidx',
+            'ceil', 'changenr', 'char2nr', 'cindent', 'clearmatches',
+            'col', 'complete', 'complete_add', 'complete_check', 'confirm',
+            'copy', 'cos', 'count', 'cscope_connection', 'cursor',
+            'deepcopy', 'delete', 'did_filetype', 'diff_filler',
+            'diff_hlID', 'empty', 'escape', 'eval', 'eventhandler',
+            'executable', 'exists', 'extend', 'expand', 'feedkeys',
+            'filereadable', 'filewritable', 'filter', 'finddir',
+            'findfile', 'float2nr', 'floor', 'fnameescape', 'fnamemodify',
+            'foldclosed', 'foldclosedend', 'foldlevel', 'foldtext',
+            'foldtextresult', 'foreground', 'garbagecollect',
+            'get', 'getbufline', 'getbufvar', 'getchar', 'getcharmod',
+            'getcmdline', 'getcmdpos', 'getcmdtype', 'getcwd', 'getfperm',
+            'getfsize', 'getfontname', 'getftime', 'getftype', 'getline',
+            'getloclist', 'getmatches', 'getpid', 'getpos', 'getqflist',
+            'getreg', 'getregtype', 'gettabwinvar', 'getwinposx',
+            'getwinposy', 'getwinvar', 'glob', 'globpath', 'has',
+            'has_key', 'haslocaldir', 'hasmapto', 'histadd', 'histdel',
+            'histget', 'histnr', 'hlexists', 'hlID', 'hostname', 'iconv',
+            'indent', 'index', 'input', 'inputdialog', 'inputlist',
+            'inputrestore', 'inputsave', 'inputsecret', 'insert',
+            'isdirectory', 'islocked', 'items', 'join', 'keys', 'len',
+            'libcall', 'libcallnr', 'line', 'line2byte', 'lispindent',
+            'localtime', 'log10', 'map', 'maparg', 'mapcheck', 'match',
+            'matchadd', 'matcharg', 'matchdelete', 'matchend', 'matchlist',
+            'matchstr', 'max', 'min', 'mkdir', 'mode', 'nextnonblank',
+            'nr2char', 'pathshorten', 'pow', 'prevnonblank', 'printf',
+            'pumvisible', 'range', 'readfile', 'reltime', 'reltimestr',
+            'remote_expr', 'remote_foreground', 'remote_peek',
+            'remote_read', 'remote_send', 'remove', 'rename', 'repeat',
+            'resolve', 'reverse', 'round', 'search', 'searchdecl',
+            'searchpair', 'searchpairpos', 'searchpos', 'server2client',
+            'serverlist', 'setbufvar', 'setcmdpos', 'setline',
+            'setloclist', 'setmatches', 'setpos', 'setqflist', 'setreg',
+            'settabwinvar', 'setwinvar', 'shellescape', 'simplify', 'sin',
+            'sort', 'soundfold', 'spellbadword', 'spellsuggest', 'split',
+            'sqrt', 'str2float', 'str2nr', 'strftime', 'stridx', 'string',
+            'strlen', 'strpart', 'strridx', 'strtrans', 'submatch',
+            'substitute', 'synID', 'synIDattr', 'synIDtrans', 'synstack',
+            'system', 'tabpagebuflist', 'tabpagenr', 'tabpagewinnr',
+            'taglist', 'tagfiles', 'tempname', 'tolower', 'toupper', 'tr',
+            'trunc', 'type', 'values', 'virtcol', 'visualmode', 'winbufnr',
+            'wincol', 'winheight', 'winline', 'winnr', 'winrestcmd',
+            'winrestview', 'winsaveview', 'winwidth', 'writefile'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}', '!', '%', '&', '*', '|', '/', '<', '>',
+        '^', '-', '+', '~', '?', ':', '$', '@', '.'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => true,
+        2 => true,
+        3 => true
+        ),
+    'STYLES' => array(
+        'BRACKETS' => array(
+            0 => 'color: #000000;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #adadad; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => ''
+            ),
+        'KEYWORDS' => array(
+            1 => 'color: #804040;',
+            2 => 'color: #668080;',
+            3 => 'color: #25BB4D;'
+            ),
+        'METHODS' => array(
+            0 => 'color: #000000;',
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #000000; font-weight:bold;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            ),
+        'STRINGS' => array(
+            0 => 'color: #C5A22D;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000000;'
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => ''
+        ),
+    'OOLANG' => false, //Save some time as OO identifiers aren't used
+    'OBJECT_SPLITTERS' => array(),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(),
+    'HIGHLIGHT_STRICT_BLOCK' => array()
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/visualfoxpro.php b/examples/includes/geshi/geshi/visualfoxpro.php
new file mode 100644 (file)
index 0000000..4592dd7
--- /dev/null
@@ -0,0 +1,456 @@
+<?php
+/*************************************************************************************
+ * visualfoxpro.php
+ * ----------------
+ * Author: Roberto Armellin (r.armellin@tin.it)
+ * Copyright: (c) 2004 Roberto Armellin, Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/09/17
+ *
+ * Visual FoxPro language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *  -  Removed tab as a symbol char
+ * 2004/11/27 (1.0.1)
+ *  -  Added support for multiple object splitters
+ * 2004/10/27 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2004/10/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Visual Fox Pro',
+    'COMMENT_SINGLE' => array(1 => "//", 2 => "\n*"),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'Case', 'Else', '#Else', 'Then',
+            'Endcase', 'Enddefine', 'Enddo', 'Endfor', 'Endfunc', 'Endif', 'Endprintjob',
+            'Endproc', 'Endscan', 'Endtext', 'Endwith', '#Endif',
+            '#Elif','#Define','#If','#Include',
+            '#Itsexpression','#Readclauses','#Region','#Section','#Undef','#Wname',
+            'Define','Do',
+            'For','Function','Hidden',
+            'If','Local','Lparameter','Lparameters','Next','Otherwise',
+            'Parameters','Printjob','Procedure','Protected','Public','Scan',
+            'Text','While','With','Abs','Accept','Access','Aclass','Acopy',
+            'Acos','Adatabases','Adbobjects','Addbs','Addrelationtoenv','Addtabletoenv',
+            'Adel','Adir','Aelement','Aerror','Afields','Afont',
+            'Agetclass','Agetfileversion','Ains','Ainstance','Alen','Align',
+            'Alines','Alltrim','Alter','Amembers','Amouseobj','Anetresources',
+            'Ansitooem','Append','Aprinters','Ascan','Aselobj','Asin',
+            'Asort','Assert','Asserts','Assist','Asubscript','Asynchronous',
+            'At_c','Atan','Atc','Atcc','Atcline','Atline',
+            'Atn2','Aused','Autoform','Autoreport','Avcxclasses','Average',
+            'BarCount','BarPrompt','BatchMode','BatchUpdateCount','Begin','BellSound',
+            'BinToC','Bintoc','Bitand','Bitclear','Bitlshift','Bitnot',
+            'Bitor','Bitrshift','Bitset','Bittest','Bitxor','Bof',
+            'Browse','BrowseRefresh','Buffering','BuilderLock','COMArray','COMReturnError',
+            'CToBin','Calculate','Call','Capslock','Cd','Cdow',
+            'Ceiling','Central','Change','Char','Chdir','Chr',
+            'Chrsaw','Chrtran','Chrtranc','Close','Cmonth','Cntbar',
+            'Cntpad','Col','Comclassinfo','CommandTargetQuery','Compile','Completed',
+            'Compobj','Compute','Concat','ConnectBusy','ConnectHandle','ConnectName',
+            'ConnectString','ConnectTimeOut','ContainerReleaseType','Continue','Copy','Cos',
+            'Cot','Count','Coverage','Cpconvert','Cpcurrent','Cpdbf',
+            'Cpnotrans','Create','CreateBinary','Createobject','Createobjectex','Createoffline',
+            'CrsBuffering','CrsFetchMemo','CrsFetchSize','CrsMaxRows','CrsMethodUsed','CrsNumBatch',
+            'CrsShareConnection','CrsUseMemoSize','CrsWhereClause','Ctobin','Ctod','Ctot',
+            'Curdate','Curdir','CurrLeft','CurrSymbol','CursorGetProp','CursorSetProp',
+            'Curtime','Curval','DBGetProp','DBSetProp','DB_BufLockRow','DB_BufLockTable',
+            'DB_BufOff','DB_BufOptRow','DB_BufOptTable','DB_Complette','DB_DeleteInsert','DB_KeyAndModified',
+            'DB_KeyAndTimestamp','DB_KeyAndUpdatable','DB_LocalSQL','DB_NoPrompt','DB_Prompt','DB_RemoteSQL',
+            'DB_TransAuto','DB_TransManual','DB_TransNone','DB_Update','Datetime','Day',
+            'Dayname','Dayofmonth','Dayofweek','Dayofyear','Dbalias','Dbused',
+            'Ddeaborttrans','Ddeadvise','Ddeenabled','Ddeexecute','Ddeinitiate','Ddelasterror',
+            'Ddepoke','Dderequest','Ddesetoption','Ddesetservice','Ddesettopic','Ddeterminate',
+            'Debugout','Declare','DefOLELCid','DefaultValue','Defaultext','Degrees',
+            'DeleteTrigger','Desc','Description','Difference','Dimension','Dir',
+            'Directory','Diskspace','DispLogin','DispWarnings','Display','Dll',
+            'Dmy','DoDefault','DoEvents','Doc','Doevents','Dow',
+            'Drivetype','Drop','Dropoffline','Dtoc','Dtor','Dtos',
+            'Dtot','DynamicInputMask','Each','Edit','Eject','Elif',
+            'End','Eof','Erase','Evaluate','Event','Eventtracking',
+            'Exclude','Exclusive','Exit','Exp','Export','External',
+            'FDate','FTime','Fchsize','Fclose','Fcount','Fcreate',
+            'Feof','Ferror','FetchMemo','FetchSize','Fflush','Fgets',
+            'Filer','Filetostr','Find','Fklabel','Fkmax','Fldlist',
+            'Flock','Floor','Flush','Fontmetric','Fopen','Forceext',
+            'Forcepath','FormSetClass','FormSetLib','FormsClass','FormsLib','Found',
+            'FoxPro','Foxcode','Foxdoc','Foxgen','Foxgraph','Foxview',
+            'Fputs','Fread','French','Fseek','Fsize','Fv',
+            'Fwrite','Gather','German','GetPem','Getbar','Getcolor',
+            'Getcp','Getdir','Getenv','Getexpr','Getfile','Getfldstate',
+            'Getfont','Gethost','Getnextmodified','Getobject','Getpad','Getpict',
+            'Getprinter','Go','Gomonth','Goto','Graph','GridHorz',
+            'GridShow','GridShowPos','GridSnap','GridVert','Help','HelpOn',
+            'HelpTo','HighLightRow','Home','Hour','IMEStatus','IdleTimeOut',
+            'Idxcollate','Ifdef','Ifndef','Iif','Import','Include',
+            'Indbc','Index','Indexseek','Inkey','Inlist','Input',
+            'Insert','InsertTrigger','Insmode','IsBlank','IsFLocked','IsLeadByte',
+            'IsMouse','IsNull','IsRLocked','Isalpha','Iscolor','Isdigit',
+            'Isexclusive','Isflocked','Ishosted','Islower','Isreadonly','Isrlocked',
+            'Isupper','Italian','Japan','Join','Justdrive','Justext',
+            'Justfname','Justpath','Juststem','KeyField','KeyFieldList','Keyboard'
+            ),
+        2 => array('Keymatch','LastProject','Lastkey','Lcase','Leftc','Len',
+            'Lenc','Length','Likec','Lineno','LoadPicture','Loadpicture',
+            'Locate','Locfile','Log','Log10','Logout','Lookup',
+            'Loop','Lower','Ltrim','Lupdate','Mail','MaxRecords',
+            'Mcol','Md','Mdown','Mdx','Mdy','Memlines',
+            'Menu','Messagebox','Minute','Mkdir','Mline','Modify',
+            'Month','Monthname','Mouse','Mrkbar','Mrkpad','Mrow',
+            'Mtdll','Mton','Mwindow','Native','Ndx','Network',
+            'NoFilter','Nodefault','Normalize','Note','Now','Ntom',
+            'NullString','Numlock','Nvl','ODBChdbc','ODBChstmt','OLEDropTextInsertion',
+            'OLELCid','Objnum','Objref','Objtoclient','Objvar','Occurs',
+            'Oemtoansi','Oldval','OlePublic','Olereturnerror','On','Open',
+            'Oracle','Order','Os','Outer','PCount','Pack',
+            'PacketSize','Padc','Padl','Padr','Payment','Pcol',
+            'PemStatus','Pi','Pivot','Play','Pop','Popup',
+            'Power','PrimaryKey','Printstatus','Private','Prmbar','Prmpad',
+            'ProjectClick','Proper','Prow','Prtinfo','Push','Putfile',
+            'Pv','Qpr','Quater','QueryTimeOut','Quit','Radians',
+            'Rand','Rat','Ratc','Ratline','Rd','Rdlevel',
+            'Read','Readkey','Recall','Reccount','RecentlyUsedFiles','Recno',
+            'Recsize','Regional','Reindex','RelatedChild','RelatedTable','RelatedTag',
+            'Remove','Rename','Repeat','Replace','Replicate','Report',
+            'ResHeight','ResWidth','ResourceOn','ResourceTo','Resources','Restore',
+            'Resume','Retry','Return','Revertoffline','Rgbscheme','Rightc',
+            'Rlock','Rmdir','Rollback','Round','Rtod','Rtrim',
+            'RuleExpression','RuleText','Run','Runscript','Rview','SQLAsynchronous',
+            'SQLBatchMode','SQLCancel','SQLColumns','SQLConnect','SQLConnectTimeOut','SQLDisconnect',
+            'SQLDispLogin','SQLDispWarnings','SQLExec','SQLGetProp','SQLIdleTimeOut','SQLMoreResults',
+            'SQLPrepare','SQLQueryTimeOut','SQLSetProp','SQLTables','SQLTransactions','SQLWaitTime',
+            'Save','SavePicture','Savepicture','ScaleUnits','Scatter','Scols',
+            'Scroll','Sec','Second','Seek','Select','SendUpdates',
+            'Set','SetDefault','Setfldstate','Setup','ShareConnection','ShowOLEControls',
+            'ShowOLEInsertable','ShowVCXs','Sign','Sin','Size','SizeBox',
+            'Skpbar','Skppad','Sort','Soundex','SourceName','Sqlcommit',
+            'Sqll','Sqlrollback','Sqlstringconnect','Sqrt','Srows','StatusBar',
+            'Store','Str','Strconv','Strtofile','Strtran','Stuff',
+            'Stuffc','Substr','Substrc','Substring','Sum','Suspend',
+            'Sys','Sysmetric','TabOrdering','Table','TableRefresh','Tablerevert',
+            'Tableupdate','TagCount','TagNo','Tan','Target','This',
+            'Thisform','Thisformset','Timestamp','Timestampdiff','Total','Transactions',
+            'Transform','Trim','Truncate','Ttoc','Ttod','Txnlevel',
+            'Txtwidth','Type','Ucase','Undefine','Unlock','Unpack',
+            'Updatable','UpdatableFieldList','Update','UpdateName','UpdateNameList','UpdateTrigger',
+            'UpdateType','Updated','Upper','Upsizing','Usa','Use',
+            'UseMemoSize','Used','Val','Validate','Varread','Vartype',
+            'Version','VersionLanguage','Wait','WaitTime','Wborder','Wchild',
+            'Wcols','Week','Wexist','Wfont','WhereType','Windcmd',
+            'Windhelp','Windmemo','Windmenu','Windmodify','Windquery','Windscreen',
+            'Windsnip','Windstproc','WizardPrompt','Wlast','Wlcol','Wlrow',
+            'Wmaximum','Wminimum','Wontop','Woutput','Wparent','Wread',
+            'Wrows','Wtitle','Wvisible','Year','Zap','_Alignment',
+            '_Asciicols','_Asciirows','_Assist','_Beautify','_Box','_Browser',
+            '_Builder','_Calcmem','_Calcvalue','_Cliptext','_Converter','_Coverage',
+            '_Curobj','_Dblclick','_Diarydate','_Dos','_Foxdoc','_Foxgraph',
+            '_Gallery','_Gengraph','_Genhtml','_Genmenu','_Genpd','_Genscrn',
+            '_Genxtab','_Getexpr','_Include','_Indent','_Lmargin','_Mac',
+            '_Mbr_appnd','_Mbr_cpart','_Mbr_delet','_Mbr_font','_Mbr_goto','_Mbr_grid',
+            '_Mbr_link','_Mbr_mode','_Mbr_mvfld','_Mbr_mvprt','_Mbr_seek','_Mbr_sp100',
+            '_Mbr_sp200','_Mbr_szfld','_Mbrowse','_Mda_appnd','_Mda_avg','_Mda_brow',
+            '_Mda_calc','_Mda_copy','_Mda_count','_Mda_label','_Mda_pack','_Mda_reprt',
+            '_Mda_rindx','_Mda_setup','_Mda_sort','_Mda_sp100','_Mda_sp200','_Mda_sp300',
+            '_Mda_sum','_Mda_total','_Mdata','_Mdiary','_Med_clear','_Med_copy',
+            '_Med_cut','_Med_cvtst','_Med_find','_Med_finda','_Med_goto','_Med_insob',
+            '_Med_link','_Med_obj','_Med_paste','_Med_pref','_Med_pstlk','_Med_redo',
+            '_Med_repl','_Med_repla','_Med_slcta','_Med_sp100','_Med_sp200','_Med_sp300',
+            '_Med_sp400','_Med_sp500','_Med_undo','_Medit','_Mfi_clall','_Mfi_close',
+            '_Mfi_export','_Mfi_import','_Mfi_new','_Mfi_open','_Mfi_pgset','_Mfi_prevu',
+            '_Mfi_print','_Mfi_quit','_Mfi_revrt','_Mfi_savas','_Mfi_save','_Mfi_send',
+            '_Mfi_setup','_Mfi_sp100','_Mfi_sp200','_Mfi_sp300','_Mfi_sp400','_Mfile',
+            '_Mfiler','_Mfirst','_Mlabel','_Mlast','_Mline','_Mmacro',
+            '_Mmbldr','_Mpr_beaut','_Mpr_cancl','_Mpr_compl','_Mpr_do','_Mpr_docum',
+            '_Mpr_formwz','_Mpr_gener','_Mpr_graph','_Mpr_resum','_Mpr_sp100','_Mpr_sp200',
+            '_Mpr_sp300','_Mpr_suspend','_Mprog','_Mproj','_Mrc_appnd','_Mrc_chnge',
+            '_Mrc_cont','_Mrc_delet','_Mrc_goto','_Mrc_locat','_Mrc_recal','_Mrc_repl',
+            '_Mrc_seek','_Mrc_sp100','_Mrc_sp200','_Mrecord','_Mreport','_Mrqbe',
+            '_Mscreen','_Msm_data','_Msm_edit','_Msm_file','_Msm_format','_Msm_prog',
+            '_Msm_recrd','_Msm_systm','_Msm_text','_Msm_tools','_Msm_view','_Msm_windo',
+            '_Mst_about','_Mst_ascii','_Mst_calcu','_Mst_captr','_Mst_dbase','_Mst_diary',
+            '_Mst_filer','_Mst_help','_Mst_hphow','_Mst_hpsch','_Mst_macro','_Mst_office',
+            '_Mst_puzzl','_Mst_sp100','_Mst_sp200','_Mst_sp300','_Mst_specl','_Msysmenu',
+            '_Msystem','_Mtable','_Mtb_appnd','_Mtb_cpart','_Mtb_delet','_Mtb_delrc',
+            '_Mtb_goto','_Mtb_link','_Mtb_mvfld','_Mtb_mvprt','_Mtb_props','_Mtb_recal',
+            '_Mtb_sp100','_Mtb_sp200','_Mtb_sp300','_Mtb_sp400','_Mtb_szfld','_Mwi_arran',
+            '_Mwi_clear','_Mwi_cmd','_Mwi_color','_Mwi_debug','_Mwi_hide','_Mwi_hidea',
+            '_Mwi_min','_Mwi_move','_Mwi_rotat','_Mwi_showa','_Mwi_size','_Mwi_sp100',
+            '_Mwi_sp200','_Mwi_toolb','_Mwi_trace','_Mwi_view','_Mwi_zoom','_Mwindow',
+            '_Mwizards','_Mwz_all','_Mwz_form','_Mwz_foxdoc','_Mwz_import','_Mwz_label',
+            '_Mwz_mail','_Mwz_pivot','_Mwz_query','_Mwz_reprt','_Mwz_setup','_Mwz_table',
+            '_Mwz_upsizing','_Netware','_Oracle','_Padvance','_Pageno','_Pbpage',
+            '_Pcolno','_Pcopies','_Pdparms','_Pdriver','_Pdsetup','_Pecode',
+            '_Peject','_Pepage','_Pform','_Plength','_Plineno','_Ploffset',
+            '_Ppitch','_Pquality','_Pretext','_Pscode','_Pspacing','_Pwait',
+            '_Rmargin','_Runactivedoc','_Samples','_Screen','_Shell','_Spellchk',
+            '_Sqlserver','_Startup','_Tabs','_Tally','_Text','_Throttle',
+            '_Transport','_Triggerlevel','_Unix','_WebDevOnly','_WebMenu','_WebMsftHomePage',
+            '_WebVFPHomePage','_WebVfpOnlineSupport','_Windows','_Wizard','_Wrap','_scctext',
+            '_vfp','Additive','After','Again','Aindent','Alignright',
+            'All','Alt','Alternate','And','Ansi','Any',
+            'Aplabout','App','Array','As','Asc','Ascending',
+            'Ascii','At','Attributes','Automatic','Autosave','Avg',
+            'Bar','Before','Bell','Between','Bitmap','Blank',
+            'Blink','Blocksize','Border','Bottom','Brstatus','Bucket',
+            'Buffers','By','Candidate','Carry','Cascade','Catalog',
+            'Cdx','Center','Century','Cga','Character','Check',
+            'Classlib','Clock','Cnt','Codepage','Collate','Color',
+            'Com1','Com2','Command','Compact','Compatible','Compress',
+            'Confirm','Connection','Connections','Connstring','Console','Copies',
+            'Cpcompile','Cpdialog','Csv','Currency','Cycle','Databases',
+            'Datasource','Date','Db4','Dbc','Dbf','Dbmemo3',
+            'Debug','Decimals','Defaultsource','Deletetables','Delimited','Delimiters',
+            'Descending','Design','Development','Device','Dif','Disabled',
+            'Distinct','Dlls','Dohistory','Dos','Dosmem','Double',
+            'Driver','Duplex','Echo','Editwork','Ega25','Ega43',
+            'Ems','Ems64','Encrypt','Encryption','Environment','Escape',
+            'Events','Exact','Except','Exe','Exists','Expression',
+            'Extended','F','Fdow','Fetch','Field','Fields',
+            'File','Files','Fill','Fixed','Float','Foldconst',
+            'Font','Footer','Force','Foreign','Fox2x','Foxplus',
+            'Free','Freeze','From','Fullpath','Fw2','Fweek',
+            'Get','Gets','Global','Group','Grow','Halfheight',
+            'Having','Heading','Headings','Helpfilter','History','Hmemory',
+            'Hours','Id','In','Indexes','Information','Instruct',
+            'Int','Integer','Intensity','Intersect','Into','Is',
+            'Isometric','Key','Keycolumns','Keycomp','Keyset','Last',
+            'Ledit','Level','Library','Like','Linked','Lock',
+            'Logerrors','Long','Lpartition','Mac','Macdesktop','Machelp',
+            'Mackey','Macros','Mark','Master','Max','Maxmem',
+            'Mdi','Memlimit','Memory','Memos','Memowidth','Memvar',
+            'Menus','Messages','Middle','Min','Minimize','Minus',
+            'Mod','Modal','Module','Mono43','Movers','Multilocks',
+            'Mvarsiz','Mvcount','N','Near','Negotiate','Noalias',
+            'Noappend','Noclear','Noclose','Noconsole','Nocptrans','Nodata',
+            'Nodebug','Nodelete','Nodup','Noedit','Noeject','Noenvironment',
+            'Nofloat','Nofollow','Nogrow','Noinit','Nolgrid','Nolink',
+            'Nolock','Nomargin','Nomdi','Nomenu','Nominimize','Nomodify'
+            ),
+        3 => array('Nomouse','None','Nooptimize','Nooverwrite','Noprojecthook','Noprompt',
+            'Noread','Norefresh','Norequery','Norgrid','Norm','Normal',
+            'Nosave','Noshadow','Noshow','Nospace','Not','Notab',
+            'Notify','Noupdate','Novalidate','Noverify','Nowait','Nowindow',
+            'Nowrap','Nozoom','Npv','Null','Number','Objects',
+            'Odometer','Of','Off','Oleobjects','Only','Optimize',
+            'Or','Orientation','Output','Outshow','Overlay','Overwrite',
+            'Pad','Palette','Paperlength','Papersize','Paperwidth','Password',
+            'Path','Pattern','Pause','Pdox','Pdsetup','Pen',
+            'Pfs','Pixels','Plain','Popups','Precision','Preference',
+            'Preview','Primary','Printer','Printquality','Procedures','Production',
+            'Program','Progwork','Project','Prompt','Query','Random',
+            'Range','Readborder','Readerror','Record','Recover','Redit',
+            'Reference','References','Relative','Remote','Reprocess','Resource',
+            'Rest','Restrict','Rgb','Right','Row','Rowset',
+            'Rpd','Runtime','Safety','Same','Sample','Say',
+            'Scale','Scheme','Scoreboard','Screen','Sdf','Seconds',
+            'Selection','Shadows','Shared','Sheet','Shell','Shift',
+            'Shutdown','Single','Some','Sortwork','Space','Sql',
+            'Standalone','Status','Std','Step','Sticky','String',
+            'Structure','Subclass','Summary','Sylk','Sysformats','Sysmenus',
+            'System','T','Tab','Tables','Talk','Tedit',
+            'Textmerge','Time','Timeout','Titles','Tmpfiles','To',
+            'Topic','Transaction','Trap','Trbetween','Trigger','Ttoption',
+            'Typeahead','Udfparms','Union','Unique','Userid','Users',
+            'Values','Var','Verb','Vga25','Vga50','Views',
+            'Volume','Where','Windows','Wk1','Wk3','Wks',
+            'Workarea','Wp','Wr1','Wrap','Wrk','Xcmdfile',
+            'Xl5','Xl8','Xls','Y','Yresolution','Zoom',
+            'Activate','ActivateCell','Add','AddColumn','AddItem','AddListItem',
+            'AddObject','AddProperty','AddToSCC','AfterBuild','AfterCloseTables','AfterDock',
+            'AfterRowColChange','BeforeBuild','BeforeDock','BeforeOpenTables','BeforeRowColChange','Box',
+            'Build','CheckIn','CheckOut','Circle','Clear','ClearData',
+            'Cleanup','Click','CloneObject','CloseEditor','CloseTables','Cls',
+            'CommandTargetExec','CommandTargetQueryStas','ContainerRelease','DataToClip','DblClick','Deactivate',
+            'Delete','DeleteColumn','Deleted','Destroy','DoCmd','Dock',
+            'DoScroll','DoVerb','DownClick','Drag','DragDrop','DragOver',
+            'DropDown','Draw','EnterFocus','Error','ErrorMessage','Eval',
+            'ExitFocus','FormatChange','GetData','GetFormat','GetLatestVersion','GoBack',
+            'GotFocus','GoForward','GridHitTest','Hide','HideDoc','IndexToItemId',
+            'Init','InteractiveChange','Item','ItemIdToIndex','KeyPress','Line',
+            'Load','LostFocus','Message','MiddleClick','MouseDown','MouseMove',
+            'MouseUp','MouseWheel','Move','Moved','NavigateTo','Newobject',
+            'OLECompleteDrag','OLEDrag','OLEDragDrop','OLEDragOver','OLEGiveFeedback','OLESetData',
+            'OLEStartDrag','OpenEditor','OpenTables','Paint','Point','Print',
+            'ProgrammaticChange','PSet','QueryAddFile','QueryModifyFile','QueryRemoveFile','QueryRunFile',
+            'QueryUnload','RangeHigh','RangeLow','ReadActivate','ReadExpression','ReadDeactivate',
+            'ReadMethod','ReadShow','ReadValid','ReadWhen','Refresh','Release',
+            'RemoveFromSCC','RemoveItem','RemoveListItem','RemoveObject','Requery','RequestData',
+            'Reset','ResetToDefault','Resize','RightClick','SaveAs','SaveAsClass',
+            'Scrolled','SetAll','SetData','SetFocus','SetFormat','SetMain',
+            'SetVar','SetViewPort','ShowDoc','ShowWhatsThis','TextHeight','TextWidth',
+            'Timer','UIEnable','UnDock','UndoCheckOut','Unload','UpClick',
+            'Valid','WhatsThisMode','When','WriteExpression','WriteMethod','ZOrder',
+            'ATGetColors','ATListColors','Accelerate','ActiveColumn','ActiveControl','ActiveForm',
+            'ActiveObjectId','ActivePage','ActiveProject','ActiveRow','AddLineFeeds','Alias',
+            'Alignment','AllowAddNew','AllowHeaderSizing','AllowResize','AllowRowSizing','AllowTabs',
+            'AlwaysOnTop','Application','AutoActivate','AutoCenter','AutoCloseTables','AutoIncrement',
+            'AutoOpenTables','AutoRelease','AutoSize','AutoVerbMenu','AutoYield','AvailNum',
+            'BackColor','BackStyle','BaseClass','BorderColor','BorderStyle','BorderWidth',
+            'Bound','BoundColumn','BoundTo','BrowseAlignment','BrowseCellMarg','BrowseDestWidth',
+            'BufferMode','BufferModeOverride','BuildDateTime','ButtonCount','ButtonIndex','Buttons',
+            'CLSID','CanAccelerate','CanGetFocus','CanLoseFocus','Cancel','Caption',
+            'ChildAlias','ChildOrder','Class','ClassLibrary','ClipControls','ClipRect',
+            'Closable','ColorScheme','ColorSource','ColumnCount','ColumnHeaders','ColumnLines',
+            'ColumnOrder','ColumnWidths','Columns','Comment','ContinuousScroll','ControlBox',
+            'ControlCount','ControlIndex','ControlSource','Controls','CurrentControl','CurrentX',
+            'CurrentY','CursorSource','Curvature','DataSession','DataSessionId','DataSourceObj',
+            'DataType','Database','DateFormat','DateMark','DefButton','DefButtonOrig',
+            'DefHeight','DefLeft','DefTop','DefWidth','Default','DefaultFilePath',
+            'DefineWindows','DeleteMark','Desktop','Dirty','DisabledBackColor','DisabledByEOF',
+            'DisabledForeColor','DisabledItemBackColor','DisabledItemForeColor','DisabledPicture','DispPageHeight','DispPageWidth',
+            'DisplayCount','DisplayValue','DoCreate','DockPosition','Docked','DocumentFile',
+            'DownPicture','DragIcon','DragMode','DragState','DrawMode','DrawStyle',
+            'DrawWidth','DynamicAlignment','DynamicBackColor','DynamicCurrentControl','DynamicFontBold','DynamicFontItalic',
+            'DynamicFontName','DynamicFontOutline','DynamicFontShadow','DynamicFontSize','DynamicFontStrikethru','DynamicFontUnderline',
+            'DynamicForeColor','EditFlags','Enabled','EnabledByReadLock','Encrypted','EnvLevel',
+            'ErasePage','FileClass','FileClassLibrary','FillColor','FillStyle','Filter',
+            'FirstElement','FontBold','FontItalic','FontName','FontOutline','FontShadow',
+            'FontSize','FontStrikethru','FontUnderline','ForceFocus','ForeColor','FormCount',
+            'FormIndex','FormPageCount','FormPageIndex','Format','Forms','FoxFont',
+            'FullName','GoFirst','GoLast','GridLineColor','GridLineWidth','GridLines'
+            ),
+        4 => array('HPROJ','HWnd','HalfHeightCaption','HasClip','HeaderGap','HeaderHeight',
+            'Height','HelpContextID','HideSelection','Highlight','HomeDir','HostName',
+            'HotKey','HscrollSmallChange','IMEMode','Icon','IgnoreInsert','InResize',
+            'Increment','IncrementalSearch','InitialSelectedAlias','InputMask','Instancing','IntegralHeight',
+            'Interval','ItemBackColor','ItemData','ItemForeColor','ItemIDData','ItemTips',
+            'JustReadLocked','KeyPreview','KeyboardHighValue','KeyboardLowValue','LastModified','Left',
+            'LeftColumn','LineSlant','LinkMaster','List','ListCount','ListIndex',
+            'ListItem','ListItemId','LockDataSource','LockScreen','MDIForm','MainClass',
+            'MainFile','Margin','MaxButton','MaxHeight','MaxLeft','MaxLength',
+            'MaxTop','MaxWidth','MemoWindow','MinButton','MinHeight','MinWidth',
+            'MouseIcon','MousePointer','Movable','MoverBars','MultiSelect','Name',
+            'NapTime','NewIndex','NewItemId','NoDataOnLoad','NoDefine','NotifyContainer',
+            'NullDisplay','NumberOfElements','OLEDragMode','OLEDragPicture','OLEDropEffects','OLEDropHasData',
+            'OLEDropMode','OLERequestPendingTimeOut','OLEServerBusyRaiseError','OLEServerBusyTimeOut','OLETypeAllowed','OleClass',
+            'OleClassId','OleControlContainer','OleIDispInValue','OleIDispOutValue','OleIDispatchIncoming','OleIDispatchOutgoing',
+            'OnResize','OneToMany','OpenViews','OpenWindow','PageCount','PageHeight',
+            'PageOrder','PageWidth','Pages','Panel','PanelLink','Parent',
+            'ParentAlias','ParentClass','Partition','PasswordChar','Picture','ProcessID',
+            'ProgID','ProjectHookClass','ProjectHookLibrary','Projects','ReadColors','ReadCycle',
+            'ReadFiller','ReadLock','ReadMouse','ReadOnly','ReadSave','ReadSize',
+            'ReadTimeout','RecordMark','RecordSource','RecordSourceType','Rect','RelationalExpr',
+            'RelativeColumn','RelativeRow','ReleaseErase','ReleaseType','ReleaseWindows','Resizable',
+            'RightToLeft','RowHeight','RowSource','RowSourceType','SCCProvider','SCCStatus',
+            'SDIForm','ScaleMode','ScrollBars','SelLength','SelStart','SelText',
+            'SelectOnEntry','Selected','SelectedBackColor','SelectedForeColor','SelectedID','SelectedItemBackColor',
+            'SelectedItemForeColor','SelfEdit','ServerClass','ServerClassLibrary','ServerHelpFile','ServerName',
+            'ServerProject','ShowTips','ShowWindow','Sizable','Size<height>','Size<maxlength>',
+            'Size<width>','Skip','SkipForm','Sorted','SourceType','Sparse',
+            'SpecialEffect','SpinnerHighValue','SpinnerLowValue','SplitBar','StartMode','StatusBarText',
+            'Stretch','StrictDateEntry','Style','SystemRefCount','TabIndex','TabStop',
+            'TabStretch','TabStyle','Tabhit','Tabs','Tag','TerminateRead',
+            'ThreadID','TitleBar','ToolTipText','Top','TopIndex','TopItemId',
+            'TypeLibCLSID','TypeLibDesc','TypeLibName','UnlockDataSource','Value','ValueDirty',
+            'VersionComments','VersionCompany','VersionCopyright','VersionDescription','VersionNumber','VersionProduct',
+            'VersionTrademarks','View','ViewPortHeight','ViewPortLeft','ViewPortTop','ViewPortWidth',
+            'Visible','VscrollSmallChange','WasActive','WasOpen','WhatsThisButton','WhatsThisHelp',
+            'WhatsThisHelpID','Width','WindowList','WindowNTIList','WindowState','WindowType',
+            'WordWrap','ZOrderSet','ActiveDoc','Checkbox','Column','ComboBox',
+            'CommandButton','CommandGroup','Container','Control','Cursor','Custom',
+            'DataEnvironment','EditBox','Empty','FontClass','Form','Formset',
+            'General','Grid','Header','HyperLink','Image','Label',
+            'ListBox','Memo','OleBaseControl','OleBoundControl','OleClassIDispOut','OleControl',
+            'OptionButton','OptionGroup','Page','PageFrame','ProjectHook','RectClass',
+            'Relation','Session','Shape','Spinner','TextBox' ,'Toolbar'
+            ),
+        ),
+    'SYMBOLS' => array(
+        "!", "@", "$", "%",
+        "(", ")", "{", "}", "[", "]",
+        "-", "+", "*", "/",
+        "=", "<", ">",
+        ":", ";", ",", ".", "&",
+        "?", "??", "???"
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: blue;',
+            2 => 'color: blue;',
+            3 => 'color: blue;',
+            4 => 'color: blue;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: green; font-style: italic;',
+            2 => 'color: green; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: blue;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #006600;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: blue;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/visualprolog.php b/examples/includes/geshi/geshi/visualprolog.php
new file mode 100644 (file)
index 0000000..2a5656b
--- /dev/null
@@ -0,0 +1,129 @@
+<?php
+/*************************************************************************************
+ * visualprolog.php
+ * ----------
+ * Author: Thomas Linder Puls (puls@pdc.dk)
+ * Copyright: (c) 2008 Thomas Linder Puls (puls@pdc.dk)
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/11/20
+ *
+ * Visual Prolog language file for GeSHi.
+ *
+ * CHANGES
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Visual Prolog',
+    'COMMENT_SINGLE' => array(1 => '%'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'HARDQUOTE' => array('@"', '"'),
+    'HARDESCAPE' => array('""'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array(
+            'clauses','constants','constructors','delegate','domains','facts',
+            'goal','guards','inherits','monitor','namespace','open',
+            'predicates','properties','resolve','supports'
+            ),
+        2 => array(
+            'align','and','anyflow','as','bitsize','catch','determ','digits',
+            'div','do','else','elseif','erroneous','externally','failure',
+            'finally','from','language','mod','multi','nondeterm','or',
+            'procedure','quot','rem','single','then','to'
+            ),
+        3 => array(
+            '#bininclude','#else','#elseif','#endif','#error','#export',
+            '#externally','#if','#import','#include','#message','#options',
+            '#orrequires','#requires','#then','#warning'
+            ),
+        ),
+    'SYMBOLS' => array(
+        '+', '-', '*', '?', '=', '/', '>', '<', '^', '!', ':', '(', ')', '{', '}', '[', ']'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => true,
+        1 => true,
+        2 => true,
+        3 => true
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #808000;',
+            2 => 'color: #333399;',
+            3 => 'color: #800080;',
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #AA77BD',
+            'MULTI' => 'color: #AA77BD'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #008080;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000000;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #00B7B7;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #0000FF;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #000000;'
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #008000;',
+            1 => 'color: #808000;',
+            2 => 'color: #333399;',
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => ':',
+        2 => '::'
+        ),
+    'REGEXPS' => array(
+        0 => "(?<![a-zA-Z0-9_])(?!(?:PIPE|SEMI)>)[A-Z_]\w*(?!\w)",
+        1 => "\\b(end\\s+)?(implement|class|interface)\\b",
+        2 => "\\b(end\\s+)?(foreach|if|try)\\b",
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/whitespace.php b/examples/includes/geshi/geshi/whitespace.php
new file mode 100644 (file)
index 0000000..dfada78
--- /dev/null
@@ -0,0 +1,121 @@
+<?php
+/*************************************************************************************
+ * whitespace.php
+ * ----------
+ * Author: Benny Baumann (BenBE@geshi.org)
+ * Copyright: (c) 2008 Benny Baumann (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2009/10/31
+ *
+ * Whitespace language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/10/31 (1.0.8.1)
+ *   -  First Release
+ *
+ * TODO
+ * ----
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+$language_data = array (
+    'LANG_NAME' => 'Whitespace',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array(),
+    'COMMENT_REGEXP' => array(
+        3 => "/[^\n\x20\x09]+/s"
+        ),
+    'CASE_KEYWORDS' => GESHI_CAPS_UPPER,
+    'QUOTEMARKS' => array(),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        ),
+    'SYMBOLS' => array(
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            ),
+        'COMMENTS' => array(
+            3 => 'color: #666666; font-style: italic;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            ),
+        'ESCAPE_CHAR' => array(
+            ),
+        'SCRIPT' => array(
+            ),
+        'REGEXPS' => array(
+            2 => 'background-color: #FF9999;',
+            3 => 'background-color: #9999FF;'
+            )
+        ),
+    'URLS' => array(
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        2 => array(
+            GESHI_SEARCH => "(?<!\\A)\x20",
+            GESHI_REPLACE => "&#32;",
+            GESHI_MODIFIERS => 's',
+            GESHI_BEFORE => "",
+            GESHI_AFTER => ""
+            ),
+        3 => array(
+            GESHI_SEARCH => "\x09",
+            GESHI_REPLACE => "&#9;",
+            GESHI_MODIFIERS => 's',
+            GESHI_BEFORE => "",
+            GESHI_AFTER => ""
+            ),
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4,
+    'PARSER_CONTROL' => array(
+        'ENABLE_FLAGS' => array(
+            'KEYWORDS' => GESHI_NEVER,
+            'SYMBOLS' => GESHI_NEVER,
+            'STRINGS' => GESHI_NEVER,
+//            'REGEXPS' => GESHI_NEVER,
+            'NUMBERS' => GESHI_NEVER
+            )
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/winbatch.php b/examples/includes/geshi/geshi/winbatch.php
new file mode 100644 (file)
index 0000000..caa94a4
--- /dev/null
@@ -0,0 +1,369 @@
+<?php
+/*************************************************************************************
+ * winbatch.php
+ * ------------
+ * Author: Craig Storey (storey.craig@gmail.com)
+ * Copyright: (c) 2004 Craig Storey (craig.xcottawa.ca)
+ * Release Version: 1.0.8.3
+ * Date Started: 2006/05/19
+ *
+ * WinBatch language file for GeSHi.
+ *
+ * WinBatch is a Windows scripting language - www.winbatch.com.
+ * The keywords were pulled from the winbatch/system/WIL.clr file for v2005G.
+ * Not all extender functions are added, but a very large set of the most common.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *   -  Added description of extra language features (SF#1970248)
+ * 2006/05/05 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2004/07/14)
+ * -------------------------
+ * - Right now any ':Subroutine' is treated as a comment. This highlights the
+ *   Subroutine's name, but it's not a perfect fix. I should use a RegEx in
+ *   GeSHI_Search&Replace features..
+ * - Update the list of extender functions.
+ * - Use a regular expression to comment UDFs that start with 'udf_'.
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Winbatch',
+    'COMMENT_SINGLE' => array(1 => ';', 2 => ':'),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"', '`'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        1 => array(
+            'While', 'To', 'Then', 'Switch', 'Select', 'Return', 'Next', 'IntControl', 'Include', 'In', 'If',
+            'Goto', 'GoSub', 'ForEach', 'For', 'Exit', 'Execute', 'ErrorMode', 'EndWhile', 'EndSwitch', '#EndSubRoutine',
+            'EndSelect', 'EndIf', '#EEndFunction', 'EndFor', 'End', 'Else', 'DropWild', 'Drop', '#DefineSubRoutine',
+            '#DefineFunction', 'Debug', 'Continue', 'Case', 'CallExt', 'Call', 'By', 'BreakPoint', 'Break'
+            ),
+        2 => array(
+            'ZOOMED', 'YES', 'WORD4', 'WORD2', 'WORD1', 'WHOLESECTION', 'WAIT', 'UNSORTED', 'UNCHECK', 'TRUE', 'TILE',
+            'TAB', 'STRING', 'STACK', 'SPC2NET', 'SORTED', 'SOK', 'SNET2PC', 'SINGLE', 'SHIFT', 'SERVER', 'SERRWINSOCK',
+            'SERRVOICE', 'SERRSOCKET', 'SERRSERVICE', 'SERRSELECT', 'SERRPARAM', 'SERROUTOFMEM', 'SERRNOTFOUND', 'SERRNOCONN',
+            'SERRNOANSWER', 'SERRMUSTWAIT', 'SERRIPADDR', 'SERRHOSTNAME', 'SERRFAILURE', 'SERRBUSY', 'SCROLLLOCK', 'SCANCEL',
+            'SAVE', 'SALREADY', 'ROWS', 'REGUSERS', 'REGROOT', 'REGMACHINE', 'REGCURRENT', 'REGCLASSES', 'RDBLCLICK', 'RCLICK',
+            'RBUTTON', 'RAD2DEG', 'QSUCCESSINFO', 'QSUCCESS', 'QSTILLEX', 'QROLLBACK', 'QNULL', 'QNODATA', 'QNEXT', 'QNEEDDATA',
+            'QFIRST', 'QCOMMIT', 'QBADHANDLE', 'PRINTER', 'PLANCKJOULES', 'PLANCKERGS', 'PI', 'PARSEONLY', 'PARSEC', 'P3ERRREPLY',
+            'OPEN', 'ON', 'OFF', 'NUMLOCK', 'NOWAIT', 'NOTIFY', 'NORMAL', 'NORESIZE', 'NONE', 'NO', 'NCSAFORMAT', 'MULTIPLE',
+            'MSFORMAT', 'MPLAYRDBLCK', 'MPLAYRCLK', 'MPLAYRBUTTON', 'MPLAYMDBLCK', 'MPLAYMCLK', 'MPLAYMBUTTON', 'MPLAYLDBLCK',
+            'MPLAYLCLK', 'MPLAYLBUTTON', 'MINOR', 'MDBLCLICK', 'MCLICK', 'MBYESNO', 'MBUTTON', 'MBOKCANCEL', 'MAJOR', 'MAGFIELD',
+            'LOCALGROUP', 'LIGHTMTPS', 'LIGHTMPS', 'LF', 'LDBLCLICK', 'LCLICK', 'LBUTTON', 'LAFFDBERROR', 'ICON', 'HTTPS', 'HTTP',
+            'HNOHEADER', 'HMETHODPOST', 'HMETHODGET', 'HIDDEN', 'HHEADERONLY', 'HHEADER', 'GRAVITATION', 'GOPHER', 'GOLDENRATIO',
+            'GMTSEC', 'GLOBALGROUP', 'GFTSEC', 'GETPROCID', 'GETEXITCODE', 'FWDSCAN', 'FTPPASSIVE', 'FTP', 'FLOAT8', 'FARADAY',
+            'FALSE', 'EXTENDED', 'EULERS', 'ENABLE', 'ELECTRIC', 'DRIVE', 'DISABLE', 'DESCENDING', 'DEG2RAD', 'DEFAULT', 'CTRL',
+            'CRLF', 'CR', 'COMMONFORMAT', 'COLUMNS', 'CHECK', 'CAPSLOCK', 'CANCEL', 'BOLTZMANN', 'BACKSCAN', 'AVOGADRO', 'ATTR_X',
+            'ATTR_T', 'ATTR_SY', 'ATTR_SH', 'ATTR_RO', 'ATTR_RI', 'ATTR_P', 'ATTR_IC', 'ATTR_H', 'ATTR_DM', 'ATTR_DI', 'ATTR_DC',
+            'ATTR_CI', 'ATTR_A', 'ASCENDING', 'ARRANGE', 'AMC', 'ACC_WRITE', 'ACC_READ_NT', 'ACC_READ_95', 'ACC_READ', 'ACC_PRINT_NT',
+            'ACC_PMANG_NT', 'ACC_PFULL_NT', 'ACC_LIST', 'ACC_FULL_NT', 'ACC_FULL_95', 'ACC_DELETE', 'ACC_CREATE', 'ACC_CONTROL',
+            'ACC_CHNG_NT', 'ACC_ATTRIB', 'ABOVEICONS'
+            ),
+        3 => array(
+            'Yields', 'Yield', 'WinZoom', 'WinWaitExist', 'WinWaitClose', 'WinWaitChild', 'WinVersion', 'WinTitle', 'WinSysInfo',
+            'WinState', 'WinShow', 'WinResources', 'WinPositionChild', 'WinPosition', 'WinPlaceSet', 'WinPlaceGet', 'WinPlaceChild',
+            'WinPlace', 'WinParmSet', 'WinParmGet', 'WinName', 'WinMetrics', 'WinItemProcId', 'WinItemNameId', 'WinItemizeEx',
+            'WinItemize', 'WinItemChild', 'WinIsDos', 'WinIdGet', 'WinIconize', 'WinHide', 'WinHelp', 'WinGetactive', 'WinExistchild',
+            'WinExist', 'WinExename', 'WinConfig', 'WinClosenot', 'WinClose', 'WinArrange', 'WinActivechild', 'WinActivchild',
+            'WinActivate', 'WebVerifyCard', 'WebSetTimeout', 'WebParamSize', 'WebParamNames', 'WebParamFile', 'WebParamData',
+            'WebParamBuf', 'WebOutFile', 'WebOutBinary', 'WebOut', 'WebDumpError', 'WebDatData', 'WebCounter', 'WebConSize', 'WebConData',
+            'WebConBuf', 'WebCmdData', 'WebBaseConv', 'Wallpaper', 'WaitForKeyEX', 'WaitForKey', 'VersionDLL', 'Version', 'VarType',
+            'TimeYmdHms', 'TimeWait', 'TimeSubtract', 'TimeJulToYmd', 'TimeJulianDay', 'TimeDiffSecs', 'TimeDiffDays', 'TimeDiff', 'TimeDelay',
+            'TimeDate', 'TimeAdd', 'TextSelect', 'TextBoxSort', 'TextBox', 'Terminate', 'Tanh', 'Tan', 'SysParamInfo', 'SvcWaitForCmd',
+            'SvcSetState', 'SvcSetAccept', 'StrUpper', 'StrTrim', 'StrSubWild', 'StrSub', 'StrScan', 'StrReplace', 'StrLower', 'StrLenWild',
+            'StrLen', 'StrIndexWild', 'StrIndexNC', 'StrIndex', 'StriCmp', 'StrFixLeft', 'StrFixCharsL', 'StrFixChars', 'StrFix', 'StrFill',
+            'StrCnt', 'StrCmp', 'StrClean', 'StrCharCount', 'StrCat', 'StrByteCount', 'Sqrt', 'SoundVolume', 'Sounds', 'Snapshot', 'Sinh', 'Sin',
+            'ShortCutMake', 'ShortCutInfo', 'ShortCutExtra', 'ShortCutEdit', 'ShortCutDir', 'ShellExecute', 'SendMenusToEx', 'SendMenusTo',
+            'SendKeysTo', 'SendKeysChild', 'SendKey', 'RunZoomWait', 'RunZoom', 'RunWithLogon', 'RunWait', 'RunShell', 'RunIconWait',
+            'RunIcon', 'RunHideWait', 'RunHide', 'RunExit', 'RunEnviron', 'Run', 'RtStatus', 'Reload', 'RegUnloadHive', 'RegSetValue',
+            'RegSetQword', 'RegSetMulSz', 'RegSetExpSz', 'RegSetEx', 'RegSetDword', 'RegSetBin', 'RegQueryValue', 'RegQueryStr',
+            'RegQueryQword', 'RegQueryMulSz', 'RegQueryKeys', 'RegQueryKeyLastWriteTime', 'RegQueryKey', 'RegQueryItem', 'RegQueryExpSz',
+            'RegQueryEx', 'RegQueryDword', 'RegQueryBin', 'RegOpenKeyEx', 'RegOpenKey', 'RegOpenFlags', 'RegLoadHive', 'RegExistValue',
+            'RegExistKey', 'RegEntryType', 'RegDelValue', 'RegDeleteKey', 'RegCreateKey', 'RegConnect', 'RegCloseKey', 'RegApp', 'Random',
+            'PtrPersistent', 'PtrGlobalDefine', 'PtrGlobal', 'Print', 'PlayWaveform', 'PlayMidi', 'PlayMedia', 'PipeServerWrite', 'PipeServerRead',
+            'PipeServerCreate', 'PipeServerClose', 'PipeInfo', 'PipeClientSendRecvData', 'PipeClientOpen', 'PipeClientClose', 'Pause',
+            'ParseData', 'ObjectTypeGet', 'ObjectType', 'ObjectOpen', 'ObjectGet', 'ObjectEventRemove', 'objecteventremove', 'ObjectEventAdd',
+            'objecteventadd', 'ObjectCreate', 'ObjectConstToArray', 'ObjectConstantsGet', 'ObjectCollectionOpen', 'ObjectCollectionNext',
+            'ObjectCollectionClose', 'ObjectClose', 'ObjectAccess', 'Num2Char', 'NetInfo', 'MsgTextGet', 'MousePlay', 'MouseMove', 'MouseInfo',
+            'MouseDrag', 'MouseCoords', 'MouseClickBtn', 'MouseClick', 'mod', 'Min', 'Message', 'Max', 'Loge', 'LogDisk', 'Log10', 'LastError',
+            'KeyToggleSet', 'KeyToggleGet', 'ItemSortNc', 'ItemSort', 'ItemSelect', 'ItemReplace', 'ItemRemove', 'ItemLocate', 'ItemInsert',
+            'ItemExtractCSV', 'ItemExtract', 'ItemCountCSV', 'ItemCount', 'IsNumber', 'IsLicensed', 'IsKeyDown', 'IsInt', 'IsFloat', 'IsDefined',
+            'Int', 'InstallFile', 'IniWritePvt', 'IniWrite', 'IniReadPvt', 'IniRead', 'IniItemizePvt', 'IniItemize', 'IniDeletePvt', 'IniDelete',
+            'IgnoreInput', 'IconReplace', 'IconInfo', 'IconExtract', 'IconArrange', 'GetTickCount', 'GetObject', 'GetExactTime', 'Floor',
+            'FindWindow', 'FileYmdHms', 'FileWrite', 'FileVerInfo', 'FileTimeTouch', 'FileTimeSetEx', 'FileTimeSet', 'FileTimeGetEx',
+            'FileTimeGet', 'FileTimeCode', 'FileSizeEx', 'FileSize', 'FileRoot', 'FileRename', 'FileRead', 'FilePutW', 'FilePut', 'FilePath',
+            'FileOpen', 'FileNameShort', 'FileNameLong', 'FileNameEval2', 'FileNameEval1', 'FileMoveAttr', 'FileMove', 'FileMapName',
+            'FileLocate', 'FileItemPath', 'FileItemize', 'FileInfoToArray', 'FileGetW', 'FileGet', 'FileFullname', 'FileExtension', 'FileExist',
+            'FileDelete', 'FileCreateTemp', 'FileCopyAttr', 'FileCopy', 'FileCompare', 'FileClose', 'FileBaseName', 'FileAttrSetEx',
+            'FileAttrSet', 'FileAttrGetEx', 'FileAttrGet', 'FileAppend', 'Fabs', 'ExtractAttachedFile', 'Exp', 'ExeTypeInfo', 'Exclusive',
+            'EnvItemize', 'EnvironSet', 'Environment', 'EndSession', 'DosVersion', 'DllLoad', 'DllLastError', 'DllHwnd', 'DllHinst',
+            'DllFree', 'DllCallCDecl', 'DllCall', 'Display', 'DiskVolinfo', 'DiskSize', 'DiskScan', 'DiskInfo', 'DiskFree', 'DiskExist',
+            'DirWindows', 'DirSize', 'DirScript', 'DirRename', 'DirRemove', 'DirMake', 'DirItemize', 'DirInfoToArray', 'DirHome', 'DirGet',
+            'DirExist', 'DirChange', 'DirAttrSetEx', 'DirAttrSet', 'DirAttrGetEx', 'DirAttrGet', 'DialogProcOptions', 'DialogObject',
+            'DialogControlState', 'DialogControlSet', 'DialogControlGet', 'DialogBox', 'Dialog', 'Delay', 'Decimals', 'DebugTrace',
+            'DebugData', 'DDETimeout', 'DDETerminate', 'DDERequest', 'DDEPoke', 'DDEInitiate', 'DDEExecute', 'DateTime', 'CurrFilepath',
+            'CurrentPath', 'CurrentFile', 'CreateObject', 'Cosh', 'Cos', 'ClipPut', 'ClipHasFormat', 'ClipGetEx', 'ClipGet', 'ClipAppend',
+            'ChrUnicodeToString', 'ChrUnicodeToHex', 'ChrStringToUnicode', 'ChrSetCodepage', 'ChrHexToUnicode', 'ChrGetCodepage',
+            'Char2Num', 'Ceiling', 'ButtonNames', 'BoxUpdates', 'BoxTitle', 'BoxTextFont', 'BoxTextColor', 'BoxText', 'BoxShut', 'BoxPen',
+            'BoxOpen', 'BoxNew', 'BoxMapmode', 'BoxesUp', 'BoxDrawText', 'BoxDrawRect', 'BoxDrawLine', 'BoxDrawCircle', 'BoxDestroy',
+            'BoxDataTag', 'BoxDataClear', 'BoxColor', 'BoxCaption', 'BoxButtonWait', 'BoxButtonStat', 'BoxButtonKill', 'BoxButtonDraw',
+            'BoxBitMap', 'BinaryXor', 'BinaryXlate', 'BinaryWriteEx', 'BinaryWrite', 'BinaryTagRepl', 'BinaryTagLen', 'BinaryTagInit',
+            'BinaryTagIndex', 'BinaryTagFind', 'BinaryTagExtr', 'BinaryStrCnt', 'BinarySort', 'BinaryReplace', 'BinaryReadEx',
+            'BinaryRead', 'BinaryPokeStrW', 'BinaryPokeStr', 'BinaryPokeHex', 'BinaryPokeFlt', 'BinaryPoke4', 'BinaryPoke2', 'BinaryPoke',
+            'BinaryPeekStrW', 'BinaryPeekStr', 'BinaryPeekHex', 'BinaryPeekFlt', 'BinaryPeek4', 'BinaryPeek2', 'BinaryPeek', 'BinaryOr',
+            'BinaryOleType', 'BinaryIndexNc', 'BinaryIndexEx', 'BinaryIndexBin', 'BinaryIndex', 'BinaryIncrFlt', 'BinaryIncr4',
+            'BinaryIncr2', 'BinaryIncr', 'BinaryHashRec', 'BinaryFree', 'BinaryEodSet', 'BinaryEodGet', 'BinaryCopy', 'BinaryConvert',
+            'BinaryCompare', 'BinaryClipPut', 'BinaryClipGet', 'BinaryChecksum', 'BinaryBufInfo', 'BinaryAnd', 'BinaryAllocArray',
+            'BinaryAlloc', 'Beep', 'Average', 'Atan', 'AskYesNo', 'AskTextbox', 'AskPassword', 'AskLine', 'AskItemlist', 'AskFont',
+            'AskFiletext', 'AskFilename', 'AskDirectory', 'AskColor', 'Asin', 'ArrInitialize', 'ArrInfo', 'ArrDimension',
+            'Arrayize', 'ArrayFilePutCSV', 'ArrayFilePut', 'ArrayFileGetCSV', 'ArrayFileGet', 'AppWaitClose', 'AppExist', 'AddExtender',
+            'Acos', 'Abs', 'About'
+            ),
+        4 => array(
+            'zZipFiles', 'zVersionInfo', 'zVersion', 'zUnZipFiles', 'zSetPortBit', 'zRPortShift', 'zPortOut', 'zPortIn', 'zNotPortBit',
+            'zLPortShift', 'zGetPortBit', 'zClrPortBit', 'xVerifyCCard', 'xSendMessage', 'xMessageBox', 'xMemCompact', 'xHex', 'xGetElapsed',
+            'xGetChildHwnd', 'xExtenderInfo', 'xEnumStreams', 'xEjectMedia', 'xDriveReady', 'xDiskLabelGet', 'xCursorSet', 'xBaseConvert',
+            'wxPing', 'wxParmSet', 'wxParmGet', 'wxMsgSetHdr', 'wxMsgGetHdr', 'wxMsgGetBody', 'wxHost2Addr', 'wxGetLastErr', 'wxGetInfo',
+            'wxGetErrDesc', 'wxAddr2Host', 'wtsWaitSystemEvent', 'wtsVersion', 'wtsTerminateProcess', 'wtsShutdownSystem', 'wtsSendMessage',
+            'wtsQuerySessionInfo', 'wtsProcIdToSessId', 'wtsLogoffSession', 'wtsLastErrMsg', 'wtsIsTSEnabled', 'wtsIsCitrixEnabled',
+            'wtsGetActiveConsoleSessId', 'wtsEnumSessions', 'wtsEnumProcesses', 'wtsDisconnectSession', 'wnWrkGroups', 'wnVersion', 'wntWtsUserSet',
+            'wntWtsUserGet', 'wntVersion', 'wntUserSidChk', 'wntUserSetDat', 'wntUserRename', 'wntUserProps', 'wntUserList', 'wntUserInfo',
+            'wntUserGetDat', 'wntUserFiles', 'wntUserExist', 'wntUserDel', 'wntUserAddDat', 'wntUserAdd', 'wntSvcStatus', 'wntSvcStart',
+            'wntSvcList', 'wntSvcDelete', 'wntSvcCreate', 'wntSvcControl', 'wntSvcCfgSet', 'wntSvcCfgGet', 'wntShutdown', 'wntShareUsers',
+            'wntShareSet', 'wntShareList', 'wntShareInfo', 'wntShareDel', 'wntShareAdd', 'wntServiceInf', 'wntServiceAt', 'wntServerType',
+            'wntServerList', 'wntServerInfo', 'wntSecurityGet', 'wntRunAsUser', 'wntResources2', 'wntResources', 'wntRemoteTime', 'wntRasUserSet',
+            'wntRasUserGet', 'wntProfileInfo', 'wntProfileDel', 'wntPrivUsers', 'wntPrivList', 'wntPrivGet', 'wntPrivDel', 'wntPrivAdd',
+            'wntOwnerSet', 'wntOwnerGet', 'wntMemberSet', 'wntMemberLst2', 'wntMemberList', 'wntMemberGrps', 'wntMemberGet', 'wntMemberDel',
+            'wntLsaPolSet', 'wntLsaPolGet', 'wntListGroups', 'wntLastErrMsg', 'wntGroupRen', 'wntGroupInfo', 'wntGroupEdit', 'wntGroupDel',
+            'wntGroupAdd', 'wntGetUser', 'wntGetDrive', 'wntGetDc', 'wntGetCon', 'wntFileUsers', 'wntFilesOpen', 'wntFileClose', 'wntEventWrite',
+            'wntEventLog', 'wntDomainSync', 'wntDirDialog', 'wntDfsList', 'wntDfsGetInfo', 'wntCurrUsers', 'wntChgPswd', 'wntCancelCon',
+            'wntAuditMod', 'wntAuditList', 'wntAuditGet', 'wntAuditDel', 'wntAuditAdd2', 'wntAuditAdd', 'wntAddPrinter', 'wntAddDrive',
+            'wntAcctPolSet', 'wntAcctPolGet', 'wntAcctList', 'wntAcctInfo', 'wntAccessMod', 'wntAccessList', 'wntAccessGet', 'wntAccessDel',
+            'wntaccessadd2', 'wntAccessAdd', 'wnShares', 'wnSharePath', 'wnShareName', 'wnShareCnt', 'wnServers', 'wnRestore', 'wnNetNames',
+            'wnGetUser', 'wnGetCon', 'wnGetCaps', 'wnDlgShare', 'wnDlgNoShare', 'wnDlgDiscon', 'wnDlgCon4', 'wnDlgCon3', 'wnDlgCon2', 'wnDlgCon',
+            'wnDlgBrowse', 'wnDialog', 'wnCmptrInfo', 'wnCancelCon', 'wnAddCon', 'WaitSRQ', 'w9xVersion', 'w9xUserSetDat', 'w9xUserRename',
+            'w9xUserprops', 'w9xUserList', 'w9xUserinfo', 'w9xUserGetDat', 'w9xUserExist', 'w9xUserDel', 'w9xUserAddDat', 'w9xUserAdd', 'w9xShareSet',
+            'w9xShareInfo', 'w9xShareDel', 'w9xShareAdd', 'w9xServiceAt', 'w9xServerList', 'w9xRemoteTime', 'w9xOwnerGet', 'w9xMemberSet',
+            'w9xMemberList', 'w9xMemberGrps', 'w9xMemberGet', 'w9xMemberDel', 'w9xListGroups', 'w9xGroupInfo', 'w9xGroupDel', 'w9xGroupAdd',
+            'w9xGetDC', 'w9xFileUsers', 'w9xAccessList', 'w9xAccessGet', 'w9xAccessDel', 'w9xAccessAdd', 'w95Version', 'w95ShareUsers',
+            'w95ShareSet', 'w95ShareList', 'w95ShareInfo', 'w95ShareDel', 'w95ShareAdd', 'w95ServiceInf', 'w95ServiceAt', 'w95ServerType',
+            'w95ServerInfo', 'w95Resources', 'w95GetUser', 'w95GetDrive', 'w95GetCon', 'w95FileUsers', 'w95FileClose', 'w95DirDialog',
+            'w95CancelCon', 'w95AddPrinter', 'w95AddDrive', 'w95AccessDel', 'w95AccessAdd', 'w3Version', 'w3PrtBrowse', 'w3NetGetUser',
+            'w3NetDialog', 'w3GetCon', 'w3GetCaps', 'w3DirBrowse', 'w3CancelCon', 'w3AddCon', 'urlGetScheme', 'urlEncode', 'urlDecode',
+            'tVersion', 'tSetPriority', 'TriggerList', 'Trigger', 'tRemoteConn', 'tOpenProc', 'tListProc', 'tListMod', 'tKillProc', 'tGetProcInfo',
+            'tGetPriority', 'tGetModInfo', 'tGetLastError', 'tGetData', 'TestSys', 'TestSRQ', 'tCountProc', 'tCompatible', 'tCloseProc',
+            'tBrowseCntrs', 'sSendString', 'sSendNum', 'sSendLine', 'sSendBinary', 'sRecvNum', 'sRecvLine', 'sRecvBinary', 'SrchVersion',
+            'SrchNext', 'SrchInit', 'SrchFree', 'sOpen', 'sOK2Send', 'sOK2Recv', 'smtpSendText', 'smtpSendFile', 'sListen', 'SetRWLS',
+            'SendSetup', 'SendLLO', 'SendList', 'SendIFC', 'SendDataBytes', 'SendCmds', 'Send', 'sConnect', 'sClose', 'SByteOrder32',
+            'sByteOrder16', 'sAccept', 'rRegVersion', 'rRegSearch', 'ResetSys', 'ReceiveSetup', 'Receive', 'ReadStsByte', 'RcvRespMsg',
+            'RasVersion', 'RasTypeSize', 'RasRename', 'RasNumCons', 'RasNameValid', 'RasListActCon', 'RasItemize', 'RasHangUp', 'RasGetLastErr',
+            'RasGetConStat', 'RasEntrySet', 'RasEntryInfo', 'RasEntryExist', 'RasEntryDel', 'RasEntryAdd', 'RasDialInfo', 'RasDial',
+            'RasCopy', 'RasConStatus', 'qVersionInfo', 'qTransact', 'qTables', 'qSpecial', 'qSetConnOpt', 'qNumRsltCol', 'qNativeSql', 'qLastCode',
+            'qGetData', 'qFreeStmt', 'qFreeEnv', 'qFreeConnect', 'qFetch', 'qExecDirect', 'qError', 'qDriverList', 'qDriverCon', 'qDisconnect',
+            'qDataSources', 'qConnect', 'qConfigError', 'qConfigData', 'qColumns', 'qBindCol', 'qAllocStmt', 'qAllocEnv', 'qAllocConnect',
+            'pWaitFor', 'pVersionInfo', 'pTimeout', 'pSetPublish', 'pSetPrtInfo', 'pSetPrtAttrib', 'pSetDefPrtEx', 'pSetDefPrt', 'pSendFile',
+            'pRecvFile', 'pPutString', 'pPutLine', 'pPutChar', 'pPutByte', 'pPutBinary', 'PPollUnconfig', 'PPollConfig', 'PPoll', 'pPeekChar',
+            'pPeekByte', 'pPaperSizes', 'pPaperBins', 'pModemSReg', 'pModemParams', 'pModemInit', 'pModemHangUp', 'pModemDial', 'pModemControl',
+            'pModemConnect', 'pModemCommand', 'pModemAnsRing', 'pModemAnsCall', 'pMediaTypes', 'pGetString', 'pGetPublish', 'pGetPrtList',
+            'pGetPrtInfo', 'pGetPrtAttrib', 'pGetLine', 'pGetLastError', 'pGetErrorMsg', 'pGetErrorCode', 'pGetDefPrtInf', 'pGetChar',
+            'pGetByte', 'pGetBinary', 'pDelPrtConn', 'pDelPrinter', 'pComOpen', 'pComModify', 'pComInfo', 'pComControl', 'pComClose',
+            'pCheckSum', 'pCheckBinary', 'pCaptureOn', 'pCaptureOff', 'pCaptureLog', 'PassControl', 'pAddPrtConn', 'pAddPrinter', 'p3RecvText',
+            'p3RecvFile', 'p3Peek', 'p3Open', 'p3GetReply', 'p3Delete', 'p3Count', 'p3Close', 'nwWhoAmI', 'nwVfyPassword', 'nwVersion',
+            'nwSrvShutdown', 'nwSrvNLMMgr', 'nwSrvGenGUID', 'nwSrvExecNCF', 'nwSetVolLimit', 'nwSetSrvParam', 'nwSetSrvInfo', 'nwSetPrimServ',
+            'nwSetPassword', 'nwSetOptions', 'nwSetFileInfo', 'nwSetDirLimit', 'nwSetDirInfo', 'nwSetContext', 'nwSetBcastMode', 'nwServerList',
+            'nwSendBcastMsg', 'nwSearchObjects', 'nwSearchFilter', 'nwRenameObject', 'nwRemoveObject', 'nwReceiveBcastMsg', 'nwNameConvert',
+            'nwMutateObject', 'nwMoveObject', 'nwModifyObject', 'nwMapDelete', 'nwMap', 'nwLogout', 'nwLogin', 'nwListUserGroups',
+            'nwListObjects', 'nwListGroupMembers', 'nwLastErrMsg', 'nwIsUserInGroup', 'nwGetVolLimit', 'nwGetSrvStats', 'nwGetSrvParam',
+            'nwGetSrvInfo', 'nwGetSrvCfg', 'nwGetOptions', 'nwGetObjValue', 'nwGetObjInfo', 'nwGetNLMInfo', 'nwGetMapped', 'nwGetFileInfo',
+            'nwGetDirLimit', 'nwGetDirInfo', 'nwGetContext', 'nwGetConnInfo', 'nwGetCapture', 'nwGetBcastMode', 'nwGetAttrInfo',
+            'nwDriveStatus', 'nwDrivePath', 'nwDetachFromServer', 'nwDelUserFromGroup', 'nwDelConnNum', 'nwCompareObject', 'nwClientInfo',
+            'nwChgPassword', 'nwAttachToServer', 'nwAddUserToGroup', 'nwAddObject', 'netVersion', 'netResources', 'netGetUser', 'netGetCon',
+            'netDirDialog', 'netCancelCon', 'netAddPrinter', 'netAddDrive', 'n4Version', 'n4UserGroups', 'n4UserGroupEx', 'n4SetPrimServ',
+            'n4SetOptions', 'n4SetContextG', 'n4SetContext', 'n4ServerList', 'n4ServerInfo', 'n4ObjSearch', 'n4ObjRename', 'n4ObjOptions',
+            'n4ObjMove', 'n4ObjGetVal', 'n4ObjectProps', 'n4ObjectList', 'n4ObjectInfo', 'n4ObjDelete', 'n4NameConvert', 'n4MsgsEndAll',
+            'n4MsgsEnd', 'n4MemberSet', 'n4MemberGet', 'n4MemberDel', 'n4MapRoot', 'n4MapDir', 'n4MapDelete', 'n4Map', 'n4LogoutTree',
+            'n4Logout', 'n4Login', 'n4GetUserName', 'n4GetUserId', 'n4GetUser', 'n4GetNetAddr', 'n4GetMapped', 'n4GetContext',
+            'n4GetConnNum', 'n4FileUsers', 'n4FileTimeGet', 'n4FileAttrSet', 'n4FileAttrGet', 'n4DriveStatus', 'n4DrivePath', 'n4DirTimeGet',
+            'n4DirAttrSet', 'n4DirAttrGet', 'n4Detach', 'n4ChgPassword', 'n4CapturePrt', 'n4CaptureGet', 'n4CaptureEnd', 'n4Attach',
+            'n3Version', 'n3UserGroups', 'n3ServerList', 'n3ServerInfo', 'n3MsgsEndAll', 'n3MsgsEnd', 'n3MemberSet', 'n3MemberGet',
+            'n3MemberDel', 'n3Maproot', 'n3Mapdir', 'n3Mapdelete', 'n3Map', 'n3Logout', 'n3GetUserId', 'n3GetUser', 'n3GetNetAddr',
+            'n3GetMapped', 'n3GetConnNum', 'n3FileTimeGet', 'n3FileAttrSet', 'n3FileAttrGet', 'n3DriveStatus', 'n3DrivePath',
+            'n3DirTimeGet', 'n3DirAttrSet', 'n3DirAttrGet', 'n3Detach', 'n3ChgPassword', 'n3CapturePrt', 'n3CaptureGet',
+            'n3CaptureEnd', 'n3Attach', 'mVersion', 'mSyncMail', 'mSendMailEx', 'mSendMail', 'mrecvmail', 'mReadNextMsg', 'mLogOn',
+            'mLogOff', 'mFindNext', 'mError', 'mCompatible', 'kVerInfo', 'kStatusInfo', 'kSendText', 'kSendFile', 'kManageImap4',
+            'kInit', 'kGetMail', 'kExtra', 'kDest', 'kDeletePop3', 'iWriteDataBuf', 'iWriteData', 'iVersion', 'IUrlOpen', 'iUrlEncode',
+            'iUrlDecode', 'iReadDataBuf', 'iReadData', 'ipVersion', 'ipPing', 'iPing', 'ipHost2Addr', 'ipGetLastErr', 'ipGetAddress',
+            'iParseURL', 'ipAddr2Host', 'iOptionSet', 'iOptionGet', 'ImgWave', 'ImgVersion', 'ImgUnsharpMask', 'ImgThreshold', 'ImgSwirl',
+            'ImgSpread', 'ImgSolarize', 'ImgShear', 'ImgSharpen', 'ImgShade', 'ImgScale', 'ImgSample', 'ImgRotate', 'ImgResize',
+            'ImgReduceNoise', 'ImgRaise', 'ImgOilPaint', 'ImgNormalize', 'ImgNegate', 'ImgMotionBlur', 'ImgModulate', 'ImgMinify',
+            'ImgMedianFilter', 'ImgMagnify', 'ImgLevel', 'ImgIsValid', 'ImgIsPalette', 'ImgIsMono', 'ImgIsGray', 'ImgInfo', 'ImgImplode',
+            'ImgGetImageType', 'ImgGetColorCount', 'ImgGaussianBlur', 'ImgGamma', 'ImgFrame', 'ImgFlop', 'ImgFlip', 'ImgEqualize',
+            'ImgEnhance', 'ImgEmboss', 'ImgCrop', 'ImgConvert', 'ImgContrast', 'ImgCompare', 'ImgColorize', 'ImgChop', 'ImgCharcoal',
+            'ImgBorder', 'ImgBlur', 'ImgAddNoise', 'iLocFindNext', 'iLocFindInit', 'iHttpOpen', 'iHttpInit', 'iHttpHeaders', 'iHttpAccept',
+            'iHostConnect', 'iHost2Addr', 'iGetResponse', 'iGetLastError', 'iGetIEVer', 'iGetConStatEx', 'iGetConState', 'iFtpRename',
+            'iFtpPut', 'iFtpOpen', 'iFtpGet', 'iFtpFindNext', 'iFtpFindInit', 'iFtpDirRemove', 'iFtpDirMake', 'iFtpDirGet', 'iFtpDirChange',
+            'iFtpDialog', 'iFtpDelete', 'iFtpCmd', 'iErrorDialog', 'iDialItemize', 'iDialHangUp', 'iDial', 'iCookieSet', 'iCookieGet',
+            'iContentURL', 'iContentFile', 'iContentData', 'iClose', 'ibWrtf', 'ibWrt', 'ibWait', 'ibVersion', 'ibUnlock', 'ibTrg',
+            'ibTmo', 'ibStop', 'ibStatus', 'ibSta', 'ibSre', 'ibSic', 'ibSad', 'ibRsv', 'ibRsp', 'ibRsc', 'ibRpp', 'ibRdf', 'ibRd',
+            'ibPpc', 'ibPoke', 'ibPct', 'ibPad', 'ibOnl', 'ibMakeAddr', 'ibLock', 'ibLoc', 'ibLn', 'ibLines', 'ibIst', 'ibInit',
+            'ibGts', 'ibGetSad', 'ibGetPad', 'ibFind', 'ibEvent', 'ibErr', 'ibEot', 'ibEos', 'iBegin', 'ibDma', 'ibDev', 'ibConfig',
+            'ibCntl', 'ibCnt', 'ibCmda', 'ibCmd', 'ibClr', 'ibCac', 'ibBna', 'ibAsk', 'iAddr2Host', 'huge_Thousands', 'huge_Subtract',
+            'huge_SetOptions', 'huge_Multiply', 'huge_GetLastError', 'huge_ExtenderInfo', 'huge_Divide', 'huge_Decimal', 'huge_Add',
+            'httpStripHTML', 'httpRecvTextF', 'httpRecvText', 'httpRecvQuery', 'httpRecvQryF', 'httpRecvFile', 'httpGetServer',
+            'httpGetQuery', 'httpGetPath', 'httpGetFile', 'httpGetDir', 'httpGetAnchor', 'httpFullPath', 'httpFirewall', 'httpAuth',
+            'ftpRename', 'ftpQuote', 'ftpPut', 'ftpOpen', 'ftpList', 'ftpGet', 'ftpFirewall', 'ftpDelete', 'ftpClose', 'ftpChDir',
+            'FindRQS', 'FindLstn', 'EnvSetVar', 'EnvPathDel', 'EnvPathChk', 'EnvPathAdd', 'EnvListVars', 'EnvGetVar', 'EnvGetInfo',
+            'EnableRemote', 'EnableLocal', 'ehllapiWait', 'ehllapiVersion', 'ehllapiUninit', 'ehllapiStopKeyIntercept', 'ehllapiStopHostNotify',
+            'ehllapiStopCloseIntercept', 'ehllapiStartKeyIntercept', 'ehllapiStartHostNotify', 'ehllapiStartCloseIntercept',
+            'ehllapiSetWindowStatus', 'ehllapiSetSessionParams', 'ehllapiSetPSWindowName', 'ehllapiSetCursorLoc', 'ehllapiSendKey',
+            'ehllapiSendFile', 'ehllapiSearchPS', 'ehllapiSearchField', 'ehllapiRunProfile', 'ehllapiResetSystem', 'ehllapiReserve',
+            'ehllapiRelease', 'ehllapiReceiveFile', 'ehllapiQuerySystem', 'ehllapiQueryPSStatus', 'ehllapiQueryHostNotify',
+            'ehllapiQueryFieldAttr', 'ehllapiQueryCursorLoc', 'ehllapiQueryCloseIntercept', 'ehllapiPostInterceptStatus',
+            'ehllapiPause', 'ehllapiLastErrMsg', 'ehllapiInit', 'ehllapiGetWindowStatus', 'ehllapiGetPSHWND', 'ehllapiGetKey',
+            'ehllapiFindFieldPos', 'ehllapiFindFieldLen', 'ehllapiDisconnectPS', 'ehllapiCvtRCToPos', 'ehllapiCvtPosToRC',
+            'ehllapiCopyTextToPS', 'ehllapiCopyTextToField', 'ehllapiCopyTextFromPS', 'ehllapiCopyTextFromField', 'ehllapiCopyOIA',
+            'ehllapiConnectPS', 'dunItemize', 'dunDisconnect', 'dunConnectEx', 'dunConnect', 'dsTestParam', 'dsSIDtoHexStr', 'dsSetSecProp',
+            'dsSetProperty', 'dsSetPassword', 'dsSetObj', 'dsSetCredentX', 'dsSetCredent', 'dsRemFromGrp', 'dsRelSecObj', 'dsMoveObj',
+            'dsIsObject', 'dsIsMemberGrp', 'dsIsContainer', 'dsGetUsersGrps', 'dsGetSecProp', 'dsGetPropName', 'dsGetProperty',
+            'dsGetPrntPath', 'dsGetPrimGrp', 'dsGetMemGrp', 'dsGetInfo', 'dsGetClass', 'dsGetChldPath', 'dsFindPath', 'dsDeleteObj',
+            'dsCreatSecObj', 'dsCreateObj', 'dsCopySecObj', 'dsAddToGrp', 'dsAclRemAce', 'dsAclOrderAce', 'dsAclGetAces', 'dsAclAddAce',
+            'DevClearList', 'DevClear', 'dbTest', 'dbSwapColumns', 'dbSort', 'dbSetRecordField', 'dbSetOptions', 'dbSetErrorReporting',
+            'dbSetEntireRecord', 'dbSetDelimiter', 'dbSave', 'dbOpen', 'dbNameColumn', 'dbMakeNewItem', 'dbInsertColumn', 'dbGetVersion',
+            'dbGetSaveStatus', 'dbGetRecordField', 'dbGetRecordCount', 'dbGetNextItem', 'dbGetLastError', 'dbGetEntireRecord',
+            'dbGetColumnType', 'dbGetColumnNumber', 'dbGetColumnName', 'dbGetColumnCount', 'dbFindRecord', 'dbExist', 'dbEasterEgg',
+            'dbDeleteRecord', 'dbDeleteColumn', 'dbDebug', 'dbCookDatabases', 'dbClose', 'dbCloneRecord', 'dbBindCol', 'cWndState',
+            'cWndinfo', 'cWndGetWndSpecName', 'cWndGetWndSpec', 'cWndexist', 'cWndByWndSpecName', 'cWndByWndSpec', 'cWndbyseq',
+            'cWndbyname', 'cWndbyid', 'cWndbyclass', 'cWinIDConvert', 'cVersionInfo', 'cVendorId', 'cSetWndText', 'cSetUpDownPos',
+            'cSetTvItem', 'cSetTrackPos', 'cSetTabItem', 'cSetLvItem', 'cSetLbItemEx', 'cSetLbItem', 'cSetIpAddr', 'cSetFocus',
+            'cSetEditText', 'cSetDtpDate', 'cSetCbItem', 'cSetCalDate', 'cSendMessage', 'cRadioButton', 'cPostMessage', 'cPostButton',
+            'cMemStat', 'cGetWndCursor', 'cGetUpDownPos', 'cGetUpDownMin', 'cGetUpDownMax', 'cGetTVItem', 'cGetTrackPos', 'cGetTrackMin',
+            'cGetTrackMax', 'cGetTbText', 'cGetSbText', 'cGetLvText', 'cGetLvSelText', 'cGetLvFocText', 'cGetLvDdtText', 'cGetLvColText',
+            'cGetLbText', 'cGetLbSelText', 'cGetLbCount', 'cGetIpAddr', 'cGetInfo', 'cGetHrText', 'cGetFocus', 'cGetEditText', 'cGetDtpDate',
+            'cGetControlImageCRC', 'cGetCBText', 'cGetCbCount', 'cGetCalDate', 'cFindByName', 'cFindByClass', 'cEnablestate', 'cDblClickItem',
+            'cCpuSupt', 'cCpuSpeed', 'cCpuIdExt', 'cCpuId', 'cCpuFeat', 'cCpuBenchmark', 'cCloneCheck', 'cClickToolbar', 'cClickButton',
+            'cClearTvItem', 'cClearLvItem', 'cClearLbAll', 'cCheckbox', 'aVersion', 'aStatusbar', 'aShellFolder', 'aMsgTimeout', 'AllSPoll',
+            'aGetLastError', 'aFileRename', 'aFileMove', 'aFileDelete', 'aFileCopy'
+            ),
+        5 => array(
+            'wWordRight', 'wWordLeft', 'wWinTile', 'wWinRestore', 'wWinNext', 'wWinMinimize', 'wWinMaximize', 'wWinCloseAll', 'wWinClose',
+            'wWinCascade', 'wWinArricons', 'wViewOutput', 'wViewOptions', 'wViewHtml', 'wUpperCase', 'wUpline', 'wUndo', 'wTopOfFile', 'wToggleIns',
+            'wTab', 'wStatusMsg', 'wStartSel', 'wSpellcheck', 'wSetProject', 'wSetPrefs', 'wSetColblk', 'wSetBookmark', 'wSelWordRight',
+            'wSelWordLeft', 'wSelUp', 'wSelTop', 'wSelRight', 'wSelPgUp', 'wSelPgDn', 'wSelLeft', 'wSelInfo', 'wSelHome', 'wSelEnd', 'wSelectAll',
+            'wSelDown', 'wSelBottom', 'wRunRebuild', 'wRunMake', 'wRunExecute', 'wRunDebug', 'wRunConfig', 'wRunCompile', 'wRunCommand', 'wRight',
+            'wRepeat', 'wRedo', 'wRecord', 'wProperties', 'wPrintDirect', 'wPrinSetup', 'wPrevError', 'wPaste', 'wPageUp', 'wPageDown', 'wNextError',
+            'wNewLine', 'wLowerCase', 'wLineCount', 'wLeft', 'wInvertCase', 'wInsString', 'wInsLine', 'wHome', 'wHelpKeyword', 'wHelpKeybrd',
+            'wHelpIndex', 'wHelpHelp', 'wHelpCmds', 'wHelpAbout', 'wGotoLine', 'wGotoCol', 'wGetWrap', 'wGetWord', 'wGetUndo', 'wGetSelstate',
+            'wGetRedo', 'wGetOutput', 'wGetModified', 'wGetLineNo', 'wGetIns', 'wGetFilename', 'wGetColNo', 'wGetChar', 'wFtpOpen', 'wFindNext',
+            'wFindInFiles', 'wFind', 'wFileSaveAs', 'wFileSave', 'wFileRevert', 'wFilePrint', 'wFilePgSetup', 'wFileOpen', 'wFileNew', 'wFileMerge',
+            'wFileList', 'wFileExit', 'wEndSel', 'wEndOfFile', 'wEnd', 'wEdWrap', 'wEdWordRight', 'wEdWordLeft', 'wEdUpLine', 'wEdUndo', 'wEdTopOfFile',
+            'wEdToggleIns', 'wEdTab', 'wEdStartSel', 'wEdSetColBlk', 'wEdSelectAll', 'wEdRight', 'wEdRedo', 'wEdPaste', 'wEdPageUp', 'wEdPageDown',
+            'wEdNewLine', 'wEdLeft', 'wEdInsString', 'wEdHome', 'wEdGoToLine', 'wEdGoToCol', 'wEdGetWord', 'wEdEndSel', 'wEdEndOfFile', 'wEdEnd',
+            'wEdDownLine', 'wEdDelete', 'wEdCutLine', 'wEdCut', 'wEdCopyLine', 'wEdCopy', 'wEdClearSel', 'wEdBackTab', 'wEdBackspace', 'wDownLine',
+            'wDelete', 'wDelButton', 'wCutMarked', 'wCutLine', 'wCutAppend', 'wCut', 'wCopyMarked', 'wCopyLine', 'wCopyAppend', 'wCopy', 'wCompile',
+            'wClearSel', 'wChange', 'wCallMacro', 'wBackTab', 'wBackspace', 'wAutoIndent', 'wAddButton', 'edWindowTile', 'edWindowRestore',
+            'edWindowNext', 'edWindowMinimize', 'edWindowMaximize', 'edWindowCloseall', 'edWindowClose', 'edWindowCascade', 'edWindowArrangeIcons',
+            'edStatusMsg', 'edSearchViewOutput', 'edSearchRepeat', 'edSearchPrevError', 'edSearchNextError', 'edSearchFind', 'edSearchChange',
+            'edRunRebuild', 'edRunMake', 'edRunExecute', 'edRunDebug', 'edRunConfigure', 'edRunCompile', 'edRunCommand', 'edRecord', 'edHelpProcedures',
+            'edHelpKeyword', 'edHelpKeyboard', 'edHelpIndex', 'edHelpHelp', 'edHelpCommands', 'edHelpAbout', 'edGetWordWrapState', 'edGetWindowName',
+            'edGetUndoState', 'edGetSelectionState', 'edGetRedoState', 'edGetModifiedStatus', 'edGetLineNumber', 'edGetInsertState', 'edGetColumnNumber',
+            'edGetChar', 'edFileSetPreferences', 'edFileSaveAs', 'edFileSave', 'edFilePrinterSetup', 'edFilePrint', 'edFilePageSetup', 'edFileOpen',
+            'edFileNew', 'edFileMerge', 'edFileList', 'edFileExit', 'edEditWrap', 'edEditWordRight', 'edEditWordLeft', 'edEditUpLine', 'edEditUndo',
+            'edEditToggleIns', 'edEditTab', 'edEditStartSelection', 'edEditSetColumnBlock', 'edEditSetBookmark', 'edEditSelectAll', 'edEditRight',
+            'edEditRedo', 'edEditPaste', 'edEditPageUp', 'edEditPageDown', 'edEditLeft', 'edEditInsertString', 'edEditGoToLine', 'edEditGoToColumn',
+            'edEditGoToBookmark', 'edEditGetCurrentWord', 'edEditEndSelection', 'edEditEndOfLine', 'edEditEndOfFile', 'edEditDownline', 'edEditDelete',
+            'edEditCutline', 'edEditCut', 'edEditCopyline', 'edEditCopy', 'edEditClearSelection', 'edEditBeginningOfLine', 'edEditBeginningOfFile',
+            'edEditBackTab', 'edEditBackspace', 'edDeleteButton', 'edAddButton'
+            )
+        ),
+    'SYMBOLS' => array(
+        '(', ')', '[', ']', '{', '}', '!', '+', '-', '~', '$', '^', '?', '@', '%', '#', '&', '*', '|', '/', '<', '>'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false,
+        5 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #800080;',
+            2 => 'color: #0080FF; font-weight: bold;',
+            3 => 'color: #0000FF;',
+            4 => 'color: #FF00FF;',
+            5 => 'color: #008000;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #008000; font-style: italic;',
+            2 => 'color: #FF1010; font-weight: bold;',
+            'MULTI' => 'color: #808080; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            0 => 'color: #006600;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #0000ff;'
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => '',
+        5 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(),
+    'REGEXPS' => array(//Variable names
+        0 => "[\\$]{1,2}[a-zA-Z_][a-zA-Z0-9_]*"
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_MAYBE,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/xml.php b/examples/includes/geshi/geshi/xml.php
new file mode 100644 (file)
index 0000000..48b748c
--- /dev/null
@@ -0,0 +1,157 @@
+<?php
+/*************************************************************************************
+ * xml.php
+ * -------
+ * Author: Nigel McNie (nigel@geshi.org)
+ * Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2004/09/01
+ *
+ * XML language file for GeSHi. Based on the idea/file by Christian Weiske
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *   -  Added description of extra language features (SF#1970248)
+ * 2005/12/28 (1.0.2)
+ *   -  Removed escape character for strings
+ * 2004/11/27 (1.0.1)
+ *   -  Added support for multiple object splitters
+ * 2004/10/27 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ * * Check regexps work and correctly highlight XML stuff and nothing else
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'XML',
+    'COMMENT_SINGLE' => array(),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        ),
+    'SYMBOLS' => array(
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            ),
+        'COMMENTS' => array(
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #66cc66;'
+            ),
+        'SCRIPT' => array(
+            -1 => 'color: #808080; font-style: italic;', // comments
+            0 => 'color: #00bbdd;',
+            1 => 'color: #ddbb00;',
+            2 => 'color: #339933;',
+            3 => 'color: #009900;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #000066;',
+            1 => 'color: #000000; font-weight: bold;',
+            2 => 'color: #000000; font-weight: bold;'
+            )
+        ),
+    'URLS' => array(
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        0 => array(//attribute names
+            GESHI_SEARCH => '([a-z_:][\w\-\.:]*)(=)',
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => 'i',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => '\\2'
+            ),
+        1 => array(//Initial header line
+            GESHI_SEARCH => '(&lt;[\/?|(\?xml)]?[a-z_:][\w\-\.:]*(\??&gt;)?)',
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => 'i',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        2 => array(//Tag end markers
+            GESHI_SEARCH => '(([\/|\?])?&gt;)',
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => 'i',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ''
+            ),
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_ALWAYS,
+    'SCRIPT_DELIMITERS' => array(
+        -1 => array(
+            '<!--' => '-->'
+            ),
+        0 => array(
+            '<!DOCTYPE' => '>'
+            ),
+        1 => array(
+            '&' => ';'
+            ),
+        2 => array(
+            '<![CDATA[' => ']]>'
+            ),
+        3 => array(
+            '<' => '>'
+            )
+    ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        -1 => false,
+        0 => false,
+        1 => false,
+        2 => false,
+        3 => true
+        ),
+    'TAB_WIDTH' => 2,
+    'PARSER_CONTROL' => array(
+        'ENABLE_FLAGS' => array(
+            'NUMBERS' => GESHI_NEVER
+        )
+    )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/xorg_conf.php b/examples/includes/geshi/geshi/xorg_conf.php
new file mode 100644 (file)
index 0000000..643d38d
--- /dev/null
@@ -0,0 +1,124 @@
+<?php
+/*************************************************************************************
+ * xorg_conf.php
+ * ----------
+ * Author: Milian Wolff (mail@milianw.de)
+ * Copyright: (c) 2008 Milian Wolff (http://milianw.de)
+ * Release Version: 1.0.8.3
+ * Date Started: 2008/06/18
+ *
+ * xorg.conf language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/06/18 (1.0.8)
+ *  -  Initial import
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'Xorg configuration',
+    'COMMENT_SINGLE' => array(1 => '#'),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array('"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        // sections
+        1 => array(
+            'Section', 'EndSection', 'SubSection', 'EndSubSection'
+            ),
+        2 => array(
+            // see http://www.x.org/archive/X11R6.9.0/doc/html/xorg.conf.5.html
+            'BiosBase', 'Black', 'Boardname', 'BusID', 'ChipID', 'ChipRev',
+            'Chipset', 'ClockChip', 'Clocks', 'DacSpeed',
+            'DefaultDepth', 'DefaultFbBpp', 'Depth', 'Device',
+            'DisplaySize', 'Driver', 'FbBpp', 'Gamma',
+            'HorizSync', 'IOBase', 'Identifier', 'InputDevice',
+            'Load', 'MemBase', 'Mode', 'Modeline', 'Modelname',
+            'Modes', 'Monitor', 'Option', 'Ramdac', 'RgbPath',
+            'Screen', 'TextClockFreq', 'UseModes', 'VendorName',
+            'VertRefresh', 'VideoAdaptor', 'VideoRam',
+            'ViewPort', 'Virtual', 'Visual', 'Weight', 'White'
+            ),
+        3 => array(
+            // some sub-keywords
+            // screen position
+            'Above', 'Absolute', 'Below', 'LeftOf', 'Relative', 'RightOf',
+            // modes
+            'DotClock', 'Flags', 'HSkew', 'HTimings', 'VScan', 'VTimings'
+            ),
+        ),
+    'REGEXPS' => array(
+        ),
+    'SYMBOLS' => array(
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #b1b100;',
+            2 => 'color: #990000;',
+            3 => 'color: #550000;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #adadad; font-style: italic;',
+            ),
+        'ESCAPE_CHAR' => array(
+            ),
+        'BRACKETS' => array(
+            ),
+        'STRINGS' => array(
+            0 => 'color: #0000ff;',
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #cc66cc;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 4
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/xpp.php b/examples/includes/geshi/geshi/xpp.php
new file mode 100644 (file)
index 0000000..6e7c980
--- /dev/null
@@ -0,0 +1,436 @@
+<?php
+/*************************************************************************************
+ * xpp.php
+ * -------
+ * Author: Simon Butcher (simon@butcher.name)
+ * Copyright: (c) 2007 Simon Butcher (http://simon.butcher.name/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2007/02/27
+ *
+ * Axapta/Dynamics Ax X++ language file for GeSHi.
+ * For details, see <http://msdn.microsoft.com/en-us/library/aa867122.aspx>
+ *
+ * CHANGES
+ * -------
+ * 2007/02/28 (1.0.0)
+ *  -  First Release
+ *
+ * TODO (updated 2007/02/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'X++',
+    'COMMENT_SINGLE' => array(1 => '//'),
+    'COMMENT_MULTI' => array('/*' => '*/'),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '\\',
+    'KEYWORDS' => array(
+        1 => array( // Primitive types
+            'void',
+            'str',
+            'real',
+            'int64',
+            'int',
+            'date',
+            'container',
+            'boolean',
+            'anytype'
+            ),
+        2 => array( // Keywords
+            'window',
+            'while',
+            'try',
+            'true',
+            'throw',
+            'switch',
+            'super',
+            'static',
+            'server',
+            'right',
+            'return',
+            'retry',
+            'public',
+            'protected',
+            'private',
+            'print',
+            'pause',
+            'null',
+            'new',
+            'mod',
+            'left',
+            'interface',
+            'implements',
+            'if',
+            'for',
+            'final',
+            'false',
+            'extends',
+            'else',
+            'edit',
+            'do',
+            'div',
+            'display',
+            'default',
+            'continue',
+            'client',
+            'class',
+            'changeCompany',
+            'case',
+            'breakpoint',
+            'break',
+            'at',
+            'abstract'
+            ),
+        3 => array( // Functions within the Axapta kernel
+            'year',
+            'wkofyr',
+            'webwebpartstr',
+            'webstaticfilestr',
+            'websitetempstr',
+            'websitedefstr',
+            'webreportstr',
+            'webpagedefstr',
+            'weboutputcontentitemstr',
+            'webmenustr',
+            'webletitemstr',
+            'webformstr',
+            'webdisplaycontentitemstr',
+            'webactionitemstr',
+            'varstr',
+            'utilmoyr',
+            'uint2str',
+            'typeof',
+            'typeid',
+            'trunc',
+            'today',
+            'timenow',
+            'time2str',
+            'term',
+            'tanh',
+            'tan',
+            'tablestr',
+            'tablestaticmethodstr',
+            'tablepname',
+            'tablenum',
+            'tablename2id',
+            'tablemethodstr',
+            'tableid2pname',
+            'tableid2name',
+            'tablefieldgroupstr',
+            'tablecollectionstr',
+            'systemdateset',
+            'systemdateget',
+            'syd',
+            'substr',
+            'strupr',
+            'strscan',
+            'strrtrim',
+            'strrep',
+            'strrem',
+            'strprompt',
+            'strpoke',
+            'strnfind',
+            'strlwr',
+            'strltrim',
+            'strline',
+            'strlen',
+            'strkeep',
+            'strins',
+            'strfmt',
+            'strfind',
+            'strdel',
+            'strcolseq',
+            'strcmp',
+            'stralpha',
+            'str2time',
+            'str2num',
+            'str2int64',
+            'str2int',
+            'str2guid',
+            'str2enum',
+            'str2date',
+            'staticmethodstr',
+            'sln',
+            'sleep',
+            'sinh',
+            'sin',
+            'setprefix',
+            'sessionid',
+            'securitykeystr',
+            'securitykeynum',
+            'runbuf',
+            'runas',
+            'round',
+            'resourcestr',
+            'reportstr',
+            'refprintall',
+            'rate',
+            'querystr',
+            'pv',
+            'pt',
+            'prmisdefault',
+            'primoyr',
+            'prevyr',
+            'prevqtr',
+            'prevmth',
+            'power',
+            'pmt',
+            'num2str',
+            'num2date',
+            'num2char',
+            'nextyr',
+            'nextqtr',
+            'nextmth',
+            'newguid',
+            'mthofyr',
+            'mthname',
+            'mkdate',
+            'minint',
+            'min',
+            'methodstr',
+            'menustr',
+            'menuitemoutputstr',
+            'menuitemdisplaystr',
+            'menuitemactionstr',
+            'maxint',
+            'maxdate',
+            'max',
+            'match',
+            'logn',
+            'log10',
+            'literalstr',
+            'licensecodestr',
+            'licensecodenum',
+            'intvnorm',
+            'intvno',
+            'intvname',
+            'intvmax',
+            'int64str',
+            'indexstr',
+            'indexnum',
+            'indexname2id',
+            'indexid2name',
+            'idg',
+            'identifierstr',
+            'helpfilestr',
+            'helpdevstr',
+            'helpapplstr',
+            'guid2str',
+            'getprefix',
+            'getCurrentUTCTime',
+            'fv',
+            'funcname',
+            'frac',
+            'formstr',
+            'fieldstr',
+            'fieldpname',
+            'fieldnum',
+            'fieldname2id',
+            'fieldid2pname',
+            'fieldid2name',
+            'extendedTypeStr',
+            'extendedTypeNum',
+            'exp10',
+            'exp',
+            'evalbuf',
+            'enumstr',
+            'enumnum',
+            'enumcnt',
+            'enum2str',
+            'endmth',
+            'dimof',
+            'dg',
+            'decround',
+            'ddb',
+            'dayofyr',
+            'dayofwk',
+            'dayofmth',
+            'dayname',
+            'date2str',
+            'date2num',
+            'curuserid',
+            'curext',
+            'cterm',
+            'cosh',
+            'cos',
+            'corrflagset',
+            'corrflagget',
+            'convertUTCTimeToLocalTime',
+            'convertUTCDateToLocalDate',
+            'conpoke',
+            'conpeek',
+            'connull',
+            'conlen',
+            'conins',
+            'confind',
+            'configurationkeystr',
+            'configurationkeynum',
+            'condel',
+            'classstr',
+            'classnum',
+            'classidget',
+            'char2num',
+            'beep',
+            'atan',
+            'asin',
+            'ascii2ansi',
+            'any2str',
+            'any2real',
+            'any2int64',
+            'any2int',
+            'any2guid',
+            'any2enum',
+            'any2date',
+            'ansi2ascii',
+            'acos',
+            'abs'
+            ),
+        4 => array( // X++ SQL stuff
+            'where',
+            'update_recordset',
+            'ttsCommit',
+            'ttsBegin',
+            'ttsAbort',
+            'sum',
+            'setting',
+            'select',
+            'reverse',
+            'pessimisticLock',
+            'outer',
+            'order by',
+            'optimisticLock',
+            'notExists',
+            'noFetch',
+            'next',
+            'minof',
+            'maxof',
+            'like',
+            'join',
+            'insert_recordset',
+            'index hint',
+            'index',
+            'group by',
+            'from',
+            'forUpdate',
+            'forceSelectOrder',
+            'forcePlaceholders',
+            'forceNestedLoop',
+            'forceLiterals',
+            'flush',
+            'firstOnly',
+            'firstFast',
+            'exists',
+            'desc',
+            'delete_from',
+            'count',
+            'avg',
+            'asc'
+            )
+        ),
+    'SYMBOLS' => array( // X++ symbols
+        '!',
+        '&',
+        '(',
+        ')',
+        '*',
+        '^',
+        '|',
+        '~',
+        '+',
+        ',',
+        '-',
+        '/',
+        ':',
+        '<',
+        '=',
+        '>',
+        '?',
+        '[',
+        ']',
+        '{',
+        '}'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        4 => false
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0000ff;',
+            2 => 'color: #0000ff;',
+            3 => 'color: #0000ff;',
+            4 => 'color: #0000ff;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #007f00;',
+            'MULTI' => 'color: #007f00; font-style: italic;'
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000000;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #000000;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #ff0000;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #000000;'
+            ),
+        'METHODS' => array(
+            1 => 'color: #000000;',
+            2 => 'color: #000000;'
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #00007f;'
+            ),
+        'REGEXPS' => array(
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => '',
+        4 => ''
+        ),
+    'OOLANG' => true,
+    'OBJECT_SPLITTERS' => array(
+        1 => '.',
+        2 => '::'
+        ),
+    'REGEXPS' => array(
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        )
+);
+
+?>
diff --git a/examples/includes/geshi/geshi/z80.php b/examples/includes/geshi/geshi/z80.php
new file mode 100644 (file)
index 0000000..845712f
--- /dev/null
@@ -0,0 +1,144 @@
+<?php
+/*************************************************************************************
+ * z80.php
+ * -------
+ * Author: Benny Baumann (BenBE@omorphia.de)
+ * Copyright: (c) 2007-2008 Benny Baumann (http://www.omorphia.de/)
+ * Release Version: 1.0.8.3
+ * Date Started: 2007/02/06
+ *
+ * ZiLOG Z80 Assembler language file for GeSHi.
+ * Syntax definition as commonly used with table assembler TASM32
+ * This file will contain some undocumented opcodes.
+ *
+ * CHANGES
+ * -------
+ * 2008/05/23 (1.0.7.22)
+ *   -  Added description of extra language features (SF#1970248)
+ * 2007/06/03 (1.0.1)
+ *   -  Fixed two typos in the language file
+ * 2007/02/06 (1.0.0)
+ *   -  First Release
+ *
+ * TODO (updated 2007/02/06)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ *     This file is part of GeSHi.
+ *
+ *   GeSHi 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.
+ *
+ *   GeSHi 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 GeSHi; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+    'LANG_NAME' => 'ZiLOG Z80 Assembler',
+    'COMMENT_SINGLE' => array(1 => ';'),
+    'COMMENT_MULTI' => array(),
+    'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+    'QUOTEMARKS' => array("'", '"'),
+    'ESCAPE_CHAR' => '',
+    'KEYWORDS' => array(
+        /*CPU*/
+        1 => array(
+            'adc','add','and','bit','call','ccf','cp','cpd','cpdr','cpir','cpi',
+            'cpl','daa','dec','di','djnz','ei','ex','exx','halt','im','in',
+            'in0','inc','ind','indr','inir','ini','jp','jr','ld','ldd','lddr',
+            'ldir','ldi','mlt','neg','nop','or','otdm','otdmr','otdr','otim',
+            'otimr','otir','out','out0','outd','outi','pop','push','res','ret',
+            'reti','retn','rl','rla','rlc','rlca','rld','rr','rra','rrc','rrca',
+            'rrd','rst','sbc','scf','set','sla','sl1','sll','slp','sra','srl',
+            'sub','tst','tstio','xor'
+            ),
+        /*registers*/
+        2 => array(
+            'a','b','c','d','e','h','l',
+            'af','bc','de','hl','ix','iy','sp',
+            'af\'','ixh','ixl','iyh','iyl'
+            ),
+        /*Directive*/
+        3 => array(
+            '#define','#endif','#else','#ifdef','#ifndef','#include','#undef',
+            '.db','.dd','.df','.dq','.dt','.dw','.end','.org','equ'
+            ),
+        ),
+    'SYMBOLS' => array(
+        '[', ']', '(', ')', '?', '+', '-', '*', '/', '%', '$'
+        ),
+    'CASE_SENSITIVE' => array(
+        GESHI_COMMENTS => false,
+        1 => false,
+        2 => false,
+        3 => false,
+        ),
+    'STYLES' => array(
+        'KEYWORDS' => array(
+            1 => 'color: #0000ff; font-weight:bold;',
+            2 => 'color: #0000ff;',
+            3 => 'color: #46aa03; font-weight:bold;'
+            ),
+        'COMMENTS' => array(
+            1 => 'color: #adadad; font-style: italic;',
+            ),
+        'ESCAPE_CHAR' => array(
+            0 => 'color: #000099; font-weight: bold;'
+            ),
+        'BRACKETS' => array(
+            0 => 'color: #0000ff;'
+            ),
+        'STRINGS' => array(
+            0 => 'color: #7f007f;'
+            ),
+        'NUMBERS' => array(
+            0 => 'color: #dd22dd;'
+            ),
+        'METHODS' => array(
+            ),
+        'SYMBOLS' => array(
+            0 => 'color: #008000;'
+            ),
+        'REGEXPS' => array(
+            0 => 'color: #22bbff;',
+            1 => 'color: #22bbff;',
+            2 => 'color: #993333;'
+            ),
+        'SCRIPT' => array(
+            )
+        ),
+    'URLS' => array(
+        1 => '',
+        2 => '',
+        3 => ''
+        ),
+    'OOLANG' => false,
+    'OBJECT_SPLITTERS' => array(
+        ),
+    'REGEXPS' => array(
+        //Hex numbers
+        0 => '0[0-9a-fA-F]{1,32}[hH]',
+        //Binary numbers
+        1 => '\%[01]{1,64}|[01]{1,64}[bB]?',
+        //Labels
+        2 => '^[_a-zA-Z][_a-zA-Z0-9]?\:'
+        ),
+    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    'SCRIPT_DELIMITERS' => array(
+        ),
+    'HIGHLIGHT_STRICT_BLOCK' => array(
+        ),
+    'TAB_WIDTH' => 8
+);
+
+?>
diff --git a/examples/includes/vp8_doc_tools.php b/examples/includes/vp8_doc_tools.php
new file mode 100644 (file)
index 0000000..aee2a2e
--- /dev/null
@@ -0,0 +1,207 @@
+#!/usr/bin/env php
+<?php
+/**
+ * vp8_doc_tools.php - Functions used when generating the
+ *   On2 VP8 user documentation.
+ *
+ * Requirements
+ *
+ *   PHP Markdown Extra
+ *   http://michelf.com/projects/php-markdown/extra/
+ *
+ *   PHP SmartyPants
+ *   http://michelf.com/projects/php-smartypants/
+ *
+ *   GeSHI
+ *   http://qbnz.com/highlighter/
+ *
+ *   ASCIIMathPHP
+ *   http://tinyurl.com/asciimathphp
+ *
+ *   HTML::Toc
+ *   http://search.cpan.org/~fvulto/HTML-Toc-0.91/Toc.pod
+ *
+ *
+ * April 2009 - Lou Quillio <lou.quillio@on2.com>
+ *
+ **********************************************************/
+
+
+// Includes
+include_once('PHP-Markdown-Extra-1.2.3/markdown.php');
+include_once('PHP-SmartyPants-1.5.1e/smartypants.php');
+include_once('ASCIIMathPHP-2.0/ASCIIMathPHP-2.0.cfg.php');
+require_once('ASCIIMathPHP-2.0/ASCIIMathPHP-2.0.class.php');
+include_once('geshi/geshi.php');
+
+
+// Paths and Scripts
+$geshi_lang   = 'geshi/geshi/';       // GeSHi language files
+$toc_script     = './do_toc.pl';
+
+
+
+/**
+ * ASCIIMathML parser
+ * http://tinyurl.com/ASCIIMathPHP
+ *
+ * @PARAM mtch_arr array - Array of ASCIIMath expressions
+ *   as returned by preg_replace_callback([pattern]). First
+ *   dimension is the full matched string (with delimiter);
+ *   2nd dimension is the undelimited contents (typically
+ *   a capture group).
+ *
+ **********************************************************/
+
+function ASCIIMathPHPCallback($mtch_arr)
+{
+  $txt = trim($mtch_arr[1]);
+
+  static $asciimath;
+
+  if (!isset($asciimath)) $asciimath = new ASCIIMathPHP($symbol_arr);
+
+  $math_attr_arr = array('displaystyle' => 'true');
+
+  $asciimath->setExpr($txt);
+  $asciimath->genMathML($math_attr_arr);
+
+  return($asciimath->getMathML());
+}
+
+/**
+ * fix_asciiMath()
+ *
+ * ASCIIMath pretty-prints its output, with linefeeds
+ * and tabs. Causes unexpected behavior in some renderers.
+ * This flattens <math> blocks.
+ *
+ * @PARAM page_body str - The <body> element of an
+ * XHTML page to transform.
+ *
+ **********************************************************/
+
+function fix_asciiMath($page_body)
+{
+  $out = FALSE;
+
+  // Remove linefeeds and whitespace in <math> elements
+  $tags_bad  = array('/(<math.*?>)\n*\s*/'
+                    , '/(<mstyle.*?>)\n*\s*/'
+                    , '/(<\/mstyle>)\n*\s*/'
+                    , '/(<mrow.*?>)\n*\s*/'
+                    , '/(<\/mrow>)\n*\s*/'
+                    , '/(<mo.*?>)\n*\s*/'
+                    , '/(<\/mo>)\n*\s*/'
+                    , '/(<mi.*?>)\n*\s*/'
+                    , '/(<\/mi>)\n*\s*/'
+                    , '/(<mn.*?>)\n*\s*/'
+                    , '/(<\/mn>)\n*\s*/'
+                    , '/(<mtext.*?>)\n*\s*/'
+                    , '/(<\/mtext>)\n*\s*/'
+                    , '/(<msqrt.*?>)\n*\s*/'
+                    , '/(<\/msqrt>)\n*\s*/'
+                    , '/(<mfrac.*?>)\n*\s*/'
+                    , '/(<\/mfrac>)\n*\s*/'
+                    );
+  $tags_good = array( '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    , '$1'
+                    );
+  $out = preg_replace($tags_bad, $tags_good, $page_body);
+
+  return $out;
+
+}
+
+/**
+ * do_geshi() - Performs GeSHi transforms on XHTML blobs
+ *
+ * @param $blob str  - The blob to transform
+ * @param $open str  - Opening expression to match
+ * @param $close str - Closing expression to match
+ * @param $lang str  - Language file to use
+ *
+ **********************************************************/
+
+function do_geshi($blob, $open = '<pre>',
+                    $close = '</pre>', $lang = 'c')
+{
+  $out = FALSE;
+  $regexp = '|' . $open . '(.*?)' . $close . '|si';
+  echo $regexp . "\n\n";
+
+  while (preg_match($regexp, $blob, $matches))
+  {
+    $geshi = new GeSHi($matches[1], $lang);
+    $geshi->set_language_path($geshi_lang);
+    $blob_new = $geshi->parse_code();
+    // Strip annoying final <br />
+    $blob_new  = preg_replace('/\n&nbsp;<\/pre>/', '</pre>' , $blob_new);
+    // Fix annoying GeSHI-injected attributes
+    $blob_new  = preg_replace('/<pre.*>/i', '<pre>' , $blob_new);
+    $blob  = preg_replace($regexp, $blob_new, $blob, 1);
+    unset($geshi);
+  }
+
+  return $out;
+
+}
+
+
+
+
+/**
+ * prep_dd_codeblocks()
+ *
+ * I'm _so_ not proud of this, but don't have time to
+ * write a proper regex.
+ *
+ * @TODO - Write that regex.
+ *
+ **********************************************************/
+/*
+function prep_dd_codeblocks($page_body)
+{
+  $out = FALSE;
+  $toggle = 0;
+  $regexp = '/~{3,}/';
+
+  while (preg_match($regexp, $page_body))
+  {
+    if ($toggle == 0)
+    {
+      $regexp = '/:\s*~{3,}\s*\n/';
+      $page_body = preg_replace($regexp, ': <pre><code>', $page_body, 1);
+      $toggle = 1;
+    }
+    else
+    {
+      $regexp = '/\n\s*~{3,}/';
+      $page_body = preg_replace($regexp, '</code></pre>', $page_body, 1);
+      $toggle = 0;
+    }
+  }
+
+  // One more time
+  $regexp = '/\n\s*~{3,}/';
+  $page_body = preg_replace($regexp, '</code></pre>', $page_body, 1);
+  $out = $page_body;
+
+  return $out;
+}
+*/
diff --git a/examples/postproc.txt b/examples/postproc.txt
new file mode 100644 (file)
index 0000000..51b251a
--- /dev/null
@@ -0,0 +1,67 @@
+@TEMPLATE decoder_tmpl.c
+Postprocessing Decoder
+======================
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+This example adds postprocessing to the simple decoder loop.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+
+
+Initializing Postprocessing
+---------------------------
+You must inform the codec that you might request postprocessing at
+initialization time. This is done by passing the VPX_CODEC_USE_POSTPROC
+flag to `vpx_codec_dec_init`. If the codec does not support
+postprocessing, this call will return VPX_CODEC_INCAPABLE. For
+demonstration purposes, we also fall back to default initialization if
+the codec does not provide support.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INIT
+/* Initialize codec */
+res = vpx_codec_dec_init(&codec, interface, NULL,
+                         VPX_CODEC_USE_POSTPROC);
+if(res == VPX_CODEC_INCAPABLE) {
+    printf("NOTICE: Postproc not supported by %s\n",
+           vpx_codec_iface_name(interface));
+    res = vpx_codec_dec_init(&codec, interface, NULL, flags);
+}
+if(res)
+    die_codec(&codec, "Failed to initialize decoder");
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INIT
+
+
+Using Adaptive Postprocessing
+-----------------------------
+VP6 provides "adaptive postprocessing." It will automatically select the
+best postprocessing filter on a frame by frame basis based on the amount
+of time remaining before the user's specified deadline expires. The
+special value 0 indicates that the codec should take as long as
+necessary to provide the best quality frame. This example gives the
+codec 15ms (15000us) to return a frame. Remember that this is a soft
+deadline, and the codec may exceed it doing its regular processing. In
+these cases, no additional postprocessing will be done.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DECODE
+/* Decode the frame with 15ms deadline */
+if(vpx_codec_decode(&codec, frame, frame_sz, NULL, 15000))
+    die_codec(&codec, "Failed to decode frame");
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DECODE
+
+
+Codec Specific Postprocessing Controls
+--------------------------------------
+Some codecs provide fine grained controls over their built-in
+postprocessors. VP8 is one example. The following sample code toggles
+postprocessing on and off every 15 frames.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PRE_DECODE
+#if CONFIG_VP8_DECODER
+if(frame_cnt%30 == 1) {
+    vp8_postproc_cfg_t  pp = {0, 0, 0};
+
+    if(vpx_codec_control(&codec, VP8_SET_POSTPROC, &pp))
+        die_codec(&codec, "Failed to turn off postproc");
+} else if(frame_cnt%30 == 16) {
+    vp8_postproc_cfg_t  pp = {VP8_DEBLOCK | VP8_DEMACROBLOCK | VP8_MFQE, 4, 0};
+
+    if(vpx_codec_control(&codec, VP8_SET_POSTPROC, &pp))
+        die_codec(&codec, "Failed to turn on postproc");
+};
+#endif
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PRE_DECODE
diff --git a/examples/simple_decoder.txt b/examples/simple_decoder.txt
new file mode 100644 (file)
index 0000000..90d9a68
--- /dev/null
@@ -0,0 +1,96 @@
+@TEMPLATE decoder_tmpl.c
+Simple Decoder
+==============
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+This is an example of a simple decoder loop. It takes an input file
+containing the compressed data (in IVF format), passes it through the
+decoder, and writes the decompressed frames to disk. Other decoder
+examples build upon this one.
+
+The details of the IVF format have been elided from this example for
+simplicity of presentation, as IVF files will not generally be used by
+your application. In general, an IVF file consists of a file header,
+followed by a variable number of frames. Each frame consists of a frame
+header followed by a variable length payload. The length of the payload
+is specified in the first four bytes of the frame header. The payload is
+the raw compressed data.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+
+
+Standard Includes
+-----------------
+For decoders, you only have to include `vpx_decoder.h` and then any
+header files for the specific codecs you use. In this case, we're using
+vp8. The `VPX_CODEC_DISABLE_COMPAT` macro can be defined to ensure
+strict compliance with the latest SDK by disabling some backwards
+compatibility features. Defining this macro is encouraged.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INCLUDES
+@DEFAULT
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INCLUDES
+
+
+Initializing The Codec
+----------------------
+The decoder is initialized by the following code. This is an example for
+the VP8 decoder, but the code is analogous for all algorithms. Replace
+`vpx_codec_vp8_dx()` with a pointer to the interface exposed by the
+algorithm you want to use. The `cfg` argument is left as NULL in this
+example, because we want the algorithm to determine the stream
+configuration (width/height) and allocate memory automatically. This
+parameter is generally only used if you need to preallocate memory,
+particularly in External Memory Allocation mode.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INIT
+@DEFAULT
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INIT
+
+
+Decoding A Frame
+----------------
+Once the frame has been read into memory, it is decoded using the
+`vpx_codec_decode` function. The call takes a pointer to the data
+(`frame`) and the length of the data (`frame_sz`). No application data
+is associated with the frame in this example, so the `user_priv`
+parameter is NULL. The `deadline` parameter is left at zero for this
+example. This parameter is generally only used when doing adaptive
+postprocessing.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DECODE
+@DEFAULT
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DECODE
+
+Codecs may produce a variable number of output frames for every call to
+`vpx_codec_decode`. These frames are retrieved by the
+`vpx_codec_get_frame` iterator function. The iterator variable `iter` is
+initialized to NULL each time `vpx_codec_decode` is called.
+`vpx_codec_get_frame` is called in a loop, returning a pointer to a
+decoded image or NULL to indicate the end of list.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GET_FRAME
+@DEFAULT
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GET_FRAME
+
+
+Processing The Decoded Data
+---------------------------
+In this example, we simply write the encoded data to disk. It is
+important to honor the image's `stride` values.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_DX
+@DEFAULT
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_DX
+
+
+Cleanup
+-------
+The `vpx_codec_destroy` call frees any memory allocated by the codec.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DESTROY
+@DEFAULT
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DESTROY
+
+
+Error Handling
+--------------
+This example does not special case any error return codes. If there was
+an error, a descriptive message is printed and the program exits. With
+few exeptions, vpx_codec functions return an enumerated error status,
+with the value `0` indicating success.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DIE_CODEC
+@DEFAULT
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DIE_CODEC
diff --git a/examples/simple_encoder.txt b/examples/simple_encoder.txt
new file mode 100644 (file)
index 0000000..44c5b08
--- /dev/null
@@ -0,0 +1,105 @@
+@TEMPLATE encoder_tmpl.c
+Simple Encoder
+==============
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+This is an example of a simple encoder loop. It takes an input file in
+YV12 format, passes it through the encoder, and writes the compressed
+frames to disk in IVF format. Other decoder examples build upon this
+one.
+
+The details of the IVF format have been elided from this example for
+simplicity of presentation, as IVF files will not generally be used by
+your application. In general, an IVF file consists of a file header,
+followed by a variable number of frames. Each frame consists of a frame
+header followed by a variable length payload. The length of the payload
+is specified in the first four bytes of the frame header. The payload is
+the raw compressed data.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+
+
+Standard Includes
+-----------------
+For encoders, you only have to include `vpx_encoder.h` and then any
+header files for the specific codecs you use. In this case, we're using
+vp8. The `VPX_CODEC_DISABLE_COMPAT` macro can be defined to ensure
+strict compliance with the latest SDK by disabling some backwards
+compatibility features. Defining this macro is encouraged.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_INCLUDES
+@DEFAULT
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_INCLUDES
+
+
+Getting The Default Configuration
+---------------------------------
+Encoders have the notion of "usage profiles." For example, an encoder
+may want to publish default configurations for both a video
+conferencing appliction and a best quality offline encoder. These
+obviously have very different default settings. Consult the
+documentation for your codec to see if it provides any default
+configurations. All codecs provide a default configuration, number 0,
+which is valid for material in the vacinity of QCIF/QVGA.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_DEF_CFG
+@DEFAULT
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_DEF_CFG
+
+
+Updating The Configuration
+---------------------------------
+Almost all applications will want to update the default configuration
+with settings specific to their usage. Here we set the width and height
+of the video file to that specified on the command line. We also scale
+the default bitrate based on the ratio between the default resolution
+and the resolution specified on the command line.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_SET_CFG
+@DEFAULT
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_SET_CFG
+
+
+Initializing The Codec
+----------------------
+The encoder is initialized by the following code.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_INIT
+@DEFAULT
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_INIT
+
+
+Encoding A Frame
+----------------
+The frame is read as a continuous block (size width * height * 3 / 2)
+from the input file. If a frame was read (the input file has not hit
+EOF) then the frame is passed to the encoder. Otherwise, a NULL
+is passed, indicating the End-Of-Stream condition to the encoder. The
+`frame_cnt` is reused as the presentation time stamp (PTS) and each
+frame is shown for one frame-time in duration. The flags parameter is
+unused in this example. The deadline is set to VPX_DL_REALTIME to
+make the example run as quickly as possible.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENCODE_FRAME
+@DEFAULT
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENCODE_FRAME
+
+Processing The Encoded Data
+---------------------------
+Each packet of type `VPX_CODEC_CX_FRAME_PKT` contains the encoded data
+for this frame. We write a IVF frame header, followed by the raw data.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_FRAME
+@DEFAULT
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_FRAME
+
+
+Cleanup
+-------
+The `vpx_codec_destroy` call frees any memory allocated by the codec.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DESTROY
+@DEFAULT
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DESTROY
+
+
+Error Handling
+--------------
+This example does not special case any error return codes. If there was
+an error, a descriptive message is printed and the program exits. With
+few exeptions, vpx_codec functions return an enumerated error status,
+with the value `0` indicating success.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DIE_CODEC
+@DEFAULT
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DIE_CODEC
diff --git a/examples/twopass_encoder.txt b/examples/twopass_encoder.txt
new file mode 100644 (file)
index 0000000..4683bc7
--- /dev/null
@@ -0,0 +1,75 @@
+@TEMPLATE encoder_tmpl.c
+Two Pass Encoder
+================
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+This is an example of a two pass encoder loop. It takes an input file in
+YV12 format, passes it through the encoder twice, and writes the compressed
+frames to disk in IVF format. It builds upon the simple_encoder example.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+
+
+Twopass Variables
+-----------------
+Twopass mode needs to track the current pass number and the buffer of
+statistics packets.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TWOPASS_VARS
+int                  pass;
+vpx_fixed_buf_t      stats = {0};
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TWOPASS_VARS
+
+
+Updating The Configuration
+---------------------------------
+In two pass mode, the configuration has to be updated on each pass. The
+statistics buffer is passed on the last pass.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TWOPASS_LOOP_BEGIN
+for(pass=0; pass<2; pass++) {
+    frame_cnt = 0;
+
+    if(pass == 0)
+        cfg.g_pass = VPX_RC_FIRST_PASS;
+    else {
+        cfg.g_pass              = VPX_RC_LAST_PASS;
+        cfg.rc_twopass_stats_in = stats;
+    }
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TWOPASS_LOOP_BEGIN
+
+
+Encoding A Frame
+----------------
+Encoding a frame in two pass mode is identical to the simple encoder
+example, except the deadline is set to VPX_DL_BEST_QUALITY to get the
+best quality possible. VPX_DL_GOOD_QUALITY could also be used.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENCODE_FRAME
+frame_avail = read_frame(infile, &raw);
+if(vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt,
+                    1, flags, VPX_DL_BEST_QUALITY))
+    die_codec(&codec, "Failed to encode frame");
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENCODE_FRAME
+
+
+Processing Statistics Packets
+-----------------------------
+Each packet of type `VPX_CODEC_CX_FRAME_PKT` contains the encoded data
+for this frame. We write a IVF frame header, followed by the raw data.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_STATS
+case VPX_CODEC_STATS_PKT:
+    stats.buf = realloc(stats.buf, stats.sz
+                        + pkt->data.twopass_stats.sz);
+    if(!stats.buf)
+        die("Memory reallocation failed.\n");
+    memcpy((char*)stats.buf + stats.sz,
+           pkt->data.twopass_stats.buf,
+           pkt->data.twopass_stats.sz);
+    stats.sz +=  pkt->data.twopass_stats.sz;
+    break;
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_STATS
+
+
+Pass Progress Reporting
+-----------------------------
+It's sometimes helpful to see when each pass completes.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TWOPASS_LOOP_END
+    printf("Pass %d complete.\n", pass+1);
+}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TWOPASS_LOOP_END
diff --git a/examples/vp8_set_maps.txt b/examples/vp8_set_maps.txt
new file mode 100644 (file)
index 0000000..ad9ef61
--- /dev/null
@@ -0,0 +1,96 @@
+@TEMPLATE encoder_tmpl.c
+VP8 Set Active and ROI Maps
+===========================
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+This is an example demonstrating how to control the VP8 encoder's
+ROI and Active maps.
+
+ROI (Reigon of Interest) maps are a way for the application to assign
+each macroblock in the image to a region, and then set quantizer and
+filtering parameters on that image.
+
+Active maps are a way for the application to specify on a
+macroblock-by-macroblock basis whether there is any activity in that
+macroblock.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+
+
+Configuration
+-------------
+An ROI map is set on frame 22. If the width of the image in macroblocks
+is evenly divisble by 4, then the output will appear to have distinct
+columns, where the quantizer, loopfilter, and static threshold differ
+from column to column.
+
+An active map is set on frame 33. If the width of the image in macroblocks
+is evenly divisble by 4, then the output will appear to have distinct
+columns, where one column will have motion and the next will not.
+
+The active map is cleared on frame 44.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  PER_FRAME_CFG
+if(frame_cnt + 1 == 22) {
+    vpx_roi_map_t  roi;
+    int            i;
+
+    roi.rows = cfg.g_h/16;
+    roi.cols = cfg.g_w/16;
+
+    roi.delta_q[0] = 0;
+    roi.delta_q[1] = -2;
+    roi.delta_q[2] = -4;
+    roi.delta_q[3] = -6;
+
+    roi.delta_lf[0] = 0;
+    roi.delta_lf[1] = 1;
+    roi.delta_lf[2] = 2;
+    roi.delta_lf[3] = 3;
+
+    roi.static_threshold[0] = 1500;
+    roi.static_threshold[1] = 1000;
+    roi.static_threshold[2] =  500;
+    roi.static_threshold[3] =    0;
+
+    /* generate an ROI map for example */
+    roi.roi_map = malloc(roi.rows * roi.cols);
+    for(i=0;i<roi.rows*roi.cols;i++)
+        roi.roi_map[i] = i & 3;
+
+    if(vpx_codec_control(&codec, VP8E_SET_ROI_MAP, &roi))
+        die_codec(&codec, "Failed to set ROI map");
+
+    free(roi.roi_map);
+} else if(frame_cnt + 1 == 33) {
+    vpx_active_map_t  active;
+    int               i;
+
+    active.rows = cfg.g_h/16;
+    active.cols = cfg.g_w/16;
+
+    /* generate active map for example */
+    active.active_map = malloc(active.rows * active.cols);
+    for(i=0;i<active.rows*active.cols;i++)
+        active.active_map[i] = i & 1;
+
+    if(vpx_codec_control(&codec, VP8E_SET_ACTIVEMAP, &active))
+        die_codec(&codec, "Failed to set active map");
+
+    free(active.active_map);
+} else if(frame_cnt + 1 == 44) {
+    vpx_active_map_t  active;
+
+    active.rows = cfg.g_h/16;
+    active.cols = cfg.g_w/16;
+
+    /* pass in null map to disable active_map*/
+    active.active_map = NULL;
+
+    if(vpx_codec_control(&codec, VP8E_SET_ACTIVEMAP, &active))
+        die_codec(&codec, "Failed to set active map");
+}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  PER_FRAME_CFG
+
+
+Observing The Effects
+---------------------
+Use the `simple_decoder` example to decode this sample, and observe
+the change in the image at frames 22, 33, and 44.
diff --git a/examples/vp8cx_set_ref.txt b/examples/vp8cx_set_ref.txt
new file mode 100644 (file)
index 0000000..dc8a717
--- /dev/null
@@ -0,0 +1,73 @@
+@TEMPLATE encoder_tmpl.c
+VP8 Set Reference Frame
+=======================
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+This is an example demonstrating how to overwrite the VP8 encoder's
+internal reference frame. In the sample we set the last frame to the
+current frame. If this is done at a cut scene it will avoid a keyframe.
+This technique could be used to bounce between two cameras.
+
+Note that the decoder would also have to set the reference frame to the
+same value on the same frame, or the video will become corrupt.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
+
+
+Usage
+-----
+This example adds a single argument to the `simple_encoder` example,
+which specifies the frame number to update the reference frame on.
+The parameter is parsed as follows:
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
+if(argc!=6)
+    die("Usage: %s <width> <height> <infile> <outfile> <frame>\n",
+        argv[0]);
+
+    update_frame_num = atoi(argv[5]);
+    if(!update_frame_num)
+        die("Couldn't parse frame number '%s'\n", argv[5]);
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
+
+
+Extra Variables
+---------------
+This example maintains the frame number passed on the command line
+in the `update_frame_num` variable:
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TWOPASS_VARS
+int                  update_frame_num = 0;
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TWOPASS_VARS
+
+
+Configuration
+-------------
+
+The reference frame is updated on the frame specified on the command
+line.
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENCODE_FRAME
+frame_avail = read_frame(infile, &raw);
+
+if(frame_cnt + 1 == update_frame_num) {
+    vpx_ref_frame_t ref;
+
+    ref.frame_type = VP8_LAST_FRAME;
+    ref.img        = raw;
+
+    if(vpx_codec_control(&codec, VP8_SET_REFERENCE, &ref))
+        die_codec(&codec, "Failed to set reference frame");
+}
+
+if(vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt,
+                    1, flags, VPX_DL_REALTIME))
+    die_codec(&codec, "Failed to encode frame");
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENCODE_FRAME
+
+
+Observing The Effects
+---------------------
+Use the `simple_encoder` example to encode a sample with a cut scene.
+Determine the frame number of the cut scene by looking for a generated
+key-frame (indicated by a 'K'). Supply that frame number as an argument
+to this example, and observe that no key-frame is generated.
diff --git a/keywords.dox b/keywords.dox
new file mode 100644 (file)
index 0000000..56f5368
--- /dev/null
@@ -0,0 +1,51 @@
+/*!\page rfc2119 RFC2119 Keywords
+
+      The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
+      NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED",  "MAY", and
+      "OPTIONAL" in this document are to be interpreted as described in
+      <a href="http://www.ietf.org/rfc/rfc2119.txt">RFC 2119.</a>
+
+Specifically, the following definitions are used:
+
+\section MUST
+\anchor REQUIRED
+\anchor SHALL
+   This word, or the terms "REQUIRED" or "SHALL", mean that the
+   definition is an absolute requirement of the specification.
+
+\section MUSTNOT MUST NOT
+\anchor SHALLNOT
+   This phrase, or the phrase "SHALL NOT", mean that the
+   definition is an absolute prohibition of the specification.
+
+\section SHOULD
+\anchor RECOMMENDED
+   This word, or the adjective "RECOMMENDED", mean that there
+   may exist valid reasons in particular circumstances to ignore a
+   particular item, but the full implications must be understood and
+   carefully weighed before choosing a different course.
+
+\section SHOULDNOT SHOULD NOT
+\anchor NOTRECOMMENDED
+   This phrase, or the phrase "NOT RECOMMENDED" mean that
+   there may exist valid reasons in particular circumstances when the
+   particular behavior is acceptable or even useful, but the full
+   implications should be understood and the case carefully weighed
+   before implementing any behavior described with this label.
+
+\section MAY
+\anchor OPTIONAL
+   This word, or the adjective "OPTIONAL", mean that an item is
+   truly optional.  One vendor may choose to include the item because a
+   particular marketplace requires it or because the vendor feels that
+   it enhances the product while another vendor may omit the same item.
+   An implementation which does not include a particular option \ref MUST be
+   prepared to interoperate with another implementation which does
+   include the option, though perhaps with reduced functionality. In the
+   same vein an implementation which does include a particular option
+   \ref MUST be prepared to interoperate with another implementation which
+   does not include the option (except, of course, for the feature the
+   option provides.)
+
+
+*/
diff --git a/libmkv/EbmlBufferWriter.c b/libmkv/EbmlBufferWriter.c
new file mode 100644 (file)
index 0000000..d9b04a8
--- /dev/null
@@ -0,0 +1,60 @@
+//#include <strmif.h>
+#include "EbmlBufferWriter.h"
+#include "EbmlWriter.h"
+//#include <cassert>
+//#include <limits>
+//#include <malloc.h>  //_alloca
+#include <stdlib.h>
+#include <wchar.h>
+#include <string.h>
+
+void Ebml_Write(EbmlGlobal *glob, const void *buffer_in, unsigned long len)
+{
+    unsigned char *src = glob->buf;
+    src += glob->offset;
+    memcpy(src, buffer_in, len);
+    glob->offset += len;
+}
+
+static void _Serialize(EbmlGlobal *glob, const unsigned char *p, const unsigned char *q)
+{
+    while (q != p)
+    {
+        --q;
+
+        unsigned long cbWritten;
+        memcpy(&(glob->buf[glob->offset]), q, 1);
+        glob->offset ++;
+    }
+}
+
+void Ebml_Serialize(EbmlGlobal *glob, const void *buffer_in, unsigned long len)
+{
+    //assert(buf);
+
+    const unsigned char *const p = (const unsigned char *)(buffer_in);
+    const unsigned char *const q = p + len;
+
+    _Serialize(glob, p, q);
+}
+
+
+void Ebml_StartSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc, unsigned long class_id)
+{
+    Ebml_WriteID(glob, class_id);
+    ebmlLoc->offset = glob->offset;
+    //todo this is always taking 8 bytes, this may need later optimization
+    unsigned long long unknownLen =  0x01FFFFFFFFFFFFFFLLU;
+    Ebml_Serialize(glob, (void *)&unknownLen, 8); //this is a key that says lenght unknown
+}
+
+void Ebml_EndSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc)
+{
+    unsigned long long size = glob->offset - ebmlLoc->offset - 8;
+    unsigned long long curOffset = glob->offset;
+    glob->offset = ebmlLoc->offset;
+    size |=  0x0100000000000000LLU;
+    Ebml_Serialize(glob, &size, 8);
+    glob->offset = curOffset;
+}
+
diff --git a/libmkv/EbmlBufferWriter.h b/libmkv/EbmlBufferWriter.h
new file mode 100644 (file)
index 0000000..ba0a9b3
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef EBMLBUFFERWRITER_HPP
+#define EBMLBUFFERWRITER_HPP
+
+typedef struct
+{
+    unsigned long long offset;
+} EbmlLoc;
+
+typedef struct
+{
+    unsigned char *buf;
+    unsigned int length;
+    unsigned int offset;
+} EbmlGlobal;
+
+
+void Ebml_StartSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc, unsigned long class_id);
+void Ebml_EndSubElement(EbmlGlobal *glob,  EbmlLoc *ebmlLoc);
+
+
+#endif
diff --git a/libmkv/EbmlIDs.h b/libmkv/EbmlIDs.h
new file mode 100644 (file)
index 0000000..3418e36
--- /dev/null
@@ -0,0 +1,231 @@
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS.  All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+
+#ifndef MKV_DEFS_HPP
+#define MKV_DEFS_HPP 1
+
+//Commenting out values not available in webm, but available in matroska
+
+enum mkv
+{
+    EBML = 0x1A45DFA3,
+    EBMLVersion = 0x4286,
+    EBMLReadVersion = 0x42F7,
+    EBMLMaxIDLength = 0x42F2,
+    EBMLMaxSizeLength = 0x42F3,
+    DocType = 0x4282,
+    DocTypeVersion = 0x4287,
+    DocTypeReadVersion = 0x4285,
+//  CRC_32 = 0xBF,
+    Void = 0xEC,
+    SignatureSlot = 0x1B538667,
+    SignatureAlgo = 0x7E8A,
+    SignatureHash = 0x7E9A,
+    SignaturePublicKey = 0x7EA5,
+    Signature = 0x7EB5,
+    SignatureElements = 0x7E5B,
+    SignatureElementList = 0x7E7B,
+    SignedElement = 0x6532,
+    //segment
+    Segment = 0x18538067,
+    //Meta Seek Information
+    SeekHead = 0x114D9B74,
+    Seek = 0x4DBB,
+    SeekID = 0x53AB,
+    SeekPosition = 0x53AC,
+    //Segment Information
+    Info = 0x1549A966,
+//  SegmentUID = 0x73A4,
+//  SegmentFilename = 0x7384,
+//  PrevUID = 0x3CB923,
+//  PrevFilename = 0x3C83AB,
+//  NextUID = 0x3EB923,
+//  NextFilename = 0x3E83BB,
+//  SegmentFamily = 0x4444,
+//  ChapterTranslate = 0x6924,
+//  ChapterTranslateEditionUID = 0x69FC,
+//  ChapterTranslateCodec = 0x69BF,
+//  ChapterTranslateID = 0x69A5,
+    TimecodeScale = 0x2AD7B1,
+    Segment_Duration = 0x4489,
+    DateUTC = 0x4461,
+//  Title = 0x7BA9,
+    MuxingApp = 0x4D80,
+    WritingApp = 0x5741,
+    //Cluster
+    Cluster = 0x1F43B675,
+    Timecode = 0xE7,
+//  SilentTracks = 0x5854,
+//  SilentTrackNumber = 0x58D7,
+//  Position = 0xA7,
+    PrevSize = 0xAB,
+    BlockGroup = 0xA0,
+    Block = 0xA1,
+//  BlockVirtual = 0xA2,
+//  BlockAdditions = 0x75A1,
+//  BlockMore = 0xA6,
+//  BlockAddID = 0xEE,
+//  BlockAdditional = 0xA5,
+    BlockDuration = 0x9B,
+//  ReferencePriority = 0xFA,
+    ReferenceBlock = 0xFB,
+//  ReferenceVirtual = 0xFD,
+//  CodecState = 0xA4,
+//  Slices = 0x8E,
+//  TimeSlice = 0xE8,
+    LaceNumber = 0xCC,
+//  FrameNumber = 0xCD,
+//  BlockAdditionID = 0xCB,
+//  MkvDelay = 0xCE,
+//  Cluster_Duration = 0xCF,
+    SimpleBlock = 0xA3,
+//  EncryptedBlock = 0xAF,
+    //Track
+    Tracks = 0x1654AE6B,
+    TrackEntry = 0xAE,
+    TrackNumber = 0xD7,
+    TrackUID = 0x73C5,
+    TrackType = 0x83,
+    FlagEnabled = 0xB9,
+    FlagDefault = 0x88,
+    FlagForced = 0x55AA,
+    FlagLacing = 0x9C,
+//  MinCache = 0x6DE7,
+//  MaxCache = 0x6DF8,
+    DefaultDuration = 0x23E383,
+//  TrackTimecodeScale = 0x23314F,
+//  TrackOffset = 0x537F,
+//  MaxBlockAdditionID = 0x55EE,
+    Name = 0x536E,
+    Language = 0x22B59C,
+    CodecID = 0x86,
+    CodecPrivate = 0x63A2,
+    CodecName = 0x258688,
+//  AttachmentLink = 0x7446,
+//  CodecSettings = 0x3A9697,
+//  CodecInfoURL = 0x3B4040,
+//  CodecDownloadURL = 0x26B240,
+//  CodecDecodeAll = 0xAA,
+//  TrackOverlay = 0x6FAB,
+//  TrackTranslate = 0x6624,
+//  TrackTranslateEditionUID = 0x66FC,
+//  TrackTranslateCodec = 0x66BF,
+//  TrackTranslateTrackID = 0x66A5,
+    //video
+    Video = 0xE0,
+    FlagInterlaced = 0x9A,
+    StereoMode = 0x53B8,
+    PixelWidth = 0xB0,
+    PixelHeight = 0xBA,
+    PixelCropBottom = 0x54AA,
+    PixelCropTop = 0x54BB,
+    PixelCropLeft = 0x54CC,
+    PixelCropRight = 0x54DD,
+    DisplayWidth = 0x54B0,
+    DisplayHeight = 0x54BA,
+    DisplayUnit = 0x54B2,
+    AspectRatioType = 0x54B3,
+//  ColourSpace = 0x2EB524,
+//  GammaValue = 0x2FB523,
+    FrameRate = 0x2383E3,
+    //end video
+    //audio
+    Audio = 0xE1,
+    SamplingFrequency = 0xB5,
+    OutputSamplingFrequency = 0x78B5,
+    Channels = 0x9F,
+//  ChannelPositions = 0x7D7B,
+    BitDepth = 0x6264,
+    //end audio
+    //content encoding
+//  ContentEncodings = 0x6d80,
+//  ContentEncoding = 0x6240,
+//  ContentEncodingOrder = 0x5031,
+//  ContentEncodingScope = 0x5032,
+//  ContentEncodingType = 0x5033,
+//  ContentCompression = 0x5034,
+//  ContentCompAlgo = 0x4254,
+//  ContentCompSettings = 0x4255,
+//  ContentEncryption = 0x5035,
+//  ContentEncAlgo = 0x47e1,
+//  ContentEncKeyID = 0x47e2,
+//  ContentSignature = 0x47e3,
+//  ContentSigKeyID = 0x47e4,
+//  ContentSigAlgo = 0x47e5,
+//  ContentSigHashAlgo = 0x47e6,
+    //end content encoding
+    //Cueing Data
+    Cues = 0x1C53BB6B,
+    CuePoint = 0xBB,
+    CueTime = 0xB3,
+    CueTrackPositions = 0xB7,
+    CueTrack = 0xF7,
+    CueClusterPosition = 0xF1,
+    CueBlockNumber = 0x5378,
+//  CueCodecState = 0xEA,
+//  CueReference = 0xDB,
+//  CueRefTime = 0x96,
+//  CueRefCluster = 0x97,
+//  CueRefNumber = 0x535F,
+//  CueRefCodecState = 0xEB,
+    //Attachment
+//  Attachments = 0x1941A469,
+//  AttachedFile = 0x61A7,
+//  FileDescription = 0x467E,
+//  FileName = 0x466E,
+//  FileMimeType = 0x4660,
+//  FileData = 0x465C,
+//  FileUID = 0x46AE,
+//  FileReferral = 0x4675,
+    //Chapters
+//  Chapters = 0x1043A770,
+//  EditionEntry = 0x45B9,
+//  EditionUID = 0x45BC,
+//  EditionFlagHidden = 0x45BD,
+//  EditionFlagDefault = 0x45DB,
+//  EditionFlagOrdered = 0x45DD,
+//  ChapterAtom = 0xB6,
+//  ChapterUID = 0x73C4,
+//  ChapterTimeStart = 0x91,
+//  ChapterTimeEnd = 0x92,
+//  ChapterFlagHidden = 0x98,
+//  ChapterFlagEnabled = 0x4598,
+//  ChapterSegmentUID = 0x6E67,
+//  ChapterSegmentEditionUID = 0x6EBC,
+//  ChapterPhysicalEquiv = 0x63C3,
+//  ChapterTrack = 0x8F,
+//  ChapterTrackNumber = 0x89,
+//  ChapterDisplay = 0x80,
+//  ChapString = 0x85,
+//  ChapLanguage = 0x437C,
+//  ChapCountry = 0x437E,
+//  ChapProcess = 0x6944,
+//  ChapProcessCodecID = 0x6955,
+//  ChapProcessPrivate = 0x450D,
+//  ChapProcessCommand = 0x6911,
+//  ChapProcessTime = 0x6922,
+//  ChapProcessData = 0x6933,
+    //Tagging
+//  Tags = 0x1254C367,
+//  Tag = 0x7373,
+//  Targets = 0x63C0,
+//  TargetTypeValue = 0x68CA,
+//  TargetType = 0x63CA,
+//  Tagging_TrackUID = 0x63C5,
+//  Tagging_EditionUID = 0x63C9,
+//  Tagging_ChapterUID = 0x63C4,
+//  AttachmentUID = 0x63C6,
+//  SimpleTag = 0x67C8,
+//  TagName = 0x45A3,
+//  TagLanguage = 0x447A,
+//  TagDefault = 0x4484,
+//  TagString = 0x4487,
+//  TagBinary = 0x4485,
+};
+#endif
diff --git a/libmkv/EbmlWriter.c b/libmkv/EbmlWriter.c
new file mode 100644 (file)
index 0000000..fbf2c66
--- /dev/null
@@ -0,0 +1,171 @@
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS.  All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+
+#include "EbmlWriter.h"
+#include <stdlib.h>
+#include <wchar.h>
+#include <string.h>
+#include <limits.h>
+#if defined(_MSC_VER)
+#define LITERALU64(n) n
+#else
+#define LITERALU64(n) n##LLU
+#endif
+
+void Ebml_WriteLen(EbmlGlobal *glob, long long val)
+{
+    //TODO check and make sure we are not > than 0x0100000000000000LLU
+    unsigned char size = 8; //size in bytes to output
+    unsigned long long minVal = LITERALU64(0x00000000000000ff); //mask to compare for byte size
+
+    for (size = 1; size < 8; size ++)
+    {
+        if (val < minVal)
+            break;
+
+        minVal = (minVal << 7);
+    }
+
+    val |= (LITERALU64(0x000000000000080) << ((size - 1) * 7));
+
+    Ebml_Serialize(glob, (void *) &val, sizeof(val), size);
+}
+
+void Ebml_WriteString(EbmlGlobal *glob, const char *str)
+{
+    const size_t size_ = strlen(str);
+    const unsigned long long  size = size_;
+    Ebml_WriteLen(glob, size);
+    //TODO: it's not clear from the spec whether the nul terminator
+    //should be serialized too.  For now we omit the null terminator.
+    Ebml_Write(glob, str, size);
+}
+
+void Ebml_WriteUTF8(EbmlGlobal *glob, const wchar_t *wstr)
+{
+    const size_t strlen = wcslen(wstr);
+
+    //TODO: it's not clear from the spec whether the nul terminator
+    //should be serialized too.  For now we include it.
+    const unsigned long long  size = strlen;
+
+    Ebml_WriteLen(glob, size);
+    Ebml_Write(glob, wstr, size);
+}
+
+void Ebml_WriteID(EbmlGlobal *glob, unsigned long class_id)
+{
+    int len;
+
+    if (class_id >= 0x01000000)
+        len = 4;
+    else if (class_id >= 0x00010000)
+        len = 3;
+    else if (class_id >= 0x00000100)
+        len = 2;
+    else
+        len = 1;
+
+    Ebml_Serialize(glob, (void *)&class_id, sizeof(class_id), len);
+}
+
+void Ebml_SerializeUnsigned64(EbmlGlobal *glob, unsigned long class_id, uint64_t ui)
+{
+    unsigned char sizeSerialized = 8 | 0x80;
+    Ebml_WriteID(glob, class_id);
+    Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
+    Ebml_Serialize(glob, &ui, sizeof(ui), 8);
+}
+
+void Ebml_SerializeUnsigned(EbmlGlobal *glob, unsigned long class_id, unsigned long ui)
+{
+    unsigned char size = 8; //size in bytes to output
+    unsigned char sizeSerialized = 0;
+    unsigned long minVal;
+
+    Ebml_WriteID(glob, class_id);
+    minVal = 0x7fLU; //mask to compare for byte size
+
+    for (size = 1; size < 4; size ++)
+    {
+        if (ui < minVal)
+        {
+            break;
+        }
+
+        minVal <<= 7;
+    }
+
+    sizeSerialized = 0x80 | size;
+    Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
+    Ebml_Serialize(glob, &ui, sizeof(ui), size);
+}
+//TODO: perhaps this is a poor name for this id serializer helper function
+void Ebml_SerializeBinary(EbmlGlobal *glob, unsigned long class_id, unsigned long bin)
+{
+    int size;
+    for (size=4; size > 1; size--)
+    {
+        if (bin & 0x000000ff << ((size-1) * 8))
+            break;
+    }
+    Ebml_WriteID(glob, class_id);
+    Ebml_WriteLen(glob, size);
+    Ebml_WriteID(glob, bin);
+}
+
+void Ebml_SerializeFloat(EbmlGlobal *glob, unsigned long class_id, double d)
+{
+    unsigned char len = 0x88;
+
+    Ebml_WriteID(glob, class_id);
+    Ebml_Serialize(glob, &len, sizeof(len), 1);
+    Ebml_Serialize(glob,  &d, sizeof(d), 8);
+}
+
+void Ebml_WriteSigned16(EbmlGlobal *glob, short val)
+{
+    signed long out = ((val & 0x003FFFFF) | 0x00200000) << 8;
+    Ebml_Serialize(glob, &out, sizeof(out), 3);
+}
+
+void Ebml_SerializeString(EbmlGlobal *glob, unsigned long class_id, const char *s)
+{
+    Ebml_WriteID(glob, class_id);
+    Ebml_WriteString(glob, s);
+}
+
+void Ebml_SerializeUTF8(EbmlGlobal *glob, unsigned long class_id, wchar_t *s)
+{
+    Ebml_WriteID(glob,  class_id);
+    Ebml_WriteUTF8(glob,  s);
+}
+
+void Ebml_SerializeData(EbmlGlobal *glob, unsigned long class_id, unsigned char *data, unsigned long data_length)
+{
+    Ebml_WriteID(glob, class_id);
+    Ebml_WriteLen(glob, data_length);
+    Ebml_Write(glob,  data, data_length);
+}
+
+void Ebml_WriteVoid(EbmlGlobal *glob, unsigned long vSize)
+{
+    unsigned char tmp = 0;
+    unsigned long i = 0;
+
+    Ebml_WriteID(glob, 0xEC);
+    Ebml_WriteLen(glob, vSize);
+
+    for (i = 0; i < vSize; i++)
+    {
+        Ebml_Write(glob, &tmp, 1);
+    }
+}
+
+//TODO Serialize Date
diff --git a/libmkv/EbmlWriter.h b/libmkv/EbmlWriter.h
new file mode 100644 (file)
index 0000000..324c9bc
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef EBMLWRITER_HPP
+#define EBMLWRITER_HPP
+
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS.  All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+//note: you must define write and serialize functions as well as your own EBML_GLOBAL
+//These functions MUST be implemented
+#include <stddef.h>
+#include "vpx/vpx_integer.h"
+
+typedef struct EbmlGlobal EbmlGlobal;
+void  Ebml_Serialize(EbmlGlobal *glob, const void *, int, unsigned long);
+void  Ebml_Write(EbmlGlobal *glob, const void *, unsigned long);
+/////
+
+
+void Ebml_WriteLen(EbmlGlobal *glob, long long val);
+void Ebml_WriteString(EbmlGlobal *glob, const char *str);
+void Ebml_WriteUTF8(EbmlGlobal *glob, const wchar_t *wstr);
+void Ebml_WriteID(EbmlGlobal *glob, unsigned long class_id);
+void Ebml_SerializeUnsigned64(EbmlGlobal *glob, unsigned long class_id, uint64_t ui);
+void Ebml_SerializeUnsigned(EbmlGlobal *glob, unsigned long class_id, unsigned long ui);
+void Ebml_SerializeBinary(EbmlGlobal *glob, unsigned long class_id, unsigned long ui);
+void Ebml_SerializeFloat(EbmlGlobal *glob, unsigned long class_id, double d);
+//TODO make this more generic to signed
+void Ebml_WriteSigned16(EbmlGlobal *glob, short val);
+void Ebml_SerializeString(EbmlGlobal *glob, unsigned long class_id, const char *s);
+void Ebml_SerializeUTF8(EbmlGlobal *glob, unsigned long class_id, wchar_t *s);
+void Ebml_SerializeData(EbmlGlobal *glob, unsigned long class_id, unsigned char *data, unsigned long data_length);
+void Ebml_WriteVoid(EbmlGlobal *glob, unsigned long vSize);
+//TODO need date function
+#endif
diff --git a/libmkv/Makefile b/libmkv/Makefile
new file mode 100644 (file)
index 0000000..b53377b
--- /dev/null
@@ -0,0 +1,25 @@
+#Variables
+CC=gcc
+LINKER=gcc
+FLAGS=
+
+
+#Build Targets
+EbmlWriter.o: EbmlWriter.c EbmlWriter.h
+       $(CC) $(FLAGS) -c EbmlWriter.c
+
+EbmlBufferWriter.o: EbmlBufferWriter.c EbmlBufferWriter.h
+       $(CC) $(FLAGS) -c EbmlBufferWriter.c
+       
+MkvElement.o: MkvElement.c WebMElement.h
+       $(CC) $(FLAGS) -c MkvElement.c
+       
+testlibmkv.o: testlibmkv.c
+       $(CC) $(FLAGS) -c testlibmkv.c
+       
+testlibmkv: testlibmkv.o MkvElement.o EbmlBufferWriter.o EbmlWriter.o
+       $(LINKER) $(FLAGS) testlibmkv.o MkvElement.o EbmlBufferWriter.o EbmlWriter.o -o testlibmkv
+
+clean:
+       rm -rf *.o testlibmkv
+       
\ No newline at end of file
diff --git a/libmkv/WebMElement.c b/libmkv/WebMElement.c
new file mode 100644 (file)
index 0000000..0ef5100
--- /dev/null
@@ -0,0 +1,220 @@
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS.  All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+
+#include "EbmlBufferWriter.h"
+#include "EbmlIDs.h"
+#include "WebMElement.h"
+#include <stdio.h>
+
+#define kVorbisPrivateMaxSize  4000
+
+void writeHeader(EbmlGlobal *glob)
+{
+    EbmlLoc start;
+    Ebml_StartSubElement(glob, &start, EBML);
+    Ebml_SerializeUnsigned(glob, EBMLVersion, 1);
+    Ebml_SerializeUnsigned(glob, EBMLReadVersion, 1); //EBML Read Version
+    Ebml_SerializeUnsigned(glob, EBMLMaxIDLength, 4); //EBML Max ID Length
+    Ebml_SerializeUnsigned(glob, EBMLMaxSizeLength, 8); //EBML Max Size Length
+    Ebml_SerializeString(glob, DocType, "webm"); //Doc Type
+    Ebml_SerializeUnsigned(glob, DocTypeVersion, 2); //Doc Type Version
+    Ebml_SerializeUnsigned(glob, DocTypeReadVersion, 2); //Doc Type Read Version
+    Ebml_EndSubElement(glob, &start);
+}
+
+void writeSimpleBlock(EbmlGlobal *glob, unsigned char trackNumber, short timeCode,
+                      int isKeyframe, unsigned char lacingFlag, int discardable,
+                      unsigned char *data, unsigned long dataLength)
+{
+    Ebml_WriteID(glob, SimpleBlock);
+    unsigned long blockLength = 4 + dataLength;
+    blockLength |= 0x10000000; //TODO check length < 0x0FFFFFFFF
+    Ebml_Serialize(glob, &blockLength, sizeof(blockLength), 4);
+    trackNumber |= 0x80;  //TODO check track nubmer < 128
+    Ebml_Write(glob, &trackNumber, 1);
+    //Ebml_WriteSigned16(glob, timeCode,2); //this is 3 bytes
+    Ebml_Serialize(glob, &timeCode, sizeof(timeCode), 2);
+    unsigned char flags = 0x00 | (isKeyframe ? 0x80 : 0x00) | (lacingFlag << 1) | discardable;
+    Ebml_Write(glob, &flags, 1);
+    Ebml_Write(glob, data, dataLength);
+}
+
+static UInt64 generateTrackID(unsigned int trackNumber)
+{
+    UInt64 t = time(NULL) * trackNumber;
+    UInt64 r = rand();
+    r = r << 32;
+    r +=  rand();
+    UInt64 rval = t ^ r;
+    return rval;
+}
+
+void writeVideoTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
+                     char *codecId, unsigned int pixelWidth, unsigned int pixelHeight,
+                     double frameRate)
+{
+    EbmlLoc start;
+    Ebml_StartSubElement(glob, &start, TrackEntry);
+    Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
+    UInt64 trackID = generateTrackID(trackNumber);
+    Ebml_SerializeUnsigned(glob, TrackUID, trackID);
+    Ebml_SerializeString(glob, CodecName, "VP8");  //TODO shouldn't be fixed
+
+    Ebml_SerializeUnsigned(glob, TrackType, 1); //video is always 1
+    Ebml_SerializeString(glob, CodecID, codecId);
+    {
+        EbmlLoc videoStart;
+        Ebml_StartSubElement(glob, &videoStart, Video);
+        Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth);
+        Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight);
+        Ebml_SerializeFloat(glob, FrameRate, frameRate);
+        Ebml_EndSubElement(glob, &videoStart); //Video
+    }
+    Ebml_EndSubElement(glob, &start); //Track Entry
+}
+void writeAudioTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
+                     char *codecId, double samplingFrequency, unsigned int channels,
+                     unsigned char *private, unsigned long privateSize)
+{
+    EbmlLoc start;
+    Ebml_StartSubElement(glob, &start, TrackEntry);
+    Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
+    UInt64 trackID = generateTrackID(trackNumber);
+    Ebml_SerializeUnsigned(glob, TrackUID, trackID);
+    Ebml_SerializeUnsigned(glob, TrackType, 2); //audio is always 2
+    //I am using defaults for thesed required fields
+    /*  Ebml_SerializeUnsigned(glob, FlagEnabled, 1);
+        Ebml_SerializeUnsigned(glob, FlagDefault, 1);
+        Ebml_SerializeUnsigned(glob, FlagForced, 1);
+        Ebml_SerializeUnsigned(glob, FlagLacing, flagLacing);*/
+    Ebml_SerializeString(glob, CodecID, codecId);
+    Ebml_SerializeData(glob, CodecPrivate, private, privateSize);
+
+    Ebml_SerializeString(glob, CodecName, "VORBIS");  //fixed for now
+    {
+        EbmlLoc AudioStart;
+        Ebml_StartSubElement(glob, &AudioStart, Audio);
+        Ebml_SerializeFloat(glob, SamplingFrequency, samplingFrequency);
+        Ebml_SerializeUnsigned(glob, Channels, channels);
+        Ebml_EndSubElement(glob, &AudioStart);
+    }
+    Ebml_EndSubElement(glob, &start);
+}
+void writeSegmentInformation(EbmlGlobal *ebml, EbmlLoc* startInfo, unsigned long timeCodeScale, double duration)
+{
+    Ebml_StartSubElement(ebml, startInfo, Info);
+    Ebml_SerializeUnsigned(ebml, TimecodeScale, timeCodeScale);
+    Ebml_SerializeFloat(ebml, Segment_Duration, duration * 1000.0); //Currently fixed to using milliseconds
+    Ebml_SerializeString(ebml, 0x4D80, "QTmuxingAppLibWebM-0.0.1");
+    Ebml_SerializeString(ebml, 0x5741, "QTwritingAppLibWebM-0.0.1");
+    Ebml_EndSubElement(ebml, startInfo);
+}
+
+/*
+void Mkv_InitializeSegment(Ebml& ebml_out, EbmlLoc& ebmlLoc)
+{
+    Ebml_StartSubElement(ebml_out, ebmlLoc, 0x18538067);
+}
+
+void Mkv_InitializeSeek(Ebml& ebml_out, EbmlLoc& ebmlLoc)
+{
+    Ebml_StartSubElement(ebml_out, ebmlLoc, 0x114d9b74);
+}
+void Mkv_WriteSeekInformation(Ebml& ebml_out, SeekStruct& seekInformation)
+{
+    EbmlLoc ebmlLoc;
+    Ebml_StartSubElement(ebml_out, ebmlLoc, 0x4dbb);
+    Ebml_SerializeString(ebml_out, 0x53ab, seekInformation.SeekID);
+    Ebml_SerializeUnsigned(ebml_out, 0x53ac, seekInformation.SeekPosition);
+    Ebml_EndSubElement(ebml_out, ebmlLoc);
+}
+
+void Mkv_WriteSegmentInformation(Ebml& ebml_out, SegmentInformationStruct& segmentInformation)
+{
+    Ebml_SerializeUnsigned(ebml_out, 0x73a4, segmentInformation.segmentUID);
+    if (segmentInformation.filename != 0)
+        Ebml_SerializeString(ebml_out, 0x7384, segmentInformation.filename);
+    Ebml_SerializeUnsigned(ebml_out, 0x2AD7B1, segmentInformation.TimecodeScale);
+    Ebml_SerializeUnsigned(ebml_out, 0x4489, segmentInformation.Duration);
+    //TODO date
+    Ebml_SerializeWString(ebml_out, 0x4D80, L"MKVMUX");
+    Ebml_SerializeWString(ebml_out, 0x5741, segmentInformation.WritingApp);
+}
+
+void Mkv_InitializeTrack(Ebml& ebml_out, EbmlLoc& ebmlLoc)
+{
+    Ebml_StartSubElement(ebml_out, ebmlLoc, 0x1654AE6B);
+}
+
+static void Mkv_WriteGenericTrackData(Ebml& ebml_out, TrackStruct& track)
+{
+    Ebml_SerializeUnsigned(ebml_out, 0xD7, track.TrackNumber);
+    Ebml_SerializeUnsigned(ebml_out, 0x73C5, track.TrackUID);
+    Ebml_SerializeUnsigned(ebml_out, 0x83, track.TrackType);
+    Ebml_SerializeUnsigned(ebml_out, 0xB9, track.FlagEnabled ? 1 :0);
+    Ebml_SerializeUnsigned(ebml_out, 0x88, track.FlagDefault ? 1 :0);
+    Ebml_SerializeUnsigned(ebml_out, 0x55AA, track.FlagForced ? 1 :0);
+    if (track.Language != 0)
+        Ebml_SerializeString(ebml_out, 0x22B59C, track.Language);
+    if (track.CodecID != 0)
+        Ebml_SerializeString(ebml_out, 0x86, track.CodecID);
+    if (track.CodecPrivate != 0)
+        Ebml_SerializeData(ebml_out, 0x63A2, track.CodecPrivate, track.CodecPrivateLength);
+    if (track.CodecName != 0)
+        Ebml_SerializeWString(ebml_out, 0x258688, track.CodecName);
+}
+
+void Mkv_WriteVideoTrack(Ebml& ebml_out, TrackStruct & track, VideoTrackStruct& video)
+{
+    EbmlLoc trackHeadLoc, videoHeadLoc;
+    Ebml_StartSubElement(ebml_out, trackHeadLoc, 0xAE);  //start Track
+    Mkv_WriteGenericTrackData(ebml_out, track);
+    Ebml_StartSubElement(ebml_out, videoHeadLoc, 0xE0);  //start Video
+    Ebml_SerializeUnsigned(ebml_out, 0x9A, video.FlagInterlaced ? 1 :0);
+    Ebml_SerializeUnsigned(ebml_out, 0xB0, video.PixelWidth);
+    Ebml_SerializeUnsigned(ebml_out, 0xBA, video.PixelHeight);
+    Ebml_SerializeUnsigned(ebml_out, 0x54B0, video.PixelDisplayWidth);
+    Ebml_SerializeUnsigned(ebml_out, 0x54BA, video.PixelDisplayHeight);
+    Ebml_SerializeUnsigned(ebml_out, 0x54B2, video.displayUnit);
+    Ebml_SerializeFloat(ebml_out, 0x2383E3, video.FrameRate);
+    Ebml_EndSubElement(ebml_out, videoHeadLoc);
+    Ebml_EndSubElement(ebml_out, trackHeadLoc);
+
+}
+
+void Mkv_WriteAudioTrack(Ebml& ebml_out, TrackStruct & track, AudioTrackStruct& video)
+{
+    EbmlLoc trackHeadLoc, audioHeadLoc;
+    Ebml_StartSubElement(ebml_out, trackHeadLoc, 0xAE);
+    Mkv_WriteGenericTrackData(ebml_out, track);
+    Ebml_StartSubElement(ebml_out, audioHeadLoc, 0xE0);  //start Audio
+    Ebml_SerializeFloat(ebml_out, 0xB5, video.SamplingFrequency);
+    Ebml_SerializeUnsigned(ebml_out, 0x9F, video.Channels);
+    Ebml_SerializeUnsigned(ebml_out, 0x6264, video.BitDepth);
+    Ebml_EndSubElement(ebml_out, audioHeadLoc); // end audio
+    Ebml_EndSubElement(ebml_out, trackHeadLoc);
+}
+
+void Mkv_WriteEbmlClusterHead(Ebml& ebml_out,  EbmlLoc& ebmlLoc, ClusterHeadStruct & clusterHead)
+{
+    Ebml_StartSubElement(ebml_out, ebmlLoc, 0x1F43B675);
+    Ebml_SerializeUnsigned(ebml_out, 0x6264, clusterHead.TimeCode);
+}
+
+void Mkv_WriteSimpleBlockHead(Ebml& ebml_out,  EbmlLoc& ebmlLoc, SimpleBlockStruct& block)
+{
+    Ebml_StartSubElement(ebml_out, ebmlLoc, 0xA3);
+    Ebml_Write1UInt(ebml_out, block.TrackNumber);
+    Ebml_WriteSigned16(ebml_out,block.TimeCode);
+    unsigned char flags = 0x00 | (block.iskey ? 0x80:0x00) | (block.lacing << 1) | block.discardable;
+    Ebml_Write1UInt(ebml_out, flags);  //TODO this may be the wrong function
+    Ebml_Serialize(ebml_out, block.data, block.dataLength);
+    Ebml_EndSubElement(ebml_out,ebmlLoc);
+}
+*/
diff --git a/libmkv/WebMElement.h b/libmkv/WebMElement.h
new file mode 100644 (file)
index 0000000..b4208f2
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS.  All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+
+#ifndef MKV_CONTEXT_HPP
+#define MKV_CONTEXT_HPP 1
+
+void writeSimpleBock(EbmlGlobal *ebml, unsigned char trackNumber, unsigned short timeCode,
+                     int isKeyframe, unsigned char lacingFlag, int  discardable,
+                     unsigned char *data, unsigned long dataLength);
+
+
+// these are helper functions
+void writeHeader(EbmlGlobal *ebml);
+void writeSegmentInformation(EbmlGlobal *ebml, EbmlLoc* startInfo , unsigned long timeCodeScale, double duration);
+//this function is a helper only, it assumes a lot of defaults
+void writeVideoTrack(EbmlGlobal *ebml, unsigned int trackNumber, int flagLacing,
+                     char *codecId, unsigned int pixelWidth, unsigned int pixelHeight,
+                     double frameRate);
+void writeAudioTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
+                     char *codecId, double samplingFrequency, unsigned int channels,
+                     unsigned char *private, unsigned long privateSize);
+
+void writeSimpleBlock(EbmlGlobal *ebml, unsigned char trackNumber, short timeCode,
+                      int isKeyframe, unsigned char lacingFlag, int discardable,
+                      unsigned char *data, unsigned long dataLength);
+
+
+
+#endif
\ No newline at end of file
diff --git a/libmkv/testlibmkv.c b/libmkv/testlibmkv.c
new file mode 100644 (file)
index 0000000..7edfc43
--- /dev/null
@@ -0,0 +1,63 @@
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS.  All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+
+
+#include "EbmlIDs.h"
+#include "EbmlBufferWriter.h"
+#include "WebMElement.h"
+
+#include <stdio.h>
+int main(int argc, char *argv[])
+{
+    //init the datatype we're using for ebml output
+    unsigned char data[8192];
+    EbmlGlobal ebml;
+    ebml.buf = data;
+    ebml.offset = 0;
+    ebml.length = 8192;
+
+    writeHeader(&ebml);
+    {
+        EbmlLoc startSegment;
+        Ebml_StartSubElement(&ebml, &startSegment, Segment); //segment
+        {
+            //segment info
+            EbmlLoc startInfo;
+            Ebml_StartSubElement(&ebml, &startInfo, Info);
+            Ebml_SerializeString(&ebml, 0x4D80, "muxingAppLibMkv");
+            Ebml_SerializeString(&ebml, 0x5741, "writingAppLibMkv");
+            Ebml_EndSubElement(&ebml, &startInfo);
+        }
+
+        {
+            EbmlLoc trackStart;
+            Ebml_StartSubElement(&ebml, &trackStart, Tracks);
+            writeVideoTrack(&ebml, 1, 1, "V_MS/VFW/FOURCC", 320, 240, 29.97);
+            //writeAudioTrack(&ebml,2,1, "A_VORBIS", 32000, 1, NULL, 0);
+            Ebml_EndSubElement(&ebml, &trackStart);
+        }
+
+        {
+            EbmlLoc clusterStart;
+            Ebml_StartSubElement(&ebml, &clusterStart, Cluster); //cluster
+            Ebml_SerializeUnsigned(&ebml, Timecode, 0);
+
+            unsigned char someData[4] = {1, 2, 3, 4};
+            writeSimpleBlock(&ebml, 1, 0, 1, 0, 0, someData, 4);
+            Ebml_EndSubElement(&ebml, &clusterStart);
+        }    //end cluster
+        Ebml_EndSubElement(&ebml, &startSegment);
+    }
+
+    //dump ebml stuff to the file
+    FILE *file_out = fopen("test.mkv", "wb");
+    size_t bytesWritten = fwrite(data, 1, ebml.offset, file_out);
+    fclose(file_out);
+    return 0;
+}
\ No newline at end of file
diff --git a/libs.doxy_template b/libs.doxy_template
new file mode 100644 (file)
index 0000000..02e2902
--- /dev/null
@@ -0,0 +1,1308 @@
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+
+# Doxyfile 1.5.4
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file that
+# follow. The default is UTF-8 which is also the encoding used for all text before
+# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into
+# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of
+# possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = "WebM VP8 Codec SDK"
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = docs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian,
+# Italian, Japanese, Japanese-en (Japanese with English messages), Korean,
+# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian,
+# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to java_doc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a java_doc-style
+# comment as the brief description. If set to NO, the java_doc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
+# include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the defqault) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct (or union) is
+# documented as struct with the name of the typedef. So
+# typedef struct type_s {} type_t, will appear in the documentation as a struct
+# with name type_t. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named type_s. This can typically
+# be useful for C code where the coding convention is that all structs are
+# typedef'ed and only the typedef is referenced never the struct's name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be extracted
+# and appear in the documentation as a namespace called 'anonymous_namespace{file}',
+# where file will be replaced with the base name of the file that contains the anonymous
+# namespace. By default anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS       = NO
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT =
+
+# This tag can be used to specify the character encoding of the source files that
+# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
+# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding.
+# See http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS          =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the output.
+# The symbol name can be a fully qualified name, a word, or if the wildcard * is used,
+# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.  Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.  The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH
+# then you must also enable this option. If you don't then doxygen will produce
+# a warning and turn it on anyway
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.  Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# java_script and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE               =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# java_script, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the la_te_x output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX         = YES
+
+# The LATEX_OUTPUT tag is used to specify where the la_te_x docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the la_te_x command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for la_te_x. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# la_te_x documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX          = YES
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = letter
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of la_te_x
+# packages that should be included in the la_te_x output.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal la_te_x header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           =
+
+# If the PDF_HYPERLINKS tag is set to YES, the la_te_x that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated la_te_x files. This will instruct la_te_x to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA             =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD                =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the auto_gen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an auto_gen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and la_te_x code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.  This is useful
+# if you want to understand what is going on.  On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS  = *.h
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED             =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#   TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#   TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and la_te_x) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to
+# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to
+# specify the directory where the mscgen tool resides. If left empty the tool is assumed to
+# be found in the default search path.
+
+MSCGEN_PATH            =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will
+# generate a caller dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS           =
+
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the number
+# of direct children of the root node in a graph is already larger than
+# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT        = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
diff --git a/libs.mk b/libs.mk
new file mode 100644 (file)
index 0000000..e2ba737
--- /dev/null
+++ b/libs.mk
@@ -0,0 +1,437 @@
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+
+# ARM assembly files are written in RVCT-style. We use some make magic to
+# filter those files to allow GCC compilation
+ifeq ($(ARCH_ARM),yes)
+  ASM:=$(if $(filter yes,$(CONFIG_GCC)),.asm.s,.asm)
+else
+  ASM:=.asm
+endif
+
+CODEC_SRCS-yes += CHANGELOG
+CODEC_SRCS-yes += libs.mk
+
+include $(SRC_PATH_BARE)/vpx/vpx_codec.mk
+CODEC_SRCS-yes += $(addprefix vpx/,$(call enabled,API_SRCS))
+
+include $(SRC_PATH_BARE)/vpx_mem/vpx_mem.mk
+CODEC_SRCS-yes += $(addprefix vpx_mem/,$(call enabled,MEM_SRCS))
+
+include $(SRC_PATH_BARE)/vpx_scale/vpx_scale.mk
+CODEC_SRCS-yes += $(addprefix vpx_scale/,$(call enabled,SCALE_SRCS))
+
+
+ifeq ($(CONFIG_VP8_ENCODER),yes)
+  VP8_PREFIX=vp8/
+  include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8cx.mk
+  CODEC_SRCS-yes += $(addprefix $(VP8_PREFIX),$(call enabled,VP8_CX_SRCS))
+  CODEC_EXPORTS-yes += $(addprefix $(VP8_PREFIX),$(VP8_CX_EXPORTS))
+  CODEC_SRCS-yes += $(VP8_PREFIX)vp8cx.mk vpx/vp8.h vpx/vp8cx.h
+  CODEC_SRCS-$(ARCH_ARM) += $(VP8_PREFIX)vp8cx_arm.mk
+  INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8cx.h
+  INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP8_PREFIX)/%
+  CODEC_DOC_SRCS += vpx/vp8.h vpx/vp8cx.h
+  CODEC_DOC_SECTIONS += vp8 vp8_encoder
+endif
+
+ifeq ($(CONFIG_VP8_DECODER),yes)
+  VP8_PREFIX=vp8/
+  include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8dx.mk
+  CODEC_SRCS-yes += $(addprefix $(VP8_PREFIX),$(call enabled,VP8_DX_SRCS))
+  CODEC_EXPORTS-yes += $(addprefix $(VP8_PREFIX),$(VP8_DX_EXPORTS))
+  CODEC_SRCS-yes += $(VP8_PREFIX)vp8dx.mk vpx/vp8.h vpx/vp8dx.h
+  INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8dx.h
+  INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP8_PREFIX)/%
+  CODEC_DOC_SRCS += vpx/vp8.h vpx/vp8dx.h
+  CODEC_DOC_SECTIONS += vp8 vp8_decoder
+endif
+
+
+ifeq ($(CONFIG_ENCODERS),yes)
+  CODEC_DOC_SECTIONS += encoder
+endif
+ifeq ($(CONFIG_DECODERS),yes)
+  CODEC_DOC_SECTIONS += decoder
+endif
+
+
+ifeq ($(CONFIG_MSVS),yes)
+CODEC_LIB=$(if $(CONFIG_STATIC_MSVCRT),vpxmt,vpxmd)
+# This variable uses deferred expansion intentionally, since the results of
+# $(wildcard) may change during the course of the Make.
+VS_PLATFORMS = $(foreach d,$(wildcard */Release/$(CODEC_LIB).lib),$(word 1,$(subst /, ,$(d))))
+endif
+
+# The following pairs define a mapping of locations in the distribution
+# tree to locations in the source/build trees.
+INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/vpx/%
+INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/vpx_ports/%
+INSTALL_MAPS += $(LIBSUBDIR)/%     %
+INSTALL_MAPS += src/%     $(SRC_PATH_BARE)/%
+ifeq ($(CONFIG_MSVS),yes)
+INSTALL_MAPS += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/%  $(p)/Release/%)
+INSTALL_MAPS += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/%  $(p)/Debug/%)
+endif
+
+# If this is a universal (fat) binary, then all the subarchitectures have
+# already been built and our job is to stitch them together. The
+# BUILD_LIBVPX variable indicates whether we should be building
+# (compiling, linking) the library. The LIPO_LIBVPX variable indicates
+# that we're stitching.
+$(eval $(if $(filter universal%,$(TOOLCHAIN)),LIPO_LIBVPX,BUILD_LIBVPX):=yes)
+
+CODEC_SRCS-$(BUILD_LIBVPX) += build/make/version.sh
+CODEC_SRCS-$(BUILD_LIBVPX) += build/make/rtcd.sh
+CODEC_SRCS-$(BUILD_LIBVPX) += vpx/vpx_integer.h
+CODEC_SRCS-$(BUILD_LIBVPX) += vpx_ports/asm_offsets.h
+CODEC_SRCS-$(BUILD_LIBVPX) += vpx_ports/vpx_timer.h
+CODEC_SRCS-$(BUILD_LIBVPX) += vpx_ports/mem.h
+CODEC_SRCS-$(BUILD_LIBVPX) += $(BUILD_PFX)vpx_config.c
+INSTALL-SRCS-no += $(BUILD_PFX)vpx_config.c
+ifeq ($(ARCH_X86)$(ARCH_X86_64),yes)
+CODEC_SRCS-$(BUILD_LIBVPX) += vpx_ports/emms.asm
+CODEC_SRCS-$(BUILD_LIBVPX) += vpx_ports/x86.h
+CODEC_SRCS-$(BUILD_LIBVPX) += vpx_ports/x86_abi_support.asm
+CODEC_SRCS-$(BUILD_LIBVPX) += vpx_ports/x86_cpuid.c
+endif
+CODEC_SRCS-$(ARCH_ARM) += vpx_ports/arm_cpudetect.c
+CODEC_SRCS-$(ARCH_ARM) += vpx_ports/arm.h
+CODEC_EXPORTS-$(BUILD_LIBVPX) += vpx/exports_com
+CODEC_EXPORTS-$(CONFIG_ENCODERS) += vpx/exports_enc
+CODEC_EXPORTS-$(CONFIG_DECODERS) += vpx/exports_dec
+
+INSTALL-LIBS-yes += include/vpx/vpx_codec.h
+INSTALL-LIBS-yes += include/vpx/vpx_image.h
+INSTALL-LIBS-yes += include/vpx/vpx_integer.h
+INSTALL-LIBS-yes += include/vpx/vpx_codec_impl_top.h
+INSTALL-LIBS-yes += include/vpx/vpx_codec_impl_bottom.h
+INSTALL-LIBS-$(CONFIG_DECODERS) += include/vpx/vpx_decoder.h
+INSTALL-LIBS-$(CONFIG_ENCODERS) += include/vpx/vpx_encoder.h
+ifeq ($(CONFIG_EXTERNAL_BUILD),yes)
+ifeq ($(CONFIG_MSVS),yes)
+INSTALL-LIBS-yes                  += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/$(CODEC_LIB).lib)
+INSTALL-LIBS-$(CONFIG_DEBUG_LIBS) += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/$(CODEC_LIB)d.lib)
+INSTALL-LIBS-$(CONFIG_SHARED) += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/vpx.dll)
+INSTALL-LIBS-$(CONFIG_SHARED) += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/vpx.exp)
+endif
+else
+INSTALL-LIBS-$(CONFIG_STATIC) += $(LIBSUBDIR)/libvpx.a
+INSTALL-LIBS-$(CONFIG_DEBUG_LIBS) += $(LIBSUBDIR)/libvpx_g.a
+endif
+
+CODEC_SRCS=$(filter-out %_test.cc,$(call enabled,CODEC_SRCS))
+INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(CODEC_SRCS)
+INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(call enabled,CODEC_EXPORTS)
+
+
+# Generate a list of all enabled sources, in particular for exporting to gyp
+# based build systems.
+libvpx_srcs.txt:
+       @echo "    [CREATE] $@"
+       @echo $(CODEC_SRCS) | xargs -n1 echo | sort -u > $@
+
+
+ifeq ($(CONFIG_EXTERNAL_BUILD),yes)
+ifeq ($(CONFIG_MSVS),yes)
+
+obj_int_extract.vcproj: $(SRC_PATH_BARE)/build/make/obj_int_extract.c
+       @cp $(SRC_PATH_BARE)/build/x86-msvs/obj_int_extract.bat .
+       @echo "    [CREATE] $@"
+       $(SRC_PATH_BARE)/build/make/gen_msvs_proj.sh \
+    --exe \
+    --target=$(TOOLCHAIN) \
+    --name=obj_int_extract \
+    --ver=$(CONFIG_VS_VERSION) \
+    --proj-guid=E1360C65-D375-4335-8057-7ED99CC3F9B2 \
+    $(if $(CONFIG_STATIC_MSVCRT),--static-crt) \
+    --out=$@ $^ \
+    -I. \
+    -I"$(SRC_PATH_BARE)" \
+
+PROJECTS-$(BUILD_LIBVPX) += obj_int_extract.vcproj
+PROJECTS-$(BUILD_LIBVPX) += obj_int_extract.bat
+
+vpx.def: $(call enabled,CODEC_EXPORTS)
+       @echo "    [CREATE] $@"
+       $(SRC_PATH_BARE)/build/make/gen_msvs_def.sh\
+            --name=vpx\
+            --out=$@ $^
+CLEAN-OBJS += vpx.def
+
+vpx.vcproj: $(CODEC_SRCS) vpx.def
+       @echo "    [CREATE] $@"
+       $(SRC_PATH_BARE)/build/make/gen_msvs_proj.sh \
+                       --lib \
+                       --target=$(TOOLCHAIN) \
+            $(if $(CONFIG_STATIC_MSVCRT),--static-crt) \
+            --name=vpx \
+            --proj-guid=DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74 \
+            --module-def=vpx.def \
+            --ver=$(CONFIG_VS_VERSION) \
+            --out=$@ $(CFLAGS) $^ \
+            --src-path-bare="$(SRC_PATH_BARE)" \
+
+PROJECTS-$(BUILD_LIBVPX) += vpx.vcproj
+
+vpx.vcproj: vpx_config.asm
+vpx.vcproj: vpx_rtcd.h
+
+endif
+else
+LIBVPX_OBJS=$(call objs,$(CODEC_SRCS))
+OBJS-$(BUILD_LIBVPX) += $(LIBVPX_OBJS)
+LIBS-$(if $(BUILD_LIBVPX),$(CONFIG_STATIC)) += $(BUILD_PFX)libvpx.a $(BUILD_PFX)libvpx_g.a
+$(BUILD_PFX)libvpx_g.a: $(LIBVPX_OBJS)
+
+BUILD_LIBVPX_SO         := $(if $(BUILD_LIBVPX),$(CONFIG_SHARED))
+LIBVPX_SO               := libvpx.so.$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)
+LIBS-$(BUILD_LIBVPX_SO) += $(BUILD_PFX)$(LIBVPX_SO)\
+                           $(notdir $(LIBVPX_SO_SYMLINKS))
+$(BUILD_PFX)$(LIBVPX_SO): $(LIBVPX_OBJS) libvpx.ver
+$(BUILD_PFX)$(LIBVPX_SO): extralibs += -lm
+$(BUILD_PFX)$(LIBVPX_SO): SONAME = libvpx.so.$(VERSION_MAJOR)
+$(BUILD_PFX)$(LIBVPX_SO): SO_VERSION_SCRIPT = libvpx.ver
+LIBVPX_SO_SYMLINKS      := $(addprefix $(LIBSUBDIR)/, \
+                             libvpx.so libvpx.so.$(VERSION_MAJOR) \
+                             libvpx.so.$(VERSION_MAJOR).$(VERSION_MINOR))
+
+libvpx.ver: $(call enabled,CODEC_EXPORTS)
+       @echo "    [CREATE] $@"
+       $(qexec)echo "{ global:" > $@
+       $(qexec)for f in $?; do awk '{print $$2";"}' < $$f >>$@; done
+       $(qexec)echo "local: *; };" >> $@
+CLEAN-OBJS += libvpx.ver
+
+define libvpx_symlink_template
+$(1): $(2)
+       @echo "    [LN]      $$@"
+       $(qexec)ln -sf $(LIBVPX_SO) $$@
+endef
+
+$(eval $(call libvpx_symlink_template,\
+    $(addprefix $(BUILD_PFX),$(notdir $(LIBVPX_SO_SYMLINKS))),\
+    $(BUILD_PFX)$(LIBVPX_SO)))
+$(eval $(call libvpx_symlink_template,\
+    $(addprefix $(DIST_DIR)/,$(LIBVPX_SO_SYMLINKS)),\
+    $(DIST_DIR)/$(LIBSUBDIR)/$(LIBVPX_SO)))
+
+INSTALL-LIBS-$(CONFIG_SHARED) += $(LIBVPX_SO_SYMLINKS)
+INSTALL-LIBS-$(CONFIG_SHARED) += $(LIBSUBDIR)/$(LIBVPX_SO)
+
+LIBS-$(BUILD_LIBVPX) += vpx.pc
+vpx.pc: config.mk libs.mk
+       @echo "    [CREATE] $@"
+       $(qexec)echo '# pkg-config file from libvpx $(VERSION_STRING)' > $@
+       $(qexec)echo 'prefix=$(PREFIX)' >> $@
+       $(qexec)echo 'exec_prefix=$${prefix}' >> $@
+       $(qexec)echo 'libdir=$${prefix}/$(LIBSUBDIR)' >> $@
+       $(qexec)echo 'includedir=$${prefix}/include' >> $@
+       $(qexec)echo '' >> $@
+       $(qexec)echo 'Name: vpx' >> $@
+       $(qexec)echo 'Description: WebM Project VPx codec implementation' >> $@
+       $(qexec)echo 'Version: $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)' >> $@
+       $(qexec)echo 'Requires:' >> $@
+       $(qexec)echo 'Conflicts:' >> $@
+       $(qexec)echo 'Libs: -L$${libdir} -lvpx' >> $@
+       $(qexec)echo 'Cflags: -I$${includedir}' >> $@
+INSTALL-LIBS-yes += $(LIBSUBDIR)/pkgconfig/vpx.pc
+INSTALL_MAPS += $(LIBSUBDIR)/pkgconfig/%.pc %.pc
+CLEAN-OBJS += vpx.pc
+endif
+
+LIBS-$(LIPO_LIBVPX) += libvpx.a
+$(eval $(if $(LIPO_LIBVPX),$(call lipo_lib_template,libvpx.a)))
+
+#
+# Rule to make assembler configuration file from C configuration file
+#
+ifeq ($(ARCH_X86)$(ARCH_X86_64),yes)
+# YASM
+$(BUILD_PFX)vpx_config.asm: $(BUILD_PFX)vpx_config.h
+       @echo "    [CREATE] $@"
+       @egrep "#define [A-Z0-9_]+ [01]" $< \
+           | awk '{print $$2 " equ " $$3}' > $@
+else
+ADS2GAS=$(if $(filter yes,$(CONFIG_GCC)),| $(ASM_CONVERSION))
+$(BUILD_PFX)vpx_config.asm: $(BUILD_PFX)vpx_config.h
+       @echo "    [CREATE] $@"
+       @egrep "#define [A-Z0-9_]+ [01]" $< \
+           | awk '{print $$2 " EQU " $$3}' $(ADS2GAS) > $@
+       @echo "        END" $(ADS2GAS) >> $@
+CLEAN-OBJS += $(BUILD_PFX)vpx_config.asm
+endif
+
+#
+# Add assembler dependencies for configuration and offsets
+#
+$(filter %.s.o,$(OBJS-yes)):     $(BUILD_PFX)vpx_config.asm
+$(filter %$(ASM).o,$(OBJS-yes)): $(BUILD_PFX)vpx_config.asm
+
+#
+# Calculate platform- and compiler-specific offsets for hand coded assembly
+#
+
+OFFSET_PATTERN:='^[a-zA-Z0-9_]* EQU'
+
+ifeq ($(filter icc gcc,$(TGT_CC)), $(TGT_CC))
+    $(BUILD_PFX)asm_com_offsets.asm: $(BUILD_PFX)$(VP8_PREFIX)common/asm_com_offsets.c.S
+       LC_ALL=C grep $(OFFSET_PATTERN) $< | tr -d '$$\#' $(ADS2GAS) > $@
+    $(BUILD_PFX)$(VP8_PREFIX)common/asm_com_offsets.c.S: $(VP8_PREFIX)common/asm_com_offsets.c
+    CLEAN-OBJS += $(BUILD_PFX)asm_com_offsets.asm $(BUILD_PFX)$(VP8_PREFIX)common/asm_com_offsets.c.S
+
+    $(BUILD_PFX)asm_enc_offsets.asm: $(BUILD_PFX)$(VP8_PREFIX)encoder/asm_enc_offsets.c.S
+       LC_ALL=C grep $(OFFSET_PATTERN) $< | tr -d '$$\#' $(ADS2GAS) > $@
+    $(BUILD_PFX)$(VP8_PREFIX)encoder/asm_enc_offsets.c.S: $(VP8_PREFIX)encoder/asm_enc_offsets.c
+    CLEAN-OBJS += $(BUILD_PFX)asm_enc_offsets.asm $(BUILD_PFX)$(VP8_PREFIX)encoder/asm_enc_offsets.c.S
+
+    $(BUILD_PFX)asm_dec_offsets.asm: $(BUILD_PFX)$(VP8_PREFIX)decoder/asm_dec_offsets.c.S
+       LC_ALL=C grep $(OFFSET_PATTERN) $< | tr -d '$$\#' $(ADS2GAS) > $@
+    $(BUILD_PFX)$(VP8_PREFIX)decoder/asm_dec_offsets.c.S: $(VP8_PREFIX)decoder/asm_dec_offsets.c
+    CLEAN-OBJS += $(BUILD_PFX)asm_dec_offsets.asm $(BUILD_PFX)$(VP8_PREFIX)decoder/asm_dec_offsets.c.S
+else
+  ifeq ($(filter rvct,$(TGT_CC)), $(TGT_CC))
+    asm_com_offsets.asm: obj_int_extract
+    asm_com_offsets.asm: $(VP8_PREFIX)common/asm_com_offsets.c.o
+       ./obj_int_extract rvds $< $(ADS2GAS) > $@
+    OBJS-yes += $(VP8_PREFIX)common/asm_com_offsets.c.o
+    CLEAN-OBJS += asm_com_offsets.asm
+    $(filter %$(ASM).o,$(OBJS-yes)): $(BUILD_PFX)asm_com_offsets.asm
+
+    asm_enc_offsets.asm: obj_int_extract
+    asm_enc_offsets.asm: $(VP8_PREFIX)encoder/asm_enc_offsets.c.o
+       ./obj_int_extract rvds $< $(ADS2GAS) > $@
+    OBJS-yes += $(VP8_PREFIX)encoder/asm_enc_offsets.c.o
+    CLEAN-OBJS += asm_enc_offsets.asm
+    $(filter %$(ASM).o,$(OBJS-yes)): $(BUILD_PFX)asm_enc_offsets.asm
+
+    asm_dec_offsets.asm: obj_int_extract
+    asm_dec_offsets.asm: $(VP8_PREFIX)decoder/asm_dec_offsets.c.o
+       ./obj_int_extract rvds $< $(ADS2GAS) > $@
+    OBJS-yes += $(VP8_PREFIX)decoder/asm_dec_offsets.c.o
+    CLEAN-OBJS += asm_dec_offsets.asm
+    $(filter %$(ASM).o,$(OBJS-yes)): $(BUILD_PFX)asm_dec_offsets.asm
+  endif
+endif
+
+$(shell $(SRC_PATH_BARE)/build/make/version.sh "$(SRC_PATH_BARE)" $(BUILD_PFX)vpx_version.h)
+CLEAN-OBJS += $(BUILD_PFX)vpx_version.h
+
+#
+# Rule to generate runtime cpu detection files
+#
+$(OBJS-yes:.o=.d): $(BUILD_PFX)vpx_rtcd.h
+$(BUILD_PFX)vpx_rtcd.h: $(SRC_PATH_BARE)/$(sort $(filter %rtcd_defs.sh,$(CODEC_SRCS)))
+       @echo "    [CREATE] $@"
+       $(qexec)$(SRC_PATH_BARE)/build/make/rtcd.sh --arch=$(TGT_ISA) \
+          --sym=vpx_rtcd \
+          --config=$(target)$(if $(FAT_ARCHS),,-$(TOOLCHAIN)).mk \
+          $(RTCD_OPTIONS) $^ > $@
+CLEAN-OBJS += $(BUILD_PFX)vpx_rtcd.h
+
+CODEC_DOC_SRCS += vpx/vpx_codec.h \
+                  vpx/vpx_decoder.h \
+                  vpx/vpx_encoder.h \
+                  vpx/vpx_image.h
+
+##
+## libvpx test directives
+##
+
+ifeq ($(CONFIG_UNIT_TESTS),yes)
+ifeq ($(CONFIG_EXTERNAL_BUILD),yes)
+ifeq ($(CONFIG_MSVS),yes)
+
+LIBVPX_TEST_SRCS=$(filter %_test.cc,$(call enabled,CODEC_SRCS))
+LIBVPX_TEST_BINS=$(sort $(LIBVPX_TEST_SRCS:.cc.o=))
+
+gtest.vcproj: $(SRC_PATH_BARE)/third_party/googletest/src/src/gtest-all.cc
+       @echo "    [CREATE] $@"
+       $(SRC_PATH_BARE)/build/make/gen_msvs_proj.sh \
+            --lib \
+            --target=$(TOOLCHAIN) \
+            $(if $(CONFIG_STATIC_MSVCRT),--static-crt) \
+            --name=gtest \
+            --proj-guid=EC00E1EC-AF68-4D92-A255-181690D1C9B1 \
+            --ver=$(CONFIG_VS_VERSION) \
+            --src-path-bare="$(SRC_PATH_BARE)" \
+            --out=gtest.vcproj $(SRC_PATH_BARE)/third_party/googletest/src/src/gtest-all.cc \
+            -I. -I"$(SRC_PATH_BARE)/third_party/googletest/src/include" -I"$(SRC_PATH_BARE)/third_party/googletest/src"
+
+PROJECTS-$(CONFIG_MSVS) += gtest.vcproj
+
+define unit_test_vcproj_template
+$(notdir $(1:.cc=.vcproj)): $(SRC_PATH_BARE)/$(1)
+       @echo "    [vcproj] $$@"
+       $$(SRC_PATH_BARE)/build/make/gen_msvs_proj.sh\
+            --exe\
+            --target=$$(TOOLCHAIN)\
+            --name=$(notdir $(1:.cc=))\
+            --ver=$$(CONFIG_VS_VERSION)\
+            $$(if $$(CONFIG_STATIC_MSVCRT),--static-crt) \
+            --out=$$@ $$(INTERNAL_CFLAGS) $$(CFLAGS) \
+            -I. -I"$(SRC_PATH_BARE)/third_party/googletest/src/include" \
+            -L. -lvpxmt -lwinmm -lgtestmt $$^
+endef
+
+$(foreach proj,$(LIBVPX_TEST_BINS),\
+    $(eval $(call unit_test_vcproj_template,$(proj))))
+
+PROJECTS-$(CONFIG_MSVS) += $(foreach proj,$(LIBVPX_TEST_BINS),\
+     $(notdir $(proj:.cc=.vcproj)))
+
+test::
+       @set -e; for t in $(addprefix Win32/Release/,$(notdir $(LIBVPX_TEST_BINS:.cc=.exe))); do $$t; done
+endif
+else
+
+include $(SRC_PATH_BARE)/third_party/googletest/gtest.mk
+GTEST_SRCS := $(addprefix third_party/googletest/src/,$(call enabled,GTEST_SRCS))
+GTEST_OBJS=$(call objs,$(GTEST_SRCS))
+$(GTEST_OBJS) $(GTEST_OBJS:.o=.d): CFLAGS += -I$(SRC_PATH_BARE)/third_party/googletest/src
+$(GTEST_OBJS) $(GTEST_OBJS:.o=.d): CFLAGS += -I$(SRC_PATH_BARE)/third_party/googletest/src/include
+OBJS-$(BUILD_LIBVPX) += $(GTEST_OBJS)
+LIBS-$(BUILD_LIBVPX) += $(BUILD_PFX)libgtest.a $(BUILD_PFX)libgtest_g.a
+$(BUILD_PFX)libgtest_g.a: $(GTEST_OBJS)
+
+LIBVPX_TEST_SRCS=$(filter %_test.cc,$(call enabled,CODEC_SRCS))
+LIBVPX_TEST_OBJS=$(call objs,$(LIBVPX_TEST_SRCS))
+$(LIBVPX_TEST_OBJS) $(LIBVPX_TEST_OBJS:.o=.d): CFLAGS += -I$(SRC_PATH_BARE)/third_party/googletest/src
+$(LIBVPX_TEST_OBJS) $(LIBVPX_TEST_OBJS:.o=.d): CFLAGS += -I$(SRC_PATH_BARE)/third_party/googletest/src/include
+LIBVPX_TEST_BINS=$(sort $(LIBVPX_TEST_OBJS:.cc.o=))
+OBJS-$(BUILD_LIBVPX) += $(LIBVPX_TEST_OBJS)
+
+$(foreach bin,$(LIBVPX_TEST_BINS),\
+    $(if $(BUILD_LIBVPX),$(eval $(bin): libvpx.a libgtest.a ))\
+    $(if $(BUILD_LIBVPX),$(eval $(call linkerxx_template,$(bin),\
+        $(bin).cc.o \
+        -L. -lvpx -lgtest -lpthread -lm)\
+        )))\
+    $(if $(LIPO_LIBS),$(eval $(call lipo_bin_template,$(bin))))\
+
+test:: $(LIBVPX_TEST_BINS)
+       @set -e; for t in $(LIBVPX_TEST_BINS); do $$t; done
+
+endif
+endif
+
+##
+## documentation directives
+##
+CLEAN-OBJS += libs.doxy
+DOCS-yes += libs.doxy
+libs.doxy: $(CODEC_DOC_SRCS)
+       @echo "    [CREATE] $@"
+       @rm -f $@
+       @echo "INPUT += $^" >> $@
+       @echo "PREDEFINED = VPX_CODEC_DISABLE_COMPAT" >> $@
+       @echo "INCLUDE_PATH += ." >> $@;
+       @echo "ENABLED_SECTIONS += $(sort $(CODEC_DOC_SECTIONS))" >> $@
diff --git a/mainpage.dox b/mainpage.dox
new file mode 100644 (file)
index 0000000..e2ec280
--- /dev/null
@@ -0,0 +1,53 @@
+/*!\mainpage WebM VP8 Codec SDK
+
+  \section main_contents Page Contents
+  - \ref main_intro
+  - \ref main_startpoints
+  - \ref main_support
+
+  \section main_intro Introduction
+  Welcome to the WebM VP8 Codec SDK. This SDK allows you to integrate your
+  applications with the VP8 video codec, a high quality, royalty free, open
+  source codec deployed on millions of computers and devices worldwide.
+
+  This distribution of the WebM VP8 Codec SDK includes the following support:
+
+  \if vp8_encoder
+  - \ref vp8_encoder
+  \endif
+  \if vp8_decoder
+  - \ref vp8_decoder
+  \endif
+
+
+  \section main_startpoints Starting Points
+  - Consult the \ref changelog for a complete list of improvements in this
+    release.
+  - The \ref readme contains instructions on recompiling the sample applications.
+  - Read the \ref usage "usage" for a narrative on codec usage.
+  - Read the \ref samples "sample code" for examples of how to interact with the
+    codec.
+  - \ref codec reference
+    \if encoder
+    - \ref encoder reference
+    \endif
+    \if decoder
+    - \ref decoder reference
+    \endif
+
+  \section main_support Support Options & FAQ
+  The WebM project is an open source project supported by its community. For
+  questions about this SDK, please mail the apps-devel@webmproject.org list.
+  To contribute, see http://www.webmproject.org/code/contribute and mail
+  codec-devel@webmproject.org.
+*/
+
+/*!\page changelog CHANGELOG
+   \verbinclude CHANGELOG
+*/
+
+/*!\page readme README
+   \verbinclude README
+*/
+
+/*!\defgroup codecs Supported Codecs */
diff --git a/md5_utils.c b/md5_utils.c
new file mode 100644 (file)
index 0000000..9a584fa
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ *
+ * Changed so as no longer to depend on Colin Plumb's `usual.h' header
+ * definitions
+ *  - Ian Jackson <ian@chiark.greenend.org.uk>.
+ * Still in the public domain.
+ */
+
+#include <string.h>   /* for memcpy() */
+
+#include "md5_utils.h"
+
+void
+byteSwap(UWORD32 *buf, unsigned words)
+{
+    md5byte *p;
+
+    /* Only swap bytes for big endian machines */
+    int i = 1;
+
+    if (*(char *)&i == 1)
+        return;
+
+    p = (md5byte *)buf;
+
+    do
+    {
+        *buf++ = (UWORD32)((unsigned)p[3] << 8 | p[2]) << 16 |
+                 ((unsigned)p[1] << 8 | p[0]);
+        p += 4;
+    }
+    while (--words);
+}
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void
+MD5Init(struct MD5Context *ctx)
+{
+    ctx->buf[0] = 0x67452301;
+    ctx->buf[1] = 0xefcdab89;
+    ctx->buf[2] = 0x98badcfe;
+    ctx->buf[3] = 0x10325476;
+
+    ctx->bytes[0] = 0;
+    ctx->bytes[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len)
+{
+    UWORD32 t;
+
+    /* Update byte count */
+
+    t = ctx->bytes[0];
+
+    if ((ctx->bytes[0] = t + len) < t)
+        ctx->bytes[1]++;  /* Carry from low to high */
+
+    t = 64 - (t & 0x3f);  /* Space available in ctx->in (at least 1) */
+
+    if (t > len)
+    {
+        memcpy((md5byte *)ctx->in + 64 - t, buf, len);
+        return;
+    }
+
+    /* First chunk is an odd size */
+    memcpy((md5byte *)ctx->in + 64 - t, buf, t);
+    byteSwap(ctx->in, 16);
+    MD5Transform(ctx->buf, ctx->in);
+    buf += t;
+    len -= t;
+
+    /* Process data in 64-byte chunks */
+    while (len >= 64)
+    {
+        memcpy(ctx->in, buf, 64);
+        byteSwap(ctx->in, 16);
+        MD5Transform(ctx->buf, ctx->in);
+        buf += 64;
+        len -= 64;
+    }
+
+    /* Handle any remaining bytes of data. */
+    memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void
+MD5Final(md5byte digest[16], struct MD5Context *ctx)
+{
+    int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */
+    md5byte *p = (md5byte *)ctx->in + count;
+
+    /* Set the first char of padding to 0x80.  There is always room. */
+    *p++ = 0x80;
+
+    /* Bytes of padding needed to make 56 bytes (-8..55) */
+    count = 56 - 1 - count;
+
+    if (count < 0)    /* Padding forces an extra block */
+    {
+        memset(p, 0, count + 8);
+        byteSwap(ctx->in, 16);
+        MD5Transform(ctx->buf, ctx->in);
+        p = (md5byte *)ctx->in;
+        count = 56;
+    }
+
+    memset(p, 0, count);
+    byteSwap(ctx->in, 14);
+
+    /* Append length in bits and transform */
+    ctx->in[14] = ctx->bytes[0] << 3;
+    ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
+    MD5Transform(ctx->buf, ctx->in);
+
+    byteSwap(ctx->buf, 4);
+    memcpy(digest, ctx->buf, 16);
+    memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
+}
+
+#ifndef ASM_MD5
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f,w,x,y,z,in,s) \
+    (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+void
+MD5Transform(UWORD32 buf[4], UWORD32 const in[16])
+{
+    register UWORD32 a, b, c, d;
+
+    a = buf[0];
+    b = buf[1];
+    c = buf[2];
+    d = buf[3];
+
+    MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+    MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+    MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+    MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+    MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+    MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+    MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+    MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+    MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+    MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+    MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+    MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+    MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+    MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+    MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+    MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+    MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+    MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+    MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+    MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+    MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+    MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+    MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+    MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+    MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+    MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+    MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+    MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+    MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+    MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+    MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+    MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+    MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+    MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+    MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+    MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+    MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+    MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+    MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+    MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+    MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+    MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+    MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+    MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+    MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+    MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+    MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+    MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+    MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+    MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+    MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+    MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+    MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+    MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+    MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+    MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+    MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+    MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+    MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+    MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+    MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+    MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+    MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+    MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+    buf[0] += a;
+    buf[1] += b;
+    buf[2] += c;
+    buf[3] += d;
+}
+
+#endif
diff --git a/md5_utils.h b/md5_utils.h
new file mode 100644 (file)
index 0000000..5ca1b5f
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * This is the header file for the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ *
+ * Changed so as no longer to depend on Colin Plumb's `usual.h'
+ * header definitions
+ *  - Ian Jackson <ian@chiark.greenend.org.uk>.
+ * Still in the public domain.
+ */
+
+#ifndef MD5_H
+#define MD5_H
+
+#define md5byte unsigned char
+#define UWORD32 unsigned int
+
+typedef struct MD5Context MD5Context;
+struct MD5Context
+{
+    UWORD32 buf[4];
+    UWORD32 bytes[2];
+    UWORD32 in[16];
+};
+
+void MD5Init(struct MD5Context *context);
+void MD5Update(struct MD5Context *context, md5byte const *buf, unsigned len);
+void MD5Final(unsigned char digest[16], struct MD5Context *context);
+void MD5Transform(UWORD32 buf[4], UWORD32 const in[16]);
+
+#endif /* !MD5_H */
diff --git a/nestegg/.gitignore b/nestegg/.gitignore
new file mode 100644 (file)
index 0000000..b2ba99c
--- /dev/null
@@ -0,0 +1,40 @@
+*.lo
+*.o
+*.swp
+*~
+.deps
+.dirstamp
+.libs
+Makefile
+Makefile.in
+_stdint.h
+aclocal.m4
+autom4te.cache
+compile
+config.guess
+config.h
+config.h.in
+config.log
+config.status
+config.sub
+configure
+depcomp
+docs/Doxyfile
+docs/doxygen-build.stamp
+docs/html
+install-sh
+libtool
+ltmain.sh
+m4/libtool.m4
+m4/ltoptions.m4
+m4/ltsugar.m4
+m4/ltversion.m4
+m4/lt~obsolete.m4
+missing
+nestegg-uninstalled.pc
+nestegg.pc
+src/.dirstamp
+src/libnestegg.la
+stamp-h1
+test/test
+include/nestegg/nestegg-stdint.h
diff --git a/nestegg/AUTHORS b/nestegg/AUTHORS
new file mode 100644 (file)
index 0000000..8204f40
--- /dev/null
@@ -0,0 +1 @@
+Matthew Gregan <kinetik@flim.org>
diff --git a/nestegg/INSTALL b/nestegg/INSTALL
new file mode 100644 (file)
index 0000000..401df41
--- /dev/null
@@ -0,0 +1,8 @@
+Build instructions for libnestegg
+=================================
+
+0. Change directory into the source directory.
+1. Run |autoreconf --install| to generate configure.
+2. Run |./configure| to configure the build.
+3. Run |make| to build.
+4. Run |make check| to run the test suite.
diff --git a/nestegg/LICENSE b/nestegg/LICENSE
new file mode 100644 (file)
index 0000000..a67984a
--- /dev/null
@@ -0,0 +1,13 @@
+Copyright © 2010 Mozilla Foundation
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/nestegg/Makefile.am b/nestegg/Makefile.am
new file mode 100644 (file)
index 0000000..5006991
--- /dev/null
@@ -0,0 +1,51 @@
+AUTOMAKE_OPTIONS = foreign 1.11 no-dist-gzip dist-bzip2 subdir-objects
+ACLOCAL_AMFLAGS = -I m4
+
+INCLUDES = -I$(top_srcdir)/include -I. -I$(top_srcdir)/halloc
+AM_CFLAGS = -ansi -pedantic -Wall -Wextra -Wno-long-long -O0 -g
+
+SUBDIRS = docs
+
+EXTRA_DIST = \
+       AUTHORS README LICENSE \
+       nestegg-uninstalled.pc.in \
+       m4/as-ac-expand.m4 \
+       m4/pkg.m4 \
+       m4/ax_create_stdint_h.m4 \
+       halloc/src/halloc.c \
+       halloc/halloc.h \
+       halloc/src/align.h \
+       halloc/src/hlist.h \
+       halloc/src/macros.h
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = nestegg.pc
+
+nesteggincludedir = $(includedir)/nestegg
+nestegginclude_HEADERS = include/nestegg/nestegg.h include/nestegg/nestegg-stdint.h
+
+lib_LTLIBRARIES = src/libnestegg.la
+
+src_libnestegg_la_SOURCES = \
+       src/nestegg.c \
+       halloc/src/halloc.c \
+       halloc/halloc.h \
+       halloc/src/align.h \
+       halloc/src/hlist.h \
+       halloc/src/macros.h
+
+check_PROGRAMS = test/test
+
+test_test_SOURCES = test/test.c
+test_test_LDADD = src/libnestegg.la
+
+DISTCLEANFILES = include/nestegg/nestegg-stdint.h
+
+dist-hook:
+       find $(distdir) -type d -name '.git' | xargs rm -rf
+
+debug:
+       $(MAKE) all CFLAGS="@DEBUG@"
+
+profile:
+       $(MAKE) all CFLAGS="@PROFILE@"
diff --git a/nestegg/README b/nestegg/README
new file mode 100644 (file)
index 0000000..47c8237
--- /dev/null
@@ -0,0 +1,6 @@
+See INSTALL for build instructions.
+
+Licensed under an ISC-style license.  See LICENSE for details.
+
+The source under the halloc/ directory is licensed under a BSD license.  See
+halloc/halloc.h for details.
diff --git a/nestegg/TODO b/nestegg/TODO
new file mode 100644 (file)
index 0000000..bf0cb04
--- /dev/null
@@ -0,0 +1,21 @@
+- Document when read, seek, tell callbacks are used.
+- Add an automated testsuite.
+- Test (and fix, if necessary) support for unknown sizes.
+- Test (and fix, if necessary) support for large files.
+- Read past unknown elements rather than seeking.
+- Try to handle unknown elements with unknown sizes.
+- Formalize handling of default element values.
+- Try to resynchronize stream when read_block fails so that failure to parse
+  a single block can be treated as non-fatal.
+- Make logging more useful to API users.
+- Avoid reparsing Cues and ignore any SeekHead at end of file.
+- Optionally build a Cue index as Clusters are parsed.
+- Support seeking without Cues.
+- Avoid building a list of Clusters as they are parsed and retain only the
+  last one parsed.
+- Add an asynchronous error code to struct nestegg and ensure that API calls
+  continue to fail safely one a fatal error has been returned.
+- Modify parser/data structures to provide a clean separation.  Perhaps the
+  parser should return a generic tree of nodes that a second pass uses to
+  initialize the main data structures.
+- Use pool allocator for all allocations.
diff --git a/nestegg/configure.ac b/nestegg/configure.ac
new file mode 100644 (file)
index 0000000..70f6e0d
--- /dev/null
@@ -0,0 +1,124 @@
+dnl ------------------------------------------------
+dnl Initialization and Versioning
+dnl ------------------------------------------------
+
+AC_INIT(libnestegg,[0.1git])
+
+AC_CANONICAL_HOST
+AC_CANONICAL_TARGET
+
+AC_CONFIG_MACRO_DIR([m4])
+
+AM_CONFIG_HEADER([config.h])
+AC_CONFIG_SRCDIR([src/nestegg.c])
+AM_INIT_AUTOMAKE
+
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+dnl Library versioning
+dnl CURRENT, REVISION, AGE
+dnl - library source changed -> increment REVISION
+dnl - interfaces added/removed/changed -> increment CURRENT, REVISION = 0
+dnl - interfaces added -> increment AGE
+dnl - interfaces removed -> AGE = 0
+
+NESTEGG_CURRENT=0
+NESTEGG_REVISION=0
+NESTEGG_AGE=1
+AC_SUBST(NESTEGG_CURRENT)
+AC_SUBST(NESTEGG_REVISION)
+AC_SUBST(NESTEGG_AGE)
+
+
+dnl --------------------------------------------------  
+dnl Check for programs
+dnl --------------------------------------------------  
+
+dnl save $CFLAGS since AC_PROG_CC likes to insert "-g -O2"
+dnl if $CFLAGS is blank
+cflags_save="$CFLAGS"
+AC_PROG_CC
+AC_PROG_CPP
+CFLAGS="$cflags_save"
+
+AM_PROG_CC_C_O
+AC_LIBTOOL_WIN32_DLL
+AM_PROG_LIBTOOL
+
+dnl Check for doxygen
+AC_ARG_ENABLE([doc],
+       AS_HELP_STRING([--enable-doc], [Build API documentation]),
+       [ac_enable_doc=$enableval], [ac_enable_doc=auto])
+
+if test "x$ac_enable_doc" != "xno"; then
+       AC_CHECK_PROG(HAVE_DOXYGEN, doxygen, true, false)
+
+       if test "x$HAVE_DOXYGEN" = "xfalse" -a "x$ac_enable_doc" = "xyes"; then
+               AC_MSG_ERROR([*** API documentation explicitly requested but Doxygen not found])
+       fi
+else
+       HAVE_DOXYGEN=false
+fi
+AM_CONDITIONAL(HAVE_DOXYGEN,$HAVE_DOXYGEN)
+if test $HAVE_DOXYGEN = "false"; then
+        AC_MSG_WARN([*** doxygen not found, API documentation will not be built])
+fi
+
+# Generate portable stdint.h replacement
+AX_CREATE_STDINT_H(include/nestegg/nestegg-stdint.h)
+
+# Test whenever ld supports -version-script
+AC_PROG_LD
+AC_PROG_LD_GNU
+AC_MSG_CHECKING([how to control symbol export])
+
+dnl --------------------------------------------------
+dnl Do substitutions
+dnl --------------------------------------------------
+
+AC_SUBST(DEBUG)
+AC_SUBST(PROFILE)
+
+AC_OUTPUT([
+  Makefile 
+  docs/Makefile
+  docs/Doxyfile
+  nestegg.pc
+  nestegg-uninstalled.pc
+])
+
+AS_AC_EXPAND(LIBDIR, ${libdir})
+AS_AC_EXPAND(INCLUDEDIR, ${includedir})
+AS_AC_EXPAND(BINDIR, ${bindir})
+AS_AC_EXPAND(DOCDIR, ${docdir})
+
+if test $HAVE_DOXYGEN = "false"; then
+  doc_build="no"
+else
+  doc_build="yes"
+fi
+
+AC_MSG_RESULT([
+------------------------------------------------------------------------
+  $PACKAGE $VERSION:  Automatic configuration OK.
+
+  General configuration:
+
+    API Documentation: .......... ${doc_build}
+
+  Installation paths:
+
+    libnestegg: .................. ${LIBDIR}
+    C header files: .............. ${INCLUDEDIR}/nestegg
+    Documentation: ............... ${DOCDIR}
+
+  Building:
+
+    Type 'make' to compile $PACKAGE.
+
+    Type 'make install' to install $PACKAGE.
+
+  Example programs will be built but not installed.
+------------------------------------------------------------------------
+])
+
diff --git a/nestegg/docs/Doxyfile.in b/nestegg/docs/Doxyfile.in
new file mode 100644 (file)
index 0000000..e0e9249
--- /dev/null
@@ -0,0 +1,1551 @@
+# Doxyfile 1.6.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = @PACKAGE@
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER         = @VERSION@
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = .
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it parses.
+# With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this tag.
+# The format is ext=language, where ext is a file extension, and language is one of
+# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP,
+# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat
+# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING      =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen to replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penality.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will rougly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS       = NO
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
+# doxygen. The layout file controls the global structure of the generated output files
+# in an output format independent way. The create the layout file that represents
+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
+# file name after the option, if omitted DoxygenLayout.xml will be used as the name
+# of the layout file.
+
+LAYOUT_FILE            =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC       = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT                  = @top_srcdir@/include/nestegg
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS          =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        =
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP         = NO
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE               =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING     =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
+# are set, an additional index file will be generated that can be used as input for
+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
+# HTML documentation.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add.
+# For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+#  will be generated, which together with the HTML files, form an Eclipse help
+#  plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before the help appears.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES       = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be implemented using a PHP enabled web server instead of at the web client using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server based approach is that it scales better to large projects and allows full text search. The disadvances is that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE      = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA             =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD                =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED             =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# By default doxygen will write a font called FreeSans.ttf to the output
+# directory and reference it in all dot files that doxygen generates. This
+# font does not include all possible unicode characters however, so when you need
+# these (or just want a differently looking font) you can specify the font name
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME           = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS           =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP            = YES
diff --git a/nestegg/docs/Makefile.am b/nestegg/docs/Makefile.am
new file mode 100644 (file)
index 0000000..42cf8ee
--- /dev/null
@@ -0,0 +1,38 @@
+doc_DATA = doxygen-build.stamp
+
+EXTRA_DIST = Doxyfile.in
+
+if HAVE_DOXYGEN
+doxygen-build.stamp: Doxyfile
+       doxygen
+       touch doxygen-build.stamp
+else
+doxygen-build.stamp:
+       echo "*** Warning: Doxygen not found; documentation will not be built."
+       touch doxygen-build.stamp
+endif
+
+dist_docdir = $(distdir)/libnestegg
+
+dist-hook:
+       if test -d html; then \
+         mkdir $(dist_docdir); \
+         echo -n "copying built documenation..."; \
+         cp -rp html $(dist_docdir)/html; \
+         echo "OK"; \
+       fi
+
+
+install-data-local: doxygen-build.stamp
+       $(mkinstalldirs) $(DESTDIR)$(docdir)
+       if test -d html; then \
+         cp -rp html $(DESTDIR)$(docdir)/html; \
+       fi
+
+uninstall-local:
+       rm -rf $(DESTDIR)$(docdir)
+
+clean-local:
+       if test -d html; then rm -rf html; fi
+       if test -f doxygen-build.stamp; then rm -f doxygen-build.stamp; fi
+
diff --git a/nestegg/halloc/README b/nestegg/halloc/README
new file mode 100644 (file)
index 0000000..380fba2
--- /dev/null
@@ -0,0 +1,45 @@
+halloc 1.2.1
+============
+      
+       Hierarchical memory heap interface - an extension to standard
+       malloc/free interface that simplifies tasks of memory disposal 
+       when allocated structures exhibit hierarchical properties.
+
+       http://swapped.cc/halloc
+=
+       To build libhalloc.a with GNU tools run
+               make
+
+       To install in /usr/include and /usr/lib
+               make install
+
+       To cleanup the build files 
+               make clean
+=
+       halloc-1.2.1
+               * fixed a double-free bug in _set_allocator() as per
+                 Matthew Gregan comments
+
+               * switched to using NULL instead of 0 where applicable
+
+       halloc-1.2.0
+               * added missing <string.h> include to halloc.c
+               
+               * improved standard compliance thanks to the feedback
+                 received from Stan Tobias. Two things were fixed -
+                 
+               - hblock_t structure no longer uses zero-sized 'data'
+                 array, which happened to be common, but non-standard
+                 extension; 
+                 
+               - secondly, added the code to test the behaviour of 
+                 realloc(ptr, 0). Standard allows it NOT to act as
+                 free(), in which case halloc will use its own version
+                 of allocator calling free() when neccessary.
+
+       halloc-1.1.0
+               * initial public release (rewrite of hhmalloc library)
+
+=============================================================================
+Copyright (c) 2004-2010, Alex Pankratov (ap@swapped.cc). All rights reserved.
+
diff --git a/nestegg/halloc/halloc.h b/nestegg/halloc/halloc.h
new file mode 100644 (file)
index 0000000..10af4e8
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ *     Copyright (c) 2004-2010 Alex Pankratov. All rights reserved.
+ *
+ *     Hierarchical memory allocator, 1.2.1
+ *     http://swapped.cc/halloc
+ */
+
+/*
+ *     The program is distributed under terms of BSD license. 
+ *     You can obtain the copy of the license by visiting:
+ *     
+ *     http://www.opensource.org/licenses/bsd-license.php
+ */
+
+#ifndef _LIBP_HALLOC_H_
+#define _LIBP_HALLOC_H_
+
+#include <stddef.h>  /* size_t */
+
+/*
+ *     Core API
+ */
+void * halloc (void * block, size_t len);
+void   hattach(void * block, void * parent);
+
+/*
+ *     standard malloc/free api
+ */
+void * h_malloc (size_t len);
+void * h_calloc (size_t n, size_t len);
+void * h_realloc(void * p, size_t len);
+void   h_free   (void * p);
+char * h_strdup (const char * str);
+
+/*
+ *     the underlying allocator
+ */
+typedef void * (* realloc_t)(void * ptr, size_t len);
+
+extern realloc_t halloc_allocator;
+
+#endif
+
diff --git a/nestegg/halloc/src/align.h b/nestegg/halloc/src/align.h
new file mode 100644 (file)
index 0000000..4c6e183
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *     Copyright (c) 2004-2010 Alex Pankratov. All rights reserved.
+ *
+ *     Hierarchical memory allocator, 1.2.1
+ *     http://swapped.cc/halloc
+ */
+
+/*
+ *     The program is distributed under terms of BSD license. 
+ *     You can obtain the copy of the license by visiting:
+ *     
+ *     http://www.opensource.org/licenses/bsd-license.php
+ */
+
+#ifndef _LIBP_ALIGN_H_
+#define _LIBP_ALIGN_H_
+
+/*
+ *     a type with the most strict alignment requirements
+ */
+union max_align
+{
+       char   c;
+       short  s;
+       long   l;
+       int    i;
+       float  f;
+       double d;
+       void * v;
+       void (*q)(void);
+};
+
+typedef union max_align max_align_t;
+
+#endif
+
diff --git a/nestegg/halloc/src/halloc.c b/nestegg/halloc/src/halloc.c
new file mode 100644 (file)
index 0000000..38fd6c1
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ *     Copyright (c) 2004i-2010 Alex Pankratov. All rights reserved.
+ *
+ *     Hierarchical memory allocator, 1.2.1
+ *     http://swapped.cc/halloc
+ */
+
+/*
+ *     The program is distributed under terms of BSD license. 
+ *     You can obtain the copy of the license by visiting:
+ *     
+ *     http://www.opensource.org/licenses/bsd-license.php
+ */
+
+#include <stdlib.h>  /* realloc */
+#include <string.h>  /* memset & co */
+
+#include "../halloc.h"
+#include "align.h"
+#include "hlist.h"
+
+/*
+ *     block control header
+ */
+typedef struct hblock
+{
+#ifndef NDEBUG
+#define HH_MAGIC    0x20040518L
+       long          magic;
+#endif
+       hlist_item_t  siblings; /* 2 pointers */
+       hlist_head_t  children; /* 1 pointer  */
+       max_align_t   data[1];  /* not allocated, see below */
+       
+} hblock_t;
+
+#define sizeof_hblock offsetof(hblock_t, data)
+
+/*
+ *
+ */
+realloc_t halloc_allocator = NULL;
+
+#define allocator halloc_allocator
+
+/*
+ *     static methods
+ */
+static void _set_allocator(void);
+static void * _realloc(void * ptr, size_t n);
+
+static int  _relate(hblock_t * b, hblock_t * p);
+static void _free_children(hblock_t * p);
+
+/*
+ *     Core API
+ */
+void * halloc(void * ptr, size_t len)
+{
+       hblock_t * p;
+
+       /* set up default allocator */
+       if (! allocator)
+       {
+               _set_allocator();
+               assert(allocator);
+       }
+
+       /* calloc */
+       if (! ptr)
+       {
+               if (! len)
+                       return NULL;
+
+               p = allocator(0, len + sizeof_hblock);
+               if (! p)
+                       return NULL;
+#ifndef NDEBUG
+               p->magic = HH_MAGIC;
+#endif
+               hlist_init(&p->children);
+               hlist_init_item(&p->siblings);
+
+               return p->data;
+       }
+
+       p = structof(ptr, hblock_t, data);
+       assert(p->magic == HH_MAGIC);
+
+       /* realloc */
+       if (len)
+       {
+               p = allocator(p, len + sizeof_hblock);
+               if (! p)
+                       return NULL;
+
+               hlist_relink(&p->siblings);
+               hlist_relink_head(&p->children);
+               
+               return p->data;
+       }
+
+       /* free */
+       _free_children(p);
+       hlist_del(&p->siblings);
+       allocator(p, 0);
+
+       return NULL;
+}
+
+void hattach(void * block, void * parent)
+{
+       hblock_t * b, * p;
+       
+       if (! block)
+       {
+               assert(! parent);
+               return;
+       }
+
+       /* detach */
+       b = structof(block, hblock_t, data);
+       assert(b->magic == HH_MAGIC);
+
+       hlist_del(&b->siblings);
+
+       if (! parent)
+               return;
+
+       /* attach */
+       p = structof(parent, hblock_t, data);
+       assert(p->magic == HH_MAGIC);
+       
+       /* sanity checks */
+       assert(b != p);          /* trivial */
+       assert(! _relate(p, b)); /* heavy ! */
+
+       hlist_add(&p->children, &b->siblings);
+}
+
+/*
+ *     malloc/free api
+ */
+void * h_malloc(size_t len)
+{
+       return halloc(0, len);
+}
+
+void * h_calloc(size_t n, size_t len)
+{
+       void * ptr = halloc(0, len*=n);
+       return ptr ? memset(ptr, 0, len) : NULL;
+}
+
+void * h_realloc(void * ptr, size_t len)
+{
+       return halloc(ptr, len);
+}
+
+void   h_free(void * ptr)
+{
+       halloc(ptr, 0);
+}
+
+char * h_strdup(const char * str)
+{
+       size_t len = strlen(str);
+       char * ptr = halloc(0, len + 1);
+       return ptr ? (ptr[len] = 0, memcpy(ptr, str, len)) : NULL;
+}
+
+/*
+ *     static stuff
+ */
+static void _set_allocator(void)
+{
+       void * p;
+       assert(! allocator);
+       
+       /*
+        *      the purpose of the test below is to check the behaviour
+        *      of realloc(ptr, 0), which is defined in the standard
+        *      as an implementation-specific. if it returns zero,
+        *      then it's equivalent to free(). it can however return
+        *      non-zero, in which case it cannot be used for freeing
+        *      memory blocks and we'll need to supply our own version
+        *
+        *      Thanks to Stan Tobias for pointing this tricky part out.
+        */
+       allocator = realloc;
+       if (! (p = malloc(1)))
+               /* hmm */
+               return;
+               
+       if ((p = realloc(p, 0)))
+       {
+               /* realloc cannot be used as free() */
+               allocator = _realloc;
+               free(p);
+       }
+}
+
+static void * _realloc(void * ptr, size_t n)
+{
+       /*
+        *      free'ing realloc()
+        */
+       if (n)
+               return realloc(ptr, n);
+       free(ptr);
+       return NULL;
+}
+
+static int _relate(hblock_t * b, hblock_t * p)
+{
+       hlist_item_t * i;
+
+       if (!b || !p)
+               return 0;
+
+       /* 
+        *  since there is no 'parent' pointer, which would've allowed
+        *  O(log(n)) upward traversal, the check must use O(n) downward 
+        *  iteration of the entire hierarchy; and this can be VERY SLOW
+        */
+       hlist_for_each(i, &p->children)
+       {
+               hblock_t * q = structof(i, hblock_t, siblings);
+               if (q == b || _relate(b, q))
+                       return 1;
+       }
+       return 0;
+}
+
+static void _free_children(hblock_t * p)
+{
+       hlist_item_t * i, * tmp;
+       
+#ifndef NDEBUG
+       /*
+        *      this catches loops in hierarchy with almost zero 
+        *      overhead (compared to _relate() running time)
+        */
+       assert(p && p->magic == HH_MAGIC);
+       p->magic = 0; 
+#endif
+       hlist_for_each_safe(i, tmp, &p->children)
+       {
+               hblock_t * q = structof(i, hblock_t, siblings);
+               _free_children(q);
+               allocator(q, 0);
+       }
+}
+
diff --git a/nestegg/halloc/src/hlist.h b/nestegg/halloc/src/hlist.h
new file mode 100644 (file)
index 0000000..2791f78
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ *     Copyright (c) 2004-2010 Alex Pankratov. All rights reserved.
+ *
+ *     Hierarchical memory allocator, 1.2.1
+ *     http://swapped.cc/halloc
+ */
+
+/*
+ *     The program is distributed under terms of BSD license. 
+ *     You can obtain the copy of the license by visiting:
+ *     
+ *     http://www.opensource.org/licenses/bsd-license.php
+ */
+
+#ifndef _LIBP_HLIST_H_
+#define _LIBP_HLIST_H_
+
+#include <assert.h>
+#include "macros.h"  /* static_inline */
+
+/*
+ *     weak double-linked list w/ tail sentinel
+ */
+typedef struct hlist_head  hlist_head_t;
+typedef struct hlist_item  hlist_item_t;
+
+/*
+ *
+ */
+struct hlist_head
+{
+       hlist_item_t * next;
+};
+
+struct hlist_item
+{
+       hlist_item_t * next;
+       hlist_item_t ** prev;
+};
+
+/*
+ *     shared tail sentinel
+ */
+struct hlist_item hlist_null;
+
+/*
+ *
+ */
+#define __hlist_init(h)      { &hlist_null }
+#define __hlist_init_item(i) { &hlist_null, &(i).next }
+
+static_inline void hlist_init(hlist_head_t * h);
+static_inline void hlist_init_item(hlist_item_t * i);
+
+/* static_inline void hlist_purge(hlist_head_t * h); */
+
+/* static_inline bool_t hlist_empty(const hlist_head_t * h); */
+
+/* static_inline hlist_item_t * hlist_head(const hlist_head_t * h); */
+
+/* static_inline hlist_item_t * hlist_next(const hlist_item_t * i); */
+/* static_inline hlist_item_t * hlist_prev(const hlist_item_t * i, 
+                                           const hlist_head_t * h); */
+
+static_inline void hlist_add(hlist_head_t * h, hlist_item_t * i);
+
+/* static_inline void hlist_add_prev(hlist_item_t * l, hlist_item_t * i); */
+/* static_inline void hlist_add_next(hlist_item_t * l, hlist_item_t * i); */
+
+static_inline void hlist_del(hlist_item_t * i);
+
+static_inline void hlist_relink(hlist_item_t * i);
+static_inline void hlist_relink_head(hlist_head_t * h);
+
+#define hlist_for_each(i, h) \
+       for (i = (h)->next; i != &hlist_null; i = i->next)
+
+#define hlist_for_each_safe(i, tmp, h) \
+       for (i = (h)->next, tmp = i->next; \
+            i!= &hlist_null; \
+            i = tmp, tmp = i->next)
+
+/*
+ *     static
+ */
+static_inline void hlist_init(hlist_head_t * h)
+{
+       assert(h);
+       h->next = &hlist_null;
+}
+
+static_inline void hlist_init_item(hlist_item_t * i)
+{
+       assert(i);
+       i->prev = &i->next;
+       i->next = &hlist_null;
+}
+
+static_inline void hlist_add(hlist_head_t * h, hlist_item_t * i)
+{
+       hlist_item_t * next;
+       assert(h && i);
+       
+       next = i->next = h->next;
+       next->prev = &i->next;
+       h->next = i;
+       i->prev = &h->next;
+}
+
+static_inline void hlist_del(hlist_item_t * i)
+{
+       hlist_item_t * next;
+       assert(i);
+
+       next = i->next;
+       next->prev = i->prev;
+       *i->prev = next;
+       
+       hlist_init_item(i);
+}
+
+static_inline void hlist_relink(hlist_item_t * i)
+{
+       assert(i);
+       *i->prev = i;
+       i->next->prev = &i->next;
+}
+
+static_inline void hlist_relink_head(hlist_head_t * h)
+{
+       assert(h);
+       h->next->prev = &h->next;
+}
+
+#endif
+
diff --git a/nestegg/halloc/src/macros.h b/nestegg/halloc/src/macros.h
new file mode 100644 (file)
index 0000000..c36b516
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *     Copyright (c) 2004-2010 Alex Pankratov. All rights reserved.
+ *
+ *     Hierarchical memory allocator, 1.2.1
+ *     http://swapped.cc/halloc
+ */
+
+/*
+ *     The program is distributed under terms of BSD license. 
+ *     You can obtain the copy of the license by visiting:
+ *     
+ *     http://www.opensource.org/licenses/bsd-license.php
+ */
+
+#ifndef _LIBP_MACROS_H_
+#define _LIBP_MACROS_H_
+
+#include <stddef.h>  /* offsetof */
+
+/*
+       restore pointer to the structure by a pointer to its field
+ */
+#define structof(p,t,f) ((t*)(- offsetof(t,f) + (char*)(p)))
+
+/*
+ *     redefine for the target compiler
+ */
+#ifdef _WIN32
+#define static_inline static __inline
+#else
+#define static_inline static __inline__
+#endif
+
+
+#endif
+
diff --git a/nestegg/include/nestegg/nestegg.h b/nestegg/include/nestegg/nestegg.h
new file mode 100644 (file)
index 0000000..7447d14
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * Copyright © 2010 Mozilla Foundation
+ *
+ * This program is made available under an ISC-style license.  See the
+ * accompanying file LICENSE for details.
+ */
+#ifndef   NESTEGG_671cac2a_365d_ed69_d7a3_4491d3538d79
+#define   NESTEGG_671cac2a_365d_ed69_d7a3_4491d3538d79
+
+#include "vpx/vpx_integer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @mainpage
+
+    @section intro Introduction
+
+    This is the documentation fot the <tt>libnestegg</tt> C API.
+    <tt>libnestegg</tt> is a demultiplexing library for <a
+    href="http://www.matroska.org/">Matroska</a> and <a
+    href="http://www.webmproject.org/">WebMedia</a> media files.
+
+    @section example Example code
+
+    @code
+    nestegg * demux_ctx;
+    nestegg_init(&demux_ctx, io, NULL);
+
+    nestegg_packet * pkt;
+    while ((r = nestegg_read_packet(demux_ctx, &pkt)) > 0) {
+      unsigned int track;
+
+      nestegg_packet_track(pkt, &track);
+
+      // This example decodes the first track only.
+      if (track == 0) {
+        unsigned int chunk, chunks;
+
+        nestegg_packet_count(pkt, &chunks);
+
+        // Decode each chunk of data.
+        for (chunk = 0; chunk < chunks; ++chunk) {
+          unsigned char * data;
+          size_t data_size;
+
+          nestegg_packet_data(pkt, chunk, &data, &data_size);
+
+          example_codec_decode(codec_ctx, data, data_size);
+        }
+      }
+
+      nestegg_free_packet(pkt);
+    }
+
+    nestegg_destroy(demux_ctx);
+    @endcode
+*/
+
+
+/** @file
+    The <tt>libnestegg</tt> C API. */
+
+#define NESTEGG_TRACK_VIDEO 0 /**< Track is of type video. */
+#define NESTEGG_TRACK_AUDIO 1 /**< Track is of type audio. */
+
+#define NESTEGG_CODEC_VP8    0 /**< Track uses Google On2 VP8 codec. */
+#define NESTEGG_CODEC_VORBIS 1 /**< Track uses Xiph Vorbis codec. */
+
+#define NESTEGG_SEEK_SET 0 /**< Seek offset relative to beginning of stream. */
+#define NESTEGG_SEEK_CUR 1 /**< Seek offset relative to current position in stream. */
+#define NESTEGG_SEEK_END 2 /**< Seek offset relative to end of stream. */
+
+#define NESTEGG_LOG_DEBUG    1     /**< Debug level log message. */
+#define NESTEGG_LOG_INFO     10    /**< Informational level log message. */
+#define NESTEGG_LOG_WARNING  100   /**< Warning level log message. */
+#define NESTEGG_LOG_ERROR    1000  /**< Error level log message. */
+#define NESTEGG_LOG_CRITICAL 10000 /**< Critical level log message. */
+
+typedef struct nestegg nestegg;               /**< Opaque handle referencing the stream state. */
+typedef struct nestegg_packet nestegg_packet; /**< Opaque handle referencing a packet of data. */
+
+/** User supplied IO context. */
+typedef struct {
+  /** User supplied read callback.
+      @param buffer   Buffer to read data into.
+      @param length   Length of supplied buffer in bytes.
+      @param userdata The #userdata supplied by the user.
+      @retval  1 Read succeeded.
+      @retval  0 End of stream.
+      @retval -1 Error. */
+  int (* read)(void * buffer, size_t length, void * userdata);
+
+  /** User supplied seek callback.
+      @param offset   Offset within the stream to seek to.
+      @param whence   Seek direction.  One of #NESTEGG_SEEK_SET,
+                      #NESTEGG_SEEK_CUR, or #NESTEGG_SEEK_END.
+      @param userdata The #userdata supplied by the user.
+      @retval  0 Seek succeeded.
+      @retval -1 Error. */
+  int (* seek)(int64_t offset, int whence, void * userdata);
+
+  /** User supplied tell callback.
+      @param userdata The #userdata supplied by the user.
+      @returns Current position within the stream.
+      @retval -1 Error. */
+  int64_t (* tell)(void * userdata);
+
+  /** User supplied pointer to be passed to the IO callbacks. */
+  void * userdata;
+} nestegg_io;
+
+/** Parameters specific to a video track. */
+typedef struct {
+  unsigned int width;          /**< Width of the video frame in pixels. */
+  unsigned int height;         /**< Height of the video frame in pixels. */
+  unsigned int display_width;  /**< Display width of the video frame in pixels. */
+  unsigned int display_height; /**< Display height of the video frame in pixels. */
+  unsigned int crop_bottom;    /**< Pixels to crop from the bottom of the frame. */
+  unsigned int crop_top;       /**< Pixels to crop from the top of the frame. */
+  unsigned int crop_left;      /**< Pixels to crop from the left of the frame. */
+  unsigned int crop_right;     /**< Pixels to crop from the right of the frame. */
+} nestegg_video_params;
+
+/** Parameters specific to an audio track. */
+typedef struct {
+  double rate;           /**< Sampling rate in Hz. */
+  unsigned int channels; /**< Number of audio channels. */
+  unsigned int depth;    /**< Bits per sample. */
+} nestegg_audio_params;
+
+/** Logging callback function pointer. */
+typedef void (* nestegg_log)(nestegg * context, unsigned int severity, char const * format, ...);
+
+/** Initialize a nestegg context.  During initialization the parser will
+    read forward in the stream processing all elements until the first
+    block of media is reached.  All track metadata has been processed at this point.
+    @param context  Storage for the new nestegg context.  @see nestegg_destroy
+    @param io       User supplied IO context.
+    @param callback Optional logging callback function pointer.  May be NULL.
+    @retval  0 Success.
+    @retval -1 Error. */
+int nestegg_init(nestegg ** context, nestegg_io io, nestegg_log callback);
+
+/** Destroy a nestegg context and free associated memory.
+    @param context #nestegg context to be freed.  @see nestegg_init */
+void nestegg_destroy(nestegg * context);
+
+/** Query the duration of the media stream in nanoseconds.
+    @param context  Stream context initialized by #nestegg_init.
+    @param duration Storage for the queried duration.
+    @retval  0 Success.
+    @retval -1 Error. */
+int nestegg_duration(nestegg * context, uint64_t * duration);
+
+/** Query the tstamp scale of the media stream in nanoseconds.
+    Timecodes presented by nestegg have been scaled by this value
+    before presentation to the caller.
+    @param context Stream context initialized by #nestegg_init.
+    @param scale   Storage for the queried scale factor.
+    @retval  0 Success.
+    @retval -1 Error. */
+int nestegg_tstamp_scale(nestegg * context, uint64_t * scale);
+
+/** Query the number of tracks in the media stream.
+    @param context Stream context initialized by #nestegg_init.
+    @param tracks  Storage for the queried track count.
+    @retval  0 Success.
+    @retval -1 Error. */
+int nestegg_track_count(nestegg * context, unsigned int * tracks);
+
+/** Seek @a track to @a tstamp.  Stream seek will terminate at the earliest
+    key point in the stream at or before @a tstamp.  Other tracks in the
+    stream will output packets with unspecified but nearby timestamps.
+    @param context Stream context initialized by #nestegg_init.
+    @param track   Zero based track number.
+    @param tstamp  Absolute timestamp in nanoseconds.
+    @retval  0 Success.
+    @retval -1 Error. */
+int nestegg_track_seek(nestegg * context, unsigned int track, uint64_t tstamp);
+
+/** Query the type specified by @a track.
+    @param context Stream context initialized by #nestegg_init.
+    @param track   Zero based track number.
+    @retval #NESTEGG_TRACK_VIDEO Track type is video.
+    @retval #NESTEGG_TRACK_AUDIO Track type is audio.
+    @retval -1 Error. */
+int nestegg_track_type(nestegg * context, unsigned int track);
+
+/** Query the codec ID specified by @a track.
+    @param context Stream context initialized by #nestegg_init.
+    @param track   Zero based track number.
+    @retval #NESTEGG_CODEC_VP8    Track codec is VP8.
+    @retval #NESTEGG_CODEC_VORBIS Track codec is Vorbis.
+    @retval -1 Error. */
+int nestegg_track_codec_id(nestegg * context, unsigned int track);
+
+/** Query the number of codec initialization chunks for @a track.  Each
+    chunk of data should be passed to the codec initialization functions in
+    the order returned.
+    @param context Stream context initialized by #nestegg_init.
+    @param track   Zero based track number.
+    @param count   Storage for the queried chunk count.
+    @retval  0 Success.
+    @retval -1 Error. */
+int nestegg_track_codec_data_count(nestegg * context, unsigned int track,
+                                   unsigned int * count);
+
+/** Get a pointer to chunk number @a item of codec initialization data for
+    @a track.
+    @param context Stream context initialized by #nestegg_init.
+    @param track   Zero based track number.
+    @param item    Zero based chunk item number.
+    @param data    Storage for the queried data pointer.
+                   The data is owned by the #nestegg context.
+    @param length  Storage for the queried data size.
+    @retval  0 Success.
+    @retval -1 Error. */
+int nestegg_track_codec_data(nestegg * context, unsigned int track, unsigned int item,
+                             unsigned char ** data, size_t * length);
+
+/** Query the video parameters specified by @a track.
+    @param context Stream context initialized by #nestegg_init.
+    @param track   Zero based track number.
+    @param params  Storage for the queried video parameters.
+    @retval  0 Success.
+    @retval -1 Error. */
+int nestegg_track_video_params(nestegg * context, unsigned int track,
+                               nestegg_video_params * params);
+
+/** Query the audio parameters specified by @a track.
+    @param context Stream context initialized by #nestegg_init.
+    @param track   Zero based track number.
+    @param params  Storage for the queried audio parameters.
+    @retval  0 Success.
+    @retval -1 Error. */
+int nestegg_track_audio_params(nestegg * context, unsigned int track,
+                               nestegg_audio_params * params);
+
+/** Read a packet of media data.  A packet consists of one or more chunks of
+    data associated with a single track.  nestegg_read_packet should be
+    called in a loop while the return value is 1 to drive the stream parser
+    forward.  @see nestegg_free_packet
+    @param context Context returned by #nestegg_init.
+    @param packet  Storage for the returned nestegg_packet.
+    @retval  1 Additional packets may be read in subsequent calls.
+    @retval  0 End of stream.
+    @retval -1 Error. */
+int nestegg_read_packet(nestegg * context, nestegg_packet ** packet);
+
+/** Destroy a nestegg_packet and free associated memory.
+    @param packet #nestegg_packet to be freed. @see nestegg_read_packet */
+void nestegg_free_packet(nestegg_packet * packet);
+
+/** Query the track number of @a packet.
+    @param packet Packet initialized by #nestegg_read_packet.
+    @param track  Storage for the queried zero based track index.
+    @retval  0 Success.
+    @retval -1 Error. */
+int nestegg_packet_track(nestegg_packet * packet, unsigned int * track);
+
+/** Query the time stamp in nanoseconds of @a packet.
+    @param packet Packet initialized by #nestegg_read_packet.
+    @param tstamp Storage for the queried timestamp in nanoseconds.
+    @retval  0 Success.
+    @retval -1 Error. */
+int nestegg_packet_tstamp(nestegg_packet * packet, uint64_t * tstamp);
+
+/** Query the number of data chunks contained in @a packet.
+    @param packet Packet initialized by #nestegg_read_packet.
+    @param count  Storage for the queried timestamp in nanoseconds.
+    @retval  0 Success.
+    @retval -1 Error. */
+int nestegg_packet_count(nestegg_packet * packet, unsigned int * count);
+
+/** Get a pointer to chunk number @a item of packet data.
+    @param packet  Packet initialized by #nestegg_read_packet.
+    @param item    Zero based chunk item number.
+    @param data    Storage for the queried data pointer.
+                   The data is owned by the #nestegg_packet packet.
+    @param length  Storage for the queried data size.
+    @retval  0 Success.
+    @retval -1 Error. */
+int nestegg_packet_data(nestegg_packet * packet, unsigned int item,
+                        unsigned char ** data, size_t * length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NESTEGG_671cac2a_365d_ed69_d7a3_4491d3538d79 */
diff --git a/nestegg/m4/as-ac-expand.m4 b/nestegg/m4/as-ac-expand.m4
new file mode 100644 (file)
index 0000000..d6c9e33
--- /dev/null
@@ -0,0 +1,43 @@
+dnl as-ac-expand.m4 0.2.0
+dnl autostars m4 macro for expanding directories using configure's prefix
+dnl thomas@apestaart.org
+
+dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR)
+dnl example
+dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir)
+dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local
+
+AC_DEFUN([AS_AC_EXPAND],
+[
+  EXP_VAR=[$1]
+  FROM_VAR=[$2]
+
+  dnl first expand prefix and exec_prefix if necessary
+  prefix_save=$prefix
+  exec_prefix_save=$exec_prefix
+
+  dnl if no prefix given, then use /usr/local, the default prefix
+  if test "x$prefix" = "xNONE"; then
+    prefix="$ac_default_prefix"
+  fi
+  dnl if no exec_prefix given, then use prefix
+  if test "x$exec_prefix" = "xNONE"; then
+    exec_prefix=$prefix
+  fi
+
+  full_var="$FROM_VAR"
+  dnl loop until it doesn't change anymore
+  while true; do
+    new_full_var="`eval echo $full_var`"
+    if test "x$new_full_var" = "x$full_var"; then break; fi
+    full_var=$new_full_var
+  done
+
+  dnl clean up
+  full_var=$new_full_var
+  AC_SUBST([$1], "$full_var")
+
+  dnl restore prefix and exec_prefix
+  prefix=$prefix_save
+  exec_prefix=$exec_prefix_save
+])
diff --git a/nestegg/m4/ax_create_stdint_h.m4 b/nestegg/m4/ax_create_stdint_h.m4
new file mode 100644 (file)
index 0000000..228105b
--- /dev/null
@@ -0,0 +1,695 @@
+dnl @synopsis AX_CREATE_STDINT_H [( HEADER-TO-GENERATE [, HEDERS-TO-CHECK])]
+dnl
+dnl the "ISO C9X: 7.18 Integer types <stdint.h>" section requires the
+dnl existence of an include file <stdint.h> that defines a set of
+dnl typedefs, especially uint8_t,int32_t,uintptr_t. Many older
+dnl installations will not provide this file, but some will have the
+dnl very same definitions in <inttypes.h>. In other enviroments we can
+dnl use the inet-types in <sys/types.h> which would define the typedefs
+dnl int8_t and u_int8_t respectivly.
+dnl
+dnl This macros will create a local "_stdint.h" or the headerfile given
+dnl as an argument. In many cases that file will just "#include
+dnl <stdint.h>" or "#include <inttypes.h>", while in other environments
+dnl it will provide the set of basic 'stdint's definitions/typedefs:
+dnl
+dnl   int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,intptr_t,uintptr_t
+dnl   int_least32_t.. int_fast32_t.. intmax_t
+dnl
+dnl which may or may not rely on the definitions of other files, or
+dnl using the AC_CHECK_SIZEOF macro to determine the actual sizeof each
+dnl type.
+dnl
+dnl if your header files require the stdint-types you will want to
+dnl create an installable file mylib-int.h that all your other
+dnl installable header may include. So if you have a library package
+dnl named "mylib", just use
+dnl
+dnl      AX_CREATE_STDINT_H(mylib-int.h)
+dnl
+dnl in configure.ac and go to install that very header file in
+dnl Makefile.am along with the other headers (mylib.h) - and the
+dnl mylib-specific headers can simply use "#include <mylib-int.h>" to
+dnl obtain the stdint-types.
+dnl
+dnl Remember, if the system already had a valid <stdint.h>, the
+dnl generated file will include it directly. No need for fuzzy
+dnl HAVE_STDINT_H things... (oops, GCC 4.2.x has deliberatly disabled
+dnl its stdint.h for non-c99 compilation and the c99-mode is not the
+dnl default. Therefore this macro will not use the compiler's stdint.h
+dnl - please complain to the GCC developers).
+dnl
+dnl @category C
+dnl @author Guido U. Draheim <guidod@gmx.de>
+dnl @version 2006-10-13
+dnl @license GPLWithACException
+
+AC_DEFUN([AX_CHECK_DATA_MODEL],[
+   AC_CHECK_SIZEOF(char)
+   AC_CHECK_SIZEOF(short)
+   AC_CHECK_SIZEOF(int)
+   AC_CHECK_SIZEOF(long)
+   AC_CHECK_SIZEOF(void*)
+   ac_cv_char_data_model=""
+   ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_char"
+   ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_short"
+   ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_int"
+   ac_cv_long_data_model=""
+   ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_int"
+   ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_long"
+   ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_voidp"
+   AC_MSG_CHECKING([data model])
+   case "$ac_cv_char_data_model/$ac_cv_long_data_model" in
+    122/242)     ac_cv_data_model="IP16"  ; n="standard 16bit machine" ;;
+    122/244)     ac_cv_data_model="LP32"  ; n="standard 32bit machine" ;;
+    122/*)       ac_cv_data_model="i16"   ; n="unusual int16 model" ;;
+    124/444)     ac_cv_data_model="ILP32" ; n="standard 32bit unixish" ;;
+    124/488)     ac_cv_data_model="LP64"  ; n="standard 64bit unixish" ;;
+    124/448)     ac_cv_data_model="LLP64" ; n="unusual 64bit unixish" ;;
+    124/*)       ac_cv_data_model="i32"   ; n="unusual int32 model" ;;
+    128/888)     ac_cv_data_model="ILP64" ; n="unusual 64bit numeric" ;;
+    128/*)       ac_cv_data_model="i64"   ; n="unusual int64 model" ;;
+    222/*2)      ac_cv_data_model="DSP16" ; n="strict 16bit dsptype" ;;
+    333/*3)      ac_cv_data_model="DSP24" ; n="strict 24bit dsptype" ;;
+    444/*4)      ac_cv_data_model="DSP32" ; n="strict 32bit dsptype" ;;
+    666/*6)      ac_cv_data_model="DSP48" ; n="strict 48bit dsptype" ;;
+    888/*8)      ac_cv_data_model="DSP64" ; n="strict 64bit dsptype" ;;
+    222/*|333/*|444/*|666/*|888/*) :
+                 ac_cv_data_model="iDSP"  ; n="unusual dsptype" ;;
+     *)          ac_cv_data_model="none"  ; n="very unusual model" ;;
+   esac
+   AC_MSG_RESULT([$ac_cv_data_model ($ac_cv_long_data_model, $n)])
+])
+
+dnl AX_CHECK_HEADER_STDINT_X([HEADERLIST][,ACTION-IF])
+AC_DEFUN([AX_CHECK_HEADER_STDINT_X],[
+AC_CACHE_CHECK([for stdint uintptr_t], [ac_cv_header_stdint_x],[
+ ac_cv_header_stdint_x="" # the 1997 typedefs (inttypes.h)
+  AC_MSG_RESULT([(..)])
+  for i in m4_ifval([$1],[$1],[stdint.h inttypes.h sys/inttypes.h sys/types.h])
+  do
+   unset ac_cv_type_uintptr_t
+   unset ac_cv_type_uint64_t
+   AC_CHECK_TYPE(uintptr_t,[ac_cv_header_stdint_x=$i],continue,[#include <$i>])
+   AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>])
+   m4_ifvaln([$1],[$1]) break
+  done
+  AC_MSG_CHECKING([for stdint uintptr_t])
+ ])
+])
+
+AC_DEFUN([AX_CHECK_HEADER_STDINT_O],[
+AC_CACHE_CHECK([for stdint uint32_t], [ac_cv_header_stdint_o],[
+ ac_cv_header_stdint_o="" # the 1995 typedefs (sys/inttypes.h)
+  AC_MSG_RESULT([(..)])
+  for i in m4_ifval([$1],[$1],[inttypes.h sys/inttypes.h sys/types.h stdint.h])
+  do
+   unset ac_cv_type_uint32_t
+   unset ac_cv_type_uint64_t
+   AC_CHECK_TYPE(uint32_t,[ac_cv_header_stdint_o=$i],continue,[#include <$i>])
+   AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>])
+   m4_ifvaln([$1],[$1]) break
+   break;
+  done
+  AC_MSG_CHECKING([for stdint uint32_t])
+ ])
+])
+
+AC_DEFUN([AX_CHECK_HEADER_STDINT_U],[
+AC_CACHE_CHECK([for stdint u_int32_t], [ac_cv_header_stdint_u],[
+ ac_cv_header_stdint_u="" # the BSD typedefs (sys/types.h)
+  AC_MSG_RESULT([(..)])
+  for i in m4_ifval([$1],[$1],[sys/types.h inttypes.h sys/inttypes.h]) ; do
+   unset ac_cv_type_u_int32_t
+   unset ac_cv_type_u_int64_t
+   AC_CHECK_TYPE(u_int32_t,[ac_cv_header_stdint_u=$i],continue,[#include <$i>])
+   AC_CHECK_TYPE(u_int64_t,[and64="/u_int64_t"],[and64=""],[#include<$i>])
+   m4_ifvaln([$1],[$1]) break
+   break;
+  done
+  AC_MSG_CHECKING([for stdint u_int32_t])
+ ])
+])
+
+AC_DEFUN([AX_CREATE_STDINT_H],
+[# ------ AX CREATE STDINT H -------------------------------------
+AC_MSG_CHECKING([for stdint types])
+ac_stdint_h=`echo ifelse($1, , _stdint.h, $1)`
+# try to shortcircuit - if the default include path of the compiler
+# can find a "stdint.h" header then we assume that all compilers can.
+AC_CACHE_VAL([ac_cv_header_stdint_t],[
+old_CXXFLAGS="$CXXFLAGS" ; CXXFLAGS=""
+old_CPPFLAGS="$CPPFLAGS" ; CPPFLAGS=""
+old_CFLAGS="$CFLAGS"     ; CFLAGS=""
+AC_TRY_COMPILE([#include <stdint.h>],[int_least32_t v = 0;],
+[ac_cv_stdint_result="(assuming C99 compatible system)"
+ ac_cv_header_stdint_t="stdint.h"; ],
+[ac_cv_header_stdint_t=""])
+if test "$GCC" = "yes" && test ".$ac_cv_header_stdint_t" = "."; then
+CFLAGS="-std=c99"
+AC_TRY_COMPILE([#include <stdint.h>],[int_least32_t v = 0;],
+[AC_MSG_WARN(your GCC compiler has a defunct stdint.h for its default-mode)])
+fi
+CXXFLAGS="$old_CXXFLAGS"
+CPPFLAGS="$old_CPPFLAGS"
+CFLAGS="$old_CFLAGS" ])
+
+v="... $ac_cv_header_stdint_h"
+if test "$ac_stdint_h" = "stdint.h" ; then
+ AC_MSG_RESULT([(are you sure you want them in ./stdint.h?)])
+elif test "$ac_stdint_h" = "inttypes.h" ; then
+ AC_MSG_RESULT([(are you sure you want them in ./inttypes.h?)])
+elif test "_$ac_cv_header_stdint_t" = "_" ; then
+ AC_MSG_RESULT([(putting them into $ac_stdint_h)$v])
+else
+ ac_cv_header_stdint="$ac_cv_header_stdint_t"
+ AC_MSG_RESULT([$ac_cv_header_stdint (shortcircuit)])
+fi
+
+if test "_$ac_cv_header_stdint_t" = "_" ; then # can not shortcircuit..
+
+dnl .....intro message done, now do a few system checks.....
+dnl btw, all old CHECK_TYPE macros do automatically "DEFINE" a type,
+dnl therefore we use the autoconf implementation detail CHECK_TYPE_NEW
+dnl instead that is triggered with 3 or more arguments (see types.m4)
+
+inttype_headers=`echo $2 | sed -e 's/,/ /g'`
+
+ac_cv_stdint_result="(no helpful system typedefs seen)"
+AX_CHECK_HEADER_STDINT_X(dnl
+   stdint.h inttypes.h sys/inttypes.h $inttype_headers,
+   ac_cv_stdint_result="(seen uintptr_t$and64 in $i)")
+
+if test "_$ac_cv_header_stdint_x" = "_" ; then
+AX_CHECK_HEADER_STDINT_O(dnl,
+   inttypes.h sys/inttypes.h stdint.h $inttype_headers,
+   ac_cv_stdint_result="(seen uint32_t$and64 in $i)")
+fi
+
+if test "_$ac_cv_header_stdint_x" = "_" ; then
+if test "_$ac_cv_header_stdint_o" = "_" ; then
+AX_CHECK_HEADER_STDINT_U(dnl,
+   sys/types.h inttypes.h sys/inttypes.h $inttype_headers,
+   ac_cv_stdint_result="(seen u_int32_t$and64 in $i)")
+fi fi
+
+dnl if there was no good C99 header file, do some typedef checks...
+if test "_$ac_cv_header_stdint_x" = "_" ; then
+   AC_MSG_CHECKING([for stdint datatype model])
+   AC_MSG_RESULT([(..)])
+   AX_CHECK_DATA_MODEL
+fi
+
+if test "_$ac_cv_header_stdint_x" != "_" ; then
+   ac_cv_header_stdint="$ac_cv_header_stdint_x"
+elif  test "_$ac_cv_header_stdint_o" != "_" ; then
+   ac_cv_header_stdint="$ac_cv_header_stdint_o"
+elif  test "_$ac_cv_header_stdint_u" != "_" ; then
+   ac_cv_header_stdint="$ac_cv_header_stdint_u"
+else
+   ac_cv_header_stdint="stddef.h"
+fi
+
+AC_MSG_CHECKING([for extra inttypes in chosen header])
+AC_MSG_RESULT([($ac_cv_header_stdint)])
+dnl see if int_least and int_fast types are present in _this_ header.
+unset ac_cv_type_int_least32_t
+unset ac_cv_type_int_fast32_t
+AC_CHECK_TYPE(int_least32_t,,,[#include <$ac_cv_header_stdint>])
+AC_CHECK_TYPE(int_fast32_t,,,[#include<$ac_cv_header_stdint>])
+AC_CHECK_TYPE(intmax_t,,,[#include <$ac_cv_header_stdint>])
+
+fi # shortcircut to system "stdint.h"
+# ------------------ PREPARE VARIABLES ------------------------------
+if test "$GCC" = "yes" ; then
+ac_cv_stdint_message="using gnu compiler "`$CC --version | head -1`
+else
+ac_cv_stdint_message="using $CC"
+fi
+
+AC_MSG_RESULT([make use of $ac_cv_header_stdint in $ac_stdint_h dnl
+$ac_cv_stdint_result])
+
+dnl -----------------------------------------------------------------
+# ----------------- DONE inttypes.h checks START header -------------
+AC_CONFIG_COMMANDS([$ac_stdint_h],[
+AC_MSG_NOTICE(creating $ac_stdint_h : $_ac_stdint_h)
+ac_stdint=$tmp/_stdint.h
+
+echo "#ifndef" $_ac_stdint_h >$ac_stdint
+echo "#define" $_ac_stdint_h "1" >>$ac_stdint
+echo "#ifndef" _GENERATED_STDINT_H >>$ac_stdint
+echo "#define" _GENERATED_STDINT_H '"'$PACKAGE $VERSION'"' >>$ac_stdint
+echo "/* generated $ac_cv_stdint_message */" >>$ac_stdint
+if test "_$ac_cv_header_stdint_t" != "_" ; then
+echo "#define _STDINT_HAVE_STDINT_H" "1" >>$ac_stdint
+echo "#include <stdint.h>" >>$ac_stdint
+echo "#endif" >>$ac_stdint
+echo "#endif" >>$ac_stdint
+else
+
+cat >>$ac_stdint <<STDINT_EOF
+
+/* ................... shortcircuit part ........................... */
+
+#if defined HAVE_STDINT_H || defined _STDINT_HAVE_STDINT_H
+#include <stdint.h>
+#else
+#include <stddef.h>
+
+/* .................... configured part ............................ */
+
+STDINT_EOF
+
+echo "/* whether we have a C99 compatible stdint header file */" >>$ac_stdint
+if test "_$ac_cv_header_stdint_x" != "_" ; then
+  ac_header="$ac_cv_header_stdint_x"
+  echo "#define _STDINT_HEADER_INTPTR" '"'"$ac_header"'"' >>$ac_stdint
+else
+  echo "/* #undef _STDINT_HEADER_INTPTR */" >>$ac_stdint
+fi
+
+echo "/* whether we have a C96 compatible inttypes header file */" >>$ac_stdint
+if  test "_$ac_cv_header_stdint_o" != "_" ; then
+  ac_header="$ac_cv_header_stdint_o"
+  echo "#define _STDINT_HEADER_UINT32" '"'"$ac_header"'"' >>$ac_stdint
+else
+  echo "/* #undef _STDINT_HEADER_UINT32 */" >>$ac_stdint
+fi
+
+echo "/* whether we have a BSD compatible inet types header */" >>$ac_stdint
+if  test "_$ac_cv_header_stdint_u" != "_" ; then
+  ac_header="$ac_cv_header_stdint_u"
+  echo "#define _STDINT_HEADER_U_INT32" '"'"$ac_header"'"' >>$ac_stdint
+else
+  echo "/* #undef _STDINT_HEADER_U_INT32 */" >>$ac_stdint
+fi
+
+echo "" >>$ac_stdint
+
+if test "_$ac_header" != "_" ; then if test "$ac_header" != "stddef.h" ; then
+  echo "#include <$ac_header>" >>$ac_stdint
+  echo "" >>$ac_stdint
+fi fi
+
+echo "/* which 64bit typedef has been found */" >>$ac_stdint
+if test "$ac_cv_type_uint64_t" = "yes" ; then
+echo "#define   _STDINT_HAVE_UINT64_T" "1"  >>$ac_stdint
+else
+echo "/* #undef _STDINT_HAVE_UINT64_T */" >>$ac_stdint
+fi
+if test "$ac_cv_type_u_int64_t" = "yes" ; then
+echo "#define   _STDINT_HAVE_U_INT64_T" "1"  >>$ac_stdint
+else
+echo "/* #undef _STDINT_HAVE_U_INT64_T */" >>$ac_stdint
+fi
+echo "" >>$ac_stdint
+
+echo "/* which type model has been detected */" >>$ac_stdint
+if test "_$ac_cv_char_data_model" != "_" ; then
+echo "#define   _STDINT_CHAR_MODEL" "$ac_cv_char_data_model" >>$ac_stdint
+echo "#define   _STDINT_LONG_MODEL" "$ac_cv_long_data_model" >>$ac_stdint
+else
+echo "/* #undef _STDINT_CHAR_MODEL // skipped */" >>$ac_stdint
+echo "/* #undef _STDINT_LONG_MODEL // skipped */" >>$ac_stdint
+fi
+echo "" >>$ac_stdint
+
+echo "/* whether int_least types were detected */" >>$ac_stdint
+if test "$ac_cv_type_int_least32_t" = "yes"; then
+echo "#define   _STDINT_HAVE_INT_LEAST32_T" "1"  >>$ac_stdint
+else
+echo "/* #undef _STDINT_HAVE_INT_LEAST32_T */" >>$ac_stdint
+fi
+echo "/* whether int_fast types were detected */" >>$ac_stdint
+if test "$ac_cv_type_int_fast32_t" = "yes"; then
+echo "#define   _STDINT_HAVE_INT_FAST32_T" "1" >>$ac_stdint
+else
+echo "/* #undef _STDINT_HAVE_INT_FAST32_T */" >>$ac_stdint
+fi
+echo "/* whether intmax_t type was detected */" >>$ac_stdint
+if test "$ac_cv_type_intmax_t" = "yes"; then
+echo "#define   _STDINT_HAVE_INTMAX_T" "1" >>$ac_stdint
+else
+echo "/* #undef _STDINT_HAVE_INTMAX_T */" >>$ac_stdint
+fi
+echo "" >>$ac_stdint
+
+  cat >>$ac_stdint <<STDINT_EOF
+/* .................... detections part ............................ */
+
+/* whether we need to define bitspecific types from compiler base types */
+#ifndef _STDINT_HEADER_INTPTR
+#ifndef _STDINT_HEADER_UINT32
+#ifndef _STDINT_HEADER_U_INT32
+#define _STDINT_NEED_INT_MODEL_T
+#else
+#define _STDINT_HAVE_U_INT_TYPES
+#endif
+#endif
+#endif
+
+#ifdef _STDINT_HAVE_U_INT_TYPES
+#undef _STDINT_NEED_INT_MODEL_T
+#endif
+
+#ifdef  _STDINT_CHAR_MODEL
+#if     _STDINT_CHAR_MODEL+0 == 122 || _STDINT_CHAR_MODEL+0 == 124
+#ifndef _STDINT_BYTE_MODEL
+#define _STDINT_BYTE_MODEL 12
+#endif
+#endif
+#endif
+
+#ifndef _STDINT_HAVE_INT_LEAST32_T
+#define _STDINT_NEED_INT_LEAST_T
+#endif
+
+#ifndef _STDINT_HAVE_INT_FAST32_T
+#define _STDINT_NEED_INT_FAST_T
+#endif
+
+#ifndef _STDINT_HEADER_INTPTR
+#define _STDINT_NEED_INTPTR_T
+#ifndef _STDINT_HAVE_INTMAX_T
+#define _STDINT_NEED_INTMAX_T
+#endif
+#endif
+
+
+/* .................... definition part ............................ */
+
+/* some system headers have good uint64_t */
+#ifndef _HAVE_UINT64_T
+#if     defined _STDINT_HAVE_UINT64_T  || defined HAVE_UINT64_T
+#define _HAVE_UINT64_T
+#elif   defined _STDINT_HAVE_U_INT64_T || defined HAVE_U_INT64_T
+#define _HAVE_UINT64_T
+typedef u_int64_t uint64_t;
+#endif
+#endif
+
+#ifndef _HAVE_UINT64_T
+/* .. here are some common heuristics using compiler runtime specifics */
+#if defined __STDC_VERSION__ && defined __STDC_VERSION__ >= 199901L
+#define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+
+#elif !defined __STRICT_ANSI__
+#if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__
+#define _HAVE_UINT64_T
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+
+#elif defined __GNUC__ || defined __MWERKS__ || defined __ELF__
+/* note: all ELF-systems seem to have loff-support which needs 64-bit */
+#if !defined _NO_LONGLONG
+#define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+#endif
+
+#elif defined __alpha || (defined __mips && defined _ABIN32)
+#if !defined _NO_LONGLONG
+typedef long int64_t;
+typedef unsigned long uint64_t;
+#endif
+  /* compiler/cpu type to define int64_t */
+#endif
+#endif
+#endif
+
+#if defined _STDINT_HAVE_U_INT_TYPES
+/* int8_t int16_t int32_t defined by inet code, redeclare the u_intXX types */
+typedef u_int8_t uint8_t;
+typedef u_int16_t uint16_t;
+typedef u_int32_t uint32_t;
+
+/* glibc compatibility */
+#ifndef __int8_t_defined
+#define __int8_t_defined
+#endif
+#endif
+
+#ifdef _STDINT_NEED_INT_MODEL_T
+/* we must guess all the basic types. Apart from byte-adressable system, */
+/* there a few 32-bit-only dsp-systems that we guard with BYTE_MODEL 8-} */
+/* (btw, those nibble-addressable systems are way off, or so we assume) */
+
+dnl   /* have a look at "64bit and data size neutrality" at */
+dnl   /* http://unix.org/version2/whatsnew/login_64bit.html */
+dnl   /* (the shorthand "ILP" types always have a "P" part) */
+
+#if defined _STDINT_BYTE_MODEL
+#if _STDINT_LONG_MODEL+0 == 242
+/* 2:4:2 =  IP16 = a normal 16-bit system                */
+typedef unsigned char   uint8_t;
+typedef unsigned short  uint16_t;
+typedef unsigned long   uint32_t;
+#ifndef __int8_t_defined
+#define __int8_t_defined
+typedef          char    int8_t;
+typedef          short   int16_t;
+typedef          long    int32_t;
+#endif
+#elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL == 444
+/* 2:4:4 =  LP32 = a 32-bit system derived from a 16-bit */
+/* 4:4:4 = ILP32 = a normal 32-bit system                */
+typedef unsigned char   uint8_t;
+typedef unsigned short  uint16_t;
+typedef unsigned int    uint32_t;
+#ifndef __int8_t_defined
+#define __int8_t_defined
+typedef          char    int8_t;
+typedef          short   int16_t;
+typedef          int     int32_t;
+#endif
+#elif _STDINT_LONG_MODEL+0 == 484 || _STDINT_LONG_MODEL+0 == 488
+/* 4:8:4 =  IP32 = a 32-bit system prepared for 64-bit    */
+/* 4:8:8 =  LP64 = a normal 64-bit system                 */
+typedef unsigned char   uint8_t;
+typedef unsigned short  uint16_t;
+typedef unsigned int    uint32_t;
+#ifndef __int8_t_defined
+#define __int8_t_defined
+typedef          char    int8_t;
+typedef          short   int16_t;
+typedef          int     int32_t;
+#endif
+/* this system has a "long" of 64bit */
+#ifndef _HAVE_UINT64_T
+#define _HAVE_UINT64_T
+typedef unsigned long   uint64_t;
+typedef          long    int64_t;
+#endif
+#elif _STDINT_LONG_MODEL+0 == 448
+/*      LLP64   a 64-bit system derived from a 32-bit system */
+typedef unsigned char   uint8_t;
+typedef unsigned short  uint16_t;
+typedef unsigned int    uint32_t;
+#ifndef __int8_t_defined
+#define __int8_t_defined
+typedef          char    int8_t;
+typedef          short   int16_t;
+typedef          int     int32_t;
+#endif
+/* assuming the system has a "long long" */
+#ifndef _HAVE_UINT64_T
+#define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
+typedef unsigned long long uint64_t;
+typedef          long long  int64_t;
+#endif
+#else
+#define _STDINT_NO_INT32_T
+#endif
+#else
+#define _STDINT_NO_INT8_T
+#define _STDINT_NO_INT32_T
+#endif
+#endif
+
+/*
+ * quote from SunOS-5.8 sys/inttypes.h:
+ * Use at your own risk.  As of February 1996, the committee is squarely
+ * behind the fixed sized types; the "least" and "fast" types are still being
+ * discussed.  The probability that the "fast" types may be removed before
+ * the standard is finalized is high enough that they are not currently
+ * implemented.
+ */
+
+#if defined _STDINT_NEED_INT_LEAST_T
+typedef  int8_t    int_least8_t;
+typedef  int16_t   int_least16_t;
+typedef  int32_t   int_least32_t;
+#ifdef _HAVE_UINT64_T
+typedef  int64_t   int_least64_t;
+#endif
+
+typedef uint8_t   uint_least8_t;
+typedef uint16_t  uint_least16_t;
+typedef uint32_t  uint_least32_t;
+#ifdef _HAVE_UINT64_T
+typedef uint64_t  uint_least64_t;
+#endif
+  /* least types */
+#endif
+
+#if defined _STDINT_NEED_INT_FAST_T
+typedef  int8_t    int_fast8_t;
+typedef  int       int_fast16_t;
+typedef  int32_t   int_fast32_t;
+#ifdef _HAVE_UINT64_T
+typedef  int64_t   int_fast64_t;
+#endif
+
+typedef uint8_t   uint_fast8_t;
+typedef unsigned  uint_fast16_t;
+typedef uint32_t  uint_fast32_t;
+#ifdef _HAVE_UINT64_T
+typedef uint64_t  uint_fast64_t;
+#endif
+  /* fast types */
+#endif
+
+#ifdef _STDINT_NEED_INTMAX_T
+#ifdef _HAVE_UINT64_T
+typedef  int64_t       intmax_t;
+typedef uint64_t      uintmax_t;
+#else
+typedef          long  intmax_t;
+typedef unsigned long uintmax_t;
+#endif
+#endif
+
+#ifdef _STDINT_NEED_INTPTR_T
+#ifndef __intptr_t_defined
+#define __intptr_t_defined
+/* we encourage using "long" to store pointer values, never use "int" ! */
+#if   _STDINT_LONG_MODEL+0 == 242 || _STDINT_LONG_MODEL+0 == 484
+typedef  unsigned int   uintptr_t;
+typedef           int    intptr_t;
+#elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL+0 == 444
+typedef  unsigned long  uintptr_t;
+typedef           long   intptr_t;
+#elif _STDINT_LONG_MODEL+0 == 448 && defined _HAVE_UINT64_T
+typedef        uint64_t uintptr_t;
+typedef         int64_t  intptr_t;
+#else /* matches typical system types ILP32 and LP64 - but not IP16 or LLP64 */
+typedef  unsigned long  uintptr_t;
+typedef           long   intptr_t;
+#endif
+#endif
+#endif
+
+/* The ISO C99 standard specifies that in C++ implementations these
+   should only be defined if explicitly requested.  */
+#if !defined __cplusplus || defined __STDC_CONSTANT_MACROS
+#ifndef UINT32_C
+
+/* Signed.  */
+# define INT8_C(c)      c
+# define INT16_C(c)     c
+# define INT32_C(c)     c
+# ifdef _HAVE_LONGLONG_UINT64_T
+#  define INT64_C(c)    c ## L
+# else
+#  define INT64_C(c)    c ## LL
+# endif
+
+/* Unsigned.  */
+# define UINT8_C(c)     c ## U
+# define UINT16_C(c)    c ## U
+# define UINT32_C(c)    c ## U
+# ifdef _HAVE_LONGLONG_UINT64_T
+#  define UINT64_C(c)   c ## UL
+# else
+#  define UINT64_C(c)   c ## ULL
+# endif
+
+/* Maximal type.  */
+# ifdef _HAVE_LONGLONG_UINT64_T
+#  define INTMAX_C(c)   c ## L
+#  define UINTMAX_C(c)  c ## UL
+# else
+#  define INTMAX_C(c)   c ## LL
+#  define UINTMAX_C(c)  c ## ULL
+# endif
+
+  /* literalnumbers */
+#endif
+#endif
+
+/* These limits are merily those of a two complement byte-oriented system */
+
+/* Minimum of signed integral types.  */
+# define INT8_MIN               (-128)
+# define INT16_MIN              (-32767-1)
+# define INT32_MIN              (-2147483647-1)
+# define INT64_MIN              (-__INT64_C(9223372036854775807)-1)
+/* Maximum of signed integral types.  */
+# define INT8_MAX               (127)
+# define INT16_MAX              (32767)
+# define INT32_MAX              (2147483647)
+# define INT64_MAX              (__INT64_C(9223372036854775807))
+
+/* Maximum of unsigned integral types.  */
+# define UINT8_MAX              (255)
+# define UINT16_MAX             (65535)
+# define UINT32_MAX             (4294967295U)
+# define UINT64_MAX             (__UINT64_C(18446744073709551615))
+
+/* Minimum of signed integral types having a minimum size.  */
+# define INT_LEAST8_MIN         INT8_MIN
+# define INT_LEAST16_MIN        INT16_MIN
+# define INT_LEAST32_MIN        INT32_MIN
+# define INT_LEAST64_MIN        INT64_MIN
+/* Maximum of signed integral types having a minimum size.  */
+# define INT_LEAST8_MAX         INT8_MAX
+# define INT_LEAST16_MAX        INT16_MAX
+# define INT_LEAST32_MAX        INT32_MAX
+# define INT_LEAST64_MAX        INT64_MAX
+
+/* Maximum of unsigned integral types having a minimum size.  */
+# define UINT_LEAST8_MAX        UINT8_MAX
+# define UINT_LEAST16_MAX       UINT16_MAX
+# define UINT_LEAST32_MAX       UINT32_MAX
+# define UINT_LEAST64_MAX       UINT64_MAX
+
+  /* shortcircuit*/
+#endif
+  /* once */
+#endif
+#endif
+STDINT_EOF
+fi
+    if cmp -s $ac_stdint_h $ac_stdint 2>/dev/null; then
+      AC_MSG_NOTICE([$ac_stdint_h is unchanged])
+    else
+      ac_dir=`AS_DIRNAME(["$ac_stdint_h"])`
+      AS_MKDIR_P(["$ac_dir"])
+      rm -f $ac_stdint_h
+      mv $ac_stdint $ac_stdint_h
+    fi
+],[# variables for create stdint.h replacement
+PACKAGE="$PACKAGE"
+VERSION="$VERSION"
+ac_stdint_h="$ac_stdint_h"
+_ac_stdint_h=AS_TR_CPP(_$PACKAGE-$ac_stdint_h)
+ac_cv_stdint_message="$ac_cv_stdint_message"
+ac_cv_header_stdint_t="$ac_cv_header_stdint_t"
+ac_cv_header_stdint_x="$ac_cv_header_stdint_x"
+ac_cv_header_stdint_o="$ac_cv_header_stdint_o"
+ac_cv_header_stdint_u="$ac_cv_header_stdint_u"
+ac_cv_type_uint64_t="$ac_cv_type_uint64_t"
+ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t"
+ac_cv_char_data_model="$ac_cv_char_data_model"
+ac_cv_long_data_model="$ac_cv_long_data_model"
+ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t"
+ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t"
+ac_cv_type_intmax_t="$ac_cv_type_intmax_t"
+])
+])
diff --git a/nestegg/m4/pkg.m4 b/nestegg/m4/pkg.m4
new file mode 100644 (file)
index 0000000..996e294
--- /dev/null
@@ -0,0 +1,157 @@
+# pkg.m4 - Macros to locate and utilise pkg-config.            -*- Autoconf -*-
+#
+# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+#
+# 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.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+       AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+       _pkg_min_version=m4_default([$1], [0.9.0])
+       AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+       if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+               AC_MSG_RESULT([yes])
+       else
+               AC_MSG_RESULT([no])
+               PKG_CONFIG=""
+       fi
+
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists.  Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+#
+# Similar to PKG_CHECK_MODULES, make sure that the first instance of
+# this or PKG_CHECK_MODULES is called, or make sure to call
+# PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+    AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+  m4_ifval([$2], [$2], [:])
+m4_ifvaln([$3], [else
+  $3])dnl
+fi])
+
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$PKG_CONFIG"; then
+    if test -n "$$1"; then
+        pkg_cv_[]$1="$$1"
+    else
+        PKG_CHECK_EXISTS([$3],
+                         [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
+                        [pkg_failed=yes])
+    fi
+else
+       pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+        _PKG_SHORT_ERRORS_SUPPORTED
+        if test $_pkg_short_errors_supported = yes; then
+               $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
+        else
+               $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
+        fi
+       # Put the nasty error message in config.log where it belongs
+       echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+       ifelse([$4], , [AC_MSG_ERROR(dnl
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT
+])],
+               [AC_MSG_RESULT([no])
+                $4])
+elif test $pkg_failed = untried; then
+       ifelse([$4], , [AC_MSG_FAILURE(dnl
+[The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])],
+               [$4])
+else
+       $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+       $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+        AC_MSG_RESULT([yes])
+       ifelse([$3], , :, [$3])
+fi[]dnl
+])# PKG_CHECK_MODULES
diff --git a/nestegg/nestegg-uninstalled.pc.in b/nestegg/nestegg-uninstalled.pc.in
new file mode 100644 (file)
index 0000000..19bb680
--- /dev/null
@@ -0,0 +1,13 @@
+# nestegg uninstalled pkg-config file
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: nestegg
+Description: WebM/Matroska demuxer
+Version: @VERSION@
+Conflicts:
+Libs: -L${libdir} -lnestegg
+Cflags: -I${includedir}
diff --git a/nestegg/nestegg.pc.in b/nestegg/nestegg.pc.in
new file mode 100644 (file)
index 0000000..32c09d7
--- /dev/null
@@ -0,0 +1,13 @@
+# nestegg installed pkg-config file
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: nestegg
+Description: WebM/Matroska demuxer
+Version: @VERSION@
+Conflicts:
+Libs: -L${libdir} -lnestegg
+Cflags: -I${includedir}
diff --git a/nestegg/src/nestegg.c b/nestegg/src/nestegg.c
new file mode 100644 (file)
index 0000000..63a0e83
--- /dev/null
@@ -0,0 +1,1938 @@
+/*
+ * Copyright © 2010 Mozilla Foundation
+ *
+ * This program is made available under an ISC-style license.  See the
+ * accompanying file LICENSE for details.
+ */
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "nestegg/halloc/halloc.h"
+#include "nestegg/include/nestegg/nestegg.h"
+
+/* EBML Elements */
+#define ID_EBML                 0x1a45dfa3
+#define ID_EBML_VERSION         0x4286
+#define ID_EBML_READ_VERSION    0x42f7
+#define ID_EBML_MAX_ID_LENGTH   0x42f2
+#define ID_EBML_MAX_SIZE_LENGTH 0x42f3
+#define ID_DOCTYPE              0x4282
+#define ID_DOCTYPE_VERSION      0x4287
+#define ID_DOCTYPE_READ_VERSION 0x4285
+
+/* Global Elements */
+#define ID_VOID                 0xec
+#define ID_CRC32                0xbf
+
+/* WebMedia Elements */
+#define ID_SEGMENT              0x18538067
+
+/* Seek Head Elements */
+#define ID_SEEK_HEAD            0x114d9b74
+#define ID_SEEK                 0x4dbb
+#define ID_SEEK_ID              0x53ab
+#define ID_SEEK_POSITION        0x53ac
+
+/* Info Elements */
+#define ID_INFO                 0x1549a966
+#define ID_TIMECODE_SCALE       0x2ad7b1
+#define ID_DURATION             0x4489
+
+/* Cluster Elements */
+#define ID_CLUSTER              0x1f43b675
+#define ID_TIMECODE             0xe7
+#define ID_BLOCK_GROUP          0xa0
+#define ID_SIMPLE_BLOCK         0xa3
+
+/* BlockGroup Elements */
+#define ID_BLOCK                0xa1
+#define ID_BLOCK_DURATION       0x9b
+#define ID_REFERENCE_BLOCK      0xfb
+
+/* Tracks Elements */
+#define ID_TRACKS               0x1654ae6b
+#define ID_TRACK_ENTRY          0xae
+#define ID_TRACK_NUMBER         0xd7
+#define ID_TRACK_UID            0x73c5
+#define ID_TRACK_TYPE           0x83
+#define ID_FLAG_ENABLED         0xb9
+#define ID_FLAG_DEFAULT         0x88
+#define ID_FLAG_LACING          0x9c
+#define ID_TRACK_TIMECODE_SCALE 0x23314f
+#define ID_LANGUAGE             0x22b59c
+#define ID_CODEC_ID             0x86
+#define ID_CODEC_PRIVATE        0x63a2
+
+/* Video Elements */
+#define ID_VIDEO                0xe0
+#define ID_PIXEL_WIDTH          0xb0
+#define ID_PIXEL_HEIGHT         0xba
+#define ID_PIXEL_CROP_BOTTOM    0x54aa
+#define ID_PIXEL_CROP_TOP       0x54bb
+#define ID_PIXEL_CROP_LEFT      0x54cc
+#define ID_PIXEL_CROP_RIGHT     0x54dd
+#define ID_DISPLAY_WIDTH        0x54b0
+#define ID_DISPLAY_HEIGHT       0x54ba
+
+/* Audio Elements */
+#define ID_AUDIO                0xe1
+#define ID_SAMPLING_FREQUENCY   0xb5
+#define ID_CHANNELS             0x9f
+#define ID_BIT_DEPTH            0x6264
+
+/* Cues Elements */
+#define ID_CUES                 0x1c53bb6b
+#define ID_CUE_POINT            0xbb
+#define ID_CUE_TIME             0xb3
+#define ID_CUE_TRACK_POSITIONS  0xb7
+#define ID_CUE_TRACK            0xf7
+#define ID_CUE_CLUSTER_POSITION 0xf1
+#define ID_CUE_BLOCK_NUMBER     0x5378
+
+/* EBML Types */
+enum ebml_type_enum {
+  TYPE_UNKNOWN,
+  TYPE_MASTER,
+  TYPE_UINT,
+  TYPE_FLOAT,
+  TYPE_INT,
+  TYPE_STRING,
+  TYPE_BINARY
+};
+
+#define LIMIT_STRING            (1 << 20)
+#define LIMIT_BINARY            (1 << 24)
+#define LIMIT_BLOCK             (1 << 30)
+#define LIMIT_FRAME             (1 << 28)
+
+/* Field Flags */
+#define DESC_FLAG_NONE          0
+#define DESC_FLAG_MULTI         (1 << 0)
+#define DESC_FLAG_SUSPEND       (1 << 1)
+#define DESC_FLAG_OFFSET        (1 << 2)
+
+/* Block Header Flags */
+#define BLOCK_FLAGS_LACING      6
+
+/* Lacing Constants */
+#define LACING_NONE             0
+#define LACING_XIPH             1
+#define LACING_FIXED            2
+#define LACING_EBML             3
+
+/* Track Types */
+#define TRACK_TYPE_VIDEO        1
+#define TRACK_TYPE_AUDIO        2
+
+/* Track IDs */
+#define TRACK_ID_VP8            "V_VP8"
+#define TRACK_ID_VORBIS         "A_VORBIS"
+
+enum vint_mask {
+  MASK_NONE,
+  MASK_FIRST_BIT
+};
+
+struct ebml_binary {
+  unsigned char * data;
+  size_t length;
+};
+
+struct ebml_list_node {
+  struct ebml_list_node * next;
+  uint64_t id;
+  void * data;
+};
+
+struct ebml_list {
+  struct ebml_list_node * head;
+  struct ebml_list_node * tail;
+};
+
+struct ebml_type {
+  union ebml_value {
+    uint64_t u;
+    double f;
+    int64_t i;
+    char * s;
+    struct ebml_binary b;
+  } v;
+  enum ebml_type_enum type;
+  int read;
+};
+
+/* EBML Definitions */
+struct ebml {
+  struct ebml_type ebml_version;
+  struct ebml_type ebml_read_version;
+  struct ebml_type ebml_max_id_length;
+  struct ebml_type ebml_max_size_length;
+  struct ebml_type doctype;
+  struct ebml_type doctype_version;
+  struct ebml_type doctype_read_version;
+};
+
+/* Matroksa Definitions */
+struct seek {
+  struct ebml_type id;
+  struct ebml_type position;
+};
+
+struct seek_head {
+  struct ebml_list seek;
+};
+
+struct info {
+  struct ebml_type timecode_scale;
+  struct ebml_type duration;
+};
+
+struct block_group {
+  struct ebml_type duration;
+  struct ebml_type reference_block;
+};
+
+struct cluster {
+  struct ebml_type timecode;
+  struct ebml_list block_group;
+};
+
+struct video {
+  struct ebml_type pixel_width;
+  struct ebml_type pixel_height;
+  struct ebml_type pixel_crop_bottom;
+  struct ebml_type pixel_crop_top;
+  struct ebml_type pixel_crop_left;
+  struct ebml_type pixel_crop_right;
+  struct ebml_type display_width;
+  struct ebml_type display_height;
+};
+
+struct audio {
+  struct ebml_type sampling_frequency;
+  struct ebml_type channels;
+  struct ebml_type bit_depth;
+};
+
+struct track_entry {
+  struct ebml_type number;
+  struct ebml_type uid;
+  struct ebml_type type;
+  struct ebml_type flag_enabled;
+  struct ebml_type flag_default;
+  struct ebml_type flag_lacing;
+  struct ebml_type track_timecode_scale;
+  struct ebml_type language;
+  struct ebml_type codec_id;
+  struct ebml_type codec_private;
+  struct video video;
+  struct audio audio;
+};
+
+struct tracks {
+  struct ebml_list track_entry;
+};
+
+struct cue_track_positions {
+  struct ebml_type track;
+  struct ebml_type cluster_position;
+  struct ebml_type block_number;
+};
+
+struct cue_point {
+  struct ebml_type time;
+  struct ebml_list cue_track_positions;
+};
+
+struct cues {
+  struct ebml_list cue_point;
+};
+
+struct segment {
+  struct ebml_list seek_head;
+  struct info info;
+  struct ebml_list cluster;
+  struct tracks tracks;
+  struct cues cues;
+};
+
+/* Misc. */
+struct pool_ctx {
+  char dummy;
+};
+
+struct list_node {
+  struct list_node * previous;
+  struct ebml_element_desc * node;
+  unsigned char * data;
+};
+
+struct saved_state {
+  int64_t stream_offset;
+  struct list_node * ancestor;
+  uint64_t last_id;
+  uint64_t last_size;
+};
+
+struct frame {
+  unsigned char * data;
+  size_t length;
+  struct frame * next;
+};
+
+/* Public (opaque) Structures */
+struct nestegg {
+  nestegg_io * io;
+  nestegg_log log;
+  struct pool_ctx * alloc_pool;
+  uint64_t last_id;
+  uint64_t last_size;
+  struct list_node * ancestor;
+  struct ebml ebml;
+  struct segment segment;
+  int64_t segment_offset;
+  unsigned int track_count;
+};
+
+struct nestegg_packet {
+  uint64_t track;
+  uint64_t timecode;
+  struct frame * frame;
+};
+
+/* Element Descriptor */
+struct ebml_element_desc {
+  char const * name;
+  uint64_t id;
+  enum ebml_type_enum type;
+  size_t offset;
+  unsigned int flags;
+  struct ebml_element_desc * children;
+  size_t size;
+  size_t data_offset;
+};
+
+#define E_FIELD(ID, TYPE, STRUCT, FIELD) \
+  { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_NONE, NULL, 0, 0 }
+#define E_MASTER(ID, TYPE, STRUCT, FIELD) \
+  { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_MULTI, ne_ ## FIELD ## _elements, \
+      sizeof(struct FIELD), 0 }
+#define E_SINGLE_MASTER_O(ID, TYPE, STRUCT, FIELD) \
+  { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_OFFSET, ne_ ## FIELD ## _elements, 0, \
+      offsetof(STRUCT, FIELD ## _offset) }
+#define E_SINGLE_MASTER(ID, TYPE, STRUCT, FIELD) \
+  { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_NONE, ne_ ## FIELD ## _elements, 0, 0 }
+#define E_SUSPEND(ID, TYPE) \
+  { #ID, ID, TYPE, 0, DESC_FLAG_SUSPEND, NULL, 0, 0 }
+#define E_LAST \
+  { NULL, 0, 0, 0, DESC_FLAG_NONE, NULL, 0, 0 }
+
+/* EBML Element Lists */
+static struct ebml_element_desc ne_ebml_elements[] = {
+  E_FIELD(ID_EBML_VERSION, TYPE_UINT, struct ebml, ebml_version),
+  E_FIELD(ID_EBML_READ_VERSION, TYPE_UINT, struct ebml, ebml_read_version),
+  E_FIELD(ID_EBML_MAX_ID_LENGTH, TYPE_UINT, struct ebml, ebml_max_id_length),
+  E_FIELD(ID_EBML_MAX_SIZE_LENGTH, TYPE_UINT, struct ebml, ebml_max_size_length),
+  E_FIELD(ID_DOCTYPE, TYPE_STRING, struct ebml, doctype),
+  E_FIELD(ID_DOCTYPE_VERSION, TYPE_UINT, struct ebml, doctype_version),
+  E_FIELD(ID_DOCTYPE_READ_VERSION, TYPE_UINT, struct ebml, doctype_read_version),
+  E_LAST
+};
+
+/* WebMedia Element Lists */
+static struct ebml_element_desc ne_seek_elements[] = {
+  E_FIELD(ID_SEEK_ID, TYPE_BINARY, struct seek, id),
+  E_FIELD(ID_SEEK_POSITION, TYPE_UINT, struct seek, position),
+  E_LAST
+};
+
+static struct ebml_element_desc ne_seek_head_elements[] = {
+  E_MASTER(ID_SEEK, TYPE_MASTER, struct seek_head, seek),
+  E_LAST
+};
+
+static struct ebml_element_desc ne_info_elements[] = {
+  E_FIELD(ID_TIMECODE_SCALE, TYPE_UINT, struct info, timecode_scale),
+  E_FIELD(ID_DURATION, TYPE_FLOAT, struct info, duration),
+  E_LAST
+};
+
+static struct ebml_element_desc ne_block_group_elements[] = {
+  E_SUSPEND(ID_BLOCK, TYPE_BINARY),
+  E_FIELD(ID_BLOCK_DURATION, TYPE_UINT, struct block_group, duration),
+  E_FIELD(ID_REFERENCE_BLOCK, TYPE_INT, struct block_group, reference_block),
+  E_LAST
+};
+
+static struct ebml_element_desc ne_cluster_elements[] = {
+  E_FIELD(ID_TIMECODE, TYPE_UINT, struct cluster, timecode),
+  E_MASTER(ID_BLOCK_GROUP, TYPE_MASTER, struct cluster, block_group),
+  E_SUSPEND(ID_SIMPLE_BLOCK, TYPE_BINARY),
+  E_LAST
+};
+
+static struct ebml_element_desc ne_video_elements[] = {
+  E_FIELD(ID_PIXEL_WIDTH, TYPE_UINT, struct video, pixel_width),
+  E_FIELD(ID_PIXEL_HEIGHT, TYPE_UINT, struct video, pixel_height),
+  E_FIELD(ID_PIXEL_CROP_BOTTOM, TYPE_UINT, struct video, pixel_crop_bottom),
+  E_FIELD(ID_PIXEL_CROP_TOP, TYPE_UINT, struct video, pixel_crop_top),
+  E_FIELD(ID_PIXEL_CROP_LEFT, TYPE_UINT, struct video, pixel_crop_left),
+  E_FIELD(ID_PIXEL_CROP_RIGHT, TYPE_UINT, struct video, pixel_crop_right),
+  E_FIELD(ID_DISPLAY_WIDTH, TYPE_UINT, struct video, display_width),
+  E_FIELD(ID_DISPLAY_HEIGHT, TYPE_UINT, struct video, display_height),
+  E_LAST
+};
+
+static struct ebml_element_desc ne_audio_elements[] = {
+  E_FIELD(ID_SAMPLING_FREQUENCY, TYPE_FLOAT, struct audio, sampling_frequency),
+  E_FIELD(ID_CHANNELS, TYPE_UINT, struct audio, channels),
+  E_FIELD(ID_BIT_DEPTH, TYPE_UINT, struct audio, bit_depth),
+  E_LAST
+};
+
+static struct ebml_element_desc ne_track_entry_elements[] = {
+  E_FIELD(ID_TRACK_NUMBER, TYPE_UINT, struct track_entry, number),
+  E_FIELD(ID_TRACK_UID, TYPE_UINT, struct track_entry, uid),
+  E_FIELD(ID_TRACK_TYPE, TYPE_UINT, struct track_entry, type),
+  E_FIELD(ID_FLAG_ENABLED, TYPE_UINT, struct track_entry, flag_enabled),
+  E_FIELD(ID_FLAG_DEFAULT, TYPE_UINT, struct track_entry, flag_default),
+  E_FIELD(ID_FLAG_LACING, TYPE_UINT, struct track_entry, flag_lacing),
+  E_FIELD(ID_TRACK_TIMECODE_SCALE, TYPE_FLOAT, struct track_entry, track_timecode_scale),
+  E_FIELD(ID_LANGUAGE, TYPE_STRING, struct track_entry, language),
+  E_FIELD(ID_CODEC_ID, TYPE_STRING, struct track_entry, codec_id),
+  E_FIELD(ID_CODEC_PRIVATE, TYPE_BINARY, struct track_entry, codec_private),
+  E_SINGLE_MASTER(ID_VIDEO, TYPE_MASTER, struct track_entry, video),
+  E_SINGLE_MASTER(ID_AUDIO, TYPE_MASTER, struct track_entry, audio),
+  E_LAST
+};
+
+static struct ebml_element_desc ne_tracks_elements[] = {
+  E_MASTER(ID_TRACK_ENTRY, TYPE_MASTER, struct tracks, track_entry),
+  E_LAST
+};
+
+static struct ebml_element_desc ne_cue_track_positions_elements[] = {
+  E_FIELD(ID_CUE_TRACK, TYPE_UINT, struct cue_track_positions, track),
+  E_FIELD(ID_CUE_CLUSTER_POSITION, TYPE_UINT, struct cue_track_positions, cluster_position),
+  E_FIELD(ID_CUE_BLOCK_NUMBER, TYPE_UINT, struct cue_track_positions, block_number),
+  E_LAST
+};
+
+static struct ebml_element_desc ne_cue_point_elements[] = {
+  E_FIELD(ID_CUE_TIME, TYPE_UINT, struct cue_point, time),
+  E_MASTER(ID_CUE_TRACK_POSITIONS, TYPE_MASTER, struct cue_point, cue_track_positions),
+  E_LAST
+};
+
+static struct ebml_element_desc ne_cues_elements[] = {
+  E_MASTER(ID_CUE_POINT, TYPE_MASTER, struct cues, cue_point),
+  E_LAST
+};
+
+static struct ebml_element_desc ne_segment_elements[] = {
+  E_MASTER(ID_SEEK_HEAD, TYPE_MASTER, struct segment, seek_head),
+  E_SINGLE_MASTER(ID_INFO, TYPE_MASTER, struct segment, info),
+  E_MASTER(ID_CLUSTER, TYPE_MASTER, struct segment, cluster),
+  E_SINGLE_MASTER(ID_TRACKS, TYPE_MASTER, struct segment, tracks),
+  E_SINGLE_MASTER(ID_CUES, TYPE_MASTER, struct segment, cues),
+  E_LAST
+};
+
+static struct ebml_element_desc ne_top_level_elements[] = {
+  E_SINGLE_MASTER(ID_EBML, TYPE_MASTER, nestegg, ebml),
+  E_SINGLE_MASTER_O(ID_SEGMENT, TYPE_MASTER, nestegg, segment),
+  E_LAST
+};
+
+#undef E_FIELD
+#undef E_MASTER
+#undef E_SINGLE_MASTER_O
+#undef E_SINGLE_MASTER
+#undef E_SUSPEND
+#undef E_LAST
+
+static struct pool_ctx *
+ne_pool_init(void)
+{
+  struct pool_ctx * pool;
+
+  pool = h_malloc(sizeof(*pool));
+  if (!pool)
+    abort();
+  return pool;
+}
+
+static void
+ne_pool_destroy(struct pool_ctx * pool)
+{
+  h_free(pool);
+}
+
+static void *
+ne_pool_alloc(size_t size, struct pool_ctx * pool)
+{
+  void * p;
+
+  p = h_malloc(size);
+  if (!p)
+    abort();
+  hattach(p, pool);
+  memset(p, 0, size);
+  return p;
+}
+
+static void *
+ne_alloc(size_t size)
+{
+  void * p;
+
+  p = calloc(1, size);
+  if (!p)
+    abort();
+  return p;
+}
+
+static int
+ne_io_read(nestegg_io * io, void * buffer, size_t length)
+{
+  return io->read(buffer, length, io->userdata);
+}
+
+static int
+ne_io_seek(nestegg_io * io, int64_t offset, int whence)
+{
+  return io->seek(offset, whence, io->userdata);
+}
+
+static int
+ne_io_read_skip(nestegg_io * io, size_t length)
+{
+  size_t get;
+  unsigned char buf[8192];
+  int r = 1;
+
+  while (length > 0) {
+    get = length < sizeof(buf) ? length : sizeof(buf);
+    r = ne_io_read(io, buf, get);
+    if (r != 1)
+      break;
+    length -= get;
+  }
+
+  return r;
+}
+
+static int64_t
+ne_io_tell(nestegg_io * io)
+{
+  return io->tell(io->userdata);
+}
+
+static int
+ne_bare_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length, enum vint_mask maskflag)
+{
+  int r;
+  unsigned char b;
+  size_t maxlen = 8;
+  unsigned int count = 1, mask = 1 << 7;
+
+  r = ne_io_read(io, &b, 1);
+  if (r != 1)
+    return r;
+
+  while (count < maxlen) {
+    if ((b & mask) != 0)
+      break;
+    mask >>= 1;
+    count += 1;
+  }
+
+  if (length)
+    *length = count;
+  *value = b;
+
+  if (maskflag == MASK_FIRST_BIT)
+    *value = b & ~mask;
+
+  while (--count) {
+    r = ne_io_read(io, &b, 1);
+    if (r != 1)
+      return r;
+    *value <<= 8;
+    *value |= b;
+  }
+
+  return 1;
+}
+
+static int
+ne_read_id(nestegg_io * io, uint64_t * value, uint64_t * length)
+{
+  return ne_bare_read_vint(io, value, length, MASK_NONE);
+}
+
+static int
+ne_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length)
+{
+  return ne_bare_read_vint(io, value, length, MASK_FIRST_BIT);
+}
+
+static int
+ne_read_svint(nestegg_io * io, int64_t * value, uint64_t * length)
+{
+  int r;
+  uint64_t uvalue;
+  uint64_t ulength;
+  int64_t svint_subtr[] = {
+    0x3f, 0x1fff,
+    0xfffff, 0x7ffffff,
+    0x3ffffffffLL, 0x1ffffffffffLL,
+    0xffffffffffffLL, 0x7fffffffffffffLL
+  };
+
+  r = ne_bare_read_vint(io, &uvalue, &ulength, MASK_FIRST_BIT);
+  if (r != 1)
+    return r;
+  *value = uvalue - svint_subtr[ulength - 1];
+  if (length)
+    *length = ulength;
+  return r;
+}
+
+static int
+ne_read_uint(nestegg_io * io, uint64_t * val, uint64_t length)
+{
+  unsigned char b;
+  int r;
+
+  if (length == 0 || length > 8)
+    return -1;
+  r = ne_io_read(io, &b, 1);
+  if (r != 1)
+    return r;
+  *val = b;
+  while (--length) {
+    r = ne_io_read(io, &b, 1);
+    if (r != 1)
+      return r;
+    *val <<= 8;
+    *val |= b;
+  }
+  return 1;
+}
+
+static int
+ne_read_int(nestegg_io * io, int64_t * val, uint64_t length)
+{
+  int r;
+  uint64_t uval, base;
+
+  r = ne_read_uint(io, &uval, length);
+  if (r != 1)
+    return r;
+
+  if (length < sizeof(int64_t)) {
+    base = 1;
+    base <<= length * 8 - 1;
+    if (uval >= base) {
+        base = 1;
+        base <<= length * 8;
+    } else {
+      base = 0;
+    }
+    *val = uval - base;
+  } else {
+    *val = (int64_t) uval;
+  }
+
+  return 1;
+}
+
+static int
+ne_read_float(nestegg_io * io, double * val, uint64_t length)
+{
+  union {
+    uint64_t u;
+    float f;
+    double d;
+  } value;
+  int r;
+
+  /* length == 10 not implemented */
+  if (length != 4 && length != 8)
+    return -1;
+  r = ne_read_uint(io, &value.u, length);
+  if (r != 1)
+    return r;
+  if (length == 4)
+    *val = value.f;
+  else
+    *val = value.d;
+  return 1;
+}
+
+static int
+ne_read_string(nestegg * ctx, char ** val, uint64_t length)
+{
+  char * str;
+  int r;
+
+  if (length == 0 || length > LIMIT_STRING)
+    return -1;
+  str = ne_pool_alloc(length + 1, ctx->alloc_pool);
+  r = ne_io_read(ctx->io, (unsigned char *) str, length);
+  if (r != 1)
+    return r;
+  str[length] = '\0';
+  *val = str;
+  return 1;
+}
+
+static int
+ne_read_binary(nestegg * ctx, struct ebml_binary * val, uint64_t length)
+{
+  if (length == 0 || length > LIMIT_BINARY)
+    return -1;
+  val->data = ne_pool_alloc(length, ctx->alloc_pool);
+  val->length = length;
+  return ne_io_read(ctx->io, val->data, length);
+}
+
+static int
+ne_get_uint(struct ebml_type type, uint64_t * value)
+{
+  if (!type.read)
+    return -1;
+
+  assert(type.type == TYPE_UINT);
+
+  *value = type.v.u;
+
+  return 0;
+}
+
+static int
+ne_get_float(struct ebml_type type, double * value)
+{
+  if (!type.read)
+    return -1;
+
+  assert(type.type == TYPE_FLOAT);
+
+  *value = type.v.f;
+
+  return 0;
+}
+
+static int
+ne_get_string(struct ebml_type type, char ** value)
+{
+  if (!type.read)
+    return -1;
+
+  assert(type.type == TYPE_STRING);
+
+  *value = type.v.s;
+
+  return 0;
+}
+
+static int
+ne_get_binary(struct ebml_type type, struct ebml_binary * value)
+{
+  if (!type.read)
+    return -1;
+
+  assert(type.type == TYPE_BINARY);
+
+  *value = type.v.b;
+
+  return 0;
+}
+
+static int
+ne_is_ancestor_element(uint64_t id, struct list_node * ancestor)
+{
+  struct ebml_element_desc * element;
+
+  for (; ancestor; ancestor = ancestor->previous)
+    for (element = ancestor->node; element->id; ++element)
+      if (element->id == id)
+        return 1;
+
+  return 0;
+}
+
+static struct ebml_element_desc *
+ne_find_element(uint64_t id, struct ebml_element_desc * elements)
+{
+  struct ebml_element_desc * element;
+
+  for (element = elements; element->id; ++element)
+    if (element->id == id)
+      return element;
+
+  return NULL;
+}
+
+static void
+ne_ctx_push(nestegg * ctx, struct ebml_element_desc * ancestor, void * data)
+{
+  struct list_node * item;
+
+  item = ne_alloc(sizeof(*item));
+  item->previous = ctx->ancestor;
+  item->node = ancestor;
+  item->data = data;
+  ctx->ancestor = item;
+}
+
+static void
+ne_ctx_pop(nestegg * ctx)
+{
+  struct list_node * item;
+
+  item = ctx->ancestor;
+  ctx->ancestor = item->previous;
+  free(item);
+}
+
+static int
+ne_ctx_save(nestegg * ctx, struct saved_state * s)
+{
+  s->stream_offset = ne_io_tell(ctx->io);
+  if (s->stream_offset < 0)
+    return -1;
+  s->ancestor = ctx->ancestor;
+  s->last_id = ctx->last_id;
+  s->last_size = ctx->last_size;
+  return 0;
+}
+
+static int
+ne_ctx_restore(nestegg * ctx, struct saved_state * s)
+{
+  int r;
+
+  r = ne_io_seek(ctx->io, s->stream_offset, NESTEGG_SEEK_SET);
+  if (r != 0)
+    return -1;
+  ctx->ancestor = s->ancestor;
+  ctx->last_id = s->last_id;
+  ctx->last_size = s->last_size;
+  return 0;
+}
+
+static int
+ne_peek_element(nestegg * ctx, uint64_t * id, uint64_t * size)
+{
+  int r;
+
+  if (ctx->last_id && ctx->last_size) {
+    if (id)
+      *id = ctx->last_id;
+    if (size)
+      *size = ctx->last_size;
+    return 1;
+  }
+
+  r = ne_read_id(ctx->io, &ctx->last_id, NULL);
+  if (r != 1)
+    return r;
+
+  r = ne_read_vint(ctx->io, &ctx->last_size, NULL);
+  if (r != 1)
+    return r;
+
+  if (id)
+    *id = ctx->last_id;
+  if (size)
+    *size = ctx->last_size;
+
+  return 1;
+}
+
+static int
+ne_read_element(nestegg * ctx, uint64_t * id, uint64_t * size)
+{
+  int r;
+
+  r = ne_peek_element(ctx, id, size);
+  if (r != 1)
+    return r;
+
+  ctx->last_id = 0;
+  ctx->last_size = 0;
+
+  return 1;
+}
+
+static void
+ne_read_master(nestegg * ctx, struct ebml_element_desc * desc)
+{
+  struct ebml_list * list;
+  struct ebml_list_node * node, * oldtail;
+
+  assert(desc->type == TYPE_MASTER && desc->flags & DESC_FLAG_MULTI);
+
+  ctx->log(ctx, NESTEGG_LOG_DEBUG, "multi master element %llx (%s)",
+           desc->id, desc->name);
+
+  list = (struct ebml_list *) (ctx->ancestor->data + desc->offset);
+
+  node = ne_pool_alloc(sizeof(*node), ctx->alloc_pool);
+  node->id = desc->id;
+  node->data = ne_pool_alloc(desc->size, ctx->alloc_pool);
+
+  oldtail = list->tail;
+  if (oldtail)
+    oldtail->next = node;
+  list->tail = node;
+  if (!list->head)
+    list->head = node;
+
+  ctx->log(ctx, NESTEGG_LOG_DEBUG, " -> using data %p", node->data);
+
+  ne_ctx_push(ctx, desc->children, node->data);
+}
+
+static void
+ne_read_single_master(nestegg * ctx, struct ebml_element_desc * desc)
+{
+  assert(desc->type == TYPE_MASTER && !(desc->flags & DESC_FLAG_MULTI));
+
+  ctx->log(ctx, NESTEGG_LOG_DEBUG, "single master element %llx (%s)",
+           desc->id, desc->name);
+  ctx->log(ctx, NESTEGG_LOG_DEBUG, " -> using data %p (%u)",
+           ctx->ancestor->data + desc->offset, desc->offset);
+
+  ne_ctx_push(ctx, desc->children, ctx->ancestor->data + desc->offset);
+}
+
+static int
+ne_read_simple(nestegg * ctx, struct ebml_element_desc * desc, size_t length)
+{
+  struct ebml_type * storage;
+  int r;
+
+  storage = (struct ebml_type *) (ctx->ancestor->data + desc->offset);
+
+  if (storage->read) {
+    ctx->log(ctx, NESTEGG_LOG_DEBUG, "element %llx (%s) already read, skipping",
+             desc->id, desc->name);
+    return 0;
+  }
+
+  storage->type = desc->type;
+
+  ctx->log(ctx, NESTEGG_LOG_DEBUG, "element %llx (%s) -> %p (%u)",
+           desc->id, desc->name, storage, desc->offset);
+
+  r = -1;
+
+  switch (desc->type) {
+  case TYPE_UINT:
+    r = ne_read_uint(ctx->io, &storage->v.u, length);
+    break;
+  case TYPE_FLOAT:
+    r = ne_read_float(ctx->io, &storage->v.f, length);
+    break;
+  case TYPE_INT:
+    r = ne_read_int(ctx->io, &storage->v.i, length);
+    break;
+  case TYPE_STRING:
+    r = ne_read_string(ctx, &storage->v.s, length);
+    break;
+  case TYPE_BINARY:
+    r = ne_read_binary(ctx, &storage->v.b, length);
+    break;
+  case TYPE_MASTER:
+  case TYPE_UNKNOWN:
+    assert(0);
+    break;
+  }
+
+  if (r == 1)
+    storage->read = 1;
+
+  return r;
+}
+
+static int
+ne_parse(nestegg * ctx, struct ebml_element_desc * top_level)
+{
+  int r;
+  int64_t * data_offset;
+  uint64_t id, size;
+  struct ebml_element_desc * element;
+
+  /* loop until we need to return:
+     - hit suspend point
+     - parse complete
+     - error occurred */
+
+  /* loop over elements at current level reading them if sublevel found,
+     push ctx onto stack and continue if sublevel ended, pop ctx off stack
+     and continue */
+
+  if (!ctx->ancestor)
+    return -1;
+
+  for (;;) {
+    r = ne_peek_element(ctx, &id, &size);
+    if (r != 1)
+      break;
+
+    element = ne_find_element(id, ctx->ancestor->node);
+    if (element) {
+      if (element->flags & DESC_FLAG_SUSPEND) {
+        assert(element->type == TYPE_BINARY);
+        ctx->log(ctx, NESTEGG_LOG_DEBUG, "suspend parse at %llx", id);
+        r = 1;
+        break;
+      }
+
+      r = ne_read_element(ctx, &id, &size);
+      if (r != 1)
+        break;
+
+      if (element->flags & DESC_FLAG_OFFSET) {
+        data_offset = (int64_t *) (ctx->ancestor->data + element->data_offset);
+        *data_offset = ne_io_tell(ctx->io);
+        if (*data_offset < 0) {
+          r = -1;
+          break;
+        }
+      }
+
+      if (element->type == TYPE_MASTER) {
+        if (element->flags & DESC_FLAG_MULTI)
+          ne_read_master(ctx, element);
+        else
+          ne_read_single_master(ctx, element);
+        continue;
+      } else {
+        r = ne_read_simple(ctx, element, size);
+        if (r < 0)
+          break;
+      }
+    } else if (ne_is_ancestor_element(id, ctx->ancestor->previous)) {
+      ctx->log(ctx, NESTEGG_LOG_DEBUG, "parent element %llx", id);
+      if (top_level && ctx->ancestor->node == top_level) {
+        ctx->log(ctx, NESTEGG_LOG_DEBUG, "*** parse about to back up past top_level");
+        r = 1;
+        break;
+      }
+      ne_ctx_pop(ctx);
+    } else {
+      r = ne_read_element(ctx, &id, &size);
+      if (r != 1)
+        break;
+
+      if (id != ID_VOID && id != ID_CRC32)
+        ctx->log(ctx, NESTEGG_LOG_DEBUG, "unknown element %llx", id);
+      r = ne_io_read_skip(ctx->io, size);
+      if (r != 1)
+        break;
+    }
+  }
+
+  if (r != 1)
+    while (ctx->ancestor)
+      ne_ctx_pop(ctx);
+
+  return r;
+}
+
+static uint64_t
+ne_xiph_lace_value(unsigned char ** np)
+{
+  uint64_t lace;
+  uint64_t value;
+  unsigned char * p = *np;
+
+  lace = *p++;
+  value = lace;
+  while (lace == 255) {
+    lace = *p++;
+    value += lace;
+  }
+
+  *np = p;
+
+  return value;
+}
+
+static int
+ne_read_xiph_lace_value(nestegg_io * io, uint64_t * value, size_t * consumed)
+{
+  int r;
+  uint64_t lace;
+
+  r = ne_read_uint(io, &lace, 1);
+  if (r != 1)
+    return r;
+  *consumed += 1;
+
+  *value = lace;
+  while (lace == 255) {
+    r = ne_read_uint(io, &lace, 1);
+    if (r != 1)
+      return r;
+    *consumed += 1;
+    *value += lace;
+  }
+
+  return 1;
+}
+
+static int
+ne_read_xiph_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
+{
+  int r;
+  size_t i = 0;
+  uint64_t sum = 0;
+
+  while (--n) {
+    r = ne_read_xiph_lace_value(io, &sizes[i], read);
+    if (r != 1)
+      return r;
+    sum += sizes[i];
+    i += 1;
+  }
+
+  if (*read + sum > block)
+    return -1;
+
+  /* last frame is the remainder of the block */
+  sizes[i] = block - *read - sum;
+  return 1;
+}
+
+static int
+ne_read_ebml_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
+{
+  int r;
+  uint64_t lace, sum, length;
+  int64_t slace;
+  size_t i = 0;
+
+  r = ne_read_vint(io, &lace, &length);
+  if (r != 1)
+    return r;
+  *read += length;
+
+  sizes[i] = lace;
+  sum = sizes[i];
+
+  i += 1;
+  n -= 1;
+
+  while (--n) {
+    r = ne_read_svint(io, &slace, &length);
+    if (r != 1)
+      return r;
+    *read += length;
+    sizes[i] = sizes[i - 1] + slace;
+    sum += sizes[i];
+    i += 1;
+  }
+
+  if (*read + sum > block)
+    return -1;
+
+  /* last frame is the remainder of the block */
+  sizes[i] = block - *read - sum;
+  return 1;
+}
+
+static uint64_t
+ne_get_timecode_scale(nestegg * ctx)
+{
+  uint64_t scale;
+
+  if (ne_get_uint(ctx->segment.info.timecode_scale, &scale) != 0)
+    scale = 1000000;
+
+  return scale;
+}
+
+static struct track_entry *
+ne_find_track_entry(nestegg * ctx, unsigned int track)
+{
+  struct ebml_list_node * node;
+  unsigned int tracks = 0;
+
+  node = ctx->segment.tracks.track_entry.head;
+  while (node) {
+    assert(node->id == ID_TRACK_ENTRY);
+    if (track == tracks)
+      return node->data;
+    tracks += 1;
+    node = node->next;
+  }
+
+  return NULL;
+}
+
+static int
+ne_read_block(nestegg * ctx, uint64_t block_id, uint64_t block_size, nestegg_packet ** data)
+{
+  int r;
+  int64_t timecode, abs_timecode;
+  nestegg_packet * pkt;
+  struct cluster * cluster;
+  struct frame * f, * last;
+  struct track_entry * entry;
+  double track_scale;
+  uint64_t track, length, frame_sizes[256], cluster_tc, flags, frames, tc_scale, total;
+  unsigned int i, lacing;
+  size_t consumed = 0;
+
+  *data = NULL;
+
+  if (block_size > LIMIT_BLOCK)
+    return -1;
+
+  r = ne_read_vint(ctx->io, &track, &length);
+  if (r != 1)
+    return r;
+
+  if (track == 0 || track > ctx->track_count)
+    return -1;
+
+  consumed += length;
+
+  r = ne_read_int(ctx->io, &timecode, 2);
+  if (r != 1)
+    return r;
+
+  consumed += 2;
+
+  r = ne_read_uint(ctx->io, &flags, 1);
+  if (r != 1)
+    return r;
+
+  consumed += 1;
+
+  frames = 0;
+
+  /* flags are different between block and simpleblock, but lacing is
+     encoded the same way */
+  lacing = (flags & BLOCK_FLAGS_LACING) >> 1;
+
+  switch (lacing) {
+  case LACING_NONE:
+    frames = 1;
+    break;
+  case LACING_XIPH:
+  case LACING_FIXED:
+  case LACING_EBML:
+    r = ne_read_uint(ctx->io, &frames, 1);
+    if (r != 1)
+      return r;
+    consumed += 1;
+    frames += 1;
+  }
+
+  if (frames > 256)
+    return -1;
+
+  switch (lacing) {
+  case LACING_NONE:
+    frame_sizes[0] = block_size - consumed;
+    break;
+  case LACING_XIPH:
+    if (frames == 1)
+      return -1;
+    r = ne_read_xiph_lacing(ctx->io, block_size, &consumed, frames, frame_sizes);
+    if (r != 1)
+      return r;
+    break;
+  case LACING_FIXED:
+    if ((block_size - consumed) % frames)
+      return -1;
+    for (i = 0; i < frames; ++i)
+      frame_sizes[i] = (block_size - consumed) / frames;
+    break;
+  case LACING_EBML:
+    if (frames == 1)
+      return -1;
+    r = ne_read_ebml_lacing(ctx->io, block_size, &consumed, frames, frame_sizes);
+    if (r != 1)
+      return r;
+    break;
+  }
+
+  /* sanity check unlaced frame sizes against total block size. */
+  total = consumed;
+  for (i = 0; i < frames; ++i)
+    total += frame_sizes[i];
+  if (total > block_size)
+    return -1;
+
+  entry = ne_find_track_entry(ctx, track - 1);
+  if (!entry)
+    return -1;
+
+  track_scale = 1.0;
+
+  tc_scale = ne_get_timecode_scale(ctx);
+
+  assert(ctx->segment.cluster.tail->id == ID_CLUSTER);
+  cluster = ctx->segment.cluster.tail->data;
+  if (ne_get_uint(cluster->timecode, &cluster_tc) != 0)
+    return -1;
+
+  abs_timecode = timecode + cluster_tc;
+  if (abs_timecode < 0)
+    return -1;
+
+  pkt = ne_alloc(sizeof(*pkt));
+  pkt->track = track - 1;
+  pkt->timecode = abs_timecode * tc_scale * track_scale;
+
+  ctx->log(ctx, NESTEGG_LOG_DEBUG, "%sblock t %lld pts %f f %llx frames: %llu",
+           block_id == ID_BLOCK ? "" : "simple", pkt->track, pkt->timecode / 1e9, flags, frames);
+
+  last = NULL;
+  for (i = 0; i < frames; ++i) {
+    if (frame_sizes[i] > LIMIT_FRAME) {
+      nestegg_free_packet(pkt);
+      return -1;
+    }
+    f = ne_alloc(sizeof(*f));
+    f->data = ne_alloc(frame_sizes[i]);
+    f->length = frame_sizes[i];
+    r = ne_io_read(ctx->io, f->data, frame_sizes[i]);
+    if (r != 1) {
+      free(f->data);
+      free(f);
+      nestegg_free_packet(pkt);
+      return -1;
+    }
+
+    if (!last)
+      pkt->frame = f;
+    else
+      last->next = f;
+    last = f;
+  }
+
+  *data = pkt;
+
+  return 1;
+}
+
+static uint64_t
+ne_buf_read_id(unsigned char const * p, size_t length)
+{
+  uint64_t id = 0;
+
+  while (length--) {
+    id <<= 8;
+    id |= *p++;
+  }
+
+  return id;
+}
+
+static struct seek *
+ne_find_seek_for_id(struct ebml_list_node * seek_head, uint64_t id)
+{
+  struct ebml_list * head;
+  struct ebml_list_node * seek;
+  struct ebml_binary binary_id;
+  struct seek * s;
+
+  while (seek_head) {
+    assert(seek_head->id == ID_SEEK_HEAD);
+    head = seek_head->data;
+    seek = head->head;
+
+    while (seek) {
+      assert(seek->id == ID_SEEK);
+      s = seek->data;
+
+      if (ne_get_binary(s->id, &binary_id) == 0 &&
+          ne_buf_read_id(binary_id.data, binary_id.length) == id)
+        return s;
+
+      seek = seek->next;
+    }
+
+    seek_head = seek_head->next;
+  }
+
+  return NULL;
+}
+
+static struct cue_point *
+ne_find_cue_point_for_tstamp(struct ebml_list_node * cue_point, uint64_t scale, uint64_t tstamp)
+{
+  uint64_t time;
+  struct cue_point * c, * prev = NULL;
+
+  while (cue_point) {
+    assert(cue_point->id == ID_CUE_POINT);
+    c = cue_point->data;
+
+    if (!prev)
+      prev = c;
+
+    if (ne_get_uint(c->time, &time) == 0 && time * scale > tstamp)
+      break;
+
+    prev = cue_point->data;
+    cue_point = cue_point->next;
+  }
+
+  return prev;
+}
+
+static int
+ne_is_suspend_element(uint64_t id)
+{
+  /* this could search the tree of elements for DESC_FLAG_SUSPEND */
+  if (id == ID_SIMPLE_BLOCK || id == ID_BLOCK)
+    return 1;
+  return 0;
+}
+
+static void
+ne_null_log_callback(nestegg * ctx, unsigned int severity, char const * fmt, ...)
+{
+  if (ctx && severity && fmt)
+    return;
+}
+
+int
+nestegg_init(nestegg ** context, nestegg_io io, nestegg_log callback)
+{
+  int r;
+  uint64_t id, version, docversion;
+  struct ebml_list_node * track;
+  char * doctype;
+  nestegg * ctx = NULL;
+
+  if (!(io.read && io.seek && io.tell))
+    return -1;
+
+  ctx = ne_alloc(sizeof(*ctx));
+
+  ctx->io = ne_alloc(sizeof(*ctx->io));
+  *ctx->io = io;
+  ctx->log = callback;
+  ctx->alloc_pool = ne_pool_init();
+
+  if (!ctx->log)
+    ctx->log = ne_null_log_callback;
+
+  r = ne_peek_element(ctx, &id, NULL);
+  if (r != 1) {
+    nestegg_destroy(ctx);
+    return -1;
+  }
+
+  if (id != ID_EBML) {
+    nestegg_destroy(ctx);
+    return -1;
+  }
+
+  ctx->log(ctx, NESTEGG_LOG_DEBUG, "ctx %p", ctx);
+
+  ne_ctx_push(ctx, ne_top_level_elements, ctx);
+
+  r = ne_parse(ctx, NULL);
+
+  if (r != 1) {
+    nestegg_destroy(ctx);
+    return -1;
+  }
+
+  if (ne_get_uint(ctx->ebml.ebml_read_version, &version) != 0)
+    version = 1;
+  if (version != 1) {
+    nestegg_destroy(ctx);
+    return -1;
+  }
+
+  if (ne_get_string(ctx->ebml.doctype, &doctype) != 0)
+    doctype = "matroska";
+  if (strcmp(doctype, "webm") != 0) {
+    nestegg_destroy(ctx);
+    return -1;
+  }
+
+  if (ne_get_uint(ctx->ebml.doctype_read_version, &docversion) != 0)
+    docversion = 1;
+  if (docversion < 1 || docversion > 2) {
+    nestegg_destroy(ctx);
+    return -1;
+  }
+
+  if (!ctx->segment.tracks.track_entry.head) {
+    nestegg_destroy(ctx);
+    return -1;
+  }
+
+  track = ctx->segment.tracks.track_entry.head;
+  ctx->track_count = 0;
+
+  while (track) {
+    ctx->track_count += 1;
+    track = track->next;
+  }
+
+  *context = ctx;
+
+  return 0;
+}
+
+void
+nestegg_destroy(nestegg * ctx)
+{
+  while (ctx->ancestor)
+    ne_ctx_pop(ctx);
+  ne_pool_destroy(ctx->alloc_pool);
+  free(ctx->io);
+  free(ctx);
+}
+
+int
+nestegg_duration(nestegg * ctx, uint64_t * duration)
+{
+  uint64_t tc_scale;
+  double unscaled_duration;
+
+  if (ne_get_float(ctx->segment.info.duration, &unscaled_duration) != 0)
+    return -1;
+
+  tc_scale = ne_get_timecode_scale(ctx);
+
+  *duration = (uint64_t) (unscaled_duration * tc_scale);
+  return 0;
+}
+
+int
+nestegg_tstamp_scale(nestegg * ctx, uint64_t * scale)
+{
+  *scale = ne_get_timecode_scale(ctx);
+  return 0;
+}
+
+int
+nestegg_track_count(nestegg * ctx, unsigned int * tracks)
+{
+  *tracks = ctx->track_count;
+  return 0;
+}
+
+int
+nestegg_track_seek(nestegg * ctx, unsigned int track, uint64_t tstamp)
+{
+  int r;
+  struct cue_point * cue_point;
+  struct cue_track_positions * pos;
+  struct saved_state state;
+  struct seek * found;
+  uint64_t seek_pos, tc_scale, t, id;
+  struct ebml_list_node * node = ctx->segment.cues.cue_point.head;
+
+  /* If there are no cues loaded, check for cues element in the seek head
+     and load it. */
+  if (!node) {
+    found = ne_find_seek_for_id(ctx->segment.seek_head.head, ID_CUES);
+    if (!found)
+      return -1;
+
+    if (ne_get_uint(found->position, &seek_pos) != 0)
+      return -1;
+
+    /* Save old parser state. */
+    r = ne_ctx_save(ctx, &state);
+    if (r != 0)
+      return -1;
+
+    /* Seek and set up parser state for segment-level element (Cues). */
+    r = ne_io_seek(ctx->io, ctx->segment_offset + seek_pos, NESTEGG_SEEK_SET);
+    if (r != 0)
+      return -1;
+    ctx->last_id = 0;
+    ctx->last_size = 0;
+
+    r = ne_read_element(ctx, &id, NULL);
+    if (r != 1)
+      return -1;
+
+    if (id != ID_CUES)
+      return -1;
+
+    ctx->ancestor = NULL;
+    ne_ctx_push(ctx, ne_top_level_elements, ctx);
+    ne_ctx_push(ctx, ne_segment_elements, &ctx->segment);
+    ne_ctx_push(ctx, ne_cues_elements, &ctx->segment.cues);
+    /* parser will run until end of cues element. */
+    ctx->log(ctx, NESTEGG_LOG_DEBUG, "seek: parsing cue elements");
+    r = ne_parse(ctx, ne_cues_elements);
+    while (ctx->ancestor)
+      ne_ctx_pop(ctx);
+
+    /* Reset parser state to original state and seek back to old position. */
+    if (ne_ctx_restore(ctx, &state) != 0)
+      return -1;
+
+    if (r < 0)
+      return -1;
+  }
+
+  tc_scale = ne_get_timecode_scale(ctx);
+
+  cue_point = ne_find_cue_point_for_tstamp(ctx->segment.cues.cue_point.head, tc_scale, tstamp);
+  if (!cue_point)
+    return -1;
+
+  node = cue_point->cue_track_positions.head;
+
+  seek_pos = 0;
+
+  while (node) {
+    assert(node->id == ID_CUE_TRACK_POSITIONS);
+    pos = node->data;
+    if (ne_get_uint(pos->track, &t) == 0 && t - 1 == track) {
+      if (ne_get_uint(pos->cluster_position, &seek_pos) != 0)
+        return -1;
+      break;
+    }
+    node = node->next;
+  }
+
+  /* Seek and set up parser state for segment-level element (Cluster). */
+  r = ne_io_seek(ctx->io, ctx->segment_offset + seek_pos, NESTEGG_SEEK_SET);
+  if (r != 0)
+    return -1;
+  ctx->last_id = 0;
+  ctx->last_size = 0;
+
+  while (ctx->ancestor)
+    ne_ctx_pop(ctx);
+
+  ne_ctx_push(ctx, ne_top_level_elements, ctx);
+  ne_ctx_push(ctx, ne_segment_elements, &ctx->segment);
+  ctx->log(ctx, NESTEGG_LOG_DEBUG, "seek: parsing cluster elements");
+  r = ne_parse(ctx, NULL);
+  if (r != 1)
+    return -1;
+
+  if (!ne_is_suspend_element(ctx->last_id))
+    return -1;
+
+  return 0;
+}
+
+int
+nestegg_track_type(nestegg * ctx, unsigned int track)
+{
+  struct track_entry * entry;
+  uint64_t type;
+
+  entry = ne_find_track_entry(ctx, track);
+  if (!entry)
+    return -1;
+
+  if (ne_get_uint(entry->type, &type) != 0)
+    return -1;
+
+  if (type & TRACK_TYPE_VIDEO)
+    return NESTEGG_TRACK_VIDEO;
+
+  if (type & TRACK_TYPE_AUDIO)
+    return NESTEGG_TRACK_AUDIO;
+
+  return -1;
+}
+
+int
+nestegg_track_codec_id(nestegg * ctx, unsigned int track)
+{
+  char * codec_id;
+  struct track_entry * entry;
+
+  entry = ne_find_track_entry(ctx, track);
+  if (!entry)
+    return -1;
+
+  if (ne_get_string(entry->codec_id, &codec_id) != 0)
+    return -1;
+
+  if (strcmp(codec_id, TRACK_ID_VP8) == 0)
+    return NESTEGG_CODEC_VP8;
+
+  if (strcmp(codec_id, TRACK_ID_VORBIS) == 0)
+    return NESTEGG_CODEC_VORBIS;
+
+  return -1;
+}
+
+int
+nestegg_track_codec_data_count(nestegg * ctx, unsigned int track,
+                               unsigned int * count)
+{
+  struct track_entry * entry;
+  struct ebml_binary codec_private;
+  unsigned char * p;
+
+  *count = 0;
+
+  entry = ne_find_track_entry(ctx, track);
+  if (!entry)
+    return -1;
+
+  if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS)
+    return -1;
+
+  if (ne_get_binary(entry->codec_private, &codec_private) != 0)
+    return -1;
+
+  if (codec_private.length < 1)
+    return -1;
+
+  p = codec_private.data;
+  *count = *p + 1;
+
+  if (*count > 3)
+    return -1;
+
+  return 0;
+}
+
+int
+nestegg_track_codec_data(nestegg * ctx, unsigned int track, unsigned int item,
+                         unsigned char ** data, size_t * length)
+{
+  struct track_entry * entry;
+  struct ebml_binary codec_private;
+  uint64_t sizes[3], total;
+  unsigned char * p;
+  unsigned int count, i;
+
+  *data = NULL;
+  *length = 0;
+
+  entry = ne_find_track_entry(ctx, track);
+  if (!entry)
+    return -1;
+
+  if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS)
+    return -1;
+
+  if (ne_get_binary(entry->codec_private, &codec_private) != 0)
+    return -1;
+
+  p = codec_private.data;
+  count = *p++ + 1;
+
+  if (count > 3)
+    return -1;
+
+  i = 0;
+  total = 0;
+  while (--count) {
+    sizes[i] = ne_xiph_lace_value(&p);
+    total += sizes[i];
+    i += 1;
+  }
+  sizes[i] = codec_private.length - total - (p - codec_private.data);
+
+  for (i = 0; i < item; ++i) {
+    if (sizes[i] > LIMIT_FRAME)
+      return -1;
+    p += sizes[i];
+  }
+  *data = p;
+  *length = sizes[item];
+
+  return 0;
+}
+
+int
+nestegg_track_video_params(nestegg * ctx, unsigned int track,
+                           nestegg_video_params * params)
+{
+  struct track_entry * entry;
+  uint64_t value;
+
+  memset(params, 0, sizeof(*params));
+
+  entry = ne_find_track_entry(ctx, track);
+  if (!entry)
+    return -1;
+
+  if (nestegg_track_type(ctx, track) != NESTEGG_TRACK_VIDEO)
+    return -1;
+
+  if (ne_get_uint(entry->video.pixel_width, &value) != 0)
+    return -1;
+  params->width = value;
+
+  if (ne_get_uint(entry->video.pixel_height, &value) != 0)
+    return -1;
+  params->height = value;
+
+  value = 0;
+  ne_get_uint(entry->video.pixel_crop_bottom, &value);
+  params->crop_bottom = value;
+
+  value = 0;
+  ne_get_uint(entry->video.pixel_crop_top, &value);
+  params->crop_top = value;
+
+  value = 0;
+  ne_get_uint(entry->video.pixel_crop_left, &value);
+  params->crop_left = value;
+
+  value = 0;
+  ne_get_uint(entry->video.pixel_crop_right, &value);
+  params->crop_right = value;
+
+  value = params->width;
+  ne_get_uint(entry->video.display_width, &value);
+  params->display_width = value;
+
+  value = params->height;
+  ne_get_uint(entry->video.display_height, &value);
+  params->display_height = value;
+
+  return 0;
+}
+
+int
+nestegg_track_audio_params(nestegg * ctx, unsigned int track,
+                           nestegg_audio_params * params)
+{
+  struct track_entry * entry;
+  uint64_t value;
+
+  memset(params, 0, sizeof(*params));
+
+  entry = ne_find_track_entry(ctx, track);
+  if (!entry)
+    return -1;
+
+  if (nestegg_track_type(ctx, track) != NESTEGG_TRACK_AUDIO)
+    return -1;
+
+  params->rate = 8000;
+  ne_get_float(entry->audio.sampling_frequency, &params->rate);
+
+  value = 1;
+  ne_get_uint(entry->audio.channels, &value);
+  params->channels = value;
+
+  value = 16;
+  ne_get_uint(entry->audio.bit_depth, &value);
+  params->depth = value;
+
+  return 0;
+}
+
+int
+nestegg_read_packet(nestegg * ctx, nestegg_packet ** pkt)
+{
+  int r;
+  uint64_t id, size;
+
+  *pkt = NULL;
+
+  for (;;) {
+    r = ne_peek_element(ctx, &id, &size);
+    if (r != 1)
+      return r;
+
+    /* any suspend fields must be handled here */
+    if (ne_is_suspend_element(id)) {
+      r = ne_read_element(ctx, &id, &size);
+      if (r != 1)
+        return r;
+
+      /* the only suspend fields are blocks and simple blocks, which we
+         handle directly. */
+      r = ne_read_block(ctx, id, size, pkt);
+      return r;
+    }
+
+    r =  ne_parse(ctx, NULL);
+    if (r != 1)
+      return r;
+  }
+
+  return 1;
+}
+
+void
+nestegg_free_packet(nestegg_packet * pkt)
+{
+  struct frame * frame;
+
+  while (pkt->frame) {
+    frame = pkt->frame;
+    pkt->frame = frame->next;
+    free(frame->data);
+    free(frame);
+  }
+
+ free(pkt);
+}
+
+int
+nestegg_packet_track(nestegg_packet * pkt, unsigned int * track)
+{
+  *track = pkt->track;
+  return 0;
+}
+
+int
+nestegg_packet_tstamp(nestegg_packet * pkt, uint64_t * tstamp)
+{
+  *tstamp = pkt->timecode;
+  return 0;
+}
+
+int
+nestegg_packet_count(nestegg_packet * pkt, unsigned int * count)
+{
+  struct frame * f = pkt->frame;
+
+  *count = 0;
+
+  while (f) {
+    *count += 1;
+    f = f->next;
+  }
+
+  return 0;
+}
+
+int
+nestegg_packet_data(nestegg_packet * pkt, unsigned int item,
+                    unsigned char ** data, size_t * length)
+{
+  struct frame * f = pkt->frame;
+  unsigned int count = 0;
+
+  *data = NULL;
+  *length = 0;
+
+  while (f) {
+    if (count == item) {
+      *data = f->data;
+      *length = f->length;
+      return 0;
+    }
+    count += 1;
+    f = f->next;
+  }
+
+  return -1;
+}
diff --git a/nestegg/test/test.c b/nestegg/test/test.c
new file mode 100644 (file)
index 0000000..210b640
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * Copyright © 2010 Mozilla Foundation
+ *
+ * This program is made available under an ISC-style license.  See the
+ * accompanying file LICENSE for details.
+ */
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "nestegg/nestegg.h"
+
+#undef DEBUG
+#define SEEK_TEST
+
+static int
+stdio_read(void * p, size_t length, void * fp)
+{
+  size_t r;
+
+  r = fread(p, length, 1, fp);
+  if (r == 0 && feof(fp))
+    return 0;
+  return r == 0 ? -1 : 1;
+}
+
+static int
+stdio_seek(int64_t offset, int whence, void * fp)
+{
+  return fseek(fp, offset, whence);
+}
+
+static int64_t
+stdio_tell(void * fp)
+{
+  return ftell(fp);
+}
+
+static void
+log_callback(nestegg * ctx, unsigned int severity, char const * fmt, ...)
+{
+  va_list ap;
+  char const * sev = NULL;
+
+#ifndef DEBUG
+  if (severity < NESTEGG_LOG_WARNING)
+    return;
+#endif
+
+  switch (severity) {
+  case NESTEGG_LOG_DEBUG:
+    sev = "debug:   ";
+    break;
+  case NESTEGG_LOG_WARNING:
+    sev = "warning: ";
+    break;
+  case NESTEGG_LOG_CRITICAL:
+    sev = "critical:";
+    break;
+  default:
+    sev = "unknown: ";
+  }
+
+  fprintf(stderr, "%p %s ", (void *) ctx, sev);
+
+  va_start(ap, fmt);
+  vfprintf(stderr, fmt, ap);
+  va_end(ap);
+
+  fprintf(stderr, "\n");
+}
+
+int
+main(int argc, char * argv[])
+{
+  FILE * fp;
+  int r, type;
+  nestegg * ctx;
+  nestegg_audio_params aparams;
+  nestegg_packet * pkt;
+  nestegg_video_params vparams;
+  size_t length, size;
+  uint64_t duration, tstamp, pkt_tstamp;
+  unsigned char * codec_data, * ptr;
+  unsigned int cnt, i, j, track, tracks, pkt_cnt, pkt_track;
+  unsigned int data_items = 0;
+  nestegg_io io = {
+    stdio_read,
+    stdio_seek,
+    stdio_tell,
+    NULL
+  };
+
+  if (argc != 2)
+    return EXIT_FAILURE;
+
+  fp = fopen(argv[1], "rb");
+  if (!fp)
+    return EXIT_FAILURE;
+
+  io.userdata = fp;
+
+  ctx = NULL;
+  r = nestegg_init(&ctx, io, log_callback);
+  if (r != 0)
+    return EXIT_FAILURE;
+
+  nestegg_track_count(ctx, &tracks);
+  nestegg_duration(ctx, &duration);
+#ifdef DEBUG
+  fprintf(stderr, "media has %u tracks and duration %fs\n", tracks, duration / 1e9);
+#endif
+
+  for (i = 0; i < tracks; ++i) {
+    type = nestegg_track_type(ctx, i);
+#ifdef DEBUG
+    fprintf(stderr, "track %u: type: %d codec: %d", i,
+            type, nestegg_track_codec_id(ctx, i));
+#endif
+    nestegg_track_codec_data_count(ctx, i, &data_items);
+    for (j = 0; j < data_items; ++j) {
+      nestegg_track_codec_data(ctx, i, j, &codec_data, &length);
+#ifdef DEBUG
+      fprintf(stderr, " (%p, %u)", codec_data, (unsigned int) length);
+#endif
+    }
+    if (type == NESTEGG_TRACK_VIDEO) {
+      nestegg_track_video_params(ctx, i, &vparams);
+#ifdef DEBUG
+      fprintf(stderr, " video: %ux%u (d: %ux%u %ux%ux%ux%u)",
+              vparams.width, vparams.height,
+              vparams.display_width, vparams.display_height,
+              vparams.crop_top, vparams.crop_left, vparams.crop_bottom, vparams.crop_right);
+#endif
+    } else if (type == NESTEGG_TRACK_AUDIO) {
+      nestegg_track_audio_params(ctx, i, &aparams);
+#ifdef DEBUG
+      fprintf(stderr, " audio: %.2fhz %u bit %u channels",
+              aparams.rate, aparams.depth, aparams.channels);
+#endif
+    }
+#ifdef DEBUG
+    fprintf(stderr, "\n");
+#endif
+  }
+
+#ifdef SEEK_TEST
+#ifdef DEBUG
+  fprintf(stderr, "seek to middle\n");
+#endif
+  r = nestegg_track_seek(ctx, 0, duration / 2);
+  if (r == 0) {
+#ifdef DEBUG
+    fprintf(stderr, "middle ");
+#endif
+    r = nestegg_read_packet(ctx, &pkt);
+    if (r == 1) {
+      nestegg_packet_track(pkt, &track);
+      nestegg_packet_count(pkt, &cnt);
+      nestegg_packet_tstamp(pkt, &tstamp);
+#ifdef DEBUG
+      fprintf(stderr, "* t %u pts %f frames %u\n", track, tstamp / 1e9, cnt);
+#endif
+      nestegg_free_packet(pkt);
+    } else {
+#ifdef DEBUG
+      fprintf(stderr, "middle seek failed\n");
+#endif
+    }
+  }
+
+#ifdef DEBUG
+  fprintf(stderr, "seek to ~end\n");
+#endif
+  r = nestegg_track_seek(ctx, 0, duration - (duration / 10));
+  if (r == 0) {
+#ifdef DEBUG
+    fprintf(stderr, "end ");
+#endif
+    r = nestegg_read_packet(ctx, &pkt);
+    if (r == 1) {
+      nestegg_packet_track(pkt, &track);
+      nestegg_packet_count(pkt, &cnt);
+      nestegg_packet_tstamp(pkt, &tstamp);
+#ifdef DEBUG
+      fprintf(stderr, "* t %u pts %f frames %u\n", track, tstamp / 1e9, cnt);
+#endif
+      nestegg_free_packet(pkt);
+    } else {
+#ifdef DEBUG
+      fprintf(stderr, "end seek failed\n");
+#endif
+    }
+  }
+
+#ifdef DEBUG
+  fprintf(stderr, "seek to ~start\n");
+#endif
+  r = nestegg_track_seek(ctx, 0, duration / 10);
+  if (r == 0) {
+#ifdef DEBUG
+    fprintf(stderr, "start ");
+#endif
+    r = nestegg_read_packet(ctx, &pkt);
+    if (r == 1) {
+      nestegg_packet_track(pkt, &track);
+      nestegg_packet_count(pkt, &cnt);
+      nestegg_packet_tstamp(pkt, &tstamp);
+#ifdef DEBUG
+      fprintf(stderr, "* t %u pts %f frames %u\n", track, tstamp / 1e9, cnt);
+#endif
+      nestegg_free_packet(pkt);
+    } else {
+#ifdef DEBUG
+      fprintf(stderr, "start seek failed\n");
+#endif
+    }
+  }
+#endif
+
+  while (nestegg_read_packet(ctx, &pkt) > 0) {
+    nestegg_packet_track(pkt, &pkt_track);
+    nestegg_packet_count(pkt, &pkt_cnt);
+    nestegg_packet_tstamp(pkt, &pkt_tstamp);
+
+#ifdef DEBUG
+    fprintf(stderr, "t %u pts %f frames %u: ", pkt_track, pkt_tstamp / 1e9, pkt_cnt);
+#endif
+
+    for (i = 0; i < pkt_cnt; ++i) {
+      nestegg_packet_data(pkt, i, &ptr, &size);
+#ifdef DEBUG
+      fprintf(stderr, "%u ", (unsigned int) size);
+#endif
+    }
+#ifdef DEBUG
+    fprintf(stderr, "\n");
+#endif
+
+    nestegg_free_packet(pkt);
+  }
+
+  nestegg_destroy(ctx);
+  fclose(fp);
+
+  return EXIT_SUCCESS;
+}
diff --git a/solution.mk b/solution.mk
new file mode 100644 (file)
index 0000000..2de1d8d
--- /dev/null
@@ -0,0 +1,31 @@
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+
+vpx.sln: $(wildcard *.vcproj)
+       @echo "    [CREATE] $@"
+       $(SRC_PATH_BARE)/build/make/gen_msvs_sln.sh \
+            $(if $(filter %vpx.vcproj,$^),\
+                $(foreach vcp,$(filter-out %vpx.vcproj %gtest.vcproj %obj_int_extract.vcproj,$^),\
+                  --dep=$(vcp:.vcproj=):vpx) \
+                $(foreach vcp,$(filter %_test.vcproj,$^),\
+                  --dep=$(vcp:.vcproj=):gtest)) \
+                  --dep=vpx:obj_int_extract \
+                  --ver=$(CONFIG_VS_VERSION)\
+                  --out=$@ $^
+vpx.sln.mk: vpx.sln
+       @true
+
+PROJECTS-yes += vpx.sln vpx.sln.mk
+-include vpx.sln.mk
+
+# Always install this file, as it is an unconditional post-build rule.
+INSTALL_MAPS += src/%     $(SRC_PATH_BARE)/%
+INSTALL-SRCS-yes            += $(target).mk
diff --git a/third_party/googletest/README.webm b/third_party/googletest/README.webm
new file mode 100644 (file)
index 0000000..571d890
--- /dev/null
@@ -0,0 +1,15 @@
+URL: http://code.google.com/p/googletest/
+Version: 1.6.0
+License: BSD
+License File: COPYING
+
+Description:
+Google's framework for writing C++ tests on a variety of platforms
+(Linux, Mac OS X, Windows, Windows CE, Symbian, etc).  Based on the
+xUnit architecture.  Supports automatic test discovery, a rich set of
+assertions, user-defined assertions, death tests, fatal and non-fatal
+failures, various options for running the tests, and XML test report
+generation.
+
+Local Modifications:
+None.
\ No newline at end of file
diff --git a/third_party/googletest/gtest.mk b/third_party/googletest/gtest.mk
new file mode 100644 (file)
index 0000000..0de3113
--- /dev/null
@@ -0,0 +1 @@
+GTEST_SRCS-yes += src/gtest-all.cc 
diff --git a/third_party/googletest/src/CHANGES b/third_party/googletest/src/CHANGES
new file mode 100644 (file)
index 0000000..5919245
--- /dev/null
@@ -0,0 +1,130 @@
+Changes for 1.6.0:
+
+* New feature: ADD_FAILURE_AT() for reporting a test failure at the
+  given source location -- useful for writing testing utilities.
+* New feature: the universal value printer is moved from Google Mock
+  to Google Test.
+* New feature: type parameters and value parameters are reported in
+  the XML report now.
+* A gtest_disable_pthreads CMake option.
+* Colored output works in GNU Screen sessions now.
+* Parameters of value-parameterized tests are now printed in the
+  textual output.
+* Failures from ad hoc test assertions run before RUN_ALL_TESTS() are
+  now correctly reported.
+* Arguments of ASSERT_XY and EXPECT_XY no longer need to support << to
+  ostream.
+* More complete handling of exceptions.
+* GTEST_ASSERT_XY can be used instead of ASSERT_XY in case the latter
+  name is already used by another library.
+* --gtest_catch_exceptions is now true by default, allowing a test
+  program to continue after an exception is thrown.
+* Value-parameterized test fixtures can now derive from Test and
+  WithParamInterface<T> separately, easing conversion of legacy tests.
+* Death test messages are clearly marked to make them more
+  distinguishable from other messages.
+* Compatibility fixes for Android, Google Native Client, MinGW, HP UX,
+  PowerPC, Lucid autotools, libCStd, Sun C++, Borland C++ Builder (Code Gear),
+  IBM XL C++ (Visual Age C++), and C++0x.
+* Bug fixes and implementation clean-ups.
+* Potentially incompatible changes: disables the harmful 'make install'
+  command in autotools.
+
+Changes for 1.5.0:
+
+ * New feature: assertions can be safely called in multiple threads
+   where the pthreads library is available.
+ * New feature: predicates used inside EXPECT_TRUE() and friends
+   can now generate custom failure messages.
+ * New feature: Google Test can now be compiled as a DLL.
+ * New feature: fused source files are included.
+ * New feature: prints help when encountering unrecognized Google Test flags.
+ * Experimental feature: CMake build script (requires CMake 2.6.4+).
+ * Experimental feature: the Pump script for meta programming.
+ * double values streamed to an assertion are printed with enough precision
+   to differentiate any two different values.
+ * Google Test now works on Solaris and AIX.
+ * Build and test script improvements.
+ * Bug fixes and implementation clean-ups.
+
+ Potentially breaking changes:
+
+ * Stopped supporting VC++ 7.1 with exceptions disabled.
+ * Dropped support for 'make install'.
+
+Changes for 1.4.0:
+
+ * New feature: the event listener API
+ * New feature: test shuffling
+ * New feature: the XML report format is closer to junitreport and can
+   be parsed by Hudson now.
+ * New feature: when a test runs under Visual Studio, its failures are
+   integrated in the IDE.
+ * New feature: /MD(d) versions of VC++ projects.
+ * New feature: elapsed time for the tests is printed by default.
+ * New feature: comes with a TR1 tuple implementation such that Boost
+   is no longer needed for Combine().
+ * New feature: EXPECT_DEATH_IF_SUPPORTED macro and friends.
+ * New feature: the Xcode project can now produce static gtest
+   libraries in addition to a framework.
+ * Compatibility fixes for Solaris, Cygwin, minGW, Windows Mobile,
+   Symbian, gcc, and C++Builder.
+ * Bug fixes and implementation clean-ups.
+
+Changes for 1.3.0:
+
+ * New feature: death tests on Windows, Cygwin, and Mac.
+ * New feature: ability to use Google Test assertions in other testing
+   frameworks.
+ * New feature: ability to run disabled test via
+   --gtest_also_run_disabled_tests.
+ * New feature: the --help flag for printing the usage.
+ * New feature: access to Google Test flag values in user code.
+ * New feature: a script that packs Google Test into one .h and one
+   .cc file for easy deployment.
+ * New feature: support for distributing test functions to multiple
+   machines (requires support from the test runner).
+ * Bug fixes and implementation clean-ups.
+
+Changes for 1.2.1:
+
+ * Compatibility fixes for Linux IA-64 and IBM z/OS.
+ * Added support for using Boost and other TR1 implementations.
+ * Changes to the build scripts to support upcoming release of Google C++
+   Mocking Framework.
+ * Added Makefile to the distribution package.
+ * Improved build instructions in README.
+
+Changes for 1.2.0:
+
+ * New feature: value-parameterized tests.
+ * New feature: the ASSERT/EXPECT_(NON)FATAL_FAILURE(_ON_ALL_THREADS)
+   macros.
+ * Changed the XML report format to match JUnit/Ant's.
+ * Added tests to the Xcode project.
+ * Added scons/SConscript for building with SCons.
+ * Added src/gtest-all.cc for building Google Test from a single file.
+ * Fixed compatibility with Solaris and z/OS.
+ * Enabled running Python tests on systems with python 2.3 installed,
+   e.g. Mac OS X 10.4.
+ * Bug fixes.
+
+Changes for 1.1.0:
+
+ * New feature: type-parameterized tests.
+ * New feature: exception assertions.
+ * New feature: printing elapsed time of tests.
+ * Improved the robustness of death tests.
+ * Added an Xcode project and samples.
+ * Adjusted the output format on Windows to be understandable by Visual Studio.
+ * Minor bug fixes.
+
+Changes for 1.0.1:
+
+ * Added project files for Visual Studio 7.1.
+ * Fixed issues with compiling on Mac OS X.
+ * Fixed issues with compiling on Cygwin.
+
+Changes for 1.0.0:
+
+ * Initial Open Source release of Google Test
diff --git a/third_party/googletest/src/CMakeLists.txt b/third_party/googletest/src/CMakeLists.txt
new file mode 100644 (file)
index 0000000..0fe2654
--- /dev/null
@@ -0,0 +1,240 @@
+########################################################################
+# CMake build script for Google Test.
+#
+# To run the tests for Google Test itself on Linux, use 'make test' or
+# ctest.  You can select which tests to run using 'ctest -R regex'.
+# For more options, run 'ctest --help'.
+
+# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to
+# make it prominent in the GUI.
+option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)." OFF)
+
+# When other libraries are using a shared version of runtime libraries,
+# Google Test also has to use one.
+option(
+  gtest_force_shared_crt
+  "Use shared (DLL) run-time lib even when Google Test is built as static lib."
+  OFF)
+
+option(gtest_build_tests "Build all of gtest's own tests." OFF)
+
+option(gtest_build_samples "Build gtest's sample programs." OFF)
+
+option(gtest_disable_pthreads "Disable uses of pthreads in gtest." OFF)
+
+# Defines pre_project_set_up_hermetic_build() and set_up_hermetic_build().
+include(cmake/hermetic_build.cmake OPTIONAL)
+
+if (COMMAND pre_project_set_up_hermetic_build)
+  pre_project_set_up_hermetic_build()
+endif()
+
+########################################################################
+#
+# Project-wide settings
+
+# Name of the project.
+#
+# CMake files in this project can refer to the root source directory
+# as ${gtest_SOURCE_DIR} and to the root binary directory as
+# ${gtest_BINARY_DIR}.
+# Language "C" is required for find_package(Threads).
+project(gtest CXX C)
+cmake_minimum_required(VERSION 2.6.2)
+
+if (COMMAND set_up_hermetic_build)
+  set_up_hermetic_build()
+endif()
+
+# Define helper functions and macros used by Google Test.
+include(cmake/internal_utils.cmake)
+
+config_compiler_and_linker()  # Defined in internal_utils.cmake.
+
+# Where Google Test's .h files can be found.
+include_directories(
+  ${gtest_SOURCE_DIR}/include
+  ${gtest_SOURCE_DIR})
+
+# Where Google Test's libraries can be found.
+link_directories(${gtest_BINARY_DIR}/src)
+
+########################################################################
+#
+# Defines the gtest & gtest_main libraries.  User tests should link
+# with one of them.
+
+# Google Test libraries.  We build them using more strict warnings than what
+# are used for other targets, to ensure that gtest can be compiled by a user
+# aggressive about warnings.
+cxx_library(gtest "${cxx_strict}" src/gtest-all.cc)
+cxx_library(gtest_main "${cxx_strict}" src/gtest_main.cc)
+target_link_libraries(gtest_main gtest)
+
+########################################################################
+#
+# Samples on how to link user tests with gtest or gtest_main.
+#
+# They are not built by default.  To build them, set the
+# gtest_build_samples option to ON.  You can do it by running ccmake
+# or specifying the -Dbuild_gtest_samples=ON flag when running cmake.
+
+if (gtest_build_samples)
+  cxx_executable(sample1_unittest samples gtest_main samples/sample1.cc)
+  cxx_executable(sample2_unittest samples gtest_main samples/sample2.cc)
+  cxx_executable(sample3_unittest samples gtest_main)
+  cxx_executable(sample4_unittest samples gtest_main samples/sample4.cc)
+  cxx_executable(sample5_unittest samples gtest_main samples/sample1.cc)
+  cxx_executable(sample6_unittest samples gtest_main)
+  cxx_executable(sample7_unittest samples gtest_main)
+  cxx_executable(sample8_unittest samples gtest_main)
+  cxx_executable(sample9_unittest samples gtest)
+  cxx_executable(sample10_unittest samples gtest)
+endif()
+
+########################################################################
+#
+# Google Test's own tests.
+#
+# You can skip this section if you aren't interested in testing
+# Google Test itself.
+#
+# The tests are not built by default.  To build them, set the
+# gtest_build_tests option to ON.  You can do it by running ccmake
+# or specifying the -Dgtest_build_tests=ON flag when running cmake.
+
+if (gtest_build_tests)
+  # This must be set in the root directory for the tests to be run by
+  # 'make test' or ctest.
+  enable_testing()
+
+  ############################################################
+  # C++ tests built with standard compiler flags.
+
+  cxx_test(gtest-death-test_test gtest_main)
+  cxx_test(gtest_environment_test gtest)
+  cxx_test(gtest-filepath_test gtest_main)
+  cxx_test(gtest-linked_ptr_test gtest_main)
+  cxx_test(gtest-listener_test gtest_main)
+  cxx_test(gtest_main_unittest gtest_main)
+  cxx_test(gtest-message_test gtest_main)
+  cxx_test(gtest_no_test_unittest gtest)
+  cxx_test(gtest-options_test gtest_main)
+  cxx_test(gtest-param-test_test gtest
+    test/gtest-param-test2_test.cc)
+  cxx_test(gtest-port_test gtest_main)
+  cxx_test(gtest_pred_impl_unittest gtest_main)
+  cxx_test(gtest-printers_test gtest_main)
+  cxx_test(gtest_prod_test gtest_main
+    test/production.cc)
+  cxx_test(gtest_repeat_test gtest)
+  cxx_test(gtest_sole_header_test gtest_main)
+  cxx_test(gtest_stress_test gtest)
+  cxx_test(gtest-test-part_test gtest_main)
+  cxx_test(gtest_throw_on_failure_ex_test gtest)
+  cxx_test(gtest-typed-test_test gtest_main
+    test/gtest-typed-test2_test.cc)
+  cxx_test(gtest_unittest gtest_main)
+  cxx_test(gtest-unittest-api_test gtest)
+
+  ############################################################
+  # C++ tests built with non-standard compiler flags.
+
+  cxx_library(gtest_no_exception "${cxx_no_exception}"
+    src/gtest-all.cc)
+  cxx_library(gtest_main_no_exception "${cxx_no_exception}"
+    src/gtest-all.cc src/gtest_main.cc)
+  cxx_library(gtest_main_no_rtti "${cxx_no_rtti}"
+    src/gtest-all.cc src/gtest_main.cc)
+
+  cxx_test_with_flags(gtest-death-test_ex_nocatch_test
+    "${cxx_exception} -DGTEST_ENABLE_CATCH_EXCEPTIONS_=0"
+    gtest test/gtest-death-test_ex_test.cc)
+  cxx_test_with_flags(gtest-death-test_ex_catch_test
+    "${cxx_exception} -DGTEST_ENABLE_CATCH_EXCEPTIONS_=1"
+    gtest test/gtest-death-test_ex_test.cc)
+
+  cxx_test_with_flags(gtest_no_rtti_unittest "${cxx_no_rtti}"
+    gtest_main_no_rtti test/gtest_unittest.cc)
+
+  cxx_shared_library(gtest_dll "${cxx_default}"
+    src/gtest-all.cc src/gtest_main.cc)
+
+  cxx_executable_with_flags(gtest_dll_test_ "${cxx_default}"
+    gtest_dll test/gtest_all_test.cc)
+  set_target_properties(gtest_dll_test_
+                        PROPERTIES
+                        COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
+
+  if (NOT MSVC OR NOT MSVC_VERSION EQUAL 1600)
+    # The C++ Standard specifies tuple_element<int, class>.
+    # Yet MSVC 10's <utility> declares tuple_element<size_t, class>.
+    # That declaration conflicts with our own standard-conforming
+    # tuple implementation.  Therefore using our own tuple with
+    # MSVC 10 doesn't compile.
+    cxx_library(gtest_main_use_own_tuple "${cxx_use_own_tuple}"
+      src/gtest-all.cc src/gtest_main.cc)
+
+    cxx_test_with_flags(gtest-tuple_test "${cxx_use_own_tuple}"
+      gtest_main_use_own_tuple test/gtest-tuple_test.cc)
+
+    cxx_test_with_flags(gtest_use_own_tuple_test "${cxx_use_own_tuple}"
+      gtest_main_use_own_tuple
+      test/gtest-param-test_test.cc test/gtest-param-test2_test.cc)
+  endif()
+
+  ############################################################
+  # Python tests.
+
+  cxx_executable(gtest_break_on_failure_unittest_ test gtest)
+  py_test(gtest_break_on_failure_unittest)
+
+  cxx_executable_with_flags(
+    gtest_catch_exceptions_no_ex_test_
+    "${cxx_no_exception}"
+    gtest_main_no_exception
+    test/gtest_catch_exceptions_test_.cc)
+  cxx_executable_with_flags(
+    gtest_catch_exceptions_ex_test_
+    "${cxx_exception}"
+    gtest_main
+    test/gtest_catch_exceptions_test_.cc)
+  py_test(gtest_catch_exceptions_test)
+
+  cxx_executable(gtest_color_test_ test gtest)
+  py_test(gtest_color_test)
+
+  cxx_executable(gtest_env_var_test_ test gtest)
+  py_test(gtest_env_var_test)
+
+  cxx_executable(gtest_filter_unittest_ test gtest)
+  py_test(gtest_filter_unittest)
+
+  cxx_executable(gtest_help_test_ test gtest_main)
+  py_test(gtest_help_test)
+
+  cxx_executable(gtest_list_tests_unittest_ test gtest)
+  py_test(gtest_list_tests_unittest)
+
+  cxx_executable(gtest_output_test_ test gtest)
+  py_test(gtest_output_test)
+
+  cxx_executable(gtest_shuffle_test_ test gtest)
+  py_test(gtest_shuffle_test)
+
+  cxx_executable(gtest_throw_on_failure_test_ test gtest_no_exception)
+  set_target_properties(gtest_throw_on_failure_test_
+    PROPERTIES
+    COMPILE_FLAGS "${cxx_no_exception}")
+  py_test(gtest_throw_on_failure_test)
+
+  cxx_executable(gtest_uninitialized_test_ test gtest)
+  py_test(gtest_uninitialized_test)
+
+  cxx_executable(gtest_xml_outfile1_test_ test gtest_main)
+  cxx_executable(gtest_xml_outfile2_test_ test gtest_main)
+  py_test(gtest_xml_outfiles_test)
+
+  cxx_executable(gtest_xml_output_unittest_ test gtest)
+  py_test(gtest_xml_output_unittest)
+endif()
diff --git a/third_party/googletest/src/CONTRIBUTORS b/third_party/googletest/src/CONTRIBUTORS
new file mode 100644 (file)
index 0000000..feae2fc
--- /dev/null
@@ -0,0 +1,37 @@
+# This file contains a list of people who've made non-trivial
+# contribution to the Google C++ Testing Framework project.  People
+# who commit code to the project are encouraged to add their names
+# here.  Please keep the list sorted by first names.
+
+Ajay Joshi <jaj@google.com>
+Balázs Dán <balazs.dan@gmail.com>
+Bharat Mediratta <bharat@menalto.com>
+Chandler Carruth <chandlerc@google.com>
+Chris Prince <cprince@google.com>
+Chris Taylor <taylorc@google.com>
+Dan Egnor <egnor@google.com>
+Eric Roman <eroman@chromium.org>
+Hady Zalek <hady.zalek@gmail.com>
+Jeffrey Yasskin <jyasskin@google.com>
+Jói Sigurðsson <joi@google.com>
+Keir Mierle <mierle@gmail.com>
+Keith Ray <keith.ray@gmail.com>
+Kenton Varda <kenton@google.com>
+Manuel Klimek <klimek@google.com>
+Markus Heule <markus.heule@gmail.com>
+Mika Raento <mikie@iki.fi>
+Miklós Fazekas <mfazekas@szemafor.com>
+Pasi Valminen <pasi.valminen@gmail.com>
+Patrick Hanna <phanna@google.com>
+Patrick Riley <pfr@google.com>
+Peter Kaminski <piotrk@google.com>
+Preston Jackson <preston.a.jackson@gmail.com>
+Rainer Klaffenboeck <rainer.klaffenboeck@dynatrace.com>
+Russ Cox <rsc@google.com>
+Russ Rufer <russ@pentad.com>
+Sean Mcafee <eefacm@gmail.com>
+Sigurður Ásgeirsson <siggi@google.com>
+Tracy Bialik <tracy@pentad.com>
+Vadim Berman <vadimb@google.com>
+Vlad Losev <vladl@google.com>
+Zhanyong Wan <wan@google.com>
diff --git a/third_party/googletest/src/COPYING b/third_party/googletest/src/COPYING
new file mode 100644 (file)
index 0000000..1941a11
--- /dev/null
@@ -0,0 +1,28 @@
+Copyright 2008, 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.
diff --git a/third_party/googletest/src/Makefile.am b/third_party/googletest/src/Makefile.am
new file mode 100644 (file)
index 0000000..cb350b7
--- /dev/null
@@ -0,0 +1,302 @@
+# Automake file
+
+ACLOCAL_AMFLAGS = -I m4
+
+# Nonstandard package files for distribution
+EXTRA_DIST = \
+  CHANGES \
+  CONTRIBUTORS \
+  include/gtest/gtest-param-test.h.pump \
+  include/gtest/internal/gtest-param-util-generated.h.pump \
+  include/gtest/internal/gtest-tuple.h.pump \
+  include/gtest/internal/gtest-type-util.h.pump \
+  make/Makefile \
+  scripts/fuse_gtest_files.py \
+  scripts/gen_gtest_pred_impl.py \
+  scripts/pump.py \
+  scripts/test/Makefile
+
+# gtest source files that we don't compile directly.  They are
+# #included by gtest-all.cc.
+GTEST_SRC = \
+  src/gtest-death-test.cc \
+  src/gtest-filepath.cc \
+  src/gtest-internal-inl.h \
+  src/gtest-port.cc \
+  src/gtest-printers.cc \
+  src/gtest-test-part.cc \
+  src/gtest-typed-test.cc \
+  src/gtest.cc
+
+EXTRA_DIST += $(GTEST_SRC)
+
+# Sample files that we don't compile.
+EXTRA_DIST += \
+  samples/prime_tables.h \
+  samples/sample2_unittest.cc \
+  samples/sample3_unittest.cc \
+  samples/sample4_unittest.cc \
+  samples/sample5_unittest.cc \
+  samples/sample6_unittest.cc \
+  samples/sample7_unittest.cc \
+  samples/sample8_unittest.cc \
+  samples/sample9_unittest.cc
+
+# C++ test files that we don't compile directly.
+EXTRA_DIST += \
+  test/gtest-death-test_ex_test.cc \
+  test/gtest-death-test_test.cc \
+  test/gtest-filepath_test.cc \
+  test/gtest-linked_ptr_test.cc \
+  test/gtest-listener_test.cc \
+  test/gtest-message_test.cc \
+  test/gtest-options_test.cc \
+  test/gtest-param-test2_test.cc \
+  test/gtest-param-test2_test.cc \
+  test/gtest-param-test_test.cc \
+  test/gtest-param-test_test.cc \
+  test/gtest-param-test_test.h \
+  test/gtest-port_test.cc \
+  test/gtest-printers_test.cc \
+  test/gtest-test-part_test.cc \
+  test/gtest-tuple_test.cc \
+  test/gtest-typed-test2_test.cc \
+  test/gtest-typed-test_test.cc \
+  test/gtest-typed-test_test.h \
+  test/gtest-unittest-api_test.cc \
+  test/gtest_break_on_failure_unittest_.cc \
+  test/gtest_catch_exceptions_test_.cc \
+  test/gtest_color_test_.cc \
+  test/gtest_env_var_test_.cc \
+  test/gtest_environment_test.cc \
+  test/gtest_filter_unittest_.cc \
+  test/gtest_help_test_.cc \
+  test/gtest_list_tests_unittest_.cc \
+  test/gtest_main_unittest.cc \
+  test/gtest_no_test_unittest.cc \
+  test/gtest_output_test_.cc \
+  test/gtest_pred_impl_unittest.cc \
+  test/gtest_prod_test.cc \
+  test/gtest_repeat_test.cc \
+  test/gtest_shuffle_test_.cc \
+  test/gtest_sole_header_test.cc \
+  test/gtest_stress_test.cc \
+  test/gtest_throw_on_failure_ex_test.cc \
+  test/gtest_throw_on_failure_test_.cc \
+  test/gtest_uninitialized_test_.cc \
+  test/gtest_unittest.cc \
+  test/gtest_unittest.cc \
+  test/gtest_xml_outfile1_test_.cc \
+  test/gtest_xml_outfile2_test_.cc \
+  test/gtest_xml_output_unittest_.cc \
+  test/production.cc \
+  test/production.h
+
+# Python tests that we don't run.
+EXTRA_DIST += \
+  test/gtest_break_on_failure_unittest.py \
+  test/gtest_catch_exceptions_test.py \
+  test/gtest_color_test.py \
+  test/gtest_env_var_test.py \
+  test/gtest_filter_unittest.py \
+  test/gtest_help_test.py \
+  test/gtest_list_tests_unittest.py \
+  test/gtest_output_test.py \
+  test/gtest_output_test_golden_lin.txt \
+  test/gtest_shuffle_test.py \
+  test/gtest_test_utils.py \
+  test/gtest_throw_on_failure_test.py \
+  test/gtest_uninitialized_test.py \
+  test/gtest_xml_outfiles_test.py \
+  test/gtest_xml_output_unittest.py \
+  test/gtest_xml_test_utils.py
+
+# CMake script
+EXTRA_DIST += \
+  CMakeLists.txt \
+  cmake/internal_utils.cmake
+
+# MSVC project files
+EXTRA_DIST += \
+  msvc/gtest-md.sln \
+  msvc/gtest-md.vcproj \
+  msvc/gtest.sln \
+  msvc/gtest.vcproj \
+  msvc/gtest_main-md.vcproj \
+  msvc/gtest_main.vcproj \
+  msvc/gtest_prod_test-md.vcproj \
+  msvc/gtest_prod_test.vcproj \
+  msvc/gtest_unittest-md.vcproj \
+  msvc/gtest_unittest.vcproj
+
+# xcode project files
+EXTRA_DIST += \
+  xcode/Config/DebugProject.xcconfig \
+  xcode/Config/FrameworkTarget.xcconfig \
+  xcode/Config/General.xcconfig \
+  xcode/Config/ReleaseProject.xcconfig \
+  xcode/Config/StaticLibraryTarget.xcconfig \
+  xcode/Config/TestTarget.xcconfig \
+  xcode/Resources/Info.plist \
+  xcode/Scripts/runtests.sh \
+  xcode/Scripts/versiongenerate.py \
+  xcode/gtest.xcodeproj/project.pbxproj
+
+# xcode sample files
+EXTRA_DIST += \
+  xcode/Samples/FrameworkSample/Info.plist \
+  xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj \
+  xcode/Samples/FrameworkSample/runtests.sh \
+  xcode/Samples/FrameworkSample/widget.cc \
+  xcode/Samples/FrameworkSample/widget.h \
+  xcode/Samples/FrameworkSample/widget_test.cc
+
+# C++Builder project files
+EXTRA_DIST += \
+  codegear/gtest.cbproj \
+  codegear/gtest.groupproj \
+  codegear/gtest_all.cc \
+  codegear/gtest_link.cc \
+  codegear/gtest_main.cbproj \
+  codegear/gtest_unittest.cbproj
+
+# Distribute and install M4 macro
+m4datadir = $(datadir)/aclocal
+m4data_DATA = m4/gtest.m4
+EXTRA_DIST += $(m4data_DATA)
+
+# We define the global AM_CPPFLAGS as everything we compile includes from these
+# directories.
+AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/include
+
+# Modifies compiler and linker flags for pthreads compatibility.
+if HAVE_PTHREADS
+  AM_CXXFLAGS = @PTHREAD_CFLAGS@ -DGTEST_HAS_PTHREAD=1
+  AM_LIBS = @PTHREAD_LIBS@
+else
+  AM_CXXFLAGS = -DGTEST_HAS_PTHREAD=0
+endif
+
+# Build rules for libraries.
+lib_LTLIBRARIES = lib/libgtest.la lib/libgtest_main.la
+
+lib_libgtest_la_SOURCES = src/gtest-all.cc
+
+pkginclude_HEADERS = \
+  include/gtest/gtest-death-test.h \
+  include/gtest/gtest-message.h \
+  include/gtest/gtest-param-test.h \
+  include/gtest/gtest-printers.h \
+  include/gtest/gtest-spi.h \
+  include/gtest/gtest-test-part.h \
+  include/gtest/gtest-typed-test.h \
+  include/gtest/gtest.h \
+  include/gtest/gtest_pred_impl.h \
+  include/gtest/gtest_prod.h
+
+pkginclude_internaldir = $(pkgincludedir)/internal
+pkginclude_internal_HEADERS = \
+  include/gtest/internal/gtest-death-test-internal.h \
+  include/gtest/internal/gtest-filepath.h \
+  include/gtest/internal/gtest-internal.h \
+  include/gtest/internal/gtest-linked_ptr.h \
+  include/gtest/internal/gtest-param-util-generated.h \
+  include/gtest/internal/gtest-param-util.h \
+  include/gtest/internal/gtest-port.h \
+  include/gtest/internal/gtest-string.h \
+  include/gtest/internal/gtest-tuple.h \
+  include/gtest/internal/gtest-type-util.h
+
+lib_libgtest_main_la_SOURCES = src/gtest_main.cc
+lib_libgtest_main_la_LIBADD = lib/libgtest.la
+
+# Bulid rules for samples and tests. Automake's naming for some of
+# these variables isn't terribly obvious, so this is a brief
+# reference:
+#
+# TESTS -- Programs run automatically by "make check"
+# check_PROGRAMS -- Programs built by "make check" but not necessarily run
+
+noinst_LTLIBRARIES = samples/libsamples.la
+
+samples_libsamples_la_SOURCES = \
+  samples/sample1.cc \
+  samples/sample1.h \
+  samples/sample2.cc \
+  samples/sample2.h \
+  samples/sample3-inl.h \
+  samples/sample4.cc \
+  samples/sample4.h
+
+TESTS=
+TESTS_ENVIRONMENT = GTEST_SOURCE_DIR="$(srcdir)/test" \
+                    GTEST_BUILD_DIR="$(top_builddir)/test"
+check_PROGRAMS=
+
+# A simple sample on using gtest.
+TESTS += samples/sample1_unittest
+check_PROGRAMS += samples/sample1_unittest
+samples_sample1_unittest_SOURCES = samples/sample1_unittest.cc
+samples_sample1_unittest_LDADD = lib/libgtest_main.la \
+                                 lib/libgtest.la \
+                                 samples/libsamples.la
+
+# Another sample.  It also verifies that libgtest works.
+TESTS += samples/sample10_unittest
+check_PROGRAMS += samples/sample10_unittest
+samples_sample10_unittest_SOURCES = samples/sample10_unittest.cc
+samples_sample10_unittest_LDADD = lib/libgtest.la
+
+# This tests most constructs of gtest and verifies that libgtest_main
+# and libgtest work.
+TESTS += test/gtest_all_test
+check_PROGRAMS += test/gtest_all_test
+test_gtest_all_test_SOURCES = test/gtest_all_test.cc
+test_gtest_all_test_LDADD = lib/libgtest_main.la \
+                            lib/libgtest.la
+
+# Tests that fused gtest files compile and work.
+FUSED_GTEST_SRC = \
+  fused-src/gtest/gtest-all.cc \
+  fused-src/gtest/gtest.h \
+  fused-src/gtest/gtest_main.cc
+
+TESTS += test/fused_gtest_test
+check_PROGRAMS += test/fused_gtest_test
+test_fused_gtest_test_SOURCES = $(FUSED_GTEST_SRC) \
+                                samples/sample1.cc samples/sample1_unittest.cc
+test_fused_gtest_test_CPPFLAGS = -I"$(srcdir)/fused-src"
+
+# Build rules for putting fused Google Test files into the distribution
+# package. The user can also create those files by manually running
+# scripts/fuse_gtest_files.py.
+$(test_fused_gtest_test_SOURCES): fused-gtest
+
+fused-gtest: $(pkginclude_HEADERS) $(pkginclude_internal_HEADERS) \
+             $(GTEST_SRC) src/gtest-all.cc src/gtest_main.cc \
+             scripts/fuse_gtest_files.py
+       mkdir -p "$(srcdir)/fused-src"
+       chmod -R u+w "$(srcdir)/fused-src"
+       rm -f "$(srcdir)/fused-src/gtest/gtest-all.cc"
+       rm -f "$(srcdir)/fused-src/gtest/gtest.h"
+       "$(srcdir)/scripts/fuse_gtest_files.py" "$(srcdir)/fused-src"
+       cp -f "$(srcdir)/src/gtest_main.cc" "$(srcdir)/fused-src/gtest/"
+
+maintainer-clean-local:
+       rm -rf "$(srcdir)/fused-src"
+
+# Death tests may produce core dumps in the build directory. In case
+# this happens, clean them to keep distcleancheck happy.
+CLEANFILES = core
+
+# Disables 'make install' as installing a compiled version of Google
+# Test can lead to undefined behavior due to violation of the
+# One-Definition Rule.
+
+install-exec-local:
+       echo "'make install' is dangerous and not supported. Instead, see README for how to integrate Google Test into your build system."
+       false
+
+install-data-local:
+       echo "'make install' is dangerous and not supported. Instead, see README for how to integrate Google Test into your build system."
+       false
diff --git a/third_party/googletest/src/README b/third_party/googletest/src/README
new file mode 100644 (file)
index 0000000..51a9376
--- /dev/null
@@ -0,0 +1,424 @@
+Google C++ Testing Framework
+============================
+
+http://code.google.com/p/googletest/
+
+Overview
+--------
+
+Google's framework for writing C++ tests on a variety of platforms
+(Linux, Mac OS X, Windows, Windows CE, Symbian, etc).  Based on the
+xUnit architecture.  Supports automatic test discovery, a rich set of
+assertions, user-defined assertions, death tests, fatal and non-fatal
+failures, various options for running the tests, and XML test report
+generation.
+
+Please see the project page above for more information as well as the
+mailing list for questions, discussions, and development.  There is
+also an IRC channel on OFTC (irc.oftc.net) #gtest available.  Please
+join us!
+
+Requirements for End Users
+--------------------------
+
+Google Test is designed to have fairly minimal requirements to build
+and use with your projects, but there are some.  Currently, we support
+Linux, Windows, Mac OS X, and Cygwin.  We will also make our best
+effort to support other platforms (e.g. Solaris, AIX, and z/OS).
+However, since core members of the Google Test project have no access
+to these platforms, Google Test may have outstanding issues there.  If
+you notice any problems on your platform, please notify
+googletestframework@googlegroups.com.  Patches for fixing them are
+even more welcome!
+
+### Linux Requirements ###
+
+These are the base requirements to build and use Google Test from a source
+package (as described below):
+  * GNU-compatible Make or gmake
+  * POSIX-standard shell
+  * POSIX(-2) Regular Expressions (regex.h)
+  * A C++98-standard-compliant compiler
+
+### Windows Requirements ###
+
+  * Microsoft Visual C++ 7.1 or newer
+
+### Cygwin Requirements ###
+
+  * Cygwin 1.5.25-14 or newer
+
+### Mac OS X Requirements ###
+
+  * Mac OS X 10.4 Tiger or newer
+  * Developer Tools Installed
+
+Also, you'll need CMake 2.6.4 or higher if you want to build the
+samples using the provided CMake script, regardless of the platform.
+
+Requirements for Contributors
+-----------------------------
+
+We welcome patches.  If you plan to contribute a patch, you need to
+build Google Test and its own tests from an SVN checkout (described
+below), which has further requirements:
+
+  * Python version 2.3 or newer (for running some of the tests and
+    re-generating certain source files from templates)
+  * CMake 2.6.4 or newer
+
+Getting the Source
+------------------
+
+There are two primary ways of getting Google Test's source code: you
+can download a stable source release in your preferred archive format,
+or directly check out the source from our Subversion (SVN) repositary.
+The SVN checkout requires a few extra steps and some extra software
+packages on your system, but lets you track the latest development and
+make patches much more easily, so we highly encourage it.
+
+### Source Package ###
+
+Google Test is released in versioned source packages which can be
+downloaded from the download page [1].  Several different archive
+formats are provided, but the only difference is the tools used to
+manipulate them, and the size of the resulting file.  Download
+whichever you are most comfortable with.
+
+  [1] http://code.google.com/p/googletest/downloads/list
+
+Once the package is downloaded, expand it using whichever tools you
+prefer for that type.  This will result in a new directory with the
+name "gtest-X.Y.Z" which contains all of the source code.  Here are
+some examples on Linux:
+
+  tar -xvzf gtest-X.Y.Z.tar.gz
+  tar -xvjf gtest-X.Y.Z.tar.bz2
+  unzip gtest-X.Y.Z.zip
+
+### SVN Checkout ###
+
+To check out the main branch (also known as the "trunk") of Google
+Test, run the following Subversion command:
+
+  svn checkout http://googletest.googlecode.com/svn/trunk/ gtest-svn
+
+Setting up the Build
+--------------------
+
+To build Google Test and your tests that use it, you need to tell your
+build system where to find its headers and source files.  The exact
+way to do it depends on which build system you use, and is usually
+straightforward.
+
+### Generic Build Instructions ###
+
+Suppose you put Google Test in directory ${GTEST_DIR}.  To build it,
+create a library build target (or a project as called by Visual Studio
+and Xcode) to compile
+
+  ${GTEST_DIR}/src/gtest-all.cc
+
+with
+
+  ${GTEST_DIR}/include and ${GTEST_DIR}
+
+in the header search path.  Assuming a Linux-like system and gcc,
+something like the following will do:
+
+  g++ -I${GTEST_DIR}/include -I${GTEST_DIR} -c ${GTEST_DIR}/src/gtest-all.cc
+  ar -rv libgtest.a gtest-all.o
+
+Next, you should compile your test source file with
+${GTEST_DIR}/include in the header search path, and link it with gtest
+and any other necessary libraries:
+
+  g++ -I${GTEST_DIR}/include path/to/your_test.cc libgtest.a -o your_test
+
+As an example, the make/ directory contains a Makefile that you can
+use to build Google Test on systems where GNU make is available
+(e.g. Linux, Mac OS X, and Cygwin).  It doesn't try to build Google
+Test's own tests.  Instead, it just builds the Google Test library and
+a sample test.  You can use it as a starting point for your own build
+script.
+
+If the default settings are correct for your environment, the
+following commands should succeed:
+
+  cd ${GTEST_DIR}/make
+  make
+  ./sample1_unittest
+
+If you see errors, try to tweak the contents of make/Makefile to make
+them go away.  There are instructions in make/Makefile on how to do
+it.
+
+### Using CMake ###
+
+Google Test comes with a CMake build script (CMakeLists.txt) that can
+be used on a wide range of platforms ("C" stands for cross-platofrm.).
+If you don't have CMake installed already, you can download it for
+free from http://www.cmake.org/.
+
+CMake works by generating native makefiles or build projects that can
+be used in the compiler environment of your choice.  The typical
+workflow starts with:
+
+  mkdir mybuild       # Create a directory to hold the build output.
+  cd mybuild
+  cmake ${GTEST_DIR}  # Generate native build scripts.
+
+If you want to build Google Test's samples, you should replace the
+last command with
+
+  cmake -Dgtest_build_samples=ON ${GTEST_DIR}
+
+If you are on a *nix system, you should now see a Makefile in the
+current directory.  Just type 'make' to build gtest.
+
+If you use Windows and have Vistual Studio installed, a gtest.sln file
+and several .vcproj files will be created.  You can then build them
+using Visual Studio.
+
+On Mac OS X with Xcode installed, a .xcodeproj file will be generated.
+
+### Legacy Build Scripts ###
+
+Before settling on CMake, we have been providing hand-maintained build
+projects/scripts for Visual Studio, Xcode, and Autotools.  While we
+continue to provide them for convenience, they are not actively
+maintained any more.  We highly recommend that you follow the
+instructions in the previous two sections to integrate Google Test
+with your existing build system.
+
+If you still need to use the legacy build scripts, here's how:
+
+The msvc\ folder contains two solutions with Visual C++ projects.
+Open the gtest.sln or gtest-md.sln file using Visual Studio, and you
+are ready to build Google Test the same way you build any Visual
+Studio project.  Files that have names ending with -md use DLL
+versions of Microsoft runtime libraries (the /MD or the /MDd compiler
+option).  Files without that suffix use static versions of the runtime
+libraries (the /MT or the /MTd option).  Please note that one must use
+the same option to compile both gtest and the test code.  If you use
+Visual Studio 2005 or above, we recommend the -md version as /MD is
+the default for new projects in these versions of Visual Studio.
+
+On Mac OS X, open the gtest.xcodeproj in the xcode/ folder using
+Xcode.  Build the "gtest" target.  The universal binary framework will
+end up in your selected build directory (selected in the Xcode
+"Preferences..." -> "Building" pane and defaults to xcode/build).
+Alternatively, at the command line, enter:
+
+  xcodebuild
+
+This will build the "Release" configuration of gtest.framework in your
+default build location.  See the "xcodebuild" man page for more
+information about building different configurations and building in
+different locations.
+
+Tweaking Google Test
+--------------------
+
+Google Test can be used in diverse environments.  The default
+configuration may not work (or may not work well) out of the box in
+some environments.  However, you can easily tweak Google Test by
+defining control macros on the compiler command line.  Generally,
+these macros are named like GTEST_XYZ and you define them to either 1
+or 0 to enable or disable a certain feature.
+
+We list the most frequently used macros below.  For a complete list,
+see file include/gtest/internal/gtest-port.h.
+
+### Choosing a TR1 Tuple Library ###
+
+Some Google Test features require the C++ Technical Report 1 (TR1)
+tuple library, which is not yet available with all compilers.  The
+good news is that Google Test implements a subset of TR1 tuple that's
+enough for its own need, and will automatically use this when the
+compiler doesn't provide TR1 tuple.
+
+Usually you don't need to care about which tuple library Google Test
+uses.  However, if your project already uses TR1 tuple, you need to
+tell Google Test to use the same TR1 tuple library the rest of your
+project uses, or the two tuple implementations will clash.  To do
+that, add
+
+  -DGTEST_USE_OWN_TR1_TUPLE=0
+
+to the compiler flags while compiling Google Test and your tests.  If
+you want to force Google Test to use its own tuple library, just add
+
+  -DGTEST_USE_OWN_TR1_TUPLE=1
+
+to the compiler flags instead.
+
+If you don't want Google Test to use tuple at all, add
+
+  -DGTEST_HAS_TR1_TUPLE=0
+
+and all features using tuple will be disabled.
+
+### Multi-threaded Tests ###
+
+Google Test is thread-safe where the pthread library is available.
+After #include "gtest/gtest.h", you can check the GTEST_IS_THREADSAFE
+macro to see whether this is the case (yes if the macro is #defined to
+1, no if it's undefined.).
+
+If Google Test doesn't correctly detect whether pthread is available
+in your environment, you can force it with
+
+  -DGTEST_HAS_PTHREAD=1
+
+or
+
+  -DGTEST_HAS_PTHREAD=0
+
+When Google Test uses pthread, you may need to add flags to your
+compiler and/or linker to select the pthread library, or you'll get
+link errors.  If you use the CMake script or the deprecated Autotools
+script, this is taken care of for you.  If you use your own build
+script, you'll need to read your compiler and linker's manual to
+figure out what flags to add.
+
+### As a Shared Library (DLL) ###
+
+Google Test is compact, so most users can build and link it as a
+static library for the simplicity.  You can choose to use Google Test
+as a shared library (known as a DLL on Windows) if you prefer.
+
+To compile *gtest* as a shared library, add
+
+  -DGTEST_CREATE_SHARED_LIBRARY=1
+
+to the compiler flags.  You'll also need to tell the linker to produce
+a shared library instead - consult your linker's manual for how to do
+it.
+
+To compile your *tests* that use the gtest shared library, add
+
+  -DGTEST_LINKED_AS_SHARED_LIBRARY=1
+
+to the compiler flags.
+
+Note: while the above steps aren't technically necessary today when
+using some compilers (e.g. GCC), they may become necessary in the
+future, if we decide to improve the speed of loading the library (see
+http://gcc.gnu.org/wiki/Visibility for details).  Therefore you are
+recommended to always add the above flags when using Google Test as a
+shared library.  Otherwise a future release of Google Test may break
+your build script.
+
+### Avoiding Macro Name Clashes ###
+
+In C++, macros don't obey namespaces.  Therefore two libraries that
+both define a macro of the same name will clash if you #include both
+definitions.  In case a Google Test macro clashes with another
+library, you can force Google Test to rename its macro to avoid the
+conflict.
+
+Specifically, if both Google Test and some other code define macro
+FOO, you can add
+
+  -DGTEST_DONT_DEFINE_FOO=1
+
+to the compiler flags to tell Google Test to change the macro's name
+from FOO to GTEST_FOO.  Currently FOO can be FAIL, SUCCEED, or TEST.
+For example, with -DGTEST_DONT_DEFINE_TEST=1, you'll need to write
+
+  GTEST_TEST(SomeTest, DoesThis) { ... }
+
+instead of
+
+  TEST(SomeTest, DoesThis) { ... }
+
+in order to define a test.
+
+Upgrating from an Earlier Version
+---------------------------------
+
+We strive to keep Google Test releases backward compatible.
+Sometimes, though, we have to make some breaking changes for the
+users' long-term benefits.  This section describes what you'll need to
+do if you are upgrading from an earlier version of Google Test.
+
+### Upgrading from 1.3.0 or Earlier ###
+
+You may need to explicitly enable or disable Google Test's own TR1
+tuple library.  See the instructions in section "Choosing a TR1 Tuple
+Library".
+
+### Upgrading from 1.4.0 or Earlier ###
+
+The Autotools build script (configure + make) is no longer officially
+supportted.  You are encouraged to migrate to your own build system or
+use CMake.  If you still need to use Autotools, you can find
+instructions in the README file from Google Test 1.4.0.
+
+On platforms where the pthread library is available, Google Test uses
+it in order to be thread-safe.  See the "Multi-threaded Tests" section
+for what this means to your build script.
+
+If you use Microsoft Visual C++ 7.1 with exceptions disabled, Google
+Test will no longer compile.  This should affect very few people, as a
+large portion of STL (including <string>) doesn't compile in this mode
+anyway.  We decided to stop supporting it in order to greatly simplify
+Google Test's implementation.
+
+Developing Google Test
+----------------------
+
+This section discusses how to make your own changes to Google Test.
+
+### Testing Google Test Itself ###
+
+To make sure your changes work as intended and don't break existing
+functionality, you'll want to compile and run Google Test's own tests.
+For that you can use CMake:
+
+  mkdir mybuild
+  cd mybuild
+  cmake -Dgtest_build_tests=ON ${GTEST_DIR}
+
+Make sure you have Python installed, as some of Google Test's tests
+are written in Python.  If the cmake command complains about not being
+able to find Python ("Could NOT find PythonInterp (missing:
+PYTHON_EXECUTABLE)"), try telling it explicitly where your Python
+executable can be found:
+
+  cmake -DPYTHON_EXECUTABLE=path/to/python -Dgtest_build_tests=ON ${GTEST_DIR}
+
+Next, you can build Google Test and all of its own tests.  On *nix,
+this is usually done by 'make'.  To run the tests, do
+
+  make test
+
+All tests should pass.
+
+### Regenerating Source Files ###
+
+Some of Google Test's source files are generated from templates (not
+in the C++ sense) using a script.  A template file is named FOO.pump,
+where FOO is the name of the file it will generate.  For example, the
+file include/gtest/internal/gtest-type-util.h.pump is used to generate
+gtest-type-util.h in the same directory.
+
+Normally you don't need to worry about regenerating the source files,
+unless you need to modify them.  In that case, you should modify the
+corresponding .pump files instead and run the pump.py Python script to
+regenerate them.  You can find pump.py in the scripts/ directory.
+Read the Pump manual [2] for how to use it.
+
+  [2] http://code.google.com/p/googletest/wiki/PumpManual
+
+### Contributing a Patch ###
+
+We welcome patches.  Please read the Google Test developer's guide [3]
+for how you can contribute.  In particular, make sure you have signed
+the Contributor License Agreement, or we won't be able to accept the
+patch.
+
+  [3] http://code.google.com/p/googletest/wiki/GoogleTestDevGuide
+
+Happy testing!
diff --git a/third_party/googletest/src/build-aux/.keep b/third_party/googletest/src/build-aux/.keep
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/third_party/googletest/src/cmake/internal_utils.cmake b/third_party/googletest/src/cmake/internal_utils.cmake
new file mode 100644 (file)
index 0000000..7efc2ac
--- /dev/null
@@ -0,0 +1,216 @@
+# Defines functions and macros useful for building Google Test and
+# Google Mock.
+#
+# Note:
+#
+# - This file will be run twice when building Google Mock (once via
+#   Google Test's CMakeLists.txt, and once via Google Mock's).
+#   Therefore it shouldn't have any side effects other than defining
+#   the functions and macros.
+#
+# - The functions/macros defined in this file may depend on Google
+#   Test and Google Mock's option() definitions, and thus must be
+#   called *after* the options have been defined.
+
+# Tweaks CMake's default compiler/linker settings to suit Google Test's needs.
+#
+# This must be a macro(), as inside a function string() can only
+# update variables in the function scope.
+macro(fix_default_compiler_settings_)
+  if (MSVC)
+    # For MSVC, CMake sets certain flags to defaults we want to override.
+    # This replacement code is taken from sample in the CMake Wiki at
+    # http://www.cmake.org/Wiki/CMake_FAQ#Dynamic_Replace.
+    foreach (flag_var
+             CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+             CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+      if (NOT BUILD_SHARED_LIBS AND NOT gtest_force_shared_crt)
+        # When Google Test is built as a shared library, it should also use
+        # shared runtime libraries.  Otherwise, it may end up with multiple
+        # copies of runtime library data in different modules, resulting in
+        # hard-to-find crashes. When it is built as a static library, it is
+        # preferable to use CRT as static libraries, as we don't have to rely
+        # on CRT DLLs being available. CMake always defaults to using shared
+        # CRT libraries, so we override that default here.
+        string(REPLACE "/MD" "-MT" ${flag_var} "${${flag_var}}")
+      endif()
+
+      # We prefer more strict warning checking for building Google Test.
+      # Replaces /W3 with /W4 in defaults.
+      string(REPLACE "/W3" "-W4" ${flag_var} "${${flag_var}}")
+    endforeach()
+  endif()
+endmacro()
+
+# Defines the compiler/linker flags used to build Google Test and
+# Google Mock.  You can tweak these definitions to suit your need.  A
+# variable's value is empty before it's explicitly assigned to.
+macro(config_compiler_and_linker)
+  if (NOT gtest_disable_pthreads)
+    # Defines CMAKE_USE_PTHREADS_INIT and CMAKE_THREAD_LIBS_INIT.
+    find_package(Threads)
+  endif()
+
+  fix_default_compiler_settings_()
+  if (MSVC)
+    # Newlines inside flags variables break CMake's NMake generator.
+    # TODO(vladl@google.com): Add -RTCs and -RTCu to debug builds.
+    set(cxx_base_flags "-GS -W4 -WX -wd4127 -wd4251 -wd4275 -nologo -J -Zi")
+    set(cxx_base_flags "${cxx_base_flags} -D_UNICODE -DUNICODE -DWIN32 -D_WIN32")
+    set(cxx_base_flags "${cxx_base_flags} -DSTRICT -DWIN32_LEAN_AND_MEAN")
+    set(cxx_exception_flags "-EHsc -D_HAS_EXCEPTIONS=1")
+    set(cxx_no_exception_flags "-D_HAS_EXCEPTIONS=0")
+    set(cxx_no_rtti_flags "-GR-")
+  elseif (CMAKE_COMPILER_IS_GNUCXX)
+    set(cxx_base_flags "-Wall -Wshadow")
+    set(cxx_exception_flags "-fexceptions")
+    set(cxx_no_exception_flags "-fno-exceptions")
+    # Until version 4.3.2, GCC doesn't define a macro to indicate
+    # whether RTTI is enabled.  Therefore we define GTEST_HAS_RTTI
+    # explicitly.
+    set(cxx_no_rtti_flags "-fno-rtti -DGTEST_HAS_RTTI=0")
+    set(cxx_strict_flags "-Wextra")
+  elseif (CMAKE_CXX_COMPILER_ID STREQUAL "SunPro")
+    set(cxx_exception_flags "-features=except")
+    # Sun Pro doesn't provide macros to indicate whether exceptions and
+    # RTTI are enabled, so we define GTEST_HAS_* explicitly.
+    set(cxx_no_exception_flags "-features=no%except -DGTEST_HAS_EXCEPTIONS=0")
+    set(cxx_no_rtti_flags "-features=no%rtti -DGTEST_HAS_RTTI=0")
+  elseif (CMAKE_CXX_COMPILER_ID STREQUAL "VisualAge" OR
+      CMAKE_CXX_COMPILER_ID STREQUAL "XL")
+    # CMake 2.8 changes Visual Age's compiler ID to "XL".
+    set(cxx_exception_flags "-qeh")
+    set(cxx_no_exception_flags "-qnoeh")
+    # Until version 9.0, Visual Age doesn't define a macro to indicate
+    # whether RTTI is enabled.  Therefore we define GTEST_HAS_RTTI
+    # explicitly.
+    set(cxx_no_rtti_flags "-qnortti -DGTEST_HAS_RTTI=0")
+  elseif (CMAKE_CXX_COMPILER_ID STREQUAL "HP")
+    set(cxx_base_flags "-AA -mt")
+    set(cxx_exception_flags "-DGTEST_HAS_EXCEPTIONS=1")
+    set(cxx_no_exception_flags "+noeh -DGTEST_HAS_EXCEPTIONS=0")
+    # RTTI can not be disabled in HP aCC compiler.
+    set(cxx_no_rtti_flags "")
+  endif()
+
+  if (CMAKE_USE_PTHREADS_INIT)  # The pthreads library is available and allowed.
+    set(cxx_base_flags "${cxx_base_flags} -DGTEST_HAS_PTHREAD=1")
+  else()
+    set(cxx_base_flags "${cxx_base_flags} -DGTEST_HAS_PTHREAD=0")
+  endif()
+
+  # For building gtest's own tests and samples.
+  set(cxx_exception "${CMAKE_CXX_FLAGS} ${cxx_base_flags} ${cxx_exception_flags}")
+  set(cxx_no_exception
+    "${CMAKE_CXX_FLAGS} ${cxx_base_flags} ${cxx_no_exception_flags}")
+  set(cxx_default "${cxx_exception}")
+  set(cxx_no_rtti "${cxx_default} ${cxx_no_rtti_flags}")
+  set(cxx_use_own_tuple "${cxx_default} -DGTEST_USE_OWN_TR1_TUPLE=1")
+
+  # For building the gtest libraries.
+  set(cxx_strict "${cxx_default} ${cxx_strict_flags}")
+endmacro()
+
+# Defines the gtest & gtest_main libraries.  User tests should link
+# with one of them.
+function(cxx_library_with_type name type cxx_flags)
+  # type can be either STATIC or SHARED to denote a static or shared library.
+  # ARGN refers to additional arguments after 'cxx_flags'.
+  add_library(${name} ${type} ${ARGN})
+  set_target_properties(${name}
+    PROPERTIES
+    COMPILE_FLAGS "${cxx_flags}")
+  if (BUILD_SHARED_LIBS OR type STREQUAL "SHARED")
+    set_target_properties(${name}
+      PROPERTIES
+      COMPILE_DEFINITIONS "GTEST_CREATE_SHARED_LIBRARY=1")
+  endif()
+  if (CMAKE_USE_PTHREADS_INIT)
+    target_link_libraries(${name} ${CMAKE_THREAD_LIBS_INIT})
+  endif()
+endfunction()
+
+########################################################################
+#
+# Helper functions for creating build targets.
+
+function(cxx_shared_library name cxx_flags)
+  cxx_library_with_type(${name} SHARED "${cxx_flags}" ${ARGN})
+endfunction()
+
+function(cxx_library name cxx_flags)
+  cxx_library_with_type(${name} "" "${cxx_flags}" ${ARGN})
+endfunction()
+
+# cxx_executable_with_flags(name cxx_flags libs srcs...)
+#
+# creates a named C++ executable that depends on the given libraries and
+# is built from the given source files with the given compiler flags.
+function(cxx_executable_with_flags name cxx_flags libs)
+  add_executable(${name} ${ARGN})
+  if (cxx_flags)
+    set_target_properties(${name}
+      PROPERTIES
+      COMPILE_FLAGS "${cxx_flags}")
+  endif()
+  if (BUILD_SHARED_LIBS)
+    set_target_properties(${name}
+      PROPERTIES
+      COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
+  endif()
+  # To support mixing linking in static and dynamic libraries, link each
+  # library in with an extra call to target_link_libraries.
+  foreach (lib "${libs}")
+    target_link_libraries(${name} ${lib})
+  endforeach()
+endfunction()
+
+# cxx_executable(name dir lib srcs...)
+#
+# creates a named target that depends on the given libs and is built
+# from the given source files.  dir/name.cc is implicitly included in
+# the source file list.
+function(cxx_executable name dir libs)
+  cxx_executable_with_flags(
+    ${name} "${cxx_default}" "${libs}" "${dir}/${name}.cc" ${ARGN})
+endfunction()
+
+# Sets PYTHONINTERP_FOUND and PYTHON_EXECUTABLE.
+find_package(PythonInterp)
+
+# cxx_test_with_flags(name cxx_flags libs srcs...)
+#
+# creates a named C++ test that depends on the given libs and is built
+# from the given source files with the given compiler flags.
+function(cxx_test_with_flags name cxx_flags libs)
+  cxx_executable_with_flags(${name} "${cxx_flags}" "${libs}" ${ARGN})
+  add_test(${name} ${name})
+endfunction()
+
+# cxx_test(name libs srcs...)
+#
+# creates a named test target that depends on the given libs and is
+# built from the given source files.  Unlike cxx_test_with_flags,
+# test/name.cc is already implicitly included in the source file list.
+function(cxx_test name libs)
+  cxx_test_with_flags("${name}" "${cxx_default}" "${libs}"
+    "test/${name}.cc" ${ARGN})
+endfunction()
+
+# py_test(name)
+#
+# creates a Python test with the given name whose main module is in
+# test/name.py.  It does nothing if Python is not installed.
+function(py_test name)
+  # We are not supporting Python tests on Linux yet as they consider
+  # all Linux environments to be google3 and try to use google3 features.
+  if (PYTHONINTERP_FOUND)
+    # ${CMAKE_BINARY_DIR} is known at configuration time, so we can
+    # directly bind it from cmake. ${CTEST_CONFIGURATION_TYPE} is known
+    # only at ctest runtime (by calling ctest -c <Configuration>), so
+    # we have to escape $ to delay variable substitution here.
+    add_test(${name}
+      ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
+          --build_dir=${CMAKE_CURRENT_BINARY_DIR}/\${CTEST_CONFIGURATION_TYPE})
+  endif()
+endfunction()
diff --git a/third_party/googletest/src/codegear/gtest.cbproj b/third_party/googletest/src/codegear/gtest.cbproj
new file mode 100644 (file)
index 0000000..95c3054
--- /dev/null
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <PropertyGroup>\r
+    <ProjectGuid>{bca37a72-5b07-46cf-b44e-89f8e06451a2}</ProjectGuid>\r
+    <Config Condition="'$(Config)'==''">Release</Config>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">\r
+    <Base>true</Base>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">\r
+    <Base>true</Base>\r
+    <Cfg_1>true</Cfg_1>\r
+    <CfgParent>Base</CfgParent>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">\r
+    <Base>true</Base>\r
+    <Cfg_2>true</Cfg_2>\r
+    <CfgParent>Base</CfgParent>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Base)'!=''">\r
+    <BCC_OptimizeForSpeed>true</BCC_OptimizeForSpeed>\r
+    <OutputExt>lib</OutputExt>\r
+    <DCC_CBuilderOutput>JPHNE</DCC_CBuilderOutput>\r
+    <Defines>NO_STRICT</Defines>\r
+    <DynamicRTL>true</DynamicRTL>\r
+    <UsePackages>true</UsePackages>\r
+    <ProjectType>CppStaticLibrary</ProjectType>\r
+    <BCC_CPPCompileAlways>true</BCC_CPPCompileAlways>\r
+    <PackageImports>rtl.bpi;vcl.bpi;bcbie.bpi;vclx.bpi;vclactnband.bpi;xmlrtl.bpi;bcbsmp.bpi;dbrtl.bpi;vcldb.bpi;bdertl.bpi;vcldbx.bpi;dsnap.bpi;dsnapcon.bpi;vclib.bpi;ibxpress.bpi;adortl.bpi;dbxcds.bpi;dbexpress.bpi;DbxCommonDriver.bpi;websnap.bpi;vclie.bpi;webdsnap.bpi;inet.bpi;inetdbbde.bpi;inetdbxpress.bpi;soaprtl.bpi;Rave75VCL.bpi;teeUI.bpi;tee.bpi;teedb.bpi;IndyCore.bpi;IndySystem.bpi;IndyProtocols.bpi;IntrawebDB_90_100.bpi;Intraweb_90_100.bpi;dclZipForged11.bpi;vclZipForged11.bpi;GR32_BDS2006.bpi;GR32_DSGN_BDS2006.bpi;Jcl.bpi;JclVcl.bpi;JvCoreD11R.bpi;JvSystemD11R.bpi;JvStdCtrlsD11R.bpi;JvAppFrmD11R.bpi;JvBandsD11R.bpi;JvDBD11R.bpi;JvDlgsD11R.bpi;JvBDED11R.bpi;JvCmpD11R.bpi;JvCryptD11R.bpi;JvCtrlsD11R.bpi;JvCustomD11R.bpi;JvDockingD11R.bpi;JvDotNetCtrlsD11R.bpi;JvEDID11R.bpi;JvGlobusD11R.bpi;JvHMID11R.bpi;JvInterpreterD11R.bpi;JvJansD11R.bpi;JvManagedThreadsD11R.bpi;JvMMD11R.bpi;JvNetD11R.bpi;JvPageCompsD11R.bpi;JvPluginD11R.bpi;JvPrintPreviewD11R.bpi;JvRuntimeDesignD11R.bpi;JvTimeFrameworkD11R.bpi;JvValidatorsD11R.bpi;JvWizardD11R.bpi;JvXPCtrlsD11R.bpi;VclSmp.bpi;CExceptionExpert11.bpi</PackageImports>\r
+    <BCC_wpar>false</BCC_wpar>\r
+    <IncludePath>$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</IncludePath>\r
+    <AllPackageLibs>rtl.lib;vcl.lib</AllPackageLibs>\r
+    <TLIB_PageSize>32</TLIB_PageSize>\r
+    <ILINK_LibraryPath>$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk</ILINK_LibraryPath>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Cfg_1)'!=''">\r
+    <BCC_OptimizeForSpeed>false</BCC_OptimizeForSpeed>\r
+    <DCC_Optimize>false</DCC_Optimize>\r
+    <DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>\r
+    <Defines>_DEBUG;$(Defines)</Defines>\r
+    <ILINK_FullDebugInfo>true</ILINK_FullDebugInfo>\r
+    <BCC_InlineFunctionExpansion>false</BCC_InlineFunctionExpansion>\r
+    <ILINK_DisableIncrementalLinking>true</ILINK_DisableIncrementalLinking>\r
+    <BCC_UseRegisterVariables>None</BCC_UseRegisterVariables>\r
+    <DCC_Define>DEBUG</DCC_Define>\r
+    <BCC_DebugLineNumbers>true</BCC_DebugLineNumbers>\r
+    <IntermediateOutputDir>Debug</IntermediateOutputDir>\r
+    <TASM_DisplaySourceLines>true</TASM_DisplaySourceLines>\r
+    <BCC_StackFrames>true</BCC_StackFrames>\r
+    <BCC_DisableOptimizations>true</BCC_DisableOptimizations>\r
+    <ILINK_LibraryPath>$(BDS)\lib\debug;$(ILINK_LibraryPath)</ILINK_LibraryPath>\r
+    <TASM_Debugging>Full</TASM_Debugging>\r
+    <BCC_SourceDebuggingOn>true</BCC_SourceDebuggingOn>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Cfg_2)'!=''">\r
+    <Defines>NDEBUG;$(Defines)</Defines>\r
+    <IntermediateOutputDir>Release</IntermediateOutputDir>\r
+    <ILINK_LibraryPath>$(BDS)\lib\release;$(ILINK_LibraryPath)</ILINK_LibraryPath>\r
+    <TASM_Debugging>None</TASM_Debugging>\r
+  </PropertyGroup>\r
+  <ProjectExtensions>\r
+    <Borland.Personality>CPlusPlusBuilder.Personality</Borland.Personality>\r
+    <Borland.ProjectType>CppStaticLibrary</Borland.ProjectType>\r
+    <BorlandProject>\r
+<BorlandProject><CPlusPlusBuilder.Personality><VersionInfo><VersionInfo Name="IncludeVerInfo">False</VersionInfo><VersionInfo Name="AutoIncBuild">False</VersionInfo><VersionInfo Name="MajorVer">1</VersionInfo><VersionInfo Name="MinorVer">0</VersionInfo><VersionInfo Name="Release">0</VersionInfo><VersionInfo Name="Build">0</VersionInfo><VersionInfo Name="Debug">False</VersionInfo><VersionInfo Name="PreRelease">False</VersionInfo><VersionInfo Name="Special">False</VersionInfo><VersionInfo Name="Private">False</VersionInfo><VersionInfo Name="DLL">False</VersionInfo><VersionInfo Name="Locale">1033</VersionInfo><VersionInfo Name="CodePage">1252</VersionInfo></VersionInfo><VersionInfoKeys><VersionInfoKeys Name="CompanyName"></VersionInfoKeys><VersionInfoKeys Name="FileDescription"></VersionInfoKeys><VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="InternalName"></VersionInfoKeys><VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys><VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys><VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys><VersionInfoKeys Name="ProductName"></VersionInfoKeys><VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="Comments"></VersionInfoKeys></VersionInfoKeys><Debugging><Debugging Name="DebugSourceDirs"></Debugging></Debugging><Parameters><Parameters Name="RunParams"></Parameters><Parameters Name="Launcher"></Parameters><Parameters Name="UseLauncher">False</Parameters><Parameters Name="DebugCWD"></Parameters><Parameters Name="HostApplication"></Parameters><Parameters Name="RemoteHost"></Parameters><Parameters Name="RemotePath"></Parameters><Parameters Name="RemoteParams"></Parameters><Parameters Name="RemoteLauncher"></Parameters><Parameters Name="UseRemoteLauncher">False</Parameters><Parameters Name="RemoteCWD"></Parameters><Parameters Name="RemoteDebug">False</Parameters><Parameters Name="Debug Symbols Search Path"></Parameters><Parameters Name="LoadAllSymbols">True</Parameters><Parameters Name="LoadUnspecifiedSymbols">False</Parameters></Parameters><Excluded_Packages>\r
+      \r
+      \r
+      <Excluded_Packages Name="$(BDS)\bin\bcboffice2k100.bpl">CodeGear C++Builder Office 2000 Servers Package</Excluded_Packages>\r
+      <Excluded_Packages Name="$(BDS)\bin\bcbofficexp100.bpl">CodeGear C++Builder Office XP Servers Package</Excluded_Packages>\r
+    </Excluded_Packages><Linker><Linker Name="LibPrefix"></Linker><Linker Name="LibSuffix"></Linker><Linker Name="LibVersion"></Linker></Linker><ProjectProperties><ProjectProperties Name="AutoShowDeps">False</ProjectProperties><ProjectProperties Name="ManagePaths">True</ProjectProperties><ProjectProperties Name="VerifyPackages">True</ProjectProperties></ProjectProperties><HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Count">3</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item0">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item1">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item2">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\src;..\include</HistoryLists_hlIncludePath></HistoryLists_hlIncludePath><HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Count">1</HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Item0">$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk</HistoryLists_hlILINK_LibraryPath></HistoryLists_hlILINK_LibraryPath><HistoryLists_hlDefines><HistoryLists_hlDefines Name="Count">1</HistoryLists_hlDefines><HistoryLists_hlDefines Name="Item0">NO_STRICT</HistoryLists_hlDefines></HistoryLists_hlDefines><HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Count">1</HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Item0">32</HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Item1">16</HistoryLists_hlTLIB_PageSize></HistoryLists_hlTLIB_PageSize></CPlusPlusBuilder.Personality></BorlandProject></BorlandProject>\r
+  </ProjectExtensions>\r
+  <Import Project="$(MSBuildBinPath)\Borland.Cpp.Targets" />\r
+  <ItemGroup>\r
+    <None Include="..\include\gtest\gtest-death-test.h">\r
+      <BuildOrder>3</BuildOrder>\r
+    </None>\r
+    <None Include="..\include\gtest\gtest-message.h">\r
+      <BuildOrder>4</BuildOrder>\r
+    </None>\r
+    <None Include="..\include\gtest\gtest-param-test.h">\r
+      <BuildOrder>5</BuildOrder>\r
+    </None>\r
+    <None Include="..\include\gtest\gtest-spi.h">\r
+      <BuildOrder>6</BuildOrder>\r
+    </None>\r
+    <None Include="..\include\gtest\gtest-test-part.h">\r
+      <BuildOrder>7</BuildOrder>\r
+    </None>\r
+    <None Include="..\include\gtest\gtest-typed-test.h">\r
+      <BuildOrder>8</BuildOrder>\r
+    </None>\r
+    <None Include="..\include\gtest\gtest.h">\r
+      <BuildOrder>0</BuildOrder>\r
+    </None>\r
+    <None Include="..\include\gtest\gtest_pred_impl.h">\r
+      <BuildOrder>1</BuildOrder>\r
+    </None>\r
+    <None Include="..\include\gtest\gtest_prod.h">\r
+      <BuildOrder>2</BuildOrder>\r
+    </None>\r
+    <None Include="..\include\gtest\internal\gtest-death-test-internal.h">\r
+      <BuildOrder>9</BuildOrder>\r
+    </None>\r
+    <None Include="..\include\gtest\internal\gtest-filepath.h">\r
+      <BuildOrder>10</BuildOrder>\r
+    </None>\r
+    <None Include="..\include\gtest\internal\gtest-internal.h">\r
+      <BuildOrder>11</BuildOrder>\r
+    </None>\r
+    <None Include="..\include\gtest\internal\gtest-linked_ptr.h">\r
+      <BuildOrder>12</BuildOrder>\r
+    </None>\r
+    <None Include="..\include\gtest\internal\gtest-param-util-generated.h">\r
+      <BuildOrder>14</BuildOrder>\r
+    </None>\r
+    <None Include="..\include\gtest\internal\gtest-param-util.h">\r
+      <BuildOrder>13</BuildOrder>\r
+    </None>\r
+    <None Include="..\include\gtest\internal\gtest-port.h">\r
+      <BuildOrder>15</BuildOrder>\r
+    </None>\r
+    <None Include="..\include\gtest\internal\gtest-string.h">\r
+      <BuildOrder>16</BuildOrder>\r
+    </None>\r
+    <None Include="..\include\gtest\internal\gtest-type-util.h">\r
+      <BuildOrder>17</BuildOrder>\r
+    </None>\r
+    <CppCompile Include="gtest_all.cc">\r
+      <BuildOrder>18</BuildOrder>\r
+    </CppCompile>\r
+    <BuildConfiguration Include="Debug">\r
+      <Key>Cfg_1</Key>\r
+    </BuildConfiguration>\r
+    <BuildConfiguration Include="Release">\r
+      <Key>Cfg_2</Key>\r
+    </BuildConfiguration>\r
+  </ItemGroup>\r
+</Project>
\ No newline at end of file
diff --git a/third_party/googletest/src/codegear/gtest.groupproj b/third_party/googletest/src/codegear/gtest.groupproj
new file mode 100644 (file)
index 0000000..faf31ca
--- /dev/null
@@ -0,0 +1,54 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <PropertyGroup>\r
+    <ProjectGuid>{c1d923e0-6cba-4332-9b6f-3420acbf5091}</ProjectGuid>\r
+  </PropertyGroup>\r
+  <ItemGroup />\r
+  <ItemGroup>\r
+    <Projects Include="gtest.cbproj" />\r
+    <Projects Include="gtest_main.cbproj" />\r
+    <Projects Include="gtest_unittest.cbproj" />\r
+  </ItemGroup>\r
+  <ProjectExtensions>\r
+    <Borland.Personality>Default.Personality</Borland.Personality>\r
+    <Borland.ProjectType />\r
+    <BorlandProject>\r
+<BorlandProject xmlns=""><Default.Personality></Default.Personality></BorlandProject></BorlandProject>\r
+  </ProjectExtensions>\r
+  <Target Name="gtest">\r
+    <MSBuild Projects="gtest.cbproj" Targets="" />\r
+  </Target>\r
+  <Target Name="gtest:Clean">\r
+    <MSBuild Projects="gtest.cbproj" Targets="Clean" />\r
+  </Target>\r
+  <Target Name="gtest:Make">\r
+    <MSBuild Projects="gtest.cbproj" Targets="Make" />\r
+  </Target>\r
+  <Target Name="gtest_main">\r
+    <MSBuild Projects="gtest_main.cbproj" Targets="" />\r
+  </Target>\r
+  <Target Name="gtest_main:Clean">\r
+    <MSBuild Projects="gtest_main.cbproj" Targets="Clean" />\r
+  </Target>\r
+  <Target Name="gtest_main:Make">\r
+    <MSBuild Projects="gtest_main.cbproj" Targets="Make" />\r
+  </Target>\r
+  <Target Name="gtest_unittest">\r
+    <MSBuild Projects="gtest_unittest.cbproj" Targets="" />\r
+  </Target>\r
+  <Target Name="gtest_unittest:Clean">\r
+    <MSBuild Projects="gtest_unittest.cbproj" Targets="Clean" />\r
+  </Target>\r
+  <Target Name="gtest_unittest:Make">\r
+    <MSBuild Projects="gtest_unittest.cbproj" Targets="Make" />\r
+  </Target>\r
+  <Target Name="Build">\r
+    <CallTarget Targets="gtest;gtest_main;gtest_unittest" />\r
+  </Target>\r
+  <Target Name="Clean">\r
+    <CallTarget Targets="gtest:Clean;gtest_main:Clean;gtest_unittest:Clean" />\r
+  </Target>\r
+  <Target Name="Make">\r
+    <CallTarget Targets="gtest:Make;gtest_main:Make;gtest_unittest:Make" />\r
+  </Target>\r
+  <Import Condition="Exists('$(MSBuildBinPath)\Borland.Group.Targets')" Project="$(MSBuildBinPath)\Borland.Group.Targets" />\r
+</Project>
\ No newline at end of file
diff --git a/third_party/googletest/src/codegear/gtest_all.cc b/third_party/googletest/src/codegear/gtest_all.cc
new file mode 100644 (file)
index 0000000..121b2d8
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2009, Google Inc.\r
+// All rights reserved.\r
+//\r
+// Redistribution and use in source and binary forms, with or without\r
+// modification, are permitted provided that the following conditions are\r
+// met:\r
+//\r
+//     * Redistributions of source code must retain the above copyright\r
+// notice, this list of conditions and the following disclaimer.\r
+//     * Redistributions in binary form must reproduce the above\r
+// copyright notice, this list of conditions and the following disclaimer\r
+// in the documentation and/or other materials provided with the\r
+// distribution.\r
+//     * Neither the name of Google Inc. nor the names of its\r
+// contributors may be used to endorse or promote products derived from\r
+// this software without specific prior written permission.\r
+//\r
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+//\r
+// Author: Josh Kelley (joshkel@gmail.com)\r
+//\r
+// Google C++ Testing Framework (Google Test)\r
+//\r
+// C++Builder's IDE cannot build a static library from files with hyphens\r
+// in their name.  See http://qc.codegear.com/wc/qcmain.aspx?d=70977 .\r
+// This file serves as a workaround.\r
+\r
+#include "src/gtest-all.cc"\r
diff --git a/third_party/googletest/src/codegear/gtest_link.cc b/third_party/googletest/src/codegear/gtest_link.cc
new file mode 100644 (file)
index 0000000..918eccd
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2009, Google Inc.\r
+// All rights reserved.\r
+//\r
+// Redistribution and use in source and binary forms, with or without\r
+// modification, are permitted provided that the following conditions are\r
+// met:\r
+//\r
+//     * Redistributions of source code must retain the above copyright\r
+// notice, this list of conditions and the following disclaimer.\r
+//     * Redistributions in binary form must reproduce the above\r
+// copyright notice, this list of conditions and the following disclaimer\r
+// in the documentation and/or other materials provided with the\r
+// distribution.\r
+//     * Neither the name of Google Inc. nor the names of its\r
+// contributors may be used to endorse or promote products derived from\r
+// this software without specific prior written permission.\r
+//\r
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+//\r
+// Author: Josh Kelley (joshkel@gmail.com)\r
+//\r
+// Google C++ Testing Framework (Google Test)\r
+//\r
+// Links gtest.lib and gtest_main.lib into the current project in C++Builder.\r
+// This means that these libraries can't be renamed, but it's the only way to\r
+// ensure that Debug versus Release test builds are linked against the\r
+// appropriate Debug or Release build of the libraries.\r
+\r
+#pragma link "gtest.lib"\r
+#pragma link "gtest_main.lib"\r
diff --git a/third_party/googletest/src/codegear/gtest_main.cbproj b/third_party/googletest/src/codegear/gtest_main.cbproj
new file mode 100644 (file)
index 0000000..d76ce13
--- /dev/null
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <PropertyGroup>\r
+    <ProjectGuid>{bca37a72-5b07-46cf-b44e-89f8e06451a2}</ProjectGuid>\r
+    <Config Condition="'$(Config)'==''">Release</Config>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">\r
+    <Base>true</Base>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">\r
+    <Base>true</Base>\r
+    <Cfg_1>true</Cfg_1>\r
+    <CfgParent>Base</CfgParent>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">\r
+    <Base>true</Base>\r
+    <Cfg_2>true</Cfg_2>\r
+    <CfgParent>Base</CfgParent>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Base)'!=''">\r
+    <BCC_OptimizeForSpeed>true</BCC_OptimizeForSpeed>\r
+    <OutputExt>lib</OutputExt>\r
+    <DCC_CBuilderOutput>JPHNE</DCC_CBuilderOutput>\r
+    <Defines>NO_STRICT</Defines>\r
+    <DynamicRTL>true</DynamicRTL>\r
+    <UsePackages>true</UsePackages>\r
+    <ProjectType>CppStaticLibrary</ProjectType>\r
+    <BCC_CPPCompileAlways>true</BCC_CPPCompileAlways>\r
+    <PackageImports>rtl.bpi;vcl.bpi;bcbie.bpi;vclx.bpi;vclactnband.bpi;xmlrtl.bpi;bcbsmp.bpi;dbrtl.bpi;vcldb.bpi;bdertl.bpi;vcldbx.bpi;dsnap.bpi;dsnapcon.bpi;vclib.bpi;ibxpress.bpi;adortl.bpi;dbxcds.bpi;dbexpress.bpi;DbxCommonDriver.bpi;websnap.bpi;vclie.bpi;webdsnap.bpi;inet.bpi;inetdbbde.bpi;inetdbxpress.bpi;soaprtl.bpi;Rave75VCL.bpi;teeUI.bpi;tee.bpi;teedb.bpi;IndyCore.bpi;IndySystem.bpi;IndyProtocols.bpi;IntrawebDB_90_100.bpi;Intraweb_90_100.bpi;dclZipForged11.bpi;vclZipForged11.bpi;GR32_BDS2006.bpi;GR32_DSGN_BDS2006.bpi;Jcl.bpi;JclVcl.bpi;JvCoreD11R.bpi;JvSystemD11R.bpi;JvStdCtrlsD11R.bpi;JvAppFrmD11R.bpi;JvBandsD11R.bpi;JvDBD11R.bpi;JvDlgsD11R.bpi;JvBDED11R.bpi;JvCmpD11R.bpi;JvCryptD11R.bpi;JvCtrlsD11R.bpi;JvCustomD11R.bpi;JvDockingD11R.bpi;JvDotNetCtrlsD11R.bpi;JvEDID11R.bpi;JvGlobusD11R.bpi;JvHMID11R.bpi;JvInterpreterD11R.bpi;JvJansD11R.bpi;JvManagedThreadsD11R.bpi;JvMMD11R.bpi;JvNetD11R.bpi;JvPageCompsD11R.bpi;JvPluginD11R.bpi;JvPrintPreviewD11R.bpi;JvRuntimeDesignD11R.bpi;JvTimeFrameworkD11R.bpi;JvValidatorsD11R.bpi;JvWizardD11R.bpi;JvXPCtrlsD11R.bpi;VclSmp.bpi;CExceptionExpert11.bpi</PackageImports>\r
+    <BCC_wpar>false</BCC_wpar>\r
+    <IncludePath>$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</IncludePath>\r
+    <AllPackageLibs>rtl.lib;vcl.lib</AllPackageLibs>\r
+    <TLIB_PageSize>32</TLIB_PageSize>\r
+    <ILINK_LibraryPath>$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk</ILINK_LibraryPath>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Cfg_1)'!=''">\r
+    <BCC_OptimizeForSpeed>false</BCC_OptimizeForSpeed>\r
+    <DCC_Optimize>false</DCC_Optimize>\r
+    <DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>\r
+    <Defines>_DEBUG;$(Defines)</Defines>\r
+    <ILINK_FullDebugInfo>true</ILINK_FullDebugInfo>\r
+    <BCC_InlineFunctionExpansion>false</BCC_InlineFunctionExpansion>\r
+    <ILINK_DisableIncrementalLinking>true</ILINK_DisableIncrementalLinking>\r
+    <BCC_UseRegisterVariables>None</BCC_UseRegisterVariables>\r
+    <DCC_Define>DEBUG</DCC_Define>\r
+    <BCC_DebugLineNumbers>true</BCC_DebugLineNumbers>\r
+    <IntermediateOutputDir>Debug</IntermediateOutputDir>\r
+    <TASM_DisplaySourceLines>true</TASM_DisplaySourceLines>\r
+    <BCC_StackFrames>true</BCC_StackFrames>\r
+    <BCC_DisableOptimizations>true</BCC_DisableOptimizations>\r
+    <ILINK_LibraryPath>$(BDS)\lib\debug;$(ILINK_LibraryPath)</ILINK_LibraryPath>\r
+    <TASM_Debugging>Full</TASM_Debugging>\r
+    <BCC_SourceDebuggingOn>true</BCC_SourceDebuggingOn>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Cfg_2)'!=''">\r
+    <Defines>NDEBUG;$(Defines)</Defines>\r
+    <IntermediateOutputDir>Release</IntermediateOutputDir>\r
+    <ILINK_LibraryPath>$(BDS)\lib\release;$(ILINK_LibraryPath)</ILINK_LibraryPath>\r
+    <TASM_Debugging>None</TASM_Debugging>\r
+  </PropertyGroup>\r
+  <ProjectExtensions>\r
+    <Borland.Personality>CPlusPlusBuilder.Personality</Borland.Personality>\r
+    <Borland.ProjectType>CppStaticLibrary</Borland.ProjectType>\r
+    <BorlandProject>\r
+<BorlandProject><CPlusPlusBuilder.Personality><VersionInfo><VersionInfo Name="IncludeVerInfo">False</VersionInfo><VersionInfo Name="AutoIncBuild">False</VersionInfo><VersionInfo Name="MajorVer">1</VersionInfo><VersionInfo Name="MinorVer">0</VersionInfo><VersionInfo Name="Release">0</VersionInfo><VersionInfo Name="Build">0</VersionInfo><VersionInfo Name="Debug">False</VersionInfo><VersionInfo Name="PreRelease">False</VersionInfo><VersionInfo Name="Special">False</VersionInfo><VersionInfo Name="Private">False</VersionInfo><VersionInfo Name="DLL">False</VersionInfo><VersionInfo Name="Locale">1033</VersionInfo><VersionInfo Name="CodePage">1252</VersionInfo></VersionInfo><VersionInfoKeys><VersionInfoKeys Name="CompanyName"></VersionInfoKeys><VersionInfoKeys Name="FileDescription"></VersionInfoKeys><VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="InternalName"></VersionInfoKeys><VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys><VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys><VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys><VersionInfoKeys Name="ProductName"></VersionInfoKeys><VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="Comments"></VersionInfoKeys></VersionInfoKeys><Debugging><Debugging Name="DebugSourceDirs"></Debugging></Debugging><Parameters><Parameters Name="RunParams"></Parameters><Parameters Name="Launcher"></Parameters><Parameters Name="UseLauncher">False</Parameters><Parameters Name="DebugCWD"></Parameters><Parameters Name="HostApplication"></Parameters><Parameters Name="RemoteHost"></Parameters><Parameters Name="RemotePath"></Parameters><Parameters Name="RemoteParams"></Parameters><Parameters Name="RemoteLauncher"></Parameters><Parameters Name="UseRemoteLauncher">False</Parameters><Parameters Name="RemoteCWD"></Parameters><Parameters Name="RemoteDebug">False</Parameters><Parameters Name="Debug Symbols Search Path"></Parameters><Parameters Name="LoadAllSymbols">True</Parameters><Parameters Name="LoadUnspecifiedSymbols">False</Parameters></Parameters><Excluded_Packages>\r
+      <Excluded_Packages Name="$(BDS)\bin\bcboffice2k100.bpl">CodeGear C++Builder Office 2000 Servers Package</Excluded_Packages>\r
+      <Excluded_Packages Name="$(BDS)\bin\bcbofficexp100.bpl">CodeGear C++Builder Office XP Servers Package</Excluded_Packages>\r
+    </Excluded_Packages><Linker><Linker Name="LibPrefix"></Linker><Linker Name="LibSuffix"></Linker><Linker Name="LibVersion"></Linker></Linker><ProjectProperties><ProjectProperties Name="AutoShowDeps">False</ProjectProperties><ProjectProperties Name="ManagePaths">True</ProjectProperties><ProjectProperties Name="VerifyPackages">True</ProjectProperties></ProjectProperties><HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Count">3</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item0">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item1">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item2">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\src;..\include</HistoryLists_hlIncludePath></HistoryLists_hlIncludePath><HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Count">1</HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Item0">$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk</HistoryLists_hlILINK_LibraryPath></HistoryLists_hlILINK_LibraryPath><HistoryLists_hlDefines><HistoryLists_hlDefines Name="Count">1</HistoryLists_hlDefines><HistoryLists_hlDefines Name="Item0">NO_STRICT</HistoryLists_hlDefines></HistoryLists_hlDefines><HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Count">1</HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Item0">32</HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Item1">16</HistoryLists_hlTLIB_PageSize></HistoryLists_hlTLIB_PageSize></CPlusPlusBuilder.Personality></BorlandProject></BorlandProject>\r
+  </ProjectExtensions>\r
+  <Import Project="$(MSBuildBinPath)\Borland.Cpp.Targets" />\r
+  <ItemGroup>\r
+    <CppCompile Include="..\src\gtest_main.cc">\r
+      <BuildOrder>0</BuildOrder>\r
+    </CppCompile>\r
+    <BuildConfiguration Include="Debug">\r
+      <Key>Cfg_1</Key>\r
+    </BuildConfiguration>\r
+    <BuildConfiguration Include="Release">\r
+      <Key>Cfg_2</Key>\r
+    </BuildConfiguration>\r
+  </ItemGroup>\r
+</Project>\r
diff --git a/third_party/googletest/src/codegear/gtest_unittest.cbproj b/third_party/googletest/src/codegear/gtest_unittest.cbproj
new file mode 100644 (file)
index 0000000..dc5db8e
--- /dev/null
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <PropertyGroup>\r
+    <ProjectGuid>{eea63393-5ac5-4b9c-8909-d75fef2daa41}</ProjectGuid>\r
+    <Config Condition="'$(Config)'==''">Release</Config>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">\r
+    <Base>true</Base>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">\r
+    <Base>true</Base>\r
+    <Cfg_1>true</Cfg_1>\r
+    <CfgParent>Base</CfgParent>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">\r
+    <Base>true</Base>\r
+    <Cfg_2>true</Cfg_2>\r
+    <CfgParent>Base</CfgParent>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Base)'!=''">\r
+    <OutputExt>exe</OutputExt>\r
+    <BCC_OptimizeForSpeed>true</BCC_OptimizeForSpeed>\r
+    <Defines>NO_STRICT</Defines>\r
+    <DCC_CBuilderOutput>JPHNE</DCC_CBuilderOutput>\r
+    <DynamicRTL>true</DynamicRTL>\r
+    <ILINK_ObjectSearchPath>..\test</ILINK_ObjectSearchPath>\r
+    <UsePackages>true</UsePackages>\r
+    <ProjectType>CppConsoleApplication</ProjectType>\r
+    <NoVCL>true</NoVCL>\r
+    <BCC_CPPCompileAlways>true</BCC_CPPCompileAlways>\r
+    <PackageImports>rtl.bpi;vcl.bpi;bcbie.bpi;vclx.bpi;vclactnband.bpi;xmlrtl.bpi;bcbsmp.bpi;dbrtl.bpi;vcldb.bpi;bdertl.bpi;vcldbx.bpi;dsnap.bpi;dsnapcon.bpi;vclib.bpi;ibxpress.bpi;adortl.bpi;dbxcds.bpi;dbexpress.bpi;DbxCommonDriver.bpi;websnap.bpi;vclie.bpi;webdsnap.bpi;inet.bpi;inetdbbde.bpi;inetdbxpress.bpi;soaprtl.bpi;Rave75VCL.bpi;teeUI.bpi;tee.bpi;teedb.bpi;IndyCore.bpi;IndySystem.bpi;IndyProtocols.bpi;IntrawebDB_90_100.bpi;Intraweb_90_100.bpi;Jcl.bpi;JclVcl.bpi;JvCoreD11R.bpi;JvSystemD11R.bpi;JvStdCtrlsD11R.bpi;JvAppFrmD11R.bpi;JvBandsD11R.bpi;JvDBD11R.bpi;JvDlgsD11R.bpi;JvBDED11R.bpi;JvCmpD11R.bpi;JvCryptD11R.bpi;JvCtrlsD11R.bpi;JvCustomD11R.bpi;JvDockingD11R.bpi;JvDotNetCtrlsD11R.bpi;JvEDID11R.bpi;JvGlobusD11R.bpi;JvHMID11R.bpi;JvInterpreterD11R.bpi;JvJansD11R.bpi;JvManagedThreadsD11R.bpi;JvMMD11R.bpi;JvNetD11R.bpi;JvPageCompsD11R.bpi;JvPluginD11R.bpi;JvPrintPreviewD11R.bpi;JvRuntimeDesignD11R.bpi;JvTimeFrameworkD11R.bpi;JvValidatorsD11R.bpi;JvWizardD11R.bpi;JvXPCtrlsD11R.bpi;VclSmp.bpi</PackageImports>\r
+    <BCC_wpar>false</BCC_wpar>\r
+    <IncludePath>$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\include;..\test;..</IncludePath>\r
+    <ILINK_LibraryPath>$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk;..\test</ILINK_LibraryPath>\r
+    <Multithreaded>true</Multithreaded>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Cfg_1)'!=''">\r
+    <BCC_OptimizeForSpeed>false</BCC_OptimizeForSpeed>\r
+    <DCC_Optimize>false</DCC_Optimize>\r
+    <DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>\r
+    <Defines>_DEBUG;$(Defines)</Defines>\r
+    <ILINK_FullDebugInfo>true</ILINK_FullDebugInfo>\r
+    <BCC_InlineFunctionExpansion>false</BCC_InlineFunctionExpansion>\r
+    <ILINK_DisableIncrementalLinking>true</ILINK_DisableIncrementalLinking>\r
+    <BCC_UseRegisterVariables>None</BCC_UseRegisterVariables>\r
+    <DCC_Define>DEBUG</DCC_Define>\r
+    <BCC_DebugLineNumbers>true</BCC_DebugLineNumbers>\r
+    <IntermediateOutputDir>Debug</IntermediateOutputDir>\r
+    <TASM_DisplaySourceLines>true</TASM_DisplaySourceLines>\r
+    <BCC_StackFrames>true</BCC_StackFrames>\r
+    <BCC_DisableOptimizations>true</BCC_DisableOptimizations>\r
+    <ILINK_LibraryPath>$(BDS)\lib\debug;$(ILINK_LibraryPath)</ILINK_LibraryPath>\r
+    <TASM_Debugging>Full</TASM_Debugging>\r
+    <BCC_SourceDebuggingOn>true</BCC_SourceDebuggingOn>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Cfg_2)'!=''">\r
+    <Defines>NDEBUG;$(Defines)</Defines>\r
+    <IntermediateOutputDir>Release</IntermediateOutputDir>\r
+    <ILINK_LibraryPath>$(BDS)\lib\release;$(ILINK_LibraryPath)</ILINK_LibraryPath>\r
+    <TASM_Debugging>None</TASM_Debugging>\r
+  </PropertyGroup>\r
+  <ProjectExtensions>\r
+    <Borland.Personality>CPlusPlusBuilder.Personality</Borland.Personality>\r
+    <Borland.ProjectType>CppConsoleApplication</Borland.ProjectType>\r
+    <BorlandProject>\r
+<BorlandProject><CPlusPlusBuilder.Personality><VersionInfo><VersionInfo Name="IncludeVerInfo">False</VersionInfo><VersionInfo Name="AutoIncBuild">False</VersionInfo><VersionInfo Name="MajorVer">1</VersionInfo><VersionInfo Name="MinorVer">0</VersionInfo><VersionInfo Name="Release">0</VersionInfo><VersionInfo Name="Build">0</VersionInfo><VersionInfo Name="Debug">False</VersionInfo><VersionInfo Name="PreRelease">False</VersionInfo><VersionInfo Name="Special">False</VersionInfo><VersionInfo Name="Private">False</VersionInfo><VersionInfo Name="DLL">False</VersionInfo><VersionInfo Name="Locale">1033</VersionInfo><VersionInfo Name="CodePage">1252</VersionInfo></VersionInfo><VersionInfoKeys><VersionInfoKeys Name="CompanyName"></VersionInfoKeys><VersionInfoKeys Name="FileDescription"></VersionInfoKeys><VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="InternalName"></VersionInfoKeys><VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys><VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys><VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys><VersionInfoKeys Name="ProductName"></VersionInfoKeys><VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="Comments"></VersionInfoKeys></VersionInfoKeys><Debugging><Debugging Name="DebugSourceDirs"></Debugging></Debugging><Parameters><Parameters Name="RunParams"></Parameters><Parameters Name="Launcher"></Parameters><Parameters Name="UseLauncher">False</Parameters><Parameters Name="DebugCWD"></Parameters><Parameters Name="HostApplication"></Parameters><Parameters Name="RemoteHost"></Parameters><Parameters Name="RemotePath"></Parameters><Parameters Name="RemoteParams"></Parameters><Parameters Name="RemoteLauncher"></Parameters><Parameters Name="UseRemoteLauncher">False</Parameters><Parameters Name="RemoteCWD"></Parameters><Parameters Name="RemoteDebug">False</Parameters><Parameters Name="Debug Symbols Search Path"></Parameters><Parameters Name="LoadAllSymbols">True</Parameters><Parameters Name="LoadUnspecifiedSymbols">False</Parameters></Parameters><Excluded_Packages>\r
+      \r
+      \r
+      <Excluded_Packages Name="$(BDS)\bin\bcboffice2k100.bpl">CodeGear C++Builder Office 2000 Servers Package</Excluded_Packages>\r
+      <Excluded_Packages Name="$(BDS)\bin\bcbofficexp100.bpl">CodeGear C++Builder Office XP Servers Package</Excluded_Packages>\r
+    </Excluded_Packages><Linker><Linker Name="LibPrefix"></Linker><Linker Name="LibSuffix"></Linker><Linker Name="LibVersion"></Linker></Linker><ProjectProperties><ProjectProperties Name="AutoShowDeps">False</ProjectProperties><ProjectProperties Name="ManagePaths">True</ProjectProperties><ProjectProperties Name="VerifyPackages">True</ProjectProperties></ProjectProperties><HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Count">3</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item0">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\include;..\test;..</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item1">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\include;..\test</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item2">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\include</HistoryLists_hlIncludePath></HistoryLists_hlIncludePath><HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Count">1</HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Item0">$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk;..\test</HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Item1">$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk;..\test</HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Item2">$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk;$(OUTPUTDIR);..\test</HistoryLists_hlILINK_LibraryPath></HistoryLists_hlILINK_LibraryPath><HistoryLists_hlDefines><HistoryLists_hlDefines Name="Count">2</HistoryLists_hlDefines><HistoryLists_hlDefines Name="Item0">NO_STRICT</HistoryLists_hlDefines><HistoryLists_hlDefines Name="Item1">STRICT</HistoryLists_hlDefines></HistoryLists_hlDefines></CPlusPlusBuilder.Personality></BorlandProject></BorlandProject>\r
+  </ProjectExtensions>\r
+  <Import Project="$(MSBuildBinPath)\Borland.Cpp.Targets" />\r
+  <ItemGroup>\r
+    <CppCompile Include="..\test\gtest_unittest.cc">\r
+      <BuildOrder>0</BuildOrder>\r
+    </CppCompile>\r
+    <CppCompile Include="gtest_link.cc">\r
+      <BuildOrder>1</BuildOrder>\r
+    </CppCompile>\r
+    <BuildConfiguration Include="Debug">\r
+      <Key>Cfg_1</Key>\r
+    </BuildConfiguration>\r
+    <BuildConfiguration Include="Release">\r
+      <Key>Cfg_2</Key>\r
+    </BuildConfiguration>\r
+  </ItemGroup>\r
+</Project>
\ No newline at end of file
diff --git a/third_party/googletest/src/configure.ac b/third_party/googletest/src/configure.ac
new file mode 100644 (file)
index 0000000..fa66029
--- /dev/null
@@ -0,0 +1,68 @@
+m4_include(m4/acx_pthread.m4)
+
+# At this point, the Xcode project assumes the version string will be three
+# integers separated by periods and surrounded by square brackets (e.g.
+# "[1.0.1]"). It also asumes that there won't be any closing parenthesis
+# between "AC_INIT(" and the closing ")" including comments and strings.
+AC_INIT([Google C++ Testing Framework],
+        [1.6.0],
+        [googletestframework@googlegroups.com],
+        [gtest])
+
+# Provide various options to initialize the Autoconf and configure processes.
+AC_PREREQ([2.59])
+AC_CONFIG_SRCDIR([./COPYING])
+AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_AUX_DIR([build-aux])
+AC_CONFIG_HEADERS([build-aux/config.h])
+AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([scripts/gtest-config], [chmod +x scripts/gtest-config])
+
+# Initialize Automake with various options. We require at least v1.9, prevent
+# pedantic complaints about package files, and enable various distribution
+# targets.
+AM_INIT_AUTOMAKE([1.9 dist-bzip2 dist-zip foreign subdir-objects])
+
+# Check for programs used in building Google Test.
+AC_PROG_CC
+AC_PROG_CXX
+AC_LANG([C++])
+AC_PROG_LIBTOOL
+
+# TODO(chandlerc@google.com): Currently we aren't running the Python tests
+# against the interpreter detected by AM_PATH_PYTHON, and so we condition
+# HAVE_PYTHON by requiring "python" to be in the PATH, and that interpreter's
+# version to be >= 2.3. This will allow the scripts to use a "/usr/bin/env"
+# hashbang.
+PYTHON=  # We *do not* allow the user to specify a python interpreter
+AC_PATH_PROG([PYTHON],[python],[:])
+AS_IF([test "$PYTHON" != ":"],
+      [AM_PYTHON_CHECK_VERSION([$PYTHON],[2.3],[:],[PYTHON=":"])])
+AM_CONDITIONAL([HAVE_PYTHON],[test "$PYTHON" != ":"])
+
+# Configure pthreads.
+AC_ARG_WITH([pthreads],
+            [AS_HELP_STRING([--with-pthreads],
+               [use pthreads (default is yes)])],
+            [with_pthreads=$withval],
+            [with_pthreads=check])
+
+have_pthreads=no
+AS_IF([test "x$with_pthreads" != "xno"],
+      [ACX_PTHREAD(
+        [],
+        [AS_IF([test "x$with_pthreads" != "xcheck"],
+               [AC_MSG_FAILURE(
+                 [--with-pthreads was specified, but unable to be used])])])
+       have_pthreads="$acx_pthread_ok"])
+AM_CONDITIONAL([HAVE_PTHREADS],[test "x$have_pthreads" == "xyes"])
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_LIBS)
+
+# TODO(chandlerc@google.com) Check for the necessary system headers.
+
+# TODO(chandlerc@google.com) Check the types, structures, and other compiler
+# and architecture characteristics.
+
+# Output the generated files. No further autoconf macros may be used.
+AC_OUTPUT
diff --git a/third_party/googletest/src/include/gtest/gtest-death-test.h b/third_party/googletest/src/include/gtest/gtest-death-test.h
new file mode 100644 (file)
index 0000000..a27883f
--- /dev/null
@@ -0,0 +1,283 @@
+// Copyright 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: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the public API for death tests.  It is
+// #included by gtest.h so a user doesn't need to include this
+// directly.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+
+#include "gtest/internal/gtest-death-test-internal.h"
+
+namespace testing {
+
+// This flag controls the style of death tests.  Valid values are "threadsafe",
+// meaning that the death test child process will re-execute the test binary
+// from the start, running only a single death test, or "fast",
+// meaning that the child process will execute the test logic immediately
+// after forking.
+GTEST_DECLARE_string_(death_test_style);
+
+#if GTEST_HAS_DEATH_TEST
+
+// The following macros are useful for writing death tests.
+
+// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is
+// executed:
+//
+//   1. It generates a warning if there is more than one active
+//   thread.  This is because it's safe to fork() or clone() only
+//   when there is a single thread.
+//
+//   2. The parent process clone()s a sub-process and runs the death
+//   test in it; the sub-process exits with code 0 at the end of the
+//   death test, if it hasn't exited already.
+//
+//   3. The parent process waits for the sub-process to terminate.
+//
+//   4. The parent process checks the exit code and error message of
+//   the sub-process.
+//
+// Examples:
+//
+//   ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number");
+//   for (int i = 0; i < 5; i++) {
+//     EXPECT_DEATH(server.ProcessRequest(i),
+//                  "Invalid request .* in ProcessRequest()")
+//         << "Failed to die on request " << i);
+//   }
+//
+//   ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting");
+//
+//   bool KilledBySIGHUP(int exit_code) {
+//     return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP;
+//   }
+//
+//   ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!");
+//
+// On the regular expressions used in death tests:
+//
+//   On POSIX-compliant systems (*nix), we use the <regex.h> library,
+//   which uses the POSIX extended regex syntax.
+//
+//   On other platforms (e.g. Windows), we only support a simple regex
+//   syntax implemented as part of Google Test.  This limited
+//   implementation should be enough most of the time when writing
+//   death tests; though it lacks many features you can find in PCRE
+//   or POSIX extended regex syntax.  For example, we don't support
+//   union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and
+//   repetition count ("x{5,7}"), among others.
+//
+//   Below is the syntax that we do support.  We chose it to be a
+//   subset of both PCRE and POSIX extended regex, so it's easy to
+//   learn wherever you come from.  In the following: 'A' denotes a
+//   literal character, period (.), or a single \\ escape sequence;
+//   'x' and 'y' denote regular expressions; 'm' and 'n' are for
+//   natural numbers.
+//
+//     c     matches any literal character c
+//     \\d   matches any decimal digit
+//     \\D   matches any character that's not a decimal digit
+//     \\f   matches \f
+//     \\n   matches \n
+//     \\r   matches \r
+//     \\s   matches any ASCII whitespace, including \n
+//     \\S   matches any character that's not a whitespace
+//     \\t   matches \t
+//     \\v   matches \v
+//     \\w   matches any letter, _, or decimal digit
+//     \\W   matches any character that \\w doesn't match
+//     \\c   matches any literal character c, which must be a punctuation
+//     .     matches any single character except \n
+//     A?    matches 0 or 1 occurrences of A
+//     A*    matches 0 or many occurrences of A
+//     A+    matches 1 or many occurrences of A
+//     ^     matches the beginning of a string (not that of each line)
+//     $     matches the end of a string (not that of each line)
+//     xy    matches x followed by y
+//
+//   If you accidentally use PCRE or POSIX extended regex features
+//   not implemented by us, you will get a run-time failure.  In that
+//   case, please try to rewrite your regular expression within the
+//   above syntax.
+//
+//   This implementation is *not* meant to be as highly tuned or robust
+//   as a compiled regex library, but should perform well enough for a
+//   death test, which already incurs significant overhead by launching
+//   a child process.
+//
+// Known caveats:
+//
+//   A "threadsafe" style death test obtains the path to the test
+//   program from argv[0] and re-executes it in the sub-process.  For
+//   simplicity, the current implementation doesn't search the PATH
+//   when launching the sub-process.  This means that the user must
+//   invoke the test program via a path that contains at least one
+//   path separator (e.g. path/to/foo_test and
+//   /absolute/path/to/bar_test are fine, but foo_test is not).  This
+//   is rarely a problem as people usually don't put the test binary
+//   directory in PATH.
+//
+// TODO(wan@google.com): make thread-safe death tests search the PATH.
+
+// Asserts that a given statement causes the program to exit, with an
+// integer exit status that satisfies predicate, and emitting error output
+// that matches regex.
+# define ASSERT_EXIT(statement, predicate, regex) \
+    GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
+
+// Like ASSERT_EXIT, but continues on to successive tests in the
+// test case, if any:
+# define EXPECT_EXIT(statement, predicate, regex) \
+    GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
+
+// Asserts that a given statement causes the program to exit, either by
+// explicitly exiting with a nonzero exit code or being killed by a
+// signal, and emitting error output that matches regex.
+# define ASSERT_DEATH(statement, regex) \
+    ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
+
+// Like ASSERT_DEATH, but continues on to successive tests in the
+// test case, if any:
+# define EXPECT_DEATH(statement, regex) \
+    EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
+
+// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
+
+// Tests that an exit code describes a normal exit with a given exit code.
+class GTEST_API_ ExitedWithCode {
+ public:
+  explicit ExitedWithCode(int exit_code);
+  bool operator()(int exit_status) const;
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ExitedWithCode& other);
+
+  const int exit_code_;
+};
+
+# if !GTEST_OS_WINDOWS
+// Tests that an exit code describes an exit due to termination by a
+// given signal.
+class GTEST_API_ KilledBySignal {
+ public:
+  explicit KilledBySignal(int signum);
+  bool operator()(int exit_status) const;
+ private:
+  const int signum_;
+};
+# endif  // !GTEST_OS_WINDOWS
+
+// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
+// The death testing framework causes this to have interesting semantics,
+// since the sideeffects of the call are only visible in opt mode, and not
+// in debug mode.
+//
+// In practice, this can be used to test functions that utilize the
+// LOG(DFATAL) macro using the following style:
+//
+// int DieInDebugOr12(int* sideeffect) {
+//   if (sideeffect) {
+//     *sideeffect = 12;
+//   }
+//   LOG(DFATAL) << "death";
+//   return 12;
+// }
+//
+// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) {
+//   int sideeffect = 0;
+//   // Only asserts in dbg.
+//   EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death");
+//
+// #ifdef NDEBUG
+//   // opt-mode has sideeffect visible.
+//   EXPECT_EQ(12, sideeffect);
+// #else
+//   // dbg-mode no visible sideeffect.
+//   EXPECT_EQ(0, sideeffect);
+// #endif
+// }
+//
+// This will assert that DieInDebugReturn12InOpt() crashes in debug
+// mode, usually due to a DCHECK or LOG(DFATAL), but returns the
+// appropriate fallback value (12 in this case) in opt mode. If you
+// need to test that a function has appropriate side-effects in opt
+// mode, include assertions against the side-effects.  A general
+// pattern for this is:
+//
+// EXPECT_DEBUG_DEATH({
+//   // Side-effects here will have an effect after this statement in
+//   // opt mode, but none in debug mode.
+//   EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
+// }, "death");
+//
+# ifdef NDEBUG
+
+#  define EXPECT_DEBUG_DEATH(statement, regex) \
+  do { statement; } while (::testing::internal::AlwaysFalse())
+
+#  define ASSERT_DEBUG_DEATH(statement, regex) \
+  do { statement; } while (::testing::internal::AlwaysFalse())
+
+# else
+
+#  define EXPECT_DEBUG_DEATH(statement, regex) \
+  EXPECT_DEATH(statement, regex)
+
+#  define ASSERT_DEBUG_DEATH(statement, regex) \
+  ASSERT_DEATH(statement, regex)
+
+# endif  // NDEBUG for EXPECT_DEBUG_DEATH
+#endif  // GTEST_HAS_DEATH_TEST
+
+// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
+// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if
+// death tests are supported; otherwise they just issue a warning.  This is
+// useful when you are combining death test assertions with normal test
+// assertions in one test.
+#if GTEST_HAS_DEATH_TEST
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+    EXPECT_DEATH(statement, regex)
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+    ASSERT_DEATH(statement, regex)
+#else
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+    GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, )
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+    GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return)
+#endif
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
diff --git a/third_party/googletest/src/include/gtest/gtest-message.h b/third_party/googletest/src/include/gtest/gtest-message.h
new file mode 100644 (file)
index 0000000..9b7142f
--- /dev/null
@@ -0,0 +1,230 @@
+// Copyright 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: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the Message class.
+//
+// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
+// leave some internal implementation details in this header file.
+// They are clearly marked by comments like this:
+//
+//   // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+//
+// Such code is NOT meant to be used by a user directly, and is subject
+// to CHANGE WITHOUT NOTICE.  Therefore DO NOT DEPEND ON IT in a user
+// program!
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+
+#include <limits>
+
+#include "gtest/internal/gtest-string.h"
+#include "gtest/internal/gtest-internal.h"
+
+namespace testing {
+
+// The Message class works like an ostream repeater.
+//
+// Typical usage:
+//
+//   1. You stream a bunch of values to a Message object.
+//      It will remember the text in a stringstream.
+//   2. Then you stream the Message object to an ostream.
+//      This causes the text in the Message to be streamed
+//      to the ostream.
+//
+// For example;
+//
+//   testing::Message foo;
+//   foo << 1 << " != " << 2;
+//   std::cout << foo;
+//
+// will print "1 != 2".
+//
+// Message is not intended to be inherited from.  In particular, its
+// destructor is not virtual.
+//
+// Note that stringstream behaves differently in gcc and in MSVC.  You
+// can stream a NULL char pointer to it in the former, but not in the
+// latter (it causes an access violation if you do).  The Message
+// class hides this difference by treating a NULL char pointer as
+// "(null)".
+class GTEST_API_ Message {
+ private:
+  // The type of basic IO manipulators (endl, ends, and flush) for
+  // narrow streams.
+  typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&);
+
+ public:
+  // Constructs an empty Message.
+  // We allocate the stringstream separately because otherwise each use of
+  // ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
+  // stack frame leading to huge stack frames in some cases; gcc does not reuse
+  // the stack space.
+  Message() : ss_(new ::std::stringstream) {
+    // By default, we want there to be enough precision when printing
+    // a double to a Message.
+    *ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2);
+  }
+
+  // Copy constructor.
+  Message(const Message& msg) : ss_(new ::std::stringstream) {  // NOLINT
+    *ss_ << msg.GetString();
+  }
+
+  // Constructs a Message from a C-string.
+  explicit Message(const char* str) : ss_(new ::std::stringstream) {
+    *ss_ << str;
+  }
+
+#if GTEST_OS_SYMBIAN
+  // Streams a value (either a pointer or not) to this object.
+  template <typename T>
+  inline Message& operator <<(const T& value) {
+    StreamHelper(typename internal::is_pointer<T>::type(), value);
+    return *this;
+  }
+#else
+  // Streams a non-pointer value to this object.
+  template <typename T>
+  inline Message& operator <<(const T& val) {
+    ::GTestStreamToHelper(ss_.get(), val);
+    return *this;
+  }
+
+  // Streams a pointer value to this object.
+  //
+  // This function is an overload of the previous one.  When you
+  // stream a pointer to a Message, this definition will be used as it
+  // is more specialized.  (The C++ Standard, section
+  // [temp.func.order].)  If you stream a non-pointer, then the
+  // previous definition will be used.
+  //
+  // The reason for this overload is that streaming a NULL pointer to
+  // ostream is undefined behavior.  Depending on the compiler, you
+  // may get "0", "(nil)", "(null)", or an access violation.  To
+  // ensure consistent result across compilers, we always treat NULL
+  // as "(null)".
+  template <typename T>
+  inline Message& operator <<(T* const& pointer) {  // NOLINT
+    if (pointer == NULL) {
+      *ss_ << "(null)";
+    } else {
+      ::GTestStreamToHelper(ss_.get(), pointer);
+    }
+    return *this;
+  }
+#endif  // GTEST_OS_SYMBIAN
+
+  // Since the basic IO manipulators are overloaded for both narrow
+  // and wide streams, we have to provide this specialized definition
+  // of operator <<, even though its body is the same as the
+  // templatized version above.  Without this definition, streaming
+  // endl or other basic IO manipulators to Message will confuse the
+  // compiler.
+  Message& operator <<(BasicNarrowIoManip val) {
+    *ss_ << val;
+    return *this;
+  }
+
+  // Instead of 1/0, we want to see true/false for bool values.
+  Message& operator <<(bool b) {
+    return *this << (b ? "true" : "false");
+  }
+
+  // These two overloads allow streaming a wide C string to a Message
+  // using the UTF-8 encoding.
+  Message& operator <<(const wchar_t* wide_c_str) {
+    return *this << internal::String::ShowWideCString(wide_c_str);
+  }
+  Message& operator <<(wchar_t* wide_c_str) {
+    return *this << internal::String::ShowWideCString(wide_c_str);
+  }
+
+#if GTEST_HAS_STD_WSTRING
+  // Converts the given wide string to a narrow string using the UTF-8
+  // encoding, and streams the result to this Message object.
+  Message& operator <<(const ::std::wstring& wstr);
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+  // Converts the given wide string to a narrow string using the UTF-8
+  // encoding, and streams the result to this Message object.
+  Message& operator <<(const ::wstring& wstr);
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+  // Gets the text streamed to this object so far as a String.
+  // Each '\0' character in the buffer is replaced with "\\0".
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  internal::String GetString() const {
+    return internal::StringStreamToString(ss_.get());
+  }
+
+ private:
+
+#if GTEST_OS_SYMBIAN
+  // These are needed as the Nokia Symbian Compiler cannot decide between
+  // const T& and const T* in a function template. The Nokia compiler _can_
+  // decide between class template specializations for T and T*, so a
+  // tr1::type_traits-like is_pointer works, and we can overload on that.
+  template <typename T>
+  inline void StreamHelper(internal::true_type /*dummy*/, T* pointer) {
+    if (pointer == NULL) {
+      *ss_ << "(null)";
+    } else {
+      ::GTestStreamToHelper(ss_.get(), pointer);
+    }
+  }
+  template <typename T>
+  inline void StreamHelper(internal::false_type /*dummy*/, const T& value) {
+    ::GTestStreamToHelper(ss_.get(), value);
+  }
+#endif  // GTEST_OS_SYMBIAN
+
+  // We'll hold the text streamed to this object here.
+  const internal::scoped_ptr< ::std::stringstream> ss_;
+
+  // We declare (but don't implement) this to prevent the compiler
+  // from implementing the assignment operator.
+  void operator=(const Message&);
+};
+
+// Streams a Message to an ostream.
+inline std::ostream& operator <<(std::ostream& os, const Message& sb) {
+  return os << sb.GetString();
+}
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
diff --git a/third_party/googletest/src/include/gtest/gtest-param-test.h b/third_party/googletest/src/include/gtest/gtest-param-test.h
new file mode 100644 (file)
index 0000000..6407cfd
--- /dev/null
@@ -0,0 +1,1421 @@
+// This file was GENERATED by command:
+//     pump.py gtest-param-test.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008, 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.
+//
+// Authors: vladl@google.com (Vlad Losev)
+//
+// Macros and functions for implementing parameterized tests
+// in Google C++ Testing Framework (Google Test)
+//
+// This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+
+
+// Value-parameterized tests allow you to test your code with different
+// parameters without writing multiple copies of the same test.
+//
+// Here is how you use value-parameterized tests:
+
+#if 0
+
+// To write value-parameterized tests, first you should define a fixture
+// class. It is usually derived from testing::TestWithParam<T> (see below for
+// another inheritance scheme that's sometimes useful in more complicated
+// class hierarchies), where the type of your parameter values.
+// TestWithParam<T> is itself derived from testing::Test. T can be any
+// copyable type. If it's a raw pointer, you are responsible for managing the
+// lifespan of the pointed values.
+
+class FooTest : public ::testing::TestWithParam<const char*> {
+  // You can implement all the usual class fixture members here.
+};
+
+// Then, use the TEST_P macro to define as many parameterized tests
+// for this fixture as you want. The _P suffix is for "parameterized"
+// or "pattern", whichever you prefer to think.
+
+TEST_P(FooTest, DoesBlah) {
+  // Inside a test, access the test parameter with the GetParam() method
+  // of the TestWithParam<T> class:
+  EXPECT_TRUE(foo.Blah(GetParam()));
+  ...
+}
+
+TEST_P(FooTest, HasBlahBlah) {
+  ...
+}
+
+// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test
+// case with any set of parameters you want. Google Test defines a number
+// of functions for generating test parameters. They return what we call
+// (surprise!) parameter generators. Here is a  summary of them, which
+// are all in the testing namespace:
+//
+//
+//  Range(begin, end [, step]) - Yields values {begin, begin+step,
+//                               begin+step+step, ...}. The values do not
+//                               include end. step defaults to 1.
+//  Values(v1, v2, ..., vN)    - Yields values {v1, v2, ..., vN}.
+//  ValuesIn(container)        - Yields values from a C-style array, an STL
+//  ValuesIn(begin,end)          container, or an iterator range [begin, end).
+//  Bool()                     - Yields sequence {false, true}.
+//  Combine(g1, g2, ..., gN)   - Yields all combinations (the Cartesian product
+//                               for the math savvy) of the values generated
+//                               by the N generators.
+//
+// For more details, see comments at the definitions of these functions below
+// in this file.
+//
+// The following statement will instantiate tests from the FooTest test case
+// each with parameter values "meeny", "miny", and "moe".
+
+INSTANTIATE_TEST_CASE_P(InstantiationName,
+                        FooTest,
+                        Values("meeny", "miny", "moe"));
+
+// To distinguish different instances of the pattern, (yes, you
+// can instantiate it more then once) the first argument to the
+// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the
+// actual test case name. Remember to pick unique prefixes for different
+// instantiations. The tests from the instantiation above will have
+// these names:
+//
+//    * InstantiationName/FooTest.DoesBlah/0 for "meeny"
+//    * InstantiationName/FooTest.DoesBlah/1 for "miny"
+//    * InstantiationName/FooTest.DoesBlah/2 for "moe"
+//    * InstantiationName/FooTest.HasBlahBlah/0 for "meeny"
+//    * InstantiationName/FooTest.HasBlahBlah/1 for "miny"
+//    * InstantiationName/FooTest.HasBlahBlah/2 for "moe"
+//
+// You can use these names in --gtest_filter.
+//
+// This statement will instantiate all tests from FooTest again, each
+// with parameter values "cat" and "dog":
+
+const char* pets[] = {"cat", "dog"};
+INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
+
+// The tests from the instantiation above will have these names:
+//
+//    * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
+//    * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
+//    * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
+//    * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog"
+//
+// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests
+// in the given test case, whether their definitions come before or
+// AFTER the INSTANTIATE_TEST_CASE_P statement.
+//
+// Please also note that generator expressions (including parameters to the
+// generators) are evaluated in InitGoogleTest(), after main() has started.
+// This allows the user on one hand, to adjust generator parameters in order
+// to dynamically determine a set of tests to run and on the other hand,
+// give the user a chance to inspect the generated tests with Google Test
+// reflection API before RUN_ALL_TESTS() is executed.
+//
+// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
+// for more examples.
+//
+// In the future, we plan to publish the API for defining new parameter
+// generators. But for now this interface remains part of the internal
+// implementation and is subject to change.
+//
+//
+// A parameterized test fixture must be derived from testing::Test and from
+// testing::WithParamInterface<T>, where T is the type of the parameter
+// values. Inheriting from TestWithParam<T> satisfies that requirement because
+// TestWithParam<T> inherits from both Test and WithParamInterface. In more
+// complicated hierarchies, however, it is occasionally useful to inherit
+// separately from Test and WithParamInterface. For example:
+
+class BaseTest : public ::testing::Test {
+  // You can inherit all the usual members for a non-parameterized test
+  // fixture here.
+};
+
+class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
+  // The usual test fixture members go here too.
+};
+
+TEST_F(BaseTest, HasFoo) {
+  // This is an ordinary non-parameterized test.
+}
+
+TEST_P(DerivedTest, DoesBlah) {
+  // GetParam works just the same here as if you inherit from TestWithParam.
+  EXPECT_TRUE(foo.Blah(GetParam()));
+}
+
+#endif  // 0
+
+#include "gtest/internal/gtest-port.h"
+
+#if !GTEST_OS_SYMBIAN
+# include <utility>
+#endif
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-param-util-generated.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Functions producing parameter generators.
+//
+// Google Test uses these generators to produce parameters for value-
+// parameterized tests. When a parameterized test case is instantiated
+// with a particular generator, Google Test creates and runs tests
+// for each element in the sequence produced by the generator.
+//
+// In the following sample, tests from test case FooTest are instantiated
+// each three times with parameter values 3, 5, and 8:
+//
+// class FooTest : public TestWithParam<int> { ... };
+//
+// TEST_P(FooTest, TestThis) {
+// }
+// TEST_P(FooTest, TestThat) {
+// }
+// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8));
+//
+
+// Range() returns generators providing sequences of values in a range.
+//
+// Synopsis:
+// Range(start, end)
+//   - returns a generator producing a sequence of values {start, start+1,
+//     start+2, ..., }.
+// Range(start, end, step)
+//   - returns a generator producing a sequence of values {start, start+step,
+//     start+step+step, ..., }.
+// Notes:
+//   * The generated sequences never include end. For example, Range(1, 5)
+//     returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2)
+//     returns a generator producing {1, 3, 5, 7}.
+//   * start and end must have the same type. That type may be any integral or
+//     floating-point type or a user defined type satisfying these conditions:
+//     * It must be assignable (have operator=() defined).
+//     * It must have operator+() (operator+(int-compatible type) for
+//       two-operand version).
+//     * It must have operator<() defined.
+//     Elements in the resulting sequences will also have that type.
+//   * Condition start < end must be satisfied in order for resulting sequences
+//     to contain any elements.
+//
+template <typename T, typename IncrementT>
+internal::ParamGenerator<T> Range(T start, T end, IncrementT step) {
+  return internal::ParamGenerator<T>(
+      new internal::RangeGenerator<T, IncrementT>(start, end, step));
+}
+
+template <typename T>
+internal::ParamGenerator<T> Range(T start, T end) {
+  return Range(start, end, 1);
+}
+
+// ValuesIn() function allows generation of tests with parameters coming from
+// a container.
+//
+// Synopsis:
+// ValuesIn(const T (&array)[N])
+//   - returns a generator producing sequences with elements from
+//     a C-style array.
+// ValuesIn(const Container& container)
+//   - returns a generator producing sequences with elements from
+//     an STL-style container.
+// ValuesIn(Iterator begin, Iterator end)
+//   - returns a generator producing sequences with elements from
+//     a range [begin, end) defined by a pair of STL-style iterators. These
+//     iterators can also be plain C pointers.
+//
+// Please note that ValuesIn copies the values from the containers
+// passed in and keeps them to generate tests in RUN_ALL_TESTS().
+//
+// Examples:
+//
+// This instantiates tests from test case StringTest
+// each with C-string values of "foo", "bar", and "baz":
+//
+// const char* strings[] = {"foo", "bar", "baz"};
+// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings));
+//
+// This instantiates tests from test case StlStringTest
+// each with STL strings with values "a" and "b":
+//
+// ::std::vector< ::std::string> GetParameterStrings() {
+//   ::std::vector< ::std::string> v;
+//   v.push_back("a");
+//   v.push_back("b");
+//   return v;
+// }
+//
+// INSTANTIATE_TEST_CASE_P(CharSequence,
+//                         StlStringTest,
+//                         ValuesIn(GetParameterStrings()));
+//
+//
+// This will also instantiate tests from CharTest
+// each with parameter values 'a' and 'b':
+//
+// ::std::list<char> GetParameterChars() {
+//   ::std::list<char> list;
+//   list.push_back('a');
+//   list.push_back('b');
+//   return list;
+// }
+// ::std::list<char> l = GetParameterChars();
+// INSTANTIATE_TEST_CASE_P(CharSequence2,
+//                         CharTest,
+//                         ValuesIn(l.begin(), l.end()));
+//
+template <typename ForwardIterator>
+internal::ParamGenerator<
+  typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end) {
+  typedef typename ::testing::internal::IteratorTraits<ForwardIterator>
+      ::value_type ParamType;
+  return internal::ParamGenerator<ParamType>(
+      new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
+}
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
+  return ValuesIn(array, array + N);
+}
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container) {
+  return ValuesIn(container.begin(), container.end());
+}
+
+// Values() allows generating tests from explicitly specified list of
+// parameters.
+//
+// Synopsis:
+// Values(T v1, T v2, ..., T vN)
+//   - returns a generator producing sequences with elements v1, v2, ..., vN.
+//
+// For example, this instantiates tests from test case BarTest each
+// with values "one", "two", and "three":
+//
+// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three"));
+//
+// This instantiates tests from test case BazTest each with values 1, 2, 3.5.
+// The exact type of values will depend on the type of parameter in BazTest.
+//
+// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5));
+//
+// Currently, Values() supports from 1 to 50 parameters.
+//
+template <typename T1>
+internal::ValueArray1<T1> Values(T1 v1) {
+  return internal::ValueArray1<T1>(v1);
+}
+
+template <typename T1, typename T2>
+internal::ValueArray2<T1, T2> Values(T1 v1, T2 v2) {
+  return internal::ValueArray2<T1, T2>(v1, v2);
+}
+
+template <typename T1, typename T2, typename T3>
+internal::ValueArray3<T1, T2, T3> Values(T1 v1, T2 v2, T3 v3) {
+  return internal::ValueArray3<T1, T2, T3>(v1, v2, v3);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+internal::ValueArray4<T1, T2, T3, T4> Values(T1 v1, T2 v2, T3 v3, T4 v4) {
+  return internal::ValueArray4<T1, T2, T3, T4>(v1, v2, v3, v4);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+internal::ValueArray5<T1, T2, T3, T4, T5> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5) {
+  return internal::ValueArray5<T1, T2, T3, T4, T5>(v1, v2, v3, v4, v5);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+internal::ValueArray6<T1, T2, T3, T4, T5, T6> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6) {
+  return internal::ValueArray6<T1, T2, T3, T4, T5, T6>(v1, v2, v3, v4, v5, v6);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+internal::ValueArray7<T1, T2, T3, T4, T5, T6, T7> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6, T7 v7) {
+  return internal::ValueArray7<T1, T2, T3, T4, T5, T6, T7>(v1, v2, v3, v4, v5,
+      v6, v7);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+internal::ValueArray8<T1, T2, T3, T4, T5, T6, T7, T8> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8) {
+  return internal::ValueArray8<T1, T2, T3, T4, T5, T6, T7, T8>(v1, v2, v3, v4,
+      v5, v6, v7, v8);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+internal::ValueArray9<T1, T2, T3, T4, T5, T6, T7, T8, T9> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9) {
+  return internal::ValueArray9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(v1, v2, v3,
+      v4, v5, v6, v7, v8, v9);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+internal::ValueArray10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> Values(T1 v1,
+    T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10) {
+  return internal::ValueArray10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(v1,
+      v2, v3, v4, v5, v6, v7, v8, v9, v10);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+internal::ValueArray11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
+    T11> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11) {
+  return internal::ValueArray11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
+      T11>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+internal::ValueArray12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+    T12> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12) {
+  return internal::ValueArray12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+internal::ValueArray13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+    T13> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13) {
+  return internal::ValueArray13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+internal::ValueArray14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) {
+  return internal::ValueArray14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+      v14);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+internal::ValueArray15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+    T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) {
+  return internal::ValueArray15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+      v13, v14, v15);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+internal::ValueArray16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16) {
+  return internal::ValueArray16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+      v12, v13, v14, v15, v16);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+internal::ValueArray17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17) {
+  return internal::ValueArray17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+      v11, v12, v13, v14, v15, v16, v17);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+internal::ValueArray18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+    T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18) {
+  return internal::ValueArray18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+      v10, v11, v12, v13, v14, v15, v16, v17, v18);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+internal::ValueArray19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+    T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+    T15 v15, T16 v16, T17 v17, T18 v18, T19 v19) {
+  return internal::ValueArray19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19>(v1, v2, v3, v4, v5, v6, v7, v8,
+      v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+internal::ValueArray20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20) {
+  return internal::ValueArray20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20>(v1, v2, v3, v4, v5, v6, v7,
+      v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+internal::ValueArray21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21) {
+  return internal::ValueArray21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21>(v1, v2, v3, v4, v5, v6,
+      v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+internal::ValueArray22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22) {
+  return internal::ValueArray22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22>(v1, v2, v3, v4,
+      v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+internal::ValueArray23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23) {
+  return internal::ValueArray23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23>(v1, v2, v3,
+      v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+internal::ValueArray24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24) {
+  return internal::ValueArray24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24>(v1, v2,
+      v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18,
+      v19, v20, v21, v22, v23, v24);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+internal::ValueArray25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Values(T1 v1,
+    T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11,
+    T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19,
+    T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25) {
+  return internal::ValueArray25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25>(v1,
+      v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17,
+      v18, v19, v20, v21, v22, v23, v24, v25);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+internal::ValueArray26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+    T26> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26) {
+  return internal::ValueArray26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
+      v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+internal::ValueArray27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+    T27> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27) {
+  return internal::ValueArray27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14,
+      v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+internal::ValueArray28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+    T28> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28) {
+  return internal::ValueArray28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+      v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27,
+      v28);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+internal::ValueArray29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29) {
+  return internal::ValueArray29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+      v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26,
+      v27, v28, v29);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+internal::ValueArray30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+    T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+    T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+    T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) {
+  return internal::ValueArray30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+      v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25,
+      v26, v27, v28, v29, v30);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+internal::ValueArray31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) {
+  return internal::ValueArray31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+      v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24,
+      v25, v26, v27, v28, v29, v30, v31);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+internal::ValueArray32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32) {
+  return internal::ValueArray32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+      v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+internal::ValueArray33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+    T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33) {
+  return internal::ValueArray33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33>(v1, v2, v3, v4, v5, v6, v7, v8,
+      v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32, v33);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+internal::ValueArray34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+    T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+    T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22,
+    T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30,
+    T31 v31, T32 v32, T33 v33, T34 v34) {
+  return internal::ValueArray34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34>(v1, v2, v3, v4, v5, v6, v7,
+      v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22,
+      v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+internal::ValueArray35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+    T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+    T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35) {
+  return internal::ValueArray35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35>(v1, v2, v3, v4, v5, v6,
+      v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21,
+      v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+internal::ValueArray36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+    T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+    T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36) {
+  return internal::ValueArray36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36>(v1, v2, v3, v4,
+      v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+      v34, v35, v36);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+internal::ValueArray37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+    T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+    T37 v37) {
+  return internal::ValueArray37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37>(v1, v2, v3,
+      v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+      v34, v35, v36, v37);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+internal::ValueArray38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+    T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+    T37 v37, T38 v38) {
+  return internal::ValueArray38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38>(v1, v2,
+      v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18,
+      v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32,
+      v33, v34, v35, v36, v37, v38);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+internal::ValueArray39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+    T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+    T37 v37, T38 v38, T39 v39) {
+  return internal::ValueArray39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39>(v1,
+      v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17,
+      v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31,
+      v32, v33, v34, v35, v36, v37, v38, v39);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+internal::ValueArray40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Values(T1 v1,
+    T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11,
+    T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19,
+    T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27,
+    T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35,
+    T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) {
+  return internal::ValueArray40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
+      v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29,
+      v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+internal::ValueArray41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+    T41> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41) {
+  return internal::ValueArray41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14,
+      v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28,
+      v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+internal::ValueArray42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+    T42> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+    T42 v42) {
+  return internal::ValueArray42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+      v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27,
+      v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41,
+      v42);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+internal::ValueArray43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+    T43> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+    T42 v42, T43 v43) {
+  return internal::ValueArray43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+      v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26,
+      v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40,
+      v41, v42, v43);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+internal::ValueArray44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+    T42 v42, T43 v43, T44 v44) {
+  return internal::ValueArray44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+      v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25,
+      v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39,
+      v40, v41, v42, v43, v44);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+internal::ValueArray45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+    T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+    T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+    T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32,
+    T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40,
+    T41 v41, T42 v42, T43 v43, T44 v44, T45 v45) {
+  return internal::ValueArray45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+      v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24,
+      v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38,
+      v39, v40, v41, v42, v43, v44, v45);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+internal::ValueArray46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+    T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) {
+  return internal::ValueArray46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+      v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37,
+      v38, v39, v40, v41, v42, v43, v44, v45, v46);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+internal::ValueArray47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+    T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) {
+  return internal::ValueArray47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47>(v1, v2, v3, v4, v5, v6, v7, v8,
+      v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37,
+      v38, v39, v40, v41, v42, v43, v44, v45, v46, v47);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+internal::ValueArray48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+    T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+    T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47,
+    T48 v48) {
+  return internal::ValueArray48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47, T48>(v1, v2, v3, v4, v5, v6, v7,
+      v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22,
+      v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36,
+      v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+internal::ValueArray49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48, T49> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+    T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+    T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22,
+    T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30,
+    T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38,
+    T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46,
+    T47 v47, T48 v48, T49 v49) {
+  return internal::ValueArray49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47, T48, T49>(v1, v2, v3, v4, v5, v6,
+      v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21,
+      v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35,
+      v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+internal::ValueArray50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48, T49, T50> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+    T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+    T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37,
+    T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45,
+    T46 v46, T47 v47, T48 v48, T49 v49, T50 v50) {
+  return internal::ValueArray50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>(v1, v2, v3, v4,
+      v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+      v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47,
+      v48, v49, v50);
+}
+
+// Bool() allows generating tests with parameters in a set of (false, true).
+//
+// Synopsis:
+// Bool()
+//   - returns a generator producing sequences with elements {false, true}.
+//
+// It is useful when testing code that depends on Boolean flags. Combinations
+// of multiple flags can be tested when several Bool()'s are combined using
+// Combine() function.
+//
+// In the following example all tests in the test case FlagDependentTest
+// will be instantiated twice with parameters false and true.
+//
+// class FlagDependentTest : public testing::TestWithParam<bool> {
+//   virtual void SetUp() {
+//     external_flag = GetParam();
+//   }
+// }
+// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool());
+//
+inline internal::ParamGenerator<bool> Bool() {
+  return Values(false, true);
+}
+
+# if GTEST_HAS_COMBINE
+// Combine() allows the user to combine two or more sequences to produce
+// values of a Cartesian product of those sequences' elements.
+//
+// Synopsis:
+// Combine(gen1, gen2, ..., genN)
+//   - returns a generator producing sequences with elements coming from
+//     the Cartesian product of elements from the sequences generated by
+//     gen1, gen2, ..., genN. The sequence elements will have a type of
+//     tuple<T1, T2, ..., TN> where T1, T2, ..., TN are the types
+//     of elements from sequences produces by gen1, gen2, ..., genN.
+//
+// Combine can have up to 10 arguments. This number is currently limited
+// by the maximum number of elements in the tuple implementation used by Google
+// Test.
+//
+// Example:
+//
+// This will instantiate tests in test case AnimalTest each one with
+// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
+// tuple("dog", BLACK), and tuple("dog", WHITE):
+//
+// enum Color { BLACK, GRAY, WHITE };
+// class AnimalTest
+//     : public testing::TestWithParam<tuple<const char*, Color> > {...};
+//
+// TEST_P(AnimalTest, AnimalLooksNice) {...}
+//
+// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest,
+//                         Combine(Values("cat", "dog"),
+//                                 Values(BLACK, WHITE)));
+//
+// This will instantiate tests in FlagDependentTest with all variations of two
+// Boolean flags:
+//
+// class FlagDependentTest
+//     : public testing::TestWithParam<tuple(bool, bool)> > {
+//   virtual void SetUp() {
+//     // Assigns external_flag_1 and external_flag_2 values from the tuple.
+//     tie(external_flag_1, external_flag_2) = GetParam();
+//   }
+// };
+//
+// TEST_P(FlagDependentTest, TestFeature1) {
+//   // Test your code using external_flag_1 and external_flag_2 here.
+// }
+// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest,
+//                         Combine(Bool(), Bool()));
+//
+template <typename Generator1, typename Generator2>
+internal::CartesianProductHolder2<Generator1, Generator2> Combine(
+    const Generator1& g1, const Generator2& g2) {
+  return internal::CartesianProductHolder2<Generator1, Generator2>(
+      g1, g2);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3>
+internal::CartesianProductHolder3<Generator1, Generator2, Generator3> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3) {
+  return internal::CartesianProductHolder3<Generator1, Generator2, Generator3>(
+      g1, g2, g3);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4>
+internal::CartesianProductHolder4<Generator1, Generator2, Generator3,
+    Generator4> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4) {
+  return internal::CartesianProductHolder4<Generator1, Generator2, Generator3,
+      Generator4>(
+      g1, g2, g3, g4);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5>
+internal::CartesianProductHolder5<Generator1, Generator2, Generator3,
+    Generator4, Generator5> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5) {
+  return internal::CartesianProductHolder5<Generator1, Generator2, Generator3,
+      Generator4, Generator5>(
+      g1, g2, g3, g4, g5);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6>
+internal::CartesianProductHolder6<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6) {
+  return internal::CartesianProductHolder6<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6>(
+      g1, g2, g3, g4, g5, g6);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7>
+internal::CartesianProductHolder7<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7) {
+  return internal::CartesianProductHolder7<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7>(
+      g1, g2, g3, g4, g5, g6, g7);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7, typename Generator8>
+internal::CartesianProductHolder8<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7, Generator8> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7, const Generator8& g8) {
+  return internal::CartesianProductHolder8<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7, Generator8>(
+      g1, g2, g3, g4, g5, g6, g7, g8);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7, typename Generator8, typename Generator9>
+internal::CartesianProductHolder9<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7, Generator8,
+    Generator9> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7, const Generator8& g8, const Generator9& g9) {
+  return internal::CartesianProductHolder9<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7, Generator8, Generator9>(
+      g1, g2, g3, g4, g5, g6, g7, g8, g9);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7, typename Generator8, typename Generator9,
+    typename Generator10>
+internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7, Generator8, Generator9,
+    Generator10> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7, const Generator8& g8, const Generator9& g9,
+        const Generator10& g10) {
+  return internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7, Generator8, Generator9,
+      Generator10>(
+      g1, g2, g3, g4, g5, g6, g7, g8, g9, g10);
+}
+# endif  // GTEST_HAS_COMBINE
+
+
+
+# define TEST_P(test_case_name, test_name) \
+  class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
+      : public test_case_name { \
+   public: \
+    GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \
+    virtual void TestBody(); \
+   private: \
+    static int AddToRegistry() { \
+      ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+          GetTestCasePatternHolder<test_case_name>(\
+              #test_case_name, __FILE__, __LINE__)->AddTestPattern(\
+                  #test_case_name, \
+                  #test_name, \
+                  new ::testing::internal::TestMetaFactory< \
+                      GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \
+      return 0; \
+    } \
+    static int gtest_registering_dummy_; \
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(\
+        GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \
+  }; \
+  int GTEST_TEST_CLASS_NAME_(test_case_name, \
+                             test_name)::gtest_registering_dummy_ = \
+      GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \
+  void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
+
+# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
+  ::testing::internal::ParamGenerator<test_case_name::ParamType> \
+      gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
+  int gtest_##prefix##test_case_name##_dummy_ = \
+      ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+          GetTestCasePatternHolder<test_case_name>(\
+              #test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\
+                  #prefix, \
+                  &gtest_##prefix##test_case_name##_EvalGenerator_, \
+                  __FILE__, __LINE__)
+
+}  // namespace testing
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
diff --git a/third_party/googletest/src/include/gtest/gtest-param-test.h.pump b/third_party/googletest/src/include/gtest/gtest-param-test.h.pump
new file mode 100644 (file)
index 0000000..401cb51
--- /dev/null
@@ -0,0 +1,487 @@
+$$ -*- mode: c++; -*-
+$var n = 50  $$ Maximum length of Values arguments we want to support.
+$var maxtuple = 10  $$ Maximum number of Combine arguments we want to support.
+// Copyright 2008, 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.
+//
+// Authors: vladl@google.com (Vlad Losev)
+//
+// Macros and functions for implementing parameterized tests
+// in Google C++ Testing Framework (Google Test)
+//
+// This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+
+
+// Value-parameterized tests allow you to test your code with different
+// parameters without writing multiple copies of the same test.
+//
+// Here is how you use value-parameterized tests:
+
+#if 0
+
+// To write value-parameterized tests, first you should define a fixture
+// class. It is usually derived from testing::TestWithParam<T> (see below for
+// another inheritance scheme that's sometimes useful in more complicated
+// class hierarchies), where the type of your parameter values.
+// TestWithParam<T> is itself derived from testing::Test. T can be any
+// copyable type. If it's a raw pointer, you are responsible for managing the
+// lifespan of the pointed values.
+
+class FooTest : public ::testing::TestWithParam<const char*> {
+  // You can implement all the usual class fixture members here.
+};
+
+// Then, use the TEST_P macro to define as many parameterized tests
+// for this fixture as you want. The _P suffix is for "parameterized"
+// or "pattern", whichever you prefer to think.
+
+TEST_P(FooTest, DoesBlah) {
+  // Inside a test, access the test parameter with the GetParam() method
+  // of the TestWithParam<T> class:
+  EXPECT_TRUE(foo.Blah(GetParam()));
+  ...
+}
+
+TEST_P(FooTest, HasBlahBlah) {
+  ...
+}
+
+// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test
+// case with any set of parameters you want. Google Test defines a number
+// of functions for generating test parameters. They return what we call
+// (surprise!) parameter generators. Here is a  summary of them, which
+// are all in the testing namespace:
+//
+//
+//  Range(begin, end [, step]) - Yields values {begin, begin+step,
+//                               begin+step+step, ...}. The values do not
+//                               include end. step defaults to 1.
+//  Values(v1, v2, ..., vN)    - Yields values {v1, v2, ..., vN}.
+//  ValuesIn(container)        - Yields values from a C-style array, an STL
+//  ValuesIn(begin,end)          container, or an iterator range [begin, end).
+//  Bool()                     - Yields sequence {false, true}.
+//  Combine(g1, g2, ..., gN)   - Yields all combinations (the Cartesian product
+//                               for the math savvy) of the values generated
+//                               by the N generators.
+//
+// For more details, see comments at the definitions of these functions below
+// in this file.
+//
+// The following statement will instantiate tests from the FooTest test case
+// each with parameter values "meeny", "miny", and "moe".
+
+INSTANTIATE_TEST_CASE_P(InstantiationName,
+                        FooTest,
+                        Values("meeny", "miny", "moe"));
+
+// To distinguish different instances of the pattern, (yes, you
+// can instantiate it more then once) the first argument to the
+// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the
+// actual test case name. Remember to pick unique prefixes for different
+// instantiations. The tests from the instantiation above will have
+// these names:
+//
+//    * InstantiationName/FooTest.DoesBlah/0 for "meeny"
+//    * InstantiationName/FooTest.DoesBlah/1 for "miny"
+//    * InstantiationName/FooTest.DoesBlah/2 for "moe"
+//    * InstantiationName/FooTest.HasBlahBlah/0 for "meeny"
+//    * InstantiationName/FooTest.HasBlahBlah/1 for "miny"
+//    * InstantiationName/FooTest.HasBlahBlah/2 for "moe"
+//
+// You can use these names in --gtest_filter.
+//
+// This statement will instantiate all tests from FooTest again, each
+// with parameter values "cat" and "dog":
+
+const char* pets[] = {"cat", "dog"};
+INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
+
+// The tests from the instantiation above will have these names:
+//
+//    * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
+//    * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
+//    * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
+//    * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog"
+//
+// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests
+// in the given test case, whether their definitions come before or
+// AFTER the INSTANTIATE_TEST_CASE_P statement.
+//
+// Please also note that generator expressions (including parameters to the
+// generators) are evaluated in InitGoogleTest(), after main() has started.
+// This allows the user on one hand, to adjust generator parameters in order
+// to dynamically determine a set of tests to run and on the other hand,
+// give the user a chance to inspect the generated tests with Google Test
+// reflection API before RUN_ALL_TESTS() is executed.
+//
+// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
+// for more examples.
+//
+// In the future, we plan to publish the API for defining new parameter
+// generators. But for now this interface remains part of the internal
+// implementation and is subject to change.
+//
+//
+// A parameterized test fixture must be derived from testing::Test and from
+// testing::WithParamInterface<T>, where T is the type of the parameter
+// values. Inheriting from TestWithParam<T> satisfies that requirement because
+// TestWithParam<T> inherits from both Test and WithParamInterface. In more
+// complicated hierarchies, however, it is occasionally useful to inherit
+// separately from Test and WithParamInterface. For example:
+
+class BaseTest : public ::testing::Test {
+  // You can inherit all the usual members for a non-parameterized test
+  // fixture here.
+};
+
+class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
+  // The usual test fixture members go here too.
+};
+
+TEST_F(BaseTest, HasFoo) {
+  // This is an ordinary non-parameterized test.
+}
+
+TEST_P(DerivedTest, DoesBlah) {
+  // GetParam works just the same here as if you inherit from TestWithParam.
+  EXPECT_TRUE(foo.Blah(GetParam()));
+}
+
+#endif  // 0
+
+#include "gtest/internal/gtest-port.h"
+
+#if !GTEST_OS_SYMBIAN
+# include <utility>
+#endif
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-param-util-generated.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Functions producing parameter generators.
+//
+// Google Test uses these generators to produce parameters for value-
+// parameterized tests. When a parameterized test case is instantiated
+// with a particular generator, Google Test creates and runs tests
+// for each element in the sequence produced by the generator.
+//
+// In the following sample, tests from test case FooTest are instantiated
+// each three times with parameter values 3, 5, and 8:
+//
+// class FooTest : public TestWithParam<int> { ... };
+//
+// TEST_P(FooTest, TestThis) {
+// }
+// TEST_P(FooTest, TestThat) {
+// }
+// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8));
+//
+
+// Range() returns generators providing sequences of values in a range.
+//
+// Synopsis:
+// Range(start, end)
+//   - returns a generator producing a sequence of values {start, start+1,
+//     start+2, ..., }.
+// Range(start, end, step)
+//   - returns a generator producing a sequence of values {start, start+step,
+//     start+step+step, ..., }.
+// Notes:
+//   * The generated sequences never include end. For example, Range(1, 5)
+//     returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2)
+//     returns a generator producing {1, 3, 5, 7}.
+//   * start and end must have the same type. That type may be any integral or
+//     floating-point type or a user defined type satisfying these conditions:
+//     * It must be assignable (have operator=() defined).
+//     * It must have operator+() (operator+(int-compatible type) for
+//       two-operand version).
+//     * It must have operator<() defined.
+//     Elements in the resulting sequences will also have that type.
+//   * Condition start < end must be satisfied in order for resulting sequences
+//     to contain any elements.
+//
+template <typename T, typename IncrementT>
+internal::ParamGenerator<T> Range(T start, T end, IncrementT step) {
+  return internal::ParamGenerator<T>(
+      new internal::RangeGenerator<T, IncrementT>(start, end, step));
+}
+
+template <typename T>
+internal::ParamGenerator<T> Range(T start, T end) {
+  return Range(start, end, 1);
+}
+
+// ValuesIn() function allows generation of tests with parameters coming from
+// a container.
+//
+// Synopsis:
+// ValuesIn(const T (&array)[N])
+//   - returns a generator producing sequences with elements from
+//     a C-style array.
+// ValuesIn(const Container& container)
+//   - returns a generator producing sequences with elements from
+//     an STL-style container.
+// ValuesIn(Iterator begin, Iterator end)
+//   - returns a generator producing sequences with elements from
+//     a range [begin, end) defined by a pair of STL-style iterators. These
+//     iterators can also be plain C pointers.
+//
+// Please note that ValuesIn copies the values from the containers
+// passed in and keeps them to generate tests in RUN_ALL_TESTS().
+//
+// Examples:
+//
+// This instantiates tests from test case StringTest
+// each with C-string values of "foo", "bar", and "baz":
+//
+// const char* strings[] = {"foo", "bar", "baz"};
+// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings));
+//
+// This instantiates tests from test case StlStringTest
+// each with STL strings with values "a" and "b":
+//
+// ::std::vector< ::std::string> GetParameterStrings() {
+//   ::std::vector< ::std::string> v;
+//   v.push_back("a");
+//   v.push_back("b");
+//   return v;
+// }
+//
+// INSTANTIATE_TEST_CASE_P(CharSequence,
+//                         StlStringTest,
+//                         ValuesIn(GetParameterStrings()));
+//
+//
+// This will also instantiate tests from CharTest
+// each with parameter values 'a' and 'b':
+//
+// ::std::list<char> GetParameterChars() {
+//   ::std::list<char> list;
+//   list.push_back('a');
+//   list.push_back('b');
+//   return list;
+// }
+// ::std::list<char> l = GetParameterChars();
+// INSTANTIATE_TEST_CASE_P(CharSequence2,
+//                         CharTest,
+//                         ValuesIn(l.begin(), l.end()));
+//
+template <typename ForwardIterator>
+internal::ParamGenerator<
+  typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end) {
+  typedef typename ::testing::internal::IteratorTraits<ForwardIterator>
+      ::value_type ParamType;
+  return internal::ParamGenerator<ParamType>(
+      new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
+}
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
+  return ValuesIn(array, array + N);
+}
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container) {
+  return ValuesIn(container.begin(), container.end());
+}
+
+// Values() allows generating tests from explicitly specified list of
+// parameters.
+//
+// Synopsis:
+// Values(T v1, T v2, ..., T vN)
+//   - returns a generator producing sequences with elements v1, v2, ..., vN.
+//
+// For example, this instantiates tests from test case BarTest each
+// with values "one", "two", and "three":
+//
+// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three"));
+//
+// This instantiates tests from test case BazTest each with values 1, 2, 3.5.
+// The exact type of values will depend on the type of parameter in BazTest.
+//
+// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5));
+//
+// Currently, Values() supports from 1 to $n parameters.
+//
+$range i 1..n
+$for i [[
+$range j 1..i
+
+template <$for j, [[typename T$j]]>
+internal::ValueArray$i<$for j, [[T$j]]> Values($for j, [[T$j v$j]]) {
+  return internal::ValueArray$i<$for j, [[T$j]]>($for j, [[v$j]]);
+}
+
+]]
+
+// Bool() allows generating tests with parameters in a set of (false, true).
+//
+// Synopsis:
+// Bool()
+//   - returns a generator producing sequences with elements {false, true}.
+//
+// It is useful when testing code that depends on Boolean flags. Combinations
+// of multiple flags can be tested when several Bool()'s are combined using
+// Combine() function.
+//
+// In the following example all tests in the test case FlagDependentTest
+// will be instantiated twice with parameters false and true.
+//
+// class FlagDependentTest : public testing::TestWithParam<bool> {
+//   virtual void SetUp() {
+//     external_flag = GetParam();
+//   }
+// }
+// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool());
+//
+inline internal::ParamGenerator<bool> Bool() {
+  return Values(false, true);
+}
+
+# if GTEST_HAS_COMBINE
+// Combine() allows the user to combine two or more sequences to produce
+// values of a Cartesian product of those sequences' elements.
+//
+// Synopsis:
+// Combine(gen1, gen2, ..., genN)
+//   - returns a generator producing sequences with elements coming from
+//     the Cartesian product of elements from the sequences generated by
+//     gen1, gen2, ..., genN. The sequence elements will have a type of
+//     tuple<T1, T2, ..., TN> where T1, T2, ..., TN are the types
+//     of elements from sequences produces by gen1, gen2, ..., genN.
+//
+// Combine can have up to $maxtuple arguments. This number is currently limited
+// by the maximum number of elements in the tuple implementation used by Google
+// Test.
+//
+// Example:
+//
+// This will instantiate tests in test case AnimalTest each one with
+// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
+// tuple("dog", BLACK), and tuple("dog", WHITE):
+//
+// enum Color { BLACK, GRAY, WHITE };
+// class AnimalTest
+//     : public testing::TestWithParam<tuple<const char*, Color> > {...};
+//
+// TEST_P(AnimalTest, AnimalLooksNice) {...}
+//
+// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest,
+//                         Combine(Values("cat", "dog"),
+//                                 Values(BLACK, WHITE)));
+//
+// This will instantiate tests in FlagDependentTest with all variations of two
+// Boolean flags:
+//
+// class FlagDependentTest
+//     : public testing::TestWithParam<tuple(bool, bool)> > {
+//   virtual void SetUp() {
+//     // Assigns external_flag_1 and external_flag_2 values from the tuple.
+//     tie(external_flag_1, external_flag_2) = GetParam();
+//   }
+// };
+//
+// TEST_P(FlagDependentTest, TestFeature1) {
+//   // Test your code using external_flag_1 and external_flag_2 here.
+// }
+// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest,
+//                         Combine(Bool(), Bool()));
+//
+$range i 2..maxtuple
+$for i [[
+$range j 1..i
+
+template <$for j, [[typename Generator$j]]>
+internal::CartesianProductHolder$i<$for j, [[Generator$j]]> Combine(
+    $for j, [[const Generator$j& g$j]]) {
+  return internal::CartesianProductHolder$i<$for j, [[Generator$j]]>(
+      $for j, [[g$j]]);
+}
+
+]]
+# endif  // GTEST_HAS_COMBINE
+
+
+
+# define TEST_P(test_case_name, test_name) \
+  class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
+      : public test_case_name { \
+   public: \
+    GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \
+    virtual void TestBody(); \
+   private: \
+    static int AddToRegistry() { \
+      ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+          GetTestCasePatternHolder<test_case_name>(\
+              #test_case_name, __FILE__, __LINE__)->AddTestPattern(\
+                  #test_case_name, \
+                  #test_name, \
+                  new ::testing::internal::TestMetaFactory< \
+                      GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \
+      return 0; \
+    } \
+    static int gtest_registering_dummy_; \
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(\
+        GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \
+  }; \
+  int GTEST_TEST_CLASS_NAME_(test_case_name, \
+                             test_name)::gtest_registering_dummy_ = \
+      GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \
+  void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
+
+# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
+  ::testing::internal::ParamGenerator<test_case_name::ParamType> \
+      gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
+  int gtest_##prefix##test_case_name##_dummy_ = \
+      ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+          GetTestCasePatternHolder<test_case_name>(\
+              #test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\
+                  #prefix, \
+                  &gtest_##prefix##test_case_name##_EvalGenerator_, \
+                  __FILE__, __LINE__)
+
+}  // namespace testing
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
diff --git a/third_party/googletest/src/include/gtest/gtest-printers.h b/third_party/googletest/src/include/gtest/gtest-printers.h
new file mode 100644 (file)
index 0000000..9cbab3f
--- /dev/null
@@ -0,0 +1,796 @@
+// Copyright 2007, 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: wan@google.com (Zhanyong Wan)
+
+// Google Test - The Google C++ Testing Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+//   void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// A user can teach this function how to print a class type T by
+// defining either operator<<() or PrintTo() in the namespace that
+// defines T.  More specifically, the FIRST defined function in the
+// following list will be used (assuming T is defined in namespace
+// foo):
+//
+//   1. foo::PrintTo(const T&, ostream*)
+//   2. operator<<(ostream&, const T&) defined in either foo or the
+//      global namespace.
+//
+// If none of the above is defined, it will print the debug string of
+// the value if it is a protocol buffer, or print the raw bytes in the
+// value otherwise.
+//
+// To aid debugging: when T is a reference type, the address of the
+// value is also printed; when T is a (const) char pointer, both the
+// pointer value and the NUL-terminated string it points to are
+// printed.
+//
+// We also provide some convenient wrappers:
+//
+//   // Prints a value to a string.  For a (const or not) char
+//   // pointer, the NUL-terminated string (but not the pointer) is
+//   // printed.
+//   std::string ::testing::PrintToString(const T& value);
+//
+//   // Prints a value tersely: for a reference type, the referenced
+//   // value (but not the address) is printed; for a (const or not) char
+//   // pointer, the NUL-terminated string (but not the pointer) is
+//   // printed.
+//   void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
+//
+//   // Prints value using the type inferred by the compiler.  The difference
+//   // from UniversalTersePrint() is that this function prints both the
+//   // pointer and the NUL-terminated string for a (const or not) char pointer.
+//   void ::testing::internal::UniversalPrint(const T& value, ostream*);
+//
+//   // Prints the fields of a tuple tersely to a string vector, one
+//   // element for each field. Tuple support must be enabled in
+//   // gtest-port.h.
+//   std::vector<string> UniversalTersePrintTupleFieldsToStrings(
+//       const Tuple& value);
+//
+// Known limitation:
+//
+// The print primitives print the elements of an STL-style container
+// using the compiler-inferred type of *iter where iter is a
+// const_iterator of the container.  When const_iterator is an input
+// iterator but not a forward iterator, this inferred type may not
+// match value_type, and the print output may be incorrect.  In
+// practice, this is rarely a problem as for most containers
+// const_iterator is a forward iterator.  We'll fix this if there's an
+// actual need for it.  Note that this fix cannot rely on value_type
+// being defined as many user-defined container types don't have
+// value_type.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-internal.h"
+
+namespace testing {
+
+// Definitions in the 'internal' and 'internal2' name spaces are
+// subject to change without notice.  DO NOT USE THEM IN USER CODE!
+namespace internal2 {
+
+// Prints the given number of bytes in the given object to the given
+// ostream.
+GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
+                                     size_t count,
+                                     ::std::ostream* os);
+
+// For selecting which printer to use when a given type has neither <<
+// nor PrintTo().
+enum TypeKind {
+  kProtobuf,              // a protobuf type
+  kConvertibleToInteger,  // a type implicitly convertible to BiggestInt
+                          // (e.g. a named or unnamed enum type)
+  kOtherType              // anything else
+};
+
+// TypeWithoutFormatter<T, kTypeKind>::PrintValue(value, os) is called
+// by the universal printer to print a value of type T when neither
+// operator<< nor PrintTo() is defined for T, where kTypeKind is the
+// "kind" of T as defined by enum TypeKind.
+template <typename T, TypeKind kTypeKind>
+class TypeWithoutFormatter {
+ public:
+  // This default version is called when kTypeKind is kOtherType.
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    PrintBytesInObjectTo(reinterpret_cast<const unsigned char*>(&value),
+                         sizeof(value), os);
+  }
+};
+
+// We print a protobuf using its ShortDebugString() when the string
+// doesn't exceed this many characters; otherwise we print it using
+// DebugString() for better readability.
+const size_t kProtobufOneLinerMaxLength = 50;
+
+template <typename T>
+class TypeWithoutFormatter<T, kProtobuf> {
+ public:
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    const ::testing::internal::string short_str = value.ShortDebugString();
+    const ::testing::internal::string pretty_str =
+        short_str.length() <= kProtobufOneLinerMaxLength ?
+        short_str : ("\n" + value.DebugString());
+    *os << ("<" + pretty_str + ">");
+  }
+};
+
+template <typename T>
+class TypeWithoutFormatter<T, kConvertibleToInteger> {
+ public:
+  // Since T has no << operator or PrintTo() but can be implicitly
+  // converted to BiggestInt, we print it as a BiggestInt.
+  //
+  // Most likely T is an enum type (either named or unnamed), in which
+  // case printing it as an integer is the desired behavior.  In case
+  // T is not an enum, printing it as an integer is the best we can do
+  // given that it has no user-defined printer.
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    const internal::BiggestInt kBigInt = value;
+    *os << kBigInt;
+  }
+};
+
+// Prints the given value to the given ostream.  If the value is a
+// protocol message, its debug string is printed; if it's an enum or
+// of a type implicitly convertible to BiggestInt, it's printed as an
+// integer; otherwise the bytes in the value are printed.  This is
+// what UniversalPrinter<T>::Print() does when it knows nothing about
+// type T and T has neither << operator nor PrintTo().
+//
+// A user can override this behavior for a class type Foo by defining
+// a << operator in the namespace where Foo is defined.
+//
+// We put this operator in namespace 'internal2' instead of 'internal'
+// to simplify the implementation, as much code in 'internal' needs to
+// use << in STL, which would conflict with our own << were it defined
+// in 'internal'.
+//
+// Note that this operator<< takes a generic std::basic_ostream<Char,
+// CharTraits> type instead of the more restricted std::ostream.  If
+// we define it to take an std::ostream instead, we'll get an
+// "ambiguous overloads" compiler error when trying to print a type
+// Foo that supports streaming to std::basic_ostream<Char,
+// CharTraits>, as the compiler cannot tell whether
+// operator<<(std::ostream&, const T&) or
+// operator<<(std::basic_stream<Char, CharTraits>, const Foo&) is more
+// specific.
+template <typename Char, typename CharTraits, typename T>
+::std::basic_ostream<Char, CharTraits>& operator<<(
+    ::std::basic_ostream<Char, CharTraits>& os, const T& x) {
+  TypeWithoutFormatter<T,
+      (internal::IsAProtocolMessage<T>::value ? kProtobuf :
+       internal::ImplicitlyConvertible<const T&, internal::BiggestInt>::value ?
+       kConvertibleToInteger : kOtherType)>::PrintValue(x, &os);
+  return os;
+}
+
+}  // namespace internal2
+}  // namespace testing
+
+// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up
+// magic needed for implementing UniversalPrinter won't work.
+namespace testing_internal {
+
+// Used to print a value that is not an STL-style container when the
+// user doesn't define PrintTo() for it.
+template <typename T>
+void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) {
+  // With the following statement, during unqualified name lookup,
+  // testing::internal2::operator<< appears as if it was declared in
+  // the nearest enclosing namespace that contains both
+  // ::testing_internal and ::testing::internal2, i.e. the global
+  // namespace.  For more details, refer to the C++ Standard section
+  // 7.3.4-1 [namespace.udir].  This allows us to fall back onto
+  // testing::internal2::operator<< in case T doesn't come with a <<
+  // operator.
+  //
+  // We cannot write 'using ::testing::internal2::operator<<;', which
+  // gcc 3.3 fails to compile due to a compiler bug.
+  using namespace ::testing::internal2;  // NOLINT
+
+  // Assuming T is defined in namespace foo, in the next statement,
+  // the compiler will consider all of:
+  //
+  //   1. foo::operator<< (thanks to Koenig look-up),
+  //   2. ::operator<< (as the current namespace is enclosed in ::),
+  //   3. testing::internal2::operator<< (thanks to the using statement above).
+  //
+  // The operator<< whose type matches T best will be picked.
+  //
+  // We deliberately allow #2 to be a candidate, as sometimes it's
+  // impossible to define #1 (e.g. when foo is ::std, defining
+  // anything in it is undefined behavior unless you are a compiler
+  // vendor.).
+  *os << value;
+}
+
+}  // namespace testing_internal
+
+namespace testing {
+namespace internal {
+
+// UniversalPrinter<T>::Print(value, ostream_ptr) prints the given
+// value to the given ostream.  The caller must ensure that
+// 'ostream_ptr' is not NULL, or the behavior is undefined.
+//
+// We define UniversalPrinter as a class template (as opposed to a
+// function template), as we need to partially specialize it for
+// reference types, which cannot be done with function templates.
+template <typename T>
+class UniversalPrinter;
+
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os);
+
+// Used to print an STL-style container when the user doesn't define
+// a PrintTo() for it.
+template <typename C>
+void DefaultPrintTo(IsContainer /* dummy */,
+                    false_type /* is not a pointer */,
+                    const C& container, ::std::ostream* os) {
+  const size_t kMaxCount = 32;  // The maximum number of elements to print.
+  *os << '{';
+  size_t count = 0;
+  for (typename C::const_iterator it = container.begin();
+       it != container.end(); ++it, ++count) {
+    if (count > 0) {
+      *os << ',';
+      if (count == kMaxCount) {  // Enough has been printed.
+        *os << " ...";
+        break;
+      }
+    }
+    *os << ' ';
+    // We cannot call PrintTo(*it, os) here as PrintTo() doesn't
+    // handle *it being a native array.
+    internal::UniversalPrint(*it, os);
+  }
+
+  if (count > 0) {
+    *os << ' ';
+  }
+  *os << '}';
+}
+
+// Used to print a pointer that is neither a char pointer nor a member
+// pointer, when the user doesn't define PrintTo() for it.  (A member
+// variable pointer or member function pointer doesn't really point to
+// a location in the address space.  Their representation is
+// implementation-defined.  Therefore they will be printed as raw
+// bytes.)
+template <typename T>
+void DefaultPrintTo(IsNotContainer /* dummy */,
+                    true_type /* is a pointer */,
+                    T* p, ::std::ostream* os) {
+  if (p == NULL) {
+    *os << "NULL";
+  } else {
+    // C++ doesn't allow casting from a function pointer to any object
+    // pointer.
+    //
+    // IsTrue() silences warnings: "Condition is always true",
+    // "unreachable code".
+    if (IsTrue(ImplicitlyConvertible<T*, const void*>::value)) {
+      // T is not a function type.  We just call << to print p,
+      // relying on ADL to pick up user-defined << for their pointer
+      // types, if any.
+      *os << p;
+    } else {
+      // T is a function type, so '*os << p' doesn't do what we want
+      // (it just prints p as bool).  We want to print p as a const
+      // void*.  However, we cannot cast it to const void* directly,
+      // even using reinterpret_cast, as earlier versions of gcc
+      // (e.g. 3.4.5) cannot compile the cast when p is a function
+      // pointer.  Casting to UInt64 first solves the problem.
+      *os << reinterpret_cast<const void*>(
+          reinterpret_cast<internal::UInt64>(p));
+    }
+  }
+}
+
+// Used to print a non-container, non-pointer value when the user
+// doesn't define PrintTo() for it.
+template <typename T>
+void DefaultPrintTo(IsNotContainer /* dummy */,
+                    false_type /* is not a pointer */,
+                    const T& value, ::std::ostream* os) {
+  ::testing_internal::DefaultPrintNonContainerTo(value, os);
+}
+
+// Prints the given value using the << operator if it has one;
+// otherwise prints the bytes in it.  This is what
+// UniversalPrinter<T>::Print() does when PrintTo() is not specialized
+// or overloaded for type T.
+//
+// A user can override this behavior for a class type Foo by defining
+// an overload of PrintTo() in the namespace where Foo is defined.  We
+// give the user this option as sometimes defining a << operator for
+// Foo is not desirable (e.g. the coding style may prevent doing it,
+// or there is already a << operator but it doesn't do what the user
+// wants).
+template <typename T>
+void PrintTo(const T& value, ::std::ostream* os) {
+  // DefaultPrintTo() is overloaded.  The type of its first two
+  // arguments determine which version will be picked.  If T is an
+  // STL-style container, the version for container will be called; if
+  // T is a pointer, the pointer version will be called; otherwise the
+  // generic version will be called.
+  //
+  // Note that we check for container types here, prior to we check
+  // for protocol message types in our operator<<.  The rationale is:
+  //
+  // For protocol messages, we want to give people a chance to
+  // override Google Mock's format by defining a PrintTo() or
+  // operator<<.  For STL containers, other formats can be
+  // incompatible with Google Mock's format for the container
+  // elements; therefore we check for container types here to ensure
+  // that our format is used.
+  //
+  // The second argument of DefaultPrintTo() is needed to bypass a bug
+  // in Symbian's C++ compiler that prevents it from picking the right
+  // overload between:
+  //
+  //   PrintTo(const T& x, ...);
+  //   PrintTo(T* x, ...);
+  DefaultPrintTo(IsContainerTest<T>(0), is_pointer<T>(), value, os);
+}
+
+// The following list of PrintTo() overloads tells
+// UniversalPrinter<T>::Print() how to print standard types (built-in
+// types, strings, plain arrays, and pointers).
+
+// Overloads for various char types.
+GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os);
+GTEST_API_ void PrintTo(signed char c, ::std::ostream* os);
+inline void PrintTo(char c, ::std::ostream* os) {
+  // When printing a plain char, we always treat it as unsigned.  This
+  // way, the output won't be affected by whether the compiler thinks
+  // char is signed or not.
+  PrintTo(static_cast<unsigned char>(c), os);
+}
+
+// Overloads for other simple built-in types.
+inline void PrintTo(bool x, ::std::ostream* os) {
+  *os << (x ? "true" : "false");
+}
+
+// Overload for wchar_t type.
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its decimal code (except for L'\0').
+// The L'\0' char is printed as "L'\\0'". The decimal code is printed
+// as signed integer when wchar_t is implemented by the compiler
+// as a signed type and is printed as an unsigned integer when wchar_t
+// is implemented as an unsigned type.
+GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os);
+
+// Overloads for C strings.
+GTEST_API_ void PrintTo(const char* s, ::std::ostream* os);
+inline void PrintTo(char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const char*>(s), os);
+}
+
+// signed/unsigned char is often used for representing binary data, so
+// we print pointers to it as void* to be safe.
+inline void PrintTo(const signed char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(signed char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(const unsigned char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(unsigned char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+
+// MSVC can be configured to define wchar_t as a typedef of unsigned
+// short.  It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native
+// type.  When wchar_t is a typedef, defining an overload for const
+// wchar_t* would cause unsigned short* be printed as a wide string,
+// possibly causing invalid memory accesses.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Overloads for wide C strings
+GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os);
+inline void PrintTo(wchar_t* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const wchar_t*>(s), os);
+}
+#endif
+
+// Overload for C arrays.  Multi-dimensional arrays are printed
+// properly.
+
+// Prints the given number of elements in an array, without printing
+// the curly braces.
+template <typename T>
+void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
+  UniversalPrint(a[0], os);
+  for (size_t i = 1; i != count; i++) {
+    *os << ", ";
+    UniversalPrint(a[i], os);
+  }
+}
+
+// Overloads for ::string and ::std::string.
+#if GTEST_HAS_GLOBAL_STRING
+GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os);
+inline void PrintTo(const ::string& s, ::std::ostream* os) {
+  PrintStringTo(s, os);
+}
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os);
+inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
+  PrintStringTo(s, os);
+}
+
+// Overloads for ::wstring and ::std::wstring.
+#if GTEST_HAS_GLOBAL_WSTRING
+GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os);
+inline void PrintTo(const ::wstring& s, ::std::ostream* os) {
+  PrintWideStringTo(s, os);
+}
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
+inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
+  PrintWideStringTo(s, os);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_TR1_TUPLE
+// Overload for ::std::tr1::tuple.  Needed for printing function arguments,
+// which are packed as tuples.
+
+// Helper function for printing a tuple.  T must be instantiated with
+// a tuple type.
+template <typename T>
+void PrintTupleTo(const T& t, ::std::ostream* os);
+
+// Overloaded PrintTo() for tuples of various arities.  We support
+// tuples of up-to 10 fields.  The following implementation works
+// regardless of whether tr1::tuple is implemented using the
+// non-standard variadic template feature or not.
+
+inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1>
+void PrintTo(const ::std::tr1::tuple<T1>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2>
+void PrintTo(const ::std::tr1::tuple<T1, T2>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7, typename T8>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7, typename T8, typename T9>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7, typename T8, typename T9, typename T10>
+void PrintTo(
+    const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& t,
+    ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+#endif  // GTEST_HAS_TR1_TUPLE
+
+// Overload for std::pair.
+template <typename T1, typename T2>
+void PrintTo(const ::std::pair<T1, T2>& value, ::std::ostream* os) {
+  *os << '(';
+  // We cannot use UniversalPrint(value.first, os) here, as T1 may be
+  // a reference type.  The same for printing value.second.
+  UniversalPrinter<T1>::Print(value.first, os);
+  *os << ", ";
+  UniversalPrinter<T2>::Print(value.second, os);
+  *os << ')';
+}
+
+// Implements printing a non-reference type T by letting the compiler
+// pick the right overload of PrintTo() for T.
+template <typename T>
+class UniversalPrinter {
+ public:
+  // MSVC warns about adding const to a function type, so we want to
+  // disable the warning.
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4180)  // Temporarily disables warning 4180.
+#endif  // _MSC_VER
+
+  // Note: we deliberately don't call this PrintTo(), as that name
+  // conflicts with ::testing::internal::PrintTo in the body of the
+  // function.
+  static void Print(const T& value, ::std::ostream* os) {
+    // By default, ::testing::internal::PrintTo() is used for printing
+    // the value.
+    //
+    // Thanks to Koenig look-up, if T is a class and has its own
+    // PrintTo() function defined in its namespace, that function will
+    // be visible here.  Since it is more specific than the generic ones
+    // in ::testing::internal, it will be picked by the compiler in the
+    // following statement - exactly what we want.
+    PrintTo(value, os);
+  }
+
+#ifdef _MSC_VER
+# pragma warning(pop)           // Restores the warning state.
+#endif  // _MSC_VER
+};
+
+// UniversalPrintArray(begin, len, os) prints an array of 'len'
+// elements, starting at address 'begin'.
+template <typename T>
+void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
+  if (len == 0) {
+    *os << "{}";
+  } else {
+    *os << "{ ";
+    const size_t kThreshold = 18;
+    const size_t kChunkSize = 8;
+    // If the array has more than kThreshold elements, we'll have to
+    // omit some details by printing only the first and the last
+    // kChunkSize elements.
+    // TODO(wan@google.com): let the user control the threshold using a flag.
+    if (len <= kThreshold) {
+      PrintRawArrayTo(begin, len, os);
+    } else {
+      PrintRawArrayTo(begin, kChunkSize, os);
+      *os << ", ..., ";
+      PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os);
+    }
+    *os << " }";
+  }
+}
+// This overload prints a (const) char array compactly.
+GTEST_API_ void UniversalPrintArray(const char* begin,
+                                    size_t len,
+                                    ::std::ostream* os);
+
+// Implements printing an array type T[N].
+template <typename T, size_t N>
+class UniversalPrinter<T[N]> {
+ public:
+  // Prints the given array, omitting some elements when there are too
+  // many.
+  static void Print(const T (&a)[N], ::std::ostream* os) {
+    UniversalPrintArray(a, N, os);
+  }
+};
+
+// Implements printing a reference type T&.
+template <typename T>
+class UniversalPrinter<T&> {
+ public:
+  // MSVC warns about adding const to a function type, so we want to
+  // disable the warning.
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4180)  // Temporarily disables warning 4180.
+#endif  // _MSC_VER
+
+  static void Print(const T& value, ::std::ostream* os) {
+    // Prints the address of the value.  We use reinterpret_cast here
+    // as static_cast doesn't compile when T is a function type.
+    *os << "@" << reinterpret_cast<const void*>(&value) << " ";
+
+    // Then prints the value itself.
+    UniversalPrint(value, os);
+  }
+
+#ifdef _MSC_VER
+# pragma warning(pop)           // Restores the warning state.
+#endif  // _MSC_VER
+};
+
+// Prints a value tersely: for a reference type, the referenced value
+// (but not the address) is printed; for a (const) char pointer, the
+// NUL-terminated string (but not the pointer) is printed.
+template <typename T>
+void UniversalTersePrint(const T& value, ::std::ostream* os) {
+  UniversalPrint(value, os);
+}
+inline void UniversalTersePrint(const char* str, ::std::ostream* os) {
+  if (str == NULL) {
+    *os << "NULL";
+  } else {
+    UniversalPrint(string(str), os);
+  }
+}
+inline void UniversalTersePrint(char* str, ::std::ostream* os) {
+  UniversalTersePrint(static_cast<const char*>(str), os);
+}
+
+// Prints a value using the type inferred by the compiler.  The
+// difference between this and UniversalTersePrint() is that for a
+// (const) char pointer, this prints both the pointer and the
+// NUL-terminated string.
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os) {
+  UniversalPrinter<T>::Print(value, os);
+}
+
+#if GTEST_HAS_TR1_TUPLE
+typedef ::std::vector<string> Strings;
+
+// This helper template allows PrintTo() for tuples and
+// UniversalTersePrintTupleFieldsToStrings() to be defined by
+// induction on the number of tuple fields.  The idea is that
+// TuplePrefixPrinter<N>::PrintPrefixTo(t, os) prints the first N
+// fields in tuple t, and can be defined in terms of
+// TuplePrefixPrinter<N - 1>.
+
+// The inductive case.
+template <size_t N>
+struct TuplePrefixPrinter {
+  // Prints the first N fields of a tuple.
+  template <typename Tuple>
+  static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
+    TuplePrefixPrinter<N - 1>::PrintPrefixTo(t, os);
+    *os << ", ";
+    UniversalPrinter<typename ::std::tr1::tuple_element<N - 1, Tuple>::type>
+        ::Print(::std::tr1::get<N - 1>(t), os);
+  }
+
+  // Tersely prints the first N fields of a tuple to a string vector,
+  // one element for each field.
+  template <typename Tuple>
+  static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
+    TuplePrefixPrinter<N - 1>::TersePrintPrefixToStrings(t, strings);
+    ::std::stringstream ss;
+    UniversalTersePrint(::std::tr1::get<N - 1>(t), &ss);
+    strings->push_back(ss.str());
+  }
+};
+
+// Base cases.
+template <>
+struct TuplePrefixPrinter<0> {
+  template <typename Tuple>
+  static void PrintPrefixTo(const Tuple&, ::std::ostream*) {}
+
+  template <typename Tuple>
+  static void TersePrintPrefixToStrings(const Tuple&, Strings*) {}
+};
+// We have to specialize the entire TuplePrefixPrinter<> class
+// template here, even though the definition of
+// TersePrintPrefixToStrings() is the same as the generic version, as
+// Embarcadero (formerly CodeGear, formerly Borland) C++ doesn't
+// support specializing a method template of a class template.
+template <>
+struct TuplePrefixPrinter<1> {
+  template <typename Tuple>
+  static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
+    UniversalPrinter<typename ::std::tr1::tuple_element<0, Tuple>::type>::
+        Print(::std::tr1::get<0>(t), os);
+  }
+
+  template <typename Tuple>
+  static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
+    ::std::stringstream ss;
+    UniversalTersePrint(::std::tr1::get<0>(t), &ss);
+    strings->push_back(ss.str());
+  }
+};
+
+// Helper function for printing a tuple.  T must be instantiated with
+// a tuple type.
+template <typename T>
+void PrintTupleTo(const T& t, ::std::ostream* os) {
+  *os << "(";
+  TuplePrefixPrinter< ::std::tr1::tuple_size<T>::value>::
+      PrintPrefixTo(t, os);
+  *os << ")";
+}
+
+// Prints the fields of a tuple tersely to a string vector, one
+// element for each field.  See the comment before
+// UniversalTersePrint() for how we define "tersely".
+template <typename Tuple>
+Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
+  Strings result;
+  TuplePrefixPrinter< ::std::tr1::tuple_size<Tuple>::value>::
+      TersePrintPrefixToStrings(value, &result);
+  return result;
+}
+#endif  // GTEST_HAS_TR1_TUPLE
+
+}  // namespace internal
+
+template <typename T>
+::std::string PrintToString(const T& value) {
+  ::std::stringstream ss;
+  internal::UniversalTersePrint(value, &ss);
+  return ss.str();
+}
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
diff --git a/third_party/googletest/src/include/gtest/gtest-spi.h b/third_party/googletest/src/include/gtest/gtest-spi.h
new file mode 100644 (file)
index 0000000..b226e55
--- /dev/null
@@ -0,0 +1,232 @@
+// Copyright 2007, 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: wan@google.com (Zhanyong Wan)
+//
+// Utilities for testing Google Test itself and code that uses Google Test
+// (e.g. frameworks built on top of Google Test).
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
+#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
+
+#include "gtest/gtest.h"
+
+namespace testing {
+
+// This helper class can be used to mock out Google Test failure reporting
+// so that we can test Google Test or code that builds on Google Test.
+//
+// An object of this class appends a TestPartResult object to the
+// TestPartResultArray object given in the constructor whenever a Google Test
+// failure is reported. It can either intercept only failures that are
+// generated in the same thread that created this object or it can intercept
+// all generated failures. The scope of this mock object can be controlled with
+// the second argument to the two arguments constructor.
+class GTEST_API_ ScopedFakeTestPartResultReporter
+    : public TestPartResultReporterInterface {
+ public:
+  // The two possible mocking modes of this object.
+  enum InterceptMode {
+    INTERCEPT_ONLY_CURRENT_THREAD,  // Intercepts only thread local failures.
+    INTERCEPT_ALL_THREADS           // Intercepts all failures.
+  };
+
+  // The c'tor sets this object as the test part result reporter used
+  // by Google Test.  The 'result' parameter specifies where to report the
+  // results. This reporter will only catch failures generated in the current
+  // thread. DEPRECATED
+  explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result);
+
+  // Same as above, but you can choose the interception scope of this object.
+  ScopedFakeTestPartResultReporter(InterceptMode intercept_mode,
+                                   TestPartResultArray* result);
+
+  // The d'tor restores the previous test part result reporter.
+  virtual ~ScopedFakeTestPartResultReporter();
+
+  // Appends the TestPartResult object to the TestPartResultArray
+  // received in the constructor.
+  //
+  // This method is from the TestPartResultReporterInterface
+  // interface.
+  virtual void ReportTestPartResult(const TestPartResult& result);
+ private:
+  void Init();
+
+  const InterceptMode intercept_mode_;
+  TestPartResultReporterInterface* old_reporter_;
+  TestPartResultArray* const result_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter);
+};
+
+namespace internal {
+
+// A helper class for implementing EXPECT_FATAL_FAILURE() and
+// EXPECT_NONFATAL_FAILURE().  Its destructor verifies that the given
+// TestPartResultArray contains exactly one failure that has the given
+// type and contains the given substring.  If that's not the case, a
+// non-fatal failure will be generated.
+class GTEST_API_ SingleFailureChecker {
+ public:
+  // The constructor remembers the arguments.
+  SingleFailureChecker(const TestPartResultArray* results,
+                       TestPartResult::Type type,
+                       const string& substr);
+  ~SingleFailureChecker();
+ private:
+  const TestPartResultArray* const results_;
+  const TestPartResult::Type type_;
+  const string substr_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
+};
+
+}  // namespace internal
+
+}  // namespace testing
+
+// A set of macros for testing Google Test assertions or code that's expected
+// to generate Google Test fatal failures.  It verifies that the given
+// statement will cause exactly one fatal Google Test failure with 'substr'
+// being part of the failure message.
+//
+// There are two different versions of this macro. EXPECT_FATAL_FAILURE only
+// affects and considers failures generated in the current thread and
+// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
+//
+// The verification of the assertion is done correctly even when the statement
+// throws an exception or aborts the current function.
+//
+// Known restrictions:
+//   - 'statement' cannot reference local non-static variables or
+//     non-static members of the current object.
+//   - 'statement' cannot return a value.
+//   - You cannot stream a failure message to this macro.
+//
+// Note that even though the implementations of the following two
+// macros are much alike, we cannot refactor them to use a common
+// helper macro, due to some peculiarity in how the preprocessor
+// works.  The AcceptsMacroThatExpandsToUnprotectedComma test in
+// gtest_unittest.cc will fail to compile if we do that.
+#define EXPECT_FATAL_FAILURE(statement, substr) \
+  do { \
+    class GTestExpectFatalFailureHelper {\
+     public:\
+      static void Execute() { statement; }\
+    };\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
+      GTestExpectFatalFailureHelper::Execute();\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
+  do { \
+    class GTestExpectFatalFailureHelper {\
+     public:\
+      static void Execute() { statement; }\
+    };\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ALL_THREADS, &gtest_failures);\
+      GTestExpectFatalFailureHelper::Execute();\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+// A macro for testing Google Test assertions or code that's expected to
+// generate Google Test non-fatal failures.  It asserts that the given
+// statement will cause exactly one non-fatal Google Test failure with 'substr'
+// being part of the failure message.
+//
+// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only
+// affects and considers failures generated in the current thread and
+// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
+//
+// 'statement' is allowed to reference local variables and members of
+// the current object.
+//
+// The verification of the assertion is done correctly even when the statement
+// throws an exception or aborts the current function.
+//
+// Known restrictions:
+//   - You cannot stream a failure message to this macro.
+//
+// Note that even though the implementations of the following two
+// macros are much alike, we cannot refactor them to use a common
+// helper macro, due to some peculiarity in how the preprocessor
+// works.  If we do that, the code won't compile when the user gives
+// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that
+// expands to code containing an unprotected comma.  The
+// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc
+// catches that.
+//
+// For the same reason, we have to write
+//   if (::testing::internal::AlwaysTrue()) { statement; }
+// instead of
+//   GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+// to avoid an MSVC warning on unreachable code.
+#define EXPECT_NONFATAL_FAILURE(statement, substr) \
+  do {\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
+        (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
+      if (::testing::internal::AlwaysTrue()) { statement; }\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
+  do {\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
+        (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS,\
+          &gtest_failures);\
+      if (::testing::internal::AlwaysTrue()) { statement; }\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_SPI_H_
diff --git a/third_party/googletest/src/include/gtest/gtest-test-part.h b/third_party/googletest/src/include/gtest/gtest-test-part.h
new file mode 100644 (file)
index 0000000..8aeea14
--- /dev/null
@@ -0,0 +1,176 @@
+// Copyright 2008, 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: mheule@google.com (Markus Heule)
+//
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+
+#include <iosfwd>
+#include <vector>
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+
+namespace testing {
+
+// A copyable object representing the result of a test part (i.e. an
+// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()).
+//
+// Don't inherit from TestPartResult as its destructor is not virtual.
+class GTEST_API_ TestPartResult {
+ public:
+  // The possible outcomes of a test part (i.e. an assertion or an
+  // explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
+  enum Type {
+    kSuccess,          // Succeeded.
+    kNonFatalFailure,  // Failed but the test can continue.
+    kFatalFailure      // Failed and the test should be terminated.
+  };
+
+  // C'tor.  TestPartResult does NOT have a default constructor.
+  // Always use this constructor (with parameters) to create a
+  // TestPartResult object.
+  TestPartResult(Type a_type,
+                 const char* a_file_name,
+                 int a_line_number,
+                 const char* a_message)
+      : type_(a_type),
+        file_name_(a_file_name),
+        line_number_(a_line_number),
+        summary_(ExtractSummary(a_message)),
+        message_(a_message) {
+  }
+
+  // Gets the outcome of the test part.
+  Type type() const { return type_; }
+
+  // Gets the name of the source file where the test part took place, or
+  // NULL if it's unknown.
+  const char* file_name() const { return file_name_.c_str(); }
+
+  // Gets the line in the source file where the test part took place,
+  // or -1 if it's unknown.
+  int line_number() const { return line_number_; }
+
+  // Gets the summary of the failure message.
+  const char* summary() const { return summary_.c_str(); }
+
+  // Gets the message associated with the test part.
+  const char* message() const { return message_.c_str(); }
+
+  // Returns true iff the test part passed.
+  bool passed() const { return type_ == kSuccess; }
+
+  // Returns true iff the test part failed.
+  bool failed() const { return type_ != kSuccess; }
+
+  // Returns true iff the test part non-fatally failed.
+  bool nonfatally_failed() const { return type_ == kNonFatalFailure; }
+
+  // Returns true iff the test part fatally failed.
+  bool fatally_failed() const { return type_ == kFatalFailure; }
+ private:
+  Type type_;
+
+  // Gets the summary of the failure message by omitting the stack
+  // trace in it.
+  static internal::String ExtractSummary(const char* message);
+
+  // The name of the source file where the test part took place, or
+  // NULL if the source file is unknown.
+  internal::String file_name_;
+  // The line in the source file where the test part took place, or -1
+  // if the line number is unknown.
+  int line_number_;
+  internal::String summary_;  // The test failure summary.
+  internal::String message_;  // The test failure message.
+};
+
+// Prints a TestPartResult object.
+std::ostream& operator<<(std::ostream& os, const TestPartResult& result);
+
+// An array of TestPartResult objects.
+//
+// Don't inherit from TestPartResultArray as its destructor is not
+// virtual.
+class GTEST_API_ TestPartResultArray {
+ public:
+  TestPartResultArray() {}
+
+  // Appends the given TestPartResult to the array.
+  void Append(const TestPartResult& result);
+
+  // Returns the TestPartResult at the given index (0-based).
+  const TestPartResult& GetTestPartResult(int index) const;
+
+  // Returns the number of TestPartResult objects in the array.
+  int size() const;
+
+ private:
+  std::vector<TestPartResult> array_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray);
+};
+
+// This interface knows how to report a test part result.
+class TestPartResultReporterInterface {
+ public:
+  virtual ~TestPartResultReporterInterface() {}
+
+  virtual void ReportTestPartResult(const TestPartResult& result) = 0;
+};
+
+namespace internal {
+
+// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a
+// statement generates new fatal failures. To do so it registers itself as the
+// current test part result reporter. Besides checking if fatal failures were
+// reported, it only delegates the reporting to the former result reporter.
+// The original result reporter is restored in the destructor.
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+class GTEST_API_ HasNewFatalFailureHelper
+    : public TestPartResultReporterInterface {
+ public:
+  HasNewFatalFailureHelper();
+  virtual ~HasNewFatalFailureHelper();
+  virtual void ReportTestPartResult(const TestPartResult& result);
+  bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
+ private:
+  bool has_new_fatal_failure_;
+  TestPartResultReporterInterface* original_reporter_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper);
+};
+
+}  // namespace internal
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
diff --git a/third_party/googletest/src/include/gtest/gtest-typed-test.h b/third_party/googletest/src/include/gtest/gtest-typed-test.h
new file mode 100644 (file)
index 0000000..fe1e83b
--- /dev/null
@@ -0,0 +1,259 @@
+// Copyright 2008 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: wan@google.com (Zhanyong Wan)
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+
+// This header implements typed tests and type-parameterized tests.
+
+// Typed (aka type-driven) tests repeat the same test for types in a
+// list.  You must know which types you want to test with when writing
+// typed tests. Here's how you do it:
+
+#if 0
+
+// First, define a fixture class template.  It should be parameterized
+// by a type.  Remember to derive it from testing::Test.
+template <typename T>
+class FooTest : public testing::Test {
+ public:
+  ...
+  typedef std::list<T> List;
+  static T shared_;
+  T value_;
+};
+
+// Next, associate a list of types with the test case, which will be
+// repeated for each type in the list.  The typedef is necessary for
+// the macro to parse correctly.
+typedef testing::Types<char, int, unsigned int> MyTypes;
+TYPED_TEST_CASE(FooTest, MyTypes);
+
+// If the type list contains only one type, you can write that type
+// directly without Types<...>:
+//   TYPED_TEST_CASE(FooTest, int);
+
+// Then, use TYPED_TEST() instead of TEST_F() to define as many typed
+// tests for this test case as you want.
+TYPED_TEST(FooTest, DoesBlah) {
+  // Inside a test, refer to TypeParam to get the type parameter.
+  // Since we are inside a derived class template, C++ requires use to
+  // visit the members of FooTest via 'this'.
+  TypeParam n = this->value_;
+
+  // To visit static members of the fixture, add the TestFixture::
+  // prefix.
+  n += TestFixture::shared_;
+
+  // To refer to typedefs in the fixture, add the "typename
+  // TestFixture::" prefix.
+  typename TestFixture::List values;
+  values.push_back(n);
+  ...
+}
+
+TYPED_TEST(FooTest, HasPropertyA) { ... }
+
+#endif  // 0
+
+// Type-parameterized tests are abstract test patterns parameterized
+// by a type.  Compared with typed tests, type-parameterized tests
+// allow you to define the test pattern without knowing what the type
+// parameters are.  The defined pattern can be instantiated with
+// different types any number of times, in any number of translation
+// units.
+//
+// If you are designing an interface or concept, you can define a
+// suite of type-parameterized tests to verify properties that any
+// valid implementation of the interface/concept should have.  Then,
+// each implementation can easily instantiate the test suite to verify
+// that it conforms to the requirements, without having to write
+// similar tests repeatedly.  Here's an example:
+
+#if 0
+
+// First, define a fixture class template.  It should be parameterized
+// by a type.  Remember to derive it from testing::Test.
+template <typename T>
+class FooTest : public testing::Test {
+  ...
+};
+
+// Next, declare that you will define a type-parameterized test case
+// (the _P suffix is for "parameterized" or "pattern", whichever you
+// prefer):
+TYPED_TEST_CASE_P(FooTest);
+
+// Then, use TYPED_TEST_P() to define as many type-parameterized tests
+// for this type-parameterized test case as you want.
+TYPED_TEST_P(FooTest, DoesBlah) {
+  // Inside a test, refer to TypeParam to get the type parameter.
+  TypeParam n = 0;
+  ...
+}
+
+TYPED_TEST_P(FooTest, HasPropertyA) { ... }
+
+// Now the tricky part: you need to register all test patterns before
+// you can instantiate them.  The first argument of the macro is the
+// test case name; the rest are the names of the tests in this test
+// case.
+REGISTER_TYPED_TEST_CASE_P(FooTest,
+                           DoesBlah, HasPropertyA);
+
+// Finally, you are free to instantiate the pattern with the types you
+// want.  If you put the above code in a header file, you can #include
+// it in multiple C++ source files and instantiate it multiple times.
+//
+// To distinguish different instances of the pattern, the first
+// argument to the INSTANTIATE_* macro is a prefix that will be added
+// to the actual test case name.  Remember to pick unique prefixes for
+// different instances.
+typedef testing::Types<char, int, unsigned int> MyTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
+
+// If the type list contains only one type, you can write that type
+// directly without Types<...>:
+//   INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int);
+
+#endif  // 0
+
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-type-util.h"
+
+// Implements typed tests.
+
+#if GTEST_HAS_TYPED_TEST
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the name of the typedef for the type parameters of the
+// given test case.
+# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
+
+// The 'Types' template argument below must have spaces around it
+// since some compilers may choke on '>>' when passing a template
+// instance (e.g. Types<int>)
+# define TYPED_TEST_CASE(CaseName, Types) \
+  typedef ::testing::internal::TypeList< Types >::type \
+      GTEST_TYPE_PARAMS_(CaseName)
+
+# define TYPED_TEST(CaseName, TestName) \
+  template <typename gtest_TypeParam_> \
+  class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
+      : public CaseName<gtest_TypeParam_> { \
+   private: \
+    typedef CaseName<gtest_TypeParam_> TestFixture; \
+    typedef gtest_TypeParam_ TypeParam; \
+    virtual void TestBody(); \
+  }; \
+  bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \
+      ::testing::internal::TypeParameterizedTest< \
+          CaseName, \
+          ::testing::internal::TemplateSel< \
+              GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \
+          GTEST_TYPE_PARAMS_(CaseName)>::Register(\
+              "", #CaseName, #TestName, 0); \
+  template <typename gtest_TypeParam_> \
+  void GTEST_TEST_CLASS_NAME_(CaseName, TestName)<gtest_TypeParam_>::TestBody()
+
+#endif  // GTEST_HAS_TYPED_TEST
+
+// Implements type-parameterized tests.
+
+#if GTEST_HAS_TYPED_TEST_P
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the namespace name that the type-parameterized tests for
+// the given type-parameterized test case are defined in.  The exact
+// name of the namespace is subject to change without notice.
+# define GTEST_CASE_NAMESPACE_(TestCaseName) \
+  gtest_case_##TestCaseName##_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the name of the variable used to remember the names of
+// the defined tests in the given test case.
+# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \
+  gtest_typed_test_case_p_state_##TestCaseName##_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
+//
+// Expands to the name of the variable used to remember the names of
+// the registered tests in the given test case.
+# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \
+  gtest_registered_test_names_##TestCaseName##_
+
+// The variables defined in the type-parameterized test macros are
+// static as typically these macros are used in a .h file that can be
+// #included in multiple translation units linked together.
+# define TYPED_TEST_CASE_P(CaseName) \
+  static ::testing::internal::TypedTestCasePState \
+      GTEST_TYPED_TEST_CASE_P_STATE_(CaseName)
+
+# define TYPED_TEST_P(CaseName, TestName) \
+  namespace GTEST_CASE_NAMESPACE_(CaseName) { \
+  template <typename gtest_TypeParam_> \
+  class TestName : public CaseName<gtest_TypeParam_> { \
+   private: \
+    typedef CaseName<gtest_TypeParam_> TestFixture; \
+    typedef gtest_TypeParam_ TypeParam; \
+    virtual void TestBody(); \
+  }; \
+  static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
+      GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\
+          __FILE__, __LINE__, #CaseName, #TestName); \
+  } \
+  template <typename gtest_TypeParam_> \
+  void GTEST_CASE_NAMESPACE_(CaseName)::TestName<gtest_TypeParam_>::TestBody()
+
+# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \
+  namespace GTEST_CASE_NAMESPACE_(CaseName) { \
+  typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
+  } \
+  static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \
+      GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\
+          __FILE__, __LINE__, #__VA_ARGS__)
+
+// The 'Types' template argument below must have spaces around it
+// since some compilers may choke on '>>' when passing a template
+// instance (e.g. Types<int>)
+# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \
+  bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \
+      ::testing::internal::TypeParameterizedTestCase<CaseName, \
+          GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \
+          ::testing::internal::TypeList< Types >::type>::Register(\
+              #Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName))
+
+#endif  // GTEST_HAS_TYPED_TEST_P
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
diff --git a/third_party/googletest/src/include/gtest/gtest.h b/third_party/googletest/src/include/gtest/gtest.h
new file mode 100644 (file)
index 0000000..cd01c7b
--- /dev/null
@@ -0,0 +1,2155 @@
+// Copyright 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: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the public API for Google Test.  It should be
+// included by any test program that uses Google Test.
+//
+// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
+// leave some internal implementation details in this header file.
+// They are clearly marked by comments like this:
+//
+//   // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+//
+// Such code is NOT meant to be used by a user directly, and is subject
+// to CHANGE WITHOUT NOTICE.  Therefore DO NOT DEPEND ON IT in a user
+// program!
+//
+// Acknowledgment: Google Test borrowed the idea of automatic test
+// registration from Barthelemy Dagenais' (barthelemy@prologique.com)
+// easyUnit framework.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_H_
+
+#include <limits>
+#include <vector>
+
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+#include "gtest/gtest-death-test.h"
+#include "gtest/gtest-message.h"
+#include "gtest/gtest-param-test.h"
+#include "gtest/gtest-printers.h"
+#include "gtest/gtest_prod.h"
+#include "gtest/gtest-test-part.h"
+#include "gtest/gtest-typed-test.h"
+
+// Depending on the platform, different string classes are available.
+// On Linux, in addition to ::std::string, Google also makes use of
+// class ::string, which has the same interface as ::std::string, but
+// has a different implementation.
+//
+// The user can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that
+// ::string is available AND is a distinct type to ::std::string, or
+// define it to 0 to indicate otherwise.
+//
+// If the user's ::std::string and ::string are the same class due to
+// aliasing, he should define GTEST_HAS_GLOBAL_STRING to 0.
+//
+// If the user doesn't define GTEST_HAS_GLOBAL_STRING, it is defined
+// heuristically.
+
+namespace testing {
+
+// Declares the flags.
+
+// This flag temporary enables the disabled tests.
+GTEST_DECLARE_bool_(also_run_disabled_tests);
+
+// This flag brings the debugger on an assertion failure.
+GTEST_DECLARE_bool_(break_on_failure);
+
+// This flag controls whether Google Test catches all test-thrown exceptions
+// and logs them as failures.
+GTEST_DECLARE_bool_(catch_exceptions);
+
+// This flag enables using colors in terminal output. Available values are
+// "yes" to enable colors, "no" (disable colors), or "auto" (the default)
+// to let Google Test decide.
+GTEST_DECLARE_string_(color);
+
+// This flag sets up the filter to select by name using a glob pattern
+// the tests to run. If the filter is not given all tests are executed.
+GTEST_DECLARE_string_(filter);
+
+// This flag causes the Google Test to list tests. None of the tests listed
+// are actually run if the flag is provided.
+GTEST_DECLARE_bool_(list_tests);
+
+// This flag controls whether Google Test emits a detailed XML report to a file
+// in addition to its normal textual output.
+GTEST_DECLARE_string_(output);
+
+// This flags control whether Google Test prints the elapsed time for each
+// test.
+GTEST_DECLARE_bool_(print_time);
+
+// This flag specifies the random number seed.
+GTEST_DECLARE_int32_(random_seed);
+
+// This flag sets how many times the tests are repeated. The default value
+// is 1. If the value is -1 the tests are repeating forever.
+GTEST_DECLARE_int32_(repeat);
+
+// This flag controls whether Google Test includes Google Test internal
+// stack frames in failure stack traces.
+GTEST_DECLARE_bool_(show_internal_stack_frames);
+
+// When this flag is specified, tests' order is randomized on every iteration.
+GTEST_DECLARE_bool_(shuffle);
+
+// This flag specifies the maximum number of stack frames to be
+// printed in a failure message.
+GTEST_DECLARE_int32_(stack_trace_depth);
+
+// When this flag is specified, a failed assertion will throw an
+// exception if exceptions are enabled, or exit the program with a
+// non-zero code otherwise.
+GTEST_DECLARE_bool_(throw_on_failure);
+
+// When this flag is set with a "host:port" string, on supported
+// platforms test results are streamed to the specified port on
+// the specified host machine.
+GTEST_DECLARE_string_(stream_result_to);
+
+// The upper limit for valid stack trace depths.
+const int kMaxStackTraceDepth = 100;
+
+namespace internal {
+
+class AssertHelper;
+class DefaultGlobalTestPartResultReporter;
+class ExecDeathTest;
+class NoExecDeathTest;
+class FinalSuccessChecker;
+class GTestFlagSaver;
+class TestResultAccessor;
+class TestEventListenersAccessor;
+class TestEventRepeater;
+class WindowsDeathTest;
+class UnitTestImpl* GetUnitTestImpl();
+void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
+                                    const String& message);
+
+// Converts a streamable value to a String.  A NULL pointer is
+// converted to "(null)".  When the input value is a ::string,
+// ::std::string, ::wstring, or ::std::wstring object, each NUL
+// character in it is replaced with "\\0".
+// Declared in gtest-internal.h but defined here, so that it has access
+// to the definition of the Message class, required by the ARM
+// compiler.
+template <typename T>
+String StreamableToString(const T& streamable) {
+  return (Message() << streamable).GetString();
+}
+
+}  // namespace internal
+
+// The friend relationship of some of these classes is cyclic.
+// If we don't forward declare them the compiler might confuse the classes
+// in friendship clauses with same named classes on the scope.
+class Test;
+class TestCase;
+class TestInfo;
+class UnitTest;
+
+// A class for indicating whether an assertion was successful.  When
+// the assertion wasn't successful, the AssertionResult object
+// remembers a non-empty message that describes how it failed.
+//
+// To create an instance of this class, use one of the factory functions
+// (AssertionSuccess() and AssertionFailure()).
+//
+// This class is useful for two purposes:
+//   1. Defining predicate functions to be used with Boolean test assertions
+//      EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts
+//   2. Defining predicate-format functions to be
+//      used with predicate assertions (ASSERT_PRED_FORMAT*, etc).
+//
+// For example, if you define IsEven predicate:
+//
+//   testing::AssertionResult IsEven(int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess();
+//     else
+//       return testing::AssertionFailure() << n << " is odd";
+//   }
+//
+// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5)))
+// will print the message
+//
+//   Value of: IsEven(Fib(5))
+//     Actual: false (5 is odd)
+//   Expected: true
+//
+// instead of a more opaque
+//
+//   Value of: IsEven(Fib(5))
+//     Actual: false
+//   Expected: true
+//
+// in case IsEven is a simple Boolean predicate.
+//
+// If you expect your predicate to be reused and want to support informative
+// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up
+// about half as often as positive ones in our tests), supply messages for
+// both success and failure cases:
+//
+//   testing::AssertionResult IsEven(int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess() << n << " is even";
+//     else
+//       return testing::AssertionFailure() << n << " is odd";
+//   }
+//
+// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print
+//
+//   Value of: IsEven(Fib(6))
+//     Actual: true (8 is even)
+//   Expected: false
+//
+// NB: Predicates that support negative Boolean assertions have reduced
+// performance in positive ones so be careful not to use them in tests
+// that have lots (tens of thousands) of positive Boolean assertions.
+//
+// To use this class with EXPECT_PRED_FORMAT assertions such as:
+//
+//   // Verifies that Foo() returns an even number.
+//   EXPECT_PRED_FORMAT1(IsEven, Foo());
+//
+// you need to define:
+//
+//   testing::AssertionResult IsEven(const char* expr, int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess();
+//     else
+//       return testing::AssertionFailure()
+//         << "Expected: " << expr << " is even\n  Actual: it's " << n;
+//   }
+//
+// If Foo() returns 5, you will see the following message:
+//
+//   Expected: Foo() is even
+//     Actual: it's 5
+//
+class GTEST_API_ AssertionResult {
+ public:
+  // Copy constructor.
+  // Used in EXPECT_TRUE/FALSE(assertion_result).
+  AssertionResult(const AssertionResult& other);
+  // Used in the EXPECT_TRUE/FALSE(bool_expression).
+  explicit AssertionResult(bool success) : success_(success) {}
+
+  // Returns true iff the assertion succeeded.
+  operator bool() const { return success_; }  // NOLINT
+
+  // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
+  AssertionResult operator!() const;
+
+  // Returns the text streamed into this AssertionResult. Test assertions
+  // use it when they fail (i.e., the predicate's outcome doesn't match the
+  // assertion's expectation). When nothing has been streamed into the
+  // object, returns an empty string.
+  const char* message() const {
+    return message_.get() != NULL ?  message_->c_str() : "";
+  }
+  // TODO(vladl@google.com): Remove this after making sure no clients use it.
+  // Deprecated; please use message() instead.
+  const char* failure_message() const { return message(); }
+
+  // Streams a custom failure message into this object.
+  template <typename T> AssertionResult& operator<<(const T& value) {
+    AppendMessage(Message() << value);
+    return *this;
+  }
+
+  // Allows streaming basic output manipulators such as endl or flush into
+  // this object.
+  AssertionResult& operator<<(
+      ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) {
+    AppendMessage(Message() << basic_manipulator);
+    return *this;
+  }
+
+ private:
+  // Appends the contents of message to message_.
+  void AppendMessage(const Message& a_message) {
+    if (message_.get() == NULL)
+      message_.reset(new ::std::string);
+    message_->append(a_message.GetString().c_str());
+  }
+
+  // Stores result of the assertion predicate.
+  bool success_;
+  // Stores the message describing the condition in case the expectation
+  // construct is not satisfied with the predicate's outcome.
+  // Referenced via a pointer to avoid taking too much stack frame space
+  // with test assertions.
+  internal::scoped_ptr< ::std::string> message_;
+
+  GTEST_DISALLOW_ASSIGN_(AssertionResult);
+};
+
+// Makes a successful assertion result.
+GTEST_API_ AssertionResult AssertionSuccess();
+
+// Makes a failed assertion result.
+GTEST_API_ AssertionResult AssertionFailure();
+
+// Makes a failed assertion result with the given failure message.
+// Deprecated; use AssertionFailure() << msg.
+GTEST_API_ AssertionResult AssertionFailure(const Message& msg);
+
+// The abstract class that all tests inherit from.
+//
+// In Google Test, a unit test program contains one or many TestCases, and
+// each TestCase contains one or many Tests.
+//
+// When you define a test using the TEST macro, you don't need to
+// explicitly derive from Test - the TEST macro automatically does
+// this for you.
+//
+// The only time you derive from Test is when defining a test fixture
+// to be used a TEST_F.  For example:
+//
+//   class FooTest : public testing::Test {
+//    protected:
+//     virtual void SetUp() { ... }
+//     virtual void TearDown() { ... }
+//     ...
+//   };
+//
+//   TEST_F(FooTest, Bar) { ... }
+//   TEST_F(FooTest, Baz) { ... }
+//
+// Test is not copyable.
+class GTEST_API_ Test {
+ public:
+  friend class TestInfo;
+
+  // Defines types for pointers to functions that set up and tear down
+  // a test case.
+  typedef internal::SetUpTestCaseFunc SetUpTestCaseFunc;
+  typedef internal::TearDownTestCaseFunc TearDownTestCaseFunc;
+
+  // The d'tor is virtual as we intend to inherit from Test.
+  virtual ~Test();
+
+  // Sets up the stuff shared by all tests in this test case.
+  //
+  // Google Test will call Foo::SetUpTestCase() before running the first
+  // test in test case Foo.  Hence a sub-class can define its own
+  // SetUpTestCase() method to shadow the one defined in the super
+  // class.
+  static void SetUpTestCase() {}
+
+  // Tears down the stuff shared by all tests in this test case.
+  //
+  // Google Test will call Foo::TearDownTestCase() after running the last
+  // test in test case Foo.  Hence a sub-class can define its own
+  // TearDownTestCase() method to shadow the one defined in the super
+  // class.
+  static void TearDownTestCase() {}
+
+  // Returns true iff the current test has a fatal failure.
+  static bool HasFatalFailure();
+
+  // Returns true iff the current test has a non-fatal failure.
+  static bool HasNonfatalFailure();
+
+  // Returns true iff the current test has a (either fatal or
+  // non-fatal) failure.
+  static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); }
+
+  // Logs a property for the current test.  Only the last value for a given
+  // key is remembered.
+  // These are public static so they can be called from utility functions
+  // that are not members of the test fixture.
+  // The arguments are const char* instead strings, as Google Test is used
+  // on platforms where string doesn't compile.
+  //
+  // Note that a driving consideration for these RecordProperty methods
+  // was to produce xml output suited to the Greenspan charting utility,
+  // which at present will only chart values that fit in a 32-bit int. It
+  // is the user's responsibility to restrict their values to 32-bit ints
+  // if they intend them to be used with Greenspan.
+  static void RecordProperty(const char* key, const char* value);
+  static void RecordProperty(const char* key, int value);
+
+ protected:
+  // Creates a Test object.
+  Test();
+
+  // Sets up the test fixture.
+  virtual void SetUp();
+
+  // Tears down the test fixture.
+  virtual void TearDown();
+
+ private:
+  // Returns true iff the current test has the same fixture class as
+  // the first test in the current test case.
+  static bool HasSameFixtureClass();
+
+  // Runs the test after the test fixture has been set up.
+  //
+  // A sub-class must implement this to define the test logic.
+  //
+  // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM.
+  // Instead, use the TEST or TEST_F macro.
+  virtual void TestBody() = 0;
+
+  // Sets up, executes, and tears down the test.
+  void Run();
+
+  // Deletes self.  We deliberately pick an unusual name for this
+  // internal method to avoid clashing with names used in user TESTs.
+  void DeleteSelf_() { delete this; }
+
+  // Uses a GTestFlagSaver to save and restore all Google Test flags.
+  const internal::GTestFlagSaver* const gtest_flag_saver_;
+
+  // Often a user mis-spells SetUp() as Setup() and spends a long time
+  // wondering why it is never called by Google Test.  The declaration of
+  // the following method is solely for catching such an error at
+  // compile time:
+  //
+  //   - The return type is deliberately chosen to be not void, so it
+  //   will be a conflict if a user declares void Setup() in his test
+  //   fixture.
+  //
+  //   - This method is private, so it will be another compiler error
+  //   if a user calls it from his test fixture.
+  //
+  // DO NOT OVERRIDE THIS FUNCTION.
+  //
+  // If you see an error about overriding the following function or
+  // about it being private, you have mis-spelled SetUp() as Setup().
+  struct Setup_should_be_spelled_SetUp {};
+  virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
+
+  // We disallow copying Tests.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Test);
+};
+
+typedef internal::TimeInMillis TimeInMillis;
+
+// A copyable object representing a user specified test property which can be
+// output as a key/value string pair.
+//
+// Don't inherit from TestProperty as its destructor is not virtual.
+class TestProperty {
+ public:
+  // C'tor.  TestProperty does NOT have a default constructor.
+  // Always use this constructor (with parameters) to create a
+  // TestProperty object.
+  TestProperty(const char* a_key, const char* a_value) :
+    key_(a_key), value_(a_value) {
+  }
+
+  // Gets the user supplied key.
+  const char* key() const {
+    return key_.c_str();
+  }
+
+  // Gets the user supplied value.
+  const char* value() const {
+    return value_.c_str();
+  }
+
+  // Sets a new value, overriding the one supplied in the constructor.
+  void SetValue(const char* new_value) {
+    value_ = new_value;
+  }
+
+ private:
+  // The key supplied by the user.
+  internal::String key_;
+  // The value supplied by the user.
+  internal::String value_;
+};
+
+// The result of a single Test.  This includes a list of
+// TestPartResults, a list of TestProperties, a count of how many
+// death tests there are in the Test, and how much time it took to run
+// the Test.
+//
+// TestResult is not copyable.
+class GTEST_API_ TestResult {
+ public:
+  // Creates an empty TestResult.
+  TestResult();
+
+  // D'tor.  Do not inherit from TestResult.
+  ~TestResult();
+
+  // Gets the number of all test parts.  This is the sum of the number
+  // of successful test parts and the number of failed test parts.
+  int total_part_count() const;
+
+  // Returns the number of the test properties.
+  int test_property_count() const;
+
+  // Returns true iff the test passed (i.e. no test part failed).
+  bool Passed() const { return !Failed(); }
+
+  // Returns true iff the test failed.
+  bool Failed() const;
+
+  // Returns true iff the test fatally failed.
+  bool HasFatalFailure() const;
+
+  // Returns true iff the test has a non-fatal failure.
+  bool HasNonfatalFailure() const;
+
+  // Returns the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Returns the i-th test part result among all the results. i can range
+  // from 0 to test_property_count() - 1. If i is not in that range, aborts
+  // the program.
+  const TestPartResult& GetTestPartResult(int i) const;
+
+  // Returns the i-th test property. i can range from 0 to
+  // test_property_count() - 1. If i is not in that range, aborts the
+  // program.
+  const TestProperty& GetTestProperty(int i) const;
+
+ private:
+  friend class TestInfo;
+  friend class UnitTest;
+  friend class internal::DefaultGlobalTestPartResultReporter;
+  friend class internal::ExecDeathTest;
+  friend class internal::TestResultAccessor;
+  friend class internal::UnitTestImpl;
+  friend class internal::WindowsDeathTest;
+
+  // Gets the vector of TestPartResults.
+  const std::vector<TestPartResult>& test_part_results() const {
+    return test_part_results_;
+  }
+
+  // Gets the vector of TestProperties.
+  const std::vector<TestProperty>& test_properties() const {
+    return test_properties_;
+  }
+
+  // Sets the elapsed time.
+  void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; }
+
+  // Adds a test property to the list. The property is validated and may add
+  // a non-fatal failure if invalid (e.g., if it conflicts with reserved
+  // key names). If a property is already recorded for the same key, the
+  // value will be updated, rather than storing multiple values for the same
+  // key.
+  void RecordProperty(const TestProperty& test_property);
+
+  // Adds a failure if the key is a reserved attribute of Google Test
+  // testcase tags.  Returns true if the property is valid.
+  // TODO(russr): Validate attribute names are legal and human readable.
+  static bool ValidateTestProperty(const TestProperty& test_property);
+
+  // Adds a test part result to the list.
+  void AddTestPartResult(const TestPartResult& test_part_result);
+
+  // Returns the death test count.
+  int death_test_count() const { return death_test_count_; }
+
+  // Increments the death test count, returning the new count.
+  int increment_death_test_count() { return ++death_test_count_; }
+
+  // Clears the test part results.
+  void ClearTestPartResults();
+
+  // Clears the object.
+  void Clear();
+
+  // Protects mutable state of the property vector and of owned
+  // properties, whose values may be updated.
+  internal::Mutex test_properites_mutex_;
+
+  // The vector of TestPartResults
+  std::vector<TestPartResult> test_part_results_;
+  // The vector of TestProperties
+  std::vector<TestProperty> test_properties_;
+  // Running count of death tests.
+  int death_test_count_;
+  // The elapsed time, in milliseconds.
+  TimeInMillis elapsed_time_;
+
+  // We disallow copying TestResult.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult);
+};  // class TestResult
+
+// A TestInfo object stores the following information about a test:
+//
+//   Test case name
+//   Test name
+//   Whether the test should be run
+//   A function pointer that creates the test object when invoked
+//   Test result
+//
+// The constructor of TestInfo registers itself with the UnitTest
+// singleton such that the RUN_ALL_TESTS() macro knows which tests to
+// run.
+class GTEST_API_ TestInfo {
+ public:
+  // Destructs a TestInfo object.  This function is not virtual, so
+  // don't inherit from TestInfo.
+  ~TestInfo();
+
+  // Returns the test case name.
+  const char* test_case_name() const { return test_case_name_.c_str(); }
+
+  // Returns the test name.
+  const char* name() const { return name_.c_str(); }
+
+  // Returns the name of the parameter type, or NULL if this is not a typed
+  // or a type-parameterized test.
+  const char* type_param() const {
+    if (type_param_.get() != NULL)
+      return type_param_->c_str();
+    return NULL;
+  }
+
+  // Returns the text representation of the value parameter, or NULL if this
+  // is not a value-parameterized test.
+  const char* value_param() const {
+    if (value_param_.get() != NULL)
+      return value_param_->c_str();
+    return NULL;
+  }
+
+  // Returns true if this test should run, that is if the test is not disabled
+  // (or it is disabled but the also_run_disabled_tests flag has been specified)
+  // and its full name matches the user-specified filter.
+  //
+  // Google Test allows the user to filter the tests by their full names.
+  // The full name of a test Bar in test case Foo is defined as
+  // "Foo.Bar".  Only the tests that match the filter will run.
+  //
+  // A filter is a colon-separated list of glob (not regex) patterns,
+  // optionally followed by a '-' and a colon-separated list of
+  // negative patterns (tests to exclude).  A test is run if it
+  // matches one of the positive patterns and does not match any of
+  // the negative patterns.
+  //
+  // For example, *A*:Foo.* is a filter that matches any string that
+  // contains the character 'A' or starts with "Foo.".
+  bool should_run() const { return should_run_; }
+
+  // Returns the result of the test.
+  const TestResult* result() const { return &result_; }
+
+ private:
+
+#if GTEST_HAS_DEATH_TEST
+  friend class internal::DefaultDeathTestFactory;
+#endif  // GTEST_HAS_DEATH_TEST
+  friend class Test;
+  friend class TestCase;
+  friend class internal::UnitTestImpl;
+  friend TestInfo* internal::MakeAndRegisterTestInfo(
+      const char* test_case_name, const char* name,
+      const char* type_param,
+      const char* value_param,
+      internal::TypeId fixture_class_id,
+      Test::SetUpTestCaseFunc set_up_tc,
+      Test::TearDownTestCaseFunc tear_down_tc,
+      internal::TestFactoryBase* factory);
+
+  // Constructs a TestInfo object. The newly constructed instance assumes
+  // ownership of the factory object.
+  TestInfo(const char* test_case_name, const char* name,
+           const char* a_type_param,
+           const char* a_value_param,
+           internal::TypeId fixture_class_id,
+           internal::TestFactoryBase* factory);
+
+  // Increments the number of death tests encountered in this test so
+  // far.
+  int increment_death_test_count() {
+    return result_.increment_death_test_count();
+  }
+
+  // Creates the test object, runs it, records its result, and then
+  // deletes it.
+  void Run();
+
+  static void ClearTestResult(TestInfo* test_info) {
+    test_info->result_.Clear();
+  }
+
+  // These fields are immutable properties of the test.
+  const std::string test_case_name_;     // Test case name
+  const std::string name_;               // Test name
+  // Name of the parameter type, or NULL if this is not a typed or a
+  // type-parameterized test.
+  const internal::scoped_ptr<const ::std::string> type_param_;
+  // Text representation of the value parameter, or NULL if this is not a
+  // value-parameterized test.
+  const internal::scoped_ptr<const ::std::string> value_param_;
+  const internal::TypeId fixture_class_id_;   // ID of the test fixture class
+  bool should_run_;                 // True iff this test should run
+  bool is_disabled_;                // True iff this test is disabled
+  bool matches_filter_;             // True if this test matches the
+                                    // user-specified filter.
+  internal::TestFactoryBase* const factory_;  // The factory that creates
+                                              // the test object
+
+  // This field is mutable and needs to be reset before running the
+  // test for the second time.
+  TestResult result_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo);
+};
+
+// A test case, which consists of a vector of TestInfos.
+//
+// TestCase is not copyable.
+class GTEST_API_ TestCase {
+ public:
+  // Creates a TestCase with the given name.
+  //
+  // TestCase does NOT have a default constructor.  Always use this
+  // constructor to create a TestCase object.
+  //
+  // Arguments:
+  //
+  //   name:         name of the test case
+  //   a_type_param: the name of the test's type parameter, or NULL if
+  //                 this is not a type-parameterized test.
+  //   set_up_tc:    pointer to the function that sets up the test case
+  //   tear_down_tc: pointer to the function that tears down the test case
+  TestCase(const char* name, const char* a_type_param,
+           Test::SetUpTestCaseFunc set_up_tc,
+           Test::TearDownTestCaseFunc tear_down_tc);
+
+  // Destructor of TestCase.
+  virtual ~TestCase();
+
+  // Gets the name of the TestCase.
+  const char* name() const { return name_.c_str(); }
+
+  // Returns the name of the parameter type, or NULL if this is not a
+  // type-parameterized test case.
+  const char* type_param() const {
+    if (type_param_.get() != NULL)
+      return type_param_->c_str();
+    return NULL;
+  }
+
+  // Returns true if any test in this test case should run.
+  bool should_run() const { return should_run_; }
+
+  // Gets the number of successful tests in this test case.
+  int successful_test_count() const;
+
+  // Gets the number of failed tests in this test case.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests in this test case.
+  int disabled_test_count() const;
+
+  // Get the number of tests in this test case that should run.
+  int test_to_run_count() const;
+
+  // Gets the number of all tests in this test case.
+  int total_test_count() const;
+
+  // Returns true iff the test case passed.
+  bool Passed() const { return !Failed(); }
+
+  // Returns true iff the test case failed.
+  bool Failed() const { return failed_test_count() > 0; }
+
+  // Returns the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Returns the i-th test among all the tests. i can range from 0 to
+  // total_test_count() - 1. If i is not in that range, returns NULL.
+  const TestInfo* GetTestInfo(int i) const;
+
+ private:
+  friend class Test;
+  friend class internal::UnitTestImpl;
+
+  // Gets the (mutable) vector of TestInfos in this TestCase.
+  std::vector<TestInfo*>& test_info_list() { return test_info_list_; }
+
+  // Gets the (immutable) vector of TestInfos in this TestCase.
+  const std::vector<TestInfo*>& test_info_list() const {
+    return test_info_list_;
+  }
+
+  // Returns the i-th test among all the tests. i can range from 0 to
+  // total_test_count() - 1. If i is not in that range, returns NULL.
+  TestInfo* GetMutableTestInfo(int i);
+
+  // Sets the should_run member.
+  void set_should_run(bool should) { should_run_ = should; }
+
+  // Adds a TestInfo to this test case.  Will delete the TestInfo upon
+  // destruction of the TestCase object.
+  void AddTestInfo(TestInfo * test_info);
+
+  // Clears the results of all tests in this test case.
+  void ClearResult();
+
+  // Clears the results of all tests in the given test case.
+  static void ClearTestCaseResult(TestCase* test_case) {
+    test_case->ClearResult();
+  }
+
+  // Runs every test in this TestCase.
+  void Run();
+
+  // Runs SetUpTestCase() for this TestCase.  This wrapper is needed
+  // for catching exceptions thrown from SetUpTestCase().
+  void RunSetUpTestCase() { (*set_up_tc_)(); }
+
+  // Runs TearDownTestCase() for this TestCase.  This wrapper is
+  // needed for catching exceptions thrown from TearDownTestCase().
+  void RunTearDownTestCase() { (*tear_down_tc_)(); }
+
+  // Returns true iff test passed.
+  static bool TestPassed(const TestInfo* test_info) {
+    return test_info->should_run() && test_info->result()->Passed();
+  }
+
+  // Returns true iff test failed.
+  static bool TestFailed(const TestInfo* test_info) {
+    return test_info->should_run() && test_info->result()->Failed();
+  }
+
+  // Returns true iff test is disabled.
+  static bool TestDisabled(const TestInfo* test_info) {
+    return test_info->is_disabled_;
+  }
+
+  // Returns true if the given test should run.
+  static bool ShouldRunTest(const TestInfo* test_info) {
+    return test_info->should_run();
+  }
+
+  // Shuffles the tests in this test case.
+  void ShuffleTests(internal::Random* random);
+
+  // Restores the test order to before the first shuffle.
+  void UnshuffleTests();
+
+  // Name of the test case.
+  internal::String name_;
+  // Name of the parameter type, or NULL if this is not a typed or a
+  // type-parameterized test.
+  const internal::scoped_ptr<const ::std::string> type_param_;
+  // The vector of TestInfos in their original order.  It owns the
+  // elements in the vector.
+  std::vector<TestInfo*> test_info_list_;
+  // Provides a level of indirection for the test list to allow easy
+  // shuffling and restoring the test order.  The i-th element in this
+  // vector is the index of the i-th test in the shuffled test list.
+  std::vector<int> test_indices_;
+  // Pointer to the function that sets up the test case.
+  Test::SetUpTestCaseFunc set_up_tc_;
+  // Pointer to the function that tears down the test case.
+  Test::TearDownTestCaseFunc tear_down_tc_;
+  // True iff any test in this test case should run.
+  bool should_run_;
+  // Elapsed time, in milliseconds.
+  TimeInMillis elapsed_time_;
+
+  // We disallow copying TestCases.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase);
+};
+
+// An Environment object is capable of setting up and tearing down an
+// environment.  The user should subclass this to define his own
+// environment(s).
+//
+// An Environment object does the set-up and tear-down in virtual
+// methods SetUp() and TearDown() instead of the constructor and the
+// destructor, as:
+//
+//   1. You cannot safely throw from a destructor.  This is a problem
+//      as in some cases Google Test is used where exceptions are enabled, and
+//      we may want to implement ASSERT_* using exceptions where they are
+//      available.
+//   2. You cannot use ASSERT_* directly in a constructor or
+//      destructor.
+class Environment {
+ public:
+  // The d'tor is virtual as we need to subclass Environment.
+  virtual ~Environment() {}
+
+  // Override this to define how to set up the environment.
+  virtual void SetUp() {}
+
+  // Override this to define how to tear down the environment.
+  virtual void TearDown() {}
+ private:
+  // If you see an error about overriding the following function or
+  // about it being private, you have mis-spelled SetUp() as Setup().
+  struct Setup_should_be_spelled_SetUp {};
+  virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
+};
+
+// The interface for tracing execution of tests. The methods are organized in
+// the order the corresponding events are fired.
+class TestEventListener {
+ public:
+  virtual ~TestEventListener() {}
+
+  // Fired before any test activity starts.
+  virtual void OnTestProgramStart(const UnitTest& unit_test) = 0;
+
+  // Fired before each iteration of tests starts.  There may be more than
+  // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration
+  // index, starting from 0.
+  virtual void OnTestIterationStart(const UnitTest& unit_test,
+                                    int iteration) = 0;
+
+  // Fired before environment set-up for each iteration of tests starts.
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0;
+
+  // Fired after environment set-up for each iteration of tests ends.
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0;
+
+  // Fired before the test case starts.
+  virtual void OnTestCaseStart(const TestCase& test_case) = 0;
+
+  // Fired before the test starts.
+  virtual void OnTestStart(const TestInfo& test_info) = 0;
+
+  // Fired after a failed assertion or a SUCCEED() invocation.
+  virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0;
+
+  // Fired after the test ends.
+  virtual void OnTestEnd(const TestInfo& test_info) = 0;
+
+  // Fired after the test case ends.
+  virtual void OnTestCaseEnd(const TestCase& test_case) = 0;
+
+  // Fired before environment tear-down for each iteration of tests starts.
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0;
+
+  // Fired after environment tear-down for each iteration of tests ends.
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0;
+
+  // Fired after each iteration of tests finishes.
+  virtual void OnTestIterationEnd(const UnitTest& unit_test,
+                                  int iteration) = 0;
+
+  // Fired after all test activities have ended.
+  virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0;
+};
+
+// The convenience class for users who need to override just one or two
+// methods and are not concerned that a possible change to a signature of
+// the methods they override will not be caught during the build.  For
+// comments about each method please see the definition of TestEventListener
+// above.
+class EmptyTestEventListener : public TestEventListener {
+ public:
+  virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationStart(const UnitTest& /*unit_test*/,
+                                    int /*iteration*/) {}
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestCaseStart(const TestCase& /*test_case*/) {}
+  virtual void OnTestStart(const TestInfo& /*test_info*/) {}
+  virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {}
+  virtual void OnTestEnd(const TestInfo& /*test_info*/) {}
+  virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {}
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/,
+                                  int /*iteration*/) {}
+  virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {}
+};
+
+// TestEventListeners lets users add listeners to track events in Google Test.
+class GTEST_API_ TestEventListeners {
+ public:
+  TestEventListeners();
+  ~TestEventListeners();
+
+  // Appends an event listener to the end of the list. Google Test assumes
+  // the ownership of the listener (i.e. it will delete the listener when
+  // the test program finishes).
+  void Append(TestEventListener* listener);
+
+  // Removes the given event listener from the list and returns it.  It then
+  // becomes the caller's responsibility to delete the listener. Returns
+  // NULL if the listener is not found in the list.
+  TestEventListener* Release(TestEventListener* listener);
+
+  // Returns the standard listener responsible for the default console
+  // output.  Can be removed from the listeners list to shut down default
+  // console output.  Note that removing this object from the listener list
+  // with Release transfers its ownership to the caller and makes this
+  // function return NULL the next time.
+  TestEventListener* default_result_printer() const {
+    return default_result_printer_;
+  }
+
+  // Returns the standard listener responsible for the default XML output
+  // controlled by the --gtest_output=xml flag.  Can be removed from the
+  // listeners list by users who want to shut down the default XML output
+  // controlled by this flag and substitute it with custom one.  Note that
+  // removing this object from the listener list with Release transfers its
+  // ownership to the caller and makes this function return NULL the next
+  // time.
+  TestEventListener* default_xml_generator() const {
+    return default_xml_generator_;
+  }
+
+ private:
+  friend class TestCase;
+  friend class TestInfo;
+  friend class internal::DefaultGlobalTestPartResultReporter;
+  friend class internal::NoExecDeathTest;
+  friend class internal::TestEventListenersAccessor;
+  friend class internal::UnitTestImpl;
+
+  // Returns repeater that broadcasts the TestEventListener events to all
+  // subscribers.
+  TestEventListener* repeater();
+
+  // Sets the default_result_printer attribute to the provided listener.
+  // The listener is also added to the listener list and previous
+  // default_result_printer is removed from it and deleted. The listener can
+  // also be NULL in which case it will not be added to the list. Does
+  // nothing if the previous and the current listener objects are the same.
+  void SetDefaultResultPrinter(TestEventListener* listener);
+
+  // Sets the default_xml_generator attribute to the provided listener.  The
+  // listener is also added to the listener list and previous
+  // default_xml_generator is removed from it and deleted. The listener can
+  // also be NULL in which case it will not be added to the list. Does
+  // nothing if the previous and the current listener objects are the same.
+  void SetDefaultXmlGenerator(TestEventListener* listener);
+
+  // Controls whether events will be forwarded by the repeater to the
+  // listeners in the list.
+  bool EventForwardingEnabled() const;
+  void SuppressEventForwarding();
+
+  // The actual list of listeners.
+  internal::TestEventRepeater* repeater_;
+  // Listener responsible for the standard result output.
+  TestEventListener* default_result_printer_;
+  // Listener responsible for the creation of the XML output file.
+  TestEventListener* default_xml_generator_;
+
+  // We disallow copying TestEventListeners.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners);
+};
+
+// A UnitTest consists of a vector of TestCases.
+//
+// This is a singleton class.  The only instance of UnitTest is
+// created when UnitTest::GetInstance() is first called.  This
+// instance is never deleted.
+//
+// UnitTest is not copyable.
+//
+// This class is thread-safe as long as the methods are called
+// according to their specification.
+class GTEST_API_ UnitTest {
+ public:
+  // Gets the singleton UnitTest object.  The first time this method
+  // is called, a UnitTest object is constructed and returned.
+  // Consecutive calls will return the same object.
+  static UnitTest* GetInstance();
+
+  // Runs all tests in this UnitTest object and prints the result.
+  // Returns 0 if successful, or 1 otherwise.
+  //
+  // This method can only be called from the main thread.
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  int Run() GTEST_MUST_USE_RESULT_;
+
+  // Returns the working directory when the first TEST() or TEST_F()
+  // was executed.  The UnitTest object owns the string.
+  const char* original_working_dir() const;
+
+  // Returns the TestCase object for the test that's currently running,
+  // or NULL if no test is running.
+  const TestCase* current_test_case() const;
+
+  // Returns the TestInfo object for the test that's currently running,
+  // or NULL if no test is running.
+  const TestInfo* current_test_info() const;
+
+  // Returns the random seed used at the start of the current test run.
+  int random_seed() const;
+
+#if GTEST_HAS_PARAM_TEST
+  // Returns the ParameterizedTestCaseRegistry object used to keep track of
+  // value-parameterized tests and instantiate and register them.
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  internal::ParameterizedTestCaseRegistry& parameterized_test_registry();
+#endif  // GTEST_HAS_PARAM_TEST
+
+  // Gets the number of successful test cases.
+  int successful_test_case_count() const;
+
+  // Gets the number of failed test cases.
+  int failed_test_case_count() const;
+
+  // Gets the number of all test cases.
+  int total_test_case_count() const;
+
+  // Gets the number of all test cases that contain at least one test
+  // that should run.
+  int test_case_to_run_count() const;
+
+  // Gets the number of successful tests.
+  int successful_test_count() const;
+
+  // Gets the number of failed tests.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests.
+  int disabled_test_count() const;
+
+  // Gets the number of all tests.
+  int total_test_count() const;
+
+  // Gets the number of tests that should run.
+  int test_to_run_count() const;
+
+  // Gets the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const;
+
+  // Returns true iff the unit test passed (i.e. all test cases passed).
+  bool Passed() const;
+
+  // Returns true iff the unit test failed (i.e. some test case failed
+  // or something outside of all tests failed).
+  bool Failed() const;
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  const TestCase* GetTestCase(int i) const;
+
+  // Returns the list of event listeners that can be used to track events
+  // inside Google Test.
+  TestEventListeners& listeners();
+
+ private:
+  // Registers and returns a global test environment.  When a test
+  // program is run, all global test environments will be set-up in
+  // the order they were registered.  After all tests in the program
+  // have finished, all global test environments will be torn-down in
+  // the *reverse* order they were registered.
+  //
+  // The UnitTest object takes ownership of the given environment.
+  //
+  // This method can only be called from the main thread.
+  Environment* AddEnvironment(Environment* env);
+
+  // Adds a TestPartResult to the current TestResult object.  All
+  // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc)
+  // eventually call this to report their results.  The user code
+  // should use the assertion macros instead of calling this directly.
+  void AddTestPartResult(TestPartResult::Type result_type,
+                         const char* file_name,
+                         int line_number,
+                         const internal::String& message,
+                         const internal::String& os_stack_trace);
+
+  // Adds a TestProperty to the current TestResult object. If the result already
+  // contains a property with the same key, the value will be updated.
+  void RecordPropertyForCurrentTest(const char* key, const char* value);
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  TestCase* GetMutableTestCase(int i);
+
+  // Accessors for the implementation object.
+  internal::UnitTestImpl* impl() { return impl_; }
+  const internal::UnitTestImpl* impl() const { return impl_; }
+
+  // These classes and funcions are friends as they need to access private
+  // members of UnitTest.
+  friend class Test;
+  friend class internal::AssertHelper;
+  friend class internal::ScopedTrace;
+  friend Environment* AddGlobalTestEnvironment(Environment* env);
+  friend internal::UnitTestImpl* internal::GetUnitTestImpl();
+  friend void internal::ReportFailureInUnknownLocation(
+      TestPartResult::Type result_type,
+      const internal::String& message);
+
+  // Creates an empty UnitTest.
+  UnitTest();
+
+  // D'tor
+  virtual ~UnitTest();
+
+  // Pushes a trace defined by SCOPED_TRACE() on to the per-thread
+  // Google Test trace stack.
+  void PushGTestTrace(const internal::TraceInfo& trace);
+
+  // Pops a trace from the per-thread Google Test trace stack.
+  void PopGTestTrace();
+
+  // Protects mutable state in *impl_.  This is mutable as some const
+  // methods need to lock it too.
+  mutable internal::Mutex mutex_;
+
+  // Opaque implementation object.  This field is never changed once
+  // the object is constructed.  We don't mark it as const here, as
+  // doing so will cause a warning in the constructor of UnitTest.
+  // Mutable state in *impl_ is protected by mutex_.
+  internal::UnitTestImpl* impl_;
+
+  // We disallow copying UnitTest.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTest);
+};
+
+// A convenient wrapper for adding an environment for the test
+// program.
+//
+// You should call this before RUN_ALL_TESTS() is called, probably in
+// main().  If you use gtest_main, you need to call this before main()
+// starts for it to take effect.  For example, you can define a global
+// variable like this:
+//
+//   testing::Environment* const foo_env =
+//       testing::AddGlobalTestEnvironment(new FooEnvironment);
+//
+// However, we strongly recommend you to write your own main() and
+// call AddGlobalTestEnvironment() there, as relying on initialization
+// of global variables makes the code harder to read and may cause
+// problems when you register multiple environments from different
+// translation units and the environments have dependencies among them
+// (remember that the compiler doesn't guarantee the order in which
+// global variables from different translation units are initialized).
+inline Environment* AddGlobalTestEnvironment(Environment* env) {
+  return UnitTest::GetInstance()->AddEnvironment(env);
+}
+
+// Initializes Google Test.  This must be called before calling
+// RUN_ALL_TESTS().  In particular, it parses a command line for the
+// flags that Google Test recognizes.  Whenever a Google Test flag is
+// seen, it is removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Test flag variables are
+// updated.
+//
+// Calling the function for the second time has no user-visible effect.
+GTEST_API_ void InitGoogleTest(int* argc, char** argv);
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv);
+
+namespace internal {
+
+// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc)
+// operand to be used in a failure message.  The type (but not value)
+// of the other operand may affect the format.  This allows us to
+// print a char* as a raw pointer when it is compared against another
+// char*, and print it as a C string when it is compared against an
+// std::string object, for example.
+//
+// The default implementation ignores the type of the other operand.
+// Some specialized versions are used to handle formatting wide or
+// narrow C strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+template <typename T1, typename T2>
+String FormatForComparisonFailureMessage(const T1& value,
+                                         const T2& /* other_operand */) {
+  // C++Builder compiles this incorrectly if the namespace isn't explicitly
+  // given.
+  return ::testing::PrintToString(value);
+}
+
+// The helper function for {ASSERT|EXPECT}_EQ.
+template <typename T1, typename T2>
+AssertionResult CmpHelperEQ(const char* expected_expression,
+                            const char* actual_expression,
+                            const T1& expected,
+                            const T2& actual) {
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4389)  // Temporarily disables warning on
+                               // signed/unsigned mismatch.
+#endif
+
+  if (expected == actual) {
+    return AssertionSuccess();
+  }
+
+#ifdef _MSC_VER
+# pragma warning(pop)          // Restores the warning state.
+#endif
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   FormatForComparisonFailureMessage(expected, actual),
+                   FormatForComparisonFailureMessage(actual, expected),
+                   false);
+}
+
+// With this overloaded version, we allow anonymous enums to be used
+// in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums
+// can be implicitly cast to BiggestInt.
+GTEST_API_ AssertionResult CmpHelperEQ(const char* expected_expression,
+                                       const char* actual_expression,
+                                       BiggestInt expected,
+                                       BiggestInt actual);
+
+// The helper class for {ASSERT|EXPECT}_EQ.  The template argument
+// lhs_is_null_literal is true iff the first argument to ASSERT_EQ()
+// is a null pointer literal.  The following default implementation is
+// for lhs_is_null_literal being false.
+template <bool lhs_is_null_literal>
+class EqHelper {
+ public:
+  // This templatized version is for the general case.
+  template <typename T1, typename T2>
+  static AssertionResult Compare(const char* expected_expression,
+                                 const char* actual_expression,
+                                 const T1& expected,
+                                 const T2& actual) {
+    return CmpHelperEQ(expected_expression, actual_expression, expected,
+                       actual);
+  }
+
+  // With this overloaded version, we allow anonymous enums to be used
+  // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous
+  // enums can be implicitly cast to BiggestInt.
+  //
+  // Even though its body looks the same as the above version, we
+  // cannot merge the two, as it will make anonymous enums unhappy.
+  static AssertionResult Compare(const char* expected_expression,
+                                 const char* actual_expression,
+                                 BiggestInt expected,
+                                 BiggestInt actual) {
+    return CmpHelperEQ(expected_expression, actual_expression, expected,
+                       actual);
+  }
+};
+
+// This specialization is used when the first argument to ASSERT_EQ()
+// is a null pointer literal, like NULL, false, or 0.
+template <>
+class EqHelper<true> {
+ public:
+  // We define two overloaded versions of Compare().  The first
+  // version will be picked when the second argument to ASSERT_EQ() is
+  // NOT a pointer, e.g. ASSERT_EQ(0, AnIntFunction()) or
+  // EXPECT_EQ(false, a_bool).
+  template <typename T1, typename T2>
+  static AssertionResult Compare(
+      const char* expected_expression,
+      const char* actual_expression,
+      const T1& expected,
+      const T2& actual,
+      // The following line prevents this overload from being considered if T2
+      // is not a pointer type.  We need this because ASSERT_EQ(NULL, my_ptr)
+      // expands to Compare("", "", NULL, my_ptr), which requires a conversion
+      // to match the Secret* in the other overload, which would otherwise make
+      // this template match better.
+      typename EnableIf<!is_pointer<T2>::value>::type* = 0) {
+    return CmpHelperEQ(expected_expression, actual_expression, expected,
+                       actual);
+  }
+
+  // This version will be picked when the second argument to ASSERT_EQ() is a
+  // pointer, e.g. ASSERT_EQ(NULL, a_pointer).
+  template <typename T>
+  static AssertionResult Compare(
+      const char* expected_expression,
+      const char* actual_expression,
+      // We used to have a second template parameter instead of Secret*.  That
+      // template parameter would deduce to 'long', making this a better match
+      // than the first overload even without the first overload's EnableIf.
+      // Unfortunately, gcc with -Wconversion-null warns when "passing NULL to
+      // non-pointer argument" (even a deduced integral argument), so the old
+      // implementation caused warnings in user code.
+      Secret* /* expected (NULL) */,
+      T* actual) {
+    // We already know that 'expected' is a null pointer.
+    return CmpHelperEQ(expected_expression, actual_expression,
+                       static_cast<T*>(NULL), actual);
+  }
+};
+
+// A macro for implementing the helper functions needed to implement
+// ASSERT_?? and EXPECT_??.  It is here just to avoid copy-and-paste
+// of similar code.
+//
+// For each templatized helper function, we also define an overloaded
+// version for BiggestInt in order to reduce code bloat and allow
+// anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled
+// with gcc 4.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
+template <typename T1, typename T2>\
+AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
+                                   const T1& val1, const T2& val2) {\
+  if (val1 op val2) {\
+    return AssertionSuccess();\
+  } else {\
+    return AssertionFailure() \
+        << "Expected: (" << expr1 << ") " #op " (" << expr2\
+        << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
+        << " vs " << FormatForComparisonFailureMessage(val2, val1);\
+  }\
+}\
+GTEST_API_ AssertionResult CmpHelper##op_name(\
+    const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2)
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+
+// Implements the helper function for {ASSERT|EXPECT}_NE
+GTEST_IMPL_CMP_HELPER_(NE, !=);
+// Implements the helper function for {ASSERT|EXPECT}_LE
+GTEST_IMPL_CMP_HELPER_(LE, <=);
+// Implements the helper function for {ASSERT|EXPECT}_LT
+GTEST_IMPL_CMP_HELPER_(LT, < );
+// Implements the helper function for {ASSERT|EXPECT}_GE
+GTEST_IMPL_CMP_HELPER_(GE, >=);
+// Implements the helper function for {ASSERT|EXPECT}_GT
+GTEST_IMPL_CMP_HELPER_(GT, > );
+
+#undef GTEST_IMPL_CMP_HELPER_
+
+// The helper function for {ASSERT|EXPECT}_STREQ.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                                          const char* actual_expression,
+                                          const char* expected,
+                                          const char* actual);
+
+// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression,
+                                              const char* actual_expression,
+                                              const char* expected,
+                                              const char* actual);
+
+// The helper function for {ASSERT|EXPECT}_STRNE.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                                          const char* s2_expression,
+                                          const char* s1,
+                                          const char* s2);
+
+// The helper function for {ASSERT|EXPECT}_STRCASENE.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
+                                              const char* s2_expression,
+                                              const char* s1,
+                                              const char* s2);
+
+
+// Helper function for *_STREQ on wide strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                                          const char* actual_expression,
+                                          const wchar_t* expected,
+                                          const wchar_t* actual);
+
+// Helper function for *_STRNE on wide strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                                          const char* s2_expression,
+                                          const wchar_t* s1,
+                                          const wchar_t* s2);
+
+}  // namespace internal
+
+// IsSubstring() and IsNotSubstring() are intended to be used as the
+// first argument to {EXPECT,ASSERT}_PRED_FORMAT2(), not by
+// themselves.  They check whether needle is a substring of haystack
+// (NULL is considered a substring of itself only), and return an
+// appropriate error message when they fail.
+//
+// The {needle,haystack}_expr arguments are the stringified
+// expressions that generated the two real arguments.
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack);
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack);
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack);
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack);
+#endif  // GTEST_HAS_STD_WSTRING
+
+namespace internal {
+
+// Helper template function for comparing floating-points.
+//
+// Template parameter:
+//
+//   RawType: the raw floating-point type (either float or double)
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+template <typename RawType>
+AssertionResult CmpHelperFloatingPointEQ(const char* expected_expression,
+                                         const char* actual_expression,
+                                         RawType expected,
+                                         RawType actual) {
+  const FloatingPoint<RawType> lhs(expected), rhs(actual);
+
+  if (lhs.AlmostEquals(rhs)) {
+    return AssertionSuccess();
+  }
+
+  ::std::stringstream expected_ss;
+  expected_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+              << expected;
+
+  ::std::stringstream actual_ss;
+  actual_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+            << actual;
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   StringStreamToString(&expected_ss),
+                   StringStreamToString(&actual_ss),
+                   false);
+}
+
+// Helper function for implementing ASSERT_NEAR.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1,
+                                                const char* expr2,
+                                                const char* abs_error_expr,
+                                                double val1,
+                                                double val2,
+                                                double abs_error);
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+// A class that enables one to stream messages to assertion macros
+class GTEST_API_ AssertHelper {
+ public:
+  // Constructor.
+  AssertHelper(TestPartResult::Type type,
+               const char* file,
+               int line,
+               const char* message);
+  ~AssertHelper();
+
+  // Message assignment is a semantic trick to enable assertion
+  // streaming; see the GTEST_MESSAGE_ macro below.
+  void operator=(const Message& message) const;
+
+ private:
+  // We put our data in a struct so that the size of the AssertHelper class can
+  // be as small as possible.  This is important because gcc is incapable of
+  // re-using stack space even for temporary variables, so every EXPECT_EQ
+  // reserves stack space for another AssertHelper.
+  struct AssertHelperData {
+    AssertHelperData(TestPartResult::Type t,
+                     const char* srcfile,
+                     int line_num,
+                     const char* msg)
+        : type(t), file(srcfile), line(line_num), message(msg) { }
+
+    TestPartResult::Type const type;
+    const char*        const file;
+    int                const line;
+    String             const message;
+
+   private:
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData);
+  };
+
+  AssertHelperData* const data_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper);
+};
+
+}  // namespace internal
+
+#if GTEST_HAS_PARAM_TEST
+// The pure interface class that all value-parameterized tests inherit from.
+// A value-parameterized class must inherit from both ::testing::Test and
+// ::testing::WithParamInterface. In most cases that just means inheriting
+// from ::testing::TestWithParam, but more complicated test hierarchies
+// may need to inherit from Test and WithParamInterface at different levels.
+//
+// This interface has support for accessing the test parameter value via
+// the GetParam() method.
+//
+// Use it with one of the parameter generator defining functions, like Range(),
+// Values(), ValuesIn(), Bool(), and Combine().
+//
+// class FooTest : public ::testing::TestWithParam<int> {
+//  protected:
+//   FooTest() {
+//     // Can use GetParam() here.
+//   }
+//   virtual ~FooTest() {
+//     // Can use GetParam() here.
+//   }
+//   virtual void SetUp() {
+//     // Can use GetParam() here.
+//   }
+//   virtual void TearDown {
+//     // Can use GetParam() here.
+//   }
+// };
+// TEST_P(FooTest, DoesBar) {
+//   // Can use GetParam() method here.
+//   Foo foo;
+//   ASSERT_TRUE(foo.DoesBar(GetParam()));
+// }
+// INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10));
+
+template <typename T>
+class WithParamInterface {
+ public:
+  typedef T ParamType;
+  virtual ~WithParamInterface() {}
+
+  // The current parameter value. Is also available in the test fixture's
+  // constructor. This member function is non-static, even though it only
+  // references static data, to reduce the opportunity for incorrect uses
+  // like writing 'WithParamInterface<bool>::GetParam()' for a test that
+  // uses a fixture whose parameter type is int.
+  const ParamType& GetParam() const { return *parameter_; }
+
+ private:
+  // Sets parameter value. The caller is responsible for making sure the value
+  // remains alive and unchanged throughout the current test.
+  static void SetParam(const ParamType* parameter) {
+    parameter_ = parameter;
+  }
+
+  // Static value used for accessing parameter during a test lifetime.
+  static const ParamType* parameter_;
+
+  // TestClass must be a subclass of WithParamInterface<T> and Test.
+  template <class TestClass> friend class internal::ParameterizedTestFactory;
+};
+
+template <typename T>
+const T* WithParamInterface<T>::parameter_ = NULL;
+
+// Most value-parameterized classes can ignore the existence of
+// WithParamInterface, and can just inherit from ::testing::TestWithParam.
+
+template <typename T>
+class TestWithParam : public Test, public WithParamInterface<T> {
+};
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+// Macros for indicating success/failure in test code.
+
+// ADD_FAILURE unconditionally adds a failure to the current test.
+// SUCCEED generates a success - it doesn't automatically make the
+// current test successful, as a test is only successful when it has
+// no failure.
+//
+// EXPECT_* verifies that a certain condition is satisfied.  If not,
+// it behaves like ADD_FAILURE.  In particular:
+//
+//   EXPECT_TRUE  verifies that a Boolean condition is true.
+//   EXPECT_FALSE verifies that a Boolean condition is false.
+//
+// FAIL and ASSERT_* are similar to ADD_FAILURE and EXPECT_*, except
+// that they will also abort the current function on failure.  People
+// usually want the fail-fast behavior of FAIL and ASSERT_*, but those
+// writing data-driven tests often find themselves using ADD_FAILURE
+// and EXPECT_* more.
+//
+// Examples:
+//
+//   EXPECT_TRUE(server.StatusIsOK());
+//   ASSERT_FALSE(server.HasPendingRequest(port))
+//       << "There are still pending requests " << "on port " << port;
+
+// Generates a nonfatal failure with a generic message.
+#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed")
+
+// Generates a nonfatal failure at the given source file location with
+// a generic message.
+#define ADD_FAILURE_AT(file, line) \
+  GTEST_MESSAGE_AT_(file, line, "Failed", \
+                    ::testing::TestPartResult::kNonFatalFailure)
+
+// Generates a fatal failure with a generic message.
+#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed")
+
+// Define this macro to 1 to omit the definition of FAIL(), which is a
+// generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_FAIL
+# define FAIL() GTEST_FAIL()
+#endif
+
+// Generates a success with a generic message.
+#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded")
+
+// Define this macro to 1 to omit the definition of SUCCEED(), which
+// is a generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_SUCCEED
+# define SUCCEED() GTEST_SUCCEED()
+#endif
+
+// Macros for testing exceptions.
+//
+//    * {ASSERT|EXPECT}_THROW(statement, expected_exception):
+//         Tests that the statement throws the expected exception.
+//    * {ASSERT|EXPECT}_NO_THROW(statement):
+//         Tests that the statement doesn't throw any exception.
+//    * {ASSERT|EXPECT}_ANY_THROW(statement):
+//         Tests that the statement throws an exception.
+
+#define EXPECT_THROW(statement, expected_exception) \
+  GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_NO_THROW(statement) \
+  GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_ANY_THROW(statement) \
+  GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_THROW(statement, expected_exception) \
+  GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_)
+#define ASSERT_NO_THROW(statement) \
+  GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_)
+#define ASSERT_ANY_THROW(statement) \
+  GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_)
+
+// Boolean assertions. Condition can be either a Boolean expression or an
+// AssertionResult. For more information on how to use AssertionResult with
+// these macros see comments on that class.
+#define EXPECT_TRUE(condition) \
+  GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
+                      GTEST_NONFATAL_FAILURE_)
+#define EXPECT_FALSE(condition) \
+  GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+                      GTEST_NONFATAL_FAILURE_)
+#define ASSERT_TRUE(condition) \
+  GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
+                      GTEST_FATAL_FAILURE_)
+#define ASSERT_FALSE(condition) \
+  GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+                      GTEST_FATAL_FAILURE_)
+
+// Includes the auto-generated header that implements a family of
+// generic predicate assertion macros.
+#include "gtest/gtest_pred_impl.h"
+
+// Macros for testing equalities and inequalities.
+//
+//    * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual
+//    * {ASSERT|EXPECT}_NE(v1, v2):           Tests that v1 != v2
+//    * {ASSERT|EXPECT}_LT(v1, v2):           Tests that v1 < v2
+//    * {ASSERT|EXPECT}_LE(v1, v2):           Tests that v1 <= v2
+//    * {ASSERT|EXPECT}_GT(v1, v2):           Tests that v1 > v2
+//    * {ASSERT|EXPECT}_GE(v1, v2):           Tests that v1 >= v2
+//
+// When they are not, Google Test prints both the tested expressions and
+// their actual values.  The values must be compatible built-in types,
+// or you will get a compiler error.  By "compatible" we mean that the
+// values can be compared by the respective operator.
+//
+// Note:
+//
+//   1. It is possible to make a user-defined type work with
+//   {ASSERT|EXPECT}_??(), but that requires overloading the
+//   comparison operators and is thus discouraged by the Google C++
+//   Usage Guide.  Therefore, you are advised to use the
+//   {ASSERT|EXPECT}_TRUE() macro to assert that two objects are
+//   equal.
+//
+//   2. The {ASSERT|EXPECT}_??() macros do pointer comparisons on
+//   pointers (in particular, C strings).  Therefore, if you use it
+//   with two C strings, you are testing how their locations in memory
+//   are related, not how their content is related.  To compare two C
+//   strings by content, use {ASSERT|EXPECT}_STR*().
+//
+//   3. {ASSERT|EXPECT}_EQ(expected, actual) is preferred to
+//   {ASSERT|EXPECT}_TRUE(expected == actual), as the former tells you
+//   what the actual value is when it fails, and similarly for the
+//   other comparisons.
+//
+//   4. Do not depend on the order in which {ASSERT|EXPECT}_??()
+//   evaluate their arguments, which is undefined.
+//
+//   5. These macros evaluate their arguments exactly once.
+//
+// Examples:
+//
+//   EXPECT_NE(5, Foo());
+//   EXPECT_EQ(NULL, a_pointer);
+//   ASSERT_LT(i, array_size);
+//   ASSERT_GT(records.size(), 0) << "There is no record left.";
+
+#define EXPECT_EQ(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal:: \
+                      EqHelper<GTEST_IS_NULL_LITERAL_(expected)>::Compare, \
+                      expected, actual)
+#define EXPECT_NE(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, expected, actual)
+#define EXPECT_LE(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
+#define EXPECT_LT(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
+#define EXPECT_GE(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
+#define EXPECT_GT(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+
+#define GTEST_ASSERT_EQ(expected, actual) \
+  ASSERT_PRED_FORMAT2(::testing::internal:: \
+                      EqHelper<GTEST_IS_NULL_LITERAL_(expected)>::Compare, \
+                      expected, actual)
+#define GTEST_ASSERT_NE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2)
+#define GTEST_ASSERT_LE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
+#define GTEST_ASSERT_LT(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
+#define GTEST_ASSERT_GE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
+#define GTEST_ASSERT_GT(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+
+// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of
+// ASSERT_XY(), which clashes with some users' own code.
+
+#if !GTEST_DONT_DEFINE_ASSERT_EQ
+# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_NE
+# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LE
+# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LT
+# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GE
+# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GT
+# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2)
+#endif
+
+// C String Comparisons.  All tests treat NULL and any non-NULL string
+// as different.  Two NULLs are equal.
+//
+//    * {ASSERT|EXPECT}_STREQ(s1, s2):     Tests that s1 == s2
+//    * {ASSERT|EXPECT}_STRNE(s1, s2):     Tests that s1 != s2
+//    * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case
+//    * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case
+//
+// For wide or narrow string objects, you can use the
+// {ASSERT|EXPECT}_??() macros.
+//
+// Don't depend on the order in which the arguments are evaluated,
+// which is undefined.
+//
+// These macros evaluate their arguments exactly once.
+
+#define EXPECT_STREQ(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual)
+#define EXPECT_STRNE(s1, s2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
+#define EXPECT_STRCASEEQ(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual)
+#define EXPECT_STRCASENE(s1, s2)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
+
+#define ASSERT_STREQ(expected, actual) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual)
+#define ASSERT_STRNE(s1, s2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
+#define ASSERT_STRCASEEQ(expected, actual) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual)
+#define ASSERT_STRCASENE(s1, s2)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
+
+// Macros for comparing floating-point numbers.
+//
+//    * {ASSERT|EXPECT}_FLOAT_EQ(expected, actual):
+//         Tests that two float values are almost equal.
+//    * {ASSERT|EXPECT}_DOUBLE_EQ(expected, actual):
+//         Tests that two double values are almost equal.
+//    * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error):
+//         Tests that v1 and v2 are within the given distance to each other.
+//
+// Google Test uses ULP-based comparison to automatically pick a default
+// error bound that is appropriate for the operands.  See the
+// FloatingPoint template class in gtest-internal.h if you are
+// interested in the implementation details.
+
+#define EXPECT_FLOAT_EQ(expected, actual)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
+                      expected, actual)
+
+#define EXPECT_DOUBLE_EQ(expected, actual)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
+                      expected, actual)
+
+#define ASSERT_FLOAT_EQ(expected, actual)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
+                      expected, actual)
+
+#define ASSERT_DOUBLE_EQ(expected, actual)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
+                      expected, actual)
+
+#define EXPECT_NEAR(val1, val2, abs_error)\
+  EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
+                      val1, val2, abs_error)
+
+#define ASSERT_NEAR(val1, val2, abs_error)\
+  ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
+                      val1, val2, abs_error)
+
+// These predicate format functions work on floating-point values, and
+// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g.
+//
+//   EXPECT_PRED_FORMAT2(testing::DoubleLE, Foo(), 5.0);
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2,
+                                   float val1, float val2);
+GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
+                                    double val1, double val2);
+
+
+#if GTEST_OS_WINDOWS
+
+// Macros that test for HRESULT failure and success, these are only useful
+// on Windows, and rely on Windows SDK macros and APIs to compile.
+//
+//    * {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}(expr)
+//
+// When expr unexpectedly fails or succeeds, Google Test prints the
+// expected result and the actual result with both a human-readable
+// string representation of the error, if available, as well as the
+// hex result code.
+# define EXPECT_HRESULT_SUCCEEDED(expr) \
+    EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
+
+# define ASSERT_HRESULT_SUCCEEDED(expr) \
+    ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
+
+# define EXPECT_HRESULT_FAILED(expr) \
+    EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
+
+# define ASSERT_HRESULT_FAILED(expr) \
+    ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
+
+#endif  // GTEST_OS_WINDOWS
+
+// Macros that execute statement and check that it doesn't generate new fatal
+// failures in the current thread.
+//
+//   * {ASSERT|EXPECT}_NO_FATAL_FAILURE(statement);
+//
+// Examples:
+//
+//   EXPECT_NO_FATAL_FAILURE(Process());
+//   ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed";
+//
+#define ASSERT_NO_FATAL_FAILURE(statement) \
+    GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_)
+#define EXPECT_NO_FATAL_FAILURE(statement) \
+    GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_)
+
+// Causes a trace (including the source file path, the current line
+// number, and the given message) to be included in every test failure
+// message generated by code in the current scope.  The effect is
+// undone when the control leaves the current scope.
+//
+// The message argument can be anything streamable to std::ostream.
+//
+// In the implementation, we include the current line number as part
+// of the dummy variable name, thus allowing multiple SCOPED_TRACE()s
+// to appear in the same block - as long as they are on different
+// lines.
+#define SCOPED_TRACE(message) \
+  ::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\
+    __FILE__, __LINE__, ::testing::Message() << (message))
+
+// Compile-time assertion for type equality.
+// StaticAssertTypeEq<type1, type2>() compiles iff type1 and type2 are
+// the same type.  The value it returns is not interesting.
+//
+// Instead of making StaticAssertTypeEq a class template, we make it a
+// function template that invokes a helper class template.  This
+// prevents a user from misusing StaticAssertTypeEq<T1, T2> by
+// defining objects of that type.
+//
+// CAVEAT:
+//
+// When used inside a method of a class template,
+// StaticAssertTypeEq<T1, T2>() is effective ONLY IF the method is
+// instantiated.  For example, given:
+//
+//   template <typename T> class Foo {
+//    public:
+//     void Bar() { testing::StaticAssertTypeEq<int, T>(); }
+//   };
+//
+// the code:
+//
+//   void Test1() { Foo<bool> foo; }
+//
+// will NOT generate a compiler error, as Foo<bool>::Bar() is never
+// actually instantiated.  Instead, you need:
+//
+//   void Test2() { Foo<bool> foo; foo.Bar(); }
+//
+// to cause a compiler error.
+template <typename T1, typename T2>
+bool StaticAssertTypeEq() {
+  (void)internal::StaticAssertTypeEqHelper<T1, T2>();
+  return true;
+}
+
+// Defines a test.
+//
+// The first parameter is the name of the test case, and the second
+// parameter is the name of the test within the test case.
+//
+// The convention is to end the test case name with "Test".  For
+// example, a test case for the Foo class can be named FooTest.
+//
+// The user should put his test code between braces after using this
+// macro.  Example:
+//
+//   TEST(FooTest, InitializesCorrectly) {
+//     Foo foo;
+//     EXPECT_TRUE(foo.StatusIsOK());
+//   }
+
+// Note that we call GetTestTypeId() instead of GetTypeId<
+// ::testing::Test>() here to get the type ID of testing::Test.  This
+// is to work around a suspected linker bug when using Google Test as
+// a framework on Mac OS X.  The bug causes GetTypeId<
+// ::testing::Test>() to return different values depending on whether
+// the call is from the Google Test framework itself or from user test
+// code.  GetTestTypeId() is guaranteed to always return the same
+// value, as it always calls GetTypeId<>() from the Google Test
+// framework.
+#define GTEST_TEST(test_case_name, test_name)\
+  GTEST_TEST_(test_case_name, test_name, \
+              ::testing::Test, ::testing::internal::GetTestTypeId())
+
+// Define this macro to 1 to omit the definition of TEST(), which
+// is a generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_TEST
+# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name)
+#endif
+
+// Defines a test that uses a test fixture.
+//
+// The first parameter is the name of the test fixture class, which
+// also doubles as the test case name.  The second parameter is the
+// name of the test within the test case.
+//
+// A test fixture class must be declared earlier.  The user should put
+// his test code between braces after using this macro.  Example:
+//
+//   class FooTest : public testing::Test {
+//    protected:
+//     virtual void SetUp() { b_.AddElement(3); }
+//
+//     Foo a_;
+//     Foo b_;
+//   };
+//
+//   TEST_F(FooTest, InitializesCorrectly) {
+//     EXPECT_TRUE(a_.StatusIsOK());
+//   }
+//
+//   TEST_F(FooTest, ReturnsElementCountCorrectly) {
+//     EXPECT_EQ(0, a_.size());
+//     EXPECT_EQ(1, b_.size());
+//   }
+
+#define TEST_F(test_fixture, test_name)\
+  GTEST_TEST_(test_fixture, test_name, test_fixture, \
+              ::testing::internal::GetTypeId<test_fixture>())
+
+// Use this macro in main() to run all tests.  It returns 0 if all
+// tests are successful, or 1 otherwise.
+//
+// RUN_ALL_TESTS() should be invoked after the command line has been
+// parsed by InitGoogleTest().
+
+#define RUN_ALL_TESTS()\
+  (::testing::UnitTest::GetInstance()->Run())
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_H_
diff --git a/third_party/googletest/src/include/gtest/gtest_pred_impl.h b/third_party/googletest/src/include/gtest/gtest_pred_impl.h
new file mode 100644 (file)
index 0000000..3805f85
--- /dev/null
@@ -0,0 +1,358 @@
+// Copyright 2006, 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.
+
+// This file is AUTOMATICALLY GENERATED on 09/24/2010 by command
+// 'gen_gtest_pred_impl.py 5'.  DO NOT EDIT BY HAND!
+//
+// Implements a family of generic predicate assertion macros.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+
+// Makes sure this header is not included before gtest.h.
+#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
+# error Do not include gtest_pred_impl.h directly.  Include gtest.h instead.
+#endif  // GTEST_INCLUDE_GTEST_GTEST_H_
+
+// This header implements a family of generic predicate assertion
+// macros:
+//
+//   ASSERT_PRED_FORMAT1(pred_format, v1)
+//   ASSERT_PRED_FORMAT2(pred_format, v1, v2)
+//   ...
+//
+// where pred_format is a function or functor that takes n (in the
+// case of ASSERT_PRED_FORMATn) values and their source expression
+// text, and returns a testing::AssertionResult.  See the definition
+// of ASSERT_EQ in gtest.h for an example.
+//
+// If you don't care about formatting, you can use the more
+// restrictive version:
+//
+//   ASSERT_PRED1(pred, v1)
+//   ASSERT_PRED2(pred, v1, v2)
+//   ...
+//
+// where pred is an n-ary function or functor that returns bool,
+// and the values v1, v2, ..., must support the << operator for
+// streaming to std::ostream.
+//
+// We also define the EXPECT_* variations.
+//
+// For now we only support predicates whose arity is at most 5.
+// Please email googletestframework@googlegroups.com if you need
+// support for higher arities.
+
+// GTEST_ASSERT_ is the basic statement to which all of the assertions
+// in this file reduce.  Don't use this in your code.
+
+#define GTEST_ASSERT_(expression, on_failure) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (const ::testing::AssertionResult gtest_ar = (expression)) \
+    ; \
+  else \
+    on_failure(gtest_ar.failure_message())
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED1.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1>
+AssertionResult AssertPred1Helper(const char* pred_text,
+                                  const char* e1,
+                                  Pred pred,
+                                  const T1& v1) {
+  if (pred(v1)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, v1),\
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED1.  Don't use
+// this in your code.
+#define GTEST_PRED1_(pred, v1, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \
+                                             #v1, \
+                                             pred, \
+                                             v1), on_failure)
+
+// Unary predicate assertion macros.
+#define EXPECT_PRED_FORMAT1(pred_format, v1) \
+  GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED1(pred, v1) \
+  GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT1(pred_format, v1) \
+  GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED1(pred, v1) \
+  GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED2.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2>
+AssertionResult AssertPred2Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2) {
+  if (pred(v1, v2)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2),\
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED2.  Don't use
+// this in your code.
+#define GTEST_PRED2_(pred, v1, v2, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             pred, \
+                                             v1, \
+                                             v2), on_failure)
+
+// Binary predicate assertion macros.
+#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
+  GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED2(pred, v1, v2) \
+  GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \
+  GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED2(pred, v1, v2) \
+  GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED3.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3>
+AssertionResult AssertPred3Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3) {
+  if (pred(v1, v2, v3)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ", "
+                            << e3 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2
+                            << "\n" << e3 << " evaluates to " << v3;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3),\
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED3.  Don't use
+// this in your code.
+#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3), on_failure)
+
+// Ternary predicate assertion macros.
+#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \
+  GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED3(pred, v1, v2, v3) \
+  GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \
+  GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED3(pred, v1, v2, v3) \
+  GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED4.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3,
+          typename T4>
+AssertionResult AssertPred4Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  const char* e4,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3,
+                                  const T4& v4) {
+  if (pred(v1, v2, v3, v4)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ", "
+                            << e3 << ", "
+                            << e4 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2
+                            << "\n" << e3 << " evaluates to " << v3
+                            << "\n" << e4 << " evaluates to " << v4;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4),\
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED4.  Don't use
+// this in your code.
+#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             #v4, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3, \
+                                             v4), on_failure)
+
+// 4-ary predicate assertion macros.
+#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
+  GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED4(pred, v1, v2, v3, v4) \
+  GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
+  GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED4(pred, v1, v2, v3, v4) \
+  GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED5.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3,
+          typename T4,
+          typename T5>
+AssertionResult AssertPred5Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  const char* e4,
+                                  const char* e5,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3,
+                                  const T4& v4,
+                                  const T5& v5) {
+  if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ", "
+                            << e3 << ", "
+                            << e4 << ", "
+                            << e5 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2
+                            << "\n" << e3 << " evaluates to " << v3
+                            << "\n" << e4 << " evaluates to " << v4
+                            << "\n" << e5 << " evaluates to " << v5;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5),\
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED5.  Don't use
+// this in your code.
+#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             #v4, \
+                                             #v5, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3, \
+                                             v4, \
+                                             v5), on_failure)
+
+// 5-ary predicate assertion macros.
+#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
+  GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \
+  GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
+  GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \
+  GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
+
+
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
diff --git a/third_party/googletest/src/include/gtest/gtest_prod.h b/third_party/googletest/src/include/gtest/gtest_prod.h
new file mode 100644 (file)
index 0000000..da80ddc
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright 2006, 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: wan@google.com (Zhanyong Wan)
+//
+// Google C++ Testing Framework definitions useful in production code.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_
+
+// When you need to test the private or protected members of a class,
+// use the FRIEND_TEST macro to declare your tests as friends of the
+// class.  For example:
+//
+// class MyClass {
+//  private:
+//   void MyMethod();
+//   FRIEND_TEST(MyClassTest, MyMethod);
+// };
+//
+// class MyClassTest : public testing::Test {
+//   // ...
+// };
+//
+// TEST_F(MyClassTest, MyMethod) {
+//   // Can call MyClass::MyMethod() here.
+// }
+
+#define FRIEND_TEST(test_case_name, test_name)\
+friend class test_case_name##_##test_name##_Test
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PROD_H_
diff --git a/third_party/googletest/src/include/gtest/internal/gtest-death-test-internal.h b/third_party/googletest/src/include/gtest/internal/gtest-death-test-internal.h
new file mode 100644 (file)
index 0000000..1d9f83b
--- /dev/null
@@ -0,0 +1,308 @@
+// Copyright 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.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines internal utilities needed for implementing
+// death tests.  They are subject to change without notice.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+
+#include "gtest/internal/gtest-internal.h"
+
+#include <stdio.h>
+
+namespace testing {
+namespace internal {
+
+GTEST_DECLARE_string_(internal_run_death_test);
+
+// Names of the flags (needed for parsing Google Test flags).
+const char kDeathTestStyleFlag[] = "death_test_style";
+const char kDeathTestUseFork[] = "death_test_use_fork";
+const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
+
+#if GTEST_HAS_DEATH_TEST
+
+// DeathTest is a class that hides much of the complexity of the
+// GTEST_DEATH_TEST_ macro.  It is abstract; its static Create method
+// returns a concrete class that depends on the prevailing death test
+// style, as defined by the --gtest_death_test_style and/or
+// --gtest_internal_run_death_test flags.
+
+// In describing the results of death tests, these terms are used with
+// the corresponding definitions:
+//
+// exit status:  The integer exit information in the format specified
+//               by wait(2)
+// exit code:    The integer code passed to exit(3), _exit(2), or
+//               returned from main()
+class GTEST_API_ DeathTest {
+ public:
+  // Create returns false if there was an error determining the
+  // appropriate action to take for the current death test; for example,
+  // if the gtest_death_test_style flag is set to an invalid value.
+  // The LastMessage method will return a more detailed message in that
+  // case.  Otherwise, the DeathTest pointer pointed to by the "test"
+  // argument is set.  If the death test should be skipped, the pointer
+  // is set to NULL; otherwise, it is set to the address of a new concrete
+  // DeathTest object that controls the execution of the current test.
+  static bool Create(const char* statement, const RE* regex,
+                     const char* file, int line, DeathTest** test);
+  DeathTest();
+  virtual ~DeathTest() { }
+
+  // A helper class that aborts a death test when it's deleted.
+  class ReturnSentinel {
+   public:
+    explicit ReturnSentinel(DeathTest* test) : test_(test) { }
+    ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); }
+   private:
+    DeathTest* const test_;
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel);
+  } GTEST_ATTRIBUTE_UNUSED_;
+
+  // An enumeration of possible roles that may be taken when a death
+  // test is encountered.  EXECUTE means that the death test logic should
+  // be executed immediately.  OVERSEE means that the program should prepare
+  // the appropriate environment for a child process to execute the death
+  // test, then wait for it to complete.
+  enum TestRole { OVERSEE_TEST, EXECUTE_TEST };
+
+  // An enumeration of the three reasons that a test might be aborted.
+  enum AbortReason {
+    TEST_ENCOUNTERED_RETURN_STATEMENT,
+    TEST_THREW_EXCEPTION,
+    TEST_DID_NOT_DIE
+  };
+
+  // Assumes one of the above roles.
+  virtual TestRole AssumeRole() = 0;
+
+  // Waits for the death test to finish and returns its status.
+  virtual int Wait() = 0;
+
+  // Returns true if the death test passed; that is, the test process
+  // exited during the test, its exit status matches a user-supplied
+  // predicate, and its stderr output matches a user-supplied regular
+  // expression.
+  // The user-supplied predicate may be a macro expression rather
+  // than a function pointer or functor, or else Wait and Passed could
+  // be combined.
+  virtual bool Passed(bool exit_status_ok) = 0;
+
+  // Signals that the death test did not die as expected.
+  virtual void Abort(AbortReason reason) = 0;
+
+  // Returns a human-readable outcome message regarding the outcome of
+  // the last death test.
+  static const char* LastMessage();
+
+  static void set_last_death_test_message(const String& message);
+
+ private:
+  // A string containing a description of the outcome of the last death test.
+  static String last_death_test_message_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest);
+};
+
+// Factory interface for death tests.  May be mocked out for testing.
+class DeathTestFactory {
+ public:
+  virtual ~DeathTestFactory() { }
+  virtual bool Create(const char* statement, const RE* regex,
+                      const char* file, int line, DeathTest** test) = 0;
+};
+
+// A concrete DeathTestFactory implementation for normal use.
+class DefaultDeathTestFactory : public DeathTestFactory {
+ public:
+  virtual bool Create(const char* statement, const RE* regex,
+                      const char* file, int line, DeathTest** test);
+};
+
+// Returns true if exit_status describes a process that was terminated
+// by a signal, or exited normally with a nonzero exit code.
+GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
+
+// Traps C++ exceptions escaping statement and reports them as test
+// failures. Note that trapping SEH exceptions is not implemented here.
+# if GTEST_HAS_EXCEPTIONS
+#  define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+  try { \
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+  } catch (const ::std::exception& gtest_exception) { \
+    fprintf(\
+        stderr, \
+        "\n%s: Caught std::exception-derived exception escaping the " \
+        "death test statement. Exception message: %s\n", \
+        ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \
+        gtest_exception.what()); \
+    fflush(stderr); \
+    death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+  } catch (...) { \
+    death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+  }
+
+# else
+#  define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+  GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+
+# endif
+
+// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
+// ASSERT_EXIT*, and EXPECT_EXIT*.
+# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    const ::testing::internal::RE& gtest_regex = (regex); \
+    ::testing::internal::DeathTest* gtest_dt; \
+    if (!::testing::internal::DeathTest::Create(#statement, &gtest_regex, \
+        __FILE__, __LINE__, &gtest_dt)) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
+    } \
+    if (gtest_dt != NULL) { \
+      ::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \
+          gtest_dt_ptr(gtest_dt); \
+      switch (gtest_dt->AssumeRole()) { \
+        case ::testing::internal::DeathTest::OVERSEE_TEST: \
+          if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \
+            goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
+          } \
+          break; \
+        case ::testing::internal::DeathTest::EXECUTE_TEST: { \
+          ::testing::internal::DeathTest::ReturnSentinel \
+              gtest_sentinel(gtest_dt); \
+          GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
+          gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
+          break; \
+        } \
+        default: \
+          break; \
+      } \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \
+      fail(::testing::internal::DeathTest::LastMessage())
+// The symbol "fail" here expands to something into which a message
+// can be streamed.
+
+// A class representing the parsed contents of the
+// --gtest_internal_run_death_test flag, as it existed when
+// RUN_ALL_TESTS was called.
+class InternalRunDeathTestFlag {
+ public:
+  InternalRunDeathTestFlag(const String& a_file,
+                           int a_line,
+                           int an_index,
+                           int a_write_fd)
+      : file_(a_file), line_(a_line), index_(an_index),
+        write_fd_(a_write_fd) {}
+
+  ~InternalRunDeathTestFlag() {
+    if (write_fd_ >= 0)
+      posix::Close(write_fd_);
+  }
+
+  String file() const { return file_; }
+  int line() const { return line_; }
+  int index() const { return index_; }
+  int write_fd() const { return write_fd_; }
+
+ private:
+  String file_;
+  int line_;
+  int index_;
+  int write_fd_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag);
+};
+
+// Returns a newly created InternalRunDeathTestFlag object with fields
+// initialized from the GTEST_FLAG(internal_run_death_test) flag if
+// the flag is specified; otherwise returns NULL.
+InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag();
+
+#else  // GTEST_HAS_DEATH_TEST
+
+// This macro is used for implementing macros such as
+// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where
+// death tests are not supported. Those macros must compile on such systems
+// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on
+// systems that support death tests. This allows one to write such a macro
+// on a system that does not support death tests and be sure that it will
+// compile on a death-test supporting system.
+//
+// Parameters:
+//   statement -  A statement that a macro such as EXPECT_DEATH would test
+//                for program termination. This macro has to make sure this
+//                statement is compiled but not executed, to ensure that
+//                EXPECT_DEATH_IF_SUPPORTED compiles with a certain
+//                parameter iff EXPECT_DEATH compiles with it.
+//   regex     -  A regex that a macro such as EXPECT_DEATH would use to test
+//                the output of statement.  This parameter has to be
+//                compiled but not evaluated by this macro, to ensure that
+//                this macro only accepts expressions that a macro such as
+//                EXPECT_DEATH would accept.
+//   terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED
+//                and a return statement for ASSERT_DEATH_IF_SUPPORTED.
+//                This ensures that ASSERT_DEATH_IF_SUPPORTED will not
+//                compile inside functions where ASSERT_DEATH doesn't
+//                compile.
+//
+//  The branch that has an always false condition is used to ensure that
+//  statement and regex are compiled (and thus syntactically correct) but
+//  never executed. The unreachable code macro protects the terminator
+//  statement from generating an 'unreachable code' warning in case
+//  statement unconditionally returns or throws. The Message constructor at
+//  the end allows the syntax of streaming additional messages into the
+//  macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
+# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+    if (::testing::internal::AlwaysTrue()) { \
+      GTEST_LOG_(WARNING) \
+          << "Death tests are not supported on this platform.\n" \
+          << "Statement '" #statement "' cannot be verified."; \
+    } else if (::testing::internal::AlwaysFalse()) { \
+      ::testing::internal::RE::PartialMatch(".*", (regex)); \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+      terminator; \
+    } else \
+      ::testing::Message()
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
diff --git a/third_party/googletest/src/include/gtest/internal/gtest-filepath.h b/third_party/googletest/src/include/gtest/internal/gtest-filepath.h
new file mode 100644 (file)
index 0000000..b36b3cf
--- /dev/null
@@ -0,0 +1,210 @@
+// Copyright 2008, 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: keith.ray@gmail.com (Keith Ray)
+//
+// Google Test filepath utilities
+//
+// This header file declares classes and functions used internally by
+// Google Test.  They are subject to change without notice.
+//
+// This file is #included in <gtest/internal/gtest-internal.h>.
+// Do not include this header file separately!
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+
+#include "gtest/internal/gtest-string.h"
+
+namespace testing {
+namespace internal {
+
+// FilePath - a class for file and directory pathname manipulation which
+// handles platform-specific conventions (like the pathname separator).
+// Used for helper functions for naming files in a directory for xml output.
+// Except for Set methods, all methods are const or static, which provides an
+// "immutable value object" -- useful for peace of mind.
+// A FilePath with a value ending in a path separator ("like/this/") represents
+// a directory, otherwise it is assumed to represent a file. In either case,
+// it may or may not represent an actual file or directory in the file system.
+// Names are NOT checked for syntax correctness -- no checking for illegal
+// characters, malformed paths, etc.
+
+class GTEST_API_ FilePath {
+ public:
+  FilePath() : pathname_("") { }
+  FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { }
+
+  explicit FilePath(const char* pathname) : pathname_(pathname) {
+    Normalize();
+  }
+
+  explicit FilePath(const String& pathname) : pathname_(pathname) {
+    Normalize();
+  }
+
+  FilePath& operator=(const FilePath& rhs) {
+    Set(rhs);
+    return *this;
+  }
+
+  void Set(const FilePath& rhs) {
+    pathname_ = rhs.pathname_;
+  }
+
+  String ToString() const { return pathname_; }
+  const char* c_str() const { return pathname_.c_str(); }
+
+  // Returns the current working directory, or "" if unsuccessful.
+  static FilePath GetCurrentDir();
+
+  // Given directory = "dir", base_name = "test", number = 0,
+  // extension = "xml", returns "dir/test.xml". If number is greater
+  // than zero (e.g., 12), returns "dir/test_12.xml".
+  // On Windows platform, uses \ as the separator rather than /.
+  static FilePath MakeFileName(const FilePath& directory,
+                               const FilePath& base_name,
+                               int number,
+                               const char* extension);
+
+  // Given directory = "dir", relative_path = "test.xml",
+  // returns "dir/test.xml".
+  // On Windows, uses \ as the separator rather than /.
+  static FilePath ConcatPaths(const FilePath& directory,
+                              const FilePath& relative_path);
+
+  // Returns a pathname for a file that does not currently exist. The pathname
+  // will be directory/base_name.extension or
+  // directory/base_name_<number>.extension if directory/base_name.extension
+  // already exists. The number will be incremented until a pathname is found
+  // that does not already exist.
+  // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
+  // There could be a race condition if two or more processes are calling this
+  // function at the same time -- they could both pick the same filename.
+  static FilePath GenerateUniqueFileName(const FilePath& directory,
+                                         const FilePath& base_name,
+                                         const char* extension);
+
+  // Returns true iff the path is NULL or "".
+  bool IsEmpty() const { return c_str() == NULL || *c_str() == '\0'; }
+
+  // If input name has a trailing separator character, removes it and returns
+  // the name, otherwise return the name string unmodified.
+  // On Windows platform, uses \ as the separator, other platforms use /.
+  FilePath RemoveTrailingPathSeparator() const;
+
+  // Returns a copy of the FilePath with the directory part removed.
+  // Example: FilePath("path/to/file").RemoveDirectoryName() returns
+  // FilePath("file"). If there is no directory part ("just_a_file"), it returns
+  // the FilePath unmodified. If there is no file part ("just_a_dir/") it
+  // returns an empty FilePath ("").
+  // On Windows platform, '\' is the path separator, otherwise it is '/'.
+  FilePath RemoveDirectoryName() const;
+
+  // RemoveFileName returns the directory path with the filename removed.
+  // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
+  // If the FilePath is "a_file" or "/a_file", RemoveFileName returns
+  // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
+  // not have a file, like "just/a/dir/", it returns the FilePath unmodified.
+  // On Windows platform, '\' is the path separator, otherwise it is '/'.
+  FilePath RemoveFileName() const;
+
+  // Returns a copy of the FilePath with the case-insensitive extension removed.
+  // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
+  // FilePath("dir/file"). If a case-insensitive extension is not
+  // found, returns a copy of the original FilePath.
+  FilePath RemoveExtension(const char* extension) const;
+
+  // Creates directories so that path exists. Returns true if successful or if
+  // the directories already exist; returns false if unable to create
+  // directories for any reason. Will also return false if the FilePath does
+  // not represent a directory (that is, it doesn't end with a path separator).
+  bool CreateDirectoriesRecursively() const;
+
+  // Create the directory so that path exists. Returns true if successful or
+  // if the directory already exists; returns false if unable to create the
+  // directory for any reason, including if the parent directory does not
+  // exist. Not named "CreateDirectory" because that's a macro on Windows.
+  bool CreateFolder() const;
+
+  // Returns true if FilePath describes something in the file-system,
+  // either a file, directory, or whatever, and that something exists.
+  bool FileOrDirectoryExists() const;
+
+  // Returns true if pathname describes a directory in the file-system
+  // that exists.
+  bool DirectoryExists() const;
+
+  // Returns true if FilePath ends with a path separator, which indicates that
+  // it is intended to represent a directory. Returns false otherwise.
+  // This does NOT check that a directory (or file) actually exists.
+  bool IsDirectory() const;
+
+  // Returns true if pathname describes a root directory. (Windows has one
+  // root directory per disk drive.)
+  bool IsRootDirectory() const;
+
+  // Returns true if pathname describes an absolute path.
+  bool IsAbsolutePath() const;
+
+ private:
+  // Replaces multiple consecutive separators with a single separator.
+  // For example, "bar///foo" becomes "bar/foo". Does not eliminate other
+  // redundancies that might be in a pathname involving "." or "..".
+  //
+  // A pathname with multiple consecutive separators may occur either through
+  // user error or as a result of some scripts or APIs that generate a pathname
+  // with a trailing separator. On other platforms the same API or script
+  // may NOT generate a pathname with a trailing "/". Then elsewhere that
+  // pathname may have another "/" and pathname components added to it,
+  // without checking for the separator already being there.
+  // The script language and operating system may allow paths like "foo//bar"
+  // but some of the functions in FilePath will not handle that correctly. In
+  // particular, RemoveTrailingPathSeparator() only removes one separator, and
+  // it is called in CreateDirectoriesRecursively() assuming that it will change
+  // a pathname from directory syntax (trailing separator) to filename syntax.
+  //
+  // On Windows this method also replaces the alternate path separator '/' with
+  // the primary path separator '\\', so that for example "bar\\/\\foo" becomes
+  // "bar\\foo".
+
+  void Normalize();
+
+  // Returns a pointer to the last occurence of a valid path separator in
+  // the FilePath. On Windows, for example, both '/' and '\' are valid path
+  // separators. Returns NULL if no path separator was found.
+  const char* FindLastPathSeparator() const;
+
+  String pathname_;
+};  // class FilePath
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
diff --git a/third_party/googletest/src/include/gtest/internal/gtest-internal.h b/third_party/googletest/src/include/gtest/internal/gtest-internal.h
new file mode 100644 (file)
index 0000000..7aa1197
--- /dev/null
@@ -0,0 +1,1226 @@
+// Copyright 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.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file declares functions and macros used internally by
+// Google Test.  They are subject to change without notice.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_OS_LINUX
+# include <stdlib.h>
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <unistd.h>
+#endif  // GTEST_OS_LINUX
+
+#include <ctype.h>
+#include <string.h>
+#include <iomanip>
+#include <limits>
+#include <set>
+
+#include "gtest/internal/gtest-string.h"
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/internal/gtest-type-util.h"
+
+// Due to C++ preprocessor weirdness, we need double indirection to
+// concatenate two tokens when one of them is __LINE__.  Writing
+//
+//   foo ## __LINE__
+//
+// will result in the token foo__LINE__, instead of foo followed by
+// the current line number.  For more details, see
+// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6
+#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar)
+#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar
+
+// Google Test defines the testing::Message class to allow construction of
+// test messages via the << operator.  The idea is that anything
+// streamable to std::ostream can be streamed to a testing::Message.
+// This allows a user to use his own types in Google Test assertions by
+// overloading the << operator.
+//
+// util/gtl/stl_logging-inl.h overloads << for STL containers.  These
+// overloads cannot be defined in the std namespace, as that will be
+// undefined behavior.  Therefore, they are defined in the global
+// namespace instead.
+//
+// C++'s symbol lookup rule (i.e. Koenig lookup) says that these
+// overloads are visible in either the std namespace or the global
+// namespace, but not other namespaces, including the testing
+// namespace which Google Test's Message class is in.
+//
+// To allow STL containers (and other types that has a << operator
+// defined in the global namespace) to be used in Google Test assertions,
+// testing::Message must access the custom << operator from the global
+// namespace.  Hence this helper function.
+//
+// Note: Jeffrey Yasskin suggested an alternative fix by "using
+// ::operator<<;" in the definition of Message's operator<<.  That fix
+// doesn't require a helper function, but unfortunately doesn't
+// compile with MSVC.
+template <typename T>
+inline void GTestStreamToHelper(std::ostream* os, const T& val) {
+  *os << val;
+}
+
+class ProtocolMessage;
+namespace proto2 { class Message; }
+
+namespace testing {
+
+// Forward declarations.
+
+class AssertionResult;                 // Result of an assertion.
+class Message;                         // Represents a failure message.
+class Test;                            // Represents a test.
+class TestInfo;                        // Information about a test.
+class TestPartResult;                  // Result of a test part.
+class UnitTest;                        // A collection of test cases.
+
+template <typename T>
+::std::string PrintToString(const T& value);
+
+namespace internal {
+
+struct TraceInfo;                      // Information about a trace point.
+class ScopedTrace;                     // Implements scoped trace.
+class TestInfoImpl;                    // Opaque implementation of TestInfo
+class UnitTestImpl;                    // Opaque implementation of UnitTest
+
+// How many times InitGoogleTest() has been called.
+extern int g_init_gtest_count;
+
+// The text used in failure messages to indicate the start of the
+// stack trace.
+GTEST_API_ extern const char kStackTraceMarker[];
+
+// A secret type that Google Test users don't know about.  It has no
+// definition on purpose.  Therefore it's impossible to create a
+// Secret object, which is what we want.
+class Secret;
+
+// Two overloaded helpers for checking at compile time whether an
+// expression is a null pointer literal (i.e. NULL or any 0-valued
+// compile-time integral constant).  Their return values have
+// different sizes, so we can use sizeof() to test which version is
+// picked by the compiler.  These helpers have no implementations, as
+// we only need their signatures.
+//
+// Given IsNullLiteralHelper(x), the compiler will pick the first
+// version if x can be implicitly converted to Secret*, and pick the
+// second version otherwise.  Since Secret is a secret and incomplete
+// type, the only expression a user can write that has type Secret* is
+// a null pointer literal.  Therefore, we know that x is a null
+// pointer literal if and only if the first version is picked by the
+// compiler.
+char IsNullLiteralHelper(Secret* p);
+char (&IsNullLiteralHelper(...))[2];  // NOLINT
+
+// A compile-time bool constant that is true if and only if x is a
+// null pointer literal (i.e. NULL or any 0-valued compile-time
+// integral constant).
+#ifdef GTEST_ELLIPSIS_NEEDS_POD_
+// We lose support for NULL detection where the compiler doesn't like
+// passing non-POD classes through ellipsis (...).
+# define GTEST_IS_NULL_LITERAL_(x) false
+#else
+# define GTEST_IS_NULL_LITERAL_(x) \
+    (sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1)
+#endif  // GTEST_ELLIPSIS_NEEDS_POD_
+
+// Appends the user-supplied message to the Google-Test-generated message.
+GTEST_API_ String AppendUserMessage(const String& gtest_msg,
+                                    const Message& user_msg);
+
+// A helper class for creating scoped traces in user programs.
+class GTEST_API_ ScopedTrace {
+ public:
+  // The c'tor pushes the given source file location and message onto
+  // a trace stack maintained by Google Test.
+  ScopedTrace(const char* file, int line, const Message& message);
+
+  // The d'tor pops the info pushed by the c'tor.
+  //
+  // Note that the d'tor is not virtual in order to be efficient.
+  // Don't inherit from ScopedTrace!
+  ~ScopedTrace();
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace);
+} GTEST_ATTRIBUTE_UNUSED_;  // A ScopedTrace object does its job in its
+                            // c'tor and d'tor.  Therefore it doesn't
+                            // need to be used otherwise.
+
+// Converts a streamable value to a String.  A NULL pointer is
+// converted to "(null)".  When the input value is a ::string,
+// ::std::string, ::wstring, or ::std::wstring object, each NUL
+// character in it is replaced with "\\0".
+// Declared here but defined in gtest.h, so that it has access
+// to the definition of the Message class, required by the ARM
+// compiler.
+template <typename T>
+String StreamableToString(const T& streamable);
+
+// The Symbian compiler has a bug that prevents it from selecting the
+// correct overload of FormatForComparisonFailureMessage (see below)
+// unless we pass the first argument by reference.  If we do that,
+// however, Visual Age C++ 10.1 generates a compiler error.  Therefore
+// we only apply the work-around for Symbian.
+#if defined(__SYMBIAN32__)
+# define GTEST_CREF_WORKAROUND_ const&
+#else
+# define GTEST_CREF_WORKAROUND_
+#endif
+
+// When this operand is a const char* or char*, if the other operand
+// is a ::std::string or ::string, we print this operand as a C string
+// rather than a pointer (we do the same for wide strings); otherwise
+// we print it as a pointer to be safe.
+
+// This internal macro is used to avoid duplicated code.
+#define GTEST_FORMAT_IMPL_(operand2_type, operand1_printer)\
+inline String FormatForComparisonFailureMessage(\
+    operand2_type::value_type* GTEST_CREF_WORKAROUND_ str, \
+    const operand2_type& /*operand2*/) {\
+  return operand1_printer(str);\
+}\
+inline String FormatForComparisonFailureMessage(\
+    const operand2_type::value_type* GTEST_CREF_WORKAROUND_ str, \
+    const operand2_type& /*operand2*/) {\
+  return operand1_printer(str);\
+}
+
+GTEST_FORMAT_IMPL_(::std::string, String::ShowCStringQuoted)
+#if GTEST_HAS_STD_WSTRING
+GTEST_FORMAT_IMPL_(::std::wstring, String::ShowWideCStringQuoted)
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_STRING
+GTEST_FORMAT_IMPL_(::string, String::ShowCStringQuoted)
+#endif  // GTEST_HAS_GLOBAL_STRING
+#if GTEST_HAS_GLOBAL_WSTRING
+GTEST_FORMAT_IMPL_(::wstring, String::ShowWideCStringQuoted)
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+#undef GTEST_FORMAT_IMPL_
+
+// The next four overloads handle the case where the operand being
+// printed is a char/wchar_t pointer and the other operand is not a
+// string/wstring object.  In such cases, we just print the operand as
+// a pointer to be safe.
+#define GTEST_FORMAT_CHAR_PTR_IMPL_(CharType)                       \
+  template <typename T>                                             \
+  String FormatForComparisonFailureMessage(CharType* GTEST_CREF_WORKAROUND_ p, \
+                                           const T&) { \
+    return PrintToString(static_cast<const void*>(p));              \
+  }
+
+GTEST_FORMAT_CHAR_PTR_IMPL_(char)
+GTEST_FORMAT_CHAR_PTR_IMPL_(const char)
+GTEST_FORMAT_CHAR_PTR_IMPL_(wchar_t)
+GTEST_FORMAT_CHAR_PTR_IMPL_(const wchar_t)
+
+#undef GTEST_FORMAT_CHAR_PTR_IMPL_
+
+// Constructs and returns the message for an equality assertion
+// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
+//
+// The first four parameters are the expressions used in the assertion
+// and their values, as strings.  For example, for ASSERT_EQ(foo, bar)
+// where foo is 5 and bar is 6, we have:
+//
+//   expected_expression: "foo"
+//   actual_expression:   "bar"
+//   expected_value:      "5"
+//   actual_value:        "6"
+//
+// The ignoring_case parameter is true iff the assertion is a
+// *_STRCASEEQ*.  When it's true, the string " (ignoring case)" will
+// be inserted into the message.
+GTEST_API_ AssertionResult EqFailure(const char* expected_expression,
+                                     const char* actual_expression,
+                                     const String& expected_value,
+                                     const String& actual_value,
+                                     bool ignoring_case);
+
+// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
+GTEST_API_ String GetBoolAssertionFailureMessage(
+    const AssertionResult& assertion_result,
+    const char* expression_text,
+    const char* actual_predicate_value,
+    const char* expected_predicate_value);
+
+// This template class represents an IEEE floating-point number
+// (either single-precision or double-precision, depending on the
+// template parameters).
+//
+// The purpose of this class is to do more sophisticated number
+// comparison.  (Due to round-off error, etc, it's very unlikely that
+// two floating-points will be equal exactly.  Hence a naive
+// comparison by the == operation often doesn't work.)
+//
+// Format of IEEE floating-point:
+//
+//   The most-significant bit being the leftmost, an IEEE
+//   floating-point looks like
+//
+//     sign_bit exponent_bits fraction_bits
+//
+//   Here, sign_bit is a single bit that designates the sign of the
+//   number.
+//
+//   For float, there are 8 exponent bits and 23 fraction bits.
+//
+//   For double, there are 11 exponent bits and 52 fraction bits.
+//
+//   More details can be found at
+//   http://en.wikipedia.org/wiki/IEEE_floating-point_standard.
+//
+// Template parameter:
+//
+//   RawType: the raw floating-point type (either float or double)
+template <typename RawType>
+class FloatingPoint {
+ public:
+  // Defines the unsigned integer type that has the same size as the
+  // floating point number.
+  typedef typename TypeWithSize<sizeof(RawType)>::UInt Bits;
+
+  // Constants.
+
+  // # of bits in a number.
+  static const size_t kBitCount = 8*sizeof(RawType);
+
+  // # of fraction bits in a number.
+  static const size_t kFractionBitCount =
+    std::numeric_limits<RawType>::digits - 1;
+
+  // # of exponent bits in a number.
+  static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount;
+
+  // The mask for the sign bit.
+  static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);
+
+  // The mask for the fraction bits.
+  static const Bits kFractionBitMask =
+    ~static_cast<Bits>(0) >> (kExponentBitCount + 1);
+
+  // The mask for the exponent bits.
+  static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask);
+
+  // How many ULP's (Units in the Last Place) we want to tolerate when
+  // comparing two numbers.  The larger the value, the more error we
+  // allow.  A 0 value means that two numbers must be exactly the same
+  // to be considered equal.
+  //
+  // The maximum error of a single floating-point operation is 0.5
+  // units in the last place.  On Intel CPU's, all floating-point
+  // calculations are done with 80-bit precision, while double has 64
+  // bits.  Therefore, 4 should be enough for ordinary use.
+  //
+  // See the following article for more details on ULP:
+  // http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm.
+  static const size_t kMaxUlps = 4;
+
+  // Constructs a FloatingPoint from a raw floating-point number.
+  //
+  // On an Intel CPU, passing a non-normalized NAN (Not a Number)
+  // around may change its bits, although the new value is guaranteed
+  // to be also a NAN.  Therefore, don't expect this constructor to
+  // preserve the bits in x when x is a NAN.
+  explicit FloatingPoint(const RawType& x) { u_.value_ = x; }
+
+  // Static methods
+
+  // Reinterprets a bit pattern as a floating-point number.
+  //
+  // This function is needed to test the AlmostEquals() method.
+  static RawType ReinterpretBits(const Bits bits) {
+    FloatingPoint fp(0);
+    fp.u_.bits_ = bits;
+    return fp.u_.value_;
+  }
+
+  // Returns the floating-point number that represent positive infinity.
+  static RawType Infinity() {
+    return ReinterpretBits(kExponentBitMask);
+  }
+
+  // Non-static methods
+
+  // Returns the bits that represents this number.
+  const Bits &bits() const { return u_.bits_; }
+
+  // Returns the exponent bits of this number.
+  Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }
+
+  // Returns the fraction bits of this number.
+  Bits fraction_bits() const { return kFractionBitMask & u_.bits_; }
+
+  // Returns the sign bit of this number.
+  Bits sign_bit() const { return kSignBitMask & u_.bits_; }
+
+  // Returns true iff this is NAN (not a number).
+  bool is_nan() const {
+    // It's a NAN if the exponent bits are all ones and the fraction
+    // bits are not entirely zeros.
+    return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0);
+  }
+
+  // Returns true iff this number is at most kMaxUlps ULP's away from
+  // rhs.  In particular, this function:
+  //
+  //   - returns false if either number is (or both are) NAN.
+  //   - treats really large numbers as almost equal to infinity.
+  //   - thinks +0.0 and -0.0 are 0 DLP's apart.
+  bool AlmostEquals(const FloatingPoint& rhs) const {
+    // The IEEE standard says that any comparison operation involving
+    // a NAN must return false.
+    if (is_nan() || rhs.is_nan()) return false;
+
+    return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_)
+        <= kMaxUlps;
+  }
+
+ private:
+  // The data type used to store the actual floating-point number.
+  union FloatingPointUnion {
+    RawType value_;  // The raw floating-point number.
+    Bits bits_;      // The bits that represent the number.
+  };
+
+  // Converts an integer from the sign-and-magnitude representation to
+  // the biased representation.  More precisely, let N be 2 to the
+  // power of (kBitCount - 1), an integer x is represented by the
+  // unsigned number x + N.
+  //
+  // For instance,
+  //
+  //   -N + 1 (the most negative number representable using
+  //          sign-and-magnitude) is represented by 1;
+  //   0      is represented by N; and
+  //   N - 1  (the biggest number representable using
+  //          sign-and-magnitude) is represented by 2N - 1.
+  //
+  // Read http://en.wikipedia.org/wiki/Signed_number_representations
+  // for more details on signed number representations.
+  static Bits SignAndMagnitudeToBiased(const Bits &sam) {
+    if (kSignBitMask & sam) {
+      // sam represents a negative number.
+      return ~sam + 1;
+    } else {
+      // sam represents a positive number.
+      return kSignBitMask | sam;
+    }
+  }
+
+  // Given two numbers in the sign-and-magnitude representation,
+  // returns the distance between them as an unsigned number.
+  static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1,
+                                                     const Bits &sam2) {
+    const Bits biased1 = SignAndMagnitudeToBiased(sam1);
+    const Bits biased2 = SignAndMagnitudeToBiased(sam2);
+    return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
+  }
+
+  FloatingPointUnion u_;
+};
+
+// Typedefs the instances of the FloatingPoint template class that we
+// care to use.
+typedef FloatingPoint<float> Float;
+typedef FloatingPoint<double> Double;
+
+// In order to catch the mistake of putting tests that use different
+// test fixture classes in the same test case, we need to assign
+// unique IDs to fixture classes and compare them.  The TypeId type is
+// used to hold such IDs.  The user should treat TypeId as an opaque
+// type: the only operation allowed on TypeId values is to compare
+// them for equality using the == operator.
+typedef const void* TypeId;
+
+template <typename T>
+class TypeIdHelper {
+ public:
+  // dummy_ must not have a const type.  Otherwise an overly eager
+  // compiler (e.g. MSVC 7.1 & 8.0) may try to merge
+  // TypeIdHelper<T>::dummy_ for different Ts as an "optimization".
+  static bool dummy_;
+};
+
+template <typename T>
+bool TypeIdHelper<T>::dummy_ = false;
+
+// GetTypeId<T>() returns the ID of type T.  Different values will be
+// returned for different types.  Calling the function twice with the
+// same type argument is guaranteed to return the same ID.
+template <typename T>
+TypeId GetTypeId() {
+  // The compiler is required to allocate a different
+  // TypeIdHelper<T>::dummy_ variable for each T used to instantiate
+  // the template.  Therefore, the address of dummy_ is guaranteed to
+  // be unique.
+  return &(TypeIdHelper<T>::dummy_);
+}
+
+// Returns the type ID of ::testing::Test.  Always call this instead
+// of GetTypeId< ::testing::Test>() to get the type ID of
+// ::testing::Test, as the latter may give the wrong result due to a
+// suspected linker bug when compiling Google Test as a Mac OS X
+// framework.
+GTEST_API_ TypeId GetTestTypeId();
+
+// Defines the abstract factory interface that creates instances
+// of a Test object.
+class TestFactoryBase {
+ public:
+  virtual ~TestFactoryBase() {}
+
+  // Creates a test instance to run. The instance is both created and destroyed
+  // within TestInfoImpl::Run()
+  virtual Test* CreateTest() = 0;
+
+ protected:
+  TestFactoryBase() {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase);
+};
+
+// This class provides implementation of TeastFactoryBase interface.
+// It is used in TEST and TEST_F macros.
+template <class TestClass>
+class TestFactoryImpl : public TestFactoryBase {
+ public:
+  virtual Test* CreateTest() { return new TestClass; }
+};
+
+#if GTEST_OS_WINDOWS
+
+// Predicate-formatters for implementing the HRESULT checking macros
+// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}
+// We pass a long instead of HRESULT to avoid causing an
+// include dependency for the HRESULT type.
+GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr,
+                                            long hr);  // NOLINT
+GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr,
+                                            long hr);  // NOLINT
+
+#endif  // GTEST_OS_WINDOWS
+
+// Types of SetUpTestCase() and TearDownTestCase() functions.
+typedef void (*SetUpTestCaseFunc)();
+typedef void (*TearDownTestCaseFunc)();
+
+// Creates a new TestInfo object and registers it with Google Test;
+// returns the created object.
+//
+// Arguments:
+//
+//   test_case_name:   name of the test case
+//   name:             name of the test
+//   type_param        the name of the test's type parameter, or NULL if
+//                     this is not  a typed or a type-parameterized test.
+//   value_param       text representation of the test's value parameter,
+//                     or NULL if this is not a type-parameterized test.
+//   fixture_class_id: ID of the test fixture class
+//   set_up_tc:        pointer to the function that sets up the test case
+//   tear_down_tc:     pointer to the function that tears down the test case
+//   factory:          pointer to the factory that creates a test object.
+//                     The newly created TestInfo instance will assume
+//                     ownership of the factory object.
+GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
+    const char* test_case_name, const char* name,
+    const char* type_param,
+    const char* value_param,
+    TypeId fixture_class_id,
+    SetUpTestCaseFunc set_up_tc,
+    TearDownTestCaseFunc tear_down_tc,
+    TestFactoryBase* factory);
+
+// If *pstr starts with the given prefix, modifies *pstr to be right
+// past the prefix and returns true; otherwise leaves *pstr unchanged
+// and returns false.  None of pstr, *pstr, and prefix can be NULL.
+GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr);
+
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// State of the definition of a type-parameterized test case.
+class GTEST_API_ TypedTestCasePState {
+ public:
+  TypedTestCasePState() : registered_(false) {}
+
+  // Adds the given test name to defined_test_names_ and return true
+  // if the test case hasn't been registered; otherwise aborts the
+  // program.
+  bool AddTestName(const char* file, int line, const char* case_name,
+                   const char* test_name) {
+    if (registered_) {
+      fprintf(stderr, "%s Test %s must be defined before "
+              "REGISTER_TYPED_TEST_CASE_P(%s, ...).\n",
+              FormatFileLocation(file, line).c_str(), test_name, case_name);
+      fflush(stderr);
+      posix::Abort();
+    }
+    defined_test_names_.insert(test_name);
+    return true;
+  }
+
+  // Verifies that registered_tests match the test names in
+  // defined_test_names_; returns registered_tests if successful, or
+  // aborts the program otherwise.
+  const char* VerifyRegisteredTestNames(
+      const char* file, int line, const char* registered_tests);
+
+ private:
+  bool registered_;
+  ::std::set<const char*> defined_test_names_;
+};
+
+// Skips to the first non-space char after the first comma in 'str';
+// returns NULL if no comma is found in 'str'.
+inline const char* SkipComma(const char* str) {
+  const char* comma = strchr(str, ',');
+  if (comma == NULL) {
+    return NULL;
+  }
+  while (IsSpace(*(++comma))) {}
+  return comma;
+}
+
+// Returns the prefix of 'str' before the first comma in it; returns
+// the entire string if it contains no comma.
+inline String GetPrefixUntilComma(const char* str) {
+  const char* comma = strchr(str, ',');
+  return comma == NULL ? String(str) : String(str, comma - str);
+}
+
+// TypeParameterizedTest<Fixture, TestSel, Types>::Register()
+// registers a list of type-parameterized tests with Google Test.  The
+// return value is insignificant - we just need to return something
+// such that we can call this function in a namespace scope.
+//
+// Implementation note: The GTEST_TEMPLATE_ macro declares a template
+// template parameter.  It's defined in gtest-type-util.h.
+template <GTEST_TEMPLATE_ Fixture, class TestSel, typename Types>
+class TypeParameterizedTest {
+ public:
+  // 'index' is the index of the test in the type list 'Types'
+  // specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase,
+  // Types).  Valid values for 'index' are [0, N - 1] where N is the
+  // length of Types.
+  static bool Register(const char* prefix, const char* case_name,
+                       const char* test_names, int index) {
+    typedef typename Types::Head Type;
+    typedef Fixture<Type> FixtureClass;
+    typedef typename GTEST_BIND_(TestSel, Type) TestClass;
+
+    // First, registers the first type-parameterized test in the type
+    // list.
+    MakeAndRegisterTestInfo(
+        String::Format("%s%s%s/%d", prefix, prefix[0] == '\0' ? "" : "/",
+                       case_name, index).c_str(),
+        GetPrefixUntilComma(test_names).c_str(),
+        GetTypeName<Type>().c_str(),
+        NULL,  // No value parameter.
+        GetTypeId<FixtureClass>(),
+        TestClass::SetUpTestCase,
+        TestClass::TearDownTestCase,
+        new TestFactoryImpl<TestClass>);
+
+    // Next, recurses (at compile time) with the tail of the type list.
+    return TypeParameterizedTest<Fixture, TestSel, typename Types::Tail>
+        ::Register(prefix, case_name, test_names, index + 1);
+  }
+};
+
+// The base case for the compile time recursion.
+template <GTEST_TEMPLATE_ Fixture, class TestSel>
+class TypeParameterizedTest<Fixture, TestSel, Types0> {
+ public:
+  static bool Register(const char* /*prefix*/, const char* /*case_name*/,
+                       const char* /*test_names*/, int /*index*/) {
+    return true;
+  }
+};
+
+// TypeParameterizedTestCase<Fixture, Tests, Types>::Register()
+// registers *all combinations* of 'Tests' and 'Types' with Google
+// Test.  The return value is insignificant - we just need to return
+// something such that we can call this function in a namespace scope.
+template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types>
+class TypeParameterizedTestCase {
+ public:
+  static bool Register(const char* prefix, const char* case_name,
+                       const char* test_names) {
+    typedef typename Tests::Head Head;
+
+    // First, register the first test in 'Test' for each type in 'Types'.
+    TypeParameterizedTest<Fixture, Head, Types>::Register(
+        prefix, case_name, test_names, 0);
+
+    // Next, recurses (at compile time) with the tail of the test list.
+    return TypeParameterizedTestCase<Fixture, typename Tests::Tail, Types>
+        ::Register(prefix, case_name, SkipComma(test_names));
+  }
+};
+
+// The base case for the compile time recursion.
+template <GTEST_TEMPLATE_ Fixture, typename Types>
+class TypeParameterizedTestCase<Fixture, Templates0, Types> {
+ public:
+  static bool Register(const char* /*prefix*/, const char* /*case_name*/,
+                       const char* /*test_names*/) {
+    return true;
+  }
+};
+
+#endif  // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// Returns the current OS stack trace as a String.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
+// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
+GTEST_API_ String GetCurrentOsStackTraceExceptTop(UnitTest* unit_test,
+                                                  int skip_count);
+
+// Helpers for suppressing warnings on unreachable code or constant
+// condition.
+
+// Always returns true.
+GTEST_API_ bool AlwaysTrue();
+
+// Always returns false.
+inline bool AlwaysFalse() { return !AlwaysTrue(); }
+
+// Helper for suppressing false warning from Clang on a const char*
+// variable declared in a conditional expression always being NULL in
+// the else branch.
+struct GTEST_API_ ConstCharPtr {
+  ConstCharPtr(const char* str) : value(str) {}
+  operator bool() const { return true; }
+  const char* value;
+};
+
+// A simple Linear Congruential Generator for generating random
+// numbers with a uniform distribution.  Unlike rand() and srand(), it
+// doesn't use global state (and therefore can't interfere with user
+// code).  Unlike rand_r(), it's portable.  An LCG isn't very random,
+// but it's good enough for our purposes.
+class GTEST_API_ Random {
+ public:
+  static const UInt32 kMaxRange = 1u << 31;
+
+  explicit Random(UInt32 seed) : state_(seed) {}
+
+  void Reseed(UInt32 seed) { state_ = seed; }
+
+  // Generates a random number from [0, range).  Crashes if 'range' is
+  // 0 or greater than kMaxRange.
+  UInt32 Generate(UInt32 range);
+
+ private:
+  UInt32 state_;
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
+};
+
+// Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a
+// compiler error iff T1 and T2 are different types.
+template <typename T1, typename T2>
+struct CompileAssertTypesEqual;
+
+template <typename T>
+struct CompileAssertTypesEqual<T, T> {
+};
+
+// Removes the reference from a type if it is a reference type,
+// otherwise leaves it unchanged.  This is the same as
+// tr1::remove_reference, which is not widely available yet.
+template <typename T>
+struct RemoveReference { typedef T type; };  // NOLINT
+template <typename T>
+struct RemoveReference<T&> { typedef T type; };  // NOLINT
+
+// A handy wrapper around RemoveReference that works when the argument
+// T depends on template parameters.
+#define GTEST_REMOVE_REFERENCE_(T) \
+    typename ::testing::internal::RemoveReference<T>::type
+
+// Removes const from a type if it is a const type, otherwise leaves
+// it unchanged.  This is the same as tr1::remove_const, which is not
+// widely available yet.
+template <typename T>
+struct RemoveConst { typedef T type; };  // NOLINT
+template <typename T>
+struct RemoveConst<const T> { typedef T type; };  // NOLINT
+
+// MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above
+// definition to fail to remove the const in 'const int[3]' and 'const
+// char[3][4]'.  The following specialization works around the bug.
+// However, it causes trouble with GCC and thus needs to be
+// conditionally compiled.
+#if defined(_MSC_VER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
+template <typename T, size_t N>
+struct RemoveConst<const T[N]> {
+  typedef typename RemoveConst<T>::type type[N];
+};
+#endif
+
+// A handy wrapper around RemoveConst that works when the argument
+// T depends on template parameters.
+#define GTEST_REMOVE_CONST_(T) \
+    typename ::testing::internal::RemoveConst<T>::type
+
+// Turns const U&, U&, const U, and U all into U.
+#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \
+    GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T))
+
+// Adds reference to a type if it is not a reference type,
+// otherwise leaves it unchanged.  This is the same as
+// tr1::add_reference, which is not widely available yet.
+template <typename T>
+struct AddReference { typedef T& type; };  // NOLINT
+template <typename T>
+struct AddReference<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper around AddReference that works when the argument T
+// depends on template parameters.
+#define GTEST_ADD_REFERENCE_(T) \
+    typename ::testing::internal::AddReference<T>::type
+
+// Adds a reference to const on top of T as necessary.  For example,
+// it transforms
+//
+//   char         ==> const char&
+//   const char   ==> const char&
+//   char&        ==> const char&
+//   const char&  ==> const char&
+//
+// The argument T must depend on some template parameters.
+#define GTEST_REFERENCE_TO_CONST_(T) \
+    GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T))
+
+// ImplicitlyConvertible<From, To>::value is a compile-time bool
+// constant that's true iff type From can be implicitly converted to
+// type To.
+template <typename From, typename To>
+class ImplicitlyConvertible {
+ private:
+  // We need the following helper functions only for their types.
+  // They have no implementations.
+
+  // MakeFrom() is an expression whose type is From.  We cannot simply
+  // use From(), as the type From may not have a public default
+  // constructor.
+  static From MakeFrom();
+
+  // These two functions are overloaded.  Given an expression
+  // Helper(x), the compiler will pick the first version if x can be
+  // implicitly converted to type To; otherwise it will pick the
+  // second version.
+  //
+  // The first version returns a value of size 1, and the second
+  // version returns a value of size 2.  Therefore, by checking the
+  // size of Helper(x), which can be done at compile time, we can tell
+  // which version of Helper() is used, and hence whether x can be
+  // implicitly converted to type To.
+  static char Helper(To);
+  static char (&Helper(...))[2];  // NOLINT
+
+  // We have to put the 'public' section after the 'private' section,
+  // or MSVC refuses to compile the code.
+ public:
+  // MSVC warns about implicitly converting from double to int for
+  // possible loss of data, so we need to temporarily disable the
+  // warning.
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4244)  // Temporarily disables warning 4244.
+
+  static const bool value =
+      sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
+# pragma warning(pop)           // Restores the warning state.
+#elif defined(__BORLANDC__)
+  // C++Builder cannot use member overload resolution during template
+  // instantiation.  The simplest workaround is to use its C++0x type traits
+  // functions (C++Builder 2009 and above only).
+  static const bool value = __is_convertible(From, To);
+#else
+  static const bool value =
+      sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
+#endif  // _MSV_VER
+};
+template <typename From, typename To>
+const bool ImplicitlyConvertible<From, To>::value;
+
+// IsAProtocolMessage<T>::value is a compile-time bool constant that's
+// true iff T is type ProtocolMessage, proto2::Message, or a subclass
+// of those.
+template <typename T>
+struct IsAProtocolMessage
+    : public bool_constant<
+  ImplicitlyConvertible<const T*, const ::ProtocolMessage*>::value ||
+  ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> {
+};
+
+// When the compiler sees expression IsContainerTest<C>(0), if C is an
+// STL-style container class, the first overload of IsContainerTest
+// will be viable (since both C::iterator* and C::const_iterator* are
+// valid types and NULL can be implicitly converted to them).  It will
+// be picked over the second overload as 'int' is a perfect match for
+// the type of argument 0.  If C::iterator or C::const_iterator is not
+// a valid type, the first overload is not viable, and the second
+// overload will be picked.  Therefore, we can determine whether C is
+// a container class by checking the type of IsContainerTest<C>(0).
+// The value of the expression is insignificant.
+//
+// Note that we look for both C::iterator and C::const_iterator.  The
+// reason is that C++ injects the name of a class as a member of the
+// class itself (e.g. you can refer to class iterator as either
+// 'iterator' or 'iterator::iterator').  If we look for C::iterator
+// only, for example, we would mistakenly think that a class named
+// iterator is an STL container.
+//
+// Also note that the simpler approach of overloading
+// IsContainerTest(typename C::const_iterator*) and
+// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
+typedef int IsContainer;
+template <class C>
+IsContainer IsContainerTest(int /* dummy */,
+                            typename C::iterator* /* it */ = NULL,
+                            typename C::const_iterator* /* const_it */ = NULL) {
+  return 0;
+}
+
+typedef char IsNotContainer;
+template <class C>
+IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
+
+// EnableIf<condition>::type is void when 'Cond' is true, and
+// undefined when 'Cond' is false.  To use SFINAE to make a function
+// overload only apply when a particular expression is true, add
+// "typename EnableIf<expression>::type* = 0" as the last parameter.
+template<bool> struct EnableIf;
+template<> struct EnableIf<true> { typedef void type; };  // NOLINT
+
+// Utilities for native arrays.
+
+// ArrayEq() compares two k-dimensional native arrays using the
+// elements' operator==, where k can be any integer >= 0.  When k is
+// 0, ArrayEq() degenerates into comparing a single pair of values.
+
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
+  return internal::ArrayEq(lhs, N, rhs);
+}
+
+// This helper reduces code bloat.  If we instead put its logic inside
+// the previous ArrayEq() function, arrays with different sizes would
+// lead to different copies of the template code.
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
+  for (size_t i = 0; i != size; i++) {
+    if (!internal::ArrayEq(lhs[i], rhs[i]))
+      return false;
+  }
+  return true;
+}
+
+// Finds the first element in the iterator range [begin, end) that
+// equals elem.  Element may be a native array type itself.
+template <typename Iter, typename Element>
+Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
+  for (Iter it = begin; it != end; ++it) {
+    if (internal::ArrayEq(*it, elem))
+      return it;
+  }
+  return end;
+}
+
+// CopyArray() copies a k-dimensional native array using the elements'
+// operator=, where k can be any integer >= 0.  When k is 0,
+// CopyArray() degenerates into copying a single value.
+
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline void CopyArray(const T& from, U* to) { *to = from; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline void CopyArray(const T(&from)[N], U(*to)[N]) {
+  internal::CopyArray(from, N, *to);
+}
+
+// This helper reduces code bloat.  If we instead put its logic inside
+// the previous CopyArray() function, arrays with different sizes
+// would lead to different copies of the template code.
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to) {
+  for (size_t i = 0; i != size; i++) {
+    internal::CopyArray(from[i], to + i);
+  }
+}
+
+// The relation between an NativeArray object (see below) and the
+// native array it represents.
+enum RelationToSource {
+  kReference,  // The NativeArray references the native array.
+  kCopy        // The NativeArray makes a copy of the native array and
+               // owns the copy.
+};
+
+// Adapts a native array to a read-only STL-style container.  Instead
+// of the complete STL container concept, this adaptor only implements
+// members useful for Google Mock's container matchers.  New members
+// should be added as needed.  To simplify the implementation, we only
+// support Element being a raw type (i.e. having no top-level const or
+// reference modifier).  It's the client's responsibility to satisfy
+// this requirement.  Element can be an array type itself (hence
+// multi-dimensional arrays are supported).
+template <typename Element>
+class NativeArray {
+ public:
+  // STL-style container typedefs.
+  typedef Element value_type;
+  typedef Element* iterator;
+  typedef const Element* const_iterator;
+
+  // Constructs from a native array.
+  NativeArray(const Element* array, size_t count, RelationToSource relation) {
+    Init(array, count, relation);
+  }
+
+  // Copy constructor.
+  NativeArray(const NativeArray& rhs) {
+    Init(rhs.array_, rhs.size_, rhs.relation_to_source_);
+  }
+
+  ~NativeArray() {
+    // Ensures that the user doesn't instantiate NativeArray with a
+    // const or reference type.
+    static_cast<void>(StaticAssertTypeEqHelper<Element,
+        GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>());
+    if (relation_to_source_ == kCopy)
+      delete[] array_;
+  }
+
+  // STL-style container methods.
+  size_t size() const { return size_; }
+  const_iterator begin() const { return array_; }
+  const_iterator end() const { return array_ + size_; }
+  bool operator==(const NativeArray& rhs) const {
+    return size() == rhs.size() &&
+        ArrayEq(begin(), size(), rhs.begin());
+  }
+
+ private:
+  // Initializes this object; makes a copy of the input array if
+  // 'relation' is kCopy.
+  void Init(const Element* array, size_t a_size, RelationToSource relation) {
+    if (relation == kReference) {
+      array_ = array;
+    } else {
+      Element* const copy = new Element[a_size];
+      CopyArray(array, a_size, copy);
+      array_ = copy;
+    }
+    size_ = a_size;
+    relation_to_source_ = relation;
+  }
+
+  const Element* array_;
+  size_t size_;
+  RelationToSource relation_to_source_;
+
+  GTEST_DISALLOW_ASSIGN_(NativeArray);
+};
+
+}  // namespace internal
+}  // namespace testing
+
+#define GTEST_MESSAGE_AT_(file, line, message, result_type) \
+  ::testing::internal::AssertHelper(result_type, file, line, message) \
+    = ::testing::Message()
+
+#define GTEST_MESSAGE_(message, result_type) \
+  GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
+
+#define GTEST_FATAL_FAILURE_(message) \
+  return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
+
+#define GTEST_NONFATAL_FAILURE_(message) \
+  GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure)
+
+#define GTEST_SUCCESS_(message) \
+  GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess)
+
+// Suppresses MSVC warnings 4072 (unreachable code) for the code following
+// statement if it returns or throws (or doesn't return or throw in some
+// situations).
+#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \
+  if (::testing::internal::AlwaysTrue()) { statement; }
+
+#define GTEST_TEST_THROW_(statement, expected_exception, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::ConstCharPtr gtest_msg = "") { \
+    bool gtest_caught_expected = false; \
+    try { \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    } \
+    catch (expected_exception const&) { \
+      gtest_caught_expected = true; \
+    } \
+    catch (...) { \
+      gtest_msg.value = \
+          "Expected: " #statement " throws an exception of type " \
+          #expected_exception ".\n  Actual: it throws a different type."; \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
+    } \
+    if (!gtest_caught_expected) { \
+      gtest_msg.value = \
+          "Expected: " #statement " throws an exception of type " \
+          #expected_exception ".\n  Actual: it throws nothing."; \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \
+      fail(gtest_msg.value)
+
+#define GTEST_TEST_NO_THROW_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    try { \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    } \
+    catch (...) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \
+      fail("Expected: " #statement " doesn't throw an exception.\n" \
+           "  Actual: it throws.")
+
+#define GTEST_TEST_ANY_THROW_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    bool gtest_caught_any = false; \
+    try { \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    } \
+    catch (...) { \
+      gtest_caught_any = true; \
+    } \
+    if (!gtest_caught_any) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \
+      fail("Expected: " #statement " throws an exception.\n" \
+           "  Actual: it doesn't.")
+
+
+// Implements Boolean test assertions such as EXPECT_TRUE. expression can be
+// either a boolean expression or an AssertionResult. text is a textual
+// represenation of expression as it was passed into the EXPECT_TRUE.
+#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (const ::testing::AssertionResult gtest_ar_ = \
+      ::testing::AssertionResult(expression)) \
+    ; \
+  else \
+    fail(::testing::internal::GetBoolAssertionFailureMessage(\
+        gtest_ar_, text, #actual, #expected).c_str())
+
+#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    ::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \
+      fail("Expected: " #statement " doesn't generate new fatal " \
+           "failures in the current thread.\n" \
+           "  Actual: it does.")
+
+// Expands to the name of the class that implements the given test.
+#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
+  test_case_name##_##test_name##_Test
+
+// Helper macro for defining tests.
+#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\
+class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
+ public:\
+  GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
+ private:\
+  virtual void TestBody();\
+  static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(\
+      GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\
+};\
+\
+::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\
+  ::test_info_ =\
+    ::testing::internal::MakeAndRegisterTestInfo(\
+        #test_case_name, #test_name, NULL, NULL, \
+        (parent_id), \
+        parent_class::SetUpTestCase, \
+        parent_class::TearDownTestCase, \
+        new ::testing::internal::TestFactoryImpl<\
+            GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\
+void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
diff --git a/third_party/googletest/src/include/gtest/internal/gtest-linked_ptr.h b/third_party/googletest/src/include/gtest/internal/gtest-linked_ptr.h
new file mode 100644 (file)
index 0000000..57147b4
--- /dev/null
@@ -0,0 +1,233 @@
+// Copyright 2003 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.
+//
+// Authors: Dan Egnor (egnor@google.com)
+//
+// A "smart" pointer type with reference tracking.  Every pointer to a
+// particular object is kept on a circular linked list.  When the last pointer
+// to an object is destroyed or reassigned, the object is deleted.
+//
+// Used properly, this deletes the object when the last reference goes away.
+// There are several caveats:
+// - Like all reference counting schemes, cycles lead to leaks.
+// - Each smart pointer is actually two pointers (8 bytes instead of 4).
+// - Every time a pointer is assigned, the entire list of pointers to that
+//   object is traversed.  This class is therefore NOT SUITABLE when there
+//   will often be more than two or three pointers to a particular object.
+// - References are only tracked as long as linked_ptr<> objects are copied.
+//   If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS
+//   will happen (double deletion).
+//
+// A good use of this class is storing object references in STL containers.
+// You can safely put linked_ptr<> in a vector<>.
+// Other uses may not be as good.
+//
+// Note: If you use an incomplete type with linked_ptr<>, the class
+// *containing* linked_ptr<> must have a constructor and destructor (even
+// if they do nothing!).
+//
+// Bill Gibbons suggested we use something like this.
+//
+// Thread Safety:
+//   Unlike other linked_ptr implementations, in this implementation
+//   a linked_ptr object is thread-safe in the sense that:
+//     - it's safe to copy linked_ptr objects concurrently,
+//     - it's safe to copy *from* a linked_ptr and read its underlying
+//       raw pointer (e.g. via get()) concurrently, and
+//     - it's safe to write to two linked_ptrs that point to the same
+//       shared object concurrently.
+// TODO(wan@google.com): rename this to safe_linked_ptr to avoid
+// confusion with normal linked_ptr.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+namespace internal {
+
+// Protects copying of all linked_ptr objects.
+GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex);
+
+// This is used internally by all instances of linked_ptr<>.  It needs to be
+// a non-template class because different types of linked_ptr<> can refer to
+// the same object (linked_ptr<Superclass>(obj) vs linked_ptr<Subclass>(obj)).
+// So, it needs to be possible for different types of linked_ptr to participate
+// in the same circular linked list, so we need a single class type here.
+//
+// DO NOT USE THIS CLASS DIRECTLY YOURSELF.  Use linked_ptr<T>.
+class linked_ptr_internal {
+ public:
+  // Create a new circle that includes only this instance.
+  void join_new() {
+    next_ = this;
+  }
+
+  // Many linked_ptr operations may change p.link_ for some linked_ptr
+  // variable p in the same circle as this object.  Therefore we need
+  // to prevent two such operations from occurring concurrently.
+  //
+  // Note that different types of linked_ptr objects can coexist in a
+  // circle (e.g. linked_ptr<Base>, linked_ptr<Derived1>, and
+  // linked_ptr<Derived2>).  Therefore we must use a single mutex to
+  // protect all linked_ptr objects.  This can create serious
+  // contention in production code, but is acceptable in a testing
+  // framework.
+
+  // Join an existing circle.
+  // L < g_linked_ptr_mutex
+  void join(linked_ptr_internal const* ptr) {
+    MutexLock lock(&g_linked_ptr_mutex);
+
+    linked_ptr_internal const* p = ptr;
+    while (p->next_ != ptr) p = p->next_;
+    p->next_ = this;
+    next_ = ptr;
+  }
+
+  // Leave whatever circle we're part of.  Returns true if we were the
+  // last member of the circle.  Once this is done, you can join() another.
+  // L < g_linked_ptr_mutex
+  bool depart() {
+    MutexLock lock(&g_linked_ptr_mutex);
+
+    if (next_ == this) return true;
+    linked_ptr_internal const* p = next_;
+    while (p->next_ != this) p = p->next_;
+    p->next_ = next_;
+    return false;
+  }
+
+ private:
+  mutable linked_ptr_internal const* next_;
+};
+
+template <typename T>
+class linked_ptr {
+ public:
+  typedef T element_type;
+
+  // Take over ownership of a raw pointer.  This should happen as soon as
+  // possible after the object is created.
+  explicit linked_ptr(T* ptr = NULL) { capture(ptr); }
+  ~linked_ptr() { depart(); }
+
+  // Copy an existing linked_ptr<>, adding ourselves to the list of references.
+  template <typename U> linked_ptr(linked_ptr<U> const& ptr) { copy(&ptr); }
+  linked_ptr(linked_ptr const& ptr) {  // NOLINT
+    assert(&ptr != this);
+    copy(&ptr);
+  }
+
+  // Assignment releases the old value and acquires the new.
+  template <typename U> linked_ptr& operator=(linked_ptr<U> const& ptr) {
+    depart();
+    copy(&ptr);
+    return *this;
+  }
+
+  linked_ptr& operator=(linked_ptr const& ptr) {
+    if (&ptr != this) {
+      depart();
+      copy(&ptr);
+    }
+    return *this;
+  }
+
+  // Smart pointer members.
+  void reset(T* ptr = NULL) {
+    depart();
+    capture(ptr);
+  }
+  T* get() const { return value_; }
+  T* operator->() const { return value_; }
+  T& operator*() const { return *value_; }
+
+  bool operator==(T* p) const { return value_ == p; }
+  bool operator!=(T* p) const { return value_ != p; }
+  template <typename U>
+  bool operator==(linked_ptr<U> const& ptr) const {
+    return value_ == ptr.get();
+  }
+  template <typename U>
+  bool operator!=(linked_ptr<U> const& ptr) const {
+    return value_ != ptr.get();
+  }
+
+ private:
+  template <typename U>
+  friend class linked_ptr;
+
+  T* value_;
+  linked_ptr_internal link_;
+
+  void depart() {
+    if (link_.depart()) delete value_;
+  }
+
+  void capture(T* ptr) {
+    value_ = ptr;
+    link_.join_new();
+  }
+
+  template <typename U> void copy(linked_ptr<U> const* ptr) {
+    value_ = ptr->get();
+    if (value_)
+      link_.join(&ptr->link_);
+    else
+      link_.join_new();
+  }
+};
+
+template<typename T> inline
+bool operator==(T* ptr, const linked_ptr<T>& x) {
+  return ptr == x.get();
+}
+
+template<typename T> inline
+bool operator!=(T* ptr, const linked_ptr<T>& x) {
+  return ptr != x.get();
+}
+
+// A function to convert T* into linked_ptr<T>
+// Doing e.g. make_linked_ptr(new FooBarBaz<type>(arg)) is a shorter notation
+// for linked_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
+template <typename T>
+linked_ptr<T> make_linked_ptr(T* ptr) {
+  return linked_ptr<T>(ptr);
+}
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
diff --git a/third_party/googletest/src/include/gtest/internal/gtest-param-util-generated.h b/third_party/googletest/src/include/gtest/internal/gtest-param-util-generated.h
new file mode 100644 (file)
index 0000000..2582675
--- /dev/null
@@ -0,0 +1,4822 @@
+// This file was GENERATED by command:
+//     pump.py gtest-param-util-generated.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008 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: vladl@google.com (Vlad Losev)
+
+// Type and function utilities for implementing parameterized tests.
+// This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+// Currently Google Test supports at most 50 arguments in Values,
+// and at most 10 arguments in Combine. Please contact
+// googletestframework@googlegroups.com if you need more.
+// Please note that the number of arguments to Combine is limited
+// by the maximum arity of the implementation of tr1::tuple which is
+// currently set at 10.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Forward declarations of ValuesIn(), which is implemented in
+// include/gtest/gtest-param-test.h.
+template <typename ForwardIterator>
+internal::ParamGenerator<
+  typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end);
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container);
+
+namespace internal {
+
+// Used in the Values() function to provide polymorphic capabilities.
+template <typename T1>
+class ValueArray1 {
+ public:
+  explicit ValueArray1(T1 v1) : v1_(v1) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const { return ValuesIn(&v1_, &v1_ + 1); }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray1& other);
+
+  const T1 v1_;
+};
+
+template <typename T1, typename T2>
+class ValueArray2 {
+ public:
+  ValueArray2(T1 v1, T2 v2) : v1_(v1), v2_(v2) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray2& other);
+
+  const T1 v1_;
+  const T2 v2_;
+};
+
+template <typename T1, typename T2, typename T3>
+class ValueArray3 {
+ public:
+  ValueArray3(T1 v1, T2 v2, T3 v3) : v1_(v1), v2_(v2), v3_(v3) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray3& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4>
+class ValueArray4 {
+ public:
+  ValueArray4(T1 v1, T2 v2, T3 v3, T4 v4) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray4& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+class ValueArray5 {
+ public:
+  ValueArray5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray5& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+class ValueArray6 {
+ public:
+  ValueArray6(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray6& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+class ValueArray7 {
+ public:
+  ValueArray7(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray7& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+class ValueArray8 {
+ public:
+  ValueArray8(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+      T8 v8) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray8& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+class ValueArray9 {
+ public:
+  ValueArray9(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+      T9 v9) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray9& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+class ValueArray10 {
+ public:
+  ValueArray10(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray10& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+class ValueArray11 {
+ public:
+  ValueArray11(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray11& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+class ValueArray12 {
+ public:
+  ValueArray12(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray12& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+class ValueArray13 {
+ public:
+  ValueArray13(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray13& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+class ValueArray14 {
+ public:
+  ValueArray14(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray14& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+class ValueArray15 {
+ public:
+  ValueArray15(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray15& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+class ValueArray16 {
+ public:
+  ValueArray16(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray16& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+class ValueArray17 {
+ public:
+  ValueArray17(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+      T17 v17) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray17& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+class ValueArray18 {
+ public:
+  ValueArray18(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray18& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+class ValueArray19 {
+ public:
+  ValueArray19(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray19& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+class ValueArray20 {
+ public:
+  ValueArray20(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray20& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+class ValueArray21 {
+ public:
+  ValueArray21(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray21& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+class ValueArray22 {
+ public:
+  ValueArray22(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray22& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+class ValueArray23 {
+ public:
+  ValueArray23(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_,
+        v23_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray23& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+class ValueArray24 {
+ public:
+  ValueArray24(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray24& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+class ValueArray25 {
+ public:
+  ValueArray25(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+      T25 v25) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray25& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+class ValueArray26 {
+ public:
+  ValueArray26(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray26& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+class ValueArray27 {
+ public:
+  ValueArray27(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+      v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+      v26_(v26), v27_(v27) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray27& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+class ValueArray28 {
+ public:
+  ValueArray28(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+      v25_(v25), v26_(v26), v27_(v27), v28_(v28) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray28& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+class ValueArray29 {
+ public:
+  ValueArray29(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+      v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray29& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+class ValueArray30 {
+ public:
+  ValueArray30(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray30& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+class ValueArray31 {
+ public:
+  ValueArray31(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray31& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+class ValueArray32 {
+ public:
+  ValueArray32(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+      v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray32& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+class ValueArray33 {
+ public:
+  ValueArray33(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32,
+      T33 v33) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray33& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+class ValueArray34 {
+ public:
+  ValueArray34(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray34& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+class ValueArray35 {
+ public:
+  ValueArray35(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+      v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+      v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31),
+      v32_(v32), v33_(v33), v34_(v34), v35_(v35) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_,
+        v35_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray35& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+class ValueArray36 {
+ public:
+  ValueArray36(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+      v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30),
+      v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray36& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+class ValueArray37 {
+ public:
+  ValueArray37(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+      v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29),
+      v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35),
+      v36_(v36), v37_(v37) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray37& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+class ValueArray38 {
+ public:
+  ValueArray38(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray38& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+class ValueArray39 {
+ public:
+  ValueArray39(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray39& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+class ValueArray40 {
+ public:
+  ValueArray40(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+      v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33),
+      v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39),
+      v40_(v40) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray40& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+class ValueArray41 {
+ public:
+  ValueArray41(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40,
+      T41 v41) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray41& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+class ValueArray42 {
+ public:
+  ValueArray42(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41), v42_(v42) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray42& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+class ValueArray43 {
+ public:
+  ValueArray43(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+      v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+      v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31),
+      v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37),
+      v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray43& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+class ValueArray44 {
+ public:
+  ValueArray44(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+      v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30),
+      v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36),
+      v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42),
+      v43_(v43), v44_(v44) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray44& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+class ValueArray45 {
+ public:
+  ValueArray45(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+      v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29),
+      v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35),
+      v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41),
+      v42_(v42), v43_(v43), v44_(v44), v45_(v45) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray45& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+class ValueArray46 {
+ public:
+  ValueArray46(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40),
+      v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray46& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+class ValueArray47 {
+ public:
+  ValueArray47(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40),
+      v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46),
+      v47_(v47) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_,
+        v47_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray47& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+class ValueArray48 {
+ public:
+  ValueArray48(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+      v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33),
+      v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39),
+      v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45),
+      v46_(v46), v47_(v47), v48_(v48) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_, v47_,
+        v48_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray48& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+  const T48 v48_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+class ValueArray49 {
+ public:
+  ValueArray49(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48,
+      T49 v49) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44),
+      v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_, v47_,
+        v48_, v49_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray49& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+  const T48 v48_;
+  const T49 v49_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+class ValueArray50 {
+ public:
+  ValueArray50(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49,
+      T50 v50) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44),
+      v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49), v50_(v50) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_, v47_,
+        v48_, v49_, v50_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray50& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+  const T48 v48_;
+  const T49 v49_;
+  const T50 v50_;
+};
+
+# if GTEST_HAS_COMBINE
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Generates values from the Cartesian product of values produced
+// by the argument generators.
+//
+template <typename T1, typename T2>
+class CartesianProductGenerator2
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2> ParamType;
+
+  CartesianProductGenerator2(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2)
+      : g1_(g1), g2_(g2) {}
+  virtual ~CartesianProductGenerator2() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current2_;
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator2::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator2& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+};  // class CartesianProductGenerator2
+
+
+template <typename T1, typename T2, typename T3>
+class CartesianProductGenerator3
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3> ParamType;
+
+  CartesianProductGenerator3(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3)
+      : g1_(g1), g2_(g2), g3_(g3) {}
+  virtual ~CartesianProductGenerator3() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current3_;
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator3::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator3& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+};  // class CartesianProductGenerator3
+
+
+template <typename T1, typename T2, typename T3, typename T4>
+class CartesianProductGenerator4
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4> ParamType;
+
+  CartesianProductGenerator4(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {}
+  virtual ~CartesianProductGenerator4() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current4_;
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator4::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator4& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+};  // class CartesianProductGenerator4
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+class CartesianProductGenerator5
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5> ParamType;
+
+  CartesianProductGenerator5(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {}
+  virtual ~CartesianProductGenerator5() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current5_;
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator5::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator5& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+};  // class CartesianProductGenerator5
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+class CartesianProductGenerator6
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5,
+        T6> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> ParamType;
+
+  CartesianProductGenerator6(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {}
+  virtual ~CartesianProductGenerator6() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current6_;
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator6::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator6& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+};  // class CartesianProductGenerator6
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+class CartesianProductGenerator7
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+        T7> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7> ParamType;
+
+  CartesianProductGenerator7(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {}
+  virtual ~CartesianProductGenerator7() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current7_;
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator7::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator7& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+};  // class CartesianProductGenerator7
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+class CartesianProductGenerator8
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+        T7, T8> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8> ParamType;
+
+  CartesianProductGenerator8(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+      const ParamGenerator<T8>& g8)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7),
+          g8_(g8) {}
+  virtual ~CartesianProductGenerator8() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin(), g8_, g8_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+        g8_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7,
+      const ParamGenerator<T8>& g8,
+      const typename ParamGenerator<T8>::iterator& current8)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+          begin8_(g8.begin()), end8_(g8.end()), current8_(current8)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current8_;
+      if (current8_ == end8_) {
+        current8_ = begin8_;
+        ++current7_;
+      }
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_ &&
+          current8_ == typed_other->current8_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_),
+        begin8_(other.begin8_),
+        end8_(other.end8_),
+        current8_(other.current8_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_, *current8_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_ ||
+          current8_ == end8_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    const typename ParamGenerator<T8>::iterator begin8_;
+    const typename ParamGenerator<T8>::iterator end8_;
+    typename ParamGenerator<T8>::iterator current8_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator8::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator8& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+  const ParamGenerator<T8> g8_;
+};  // class CartesianProductGenerator8
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+class CartesianProductGenerator9
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+        T7, T8, T9> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9> ParamType;
+
+  CartesianProductGenerator9(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+      const ParamGenerator<T8>& g8, const ParamGenerator<T9>& g9)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9) {}
+  virtual ~CartesianProductGenerator9() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+        g8_.end(), g9_, g9_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7,
+      const ParamGenerator<T8>& g8,
+      const typename ParamGenerator<T8>::iterator& current8,
+      const ParamGenerator<T9>& g9,
+      const typename ParamGenerator<T9>::iterator& current9)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+          begin8_(g8.begin()), end8_(g8.end()), current8_(current8),
+          begin9_(g9.begin()), end9_(g9.end()), current9_(current9)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current9_;
+      if (current9_ == end9_) {
+        current9_ = begin9_;
+        ++current8_;
+      }
+      if (current8_ == end8_) {
+        current8_ = begin8_;
+        ++current7_;
+      }
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_ &&
+          current8_ == typed_other->current8_ &&
+          current9_ == typed_other->current9_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_),
+        begin8_(other.begin8_),
+        end8_(other.end8_),
+        current8_(other.current8_),
+        begin9_(other.begin9_),
+        end9_(other.end9_),
+        current9_(other.current9_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_, *current8_,
+            *current9_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_ ||
+          current8_ == end8_ ||
+          current9_ == end9_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    const typename ParamGenerator<T8>::iterator begin8_;
+    const typename ParamGenerator<T8>::iterator end8_;
+    typename ParamGenerator<T8>::iterator current8_;
+    const typename ParamGenerator<T9>::iterator begin9_;
+    const typename ParamGenerator<T9>::iterator end9_;
+    typename ParamGenerator<T9>::iterator current9_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator9::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator9& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+  const ParamGenerator<T8> g8_;
+  const ParamGenerator<T9> g9_;
+};  // class CartesianProductGenerator9
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+class CartesianProductGenerator10
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+        T7, T8, T9, T10> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ParamType;
+
+  CartesianProductGenerator10(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+      const ParamGenerator<T8>& g8, const ParamGenerator<T9>& g9,
+      const ParamGenerator<T10>& g10)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9), g10_(g10) {}
+  virtual ~CartesianProductGenerator10() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin(), g10_, g10_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+        g8_.end(), g9_, g9_.end(), g10_, g10_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7,
+      const ParamGenerator<T8>& g8,
+      const typename ParamGenerator<T8>::iterator& current8,
+      const ParamGenerator<T9>& g9,
+      const typename ParamGenerator<T9>::iterator& current9,
+      const ParamGenerator<T10>& g10,
+      const typename ParamGenerator<T10>::iterator& current10)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+          begin8_(g8.begin()), end8_(g8.end()), current8_(current8),
+          begin9_(g9.begin()), end9_(g9.end()), current9_(current9),
+          begin10_(g10.begin()), end10_(g10.end()), current10_(current10)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current10_;
+      if (current10_ == end10_) {
+        current10_ = begin10_;
+        ++current9_;
+      }
+      if (current9_ == end9_) {
+        current9_ = begin9_;
+        ++current8_;
+      }
+      if (current8_ == end8_) {
+        current8_ = begin8_;
+        ++current7_;
+      }
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_ &&
+          current8_ == typed_other->current8_ &&
+          current9_ == typed_other->current9_ &&
+          current10_ == typed_other->current10_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_),
+        begin8_(other.begin8_),
+        end8_(other.end8_),
+        current8_(other.current8_),
+        begin9_(other.begin9_),
+        end9_(other.end9_),
+        current9_(other.current9_),
+        begin10_(other.begin10_),
+        end10_(other.end10_),
+        current10_(other.current10_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_, *current8_,
+            *current9_, *current10_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_ ||
+          current8_ == end8_ ||
+          current9_ == end9_ ||
+          current10_ == end10_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    const typename ParamGenerator<T8>::iterator begin8_;
+    const typename ParamGenerator<T8>::iterator end8_;
+    typename ParamGenerator<T8>::iterator current8_;
+    const typename ParamGenerator<T9>::iterator begin9_;
+    const typename ParamGenerator<T9>::iterator end9_;
+    typename ParamGenerator<T9>::iterator current9_;
+    const typename ParamGenerator<T10>::iterator begin10_;
+    const typename ParamGenerator<T10>::iterator end10_;
+    typename ParamGenerator<T10>::iterator current10_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator10::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator10& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+  const ParamGenerator<T8> g8_;
+  const ParamGenerator<T9> g9_;
+  const ParamGenerator<T10> g10_;
+};  // class CartesianProductGenerator10
+
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Helper classes providing Combine() with polymorphic features. They allow
+// casting CartesianProductGeneratorN<T> to ParamGenerator<U> if T is
+// convertible to U.
+//
+template <class Generator1, class Generator2>
+class CartesianProductHolder2 {
+ public:
+CartesianProductHolder2(const Generator1& g1, const Generator2& g2)
+      : g1_(g1), g2_(g2) {}
+  template <typename T1, typename T2>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2> >(
+        new CartesianProductGenerator2<T1, T2>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder2& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+};  // class CartesianProductHolder2
+
+template <class Generator1, class Generator2, class Generator3>
+class CartesianProductHolder3 {
+ public:
+CartesianProductHolder3(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3)
+      : g1_(g1), g2_(g2), g3_(g3) {}
+  template <typename T1, typename T2, typename T3>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3> >(
+        new CartesianProductGenerator3<T1, T2, T3>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder3& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+};  // class CartesianProductHolder3
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4>
+class CartesianProductHolder4 {
+ public:
+CartesianProductHolder4(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {}
+  template <typename T1, typename T2, typename T3, typename T4>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4> >(
+        new CartesianProductGenerator4<T1, T2, T3, T4>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder4& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+};  // class CartesianProductHolder4
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5>
+class CartesianProductHolder5 {
+ public:
+CartesianProductHolder5(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5> >(
+        new CartesianProductGenerator5<T1, T2, T3, T4, T5>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder5& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+};  // class CartesianProductHolder5
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6>
+class CartesianProductHolder6 {
+ public:
+CartesianProductHolder6(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> >(
+        new CartesianProductGenerator6<T1, T2, T3, T4, T5, T6>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder6& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+};  // class CartesianProductHolder6
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7>
+class CartesianProductHolder7 {
+ public:
+CartesianProductHolder7(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+      T7> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7> >(
+        new CartesianProductGenerator7<T1, T2, T3, T4, T5, T6, T7>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder7& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+};  // class CartesianProductHolder7
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7,
+    class Generator8>
+class CartesianProductHolder8 {
+ public:
+CartesianProductHolder8(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7, const Generator8& g8)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7),
+          g8_(g8) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7, typename T8>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7,
+      T8> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8> >(
+        new CartesianProductGenerator8<T1, T2, T3, T4, T5, T6, T7, T8>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_),
+        static_cast<ParamGenerator<T8> >(g8_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder8& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+  const Generator8 g8_;
+};  // class CartesianProductHolder8
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7,
+    class Generator8, class Generator9>
+class CartesianProductHolder9 {
+ public:
+CartesianProductHolder9(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7, const Generator8& g8,
+    const Generator9& g9)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7, typename T8, typename T9>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+      T9> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+        T9> >(
+        new CartesianProductGenerator9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_),
+        static_cast<ParamGenerator<T8> >(g8_),
+        static_cast<ParamGenerator<T9> >(g9_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder9& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+  const Generator8 g8_;
+  const Generator9 g9_;
+};  // class CartesianProductHolder9
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7,
+    class Generator8, class Generator9, class Generator10>
+class CartesianProductHolder10 {
+ public:
+CartesianProductHolder10(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7, const Generator8& g8,
+    const Generator9& g9, const Generator10& g10)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9), g10_(g10) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7, typename T8, typename T9, typename T10>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+      T9, T10> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+        T9, T10> >(
+        new CartesianProductGenerator10<T1, T2, T3, T4, T5, T6, T7, T8, T9,
+            T10>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_),
+        static_cast<ParamGenerator<T8> >(g8_),
+        static_cast<ParamGenerator<T9> >(g9_),
+        static_cast<ParamGenerator<T10> >(g10_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder10& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+  const Generator8 g8_;
+  const Generator9 g9_;
+  const Generator10 g10_;
+};  // class CartesianProductHolder10
+
+# endif  // GTEST_HAS_COMBINE
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  //  GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
diff --git a/third_party/googletest/src/include/gtest/internal/gtest-param-util-generated.h.pump b/third_party/googletest/src/include/gtest/internal/gtest-param-util-generated.h.pump
new file mode 100644 (file)
index 0000000..dbe9386
--- /dev/null
@@ -0,0 +1,301 @@
+$$ -*- mode: c++; -*-
+$var n = 50  $$ Maximum length of Values arguments we want to support.
+$var maxtuple = 10  $$ Maximum number of Combine arguments we want to support.
+// Copyright 2008 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: vladl@google.com (Vlad Losev)
+
+// Type and function utilities for implementing parameterized tests.
+// This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+// Currently Google Test supports at most $n arguments in Values,
+// and at most $maxtuple arguments in Combine. Please contact
+// googletestframework@googlegroups.com if you need more.
+// Please note that the number of arguments to Combine is limited
+// by the maximum arity of the implementation of tr1::tuple which is
+// currently set at $maxtuple.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Forward declarations of ValuesIn(), which is implemented in
+// include/gtest/gtest-param-test.h.
+template <typename ForwardIterator>
+internal::ParamGenerator<
+  typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end);
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container);
+
+namespace internal {
+
+// Used in the Values() function to provide polymorphic capabilities.
+template <typename T1>
+class ValueArray1 {
+ public:
+  explicit ValueArray1(T1 v1) : v1_(v1) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const { return ValuesIn(&v1_, &v1_ + 1); }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray1& other);
+
+  const T1 v1_;
+};
+
+$range i 2..n
+$for i [[
+$range j 1..i
+
+template <$for j, [[typename T$j]]>
+class ValueArray$i {
+ public:
+  ValueArray$i($for j, [[T$j v$j]]) : $for j, [[v$(j)_(v$j)]] {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {$for j, [[v$(j)_]]};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray$i& other);
+
+$for j [[
+
+  const T$j v$(j)_;
+]]
+
+};
+
+]]
+
+# if GTEST_HAS_COMBINE
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Generates values from the Cartesian product of values produced
+// by the argument generators.
+//
+$range i 2..maxtuple
+$for i [[
+$range j 1..i
+$range k 2..i
+
+template <$for j, [[typename T$j]]>
+class CartesianProductGenerator$i
+    : public ParamGeneratorInterface< ::std::tr1::tuple<$for j, [[T$j]]> > {
+ public:
+  typedef ::std::tr1::tuple<$for j, [[T$j]]> ParamType;
+
+  CartesianProductGenerator$i($for j, [[const ParamGenerator<T$j>& g$j]])
+      : $for j, [[g$(j)_(g$j)]] {}
+  virtual ~CartesianProductGenerator$i() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, $for j, [[g$(j)_, g$(j)_.begin()]]);
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, $for j, [[g$(j)_, g$(j)_.end()]]);
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base, $for j, [[
+
+      const ParamGenerator<T$j>& g$j,
+      const typename ParamGenerator<T$j>::iterator& current$(j)]])
+        : base_(base),
+$for j, [[
+
+          begin$(j)_(g$j.begin()), end$(j)_(g$j.end()), current$(j)_(current$j)
+]]    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current$(i)_;
+
+$for k [[
+      if (current$(i+2-k)_ == end$(i+2-k)_) {
+        current$(i+2-k)_ = begin$(i+2-k)_;
+        ++current$(i+2-k-1)_;
+      }
+
+]]
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         ($for j  && [[
+
+          current$(j)_ == typed_other->current$(j)_
+]]);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_), $for j, [[
+
+        begin$(j)_(other.begin$(j)_),
+        end$(j)_(other.end$(j)_),
+        current$(j)_(other.current$(j)_)
+]] {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType($for j, [[*current$(j)_]]);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+$for j  || [[
+
+          current$(j)_ == end$(j)_
+]];
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+$for j [[
+
+    const typename ParamGenerator<T$j>::iterator begin$(j)_;
+    const typename ParamGenerator<T$j>::iterator end$(j)_;
+    typename ParamGenerator<T$j>::iterator current$(j)_;
+]]
+
+    ParamType current_value_;
+  };  // class CartesianProductGenerator$i::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator$i& other);
+
+
+$for j [[
+  const ParamGenerator<T$j> g$(j)_;
+
+]]
+};  // class CartesianProductGenerator$i
+
+
+]]
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Helper classes providing Combine() with polymorphic features. They allow
+// casting CartesianProductGeneratorN<T> to ParamGenerator<U> if T is
+// convertible to U.
+//
+$range i 2..maxtuple
+$for i [[
+$range j 1..i
+
+template <$for j, [[class Generator$j]]>
+class CartesianProductHolder$i {
+ public:
+CartesianProductHolder$i($for j, [[const Generator$j& g$j]])
+      : $for j, [[g$(j)_(g$j)]] {}
+  template <$for j, [[typename T$j]]>
+  operator ParamGenerator< ::std::tr1::tuple<$for j, [[T$j]]> >() const {
+    return ParamGenerator< ::std::tr1::tuple<$for j, [[T$j]]> >(
+        new CartesianProductGenerator$i<$for j, [[T$j]]>(
+$for j,[[
+
+        static_cast<ParamGenerator<T$j> >(g$(j)_)
+]]));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder$i& other);
+
+
+$for j [[
+  const Generator$j g$(j)_;
+
+]]
+};  // class CartesianProductHolder$i
+
+]]
+
+# endif  // GTEST_HAS_COMBINE
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  //  GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
diff --git a/third_party/googletest/src/include/gtest/internal/gtest-param-util.h b/third_party/googletest/src/include/gtest/internal/gtest-param-util.h
new file mode 100644 (file)
index 0000000..0ef9718
--- /dev/null
@@ -0,0 +1,619 @@
+// Copyright 2008 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: vladl@google.com (Vlad Losev)
+
+// Type and function utilities for implementing parameterized tests.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+
+#include <iterator>
+#include <utility>
+#include <vector>
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-linked_ptr.h"
+#include "gtest/internal/gtest-port.h"
+#include "gtest/gtest-printers.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+namespace internal {
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Outputs a message explaining invalid registration of different
+// fixture class for the same test case. This may happen when
+// TEST_P macro is used to define two tests with the same name
+// but in different namespaces.
+GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name,
+                                          const char* file, int line);
+
+template <typename> class ParamGeneratorInterface;
+template <typename> class ParamGenerator;
+
+// Interface for iterating over elements provided by an implementation
+// of ParamGeneratorInterface<T>.
+template <typename T>
+class ParamIteratorInterface {
+ public:
+  virtual ~ParamIteratorInterface() {}
+  // A pointer to the base generator instance.
+  // Used only for the purposes of iterator comparison
+  // to make sure that two iterators belong to the same generator.
+  virtual const ParamGeneratorInterface<T>* BaseGenerator() const = 0;
+  // Advances iterator to point to the next element
+  // provided by the generator. The caller is responsible
+  // for not calling Advance() on an iterator equal to
+  // BaseGenerator()->End().
+  virtual void Advance() = 0;
+  // Clones the iterator object. Used for implementing copy semantics
+  // of ParamIterator<T>.
+  virtual ParamIteratorInterface* Clone() const = 0;
+  // Dereferences the current iterator and provides (read-only) access
+  // to the pointed value. It is the caller's responsibility not to call
+  // Current() on an iterator equal to BaseGenerator()->End().
+  // Used for implementing ParamGenerator<T>::operator*().
+  virtual const T* Current() const = 0;
+  // Determines whether the given iterator and other point to the same
+  // element in the sequence generated by the generator.
+  // Used for implementing ParamGenerator<T>::operator==().
+  virtual bool Equals(const ParamIteratorInterface& other) const = 0;
+};
+
+// Class iterating over elements provided by an implementation of
+// ParamGeneratorInterface<T>. It wraps ParamIteratorInterface<T>
+// and implements the const forward iterator concept.
+template <typename T>
+class ParamIterator {
+ public:
+  typedef T value_type;
+  typedef const T& reference;
+  typedef ptrdiff_t difference_type;
+
+  // ParamIterator assumes ownership of the impl_ pointer.
+  ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
+  ParamIterator& operator=(const ParamIterator& other) {
+    if (this != &other)
+      impl_.reset(other.impl_->Clone());
+    return *this;
+  }
+
+  const T& operator*() const { return *impl_->Current(); }
+  const T* operator->() const { return impl_->Current(); }
+  // Prefix version of operator++.
+  ParamIterator& operator++() {
+    impl_->Advance();
+    return *this;
+  }
+  // Postfix version of operator++.
+  ParamIterator operator++(int /*unused*/) {
+    ParamIteratorInterface<T>* clone = impl_->Clone();
+    impl_->Advance();
+    return ParamIterator(clone);
+  }
+  bool operator==(const ParamIterator& other) const {
+    return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_);
+  }
+  bool operator!=(const ParamIterator& other) const {
+    return !(*this == other);
+  }
+
+ private:
+  friend class ParamGenerator<T>;
+  explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
+  scoped_ptr<ParamIteratorInterface<T> > impl_;
+};
+
+// ParamGeneratorInterface<T> is the binary interface to access generators
+// defined in other translation units.
+template <typename T>
+class ParamGeneratorInterface {
+ public:
+  typedef T ParamType;
+
+  virtual ~ParamGeneratorInterface() {}
+
+  // Generator interface definition
+  virtual ParamIteratorInterface<T>* Begin() const = 0;
+  virtual ParamIteratorInterface<T>* End() const = 0;
+};
+
+// Wraps ParamGeneratorInterface<T> and provides general generator syntax
+// compatible with the STL Container concept.
+// This class implements copy initialization semantics and the contained
+// ParamGeneratorInterface<T> instance is shared among all copies
+// of the original object. This is possible because that instance is immutable.
+template<typename T>
+class ParamGenerator {
+ public:
+  typedef ParamIterator<T> iterator;
+
+  explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
+  ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {}
+
+  ParamGenerator& operator=(const ParamGenerator& other) {
+    impl_ = other.impl_;
+    return *this;
+  }
+
+  iterator begin() const { return iterator(impl_->Begin()); }
+  iterator end() const { return iterator(impl_->End()); }
+
+ private:
+  linked_ptr<const ParamGeneratorInterface<T> > impl_;
+};
+
+// Generates values from a range of two comparable values. Can be used to
+// generate sequences of user-defined types that implement operator+() and
+// operator<().
+// This class is used in the Range() function.
+template <typename T, typename IncrementT>
+class RangeGenerator : public ParamGeneratorInterface<T> {
+ public:
+  RangeGenerator(T begin, T end, IncrementT step)
+      : begin_(begin), end_(end),
+        step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
+  virtual ~RangeGenerator() {}
+
+  virtual ParamIteratorInterface<T>* Begin() const {
+    return new Iterator(this, begin_, 0, step_);
+  }
+  virtual ParamIteratorInterface<T>* End() const {
+    return new Iterator(this, end_, end_index_, step_);
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<T> {
+   public:
+    Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
+             IncrementT step)
+        : base_(base), value_(value), index_(index), step_(step) {}
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
+      return base_;
+    }
+    virtual void Advance() {
+      value_ = value_ + step_;
+      index_++;
+    }
+    virtual ParamIteratorInterface<T>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const T* Current() const { return &value_; }
+    virtual bool Equals(const ParamIteratorInterface<T>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const int other_index =
+          CheckedDowncastToActualType<const Iterator>(&other)->index_;
+      return index_ == other_index;
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : ParamIteratorInterface<T>(),
+          base_(other.base_), value_(other.value_), index_(other.index_),
+          step_(other.step_) {}
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<T>* const base_;
+    T value_;
+    int index_;
+    const IncrementT step_;
+  };  // class RangeGenerator::Iterator
+
+  static int CalculateEndIndex(const T& begin,
+                               const T& end,
+                               const IncrementT& step) {
+    int end_index = 0;
+    for (T i = begin; i < end; i = i + step)
+      end_index++;
+    return end_index;
+  }
+
+  // No implementation - assignment is unsupported.
+  void operator=(const RangeGenerator& other);
+
+  const T begin_;
+  const T end_;
+  const IncrementT step_;
+  // The index for the end() iterator. All the elements in the generated
+  // sequence are indexed (0-based) to aid iterator comparison.
+  const int end_index_;
+};  // class RangeGenerator
+
+
+// Generates values from a pair of STL-style iterators. Used in the
+// ValuesIn() function. The elements are copied from the source range
+// since the source can be located on the stack, and the generator
+// is likely to persist beyond that stack frame.
+template <typename T>
+class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
+ public:
+  template <typename ForwardIterator>
+  ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
+      : container_(begin, end) {}
+  virtual ~ValuesInIteratorRangeGenerator() {}
+
+  virtual ParamIteratorInterface<T>* Begin() const {
+    return new Iterator(this, container_.begin());
+  }
+  virtual ParamIteratorInterface<T>* End() const {
+    return new Iterator(this, container_.end());
+  }
+
+ private:
+  typedef typename ::std::vector<T> ContainerType;
+
+  class Iterator : public ParamIteratorInterface<T> {
+   public:
+    Iterator(const ParamGeneratorInterface<T>* base,
+             typename ContainerType::const_iterator iterator)
+        : base_(base), iterator_(iterator) {}
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
+      return base_;
+    }
+    virtual void Advance() {
+      ++iterator_;
+      value_.reset();
+    }
+    virtual ParamIteratorInterface<T>* Clone() const {
+      return new Iterator(*this);
+    }
+    // We need to use cached value referenced by iterator_ because *iterator_
+    // can return a temporary object (and of type other then T), so just
+    // having "return &*iterator_;" doesn't work.
+    // value_ is updated here and not in Advance() because Advance()
+    // can advance iterator_ beyond the end of the range, and we cannot
+    // detect that fact. The client code, on the other hand, is
+    // responsible for not calling Current() on an out-of-range iterator.
+    virtual const T* Current() const {
+      if (value_.get() == NULL)
+        value_.reset(new T(*iterator_));
+      return value_.get();
+    }
+    virtual bool Equals(const ParamIteratorInterface<T>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      return iterator_ ==
+          CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
+    }
+
+   private:
+    Iterator(const Iterator& other)
+          // The explicit constructor call suppresses a false warning
+          // emitted by gcc when supplied with the -Wextra option.
+        : ParamIteratorInterface<T>(),
+          base_(other.base_),
+          iterator_(other.iterator_) {}
+
+    const ParamGeneratorInterface<T>* const base_;
+    typename ContainerType::const_iterator iterator_;
+    // A cached value of *iterator_. We keep it here to allow access by
+    // pointer in the wrapping iterator's operator->().
+    // value_ needs to be mutable to be accessed in Current().
+    // Use of scoped_ptr helps manage cached value's lifetime,
+    // which is bound by the lifespan of the iterator itself.
+    mutable scoped_ptr<const T> value_;
+  };  // class ValuesInIteratorRangeGenerator::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const ValuesInIteratorRangeGenerator& other);
+
+  const ContainerType container_;
+};  // class ValuesInIteratorRangeGenerator
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Stores a parameter value and later creates tests parameterized with that
+// value.
+template <class TestClass>
+class ParameterizedTestFactory : public TestFactoryBase {
+ public:
+  typedef typename TestClass::ParamType ParamType;
+  explicit ParameterizedTestFactory(ParamType parameter) :
+      parameter_(parameter) {}
+  virtual Test* CreateTest() {
+    TestClass::SetParam(&parameter_);
+    return new TestClass();
+  }
+
+ private:
+  const ParamType parameter_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// TestMetaFactoryBase is a base class for meta-factories that create
+// test factories for passing into MakeAndRegisterTestInfo function.
+template <class ParamType>
+class TestMetaFactoryBase {
+ public:
+  virtual ~TestMetaFactoryBase() {}
+
+  virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0;
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// TestMetaFactory creates test factories for passing into
+// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives
+// ownership of test factory pointer, same factory object cannot be passed
+// into that method twice. But ParameterizedTestCaseInfo is going to call
+// it for each Test/Parameter value combination. Thus it needs meta factory
+// creator class.
+template <class TestCase>
+class TestMetaFactory
+    : public TestMetaFactoryBase<typename TestCase::ParamType> {
+ public:
+  typedef typename TestCase::ParamType ParamType;
+
+  TestMetaFactory() {}
+
+  virtual TestFactoryBase* CreateTestFactory(ParamType parameter) {
+    return new ParameterizedTestFactory<TestCase>(parameter);
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseInfoBase is a generic interface
+// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase
+// accumulates test information provided by TEST_P macro invocations
+// and generators provided by INSTANTIATE_TEST_CASE_P macro invocations
+// and uses that information to register all resulting test instances
+// in RegisterTests method. The ParameterizeTestCaseRegistry class holds
+// a collection of pointers to the ParameterizedTestCaseInfo objects
+// and calls RegisterTests() on each of them when asked.
+class ParameterizedTestCaseInfoBase {
+ public:
+  virtual ~ParameterizedTestCaseInfoBase() {}
+
+  // Base part of test case name for display purposes.
+  virtual const string& GetTestCaseName() const = 0;
+  // Test case id to verify identity.
+  virtual TypeId GetTestCaseTypeId() const = 0;
+  // UnitTest class invokes this method to register tests in this
+  // test case right before running them in RUN_ALL_TESTS macro.
+  // This method should not be called more then once on any single
+  // instance of a ParameterizedTestCaseInfoBase derived class.
+  virtual void RegisterTests() = 0;
+
+ protected:
+  ParameterizedTestCaseInfoBase() {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P
+// macro invocations for a particular test case and generators
+// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that
+// test case. It registers tests with all values generated by all
+// generators when asked.
+template <class TestCase>
+class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
+ public:
+  // ParamType and GeneratorCreationFunc are private types but are required
+  // for declarations of public methods AddTestPattern() and
+  // AddTestCaseInstantiation().
+  typedef typename TestCase::ParamType ParamType;
+  // A function that returns an instance of appropriate generator type.
+  typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
+
+  explicit ParameterizedTestCaseInfo(const char* name)
+      : test_case_name_(name) {}
+
+  // Test case base name for display purposes.
+  virtual const string& GetTestCaseName() const { return test_case_name_; }
+  // Test case id to verify identity.
+  virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); }
+  // TEST_P macro uses AddTestPattern() to record information
+  // about a single test in a LocalTestInfo structure.
+  // test_case_name is the base name of the test case (without invocation
+  // prefix). test_base_name is the name of an individual test without
+  // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
+  // test case base name and DoBar is test base name.
+  void AddTestPattern(const char* test_case_name,
+                      const char* test_base_name,
+                      TestMetaFactoryBase<ParamType>* meta_factory) {
+    tests_.push_back(linked_ptr<TestInfo>(new TestInfo(test_case_name,
+                                                       test_base_name,
+                                                       meta_factory)));
+  }
+  // INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information
+  // about a generator.
+  int AddTestCaseInstantiation(const string& instantiation_name,
+                               GeneratorCreationFunc* func,
+                               const char* /* file */,
+                               int /* line */) {
+    instantiations_.push_back(::std::make_pair(instantiation_name, func));
+    return 0;  // Return value used only to run this method in namespace scope.
+  }
+  // UnitTest class invokes this method to register tests in this test case
+  // test cases right before running tests in RUN_ALL_TESTS macro.
+  // This method should not be called more then once on any single
+  // instance of a ParameterizedTestCaseInfoBase derived class.
+  // UnitTest has a guard to prevent from calling this method more then once.
+  virtual void RegisterTests() {
+    for (typename TestInfoContainer::iterator test_it = tests_.begin();
+         test_it != tests_.end(); ++test_it) {
+      linked_ptr<TestInfo> test_info = *test_it;
+      for (typename InstantiationContainer::iterator gen_it =
+               instantiations_.begin(); gen_it != instantiations_.end();
+               ++gen_it) {
+        const string& instantiation_name = gen_it->first;
+        ParamGenerator<ParamType> generator((*gen_it->second)());
+
+        Message test_case_name_stream;
+        if ( !instantiation_name.empty() )
+          test_case_name_stream << instantiation_name << "/";
+        test_case_name_stream << test_info->test_case_base_name;
+
+        int i = 0;
+        for (typename ParamGenerator<ParamType>::iterator param_it =
+                 generator.begin();
+             param_it != generator.end(); ++param_it, ++i) {
+          Message test_name_stream;
+          test_name_stream << test_info->test_base_name << "/" << i;
+          MakeAndRegisterTestInfo(
+              test_case_name_stream.GetString().c_str(),
+              test_name_stream.GetString().c_str(),
+              NULL,  // No type parameter.
+              PrintToString(*param_it).c_str(),
+              GetTestCaseTypeId(),
+              TestCase::SetUpTestCase,
+              TestCase::TearDownTestCase,
+              test_info->test_meta_factory->CreateTestFactory(*param_it));
+        }  // for param_it
+      }  // for gen_it
+    }  // for test_it
+  }  // RegisterTests
+
+ private:
+  // LocalTestInfo structure keeps information about a single test registered
+  // with TEST_P macro.
+  struct TestInfo {
+    TestInfo(const char* a_test_case_base_name,
+             const char* a_test_base_name,
+             TestMetaFactoryBase<ParamType>* a_test_meta_factory) :
+        test_case_base_name(a_test_case_base_name),
+        test_base_name(a_test_base_name),
+        test_meta_factory(a_test_meta_factory) {}
+
+    const string test_case_base_name;
+    const string test_base_name;
+    const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
+  };
+  typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer;
+  // Keeps pairs of <Instantiation name, Sequence generator creation function>
+  // received from INSTANTIATE_TEST_CASE_P macros.
+  typedef ::std::vector<std::pair<string, GeneratorCreationFunc*> >
+      InstantiationContainer;
+
+  const string test_case_name_;
+  TestInfoContainer tests_;
+  InstantiationContainer instantiations_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo);
+};  // class ParameterizedTestCaseInfo
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase
+// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P
+// macros use it to locate their corresponding ParameterizedTestCaseInfo
+// descriptors.
+class ParameterizedTestCaseRegistry {
+ public:
+  ParameterizedTestCaseRegistry() {}
+  ~ParameterizedTestCaseRegistry() {
+    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+         it != test_case_infos_.end(); ++it) {
+      delete *it;
+    }
+  }
+
+  // Looks up or creates and returns a structure containing information about
+  // tests and instantiations of a particular test case.
+  template <class TestCase>
+  ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
+      const char* test_case_name,
+      const char* file,
+      int line) {
+    ParameterizedTestCaseInfo<TestCase>* typed_test_info = NULL;
+    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+         it != test_case_infos_.end(); ++it) {
+      if ((*it)->GetTestCaseName() == test_case_name) {
+        if ((*it)->GetTestCaseTypeId() != GetTypeId<TestCase>()) {
+          // Complain about incorrect usage of Google Test facilities
+          // and terminate the program since we cannot guaranty correct
+          // test case setup and tear-down in this case.
+          ReportInvalidTestCaseType(test_case_name,  file, line);
+          posix::Abort();
+        } else {
+          // At this point we are sure that the object we found is of the same
+          // type we are looking for, so we downcast it to that type
+          // without further checks.
+          typed_test_info = CheckedDowncastToActualType<
+              ParameterizedTestCaseInfo<TestCase> >(*it);
+        }
+        break;
+      }
+    }
+    if (typed_test_info == NULL) {
+      typed_test_info = new ParameterizedTestCaseInfo<TestCase>(test_case_name);
+      test_case_infos_.push_back(typed_test_info);
+    }
+    return typed_test_info;
+  }
+  void RegisterTests() {
+    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+         it != test_case_infos_.end(); ++it) {
+      (*it)->RegisterTests();
+    }
+  }
+
+ private:
+  typedef ::std::vector<ParameterizedTestCaseInfoBase*> TestCaseInfoContainer;
+
+  TestCaseInfoContainer test_case_infos_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry);
+};
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  //  GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
diff --git a/third_party/googletest/src/include/gtest/internal/gtest-port.h b/third_party/googletest/src/include/gtest/internal/gtest-port.h
new file mode 100644 (file)
index 0000000..157b47f
--- /dev/null
@@ -0,0 +1,1775 @@
+// Copyright 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.
+//
+// Authors: wan@google.com (Zhanyong Wan)
+//
+// Low-level types and utilities for porting Google Test to various
+// platforms.  They are subject to change without notice.  DO NOT USE
+// THEM IN USER CODE.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+
+// The user can define the following macros in the build script to
+// control Google Test's behavior.  If the user doesn't define a macro
+// in this list, Google Test will define it.
+//
+//   GTEST_HAS_CLONE          - Define it to 1/0 to indicate that clone(2)
+//                              is/isn't available.
+//   GTEST_HAS_EXCEPTIONS     - Define it to 1/0 to indicate that exceptions
+//                              are enabled.
+//   GTEST_HAS_GLOBAL_STRING  - Define it to 1/0 to indicate that ::string
+//                              is/isn't available (some systems define
+//                              ::string, which is different to std::string).
+//   GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string
+//                              is/isn't available (some systems define
+//                              ::wstring, which is different to std::wstring).
+//   GTEST_HAS_POSIX_RE       - Define it to 1/0 to indicate that POSIX regular
+//                              expressions are/aren't available.
+//   GTEST_HAS_PTHREAD        - Define it to 1/0 to indicate that <pthread.h>
+//                              is/isn't available.
+//   GTEST_HAS_RTTI           - Define it to 1/0 to indicate that RTTI is/isn't
+//                              enabled.
+//   GTEST_HAS_STD_WSTRING    - Define it to 1/0 to indicate that
+//                              std::wstring does/doesn't work (Google Test can
+//                              be used where std::wstring is unavailable).
+//   GTEST_HAS_TR1_TUPLE      - Define it to 1/0 to indicate tr1::tuple
+//                              is/isn't available.
+//   GTEST_HAS_SEH            - Define it to 1/0 to indicate whether the
+//                              compiler supports Microsoft's "Structured
+//                              Exception Handling".
+//   GTEST_HAS_STREAM_REDIRECTION
+//                            - Define it to 1/0 to indicate whether the
+//                              platform supports I/O stream redirection using
+//                              dup() and dup2().
+//   GTEST_USE_OWN_TR1_TUPLE  - Define it to 1/0 to indicate whether Google
+//                              Test's own tr1 tuple implementation should be
+//                              used.  Unused when the user sets
+//                              GTEST_HAS_TR1_TUPLE to 0.
+//   GTEST_LINKED_AS_SHARED_LIBRARY
+//                            - Define to 1 when compiling tests that use
+//                              Google Test as a shared library (known as
+//                              DLL on Windows).
+//   GTEST_CREATE_SHARED_LIBRARY
+//                            - Define to 1 when compiling Google Test itself
+//                              as a shared library.
+
+// This header defines the following utilities:
+//
+// Macros indicating the current platform (defined to 1 if compiled on
+// the given platform; otherwise undefined):
+//   GTEST_OS_AIX      - IBM AIX
+//   GTEST_OS_CYGWIN   - Cygwin
+//   GTEST_OS_HPUX     - HP-UX
+//   GTEST_OS_LINUX    - Linux
+//     GTEST_OS_LINUX_ANDROID - Google Android
+//   GTEST_OS_MAC      - Mac OS X
+//   GTEST_OS_NACL     - Google Native Client (NaCl)
+//   GTEST_OS_SOLARIS  - Sun Solaris
+//   GTEST_OS_SYMBIAN  - Symbian
+//   GTEST_OS_WINDOWS  - Windows (Desktop, MinGW, or Mobile)
+//     GTEST_OS_WINDOWS_DESKTOP  - Windows Desktop
+//     GTEST_OS_WINDOWS_MINGW    - MinGW
+//     GTEST_OS_WINDOWS_MOBILE   - Windows Mobile
+//   GTEST_OS_ZOS      - z/OS
+//
+// Among the platforms, Cygwin, Linux, Max OS X, and Windows have the
+// most stable support.  Since core members of the Google Test project
+// don't have access to other platforms, support for them may be less
+// stable.  If you notice any problems on your platform, please notify
+// googletestframework@googlegroups.com (patches for fixing them are
+// even more welcome!).
+//
+// Note that it is possible that none of the GTEST_OS_* macros are defined.
+//
+// Macros indicating available Google Test features (defined to 1 if
+// the corresponding feature is supported; otherwise undefined):
+//   GTEST_HAS_COMBINE      - the Combine() function (for value-parameterized
+//                            tests)
+//   GTEST_HAS_DEATH_TEST   - death tests
+//   GTEST_HAS_PARAM_TEST   - value-parameterized tests
+//   GTEST_HAS_TYPED_TEST   - typed tests
+//   GTEST_HAS_TYPED_TEST_P - type-parameterized tests
+//   GTEST_USES_POSIX_RE    - enhanced POSIX regex is used. Do not confuse with
+//                            GTEST_HAS_POSIX_RE (see above) which users can
+//                            define themselves.
+//   GTEST_USES_SIMPLE_RE   - our own simple regex is used;
+//                            the above two are mutually exclusive.
+//   GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ().
+//
+// Macros for basic C++ coding:
+//   GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning.
+//   GTEST_ATTRIBUTE_UNUSED_  - declares that a class' instances or a
+//                              variable don't have to be used.
+//   GTEST_DISALLOW_ASSIGN_   - disables operator=.
+//   GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=.
+//   GTEST_MUST_USE_RESULT_   - declares that a function's result must be used.
+//
+// Synchronization:
+//   Mutex, MutexLock, ThreadLocal, GetThreadCount()
+//                  - synchronization primitives.
+//   GTEST_IS_THREADSAFE - defined to 1 to indicate that the above
+//                         synchronization primitives have real implementations
+//                         and Google Test is thread-safe; or 0 otherwise.
+//
+// Template meta programming:
+//   is_pointer     - as in TR1; needed on Symbian and IBM XL C/C++ only.
+//   IteratorTraits - partial implementation of std::iterator_traits, which
+//                    is not available in libCstd when compiled with Sun C++.
+//
+// Smart pointers:
+//   scoped_ptr     - as in TR2.
+//
+// Regular expressions:
+//   RE             - a simple regular expression class using the POSIX
+//                    Extended Regular Expression syntax on UNIX-like
+//                    platforms, or a reduced regular exception syntax on
+//                    other platforms, including Windows.
+//
+// Logging:
+//   GTEST_LOG_()   - logs messages at the specified severity level.
+//   LogToStderr()  - directs all log messages to stderr.
+//   FlushInfoLog() - flushes informational log messages.
+//
+// Stdout and stderr capturing:
+//   CaptureStdout()     - starts capturing stdout.
+//   GetCapturedStdout() - stops capturing stdout and returns the captured
+//                         string.
+//   CaptureStderr()     - starts capturing stderr.
+//   GetCapturedStderr() - stops capturing stderr and returns the captured
+//                         string.
+//
+// Integer types:
+//   TypeWithSize   - maps an integer to a int type.
+//   Int32, UInt32, Int64, UInt64, TimeInMillis
+//                  - integers of known sizes.
+//   BiggestInt     - the biggest signed integer type.
+//
+// Command-line utilities:
+//   GTEST_FLAG()       - references a flag.
+//   GTEST_DECLARE_*()  - declares a flag.
+//   GTEST_DEFINE_*()   - defines a flag.
+//   GetArgvs()         - returns the command line as a vector of strings.
+//
+// Environment variable utilities:
+//   GetEnv()             - gets the value of an environment variable.
+//   BoolFromGTestEnv()   - parses a bool environment variable.
+//   Int32FromGTestEnv()  - parses an Int32 environment variable.
+//   StringFromGTestEnv() - parses a string environment variable.
+
+#include <ctype.h>   // for isspace, etc
+#include <stddef.h>  // for ptrdiff_t
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifndef _WIN32_WCE
+# include <sys/types.h>
+# include <sys/stat.h>
+#endif  // !_WIN32_WCE
+
+#include <iostream>  // NOLINT
+#include <sstream>  // NOLINT
+#include <string>  // NOLINT
+
+#define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com"
+#define GTEST_FLAG_PREFIX_ "gtest_"
+#define GTEST_FLAG_PREFIX_DASH_ "gtest-"
+#define GTEST_FLAG_PREFIX_UPPER_ "GTEST_"
+#define GTEST_NAME_ "Google Test"
+#define GTEST_PROJECT_URL_ "http://code.google.com/p/googletest/"
+
+// Determines the version of gcc that is used to compile this.
+#ifdef __GNUC__
+// 40302 means version 4.3.2.
+# define GTEST_GCC_VER_ \
+    (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__)
+#endif  // __GNUC__
+
+// Determines the platform on which Google Test is compiled.
+#ifdef __CYGWIN__
+# define GTEST_OS_CYGWIN 1
+#elif defined __SYMBIAN32__
+# define GTEST_OS_SYMBIAN 1
+#elif defined _WIN32
+# define GTEST_OS_WINDOWS 1
+# ifdef _WIN32_WCE
+#  define GTEST_OS_WINDOWS_MOBILE 1
+# elif defined(__MINGW__) || defined(__MINGW32__)
+#  define GTEST_OS_WINDOWS_MINGW 1
+# else
+#  define GTEST_OS_WINDOWS_DESKTOP 1
+# endif  // _WIN32_WCE
+#elif defined __APPLE__
+# define GTEST_OS_MAC 1
+#elif defined __linux__
+# define GTEST_OS_LINUX 1
+# ifdef ANDROID
+#  define GTEST_OS_LINUX_ANDROID 1
+# endif  // ANDROID
+#elif defined __MVS__
+# define GTEST_OS_ZOS 1
+#elif defined(__sun) && defined(__SVR4)
+# define GTEST_OS_SOLARIS 1
+#elif defined(_AIX)
+# define GTEST_OS_AIX 1
+#elif defined(__hpux)
+# define GTEST_OS_HPUX 1
+#elif defined __native_client__
+# define GTEST_OS_NACL 1
+#endif  // __CYGWIN__
+
+// Brings in definitions for functions used in the testing::internal::posix
+// namespace (read, write, close, chdir, isatty, stat). We do not currently
+// use them on Windows Mobile.
+#if !GTEST_OS_WINDOWS
+// This assumes that non-Windows OSes provide unistd.h. For OSes where this
+// is not the case, we need to include headers that provide the functions
+// mentioned above.
+# include <unistd.h>
+# if !GTEST_OS_NACL
+// TODO(vladl@google.com): Remove this condition when Native Client SDK adds
+// strings.h (tracked in
+// http://code.google.com/p/nativeclient/issues/detail?id=1175).
+#  include <strings.h>  // Native Client doesn't provide strings.h.
+# endif
+#elif !GTEST_OS_WINDOWS_MOBILE
+# include <direct.h>
+# include <io.h>
+#endif
+
+// Defines this to true iff Google Test can use POSIX regular expressions.
+#ifndef GTEST_HAS_POSIX_RE
+# define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS)
+#endif
+
+#if GTEST_HAS_POSIX_RE
+
+// On some platforms, <regex.h> needs someone to define size_t, and
+// won't compile otherwise.  We can #include it here as we already
+// included <stdlib.h>, which is guaranteed to define size_t through
+// <stddef.h>.
+# include <regex.h>  // NOLINT
+
+# define GTEST_USES_POSIX_RE 1
+
+#elif GTEST_OS_WINDOWS
+
+// <regex.h> is not available on Windows.  Use our own simple regex
+// implementation instead.
+# define GTEST_USES_SIMPLE_RE 1
+
+#else
+
+// <regex.h> may not be available on this platform.  Use our own
+// simple regex implementation instead.
+# define GTEST_USES_SIMPLE_RE 1
+
+#endif  // GTEST_HAS_POSIX_RE
+
+#ifndef GTEST_HAS_EXCEPTIONS
+// The user didn't tell us whether exceptions are enabled, so we need
+// to figure it out.
+# if defined(_MSC_VER) || defined(__BORLANDC__)
+// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS
+// macro to enable exceptions, so we'll do the same.
+// Assumes that exceptions are enabled by default.
+#  ifndef _HAS_EXCEPTIONS
+#   define _HAS_EXCEPTIONS 1
+#  endif  // _HAS_EXCEPTIONS
+#  define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS
+# elif defined(__GNUC__) && __EXCEPTIONS
+// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__SUNPRO_CC)
+// Sun Pro CC supports exceptions.  However, there is no compile-time way of
+// detecting whether they are enabled or not.  Therefore, we assume that
+// they are enabled unless the user tells us otherwise.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__IBMCPP__) && __EXCEPTIONS
+// xlC defines __EXCEPTIONS to 1 iff exceptions are enabled.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__HP_aCC)
+// Exception handling is in effect by default in HP aCC compiler. It has to
+// be turned of by +noeh compiler option if desired.
+#  define GTEST_HAS_EXCEPTIONS 1
+# else
+// For other compilers, we assume exceptions are disabled to be
+// conservative.
+#  define GTEST_HAS_EXCEPTIONS 0
+# endif  // defined(_MSC_VER) || defined(__BORLANDC__)
+#endif  // GTEST_HAS_EXCEPTIONS
+
+#if !defined(GTEST_HAS_STD_STRING)
+// Even though we don't use this macro any longer, we keep it in case
+// some clients still depend on it.
+# define GTEST_HAS_STD_STRING 1
+#elif !GTEST_HAS_STD_STRING
+// The user told us that ::std::string isn't available.
+# error "Google Test cannot be used where ::std::string isn't available."
+#endif  // !defined(GTEST_HAS_STD_STRING)
+
+#ifndef GTEST_HAS_GLOBAL_STRING
+// The user didn't tell us whether ::string is available, so we need
+// to figure it out.
+
+# define GTEST_HAS_GLOBAL_STRING 0
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+#ifndef GTEST_HAS_STD_WSTRING
+// The user didn't tell us whether ::std::wstring is available, so we need
+// to figure it out.
+// TODO(wan@google.com): uses autoconf to detect whether ::std::wstring
+//   is available.
+
+// Cygwin 1.7 and below doesn't support ::std::wstring.
+// Solaris' libc++ doesn't support it either.  Android has
+// no support for it at least as recent as Froyo (2.2).
+# define GTEST_HAS_STD_WSTRING \
+    (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS))
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+#ifndef GTEST_HAS_GLOBAL_WSTRING
+// The user didn't tell us whether ::wstring is available, so we need
+// to figure it out.
+# define GTEST_HAS_GLOBAL_WSTRING \
+    (GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING)
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+// Determines whether RTTI is available.
+#ifndef GTEST_HAS_RTTI
+// The user didn't tell us whether RTTI is enabled, so we need to
+// figure it out.
+
+# ifdef _MSC_VER
+
+#  ifdef _CPPRTTI  // MSVC defines this macro iff RTTI is enabled.
+#   define GTEST_HAS_RTTI 1
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif
+
+// Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled.
+# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302)
+
+#  ifdef __GXX_RTTI
+#   define GTEST_HAS_RTTI 1
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif  // __GXX_RTTI
+
+// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if
+// both the typeid and dynamic_cast features are present.
+# elif defined(__IBMCPP__) && (__IBMCPP__ >= 900)
+
+#  ifdef __RTTI_ALL__
+#   define GTEST_HAS_RTTI 1
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif
+
+# else
+
+// For all other compilers, we assume RTTI is enabled.
+#  define GTEST_HAS_RTTI 1
+
+# endif  // _MSC_VER
+
+#endif  // GTEST_HAS_RTTI
+
+// It's this header's responsibility to #include <typeinfo> when RTTI
+// is enabled.
+#if GTEST_HAS_RTTI
+# include <typeinfo>
+#endif
+
+// Determines whether Google Test can use the pthreads library.
+#ifndef GTEST_HAS_PTHREAD
+// The user didn't tell us explicitly, so we assume pthreads support is
+// available on Linux and Mac.
+//
+// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0
+// to your compiler flags.
+# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX)
+#endif  // GTEST_HAS_PTHREAD
+
+#if GTEST_HAS_PTHREAD
+// gtest-port.h guarantees to #include <pthread.h> when GTEST_HAS_PTHREAD is
+// true.
+# include <pthread.h>  // NOLINT
+
+// For timespec and nanosleep, used below.
+# include <time.h>  // NOLINT
+#endif
+
+// Determines whether Google Test can use tr1/tuple.  You can define
+// this macro to 0 to prevent Google Test from using tuple (any
+// feature depending on tuple with be disabled in this mode).
+#ifndef GTEST_HAS_TR1_TUPLE
+// The user didn't tell us not to do it, so we assume it's OK.
+# define GTEST_HAS_TR1_TUPLE 1
+#endif  // GTEST_HAS_TR1_TUPLE
+
+// Determines whether Google Test's own tr1 tuple implementation
+// should be used.
+#ifndef GTEST_USE_OWN_TR1_TUPLE
+// The user didn't tell us, so we need to figure it out.
+
+// We use our own TR1 tuple if we aren't sure the user has an
+// implementation of it already.  At this time, GCC 4.0.0+ and MSVC
+// 2010 are the only mainstream compilers that come with a TR1 tuple
+// implementation.  NVIDIA's CUDA NVCC compiler pretends to be GCC by
+// defining __GNUC__ and friends, but cannot compile GCC's tuple
+// implementation.  MSVC 2008 (9.0) provides TR1 tuple in a 323 MB
+// Feature Pack download, which we cannot assume the user has.
+# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000)) \
+    || _MSC_VER >= 1600
+#  define GTEST_USE_OWN_TR1_TUPLE 0
+# else
+#  define GTEST_USE_OWN_TR1_TUPLE 1
+# endif
+
+#endif  // GTEST_USE_OWN_TR1_TUPLE
+
+// To avoid conditional compilation everywhere, we make it
+// gtest-port.h's responsibility to #include the header implementing
+// tr1/tuple.
+#if GTEST_HAS_TR1_TUPLE
+
+# if GTEST_USE_OWN_TR1_TUPLE
+#  include "gtest/internal/gtest-tuple.h"
+# elif GTEST_OS_SYMBIAN
+
+// On Symbian, BOOST_HAS_TR1_TUPLE causes Boost's TR1 tuple library to
+// use STLport's tuple implementation, which unfortunately doesn't
+// work as the copy of STLport distributed with Symbian is incomplete.
+// By making sure BOOST_HAS_TR1_TUPLE is undefined, we force Boost to
+// use its own tuple implementation.
+#  ifdef BOOST_HAS_TR1_TUPLE
+#   undef BOOST_HAS_TR1_TUPLE
+#  endif  // BOOST_HAS_TR1_TUPLE
+
+// This prevents <boost/tr1/detail/config.hpp>, which defines
+// BOOST_HAS_TR1_TUPLE, from being #included by Boost's <tuple>.
+#  define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED
+#  include <tuple>
+
+# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000)
+// GCC 4.0+ implements tr1/tuple in the <tr1/tuple> header.  This does
+// not conform to the TR1 spec, which requires the header to be <tuple>.
+
+#  if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+// Until version 4.3.2, gcc has a bug that causes <tr1/functional>,
+// which is #included by <tr1/tuple>, to not compile when RTTI is
+// disabled.  _TR1_FUNCTIONAL is the header guard for
+// <tr1/functional>.  Hence the following #define is a hack to prevent
+// <tr1/functional> from being included.
+#   define _TR1_FUNCTIONAL 1
+#   include <tr1/tuple>
+#   undef _TR1_FUNCTIONAL  // Allows the user to #include
+                        // <tr1/functional> if he chooses to.
+#  else
+#   include <tr1/tuple>  // NOLINT
+#  endif  // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+
+# else
+// If the compiler is not GCC 4.0+, we assume the user is using a
+// spec-conforming TR1 implementation.
+#  include <tuple>  // NOLINT
+# endif  // GTEST_USE_OWN_TR1_TUPLE
+
+#endif  // GTEST_HAS_TR1_TUPLE
+
+// Determines whether clone(2) is supported.
+// Usually it will only be available on Linux, excluding
+// Linux on the Itanium architecture.
+// Also see http://linux.die.net/man/2/clone.
+#ifndef GTEST_HAS_CLONE
+// The user didn't tell us, so we need to figure it out.
+
+# if GTEST_OS_LINUX && !defined(__ia64__)
+#  define GTEST_HAS_CLONE 1
+# else
+#  define GTEST_HAS_CLONE 0
+# endif  // GTEST_OS_LINUX && !defined(__ia64__)
+
+#endif  // GTEST_HAS_CLONE
+
+// Determines whether to support stream redirection. This is used to test
+// output correctness and to implement death tests.
+#ifndef GTEST_HAS_STREAM_REDIRECTION
+// By default, we assume that stream redirection is supported on all
+// platforms except known mobile ones.
+# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN
+#  define GTEST_HAS_STREAM_REDIRECTION 0
+# else
+#  define GTEST_HAS_STREAM_REDIRECTION 1
+# endif  // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// Determines whether to support death tests.
+// Google Test does not support death tests for VC 7.1 and earlier as
+// abort() in a VC 7.1 application compiled as GUI in debug config
+// pops up a dialog window that cannot be suppressed programmatically.
+#if (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \
+     (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \
+     GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX)
+# define GTEST_HAS_DEATH_TEST 1
+# include <vector>  // NOLINT
+#endif
+
+// We don't support MSVC 7.1 with exceptions disabled now.  Therefore
+// all the compilers we care about are adequate for supporting
+// value-parameterized tests.
+#define GTEST_HAS_PARAM_TEST 1
+
+// Determines whether to support type-driven tests.
+
+// Typed tests need <typeinfo> and variadic macros, which GCC, VC++ 8.0,
+// Sun Pro CC, IBM Visual Age, and HP aCC support.
+#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \
+    defined(__IBMCPP__) || defined(__HP_aCC)
+# define GTEST_HAS_TYPED_TEST 1
+# define GTEST_HAS_TYPED_TEST_P 1
+#endif
+
+// Determines whether to support Combine(). This only makes sense when
+// value-parameterized tests are enabled.  The implementation doesn't
+// work on Sun Studio since it doesn't understand templated conversion
+// operators.
+#if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC)
+# define GTEST_HAS_COMBINE 1
+#endif
+
+// Determines whether the system compiler uses UTF-16 for encoding wide strings.
+#define GTEST_WIDE_STRING_USES_UTF16_ \
+    (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_SYMBIAN || GTEST_OS_AIX)
+
+// Determines whether test results can be streamed to a socket.
+#if GTEST_OS_LINUX
+# define GTEST_CAN_STREAM_RESULTS_ 1
+#endif
+
+// Defines some utility macros.
+
+// The GNU compiler emits a warning if nested "if" statements are followed by
+// an "else" statement and braces are not used to explicitly disambiguate the
+// "else" binding.  This leads to problems with code like:
+//
+//   if (gate)
+//     ASSERT_*(condition) << "Some message";
+//
+// The "switch (0) case 0:" idiom is used to suppress this.
+#ifdef __INTEL_COMPILER
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_
+#else
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default:  // NOLINT
+#endif
+
+// Use this annotation at the end of a struct/class definition to
+// prevent the compiler from optimizing away instances that are never
+// used.  This is useful when all interesting logic happens inside the
+// c'tor and / or d'tor.  Example:
+//
+//   struct Foo {
+//     Foo() { ... }
+//   } GTEST_ATTRIBUTE_UNUSED_;
+//
+// Also use it after a variable or parameter declaration to tell the
+// compiler the variable/parameter does not have to be used.
+#if defined(__GNUC__) && !defined(COMPILER_ICC)
+# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
+#else
+# define GTEST_ATTRIBUTE_UNUSED_
+#endif
+
+// A macro to disallow operator=
+// This should be used in the private: declarations for a class.
+#define GTEST_DISALLOW_ASSIGN_(type)\
+  void operator=(type const &)
+
+// A macro to disallow copy constructor and operator=
+// This should be used in the private: declarations for a class.
+#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)\
+  type(type const &);\
+  GTEST_DISALLOW_ASSIGN_(type)
+
+// Tell the compiler to warn about unused return values for functions declared
+// with this macro.  The macro should be used on function declarations
+// following the argument list:
+//
+//   Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_;
+#if defined(__GNUC__) && (GTEST_GCC_VER_ >= 30400) && !defined(COMPILER_ICC)
+# define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result))
+#else
+# define GTEST_MUST_USE_RESULT_
+#endif  // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC
+
+// Determine whether the compiler supports Microsoft's Structured Exception
+// Handling.  This is supported by several Windows compilers but generally
+// does not exist on any other system.
+#ifndef GTEST_HAS_SEH
+// The user didn't tell us, so we need to figure it out.
+
+# if defined(_MSC_VER) || defined(__BORLANDC__)
+// These two compilers are known to support SEH.
+#  define GTEST_HAS_SEH 1
+# else
+// Assume no SEH.
+#  define GTEST_HAS_SEH 0
+# endif
+
+#endif  // GTEST_HAS_SEH
+
+#ifdef _MSC_VER
+
+# if GTEST_LINKED_AS_SHARED_LIBRARY
+#  define GTEST_API_ __declspec(dllimport)
+# elif GTEST_CREATE_SHARED_LIBRARY
+#  define GTEST_API_ __declspec(dllexport)
+# endif
+
+#endif  // _MSC_VER
+
+#ifndef GTEST_API_
+# define GTEST_API_
+#endif
+
+#ifdef __GNUC__
+// Ask the compiler to never inline a given function.
+# define GTEST_NO_INLINE_ __attribute__((noinline))
+#else
+# define GTEST_NO_INLINE_
+#endif
+
+namespace testing {
+
+class Message;
+
+namespace internal {
+
+class String;
+
+// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time
+// expression is true. For example, you could use it to verify the
+// size of a static array:
+//
+//   GTEST_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
+//                         content_type_names_incorrect_size);
+//
+// or to make sure a struct is smaller than a certain size:
+//
+//   GTEST_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large);
+//
+// The second argument to the macro is the name of the variable. If
+// the expression is false, most compilers will issue a warning/error
+// containing the name of the variable.
+
+template <bool>
+struct CompileAssert {
+};
+
+#define GTEST_COMPILE_ASSERT_(expr, msg) \
+  typedef ::testing::internal::CompileAssert<(bool(expr))> \
+      msg[bool(expr) ? 1 : -1]
+
+// Implementation details of GTEST_COMPILE_ASSERT_:
+//
+// - GTEST_COMPILE_ASSERT_ works by defining an array type that has -1
+//   elements (and thus is invalid) when the expression is false.
+//
+// - The simpler definition
+//
+//    #define GTEST_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1]
+//
+//   does not work, as gcc supports variable-length arrays whose sizes
+//   are determined at run-time (this is gcc's extension and not part
+//   of the C++ standard).  As a result, gcc fails to reject the
+//   following code with the simple definition:
+//
+//     int foo;
+//     GTEST_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is
+//                                      // not a compile-time constant.
+//
+// - By using the type CompileAssert<(bool(expr))>, we ensures that
+//   expr is a compile-time constant.  (Template arguments must be
+//   determined at compile-time.)
+//
+// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
+//   to work around a bug in gcc 3.4.4 and 4.0.1.  If we had written
+//
+//     CompileAssert<bool(expr)>
+//
+//   instead, these compilers will refuse to compile
+//
+//     GTEST_COMPILE_ASSERT_(5 > 0, some_message);
+//
+//   (They seem to think the ">" in "5 > 0" marks the end of the
+//   template argument list.)
+//
+// - The array size is (bool(expr) ? 1 : -1), instead of simply
+//
+//     ((expr) ? 1 : -1).
+//
+//   This is to avoid running into a bug in MS VC 7.1, which
+//   causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
+
+// StaticAssertTypeEqHelper is used by StaticAssertTypeEq defined in gtest.h.
+//
+// This template is declared, but intentionally undefined.
+template <typename T1, typename T2>
+struct StaticAssertTypeEqHelper;
+
+template <typename T>
+struct StaticAssertTypeEqHelper<T, T> {};
+
+#if GTEST_HAS_GLOBAL_STRING
+typedef ::string string;
+#else
+typedef ::std::string string;
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+typedef ::wstring wstring;
+#elif GTEST_HAS_STD_WSTRING
+typedef ::std::wstring wstring;
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+// A helper for suppressing warnings on constant condition.  It just
+// returns 'condition'.
+GTEST_API_ bool IsTrue(bool condition);
+
+// Defines scoped_ptr.
+
+// This implementation of scoped_ptr is PARTIAL - it only contains
+// enough stuff to satisfy Google Test's need.
+template <typename T>
+class scoped_ptr {
+ public:
+  typedef T element_type;
+
+  explicit scoped_ptr(T* p = NULL) : ptr_(p) {}
+  ~scoped_ptr() { reset(); }
+
+  T& operator*() const { return *ptr_; }
+  T* operator->() const { return ptr_; }
+  T* get() const { return ptr_; }
+
+  T* release() {
+    T* const ptr = ptr_;
+    ptr_ = NULL;
+    return ptr;
+  }
+
+  void reset(T* p = NULL) {
+    if (p != ptr_) {
+      if (IsTrue(sizeof(T) > 0)) {  // Makes sure T is a complete type.
+        delete ptr_;
+      }
+      ptr_ = p;
+    }
+  }
+ private:
+  T* ptr_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(scoped_ptr);
+};
+
+// Defines RE.
+
+// A simple C++ wrapper for <regex.h>.  It uses the POSIX Extended
+// Regular Expression syntax.
+class GTEST_API_ RE {
+ public:
+  // A copy constructor is required by the Standard to initialize object
+  // references from r-values.
+  RE(const RE& other) { Init(other.pattern()); }
+
+  // Constructs an RE from a string.
+  RE(const ::std::string& regex) { Init(regex.c_str()); }  // NOLINT
+
+#if GTEST_HAS_GLOBAL_STRING
+
+  RE(const ::string& regex) { Init(regex.c_str()); }  // NOLINT
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+  RE(const char* regex) { Init(regex); }  // NOLINT
+  ~RE();
+
+  // Returns the string representation of the regex.
+  const char* pattern() const { return pattern_; }
+
+  // FullMatch(str, re) returns true iff regular expression re matches
+  // the entire str.
+  // PartialMatch(str, re) returns true iff regular expression re
+  // matches a substring of str (including str itself).
+  //
+  // TODO(wan@google.com): make FullMatch() and PartialMatch() work
+  // when str contains NUL characters.
+  static bool FullMatch(const ::std::string& str, const RE& re) {
+    return FullMatch(str.c_str(), re);
+  }
+  static bool PartialMatch(const ::std::string& str, const RE& re) {
+    return PartialMatch(str.c_str(), re);
+  }
+
+#if GTEST_HAS_GLOBAL_STRING
+
+  static bool FullMatch(const ::string& str, const RE& re) {
+    return FullMatch(str.c_str(), re);
+  }
+  static bool PartialMatch(const ::string& str, const RE& re) {
+    return PartialMatch(str.c_str(), re);
+  }
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+  static bool FullMatch(const char* str, const RE& re);
+  static bool PartialMatch(const char* str, const RE& re);
+
+ private:
+  void Init(const char* regex);
+
+  // We use a const char* instead of a string, as Google Test may be used
+  // where string is not available.  We also do not use Google Test's own
+  // String type here, in order to simplify dependencies between the
+  // files.
+  const char* pattern_;
+  bool is_valid_;
+
+#if GTEST_USES_POSIX_RE
+
+  regex_t full_regex_;     // For FullMatch().
+  regex_t partial_regex_;  // For PartialMatch().
+
+#else  // GTEST_USES_SIMPLE_RE
+
+  const char* full_pattern_;  // For FullMatch();
+
+#endif
+
+  GTEST_DISALLOW_ASSIGN_(RE);
+};
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line);
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file,
+                                                               int line);
+
+// Defines logging utilities:
+//   GTEST_LOG_(severity) - logs messages at the specified severity level. The
+//                          message itself is streamed into the macro.
+//   LogToStderr()  - directs all log messages to stderr.
+//   FlushInfoLog() - flushes informational log messages.
+
+enum GTestLogSeverity {
+  GTEST_INFO,
+  GTEST_WARNING,
+  GTEST_ERROR,
+  GTEST_FATAL
+};
+
+// Formats log entry severity, provides a stream object for streaming the
+// log message, and terminates the message with a newline when going out of
+// scope.
+class GTEST_API_ GTestLog {
+ public:
+  GTestLog(GTestLogSeverity severity, const char* file, int line);
+
+  // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
+  ~GTestLog();
+
+  ::std::ostream& GetStream() { return ::std::cerr; }
+
+ private:
+  const GTestLogSeverity severity_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestLog);
+};
+
+#define GTEST_LOG_(severity) \
+    ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \
+                                  __FILE__, __LINE__).GetStream()
+
+inline void LogToStderr() {}
+inline void FlushInfoLog() { fflush(NULL); }
+
+// INTERNAL IMPLEMENTATION - DO NOT USE.
+//
+// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition
+// is not satisfied.
+//  Synopsys:
+//    GTEST_CHECK_(boolean_condition);
+//     or
+//    GTEST_CHECK_(boolean_condition) << "Additional message";
+//
+//    This checks the condition and if the condition is not satisfied
+//    it prints message about the condition violation, including the
+//    condition itself, plus additional message streamed into it, if any,
+//    and then it aborts the program. It aborts the program irrespective of
+//    whether it is built in the debug mode or not.
+#define GTEST_CHECK_(condition) \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+    if (::testing::internal::IsTrue(condition)) \
+      ; \
+    else \
+      GTEST_LOG_(FATAL) << "Condition " #condition " failed. "
+
+// An all-mode assert to verify that the given POSIX-style function
+// call returns 0 (indicating success).  Known limitation: this
+// doesn't expand to a balanced 'if' statement, so enclose the macro
+// in {} if you need to use it as the only statement in an 'if'
+// branch.
+#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \
+  if (const int gtest_error = (posix_call)) \
+    GTEST_LOG_(FATAL) << #posix_call << "failed with error " \
+                      << gtest_error
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Use ImplicitCast_ as a safe version of static_cast for upcasting in
+// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a
+// const Foo*).  When you use ImplicitCast_, the compiler checks that
+// the cast is safe.  Such explicit ImplicitCast_s are necessary in
+// surprisingly many situations where C++ demands an exact type match
+// instead of an argument type convertable to a target type.
+//
+// The syntax for using ImplicitCast_ is the same as for static_cast:
+//
+//   ImplicitCast_<ToType>(expr)
+//
+// ImplicitCast_ would have been part of the C++ standard library,
+// but the proposal was submitted too late.  It will probably make
+// its way into the language in the future.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., implicit_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To>
+inline To ImplicitCast_(To x) { return x; }
+
+// When you upcast (that is, cast a pointer from type Foo to type
+// SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts
+// always succeed.  When you downcast (that is, cast a pointer from
+// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
+// how do you know the pointer is really of type SubclassOfFoo?  It
+// could be a bare Foo, or of type DifferentSubclassOfFoo.  Thus,
+// when you downcast, you should use this macro.  In debug mode, we
+// use dynamic_cast<> to double-check the downcast is legal (we die
+// if it's not).  In normal mode, we do the efficient static_cast<>
+// instead.  Thus, it's important to test in debug mode to make sure
+// the cast is legal!
+//    This is the only place in the code we should use dynamic_cast<>.
+// In particular, you SHOULDN'T be using dynamic_cast<> in order to
+// do RTTI (eg code like this:
+//    if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
+//    if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
+// You should design the code some other way not to need this.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., down_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To, typename From>  // use like this: DownCast_<T*>(foo);
+inline To DownCast_(From* f) {  // so we only accept pointers
+  // Ensures that To is a sub-type of From *.  This test is here only
+  // for compile-time type checking, and has no overhead in an
+  // optimized build at run-time, as it will be optimized away
+  // completely.
+  if (false) {
+    const To to = NULL;
+    ::testing::internal::ImplicitCast_<From*>(to);
+  }
+
+#if GTEST_HAS_RTTI
+  // RTTI: debug mode only!
+  GTEST_CHECK_(f == NULL || dynamic_cast<To>(f) != NULL);
+#endif
+  return static_cast<To>(f);
+}
+
+// Downcasts the pointer of type Base to Derived.
+// Derived must be a subclass of Base. The parameter MUST
+// point to a class of type Derived, not any subclass of it.
+// When RTTI is available, the function performs a runtime
+// check to enforce this.
+template <class Derived, class Base>
+Derived* CheckedDowncastToActualType(Base* base) {
+#if GTEST_HAS_RTTI
+  GTEST_CHECK_(typeid(*base) == typeid(Derived));
+  return dynamic_cast<Derived*>(base);  // NOLINT
+#else
+  return static_cast<Derived*>(base);  // Poor man's downcast.
+#endif
+}
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Defines the stderr capturer:
+//   CaptureStdout     - starts capturing stdout.
+//   GetCapturedStdout - stops capturing stdout and returns the captured string.
+//   CaptureStderr     - starts capturing stderr.
+//   GetCapturedStderr - stops capturing stderr and returns the captured string.
+//
+GTEST_API_ void CaptureStdout();
+GTEST_API_ String GetCapturedStdout();
+GTEST_API_ void CaptureStderr();
+GTEST_API_ String GetCapturedStderr();
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+
+#if GTEST_HAS_DEATH_TEST
+
+// A copy of all command line arguments.  Set by InitGoogleTest().
+extern ::std::vector<String> g_argvs;
+
+// GTEST_HAS_DEATH_TEST implies we have ::std::string.
+const ::std::vector<String>& GetArgvs();
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Defines synchronization primitives.
+
+#if GTEST_HAS_PTHREAD
+
+// Sleeps for (roughly) n milli-seconds.  This function is only for
+// testing Google Test's own constructs.  Don't use it in user tests,
+// either directly or indirectly.
+inline void SleepMilliseconds(int n) {
+  const timespec time = {
+    0,                  // 0 seconds.
+    n * 1000L * 1000L,  // And n ms.
+  };
+  nanosleep(&time, NULL);
+}
+
+// Allows a controller thread to pause execution of newly created
+// threads until notified.  Instances of this class must be created
+// and destroyed in the controller thread.
+//
+// This class is only for testing Google Test's own constructs. Do not
+// use it in user tests, either directly or indirectly.
+class Notification {
+ public:
+  Notification() : notified_(false) {}
+
+  // Notifies all threads created with this notification to start. Must
+  // be called from the controller thread.
+  void Notify() { notified_ = true; }
+
+  // Blocks until the controller thread notifies. Must be called from a test
+  // thread.
+  void WaitForNotification() {
+    while(!notified_) {
+      SleepMilliseconds(10);
+    }
+  }
+
+ private:
+  volatile bool notified_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification);
+};
+
+// As a C-function, ThreadFuncWithCLinkage cannot be templated itself.
+// Consequently, it cannot select a correct instantiation of ThreadWithParam
+// in order to call its Run(). Introducing ThreadWithParamBase as a
+// non-templated base class for ThreadWithParam allows us to bypass this
+// problem.
+class ThreadWithParamBase {
+ public:
+  virtual ~ThreadWithParamBase() {}
+  virtual void Run() = 0;
+};
+
+// pthread_create() accepts a pointer to a function type with the C linkage.
+// According to the Standard (7.5/1), function types with different linkages
+// are different even if they are otherwise identical.  Some compilers (for
+// example, SunStudio) treat them as different types.  Since class methods
+// cannot be defined with C-linkage we need to define a free C-function to
+// pass into pthread_create().
+extern "C" inline void* ThreadFuncWithCLinkage(void* thread) {
+  static_cast<ThreadWithParamBase*>(thread)->Run();
+  return NULL;
+}
+
+// Helper class for testing Google Test's multi-threading constructs.
+// To use it, write:
+//
+//   void ThreadFunc(int param) { /* Do things with param */ }
+//   Notification thread_can_start;
+//   ...
+//   // The thread_can_start parameter is optional; you can supply NULL.
+//   ThreadWithParam<int> thread(&ThreadFunc, 5, &thread_can_start);
+//   thread_can_start.Notify();
+//
+// These classes are only for testing Google Test's own constructs. Do
+// not use them in user tests, either directly or indirectly.
+template <typename T>
+class ThreadWithParam : public ThreadWithParamBase {
+ public:
+  typedef void (*UserThreadFunc)(T);
+
+  ThreadWithParam(
+      UserThreadFunc func, T param, Notification* thread_can_start)
+      : func_(func),
+        param_(param),
+        thread_can_start_(thread_can_start),
+        finished_(false) {
+    ThreadWithParamBase* const base = this;
+    // The thread can be created only after all fields except thread_
+    // have been initialized.
+    GTEST_CHECK_POSIX_SUCCESS_(
+        pthread_create(&thread_, 0, &ThreadFuncWithCLinkage, base));
+  }
+  ~ThreadWithParam() { Join(); }
+
+  void Join() {
+    if (!finished_) {
+      GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0));
+      finished_ = true;
+    }
+  }
+
+  virtual void Run() {
+    if (thread_can_start_ != NULL)
+      thread_can_start_->WaitForNotification();
+    func_(param_);
+  }
+
+ private:
+  const UserThreadFunc func_;  // User-supplied thread function.
+  const T param_;  // User-supplied parameter to the thread function.
+  // When non-NULL, used to block execution until the controller thread
+  // notifies.
+  Notification* const thread_can_start_;
+  bool finished_;  // true iff we know that the thread function has finished.
+  pthread_t thread_;  // The native thread object.
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam);
+};
+
+// MutexBase and Mutex implement mutex on pthreads-based platforms. They
+// are used in conjunction with class MutexLock:
+//
+//   Mutex mutex;
+//   ...
+//   MutexLock lock(&mutex);  // Acquires the mutex and releases it at the end
+//                            // of the current scope.
+//
+// MutexBase implements behavior for both statically and dynamically
+// allocated mutexes.  Do not use MutexBase directly.  Instead, write
+// the following to define a static mutex:
+//
+//   GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex);
+//
+// You can forward declare a static mutex like this:
+//
+//   GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex);
+//
+// To create a dynamic mutex, just define an object of type Mutex.
+class MutexBase {
+ public:
+  // Acquires this mutex.
+  void Lock() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_));
+    owner_ = pthread_self();
+  }
+
+  // Releases this mutex.
+  void Unlock() {
+    // We don't protect writing to owner_ here, as it's the caller's
+    // responsibility to ensure that the current thread holds the
+    // mutex when this is called.
+    owner_ = 0;
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_));
+  }
+
+  // Does nothing if the current thread holds the mutex. Otherwise, crashes
+  // with high probability.
+  void AssertHeld() const {
+    GTEST_CHECK_(owner_ == pthread_self())
+        << "The current thread is not holding the mutex @" << this;
+  }
+
+  // A static mutex may be used before main() is entered.  It may even
+  // be used before the dynamic initialization stage.  Therefore we
+  // must be able to initialize a static mutex object at link time.
+  // This means MutexBase has to be a POD and its member variables
+  // have to be public.
+ public:
+  pthread_mutex_t mutex_;  // The underlying pthread mutex.
+  pthread_t owner_;  // The thread holding the mutex; 0 means no one holds it.
+};
+
+// Forward-declares a static mutex.
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+    extern ::testing::internal::MutexBase mutex
+
+// Defines and statically (i.e. at link time) initializes a static mutex.
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
+    ::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, 0 }
+
+// The Mutex class can only be used for mutexes created at runtime. It
+// shares its API with MutexBase otherwise.
+class Mutex : public MutexBase {
+ public:
+  Mutex() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL));
+    owner_ = 0;
+  }
+  ~Mutex() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_));
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex);
+};
+
+// We cannot name this class MutexLock as the ctor declaration would
+// conflict with a macro named MutexLock, which is defined on some
+// platforms.  Hence the typedef trick below.
+class GTestMutexLock {
+ public:
+  explicit GTestMutexLock(MutexBase* mutex)
+      : mutex_(mutex) { mutex_->Lock(); }
+
+  ~GTestMutexLock() { mutex_->Unlock(); }
+
+ private:
+  MutexBase* const mutex_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock);
+};
+
+typedef GTestMutexLock MutexLock;
+
+// Helpers for ThreadLocal.
+
+// pthread_key_create() requires DeleteThreadLocalValue() to have
+// C-linkage.  Therefore it cannot be templatized to access
+// ThreadLocal<T>.  Hence the need for class
+// ThreadLocalValueHolderBase.
+class ThreadLocalValueHolderBase {
+ public:
+  virtual ~ThreadLocalValueHolderBase() {}
+};
+
+// Called by pthread to delete thread-local data stored by
+// pthread_setspecific().
+extern "C" inline void DeleteThreadLocalValue(void* value_holder) {
+  delete static_cast<ThreadLocalValueHolderBase*>(value_holder);
+}
+
+// Implements thread-local storage on pthreads-based systems.
+//
+//   // Thread 1
+//   ThreadLocal<int> tl(100);  // 100 is the default value for each thread.
+//
+//   // Thread 2
+//   tl.set(150);  // Changes the value for thread 2 only.
+//   EXPECT_EQ(150, tl.get());
+//
+//   // Thread 1
+//   EXPECT_EQ(100, tl.get());  // In thread 1, tl has the original value.
+//   tl.set(200);
+//   EXPECT_EQ(200, tl.get());
+//
+// The template type argument T must have a public copy constructor.
+// In addition, the default ThreadLocal constructor requires T to have
+// a public default constructor.
+//
+// An object managed for a thread by a ThreadLocal instance is deleted
+// when the thread exits.  Or, if the ThreadLocal instance dies in
+// that thread, when the ThreadLocal dies.  It's the user's
+// responsibility to ensure that all other threads using a ThreadLocal
+// have exited when it dies, or the per-thread objects for those
+// threads will not be deleted.
+//
+// Google Test only uses global ThreadLocal objects.  That means they
+// will die after main() has returned.  Therefore, no per-thread
+// object managed by Google Test will be leaked as long as all threads
+// using Google Test have exited when main() returns.
+template <typename T>
+class ThreadLocal {
+ public:
+  ThreadLocal() : key_(CreateKey()),
+                  default_() {}
+  explicit ThreadLocal(const T& value) : key_(CreateKey()),
+                                         default_(value) {}
+
+  ~ThreadLocal() {
+    // Destroys the managed object for the current thread, if any.
+    DeleteThreadLocalValue(pthread_getspecific(key_));
+
+    // Releases resources associated with the key.  This will *not*
+    // delete managed objects for other threads.
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_));
+  }
+
+  T* pointer() { return GetOrCreateValue(); }
+  const T* pointer() const { return GetOrCreateValue(); }
+  const T& get() const { return *pointer(); }
+  void set(const T& value) { *pointer() = value; }
+
+ private:
+  // Holds a value of type T.
+  class ValueHolder : public ThreadLocalValueHolderBase {
+   public:
+    explicit ValueHolder(const T& value) : value_(value) {}
+
+    T* pointer() { return &value_; }
+
+   private:
+    T value_;
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder);
+  };
+
+  static pthread_key_t CreateKey() {
+    pthread_key_t key;
+    // When a thread exits, DeleteThreadLocalValue() will be called on
+    // the object managed for that thread.
+    GTEST_CHECK_POSIX_SUCCESS_(
+        pthread_key_create(&key, &DeleteThreadLocalValue));
+    return key;
+  }
+
+  T* GetOrCreateValue() const {
+    ThreadLocalValueHolderBase* const holder =
+        static_cast<ThreadLocalValueHolderBase*>(pthread_getspecific(key_));
+    if (holder != NULL) {
+      return CheckedDowncastToActualType<ValueHolder>(holder)->pointer();
+    }
+
+    ValueHolder* const new_holder = new ValueHolder(default_);
+    ThreadLocalValueHolderBase* const holder_base = new_holder;
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base));
+    return new_holder->pointer();
+  }
+
+  // A key pthreads uses for looking up per-thread values.
+  const pthread_key_t key_;
+  const T default_;  // The default value for each thread.
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
+};
+
+# define GTEST_IS_THREADSAFE 1
+
+#else  // GTEST_HAS_PTHREAD
+
+// A dummy implementation of synchronization primitives (mutex, lock,
+// and thread-local variable).  Necessary for compiling Google Test where
+// mutex is not supported - using Google Test in multiple threads is not
+// supported on such platforms.
+
+class Mutex {
+ public:
+  Mutex() {}
+  void AssertHeld() const {}
+};
+
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+  extern ::testing::internal::Mutex mutex
+
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
+
+class GTestMutexLock {
+ public:
+  explicit GTestMutexLock(Mutex*) {}  // NOLINT
+};
+
+typedef GTestMutexLock MutexLock;
+
+template <typename T>
+class ThreadLocal {
+ public:
+  ThreadLocal() : value_() {}
+  explicit ThreadLocal(const T& value) : value_(value) {}
+  T* pointer() { return &value_; }
+  const T* pointer() const { return &value_; }
+  const T& get() const { return value_; }
+  void set(const T& value) { value_ = value; }
+ private:
+  T value_;
+};
+
+// The above synchronization primitives have dummy implementations.
+// Therefore Google Test is not thread-safe.
+# define GTEST_IS_THREADSAFE 0
+
+#endif  // GTEST_HAS_PTHREAD
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+GTEST_API_ size_t GetThreadCount();
+
+// Passing non-POD classes through ellipsis (...) crashes the ARM
+// compiler and generates a warning in Sun Studio.  The Nokia Symbian
+// and the IBM XL C/C++ compiler try to instantiate a copy constructor
+// for objects passed through ellipsis (...), failing for uncopyable
+// objects.  We define this to ensure that only POD is passed through
+// ellipsis on these systems.
+#if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC)
+// We lose support for NULL detection where the compiler doesn't like
+// passing non-POD classes through ellipsis (...).
+# define GTEST_ELLIPSIS_NEEDS_POD_ 1
+#else
+# define GTEST_CAN_COMPARE_NULL 1
+#endif
+
+// The Nokia Symbian and IBM XL C/C++ compilers cannot decide between
+// const T& and const T* in a function template.  These compilers
+// _can_ decide between class template specializations for T and T*,
+// so a tr1::type_traits-like is_pointer works.
+#if defined(__SYMBIAN32__) || defined(__IBMCPP__)
+# define GTEST_NEEDS_IS_POINTER_ 1
+#endif
+
+template <bool bool_value>
+struct bool_constant {
+  typedef bool_constant<bool_value> type;
+  static const bool value = bool_value;
+};
+template <bool bool_value> const bool bool_constant<bool_value>::value;
+
+typedef bool_constant<false> false_type;
+typedef bool_constant<true> true_type;
+
+template <typename T>
+struct is_pointer : public false_type {};
+
+template <typename T>
+struct is_pointer<T*> : public true_type {};
+
+template <typename Iterator>
+struct IteratorTraits {
+  typedef typename Iterator::value_type value_type;
+};
+
+template <typename T>
+struct IteratorTraits<T*> {
+  typedef T value_type;
+};
+
+template <typename T>
+struct IteratorTraits<const T*> {
+  typedef T value_type;
+};
+
+#if GTEST_OS_WINDOWS
+# define GTEST_PATH_SEP_ "\\"
+# define GTEST_HAS_ALT_PATH_SEP_ 1
+// The biggest signed integer type the compiler supports.
+typedef __int64 BiggestInt;
+#else
+# define GTEST_PATH_SEP_ "/"
+# define GTEST_HAS_ALT_PATH_SEP_ 0
+typedef long long BiggestInt;  // NOLINT
+#endif  // GTEST_OS_WINDOWS
+
+// Utilities for char.
+
+// isspace(int ch) and friends accept an unsigned char or EOF.  char
+// may be signed, depending on the compiler (or compiler flags).
+// Therefore we need to cast a char to unsigned char before calling
+// isspace(), etc.
+
+inline bool IsAlpha(char ch) {
+  return isalpha(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsAlNum(char ch) {
+  return isalnum(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsDigit(char ch) {
+  return isdigit(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsLower(char ch) {
+  return islower(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsSpace(char ch) {
+  return isspace(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsUpper(char ch) {
+  return isupper(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsXDigit(char ch) {
+  return isxdigit(static_cast<unsigned char>(ch)) != 0;
+}
+
+inline char ToLower(char ch) {
+  return static_cast<char>(tolower(static_cast<unsigned char>(ch)));
+}
+inline char ToUpper(char ch) {
+  return static_cast<char>(toupper(static_cast<unsigned char>(ch)));
+}
+
+// The testing::internal::posix namespace holds wrappers for common
+// POSIX functions.  These wrappers hide the differences between
+// Windows/MSVC and POSIX systems.  Since some compilers define these
+// standard functions as macros, the wrapper cannot have the same name
+// as the wrapped function.
+
+namespace posix {
+
+// Functions with a different name on Windows.
+
+#if GTEST_OS_WINDOWS
+
+typedef struct _stat StatStruct;
+
+# ifdef __BORLANDC__
+inline int IsATTY(int fd) { return isatty(fd); }
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return stricmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return strdup(src); }
+# else  // !__BORLANDC__
+#  if GTEST_OS_WINDOWS_MOBILE
+inline int IsATTY(int /* fd */) { return 0; }
+#  else
+inline int IsATTY(int fd) { return _isatty(fd); }
+#  endif  // GTEST_OS_WINDOWS_MOBILE
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return _stricmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return _strdup(src); }
+# endif  // __BORLANDC__
+
+# if GTEST_OS_WINDOWS_MOBILE
+inline int FileNo(FILE* file) { return reinterpret_cast<int>(_fileno(file)); }
+// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this
+// time and thus not defined there.
+# else
+inline int FileNo(FILE* file) { return _fileno(file); }
+inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); }
+inline int RmDir(const char* dir) { return _rmdir(dir); }
+inline bool IsDir(const StatStruct& st) {
+  return (_S_IFDIR & st.st_mode) != 0;
+}
+# endif  // GTEST_OS_WINDOWS_MOBILE
+
+#else
+
+typedef struct stat StatStruct;
+
+inline int FileNo(FILE* file) { return fileno(file); }
+inline int IsATTY(int fd) { return isatty(fd); }
+inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); }
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return strcasecmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return strdup(src); }
+inline int RmDir(const char* dir) { return rmdir(dir); }
+inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
+
+#endif  // GTEST_OS_WINDOWS
+
+// Functions deprecated by MSVC 8.0.
+
+#ifdef _MSC_VER
+// Temporarily disable warning 4996 (deprecated function).
+# pragma warning(push)
+# pragma warning(disable:4996)
+#endif
+
+inline const char* StrNCpy(char* dest, const char* src, size_t n) {
+  return strncpy(dest, src, n);
+}
+
+// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and
+// StrError() aren't needed on Windows CE at this time and thus not
+// defined there.
+
+#if !GTEST_OS_WINDOWS_MOBILE
+inline int ChDir(const char* dir) { return chdir(dir); }
+#endif
+inline FILE* FOpen(const char* path, const char* mode) {
+  return fopen(path, mode);
+}
+#if !GTEST_OS_WINDOWS_MOBILE
+inline FILE *FReopen(const char* path, const char* mode, FILE* stream) {
+  return freopen(path, mode, stream);
+}
+inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); }
+#endif
+inline int FClose(FILE* fp) { return fclose(fp); }
+#if !GTEST_OS_WINDOWS_MOBILE
+inline int Read(int fd, void* buf, unsigned int count) {
+  return static_cast<int>(read(fd, buf, count));
+}
+inline int Write(int fd, const void* buf, unsigned int count) {
+  return static_cast<int>(write(fd, buf, count));
+}
+inline int Close(int fd) { return close(fd); }
+inline const char* StrError(int errnum) { return strerror(errnum); }
+#endif
+inline const char* GetEnv(const char* name) {
+#if GTEST_OS_WINDOWS_MOBILE
+  // We are on Windows CE, which has no environment variables.
+  return NULL;
+#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
+  // Environment variables which we programmatically clear will be set to the
+  // empty string rather than unset (NULL).  Handle that case.
+  const char* const env = getenv(name);
+  return (env != NULL && env[0] != '\0') ? env : NULL;
+#else
+  return getenv(name);
+#endif
+}
+
+#ifdef _MSC_VER
+# pragma warning(pop)  // Restores the warning state.
+#endif
+
+#if GTEST_OS_WINDOWS_MOBILE
+// Windows CE has no C library. The abort() function is used in
+// several places in Google Test. This implementation provides a reasonable
+// imitation of standard behaviour.
+void Abort();
+#else
+inline void Abort() { abort(); }
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+}  // namespace posix
+
+// The maximum number a BiggestInt can represent.  This definition
+// works no matter BiggestInt is represented in one's complement or
+// two's complement.
+//
+// We cannot rely on numeric_limits in STL, as __int64 and long long
+// are not part of standard C++ and numeric_limits doesn't need to be
+// defined for them.
+const BiggestInt kMaxBiggestInt =
+    ~(static_cast<BiggestInt>(1) << (8*sizeof(BiggestInt) - 1));
+
+// This template class serves as a compile-time function from size to
+// type.  It maps a size in bytes to a primitive type with that
+// size. e.g.
+//
+//   TypeWithSize<4>::UInt
+//
+// is typedef-ed to be unsigned int (unsigned integer made up of 4
+// bytes).
+//
+// Such functionality should belong to STL, but I cannot find it
+// there.
+//
+// Google Test uses this class in the implementation of floating-point
+// comparison.
+//
+// For now it only handles UInt (unsigned int) as that's all Google Test
+// needs.  Other types can be easily added in the future if need
+// arises.
+template <size_t size>
+class TypeWithSize {
+ public:
+  // This prevents the user from using TypeWithSize<N> with incorrect
+  // values of N.
+  typedef void UInt;
+};
+
+// The specialization for size 4.
+template <>
+class TypeWithSize<4> {
+ public:
+  // unsigned int has size 4 in both gcc and MSVC.
+  //
+  // As base/basictypes.h doesn't compile on Windows, we cannot use
+  // uint32, uint64, and etc here.
+  typedef int Int;
+  typedef unsigned int UInt;
+};
+
+// The specialization for size 8.
+template <>
+class TypeWithSize<8> {
+ public:
+
+#if GTEST_OS_WINDOWS
+  typedef __int64 Int;
+  typedef unsigned __int64 UInt;
+#else
+  typedef long long Int;  // NOLINT
+  typedef unsigned long long UInt;  // NOLINT
+#endif  // GTEST_OS_WINDOWS
+};
+
+// Integer types of known sizes.
+typedef TypeWithSize<4>::Int Int32;
+typedef TypeWithSize<4>::UInt UInt32;
+typedef TypeWithSize<8>::Int Int64;
+typedef TypeWithSize<8>::UInt UInt64;
+typedef TypeWithSize<8>::Int TimeInMillis;  // Represents time in milliseconds.
+
+// Utilities for command line flags and environment variables.
+
+// Macro for referencing flags.
+#define GTEST_FLAG(name) FLAGS_gtest_##name
+
+// Macros for declaring flags.
+#define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name)
+#define GTEST_DECLARE_int32_(name) \
+    GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name)
+#define GTEST_DECLARE_string_(name) \
+    GTEST_API_ extern ::testing::internal::String GTEST_FLAG(name)
+
+// Macros for defining flags.
+#define GTEST_DEFINE_bool_(name, default_val, doc) \
+    GTEST_API_ bool GTEST_FLAG(name) = (default_val)
+#define GTEST_DEFINE_int32_(name, default_val, doc) \
+    GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val)
+#define GTEST_DEFINE_string_(name, default_val, doc) \
+    GTEST_API_ ::testing::internal::String GTEST_FLAG(name) = (default_val)
+
+// Parses 'str' for a 32-bit signed integer.  If successful, writes the result
+// to *value and returns true; otherwise leaves *value unchanged and returns
+// false.
+// TODO(chandlerc): Find a better way to refactor flag and environment parsing
+// out of both gtest-port.cc and gtest.cc to avoid exporting this utility
+// function.
+bool ParseInt32(const Message& src_text, const char* str, Int32* value);
+
+// Parses a bool/Int32/string from the environment variable
+// corresponding to the given Google Test flag.
+bool BoolFromGTestEnv(const char* flag, bool default_val);
+GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val);
+const char* StringFromGTestEnv(const char* flag, const char* default_val);
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
diff --git a/third_party/googletest/src/include/gtest/internal/gtest-string.h b/third_party/googletest/src/include/gtest/internal/gtest-string.h
new file mode 100644 (file)
index 0000000..dc3a07b
--- /dev/null
@@ -0,0 +1,350 @@
+// Copyright 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.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file declares the String class and functions used internally by
+// Google Test.  They are subject to change without notice. They should not used
+// by code external to Google Test.
+//
+// This header file is #included by <gtest/internal/gtest-internal.h>.
+// It should not be #included by other files.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+
+#ifdef __BORLANDC__
+// string.h is not guaranteed to provide strcpy on C++ Builder.
+# include <mem.h>
+#endif
+
+#include <string.h>
+#include "gtest/internal/gtest-port.h"
+
+#include <string>
+
+namespace testing {
+namespace internal {
+
+// String - a UTF-8 string class.
+//
+// For historic reasons, we don't use std::string.
+//
+// TODO(wan@google.com): replace this class with std::string or
+// implement it in terms of the latter.
+//
+// Note that String can represent both NULL and the empty string,
+// while std::string cannot represent NULL.
+//
+// NULL and the empty string are considered different.  NULL is less
+// than anything (including the empty string) except itself.
+//
+// This class only provides minimum functionality necessary for
+// implementing Google Test.  We do not intend to implement a full-fledged
+// string class here.
+//
+// Since the purpose of this class is to provide a substitute for
+// std::string on platforms where it cannot be used, we define a copy
+// constructor and assignment operators such that we don't need
+// conditional compilation in a lot of places.
+//
+// In order to make the representation efficient, the d'tor of String
+// is not virtual.  Therefore DO NOT INHERIT FROM String.
+class GTEST_API_ String {
+ public:
+  // Static utility methods
+
+  // Returns the input enclosed in double quotes if it's not NULL;
+  // otherwise returns "(null)".  For example, "\"Hello\"" is returned
+  // for input "Hello".
+  //
+  // This is useful for printing a C string in the syntax of a literal.
+  //
+  // Known issue: escape sequences are not handled yet.
+  static String ShowCStringQuoted(const char* c_str);
+
+  // Clones a 0-terminated C string, allocating memory using new.  The
+  // caller is responsible for deleting the return value using
+  // delete[].  Returns the cloned string, or NULL if the input is
+  // NULL.
+  //
+  // This is different from strdup() in string.h, which allocates
+  // memory using malloc().
+  static const char* CloneCString(const char* c_str);
+
+#if GTEST_OS_WINDOWS_MOBILE
+  // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be
+  // able to pass strings to Win32 APIs on CE we need to convert them
+  // to 'Unicode', UTF-16.
+
+  // Creates a UTF-16 wide string from the given ANSI string, allocating
+  // memory using new. The caller is responsible for deleting the return
+  // value using delete[]. Returns the wide string, or NULL if the
+  // input is NULL.
+  //
+  // The wide string is created using the ANSI codepage (CP_ACP) to
+  // match the behaviour of the ANSI versions of Win32 calls and the
+  // C runtime.
+  static LPCWSTR AnsiToUtf16(const char* c_str);
+
+  // Creates an ANSI string from the given wide string, allocating
+  // memory using new. The caller is responsible for deleting the return
+  // value using delete[]. Returns the ANSI string, or NULL if the
+  // input is NULL.
+  //
+  // The returned string is created using the ANSI codepage (CP_ACP) to
+  // match the behaviour of the ANSI versions of Win32 calls and the
+  // C runtime.
+  static const char* Utf16ToAnsi(LPCWSTR utf16_str);
+#endif
+
+  // Compares two C strings.  Returns true iff they have the same content.
+  //
+  // Unlike strcmp(), this function can handle NULL argument(s).  A
+  // NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool CStringEquals(const char* lhs, const char* rhs);
+
+  // Converts a wide C string to a String using the UTF-8 encoding.
+  // NULL will be converted to "(null)".  If an error occurred during
+  // the conversion, "(failed to convert from wide string)" is
+  // returned.
+  static String ShowWideCString(const wchar_t* wide_c_str);
+
+  // Similar to ShowWideCString(), except that this function encloses
+  // the converted string in double quotes.
+  static String ShowWideCStringQuoted(const wchar_t* wide_c_str);
+
+  // Compares two wide C strings.  Returns true iff they have the same
+  // content.
+  //
+  // Unlike wcscmp(), this function can handle NULL argument(s).  A
+  // NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs);
+
+  // Compares two C strings, ignoring case.  Returns true iff they
+  // have the same content.
+  //
+  // Unlike strcasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool CaseInsensitiveCStringEquals(const char* lhs,
+                                           const char* rhs);
+
+  // Compares two wide C strings, ignoring case.  Returns true iff they
+  // have the same content.
+  //
+  // Unlike wcscasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL wide C string,
+  // including the empty string.
+  // NB: The implementations on different platforms slightly differ.
+  // On windows, this method uses _wcsicmp which compares according to LC_CTYPE
+  // environment variable. On GNU platform this method uses wcscasecmp
+  // which compares according to LC_CTYPE category of the current locale.
+  // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
+  // current locale.
+  static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
+                                               const wchar_t* rhs);
+
+  // Formats a list of arguments to a String, using the same format
+  // spec string as for printf.
+  //
+  // We do not use the StringPrintf class as it is not universally
+  // available.
+  //
+  // The result is limited to 4096 characters (including the tailing
+  // 0).  If 4096 characters are not enough to format the input,
+  // "<buffer exceeded>" is returned.
+  static String Format(const char* format, ...);
+
+  // C'tors
+
+  // The default c'tor constructs a NULL string.
+  String() : c_str_(NULL), length_(0) {}
+
+  // Constructs a String by cloning a 0-terminated C string.
+  String(const char* a_c_str) {  // NOLINT
+    if (a_c_str == NULL) {
+      c_str_ = NULL;
+      length_ = 0;
+    } else {
+      ConstructNonNull(a_c_str, strlen(a_c_str));
+    }
+  }
+
+  // Constructs a String by copying a given number of chars from a
+  // buffer.  E.g. String("hello", 3) creates the string "hel",
+  // String("a\0bcd", 4) creates "a\0bc", String(NULL, 0) creates "",
+  // and String(NULL, 1) results in access violation.
+  String(const char* buffer, size_t a_length) {
+    ConstructNonNull(buffer, a_length);
+  }
+
+  // The copy c'tor creates a new copy of the string.  The two
+  // String objects do not share content.
+  String(const String& str) : c_str_(NULL), length_(0) { *this = str; }
+
+  // D'tor.  String is intended to be a final class, so the d'tor
+  // doesn't need to be virtual.
+  ~String() { delete[] c_str_; }
+
+  // Allows a String to be implicitly converted to an ::std::string or
+  // ::string, and vice versa.  Converting a String containing a NULL
+  // pointer to ::std::string or ::string is undefined behavior.
+  // Converting a ::std::string or ::string containing an embedded NUL
+  // character to a String will result in the prefix up to the first
+  // NUL character.
+  String(const ::std::string& str) {
+    ConstructNonNull(str.c_str(), str.length());
+  }
+
+  operator ::std::string() const { return ::std::string(c_str(), length()); }
+
+#if GTEST_HAS_GLOBAL_STRING
+  String(const ::string& str) {
+    ConstructNonNull(str.c_str(), str.length());
+  }
+
+  operator ::string() const { return ::string(c_str(), length()); }
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+  // Returns true iff this is an empty string (i.e. "").
+  bool empty() const { return (c_str() != NULL) && (length() == 0); }
+
+  // Compares this with another String.
+  // Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0
+  // if this is greater than rhs.
+  int Compare(const String& rhs) const;
+
+  // Returns true iff this String equals the given C string.  A NULL
+  // string and a non-NULL string are considered not equal.
+  bool operator==(const char* a_c_str) const { return Compare(a_c_str) == 0; }
+
+  // Returns true iff this String is less than the given String.  A
+  // NULL string is considered less than "".
+  bool operator<(const String& rhs) const { return Compare(rhs) < 0; }
+
+  // Returns true iff this String doesn't equal the given C string.  A NULL
+  // string and a non-NULL string are considered not equal.
+  bool operator!=(const char* a_c_str) const { return !(*this == a_c_str); }
+
+  // Returns true iff this String ends with the given suffix.  *Any*
+  // String is considered to end with a NULL or empty suffix.
+  bool EndsWith(const char* suffix) const;
+
+  // Returns true iff this String ends with the given suffix, not considering
+  // case. Any String is considered to end with a NULL or empty suffix.
+  bool EndsWithCaseInsensitive(const char* suffix) const;
+
+  // Returns the length of the encapsulated string, or 0 if the
+  // string is NULL.
+  size_t length() const { return length_; }
+
+  // Gets the 0-terminated C string this String object represents.
+  // The String object still owns the string.  Therefore the caller
+  // should NOT delete the return value.
+  const char* c_str() const { return c_str_; }
+
+  // Assigns a C string to this object.  Self-assignment works.
+  const String& operator=(const char* a_c_str) {
+    return *this = String(a_c_str);
+  }
+
+  // Assigns a String object to this object.  Self-assignment works.
+  const String& operator=(const String& rhs) {
+    if (this != &rhs) {
+      delete[] c_str_;
+      if (rhs.c_str() == NULL) {
+        c_str_ = NULL;
+        length_ = 0;
+      } else {
+        ConstructNonNull(rhs.c_str(), rhs.length());
+      }
+    }
+
+    return *this;
+  }
+
+ private:
+  // Constructs a non-NULL String from the given content.  This
+  // function can only be called when c_str_ has not been allocated.
+  // ConstructNonNull(NULL, 0) results in an empty string ("").
+  // ConstructNonNull(NULL, non_zero) is undefined behavior.
+  void ConstructNonNull(const char* buffer, size_t a_length) {
+    char* const str = new char[a_length + 1];
+    memcpy(str, buffer, a_length);
+    str[a_length] = '\0';
+    c_str_ = str;
+    length_ = a_length;
+  }
+
+  const char* c_str_;
+  size_t length_;
+};  // class String
+
+// Streams a String to an ostream.  Each '\0' character in the String
+// is replaced with "\\0".
+inline ::std::ostream& operator<<(::std::ostream& os, const String& str) {
+  if (str.c_str() == NULL) {
+    os << "(null)";
+  } else {
+    const char* const c_str = str.c_str();
+    for (size_t i = 0; i != str.length(); i++) {
+      if (c_str[i] == '\0') {
+        os << "\\0";
+      } else {
+        os << c_str[i];
+      }
+    }
+  }
+  return os;
+}
+
+// Gets the content of the stringstream's buffer as a String.  Each '\0'
+// character in the buffer is replaced with "\\0".
+GTEST_API_ String StringStreamToString(::std::stringstream* stream);
+
+// Converts a streamable value to a String.  A NULL pointer is
+// converted to "(null)".  When the input value is a ::string,
+// ::std::string, ::wstring, or ::std::wstring object, each NUL
+// character in it is replaced with "\\0".
+
+// Declared here but defined in gtest.h, so that it has access
+// to the definition of the Message class, required by the ARM
+// compiler.
+template <typename T>
+String StreamableToString(const T& streamable);
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
diff --git a/third_party/googletest/src/include/gtest/internal/gtest-tuple.h b/third_party/googletest/src/include/gtest/internal/gtest-tuple.h
new file mode 100644 (file)
index 0000000..d1af50e
--- /dev/null
@@ -0,0 +1,968 @@
+// This file was GENERATED by a script.  DO NOT EDIT BY HAND!!!
+
+// Copyright 2009 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: wan@google.com (Zhanyong Wan)
+
+// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+
+#include <utility>  // For ::std::pair.
+
+// The compiler used in Symbian has a bug that prevents us from declaring the
+// tuple template as a friend (it complains that tuple is redefined).  This
+// hack bypasses the bug by declaring the members that should otherwise be
+// private as public.
+// Sun Studio versions < 12 also have the above bug.
+#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
+#else
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
+    template <GTEST_10_TYPENAMES_(U)> friend class tuple; \
+   private:
+#endif
+
+// GTEST_n_TUPLE_(T) is the type of an n-tuple.
+#define GTEST_0_TUPLE_(T) tuple<>
+#define GTEST_1_TUPLE_(T) tuple<T##0, void, void, void, void, void, void, \
+    void, void, void>
+#define GTEST_2_TUPLE_(T) tuple<T##0, T##1, void, void, void, void, void, \
+    void, void, void>
+#define GTEST_3_TUPLE_(T) tuple<T##0, T##1, T##2, void, void, void, void, \
+    void, void, void>
+#define GTEST_4_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, void, void, void, \
+    void, void, void>
+#define GTEST_5_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, void, void, \
+    void, void, void>
+#define GTEST_6_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, void, \
+    void, void, void>
+#define GTEST_7_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    void, void, void>
+#define GTEST_8_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    T##7, void, void>
+#define GTEST_9_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    T##7, T##8, void>
+#define GTEST_10_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    T##7, T##8, T##9>
+
+// GTEST_n_TYPENAMES_(T) declares a list of n typenames.
+#define GTEST_0_TYPENAMES_(T)
+#define GTEST_1_TYPENAMES_(T) typename T##0
+#define GTEST_2_TYPENAMES_(T) typename T##0, typename T##1
+#define GTEST_3_TYPENAMES_(T) typename T##0, typename T##1, typename T##2
+#define GTEST_4_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3
+#define GTEST_5_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4
+#define GTEST_6_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5
+#define GTEST_7_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6
+#define GTEST_8_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6, typename T##7
+#define GTEST_9_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6, \
+    typename T##7, typename T##8
+#define GTEST_10_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6, \
+    typename T##7, typename T##8, typename T##9
+
+// In theory, defining stuff in the ::std namespace is undefined
+// behavior.  We can do this as we are playing the role of a standard
+// library vendor.
+namespace std {
+namespace tr1 {
+
+template <typename T0 = void, typename T1 = void, typename T2 = void,
+    typename T3 = void, typename T4 = void, typename T5 = void,
+    typename T6 = void, typename T7 = void, typename T8 = void,
+    typename T9 = void>
+class tuple;
+
+// Anything in namespace gtest_internal is Google Test's INTERNAL
+// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code.
+namespace gtest_internal {
+
+// ByRef<T>::type is T if T is a reference; otherwise it's const T&.
+template <typename T>
+struct ByRef { typedef const T& type; };  // NOLINT
+template <typename T>
+struct ByRef<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper for ByRef.
+#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type
+
+// AddRef<T>::type is T if T is a reference; otherwise it's T&.  This
+// is the same as tr1::add_reference<T>::type.
+template <typename T>
+struct AddRef { typedef T& type; };  // NOLINT
+template <typename T>
+struct AddRef<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper for AddRef.
+#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type
+
+// A helper for implementing get<k>().
+template <int k> class Get;
+
+// A helper for implementing tuple_element<k, T>.  kIndexValid is true
+// iff k < the number of fields in tuple type T.
+template <bool kIndexValid, int kIndex, class Tuple>
+struct TupleElement;
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 0, GTEST_10_TUPLE_(T)> { typedef T0 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 1, GTEST_10_TUPLE_(T)> { typedef T1 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 2, GTEST_10_TUPLE_(T)> { typedef T2 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 3, GTEST_10_TUPLE_(T)> { typedef T3 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 4, GTEST_10_TUPLE_(T)> { typedef T4 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 5, GTEST_10_TUPLE_(T)> { typedef T5 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 6, GTEST_10_TUPLE_(T)> { typedef T6 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 7, GTEST_10_TUPLE_(T)> { typedef T7 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 8, GTEST_10_TUPLE_(T)> { typedef T8 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 9, GTEST_10_TUPLE_(T)> { typedef T9 type; };
+
+}  // namespace gtest_internal
+
+template <>
+class tuple<> {
+ public:
+  tuple() {}
+  tuple(const tuple& /* t */)  {}
+  tuple& operator=(const tuple& /* t */) { return *this; }
+};
+
+template <GTEST_1_TYPENAMES_(T)>
+class GTEST_1_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {}
+
+  tuple(const tuple& t) : f0_(t.f0_) {}
+
+  template <GTEST_1_TYPENAMES_(U)>
+  tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_1_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_1_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_1_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    return *this;
+  }
+
+  T0 f0_;
+};
+
+template <GTEST_2_TYPENAMES_(T)>
+class GTEST_2_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0),
+      f1_(f1) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_) {}
+
+  template <GTEST_2_TYPENAMES_(U)>
+  tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {}
+  template <typename U0, typename U1>
+  tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_2_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_2_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+  template <typename U0, typename U1>
+  tuple& operator=(const ::std::pair<U0, U1>& p) {
+    f0_ = p.first;
+    f1_ = p.second;
+    return *this;
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_2_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+};
+
+template <GTEST_3_TYPENAMES_(T)>
+class GTEST_3_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {}
+
+  template <GTEST_3_TYPENAMES_(U)>
+  tuple(const GTEST_3_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_3_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_3_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_3_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_3_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+};
+
+template <GTEST_4_TYPENAMES_(T)>
+class GTEST_4_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2),
+      f3_(f3) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_) {}
+
+  template <GTEST_4_TYPENAMES_(U)>
+  tuple(const GTEST_4_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_4_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_4_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_4_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_4_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+};
+
+template <GTEST_5_TYPENAMES_(T)>
+class GTEST_5_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3,
+      GTEST_BY_REF_(T4) f4) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_) {}
+
+  template <GTEST_5_TYPENAMES_(U)>
+  tuple(const GTEST_5_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_5_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_5_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_5_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_5_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+};
+
+template <GTEST_6_TYPENAMES_(T)>
+class GTEST_6_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+      f5_(f5) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_) {}
+
+  template <GTEST_6_TYPENAMES_(U)>
+  tuple(const GTEST_6_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_6_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_6_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_6_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_6_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+};
+
+template <GTEST_7_TYPENAMES_(T)>
+class GTEST_7_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6) : f0_(f0), f1_(f1), f2_(f2),
+      f3_(f3), f4_(f4), f5_(f5), f6_(f6) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {}
+
+  template <GTEST_7_TYPENAMES_(U)>
+  tuple(const GTEST_7_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_7_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_7_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_7_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_7_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+};
+
+template <GTEST_8_TYPENAMES_(T)>
+class GTEST_8_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6,
+      GTEST_BY_REF_(T7) f7) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+      f5_(f5), f6_(f6), f7_(f7) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {}
+
+  template <GTEST_8_TYPENAMES_(U)>
+  tuple(const GTEST_8_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_8_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_8_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_8_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_8_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    f7_ = t.f7_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+  T7 f7_;
+};
+
+template <GTEST_9_TYPENAMES_(T)>
+class GTEST_9_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7,
+      GTEST_BY_REF_(T8) f8) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+      f5_(f5), f6_(f6), f7_(f7), f8_(f8) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {}
+
+  template <GTEST_9_TYPENAMES_(U)>
+  tuple(const GTEST_9_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_9_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_9_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_9_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_9_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    f7_ = t.f7_;
+    f8_ = t.f8_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+  T7 f7_;
+  T8 f8_;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+class tuple {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(),
+      f9_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7,
+      GTEST_BY_REF_(T8) f8, GTEST_BY_REF_(T9) f9) : f0_(f0), f1_(f1), f2_(f2),
+      f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7), f8_(f8), f9_(f9) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), f9_(t.f9_) {}
+
+  template <GTEST_10_TYPENAMES_(U)>
+  tuple(const GTEST_10_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_),
+      f9_(t.f9_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_10_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_10_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_10_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_10_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    f7_ = t.f7_;
+    f8_ = t.f8_;
+    f9_ = t.f9_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+  T7 f7_;
+  T8 f8_;
+  T9 f9_;
+};
+
+// 6.1.3.2 Tuple creation functions.
+
+// Known limitations: we don't support passing an
+// std::tr1::reference_wrapper<T> to make_tuple().  And we don't
+// implement tie().
+
+inline tuple<> make_tuple() { return tuple<>(); }
+
+template <GTEST_1_TYPENAMES_(T)>
+inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) {
+  return GTEST_1_TUPLE_(T)(f0);
+}
+
+template <GTEST_2_TYPENAMES_(T)>
+inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) {
+  return GTEST_2_TUPLE_(T)(f0, f1);
+}
+
+template <GTEST_3_TYPENAMES_(T)>
+inline GTEST_3_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2) {
+  return GTEST_3_TUPLE_(T)(f0, f1, f2);
+}
+
+template <GTEST_4_TYPENAMES_(T)>
+inline GTEST_4_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3) {
+  return GTEST_4_TUPLE_(T)(f0, f1, f2, f3);
+}
+
+template <GTEST_5_TYPENAMES_(T)>
+inline GTEST_5_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4) {
+  return GTEST_5_TUPLE_(T)(f0, f1, f2, f3, f4);
+}
+
+template <GTEST_6_TYPENAMES_(T)>
+inline GTEST_6_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5) {
+  return GTEST_6_TUPLE_(T)(f0, f1, f2, f3, f4, f5);
+}
+
+template <GTEST_7_TYPENAMES_(T)>
+inline GTEST_7_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6) {
+  return GTEST_7_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6);
+}
+
+template <GTEST_8_TYPENAMES_(T)>
+inline GTEST_8_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7) {
+  return GTEST_8_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7);
+}
+
+template <GTEST_9_TYPENAMES_(T)>
+inline GTEST_9_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7,
+    const T8& f8) {
+  return GTEST_9_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8);
+}
+
+template <GTEST_10_TYPENAMES_(T)>
+inline GTEST_10_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7,
+    const T8& f8, const T9& f9) {
+  return GTEST_10_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9);
+}
+
+// 6.1.3.3 Tuple helper classes.
+
+template <typename Tuple> struct tuple_size;
+
+template <GTEST_0_TYPENAMES_(T)>
+struct tuple_size<GTEST_0_TUPLE_(T)> { static const int value = 0; };
+
+template <GTEST_1_TYPENAMES_(T)>
+struct tuple_size<GTEST_1_TUPLE_(T)> { static const int value = 1; };
+
+template <GTEST_2_TYPENAMES_(T)>
+struct tuple_size<GTEST_2_TUPLE_(T)> { static const int value = 2; };
+
+template <GTEST_3_TYPENAMES_(T)>
+struct tuple_size<GTEST_3_TUPLE_(T)> { static const int value = 3; };
+
+template <GTEST_4_TYPENAMES_(T)>
+struct tuple_size<GTEST_4_TUPLE_(T)> { static const int value = 4; };
+
+template <GTEST_5_TYPENAMES_(T)>
+struct tuple_size<GTEST_5_TUPLE_(T)> { static const int value = 5; };
+
+template <GTEST_6_TYPENAMES_(T)>
+struct tuple_size<GTEST_6_TUPLE_(T)> { static const int value = 6; };
+
+template <GTEST_7_TYPENAMES_(T)>
+struct tuple_size<GTEST_7_TUPLE_(T)> { static const int value = 7; };
+
+template <GTEST_8_TYPENAMES_(T)>
+struct tuple_size<GTEST_8_TUPLE_(T)> { static const int value = 8; };
+
+template <GTEST_9_TYPENAMES_(T)>
+struct tuple_size<GTEST_9_TUPLE_(T)> { static const int value = 9; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct tuple_size<GTEST_10_TUPLE_(T)> { static const int value = 10; };
+
+template <int k, class Tuple>
+struct tuple_element {
+  typedef typename gtest_internal::TupleElement<
+      k < (tuple_size<Tuple>::value), k, Tuple>::type type;
+};
+
+#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
+
+// 6.1.3.4 Element access.
+
+namespace gtest_internal {
+
+template <>
+class Get<0> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple))
+  Field(Tuple& t) { return t.f0_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple))
+  ConstField(const Tuple& t) { return t.f0_; }
+};
+
+template <>
+class Get<1> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple))
+  Field(Tuple& t) { return t.f1_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple))
+  ConstField(const Tuple& t) { return t.f1_; }
+};
+
+template <>
+class Get<2> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple))
+  Field(Tuple& t) { return t.f2_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple))
+  ConstField(const Tuple& t) { return t.f2_; }
+};
+
+template <>
+class Get<3> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple))
+  Field(Tuple& t) { return t.f3_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple))
+  ConstField(const Tuple& t) { return t.f3_; }
+};
+
+template <>
+class Get<4> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple))
+  Field(Tuple& t) { return t.f4_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple))
+  ConstField(const Tuple& t) { return t.f4_; }
+};
+
+template <>
+class Get<5> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple))
+  Field(Tuple& t) { return t.f5_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple))
+  ConstField(const Tuple& t) { return t.f5_; }
+};
+
+template <>
+class Get<6> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple))
+  Field(Tuple& t) { return t.f6_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple))
+  ConstField(const Tuple& t) { return t.f6_; }
+};
+
+template <>
+class Get<7> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple))
+  Field(Tuple& t) { return t.f7_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple))
+  ConstField(const Tuple& t) { return t.f7_; }
+};
+
+template <>
+class Get<8> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple))
+  Field(Tuple& t) { return t.f8_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple))
+  ConstField(const Tuple& t) { return t.f8_; }
+};
+
+template <>
+class Get<9> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple))
+  Field(Tuple& t) { return t.f9_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple))
+  ConstField(const Tuple& t) { return t.f9_; }
+};
+
+}  // namespace gtest_internal
+
+template <int k, GTEST_10_TYPENAMES_(T)>
+GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T)))
+get(GTEST_10_TUPLE_(T)& t) {
+  return gtest_internal::Get<k>::Field(t);
+}
+
+template <int k, GTEST_10_TYPENAMES_(T)>
+GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k,  GTEST_10_TUPLE_(T)))
+get(const GTEST_10_TUPLE_(T)& t) {
+  return gtest_internal::Get<k>::ConstField(t);
+}
+
+// 6.1.3.5 Relational operators
+
+// We only implement == and !=, as we don't have a need for the rest yet.
+
+namespace gtest_internal {
+
+// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
+// first k fields of t1 equals the first k fields of t2.
+// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
+// k1 != k2.
+template <int kSize1, int kSize2>
+struct SameSizeTuplePrefixComparator;
+
+template <>
+struct SameSizeTuplePrefixComparator<0, 0> {
+  template <class Tuple1, class Tuple2>
+  static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
+    return true;
+  }
+};
+
+template <int k>
+struct SameSizeTuplePrefixComparator<k, k> {
+  template <class Tuple1, class Tuple2>
+  static bool Eq(const Tuple1& t1, const Tuple2& t2) {
+    return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
+        ::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
+  }
+};
+
+}  // namespace gtest_internal
+
+template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)>
+inline bool operator==(const GTEST_10_TUPLE_(T)& t,
+                       const GTEST_10_TUPLE_(U)& u) {
+  return gtest_internal::SameSizeTuplePrefixComparator<
+      tuple_size<GTEST_10_TUPLE_(T)>::value,
+      tuple_size<GTEST_10_TUPLE_(U)>::value>::Eq(t, u);
+}
+
+template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)>
+inline bool operator!=(const GTEST_10_TUPLE_(T)& t,
+                       const GTEST_10_TUPLE_(U)& u) { return !(t == u); }
+
+// 6.1.4 Pairs.
+// Unimplemented.
+
+}  // namespace tr1
+}  // namespace std
+
+#undef GTEST_0_TUPLE_
+#undef GTEST_1_TUPLE_
+#undef GTEST_2_TUPLE_
+#undef GTEST_3_TUPLE_
+#undef GTEST_4_TUPLE_
+#undef GTEST_5_TUPLE_
+#undef GTEST_6_TUPLE_
+#undef GTEST_7_TUPLE_
+#undef GTEST_8_TUPLE_
+#undef GTEST_9_TUPLE_
+#undef GTEST_10_TUPLE_
+
+#undef GTEST_0_TYPENAMES_
+#undef GTEST_1_TYPENAMES_
+#undef GTEST_2_TYPENAMES_
+#undef GTEST_3_TYPENAMES_
+#undef GTEST_4_TYPENAMES_
+#undef GTEST_5_TYPENAMES_
+#undef GTEST_6_TYPENAMES_
+#undef GTEST_7_TYPENAMES_
+#undef GTEST_8_TYPENAMES_
+#undef GTEST_9_TYPENAMES_
+#undef GTEST_10_TYPENAMES_
+
+#undef GTEST_DECLARE_TUPLE_AS_FRIEND_
+#undef GTEST_BY_REF_
+#undef GTEST_ADD_REF_
+#undef GTEST_TUPLE_ELEMENT_
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
diff --git a/third_party/googletest/src/include/gtest/internal/gtest-tuple.h.pump b/third_party/googletest/src/include/gtest/internal/gtest-tuple.h.pump
new file mode 100644 (file)
index 0000000..ef51909
--- /dev/null
@@ -0,0 +1,336 @@
+$$ -*- mode: c++; -*-
+$var n = 10  $$ Maximum number of tuple fields we want to support.
+$$ This meta comment fixes auto-indentation in Emacs. }}
+// Copyright 2009 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: wan@google.com (Zhanyong Wan)
+
+// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+
+#include <utility>  // For ::std::pair.
+
+// The compiler used in Symbian has a bug that prevents us from declaring the
+// tuple template as a friend (it complains that tuple is redefined).  This
+// hack bypasses the bug by declaring the members that should otherwise be
+// private as public.
+// Sun Studio versions < 12 also have the above bug.
+#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
+#else
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
+    template <GTEST_$(n)_TYPENAMES_(U)> friend class tuple; \
+   private:
+#endif
+
+
+$range i 0..n-1
+$range j 0..n
+$range k 1..n
+// GTEST_n_TUPLE_(T) is the type of an n-tuple.
+#define GTEST_0_TUPLE_(T) tuple<>
+
+$for k [[
+$range m 0..k-1
+$range m2 k..n-1
+#define GTEST_$(k)_TUPLE_(T) tuple<$for m, [[T##$m]]$for m2 [[, void]]>
+
+]]
+
+// GTEST_n_TYPENAMES_(T) declares a list of n typenames.
+
+$for j [[
+$range m 0..j-1
+#define GTEST_$(j)_TYPENAMES_(T) $for m, [[typename T##$m]]
+
+
+]]
+
+// In theory, defining stuff in the ::std namespace is undefined
+// behavior.  We can do this as we are playing the role of a standard
+// library vendor.
+namespace std {
+namespace tr1 {
+
+template <$for i, [[typename T$i = void]]>
+class tuple;
+
+// Anything in namespace gtest_internal is Google Test's INTERNAL
+// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code.
+namespace gtest_internal {
+
+// ByRef<T>::type is T if T is a reference; otherwise it's const T&.
+template <typename T>
+struct ByRef { typedef const T& type; };  // NOLINT
+template <typename T>
+struct ByRef<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper for ByRef.
+#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type
+
+// AddRef<T>::type is T if T is a reference; otherwise it's T&.  This
+// is the same as tr1::add_reference<T>::type.
+template <typename T>
+struct AddRef { typedef T& type; };  // NOLINT
+template <typename T>
+struct AddRef<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper for AddRef.
+#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type
+
+// A helper for implementing get<k>().
+template <int k> class Get;
+
+// A helper for implementing tuple_element<k, T>.  kIndexValid is true
+// iff k < the number of fields in tuple type T.
+template <bool kIndexValid, int kIndex, class Tuple>
+struct TupleElement;
+
+
+$for i [[
+template <GTEST_$(n)_TYPENAMES_(T)>
+struct TupleElement<true, $i, GTEST_$(n)_TUPLE_(T)> [[]]
+{ typedef T$i type; };
+
+
+]]
+}  // namespace gtest_internal
+
+template <>
+class tuple<> {
+ public:
+  tuple() {}
+  tuple(const tuple& /* t */)  {}
+  tuple& operator=(const tuple& /* t */) { return *this; }
+};
+
+
+$for k [[
+$range m 0..k-1
+template <GTEST_$(k)_TYPENAMES_(T)>
+class $if k < n [[GTEST_$(k)_TUPLE_(T)]] $else [[tuple]] {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : $for m, [[f$(m)_()]] {}
+
+  explicit tuple($for m, [[GTEST_BY_REF_(T$m) f$m]]) : [[]]
+$for m, [[f$(m)_(f$m)]] {}
+
+  tuple(const tuple& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
+
+  template <GTEST_$(k)_TYPENAMES_(U)>
+  tuple(const GTEST_$(k)_TUPLE_(U)& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
+
+$if k == 2 [[
+  template <typename U0, typename U1>
+  tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
+
+]]
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_$(k)_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_$(k)_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+$if k == 2 [[
+  template <typename U0, typename U1>
+  tuple& operator=(const ::std::pair<U0, U1>& p) {
+    f0_ = p.first;
+    f1_ = p.second;
+    return *this;
+  }
+
+]]
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_$(k)_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_$(k)_TUPLE_(U)& t) {
+
+$for m [[
+    f$(m)_ = t.f$(m)_;
+
+]]
+    return *this;
+  }
+
+
+$for m [[
+  T$m f$(m)_;
+
+]]
+};
+
+
+]]
+// 6.1.3.2 Tuple creation functions.
+
+// Known limitations: we don't support passing an
+// std::tr1::reference_wrapper<T> to make_tuple().  And we don't
+// implement tie().
+
+inline tuple<> make_tuple() { return tuple<>(); }
+
+$for k [[
+$range m 0..k-1
+
+template <GTEST_$(k)_TYPENAMES_(T)>
+inline GTEST_$(k)_TUPLE_(T) make_tuple($for m, [[const T$m& f$m]]) {
+  return GTEST_$(k)_TUPLE_(T)($for m, [[f$m]]);
+}
+
+]]
+
+// 6.1.3.3 Tuple helper classes.
+
+template <typename Tuple> struct tuple_size;
+
+
+$for j [[
+template <GTEST_$(j)_TYPENAMES_(T)>
+struct tuple_size<GTEST_$(j)_TUPLE_(T)> { static const int value = $j; };
+
+
+]]
+template <int k, class Tuple>
+struct tuple_element {
+  typedef typename gtest_internal::TupleElement<
+      k < (tuple_size<Tuple>::value), k, Tuple>::type type;
+};
+
+#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
+
+// 6.1.3.4 Element access.
+
+namespace gtest_internal {
+
+
+$for i [[
+template <>
+class Get<$i> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
+  Field(Tuple& t) { return t.f$(i)_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
+  ConstField(const Tuple& t) { return t.f$(i)_; }
+};
+
+
+]]
+}  // namespace gtest_internal
+
+template <int k, GTEST_$(n)_TYPENAMES_(T)>
+GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T)))
+get(GTEST_$(n)_TUPLE_(T)& t) {
+  return gtest_internal::Get<k>::Field(t);
+}
+
+template <int k, GTEST_$(n)_TYPENAMES_(T)>
+GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k,  GTEST_$(n)_TUPLE_(T)))
+get(const GTEST_$(n)_TUPLE_(T)& t) {
+  return gtest_internal::Get<k>::ConstField(t);
+}
+
+// 6.1.3.5 Relational operators
+
+// We only implement == and !=, as we don't have a need for the rest yet.
+
+namespace gtest_internal {
+
+// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
+// first k fields of t1 equals the first k fields of t2.
+// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
+// k1 != k2.
+template <int kSize1, int kSize2>
+struct SameSizeTuplePrefixComparator;
+
+template <>
+struct SameSizeTuplePrefixComparator<0, 0> {
+  template <class Tuple1, class Tuple2>
+  static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
+    return true;
+  }
+};
+
+template <int k>
+struct SameSizeTuplePrefixComparator<k, k> {
+  template <class Tuple1, class Tuple2>
+  static bool Eq(const Tuple1& t1, const Tuple2& t2) {
+    return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
+        ::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
+  }
+};
+
+}  // namespace gtest_internal
+
+template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
+inline bool operator==(const GTEST_$(n)_TUPLE_(T)& t,
+                       const GTEST_$(n)_TUPLE_(U)& u) {
+  return gtest_internal::SameSizeTuplePrefixComparator<
+      tuple_size<GTEST_$(n)_TUPLE_(T)>::value,
+      tuple_size<GTEST_$(n)_TUPLE_(U)>::value>::Eq(t, u);
+}
+
+template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
+inline bool operator!=(const GTEST_$(n)_TUPLE_(T)& t,
+                       const GTEST_$(n)_TUPLE_(U)& u) { return !(t == u); }
+
+// 6.1.4 Pairs.
+// Unimplemented.
+
+}  // namespace tr1
+}  // namespace std
+
+
+$for j [[
+#undef GTEST_$(j)_TUPLE_
+
+]]
+
+
+$for j [[
+#undef GTEST_$(j)_TYPENAMES_
+
+]]
+
+#undef GTEST_DECLARE_TUPLE_AS_FRIEND_
+#undef GTEST_BY_REF_
+#undef GTEST_ADD_REF_
+#undef GTEST_TUPLE_ELEMENT_
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
diff --git a/third_party/googletest/src/include/gtest/internal/gtest-type-util.h b/third_party/googletest/src/include/gtest/internal/gtest-type-util.h
new file mode 100644 (file)
index 0000000..b7b01b0
--- /dev/null
@@ -0,0 +1,3330 @@
+// This file was GENERATED by command:
+//     pump.py gtest-type-util.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008 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: wan@google.com (Zhanyong Wan)
+
+// Type utilities needed for implementing typed and type-parameterized
+// tests.  This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+// Currently we support at most 50 types in a list, and at most 50
+// type-parameterized tests in one type-parameterized test case.
+// Please contact googletestframework@googlegroups.com if you need
+// more.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-string.h"
+
+// #ifdef __GNUC__ is too general here.  It is possible to use gcc without using
+// libstdc++ (which is where cxxabi.h comes from).
+# ifdef __GLIBCXX__
+#  include <cxxabi.h>
+# elif defined(__HP_aCC)
+#  include <acxx_demangle.h>
+# endif  // __GLIBCXX__
+
+namespace testing {
+namespace internal {
+
+// GetTypeName<T>() returns a human-readable name of type T.
+// NB: This function is also used in Google Mock, so don't move it inside of
+// the typed-test-only section below.
+template <typename T>
+String GetTypeName() {
+# if GTEST_HAS_RTTI
+
+  const char* const name = typeid(T).name();
+#  if defined(__GLIBCXX__) || defined(__HP_aCC)
+  int status = 0;
+  // gcc's implementation of typeid(T).name() mangles the type name,
+  // so we have to demangle it.
+#   ifdef __GLIBCXX__
+  using abi::__cxa_demangle;
+#   endif // __GLIBCXX__
+  char* const readable_name = __cxa_demangle(name, 0, 0, &status);
+  const String name_str(status == 0 ? readable_name : name);
+  free(readable_name);
+  return name_str;
+#  else
+  return name;
+#  endif  // __GLIBCXX__ || __HP_aCC
+
+# else
+
+  return "<type>";
+
+# endif  // GTEST_HAS_RTTI
+}
+
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
+// type.  This can be used as a compile-time assertion to ensure that
+// two types are equal.
+
+template <typename T1, typename T2>
+struct AssertTypeEq;
+
+template <typename T>
+struct AssertTypeEq<T, T> {
+  typedef bool type;
+};
+
+// A unique type used as the default value for the arguments of class
+// template Types.  This allows us to simulate variadic templates
+// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
+// support directly.
+struct None {};
+
+// The following family of struct and struct templates are used to
+// represent type lists.  In particular, TypesN<T1, T2, ..., TN>
+// represents a type list with N types (T1, T2, ..., and TN) in it.
+// Except for Types0, every struct in the family has two member types:
+// Head for the first type in the list, and Tail for the rest of the
+// list.
+
+// The empty type list.
+struct Types0 {};
+
+// Type lists of length 1, 2, 3, and so on.
+
+template <typename T1>
+struct Types1 {
+  typedef T1 Head;
+  typedef Types0 Tail;
+};
+template <typename T1, typename T2>
+struct Types2 {
+  typedef T1 Head;
+  typedef Types1<T2> Tail;
+};
+
+template <typename T1, typename T2, typename T3>
+struct Types3 {
+  typedef T1 Head;
+  typedef Types2<T2, T3> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4>
+struct Types4 {
+  typedef T1 Head;
+  typedef Types3<T2, T3, T4> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+struct Types5 {
+  typedef T1 Head;
+  typedef Types4<T2, T3, T4, T5> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+struct Types6 {
+  typedef T1 Head;
+  typedef Types5<T2, T3, T4, T5, T6> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+struct Types7 {
+  typedef T1 Head;
+  typedef Types6<T2, T3, T4, T5, T6, T7> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+struct Types8 {
+  typedef T1 Head;
+  typedef Types7<T2, T3, T4, T5, T6, T7, T8> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+struct Types9 {
+  typedef T1 Head;
+  typedef Types8<T2, T3, T4, T5, T6, T7, T8, T9> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+struct Types10 {
+  typedef T1 Head;
+  typedef Types9<T2, T3, T4, T5, T6, T7, T8, T9, T10> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+struct Types11 {
+  typedef T1 Head;
+  typedef Types10<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+struct Types12 {
+  typedef T1 Head;
+  typedef Types11<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+struct Types13 {
+  typedef T1 Head;
+  typedef Types12<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+struct Types14 {
+  typedef T1 Head;
+  typedef Types13<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Types15 {
+  typedef T1 Head;
+  typedef Types14<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+struct Types16 {
+  typedef T1 Head;
+  typedef Types15<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+struct Types17 {
+  typedef T1 Head;
+  typedef Types16<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+struct Types18 {
+  typedef T1 Head;
+  typedef Types17<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+struct Types19 {
+  typedef T1 Head;
+  typedef Types18<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+struct Types20 {
+  typedef T1 Head;
+  typedef Types19<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+struct Types21 {
+  typedef T1 Head;
+  typedef Types20<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+struct Types22 {
+  typedef T1 Head;
+  typedef Types21<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+struct Types23 {
+  typedef T1 Head;
+  typedef Types22<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+struct Types24 {
+  typedef T1 Head;
+  typedef Types23<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+struct Types25 {
+  typedef T1 Head;
+  typedef Types24<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+struct Types26 {
+  typedef T1 Head;
+  typedef Types25<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+struct Types27 {
+  typedef T1 Head;
+  typedef Types26<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+struct Types28 {
+  typedef T1 Head;
+  typedef Types27<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+struct Types29 {
+  typedef T1 Head;
+  typedef Types28<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+struct Types30 {
+  typedef T1 Head;
+  typedef Types29<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+struct Types31 {
+  typedef T1 Head;
+  typedef Types30<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+struct Types32 {
+  typedef T1 Head;
+  typedef Types31<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+struct Types33 {
+  typedef T1 Head;
+  typedef Types32<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+struct Types34 {
+  typedef T1 Head;
+  typedef Types33<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+struct Types35 {
+  typedef T1 Head;
+  typedef Types34<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+struct Types36 {
+  typedef T1 Head;
+  typedef Types35<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+struct Types37 {
+  typedef T1 Head;
+  typedef Types36<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+struct Types38 {
+  typedef T1 Head;
+  typedef Types37<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+struct Types39 {
+  typedef T1 Head;
+  typedef Types38<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+struct Types40 {
+  typedef T1 Head;
+  typedef Types39<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+struct Types41 {
+  typedef T1 Head;
+  typedef Types40<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+struct Types42 {
+  typedef T1 Head;
+  typedef Types41<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+struct Types43 {
+  typedef T1 Head;
+  typedef Types42<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+struct Types44 {
+  typedef T1 Head;
+  typedef Types43<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+struct Types45 {
+  typedef T1 Head;
+  typedef Types44<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+struct Types46 {
+  typedef T1 Head;
+  typedef Types45<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+struct Types47 {
+  typedef T1 Head;
+  typedef Types46<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+struct Types48 {
+  typedef T1 Head;
+  typedef Types47<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47, T48> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+struct Types49 {
+  typedef T1 Head;
+  typedef Types48<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47, T48, T49> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+struct Types50 {
+  typedef T1 Head;
+  typedef Types49<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47, T48, T49, T50> Tail;
+};
+
+
+}  // namespace internal
+
+// We don't want to require the users to write TypesN<...> directly,
+// as that would require them to count the length.  Types<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Types<int>
+// will appear as Types<int, None, None, ..., None> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Types<T1, ..., TN>, and Google Test will translate
+// that to TypesN<T1, ..., TN> internally to make error messages
+// readable.  The translation is done by the 'type' member of the
+// Types template.
+template <typename T1 = internal::None, typename T2 = internal::None,
+    typename T3 = internal::None, typename T4 = internal::None,
+    typename T5 = internal::None, typename T6 = internal::None,
+    typename T7 = internal::None, typename T8 = internal::None,
+    typename T9 = internal::None, typename T10 = internal::None,
+    typename T11 = internal::None, typename T12 = internal::None,
+    typename T13 = internal::None, typename T14 = internal::None,
+    typename T15 = internal::None, typename T16 = internal::None,
+    typename T17 = internal::None, typename T18 = internal::None,
+    typename T19 = internal::None, typename T20 = internal::None,
+    typename T21 = internal::None, typename T22 = internal::None,
+    typename T23 = internal::None, typename T24 = internal::None,
+    typename T25 = internal::None, typename T26 = internal::None,
+    typename T27 = internal::None, typename T28 = internal::None,
+    typename T29 = internal::None, typename T30 = internal::None,
+    typename T31 = internal::None, typename T32 = internal::None,
+    typename T33 = internal::None, typename T34 = internal::None,
+    typename T35 = internal::None, typename T36 = internal::None,
+    typename T37 = internal::None, typename T38 = internal::None,
+    typename T39 = internal::None, typename T40 = internal::None,
+    typename T41 = internal::None, typename T42 = internal::None,
+    typename T43 = internal::None, typename T44 = internal::None,
+    typename T45 = internal::None, typename T46 = internal::None,
+    typename T47 = internal::None, typename T48 = internal::None,
+    typename T49 = internal::None, typename T50 = internal::None>
+struct Types {
+  typedef internal::Types50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48, T49, T50> type;
+};
+
+template <>
+struct Types<internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types0 type;
+};
+template <typename T1>
+struct Types<T1, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types1<T1> type;
+};
+template <typename T1, typename T2>
+struct Types<T1, T2, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types2<T1, T2> type;
+};
+template <typename T1, typename T2, typename T3>
+struct Types<T1, T2, T3, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types3<T1, T2, T3> type;
+};
+template <typename T1, typename T2, typename T3, typename T4>
+struct Types<T1, T2, T3, T4, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types4<T1, T2, T3, T4> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+struct Types<T1, T2, T3, T4, T5, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types5<T1, T2, T3, T4, T5> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+struct Types<T1, T2, T3, T4, T5, T6, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types6<T1, T2, T3, T4, T5, T6> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+struct Types<T1, T2, T3, T4, T5, T6, T7, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types7<T1, T2, T3, T4, T5, T6, T7> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types8<T1, T2, T3, T4, T5, T6, T7, T8> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types9<T1, T2, T3, T4, T5, T6, T7, T8, T9> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, T47, internal::None, internal::None, internal::None> {
+  typedef internal::Types47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, T47, T48, internal::None, internal::None> {
+  typedef internal::Types48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, T47, T48, T49, internal::None> {
+  typedef internal::Types49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48, T49> type;
+};
+
+namespace internal {
+
+# define GTEST_TEMPLATE_ template <typename T> class
+
+// The template "selector" struct TemplateSel<Tmpl> is used to
+// represent Tmpl, which must be a class template with one type
+// parameter, as a type.  TemplateSel<Tmpl>::Bind<T>::type is defined
+// as the type Tmpl<T>.  This allows us to actually instantiate the
+// template "selected" by TemplateSel<Tmpl>.
+//
+// This trick is necessary for simulating typedef for class templates,
+// which C++ doesn't support directly.
+template <GTEST_TEMPLATE_ Tmpl>
+struct TemplateSel {
+  template <typename T>
+  struct Bind {
+    typedef Tmpl<T> type;
+  };
+};
+
+# define GTEST_BIND_(TmplSel, T) \
+  TmplSel::template Bind<T>::type
+
+// A unique struct template used as the default value for the
+// arguments of class template Templates.  This allows us to simulate
+// variadic templates (e.g. Templates<int>, Templates<int, double>,
+// and etc), which C++ doesn't support directly.
+template <typename T>
+struct NoneT {};
+
+// The following family of struct and struct templates are used to
+// represent template lists.  In particular, TemplatesN<T1, T2, ...,
+// TN> represents a list of N templates (T1, T2, ..., and TN).  Except
+// for Templates0, every struct in the family has two member types:
+// Head for the selector of the first template in the list, and Tail
+// for the rest of the list.
+
+// The empty template list.
+struct Templates0 {};
+
+// Template lists of length 1, 2, 3, and so on.
+
+template <GTEST_TEMPLATE_ T1>
+struct Templates1 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates0 Tail;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2>
+struct Templates2 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates1<T2> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3>
+struct Templates3 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates2<T2, T3> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4>
+struct Templates4 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates3<T2, T3, T4> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5>
+struct Templates5 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates4<T2, T3, T4, T5> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6>
+struct Templates6 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates5<T2, T3, T4, T5, T6> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7>
+struct Templates7 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates6<T2, T3, T4, T5, T6, T7> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8>
+struct Templates8 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates7<T2, T3, T4, T5, T6, T7, T8> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9>
+struct Templates9 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates8<T2, T3, T4, T5, T6, T7, T8, T9> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10>
+struct Templates10 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates9<T2, T3, T4, T5, T6, T7, T8, T9, T10> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11>
+struct Templates11 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates10<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12>
+struct Templates12 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates11<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13>
+struct Templates13 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates12<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14>
+struct Templates14 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates13<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15>
+struct Templates15 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates14<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16>
+struct Templates16 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates15<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17>
+struct Templates17 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates16<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18>
+struct Templates18 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates17<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19>
+struct Templates19 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates18<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20>
+struct Templates20 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates19<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21>
+struct Templates21 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates20<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22>
+struct Templates22 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates21<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23>
+struct Templates23 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates22<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24>
+struct Templates24 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates23<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25>
+struct Templates25 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates24<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26>
+struct Templates26 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates25<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27>
+struct Templates27 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates26<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28>
+struct Templates28 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates27<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29>
+struct Templates29 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates28<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30>
+struct Templates30 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates29<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31>
+struct Templates31 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates30<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32>
+struct Templates32 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates31<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33>
+struct Templates33 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates32<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34>
+struct Templates34 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates33<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35>
+struct Templates35 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates34<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36>
+struct Templates36 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates35<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37>
+struct Templates37 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates36<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38>
+struct Templates38 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates37<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39>
+struct Templates39 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates38<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40>
+struct Templates40 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates39<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41>
+struct Templates41 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates40<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42>
+struct Templates42 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates41<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43>
+struct Templates43 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates42<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44>
+struct Templates44 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates43<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45>
+struct Templates45 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates44<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46>
+struct Templates46 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates45<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47>
+struct Templates47 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates46<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48>
+struct Templates48 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates47<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47, T48> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+    GTEST_TEMPLATE_ T49>
+struct Templates49 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates48<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47, T48, T49> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+    GTEST_TEMPLATE_ T49, GTEST_TEMPLATE_ T50>
+struct Templates50 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates49<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47, T48, T49, T50> Tail;
+};
+
+
+// We don't want to require the users to write TemplatesN<...> directly,
+// as that would require them to count the length.  Templates<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Templates<list>
+// will appear as Templates<list, NoneT, NoneT, ..., NoneT> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Templates<T1, ..., TN>, and Google Test will translate
+// that to TemplatesN<T1, ..., TN> internally to make error messages
+// readable.  The translation is done by the 'type' member of the
+// Templates template.
+template <GTEST_TEMPLATE_ T1 = NoneT, GTEST_TEMPLATE_ T2 = NoneT,
+    GTEST_TEMPLATE_ T3 = NoneT, GTEST_TEMPLATE_ T4 = NoneT,
+    GTEST_TEMPLATE_ T5 = NoneT, GTEST_TEMPLATE_ T6 = NoneT,
+    GTEST_TEMPLATE_ T7 = NoneT, GTEST_TEMPLATE_ T8 = NoneT,
+    GTEST_TEMPLATE_ T9 = NoneT, GTEST_TEMPLATE_ T10 = NoneT,
+    GTEST_TEMPLATE_ T11 = NoneT, GTEST_TEMPLATE_ T12 = NoneT,
+    GTEST_TEMPLATE_ T13 = NoneT, GTEST_TEMPLATE_ T14 = NoneT,
+    GTEST_TEMPLATE_ T15 = NoneT, GTEST_TEMPLATE_ T16 = NoneT,
+    GTEST_TEMPLATE_ T17 = NoneT, GTEST_TEMPLATE_ T18 = NoneT,
+    GTEST_TEMPLATE_ T19 = NoneT, GTEST_TEMPLATE_ T20 = NoneT,
+    GTEST_TEMPLATE_ T21 = NoneT, GTEST_TEMPLATE_ T22 = NoneT,
+    GTEST_TEMPLATE_ T23 = NoneT, GTEST_TEMPLATE_ T24 = NoneT,
+    GTEST_TEMPLATE_ T25 = NoneT, GTEST_TEMPLATE_ T26 = NoneT,
+    GTEST_TEMPLATE_ T27 = NoneT, GTEST_TEMPLATE_ T28 = NoneT,
+    GTEST_TEMPLATE_ T29 = NoneT, GTEST_TEMPLATE_ T30 = NoneT,
+    GTEST_TEMPLATE_ T31 = NoneT, GTEST_TEMPLATE_ T32 = NoneT,
+    GTEST_TEMPLATE_ T33 = NoneT, GTEST_TEMPLATE_ T34 = NoneT,
+    GTEST_TEMPLATE_ T35 = NoneT, GTEST_TEMPLATE_ T36 = NoneT,
+    GTEST_TEMPLATE_ T37 = NoneT, GTEST_TEMPLATE_ T38 = NoneT,
+    GTEST_TEMPLATE_ T39 = NoneT, GTEST_TEMPLATE_ T40 = NoneT,
+    GTEST_TEMPLATE_ T41 = NoneT, GTEST_TEMPLATE_ T42 = NoneT,
+    GTEST_TEMPLATE_ T43 = NoneT, GTEST_TEMPLATE_ T44 = NoneT,
+    GTEST_TEMPLATE_ T45 = NoneT, GTEST_TEMPLATE_ T46 = NoneT,
+    GTEST_TEMPLATE_ T47 = NoneT, GTEST_TEMPLATE_ T48 = NoneT,
+    GTEST_TEMPLATE_ T49 = NoneT, GTEST_TEMPLATE_ T50 = NoneT>
+struct Templates {
+  typedef Templates50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47, T48, T49, T50> type;
+};
+
+template <>
+struct Templates<NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates0 type;
+};
+template <GTEST_TEMPLATE_ T1>
+struct Templates<T1, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates1<T1> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2>
+struct Templates<T1, T2, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates2<T1, T2> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3>
+struct Templates<T1, T2, T3, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates3<T1, T2, T3> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4>
+struct Templates<T1, T2, T3, T4, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates4<T1, T2, T3, T4> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5>
+struct Templates<T1, T2, T3, T4, T5, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates5<T1, T2, T3, T4, T5> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6>
+struct Templates<T1, T2, T3, T4, T5, T6, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates6<T1, T2, T3, T4, T5, T6> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates7<T1, T2, T3, T4, T5, T6, T7> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates8<T1, T2, T3, T4, T5, T6, T7, T8> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates9<T1, T2, T3, T4, T5, T6, T7, T8, T9> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT> {
+  typedef Templates22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT> {
+  typedef Templates23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT> {
+  typedef Templates24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, T47, NoneT, NoneT, NoneT> {
+  typedef Templates47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, T47, T48, NoneT, NoneT> {
+  typedef Templates48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47, T48> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+    GTEST_TEMPLATE_ T49>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, T47, T48, T49, NoneT> {
+  typedef Templates49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47, T48, T49> type;
+};
+
+// The TypeList template makes it possible to use either a single type
+// or a Types<...> list in TYPED_TEST_CASE() and
+// INSTANTIATE_TYPED_TEST_CASE_P().
+
+template <typename T>
+struct TypeList { typedef Types1<T> type; };
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+struct TypeList<Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48, T49, T50> > {
+  typedef typename Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>::type type;
+};
+
+#endif  // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
diff --git a/third_party/googletest/src/include/gtest/internal/gtest-type-util.h.pump b/third_party/googletest/src/include/gtest/internal/gtest-type-util.h.pump
new file mode 100644 (file)
index 0000000..27f331d
--- /dev/null
@@ -0,0 +1,296 @@
+$$ -*- mode: c++; -*-
+$var n = 50  $$ Maximum length of type lists we want to support.
+// Copyright 2008 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: wan@google.com (Zhanyong Wan)
+
+// Type utilities needed for implementing typed and type-parameterized
+// tests.  This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+// Currently we support at most $n types in a list, and at most $n
+// type-parameterized tests in one type-parameterized test case.
+// Please contact googletestframework@googlegroups.com if you need
+// more.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-string.h"
+
+// #ifdef __GNUC__ is too general here.  It is possible to use gcc without using
+// libstdc++ (which is where cxxabi.h comes from).
+# ifdef __GLIBCXX__
+#  include <cxxabi.h>
+# elif defined(__HP_aCC)
+#  include <acxx_demangle.h>
+# endif  // __GLIBCXX__
+
+namespace testing {
+namespace internal {
+
+// GetTypeName<T>() returns a human-readable name of type T.
+// NB: This function is also used in Google Mock, so don't move it inside of
+// the typed-test-only section below.
+template <typename T>
+String GetTypeName() {
+# if GTEST_HAS_RTTI
+
+  const char* const name = typeid(T).name();
+#  if defined(__GLIBCXX__) || defined(__HP_aCC)
+  int status = 0;
+  // gcc's implementation of typeid(T).name() mangles the type name,
+  // so we have to demangle it.
+#   ifdef __GLIBCXX__
+  using abi::__cxa_demangle;
+#   endif // __GLIBCXX__
+  char* const readable_name = __cxa_demangle(name, 0, 0, &status);
+  const String name_str(status == 0 ? readable_name : name);
+  free(readable_name);
+  return name_str;
+#  else
+  return name;
+#  endif  // __GLIBCXX__ || __HP_aCC
+
+# else
+
+  return "<type>";
+
+# endif  // GTEST_HAS_RTTI
+}
+
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
+// type.  This can be used as a compile-time assertion to ensure that
+// two types are equal.
+
+template <typename T1, typename T2>
+struct AssertTypeEq;
+
+template <typename T>
+struct AssertTypeEq<T, T> {
+  typedef bool type;
+};
+
+// A unique type used as the default value for the arguments of class
+// template Types.  This allows us to simulate variadic templates
+// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
+// support directly.
+struct None {};
+
+// The following family of struct and struct templates are used to
+// represent type lists.  In particular, TypesN<T1, T2, ..., TN>
+// represents a type list with N types (T1, T2, ..., and TN) in it.
+// Except for Types0, every struct in the family has two member types:
+// Head for the first type in the list, and Tail for the rest of the
+// list.
+
+// The empty type list.
+struct Types0 {};
+
+// Type lists of length 1, 2, 3, and so on.
+
+template <typename T1>
+struct Types1 {
+  typedef T1 Head;
+  typedef Types0 Tail;
+};
+
+$range i 2..n
+
+$for i [[
+$range j 1..i
+$range k 2..i
+template <$for j, [[typename T$j]]>
+struct Types$i {
+  typedef T1 Head;
+  typedef Types$(i-1)<$for k, [[T$k]]> Tail;
+};
+
+
+]]
+
+}  // namespace internal
+
+// We don't want to require the users to write TypesN<...> directly,
+// as that would require them to count the length.  Types<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Types<int>
+// will appear as Types<int, None, None, ..., None> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Types<T1, ..., TN>, and Google Test will translate
+// that to TypesN<T1, ..., TN> internally to make error messages
+// readable.  The translation is done by the 'type' member of the
+// Types template.
+
+$range i 1..n
+template <$for i, [[typename T$i = internal::None]]>
+struct Types {
+  typedef internal::Types$n<$for i, [[T$i]]> type;
+};
+
+template <>
+struct Types<$for i, [[internal::None]]> {
+  typedef internal::Types0 type;
+};
+
+$range i 1..n-1
+$for i [[
+$range j 1..i
+$range k i+1..n
+template <$for j, [[typename T$j]]>
+struct Types<$for j, [[T$j]]$for k[[, internal::None]]> {
+  typedef internal::Types$i<$for j, [[T$j]]> type;
+};
+
+]]
+
+namespace internal {
+
+# define GTEST_TEMPLATE_ template <typename T> class
+
+// The template "selector" struct TemplateSel<Tmpl> is used to
+// represent Tmpl, which must be a class template with one type
+// parameter, as a type.  TemplateSel<Tmpl>::Bind<T>::type is defined
+// as the type Tmpl<T>.  This allows us to actually instantiate the
+// template "selected" by TemplateSel<Tmpl>.
+//
+// This trick is necessary for simulating typedef for class templates,
+// which C++ doesn't support directly.
+template <GTEST_TEMPLATE_ Tmpl>
+struct TemplateSel {
+  template <typename T>
+  struct Bind {
+    typedef Tmpl<T> type;
+  };
+};
+
+# define GTEST_BIND_(TmplSel, T) \
+  TmplSel::template Bind<T>::type
+
+// A unique struct template used as the default value for the
+// arguments of class template Templates.  This allows us to simulate
+// variadic templates (e.g. Templates<int>, Templates<int, double>,
+// and etc), which C++ doesn't support directly.
+template <typename T>
+struct NoneT {};
+
+// The following family of struct and struct templates are used to
+// represent template lists.  In particular, TemplatesN<T1, T2, ...,
+// TN> represents a list of N templates (T1, T2, ..., and TN).  Except
+// for Templates0, every struct in the family has two member types:
+// Head for the selector of the first template in the list, and Tail
+// for the rest of the list.
+
+// The empty template list.
+struct Templates0 {};
+
+// Template lists of length 1, 2, 3, and so on.
+
+template <GTEST_TEMPLATE_ T1>
+struct Templates1 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates0 Tail;
+};
+
+$range i 2..n
+
+$for i [[
+$range j 1..i
+$range k 2..i
+template <$for j, [[GTEST_TEMPLATE_ T$j]]>
+struct Templates$i {
+  typedef TemplateSel<T1> Head;
+  typedef Templates$(i-1)<$for k, [[T$k]]> Tail;
+};
+
+
+]]
+
+// We don't want to require the users to write TemplatesN<...> directly,
+// as that would require them to count the length.  Templates<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Templates<list>
+// will appear as Templates<list, NoneT, NoneT, ..., NoneT> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Templates<T1, ..., TN>, and Google Test will translate
+// that to TemplatesN<T1, ..., TN> internally to make error messages
+// readable.  The translation is done by the 'type' member of the
+// Templates template.
+
+$range i 1..n
+template <$for i, [[GTEST_TEMPLATE_ T$i = NoneT]]>
+struct Templates {
+  typedef Templates$n<$for i, [[T$i]]> type;
+};
+
+template <>
+struct Templates<$for i, [[NoneT]]> {
+  typedef Templates0 type;
+};
+
+$range i 1..n-1
+$for i [[
+$range j 1..i
+$range k i+1..n
+template <$for j, [[GTEST_TEMPLATE_ T$j]]>
+struct Templates<$for j, [[T$j]]$for k[[, NoneT]]> {
+  typedef Templates$i<$for j, [[T$j]]> type;
+};
+
+]]
+
+// The TypeList template makes it possible to use either a single type
+// or a Types<...> list in TYPED_TEST_CASE() and
+// INSTANTIATE_TYPED_TEST_CASE_P().
+
+template <typename T>
+struct TypeList { typedef Types1<T> type; };
+
+
+$range i 1..n
+template <$for i, [[typename T$i]]>
+struct TypeList<Types<$for i, [[T$i]]> > {
+  typedef typename Types<$for i, [[T$i]]>::type type;
+};
+
+#endif  // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
diff --git a/third_party/googletest/src/m4/acx_pthread.m4 b/third_party/googletest/src/m4/acx_pthread.m4
new file mode 100644 (file)
index 0000000..2cf20de
--- /dev/null
@@ -0,0 +1,363 @@
+# This was retrieved from
+#    http://svn.0pointer.de/viewvc/trunk/common/acx_pthread.m4?revision=1277&root=avahi
+# See also (perhaps for new versions?)
+#    http://svn.0pointer.de/viewvc/trunk/common/acx_pthread.m4?root=avahi
+#
+# We've rewritten the inconsistency check code (from avahi), to work
+# more broadly.  In particular, it no longer assumes ld accepts -zdefs.
+# This caused a restructing of the code, but the functionality has only
+# changed a little.
+
+dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+dnl
+dnl @summary figure out how to build C programs using POSIX threads
+dnl
+dnl This macro figures out how to build C programs using POSIX threads.
+dnl It sets the PTHREAD_LIBS output variable to the threads library and
+dnl linker flags, and the PTHREAD_CFLAGS output variable to any special
+dnl C compiler flags that are needed. (The user can also force certain
+dnl compiler flags/libs to be tested by setting these environment
+dnl variables.)
+dnl
+dnl Also sets PTHREAD_CC to any special C compiler that is needed for
+dnl multi-threaded programs (defaults to the value of CC otherwise).
+dnl (This is necessary on AIX to use the special cc_r compiler alias.)
+dnl
+dnl NOTE: You are assumed to not only compile your program with these
+dnl flags, but also link it with them as well. e.g. you should link
+dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS
+dnl $LIBS
+dnl
+dnl If you are only building threads programs, you may wish to use
+dnl these variables in your default LIBS, CFLAGS, and CC:
+dnl
+dnl        LIBS="$PTHREAD_LIBS $LIBS"
+dnl        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+dnl        CC="$PTHREAD_CC"
+dnl
+dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute
+dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to
+dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+dnl
+dnl ACTION-IF-FOUND is a list of shell commands to run if a threads
+dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to
+dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the
+dnl default action will define HAVE_PTHREAD.
+dnl
+dnl Please let the authors know if this macro fails on any platform, or
+dnl if you have any other suggestions or comments. This macro was based
+dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with
+dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros
+dnl posted by Alejandro Forero Cuervo to the autoconf macro repository.
+dnl We are also grateful for the helpful feedback of numerous users.
+dnl
+dnl @category InstalledPackages
+dnl @author Steven G. Johnson <stevenj@alum.mit.edu>
+dnl @version 2006-05-29
+dnl @license GPLWithACException
+dnl 
+dnl Checks for GCC shared/pthread inconsistency based on work by
+dnl Marcin Owsiany <marcin@owsiany.pl>
+
+
+AC_DEFUN([ACX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_SAVE
+AC_LANG_C
+acx_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+        AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
+        AC_MSG_RESULT($acx_pthread_ok)
+        if test x"$acx_pthread_ok" = xno; then
+                PTHREAD_LIBS=""
+                PTHREAD_CFLAGS=""
+        fi
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try.  Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all, and "pthread-config"
+# which is a program returning the flags for the Pth emulation library.
+
+acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important.  Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+#       other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+#      doesn't hurt to check since this sometimes defines pthreads too;
+#      also defines -D_REENTRANT)
+#      ... -mt is also the pthreads flag for HP/aCC
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case "${host_cpu}-${host_os}" in
+        *solaris*)
+
+        # On Solaris (at least, for some versions), libc contains stubbed
+        # (non-functional) versions of the pthreads routines, so link-based
+        # tests will erroneously succeed.  (We need to link with -pthreads/-mt/
+        # -lpthread.)  (The stubs are missing pthread_cleanup_push, or rather
+        # a function called by this macro, so we could check for that, but
+        # who knows whether they'll stub that too in a future libc.)  So,
+        # we'll just look for -pthreads and -lpthread first:
+
+        acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags"
+        ;;
+esac
+
+if test x"$acx_pthread_ok" = xno; then
+for flag in $acx_pthread_flags; do
+
+        case $flag in
+                none)
+                AC_MSG_CHECKING([whether pthreads work without any flags])
+                ;;
+
+                -*)
+                AC_MSG_CHECKING([whether pthreads work with $flag])
+                PTHREAD_CFLAGS="$flag"
+                ;;
+
+               pthread-config)
+               AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no)
+               if test x"$acx_pthread_config" = xno; then continue; fi
+               PTHREAD_CFLAGS="`pthread-config --cflags`"
+               PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+               ;;
+
+                *)
+                AC_MSG_CHECKING([for the pthreads library -l$flag])
+                PTHREAD_LIBS="-l$flag"
+                ;;
+        esac
+
+        save_LIBS="$LIBS"
+        save_CFLAGS="$CFLAGS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Check for various functions.  We must include pthread.h,
+        # since some functions may be macros.  (On the Sequent, we
+        # need a special flag -Kthread to make this header compile.)
+        # We check for pthread_join because it is in -lpthread on IRIX
+        # while pthread_create is in libc.  We check for pthread_attr_init
+        # due to DEC craziness with -lpthreads.  We check for
+        # pthread_cleanup_push because it is one of the few pthread
+        # functions on Solaris that doesn't have a non-functional libc stub.
+        # We try pthread_create on general principles.
+        AC_TRY_LINK([#include <pthread.h>],
+                    [pthread_t th; pthread_join(th, 0);
+                     pthread_attr_init(0); pthread_cleanup_push(0, 0);
+                     pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+                    [acx_pthread_ok=yes])
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+
+        AC_MSG_RESULT($acx_pthread_ok)
+        if test "x$acx_pthread_ok" = xyes; then
+                break;
+        fi
+
+        PTHREAD_LIBS=""
+        PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$acx_pthread_ok" = xyes; then
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+       AC_MSG_CHECKING([for joinable pthread attribute])
+       attr_name=unknown
+       for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+           AC_TRY_LINK([#include <pthread.h>], [int attr=$attr; return attr;],
+                        [attr_name=$attr; break])
+       done
+        AC_MSG_RESULT($attr_name)
+        if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
+            AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
+                               [Define to necessary symbol if this constant
+                                uses a non-standard name on your system.])
+        fi
+
+        AC_MSG_CHECKING([if more special flags are required for pthreads])
+        flag=no
+        case "${host_cpu}-${host_os}" in
+            *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
+            *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+        esac
+        AC_MSG_RESULT(${flag})
+        if test "x$flag" != xno; then
+            PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+        fi
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+        # More AIX lossage: must compile with xlc_r or cc_r
+       if test x"$GCC" != xyes; then
+          AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
+        else
+          PTHREAD_CC=$CC
+       fi
+
+       # The next part tries to detect GCC inconsistency with -shared on some
+       # architectures and systems. The problem is that in certain
+       # configurations, when -shared is specified, GCC "forgets" to
+       # internally use various flags which are still necessary.
+       
+       #
+       # Prepare the flags
+       #
+       save_CFLAGS="$CFLAGS"
+       save_LIBS="$LIBS"
+       save_CC="$CC"
+       
+       # Try with the flags determined by the earlier checks.
+       #
+       # -Wl,-z,defs forces link-time symbol resolution, so that the
+       # linking checks with -shared actually have any value
+       #
+       # FIXME: -fPIC is required for -shared on many architectures,
+       # so we specify it here, but the right way would probably be to
+       # properly detect whether it is actually required.
+       CFLAGS="-shared -fPIC -Wl,-z,defs $CFLAGS $PTHREAD_CFLAGS"
+       LIBS="$PTHREAD_LIBS $LIBS"
+       CC="$PTHREAD_CC"
+       
+       # In order not to create several levels of indentation, we test
+       # the value of "$done" until we find the cure or run out of ideas.
+       done="no"
+       
+       # First, make sure the CFLAGS we added are actually accepted by our
+       # compiler.  If not (and OS X's ld, for instance, does not accept -z),
+       # then we can't do this test.
+       if test x"$done" = xno; then
+          AC_MSG_CHECKING([whether to check for GCC pthread/shared inconsistencies])
+          AC_TRY_LINK(,, , [done=yes])
+       
+          if test "x$done" = xyes ; then
+             AC_MSG_RESULT([no])
+          else
+             AC_MSG_RESULT([yes])
+          fi
+       fi
+       
+       if test x"$done" = xno; then
+          AC_MSG_CHECKING([whether -pthread is sufficient with -shared])
+          AC_TRY_LINK([#include <pthread.h>],
+             [pthread_t th; pthread_join(th, 0);
+             pthread_attr_init(0); pthread_cleanup_push(0, 0);
+             pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+             [done=yes])
+          
+          if test "x$done" = xyes; then
+             AC_MSG_RESULT([yes])
+          else
+             AC_MSG_RESULT([no])
+          fi
+       fi
+       
+       #
+       # Linux gcc on some architectures such as mips/mipsel forgets
+       # about -lpthread
+       #
+       if test x"$done" = xno; then
+          AC_MSG_CHECKING([whether -lpthread fixes that])
+          LIBS="-lpthread $PTHREAD_LIBS $save_LIBS"
+          AC_TRY_LINK([#include <pthread.h>],
+             [pthread_t th; pthread_join(th, 0);
+             pthread_attr_init(0); pthread_cleanup_push(0, 0);
+             pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+             [done=yes])
+       
+          if test "x$done" = xyes; then
+             AC_MSG_RESULT([yes])
+             PTHREAD_LIBS="-lpthread $PTHREAD_LIBS"
+          else
+             AC_MSG_RESULT([no])
+          fi
+       fi
+       #
+       # FreeBSD 4.10 gcc forgets to use -lc_r instead of -lc
+       #
+       if test x"$done" = xno; then
+          AC_MSG_CHECKING([whether -lc_r fixes that])
+          LIBS="-lc_r $PTHREAD_LIBS $save_LIBS"
+          AC_TRY_LINK([#include <pthread.h>],
+              [pthread_t th; pthread_join(th, 0);
+               pthread_attr_init(0); pthread_cleanup_push(0, 0);
+               pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+              [done=yes])
+       
+          if test "x$done" = xyes; then
+             AC_MSG_RESULT([yes])
+             PTHREAD_LIBS="-lc_r $PTHREAD_LIBS"
+          else
+             AC_MSG_RESULT([no])
+          fi
+       fi
+       if test x"$done" = xno; then
+          # OK, we have run out of ideas
+          AC_MSG_WARN([Impossible to determine how to use pthreads with shared libraries])
+       
+          # so it's not safe to assume that we may use pthreads
+          acx_pthread_ok=no
+       fi
+       
+       CFLAGS="$save_CFLAGS"
+       LIBS="$save_LIBS"
+       CC="$save_CC"
+else
+        PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_pthread_ok" = xyes; then
+        ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+        :
+else
+        acx_pthread_ok=no
+        $2
+fi
+AC_LANG_RESTORE
+])dnl ACX_PTHREAD
diff --git a/third_party/googletest/src/m4/gtest.m4 b/third_party/googletest/src/m4/gtest.m4
new file mode 100644 (file)
index 0000000..6598ba7
--- /dev/null
@@ -0,0 +1,74 @@
+dnl GTEST_LIB_CHECK([minimum version [,
+dnl                  action if found [,action if not found]]])
+dnl
+dnl Check for the presence of the Google Test library, optionally at a minimum
+dnl version, and indicate a viable version with the HAVE_GTEST flag. It defines
+dnl standard variables for substitution including GTEST_CPPFLAGS,
+dnl GTEST_CXXFLAGS, GTEST_LDFLAGS, and GTEST_LIBS. It also defines
+dnl GTEST_VERSION as the version of Google Test found. Finally, it provides
+dnl optional custom action slots in the event GTEST is found or not.
+AC_DEFUN([GTEST_LIB_CHECK],
+[
+dnl Provide a flag to enable or disable Google Test usage.
+AC_ARG_ENABLE([gtest],
+  [AS_HELP_STRING([--enable-gtest],
+                  [Enable tests using the Google C++ Testing Framework.
+                  (Default is enabled.)])],
+  [],
+  [enable_gtest=])
+AC_ARG_VAR([GTEST_CONFIG],
+           [The exact path of Google Test's 'gtest-config' script.])
+AC_ARG_VAR([GTEST_CPPFLAGS],
+           [C-like preprocessor flags for Google Test.])
+AC_ARG_VAR([GTEST_CXXFLAGS],
+           [C++ compile flags for Google Test.])
+AC_ARG_VAR([GTEST_LDFLAGS],
+           [Linker path and option flags for Google Test.])
+AC_ARG_VAR([GTEST_LIBS],
+           [Library linking flags for Google Test.])
+AC_ARG_VAR([GTEST_VERSION],
+           [The version of Google Test available.])
+HAVE_GTEST="no"
+AS_IF([test "x${enable_gtest}" != "xno"],
+  [AC_MSG_CHECKING([for 'gtest-config'])
+   AS_IF([test "x${enable_gtest}" != "xyes"],
+     [AS_IF([test -x "${enable_gtest}/scripts/gtest-config"],
+        [GTEST_CONFIG="${enable_gtest}/scripts/gtest-config"],
+        [GTEST_CONFIG="${enable_gtest}/bin/gtest-config"])
+      AS_IF([test -x "${GTEST_CONFIG}"], [],
+        [AC_MSG_RESULT([no])
+         AC_MSG_ERROR([dnl
+Unable to locate either a built or installed Google Test.
+The specific location '${enable_gtest}' was provided for a built or installed
+Google Test, but no 'gtest-config' script could be found at this location.])
+         ])],
+     [AC_PATH_PROG([GTEST_CONFIG], [gtest-config])])
+   AS_IF([test -x "${GTEST_CONFIG}"],
+     [AC_MSG_RESULT([${GTEST_CONFIG}])
+      m4_ifval([$1],
+        [_gtest_min_version="--min-version=$1"
+         AC_MSG_CHECKING([for Google Test at least version >= $1])],
+        [_gtest_min_version="--min-version=0"
+         AC_MSG_CHECKING([for Google Test])])
+      AS_IF([${GTEST_CONFIG} ${_gtest_min_version}],
+        [AC_MSG_RESULT([yes])
+         HAVE_GTEST='yes'],
+        [AC_MSG_RESULT([no])])],
+     [AC_MSG_RESULT([no])])
+   AS_IF([test "x${HAVE_GTEST}" = "xyes"],
+     [GTEST_CPPFLAGS=`${GTEST_CONFIG} --cppflags`
+      GTEST_CXXFLAGS=`${GTEST_CONFIG} --cxxflags`
+      GTEST_LDFLAGS=`${GTEST_CONFIG} --ldflags`
+      GTEST_LIBS=`${GTEST_CONFIG} --libs`
+      GTEST_VERSION=`${GTEST_CONFIG} --version`
+      AC_DEFINE([HAVE_GTEST],[1],[Defined when Google Test is available.])],
+     [AS_IF([test "x${enable_gtest}" = "xyes"],
+        [AC_MSG_ERROR([dnl
+Google Test was enabled, but no viable version could be found.])
+         ])])])
+AC_SUBST([HAVE_GTEST])
+AM_CONDITIONAL([HAVE_GTEST],[test "x$HAVE_GTEST" = "xyes"])
+AS_IF([test "x$HAVE_GTEST" = "xyes"],
+  [m4_ifval([$2], [$2])],
+  [m4_ifval([$3], [$3])])
+])
diff --git a/third_party/googletest/src/make/Makefile b/third_party/googletest/src/make/Makefile
new file mode 100644 (file)
index 0000000..5b27b6a
--- /dev/null
@@ -0,0 +1,80 @@
+# A sample Makefile for building Google Test and using it in user
+# tests.  Please tweak it to suit your environment and project.  You
+# may want to move it to your project's root directory.
+#
+# SYNOPSIS:
+#
+#   make [all]  - makes everything.
+#   make TARGET - makes the given target.
+#   make clean  - removes all files generated by make.
+
+# Please tweak the following variable definitions as needed by your
+# project, except GTEST_HEADERS, which you can use in your own targets
+# but shouldn't modify.
+
+# Points to the root of Google Test, relative to where this file is.
+# Remember to tweak this if you move this file.
+GTEST_DIR = ..
+
+# Where to find user code.
+USER_DIR = ../samples
+
+# Flags passed to the preprocessor.
+CPPFLAGS += -I$(GTEST_DIR)/include
+
+# Flags passed to the C++ compiler.
+CXXFLAGS += -g -Wall -Wextra
+
+# All tests produced by this Makefile.  Remember to add new tests you
+# created to the list.
+TESTS = sample1_unittest
+
+# All Google Test headers.  Usually you shouldn't change this
+# definition.
+GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
+                $(GTEST_DIR)/include/gtest/internal/*.h
+
+# House-keeping build targets.
+
+all : $(TESTS)
+
+clean :
+       rm -f $(TESTS) gtest.a gtest_main.a *.o
+
+# Builds gtest.a and gtest_main.a.
+
+# Usually you shouldn't tweak such internal variables, indicated by a
+# trailing _.
+GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)
+
+# For simplicity and to avoid depending on Google Test's
+# implementation details, the dependencies specified below are
+# conservative and not optimized.  This is fine as Google Test
+# compiles fast and for ordinary users its source rarely changes.
+gtest-all.o : $(GTEST_SRCS_)
+       $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
+            $(GTEST_DIR)/src/gtest-all.cc
+
+gtest_main.o : $(GTEST_SRCS_)
+       $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
+            $(GTEST_DIR)/src/gtest_main.cc
+
+gtest.a : gtest-all.o
+       $(AR) $(ARFLAGS) $@ $^
+
+gtest_main.a : gtest-all.o gtest_main.o
+       $(AR) $(ARFLAGS) $@ $^
+
+# Builds a sample test.  A test should link with either gtest.a or
+# gtest_main.a, depending on whether it defines its own main()
+# function.
+
+sample1.o : $(USER_DIR)/sample1.cc $(USER_DIR)/sample1.h $(GTEST_HEADERS)
+       $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/sample1.cc
+
+sample1_unittest.o : $(USER_DIR)/sample1_unittest.cc \
+                     $(USER_DIR)/sample1.h $(GTEST_HEADERS)
+       $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/sample1_unittest.cc
+
+sample1_unittest : sample1.o sample1_unittest.o gtest_main.a
+       $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
diff --git a/third_party/googletest/src/msvc/gtest-md.sln b/third_party/googletest/src/msvc/gtest-md.sln
new file mode 100644 (file)
index 0000000..f7908da
--- /dev/null
@@ -0,0 +1,45 @@
+Microsoft Visual Studio Solution File, Format Version 8.00\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest-md", "gtest-md.vcproj", "{C8F6C172-56F2-4E76-B5FA-C3B423B31BE8}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest_main-md", "gtest_main-md.vcproj", "{3AF54C8A-10BF-4332-9147-F68ED9862033}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest_prod_test-md", "gtest_prod_test-md.vcproj", "{24848551-EF4F-47E8-9A9D-EA4D49BC3ECB}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest_unittest-md", "gtest_unittest-md.vcproj", "{4D9FDFB5-986A-4139-823C-F4EE0ED481A2}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+       EndProjectSection\r
+EndProject\r
+Global\r
+       GlobalSection(SolutionConfiguration) = preSolution\r
+               Debug = Debug\r
+               Release = Release\r
+       EndGlobalSection\r
+       GlobalSection(ProjectConfiguration) = postSolution\r
+               {C8F6C172-56F2-4E76-B5FA-C3B423B31BE8}.Debug.ActiveCfg = Debug|Win32\r
+               {C8F6C172-56F2-4E76-B5FA-C3B423B31BE8}.Debug.Build.0 = Debug|Win32\r
+               {C8F6C172-56F2-4E76-B5FA-C3B423B31BE8}.Release.ActiveCfg = Release|Win32\r
+               {C8F6C172-56F2-4E76-B5FA-C3B423B31BE8}.Release.Build.0 = Release|Win32\r
+               {3AF54C8A-10BF-4332-9147-F68ED9862033}.Debug.ActiveCfg = Debug|Win32\r
+               {3AF54C8A-10BF-4332-9147-F68ED9862033}.Debug.Build.0 = Debug|Win32\r
+               {3AF54C8A-10BF-4332-9147-F68ED9862033}.Release.ActiveCfg = Release|Win32\r
+               {3AF54C8A-10BF-4332-9147-F68ED9862033}.Release.Build.0 = Release|Win32\r
+               {24848551-EF4F-47E8-9A9D-EA4D49BC3ECB}.Debug.ActiveCfg = Debug|Win32\r
+               {24848551-EF4F-47E8-9A9D-EA4D49BC3ECB}.Debug.Build.0 = Debug|Win32\r
+               {24848551-EF4F-47E8-9A9D-EA4D49BC3ECB}.Release.ActiveCfg = Release|Win32\r
+               {24848551-EF4F-47E8-9A9D-EA4D49BC3ECB}.Release.Build.0 = Release|Win32\r
+               {4D9FDFB5-986A-4139-823C-F4EE0ED481A2}.Debug.ActiveCfg = Debug|Win32\r
+               {4D9FDFB5-986A-4139-823C-F4EE0ED481A2}.Debug.Build.0 = Debug|Win32\r
+               {4D9FDFB5-986A-4139-823C-F4EE0ED481A2}.Release.ActiveCfg = Release|Win32\r
+               {4D9FDFB5-986A-4139-823C-F4EE0ED481A2}.Release.Build.0 = Release|Win32\r
+       EndGlobalSection\r
+       GlobalSection(ExtensibilityGlobals) = postSolution\r
+       EndGlobalSection\r
+       GlobalSection(ExtensibilityAddIns) = postSolution\r
+       EndGlobalSection\r
+EndGlobal\r
diff --git a/third_party/googletest/src/msvc/gtest-md.vcproj b/third_party/googletest/src/msvc/gtest-md.vcproj
new file mode 100644 (file)
index 0000000..1c35c3a
--- /dev/null
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="gtest-md"\r
+       ProjectGUID="{C8F6C172-56F2-4E76-B5FA-C3B423B31BE8}"\r
+       Keyword="Win32Proj">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionName)/$(ConfigurationName)"\r
+                       IntermediateDirectory="$(OutDir)/$(ProjectName)"\r
+                       ConfigurationType="4"\r
+                       CharacterSet="2"\r
+                       ReferencesPath="">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_LIB"\r
+                               MinimalRebuild="TRUE"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="FALSE"\r
+                               DebugInformationFormat="4"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLibrarianTool"\r
+                               OutputFile="$(OutDir)/gtestd.lib"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionName)/$(ConfigurationName)"\r
+                       IntermediateDirectory="$(OutDir)/$(ProjectName)"\r
+                       ConfigurationType="4"\r
+                       CharacterSet="2"\r
+                       ReferencesPath="&quot;..\include&quot;;&quot;..&quot;">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_LIB"\r
+                               RuntimeLibrary="2"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="FALSE"\r
+                               DebugInformationFormat="3"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLibrarianTool"\r
+                               OutputFile="$(OutDir)/gtest.lib"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">\r
+                       <File\r
+                               RelativePath="..\src\gtest-all.cc">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/third_party/googletest/src/msvc/gtest.sln b/third_party/googletest/src/msvc/gtest.sln
new file mode 100644 (file)
index 0000000..ef4b057
--- /dev/null
@@ -0,0 +1,45 @@
+Microsoft Visual Studio Solution File, Format Version 8.00\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest", "gtest.vcproj", "{C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest_main", "gtest_main.vcproj", "{3AF54C8A-10BF-4332-9147-F68ED9862032}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest_unittest", "gtest_unittest.vcproj", "{4D9FDFB5-986A-4139-823C-F4EE0ED481A1}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest_prod_test", "gtest_prod_test.vcproj", "{24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+       EndProjectSection\r
+EndProject\r
+Global\r
+       GlobalSection(SolutionConfiguration) = preSolution\r
+               Debug = Debug\r
+               Release = Release\r
+       EndGlobalSection\r
+       GlobalSection(ProjectConfiguration) = postSolution\r
+               {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Debug.ActiveCfg = Debug|Win32\r
+               {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Debug.Build.0 = Debug|Win32\r
+               {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Release.ActiveCfg = Release|Win32\r
+               {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Release.Build.0 = Release|Win32\r
+               {3AF54C8A-10BF-4332-9147-F68ED9862032}.Debug.ActiveCfg = Debug|Win32\r
+               {3AF54C8A-10BF-4332-9147-F68ED9862032}.Debug.Build.0 = Debug|Win32\r
+               {3AF54C8A-10BF-4332-9147-F68ED9862032}.Release.ActiveCfg = Release|Win32\r
+               {3AF54C8A-10BF-4332-9147-F68ED9862032}.Release.Build.0 = Release|Win32\r
+               {4D9FDFB5-986A-4139-823C-F4EE0ED481A1}.Debug.ActiveCfg = Debug|Win32\r
+               {4D9FDFB5-986A-4139-823C-F4EE0ED481A1}.Debug.Build.0 = Debug|Win32\r
+               {4D9FDFB5-986A-4139-823C-F4EE0ED481A1}.Release.ActiveCfg = Release|Win32\r
+               {4D9FDFB5-986A-4139-823C-F4EE0ED481A1}.Release.Build.0 = Release|Win32\r
+               {24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}.Debug.ActiveCfg = Debug|Win32\r
+               {24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}.Debug.Build.0 = Debug|Win32\r
+               {24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}.Release.ActiveCfg = Release|Win32\r
+               {24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}.Release.Build.0 = Release|Win32\r
+       EndGlobalSection\r
+       GlobalSection(ExtensibilityGlobals) = postSolution\r
+       EndGlobalSection\r
+       GlobalSection(ExtensibilityAddIns) = postSolution\r
+       EndGlobalSection\r
+EndGlobal\r
diff --git a/third_party/googletest/src/msvc/gtest.vcproj b/third_party/googletest/src/msvc/gtest.vcproj
new file mode 100644 (file)
index 0000000..a8373ce
--- /dev/null
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="gtest"\r
+       ProjectGUID="{C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}"\r
+       Keyword="Win32Proj">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionName)/$(ConfigurationName)"\r
+                       IntermediateDirectory="$(OutDir)/$(ProjectName)"\r
+                       ConfigurationType="4"\r
+                       CharacterSet="2"\r
+                       ReferencesPath="">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_LIB"\r
+                               MinimalRebuild="TRUE"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="5"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="FALSE"\r
+                               DebugInformationFormat="4"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLibrarianTool"\r
+                               OutputFile="$(OutDir)/gtestd.lib"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionName)/$(ConfigurationName)"\r
+                       IntermediateDirectory="$(OutDir)/$(ProjectName)"\r
+                       ConfigurationType="4"\r
+                       CharacterSet="2"\r
+                       ReferencesPath="&quot;..\include&quot;;&quot;..&quot;">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_LIB"\r
+                               RuntimeLibrary="4"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="FALSE"\r
+                               DebugInformationFormat="3"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLibrarianTool"\r
+                               OutputFile="$(OutDir)/gtest.lib"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">\r
+                       <File\r
+                               RelativePath="..\src\gtest-all.cc">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/third_party/googletest/src/msvc/gtest_main-md.vcproj b/third_party/googletest/src/msvc/gtest_main-md.vcproj
new file mode 100644 (file)
index 0000000..b5379fe
--- /dev/null
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="gtest_main-md"\r
+       ProjectGUID="{3AF54C8A-10BF-4332-9147-F68ED9862033}"\r
+       Keyword="Win32Proj">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionName)/$(ConfigurationName)"\r
+                       IntermediateDirectory="$(OutDir)/$(ProjectName)"\r
+                       ConfigurationType="4"\r
+                       CharacterSet="2"\r
+                       ReferencesPath="">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_LIB"\r
+                               MinimalRebuild="TRUE"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="FALSE"\r
+                               DebugInformationFormat="4"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLibrarianTool"\r
+                               OutputFile="$(OutDir)/$(ProjectName)d.lib"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionName)/$(ConfigurationName)"\r
+                       IntermediateDirectory="$(OutDir)/$(ProjectName)"\r
+                       ConfigurationType="4"\r
+                       CharacterSet="2"\r
+                       ReferencesPath="&quot;..\include&quot;;&quot;..&quot;">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_LIB"\r
+                               RuntimeLibrary="2"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="FALSE"\r
+                               DebugInformationFormat="3"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLibrarianTool"\r
+                               OutputFile="$(OutDir)/$(ProjectName).lib"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+               <ProjectReference\r
+                       ReferencedProjectIdentifier="{C8F6C172-56F2-4E76-B5FA-C3B423B31BE8}"\r
+                       Name="gtest-md"/>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">\r
+                       <File\r
+                               RelativePath="..\src\gtest_main.cc">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/third_party/googletest/src/msvc/gtest_main.vcproj b/third_party/googletest/src/msvc/gtest_main.vcproj
new file mode 100644 (file)
index 0000000..e8b763c
--- /dev/null
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="gtest_main"\r
+       ProjectGUID="{3AF54C8A-10BF-4332-9147-F68ED9862032}"\r
+       Keyword="Win32Proj">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionName)/$(ConfigurationName)"\r
+                       IntermediateDirectory="$(OutDir)/$(ProjectName)"\r
+                       ConfigurationType="4"\r
+                       CharacterSet="2"\r
+                       ReferencesPath="">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_LIB"\r
+                               MinimalRebuild="TRUE"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="5"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="FALSE"\r
+                               DebugInformationFormat="4"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLibrarianTool"\r
+                               OutputFile="$(OutDir)/$(ProjectName)d.lib"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionName)/$(ConfigurationName)"\r
+                       IntermediateDirectory="$(OutDir)/$(ProjectName)"\r
+                       ConfigurationType="4"\r
+                       CharacterSet="2"\r
+                       ReferencesPath="&quot;..\include&quot;;&quot;..&quot;">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_LIB"\r
+                               RuntimeLibrary="4"\r
+                               UsePrecompiledHeader="0"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="FALSE"\r
+                               DebugInformationFormat="3"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLibrarianTool"\r
+                               OutputFile="$(OutDir)/$(ProjectName).lib"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+               <ProjectReference\r
+                       ReferencedProjectIdentifier="{C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}"\r
+                       Name="gtest"/>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">\r
+                       <File\r
+                               RelativePath="..\src\gtest_main.cc">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/third_party/googletest/src/msvc/gtest_prod_test-md.vcproj b/third_party/googletest/src/msvc/gtest_prod_test-md.vcproj
new file mode 100644 (file)
index 0000000..05b05d9
--- /dev/null
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="gtest_prod_test-md"\r
+       ProjectGUID="{24848551-EF4F-47E8-9A9D-EA4D49BC3ECB}"\r
+       Keyword="Win32Proj">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionName)/$(ConfigurationName)"\r
+                       IntermediateDirectory="$(OutDir)/$(ProjectName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="2">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"\r
+                               MinimalRebuild="TRUE"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="3"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="FALSE"\r
+                               DebugInformationFormat="4"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="$(OutDir)/gtest_prod_test.exe"\r
+                               LinkIncremental="2"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(OutDir)/gtest_prod_test.pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionName)/$(ConfigurationName)"\r
+                       IntermediateDirectory="$(OutDir)/$(ProjectName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="2">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"\r
+                               RuntimeLibrary="2"\r
+                               UsePrecompiledHeader="3"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="FALSE"\r
+                               DebugInformationFormat="3"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="$(OutDir)/gtest_prod_test.exe"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="TRUE"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+               <ProjectReference\r
+                       ReferencedProjectIdentifier="{3AF54C8A-10BF-4332-9147-F68ED9862033}"\r
+                       Name="gtest_main-md"/>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">\r
+                       <File\r
+                               RelativePath="..\test\gtest_prod_test.cc">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"\r
+                                               UsePrecompiledHeader="0"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"\r
+                                               UsePrecompiledHeader="0"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\test\production.cc">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"\r
+                                               UsePrecompiledHeader="0"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"\r
+                                               UsePrecompiledHeader="0"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">\r
+                       <File\r
+                               RelativePath="..\test\production.h">\r
+                       </File>\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/third_party/googletest/src/msvc/gtest_prod_test.vcproj b/third_party/googletest/src/msvc/gtest_prod_test.vcproj
new file mode 100644 (file)
index 0000000..6d7a2f0
--- /dev/null
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="gtest_prod_test"\r
+       ProjectGUID="{24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}"\r
+       Keyword="Win32Proj">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionName)/$(ConfigurationName)"\r
+                       IntermediateDirectory="$(OutDir)/$(ProjectName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="2">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"\r
+                               MinimalRebuild="TRUE"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="5"\r
+                               UsePrecompiledHeader="3"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="FALSE"\r
+                               DebugInformationFormat="4"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="$(OutDir)/gtest_prod_test.exe"\r
+                               LinkIncremental="2"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(OutDir)/gtest_prod_test.pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionName)/$(ConfigurationName)"\r
+                       IntermediateDirectory="$(OutDir)/$(ProjectName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="2">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"\r
+                               RuntimeLibrary="4"\r
+                               UsePrecompiledHeader="3"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="FALSE"\r
+                               DebugInformationFormat="3"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="$(OutDir)/gtest_prod_test.exe"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="TRUE"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+               <ProjectReference\r
+                       ReferencedProjectIdentifier="{3AF54C8A-10BF-4332-9147-F68ED9862032}"\r
+                       Name="gtest_main"/>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">\r
+                       <File\r
+                               RelativePath="..\test\gtest_prod_test.cc">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"\r
+                                               UsePrecompiledHeader="0"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"\r
+                                               UsePrecompiledHeader="0"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\test\production.cc">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"\r
+                                               UsePrecompiledHeader="0"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"\r
+                                               UsePrecompiledHeader="0"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">\r
+                       <File\r
+                               RelativePath="..\test\production.h">\r
+                       </File>\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/third_party/googletest/src/msvc/gtest_unittest-md.vcproj b/third_party/googletest/src/msvc/gtest_unittest-md.vcproj
new file mode 100644 (file)
index 0000000..38a5e56
--- /dev/null
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="gtest_unittest-md"\r
+       ProjectGUID="{4D9FDFB5-986A-4139-823C-F4EE0ED481A2}"\r
+       Keyword="Win32Proj">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionName)/$(ConfigurationName)"\r
+                       IntermediateDirectory="$(OutDir)/$(ProjectName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="2">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"\r
+                               MinimalRebuild="TRUE"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="3"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="FALSE"\r
+                               DebugInformationFormat="4"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="$(OutDir)/gtest_unittest.exe"\r
+                               LinkIncremental="2"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(OutDir)/gtest_unittest.pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionName)/$(ConfigurationName)"\r
+                       IntermediateDirectory="$(OutDir)/$(ProjectName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="2">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"\r
+                               RuntimeLibrary="2"\r
+                               UsePrecompiledHeader="3"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="FALSE"\r
+                               DebugInformationFormat="3"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="$(OutDir)/gtest_unittest.exe"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="TRUE"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+               <ProjectReference\r
+                       ReferencedProjectIdentifier="{3AF54C8A-10BF-4332-9147-F68ED9862033}"\r
+                       Name="gtest_main-md"/>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">\r
+                       <File\r
+                               RelativePath="..\test\gtest_unittest.cc">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="1"\r
+                                               AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"\r
+                                               BasicRuntimeChecks="0"\r
+                                               UsePrecompiledHeader="0"\r
+                                               DebugInformationFormat="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"\r
+                                               UsePrecompiledHeader="0"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/third_party/googletest/src/msvc/gtest_unittest.vcproj b/third_party/googletest/src/msvc/gtest_unittest.vcproj
new file mode 100644 (file)
index 0000000..cb1f52b
--- /dev/null
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="gtest_unittest"\r
+       ProjectGUID="{4D9FDFB5-986A-4139-823C-F4EE0ED481A1}"\r
+       Keyword="Win32Proj">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory="$(SolutionName)/$(ConfigurationName)"\r
+                       IntermediateDirectory="$(OutDir)/$(ProjectName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="2">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"\r
+                               MinimalRebuild="TRUE"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="5"\r
+                               UsePrecompiledHeader="3"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="FALSE"\r
+                               DebugInformationFormat="4"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="$(OutDir)/gtest_unittest.exe"\r
+                               LinkIncremental="2"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(OutDir)/gtest_unittest.pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(SolutionName)/$(ConfigurationName)"\r
+                       IntermediateDirectory="$(OutDir)/$(ProjectName)"\r
+                       ConfigurationType="1"\r
+                       CharacterSet="2">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"\r
+                               RuntimeLibrary="4"\r
+                               UsePrecompiledHeader="3"\r
+                               WarningLevel="3"\r
+                               Detect64BitPortabilityProblems="FALSE"\r
+                               DebugInformationFormat="3"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="$(OutDir)/gtest_unittest.exe"\r
+                               LinkIncremental="1"\r
+                               GenerateDebugInformation="TRUE"\r
+                               SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+               <ProjectReference\r
+                       ReferencedProjectIdentifier="{3AF54C8A-10BF-4332-9147-F68ED9862032}"\r
+                       Name="gtest_main"/>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+                       UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">\r
+                       <File\r
+                               RelativePath="..\test\gtest_unittest.cc">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="1"\r
+                                               AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"\r
+                                               BasicRuntimeChecks="0"\r
+                                               UsePrecompiledHeader="0"\r
+                                               DebugInformationFormat="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               AdditionalIncludeDirectories="&quot;..&quot;;&quot;..\include&quot;"\r
+                                               UsePrecompiledHeader="0"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+                       UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/third_party/googletest/src/samples/prime_tables.h b/third_party/googletest/src/samples/prime_tables.h
new file mode 100644 (file)
index 0000000..92ce16a
--- /dev/null
@@ -0,0 +1,123 @@
+// Copyright 2008 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: wan@google.com (Zhanyong Wan)
+// Author: vladl@google.com (Vlad Losev)
+
+// This provides interface PrimeTable that determines whether a number is a
+// prime and determines a next prime number. This interface is used
+// in Google Test samples demonstrating use of parameterized tests.
+
+#ifndef GTEST_SAMPLES_PRIME_TABLES_H_
+#define GTEST_SAMPLES_PRIME_TABLES_H_
+
+#include <algorithm>
+
+// The prime table interface.
+class PrimeTable {
+ public:
+  virtual ~PrimeTable() {}
+
+  // Returns true iff n is a prime number.
+  virtual bool IsPrime(int n) const = 0;
+
+  // Returns the smallest prime number greater than p; or returns -1
+  // if the next prime is beyond the capacity of the table.
+  virtual int GetNextPrime(int p) const = 0;
+};
+
+// Implementation #1 calculates the primes on-the-fly.
+class OnTheFlyPrimeTable : public PrimeTable {
+ public:
+  virtual bool IsPrime(int n) const {
+    if (n <= 1) return false;
+
+    for (int i = 2; i*i <= n; i++) {
+      // n is divisible by an integer other than 1 and itself.
+      if ((n % i) == 0) return false;
+    }
+
+    return true;
+  }
+
+  virtual int GetNextPrime(int p) const {
+    for (int n = p + 1; n > 0; n++) {
+      if (IsPrime(n)) return n;
+    }
+
+    return -1;
+  }
+};
+
+// Implementation #2 pre-calculates the primes and stores the result
+// in an array.
+class PreCalculatedPrimeTable : public PrimeTable {
+ public:
+  // 'max' specifies the maximum number the prime table holds.
+  explicit PreCalculatedPrimeTable(int max)
+      : is_prime_size_(max + 1), is_prime_(new bool[max + 1]) {
+    CalculatePrimesUpTo(max);
+  }
+  virtual ~PreCalculatedPrimeTable() { delete[] is_prime_; }
+
+  virtual bool IsPrime(int n) const {
+    return 0 <= n && n < is_prime_size_ && is_prime_[n];
+  }
+
+  virtual int GetNextPrime(int p) const {
+    for (int n = p + 1; n < is_prime_size_; n++) {
+      if (is_prime_[n]) return n;
+    }
+
+    return -1;
+  }
+
+ private:
+  void CalculatePrimesUpTo(int max) {
+    ::std::fill(is_prime_, is_prime_ + is_prime_size_, true);
+    is_prime_[0] = is_prime_[1] = false;
+
+    for (int i = 2; i <= max; i++) {
+      if (!is_prime_[i]) continue;
+
+      // Marks all multiples of i (except i itself) as non-prime.
+      for (int j = 2*i; j <= max; j += i) {
+        is_prime_[j] = false;
+      }
+    }
+  }
+
+  const int is_prime_size_;
+  bool* const is_prime_;
+
+  // Disables compiler warning "assignment operator could not be generated."
+  void operator=(const PreCalculatedPrimeTable& rhs);
+};
+
+#endif  // GTEST_SAMPLES_PRIME_TABLES_H_
diff --git a/third_party/googletest/src/samples/sample1.cc b/third_party/googletest/src/samples/sample1.cc
new file mode 100644 (file)
index 0000000..f171e26
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright 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.
+
+// A sample program demonstrating using Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "sample1.h"
+
+// Returns n! (the factorial of n).  For negative n, n! is defined to be 1.
+int Factorial(int n) {
+  int result = 1;
+  for (int i = 1; i <= n; i++) {
+    result *= i;
+  }
+
+  return result;
+}
+
+// Returns true iff n is a prime number.
+bool IsPrime(int n) {
+  // Trivial case 1: small numbers
+  if (n <= 1) return false;
+
+  // Trivial case 2: even numbers
+  if (n % 2 == 0) return n == 2;
+
+  // Now, we have that n is odd and n >= 3.
+
+  // Try to divide n by every odd number i, starting from 3
+  for (int i = 3; ; i += 2) {
+    // We only have to try i up to the squre root of n
+    if (i > n/i) break;
+
+    // Now, we have i <= n/i < n.
+    // If n is divisible by i, n is not prime.
+    if (n % i == 0) return false;
+  }
+
+  // n has no integer factor in the range (1, n), and thus is prime.
+  return true;
+}
diff --git a/third_party/googletest/src/samples/sample1.h b/third_party/googletest/src/samples/sample1.h
new file mode 100644 (file)
index 0000000..3dfeb98
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 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.
+
+// A sample program demonstrating using Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#ifndef GTEST_SAMPLES_SAMPLE1_H_
+#define GTEST_SAMPLES_SAMPLE1_H_
+
+// Returns n! (the factorial of n).  For negative n, n! is defined to be 1.
+int Factorial(int n);
+
+// Returns true iff n is a prime number.
+bool IsPrime(int n);
+
+#endif  // GTEST_SAMPLES_SAMPLE1_H_
diff --git a/third_party/googletest/src/samples/sample10_unittest.cc b/third_party/googletest/src/samples/sample10_unittest.cc
new file mode 100644 (file)
index 0000000..2813d04
--- /dev/null
@@ -0,0 +1,145 @@
+// Copyright 2009 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: vladl@google.com (Vlad Losev)
+
+// This sample shows how to use Google Test listener API to implement
+// a primitive leak checker.
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "gtest/gtest.h"
+
+using ::testing::EmptyTestEventListener;
+using ::testing::InitGoogleTest;
+using ::testing::Test;
+using ::testing::TestCase;
+using ::testing::TestEventListeners;
+using ::testing::TestInfo;
+using ::testing::TestPartResult;
+using ::testing::UnitTest;
+
+namespace {
+
+// We will track memory used by this class.
+class Water {
+ public:
+  // Normal Water declarations go here.
+
+  // operator new and operator delete help us control water allocation.
+  void* operator new(size_t allocation_size) {
+    allocated_++;
+    return malloc(allocation_size);
+  }
+
+  void operator delete(void* block, size_t /* allocation_size */) {
+    allocated_--;
+    free(block);
+  }
+
+  static int allocated() { return allocated_; }
+
+ private:
+  static int allocated_;
+};
+
+int Water::allocated_ = 0;
+
+// This event listener monitors how many Water objects are created and
+// destroyed by each test, and reports a failure if a test leaks some Water
+// objects. It does this by comparing the number of live Water objects at
+// the beginning of a test and at the end of a test.
+class LeakChecker : public EmptyTestEventListener {
+ private:
+  // Called before a test starts.
+  virtual void OnTestStart(const TestInfo& /* test_info */) {
+    initially_allocated_ = Water::allocated();
+  }
+
+  // Called after a test ends.
+  virtual void OnTestEnd(const TestInfo& /* test_info */) {
+    int difference = Water::allocated() - initially_allocated_;
+
+    // You can generate a failure in any event handler except
+    // OnTestPartResult. Just use an appropriate Google Test assertion to do
+    // it.
+    EXPECT_TRUE(difference <= 0)
+        << "Leaked " << difference << " unit(s) of Water!";
+  }
+
+  int initially_allocated_;
+};
+
+TEST(ListenersTest, DoesNotLeak) {
+  Water* water = new Water;
+  delete water;
+}
+
+// This should fail when the --check_for_leaks command line flag is
+// specified.
+TEST(ListenersTest, LeaksWater) {
+  Water* water = new Water;
+  EXPECT_TRUE(water != NULL);
+}
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  InitGoogleTest(&argc, argv);
+
+  bool check_for_leaks = false;
+  if (argc > 1 && strcmp(argv[1], "--check_for_leaks") == 0 )
+    check_for_leaks = true;
+  else
+    printf("%s\n", "Run this program with --check_for_leaks to enable "
+           "custom leak checking in the tests.");
+
+  // If we are given the --check_for_leaks command line flag, installs the
+  // leak checker.
+  if (check_for_leaks) {
+    TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
+
+    // Adds the leak checker to the end of the test event listener list,
+    // after the default text output printer and the default XML report
+    // generator.
+    //
+    // The order is important - it ensures that failures generated in the
+    // leak checker's OnTestEnd() method are processed by the text and XML
+    // printers *before* their OnTestEnd() methods are called, such that
+    // they are attributed to the right test. Remember that a listener
+    // receives an OnXyzStart event *after* listeners preceding it in the
+    // list received that event, and receives an OnXyzEnd event *before*
+    // listeners preceding it.
+    //
+    // We don't need to worry about deleting the new listener later, as
+    // Google Test will do it.
+    listeners.Append(new LeakChecker);
+  }
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/src/samples/sample1_unittest.cc b/third_party/googletest/src/samples/sample1_unittest.cc
new file mode 100644 (file)
index 0000000..a8a7c79
--- /dev/null
@@ -0,0 +1,153 @@
+// Copyright 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.
+
+// A sample program demonstrating using Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+
+// This sample shows how to write a simple unit test for a function,
+// using Google C++ testing framework.
+//
+// Writing a unit test using Google C++ testing framework is easy as 1-2-3:
+
+
+// Step 1. Include necessary header files such that the stuff your
+// test logic needs is declared.
+//
+// Don't forget gtest.h, which declares the testing framework.
+
+#include <limits.h>
+#include "sample1.h"
+#include "gtest/gtest.h"
+
+
+// Step 2. Use the TEST macro to define your tests.
+//
+// TEST has two parameters: the test case name and the test name.
+// After using the macro, you should define your test logic between a
+// pair of braces.  You can use a bunch of macros to indicate the
+// success or failure of a test.  EXPECT_TRUE and EXPECT_EQ are
+// examples of such macros.  For a complete list, see gtest.h.
+//
+// <TechnicalDetails>
+//
+// In Google Test, tests are grouped into test cases.  This is how we
+// keep test code organized.  You should put logically related tests
+// into the same test case.
+//
+// The test case name and the test name should both be valid C++
+// identifiers.  And you should not use underscore (_) in the names.
+//
+// Google Test guarantees that each test you define is run exactly
+// once, but it makes no guarantee on the order the tests are
+// executed.  Therefore, you should write your tests in such a way
+// that their results don't depend on their order.
+//
+// </TechnicalDetails>
+
+
+// Tests Factorial().
+
+// Tests factorial of negative numbers.
+TEST(FactorialTest, Negative) {
+  // This test is named "Negative", and belongs to the "FactorialTest"
+  // test case.
+  EXPECT_EQ(1, Factorial(-5));
+  EXPECT_EQ(1, Factorial(-1));
+  EXPECT_TRUE(Factorial(-10) > 0);
+
+  // <TechnicalDetails>
+  //
+  // EXPECT_EQ(expected, actual) is the same as
+  //
+  //   EXPECT_TRUE((expected) == (actual))
+  //
+  // except that it will print both the expected value and the actual
+  // value when the assertion fails.  This is very helpful for
+  // debugging.  Therefore in this case EXPECT_EQ is preferred.
+  //
+  // On the other hand, EXPECT_TRUE accepts any Boolean expression,
+  // and is thus more general.
+  //
+  // </TechnicalDetails>
+}
+
+// Tests factorial of 0.
+TEST(FactorialTest, Zero) {
+  EXPECT_EQ(1, Factorial(0));
+}
+
+// Tests factorial of positive numbers.
+TEST(FactorialTest, Positive) {
+  EXPECT_EQ(1, Factorial(1));
+  EXPECT_EQ(2, Factorial(2));
+  EXPECT_EQ(6, Factorial(3));
+  EXPECT_EQ(40320, Factorial(8));
+}
+
+
+// Tests IsPrime()
+
+// Tests negative input.
+TEST(IsPrimeTest, Negative) {
+  // This test belongs to the IsPrimeTest test case.
+
+  EXPECT_FALSE(IsPrime(-1));
+  EXPECT_FALSE(IsPrime(-2));
+  EXPECT_FALSE(IsPrime(INT_MIN));
+}
+
+// Tests some trivial cases.
+TEST(IsPrimeTest, Trivial) {
+  EXPECT_FALSE(IsPrime(0));
+  EXPECT_FALSE(IsPrime(1));
+  EXPECT_TRUE(IsPrime(2));
+  EXPECT_TRUE(IsPrime(3));
+}
+
+// Tests positive input.
+TEST(IsPrimeTest, Positive) {
+  EXPECT_FALSE(IsPrime(4));
+  EXPECT_TRUE(IsPrime(5));
+  EXPECT_FALSE(IsPrime(6));
+  EXPECT_TRUE(IsPrime(23));
+}
+
+// Step 3. Call RUN_ALL_TESTS() in main().
+//
+// We do this by linking in src/gtest_main.cc file, which consists of
+// a main() function which calls RUN_ALL_TESTS() for us.
+//
+// This runs all the tests you've defined, prints the result, and
+// returns 0 if successful, or 1 otherwise.
+//
+// Did you notice that we didn't register the tests?  The
+// RUN_ALL_TESTS() macro magically knows about all the tests we
+// defined.  Isn't this convenient?
diff --git a/third_party/googletest/src/samples/sample2.cc b/third_party/googletest/src/samples/sample2.cc
new file mode 100644 (file)
index 0000000..5f763b9
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright 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.
+
+// A sample program demonstrating using Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "sample2.h"
+
+#include <string.h>
+
+// Clones a 0-terminated C string, allocating memory using new.
+const char* MyString::CloneCString(const char* a_c_string) {
+  if (a_c_string == NULL) return NULL;
+
+  const size_t len = strlen(a_c_string);
+  char* const clone = new char[ len + 1 ];
+  memcpy(clone, a_c_string, len + 1);
+
+  return clone;
+}
+
+// Sets the 0-terminated C string this MyString object
+// represents.
+void MyString::Set(const char* a_c_string) {
+  // Makes sure this works when c_string == c_string_
+  const char* const temp = MyString::CloneCString(a_c_string);
+  delete[] c_string_;
+  c_string_ = temp;
+}
diff --git a/third_party/googletest/src/samples/sample2.h b/third_party/googletest/src/samples/sample2.h
new file mode 100644 (file)
index 0000000..5b57e60
--- /dev/null
@@ -0,0 +1,86 @@
+// Copyright 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.
+
+// A sample program demonstrating using Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#ifndef GTEST_SAMPLES_SAMPLE2_H_
+#define GTEST_SAMPLES_SAMPLE2_H_
+
+#include <string.h>
+
+
+// A simple string class.
+class MyString {
+ private:
+  const char* c_string_;
+  const MyString& operator=(const MyString& rhs);
+
+ public:
+
+  // Clones a 0-terminated C string, allocating memory using new.
+  static const char* CloneCString(const char* a_c_string);
+
+  ////////////////////////////////////////////////////////////
+  //
+  // C'tors
+
+  // The default c'tor constructs a NULL string.
+  MyString() : c_string_(NULL) {}
+
+  // Constructs a MyString by cloning a 0-terminated C string.
+  explicit MyString(const char* a_c_string) : c_string_(NULL) {
+    Set(a_c_string);
+  }
+
+  // Copy c'tor
+  MyString(const MyString& string) : c_string_(NULL) {
+    Set(string.c_string_);
+  }
+
+  ////////////////////////////////////////////////////////////
+  //
+  // D'tor.  MyString is intended to be a final class, so the d'tor
+  // doesn't need to be virtual.
+  ~MyString() { delete[] c_string_; }
+
+  // Gets the 0-terminated C string this MyString object represents.
+  const char* c_string() const { return c_string_; }
+
+  size_t Length() const {
+    return c_string_ == NULL ? 0 : strlen(c_string_);
+  }
+
+  // Sets the 0-terminated C string this MyString object represents.
+  void Set(const char* c_string);
+};
+
+
+#endif  // GTEST_SAMPLES_SAMPLE2_H_
diff --git a/third_party/googletest/src/samples/sample2_unittest.cc b/third_party/googletest/src/samples/sample2_unittest.cc
new file mode 100644 (file)
index 0000000..3792fa5
--- /dev/null
@@ -0,0 +1,109 @@
+// Copyright 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.
+
+// A sample program demonstrating using Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+
+// This sample shows how to write a more complex unit test for a class
+// that has multiple member functions.
+//
+// Usually, it's a good idea to have one test for each method in your
+// class.  You don't have to do that exactly, but it helps to keep
+// your tests organized.  You may also throw in additional tests as
+// needed.
+
+#include "sample2.h"
+#include "gtest/gtest.h"
+
+// In this example, we test the MyString class (a simple string).
+
+// Tests the default c'tor.
+TEST(MyString, DefaultConstructor) {
+  const MyString s;
+
+  // Asserts that s.c_string() returns NULL.
+  //
+  // <TechnicalDetails>
+  //
+  // If we write NULL instead of
+  //
+  //   static_cast<const char *>(NULL)
+  //
+  // in this assertion, it will generate a warning on gcc 3.4.  The
+  // reason is that EXPECT_EQ needs to know the types of its
+  // arguments in order to print them when it fails.  Since NULL is
+  // #defined as 0, the compiler will use the formatter function for
+  // int to print it.  However, gcc thinks that NULL should be used as
+  // a pointer, not an int, and therefore complains.
+  //
+  // The root of the problem is C++'s lack of distinction between the
+  // integer number 0 and the null pointer constant.  Unfortunately,
+  // we have to live with this fact.
+  //
+  // </TechnicalDetails>
+  EXPECT_STREQ(NULL, s.c_string());
+
+  EXPECT_EQ(0u, s.Length());
+}
+
+const char kHelloString[] = "Hello, world!";
+
+// Tests the c'tor that accepts a C string.
+TEST(MyString, ConstructorFromCString) {
+  const MyString s(kHelloString);
+  EXPECT_TRUE(strcmp(s.c_string(), kHelloString) == 0);
+  EXPECT_EQ(sizeof(kHelloString)/sizeof(kHelloString[0]) - 1,
+            s.Length());
+}
+
+// Tests the copy c'tor.
+TEST(MyString, CopyConstructor) {
+  const MyString s1(kHelloString);
+  const MyString s2 = s1;
+  EXPECT_TRUE(strcmp(s2.c_string(), kHelloString) == 0);
+}
+
+// Tests the Set method.
+TEST(MyString, Set) {
+  MyString s;
+
+  s.Set(kHelloString);
+  EXPECT_TRUE(strcmp(s.c_string(), kHelloString) == 0);
+
+  // Set should work when the input pointer is the same as the one
+  // already in the MyString object.
+  s.Set(s.c_string());
+  EXPECT_TRUE(strcmp(s.c_string(), kHelloString) == 0);
+
+  // Can we set the MyString to NULL?
+  s.Set(NULL);
+  EXPECT_STREQ(NULL, s.c_string());
+}
diff --git a/third_party/googletest/src/samples/sample3-inl.h b/third_party/googletest/src/samples/sample3-inl.h
new file mode 100644 (file)
index 0000000..46369a0
--- /dev/null
@@ -0,0 +1,173 @@
+// Copyright 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.
+
+// A sample program demonstrating using Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#ifndef GTEST_SAMPLES_SAMPLE3_INL_H_
+#define GTEST_SAMPLES_SAMPLE3_INL_H_
+
+#include <stddef.h>
+
+
+// Queue is a simple queue implemented as a singled-linked list.
+//
+// The element type must support copy constructor.
+template <typename E>  // E is the element type
+class Queue;
+
+// QueueNode is a node in a Queue, which consists of an element of
+// type E and a pointer to the next node.
+template <typename E>  // E is the element type
+class QueueNode {
+  friend class Queue<E>;
+
+ public:
+  // Gets the element in this node.
+  const E& element() const { return element_; }
+
+  // Gets the next node in the queue.
+  QueueNode* next() { return next_; }
+  const QueueNode* next() const { return next_; }
+
+ private:
+  // Creates a node with a given element value.  The next pointer is
+  // set to NULL.
+  QueueNode(const E& an_element) : element_(an_element), next_(NULL) {}
+
+  // We disable the default assignment operator and copy c'tor.
+  const QueueNode& operator = (const QueueNode&);
+  QueueNode(const QueueNode&);
+
+  E element_;
+  QueueNode* next_;
+};
+
+template <typename E>  // E is the element type.
+class Queue {
+public:
+
+  // Creates an empty queue.
+  Queue() : head_(NULL), last_(NULL), size_(0) {}
+
+  // D'tor.  Clears the queue.
+  ~Queue() { Clear(); }
+
+  // Clears the queue.
+  void Clear() {
+    if (size_ > 0) {
+      // 1. Deletes every node.
+      QueueNode<E>* node = head_;
+      QueueNode<E>* next = node->next();
+      for (; ;) {
+        delete node;
+        node = next;
+        if (node == NULL) break;
+        next = node->next();
+      }
+
+      // 2. Resets the member variables.
+      head_ = last_ = NULL;
+      size_ = 0;
+    }
+  }
+
+  // Gets the number of elements.
+  size_t Size() const { return size_; }
+
+  // Gets the first element of the queue, or NULL if the queue is empty.
+  QueueNode<E>* Head() { return head_; }
+  const QueueNode<E>* Head() const { return head_; }
+
+  // Gets the last element of the queue, or NULL if the queue is empty.
+  QueueNode<E>* Last() { return last_; }
+  const QueueNode<E>* Last() const { return last_; }
+
+  // Adds an element to the end of the queue.  A copy of the element is
+  // created using the copy constructor, and then stored in the queue.
+  // Changes made to the element in the queue doesn't affect the source
+  // object, and vice versa.
+  void Enqueue(const E& element) {
+    QueueNode<E>* new_node = new QueueNode<E>(element);
+
+    if (size_ == 0) {
+      head_ = last_ = new_node;
+      size_ = 1;
+    } else {
+      last_->next_ = new_node;
+      last_ = new_node;
+      size_++;
+    }
+  }
+
+  // Removes the head of the queue and returns it.  Returns NULL if
+  // the queue is empty.
+  E* Dequeue() {
+    if (size_ == 0) {
+      return NULL;
+    }
+
+    const QueueNode<E>* const old_head = head_;
+    head_ = head_->next_;
+    size_--;
+    if (size_ == 0) {
+      last_ = NULL;
+    }
+
+    E* element = new E(old_head->element());
+    delete old_head;
+
+    return element;
+  }
+
+  // Applies a function/functor on each element of the queue, and
+  // returns the result in a new queue.  The original queue is not
+  // affected.
+  template <typename F>
+  Queue* Map(F function) const {
+    Queue* new_queue = new Queue();
+    for (const QueueNode<E>* node = head_; node != NULL; node = node->next_) {
+      new_queue->Enqueue(function(node->element()));
+    }
+
+    return new_queue;
+  }
+
+ private:
+  QueueNode<E>* head_;  // The first node of the queue.
+  QueueNode<E>* last_;  // The last node of the queue.
+  size_t size_;  // The number of elements in the queue.
+
+  // We disallow copying a queue.
+  Queue(const Queue&);
+  const Queue& operator = (const Queue&);
+ };
+
+#endif  // GTEST_SAMPLES_SAMPLE3_INL_H_
diff --git a/third_party/googletest/src/samples/sample3_unittest.cc b/third_party/googletest/src/samples/sample3_unittest.cc
new file mode 100644 (file)
index 0000000..bf3877d
--- /dev/null
@@ -0,0 +1,151 @@
+// Copyright 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.
+
+// A sample program demonstrating using Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+
+// In this example, we use a more advanced feature of Google Test called
+// test fixture.
+//
+// A test fixture is a place to hold objects and functions shared by
+// all tests in a test case.  Using a test fixture avoids duplicating
+// the test code necessary to initialize and cleanup those common
+// objects for each test.  It is also useful for defining sub-routines
+// that your tests need to invoke a lot.
+//
+// <TechnicalDetails>
+//
+// The tests share the test fixture in the sense of code sharing, not
+// data sharing.  Each test is given its own fresh copy of the
+// fixture.  You cannot expect the data modified by one test to be
+// passed on to another test, which is a bad idea.
+//
+// The reason for this design is that tests should be independent and
+// repeatable.  In particular, a test should not fail as the result of
+// another test's failure.  If one test depends on info produced by
+// another test, then the two tests should really be one big test.
+//
+// The macros for indicating the success/failure of a test
+// (EXPECT_TRUE, FAIL, etc) need to know what the current test is
+// (when Google Test prints the test result, it tells you which test
+// each failure belongs to).  Technically, these macros invoke a
+// member function of the Test class.  Therefore, you cannot use them
+// in a global function.  That's why you should put test sub-routines
+// in a test fixture.
+//
+// </TechnicalDetails>
+
+#include "sample3-inl.h"
+#include "gtest/gtest.h"
+
+// To use a test fixture, derive a class from testing::Test.
+class QueueTest : public testing::Test {
+ protected:  // You should make the members protected s.t. they can be
+             // accessed from sub-classes.
+
+  // virtual void SetUp() will be called before each test is run.  You
+  // should define it if you need to initialize the varaibles.
+  // Otherwise, this can be skipped.
+  virtual void SetUp() {
+    q1_.Enqueue(1);
+    q2_.Enqueue(2);
+    q2_.Enqueue(3);
+  }
+
+  // virtual void TearDown() will be called after each test is run.
+  // You should define it if there is cleanup work to do.  Otherwise,
+  // you don't have to provide it.
+  //
+  // virtual void TearDown() {
+  // }
+
+  // A helper function that some test uses.
+  static int Double(int n) {
+    return 2*n;
+  }
+
+  // A helper function for testing Queue::Map().
+  void MapTester(const Queue<int> * q) {
+    // Creates a new queue, where each element is twice as big as the
+    // corresponding one in q.
+    const Queue<int> * const new_q = q->Map(Double);
+
+    // Verifies that the new queue has the same size as q.
+    ASSERT_EQ(q->Size(), new_q->Size());
+
+    // Verifies the relationship between the elements of the two queues.
+    for ( const QueueNode<int> * n1 = q->Head(), * n2 = new_q->Head();
+          n1 != NULL; n1 = n1->next(), n2 = n2->next() ) {
+      EXPECT_EQ(2 * n1->element(), n2->element());
+    }
+
+    delete new_q;
+  }
+
+  // Declares the variables your tests want to use.
+  Queue<int> q0_;
+  Queue<int> q1_;
+  Queue<int> q2_;
+};
+
+// When you have a test fixture, you define a test using TEST_F
+// instead of TEST.
+
+// Tests the default c'tor.
+TEST_F(QueueTest, DefaultConstructor) {
+  // You can access data in the test fixture here.
+  EXPECT_EQ(0u, q0_.Size());
+}
+
+// Tests Dequeue().
+TEST_F(QueueTest, Dequeue) {
+  int * n = q0_.Dequeue();
+  EXPECT_TRUE(n == NULL);
+
+  n = q1_.Dequeue();
+  ASSERT_TRUE(n != NULL);
+  EXPECT_EQ(1, *n);
+  EXPECT_EQ(0u, q1_.Size());
+  delete n;
+
+  n = q2_.Dequeue();
+  ASSERT_TRUE(n != NULL);
+  EXPECT_EQ(2, *n);
+  EXPECT_EQ(1u, q2_.Size());
+  delete n;
+}
+
+// Tests the Queue::Map() function.
+TEST_F(QueueTest, Map) {
+  MapTester(&q0_);
+  MapTester(&q1_);
+  MapTester(&q2_);
+}
diff --git a/third_party/googletest/src/samples/sample4.cc b/third_party/googletest/src/samples/sample4.cc
new file mode 100644 (file)
index 0000000..ae44bda
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 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.
+
+// A sample program demonstrating using Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include <stdio.h>
+
+#include "sample4.h"
+
+// Returns the current counter value, and increments it.
+int Counter::Increment() {
+  return counter_++;
+}
+
+// Prints the current counter value to STDOUT.
+void Counter::Print() const {
+  printf("%d", counter_);
+}
diff --git a/third_party/googletest/src/samples/sample4.h b/third_party/googletest/src/samples/sample4.h
new file mode 100644 (file)
index 0000000..cd60f0d
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright 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.
+
+// A sample program demonstrating using Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#ifndef GTEST_SAMPLES_SAMPLE4_H_
+#define GTEST_SAMPLES_SAMPLE4_H_
+
+// A simple monotonic counter.
+class Counter {
+ private:
+  int counter_;
+
+ public:
+  // Creates a counter that starts at 0.
+  Counter() : counter_(0) {}
+
+  // Returns the current counter value, and increments it.
+  int Increment();
+
+  // Prints the current counter value to STDOUT.
+  void Print() const;
+};
+
+#endif  // GTEST_SAMPLES_SAMPLE4_H_
diff --git a/third_party/googletest/src/samples/sample4_unittest.cc b/third_party/googletest/src/samples/sample4_unittest.cc
new file mode 100644 (file)
index 0000000..fa5afc7
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright 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: wan@google.com (Zhanyong Wan)
+
+#include "gtest/gtest.h"
+#include "sample4.h"
+
+// Tests the Increment() method.
+TEST(Counter, Increment) {
+  Counter c;
+
+  // EXPECT_EQ() evaluates its arguments exactly once, so they
+  // can have side effects.
+
+  EXPECT_EQ(0, c.Increment());
+  EXPECT_EQ(1, c.Increment());
+  EXPECT_EQ(2, c.Increment());
+}
diff --git a/third_party/googletest/src/samples/sample5_unittest.cc b/third_party/googletest/src/samples/sample5_unittest.cc
new file mode 100644 (file)
index 0000000..e7cab01
--- /dev/null
@@ -0,0 +1,199 @@
+// Copyright 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: wan@google.com (Zhanyong Wan)
+
+// This sample teaches how to reuse a test fixture in multiple test
+// cases by deriving sub-fixtures from it.
+//
+// When you define a test fixture, you specify the name of the test
+// case that will use this fixture.  Therefore, a test fixture can
+// be used by only one test case.
+//
+// Sometimes, more than one test cases may want to use the same or
+// slightly different test fixtures.  For example, you may want to
+// make sure that all tests for a GUI library don't leak important
+// system resources like fonts and brushes.  In Google Test, you do
+// this by putting the shared logic in a super (as in "super class")
+// test fixture, and then have each test case use a fixture derived
+// from this super fixture.
+
+#include <limits.h>
+#include <time.h>
+#include "sample3-inl.h"
+#include "gtest/gtest.h"
+#include "sample1.h"
+
+// In this sample, we want to ensure that every test finishes within
+// ~5 seconds.  If a test takes longer to run, we consider it a
+// failure.
+//
+// We put the code for timing a test in a test fixture called
+// "QuickTest".  QuickTest is intended to be the super fixture that
+// other fixtures derive from, therefore there is no test case with
+// the name "QuickTest".  This is OK.
+//
+// Later, we will derive multiple test fixtures from QuickTest.
+class QuickTest : public testing::Test {
+ protected:
+  // Remember that SetUp() is run immediately before a test starts.
+  // This is a good place to record the start time.
+  virtual void SetUp() {
+    start_time_ = time(NULL);
+  }
+
+  // TearDown() is invoked immediately after a test finishes.  Here we
+  // check if the test was too slow.
+  virtual void TearDown() {
+    // Gets the time when the test finishes
+    const time_t end_time = time(NULL);
+
+    // Asserts that the test took no more than ~5 seconds.  Did you
+    // know that you can use assertions in SetUp() and TearDown() as
+    // well?
+    EXPECT_TRUE(end_time - start_time_ <= 5) << "The test took too long.";
+  }
+
+  // The UTC time (in seconds) when the test starts
+  time_t start_time_;
+};
+
+
+// We derive a fixture named IntegerFunctionTest from the QuickTest
+// fixture.  All tests using this fixture will be automatically
+// required to be quick.
+class IntegerFunctionTest : public QuickTest {
+  // We don't need any more logic than already in the QuickTest fixture.
+  // Therefore the body is empty.
+};
+
+
+// Now we can write tests in the IntegerFunctionTest test case.
+
+// Tests Factorial()
+TEST_F(IntegerFunctionTest, Factorial) {
+  // Tests factorial of negative numbers.
+  EXPECT_EQ(1, Factorial(-5));
+  EXPECT_EQ(1, Factorial(-1));
+  EXPECT_TRUE(Factorial(-10) > 0);
+
+  // Tests factorial of 0.
+  EXPECT_EQ(1, Factorial(0));
+
+  // Tests factorial of positive numbers.
+  EXPECT_EQ(1, Factorial(1));
+  EXPECT_EQ(2, Factorial(2));
+  EXPECT_EQ(6, Factorial(3));
+  EXPECT_EQ(40320, Factorial(8));
+}
+
+
+// Tests IsPrime()
+TEST_F(IntegerFunctionTest, IsPrime) {
+  // Tests negative input.
+  EXPECT_TRUE(!IsPrime(-1));
+  EXPECT_TRUE(!IsPrime(-2));
+  EXPECT_TRUE(!IsPrime(INT_MIN));
+
+  // Tests some trivial cases.
+  EXPECT_TRUE(!IsPrime(0));
+  EXPECT_TRUE(!IsPrime(1));
+  EXPECT_TRUE(IsPrime(2));
+  EXPECT_TRUE(IsPrime(3));
+
+  // Tests positive input.
+  EXPECT_TRUE(!IsPrime(4));
+  EXPECT_TRUE(IsPrime(5));
+  EXPECT_TRUE(!IsPrime(6));
+  EXPECT_TRUE(IsPrime(23));
+}
+
+
+// The next test case (named "QueueTest") also needs to be quick, so
+// we derive another fixture from QuickTest.
+//
+// The QueueTest test fixture has some logic and shared objects in
+// addition to what's in QuickTest already.  We define the additional
+// stuff inside the body of the test fixture, as usual.
+class QueueTest : public QuickTest {
+ protected:
+  virtual void SetUp() {
+    // First, we need to set up the super fixture (QuickTest).
+    QuickTest::SetUp();
+
+    // Second, some additional setup for this fixture.
+    q1_.Enqueue(1);
+    q2_.Enqueue(2);
+    q2_.Enqueue(3);
+  }
+
+  // By default, TearDown() inherits the behavior of
+  // QuickTest::TearDown().  As we have no additional cleaning work
+  // for QueueTest, we omit it here.
+  //
+  // virtual void TearDown() {
+  //   QuickTest::TearDown();
+  // }
+
+  Queue<int> q0_;
+  Queue<int> q1_;
+  Queue<int> q2_;
+};
+
+
+// Now, let's write tests using the QueueTest fixture.
+
+// Tests the default constructor.
+TEST_F(QueueTest, DefaultConstructor) {
+  EXPECT_EQ(0u, q0_.Size());
+}
+
+// Tests Dequeue().
+TEST_F(QueueTest, Dequeue) {
+  int* n = q0_.Dequeue();
+  EXPECT_TRUE(n == NULL);
+
+  n = q1_.Dequeue();
+  EXPECT_TRUE(n != NULL);
+  EXPECT_EQ(1, *n);
+  EXPECT_EQ(0u, q1_.Size());
+  delete n;
+
+  n = q2_.Dequeue();
+  EXPECT_TRUE(n != NULL);
+  EXPECT_EQ(2, *n);
+  EXPECT_EQ(1u, q2_.Size());
+  delete n;
+}
+
+// If necessary, you can derive further test fixtures from a derived
+// fixture itself.  For example, you can derive another fixture from
+// QueueTest.  Google Test imposes no limit on how deep the hierarchy
+// can be.  In practice, however, you probably don't want it to be too
+// deep as to be confusing.
diff --git a/third_party/googletest/src/samples/sample6_unittest.cc b/third_party/googletest/src/samples/sample6_unittest.cc
new file mode 100644 (file)
index 0000000..8f2036a
--- /dev/null
@@ -0,0 +1,224 @@
+// Copyright 2008 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: wan@google.com (Zhanyong Wan)
+
+// This sample shows how to test common properties of multiple
+// implementations of the same interface (aka interface tests).
+
+// The interface and its implementations are in this header.
+#include "prime_tables.h"
+
+#include "gtest/gtest.h"
+
+// First, we define some factory functions for creating instances of
+// the implementations.  You may be able to skip this step if all your
+// implementations can be constructed the same way.
+
+template <class T>
+PrimeTable* CreatePrimeTable();
+
+template <>
+PrimeTable* CreatePrimeTable<OnTheFlyPrimeTable>() {
+  return new OnTheFlyPrimeTable;
+}
+
+template <>
+PrimeTable* CreatePrimeTable<PreCalculatedPrimeTable>() {
+  return new PreCalculatedPrimeTable(10000);
+}
+
+// Then we define a test fixture class template.
+template <class T>
+class PrimeTableTest : public testing::Test {
+ protected:
+  // The ctor calls the factory function to create a prime table
+  // implemented by T.
+  PrimeTableTest() : table_(CreatePrimeTable<T>()) {}
+
+  virtual ~PrimeTableTest() { delete table_; }
+
+  // Note that we test an implementation via the base interface
+  // instead of the actual implementation class.  This is important
+  // for keeping the tests close to the real world scenario, where the
+  // implementation is invoked via the base interface.  It avoids
+  // got-yas where the implementation class has a method that shadows
+  // a method with the same name (but slightly different argument
+  // types) in the base interface, for example.
+  PrimeTable* const table_;
+};
+
+#if GTEST_HAS_TYPED_TEST
+
+using testing::Types;
+
+// Google Test offers two ways for reusing tests for different types.
+// The first is called "typed tests".  You should use it if you
+// already know *all* the types you are gonna exercise when you write
+// the tests.
+
+// To write a typed test case, first use
+//
+//   TYPED_TEST_CASE(TestCaseName, TypeList);
+//
+// to declare it and specify the type parameters.  As with TEST_F,
+// TestCaseName must match the test fixture name.
+
+// The list of types we want to test.
+typedef Types<OnTheFlyPrimeTable, PreCalculatedPrimeTable> Implementations;
+
+TYPED_TEST_CASE(PrimeTableTest, Implementations);
+
+// Then use TYPED_TEST(TestCaseName, TestName) to define a typed test,
+// similar to TEST_F.
+TYPED_TEST(PrimeTableTest, ReturnsFalseForNonPrimes) {
+  // Inside the test body, you can refer to the type parameter by
+  // TypeParam, and refer to the fixture class by TestFixture.  We
+  // don't need them in this example.
+
+  // Since we are in the template world, C++ requires explicitly
+  // writing 'this->' when referring to members of the fixture class.
+  // This is something you have to learn to live with.
+  EXPECT_FALSE(this->table_->IsPrime(-5));
+  EXPECT_FALSE(this->table_->IsPrime(0));
+  EXPECT_FALSE(this->table_->IsPrime(1));
+  EXPECT_FALSE(this->table_->IsPrime(4));
+  EXPECT_FALSE(this->table_->IsPrime(6));
+  EXPECT_FALSE(this->table_->IsPrime(100));
+}
+
+TYPED_TEST(PrimeTableTest, ReturnsTrueForPrimes) {
+  EXPECT_TRUE(this->table_->IsPrime(2));
+  EXPECT_TRUE(this->table_->IsPrime(3));
+  EXPECT_TRUE(this->table_->IsPrime(5));
+  EXPECT_TRUE(this->table_->IsPrime(7));
+  EXPECT_TRUE(this->table_->IsPrime(11));
+  EXPECT_TRUE(this->table_->IsPrime(131));
+}
+
+TYPED_TEST(PrimeTableTest, CanGetNextPrime) {
+  EXPECT_EQ(2, this->table_->GetNextPrime(0));
+  EXPECT_EQ(3, this->table_->GetNextPrime(2));
+  EXPECT_EQ(5, this->table_->GetNextPrime(3));
+  EXPECT_EQ(7, this->table_->GetNextPrime(5));
+  EXPECT_EQ(11, this->table_->GetNextPrime(7));
+  EXPECT_EQ(131, this->table_->GetNextPrime(128));
+}
+
+// That's it!  Google Test will repeat each TYPED_TEST for each type
+// in the type list specified in TYPED_TEST_CASE.  Sit back and be
+// happy that you don't have to define them multiple times.
+
+#endif  // GTEST_HAS_TYPED_TEST
+
+#if GTEST_HAS_TYPED_TEST_P
+
+using testing::Types;
+
+// Sometimes, however, you don't yet know all the types that you want
+// to test when you write the tests.  For example, if you are the
+// author of an interface and expect other people to implement it, you
+// might want to write a set of tests to make sure each implementation
+// conforms to some basic requirements, but you don't know what
+// implementations will be written in the future.
+//
+// How can you write the tests without committing to the type
+// parameters?  That's what "type-parameterized tests" can do for you.
+// It is a bit more involved than typed tests, but in return you get a
+// test pattern that can be reused in many contexts, which is a big
+// win.  Here's how you do it:
+
+// First, define a test fixture class template.  Here we just reuse
+// the PrimeTableTest fixture defined earlier:
+
+template <class T>
+class PrimeTableTest2 : public PrimeTableTest<T> {
+};
+
+// Then, declare the test case.  The argument is the name of the test
+// fixture, and also the name of the test case (as usual).  The _P
+// suffix is for "parameterized" or "pattern".
+TYPED_TEST_CASE_P(PrimeTableTest2);
+
+// Next, use TYPED_TEST_P(TestCaseName, TestName) to define a test,
+// similar to what you do with TEST_F.
+TYPED_TEST_P(PrimeTableTest2, ReturnsFalseForNonPrimes) {
+  EXPECT_FALSE(this->table_->IsPrime(-5));
+  EXPECT_FALSE(this->table_->IsPrime(0));
+  EXPECT_FALSE(this->table_->IsPrime(1));
+  EXPECT_FALSE(this->table_->IsPrime(4));
+  EXPECT_FALSE(this->table_->IsPrime(6));
+  EXPECT_FALSE(this->table_->IsPrime(100));
+}
+
+TYPED_TEST_P(PrimeTableTest2, ReturnsTrueForPrimes) {
+  EXPECT_TRUE(this->table_->IsPrime(2));
+  EXPECT_TRUE(this->table_->IsPrime(3));
+  EXPECT_TRUE(this->table_->IsPrime(5));
+  EXPECT_TRUE(this->table_->IsPrime(7));
+  EXPECT_TRUE(this->table_->IsPrime(11));
+  EXPECT_TRUE(this->table_->IsPrime(131));
+}
+
+TYPED_TEST_P(PrimeTableTest2, CanGetNextPrime) {
+  EXPECT_EQ(2, this->table_->GetNextPrime(0));
+  EXPECT_EQ(3, this->table_->GetNextPrime(2));
+  EXPECT_EQ(5, this->table_->GetNextPrime(3));
+  EXPECT_EQ(7, this->table_->GetNextPrime(5));
+  EXPECT_EQ(11, this->table_->GetNextPrime(7));
+  EXPECT_EQ(131, this->table_->GetNextPrime(128));
+}
+
+// Type-parameterized tests involve one extra step: you have to
+// enumerate the tests you defined:
+REGISTER_TYPED_TEST_CASE_P(
+    PrimeTableTest2,  // The first argument is the test case name.
+    // The rest of the arguments are the test names.
+    ReturnsFalseForNonPrimes, ReturnsTrueForPrimes, CanGetNextPrime);
+
+// At this point the test pattern is done.  However, you don't have
+// any real test yet as you haven't said which types you want to run
+// the tests with.
+
+// To turn the abstract test pattern into real tests, you instantiate
+// it with a list of types.  Usually the test pattern will be defined
+// in a .h file, and anyone can #include and instantiate it.  You can
+// even instantiate it more than once in the same program.  To tell
+// different instances apart, you give each of them a name, which will
+// become part of the test case name and can be used in test filters.
+
+// The list of types we want to test.  Note that it doesn't have to be
+// defined at the time we write the TYPED_TEST_P()s.
+typedef Types<OnTheFlyPrimeTable, PreCalculatedPrimeTable>
+    PrimeTableImplementations;
+INSTANTIATE_TYPED_TEST_CASE_P(OnTheFlyAndPreCalculated,    // Instance name
+                              PrimeTableTest2,             // Test case name
+                              PrimeTableImplementations);  // Type list
+
+#endif  // GTEST_HAS_TYPED_TEST_P
diff --git a/third_party/googletest/src/samples/sample7_unittest.cc b/third_party/googletest/src/samples/sample7_unittest.cc
new file mode 100644 (file)
index 0000000..1b651a2
--- /dev/null
@@ -0,0 +1,130 @@
+// Copyright 2008 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: vladl@google.com (Vlad Losev)
+
+// This sample shows how to test common properties of multiple
+// implementations of an interface (aka interface tests) using
+// value-parameterized tests. Each test in the test case has
+// a parameter that is an interface pointer to an implementation
+// tested.
+
+// The interface and its implementations are in this header.
+#include "prime_tables.h"
+
+#include "gtest/gtest.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+using ::testing::TestWithParam;
+using ::testing::Values;
+
+// As a general rule, to prevent a test from affecting the tests that come
+// after it, you should create and destroy the tested objects for each test
+// instead of reusing them.  In this sample we will define a simple factory
+// function for PrimeTable objects.  We will instantiate objects in test's
+// SetUp() method and delete them in TearDown() method.
+typedef PrimeTable* CreatePrimeTableFunc();
+
+PrimeTable* CreateOnTheFlyPrimeTable() {
+  return new OnTheFlyPrimeTable();
+}
+
+template <size_t max_precalculated>
+PrimeTable* CreatePreCalculatedPrimeTable() {
+  return new PreCalculatedPrimeTable(max_precalculated);
+}
+
+// Inside the test body, fixture constructor, SetUp(), and TearDown() you
+// can refer to the test parameter by GetParam().  In this case, the test
+// parameter is a factory function which we call in fixture's SetUp() to
+// create and store an instance of PrimeTable.
+class PrimeTableTest : public TestWithParam<CreatePrimeTableFunc*> {
+ public:
+  virtual ~PrimeTableTest() { delete table_; }
+  virtual void SetUp() { table_ = (*GetParam())(); }
+  virtual void TearDown() {
+    delete table_;
+    table_ = NULL;
+  }
+
+ protected:
+  PrimeTable* table_;
+};
+
+TEST_P(PrimeTableTest, ReturnsFalseForNonPrimes) {
+  EXPECT_FALSE(table_->IsPrime(-5));
+  EXPECT_FALSE(table_->IsPrime(0));
+  EXPECT_FALSE(table_->IsPrime(1));
+  EXPECT_FALSE(table_->IsPrime(4));
+  EXPECT_FALSE(table_->IsPrime(6));
+  EXPECT_FALSE(table_->IsPrime(100));
+}
+
+TEST_P(PrimeTableTest, ReturnsTrueForPrimes) {
+  EXPECT_TRUE(table_->IsPrime(2));
+  EXPECT_TRUE(table_->IsPrime(3));
+  EXPECT_TRUE(table_->IsPrime(5));
+  EXPECT_TRUE(table_->IsPrime(7));
+  EXPECT_TRUE(table_->IsPrime(11));
+  EXPECT_TRUE(table_->IsPrime(131));
+}
+
+TEST_P(PrimeTableTest, CanGetNextPrime) {
+  EXPECT_EQ(2, table_->GetNextPrime(0));
+  EXPECT_EQ(3, table_->GetNextPrime(2));
+  EXPECT_EQ(5, table_->GetNextPrime(3));
+  EXPECT_EQ(7, table_->GetNextPrime(5));
+  EXPECT_EQ(11, table_->GetNextPrime(7));
+  EXPECT_EQ(131, table_->GetNextPrime(128));
+}
+
+// In order to run value-parameterized tests, you need to instantiate them,
+// or bind them to a list of values which will be used as test parameters.
+// You can instantiate them in a different translation module, or even
+// instantiate them several times.
+//
+// Here, we instantiate our tests with a list of two PrimeTable object
+// factory functions:
+INSTANTIATE_TEST_CASE_P(
+    OnTheFlyAndPreCalculated,
+    PrimeTableTest,
+    Values(&CreateOnTheFlyPrimeTable, &CreatePreCalculatedPrimeTable<1000>));
+
+#else
+
+// Google Test may not support value-parameterized tests with some
+// compilers. If we use conditional compilation to compile out all
+// code referring to the gtest_main library, MSVC linker will not link
+// that library at all and consequently complain about missing entry
+// point defined in that library (fatal error LNK1561: entry point
+// must be defined). This dummy test keeps gtest_main linked in.
+TEST(DummyTest, ValueParameterizedTestsAreNotSupportedOnThisPlatform) {}
+
+#endif  // GTEST_HAS_PARAM_TEST
diff --git a/third_party/googletest/src/samples/sample8_unittest.cc b/third_party/googletest/src/samples/sample8_unittest.cc
new file mode 100644 (file)
index 0000000..5ad2e2c
--- /dev/null
@@ -0,0 +1,173 @@
+// Copyright 2008 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: vladl@google.com (Vlad Losev)
+
+// This sample shows how to test code relying on some global flag variables.
+// Combine() helps with generating all possible combinations of such flags,
+// and each test is given one combination as a parameter.
+
+// Use class definitions to test from this header.
+#include "prime_tables.h"
+
+#include "gtest/gtest.h"
+
+#if GTEST_HAS_COMBINE
+
+// Suppose we want to introduce a new, improved implementation of PrimeTable
+// which combines speed of PrecalcPrimeTable and versatility of
+// OnTheFlyPrimeTable (see prime_tables.h). Inside it instantiates both
+// PrecalcPrimeTable and OnTheFlyPrimeTable and uses the one that is more
+// appropriate under the circumstances. But in low memory conditions, it can be
+// told to instantiate without PrecalcPrimeTable instance at all and use only
+// OnTheFlyPrimeTable.
+class HybridPrimeTable : public PrimeTable {
+ public:
+  HybridPrimeTable(bool force_on_the_fly, int max_precalculated)
+      : on_the_fly_impl_(new OnTheFlyPrimeTable),
+        precalc_impl_(force_on_the_fly ? NULL :
+                          new PreCalculatedPrimeTable(max_precalculated)),
+        max_precalculated_(max_precalculated) {}
+  virtual ~HybridPrimeTable() {
+    delete on_the_fly_impl_;
+    delete precalc_impl_;
+  }
+
+  virtual bool IsPrime(int n) const {
+    if (precalc_impl_ != NULL && n < max_precalculated_)
+      return precalc_impl_->IsPrime(n);
+    else
+      return on_the_fly_impl_->IsPrime(n);
+  }
+
+  virtual int GetNextPrime(int p) const {
+    int next_prime = -1;
+    if (precalc_impl_ != NULL && p < max_precalculated_)
+      next_prime = precalc_impl_->GetNextPrime(p);
+
+    return next_prime != -1 ? next_prime : on_the_fly_impl_->GetNextPrime(p);
+  }
+
+ private:
+  OnTheFlyPrimeTable* on_the_fly_impl_;
+  PreCalculatedPrimeTable* precalc_impl_;
+  int max_precalculated_;
+};
+
+using ::testing::TestWithParam;
+using ::testing::Bool;
+using ::testing::Values;
+using ::testing::Combine;
+
+// To test all code paths for HybridPrimeTable we must test it with numbers
+// both within and outside PreCalculatedPrimeTable's capacity and also with
+// PreCalculatedPrimeTable disabled. We do this by defining fixture which will
+// accept different combinations of parameters for instantiating a
+// HybridPrimeTable instance.
+class PrimeTableTest : public TestWithParam< ::std::tr1::tuple<bool, int> > {
+ protected:
+  virtual void SetUp() {
+    // This can be written as
+    //
+    // bool force_on_the_fly;
+    // int max_precalculated;
+    // tie(force_on_the_fly, max_precalculated) = GetParam();
+    //
+    // once the Google C++ Style Guide allows use of ::std::tr1::tie.
+    //
+    bool force_on_the_fly = ::std::tr1::get<0>(GetParam());
+    int max_precalculated = ::std::tr1::get<1>(GetParam());
+    table_ = new HybridPrimeTable(force_on_the_fly, max_precalculated);
+  }
+  virtual void TearDown() {
+    delete table_;
+    table_ = NULL;
+  }
+  HybridPrimeTable* table_;
+};
+
+TEST_P(PrimeTableTest, ReturnsFalseForNonPrimes) {
+  // Inside the test body, you can refer to the test parameter by GetParam().
+  // In this case, the test parameter is a PrimeTable interface pointer which
+  // we can use directly.
+  // Please note that you can also save it in the fixture's SetUp() method
+  // or constructor and use saved copy in the tests.
+
+  EXPECT_FALSE(table_->IsPrime(-5));
+  EXPECT_FALSE(table_->IsPrime(0));
+  EXPECT_FALSE(table_->IsPrime(1));
+  EXPECT_FALSE(table_->IsPrime(4));
+  EXPECT_FALSE(table_->IsPrime(6));
+  EXPECT_FALSE(table_->IsPrime(100));
+}
+
+TEST_P(PrimeTableTest, ReturnsTrueForPrimes) {
+  EXPECT_TRUE(table_->IsPrime(2));
+  EXPECT_TRUE(table_->IsPrime(3));
+  EXPECT_TRUE(table_->IsPrime(5));
+  EXPECT_TRUE(table_->IsPrime(7));
+  EXPECT_TRUE(table_->IsPrime(11));
+  EXPECT_TRUE(table_->IsPrime(131));
+}
+
+TEST_P(PrimeTableTest, CanGetNextPrime) {
+  EXPECT_EQ(2, table_->GetNextPrime(0));
+  EXPECT_EQ(3, table_->GetNextPrime(2));
+  EXPECT_EQ(5, table_->GetNextPrime(3));
+  EXPECT_EQ(7, table_->GetNextPrime(5));
+  EXPECT_EQ(11, table_->GetNextPrime(7));
+  EXPECT_EQ(131, table_->GetNextPrime(128));
+}
+
+// In order to run value-parameterized tests, you need to instantiate them,
+// or bind them to a list of values which will be used as test parameters.
+// You can instantiate them in a different translation module, or even
+// instantiate them several times.
+//
+// Here, we instantiate our tests with a list of parameters. We must combine
+// all variations of the boolean flag suppressing PrecalcPrimeTable and some
+// meaningful values for tests. We choose a small value (1), and a value that
+// will put some of the tested numbers beyond the capability of the
+// PrecalcPrimeTable instance and some inside it (10). Combine will produce all
+// possible combinations.
+INSTANTIATE_TEST_CASE_P(MeaningfulTestParameters,
+                        PrimeTableTest,
+                        Combine(Bool(), Values(1, 10)));
+
+#else
+
+// Google Test may not support Combine() with some compilers. If we
+// use conditional compilation to compile out all code referring to
+// the gtest_main library, MSVC linker will not link that library at
+// all and consequently complain about missing entry point defined in
+// that library (fatal error LNK1561: entry point must be
+// defined). This dummy test keeps gtest_main linked in.
+TEST(DummyTest, CombineIsNotSupportedOnThisPlatform) {}
+
+#endif  // GTEST_HAS_COMBINE
diff --git a/third_party/googletest/src/samples/sample9_unittest.cc b/third_party/googletest/src/samples/sample9_unittest.cc
new file mode 100644 (file)
index 0000000..b2e2079
--- /dev/null
@@ -0,0 +1,160 @@
+// Copyright 2009 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: vladl@google.com (Vlad Losev)
+
+// This sample shows how to use Google Test listener API to implement
+// an alternative console output and how to use the UnitTest reflection API
+// to enumerate test cases and tests and to inspect their results.
+
+#include <stdio.h>
+
+#include "gtest/gtest.h"
+
+using ::testing::EmptyTestEventListener;
+using ::testing::InitGoogleTest;
+using ::testing::Test;
+using ::testing::TestCase;
+using ::testing::TestEventListeners;
+using ::testing::TestInfo;
+using ::testing::TestPartResult;
+using ::testing::UnitTest;
+
+namespace {
+
+// Provides alternative output mode which produces minimal amount of
+// information about tests.
+class TersePrinter : public EmptyTestEventListener {
+ private:
+  // Called before any test activity starts.
+  virtual void OnTestProgramStart(const UnitTest& /* unit_test */) {}
+
+  // Called after all test activities have ended.
+  virtual void OnTestProgramEnd(const UnitTest& unit_test) {
+    fprintf(stdout, "TEST %s\n", unit_test.Passed() ? "PASSED" : "FAILED");
+    fflush(stdout);
+  }
+
+  // Called before a test starts.
+  virtual void OnTestStart(const TestInfo& test_info) {
+    fprintf(stdout,
+            "*** Test %s.%s starting.\n",
+            test_info.test_case_name(),
+            test_info.name());
+    fflush(stdout);
+  }
+
+  // Called after a failed assertion or a SUCCEED() invocation.
+  virtual void OnTestPartResult(const TestPartResult& test_part_result) {
+    fprintf(stdout,
+            "%s in %s:%d\n%s\n",
+            test_part_result.failed() ? "*** Failure" : "Success",
+            test_part_result.file_name(),
+            test_part_result.line_number(),
+            test_part_result.summary());
+    fflush(stdout);
+  }
+
+  // Called after a test ends.
+  virtual void OnTestEnd(const TestInfo& test_info) {
+    fprintf(stdout,
+            "*** Test %s.%s ending.\n",
+            test_info.test_case_name(),
+            test_info.name());
+    fflush(stdout);
+  }
+};  // class TersePrinter
+
+TEST(CustomOutputTest, PrintsMessage) {
+  printf("Printing something from the test body...\n");
+}
+
+TEST(CustomOutputTest, Succeeds) {
+  SUCCEED() << "SUCCEED() has been invoked from here";
+}
+
+TEST(CustomOutputTest, Fails) {
+  EXPECT_EQ(1, 2)
+      << "This test fails in order to demonstrate alternative failure messages";
+}
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  InitGoogleTest(&argc, argv);
+
+  bool terse_output = false;
+  if (argc > 1 && strcmp(argv[1], "--terse_output") == 0 )
+    terse_output = true;
+  else
+    printf("%s\n", "Run this program with --terse_output to change the way "
+           "it prints its output.");
+
+  UnitTest& unit_test = *UnitTest::GetInstance();
+
+  // If we are given the --terse_output command line flag, suppresses the
+  // standard output and attaches own result printer.
+  if (terse_output) {
+    TestEventListeners& listeners = unit_test.listeners();
+
+    // Removes the default console output listener from the list so it will
+    // not receive events from Google Test and won't print any output. Since
+    // this operation transfers ownership of the listener to the caller we
+    // have to delete it as well.
+    delete listeners.Release(listeners.default_result_printer());
+
+    // Adds the custom output listener to the list. It will now receive
+    // events from Google Test and print the alternative output. We don't
+    // have to worry about deleting it since Google Test assumes ownership
+    // over it after adding it to the list.
+    listeners.Append(new TersePrinter);
+  }
+  int ret_val = RUN_ALL_TESTS();
+
+  // This is an example of using the UnitTest reflection API to inspect test
+  // results. Here we discount failures from the tests we expected to fail.
+  int unexpectedly_failed_tests = 0;
+  for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
+    const TestCase& test_case = *unit_test.GetTestCase(i);
+    for (int j = 0; j < test_case.total_test_count(); ++j) {
+      const TestInfo& test_info = *test_case.GetTestInfo(j);
+      // Counts failed tests that were not meant to fail (those without
+      // 'Fails' in the name).
+      if (test_info.result()->Failed() &&
+          strcmp(test_info.name(), "Fails") != 0) {
+        unexpectedly_failed_tests++;
+      }
+    }
+  }
+
+  // Test that were meant to fail should not affect the test program outcome.
+  if (unexpectedly_failed_tests == 0)
+    ret_val = 0;
+
+  return ret_val;
+}
diff --git a/third_party/googletest/src/scripts/fuse_gtest_files.py b/third_party/googletest/src/scripts/fuse_gtest_files.py
new file mode 100755 (executable)
index 0000000..57ef72f
--- /dev/null
@@ -0,0 +1,250 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, 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.
+
+"""fuse_gtest_files.py v0.2.0
+Fuses Google Test source code into a .h file and a .cc file.
+
+SYNOPSIS
+       fuse_gtest_files.py [GTEST_ROOT_DIR] OUTPUT_DIR
+
+       Scans GTEST_ROOT_DIR for Google Test source code, and generates
+       two files: OUTPUT_DIR/gtest/gtest.h and OUTPUT_DIR/gtest/gtest-all.cc.
+       Then you can build your tests by adding OUTPUT_DIR to the include
+       search path and linking with OUTPUT_DIR/gtest/gtest-all.cc.  These
+       two files contain everything you need to use Google Test.  Hence
+       you can "install" Google Test by copying them to wherever you want.
+
+       GTEST_ROOT_DIR can be omitted and defaults to the parent
+       directory of the directory holding this script.
+
+EXAMPLES
+       ./fuse_gtest_files.py fused_gtest
+       ./fuse_gtest_files.py path/to/unpacked/gtest fused_gtest
+
+This tool is experimental.  In particular, it assumes that there is no
+conditional inclusion of Google Test headers.  Please report any
+problems to googletestframework@googlegroups.com.  You can read
+http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide for
+more information.
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import re
+import sets
+import sys
+
+# We assume that this file is in the scripts/ directory in the Google
+# Test root directory.
+DEFAULT_GTEST_ROOT_DIR = os.path.join(os.path.dirname(__file__), '..')
+
+# Regex for matching '#include "gtest/..."'.
+INCLUDE_GTEST_FILE_REGEX = re.compile(r'^\s*#\s*include\s*"(gtest/.+)"')
+
+# Regex for matching '#include "src/..."'.
+INCLUDE_SRC_FILE_REGEX = re.compile(r'^\s*#\s*include\s*"(src/.+)"')
+
+# Where to find the source seed files.
+GTEST_H_SEED = 'include/gtest/gtest.h'
+GTEST_SPI_H_SEED = 'include/gtest/gtest-spi.h'
+GTEST_ALL_CC_SEED = 'src/gtest-all.cc'
+
+# Where to put the generated files.
+GTEST_H_OUTPUT = 'gtest/gtest.h'
+GTEST_ALL_CC_OUTPUT = 'gtest/gtest-all.cc'
+
+
+def VerifyFileExists(directory, relative_path):
+  """Verifies that the given file exists; aborts on failure.
+
+  relative_path is the file path relative to the given directory.
+  """
+
+  if not os.path.isfile(os.path.join(directory, relative_path)):
+    print 'ERROR: Cannot find %s in directory %s.' % (relative_path,
+                                                      directory)
+    print ('Please either specify a valid project root directory '
+           'or omit it on the command line.')
+    sys.exit(1)
+
+
+def ValidateGTestRootDir(gtest_root):
+  """Makes sure gtest_root points to a valid gtest root directory.
+
+  The function aborts the program on failure.
+  """
+
+  VerifyFileExists(gtest_root, GTEST_H_SEED)
+  VerifyFileExists(gtest_root, GTEST_ALL_CC_SEED)
+
+
+def VerifyOutputFile(output_dir, relative_path):
+  """Verifies that the given output file path is valid.
+
+  relative_path is relative to the output_dir directory.
+  """
+
+  # Makes sure the output file either doesn't exist or can be overwritten.
+  output_file = os.path.join(output_dir, relative_path)
+  if os.path.exists(output_file):
+    # TODO(wan@google.com): The following user-interaction doesn't
+    # work with automated processes.  We should provide a way for the
+    # Makefile to force overwriting the files.
+    print ('%s already exists in directory %s - overwrite it? (y/N) ' %
+           (relative_path, output_dir))
+    answer = sys.stdin.readline().strip()
+    if answer not in ['y', 'Y']:
+      print 'ABORTED.'
+      sys.exit(1)
+
+  # Makes sure the directory holding the output file exists; creates
+  # it and all its ancestors if necessary.
+  parent_directory = os.path.dirname(output_file)
+  if not os.path.isdir(parent_directory):
+    os.makedirs(parent_directory)
+
+
+def ValidateOutputDir(output_dir):
+  """Makes sure output_dir points to a valid output directory.
+
+  The function aborts the program on failure.
+  """
+
+  VerifyOutputFile(output_dir, GTEST_H_OUTPUT)
+  VerifyOutputFile(output_dir, GTEST_ALL_CC_OUTPUT)
+
+
+def FuseGTestH(gtest_root, output_dir):
+  """Scans folder gtest_root to generate gtest/gtest.h in output_dir."""
+
+  output_file = file(os.path.join(output_dir, GTEST_H_OUTPUT), 'w')
+  processed_files = sets.Set()  # Holds all gtest headers we've processed.
+
+  def ProcessFile(gtest_header_path):
+    """Processes the given gtest header file."""
+
+    # We don't process the same header twice.
+    if gtest_header_path in processed_files:
+      return
+
+    processed_files.add(gtest_header_path)
+
+    # Reads each line in the given gtest header.
+    for line in file(os.path.join(gtest_root, gtest_header_path), 'r'):
+      m = INCLUDE_GTEST_FILE_REGEX.match(line)
+      if m:
+        # It's '#include "gtest/..."' - let's process it recursively.
+        ProcessFile('include/' + m.group(1))
+      else:
+        # Otherwise we copy the line unchanged to the output file.
+        output_file.write(line)
+
+  ProcessFile(GTEST_H_SEED)
+  output_file.close()
+
+
+def FuseGTestAllCcToFile(gtest_root, output_file):
+  """Scans folder gtest_root to generate gtest/gtest-all.cc in output_file."""
+
+  processed_files = sets.Set()
+
+  def ProcessFile(gtest_source_file):
+    """Processes the given gtest source file."""
+
+    # We don't process the same #included file twice.
+    if gtest_source_file in processed_files:
+      return
+
+    processed_files.add(gtest_source_file)
+
+    # Reads each line in the given gtest source file.
+    for line in file(os.path.join(gtest_root, gtest_source_file), 'r'):
+      m = INCLUDE_GTEST_FILE_REGEX.match(line)
+      if m:
+        if 'include/' + m.group(1) == GTEST_SPI_H_SEED:
+          # It's '#include "gtest/gtest-spi.h"'.  This file is not
+          # #included by "gtest/gtest.h", so we need to process it.
+          ProcessFile(GTEST_SPI_H_SEED)
+        else:
+          # It's '#include "gtest/foo.h"' where foo is not gtest-spi.
+          # We treat it as '#include "gtest/gtest.h"', as all other
+          # gtest headers are being fused into gtest.h and cannot be
+          # #included directly.
+
+          # There is no need to #include "gtest/gtest.h" more than once.
+          if not GTEST_H_SEED in processed_files:
+            processed_files.add(GTEST_H_SEED)
+            output_file.write('#include "%s"\n' % (GTEST_H_OUTPUT,))
+      else:
+        m = INCLUDE_SRC_FILE_REGEX.match(line)
+        if m:
+          # It's '#include "src/foo"' - let's process it recursively.
+          ProcessFile(m.group(1))
+        else:
+          output_file.write(line)
+
+  ProcessFile(GTEST_ALL_CC_SEED)
+
+
+def FuseGTestAllCc(gtest_root, output_dir):
+  """Scans folder gtest_root to generate gtest/gtest-all.cc in output_dir."""
+
+  output_file = file(os.path.join(output_dir, GTEST_ALL_CC_OUTPUT), 'w')
+  FuseGTestAllCcToFile(gtest_root, output_file)
+  output_file.close()
+
+
+def FuseGTest(gtest_root, output_dir):
+  """Fuses gtest.h and gtest-all.cc."""
+
+  ValidateGTestRootDir(gtest_root)
+  ValidateOutputDir(output_dir)
+
+  FuseGTestH(gtest_root, output_dir)
+  FuseGTestAllCc(gtest_root, output_dir)
+
+
+def main():
+  argc = len(sys.argv)
+  if argc == 2:
+    # fuse_gtest_files.py OUTPUT_DIR
+    FuseGTest(DEFAULT_GTEST_ROOT_DIR, sys.argv[1])
+  elif argc == 3:
+    # fuse_gtest_files.py GTEST_ROOT_DIR OUTPUT_DIR
+    FuseGTest(sys.argv[1], sys.argv[2])
+  else:
+    print __doc__
+    sys.exit(1)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/third_party/googletest/src/scripts/gen_gtest_pred_impl.py b/third_party/googletest/src/scripts/gen_gtest_pred_impl.py
new file mode 100755 (executable)
index 0000000..d35b4f0
--- /dev/null
@@ -0,0 +1,730 @@
+#!/usr/bin/env python
+#
+# Copyright 2006, 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.
+
+"""gen_gtest_pred_impl.py v0.1
+
+Generates the implementation of Google Test predicate assertions and
+accompanying tests.
+
+Usage:
+
+  gen_gtest_pred_impl.py MAX_ARITY
+
+where MAX_ARITY is a positive integer.
+
+The command generates the implementation of up-to MAX_ARITY-ary
+predicate assertions, and writes it to file gtest_pred_impl.h in the
+directory where the script is.  It also generates the accompanying
+unit test in file gtest_pred_impl_unittest.cc.
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import sys
+import time
+
+# Where this script is.
+SCRIPT_DIR = os.path.dirname(sys.argv[0])
+
+# Where to store the generated header.
+HEADER = os.path.join(SCRIPT_DIR, '../include/gtest/gtest_pred_impl.h')
+
+# Where to store the generated unit test.
+UNIT_TEST = os.path.join(SCRIPT_DIR, '../test/gtest_pred_impl_unittest.cc')
+
+
+def HeaderPreamble(n):
+  """Returns the preamble for the header file.
+
+  Args:
+    n:  the maximum arity of the predicate macros to be generated.
+  """
+
+  # A map that defines the values used in the preamble template.
+  DEFS = {
+    'today' : time.strftime('%m/%d/%Y'),
+    'year' : time.strftime('%Y'),
+    'command' : '%s %s' % (os.path.basename(sys.argv[0]), n),
+    'n' : n
+    }
+
+  return (
+"""// Copyright 2006, 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.
+
+// This file is AUTOMATICALLY GENERATED on %(today)s by command
+// '%(command)s'.  DO NOT EDIT BY HAND!
+//
+// Implements a family of generic predicate assertion macros.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+
+// Makes sure this header is not included before gtest.h.
+#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
+#error Do not include gtest_pred_impl.h directly.  Include gtest.h instead.
+#endif  // GTEST_INCLUDE_GTEST_GTEST_H_
+
+// This header implements a family of generic predicate assertion
+// macros:
+//
+//   ASSERT_PRED_FORMAT1(pred_format, v1)
+//   ASSERT_PRED_FORMAT2(pred_format, v1, v2)
+//   ...
+//
+// where pred_format is a function or functor that takes n (in the
+// case of ASSERT_PRED_FORMATn) values and their source expression
+// text, and returns a testing::AssertionResult.  See the definition
+// of ASSERT_EQ in gtest.h for an example.
+//
+// If you don't care about formatting, you can use the more
+// restrictive version:
+//
+//   ASSERT_PRED1(pred, v1)
+//   ASSERT_PRED2(pred, v1, v2)
+//   ...
+//
+// where pred is an n-ary function or functor that returns bool,
+// and the values v1, v2, ..., must support the << operator for
+// streaming to std::ostream.
+//
+// We also define the EXPECT_* variations.
+//
+// For now we only support predicates whose arity is at most %(n)s.
+// Please email googletestframework@googlegroups.com if you need
+// support for higher arities.
+
+// GTEST_ASSERT_ is the basic statement to which all of the assertions
+// in this file reduce.  Don't use this in your code.
+
+#define GTEST_ASSERT_(expression, on_failure) \\
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \\
+  if (const ::testing::AssertionResult gtest_ar = (expression)) \\
+    ; \\
+  else \\
+    on_failure(gtest_ar.failure_message())
+""" % DEFS)
+
+
+def Arity(n):
+  """Returns the English name of the given arity."""
+
+  if n < 0:
+    return None
+  elif n <= 3:
+    return ['nullary', 'unary', 'binary', 'ternary'][n]
+  else:
+    return '%s-ary' % n
+
+
+def Title(word):
+  """Returns the given word in title case.  The difference between
+  this and string's title() method is that Title('4-ary') is '4-ary'
+  while '4-ary'.title() is '4-Ary'."""
+
+  return word[0].upper() + word[1:]
+
+
+def OneTo(n):
+  """Returns the list [1, 2, 3, ..., n]."""
+
+  return range(1, n + 1)
+
+
+def Iter(n, format, sep=''):
+  """Given a positive integer n, a format string that contains 0 or
+  more '%s' format specs, and optionally a separator string, returns
+  the join of n strings, each formatted with the format string on an
+  iterator ranged from 1 to n.
+
+  Example:
+
+  Iter(3, 'v%s', sep=', ') returns 'v1, v2, v3'.
+  """
+
+  # How many '%s' specs are in format?
+  spec_count = len(format.split('%s')) - 1
+  return sep.join([format % (spec_count * (i,)) for i in OneTo(n)])
+
+
+def ImplementationForArity(n):
+  """Returns the implementation of n-ary predicate assertions."""
+
+  # A map the defines the values used in the implementation template.
+  DEFS = {
+    'n' : str(n),
+    'vs' : Iter(n, 'v%s', sep=', '),
+    'vts' : Iter(n, '#v%s', sep=', '),
+    'arity' : Arity(n),
+    'Arity' : Title(Arity(n))
+    }
+
+  impl = """
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED%(n)s.  Don't use
+// this in your code.
+template <typename Pred""" % DEFS
+
+  impl += Iter(n, """,
+          typename T%s""")
+
+  impl += """>
+AssertionResult AssertPred%(n)sHelper(const char* pred_text""" % DEFS
+
+  impl += Iter(n, """,
+                                  const char* e%s""")
+
+  impl += """,
+                                  Pred pred"""
+
+  impl += Iter(n, """,
+                                  const T%s& v%s""")
+
+  impl += """) {
+  if (pred(%(vs)s)) return AssertionSuccess();
+
+""" % DEFS
+
+  impl += '  return AssertionFailure() << pred_text << "("'
+
+  impl += Iter(n, """
+                            << e%s""", sep=' << ", "')
+
+  impl += ' << ") evaluates to false, where"'
+
+  impl += Iter(n, """
+                            << "\\n" << e%s << " evaluates to " << v%s""")
+
+  impl += """;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT%(n)s.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT%(n)s_(pred_format, %(vs)s, on_failure)\\
+  GTEST_ASSERT_(pred_format(%(vts)s, %(vs)s),\\
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED%(n)s.  Don't use
+// this in your code.
+#define GTEST_PRED%(n)s_(pred, %(vs)s, on_failure)\\
+  GTEST_ASSERT_(::testing::AssertPred%(n)sHelper(#pred""" % DEFS
+
+  impl += Iter(n, """, \\
+                                             #v%s""")
+
+  impl += """, \\
+                                             pred"""
+
+  impl += Iter(n, """, \\
+                                             v%s""")
+
+  impl += """), on_failure)
+
+// %(Arity)s predicate assertion macros.
+#define EXPECT_PRED_FORMAT%(n)s(pred_format, %(vs)s) \\
+  GTEST_PRED_FORMAT%(n)s_(pred_format, %(vs)s, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED%(n)s(pred, %(vs)s) \\
+  GTEST_PRED%(n)s_(pred, %(vs)s, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT%(n)s(pred_format, %(vs)s) \\
+  GTEST_PRED_FORMAT%(n)s_(pred_format, %(vs)s, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED%(n)s(pred, %(vs)s) \\
+  GTEST_PRED%(n)s_(pred, %(vs)s, GTEST_FATAL_FAILURE_)
+
+""" % DEFS
+
+  return impl
+
+
+def HeaderPostamble():
+  """Returns the postamble for the header file."""
+
+  return """
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+"""
+
+
+def GenerateFile(path, content):
+  """Given a file path and a content string, overwrites it with the
+  given content."""
+
+  print 'Updating file %s . . .' % path
+
+  f = file(path, 'w+')
+  print >>f, content,
+  f.close()
+
+  print 'File %s has been updated.' % path
+
+
+def GenerateHeader(n):
+  """Given the maximum arity n, updates the header file that implements
+  the predicate assertions."""
+
+  GenerateFile(HEADER,
+               HeaderPreamble(n)
+               + ''.join([ImplementationForArity(i) for i in OneTo(n)])
+               + HeaderPostamble())
+
+
+def UnitTestPreamble():
+  """Returns the preamble for the unit test file."""
+
+  # A map that defines the values used in the preamble template.
+  DEFS = {
+    'today' : time.strftime('%m/%d/%Y'),
+    'year' : time.strftime('%Y'),
+    'command' : '%s %s' % (os.path.basename(sys.argv[0]), sys.argv[1]),
+    }
+
+  return (
+"""// Copyright 2006, 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.
+
+// This file is AUTOMATICALLY GENERATED on %(today)s by command
+// '%(command)s'.  DO NOT EDIT BY HAND!
+
+// Regression test for gtest_pred_impl.h
+//
+// This file is generated by a script and quite long.  If you intend to
+// learn how Google Test works by reading its unit tests, read
+// gtest_unittest.cc instead.
+//
+// This is intended as a regression test for the Google Test predicate
+// assertions.  We compile it as part of the gtest_unittest target
+// only to keep the implementation tidy and compact, as it is quite
+// involved to set up the stage for testing Google Test using Google
+// Test itself.
+//
+// Currently, gtest_unittest takes ~11 seconds to run in the testing
+// daemon.  In the future, if it grows too large and needs much more
+// time to finish, we should consider separating this file into a
+// stand-alone regression test.
+
+#include <iostream>
+
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
+
+// A user-defined data type.
+struct Bool {
+  explicit Bool(int val) : value(val != 0) {}
+
+  bool operator>(int n) const { return value > Bool(n).value; }
+
+  Bool operator+(const Bool& rhs) const { return Bool(value + rhs.value); }
+
+  bool operator==(const Bool& rhs) const { return value == rhs.value; }
+
+  bool value;
+};
+
+// Enables Bool to be used in assertions.
+std::ostream& operator<<(std::ostream& os, const Bool& x) {
+  return os << (x.value ? "true" : "false");
+}
+
+""" % DEFS)
+
+
+def TestsForArity(n):
+  """Returns the tests for n-ary predicate assertions."""
+
+  # A map that defines the values used in the template for the tests.
+  DEFS = {
+    'n' : n,
+    'es' : Iter(n, 'e%s', sep=', '),
+    'vs' : Iter(n, 'v%s', sep=', '),
+    'vts' : Iter(n, '#v%s', sep=', '),
+    'tvs' : Iter(n, 'T%s v%s', sep=', '),
+    'int_vs' : Iter(n, 'int v%s', sep=', '),
+    'Bool_vs' : Iter(n, 'Bool v%s', sep=', '),
+    'types' : Iter(n, 'typename T%s', sep=', '),
+    'v_sum' : Iter(n, 'v%s', sep=' + '),
+    'arity' : Arity(n),
+    'Arity' : Title(Arity(n)),
+    }
+
+  tests = (
+"""// Sample functions/functors for testing %(arity)s predicate assertions.
+
+// A %(arity)s predicate function.
+template <%(types)s>
+bool PredFunction%(n)s(%(tvs)s) {
+  return %(v_sum)s > 0;
+}
+
+// The following two functions are needed to circumvent a bug in
+// gcc 2.95.3, which sometimes has problem with the above template
+// function.
+bool PredFunction%(n)sInt(%(int_vs)s) {
+  return %(v_sum)s > 0;
+}
+bool PredFunction%(n)sBool(%(Bool_vs)s) {
+  return %(v_sum)s > 0;
+}
+""" % DEFS)
+
+  tests += """
+// A %(arity)s predicate functor.
+struct PredFunctor%(n)s {
+  template <%(types)s>
+  bool operator()(""" % DEFS
+
+  tests += Iter(n, 'const T%s& v%s', sep=""",
+                  """)
+
+  tests += """) {
+    return %(v_sum)s > 0;
+  }
+};
+""" % DEFS
+
+  tests += """
+// A %(arity)s predicate-formatter function.
+template <%(types)s>
+testing::AssertionResult PredFormatFunction%(n)s(""" % DEFS
+
+  tests += Iter(n, 'const char* e%s', sep=""",
+                                             """)
+
+  tests += Iter(n, """,
+                                             const T%s& v%s""")
+
+  tests += """) {
+  if (PredFunction%(n)s(%(vs)s))
+    return testing::AssertionSuccess();
+
+  return testing::AssertionFailure()
+      << """ % DEFS
+
+  tests += Iter(n, 'e%s', sep=' << " + " << ')
+
+  tests += """
+      << " is expected to be positive, but evaluates to "
+      << %(v_sum)s << ".";
+}
+""" % DEFS
+
+  tests += """
+// A %(arity)s predicate-formatter functor.
+struct PredFormatFunctor%(n)s {
+  template <%(types)s>
+  testing::AssertionResult operator()(""" % DEFS
+
+  tests += Iter(n, 'const char* e%s', sep=""",
+                                      """)
+
+  tests += Iter(n, """,
+                                      const T%s& v%s""")
+
+  tests += """) const {
+    return PredFormatFunction%(n)s(%(es)s, %(vs)s);
+  }
+};
+""" % DEFS
+
+  tests += """
+// Tests for {EXPECT|ASSERT}_PRED_FORMAT%(n)s.
+
+class Predicate%(n)sTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    expected_to_finish_ = true;
+    finished_ = false;""" % DEFS
+
+  tests += """
+    """ + Iter(n, 'n%s_ = ') + """0;
+  }
+"""
+
+  tests += """
+  virtual void TearDown() {
+    // Verifies that each of the predicate's arguments was evaluated
+    // exactly once."""
+
+  tests += ''.join(["""
+    EXPECT_EQ(1, n%s_) <<
+        "The predicate assertion didn't evaluate argument %s "
+        "exactly once.";""" % (i, i + 1) for i in OneTo(n)])
+
+  tests += """
+
+    // Verifies that the control flow in the test function is expected.
+    if (expected_to_finish_ && !finished_) {
+      FAIL() << "The predicate assertion unexpactedly aborted the test.";
+    } else if (!expected_to_finish_ && finished_) {
+      FAIL() << "The failed predicate assertion didn't abort the test "
+                "as expected.";
+    }
+  }
+
+  // true iff the test function is expected to run to finish.
+  static bool expected_to_finish_;
+
+  // true iff the test function did run to finish.
+  static bool finished_;
+""" % DEFS
+
+  tests += Iter(n, """
+  static int n%s_;""")
+
+  tests += """
+};
+
+bool Predicate%(n)sTest::expected_to_finish_;
+bool Predicate%(n)sTest::finished_;
+""" % DEFS
+
+  tests += Iter(n, """int Predicate%%(n)sTest::n%s_;
+""") % DEFS
+
+  tests += """
+typedef Predicate%(n)sTest EXPECT_PRED_FORMAT%(n)sTest;
+typedef Predicate%(n)sTest ASSERT_PRED_FORMAT%(n)sTest;
+typedef Predicate%(n)sTest EXPECT_PRED%(n)sTest;
+typedef Predicate%(n)sTest ASSERT_PRED%(n)sTest;
+""" % DEFS
+
+  def GenTest(use_format, use_assert, expect_failure,
+              use_functor, use_user_type):
+    """Returns the test for a predicate assertion macro.
+
+    Args:
+      use_format:     true iff the assertion is a *_PRED_FORMAT*.
+      use_assert:     true iff the assertion is a ASSERT_*.
+      expect_failure: true iff the assertion is expected to fail.
+      use_functor:    true iff the first argument of the assertion is
+                      a functor (as opposed to a function)
+      use_user_type:  true iff the predicate functor/function takes
+                      argument(s) of a user-defined type.
+
+    Example:
+
+      GenTest(1, 0, 0, 1, 0) returns a test that tests the behavior
+      of a successful EXPECT_PRED_FORMATn() that takes a functor
+      whose arguments have built-in types."""
+
+    if use_assert:
+      assrt = 'ASSERT'  # 'assert' is reserved, so we cannot use
+                        # that identifier here.
+    else:
+      assrt = 'EXPECT'
+
+    assertion = assrt + '_PRED'
+
+    if use_format:
+      pred_format = 'PredFormat'
+      assertion += '_FORMAT'
+    else:
+      pred_format = 'Pred'
+
+    assertion += '%(n)s' % DEFS
+
+    if use_functor:
+      pred_format_type = 'functor'
+      pred_format += 'Functor%(n)s()'
+    else:
+      pred_format_type = 'function'
+      pred_format += 'Function%(n)s'
+      if not use_format:
+        if use_user_type:
+          pred_format += 'Bool'
+        else:
+          pred_format += 'Int'
+
+    test_name = pred_format_type.title()
+
+    if use_user_type:
+      arg_type = 'user-defined type (Bool)'
+      test_name += 'OnUserType'
+      if expect_failure:
+        arg = 'Bool(n%s_++)'
+      else:
+        arg = 'Bool(++n%s_)'
+    else:
+      arg_type = 'built-in type (int)'
+      test_name += 'OnBuiltInType'
+      if expect_failure:
+        arg = 'n%s_++'
+      else:
+        arg = '++n%s_'
+
+    if expect_failure:
+      successful_or_failed = 'failed'
+      expected_or_not = 'expected.'
+      test_name +=  'Failure'
+    else:
+      successful_or_failed = 'successful'
+      expected_or_not = 'UNEXPECTED!'
+      test_name +=  'Success'
+
+    # A map that defines the values used in the test template.
+    defs = DEFS.copy()
+    defs.update({
+      'assert' : assrt,
+      'assertion' : assertion,
+      'test_name' : test_name,
+      'pf_type' : pred_format_type,
+      'pf' : pred_format,
+      'arg_type' : arg_type,
+      'arg' : arg,
+      'successful' : successful_or_failed,
+      'expected' : expected_or_not,
+      })
+
+    test = """
+// Tests a %(successful)s %(assertion)s where the
+// predicate-formatter is a %(pf_type)s on a %(arg_type)s.
+TEST_F(%(assertion)sTest, %(test_name)s) {""" % defs
+
+    indent = (len(assertion) + 3)*' '
+    extra_indent = ''
+
+    if expect_failure:
+      extra_indent = '  '
+      if use_assert:
+        test += """
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT"""
+      else:
+        test += """
+  EXPECT_NONFATAL_FAILURE({  // NOLINT"""
+
+    test += '\n' + extra_indent + """  %(assertion)s(%(pf)s""" % defs
+
+    test = test % defs
+    test += Iter(n, ',\n' + indent + extra_indent + '%(arg)s' % defs)
+    test += ');\n' + extra_indent + '  finished_ = true;\n'
+
+    if expect_failure:
+      test += '  }, "");\n'
+
+    test += '}\n'
+    return test
+
+  # Generates tests for all 2**6 = 64 combinations.
+  tests += ''.join([GenTest(use_format, use_assert, expect_failure,
+                            use_functor, use_user_type)
+                    for use_format in [0, 1]
+                    for use_assert in [0, 1]
+                    for expect_failure in [0, 1]
+                    for use_functor in [0, 1]
+                    for use_user_type in [0, 1]
+                    ])
+
+  return tests
+
+
+def UnitTestPostamble():
+  """Returns the postamble for the tests."""
+
+  return ''
+
+
+def GenerateUnitTest(n):
+  """Returns the tests for up-to n-ary predicate assertions."""
+
+  GenerateFile(UNIT_TEST,
+               UnitTestPreamble()
+               + ''.join([TestsForArity(i) for i in OneTo(n)])
+               + UnitTestPostamble())
+
+
+def _Main():
+  """The entry point of the script.  Generates the header file and its
+  unit test."""
+
+  if len(sys.argv) != 2:
+    print __doc__
+    print 'Author: ' + __author__
+    sys.exit(1)
+
+  n = int(sys.argv[1])
+  GenerateHeader(n)
+  GenerateUnitTest(n)
+
+
+if __name__ == '__main__':
+  _Main()
diff --git a/third_party/googletest/src/scripts/gtest-config.in b/third_party/googletest/src/scripts/gtest-config.in
new file mode 100644 (file)
index 0000000..9c72638
--- /dev/null
@@ -0,0 +1,274 @@
+#!/bin/sh
+
+# These variables are automatically filled in by the configure script.
+name="@PACKAGE_TARNAME@"
+version="@PACKAGE_VERSION@"
+
+show_usage()
+{
+  echo "Usage: gtest-config [OPTIONS...]"
+}
+
+show_help()
+{
+  show_usage
+  cat <<\EOF
+
+The `gtest-config' script provides access to the necessary compile and linking
+flags to connect with Google C++ Testing Framework, both in a build prior to
+installation, and on the system proper after installation. The installation
+overrides may be issued in combination with any other queries, but will only
+affect installation queries if called on a built but not installed gtest. The
+installation queries may not be issued with any other types of queries, and
+only one installation query may be made at a time. The version queries and
+compiler flag queries may be combined as desired but not mixed. Different
+version queries are always combined with logical "and" semantics, and only the
+last of any particular query is used while all previous ones ignored. All
+versions must be specified as a sequence of numbers separated by periods.
+Compiler flag queries output the union of the sets of flags when combined.
+
+ Examples:
+  gtest-config --min-version=1.0 || echo "Insufficient Google Test version."
+
+  g++ $(gtest-config --cppflags --cxxflags) -o foo.o -c foo.cpp
+  g++ $(gtest-config --ldflags --libs) -o foo foo.o
+
+  # When using a built but not installed Google Test:
+  g++ $(../../my_gtest_build/scripts/gtest-config ...) ...
+
+  # When using an installed Google Test, but with installation overrides:
+  export GTEST_PREFIX="/opt"
+  g++ $(gtest-config --libdir="/opt/lib64" ...) ...
+
+ Help:
+  --usage                    brief usage information
+  --help                     display this help message
+
+ Installation Overrides:
+  --prefix=<dir>             overrides the installation prefix
+  --exec-prefix=<dir>        overrides the executable installation prefix
+  --libdir=<dir>             overrides the library installation prefix
+  --includedir=<dir>         overrides the header file installation prefix
+
+ Installation Queries:
+  --prefix                   installation prefix
+  --exec-prefix              executable installation prefix
+  --libdir                   library installation directory
+  --includedir               header file installation directory
+  --version                  the version of the Google Test installation
+
+ Version Queries:
+  --min-version=VERSION      return 0 if the version is at least VERSION
+  --exact-version=VERSION    return 0 if the version is exactly VERSION
+  --max-version=VERSION      return 0 if the version is at most VERSION
+
+ Compilation Flag Queries:
+  --cppflags                 compile flags specific to the C-like preprocessors
+  --cxxflags                 compile flags appropriate for C++ programs
+  --ldflags                  linker flags
+  --libs                     libraries for linking
+
+EOF
+}
+
+# This function bounds our version with a min and a max. It uses some clever
+# POSIX-compliant variable expansion to portably do all the work in the shell
+# and avoid any dependency on a particular "sed" or "awk" implementation.
+# Notable is that it will only ever compare the first 3 components of versions.
+# Further components will be cleanly stripped off. All versions must be
+# unadorned, so "v1.0" will *not* work. The minimum version must be in $1, and
+# the max in $2. TODO(chandlerc@google.com): If this ever breaks, we should
+# investigate expanding this via autom4te from AS_VERSION_COMPARE rather than
+# continuing to maintain our own shell version.
+check_versions()
+{
+  major_version=${version%%.*}
+  minor_version="0"
+  point_version="0"
+  if test "${version#*.}" != "${version}"; then
+    minor_version=${version#*.}
+    minor_version=${minor_version%%.*}
+  fi
+  if test "${version#*.*.}" != "${version}"; then
+    point_version=${version#*.*.}
+    point_version=${point_version%%.*}
+  fi
+
+  min_version="$1"
+  min_major_version=${min_version%%.*}
+  min_minor_version="0"
+  min_point_version="0"
+  if test "${min_version#*.}" != "${min_version}"; then
+    min_minor_version=${min_version#*.}
+    min_minor_version=${min_minor_version%%.*}
+  fi
+  if test "${min_version#*.*.}" != "${min_version}"; then
+    min_point_version=${min_version#*.*.}
+    min_point_version=${min_point_version%%.*}
+  fi
+
+  max_version="$2"
+  max_major_version=${max_version%%.*}
+  max_minor_version="0"
+  max_point_version="0"
+  if test "${max_version#*.}" != "${max_version}"; then
+    max_minor_version=${max_version#*.}
+    max_minor_version=${max_minor_version%%.*}
+  fi
+  if test "${max_version#*.*.}" != "${max_version}"; then
+    max_point_version=${max_version#*.*.}
+    max_point_version=${max_point_version%%.*}
+  fi
+
+  test $(($major_version)) -lt $(($min_major_version)) && exit 1
+  if test $(($major_version)) -eq $(($min_major_version)); then
+    test $(($minor_version)) -lt $(($min_minor_version)) && exit 1
+    if test $(($minor_version)) -eq $(($min_minor_version)); then
+      test $(($point_version)) -lt $(($min_point_version)) && exit 1
+    fi
+  fi
+
+  test $(($major_version)) -gt $(($max_major_version)) && exit 1
+  if test $(($major_version)) -eq $(($max_major_version)); then
+    test $(($minor_version)) -gt $(($max_minor_version)) && exit 1
+    if test $(($minor_version)) -eq $(($max_minor_version)); then
+      test $(($point_version)) -gt $(($max_point_version)) && exit 1
+    fi
+  fi
+
+  exit 0
+}
+
+# Show the usage line when no arguments are specified.
+if test $# -eq 0; then
+  show_usage
+  exit 1
+fi
+
+while test $# -gt 0; do
+  case $1 in
+    --usage)          show_usage;         exit 0;;
+    --help)           show_help;          exit 0;;
+
+    # Installation overrides
+    --prefix=*)       GTEST_PREFIX=${1#--prefix=};;
+    --exec-prefix=*)  GTEST_EXEC_PREFIX=${1#--exec-prefix=};;
+    --libdir=*)       GTEST_LIBDIR=${1#--libdir=};;
+    --includedir=*)   GTEST_INCLUDEDIR=${1#--includedir=};;
+
+    # Installation queries
+    --prefix|--exec-prefix|--libdir|--includedir|--version)
+      if test -n "${do_query}"; then
+        show_usage
+        exit 1
+      fi
+      do_query=${1#--}
+      ;;
+
+    # Version checking
+    --min-version=*)
+      do_check_versions=yes
+      min_version=${1#--min-version=}
+      ;;
+    --max-version=*)
+      do_check_versions=yes
+      max_version=${1#--max-version=}
+      ;;
+    --exact-version=*)
+      do_check_versions=yes
+      exact_version=${1#--exact-version=}
+      ;;
+
+    # Compiler flag output
+    --cppflags)       echo_cppflags=yes;;
+    --cxxflags)       echo_cxxflags=yes;;
+    --ldflags)        echo_ldflags=yes;;
+    --libs)           echo_libs=yes;;
+
+    # Everything else is an error
+    *)                show_usage;         exit 1;;
+  esac
+  shift
+done
+
+# These have defaults filled in by the configure script but can also be
+# overridden by environment variables or command line parameters.
+prefix="${GTEST_PREFIX:-@prefix@}"
+exec_prefix="${GTEST_EXEC_PREFIX:-@exec_prefix@}"
+libdir="${GTEST_LIBDIR:-@libdir@}"
+includedir="${GTEST_INCLUDEDIR:-@includedir@}"
+
+# We try and detect if our binary is not located at its installed location. If
+# it's not, we provide variables pointing to the source and build tree rather
+# than to the install tree. This allows building against a just-built gtest
+# rather than an installed gtest.
+bindir="@bindir@"
+this_relative_bindir=`dirname $0`
+this_bindir=`cd ${this_relative_bindir}; pwd -P`
+if test "${this_bindir}" = "${this_bindir%${bindir}}"; then
+  # The path to the script doesn't end in the bindir sequence from Autoconf,
+  # assume that we are in a build tree.
+  build_dir=`dirname ${this_bindir}`
+  src_dir=`cd ${this_bindir}/@top_srcdir@; pwd -P`
+
+  # TODO(chandlerc@google.com): This is a dangerous dependency on libtool, we
+  # should work to remove it, and/or remove libtool altogether, replacing it
+  # with direct references to the library and a link path.
+  gtest_libs="${build_dir}/lib/libgtest.la @PTHREAD_CFLAGS@ @PTHREAD_LIBS@"
+  gtest_ldflags=""
+
+  # We provide hooks to include from either the source or build dir, where the
+  # build dir is always preferred. This will potentially allow us to write
+  # build rules for generated headers and have them automatically be preferred
+  # over provided versions.
+  gtest_cppflags="-I${build_dir}/include -I${src_dir}/include"
+  gtest_cxxflags="@PTHREAD_CFLAGS@"
+else
+  # We're using an installed gtest, although it may be staged under some
+  # prefix. Assume (as our own libraries do) that we can resolve the prefix,
+  # and are present in the dynamic link paths.
+  gtest_ldflags="-L${libdir}"
+  gtest_libs="-l${name} @PTHREAD_CFLAGS@ @PTHREAD_LIBS@"
+  gtest_cppflags="-I${includedir}"
+  gtest_cxxflags="@PTHREAD_CFLAGS@"
+fi
+
+# Do an installation query if requested.
+if test -n "$do_query"; then
+  case $do_query in
+    prefix)           echo $prefix;       exit 0;;
+    exec-prefix)      echo $exec_prefix;  exit 0;;
+    libdir)           echo $libdir;       exit 0;;
+    includedir)       echo $includedir;   exit 0;;
+    version)          echo $version;      exit 0;;
+    *)                show_usage;         exit 1;;
+  esac
+fi
+
+# Do a version check if requested.
+if test "$do_check_versions" = "yes"; then
+  # Make sure we didn't receive a bad combination of parameters.
+  test "$echo_cppflags" = "yes" && show_usage && exit 1
+  test "$echo_cxxflags" = "yes" && show_usage && exit 1
+  test "$echo_ldflags" = "yes"  && show_usage && exit 1
+  test "$echo_libs" = "yes"     && show_usage && exit 1
+
+  if test "$exact_version" != ""; then
+    check_versions $exact_version $exact_version
+    # unreachable
+  else
+    check_versions ${min_version:-0.0.0} ${max_version:-9999.9999.9999}
+    # unreachable
+  fi
+fi
+
+# Do the output in the correct order so that these can be used in-line of
+# a compiler invocation.
+output=""
+test "$echo_cppflags" = "yes" && output="$output $gtest_cppflags"
+test "$echo_cxxflags" = "yes" && output="$output $gtest_cxxflags"
+test "$echo_ldflags" = "yes"  && output="$output $gtest_ldflags"
+test "$echo_libs" = "yes"     && output="$output $gtest_libs"
+echo $output
+
+exit 0
diff --git a/third_party/googletest/src/scripts/pump.py b/third_party/googletest/src/scripts/pump.py
new file mode 100755 (executable)
index 0000000..8afe808
--- /dev/null
@@ -0,0 +1,847 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, 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.
+
+"""pump v0.2.0 - Pretty Useful for Meta Programming.
+
+A tool for preprocessor meta programming.  Useful for generating
+repetitive boilerplate code.  Especially useful for writing C++
+classes, functions, macros, and templates that need to work with
+various number of arguments.
+
+USAGE:
+       pump.py SOURCE_FILE
+
+EXAMPLES:
+       pump.py foo.cc.pump
+         Converts foo.cc.pump to foo.cc.
+
+GRAMMAR:
+       CODE ::= ATOMIC_CODE*
+       ATOMIC_CODE ::= $var ID = EXPRESSION
+           | $var ID = [[ CODE ]]
+           | $range ID EXPRESSION..EXPRESSION
+           | $for ID SEPARATOR [[ CODE ]]
+           | $($)
+           | $ID
+           | $(EXPRESSION)
+           | $if EXPRESSION [[ CODE ]] ELSE_BRANCH
+           | [[ CODE ]]
+           | RAW_CODE
+       SEPARATOR ::= RAW_CODE | EMPTY
+       ELSE_BRANCH ::= $else [[ CODE ]]
+           | $elif EXPRESSION [[ CODE ]] ELSE_BRANCH
+           | EMPTY
+       EXPRESSION has Python syntax.
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import re
+import sys
+
+
+TOKEN_TABLE = [
+    (re.compile(r'\$var\s+'), '$var'),
+    (re.compile(r'\$elif\s+'), '$elif'),
+    (re.compile(r'\$else\s+'), '$else'),
+    (re.compile(r'\$for\s+'), '$for'),
+    (re.compile(r'\$if\s+'), '$if'),
+    (re.compile(r'\$range\s+'), '$range'),
+    (re.compile(r'\$[_A-Za-z]\w*'), '$id'),
+    (re.compile(r'\$\(\$\)'), '$($)'),
+    (re.compile(r'\$'), '$'),
+    (re.compile(r'\[\[\n?'), '[['),
+    (re.compile(r'\]\]\n?'), ']]'),
+    ]
+
+
+class Cursor:
+  """Represents a position (line and column) in a text file."""
+
+  def __init__(self, line=-1, column=-1):
+    self.line = line
+    self.column = column
+
+  def __eq__(self, rhs):
+    return self.line == rhs.line and self.column == rhs.column
+
+  def __ne__(self, rhs):
+    return not self == rhs
+
+  def __lt__(self, rhs):
+    return self.line < rhs.line or (
+        self.line == rhs.line and self.column < rhs.column)
+
+  def __le__(self, rhs):
+    return self < rhs or self == rhs
+
+  def __gt__(self, rhs):
+    return rhs < self
+
+  def __ge__(self, rhs):
+    return rhs <= self
+
+  def __str__(self):
+    if self == Eof():
+      return 'EOF'
+    else:
+      return '%s(%s)' % (self.line + 1, self.column)
+
+  def __add__(self, offset):
+    return Cursor(self.line, self.column + offset)
+
+  def __sub__(self, offset):
+    return Cursor(self.line, self.column - offset)
+
+  def Clone(self):
+    """Returns a copy of self."""
+
+    return Cursor(self.line, self.column)
+
+
+# Special cursor to indicate the end-of-file.
+def Eof():
+  """Returns the special cursor to denote the end-of-file."""
+  return Cursor(-1, -1)
+
+
+class Token:
+  """Represents a token in a Pump source file."""
+
+  def __init__(self, start=None, end=None, value=None, token_type=None):
+    if start is None:
+      self.start = Eof()
+    else:
+      self.start = start
+    if end is None:
+      self.end = Eof()
+    else:
+      self.end = end
+    self.value = value
+    self.token_type = token_type
+
+  def __str__(self):
+    return 'Token @%s: \'%s\' type=%s' % (
+        self.start, self.value, self.token_type)
+
+  def Clone(self):
+    """Returns a copy of self."""
+
+    return Token(self.start.Clone(), self.end.Clone(), self.value,
+                 self.token_type)
+
+
+def StartsWith(lines, pos, string):
+  """Returns True iff the given position in lines starts with 'string'."""
+
+  return lines[pos.line][pos.column:].startswith(string)
+
+
+def FindFirstInLine(line, token_table):
+  best_match_start = -1
+  for (regex, token_type) in token_table:
+    m = regex.search(line)
+    if m:
+      # We found regex in lines
+      if best_match_start < 0 or m.start() < best_match_start:
+        best_match_start = m.start()
+        best_match_length = m.end() - m.start()
+        best_match_token_type = token_type
+
+  if best_match_start < 0:
+    return None
+
+  return (best_match_start, best_match_length, best_match_token_type)
+
+
+def FindFirst(lines, token_table, cursor):
+  """Finds the first occurrence of any string in strings in lines."""
+
+  start = cursor.Clone()
+  cur_line_number = cursor.line
+  for line in lines[start.line:]:
+    if cur_line_number == start.line:
+      line = line[start.column:]
+    m = FindFirstInLine(line, token_table)
+    if m:
+      # We found a regex in line.
+      (start_column, length, token_type) = m
+      if cur_line_number == start.line:
+        start_column += start.column
+      found_start = Cursor(cur_line_number, start_column)
+      found_end = found_start + length
+      return MakeToken(lines, found_start, found_end, token_type)
+    cur_line_number += 1
+  # We failed to find str in lines
+  return None
+
+
+def SubString(lines, start, end):
+  """Returns a substring in lines."""
+
+  if end == Eof():
+    end = Cursor(len(lines) - 1, len(lines[-1]))
+
+  if start >= end:
+    return ''
+
+  if start.line == end.line:
+    return lines[start.line][start.column:end.column]
+
+  result_lines = ([lines[start.line][start.column:]] +
+                  lines[start.line + 1:end.line] +
+                  [lines[end.line][:end.column]])
+  return ''.join(result_lines)
+
+
+def StripMetaComments(str):
+  """Strip meta comments from each line in the given string."""
+
+  # First, completely remove lines containing nothing but a meta
+  # comment, including the trailing \n.
+  str = re.sub(r'^\s*\$\$.*\n', '', str)
+
+  # Then, remove meta comments from contentful lines.
+  return re.sub(r'\s*\$\$.*', '', str)
+
+
+def MakeToken(lines, start, end, token_type):
+  """Creates a new instance of Token."""
+
+  return Token(start, end, SubString(lines, start, end), token_type)
+
+
+def ParseToken(lines, pos, regex, token_type):
+  line = lines[pos.line][pos.column:]
+  m = regex.search(line)
+  if m and not m.start():
+    return MakeToken(lines, pos, pos + m.end(), token_type)
+  else:
+    print 'ERROR: %s expected at %s.' % (token_type, pos)
+    sys.exit(1)
+
+
+ID_REGEX = re.compile(r'[_A-Za-z]\w*')
+EQ_REGEX = re.compile(r'=')
+REST_OF_LINE_REGEX = re.compile(r'.*?(?=$|\$\$)')
+OPTIONAL_WHITE_SPACES_REGEX = re.compile(r'\s*')
+WHITE_SPACE_REGEX = re.compile(r'\s')
+DOT_DOT_REGEX = re.compile(r'\.\.')
+
+
+def Skip(lines, pos, regex):
+  line = lines[pos.line][pos.column:]
+  m = re.search(regex, line)
+  if m and not m.start():
+    return pos + m.end()
+  else:
+    return pos
+
+
+def SkipUntil(lines, pos, regex, token_type):
+  line = lines[pos.line][pos.column:]
+  m = re.search(regex, line)
+  if m:
+    return pos + m.start()
+  else:
+    print ('ERROR: %s expected on line %s after column %s.' %
+           (token_type, pos.line + 1, pos.column))
+    sys.exit(1)
+
+
+def ParseExpTokenInParens(lines, pos):
+  def ParseInParens(pos):
+    pos = Skip(lines, pos, OPTIONAL_WHITE_SPACES_REGEX)
+    pos = Skip(lines, pos, r'\(')
+    pos = Parse(pos)
+    pos = Skip(lines, pos, r'\)')
+    return pos
+
+  def Parse(pos):
+    pos = SkipUntil(lines, pos, r'\(|\)', ')')
+    if SubString(lines, pos, pos + 1) == '(':
+      pos = Parse(pos + 1)
+      pos = Skip(lines, pos, r'\)')
+      return Parse(pos)
+    else:
+      return pos
+
+  start = pos.Clone()
+  pos = ParseInParens(pos)
+  return MakeToken(lines, start, pos, 'exp')
+
+
+def RStripNewLineFromToken(token):
+  if token.value.endswith('\n'):
+    return Token(token.start, token.end, token.value[:-1], token.token_type)
+  else:
+    return token
+
+
+def TokenizeLines(lines, pos):
+  while True:
+    found = FindFirst(lines, TOKEN_TABLE, pos)
+    if not found:
+      yield MakeToken(lines, pos, Eof(), 'code')
+      return
+
+    if found.start == pos:
+      prev_token = None
+      prev_token_rstripped = None
+    else:
+      prev_token = MakeToken(lines, pos, found.start, 'code')
+      prev_token_rstripped = RStripNewLineFromToken(prev_token)
+
+    if found.token_type == '$var':
+      if prev_token_rstripped:
+        yield prev_token_rstripped
+      yield found
+      id_token = ParseToken(lines, found.end, ID_REGEX, 'id')
+      yield id_token
+      pos = Skip(lines, id_token.end, OPTIONAL_WHITE_SPACES_REGEX)
+
+      eq_token = ParseToken(lines, pos, EQ_REGEX, '=')
+      yield eq_token
+      pos = Skip(lines, eq_token.end, r'\s*')
+
+      if SubString(lines, pos, pos + 2) != '[[':
+        exp_token = ParseToken(lines, pos, REST_OF_LINE_REGEX, 'exp')
+        yield exp_token
+        pos = Cursor(exp_token.end.line + 1, 0)
+    elif found.token_type == '$for':
+      if prev_token_rstripped:
+        yield prev_token_rstripped
+      yield found
+      id_token = ParseToken(lines, found.end, ID_REGEX, 'id')
+      yield id_token
+      pos = Skip(lines, id_token.end, WHITE_SPACE_REGEX)
+    elif found.token_type == '$range':
+      if prev_token_rstripped:
+        yield prev_token_rstripped
+      yield found
+      id_token = ParseToken(lines, found.end, ID_REGEX, 'id')
+      yield id_token
+      pos = Skip(lines, id_token.end, OPTIONAL_WHITE_SPACES_REGEX)
+
+      dots_pos = SkipUntil(lines, pos, DOT_DOT_REGEX, '..')
+      yield MakeToken(lines, pos, dots_pos, 'exp')
+      yield MakeToken(lines, dots_pos, dots_pos + 2, '..')
+      pos = dots_pos + 2
+      new_pos = Cursor(pos.line + 1, 0)
+      yield MakeToken(lines, pos, new_pos, 'exp')
+      pos = new_pos
+    elif found.token_type == '$':
+      if prev_token:
+        yield prev_token
+      yield found
+      exp_token = ParseExpTokenInParens(lines, found.end)
+      yield exp_token
+      pos = exp_token.end
+    elif (found.token_type == ']]' or found.token_type == '$if' or
+          found.token_type == '$elif' or found.token_type == '$else'):
+      if prev_token_rstripped:
+        yield prev_token_rstripped
+      yield found
+      pos = found.end
+    else:
+      if prev_token:
+        yield prev_token
+      yield found
+      pos = found.end
+
+
+def Tokenize(s):
+  """A generator that yields the tokens in the given string."""
+  if s != '':
+    lines = s.splitlines(True)
+    for token in TokenizeLines(lines, Cursor(0, 0)):
+      yield token
+
+
+class CodeNode:
+  def __init__(self, atomic_code_list=None):
+    self.atomic_code = atomic_code_list
+
+
+class VarNode:
+  def __init__(self, identifier=None, atomic_code=None):
+    self.identifier = identifier
+    self.atomic_code = atomic_code
+
+
+class RangeNode:
+  def __init__(self, identifier=None, exp1=None, exp2=None):
+    self.identifier = identifier
+    self.exp1 = exp1
+    self.exp2 = exp2
+
+
+class ForNode:
+  def __init__(self, identifier=None, sep=None, code=None):
+    self.identifier = identifier
+    self.sep = sep
+    self.code = code
+
+
+class ElseNode:
+  def __init__(self, else_branch=None):
+    self.else_branch = else_branch
+
+
+class IfNode:
+  def __init__(self, exp=None, then_branch=None, else_branch=None):
+    self.exp = exp
+    self.then_branch = then_branch
+    self.else_branch = else_branch
+
+
+class RawCodeNode:
+  def __init__(self, token=None):
+    self.raw_code = token
+
+
+class LiteralDollarNode:
+  def __init__(self, token):
+    self.token = token
+
+
+class ExpNode:
+  def __init__(self, token, python_exp):
+    self.token = token
+    self.python_exp = python_exp
+
+
+def PopFront(a_list):
+  head = a_list[0]
+  a_list[:1] = []
+  return head
+
+
+def PushFront(a_list, elem):
+  a_list[:0] = [elem]
+
+
+def PopToken(a_list, token_type=None):
+  token = PopFront(a_list)
+  if token_type is not None and token.token_type != token_type:
+    print 'ERROR: %s expected at %s' % (token_type, token.start)
+    print 'ERROR: %s found instead' % (token,)
+    sys.exit(1)
+
+  return token
+
+
+def PeekToken(a_list):
+  if not a_list:
+    return None
+
+  return a_list[0]
+
+
+def ParseExpNode(token):
+  python_exp = re.sub(r'([_A-Za-z]\w*)', r'self.GetValue("\1")', token.value)
+  return ExpNode(token, python_exp)
+
+
+def ParseElseNode(tokens):
+  def Pop(token_type=None):
+    return PopToken(tokens, token_type)
+
+  next = PeekToken(tokens)
+  if not next:
+    return None
+  if next.token_type == '$else':
+    Pop('$else')
+    Pop('[[')
+    code_node = ParseCodeNode(tokens)
+    Pop(']]')
+    return code_node
+  elif next.token_type == '$elif':
+    Pop('$elif')
+    exp = Pop('code')
+    Pop('[[')
+    code_node = ParseCodeNode(tokens)
+    Pop(']]')
+    inner_else_node = ParseElseNode(tokens)
+    return CodeNode([IfNode(ParseExpNode(exp), code_node, inner_else_node)])
+  elif not next.value.strip():
+    Pop('code')
+    return ParseElseNode(tokens)
+  else:
+    return None
+
+
+def ParseAtomicCodeNode(tokens):
+  def Pop(token_type=None):
+    return PopToken(tokens, token_type)
+
+  head = PopFront(tokens)
+  t = head.token_type
+  if t == 'code':
+    return RawCodeNode(head)
+  elif t == '$var':
+    id_token = Pop('id')
+    Pop('=')
+    next = PeekToken(tokens)
+    if next.token_type == 'exp':
+      exp_token = Pop()
+      return VarNode(id_token, ParseExpNode(exp_token))
+    Pop('[[')
+    code_node = ParseCodeNode(tokens)
+    Pop(']]')
+    return VarNode(id_token, code_node)
+  elif t == '$for':
+    id_token = Pop('id')
+    next_token = PeekToken(tokens)
+    if next_token.token_type == 'code':
+      sep_token = next_token
+      Pop('code')
+    else:
+      sep_token = None
+    Pop('[[')
+    code_node = ParseCodeNode(tokens)
+    Pop(']]')
+    return ForNode(id_token, sep_token, code_node)
+  elif t == '$if':
+    exp_token = Pop('code')
+    Pop('[[')
+    code_node = ParseCodeNode(tokens)
+    Pop(']]')
+    else_node = ParseElseNode(tokens)
+    return IfNode(ParseExpNode(exp_token), code_node, else_node)
+  elif t == '$range':
+    id_token = Pop('id')
+    exp1_token = Pop('exp')
+    Pop('..')
+    exp2_token = Pop('exp')
+    return RangeNode(id_token, ParseExpNode(exp1_token),
+                     ParseExpNode(exp2_token))
+  elif t == '$id':
+    return ParseExpNode(Token(head.start + 1, head.end, head.value[1:], 'id'))
+  elif t == '$($)':
+    return LiteralDollarNode(head)
+  elif t == '$':
+    exp_token = Pop('exp')
+    return ParseExpNode(exp_token)
+  elif t == '[[':
+    code_node = ParseCodeNode(tokens)
+    Pop(']]')
+    return code_node
+  else:
+    PushFront(tokens, head)
+    return None
+
+
+def ParseCodeNode(tokens):
+  atomic_code_list = []
+  while True:
+    if not tokens:
+      break
+    atomic_code_node = ParseAtomicCodeNode(tokens)
+    if atomic_code_node:
+      atomic_code_list.append(atomic_code_node)
+    else:
+      break
+  return CodeNode(atomic_code_list)
+
+
+def ParseToAST(pump_src_text):
+  """Convert the given Pump source text into an AST."""
+  tokens = list(Tokenize(pump_src_text))
+  code_node = ParseCodeNode(tokens)
+  return code_node
+
+
+class Env:
+  def __init__(self):
+    self.variables = []
+    self.ranges = []
+
+  def Clone(self):
+    clone = Env()
+    clone.variables = self.variables[:]
+    clone.ranges = self.ranges[:]
+    return clone
+
+  def PushVariable(self, var, value):
+    # If value looks like an int, store it as an int.
+    try:
+      int_value = int(value)
+      if ('%s' % int_value) == value:
+        value = int_value
+    except Exception:
+      pass
+    self.variables[:0] = [(var, value)]
+
+  def PopVariable(self):
+    self.variables[:1] = []
+
+  def PushRange(self, var, lower, upper):
+    self.ranges[:0] = [(var, lower, upper)]
+
+  def PopRange(self):
+    self.ranges[:1] = []
+
+  def GetValue(self, identifier):
+    for (var, value) in self.variables:
+      if identifier == var:
+        return value
+
+    print 'ERROR: meta variable %s is undefined.' % (identifier,)
+    sys.exit(1)
+
+  def EvalExp(self, exp):
+    try:
+      result = eval(exp.python_exp)
+    except Exception, e:
+      print 'ERROR: caught exception %s: %s' % (e.__class__.__name__, e)
+      print ('ERROR: failed to evaluate meta expression %s at %s' %
+             (exp.python_exp, exp.token.start))
+      sys.exit(1)
+    return result
+
+  def GetRange(self, identifier):
+    for (var, lower, upper) in self.ranges:
+      if identifier == var:
+        return (lower, upper)
+
+    print 'ERROR: range %s is undefined.' % (identifier,)
+    sys.exit(1)
+
+
+class Output:
+  def __init__(self):
+    self.string = ''
+
+  def GetLastLine(self):
+    index = self.string.rfind('\n')
+    if index < 0:
+      return ''
+
+    return self.string[index + 1:]
+
+  def Append(self, s):
+    self.string += s
+
+
+def RunAtomicCode(env, node, output):
+  if isinstance(node, VarNode):
+    identifier = node.identifier.value.strip()
+    result = Output()
+    RunAtomicCode(env.Clone(), node.atomic_code, result)
+    value = result.string
+    env.PushVariable(identifier, value)
+  elif isinstance(node, RangeNode):
+    identifier = node.identifier.value.strip()
+    lower = int(env.EvalExp(node.exp1))
+    upper = int(env.EvalExp(node.exp2))
+    env.PushRange(identifier, lower, upper)
+  elif isinstance(node, ForNode):
+    identifier = node.identifier.value.strip()
+    if node.sep is None:
+      sep = ''
+    else:
+      sep = node.sep.value
+    (lower, upper) = env.GetRange(identifier)
+    for i in range(lower, upper + 1):
+      new_env = env.Clone()
+      new_env.PushVariable(identifier, i)
+      RunCode(new_env, node.code, output)
+      if i != upper:
+        output.Append(sep)
+  elif isinstance(node, RawCodeNode):
+    output.Append(node.raw_code.value)
+  elif isinstance(node, IfNode):
+    cond = env.EvalExp(node.exp)
+    if cond:
+      RunCode(env.Clone(), node.then_branch, output)
+    elif node.else_branch is not None:
+      RunCode(env.Clone(), node.else_branch, output)
+  elif isinstance(node, ExpNode):
+    value = env.EvalExp(node)
+    output.Append('%s' % (value,))
+  elif isinstance(node, LiteralDollarNode):
+    output.Append('$')
+  elif isinstance(node, CodeNode):
+    RunCode(env.Clone(), node, output)
+  else:
+    print 'BAD'
+    print node
+    sys.exit(1)
+
+
+def RunCode(env, code_node, output):
+  for atomic_code in code_node.atomic_code:
+    RunAtomicCode(env, atomic_code, output)
+
+
+def IsComment(cur_line):
+  return '//' in cur_line
+
+
+def IsInPreprocessorDirevative(prev_lines, cur_line):
+  if cur_line.lstrip().startswith('#'):
+    return True
+  return prev_lines != [] and prev_lines[-1].endswith('\\')
+
+
+def WrapComment(line, output):
+  loc = line.find('//')
+  before_comment = line[:loc].rstrip()
+  if before_comment == '':
+    indent = loc
+  else:
+    output.append(before_comment)
+    indent = len(before_comment) - len(before_comment.lstrip())
+  prefix = indent*' ' + '// '
+  max_len = 80 - len(prefix)
+  comment = line[loc + 2:].strip()
+  segs = [seg for seg in re.split(r'(\w+\W*)', comment) if seg != '']
+  cur_line = ''
+  for seg in segs:
+    if len((cur_line + seg).rstrip()) < max_len:
+      cur_line += seg
+    else:
+      if cur_line.strip() != '':
+        output.append(prefix + cur_line.rstrip())
+      cur_line = seg.lstrip()
+  if cur_line.strip() != '':
+    output.append(prefix + cur_line.strip())
+
+
+def WrapCode(line, line_concat, output):
+  indent = len(line) - len(line.lstrip())
+  prefix = indent*' '  # Prefix of the current line
+  max_len = 80 - indent - len(line_concat)  # Maximum length of the current line
+  new_prefix = prefix + 4*' '  # Prefix of a continuation line
+  new_max_len = max_len - 4  # Maximum length of a continuation line
+  # Prefers to wrap a line after a ',' or ';'.
+  segs = [seg for seg in re.split(r'([^,;]+[,;]?)', line.strip()) if seg != '']
+  cur_line = ''  # The current line without leading spaces.
+  for seg in segs:
+    # If the line is still too long, wrap at a space.
+    while cur_line == '' and len(seg.strip()) > max_len:
+      seg = seg.lstrip()
+      split_at = seg.rfind(' ', 0, max_len)
+      output.append(prefix + seg[:split_at].strip() + line_concat)
+      seg = seg[split_at + 1:]
+      prefix = new_prefix
+      max_len = new_max_len
+
+    if len((cur_line + seg).rstrip()) < max_len:
+      cur_line = (cur_line + seg).lstrip()
+    else:
+      output.append(prefix + cur_line.rstrip() + line_concat)
+      prefix = new_prefix
+      max_len = new_max_len
+      cur_line = seg.lstrip()
+  if cur_line.strip() != '':
+    output.append(prefix + cur_line.strip())
+
+
+def WrapPreprocessorDirevative(line, output):
+  WrapCode(line, ' \\', output)
+
+
+def WrapPlainCode(line, output):
+  WrapCode(line, '', output)
+
+
+def IsHeaderGuardOrInclude(line):
+  return (re.match(r'^#(ifndef|define|endif\s*//)\s*[\w_]+\s*$', line) or
+          re.match(r'^#include\s', line))
+
+
+def WrapLongLine(line, output):
+  line = line.rstrip()
+  if len(line) <= 80:
+    output.append(line)
+  elif IsComment(line):
+    if IsHeaderGuardOrInclude(line):
+      # The style guide made an exception to allow long header guard lines
+      # and includes.
+      output.append(line)
+    else:
+      WrapComment(line, output)
+  elif IsInPreprocessorDirevative(output, line):
+    if IsHeaderGuardOrInclude(line):
+      # The style guide made an exception to allow long header guard lines
+      # and includes.
+      output.append(line)
+    else:
+      WrapPreprocessorDirevative(line, output)
+  else:
+    WrapPlainCode(line, output)
+
+
+def BeautifyCode(string):
+  lines = string.splitlines()
+  output = []
+  for line in lines:
+    WrapLongLine(line, output)
+  output2 = [line.rstrip() for line in output]
+  return '\n'.join(output2) + '\n'
+
+
+def ConvertFromPumpSource(src_text):
+  """Return the text generated from the given Pump source text."""
+  ast = ParseToAST(StripMetaComments(src_text))
+  output = Output()
+  RunCode(Env(), ast, output)
+  return BeautifyCode(output.string)
+
+
+def main(argv):
+  if len(argv) == 1:
+    print __doc__
+    sys.exit(1)
+
+  file_path = argv[-1]
+  output_str = ConvertFromPumpSource(file(file_path, 'r').read())
+  if file_path.endswith('.pump'):
+    output_file_path = file_path[:-5]
+  else:
+    output_file_path = '-'
+  if output_file_path == '-':
+    print output_str,
+  else:
+    output_file = file(output_file_path, 'w')
+    output_file.write('// This file was GENERATED by command:\n')
+    output_file.write('//     %s %s\n' %
+                      (os.path.basename(__file__), os.path.basename(file_path)))
+    output_file.write('// DO NOT EDIT BY HAND!!!\n\n')
+    output_file.write(output_str)
+    output_file.close()
+
+
+if __name__ == '__main__':
+  main(sys.argv)
diff --git a/third_party/googletest/src/scripts/test/Makefile b/third_party/googletest/src/scripts/test/Makefile
new file mode 100644 (file)
index 0000000..cdff584
--- /dev/null
@@ -0,0 +1,59 @@
+# A Makefile for fusing Google Test and building a sample test against it.
+#
+# SYNOPSIS:
+#
+#   make [all]  - makes everything.
+#   make TARGET - makes the given target.
+#   make check  - makes everything and runs the built sample test.
+#   make clean  - removes all files generated by make.
+
+# Points to the root of fused Google Test, relative to where this file is.
+FUSED_GTEST_DIR = output
+
+# Paths to the fused gtest files.
+FUSED_GTEST_H = $(FUSED_GTEST_DIR)/gtest/gtest.h
+FUSED_GTEST_ALL_CC = $(FUSED_GTEST_DIR)/gtest/gtest-all.cc
+
+# Where to find the sample test.
+SAMPLE_DIR = ../../samples
+
+# Where to find gtest_main.cc.
+GTEST_MAIN_CC = ../../src/gtest_main.cc
+
+# Flags passed to the preprocessor.
+# We have no idea here whether pthreads is available in the system, so
+# disable its use.
+CPPFLAGS += -I$(FUSED_GTEST_DIR) -DGTEST_HAS_PTHREAD=0
+
+# Flags passed to the C++ compiler.
+CXXFLAGS += -g
+
+all : sample1_unittest
+
+check : all
+       ./sample1_unittest
+
+clean :
+       rm -rf $(FUSED_GTEST_DIR) sample1_unittest *.o
+
+$(FUSED_GTEST_H) :
+       ../fuse_gtest_files.py $(FUSED_GTEST_DIR)
+
+$(FUSED_GTEST_ALL_CC) :
+       ../fuse_gtest_files.py $(FUSED_GTEST_DIR)
+
+gtest-all.o : $(FUSED_GTEST_H) $(FUSED_GTEST_ALL_CC)
+       $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(FUSED_GTEST_DIR)/gtest/gtest-all.cc
+
+gtest_main.o : $(FUSED_GTEST_H) $(GTEST_MAIN_CC)
+       $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(GTEST_MAIN_CC)
+
+sample1.o : $(SAMPLE_DIR)/sample1.cc $(SAMPLE_DIR)/sample1.h
+       $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(SAMPLE_DIR)/sample1.cc
+
+sample1_unittest.o : $(SAMPLE_DIR)/sample1_unittest.cc \
+                     $(SAMPLE_DIR)/sample1.h $(FUSED_GTEST_H)
+       $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(SAMPLE_DIR)/sample1_unittest.cc
+
+sample1_unittest : sample1.o sample1_unittest.o gtest-all.o gtest_main.o
+       $(CXX) $(CPPFLAGS) $(CXXFLAGS) $^ -o $@
diff --git a/third_party/googletest/src/scripts/upload.py b/third_party/googletest/src/scripts/upload.py
new file mode 100755 (executable)
index 0000000..6e6f9a1
--- /dev/null
@@ -0,0 +1,1387 @@
+#!/usr/bin/env python
+#
+# Copyright 2007 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Tool for uploading diffs from a version control system to the codereview app.
+
+Usage summary: upload.py [options] [-- diff_options]
+
+Diff options are passed to the diff command of the underlying system.
+
+Supported version control systems:
+  Git
+  Mercurial
+  Subversion
+
+It is important for Git/Mercurial users to specify a tree/node/branch to diff
+against by using the '--rev' option.
+"""
+# This code is derived from appcfg.py in the App Engine SDK (open source),
+# and from ASPN recipe #146306.
+
+import cookielib
+import getpass
+import logging
+import md5
+import mimetypes
+import optparse
+import os
+import re
+import socket
+import subprocess
+import sys
+import urllib
+import urllib2
+import urlparse
+
+try:
+  import readline
+except ImportError:
+  pass
+
+# The logging verbosity:
+#  0: Errors only.
+#  1: Status messages.
+#  2: Info logs.
+#  3: Debug logs.
+verbosity = 1
+
+# Max size of patch or base file.
+MAX_UPLOAD_SIZE = 900 * 1024
+
+
+def GetEmail(prompt):
+  """Prompts the user for their email address and returns it.
+
+  The last used email address is saved to a file and offered up as a suggestion
+  to the user. If the user presses enter without typing in anything the last
+  used email address is used. If the user enters a new address, it is saved
+  for next time we prompt.
+
+  """
+  last_email_file_name = os.path.expanduser("~/.last_codereview_email_address")
+  last_email = ""
+  if os.path.exists(last_email_file_name):
+    try:
+      last_email_file = open(last_email_file_name, "r")
+      last_email = last_email_file.readline().strip("\n")
+      last_email_file.close()
+      prompt += " [%s]" % last_email
+    except IOError, e:
+      pass
+  email = raw_input(prompt + ": ").strip()
+  if email:
+    try:
+      last_email_file = open(last_email_file_name, "w")
+      last_email_file.write(email)
+      last_email_file.close()
+    except IOError, e:
+      pass
+  else:
+    email = last_email
+  return email
+
+
+def StatusUpdate(msg):
+  """Print a status message to stdout.
+
+  If 'verbosity' is greater than 0, print the message.
+
+  Args:
+    msg: The string to print.
+  """
+  if verbosity > 0:
+    print msg
+
+
+def ErrorExit(msg):
+  """Print an error message to stderr and exit."""
+  print >>sys.stderr, msg
+  sys.exit(1)
+
+
+class ClientLoginError(urllib2.HTTPError):
+  """Raised to indicate there was an error authenticating with ClientLogin."""
+
+  def __init__(self, url, code, msg, headers, args):
+    urllib2.HTTPError.__init__(self, url, code, msg, headers, None)
+    self.args = args
+    self.reason = args["Error"]
+
+
+class AbstractRpcServer(object):
+  """Provides a common interface for a simple RPC server."""
+
+  def __init__(self, host, auth_function, host_override=None, extra_headers={},
+               save_cookies=False):
+    """Creates a new HttpRpcServer.
+
+    Args:
+      host: The host to send requests to.
+      auth_function: A function that takes no arguments and returns an
+        (email, password) tuple when called. Will be called if authentication
+        is required.
+      host_override: The host header to send to the server (defaults to host).
+      extra_headers: A dict of extra headers to append to every request.
+      save_cookies: If True, save the authentication cookies to local disk.
+        If False, use an in-memory cookiejar instead.  Subclasses must
+        implement this functionality.  Defaults to False.
+    """
+    self.host = host
+    self.host_override = host_override
+    self.auth_function = auth_function
+    self.authenticated = False
+    self.extra_headers = extra_headers
+    self.save_cookies = save_cookies
+    self.opener = self._GetOpener()
+    if self.host_override:
+      logging.info("Server: %s; Host: %s", self.host, self.host_override)
+    else:
+      logging.info("Server: %s", self.host)
+
+  def _GetOpener(self):
+    """Returns an OpenerDirector for making HTTP requests.
+
+    Returns:
+      A urllib2.OpenerDirector object.
+    """
+    raise NotImplementedError()
+
+  def _CreateRequest(self, url, data=None):
+    """Creates a new urllib request."""
+    logging.debug("Creating request for: '%s' with payload:\n%s", url, data)
+    req = urllib2.Request(url, data=data)
+    if self.host_override:
+      req.add_header("Host", self.host_override)
+    for key, value in self.extra_headers.iteritems():
+      req.add_header(key, value)
+    return req
+
+  def _GetAuthToken(self, email, password):
+    """Uses ClientLogin to authenticate the user, returning an auth token.
+
+    Args:
+      email:    The user's email address
+      password: The user's password
+
+    Raises:
+      ClientLoginError: If there was an error authenticating with ClientLogin.
+      HTTPError: If there was some other form of HTTP error.
+
+    Returns:
+      The authentication token returned by ClientLogin.
+    """
+    account_type = "GOOGLE"
+    if self.host.endswith(".google.com"):
+      # Needed for use inside Google.
+      account_type = "HOSTED"
+    req = self._CreateRequest(
+        url="https://www.google.com/accounts/ClientLogin",
+        data=urllib.urlencode({
+            "Email": email,
+            "Passwd": password,
+            "service": "ah",
+            "source": "rietveld-codereview-upload",
+            "accountType": account_type,
+        }),
+    )
+    try:
+      response = self.opener.open(req)
+      response_body = response.read()
+      response_dict = dict(x.split("=")
+                           for x in response_body.split("\n") if x)
+      return response_dict["Auth"]
+    except urllib2.HTTPError, e:
+      if e.code == 403:
+        body = e.read()
+        response_dict = dict(x.split("=", 1) for x in body.split("\n") if x)
+        raise ClientLoginError(req.get_full_url(), e.code, e.msg,
+                               e.headers, response_dict)
+      else:
+        raise
+
+  def _GetAuthCookie(self, auth_token):
+    """Fetches authentication cookies for an authentication token.
+
+    Args:
+      auth_token: The authentication token returned by ClientLogin.
+
+    Raises:
+      HTTPError: If there was an error fetching the authentication cookies.
+    """
+    # This is a dummy value to allow us to identify when we're successful.
+    continue_location = "http://localhost/"
+    args = {"continue": continue_location, "auth": auth_token}
+    req = self._CreateRequest("http://%s/_ah/login?%s" %
+                              (self.host, urllib.urlencode(args)))
+    try:
+      response = self.opener.open(req)
+    except urllib2.HTTPError, e:
+      response = e
+    if (response.code != 302 or
+        response.info()["location"] != continue_location):
+      raise urllib2.HTTPError(req.get_full_url(), response.code, response.msg,
+                              response.headers, response.fp)
+    self.authenticated = True
+
+  def _Authenticate(self):
+    """Authenticates the user.
+
+    The authentication process works as follows:
+     1) We get a username and password from the user
+     2) We use ClientLogin to obtain an AUTH token for the user
+        (see http://code.google.com/apis/accounts/AuthForInstalledApps.html).
+     3) We pass the auth token to /_ah/login on the server to obtain an
+        authentication cookie. If login was successful, it tries to redirect
+        us to the URL we provided.
+
+    If we attempt to access the upload API without first obtaining an
+    authentication cookie, it returns a 401 response and directs us to
+    authenticate ourselves with ClientLogin.
+    """
+    for i in range(3):
+      credentials = self.auth_function()
+      try:
+        auth_token = self._GetAuthToken(credentials[0], credentials[1])
+      except ClientLoginError, e:
+        if e.reason == "BadAuthentication":
+          print >>sys.stderr, "Invalid username or password."
+          continue
+        if e.reason == "CaptchaRequired":
+          print >>sys.stderr, (
+              "Please go to\n"
+              "https://www.google.com/accounts/DisplayUnlockCaptcha\n"
+              "and verify you are a human.  Then try again.")
+          break
+        if e.reason == "NotVerified":
+          print >>sys.stderr, "Account not verified."
+          break
+        if e.reason == "TermsNotAgreed":
+          print >>sys.stderr, "User has not agreed to TOS."
+          break
+        if e.reason == "AccountDeleted":
+          print >>sys.stderr, "The user account has been deleted."
+          break
+        if e.reason == "AccountDisabled":
+          print >>sys.stderr, "The user account has been disabled."
+          break
+        if e.reason == "ServiceDisabled":
+          print >>sys.stderr, ("The user's access to the service has been "
+                               "disabled.")
+          break
+        if e.reason == "ServiceUnavailable":
+          print >>sys.stderr, "The service is not available; try again later."
+          break
+        raise
+      self._GetAuthCookie(auth_token)
+      return
+
+  def Send(self, request_path, payload=None,
+           content_type="application/octet-stream",
+           timeout=None,
+           **kwargs):
+    """Sends an RPC and returns the response.
+
+    Args:
+      request_path: The path to send the request to, eg /api/appversion/create.
+      payload: The body of the request, or None to send an empty request.
+      content_type: The Content-Type header to use.
+      timeout: timeout in seconds; default None i.e. no timeout.
+        (Note: for large requests on OS X, the timeout doesn't work right.)
+      kwargs: Any keyword arguments are converted into query string parameters.
+
+    Returns:
+      The response body, as a string.
+    """
+    # TODO: Don't require authentication.  Let the server say
+    # whether it is necessary.
+    if not self.authenticated:
+      self._Authenticate()
+
+    old_timeout = socket.getdefaulttimeout()
+    socket.setdefaulttimeout(timeout)
+    try:
+      tries = 0
+      while True:
+        tries += 1
+        args = dict(kwargs)
+        url = "http://%s%s" % (self.host, request_path)
+        if args:
+          url += "?" + urllib.urlencode(args)
+        req = self._CreateRequest(url=url, data=payload)
+        req.add_header("Content-Type", content_type)
+        try:
+          f = self.opener.open(req)
+          response = f.read()
+          f.close()
+          return response
+        except urllib2.HTTPError, e:
+          if tries > 3:
+            raise
+          elif e.code == 401:
+            self._Authenticate()
+##           elif e.code >= 500 and e.code < 600:
+##             # Server Error - try again.
+##             continue
+          else:
+            raise
+    finally:
+      socket.setdefaulttimeout(old_timeout)
+
+
+class HttpRpcServer(AbstractRpcServer):
+  """Provides a simplified RPC-style interface for HTTP requests."""
+
+  def _Authenticate(self):
+    """Save the cookie jar after authentication."""
+    super(HttpRpcServer, self)._Authenticate()
+    if self.save_cookies:
+      StatusUpdate("Saving authentication cookies to %s" % self.cookie_file)
+      self.cookie_jar.save()
+
+  def _GetOpener(self):
+    """Returns an OpenerDirector that supports cookies and ignores redirects.
+
+    Returns:
+      A urllib2.OpenerDirector object.
+    """
+    opener = urllib2.OpenerDirector()
+    opener.add_handler(urllib2.ProxyHandler())
+    opener.add_handler(urllib2.UnknownHandler())
+    opener.add_handler(urllib2.HTTPHandler())
+    opener.add_handler(urllib2.HTTPDefaultErrorHandler())
+    opener.add_handler(urllib2.HTTPSHandler())
+    opener.add_handler(urllib2.HTTPErrorProcessor())
+    if self.save_cookies:
+      self.cookie_file = os.path.expanduser("~/.codereview_upload_cookies")
+      self.cookie_jar = cookielib.MozillaCookieJar(self.cookie_file)
+      if os.path.exists(self.cookie_file):
+        try:
+          self.cookie_jar.load()
+          self.authenticated = True
+          StatusUpdate("Loaded authentication cookies from %s" %
+                       self.cookie_file)
+        except (cookielib.LoadError, IOError):
+          # Failed to load cookies - just ignore them.
+          pass
+      else:
+        # Create an empty cookie file with mode 600
+        fd = os.open(self.cookie_file, os.O_CREAT, 0600)
+        os.close(fd)
+      # Always chmod the cookie file
+      os.chmod(self.cookie_file, 0600)
+    else:
+      # Don't save cookies across runs of update.py.
+      self.cookie_jar = cookielib.CookieJar()
+    opener.add_handler(urllib2.HTTPCookieProcessor(self.cookie_jar))
+    return opener
+
+
+parser = optparse.OptionParser(usage="%prog [options] [-- diff_options]")
+parser.add_option("-y", "--assume_yes", action="store_true",
+                  dest="assume_yes", default=False,
+                  help="Assume that the answer to yes/no questions is 'yes'.")
+# Logging
+group = parser.add_option_group("Logging options")
+group.add_option("-q", "--quiet", action="store_const", const=0,
+                 dest="verbose", help="Print errors only.")
+group.add_option("-v", "--verbose", action="store_const", const=2,
+                 dest="verbose", default=1,
+                 help="Print info level logs (default).")
+group.add_option("--noisy", action="store_const", const=3,
+                 dest="verbose", help="Print all logs.")
+# Review server
+group = parser.add_option_group("Review server options")
+group.add_option("-s", "--server", action="store", dest="server",
+                 default="codereview.appspot.com",
+                 metavar="SERVER",
+                 help=("The server to upload to. The format is host[:port]. "
+                       "Defaults to 'codereview.appspot.com'."))
+group.add_option("-e", "--email", action="store", dest="email",
+                 metavar="EMAIL", default=None,
+                 help="The username to use. Will prompt if omitted.")
+group.add_option("-H", "--host", action="store", dest="host",
+                 metavar="HOST", default=None,
+                 help="Overrides the Host header sent with all RPCs.")
+group.add_option("--no_cookies", action="store_false",
+                 dest="save_cookies", default=True,
+                 help="Do not save authentication cookies to local disk.")
+# Issue
+group = parser.add_option_group("Issue options")
+group.add_option("-d", "--description", action="store", dest="description",
+                 metavar="DESCRIPTION", default=None,
+                 help="Optional description when creating an issue.")
+group.add_option("-f", "--description_file", action="store",
+                 dest="description_file", metavar="DESCRIPTION_FILE",
+                 default=None,
+                 help="Optional path of a file that contains "
+                      "the description when creating an issue.")
+group.add_option("-r", "--reviewers", action="store", dest="reviewers",
+                 metavar="REVIEWERS", default=None,
+                 help="Add reviewers (comma separated email addresses).")
+group.add_option("--cc", action="store", dest="cc",
+                 metavar="CC", default=None,
+                 help="Add CC (comma separated email addresses).")
+# Upload options
+group = parser.add_option_group("Patch options")
+group.add_option("-m", "--message", action="store", dest="message",
+                 metavar="MESSAGE", default=None,
+                 help="A message to identify the patch. "
+                      "Will prompt if omitted.")
+group.add_option("-i", "--issue", type="int", action="store",
+                 metavar="ISSUE", default=None,
+                 help="Issue number to which to add. Defaults to new issue.")
+group.add_option("--download_base", action="store_true",
+                 dest="download_base", default=False,
+                 help="Base files will be downloaded by the server "
+                 "(side-by-side diffs may not work on files with CRs).")
+group.add_option("--rev", action="store", dest="revision",
+                 metavar="REV", default=None,
+                 help="Branch/tree/revision to diff against (used by DVCS).")
+group.add_option("--send_mail", action="store_true",
+                 dest="send_mail", default=False,
+                 help="Send notification email to reviewers.")
+
+
+def GetRpcServer(options):
+  """Returns an instance of an AbstractRpcServer.
+
+  Returns:
+    A new AbstractRpcServer, on which RPC calls can be made.
+  """
+
+  rpc_server_class = HttpRpcServer
+
+  def GetUserCredentials():
+    """Prompts the user for a username and password."""
+    email = options.email
+    if email is None:
+      email = GetEmail("Email (login for uploading to %s)" % options.server)
+    password = getpass.getpass("Password for %s: " % email)
+    return (email, password)
+
+  # If this is the dev_appserver, use fake authentication.
+  host = (options.host or options.server).lower()
+  if host == "localhost" or host.startswith("localhost:"):
+    email = options.email
+    if email is None:
+      email = "test@example.com"
+      logging.info("Using debug user %s.  Override with --email" % email)
+    server = rpc_server_class(
+        options.server,
+        lambda: (email, "password"),
+        host_override=options.host,
+        extra_headers={"Cookie":
+                       'dev_appserver_login="%s:False"' % email},
+        save_cookies=options.save_cookies)
+    # Don't try to talk to ClientLogin.
+    server.authenticated = True
+    return server
+
+  return rpc_server_class(options.server, GetUserCredentials,
+                          host_override=options.host,
+                          save_cookies=options.save_cookies)
+
+
+def EncodeMultipartFormData(fields, files):
+  """Encode form fields for multipart/form-data.
+
+  Args:
+    fields: A sequence of (name, value) elements for regular form fields.
+    files: A sequence of (name, filename, value) elements for data to be
+           uploaded as files.
+  Returns:
+    (content_type, body) ready for httplib.HTTP instance.
+
+  Source:
+    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306
+  """
+  BOUNDARY = '-M-A-G-I-C---B-O-U-N-D-A-R-Y-'
+  CRLF = '\r\n'
+  lines = []
+  for (key, value) in fields:
+    lines.append('--' + BOUNDARY)
+    lines.append('Content-Disposition: form-data; name="%s"' % key)
+    lines.append('')
+    lines.append(value)
+  for (key, filename, value) in files:
+    lines.append('--' + BOUNDARY)
+    lines.append('Content-Disposition: form-data; name="%s"; filename="%s"' %
+             (key, filename))
+    lines.append('Content-Type: %s' % GetContentType(filename))
+    lines.append('')
+    lines.append(value)
+  lines.append('--' + BOUNDARY + '--')
+  lines.append('')
+  body = CRLF.join(lines)
+  content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
+  return content_type, body
+
+
+def GetContentType(filename):
+  """Helper to guess the content-type from the filename."""
+  return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
+
+
+# Use a shell for subcommands on Windows to get a PATH search.
+use_shell = sys.platform.startswith("win")
+
+def RunShellWithReturnCode(command, print_output=False,
+                           universal_newlines=True):
+  """Executes a command and returns the output from stdout and the return code.
+
+  Args:
+    command: Command to execute.
+    print_output: If True, the output is printed to stdout.
+                  If False, both stdout and stderr are ignored.
+    universal_newlines: Use universal_newlines flag (default: True).
+
+  Returns:
+    Tuple (output, return code)
+  """
+  logging.info("Running %s", command)
+  p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+                       shell=use_shell, universal_newlines=universal_newlines)
+  if print_output:
+    output_array = []
+    while True:
+      line = p.stdout.readline()
+      if not line:
+        break
+      print line.strip("\n")
+      output_array.append(line)
+    output = "".join(output_array)
+  else:
+    output = p.stdout.read()
+  p.wait()
+  errout = p.stderr.read()
+  if print_output and errout:
+    print >>sys.stderr, errout
+  p.stdout.close()
+  p.stderr.close()
+  return output, p.returncode
+
+
+def RunShell(command, silent_ok=False, universal_newlines=True,
+             print_output=False):
+  data, retcode = RunShellWithReturnCode(command, print_output,
+                                         universal_newlines)
+  if retcode:
+    ErrorExit("Got error status from %s:\n%s" % (command, data))
+  if not silent_ok and not data:
+    ErrorExit("No output from %s" % command)
+  return data
+
+
+class VersionControlSystem(object):
+  """Abstract base class providing an interface to the VCS."""
+
+  def __init__(self, options):
+    """Constructor.
+
+    Args:
+      options: Command line options.
+    """
+    self.options = options
+
+  def GenerateDiff(self, args):
+    """Return the current diff as a string.
+
+    Args:
+      args: Extra arguments to pass to the diff command.
+    """
+    raise NotImplementedError(
+        "abstract method -- subclass %s must override" % self.__class__)
+
+  def GetUnknownFiles(self):
+    """Return a list of files unknown to the VCS."""
+    raise NotImplementedError(
+        "abstract method -- subclass %s must override" % self.__class__)
+
+  def CheckForUnknownFiles(self):
+    """Show an "are you sure?" prompt if there are unknown files."""
+    unknown_files = self.GetUnknownFiles()
+    if unknown_files:
+      print "The following files are not added to version control:"
+      for line in unknown_files:
+        print line
+      prompt = "Are you sure to continue?(y/N) "
+      answer = raw_input(prompt).strip()
+      if answer != "y":
+        ErrorExit("User aborted")
+
+  def GetBaseFile(self, filename):
+    """Get the content of the upstream version of a file.
+
+    Returns:
+      A tuple (base_content, new_content, is_binary, status)
+        base_content: The contents of the base file.
+        new_content: For text files, this is empty.  For binary files, this is
+          the contents of the new file, since the diff output won't contain
+          information to reconstruct the current file.
+        is_binary: True iff the file is binary.
+        status: The status of the file.
+    """
+
+    raise NotImplementedError(
+        "abstract method -- subclass %s must override" % self.__class__)
+
+
+  def GetBaseFiles(self, diff):
+    """Helper that calls GetBase file for each file in the patch.
+
+    Returns:
+      A dictionary that maps from filename to GetBaseFile's tuple.  Filenames
+      are retrieved based on lines that start with "Index:" or
+      "Property changes on:".
+    """
+    files = {}
+    for line in diff.splitlines(True):
+      if line.startswith('Index:') or line.startswith('Property changes on:'):
+        unused, filename = line.split(':', 1)
+        # On Windows if a file has property changes its filename uses '\'
+        # instead of '/'.
+        filename = filename.strip().replace('\\', '/')
+        files[filename] = self.GetBaseFile(filename)
+    return files
+
+
+  def UploadBaseFiles(self, issue, rpc_server, patch_list, patchset, options,
+                      files):
+    """Uploads the base files (and if necessary, the current ones as well)."""
+
+    def UploadFile(filename, file_id, content, is_binary, status, is_base):
+      """Uploads a file to the server."""
+      file_too_large = False
+      if is_base:
+        type = "base"
+      else:
+        type = "current"
+      if len(content) > MAX_UPLOAD_SIZE:
+        print ("Not uploading the %s file for %s because it's too large." %
+               (type, filename))
+        file_too_large = True
+        content = ""
+      checksum = md5.new(content).hexdigest()
+      if options.verbose > 0 and not file_too_large:
+        print "Uploading %s file for %s" % (type, filename)
+      url = "/%d/upload_content/%d/%d" % (int(issue), int(patchset), file_id)
+      form_fields = [("filename", filename),
+                     ("status", status),
+                     ("checksum", checksum),
+                     ("is_binary", str(is_binary)),
+                     ("is_current", str(not is_base)),
+                    ]
+      if file_too_large:
+        form_fields.append(("file_too_large", "1"))
+      if options.email:
+        form_fields.append(("user", options.email))
+      ctype, body = EncodeMultipartFormData(form_fields,
+                                            [("data", filename, content)])
+      response_body = rpc_server.Send(url, body,
+                                      content_type=ctype)
+      if not response_body.startswith("OK"):
+        StatusUpdate("  --> %s" % response_body)
+        sys.exit(1)
+
+    patches = dict()
+    [patches.setdefault(v, k) for k, v in patch_list]
+    for filename in patches.keys():
+      base_content, new_content, is_binary, status = files[filename]
+      file_id_str = patches.get(filename)
+      if file_id_str.find("nobase") != -1:
+        base_content = None
+        file_id_str = file_id_str[file_id_str.rfind("_") + 1:]
+      file_id = int(file_id_str)
+      if base_content != None:
+        UploadFile(filename, file_id, base_content, is_binary, status, True)
+      if new_content != None:
+        UploadFile(filename, file_id, new_content, is_binary, status, False)
+
+  def IsImage(self, filename):
+    """Returns true if the filename has an image extension."""
+    mimetype =  mimetypes.guess_type(filename)[0]
+    if not mimetype:
+      return False
+    return mimetype.startswith("image/")
+
+
+class SubversionVCS(VersionControlSystem):
+  """Implementation of the VersionControlSystem interface for Subversion."""
+
+  def __init__(self, options):
+    super(SubversionVCS, self).__init__(options)
+    if self.options.revision:
+      match = re.match(r"(\d+)(:(\d+))?", self.options.revision)
+      if not match:
+        ErrorExit("Invalid Subversion revision %s." % self.options.revision)
+      self.rev_start = match.group(1)
+      self.rev_end = match.group(3)
+    else:
+      self.rev_start = self.rev_end = None
+    # Cache output from "svn list -r REVNO dirname".
+    # Keys: dirname, Values: 2-tuple (ouput for start rev and end rev).
+    self.svnls_cache = {}
+    # SVN base URL is required to fetch files deleted in an older revision.
+    # Result is cached to not guess it over and over again in GetBaseFile().
+    required = self.options.download_base or self.options.revision is not None
+    self.svn_base = self._GuessBase(required)
+
+  def GuessBase(self, required):
+    """Wrapper for _GuessBase."""
+    return self.svn_base
+
+  def _GuessBase(self, required):
+    """Returns the SVN base URL.
+
+    Args:
+      required: If true, exits if the url can't be guessed, otherwise None is
+        returned.
+    """
+    info = RunShell(["svn", "info"])
+    for line in info.splitlines():
+      words = line.split()
+      if len(words) == 2 and words[0] == "URL:":
+        url = words[1]
+        scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
+        username, netloc = urllib.splituser(netloc)
+        if username:
+          logging.info("Removed username from base URL")
+        if netloc.endswith("svn.python.org"):
+          if netloc == "svn.python.org":
+            if path.startswith("/projects/"):
+              path = path[9:]
+          elif netloc != "pythondev@svn.python.org":
+            ErrorExit("Unrecognized Python URL: %s" % url)
+          base = "http://svn.python.org/view/*checkout*%s/" % path
+          logging.info("Guessed Python base = %s", base)
+        elif netloc.endswith("svn.collab.net"):
+          if path.startswith("/repos/"):
+            path = path[6:]
+          base = "http://svn.collab.net/viewvc/*checkout*%s/" % path
+          logging.info("Guessed CollabNet base = %s", base)
+        elif netloc.endswith(".googlecode.com"):
+          path = path + "/"
+          base = urlparse.urlunparse(("http", netloc, path, params,
+                                      query, fragment))
+          logging.info("Guessed Google Code base = %s", base)
+        else:
+          path = path + "/"
+          base = urlparse.urlunparse((scheme, netloc, path, params,
+                                      query, fragment))
+          logging.info("Guessed base = %s", base)
+        return base
+    if required:
+      ErrorExit("Can't find URL in output from svn info")
+    return None
+
+  def GenerateDiff(self, args):
+    cmd = ["svn", "diff"]
+    if self.options.revision:
+      cmd += ["-r", self.options.revision]
+    cmd.extend(args)
+    data = RunShell(cmd)
+    count = 0
+    for line in data.splitlines():
+      if line.startswith("Index:") or line.startswith("Property changes on:"):
+        count += 1
+        logging.info(line)
+    if not count:
+      ErrorExit("No valid patches found in output from svn diff")
+    return data
+
+  def _CollapseKeywords(self, content, keyword_str):
+    """Collapses SVN keywords."""
+    # svn cat translates keywords but svn diff doesn't. As a result of this
+    # behavior patching.PatchChunks() fails with a chunk mismatch error.
+    # This part was originally written by the Review Board development team
+    # who had the same problem (http://reviews.review-board.org/r/276/).
+    # Mapping of keywords to known aliases
+    svn_keywords = {
+      # Standard keywords
+      'Date':                ['Date', 'LastChangedDate'],
+      'Revision':            ['Revision', 'LastChangedRevision', 'Rev'],
+      'Author':              ['Author', 'LastChangedBy'],
+      'HeadURL':             ['HeadURL', 'URL'],
+      'Id':                  ['Id'],
+
+      # Aliases
+      'LastChangedDate':     ['LastChangedDate', 'Date'],
+      'LastChangedRevision': ['LastChangedRevision', 'Rev', 'Revision'],
+      'LastChangedBy':       ['LastChangedBy', 'Author'],
+      'URL':                 ['URL', 'HeadURL'],
+    }
+
+    def repl(m):
+       if m.group(2):
+         return "$%s::%s$" % (m.group(1), " " * len(m.group(3)))
+       return "$%s$" % m.group(1)
+    keywords = [keyword
+                for name in keyword_str.split(" ")
+                for keyword in svn_keywords.get(name, [])]
+    return re.sub(r"\$(%s):(:?)([^\$]+)\$" % '|'.join(keywords), repl, content)
+
+  def GetUnknownFiles(self):
+    status = RunShell(["svn", "status", "--ignore-externals"], silent_ok=True)
+    unknown_files = []
+    for line in status.split("\n"):
+      if line and line[0] == "?":
+        unknown_files.append(line)
+    return unknown_files
+
+  def ReadFile(self, filename):
+    """Returns the contents of a file."""
+    file = open(filename, 'rb')
+    result = ""
+    try:
+      result = file.read()
+    finally:
+      file.close()
+    return result
+
+  def GetStatus(self, filename):
+    """Returns the status of a file."""
+    if not self.options.revision:
+      status = RunShell(["svn", "status", "--ignore-externals", filename])
+      if not status:
+        ErrorExit("svn status returned no output for %s" % filename)
+      status_lines = status.splitlines()
+      # If file is in a cl, the output will begin with
+      # "\n--- Changelist 'cl_name':\n".  See
+      # http://svn.collab.net/repos/svn/trunk/notes/changelist-design.txt
+      if (len(status_lines) == 3 and
+          not status_lines[0] and
+          status_lines[1].startswith("--- Changelist")):
+        status = status_lines[2]
+      else:
+        status = status_lines[0]
+    # If we have a revision to diff against we need to run "svn list"
+    # for the old and the new revision and compare the results to get
+    # the correct status for a file.
+    else:
+      dirname, relfilename = os.path.split(filename)
+      if dirname not in self.svnls_cache:
+        cmd = ["svn", "list", "-r", self.rev_start, dirname or "."]
+        out, returncode = RunShellWithReturnCode(cmd)
+        if returncode:
+          ErrorExit("Failed to get status for %s." % filename)
+        old_files = out.splitlines()
+        args = ["svn", "list"]
+        if self.rev_end:
+          args += ["-r", self.rev_end]
+        cmd = args + [dirname or "."]
+        out, returncode = RunShellWithReturnCode(cmd)
+        if returncode:
+          ErrorExit("Failed to run command %s" % cmd)
+        self.svnls_cache[dirname] = (old_files, out.splitlines())
+      old_files, new_files = self.svnls_cache[dirname]
+      if relfilename in old_files and relfilename not in new_files:
+        status = "D   "
+      elif relfilename in old_files and relfilename in new_files:
+        status = "M   "
+      else:
+        status = "A   "
+    return status
+
+  def GetBaseFile(self, filename):
+    status = self.GetStatus(filename)
+    base_content = None
+    new_content = None
+
+    # If a file is copied its status will be "A  +", which signifies
+    # "addition-with-history".  See "svn st" for more information.  We need to
+    # upload the original file or else diff parsing will fail if the file was
+    # edited.
+    if status[0] == "A" and status[3] != "+":
+      # We'll need to upload the new content if we're adding a binary file
+      # since diff's output won't contain it.
+      mimetype = RunShell(["svn", "propget", "svn:mime-type", filename],
+                          silent_ok=True)
+      base_content = ""
+      is_binary = mimetype and not mimetype.startswith("text/")
+      if is_binary and self.IsImage(filename):
+        new_content = self.ReadFile(filename)
+    elif (status[0] in ("M", "D", "R") or
+          (status[0] == "A" and status[3] == "+") or  # Copied file.
+          (status[0] == " " and status[1] == "M")):  # Property change.
+      args = []
+      if self.options.revision:
+        url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start)
+      else:
+        # Don't change filename, it's needed later.
+        url = filename
+        args += ["-r", "BASE"]
+      cmd = ["svn"] + args + ["propget", "svn:mime-type", url]
+      mimetype, returncode = RunShellWithReturnCode(cmd)
+      if returncode:
+        # File does not exist in the requested revision.
+        # Reset mimetype, it contains an error message.
+        mimetype = ""
+      get_base = False
+      is_binary = mimetype and not mimetype.startswith("text/")
+      if status[0] == " ":
+        # Empty base content just to force an upload.
+        base_content = ""
+      elif is_binary:
+        if self.IsImage(filename):
+          get_base = True
+          if status[0] == "M":
+            if not self.rev_end:
+              new_content = self.ReadFile(filename)
+            else:
+              url = "%s/%s@%s" % (self.svn_base, filename, self.rev_end)
+              new_content = RunShell(["svn", "cat", url],
+                                     universal_newlines=True, silent_ok=True)
+        else:
+          base_content = ""
+      else:
+        get_base = True
+
+      if get_base:
+        if is_binary:
+          universal_newlines = False
+        else:
+          universal_newlines = True
+        if self.rev_start:
+          # "svn cat -r REV delete_file.txt" doesn't work. cat requires
+          # the full URL with "@REV" appended instead of using "-r" option.
+          url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start)
+          base_content = RunShell(["svn", "cat", url],
+                                  universal_newlines=universal_newlines,
+                                  silent_ok=True)
+        else:
+          base_content = RunShell(["svn", "cat", filename],
+                                  universal_newlines=universal_newlines,
+                                  silent_ok=True)
+        if not is_binary:
+          args = []
+          if self.rev_start:
+            url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start)
+          else:
+            url = filename
+            args += ["-r", "BASE"]
+          cmd = ["svn"] + args + ["propget", "svn:keywords", url]
+          keywords, returncode = RunShellWithReturnCode(cmd)
+          if keywords and not returncode:
+            base_content = self._CollapseKeywords(base_content, keywords)
+    else:
+      StatusUpdate("svn status returned unexpected output: %s" % status)
+      sys.exit(1)
+    return base_content, new_content, is_binary, status[0:5]
+
+
+class GitVCS(VersionControlSystem):
+  """Implementation of the VersionControlSystem interface for Git."""
+
+  def __init__(self, options):
+    super(GitVCS, self).__init__(options)
+    # Map of filename -> hash of base file.
+    self.base_hashes = {}
+
+  def GenerateDiff(self, extra_args):
+    # This is more complicated than svn's GenerateDiff because we must convert
+    # the diff output to include an svn-style "Index:" line as well as record
+    # the hashes of the base files, so we can upload them along with our diff.
+    if self.options.revision:
+      extra_args = [self.options.revision] + extra_args
+    gitdiff = RunShell(["git", "diff", "--full-index"] + extra_args)
+    svndiff = []
+    filecount = 0
+    filename = None
+    for line in gitdiff.splitlines():
+      match = re.match(r"diff --git a/(.*) b/.*$", line)
+      if match:
+        filecount += 1
+        filename = match.group(1)
+        svndiff.append("Index: %s\n" % filename)
+      else:
+        # The "index" line in a git diff looks like this (long hashes elided):
+        #   index 82c0d44..b2cee3f 100755
+        # We want to save the left hash, as that identifies the base file.
+        match = re.match(r"index (\w+)\.\.", line)
+        if match:
+          self.base_hashes[filename] = match.group(1)
+      svndiff.append(line + "\n")
+    if not filecount:
+      ErrorExit("No valid patches found in output from git diff")
+    return "".join(svndiff)
+
+  def GetUnknownFiles(self):
+    status = RunShell(["git", "ls-files", "--exclude-standard", "--others"],
+                      silent_ok=True)
+    return status.splitlines()
+
+  def GetBaseFile(self, filename):
+    hash = self.base_hashes[filename]
+    base_content = None
+    new_content = None
+    is_binary = False
+    if hash == "0" * 40:  # All-zero hash indicates no base file.
+      status = "A"
+      base_content = ""
+    else:
+      status = "M"
+      base_content, returncode = RunShellWithReturnCode(["git", "show", hash])
+      if returncode:
+        ErrorExit("Got error status from 'git show %s'" % hash)
+    return (base_content, new_content, is_binary, status)
+
+
+class MercurialVCS(VersionControlSystem):
+  """Implementation of the VersionControlSystem interface for Mercurial."""
+
+  def __init__(self, options, repo_dir):
+    super(MercurialVCS, self).__init__(options)
+    # Absolute path to repository (we can be in a subdir)
+    self.repo_dir = os.path.normpath(repo_dir)
+    # Compute the subdir
+    cwd = os.path.normpath(os.getcwd())
+    assert cwd.startswith(self.repo_dir)
+    self.subdir = cwd[len(self.repo_dir):].lstrip(r"\/")
+    if self.options.revision:
+      self.base_rev = self.options.revision
+    else:
+      self.base_rev = RunShell(["hg", "parent", "-q"]).split(':')[1].strip()
+
+  def _GetRelPath(self, filename):
+    """Get relative path of a file according to the current directory,
+    given its logical path in the repo."""
+    assert filename.startswith(self.subdir), filename
+    return filename[len(self.subdir):].lstrip(r"\/")
+
+  def GenerateDiff(self, extra_args):
+    # If no file specified, restrict to the current subdir
+    extra_args = extra_args or ["."]
+    cmd = ["hg", "diff", "--git", "-r", self.base_rev] + extra_args
+    data = RunShell(cmd, silent_ok=True)
+    svndiff = []
+    filecount = 0
+    for line in data.splitlines():
+      m = re.match("diff --git a/(\S+) b/(\S+)", line)
+      if m:
+        # Modify line to make it look like as it comes from svn diff.
+        # With this modification no changes on the server side are required
+        # to make upload.py work with Mercurial repos.
+        # NOTE: for proper handling of moved/copied files, we have to use
+        # the second filename.
+        filename = m.group(2)
+        svndiff.append("Index: %s" % filename)
+        svndiff.append("=" * 67)
+        filecount += 1
+        logging.info(line)
+      else:
+        svndiff.append(line)
+    if not filecount:
+      ErrorExit("No valid patches found in output from hg diff")
+    return "\n".join(svndiff) + "\n"
+
+  def GetUnknownFiles(self):
+    """Return a list of files unknown to the VCS."""
+    args = []
+    status = RunShell(["hg", "status", "--rev", self.base_rev, "-u", "."],
+        silent_ok=True)
+    unknown_files = []
+    for line in status.splitlines():
+      st, fn = line.split(" ", 1)
+      if st == "?":
+        unknown_files.append(fn)
+    return unknown_files
+
+  def GetBaseFile(self, filename):
+    # "hg status" and "hg cat" both take a path relative to the current subdir
+    # rather than to the repo root, but "hg diff" has given us the full path
+    # to the repo root.
+    base_content = ""
+    new_content = None
+    is_binary = False
+    oldrelpath = relpath = self._GetRelPath(filename)
+    # "hg status -C" returns two lines for moved/copied files, one otherwise
+    out = RunShell(["hg", "status", "-C", "--rev", self.base_rev, relpath])
+    out = out.splitlines()
+    # HACK: strip error message about missing file/directory if it isn't in
+    # the working copy
+    if out[0].startswith('%s: ' % relpath):
+      out = out[1:]
+    if len(out) > 1:
+      # Moved/copied => considered as modified, use old filename to
+      # retrieve base contents
+      oldrelpath = out[1].strip()
+      status = "M"
+    else:
+      status, _ = out[0].split(' ', 1)
+    if status != "A":
+      base_content = RunShell(["hg", "cat", "-r", self.base_rev, oldrelpath],
+        silent_ok=True)
+      is_binary = "\0" in base_content  # Mercurial's heuristic
+    if status != "R":
+      new_content = open(relpath, "rb").read()
+      is_binary = is_binary or "\0" in new_content
+    if is_binary and base_content:
+      # Fetch again without converting newlines
+      base_content = RunShell(["hg", "cat", "-r", self.base_rev, oldrelpath],
+        silent_ok=True, universal_newlines=False)
+    if not is_binary or not self.IsImage(relpath):
+      new_content = None
+    return base_content, new_content, is_binary, status
+
+
+# NOTE: The SplitPatch function is duplicated in engine.py, keep them in sync.
+def SplitPatch(data):
+  """Splits a patch into separate pieces for each file.
+
+  Args:
+    data: A string containing the output of svn diff.
+
+  Returns:
+    A list of 2-tuple (filename, text) where text is the svn diff output
+      pertaining to filename.
+  """
+  patches = []
+  filename = None
+  diff = []
+  for line in data.splitlines(True):
+    new_filename = None
+    if line.startswith('Index:'):
+      unused, new_filename = line.split(':', 1)
+      new_filename = new_filename.strip()
+    elif line.startswith('Property changes on:'):
+      unused, temp_filename = line.split(':', 1)
+      # When a file is modified, paths use '/' between directories, however
+      # when a property is modified '\' is used on Windows.  Make them the same
+      # otherwise the file shows up twice.
+      temp_filename = temp_filename.strip().replace('\\', '/')
+      if temp_filename != filename:
+        # File has property changes but no modifications, create a new diff.
+        new_filename = temp_filename
+    if new_filename:
+      if filename and diff:
+        patches.append((filename, ''.join(diff)))
+      filename = new_filename
+      diff = [line]
+      continue
+    if diff is not None:
+      diff.append(line)
+  if filename and diff:
+    patches.append((filename, ''.join(diff)))
+  return patches
+
+
+def UploadSeparatePatches(issue, rpc_server, patchset, data, options):
+  """Uploads a separate patch for each file in the diff output.
+
+  Returns a list of [patch_key, filename] for each file.
+  """
+  patches = SplitPatch(data)
+  rv = []
+  for patch in patches:
+    if len(patch[1]) > MAX_UPLOAD_SIZE:
+      print ("Not uploading the patch for " + patch[0] +
+             " because the file is too large.")
+      continue
+    form_fields = [("filename", patch[0])]
+    if not options.download_base:
+      form_fields.append(("content_upload", "1"))
+    files = [("data", "data.diff", patch[1])]
+    ctype, body = EncodeMultipartFormData(form_fields, files)
+    url = "/%d/upload_patch/%d" % (int(issue), int(patchset))
+    print "Uploading patch for " + patch[0]
+    response_body = rpc_server.Send(url, body, content_type=ctype)
+    lines = response_body.splitlines()
+    if not lines or lines[0] != "OK":
+      StatusUpdate("  --> %s" % response_body)
+      sys.exit(1)
+    rv.append([lines[1], patch[0]])
+  return rv
+
+
+def GuessVCS(options):
+  """Helper to guess the version control system.
+
+  This examines the current directory, guesses which VersionControlSystem
+  we're using, and returns an instance of the appropriate class.  Exit with an
+  error if we can't figure it out.
+
+  Returns:
+    A VersionControlSystem instance. Exits if the VCS can't be guessed.
+  """
+  # Mercurial has a command to get the base directory of a repository
+  # Try running it, but don't die if we don't have hg installed.
+  # NOTE: we try Mercurial first as it can sit on top of an SVN working copy.
+  try:
+    out, returncode = RunShellWithReturnCode(["hg", "root"])
+    if returncode == 0:
+      return MercurialVCS(options, out.strip())
+  except OSError, (errno, message):
+    if errno != 2:  # ENOENT -- they don't have hg installed.
+      raise
+
+  # Subversion has a .svn in all working directories.
+  if os.path.isdir('.svn'):
+    logging.info("Guessed VCS = Subversion")
+    return SubversionVCS(options)
+
+  # Git has a command to test if you're in a git tree.
+  # Try running it, but don't die if we don't have git installed.
+  try:
+    out, returncode = RunShellWithReturnCode(["git", "rev-parse",
+                                              "--is-inside-work-tree"])
+    if returncode == 0:
+      return GitVCS(options)
+  except OSError, (errno, message):
+    if errno != 2:  # ENOENT -- they don't have git installed.
+      raise
+
+  ErrorExit(("Could not guess version control system. "
+             "Are you in a working copy directory?"))
+
+
+def RealMain(argv, data=None):
+  """The real main function.
+
+  Args:
+    argv: Command line arguments.
+    data: Diff contents. If None (default) the diff is generated by
+      the VersionControlSystem implementation returned by GuessVCS().
+
+  Returns:
+    A 2-tuple (issue id, patchset id).
+    The patchset id is None if the base files are not uploaded by this
+    script (applies only to SVN checkouts).
+  """
+  logging.basicConfig(format=("%(asctime).19s %(levelname)s %(filename)s:"
+                              "%(lineno)s %(message)s "))
+  os.environ['LC_ALL'] = 'C'
+  options, args = parser.parse_args(argv[1:])
+  global verbosity
+  verbosity = options.verbose
+  if verbosity >= 3:
+    logging.getLogger().setLevel(logging.DEBUG)
+  elif verbosity >= 2:
+    logging.getLogger().setLevel(logging.INFO)
+  vcs = GuessVCS(options)
+  if isinstance(vcs, SubversionVCS):
+    # base field is only allowed for Subversion.
+    # Note: Fetching base files may become deprecated in future releases.
+    base = vcs.GuessBase(options.download_base)
+  else:
+    base = None
+  if not base and options.download_base:
+    options.download_base = True
+    logging.info("Enabled upload of base file")
+  if not options.assume_yes:
+    vcs.CheckForUnknownFiles()
+  if data is None:
+    data = vcs.GenerateDiff(args)
+  files = vcs.GetBaseFiles(data)
+  if verbosity >= 1:
+    print "Upload server:", options.server, "(change with -s/--server)"
+  if options.issue:
+    prompt = "Message describing this patch set: "
+  else:
+    prompt = "New issue subject: "
+  message = options.message or raw_input(prompt).strip()
+  if not message:
+    ErrorExit("A non-empty message is required")
+  rpc_server = GetRpcServer(options)
+  form_fields = [("subject", message)]
+  if base:
+    form_fields.append(("base", base))
+  if options.issue:
+    form_fields.append(("issue", str(options.issue)))
+  if options.email:
+    form_fields.append(("user", options.email))
+  if options.reviewers:
+    for reviewer in options.reviewers.split(','):
+      if "@" in reviewer and not reviewer.split("@")[1].count(".") == 1:
+        ErrorExit("Invalid email address: %s" % reviewer)
+    form_fields.append(("reviewers", options.reviewers))
+  if options.cc:
+    for cc in options.cc.split(','):
+      if "@" in cc and not cc.split("@")[1].count(".") == 1:
+        ErrorExit("Invalid email address: %s" % cc)
+    form_fields.append(("cc", options.cc))
+  description = options.description
+  if options.description_file:
+    if options.description:
+      ErrorExit("Can't specify description and description_file")
+    file = open(options.description_file, 'r')
+    description = file.read()
+    file.close()
+  if description:
+    form_fields.append(("description", description))
+  # Send a hash of all the base file so the server can determine if a copy
+  # already exists in an earlier patchset.
+  base_hashes = ""
+  for file, info in files.iteritems():
+    if not info[0] is None:
+      checksum = md5.new(info[0]).hexdigest()
+      if base_hashes:
+        base_hashes += "|"
+      base_hashes += checksum + ":" + file
+  form_fields.append(("base_hashes", base_hashes))
+  # If we're uploading base files, don't send the email before the uploads, so
+  # that it contains the file status.
+  if options.send_mail and options.download_base:
+    form_fields.append(("send_mail", "1"))
+  if not options.download_base:
+    form_fields.append(("content_upload", "1"))
+  if len(data) > MAX_UPLOAD_SIZE:
+    print "Patch is large, so uploading file patches separately."
+    uploaded_diff_file = []
+    form_fields.append(("separate_patches", "1"))
+  else:
+    uploaded_diff_file = [("data", "data.diff", data)]
+  ctype, body = EncodeMultipartFormData(form_fields, uploaded_diff_file)
+  response_body = rpc_server.Send("/upload", body, content_type=ctype)
+  patchset = None
+  if not options.download_base or not uploaded_diff_file:
+    lines = response_body.splitlines()
+    if len(lines) >= 2:
+      msg = lines[0]
+      patchset = lines[1].strip()
+      patches = [x.split(" ", 1) for x in lines[2:]]
+    else:
+      msg = response_body
+  else:
+    msg = response_body
+  StatusUpdate(msg)
+  if not response_body.startswith("Issue created.") and \
+  not response_body.startswith("Issue updated."):
+    sys.exit(0)
+  issue = msg[msg.rfind("/")+1:]
+
+  if not uploaded_diff_file:
+    result = UploadSeparatePatches(issue, rpc_server, patchset, data, options)
+    if not options.download_base:
+      patches = result
+
+  if not options.download_base:
+    vcs.UploadBaseFiles(issue, rpc_server, patches, patchset, options, files)
+    if options.send_mail:
+      rpc_server.Send("/" + issue + "/mail", payload="")
+  return issue, patchset
+
+
+def main():
+  try:
+    RealMain(sys.argv)
+  except KeyboardInterrupt:
+    print
+    StatusUpdate("Interrupted.")
+    sys.exit(1)
+
+
+if __name__ == "__main__":
+  main()
diff --git a/third_party/googletest/src/scripts/upload_gtest.py b/third_party/googletest/src/scripts/upload_gtest.py
new file mode 100755 (executable)
index 0000000..be19ae8
--- /dev/null
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, 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.
+
+"""upload_gtest.py v0.1.0 -- uploads a Google Test patch for review.
+
+This simple wrapper passes all command line flags and
+--cc=googletestframework@googlegroups.com to upload.py.
+
+USAGE: upload_gtest.py [options for upload.py]
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import sys
+
+CC_FLAG = '--cc='
+GTEST_GROUP = 'googletestframework@googlegroups.com'
+
+
+def main():
+  # Finds the path to upload.py, assuming it is in the same directory
+  # as this file.
+  my_dir = os.path.dirname(os.path.abspath(__file__))
+  upload_py_path = os.path.join(my_dir, 'upload.py')
+
+  # Adds Google Test discussion group to the cc line if it's not there
+  # already.
+  upload_py_argv = [upload_py_path]
+  found_cc_flag = False
+  for arg in sys.argv[1:]:
+    if arg.startswith(CC_FLAG):
+      found_cc_flag = True
+      cc_line = arg[len(CC_FLAG):]
+      cc_list = [addr for addr in cc_line.split(',') if addr]
+      if GTEST_GROUP not in cc_list:
+        cc_list.append(GTEST_GROUP)
+      upload_py_argv.append(CC_FLAG + ','.join(cc_list))
+    else:
+      upload_py_argv.append(arg)
+
+  if not found_cc_flag:
+    upload_py_argv.append(CC_FLAG + GTEST_GROUP)
+
+  # Invokes upload.py with the modified command line flags.
+  os.execv(upload_py_path, upload_py_argv)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/third_party/googletest/src/src/gtest-all.cc b/third_party/googletest/src/src/gtest-all.cc
new file mode 100644 (file)
index 0000000..0a9cee5
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2008, 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: mheule@google.com (Markus Heule)
+//
+// Google C++ Testing Framework (Google Test)
+//
+// Sometimes it's desirable to build Google Test by compiling a single file.
+// This file serves this purpose.
+
+// This line ensures that gtest.h can be compiled on its own, even
+// when it's fused.
+#include "gtest/gtest.h"
+
+// The following lines pull in the real gtest *.cc files.
+#include "src/gtest.cc"
+#include "src/gtest-death-test.cc"
+#include "src/gtest-filepath.cc"
+#include "src/gtest-port.cc"
+#include "src/gtest-printers.cc"
+#include "src/gtest-test-part.cc"
+#include "src/gtest-typed-test.cc"
diff --git a/third_party/googletest/src/src/gtest-death-test.cc b/third_party/googletest/src/src/gtest-death-test.cc
new file mode 100644 (file)
index 0000000..8b2e413
--- /dev/null
@@ -0,0 +1,1234 @@
+// Copyright 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: wan@google.com (Zhanyong Wan), vladl@google.com (Vlad Losev)
+//
+// This file implements death tests.
+
+#include "gtest/gtest-death-test.h"
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_HAS_DEATH_TEST
+
+# if GTEST_OS_MAC
+#  include <crt_externs.h>
+# endif  // GTEST_OS_MAC
+
+# include <errno.h>
+# include <fcntl.h>
+# include <limits.h>
+# include <stdarg.h>
+
+# if GTEST_OS_WINDOWS
+#  include <windows.h>
+# else
+#  include <sys/mman.h>
+#  include <sys/wait.h>
+# endif  // GTEST_OS_WINDOWS
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-string.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+
+// Constants.
+
+// The default death test style.
+static const char kDefaultDeathTestStyle[] = "fast";
+
+GTEST_DEFINE_string_(
+    death_test_style,
+    internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle),
+    "Indicates how to run a death test in a forked child process: "
+    "\"threadsafe\" (child process re-executes the test binary "
+    "from the beginning, running only the specific death test) or "
+    "\"fast\" (child process runs the death test immediately "
+    "after forking).");
+
+GTEST_DEFINE_bool_(
+    death_test_use_fork,
+    internal::BoolFromGTestEnv("death_test_use_fork", false),
+    "Instructs to use fork()/_exit() instead of clone() in death tests. "
+    "Ignored and always uses fork() on POSIX systems where clone() is not "
+    "implemented. Useful when running under valgrind or similar tools if "
+    "those do not support clone(). Valgrind 3.3.1 will just fail if "
+    "it sees an unsupported combination of clone() flags. "
+    "It is not recommended to use this flag w/o valgrind though it will "
+    "work in 99% of the cases. Once valgrind is fixed, this flag will "
+    "most likely be removed.");
+
+namespace internal {
+GTEST_DEFINE_string_(
+    internal_run_death_test, "",
+    "Indicates the file, line number, temporal index of "
+    "the single death test to run, and a file descriptor to "
+    "which a success code may be sent, all separated by "
+    "colons.  This flag is specified if and only if the current "
+    "process is a sub-process launched for running a thread-safe "
+    "death test.  FOR INTERNAL USE ONLY.");
+}  // namespace internal
+
+#if GTEST_HAS_DEATH_TEST
+
+// ExitedWithCode constructor.
+ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {
+}
+
+// ExitedWithCode function-call operator.
+bool ExitedWithCode::operator()(int exit_status) const {
+# if GTEST_OS_WINDOWS
+
+  return exit_status == exit_code_;
+
+# else
+
+  return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
+
+# endif  // GTEST_OS_WINDOWS
+}
+
+# if !GTEST_OS_WINDOWS
+// KilledBySignal constructor.
+KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
+}
+
+// KilledBySignal function-call operator.
+bool KilledBySignal::operator()(int exit_status) const {
+  return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
+}
+# endif  // !GTEST_OS_WINDOWS
+
+namespace internal {
+
+// Utilities needed for death tests.
+
+// Generates a textual description of a given exit code, in the format
+// specified by wait(2).
+static String ExitSummary(int exit_code) {
+  Message m;
+
+# if GTEST_OS_WINDOWS
+
+  m << "Exited with exit status " << exit_code;
+
+# else
+
+  if (WIFEXITED(exit_code)) {
+    m << "Exited with exit status " << WEXITSTATUS(exit_code);
+  } else if (WIFSIGNALED(exit_code)) {
+    m << "Terminated by signal " << WTERMSIG(exit_code);
+  }
+#  ifdef WCOREDUMP
+  if (WCOREDUMP(exit_code)) {
+    m << " (core dumped)";
+  }
+#  endif
+# endif  // GTEST_OS_WINDOWS
+
+  return m.GetString();
+}
+
+// Returns true if exit_status describes a process that was terminated
+// by a signal, or exited normally with a nonzero exit code.
+bool ExitedUnsuccessfully(int exit_status) {
+  return !ExitedWithCode(0)(exit_status);
+}
+
+# if !GTEST_OS_WINDOWS
+// Generates a textual failure message when a death test finds more than
+// one thread running, or cannot determine the number of threads, prior
+// to executing the given statement.  It is the responsibility of the
+// caller not to pass a thread_count of 1.
+static String DeathTestThreadWarning(size_t thread_count) {
+  Message msg;
+  msg << "Death tests use fork(), which is unsafe particularly"
+      << " in a threaded context. For this test, " << GTEST_NAME_ << " ";
+  if (thread_count == 0)
+    msg << "couldn't detect the number of threads.";
+  else
+    msg << "detected " << thread_count << " threads.";
+  return msg.GetString();
+}
+# endif  // !GTEST_OS_WINDOWS
+
+// Flag characters for reporting a death test that did not die.
+static const char kDeathTestLived = 'L';
+static const char kDeathTestReturned = 'R';
+static const char kDeathTestThrew = 'T';
+static const char kDeathTestInternalError = 'I';
+
+// An enumeration describing all of the possible ways that a death test can
+// conclude.  DIED means that the process died while executing the test
+// code; LIVED means that process lived beyond the end of the test code;
+// RETURNED means that the test statement attempted to execute a return
+// statement, which is not allowed; THREW means that the test statement
+// returned control by throwing an exception.  IN_PROGRESS means the test
+// has not yet concluded.
+// TODO(vladl@google.com): Unify names and possibly values for
+// AbortReason, DeathTestOutcome, and flag characters above.
+enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
+
+// Routine for aborting the program which is safe to call from an
+// exec-style death test child process, in which case the error
+// message is propagated back to the parent process.  Otherwise, the
+// message is simply printed to stderr.  In either case, the program
+// then exits with status 1.
+void DeathTestAbort(const String& message) {
+  // On a POSIX system, this function may be called from a threadsafe-style
+  // death test child process, which operates on a very small stack.  Use
+  // the heap for any additional non-minuscule memory requirements.
+  const InternalRunDeathTestFlag* const flag =
+      GetUnitTestImpl()->internal_run_death_test_flag();
+  if (flag != NULL) {
+    FILE* parent = posix::FDOpen(flag->write_fd(), "w");
+    fputc(kDeathTestInternalError, parent);
+    fprintf(parent, "%s", message.c_str());
+    fflush(parent);
+    _exit(1);
+  } else {
+    fprintf(stderr, "%s", message.c_str());
+    fflush(stderr);
+    posix::Abort();
+  }
+}
+
+// A replacement for CHECK that calls DeathTestAbort if the assertion
+// fails.
+# define GTEST_DEATH_TEST_CHECK_(expression) \
+  do { \
+    if (!::testing::internal::IsTrue(expression)) { \
+      DeathTestAbort(::testing::internal::String::Format( \
+          "CHECK failed: File %s, line %d: %s", \
+          __FILE__, __LINE__, #expression)); \
+    } \
+  } while (::testing::internal::AlwaysFalse())
+
+// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for
+// evaluating any system call that fulfills two conditions: it must return
+// -1 on failure, and set errno to EINTR when it is interrupted and
+// should be tried again.  The macro expands to a loop that repeatedly
+// evaluates the expression as long as it evaluates to -1 and sets
+// errno to EINTR.  If the expression evaluates to -1 but errno is
+// something other than EINTR, DeathTestAbort is called.
+# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
+  do { \
+    int gtest_retval; \
+    do { \
+      gtest_retval = (expression); \
+    } while (gtest_retval == -1 && errno == EINTR); \
+    if (gtest_retval == -1) { \
+      DeathTestAbort(::testing::internal::String::Format( \
+          "CHECK failed: File %s, line %d: %s != -1", \
+          __FILE__, __LINE__, #expression)); \
+    } \
+  } while (::testing::internal::AlwaysFalse())
+
+// Returns the message describing the last system error in errno.
+String GetLastErrnoDescription() {
+    return String(errno == 0 ? "" : posix::StrError(errno));
+}
+
+// This is called from a death test parent process to read a failure
+// message from the death test child process and log it with the FATAL
+// severity. On Windows, the message is read from a pipe handle. On other
+// platforms, it is read from a file descriptor.
+static void FailFromInternalError(int fd) {
+  Message error;
+  char buffer[256];
+  int num_read;
+
+  do {
+    while ((num_read = posix::Read(fd, buffer, 255)) > 0) {
+      buffer[num_read] = '\0';
+      error << buffer;
+    }
+  } while (num_read == -1 && errno == EINTR);
+
+  if (num_read == 0) {
+    GTEST_LOG_(FATAL) << error.GetString();
+  } else {
+    const int last_error = errno;
+    GTEST_LOG_(FATAL) << "Error while reading death test internal: "
+                      << GetLastErrnoDescription() << " [" << last_error << "]";
+  }
+}
+
+// Death test constructor.  Increments the running death test count
+// for the current test.
+DeathTest::DeathTest() {
+  TestInfo* const info = GetUnitTestImpl()->current_test_info();
+  if (info == NULL) {
+    DeathTestAbort("Cannot run a death test outside of a TEST or "
+                   "TEST_F construct");
+  }
+}
+
+// Creates and returns a death test by dispatching to the current
+// death test factory.
+bool DeathTest::Create(const char* statement, const RE* regex,
+                       const char* file, int line, DeathTest** test) {
+  return GetUnitTestImpl()->death_test_factory()->Create(
+      statement, regex, file, line, test);
+}
+
+const char* DeathTest::LastMessage() {
+  return last_death_test_message_.c_str();
+}
+
+void DeathTest::set_last_death_test_message(const String& message) {
+  last_death_test_message_ = message;
+}
+
+String DeathTest::last_death_test_message_;
+
+// Provides cross platform implementation for some death functionality.
+class DeathTestImpl : public DeathTest {
+ protected:
+  DeathTestImpl(const char* a_statement, const RE* a_regex)
+      : statement_(a_statement),
+        regex_(a_regex),
+        spawned_(false),
+        status_(-1),
+        outcome_(IN_PROGRESS),
+        read_fd_(-1),
+        write_fd_(-1) {}
+
+  // read_fd_ is expected to be closed and cleared by a derived class.
+  ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); }
+
+  void Abort(AbortReason reason);
+  virtual bool Passed(bool status_ok);
+
+  const char* statement() const { return statement_; }
+  const RE* regex() const { return regex_; }
+  bool spawned() const { return spawned_; }
+  void set_spawned(bool is_spawned) { spawned_ = is_spawned; }
+  int status() const { return status_; }
+  void set_status(int a_status) { status_ = a_status; }
+  DeathTestOutcome outcome() const { return outcome_; }
+  void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; }
+  int read_fd() const { return read_fd_; }
+  void set_read_fd(int fd) { read_fd_ = fd; }
+  int write_fd() const { return write_fd_; }
+  void set_write_fd(int fd) { write_fd_ = fd; }
+
+  // Called in the parent process only. Reads the result code of the death
+  // test child process via a pipe, interprets it to set the outcome_
+  // member, and closes read_fd_.  Outputs diagnostics and terminates in
+  // case of unexpected codes.
+  void ReadAndInterpretStatusByte();
+
+ private:
+  // The textual content of the code this object is testing.  This class
+  // doesn't own this string and should not attempt to delete it.
+  const char* const statement_;
+  // The regular expression which test output must match.  DeathTestImpl
+  // doesn't own this object and should not attempt to delete it.
+  const RE* const regex_;
+  // True if the death test child process has been successfully spawned.
+  bool spawned_;
+  // The exit status of the child process.
+  int status_;
+  // How the death test concluded.
+  DeathTestOutcome outcome_;
+  // Descriptor to the read end of the pipe to the child process.  It is
+  // always -1 in the child process.  The child keeps its write end of the
+  // pipe in write_fd_.
+  int read_fd_;
+  // Descriptor to the child's write end of the pipe to the parent process.
+  // It is always -1 in the parent process.  The parent keeps its end of the
+  // pipe in read_fd_.
+  int write_fd_;
+};
+
+// Called in the parent process only. Reads the result code of the death
+// test child process via a pipe, interprets it to set the outcome_
+// member, and closes read_fd_.  Outputs diagnostics and terminates in
+// case of unexpected codes.
+void DeathTestImpl::ReadAndInterpretStatusByte() {
+  char flag;
+  int bytes_read;
+
+  // The read() here blocks until data is available (signifying the
+  // failure of the death test) or until the pipe is closed (signifying
+  // its success), so it's okay to call this in the parent before
+  // the child process has exited.
+  do {
+    bytes_read = posix::Read(read_fd(), &flag, 1);
+  } while (bytes_read == -1 && errno == EINTR);
+
+  if (bytes_read == 0) {
+    set_outcome(DIED);
+  } else if (bytes_read == 1) {
+    switch (flag) {
+      case kDeathTestReturned:
+        set_outcome(RETURNED);
+        break;
+      case kDeathTestThrew:
+        set_outcome(THREW);
+        break;
+      case kDeathTestLived:
+        set_outcome(LIVED);
+        break;
+      case kDeathTestInternalError:
+        FailFromInternalError(read_fd());  // Does not return.
+        break;
+      default:
+        GTEST_LOG_(FATAL) << "Death test child process reported "
+                          << "unexpected status byte ("
+                          << static_cast<unsigned int>(flag) << ")";
+    }
+  } else {
+    GTEST_LOG_(FATAL) << "Read from death test child process failed: "
+                      << GetLastErrnoDescription();
+  }
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd()));
+  set_read_fd(-1);
+}
+
+// Signals that the death test code which should have exited, didn't.
+// Should be called only in a death test child process.
+// Writes a status byte to the child's status file descriptor, then
+// calls _exit(1).
+void DeathTestImpl::Abort(AbortReason reason) {
+  // The parent process considers the death test to be a failure if
+  // it finds any data in our pipe.  So, here we write a single flag byte
+  // to the pipe, then exit.
+  const char status_ch =
+      reason == TEST_DID_NOT_DIE ? kDeathTestLived :
+      reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned;
+
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
+  // We are leaking the descriptor here because on some platforms (i.e.,
+  // when built as Windows DLL), destructors of global objects will still
+  // run after calling _exit(). On such systems, write_fd_ will be
+  // indirectly closed from the destructor of UnitTestImpl, causing double
+  // close if it is also closed here. On debug configurations, double close
+  // may assert. As there are no in-process buffers to flush here, we are
+  // relying on the OS to close the descriptor after the process terminates
+  // when the destructors are not run.
+  _exit(1);  // Exits w/o any normal exit hooks (we were supposed to crash)
+}
+
+// Returns an indented copy of stderr output for a death test.
+// This makes distinguishing death test output lines from regular log lines
+// much easier.
+static ::std::string FormatDeathTestOutput(const ::std::string& output) {
+  ::std::string ret;
+  for (size_t at = 0; ; ) {
+    const size_t line_end = output.find('\n', at);
+    ret += "[  DEATH   ] ";
+    if (line_end == ::std::string::npos) {
+      ret += output.substr(at);
+      break;
+    }
+    ret += output.substr(at, line_end + 1 - at);
+    at = line_end + 1;
+  }
+  return ret;
+}
+
+// Assesses the success or failure of a death test, using both private
+// members which have previously been set, and one argument:
+//
+// Private data members:
+//   outcome:  An enumeration describing how the death test
+//             concluded: DIED, LIVED, THREW, or RETURNED.  The death test
+//             fails in the latter three cases.
+//   status:   The exit status of the child process. On *nix, it is in the
+//             in the format specified by wait(2). On Windows, this is the
+//             value supplied to the ExitProcess() API or a numeric code
+//             of the exception that terminated the program.
+//   regex:    A regular expression object to be applied to
+//             the test's captured standard error output; the death test
+//             fails if it does not match.
+//
+// Argument:
+//   status_ok: true if exit_status is acceptable in the context of
+//              this particular death test, which fails if it is false
+//
+// Returns true iff all of the above conditions are met.  Otherwise, the
+// first failing condition, in the order given above, is the one that is
+// reported. Also sets the last death test message string.
+bool DeathTestImpl::Passed(bool status_ok) {
+  if (!spawned())
+    return false;
+
+  const String error_message = GetCapturedStderr();
+
+  bool success = false;
+  Message buffer;
+
+  buffer << "Death test: " << statement() << "\n";
+  switch (outcome()) {
+    case LIVED:
+      buffer << "    Result: failed to die.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case THREW:
+      buffer << "    Result: threw an exception.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case RETURNED:
+      buffer << "    Result: illegal return in test statement.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case DIED:
+      if (status_ok) {
+        const bool matched = RE::PartialMatch(error_message.c_str(), *regex());
+        if (matched) {
+          success = true;
+        } else {
+          buffer << "    Result: died but not with expected error.\n"
+                 << "  Expected: " << regex()->pattern() << "\n"
+                 << "Actual msg:\n" << FormatDeathTestOutput(error_message);
+        }
+      } else {
+        buffer << "    Result: died but not with expected exit code:\n"
+               << "            " << ExitSummary(status()) << "\n"
+               << "Actual msg:\n" << FormatDeathTestOutput(error_message);
+      }
+      break;
+    case IN_PROGRESS:
+    default:
+      GTEST_LOG_(FATAL)
+          << "DeathTest::Passed somehow called before conclusion of test";
+  }
+
+  DeathTest::set_last_death_test_message(buffer.GetString());
+  return success;
+}
+
+# if GTEST_OS_WINDOWS
+// WindowsDeathTest implements death tests on Windows. Due to the
+// specifics of starting new processes on Windows, death tests there are
+// always threadsafe, and Google Test considers the
+// --gtest_death_test_style=fast setting to be equivalent to
+// --gtest_death_test_style=threadsafe there.
+//
+// A few implementation notes:  Like the Linux version, the Windows
+// implementation uses pipes for child-to-parent communication. But due to
+// the specifics of pipes on Windows, some extra steps are required:
+//
+// 1. The parent creates a communication pipe and stores handles to both
+//    ends of it.
+// 2. The parent starts the child and provides it with the information
+//    necessary to acquire the handle to the write end of the pipe.
+// 3. The child acquires the write end of the pipe and signals the parent
+//    using a Windows event.
+// 4. Now the parent can release the write end of the pipe on its side. If
+//    this is done before step 3, the object's reference count goes down to
+//    0 and it is destroyed, preventing the child from acquiring it. The
+//    parent now has to release it, or read operations on the read end of
+//    the pipe will not return when the child terminates.
+// 5. The parent reads child's output through the pipe (outcome code and
+//    any possible error messages) from the pipe, and its stderr and then
+//    determines whether to fail the test.
+//
+// Note: to distinguish Win32 API calls from the local method and function
+// calls, the former are explicitly resolved in the global namespace.
+//
+class WindowsDeathTest : public DeathTestImpl {
+ public:
+  WindowsDeathTest(const char* a_statement,
+                   const RE* a_regex,
+                   const char* file,
+                   int line)
+      : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {}
+
+  // All of these virtual functions are inherited from DeathTest.
+  virtual int Wait();
+  virtual TestRole AssumeRole();
+
+ private:
+  // The name of the file in which the death test is located.
+  const char* const file_;
+  // The line number on which the death test is located.
+  const int line_;
+  // Handle to the write end of the pipe to the child process.
+  AutoHandle write_handle_;
+  // Child process handle.
+  AutoHandle child_handle_;
+  // Event the child process uses to signal the parent that it has
+  // acquired the handle to the write end of the pipe. After seeing this
+  // event the parent can release its own handles to make sure its
+  // ReadFile() calls return when the child terminates.
+  AutoHandle event_handle_;
+};
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists.  As a side effect, sets the
+// outcome data member.
+int WindowsDeathTest::Wait() {
+  if (!spawned())
+    return 0;
+
+  // Wait until the child either signals that it has acquired the write end
+  // of the pipe or it dies.
+  const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() };
+  switch (::WaitForMultipleObjects(2,
+                                   wait_handles,
+                                   FALSE,  // Waits for any of the handles.
+                                   INFINITE)) {
+    case WAIT_OBJECT_0:
+    case WAIT_OBJECT_0 + 1:
+      break;
+    default:
+      GTEST_DEATH_TEST_CHECK_(false);  // Should not get here.
+  }
+
+  // The child has acquired the write end of the pipe or exited.
+  // We release the handle on our side and continue.
+  write_handle_.Reset();
+  event_handle_.Reset();
+
+  ReadAndInterpretStatusByte();
+
+  // Waits for the child process to exit if it haven't already. This
+  // returns immediately if the child has already exited, regardless of
+  // whether previous calls to WaitForMultipleObjects synchronized on this
+  // handle or not.
+  GTEST_DEATH_TEST_CHECK_(
+      WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(),
+                                             INFINITE));
+  DWORD status_code;
+  GTEST_DEATH_TEST_CHECK_(
+      ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE);
+  child_handle_.Reset();
+  set_status(static_cast<int>(status_code));
+  return status();
+}
+
+// The AssumeRole process for a Windows death test.  It creates a child
+// process with the same executable as the current process to run the
+// death test.  The child process is given the --gtest_filter and
+// --gtest_internal_run_death_test flags such that it knows to run the
+// current death test only.
+DeathTest::TestRole WindowsDeathTest::AssumeRole() {
+  const UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const TestInfo* const info = impl->current_test_info();
+  const int death_test_index = info->result()->death_test_count();
+
+  if (flag != NULL) {
+    // ParseInternalRunDeathTestFlag() has performed all the necessary
+    // processing.
+    set_write_fd(flag->write_fd());
+    return EXECUTE_TEST;
+  }
+
+  // WindowsDeathTest uses an anonymous pipe to communicate results of
+  // a death test.
+  SECURITY_ATTRIBUTES handles_are_inheritable = {
+    sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
+  HANDLE read_handle, write_handle;
+  GTEST_DEATH_TEST_CHECK_(
+      ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable,
+                   0)  // Default buffer size.
+      != FALSE);
+  set_read_fd(::_open_osfhandle(reinterpret_cast<intptr_t>(read_handle),
+                                O_RDONLY));
+  write_handle_.Reset(write_handle);
+  event_handle_.Reset(::CreateEvent(
+      &handles_are_inheritable,
+      TRUE,    // The event will automatically reset to non-signaled state.
+      FALSE,   // The initial state is non-signalled.
+      NULL));  // The even is unnamed.
+  GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL);
+  const String filter_flag = String::Format("--%s%s=%s.%s",
+                                            GTEST_FLAG_PREFIX_, kFilterFlag,
+                                            info->test_case_name(),
+                                            info->name());
+  const String internal_flag = String::Format(
+    "--%s%s=%s|%d|%d|%u|%Iu|%Iu",
+      GTEST_FLAG_PREFIX_,
+      kInternalRunDeathTestFlag,
+      file_, line_,
+      death_test_index,
+      static_cast<unsigned int>(::GetCurrentProcessId()),
+      // size_t has the same with as pointers on both 32-bit and 64-bit
+      // Windows platforms.
+      // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx.
+      reinterpret_cast<size_t>(write_handle),
+      reinterpret_cast<size_t>(event_handle_.Get()));
+
+  char executable_path[_MAX_PATH + 1];  // NOLINT
+  GTEST_DEATH_TEST_CHECK_(
+      _MAX_PATH + 1 != ::GetModuleFileNameA(NULL,
+                                            executable_path,
+                                            _MAX_PATH));
+
+  String command_line = String::Format("%s %s \"%s\"",
+                                       ::GetCommandLineA(),
+                                       filter_flag.c_str(),
+                                       internal_flag.c_str());
+
+  DeathTest::set_last_death_test_message("");
+
+  CaptureStderr();
+  // Flush the log buffers since the log streams are shared with the child.
+  FlushInfoLog();
+
+  // The child process will share the standard handles with the parent.
+  STARTUPINFOA startup_info;
+  memset(&startup_info, 0, sizeof(STARTUPINFO));
+  startup_info.dwFlags = STARTF_USESTDHANDLES;
+  startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE);
+  startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
+  startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
+
+  PROCESS_INFORMATION process_info;
+  GTEST_DEATH_TEST_CHECK_(::CreateProcessA(
+      executable_path,
+      const_cast<char*>(command_line.c_str()),
+      NULL,   // Retuned process handle is not inheritable.
+      NULL,   // Retuned thread handle is not inheritable.
+      TRUE,   // Child inherits all inheritable handles (for write_handle_).
+      0x0,    // Default creation flags.
+      NULL,   // Inherit the parent's environment.
+      UnitTest::GetInstance()->original_working_dir(),
+      &startup_info,
+      &process_info) != FALSE);
+  child_handle_.Reset(process_info.hProcess);
+  ::CloseHandle(process_info.hThread);
+  set_spawned(true);
+  return OVERSEE_TEST;
+}
+# else  // We are not on Windows.
+
+// ForkingDeathTest provides implementations for most of the abstract
+// methods of the DeathTest interface.  Only the AssumeRole method is
+// left undefined.
+class ForkingDeathTest : public DeathTestImpl {
+ public:
+  ForkingDeathTest(const char* statement, const RE* regex);
+
+  // All of these virtual functions are inherited from DeathTest.
+  virtual int Wait();
+
+ protected:
+  void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; }
+
+ private:
+  // PID of child process during death test; 0 in the child process itself.
+  pid_t child_pid_;
+};
+
+// Constructs a ForkingDeathTest.
+ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex)
+    : DeathTestImpl(a_statement, a_regex),
+      child_pid_(-1) {}
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists.  As a side effect, sets the
+// outcome data member.
+int ForkingDeathTest::Wait() {
+  if (!spawned())
+    return 0;
+
+  ReadAndInterpretStatusByte();
+
+  int status_value;
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0));
+  set_status(status_value);
+  return status_value;
+}
+
+// A concrete death test class that forks, then immediately runs the test
+// in the child process.
+class NoExecDeathTest : public ForkingDeathTest {
+ public:
+  NoExecDeathTest(const char* a_statement, const RE* a_regex) :
+      ForkingDeathTest(a_statement, a_regex) { }
+  virtual TestRole AssumeRole();
+};
+
+// The AssumeRole process for a fork-and-run death test.  It implements a
+// straightforward fork, with a simple pipe to transmit the status byte.
+DeathTest::TestRole NoExecDeathTest::AssumeRole() {
+  const size_t thread_count = GetThreadCount();
+  if (thread_count != 1) {
+    GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count);
+  }
+
+  int pipe_fd[2];
+  GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
+
+  DeathTest::set_last_death_test_message("");
+  CaptureStderr();
+  // When we fork the process below, the log file buffers are copied, but the
+  // file descriptors are shared.  We flush all log files here so that closing
+  // the file descriptors in the child process doesn't throw off the
+  // synchronization between descriptors and buffers in the parent process.
+  // This is as close to the fork as possible to avoid a race condition in case
+  // there are multiple threads running before the death test, and another
+  // thread writes to the log file.
+  FlushInfoLog();
+
+  const pid_t child_pid = fork();
+  GTEST_DEATH_TEST_CHECK_(child_pid != -1);
+  set_child_pid(child_pid);
+  if (child_pid == 0) {
+    GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0]));
+    set_write_fd(pipe_fd[1]);
+    // Redirects all logging to stderr in the child process to prevent
+    // concurrent writes to the log files.  We capture stderr in the parent
+    // process and append the child process' output to a log.
+    LogToStderr();
+    // Event forwarding to the listeners of event listener API mush be shut
+    // down in death test subprocesses.
+    GetUnitTestImpl()->listeners()->SuppressEventForwarding();
+    return EXECUTE_TEST;
+  } else {
+    GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
+    set_read_fd(pipe_fd[0]);
+    set_spawned(true);
+    return OVERSEE_TEST;
+  }
+}
+
+// A concrete death test class that forks and re-executes the main
+// program from the beginning, with command-line flags set that cause
+// only this specific death test to be run.
+class ExecDeathTest : public ForkingDeathTest {
+ public:
+  ExecDeathTest(const char* a_statement, const RE* a_regex,
+                const char* file, int line) :
+      ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { }
+  virtual TestRole AssumeRole();
+ private:
+  // The name of the file in which the death test is located.
+  const char* const file_;
+  // The line number on which the death test is located.
+  const int line_;
+};
+
+// Utility class for accumulating command-line arguments.
+class Arguments {
+ public:
+  Arguments() {
+    args_.push_back(NULL);
+  }
+
+  ~Arguments() {
+    for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
+         ++i) {
+      free(*i);
+    }
+  }
+  void AddArgument(const char* argument) {
+    args_.insert(args_.end() - 1, posix::StrDup(argument));
+  }
+
+  template <typename Str>
+  void AddArguments(const ::std::vector<Str>& arguments) {
+    for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
+         i != arguments.end();
+         ++i) {
+      args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
+    }
+  }
+  char* const* Argv() {
+    return &args_[0];
+  }
+ private:
+  std::vector<char*> args_;
+};
+
+// A struct that encompasses the arguments to the child process of a
+// threadsafe-style death test process.
+struct ExecDeathTestArgs {
+  char* const* argv;  // Command-line arguments for the child's call to exec
+  int close_fd;       // File descriptor to close; the read end of a pipe
+};
+
+#  if GTEST_OS_MAC
+inline char** GetEnviron() {
+  // When Google Test is built as a framework on MacOS X, the environ variable
+  // is unavailable. Apple's documentation (man environ) recommends using
+  // _NSGetEnviron() instead.
+  return *_NSGetEnviron();
+}
+#  else
+// Some POSIX platforms expect you to declare environ. extern "C" makes
+// it reside in the global namespace.
+extern "C" char** environ;
+inline char** GetEnviron() { return environ; }
+#  endif  // GTEST_OS_MAC
+
+// The main function for a threadsafe-style death test child process.
+// This function is called in a clone()-ed process and thus must avoid
+// any potentially unsafe operations like malloc or libc functions.
+static int ExecDeathTestChildMain(void* child_arg) {
+  ExecDeathTestArgs* const args = static_cast<ExecDeathTestArgs*>(child_arg);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd));
+
+  // We need to execute the test program in the same environment where
+  // it was originally invoked.  Therefore we change to the original
+  // working directory first.
+  const char* const original_dir =
+      UnitTest::GetInstance()->original_working_dir();
+  // We can safely call chdir() as it's a direct system call.
+  if (chdir(original_dir) != 0) {
+    DeathTestAbort(String::Format("chdir(\"%s\") failed: %s",
+                                  original_dir,
+                                  GetLastErrnoDescription().c_str()));
+    return EXIT_FAILURE;
+  }
+
+  // We can safely call execve() as it's a direct system call.  We
+  // cannot use execvp() as it's a libc function and thus potentially
+  // unsafe.  Since execve() doesn't search the PATH, the user must
+  // invoke the test program via a valid path that contains at least
+  // one path separator.
+  execve(args->argv[0], args->argv, GetEnviron());
+  DeathTestAbort(String::Format("execve(%s, ...) in %s failed: %s",
+                                args->argv[0],
+                                original_dir,
+                                GetLastErrnoDescription().c_str()));
+  return EXIT_FAILURE;
+}
+
+// Two utility routines that together determine the direction the stack
+// grows.
+// This could be accomplished more elegantly by a single recursive
+// function, but we want to guard against the unlikely possibility of
+// a smart compiler optimizing the recursion away.
+//
+// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
+// StackLowerThanAddress into StackGrowsDown, which then doesn't give
+// correct answer.
+bool StackLowerThanAddress(const void* ptr) GTEST_NO_INLINE_;
+bool StackLowerThanAddress(const void* ptr) {
+  int dummy;
+  return &dummy < ptr;
+}
+
+bool StackGrowsDown() {
+  int dummy;
+  return StackLowerThanAddress(&dummy);
+}
+
+// A threadsafe implementation of fork(2) for threadsafe-style death tests
+// that uses clone(2).  It dies with an error message if anything goes
+// wrong.
+static pid_t ExecDeathTestFork(char* const* argv, int close_fd) {
+  ExecDeathTestArgs args = { argv, close_fd };
+  pid_t child_pid = -1;
+
+#  if GTEST_HAS_CLONE
+  const bool use_fork = GTEST_FLAG(death_test_use_fork);
+
+  if (!use_fork) {
+    static const bool stack_grows_down = StackGrowsDown();
+    const size_t stack_size = getpagesize();
+    // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead.
+    void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,
+                             MAP_ANON | MAP_PRIVATE, -1, 0);
+    GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED);
+    void* const stack_top =
+        static_cast<char*>(stack) + (stack_grows_down ? stack_size : 0);
+
+    child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args);
+
+    GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
+  }
+#  else
+  const bool use_fork = true;
+#  endif  // GTEST_HAS_CLONE
+
+  if (use_fork && (child_pid = fork()) == 0) {
+      ExecDeathTestChildMain(&args);
+      _exit(0);
+  }
+
+  GTEST_DEATH_TEST_CHECK_(child_pid != -1);
+  return child_pid;
+}
+
+// The AssumeRole process for a fork-and-exec death test.  It re-executes the
+// main program from the beginning, setting the --gtest_filter
+// and --gtest_internal_run_death_test flags to cause only the current
+// death test to be re-run.
+DeathTest::TestRole ExecDeathTest::AssumeRole() {
+  const UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const TestInfo* const info = impl->current_test_info();
+  const int death_test_index = info->result()->death_test_count();
+
+  if (flag != NULL) {
+    set_write_fd(flag->write_fd());
+    return EXECUTE_TEST;
+  }
+
+  int pipe_fd[2];
+  GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
+  // Clear the close-on-exec flag on the write end of the pipe, lest
+  // it be closed when the child process does an exec:
+  GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1);
+
+  const String filter_flag =
+      String::Format("--%s%s=%s.%s",
+                     GTEST_FLAG_PREFIX_, kFilterFlag,
+                     info->test_case_name(), info->name());
+  const String internal_flag =
+      String::Format("--%s%s=%s|%d|%d|%d",
+                     GTEST_FLAG_PREFIX_, kInternalRunDeathTestFlag,
+                     file_, line_, death_test_index, pipe_fd[1]);
+  Arguments args;
+  args.AddArguments(GetArgvs());
+  args.AddArgument(filter_flag.c_str());
+  args.AddArgument(internal_flag.c_str());
+
+  DeathTest::set_last_death_test_message("");
+
+  CaptureStderr();
+  // See the comment in NoExecDeathTest::AssumeRole for why the next line
+  // is necessary.
+  FlushInfoLog();
+
+  const pid_t child_pid = ExecDeathTestFork(args.Argv(), pipe_fd[0]);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
+  set_child_pid(child_pid);
+  set_read_fd(pipe_fd[0]);
+  set_spawned(true);
+  return OVERSEE_TEST;
+}
+
+# endif  // !GTEST_OS_WINDOWS
+
+// Creates a concrete DeathTest-derived class that depends on the
+// --gtest_death_test_style flag, and sets the pointer pointed to
+// by the "test" argument to its address.  If the test should be
+// skipped, sets that pointer to NULL.  Returns true, unless the
+// flag is set to an invalid value.
+bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
+                                     const char* file, int line,
+                                     DeathTest** test) {
+  UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const int death_test_index = impl->current_test_info()
+      ->increment_death_test_count();
+
+  if (flag != NULL) {
+    if (death_test_index > flag->index()) {
+      DeathTest::set_last_death_test_message(String::Format(
+          "Death test count (%d) somehow exceeded expected maximum (%d)",
+          death_test_index, flag->index()));
+      return false;
+    }
+
+    if (!(flag->file() == file && flag->line() == line &&
+          flag->index() == death_test_index)) {
+      *test = NULL;
+      return true;
+    }
+  }
+
+# if GTEST_OS_WINDOWS
+
+  if (GTEST_FLAG(death_test_style) == "threadsafe" ||
+      GTEST_FLAG(death_test_style) == "fast") {
+    *test = new WindowsDeathTest(statement, regex, file, line);
+  }
+
+# else
+
+  if (GTEST_FLAG(death_test_style) == "threadsafe") {
+    *test = new ExecDeathTest(statement, regex, file, line);
+  } else if (GTEST_FLAG(death_test_style) == "fast") {
+    *test = new NoExecDeathTest(statement, regex);
+  }
+
+# endif  // GTEST_OS_WINDOWS
+
+  else {  // NOLINT - this is more readable than unbalanced brackets inside #if.
+    DeathTest::set_last_death_test_message(String::Format(
+        "Unknown death test style \"%s\" encountered",
+        GTEST_FLAG(death_test_style).c_str()));
+    return false;
+  }
+
+  return true;
+}
+
+// Splits a given string on a given delimiter, populating a given
+// vector with the fields.  GTEST_HAS_DEATH_TEST implies that we have
+// ::std::string, so we can use it here.
+static void SplitString(const ::std::string& str, char delimiter,
+                        ::std::vector< ::std::string>* dest) {
+  ::std::vector< ::std::string> parsed;
+  ::std::string::size_type pos = 0;
+  while (::testing::internal::AlwaysTrue()) {
+    const ::std::string::size_type colon = str.find(delimiter, pos);
+    if (colon == ::std::string::npos) {
+      parsed.push_back(str.substr(pos));
+      break;
+    } else {
+      parsed.push_back(str.substr(pos, colon - pos));
+      pos = colon + 1;
+    }
+  }
+  dest->swap(parsed);
+}
+
+# if GTEST_OS_WINDOWS
+// Recreates the pipe and event handles from the provided parameters,
+// signals the event, and returns a file descriptor wrapped around the pipe
+// handle. This function is called in the child process only.
+int GetStatusFileDescriptor(unsigned int parent_process_id,
+                            size_t write_handle_as_size_t,
+                            size_t event_handle_as_size_t) {
+  AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE,
+                                                   FALSE,  // Non-inheritable.
+                                                   parent_process_id));
+  if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) {
+    DeathTestAbort(String::Format("Unable to open parent process %u",
+                                  parent_process_id));
+  }
+
+  // TODO(vladl@google.com): Replace the following check with a
+  // compile-time assertion when available.
+  GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t));
+
+  const HANDLE write_handle =
+      reinterpret_cast<HANDLE>(write_handle_as_size_t);
+  HANDLE dup_write_handle;
+
+  // The newly initialized handle is accessible only in in the parent
+  // process. To obtain one accessible within the child, we need to use
+  // DuplicateHandle.
+  if (!::DuplicateHandle(parent_process_handle.Get(), write_handle,
+                         ::GetCurrentProcess(), &dup_write_handle,
+                         0x0,    // Requested privileges ignored since
+                                 // DUPLICATE_SAME_ACCESS is used.
+                         FALSE,  // Request non-inheritable handler.
+                         DUPLICATE_SAME_ACCESS)) {
+    DeathTestAbort(String::Format(
+        "Unable to duplicate the pipe handle %Iu from the parent process %u",
+        write_handle_as_size_t, parent_process_id));
+  }
+
+  const HANDLE event_handle = reinterpret_cast<HANDLE>(event_handle_as_size_t);
+  HANDLE dup_event_handle;
+
+  if (!::DuplicateHandle(parent_process_handle.Get(), event_handle,
+                         ::GetCurrentProcess(), &dup_event_handle,
+                         0x0,
+                         FALSE,
+                         DUPLICATE_SAME_ACCESS)) {
+    DeathTestAbort(String::Format(
+        "Unable to duplicate the event handle %Iu from the parent process %u",
+        event_handle_as_size_t, parent_process_id));
+  }
+
+  const int write_fd =
+      ::_open_osfhandle(reinterpret_cast<intptr_t>(dup_write_handle), O_APPEND);
+  if (write_fd == -1) {
+    DeathTestAbort(String::Format(
+        "Unable to convert pipe handle %Iu to a file descriptor",
+        write_handle_as_size_t));
+  }
+
+  // Signals the parent that the write end of the pipe has been acquired
+  // so the parent can release its own write end.
+  ::SetEvent(dup_event_handle);
+
+  return write_fd;
+}
+# endif  // GTEST_OS_WINDOWS
+
+// Returns a newly created InternalRunDeathTestFlag object with fields
+// initialized from the GTEST_FLAG(internal_run_death_test) flag if
+// the flag is specified; otherwise returns NULL.
+InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
+  if (GTEST_FLAG(internal_run_death_test) == "") return NULL;
+
+  // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
+  // can use it here.
+  int line = -1;
+  int index = -1;
+  ::std::vector< ::std::string> fields;
+  SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields);
+  int write_fd = -1;
+
+# if GTEST_OS_WINDOWS
+
+  unsigned int parent_process_id = 0;
+  size_t write_handle_as_size_t = 0;
+  size_t event_handle_as_size_t = 0;
+
+  if (fields.size() != 6
+      || !ParseNaturalNumber(fields[1], &line)
+      || !ParseNaturalNumber(fields[2], &index)
+      || !ParseNaturalNumber(fields[3], &parent_process_id)
+      || !ParseNaturalNumber(fields[4], &write_handle_as_size_t)
+      || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) {
+    DeathTestAbort(String::Format(
+        "Bad --gtest_internal_run_death_test flag: %s",
+        GTEST_FLAG(internal_run_death_test).c_str()));
+  }
+  write_fd = GetStatusFileDescriptor(parent_process_id,
+                                     write_handle_as_size_t,
+                                     event_handle_as_size_t);
+# else
+
+  if (fields.size() != 4
+      || !ParseNaturalNumber(fields[1], &line)
+      || !ParseNaturalNumber(fields[2], &index)
+      || !ParseNaturalNumber(fields[3], &write_fd)) {
+    DeathTestAbort(String::Format(
+        "Bad --gtest_internal_run_death_test flag: %s",
+        GTEST_FLAG(internal_run_death_test).c_str()));
+  }
+
+# endif  // GTEST_OS_WINDOWS
+
+  return new InternalRunDeathTestFlag(fields[0], line, index, write_fd);
+}
+
+}  // namespace internal
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+}  // namespace testing
diff --git a/third_party/googletest/src/src/gtest-filepath.cc b/third_party/googletest/src/src/gtest-filepath.cc
new file mode 100644 (file)
index 0000000..91b2571
--- /dev/null
@@ -0,0 +1,380 @@
+// Copyright 2008, 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.
+//
+// Authors: keith.ray@gmail.com (Keith Ray)
+
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/internal/gtest-port.h"
+
+#include <stdlib.h>
+
+#if GTEST_OS_WINDOWS_MOBILE
+# include <windows.h>
+#elif GTEST_OS_WINDOWS
+# include <direct.h>
+# include <io.h>
+#elif GTEST_OS_SYMBIAN || GTEST_OS_NACL
+// Symbian OpenC and NaCl have PATH_MAX in sys/syslimits.h
+# include <sys/syslimits.h>
+#else
+# include <limits.h>
+# include <climits>  // Some Linux distributions define PATH_MAX here.
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+#if GTEST_OS_WINDOWS
+# define GTEST_PATH_MAX_ _MAX_PATH
+#elif defined(PATH_MAX)
+# define GTEST_PATH_MAX_ PATH_MAX
+#elif defined(_XOPEN_PATH_MAX)
+# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
+#else
+# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
+#endif  // GTEST_OS_WINDOWS
+
+#include "gtest/internal/gtest-string.h"
+
+namespace testing {
+namespace internal {
+
+#if GTEST_OS_WINDOWS
+// On Windows, '\\' is the standard path separator, but many tools and the
+// Windows API also accept '/' as an alternate path separator. Unless otherwise
+// noted, a file path can contain either kind of path separators, or a mixture
+// of them.
+const char kPathSeparator = '\\';
+const char kAlternatePathSeparator = '/';
+const char kPathSeparatorString[] = "\\";
+const char kAlternatePathSeparatorString[] = "/";
+# if GTEST_OS_WINDOWS_MOBILE
+// Windows CE doesn't have a current directory. You should not use
+// the current directory in tests on Windows CE, but this at least
+// provides a reasonable fallback.
+const char kCurrentDirectoryString[] = "\\";
+// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
+const DWORD kInvalidFileAttributes = 0xffffffff;
+# else
+const char kCurrentDirectoryString[] = ".\\";
+# endif  // GTEST_OS_WINDOWS_MOBILE
+#else
+const char kPathSeparator = '/';
+const char kPathSeparatorString[] = "/";
+const char kCurrentDirectoryString[] = "./";
+#endif  // GTEST_OS_WINDOWS
+
+// Returns whether the given character is a valid path separator.
+static bool IsPathSeparator(char c) {
+#if GTEST_HAS_ALT_PATH_SEP_
+  return (c == kPathSeparator) || (c == kAlternatePathSeparator);
+#else
+  return c == kPathSeparator;
+#endif
+}
+
+// Returns the current working directory, or "" if unsuccessful.
+FilePath FilePath::GetCurrentDir() {
+#if GTEST_OS_WINDOWS_MOBILE
+  // Windows CE doesn't have a current directory, so we just return
+  // something reasonable.
+  return FilePath(kCurrentDirectoryString);
+#elif GTEST_OS_WINDOWS
+  char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
+  return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
+#else
+  char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
+  return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Returns a copy of the FilePath with the case-insensitive extension removed.
+// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
+// FilePath("dir/file"). If a case-insensitive extension is not
+// found, returns a copy of the original FilePath.
+FilePath FilePath::RemoveExtension(const char* extension) const {
+  String dot_extension(String::Format(".%s", extension));
+  if (pathname_.EndsWithCaseInsensitive(dot_extension.c_str())) {
+    return FilePath(String(pathname_.c_str(), pathname_.length() - 4));
+  }
+  return *this;
+}
+
+// Returns a pointer to the last occurence of a valid path separator in
+// the FilePath. On Windows, for example, both '/' and '\' are valid path
+// separators. Returns NULL if no path separator was found.
+const char* FilePath::FindLastPathSeparator() const {
+  const char* const last_sep = strrchr(c_str(), kPathSeparator);
+#if GTEST_HAS_ALT_PATH_SEP_
+  const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
+  // Comparing two pointers of which only one is NULL is undefined.
+  if (last_alt_sep != NULL &&
+      (last_sep == NULL || last_alt_sep > last_sep)) {
+    return last_alt_sep;
+  }
+#endif
+  return last_sep;
+}
+
+// Returns a copy of the FilePath with the directory part removed.
+// Example: FilePath("path/to/file").RemoveDirectoryName() returns
+// FilePath("file"). If there is no directory part ("just_a_file"), it returns
+// the FilePath unmodified. If there is no file part ("just_a_dir/") it
+// returns an empty FilePath ("").
+// On Windows platform, '\' is the path separator, otherwise it is '/'.
+FilePath FilePath::RemoveDirectoryName() const {
+  const char* const last_sep = FindLastPathSeparator();
+  return last_sep ? FilePath(String(last_sep + 1)) : *this;
+}
+
+// RemoveFileName returns the directory path with the filename removed.
+// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
+// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
+// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
+// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
+// On Windows platform, '\' is the path separator, otherwise it is '/'.
+FilePath FilePath::RemoveFileName() const {
+  const char* const last_sep = FindLastPathSeparator();
+  String dir;
+  if (last_sep) {
+    dir = String(c_str(), last_sep + 1 - c_str());
+  } else {
+    dir = kCurrentDirectoryString;
+  }
+  return FilePath(dir);
+}
+
+// Helper functions for naming files in a directory for xml output.
+
+// Given directory = "dir", base_name = "test", number = 0,
+// extension = "xml", returns "dir/test.xml". If number is greater
+// than zero (e.g., 12), returns "dir/test_12.xml".
+// On Windows platform, uses \ as the separator rather than /.
+FilePath FilePath::MakeFileName(const FilePath& directory,
+                                const FilePath& base_name,
+                                int number,
+                                const char* extension) {
+  String file;
+  if (number == 0) {
+    file = String::Format("%s.%s", base_name.c_str(), extension);
+  } else {
+    file = String::Format("%s_%d.%s", base_name.c_str(), number, extension);
+  }
+  return ConcatPaths(directory, FilePath(file));
+}
+
+// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml".
+// On Windows, uses \ as the separator rather than /.
+FilePath FilePath::ConcatPaths(const FilePath& directory,
+                               const FilePath& relative_path) {
+  if (directory.IsEmpty())
+    return relative_path;
+  const FilePath dir(directory.RemoveTrailingPathSeparator());
+  return FilePath(String::Format("%s%c%s", dir.c_str(), kPathSeparator,
+                                 relative_path.c_str()));
+}
+
+// Returns true if pathname describes something findable in the file-system,
+// either a file, directory, or whatever.
+bool FilePath::FileOrDirectoryExists() const {
+#if GTEST_OS_WINDOWS_MOBILE
+  LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
+  const DWORD attributes = GetFileAttributes(unicode);
+  delete [] unicode;
+  return attributes != kInvalidFileAttributes;
+#else
+  posix::StatStruct file_stat;
+  return posix::Stat(pathname_.c_str(), &file_stat) == 0;
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Returns true if pathname describes a directory in the file-system
+// that exists.
+bool FilePath::DirectoryExists() const {
+  bool result = false;
+#if GTEST_OS_WINDOWS
+  // Don't strip off trailing separator if path is a root directory on
+  // Windows (like "C:\\").
+  const FilePath& path(IsRootDirectory() ? *this :
+                                           RemoveTrailingPathSeparator());
+#else
+  const FilePath& path(*this);
+#endif
+
+#if GTEST_OS_WINDOWS_MOBILE
+  LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
+  const DWORD attributes = GetFileAttributes(unicode);
+  delete [] unicode;
+  if ((attributes != kInvalidFileAttributes) &&
+      (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
+    result = true;
+  }
+#else
+  posix::StatStruct file_stat;
+  result = posix::Stat(path.c_str(), &file_stat) == 0 &&
+      posix::IsDir(file_stat);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+  return result;
+}
+
+// Returns true if pathname describes a root directory. (Windows has one
+// root directory per disk drive.)
+bool FilePath::IsRootDirectory() const {
+#if GTEST_OS_WINDOWS
+  // TODO(wan@google.com): on Windows a network share like
+  // \\server\share can be a root directory, although it cannot be the
+  // current directory.  Handle this properly.
+  return pathname_.length() == 3 && IsAbsolutePath();
+#else
+  return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
+#endif
+}
+
+// Returns true if pathname describes an absolute path.
+bool FilePath::IsAbsolutePath() const {
+  const char* const name = pathname_.c_str();
+#if GTEST_OS_WINDOWS
+  return pathname_.length() >= 3 &&
+     ((name[0] >= 'a' && name[0] <= 'z') ||
+      (name[0] >= 'A' && name[0] <= 'Z')) &&
+     name[1] == ':' &&
+     IsPathSeparator(name[2]);
+#else
+  return IsPathSeparator(name[0]);
+#endif
+}
+
+// Returns a pathname for a file that does not currently exist. The pathname
+// will be directory/base_name.extension or
+// directory/base_name_<number>.extension if directory/base_name.extension
+// already exists. The number will be incremented until a pathname is found
+// that does not already exist.
+// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
+// There could be a race condition if two or more processes are calling this
+// function at the same time -- they could both pick the same filename.
+FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
+                                          const FilePath& base_name,
+                                          const char* extension) {
+  FilePath full_pathname;
+  int number = 0;
+  do {
+    full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
+  } while (full_pathname.FileOrDirectoryExists());
+  return full_pathname;
+}
+
+// Returns true if FilePath ends with a path separator, which indicates that
+// it is intended to represent a directory. Returns false otherwise.
+// This does NOT check that a directory (or file) actually exists.
+bool FilePath::IsDirectory() const {
+  return !pathname_.empty() &&
+         IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
+}
+
+// Create directories so that path exists. Returns true if successful or if
+// the directories already exist; returns false if unable to create directories
+// for any reason.
+bool FilePath::CreateDirectoriesRecursively() const {
+  if (!this->IsDirectory()) {
+    return false;
+  }
+
+  if (pathname_.length() == 0 || this->DirectoryExists()) {
+    return true;
+  }
+
+  const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
+  return parent.CreateDirectoriesRecursively() && this->CreateFolder();
+}
+
+// Create the directory so that path exists. Returns true if successful or
+// if the directory already exists; returns false if unable to create the
+// directory for any reason, including if the parent directory does not
+// exist. Not named "CreateDirectory" because that's a macro on Windows.
+bool FilePath::CreateFolder() const {
+#if GTEST_OS_WINDOWS_MOBILE
+  FilePath removed_sep(this->RemoveTrailingPathSeparator());
+  LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
+  int result = CreateDirectory(unicode, NULL) ? 0 : -1;
+  delete [] unicode;
+#elif GTEST_OS_WINDOWS
+  int result = _mkdir(pathname_.c_str());
+#else
+  int result = mkdir(pathname_.c_str(), 0777);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+  if (result == -1) {
+    return this->DirectoryExists();  // An error is OK if the directory exists.
+  }
+  return true;  // No error.
+}
+
+// If input name has a trailing separator character, remove it and return the
+// name, otherwise return the name string unmodified.
+// On Windows platform, uses \ as the separator, other platforms use /.
+FilePath FilePath::RemoveTrailingPathSeparator() const {
+  return IsDirectory()
+      ? FilePath(String(pathname_.c_str(), pathname_.length() - 1))
+      : *this;
+}
+
+// Removes any redundant separators that might be in the pathname.
+// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
+// redundancies that might be in a pathname involving "." or "..".
+// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share).
+void FilePath::Normalize() {
+  if (pathname_.c_str() == NULL) {
+    pathname_ = "";
+    return;
+  }
+  const char* src = pathname_.c_str();
+  char* const dest = new char[pathname_.length() + 1];
+  char* dest_ptr = dest;
+  memset(dest_ptr, 0, pathname_.length() + 1);
+
+  while (*src != '\0') {
+    *dest_ptr = *src;
+    if (!IsPathSeparator(*src)) {
+      src++;
+    } else {
+#if GTEST_HAS_ALT_PATH_SEP_
+      if (*dest_ptr == kAlternatePathSeparator) {
+        *dest_ptr = kPathSeparator;
+      }
+#endif
+      while (IsPathSeparator(*src))
+        src++;
+    }
+    dest_ptr++;
+  }
+  *dest_ptr = '\0';
+  pathname_ = dest;
+  delete[] dest;
+}
+
+}  // namespace internal
+}  // namespace testing
diff --git a/third_party/googletest/src/src/gtest-internal-inl.h b/third_party/googletest/src/src/gtest-internal-inl.h
new file mode 100644 (file)
index 0000000..65a2101
--- /dev/null
@@ -0,0 +1,1038 @@
+// Copyright 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.
+
+// Utility functions and classes used by the Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// This file contains purely Google Test's internal implementation.  Please
+// DO NOT #INCLUDE IT IN A USER PROGRAM.
+
+#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_
+#define GTEST_SRC_GTEST_INTERNAL_INL_H_
+
+// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is
+// part of Google Test's implementation; otherwise it's undefined.
+#if !GTEST_IMPLEMENTATION_
+// A user is trying to include this from his code - just say no.
+# error "gtest-internal-inl.h is part of Google Test's internal implementation."
+# error "It must not be included except by Google Test itself."
+#endif  // GTEST_IMPLEMENTATION_
+
+#ifndef _WIN32_WCE
+# include <errno.h>
+#endif  // !_WIN32_WCE
+#include <stddef.h>
+#include <stdlib.h>  // For strtoll/_strtoul64/malloc/free.
+#include <string.h>  // For memmove.
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_OS_WINDOWS
+# include <windows.h>  // NOLINT
+#endif  // GTEST_OS_WINDOWS
+
+#include "gtest/gtest.h"  // NOLINT
+#include "gtest/gtest-spi.h"
+
+namespace testing {
+
+// Declares the flags.
+//
+// We don't want the users to modify this flag in the code, but want
+// Google Test's own unit tests to be able to access it. Therefore we
+// declare it here as opposed to in gtest.h.
+GTEST_DECLARE_bool_(death_test_use_fork);
+
+namespace internal {
+
+// The value of GetTestTypeId() as seen from within the Google Test
+// library.  This is solely for testing GetTestTypeId().
+GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest;
+
+// Names of the flags (needed for parsing Google Test flags).
+const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests";
+const char kBreakOnFailureFlag[] = "break_on_failure";
+const char kCatchExceptionsFlag[] = "catch_exceptions";
+const char kColorFlag[] = "color";
+const char kFilterFlag[] = "filter";
+const char kListTestsFlag[] = "list_tests";
+const char kOutputFlag[] = "output";
+const char kPrintTimeFlag[] = "print_time";
+const char kRandomSeedFlag[] = "random_seed";
+const char kRepeatFlag[] = "repeat";
+const char kShuffleFlag[] = "shuffle";
+const char kStackTraceDepthFlag[] = "stack_trace_depth";
+const char kStreamResultToFlag[] = "stream_result_to";
+const char kThrowOnFailureFlag[] = "throw_on_failure";
+
+// A valid random seed must be in [1, kMaxRandomSeed].
+const int kMaxRandomSeed = 99999;
+
+// g_help_flag is true iff the --help flag or an equivalent form is
+// specified on the command line.
+GTEST_API_ extern bool g_help_flag;
+
+// Returns the current time in milliseconds.
+GTEST_API_ TimeInMillis GetTimeInMillis();
+
+// Returns true iff Google Test should use colors in the output.
+GTEST_API_ bool ShouldUseColor(bool stdout_is_tty);
+
+// Formats the given time in milliseconds as seconds.
+GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms);
+
+// Parses a string for an Int32 flag, in the form of "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+GTEST_API_ bool ParseInt32Flag(
+    const char* str, const char* flag, Int32* value);
+
+// Returns a random seed in range [1, kMaxRandomSeed] based on the
+// given --gtest_random_seed flag value.
+inline int GetRandomSeedFromFlag(Int32 random_seed_flag) {
+  const unsigned int raw_seed = (random_seed_flag == 0) ?
+      static_cast<unsigned int>(GetTimeInMillis()) :
+      static_cast<unsigned int>(random_seed_flag);
+
+  // Normalizes the actual seed to range [1, kMaxRandomSeed] such that
+  // it's easy to type.
+  const int normalized_seed =
+      static_cast<int>((raw_seed - 1U) %
+                       static_cast<unsigned int>(kMaxRandomSeed)) + 1;
+  return normalized_seed;
+}
+
+// Returns the first valid random seed after 'seed'.  The behavior is
+// undefined if 'seed' is invalid.  The seed after kMaxRandomSeed is
+// considered to be 1.
+inline int GetNextRandomSeed(int seed) {
+  GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed)
+      << "Invalid random seed " << seed << " - must be in [1, "
+      << kMaxRandomSeed << "].";
+  const int next_seed = seed + 1;
+  return (next_seed > kMaxRandomSeed) ? 1 : next_seed;
+}
+
+// This class saves the values of all Google Test flags in its c'tor, and
+// restores them in its d'tor.
+class GTestFlagSaver {
+ public:
+  // The c'tor.
+  GTestFlagSaver() {
+    also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests);
+    break_on_failure_ = GTEST_FLAG(break_on_failure);
+    catch_exceptions_ = GTEST_FLAG(catch_exceptions);
+    color_ = GTEST_FLAG(color);
+    death_test_style_ = GTEST_FLAG(death_test_style);
+    death_test_use_fork_ = GTEST_FLAG(death_test_use_fork);
+    filter_ = GTEST_FLAG(filter);
+    internal_run_death_test_ = GTEST_FLAG(internal_run_death_test);
+    list_tests_ = GTEST_FLAG(list_tests);
+    output_ = GTEST_FLAG(output);
+    print_time_ = GTEST_FLAG(print_time);
+    random_seed_ = GTEST_FLAG(random_seed);
+    repeat_ = GTEST_FLAG(repeat);
+    shuffle_ = GTEST_FLAG(shuffle);
+    stack_trace_depth_ = GTEST_FLAG(stack_trace_depth);
+    stream_result_to_ = GTEST_FLAG(stream_result_to);
+    throw_on_failure_ = GTEST_FLAG(throw_on_failure);
+  }
+
+  // The d'tor is not virtual.  DO NOT INHERIT FROM THIS CLASS.
+  ~GTestFlagSaver() {
+    GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_;
+    GTEST_FLAG(break_on_failure) = break_on_failure_;
+    GTEST_FLAG(catch_exceptions) = catch_exceptions_;
+    GTEST_FLAG(color) = color_;
+    GTEST_FLAG(death_test_style) = death_test_style_;
+    GTEST_FLAG(death_test_use_fork) = death_test_use_fork_;
+    GTEST_FLAG(filter) = filter_;
+    GTEST_FLAG(internal_run_death_test) = internal_run_death_test_;
+    GTEST_FLAG(list_tests) = list_tests_;
+    GTEST_FLAG(output) = output_;
+    GTEST_FLAG(print_time) = print_time_;
+    GTEST_FLAG(random_seed) = random_seed_;
+    GTEST_FLAG(repeat) = repeat_;
+    GTEST_FLAG(shuffle) = shuffle_;
+    GTEST_FLAG(stack_trace_depth) = stack_trace_depth_;
+    GTEST_FLAG(stream_result_to) = stream_result_to_;
+    GTEST_FLAG(throw_on_failure) = throw_on_failure_;
+  }
+ private:
+  // Fields for saving the original values of flags.
+  bool also_run_disabled_tests_;
+  bool break_on_failure_;
+  bool catch_exceptions_;
+  String color_;
+  String death_test_style_;
+  bool death_test_use_fork_;
+  String filter_;
+  String internal_run_death_test_;
+  bool list_tests_;
+  String output_;
+  bool print_time_;
+  bool pretty_;
+  internal::Int32 random_seed_;
+  internal::Int32 repeat_;
+  bool shuffle_;
+  internal::Int32 stack_trace_depth_;
+  String stream_result_to_;
+  bool throw_on_failure_;
+} GTEST_ATTRIBUTE_UNUSED_;
+
+// Converts a Unicode code point to a narrow string in UTF-8 encoding.
+// code_point parameter is of type UInt32 because wchar_t may not be
+// wide enough to contain a code point.
+// The output buffer str must containt at least 32 characters.
+// The function returns the address of the output buffer.
+// If the code_point is not a valid Unicode code point
+// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'.
+GTEST_API_ char* CodePointToUtf8(UInt32 code_point, char* str);
+
+// Converts a wide string to a narrow string in UTF-8 encoding.
+// The wide string is assumed to have the following encoding:
+//   UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS)
+//   UTF-32 if sizeof(wchar_t) == 4 (on Linux)
+// Parameter str points to a null-terminated wide string.
+// Parameter num_chars may additionally limit the number
+// of wchar_t characters processed. -1 is used when the entire string
+// should be processed.
+// If the string contains code points that are not valid Unicode code points
+// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
+// and contains invalid UTF-16 surrogate pairs, values in those pairs
+// will be encoded as individual Unicode characters from Basic Normal Plane.
+GTEST_API_ String WideStringToUtf8(const wchar_t* str, int num_chars);
+
+// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
+// if the variable is present. If a file already exists at this location, this
+// function will write over it. If the variable is present, but the file cannot
+// be created, prints an error and exits.
+void WriteToShardStatusFileIfNeeded();
+
+// Checks whether sharding is enabled by examining the relevant
+// environment variable values. If the variables are present,
+// but inconsistent (e.g., shard_index >= total_shards), prints
+// an error and exits. If in_subprocess_for_death_test, sharding is
+// disabled because it must only be applied to the original test
+// process. Otherwise, we could filter out death tests we intended to execute.
+GTEST_API_ bool ShouldShard(const char* total_shards_str,
+                            const char* shard_index_str,
+                            bool in_subprocess_for_death_test);
+
+// Parses the environment variable var as an Int32. If it is unset,
+// returns default_val. If it is not an Int32, prints an error and
+// and aborts.
+GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val);
+
+// Given the total number of shards, the shard index, and the test id,
+// returns true iff the test should be run on this shard. The test id is
+// some arbitrary but unique non-negative integer assigned to each test
+// method. Assumes that 0 <= shard_index < total_shards.
+GTEST_API_ bool ShouldRunTestOnShard(
+    int total_shards, int shard_index, int test_id);
+
+// STL container utilities.
+
+// Returns the number of elements in the given container that satisfy
+// the given predicate.
+template <class Container, typename Predicate>
+inline int CountIf(const Container& c, Predicate predicate) {
+  // Implemented as an explicit loop since std::count_if() in libCstd on
+  // Solaris has a non-standard signature.
+  int count = 0;
+  for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) {
+    if (predicate(*it))
+      ++count;
+  }
+  return count;
+}
+
+// Applies a function/functor to each element in the container.
+template <class Container, typename Functor>
+void ForEach(const Container& c, Functor functor) {
+  std::for_each(c.begin(), c.end(), functor);
+}
+
+// Returns the i-th element of the vector, or default_value if i is not
+// in range [0, v.size()).
+template <typename E>
+inline E GetElementOr(const std::vector<E>& v, int i, E default_value) {
+  return (i < 0 || i >= static_cast<int>(v.size())) ? default_value : v[i];
+}
+
+// Performs an in-place shuffle of a range of the vector's elements.
+// 'begin' and 'end' are element indices as an STL-style range;
+// i.e. [begin, end) are shuffled, where 'end' == size() means to
+// shuffle to the end of the vector.
+template <typename E>
+void ShuffleRange(internal::Random* random, int begin, int end,
+                  std::vector<E>* v) {
+  const int size = static_cast<int>(v->size());
+  GTEST_CHECK_(0 <= begin && begin <= size)
+      << "Invalid shuffle range start " << begin << ": must be in range [0, "
+      << size << "].";
+  GTEST_CHECK_(begin <= end && end <= size)
+      << "Invalid shuffle range finish " << end << ": must be in range ["
+      << begin << ", " << size << "].";
+
+  // Fisher-Yates shuffle, from
+  // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
+  for (int range_width = end - begin; range_width >= 2; range_width--) {
+    const int last_in_range = begin + range_width - 1;
+    const int selected = begin + random->Generate(range_width);
+    std::swap((*v)[selected], (*v)[last_in_range]);
+  }
+}
+
+// Performs an in-place shuffle of the vector's elements.
+template <typename E>
+inline void Shuffle(internal::Random* random, std::vector<E>* v) {
+  ShuffleRange(random, 0, static_cast<int>(v->size()), v);
+}
+
+// A function for deleting an object.  Handy for being used as a
+// functor.
+template <typename T>
+static void Delete(T* x) {
+  delete x;
+}
+
+// A predicate that checks the key of a TestProperty against a known key.
+//
+// TestPropertyKeyIs is copyable.
+class TestPropertyKeyIs {
+ public:
+  // Constructor.
+  //
+  // TestPropertyKeyIs has NO default constructor.
+  explicit TestPropertyKeyIs(const char* key)
+      : key_(key) {}
+
+  // Returns true iff the test name of test property matches on key_.
+  bool operator()(const TestProperty& test_property) const {
+    return String(test_property.key()).Compare(key_) == 0;
+  }
+
+ private:
+  String key_;
+};
+
+// Class UnitTestOptions.
+//
+// This class contains functions for processing options the user
+// specifies when running the tests.  It has only static members.
+//
+// In most cases, the user can specify an option using either an
+// environment variable or a command line flag.  E.g. you can set the
+// test filter using either GTEST_FILTER or --gtest_filter.  If both
+// the variable and the flag are present, the latter overrides the
+// former.
+class GTEST_API_ UnitTestOptions {
+ public:
+  // Functions for processing the gtest_output flag.
+
+  // Returns the output format, or "" for normal printed output.
+  static String GetOutputFormat();
+
+  // Returns the absolute path of the requested output file, or the
+  // default (test_detail.xml in the original working directory) if
+  // none was explicitly specified.
+  static String GetAbsolutePathToOutputFile();
+
+  // Functions for processing the gtest_filter flag.
+
+  // Returns true iff the wildcard pattern matches the string.  The
+  // first ':' or '\0' character in pattern marks the end of it.
+  //
+  // This recursive algorithm isn't very efficient, but is clear and
+  // works well enough for matching test names, which are short.
+  static bool PatternMatchesString(const char *pattern, const char *str);
+
+  // Returns true iff the user-specified filter matches the test case
+  // name and the test name.
+  static bool FilterMatchesTest(const String &test_case_name,
+                                const String &test_name);
+
+#if GTEST_OS_WINDOWS
+  // Function for supporting the gtest_catch_exception flag.
+
+  // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
+  // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
+  // This function is useful as an __except condition.
+  static int GTestShouldProcessSEH(DWORD exception_code);
+#endif  // GTEST_OS_WINDOWS
+
+  // Returns true if "name" matches the ':' separated list of glob-style
+  // filters in "filter".
+  static bool MatchesFilter(const String& name, const char* filter);
+};
+
+// Returns the current application's name, removing directory path if that
+// is present.  Used by UnitTestOptions::GetOutputFile.
+GTEST_API_ FilePath GetCurrentExecutableName();
+
+// The role interface for getting the OS stack trace as a string.
+class OsStackTraceGetterInterface {
+ public:
+  OsStackTraceGetterInterface() {}
+  virtual ~OsStackTraceGetterInterface() {}
+
+  // Returns the current OS stack trace as a String.  Parameters:
+  //
+  //   max_depth  - the maximum number of stack frames to be included
+  //                in the trace.
+  //   skip_count - the number of top frames to be skipped; doesn't count
+  //                against max_depth.
+  virtual String CurrentStackTrace(int max_depth, int skip_count) = 0;
+
+  // UponLeavingGTest() should be called immediately before Google Test calls
+  // user code. It saves some information about the current stack that
+  // CurrentStackTrace() will use to find and hide Google Test stack frames.
+  virtual void UponLeavingGTest() = 0;
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface);
+};
+
+// A working implementation of the OsStackTraceGetterInterface interface.
+class OsStackTraceGetter : public OsStackTraceGetterInterface {
+ public:
+  OsStackTraceGetter() : caller_frame_(NULL) {}
+  virtual String CurrentStackTrace(int max_depth, int skip_count);
+  virtual void UponLeavingGTest();
+
+  // This string is inserted in place of stack frames that are part of
+  // Google Test's implementation.
+  static const char* const kElidedFramesMarker;
+
+ private:
+  Mutex mutex_;  // protects all internal state
+
+  // We save the stack frame below the frame that calls user code.
+  // We do this because the address of the frame immediately below
+  // the user code changes between the call to UponLeavingGTest()
+  // and any calls to CurrentStackTrace() from within the user code.
+  void* caller_frame_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter);
+};
+
+// Information about a Google Test trace point.
+struct TraceInfo {
+  const char* file;
+  int line;
+  String message;
+};
+
+// This is the default global test part result reporter used in UnitTestImpl.
+// This class should only be used by UnitTestImpl.
+class DefaultGlobalTestPartResultReporter
+  : public TestPartResultReporterInterface {
+ public:
+  explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test);
+  // Implements the TestPartResultReporterInterface. Reports the test part
+  // result in the current test.
+  virtual void ReportTestPartResult(const TestPartResult& result);
+
+ private:
+  UnitTestImpl* const unit_test_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter);
+};
+
+// This is the default per thread test part result reporter used in
+// UnitTestImpl. This class should only be used by UnitTestImpl.
+class DefaultPerThreadTestPartResultReporter
+    : public TestPartResultReporterInterface {
+ public:
+  explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test);
+  // Implements the TestPartResultReporterInterface. The implementation just
+  // delegates to the current global test part result reporter of *unit_test_.
+  virtual void ReportTestPartResult(const TestPartResult& result);
+
+ private:
+  UnitTestImpl* const unit_test_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter);
+};
+
+// The private implementation of the UnitTest class.  We don't protect
+// the methods under a mutex, as this class is not accessible by a
+// user and the UnitTest class that delegates work to this class does
+// proper locking.
+class GTEST_API_ UnitTestImpl {
+ public:
+  explicit UnitTestImpl(UnitTest* parent);
+  virtual ~UnitTestImpl();
+
+  // There are two different ways to register your own TestPartResultReporter.
+  // You can register your own repoter to listen either only for test results
+  // from the current thread or for results from all threads.
+  // By default, each per-thread test result repoter just passes a new
+  // TestPartResult to the global test result reporter, which registers the
+  // test part result for the currently running test.
+
+  // Returns the global test part result reporter.
+  TestPartResultReporterInterface* GetGlobalTestPartResultReporter();
+
+  // Sets the global test part result reporter.
+  void SetGlobalTestPartResultReporter(
+      TestPartResultReporterInterface* reporter);
+
+  // Returns the test part result reporter for the current thread.
+  TestPartResultReporterInterface* GetTestPartResultReporterForCurrentThread();
+
+  // Sets the test part result reporter for the current thread.
+  void SetTestPartResultReporterForCurrentThread(
+      TestPartResultReporterInterface* reporter);
+
+  // Gets the number of successful test cases.
+  int successful_test_case_count() const;
+
+  // Gets the number of failed test cases.
+  int failed_test_case_count() const;
+
+  // Gets the number of all test cases.
+  int total_test_case_count() const;
+
+  // Gets the number of all test cases that contain at least one test
+  // that should run.
+  int test_case_to_run_count() const;
+
+  // Gets the number of successful tests.
+  int successful_test_count() const;
+
+  // Gets the number of failed tests.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests.
+  int disabled_test_count() const;
+
+  // Gets the number of all tests.
+  int total_test_count() const;
+
+  // Gets the number of tests that should run.
+  int test_to_run_count() const;
+
+  // Gets the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Returns true iff the unit test passed (i.e. all test cases passed).
+  bool Passed() const { return !Failed(); }
+
+  // Returns true iff the unit test failed (i.e. some test case failed
+  // or something outside of all tests failed).
+  bool Failed() const {
+    return failed_test_case_count() > 0 || ad_hoc_test_result()->Failed();
+  }
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  const TestCase* GetTestCase(int i) const {
+    const int index = GetElementOr(test_case_indices_, i, -1);
+    return index < 0 ? NULL : test_cases_[i];
+  }
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  TestCase* GetMutableTestCase(int i) {
+    const int index = GetElementOr(test_case_indices_, i, -1);
+    return index < 0 ? NULL : test_cases_[index];
+  }
+
+  // Provides access to the event listener list.
+  TestEventListeners* listeners() { return &listeners_; }
+
+  // Returns the TestResult for the test that's currently running, or
+  // the TestResult for the ad hoc test if no test is running.
+  TestResult* current_test_result();
+
+  // Returns the TestResult for the ad hoc test.
+  const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; }
+
+  // Sets the OS stack trace getter.
+  //
+  // Does nothing if the input and the current OS stack trace getter
+  // are the same; otherwise, deletes the old getter and makes the
+  // input the current getter.
+  void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter);
+
+  // Returns the current OS stack trace getter if it is not NULL;
+  // otherwise, creates an OsStackTraceGetter, makes it the current
+  // getter, and returns it.
+  OsStackTraceGetterInterface* os_stack_trace_getter();
+
+  // Returns the current OS stack trace as a String.
+  //
+  // The maximum number of stack frames to be included is specified by
+  // the gtest_stack_trace_depth flag.  The skip_count parameter
+  // specifies the number of top frames to be skipped, which doesn't
+  // count against the number of frames to be included.
+  //
+  // For example, if Foo() calls Bar(), which in turn calls
+  // CurrentOsStackTraceExceptTop(1), Foo() will be included in the
+  // trace but Bar() and CurrentOsStackTraceExceptTop() won't.
+  String CurrentOsStackTraceExceptTop(int skip_count);
+
+  // Finds and returns a TestCase with the given name.  If one doesn't
+  // exist, creates one and returns it.
+  //
+  // Arguments:
+  //
+  //   test_case_name: name of the test case
+  //   type_param:     the name of the test's type parameter, or NULL if
+  //                   this is not a typed or a type-parameterized test.
+  //   set_up_tc:      pointer to the function that sets up the test case
+  //   tear_down_tc:   pointer to the function that tears down the test case
+  TestCase* GetTestCase(const char* test_case_name,
+                        const char* type_param,
+                        Test::SetUpTestCaseFunc set_up_tc,
+                        Test::TearDownTestCaseFunc tear_down_tc);
+
+  // Adds a TestInfo to the unit test.
+  //
+  // Arguments:
+  //
+  //   set_up_tc:    pointer to the function that sets up the test case
+  //   tear_down_tc: pointer to the function that tears down the test case
+  //   test_info:    the TestInfo object
+  void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc,
+                   Test::TearDownTestCaseFunc tear_down_tc,
+                   TestInfo* test_info) {
+    // In order to support thread-safe death tests, we need to
+    // remember the original working directory when the test program
+    // was first invoked.  We cannot do this in RUN_ALL_TESTS(), as
+    // the user may have changed the current directory before calling
+    // RUN_ALL_TESTS().  Therefore we capture the current directory in
+    // AddTestInfo(), which is called to register a TEST or TEST_F
+    // before main() is reached.
+    if (original_working_dir_.IsEmpty()) {
+      original_working_dir_.Set(FilePath::GetCurrentDir());
+      GTEST_CHECK_(!original_working_dir_.IsEmpty())
+          << "Failed to get the current working directory.";
+    }
+
+    GetTestCase(test_info->test_case_name(),
+                test_info->type_param(),
+                set_up_tc,
+                tear_down_tc)->AddTestInfo(test_info);
+  }
+
+#if GTEST_HAS_PARAM_TEST
+  // Returns ParameterizedTestCaseRegistry object used to keep track of
+  // value-parameterized tests and instantiate and register them.
+  internal::ParameterizedTestCaseRegistry& parameterized_test_registry() {
+    return parameterized_test_registry_;
+  }
+#endif  // GTEST_HAS_PARAM_TEST
+
+  // Sets the TestCase object for the test that's currently running.
+  void set_current_test_case(TestCase* a_current_test_case) {
+    current_test_case_ = a_current_test_case;
+  }
+
+  // Sets the TestInfo object for the test that's currently running.  If
+  // current_test_info is NULL, the assertion results will be stored in
+  // ad_hoc_test_result_.
+  void set_current_test_info(TestInfo* a_current_test_info) {
+    current_test_info_ = a_current_test_info;
+  }
+
+  // Registers all parameterized tests defined using TEST_P and
+  // INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter
+  // combination. This method can be called more then once; it has guards
+  // protecting from registering the tests more then once.  If
+  // value-parameterized tests are disabled, RegisterParameterizedTests is
+  // present but does nothing.
+  void RegisterParameterizedTests();
+
+  // Runs all tests in this UnitTest object, prints the result, and
+  // returns true if all tests are successful.  If any exception is
+  // thrown during a test, this test is considered to be failed, but
+  // the rest of the tests will still be run.
+  bool RunAllTests();
+
+  // Clears the results of all tests, except the ad hoc tests.
+  void ClearNonAdHocTestResult() {
+    ForEach(test_cases_, TestCase::ClearTestCaseResult);
+  }
+
+  // Clears the results of ad-hoc test assertions.
+  void ClearAdHocTestResult() {
+    ad_hoc_test_result_.Clear();
+  }
+
+  enum ReactionToSharding {
+    HONOR_SHARDING_PROTOCOL,
+    IGNORE_SHARDING_PROTOCOL
+  };
+
+  // Matches the full name of each test against the user-specified
+  // filter to decide whether the test should run, then records the
+  // result in each TestCase and TestInfo object.
+  // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests
+  // based on sharding variables in the environment.
+  // Returns the number of tests that should run.
+  int FilterTests(ReactionToSharding shard_tests);
+
+  // Prints the names of the tests matching the user-specified filter flag.
+  void ListTestsMatchingFilter();
+
+  const TestCase* current_test_case() const { return current_test_case_; }
+  TestInfo* current_test_info() { return current_test_info_; }
+  const TestInfo* current_test_info() const { return current_test_info_; }
+
+  // Returns the vector of environments that need to be set-up/torn-down
+  // before/after the tests are run.
+  std::vector<Environment*>& environments() { return environments_; }
+
+  // Getters for the per-thread Google Test trace stack.
+  std::vector<TraceInfo>& gtest_trace_stack() {
+    return *(gtest_trace_stack_.pointer());
+  }
+  const std::vector<TraceInfo>& gtest_trace_stack() const {
+    return gtest_trace_stack_.get();
+  }
+
+#if GTEST_HAS_DEATH_TEST
+  void InitDeathTestSubprocessControlInfo() {
+    internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag());
+  }
+  // Returns a pointer to the parsed --gtest_internal_run_death_test
+  // flag, or NULL if that flag was not specified.
+  // This information is useful only in a death test child process.
+  // Must not be called before a call to InitGoogleTest.
+  const InternalRunDeathTestFlag* internal_run_death_test_flag() const {
+    return internal_run_death_test_flag_.get();
+  }
+
+  // Returns a pointer to the current death test factory.
+  internal::DeathTestFactory* death_test_factory() {
+    return death_test_factory_.get();
+  }
+
+  void SuppressTestEventsIfInSubprocess();
+
+  friend class ReplaceDeathTestFactory;
+#endif  // GTEST_HAS_DEATH_TEST
+
+  // Initializes the event listener performing XML output as specified by
+  // UnitTestOptions. Must not be called before InitGoogleTest.
+  void ConfigureXmlOutput();
+
+#if GTEST_CAN_STREAM_RESULTS_
+  // Initializes the event listener for streaming test results to a socket.
+  // Must not be called before InitGoogleTest.
+  void ConfigureStreamingOutput();
+#endif
+
+  // Performs initialization dependent upon flag values obtained in
+  // ParseGoogleTestFlagsOnly.  Is called from InitGoogleTest after the call to
+  // ParseGoogleTestFlagsOnly.  In case a user neglects to call InitGoogleTest
+  // this function is also called from RunAllTests.  Since this function can be
+  // called more than once, it has to be idempotent.
+  void PostFlagParsingInit();
+
+  // Gets the random seed used at the start of the current test iteration.
+  int random_seed() const { return random_seed_; }
+
+  // Gets the random number generator.
+  internal::Random* random() { return &random_; }
+
+  // Shuffles all test cases, and the tests within each test case,
+  // making sure that death tests are still run first.
+  void ShuffleTests();
+
+  // Restores the test cases and tests to their order before the first shuffle.
+  void UnshuffleTests();
+
+  // Returns the value of GTEST_FLAG(catch_exceptions) at the moment
+  // UnitTest::Run() starts.
+  bool catch_exceptions() const { return catch_exceptions_; }
+
+ private:
+  friend class ::testing::UnitTest;
+
+  // Used by UnitTest::Run() to capture the state of
+  // GTEST_FLAG(catch_exceptions) at the moment it starts.
+  void set_catch_exceptions(bool value) { catch_exceptions_ = value; }
+
+  // The UnitTest object that owns this implementation object.
+  UnitTest* const parent_;
+
+  // The working directory when the first TEST() or TEST_F() was
+  // executed.
+  internal::FilePath original_working_dir_;
+
+  // The default test part result reporters.
+  DefaultGlobalTestPartResultReporter default_global_test_part_result_reporter_;
+  DefaultPerThreadTestPartResultReporter
+      default_per_thread_test_part_result_reporter_;
+
+  // Points to (but doesn't own) the global test part result reporter.
+  TestPartResultReporterInterface* global_test_part_result_repoter_;
+
+  // Protects read and write access to global_test_part_result_reporter_.
+  internal::Mutex global_test_part_result_reporter_mutex_;
+
+  // Points to (but doesn't own) the per-thread test part result reporter.
+  internal::ThreadLocal<TestPartResultReporterInterface*>
+      per_thread_test_part_result_reporter_;
+
+  // The vector of environments that need to be set-up/torn-down
+  // before/after the tests are run.
+  std::vector<Environment*> environments_;
+
+  // The vector of TestCases in their original order.  It owns the
+  // elements in the vector.
+  std::vector<TestCase*> test_cases_;
+
+  // Provides a level of indirection for the test case list to allow
+  // easy shuffling and restoring the test case order.  The i-th
+  // element of this vector is the index of the i-th test case in the
+  // shuffled order.
+  std::vector<int> test_case_indices_;
+
+#if GTEST_HAS_PARAM_TEST
+  // ParameterizedTestRegistry object used to register value-parameterized
+  // tests.
+  internal::ParameterizedTestCaseRegistry parameterized_test_registry_;
+
+  // Indicates whether RegisterParameterizedTests() has been called already.
+  bool parameterized_tests_registered_;
+#endif  // GTEST_HAS_PARAM_TEST
+
+  // Index of the last death test case registered.  Initially -1.
+  int last_death_test_case_;
+
+  // This points to the TestCase for the currently running test.  It
+  // changes as Google Test goes through one test case after another.
+  // When no test is running, this is set to NULL and Google Test
+  // stores assertion results in ad_hoc_test_result_.  Initially NULL.
+  TestCase* current_test_case_;
+
+  // This points to the TestInfo for the currently running test.  It
+  // changes as Google Test goes through one test after another.  When
+  // no test is running, this is set to NULL and Google Test stores
+  // assertion results in ad_hoc_test_result_.  Initially NULL.
+  TestInfo* current_test_info_;
+
+  // Normally, a user only writes assertions inside a TEST or TEST_F,
+  // or inside a function called by a TEST or TEST_F.  Since Google
+  // Test keeps track of which test is current running, it can
+  // associate such an assertion with the test it belongs to.
+  //
+  // If an assertion is encountered when no TEST or TEST_F is running,
+  // Google Test attributes the assertion result to an imaginary "ad hoc"
+  // test, and records the result in ad_hoc_test_result_.
+  TestResult ad_hoc_test_result_;
+
+  // The list of event listeners that can be used to track events inside
+  // Google Test.
+  TestEventListeners listeners_;
+
+  // The OS stack trace getter.  Will be deleted when the UnitTest
+  // object is destructed.  By default, an OsStackTraceGetter is used,
+  // but the user can set this field to use a custom getter if that is
+  // desired.
+  OsStackTraceGetterInterface* os_stack_trace_getter_;
+
+  // True iff PostFlagParsingInit() has been called.
+  bool post_flag_parse_init_performed_;
+
+  // The random number seed used at the beginning of the test run.
+  int random_seed_;
+
+  // Our random number generator.
+  internal::Random random_;
+
+  // How long the test took to run, in milliseconds.
+  TimeInMillis elapsed_time_;
+
+#if GTEST_HAS_DEATH_TEST
+  // The decomposed components of the gtest_internal_run_death_test flag,
+  // parsed when RUN_ALL_TESTS is called.
+  internal::scoped_ptr<InternalRunDeathTestFlag> internal_run_death_test_flag_;
+  internal::scoped_ptr<internal::DeathTestFactory> death_test_factory_;
+#endif  // GTEST_HAS_DEATH_TEST
+
+  // A per-thread stack of traces created by the SCOPED_TRACE() macro.
+  internal::ThreadLocal<std::vector<TraceInfo> > gtest_trace_stack_;
+
+  // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests()
+  // starts.
+  bool catch_exceptions_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl);
+};  // class UnitTestImpl
+
+// Convenience function for accessing the global UnitTest
+// implementation object.
+inline UnitTestImpl* GetUnitTestImpl() {
+  return UnitTest::GetInstance()->impl();
+}
+
+#if GTEST_USES_SIMPLE_RE
+
+// Internal helper functions for implementing the simple regular
+// expression matcher.
+GTEST_API_ bool IsInSet(char ch, const char* str);
+GTEST_API_ bool IsAsciiDigit(char ch);
+GTEST_API_ bool IsAsciiPunct(char ch);
+GTEST_API_ bool IsRepeat(char ch);
+GTEST_API_ bool IsAsciiWhiteSpace(char ch);
+GTEST_API_ bool IsAsciiWordChar(char ch);
+GTEST_API_ bool IsValidEscape(char ch);
+GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch);
+GTEST_API_ bool ValidateRegex(const char* regex);
+GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str);
+GTEST_API_ bool MatchRepetitionAndRegexAtHead(
+    bool escaped, char ch, char repeat, const char* regex, const char* str);
+GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str);
+
+#endif  // GTEST_USES_SIMPLE_RE
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.
+GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv);
+GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv);
+
+#if GTEST_HAS_DEATH_TEST
+
+// Returns the message describing the last system error, regardless of the
+// platform.
+GTEST_API_ String GetLastErrnoDescription();
+
+# if GTEST_OS_WINDOWS
+// Provides leak-safe Windows kernel handle ownership.
+class AutoHandle {
+ public:
+  AutoHandle() : handle_(INVALID_HANDLE_VALUE) {}
+  explicit AutoHandle(HANDLE handle) : handle_(handle) {}
+
+  ~AutoHandle() { Reset(); }
+
+  HANDLE Get() const { return handle_; }
+  void Reset() { Reset(INVALID_HANDLE_VALUE); }
+  void Reset(HANDLE handle) {
+    if (handle != handle_) {
+      if (handle_ != INVALID_HANDLE_VALUE)
+        ::CloseHandle(handle_);
+      handle_ = handle;
+    }
+  }
+
+ private:
+  HANDLE handle_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle);
+};
+# endif  // GTEST_OS_WINDOWS
+
+// Attempts to parse a string into a positive integer pointed to by the
+// number parameter.  Returns true if that is possible.
+// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use
+// it here.
+template <typename Integer>
+bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
+  // Fail fast if the given string does not begin with a digit;
+  // this bypasses strtoXXX's "optional leading whitespace and plus
+  // or minus sign" semantics, which are undesirable here.
+  if (str.empty() || !IsDigit(str[0])) {
+    return false;
+  }
+  errno = 0;
+
+  char* end;
+  // BiggestConvertible is the largest integer type that system-provided
+  // string-to-number conversion routines can return.
+
+# if GTEST_OS_WINDOWS && !defined(__GNUC__)
+
+  // MSVC and C++ Builder define __int64 instead of the standard long long.
+  typedef unsigned __int64 BiggestConvertible;
+  const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10);
+
+# else
+
+  typedef unsigned long long BiggestConvertible;  // NOLINT
+  const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10);
+
+# endif  // GTEST_OS_WINDOWS && !defined(__GNUC__)
+
+  const bool parse_success = *end == '\0' && errno == 0;
+
+  // TODO(vladl@google.com): Convert this to compile time assertion when it is
+  // available.
+  GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed));
+
+  const Integer result = static_cast<Integer>(parsed);
+  if (parse_success && static_cast<BiggestConvertible>(result) == parsed) {
+    *number = result;
+    return true;
+  }
+  return false;
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+// TestResult contains some private methods that should be hidden from
+// Google Test user but are required for testing. This class allow our tests
+// to access them.
+//
+// This class is supplied only for the purpose of testing Google Test's own
+// constructs. Do not use it in user tests, either directly or indirectly.
+class TestResultAccessor {
+ public:
+  static void RecordProperty(TestResult* test_result,
+                             const TestProperty& property) {
+    test_result->RecordProperty(property);
+  }
+
+  static void ClearTestPartResults(TestResult* test_result) {
+    test_result->ClearTestPartResults();
+  }
+
+  static const std::vector<testing::TestPartResult>& test_part_results(
+      const TestResult& test_result) {
+    return test_result.test_part_results();
+  }
+};
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_SRC_GTEST_INTERNAL_INL_H_
diff --git a/third_party/googletest/src/src/gtest-port.cc b/third_party/googletest/src/src/gtest-port.cc
new file mode 100644 (file)
index 0000000..b860d48
--- /dev/null
@@ -0,0 +1,746 @@
+// Copyright 2008, 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: wan@google.com (Zhanyong Wan)
+
+#include "gtest/internal/gtest-port.h"
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#if GTEST_OS_WINDOWS_MOBILE
+# include <windows.h>  // For TerminateProcess()
+#elif GTEST_OS_WINDOWS
+# include <io.h>
+# include <sys/stat.h>
+#else
+# include <unistd.h>
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+#if GTEST_OS_MAC
+# include <mach/mach_init.h>
+# include <mach/task.h>
+# include <mach/vm_map.h>
+#endif  // GTEST_OS_MAC
+
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+namespace internal {
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+// MSVC and C++Builder do not provide a definition of STDERR_FILENO.
+const int kStdOutFileno = 1;
+const int kStdErrFileno = 2;
+#else
+const int kStdOutFileno = STDOUT_FILENO;
+const int kStdErrFileno = STDERR_FILENO;
+#endif  // _MSC_VER
+
+#if GTEST_OS_MAC
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+size_t GetThreadCount() {
+  const task_t task = mach_task_self();
+  mach_msg_type_number_t thread_count;
+  thread_act_array_t thread_list;
+  const kern_return_t status = task_threads(task, &thread_list, &thread_count);
+  if (status == KERN_SUCCESS) {
+    // task_threads allocates resources in thread_list and we need to free them
+    // to avoid leaks.
+    vm_deallocate(task,
+                  reinterpret_cast<vm_address_t>(thread_list),
+                  sizeof(thread_t) * thread_count);
+    return static_cast<size_t>(thread_count);
+  } else {
+    return 0;
+  }
+}
+
+#else
+
+size_t GetThreadCount() {
+  // There's no portable way to detect the number of threads, so we just
+  // return 0 to indicate that we cannot detect it.
+  return 0;
+}
+
+#endif  // GTEST_OS_MAC
+
+#if GTEST_USES_POSIX_RE
+
+// Implements RE.  Currently only needed for death tests.
+
+RE::~RE() {
+  if (is_valid_) {
+    // regfree'ing an invalid regex might crash because the content
+    // of the regex is undefined. Since the regex's are essentially
+    // the same, one cannot be valid (or invalid) without the other
+    // being so too.
+    regfree(&partial_regex_);
+    regfree(&full_regex_);
+  }
+  free(const_cast<char*>(pattern_));
+}
+
+// Returns true iff regular expression re matches the entire str.
+bool RE::FullMatch(const char* str, const RE& re) {
+  if (!re.is_valid_) return false;
+
+  regmatch_t match;
+  return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
+}
+
+// Returns true iff regular expression re matches a substring of str
+// (including str itself).
+bool RE::PartialMatch(const char* str, const RE& re) {
+  if (!re.is_valid_) return false;
+
+  regmatch_t match;
+  return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
+}
+
+// Initializes an RE from its string representation.
+void RE::Init(const char* regex) {
+  pattern_ = posix::StrDup(regex);
+
+  // Reserves enough bytes to hold the regular expression used for a
+  // full match.
+  const size_t full_regex_len = strlen(regex) + 10;
+  char* const full_pattern = new char[full_regex_len];
+
+  snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
+  is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
+  // We want to call regcomp(&partial_regex_, ...) even if the
+  // previous expression returns false.  Otherwise partial_regex_ may
+  // not be properly initialized can may cause trouble when it's
+  // freed.
+  //
+  // Some implementation of POSIX regex (e.g. on at least some
+  // versions of Cygwin) doesn't accept the empty string as a valid
+  // regex.  We change it to an equivalent form "()" to be safe.
+  if (is_valid_) {
+    const char* const partial_regex = (*regex == '\0') ? "()" : regex;
+    is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
+  }
+  EXPECT_TRUE(is_valid_)
+      << "Regular expression \"" << regex
+      << "\" is not a valid POSIX Extended regular expression.";
+
+  delete[] full_pattern;
+}
+
+#elif GTEST_USES_SIMPLE_RE
+
+// Returns true iff ch appears anywhere in str (excluding the
+// terminating '\0' character).
+bool IsInSet(char ch, const char* str) {
+  return ch != '\0' && strchr(str, ch) != NULL;
+}
+
+// Returns true iff ch belongs to the given classification.  Unlike
+// similar functions in <ctype.h>, these aren't affected by the
+// current locale.
+bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
+bool IsAsciiPunct(char ch) {
+  return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
+}
+bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
+bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
+bool IsAsciiWordChar(char ch) {
+  return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
+      ('0' <= ch && ch <= '9') || ch == '_';
+}
+
+// Returns true iff "\\c" is a supported escape sequence.
+bool IsValidEscape(char c) {
+  return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
+}
+
+// Returns true iff the given atom (specified by escaped and pattern)
+// matches ch.  The result is undefined if the atom is invalid.
+bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
+  if (escaped) {  // "\\p" where p is pattern_char.
+    switch (pattern_char) {
+      case 'd': return IsAsciiDigit(ch);
+      case 'D': return !IsAsciiDigit(ch);
+      case 'f': return ch == '\f';
+      case 'n': return ch == '\n';
+      case 'r': return ch == '\r';
+      case 's': return IsAsciiWhiteSpace(ch);
+      case 'S': return !IsAsciiWhiteSpace(ch);
+      case 't': return ch == '\t';
+      case 'v': return ch == '\v';
+      case 'w': return IsAsciiWordChar(ch);
+      case 'W': return !IsAsciiWordChar(ch);
+    }
+    return IsAsciiPunct(pattern_char) && pattern_char == ch;
+  }
+
+  return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
+}
+
+// Helper function used by ValidateRegex() to format error messages.
+String FormatRegexSyntaxError(const char* regex, int index) {
+  return (Message() << "Syntax error at index " << index
+          << " in simple regular expression \"" << regex << "\": ").GetString();
+}
+
+// Generates non-fatal failures and returns false if regex is invalid;
+// otherwise returns true.
+bool ValidateRegex(const char* regex) {
+  if (regex == NULL) {
+    // TODO(wan@google.com): fix the source file location in the
+    // assertion failures to match where the regex is used in user
+    // code.
+    ADD_FAILURE() << "NULL is not a valid simple regular expression.";
+    return false;
+  }
+
+  bool is_valid = true;
+
+  // True iff ?, *, or + can follow the previous atom.
+  bool prev_repeatable = false;
+  for (int i = 0; regex[i]; i++) {
+    if (regex[i] == '\\') {  // An escape sequence
+      i++;
+      if (regex[i] == '\0') {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
+                      << "'\\' cannot appear at the end.";
+        return false;
+      }
+
+      if (!IsValidEscape(regex[i])) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
+                      << "invalid escape sequence \"\\" << regex[i] << "\".";
+        is_valid = false;
+      }
+      prev_repeatable = true;
+    } else {  // Not an escape sequence.
+      const char ch = regex[i];
+
+      if (ch == '^' && i > 0) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'^' can only appear at the beginning.";
+        is_valid = false;
+      } else if (ch == '$' && regex[i + 1] != '\0') {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'$' can only appear at the end.";
+        is_valid = false;
+      } else if (IsInSet(ch, "()[]{}|")) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'" << ch << "' is unsupported.";
+        is_valid = false;
+      } else if (IsRepeat(ch) && !prev_repeatable) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'" << ch << "' can only follow a repeatable token.";
+        is_valid = false;
+      }
+
+      prev_repeatable = !IsInSet(ch, "^$?*+");
+    }
+  }
+
+  return is_valid;
+}
+
+// Matches a repeated regex atom followed by a valid simple regular
+// expression.  The regex atom is defined as c if escaped is false,
+// or \c otherwise.  repeat is the repetition meta character (?, *,
+// or +).  The behavior is undefined if str contains too many
+// characters to be indexable by size_t, in which case the test will
+// probably time out anyway.  We are fine with this limitation as
+// std::string has it too.
+bool MatchRepetitionAndRegexAtHead(
+    bool escaped, char c, char repeat, const char* regex,
+    const char* str) {
+  const size_t min_count = (repeat == '+') ? 1 : 0;
+  const size_t max_count = (repeat == '?') ? 1 :
+      static_cast<size_t>(-1) - 1;
+  // We cannot call numeric_limits::max() as it conflicts with the
+  // max() macro on Windows.
+
+  for (size_t i = 0; i <= max_count; ++i) {
+    // We know that the atom matches each of the first i characters in str.
+    if (i >= min_count && MatchRegexAtHead(regex, str + i)) {
+      // We have enough matches at the head, and the tail matches too.
+      // Since we only care about *whether* the pattern matches str
+      // (as opposed to *how* it matches), there is no need to find a
+      // greedy match.
+      return true;
+    }
+    if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i]))
+      return false;
+  }
+  return false;
+}
+
+// Returns true iff regex matches a prefix of str.  regex must be a
+// valid simple regular expression and not start with "^", or the
+// result is undefined.
+bool MatchRegexAtHead(const char* regex, const char* str) {
+  if (*regex == '\0')  // An empty regex matches a prefix of anything.
+    return true;
+
+  // "$" only matches the end of a string.  Note that regex being
+  // valid guarantees that there's nothing after "$" in it.
+  if (*regex == '$')
+    return *str == '\0';
+
+  // Is the first thing in regex an escape sequence?
+  const bool escaped = *regex == '\\';
+  if (escaped)
+    ++regex;
+  if (IsRepeat(regex[1])) {
+    // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
+    // here's an indirect recursion.  It terminates as the regex gets
+    // shorter in each recursion.
+    return MatchRepetitionAndRegexAtHead(
+        escaped, regex[0], regex[1], regex + 2, str);
+  } else {
+    // regex isn't empty, isn't "$", and doesn't start with a
+    // repetition.  We match the first atom of regex with the first
+    // character of str and recurse.
+    return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
+        MatchRegexAtHead(regex + 1, str + 1);
+  }
+}
+
+// Returns true iff regex matches any substring of str.  regex must be
+// a valid simple regular expression, or the result is undefined.
+//
+// The algorithm is recursive, but the recursion depth doesn't exceed
+// the regex length, so we won't need to worry about running out of
+// stack space normally.  In rare cases the time complexity can be
+// exponential with respect to the regex length + the string length,
+// but usually it's must faster (often close to linear).
+bool MatchRegexAnywhere(const char* regex, const char* str) {
+  if (regex == NULL || str == NULL)
+    return false;
+
+  if (*regex == '^')
+    return MatchRegexAtHead(regex + 1, str);
+
+  // A successful match can be anywhere in str.
+  do {
+    if (MatchRegexAtHead(regex, str))
+      return true;
+  } while (*str++ != '\0');
+  return false;
+}
+
+// Implements the RE class.
+
+RE::~RE() {
+  free(const_cast<char*>(pattern_));
+  free(const_cast<char*>(full_pattern_));
+}
+
+// Returns true iff regular expression re matches the entire str.
+bool RE::FullMatch(const char* str, const RE& re) {
+  return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
+}
+
+// Returns true iff regular expression re matches a substring of str
+// (including str itself).
+bool RE::PartialMatch(const char* str, const RE& re) {
+  return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
+}
+
+// Initializes an RE from its string representation.
+void RE::Init(const char* regex) {
+  pattern_ = full_pattern_ = NULL;
+  if (regex != NULL) {
+    pattern_ = posix::StrDup(regex);
+  }
+
+  is_valid_ = ValidateRegex(regex);
+  if (!is_valid_) {
+    // No need to calculate the full pattern when the regex is invalid.
+    return;
+  }
+
+  const size_t len = strlen(regex);
+  // Reserves enough bytes to hold the regular expression used for a
+  // full match: we need space to prepend a '^', append a '$', and
+  // terminate the string with '\0'.
+  char* buffer = static_cast<char*>(malloc(len + 3));
+  full_pattern_ = buffer;
+
+  if (*regex != '^')
+    *buffer++ = '^';  // Makes sure full_pattern_ starts with '^'.
+
+  // We don't use snprintf or strncpy, as they trigger a warning when
+  // compiled with VC++ 8.0.
+  memcpy(buffer, regex, len);
+  buffer += len;
+
+  if (len == 0 || regex[len - 1] != '$')
+    *buffer++ = '$';  // Makes sure full_pattern_ ends with '$'.
+
+  *buffer = '\0';
+}
+
+#endif  // GTEST_USES_POSIX_RE
+
+const char kUnknownFile[] = "unknown file";
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
+  const char* const file_name = file == NULL ? kUnknownFile : file;
+
+  if (line < 0) {
+    return String::Format("%s:", file_name).c_str();
+  }
+#ifdef _MSC_VER
+  return String::Format("%s(%d):", file_name, line).c_str();
+#else
+  return String::Format("%s:%d:", file_name, line).c_str();
+#endif  // _MSC_VER
+}
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+// Note that FormatCompilerIndependentFileLocation() does NOT append colon
+// to the file location it produces, unlike FormatFileLocation().
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
+    const char* file, int line) {
+  const char* const file_name = file == NULL ? kUnknownFile : file;
+
+  if (line < 0)
+    return file_name;
+  else
+    return String::Format("%s:%d", file_name, line).c_str();
+}
+
+
+GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
+    : severity_(severity) {
+  const char* const marker =
+      severity == GTEST_INFO ?    "[  INFO ]" :
+      severity == GTEST_WARNING ? "[WARNING]" :
+      severity == GTEST_ERROR ?   "[ ERROR ]" : "[ FATAL ]";
+  GetStream() << ::std::endl << marker << " "
+              << FormatFileLocation(file, line).c_str() << ": ";
+}
+
+// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
+GTestLog::~GTestLog() {
+  GetStream() << ::std::endl;
+  if (severity_ == GTEST_FATAL) {
+    fflush(stderr);
+    posix::Abort();
+  }
+}
+// Disable Microsoft deprecation warnings for POSIX functions called from
+// this class (creat, dup, dup2, and close)
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4996)
+#endif  // _MSC_VER
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Object that captures an output stream (stdout/stderr).
+class CapturedStream {
+ public:
+  // The ctor redirects the stream to a temporary file.
+  CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
+
+# if GTEST_OS_WINDOWS
+    char temp_dir_path[MAX_PATH + 1] = { '\0' };  // NOLINT
+    char temp_file_path[MAX_PATH + 1] = { '\0' };  // NOLINT
+
+    ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
+    const UINT success = ::GetTempFileNameA(temp_dir_path,
+                                            "gtest_redir",
+                                            0,  // Generate unique file name.
+                                            temp_file_path);
+    GTEST_CHECK_(success != 0)
+        << "Unable to create a temporary file in " << temp_dir_path;
+    const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
+    GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
+                                    << temp_file_path;
+    filename_ = temp_file_path;
+# else
+    // There's no guarantee that a test has write access to the
+    // current directory, so we create the temporary file in the /tmp
+    // directory instead.
+    char name_template[] = "/tmp/captured_stream.XXXXXX";
+    const int captured_fd = mkstemp(name_template);
+    filename_ = name_template;
+# endif  // GTEST_OS_WINDOWS
+    fflush(NULL);
+    dup2(captured_fd, fd_);
+    close(captured_fd);
+  }
+
+  ~CapturedStream() {
+    remove(filename_.c_str());
+  }
+
+  String GetCapturedString() {
+    if (uncaptured_fd_ != -1) {
+      // Restores the original stream.
+      fflush(NULL);
+      dup2(uncaptured_fd_, fd_);
+      close(uncaptured_fd_);
+      uncaptured_fd_ = -1;
+    }
+
+    FILE* const file = posix::FOpen(filename_.c_str(), "r");
+    const String content = ReadEntireFile(file);
+    posix::FClose(file);
+    return content;
+  }
+
+ private:
+  // Reads the entire content of a file as a String.
+  static String ReadEntireFile(FILE* file);
+
+  // Returns the size (in bytes) of a file.
+  static size_t GetFileSize(FILE* file);
+
+  const int fd_;  // A stream to capture.
+  int uncaptured_fd_;
+  // Name of the temporary file holding the stderr output.
+  ::std::string filename_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
+};
+
+// Returns the size (in bytes) of a file.
+size_t CapturedStream::GetFileSize(FILE* file) {
+  fseek(file, 0, SEEK_END);
+  return static_cast<size_t>(ftell(file));
+}
+
+// Reads the entire content of a file as a string.
+String CapturedStream::ReadEntireFile(FILE* file) {
+  const size_t file_size = GetFileSize(file);
+  char* const buffer = new char[file_size];
+
+  size_t bytes_last_read = 0;  // # of bytes read in the last fread()
+  size_t bytes_read = 0;       // # of bytes read so far
+
+  fseek(file, 0, SEEK_SET);
+
+  // Keeps reading the file until we cannot read further or the
+  // pre-determined file size is reached.
+  do {
+    bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
+    bytes_read += bytes_last_read;
+  } while (bytes_last_read > 0 && bytes_read < file_size);
+
+  const String content(buffer, bytes_read);
+  delete[] buffer;
+
+  return content;
+}
+
+# ifdef _MSC_VER
+#  pragma warning(pop)
+# endif  // _MSC_VER
+
+static CapturedStream* g_captured_stderr = NULL;
+static CapturedStream* g_captured_stdout = NULL;
+
+// Starts capturing an output stream (stdout/stderr).
+void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) {
+  if (*stream != NULL) {
+    GTEST_LOG_(FATAL) << "Only one " << stream_name
+                      << " capturer can exist at a time.";
+  }
+  *stream = new CapturedStream(fd);
+}
+
+// Stops capturing the output stream and returns the captured string.
+String GetCapturedStream(CapturedStream** captured_stream) {
+  const String content = (*captured_stream)->GetCapturedString();
+
+  delete *captured_stream;
+  *captured_stream = NULL;
+
+  return content;
+}
+
+// Starts capturing stdout.
+void CaptureStdout() {
+  CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
+}
+
+// Starts capturing stderr.
+void CaptureStderr() {
+  CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr);
+}
+
+// Stops capturing stdout and returns the captured string.
+String GetCapturedStdout() { return GetCapturedStream(&g_captured_stdout); }
+
+// Stops capturing stderr and returns the captured string.
+String GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); }
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+#if GTEST_HAS_DEATH_TEST
+
+// A copy of all command line arguments.  Set by InitGoogleTest().
+::std::vector<String> g_argvs;
+
+// Returns the command line as a vector of strings.
+const ::std::vector<String>& GetArgvs() { return g_argvs; }
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+#if GTEST_OS_WINDOWS_MOBILE
+namespace posix {
+void Abort() {
+  DebugBreak();
+  TerminateProcess(GetCurrentProcess(), 1);
+}
+}  // namespace posix
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Returns the name of the environment variable corresponding to the
+// given flag.  For example, FlagToEnvVar("foo") will return
+// "GTEST_FOO" in the open-source version.
+static String FlagToEnvVar(const char* flag) {
+  const String full_flag =
+      (Message() << GTEST_FLAG_PREFIX_ << flag).GetString();
+
+  Message env_var;
+  for (size_t i = 0; i != full_flag.length(); i++) {
+    env_var << ToUpper(full_flag.c_str()[i]);
+  }
+
+  return env_var.GetString();
+}
+
+// Parses 'str' for a 32-bit signed integer.  If successful, writes
+// the result to *value and returns true; otherwise leaves *value
+// unchanged and returns false.
+bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
+  // Parses the environment variable as a decimal integer.
+  char* end = NULL;
+  const long long_value = strtol(str, &end, 10);  // NOLINT
+
+  // Has strtol() consumed all characters in the string?
+  if (*end != '\0') {
+    // No - an invalid character was encountered.
+    Message msg;
+    msg << "WARNING: " << src_text
+        << " is expected to be a 32-bit integer, but actually"
+        << " has value \"" << str << "\".\n";
+    printf("%s", msg.GetString().c_str());
+    fflush(stdout);
+    return false;
+  }
+
+  // Is the parsed value in the range of an Int32?
+  const Int32 result = static_cast<Int32>(long_value);
+  if (long_value == LONG_MAX || long_value == LONG_MIN ||
+      // The parsed value overflows as a long.  (strtol() returns
+      // LONG_MAX or LONG_MIN when the input overflows.)
+      result != long_value
+      // The parsed value overflows as an Int32.
+      ) {
+    Message msg;
+    msg << "WARNING: " << src_text
+        << " is expected to be a 32-bit integer, but actually"
+        << " has value " << str << ", which overflows.\n";
+    printf("%s", msg.GetString().c_str());
+    fflush(stdout);
+    return false;
+  }
+
+  *value = result;
+  return true;
+}
+
+// Reads and returns the Boolean environment variable corresponding to
+// the given flag; if it's not set, returns default_value.
+//
+// The value is considered true iff it's not "0".
+bool BoolFromGTestEnv(const char* flag, bool default_value) {
+  const String env_var = FlagToEnvVar(flag);
+  const char* const string_value = posix::GetEnv(env_var.c_str());
+  return string_value == NULL ?
+      default_value : strcmp(string_value, "0") != 0;
+}
+
+// Reads and returns a 32-bit integer stored in the environment
+// variable corresponding to the given flag; if it isn't set or
+// doesn't represent a valid 32-bit integer, returns default_value.
+Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
+  const String env_var = FlagToEnvVar(flag);
+  const char* const string_value = posix::GetEnv(env_var.c_str());
+  if (string_value == NULL) {
+    // The environment variable is not set.
+    return default_value;
+  }
+
+  Int32 result = default_value;
+  if (!ParseInt32(Message() << "Environment variable " << env_var,
+                  string_value, &result)) {
+    printf("The default value %s is used.\n",
+           (Message() << default_value).GetString().c_str());
+    fflush(stdout);
+    return default_value;
+  }
+
+  return result;
+}
+
+// Reads and returns the string environment variable corresponding to
+// the given flag; if it's not set, returns default_value.
+const char* StringFromGTestEnv(const char* flag, const char* default_value) {
+  const String env_var = FlagToEnvVar(flag);
+  const char* const value = posix::GetEnv(env_var.c_str());
+  return value == NULL ? default_value : value;
+}
+
+}  // namespace internal
+}  // namespace testing
diff --git a/third_party/googletest/src/src/gtest-printers.cc b/third_party/googletest/src/src/gtest-printers.cc
new file mode 100644 (file)
index 0000000..ed63c7b
--- /dev/null
@@ -0,0 +1,356 @@
+// Copyright 2007, 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: wan@google.com (Zhanyong Wan)
+
+// Google Test - The Google C++ Testing Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+//   void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// It uses the << operator when possible, and prints the bytes in the
+// object otherwise.  A user can override its behavior for a class
+// type Foo by defining either operator<<(::std::ostream&, const Foo&)
+// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
+// defines Foo.
+
+#include "gtest/gtest-printers.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <ostream>  // NOLINT
+#include <string>
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+
+namespace {
+
+using ::std::ostream;
+
+#if GTEST_OS_WINDOWS_MOBILE  // Windows CE does not define _snprintf_s.
+# define snprintf _snprintf
+#elif _MSC_VER >= 1400  // VC 8.0 and later deprecate snprintf and _snprintf.
+# define snprintf _snprintf_s
+#elif _MSC_VER
+# define snprintf _snprintf
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Prints a segment of bytes in the given object.
+void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
+                                size_t count, ostream* os) {
+  char text[5] = "";
+  for (size_t i = 0; i != count; i++) {
+    const size_t j = start + i;
+    if (i != 0) {
+      // Organizes the bytes into groups of 2 for easy parsing by
+      // human.
+      if ((j % 2) == 0)
+        *os << ' ';
+      else
+        *os << '-';
+    }
+    snprintf(text, sizeof(text), "%02X", obj_bytes[j]);
+    *os << text;
+  }
+}
+
+// Prints the bytes in the given value to the given ostream.
+void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
+                              ostream* os) {
+  // Tells the user how big the object is.
+  *os << count << "-byte object <";
+
+  const size_t kThreshold = 132;
+  const size_t kChunkSize = 64;
+  // If the object size is bigger than kThreshold, we'll have to omit
+  // some details by printing only the first and the last kChunkSize
+  // bytes.
+  // TODO(wan): let the user control the threshold using a flag.
+  if (count < kThreshold) {
+    PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
+  } else {
+    PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
+    *os << " ... ";
+    // Rounds up to 2-byte boundary.
+    const size_t resume_pos = (count - kChunkSize + 1)/2*2;
+    PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
+  }
+  *os << ">";
+}
+
+}  // namespace
+
+namespace internal2 {
+
+// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
+// given object.  The delegation simplifies the implementation, which
+// uses the << operator and thus is easier done outside of the
+// ::testing::internal namespace, which contains a << operator that
+// sometimes conflicts with the one in STL.
+void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
+                          ostream* os) {
+  PrintBytesInObjectToImpl(obj_bytes, count, os);
+}
+
+}  // namespace internal2
+
+namespace internal {
+
+// Depending on the value of a char (or wchar_t), we print it in one
+// of three formats:
+//   - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
+//   - as a hexidecimal escape sequence (e.g. '\x7F'), or
+//   - as a special escape sequence (e.g. '\r', '\n').
+enum CharFormat {
+  kAsIs,
+  kHexEscape,
+  kSpecialEscape
+};
+
+// Returns true if c is a printable ASCII character.  We test the
+// value of c directly instead of calling isprint(), which is buggy on
+// Windows Mobile.
+inline bool IsPrintableAscii(wchar_t c) {
+  return 0x20 <= c && c <= 0x7E;
+}
+
+// Prints a wide or narrow char c as a character literal without the
+// quotes, escaping it when necessary; returns how c was formatted.
+// The template argument UnsignedChar is the unsigned version of Char,
+// which is the type of c.
+template <typename UnsignedChar, typename Char>
+static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
+  switch (static_cast<wchar_t>(c)) {
+    case L'\0':
+      *os << "\\0";
+      break;
+    case L'\'':
+      *os << "\\'";
+      break;
+    case L'\\':
+      *os << "\\\\";
+      break;
+    case L'\a':
+      *os << "\\a";
+      break;
+    case L'\b':
+      *os << "\\b";
+      break;
+    case L'\f':
+      *os << "\\f";
+      break;
+    case L'\n':
+      *os << "\\n";
+      break;
+    case L'\r':
+      *os << "\\r";
+      break;
+    case L'\t':
+      *os << "\\t";
+      break;
+    case L'\v':
+      *os << "\\v";
+      break;
+    default:
+      if (IsPrintableAscii(c)) {
+        *os << static_cast<char>(c);
+        return kAsIs;
+      } else {
+        *os << String::Format("\\x%X", static_cast<UnsignedChar>(c));
+        return kHexEscape;
+      }
+  }
+  return kSpecialEscape;
+}
+
+// Prints a char c as if it's part of a string literal, escaping it when
+// necessary; returns how c was formatted.
+static CharFormat PrintAsWideStringLiteralTo(wchar_t c, ostream* os) {
+  switch (c) {
+    case L'\'':
+      *os << "'";
+      return kAsIs;
+    case L'"':
+      *os << "\\\"";
+      return kSpecialEscape;
+    default:
+      return PrintAsCharLiteralTo<wchar_t>(c, os);
+  }
+}
+
+// Prints a char c as if it's part of a string literal, escaping it when
+// necessary; returns how c was formatted.
+static CharFormat PrintAsNarrowStringLiteralTo(char c, ostream* os) {
+  return PrintAsWideStringLiteralTo(static_cast<unsigned char>(c), os);
+}
+
+// Prints a wide or narrow character c and its code.  '\0' is printed
+// as "'\\0'", other unprintable characters are also properly escaped
+// using the standard C++ escape sequence.  The template argument
+// UnsignedChar is the unsigned version of Char, which is the type of c.
+template <typename UnsignedChar, typename Char>
+void PrintCharAndCodeTo(Char c, ostream* os) {
+  // First, print c as a literal in the most readable form we can find.
+  *os << ((sizeof(c) > 1) ? "L'" : "'");
+  const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os);
+  *os << "'";
+
+  // To aid user debugging, we also print c's code in decimal, unless
+  // it's 0 (in which case c was printed as '\\0', making the code
+  // obvious).
+  if (c == 0)
+    return;
+  *os << " (" << String::Format("%d", c).c_str();
+
+  // For more convenience, we print c's code again in hexidecimal,
+  // unless c was already printed in the form '\x##' or the code is in
+  // [1, 9].
+  if (format == kHexEscape || (1 <= c && c <= 9)) {
+    // Do nothing.
+  } else {
+    *os << String::Format(", 0x%X",
+                          static_cast<UnsignedChar>(c)).c_str();
+  }
+  *os << ")";
+}
+
+void PrintTo(unsigned char c, ::std::ostream* os) {
+  PrintCharAndCodeTo<unsigned char>(c, os);
+}
+void PrintTo(signed char c, ::std::ostream* os) {
+  PrintCharAndCodeTo<unsigned char>(c, os);
+}
+
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its code.  L'\0' is printed as "L'\\0'".
+void PrintTo(wchar_t wc, ostream* os) {
+  PrintCharAndCodeTo<wchar_t>(wc, os);
+}
+
+// Prints the given array of characters to the ostream.
+// The array starts at *begin, the length is len, it may include '\0' characters
+// and may not be null-terminated.
+static void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) {
+  *os << "\"";
+  bool is_previous_hex = false;
+  for (size_t index = 0; index < len; ++index) {
+    const char cur = begin[index];
+    if (is_previous_hex && IsXDigit(cur)) {
+      // Previous character is of '\x..' form and this character can be
+      // interpreted as another hexadecimal digit in its number. Break string to
+      // disambiguate.
+      *os << "\" \"";
+    }
+    is_previous_hex = PrintAsNarrowStringLiteralTo(cur, os) == kHexEscape;
+  }
+  *os << "\"";
+}
+
+// Prints a (const) char array of 'len' elements, starting at address 'begin'.
+void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
+  PrintCharsAsStringTo(begin, len, os);
+}
+
+// Prints the given array of wide characters to the ostream.
+// The array starts at *begin, the length is len, it may include L'\0'
+// characters and may not be null-terminated.
+static void PrintWideCharsAsStringTo(const wchar_t* begin, size_t len,
+                                     ostream* os) {
+  *os << "L\"";
+  bool is_previous_hex = false;
+  for (size_t index = 0; index < len; ++index) {
+    const wchar_t cur = begin[index];
+    if (is_previous_hex && isascii(cur) && IsXDigit(static_cast<char>(cur))) {
+      // Previous character is of '\x..' form and this character can be
+      // interpreted as another hexadecimal digit in its number. Break string to
+      // disambiguate.
+      *os << "\" L\"";
+    }
+    is_previous_hex = PrintAsWideStringLiteralTo(cur, os) == kHexEscape;
+  }
+  *os << "\"";
+}
+
+// Prints the given C string to the ostream.
+void PrintTo(const char* s, ostream* os) {
+  if (s == NULL) {
+    *os << "NULL";
+  } else {
+    *os << ImplicitCast_<const void*>(s) << " pointing to ";
+    PrintCharsAsStringTo(s, strlen(s), os);
+  }
+}
+
+// MSVC compiler can be configured to define whar_t as a typedef
+// of unsigned short. Defining an overload for const wchar_t* in that case
+// would cause pointers to unsigned shorts be printed as wide strings,
+// possibly accessing more memory than intended and causing invalid
+// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
+// wchar_t is implemented as a native type.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Prints the given wide C string to the ostream.
+void PrintTo(const wchar_t* s, ostream* os) {
+  if (s == NULL) {
+    *os << "NULL";
+  } else {
+    *os << ImplicitCast_<const void*>(s) << " pointing to ";
+    PrintWideCharsAsStringTo(s, wcslen(s), os);
+  }
+}
+#endif  // wchar_t is native
+
+// Prints a ::string object.
+#if GTEST_HAS_GLOBAL_STRING
+void PrintStringTo(const ::string& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+void PrintStringTo(const ::std::string& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+
+// Prints a ::wstring object.
+#if GTEST_HAS_GLOBAL_WSTRING
+void PrintWideStringTo(const ::wstring& s, ostream* os) {
+  PrintWideCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+#if GTEST_HAS_STD_WSTRING
+void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
+  PrintWideCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+}  // namespace internal
+
+}  // namespace testing
diff --git a/third_party/googletest/src/src/gtest-test-part.cc b/third_party/googletest/src/src/gtest-test-part.cc
new file mode 100644 (file)
index 0000000..5ddc67c
--- /dev/null
@@ -0,0 +1,110 @@
+// Copyright 2008, 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: mheule@google.com (Markus Heule)
+//
+// The Google C++ Testing Framework (Google Test)
+
+#include "gtest/gtest-test-part.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+
+using internal::GetUnitTestImpl;
+
+// Gets the summary of the failure message by omitting the stack trace
+// in it.
+internal::String TestPartResult::ExtractSummary(const char* message) {
+  const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
+  return stack_trace == NULL ? internal::String(message) :
+      internal::String(message, stack_trace - message);
+}
+
+// Prints a TestPartResult object.
+std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
+  return os
+      << result.file_name() << ":" << result.line_number() << ": "
+      << (result.type() == TestPartResult::kSuccess ? "Success" :
+          result.type() == TestPartResult::kFatalFailure ? "Fatal failure" :
+          "Non-fatal failure") << ":\n"
+      << result.message() << std::endl;
+}
+
+// Appends a TestPartResult to the array.
+void TestPartResultArray::Append(const TestPartResult& result) {
+  array_.push_back(result);
+}
+
+// Returns the TestPartResult at the given index (0-based).
+const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
+  if (index < 0 || index >= size()) {
+    printf("\nInvalid index (%d) into TestPartResultArray.\n", index);
+    internal::posix::Abort();
+  }
+
+  return array_[index];
+}
+
+// Returns the number of TestPartResult objects in the array.
+int TestPartResultArray::size() const {
+  return static_cast<int>(array_.size());
+}
+
+namespace internal {
+
+HasNewFatalFailureHelper::HasNewFatalFailureHelper()
+    : has_new_fatal_failure_(false),
+      original_reporter_(GetUnitTestImpl()->
+                         GetTestPartResultReporterForCurrentThread()) {
+  GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this);
+}
+
+HasNewFatalFailureHelper::~HasNewFatalFailureHelper() {
+  GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(
+      original_reporter_);
+}
+
+void HasNewFatalFailureHelper::ReportTestPartResult(
+    const TestPartResult& result) {
+  if (result.fatally_failed())
+    has_new_fatal_failure_ = true;
+  original_reporter_->ReportTestPartResult(result);
+}
+
+}  // namespace internal
+
+}  // namespace testing
diff --git a/third_party/googletest/src/src/gtest-typed-test.cc b/third_party/googletest/src/src/gtest-typed-test.cc
new file mode 100644 (file)
index 0000000..a5cc88f
--- /dev/null
@@ -0,0 +1,110 @@
+// Copyright 2008 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: wan@google.com (Zhanyong Wan)
+
+#include "gtest/gtest-typed-test.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+namespace internal {
+
+#if GTEST_HAS_TYPED_TEST_P
+
+// Skips to the first non-space char in str. Returns an empty string if str
+// contains only whitespace characters.
+static const char* SkipSpaces(const char* str) {
+  while (IsSpace(*str))
+    str++;
+  return str;
+}
+
+// Verifies that registered_tests match the test names in
+// defined_test_names_; returns registered_tests if successful, or
+// aborts the program otherwise.
+const char* TypedTestCasePState::VerifyRegisteredTestNames(
+    const char* file, int line, const char* registered_tests) {
+  typedef ::std::set<const char*>::const_iterator DefinedTestIter;
+  registered_ = true;
+
+  // Skip initial whitespace in registered_tests since some
+  // preprocessors prefix stringizied literals with whitespace.
+  registered_tests = SkipSpaces(registered_tests);
+
+  Message errors;
+  ::std::set<String> tests;
+  for (const char* names = registered_tests; names != NULL;
+       names = SkipComma(names)) {
+    const String name = GetPrefixUntilComma(names);
+    if (tests.count(name) != 0) {
+      errors << "Test " << name << " is listed more than once.\n";
+      continue;
+    }
+
+    bool found = false;
+    for (DefinedTestIter it = defined_test_names_.begin();
+         it != defined_test_names_.end();
+         ++it) {
+      if (name == *it) {
+        found = true;
+        break;
+      }
+    }
+
+    if (found) {
+      tests.insert(name);
+    } else {
+      errors << "No test named " << name
+             << " can be found in this test case.\n";
+    }
+  }
+
+  for (DefinedTestIter it = defined_test_names_.begin();
+       it != defined_test_names_.end();
+       ++it) {
+    if (tests.count(*it) == 0) {
+      errors << "You forgot to list test " << *it << ".\n";
+    }
+  }
+
+  const String& errors_str = errors.GetString();
+  if (errors_str != "") {
+    fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
+            errors_str.c_str());
+    fflush(stderr);
+    posix::Abort();
+  }
+
+  return registered_tests;
+}
+
+#endif  // GTEST_HAS_TYPED_TEST_P
+
+}  // namespace internal
+}  // namespace testing
diff --git a/third_party/googletest/src/src/gtest.cc b/third_party/googletest/src/src/gtest.cc
new file mode 100644 (file)
index 0000000..904d9d7
--- /dev/null
@@ -0,0 +1,4898 @@
+// Copyright 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: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
+
+#include <ctype.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include <algorithm>
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <vector>
+
+#if GTEST_OS_LINUX
+
+// TODO(kenton@google.com): Use autoconf to detect availability of
+// gettimeofday().
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+
+# include <fcntl.h>  // NOLINT
+# include <limits.h>  // NOLINT
+# include <sched.h>  // NOLINT
+// Declares vsnprintf().  This header is not available on Windows.
+# include <strings.h>  // NOLINT
+# include <sys/mman.h>  // NOLINT
+# include <sys/time.h>  // NOLINT
+# include <unistd.h>  // NOLINT
+# include <string>
+
+#elif GTEST_OS_SYMBIAN
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h>  // NOLINT
+
+#elif GTEST_OS_ZOS
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h>  // NOLINT
+
+// On z/OS we additionally need strings.h for strcasecmp.
+# include <strings.h>  // NOLINT
+
+#elif GTEST_OS_WINDOWS_MOBILE  // We are on Windows CE.
+
+# include <windows.h>  // NOLINT
+
+#elif GTEST_OS_WINDOWS  // We are on Windows proper.
+
+# include <io.h>  // NOLINT
+# include <sys/timeb.h>  // NOLINT
+# include <sys/types.h>  // NOLINT
+# include <sys/stat.h>  // NOLINT
+
+# if GTEST_OS_WINDOWS_MINGW
+// MinGW has gettimeofday() but not _ftime64().
+// TODO(kenton@google.com): Use autoconf to detect availability of
+//   gettimeofday().
+// TODO(kenton@google.com): There are other ways to get the time on
+//   Windows, like GetTickCount() or GetSystemTimeAsFileTime().  MinGW
+//   supports these.  consider using them instead.
+#  define GTEST_HAS_GETTIMEOFDAY_ 1
+#  include <sys/time.h>  // NOLINT
+# endif  // GTEST_OS_WINDOWS_MINGW
+
+// cpplint thinks that the header is already included, so we want to
+// silence it.
+# include <windows.h>  // NOLINT
+
+#else
+
+// Assume other platforms have gettimeofday().
+// TODO(kenton@google.com): Use autoconf to detect availability of
+//   gettimeofday().
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+
+// cpplint thinks that the header is already included, so we want to
+// silence it.
+# include <sys/time.h>  // NOLINT
+# include <unistd.h>  // NOLINT
+
+#endif  // GTEST_OS_LINUX
+
+#if GTEST_HAS_EXCEPTIONS
+# include <stdexcept>
+#endif
+
+#if GTEST_CAN_STREAM_RESULTS_
+# include <arpa/inet.h>  // NOLINT
+# include <netdb.h>  // NOLINT
+#endif
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+#if GTEST_OS_WINDOWS
+# define vsnprintf _vsnprintf
+#endif  // GTEST_OS_WINDOWS
+
+namespace testing {
+
+using internal::CountIf;
+using internal::ForEach;
+using internal::GetElementOr;
+using internal::Shuffle;
+
+// Constants.
+
+// A test whose test case name or test name matches this filter is
+// disabled and not run.
+static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*";
+
+// A test case whose name matches this filter is considered a death
+// test case and will be run before test cases whose name doesn't
+// match this filter.
+static const char kDeathTestCaseFilter[] = "*DeathTest:*DeathTest/*";
+
+// A test filter that matches everything.
+static const char kUniversalFilter[] = "*";
+
+// The default output file for XML output.
+static const char kDefaultOutputFile[] = "test_detail.xml";
+
+// The environment variable name for the test shard index.
+static const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
+// The environment variable name for the total number of test shards.
+static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
+// The environment variable name for the test shard status file.
+static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE";
+
+namespace internal {
+
+// The text used in failure messages to indicate the start of the
+// stack trace.
+const char kStackTraceMarker[] = "\nStack trace:\n";
+
+// g_help_flag is true iff the --help flag or an equivalent form is
+// specified on the command line.
+bool g_help_flag = false;
+
+}  // namespace internal
+
+GTEST_DEFINE_bool_(
+    also_run_disabled_tests,
+    internal::BoolFromGTestEnv("also_run_disabled_tests", false),
+    "Run disabled tests too, in addition to the tests normally being run.");
+
+GTEST_DEFINE_bool_(
+    break_on_failure,
+    internal::BoolFromGTestEnv("break_on_failure", false),
+    "True iff a failed assertion should be a debugger break-point.");
+
+GTEST_DEFINE_bool_(
+    catch_exceptions,
+    internal::BoolFromGTestEnv("catch_exceptions", true),
+    "True iff " GTEST_NAME_
+    " should catch exceptions and treat them as test failures.");
+
+GTEST_DEFINE_string_(
+    color,
+    internal::StringFromGTestEnv("color", "auto"),
+    "Whether to use colors in the output.  Valid values: yes, no, "
+    "and auto.  'auto' means to use colors if the output is "
+    "being sent to a terminal and the TERM environment variable "
+    "is set to xterm, xterm-color, xterm-256color, linux or cygwin.");
+
+GTEST_DEFINE_string_(
+    filter,
+    internal::StringFromGTestEnv("filter", kUniversalFilter),
+    "A colon-separated list of glob (not regex) patterns "
+    "for filtering the tests to run, optionally followed by a "
+    "'-' and a : separated list of negative patterns (tests to "
+    "exclude).  A test is run if it matches one of the positive "
+    "patterns and does not match any of the negative patterns.");
+
+GTEST_DEFINE_bool_(list_tests, false,
+                   "List all tests without running them.");
+
+GTEST_DEFINE_string_(
+    output,
+    internal::StringFromGTestEnv("output", ""),
+    "A format (currently must be \"xml\"), optionally followed "
+    "by a colon and an output file name or directory. A directory "
+    "is indicated by a trailing pathname separator. "
+    "Examples: \"xml:filename.xml\", \"xml::directoryname/\". "
+    "If a directory is specified, output files will be created "
+    "within that directory, with file-names based on the test "
+    "executable's name and, if necessary, made unique by adding "
+    "digits.");
+
+GTEST_DEFINE_bool_(
+    print_time,
+    internal::BoolFromGTestEnv("print_time", true),
+    "True iff " GTEST_NAME_
+    " should display elapsed time in text output.");
+
+GTEST_DEFINE_int32_(
+    random_seed,
+    internal::Int32FromGTestEnv("random_seed", 0),
+    "Random number seed to use when shuffling test orders.  Must be in range "
+    "[1, 99999], or 0 to use a seed based on the current time.");
+
+GTEST_DEFINE_int32_(
+    repeat,
+    internal::Int32FromGTestEnv("repeat", 1),
+    "How many times to repeat each test.  Specify a negative number "
+    "for repeating forever.  Useful for shaking out flaky tests.");
+
+GTEST_DEFINE_bool_(
+    show_internal_stack_frames, false,
+    "True iff " GTEST_NAME_ " should include internal stack frames when "
+    "printing test failure stack traces.");
+
+GTEST_DEFINE_bool_(
+    shuffle,
+    internal::BoolFromGTestEnv("shuffle", false),
+    "True iff " GTEST_NAME_
+    " should randomize tests' order on every run.");
+
+GTEST_DEFINE_int32_(
+    stack_trace_depth,
+    internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth),
+    "The maximum number of stack frames to print when an "
+    "assertion fails.  The valid range is 0 through 100, inclusive.");
+
+GTEST_DEFINE_string_(
+    stream_result_to,
+    internal::StringFromGTestEnv("stream_result_to", ""),
+    "This flag specifies the host name and the port number on which to stream "
+    "test results. Example: \"localhost:555\". The flag is effective only on "
+    "Linux.");
+
+GTEST_DEFINE_bool_(
+    throw_on_failure,
+    internal::BoolFromGTestEnv("throw_on_failure", false),
+    "When this flag is specified, a failed assertion will throw an exception "
+    "if exceptions are enabled or exit the program with a non-zero code "
+    "otherwise.");
+
+namespace internal {
+
+// Generates a random number from [0, range), using a Linear
+// Congruential Generator (LCG).  Crashes if 'range' is 0 or greater
+// than kMaxRange.
+UInt32 Random::Generate(UInt32 range) {
+  // These constants are the same as are used in glibc's rand(3).
+  state_ = (1103515245U*state_ + 12345U) % kMaxRange;
+
+  GTEST_CHECK_(range > 0)
+      << "Cannot generate a number in the range [0, 0).";
+  GTEST_CHECK_(range <= kMaxRange)
+      << "Generation of a number in [0, " << range << ") was requested, "
+      << "but this can only generate numbers in [0, " << kMaxRange << ").";
+
+  // Converting via modulus introduces a bit of downward bias, but
+  // it's simple, and a linear congruential generator isn't too good
+  // to begin with.
+  return state_ % range;
+}
+
+// GTestIsInitialized() returns true iff the user has initialized
+// Google Test.  Useful for catching the user mistake of not initializing
+// Google Test before calling RUN_ALL_TESTS().
+//
+// A user must call testing::InitGoogleTest() to initialize Google
+// Test.  g_init_gtest_count is set to the number of times
+// InitGoogleTest() has been called.  We don't protect this variable
+// under a mutex as it is only accessed in the main thread.
+int g_init_gtest_count = 0;
+static bool GTestIsInitialized() { return g_init_gtest_count != 0; }
+
+// Iterates over a vector of TestCases, keeping a running sum of the
+// results of calling a given int-returning method on each.
+// Returns the sum.
+static int SumOverTestCaseList(const std::vector<TestCase*>& case_list,
+                               int (TestCase::*method)() const) {
+  int sum = 0;
+  for (size_t i = 0; i < case_list.size(); i++) {
+    sum += (case_list[i]->*method)();
+  }
+  return sum;
+}
+
+// Returns true iff the test case passed.
+static bool TestCasePassed(const TestCase* test_case) {
+  return test_case->should_run() && test_case->Passed();
+}
+
+// Returns true iff the test case failed.
+static bool TestCaseFailed(const TestCase* test_case) {
+  return test_case->should_run() && test_case->Failed();
+}
+
+// Returns true iff test_case contains at least one test that should
+// run.
+static bool ShouldRunTestCase(const TestCase* test_case) {
+  return test_case->should_run();
+}
+
+// AssertHelper constructor.
+AssertHelper::AssertHelper(TestPartResult::Type type,
+                           const char* file,
+                           int line,
+                           const char* message)
+    : data_(new AssertHelperData(type, file, line, message)) {
+}
+
+AssertHelper::~AssertHelper() {
+  delete data_;
+}
+
+// Message assignment, for assertion streaming support.
+void AssertHelper::operator=(const Message& message) const {
+  UnitTest::GetInstance()->
+    AddTestPartResult(data_->type, data_->file, data_->line,
+                      AppendUserMessage(data_->message, message),
+                      UnitTest::GetInstance()->impl()
+                      ->CurrentOsStackTraceExceptTop(1)
+                      // Skips the stack frame for this function itself.
+                      );  // NOLINT
+}
+
+// Mutex for linked pointers.
+GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex);
+
+// Application pathname gotten in InitGoogleTest.
+String g_executable_path;
+
+// Returns the current application's name, removing directory path if that
+// is present.
+FilePath GetCurrentExecutableName() {
+  FilePath result;
+
+#if GTEST_OS_WINDOWS
+  result.Set(FilePath(g_executable_path).RemoveExtension("exe"));
+#else
+  result.Set(FilePath(g_executable_path));
+#endif  // GTEST_OS_WINDOWS
+
+  return result.RemoveDirectoryName();
+}
+
+// Functions for processing the gtest_output flag.
+
+// Returns the output format, or "" for normal printed output.
+String UnitTestOptions::GetOutputFormat() {
+  const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
+  if (gtest_output_flag == NULL) return String("");
+
+  const char* const colon = strchr(gtest_output_flag, ':');
+  return (colon == NULL) ?
+      String(gtest_output_flag) :
+      String(gtest_output_flag, colon - gtest_output_flag);
+}
+
+// Returns the name of the requested output file, or the default if none
+// was explicitly specified.
+String UnitTestOptions::GetAbsolutePathToOutputFile() {
+  const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
+  if (gtest_output_flag == NULL)
+    return String("");
+
+  const char* const colon = strchr(gtest_output_flag, ':');
+  if (colon == NULL)
+    return String(internal::FilePath::ConcatPaths(
+               internal::FilePath(
+                   UnitTest::GetInstance()->original_working_dir()),
+               internal::FilePath(kDefaultOutputFile)).ToString() );
+
+  internal::FilePath output_name(colon + 1);
+  if (!output_name.IsAbsolutePath())
+    // TODO(wan@google.com): on Windows \some\path is not an absolute
+    // path (as its meaning depends on the current drive), yet the
+    // following logic for turning it into an absolute path is wrong.
+    // Fix it.
+    output_name = internal::FilePath::ConcatPaths(
+        internal::FilePath(UnitTest::GetInstance()->original_working_dir()),
+        internal::FilePath(colon + 1));
+
+  if (!output_name.IsDirectory())
+    return output_name.ToString();
+
+  internal::FilePath result(internal::FilePath::GenerateUniqueFileName(
+      output_name, internal::GetCurrentExecutableName(),
+      GetOutputFormat().c_str()));
+  return result.ToString();
+}
+
+// Returns true iff the wildcard pattern matches the string.  The
+// first ':' or '\0' character in pattern marks the end of it.
+//
+// This recursive algorithm isn't very efficient, but is clear and
+// works well enough for matching test names, which are short.
+bool UnitTestOptions::PatternMatchesString(const char *pattern,
+                                           const char *str) {
+  switch (*pattern) {
+    case '\0':
+    case ':':  // Either ':' or '\0' marks the end of the pattern.
+      return *str == '\0';
+    case '?':  // Matches any single character.
+      return *str != '\0' && PatternMatchesString(pattern + 1, str + 1);
+    case '*':  // Matches any string (possibly empty) of characters.
+      return (*str != '\0' && PatternMatchesString(pattern, str + 1)) ||
+          PatternMatchesString(pattern + 1, str);
+    default:  // Non-special character.  Matches itself.
+      return *pattern == *str &&
+          PatternMatchesString(pattern + 1, str + 1);
+  }
+}
+
+bool UnitTestOptions::MatchesFilter(const String& name, const char* filter) {
+  const char *cur_pattern = filter;
+  for (;;) {
+    if (PatternMatchesString(cur_pattern, name.c_str())) {
+      return true;
+    }
+
+    // Finds the next pattern in the filter.
+    cur_pattern = strchr(cur_pattern, ':');
+
+    // Returns if no more pattern can be found.
+    if (cur_pattern == NULL) {
+      return false;
+    }
+
+    // Skips the pattern separater (the ':' character).
+    cur_pattern++;
+  }
+}
+
+// TODO(keithray): move String function implementations to gtest-string.cc.
+
+// Returns true iff the user-specified filter matches the test case
+// name and the test name.
+bool UnitTestOptions::FilterMatchesTest(const String &test_case_name,
+                                        const String &test_name) {
+  const String& full_name = String::Format("%s.%s",
+                                           test_case_name.c_str(),
+                                           test_name.c_str());
+
+  // Split --gtest_filter at '-', if there is one, to separate into
+  // positive filter and negative filter portions
+  const char* const p = GTEST_FLAG(filter).c_str();
+  const char* const dash = strchr(p, '-');
+  String positive;
+  String negative;
+  if (dash == NULL) {
+    positive = GTEST_FLAG(filter).c_str();  // Whole string is a positive filter
+    negative = String("");
+  } else {
+    positive = String(p, dash - p);  // Everything up to the dash
+    negative = String(dash+1);       // Everything after the dash
+    if (positive.empty()) {
+      // Treat '-test1' as the same as '*-test1'
+      positive = kUniversalFilter;
+    }
+  }
+
+  // A filter is a colon-separated list of patterns.  It matches a
+  // test if any pattern in it matches the test.
+  return (MatchesFilter(full_name, positive.c_str()) &&
+          !MatchesFilter(full_name, negative.c_str()));
+}
+
+#if GTEST_HAS_SEH
+// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
+// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
+// This function is useful as an __except condition.
+int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) {
+  // Google Test should handle a SEH exception if:
+  //   1. the user wants it to, AND
+  //   2. this is not a breakpoint exception, AND
+  //   3. this is not a C++ exception (VC++ implements them via SEH,
+  //      apparently).
+  //
+  // SEH exception code for C++ exceptions.
+  // (see http://support.microsoft.com/kb/185294 for more information).
+  const DWORD kCxxExceptionCode = 0xe06d7363;
+
+  bool should_handle = true;
+
+  if (!GTEST_FLAG(catch_exceptions))
+    should_handle = false;
+  else if (exception_code == EXCEPTION_BREAKPOINT)
+    should_handle = false;
+  else if (exception_code == kCxxExceptionCode)
+    should_handle = false;
+
+  return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
+}
+#endif  // GTEST_HAS_SEH
+
+}  // namespace internal
+
+// The c'tor sets this object as the test part result reporter used by
+// Google Test.  The 'result' parameter specifies where to report the
+// results. Intercepts only failures from the current thread.
+ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
+    TestPartResultArray* result)
+    : intercept_mode_(INTERCEPT_ONLY_CURRENT_THREAD),
+      result_(result) {
+  Init();
+}
+
+// The c'tor sets this object as the test part result reporter used by
+// Google Test.  The 'result' parameter specifies where to report the
+// results.
+ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
+    InterceptMode intercept_mode, TestPartResultArray* result)
+    : intercept_mode_(intercept_mode),
+      result_(result) {
+  Init();
+}
+
+void ScopedFakeTestPartResultReporter::Init() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
+    old_reporter_ = impl->GetGlobalTestPartResultReporter();
+    impl->SetGlobalTestPartResultReporter(this);
+  } else {
+    old_reporter_ = impl->GetTestPartResultReporterForCurrentThread();
+    impl->SetTestPartResultReporterForCurrentThread(this);
+  }
+}
+
+// The d'tor restores the test part result reporter used by Google Test
+// before.
+ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
+    impl->SetGlobalTestPartResultReporter(old_reporter_);
+  } else {
+    impl->SetTestPartResultReporterForCurrentThread(old_reporter_);
+  }
+}
+
+// Increments the test part result count and remembers the result.
+// This method is from the TestPartResultReporterInterface interface.
+void ScopedFakeTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  result_->Append(result);
+}
+
+namespace internal {
+
+// Returns the type ID of ::testing::Test.  We should always call this
+// instead of GetTypeId< ::testing::Test>() to get the type ID of
+// testing::Test.  This is to work around a suspected linker bug when
+// using Google Test as a framework on Mac OS X.  The bug causes
+// GetTypeId< ::testing::Test>() to return different values depending
+// on whether the call is from the Google Test framework itself or
+// from user test code.  GetTestTypeId() is guaranteed to always
+// return the same value, as it always calls GetTypeId<>() from the
+// gtest.cc, which is within the Google Test framework.
+TypeId GetTestTypeId() {
+  return GetTypeId<Test>();
+}
+
+// The value of GetTestTypeId() as seen from within the Google Test
+// library.  This is solely for testing GetTestTypeId().
+extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId();
+
+// This predicate-formatter checks that 'results' contains a test part
+// failure of the given type and that the failure message contains the
+// given substring.
+AssertionResult HasOneFailure(const char* /* results_expr */,
+                              const char* /* type_expr */,
+                              const char* /* substr_expr */,
+                              const TestPartResultArray& results,
+                              TestPartResult::Type type,
+                              const string& substr) {
+  const String expected(type == TestPartResult::kFatalFailure ?
+                        "1 fatal failure" :
+                        "1 non-fatal failure");
+  Message msg;
+  if (results.size() != 1) {
+    msg << "Expected: " << expected << "\n"
+        << "  Actual: " << results.size() << " failures";
+    for (int i = 0; i < results.size(); i++) {
+      msg << "\n" << results.GetTestPartResult(i);
+    }
+    return AssertionFailure() << msg;
+  }
+
+  const TestPartResult& r = results.GetTestPartResult(0);
+  if (r.type() != type) {
+    return AssertionFailure() << "Expected: " << expected << "\n"
+                              << "  Actual:\n"
+                              << r;
+  }
+
+  if (strstr(r.message(), substr.c_str()) == NULL) {
+    return AssertionFailure() << "Expected: " << expected << " containing \""
+                              << substr << "\"\n"
+                              << "  Actual:\n"
+                              << r;
+  }
+
+  return AssertionSuccess();
+}
+
+// The constructor of SingleFailureChecker remembers where to look up
+// test part results, what type of failure we expect, and what
+// substring the failure message should contain.
+SingleFailureChecker:: SingleFailureChecker(
+    const TestPartResultArray* results,
+    TestPartResult::Type type,
+    const string& substr)
+    : results_(results),
+      type_(type),
+      substr_(substr) {}
+
+// The destructor of SingleFailureChecker verifies that the given
+// TestPartResultArray contains exactly one failure that has the given
+// type and contains the given substring.  If that's not the case, a
+// non-fatal failure will be generated.
+SingleFailureChecker::~SingleFailureChecker() {
+  EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_);
+}
+
+DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter(
+    UnitTestImpl* unit_test) : unit_test_(unit_test) {}
+
+void DefaultGlobalTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  unit_test_->current_test_result()->AddTestPartResult(result);
+  unit_test_->listeners()->repeater()->OnTestPartResult(result);
+}
+
+DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter(
+    UnitTestImpl* unit_test) : unit_test_(unit_test) {}
+
+void DefaultPerThreadTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  unit_test_->GetGlobalTestPartResultReporter()->ReportTestPartResult(result);
+}
+
+// Returns the global test part result reporter.
+TestPartResultReporterInterface*
+UnitTestImpl::GetGlobalTestPartResultReporter() {
+  internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
+  return global_test_part_result_repoter_;
+}
+
+// Sets the global test part result reporter.
+void UnitTestImpl::SetGlobalTestPartResultReporter(
+    TestPartResultReporterInterface* reporter) {
+  internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
+  global_test_part_result_repoter_ = reporter;
+}
+
+// Returns the test part result reporter for the current thread.
+TestPartResultReporterInterface*
+UnitTestImpl::GetTestPartResultReporterForCurrentThread() {
+  return per_thread_test_part_result_reporter_.get();
+}
+
+// Sets the test part result reporter for the current thread.
+void UnitTestImpl::SetTestPartResultReporterForCurrentThread(
+    TestPartResultReporterInterface* reporter) {
+  per_thread_test_part_result_reporter_.set(reporter);
+}
+
+// Gets the number of successful test cases.
+int UnitTestImpl::successful_test_case_count() const {
+  return CountIf(test_cases_, TestCasePassed);
+}
+
+// Gets the number of failed test cases.
+int UnitTestImpl::failed_test_case_count() const {
+  return CountIf(test_cases_, TestCaseFailed);
+}
+
+// Gets the number of all test cases.
+int UnitTestImpl::total_test_case_count() const {
+  return static_cast<int>(test_cases_.size());
+}
+
+// Gets the number of all test cases that contain at least one test
+// that should run.
+int UnitTestImpl::test_case_to_run_count() const {
+  return CountIf(test_cases_, ShouldRunTestCase);
+}
+
+// Gets the number of successful tests.
+int UnitTestImpl::successful_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::successful_test_count);
+}
+
+// Gets the number of failed tests.
+int UnitTestImpl::failed_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::failed_test_count);
+}
+
+// Gets the number of disabled tests.
+int UnitTestImpl::disabled_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::disabled_test_count);
+}
+
+// Gets the number of all tests.
+int UnitTestImpl::total_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::total_test_count);
+}
+
+// Gets the number of tests that should run.
+int UnitTestImpl::test_to_run_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::test_to_run_count);
+}
+
+// Returns the current OS stack trace as a String.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// CurrentOsStackTraceExceptTop(1), Foo() will be included in the
+// trace but Bar() and CurrentOsStackTraceExceptTop() won't.
+String UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) {
+  (void)skip_count;
+  return String("");
+}
+
+// Returns the current time in milliseconds.
+TimeInMillis GetTimeInMillis() {
+#if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__)
+  // Difference between 1970-01-01 and 1601-01-01 in milliseconds.
+  // http://analogous.blogspot.com/2005/04/epoch.html
+  const TimeInMillis kJavaEpochToWinFileTimeDelta =
+    static_cast<TimeInMillis>(116444736UL) * 100000UL;
+  const DWORD kTenthMicrosInMilliSecond = 10000;
+
+  SYSTEMTIME now_systime;
+  FILETIME now_filetime;
+  ULARGE_INTEGER now_int64;
+  // TODO(kenton@google.com): Shouldn't this just use
+  //   GetSystemTimeAsFileTime()?
+  GetSystemTime(&now_systime);
+  if (SystemTimeToFileTime(&now_systime, &now_filetime)) {
+    now_int64.LowPart = now_filetime.dwLowDateTime;
+    now_int64.HighPart = now_filetime.dwHighDateTime;
+    now_int64.QuadPart = (now_int64.QuadPart / kTenthMicrosInMilliSecond) -
+      kJavaEpochToWinFileTimeDelta;
+    return now_int64.QuadPart;
+  }
+  return 0;
+#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_
+  __timeb64 now;
+
+# ifdef _MSC_VER
+
+  // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996
+  // (deprecated function) there.
+  // TODO(kenton@google.com): Use GetTickCount()?  Or use
+  //   SystemTimeToFileTime()
+#  pragma warning(push)          // Saves the current warning state.
+#  pragma warning(disable:4996)  // Temporarily disables warning 4996.
+  _ftime64(&now);
+#  pragma warning(pop)           // Restores the warning state.
+# else
+
+  _ftime64(&now);
+
+# endif  // _MSC_VER
+
+  return static_cast<TimeInMillis>(now.time) * 1000 + now.millitm;
+#elif GTEST_HAS_GETTIMEOFDAY_
+  struct timeval now;
+  gettimeofday(&now, NULL);
+  return static_cast<TimeInMillis>(now.tv_sec) * 1000 + now.tv_usec / 1000;
+#else
+# error "Don't know how to get the current time on your system."
+#endif
+}
+
+// Utilities
+
+// class String
+
+// Returns the input enclosed in double quotes if it's not NULL;
+// otherwise returns "(null)".  For example, "\"Hello\"" is returned
+// for input "Hello".
+//
+// This is useful for printing a C string in the syntax of a literal.
+//
+// Known issue: escape sequences are not handled yet.
+String String::ShowCStringQuoted(const char* c_str) {
+  return c_str ? String::Format("\"%s\"", c_str) : String("(null)");
+}
+
+// Copies at most length characters from str into a newly-allocated
+// piece of memory of size length+1.  The memory is allocated with new[].
+// A terminating null byte is written to the memory, and a pointer to it
+// is returned.  If str is NULL, NULL is returned.
+static char* CloneString(const char* str, size_t length) {
+  if (str == NULL) {
+    return NULL;
+  } else {
+    char* const clone = new char[length + 1];
+    posix::StrNCpy(clone, str, length);
+    clone[length] = '\0';
+    return clone;
+  }
+}
+
+// Clones a 0-terminated C string, allocating memory using new.  The
+// caller is responsible for deleting[] the return value.  Returns the
+// cloned string, or NULL if the input is NULL.
+const char * String::CloneCString(const char* c_str) {
+  return (c_str == NULL) ?
+                    NULL : CloneString(c_str, strlen(c_str));
+}
+
+#if GTEST_OS_WINDOWS_MOBILE
+// Creates a UTF-16 wide string from the given ANSI string, allocating
+// memory using new. The caller is responsible for deleting the return
+// value using delete[]. Returns the wide string, or NULL if the
+// input is NULL.
+LPCWSTR String::AnsiToUtf16(const char* ansi) {
+  if (!ansi) return NULL;
+  const int length = strlen(ansi);
+  const int unicode_length =
+      MultiByteToWideChar(CP_ACP, 0, ansi, length,
+                          NULL, 0);
+  WCHAR* unicode = new WCHAR[unicode_length + 1];
+  MultiByteToWideChar(CP_ACP, 0, ansi, length,
+                      unicode, unicode_length);
+  unicode[unicode_length] = 0;
+  return unicode;
+}
+
+// Creates an ANSI string from the given wide string, allocating
+// memory using new. The caller is responsible for deleting the return
+// value using delete[]. Returns the ANSI string, or NULL if the
+// input is NULL.
+const char* String::Utf16ToAnsi(LPCWSTR utf16_str)  {
+  if (!utf16_str) return NULL;
+  const int ansi_length =
+      WideCharToMultiByte(CP_ACP, 0, utf16_str, -1,
+                          NULL, 0, NULL, NULL);
+  char* ansi = new char[ansi_length + 1];
+  WideCharToMultiByte(CP_ACP, 0, utf16_str, -1,
+                      ansi, ansi_length, NULL, NULL);
+  ansi[ansi_length] = 0;
+  return ansi;
+}
+
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Compares two C strings.  Returns true iff they have the same content.
+//
+// Unlike strcmp(), this function can handle NULL argument(s).  A NULL
+// C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::CStringEquals(const char * lhs, const char * rhs) {
+  if ( lhs == NULL ) return rhs == NULL;
+
+  if ( rhs == NULL ) return false;
+
+  return strcmp(lhs, rhs) == 0;
+}
+
+#if GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING
+
+// Converts an array of wide chars to a narrow string using the UTF-8
+// encoding, and streams the result to the given Message object.
+static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length,
+                                     Message* msg) {
+  // TODO(wan): consider allowing a testing::String object to
+  // contain '\0'.  This will make it behave more like std::string,
+  // and will allow ToUtf8String() to return the correct encoding
+  // for '\0' s.t. we can get rid of the conditional here (and in
+  // several other places).
+  for (size_t i = 0; i != length; ) {  // NOLINT
+    if (wstr[i] != L'\0') {
+      *msg << WideStringToUtf8(wstr + i, static_cast<int>(length - i));
+      while (i != length && wstr[i] != L'\0')
+        i++;
+    } else {
+      *msg << '\0';
+      i++;
+    }
+  }
+}
+
+#endif  // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING
+
+}  // namespace internal
+
+#if GTEST_HAS_STD_WSTRING
+// Converts the given wide string to a narrow string using the UTF-8
+// encoding, and streams the result to this Message object.
+Message& Message::operator <<(const ::std::wstring& wstr) {
+  internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this);
+  return *this;
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+// Converts the given wide string to a narrow string using the UTF-8
+// encoding, and streams the result to this Message object.
+Message& Message::operator <<(const ::wstring& wstr) {
+  internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this);
+  return *this;
+}
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+// AssertionResult constructors.
+// Used in EXPECT_TRUE/FALSE(assertion_result).
+AssertionResult::AssertionResult(const AssertionResult& other)
+    : success_(other.success_),
+      message_(other.message_.get() != NULL ?
+               new ::std::string(*other.message_) :
+               static_cast< ::std::string*>(NULL)) {
+}
+
+// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
+AssertionResult AssertionResult::operator!() const {
+  AssertionResult negation(!success_);
+  if (message_.get() != NULL)
+    negation << *message_;
+  return negation;
+}
+
+// Makes a successful assertion result.
+AssertionResult AssertionSuccess() {
+  return AssertionResult(true);
+}
+
+// Makes a failed assertion result.
+AssertionResult AssertionFailure() {
+  return AssertionResult(false);
+}
+
+// Makes a failed assertion result with the given failure message.
+// Deprecated; use AssertionFailure() << message.
+AssertionResult AssertionFailure(const Message& message) {
+  return AssertionFailure() << message;
+}
+
+namespace internal {
+
+// Constructs and returns the message for an equality assertion
+// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
+//
+// The first four parameters are the expressions used in the assertion
+// and their values, as strings.  For example, for ASSERT_EQ(foo, bar)
+// where foo is 5 and bar is 6, we have:
+//
+//   expected_expression: "foo"
+//   actual_expression:   "bar"
+//   expected_value:      "5"
+//   actual_value:        "6"
+//
+// The ignoring_case parameter is true iff the assertion is a
+// *_STRCASEEQ*.  When it's true, the string " (ignoring case)" will
+// be inserted into the message.
+AssertionResult EqFailure(const char* expected_expression,
+                          const char* actual_expression,
+                          const String& expected_value,
+                          const String& actual_value,
+                          bool ignoring_case) {
+  Message msg;
+  msg << "Value of: " << actual_expression;
+  if (actual_value != actual_expression) {
+    msg << "\n  Actual: " << actual_value;
+  }
+
+  msg << "\nExpected: " << expected_expression;
+  if (ignoring_case) {
+    msg << " (ignoring case)";
+  }
+  if (expected_value != expected_expression) {
+    msg << "\nWhich is: " << expected_value;
+  }
+
+  return AssertionFailure() << msg;
+}
+
+// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
+String GetBoolAssertionFailureMessage(const AssertionResult& assertion_result,
+                                      const char* expression_text,
+                                      const char* actual_predicate_value,
+                                      const char* expected_predicate_value) {
+  const char* actual_message = assertion_result.message();
+  Message msg;
+  msg << "Value of: " << expression_text
+      << "\n  Actual: " << actual_predicate_value;
+  if (actual_message[0] != '\0')
+    msg << " (" << actual_message << ")";
+  msg << "\nExpected: " << expected_predicate_value;
+  return msg.GetString();
+}
+
+// Helper function for implementing ASSERT_NEAR.
+AssertionResult DoubleNearPredFormat(const char* expr1,
+                                     const char* expr2,
+                                     const char* abs_error_expr,
+                                     double val1,
+                                     double val2,
+                                     double abs_error) {
+  const double diff = fabs(val1 - val2);
+  if (diff <= abs_error) return AssertionSuccess();
+
+  // TODO(wan): do not print the value of an expression if it's
+  // already a literal.
+  return AssertionFailure()
+      << "The difference between " << expr1 << " and " << expr2
+      << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n"
+      << expr1 << " evaluates to " << val1 << ",\n"
+      << expr2 << " evaluates to " << val2 << ", and\n"
+      << abs_error_expr << " evaluates to " << abs_error << ".";
+}
+
+
+// Helper template for implementing FloatLE() and DoubleLE().
+template <typename RawType>
+AssertionResult FloatingPointLE(const char* expr1,
+                                const char* expr2,
+                                RawType val1,
+                                RawType val2) {
+  // Returns success if val1 is less than val2,
+  if (val1 < val2) {
+    return AssertionSuccess();
+  }
+
+  // or if val1 is almost equal to val2.
+  const FloatingPoint<RawType> lhs(val1), rhs(val2);
+  if (lhs.AlmostEquals(rhs)) {
+    return AssertionSuccess();
+  }
+
+  // Note that the above two checks will both fail if either val1 or
+  // val2 is NaN, as the IEEE floating-point standard requires that
+  // any predicate involving a NaN must return false.
+
+  ::std::stringstream val1_ss;
+  val1_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+          << val1;
+
+  ::std::stringstream val2_ss;
+  val2_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+          << val2;
+
+  return AssertionFailure()
+      << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n"
+      << "  Actual: " << StringStreamToString(&val1_ss) << " vs "
+      << StringStreamToString(&val2_ss);
+}
+
+}  // namespace internal
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+AssertionResult FloatLE(const char* expr1, const char* expr2,
+                        float val1, float val2) {
+  return internal::FloatingPointLE<float>(expr1, expr2, val1, val2);
+}
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+AssertionResult DoubleLE(const char* expr1, const char* expr2,
+                         double val1, double val2) {
+  return internal::FloatingPointLE<double>(expr1, expr2, val1, val2);
+}
+
+namespace internal {
+
+// The helper function for {ASSERT|EXPECT}_EQ with int or enum
+// arguments.
+AssertionResult CmpHelperEQ(const char* expected_expression,
+                            const char* actual_expression,
+                            BiggestInt expected,
+                            BiggestInt actual) {
+  if (expected == actual) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   FormatForComparisonFailureMessage(expected, actual),
+                   FormatForComparisonFailureMessage(actual, expected),
+                   false);
+}
+
+// A macro for implementing the helper functions needed to implement
+// ASSERT_?? and EXPECT_?? with integer or enum arguments.  It is here
+// just to avoid copy-and-paste of similar code.
+#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
+AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
+                                   BiggestInt val1, BiggestInt val2) {\
+  if (val1 op val2) {\
+    return AssertionSuccess();\
+  } else {\
+    return AssertionFailure() \
+        << "Expected: (" << expr1 << ") " #op " (" << expr2\
+        << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
+        << " vs " << FormatForComparisonFailureMessage(val2, val1);\
+  }\
+}
+
+// Implements the helper function for {ASSERT|EXPECT}_NE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(NE, !=)
+// Implements the helper function for {ASSERT|EXPECT}_LE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(LE, <=)
+// Implements the helper function for {ASSERT|EXPECT}_LT with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(LT, < )
+// Implements the helper function for {ASSERT|EXPECT}_GE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(GE, >=)
+// Implements the helper function for {ASSERT|EXPECT}_GT with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(GT, > )
+
+#undef GTEST_IMPL_CMP_HELPER_
+
+// The helper function for {ASSERT|EXPECT}_STREQ.
+AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                               const char* actual_expression,
+                               const char* expected,
+                               const char* actual) {
+  if (String::CStringEquals(expected, actual)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   String::ShowCStringQuoted(expected),
+                   String::ShowCStringQuoted(actual),
+                   false);
+}
+
+// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
+AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression,
+                                   const char* actual_expression,
+                                   const char* expected,
+                                   const char* actual) {
+  if (String::CaseInsensitiveCStringEquals(expected, actual)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   String::ShowCStringQuoted(expected),
+                   String::ShowCStringQuoted(actual),
+                   true);
+}
+
+// The helper function for {ASSERT|EXPECT}_STRNE.
+AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                               const char* s2_expression,
+                               const char* s1,
+                               const char* s2) {
+  if (!String::CStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  } else {
+    return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+                              << s2_expression << "), actual: \""
+                              << s1 << "\" vs \"" << s2 << "\"";
+  }
+}
+
+// The helper function for {ASSERT|EXPECT}_STRCASENE.
+AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
+                                   const char* s2_expression,
+                                   const char* s1,
+                                   const char* s2) {
+  if (!String::CaseInsensitiveCStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  } else {
+    return AssertionFailure()
+        << "Expected: (" << s1_expression << ") != ("
+        << s2_expression << ") (ignoring case), actual: \""
+        << s1 << "\" vs \"" << s2 << "\"";
+  }
+}
+
+}  // namespace internal
+
+namespace {
+
+// Helper functions for implementing IsSubString() and IsNotSubstring().
+
+// This group of overloaded functions return true iff needle is a
+// substring of haystack.  NULL is considered a substring of itself
+// only.
+
+bool IsSubstringPred(const char* needle, const char* haystack) {
+  if (needle == NULL || haystack == NULL)
+    return needle == haystack;
+
+  return strstr(haystack, needle) != NULL;
+}
+
+bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) {
+  if (needle == NULL || haystack == NULL)
+    return needle == haystack;
+
+  return wcsstr(haystack, needle) != NULL;
+}
+
+// StringType here can be either ::std::string or ::std::wstring.
+template <typename StringType>
+bool IsSubstringPred(const StringType& needle,
+                     const StringType& haystack) {
+  return haystack.find(needle) != StringType::npos;
+}
+
+// This function implements either IsSubstring() or IsNotSubstring(),
+// depending on the value of the expected_to_be_substring parameter.
+// StringType here can be const char*, const wchar_t*, ::std::string,
+// or ::std::wstring.
+template <typename StringType>
+AssertionResult IsSubstringImpl(
+    bool expected_to_be_substring,
+    const char* needle_expr, const char* haystack_expr,
+    const StringType& needle, const StringType& haystack) {
+  if (IsSubstringPred(needle, haystack) == expected_to_be_substring)
+    return AssertionSuccess();
+
+  const bool is_wide_string = sizeof(needle[0]) > 1;
+  const char* const begin_string_quote = is_wide_string ? "L\"" : "\"";
+  return AssertionFailure()
+      << "Value of: " << needle_expr << "\n"
+      << "  Actual: " << begin_string_quote << needle << "\"\n"
+      << "Expected: " << (expected_to_be_substring ? "" : "not ")
+      << "a substring of " << haystack_expr << "\n"
+      << "Which is: " << begin_string_quote << haystack << "\"";
+}
+
+}  // namespace
+
+// IsSubstring() and IsNotSubstring() check whether needle is a
+// substring of haystack (NULL is considered a substring of itself
+// only), and return an appropriate error message when they fail.
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+#if GTEST_HAS_STD_WSTRING
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+namespace internal {
+
+#if GTEST_OS_WINDOWS
+
+namespace {
+
+// Helper function for IsHRESULT{SuccessFailure} predicates
+AssertionResult HRESULTFailureHelper(const char* expr,
+                                     const char* expected,
+                                     long hr) {  // NOLINT
+# if GTEST_OS_WINDOWS_MOBILE
+
+  // Windows CE doesn't support FormatMessage.
+  const char error_text[] = "";
+
+# else
+
+  // Looks up the human-readable system message for the HRESULT code
+  // and since we're not passing any params to FormatMessage, we don't
+  // want inserts expanded.
+  const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM |
+                       FORMAT_MESSAGE_IGNORE_INSERTS;
+  const DWORD kBufSize = 4096;  // String::Format can't exceed this length.
+  // Gets the system's human readable message string for this HRESULT.
+  char error_text[kBufSize] = { '\0' };
+  DWORD message_length = ::FormatMessageA(kFlags,
+                                          0,  // no source, we're asking system
+                                          hr,  // the error
+                                          0,  // no line width restrictions
+                                          error_text,  // output buffer
+                                          kBufSize,  // buf size
+                                          NULL);  // no arguments for inserts
+  // Trims tailing white space (FormatMessage leaves a trailing cr-lf)
+  for (; message_length && IsSpace(error_text[message_length - 1]);
+          --message_length) {
+    error_text[message_length - 1] = '\0';
+  }
+
+# endif  // GTEST_OS_WINDOWS_MOBILE
+
+  const String error_hex(String::Format("0x%08X ", hr));
+  return ::testing::AssertionFailure()
+      << "Expected: " << expr << " " << expected << ".\n"
+      << "  Actual: " << error_hex << error_text << "\n";
+}
+
+}  // namespace
+
+AssertionResult IsHRESULTSuccess(const char* expr, long hr) {  // NOLINT
+  if (SUCCEEDED(hr)) {
+    return AssertionSuccess();
+  }
+  return HRESULTFailureHelper(expr, "succeeds", hr);
+}
+
+AssertionResult IsHRESULTFailure(const char* expr, long hr) {  // NOLINT
+  if (FAILED(hr)) {
+    return AssertionSuccess();
+  }
+  return HRESULTFailureHelper(expr, "fails", hr);
+}
+
+#endif  // GTEST_OS_WINDOWS
+
+// Utility functions for encoding Unicode text (wide strings) in
+// UTF-8.
+
+// A Unicode code-point can have upto 21 bits, and is encoded in UTF-8
+// like this:
+//
+// Code-point length   Encoding
+//   0 -  7 bits       0xxxxxxx
+//   8 - 11 bits       110xxxxx 10xxxxxx
+//  12 - 16 bits       1110xxxx 10xxxxxx 10xxxxxx
+//  17 - 21 bits       11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+
+// The maximum code-point a one-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint1 = (static_cast<UInt32>(1) <<  7) - 1;
+
+// The maximum code-point a two-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint2 = (static_cast<UInt32>(1) << (5 + 6)) - 1;
+
+// The maximum code-point a three-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint3 = (static_cast<UInt32>(1) << (4 + 2*6)) - 1;
+
+// The maximum code-point a four-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint4 = (static_cast<UInt32>(1) << (3 + 3*6)) - 1;
+
+// Chops off the n lowest bits from a bit pattern.  Returns the n
+// lowest bits.  As a side effect, the original bit pattern will be
+// shifted to the right by n bits.
+inline UInt32 ChopLowBits(UInt32* bits, int n) {
+  const UInt32 low_bits = *bits & ((static_cast<UInt32>(1) << n) - 1);
+  *bits >>= n;
+  return low_bits;
+}
+
+// Converts a Unicode code point to a narrow string in UTF-8 encoding.
+// code_point parameter is of type UInt32 because wchar_t may not be
+// wide enough to contain a code point.
+// The output buffer str must containt at least 32 characters.
+// The function returns the address of the output buffer.
+// If the code_point is not a valid Unicode code point
+// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'.
+char* CodePointToUtf8(UInt32 code_point, char* str) {
+  if (code_point <= kMaxCodePoint1) {
+    str[1] = '\0';
+    str[0] = static_cast<char>(code_point);                          // 0xxxxxxx
+  } else if (code_point <= kMaxCodePoint2) {
+    str[2] = '\0';
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xC0 | code_point);                   // 110xxxxx
+  } else if (code_point <= kMaxCodePoint3) {
+    str[3] = '\0';
+    str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xE0 | code_point);                   // 1110xxxx
+  } else if (code_point <= kMaxCodePoint4) {
+    str[4] = '\0';
+    str[3] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xF0 | code_point);                   // 11110xxx
+  } else {
+    // The longest string String::Format can produce when invoked
+    // with these parameters is 28 character long (not including
+    // the terminating nul character). We are asking for 32 character
+    // buffer just in case. This is also enough for strncpy to
+    // null-terminate the destination string.
+    posix::StrNCpy(
+        str, String::Format("(Invalid Unicode 0x%X)", code_point).c_str(), 32);
+    str[31] = '\0';  // Makes sure no change in the format to strncpy leaves
+                     // the result unterminated.
+  }
+  return str;
+}
+
+// The following two functions only make sense if the the system
+// uses UTF-16 for wide string encoding. All supported systems
+// with 16 bit wchar_t (Windows, Cygwin, Symbian OS) do use UTF-16.
+
+// Determines if the arguments constitute UTF-16 surrogate pair
+// and thus should be combined into a single Unicode code point
+// using CreateCodePointFromUtf16SurrogatePair.
+inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) {
+  return sizeof(wchar_t) == 2 &&
+      (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00;
+}
+
+// Creates a Unicode code point from UTF16 surrogate pair.
+inline UInt32 CreateCodePointFromUtf16SurrogatePair(wchar_t first,
+                                                    wchar_t second) {
+  const UInt32 mask = (1 << 10) - 1;
+  return (sizeof(wchar_t) == 2) ?
+      (((first & mask) << 10) | (second & mask)) + 0x10000 :
+      // This function should not be called when the condition is
+      // false, but we provide a sensible default in case it is.
+      static_cast<UInt32>(first);
+}
+
+// Converts a wide string to a narrow string in UTF-8 encoding.
+// The wide string is assumed to have the following encoding:
+//   UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS)
+//   UTF-32 if sizeof(wchar_t) == 4 (on Linux)
+// Parameter str points to a null-terminated wide string.
+// Parameter num_chars may additionally limit the number
+// of wchar_t characters processed. -1 is used when the entire string
+// should be processed.
+// If the string contains code points that are not valid Unicode code points
+// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
+// and contains invalid UTF-16 surrogate pairs, values in those pairs
+// will be encoded as individual Unicode characters from Basic Normal Plane.
+String WideStringToUtf8(const wchar_t* str, int num_chars) {
+  if (num_chars == -1)
+    num_chars = static_cast<int>(wcslen(str));
+
+  ::std::stringstream stream;
+  for (int i = 0; i < num_chars; ++i) {
+    UInt32 unicode_code_point;
+
+    if (str[i] == L'\0') {
+      break;
+    } else if (i + 1 < num_chars && IsUtf16SurrogatePair(str[i], str[i + 1])) {
+      unicode_code_point = CreateCodePointFromUtf16SurrogatePair(str[i],
+                                                                 str[i + 1]);
+      i++;
+    } else {
+      unicode_code_point = static_cast<UInt32>(str[i]);
+    }
+
+    char buffer[32];  // CodePointToUtf8 requires a buffer this big.
+    stream << CodePointToUtf8(unicode_code_point, buffer);
+  }
+  return StringStreamToString(&stream);
+}
+
+// Converts a wide C string to a String using the UTF-8 encoding.
+// NULL will be converted to "(null)".
+String String::ShowWideCString(const wchar_t * wide_c_str) {
+  if (wide_c_str == NULL) return String("(null)");
+
+  return String(internal::WideStringToUtf8(wide_c_str, -1).c_str());
+}
+
+// Similar to ShowWideCString(), except that this function encloses
+// the converted string in double quotes.
+String String::ShowWideCStringQuoted(const wchar_t* wide_c_str) {
+  if (wide_c_str == NULL) return String("(null)");
+
+  return String::Format("L\"%s\"",
+                        String::ShowWideCString(wide_c_str).c_str());
+}
+
+// Compares two wide C strings.  Returns true iff they have the same
+// content.
+//
+// Unlike wcscmp(), this function can handle NULL argument(s).  A NULL
+// C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::WideCStringEquals(const wchar_t * lhs, const wchar_t * rhs) {
+  if (lhs == NULL) return rhs == NULL;
+
+  if (rhs == NULL) return false;
+
+  return wcscmp(lhs, rhs) == 0;
+}
+
+// Helper function for *_STREQ on wide strings.
+AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                               const char* actual_expression,
+                               const wchar_t* expected,
+                               const wchar_t* actual) {
+  if (String::WideCStringEquals(expected, actual)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   String::ShowWideCStringQuoted(expected),
+                   String::ShowWideCStringQuoted(actual),
+                   false);
+}
+
+// Helper function for *_STRNE on wide strings.
+AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                               const char* s2_expression,
+                               const wchar_t* s1,
+                               const wchar_t* s2) {
+  if (!String::WideCStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  }
+
+  return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+                            << s2_expression << "), actual: "
+                            << String::ShowWideCStringQuoted(s1)
+                            << " vs " << String::ShowWideCStringQuoted(s2);
+}
+
+// Compares two C strings, ignoring case.  Returns true iff they have
+// the same content.
+//
+// Unlike strcasecmp(), this function can handle NULL argument(s).  A
+// NULL C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) {
+  if (lhs == NULL)
+    return rhs == NULL;
+  if (rhs == NULL)
+    return false;
+  return posix::StrCaseCmp(lhs, rhs) == 0;
+}
+
+  // Compares two wide C strings, ignoring case.  Returns true iff they
+  // have the same content.
+  //
+  // Unlike wcscasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL wide C string,
+  // including the empty string.
+  // NB: The implementations on different platforms slightly differ.
+  // On windows, this method uses _wcsicmp which compares according to LC_CTYPE
+  // environment variable. On GNU platform this method uses wcscasecmp
+  // which compares according to LC_CTYPE category of the current locale.
+  // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
+  // current locale.
+bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
+                                              const wchar_t* rhs) {
+  if (lhs == NULL) return rhs == NULL;
+
+  if (rhs == NULL) return false;
+
+#if GTEST_OS_WINDOWS
+  return _wcsicmp(lhs, rhs) == 0;
+#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID
+  return wcscasecmp(lhs, rhs) == 0;
+#else
+  // Android, Mac OS X and Cygwin don't define wcscasecmp.
+  // Other unknown OSes may not define it either.
+  wint_t left, right;
+  do {
+    left = towlower(*lhs++);
+    right = towlower(*rhs++);
+  } while (left && left == right);
+  return left == right;
+#endif  // OS selector
+}
+
+// Compares this with another String.
+// Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0
+// if this is greater than rhs.
+int String::Compare(const String & rhs) const {
+  const char* const lhs_c_str = c_str();
+  const char* const rhs_c_str = rhs.c_str();
+
+  if (lhs_c_str == NULL) {
+    return rhs_c_str == NULL ? 0 : -1;  // NULL < anything except NULL
+  } else if (rhs_c_str == NULL) {
+    return 1;
+  }
+
+  const size_t shorter_str_len =
+      length() <= rhs.length() ? length() : rhs.length();
+  for (size_t i = 0; i != shorter_str_len; i++) {
+    if (lhs_c_str[i] < rhs_c_str[i]) {
+      return -1;
+    } else if (lhs_c_str[i] > rhs_c_str[i]) {
+      return 1;
+    }
+  }
+  return (length() < rhs.length()) ? -1 :
+      (length() > rhs.length()) ? 1 : 0;
+}
+
+// Returns true iff this String ends with the given suffix.  *Any*
+// String is considered to end with a NULL or empty suffix.
+bool String::EndsWith(const char* suffix) const {
+  if (suffix == NULL || CStringEquals(suffix, "")) return true;
+
+  if (c_str() == NULL) return false;
+
+  const size_t this_len = strlen(c_str());
+  const size_t suffix_len = strlen(suffix);
+  return (this_len >= suffix_len) &&
+         CStringEquals(c_str() + this_len - suffix_len, suffix);
+}
+
+// Returns true iff this String ends with the given suffix, ignoring case.
+// Any String is considered to end with a NULL or empty suffix.
+bool String::EndsWithCaseInsensitive(const char* suffix) const {
+  if (suffix == NULL || CStringEquals(suffix, "")) return true;
+
+  if (c_str() == NULL) return false;
+
+  const size_t this_len = strlen(c_str());
+  const size_t suffix_len = strlen(suffix);
+  return (this_len >= suffix_len) &&
+         CaseInsensitiveCStringEquals(c_str() + this_len - suffix_len, suffix);
+}
+
+// Formats a list of arguments to a String, using the same format
+// spec string as for printf.
+//
+// We do not use the StringPrintf class as it is not universally
+// available.
+//
+// The result is limited to 4096 characters (including the tailing 0).
+// If 4096 characters are not enough to format the input, or if
+// there's an error, "<formatting error or buffer exceeded>" is
+// returned.
+String String::Format(const char * format, ...) {
+  va_list args;
+  va_start(args, format);
+
+  char buffer[4096];
+  const int kBufferSize = sizeof(buffer)/sizeof(buffer[0]);
+
+  // MSVC 8 deprecates vsnprintf(), so we want to suppress warning
+  // 4996 (deprecated function) there.
+#ifdef _MSC_VER  // We are using MSVC.
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4996)  // Temporarily disables warning 4996.
+
+  const int size = vsnprintf(buffer, kBufferSize, format, args);
+
+# pragma warning(pop)           // Restores the warning state.
+#else  // We are not using MSVC.
+  const int size = vsnprintf(buffer, kBufferSize, format, args);
+#endif  // _MSC_VER
+  va_end(args);
+
+  // vsnprintf()'s behavior is not portable.  When the buffer is not
+  // big enough, it returns a negative value in MSVC, and returns the
+  // needed buffer size on Linux.  When there is an output error, it
+  // always returns a negative value.  For simplicity, we lump the two
+  // error cases together.
+  if (size < 0 || size >= kBufferSize) {
+    return String("<formatting error or buffer exceeded>");
+  } else {
+    return String(buffer, size);
+  }
+}
+
+// Converts the buffer in a stringstream to a String, converting NUL
+// bytes to "\\0" along the way.
+String StringStreamToString(::std::stringstream* ss) {
+  const ::std::string& str = ss->str();
+  const char* const start = str.c_str();
+  const char* const end = start + str.length();
+
+  // We need to use a helper stringstream to do this transformation
+  // because String doesn't support push_back().
+  ::std::stringstream helper;
+  for (const char* ch = start; ch != end; ++ch) {
+    if (*ch == '\0') {
+      helper << "\\0";  // Replaces NUL with "\\0";
+    } else {
+      helper.put(*ch);
+    }
+  }
+
+  return String(helper.str().c_str());
+}
+
+// Appends the user-supplied message to the Google-Test-generated message.
+String AppendUserMessage(const String& gtest_msg,
+                         const Message& user_msg) {
+  // Appends the user message if it's non-empty.
+  const String user_msg_string = user_msg.GetString();
+  if (user_msg_string.empty()) {
+    return gtest_msg;
+  }
+
+  Message msg;
+  msg << gtest_msg << "\n" << user_msg_string;
+
+  return msg.GetString();
+}
+
+}  // namespace internal
+
+// class TestResult
+
+// Creates an empty TestResult.
+TestResult::TestResult()
+    : death_test_count_(0),
+      elapsed_time_(0) {
+}
+
+// D'tor.
+TestResult::~TestResult() {
+}
+
+// Returns the i-th test part result among all the results. i can
+// range from 0 to total_part_count() - 1. If i is not in that range,
+// aborts the program.
+const TestPartResult& TestResult::GetTestPartResult(int i) const {
+  if (i < 0 || i >= total_part_count())
+    internal::posix::Abort();
+  return test_part_results_.at(i);
+}
+
+// Returns the i-th test property. i can range from 0 to
+// test_property_count() - 1. If i is not in that range, aborts the
+// program.
+const TestProperty& TestResult::GetTestProperty(int i) const {
+  if (i < 0 || i >= test_property_count())
+    internal::posix::Abort();
+  return test_properties_.at(i);
+}
+
+// Clears the test part results.
+void TestResult::ClearTestPartResults() {
+  test_part_results_.clear();
+}
+
+// Adds a test part result to the list.
+void TestResult::AddTestPartResult(const TestPartResult& test_part_result) {
+  test_part_results_.push_back(test_part_result);
+}
+
+// Adds a test property to the list. If a property with the same key as the
+// supplied property is already represented, the value of this test_property
+// replaces the old value for that key.
+void TestResult::RecordProperty(const TestProperty& test_property) {
+  if (!ValidateTestProperty(test_property)) {
+    return;
+  }
+  internal::MutexLock lock(&test_properites_mutex_);
+  const std::vector<TestProperty>::iterator property_with_matching_key =
+      std::find_if(test_properties_.begin(), test_properties_.end(),
+                   internal::TestPropertyKeyIs(test_property.key()));
+  if (property_with_matching_key == test_properties_.end()) {
+    test_properties_.push_back(test_property);
+    return;
+  }
+  property_with_matching_key->SetValue(test_property.value());
+}
+
+// Adds a failure if the key is a reserved attribute of Google Test
+// testcase tags.  Returns true if the property is valid.
+bool TestResult::ValidateTestProperty(const TestProperty& test_property) {
+  internal::String key(test_property.key());
+  if (key == "name" || key == "status" || key == "time" || key == "classname") {
+    ADD_FAILURE()
+        << "Reserved key used in RecordProperty(): "
+        << key
+        << " ('name', 'status', 'time', and 'classname' are reserved by "
+        << GTEST_NAME_ << ")";
+    return false;
+  }
+  return true;
+}
+
+// Clears the object.
+void TestResult::Clear() {
+  test_part_results_.clear();
+  test_properties_.clear();
+  death_test_count_ = 0;
+  elapsed_time_ = 0;
+}
+
+// Returns true iff the test failed.
+bool TestResult::Failed() const {
+  for (int i = 0; i < total_part_count(); ++i) {
+    if (GetTestPartResult(i).failed())
+      return true;
+  }
+  return false;
+}
+
+// Returns true iff the test part fatally failed.
+static bool TestPartFatallyFailed(const TestPartResult& result) {
+  return result.fatally_failed();
+}
+
+// Returns true iff the test fatally failed.
+bool TestResult::HasFatalFailure() const {
+  return CountIf(test_part_results_, TestPartFatallyFailed) > 0;
+}
+
+// Returns true iff the test part non-fatally failed.
+static bool TestPartNonfatallyFailed(const TestPartResult& result) {
+  return result.nonfatally_failed();
+}
+
+// Returns true iff the test has a non-fatal failure.
+bool TestResult::HasNonfatalFailure() const {
+  return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0;
+}
+
+// Gets the number of all test parts.  This is the sum of the number
+// of successful test parts and the number of failed test parts.
+int TestResult::total_part_count() const {
+  return static_cast<int>(test_part_results_.size());
+}
+
+// Returns the number of the test properties.
+int TestResult::test_property_count() const {
+  return static_cast<int>(test_properties_.size());
+}
+
+// class Test
+
+// Creates a Test object.
+
+// The c'tor saves the values of all Google Test flags.
+Test::Test()
+    : gtest_flag_saver_(new internal::GTestFlagSaver) {
+}
+
+// The d'tor restores the values of all Google Test flags.
+Test::~Test() {
+  delete gtest_flag_saver_;
+}
+
+// Sets up the test fixture.
+//
+// A sub-class may override this.
+void Test::SetUp() {
+}
+
+// Tears down the test fixture.
+//
+// A sub-class may override this.
+void Test::TearDown() {
+}
+
+// Allows user supplied key value pairs to be recorded for later output.
+void Test::RecordProperty(const char* key, const char* value) {
+  UnitTest::GetInstance()->RecordPropertyForCurrentTest(key, value);
+}
+
+// Allows user supplied key value pairs to be recorded for later output.
+void Test::RecordProperty(const char* key, int value) {
+  Message value_message;
+  value_message << value;
+  RecordProperty(key, value_message.GetString().c_str());
+}
+
+namespace internal {
+
+void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
+                                    const String& message) {
+  // This function is a friend of UnitTest and as such has access to
+  // AddTestPartResult.
+  UnitTest::GetInstance()->AddTestPartResult(
+      result_type,
+      NULL,  // No info about the source file where the exception occurred.
+      -1,    // We have no info on which line caused the exception.
+      message,
+      String());  // No stack trace, either.
+}
+
+}  // namespace internal
+
+// Google Test requires all tests in the same test case to use the same test
+// fixture class.  This function checks if the current test has the
+// same fixture class as the first test in the current test case.  If
+// yes, it returns true; otherwise it generates a Google Test failure and
+// returns false.
+bool Test::HasSameFixtureClass() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  const TestCase* const test_case = impl->current_test_case();
+
+  // Info about the first test in the current test case.
+  const TestInfo* const first_test_info = test_case->test_info_list()[0];
+  const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_;
+  const char* const first_test_name = first_test_info->name();
+
+  // Info about the current test.
+  const TestInfo* const this_test_info = impl->current_test_info();
+  const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_;
+  const char* const this_test_name = this_test_info->name();
+
+  if (this_fixture_id != first_fixture_id) {
+    // Is the first test defined using TEST?
+    const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId();
+    // Is this test defined using TEST?
+    const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId();
+
+    if (first_is_TEST || this_is_TEST) {
+      // The user mixed TEST and TEST_F in this test case - we'll tell
+      // him/her how to fix it.
+
+      // Gets the name of the TEST and the name of the TEST_F.  Note
+      // that first_is_TEST and this_is_TEST cannot both be true, as
+      // the fixture IDs are different for the two tests.
+      const char* const TEST_name =
+          first_is_TEST ? first_test_name : this_test_name;
+      const char* const TEST_F_name =
+          first_is_TEST ? this_test_name : first_test_name;
+
+      ADD_FAILURE()
+          << "All tests in the same test case must use the same test fixture\n"
+          << "class, so mixing TEST_F and TEST in the same test case is\n"
+          << "illegal.  In test case " << this_test_info->test_case_name()
+          << ",\n"
+          << "test " << TEST_F_name << " is defined using TEST_F but\n"
+          << "test " << TEST_name << " is defined using TEST.  You probably\n"
+          << "want to change the TEST to TEST_F or move it to another test\n"
+          << "case.";
+    } else {
+      // The user defined two fixture classes with the same name in
+      // two namespaces - we'll tell him/her how to fix it.
+      ADD_FAILURE()
+          << "All tests in the same test case must use the same test fixture\n"
+          << "class.  However, in test case "
+          << this_test_info->test_case_name() << ",\n"
+          << "you defined test " << first_test_name
+          << " and test " << this_test_name << "\n"
+          << "using two different test fixture classes.  This can happen if\n"
+          << "the two classes are from different namespaces or translation\n"
+          << "units and have the same name.  You should probably rename one\n"
+          << "of the classes to put the tests into different test cases.";
+    }
+    return false;
+  }
+
+  return true;
+}
+
+#if GTEST_HAS_SEH
+
+// Adds an "exception thrown" fatal failure to the current test.  This
+// function returns its result via an output parameter pointer because VC++
+// prohibits creation of objects with destructors on stack in functions
+// using __try (see error C2712).
+static internal::String* FormatSehExceptionMessage(DWORD exception_code,
+                                                   const char* location) {
+  Message message;
+  message << "SEH exception with code 0x" << std::setbase(16) <<
+    exception_code << std::setbase(10) << " thrown in " << location << ".";
+
+  return new internal::String(message.GetString());
+}
+
+#endif  // GTEST_HAS_SEH
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Adds an "exception thrown" fatal failure to the current test.
+static internal::String FormatCxxExceptionMessage(const char* description,
+                                                  const char* location) {
+  Message message;
+  if (description != NULL) {
+    message << "C++ exception with description \"" << description << "\"";
+  } else {
+    message << "Unknown C++ exception";
+  }
+  message << " thrown in " << location << ".";
+
+  return message.GetString();
+}
+
+static internal::String PrintTestPartResultToString(
+    const TestPartResult& test_part_result);
+
+// A failed Google Test assertion will throw an exception of this type when
+// GTEST_FLAG(throw_on_failure) is true (if exceptions are enabled).  We
+// derive it from std::runtime_error, which is for errors presumably
+// detectable only at run time.  Since std::runtime_error inherits from
+// std::exception, many testing frameworks know how to extract and print the
+// message inside it.
+class GoogleTestFailureException : public ::std::runtime_error {
+ public:
+  explicit GoogleTestFailureException(const TestPartResult& failure)
+      : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {}
+};
+#endif  // GTEST_HAS_EXCEPTIONS
+
+namespace internal {
+// We put these helper functions in the internal namespace as IBM's xlC
+// compiler rejects the code if they were declared static.
+
+// Runs the given method and handles SEH exceptions it throws, when
+// SEH is supported; returns the 0-value for type Result in case of an
+// SEH exception.  (Microsoft compilers cannot handle SEH and C++
+// exceptions in the same function.  Therefore, we provide a separate
+// wrapper function for handling SEH exceptions.)
+template <class T, typename Result>
+Result HandleSehExceptionsInMethodIfSupported(
+    T* object, Result (T::*method)(), const char* location) {
+#if GTEST_HAS_SEH
+  __try {
+    return (object->*method)();
+  } __except (internal::UnitTestOptions::GTestShouldProcessSEH(  // NOLINT
+      GetExceptionCode())) {
+    // We create the exception message on the heap because VC++ prohibits
+    // creation of objects with destructors on stack in functions using __try
+    // (see error C2712).
+    internal::String* exception_message = FormatSehExceptionMessage(
+        GetExceptionCode(), location);
+    internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,
+                                             *exception_message);
+    delete exception_message;
+    return static_cast<Result>(0);
+  }
+#else
+  (void)location;
+  return (object->*method)();
+#endif  // GTEST_HAS_SEH
+}
+
+// Runs the given method and catches and reports C++ and/or SEH-style
+// exceptions, if they are supported; returns the 0-value for type
+// Result in case of an SEH exception.
+template <class T, typename Result>
+Result HandleExceptionsInMethodIfSupported(
+    T* object, Result (T::*method)(), const char* location) {
+  // NOTE: The user code can affect the way in which Google Test handles
+  // exceptions by setting GTEST_FLAG(catch_exceptions), but only before
+  // RUN_ALL_TESTS() starts. It is technically possible to check the flag
+  // after the exception is caught and either report or re-throw the
+  // exception based on the flag's value:
+  //
+  // try {
+  //   // Perform the test method.
+  // } catch (...) {
+  //   if (GTEST_FLAG(catch_exceptions))
+  //     // Report the exception as failure.
+  //   else
+  //     throw;  // Re-throws the original exception.
+  // }
+  //
+  // However, the purpose of this flag is to allow the program to drop into
+  // the debugger when the exception is thrown. On most platforms, once the
+  // control enters the catch block, the exception origin information is
+  // lost and the debugger will stop the program at the point of the
+  // re-throw in this function -- instead of at the point of the original
+  // throw statement in the code under test.  For this reason, we perform
+  // the check early, sacrificing the ability to affect Google Test's
+  // exception handling in the method where the exception is thrown.
+  if (internal::GetUnitTestImpl()->catch_exceptions()) {
+#if GTEST_HAS_EXCEPTIONS
+    try {
+      return HandleSehExceptionsInMethodIfSupported(object, method, location);
+    } catch (const GoogleTestFailureException&) {  // NOLINT
+      // This exception doesn't originate in code under test. It makes no
+      // sense to report it as a test failure.
+      throw;
+    } catch (const std::exception& e) {  // NOLINT
+      internal::ReportFailureInUnknownLocation(
+          TestPartResult::kFatalFailure,
+          FormatCxxExceptionMessage(e.what(), location));
+    } catch (...) {  // NOLINT
+      internal::ReportFailureInUnknownLocation(
+          TestPartResult::kFatalFailure,
+          FormatCxxExceptionMessage(NULL, location));
+    }
+    return static_cast<Result>(0);
+#else
+    return HandleSehExceptionsInMethodIfSupported(object, method, location);
+#endif  // GTEST_HAS_EXCEPTIONS
+  } else {
+    return (object->*method)();
+  }
+}
+
+}  // namespace internal
+
+// Runs the test and updates the test result.
+void Test::Run() {
+  if (!HasSameFixtureClass()) return;
+
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()");
+  // We will run the test only if SetUp() was successful.
+  if (!HasFatalFailure()) {
+    impl->os_stack_trace_getter()->UponLeavingGTest();
+    internal::HandleExceptionsInMethodIfSupported(
+        this, &Test::TestBody, "the test body");
+  }
+
+  // However, we want to clean up as much as possible.  Hence we will
+  // always call TearDown(), even if SetUp() or the test body has
+  // failed.
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &Test::TearDown, "TearDown()");
+}
+
+// Returns true iff the current test has a fatal failure.
+bool Test::HasFatalFailure() {
+  return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure();
+}
+
+// Returns true iff the current test has a non-fatal failure.
+bool Test::HasNonfatalFailure() {
+  return internal::GetUnitTestImpl()->current_test_result()->
+      HasNonfatalFailure();
+}
+
+// class TestInfo
+
+// Constructs a TestInfo object. It assumes ownership of the test factory
+// object.
+// TODO(vladl@google.com): Make a_test_case_name and a_name const string&'s
+// to signify they cannot be NULLs.
+TestInfo::TestInfo(const char* a_test_case_name,
+                   const char* a_name,
+                   const char* a_type_param,
+                   const char* a_value_param,
+                   internal::TypeId fixture_class_id,
+                   internal::TestFactoryBase* factory)
+    : test_case_name_(a_test_case_name),
+      name_(a_name),
+      type_param_(a_type_param ? new std::string(a_type_param) : NULL),
+      value_param_(a_value_param ? new std::string(a_value_param) : NULL),
+      fixture_class_id_(fixture_class_id),
+      should_run_(false),
+      is_disabled_(false),
+      matches_filter_(false),
+      factory_(factory),
+      result_() {}
+
+// Destructs a TestInfo object.
+TestInfo::~TestInfo() { delete factory_; }
+
+namespace internal {
+
+// Creates a new TestInfo object and registers it with Google Test;
+// returns the created object.
+//
+// Arguments:
+//
+//   test_case_name:   name of the test case
+//   name:             name of the test
+//   type_param:       the name of the test's type parameter, or NULL if
+//                     this is not a typed or a type-parameterized test.
+//   value_param:      text representation of the test's value parameter,
+//                     or NULL if this is not a value-parameterized test.
+//   fixture_class_id: ID of the test fixture class
+//   set_up_tc:        pointer to the function that sets up the test case
+//   tear_down_tc:     pointer to the function that tears down the test case
+//   factory:          pointer to the factory that creates a test object.
+//                     The newly created TestInfo instance will assume
+//                     ownership of the factory object.
+TestInfo* MakeAndRegisterTestInfo(
+    const char* test_case_name, const char* name,
+    const char* type_param,
+    const char* value_param,
+    TypeId fixture_class_id,
+    SetUpTestCaseFunc set_up_tc,
+    TearDownTestCaseFunc tear_down_tc,
+    TestFactoryBase* factory) {
+  TestInfo* const test_info =
+      new TestInfo(test_case_name, name, type_param, value_param,
+                   fixture_class_id, factory);
+  GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
+  return test_info;
+}
+
+#if GTEST_HAS_PARAM_TEST
+void ReportInvalidTestCaseType(const char* test_case_name,
+                               const char* file, int line) {
+  Message errors;
+  errors
+      << "Attempted redefinition of test case " << test_case_name << ".\n"
+      << "All tests in the same test case must use the same test fixture\n"
+      << "class.  However, in test case " << test_case_name << ", you tried\n"
+      << "to define a test using a fixture class different from the one\n"
+      << "used earlier. This can happen if the two fixture classes are\n"
+      << "from different namespaces and have the same name. You should\n"
+      << "probably rename one of the classes to put the tests into different\n"
+      << "test cases.";
+
+  fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
+          errors.GetString().c_str());
+}
+#endif  // GTEST_HAS_PARAM_TEST
+
+}  // namespace internal
+
+namespace {
+
+// A predicate that checks the test name of a TestInfo against a known
+// value.
+//
+// This is used for implementation of the TestCase class only.  We put
+// it in the anonymous namespace to prevent polluting the outer
+// namespace.
+//
+// TestNameIs is copyable.
+class TestNameIs {
+ public:
+  // Constructor.
+  //
+  // TestNameIs has NO default constructor.
+  explicit TestNameIs(const char* name)
+      : name_(name) {}
+
+  // Returns true iff the test name of test_info matches name_.
+  bool operator()(const TestInfo * test_info) const {
+    return test_info && internal::String(test_info->name()).Compare(name_) == 0;
+  }
+
+ private:
+  internal::String name_;
+};
+
+}  // namespace
+
+namespace internal {
+
+// This method expands all parameterized tests registered with macros TEST_P
+// and INSTANTIATE_TEST_CASE_P into regular tests and registers those.
+// This will be done just once during the program runtime.
+void UnitTestImpl::RegisterParameterizedTests() {
+#if GTEST_HAS_PARAM_TEST
+  if (!parameterized_tests_registered_) {
+    parameterized_test_registry_.RegisterTests();
+    parameterized_tests_registered_ = true;
+  }
+#endif
+}
+
+}  // namespace internal
+
+// Creates the test object, runs it, records its result, and then
+// deletes it.
+void TestInfo::Run() {
+  if (!should_run_) return;
+
+  // Tells UnitTest where to store test result.
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->set_current_test_info(this);
+
+  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+  // Notifies the unit test event listeners that a test is about to start.
+  repeater->OnTestStart(*this);
+
+  const TimeInMillis start = internal::GetTimeInMillis();
+
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+
+  // Creates the test object.
+  Test* const test = internal::HandleExceptionsInMethodIfSupported(
+      factory_, &internal::TestFactoryBase::CreateTest,
+      "the test fixture's constructor");
+
+  // Runs the test only if the test object was created and its
+  // constructor didn't generate a fatal failure.
+  if ((test != NULL) && !Test::HasFatalFailure()) {
+    // This doesn't throw as all user code that can throw are wrapped into
+    // exception handling code.
+    test->Run();
+  }
+
+  // Deletes the test object.
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      test, &Test::DeleteSelf_, "the test fixture's destructor");
+
+  result_.set_elapsed_time(internal::GetTimeInMillis() - start);
+
+  // Notifies the unit test event listener that a test has just finished.
+  repeater->OnTestEnd(*this);
+
+  // Tells UnitTest to stop associating assertion results to this
+  // test.
+  impl->set_current_test_info(NULL);
+}
+
+// class TestCase
+
+// Gets the number of successful tests in this test case.
+int TestCase::successful_test_count() const {
+  return CountIf(test_info_list_, TestPassed);
+}
+
+// Gets the number of failed tests in this test case.
+int TestCase::failed_test_count() const {
+  return CountIf(test_info_list_, TestFailed);
+}
+
+int TestCase::disabled_test_count() const {
+  return CountIf(test_info_list_, TestDisabled);
+}
+
+// Get the number of tests in this test case that should run.
+int TestCase::test_to_run_count() const {
+  return CountIf(test_info_list_, ShouldRunTest);
+}
+
+// Gets the number of all tests.
+int TestCase::total_test_count() const {
+  return static_cast<int>(test_info_list_.size());
+}
+
+// Creates a TestCase with the given name.
+//
+// Arguments:
+//
+//   name:         name of the test case
+//   a_type_param: the name of the test case's type parameter, or NULL if
+//                 this is not a typed or a type-parameterized test case.
+//   set_up_tc:    pointer to the function that sets up the test case
+//   tear_down_tc: pointer to the function that tears down the test case
+TestCase::TestCase(const char* a_name, const char* a_type_param,
+                   Test::SetUpTestCaseFunc set_up_tc,
+                   Test::TearDownTestCaseFunc tear_down_tc)
+    : name_(a_name),
+      type_param_(a_type_param ? new std::string(a_type_param) : NULL),
+      set_up_tc_(set_up_tc),
+      tear_down_tc_(tear_down_tc),
+      should_run_(false),
+      elapsed_time_(0) {
+}
+
+// Destructor of TestCase.
+TestCase::~TestCase() {
+  // Deletes every Test in the collection.
+  ForEach(test_info_list_, internal::Delete<TestInfo>);
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+const TestInfo* TestCase::GetTestInfo(int i) const {
+  const int index = GetElementOr(test_indices_, i, -1);
+  return index < 0 ? NULL : test_info_list_[index];
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+TestInfo* TestCase::GetMutableTestInfo(int i) {
+  const int index = GetElementOr(test_indices_, i, -1);
+  return index < 0 ? NULL : test_info_list_[index];
+}
+
+// Adds a test to this test case.  Will delete the test upon
+// destruction of the TestCase object.
+void TestCase::AddTestInfo(TestInfo * test_info) {
+  test_info_list_.push_back(test_info);
+  test_indices_.push_back(static_cast<int>(test_indices_.size()));
+}
+
+// Runs every test in this TestCase.
+void TestCase::Run() {
+  if (!should_run_) return;
+
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->set_current_test_case(this);
+
+  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+  repeater->OnTestCaseStart(*this);
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &TestCase::RunSetUpTestCase, "SetUpTestCase()");
+
+  const internal::TimeInMillis start = internal::GetTimeInMillis();
+  for (int i = 0; i < total_test_count(); i++) {
+    GetMutableTestInfo(i)->Run();
+  }
+  elapsed_time_ = internal::GetTimeInMillis() - start;
+
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &TestCase::RunTearDownTestCase, "TearDownTestCase()");
+
+  repeater->OnTestCaseEnd(*this);
+  impl->set_current_test_case(NULL);
+}
+
+// Clears the results of all tests in this test case.
+void TestCase::ClearResult() {
+  ForEach(test_info_list_, TestInfo::ClearTestResult);
+}
+
+// Shuffles the tests in this test case.
+void TestCase::ShuffleTests(internal::Random* random) {
+  Shuffle(random, &test_indices_);
+}
+
+// Restores the test order to before the first shuffle.
+void TestCase::UnshuffleTests() {
+  for (size_t i = 0; i < test_indices_.size(); i++) {
+    test_indices_[i] = static_cast<int>(i);
+  }
+}
+
+// Formats a countable noun.  Depending on its quantity, either the
+// singular form or the plural form is used. e.g.
+//
+// FormatCountableNoun(1, "formula", "formuli") returns "1 formula".
+// FormatCountableNoun(5, "book", "books") returns "5 books".
+static internal::String FormatCountableNoun(int count,
+                                            const char * singular_form,
+                                            const char * plural_form) {
+  return internal::String::Format("%d %s", count,
+                                  count == 1 ? singular_form : plural_form);
+}
+
+// Formats the count of tests.
+static internal::String FormatTestCount(int test_count) {
+  return FormatCountableNoun(test_count, "test", "tests");
+}
+
+// Formats the count of test cases.
+static internal::String FormatTestCaseCount(int test_case_count) {
+  return FormatCountableNoun(test_case_count, "test case", "test cases");
+}
+
+// Converts a TestPartResult::Type enum to human-friendly string
+// representation.  Both kNonFatalFailure and kFatalFailure are translated
+// to "Failure", as the user usually doesn't care about the difference
+// between the two when viewing the test result.
+static const char * TestPartResultTypeToString(TestPartResult::Type type) {
+  switch (type) {
+    case TestPartResult::kSuccess:
+      return "Success";
+
+    case TestPartResult::kNonFatalFailure:
+    case TestPartResult::kFatalFailure:
+#ifdef _MSC_VER
+      return "error: ";
+#else
+      return "Failure\n";
+#endif
+    default:
+      return "Unknown result type";
+  }
+}
+
+// Prints a TestPartResult to a String.
+static internal::String PrintTestPartResultToString(
+    const TestPartResult& test_part_result) {
+  return (Message()
+          << internal::FormatFileLocation(test_part_result.file_name(),
+                                          test_part_result.line_number())
+          << " " << TestPartResultTypeToString(test_part_result.type())
+          << test_part_result.message()).GetString();
+}
+
+// Prints a TestPartResult.
+static void PrintTestPartResult(const TestPartResult& test_part_result) {
+  const internal::String& result =
+      PrintTestPartResultToString(test_part_result);
+  printf("%s\n", result.c_str());
+  fflush(stdout);
+  // If the test program runs in Visual Studio or a debugger, the
+  // following statements add the test part result message to the Output
+  // window such that the user can double-click on it to jump to the
+  // corresponding source code location; otherwise they do nothing.
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+  // We don't call OutputDebugString*() on Windows Mobile, as printing
+  // to stdout is done by OutputDebugString() there already - we don't
+  // want the same message printed twice.
+  ::OutputDebugStringA(result.c_str());
+  ::OutputDebugStringA("\n");
+#endif
+}
+
+// class PrettyUnitTestResultPrinter
+
+namespace internal {
+
+enum GTestColor {
+  COLOR_DEFAULT,
+  COLOR_RED,
+  COLOR_GREEN,
+  COLOR_YELLOW
+};
+
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+
+// Returns the character attribute for the given color.
+WORD GetColorAttribute(GTestColor color) {
+  switch (color) {
+    case COLOR_RED:    return FOREGROUND_RED;
+    case COLOR_GREEN:  return FOREGROUND_GREEN;
+    case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
+    default:           return 0;
+  }
+}
+
+#else
+
+// Returns the ANSI color code for the given color.  COLOR_DEFAULT is
+// an invalid input.
+const char* GetAnsiColorCode(GTestColor color) {
+  switch (color) {
+    case COLOR_RED:     return "1";
+    case COLOR_GREEN:   return "2";
+    case COLOR_YELLOW:  return "3";
+    default:            return NULL;
+  };
+}
+
+#endif  // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+
+// Returns true iff Google Test should use colors in the output.
+bool ShouldUseColor(bool stdout_is_tty) {
+  const char* const gtest_color = GTEST_FLAG(color).c_str();
+
+  if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) {
+#if GTEST_OS_WINDOWS
+    // On Windows the TERM variable is usually not set, but the
+    // console there does support colors.
+    return stdout_is_tty;
+#else
+    // On non-Windows platforms, we rely on the TERM variable.
+    const char* const term = posix::GetEnv("TERM");
+    const bool term_supports_color =
+        String::CStringEquals(term, "xterm") ||
+        String::CStringEquals(term, "xterm-color") ||
+        String::CStringEquals(term, "xterm-256color") ||
+        String::CStringEquals(term, "screen") ||
+        String::CStringEquals(term, "linux") ||
+        String::CStringEquals(term, "cygwin");
+    return stdout_is_tty && term_supports_color;
+#endif  // GTEST_OS_WINDOWS
+  }
+
+  return String::CaseInsensitiveCStringEquals(gtest_color, "yes") ||
+      String::CaseInsensitiveCStringEquals(gtest_color, "true") ||
+      String::CaseInsensitiveCStringEquals(gtest_color, "t") ||
+      String::CStringEquals(gtest_color, "1");
+  // We take "yes", "true", "t", and "1" as meaning "yes".  If the
+  // value is neither one of these nor "auto", we treat it as "no" to
+  // be conservative.
+}
+
+// Helpers for printing colored strings to stdout. Note that on Windows, we
+// cannot simply emit special characters and have the terminal change colors.
+// This routine must actually emit the characters rather than return a string
+// that would be colored when printed, as can be done on Linux.
+void ColoredPrintf(GTestColor color, const char* fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+
+#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS
+  const bool use_color = false;
+#else
+  static const bool in_color_mode =
+      ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0);
+  const bool use_color = in_color_mode && (color != COLOR_DEFAULT);
+#endif  // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS
+  // The '!= 0' comparison is necessary to satisfy MSVC 7.1.
+
+  if (!use_color) {
+    vprintf(fmt, args);
+    va_end(args);
+    return;
+  }
+
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+  const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
+
+  // Gets the current text color.
+  CONSOLE_SCREEN_BUFFER_INFO buffer_info;
+  GetConsoleScreenBufferInfo(stdout_handle, &buffer_info);
+  const WORD old_color_attrs = buffer_info.wAttributes;
+
+  // We need to flush the stream buffers into the console before each
+  // SetConsoleTextAttribute call lest it affect the text that is already
+  // printed but has not yet reached the console.
+  fflush(stdout);
+  SetConsoleTextAttribute(stdout_handle,
+                          GetColorAttribute(color) | FOREGROUND_INTENSITY);
+  vprintf(fmt, args);
+
+  fflush(stdout);
+  // Restores the text color.
+  SetConsoleTextAttribute(stdout_handle, old_color_attrs);
+#else
+  printf("\033[0;3%sm", GetAnsiColorCode(color));
+  vprintf(fmt, args);
+  printf("\033[m");  // Resets the terminal to default.
+#endif  // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+  va_end(args);
+}
+
+void PrintFullTestCommentIfPresent(const TestInfo& test_info) {
+  const char* const type_param = test_info.type_param();
+  const char* const value_param = test_info.value_param();
+
+  if (type_param != NULL || value_param != NULL) {
+    printf(", where ");
+    if (type_param != NULL) {
+      printf("TypeParam = %s", type_param);
+      if (value_param != NULL)
+        printf(" and ");
+    }
+    if (value_param != NULL) {
+      printf("GetParam() = %s", value_param);
+    }
+  }
+}
+
+// This class implements the TestEventListener interface.
+//
+// Class PrettyUnitTestResultPrinter is copyable.
+class PrettyUnitTestResultPrinter : public TestEventListener {
+ public:
+  PrettyUnitTestResultPrinter() {}
+  static void PrintTestName(const char * test_case, const char * test) {
+    printf("%s.%s", test_case, test);
+  }
+
+  // The following methods override what's in the TestEventListener class.
+  virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration);
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestCaseStart(const TestCase& test_case);
+  virtual void OnTestStart(const TestInfo& test_info);
+  virtual void OnTestPartResult(const TestPartResult& result);
+  virtual void OnTestEnd(const TestInfo& test_info);
+  virtual void OnTestCaseEnd(const TestCase& test_case);
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+  virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {}
+
+ private:
+  static void PrintFailedTests(const UnitTest& unit_test);
+
+  internal::String test_case_name_;
+};
+
+  // Fired before each iteration of tests starts.
+void PrettyUnitTestResultPrinter::OnTestIterationStart(
+    const UnitTest& unit_test, int iteration) {
+  if (GTEST_FLAG(repeat) != 1)
+    printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1);
+
+  const char* const filter = GTEST_FLAG(filter).c_str();
+
+  // Prints the filter if it's not *.  This reminds the user that some
+  // tests may be skipped.
+  if (!internal::String::CStringEquals(filter, kUniversalFilter)) {
+    ColoredPrintf(COLOR_YELLOW,
+                  "Note: %s filter = %s\n", GTEST_NAME_, filter);
+  }
+
+  if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) {
+    const Int32 shard_index = Int32FromEnvOrDie(kTestShardIndex, -1);
+    ColoredPrintf(COLOR_YELLOW,
+                  "Note: This is test shard %d of %s.\n",
+                  static_cast<int>(shard_index) + 1,
+                  internal::posix::GetEnv(kTestTotalShards));
+  }
+
+  if (GTEST_FLAG(shuffle)) {
+    ColoredPrintf(COLOR_YELLOW,
+                  "Note: Randomizing tests' orders with a seed of %d .\n",
+                  unit_test.random_seed());
+  }
+
+  ColoredPrintf(COLOR_GREEN,  "[==========] ");
+  printf("Running %s from %s.\n",
+         FormatTestCount(unit_test.test_to_run_count()).c_str(),
+         FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str());
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart(
+    const UnitTest& /*unit_test*/) {
+  ColoredPrintf(COLOR_GREEN,  "[----------] ");
+  printf("Global test environment set-up.\n");
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) {
+  test_case_name_ = test_case.name();
+  const internal::String counts =
+      FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
+  ColoredPrintf(COLOR_GREEN, "[----------] ");
+  printf("%s from %s", counts.c_str(), test_case_name_.c_str());
+  if (test_case.type_param() == NULL) {
+    printf("\n");
+  } else {
+    printf(", where TypeParam = %s\n", test_case.type_param());
+  }
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) {
+  ColoredPrintf(COLOR_GREEN,  "[ RUN      ] ");
+  PrintTestName(test_case_name_.c_str(), test_info.name());
+  printf("\n");
+  fflush(stdout);
+}
+
+// Called after an assertion failure.
+void PrettyUnitTestResultPrinter::OnTestPartResult(
+    const TestPartResult& result) {
+  // If the test part succeeded, we don't need to do anything.
+  if (result.type() == TestPartResult::kSuccess)
+    return;
+
+  // Print failure message from the assertion (e.g. expected this and got that).
+  PrintTestPartResult(result);
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) {
+  if (test_info.result()->Passed()) {
+    ColoredPrintf(COLOR_GREEN, "[       OK ] ");
+  } else {
+    ColoredPrintf(COLOR_RED, "[  FAILED  ] ");
+  }
+  PrintTestName(test_case_name_.c_str(), test_info.name());
+  if (test_info.result()->Failed())
+    PrintFullTestCommentIfPresent(test_info);
+
+  if (GTEST_FLAG(print_time)) {
+    printf(" (%s ms)\n", internal::StreamableToString(
+           test_info.result()->elapsed_time()).c_str());
+  } else {
+    printf("\n");
+  }
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) {
+  if (!GTEST_FLAG(print_time)) return;
+
+  test_case_name_ = test_case.name();
+  const internal::String counts =
+      FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
+  ColoredPrintf(COLOR_GREEN, "[----------] ");
+  printf("%s from %s (%s ms total)\n\n",
+         counts.c_str(), test_case_name_.c_str(),
+         internal::StreamableToString(test_case.elapsed_time()).c_str());
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart(
+    const UnitTest& /*unit_test*/) {
+  ColoredPrintf(COLOR_GREEN,  "[----------] ");
+  printf("Global test environment tear-down\n");
+  fflush(stdout);
+}
+
+// Internal helper for printing the list of failed tests.
+void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) {
+  const int failed_test_count = unit_test.failed_test_count();
+  if (failed_test_count == 0) {
+    return;
+  }
+
+  for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
+    const TestCase& test_case = *unit_test.GetTestCase(i);
+    if (!test_case.should_run() || (test_case.failed_test_count() == 0)) {
+      continue;
+    }
+    for (int j = 0; j < test_case.total_test_count(); ++j) {
+      const TestInfo& test_info = *test_case.GetTestInfo(j);
+      if (!test_info.should_run() || test_info.result()->Passed()) {
+        continue;
+      }
+      ColoredPrintf(COLOR_RED, "[  FAILED  ] ");
+      printf("%s.%s", test_case.name(), test_info.name());
+      PrintFullTestCommentIfPresent(test_info);
+      printf("\n");
+    }
+  }
+}
+
+void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+                                                     int /*iteration*/) {
+  ColoredPrintf(COLOR_GREEN,  "[==========] ");
+  printf("%s from %s ran.",
+         FormatTestCount(unit_test.test_to_run_count()).c_str(),
+         FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str());
+  if (GTEST_FLAG(print_time)) {
+    printf(" (%s ms total)",
+           internal::StreamableToString(unit_test.elapsed_time()).c_str());
+  }
+  printf("\n");
+  ColoredPrintf(COLOR_GREEN,  "[  PASSED  ] ");
+  printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str());
+
+  int num_failures = unit_test.failed_test_count();
+  if (!unit_test.Passed()) {
+    const int failed_test_count = unit_test.failed_test_count();
+    ColoredPrintf(COLOR_RED,  "[  FAILED  ] ");
+    printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str());
+    PrintFailedTests(unit_test);
+    printf("\n%2d FAILED %s\n", num_failures,
+                        num_failures == 1 ? "TEST" : "TESTS");
+  }
+
+  int num_disabled = unit_test.disabled_test_count();
+  if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) {
+    if (!num_failures) {
+      printf("\n");  // Add a spacer if no FAILURE banner is displayed.
+    }
+    ColoredPrintf(COLOR_YELLOW,
+                  "  YOU HAVE %d DISABLED %s\n\n",
+                  num_disabled,
+                  num_disabled == 1 ? "TEST" : "TESTS");
+  }
+  // Ensure that Google Test output is printed before, e.g., heapchecker output.
+  fflush(stdout);
+}
+
+// End PrettyUnitTestResultPrinter
+
+// class TestEventRepeater
+//
+// This class forwards events to other event listeners.
+class TestEventRepeater : public TestEventListener {
+ public:
+  TestEventRepeater() : forwarding_enabled_(true) {}
+  virtual ~TestEventRepeater();
+  void Append(TestEventListener *listener);
+  TestEventListener* Release(TestEventListener* listener);
+
+  // Controls whether events will be forwarded to listeners_. Set to false
+  // in death test child processes.
+  bool forwarding_enabled() const { return forwarding_enabled_; }
+  void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; }
+
+  virtual void OnTestProgramStart(const UnitTest& unit_test);
+  virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration);
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test);
+  virtual void OnTestCaseStart(const TestCase& test_case);
+  virtual void OnTestStart(const TestInfo& test_info);
+  virtual void OnTestPartResult(const TestPartResult& result);
+  virtual void OnTestEnd(const TestInfo& test_info);
+  virtual void OnTestCaseEnd(const TestCase& test_case);
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test);
+  virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+  virtual void OnTestProgramEnd(const UnitTest& unit_test);
+
+ private:
+  // Controls whether events will be forwarded to listeners_. Set to false
+  // in death test child processes.
+  bool forwarding_enabled_;
+  // The list of listeners that receive events.
+  std::vector<TestEventListener*> listeners_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater);
+};
+
+TestEventRepeater::~TestEventRepeater() {
+  ForEach(listeners_, Delete<TestEventListener>);
+}
+
+void TestEventRepeater::Append(TestEventListener *listener) {
+  listeners_.push_back(listener);
+}
+
+// TODO(vladl@google.com): Factor the search functionality into Vector::Find.
+TestEventListener* TestEventRepeater::Release(TestEventListener *listener) {
+  for (size_t i = 0; i < listeners_.size(); ++i) {
+    if (listeners_[i] == listener) {
+      listeners_.erase(listeners_.begin() + i);
+      return listener;
+    }
+  }
+
+  return NULL;
+}
+
+// Since most methods are very similar, use macros to reduce boilerplate.
+// This defines a member that forwards the call to all listeners.
+#define GTEST_REPEATER_METHOD_(Name, Type) \
+void TestEventRepeater::Name(const Type& parameter) { \
+  if (forwarding_enabled_) { \
+    for (size_t i = 0; i < listeners_.size(); i++) { \
+      listeners_[i]->Name(parameter); \
+    } \
+  } \
+}
+// This defines a member that forwards the call to all listeners in reverse
+// order.
+#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \
+void TestEventRepeater::Name(const Type& parameter) { \
+  if (forwarding_enabled_) { \
+    for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) { \
+      listeners_[i]->Name(parameter); \
+    } \
+  } \
+}
+
+GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest)
+GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest)
+GTEST_REPEATER_METHOD_(OnTestCaseStart, TestCase)
+GTEST_REPEATER_METHOD_(OnTestStart, TestInfo)
+GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult)
+GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestCase)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest)
+
+#undef GTEST_REPEATER_METHOD_
+#undef GTEST_REVERSE_REPEATER_METHOD_
+
+void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test,
+                                             int iteration) {
+  if (forwarding_enabled_) {
+    for (size_t i = 0; i < listeners_.size(); i++) {
+      listeners_[i]->OnTestIterationStart(unit_test, iteration);
+    }
+  }
+}
+
+void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test,
+                                           int iteration) {
+  if (forwarding_enabled_) {
+    for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) {
+      listeners_[i]->OnTestIterationEnd(unit_test, iteration);
+    }
+  }
+}
+
+// End TestEventRepeater
+
+// This class generates an XML output file.
+class XmlUnitTestResultPrinter : public EmptyTestEventListener {
+ public:
+  explicit XmlUnitTestResultPrinter(const char* output_file);
+
+  virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+
+ private:
+  // Is c a whitespace character that is normalized to a space character
+  // when it appears in an XML attribute value?
+  static bool IsNormalizableWhitespace(char c) {
+    return c == 0x9 || c == 0xA || c == 0xD;
+  }
+
+  // May c appear in a well-formed XML document?
+  static bool IsValidXmlCharacter(char c) {
+    return IsNormalizableWhitespace(c) || c >= 0x20;
+  }
+
+  // Returns an XML-escaped copy of the input string str.  If
+  // is_attribute is true, the text is meant to appear as an attribute
+  // value, and normalizable whitespace is preserved by replacing it
+  // with character references.
+  static String EscapeXml(const char* str, bool is_attribute);
+
+  // Returns the given string with all characters invalid in XML removed.
+  static string RemoveInvalidXmlCharacters(const string& str);
+
+  // Convenience wrapper around EscapeXml when str is an attribute value.
+  static String EscapeXmlAttribute(const char* str) {
+    return EscapeXml(str, true);
+  }
+
+  // Convenience wrapper around EscapeXml when str is not an attribute value.
+  static String EscapeXmlText(const char* str) { return EscapeXml(str, false); }
+
+  // Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
+  static void OutputXmlCDataSection(::std::ostream* stream, const char* data);
+
+  // Streams an XML representation of a TestInfo object.
+  static void OutputXmlTestInfo(::std::ostream* stream,
+                                const char* test_case_name,
+                                const TestInfo& test_info);
+
+  // Prints an XML representation of a TestCase object
+  static void PrintXmlTestCase(FILE* out, const TestCase& test_case);
+
+  // Prints an XML summary of unit_test to output stream out.
+  static void PrintXmlUnitTest(FILE* out, const UnitTest& unit_test);
+
+  // Produces a string representing the test properties in a result as space
+  // delimited XML attributes based on the property key="value" pairs.
+  // When the String is not empty, it includes a space at the beginning,
+  // to delimit this attribute from prior attributes.
+  static String TestPropertiesAsXmlAttributes(const TestResult& result);
+
+  // The output file.
+  const String output_file_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter);
+};
+
+// Creates a new XmlUnitTestResultPrinter.
+XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file)
+    : output_file_(output_file) {
+  if (output_file_.c_str() == NULL || output_file_.empty()) {
+    fprintf(stderr, "XML output file may not be null\n");
+    fflush(stderr);
+    exit(EXIT_FAILURE);
+  }
+}
+
+// Called after the unit test ends.
+void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+                                                  int /*iteration*/) {
+  FILE* xmlout = NULL;
+  FilePath output_file(output_file_);
+  FilePath output_dir(output_file.RemoveFileName());
+
+  if (output_dir.CreateDirectoriesRecursively()) {
+    xmlout = posix::FOpen(output_file_.c_str(), "w");
+  }
+  if (xmlout == NULL) {
+    // TODO(wan): report the reason of the failure.
+    //
+    // We don't do it for now as:
+    //
+    //   1. There is no urgent need for it.
+    //   2. It's a bit involved to make the errno variable thread-safe on
+    //      all three operating systems (Linux, Windows, and Mac OS).
+    //   3. To interpret the meaning of errno in a thread-safe way,
+    //      we need the strerror_r() function, which is not available on
+    //      Windows.
+    fprintf(stderr,
+            "Unable to open file \"%s\"\n",
+            output_file_.c_str());
+    fflush(stderr);
+    exit(EXIT_FAILURE);
+  }
+  PrintXmlUnitTest(xmlout, unit_test);
+  fclose(xmlout);
+}
+
+// Returns an XML-escaped copy of the input string str.  If is_attribute
+// is true, the text is meant to appear as an attribute value, and
+// normalizable whitespace is preserved by replacing it with character
+// references.
+//
+// Invalid XML characters in str, if any, are stripped from the output.
+// It is expected that most, if not all, of the text processed by this
+// module will consist of ordinary English text.
+// If this module is ever modified to produce version 1.1 XML output,
+// most invalid characters can be retained using character references.
+// TODO(wan): It might be nice to have a minimally invasive, human-readable
+// escaping scheme for invalid characters, rather than dropping them.
+String XmlUnitTestResultPrinter::EscapeXml(const char* str, bool is_attribute) {
+  Message m;
+
+  if (str != NULL) {
+    for (const char* src = str; *src; ++src) {
+      switch (*src) {
+        case '<':
+          m << "&lt;";
+          break;
+        case '>':
+          m << "&gt;";
+          break;
+        case '&':
+          m << "&amp;";
+          break;
+        case '\'':
+          if (is_attribute)
+            m << "&apos;";
+          else
+            m << '\'';
+          break;
+        case '"':
+          if (is_attribute)
+            m << "&quot;";
+          else
+            m << '"';
+          break;
+        default:
+          if (IsValidXmlCharacter(*src)) {
+            if (is_attribute && IsNormalizableWhitespace(*src))
+              m << String::Format("&#x%02X;", unsigned(*src));
+            else
+              m << *src;
+          }
+          break;
+      }
+    }
+  }
+
+  return m.GetString();
+}
+
+// Returns the given string with all characters invalid in XML removed.
+// Currently invalid characters are dropped from the string. An
+// alternative is to replace them with certain characters such as . or ?.
+string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(const string& str) {
+  string output;
+  output.reserve(str.size());
+  for (string::const_iterator it = str.begin(); it != str.end(); ++it)
+    if (IsValidXmlCharacter(*it))
+      output.push_back(*it);
+
+  return output;
+}
+
+// The following routines generate an XML representation of a UnitTest
+// object.
+//
+// This is how Google Test concepts map to the DTD:
+//
+// <testsuites name="AllTests">        <-- corresponds to a UnitTest object
+//   <testsuite name="testcase-name">  <-- corresponds to a TestCase object
+//     <testcase name="test-name">     <-- corresponds to a TestInfo object
+//       <failure message="...">...</failure>
+//       <failure message="...">...</failure>
+//       <failure message="...">...</failure>
+//                                     <-- individual assertion failures
+//     </testcase>
+//   </testsuite>
+// </testsuites>
+
+// Formats the given time in milliseconds as seconds.
+std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) {
+  ::std::stringstream ss;
+  ss << ms/1000.0;
+  return ss.str();
+}
+
+// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
+void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream,
+                                                     const char* data) {
+  const char* segment = data;
+  *stream << "<![CDATA[";
+  for (;;) {
+    const char* const next_segment = strstr(segment, "]]>");
+    if (next_segment != NULL) {
+      stream->write(
+          segment, static_cast<std::streamsize>(next_segment - segment));
+      *stream << "]]>]]&gt;<![CDATA[";
+      segment = next_segment + strlen("]]>");
+    } else {
+      *stream << segment;
+      break;
+    }
+  }
+  *stream << "]]>";
+}
+
+// Prints an XML representation of a TestInfo object.
+// TODO(wan): There is also value in printing properties with the plain printer.
+void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
+                                                 const char* test_case_name,
+                                                 const TestInfo& test_info) {
+  const TestResult& result = *test_info.result();
+  *stream << "    <testcase name=\""
+          << EscapeXmlAttribute(test_info.name()).c_str() << "\"";
+
+  if (test_info.value_param() != NULL) {
+    *stream << " value_param=\"" << EscapeXmlAttribute(test_info.value_param())
+            << "\"";
+  }
+  if (test_info.type_param() != NULL) {
+    *stream << " type_param=\"" << EscapeXmlAttribute(test_info.type_param())
+            << "\"";
+  }
+
+  *stream << " status=\""
+          << (test_info.should_run() ? "run" : "notrun")
+          << "\" time=\""
+          << FormatTimeInMillisAsSeconds(result.elapsed_time())
+          << "\" classname=\"" << EscapeXmlAttribute(test_case_name).c_str()
+          << "\"" << TestPropertiesAsXmlAttributes(result).c_str();
+
+  int failures = 0;
+  for (int i = 0; i < result.total_part_count(); ++i) {
+    const TestPartResult& part = result.GetTestPartResult(i);
+    if (part.failed()) {
+      if (++failures == 1)
+        *stream << ">\n";
+      *stream << "      <failure message=\""
+              << EscapeXmlAttribute(part.summary()).c_str()
+              << "\" type=\"\">";
+      const string location = internal::FormatCompilerIndependentFileLocation(
+          part.file_name(), part.line_number());
+      const string message = location + "\n" + part.message();
+      OutputXmlCDataSection(stream,
+                            RemoveInvalidXmlCharacters(message).c_str());
+      *stream << "</failure>\n";
+    }
+  }
+
+  if (failures == 0)
+    *stream << " />\n";
+  else
+    *stream << "    </testcase>\n";
+}
+
+// Prints an XML representation of a TestCase object
+void XmlUnitTestResultPrinter::PrintXmlTestCase(FILE* out,
+                                                const TestCase& test_case) {
+  fprintf(out,
+          "  <testsuite name=\"%s\" tests=\"%d\" failures=\"%d\" "
+          "disabled=\"%d\" ",
+          EscapeXmlAttribute(test_case.name()).c_str(),
+          test_case.total_test_count(),
+          test_case.failed_test_count(),
+          test_case.disabled_test_count());
+  fprintf(out,
+          "errors=\"0\" time=\"%s\">\n",
+          FormatTimeInMillisAsSeconds(test_case.elapsed_time()).c_str());
+  for (int i = 0; i < test_case.total_test_count(); ++i) {
+    ::std::stringstream stream;
+    OutputXmlTestInfo(&stream, test_case.name(), *test_case.GetTestInfo(i));
+    fprintf(out, "%s", StringStreamToString(&stream).c_str());
+  }
+  fprintf(out, "  </testsuite>\n");
+}
+
+// Prints an XML summary of unit_test to output stream out.
+void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out,
+                                                const UnitTest& unit_test) {
+  fprintf(out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+  fprintf(out,
+          "<testsuites tests=\"%d\" failures=\"%d\" disabled=\"%d\" "
+          "errors=\"0\" time=\"%s\" ",
+          unit_test.total_test_count(),
+          unit_test.failed_test_count(),
+          unit_test.disabled_test_count(),
+          FormatTimeInMillisAsSeconds(unit_test.elapsed_time()).c_str());
+  if (GTEST_FLAG(shuffle)) {
+    fprintf(out, "random_seed=\"%d\" ", unit_test.random_seed());
+  }
+  fprintf(out, "name=\"AllTests\">\n");
+  for (int i = 0; i < unit_test.total_test_case_count(); ++i)
+    PrintXmlTestCase(out, *unit_test.GetTestCase(i));
+  fprintf(out, "</testsuites>\n");
+}
+
+// Produces a string representing the test properties in a result as space
+// delimited XML attributes based on the property key="value" pairs.
+String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
+    const TestResult& result) {
+  Message attributes;
+  for (int i = 0; i < result.test_property_count(); ++i) {
+    const TestProperty& property = result.GetTestProperty(i);
+    attributes << " " << property.key() << "="
+        << "\"" << EscapeXmlAttribute(property.value()) << "\"";
+  }
+  return attributes.GetString();
+}
+
+// End XmlUnitTestResultPrinter
+
+#if GTEST_CAN_STREAM_RESULTS_
+
+// Streams test results to the given port on the given host machine.
+class StreamingListener : public EmptyTestEventListener {
+ public:
+  // Escapes '=', '&', '%', and '\n' characters in str as "%xx".
+  static string UrlEncode(const char* str);
+
+  StreamingListener(const string& host, const string& port)
+      : sockfd_(-1), host_name_(host), port_num_(port) {
+    MakeConnection();
+    Send("gtest_streaming_protocol_version=1.0\n");
+  }
+
+  virtual ~StreamingListener() {
+    if (sockfd_ != -1)
+      CloseConnection();
+  }
+
+  void OnTestProgramStart(const UnitTest& /* unit_test */) {
+    Send("event=TestProgramStart\n");
+  }
+
+  void OnTestProgramEnd(const UnitTest& unit_test) {
+    // Note that Google Test current only report elapsed time for each
+    // test iteration, not for the entire test program.
+    Send(String::Format("event=TestProgramEnd&passed=%d\n",
+                        unit_test.Passed()));
+
+    // Notify the streaming server to stop.
+    CloseConnection();
+  }
+
+  void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) {
+    Send(String::Format("event=TestIterationStart&iteration=%d\n",
+                        iteration));
+  }
+
+  void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) {
+    Send(String::Format("event=TestIterationEnd&passed=%d&elapsed_time=%sms\n",
+                        unit_test.Passed(),
+                        StreamableToString(unit_test.elapsed_time()).c_str()));
+  }
+
+  void OnTestCaseStart(const TestCase& test_case) {
+    Send(String::Format("event=TestCaseStart&name=%s\n", test_case.name()));
+  }
+
+  void OnTestCaseEnd(const TestCase& test_case) {
+    Send(String::Format("event=TestCaseEnd&passed=%d&elapsed_time=%sms\n",
+                        test_case.Passed(),
+                        StreamableToString(test_case.elapsed_time()).c_str()));
+  }
+
+  void OnTestStart(const TestInfo& test_info) {
+    Send(String::Format("event=TestStart&name=%s\n", test_info.name()));
+  }
+
+  void OnTestEnd(const TestInfo& test_info) {
+    Send(String::Format(
+        "event=TestEnd&passed=%d&elapsed_time=%sms\n",
+        (test_info.result())->Passed(),
+        StreamableToString((test_info.result())->elapsed_time()).c_str()));
+  }
+
+  void OnTestPartResult(const TestPartResult& test_part_result) {
+    const char* file_name = test_part_result.file_name();
+    if (file_name == NULL)
+      file_name = "";
+    Send(String::Format("event=TestPartResult&file=%s&line=%d&message=",
+                        UrlEncode(file_name).c_str(),
+                        test_part_result.line_number()));
+    Send(UrlEncode(test_part_result.message()) + "\n");
+  }
+
+ private:
+  // Creates a client socket and connects to the server.
+  void MakeConnection();
+
+  // Closes the socket.
+  void CloseConnection() {
+    GTEST_CHECK_(sockfd_ != -1)
+        << "CloseConnection() can be called only when there is a connection.";
+
+    close(sockfd_);
+    sockfd_ = -1;
+  }
+
+  // Sends a string to the socket.
+  void Send(const string& message) {
+    GTEST_CHECK_(sockfd_ != -1)
+        << "Send() can be called only when there is a connection.";
+
+    const int len = static_cast<int>(message.length());
+    if (write(sockfd_, message.c_str(), len) != len) {
+      GTEST_LOG_(WARNING)
+          << "stream_result_to: failed to stream to "
+          << host_name_ << ":" << port_num_;
+    }
+  }
+
+  int sockfd_;   // socket file descriptor
+  const string host_name_;
+  const string port_num_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener);
+};  // class StreamingListener
+
+// Checks if str contains '=', '&', '%' or '\n' characters. If yes,
+// replaces them by "%xx" where xx is their hexadecimal value. For
+// example, replaces "=" with "%3D".  This algorithm is O(strlen(str))
+// in both time and space -- important as the input str may contain an
+// arbitrarily long test failure message and stack trace.
+string StreamingListener::UrlEncode(const char* str) {
+  string result;
+  result.reserve(strlen(str) + 1);
+  for (char ch = *str; ch != '\0'; ch = *++str) {
+    switch (ch) {
+      case '%':
+      case '=':
+      case '&':
+      case '\n':
+        result.append(String::Format("%%%02x", static_cast<unsigned char>(ch)));
+        break;
+      default:
+        result.push_back(ch);
+        break;
+    }
+  }
+  return result;
+}
+
+void StreamingListener::MakeConnection() {
+  GTEST_CHECK_(sockfd_ == -1)
+      << "MakeConnection() can't be called when there is already a connection.";
+
+  addrinfo hints;
+  memset(&hints, 0, sizeof(hints));
+  hints.ai_family = AF_UNSPEC;    // To allow both IPv4 and IPv6 addresses.
+  hints.ai_socktype = SOCK_STREAM;
+  addrinfo* servinfo = NULL;
+
+  // Use the getaddrinfo() to get a linked list of IP addresses for
+  // the given host name.
+  const int error_num = getaddrinfo(
+      host_name_.c_str(), port_num_.c_str(), &hints, &servinfo);
+  if (error_num != 0) {
+    GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: "
+                        << gai_strerror(error_num);
+  }
+
+  // Loop through all the results and connect to the first we can.
+  for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != NULL;
+       cur_addr = cur_addr->ai_next) {
+    sockfd_ = socket(
+        cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol);
+    if (sockfd_ != -1) {
+      // Connect the client socket to the server socket.
+      if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) {
+        close(sockfd_);
+        sockfd_ = -1;
+      }
+    }
+  }
+
+  freeaddrinfo(servinfo);  // all done with this structure
+
+  if (sockfd_ == -1) {
+    GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to "
+                        << host_name_ << ":" << port_num_;
+  }
+}
+
+// End of class Streaming Listener
+#endif  // GTEST_CAN_STREAM_RESULTS__
+
+// Class ScopedTrace
+
+// Pushes the given source file location and message onto a per-thread
+// trace stack maintained by Google Test.
+// L < UnitTest::mutex_
+ScopedTrace::ScopedTrace(const char* file, int line, const Message& message) {
+  TraceInfo trace;
+  trace.file = file;
+  trace.line = line;
+  trace.message = message.GetString();
+
+  UnitTest::GetInstance()->PushGTestTrace(trace);
+}
+
+// Pops the info pushed by the c'tor.
+// L < UnitTest::mutex_
+ScopedTrace::~ScopedTrace() {
+  UnitTest::GetInstance()->PopGTestTrace();
+}
+
+
+// class OsStackTraceGetter
+
+// Returns the current OS stack trace as a String.  Parameters:
+//
+//   max_depth  - the maximum number of stack frames to be included
+//                in the trace.
+//   skip_count - the number of top frames to be skipped; doesn't count
+//                against max_depth.
+//
+// L < mutex_
+// We use "L < mutex_" to denote that the function may acquire mutex_.
+String OsStackTraceGetter::CurrentStackTrace(int, int) {
+  return String("");
+}
+
+// L < mutex_
+void OsStackTraceGetter::UponLeavingGTest() {
+}
+
+const char* const
+OsStackTraceGetter::kElidedFramesMarker =
+    "... " GTEST_NAME_ " internal frames ...";
+
+}  // namespace internal
+
+// class TestEventListeners
+
+TestEventListeners::TestEventListeners()
+    : repeater_(new internal::TestEventRepeater()),
+      default_result_printer_(NULL),
+      default_xml_generator_(NULL) {
+}
+
+TestEventListeners::~TestEventListeners() { delete repeater_; }
+
+// Returns the standard listener responsible for the default console
+// output.  Can be removed from the listeners list to shut down default
+// console output.  Note that removing this object from the listener list
+// with Release transfers its ownership to the user.
+void TestEventListeners::Append(TestEventListener* listener) {
+  repeater_->Append(listener);
+}
+
+// Removes the given event listener from the list and returns it.  It then
+// becomes the caller's responsibility to delete the listener. Returns
+// NULL if the listener is not found in the list.
+TestEventListener* TestEventListeners::Release(TestEventListener* listener) {
+  if (listener == default_result_printer_)
+    default_result_printer_ = NULL;
+  else if (listener == default_xml_generator_)
+    default_xml_generator_ = NULL;
+  return repeater_->Release(listener);
+}
+
+// Returns repeater that broadcasts the TestEventListener events to all
+// subscribers.
+TestEventListener* TestEventListeners::repeater() { return repeater_; }
+
+// Sets the default_result_printer attribute to the provided listener.
+// The listener is also added to the listener list and previous
+// default_result_printer is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) {
+  if (default_result_printer_ != listener) {
+    // It is an error to pass this method a listener that is already in the
+    // list.
+    delete Release(default_result_printer_);
+    default_result_printer_ = listener;
+    if (listener != NULL)
+      Append(listener);
+  }
+}
+
+// Sets the default_xml_generator attribute to the provided listener.  The
+// listener is also added to the listener list and previous
+// default_xml_generator is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) {
+  if (default_xml_generator_ != listener) {
+    // It is an error to pass this method a listener that is already in the
+    // list.
+    delete Release(default_xml_generator_);
+    default_xml_generator_ = listener;
+    if (listener != NULL)
+      Append(listener);
+  }
+}
+
+// Controls whether events will be forwarded by the repeater to the
+// listeners in the list.
+bool TestEventListeners::EventForwardingEnabled() const {
+  return repeater_->forwarding_enabled();
+}
+
+void TestEventListeners::SuppressEventForwarding() {
+  repeater_->set_forwarding_enabled(false);
+}
+
+// class UnitTest
+
+// Gets the singleton UnitTest object.  The first time this method is
+// called, a UnitTest object is constructed and returned.  Consecutive
+// calls will return the same object.
+//
+// We don't protect this under mutex_ as a user is not supposed to
+// call this before main() starts, from which point on the return
+// value will never change.
+UnitTest * UnitTest::GetInstance() {
+  // When compiled with MSVC 7.1 in optimized mode, destroying the
+  // UnitTest object upon exiting the program messes up the exit code,
+  // causing successful tests to appear failed.  We have to use a
+  // different implementation in this case to bypass the compiler bug.
+  // This implementation makes the compiler happy, at the cost of
+  // leaking the UnitTest object.
+
+  // CodeGear C++Builder insists on a public destructor for the
+  // default implementation.  Use this implementation to keep good OO
+  // design with private destructor.
+
+#if (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__)
+  static UnitTest* const instance = new UnitTest;
+  return instance;
+#else
+  static UnitTest instance;
+  return &instance;
+#endif  // (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__)
+}
+
+// Gets the number of successful test cases.
+int UnitTest::successful_test_case_count() const {
+  return impl()->successful_test_case_count();
+}
+
+// Gets the number of failed test cases.
+int UnitTest::failed_test_case_count() const {
+  return impl()->failed_test_case_count();
+}
+
+// Gets the number of all test cases.
+int UnitTest::total_test_case_count() const {
+  return impl()->total_test_case_count();
+}
+
+// Gets the number of all test cases that contain at least one test
+// that should run.
+int UnitTest::test_case_to_run_count() const {
+  return impl()->test_case_to_run_count();
+}
+
+// Gets the number of successful tests.
+int UnitTest::successful_test_count() const {
+  return impl()->successful_test_count();
+}
+
+// Gets the number of failed tests.
+int UnitTest::failed_test_count() const { return impl()->failed_test_count(); }
+
+// Gets the number of disabled tests.
+int UnitTest::disabled_test_count() const {
+  return impl()->disabled_test_count();
+}
+
+// Gets the number of all tests.
+int UnitTest::total_test_count() const { return impl()->total_test_count(); }
+
+// Gets the number of tests that should run.
+int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); }
+
+// Gets the elapsed time, in milliseconds.
+internal::TimeInMillis UnitTest::elapsed_time() const {
+  return impl()->elapsed_time();
+}
+
+// Returns true iff the unit test passed (i.e. all test cases passed).
+bool UnitTest::Passed() const { return impl()->Passed(); }
+
+// Returns true iff the unit test failed (i.e. some test case failed
+// or something outside of all tests failed).
+bool UnitTest::Failed() const { return impl()->Failed(); }
+
+// Gets the i-th test case among all the test cases. i can range from 0 to
+// total_test_case_count() - 1. If i is not in that range, returns NULL.
+const TestCase* UnitTest::GetTestCase(int i) const {
+  return impl()->GetTestCase(i);
+}
+
+// Gets the i-th test case among all the test cases. i can range from 0 to
+// total_test_case_count() - 1. If i is not in that range, returns NULL.
+TestCase* UnitTest::GetMutableTestCase(int i) {
+  return impl()->GetMutableTestCase(i);
+}
+
+// Returns the list of event listeners that can be used to track events
+// inside Google Test.
+TestEventListeners& UnitTest::listeners() {
+  return *impl()->listeners();
+}
+
+// Registers and returns a global test environment.  When a test
+// program is run, all global test environments will be set-up in the
+// order they were registered.  After all tests in the program have
+// finished, all global test environments will be torn-down in the
+// *reverse* order they were registered.
+//
+// The UnitTest object takes ownership of the given environment.
+//
+// We don't protect this under mutex_, as we only support calling it
+// from the main thread.
+Environment* UnitTest::AddEnvironment(Environment* env) {
+  if (env == NULL) {
+    return NULL;
+  }
+
+  impl_->environments().push_back(env);
+  return env;
+}
+
+// Adds a TestPartResult to the current TestResult object.  All Google Test
+// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call
+// this to report their results.  The user code should use the
+// assertion macros instead of calling this directly.
+// L < mutex_
+void UnitTest::AddTestPartResult(TestPartResult::Type result_type,
+                                 const char* file_name,
+                                 int line_number,
+                                 const internal::String& message,
+                                 const internal::String& os_stack_trace) {
+  Message msg;
+  msg << message;
+
+  internal::MutexLock lock(&mutex_);
+  if (impl_->gtest_trace_stack().size() > 0) {
+    msg << "\n" << GTEST_NAME_ << " trace:";
+
+    for (int i = static_cast<int>(impl_->gtest_trace_stack().size());
+         i > 0; --i) {
+      const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1];
+      msg << "\n" << internal::FormatFileLocation(trace.file, trace.line)
+          << " " << trace.message;
+    }
+  }
+
+  if (os_stack_trace.c_str() != NULL && !os_stack_trace.empty()) {
+    msg << internal::kStackTraceMarker << os_stack_trace;
+  }
+
+  const TestPartResult result =
+    TestPartResult(result_type, file_name, line_number,
+                   msg.GetString().c_str());
+  impl_->GetTestPartResultReporterForCurrentThread()->
+      ReportTestPartResult(result);
+
+  if (result_type != TestPartResult::kSuccess) {
+    // gtest_break_on_failure takes precedence over
+    // gtest_throw_on_failure.  This allows a user to set the latter
+    // in the code (perhaps in order to use Google Test assertions
+    // with another testing framework) and specify the former on the
+    // command line for debugging.
+    if (GTEST_FLAG(break_on_failure)) {
+#if GTEST_OS_WINDOWS
+      // Using DebugBreak on Windows allows gtest to still break into a debugger
+      // when a failure happens and both the --gtest_break_on_failure and
+      // the --gtest_catch_exceptions flags are specified.
+      DebugBreak();
+#else
+      // Dereference NULL through a volatile pointer to prevent the compiler
+      // from removing. We use this rather than abort() or __builtin_trap() for
+      // portability: Symbian doesn't implement abort() well, and some debuggers
+      // don't correctly trap abort().
+      *static_cast<volatile int*>(NULL) = 1;
+#endif  // GTEST_OS_WINDOWS
+    } else if (GTEST_FLAG(throw_on_failure)) {
+#if GTEST_HAS_EXCEPTIONS
+      throw GoogleTestFailureException(result);
+#else
+      // We cannot call abort() as it generates a pop-up in debug mode
+      // that cannot be suppressed in VC 7.1 or below.
+      exit(1);
+#endif
+    }
+  }
+}
+
+// Creates and adds a property to the current TestResult. If a property matching
+// the supplied value already exists, updates its value instead.
+void UnitTest::RecordPropertyForCurrentTest(const char* key,
+                                            const char* value) {
+  const TestProperty test_property(key, value);
+  impl_->current_test_result()->RecordProperty(test_property);
+}
+
+// Runs all tests in this UnitTest object and prints the result.
+// Returns 0 if successful, or 1 otherwise.
+//
+// We don't protect this under mutex_, as we only support calling it
+// from the main thread.
+int UnitTest::Run() {
+  // Captures the value of GTEST_FLAG(catch_exceptions).  This value will be
+  // used for the duration of the program.
+  impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions));
+
+#if GTEST_HAS_SEH
+  const bool in_death_test_child_process =
+      internal::GTEST_FLAG(internal_run_death_test).length() > 0;
+
+  // Either the user wants Google Test to catch exceptions thrown by the
+  // tests or this is executing in the context of death test child
+  // process. In either case the user does not want to see pop-up dialogs
+  // about crashes - they are expected.
+  if (impl()->catch_exceptions() || in_death_test_child_process) {
+
+# if !GTEST_OS_WINDOWS_MOBILE
+    // SetErrorMode doesn't exist on CE.
+    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
+                 SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
+# endif  // !GTEST_OS_WINDOWS_MOBILE
+
+# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE
+    // Death test children can be terminated with _abort().  On Windows,
+    // _abort() can show a dialog with a warning message.  This forces the
+    // abort message to go to stderr instead.
+    _set_error_mode(_OUT_TO_STDERR);
+# endif
+
+# if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE
+    // In the debug version, Visual Studio pops up a separate dialog
+    // offering a choice to debug the aborted program. We need to suppress
+    // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement
+    // executed. Google Test will notify the user of any unexpected
+    // failure via stderr.
+    //
+    // VC++ doesn't define _set_abort_behavior() prior to the version 8.0.
+    // Users of prior VC versions shall suffer the agony and pain of
+    // clicking through the countless debug dialogs.
+    // TODO(vladl@google.com): find a way to suppress the abort dialog() in the
+    // debug mode when compiled with VC 7.1 or lower.
+    if (!GTEST_FLAG(break_on_failure))
+      _set_abort_behavior(
+          0x0,                                    // Clear the following flags:
+          _WRITE_ABORT_MSG | _CALL_REPORTFAULT);  // pop-up window, core dump.
+# endif
+
+  }
+#endif  // GTEST_HAS_SEH
+
+  return internal::HandleExceptionsInMethodIfSupported(
+      impl(),
+      &internal::UnitTestImpl::RunAllTests,
+      "auxiliary test code (environments or event listeners)") ? 0 : 1;
+}
+
+// Returns the working directory when the first TEST() or TEST_F() was
+// executed.
+const char* UnitTest::original_working_dir() const {
+  return impl_->original_working_dir_.c_str();
+}
+
+// Returns the TestCase object for the test that's currently running,
+// or NULL if no test is running.
+// L < mutex_
+const TestCase* UnitTest::current_test_case() const {
+  internal::MutexLock lock(&mutex_);
+  return impl_->current_test_case();
+}
+
+// Returns the TestInfo object for the test that's currently running,
+// or NULL if no test is running.
+// L < mutex_
+const TestInfo* UnitTest::current_test_info() const {
+  internal::MutexLock lock(&mutex_);
+  return impl_->current_test_info();
+}
+
+// Returns the random seed used at the start of the current test run.
+int UnitTest::random_seed() const { return impl_->random_seed(); }
+
+#if GTEST_HAS_PARAM_TEST
+// Returns ParameterizedTestCaseRegistry object used to keep track of
+// value-parameterized tests and instantiate and register them.
+// L < mutex_
+internal::ParameterizedTestCaseRegistry&
+    UnitTest::parameterized_test_registry() {
+  return impl_->parameterized_test_registry();
+}
+#endif  // GTEST_HAS_PARAM_TEST
+
+// Creates an empty UnitTest.
+UnitTest::UnitTest() {
+  impl_ = new internal::UnitTestImpl(this);
+}
+
+// Destructor of UnitTest.
+UnitTest::~UnitTest() {
+  delete impl_;
+}
+
+// Pushes a trace defined by SCOPED_TRACE() on to the per-thread
+// Google Test trace stack.
+// L < mutex_
+void UnitTest::PushGTestTrace(const internal::TraceInfo& trace) {
+  internal::MutexLock lock(&mutex_);
+  impl_->gtest_trace_stack().push_back(trace);
+}
+
+// Pops a trace from the per-thread Google Test trace stack.
+// L < mutex_
+void UnitTest::PopGTestTrace() {
+  internal::MutexLock lock(&mutex_);
+  impl_->gtest_trace_stack().pop_back();
+}
+
+namespace internal {
+
+UnitTestImpl::UnitTestImpl(UnitTest* parent)
+    : parent_(parent),
+#ifdef _MSC_VER
+# pragma warning(push)                    // Saves the current warning state.
+# pragma warning(disable:4355)            // Temporarily disables warning 4355
+                                         // (using this in initializer).
+      default_global_test_part_result_reporter_(this),
+      default_per_thread_test_part_result_reporter_(this),
+# pragma warning(pop)                     // Restores the warning state again.
+#else
+      default_global_test_part_result_reporter_(this),
+      default_per_thread_test_part_result_reporter_(this),
+#endif  // _MSC_VER
+      global_test_part_result_repoter_(
+          &default_global_test_part_result_reporter_),
+      per_thread_test_part_result_reporter_(
+          &default_per_thread_test_part_result_reporter_),
+#if GTEST_HAS_PARAM_TEST
+      parameterized_test_registry_(),
+      parameterized_tests_registered_(false),
+#endif  // GTEST_HAS_PARAM_TEST
+      last_death_test_case_(-1),
+      current_test_case_(NULL),
+      current_test_info_(NULL),
+      ad_hoc_test_result_(),
+      os_stack_trace_getter_(NULL),
+      post_flag_parse_init_performed_(false),
+      random_seed_(0),  // Will be overridden by the flag before first use.
+      random_(0),  // Will be reseeded before first use.
+      elapsed_time_(0),
+#if GTEST_HAS_DEATH_TEST
+      internal_run_death_test_flag_(NULL),
+      death_test_factory_(new DefaultDeathTestFactory),
+#endif
+      // Will be overridden by the flag before first use.
+      catch_exceptions_(false) {
+  listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter);
+}
+
+UnitTestImpl::~UnitTestImpl() {
+  // Deletes every TestCase.
+  ForEach(test_cases_, internal::Delete<TestCase>);
+
+  // Deletes every Environment.
+  ForEach(environments_, internal::Delete<Environment>);
+
+  delete os_stack_trace_getter_;
+}
+
+#if GTEST_HAS_DEATH_TEST
+// Disables event forwarding if the control is currently in a death test
+// subprocess. Must not be called before InitGoogleTest.
+void UnitTestImpl::SuppressTestEventsIfInSubprocess() {
+  if (internal_run_death_test_flag_.get() != NULL)
+    listeners()->SuppressEventForwarding();
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Initializes event listeners performing XML output as specified by
+// UnitTestOptions. Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureXmlOutput() {
+  const String& output_format = UnitTestOptions::GetOutputFormat();
+  if (output_format == "xml") {
+    listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter(
+        UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
+  } else if (output_format != "") {
+    printf("WARNING: unrecognized output format \"%s\" ignored.\n",
+           output_format.c_str());
+    fflush(stdout);
+  }
+}
+
+#if GTEST_CAN_STREAM_RESULTS_
+// Initializes event listeners for streaming test results in String form.
+// Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureStreamingOutput() {
+  const string& target = GTEST_FLAG(stream_result_to);
+  if (!target.empty()) {
+    const size_t pos = target.find(':');
+    if (pos != string::npos) {
+      listeners()->Append(new StreamingListener(target.substr(0, pos),
+                                                target.substr(pos+1)));
+    } else {
+      printf("WARNING: unrecognized streaming target \"%s\" ignored.\n",
+             target.c_str());
+      fflush(stdout);
+    }
+  }
+}
+#endif  // GTEST_CAN_STREAM_RESULTS_
+
+// Performs initialization dependent upon flag values obtained in
+// ParseGoogleTestFlagsOnly.  Is called from InitGoogleTest after the call to
+// ParseGoogleTestFlagsOnly.  In case a user neglects to call InitGoogleTest
+// this function is also called from RunAllTests.  Since this function can be
+// called more than once, it has to be idempotent.
+void UnitTestImpl::PostFlagParsingInit() {
+  // Ensures that this function does not execute more than once.
+  if (!post_flag_parse_init_performed_) {
+    post_flag_parse_init_performed_ = true;
+
+#if GTEST_HAS_DEATH_TEST
+    InitDeathTestSubprocessControlInfo();
+    SuppressTestEventsIfInSubprocess();
+#endif  // GTEST_HAS_DEATH_TEST
+
+    // Registers parameterized tests. This makes parameterized tests
+    // available to the UnitTest reflection API without running
+    // RUN_ALL_TESTS.
+    RegisterParameterizedTests();
+
+    // Configures listeners for XML output. This makes it possible for users
+    // to shut down the default XML output before invoking RUN_ALL_TESTS.
+    ConfigureXmlOutput();
+
+#if GTEST_CAN_STREAM_RESULTS_
+    // Configures listeners for streaming test results to the specified server.
+    ConfigureStreamingOutput();
+#endif  // GTEST_CAN_STREAM_RESULTS_
+  }
+}
+
+// A predicate that checks the name of a TestCase against a known
+// value.
+//
+// This is used for implementation of the UnitTest class only.  We put
+// it in the anonymous namespace to prevent polluting the outer
+// namespace.
+//
+// TestCaseNameIs is copyable.
+class TestCaseNameIs {
+ public:
+  // Constructor.
+  explicit TestCaseNameIs(const String& name)
+      : name_(name) {}
+
+  // Returns true iff the name of test_case matches name_.
+  bool operator()(const TestCase* test_case) const {
+    return test_case != NULL && strcmp(test_case->name(), name_.c_str()) == 0;
+  }
+
+ private:
+  String name_;
+};
+
+// Finds and returns a TestCase with the given name.  If one doesn't
+// exist, creates one and returns it.  It's the CALLER'S
+// RESPONSIBILITY to ensure that this function is only called WHEN THE
+// TESTS ARE NOT SHUFFLED.
+//
+// Arguments:
+//
+//   test_case_name: name of the test case
+//   type_param:     the name of the test case's type parameter, or NULL if
+//                   this is not a typed or a type-parameterized test case.
+//   set_up_tc:      pointer to the function that sets up the test case
+//   tear_down_tc:   pointer to the function that tears down the test case
+TestCase* UnitTestImpl::GetTestCase(const char* test_case_name,
+                                    const char* type_param,
+                                    Test::SetUpTestCaseFunc set_up_tc,
+                                    Test::TearDownTestCaseFunc tear_down_tc) {
+  // Can we find a TestCase with the given name?
+  const std::vector<TestCase*>::const_iterator test_case =
+      std::find_if(test_cases_.begin(), test_cases_.end(),
+                   TestCaseNameIs(test_case_name));
+
+  if (test_case != test_cases_.end())
+    return *test_case;
+
+  // No.  Let's create one.
+  TestCase* const new_test_case =
+      new TestCase(test_case_name, type_param, set_up_tc, tear_down_tc);
+
+  // Is this a death test case?
+  if (internal::UnitTestOptions::MatchesFilter(String(test_case_name),
+                                               kDeathTestCaseFilter)) {
+    // Yes.  Inserts the test case after the last death test case
+    // defined so far.  This only works when the test cases haven't
+    // been shuffled.  Otherwise we may end up running a death test
+    // after a non-death test.
+    ++last_death_test_case_;
+    test_cases_.insert(test_cases_.begin() + last_death_test_case_,
+                       new_test_case);
+  } else {
+    // No.  Appends to the end of the list.
+    test_cases_.push_back(new_test_case);
+  }
+
+  test_case_indices_.push_back(static_cast<int>(test_case_indices_.size()));
+  return new_test_case;
+}
+
+// Helpers for setting up / tearing down the given environment.  They
+// are for use in the ForEach() function.
+static void SetUpEnvironment(Environment* env) { env->SetUp(); }
+static void TearDownEnvironment(Environment* env) { env->TearDown(); }
+
+// Runs all tests in this UnitTest object, prints the result, and
+// returns true if all tests are successful.  If any exception is
+// thrown during a test, the test is considered to be failed, but the
+// rest of the tests will still be run.
+//
+// When parameterized tests are enabled, it expands and registers
+// parameterized tests first in RegisterParameterizedTests().
+// All other functions called from RunAllTests() may safely assume that
+// parameterized tests are ready to be counted and run.
+bool UnitTestImpl::RunAllTests() {
+  // Makes sure InitGoogleTest() was called.
+  if (!GTestIsInitialized()) {
+    printf("%s",
+           "\nThis test program did NOT call ::testing::InitGoogleTest "
+           "before calling RUN_ALL_TESTS().  Please fix it.\n");
+    return false;
+  }
+
+  // Do not run any test if the --help flag was specified.
+  if (g_help_flag)
+    return true;
+
+  // Repeats the call to the post-flag parsing initialization in case the
+  // user didn't call InitGoogleTest.
+  PostFlagParsingInit();
+
+  // Even if sharding is not on, test runners may want to use the
+  // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding
+  // protocol.
+  internal::WriteToShardStatusFileIfNeeded();
+
+  // True iff we are in a subprocess for running a thread-safe-style
+  // death test.
+  bool in_subprocess_for_death_test = false;
+
+#if GTEST_HAS_DEATH_TEST
+  in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL);
+#endif  // GTEST_HAS_DEATH_TEST
+
+  const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex,
+                                        in_subprocess_for_death_test);
+
+  // Compares the full test names with the filter to decide which
+  // tests to run.
+  const bool has_tests_to_run = FilterTests(should_shard
+                                              ? HONOR_SHARDING_PROTOCOL
+                                              : IGNORE_SHARDING_PROTOCOL) > 0;
+
+  // Lists the tests and exits if the --gtest_list_tests flag was specified.
+  if (GTEST_FLAG(list_tests)) {
+    // This must be called *after* FilterTests() has been called.
+    ListTestsMatchingFilter();
+    return true;
+  }
+
+  random_seed_ = GTEST_FLAG(shuffle) ?
+      GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0;
+
+  // True iff at least one test has failed.
+  bool failed = false;
+
+  TestEventListener* repeater = listeners()->repeater();
+
+  repeater->OnTestProgramStart(*parent_);
+
+  // How many times to repeat the tests?  We don't want to repeat them
+  // when we are inside the subprocess of a death test.
+  const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat);
+  // Repeats forever if the repeat count is negative.
+  const bool forever = repeat < 0;
+  for (int i = 0; forever || i != repeat; i++) {
+    // We want to preserve failures generated by ad-hoc test
+    // assertions executed before RUN_ALL_TESTS().
+    ClearNonAdHocTestResult();
+
+    const TimeInMillis start = GetTimeInMillis();
+
+    // Shuffles test cases and tests if requested.
+    if (has_tests_to_run && GTEST_FLAG(shuffle)) {
+      random()->Reseed(random_seed_);
+      // This should be done before calling OnTestIterationStart(),
+      // such that a test event listener can see the actual test order
+      // in the event.
+      ShuffleTests();
+    }
+
+    // Tells the unit test event listeners that the tests are about to start.
+    repeater->OnTestIterationStart(*parent_, i);
+
+    // Runs each test case if there is at least one test to run.
+    if (has_tests_to_run) {
+      // Sets up all environments beforehand.
+      repeater->OnEnvironmentsSetUpStart(*parent_);
+      ForEach(environments_, SetUpEnvironment);
+      repeater->OnEnvironmentsSetUpEnd(*parent_);
+
+      // Runs the tests only if there was no fatal failure during global
+      // set-up.
+      if (!Test::HasFatalFailure()) {
+        for (int test_index = 0; test_index < total_test_case_count();
+             test_index++) {
+          GetMutableTestCase(test_index)->Run();
+        }
+      }
+
+      // Tears down all environments in reverse order afterwards.
+      repeater->OnEnvironmentsTearDownStart(*parent_);
+      std::for_each(environments_.rbegin(), environments_.rend(),
+                    TearDownEnvironment);
+      repeater->OnEnvironmentsTearDownEnd(*parent_);
+    }
+
+    elapsed_time_ = GetTimeInMillis() - start;
+
+    // Tells the unit test event listener that the tests have just finished.
+    repeater->OnTestIterationEnd(*parent_, i);
+
+    // Gets the result and clears it.
+    if (!Passed()) {
+      failed = true;
+    }
+
+    // Restores the original test order after the iteration.  This
+    // allows the user to quickly repro a failure that happens in the
+    // N-th iteration without repeating the first (N - 1) iterations.
+    // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in
+    // case the user somehow changes the value of the flag somewhere
+    // (it's always safe to unshuffle the tests).
+    UnshuffleTests();
+
+    if (GTEST_FLAG(shuffle)) {
+      // Picks a new random seed for each iteration.
+      random_seed_ = GetNextRandomSeed(random_seed_);
+    }
+  }
+
+  repeater->OnTestProgramEnd(*parent_);
+
+  return !failed;
+}
+
+// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
+// if the variable is present. If a file already exists at this location, this
+// function will write over it. If the variable is present, but the file cannot
+// be created, prints an error and exits.
+void WriteToShardStatusFileIfNeeded() {
+  const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile);
+  if (test_shard_file != NULL) {
+    FILE* const file = posix::FOpen(test_shard_file, "w");
+    if (file == NULL) {
+      ColoredPrintf(COLOR_RED,
+                    "Could not write to the test shard status file \"%s\" "
+                    "specified by the %s environment variable.\n",
+                    test_shard_file, kTestShardStatusFile);
+      fflush(stdout);
+      exit(EXIT_FAILURE);
+    }
+    fclose(file);
+  }
+}
+
+// Checks whether sharding is enabled by examining the relevant
+// environment variable values. If the variables are present,
+// but inconsistent (i.e., shard_index >= total_shards), prints
+// an error and exits. If in_subprocess_for_death_test, sharding is
+// disabled because it must only be applied to the original test
+// process. Otherwise, we could filter out death tests we intended to execute.
+bool ShouldShard(const char* total_shards_env,
+                 const char* shard_index_env,
+                 bool in_subprocess_for_death_test) {
+  if (in_subprocess_for_death_test) {
+    return false;
+  }
+
+  const Int32 total_shards = Int32FromEnvOrDie(total_shards_env, -1);
+  const Int32 shard_index = Int32FromEnvOrDie(shard_index_env, -1);
+
+  if (total_shards == -1 && shard_index == -1) {
+    return false;
+  } else if (total_shards == -1 && shard_index != -1) {
+    const Message msg = Message()
+      << "Invalid environment variables: you have "
+      << kTestShardIndex << " = " << shard_index
+      << ", but have left " << kTestTotalShards << " unset.\n";
+    ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  } else if (total_shards != -1 && shard_index == -1) {
+    const Message msg = Message()
+      << "Invalid environment variables: you have "
+      << kTestTotalShards << " = " << total_shards
+      << ", but have left " << kTestShardIndex << " unset.\n";
+    ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  } else if (shard_index < 0 || shard_index >= total_shards) {
+    const Message msg = Message()
+      << "Invalid environment variables: we require 0 <= "
+      << kTestShardIndex << " < " << kTestTotalShards
+      << ", but you have " << kTestShardIndex << "=" << shard_index
+      << ", " << kTestTotalShards << "=" << total_shards << ".\n";
+    ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  }
+
+  return total_shards > 1;
+}
+
+// Parses the environment variable var as an Int32. If it is unset,
+// returns default_val. If it is not an Int32, prints an error
+// and aborts.
+Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) {
+  const char* str_val = posix::GetEnv(var);
+  if (str_val == NULL) {
+    return default_val;
+  }
+
+  Int32 result;
+  if (!ParseInt32(Message() << "The value of environment variable " << var,
+                  str_val, &result)) {
+    exit(EXIT_FAILURE);
+  }
+  return result;
+}
+
+// Given the total number of shards, the shard index, and the test id,
+// returns true iff the test should be run on this shard. The test id is
+// some arbitrary but unique non-negative integer assigned to each test
+// method. Assumes that 0 <= shard_index < total_shards.
+bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) {
+  return (test_id % total_shards) == shard_index;
+}
+
+// Compares the name of each test with the user-specified filter to
+// decide whether the test should be run, then records the result in
+// each TestCase and TestInfo object.
+// If shard_tests == true, further filters tests based on sharding
+// variables in the environment - see
+// http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide.
+// Returns the number of tests that should run.
+int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
+  const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ?
+      Int32FromEnvOrDie(kTestTotalShards, -1) : -1;
+  const Int32 shard_index = shard_tests == HONOR_SHARDING_PROTOCOL ?
+      Int32FromEnvOrDie(kTestShardIndex, -1) : -1;
+
+  // num_runnable_tests are the number of tests that will
+  // run across all shards (i.e., match filter and are not disabled).
+  // num_selected_tests are the number of tests to be run on
+  // this shard.
+  int num_runnable_tests = 0;
+  int num_selected_tests = 0;
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    TestCase* const test_case = test_cases_[i];
+    const String &test_case_name = test_case->name();
+    test_case->set_should_run(false);
+
+    for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
+      TestInfo* const test_info = test_case->test_info_list()[j];
+      const String test_name(test_info->name());
+      // A test is disabled if test case name or test name matches
+      // kDisableTestFilter.
+      const bool is_disabled =
+          internal::UnitTestOptions::MatchesFilter(test_case_name,
+                                                   kDisableTestFilter) ||
+          internal::UnitTestOptions::MatchesFilter(test_name,
+                                                   kDisableTestFilter);
+      test_info->is_disabled_ = is_disabled;
+
+      const bool matches_filter =
+          internal::UnitTestOptions::FilterMatchesTest(test_case_name,
+                                                       test_name);
+      test_info->matches_filter_ = matches_filter;
+
+      const bool is_runnable =
+          (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) &&
+          matches_filter;
+
+      const bool is_selected = is_runnable &&
+          (shard_tests == IGNORE_SHARDING_PROTOCOL ||
+           ShouldRunTestOnShard(total_shards, shard_index,
+                                num_runnable_tests));
+
+      num_runnable_tests += is_runnable;
+      num_selected_tests += is_selected;
+
+      test_info->should_run_ = is_selected;
+      test_case->set_should_run(test_case->should_run() || is_selected);
+    }
+  }
+  return num_selected_tests;
+}
+
+// Prints the names of the tests matching the user-specified filter flag.
+void UnitTestImpl::ListTestsMatchingFilter() {
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    const TestCase* const test_case = test_cases_[i];
+    bool printed_test_case_name = false;
+
+    for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
+      const TestInfo* const test_info =
+          test_case->test_info_list()[j];
+      if (test_info->matches_filter_) {
+        if (!printed_test_case_name) {
+          printed_test_case_name = true;
+          printf("%s.\n", test_case->name());
+        }
+        printf("  %s\n", test_info->name());
+      }
+    }
+  }
+  fflush(stdout);
+}
+
+// Sets the OS stack trace getter.
+//
+// Does nothing if the input and the current OS stack trace getter are
+// the same; otherwise, deletes the old getter and makes the input the
+// current getter.
+void UnitTestImpl::set_os_stack_trace_getter(
+    OsStackTraceGetterInterface* getter) {
+  if (os_stack_trace_getter_ != getter) {
+    delete os_stack_trace_getter_;
+    os_stack_trace_getter_ = getter;
+  }
+}
+
+// Returns the current OS stack trace getter if it is not NULL;
+// otherwise, creates an OsStackTraceGetter, makes it the current
+// getter, and returns it.
+OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() {
+  if (os_stack_trace_getter_ == NULL) {
+    os_stack_trace_getter_ = new OsStackTraceGetter;
+  }
+
+  return os_stack_trace_getter_;
+}
+
+// Returns the TestResult for the test that's currently running, or
+// the TestResult for the ad hoc test if no test is running.
+TestResult* UnitTestImpl::current_test_result() {
+  return current_test_info_ ?
+      &(current_test_info_->result_) : &ad_hoc_test_result_;
+}
+
+// Shuffles all test cases, and the tests within each test case,
+// making sure that death tests are still run first.
+void UnitTestImpl::ShuffleTests() {
+  // Shuffles the death test cases.
+  ShuffleRange(random(), 0, last_death_test_case_ + 1, &test_case_indices_);
+
+  // Shuffles the non-death test cases.
+  ShuffleRange(random(), last_death_test_case_ + 1,
+               static_cast<int>(test_cases_.size()), &test_case_indices_);
+
+  // Shuffles the tests inside each test case.
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    test_cases_[i]->ShuffleTests(random());
+  }
+}
+
+// Restores the test cases and tests to their order before the first shuffle.
+void UnitTestImpl::UnshuffleTests() {
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    // Unshuffles the tests in each test case.
+    test_cases_[i]->UnshuffleTests();
+    // Resets the index of each test case.
+    test_case_indices_[i] = static_cast<int>(i);
+  }
+}
+
+// Returns the current OS stack trace as a String.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
+// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
+String GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/,
+                                       int skip_count) {
+  // We pass skip_count + 1 to skip this wrapper function in addition
+  // to what the user really wants to skip.
+  return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1);
+}
+
+// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to
+// suppress unreachable code warnings.
+namespace {
+class ClassUniqueToAlwaysTrue {};
+}
+
+bool IsTrue(bool condition) { return condition; }
+
+bool AlwaysTrue() {
+#if GTEST_HAS_EXCEPTIONS
+  // This condition is always false so AlwaysTrue() never actually throws,
+  // but it makes the compiler think that it may throw.
+  if (IsTrue(false))
+    throw ClassUniqueToAlwaysTrue();
+#endif  // GTEST_HAS_EXCEPTIONS
+  return true;
+}
+
+// If *pstr starts with the given prefix, modifies *pstr to be right
+// past the prefix and returns true; otherwise leaves *pstr unchanged
+// and returns false.  None of pstr, *pstr, and prefix can be NULL.
+bool SkipPrefix(const char* prefix, const char** pstr) {
+  const size_t prefix_len = strlen(prefix);
+  if (strncmp(*pstr, prefix, prefix_len) == 0) {
+    *pstr += prefix_len;
+    return true;
+  }
+  return false;
+}
+
+// Parses a string as a command line flag.  The string should have
+// the format "--flag=value".  When def_optional is true, the "=value"
+// part can be omitted.
+//
+// Returns the value of the flag, or NULL if the parsing failed.
+const char* ParseFlagValue(const char* str,
+                           const char* flag,
+                           bool def_optional) {
+  // str and flag must not be NULL.
+  if (str == NULL || flag == NULL) return NULL;
+
+  // The flag must start with "--" followed by GTEST_FLAG_PREFIX_.
+  const String flag_str = String::Format("--%s%s", GTEST_FLAG_PREFIX_, flag);
+  const size_t flag_len = flag_str.length();
+  if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL;
+
+  // Skips the flag name.
+  const char* flag_end = str + flag_len;
+
+  // When def_optional is true, it's OK to not have a "=value" part.
+  if (def_optional && (flag_end[0] == '\0')) {
+    return flag_end;
+  }
+
+  // If def_optional is true and there are more characters after the
+  // flag name, or if def_optional is false, there must be a '=' after
+  // the flag name.
+  if (flag_end[0] != '=') return NULL;
+
+  // Returns the string after "=".
+  return flag_end + 1;
+}
+
+// Parses a string for a bool flag, in the form of either
+// "--flag=value" or "--flag".
+//
+// In the former case, the value is taken as true as long as it does
+// not start with '0', 'f', or 'F'.
+//
+// In the latter case, the value is taken as true.
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+bool ParseBoolFlag(const char* str, const char* flag, bool* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, true);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Converts the string value to a bool.
+  *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F');
+  return true;
+}
+
+// Parses a string for an Int32 flag, in the form of
+// "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+bool ParseInt32Flag(const char* str, const char* flag, Int32* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, false);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Sets *value to the value of the flag.
+  return ParseInt32(Message() << "The value of flag --" << flag,
+                    value_str, value);
+}
+
+// Parses a string for a string flag, in the form of
+// "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+bool ParseStringFlag(const char* str, const char* flag, String* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, false);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Sets *value to the value of the flag.
+  *value = value_str;
+  return true;
+}
+
+// Determines whether a string has a prefix that Google Test uses for its
+// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_.
+// If Google Test detects that a command line flag has its prefix but is not
+// recognized, it will print its help message. Flags starting with
+// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test
+// internal flags and do not trigger the help message.
+static bool HasGoogleTestFlagPrefix(const char* str) {
+  return (SkipPrefix("--", &str) ||
+          SkipPrefix("-", &str) ||
+          SkipPrefix("/", &str)) &&
+         !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) &&
+         (SkipPrefix(GTEST_FLAG_PREFIX_, &str) ||
+          SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str));
+}
+
+// Prints a string containing code-encoded text.  The following escape
+// sequences can be used in the string to control the text color:
+//
+//   @@    prints a single '@' character.
+//   @R    changes the color to red.
+//   @G    changes the color to green.
+//   @Y    changes the color to yellow.
+//   @D    changes to the default terminal text color.
+//
+// TODO(wan@google.com): Write tests for this once we add stdout
+// capturing to Google Test.
+static void PrintColorEncoded(const char* str) {
+  GTestColor color = COLOR_DEFAULT;  // The current color.
+
+  // Conceptually, we split the string into segments divided by escape
+  // sequences.  Then we print one segment at a time.  At the end of
+  // each iteration, the str pointer advances to the beginning of the
+  // next segment.
+  for (;;) {
+    const char* p = strchr(str, '@');
+    if (p == NULL) {
+      ColoredPrintf(color, "%s", str);
+      return;
+    }
+
+    ColoredPrintf(color, "%s", String(str, p - str).c_str());
+
+    const char ch = p[1];
+    str = p + 2;
+    if (ch == '@') {
+      ColoredPrintf(color, "@");
+    } else if (ch == 'D') {
+      color = COLOR_DEFAULT;
+    } else if (ch == 'R') {
+      color = COLOR_RED;
+    } else if (ch == 'G') {
+      color = COLOR_GREEN;
+    } else if (ch == 'Y') {
+      color = COLOR_YELLOW;
+    } else {
+      --str;
+    }
+  }
+}
+
+static const char kColorEncodedHelpMessage[] =
+"This program contains tests written using " GTEST_NAME_ ". You can use the\n"
+"following command line flags to control its behavior:\n"
+"\n"
+"Test Selection:\n"
+"  @G--" GTEST_FLAG_PREFIX_ "list_tests@D\n"
+"      List the names of all tests instead of running them. The name of\n"
+"      TEST(Foo, Bar) is \"Foo.Bar\".\n"
+"  @G--" GTEST_FLAG_PREFIX_ "filter=@YPOSTIVE_PATTERNS"
+    "[@G-@YNEGATIVE_PATTERNS]@D\n"
+"      Run only the tests whose name matches one of the positive patterns but\n"
+"      none of the negative patterns. '?' matches any single character; '*'\n"
+"      matches any substring; ':' separates two patterns.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "also_run_disabled_tests@D\n"
+"      Run all disabled tests too.\n"
+"\n"
+"Test Execution:\n"
+"  @G--" GTEST_FLAG_PREFIX_ "repeat=@Y[COUNT]@D\n"
+"      Run the tests repeatedly; use a negative count to repeat forever.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "shuffle@D\n"
+"      Randomize tests' orders on every iteration.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "random_seed=@Y[NUMBER]@D\n"
+"      Random number seed to use for shuffling test orders (between 1 and\n"
+"      99999, or 0 to use a seed based on the current time).\n"
+"\n"
+"Test Output:\n"
+"  @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n"
+"      Enable/disable colored output. The default is @Gauto@D.\n"
+"  -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n"
+"      Don't print the elapsed time of each test.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "output=xml@Y[@G:@YDIRECTORY_PATH@G"
+    GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n"
+"      Generate an XML report in the given directory or with the given file\n"
+"      name. @YFILE_PATH@D defaults to @Gtest_details.xml@D.\n"
+#if GTEST_CAN_STREAM_RESULTS_
+"  @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n"
+"      Stream test results to the given server.\n"
+#endif  // GTEST_CAN_STREAM_RESULTS_
+"\n"
+"Assertion Behavior:\n"
+#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
+"  @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n"
+"      Set the default death test style.\n"
+#endif  // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
+"  @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n"
+"      Turn assertion failures into debugger break-points.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n"
+"      Turn assertion failures into C++ exceptions.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n"
+"      Do not report exceptions as test failures. Instead, allow them\n"
+"      to crash the program or throw a pop-up (on Windows).\n"
+"\n"
+"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set "
+    "the corresponding\n"
+"environment variable of a flag (all letters in upper-case). For example, to\n"
+"disable colored text output, you can either specify @G--" GTEST_FLAG_PREFIX_
+    "color=no@D or set\n"
+"the @G" GTEST_FLAG_PREFIX_UPPER_ "COLOR@D environment variable to @Gno@D.\n"
+"\n"
+"For more information, please read the " GTEST_NAME_ " documentation at\n"
+"@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_ "\n"
+"(not one in your own code or tests), please report it to\n"
+"@G<" GTEST_DEV_EMAIL_ ">@D.\n";
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.  The type parameter CharType can be
+// instantiated to either char or wchar_t.
+template <typename CharType>
+void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
+  for (int i = 1; i < *argc; i++) {
+    const String arg_string = StreamableToString(argv[i]);
+    const char* const arg = arg_string.c_str();
+
+    using internal::ParseBoolFlag;
+    using internal::ParseInt32Flag;
+    using internal::ParseStringFlag;
+
+    // Do we see a Google Test flag?
+    if (ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag,
+                      &GTEST_FLAG(also_run_disabled_tests)) ||
+        ParseBoolFlag(arg, kBreakOnFailureFlag,
+                      &GTEST_FLAG(break_on_failure)) ||
+        ParseBoolFlag(arg, kCatchExceptionsFlag,
+                      &GTEST_FLAG(catch_exceptions)) ||
+        ParseStringFlag(arg, kColorFlag, &GTEST_FLAG(color)) ||
+        ParseStringFlag(arg, kDeathTestStyleFlag,
+                        &GTEST_FLAG(death_test_style)) ||
+        ParseBoolFlag(arg, kDeathTestUseFork,
+                      &GTEST_FLAG(death_test_use_fork)) ||
+        ParseStringFlag(arg, kFilterFlag, &GTEST_FLAG(filter)) ||
+        ParseStringFlag(arg, kInternalRunDeathTestFlag,
+                        &GTEST_FLAG(internal_run_death_test)) ||
+        ParseBoolFlag(arg, kListTestsFlag, &GTEST_FLAG(list_tests)) ||
+        ParseStringFlag(arg, kOutputFlag, &GTEST_FLAG(output)) ||
+        ParseBoolFlag(arg, kPrintTimeFlag, &GTEST_FLAG(print_time)) ||
+        ParseInt32Flag(arg, kRandomSeedFlag, &GTEST_FLAG(random_seed)) ||
+        ParseInt32Flag(arg, kRepeatFlag, &GTEST_FLAG(repeat)) ||
+        ParseBoolFlag(arg, kShuffleFlag, &GTEST_FLAG(shuffle)) ||
+        ParseInt32Flag(arg, kStackTraceDepthFlag,
+                       &GTEST_FLAG(stack_trace_depth)) ||
+        ParseStringFlag(arg, kStreamResultToFlag,
+                        &GTEST_FLAG(stream_result_to)) ||
+        ParseBoolFlag(arg, kThrowOnFailureFlag,
+                      &GTEST_FLAG(throw_on_failure))
+        ) {
+      // Yes.  Shift the remainder of the argv list left by one.  Note
+      // that argv has (*argc + 1) elements, the last one always being
+      // NULL.  The following loop moves the trailing NULL element as
+      // well.
+      for (int j = i; j != *argc; j++) {
+        argv[j] = argv[j + 1];
+      }
+
+      // Decrements the argument count.
+      (*argc)--;
+
+      // We also need to decrement the iterator as we just removed
+      // an element.
+      i--;
+    } else if (arg_string == "--help" || arg_string == "-h" ||
+               arg_string == "-?" || arg_string == "/?" ||
+               HasGoogleTestFlagPrefix(arg)) {
+      // Both help flag and unrecognized Google Test flags (excluding
+      // internal ones) trigger help display.
+      g_help_flag = true;
+    }
+  }
+
+  if (g_help_flag) {
+    // We print the help here instead of in RUN_ALL_TESTS(), as the
+    // latter may not be called at all if the user is using Google
+    // Test with another testing framework.
+    PrintColorEncoded(kColorEncodedHelpMessage);
+  }
+}
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.
+void ParseGoogleTestFlagsOnly(int* argc, char** argv) {
+  ParseGoogleTestFlagsOnlyImpl(argc, argv);
+}
+void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) {
+  ParseGoogleTestFlagsOnlyImpl(argc, argv);
+}
+
+// The internal implementation of InitGoogleTest().
+//
+// The type parameter CharType can be instantiated to either char or
+// wchar_t.
+template <typename CharType>
+void InitGoogleTestImpl(int* argc, CharType** argv) {
+  g_init_gtest_count++;
+
+  // We don't want to run the initialization code twice.
+  if (g_init_gtest_count != 1) return;
+
+  if (*argc <= 0) return;
+
+  internal::g_executable_path = internal::StreamableToString(argv[0]);
+
+#if GTEST_HAS_DEATH_TEST
+
+  g_argvs.clear();
+  for (int i = 0; i != *argc; i++) {
+    g_argvs.push_back(StreamableToString(argv[i]));
+  }
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+  ParseGoogleTestFlagsOnly(argc, argv);
+  GetUnitTestImpl()->PostFlagParsingInit();
+}
+
+}  // namespace internal
+
+// Initializes Google Test.  This must be called before calling
+// RUN_ALL_TESTS().  In particular, it parses a command line for the
+// flags that Google Test recognizes.  Whenever a Google Test flag is
+// seen, it is removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Test flag variables are
+// updated.
+//
+// Calling the function for the second time has no user-visible effect.
+void InitGoogleTest(int* argc, char** argv) {
+  internal::InitGoogleTestImpl(argc, argv);
+}
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+void InitGoogleTest(int* argc, wchar_t** argv) {
+  internal::InitGoogleTestImpl(argc, argv);
+}
+
+}  // namespace testing
diff --git a/third_party/googletest/src/src/gtest_main.cc b/third_party/googletest/src/src/gtest_main.cc
new file mode 100644 (file)
index 0000000..a09bbe0
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2006, 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.
+
+#include <iostream>
+
+#include "gtest/gtest.h"
+
+GTEST_API_ int main(int argc, char **argv) {
+  std::cout << "Running main() from gtest_main.cc\n";
+
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/src/test/gtest-death-test_ex_test.cc b/third_party/googletest/src/test/gtest-death-test_ex_test.cc
new file mode 100644 (file)
index 0000000..b50a13d
--- /dev/null
@@ -0,0 +1,93 @@
+// Copyright 2010, 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: vladl@google.com (Vlad Losev)
+//
+// Tests that verify interaction of exceptions and death tests.
+
+#include "gtest/gtest-death-test.h"
+#include "gtest/gtest.h"
+
+#if GTEST_HAS_DEATH_TEST
+
+# if GTEST_HAS_SEH
+#  include <windows.h>          // For RaiseException().
+# endif
+
+# include "gtest/gtest-spi.h"
+
+# if GTEST_HAS_EXCEPTIONS
+
+#  include <exception>  // For std::exception.
+
+// Tests that death tests report thrown exceptions as failures and that the
+// exceptions do not escape death test macros.
+TEST(CxxExceptionDeathTest, ExceptionIsFailure) {
+  try {
+    EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(throw 1, ""), "threw an exception");
+  } catch (...) {  // NOLINT
+    FAIL() << "An exception escaped a death test macro invocation "
+           << "with catch_exceptions "
+           << (testing::GTEST_FLAG(catch_exceptions) ? "enabled" : "disabled");
+  }
+}
+
+class TestException : public std::exception {
+ public:
+  virtual const char* what() const throw() { return "exceptional message"; }
+};
+
+TEST(CxxExceptionDeathTest, PrintsMessageForStdExceptions) {
+  // Verifies that the exception message is quoted in the failure text.
+  EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(throw TestException(), ""),
+                          "exceptional message");
+  // Verifies that the location is mentioned in the failure text.
+  EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(throw TestException(), ""),
+                          "gtest-death-test_ex_test.cc");
+}
+# endif  // GTEST_HAS_EXCEPTIONS
+
+# if GTEST_HAS_SEH
+// Tests that enabling interception of SEH exceptions with the
+// catch_exceptions flag does not interfere with SEH exceptions being
+// treated as death by death tests.
+TEST(SehExceptionDeasTest, CatchExceptionsDoesNotInterfere) {
+  EXPECT_DEATH(RaiseException(42, 0x0, 0, NULL), "")
+      << "with catch_exceptions "
+      << (testing::GTEST_FLAG(catch_exceptions) ? "enabled" : "disabled");
+}
+# endif
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+  testing::GTEST_FLAG(catch_exceptions) = GTEST_ENABLE_CATCH_EXCEPTIONS_ != 0;
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/src/test/gtest-death-test_test.cc b/third_party/googletest/src/test/gtest-death-test_test.cc
new file mode 100644 (file)
index 0000000..bcf8e2a
--- /dev/null
@@ -0,0 +1,1296 @@
+// Copyright 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: wan@google.com (Zhanyong Wan)
+//
+// Tests for death tests.
+
+#include "gtest/gtest-death-test.h"
+#include "gtest/gtest.h"
+#include "gtest/internal/gtest-filepath.h"
+
+using testing::internal::AlwaysFalse;
+using testing::internal::AlwaysTrue;
+
+#if GTEST_HAS_DEATH_TEST
+
+# if GTEST_OS_WINDOWS
+#  include <direct.h>          // For chdir().
+# else
+#  include <unistd.h>
+#  include <sys/wait.h>        // For waitpid.
+#  include <limits>            // For std::numeric_limits.
+# endif  // GTEST_OS_WINDOWS
+
+# include <limits.h>
+# include <signal.h>
+# include <stdio.h>
+
+# include "gtest/gtest-spi.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+# define GTEST_IMPLEMENTATION_ 1
+# include "src/gtest-internal-inl.h"
+# undef GTEST_IMPLEMENTATION_
+
+namespace posix = ::testing::internal::posix;
+
+using testing::Message;
+using testing::internal::DeathTest;
+using testing::internal::DeathTestFactory;
+using testing::internal::FilePath;
+using testing::internal::GetLastErrnoDescription;
+using testing::internal::GetUnitTestImpl;
+using testing::internal::ParseNaturalNumber;
+using testing::internal::String;
+
+namespace testing {
+namespace internal {
+
+// A helper class whose objects replace the death test factory for a
+// single UnitTest object during their lifetimes.
+class ReplaceDeathTestFactory {
+ public:
+  explicit ReplaceDeathTestFactory(DeathTestFactory* new_factory)
+      : unit_test_impl_(GetUnitTestImpl()) {
+    old_factory_ = unit_test_impl_->death_test_factory_.release();
+    unit_test_impl_->death_test_factory_.reset(new_factory);
+  }
+
+  ~ReplaceDeathTestFactory() {
+    unit_test_impl_->death_test_factory_.release();
+    unit_test_impl_->death_test_factory_.reset(old_factory_);
+  }
+ private:
+  // Prevents copying ReplaceDeathTestFactory objects.
+  ReplaceDeathTestFactory(const ReplaceDeathTestFactory&);
+  void operator=(const ReplaceDeathTestFactory&);
+
+  UnitTestImpl* unit_test_impl_;
+  DeathTestFactory* old_factory_;
+};
+
+}  // namespace internal
+}  // namespace testing
+
+void DieWithMessage(const ::std::string& message) {
+  fprintf(stderr, "%s", message.c_str());
+  fflush(stderr);  // Make sure the text is printed before the process exits.
+
+  // We call _exit() instead of exit(), as the former is a direct
+  // system call and thus safer in the presence of threads.  exit()
+  // will invoke user-defined exit-hooks, which may do dangerous
+  // things that conflict with death tests.
+  //
+  // Some compilers can recognize that _exit() never returns and issue the
+  // 'unreachable code' warning for code following this function, unless
+  // fooled by a fake condition.
+  if (AlwaysTrue())
+    _exit(1);
+}
+
+void DieInside(const ::std::string& function) {
+  DieWithMessage("death inside " + function + "().");
+}
+
+// Tests that death tests work.
+
+class TestForDeathTest : public testing::Test {
+ protected:
+  TestForDeathTest() : original_dir_(FilePath::GetCurrentDir()) {}
+
+  virtual ~TestForDeathTest() {
+    posix::ChDir(original_dir_.c_str());
+  }
+
+  // A static member function that's expected to die.
+  static void StaticMemberFunction() { DieInside("StaticMemberFunction"); }
+
+  // A method of the test fixture that may die.
+  void MemberFunction() {
+    if (should_die_)
+      DieInside("MemberFunction");
+  }
+
+  // True iff MemberFunction() should die.
+  bool should_die_;
+  const FilePath original_dir_;
+};
+
+// A class with a member function that may die.
+class MayDie {
+ public:
+  explicit MayDie(bool should_die) : should_die_(should_die) {}
+
+  // A member function that may die.
+  void MemberFunction() const {
+    if (should_die_)
+      DieInside("MayDie::MemberFunction");
+  }
+
+ private:
+  // True iff MemberFunction() should die.
+  bool should_die_;
+};
+
+// A global function that's expected to die.
+void GlobalFunction() { DieInside("GlobalFunction"); }
+
+// A non-void function that's expected to die.
+int NonVoidFunction() {
+  DieInside("NonVoidFunction");
+  return 1;
+}
+
+// A unary function that may die.
+void DieIf(bool should_die) {
+  if (should_die)
+    DieInside("DieIf");
+}
+
+// A binary function that may die.
+bool DieIfLessThan(int x, int y) {
+  if (x < y) {
+    DieInside("DieIfLessThan");
+  }
+  return true;
+}
+
+// Tests that ASSERT_DEATH can be used outside a TEST, TEST_F, or test fixture.
+void DeathTestSubroutine() {
+  EXPECT_DEATH(GlobalFunction(), "death.*GlobalFunction");
+  ASSERT_DEATH(GlobalFunction(), "death.*GlobalFunction");
+}
+
+// Death in dbg, not opt.
+int DieInDebugElse12(int* sideeffect) {
+  if (sideeffect) *sideeffect = 12;
+
+# ifndef NDEBUG
+
+  DieInside("DieInDebugElse12");
+
+# endif  // NDEBUG
+
+  return 12;
+}
+
+# if GTEST_OS_WINDOWS
+
+// Tests the ExitedWithCode predicate.
+TEST(ExitStatusPredicateTest, ExitedWithCode) {
+  // On Windows, the process's exit code is the same as its exit status,
+  // so the predicate just compares the its input with its parameter.
+  EXPECT_TRUE(testing::ExitedWithCode(0)(0));
+  EXPECT_TRUE(testing::ExitedWithCode(1)(1));
+  EXPECT_TRUE(testing::ExitedWithCode(42)(42));
+  EXPECT_FALSE(testing::ExitedWithCode(0)(1));
+  EXPECT_FALSE(testing::ExitedWithCode(1)(0));
+}
+
+# else
+
+// Returns the exit status of a process that calls _exit(2) with a
+// given exit code.  This is a helper function for the
+// ExitStatusPredicateTest test suite.
+static int NormalExitStatus(int exit_code) {
+  pid_t child_pid = fork();
+  if (child_pid == 0) {
+    _exit(exit_code);
+  }
+  int status;
+  waitpid(child_pid, &status, 0);
+  return status;
+}
+
+// Returns the exit status of a process that raises a given signal.
+// If the signal does not cause the process to die, then it returns
+// instead the exit status of a process that exits normally with exit
+// code 1.  This is a helper function for the ExitStatusPredicateTest
+// test suite.
+static int KilledExitStatus(int signum) {
+  pid_t child_pid = fork();
+  if (child_pid == 0) {
+    raise(signum);
+    _exit(1);
+  }
+  int status;
+  waitpid(child_pid, &status, 0);
+  return status;
+}
+
+// Tests the ExitedWithCode predicate.
+TEST(ExitStatusPredicateTest, ExitedWithCode) {
+  const int status0  = NormalExitStatus(0);
+  const int status1  = NormalExitStatus(1);
+  const int status42 = NormalExitStatus(42);
+  const testing::ExitedWithCode pred0(0);
+  const testing::ExitedWithCode pred1(1);
+  const testing::ExitedWithCode pred42(42);
+  EXPECT_PRED1(pred0,  status0);
+  EXPECT_PRED1(pred1,  status1);
+  EXPECT_PRED1(pred42, status42);
+  EXPECT_FALSE(pred0(status1));
+  EXPECT_FALSE(pred42(status0));
+  EXPECT_FALSE(pred1(status42));
+}
+
+// Tests the KilledBySignal predicate.
+TEST(ExitStatusPredicateTest, KilledBySignal) {
+  const int status_segv = KilledExitStatus(SIGSEGV);
+  const int status_kill = KilledExitStatus(SIGKILL);
+  const testing::KilledBySignal pred_segv(SIGSEGV);
+  const testing::KilledBySignal pred_kill(SIGKILL);
+  EXPECT_PRED1(pred_segv, status_segv);
+  EXPECT_PRED1(pred_kill, status_kill);
+  EXPECT_FALSE(pred_segv(status_kill));
+  EXPECT_FALSE(pred_kill(status_segv));
+}
+
+# endif  // GTEST_OS_WINDOWS
+
+// Tests that the death test macros expand to code which may or may not
+// be followed by operator<<, and that in either case the complete text
+// comprises only a single C++ statement.
+TEST_F(TestForDeathTest, SingleStatement) {
+  if (AlwaysFalse())
+    // This would fail if executed; this is a compilation test only
+    ASSERT_DEATH(return, "");
+
+  if (AlwaysTrue())
+    EXPECT_DEATH(_exit(1), "");
+  else
+    // This empty "else" branch is meant to ensure that EXPECT_DEATH
+    // doesn't expand into an "if" statement without an "else"
+    ;
+
+  if (AlwaysFalse())
+    ASSERT_DEATH(return, "") << "did not die";
+
+  if (AlwaysFalse())
+    ;
+  else
+    EXPECT_DEATH(_exit(1), "") << 1 << 2 << 3;
+}
+
+void DieWithEmbeddedNul() {
+  fprintf(stderr, "Hello%cmy null world.\n", '\0');
+  fflush(stderr);
+  _exit(1);
+}
+
+# if GTEST_USES_PCRE
+// Tests that EXPECT_DEATH and ASSERT_DEATH work when the error
+// message has a NUL character in it.
+TEST_F(TestForDeathTest, EmbeddedNulInMessage) {
+  // TODO(wan@google.com): <regex.h> doesn't support matching strings
+  // with embedded NUL characters - find a way to workaround it.
+  EXPECT_DEATH(DieWithEmbeddedNul(), "my null world");
+  ASSERT_DEATH(DieWithEmbeddedNul(), "my null world");
+}
+# endif  // GTEST_USES_PCRE
+
+// Tests that death test macros expand to code which interacts well with switch
+// statements.
+TEST_F(TestForDeathTest, SwitchStatement) {
+// Microsoft compiler usually complains about switch statements without
+// case labels. We suppress that warning for this test.
+# ifdef _MSC_VER
+#  pragma warning(push)
+#  pragma warning(disable: 4065)
+# endif  // _MSC_VER
+
+  switch (0)
+    default:
+      ASSERT_DEATH(_exit(1), "") << "exit in default switch handler";
+
+  switch (0)
+    case 0:
+      EXPECT_DEATH(_exit(1), "") << "exit in switch case";
+
+# ifdef _MSC_VER
+#  pragma warning(pop)
+# endif  // _MSC_VER
+}
+
+// Tests that a static member function can be used in a "fast" style
+// death test.
+TEST_F(TestForDeathTest, StaticMemberFunctionFastStyle) {
+  testing::GTEST_FLAG(death_test_style) = "fast";
+  ASSERT_DEATH(StaticMemberFunction(), "death.*StaticMember");
+}
+
+// Tests that a method of the test fixture can be used in a "fast"
+// style death test.
+TEST_F(TestForDeathTest, MemberFunctionFastStyle) {
+  testing::GTEST_FLAG(death_test_style) = "fast";
+  should_die_ = true;
+  EXPECT_DEATH(MemberFunction(), "inside.*MemberFunction");
+}
+
+void ChangeToRootDir() { posix::ChDir(GTEST_PATH_SEP_); }
+
+// Tests that death tests work even if the current directory has been
+// changed.
+TEST_F(TestForDeathTest, FastDeathTestInChangedDir) {
+  testing::GTEST_FLAG(death_test_style) = "fast";
+
+  ChangeToRootDir();
+  EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), "");
+
+  ChangeToRootDir();
+  ASSERT_DEATH(_exit(1), "");
+}
+
+// Repeats a representative sample of death tests in the "threadsafe" style:
+
+TEST_F(TestForDeathTest, StaticMemberFunctionThreadsafeStyle) {
+  testing::GTEST_FLAG(death_test_style) = "threadsafe";
+  ASSERT_DEATH(StaticMemberFunction(), "death.*StaticMember");
+}
+
+TEST_F(TestForDeathTest, MemberFunctionThreadsafeStyle) {
+  testing::GTEST_FLAG(death_test_style) = "threadsafe";
+  should_die_ = true;
+  EXPECT_DEATH(MemberFunction(), "inside.*MemberFunction");
+}
+
+TEST_F(TestForDeathTest, ThreadsafeDeathTestInLoop) {
+  testing::GTEST_FLAG(death_test_style) = "threadsafe";
+
+  for (int i = 0; i < 3; ++i)
+    EXPECT_EXIT(_exit(i), testing::ExitedWithCode(i), "") << ": i = " << i;
+}
+
+TEST_F(TestForDeathTest, ThreadsafeDeathTestInChangedDir) {
+  testing::GTEST_FLAG(death_test_style) = "threadsafe";
+
+  ChangeToRootDir();
+  EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), "");
+
+  ChangeToRootDir();
+  ASSERT_DEATH(_exit(1), "");
+}
+
+TEST_F(TestForDeathTest, MixedStyles) {
+  testing::GTEST_FLAG(death_test_style) = "threadsafe";
+  EXPECT_DEATH(_exit(1), "");
+  testing::GTEST_FLAG(death_test_style) = "fast";
+  EXPECT_DEATH(_exit(1), "");
+}
+
+namespace {
+
+bool pthread_flag;
+
+void SetPthreadFlag() {
+  pthread_flag = true;
+}
+
+}  // namespace
+
+# if GTEST_HAS_CLONE && GTEST_HAS_PTHREAD
+
+TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) {
+  if (!testing::GTEST_FLAG(death_test_use_fork)) {
+    testing::GTEST_FLAG(death_test_style) = "threadsafe";
+    pthread_flag = false;
+    ASSERT_EQ(0, pthread_atfork(&SetPthreadFlag, NULL, NULL));
+    ASSERT_DEATH(_exit(1), "");
+    ASSERT_FALSE(pthread_flag);
+  }
+}
+
+# endif  // GTEST_HAS_CLONE && GTEST_HAS_PTHREAD
+
+// Tests that a method of another class can be used in a death test.
+TEST_F(TestForDeathTest, MethodOfAnotherClass) {
+  const MayDie x(true);
+  ASSERT_DEATH(x.MemberFunction(), "MayDie\\:\\:MemberFunction");
+}
+
+// Tests that a global function can be used in a death test.
+TEST_F(TestForDeathTest, GlobalFunction) {
+  EXPECT_DEATH(GlobalFunction(), "GlobalFunction");
+}
+
+// Tests that any value convertible to an RE works as a second
+// argument to EXPECT_DEATH.
+TEST_F(TestForDeathTest, AcceptsAnythingConvertibleToRE) {
+  static const char regex_c_str[] = "GlobalFunction";
+  EXPECT_DEATH(GlobalFunction(), regex_c_str);
+
+  const testing::internal::RE regex(regex_c_str);
+  EXPECT_DEATH(GlobalFunction(), regex);
+
+# if GTEST_HAS_GLOBAL_STRING
+
+  const string regex_str(regex_c_str);
+  EXPECT_DEATH(GlobalFunction(), regex_str);
+
+# endif  // GTEST_HAS_GLOBAL_STRING
+
+  const ::std::string regex_std_str(regex_c_str);
+  EXPECT_DEATH(GlobalFunction(), regex_std_str);
+}
+
+// Tests that a non-void function can be used in a death test.
+TEST_F(TestForDeathTest, NonVoidFunction) {
+  ASSERT_DEATH(NonVoidFunction(), "NonVoidFunction");
+}
+
+// Tests that functions that take parameter(s) can be used in a death test.
+TEST_F(TestForDeathTest, FunctionWithParameter) {
+  EXPECT_DEATH(DieIf(true), "DieIf\\(\\)");
+  EXPECT_DEATH(DieIfLessThan(2, 3), "DieIfLessThan");
+}
+
+// Tests that ASSERT_DEATH can be used outside a TEST, TEST_F, or test fixture.
+TEST_F(TestForDeathTest, OutsideFixture) {
+  DeathTestSubroutine();
+}
+
+// Tests that death tests can be done inside a loop.
+TEST_F(TestForDeathTest, InsideLoop) {
+  for (int i = 0; i < 5; i++) {
+    EXPECT_DEATH(DieIfLessThan(-1, i), "DieIfLessThan") << "where i == " << i;
+  }
+}
+
+// Tests that a compound statement can be used in a death test.
+TEST_F(TestForDeathTest, CompoundStatement) {
+  EXPECT_DEATH({  // NOLINT
+    const int x = 2;
+    const int y = x + 1;
+    DieIfLessThan(x, y);
+  },
+  "DieIfLessThan");
+}
+
+// Tests that code that doesn't die causes a death test to fail.
+TEST_F(TestForDeathTest, DoesNotDie) {
+  EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(DieIf(false), "DieIf"),
+                          "failed to die");
+}
+
+// Tests that a death test fails when the error message isn't expected.
+TEST_F(TestForDeathTest, ErrorMessageMismatch) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_DEATH(DieIf(true), "DieIfLessThan") << "End of death test message.";
+  }, "died but not with expected error");
+}
+
+// On exit, *aborted will be true iff the EXPECT_DEATH() statement
+// aborted the function.
+void ExpectDeathTestHelper(bool* aborted) {
+  *aborted = true;
+  EXPECT_DEATH(DieIf(false), "DieIf");  // This assertion should fail.
+  *aborted = false;
+}
+
+// Tests that EXPECT_DEATH doesn't abort the test on failure.
+TEST_F(TestForDeathTest, EXPECT_DEATH) {
+  bool aborted = true;
+  EXPECT_NONFATAL_FAILURE(ExpectDeathTestHelper(&aborted),
+                          "failed to die");
+  EXPECT_FALSE(aborted);
+}
+
+// Tests that ASSERT_DEATH does abort the test on failure.
+TEST_F(TestForDeathTest, ASSERT_DEATH) {
+  static bool aborted;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    aborted = true;
+    ASSERT_DEATH(DieIf(false), "DieIf");  // This assertion should fail.
+    aborted = false;
+  }, "failed to die");
+  EXPECT_TRUE(aborted);
+}
+
+// Tests that EXPECT_DEATH evaluates the arguments exactly once.
+TEST_F(TestForDeathTest, SingleEvaluation) {
+  int x = 3;
+  EXPECT_DEATH(DieIf((++x) == 4), "DieIf");
+
+  const char* regex = "DieIf";
+  const char* regex_save = regex;
+  EXPECT_DEATH(DieIfLessThan(3, 4), regex++);
+  EXPECT_EQ(regex_save + 1, regex);
+}
+
+// Tests that run-away death tests are reported as failures.
+TEST_F(TestForDeathTest, RunawayIsFailure) {
+  EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(static_cast<void>(0), "Foo"),
+                          "failed to die.");
+}
+
+// Tests that death tests report executing 'return' in the statement as
+// failure.
+TEST_F(TestForDeathTest, ReturnIsFailure) {
+  EXPECT_FATAL_FAILURE(ASSERT_DEATH(return, "Bar"),
+                       "illegal return in test statement.");
+}
+
+// Tests that EXPECT_DEBUG_DEATH works as expected,
+// that is, in debug mode, it:
+// 1. Asserts on death.
+// 2. Has no side effect.
+//
+// And in opt mode, it:
+// 1.  Has side effects but does not assert.
+TEST_F(TestForDeathTest, TestExpectDebugDeath) {
+  int sideeffect = 0;
+
+  EXPECT_DEBUG_DEATH(DieInDebugElse12(&sideeffect),
+                     "death.*DieInDebugElse12");
+
+# ifdef NDEBUG
+
+  // Checks that the assignment occurs in opt mode (sideeffect).
+  EXPECT_EQ(12, sideeffect);
+
+# else
+
+  // Checks that the assignment does not occur in dbg mode (no sideeffect).
+  EXPECT_EQ(0, sideeffect);
+
+# endif
+}
+
+// Tests that ASSERT_DEBUG_DEATH works as expected
+// In debug mode:
+// 1. Asserts on debug death.
+// 2. Has no side effect.
+//
+// In opt mode:
+// 1. Has side effects and returns the expected value (12).
+TEST_F(TestForDeathTest, TestAssertDebugDeath) {
+  int sideeffect = 0;
+
+  ASSERT_DEBUG_DEATH({  // NOLINT
+    // Tests that the return value is 12 in opt mode.
+    EXPECT_EQ(12, DieInDebugElse12(&sideeffect));
+    // Tests that the side effect occurred in opt mode.
+    EXPECT_EQ(12, sideeffect);
+  }, "death.*DieInDebugElse12");
+
+# ifdef NDEBUG
+
+  // Checks that the assignment occurs in opt mode (sideeffect).
+  EXPECT_EQ(12, sideeffect);
+
+# else
+
+  // Checks that the assignment does not occur in dbg mode (no sideeffect).
+  EXPECT_EQ(0, sideeffect);
+
+# endif
+}
+
+# ifndef NDEBUG
+
+void ExpectDebugDeathHelper(bool* aborted) {
+  *aborted = true;
+  EXPECT_DEBUG_DEATH(return, "") << "This is expected to fail.";
+  *aborted = false;
+}
+
+#  if GTEST_OS_WINDOWS
+TEST(PopUpDeathTest, DoesNotShowPopUpOnAbort) {
+  printf("This test should be considered failing if it shows "
+         "any pop-up dialogs.\n");
+  fflush(stdout);
+
+  EXPECT_DEATH({
+    testing::GTEST_FLAG(catch_exceptions) = false;
+    abort();
+  }, "");
+}
+#  endif  // GTEST_OS_WINDOWS
+
+// Tests that EXPECT_DEBUG_DEATH in debug mode does not abort
+// the function.
+TEST_F(TestForDeathTest, ExpectDebugDeathDoesNotAbort) {
+  bool aborted = true;
+  EXPECT_NONFATAL_FAILURE(ExpectDebugDeathHelper(&aborted), "");
+  EXPECT_FALSE(aborted);
+}
+
+void AssertDebugDeathHelper(bool* aborted) {
+  *aborted = true;
+  ASSERT_DEBUG_DEATH(return, "") << "This is expected to fail.";
+  *aborted = false;
+}
+
+// Tests that ASSERT_DEBUG_DEATH in debug mode aborts the function on
+// failure.
+TEST_F(TestForDeathTest, AssertDebugDeathAborts) {
+  static bool aborted;
+  aborted = false;
+  EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
+  EXPECT_TRUE(aborted);
+}
+
+# endif  // _NDEBUG
+
+// Tests the *_EXIT family of macros, using a variety of predicates.
+static void TestExitMacros() {
+  EXPECT_EXIT(_exit(1),  testing::ExitedWithCode(1),  "");
+  ASSERT_EXIT(_exit(42), testing::ExitedWithCode(42), "");
+
+# if GTEST_OS_WINDOWS
+
+  // Of all signals effects on the process exit code, only those of SIGABRT
+  // are documented on Windows.
+  // See http://msdn.microsoft.com/en-us/library/dwwzkt4c(VS.71).aspx.
+  EXPECT_EXIT(raise(SIGABRT), testing::ExitedWithCode(3), "");
+
+# else
+
+  EXPECT_EXIT(raise(SIGKILL), testing::KilledBySignal(SIGKILL), "") << "foo";
+  ASSERT_EXIT(raise(SIGUSR2), testing::KilledBySignal(SIGUSR2), "") << "bar";
+
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_EXIT(_exit(0), testing::KilledBySignal(SIGSEGV), "")
+        << "This failure is expected, too.";
+  }, "This failure is expected, too.");
+
+# endif  // GTEST_OS_WINDOWS
+
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_EXIT(raise(SIGSEGV), testing::ExitedWithCode(0), "")
+        << "This failure is expected.";
+  }, "This failure is expected.");
+}
+
+TEST_F(TestForDeathTest, ExitMacros) {
+  TestExitMacros();
+}
+
+TEST_F(TestForDeathTest, ExitMacrosUsingFork) {
+  testing::GTEST_FLAG(death_test_use_fork) = true;
+  TestExitMacros();
+}
+
+TEST_F(TestForDeathTest, InvalidStyle) {
+  testing::GTEST_FLAG(death_test_style) = "rococo";
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_DEATH(_exit(0), "") << "This failure is expected.";
+  }, "This failure is expected.");
+}
+
+TEST_F(TestForDeathTest, DeathTestFailedOutput) {
+  testing::GTEST_FLAG(death_test_style) = "fast";
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_DEATH(DieWithMessage("death\n"),
+                   "expected message"),
+      "Actual msg:\n"
+      "[  DEATH   ] death\n");
+}
+
+TEST_F(TestForDeathTest, DeathTestUnexpectedReturnOutput) {
+  testing::GTEST_FLAG(death_test_style) = "fast";
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_DEATH({
+          fprintf(stderr, "returning\n");
+          fflush(stderr);
+          return;
+        }, ""),
+      "    Result: illegal return in test statement.\n"
+      " Error msg:\n"
+      "[  DEATH   ] returning\n");
+}
+
+TEST_F(TestForDeathTest, DeathTestBadExitCodeOutput) {
+  testing::GTEST_FLAG(death_test_style) = "fast";
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_EXIT(DieWithMessage("exiting with rc 1\n"),
+                  testing::ExitedWithCode(3),
+                  "expected message"),
+      "    Result: died but not with expected exit code:\n"
+      "            Exited with exit status 1\n"
+      "Actual msg:\n"
+      "[  DEATH   ] exiting with rc 1\n");
+}
+
+TEST_F(TestForDeathTest, DeathTestMultiLineMatchFail) {
+  testing::GTEST_FLAG(death_test_style) = "fast";
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_DEATH(DieWithMessage("line 1\nline 2\nline 3\n"),
+                   "line 1\nxyz\nline 3\n"),
+      "Actual msg:\n"
+      "[  DEATH   ] line 1\n"
+      "[  DEATH   ] line 2\n"
+      "[  DEATH   ] line 3\n");
+}
+
+TEST_F(TestForDeathTest, DeathTestMultiLineMatchPass) {
+  testing::GTEST_FLAG(death_test_style) = "fast";
+  EXPECT_DEATH(DieWithMessage("line 1\nline 2\nline 3\n"),
+               "line 1\nline 2\nline 3\n");
+}
+
+// A DeathTestFactory that returns MockDeathTests.
+class MockDeathTestFactory : public DeathTestFactory {
+ public:
+  MockDeathTestFactory();
+  virtual bool Create(const char* statement,
+                      const ::testing::internal::RE* regex,
+                      const char* file, int line, DeathTest** test);
+
+  // Sets the parameters for subsequent calls to Create.
+  void SetParameters(bool create, DeathTest::TestRole role,
+                     int status, bool passed);
+
+  // Accessors.
+  int AssumeRoleCalls() const { return assume_role_calls_; }
+  int WaitCalls() const { return wait_calls_; }
+  int PassedCalls() const { return passed_args_.size(); }
+  bool PassedArgument(int n) const { return passed_args_[n]; }
+  int AbortCalls() const { return abort_args_.size(); }
+  DeathTest::AbortReason AbortArgument(int n) const {
+    return abort_args_[n];
+  }
+  bool TestDeleted() const { return test_deleted_; }
+
+ private:
+  friend class MockDeathTest;
+  // If true, Create will return a MockDeathTest; otherwise it returns
+  // NULL.
+  bool create_;
+  // The value a MockDeathTest will return from its AssumeRole method.
+  DeathTest::TestRole role_;
+  // The value a MockDeathTest will return from its Wait method.
+  int status_;
+  // The value a MockDeathTest will return from its Passed method.
+  bool passed_;
+
+  // Number of times AssumeRole was called.
+  int assume_role_calls_;
+  // Number of times Wait was called.
+  int wait_calls_;
+  // The arguments to the calls to Passed since the last call to
+  // SetParameters.
+  std::vector<bool> passed_args_;
+  // The arguments to the calls to Abort since the last call to
+  // SetParameters.
+  std::vector<DeathTest::AbortReason> abort_args_;
+  // True if the last MockDeathTest returned by Create has been
+  // deleted.
+  bool test_deleted_;
+};
+
+
+// A DeathTest implementation useful in testing.  It returns values set
+// at its creation from its various inherited DeathTest methods, and
+// reports calls to those methods to its parent MockDeathTestFactory
+// object.
+class MockDeathTest : public DeathTest {
+ public:
+  MockDeathTest(MockDeathTestFactory *parent,
+                TestRole role, int status, bool passed) :
+      parent_(parent), role_(role), status_(status), passed_(passed) {
+  }
+  virtual ~MockDeathTest() {
+    parent_->test_deleted_ = true;
+  }
+  virtual TestRole AssumeRole() {
+    ++parent_->assume_role_calls_;
+    return role_;
+  }
+  virtual int Wait() {
+    ++parent_->wait_calls_;
+    return status_;
+  }
+  virtual bool Passed(bool exit_status_ok) {
+    parent_->passed_args_.push_back(exit_status_ok);
+    return passed_;
+  }
+  virtual void Abort(AbortReason reason) {
+    parent_->abort_args_.push_back(reason);
+  }
+ private:
+  MockDeathTestFactory* const parent_;
+  const TestRole role_;
+  const int status_;
+  const bool passed_;
+};
+
+
+// MockDeathTestFactory constructor.
+MockDeathTestFactory::MockDeathTestFactory()
+    : create_(true),
+      role_(DeathTest::OVERSEE_TEST),
+      status_(0),
+      passed_(true),
+      assume_role_calls_(0),
+      wait_calls_(0),
+      passed_args_(),
+      abort_args_() {
+}
+
+
+// Sets the parameters for subsequent calls to Create.
+void MockDeathTestFactory::SetParameters(bool create,
+                                         DeathTest::TestRole role,
+                                         int status, bool passed) {
+  create_ = create;
+  role_ = role;
+  status_ = status;
+  passed_ = passed;
+
+  assume_role_calls_ = 0;
+  wait_calls_ = 0;
+  passed_args_.clear();
+  abort_args_.clear();
+}
+
+
+// Sets test to NULL (if create_ is false) or to the address of a new
+// MockDeathTest object with parameters taken from the last call
+// to SetParameters (if create_ is true).  Always returns true.
+bool MockDeathTestFactory::Create(const char* /*statement*/,
+                                  const ::testing::internal::RE* /*regex*/,
+                                  const char* /*file*/,
+                                  int /*line*/,
+                                  DeathTest** test) {
+  test_deleted_ = false;
+  if (create_) {
+    *test = new MockDeathTest(this, role_, status_, passed_);
+  } else {
+    *test = NULL;
+  }
+  return true;
+}
+
+// A test fixture for testing the logic of the GTEST_DEATH_TEST_ macro.
+// It installs a MockDeathTestFactory that is used for the duration
+// of the test case.
+class MacroLogicDeathTest : public testing::Test {
+ protected:
+  static testing::internal::ReplaceDeathTestFactory* replacer_;
+  static MockDeathTestFactory* factory_;
+
+  static void SetUpTestCase() {
+    factory_ = new MockDeathTestFactory;
+    replacer_ = new testing::internal::ReplaceDeathTestFactory(factory_);
+  }
+
+  static void TearDownTestCase() {
+    delete replacer_;
+    replacer_ = NULL;
+    delete factory_;
+    factory_ = NULL;
+  }
+
+  // Runs a death test that breaks the rules by returning.  Such a death
+  // test cannot be run directly from a test routine that uses a
+  // MockDeathTest, or the remainder of the routine will not be executed.
+  static void RunReturningDeathTest(bool* flag) {
+    ASSERT_DEATH({  // NOLINT
+      *flag = true;
+      return;
+    }, "");
+  }
+};
+
+testing::internal::ReplaceDeathTestFactory* MacroLogicDeathTest::replacer_
+    = NULL;
+MockDeathTestFactory* MacroLogicDeathTest::factory_ = NULL;
+
+
+// Test that nothing happens when the factory doesn't return a DeathTest:
+TEST_F(MacroLogicDeathTest, NothingHappens) {
+  bool flag = false;
+  factory_->SetParameters(false, DeathTest::OVERSEE_TEST, 0, true);
+  EXPECT_DEATH(flag = true, "");
+  EXPECT_FALSE(flag);
+  EXPECT_EQ(0, factory_->AssumeRoleCalls());
+  EXPECT_EQ(0, factory_->WaitCalls());
+  EXPECT_EQ(0, factory_->PassedCalls());
+  EXPECT_EQ(0, factory_->AbortCalls());
+  EXPECT_FALSE(factory_->TestDeleted());
+}
+
+// Test that the parent process doesn't run the death test code,
+// and that the Passed method returns false when the (simulated)
+// child process exits with status 0:
+TEST_F(MacroLogicDeathTest, ChildExitsSuccessfully) {
+  bool flag = false;
+  factory_->SetParameters(true, DeathTest::OVERSEE_TEST, 0, true);
+  EXPECT_DEATH(flag = true, "");
+  EXPECT_FALSE(flag);
+  EXPECT_EQ(1, factory_->AssumeRoleCalls());
+  EXPECT_EQ(1, factory_->WaitCalls());
+  ASSERT_EQ(1, factory_->PassedCalls());
+  EXPECT_FALSE(factory_->PassedArgument(0));
+  EXPECT_EQ(0, factory_->AbortCalls());
+  EXPECT_TRUE(factory_->TestDeleted());
+}
+
+// Tests that the Passed method was given the argument "true" when
+// the (simulated) child process exits with status 1:
+TEST_F(MacroLogicDeathTest, ChildExitsUnsuccessfully) {
+  bool flag = false;
+  factory_->SetParameters(true, DeathTest::OVERSEE_TEST, 1, true);
+  EXPECT_DEATH(flag = true, "");
+  EXPECT_FALSE(flag);
+  EXPECT_EQ(1, factory_->AssumeRoleCalls());
+  EXPECT_EQ(1, factory_->WaitCalls());
+  ASSERT_EQ(1, factory_->PassedCalls());
+  EXPECT_TRUE(factory_->PassedArgument(0));
+  EXPECT_EQ(0, factory_->AbortCalls());
+  EXPECT_TRUE(factory_->TestDeleted());
+}
+
+// Tests that the (simulated) child process executes the death test
+// code, and is aborted with the correct AbortReason if it
+// executes a return statement.
+TEST_F(MacroLogicDeathTest, ChildPerformsReturn) {
+  bool flag = false;
+  factory_->SetParameters(true, DeathTest::EXECUTE_TEST, 0, true);
+  RunReturningDeathTest(&flag);
+  EXPECT_TRUE(flag);
+  EXPECT_EQ(1, factory_->AssumeRoleCalls());
+  EXPECT_EQ(0, factory_->WaitCalls());
+  EXPECT_EQ(0, factory_->PassedCalls());
+  EXPECT_EQ(1, factory_->AbortCalls());
+  EXPECT_EQ(DeathTest::TEST_ENCOUNTERED_RETURN_STATEMENT,
+            factory_->AbortArgument(0));
+  EXPECT_TRUE(factory_->TestDeleted());
+}
+
+// Tests that the (simulated) child process is aborted with the
+// correct AbortReason if it does not die.
+TEST_F(MacroLogicDeathTest, ChildDoesNotDie) {
+  bool flag = false;
+  factory_->SetParameters(true, DeathTest::EXECUTE_TEST, 0, true);
+  EXPECT_DEATH(flag = true, "");
+  EXPECT_TRUE(flag);
+  EXPECT_EQ(1, factory_->AssumeRoleCalls());
+  EXPECT_EQ(0, factory_->WaitCalls());
+  EXPECT_EQ(0, factory_->PassedCalls());
+  // This time there are two calls to Abort: one since the test didn't
+  // die, and another from the ReturnSentinel when it's destroyed.  The
+  // sentinel normally isn't destroyed if a test doesn't die, since
+  // _exit(2) is called in that case by ForkingDeathTest, but not by
+  // our MockDeathTest.
+  ASSERT_EQ(2, factory_->AbortCalls());
+  EXPECT_EQ(DeathTest::TEST_DID_NOT_DIE,
+            factory_->AbortArgument(0));
+  EXPECT_EQ(DeathTest::TEST_ENCOUNTERED_RETURN_STATEMENT,
+            factory_->AbortArgument(1));
+  EXPECT_TRUE(factory_->TestDeleted());
+}
+
+// Tests that a successful death test does not register a successful
+// test part.
+TEST(SuccessRegistrationDeathTest, NoSuccessPart) {
+  EXPECT_DEATH(_exit(1), "");
+  EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
+}
+
+TEST(StreamingAssertionsDeathTest, DeathTest) {
+  EXPECT_DEATH(_exit(1), "") << "unexpected failure";
+  ASSERT_DEATH(_exit(1), "") << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_DEATH(_exit(0), "") << "expected failure";
+  }, "expected failure");
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_DEATH(_exit(0), "") << "expected failure";
+  }, "expected failure");
+}
+
+// Tests that GetLastErrnoDescription returns an empty string when the
+// last error is 0 and non-empty string when it is non-zero.
+TEST(GetLastErrnoDescription, GetLastErrnoDescriptionWorks) {
+  errno = ENOENT;
+  EXPECT_STRNE("", GetLastErrnoDescription().c_str());
+  errno = 0;
+  EXPECT_STREQ("", GetLastErrnoDescription().c_str());
+}
+
+# if GTEST_OS_WINDOWS
+TEST(AutoHandleTest, AutoHandleWorks) {
+  HANDLE handle = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+  ASSERT_NE(INVALID_HANDLE_VALUE, handle);
+
+  // Tests that the AutoHandle is correctly initialized with a handle.
+  testing::internal::AutoHandle auto_handle(handle);
+  EXPECT_EQ(handle, auto_handle.Get());
+
+  // Tests that Reset assigns INVALID_HANDLE_VALUE.
+  // Note that this cannot verify whether the original handle is closed.
+  auto_handle.Reset();
+  EXPECT_EQ(INVALID_HANDLE_VALUE, auto_handle.Get());
+
+  // Tests that Reset assigns the new handle.
+  // Note that this cannot verify whether the original handle is closed.
+  handle = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+  ASSERT_NE(INVALID_HANDLE_VALUE, handle);
+  auto_handle.Reset(handle);
+  EXPECT_EQ(handle, auto_handle.Get());
+
+  // Tests that AutoHandle contains INVALID_HANDLE_VALUE by default.
+  testing::internal::AutoHandle auto_handle2;
+  EXPECT_EQ(INVALID_HANDLE_VALUE, auto_handle2.Get());
+}
+# endif  // GTEST_OS_WINDOWS
+
+# if GTEST_OS_WINDOWS
+typedef unsigned __int64 BiggestParsable;
+typedef signed __int64 BiggestSignedParsable;
+const BiggestParsable kBiggestParsableMax = ULLONG_MAX;
+const BiggestSignedParsable kBiggestSignedParsableMax = LLONG_MAX;
+# else
+typedef unsigned long long BiggestParsable;
+typedef signed long long BiggestSignedParsable;
+const BiggestParsable kBiggestParsableMax =
+    ::std::numeric_limits<BiggestParsable>::max();
+const BiggestSignedParsable kBiggestSignedParsableMax =
+    ::std::numeric_limits<BiggestSignedParsable>::max();
+# endif  // GTEST_OS_WINDOWS
+
+TEST(ParseNaturalNumberTest, RejectsInvalidFormat) {
+  BiggestParsable result = 0;
+
+  // Rejects non-numbers.
+  EXPECT_FALSE(ParseNaturalNumber(String("non-number string"), &result));
+
+  // Rejects numbers with whitespace prefix.
+  EXPECT_FALSE(ParseNaturalNumber(String(" 123"), &result));
+
+  // Rejects negative numbers.
+  EXPECT_FALSE(ParseNaturalNumber(String("-123"), &result));
+
+  // Rejects numbers starting with a plus sign.
+  EXPECT_FALSE(ParseNaturalNumber(String("+123"), &result));
+  errno = 0;
+}
+
+TEST(ParseNaturalNumberTest, RejectsOverflownNumbers) {
+  BiggestParsable result = 0;
+
+  EXPECT_FALSE(ParseNaturalNumber(String("99999999999999999999999"), &result));
+
+  signed char char_result = 0;
+  EXPECT_FALSE(ParseNaturalNumber(String("200"), &char_result));
+  errno = 0;
+}
+
+TEST(ParseNaturalNumberTest, AcceptsValidNumbers) {
+  BiggestParsable result = 0;
+
+  result = 0;
+  ASSERT_TRUE(ParseNaturalNumber(String("123"), &result));
+  EXPECT_EQ(123U, result);
+
+  // Check 0 as an edge case.
+  result = 1;
+  ASSERT_TRUE(ParseNaturalNumber(String("0"), &result));
+  EXPECT_EQ(0U, result);
+
+  result = 1;
+  ASSERT_TRUE(ParseNaturalNumber(String("00000"), &result));
+  EXPECT_EQ(0U, result);
+}
+
+TEST(ParseNaturalNumberTest, AcceptsTypeLimits) {
+  Message msg;
+  msg << kBiggestParsableMax;
+
+  BiggestParsable result = 0;
+  EXPECT_TRUE(ParseNaturalNumber(msg.GetString(), &result));
+  EXPECT_EQ(kBiggestParsableMax, result);
+
+  Message msg2;
+  msg2 << kBiggestSignedParsableMax;
+
+  BiggestSignedParsable signed_result = 0;
+  EXPECT_TRUE(ParseNaturalNumber(msg2.GetString(), &signed_result));
+  EXPECT_EQ(kBiggestSignedParsableMax, signed_result);
+
+  Message msg3;
+  msg3 << INT_MAX;
+
+  int int_result = 0;
+  EXPECT_TRUE(ParseNaturalNumber(msg3.GetString(), &int_result));
+  EXPECT_EQ(INT_MAX, int_result);
+
+  Message msg4;
+  msg4 << UINT_MAX;
+
+  unsigned int uint_result = 0;
+  EXPECT_TRUE(ParseNaturalNumber(msg4.GetString(), &uint_result));
+  EXPECT_EQ(UINT_MAX, uint_result);
+}
+
+TEST(ParseNaturalNumberTest, WorksForShorterIntegers) {
+  short short_result = 0;
+  ASSERT_TRUE(ParseNaturalNumber(String("123"), &short_result));
+  EXPECT_EQ(123, short_result);
+
+  signed char char_result = 0;
+  ASSERT_TRUE(ParseNaturalNumber(String("123"), &char_result));
+  EXPECT_EQ(123, char_result);
+}
+
+# if GTEST_OS_WINDOWS
+TEST(EnvironmentTest, HandleFitsIntoSizeT) {
+  // TODO(vladl@google.com): Remove this test after this condition is verified
+  // in a static assertion in gtest-death-test.cc in the function
+  // GetStatusFileDescriptor.
+  ASSERT_TRUE(sizeof(HANDLE) <= sizeof(size_t));
+}
+# endif  // GTEST_OS_WINDOWS
+
+// Tests that EXPECT_DEATH_IF_SUPPORTED/ASSERT_DEATH_IF_SUPPORTED trigger
+// failures when death tests are available on the system.
+TEST(ConditionalDeathMacrosDeathTest, ExpectsDeathWhenDeathTestsAvailable) {
+  EXPECT_DEATH_IF_SUPPORTED(DieInside("CondDeathTestExpectMacro"),
+                            "death inside CondDeathTestExpectMacro");
+  ASSERT_DEATH_IF_SUPPORTED(DieInside("CondDeathTestAssertMacro"),
+                            "death inside CondDeathTestAssertMacro");
+
+  // Empty statement will not crash, which must trigger a failure.
+  EXPECT_NONFATAL_FAILURE(EXPECT_DEATH_IF_SUPPORTED(;, ""), "");
+  EXPECT_FATAL_FAILURE(ASSERT_DEATH_IF_SUPPORTED(;, ""), "");
+}
+
+#else
+
+using testing::internal::CaptureStderr;
+using testing::internal::GetCapturedStderr;
+using testing::internal::String;
+
+// Tests that EXPECT_DEATH_IF_SUPPORTED/ASSERT_DEATH_IF_SUPPORTED are still
+// defined but do not trigger failures when death tests are not available on
+// the system.
+TEST(ConditionalDeathMacrosTest, WarnsWhenDeathTestsNotAvailable) {
+  // Empty statement will not crash, but that should not trigger a failure
+  // when death tests are not supported.
+  CaptureStderr();
+  EXPECT_DEATH_IF_SUPPORTED(;, "");
+  String output = GetCapturedStderr();
+  ASSERT_TRUE(NULL != strstr(output.c_str(),
+                             "Death tests are not supported on this platform"));
+  ASSERT_TRUE(NULL != strstr(output.c_str(), ";"));
+
+  // The streamed message should not be printed as there is no test failure.
+  CaptureStderr();
+  EXPECT_DEATH_IF_SUPPORTED(;, "") << "streamed message";
+  output = GetCapturedStderr();
+  ASSERT_TRUE(NULL == strstr(output.c_str(), "streamed message"));
+
+  CaptureStderr();
+  ASSERT_DEATH_IF_SUPPORTED(;, "");  // NOLINT
+  output = GetCapturedStderr();
+  ASSERT_TRUE(NULL != strstr(output.c_str(),
+                             "Death tests are not supported on this platform"));
+  ASSERT_TRUE(NULL != strstr(output.c_str(), ";"));
+
+  CaptureStderr();
+  ASSERT_DEATH_IF_SUPPORTED(;, "") << "streamed message";  // NOLINT
+  output = GetCapturedStderr();
+  ASSERT_TRUE(NULL == strstr(output.c_str(), "streamed message"));
+}
+
+void FuncWithAssert(int* n) {
+  ASSERT_DEATH_IF_SUPPORTED(return;, "");
+  (*n)++;
+}
+
+// Tests that ASSERT_DEATH_IF_SUPPORTED does not return from the current
+// function (as ASSERT_DEATH does) if death tests are not supported.
+TEST(ConditionalDeathMacrosTest, AssertDeatDoesNotReturnhIfUnsupported) {
+  int n = 0;
+  FuncWithAssert(&n);
+  EXPECT_EQ(1, n);
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Tests that the death test macros expand to code which may or may not
+// be followed by operator<<, and that in either case the complete text
+// comprises only a single C++ statement.
+//
+// The syntax should work whether death tests are available or not.
+TEST(ConditionalDeathMacrosSyntaxDeathTest, SingleStatement) {
+  if (AlwaysFalse())
+    // This would fail if executed; this is a compilation test only
+    ASSERT_DEATH_IF_SUPPORTED(return, "");
+
+  if (AlwaysTrue())
+    EXPECT_DEATH_IF_SUPPORTED(_exit(1), "");
+  else
+    // This empty "else" branch is meant to ensure that EXPECT_DEATH
+    // doesn't expand into an "if" statement without an "else"
+    ;  // NOLINT
+
+  if (AlwaysFalse())
+    ASSERT_DEATH_IF_SUPPORTED(return, "") << "did not die";
+
+  if (AlwaysFalse())
+    ;  // NOLINT
+  else
+    EXPECT_DEATH_IF_SUPPORTED(_exit(1), "") << 1 << 2 << 3;
+}
+
+// Tests that conditional death test macros expand to code which interacts
+// well with switch statements.
+TEST(ConditionalDeathMacrosSyntaxDeathTest, SwitchStatement) {
+// Microsoft compiler usually complains about switch statements without
+// case labels. We suppress that warning for this test.
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4065)
+#endif  // _MSC_VER
+
+  switch (0)
+    default:
+      ASSERT_DEATH_IF_SUPPORTED(_exit(1), "")
+          << "exit in default switch handler";
+
+  switch (0)
+    case 0:
+      EXPECT_DEATH_IF_SUPPORTED(_exit(1), "") << "exit in switch case";
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif  // _MSC_VER
+}
+
+// Tests that a test case whose name ends with "DeathTest" works fine
+// on Windows.
+TEST(NotADeathTest, Test) {
+  SUCCEED();
+}
diff --git a/third_party/googletest/src/test/gtest-filepath_test.cc b/third_party/googletest/src/test/gtest-filepath_test.cc
new file mode 100644 (file)
index 0000000..66d4118
--- /dev/null
@@ -0,0 +1,696 @@
+// Copyright 2008, 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.
+//
+// Authors: keith.ray@gmail.com (Keith Ray)
+//
+// Google Test filepath utilities
+//
+// This file tests classes and functions used internally by
+// Google Test.  They are subject to change without notice.
+//
+// This file is #included from gtest_unittest.cc, to avoid changing
+// build or make-files for some existing Google Test clients. Do not
+// #include this file anywhere else!
+
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/gtest.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+#if GTEST_OS_WINDOWS_MOBILE
+# include <windows.h>  // NOLINT
+#elif GTEST_OS_WINDOWS
+# include <direct.h>  // NOLINT
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+namespace testing {
+namespace internal {
+namespace {
+
+#if GTEST_OS_WINDOWS_MOBILE
+// TODO(wan@google.com): Move these to the POSIX adapter section in
+// gtest-port.h.
+
+// Windows CE doesn't have the remove C function.
+int remove(const char* path) {
+  LPCWSTR wpath = String::AnsiToUtf16(path);
+  int ret = DeleteFile(wpath) ? 0 : -1;
+  delete [] wpath;
+  return ret;
+}
+// Windows CE doesn't have the _rmdir C function.
+int _rmdir(const char* path) {
+  FilePath filepath(path);
+  LPCWSTR wpath = String::AnsiToUtf16(
+      filepath.RemoveTrailingPathSeparator().c_str());
+  int ret = RemoveDirectory(wpath) ? 0 : -1;
+  delete [] wpath;
+  return ret;
+}
+
+#else
+
+TEST(GetCurrentDirTest, ReturnsCurrentDir) {
+  const FilePath original_dir = FilePath::GetCurrentDir();
+  EXPECT_FALSE(original_dir.IsEmpty());
+
+  posix::ChDir(GTEST_PATH_SEP_);
+  const FilePath cwd = FilePath::GetCurrentDir();
+  posix::ChDir(original_dir.c_str());
+
+# if GTEST_OS_WINDOWS
+
+  // Skips the ":".
+  const char* const cwd_without_drive = strchr(cwd.c_str(), ':');
+  ASSERT_TRUE(cwd_without_drive != NULL);
+  EXPECT_STREQ(GTEST_PATH_SEP_, cwd_without_drive + 1);
+
+# else
+
+  EXPECT_STREQ(GTEST_PATH_SEP_, cwd.c_str());
+
+# endif
+}
+
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+TEST(IsEmptyTest, ReturnsTrueForEmptyPath) {
+  EXPECT_TRUE(FilePath("").IsEmpty());
+  EXPECT_TRUE(FilePath(NULL).IsEmpty());
+}
+
+TEST(IsEmptyTest, ReturnsFalseForNonEmptyPath) {
+  EXPECT_FALSE(FilePath("a").IsEmpty());
+  EXPECT_FALSE(FilePath(".").IsEmpty());
+  EXPECT_FALSE(FilePath("a/b").IsEmpty());
+  EXPECT_FALSE(FilePath("a\\b\\").IsEmpty());
+}
+
+// RemoveDirectoryName "" -> ""
+TEST(RemoveDirectoryNameTest, WhenEmptyName) {
+  EXPECT_STREQ("", FilePath("").RemoveDirectoryName().c_str());
+}
+
+// RemoveDirectoryName "afile" -> "afile"
+TEST(RemoveDirectoryNameTest, ButNoDirectory) {
+  EXPECT_STREQ("afile",
+      FilePath("afile").RemoveDirectoryName().c_str());
+}
+
+// RemoveDirectoryName "/afile" -> "afile"
+TEST(RemoveDirectoryNameTest, RootFileShouldGiveFileName) {
+  EXPECT_STREQ("afile",
+      FilePath(GTEST_PATH_SEP_ "afile").RemoveDirectoryName().c_str());
+}
+
+// RemoveDirectoryName "adir/" -> ""
+TEST(RemoveDirectoryNameTest, WhereThereIsNoFileName) {
+  EXPECT_STREQ("",
+      FilePath("adir" GTEST_PATH_SEP_).RemoveDirectoryName().c_str());
+}
+
+// RemoveDirectoryName "adir/afile" -> "afile"
+TEST(RemoveDirectoryNameTest, ShouldGiveFileName) {
+  EXPECT_STREQ("afile",
+      FilePath("adir" GTEST_PATH_SEP_ "afile").RemoveDirectoryName().c_str());
+}
+
+// RemoveDirectoryName "adir/subdir/afile" -> "afile"
+TEST(RemoveDirectoryNameTest, ShouldAlsoGiveFileName) {
+  EXPECT_STREQ("afile",
+      FilePath("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_ "afile")
+      .RemoveDirectoryName().c_str());
+}
+
+#if GTEST_HAS_ALT_PATH_SEP_
+
+// Tests that RemoveDirectoryName() works with the alternate separator
+// on Windows.
+
+// RemoveDirectoryName("/afile") -> "afile"
+TEST(RemoveDirectoryNameTest, RootFileShouldGiveFileNameForAlternateSeparator) {
+  EXPECT_STREQ("afile",
+               FilePath("/afile").RemoveDirectoryName().c_str());
+}
+
+// RemoveDirectoryName("adir/") -> ""
+TEST(RemoveDirectoryNameTest, WhereThereIsNoFileNameForAlternateSeparator) {
+  EXPECT_STREQ("",
+               FilePath("adir/").RemoveDirectoryName().c_str());
+}
+
+// RemoveDirectoryName("adir/afile") -> "afile"
+TEST(RemoveDirectoryNameTest, ShouldGiveFileNameForAlternateSeparator) {
+  EXPECT_STREQ("afile",
+               FilePath("adir/afile").RemoveDirectoryName().c_str());
+}
+
+// RemoveDirectoryName("adir/subdir/afile") -> "afile"
+TEST(RemoveDirectoryNameTest, ShouldAlsoGiveFileNameForAlternateSeparator) {
+  EXPECT_STREQ("afile",
+               FilePath("adir/subdir/afile").RemoveDirectoryName().c_str());
+}
+
+#endif
+
+// RemoveFileName "" -> "./"
+TEST(RemoveFileNameTest, EmptyName) {
+#if GTEST_OS_WINDOWS_MOBILE
+  // On Windows CE, we use the root as the current directory.
+  EXPECT_STREQ(GTEST_PATH_SEP_,
+      FilePath("").RemoveFileName().c_str());
+#else
+  EXPECT_STREQ("." GTEST_PATH_SEP_,
+      FilePath("").RemoveFileName().c_str());
+#endif
+}
+
+// RemoveFileName "adir/" -> "adir/"
+TEST(RemoveFileNameTest, ButNoFile) {
+  EXPECT_STREQ("adir" GTEST_PATH_SEP_,
+      FilePath("adir" GTEST_PATH_SEP_).RemoveFileName().c_str());
+}
+
+// RemoveFileName "adir/afile" -> "adir/"
+TEST(RemoveFileNameTest, GivesDirName) {
+  EXPECT_STREQ("adir" GTEST_PATH_SEP_,
+      FilePath("adir" GTEST_PATH_SEP_ "afile")
+      .RemoveFileName().c_str());
+}
+
+// RemoveFileName "adir/subdir/afile" -> "adir/subdir/"
+TEST(RemoveFileNameTest, GivesDirAndSubDirName) {
+  EXPECT_STREQ("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_,
+      FilePath("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_ "afile")
+      .RemoveFileName().c_str());
+}
+
+// RemoveFileName "/afile" -> "/"
+TEST(RemoveFileNameTest, GivesRootDir) {
+  EXPECT_STREQ(GTEST_PATH_SEP_,
+      FilePath(GTEST_PATH_SEP_ "afile").RemoveFileName().c_str());
+}
+
+#if GTEST_HAS_ALT_PATH_SEP_
+
+// Tests that RemoveFileName() works with the alternate separator on
+// Windows.
+
+// RemoveFileName("adir/") -> "adir/"
+TEST(RemoveFileNameTest, ButNoFileForAlternateSeparator) {
+  EXPECT_STREQ("adir" GTEST_PATH_SEP_,
+               FilePath("adir/").RemoveFileName().c_str());
+}
+
+// RemoveFileName("adir/afile") -> "adir/"
+TEST(RemoveFileNameTest, GivesDirNameForAlternateSeparator) {
+  EXPECT_STREQ("adir" GTEST_PATH_SEP_,
+               FilePath("adir/afile").RemoveFileName().c_str());
+}
+
+// RemoveFileName("adir/subdir/afile") -> "adir/subdir/"
+TEST(RemoveFileNameTest, GivesDirAndSubDirNameForAlternateSeparator) {
+  EXPECT_STREQ("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_,
+               FilePath("adir/subdir/afile").RemoveFileName().c_str());
+}
+
+// RemoveFileName("/afile") -> "\"
+TEST(RemoveFileNameTest, GivesRootDirForAlternateSeparator) {
+  EXPECT_STREQ(GTEST_PATH_SEP_,
+               FilePath("/afile").RemoveFileName().c_str());
+}
+
+#endif
+
+TEST(MakeFileNameTest, GenerateWhenNumberIsZero) {
+  FilePath actual = FilePath::MakeFileName(FilePath("foo"), FilePath("bar"),
+      0, "xml");
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_ "bar.xml", actual.c_str());
+}
+
+TEST(MakeFileNameTest, GenerateFileNameNumberGtZero) {
+  FilePath actual = FilePath::MakeFileName(FilePath("foo"), FilePath("bar"),
+      12, "xml");
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_ "bar_12.xml", actual.c_str());
+}
+
+TEST(MakeFileNameTest, GenerateFileNameWithSlashNumberIsZero) {
+  FilePath actual = FilePath::MakeFileName(FilePath("foo" GTEST_PATH_SEP_),
+      FilePath("bar"), 0, "xml");
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_ "bar.xml", actual.c_str());
+}
+
+TEST(MakeFileNameTest, GenerateFileNameWithSlashNumberGtZero) {
+  FilePath actual = FilePath::MakeFileName(FilePath("foo" GTEST_PATH_SEP_),
+      FilePath("bar"), 12, "xml");
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_ "bar_12.xml", actual.c_str());
+}
+
+TEST(MakeFileNameTest, GenerateWhenNumberIsZeroAndDirIsEmpty) {
+  FilePath actual = FilePath::MakeFileName(FilePath(""), FilePath("bar"),
+      0, "xml");
+  EXPECT_STREQ("bar.xml", actual.c_str());
+}
+
+TEST(MakeFileNameTest, GenerateWhenNumberIsNotZeroAndDirIsEmpty) {
+  FilePath actual = FilePath::MakeFileName(FilePath(""), FilePath("bar"),
+      14, "xml");
+  EXPECT_STREQ("bar_14.xml", actual.c_str());
+}
+
+TEST(ConcatPathsTest, WorksWhenDirDoesNotEndWithPathSep) {
+  FilePath actual = FilePath::ConcatPaths(FilePath("foo"),
+                                          FilePath("bar.xml"));
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_ "bar.xml", actual.c_str());
+}
+
+TEST(ConcatPathsTest, WorksWhenPath1EndsWithPathSep) {
+  FilePath actual = FilePath::ConcatPaths(FilePath("foo" GTEST_PATH_SEP_),
+                                          FilePath("bar.xml"));
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_ "bar.xml", actual.c_str());
+}
+
+TEST(ConcatPathsTest, Path1BeingEmpty) {
+  FilePath actual = FilePath::ConcatPaths(FilePath(""),
+                                          FilePath("bar.xml"));
+  EXPECT_STREQ("bar.xml", actual.c_str());
+}
+
+TEST(ConcatPathsTest, Path2BeingEmpty) {
+  FilePath actual = FilePath::ConcatPaths(FilePath("foo"),
+                                          FilePath(""));
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_, actual.c_str());
+}
+
+TEST(ConcatPathsTest, BothPathBeingEmpty) {
+  FilePath actual = FilePath::ConcatPaths(FilePath(""),
+                                          FilePath(""));
+  EXPECT_STREQ("", actual.c_str());
+}
+
+TEST(ConcatPathsTest, Path1ContainsPathSep) {
+  FilePath actual = FilePath::ConcatPaths(FilePath("foo" GTEST_PATH_SEP_ "bar"),
+                                          FilePath("foobar.xml"));
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_ "bar" GTEST_PATH_SEP_ "foobar.xml",
+               actual.c_str());
+}
+
+TEST(ConcatPathsTest, Path2ContainsPathSep) {
+  FilePath actual = FilePath::ConcatPaths(
+      FilePath("foo" GTEST_PATH_SEP_),
+      FilePath("bar" GTEST_PATH_SEP_ "bar.xml"));
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_ "bar" GTEST_PATH_SEP_ "bar.xml",
+               actual.c_str());
+}
+
+TEST(ConcatPathsTest, Path2EndsWithPathSep) {
+  FilePath actual = FilePath::ConcatPaths(FilePath("foo"),
+                                          FilePath("bar" GTEST_PATH_SEP_));
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_ "bar" GTEST_PATH_SEP_, actual.c_str());
+}
+
+// RemoveTrailingPathSeparator "" -> ""
+TEST(RemoveTrailingPathSeparatorTest, EmptyString) {
+  EXPECT_STREQ("",
+      FilePath("").RemoveTrailingPathSeparator().c_str());
+}
+
+// RemoveTrailingPathSeparator "foo" -> "foo"
+TEST(RemoveTrailingPathSeparatorTest, FileNoSlashString) {
+  EXPECT_STREQ("foo",
+      FilePath("foo").RemoveTrailingPathSeparator().c_str());
+}
+
+// RemoveTrailingPathSeparator "foo/" -> "foo"
+TEST(RemoveTrailingPathSeparatorTest, ShouldRemoveTrailingSeparator) {
+  EXPECT_STREQ(
+      "foo",
+      FilePath("foo" GTEST_PATH_SEP_).RemoveTrailingPathSeparator().c_str());
+#if GTEST_HAS_ALT_PATH_SEP_
+  EXPECT_STREQ("foo",
+               FilePath("foo/").RemoveTrailingPathSeparator().c_str());
+#endif
+}
+
+// RemoveTrailingPathSeparator "foo/bar/" -> "foo/bar/"
+TEST(RemoveTrailingPathSeparatorTest, ShouldRemoveLastSeparator) {
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_ "bar",
+               FilePath("foo" GTEST_PATH_SEP_ "bar" GTEST_PATH_SEP_)
+               .RemoveTrailingPathSeparator().c_str());
+}
+
+// RemoveTrailingPathSeparator "foo/bar" -> "foo/bar"
+TEST(RemoveTrailingPathSeparatorTest, ShouldReturnUnmodified) {
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_ "bar",
+               FilePath("foo" GTEST_PATH_SEP_ "bar")
+               .RemoveTrailingPathSeparator().c_str());
+}
+
+TEST(DirectoryTest, RootDirectoryExists) {
+#if GTEST_OS_WINDOWS  // We are on Windows.
+  char current_drive[_MAX_PATH];  // NOLINT
+  current_drive[0] = static_cast<char>(_getdrive() + 'A' - 1);
+  current_drive[1] = ':';
+  current_drive[2] = '\\';
+  current_drive[3] = '\0';
+  EXPECT_TRUE(FilePath(current_drive).DirectoryExists());
+#else
+  EXPECT_TRUE(FilePath("/").DirectoryExists());
+#endif  // GTEST_OS_WINDOWS
+}
+
+#if GTEST_OS_WINDOWS
+TEST(DirectoryTest, RootOfWrongDriveDoesNotExists) {
+  const int saved_drive_ = _getdrive();
+  // Find a drive that doesn't exist. Start with 'Z' to avoid common ones.
+  for (char drive = 'Z'; drive >= 'A'; drive--)
+    if (_chdrive(drive - 'A' + 1) == -1) {
+      char non_drive[_MAX_PATH];  // NOLINT
+      non_drive[0] = drive;
+      non_drive[1] = ':';
+      non_drive[2] = '\\';
+      non_drive[3] = '\0';
+      EXPECT_FALSE(FilePath(non_drive).DirectoryExists());
+      break;
+    }
+  _chdrive(saved_drive_);
+}
+#endif  // GTEST_OS_WINDOWS
+
+#if !GTEST_OS_WINDOWS_MOBILE
+// Windows CE _does_ consider an empty directory to exist.
+TEST(DirectoryTest, EmptyPathDirectoryDoesNotExist) {
+  EXPECT_FALSE(FilePath("").DirectoryExists());
+}
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+TEST(DirectoryTest, CurrentDirectoryExists) {
+#if GTEST_OS_WINDOWS  // We are on Windows.
+# ifndef _WIN32_CE  // Windows CE doesn't have a current directory.
+
+  EXPECT_TRUE(FilePath(".").DirectoryExists());
+  EXPECT_TRUE(FilePath(".\\").DirectoryExists());
+
+# endif  // _WIN32_CE
+#else
+  EXPECT_TRUE(FilePath(".").DirectoryExists());
+  EXPECT_TRUE(FilePath("./").DirectoryExists());
+#endif  // GTEST_OS_WINDOWS
+}
+
+TEST(NormalizeTest, NullStringsEqualEmptyDirectory) {
+  EXPECT_STREQ("", FilePath(NULL).c_str());
+  EXPECT_STREQ("", FilePath(String(NULL)).c_str());
+}
+
+// "foo/bar" == foo//bar" == "foo///bar"
+TEST(NormalizeTest, MultipleConsecutiveSepaparatorsInMidstring) {
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_ "bar",
+               FilePath("foo" GTEST_PATH_SEP_ "bar").c_str());
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_ "bar",
+               FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar").c_str());
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_ "bar",
+               FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_
+                        GTEST_PATH_SEP_ "bar").c_str());
+}
+
+// "/bar" == //bar" == "///bar"
+TEST(NormalizeTest, MultipleConsecutiveSepaparatorsAtStringStart) {
+  EXPECT_STREQ(GTEST_PATH_SEP_ "bar",
+    FilePath(GTEST_PATH_SEP_ "bar").c_str());
+  EXPECT_STREQ(GTEST_PATH_SEP_ "bar",
+    FilePath(GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar").c_str());
+  EXPECT_STREQ(GTEST_PATH_SEP_ "bar",
+    FilePath(GTEST_PATH_SEP_ GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar").c_str());
+}
+
+// "foo/" == foo//" == "foo///"
+TEST(NormalizeTest, MultipleConsecutiveSepaparatorsAtStringEnd) {
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_,
+    FilePath("foo" GTEST_PATH_SEP_).c_str());
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_,
+    FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_).c_str());
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_,
+    FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_ GTEST_PATH_SEP_).c_str());
+}
+
+#if GTEST_HAS_ALT_PATH_SEP_
+
+// Tests that separators at the end of the string are normalized
+// regardless of their combination (e.g. "foo\" =="foo/\" ==
+// "foo\\/").
+TEST(NormalizeTest, MixAlternateSeparatorAtStringEnd) {
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_,
+               FilePath("foo/").c_str());
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_,
+               FilePath("foo" GTEST_PATH_SEP_ "/").c_str());
+  EXPECT_STREQ("foo" GTEST_PATH_SEP_,
+               FilePath("foo//" GTEST_PATH_SEP_).c_str());
+}
+
+#endif
+
+TEST(AssignmentOperatorTest, DefaultAssignedToNonDefault) {
+  FilePath default_path;
+  FilePath non_default_path("path");
+  non_default_path = default_path;
+  EXPECT_STREQ("", non_default_path.c_str());
+  EXPECT_STREQ("", default_path.c_str());  // RHS var is unchanged.
+}
+
+TEST(AssignmentOperatorTest, NonDefaultAssignedToDefault) {
+  FilePath non_default_path("path");
+  FilePath default_path;
+  default_path = non_default_path;
+  EXPECT_STREQ("path", default_path.c_str());
+  EXPECT_STREQ("path", non_default_path.c_str());  // RHS var is unchanged.
+}
+
+TEST(AssignmentOperatorTest, ConstAssignedToNonConst) {
+  const FilePath const_default_path("const_path");
+  FilePath non_default_path("path");
+  non_default_path = const_default_path;
+  EXPECT_STREQ("const_path", non_default_path.c_str());
+}
+
+class DirectoryCreationTest : public Test {
+ protected:
+  virtual void SetUp() {
+    testdata_path_.Set(FilePath(String::Format("%s%s%s",
+        TempDir().c_str(), GetCurrentExecutableName().c_str(),
+        "_directory_creation" GTEST_PATH_SEP_ "test" GTEST_PATH_SEP_)));
+    testdata_file_.Set(testdata_path_.RemoveTrailingPathSeparator());
+
+    unique_file0_.Set(FilePath::MakeFileName(testdata_path_, FilePath("unique"),
+        0, "txt"));
+    unique_file1_.Set(FilePath::MakeFileName(testdata_path_, FilePath("unique"),
+        1, "txt"));
+
+    remove(testdata_file_.c_str());
+    remove(unique_file0_.c_str());
+    remove(unique_file1_.c_str());
+    posix::RmDir(testdata_path_.c_str());
+  }
+
+  virtual void TearDown() {
+    remove(testdata_file_.c_str());
+    remove(unique_file0_.c_str());
+    remove(unique_file1_.c_str());
+    posix::RmDir(testdata_path_.c_str());
+  }
+
+  String TempDir() const {
+#if GTEST_OS_WINDOWS_MOBILE
+    return String("\\temp\\");
+#elif GTEST_OS_WINDOWS
+    const char* temp_dir = posix::GetEnv("TEMP");
+    if (temp_dir == NULL || temp_dir[0] == '\0')
+      return String("\\temp\\");
+    else if (String(temp_dir).EndsWith("\\"))
+      return String(temp_dir);
+    else
+      return String::Format("%s\\", temp_dir);
+#else
+    return String("/tmp/");
+#endif  // GTEST_OS_WINDOWS_MOBILE
+  }
+
+  void CreateTextFile(const char* filename) {
+    FILE* f = posix::FOpen(filename, "w");
+    fprintf(f, "text\n");
+    fclose(f);
+  }
+
+  // Strings representing a directory and a file, with identical paths
+  // except for the trailing separator character that distinquishes
+  // a directory named 'test' from a file named 'test'. Example names:
+  FilePath testdata_path_;  // "/tmp/directory_creation/test/"
+  FilePath testdata_file_;  // "/tmp/directory_creation/test"
+  FilePath unique_file0_;  // "/tmp/directory_creation/test/unique.txt"
+  FilePath unique_file1_;  // "/tmp/directory_creation/test/unique_1.txt"
+};
+
+TEST_F(DirectoryCreationTest, CreateDirectoriesRecursively) {
+  EXPECT_FALSE(testdata_path_.DirectoryExists()) << testdata_path_.c_str();
+  EXPECT_TRUE(testdata_path_.CreateDirectoriesRecursively());
+  EXPECT_TRUE(testdata_path_.DirectoryExists());
+}
+
+TEST_F(DirectoryCreationTest, CreateDirectoriesForAlreadyExistingPath) {
+  EXPECT_FALSE(testdata_path_.DirectoryExists()) << testdata_path_.c_str();
+  EXPECT_TRUE(testdata_path_.CreateDirectoriesRecursively());
+  // Call 'create' again... should still succeed.
+  EXPECT_TRUE(testdata_path_.CreateDirectoriesRecursively());
+}
+
+TEST_F(DirectoryCreationTest, CreateDirectoriesAndUniqueFilename) {
+  FilePath file_path(FilePath::GenerateUniqueFileName(testdata_path_,
+      FilePath("unique"), "txt"));
+  EXPECT_STREQ(unique_file0_.c_str(), file_path.c_str());
+  EXPECT_FALSE(file_path.FileOrDirectoryExists());  // file not there
+
+  testdata_path_.CreateDirectoriesRecursively();
+  EXPECT_FALSE(file_path.FileOrDirectoryExists());  // file still not there
+  CreateTextFile(file_path.c_str());
+  EXPECT_TRUE(file_path.FileOrDirectoryExists());
+
+  FilePath file_path2(FilePath::GenerateUniqueFileName(testdata_path_,
+      FilePath("unique"), "txt"));
+  EXPECT_STREQ(unique_file1_.c_str(), file_path2.c_str());
+  EXPECT_FALSE(file_path2.FileOrDirectoryExists());  // file not there
+  CreateTextFile(file_path2.c_str());
+  EXPECT_TRUE(file_path2.FileOrDirectoryExists());
+}
+
+TEST_F(DirectoryCreationTest, CreateDirectoriesFail) {
+  // force a failure by putting a file where we will try to create a directory.
+  CreateTextFile(testdata_file_.c_str());
+  EXPECT_TRUE(testdata_file_.FileOrDirectoryExists());
+  EXPECT_FALSE(testdata_file_.DirectoryExists());
+  EXPECT_FALSE(testdata_file_.CreateDirectoriesRecursively());
+}
+
+TEST(NoDirectoryCreationTest, CreateNoDirectoriesForDefaultXmlFile) {
+  const FilePath test_detail_xml("test_detail.xml");
+  EXPECT_FALSE(test_detail_xml.CreateDirectoriesRecursively());
+}
+
+TEST(FilePathTest, DefaultConstructor) {
+  FilePath fp;
+  EXPECT_STREQ("", fp.c_str());
+}
+
+TEST(FilePathTest, CharAndCopyConstructors) {
+  const FilePath fp("spicy");
+  EXPECT_STREQ("spicy", fp.c_str());
+
+  const FilePath fp_copy(fp);
+  EXPECT_STREQ("spicy", fp_copy.c_str());
+}
+
+TEST(FilePathTest, StringConstructor) {
+  const FilePath fp(String("cider"));
+  EXPECT_STREQ("cider", fp.c_str());
+}
+
+TEST(FilePathTest, Set) {
+  const FilePath apple("apple");
+  FilePath mac("mac");
+  mac.Set(apple);  // Implement Set() since overloading operator= is forbidden.
+  EXPECT_STREQ("apple", mac.c_str());
+  EXPECT_STREQ("apple", apple.c_str());
+}
+
+TEST(FilePathTest, ToString) {
+  const FilePath file("drink");
+  String str(file.ToString());
+  EXPECT_STREQ("drink", str.c_str());
+}
+
+TEST(FilePathTest, RemoveExtension) {
+  EXPECT_STREQ("app", FilePath("app.exe").RemoveExtension("exe").c_str());
+  EXPECT_STREQ("APP", FilePath("APP.EXE").RemoveExtension("exe").c_str());
+}
+
+TEST(FilePathTest, RemoveExtensionWhenThereIsNoExtension) {
+  EXPECT_STREQ("app", FilePath("app").RemoveExtension("exe").c_str());
+}
+
+TEST(FilePathTest, IsDirectory) {
+  EXPECT_FALSE(FilePath("cola").IsDirectory());
+  EXPECT_TRUE(FilePath("koala" GTEST_PATH_SEP_).IsDirectory());
+#if GTEST_HAS_ALT_PATH_SEP_
+  EXPECT_TRUE(FilePath("koala/").IsDirectory());
+#endif
+}
+
+TEST(FilePathTest, IsAbsolutePath) {
+  EXPECT_FALSE(FilePath("is" GTEST_PATH_SEP_ "relative").IsAbsolutePath());
+  EXPECT_FALSE(FilePath("").IsAbsolutePath());
+#if GTEST_OS_WINDOWS
+  EXPECT_TRUE(FilePath("c:\\" GTEST_PATH_SEP_ "is_not"
+                       GTEST_PATH_SEP_ "relative").IsAbsolutePath());
+  EXPECT_FALSE(FilePath("c:foo" GTEST_PATH_SEP_ "bar").IsAbsolutePath());
+  EXPECT_TRUE(FilePath("c:/" GTEST_PATH_SEP_ "is_not"
+                       GTEST_PATH_SEP_ "relative").IsAbsolutePath());
+#else
+  EXPECT_TRUE(FilePath(GTEST_PATH_SEP_ "is_not" GTEST_PATH_SEP_ "relative")
+              .IsAbsolutePath());
+#endif  // GTEST_OS_WINDOWS
+}
+
+TEST(FilePathTest, IsRootDirectory) {
+#if GTEST_OS_WINDOWS
+  EXPECT_TRUE(FilePath("a:\\").IsRootDirectory());
+  EXPECT_TRUE(FilePath("Z:/").IsRootDirectory());
+  EXPECT_TRUE(FilePath("e://").IsRootDirectory());
+  EXPECT_FALSE(FilePath("").IsRootDirectory());
+  EXPECT_FALSE(FilePath("b:").IsRootDirectory());
+  EXPECT_FALSE(FilePath("b:a").IsRootDirectory());
+  EXPECT_FALSE(FilePath("8:/").IsRootDirectory());
+  EXPECT_FALSE(FilePath("c|/").IsRootDirectory());
+#else
+  EXPECT_TRUE(FilePath("/").IsRootDirectory());
+  EXPECT_TRUE(FilePath("//").IsRootDirectory());
+  EXPECT_FALSE(FilePath("").IsRootDirectory());
+  EXPECT_FALSE(FilePath("\\").IsRootDirectory());
+  EXPECT_FALSE(FilePath("/x").IsRootDirectory());
+#endif
+}
+
+}  // namespace
+}  // namespace internal
+}  // namespace testing
diff --git a/third_party/googletest/src/test/gtest-linked_ptr_test.cc b/third_party/googletest/src/test/gtest-linked_ptr_test.cc
new file mode 100644 (file)
index 0000000..0d5508a
--- /dev/null
@@ -0,0 +1,155 @@
+// Copyright 2003, 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.
+//
+// Authors: Dan Egnor (egnor@google.com)
+// Ported to Windows: Vadim Berman (vadimb@google.com)
+
+#include "gtest/internal/gtest-linked_ptr.h"
+
+#include <stdlib.h>
+#include "gtest/gtest.h"
+
+namespace {
+
+using testing::Message;
+using testing::internal::linked_ptr;
+
+int num;
+Message* history = NULL;
+
+// Class which tracks allocation/deallocation
+class A {
+ public:
+  A(): mynum(num++) { *history << "A" << mynum << " ctor\n"; }
+  virtual ~A() { *history << "A" << mynum << " dtor\n"; }
+  virtual void Use() { *history << "A" << mynum << " use\n"; }
+ protected:
+  int mynum;
+};
+
+// Subclass
+class B : public A {
+ public:
+  B() { *history << "B" << mynum << " ctor\n"; }
+  ~B() { *history << "B" << mynum << " dtor\n"; }
+  virtual void Use() { *history << "B" << mynum << " use\n"; }
+};
+
+class LinkedPtrTest : public testing::Test {
+ public:
+  LinkedPtrTest() {
+    num = 0;
+    history = new Message;
+  }
+
+  virtual ~LinkedPtrTest() {
+    delete history;
+    history = NULL;
+  }
+};
+
+TEST_F(LinkedPtrTest, GeneralTest) {
+  {
+    linked_ptr<A> a0, a1, a2;
+    // Use explicit function call notation here to suppress self-assign warning.
+    a0.operator=(a0);
+    a1 = a2;
+    ASSERT_EQ(a0.get(), static_cast<A*>(NULL));
+    ASSERT_EQ(a1.get(), static_cast<A*>(NULL));
+    ASSERT_EQ(a2.get(), static_cast<A*>(NULL));
+    ASSERT_TRUE(a0 == NULL);
+    ASSERT_TRUE(a1 == NULL);
+    ASSERT_TRUE(a2 == NULL);
+
+    {
+      linked_ptr<A> a3(new A);
+      a0 = a3;
+      ASSERT_TRUE(a0 == a3);
+      ASSERT_TRUE(a0 != NULL);
+      ASSERT_TRUE(a0.get() == a3);
+      ASSERT_TRUE(a0 == a3.get());
+      linked_ptr<A> a4(a0);
+      a1 = a4;
+      linked_ptr<A> a5(new A);
+      ASSERT_TRUE(a5.get() != a3);
+      ASSERT_TRUE(a5 != a3.get());
+      a2 = a5;
+      linked_ptr<B> b0(new B);
+      linked_ptr<A> a6(b0);
+      ASSERT_TRUE(b0 == a6);
+      ASSERT_TRUE(a6 == b0);
+      ASSERT_TRUE(b0 != NULL);
+      a5 = b0;
+      a5 = b0;
+      a3->Use();
+      a4->Use();
+      a5->Use();
+      a6->Use();
+      b0->Use();
+      (*b0).Use();
+      b0.get()->Use();
+    }
+
+    a0->Use();
+    a1->Use();
+    a2->Use();
+
+    a1 = a2;
+    a2.reset(new A);
+    a0.reset();
+
+    linked_ptr<A> a7;
+  }
+
+  ASSERT_STREQ(
+    "A0 ctor\n"
+    "A1 ctor\n"
+    "A2 ctor\n"
+    "B2 ctor\n"
+    "A0 use\n"
+    "A0 use\n"
+    "B2 use\n"
+    "B2 use\n"
+    "B2 use\n"
+    "B2 use\n"
+    "B2 use\n"
+    "B2 dtor\n"
+    "A2 dtor\n"
+    "A0 use\n"
+    "A0 use\n"
+    "A1 use\n"
+    "A3 ctor\n"
+    "A0 dtor\n"
+    "A3 dtor\n"
+    "A1 dtor\n",
+    history->GetString().c_str()
+  );
+}
+
+}  // Unnamed namespace
diff --git a/third_party/googletest/src/test/gtest-listener_test.cc b/third_party/googletest/src/test/gtest-listener_test.cc
new file mode 100644 (file)
index 0000000..2aa08ef
--- /dev/null
@@ -0,0 +1,313 @@
+// Copyright 2009 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: vladl@google.com (Vlad Losev)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This file verifies Google Test event listeners receive events at the
+// right times.
+
+#include "gtest/gtest.h"
+#include <vector>
+
+using ::testing::AddGlobalTestEnvironment;
+using ::testing::Environment;
+using ::testing::InitGoogleTest;
+using ::testing::Test;
+using ::testing::TestCase;
+using ::testing::TestEventListener;
+using ::testing::TestInfo;
+using ::testing::TestPartResult;
+using ::testing::UnitTest;
+using ::testing::internal::String;
+
+// Used by tests to register their events.
+std::vector<String>* g_events = NULL;
+
+namespace testing {
+namespace internal {
+
+class EventRecordingListener : public TestEventListener {
+ public:
+  EventRecordingListener(const char* name) : name_(name) {}
+
+ protected:
+  virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {
+    g_events->push_back(GetFullMethodName("OnTestProgramStart"));
+  }
+
+  virtual void OnTestIterationStart(const UnitTest& /*unit_test*/,
+                                    int iteration) {
+    Message message;
+    message << GetFullMethodName("OnTestIterationStart")
+            << "(" << iteration << ")";
+    g_events->push_back(message.GetString());
+  }
+
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {
+    g_events->push_back(GetFullMethodName("OnEnvironmentsSetUpStart"));
+  }
+
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {
+    g_events->push_back(GetFullMethodName("OnEnvironmentsSetUpEnd"));
+  }
+
+  virtual void OnTestCaseStart(const TestCase& /*test_case*/) {
+    g_events->push_back(GetFullMethodName("OnTestCaseStart"));
+  }
+
+  virtual void OnTestStart(const TestInfo& /*test_info*/) {
+    g_events->push_back(GetFullMethodName("OnTestStart"));
+  }
+
+  virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {
+    g_events->push_back(GetFullMethodName("OnTestPartResult"));
+  }
+
+  virtual void OnTestEnd(const TestInfo& /*test_info*/) {
+    g_events->push_back(GetFullMethodName("OnTestEnd"));
+  }
+
+  virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {
+    g_events->push_back(GetFullMethodName("OnTestCaseEnd"));
+  }
+
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {
+    g_events->push_back(GetFullMethodName("OnEnvironmentsTearDownStart"));
+  }
+
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {
+    g_events->push_back(GetFullMethodName("OnEnvironmentsTearDownEnd"));
+  }
+
+  virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/,
+                                  int iteration) {
+    Message message;
+    message << GetFullMethodName("OnTestIterationEnd")
+            << "("  << iteration << ")";
+    g_events->push_back(message.GetString());
+  }
+
+  virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {
+    g_events->push_back(GetFullMethodName("OnTestProgramEnd"));
+  }
+
+ private:
+  String GetFullMethodName(const char* name) {
+    Message message;
+    message << name_ << "." << name;
+    return message.GetString();
+  }
+
+  String name_;
+};
+
+class EnvironmentInvocationCatcher : public Environment {
+ protected:
+  virtual void SetUp() {
+    g_events->push_back(String("Environment::SetUp"));
+  }
+
+  virtual void TearDown() {
+    g_events->push_back(String("Environment::TearDown"));
+  }
+};
+
+class ListenerTest : public Test {
+ protected:
+  static void SetUpTestCase() {
+    g_events->push_back(String("ListenerTest::SetUpTestCase"));
+  }
+
+  static void TearDownTestCase() {
+    g_events->push_back(String("ListenerTest::TearDownTestCase"));
+  }
+
+  virtual void SetUp() {
+    g_events->push_back(String("ListenerTest::SetUp"));
+  }
+
+  virtual void TearDown() {
+    g_events->push_back(String("ListenerTest::TearDown"));
+  }
+};
+
+TEST_F(ListenerTest, DoesFoo) {
+  // Test execution order within a test case is not guaranteed so we are not
+  // recording the test name.
+  g_events->push_back(String("ListenerTest::* Test Body"));
+  SUCCEED();  // Triggers OnTestPartResult.
+}
+
+TEST_F(ListenerTest, DoesBar) {
+  g_events->push_back(String("ListenerTest::* Test Body"));
+  SUCCEED();  // Triggers OnTestPartResult.
+}
+
+}  // namespace internal
+
+}  // namespace testing
+
+using ::testing::internal::EnvironmentInvocationCatcher;
+using ::testing::internal::EventRecordingListener;
+
+void VerifyResults(const std::vector<String>& data,
+                   const char* const* expected_data,
+                   int expected_data_size) {
+  const int actual_size = data.size();
+  // If the following assertion fails, a new entry will be appended to
+  // data.  Hence we save data.size() first.
+  EXPECT_EQ(expected_data_size, actual_size);
+
+  // Compares the common prefix.
+  const int shorter_size = expected_data_size <= actual_size ?
+      expected_data_size : actual_size;
+  int i = 0;
+  for (; i < shorter_size; ++i) {
+    ASSERT_STREQ(expected_data[i], data[i].c_str())
+        << "at position " << i;
+  }
+
+  // Prints extra elements in the actual data.
+  for (; i < actual_size; ++i) {
+    printf("  Actual event #%d: %s\n", i, data[i].c_str());
+  }
+}
+
+int main(int argc, char **argv) {
+  std::vector<String> events;
+  g_events = &events;
+  InitGoogleTest(&argc, argv);
+
+  UnitTest::GetInstance()->listeners().Append(
+      new EventRecordingListener("1st"));
+  UnitTest::GetInstance()->listeners().Append(
+      new EventRecordingListener("2nd"));
+
+  AddGlobalTestEnvironment(new EnvironmentInvocationCatcher);
+
+  GTEST_CHECK_(events.size() == 0)
+      << "AddGlobalTestEnvironment should not generate any events itself.";
+
+  ::testing::GTEST_FLAG(repeat) = 2;
+  int ret_val = RUN_ALL_TESTS();
+
+  const char* const expected_events[] = {
+    "1st.OnTestProgramStart",
+    "2nd.OnTestProgramStart",
+    "1st.OnTestIterationStart(0)",
+    "2nd.OnTestIterationStart(0)",
+    "1st.OnEnvironmentsSetUpStart",
+    "2nd.OnEnvironmentsSetUpStart",
+    "Environment::SetUp",
+    "2nd.OnEnvironmentsSetUpEnd",
+    "1st.OnEnvironmentsSetUpEnd",
+    "1st.OnTestCaseStart",
+    "2nd.OnTestCaseStart",
+    "ListenerTest::SetUpTestCase",
+    "1st.OnTestStart",
+    "2nd.OnTestStart",
+    "ListenerTest::SetUp",
+    "ListenerTest::* Test Body",
+    "1st.OnTestPartResult",
+    "2nd.OnTestPartResult",
+    "ListenerTest::TearDown",
+    "2nd.OnTestEnd",
+    "1st.OnTestEnd",
+    "1st.OnTestStart",
+    "2nd.OnTestStart",
+    "ListenerTest::SetUp",
+    "ListenerTest::* Test Body",
+    "1st.OnTestPartResult",
+    "2nd.OnTestPartResult",
+    "ListenerTest::TearDown",
+    "2nd.OnTestEnd",
+    "1st.OnTestEnd",
+    "ListenerTest::TearDownTestCase",
+    "2nd.OnTestCaseEnd",
+    "1st.OnTestCaseEnd",
+    "1st.OnEnvironmentsTearDownStart",
+    "2nd.OnEnvironmentsTearDownStart",
+    "Environment::TearDown",
+    "2nd.OnEnvironmentsTearDownEnd",
+    "1st.OnEnvironmentsTearDownEnd",
+    "2nd.OnTestIterationEnd(0)",
+    "1st.OnTestIterationEnd(0)",
+    "1st.OnTestIterationStart(1)",
+    "2nd.OnTestIterationStart(1)",
+    "1st.OnEnvironmentsSetUpStart",
+    "2nd.OnEnvironmentsSetUpStart",
+    "Environment::SetUp",
+    "2nd.OnEnvironmentsSetUpEnd",
+    "1st.OnEnvironmentsSetUpEnd",
+    "1st.OnTestCaseStart",
+    "2nd.OnTestCaseStart",
+    "ListenerTest::SetUpTestCase",
+    "1st.OnTestStart",
+    "2nd.OnTestStart",
+    "ListenerTest::SetUp",
+    "ListenerTest::* Test Body",
+    "1st.OnTestPartResult",
+    "2nd.OnTestPartResult",
+    "ListenerTest::TearDown",
+    "2nd.OnTestEnd",
+    "1st.OnTestEnd",
+    "1st.OnTestStart",
+    "2nd.OnTestStart",
+    "ListenerTest::SetUp",
+    "ListenerTest::* Test Body",
+    "1st.OnTestPartResult",
+    "2nd.OnTestPartResult",
+    "ListenerTest::TearDown",
+    "2nd.OnTestEnd",
+    "1st.OnTestEnd",
+    "ListenerTest::TearDownTestCase",
+    "2nd.OnTestCaseEnd",
+    "1st.OnTestCaseEnd",
+    "1st.OnEnvironmentsTearDownStart",
+    "2nd.OnEnvironmentsTearDownStart",
+    "Environment::TearDown",
+    "2nd.OnEnvironmentsTearDownEnd",
+    "1st.OnEnvironmentsTearDownEnd",
+    "2nd.OnTestIterationEnd(1)",
+    "1st.OnTestIterationEnd(1)",
+    "2nd.OnTestProgramEnd",
+    "1st.OnTestProgramEnd"
+  };
+  VerifyResults(events,
+                expected_events,
+                sizeof(expected_events)/sizeof(expected_events[0]));
+
+  // We need to check manually for ad hoc test failures that happen after
+  // RUN_ALL_TESTS finishes.
+  if (UnitTest::GetInstance()->Failed())
+    ret_val = 1;
+
+  return ret_val;
+}
diff --git a/third_party/googletest/src/test/gtest-message_test.cc b/third_party/googletest/src/test/gtest-message_test.cc
new file mode 100644 (file)
index 0000000..c09c6a8
--- /dev/null
@@ -0,0 +1,166 @@
+// Copyright 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: wan@google.com (Zhanyong Wan)
+//
+// Tests for the Message class.
+
+#include "gtest/gtest-message.h"
+
+#include "gtest/gtest.h"
+
+namespace {
+
+using ::testing::Message;
+
+// A helper function that turns a Message into a C string.
+const char* ToCString(const Message& msg) {
+  static testing::internal::String result;
+  result = msg.GetString();
+  return result.c_str();
+}
+
+// Tests the testing::Message class
+
+// Tests the default constructor.
+TEST(MessageTest, DefaultConstructor) {
+  const Message msg;
+  EXPECT_STREQ("", ToCString(msg));
+}
+
+// Tests the copy constructor.
+TEST(MessageTest, CopyConstructor) {
+  const Message msg1("Hello");
+  const Message msg2(msg1);
+  EXPECT_STREQ("Hello", ToCString(msg2));
+}
+
+// Tests constructing a Message from a C-string.
+TEST(MessageTest, ConstructsFromCString) {
+  Message msg("Hello");
+  EXPECT_STREQ("Hello", ToCString(msg));
+}
+
+// Tests streaming a float.
+TEST(MessageTest, StreamsFloat) {
+  const char* const s = ToCString(Message() << 1.23456F << " " << 2.34567F);
+  // Both numbers should be printed with enough precision.
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "1.234560", s);
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, " 2.345669", s);
+}
+
+// Tests streaming a double.
+TEST(MessageTest, StreamsDouble) {
+  const char* const s = ToCString(Message() << 1260570880.4555497 << " "
+                                  << 1260572265.1954534);
+  // Both numbers should be printed with enough precision.
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "1260570880.45", s);
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, " 1260572265.19", s);
+}
+
+// Tests streaming a non-char pointer.
+TEST(MessageTest, StreamsPointer) {
+  int n = 0;
+  int* p = &n;
+  EXPECT_STRNE("(null)", ToCString(Message() << p));
+}
+
+// Tests streaming a NULL non-char pointer.
+TEST(MessageTest, StreamsNullPointer) {
+  int* p = NULL;
+  EXPECT_STREQ("(null)", ToCString(Message() << p));
+}
+
+// Tests streaming a C string.
+TEST(MessageTest, StreamsCString) {
+  EXPECT_STREQ("Foo", ToCString(Message() << "Foo"));
+}
+
+// Tests streaming a NULL C string.
+TEST(MessageTest, StreamsNullCString) {
+  char* p = NULL;
+  EXPECT_STREQ("(null)", ToCString(Message() << p));
+}
+
+// Tests streaming std::string.
+TEST(MessageTest, StreamsString) {
+  const ::std::string str("Hello");
+  EXPECT_STREQ("Hello", ToCString(Message() << str));
+}
+
+// Tests that we can output strings containing embedded NULs.
+TEST(MessageTest, StreamsStringWithEmbeddedNUL) {
+  const char char_array_with_nul[] =
+      "Here's a NUL\0 and some more string";
+  const ::std::string string_with_nul(char_array_with_nul,
+                                      sizeof(char_array_with_nul) - 1);
+  EXPECT_STREQ("Here's a NUL\\0 and some more string",
+               ToCString(Message() << string_with_nul));
+}
+
+// Tests streaming a NUL char.
+TEST(MessageTest, StreamsNULChar) {
+  EXPECT_STREQ("\\0", ToCString(Message() << '\0'));
+}
+
+// Tests streaming int.
+TEST(MessageTest, StreamsInt) {
+  EXPECT_STREQ("123", ToCString(Message() << 123));
+}
+
+// Tests that basic IO manipulators (endl, ends, and flush) can be
+// streamed to Message.
+TEST(MessageTest, StreamsBasicIoManip) {
+  EXPECT_STREQ("Line 1.\nA NUL char \\0 in line 2.",
+               ToCString(Message() << "Line 1." << std::endl
+                         << "A NUL char " << std::ends << std::flush
+                         << " in line 2."));
+}
+
+// Tests Message::GetString()
+TEST(MessageTest, GetString) {
+  Message msg;
+  msg << 1 << " lamb";
+  EXPECT_STREQ("1 lamb", msg.GetString().c_str());
+}
+
+// Tests streaming a Message object to an ostream.
+TEST(MessageTest, StreamsToOStream) {
+  Message msg("Hello");
+  ::std::stringstream ss;
+  ss << msg;
+  EXPECT_STREQ("Hello", testing::internal::StringStreamToString(&ss).c_str());
+}
+
+// Tests that a Message object doesn't take up too much stack space.
+TEST(MessageTest, DoesNotTakeUpMuchStackSpace) {
+  EXPECT_LE(sizeof(Message), 16U);
+}
+
+}  // namespace
diff --git a/third_party/googletest/src/test/gtest-options_test.cc b/third_party/googletest/src/test/gtest-options_test.cc
new file mode 100644 (file)
index 0000000..9e98f3f
--- /dev/null
@@ -0,0 +1,212 @@
+// Copyright 2008, 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.
+//
+// Authors: keith.ray@gmail.com (Keith Ray)
+//
+// Google Test UnitTestOptions tests
+//
+// This file tests classes and functions used internally by
+// Google Test.  They are subject to change without notice.
+//
+// This file is #included from gtest.cc, to avoid changing build or
+// make-files on Windows and other platforms. Do not #include this file
+// anywhere else!
+
+#include "gtest/gtest.h"
+
+#if GTEST_OS_WINDOWS_MOBILE
+# include <windows.h>
+#elif GTEST_OS_WINDOWS
+# include <direct.h>
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+namespace internal {
+namespace {
+
+// Turns the given relative path into an absolute path.
+FilePath GetAbsolutePathOf(const FilePath& relative_path) {
+  return FilePath::ConcatPaths(FilePath::GetCurrentDir(), relative_path);
+}
+
+// Testing UnitTestOptions::GetOutputFormat/GetOutputFile.
+
+TEST(XmlOutputTest, GetOutputFormatDefault) {
+  GTEST_FLAG(output) = "";
+  EXPECT_STREQ("", UnitTestOptions::GetOutputFormat().c_str());
+}
+
+TEST(XmlOutputTest, GetOutputFormat) {
+  GTEST_FLAG(output) = "xml:filename";
+  EXPECT_STREQ("xml", UnitTestOptions::GetOutputFormat().c_str());
+}
+
+TEST(XmlOutputTest, GetOutputFileDefault) {
+  GTEST_FLAG(output) = "";
+  EXPECT_STREQ(GetAbsolutePathOf(FilePath("test_detail.xml")).c_str(),
+               UnitTestOptions::GetAbsolutePathToOutputFile().c_str());
+}
+
+TEST(XmlOutputTest, GetOutputFileSingleFile) {
+  GTEST_FLAG(output) = "xml:filename.abc";
+  EXPECT_STREQ(GetAbsolutePathOf(FilePath("filename.abc")).c_str(),
+               UnitTestOptions::GetAbsolutePathToOutputFile().c_str());
+}
+
+TEST(XmlOutputTest, GetOutputFileFromDirectoryPath) {
+  GTEST_FLAG(output) = "xml:path" GTEST_PATH_SEP_;
+  const std::string expected_output_file =
+      GetAbsolutePathOf(
+          FilePath(std::string("path") + GTEST_PATH_SEP_ +
+                   GetCurrentExecutableName().c_str() + ".xml")).c_str();
+  const String& output_file = UnitTestOptions::GetAbsolutePathToOutputFile();
+#if GTEST_OS_WINDOWS
+  EXPECT_STRCASEEQ(expected_output_file.c_str(), output_file.c_str());
+#else
+  EXPECT_EQ(expected_output_file, output_file.c_str());
+#endif
+}
+
+TEST(OutputFileHelpersTest, GetCurrentExecutableName) {
+  const std::string exe_str = GetCurrentExecutableName().c_str();
+#if GTEST_OS_WINDOWS
+  const bool success =
+      _strcmpi("gtest-options_test", exe_str.c_str()) == 0 ||
+      _strcmpi("gtest-options-ex_test", exe_str.c_str()) == 0 ||
+      _strcmpi("gtest_all_test", exe_str.c_str()) == 0 ||
+      _strcmpi("gtest_dll_test", exe_str.c_str()) == 0;
+#else
+  // TODO(wan@google.com): remove the hard-coded "lt-" prefix when
+  //   Chandler Carruth's libtool replacement is ready.
+  const bool success =
+      exe_str == "gtest-options_test" ||
+      exe_str == "gtest_all_test" ||
+      exe_str == "lt-gtest_all_test" ||
+      exe_str == "gtest_dll_test";
+#endif  // GTEST_OS_WINDOWS
+  if (!success)
+    FAIL() << "GetCurrentExecutableName() returns " << exe_str;
+}
+
+class XmlOutputChangeDirTest : public Test {
+ protected:
+  virtual void SetUp() {
+    original_working_dir_ = FilePath::GetCurrentDir();
+    posix::ChDir("..");
+    // This will make the test fail if run from the root directory.
+    EXPECT_STRNE(original_working_dir_.c_str(),
+                 FilePath::GetCurrentDir().c_str());
+  }
+
+  virtual void TearDown() {
+    posix::ChDir(original_working_dir_.c_str());
+  }
+
+  FilePath original_working_dir_;
+};
+
+TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithDefault) {
+  GTEST_FLAG(output) = "";
+  EXPECT_STREQ(FilePath::ConcatPaths(original_working_dir_,
+                                     FilePath("test_detail.xml")).c_str(),
+               UnitTestOptions::GetAbsolutePathToOutputFile().c_str());
+}
+
+TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithDefaultXML) {
+  GTEST_FLAG(output) = "xml";
+  EXPECT_STREQ(FilePath::ConcatPaths(original_working_dir_,
+                                     FilePath("test_detail.xml")).c_str(),
+               UnitTestOptions::GetAbsolutePathToOutputFile().c_str());
+}
+
+TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithRelativeFile) {
+  GTEST_FLAG(output) = "xml:filename.abc";
+  EXPECT_STREQ(FilePath::ConcatPaths(original_working_dir_,
+                                     FilePath("filename.abc")).c_str(),
+               UnitTestOptions::GetAbsolutePathToOutputFile().c_str());
+}
+
+TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithRelativePath) {
+  GTEST_FLAG(output) = "xml:path" GTEST_PATH_SEP_;
+  const std::string expected_output_file =
+      FilePath::ConcatPaths(
+          original_working_dir_,
+          FilePath(std::string("path") + GTEST_PATH_SEP_ +
+                   GetCurrentExecutableName().c_str() + ".xml")).c_str();
+  const String& output_file = UnitTestOptions::GetAbsolutePathToOutputFile();
+#if GTEST_OS_WINDOWS
+  EXPECT_STRCASEEQ(expected_output_file.c_str(), output_file.c_str());
+#else
+  EXPECT_EQ(expected_output_file, output_file.c_str());
+#endif
+}
+
+TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithAbsoluteFile) {
+#if GTEST_OS_WINDOWS
+  GTEST_FLAG(output) = "xml:c:\\tmp\\filename.abc";
+  EXPECT_STREQ(FilePath("c:\\tmp\\filename.abc").c_str(),
+               UnitTestOptions::GetAbsolutePathToOutputFile().c_str());
+#else
+  GTEST_FLAG(output) ="xml:/tmp/filename.abc";
+  EXPECT_STREQ(FilePath("/tmp/filename.abc").c_str(),
+               UnitTestOptions::GetAbsolutePathToOutputFile().c_str());
+#endif
+}
+
+TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithAbsolutePath) {
+#if GTEST_OS_WINDOWS
+  const std::string path = "c:\\tmp\\";
+#else
+  const std::string path = "/tmp/";
+#endif
+
+  GTEST_FLAG(output) = "xml:" + path;
+  const std::string expected_output_file =
+      path + GetCurrentExecutableName().c_str() + ".xml";
+  const String& output_file = UnitTestOptions::GetAbsolutePathToOutputFile();
+
+#if GTEST_OS_WINDOWS
+  EXPECT_STRCASEEQ(expected_output_file.c_str(), output_file.c_str());
+#else
+  EXPECT_EQ(expected_output_file, output_file.c_str());
+#endif
+}
+
+}  // namespace
+}  // namespace internal
+}  // namespace testing
diff --git a/third_party/googletest/src/test/gtest-param-test2_test.cc b/third_party/googletest/src/test/gtest-param-test2_test.cc
new file mode 100644 (file)
index 0000000..4a782fe
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright 2008, 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: vladl@google.com (Vlad Losev)
+//
+// Tests for Google Test itself.  This verifies that the basic constructs of
+// Google Test work.
+
+#include "gtest/gtest.h"
+
+#include "test/gtest-param-test_test.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+using ::testing::Values;
+using ::testing::internal::ParamGenerator;
+
+// Tests that generators defined in a different translation unit
+// are functional. The test using extern_gen is defined
+// in gtest-param-test_test.cc.
+ParamGenerator<int> extern_gen = Values(33);
+
+// Tests that a parameterized test case can be defined in one translation unit
+// and instantiated in another. The test is defined in gtest-param-test_test.cc
+// and ExternalInstantiationTest fixture class is defined in
+// gtest-param-test_test.h.
+INSTANTIATE_TEST_CASE_P(MultiplesOf33,
+                        ExternalInstantiationTest,
+                        Values(33, 66));
+
+// Tests that a parameterized test case can be instantiated
+// in multiple translation units. Another instantiation is defined
+// in gtest-param-test_test.cc and InstantiationInMultipleTranslaionUnitsTest
+// fixture is defined in gtest-param-test_test.h
+INSTANTIATE_TEST_CASE_P(Sequence2,
+                        InstantiationInMultipleTranslaionUnitsTest,
+                        Values(42*3, 42*4, 42*5));
+
+#endif  // GTEST_HAS_PARAM_TEST
diff --git a/third_party/googletest/src/test/gtest-param-test_test.cc b/third_party/googletest/src/test/gtest-param-test_test.cc
new file mode 100644 (file)
index 0000000..94a53d9
--- /dev/null
@@ -0,0 +1,895 @@
+// Copyright 2008, 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: vladl@google.com (Vlad Losev)
+//
+// Tests for Google Test itself. This file verifies that the parameter
+// generators objects produce correct parameter sequences and that
+// Google Test runtime instantiates correct tests from those sequences.
+
+#include "gtest/gtest.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+# include <algorithm>
+# include <iostream>
+# include <list>
+# include <sstream>
+# include <string>
+# include <vector>
+
+// To include gtest-internal-inl.h.
+# define GTEST_IMPLEMENTATION_ 1
+# include "src/gtest-internal-inl.h"  // for UnitTestOptions
+# undef GTEST_IMPLEMENTATION_
+
+# include "test/gtest-param-test_test.h"
+
+using ::std::vector;
+using ::std::sort;
+
+using ::testing::AddGlobalTestEnvironment;
+using ::testing::Bool;
+using ::testing::Message;
+using ::testing::Range;
+using ::testing::TestWithParam;
+using ::testing::Values;
+using ::testing::ValuesIn;
+
+# if GTEST_HAS_COMBINE
+using ::testing::Combine;
+using ::std::tr1::get;
+using ::std::tr1::make_tuple;
+using ::std::tr1::tuple;
+# endif  // GTEST_HAS_COMBINE
+
+using ::testing::internal::ParamGenerator;
+using ::testing::internal::UnitTestOptions;
+
+// Prints a value to a string.
+//
+// TODO(wan@google.com): remove PrintValue() when we move matchers and
+// EXPECT_THAT() from Google Mock to Google Test.  At that time, we
+// can write EXPECT_THAT(x, Eq(y)) to compare two tuples x and y, as
+// EXPECT_THAT() and the matchers know how to print tuples.
+template <typename T>
+::std::string PrintValue(const T& value) {
+  ::std::stringstream stream;
+  stream << value;
+  return stream.str();
+}
+
+# if GTEST_HAS_COMBINE
+
+// These overloads allow printing tuples in our tests.  We cannot
+// define an operator<< for tuples, as that definition needs to be in
+// the std namespace in order to be picked up by Google Test via
+// Argument-Dependent Lookup, yet defining anything in the std
+// namespace in non-STL code is undefined behavior.
+
+template <typename T1, typename T2>
+::std::string PrintValue(const tuple<T1, T2>& value) {
+  ::std::stringstream stream;
+  stream << "(" << get<0>(value) << ", " << get<1>(value) << ")";
+  return stream.str();
+}
+
+template <typename T1, typename T2, typename T3>
+::std::string PrintValue(const tuple<T1, T2, T3>& value) {
+  ::std::stringstream stream;
+  stream << "(" << get<0>(value) << ", " << get<1>(value)
+         << ", "<< get<2>(value) << ")";
+  return stream.str();
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7, typename T8, typename T9, typename T10>
+::std::string PrintValue(
+    const tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& value) {
+  ::std::stringstream stream;
+  stream << "(" << get<0>(value) << ", " << get<1>(value)
+         << ", "<< get<2>(value) << ", " << get<3>(value)
+         << ", "<< get<4>(value) << ", " << get<5>(value)
+         << ", "<< get<6>(value) << ", " << get<7>(value)
+         << ", "<< get<8>(value) << ", " << get<9>(value) << ")";
+  return stream.str();
+}
+
+# endif  // GTEST_HAS_COMBINE
+
+// Verifies that a sequence generated by the generator and accessed
+// via the iterator object matches the expected one using Google Test
+// assertions.
+template <typename T, size_t N>
+void VerifyGenerator(const ParamGenerator<T>& generator,
+                     const T (&expected_values)[N]) {
+  typename ParamGenerator<T>::iterator it = generator.begin();
+  for (size_t i = 0; i < N; ++i) {
+    ASSERT_FALSE(it == generator.end())
+        << "At element " << i << " when accessing via an iterator "
+        << "created with the copy constructor.\n";
+    // We cannot use EXPECT_EQ() here as the values may be tuples,
+    // which don't support <<.
+    EXPECT_TRUE(expected_values[i] == *it)
+        << "where i is " << i
+        << ", expected_values[i] is " << PrintValue(expected_values[i])
+        << ", *it is " << PrintValue(*it)
+        << ", and 'it' is an iterator created with the copy constructor.\n";
+    it++;
+  }
+  EXPECT_TRUE(it == generator.end())
+        << "At the presumed end of sequence when accessing via an iterator "
+        << "created with the copy constructor.\n";
+
+  // Test the iterator assignment. The following lines verify that
+  // the sequence accessed via an iterator initialized via the
+  // assignment operator (as opposed to a copy constructor) matches
+  // just the same.
+  it = generator.begin();
+  for (size_t i = 0; i < N; ++i) {
+    ASSERT_FALSE(it == generator.end())
+        << "At element " << i << " when accessing via an iterator "
+        << "created with the assignment operator.\n";
+    EXPECT_TRUE(expected_values[i] == *it)
+        << "where i is " << i
+        << ", expected_values[i] is " << PrintValue(expected_values[i])
+        << ", *it is " << PrintValue(*it)
+        << ", and 'it' is an iterator created with the copy constructor.\n";
+    it++;
+  }
+  EXPECT_TRUE(it == generator.end())
+        << "At the presumed end of sequence when accessing via an iterator "
+        << "created with the assignment operator.\n";
+}
+
+template <typename T>
+void VerifyGeneratorIsEmpty(const ParamGenerator<T>& generator) {
+  typename ParamGenerator<T>::iterator it = generator.begin();
+  EXPECT_TRUE(it == generator.end());
+
+  it = generator.begin();
+  EXPECT_TRUE(it == generator.end());
+}
+
+// Generator tests. They test that each of the provided generator functions
+// generates an expected sequence of values. The general test pattern
+// instantiates a generator using one of the generator functions,
+// checks the sequence produced by the generator using its iterator API,
+// and then resets the iterator back to the beginning of the sequence
+// and checks the sequence again.
+
+// Tests that iterators produced by generator functions conform to the
+// ForwardIterator concept.
+TEST(IteratorTest, ParamIteratorConformsToForwardIteratorConcept) {
+  const ParamGenerator<int> gen = Range(0, 10);
+  ParamGenerator<int>::iterator it = gen.begin();
+
+  // Verifies that iterator initialization works as expected.
+  ParamGenerator<int>::iterator it2 = it;
+  EXPECT_TRUE(*it == *it2) << "Initialized iterators must point to the "
+                           << "element same as its source points to";
+
+  // Verifies that iterator assignment works as expected.
+  it++;
+  EXPECT_FALSE(*it == *it2);
+  it2 = it;
+  EXPECT_TRUE(*it == *it2) << "Assigned iterators must point to the "
+                           << "element same as its source points to";
+
+  // Verifies that prefix operator++() returns *this.
+  EXPECT_EQ(&it, &(++it)) << "Result of the prefix operator++ must be "
+                          << "refer to the original object";
+
+  // Verifies that the result of the postfix operator++ points to the value
+  // pointed to by the original iterator.
+  int original_value = *it;  // Have to compute it outside of macro call to be
+                             // unaffected by the parameter evaluation order.
+  EXPECT_EQ(original_value, *(it++));
+
+  // Verifies that prefix and postfix operator++() advance an iterator
+  // all the same.
+  it2 = it;
+  it++;
+  ++it2;
+  EXPECT_TRUE(*it == *it2);
+}
+
+// Tests that Range() generates the expected sequence.
+TEST(RangeTest, IntRangeWithDefaultStep) {
+  const ParamGenerator<int> gen = Range(0, 3);
+  const int expected_values[] = {0, 1, 2};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Edge case. Tests that Range() generates the single element sequence
+// as expected when provided with range limits that are equal.
+TEST(RangeTest, IntRangeSingleValue) {
+  const ParamGenerator<int> gen = Range(0, 1);
+  const int expected_values[] = {0};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Edge case. Tests that Range() with generates empty sequence when
+// supplied with an empty range.
+TEST(RangeTest, IntRangeEmpty) {
+  const ParamGenerator<int> gen = Range(0, 0);
+  VerifyGeneratorIsEmpty(gen);
+}
+
+// Tests that Range() with custom step (greater then one) generates
+// the expected sequence.
+TEST(RangeTest, IntRangeWithCustomStep) {
+  const ParamGenerator<int> gen = Range(0, 9, 3);
+  const int expected_values[] = {0, 3, 6};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that Range() with custom step (greater then one) generates
+// the expected sequence when the last element does not fall on the
+// upper range limit. Sequences generated by Range() must not have
+// elements beyond the range limits.
+TEST(RangeTest, IntRangeWithCustomStepOverUpperBound) {
+  const ParamGenerator<int> gen = Range(0, 4, 3);
+  const int expected_values[] = {0, 3};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Verifies that Range works with user-defined types that define
+// copy constructor, operator=(), operator+(), and operator<().
+class DogAdder {
+ public:
+  explicit DogAdder(const char* a_value) : value_(a_value) {}
+  DogAdder(const DogAdder& other) : value_(other.value_.c_str()) {}
+
+  DogAdder operator=(const DogAdder& other) {
+    if (this != &other)
+      value_ = other.value_;
+    return *this;
+  }
+  DogAdder operator+(const DogAdder& other) const {
+    Message msg;
+    msg << value_.c_str() << other.value_.c_str();
+    return DogAdder(msg.GetString().c_str());
+  }
+  bool operator<(const DogAdder& other) const {
+    return value_ < other.value_;
+  }
+  const ::testing::internal::String& value() const { return value_; }
+
+ private:
+  ::testing::internal::String value_;
+};
+
+TEST(RangeTest, WorksWithACustomType) {
+  const ParamGenerator<DogAdder> gen =
+      Range(DogAdder("cat"), DogAdder("catdogdog"), DogAdder("dog"));
+  ParamGenerator<DogAdder>::iterator it = gen.begin();
+
+  ASSERT_FALSE(it == gen.end());
+  EXPECT_STREQ("cat", it->value().c_str());
+
+  ASSERT_FALSE(++it == gen.end());
+  EXPECT_STREQ("catdog", it->value().c_str());
+
+  EXPECT_TRUE(++it == gen.end());
+}
+
+class IntWrapper {
+ public:
+  explicit IntWrapper(int a_value) : value_(a_value) {}
+  IntWrapper(const IntWrapper& other) : value_(other.value_) {}
+
+  IntWrapper operator=(const IntWrapper& other) {
+    value_ = other.value_;
+    return *this;
+  }
+  // operator+() adds a different type.
+  IntWrapper operator+(int other) const { return IntWrapper(value_ + other); }
+  bool operator<(const IntWrapper& other) const {
+    return value_ < other.value_;
+  }
+  int value() const { return value_; }
+
+ private:
+  int value_;
+};
+
+TEST(RangeTest, WorksWithACustomTypeWithDifferentIncrementType) {
+  const ParamGenerator<IntWrapper> gen = Range(IntWrapper(0), IntWrapper(2));
+  ParamGenerator<IntWrapper>::iterator it = gen.begin();
+
+  ASSERT_FALSE(it == gen.end());
+  EXPECT_EQ(0, it->value());
+
+  ASSERT_FALSE(++it == gen.end());
+  EXPECT_EQ(1, it->value());
+
+  EXPECT_TRUE(++it == gen.end());
+}
+
+// Tests that ValuesIn() with an array parameter generates
+// the expected sequence.
+TEST(ValuesInTest, ValuesInArray) {
+  int array[] = {3, 5, 8};
+  const ParamGenerator<int> gen = ValuesIn(array);
+  VerifyGenerator(gen, array);
+}
+
+// Tests that ValuesIn() with a const array parameter generates
+// the expected sequence.
+TEST(ValuesInTest, ValuesInConstArray) {
+  const int array[] = {3, 5, 8};
+  const ParamGenerator<int> gen = ValuesIn(array);
+  VerifyGenerator(gen, array);
+}
+
+// Edge case. Tests that ValuesIn() with an array parameter containing a
+// single element generates the single element sequence.
+TEST(ValuesInTest, ValuesInSingleElementArray) {
+  int array[] = {42};
+  const ParamGenerator<int> gen = ValuesIn(array);
+  VerifyGenerator(gen, array);
+}
+
+// Tests that ValuesIn() generates the expected sequence for an STL
+// container (vector).
+TEST(ValuesInTest, ValuesInVector) {
+  typedef ::std::vector<int> ContainerType;
+  ContainerType values;
+  values.push_back(3);
+  values.push_back(5);
+  values.push_back(8);
+  const ParamGenerator<int> gen = ValuesIn(values);
+
+  const int expected_values[] = {3, 5, 8};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that ValuesIn() generates the expected sequence.
+TEST(ValuesInTest, ValuesInIteratorRange) {
+  typedef ::std::vector<int> ContainerType;
+  ContainerType values;
+  values.push_back(3);
+  values.push_back(5);
+  values.push_back(8);
+  const ParamGenerator<int> gen = ValuesIn(values.begin(), values.end());
+
+  const int expected_values[] = {3, 5, 8};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Edge case. Tests that ValuesIn() provided with an iterator range specifying a
+// single value generates a single-element sequence.
+TEST(ValuesInTest, ValuesInSingleElementIteratorRange) {
+  typedef ::std::vector<int> ContainerType;
+  ContainerType values;
+  values.push_back(42);
+  const ParamGenerator<int> gen = ValuesIn(values.begin(), values.end());
+
+  const int expected_values[] = {42};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Edge case. Tests that ValuesIn() provided with an empty iterator range
+// generates an empty sequence.
+TEST(ValuesInTest, ValuesInEmptyIteratorRange) {
+  typedef ::std::vector<int> ContainerType;
+  ContainerType values;
+  const ParamGenerator<int> gen = ValuesIn(values.begin(), values.end());
+
+  VerifyGeneratorIsEmpty(gen);
+}
+
+// Tests that the Values() generates the expected sequence.
+TEST(ValuesTest, ValuesWorks) {
+  const ParamGenerator<int> gen = Values(3, 5, 8);
+
+  const int expected_values[] = {3, 5, 8};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that Values() generates the expected sequences from elements of
+// different types convertible to ParamGenerator's parameter type.
+TEST(ValuesTest, ValuesWorksForValuesOfCompatibleTypes) {
+  const ParamGenerator<double> gen = Values(3, 5.0f, 8.0);
+
+  const double expected_values[] = {3.0, 5.0, 8.0};
+  VerifyGenerator(gen, expected_values);
+}
+
+TEST(ValuesTest, ValuesWorksForMaxLengthList) {
+  const ParamGenerator<int> gen = Values(
+      10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
+      110, 120, 130, 140, 150, 160, 170, 180, 190, 200,
+      210, 220, 230, 240, 250, 260, 270, 280, 290, 300,
+      310, 320, 330, 340, 350, 360, 370, 380, 390, 400,
+      410, 420, 430, 440, 450, 460, 470, 480, 490, 500);
+
+  const int expected_values[] = {
+      10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
+      110, 120, 130, 140, 150, 160, 170, 180, 190, 200,
+      210, 220, 230, 240, 250, 260, 270, 280, 290, 300,
+      310, 320, 330, 340, 350, 360, 370, 380, 390, 400,
+      410, 420, 430, 440, 450, 460, 470, 480, 490, 500};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Edge case test. Tests that single-parameter Values() generates the sequence
+// with the single value.
+TEST(ValuesTest, ValuesWithSingleParameter) {
+  const ParamGenerator<int> gen = Values(42);
+
+  const int expected_values[] = {42};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that Bool() generates sequence (false, true).
+TEST(BoolTest, BoolWorks) {
+  const ParamGenerator<bool> gen = Bool();
+
+  const bool expected_values[] = {false, true};
+  VerifyGenerator(gen, expected_values);
+}
+
+# if GTEST_HAS_COMBINE
+
+// Tests that Combine() with two parameters generates the expected sequence.
+TEST(CombineTest, CombineWithTwoParameters) {
+  const char* foo = "foo";
+  const char* bar = "bar";
+  const ParamGenerator<tuple<const char*, int> > gen =
+      Combine(Values(foo, bar), Values(3, 4));
+
+  tuple<const char*, int> expected_values[] = {
+    make_tuple(foo, 3), make_tuple(foo, 4),
+    make_tuple(bar, 3), make_tuple(bar, 4)};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that Combine() with three parameters generates the expected sequence.
+TEST(CombineTest, CombineWithThreeParameters) {
+  const ParamGenerator<tuple<int, int, int> > gen = Combine(Values(0, 1),
+                                                            Values(3, 4),
+                                                            Values(5, 6));
+  tuple<int, int, int> expected_values[] = {
+    make_tuple(0, 3, 5), make_tuple(0, 3, 6),
+    make_tuple(0, 4, 5), make_tuple(0, 4, 6),
+    make_tuple(1, 3, 5), make_tuple(1, 3, 6),
+    make_tuple(1, 4, 5), make_tuple(1, 4, 6)};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that the Combine() with the first parameter generating a single value
+// sequence generates a sequence with the number of elements equal to the
+// number of elements in the sequence generated by the second parameter.
+TEST(CombineTest, CombineWithFirstParameterSingleValue) {
+  const ParamGenerator<tuple<int, int> > gen = Combine(Values(42),
+                                                       Values(0, 1));
+
+  tuple<int, int> expected_values[] = {make_tuple(42, 0), make_tuple(42, 1)};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that the Combine() with the second parameter generating a single value
+// sequence generates a sequence with the number of elements equal to the
+// number of elements in the sequence generated by the first parameter.
+TEST(CombineTest, CombineWithSecondParameterSingleValue) {
+  const ParamGenerator<tuple<int, int> > gen = Combine(Values(0, 1),
+                                                       Values(42));
+
+  tuple<int, int> expected_values[] = {make_tuple(0, 42), make_tuple(1, 42)};
+  VerifyGenerator(gen, expected_values);
+}
+
+// Tests that when the first parameter produces an empty sequence,
+// Combine() produces an empty sequence, too.
+TEST(CombineTest, CombineWithFirstParameterEmptyRange) {
+  const ParamGenerator<tuple<int, int> > gen = Combine(Range(0, 0),
+                                                       Values(0, 1));
+  VerifyGeneratorIsEmpty(gen);
+}
+
+// Tests that when the second parameter produces an empty sequence,
+// Combine() produces an empty sequence, too.
+TEST(CombineTest, CombineWithSecondParameterEmptyRange) {
+  const ParamGenerator<tuple<int, int> > gen = Combine(Values(0, 1),
+                                                       Range(1, 1));
+  VerifyGeneratorIsEmpty(gen);
+}
+
+// Edge case. Tests that combine works with the maximum number
+// of parameters supported by Google Test (currently 10).
+TEST(CombineTest, CombineWithMaxNumberOfParameters) {
+  const char* foo = "foo";
+  const char* bar = "bar";
+  const ParamGenerator<tuple<const char*, int, int, int, int, int, int, int,
+                             int, int> > gen = Combine(Values(foo, bar),
+                                                       Values(1), Values(2),
+                                                       Values(3), Values(4),
+                                                       Values(5), Values(6),
+                                                       Values(7), Values(8),
+                                                       Values(9));
+
+  tuple<const char*, int, int, int, int, int, int, int, int, int>
+      expected_values[] = {make_tuple(foo, 1, 2, 3, 4, 5, 6, 7, 8, 9),
+                           make_tuple(bar, 1, 2, 3, 4, 5, 6, 7, 8, 9)};
+  VerifyGenerator(gen, expected_values);
+}
+
+# endif  // GTEST_HAS_COMBINE
+
+// Tests that an generator produces correct sequence after being
+// assigned from another generator.
+TEST(ParamGeneratorTest, AssignmentWorks) {
+  ParamGenerator<int> gen = Values(1, 2);
+  const ParamGenerator<int> gen2 = Values(3, 4);
+  gen = gen2;
+
+  const int expected_values[] = {3, 4};
+  VerifyGenerator(gen, expected_values);
+}
+
+// This test verifies that the tests are expanded and run as specified:
+// one test per element from the sequence produced by the generator
+// specified in INSTANTIATE_TEST_CASE_P. It also verifies that the test's
+// fixture constructor, SetUp(), and TearDown() have run and have been
+// supplied with the correct parameters.
+
+// The use of environment object allows detection of the case where no test
+// case functionality is run at all. In this case TestCaseTearDown will not
+// be able to detect missing tests, naturally.
+template <int kExpectedCalls>
+class TestGenerationEnvironment : public ::testing::Environment {
+ public:
+  static TestGenerationEnvironment* Instance() {
+    static TestGenerationEnvironment* instance = new TestGenerationEnvironment;
+    return instance;
+  }
+
+  void FixtureConstructorExecuted() { fixture_constructor_count_++; }
+  void SetUpExecuted() { set_up_count_++; }
+  void TearDownExecuted() { tear_down_count_++; }
+  void TestBodyExecuted() { test_body_count_++; }
+
+  virtual void TearDown() {
+    // If all MultipleTestGenerationTest tests have been de-selected
+    // by the filter flag, the following checks make no sense.
+    bool perform_check = false;
+
+    for (int i = 0; i < kExpectedCalls; ++i) {
+      Message msg;
+      msg << "TestsExpandedAndRun/" << i;
+      if (UnitTestOptions::FilterMatchesTest(
+             "TestExpansionModule/MultipleTestGenerationTest",
+              msg.GetString().c_str())) {
+        perform_check = true;
+      }
+    }
+    if (perform_check) {
+      EXPECT_EQ(kExpectedCalls, fixture_constructor_count_)
+          << "Fixture constructor of ParamTestGenerationTest test case "
+          << "has not been run as expected.";
+      EXPECT_EQ(kExpectedCalls, set_up_count_)
+          << "Fixture SetUp method of ParamTestGenerationTest test case "
+          << "has not been run as expected.";
+      EXPECT_EQ(kExpectedCalls, tear_down_count_)
+          << "Fixture TearDown method of ParamTestGenerationTest test case "
+          << "has not been run as expected.";
+      EXPECT_EQ(kExpectedCalls, test_body_count_)
+          << "Test in ParamTestGenerationTest test case "
+          << "has not been run as expected.";
+    }
+  }
+ private:
+  TestGenerationEnvironment() : fixture_constructor_count_(0), set_up_count_(0),
+                                tear_down_count_(0), test_body_count_(0) {}
+
+  int fixture_constructor_count_;
+  int set_up_count_;
+  int tear_down_count_;
+  int test_body_count_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestGenerationEnvironment);
+};
+
+const int test_generation_params[] = {36, 42, 72};
+
+class TestGenerationTest : public TestWithParam<int> {
+ public:
+  enum {
+    PARAMETER_COUNT =
+        sizeof(test_generation_params)/sizeof(test_generation_params[0])
+  };
+
+  typedef TestGenerationEnvironment<PARAMETER_COUNT> Environment;
+
+  TestGenerationTest() {
+    Environment::Instance()->FixtureConstructorExecuted();
+    current_parameter_ = GetParam();
+  }
+  virtual void SetUp() {
+    Environment::Instance()->SetUpExecuted();
+    EXPECT_EQ(current_parameter_, GetParam());
+  }
+  virtual void TearDown() {
+    Environment::Instance()->TearDownExecuted();
+    EXPECT_EQ(current_parameter_, GetParam());
+  }
+
+  static void SetUpTestCase() {
+    bool all_tests_in_test_case_selected = true;
+
+    for (int i = 0; i < PARAMETER_COUNT; ++i) {
+      Message test_name;
+      test_name << "TestsExpandedAndRun/" << i;
+      if ( !UnitTestOptions::FilterMatchesTest(
+                "TestExpansionModule/MultipleTestGenerationTest",
+                test_name.GetString())) {
+        all_tests_in_test_case_selected = false;
+      }
+    }
+    EXPECT_TRUE(all_tests_in_test_case_selected)
+        << "When running the TestGenerationTest test case all of its tests\n"
+        << "must be selected by the filter flag for the test case to pass.\n"
+        << "If not all of them are enabled, we can't reliably conclude\n"
+        << "that the correct number of tests have been generated.";
+
+    collected_parameters_.clear();
+  }
+
+  static void TearDownTestCase() {
+    vector<int> expected_values(test_generation_params,
+                                test_generation_params + PARAMETER_COUNT);
+    // Test execution order is not guaranteed by Google Test,
+    // so the order of values in collected_parameters_ can be
+    // different and we have to sort to compare.
+    sort(expected_values.begin(), expected_values.end());
+    sort(collected_parameters_.begin(), collected_parameters_.end());
+
+    EXPECT_TRUE(collected_parameters_ == expected_values);
+  }
+ protected:
+  int current_parameter_;
+  static vector<int> collected_parameters_;
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestGenerationTest);
+};
+vector<int> TestGenerationTest::collected_parameters_;
+
+TEST_P(TestGenerationTest, TestsExpandedAndRun) {
+  Environment::Instance()->TestBodyExecuted();
+  EXPECT_EQ(current_parameter_, GetParam());
+  collected_parameters_.push_back(GetParam());
+}
+INSTANTIATE_TEST_CASE_P(TestExpansionModule, TestGenerationTest,
+                        ValuesIn(test_generation_params));
+
+// This test verifies that the element sequence (third parameter of
+// INSTANTIATE_TEST_CASE_P) is evaluated in InitGoogleTest() and neither at
+// the call site of INSTANTIATE_TEST_CASE_P nor in RUN_ALL_TESTS().  For
+// that, we declare param_value_ to be a static member of
+// GeneratorEvaluationTest and initialize it to 0.  We set it to 1 in
+// main(), just before invocation of InitGoogleTest().  After calling
+// InitGoogleTest(), we set the value to 2.  If the sequence is evaluated
+// before or after InitGoogleTest, INSTANTIATE_TEST_CASE_P will create a
+// test with parameter other than 1, and the test body will fail the
+// assertion.
+class GeneratorEvaluationTest : public TestWithParam<int> {
+ public:
+  static int param_value() { return param_value_; }
+  static void set_param_value(int param_value) { param_value_ = param_value; }
+
+ private:
+  static int param_value_;
+};
+int GeneratorEvaluationTest::param_value_ = 0;
+
+TEST_P(GeneratorEvaluationTest, GeneratorsEvaluatedInMain) {
+  EXPECT_EQ(1, GetParam());
+}
+INSTANTIATE_TEST_CASE_P(GenEvalModule,
+                        GeneratorEvaluationTest,
+                        Values(GeneratorEvaluationTest::param_value()));
+
+// Tests that generators defined in a different translation unit are
+// functional. Generator extern_gen is defined in gtest-param-test_test2.cc.
+extern ParamGenerator<int> extern_gen;
+class ExternalGeneratorTest : public TestWithParam<int> {};
+TEST_P(ExternalGeneratorTest, ExternalGenerator) {
+  // Sequence produced by extern_gen contains only a single value
+  // which we verify here.
+  EXPECT_EQ(GetParam(), 33);
+}
+INSTANTIATE_TEST_CASE_P(ExternalGeneratorModule,
+                        ExternalGeneratorTest,
+                        extern_gen);
+
+// Tests that a parameterized test case can be defined in one translation
+// unit and instantiated in another. This test will be instantiated in
+// gtest-param-test_test2.cc. ExternalInstantiationTest fixture class is
+// defined in gtest-param-test_test.h.
+TEST_P(ExternalInstantiationTest, IsMultipleOf33) {
+  EXPECT_EQ(0, GetParam() % 33);
+}
+
+// Tests that a parameterized test case can be instantiated with multiple
+// generators.
+class MultipleInstantiationTest : public TestWithParam<int> {};
+TEST_P(MultipleInstantiationTest, AllowsMultipleInstances) {
+}
+INSTANTIATE_TEST_CASE_P(Sequence1, MultipleInstantiationTest, Values(1, 2));
+INSTANTIATE_TEST_CASE_P(Sequence2, MultipleInstantiationTest, Range(3, 5));
+
+// Tests that a parameterized test case can be instantiated
+// in multiple translation units. This test will be instantiated
+// here and in gtest-param-test_test2.cc.
+// InstantiationInMultipleTranslationUnitsTest fixture class
+// is defined in gtest-param-test_test.h.
+TEST_P(InstantiationInMultipleTranslaionUnitsTest, IsMultipleOf42) {
+  EXPECT_EQ(0, GetParam() % 42);
+}
+INSTANTIATE_TEST_CASE_P(Sequence1,
+                        InstantiationInMultipleTranslaionUnitsTest,
+                        Values(42, 42*2));
+
+// Tests that each iteration of parameterized test runs in a separate test
+// object.
+class SeparateInstanceTest : public TestWithParam<int> {
+ public:
+  SeparateInstanceTest() : count_(0) {}
+
+  static void TearDownTestCase() {
+    EXPECT_GE(global_count_, 2)
+        << "If some (but not all) SeparateInstanceTest tests have been "
+        << "filtered out this test will fail. Make sure that all "
+        << "GeneratorEvaluationTest are selected or de-selected together "
+        << "by the test filter.";
+  }
+
+ protected:
+  int count_;
+  static int global_count_;
+};
+int SeparateInstanceTest::global_count_ = 0;
+
+TEST_P(SeparateInstanceTest, TestsRunInSeparateInstances) {
+  EXPECT_EQ(0, count_++);
+  global_count_++;
+}
+INSTANTIATE_TEST_CASE_P(FourElemSequence, SeparateInstanceTest, Range(1, 4));
+
+// Tests that all instantiations of a test have named appropriately. Test
+// defined with TEST_P(TestCaseName, TestName) and instantiated with
+// INSTANTIATE_TEST_CASE_P(SequenceName, TestCaseName, generator) must be named
+// SequenceName/TestCaseName.TestName/i, where i is the 0-based index of the
+// sequence element used to instantiate the test.
+class NamingTest : public TestWithParam<int> {};
+
+TEST_P(NamingTest, TestsReportCorrectNamesAndParameters) {
+  const ::testing::TestInfo* const test_info =
+     ::testing::UnitTest::GetInstance()->current_test_info();
+
+  EXPECT_STREQ("ZeroToFiveSequence/NamingTest", test_info->test_case_name());
+
+  Message index_stream;
+  index_stream << "TestsReportCorrectNamesAndParameters/" << GetParam();
+  EXPECT_STREQ(index_stream.GetString().c_str(), test_info->name());
+
+  EXPECT_EQ(::testing::PrintToString(GetParam()), test_info->value_param());
+}
+
+INSTANTIATE_TEST_CASE_P(ZeroToFiveSequence, NamingTest, Range(0, 5));
+
+// Class that cannot be streamed into an ostream.  It needs to be copyable
+// (and, in case of MSVC, also assignable) in order to be a test parameter
+// type.  Its default copy constructor and assignment operator do exactly
+// what we need.
+class Unstreamable {
+ public:
+  explicit Unstreamable(int value) : value_(value) {}
+
+ private:
+  int value_;
+};
+
+class CommentTest : public TestWithParam<Unstreamable> {};
+
+TEST_P(CommentTest, TestsCorrectlyReportUnstreamableParams) {
+  const ::testing::TestInfo* const test_info =
+     ::testing::UnitTest::GetInstance()->current_test_info();
+
+  EXPECT_EQ(::testing::PrintToString(GetParam()), test_info->value_param());
+}
+
+INSTANTIATE_TEST_CASE_P(InstantiationWithComments,
+                        CommentTest,
+                        Values(Unstreamable(1)));
+
+// Verify that we can create a hierarchy of test fixtures, where the base
+// class fixture is not parameterized and the derived class is. In this case
+// ParameterizedDerivedTest inherits from NonParameterizedBaseTest.  We
+// perform simple tests on both.
+class NonParameterizedBaseTest : public ::testing::Test {
+ public:
+  NonParameterizedBaseTest() : n_(17) { }
+ protected:
+  int n_;
+};
+
+class ParameterizedDerivedTest : public NonParameterizedBaseTest,
+                                 public ::testing::WithParamInterface<int> {
+ protected:
+  ParameterizedDerivedTest() : count_(0) { }
+  int count_;
+  static int global_count_;
+};
+
+int ParameterizedDerivedTest::global_count_ = 0;
+
+TEST_F(NonParameterizedBaseTest, FixtureIsInitialized) {
+  EXPECT_EQ(17, n_);
+}
+
+TEST_P(ParameterizedDerivedTest, SeesSequence) {
+  EXPECT_EQ(17, n_);
+  EXPECT_EQ(0, count_++);
+  EXPECT_EQ(GetParam(), global_count_++);
+}
+
+INSTANTIATE_TEST_CASE_P(RangeZeroToFive, ParameterizedDerivedTest, Range(0, 5));
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+TEST(CompileTest, CombineIsDefinedOnlyWhenGtestHasParamTestIsDefined) {
+#if GTEST_HAS_COMBINE && !GTEST_HAS_PARAM_TEST
+  FAIL() << "GTEST_HAS_COMBINE is defined while GTEST_HAS_PARAM_TEST is not\n"
+#endif
+}
+
+int main(int argc, char **argv) {
+#if GTEST_HAS_PARAM_TEST
+  // Used in TestGenerationTest test case.
+  AddGlobalTestEnvironment(TestGenerationTest::Environment::Instance());
+  // Used in GeneratorEvaluationTest test case. Tests that the updated value
+  // will be picked up for instantiating tests in GeneratorEvaluationTest.
+  GeneratorEvaluationTest::set_param_value(1);
+#endif  // GTEST_HAS_PARAM_TEST
+
+  ::testing::InitGoogleTest(&argc, argv);
+
+#if GTEST_HAS_PARAM_TEST
+  // Used in GeneratorEvaluationTest test case. Tests that value updated
+  // here will NOT be used for instantiating tests in
+  // GeneratorEvaluationTest.
+  GeneratorEvaluationTest::set_param_value(2);
+#endif  // GTEST_HAS_PARAM_TEST
+
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/src/test/gtest-param-test_test.h b/third_party/googletest/src/test/gtest-param-test_test.h
new file mode 100644 (file)
index 0000000..d0f6556
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright 2008, 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.
+//
+// Authors: vladl@google.com (Vlad Losev)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file provides classes and functions used internally
+// for testing Google Test itself.
+
+#ifndef GTEST_TEST_GTEST_PARAM_TEST_TEST_H_
+#define GTEST_TEST_GTEST_PARAM_TEST_TEST_H_
+
+#include "gtest/gtest.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+// Test fixture for testing definition and instantiation of a test
+// in separate translation units.
+class ExternalInstantiationTest : public ::testing::TestWithParam<int> {};
+
+// Test fixture for testing instantiation of a test in multiple
+// translation units.
+class InstantiationInMultipleTranslaionUnitsTest
+    : public ::testing::TestWithParam<int> {};
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_TEST_GTEST_PARAM_TEST_TEST_H_
diff --git a/third_party/googletest/src/test/gtest-port_test.cc b/third_party/googletest/src/test/gtest-port_test.cc
new file mode 100644 (file)
index 0000000..1c6e2b0
--- /dev/null
@@ -0,0 +1,1206 @@
+// Copyright 2008, 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.
+//
+// Authors: vladl@google.com (Vlad Losev), wan@google.com (Zhanyong Wan)
+//
+// This file tests the internal cross-platform support utilities.
+
+#include "gtest/internal/gtest-port.h"
+
+#include <stdio.h>
+
+#if GTEST_OS_MAC
+# include <time.h>
+#endif  // GTEST_OS_MAC
+
+#include <list>
+#include <utility>  // For std::pair and std::make_pair.
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+using std::make_pair;
+using std::pair;
+
+namespace testing {
+namespace internal {
+
+class Base {
+ public:
+  // Copy constructor and assignment operator do exactly what we need, so we
+  // use them.
+  Base() : member_(0) {}
+  explicit Base(int n) : member_(n) {}
+  virtual ~Base() {}
+  int member() { return member_; }
+
+ private:
+  int member_;
+};
+
+class Derived : public Base {
+ public:
+  explicit Derived(int n) : Base(n) {}
+};
+
+TEST(ImplicitCastTest, ConvertsPointers) {
+  Derived derived(0);
+  EXPECT_TRUE(&derived == ::testing::internal::ImplicitCast_<Base*>(&derived));
+}
+
+TEST(ImplicitCastTest, CanUseInheritance) {
+  Derived derived(1);
+  Base base = ::testing::internal::ImplicitCast_<Base>(derived);
+  EXPECT_EQ(derived.member(), base.member());
+}
+
+class Castable {
+ public:
+  Castable(bool* converted) : converted_(converted) {}
+  operator Base() {
+    *converted_ = true;
+    return Base();
+  }
+
+ private:
+  bool* converted_;
+};
+
+TEST(ImplicitCastTest, CanUseNonConstCastOperator) {
+  bool converted = false;
+  Castable castable(&converted);
+  Base base = ::testing::internal::ImplicitCast_<Base>(castable);
+  EXPECT_TRUE(converted);
+}
+
+class ConstCastable {
+ public:
+  ConstCastable(bool* converted) : converted_(converted) {}
+  operator Base() const {
+    *converted_ = true;
+    return Base();
+  }
+
+ private:
+  bool* converted_;
+};
+
+TEST(ImplicitCastTest, CanUseConstCastOperatorOnConstValues) {
+  bool converted = false;
+  const ConstCastable const_castable(&converted);
+  Base base = ::testing::internal::ImplicitCast_<Base>(const_castable);
+  EXPECT_TRUE(converted);
+}
+
+class ConstAndNonConstCastable {
+ public:
+  ConstAndNonConstCastable(bool* converted, bool* const_converted)
+      : converted_(converted), const_converted_(const_converted) {}
+  operator Base() {
+    *converted_ = true;
+    return Base();
+  }
+  operator Base() const {
+    *const_converted_ = true;
+    return Base();
+  }
+
+ private:
+  bool* converted_;
+  bool* const_converted_;
+};
+
+TEST(ImplicitCastTest, CanSelectBetweenConstAndNonConstCasrAppropriately) {
+  bool converted = false;
+  bool const_converted = false;
+  ConstAndNonConstCastable castable(&converted, &const_converted);
+  Base base = ::testing::internal::ImplicitCast_<Base>(castable);
+  EXPECT_TRUE(converted);
+  EXPECT_FALSE(const_converted);
+
+  converted = false;
+  const_converted = false;
+  const ConstAndNonConstCastable const_castable(&converted, &const_converted);
+  base = ::testing::internal::ImplicitCast_<Base>(const_castable);
+  EXPECT_FALSE(converted);
+  EXPECT_TRUE(const_converted);
+}
+
+class To {
+ public:
+  To(bool* converted) { *converted = true; }  // NOLINT
+};
+
+TEST(ImplicitCastTest, CanUseImplicitConstructor) {
+  bool converted = false;
+  To to = ::testing::internal::ImplicitCast_<To>(&converted);
+  (void)to;
+  EXPECT_TRUE(converted);
+}
+
+TEST(IteratorTraitsTest, WorksForSTLContainerIterators) {
+  StaticAssertTypeEq<int,
+      IteratorTraits< ::std::vector<int>::const_iterator>::value_type>();
+  StaticAssertTypeEq<bool,
+      IteratorTraits< ::std::list<bool>::iterator>::value_type>();
+}
+
+TEST(IteratorTraitsTest, WorksForPointerToNonConst) {
+  StaticAssertTypeEq<char, IteratorTraits<char*>::value_type>();
+  StaticAssertTypeEq<const void*, IteratorTraits<const void**>::value_type>();
+}
+
+TEST(IteratorTraitsTest, WorksForPointerToConst) {
+  StaticAssertTypeEq<char, IteratorTraits<const char*>::value_type>();
+  StaticAssertTypeEq<const void*,
+      IteratorTraits<const void* const*>::value_type>();
+}
+
+// Tests that the element_type typedef is available in scoped_ptr and refers
+// to the parameter type.
+TEST(ScopedPtrTest, DefinesElementType) {
+  StaticAssertTypeEq<int, ::testing::internal::scoped_ptr<int>::element_type>();
+}
+
+// TODO(vladl@google.com): Implement THE REST of scoped_ptr tests.
+
+TEST(GtestCheckSyntaxTest, BehavesLikeASingleStatement) {
+  if (AlwaysFalse())
+    GTEST_CHECK_(false) << "This should never be executed; "
+                           "It's a compilation test only.";
+
+  if (AlwaysTrue())
+    GTEST_CHECK_(true);
+  else
+    ;  // NOLINT
+
+  if (AlwaysFalse())
+    ;  // NOLINT
+  else
+    GTEST_CHECK_(true) << "";
+}
+
+TEST(GtestCheckSyntaxTest, WorksWithSwitch) {
+  switch (0) {
+    case 1:
+      break;
+    default:
+      GTEST_CHECK_(true);
+  }
+
+  switch(0)
+    case 0:
+      GTEST_CHECK_(true) << "Check failed in switch case";
+}
+
+// Verifies behavior of FormatFileLocation.
+TEST(FormatFileLocationTest, FormatsFileLocation) {
+  EXPECT_PRED_FORMAT2(IsSubstring, "foo.cc", FormatFileLocation("foo.cc", 42));
+  EXPECT_PRED_FORMAT2(IsSubstring, "42", FormatFileLocation("foo.cc", 42));
+}
+
+TEST(FormatFileLocationTest, FormatsUnknownFile) {
+  EXPECT_PRED_FORMAT2(
+      IsSubstring, "unknown file", FormatFileLocation(NULL, 42));
+  EXPECT_PRED_FORMAT2(IsSubstring, "42", FormatFileLocation(NULL, 42));
+}
+
+TEST(FormatFileLocationTest, FormatsUknownLine) {
+  EXPECT_EQ("foo.cc:", FormatFileLocation("foo.cc", -1));
+}
+
+TEST(FormatFileLocationTest, FormatsUknownFileAndLine) {
+  EXPECT_EQ("unknown file:", FormatFileLocation(NULL, -1));
+}
+
+// Verifies behavior of FormatCompilerIndependentFileLocation.
+TEST(FormatCompilerIndependentFileLocationTest, FormatsFileLocation) {
+  EXPECT_EQ("foo.cc:42", FormatCompilerIndependentFileLocation("foo.cc", 42));
+}
+
+TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFile) {
+  EXPECT_EQ("unknown file:42",
+            FormatCompilerIndependentFileLocation(NULL, 42));
+}
+
+TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownLine) {
+  EXPECT_EQ("foo.cc", FormatCompilerIndependentFileLocation("foo.cc", -1));
+}
+
+TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFileAndLine) {
+  EXPECT_EQ("unknown file", FormatCompilerIndependentFileLocation(NULL, -1));
+}
+
+#if GTEST_OS_MAC
+void* ThreadFunc(void* data) {
+  pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data);
+  pthread_mutex_lock(mutex);
+  pthread_mutex_unlock(mutex);
+  return NULL;
+}
+
+TEST(GetThreadCountTest, ReturnsCorrectValue) {
+  EXPECT_EQ(1U, GetThreadCount());
+  pthread_mutex_t mutex;
+  pthread_attr_t  attr;
+  pthread_t       thread_id;
+
+  // TODO(vladl@google.com): turn mutex into internal::Mutex for automatic
+  // destruction.
+  pthread_mutex_init(&mutex, NULL);
+  pthread_mutex_lock(&mutex);
+  ASSERT_EQ(0, pthread_attr_init(&attr));
+  ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
+
+  const int status = pthread_create(&thread_id, &attr, &ThreadFunc, &mutex);
+  ASSERT_EQ(0, pthread_attr_destroy(&attr));
+  ASSERT_EQ(0, status);
+  EXPECT_EQ(2U, GetThreadCount());
+  pthread_mutex_unlock(&mutex);
+
+  void* dummy;
+  ASSERT_EQ(0, pthread_join(thread_id, &dummy));
+
+  // MacOS X may not immediately report the updated thread count after
+  // joining a thread, causing flakiness in this test. To counter that, we
+  // wait for up to .5 seconds for the OS to report the correct value.
+  for (int i = 0; i < 5; ++i) {
+    if (GetThreadCount() == 1)
+      break;
+
+    SleepMilliseconds(100);
+  }
+  EXPECT_EQ(1U, GetThreadCount());
+  pthread_mutex_destroy(&mutex);
+}
+#else
+TEST(GetThreadCountTest, ReturnsZeroWhenUnableToCountThreads) {
+  EXPECT_EQ(0U, GetThreadCount());
+}
+#endif  // GTEST_OS_MAC
+
+TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) {
+  const bool a_false_condition = false;
+  const char regex[] =
+#ifdef _MSC_VER
+     "gtest-port_test\\.cc\\(\\d+\\):"
+#elif GTEST_USES_POSIX_RE
+     "gtest-port_test\\.cc:[0-9]+"
+#else
+     "gtest-port_test\\.cc:\\d+"
+#endif  // _MSC_VER
+     ".*a_false_condition.*Extra info.*";
+
+  EXPECT_DEATH_IF_SUPPORTED(GTEST_CHECK_(a_false_condition) << "Extra info",
+                            regex);
+}
+
+#if GTEST_HAS_DEATH_TEST
+
+TEST(GtestCheckDeathTest, LivesSilentlyOnSuccess) {
+  EXPECT_EXIT({
+      GTEST_CHECK_(true) << "Extra info";
+      ::std::cerr << "Success\n";
+      exit(0); },
+      ::testing::ExitedWithCode(0), "Success");
+}
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Verifies that Google Test choose regular expression engine appropriate to
+// the platform. The test will produce compiler errors in case of failure.
+// For simplicity, we only cover the most important platforms here.
+TEST(RegexEngineSelectionTest, SelectsCorrectRegexEngine) {
+#if GTEST_HAS_POSIX_RE
+
+  EXPECT_TRUE(GTEST_USES_POSIX_RE);
+
+#else
+
+  EXPECT_TRUE(GTEST_USES_SIMPLE_RE);
+
+#endif
+}
+
+#if GTEST_USES_POSIX_RE
+
+# if GTEST_HAS_TYPED_TEST
+
+template <typename Str>
+class RETest : public ::testing::Test {};
+
+// Defines StringTypes as the list of all string types that class RE
+// supports.
+typedef testing::Types<
+    ::std::string,
+#  if GTEST_HAS_GLOBAL_STRING
+    ::string,
+#  endif  // GTEST_HAS_GLOBAL_STRING
+    const char*> StringTypes;
+
+TYPED_TEST_CASE(RETest, StringTypes);
+
+// Tests RE's implicit constructors.
+TYPED_TEST(RETest, ImplicitConstructorWorks) {
+  const RE empty(TypeParam(""));
+  EXPECT_STREQ("", empty.pattern());
+
+  const RE simple(TypeParam("hello"));
+  EXPECT_STREQ("hello", simple.pattern());
+
+  const RE normal(TypeParam(".*(\\w+)"));
+  EXPECT_STREQ(".*(\\w+)", normal.pattern());
+}
+
+// Tests that RE's constructors reject invalid regular expressions.
+TYPED_TEST(RETest, RejectsInvalidRegex) {
+  EXPECT_NONFATAL_FAILURE({
+    const RE invalid(TypeParam("?"));
+  }, "\"?\" is not a valid POSIX Extended regular expression.");
+}
+
+// Tests RE::FullMatch().
+TYPED_TEST(RETest, FullMatchWorks) {
+  const RE empty(TypeParam(""));
+  EXPECT_TRUE(RE::FullMatch(TypeParam(""), empty));
+  EXPECT_FALSE(RE::FullMatch(TypeParam("a"), empty));
+
+  const RE re(TypeParam("a.*z"));
+  EXPECT_TRUE(RE::FullMatch(TypeParam("az"), re));
+  EXPECT_TRUE(RE::FullMatch(TypeParam("axyz"), re));
+  EXPECT_FALSE(RE::FullMatch(TypeParam("baz"), re));
+  EXPECT_FALSE(RE::FullMatch(TypeParam("azy"), re));
+}
+
+// Tests RE::PartialMatch().
+TYPED_TEST(RETest, PartialMatchWorks) {
+  const RE empty(TypeParam(""));
+  EXPECT_TRUE(RE::PartialMatch(TypeParam(""), empty));
+  EXPECT_TRUE(RE::PartialMatch(TypeParam("a"), empty));
+
+  const RE re(TypeParam("a.*z"));
+  EXPECT_TRUE(RE::PartialMatch(TypeParam("az"), re));
+  EXPECT_TRUE(RE::PartialMatch(TypeParam("axyz"), re));
+  EXPECT_TRUE(RE::PartialMatch(TypeParam("baz"), re));
+  EXPECT_TRUE(RE::PartialMatch(TypeParam("azy"), re));
+  EXPECT_FALSE(RE::PartialMatch(TypeParam("zza"), re));
+}
+
+# endif  // GTEST_HAS_TYPED_TEST
+
+#elif GTEST_USES_SIMPLE_RE
+
+TEST(IsInSetTest, NulCharIsNotInAnySet) {
+  EXPECT_FALSE(IsInSet('\0', ""));
+  EXPECT_FALSE(IsInSet('\0', "\0"));
+  EXPECT_FALSE(IsInSet('\0', "a"));
+}
+
+TEST(IsInSetTest, WorksForNonNulChars) {
+  EXPECT_FALSE(IsInSet('a', "Ab"));
+  EXPECT_FALSE(IsInSet('c', ""));
+
+  EXPECT_TRUE(IsInSet('b', "bcd"));
+  EXPECT_TRUE(IsInSet('b', "ab"));
+}
+
+TEST(IsAsciiDigitTest, IsFalseForNonDigit) {
+  EXPECT_FALSE(IsAsciiDigit('\0'));
+  EXPECT_FALSE(IsAsciiDigit(' '));
+  EXPECT_FALSE(IsAsciiDigit('+'));
+  EXPECT_FALSE(IsAsciiDigit('-'));
+  EXPECT_FALSE(IsAsciiDigit('.'));
+  EXPECT_FALSE(IsAsciiDigit('a'));
+}
+
+TEST(IsAsciiDigitTest, IsTrueForDigit) {
+  EXPECT_TRUE(IsAsciiDigit('0'));
+  EXPECT_TRUE(IsAsciiDigit('1'));
+  EXPECT_TRUE(IsAsciiDigit('5'));
+  EXPECT_TRUE(IsAsciiDigit('9'));
+}
+
+TEST(IsAsciiPunctTest, IsFalseForNonPunct) {
+  EXPECT_FALSE(IsAsciiPunct('\0'));
+  EXPECT_FALSE(IsAsciiPunct(' '));
+  EXPECT_FALSE(IsAsciiPunct('\n'));
+  EXPECT_FALSE(IsAsciiPunct('a'));
+  EXPECT_FALSE(IsAsciiPunct('0'));
+}
+
+TEST(IsAsciiPunctTest, IsTrueForPunct) {
+  for (const char* p = "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~"; *p; p++) {
+    EXPECT_PRED1(IsAsciiPunct, *p);
+  }
+}
+
+TEST(IsRepeatTest, IsFalseForNonRepeatChar) {
+  EXPECT_FALSE(IsRepeat('\0'));
+  EXPECT_FALSE(IsRepeat(' '));
+  EXPECT_FALSE(IsRepeat('a'));
+  EXPECT_FALSE(IsRepeat('1'));
+  EXPECT_FALSE(IsRepeat('-'));
+}
+
+TEST(IsRepeatTest, IsTrueForRepeatChar) {
+  EXPECT_TRUE(IsRepeat('?'));
+  EXPECT_TRUE(IsRepeat('*'));
+  EXPECT_TRUE(IsRepeat('+'));
+}
+
+TEST(IsAsciiWhiteSpaceTest, IsFalseForNonWhiteSpace) {
+  EXPECT_FALSE(IsAsciiWhiteSpace('\0'));
+  EXPECT_FALSE(IsAsciiWhiteSpace('a'));
+  EXPECT_FALSE(IsAsciiWhiteSpace('1'));
+  EXPECT_FALSE(IsAsciiWhiteSpace('+'));
+  EXPECT_FALSE(IsAsciiWhiteSpace('_'));
+}
+
+TEST(IsAsciiWhiteSpaceTest, IsTrueForWhiteSpace) {
+  EXPECT_TRUE(IsAsciiWhiteSpace(' '));
+  EXPECT_TRUE(IsAsciiWhiteSpace('\n'));
+  EXPECT_TRUE(IsAsciiWhiteSpace('\r'));
+  EXPECT_TRUE(IsAsciiWhiteSpace('\t'));
+  EXPECT_TRUE(IsAsciiWhiteSpace('\v'));
+  EXPECT_TRUE(IsAsciiWhiteSpace('\f'));
+}
+
+TEST(IsAsciiWordCharTest, IsFalseForNonWordChar) {
+  EXPECT_FALSE(IsAsciiWordChar('\0'));
+  EXPECT_FALSE(IsAsciiWordChar('+'));
+  EXPECT_FALSE(IsAsciiWordChar('.'));
+  EXPECT_FALSE(IsAsciiWordChar(' '));
+  EXPECT_FALSE(IsAsciiWordChar('\n'));
+}
+
+TEST(IsAsciiWordCharTest, IsTrueForLetter) {
+  EXPECT_TRUE(IsAsciiWordChar('a'));
+  EXPECT_TRUE(IsAsciiWordChar('b'));
+  EXPECT_TRUE(IsAsciiWordChar('A'));
+  EXPECT_TRUE(IsAsciiWordChar('Z'));
+}
+
+TEST(IsAsciiWordCharTest, IsTrueForDigit) {
+  EXPECT_TRUE(IsAsciiWordChar('0'));
+  EXPECT_TRUE(IsAsciiWordChar('1'));
+  EXPECT_TRUE(IsAsciiWordChar('7'));
+  EXPECT_TRUE(IsAsciiWordChar('9'));
+}
+
+TEST(IsAsciiWordCharTest, IsTrueForUnderscore) {
+  EXPECT_TRUE(IsAsciiWordChar('_'));
+}
+
+TEST(IsValidEscapeTest, IsFalseForNonPrintable) {
+  EXPECT_FALSE(IsValidEscape('\0'));
+  EXPECT_FALSE(IsValidEscape('\007'));
+}
+
+TEST(IsValidEscapeTest, IsFalseForDigit) {
+  EXPECT_FALSE(IsValidEscape('0'));
+  EXPECT_FALSE(IsValidEscape('9'));
+}
+
+TEST(IsValidEscapeTest, IsFalseForWhiteSpace) {
+  EXPECT_FALSE(IsValidEscape(' '));
+  EXPECT_FALSE(IsValidEscape('\n'));
+}
+
+TEST(IsValidEscapeTest, IsFalseForSomeLetter) {
+  EXPECT_FALSE(IsValidEscape('a'));
+  EXPECT_FALSE(IsValidEscape('Z'));
+}
+
+TEST(IsValidEscapeTest, IsTrueForPunct) {
+  EXPECT_TRUE(IsValidEscape('.'));
+  EXPECT_TRUE(IsValidEscape('-'));
+  EXPECT_TRUE(IsValidEscape('^'));
+  EXPECT_TRUE(IsValidEscape('$'));
+  EXPECT_TRUE(IsValidEscape('('));
+  EXPECT_TRUE(IsValidEscape(']'));
+  EXPECT_TRUE(IsValidEscape('{'));
+  EXPECT_TRUE(IsValidEscape('|'));
+}
+
+TEST(IsValidEscapeTest, IsTrueForSomeLetter) {
+  EXPECT_TRUE(IsValidEscape('d'));
+  EXPECT_TRUE(IsValidEscape('D'));
+  EXPECT_TRUE(IsValidEscape('s'));
+  EXPECT_TRUE(IsValidEscape('S'));
+  EXPECT_TRUE(IsValidEscape('w'));
+  EXPECT_TRUE(IsValidEscape('W'));
+}
+
+TEST(AtomMatchesCharTest, EscapedPunct) {
+  EXPECT_FALSE(AtomMatchesChar(true, '\\', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, '\\', ' '));
+  EXPECT_FALSE(AtomMatchesChar(true, '_', '.'));
+  EXPECT_FALSE(AtomMatchesChar(true, '.', 'a'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, '\\', '\\'));
+  EXPECT_TRUE(AtomMatchesChar(true, '_', '_'));
+  EXPECT_TRUE(AtomMatchesChar(true, '+', '+'));
+  EXPECT_TRUE(AtomMatchesChar(true, '.', '.'));
+}
+
+TEST(AtomMatchesCharTest, Escaped_d) {
+  EXPECT_FALSE(AtomMatchesChar(true, 'd', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'd', 'a'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'd', '.'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 'd', '0'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'd', '9'));
+}
+
+TEST(AtomMatchesCharTest, Escaped_D) {
+  EXPECT_FALSE(AtomMatchesChar(true, 'D', '0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'D', '9'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 'D', '\0'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'D', 'a'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'D', '-'));
+}
+
+TEST(AtomMatchesCharTest, Escaped_s) {
+  EXPECT_FALSE(AtomMatchesChar(true, 's', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 's', 'a'));
+  EXPECT_FALSE(AtomMatchesChar(true, 's', '.'));
+  EXPECT_FALSE(AtomMatchesChar(true, 's', '9'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 's', ' '));
+  EXPECT_TRUE(AtomMatchesChar(true, 's', '\n'));
+  EXPECT_TRUE(AtomMatchesChar(true, 's', '\t'));
+}
+
+TEST(AtomMatchesCharTest, Escaped_S) {
+  EXPECT_FALSE(AtomMatchesChar(true, 'S', ' '));
+  EXPECT_FALSE(AtomMatchesChar(true, 'S', '\r'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 'S', '\0'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'S', 'a'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'S', '9'));
+}
+
+TEST(AtomMatchesCharTest, Escaped_w) {
+  EXPECT_FALSE(AtomMatchesChar(true, 'w', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'w', '+'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'w', ' '));
+  EXPECT_FALSE(AtomMatchesChar(true, 'w', '\n'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 'w', '0'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'w', 'b'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'w', 'C'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'w', '_'));
+}
+
+TEST(AtomMatchesCharTest, Escaped_W) {
+  EXPECT_FALSE(AtomMatchesChar(true, 'W', 'A'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'W', 'b'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'W', '9'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'W', '_'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 'W', '\0'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'W', '*'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'W', '\n'));
+}
+
+TEST(AtomMatchesCharTest, EscapedWhiteSpace) {
+  EXPECT_FALSE(AtomMatchesChar(true, 'f', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'f', '\n'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'n', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'n', '\r'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'r', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'r', 'a'));
+  EXPECT_FALSE(AtomMatchesChar(true, 't', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 't', 't'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'v', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(true, 'v', '\f'));
+
+  EXPECT_TRUE(AtomMatchesChar(true, 'f', '\f'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'n', '\n'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'r', '\r'));
+  EXPECT_TRUE(AtomMatchesChar(true, 't', '\t'));
+  EXPECT_TRUE(AtomMatchesChar(true, 'v', '\v'));
+}
+
+TEST(AtomMatchesCharTest, UnescapedDot) {
+  EXPECT_FALSE(AtomMatchesChar(false, '.', '\n'));
+
+  EXPECT_TRUE(AtomMatchesChar(false, '.', '\0'));
+  EXPECT_TRUE(AtomMatchesChar(false, '.', '.'));
+  EXPECT_TRUE(AtomMatchesChar(false, '.', 'a'));
+  EXPECT_TRUE(AtomMatchesChar(false, '.', ' '));
+}
+
+TEST(AtomMatchesCharTest, UnescapedChar) {
+  EXPECT_FALSE(AtomMatchesChar(false, 'a', '\0'));
+  EXPECT_FALSE(AtomMatchesChar(false, 'a', 'b'));
+  EXPECT_FALSE(AtomMatchesChar(false, '$', 'a'));
+
+  EXPECT_TRUE(AtomMatchesChar(false, '$', '$'));
+  EXPECT_TRUE(AtomMatchesChar(false, '5', '5'));
+  EXPECT_TRUE(AtomMatchesChar(false, 'Z', 'Z'));
+}
+
+TEST(ValidateRegexTest, GeneratesFailureAndReturnsFalseForInvalid) {
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex(NULL)),
+                          "NULL is not a valid simple regular expression");
+  EXPECT_NONFATAL_FAILURE(
+      ASSERT_FALSE(ValidateRegex("a\\")),
+      "Syntax error at index 1 in simple regular expression \"a\\\": ");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("a\\")),
+                          "'\\' cannot appear at the end");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("\\n\\")),
+                          "'\\' cannot appear at the end");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("\\s\\hb")),
+                          "invalid escape sequence \"\\h\"");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("^^")),
+                          "'^' can only appear at the beginning");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex(".*^b")),
+                          "'^' can only appear at the beginning");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("$$")),
+                          "'$' can only appear at the end");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("^$a")),
+                          "'$' can only appear at the end");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("a(b")),
+                          "'(' is unsupported");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("ab)")),
+                          "')' is unsupported");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("[ab")),
+                          "'[' is unsupported");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("a{2")),
+                          "'{' is unsupported");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("?")),
+                          "'?' can only follow a repeatable token");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("^*")),
+                          "'*' can only follow a repeatable token");
+  EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("5*+")),
+                          "'+' can only follow a repeatable token");
+}
+
+TEST(ValidateRegexTest, ReturnsTrueForValid) {
+  EXPECT_TRUE(ValidateRegex(""));
+  EXPECT_TRUE(ValidateRegex("a"));
+  EXPECT_TRUE(ValidateRegex(".*"));
+  EXPECT_TRUE(ValidateRegex("^a_+"));
+  EXPECT_TRUE(ValidateRegex("^a\\t\\&?"));
+  EXPECT_TRUE(ValidateRegex("09*$"));
+  EXPECT_TRUE(ValidateRegex("^Z$"));
+  EXPECT_TRUE(ValidateRegex("a\\^Z\\$\\(\\)\\|\\[\\]\\{\\}"));
+}
+
+TEST(MatchRepetitionAndRegexAtHeadTest, WorksForZeroOrOne) {
+  EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "a", "ba"));
+  // Repeating more than once.
+  EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "b", "aab"));
+
+  // Repeating zero times.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "b", "ba"));
+  // Repeating once.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "b", "ab"));
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '#', '?', ".", "##"));
+}
+
+TEST(MatchRepetitionAndRegexAtHeadTest, WorksForZeroOrMany) {
+  EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, '.', '*', "a$", "baab"));
+
+  // Repeating zero times.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '.', '*', "b", "bc"));
+  // Repeating once.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '.', '*', "b", "abc"));
+  // Repeating more than once.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(true, 'w', '*', "-", "ab_1-g"));
+}
+
+TEST(MatchRepetitionAndRegexAtHeadTest, WorksForOneOrMany) {
+  EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, '.', '+', "a$", "baab"));
+  // Repeating zero times.
+  EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, '.', '+', "b", "bc"));
+
+  // Repeating once.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '.', '+', "b", "abc"));
+  // Repeating more than once.
+  EXPECT_TRUE(MatchRepetitionAndRegexAtHead(true, 'w', '+', "-", "ab_1-g"));
+}
+
+TEST(MatchRegexAtHeadTest, ReturnsTrueForEmptyRegex) {
+  EXPECT_TRUE(MatchRegexAtHead("", ""));
+  EXPECT_TRUE(MatchRegexAtHead("", "ab"));
+}
+
+TEST(MatchRegexAtHeadTest, WorksWhenDollarIsInRegex) {
+  EXPECT_FALSE(MatchRegexAtHead("$", "a"));
+
+  EXPECT_TRUE(MatchRegexAtHead("$", ""));
+  EXPECT_TRUE(MatchRegexAtHead("a$", "a"));
+}
+
+TEST(MatchRegexAtHeadTest, WorksWhenRegexStartsWithEscapeSequence) {
+  EXPECT_FALSE(MatchRegexAtHead("\\w", "+"));
+  EXPECT_FALSE(MatchRegexAtHead("\\W", "ab"));
+
+  EXPECT_TRUE(MatchRegexAtHead("\\sa", "\nab"));
+  EXPECT_TRUE(MatchRegexAtHead("\\d", "1a"));
+}
+
+TEST(MatchRegexAtHeadTest, WorksWhenRegexStartsWithRepetition) {
+  EXPECT_FALSE(MatchRegexAtHead(".+a", "abc"));
+  EXPECT_FALSE(MatchRegexAtHead("a?b", "aab"));
+
+  EXPECT_TRUE(MatchRegexAtHead(".*a", "bc12-ab"));
+  EXPECT_TRUE(MatchRegexAtHead("a?b", "b"));
+  EXPECT_TRUE(MatchRegexAtHead("a?b", "ab"));
+}
+
+TEST(MatchRegexAtHeadTest,
+     WorksWhenRegexStartsWithRepetionOfEscapeSequence) {
+  EXPECT_FALSE(MatchRegexAtHead("\\.+a", "abc"));
+  EXPECT_FALSE(MatchRegexAtHead("\\s?b", "  b"));
+
+  EXPECT_TRUE(MatchRegexAtHead("\\(*a", "((((ab"));
+  EXPECT_TRUE(MatchRegexAtHead("\\^?b", "^b"));
+  EXPECT_TRUE(MatchRegexAtHead("\\\\?b", "b"));
+  EXPECT_TRUE(MatchRegexAtHead("\\\\?b", "\\b"));
+}
+
+TEST(MatchRegexAtHeadTest, MatchesSequentially) {
+  EXPECT_FALSE(MatchRegexAtHead("ab.*c", "acabc"));
+
+  EXPECT_TRUE(MatchRegexAtHead("ab.*c", "ab-fsc"));
+}
+
+TEST(MatchRegexAnywhereTest, ReturnsFalseWhenStringIsNull) {
+  EXPECT_FALSE(MatchRegexAnywhere("", NULL));
+}
+
+TEST(MatchRegexAnywhereTest, WorksWhenRegexStartsWithCaret) {
+  EXPECT_FALSE(MatchRegexAnywhere("^a", "ba"));
+  EXPECT_FALSE(MatchRegexAnywhere("^$", "a"));
+
+  EXPECT_TRUE(MatchRegexAnywhere("^a", "ab"));
+  EXPECT_TRUE(MatchRegexAnywhere("^", "ab"));
+  EXPECT_TRUE(MatchRegexAnywhere("^$", ""));
+}
+
+TEST(MatchRegexAnywhereTest, ReturnsFalseWhenNoMatch) {
+  EXPECT_FALSE(MatchRegexAnywhere("a", "bcde123"));
+  EXPECT_FALSE(MatchRegexAnywhere("a.+a", "--aa88888888"));
+}
+
+TEST(MatchRegexAnywhereTest, ReturnsTrueWhenMatchingPrefix) {
+  EXPECT_TRUE(MatchRegexAnywhere("\\w+", "ab1_ - 5"));
+  EXPECT_TRUE(MatchRegexAnywhere(".*=", "="));
+  EXPECT_TRUE(MatchRegexAnywhere("x.*ab?.*bc", "xaaabc"));
+}
+
+TEST(MatchRegexAnywhereTest, ReturnsTrueWhenMatchingNonPrefix) {
+  EXPECT_TRUE(MatchRegexAnywhere("\\w+", "$$$ ab1_ - 5"));
+  EXPECT_TRUE(MatchRegexAnywhere("\\.+=", "=  ...="));
+}
+
+// Tests RE's implicit constructors.
+TEST(RETest, ImplicitConstructorWorks) {
+  const RE empty("");
+  EXPECT_STREQ("", empty.pattern());
+
+  const RE simple("hello");
+  EXPECT_STREQ("hello", simple.pattern());
+}
+
+// Tests that RE's constructors reject invalid regular expressions.
+TEST(RETest, RejectsInvalidRegex) {
+  EXPECT_NONFATAL_FAILURE({
+    const RE normal(NULL);
+  }, "NULL is not a valid simple regular expression");
+
+  EXPECT_NONFATAL_FAILURE({
+    const RE normal(".*(\\w+");
+  }, "'(' is unsupported");
+
+  EXPECT_NONFATAL_FAILURE({
+    const RE invalid("^?");
+  }, "'?' can only follow a repeatable token");
+}
+
+// Tests RE::FullMatch().
+TEST(RETest, FullMatchWorks) {
+  const RE empty("");
+  EXPECT_TRUE(RE::FullMatch("", empty));
+  EXPECT_FALSE(RE::FullMatch("a", empty));
+
+  const RE re1("a");
+  EXPECT_TRUE(RE::FullMatch("a", re1));
+
+  const RE re("a.*z");
+  EXPECT_TRUE(RE::FullMatch("az", re));
+  EXPECT_TRUE(RE::FullMatch("axyz", re));
+  EXPECT_FALSE(RE::FullMatch("baz", re));
+  EXPECT_FALSE(RE::FullMatch("azy", re));
+}
+
+// Tests RE::PartialMatch().
+TEST(RETest, PartialMatchWorks) {
+  const RE empty("");
+  EXPECT_TRUE(RE::PartialMatch("", empty));
+  EXPECT_TRUE(RE::PartialMatch("a", empty));
+
+  const RE re("a.*z");
+  EXPECT_TRUE(RE::PartialMatch("az", re));
+  EXPECT_TRUE(RE::PartialMatch("axyz", re));
+  EXPECT_TRUE(RE::PartialMatch("baz", re));
+  EXPECT_TRUE(RE::PartialMatch("azy", re));
+  EXPECT_FALSE(RE::PartialMatch("zza", re));
+}
+
+#endif  // GTEST_USES_POSIX_RE
+
+#if !GTEST_OS_WINDOWS_MOBILE
+
+TEST(CaptureTest, CapturesStdout) {
+  CaptureStdout();
+  fprintf(stdout, "abc");
+  EXPECT_STREQ("abc", GetCapturedStdout().c_str());
+
+  CaptureStdout();
+  fprintf(stdout, "def%cghi", '\0');
+  EXPECT_EQ(::std::string("def\0ghi", 7), ::std::string(GetCapturedStdout()));
+}
+
+TEST(CaptureTest, CapturesStderr) {
+  CaptureStderr();
+  fprintf(stderr, "jkl");
+  EXPECT_STREQ("jkl", GetCapturedStderr().c_str());
+
+  CaptureStderr();
+  fprintf(stderr, "jkl%cmno", '\0');
+  EXPECT_EQ(::std::string("jkl\0mno", 7), ::std::string(GetCapturedStderr()));
+}
+
+// Tests that stdout and stderr capture don't interfere with each other.
+TEST(CaptureTest, CapturesStdoutAndStderr) {
+  CaptureStdout();
+  CaptureStderr();
+  fprintf(stdout, "pqr");
+  fprintf(stderr, "stu");
+  EXPECT_STREQ("pqr", GetCapturedStdout().c_str());
+  EXPECT_STREQ("stu", GetCapturedStderr().c_str());
+}
+
+TEST(CaptureDeathTest, CannotReenterStdoutCapture) {
+  CaptureStdout();
+  EXPECT_DEATH_IF_SUPPORTED(CaptureStdout();,
+                            "Only one stdout capturer can exist at a time");
+  GetCapturedStdout();
+
+  // We cannot test stderr capturing using death tests as they use it
+  // themselves.
+}
+
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+TEST(ThreadLocalTest, DefaultConstructorInitializesToDefaultValues) {
+  ThreadLocal<int> t1;
+  EXPECT_EQ(0, t1.get());
+
+  ThreadLocal<void*> t2;
+  EXPECT_TRUE(t2.get() == NULL);
+}
+
+TEST(ThreadLocalTest, SingleParamConstructorInitializesToParam) {
+  ThreadLocal<int> t1(123);
+  EXPECT_EQ(123, t1.get());
+
+  int i = 0;
+  ThreadLocal<int*> t2(&i);
+  EXPECT_EQ(&i, t2.get());
+}
+
+class NoDefaultContructor {
+ public:
+  explicit NoDefaultContructor(const char*) {}
+  NoDefaultContructor(const NoDefaultContructor&) {}
+};
+
+TEST(ThreadLocalTest, ValueDefaultContructorIsNotRequiredForParamVersion) {
+  ThreadLocal<NoDefaultContructor> bar(NoDefaultContructor("foo"));
+  bar.pointer();
+}
+
+TEST(ThreadLocalTest, GetAndPointerReturnSameValue) {
+  ThreadLocal<String> thread_local;
+
+  EXPECT_EQ(thread_local.pointer(), &(thread_local.get()));
+
+  // Verifies the condition still holds after calling set.
+  thread_local.set("foo");
+  EXPECT_EQ(thread_local.pointer(), &(thread_local.get()));
+}
+
+TEST(ThreadLocalTest, PointerAndConstPointerReturnSameValue) {
+  ThreadLocal<String> thread_local;
+  const ThreadLocal<String>& const_thread_local = thread_local;
+
+  EXPECT_EQ(thread_local.pointer(), const_thread_local.pointer());
+
+  thread_local.set("foo");
+  EXPECT_EQ(thread_local.pointer(), const_thread_local.pointer());
+}
+
+#if GTEST_IS_THREADSAFE
+
+void AddTwo(int* param) { *param += 2; }
+
+TEST(ThreadWithParamTest, ConstructorExecutesThreadFunc) {
+  int i = 40;
+  ThreadWithParam<int*> thread(&AddTwo, &i, NULL);
+  thread.Join();
+  EXPECT_EQ(42, i);
+}
+
+TEST(MutexDeathTest, AssertHeldShouldAssertWhenNotLocked) {
+  // AssertHeld() is flaky only in the presence of multiple threads accessing
+  // the lock. In this case, the test is robust.
+  EXPECT_DEATH_IF_SUPPORTED({
+    Mutex m;
+    { MutexLock lock(&m); }
+    m.AssertHeld();
+  },
+  "thread .*hold");
+}
+
+TEST(MutexTest, AssertHeldShouldNotAssertWhenLocked) {
+  Mutex m;
+  MutexLock lock(&m);
+  m.AssertHeld();
+}
+
+class AtomicCounterWithMutex {
+ public:
+  explicit AtomicCounterWithMutex(Mutex* mutex) :
+    value_(0), mutex_(mutex), random_(42) {}
+
+  void Increment() {
+    MutexLock lock(mutex_);
+    int temp = value_;
+    {
+      // Locking a mutex puts up a memory barrier, preventing reads and
+      // writes to value_ rearranged when observed from other threads.
+      //
+      // We cannot use Mutex and MutexLock here or rely on their memory
+      // barrier functionality as we are testing them here.
+      pthread_mutex_t memory_barrier_mutex;
+      GTEST_CHECK_POSIX_SUCCESS_(
+          pthread_mutex_init(&memory_barrier_mutex, NULL));
+      GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&memory_barrier_mutex));
+
+      SleepMilliseconds(random_.Generate(30));
+
+      GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&memory_barrier_mutex));
+    }
+    value_ = temp + 1;
+  }
+  int value() const { return value_; }
+
+ private:
+  volatile int value_;
+  Mutex* const mutex_;  // Protects value_.
+  Random       random_;
+};
+
+void CountingThreadFunc(pair<AtomicCounterWithMutex*, int> param) {
+  for (int i = 0; i < param.second; ++i)
+      param.first->Increment();
+}
+
+// Tests that the mutex only lets one thread at a time to lock it.
+TEST(MutexTest, OnlyOneThreadCanLockAtATime) {
+  Mutex mutex;
+  AtomicCounterWithMutex locked_counter(&mutex);
+
+  typedef ThreadWithParam<pair<AtomicCounterWithMutex*, int> > ThreadType;
+  const int kCycleCount = 20;
+  const int kThreadCount = 7;
+  scoped_ptr<ThreadType> counting_threads[kThreadCount];
+  Notification threads_can_start;
+  // Creates and runs kThreadCount threads that increment locked_counter
+  // kCycleCount times each.
+  for (int i = 0; i < kThreadCount; ++i) {
+    counting_threads[i].reset(new ThreadType(&CountingThreadFunc,
+                                             make_pair(&locked_counter,
+                                                       kCycleCount),
+                                             &threads_can_start));
+  }
+  threads_can_start.Notify();
+  for (int i = 0; i < kThreadCount; ++i)
+    counting_threads[i]->Join();
+
+  // If the mutex lets more than one thread to increment the counter at a
+  // time, they are likely to encounter a race condition and have some
+  // increments overwritten, resulting in the lower then expected counter
+  // value.
+  EXPECT_EQ(kCycleCount * kThreadCount, locked_counter.value());
+}
+
+template <typename T>
+void RunFromThread(void (func)(T), T param) {
+  ThreadWithParam<T> thread(func, param, NULL);
+  thread.Join();
+}
+
+void RetrieveThreadLocalValue(pair<ThreadLocal<String>*, String*> param) {
+  *param.second = param.first->get();
+}
+
+TEST(ThreadLocalTest, ParameterizedConstructorSetsDefault) {
+  ThreadLocal<String> thread_local("foo");
+  EXPECT_STREQ("foo", thread_local.get().c_str());
+
+  thread_local.set("bar");
+  EXPECT_STREQ("bar", thread_local.get().c_str());
+
+  String result;
+  RunFromThread(&RetrieveThreadLocalValue, make_pair(&thread_local, &result));
+  EXPECT_STREQ("foo", result.c_str());
+}
+
+// DestructorTracker keeps track of whether its instances have been
+// destroyed.
+static std::vector<bool> g_destroyed;
+
+class DestructorTracker {
+ public:
+  DestructorTracker() : index_(GetNewIndex()) {}
+  DestructorTracker(const DestructorTracker& /* rhs */)
+      : index_(GetNewIndex()) {}
+  ~DestructorTracker() {
+    // We never access g_destroyed concurrently, so we don't need to
+    // protect the write operation under a mutex.
+    g_destroyed[index_] = true;
+  }
+
+ private:
+  static int GetNewIndex() {
+    g_destroyed.push_back(false);
+    return g_destroyed.size() - 1;
+  }
+  const int index_;
+};
+
+typedef ThreadLocal<DestructorTracker>* ThreadParam;
+
+void CallThreadLocalGet(ThreadParam thread_local) {
+  thread_local->get();
+}
+
+// Tests that when a ThreadLocal object dies in a thread, it destroys
+// the managed object for that thread.
+TEST(ThreadLocalTest, DestroysManagedObjectForOwnThreadWhenDying) {
+  g_destroyed.clear();
+
+  {
+    // The next line default constructs a DestructorTracker object as
+    // the default value of objects managed by thread_local.
+    ThreadLocal<DestructorTracker> thread_local;
+    ASSERT_EQ(1U, g_destroyed.size());
+    ASSERT_FALSE(g_destroyed[0]);
+
+    // This creates another DestructorTracker object for the main thread.
+    thread_local.get();
+    ASSERT_EQ(2U, g_destroyed.size());
+    ASSERT_FALSE(g_destroyed[0]);
+    ASSERT_FALSE(g_destroyed[1]);
+  }
+
+  // Now thread_local has died.  It should have destroyed both the
+  // default value shared by all threads and the value for the main
+  // thread.
+  ASSERT_EQ(2U, g_destroyed.size());
+  EXPECT_TRUE(g_destroyed[0]);
+  EXPECT_TRUE(g_destroyed[1]);
+
+  g_destroyed.clear();
+}
+
+// Tests that when a thread exits, the thread-local object for that
+// thread is destroyed.
+TEST(ThreadLocalTest, DestroysManagedObjectAtThreadExit) {
+  g_destroyed.clear();
+
+  {
+    // The next line default constructs a DestructorTracker object as
+    // the default value of objects managed by thread_local.
+    ThreadLocal<DestructorTracker> thread_local;
+    ASSERT_EQ(1U, g_destroyed.size());
+    ASSERT_FALSE(g_destroyed[0]);
+
+    // This creates another DestructorTracker object in the new thread.
+    ThreadWithParam<ThreadParam> thread(
+        &CallThreadLocalGet, &thread_local, NULL);
+    thread.Join();
+
+    // Now the new thread has exited.  The per-thread object for it
+    // should have been destroyed.
+    ASSERT_EQ(2U, g_destroyed.size());
+    ASSERT_FALSE(g_destroyed[0]);
+    ASSERT_TRUE(g_destroyed[1]);
+  }
+
+  // Now thread_local has died.  The default value should have been
+  // destroyed too.
+  ASSERT_EQ(2U, g_destroyed.size());
+  EXPECT_TRUE(g_destroyed[0]);
+  EXPECT_TRUE(g_destroyed[1]);
+
+  g_destroyed.clear();
+}
+
+TEST(ThreadLocalTest, ThreadLocalMutationsAffectOnlyCurrentThread) {
+  ThreadLocal<String> thread_local;
+  thread_local.set("Foo");
+  EXPECT_STREQ("Foo", thread_local.get().c_str());
+
+  String result;
+  RunFromThread(&RetrieveThreadLocalValue, make_pair(&thread_local, &result));
+  EXPECT_TRUE(result.c_str() == NULL);
+}
+
+#endif  // GTEST_IS_THREADSAFE
+
+}  // namespace internal
+}  // namespace testing
diff --git a/third_party/googletest/src/test/gtest-printers_test.cc b/third_party/googletest/src/test/gtest-printers_test.cc
new file mode 100644 (file)
index 0000000..6292c7f
--- /dev/null
@@ -0,0 +1,1307 @@
+// Copyright 2007, 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: wan@google.com (Zhanyong Wan)
+
+// Google Test - The Google C++ Testing Framework
+//
+// This file tests the universal value printer.
+
+#include "gtest/gtest-printers.h"
+
+#include <ctype.h>
+#include <limits.h>
+#include <string.h>
+#include <algorithm>
+#include <deque>
+#include <list>
+#include <map>
+#include <set>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "gtest/gtest.h"
+
+// hash_map and hash_set are available under Visual C++.
+#if _MSC_VER
+# define GTEST_HAS_HASH_MAP_ 1  // Indicates that hash_map is available.
+# include <hash_map>            // NOLINT
+# define GTEST_HAS_HASH_SET_ 1  // Indicates that hash_set is available.
+# include <hash_set>            // NOLINT
+#endif  // GTEST_OS_WINDOWS
+
+// Some user-defined types for testing the universal value printer.
+
+// An anonymous enum type.
+enum AnonymousEnum {
+  kAE1 = -1,
+  kAE2 = 1
+};
+
+// An enum without a user-defined printer.
+enum EnumWithoutPrinter {
+  kEWP1 = -2,
+  kEWP2 = 42
+};
+
+// An enum with a << operator.
+enum EnumWithStreaming {
+  kEWS1 = 10
+};
+
+std::ostream& operator<<(std::ostream& os, EnumWithStreaming e) {
+  return os << (e == kEWS1 ? "kEWS1" : "invalid");
+}
+
+// An enum with a PrintTo() function.
+enum EnumWithPrintTo {
+  kEWPT1 = 1
+};
+
+void PrintTo(EnumWithPrintTo e, std::ostream* os) {
+  *os << (e == kEWPT1 ? "kEWPT1" : "invalid");
+}
+
+// A class implicitly convertible to BiggestInt.
+class BiggestIntConvertible {
+ public:
+  operator ::testing::internal::BiggestInt() const { return 42; }
+};
+
+// A user-defined unprintable class template in the global namespace.
+template <typename T>
+class UnprintableTemplateInGlobal {
+ public:
+  UnprintableTemplateInGlobal() : value_() {}
+ private:
+  T value_;
+};
+
+// A user-defined streamable type in the global namespace.
+class StreamableInGlobal {
+ public:
+  virtual ~StreamableInGlobal() {}
+};
+
+inline void operator<<(::std::ostream& os, const StreamableInGlobal& /* x */) {
+  os << "StreamableInGlobal";
+}
+
+void operator<<(::std::ostream& os, const StreamableInGlobal* /* x */) {
+  os << "StreamableInGlobal*";
+}
+
+namespace foo {
+
+// A user-defined unprintable type in a user namespace.
+class UnprintableInFoo {
+ public:
+  UnprintableInFoo() : z_(0) { memcpy(xy_, "\xEF\x12\x0\x0\x34\xAB\x0\x0", 8); }
+ private:
+  char xy_[8];
+  double z_;
+};
+
+// A user-defined printable type in a user-chosen namespace.
+struct PrintableViaPrintTo {
+  PrintableViaPrintTo() : value() {}
+  int value;
+};
+
+void PrintTo(const PrintableViaPrintTo& x, ::std::ostream* os) {
+  *os << "PrintableViaPrintTo: " << x.value;
+}
+
+// A type with a user-defined << for printing its pointer.
+struct PointerPrintable {
+};
+
+::std::ostream& operator<<(::std::ostream& os,
+                           const PointerPrintable* /* x */) {
+  return os << "PointerPrintable*";
+}
+
+// A user-defined printable class template in a user-chosen namespace.
+template <typename T>
+class PrintableViaPrintToTemplate {
+ public:
+  explicit PrintableViaPrintToTemplate(const T& a_value) : value_(a_value) {}
+
+  const T& value() const { return value_; }
+ private:
+  T value_;
+};
+
+template <typename T>
+void PrintTo(const PrintableViaPrintToTemplate<T>& x, ::std::ostream* os) {
+  *os << "PrintableViaPrintToTemplate: " << x.value();
+}
+
+// A user-defined streamable class template in a user namespace.
+template <typename T>
+class StreamableTemplateInFoo {
+ public:
+  StreamableTemplateInFoo() : value_() {}
+
+  const T& value() const { return value_; }
+ private:
+  T value_;
+};
+
+template <typename T>
+inline ::std::ostream& operator<<(::std::ostream& os,
+                                  const StreamableTemplateInFoo<T>& x) {
+  return os << "StreamableTemplateInFoo: " << x.value();
+}
+
+}  // namespace foo
+
+namespace testing {
+namespace gtest_printers_test {
+
+using ::std::deque;
+using ::std::list;
+using ::std::make_pair;
+using ::std::map;
+using ::std::multimap;
+using ::std::multiset;
+using ::std::pair;
+using ::std::set;
+using ::std::vector;
+using ::testing::PrintToString;
+using ::testing::internal::NativeArray;
+using ::testing::internal::RE;
+using ::testing::internal::Strings;
+using ::testing::internal::UniversalTersePrint;
+using ::testing::internal::UniversalPrint;
+using ::testing::internal::UniversalTersePrintTupleFieldsToStrings;
+using ::testing::internal::UniversalPrinter;
+using ::testing::internal::kReference;
+using ::testing::internal::string;
+
+#if GTEST_HAS_TR1_TUPLE
+using ::std::tr1::make_tuple;
+using ::std::tr1::tuple;
+#endif
+
+#if _MSC_VER
+// MSVC defines the following classes in the ::stdext namespace while
+// gcc defines them in the :: namespace.  Note that they are not part
+// of the C++ standard.
+using ::stdext::hash_map;
+using ::stdext::hash_set;
+using ::stdext::hash_multimap;
+using ::stdext::hash_multiset;
+#endif
+
+// Prints a value to a string using the universal value printer.  This
+// is a helper for testing UniversalPrinter<T>::Print() for various types.
+template <typename T>
+string Print(const T& value) {
+  ::std::stringstream ss;
+  UniversalPrinter<T>::Print(value, &ss);
+  return ss.str();
+}
+
+// Prints a value passed by reference to a string, using the universal
+// value printer.  This is a helper for testing
+// UniversalPrinter<T&>::Print() for various types.
+template <typename T>
+string PrintByRef(const T& value) {
+  ::std::stringstream ss;
+  UniversalPrinter<T&>::Print(value, &ss);
+  return ss.str();
+}
+
+// Tests printing various enum types.
+
+TEST(PrintEnumTest, AnonymousEnum) {
+  EXPECT_EQ("-1", Print(kAE1));
+  EXPECT_EQ("1", Print(kAE2));
+}
+
+TEST(PrintEnumTest, EnumWithoutPrinter) {
+  EXPECT_EQ("-2", Print(kEWP1));
+  EXPECT_EQ("42", Print(kEWP2));
+}
+
+TEST(PrintEnumTest, EnumWithStreaming) {
+  EXPECT_EQ("kEWS1", Print(kEWS1));
+  EXPECT_EQ("invalid", Print(static_cast<EnumWithStreaming>(0)));
+}
+
+TEST(PrintEnumTest, EnumWithPrintTo) {
+  EXPECT_EQ("kEWPT1", Print(kEWPT1));
+  EXPECT_EQ("invalid", Print(static_cast<EnumWithPrintTo>(0)));
+}
+
+// Tests printing a class implicitly convertible to BiggestInt.
+
+TEST(PrintClassTest, BiggestIntConvertible) {
+  EXPECT_EQ("42", Print(BiggestIntConvertible()));
+}
+
+// Tests printing various char types.
+
+// char.
+TEST(PrintCharTest, PlainChar) {
+  EXPECT_EQ("'\\0'", Print('\0'));
+  EXPECT_EQ("'\\'' (39, 0x27)", Print('\''));
+  EXPECT_EQ("'\"' (34, 0x22)", Print('"'));
+  EXPECT_EQ("'?' (63, 0x3F)", Print('?'));
+  EXPECT_EQ("'\\\\' (92, 0x5C)", Print('\\'));
+  EXPECT_EQ("'\\a' (7)", Print('\a'));
+  EXPECT_EQ("'\\b' (8)", Print('\b'));
+  EXPECT_EQ("'\\f' (12, 0xC)", Print('\f'));
+  EXPECT_EQ("'\\n' (10, 0xA)", Print('\n'));
+  EXPECT_EQ("'\\r' (13, 0xD)", Print('\r'));
+  EXPECT_EQ("'\\t' (9)", Print('\t'));
+  EXPECT_EQ("'\\v' (11, 0xB)", Print('\v'));
+  EXPECT_EQ("'\\x7F' (127)", Print('\x7F'));
+  EXPECT_EQ("'\\xFF' (255)", Print('\xFF'));
+  EXPECT_EQ("' ' (32, 0x20)", Print(' '));
+  EXPECT_EQ("'a' (97, 0x61)", Print('a'));
+}
+
+// signed char.
+TEST(PrintCharTest, SignedChar) {
+  EXPECT_EQ("'\\0'", Print(static_cast<signed char>('\0')));
+  EXPECT_EQ("'\\xCE' (-50)",
+            Print(static_cast<signed char>(-50)));
+}
+
+// unsigned char.
+TEST(PrintCharTest, UnsignedChar) {
+  EXPECT_EQ("'\\0'", Print(static_cast<unsigned char>('\0')));
+  EXPECT_EQ("'b' (98, 0x62)",
+            Print(static_cast<unsigned char>('b')));
+}
+
+// Tests printing other simple, built-in types.
+
+// bool.
+TEST(PrintBuiltInTypeTest, Bool) {
+  EXPECT_EQ("false", Print(false));
+  EXPECT_EQ("true", Print(true));
+}
+
+// wchar_t.
+TEST(PrintBuiltInTypeTest, Wchar_t) {
+  EXPECT_EQ("L'\\0'", Print(L'\0'));
+  EXPECT_EQ("L'\\'' (39, 0x27)", Print(L'\''));
+  EXPECT_EQ("L'\"' (34, 0x22)", Print(L'"'));
+  EXPECT_EQ("L'?' (63, 0x3F)", Print(L'?'));
+  EXPECT_EQ("L'\\\\' (92, 0x5C)", Print(L'\\'));
+  EXPECT_EQ("L'\\a' (7)", Print(L'\a'));
+  EXPECT_EQ("L'\\b' (8)", Print(L'\b'));
+  EXPECT_EQ("L'\\f' (12, 0xC)", Print(L'\f'));
+  EXPECT_EQ("L'\\n' (10, 0xA)", Print(L'\n'));
+  EXPECT_EQ("L'\\r' (13, 0xD)", Print(L'\r'));
+  EXPECT_EQ("L'\\t' (9)", Print(L'\t'));
+  EXPECT_EQ("L'\\v' (11, 0xB)", Print(L'\v'));
+  EXPECT_EQ("L'\\x7F' (127)", Print(L'\x7F'));
+  EXPECT_EQ("L'\\xFF' (255)", Print(L'\xFF'));
+  EXPECT_EQ("L' ' (32, 0x20)", Print(L' '));
+  EXPECT_EQ("L'a' (97, 0x61)", Print(L'a'));
+  EXPECT_EQ("L'\\x576' (1398)", Print(static_cast<wchar_t>(0x576)));
+  EXPECT_EQ("L'\\xC74D' (51021)", Print(static_cast<wchar_t>(0xC74D)));
+}
+
+// Test that Int64 provides more storage than wchar_t.
+TEST(PrintTypeSizeTest, Wchar_t) {
+  EXPECT_LT(sizeof(wchar_t), sizeof(testing::internal::Int64));
+}
+
+// Various integer types.
+TEST(PrintBuiltInTypeTest, Integer) {
+  EXPECT_EQ("'\\xFF' (255)", Print(static_cast<unsigned char>(255)));  // uint8
+  EXPECT_EQ("'\\x80' (-128)", Print(static_cast<signed char>(-128)));  // int8
+  EXPECT_EQ("65535", Print(USHRT_MAX));  // uint16
+  EXPECT_EQ("-32768", Print(SHRT_MIN));  // int16
+  EXPECT_EQ("4294967295", Print(UINT_MAX));  // uint32
+  EXPECT_EQ("-2147483648", Print(INT_MIN));  // int32
+  EXPECT_EQ("18446744073709551615",
+            Print(static_cast<testing::internal::UInt64>(-1)));  // uint64
+  EXPECT_EQ("-9223372036854775808",
+            Print(static_cast<testing::internal::Int64>(1) << 63));  // int64
+}
+
+// Size types.
+TEST(PrintBuiltInTypeTest, Size_t) {
+  EXPECT_EQ("1", Print(sizeof('a')));  // size_t.
+#if !GTEST_OS_WINDOWS
+  // Windows has no ssize_t type.
+  EXPECT_EQ("-2", Print(static_cast<ssize_t>(-2)));  // ssize_t.
+#endif  // !GTEST_OS_WINDOWS
+}
+
+// Floating-points.
+TEST(PrintBuiltInTypeTest, FloatingPoints) {
+  EXPECT_EQ("1.5", Print(1.5f));   // float
+  EXPECT_EQ("-2.5", Print(-2.5));  // double
+}
+
+// Since ::std::stringstream::operator<<(const void *) formats the pointer
+// output differently with different compilers, we have to create the expected
+// output first and use it as our expectation.
+static string PrintPointer(const void *p) {
+  ::std::stringstream expected_result_stream;
+  expected_result_stream << p;
+  return expected_result_stream.str();
+}
+
+// Tests printing C strings.
+
+// const char*.
+TEST(PrintCStringTest, Const) {
+  const char* p = "World";
+  EXPECT_EQ(PrintPointer(p) + " pointing to \"World\"", Print(p));
+}
+
+// char*.
+TEST(PrintCStringTest, NonConst) {
+  char p[] = "Hi";
+  EXPECT_EQ(PrintPointer(p) + " pointing to \"Hi\"",
+            Print(static_cast<char*>(p)));
+}
+
+// NULL C string.
+TEST(PrintCStringTest, Null) {
+  const char* p = NULL;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests that C strings are escaped properly.
+TEST(PrintCStringTest, EscapesProperly) {
+  const char* p = "'\"?\\\a\b\f\n\r\t\v\x7F\xFF a";
+  EXPECT_EQ(PrintPointer(p) + " pointing to \"'\\\"?\\\\\\a\\b\\f"
+            "\\n\\r\\t\\v\\x7F\\xFF a\"",
+            Print(p));
+}
+
+
+
+// MSVC compiler can be configured to define whar_t as a typedef
+// of unsigned short. Defining an overload for const wchar_t* in that case
+// would cause pointers to unsigned shorts be printed as wide strings,
+// possibly accessing more memory than intended and causing invalid
+// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
+// wchar_t is implemented as a native type.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+
+// const wchar_t*.
+TEST(PrintWideCStringTest, Const) {
+  const wchar_t* p = L"World";
+  EXPECT_EQ(PrintPointer(p) + " pointing to L\"World\"", Print(p));
+}
+
+// wchar_t*.
+TEST(PrintWideCStringTest, NonConst) {
+  wchar_t p[] = L"Hi";
+  EXPECT_EQ(PrintPointer(p) + " pointing to L\"Hi\"",
+            Print(static_cast<wchar_t*>(p)));
+}
+
+// NULL wide C string.
+TEST(PrintWideCStringTest, Null) {
+  const wchar_t* p = NULL;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests that wide C strings are escaped properly.
+TEST(PrintWideCStringTest, EscapesProperly) {
+  const wchar_t s[] = {'\'', '"', '?', '\\', '\a', '\b', '\f', '\n', '\r',
+                       '\t', '\v', 0xD3, 0x576, 0x8D3, 0xC74D, ' ', 'a', '\0'};
+  EXPECT_EQ(PrintPointer(s) + " pointing to L\"'\\\"?\\\\\\a\\b\\f"
+            "\\n\\r\\t\\v\\xD3\\x576\\x8D3\\xC74D a\"",
+            Print(static_cast<const wchar_t*>(s)));
+}
+#endif  // native wchar_t
+
+// Tests printing pointers to other char types.
+
+// signed char*.
+TEST(PrintCharPointerTest, SignedChar) {
+  signed char* p = reinterpret_cast<signed char*>(0x1234);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = NULL;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// const signed char*.
+TEST(PrintCharPointerTest, ConstSignedChar) {
+  signed char* p = reinterpret_cast<signed char*>(0x1234);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = NULL;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// unsigned char*.
+TEST(PrintCharPointerTest, UnsignedChar) {
+  unsigned char* p = reinterpret_cast<unsigned char*>(0x1234);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = NULL;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// const unsigned char*.
+TEST(PrintCharPointerTest, ConstUnsignedChar) {
+  const unsigned char* p = reinterpret_cast<const unsigned char*>(0x1234);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = NULL;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests printing pointers to simple, built-in types.
+
+// bool*.
+TEST(PrintPointerToBuiltInTypeTest, Bool) {
+  bool* p = reinterpret_cast<bool*>(0xABCD);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = NULL;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// void*.
+TEST(PrintPointerToBuiltInTypeTest, Void) {
+  void* p = reinterpret_cast<void*>(0xABCD);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = NULL;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// const void*.
+TEST(PrintPointerToBuiltInTypeTest, ConstVoid) {
+  const void* p = reinterpret_cast<const void*>(0xABCD);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = NULL;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests printing pointers to pointers.
+TEST(PrintPointerToPointerTest, IntPointerPointer) {
+  int** p = reinterpret_cast<int**>(0xABCD);
+  EXPECT_EQ(PrintPointer(p), Print(p));
+  p = NULL;
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests printing (non-member) function pointers.
+
+void MyFunction(int /* n */) {}
+
+TEST(PrintPointerTest, NonMemberFunctionPointer) {
+  // We cannot directly cast &MyFunction to const void* because the
+  // standard disallows casting between pointers to functions and
+  // pointers to objects, and some compilers (e.g. GCC 3.4) enforce
+  // this limitation.
+  EXPECT_EQ(
+      PrintPointer(reinterpret_cast<const void*>(
+          reinterpret_cast<internal::BiggestInt>(&MyFunction))),
+      Print(&MyFunction));
+  int (*p)(bool) = NULL;  // NOLINT
+  EXPECT_EQ("NULL", Print(p));
+}
+
+// An assertion predicate determining whether a one string is a prefix for
+// another.
+template <typename StringType>
+AssertionResult HasPrefix(const StringType& str, const StringType& prefix) {
+  if (str.find(prefix, 0) == 0)
+    return AssertionSuccess();
+
+  const bool is_wide_string = sizeof(prefix[0]) > 1;
+  const char* const begin_string_quote = is_wide_string ? "L\"" : "\"";
+  return AssertionFailure()
+      << begin_string_quote << prefix << "\" is not a prefix of "
+      << begin_string_quote << str << "\"\n";
+}
+
+// Tests printing member variable pointers.  Although they are called
+// pointers, they don't point to a location in the address space.
+// Their representation is implementation-defined.  Thus they will be
+// printed as raw bytes.
+
+struct Foo {
+ public:
+  virtual ~Foo() {}
+  int MyMethod(char x) { return x + 1; }
+  virtual char MyVirtualMethod(int /* n */) { return 'a'; }
+
+  int value;
+};
+
+TEST(PrintPointerTest, MemberVariablePointer) {
+  EXPECT_TRUE(HasPrefix(Print(&Foo::value),
+                        Print(sizeof(&Foo::value)) + "-byte object "));
+  int (Foo::*p) = NULL;  // NOLINT
+  EXPECT_TRUE(HasPrefix(Print(p),
+                        Print(sizeof(p)) + "-byte object "));
+}
+
+// Tests printing member function pointers.  Although they are called
+// pointers, they don't point to a location in the address space.
+// Their representation is implementation-defined.  Thus they will be
+// printed as raw bytes.
+TEST(PrintPointerTest, MemberFunctionPointer) {
+  EXPECT_TRUE(HasPrefix(Print(&Foo::MyMethod),
+                        Print(sizeof(&Foo::MyMethod)) + "-byte object "));
+  EXPECT_TRUE(
+      HasPrefix(Print(&Foo::MyVirtualMethod),
+                Print(sizeof((&Foo::MyVirtualMethod))) + "-byte object "));
+  int (Foo::*p)(char) = NULL;  // NOLINT
+  EXPECT_TRUE(HasPrefix(Print(p),
+                        Print(sizeof(p)) + "-byte object "));
+}
+
+// Tests printing C arrays.
+
+// The difference between this and Print() is that it ensures that the
+// argument is a reference to an array.
+template <typename T, size_t N>
+string PrintArrayHelper(T (&a)[N]) {
+  return Print(a);
+}
+
+// One-dimensional array.
+TEST(PrintArrayTest, OneDimensionalArray) {
+  int a[5] = { 1, 2, 3, 4, 5 };
+  EXPECT_EQ("{ 1, 2, 3, 4, 5 }", PrintArrayHelper(a));
+}
+
+// Two-dimensional array.
+TEST(PrintArrayTest, TwoDimensionalArray) {
+  int a[2][5] = {
+    { 1, 2, 3, 4, 5 },
+    { 6, 7, 8, 9, 0 }
+  };
+  EXPECT_EQ("{ { 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 0 } }", PrintArrayHelper(a));
+}
+
+// Array of const elements.
+TEST(PrintArrayTest, ConstArray) {
+  const bool a[1] = { false };
+  EXPECT_EQ("{ false }", PrintArrayHelper(a));
+}
+
+// Char array.
+TEST(PrintArrayTest, CharArray) {
+  // Array a contains '\0' in the middle and doesn't end with '\0'.
+  char a[3] = { 'H', '\0', 'i' };
+  EXPECT_EQ("\"H\\0i\"", PrintArrayHelper(a));
+}
+
+// Const char array.
+TEST(PrintArrayTest, ConstCharArray) {
+  const char a[4] = "\0Hi";
+  EXPECT_EQ("\"\\0Hi\\0\"", PrintArrayHelper(a));
+}
+
+// Array of objects.
+TEST(PrintArrayTest, ObjectArray) {
+  string a[3] = { "Hi", "Hello", "Ni hao" };
+  EXPECT_EQ("{ \"Hi\", \"Hello\", \"Ni hao\" }", PrintArrayHelper(a));
+}
+
+// Array with many elements.
+TEST(PrintArrayTest, BigArray) {
+  int a[100] = { 1, 2, 3 };
+  EXPECT_EQ("{ 1, 2, 3, 0, 0, 0, 0, 0, ..., 0, 0, 0, 0, 0, 0, 0, 0 }",
+            PrintArrayHelper(a));
+}
+
+// Tests printing ::string and ::std::string.
+
+#if GTEST_HAS_GLOBAL_STRING
+// ::string.
+TEST(PrintStringTest, StringInGlobalNamespace) {
+  const char s[] = "'\"?\\\a\b\f\n\0\r\t\v\x7F\xFF a";
+  const ::string str(s, sizeof(s));
+  EXPECT_EQ("\"'\\\"?\\\\\\a\\b\\f\\n\\0\\r\\t\\v\\x7F\\xFF a\\0\"",
+            Print(str));
+}
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+// ::std::string.
+TEST(PrintStringTest, StringInStdNamespace) {
+  const char s[] = "'\"?\\\a\b\f\n\0\r\t\v\x7F\xFF a";
+  const ::std::string str(s, sizeof(s));
+  EXPECT_EQ("\"'\\\"?\\\\\\a\\b\\f\\n\\0\\r\\t\\v\\x7F\\xFF a\\0\"",
+            Print(str));
+}
+
+TEST(PrintStringTest, StringAmbiguousHex) {
+  // "\x6BANANA" is ambiguous, it can be interpreted as starting with either of:
+  // '\x6', '\x6B', or '\x6BA'.
+
+  // a hex escaping sequence following by a decimal digit
+  EXPECT_EQ("\"0\\x12\" \"3\"", Print(::std::string("0\x12" "3")));
+  // a hex escaping sequence following by a hex digit (lower-case)
+  EXPECT_EQ("\"mm\\x6\" \"bananas\"", Print(::std::string("mm\x6" "bananas")));
+  // a hex escaping sequence following by a hex digit (upper-case)
+  EXPECT_EQ("\"NOM\\x6\" \"BANANA\"", Print(::std::string("NOM\x6" "BANANA")));
+  // a hex escaping sequence following by a non-xdigit
+  EXPECT_EQ("\"!\\x5-!\"", Print(::std::string("!\x5-!")));
+}
+
+// Tests printing ::wstring and ::std::wstring.
+
+#if GTEST_HAS_GLOBAL_WSTRING
+// ::wstring.
+TEST(PrintWideStringTest, StringInGlobalNamespace) {
+  const wchar_t s[] = L"'\"?\\\a\b\f\n\0\r\t\v\xD3\x576\x8D3\xC74D a";
+  const ::wstring str(s, sizeof(s)/sizeof(wchar_t));
+  EXPECT_EQ("L\"'\\\"?\\\\\\a\\b\\f\\n\\0\\r\\t\\v"
+            "\\xD3\\x576\\x8D3\\xC74D a\\0\"",
+            Print(str));
+}
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+#if GTEST_HAS_STD_WSTRING
+// ::std::wstring.
+TEST(PrintWideStringTest, StringInStdNamespace) {
+  const wchar_t s[] = L"'\"?\\\a\b\f\n\0\r\t\v\xD3\x576\x8D3\xC74D a";
+  const ::std::wstring str(s, sizeof(s)/sizeof(wchar_t));
+  EXPECT_EQ("L\"'\\\"?\\\\\\a\\b\\f\\n\\0\\r\\t\\v"
+            "\\xD3\\x576\\x8D3\\xC74D a\\0\"",
+            Print(str));
+}
+
+TEST(PrintWideStringTest, StringAmbiguousHex) {
+  // same for wide strings.
+  EXPECT_EQ("L\"0\\x12\" L\"3\"", Print(::std::wstring(L"0\x12" L"3")));
+  EXPECT_EQ("L\"mm\\x6\" L\"bananas\"",
+            Print(::std::wstring(L"mm\x6" L"bananas")));
+  EXPECT_EQ("L\"NOM\\x6\" L\"BANANA\"",
+            Print(::std::wstring(L"NOM\x6" L"BANANA")));
+  EXPECT_EQ("L\"!\\x5-!\"", Print(::std::wstring(L"!\x5-!")));
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+// Tests printing types that support generic streaming (i.e. streaming
+// to std::basic_ostream<Char, CharTraits> for any valid Char and
+// CharTraits types).
+
+// Tests printing a non-template type that supports generic streaming.
+
+class AllowsGenericStreaming {};
+
+template <typename Char, typename CharTraits>
+std::basic_ostream<Char, CharTraits>& operator<<(
+    std::basic_ostream<Char, CharTraits>& os,
+    const AllowsGenericStreaming& /* a */) {
+  return os << "AllowsGenericStreaming";
+}
+
+TEST(PrintTypeWithGenericStreamingTest, NonTemplateType) {
+  AllowsGenericStreaming a;
+  EXPECT_EQ("AllowsGenericStreaming", Print(a));
+}
+
+// Tests printing a template type that supports generic streaming.
+
+template <typename T>
+class AllowsGenericStreamingTemplate {};
+
+template <typename Char, typename CharTraits, typename T>
+std::basic_ostream<Char, CharTraits>& operator<<(
+    std::basic_ostream<Char, CharTraits>& os,
+    const AllowsGenericStreamingTemplate<T>& /* a */) {
+  return os << "AllowsGenericStreamingTemplate";
+}
+
+TEST(PrintTypeWithGenericStreamingTest, TemplateType) {
+  AllowsGenericStreamingTemplate<int> a;
+  EXPECT_EQ("AllowsGenericStreamingTemplate", Print(a));
+}
+
+// Tests printing a type that supports generic streaming and can be
+// implicitly converted to another printable type.
+
+template <typename T>
+class AllowsGenericStreamingAndImplicitConversionTemplate {
+ public:
+  operator bool() const { return false; }
+};
+
+template <typename Char, typename CharTraits, typename T>
+std::basic_ostream<Char, CharTraits>& operator<<(
+    std::basic_ostream<Char, CharTraits>& os,
+    const AllowsGenericStreamingAndImplicitConversionTemplate<T>& /* a */) {
+  return os << "AllowsGenericStreamingAndImplicitConversionTemplate";
+}
+
+TEST(PrintTypeWithGenericStreamingTest, TypeImplicitlyConvertible) {
+  AllowsGenericStreamingAndImplicitConversionTemplate<int> a;
+  EXPECT_EQ("AllowsGenericStreamingAndImplicitConversionTemplate", Print(a));
+}
+
+#if GTEST_HAS_STRING_PIECE_
+
+// Tests printing StringPiece.
+
+TEST(PrintStringPieceTest, SimpleStringPiece) {
+  const StringPiece sp = "Hello";
+  EXPECT_EQ("\"Hello\"", Print(sp));
+}
+
+TEST(PrintStringPieceTest, UnprintableCharacters) {
+  const char str[] = "NUL (\0) and \r\t";
+  const StringPiece sp(str, sizeof(str) - 1);
+  EXPECT_EQ("\"NUL (\\0) and \\r\\t\"", Print(sp));
+}
+
+#endif  // GTEST_HAS_STRING_PIECE_
+
+// Tests printing STL containers.
+
+TEST(PrintStlContainerTest, EmptyDeque) {
+  deque<char> empty;
+  EXPECT_EQ("{}", Print(empty));
+}
+
+TEST(PrintStlContainerTest, NonEmptyDeque) {
+  deque<int> non_empty;
+  non_empty.push_back(1);
+  non_empty.push_back(3);
+  EXPECT_EQ("{ 1, 3 }", Print(non_empty));
+}
+
+#if GTEST_HAS_HASH_MAP_
+
+TEST(PrintStlContainerTest, OneElementHashMap) {
+  hash_map<int, char> map1;
+  map1[1] = 'a';
+  EXPECT_EQ("{ (1, 'a' (97, 0x61)) }", Print(map1));
+}
+
+TEST(PrintStlContainerTest, HashMultiMap) {
+  hash_multimap<int, bool> map1;
+  map1.insert(make_pair(5, true));
+  map1.insert(make_pair(5, false));
+
+  // Elements of hash_multimap can be printed in any order.
+  const string result = Print(map1);
+  EXPECT_TRUE(result == "{ (5, true), (5, false) }" ||
+              result == "{ (5, false), (5, true) }")
+                  << " where Print(map1) returns \"" << result << "\".";
+}
+
+#endif  // GTEST_HAS_HASH_MAP_
+
+#if GTEST_HAS_HASH_SET_
+
+TEST(PrintStlContainerTest, HashSet) {
+  hash_set<string> set1;
+  set1.insert("hello");
+  EXPECT_EQ("{ \"hello\" }", Print(set1));
+}
+
+TEST(PrintStlContainerTest, HashMultiSet) {
+  const int kSize = 5;
+  int a[kSize] = { 1, 1, 2, 5, 1 };
+  hash_multiset<int> set1(a, a + kSize);
+
+  // Elements of hash_multiset can be printed in any order.
+  const string result = Print(set1);
+  const string expected_pattern = "{ d, d, d, d, d }";  // d means a digit.
+
+  // Verifies the result matches the expected pattern; also extracts
+  // the numbers in the result.
+  ASSERT_EQ(expected_pattern.length(), result.length());
+  std::vector<int> numbers;
+  for (size_t i = 0; i != result.length(); i++) {
+    if (expected_pattern[i] == 'd') {
+      ASSERT_TRUE(isdigit(static_cast<unsigned char>(result[i])) != 0);
+      numbers.push_back(result[i] - '0');
+    } else {
+      EXPECT_EQ(expected_pattern[i], result[i]) << " where result is "
+                                                << result;
+    }
+  }
+
+  // Makes sure the result contains the right numbers.
+  std::sort(numbers.begin(), numbers.end());
+  std::sort(a, a + kSize);
+  EXPECT_TRUE(std::equal(a, a + kSize, numbers.begin()));
+}
+
+#endif  // GTEST_HAS_HASH_SET_
+
+TEST(PrintStlContainerTest, List) {
+  const string a[] = {
+    "hello",
+    "world"
+  };
+  const list<string> strings(a, a + 2);
+  EXPECT_EQ("{ \"hello\", \"world\" }", Print(strings));
+}
+
+TEST(PrintStlContainerTest, Map) {
+  map<int, bool> map1;
+  map1[1] = true;
+  map1[5] = false;
+  map1[3] = true;
+  EXPECT_EQ("{ (1, true), (3, true), (5, false) }", Print(map1));
+}
+
+TEST(PrintStlContainerTest, MultiMap) {
+  multimap<bool, int> map1;
+  // The make_pair template function would deduce the type as
+  // pair<bool, int> here, and since the key part in a multimap has to
+  // be constant, without a templated ctor in the pair class (as in
+  // libCstd on Solaris), make_pair call would fail to compile as no
+  // implicit conversion is found.  Thus explicit typename is used
+  // here instead.
+  map1.insert(pair<const bool, int>(true, 0));
+  map1.insert(pair<const bool, int>(true, 1));
+  map1.insert(pair<const bool, int>(false, 2));
+  EXPECT_EQ("{ (false, 2), (true, 0), (true, 1) }", Print(map1));
+}
+
+TEST(PrintStlContainerTest, Set) {
+  const unsigned int a[] = { 3, 0, 5 };
+  set<unsigned int> set1(a, a + 3);
+  EXPECT_EQ("{ 0, 3, 5 }", Print(set1));
+}
+
+TEST(PrintStlContainerTest, MultiSet) {
+  const int a[] = { 1, 1, 2, 5, 1 };
+  multiset<int> set1(a, a + 5);
+  EXPECT_EQ("{ 1, 1, 1, 2, 5 }", Print(set1));
+}
+
+TEST(PrintStlContainerTest, Pair) {
+  pair<const bool, int> p(true, 5);
+  EXPECT_EQ("(true, 5)", Print(p));
+}
+
+TEST(PrintStlContainerTest, Vector) {
+  vector<int> v;
+  v.push_back(1);
+  v.push_back(2);
+  EXPECT_EQ("{ 1, 2 }", Print(v));
+}
+
+TEST(PrintStlContainerTest, LongSequence) {
+  const int a[100] = { 1, 2, 3 };
+  const vector<int> v(a, a + 100);
+  EXPECT_EQ("{ 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "
+            "0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... }", Print(v));
+}
+
+TEST(PrintStlContainerTest, NestedContainer) {
+  const int a1[] = { 1, 2 };
+  const int a2[] = { 3, 4, 5 };
+  const list<int> l1(a1, a1 + 2);
+  const list<int> l2(a2, a2 + 3);
+
+  vector<list<int> > v;
+  v.push_back(l1);
+  v.push_back(l2);
+  EXPECT_EQ("{ { 1, 2 }, { 3, 4, 5 } }", Print(v));
+}
+
+TEST(PrintStlContainerTest, OneDimensionalNativeArray) {
+  const int a[3] = { 1, 2, 3 };
+  NativeArray<int> b(a, 3, kReference);
+  EXPECT_EQ("{ 1, 2, 3 }", Print(b));
+}
+
+TEST(PrintStlContainerTest, TwoDimensionalNativeArray) {
+  const int a[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
+  NativeArray<int[3]> b(a, 2, kReference);
+  EXPECT_EQ("{ { 1, 2, 3 }, { 4, 5, 6 } }", Print(b));
+}
+
+// Tests that a class named iterator isn't treated as a container.
+
+struct iterator {
+  char x;
+};
+
+TEST(PrintStlContainerTest, Iterator) {
+  iterator it = {};
+  EXPECT_EQ("1-byte object <00>", Print(it));
+}
+
+// Tests that a class named const_iterator isn't treated as a container.
+
+struct const_iterator {
+  char x;
+};
+
+TEST(PrintStlContainerTest, ConstIterator) {
+  const_iterator it = {};
+  EXPECT_EQ("1-byte object <00>", Print(it));
+}
+
+#if GTEST_HAS_TR1_TUPLE
+// Tests printing tuples.
+
+// Tuples of various arities.
+TEST(PrintTupleTest, VariousSizes) {
+  tuple<> t0;
+  EXPECT_EQ("()", Print(t0));
+
+  tuple<int> t1(5);
+  EXPECT_EQ("(5)", Print(t1));
+
+  tuple<char, bool> t2('a', true);
+  EXPECT_EQ("('a' (97, 0x61), true)", Print(t2));
+
+  tuple<bool, int, int> t3(false, 2, 3);
+  EXPECT_EQ("(false, 2, 3)", Print(t3));
+
+  tuple<bool, int, int, int> t4(false, 2, 3, 4);
+  EXPECT_EQ("(false, 2, 3, 4)", Print(t4));
+
+  tuple<bool, int, int, int, bool> t5(false, 2, 3, 4, true);
+  EXPECT_EQ("(false, 2, 3, 4, true)", Print(t5));
+
+  tuple<bool, int, int, int, bool, int> t6(false, 2, 3, 4, true, 6);
+  EXPECT_EQ("(false, 2, 3, 4, true, 6)", Print(t6));
+
+  tuple<bool, int, int, int, bool, int, int> t7(false, 2, 3, 4, true, 6, 7);
+  EXPECT_EQ("(false, 2, 3, 4, true, 6, 7)", Print(t7));
+
+  tuple<bool, int, int, int, bool, int, int, bool> t8(
+      false, 2, 3, 4, true, 6, 7, true);
+  EXPECT_EQ("(false, 2, 3, 4, true, 6, 7, true)", Print(t8));
+
+  tuple<bool, int, int, int, bool, int, int, bool, int> t9(
+      false, 2, 3, 4, true, 6, 7, true, 9);
+  EXPECT_EQ("(false, 2, 3, 4, true, 6, 7, true, 9)", Print(t9));
+
+  const char* const str = "8";
+  tuple<bool, char, short, testing::internal::Int32,  // NOLINT
+      testing::internal::Int64, float, double, const char*, void*, string>
+      t10(false, 'a', 3, 4, 5, 1.5F, -2.5, str, NULL, "10");
+  EXPECT_EQ("(false, 'a' (97, 0x61), 3, 4, 5, 1.5, -2.5, " + PrintPointer(str) +
+            " pointing to \"8\", NULL, \"10\")",
+            Print(t10));
+}
+
+// Nested tuples.
+TEST(PrintTupleTest, NestedTuple) {
+  tuple<tuple<int, bool>, char> nested(make_tuple(5, true), 'a');
+  EXPECT_EQ("((5, true), 'a' (97, 0x61))", Print(nested));
+}
+
+#endif  // GTEST_HAS_TR1_TUPLE
+
+// Tests printing user-defined unprintable types.
+
+// Unprintable types in the global namespace.
+TEST(PrintUnprintableTypeTest, InGlobalNamespace) {
+  EXPECT_EQ("1-byte object <00>",
+            Print(UnprintableTemplateInGlobal<char>()));
+}
+
+// Unprintable types in a user namespace.
+TEST(PrintUnprintableTypeTest, InUserNamespace) {
+  EXPECT_EQ("16-byte object <EF-12 00-00 34-AB 00-00 00-00 00-00 00-00 00-00>",
+            Print(::foo::UnprintableInFoo()));
+}
+
+// Unprintable types are that too big to be printed completely.
+
+struct Big {
+  Big() { memset(array, 0, sizeof(array)); }
+  char array[257];
+};
+
+TEST(PrintUnpritableTypeTest, BigObject) {
+  EXPECT_EQ("257-byte object <00-00 00-00 00-00 00-00 00-00 00-00 "
+            "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 "
+            "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 "
+            "00-00 00-00 00-00 00-00 00-00 00-00 ... 00-00 00-00 00-00 "
+            "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 "
+            "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 "
+            "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00>",
+            Print(Big()));
+}
+
+// Tests printing user-defined streamable types.
+
+// Streamable types in the global namespace.
+TEST(PrintStreamableTypeTest, InGlobalNamespace) {
+  StreamableInGlobal x;
+  EXPECT_EQ("StreamableInGlobal", Print(x));
+  EXPECT_EQ("StreamableInGlobal*", Print(&x));
+}
+
+// Printable template types in a user namespace.
+TEST(PrintStreamableTypeTest, TemplateTypeInUserNamespace) {
+  EXPECT_EQ("StreamableTemplateInFoo: 0",
+            Print(::foo::StreamableTemplateInFoo<int>()));
+}
+
+// Tests printing user-defined types that have a PrintTo() function.
+TEST(PrintPrintableTypeTest, InUserNamespace) {
+  EXPECT_EQ("PrintableViaPrintTo: 0",
+            Print(::foo::PrintableViaPrintTo()));
+}
+
+// Tests printing a pointer to a user-defined type that has a <<
+// operator for its pointer.
+TEST(PrintPrintableTypeTest, PointerInUserNamespace) {
+  ::foo::PointerPrintable x;
+  EXPECT_EQ("PointerPrintable*", Print(&x));
+}
+
+// Tests printing user-defined class template that have a PrintTo() function.
+TEST(PrintPrintableTypeTest, TemplateInUserNamespace) {
+  EXPECT_EQ("PrintableViaPrintToTemplate: 5",
+            Print(::foo::PrintableViaPrintToTemplate<int>(5)));
+}
+
+#if GTEST_HAS_PROTOBUF_
+
+// Tests printing a protocol message.
+TEST(PrintProtocolMessageTest, PrintsShortDebugString) {
+  testing::internal::TestMessage msg;
+  msg.set_member("yes");
+  EXPECT_EQ("<member:\"yes\">", Print(msg));
+}
+
+// Tests printing a short proto2 message.
+TEST(PrintProto2MessageTest, PrintsShortDebugStringWhenItIsShort) {
+  testing::internal::FooMessage msg;
+  msg.set_int_field(2);
+  msg.set_string_field("hello");
+  EXPECT_PRED2(RE::FullMatch, Print(msg),
+               "<int_field:\\s*2\\s+string_field:\\s*\"hello\">");
+}
+
+// Tests printing a long proto2 message.
+TEST(PrintProto2MessageTest, PrintsDebugStringWhenItIsLong) {
+  testing::internal::FooMessage msg;
+  msg.set_int_field(2);
+  msg.set_string_field("hello");
+  msg.add_names("peter");
+  msg.add_names("paul");
+  msg.add_names("mary");
+  EXPECT_PRED2(RE::FullMatch, Print(msg),
+               "<\n"
+               "int_field:\\s*2\n"
+               "string_field:\\s*\"hello\"\n"
+               "names:\\s*\"peter\"\n"
+               "names:\\s*\"paul\"\n"
+               "names:\\s*\"mary\"\n"
+               ">");
+}
+
+#endif  // GTEST_HAS_PROTOBUF_
+
+// Tests that the universal printer prints both the address and the
+// value of a reference.
+TEST(PrintReferenceTest, PrintsAddressAndValue) {
+  int n = 5;
+  EXPECT_EQ("@" + PrintPointer(&n) + " 5", PrintByRef(n));
+
+  int a[2][3] = {
+    { 0, 1, 2 },
+    { 3, 4, 5 }
+  };
+  EXPECT_EQ("@" + PrintPointer(a) + " { { 0, 1, 2 }, { 3, 4, 5 } }",
+            PrintByRef(a));
+
+  const ::foo::UnprintableInFoo x;
+  EXPECT_EQ("@" + PrintPointer(&x) + " 16-byte object "
+            "<EF-12 00-00 34-AB 00-00 00-00 00-00 00-00 00-00>",
+            PrintByRef(x));
+}
+
+// Tests that the universal printer prints a function pointer passed by
+// reference.
+TEST(PrintReferenceTest, HandlesFunctionPointer) {
+  void (*fp)(int n) = &MyFunction;
+  const string fp_pointer_string =
+      PrintPointer(reinterpret_cast<const void*>(&fp));
+  // We cannot directly cast &MyFunction to const void* because the
+  // standard disallows casting between pointers to functions and
+  // pointers to objects, and some compilers (e.g. GCC 3.4) enforce
+  // this limitation.
+  const string fp_string = PrintPointer(reinterpret_cast<const void*>(
+      reinterpret_cast<internal::BiggestInt>(fp)));
+  EXPECT_EQ("@" + fp_pointer_string + " " + fp_string,
+            PrintByRef(fp));
+}
+
+// Tests that the universal printer prints a member function pointer
+// passed by reference.
+TEST(PrintReferenceTest, HandlesMemberFunctionPointer) {
+  int (Foo::*p)(char ch) = &Foo::MyMethod;
+  EXPECT_TRUE(HasPrefix(
+      PrintByRef(p),
+      "@" + PrintPointer(reinterpret_cast<const void*>(&p)) + " " +
+          Print(sizeof(p)) + "-byte object "));
+
+  char (Foo::*p2)(int n) = &Foo::MyVirtualMethod;
+  EXPECT_TRUE(HasPrefix(
+      PrintByRef(p2),
+      "@" + PrintPointer(reinterpret_cast<const void*>(&p2)) + " " +
+          Print(sizeof(p2)) + "-byte object "));
+}
+
+// Tests that the universal printer prints a member variable pointer
+// passed by reference.
+TEST(PrintReferenceTest, HandlesMemberVariablePointer) {
+  int (Foo::*p) = &Foo::value;  // NOLINT
+  EXPECT_TRUE(HasPrefix(
+      PrintByRef(p),
+      "@" + PrintPointer(&p) + " " + Print(sizeof(p)) + "-byte object "));
+}
+
+// Useful for testing PrintToString().  We cannot use EXPECT_EQ()
+// there as its implementation uses PrintToString().  The caller must
+// ensure that 'value' has no side effect.
+#define EXPECT_PRINT_TO_STRING_(value, expected_string)         \
+  EXPECT_TRUE(PrintToString(value) == (expected_string))        \
+      << " where " #value " prints as " << (PrintToString(value))
+
+TEST(PrintToStringTest, WorksForScalar) {
+  EXPECT_PRINT_TO_STRING_(123, "123");
+}
+
+TEST(PrintToStringTest, WorksForPointerToConstChar) {
+  const char* p = "hello";
+  EXPECT_PRINT_TO_STRING_(p, "\"hello\"");
+}
+
+TEST(PrintToStringTest, WorksForPointerToNonConstChar) {
+  char s[] = "hello";
+  char* p = s;
+  EXPECT_PRINT_TO_STRING_(p, "\"hello\"");
+}
+
+TEST(PrintToStringTest, WorksForArray) {
+  int n[3] = { 1, 2, 3 };
+  EXPECT_PRINT_TO_STRING_(n, "{ 1, 2, 3 }");
+}
+
+#undef EXPECT_PRINT_TO_STRING_
+
+TEST(UniversalTersePrintTest, WorksForNonReference) {
+  ::std::stringstream ss;
+  UniversalTersePrint(123, &ss);
+  EXPECT_EQ("123", ss.str());
+}
+
+TEST(UniversalTersePrintTest, WorksForReference) {
+  const int& n = 123;
+  ::std::stringstream ss;
+  UniversalTersePrint(n, &ss);
+  EXPECT_EQ("123", ss.str());
+}
+
+TEST(UniversalTersePrintTest, WorksForCString) {
+  const char* s1 = "abc";
+  ::std::stringstream ss1;
+  UniversalTersePrint(s1, &ss1);
+  EXPECT_EQ("\"abc\"", ss1.str());
+
+  char* s2 = const_cast<char*>(s1);
+  ::std::stringstream ss2;
+  UniversalTersePrint(s2, &ss2);
+  EXPECT_EQ("\"abc\"", ss2.str());
+
+  const char* s3 = NULL;
+  ::std::stringstream ss3;
+  UniversalTersePrint(s3, &ss3);
+  EXPECT_EQ("NULL", ss3.str());
+}
+
+TEST(UniversalPrintTest, WorksForNonReference) {
+  ::std::stringstream ss;
+  UniversalPrint(123, &ss);
+  EXPECT_EQ("123", ss.str());
+}
+
+TEST(UniversalPrintTest, WorksForReference) {
+  const int& n = 123;
+  ::std::stringstream ss;
+  UniversalPrint(n, &ss);
+  EXPECT_EQ("123", ss.str());
+}
+
+TEST(UniversalPrintTest, WorksForCString) {
+  const char* s1 = "abc";
+  ::std::stringstream ss1;
+  UniversalPrint(s1, &ss1);
+  EXPECT_EQ(PrintPointer(s1) + " pointing to \"abc\"", string(ss1.str()));
+
+  char* s2 = const_cast<char*>(s1);
+  ::std::stringstream ss2;
+  UniversalPrint(s2, &ss2);
+  EXPECT_EQ(PrintPointer(s2) + " pointing to \"abc\"", string(ss2.str()));
+
+  const char* s3 = NULL;
+  ::std::stringstream ss3;
+  UniversalPrint(s3, &ss3);
+  EXPECT_EQ("NULL", ss3.str());
+}
+
+
+#if GTEST_HAS_TR1_TUPLE
+
+TEST(UniversalTersePrintTupleFieldsToStringsTest, PrintsEmptyTuple) {
+  Strings result = UniversalTersePrintTupleFieldsToStrings(make_tuple());
+  EXPECT_EQ(0u, result.size());
+}
+
+TEST(UniversalTersePrintTupleFieldsToStringsTest, PrintsOneTuple) {
+  Strings result = UniversalTersePrintTupleFieldsToStrings(make_tuple(1));
+  ASSERT_EQ(1u, result.size());
+  EXPECT_EQ("1", result[0]);
+}
+
+TEST(UniversalTersePrintTupleFieldsToStringsTest, PrintsTwoTuple) {
+  Strings result = UniversalTersePrintTupleFieldsToStrings(make_tuple(1, 'a'));
+  ASSERT_EQ(2u, result.size());
+  EXPECT_EQ("1", result[0]);
+  EXPECT_EQ("'a' (97, 0x61)", result[1]);
+}
+
+TEST(UniversalTersePrintTupleFieldsToStringsTest, PrintsTersely) {
+  const int n = 1;
+  Strings result = UniversalTersePrintTupleFieldsToStrings(
+      tuple<const int&, const char*>(n, "a"));
+  ASSERT_EQ(2u, result.size());
+  EXPECT_EQ("1", result[0]);
+  EXPECT_EQ("\"a\"", result[1]);
+}
+
+#endif  // GTEST_HAS_TR1_TUPLE
+
+}  // namespace gtest_printers_test
+}  // namespace testing
diff --git a/third_party/googletest/src/test/gtest-test-part_test.cc b/third_party/googletest/src/test/gtest-test-part_test.cc
new file mode 100644 (file)
index 0000000..ca8ba93
--- /dev/null
@@ -0,0 +1,208 @@
+// Copyright 2008 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: mheule@google.com (Markus Heule)
+//
+
+#include "gtest/gtest-test-part.h"
+
+#include "gtest/gtest.h"
+
+using testing::Message;
+using testing::Test;
+using testing::TestPartResult;
+using testing::TestPartResultArray;
+
+namespace {
+
+// Tests the TestPartResult class.
+
+// The test fixture for testing TestPartResult.
+class TestPartResultTest : public Test {
+ protected:
+  TestPartResultTest()
+      : r1_(TestPartResult::kSuccess, "foo/bar.cc", 10, "Success!"),
+        r2_(TestPartResult::kNonFatalFailure, "foo/bar.cc", -1, "Failure!"),
+        r3_(TestPartResult::kFatalFailure, NULL, -1, "Failure!") {}
+
+  TestPartResult r1_, r2_, r3_;
+};
+
+
+TEST_F(TestPartResultTest, ConstructorWorks) {
+  Message message;
+  message << "something is terribly wrong";
+  message << static_cast<const char*>(testing::internal::kStackTraceMarker);
+  message << "some unimportant stack trace";
+
+  const TestPartResult result(TestPartResult::kNonFatalFailure,
+                              "some_file.cc",
+                              42,
+                              message.GetString().c_str());
+
+  EXPECT_EQ(TestPartResult::kNonFatalFailure, result.type());
+  EXPECT_STREQ("some_file.cc", result.file_name());
+  EXPECT_EQ(42, result.line_number());
+  EXPECT_STREQ(message.GetString().c_str(), result.message());
+  EXPECT_STREQ("something is terribly wrong", result.summary());
+}
+
+TEST_F(TestPartResultTest, ResultAccessorsWork) {
+  const TestPartResult success(TestPartResult::kSuccess,
+                               "file.cc",
+                               42,
+                               "message");
+  EXPECT_TRUE(success.passed());
+  EXPECT_FALSE(success.failed());
+  EXPECT_FALSE(success.nonfatally_failed());
+  EXPECT_FALSE(success.fatally_failed());
+
+  const TestPartResult nonfatal_failure(TestPartResult::kNonFatalFailure,
+                                        "file.cc",
+                                        42,
+                                        "message");
+  EXPECT_FALSE(nonfatal_failure.passed());
+  EXPECT_TRUE(nonfatal_failure.failed());
+  EXPECT_TRUE(nonfatal_failure.nonfatally_failed());
+  EXPECT_FALSE(nonfatal_failure.fatally_failed());
+
+  const TestPartResult fatal_failure(TestPartResult::kFatalFailure,
+                                     "file.cc",
+                                     42,
+                                     "message");
+  EXPECT_FALSE(fatal_failure.passed());
+  EXPECT_TRUE(fatal_failure.failed());
+  EXPECT_FALSE(fatal_failure.nonfatally_failed());
+  EXPECT_TRUE(fatal_failure.fatally_failed());
+}
+
+// Tests TestPartResult::type().
+TEST_F(TestPartResultTest, type) {
+  EXPECT_EQ(TestPartResult::kSuccess, r1_.type());
+  EXPECT_EQ(TestPartResult::kNonFatalFailure, r2_.type());
+  EXPECT_EQ(TestPartResult::kFatalFailure, r3_.type());
+}
+
+// Tests TestPartResult::file_name().
+TEST_F(TestPartResultTest, file_name) {
+  EXPECT_STREQ("foo/bar.cc", r1_.file_name());
+  EXPECT_STREQ(NULL, r3_.file_name());
+}
+
+// Tests TestPartResult::line_number().
+TEST_F(TestPartResultTest, line_number) {
+  EXPECT_EQ(10, r1_.line_number());
+  EXPECT_EQ(-1, r2_.line_number());
+}
+
+// Tests TestPartResult::message().
+TEST_F(TestPartResultTest, message) {
+  EXPECT_STREQ("Success!", r1_.message());
+}
+
+// Tests TestPartResult::passed().
+TEST_F(TestPartResultTest, Passed) {
+  EXPECT_TRUE(r1_.passed());
+  EXPECT_FALSE(r2_.passed());
+  EXPECT_FALSE(r3_.passed());
+}
+
+// Tests TestPartResult::failed().
+TEST_F(TestPartResultTest, Failed) {
+  EXPECT_FALSE(r1_.failed());
+  EXPECT_TRUE(r2_.failed());
+  EXPECT_TRUE(r3_.failed());
+}
+
+// Tests TestPartResult::fatally_failed().
+TEST_F(TestPartResultTest, FatallyFailed) {
+  EXPECT_FALSE(r1_.fatally_failed());
+  EXPECT_FALSE(r2_.fatally_failed());
+  EXPECT_TRUE(r3_.fatally_failed());
+}
+
+// Tests TestPartResult::nonfatally_failed().
+TEST_F(TestPartResultTest, NonfatallyFailed) {
+  EXPECT_FALSE(r1_.nonfatally_failed());
+  EXPECT_TRUE(r2_.nonfatally_failed());
+  EXPECT_FALSE(r3_.nonfatally_failed());
+}
+
+// Tests the TestPartResultArray class.
+
+class TestPartResultArrayTest : public Test {
+ protected:
+  TestPartResultArrayTest()
+      : r1_(TestPartResult::kNonFatalFailure, "foo/bar.cc", -1, "Failure 1"),
+        r2_(TestPartResult::kFatalFailure, "foo/bar.cc", -1, "Failure 2") {}
+
+  const TestPartResult r1_, r2_;
+};
+
+// Tests that TestPartResultArray initially has size 0.
+TEST_F(TestPartResultArrayTest, InitialSizeIsZero) {
+  TestPartResultArray results;
+  EXPECT_EQ(0, results.size());
+}
+
+// Tests that TestPartResultArray contains the given TestPartResult
+// after one Append() operation.
+TEST_F(TestPartResultArrayTest, ContainsGivenResultAfterAppend) {
+  TestPartResultArray results;
+  results.Append(r1_);
+  EXPECT_EQ(1, results.size());
+  EXPECT_STREQ("Failure 1", results.GetTestPartResult(0).message());
+}
+
+// Tests that TestPartResultArray contains the given TestPartResults
+// after two Append() operations.
+TEST_F(TestPartResultArrayTest, ContainsGivenResultsAfterTwoAppends) {
+  TestPartResultArray results;
+  results.Append(r1_);
+  results.Append(r2_);
+  EXPECT_EQ(2, results.size());
+  EXPECT_STREQ("Failure 1", results.GetTestPartResult(0).message());
+  EXPECT_STREQ("Failure 2", results.GetTestPartResult(1).message());
+}
+
+typedef TestPartResultArrayTest TestPartResultArrayDeathTest;
+
+// Tests that the program dies when GetTestPartResult() is called with
+// an invalid index.
+TEST_F(TestPartResultArrayDeathTest, DiesWhenIndexIsOutOfBound) {
+  TestPartResultArray results;
+  results.Append(r1_);
+
+  EXPECT_DEATH_IF_SUPPORTED(results.GetTestPartResult(-1), "");
+  EXPECT_DEATH_IF_SUPPORTED(results.GetTestPartResult(1), "");
+}
+
+// TODO(mheule@google.com): Add a test for the class HasNewFatalFailureHelper.
+
+}  // namespace
diff --git a/third_party/googletest/src/test/gtest-tuple_test.cc b/third_party/googletest/src/test/gtest-tuple_test.cc
new file mode 100644 (file)
index 0000000..bfaa3e0
--- /dev/null
@@ -0,0 +1,320 @@
+// Copyright 2007, 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: wan@google.com (Zhanyong Wan)
+
+#include "gtest/internal/gtest-tuple.h"
+#include <utility>
+#include "gtest/gtest.h"
+
+namespace {
+
+using ::std::tr1::get;
+using ::std::tr1::make_tuple;
+using ::std::tr1::tuple;
+using ::std::tr1::tuple_element;
+using ::std::tr1::tuple_size;
+using ::testing::StaticAssertTypeEq;
+
+// Tests that tuple_element<K, tuple<T0, T1, ..., TN> >::type returns TK.
+TEST(tuple_element_Test, ReturnsElementType) {
+  StaticAssertTypeEq<int, tuple_element<0, tuple<int, char> >::type>();
+  StaticAssertTypeEq<int&, tuple_element<1, tuple<double, int&> >::type>();
+  StaticAssertTypeEq<bool, tuple_element<2, tuple<double, int, bool> >::type>();
+}
+
+// Tests that tuple_size<T>::value gives the number of fields in tuple
+// type T.
+TEST(tuple_size_Test, ReturnsNumberOfFields) {
+  EXPECT_EQ(0, +tuple_size<tuple<> >::value);
+  EXPECT_EQ(1, +tuple_size<tuple<void*> >::value);
+  EXPECT_EQ(1, +tuple_size<tuple<char> >::value);
+  EXPECT_EQ(1, +(tuple_size<tuple<tuple<int, double> > >::value));
+  EXPECT_EQ(2, +(tuple_size<tuple<int&, const char> >::value));
+  EXPECT_EQ(3, +(tuple_size<tuple<char*, void, const bool&> >::value));
+}
+
+// Tests comparing a tuple with itself.
+TEST(ComparisonTest, ComparesWithSelf) {
+  const tuple<int, char, bool> a(5, 'a', false);
+
+  EXPECT_TRUE(a == a);
+  EXPECT_FALSE(a != a);
+}
+
+// Tests comparing two tuples with the same value.
+TEST(ComparisonTest, ComparesEqualTuples) {
+  const tuple<int, bool> a(5, true), b(5, true);
+
+  EXPECT_TRUE(a == b);
+  EXPECT_FALSE(a != b);
+}
+
+// Tests comparing two different tuples that have no reference fields.
+TEST(ComparisonTest, ComparesUnequalTuplesWithoutReferenceFields) {
+  typedef tuple<const int, char> FooTuple;
+
+  const FooTuple a(0, 'x');
+  const FooTuple b(1, 'a');
+
+  EXPECT_TRUE(a != b);
+  EXPECT_FALSE(a == b);
+
+  const FooTuple c(1, 'b');
+
+  EXPECT_TRUE(b != c);
+  EXPECT_FALSE(b == c);
+}
+
+// Tests comparing two different tuples that have reference fields.
+TEST(ComparisonTest, ComparesUnequalTuplesWithReferenceFields) {
+  typedef tuple<int&, const char&> FooTuple;
+
+  int i = 5;
+  const char ch = 'a';
+  const FooTuple a(i, ch);
+
+  int j = 6;
+  const FooTuple b(j, ch);
+
+  EXPECT_TRUE(a != b);
+  EXPECT_FALSE(a == b);
+
+  j = 5;
+  const char ch2 = 'b';
+  const FooTuple c(j, ch2);
+
+  EXPECT_TRUE(b != c);
+  EXPECT_FALSE(b == c);
+}
+
+// Tests that a tuple field with a reference type is an alias of the
+// variable it's supposed to reference.
+TEST(ReferenceFieldTest, IsAliasOfReferencedVariable) {
+  int n = 0;
+  tuple<bool, int&> t(true, n);
+
+  n = 1;
+  EXPECT_EQ(n, get<1>(t))
+      << "Changing a underlying variable should update the reference field.";
+
+  // Makes sure that the implementation doesn't do anything funny with
+  // the & operator for the return type of get<>().
+  EXPECT_EQ(&n, &(get<1>(t)))
+      << "The address of a reference field should equal the address of "
+      << "the underlying variable.";
+
+  get<1>(t) = 2;
+  EXPECT_EQ(2, n)
+      << "Changing a reference field should update the underlying variable.";
+}
+
+// Tests that tuple's default constructor default initializes each field.
+// This test needs to compile without generating warnings.
+TEST(TupleConstructorTest, DefaultConstructorDefaultInitializesEachField) {
+  // The TR1 report requires that tuple's default constructor default
+  // initializes each field, even if it's a primitive type.  If the
+  // implementation forgets to do this, this test will catch it by
+  // generating warnings about using uninitialized variables (assuming
+  // a decent compiler).
+
+  tuple<> empty;
+
+  tuple<int> a1, b1;
+  b1 = a1;
+  EXPECT_EQ(0, get<0>(b1));
+
+  tuple<int, double> a2, b2;
+  b2 = a2;
+  EXPECT_EQ(0, get<0>(b2));
+  EXPECT_EQ(0.0, get<1>(b2));
+
+  tuple<double, char, bool*> a3, b3;
+  b3 = a3;
+  EXPECT_EQ(0.0, get<0>(b3));
+  EXPECT_EQ('\0', get<1>(b3));
+  EXPECT_TRUE(get<2>(b3) == NULL);
+
+  tuple<int, int, int, int, int, int, int, int, int, int> a10, b10;
+  b10 = a10;
+  EXPECT_EQ(0, get<0>(b10));
+  EXPECT_EQ(0, get<1>(b10));
+  EXPECT_EQ(0, get<2>(b10));
+  EXPECT_EQ(0, get<3>(b10));
+  EXPECT_EQ(0, get<4>(b10));
+  EXPECT_EQ(0, get<5>(b10));
+  EXPECT_EQ(0, get<6>(b10));
+  EXPECT_EQ(0, get<7>(b10));
+  EXPECT_EQ(0, get<8>(b10));
+  EXPECT_EQ(0, get<9>(b10));
+}
+
+// Tests constructing a tuple from its fields.
+TEST(TupleConstructorTest, ConstructsFromFields) {
+  int n = 1;
+  // Reference field.
+  tuple<int&> a(n);
+  EXPECT_EQ(&n, &(get<0>(a)));
+
+  // Non-reference fields.
+  tuple<int, char> b(5, 'a');
+  EXPECT_EQ(5, get<0>(b));
+  EXPECT_EQ('a', get<1>(b));
+
+  // Const reference field.
+  const int m = 2;
+  tuple<bool, const int&> c(true, m);
+  EXPECT_TRUE(get<0>(c));
+  EXPECT_EQ(&m, &(get<1>(c)));
+}
+
+// Tests tuple's copy constructor.
+TEST(TupleConstructorTest, CopyConstructor) {
+  tuple<double, bool> a(0.0, true);
+  tuple<double, bool> b(a);
+
+  EXPECT_DOUBLE_EQ(0.0, get<0>(b));
+  EXPECT_TRUE(get<1>(b));
+}
+
+// Tests constructing a tuple from another tuple that has a compatible
+// but different type.
+TEST(TupleConstructorTest, ConstructsFromDifferentTupleType) {
+  tuple<int, int, char> a(0, 1, 'a');
+  tuple<double, long, int> b(a);
+
+  EXPECT_DOUBLE_EQ(0.0, get<0>(b));
+  EXPECT_EQ(1, get<1>(b));
+  EXPECT_EQ('a', get<2>(b));
+}
+
+// Tests constructing a 2-tuple from an std::pair.
+TEST(TupleConstructorTest, ConstructsFromPair) {
+  ::std::pair<int, char> a(1, 'a');
+  tuple<int, char> b(a);
+  tuple<int, const char&> c(a);
+}
+
+// Tests assigning a tuple to another tuple with the same type.
+TEST(TupleAssignmentTest, AssignsToSameTupleType) {
+  const tuple<int, long> a(5, 7L);
+  tuple<int, long> b;
+  b = a;
+  EXPECT_EQ(5, get<0>(b));
+  EXPECT_EQ(7L, get<1>(b));
+}
+
+// Tests assigning a tuple to another tuple with a different but
+// compatible type.
+TEST(TupleAssignmentTest, AssignsToDifferentTupleType) {
+  const tuple<int, long, bool> a(1, 7L, true);
+  tuple<long, int, bool> b;
+  b = a;
+  EXPECT_EQ(1L, get<0>(b));
+  EXPECT_EQ(7, get<1>(b));
+  EXPECT_TRUE(get<2>(b));
+}
+
+// Tests assigning an std::pair to a 2-tuple.
+TEST(TupleAssignmentTest, AssignsFromPair) {
+  const ::std::pair<int, bool> a(5, true);
+  tuple<int, bool> b;
+  b = a;
+  EXPECT_EQ(5, get<0>(b));
+  EXPECT_TRUE(get<1>(b));
+
+  tuple<long, bool> c;
+  c = a;
+  EXPECT_EQ(5L, get<0>(c));
+  EXPECT_TRUE(get<1>(c));
+}
+
+// A fixture for testing big tuples.
+class BigTupleTest : public testing::Test {
+ protected:
+  typedef tuple<int, int, int, int, int, int, int, int, int, int> BigTuple;
+
+  BigTupleTest() :
+      a_(1, 0, 0, 0, 0, 0, 0, 0, 0, 2),
+      b_(1, 0, 0, 0, 0, 0, 0, 0, 0, 3) {}
+
+  BigTuple a_, b_;
+};
+
+// Tests constructing big tuples.
+TEST_F(BigTupleTest, Construction) {
+  BigTuple a;
+  BigTuple b(b_);
+}
+
+// Tests that get<N>(t) returns the N-th (0-based) field of tuple t.
+TEST_F(BigTupleTest, get) {
+  EXPECT_EQ(1, get<0>(a_));
+  EXPECT_EQ(2, get<9>(a_));
+
+  // Tests that get() works on a const tuple too.
+  const BigTuple a(a_);
+  EXPECT_EQ(1, get<0>(a));
+  EXPECT_EQ(2, get<9>(a));
+}
+
+// Tests comparing big tuples.
+TEST_F(BigTupleTest, Comparisons) {
+  EXPECT_TRUE(a_ == a_);
+  EXPECT_FALSE(a_ != a_);
+
+  EXPECT_TRUE(a_ != b_);
+  EXPECT_FALSE(a_ == b_);
+}
+
+TEST(MakeTupleTest, WorksForScalarTypes) {
+  tuple<bool, int> a;
+  a = make_tuple(true, 5);
+  EXPECT_TRUE(get<0>(a));
+  EXPECT_EQ(5, get<1>(a));
+
+  tuple<char, int, long> b;
+  b = make_tuple('a', 'b', 5);
+  EXPECT_EQ('a', get<0>(b));
+  EXPECT_EQ('b', get<1>(b));
+  EXPECT_EQ(5, get<2>(b));
+}
+
+TEST(MakeTupleTest, WorksForPointers) {
+  int a[] = { 1, 2, 3, 4 };
+  const char* const str = "hi";
+  int* const p = a;
+
+  tuple<const char*, int*> t;
+  t = make_tuple(str, p);
+  EXPECT_EQ(str, get<0>(t));
+  EXPECT_EQ(p, get<1>(t));
+}
+
+}  // namespace
diff --git a/third_party/googletest/src/test/gtest-typed-test2_test.cc b/third_party/googletest/src/test/gtest-typed-test2_test.cc
new file mode 100644 (file)
index 0000000..c284700
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright 2008 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: wan@google.com (Zhanyong Wan)
+
+#include <vector>
+
+#include "test/gtest-typed-test_test.h"
+#include "gtest/gtest.h"
+
+#if GTEST_HAS_TYPED_TEST_P
+
+// Tests that the same type-parameterized test case can be
+// instantiated in different translation units linked together.
+// (ContainerTest is also instantiated in gtest-typed-test_test.cc.)
+INSTANTIATE_TYPED_TEST_CASE_P(Vector, ContainerTest,
+                              testing::Types<std::vector<int> >);
+
+#endif  // GTEST_HAS_TYPED_TEST_P
diff --git a/third_party/googletest/src/test/gtest-typed-test_test.cc b/third_party/googletest/src/test/gtest-typed-test_test.cc
new file mode 100644 (file)
index 0000000..dd4ba43
--- /dev/null
@@ -0,0 +1,360 @@
+// Copyright 2008 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: wan@google.com (Zhanyong Wan)
+
+#include <set>
+#include <vector>
+
+#include "test/gtest-typed-test_test.h"
+#include "gtest/gtest.h"
+
+using testing::Test;
+
+// Used for testing that SetUpTestCase()/TearDownTestCase(), fixture
+// ctor/dtor, and SetUp()/TearDown() work correctly in typed tests and
+// type-parameterized test.
+template <typename T>
+class CommonTest : public Test {
+  // For some technical reason, SetUpTestCase() and TearDownTestCase()
+  // must be public.
+ public:
+  static void SetUpTestCase() {
+    shared_ = new T(5);
+  }
+
+  static void TearDownTestCase() {
+    delete shared_;
+    shared_ = NULL;
+  }
+
+  // This 'protected:' is optional.  There's no harm in making all
+  // members of this fixture class template public.
+ protected:
+  // We used to use std::list here, but switched to std::vector since
+  // MSVC's <list> doesn't compile cleanly with /W4.
+  typedef std::vector<T> Vector;
+  typedef std::set<int> IntSet;
+
+  CommonTest() : value_(1) {}
+
+  virtual ~CommonTest() { EXPECT_EQ(3, value_); }
+
+  virtual void SetUp() {
+    EXPECT_EQ(1, value_);
+    value_++;
+  }
+
+  virtual void TearDown() {
+    EXPECT_EQ(2, value_);
+    value_++;
+  }
+
+  T value_;
+  static T* shared_;
+};
+
+template <typename T>
+T* CommonTest<T>::shared_ = NULL;
+
+// This #ifdef block tests typed tests.
+#if GTEST_HAS_TYPED_TEST
+
+using testing::Types;
+
+// Tests that SetUpTestCase()/TearDownTestCase(), fixture ctor/dtor,
+// and SetUp()/TearDown() work correctly in typed tests
+
+typedef Types<char, int> TwoTypes;
+TYPED_TEST_CASE(CommonTest, TwoTypes);
+
+TYPED_TEST(CommonTest, ValuesAreCorrect) {
+  // Static members of the fixture class template can be visited via
+  // the TestFixture:: prefix.
+  EXPECT_EQ(5, *TestFixture::shared_);
+
+  // Typedefs in the fixture class template can be visited via the
+  // "typename TestFixture::" prefix.
+  typename TestFixture::Vector empty;
+  EXPECT_EQ(0U, empty.size());
+
+  typename TestFixture::IntSet empty2;
+  EXPECT_EQ(0U, empty2.size());
+
+  // Non-static members of the fixture class must be visited via
+  // 'this', as required by C++ for class templates.
+  EXPECT_EQ(2, this->value_);
+}
+
+// The second test makes sure shared_ is not deleted after the first
+// test.
+TYPED_TEST(CommonTest, ValuesAreStillCorrect) {
+  // Static members of the fixture class template can also be visited
+  // via 'this'.
+  ASSERT_TRUE(this->shared_ != NULL);
+  EXPECT_EQ(5, *this->shared_);
+
+  // TypeParam can be used to refer to the type parameter.
+  EXPECT_EQ(static_cast<TypeParam>(2), this->value_);
+}
+
+// Tests that multiple TYPED_TEST_CASE's can be defined in the same
+// translation unit.
+
+template <typename T>
+class TypedTest1 : public Test {
+};
+
+// Verifies that the second argument of TYPED_TEST_CASE can be a
+// single type.
+TYPED_TEST_CASE(TypedTest1, int);
+TYPED_TEST(TypedTest1, A) {}
+
+template <typename T>
+class TypedTest2 : public Test {
+};
+
+// Verifies that the second argument of TYPED_TEST_CASE can be a
+// Types<...> type list.
+TYPED_TEST_CASE(TypedTest2, Types<int>);
+
+// This also verifies that tests from different typed test cases can
+// share the same name.
+TYPED_TEST(TypedTest2, A) {}
+
+// Tests that a typed test case can be defined in a namespace.
+
+namespace library1 {
+
+template <typename T>
+class NumericTest : public Test {
+};
+
+typedef Types<int, long> NumericTypes;
+TYPED_TEST_CASE(NumericTest, NumericTypes);
+
+TYPED_TEST(NumericTest, DefaultIsZero) {
+  EXPECT_EQ(0, TypeParam());
+}
+
+}  // namespace library1
+
+#endif  // GTEST_HAS_TYPED_TEST
+
+// This #ifdef block tests type-parameterized tests.
+#if GTEST_HAS_TYPED_TEST_P
+
+using testing::Types;
+using testing::internal::TypedTestCasePState;
+
+// Tests TypedTestCasePState.
+
+class TypedTestCasePStateTest : public Test {
+ protected:
+  virtual void SetUp() {
+    state_.AddTestName("foo.cc", 0, "FooTest", "A");
+    state_.AddTestName("foo.cc", 0, "FooTest", "B");
+    state_.AddTestName("foo.cc", 0, "FooTest", "C");
+  }
+
+  TypedTestCasePState state_;
+};
+
+TEST_F(TypedTestCasePStateTest, SucceedsForMatchingList) {
+  const char* tests = "A, B, C";
+  EXPECT_EQ(tests,
+            state_.VerifyRegisteredTestNames("foo.cc", 1, tests));
+}
+
+// Makes sure that the order of the tests and spaces around the names
+// don't matter.
+TEST_F(TypedTestCasePStateTest, IgnoresOrderAndSpaces) {
+  const char* tests = "A,C,   B";
+  EXPECT_EQ(tests,
+            state_.VerifyRegisteredTestNames("foo.cc", 1, tests));
+}
+
+typedef TypedTestCasePStateTest TypedTestCasePStateDeathTest;
+
+TEST_F(TypedTestCasePStateDeathTest, DetectsDuplicates) {
+  EXPECT_DEATH_IF_SUPPORTED(
+      state_.VerifyRegisteredTestNames("foo.cc", 1, "A, B, A, C"),
+      "foo\\.cc.1.?: Test A is listed more than once\\.");
+}
+
+TEST_F(TypedTestCasePStateDeathTest, DetectsExtraTest) {
+  EXPECT_DEATH_IF_SUPPORTED(
+      state_.VerifyRegisteredTestNames("foo.cc", 1, "A, B, C, D"),
+      "foo\\.cc.1.?: No test named D can be found in this test case\\.");
+}
+
+TEST_F(TypedTestCasePStateDeathTest, DetectsMissedTest) {
+  EXPECT_DEATH_IF_SUPPORTED(
+      state_.VerifyRegisteredTestNames("foo.cc", 1, "A, C"),
+      "foo\\.cc.1.?: You forgot to list test B\\.");
+}
+
+// Tests that defining a test for a parameterized test case generates
+// a run-time error if the test case has been registered.
+TEST_F(TypedTestCasePStateDeathTest, DetectsTestAfterRegistration) {
+  state_.VerifyRegisteredTestNames("foo.cc", 1, "A, B, C");
+  EXPECT_DEATH_IF_SUPPORTED(
+      state_.AddTestName("foo.cc", 2, "FooTest", "D"),
+      "foo\\.cc.2.?: Test D must be defined before REGISTER_TYPED_TEST_CASE_P"
+      "\\(FooTest, \\.\\.\\.\\)\\.");
+}
+
+// Tests that SetUpTestCase()/TearDownTestCase(), fixture ctor/dtor,
+// and SetUp()/TearDown() work correctly in type-parameterized tests.
+
+template <typename T>
+class DerivedTest : public CommonTest<T> {
+};
+
+TYPED_TEST_CASE_P(DerivedTest);
+
+TYPED_TEST_P(DerivedTest, ValuesAreCorrect) {
+  // Static members of the fixture class template can be visited via
+  // the TestFixture:: prefix.
+  EXPECT_EQ(5, *TestFixture::shared_);
+
+  // Non-static members of the fixture class must be visited via
+  // 'this', as required by C++ for class templates.
+  EXPECT_EQ(2, this->value_);
+}
+
+// The second test makes sure shared_ is not deleted after the first
+// test.
+TYPED_TEST_P(DerivedTest, ValuesAreStillCorrect) {
+  // Static members of the fixture class template can also be visited
+  // via 'this'.
+  ASSERT_TRUE(this->shared_ != NULL);
+  EXPECT_EQ(5, *this->shared_);
+  EXPECT_EQ(2, this->value_);
+}
+
+REGISTER_TYPED_TEST_CASE_P(DerivedTest,
+                           ValuesAreCorrect, ValuesAreStillCorrect);
+
+typedef Types<short, long> MyTwoTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(My, DerivedTest, MyTwoTypes);
+
+// Tests that multiple TYPED_TEST_CASE_P's can be defined in the same
+// translation unit.
+
+template <typename T>
+class TypedTestP1 : public Test {
+};
+
+TYPED_TEST_CASE_P(TypedTestP1);
+
+// For testing that the code between TYPED_TEST_CASE_P() and
+// TYPED_TEST_P() is not enclosed in a namespace.
+typedef int IntAfterTypedTestCaseP;
+
+TYPED_TEST_P(TypedTestP1, A) {}
+TYPED_TEST_P(TypedTestP1, B) {}
+
+// For testing that the code between TYPED_TEST_P() and
+// REGISTER_TYPED_TEST_CASE_P() is not enclosed in a namespace.
+typedef int IntBeforeRegisterTypedTestCaseP;
+
+REGISTER_TYPED_TEST_CASE_P(TypedTestP1, A, B);
+
+template <typename T>
+class TypedTestP2 : public Test {
+};
+
+TYPED_TEST_CASE_P(TypedTestP2);
+
+// This also verifies that tests from different type-parameterized
+// test cases can share the same name.
+TYPED_TEST_P(TypedTestP2, A) {}
+
+REGISTER_TYPED_TEST_CASE_P(TypedTestP2, A);
+
+// Verifies that the code between TYPED_TEST_CASE_P() and
+// REGISTER_TYPED_TEST_CASE_P() is not enclosed in a namespace.
+IntAfterTypedTestCaseP after = 0;
+IntBeforeRegisterTypedTestCaseP before = 0;
+
+// Verifies that the last argument of INSTANTIATE_TYPED_TEST_CASE_P()
+// can be either a single type or a Types<...> type list.
+INSTANTIATE_TYPED_TEST_CASE_P(Int, TypedTestP1, int);
+INSTANTIATE_TYPED_TEST_CASE_P(Int, TypedTestP2, Types<int>);
+
+// Tests that the same type-parameterized test case can be
+// instantiated more than once in the same translation unit.
+INSTANTIATE_TYPED_TEST_CASE_P(Double, TypedTestP2, Types<double>);
+
+// Tests that the same type-parameterized test case can be
+// instantiated in different translation units linked together.
+// (ContainerTest is also instantiated in gtest-typed-test_test.cc.)
+typedef Types<std::vector<double>, std::set<char> > MyContainers;
+INSTANTIATE_TYPED_TEST_CASE_P(My, ContainerTest, MyContainers);
+
+// Tests that a type-parameterized test case can be defined and
+// instantiated in a namespace.
+
+namespace library2 {
+
+template <typename T>
+class NumericTest : public Test {
+};
+
+TYPED_TEST_CASE_P(NumericTest);
+
+TYPED_TEST_P(NumericTest, DefaultIsZero) {
+  EXPECT_EQ(0, TypeParam());
+}
+
+TYPED_TEST_P(NumericTest, ZeroIsLessThanOne) {
+  EXPECT_LT(TypeParam(0), TypeParam(1));
+}
+
+REGISTER_TYPED_TEST_CASE_P(NumericTest,
+                           DefaultIsZero, ZeroIsLessThanOne);
+typedef Types<int, double> NumericTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(My, NumericTest, NumericTypes);
+
+}  // namespace library2
+
+#endif  // GTEST_HAS_TYPED_TEST_P
+
+#if !defined(GTEST_HAS_TYPED_TEST) && !defined(GTEST_HAS_TYPED_TEST_P)
+
+// Google Test may not support type-parameterized tests with some
+// compilers. If we use conditional compilation to compile out all
+// code referring to the gtest_main library, MSVC linker will not link
+// that library at all and consequently complain about missing entry
+// point defined in that library (fatal error LNK1561: entry point
+// must be defined). This dummy test keeps gtest_main linked in.
+TEST(DummyTest, TypedTestsAreNotSupportedOnThisPlatform) {}
+
+#endif  // #if !defined(GTEST_HAS_TYPED_TEST) && !defined(GTEST_HAS_TYPED_TEST_P)
diff --git a/third_party/googletest/src/test/gtest-typed-test_test.h b/third_party/googletest/src/test/gtest-typed-test_test.h
new file mode 100644 (file)
index 0000000..41d7570
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright 2008 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: wan@google.com (Zhanyong Wan)
+
+#ifndef GTEST_TEST_GTEST_TYPED_TEST_TEST_H_
+#define GTEST_TEST_GTEST_TYPED_TEST_TEST_H_
+
+#include "gtest/gtest.h"
+
+#if GTEST_HAS_TYPED_TEST_P
+
+using testing::Test;
+
+// For testing that the same type-parameterized test case can be
+// instantiated in different translation units linked together.
+// ContainerTest will be instantiated in both gtest-typed-test_test.cc
+// and gtest-typed-test2_test.cc.
+
+template <typename T>
+class ContainerTest : public Test {
+};
+
+TYPED_TEST_CASE_P(ContainerTest);
+
+TYPED_TEST_P(ContainerTest, CanBeDefaultConstructed) {
+  TypeParam container;
+}
+
+TYPED_TEST_P(ContainerTest, InitialSizeIsZero) {
+  TypeParam container;
+  EXPECT_EQ(0U, container.size());
+}
+
+REGISTER_TYPED_TEST_CASE_P(ContainerTest,
+                           CanBeDefaultConstructed, InitialSizeIsZero);
+
+#endif  // GTEST_HAS_TYPED_TEST_P
+
+#endif  // GTEST_TEST_GTEST_TYPED_TEST_TEST_H_
diff --git a/third_party/googletest/src/test/gtest-unittest-api_test.cc b/third_party/googletest/src/test/gtest-unittest-api_test.cc
new file mode 100644 (file)
index 0000000..07083e5
--- /dev/null
@@ -0,0 +1,341 @@
+// Copyright 2009 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: vladl@google.com (Vlad Losev)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This file contains tests verifying correctness of data provided via
+// UnitTest's public methods.
+
+#include "gtest/gtest.h"
+
+#include <string.h>  // For strcmp.
+#include <algorithm>
+
+using ::testing::InitGoogleTest;
+
+namespace testing {
+namespace internal {
+
+template <typename T>
+struct LessByName {
+  bool operator()(const T* a, const T* b) {
+    return strcmp(a->name(), b->name()) < 0;
+  }
+};
+
+class UnitTestHelper {
+ public:
+  // Returns the array of pointers to all test cases sorted by the test case
+  // name.  The caller is responsible for deleting the array.
+  static TestCase const** const GetSortedTestCases() {
+    UnitTest& unit_test = *UnitTest::GetInstance();
+    TestCase const** const test_cases =
+        new const TestCase*[unit_test.total_test_case_count()];
+
+    for (int i = 0; i < unit_test.total_test_case_count(); ++i)
+      test_cases[i] = unit_test.GetTestCase(i);
+
+    std::sort(test_cases,
+              test_cases + unit_test.total_test_case_count(),
+              LessByName<TestCase>());
+    return test_cases;
+  }
+
+  // Returns the test case by its name.  The caller doesn't own the returned
+  // pointer.
+  static const TestCase* FindTestCase(const char* name) {
+    UnitTest& unit_test = *UnitTest::GetInstance();
+    for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
+      const TestCase* test_case = unit_test.GetTestCase(i);
+      if (0 == strcmp(test_case->name(), name))
+        return test_case;
+    }
+    return NULL;
+  }
+
+  // Returns the array of pointers to all tests in a particular test case
+  // sorted by the test name.  The caller is responsible for deleting the
+  // array.
+  static TestInfo const** const GetSortedTests(const TestCase* test_case) {
+    TestInfo const** const tests =
+        new const TestInfo*[test_case->total_test_count()];
+
+    for (int i = 0; i < test_case->total_test_count(); ++i)
+      tests[i] = test_case->GetTestInfo(i);
+
+    std::sort(tests, tests + test_case->total_test_count(),
+              LessByName<TestInfo>());
+    return tests;
+  }
+};
+
+#if GTEST_HAS_TYPED_TEST
+template <typename T> class TestCaseWithCommentTest : public Test {};
+TYPED_TEST_CASE(TestCaseWithCommentTest, Types<int>);
+TYPED_TEST(TestCaseWithCommentTest, Dummy) {}
+
+const int kTypedTestCases = 1;
+const int kTypedTests = 1;
+#else
+const int kTypedTestCases = 0;
+const int kTypedTests = 0;
+#endif  // GTEST_HAS_TYPED_TEST
+
+// We can only test the accessors that do not change value while tests run.
+// Since tests can be run in any order, the values the accessors that track
+// test execution (such as failed_test_count) can not be predicted.
+TEST(ApiTest, UnitTestImmutableAccessorsWork) {
+  UnitTest* unit_test = UnitTest::GetInstance();
+
+  ASSERT_EQ(2 + kTypedTestCases, unit_test->total_test_case_count());
+  EXPECT_EQ(1 + kTypedTestCases, unit_test->test_case_to_run_count());
+  EXPECT_EQ(2, unit_test->disabled_test_count());
+  EXPECT_EQ(5 + kTypedTests, unit_test->total_test_count());
+  EXPECT_EQ(3 + kTypedTests, unit_test->test_to_run_count());
+
+  const TestCase** const test_cases = UnitTestHelper::GetSortedTestCases();
+
+  EXPECT_STREQ("ApiTest", test_cases[0]->name());
+  EXPECT_STREQ("DISABLED_Test", test_cases[1]->name());
+#if GTEST_HAS_TYPED_TEST
+  EXPECT_STREQ("TestCaseWithCommentTest/0", test_cases[2]->name());
+#endif  // GTEST_HAS_TYPED_TEST
+
+  delete[] test_cases;
+
+  // The following lines initiate actions to verify certain methods in
+  // FinalSuccessChecker::TearDown.
+
+  // Records a test property to verify TestResult::GetTestProperty().
+  RecordProperty("key", "value");
+}
+
+AssertionResult IsNull(const char* str) {
+  if (str != NULL) {
+    return testing::AssertionFailure() << "argument is " << str;
+  }
+  return AssertionSuccess();
+}
+
+TEST(ApiTest, TestCaseImmutableAccessorsWork) {
+  const TestCase* test_case = UnitTestHelper::FindTestCase("ApiTest");
+  ASSERT_TRUE(test_case != NULL);
+
+  EXPECT_STREQ("ApiTest", test_case->name());
+  EXPECT_TRUE(IsNull(test_case->type_param()));
+  EXPECT_TRUE(test_case->should_run());
+  EXPECT_EQ(1, test_case->disabled_test_count());
+  EXPECT_EQ(3, test_case->test_to_run_count());
+  ASSERT_EQ(4, test_case->total_test_count());
+
+  const TestInfo** tests = UnitTestHelper::GetSortedTests(test_case);
+
+  EXPECT_STREQ("DISABLED_Dummy1", tests[0]->name());
+  EXPECT_STREQ("ApiTest", tests[0]->test_case_name());
+  EXPECT_TRUE(IsNull(tests[0]->value_param()));
+  EXPECT_TRUE(IsNull(tests[0]->type_param()));
+  EXPECT_FALSE(tests[0]->should_run());
+
+  EXPECT_STREQ("TestCaseDisabledAccessorsWork", tests[1]->name());
+  EXPECT_STREQ("ApiTest", tests[1]->test_case_name());
+  EXPECT_TRUE(IsNull(tests[1]->value_param()));
+  EXPECT_TRUE(IsNull(tests[1]->type_param()));
+  EXPECT_TRUE(tests[1]->should_run());
+
+  EXPECT_STREQ("TestCaseImmutableAccessorsWork", tests[2]->name());
+  EXPECT_STREQ("ApiTest", tests[2]->test_case_name());
+  EXPECT_TRUE(IsNull(tests[2]->value_param()));
+  EXPECT_TRUE(IsNull(tests[2]->type_param()));
+  EXPECT_TRUE(tests[2]->should_run());
+
+  EXPECT_STREQ("UnitTestImmutableAccessorsWork", tests[3]->name());
+  EXPECT_STREQ("ApiTest", tests[3]->test_case_name());
+  EXPECT_TRUE(IsNull(tests[3]->value_param()));
+  EXPECT_TRUE(IsNull(tests[3]->type_param()));
+  EXPECT_TRUE(tests[3]->should_run());
+
+  delete[] tests;
+  tests = NULL;
+
+#if GTEST_HAS_TYPED_TEST
+  test_case = UnitTestHelper::FindTestCase("TestCaseWithCommentTest/0");
+  ASSERT_TRUE(test_case != NULL);
+
+  EXPECT_STREQ("TestCaseWithCommentTest/0", test_case->name());
+  EXPECT_STREQ(GetTypeName<int>().c_str(), test_case->type_param());
+  EXPECT_TRUE(test_case->should_run());
+  EXPECT_EQ(0, test_case->disabled_test_count());
+  EXPECT_EQ(1, test_case->test_to_run_count());
+  ASSERT_EQ(1, test_case->total_test_count());
+
+  tests = UnitTestHelper::GetSortedTests(test_case);
+
+  EXPECT_STREQ("Dummy", tests[0]->name());
+  EXPECT_STREQ("TestCaseWithCommentTest/0", tests[0]->test_case_name());
+  EXPECT_TRUE(IsNull(tests[0]->value_param()));
+  EXPECT_STREQ(GetTypeName<int>().c_str(), tests[0]->type_param());
+  EXPECT_TRUE(tests[0]->should_run());
+
+  delete[] tests;
+#endif  // GTEST_HAS_TYPED_TEST
+}
+
+TEST(ApiTest, TestCaseDisabledAccessorsWork) {
+  const TestCase* test_case = UnitTestHelper::FindTestCase("DISABLED_Test");
+  ASSERT_TRUE(test_case != NULL);
+
+  EXPECT_STREQ("DISABLED_Test", test_case->name());
+  EXPECT_TRUE(IsNull(test_case->type_param()));
+  EXPECT_FALSE(test_case->should_run());
+  EXPECT_EQ(1, test_case->disabled_test_count());
+  EXPECT_EQ(0, test_case->test_to_run_count());
+  ASSERT_EQ(1, test_case->total_test_count());
+
+  const TestInfo* const test_info = test_case->GetTestInfo(0);
+  EXPECT_STREQ("Dummy2", test_info->name());
+  EXPECT_STREQ("DISABLED_Test", test_info->test_case_name());
+  EXPECT_TRUE(IsNull(test_info->value_param()));
+  EXPECT_TRUE(IsNull(test_info->type_param()));
+  EXPECT_FALSE(test_info->should_run());
+}
+
+// These two tests are here to provide support for testing
+// test_case_to_run_count, disabled_test_count, and test_to_run_count.
+TEST(ApiTest, DISABLED_Dummy1) {}
+TEST(DISABLED_Test, Dummy2) {}
+
+class FinalSuccessChecker : public Environment {
+ protected:
+  virtual void TearDown() {
+    UnitTest* unit_test = UnitTest::GetInstance();
+
+    EXPECT_EQ(1 + kTypedTestCases, unit_test->successful_test_case_count());
+    EXPECT_EQ(3 + kTypedTests, unit_test->successful_test_count());
+    EXPECT_EQ(0, unit_test->failed_test_case_count());
+    EXPECT_EQ(0, unit_test->failed_test_count());
+    EXPECT_TRUE(unit_test->Passed());
+    EXPECT_FALSE(unit_test->Failed());
+    ASSERT_EQ(2 + kTypedTestCases, unit_test->total_test_case_count());
+
+    const TestCase** const test_cases = UnitTestHelper::GetSortedTestCases();
+
+    EXPECT_STREQ("ApiTest", test_cases[0]->name());
+    EXPECT_TRUE(IsNull(test_cases[0]->type_param()));
+    EXPECT_TRUE(test_cases[0]->should_run());
+    EXPECT_EQ(1, test_cases[0]->disabled_test_count());
+    ASSERT_EQ(4, test_cases[0]->total_test_count());
+    EXPECT_EQ(3, test_cases[0]->successful_test_count());
+    EXPECT_EQ(0, test_cases[0]->failed_test_count());
+    EXPECT_TRUE(test_cases[0]->Passed());
+    EXPECT_FALSE(test_cases[0]->Failed());
+
+    EXPECT_STREQ("DISABLED_Test", test_cases[1]->name());
+    EXPECT_TRUE(IsNull(test_cases[1]->type_param()));
+    EXPECT_FALSE(test_cases[1]->should_run());
+    EXPECT_EQ(1, test_cases[1]->disabled_test_count());
+    ASSERT_EQ(1, test_cases[1]->total_test_count());
+    EXPECT_EQ(0, test_cases[1]->successful_test_count());
+    EXPECT_EQ(0, test_cases[1]->failed_test_count());
+
+#if GTEST_HAS_TYPED_TEST
+    EXPECT_STREQ("TestCaseWithCommentTest/0", test_cases[2]->name());
+    EXPECT_STREQ(GetTypeName<int>().c_str(), test_cases[2]->type_param());
+    EXPECT_TRUE(test_cases[2]->should_run());
+    EXPECT_EQ(0, test_cases[2]->disabled_test_count());
+    ASSERT_EQ(1, test_cases[2]->total_test_count());
+    EXPECT_EQ(1, test_cases[2]->successful_test_count());
+    EXPECT_EQ(0, test_cases[2]->failed_test_count());
+    EXPECT_TRUE(test_cases[2]->Passed());
+    EXPECT_FALSE(test_cases[2]->Failed());
+#endif  // GTEST_HAS_TYPED_TEST
+
+    const TestCase* test_case = UnitTestHelper::FindTestCase("ApiTest");
+    const TestInfo** tests = UnitTestHelper::GetSortedTests(test_case);
+    EXPECT_STREQ("DISABLED_Dummy1", tests[0]->name());
+    EXPECT_STREQ("ApiTest", tests[0]->test_case_name());
+    EXPECT_FALSE(tests[0]->should_run());
+
+    EXPECT_STREQ("TestCaseDisabledAccessorsWork", tests[1]->name());
+    EXPECT_STREQ("ApiTest", tests[1]->test_case_name());
+    EXPECT_TRUE(IsNull(tests[1]->value_param()));
+    EXPECT_TRUE(IsNull(tests[1]->type_param()));
+    EXPECT_TRUE(tests[1]->should_run());
+    EXPECT_TRUE(tests[1]->result()->Passed());
+    EXPECT_EQ(0, tests[1]->result()->test_property_count());
+
+    EXPECT_STREQ("TestCaseImmutableAccessorsWork", tests[2]->name());
+    EXPECT_STREQ("ApiTest", tests[2]->test_case_name());
+    EXPECT_TRUE(IsNull(tests[2]->value_param()));
+    EXPECT_TRUE(IsNull(tests[2]->type_param()));
+    EXPECT_TRUE(tests[2]->should_run());
+    EXPECT_TRUE(tests[2]->result()->Passed());
+    EXPECT_EQ(0, tests[2]->result()->test_property_count());
+
+    EXPECT_STREQ("UnitTestImmutableAccessorsWork", tests[3]->name());
+    EXPECT_STREQ("ApiTest", tests[3]->test_case_name());
+    EXPECT_TRUE(IsNull(tests[3]->value_param()));
+    EXPECT_TRUE(IsNull(tests[3]->type_param()));
+    EXPECT_TRUE(tests[3]->should_run());
+    EXPECT_TRUE(tests[3]->result()->Passed());
+    EXPECT_EQ(1, tests[3]->result()->test_property_count());
+    const TestProperty& property = tests[3]->result()->GetTestProperty(0);
+    EXPECT_STREQ("key", property.key());
+    EXPECT_STREQ("value", property.value());
+
+    delete[] tests;
+
+#if GTEST_HAS_TYPED_TEST
+    test_case = UnitTestHelper::FindTestCase("TestCaseWithCommentTest/0");
+    tests = UnitTestHelper::GetSortedTests(test_case);
+
+    EXPECT_STREQ("Dummy", tests[0]->name());
+    EXPECT_STREQ("TestCaseWithCommentTest/0", tests[0]->test_case_name());
+    EXPECT_TRUE(IsNull(tests[0]->value_param()));
+    EXPECT_STREQ(GetTypeName<int>().c_str(), tests[0]->type_param());
+    EXPECT_TRUE(tests[0]->should_run());
+    EXPECT_TRUE(tests[0]->result()->Passed());
+    EXPECT_EQ(0, tests[0]->result()->test_property_count());
+
+    delete[] tests;
+#endif  // GTEST_HAS_TYPED_TEST
+    delete[] test_cases;
+  }
+};
+
+}  // namespace internal
+}  // namespace testing
+
+int main(int argc, char **argv) {
+  InitGoogleTest(&argc, argv);
+
+  AddGlobalTestEnvironment(new testing::internal::FinalSuccessChecker());
+
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/src/test/gtest_all_test.cc b/third_party/googletest/src/test/gtest_all_test.cc
new file mode 100644 (file)
index 0000000..955aa62
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright 2009, 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: wan@google.com (Zhanyong Wan)
+//
+// Tests for Google C++ Testing Framework (Google Test)
+//
+// Sometimes it's desirable to build most of Google Test's own tests
+// by compiling a single file.  This file serves this purpose.
+#include "test/gtest-filepath_test.cc"
+#include "test/gtest-linked_ptr_test.cc"
+#include "test/gtest-message_test.cc"
+#include "test/gtest-options_test.cc"
+#include "test/gtest-port_test.cc"
+#include "test/gtest_pred_impl_unittest.cc"
+#include "test/gtest_prod_test.cc"
+#include "test/gtest-test-part_test.cc"
+#include "test/gtest-typed-test_test.cc"
+#include "test/gtest-typed-test2_test.cc"
+#include "test/gtest_unittest.cc"
+#include "test/production.cc"
diff --git a/third_party/googletest/src/test/gtest_break_on_failure_unittest.py b/third_party/googletest/src/test/gtest_break_on_failure_unittest.py
new file mode 100755 (executable)
index 0000000..c819183
--- /dev/null
@@ -0,0 +1,218 @@
+#!/usr/bin/env python
+#
+# Copyright 2006, 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.
+
+"""Unit test for Google Test's break-on-failure mode.
+
+A user can ask Google Test to seg-fault when an assertion fails, using
+either the GTEST_BREAK_ON_FAILURE environment variable or the
+--gtest_break_on_failure flag.  This script tests such functionality
+by invoking gtest_break_on_failure_unittest_ (a program written with
+Google Test) with different environments and command line flags.
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import gtest_test_utils
+import os
+import sys
+
+
+# Constants.
+
+IS_WINDOWS = os.name == 'nt'
+
+# The environment variable for enabling/disabling the break-on-failure mode.
+BREAK_ON_FAILURE_ENV_VAR = 'GTEST_BREAK_ON_FAILURE'
+
+# The command line flag for enabling/disabling the break-on-failure mode.
+BREAK_ON_FAILURE_FLAG = 'gtest_break_on_failure'
+
+# The environment variable for enabling/disabling the throw-on-failure mode.
+THROW_ON_FAILURE_ENV_VAR = 'GTEST_THROW_ON_FAILURE'
+
+# The environment variable for enabling/disabling the catch-exceptions mode.
+CATCH_EXCEPTIONS_ENV_VAR = 'GTEST_CATCH_EXCEPTIONS'
+
+# Path to the gtest_break_on_failure_unittest_ program.
+EXE_PATH = gtest_test_utils.GetTestExecutablePath(
+    'gtest_break_on_failure_unittest_')
+
+
+# Utilities.
+
+
+environ = os.environ.copy()
+
+
+def SetEnvVar(env_var, value):
+  """Sets an environment variable to a given value; unsets it when the
+  given value is None.
+  """
+
+  if value is not None:
+    environ[env_var] = value
+  elif env_var in environ:
+    del environ[env_var]
+
+
+def Run(command):
+  """Runs a command; returns 1 if it was killed by a signal, or 0 otherwise."""
+
+  p = gtest_test_utils.Subprocess(command, env=environ)
+  if p.terminated_by_signal:
+    return 1
+  else:
+    return 0
+
+
+# The tests.
+
+
+class GTestBreakOnFailureUnitTest(gtest_test_utils.TestCase):
+  """Tests using the GTEST_BREAK_ON_FAILURE environment variable or
+  the --gtest_break_on_failure flag to turn assertion failures into
+  segmentation faults.
+  """
+
+  def RunAndVerify(self, env_var_value, flag_value, expect_seg_fault):
+    """Runs gtest_break_on_failure_unittest_ and verifies that it does
+    (or does not) have a seg-fault.
+
+    Args:
+      env_var_value:    value of the GTEST_BREAK_ON_FAILURE environment
+                        variable; None if the variable should be unset.
+      flag_value:       value of the --gtest_break_on_failure flag;
+                        None if the flag should not be present.
+      expect_seg_fault: 1 if the program is expected to generate a seg-fault;
+                        0 otherwise.
+    """
+
+    SetEnvVar(BREAK_ON_FAILURE_ENV_VAR, env_var_value)
+
+    if env_var_value is None:
+      env_var_value_msg = ' is not set'
+    else:
+      env_var_value_msg = '=' + env_var_value
+
+    if flag_value is None:
+      flag = ''
+    elif flag_value == '0':
+      flag = '--%s=0' % BREAK_ON_FAILURE_FLAG
+    else:
+      flag = '--%s' % BREAK_ON_FAILURE_FLAG
+
+    command = [EXE_PATH]
+    if flag:
+      command.append(flag)
+
+    if expect_seg_fault:
+      should_or_not = 'should'
+    else:
+      should_or_not = 'should not'
+
+    has_seg_fault = Run(command)
+
+    SetEnvVar(BREAK_ON_FAILURE_ENV_VAR, None)
+
+    msg = ('when %s%s, an assertion failure in "%s" %s cause a seg-fault.' %
+           (BREAK_ON_FAILURE_ENV_VAR, env_var_value_msg, ' '.join(command),
+            should_or_not))
+    self.assert_(has_seg_fault == expect_seg_fault, msg)
+
+  def testDefaultBehavior(self):
+    """Tests the behavior of the default mode."""
+
+    self.RunAndVerify(env_var_value=None,
+                      flag_value=None,
+                      expect_seg_fault=0)
+
+  def testEnvVar(self):
+    """Tests using the GTEST_BREAK_ON_FAILURE environment variable."""
+
+    self.RunAndVerify(env_var_value='0',
+                      flag_value=None,
+                      expect_seg_fault=0)
+    self.RunAndVerify(env_var_value='1',
+                      flag_value=None,
+                      expect_seg_fault=1)
+
+  def testFlag(self):
+    """Tests using the --gtest_break_on_failure flag."""
+
+    self.RunAndVerify(env_var_value=None,
+                      flag_value='0',
+                      expect_seg_fault=0)
+    self.RunAndVerify(env_var_value=None,
+                      flag_value='1',
+                      expect_seg_fault=1)
+
+  def testFlagOverridesEnvVar(self):
+    """Tests that the flag overrides the environment variable."""
+
+    self.RunAndVerify(env_var_value='0',
+                      flag_value='0',
+                      expect_seg_fault=0)
+    self.RunAndVerify(env_var_value='0',
+                      flag_value='1',
+                      expect_seg_fault=1)
+    self.RunAndVerify(env_var_value='1',
+                      flag_value='0',
+                      expect_seg_fault=0)
+    self.RunAndVerify(env_var_value='1',
+                      flag_value='1',
+                      expect_seg_fault=1)
+
+  def testBreakOnFailureOverridesThrowOnFailure(self):
+    """Tests that gtest_break_on_failure overrides gtest_throw_on_failure."""
+
+    SetEnvVar(THROW_ON_FAILURE_ENV_VAR, '1')
+    try:
+      self.RunAndVerify(env_var_value=None,
+                        flag_value='1',
+                        expect_seg_fault=1)
+    finally:
+      SetEnvVar(THROW_ON_FAILURE_ENV_VAR, None)
+
+  if IS_WINDOWS:
+    def testCatchExceptionsDoesNotInterfere(self):
+      """Tests that gtest_catch_exceptions doesn't interfere."""
+
+      SetEnvVar(CATCH_EXCEPTIONS_ENV_VAR, '1')
+      try:
+        self.RunAndVerify(env_var_value='1',
+                          flag_value='1',
+                          expect_seg_fault=1)
+      finally:
+        SetEnvVar(CATCH_EXCEPTIONS_ENV_VAR, None)
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/src/test/gtest_break_on_failure_unittest_.cc b/third_party/googletest/src/test/gtest_break_on_failure_unittest_.cc
new file mode 100644 (file)
index 0000000..dd07478
--- /dev/null
@@ -0,0 +1,88 @@
+// Copyright 2006, 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: wan@google.com (Zhanyong Wan)
+
+// Unit test for Google Test's break-on-failure mode.
+//
+// A user can ask Google Test to seg-fault when an assertion fails, using
+// either the GTEST_BREAK_ON_FAILURE environment variable or the
+// --gtest_break_on_failure flag.  This file is used for testing such
+// functionality.
+//
+// This program will be invoked from a Python unit test.  It is
+// expected to fail.  Don't run it directly.
+
+#include "gtest/gtest.h"
+
+#if GTEST_OS_WINDOWS
+# include <windows.h>
+# include <stdlib.h>
+#endif
+
+namespace {
+
+// A test that's expected to fail.
+TEST(Foo, Bar) {
+  EXPECT_EQ(2, 3);
+}
+
+#if GTEST_HAS_SEH && !GTEST_OS_WINDOWS_MOBILE
+// On Windows Mobile global exception handlers are not supported.
+LONG WINAPI ExitWithExceptionCode(
+    struct _EXCEPTION_POINTERS* exception_pointers) {
+  exit(exception_pointers->ExceptionRecord->ExceptionCode);
+}
+#endif
+
+}  // namespace
+
+int main(int argc, char **argv) {
+#if GTEST_OS_WINDOWS
+  // Suppresses display of the Windows error dialog upon encountering
+  // a general protection fault (segment violation).
+  SetErrorMode(SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS);
+
+# if GTEST_HAS_SEH && !GTEST_OS_WINDOWS_MOBILE
+
+  // The default unhandled exception filter does not always exit
+  // with the exception code as exit code - for example it exits with
+  // 0 for EXCEPTION_ACCESS_VIOLATION and 1 for EXCEPTION_BREAKPOINT
+  // if the application is compiled in debug mode. Thus we use our own
+  // filter which always exits with the exception code for unhandled
+  // exceptions.
+  SetUnhandledExceptionFilter(ExitWithExceptionCode);
+
+# endif
+#endif
+
+  testing::InitGoogleTest(&argc, argv);
+
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/src/test/gtest_catch_exceptions_test.py b/third_party/googletest/src/test/gtest_catch_exceptions_test.py
new file mode 100755 (executable)
index 0000000..7fd7dba
--- /dev/null
@@ -0,0 +1,220 @@
+#!/usr/bin/env python
+#
+# Copyright 2010 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.
+
+"""Tests Google Test's exception catching behavior.
+
+This script invokes gtest_catch_exceptions_test_ and
+gtest_catch_exceptions_ex_test_ (programs written with
+Google Test) and verifies their output.
+"""
+
+__author__ = 'vladl@google.com (Vlad Losev)'
+
+import os
+
+import gtest_test_utils
+
+# Constants.
+FLAG_PREFIX = '--gtest_'
+LIST_TESTS_FLAG = FLAG_PREFIX + 'list_tests'
+NO_CATCH_EXCEPTIONS_FLAG = FLAG_PREFIX + 'catch_exceptions=0'
+FILTER_FLAG = FLAG_PREFIX + 'filter'
+
+# Path to the gtest_catch_exceptions_ex_test_ binary, compiled with
+# exceptions enabled.
+EX_EXE_PATH = gtest_test_utils.GetTestExecutablePath(
+    'gtest_catch_exceptions_ex_test_')
+
+# Path to the gtest_catch_exceptions_test_ binary, compiled with
+# exceptions disabled.
+EXE_PATH = gtest_test_utils.GetTestExecutablePath(
+    'gtest_catch_exceptions_no_ex_test_')
+
+TEST_LIST = gtest_test_utils.Subprocess([EXE_PATH, LIST_TESTS_FLAG]).output
+
+SUPPORTS_SEH_EXCEPTIONS = 'ThrowsSehException' in TEST_LIST
+
+if SUPPORTS_SEH_EXCEPTIONS:
+  BINARY_OUTPUT = gtest_test_utils.Subprocess([EXE_PATH]).output
+
+EX_BINARY_OUTPUT = gtest_test_utils.Subprocess([EX_EXE_PATH]).output
+
+# The tests.
+if SUPPORTS_SEH_EXCEPTIONS:
+  # pylint:disable-msg=C6302
+  class CatchSehExceptionsTest(gtest_test_utils.TestCase):
+    """Tests exception-catching behavior."""
+
+
+    def TestSehExceptions(self, test_output):
+      self.assert_('SEH exception with code 0x2a thrown '
+                   'in the test fixture\'s constructor'
+                   in test_output)
+      self.assert_('SEH exception with code 0x2a thrown '
+                   'in the test fixture\'s destructor'
+                   in test_output)
+      self.assert_('SEH exception with code 0x2a thrown in SetUpTestCase()'
+                   in test_output)
+      self.assert_('SEH exception with code 0x2a thrown in TearDownTestCase()'
+                   in test_output)
+      self.assert_('SEH exception with code 0x2a thrown in SetUp()'
+                   in test_output)
+      self.assert_('SEH exception with code 0x2a thrown in TearDown()'
+                   in test_output)
+      self.assert_('SEH exception with code 0x2a thrown in the test body'
+                   in test_output)
+
+    def testCatchesSehExceptionsWithCxxExceptionsEnabled(self):
+      self.TestSehExceptions(EX_BINARY_OUTPUT)
+
+    def testCatchesSehExceptionsWithCxxExceptionsDisabled(self):
+      self.TestSehExceptions(BINARY_OUTPUT)
+
+
+class CatchCxxExceptionsTest(gtest_test_utils.TestCase):
+  """Tests C++ exception-catching behavior.
+
+     Tests in this test case verify that:
+     * C++ exceptions are caught and logged as C++ (not SEH) exceptions
+     * Exception thrown affect the remainder of the test work flow in the
+       expected manner.
+  """
+
+  def testCatchesCxxExceptionsInFixtureConstructor(self):
+    self.assert_('C++ exception with description '
+                 '"Standard C++ exception" thrown '
+                 'in the test fixture\'s constructor'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('unexpected' not in EX_BINARY_OUTPUT,
+                 'This failure belongs in this test only if '
+                 '"CxxExceptionInConstructorTest" (no quotes) '
+                 'appears on the same line as words "called unexpectedly"')
+
+  def testCatchesCxxExceptionsInFixtureDestructor(self):
+    self.assert_('C++ exception with description '
+                 '"Standard C++ exception" thrown '
+                 'in the test fixture\'s destructor'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInDestructorTest::TearDownTestCase() '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+
+  def testCatchesCxxExceptionsInSetUpTestCase(self):
+    self.assert_('C++ exception with description "Standard C++ exception"'
+                 ' thrown in SetUpTestCase()'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInConstructorTest::TearDownTestCase() '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInSetUpTestCaseTest constructor '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInSetUpTestCaseTest destructor '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInSetUpTestCaseTest::SetUp() '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInSetUpTestCaseTest::TearDown() '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInSetUpTestCaseTest test body '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+
+  def testCatchesCxxExceptionsInTearDownTestCase(self):
+    self.assert_('C++ exception with description "Standard C++ exception"'
+                 ' thrown in TearDownTestCase()'
+                 in EX_BINARY_OUTPUT)
+
+  def testCatchesCxxExceptionsInSetUp(self):
+    self.assert_('C++ exception with description "Standard C++ exception"'
+                 ' thrown in SetUp()'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInSetUpTest::TearDownTestCase() '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInSetUpTest destructor '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInSetUpTest::TearDown() '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('unexpected' not in EX_BINARY_OUTPUT,
+                 'This failure belongs in this test only if '
+                 '"CxxExceptionInSetUpTest" (no quotes) '
+                 'appears on the same line as words "called unexpectedly"')
+
+  def testCatchesCxxExceptionsInTearDown(self):
+    self.assert_('C++ exception with description "Standard C++ exception"'
+                 ' thrown in TearDown()'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInTearDownTest::TearDownTestCase() '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInTearDownTest destructor '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+
+  def testCatchesCxxExceptionsInTestBody(self):
+    self.assert_('C++ exception with description "Standard C++ exception"'
+                 ' thrown in the test body'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInTestBodyTest::TearDownTestCase() '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInTestBodyTest destructor '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+    self.assert_('CxxExceptionInTestBodyTest::TearDown() '
+                 'called as expected.'
+                 in EX_BINARY_OUTPUT)
+
+  def testCatchesNonStdCxxExceptions(self):
+    self.assert_('Unknown C++ exception thrown in the test body'
+                 in EX_BINARY_OUTPUT)
+
+  def testUnhandledCxxExceptionsAbortTheProgram(self):
+    # Filters out SEH exception tests on Windows. Unhandled SEH exceptions
+    # cause tests to show pop-up windows there.
+    FITLER_OUT_SEH_TESTS_FLAG = FILTER_FLAG + '=-*Seh*'
+    # By default, Google Test doesn't catch the exceptions.
+    uncaught_exceptions_ex_binary_output = gtest_test_utils.Subprocess(
+        [EX_EXE_PATH,
+         NO_CATCH_EXCEPTIONS_FLAG,
+         FITLER_OUT_SEH_TESTS_FLAG]).output
+
+    self.assert_('Unhandled C++ exception terminating the program'
+                 in uncaught_exceptions_ex_binary_output)
+    self.assert_('unexpected' not in uncaught_exceptions_ex_binary_output)
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/src/test/gtest_catch_exceptions_test_.cc b/third_party/googletest/src/test/gtest_catch_exceptions_test_.cc
new file mode 100644 (file)
index 0000000..a35103f
--- /dev/null
@@ -0,0 +1,308 @@
+// Copyright 2010, 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: vladl@google.com (Vlad Losev)
+//
+// Tests for Google Test itself. Tests in this file throw C++ or SEH
+// exceptions, and the output is verified by gtest_catch_exceptions_test.py.
+
+#include "gtest/gtest.h"
+
+#include <stdio.h>  // NOLINT
+#include <stdlib.h>  // For exit().
+
+#if GTEST_HAS_SEH
+# include <windows.h>
+#endif
+
+#if GTEST_HAS_EXCEPTIONS
+# include <exception>  // For set_terminate().
+# include <stdexcept>
+#endif
+
+using testing::Test;
+
+#if GTEST_HAS_SEH
+
+class SehExceptionInConstructorTest : public Test {
+ public:
+  SehExceptionInConstructorTest() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInConstructorTest, ThrowsExceptionInConstructor) {}
+
+class SehExceptionInDestructorTest : public Test {
+ public:
+  ~SehExceptionInDestructorTest() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInDestructorTest, ThrowsExceptionInDestructor) {}
+
+class SehExceptionInSetUpTestCaseTest : public Test {
+ public:
+  static void SetUpTestCase() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInSetUpTestCaseTest, ThrowsExceptionInSetUpTestCase) {}
+
+class SehExceptionInTearDownTestCaseTest : public Test {
+ public:
+  static void TearDownTestCase() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInTearDownTestCaseTest, ThrowsExceptionInTearDownTestCase) {}
+
+class SehExceptionInSetUpTest : public Test {
+ protected:
+  virtual void SetUp() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInSetUpTest, ThrowsExceptionInSetUp) {}
+
+class SehExceptionInTearDownTest : public Test {
+ protected:
+  virtual void TearDown() { RaiseException(42, 0, 0, NULL); }
+};
+
+TEST_F(SehExceptionInTearDownTest, ThrowsExceptionInTearDown) {}
+
+TEST(SehExceptionTest, ThrowsSehException) {
+  RaiseException(42, 0, 0, NULL);
+}
+
+#endif  // GTEST_HAS_SEH
+
+#if GTEST_HAS_EXCEPTIONS
+
+class CxxExceptionInConstructorTest : public Test {
+ public:
+  CxxExceptionInConstructorTest() {
+    // Without this macro VC++ complains about unreachable code at the end of
+    // the constructor.
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(
+        throw std::runtime_error("Standard C++ exception"));
+  }
+
+  static void TearDownTestCase() {
+    printf("%s",
+           "CxxExceptionInConstructorTest::TearDownTestCase() "
+           "called as expected.\n");
+  }
+
+ protected:
+  ~CxxExceptionInConstructorTest() {
+    ADD_FAILURE() << "CxxExceptionInConstructorTest destructor "
+                  << "called unexpectedly.";
+  }
+
+  virtual void SetUp() {
+    ADD_FAILURE() << "CxxExceptionInConstructorTest::SetUp() "
+                  << "called unexpectedly.";
+  }
+
+  virtual void TearDown() {
+    ADD_FAILURE() << "CxxExceptionInConstructorTest::TearDown() "
+                  << "called unexpectedly.";
+  }
+};
+
+TEST_F(CxxExceptionInConstructorTest, ThrowsExceptionInConstructor) {
+  ADD_FAILURE() << "CxxExceptionInConstructorTest test body "
+                << "called unexpectedly.";
+}
+
+class CxxExceptionInDestructorTest : public Test {
+ public:
+  static void TearDownTestCase() {
+    printf("%s",
+           "CxxExceptionInDestructorTest::TearDownTestCase() "
+           "called as expected.\n");
+  }
+
+ protected:
+  ~CxxExceptionInDestructorTest() {
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(
+        throw std::runtime_error("Standard C++ exception"));
+  }
+};
+
+TEST_F(CxxExceptionInDestructorTest, ThrowsExceptionInDestructor) {}
+
+class CxxExceptionInSetUpTestCaseTest : public Test {
+ public:
+  CxxExceptionInSetUpTestCaseTest() {
+    printf("%s",
+           "CxxExceptionInSetUpTestCaseTest constructor "
+           "called as expected.\n");
+  }
+
+  static void SetUpTestCase() {
+    throw std::runtime_error("Standard C++ exception");
+  }
+
+  static void TearDownTestCase() {
+    printf("%s",
+           "CxxExceptionInSetUpTestCaseTest::TearDownTestCase() "
+           "called as expected.\n");
+  }
+
+ protected:
+  ~CxxExceptionInSetUpTestCaseTest() {
+    printf("%s",
+           "CxxExceptionInSetUpTestCaseTest destructor "
+           "called as expected.\n");
+  }
+
+  virtual void SetUp() {
+    printf("%s",
+           "CxxExceptionInSetUpTestCaseTest::SetUp() "
+           "called as expected.\n");
+  }
+
+  virtual void TearDown() {
+    printf("%s",
+           "CxxExceptionInSetUpTestCaseTest::TearDown() "
+           "called as expected.\n");
+  }
+};
+
+TEST_F(CxxExceptionInSetUpTestCaseTest, ThrowsExceptionInSetUpTestCase) {
+  printf("%s",
+         "CxxExceptionInSetUpTestCaseTest test body "
+         "called as expected.\n");
+}
+
+class CxxExceptionInTearDownTestCaseTest : public Test {
+ public:
+  static void TearDownTestCase() {
+    throw std::runtime_error("Standard C++ exception");
+  }
+};
+
+TEST_F(CxxExceptionInTearDownTestCaseTest, ThrowsExceptionInTearDownTestCase) {}
+
+class CxxExceptionInSetUpTest : public Test {
+ public:
+  static void TearDownTestCase() {
+    printf("%s",
+           "CxxExceptionInSetUpTest::TearDownTestCase() "
+           "called as expected.\n");
+  }
+
+ protected:
+  ~CxxExceptionInSetUpTest() {
+    printf("%s",
+           "CxxExceptionInSetUpTest destructor "
+           "called as expected.\n");
+  }
+
+  virtual void SetUp() { throw std::runtime_error("Standard C++ exception"); }
+
+  virtual void TearDown() {
+    printf("%s",
+           "CxxExceptionInSetUpTest::TearDown() "
+           "called as expected.\n");
+  }
+};
+
+TEST_F(CxxExceptionInSetUpTest, ThrowsExceptionInSetUp) {
+  ADD_FAILURE() << "CxxExceptionInSetUpTest test body "
+                << "called unexpectedly.";
+}
+
+class CxxExceptionInTearDownTest : public Test {
+ public:
+  static void TearDownTestCase() {
+    printf("%s",
+           "CxxExceptionInTearDownTest::TearDownTestCase() "
+           "called as expected.\n");
+  }
+
+ protected:
+  ~CxxExceptionInTearDownTest() {
+    printf("%s",
+           "CxxExceptionInTearDownTest destructor "
+           "called as expected.\n");
+  }
+
+  virtual void TearDown() {
+    throw std::runtime_error("Standard C++ exception");
+  }
+};
+
+TEST_F(CxxExceptionInTearDownTest, ThrowsExceptionInTearDown) {}
+
+class CxxExceptionInTestBodyTest : public Test {
+ public:
+  static void TearDownTestCase() {
+    printf("%s",
+           "CxxExceptionInTestBodyTest::TearDownTestCase() "
+           "called as expected.\n");
+  }
+
+ protected:
+  ~CxxExceptionInTestBodyTest() {
+    printf("%s",
+           "CxxExceptionInTestBodyTest destructor "
+           "called as expected.\n");
+  }
+
+  virtual void TearDown() {
+    printf("%s",
+           "CxxExceptionInTestBodyTest::TearDown() "
+           "called as expected.\n");
+  }
+};
+
+TEST_F(CxxExceptionInTestBodyTest, ThrowsStdCxxException) {
+  throw std::runtime_error("Standard C++ exception");
+}
+
+TEST(CxxExceptionTest, ThrowsNonStdCxxException) {
+  throw "C-string";
+}
+
+// This terminate handler aborts the program using exit() rather than abort().
+// This avoids showing pop-ups on Windows systems and core dumps on Unix-like
+// ones.
+void TerminateHandler() {
+  fprintf(stderr, "%s\n", "Unhandled C++ exception terminating the program.");
+  fflush(NULL);
+  exit(3);
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+int main(int argc, char** argv) {
+#if GTEST_HAS_EXCEPTIONS
+  std::set_terminate(&TerminateHandler);
+#endif
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/src/test/gtest_color_test.py b/third_party/googletest/src/test/gtest_color_test.py
new file mode 100755 (executable)
index 0000000..d02a53e
--- /dev/null
@@ -0,0 +1,130 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, 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.
+
+"""Verifies that Google Test correctly determines whether to use colors."""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import gtest_test_utils
+
+
+IS_WINDOWS = os.name = 'nt'
+
+COLOR_ENV_VAR = 'GTEST_COLOR'
+COLOR_FLAG = 'gtest_color'
+COMMAND = gtest_test_utils.GetTestExecutablePath('gtest_color_test_')
+
+
+def SetEnvVar(env_var, value):
+  """Sets the env variable to 'value'; unsets it when 'value' is None."""
+
+  if value is not None:
+    os.environ[env_var] = value
+  elif env_var in os.environ:
+    del os.environ[env_var]
+
+
+def UsesColor(term, color_env_var, color_flag):
+  """Runs gtest_color_test_ and returns its exit code."""
+
+  SetEnvVar('TERM', term)
+  SetEnvVar(COLOR_ENV_VAR, color_env_var)
+
+  if color_flag is None:
+    args = []
+  else:
+    args = ['--%s=%s' % (COLOR_FLAG, color_flag)]
+  p = gtest_test_utils.Subprocess([COMMAND] + args)
+  return not p.exited or p.exit_code
+
+
+class GTestColorTest(gtest_test_utils.TestCase):
+  def testNoEnvVarNoFlag(self):
+    """Tests the case when there's neither GTEST_COLOR nor --gtest_color."""
+
+    if not IS_WINDOWS:
+      self.assert_(not UsesColor('dumb', None, None))
+      self.assert_(not UsesColor('emacs', None, None))
+      self.assert_(not UsesColor('xterm-mono', None, None))
+      self.assert_(not UsesColor('unknown', None, None))
+      self.assert_(not UsesColor(None, None, None))
+    self.assert_(UsesColor('linux', None, None))
+    self.assert_(UsesColor('cygwin', None, None))
+    self.assert_(UsesColor('xterm', None, None))
+    self.assert_(UsesColor('xterm-color', None, None))
+    self.assert_(UsesColor('xterm-256color', None, None))
+
+  def testFlagOnly(self):
+    """Tests the case when there's --gtest_color but not GTEST_COLOR."""
+
+    self.assert_(not UsesColor('dumb', None, 'no'))
+    self.assert_(not UsesColor('xterm-color', None, 'no'))
+    if not IS_WINDOWS:
+      self.assert_(not UsesColor('emacs', None, 'auto'))
+    self.assert_(UsesColor('xterm', None, 'auto'))
+    self.assert_(UsesColor('dumb', None, 'yes'))
+    self.assert_(UsesColor('xterm', None, 'yes'))
+
+  def testEnvVarOnly(self):
+    """Tests the case when there's GTEST_COLOR but not --gtest_color."""
+
+    self.assert_(not UsesColor('dumb', 'no', None))
+    self.assert_(not UsesColor('xterm-color', 'no', None))
+    if not IS_WINDOWS:
+      self.assert_(not UsesColor('dumb', 'auto', None))
+    self.assert_(UsesColor('xterm-color', 'auto', None))
+    self.assert_(UsesColor('dumb', 'yes', None))
+    self.assert_(UsesColor('xterm-color', 'yes', None))
+
+  def testEnvVarAndFlag(self):
+    """Tests the case when there are both GTEST_COLOR and --gtest_color."""
+
+    self.assert_(not UsesColor('xterm-color', 'no', 'no'))
+    self.assert_(UsesColor('dumb', 'no', 'yes'))
+    self.assert_(UsesColor('xterm-color', 'no', 'auto'))
+
+  def testAliasesOfYesAndNo(self):
+    """Tests using aliases in specifying --gtest_color."""
+
+    self.assert_(UsesColor('dumb', None, 'true'))
+    self.assert_(UsesColor('dumb', None, 'YES'))
+    self.assert_(UsesColor('dumb', None, 'T'))
+    self.assert_(UsesColor('dumb', None, '1'))
+
+    self.assert_(not UsesColor('xterm', None, 'f'))
+    self.assert_(not UsesColor('xterm', None, 'false'))
+    self.assert_(not UsesColor('xterm', None, '0'))
+    self.assert_(not UsesColor('xterm', None, 'unknown'))
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/src/test/gtest_color_test_.cc b/third_party/googletest/src/test/gtest_color_test_.cc
new file mode 100644 (file)
index 0000000..f61ebb8
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright 2008, 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: wan@google.com (Zhanyong Wan)
+
+// A helper program for testing how Google Test determines whether to use
+// colors in the output.  It prints "YES" and returns 1 if Google Test
+// decides to use colors, and prints "NO" and returns 0 otherwise.
+
+#include <stdio.h>
+
+#include "gtest/gtest.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+using testing::internal::ShouldUseColor;
+
+// The purpose of this is to ensure that the UnitTest singleton is
+// created before main() is entered, and thus that ShouldUseColor()
+// works the same way as in a real Google-Test-based test.  We don't actual
+// run the TEST itself.
+TEST(GTestColorTest, Dummy) {
+}
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  if (ShouldUseColor(true)) {
+    // Google Test decides to use colors in the output (assuming it
+    // goes to a TTY).
+    printf("YES\n");
+    return 1;
+  } else {
+    // Google Test decides not to use colors in the output.
+    printf("NO\n");
+    return 0;
+  }
+}
diff --git a/third_party/googletest/src/test/gtest_env_var_test.py b/third_party/googletest/src/test/gtest_env_var_test.py
new file mode 100755 (executable)
index 0000000..ac24337
--- /dev/null
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, 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.
+
+"""Verifies that Google Test correctly parses environment variables."""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import gtest_test_utils
+
+
+IS_WINDOWS = os.name == 'nt'
+IS_LINUX = os.name == 'posix' and os.uname()[0] == 'Linux'
+
+COMMAND = gtest_test_utils.GetTestExecutablePath('gtest_env_var_test_')
+
+environ = os.environ.copy()
+
+
+def AssertEq(expected, actual):
+  if expected != actual:
+    print 'Expected: %s' % (expected,)
+    print '  Actual: %s' % (actual,)
+    raise AssertionError
+
+
+def SetEnvVar(env_var, value):
+  """Sets the env variable to 'value'; unsets it when 'value' is None."""
+
+  if value is not None:
+    environ[env_var] = value
+  elif env_var in environ:
+    del environ[env_var]
+
+
+def GetFlag(flag):
+  """Runs gtest_env_var_test_ and returns its output."""
+
+  args = [COMMAND]
+  if flag is not None:
+    args += [flag]
+  return gtest_test_utils.Subprocess(args, env=environ).output
+
+
+def TestFlag(flag, test_val, default_val):
+  """Verifies that the given flag is affected by the corresponding env var."""
+
+  env_var = 'GTEST_' + flag.upper()
+  SetEnvVar(env_var, test_val)
+  AssertEq(test_val, GetFlag(flag))
+  SetEnvVar(env_var, None)
+  AssertEq(default_val, GetFlag(flag))
+
+
+class GTestEnvVarTest(gtest_test_utils.TestCase):
+  def testEnvVarAffectsFlag(self):
+    """Tests that environment variable should affect the corresponding flag."""
+
+    TestFlag('break_on_failure', '1', '0')
+    TestFlag('color', 'yes', 'auto')
+    TestFlag('filter', 'FooTest.Bar', '*')
+    TestFlag('output', 'xml:tmp/foo.xml', '')
+    TestFlag('print_time', '0', '1')
+    TestFlag('repeat', '999', '1')
+    TestFlag('throw_on_failure', '1', '0')
+    TestFlag('death_test_style', 'threadsafe', 'fast')
+    TestFlag('catch_exceptions', '0', '1')
+
+    if IS_LINUX:
+      TestFlag('death_test_use_fork', '1', '0')
+      TestFlag('stack_trace_depth', '0', '100')
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/src/test/gtest_env_var_test_.cc b/third_party/googletest/src/test/gtest_env_var_test_.cc
new file mode 100644 (file)
index 0000000..539afc9
--- /dev/null
@@ -0,0 +1,126 @@
+// Copyright 2008, 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: wan@google.com (Zhanyong Wan)
+
+// A helper program for testing that Google Test parses the environment
+// variables correctly.
+
+#include "gtest/gtest.h"
+
+#include <iostream>
+
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+using ::std::cout;
+
+namespace testing {
+
+// The purpose of this is to make the test more realistic by ensuring
+// that the UnitTest singleton is created before main() is entered.
+// We don't actual run the TEST itself.
+TEST(GTestEnvVarTest, Dummy) {
+}
+
+void PrintFlag(const char* flag) {
+  if (strcmp(flag, "break_on_failure") == 0) {
+    cout << GTEST_FLAG(break_on_failure);
+    return;
+  }
+
+  if (strcmp(flag, "catch_exceptions") == 0) {
+    cout << GTEST_FLAG(catch_exceptions);
+    return;
+  }
+
+  if (strcmp(flag, "color") == 0) {
+    cout << GTEST_FLAG(color);
+    return;
+  }
+
+  if (strcmp(flag, "death_test_style") == 0) {
+    cout << GTEST_FLAG(death_test_style);
+    return;
+  }
+
+  if (strcmp(flag, "death_test_use_fork") == 0) {
+    cout << GTEST_FLAG(death_test_use_fork);
+    return;
+  }
+
+  if (strcmp(flag, "filter") == 0) {
+    cout << GTEST_FLAG(filter);
+    return;
+  }
+
+  if (strcmp(flag, "output") == 0) {
+    cout << GTEST_FLAG(output);
+    return;
+  }
+
+  if (strcmp(flag, "print_time") == 0) {
+    cout << GTEST_FLAG(print_time);
+    return;
+  }
+
+  if (strcmp(flag, "repeat") == 0) {
+    cout << GTEST_FLAG(repeat);
+    return;
+  }
+
+  if (strcmp(flag, "stack_trace_depth") == 0) {
+    cout << GTEST_FLAG(stack_trace_depth);
+    return;
+  }
+
+  if (strcmp(flag, "throw_on_failure") == 0) {
+    cout << GTEST_FLAG(throw_on_failure);
+    return;
+  }
+
+  cout << "Invalid flag name " << flag
+       << ".  Valid names are break_on_failure, color, filter, etc.\n";
+  exit(1);
+}
+
+}  // namespace testing
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  if (argc != 2) {
+    cout << "Usage: gtest_env_var_test_ NAME_OF_FLAG\n";
+    return 1;
+  }
+
+  testing::PrintFlag(argv[1]);
+  return 0;
+}
diff --git a/third_party/googletest/src/test/gtest_environment_test.cc b/third_party/googletest/src/test/gtest_environment_test.cc
new file mode 100644 (file)
index 0000000..ec9aa2c
--- /dev/null
@@ -0,0 +1,191 @@
+// Copyright 2007, 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: wan@google.com (Zhanyong Wan)
+//
+// Tests using global test environments.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "gtest/gtest.h"
+
+#define GTEST_IMPLEMENTATION_ 1  // Required for the next #include.
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+GTEST_DECLARE_string_(filter);
+}
+
+namespace {
+
+enum FailureType {
+  NO_FAILURE, NON_FATAL_FAILURE, FATAL_FAILURE
+};
+
+// For testing using global test environments.
+class MyEnvironment : public testing::Environment {
+ public:
+  MyEnvironment() { Reset(); }
+
+  // Depending on the value of failure_in_set_up_, SetUp() will
+  // generate a non-fatal failure, generate a fatal failure, or
+  // succeed.
+  virtual void SetUp() {
+    set_up_was_run_ = true;
+
+    switch (failure_in_set_up_) {
+      case NON_FATAL_FAILURE:
+        ADD_FAILURE() << "Expected non-fatal failure in global set-up.";
+        break;
+      case FATAL_FAILURE:
+        FAIL() << "Expected fatal failure in global set-up.";
+        break;
+      default:
+        break;
+    }
+  }
+
+  // Generates a non-fatal failure.
+  virtual void TearDown() {
+    tear_down_was_run_ = true;
+    ADD_FAILURE() << "Expected non-fatal failure in global tear-down.";
+  }
+
+  // Resets the state of the environment s.t. it can be reused.
+  void Reset() {
+    failure_in_set_up_ = NO_FAILURE;
+    set_up_was_run_ = false;
+    tear_down_was_run_ = false;
+  }
+
+  // We call this function to set the type of failure SetUp() should
+  // generate.
+  void set_failure_in_set_up(FailureType type) {
+    failure_in_set_up_ = type;
+  }
+
+  // Was SetUp() run?
+  bool set_up_was_run() const { return set_up_was_run_; }
+
+  // Was TearDown() run?
+  bool tear_down_was_run() const { return tear_down_was_run_; }
+ private:
+  FailureType failure_in_set_up_;
+  bool set_up_was_run_;
+  bool tear_down_was_run_;
+};
+
+// Was the TEST run?
+bool test_was_run;
+
+// The sole purpose of this TEST is to enable us to check whether it
+// was run.
+TEST(FooTest, Bar) {
+  test_was_run = true;
+}
+
+// Prints the message and aborts the program if condition is false.
+void Check(bool condition, const char* msg) {
+  if (!condition) {
+    printf("FAILED: %s\n", msg);
+    testing::internal::posix::Abort();
+  }
+}
+
+// Runs the tests.  Return true iff successful.
+//
+// The 'failure' parameter specifies the type of failure that should
+// be generated by the global set-up.
+int RunAllTests(MyEnvironment* env, FailureType failure) {
+  env->Reset();
+  env->set_failure_in_set_up(failure);
+  test_was_run = false;
+  testing::internal::GetUnitTestImpl()->ClearAdHocTestResult();
+  return RUN_ALL_TESTS();
+}
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  // Registers a global test environment, and verifies that the
+  // registration function returns its argument.
+  MyEnvironment* const env = new MyEnvironment;
+  Check(testing::AddGlobalTestEnvironment(env) == env,
+        "AddGlobalTestEnvironment() should return its argument.");
+
+  // Verifies that RUN_ALL_TESTS() runs the tests when the global
+  // set-up is successful.
+  Check(RunAllTests(env, NO_FAILURE) != 0,
+        "RUN_ALL_TESTS() should return non-zero, as the global tear-down "
+        "should generate a failure.");
+  Check(test_was_run,
+        "The tests should run, as the global set-up should generate no "
+        "failure");
+  Check(env->tear_down_was_run(),
+        "The global tear-down should run, as the global set-up was run.");
+
+  // Verifies that RUN_ALL_TESTS() runs the tests when the global
+  // set-up generates no fatal failure.
+  Check(RunAllTests(env, NON_FATAL_FAILURE) != 0,
+        "RUN_ALL_TESTS() should return non-zero, as both the global set-up "
+        "and the global tear-down should generate a non-fatal failure.");
+  Check(test_was_run,
+        "The tests should run, as the global set-up should generate no "
+        "fatal failure.");
+  Check(env->tear_down_was_run(),
+        "The global tear-down should run, as the global set-up was run.");
+
+  // Verifies that RUN_ALL_TESTS() runs no test when the global set-up
+  // generates a fatal failure.
+  Check(RunAllTests(env, FATAL_FAILURE) != 0,
+        "RUN_ALL_TESTS() should return non-zero, as the global set-up "
+        "should generate a fatal failure.");
+  Check(!test_was_run,
+        "The tests should not run, as the global set-up should generate "
+        "a fatal failure.");
+  Check(env->tear_down_was_run(),
+        "The global tear-down should run, as the global set-up was run.");
+
+  // Verifies that RUN_ALL_TESTS() doesn't do global set-up or
+  // tear-down when there is no test to run.
+  testing::GTEST_FLAG(filter) = "-*";
+  Check(RunAllTests(env, NO_FAILURE) == 0,
+        "RUN_ALL_TESTS() should return zero, as there is no test to run.");
+  Check(!env->set_up_was_run(),
+        "The global set-up should not run, as there is no test to run.");
+  Check(!env->tear_down_was_run(),
+        "The global tear-down should not run, "
+        "as the global set-up was not run.");
+
+  printf("PASS\n");
+  return 0;
+}
diff --git a/third_party/googletest/src/test/gtest_filter_unittest.py b/third_party/googletest/src/test/gtest_filter_unittest.py
new file mode 100755 (executable)
index 0000000..0d1a770
--- /dev/null
@@ -0,0 +1,633 @@
+#!/usr/bin/env python
+#
+# Copyright 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.
+
+"""Unit test for Google Test test filters.
+
+A user can specify which test(s) in a Google Test program to run via either
+the GTEST_FILTER environment variable or the --gtest_filter flag.
+This script tests such functionality by invoking
+gtest_filter_unittest_ (a program written with Google Test) with different
+environments and command line flags.
+
+Note that test sharding may also influence which tests are filtered. Therefore,
+we test that here also.
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import re
+import sets
+import sys
+
+import gtest_test_utils
+
+# Constants.
+
+# Checks if this platform can pass empty environment variables to child
+# processes.  We set an env variable to an empty string and invoke a python
+# script in a subprocess to print whether the variable is STILL in
+# os.environ.  We then use 'eval' to parse the child's output so that an
+# exception is thrown if the input is anything other than 'True' nor 'False'.
+os.environ['EMPTY_VAR'] = ''
+child = gtest_test_utils.Subprocess(
+    [sys.executable, '-c', 'import os; print \'EMPTY_VAR\' in os.environ'])
+CAN_PASS_EMPTY_ENV = eval(child.output)
+
+
+# Check if this platform can unset environment variables in child processes.
+# We set an env variable to a non-empty string, unset it, and invoke
+# a python script in a subprocess to print whether the variable
+# is NO LONGER in os.environ.
+# We use 'eval' to parse the child's output so that an exception
+# is thrown if the input is neither 'True' nor 'False'.
+os.environ['UNSET_VAR'] = 'X'
+del os.environ['UNSET_VAR']
+child = gtest_test_utils.Subprocess(
+    [sys.executable, '-c', 'import os; print \'UNSET_VAR\' not in os.environ'])
+CAN_UNSET_ENV = eval(child.output)
+
+
+# Checks if we should test with an empty filter. This doesn't
+# make sense on platforms that cannot pass empty env variables (Win32)
+# and on platforms that cannot unset variables (since we cannot tell
+# the difference between "" and NULL -- Borland and Solaris < 5.10)
+CAN_TEST_EMPTY_FILTER = (CAN_PASS_EMPTY_ENV and CAN_UNSET_ENV)
+
+
+# The environment variable for specifying the test filters.
+FILTER_ENV_VAR = 'GTEST_FILTER'
+
+# The environment variables for test sharding.
+TOTAL_SHARDS_ENV_VAR = 'GTEST_TOTAL_SHARDS'
+SHARD_INDEX_ENV_VAR = 'GTEST_SHARD_INDEX'
+SHARD_STATUS_FILE_ENV_VAR = 'GTEST_SHARD_STATUS_FILE'
+
+# The command line flag for specifying the test filters.
+FILTER_FLAG = 'gtest_filter'
+
+# The command line flag for including disabled tests.
+ALSO_RUN_DISABED_TESTS_FLAG = 'gtest_also_run_disabled_tests'
+
+# Command to run the gtest_filter_unittest_ program.
+COMMAND = gtest_test_utils.GetTestExecutablePath('gtest_filter_unittest_')
+
+# Regex for determining whether parameterized tests are enabled in the binary.
+PARAM_TEST_REGEX = re.compile(r'/ParamTest')
+
+# Regex for parsing test case names from Google Test's output.
+TEST_CASE_REGEX = re.compile(r'^\[\-+\] \d+ tests? from (\w+(/\w+)?)')
+
+# Regex for parsing test names from Google Test's output.
+TEST_REGEX = re.compile(r'^\[\s*RUN\s*\].*\.(\w+(/\w+)?)')
+
+# The command line flag to tell Google Test to output the list of tests it
+# will run.
+LIST_TESTS_FLAG = '--gtest_list_tests'
+
+# Indicates whether Google Test supports death tests.
+SUPPORTS_DEATH_TESTS = 'HasDeathTest' in gtest_test_utils.Subprocess(
+    [COMMAND, LIST_TESTS_FLAG]).output
+
+# Full names of all tests in gtest_filter_unittests_.
+PARAM_TESTS = [
+    'SeqP/ParamTest.TestX/0',
+    'SeqP/ParamTest.TestX/1',
+    'SeqP/ParamTest.TestY/0',
+    'SeqP/ParamTest.TestY/1',
+    'SeqQ/ParamTest.TestX/0',
+    'SeqQ/ParamTest.TestX/1',
+    'SeqQ/ParamTest.TestY/0',
+    'SeqQ/ParamTest.TestY/1',
+    ]
+
+DISABLED_TESTS = [
+    'BarTest.DISABLED_TestFour',
+    'BarTest.DISABLED_TestFive',
+    'BazTest.DISABLED_TestC',
+    'DISABLED_FoobarTest.Test1',
+    'DISABLED_FoobarTest.DISABLED_Test2',
+    'DISABLED_FoobarbazTest.TestA',
+    ]
+
+if SUPPORTS_DEATH_TESTS:
+  DEATH_TESTS = [
+    'HasDeathTest.Test1',
+    'HasDeathTest.Test2',
+    ]
+else:
+  DEATH_TESTS = []
+
+# All the non-disabled tests.
+ACTIVE_TESTS = [
+    'FooTest.Abc',
+    'FooTest.Xyz',
+
+    'BarTest.TestOne',
+    'BarTest.TestTwo',
+    'BarTest.TestThree',
+
+    'BazTest.TestOne',
+    'BazTest.TestA',
+    'BazTest.TestB',
+    ] + DEATH_TESTS + PARAM_TESTS
+
+param_tests_present = None
+
+# Utilities.
+
+environ = os.environ.copy()
+
+
+def SetEnvVar(env_var, value):
+  """Sets the env variable to 'value'; unsets it when 'value' is None."""
+
+  if value is not None:
+    environ[env_var] = value
+  elif env_var in environ:
+    del environ[env_var]
+
+
+def RunAndReturnOutput(args = None):
+  """Runs the test program and returns its output."""
+
+  return gtest_test_utils.Subprocess([COMMAND] + (args or []),
+                                     env=environ).output
+
+
+def RunAndExtractTestList(args = None):
+  """Runs the test program and returns its exit code and a list of tests run."""
+
+  p = gtest_test_utils.Subprocess([COMMAND] + (args or []), env=environ)
+  tests_run = []
+  test_case = ''
+  test = ''
+  for line in p.output.split('\n'):
+    match = TEST_CASE_REGEX.match(line)
+    if match is not None:
+      test_case = match.group(1)
+    else:
+      match = TEST_REGEX.match(line)
+      if match is not None:
+        test = match.group(1)
+        tests_run.append(test_case + '.' + test)
+  return (tests_run, p.exit_code)
+
+
+def InvokeWithModifiedEnv(extra_env, function, *args, **kwargs):
+  """Runs the given function and arguments in a modified environment."""
+  try:
+    original_env = environ.copy()
+    environ.update(extra_env)
+    return function(*args, **kwargs)
+  finally:
+    environ.clear()
+    environ.update(original_env)
+
+
+def RunWithSharding(total_shards, shard_index, command):
+  """Runs a test program shard and returns exit code and a list of tests run."""
+
+  extra_env = {SHARD_INDEX_ENV_VAR: str(shard_index),
+               TOTAL_SHARDS_ENV_VAR: str(total_shards)}
+  return InvokeWithModifiedEnv(extra_env, RunAndExtractTestList, command)
+
+# The unit test.
+
+
+class GTestFilterUnitTest(gtest_test_utils.TestCase):
+  """Tests the env variable or the command line flag to filter tests."""
+
+  # Utilities.
+
+  def AssertSetEqual(self, lhs, rhs):
+    """Asserts that two sets are equal."""
+
+    for elem in lhs:
+      self.assert_(elem in rhs, '%s in %s' % (elem, rhs))
+
+    for elem in rhs:
+      self.assert_(elem in lhs, '%s in %s' % (elem, lhs))
+
+  def AssertPartitionIsValid(self, set_var, list_of_sets):
+    """Asserts that list_of_sets is a valid partition of set_var."""
+
+    full_partition = []
+    for slice_var in list_of_sets:
+      full_partition.extend(slice_var)
+    self.assertEqual(len(set_var), len(full_partition))
+    self.assertEqual(sets.Set(set_var), sets.Set(full_partition))
+
+  def AdjustForParameterizedTests(self, tests_to_run):
+    """Adjust tests_to_run in case value parameterized tests are disabled."""
+
+    global param_tests_present
+    if not param_tests_present:
+      return list(sets.Set(tests_to_run) - sets.Set(PARAM_TESTS))
+    else:
+      return tests_to_run
+
+  def RunAndVerify(self, gtest_filter, tests_to_run):
+    """Checks that the binary runs correct set of tests for a given filter."""
+
+    tests_to_run = self.AdjustForParameterizedTests(tests_to_run)
+
+    # First, tests using the environment variable.
+
+    # Windows removes empty variables from the environment when passing it
+    # to a new process.  This means it is impossible to pass an empty filter
+    # into a process using the environment variable.  However, we can still
+    # test the case when the variable is not supplied (i.e., gtest_filter is
+    # None).
+    # pylint: disable-msg=C6403
+    if CAN_TEST_EMPTY_FILTER or gtest_filter != '':
+      SetEnvVar(FILTER_ENV_VAR, gtest_filter)
+      tests_run = RunAndExtractTestList()[0]
+      SetEnvVar(FILTER_ENV_VAR, None)
+      self.AssertSetEqual(tests_run, tests_to_run)
+    # pylint: enable-msg=C6403
+
+    # Next, tests using the command line flag.
+
+    if gtest_filter is None:
+      args = []
+    else:
+      args = ['--%s=%s' % (FILTER_FLAG, gtest_filter)]
+
+    tests_run = RunAndExtractTestList(args)[0]
+    self.AssertSetEqual(tests_run, tests_to_run)
+
+  def RunAndVerifyWithSharding(self, gtest_filter, total_shards, tests_to_run,
+                               args=None, check_exit_0=False):
+    """Checks that binary runs correct tests for the given filter and shard.
+
+    Runs all shards of gtest_filter_unittest_ with the given filter, and
+    verifies that the right set of tests were run. The union of tests run
+    on each shard should be identical to tests_to_run, without duplicates.
+
+    Args:
+      gtest_filter: A filter to apply to the tests.
+      total_shards: A total number of shards to split test run into.
+      tests_to_run: A set of tests expected to run.
+      args   :      Arguments to pass to the to the test binary.
+      check_exit_0: When set to a true value, make sure that all shards
+                    return 0.
+    """
+
+    tests_to_run = self.AdjustForParameterizedTests(tests_to_run)
+
+    # Windows removes empty variables from the environment when passing it
+    # to a new process.  This means it is impossible to pass an empty filter
+    # into a process using the environment variable.  However, we can still
+    # test the case when the variable is not supplied (i.e., gtest_filter is
+    # None).
+    # pylint: disable-msg=C6403
+    if CAN_TEST_EMPTY_FILTER or gtest_filter != '':
+      SetEnvVar(FILTER_ENV_VAR, gtest_filter)
+      partition = []
+      for i in range(0, total_shards):
+        (tests_run, exit_code) = RunWithSharding(total_shards, i, args)
+        if check_exit_0:
+          self.assertEqual(0, exit_code)
+        partition.append(tests_run)
+
+      self.AssertPartitionIsValid(tests_to_run, partition)
+      SetEnvVar(FILTER_ENV_VAR, None)
+    # pylint: enable-msg=C6403
+
+  def RunAndVerifyAllowingDisabled(self, gtest_filter, tests_to_run):
+    """Checks that the binary runs correct set of tests for the given filter.
+
+    Runs gtest_filter_unittest_ with the given filter, and enables
+    disabled tests. Verifies that the right set of tests were run.
+
+    Args:
+      gtest_filter: A filter to apply to the tests.
+      tests_to_run: A set of tests expected to run.
+    """
+
+    tests_to_run = self.AdjustForParameterizedTests(tests_to_run)
+
+    # Construct the command line.
+    args = ['--%s' % ALSO_RUN_DISABED_TESTS_FLAG]
+    if gtest_filter is not None:
+      args.append('--%s=%s' % (FILTER_FLAG, gtest_filter))
+
+    tests_run = RunAndExtractTestList(args)[0]
+    self.AssertSetEqual(tests_run, tests_to_run)
+
+  def setUp(self):
+    """Sets up test case.
+
+    Determines whether value-parameterized tests are enabled in the binary and
+    sets the flags accordingly.
+    """
+
+    global param_tests_present
+    if param_tests_present is None:
+      param_tests_present = PARAM_TEST_REGEX.search(
+          RunAndReturnOutput()) is not None
+
+  def testDefaultBehavior(self):
+    """Tests the behavior of not specifying the filter."""
+
+    self.RunAndVerify(None, ACTIVE_TESTS)
+
+  def testDefaultBehaviorWithShards(self):
+    """Tests the behavior without the filter, with sharding enabled."""
+
+    self.RunAndVerifyWithSharding(None, 1, ACTIVE_TESTS)
+    self.RunAndVerifyWithSharding(None, 2, ACTIVE_TESTS)
+    self.RunAndVerifyWithSharding(None, len(ACTIVE_TESTS) - 1, ACTIVE_TESTS)
+    self.RunAndVerifyWithSharding(None, len(ACTIVE_TESTS), ACTIVE_TESTS)
+    self.RunAndVerifyWithSharding(None, len(ACTIVE_TESTS) + 1, ACTIVE_TESTS)
+
+  def testEmptyFilter(self):
+    """Tests an empty filter."""
+
+    self.RunAndVerify('', [])
+    self.RunAndVerifyWithSharding('', 1, [])
+    self.RunAndVerifyWithSharding('', 2, [])
+
+  def testBadFilter(self):
+    """Tests a filter that matches nothing."""
+
+    self.RunAndVerify('BadFilter', [])
+    self.RunAndVerifyAllowingDisabled('BadFilter', [])
+
+  def testFullName(self):
+    """Tests filtering by full name."""
+
+    self.RunAndVerify('FooTest.Xyz', ['FooTest.Xyz'])
+    self.RunAndVerifyAllowingDisabled('FooTest.Xyz', ['FooTest.Xyz'])
+    self.RunAndVerifyWithSharding('FooTest.Xyz', 5, ['FooTest.Xyz'])
+
+  def testUniversalFilters(self):
+    """Tests filters that match everything."""
+
+    self.RunAndVerify('*', ACTIVE_TESTS)
+    self.RunAndVerify('*.*', ACTIVE_TESTS)
+    self.RunAndVerifyWithSharding('*.*', len(ACTIVE_TESTS) - 3, ACTIVE_TESTS)
+    self.RunAndVerifyAllowingDisabled('*', ACTIVE_TESTS + DISABLED_TESTS)
+    self.RunAndVerifyAllowingDisabled('*.*', ACTIVE_TESTS + DISABLED_TESTS)
+
+  def testFilterByTestCase(self):
+    """Tests filtering by test case name."""
+
+    self.RunAndVerify('FooTest.*', ['FooTest.Abc', 'FooTest.Xyz'])
+
+    BAZ_TESTS = ['BazTest.TestOne', 'BazTest.TestA', 'BazTest.TestB']
+    self.RunAndVerify('BazTest.*', BAZ_TESTS)
+    self.RunAndVerifyAllowingDisabled('BazTest.*',
+                                      BAZ_TESTS + ['BazTest.DISABLED_TestC'])
+
+  def testFilterByTest(self):
+    """Tests filtering by test name."""
+
+    self.RunAndVerify('*.TestOne', ['BarTest.TestOne', 'BazTest.TestOne'])
+
+  def testFilterDisabledTests(self):
+    """Select only the disabled tests to run."""
+
+    self.RunAndVerify('DISABLED_FoobarTest.Test1', [])
+    self.RunAndVerifyAllowingDisabled('DISABLED_FoobarTest.Test1',
+                                      ['DISABLED_FoobarTest.Test1'])
+
+    self.RunAndVerify('*DISABLED_*', [])
+    self.RunAndVerifyAllowingDisabled('*DISABLED_*', DISABLED_TESTS)
+
+    self.RunAndVerify('*.DISABLED_*', [])
+    self.RunAndVerifyAllowingDisabled('*.DISABLED_*', [
+        'BarTest.DISABLED_TestFour',
+        'BarTest.DISABLED_TestFive',
+        'BazTest.DISABLED_TestC',
+        'DISABLED_FoobarTest.DISABLED_Test2',
+        ])
+
+    self.RunAndVerify('DISABLED_*', [])
+    self.RunAndVerifyAllowingDisabled('DISABLED_*', [
+        'DISABLED_FoobarTest.Test1',
+        'DISABLED_FoobarTest.DISABLED_Test2',
+        'DISABLED_FoobarbazTest.TestA',
+        ])
+
+  def testWildcardInTestCaseName(self):
+    """Tests using wildcard in the test case name."""
+
+    self.RunAndVerify('*a*.*', [
+        'BarTest.TestOne',
+        'BarTest.TestTwo',
+        'BarTest.TestThree',
+
+        'BazTest.TestOne',
+        'BazTest.TestA',
+        'BazTest.TestB', ] + DEATH_TESTS + PARAM_TESTS)
+
+  def testWildcardInTestName(self):
+    """Tests using wildcard in the test name."""
+
+    self.RunAndVerify('*.*A*', ['FooTest.Abc', 'BazTest.TestA'])
+
+  def testFilterWithoutDot(self):
+    """Tests a filter that has no '.' in it."""
+
+    self.RunAndVerify('*z*', [
+        'FooTest.Xyz',
+
+        'BazTest.TestOne',
+        'BazTest.TestA',
+        'BazTest.TestB',
+        ])
+
+  def testTwoPatterns(self):
+    """Tests filters that consist of two patterns."""
+
+    self.RunAndVerify('Foo*.*:*A*', [
+        'FooTest.Abc',
+        'FooTest.Xyz',
+
+        'BazTest.TestA',
+        ])
+
+    # An empty pattern + a non-empty one
+    self.RunAndVerify(':*A*', ['FooTest.Abc', 'BazTest.TestA'])
+
+  def testThreePatterns(self):
+    """Tests filters that consist of three patterns."""
+
+    self.RunAndVerify('*oo*:*A*:*One', [
+        'FooTest.Abc',
+        'FooTest.Xyz',
+
+        'BarTest.TestOne',
+
+        'BazTest.TestOne',
+        'BazTest.TestA',
+        ])
+
+    # The 2nd pattern is empty.
+    self.RunAndVerify('*oo*::*One', [
+        'FooTest.Abc',
+        'FooTest.Xyz',
+
+        'BarTest.TestOne',
+
+        'BazTest.TestOne',
+        ])
+
+    # The last 2 patterns are empty.
+    self.RunAndVerify('*oo*::', [
+        'FooTest.Abc',
+        'FooTest.Xyz',
+        ])
+
+  def testNegativeFilters(self):
+    self.RunAndVerify('*-BazTest.TestOne', [
+        'FooTest.Abc',
+        'FooTest.Xyz',
+
+        'BarTest.TestOne',
+        'BarTest.TestTwo',
+        'BarTest.TestThree',
+
+        'BazTest.TestA',
+        'BazTest.TestB',
+        ] + DEATH_TESTS + PARAM_TESTS)
+
+    self.RunAndVerify('*-FooTest.Abc:BazTest.*', [
+        'FooTest.Xyz',
+
+        'BarTest.TestOne',
+        'BarTest.TestTwo',
+        'BarTest.TestThree',
+        ] + DEATH_TESTS + PARAM_TESTS)
+
+    self.RunAndVerify('BarTest.*-BarTest.TestOne', [
+        'BarTest.TestTwo',
+        'BarTest.TestThree',
+        ])
+
+    # Tests without leading '*'.
+    self.RunAndVerify('-FooTest.Abc:FooTest.Xyz:BazTest.*', [
+        'BarTest.TestOne',
+        'BarTest.TestTwo',
+        'BarTest.TestThree',
+        ] + DEATH_TESTS + PARAM_TESTS)
+
+    # Value parameterized tests.
+    self.RunAndVerify('*/*', PARAM_TESTS)
+
+    # Value parameterized tests filtering by the sequence name.
+    self.RunAndVerify('SeqP/*', [
+        'SeqP/ParamTest.TestX/0',
+        'SeqP/ParamTest.TestX/1',
+        'SeqP/ParamTest.TestY/0',
+        'SeqP/ParamTest.TestY/1',
+        ])
+
+    # Value parameterized tests filtering by the test name.
+    self.RunAndVerify('*/0', [
+        'SeqP/ParamTest.TestX/0',
+        'SeqP/ParamTest.TestY/0',
+        'SeqQ/ParamTest.TestX/0',
+        'SeqQ/ParamTest.TestY/0',
+        ])
+
+  def testFlagOverridesEnvVar(self):
+    """Tests that the filter flag overrides the filtering env. variable."""
+
+    SetEnvVar(FILTER_ENV_VAR, 'Foo*')
+    args = ['--%s=%s' % (FILTER_FLAG, '*One')]
+    tests_run = RunAndExtractTestList(args)[0]
+    SetEnvVar(FILTER_ENV_VAR, None)
+
+    self.AssertSetEqual(tests_run, ['BarTest.TestOne', 'BazTest.TestOne'])
+
+  def testShardStatusFileIsCreated(self):
+    """Tests that the shard file is created if specified in the environment."""
+
+    shard_status_file = os.path.join(gtest_test_utils.GetTempDir(),
+                                     'shard_status_file')
+    self.assert_(not os.path.exists(shard_status_file))
+
+    extra_env = {SHARD_STATUS_FILE_ENV_VAR: shard_status_file}
+    try:
+      InvokeWithModifiedEnv(extra_env, RunAndReturnOutput)
+    finally:
+      self.assert_(os.path.exists(shard_status_file))
+      os.remove(shard_status_file)
+
+  def testShardStatusFileIsCreatedWithListTests(self):
+    """Tests that the shard file is created with the "list_tests" flag."""
+
+    shard_status_file = os.path.join(gtest_test_utils.GetTempDir(),
+                                     'shard_status_file2')
+    self.assert_(not os.path.exists(shard_status_file))
+
+    extra_env = {SHARD_STATUS_FILE_ENV_VAR: shard_status_file}
+    try:
+      output = InvokeWithModifiedEnv(extra_env,
+                                     RunAndReturnOutput,
+                                     [LIST_TESTS_FLAG])
+    finally:
+      # This assertion ensures that Google Test enumerated the tests as
+      # opposed to running them.
+      self.assert_('[==========]' not in output,
+                   'Unexpected output during test enumeration.\n'
+                   'Please ensure that LIST_TESTS_FLAG is assigned the\n'
+                   'correct flag value for listing Google Test tests.')
+
+      self.assert_(os.path.exists(shard_status_file))
+      os.remove(shard_status_file)
+
+  if SUPPORTS_DEATH_TESTS:
+    def testShardingWorksWithDeathTests(self):
+      """Tests integration with death tests and sharding."""
+
+      gtest_filter = 'HasDeathTest.*:SeqP/*'
+      expected_tests = [
+          'HasDeathTest.Test1',
+          'HasDeathTest.Test2',
+
+          'SeqP/ParamTest.TestX/0',
+          'SeqP/ParamTest.TestX/1',
+          'SeqP/ParamTest.TestY/0',
+          'SeqP/ParamTest.TestY/1',
+          ]
+
+      for flag in ['--gtest_death_test_style=threadsafe',
+                   '--gtest_death_test_style=fast']:
+        self.RunAndVerifyWithSharding(gtest_filter, 3, expected_tests,
+                                      check_exit_0=True, args=[flag])
+        self.RunAndVerifyWithSharding(gtest_filter, 5, expected_tests,
+                                      check_exit_0=True, args=[flag])
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/src/test/gtest_filter_unittest_.cc b/third_party/googletest/src/test/gtest_filter_unittest_.cc
new file mode 100644 (file)
index 0000000..77deffc
--- /dev/null
@@ -0,0 +1,140 @@
+// Copyright 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: wan@google.com (Zhanyong Wan)
+
+// Unit test for Google Test test filters.
+//
+// A user can specify which test(s) in a Google Test program to run via
+// either the GTEST_FILTER environment variable or the --gtest_filter
+// flag.  This is used for testing such functionality.
+//
+// The program will be invoked from a Python unit test.  Don't run it
+// directly.
+
+#include "gtest/gtest.h"
+
+namespace {
+
+// Test case FooTest.
+
+class FooTest : public testing::Test {
+};
+
+TEST_F(FooTest, Abc) {
+}
+
+TEST_F(FooTest, Xyz) {
+  FAIL() << "Expected failure.";
+}
+
+// Test case BarTest.
+
+TEST(BarTest, TestOne) {
+}
+
+TEST(BarTest, TestTwo) {
+}
+
+TEST(BarTest, TestThree) {
+}
+
+TEST(BarTest, DISABLED_TestFour) {
+  FAIL() << "Expected failure.";
+}
+
+TEST(BarTest, DISABLED_TestFive) {
+  FAIL() << "Expected failure.";
+}
+
+// Test case BazTest.
+
+TEST(BazTest, TestOne) {
+  FAIL() << "Expected failure.";
+}
+
+TEST(BazTest, TestA) {
+}
+
+TEST(BazTest, TestB) {
+}
+
+TEST(BazTest, DISABLED_TestC) {
+  FAIL() << "Expected failure.";
+}
+
+// Test case HasDeathTest
+
+TEST(HasDeathTest, Test1) {
+  EXPECT_DEATH_IF_SUPPORTED(exit(1), ".*");
+}
+
+// We need at least two death tests to make sure that the all death tests
+// aren't on the first shard.
+TEST(HasDeathTest, Test2) {
+  EXPECT_DEATH_IF_SUPPORTED(exit(1), ".*");
+}
+
+// Test case FoobarTest
+
+TEST(DISABLED_FoobarTest, Test1) {
+  FAIL() << "Expected failure.";
+}
+
+TEST(DISABLED_FoobarTest, DISABLED_Test2) {
+  FAIL() << "Expected failure.";
+}
+
+// Test case FoobarbazTest
+
+TEST(DISABLED_FoobarbazTest, TestA) {
+  FAIL() << "Expected failure.";
+}
+
+#if GTEST_HAS_PARAM_TEST
+class ParamTest : public testing::TestWithParam<int> {
+};
+
+TEST_P(ParamTest, TestX) {
+}
+
+TEST_P(ParamTest, TestY) {
+}
+
+INSTANTIATE_TEST_CASE_P(SeqP, ParamTest, testing::Values(1, 2));
+INSTANTIATE_TEST_CASE_P(SeqQ, ParamTest, testing::Values(5, 6));
+#endif  // GTEST_HAS_PARAM_TEST
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/src/test/gtest_help_test.py b/third_party/googletest/src/test/gtest_help_test.py
new file mode 100755 (executable)
index 0000000..093c838
--- /dev/null
@@ -0,0 +1,172 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, 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.
+
+"""Tests the --help flag of Google C++ Testing Framework.
+
+SYNOPSIS
+       gtest_help_test.py --build_dir=BUILD/DIR
+         # where BUILD/DIR contains the built gtest_help_test_ file.
+       gtest_help_test.py
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import re
+import gtest_test_utils
+
+
+IS_LINUX = os.name == 'posix' and os.uname()[0] == 'Linux'
+IS_WINDOWS = os.name == 'nt'
+
+PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath('gtest_help_test_')
+FLAG_PREFIX = '--gtest_'
+DEATH_TEST_STYLE_FLAG = FLAG_PREFIX + 'death_test_style'
+STREAM_RESULT_TO_FLAG = FLAG_PREFIX + 'stream_result_to'
+UNKNOWN_FLAG = FLAG_PREFIX + 'unknown_flag_for_testing'
+LIST_TESTS_FLAG = FLAG_PREFIX + 'list_tests'
+INCORRECT_FLAG_VARIANTS = [re.sub('^--', '-', LIST_TESTS_FLAG),
+                           re.sub('^--', '/', LIST_TESTS_FLAG),
+                           re.sub('_', '-', LIST_TESTS_FLAG)]
+INTERNAL_FLAG_FOR_TESTING = FLAG_PREFIX + 'internal_flag_for_testing'
+
+SUPPORTS_DEATH_TESTS = "DeathTest" in gtest_test_utils.Subprocess(
+    [PROGRAM_PATH, LIST_TESTS_FLAG]).output
+
+# The help message must match this regex.
+HELP_REGEX = re.compile(
+    FLAG_PREFIX + r'list_tests.*' +
+    FLAG_PREFIX + r'filter=.*' +
+    FLAG_PREFIX + r'also_run_disabled_tests.*' +
+    FLAG_PREFIX + r'repeat=.*' +
+    FLAG_PREFIX + r'shuffle.*' +
+    FLAG_PREFIX + r'random_seed=.*' +
+    FLAG_PREFIX + r'color=.*' +
+    FLAG_PREFIX + r'print_time.*' +
+    FLAG_PREFIX + r'output=.*' +
+    FLAG_PREFIX + r'break_on_failure.*' +
+    FLAG_PREFIX + r'throw_on_failure.*' +
+    FLAG_PREFIX + r'catch_exceptions=0.*',
+    re.DOTALL)
+
+
+def RunWithFlag(flag):
+  """Runs gtest_help_test_ with the given flag.
+
+  Returns:
+    the exit code and the text output as a tuple.
+  Args:
+    flag: the command-line flag to pass to gtest_help_test_, or None.
+  """
+
+  if flag is None:
+    command = [PROGRAM_PATH]
+  else:
+    command = [PROGRAM_PATH, flag]
+  child = gtest_test_utils.Subprocess(command)
+  return child.exit_code, child.output
+
+
+class GTestHelpTest(gtest_test_utils.TestCase):
+  """Tests the --help flag and its equivalent forms."""
+
+  def TestHelpFlag(self, flag):
+    """Verifies correct behavior when help flag is specified.
+
+    The right message must be printed and the tests must
+    skipped when the given flag is specified.
+
+    Args:
+      flag:  A flag to pass to the binary or None.
+    """
+
+    exit_code, output = RunWithFlag(flag)
+    self.assertEquals(0, exit_code)
+    self.assert_(HELP_REGEX.search(output), output)
+
+    if IS_LINUX:
+      self.assert_(STREAM_RESULT_TO_FLAG in output, output)
+    else:
+      self.assert_(STREAM_RESULT_TO_FLAG not in output, output)
+
+    if SUPPORTS_DEATH_TESTS and not IS_WINDOWS:
+      self.assert_(DEATH_TEST_STYLE_FLAG in output, output)
+    else:
+      self.assert_(DEATH_TEST_STYLE_FLAG not in output, output)
+
+  def TestNonHelpFlag(self, flag):
+    """Verifies correct behavior when no help flag is specified.
+
+    Verifies that when no help flag is specified, the tests are run
+    and the help message is not printed.
+
+    Args:
+      flag:  A flag to pass to the binary or None.
+    """
+
+    exit_code, output = RunWithFlag(flag)
+    self.assert_(exit_code != 0)
+    self.assert_(not HELP_REGEX.search(output), output)
+
+  def testPrintsHelpWithFullFlag(self):
+    self.TestHelpFlag('--help')
+
+  def testPrintsHelpWithShortFlag(self):
+    self.TestHelpFlag('-h')
+
+  def testPrintsHelpWithQuestionFlag(self):
+    self.TestHelpFlag('-?')
+
+  def testPrintsHelpWithWindowsStyleQuestionFlag(self):
+    self.TestHelpFlag('/?')
+
+  def testPrintsHelpWithUnrecognizedGoogleTestFlag(self):
+    self.TestHelpFlag(UNKNOWN_FLAG)
+
+  def testPrintsHelpWithIncorrectFlagStyle(self):
+    for incorrect_flag in INCORRECT_FLAG_VARIANTS:
+      self.TestHelpFlag(incorrect_flag)
+
+  def testRunsTestsWithoutHelpFlag(self):
+    """Verifies that when no help flag is specified, the tests are run
+    and the help message is not printed."""
+
+    self.TestNonHelpFlag(None)
+
+  def testRunsTestsWithGtestInternalFlag(self):
+    """Verifies that the tests are run and no help message is printed when
+    a flag starting with Google Test prefix and 'internal_' is supplied."""
+
+    self.TestNonHelpFlag(INTERNAL_FLAG_FOR_TESTING)
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/src/test/gtest_help_test_.cc b/third_party/googletest/src/test/gtest_help_test_.cc
new file mode 100644 (file)
index 0000000..31f78c2
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2009, 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: wan@google.com (Zhanyong Wan)
+
+// This program is meant to be run by gtest_help_test.py.  Do not run
+// it directly.
+
+#include "gtest/gtest.h"
+
+// When a help flag is specified, this program should skip the tests
+// and exit with 0; otherwise the following test will be executed,
+// causing this program to exit with a non-zero code.
+TEST(HelpFlagTest, ShouldNotBeRun) {
+  ASSERT_TRUE(false) << "Tests shouldn't be run when --help is specified.";
+}
+
+#if GTEST_HAS_DEATH_TEST
+TEST(DeathTest, UsedByPythonScriptToDetectSupportForDeathTestsInThisBinary) {}
+#endif
diff --git a/third_party/googletest/src/test/gtest_list_tests_unittest.py b/third_party/googletest/src/test/gtest_list_tests_unittest.py
new file mode 100755 (executable)
index 0000000..ce8c3ef
--- /dev/null
@@ -0,0 +1,177 @@
+#!/usr/bin/env python
+#
+# Copyright 2006, 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.
+
+"""Unit test for Google Test's --gtest_list_tests flag.
+
+A user can ask Google Test to list all tests by specifying the
+--gtest_list_tests flag.  This script tests such functionality
+by invoking gtest_list_tests_unittest_ (a program written with
+Google Test) the command line flags.
+"""
+
+__author__ = 'phanna@google.com (Patrick Hanna)'
+
+import gtest_test_utils
+
+
+# Constants.
+
+# The command line flag for enabling/disabling listing all tests.
+LIST_TESTS_FLAG = 'gtest_list_tests'
+
+# Path to the gtest_list_tests_unittest_ program.
+EXE_PATH = gtest_test_utils.GetTestExecutablePath('gtest_list_tests_unittest_')
+
+# The expected output when running gtest_list_tests_unittest_ with
+# --gtest_list_tests
+EXPECTED_OUTPUT_NO_FILTER = """FooDeathTest.
+  Test1
+Foo.
+  Bar1
+  Bar2
+  DISABLED_Bar3
+Abc.
+  Xyz
+  Def
+FooBar.
+  Baz
+FooTest.
+  Test1
+  DISABLED_Test2
+  Test3
+"""
+
+# The expected output when running gtest_list_tests_unittest_ with
+# --gtest_list_tests and --gtest_filter=Foo*.
+EXPECTED_OUTPUT_FILTER_FOO = """FooDeathTest.
+  Test1
+Foo.
+  Bar1
+  Bar2
+  DISABLED_Bar3
+FooBar.
+  Baz
+FooTest.
+  Test1
+  DISABLED_Test2
+  Test3
+"""
+
+# Utilities.
+
+
+def Run(args):
+  """Runs gtest_list_tests_unittest_ and returns the list of tests printed."""
+
+  return gtest_test_utils.Subprocess([EXE_PATH] + args,
+                                     capture_stderr=False).output
+
+
+# The unit test.
+
+class GTestListTestsUnitTest(gtest_test_utils.TestCase):
+  """Tests using the --gtest_list_tests flag to list all tests."""
+
+  def RunAndVerify(self, flag_value, expected_output, other_flag):
+    """Runs gtest_list_tests_unittest_ and verifies that it prints
+    the correct tests.
+
+    Args:
+      flag_value:       value of the --gtest_list_tests flag;
+                        None if the flag should not be present.
+
+      expected_output:  the expected output after running command;
+
+      other_flag:       a different flag to be passed to command
+                        along with gtest_list_tests;
+                        None if the flag should not be present.
+    """
+
+    if flag_value is None:
+      flag = ''
+      flag_expression = 'not set'
+    elif flag_value == '0':
+      flag = '--%s=0' % LIST_TESTS_FLAG
+      flag_expression = '0'
+    else:
+      flag = '--%s' % LIST_TESTS_FLAG
+      flag_expression = '1'
+
+    args = [flag]
+
+    if other_flag is not None:
+      args += [other_flag]
+
+    output = Run(args)
+
+    msg = ('when %s is %s, the output of "%s" is "%s".' %
+           (LIST_TESTS_FLAG, flag_expression, ' '.join(args), output))
+
+    if expected_output is not None:
+      self.assert_(output == expected_output, msg)
+    else:
+      self.assert_(output != EXPECTED_OUTPUT_NO_FILTER, msg)
+
+  def testDefaultBehavior(self):
+    """Tests the behavior of the default mode."""
+
+    self.RunAndVerify(flag_value=None,
+                      expected_output=None,
+                      other_flag=None)
+
+  def testFlag(self):
+    """Tests using the --gtest_list_tests flag."""
+
+    self.RunAndVerify(flag_value='0',
+                      expected_output=None,
+                      other_flag=None)
+    self.RunAndVerify(flag_value='1',
+                      expected_output=EXPECTED_OUTPUT_NO_FILTER,
+                      other_flag=None)
+
+  def testOverrideNonFilterFlags(self):
+    """Tests that --gtest_list_tests overrides the non-filter flags."""
+
+    self.RunAndVerify(flag_value='1',
+                      expected_output=EXPECTED_OUTPUT_NO_FILTER,
+                      other_flag='--gtest_break_on_failure')
+
+  def testWithFilterFlags(self):
+    """Tests that --gtest_list_tests takes into account the
+    --gtest_filter flag."""
+
+    self.RunAndVerify(flag_value='1',
+                      expected_output=EXPECTED_OUTPUT_FILTER_FOO,
+                      other_flag='--gtest_filter=Foo*')
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/src/test/gtest_list_tests_unittest_.cc b/third_party/googletest/src/test/gtest_list_tests_unittest_.cc
new file mode 100644 (file)
index 0000000..2b1d078
--- /dev/null
@@ -0,0 +1,85 @@
+// Copyright 2006, 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: phanna@google.com (Patrick Hanna)
+
+// Unit test for Google Test's --gtest_list_tests flag.
+//
+// A user can ask Google Test to list all tests that will run
+// so that when using a filter, a user will know what
+// tests to look for. The tests will not be run after listing.
+//
+// This program will be invoked from a Python unit test.
+// Don't run it directly.
+
+#include "gtest/gtest.h"
+
+namespace {
+
+// Several different test cases and tests that will be listed.
+TEST(Foo, Bar1) {
+}
+
+TEST(Foo, Bar2) {
+}
+
+TEST(Foo, DISABLED_Bar3) {
+}
+
+TEST(Abc, Xyz) {
+}
+
+TEST(Abc, Def) {
+}
+
+TEST(FooBar, Baz) {
+}
+
+class FooTest : public testing::Test {
+};
+
+TEST_F(FooTest, Test1) {
+}
+
+TEST_F(FooTest, DISABLED_Test2) {
+}
+
+TEST_F(FooTest, Test3) {
+}
+
+TEST(FooDeathTest, Test1) {
+}
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/src/test/gtest_main_unittest.cc b/third_party/googletest/src/test/gtest_main_unittest.cc
new file mode 100644 (file)
index 0000000..ecd9bb8
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright 2006, 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: wan@google.com (Zhanyong Wan)
+
+#include "gtest/gtest.h"
+
+// Tests that we don't have to define main() when we link to
+// gtest_main instead of gtest.
+
+namespace {
+
+TEST(GTestMainTest, ShouldSucceed) {
+}
+
+}  // namespace
+
+// We are using the main() function defined in src/gtest_main.cc, so
+// we don't define it here.
diff --git a/third_party/googletest/src/test/gtest_no_test_unittest.cc b/third_party/googletest/src/test/gtest_no_test_unittest.cc
new file mode 100644 (file)
index 0000000..e3a85f1
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright 2006, 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.
+
+// Tests that a Google Test program that has no test defined can run
+// successfully.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "gtest/gtest.h"
+
+
+int main(int argc, char **argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  // An ad-hoc assertion outside of all tests.
+  //
+  // This serves three purposes:
+  //
+  // 1. It verifies that an ad-hoc assertion can be executed even if
+  //    no test is defined.
+  // 2. It verifies that a failed ad-hoc assertion causes the test
+  //    program to fail.
+  // 3. We had a bug where the XML output won't be generated if an
+  //    assertion is executed before RUN_ALL_TESTS() is called, even
+  //    though --gtest_output=xml is specified.  This makes sure the
+  //    bug is fixed and doesn't regress.
+  EXPECT_EQ(1, 2);
+
+  // The above EXPECT_EQ() should cause RUN_ALL_TESTS() to return non-zero.
+  return RUN_ALL_TESTS() ? 0 : 1;
+}
diff --git a/third_party/googletest/src/test/gtest_output_test.py b/third_party/googletest/src/test/gtest_output_test.py
new file mode 100755 (executable)
index 0000000..f409e2a
--- /dev/null
@@ -0,0 +1,335 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, 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.
+
+"""Tests the text output of Google C++ Testing Framework.
+
+SYNOPSIS
+       gtest_output_test.py --build_dir=BUILD/DIR --gengolden
+         # where BUILD/DIR contains the built gtest_output_test_ file.
+       gtest_output_test.py --gengolden
+       gtest_output_test.py
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import re
+import sys
+import gtest_test_utils
+
+
+# The flag for generating the golden file
+GENGOLDEN_FLAG = '--gengolden'
+CATCH_EXCEPTIONS_ENV_VAR_NAME = 'GTEST_CATCH_EXCEPTIONS'
+
+IS_WINDOWS = os.name == 'nt'
+
+# TODO(vladl@google.com): remove the _lin suffix.
+GOLDEN_NAME = 'gtest_output_test_golden_lin.txt'
+
+PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath('gtest_output_test_')
+
+# At least one command we exercise must not have the
+# --gtest_internal_skip_environment_and_ad_hoc_tests flag.
+COMMAND_LIST_TESTS = ({}, [PROGRAM_PATH, '--gtest_list_tests'])
+COMMAND_WITH_COLOR = ({}, [PROGRAM_PATH, '--gtest_color=yes'])
+COMMAND_WITH_TIME = ({}, [PROGRAM_PATH,
+                          '--gtest_print_time',
+                          '--gtest_internal_skip_environment_and_ad_hoc_tests',
+                          '--gtest_filter=FatalFailureTest.*:LoggingTest.*'])
+COMMAND_WITH_DISABLED = (
+    {}, [PROGRAM_PATH,
+         '--gtest_also_run_disabled_tests',
+         '--gtest_internal_skip_environment_and_ad_hoc_tests',
+         '--gtest_filter=*DISABLED_*'])
+COMMAND_WITH_SHARDING = (
+    {'GTEST_SHARD_INDEX': '1', 'GTEST_TOTAL_SHARDS': '2'},
+    [PROGRAM_PATH,
+     '--gtest_internal_skip_environment_and_ad_hoc_tests',
+     '--gtest_filter=PassingTest.*'])
+
+GOLDEN_PATH = os.path.join(gtest_test_utils.GetSourceDir(), GOLDEN_NAME)
+
+
+def ToUnixLineEnding(s):
+  """Changes all Windows/Mac line endings in s to UNIX line endings."""
+
+  return s.replace('\r\n', '\n').replace('\r', '\n')
+
+
+def RemoveLocations(test_output):
+  """Removes all file location info from a Google Test program's output.
+
+  Args:
+       test_output:  the output of a Google Test program.
+
+  Returns:
+       output with all file location info (in the form of
+       'DIRECTORY/FILE_NAME:LINE_NUMBER: 'or
+       'DIRECTORY\\FILE_NAME(LINE_NUMBER): ') replaced by
+       'FILE_NAME:#: '.
+  """
+
+  return re.sub(r'.*[/\\](.+)(\:\d+|\(\d+\))\: ', r'\1:#: ', test_output)
+
+
+def RemoveStackTraceDetails(output):
+  """Removes all stack traces from a Google Test program's output."""
+
+  # *? means "find the shortest string that matches".
+  return re.sub(r'Stack trace:(.|\n)*?\n\n',
+                'Stack trace: (omitted)\n\n', output)
+
+
+def RemoveStackTraces(output):
+  """Removes all traces of stack traces from a Google Test program's output."""
+
+  # *? means "find the shortest string that matches".
+  return re.sub(r'Stack trace:(.|\n)*?\n\n', '', output)
+
+
+def RemoveTime(output):
+  """Removes all time information from a Google Test program's output."""
+
+  return re.sub(r'\(\d+ ms', '(? ms', output)
+
+
+def RemoveTypeInfoDetails(test_output):
+  """Removes compiler-specific type info from Google Test program's output.
+
+  Args:
+       test_output:  the output of a Google Test program.
+
+  Returns:
+       output with type information normalized to canonical form.
+  """
+
+  # some compilers output the name of type 'unsigned int' as 'unsigned'
+  return re.sub(r'unsigned int', 'unsigned', test_output)
+
+
+def NormalizeToCurrentPlatform(test_output):
+  """Normalizes platform specific output details for easier comparison."""
+
+  if IS_WINDOWS:
+    # Removes the color information that is not present on Windows.
+    test_output = re.sub('\x1b\\[(0;3\d)?m', '', test_output)
+    # Changes failure message headers into the Windows format.
+    test_output = re.sub(r': Failure\n', r': error: ', test_output)
+    # Changes file(line_number) to file:line_number.
+    test_output = re.sub(r'((\w|\.)+)\((\d+)\):', r'\1:\3:', test_output)
+
+  return test_output
+
+
+def RemoveTestCounts(output):
+  """Removes test counts from a Google Test program's output."""
+
+  output = re.sub(r'\d+ tests?, listed below',
+                  '? tests, listed below', output)
+  output = re.sub(r'\d+ FAILED TESTS',
+                  '? FAILED TESTS', output)
+  output = re.sub(r'\d+ tests? from \d+ test cases?',
+                  '? tests from ? test cases', output)
+  output = re.sub(r'\d+ tests? from ([a-zA-Z_])',
+                  r'? tests from \1', output)
+  return re.sub(r'\d+ tests?\.', '? tests.', output)
+
+
+def RemoveMatchingTests(test_output, pattern):
+  """Removes output of specified tests from a Google Test program's output.
+
+  This function strips not only the beginning and the end of a test but also
+  all output in between.
+
+  Args:
+    test_output:       A string containing the test output.
+    pattern:           A regex string that matches names of test cases or
+                       tests to remove.
+
+  Returns:
+    Contents of test_output with tests whose names match pattern removed.
+  """
+
+  test_output = re.sub(
+      r'.*\[ RUN      \] .*%s(.|\n)*?\[(  FAILED  |       OK )\] .*%s.*\n' % (
+          pattern, pattern),
+      '',
+      test_output)
+  return re.sub(r'.*%s.*\n' % pattern, '', test_output)
+
+
+def NormalizeOutput(output):
+  """Normalizes output (the output of gtest_output_test_.exe)."""
+
+  output = ToUnixLineEnding(output)
+  output = RemoveLocations(output)
+  output = RemoveStackTraceDetails(output)
+  output = RemoveTime(output)
+  return output
+
+
+def GetShellCommandOutput(env_cmd):
+  """Runs a command in a sub-process, and returns its output in a string.
+
+  Args:
+    env_cmd: The shell command. A 2-tuple where element 0 is a dict of extra
+             environment variables to set, and element 1 is a string with
+             the command and any flags.
+
+  Returns:
+    A string with the command's combined standard and diagnostic output.
+  """
+
+  # Spawns cmd in a sub-process, and gets its standard I/O file objects.
+  # Set and save the environment properly.
+  environ = os.environ.copy()
+  environ.update(env_cmd[0])
+  p = gtest_test_utils.Subprocess(env_cmd[1], env=environ)
+
+  return p.output
+
+
+def GetCommandOutput(env_cmd):
+  """Runs a command and returns its output with all file location
+  info stripped off.
+
+  Args:
+    env_cmd:  The shell command. A 2-tuple where element 0 is a dict of extra
+              environment variables to set, and element 1 is a string with
+              the command and any flags.
+  """
+
+  # Disables exception pop-ups on Windows.
+  environ, cmdline = env_cmd
+  environ = dict(environ)  # Ensures we are modifying a copy.
+  environ[CATCH_EXCEPTIONS_ENV_VAR_NAME] = '1'
+  return NormalizeOutput(GetShellCommandOutput((environ, cmdline)))
+
+
+def GetOutputOfAllCommands():
+  """Returns concatenated output from several representative commands."""
+
+  return (GetCommandOutput(COMMAND_WITH_COLOR) +
+          GetCommandOutput(COMMAND_WITH_TIME) +
+          GetCommandOutput(COMMAND_WITH_DISABLED) +
+          GetCommandOutput(COMMAND_WITH_SHARDING))
+
+
+test_list = GetShellCommandOutput(COMMAND_LIST_TESTS)
+SUPPORTS_DEATH_TESTS = 'DeathTest' in test_list
+SUPPORTS_TYPED_TESTS = 'TypedTest' in test_list
+SUPPORTS_THREADS = 'ExpectFailureWithThreadsTest' in test_list
+SUPPORTS_STACK_TRACES = False
+
+CAN_GENERATE_GOLDEN_FILE = (SUPPORTS_DEATH_TESTS and
+                            SUPPORTS_TYPED_TESTS and
+                            SUPPORTS_THREADS)
+
+
+class GTestOutputTest(gtest_test_utils.TestCase):
+  def RemoveUnsupportedTests(self, test_output):
+    if not SUPPORTS_DEATH_TESTS:
+      test_output = RemoveMatchingTests(test_output, 'DeathTest')
+    if not SUPPORTS_TYPED_TESTS:
+      test_output = RemoveMatchingTests(test_output, 'TypedTest')
+      test_output = RemoveMatchingTests(test_output, 'TypedDeathTest')
+      test_output = RemoveMatchingTests(test_output, 'TypeParamDeathTest')
+    if not SUPPORTS_THREADS:
+      test_output = RemoveMatchingTests(test_output,
+                                        'ExpectFailureWithThreadsTest')
+      test_output = RemoveMatchingTests(test_output,
+                                        'ScopedFakeTestPartResultReporterTest')
+      test_output = RemoveMatchingTests(test_output,
+                                        'WorksConcurrently')
+    if not SUPPORTS_STACK_TRACES:
+      test_output = RemoveStackTraces(test_output)
+
+    return test_output
+
+  def testOutput(self):
+    output = GetOutputOfAllCommands()
+
+    golden_file = open(GOLDEN_PATH, 'rb')
+    # A mis-configured source control system can cause \r appear in EOL
+    # sequences when we read the golden file irrespective of an operating
+    # system used. Therefore, we need to strip those \r's from newlines
+    # unconditionally.
+    golden = ToUnixLineEnding(golden_file.read())
+    golden_file.close()
+
+    # We want the test to pass regardless of certain features being
+    # supported or not.
+
+    # We still have to remove type name specifics in all cases.
+    normalized_actual = RemoveTypeInfoDetails(output)
+    normalized_golden = RemoveTypeInfoDetails(golden)
+
+    if CAN_GENERATE_GOLDEN_FILE:
+      self.assertEqual(normalized_golden, normalized_actual)
+    else:
+      normalized_actual = NormalizeToCurrentPlatform(
+          RemoveTestCounts(normalized_actual))
+      normalized_golden = NormalizeToCurrentPlatform(
+          RemoveTestCounts(self.RemoveUnsupportedTests(normalized_golden)))
+
+      # This code is very handy when debugging golden file differences:
+      if os.getenv('DEBUG_GTEST_OUTPUT_TEST'):
+        open(os.path.join(
+            gtest_test_utils.GetSourceDir(),
+            '_gtest_output_test_normalized_actual.txt'), 'wb').write(
+                normalized_actual)
+        open(os.path.join(
+            gtest_test_utils.GetSourceDir(),
+            '_gtest_output_test_normalized_golden.txt'), 'wb').write(
+                normalized_golden)
+
+      self.assertEqual(normalized_golden, normalized_actual)
+
+
+if __name__ == '__main__':
+  if sys.argv[1:] == [GENGOLDEN_FLAG]:
+    if CAN_GENERATE_GOLDEN_FILE:
+      output = GetOutputOfAllCommands()
+      golden_file = open(GOLDEN_PATH, 'wb')
+      golden_file.write(output)
+      golden_file.close()
+    else:
+      message = (
+          """Unable to write a golden file when compiled in an environment
+that does not support all the required features (death tests, typed tests,
+and multiple threads).  Please generate the golden file using a binary built
+with those features enabled.""")
+
+      sys.stderr.write(message)
+      sys.exit(1)
+  else:
+    gtest_test_utils.Main()
diff --git a/third_party/googletest/src/test/gtest_output_test_.cc b/third_party/googletest/src/test/gtest_output_test_.cc
new file mode 100644 (file)
index 0000000..13dbec4
--- /dev/null
@@ -0,0 +1,1020 @@
+// Copyright 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.
+//
+// A unit test for Google Test itself.  This verifies that the basic
+// constructs of Google Test work.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+#include <stdlib.h>
+
+#if GTEST_IS_THREADSAFE
+using testing::ScopedFakeTestPartResultReporter;
+using testing::TestPartResultArray;
+
+using testing::internal::Notification;
+using testing::internal::ThreadWithParam;
+#endif
+
+namespace posix = ::testing::internal::posix;
+using testing::internal::String;
+using testing::internal::scoped_ptr;
+
+// Tests catching fatal failures.
+
+// A subroutine used by the following test.
+void TestEq1(int x) {
+  ASSERT_EQ(1, x);
+}
+
+// This function calls a test subroutine, catches the fatal failure it
+// generates, and then returns early.
+void TryTestSubroutine() {
+  // Calls a subrountine that yields a fatal failure.
+  TestEq1(2);
+
+  // Catches the fatal failure and aborts the test.
+  //
+  // The testing::Test:: prefix is necessary when calling
+  // HasFatalFailure() outside of a TEST, TEST_F, or test fixture.
+  if (testing::Test::HasFatalFailure()) return;
+
+  // If we get here, something is wrong.
+  FAIL() << "This should never be reached.";
+}
+
+TEST(PassingTest, PassingTest1) {
+}
+
+TEST(PassingTest, PassingTest2) {
+}
+
+// Tests that parameters of failing parameterized tests are printed in the
+// failing test summary.
+class FailingParamTest : public testing::TestWithParam<int> {};
+
+TEST_P(FailingParamTest, Fails) {
+  EXPECT_EQ(1, GetParam());
+}
+
+// This generates a test which will fail. Google Test is expected to print
+// its parameter when it outputs the list of all failed tests.
+INSTANTIATE_TEST_CASE_P(PrintingFailingParams,
+                        FailingParamTest,
+                        testing::Values(2));
+
+// Tests catching a fatal failure in a subroutine.
+TEST(FatalFailureTest, FatalFailureInSubroutine) {
+  printf("(expecting a failure that x should be 1)\n");
+
+  TryTestSubroutine();
+}
+
+// Tests catching a fatal failure in a nested subroutine.
+TEST(FatalFailureTest, FatalFailureInNestedSubroutine) {
+  printf("(expecting a failure that x should be 1)\n");
+
+  // Calls a subrountine that yields a fatal failure.
+  TryTestSubroutine();
+
+  // Catches the fatal failure and aborts the test.
+  //
+  // When calling HasFatalFailure() inside a TEST, TEST_F, or test
+  // fixture, the testing::Test:: prefix is not needed.
+  if (HasFatalFailure()) return;
+
+  // If we get here, something is wrong.
+  FAIL() << "This should never be reached.";
+}
+
+// Tests HasFatalFailure() after a failed EXPECT check.
+TEST(FatalFailureTest, NonfatalFailureInSubroutine) {
+  printf("(expecting a failure on false)\n");
+  EXPECT_TRUE(false);  // Generates a nonfatal failure
+  ASSERT_FALSE(HasFatalFailure());  // This should succeed.
+}
+
+// Tests interleaving user logging and Google Test assertions.
+TEST(LoggingTest, InterleavingLoggingAndAssertions) {
+  static const int a[4] = {
+    3, 9, 2, 6
+  };
+
+  printf("(expecting 2 failures on (3) >= (a[i]))\n");
+  for (int i = 0; i < static_cast<int>(sizeof(a)/sizeof(*a)); i++) {
+    printf("i == %d\n", i);
+    EXPECT_GE(3, a[i]);
+  }
+}
+
+// Tests the SCOPED_TRACE macro.
+
+// A helper function for testing SCOPED_TRACE.
+void SubWithoutTrace(int n) {
+  EXPECT_EQ(1, n);
+  ASSERT_EQ(2, n);
+}
+
+// Another helper function for testing SCOPED_TRACE.
+void SubWithTrace(int n) {
+  SCOPED_TRACE(testing::Message() << "n = " << n);
+
+  SubWithoutTrace(n);
+}
+
+// Tests that SCOPED_TRACE() obeys lexical scopes.
+TEST(SCOPED_TRACETest, ObeysScopes) {
+  printf("(expected to fail)\n");
+
+  // There should be no trace before SCOPED_TRACE() is invoked.
+  ADD_FAILURE() << "This failure is expected, and shouldn't have a trace.";
+
+  {
+    SCOPED_TRACE("Expected trace");
+    // After SCOPED_TRACE(), a failure in the current scope should contain
+    // the trace.
+    ADD_FAILURE() << "This failure is expected, and should have a trace.";
+  }
+
+  // Once the control leaves the scope of the SCOPED_TRACE(), there
+  // should be no trace again.
+  ADD_FAILURE() << "This failure is expected, and shouldn't have a trace.";
+}
+
+// Tests that SCOPED_TRACE works inside a loop.
+TEST(SCOPED_TRACETest, WorksInLoop) {
+  printf("(expected to fail)\n");
+
+  for (int i = 1; i <= 2; i++) {
+    SCOPED_TRACE(testing::Message() << "i = " << i);
+
+    SubWithoutTrace(i);
+  }
+}
+
+// Tests that SCOPED_TRACE works in a subroutine.
+TEST(SCOPED_TRACETest, WorksInSubroutine) {
+  printf("(expected to fail)\n");
+
+  SubWithTrace(1);
+  SubWithTrace(2);
+}
+
+// Tests that SCOPED_TRACE can be nested.
+TEST(SCOPED_TRACETest, CanBeNested) {
+  printf("(expected to fail)\n");
+
+  SCOPED_TRACE("");  // A trace without a message.
+
+  SubWithTrace(2);
+}
+
+// Tests that multiple SCOPED_TRACEs can be used in the same scope.
+TEST(SCOPED_TRACETest, CanBeRepeated) {
+  printf("(expected to fail)\n");
+
+  SCOPED_TRACE("A");
+  ADD_FAILURE()
+      << "This failure is expected, and should contain trace point A.";
+
+  SCOPED_TRACE("B");
+  ADD_FAILURE()
+      << "This failure is expected, and should contain trace point A and B.";
+
+  {
+    SCOPED_TRACE("C");
+    ADD_FAILURE() << "This failure is expected, and should contain "
+                  << "trace point A, B, and C.";
+  }
+
+  SCOPED_TRACE("D");
+  ADD_FAILURE() << "This failure is expected, and should contain "
+                << "trace point A, B, and D.";
+}
+
+#if GTEST_IS_THREADSAFE
+// Tests that SCOPED_TRACE()s can be used concurrently from multiple
+// threads.  Namely, an assertion should be affected by
+// SCOPED_TRACE()s in its own thread only.
+
+// Here's the sequence of actions that happen in the test:
+//
+//   Thread A (main)                | Thread B (spawned)
+//   ===============================|================================
+//   spawns thread B                |
+//   -------------------------------+--------------------------------
+//   waits for n1                   | SCOPED_TRACE("Trace B");
+//                                  | generates failure #1
+//                                  | notifies n1
+//   -------------------------------+--------------------------------
+//   SCOPED_TRACE("Trace A");       | waits for n2
+//   generates failure #2           |
+//   notifies n2                    |
+//   -------------------------------|--------------------------------
+//   waits for n3                   | generates failure #3
+//                                  | trace B dies
+//                                  | generates failure #4
+//                                  | notifies n3
+//   -------------------------------|--------------------------------
+//   generates failure #5           | finishes
+//   trace A dies                   |
+//   generates failure #6           |
+//   -------------------------------|--------------------------------
+//   waits for thread B to finish   |
+
+struct CheckPoints {
+  Notification n1;
+  Notification n2;
+  Notification n3;
+};
+
+static void ThreadWithScopedTrace(CheckPoints* check_points) {
+  {
+    SCOPED_TRACE("Trace B");
+    ADD_FAILURE()
+        << "Expected failure #1 (in thread B, only trace B alive).";
+    check_points->n1.Notify();
+    check_points->n2.WaitForNotification();
+
+    ADD_FAILURE()
+        << "Expected failure #3 (in thread B, trace A & B both alive).";
+  }  // Trace B dies here.
+  ADD_FAILURE()
+      << "Expected failure #4 (in thread B, only trace A alive).";
+  check_points->n3.Notify();
+}
+
+TEST(SCOPED_TRACETest, WorksConcurrently) {
+  printf("(expecting 6 failures)\n");
+
+  CheckPoints check_points;
+  ThreadWithParam<CheckPoints*> thread(&ThreadWithScopedTrace,
+                                       &check_points,
+                                       NULL);
+  check_points.n1.WaitForNotification();
+
+  {
+    SCOPED_TRACE("Trace A");
+    ADD_FAILURE()
+        << "Expected failure #2 (in thread A, trace A & B both alive).";
+    check_points.n2.Notify();
+    check_points.n3.WaitForNotification();
+
+    ADD_FAILURE()
+        << "Expected failure #5 (in thread A, only trace A alive).";
+  }  // Trace A dies here.
+  ADD_FAILURE()
+      << "Expected failure #6 (in thread A, no trace alive).";
+  thread.Join();
+}
+#endif  // GTEST_IS_THREADSAFE
+
+TEST(DisabledTestsWarningTest,
+     DISABLED_AlsoRunDisabledTestsFlagSuppressesWarning) {
+  // This test body is intentionally empty.  Its sole purpose is for
+  // verifying that the --gtest_also_run_disabled_tests flag
+  // suppresses the "YOU HAVE 12 DISABLED TESTS" warning at the end of
+  // the test output.
+}
+
+// Tests using assertions outside of TEST and TEST_F.
+//
+// This function creates two failures intentionally.
+void AdHocTest() {
+  printf("The non-test part of the code is expected to have 2 failures.\n\n");
+  EXPECT_TRUE(false);
+  EXPECT_EQ(2, 3);
+}
+
+// Runs all TESTs, all TEST_Fs, and the ad hoc test.
+int RunAllTests() {
+  AdHocTest();
+  return RUN_ALL_TESTS();
+}
+
+// Tests non-fatal failures in the fixture constructor.
+class NonFatalFailureInFixtureConstructorTest : public testing::Test {
+ protected:
+  NonFatalFailureInFixtureConstructorTest() {
+    printf("(expecting 5 failures)\n");
+    ADD_FAILURE() << "Expected failure #1, in the test fixture c'tor.";
+  }
+
+  ~NonFatalFailureInFixtureConstructorTest() {
+    ADD_FAILURE() << "Expected failure #5, in the test fixture d'tor.";
+  }
+
+  virtual void SetUp() {
+    ADD_FAILURE() << "Expected failure #2, in SetUp().";
+  }
+
+  virtual void TearDown() {
+    ADD_FAILURE() << "Expected failure #4, in TearDown.";
+  }
+};
+
+TEST_F(NonFatalFailureInFixtureConstructorTest, FailureInConstructor) {
+  ADD_FAILURE() << "Expected failure #3, in the test body.";
+}
+
+// Tests fatal failures in the fixture constructor.
+class FatalFailureInFixtureConstructorTest : public testing::Test {
+ protected:
+  FatalFailureInFixtureConstructorTest() {
+    printf("(expecting 2 failures)\n");
+    Init();
+  }
+
+  ~FatalFailureInFixtureConstructorTest() {
+    ADD_FAILURE() << "Expected failure #2, in the test fixture d'tor.";
+  }
+
+  virtual void SetUp() {
+    ADD_FAILURE() << "UNEXPECTED failure in SetUp().  "
+                  << "We should never get here, as the test fixture c'tor "
+                  << "had a fatal failure.";
+  }
+
+  virtual void TearDown() {
+    ADD_FAILURE() << "UNEXPECTED failure in TearDown().  "
+                  << "We should never get here, as the test fixture c'tor "
+                  << "had a fatal failure.";
+  }
+ private:
+  void Init() {
+    FAIL() << "Expected failure #1, in the test fixture c'tor.";
+  }
+};
+
+TEST_F(FatalFailureInFixtureConstructorTest, FailureInConstructor) {
+  ADD_FAILURE() << "UNEXPECTED failure in the test body.  "
+                << "We should never get here, as the test fixture c'tor "
+                << "had a fatal failure.";
+}
+
+// Tests non-fatal failures in SetUp().
+class NonFatalFailureInSetUpTest : public testing::Test {
+ protected:
+  virtual ~NonFatalFailureInSetUpTest() {
+    Deinit();
+  }
+
+  virtual void SetUp() {
+    printf("(expecting 4 failures)\n");
+    ADD_FAILURE() << "Expected failure #1, in SetUp().";
+  }
+
+  virtual void TearDown() {
+    FAIL() << "Expected failure #3, in TearDown().";
+  }
+ private:
+  void Deinit() {
+    FAIL() << "Expected failure #4, in the test fixture d'tor.";
+  }
+};
+
+TEST_F(NonFatalFailureInSetUpTest, FailureInSetUp) {
+  FAIL() << "Expected failure #2, in the test function.";
+}
+
+// Tests fatal failures in SetUp().
+class FatalFailureInSetUpTest : public testing::Test {
+ protected:
+  virtual ~FatalFailureInSetUpTest() {
+    Deinit();
+  }
+
+  virtual void SetUp() {
+    printf("(expecting 3 failures)\n");
+    FAIL() << "Expected failure #1, in SetUp().";
+  }
+
+  virtual void TearDown() {
+    FAIL() << "Expected failure #2, in TearDown().";
+  }
+ private:
+  void Deinit() {
+    FAIL() << "Expected failure #3, in the test fixture d'tor.";
+  }
+};
+
+TEST_F(FatalFailureInSetUpTest, FailureInSetUp) {
+  FAIL() << "UNEXPECTED failure in the test function.  "
+         << "We should never get here, as SetUp() failed.";
+}
+
+TEST(AddFailureAtTest, MessageContainsSpecifiedFileAndLineNumber) {
+  ADD_FAILURE_AT("foo.cc", 42) << "Expected failure in foo.cc";
+}
+
+#if GTEST_IS_THREADSAFE
+
+// A unary function that may die.
+void DieIf(bool should_die) {
+  GTEST_CHECK_(!should_die) << " - death inside DieIf().";
+}
+
+// Tests running death tests in a multi-threaded context.
+
+// Used for coordination between the main and the spawn thread.
+struct SpawnThreadNotifications {
+  SpawnThreadNotifications() {}
+
+  Notification spawn_thread_started;
+  Notification spawn_thread_ok_to_terminate;
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(SpawnThreadNotifications);
+};
+
+// The function to be executed in the thread spawn by the
+// MultipleThreads test (below).
+static void ThreadRoutine(SpawnThreadNotifications* notifications) {
+  // Signals the main thread that this thread has started.
+  notifications->spawn_thread_started.Notify();
+
+  // Waits for permission to finish from the main thread.
+  notifications->spawn_thread_ok_to_terminate.WaitForNotification();
+}
+
+// This is a death-test test, but it's not named with a DeathTest
+// suffix.  It starts threads which might interfere with later
+// death tests, so it must run after all other death tests.
+class DeathTestAndMultiThreadsTest : public testing::Test {
+ protected:
+  // Starts a thread and waits for it to begin.
+  virtual void SetUp() {
+    thread_.reset(new ThreadWithParam<SpawnThreadNotifications*>(
+        &ThreadRoutine, &notifications_, NULL));
+    notifications_.spawn_thread_started.WaitForNotification();
+  }
+  // Tells the thread to finish, and reaps it.
+  // Depending on the version of the thread library in use,
+  // a manager thread might still be left running that will interfere
+  // with later death tests.  This is unfortunate, but this class
+  // cleans up after itself as best it can.
+  virtual void TearDown() {
+    notifications_.spawn_thread_ok_to_terminate.Notify();
+  }
+
+ private:
+  SpawnThreadNotifications notifications_;
+  scoped_ptr<ThreadWithParam<SpawnThreadNotifications*> > thread_;
+};
+
+#endif  // GTEST_IS_THREADSAFE
+
+// The MixedUpTestCaseTest test case verifies that Google Test will fail a
+// test if it uses a different fixture class than what other tests in
+// the same test case use.  It deliberately contains two fixture
+// classes with the same name but defined in different namespaces.
+
+// The MixedUpTestCaseWithSameTestNameTest test case verifies that
+// when the user defines two tests with the same test case name AND
+// same test name (but in different namespaces), the second test will
+// fail.
+
+namespace foo {
+
+class MixedUpTestCaseTest : public testing::Test {
+};
+
+TEST_F(MixedUpTestCaseTest, FirstTestFromNamespaceFoo) {}
+TEST_F(MixedUpTestCaseTest, SecondTestFromNamespaceFoo) {}
+
+class MixedUpTestCaseWithSameTestNameTest : public testing::Test {
+};
+
+TEST_F(MixedUpTestCaseWithSameTestNameTest,
+       TheSecondTestWithThisNameShouldFail) {}
+
+}  // namespace foo
+
+namespace bar {
+
+class MixedUpTestCaseTest : public testing::Test {
+};
+
+// The following two tests are expected to fail.  We rely on the
+// golden file to check that Google Test generates the right error message.
+TEST_F(MixedUpTestCaseTest, ThisShouldFail) {}
+TEST_F(MixedUpTestCaseTest, ThisShouldFailToo) {}
+
+class MixedUpTestCaseWithSameTestNameTest : public testing::Test {
+};
+
+// Expected to fail.  We rely on the golden file to check that Google Test
+// generates the right error message.
+TEST_F(MixedUpTestCaseWithSameTestNameTest,
+       TheSecondTestWithThisNameShouldFail) {}
+
+}  // namespace bar
+
+// The following two test cases verify that Google Test catches the user
+// error of mixing TEST and TEST_F in the same test case.  The first
+// test case checks the scenario where TEST_F appears before TEST, and
+// the second one checks where TEST appears before TEST_F.
+
+class TEST_F_before_TEST_in_same_test_case : public testing::Test {
+};
+
+TEST_F(TEST_F_before_TEST_in_same_test_case, DefinedUsingTEST_F) {}
+
+// Expected to fail.  We rely on the golden file to check that Google Test
+// generates the right error message.
+TEST(TEST_F_before_TEST_in_same_test_case, DefinedUsingTESTAndShouldFail) {}
+
+class TEST_before_TEST_F_in_same_test_case : public testing::Test {
+};
+
+TEST(TEST_before_TEST_F_in_same_test_case, DefinedUsingTEST) {}
+
+// Expected to fail.  We rely on the golden file to check that Google Test
+// generates the right error message.
+TEST_F(TEST_before_TEST_F_in_same_test_case, DefinedUsingTEST_FAndShouldFail) {
+}
+
+// Used for testing EXPECT_NONFATAL_FAILURE() and EXPECT_FATAL_FAILURE().
+int global_integer = 0;
+
+// Tests that EXPECT_NONFATAL_FAILURE() can reference global variables.
+TEST(ExpectNonfatalFailureTest, CanReferenceGlobalVariables) {
+  global_integer = 0;
+  EXPECT_NONFATAL_FAILURE({
+    EXPECT_EQ(1, global_integer) << "Expected non-fatal failure.";
+  }, "Expected non-fatal failure.");
+}
+
+// Tests that EXPECT_NONFATAL_FAILURE() can reference local variables
+// (static or not).
+TEST(ExpectNonfatalFailureTest, CanReferenceLocalVariables) {
+  int m = 0;
+  static int n;
+  n = 1;
+  EXPECT_NONFATAL_FAILURE({
+    EXPECT_EQ(m, n) << "Expected non-fatal failure.";
+  }, "Expected non-fatal failure.");
+}
+
+// Tests that EXPECT_NONFATAL_FAILURE() succeeds when there is exactly
+// one non-fatal failure and no fatal failure.
+TEST(ExpectNonfatalFailureTest, SucceedsWhenThereIsOneNonfatalFailure) {
+  EXPECT_NONFATAL_FAILURE({
+    ADD_FAILURE() << "Expected non-fatal failure.";
+  }, "Expected non-fatal failure.");
+}
+
+// Tests that EXPECT_NONFATAL_FAILURE() fails when there is no
+// non-fatal failure.
+TEST(ExpectNonfatalFailureTest, FailsWhenThereIsNoNonfatalFailure) {
+  printf("(expecting a failure)\n");
+  EXPECT_NONFATAL_FAILURE({
+  }, "");
+}
+
+// Tests that EXPECT_NONFATAL_FAILURE() fails when there are two
+// non-fatal failures.
+TEST(ExpectNonfatalFailureTest, FailsWhenThereAreTwoNonfatalFailures) {
+  printf("(expecting a failure)\n");
+  EXPECT_NONFATAL_FAILURE({
+    ADD_FAILURE() << "Expected non-fatal failure 1.";
+    ADD_FAILURE() << "Expected non-fatal failure 2.";
+  }, "");
+}
+
+// Tests that EXPECT_NONFATAL_FAILURE() fails when there is one fatal
+// failure.
+TEST(ExpectNonfatalFailureTest, FailsWhenThereIsOneFatalFailure) {
+  printf("(expecting a failure)\n");
+  EXPECT_NONFATAL_FAILURE({
+    FAIL() << "Expected fatal failure.";
+  }, "");
+}
+
+// Tests that EXPECT_NONFATAL_FAILURE() fails when the statement being
+// tested returns.
+TEST(ExpectNonfatalFailureTest, FailsWhenStatementReturns) {
+  printf("(expecting a failure)\n");
+  EXPECT_NONFATAL_FAILURE({
+    return;
+  }, "");
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Tests that EXPECT_NONFATAL_FAILURE() fails when the statement being
+// tested throws.
+TEST(ExpectNonfatalFailureTest, FailsWhenStatementThrows) {
+  printf("(expecting a failure)\n");
+  try {
+    EXPECT_NONFATAL_FAILURE({
+      throw 0;
+    }, "");
+  } catch(int) {  // NOLINT
+  }
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// Tests that EXPECT_FATAL_FAILURE() can reference global variables.
+TEST(ExpectFatalFailureTest, CanReferenceGlobalVariables) {
+  global_integer = 0;
+  EXPECT_FATAL_FAILURE({
+    ASSERT_EQ(1, global_integer) << "Expected fatal failure.";
+  }, "Expected fatal failure.");
+}
+
+// Tests that EXPECT_FATAL_FAILURE() can reference local static
+// variables.
+TEST(ExpectFatalFailureTest, CanReferenceLocalStaticVariables) {
+  static int n;
+  n = 1;
+  EXPECT_FATAL_FAILURE({
+    ASSERT_EQ(0, n) << "Expected fatal failure.";
+  }, "Expected fatal failure.");
+}
+
+// Tests that EXPECT_FATAL_FAILURE() succeeds when there is exactly
+// one fatal failure and no non-fatal failure.
+TEST(ExpectFatalFailureTest, SucceedsWhenThereIsOneFatalFailure) {
+  EXPECT_FATAL_FAILURE({
+    FAIL() << "Expected fatal failure.";
+  }, "Expected fatal failure.");
+}
+
+// Tests that EXPECT_FATAL_FAILURE() fails when there is no fatal
+// failure.
+TEST(ExpectFatalFailureTest, FailsWhenThereIsNoFatalFailure) {
+  printf("(expecting a failure)\n");
+  EXPECT_FATAL_FAILURE({
+  }, "");
+}
+
+// A helper for generating a fatal failure.
+void FatalFailure() {
+  FAIL() << "Expected fatal failure.";
+}
+
+// Tests that EXPECT_FATAL_FAILURE() fails when there are two
+// fatal failures.
+TEST(ExpectFatalFailureTest, FailsWhenThereAreTwoFatalFailures) {
+  printf("(expecting a failure)\n");
+  EXPECT_FATAL_FAILURE({
+    FatalFailure();
+    FatalFailure();
+  }, "");
+}
+
+// Tests that EXPECT_FATAL_FAILURE() fails when there is one non-fatal
+// failure.
+TEST(ExpectFatalFailureTest, FailsWhenThereIsOneNonfatalFailure) {
+  printf("(expecting a failure)\n");
+  EXPECT_FATAL_FAILURE({
+    ADD_FAILURE() << "Expected non-fatal failure.";
+  }, "");
+}
+
+// Tests that EXPECT_FATAL_FAILURE() fails when the statement being
+// tested returns.
+TEST(ExpectFatalFailureTest, FailsWhenStatementReturns) {
+  printf("(expecting a failure)\n");
+  EXPECT_FATAL_FAILURE({
+    return;
+  }, "");
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Tests that EXPECT_FATAL_FAILURE() fails when the statement being
+// tested throws.
+TEST(ExpectFatalFailureTest, FailsWhenStatementThrows) {
+  printf("(expecting a failure)\n");
+  try {
+    EXPECT_FATAL_FAILURE({
+      throw 0;
+    }, "");
+  } catch(int) {  // NOLINT
+  }
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// This #ifdef block tests the output of typed tests.
+#if GTEST_HAS_TYPED_TEST
+
+template <typename T>
+class TypedTest : public testing::Test {
+};
+
+TYPED_TEST_CASE(TypedTest, testing::Types<int>);
+
+TYPED_TEST(TypedTest, Success) {
+  EXPECT_EQ(0, TypeParam());
+}
+
+TYPED_TEST(TypedTest, Failure) {
+  EXPECT_EQ(1, TypeParam()) << "Expected failure";
+}
+
+#endif  // GTEST_HAS_TYPED_TEST
+
+// This #ifdef block tests the output of type-parameterized tests.
+#if GTEST_HAS_TYPED_TEST_P
+
+template <typename T>
+class TypedTestP : public testing::Test {
+};
+
+TYPED_TEST_CASE_P(TypedTestP);
+
+TYPED_TEST_P(TypedTestP, Success) {
+  EXPECT_EQ(0U, TypeParam());
+}
+
+TYPED_TEST_P(TypedTestP, Failure) {
+  EXPECT_EQ(1U, TypeParam()) << "Expected failure";
+}
+
+REGISTER_TYPED_TEST_CASE_P(TypedTestP, Success, Failure);
+
+typedef testing::Types<unsigned char, unsigned int> UnsignedTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(Unsigned, TypedTestP, UnsignedTypes);
+
+#endif  // GTEST_HAS_TYPED_TEST_P
+
+#if GTEST_HAS_DEATH_TEST
+
+// We rely on the golden file to verify that tests whose test case
+// name ends with DeathTest are run first.
+
+TEST(ADeathTest, ShouldRunFirst) {
+}
+
+# if GTEST_HAS_TYPED_TEST
+
+// We rely on the golden file to verify that typed tests whose test
+// case name ends with DeathTest are run first.
+
+template <typename T>
+class ATypedDeathTest : public testing::Test {
+};
+
+typedef testing::Types<int, double> NumericTypes;
+TYPED_TEST_CASE(ATypedDeathTest, NumericTypes);
+
+TYPED_TEST(ATypedDeathTest, ShouldRunFirst) {
+}
+
+# endif  // GTEST_HAS_TYPED_TEST
+
+# if GTEST_HAS_TYPED_TEST_P
+
+
+// We rely on the golden file to verify that type-parameterized tests
+// whose test case name ends with DeathTest are run first.
+
+template <typename T>
+class ATypeParamDeathTest : public testing::Test {
+};
+
+TYPED_TEST_CASE_P(ATypeParamDeathTest);
+
+TYPED_TEST_P(ATypeParamDeathTest, ShouldRunFirst) {
+}
+
+REGISTER_TYPED_TEST_CASE_P(ATypeParamDeathTest, ShouldRunFirst);
+
+INSTANTIATE_TYPED_TEST_CASE_P(My, ATypeParamDeathTest, NumericTypes);
+
+# endif  // GTEST_HAS_TYPED_TEST_P
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Tests various failure conditions of
+// EXPECT_{,NON}FATAL_FAILURE{,_ON_ALL_THREADS}.
+class ExpectFailureTest : public testing::Test {
+ public:  // Must be public and not protected due to a bug in g++ 3.4.2.
+  enum FailureMode {
+    FATAL_FAILURE,
+    NONFATAL_FAILURE
+  };
+  static void AddFailure(FailureMode failure) {
+    if (failure == FATAL_FAILURE) {
+      FAIL() << "Expected fatal failure.";
+    } else {
+      ADD_FAILURE() << "Expected non-fatal failure.";
+    }
+  }
+};
+
+TEST_F(ExpectFailureTest, ExpectFatalFailure) {
+  // Expected fatal failure, but succeeds.
+  printf("(expecting 1 failure)\n");
+  EXPECT_FATAL_FAILURE(SUCCEED(), "Expected fatal failure.");
+  // Expected fatal failure, but got a non-fatal failure.
+  printf("(expecting 1 failure)\n");
+  EXPECT_FATAL_FAILURE(AddFailure(NONFATAL_FAILURE), "Expected non-fatal "
+                       "failure.");
+  // Wrong message.
+  printf("(expecting 1 failure)\n");
+  EXPECT_FATAL_FAILURE(AddFailure(FATAL_FAILURE), "Some other fatal failure "
+                       "expected.");
+}
+
+TEST_F(ExpectFailureTest, ExpectNonFatalFailure) {
+  // Expected non-fatal failure, but succeeds.
+  printf("(expecting 1 failure)\n");
+  EXPECT_NONFATAL_FAILURE(SUCCEED(), "Expected non-fatal failure.");
+  // Expected non-fatal failure, but got a fatal failure.
+  printf("(expecting 1 failure)\n");
+  EXPECT_NONFATAL_FAILURE(AddFailure(FATAL_FAILURE), "Expected fatal failure.");
+  // Wrong message.
+  printf("(expecting 1 failure)\n");
+  EXPECT_NONFATAL_FAILURE(AddFailure(NONFATAL_FAILURE), "Some other non-fatal "
+                          "failure.");
+}
+
+#if GTEST_IS_THREADSAFE
+
+class ExpectFailureWithThreadsTest : public ExpectFailureTest {
+ protected:
+  static void AddFailureInOtherThread(FailureMode failure) {
+    ThreadWithParam<FailureMode> thread(&AddFailure, failure, NULL);
+    thread.Join();
+  }
+};
+
+TEST_F(ExpectFailureWithThreadsTest, ExpectFatalFailure) {
+  // We only intercept the current thread.
+  printf("(expecting 2 failures)\n");
+  EXPECT_FATAL_FAILURE(AddFailureInOtherThread(FATAL_FAILURE),
+                       "Expected fatal failure.");
+}
+
+TEST_F(ExpectFailureWithThreadsTest, ExpectNonFatalFailure) {
+  // We only intercept the current thread.
+  printf("(expecting 2 failures)\n");
+  EXPECT_NONFATAL_FAILURE(AddFailureInOtherThread(NONFATAL_FAILURE),
+                          "Expected non-fatal failure.");
+}
+
+typedef ExpectFailureWithThreadsTest ScopedFakeTestPartResultReporterTest;
+
+// Tests that the ScopedFakeTestPartResultReporter only catches failures from
+// the current thread if it is instantiated with INTERCEPT_ONLY_CURRENT_THREAD.
+TEST_F(ScopedFakeTestPartResultReporterTest, InterceptOnlyCurrentThread) {
+  printf("(expecting 2 failures)\n");
+  TestPartResultArray results;
+  {
+    ScopedFakeTestPartResultReporter reporter(
+        ScopedFakeTestPartResultReporter::INTERCEPT_ONLY_CURRENT_THREAD,
+        &results);
+    AddFailureInOtherThread(FATAL_FAILURE);
+    AddFailureInOtherThread(NONFATAL_FAILURE);
+  }
+  // The two failures should not have been intercepted.
+  EXPECT_EQ(0, results.size()) << "This shouldn't fail.";
+}
+
+#endif  // GTEST_IS_THREADSAFE
+
+TEST_F(ExpectFailureTest, ExpectFatalFailureOnAllThreads) {
+  // Expected fatal failure, but succeeds.
+  printf("(expecting 1 failure)\n");
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(SUCCEED(), "Expected fatal failure.");
+  // Expected fatal failure, but got a non-fatal failure.
+  printf("(expecting 1 failure)\n");
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(AddFailure(NONFATAL_FAILURE),
+                                      "Expected non-fatal failure.");
+  // Wrong message.
+  printf("(expecting 1 failure)\n");
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(AddFailure(FATAL_FAILURE),
+                                      "Some other fatal failure expected.");
+}
+
+TEST_F(ExpectFailureTest, ExpectNonFatalFailureOnAllThreads) {
+  // Expected non-fatal failure, but succeeds.
+  printf("(expecting 1 failure)\n");
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(SUCCEED(), "Expected non-fatal "
+                                         "failure.");
+  // Expected non-fatal failure, but got a fatal failure.
+  printf("(expecting 1 failure)\n");
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(AddFailure(FATAL_FAILURE),
+                                         "Expected fatal failure.");
+  // Wrong message.
+  printf("(expecting 1 failure)\n");
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(AddFailure(NONFATAL_FAILURE),
+                                         "Some other non-fatal failure.");
+}
+
+
+// Two test environments for testing testing::AddGlobalTestEnvironment().
+
+class FooEnvironment : public testing::Environment {
+ public:
+  virtual void SetUp() {
+    printf("%s", "FooEnvironment::SetUp() called.\n");
+  }
+
+  virtual void TearDown() {
+    printf("%s", "FooEnvironment::TearDown() called.\n");
+    FAIL() << "Expected fatal failure.";
+  }
+};
+
+class BarEnvironment : public testing::Environment {
+ public:
+  virtual void SetUp() {
+    printf("%s", "BarEnvironment::SetUp() called.\n");
+  }
+
+  virtual void TearDown() {
+    printf("%s", "BarEnvironment::TearDown() called.\n");
+    ADD_FAILURE() << "Expected non-fatal failure.";
+  }
+};
+
+bool GTEST_FLAG(internal_skip_environment_and_ad_hoc_tests) = false;
+
+// The main function.
+//
+// The idea is to use Google Test to run all the tests we have defined (some
+// of them are intended to fail), and then compare the test results
+// with the "golden" file.
+int main(int argc, char **argv) {
+  testing::GTEST_FLAG(print_time) = false;
+
+  // We just run the tests, knowing some of them are intended to fail.
+  // We will use a separate Python script to compare the output of
+  // this program with the golden file.
+
+  // It's hard to test InitGoogleTest() directly, as it has many
+  // global side effects.  The following line serves as a sanity test
+  // for it.
+  testing::InitGoogleTest(&argc, argv);
+  if (argc >= 2 &&
+      String(argv[1]) == "--gtest_internal_skip_environment_and_ad_hoc_tests")
+    GTEST_FLAG(internal_skip_environment_and_ad_hoc_tests) = true;
+
+#if GTEST_HAS_DEATH_TEST
+  if (testing::internal::GTEST_FLAG(internal_run_death_test) != "") {
+    // Skip the usual output capturing if we're running as the child
+    // process of an threadsafe-style death test.
+# if GTEST_OS_WINDOWS
+    posix::FReopen("nul:", "w", stdout);
+# else
+    posix::FReopen("/dev/null", "w", stdout);
+# endif  // GTEST_OS_WINDOWS
+    return RUN_ALL_TESTS();
+  }
+#endif  // GTEST_HAS_DEATH_TEST
+
+  if (GTEST_FLAG(internal_skip_environment_and_ad_hoc_tests))
+    return RUN_ALL_TESTS();
+
+  // Registers two global test environments.
+  // The golden file verifies that they are set up in the order they
+  // are registered, and torn down in the reverse order.
+  testing::AddGlobalTestEnvironment(new FooEnvironment);
+  testing::AddGlobalTestEnvironment(new BarEnvironment);
+
+  return RunAllTests();
+}
diff --git a/third_party/googletest/src/test/gtest_output_test_golden_lin.txt b/third_party/googletest/src/test/gtest_output_test_golden_lin.txt
new file mode 100644 (file)
index 0000000..a1d342d
--- /dev/null
@@ -0,0 +1,711 @@
+The non-test part of the code is expected to have 2 failures.
+
+gtest_output_test_.cc:#: Failure
+Value of: false
+  Actual: false
+Expected: true
+gtest_output_test_.cc:#: Failure
+Value of: 3
+Expected: 2
+\e[0;32m[==========] \e[mRunning 62 tests from 27 test cases.
+\e[0;32m[----------] \e[mGlobal test environment set-up.
+FooEnvironment::SetUp() called.
+BarEnvironment::SetUp() called.
+\e[0;32m[----------] \e[m1 test from ADeathTest
+\e[0;32m[ RUN      ] \e[mADeathTest.ShouldRunFirst
+\e[0;32m[       OK ] \e[mADeathTest.ShouldRunFirst
+\e[0;32m[----------] \e[m1 test from ATypedDeathTest/0, where TypeParam = int
+\e[0;32m[ RUN      ] \e[mATypedDeathTest/0.ShouldRunFirst
+\e[0;32m[       OK ] \e[mATypedDeathTest/0.ShouldRunFirst
+\e[0;32m[----------] \e[m1 test from ATypedDeathTest/1, where TypeParam = double
+\e[0;32m[ RUN      ] \e[mATypedDeathTest/1.ShouldRunFirst
+\e[0;32m[       OK ] \e[mATypedDeathTest/1.ShouldRunFirst
+\e[0;32m[----------] \e[m1 test from My/ATypeParamDeathTest/0, where TypeParam = int
+\e[0;32m[ RUN      ] \e[mMy/ATypeParamDeathTest/0.ShouldRunFirst
+\e[0;32m[       OK ] \e[mMy/ATypeParamDeathTest/0.ShouldRunFirst
+\e[0;32m[----------] \e[m1 test from My/ATypeParamDeathTest/1, where TypeParam = double
+\e[0;32m[ RUN      ] \e[mMy/ATypeParamDeathTest/1.ShouldRunFirst
+\e[0;32m[       OK ] \e[mMy/ATypeParamDeathTest/1.ShouldRunFirst
+\e[0;32m[----------] \e[m2 tests from PassingTest
+\e[0;32m[ RUN      ] \e[mPassingTest.PassingTest1
+\e[0;32m[       OK ] \e[mPassingTest.PassingTest1
+\e[0;32m[ RUN      ] \e[mPassingTest.PassingTest2
+\e[0;32m[       OK ] \e[mPassingTest.PassingTest2
+\e[0;32m[----------] \e[m3 tests from FatalFailureTest
+\e[0;32m[ RUN      ] \e[mFatalFailureTest.FatalFailureInSubroutine
+(expecting a failure that x should be 1)
+gtest_output_test_.cc:#: Failure
+Value of: x
+  Actual: 2
+Expected: 1
+\e[0;31m[  FAILED  ] \e[mFatalFailureTest.FatalFailureInSubroutine
+\e[0;32m[ RUN      ] \e[mFatalFailureTest.FatalFailureInNestedSubroutine
+(expecting a failure that x should be 1)
+gtest_output_test_.cc:#: Failure
+Value of: x
+  Actual: 2
+Expected: 1
+\e[0;31m[  FAILED  ] \e[mFatalFailureTest.FatalFailureInNestedSubroutine
+\e[0;32m[ RUN      ] \e[mFatalFailureTest.NonfatalFailureInSubroutine
+(expecting a failure on false)
+gtest_output_test_.cc:#: Failure
+Value of: false
+  Actual: false
+Expected: true
+\e[0;31m[  FAILED  ] \e[mFatalFailureTest.NonfatalFailureInSubroutine
+\e[0;32m[----------] \e[m1 test from LoggingTest
+\e[0;32m[ RUN      ] \e[mLoggingTest.InterleavingLoggingAndAssertions
+(expecting 2 failures on (3) >= (a[i]))
+i == 0
+i == 1
+gtest_output_test_.cc:#: Failure
+Expected: (3) >= (a[i]), actual: 3 vs 9
+i == 2
+i == 3
+gtest_output_test_.cc:#: Failure
+Expected: (3) >= (a[i]), actual: 3 vs 6
+\e[0;31m[  FAILED  ] \e[mLoggingTest.InterleavingLoggingAndAssertions
+\e[0;32m[----------] \e[m6 tests from SCOPED_TRACETest
+\e[0;32m[ RUN      ] \e[mSCOPED_TRACETest.ObeysScopes
+(expected to fail)
+gtest_output_test_.cc:#: Failure
+Failed
+This failure is expected, and shouldn't have a trace.
+gtest_output_test_.cc:#: Failure
+Failed
+This failure is expected, and should have a trace.
+Google Test trace:
+gtest_output_test_.cc:#: Expected trace
+gtest_output_test_.cc:#: Failure
+Failed
+This failure is expected, and shouldn't have a trace.
+\e[0;31m[  FAILED  ] \e[mSCOPED_TRACETest.ObeysScopes
+\e[0;32m[ RUN      ] \e[mSCOPED_TRACETest.WorksInLoop
+(expected to fail)
+gtest_output_test_.cc:#: Failure
+Value of: n
+  Actual: 1
+Expected: 2
+Google Test trace:
+gtest_output_test_.cc:#: i = 1
+gtest_output_test_.cc:#: Failure
+Value of: n
+  Actual: 2
+Expected: 1
+Google Test trace:
+gtest_output_test_.cc:#: i = 2
+\e[0;31m[  FAILED  ] \e[mSCOPED_TRACETest.WorksInLoop
+\e[0;32m[ RUN      ] \e[mSCOPED_TRACETest.WorksInSubroutine
+(expected to fail)
+gtest_output_test_.cc:#: Failure
+Value of: n
+  Actual: 1
+Expected: 2
+Google Test trace:
+gtest_output_test_.cc:#: n = 1
+gtest_output_test_.cc:#: Failure
+Value of: n
+  Actual: 2
+Expected: 1
+Google Test trace:
+gtest_output_test_.cc:#: n = 2
+\e[0;31m[  FAILED  ] \e[mSCOPED_TRACETest.WorksInSubroutine
+\e[0;32m[ RUN      ] \e[mSCOPED_TRACETest.CanBeNested
+(expected to fail)
+gtest_output_test_.cc:#: Failure
+Value of: n
+  Actual: 2
+Expected: 1
+Google Test trace:
+gtest_output_test_.cc:#: n = 2
+gtest_output_test_.cc:#: 
+\e[0;31m[  FAILED  ] \e[mSCOPED_TRACETest.CanBeNested
+\e[0;32m[ RUN      ] \e[mSCOPED_TRACETest.CanBeRepeated
+(expected to fail)
+gtest_output_test_.cc:#: Failure
+Failed
+This failure is expected, and should contain trace point A.
+Google Test trace:
+gtest_output_test_.cc:#: A
+gtest_output_test_.cc:#: Failure
+Failed
+This failure is expected, and should contain trace point A and B.
+Google Test trace:
+gtest_output_test_.cc:#: B
+gtest_output_test_.cc:#: A
+gtest_output_test_.cc:#: Failure
+Failed
+This failure is expected, and should contain trace point A, B, and C.
+Google Test trace:
+gtest_output_test_.cc:#: C
+gtest_output_test_.cc:#: B
+gtest_output_test_.cc:#: A
+gtest_output_test_.cc:#: Failure
+Failed
+This failure is expected, and should contain trace point A, B, and D.
+Google Test trace:
+gtest_output_test_.cc:#: D
+gtest_output_test_.cc:#: B
+gtest_output_test_.cc:#: A
+\e[0;31m[  FAILED  ] \e[mSCOPED_TRACETest.CanBeRepeated
+\e[0;32m[ RUN      ] \e[mSCOPED_TRACETest.WorksConcurrently
+(expecting 6 failures)
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #1 (in thread B, only trace B alive).
+Google Test trace:
+gtest_output_test_.cc:#: Trace B
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #2 (in thread A, trace A & B both alive).
+Google Test trace:
+gtest_output_test_.cc:#: Trace A
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #3 (in thread B, trace A & B both alive).
+Google Test trace:
+gtest_output_test_.cc:#: Trace B
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #4 (in thread B, only trace A alive).
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #5 (in thread A, only trace A alive).
+Google Test trace:
+gtest_output_test_.cc:#: Trace A
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #6 (in thread A, no trace alive).
+\e[0;31m[  FAILED  ] \e[mSCOPED_TRACETest.WorksConcurrently
+\e[0;32m[----------] \e[m1 test from NonFatalFailureInFixtureConstructorTest
+\e[0;32m[ RUN      ] \e[mNonFatalFailureInFixtureConstructorTest.FailureInConstructor
+(expecting 5 failures)
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #1, in the test fixture c'tor.
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #2, in SetUp().
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #3, in the test body.
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #4, in TearDown.
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #5, in the test fixture d'tor.
+\e[0;31m[  FAILED  ] \e[mNonFatalFailureInFixtureConstructorTest.FailureInConstructor
+\e[0;32m[----------] \e[m1 test from FatalFailureInFixtureConstructorTest
+\e[0;32m[ RUN      ] \e[mFatalFailureInFixtureConstructorTest.FailureInConstructor
+(expecting 2 failures)
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #1, in the test fixture c'tor.
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #2, in the test fixture d'tor.
+\e[0;31m[  FAILED  ] \e[mFatalFailureInFixtureConstructorTest.FailureInConstructor
+\e[0;32m[----------] \e[m1 test from NonFatalFailureInSetUpTest
+\e[0;32m[ RUN      ] \e[mNonFatalFailureInSetUpTest.FailureInSetUp
+(expecting 4 failures)
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #1, in SetUp().
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #2, in the test function.
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #3, in TearDown().
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #4, in the test fixture d'tor.
+\e[0;31m[  FAILED  ] \e[mNonFatalFailureInSetUpTest.FailureInSetUp
+\e[0;32m[----------] \e[m1 test from FatalFailureInSetUpTest
+\e[0;32m[ RUN      ] \e[mFatalFailureInSetUpTest.FailureInSetUp
+(expecting 3 failures)
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #1, in SetUp().
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #2, in TearDown().
+gtest_output_test_.cc:#: Failure
+Failed
+Expected failure #3, in the test fixture d'tor.
+\e[0;31m[  FAILED  ] \e[mFatalFailureInSetUpTest.FailureInSetUp
+\e[0;32m[----------] \e[m1 test from AddFailureAtTest
+\e[0;32m[ RUN      ] \e[mAddFailureAtTest.MessageContainsSpecifiedFileAndLineNumber
+foo.cc:42: Failure
+Failed
+Expected failure in foo.cc
+\e[0;31m[  FAILED  ] \e[mAddFailureAtTest.MessageContainsSpecifiedFileAndLineNumber
+\e[0;32m[----------] \e[m4 tests from MixedUpTestCaseTest
+\e[0;32m[ RUN      ] \e[mMixedUpTestCaseTest.FirstTestFromNamespaceFoo
+\e[0;32m[       OK ] \e[mMixedUpTestCaseTest.FirstTestFromNamespaceFoo
+\e[0;32m[ RUN      ] \e[mMixedUpTestCaseTest.SecondTestFromNamespaceFoo
+\e[0;32m[       OK ] \e[mMixedUpTestCaseTest.SecondTestFromNamespaceFoo
+\e[0;32m[ RUN      ] \e[mMixedUpTestCaseTest.ThisShouldFail
+gtest.cc:#: Failure
+Failed
+All tests in the same test case must use the same test fixture
+class.  However, in test case MixedUpTestCaseTest,
+you defined test FirstTestFromNamespaceFoo and test ThisShouldFail
+using two different test fixture classes.  This can happen if
+the two classes are from different namespaces or translation
+units and have the same name.  You should probably rename one
+of the classes to put the tests into different test cases.
+\e[0;31m[  FAILED  ] \e[mMixedUpTestCaseTest.ThisShouldFail
+\e[0;32m[ RUN      ] \e[mMixedUpTestCaseTest.ThisShouldFailToo
+gtest.cc:#: Failure
+Failed
+All tests in the same test case must use the same test fixture
+class.  However, in test case MixedUpTestCaseTest,
+you defined test FirstTestFromNamespaceFoo and test ThisShouldFailToo
+using two different test fixture classes.  This can happen if
+the two classes are from different namespaces or translation
+units and have the same name.  You should probably rename one
+of the classes to put the tests into different test cases.
+\e[0;31m[  FAILED  ] \e[mMixedUpTestCaseTest.ThisShouldFailToo
+\e[0;32m[----------] \e[m2 tests from MixedUpTestCaseWithSameTestNameTest
+\e[0;32m[ RUN      ] \e[mMixedUpTestCaseWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
+\e[0;32m[       OK ] \e[mMixedUpTestCaseWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
+\e[0;32m[ RUN      ] \e[mMixedUpTestCaseWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
+gtest.cc:#: Failure
+Failed
+All tests in the same test case must use the same test fixture
+class.  However, in test case MixedUpTestCaseWithSameTestNameTest,
+you defined test TheSecondTestWithThisNameShouldFail and test TheSecondTestWithThisNameShouldFail
+using two different test fixture classes.  This can happen if
+the two classes are from different namespaces or translation
+units and have the same name.  You should probably rename one
+of the classes to put the tests into different test cases.
+\e[0;31m[  FAILED  ] \e[mMixedUpTestCaseWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
+\e[0;32m[----------] \e[m2 tests from TEST_F_before_TEST_in_same_test_case
+\e[0;32m[ RUN      ] \e[mTEST_F_before_TEST_in_same_test_case.DefinedUsingTEST_F
+\e[0;32m[       OK ] \e[mTEST_F_before_TEST_in_same_test_case.DefinedUsingTEST_F
+\e[0;32m[ RUN      ] \e[mTEST_F_before_TEST_in_same_test_case.DefinedUsingTESTAndShouldFail
+gtest.cc:#: Failure
+Failed
+All tests in the same test case must use the same test fixture
+class, so mixing TEST_F and TEST in the same test case is
+illegal.  In test case TEST_F_before_TEST_in_same_test_case,
+test DefinedUsingTEST_F is defined using TEST_F but
+test DefinedUsingTESTAndShouldFail is defined using TEST.  You probably
+want to change the TEST to TEST_F or move it to another test
+case.
+\e[0;31m[  FAILED  ] \e[mTEST_F_before_TEST_in_same_test_case.DefinedUsingTESTAndShouldFail
+\e[0;32m[----------] \e[m2 tests from TEST_before_TEST_F_in_same_test_case
+\e[0;32m[ RUN      ] \e[mTEST_before_TEST_F_in_same_test_case.DefinedUsingTEST
+\e[0;32m[       OK ] \e[mTEST_before_TEST_F_in_same_test_case.DefinedUsingTEST
+\e[0;32m[ RUN      ] \e[mTEST_before_TEST_F_in_same_test_case.DefinedUsingTEST_FAndShouldFail
+gtest.cc:#: Failure
+Failed
+All tests in the same test case must use the same test fixture
+class, so mixing TEST_F and TEST in the same test case is
+illegal.  In test case TEST_before_TEST_F_in_same_test_case,
+test DefinedUsingTEST_FAndShouldFail is defined using TEST_F but
+test DefinedUsingTEST is defined using TEST.  You probably
+want to change the TEST to TEST_F or move it to another test
+case.
+\e[0;31m[  FAILED  ] \e[mTEST_before_TEST_F_in_same_test_case.DefinedUsingTEST_FAndShouldFail
+\e[0;32m[----------] \e[m8 tests from ExpectNonfatalFailureTest
+\e[0;32m[ RUN      ] \e[mExpectNonfatalFailureTest.CanReferenceGlobalVariables
+\e[0;32m[       OK ] \e[mExpectNonfatalFailureTest.CanReferenceGlobalVariables
+\e[0;32m[ RUN      ] \e[mExpectNonfatalFailureTest.CanReferenceLocalVariables
+\e[0;32m[       OK ] \e[mExpectNonfatalFailureTest.CanReferenceLocalVariables
+\e[0;32m[ RUN      ] \e[mExpectNonfatalFailureTest.SucceedsWhenThereIsOneNonfatalFailure
+\e[0;32m[       OK ] \e[mExpectNonfatalFailureTest.SucceedsWhenThereIsOneNonfatalFailure
+\e[0;32m[ RUN      ] \e[mExpectNonfatalFailureTest.FailsWhenThereIsNoNonfatalFailure
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual: 0 failures
+\e[0;31m[  FAILED  ] \e[mExpectNonfatalFailureTest.FailsWhenThereIsNoNonfatalFailure
+\e[0;32m[ RUN      ] \e[mExpectNonfatalFailureTest.FailsWhenThereAreTwoNonfatalFailures
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual: 2 failures
+gtest_output_test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure 1.
+
+gtest_output_test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure 2.
+
+\e[0;31m[  FAILED  ] \e[mExpectNonfatalFailureTest.FailsWhenThereAreTwoNonfatalFailures
+\e[0;32m[ RUN      ] \e[mExpectNonfatalFailureTest.FailsWhenThereIsOneFatalFailure
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual:
+gtest_output_test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+
+\e[0;31m[  FAILED  ] \e[mExpectNonfatalFailureTest.FailsWhenThereIsOneFatalFailure
+\e[0;32m[ RUN      ] \e[mExpectNonfatalFailureTest.FailsWhenStatementReturns
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual: 0 failures
+\e[0;31m[  FAILED  ] \e[mExpectNonfatalFailureTest.FailsWhenStatementReturns
+\e[0;32m[ RUN      ] \e[mExpectNonfatalFailureTest.FailsWhenStatementThrows
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual: 0 failures
+\e[0;31m[  FAILED  ] \e[mExpectNonfatalFailureTest.FailsWhenStatementThrows
+\e[0;32m[----------] \e[m8 tests from ExpectFatalFailureTest
+\e[0;32m[ RUN      ] \e[mExpectFatalFailureTest.CanReferenceGlobalVariables
+\e[0;32m[       OK ] \e[mExpectFatalFailureTest.CanReferenceGlobalVariables
+\e[0;32m[ RUN      ] \e[mExpectFatalFailureTest.CanReferenceLocalStaticVariables
+\e[0;32m[       OK ] \e[mExpectFatalFailureTest.CanReferenceLocalStaticVariables
+\e[0;32m[ RUN      ] \e[mExpectFatalFailureTest.SucceedsWhenThereIsOneFatalFailure
+\e[0;32m[       OK ] \e[mExpectFatalFailureTest.SucceedsWhenThereIsOneFatalFailure
+\e[0;32m[ RUN      ] \e[mExpectFatalFailureTest.FailsWhenThereIsNoFatalFailure
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual: 0 failures
+\e[0;31m[  FAILED  ] \e[mExpectFatalFailureTest.FailsWhenThereIsNoFatalFailure
+\e[0;32m[ RUN      ] \e[mExpectFatalFailureTest.FailsWhenThereAreTwoFatalFailures
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual: 2 failures
+gtest_output_test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+
+gtest_output_test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+
+\e[0;31m[  FAILED  ] \e[mExpectFatalFailureTest.FailsWhenThereAreTwoFatalFailures
+\e[0;32m[ RUN      ] \e[mExpectFatalFailureTest.FailsWhenThereIsOneNonfatalFailure
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual:
+gtest_output_test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure.
+
+\e[0;31m[  FAILED  ] \e[mExpectFatalFailureTest.FailsWhenThereIsOneNonfatalFailure
+\e[0;32m[ RUN      ] \e[mExpectFatalFailureTest.FailsWhenStatementReturns
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual: 0 failures
+\e[0;31m[  FAILED  ] \e[mExpectFatalFailureTest.FailsWhenStatementReturns
+\e[0;32m[ RUN      ] \e[mExpectFatalFailureTest.FailsWhenStatementThrows
+(expecting a failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual: 0 failures
+\e[0;31m[  FAILED  ] \e[mExpectFatalFailureTest.FailsWhenStatementThrows
+\e[0;32m[----------] \e[m2 tests from TypedTest/0, where TypeParam = int
+\e[0;32m[ RUN      ] \e[mTypedTest/0.Success
+\e[0;32m[       OK ] \e[mTypedTest/0.Success
+\e[0;32m[ RUN      ] \e[mTypedTest/0.Failure
+gtest_output_test_.cc:#: Failure
+Value of: TypeParam()
+  Actual: 0
+Expected: 1
+Expected failure
+\e[0;31m[  FAILED  ] \e[mTypedTest/0.Failure, where TypeParam = int
+\e[0;32m[----------] \e[m2 tests from Unsigned/TypedTestP/0, where TypeParam = unsigned char
+\e[0;32m[ RUN      ] \e[mUnsigned/TypedTestP/0.Success
+\e[0;32m[       OK ] \e[mUnsigned/TypedTestP/0.Success
+\e[0;32m[ RUN      ] \e[mUnsigned/TypedTestP/0.Failure
+gtest_output_test_.cc:#: Failure
+Value of: TypeParam()
+  Actual: '\0'
+Expected: 1U
+Which is: 1
+Expected failure
+\e[0;31m[  FAILED  ] \e[mUnsigned/TypedTestP/0.Failure, where TypeParam = unsigned char
+\e[0;32m[----------] \e[m2 tests from Unsigned/TypedTestP/1, where TypeParam = unsigned int
+\e[0;32m[ RUN      ] \e[mUnsigned/TypedTestP/1.Success
+\e[0;32m[       OK ] \e[mUnsigned/TypedTestP/1.Success
+\e[0;32m[ RUN      ] \e[mUnsigned/TypedTestP/1.Failure
+gtest_output_test_.cc:#: Failure
+Value of: TypeParam()
+  Actual: 0
+Expected: 1U
+Which is: 1
+Expected failure
+\e[0;31m[  FAILED  ] \e[mUnsigned/TypedTestP/1.Failure, where TypeParam = unsigned int
+\e[0;32m[----------] \e[m4 tests from ExpectFailureTest
+\e[0;32m[ RUN      ] \e[mExpectFailureTest.ExpectFatalFailure
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual:
+gtest_output_test_.cc:#: Success:
+Succeeded
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual:
+gtest_output_test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure.
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure containing "Some other fatal failure expected."
+  Actual:
+gtest_output_test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+
+\e[0;31m[  FAILED  ] \e[mExpectFailureTest.ExpectFatalFailure
+\e[0;32m[ RUN      ] \e[mExpectFailureTest.ExpectNonFatalFailure
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual:
+gtest_output_test_.cc:#: Success:
+Succeeded
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual:
+gtest_output_test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure containing "Some other non-fatal failure."
+  Actual:
+gtest_output_test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure.
+
+\e[0;31m[  FAILED  ] \e[mExpectFailureTest.ExpectNonFatalFailure
+\e[0;32m[ RUN      ] \e[mExpectFailureTest.ExpectFatalFailureOnAllThreads
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual:
+gtest_output_test_.cc:#: Success:
+Succeeded
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual:
+gtest_output_test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure.
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 fatal failure containing "Some other fatal failure expected."
+  Actual:
+gtest_output_test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+
+\e[0;31m[  FAILED  ] \e[mExpectFailureTest.ExpectFatalFailureOnAllThreads
+\e[0;32m[ RUN      ] \e[mExpectFailureTest.ExpectNonFatalFailureOnAllThreads
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual:
+gtest_output_test_.cc:#: Success:
+Succeeded
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual:
+gtest_output_test_.cc:#: Fatal failure:
+Failed
+Expected fatal failure.
+
+(expecting 1 failure)
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure containing "Some other non-fatal failure."
+  Actual:
+gtest_output_test_.cc:#: Non-fatal failure:
+Failed
+Expected non-fatal failure.
+
+\e[0;31m[  FAILED  ] \e[mExpectFailureTest.ExpectNonFatalFailureOnAllThreads
+\e[0;32m[----------] \e[m2 tests from ExpectFailureWithThreadsTest
+\e[0;32m[ RUN      ] \e[mExpectFailureWithThreadsTest.ExpectFatalFailure
+(expecting 2 failures)
+gtest_output_test_.cc:#: Failure
+Failed
+Expected fatal failure.
+gtest.cc:#: Failure
+Expected: 1 fatal failure
+  Actual: 0 failures
+\e[0;31m[  FAILED  ] \e[mExpectFailureWithThreadsTest.ExpectFatalFailure
+\e[0;32m[ RUN      ] \e[mExpectFailureWithThreadsTest.ExpectNonFatalFailure
+(expecting 2 failures)
+gtest_output_test_.cc:#: Failure
+Failed
+Expected non-fatal failure.
+gtest.cc:#: Failure
+Expected: 1 non-fatal failure
+  Actual: 0 failures
+\e[0;31m[  FAILED  ] \e[mExpectFailureWithThreadsTest.ExpectNonFatalFailure
+\e[0;32m[----------] \e[m1 test from ScopedFakeTestPartResultReporterTest
+\e[0;32m[ RUN      ] \e[mScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
+(expecting 2 failures)
+gtest_output_test_.cc:#: Failure
+Failed
+Expected fatal failure.
+gtest_output_test_.cc:#: Failure
+Failed
+Expected non-fatal failure.
+\e[0;31m[  FAILED  ] \e[mScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
+\e[0;32m[----------] \e[m1 test from PrintingFailingParams/FailingParamTest
+\e[0;32m[ RUN      ] \e[mPrintingFailingParams/FailingParamTest.Fails/0
+gtest_output_test_.cc:#: Failure
+Value of: GetParam()
+  Actual: 2
+Expected: 1
+\e[0;31m[  FAILED  ] \e[mPrintingFailingParams/FailingParamTest.Fails/0, where GetParam() = 2
+\e[0;32m[----------] \e[mGlobal test environment tear-down
+BarEnvironment::TearDown() called.
+gtest_output_test_.cc:#: Failure
+Failed
+Expected non-fatal failure.
+FooEnvironment::TearDown() called.
+gtest_output_test_.cc:#: Failure
+Failed
+Expected fatal failure.
+\e[0;32m[==========] \e[m62 tests from 27 test cases ran.
+\e[0;32m[  PASSED  ] \e[m21 tests.
+\e[0;31m[  FAILED  ] \e[m41 tests, listed below:
+\e[0;31m[  FAILED  ] \e[mFatalFailureTest.FatalFailureInSubroutine
+\e[0;31m[  FAILED  ] \e[mFatalFailureTest.FatalFailureInNestedSubroutine
+\e[0;31m[  FAILED  ] \e[mFatalFailureTest.NonfatalFailureInSubroutine
+\e[0;31m[  FAILED  ] \e[mLoggingTest.InterleavingLoggingAndAssertions
+\e[0;31m[  FAILED  ] \e[mSCOPED_TRACETest.ObeysScopes
+\e[0;31m[  FAILED  ] \e[mSCOPED_TRACETest.WorksInLoop
+\e[0;31m[  FAILED  ] \e[mSCOPED_TRACETest.WorksInSubroutine
+\e[0;31m[  FAILED  ] \e[mSCOPED_TRACETest.CanBeNested
+\e[0;31m[  FAILED  ] \e[mSCOPED_TRACETest.CanBeRepeated
+\e[0;31m[  FAILED  ] \e[mSCOPED_TRACETest.WorksConcurrently
+\e[0;31m[  FAILED  ] \e[mNonFatalFailureInFixtureConstructorTest.FailureInConstructor
+\e[0;31m[  FAILED  ] \e[mFatalFailureInFixtureConstructorTest.FailureInConstructor
+\e[0;31m[  FAILED  ] \e[mNonFatalFailureInSetUpTest.FailureInSetUp
+\e[0;31m[  FAILED  ] \e[mFatalFailureInSetUpTest.FailureInSetUp
+\e[0;31m[  FAILED  ] \e[mAddFailureAtTest.MessageContainsSpecifiedFileAndLineNumber
+\e[0;31m[  FAILED  ] \e[mMixedUpTestCaseTest.ThisShouldFail
+\e[0;31m[  FAILED  ] \e[mMixedUpTestCaseTest.ThisShouldFailToo
+\e[0;31m[  FAILED  ] \e[mMixedUpTestCaseWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
+\e[0;31m[  FAILED  ] \e[mTEST_F_before_TEST_in_same_test_case.DefinedUsingTESTAndShouldFail
+\e[0;31m[  FAILED  ] \e[mTEST_before_TEST_F_in_same_test_case.DefinedUsingTEST_FAndShouldFail
+\e[0;31m[  FAILED  ] \e[mExpectNonfatalFailureTest.FailsWhenThereIsNoNonfatalFailure
+\e[0;31m[  FAILED  ] \e[mExpectNonfatalFailureTest.FailsWhenThereAreTwoNonfatalFailures
+\e[0;31m[  FAILED  ] \e[mExpectNonfatalFailureTest.FailsWhenThereIsOneFatalFailure
+\e[0;31m[  FAILED  ] \e[mExpectNonfatalFailureTest.FailsWhenStatementReturns
+\e[0;31m[  FAILED  ] \e[mExpectNonfatalFailureTest.FailsWhenStatementThrows
+\e[0;31m[  FAILED  ] \e[mExpectFatalFailureTest.FailsWhenThereIsNoFatalFailure
+\e[0;31m[  FAILED  ] \e[mExpectFatalFailureTest.FailsWhenThereAreTwoFatalFailures
+\e[0;31m[  FAILED  ] \e[mExpectFatalFailureTest.FailsWhenThereIsOneNonfatalFailure
+\e[0;31m[  FAILED  ] \e[mExpectFatalFailureTest.FailsWhenStatementReturns
+\e[0;31m[  FAILED  ] \e[mExpectFatalFailureTest.FailsWhenStatementThrows
+\e[0;31m[  FAILED  ] \e[mTypedTest/0.Failure, where TypeParam = int
+\e[0;31m[  FAILED  ] \e[mUnsigned/TypedTestP/0.Failure, where TypeParam = unsigned char
+\e[0;31m[  FAILED  ] \e[mUnsigned/TypedTestP/1.Failure, where TypeParam = unsigned int
+\e[0;31m[  FAILED  ] \e[mExpectFailureTest.ExpectFatalFailure
+\e[0;31m[  FAILED  ] \e[mExpectFailureTest.ExpectNonFatalFailure
+\e[0;31m[  FAILED  ] \e[mExpectFailureTest.ExpectFatalFailureOnAllThreads
+\e[0;31m[  FAILED  ] \e[mExpectFailureTest.ExpectNonFatalFailureOnAllThreads
+\e[0;31m[  FAILED  ] \e[mExpectFailureWithThreadsTest.ExpectFatalFailure
+\e[0;31m[  FAILED  ] \e[mExpectFailureWithThreadsTest.ExpectNonFatalFailure
+\e[0;31m[  FAILED  ] \e[mScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
+\e[0;31m[  FAILED  ] \e[mPrintingFailingParams/FailingParamTest.Fails/0, where GetParam() = 2
+
+41 FAILED TESTS
+\e[0;33m  YOU HAVE 1 DISABLED TEST
+
+\e[mNote: Google Test filter = FatalFailureTest.*:LoggingTest.*
+[==========] Running 4 tests from 2 test cases.
+[----------] Global test environment set-up.
+[----------] 3 tests from FatalFailureTest
+[ RUN      ] FatalFailureTest.FatalFailureInSubroutine
+(expecting a failure that x should be 1)
+gtest_output_test_.cc:#: Failure
+Value of: x
+  Actual: 2
+Expected: 1
+[  FAILED  ] FatalFailureTest.FatalFailureInSubroutine (? ms)
+[ RUN      ] FatalFailureTest.FatalFailureInNestedSubroutine
+(expecting a failure that x should be 1)
+gtest_output_test_.cc:#: Failure
+Value of: x
+  Actual: 2
+Expected: 1
+[  FAILED  ] FatalFailureTest.FatalFailureInNestedSubroutine (? ms)
+[ RUN      ] FatalFailureTest.NonfatalFailureInSubroutine
+(expecting a failure on false)
+gtest_output_test_.cc:#: Failure
+Value of: false
+  Actual: false
+Expected: true
+[  FAILED  ] FatalFailureTest.NonfatalFailureInSubroutine (? ms)
+[----------] 3 tests from FatalFailureTest (? ms total)
+
+[----------] 1 test from LoggingTest
+[ RUN      ] LoggingTest.InterleavingLoggingAndAssertions
+(expecting 2 failures on (3) >= (a[i]))
+i == 0
+i == 1
+gtest_output_test_.cc:#: Failure
+Expected: (3) >= (a[i]), actual: 3 vs 9
+i == 2
+i == 3
+gtest_output_test_.cc:#: Failure
+Expected: (3) >= (a[i]), actual: 3 vs 6
+[  FAILED  ] LoggingTest.InterleavingLoggingAndAssertions (? ms)
+[----------] 1 test from LoggingTest (? ms total)
+
+[----------] Global test environment tear-down
+[==========] 4 tests from 2 test cases ran. (? ms total)
+[  PASSED  ] 0 tests.
+[  FAILED  ] 4 tests, listed below:
+[  FAILED  ] FatalFailureTest.FatalFailureInSubroutine
+[  FAILED  ] FatalFailureTest.FatalFailureInNestedSubroutine
+[  FAILED  ] FatalFailureTest.NonfatalFailureInSubroutine
+[  FAILED  ] LoggingTest.InterleavingLoggingAndAssertions
+
+ 4 FAILED TESTS
+  YOU HAVE 1 DISABLED TEST
+
+Note: Google Test filter = *DISABLED_*
+[==========] Running 1 test from 1 test case.
+[----------] Global test environment set-up.
+[----------] 1 test from DisabledTestsWarningTest
+[ RUN      ] DisabledTestsWarningTest.DISABLED_AlsoRunDisabledTestsFlagSuppressesWarning
+[       OK ] DisabledTestsWarningTest.DISABLED_AlsoRunDisabledTestsFlagSuppressesWarning
+[----------] Global test environment tear-down
+[==========] 1 test from 1 test case ran.
+[  PASSED  ] 1 test.
+Note: Google Test filter = PassingTest.*
+Note: This is test shard 2 of 2.
+[==========] Running 1 test from 1 test case.
+[----------] Global test environment set-up.
+[----------] 1 test from PassingTest
+[ RUN      ] PassingTest.PassingTest2
+[       OK ] PassingTest.PassingTest2
+[----------] Global test environment tear-down
+[==========] 1 test from 1 test case ran.
+[  PASSED  ] 1 test.
+
+  YOU HAVE 1 DISABLED TEST
+
diff --git a/third_party/googletest/src/test/gtest_pred_impl_unittest.cc b/third_party/googletest/src/test/gtest_pred_impl_unittest.cc
new file mode 100644 (file)
index 0000000..35dc9bc
--- /dev/null
@@ -0,0 +1,2427 @@
+// Copyright 2006, 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.
+
+// This file is AUTOMATICALLY GENERATED on 09/24/2010 by command
+// 'gen_gtest_pred_impl.py 5'.  DO NOT EDIT BY HAND!
+
+// Regression test for gtest_pred_impl.h
+//
+// This file is generated by a script and quite long.  If you intend to
+// learn how Google Test works by reading its unit tests, read
+// gtest_unittest.cc instead.
+//
+// This is intended as a regression test for the Google Test predicate
+// assertions.  We compile it as part of the gtest_unittest target
+// only to keep the implementation tidy and compact, as it is quite
+// involved to set up the stage for testing Google Test using Google
+// Test itself.
+//
+// Currently, gtest_unittest takes ~11 seconds to run in the testing
+// daemon.  In the future, if it grows too large and needs much more
+// time to finish, we should consider separating this file into a
+// stand-alone regression test.
+
+#include <iostream>
+
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
+
+// A user-defined data type.
+struct Bool {
+  explicit Bool(int val) : value(val != 0) {}
+
+  bool operator>(int n) const { return value > Bool(n).value; }
+
+  Bool operator+(const Bool& rhs) const { return Bool(value + rhs.value); }
+
+  bool operator==(const Bool& rhs) const { return value == rhs.value; }
+
+  bool value;
+};
+
+// Enables Bool to be used in assertions.
+std::ostream& operator<<(std::ostream& os, const Bool& x) {
+  return os << (x.value ? "true" : "false");
+}
+
+// Sample functions/functors for testing unary predicate assertions.
+
+// A unary predicate function.
+template <typename T1>
+bool PredFunction1(T1 v1) {
+  return v1 > 0;
+}
+
+// The following two functions are needed to circumvent a bug in
+// gcc 2.95.3, which sometimes has problem with the above template
+// function.
+bool PredFunction1Int(int v1) {
+  return v1 > 0;
+}
+bool PredFunction1Bool(Bool v1) {
+  return v1 > 0;
+}
+
+// A unary predicate functor.
+struct PredFunctor1 {
+  template <typename T1>
+  bool operator()(const T1& v1) {
+    return v1 > 0;
+  }
+};
+
+// A unary predicate-formatter function.
+template <typename T1>
+testing::AssertionResult PredFormatFunction1(const char* e1,
+                                             const T1& v1) {
+  if (PredFunction1(v1))
+    return testing::AssertionSuccess();
+
+  return testing::AssertionFailure()
+      << e1
+      << " is expected to be positive, but evaluates to "
+      << v1 << ".";
+}
+
+// A unary predicate-formatter functor.
+struct PredFormatFunctor1 {
+  template <typename T1>
+  testing::AssertionResult operator()(const char* e1,
+                                      const T1& v1) const {
+    return PredFormatFunction1(e1, v1);
+  }
+};
+
+// Tests for {EXPECT|ASSERT}_PRED_FORMAT1.
+
+class Predicate1Test : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    expected_to_finish_ = true;
+    finished_ = false;
+    n1_ = 0;
+  }
+
+  virtual void TearDown() {
+    // Verifies that each of the predicate's arguments was evaluated
+    // exactly once.
+    EXPECT_EQ(1, n1_) <<
+        "The predicate assertion didn't evaluate argument 2 "
+        "exactly once.";
+
+    // Verifies that the control flow in the test function is expected.
+    if (expected_to_finish_ && !finished_) {
+      FAIL() << "The predicate assertion unexpactedly aborted the test.";
+    } else if (!expected_to_finish_ && finished_) {
+      FAIL() << "The failed predicate assertion didn't abort the test "
+                "as expected.";
+    }
+  }
+
+  // true iff the test function is expected to run to finish.
+  static bool expected_to_finish_;
+
+  // true iff the test function did run to finish.
+  static bool finished_;
+
+  static int n1_;
+};
+
+bool Predicate1Test::expected_to_finish_;
+bool Predicate1Test::finished_;
+int Predicate1Test::n1_;
+
+typedef Predicate1Test EXPECT_PRED_FORMAT1Test;
+typedef Predicate1Test ASSERT_PRED_FORMAT1Test;
+typedef Predicate1Test EXPECT_PRED1Test;
+typedef Predicate1Test ASSERT_PRED1Test;
+
+// Tests a successful EXPECT_PRED1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED1Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED1(PredFunction1Int,
+               ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED1Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED1(PredFunction1Bool,
+               Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED1Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED1(PredFunctor1(),
+               ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED1Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED1(PredFunctor1(),
+               Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED1Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED1(PredFunction1Int,
+                 n1_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED1Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED1(PredFunction1Bool,
+                 Bool(n1_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED1Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED1(PredFunctor1(),
+                 n1_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED1Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED1(PredFunctor1(),
+                 Bool(n1_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful ASSERT_PRED1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED1Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED1(PredFunction1Int,
+               ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED1Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED1(PredFunction1Bool,
+               Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED1Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED1(PredFunctor1(),
+               ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED1Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED1(PredFunctor1(),
+               Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED1Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED1(PredFunction1Int,
+                 n1_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED1Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED1(PredFunction1Bool,
+                 Bool(n1_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED1Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED1(PredFunctor1(),
+                 n1_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED1Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED1(PredFunctor1(),
+                 Bool(n1_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT1(PredFormatFunction1,
+                      ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT1(PredFormatFunction1,
+                      Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT1(PredFormatFunctor1(),
+                      ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT1(PredFormatFunctor1(),
+                      Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT1(PredFormatFunction1,
+                        n1_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT1(PredFormatFunction1,
+                        Bool(n1_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT1(PredFormatFunctor1(),
+                        n1_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT1Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT1(PredFormatFunctor1(),
+                        Bool(n1_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT1(PredFormatFunction1,
+                      ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT1(PredFormatFunction1,
+                      Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT1(PredFormatFunctor1(),
+                      ++n1_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT1(PredFormatFunctor1(),
+                      Bool(++n1_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT1(PredFormatFunction1,
+                        n1_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT1(PredFormatFunction1,
+                        Bool(n1_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT1(PredFormatFunctor1(),
+                        n1_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT1 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT1Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT1(PredFormatFunctor1(),
+                        Bool(n1_++));
+    finished_ = true;
+  }, "");
+}
+// Sample functions/functors for testing binary predicate assertions.
+
+// A binary predicate function.
+template <typename T1, typename T2>
+bool PredFunction2(T1 v1, T2 v2) {
+  return v1 + v2 > 0;
+}
+
+// The following two functions are needed to circumvent a bug in
+// gcc 2.95.3, which sometimes has problem with the above template
+// function.
+bool PredFunction2Int(int v1, int v2) {
+  return v1 + v2 > 0;
+}
+bool PredFunction2Bool(Bool v1, Bool v2) {
+  return v1 + v2 > 0;
+}
+
+// A binary predicate functor.
+struct PredFunctor2 {
+  template <typename T1, typename T2>
+  bool operator()(const T1& v1,
+                  const T2& v2) {
+    return v1 + v2 > 0;
+  }
+};
+
+// A binary predicate-formatter function.
+template <typename T1, typename T2>
+testing::AssertionResult PredFormatFunction2(const char* e1,
+                                             const char* e2,
+                                             const T1& v1,
+                                             const T2& v2) {
+  if (PredFunction2(v1, v2))
+    return testing::AssertionSuccess();
+
+  return testing::AssertionFailure()
+      << e1 << " + " << e2
+      << " is expected to be positive, but evaluates to "
+      << v1 + v2 << ".";
+}
+
+// A binary predicate-formatter functor.
+struct PredFormatFunctor2 {
+  template <typename T1, typename T2>
+  testing::AssertionResult operator()(const char* e1,
+                                      const char* e2,
+                                      const T1& v1,
+                                      const T2& v2) const {
+    return PredFormatFunction2(e1, e2, v1, v2);
+  }
+};
+
+// Tests for {EXPECT|ASSERT}_PRED_FORMAT2.
+
+class Predicate2Test : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    expected_to_finish_ = true;
+    finished_ = false;
+    n1_ = n2_ = 0;
+  }
+
+  virtual void TearDown() {
+    // Verifies that each of the predicate's arguments was evaluated
+    // exactly once.
+    EXPECT_EQ(1, n1_) <<
+        "The predicate assertion didn't evaluate argument 2 "
+        "exactly once.";
+    EXPECT_EQ(1, n2_) <<
+        "The predicate assertion didn't evaluate argument 3 "
+        "exactly once.";
+
+    // Verifies that the control flow in the test function is expected.
+    if (expected_to_finish_ && !finished_) {
+      FAIL() << "The predicate assertion unexpactedly aborted the test.";
+    } else if (!expected_to_finish_ && finished_) {
+      FAIL() << "The failed predicate assertion didn't abort the test "
+                "as expected.";
+    }
+  }
+
+  // true iff the test function is expected to run to finish.
+  static bool expected_to_finish_;
+
+  // true iff the test function did run to finish.
+  static bool finished_;
+
+  static int n1_;
+  static int n2_;
+};
+
+bool Predicate2Test::expected_to_finish_;
+bool Predicate2Test::finished_;
+int Predicate2Test::n1_;
+int Predicate2Test::n2_;
+
+typedef Predicate2Test EXPECT_PRED_FORMAT2Test;
+typedef Predicate2Test ASSERT_PRED_FORMAT2Test;
+typedef Predicate2Test EXPECT_PRED2Test;
+typedef Predicate2Test ASSERT_PRED2Test;
+
+// Tests a successful EXPECT_PRED2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED2Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED2(PredFunction2Int,
+               ++n1_,
+               ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED2Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED2(PredFunction2Bool,
+               Bool(++n1_),
+               Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED2Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED2(PredFunctor2(),
+               ++n1_,
+               ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED2Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED2(PredFunctor2(),
+               Bool(++n1_),
+               Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED2Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED2(PredFunction2Int,
+                 n1_++,
+                 n2_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED2Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED2(PredFunction2Bool,
+                 Bool(n1_++),
+                 Bool(n2_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED2Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED2(PredFunctor2(),
+                 n1_++,
+                 n2_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED2Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED2(PredFunctor2(),
+                 Bool(n1_++),
+                 Bool(n2_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful ASSERT_PRED2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED2Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED2(PredFunction2Int,
+               ++n1_,
+               ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED2Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED2(PredFunction2Bool,
+               Bool(++n1_),
+               Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED2Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED2(PredFunctor2(),
+               ++n1_,
+               ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED2Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED2(PredFunctor2(),
+               Bool(++n1_),
+               Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED2Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED2(PredFunction2Int,
+                 n1_++,
+                 n2_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED2Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED2(PredFunction2Bool,
+                 Bool(n1_++),
+                 Bool(n2_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED2Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED2(PredFunctor2(),
+                 n1_++,
+                 n2_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED2Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED2(PredFunctor2(),
+                 Bool(n1_++),
+                 Bool(n2_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT2(PredFormatFunction2,
+                      ++n1_,
+                      ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT2(PredFormatFunction2,
+                      Bool(++n1_),
+                      Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT2(PredFormatFunctor2(),
+                      ++n1_,
+                      ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT2(PredFormatFunctor2(),
+                      Bool(++n1_),
+                      Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT2(PredFormatFunction2,
+                        n1_++,
+                        n2_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT2(PredFormatFunction2,
+                        Bool(n1_++),
+                        Bool(n2_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT2(PredFormatFunctor2(),
+                        n1_++,
+                        n2_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT2Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT2(PredFormatFunctor2(),
+                        Bool(n1_++),
+                        Bool(n2_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT2(PredFormatFunction2,
+                      ++n1_,
+                      ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT2(PredFormatFunction2,
+                      Bool(++n1_),
+                      Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT2(PredFormatFunctor2(),
+                      ++n1_,
+                      ++n2_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT2(PredFormatFunctor2(),
+                      Bool(++n1_),
+                      Bool(++n2_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT2(PredFormatFunction2,
+                        n1_++,
+                        n2_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT2(PredFormatFunction2,
+                        Bool(n1_++),
+                        Bool(n2_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT2(PredFormatFunctor2(),
+                        n1_++,
+                        n2_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT2 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT2Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT2(PredFormatFunctor2(),
+                        Bool(n1_++),
+                        Bool(n2_++));
+    finished_ = true;
+  }, "");
+}
+// Sample functions/functors for testing ternary predicate assertions.
+
+// A ternary predicate function.
+template <typename T1, typename T2, typename T3>
+bool PredFunction3(T1 v1, T2 v2, T3 v3) {
+  return v1 + v2 + v3 > 0;
+}
+
+// The following two functions are needed to circumvent a bug in
+// gcc 2.95.3, which sometimes has problem with the above template
+// function.
+bool PredFunction3Int(int v1, int v2, int v3) {
+  return v1 + v2 + v3 > 0;
+}
+bool PredFunction3Bool(Bool v1, Bool v2, Bool v3) {
+  return v1 + v2 + v3 > 0;
+}
+
+// A ternary predicate functor.
+struct PredFunctor3 {
+  template <typename T1, typename T2, typename T3>
+  bool operator()(const T1& v1,
+                  const T2& v2,
+                  const T3& v3) {
+    return v1 + v2 + v3 > 0;
+  }
+};
+
+// A ternary predicate-formatter function.
+template <typename T1, typename T2, typename T3>
+testing::AssertionResult PredFormatFunction3(const char* e1,
+                                             const char* e2,
+                                             const char* e3,
+                                             const T1& v1,
+                                             const T2& v2,
+                                             const T3& v3) {
+  if (PredFunction3(v1, v2, v3))
+    return testing::AssertionSuccess();
+
+  return testing::AssertionFailure()
+      << e1 << " + " << e2 << " + " << e3
+      << " is expected to be positive, but evaluates to "
+      << v1 + v2 + v3 << ".";
+}
+
+// A ternary predicate-formatter functor.
+struct PredFormatFunctor3 {
+  template <typename T1, typename T2, typename T3>
+  testing::AssertionResult operator()(const char* e1,
+                                      const char* e2,
+                                      const char* e3,
+                                      const T1& v1,
+                                      const T2& v2,
+                                      const T3& v3) const {
+    return PredFormatFunction3(e1, e2, e3, v1, v2, v3);
+  }
+};
+
+// Tests for {EXPECT|ASSERT}_PRED_FORMAT3.
+
+class Predicate3Test : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    expected_to_finish_ = true;
+    finished_ = false;
+    n1_ = n2_ = n3_ = 0;
+  }
+
+  virtual void TearDown() {
+    // Verifies that each of the predicate's arguments was evaluated
+    // exactly once.
+    EXPECT_EQ(1, n1_) <<
+        "The predicate assertion didn't evaluate argument 2 "
+        "exactly once.";
+    EXPECT_EQ(1, n2_) <<
+        "The predicate assertion didn't evaluate argument 3 "
+        "exactly once.";
+    EXPECT_EQ(1, n3_) <<
+        "The predicate assertion didn't evaluate argument 4 "
+        "exactly once.";
+
+    // Verifies that the control flow in the test function is expected.
+    if (expected_to_finish_ && !finished_) {
+      FAIL() << "The predicate assertion unexpactedly aborted the test.";
+    } else if (!expected_to_finish_ && finished_) {
+      FAIL() << "The failed predicate assertion didn't abort the test "
+                "as expected.";
+    }
+  }
+
+  // true iff the test function is expected to run to finish.
+  static bool expected_to_finish_;
+
+  // true iff the test function did run to finish.
+  static bool finished_;
+
+  static int n1_;
+  static int n2_;
+  static int n3_;
+};
+
+bool Predicate3Test::expected_to_finish_;
+bool Predicate3Test::finished_;
+int Predicate3Test::n1_;
+int Predicate3Test::n2_;
+int Predicate3Test::n3_;
+
+typedef Predicate3Test EXPECT_PRED_FORMAT3Test;
+typedef Predicate3Test ASSERT_PRED_FORMAT3Test;
+typedef Predicate3Test EXPECT_PRED3Test;
+typedef Predicate3Test ASSERT_PRED3Test;
+
+// Tests a successful EXPECT_PRED3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED3Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED3(PredFunction3Int,
+               ++n1_,
+               ++n2_,
+               ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED3Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED3(PredFunction3Bool,
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED3Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED3(PredFunctor3(),
+               ++n1_,
+               ++n2_,
+               ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED3Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED3(PredFunctor3(),
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED3Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED3(PredFunction3Int,
+                 n1_++,
+                 n2_++,
+                 n3_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED3Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED3(PredFunction3Bool,
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED3Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED3(PredFunctor3(),
+                 n1_++,
+                 n2_++,
+                 n3_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED3Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED3(PredFunctor3(),
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful ASSERT_PRED3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED3Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED3(PredFunction3Int,
+               ++n1_,
+               ++n2_,
+               ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED3Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED3(PredFunction3Bool,
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED3Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED3(PredFunctor3(),
+               ++n1_,
+               ++n2_,
+               ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED3Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED3(PredFunctor3(),
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED3Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED3(PredFunction3Int,
+                 n1_++,
+                 n2_++,
+                 n3_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED3Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED3(PredFunction3Bool,
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED3Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED3(PredFunctor3(),
+                 n1_++,
+                 n2_++,
+                 n3_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED3Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED3(PredFunctor3(),
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT3(PredFormatFunction3,
+                      ++n1_,
+                      ++n2_,
+                      ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT3(PredFormatFunction3,
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT3(PredFormatFunctor3(),
+                      ++n1_,
+                      ++n2_,
+                      ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT3(PredFormatFunctor3(),
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT3(PredFormatFunction3,
+                        n1_++,
+                        n2_++,
+                        n3_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT3(PredFormatFunction3,
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT3(PredFormatFunctor3(),
+                        n1_++,
+                        n2_++,
+                        n3_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT3Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT3(PredFormatFunctor3(),
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT3(PredFormatFunction3,
+                      ++n1_,
+                      ++n2_,
+                      ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT3(PredFormatFunction3,
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT3(PredFormatFunctor3(),
+                      ++n1_,
+                      ++n2_,
+                      ++n3_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT3(PredFormatFunctor3(),
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT3(PredFormatFunction3,
+                        n1_++,
+                        n2_++,
+                        n3_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT3(PredFormatFunction3,
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT3(PredFormatFunctor3(),
+                        n1_++,
+                        n2_++,
+                        n3_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT3 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT3Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT3(PredFormatFunctor3(),
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++));
+    finished_ = true;
+  }, "");
+}
+// Sample functions/functors for testing 4-ary predicate assertions.
+
+// A 4-ary predicate function.
+template <typename T1, typename T2, typename T3, typename T4>
+bool PredFunction4(T1 v1, T2 v2, T3 v3, T4 v4) {
+  return v1 + v2 + v3 + v4 > 0;
+}
+
+// The following two functions are needed to circumvent a bug in
+// gcc 2.95.3, which sometimes has problem with the above template
+// function.
+bool PredFunction4Int(int v1, int v2, int v3, int v4) {
+  return v1 + v2 + v3 + v4 > 0;
+}
+bool PredFunction4Bool(Bool v1, Bool v2, Bool v3, Bool v4) {
+  return v1 + v2 + v3 + v4 > 0;
+}
+
+// A 4-ary predicate functor.
+struct PredFunctor4 {
+  template <typename T1, typename T2, typename T3, typename T4>
+  bool operator()(const T1& v1,
+                  const T2& v2,
+                  const T3& v3,
+                  const T4& v4) {
+    return v1 + v2 + v3 + v4 > 0;
+  }
+};
+
+// A 4-ary predicate-formatter function.
+template <typename T1, typename T2, typename T3, typename T4>
+testing::AssertionResult PredFormatFunction4(const char* e1,
+                                             const char* e2,
+                                             const char* e3,
+                                             const char* e4,
+                                             const T1& v1,
+                                             const T2& v2,
+                                             const T3& v3,
+                                             const T4& v4) {
+  if (PredFunction4(v1, v2, v3, v4))
+    return testing::AssertionSuccess();
+
+  return testing::AssertionFailure()
+      << e1 << " + " << e2 << " + " << e3 << " + " << e4
+      << " is expected to be positive, but evaluates to "
+      << v1 + v2 + v3 + v4 << ".";
+}
+
+// A 4-ary predicate-formatter functor.
+struct PredFormatFunctor4 {
+  template <typename T1, typename T2, typename T3, typename T4>
+  testing::AssertionResult operator()(const char* e1,
+                                      const char* e2,
+                                      const char* e3,
+                                      const char* e4,
+                                      const T1& v1,
+                                      const T2& v2,
+                                      const T3& v3,
+                                      const T4& v4) const {
+    return PredFormatFunction4(e1, e2, e3, e4, v1, v2, v3, v4);
+  }
+};
+
+// Tests for {EXPECT|ASSERT}_PRED_FORMAT4.
+
+class Predicate4Test : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    expected_to_finish_ = true;
+    finished_ = false;
+    n1_ = n2_ = n3_ = n4_ = 0;
+  }
+
+  virtual void TearDown() {
+    // Verifies that each of the predicate's arguments was evaluated
+    // exactly once.
+    EXPECT_EQ(1, n1_) <<
+        "The predicate assertion didn't evaluate argument 2 "
+        "exactly once.";
+    EXPECT_EQ(1, n2_) <<
+        "The predicate assertion didn't evaluate argument 3 "
+        "exactly once.";
+    EXPECT_EQ(1, n3_) <<
+        "The predicate assertion didn't evaluate argument 4 "
+        "exactly once.";
+    EXPECT_EQ(1, n4_) <<
+        "The predicate assertion didn't evaluate argument 5 "
+        "exactly once.";
+
+    // Verifies that the control flow in the test function is expected.
+    if (expected_to_finish_ && !finished_) {
+      FAIL() << "The predicate assertion unexpactedly aborted the test.";
+    } else if (!expected_to_finish_ && finished_) {
+      FAIL() << "The failed predicate assertion didn't abort the test "
+                "as expected.";
+    }
+  }
+
+  // true iff the test function is expected to run to finish.
+  static bool expected_to_finish_;
+
+  // true iff the test function did run to finish.
+  static bool finished_;
+
+  static int n1_;
+  static int n2_;
+  static int n3_;
+  static int n4_;
+};
+
+bool Predicate4Test::expected_to_finish_;
+bool Predicate4Test::finished_;
+int Predicate4Test::n1_;
+int Predicate4Test::n2_;
+int Predicate4Test::n3_;
+int Predicate4Test::n4_;
+
+typedef Predicate4Test EXPECT_PRED_FORMAT4Test;
+typedef Predicate4Test ASSERT_PRED_FORMAT4Test;
+typedef Predicate4Test EXPECT_PRED4Test;
+typedef Predicate4Test ASSERT_PRED4Test;
+
+// Tests a successful EXPECT_PRED4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED4Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED4(PredFunction4Int,
+               ++n1_,
+               ++n2_,
+               ++n3_,
+               ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED4Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED4(PredFunction4Bool,
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_),
+               Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED4Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED4(PredFunctor4(),
+               ++n1_,
+               ++n2_,
+               ++n3_,
+               ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED4Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED4(PredFunctor4(),
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_),
+               Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED4Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED4(PredFunction4Int,
+                 n1_++,
+                 n2_++,
+                 n3_++,
+                 n4_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED4Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED4(PredFunction4Bool,
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++),
+                 Bool(n4_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED4Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED4(PredFunctor4(),
+                 n1_++,
+                 n2_++,
+                 n3_++,
+                 n4_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED4Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED4(PredFunctor4(),
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++),
+                 Bool(n4_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful ASSERT_PRED4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED4Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED4(PredFunction4Int,
+               ++n1_,
+               ++n2_,
+               ++n3_,
+               ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED4Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED4(PredFunction4Bool,
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_),
+               Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED4Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED4(PredFunctor4(),
+               ++n1_,
+               ++n2_,
+               ++n3_,
+               ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED4Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED4(PredFunctor4(),
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_),
+               Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED4Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED4(PredFunction4Int,
+                 n1_++,
+                 n2_++,
+                 n3_++,
+                 n4_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED4Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED4(PredFunction4Bool,
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++),
+                 Bool(n4_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED4Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED4(PredFunctor4(),
+                 n1_++,
+                 n2_++,
+                 n3_++,
+                 n4_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED4Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED4(PredFunctor4(),
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++),
+                 Bool(n4_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT4(PredFormatFunction4,
+                      ++n1_,
+                      ++n2_,
+                      ++n3_,
+                      ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT4(PredFormatFunction4,
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_),
+                      Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT4(PredFormatFunctor4(),
+                      ++n1_,
+                      ++n2_,
+                      ++n3_,
+                      ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT4(PredFormatFunctor4(),
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_),
+                      Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT4(PredFormatFunction4,
+                        n1_++,
+                        n2_++,
+                        n3_++,
+                        n4_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT4(PredFormatFunction4,
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++),
+                        Bool(n4_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT4(PredFormatFunctor4(),
+                        n1_++,
+                        n2_++,
+                        n3_++,
+                        n4_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT4Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT4(PredFormatFunctor4(),
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++),
+                        Bool(n4_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT4(PredFormatFunction4,
+                      ++n1_,
+                      ++n2_,
+                      ++n3_,
+                      ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT4(PredFormatFunction4,
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_),
+                      Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT4(PredFormatFunctor4(),
+                      ++n1_,
+                      ++n2_,
+                      ++n3_,
+                      ++n4_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT4(PredFormatFunctor4(),
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_),
+                      Bool(++n4_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT4(PredFormatFunction4,
+                        n1_++,
+                        n2_++,
+                        n3_++,
+                        n4_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT4(PredFormatFunction4,
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++),
+                        Bool(n4_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT4(PredFormatFunctor4(),
+                        n1_++,
+                        n2_++,
+                        n3_++,
+                        n4_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT4 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT4Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT4(PredFormatFunctor4(),
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++),
+                        Bool(n4_++));
+    finished_ = true;
+  }, "");
+}
+// Sample functions/functors for testing 5-ary predicate assertions.
+
+// A 5-ary predicate function.
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+bool PredFunction5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) {
+  return v1 + v2 + v3 + v4 + v5 > 0;
+}
+
+// The following two functions are needed to circumvent a bug in
+// gcc 2.95.3, which sometimes has problem with the above template
+// function.
+bool PredFunction5Int(int v1, int v2, int v3, int v4, int v5) {
+  return v1 + v2 + v3 + v4 + v5 > 0;
+}
+bool PredFunction5Bool(Bool v1, Bool v2, Bool v3, Bool v4, Bool v5) {
+  return v1 + v2 + v3 + v4 + v5 > 0;
+}
+
+// A 5-ary predicate functor.
+struct PredFunctor5 {
+  template <typename T1, typename T2, typename T3, typename T4, typename T5>
+  bool operator()(const T1& v1,
+                  const T2& v2,
+                  const T3& v3,
+                  const T4& v4,
+                  const T5& v5) {
+    return v1 + v2 + v3 + v4 + v5 > 0;
+  }
+};
+
+// A 5-ary predicate-formatter function.
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+testing::AssertionResult PredFormatFunction5(const char* e1,
+                                             const char* e2,
+                                             const char* e3,
+                                             const char* e4,
+                                             const char* e5,
+                                             const T1& v1,
+                                             const T2& v2,
+                                             const T3& v3,
+                                             const T4& v4,
+                                             const T5& v5) {
+  if (PredFunction5(v1, v2, v3, v4, v5))
+    return testing::AssertionSuccess();
+
+  return testing::AssertionFailure()
+      << e1 << " + " << e2 << " + " << e3 << " + " << e4 << " + " << e5
+      << " is expected to be positive, but evaluates to "
+      << v1 + v2 + v3 + v4 + v5 << ".";
+}
+
+// A 5-ary predicate-formatter functor.
+struct PredFormatFunctor5 {
+  template <typename T1, typename T2, typename T3, typename T4, typename T5>
+  testing::AssertionResult operator()(const char* e1,
+                                      const char* e2,
+                                      const char* e3,
+                                      const char* e4,
+                                      const char* e5,
+                                      const T1& v1,
+                                      const T2& v2,
+                                      const T3& v3,
+                                      const T4& v4,
+                                      const T5& v5) const {
+    return PredFormatFunction5(e1, e2, e3, e4, e5, v1, v2, v3, v4, v5);
+  }
+};
+
+// Tests for {EXPECT|ASSERT}_PRED_FORMAT5.
+
+class Predicate5Test : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    expected_to_finish_ = true;
+    finished_ = false;
+    n1_ = n2_ = n3_ = n4_ = n5_ = 0;
+  }
+
+  virtual void TearDown() {
+    // Verifies that each of the predicate's arguments was evaluated
+    // exactly once.
+    EXPECT_EQ(1, n1_) <<
+        "The predicate assertion didn't evaluate argument 2 "
+        "exactly once.";
+    EXPECT_EQ(1, n2_) <<
+        "The predicate assertion didn't evaluate argument 3 "
+        "exactly once.";
+    EXPECT_EQ(1, n3_) <<
+        "The predicate assertion didn't evaluate argument 4 "
+        "exactly once.";
+    EXPECT_EQ(1, n4_) <<
+        "The predicate assertion didn't evaluate argument 5 "
+        "exactly once.";
+    EXPECT_EQ(1, n5_) <<
+        "The predicate assertion didn't evaluate argument 6 "
+        "exactly once.";
+
+    // Verifies that the control flow in the test function is expected.
+    if (expected_to_finish_ && !finished_) {
+      FAIL() << "The predicate assertion unexpactedly aborted the test.";
+    } else if (!expected_to_finish_ && finished_) {
+      FAIL() << "The failed predicate assertion didn't abort the test "
+                "as expected.";
+    }
+  }
+
+  // true iff the test function is expected to run to finish.
+  static bool expected_to_finish_;
+
+  // true iff the test function did run to finish.
+  static bool finished_;
+
+  static int n1_;
+  static int n2_;
+  static int n3_;
+  static int n4_;
+  static int n5_;
+};
+
+bool Predicate5Test::expected_to_finish_;
+bool Predicate5Test::finished_;
+int Predicate5Test::n1_;
+int Predicate5Test::n2_;
+int Predicate5Test::n3_;
+int Predicate5Test::n4_;
+int Predicate5Test::n5_;
+
+typedef Predicate5Test EXPECT_PRED_FORMAT5Test;
+typedef Predicate5Test ASSERT_PRED_FORMAT5Test;
+typedef Predicate5Test EXPECT_PRED5Test;
+typedef Predicate5Test ASSERT_PRED5Test;
+
+// Tests a successful EXPECT_PRED5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED5Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED5(PredFunction5Int,
+               ++n1_,
+               ++n2_,
+               ++n3_,
+               ++n4_,
+               ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED5Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED5(PredFunction5Bool,
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_),
+               Bool(++n4_),
+               Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED5Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED5(PredFunctor5(),
+               ++n1_,
+               ++n2_,
+               ++n3_,
+               ++n4_,
+               ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED5Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED5(PredFunctor5(),
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_),
+               Bool(++n4_),
+               Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED5Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED5(PredFunction5Int,
+                 n1_++,
+                 n2_++,
+                 n3_++,
+                 n4_++,
+                 n5_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED5Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED5(PredFunction5Bool,
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++),
+                 Bool(n4_++),
+                 Bool(n5_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED5Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED5(PredFunctor5(),
+                 n1_++,
+                 n2_++,
+                 n3_++,
+                 n4_++,
+                 n5_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED5Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED5(PredFunctor5(),
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++),
+                 Bool(n4_++),
+                 Bool(n5_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful ASSERT_PRED5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED5Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED5(PredFunction5Int,
+               ++n1_,
+               ++n2_,
+               ++n3_,
+               ++n4_,
+               ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED5Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED5(PredFunction5Bool,
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_),
+               Bool(++n4_),
+               Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED5Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED5(PredFunctor5(),
+               ++n1_,
+               ++n2_,
+               ++n3_,
+               ++n4_,
+               ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED5Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED5(PredFunctor5(),
+               Bool(++n1_),
+               Bool(++n2_),
+               Bool(++n3_),
+               Bool(++n4_),
+               Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED5Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED5(PredFunction5Int,
+                 n1_++,
+                 n2_++,
+                 n3_++,
+                 n4_++,
+                 n5_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED5Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED5(PredFunction5Bool,
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++),
+                 Bool(n4_++),
+                 Bool(n5_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED5Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED5(PredFunctor5(),
+                 n1_++,
+                 n2_++,
+                 n3_++,
+                 n4_++,
+                 n5_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED5Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED5(PredFunctor5(),
+                 Bool(n1_++),
+                 Bool(n2_++),
+                 Bool(n3_++),
+                 Bool(n4_++),
+                 Bool(n5_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctionOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT5(PredFormatFunction5,
+                      ++n1_,
+                      ++n2_,
+                      ++n3_,
+                      ++n4_,
+                      ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctionOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT5(PredFormatFunction5,
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_),
+                      Bool(++n4_),
+                      Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctorOnBuiltInTypeSuccess) {
+  EXPECT_PRED_FORMAT5(PredFormatFunctor5(),
+                      ++n1_,
+                      ++n2_,
+                      ++n3_,
+                      ++n4_,
+                      ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctorOnUserTypeSuccess) {
+  EXPECT_PRED_FORMAT5(PredFormatFunctor5(),
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_),
+                      Bool(++n4_),
+                      Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a failed EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctionOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT5(PredFormatFunction5,
+                        n1_++,
+                        n2_++,
+                        n3_++,
+                        n4_++,
+                        n5_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctionOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT5(PredFormatFunction5,
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++),
+                        Bool(n4_++),
+                        Bool(n5_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctorOnBuiltInTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT5(PredFormatFunctor5(),
+                        n1_++,
+                        n2_++,
+                        n3_++,
+                        n4_++,
+                        n5_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed EXPECT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(EXPECT_PRED_FORMAT5Test, FunctorOnUserTypeFailure) {
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT5(PredFormatFunctor5(),
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++),
+                        Bool(n4_++),
+                        Bool(n5_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a successful ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctionOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT5(PredFormatFunction5,
+                      ++n1_,
+                      ++n2_,
+                      ++n3_,
+                      ++n4_,
+                      ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctionOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT5(PredFormatFunction5,
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_),
+                      Bool(++n4_),
+                      Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctorOnBuiltInTypeSuccess) {
+  ASSERT_PRED_FORMAT5(PredFormatFunctor5(),
+                      ++n1_,
+                      ++n2_,
+                      ++n3_,
+                      ++n4_,
+                      ++n5_);
+  finished_ = true;
+}
+
+// Tests a successful ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctorOnUserTypeSuccess) {
+  ASSERT_PRED_FORMAT5(PredFormatFunctor5(),
+                      Bool(++n1_),
+                      Bool(++n2_),
+                      Bool(++n3_),
+                      Bool(++n4_),
+                      Bool(++n5_));
+  finished_ = true;
+}
+
+// Tests a failed ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctionOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT5(PredFormatFunction5,
+                        n1_++,
+                        n2_++,
+                        n3_++,
+                        n4_++,
+                        n5_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a function on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctionOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT5(PredFormatFunction5,
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++),
+                        Bool(n4_++),
+                        Bool(n5_++));
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a built-in type (int).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctorOnBuiltInTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT5(PredFormatFunctor5(),
+                        n1_++,
+                        n2_++,
+                        n3_++,
+                        n4_++,
+                        n5_++);
+    finished_ = true;
+  }, "");
+}
+
+// Tests a failed ASSERT_PRED_FORMAT5 where the
+// predicate-formatter is a functor on a user-defined type (Bool).
+TEST_F(ASSERT_PRED_FORMAT5Test, FunctorOnUserTypeFailure) {
+  expected_to_finish_ = false;
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT5(PredFormatFunctor5(),
+                        Bool(n1_++),
+                        Bool(n2_++),
+                        Bool(n3_++),
+                        Bool(n4_++),
+                        Bool(n5_++));
+    finished_ = true;
+  }, "");
+}
diff --git a/third_party/googletest/src/test/gtest_prod_test.cc b/third_party/googletest/src/test/gtest_prod_test.cc
new file mode 100644 (file)
index 0000000..060abce
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright 2006, 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: wan@google.com (Zhanyong Wan)
+//
+// Unit test for include/gtest/gtest_prod.h.
+
+#include "gtest/gtest.h"
+#include "test/production.h"
+
+// Tests that private members can be accessed from a TEST declared as
+// a friend of the class.
+TEST(PrivateCodeTest, CanAccessPrivateMembers) {
+  PrivateCode a;
+  EXPECT_EQ(0, a.x_);
+
+  a.set_x(1);
+  EXPECT_EQ(1, a.x_);
+}
+
+typedef testing::Test PrivateCodeFixtureTest;
+
+// Tests that private members can be accessed from a TEST_F declared
+// as a friend of the class.
+TEST_F(PrivateCodeFixtureTest, CanAccessPrivateMembers) {
+  PrivateCode a;
+  EXPECT_EQ(0, a.x_);
+
+  a.set_x(2);
+  EXPECT_EQ(2, a.x_);
+}
diff --git a/third_party/googletest/src/test/gtest_repeat_test.cc b/third_party/googletest/src/test/gtest_repeat_test.cc
new file mode 100644 (file)
index 0000000..5223dc0
--- /dev/null
@@ -0,0 +1,253 @@
+// Copyright 2008, 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: wan@google.com (Zhanyong Wan)
+
+// Tests the --gtest_repeat=number flag.
+
+#include <stdlib.h>
+#include <iostream>
+#include "gtest/gtest.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+
+GTEST_DECLARE_string_(death_test_style);
+GTEST_DECLARE_string_(filter);
+GTEST_DECLARE_int32_(repeat);
+
+}  // namespace testing
+
+using testing::GTEST_FLAG(death_test_style);
+using testing::GTEST_FLAG(filter);
+using testing::GTEST_FLAG(repeat);
+
+namespace {
+
+// We need this when we are testing Google Test itself and therefore
+// cannot use Google Test assertions.
+#define GTEST_CHECK_INT_EQ_(expected, actual) \
+  do {\
+    const int expected_val = (expected);\
+    const int actual_val = (actual);\
+    if (::testing::internal::IsTrue(expected_val != actual_val)) {\
+      ::std::cout << "Value of: " #actual "\n"\
+                  << "  Actual: " << actual_val << "\n"\
+                  << "Expected: " #expected "\n"\
+                  << "Which is: " << expected_val << "\n";\
+      ::testing::internal::posix::Abort();\
+    }\
+  } while(::testing::internal::AlwaysFalse())
+
+
+// Used for verifying that global environment set-up and tear-down are
+// inside the gtest_repeat loop.
+
+int g_environment_set_up_count = 0;
+int g_environment_tear_down_count = 0;
+
+class MyEnvironment : public testing::Environment {
+ public:
+  MyEnvironment() {}
+  virtual void SetUp() { g_environment_set_up_count++; }
+  virtual void TearDown() { g_environment_tear_down_count++; }
+};
+
+// A test that should fail.
+
+int g_should_fail_count = 0;
+
+TEST(FooTest, ShouldFail) {
+  g_should_fail_count++;
+  EXPECT_EQ(0, 1) << "Expected failure.";
+}
+
+// A test that should pass.
+
+int g_should_pass_count = 0;
+
+TEST(FooTest, ShouldPass) {
+  g_should_pass_count++;
+}
+
+// A test that contains a thread-safe death test and a fast death
+// test.  It should pass.
+
+int g_death_test_count = 0;
+
+TEST(BarDeathTest, ThreadSafeAndFast) {
+  g_death_test_count++;
+
+  GTEST_FLAG(death_test_style) = "threadsafe";
+  EXPECT_DEATH_IF_SUPPORTED(::testing::internal::posix::Abort(), "");
+
+  GTEST_FLAG(death_test_style) = "fast";
+  EXPECT_DEATH_IF_SUPPORTED(::testing::internal::posix::Abort(), "");
+}
+
+#if GTEST_HAS_PARAM_TEST
+int g_param_test_count = 0;
+
+const int kNumberOfParamTests = 10;
+
+class MyParamTest : public testing::TestWithParam<int> {};
+
+TEST_P(MyParamTest, ShouldPass) {
+  // TODO(vladl@google.com): Make parameter value checking robust
+  //                         WRT order of tests.
+  GTEST_CHECK_INT_EQ_(g_param_test_count % kNumberOfParamTests, GetParam());
+  g_param_test_count++;
+}
+INSTANTIATE_TEST_CASE_P(MyParamSequence,
+                        MyParamTest,
+                        testing::Range(0, kNumberOfParamTests));
+#endif  // GTEST_HAS_PARAM_TEST
+
+// Resets the count for each test.
+void ResetCounts() {
+  g_environment_set_up_count = 0;
+  g_environment_tear_down_count = 0;
+  g_should_fail_count = 0;
+  g_should_pass_count = 0;
+  g_death_test_count = 0;
+#if GTEST_HAS_PARAM_TEST
+  g_param_test_count = 0;
+#endif  // GTEST_HAS_PARAM_TEST
+}
+
+// Checks that the count for each test is expected.
+void CheckCounts(int expected) {
+  GTEST_CHECK_INT_EQ_(expected, g_environment_set_up_count);
+  GTEST_CHECK_INT_EQ_(expected, g_environment_tear_down_count);
+  GTEST_CHECK_INT_EQ_(expected, g_should_fail_count);
+  GTEST_CHECK_INT_EQ_(expected, g_should_pass_count);
+  GTEST_CHECK_INT_EQ_(expected, g_death_test_count);
+#if GTEST_HAS_PARAM_TEST
+  GTEST_CHECK_INT_EQ_(expected * kNumberOfParamTests, g_param_test_count);
+#endif  // GTEST_HAS_PARAM_TEST
+}
+
+// Tests the behavior of Google Test when --gtest_repeat is not specified.
+void TestRepeatUnspecified() {
+  ResetCounts();
+  GTEST_CHECK_INT_EQ_(1, RUN_ALL_TESTS());
+  CheckCounts(1);
+}
+
+// Tests the behavior of Google Test when --gtest_repeat has the given value.
+void TestRepeat(int repeat) {
+  GTEST_FLAG(repeat) = repeat;
+
+  ResetCounts();
+  GTEST_CHECK_INT_EQ_(repeat > 0 ? 1 : 0, RUN_ALL_TESTS());
+  CheckCounts(repeat);
+}
+
+// Tests using --gtest_repeat when --gtest_filter specifies an empty
+// set of tests.
+void TestRepeatWithEmptyFilter(int repeat) {
+  GTEST_FLAG(repeat) = repeat;
+  GTEST_FLAG(filter) = "None";
+
+  ResetCounts();
+  GTEST_CHECK_INT_EQ_(0, RUN_ALL_TESTS());
+  CheckCounts(0);
+}
+
+// Tests using --gtest_repeat when --gtest_filter specifies a set of
+// successful tests.
+void TestRepeatWithFilterForSuccessfulTests(int repeat) {
+  GTEST_FLAG(repeat) = repeat;
+  GTEST_FLAG(filter) = "*-*ShouldFail";
+
+  ResetCounts();
+  GTEST_CHECK_INT_EQ_(0, RUN_ALL_TESTS());
+  GTEST_CHECK_INT_EQ_(repeat, g_environment_set_up_count);
+  GTEST_CHECK_INT_EQ_(repeat, g_environment_tear_down_count);
+  GTEST_CHECK_INT_EQ_(0, g_should_fail_count);
+  GTEST_CHECK_INT_EQ_(repeat, g_should_pass_count);
+  GTEST_CHECK_INT_EQ_(repeat, g_death_test_count);
+#if GTEST_HAS_PARAM_TEST
+  GTEST_CHECK_INT_EQ_(repeat * kNumberOfParamTests, g_param_test_count);
+#endif  // GTEST_HAS_PARAM_TEST
+}
+
+// Tests using --gtest_repeat when --gtest_filter specifies a set of
+// failed tests.
+void TestRepeatWithFilterForFailedTests(int repeat) {
+  GTEST_FLAG(repeat) = repeat;
+  GTEST_FLAG(filter) = "*ShouldFail";
+
+  ResetCounts();
+  GTEST_CHECK_INT_EQ_(1, RUN_ALL_TESTS());
+  GTEST_CHECK_INT_EQ_(repeat, g_environment_set_up_count);
+  GTEST_CHECK_INT_EQ_(repeat, g_environment_tear_down_count);
+  GTEST_CHECK_INT_EQ_(repeat, g_should_fail_count);
+  GTEST_CHECK_INT_EQ_(0, g_should_pass_count);
+  GTEST_CHECK_INT_EQ_(0, g_death_test_count);
+#if GTEST_HAS_PARAM_TEST
+  GTEST_CHECK_INT_EQ_(0, g_param_test_count);
+#endif  // GTEST_HAS_PARAM_TEST
+}
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  testing::InitGoogleTest(&argc, argv);
+  testing::AddGlobalTestEnvironment(new MyEnvironment);
+
+  TestRepeatUnspecified();
+  TestRepeat(0);
+  TestRepeat(1);
+  TestRepeat(5);
+
+  TestRepeatWithEmptyFilter(2);
+  TestRepeatWithEmptyFilter(3);
+
+  TestRepeatWithFilterForSuccessfulTests(3);
+
+  TestRepeatWithFilterForFailedTests(4);
+
+  // It would be nice to verify that the tests indeed loop forever
+  // when GTEST_FLAG(repeat) is negative, but this test will be quite
+  // complicated to write.  Since this flag is for interactive
+  // debugging only and doesn't affect the normal test result, such a
+  // test would be an overkill.
+
+  printf("PASS\n");
+  return 0;
+}
diff --git a/third_party/googletest/src/test/gtest_shuffle_test.py b/third_party/googletest/src/test/gtest_shuffle_test.py
new file mode 100755 (executable)
index 0000000..30d0303
--- /dev/null
@@ -0,0 +1,325 @@
+#!/usr/bin/env python
+#
+# Copyright 2009 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.
+
+"""Verifies that test shuffling works."""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import gtest_test_utils
+
+# Command to run the gtest_shuffle_test_ program.
+COMMAND = gtest_test_utils.GetTestExecutablePath('gtest_shuffle_test_')
+
+# The environment variables for test sharding.
+TOTAL_SHARDS_ENV_VAR = 'GTEST_TOTAL_SHARDS'
+SHARD_INDEX_ENV_VAR = 'GTEST_SHARD_INDEX'
+
+TEST_FILTER = 'A*.A:A*.B:C*'
+
+ALL_TESTS = []
+ACTIVE_TESTS = []
+FILTERED_TESTS = []
+SHARDED_TESTS = []
+
+SHUFFLED_ALL_TESTS = []
+SHUFFLED_ACTIVE_TESTS = []
+SHUFFLED_FILTERED_TESTS = []
+SHUFFLED_SHARDED_TESTS = []
+
+
+def AlsoRunDisabledTestsFlag():
+  return '--gtest_also_run_disabled_tests'
+
+
+def FilterFlag(test_filter):
+  return '--gtest_filter=%s' % (test_filter,)
+
+
+def RepeatFlag(n):
+  return '--gtest_repeat=%s' % (n,)
+
+
+def ShuffleFlag():
+  return '--gtest_shuffle'
+
+
+def RandomSeedFlag(n):
+  return '--gtest_random_seed=%s' % (n,)
+
+
+def RunAndReturnOutput(extra_env, args):
+  """Runs the test program and returns its output."""
+
+  environ_copy = os.environ.copy()
+  environ_copy.update(extra_env)
+
+  return gtest_test_utils.Subprocess([COMMAND] + args, env=environ_copy).output
+
+
+def GetTestsForAllIterations(extra_env, args):
+  """Runs the test program and returns a list of test lists.
+
+  Args:
+    extra_env: a map from environment variables to their values
+    args: command line flags to pass to gtest_shuffle_test_
+
+  Returns:
+    A list where the i-th element is the list of tests run in the i-th
+    test iteration.
+  """
+
+  test_iterations = []
+  for line in RunAndReturnOutput(extra_env, args).split('\n'):
+    if line.startswith('----'):
+      tests = []
+      test_iterations.append(tests)
+    elif line.strip():
+      tests.append(line.strip())  # 'TestCaseName.TestName'
+
+  return test_iterations
+
+
+def GetTestCases(tests):
+  """Returns a list of test cases in the given full test names.
+
+  Args:
+    tests: a list of full test names
+
+  Returns:
+    A list of test cases from 'tests', in their original order.
+    Consecutive duplicates are removed.
+  """
+
+  test_cases = []
+  for test in tests:
+    test_case = test.split('.')[0]
+    if not test_case in test_cases:
+      test_cases.append(test_case)
+
+  return test_cases
+
+
+def CalculateTestLists():
+  """Calculates the list of tests run under different flags."""
+
+  if not ALL_TESTS:
+    ALL_TESTS.extend(
+        GetTestsForAllIterations({}, [AlsoRunDisabledTestsFlag()])[0])
+
+  if not ACTIVE_TESTS:
+    ACTIVE_TESTS.extend(GetTestsForAllIterations({}, [])[0])
+
+  if not FILTERED_TESTS:
+    FILTERED_TESTS.extend(
+        GetTestsForAllIterations({}, [FilterFlag(TEST_FILTER)])[0])
+
+  if not SHARDED_TESTS:
+    SHARDED_TESTS.extend(
+        GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
+                                  SHARD_INDEX_ENV_VAR: '1'},
+                                 [])[0])
+
+  if not SHUFFLED_ALL_TESTS:
+    SHUFFLED_ALL_TESTS.extend(GetTestsForAllIterations(
+        {}, [AlsoRunDisabledTestsFlag(), ShuffleFlag(), RandomSeedFlag(1)])[0])
+
+  if not SHUFFLED_ACTIVE_TESTS:
+    SHUFFLED_ACTIVE_TESTS.extend(GetTestsForAllIterations(
+        {}, [ShuffleFlag(), RandomSeedFlag(1)])[0])
+
+  if not SHUFFLED_FILTERED_TESTS:
+    SHUFFLED_FILTERED_TESTS.extend(GetTestsForAllIterations(
+        {}, [ShuffleFlag(), RandomSeedFlag(1), FilterFlag(TEST_FILTER)])[0])
+
+  if not SHUFFLED_SHARDED_TESTS:
+    SHUFFLED_SHARDED_TESTS.extend(
+        GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
+                                  SHARD_INDEX_ENV_VAR: '1'},
+                                 [ShuffleFlag(), RandomSeedFlag(1)])[0])
+
+
+class GTestShuffleUnitTest(gtest_test_utils.TestCase):
+  """Tests test shuffling."""
+
+  def setUp(self):
+    CalculateTestLists()
+
+  def testShufflePreservesNumberOfTests(self):
+    self.assertEqual(len(ALL_TESTS), len(SHUFFLED_ALL_TESTS))
+    self.assertEqual(len(ACTIVE_TESTS), len(SHUFFLED_ACTIVE_TESTS))
+    self.assertEqual(len(FILTERED_TESTS), len(SHUFFLED_FILTERED_TESTS))
+    self.assertEqual(len(SHARDED_TESTS), len(SHUFFLED_SHARDED_TESTS))
+
+  def testShuffleChangesTestOrder(self):
+    self.assert_(SHUFFLED_ALL_TESTS != ALL_TESTS, SHUFFLED_ALL_TESTS)
+    self.assert_(SHUFFLED_ACTIVE_TESTS != ACTIVE_TESTS, SHUFFLED_ACTIVE_TESTS)
+    self.assert_(SHUFFLED_FILTERED_TESTS != FILTERED_TESTS,
+                 SHUFFLED_FILTERED_TESTS)
+    self.assert_(SHUFFLED_SHARDED_TESTS != SHARDED_TESTS,
+                 SHUFFLED_SHARDED_TESTS)
+
+  def testShuffleChangesTestCaseOrder(self):
+    self.assert_(GetTestCases(SHUFFLED_ALL_TESTS) != GetTestCases(ALL_TESTS),
+                 GetTestCases(SHUFFLED_ALL_TESTS))
+    self.assert_(
+        GetTestCases(SHUFFLED_ACTIVE_TESTS) != GetTestCases(ACTIVE_TESTS),
+        GetTestCases(SHUFFLED_ACTIVE_TESTS))
+    self.assert_(
+        GetTestCases(SHUFFLED_FILTERED_TESTS) != GetTestCases(FILTERED_TESTS),
+        GetTestCases(SHUFFLED_FILTERED_TESTS))
+    self.assert_(
+        GetTestCases(SHUFFLED_SHARDED_TESTS) != GetTestCases(SHARDED_TESTS),
+        GetTestCases(SHUFFLED_SHARDED_TESTS))
+
+  def testShuffleDoesNotRepeatTest(self):
+    for test in SHUFFLED_ALL_TESTS:
+      self.assertEqual(1, SHUFFLED_ALL_TESTS.count(test),
+                       '%s appears more than once' % (test,))
+    for test in SHUFFLED_ACTIVE_TESTS:
+      self.assertEqual(1, SHUFFLED_ACTIVE_TESTS.count(test),
+                       '%s appears more than once' % (test,))
+    for test in SHUFFLED_FILTERED_TESTS:
+      self.assertEqual(1, SHUFFLED_FILTERED_TESTS.count(test),
+                       '%s appears more than once' % (test,))
+    for test in SHUFFLED_SHARDED_TESTS:
+      self.assertEqual(1, SHUFFLED_SHARDED_TESTS.count(test),
+                       '%s appears more than once' % (test,))
+
+  def testShuffleDoesNotCreateNewTest(self):
+    for test in SHUFFLED_ALL_TESTS:
+      self.assert_(test in ALL_TESTS, '%s is an invalid test' % (test,))
+    for test in SHUFFLED_ACTIVE_TESTS:
+      self.assert_(test in ACTIVE_TESTS, '%s is an invalid test' % (test,))
+    for test in SHUFFLED_FILTERED_TESTS:
+      self.assert_(test in FILTERED_TESTS, '%s is an invalid test' % (test,))
+    for test in SHUFFLED_SHARDED_TESTS:
+      self.assert_(test in SHARDED_TESTS, '%s is an invalid test' % (test,))
+
+  def testShuffleIncludesAllTests(self):
+    for test in ALL_TESTS:
+      self.assert_(test in SHUFFLED_ALL_TESTS, '%s is missing' % (test,))
+    for test in ACTIVE_TESTS:
+      self.assert_(test in SHUFFLED_ACTIVE_TESTS, '%s is missing' % (test,))
+    for test in FILTERED_TESTS:
+      self.assert_(test in SHUFFLED_FILTERED_TESTS, '%s is missing' % (test,))
+    for test in SHARDED_TESTS:
+      self.assert_(test in SHUFFLED_SHARDED_TESTS, '%s is missing' % (test,))
+
+  def testShuffleLeavesDeathTestsAtFront(self):
+    non_death_test_found = False
+    for test in SHUFFLED_ACTIVE_TESTS:
+      if 'DeathTest.' in test:
+        self.assert_(not non_death_test_found,
+                     '%s appears after a non-death test' % (test,))
+      else:
+        non_death_test_found = True
+
+  def _VerifyTestCasesDoNotInterleave(self, tests):
+    test_cases = []
+    for test in tests:
+      [test_case, _] = test.split('.')
+      if test_cases and test_cases[-1] != test_case:
+        test_cases.append(test_case)
+        self.assertEqual(1, test_cases.count(test_case),
+                         'Test case %s is not grouped together in %s' %
+                         (test_case, tests))
+
+  def testShuffleDoesNotInterleaveTestCases(self):
+    self._VerifyTestCasesDoNotInterleave(SHUFFLED_ALL_TESTS)
+    self._VerifyTestCasesDoNotInterleave(SHUFFLED_ACTIVE_TESTS)
+    self._VerifyTestCasesDoNotInterleave(SHUFFLED_FILTERED_TESTS)
+    self._VerifyTestCasesDoNotInterleave(SHUFFLED_SHARDED_TESTS)
+
+  def testShuffleRestoresOrderAfterEachIteration(self):
+    # Get the test lists in all 3 iterations, using random seed 1, 2,
+    # and 3 respectively.  Google Test picks a different seed in each
+    # iteration, and this test depends on the current implementation
+    # picking successive numbers.  This dependency is not ideal, but
+    # makes the test much easier to write.
+    [tests_in_iteration1, tests_in_iteration2, tests_in_iteration3] = (
+        GetTestsForAllIterations(
+            {}, [ShuffleFlag(), RandomSeedFlag(1), RepeatFlag(3)]))
+
+    # Make sure running the tests with random seed 1 gets the same
+    # order as in iteration 1 above.
+    [tests_with_seed1] = GetTestsForAllIterations(
+        {}, [ShuffleFlag(), RandomSeedFlag(1)])
+    self.assertEqual(tests_in_iteration1, tests_with_seed1)
+
+    # Make sure running the tests with random seed 2 gets the same
+    # order as in iteration 2 above.  Success means that Google Test
+    # correctly restores the test order before re-shuffling at the
+    # beginning of iteration 2.
+    [tests_with_seed2] = GetTestsForAllIterations(
+        {}, [ShuffleFlag(), RandomSeedFlag(2)])
+    self.assertEqual(tests_in_iteration2, tests_with_seed2)
+
+    # Make sure running the tests with random seed 3 gets the same
+    # order as in iteration 3 above.  Success means that Google Test
+    # correctly restores the test order before re-shuffling at the
+    # beginning of iteration 3.
+    [tests_with_seed3] = GetTestsForAllIterations(
+        {}, [ShuffleFlag(), RandomSeedFlag(3)])
+    self.assertEqual(tests_in_iteration3, tests_with_seed3)
+
+  def testShuffleGeneratesNewOrderInEachIteration(self):
+    [tests_in_iteration1, tests_in_iteration2, tests_in_iteration3] = (
+        GetTestsForAllIterations(
+            {}, [ShuffleFlag(), RandomSeedFlag(1), RepeatFlag(3)]))
+
+    self.assert_(tests_in_iteration1 != tests_in_iteration2,
+                 tests_in_iteration1)
+    self.assert_(tests_in_iteration1 != tests_in_iteration3,
+                 tests_in_iteration1)
+    self.assert_(tests_in_iteration2 != tests_in_iteration3,
+                 tests_in_iteration2)
+
+  def testShuffleShardedTestsPreservesPartition(self):
+    # If we run M tests on N shards, the same M tests should be run in
+    # total, regardless of the random seeds used by the shards.
+    [tests1] = GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
+                                         SHARD_INDEX_ENV_VAR: '0'},
+                                        [ShuffleFlag(), RandomSeedFlag(1)])
+    [tests2] = GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
+                                         SHARD_INDEX_ENV_VAR: '1'},
+                                        [ShuffleFlag(), RandomSeedFlag(20)])
+    [tests3] = GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
+                                         SHARD_INDEX_ENV_VAR: '2'},
+                                        [ShuffleFlag(), RandomSeedFlag(25)])
+    sorted_sharded_tests = tests1 + tests2 + tests3
+    sorted_sharded_tests.sort()
+    sorted_active_tests = []
+    sorted_active_tests.extend(ACTIVE_TESTS)
+    sorted_active_tests.sort()
+    self.assertEqual(sorted_active_tests, sorted_sharded_tests)
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/src/test/gtest_shuffle_test_.cc b/third_party/googletest/src/test/gtest_shuffle_test_.cc
new file mode 100644 (file)
index 0000000..0752789
--- /dev/null
@@ -0,0 +1,104 @@
+// Copyright 2009, 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: wan@google.com (Zhanyong Wan)
+
+// Verifies that test shuffling works.
+
+#include "gtest/gtest.h"
+
+namespace {
+
+using ::testing::EmptyTestEventListener;
+using ::testing::InitGoogleTest;
+using ::testing::Message;
+using ::testing::Test;
+using ::testing::TestEventListeners;
+using ::testing::TestInfo;
+using ::testing::UnitTest;
+using ::testing::internal::String;
+using ::testing::internal::scoped_ptr;
+
+// The test methods are empty, as the sole purpose of this program is
+// to print the test names before/after shuffling.
+
+class A : public Test {};
+TEST_F(A, A) {}
+TEST_F(A, B) {}
+
+TEST(ADeathTest, A) {}
+TEST(ADeathTest, B) {}
+TEST(ADeathTest, C) {}
+
+TEST(B, A) {}
+TEST(B, B) {}
+TEST(B, C) {}
+TEST(B, DISABLED_D) {}
+TEST(B, DISABLED_E) {}
+
+TEST(BDeathTest, A) {}
+TEST(BDeathTest, B) {}
+
+TEST(C, A) {}
+TEST(C, B) {}
+TEST(C, C) {}
+TEST(C, DISABLED_D) {}
+
+TEST(CDeathTest, A) {}
+
+TEST(DISABLED_D, A) {}
+TEST(DISABLED_D, DISABLED_B) {}
+
+// This printer prints the full test names only, starting each test
+// iteration with a "----" marker.
+class TestNamePrinter : public EmptyTestEventListener {
+ public:
+  virtual void OnTestIterationStart(const UnitTest& /* unit_test */,
+                                    int /* iteration */) {
+    printf("----\n");
+  }
+
+  virtual void OnTestStart(const TestInfo& test_info) {
+    printf("%s.%s\n", test_info.test_case_name(), test_info.name());
+  }
+};
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  InitGoogleTest(&argc, argv);
+
+  // Replaces the default printer with TestNamePrinter, which prints
+  // the test name only.
+  TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
+  delete listeners.Release(listeners.default_result_printer());
+  listeners.Append(new TestNamePrinter);
+
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/src/test/gtest_sole_header_test.cc b/third_party/googletest/src/test/gtest_sole_header_test.cc
new file mode 100644 (file)
index 0000000..ccd091a
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright 2008, 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: mheule@google.com (Markus Heule)
+//
+// This test verifies that it's possible to use Google Test by including
+// the gtest.h header file alone.
+
+#include "gtest/gtest.h"
+
+namespace {
+
+void Subroutine() {
+  EXPECT_EQ(42, 42);
+}
+
+TEST(NoFatalFailureTest, ExpectNoFatalFailure) {
+  EXPECT_NO_FATAL_FAILURE(;);
+  EXPECT_NO_FATAL_FAILURE(SUCCEED());
+  EXPECT_NO_FATAL_FAILURE(Subroutine());
+  EXPECT_NO_FATAL_FAILURE({ SUCCEED(); });
+}
+
+TEST(NoFatalFailureTest, AssertNoFatalFailure) {
+  ASSERT_NO_FATAL_FAILURE(;);
+  ASSERT_NO_FATAL_FAILURE(SUCCEED());
+  ASSERT_NO_FATAL_FAILURE(Subroutine());
+  ASSERT_NO_FATAL_FAILURE({ SUCCEED(); });
+}
+
+}  // namespace
diff --git a/third_party/googletest/src/test/gtest_stress_test.cc b/third_party/googletest/src/test/gtest_stress_test.cc
new file mode 100644 (file)
index 0000000..4e7d9bf
--- /dev/null
@@ -0,0 +1,257 @@
+// Copyright 2007, 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: wan@google.com (Zhanyong Wan)
+
+// Tests that SCOPED_TRACE() and various Google Test assertions can be
+// used in a large number of threads concurrently.
+
+#include "gtest/gtest.h"
+
+#include <iostream>
+#include <vector>
+
+// We must define this macro in order to #include
+// gtest-internal-inl.h.  This is how Google Test prevents a user from
+// accidentally depending on its internal implementation.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+#if GTEST_IS_THREADSAFE
+
+namespace testing {
+namespace {
+
+using internal::Notification;
+using internal::String;
+using internal::TestPropertyKeyIs;
+using internal::ThreadWithParam;
+using internal::scoped_ptr;
+
+// In order to run tests in this file, for platforms where Google Test is
+// thread safe, implement ThreadWithParam. See the description of its API
+// in gtest-port.h, where it is defined for already supported platforms.
+
+// How many threads to create?
+const int kThreadCount = 50;
+
+String IdToKey(int id, const char* suffix) {
+  Message key;
+  key << "key_" << id << "_" << suffix;
+  return key.GetString();
+}
+
+String IdToString(int id) {
+  Message id_message;
+  id_message << id;
+  return id_message.GetString();
+}
+
+void ExpectKeyAndValueWereRecordedForId(
+    const std::vector<TestProperty>& properties,
+    int id, const char* suffix) {
+  TestPropertyKeyIs matches_key(IdToKey(id, suffix).c_str());
+  const std::vector<TestProperty>::const_iterator property =
+      std::find_if(properties.begin(), properties.end(), matches_key);
+  ASSERT_TRUE(property != properties.end())
+      << "expecting " << suffix << " value for id " << id;
+  EXPECT_STREQ(IdToString(id).c_str(), property->value());
+}
+
+// Calls a large number of Google Test assertions, where exactly one of them
+// will fail.
+void ManyAsserts(int id) {
+  GTEST_LOG_(INFO) << "Thread #" << id << " running...";
+
+  SCOPED_TRACE(Message() << "Thread #" << id);
+
+  for (int i = 0; i < kThreadCount; i++) {
+    SCOPED_TRACE(Message() << "Iteration #" << i);
+
+    // A bunch of assertions that should succeed.
+    EXPECT_TRUE(true);
+    ASSERT_FALSE(false) << "This shouldn't fail.";
+    EXPECT_STREQ("a", "a");
+    ASSERT_LE(5, 6);
+    EXPECT_EQ(i, i) << "This shouldn't fail.";
+
+    // RecordProperty() should interact safely with other threads as well.
+    // The shared_key forces property updates.
+    Test::RecordProperty(IdToKey(id, "string").c_str(), IdToString(id).c_str());
+    Test::RecordProperty(IdToKey(id, "int").c_str(), id);
+    Test::RecordProperty("shared_key", IdToString(id).c_str());
+
+    // This assertion should fail kThreadCount times per thread.  It
+    // is for testing whether Google Test can handle failed assertions in a
+    // multi-threaded context.
+    EXPECT_LT(i, 0) << "This should always fail.";
+  }
+}
+
+void CheckTestFailureCount(int expected_failures) {
+  const TestInfo* const info = UnitTest::GetInstance()->current_test_info();
+  const TestResult* const result = info->result();
+  GTEST_CHECK_(expected_failures == result->total_part_count())
+      << "Logged " << result->total_part_count() << " failures "
+      << " vs. " << expected_failures << " expected";
+}
+
+// Tests using SCOPED_TRACE() and Google Test assertions in many threads
+// concurrently.
+TEST(StressTest, CanUseScopedTraceAndAssertionsInManyThreads) {
+  {
+    scoped_ptr<ThreadWithParam<int> > threads[kThreadCount];
+    Notification threads_can_start;
+    for (int i = 0; i != kThreadCount; i++)
+      threads[i].reset(new ThreadWithParam<int>(&ManyAsserts,
+                                                i,
+                                                &threads_can_start));
+
+    threads_can_start.Notify();
+
+    // Blocks until all the threads are done.
+    for (int i = 0; i != kThreadCount; i++)
+      threads[i]->Join();
+  }
+
+  // Ensures that kThreadCount*kThreadCount failures have been reported.
+  const TestInfo* const info = UnitTest::GetInstance()->current_test_info();
+  const TestResult* const result = info->result();
+
+  std::vector<TestProperty> properties;
+  // We have no access to the TestResult's list of properties but we can
+  // copy them one by one.
+  for (int i = 0; i < result->test_property_count(); ++i)
+    properties.push_back(result->GetTestProperty(i));
+
+  EXPECT_EQ(kThreadCount * 2 + 1, result->test_property_count())
+      << "String and int values recorded on each thread, "
+      << "as well as one shared_key";
+  for (int i = 0; i < kThreadCount; ++i) {
+    ExpectKeyAndValueWereRecordedForId(properties, i, "string");
+    ExpectKeyAndValueWereRecordedForId(properties, i, "int");
+  }
+  CheckTestFailureCount(kThreadCount*kThreadCount);
+}
+
+void FailingThread(bool is_fatal) {
+  if (is_fatal)
+    FAIL() << "Fatal failure in some other thread. "
+           << "(This failure is expected.)";
+  else
+    ADD_FAILURE() << "Non-fatal failure in some other thread. "
+                  << "(This failure is expected.)";
+}
+
+void GenerateFatalFailureInAnotherThread(bool is_fatal) {
+  ThreadWithParam<bool> thread(&FailingThread, is_fatal, NULL);
+  thread.Join();
+}
+
+TEST(NoFatalFailureTest, ExpectNoFatalFailureIgnoresFailuresInOtherThreads) {
+  EXPECT_NO_FATAL_FAILURE(GenerateFatalFailureInAnotherThread(true));
+  // We should only have one failure (the one from
+  // GenerateFatalFailureInAnotherThread()), since the EXPECT_NO_FATAL_FAILURE
+  // should succeed.
+  CheckTestFailureCount(1);
+}
+
+void AssertNoFatalFailureIgnoresFailuresInOtherThreads() {
+  ASSERT_NO_FATAL_FAILURE(GenerateFatalFailureInAnotherThread(true));
+}
+TEST(NoFatalFailureTest, AssertNoFatalFailureIgnoresFailuresInOtherThreads) {
+  // Using a subroutine, to make sure, that the test continues.
+  AssertNoFatalFailureIgnoresFailuresInOtherThreads();
+  // We should only have one failure (the one from
+  // GenerateFatalFailureInAnotherThread()), since the EXPECT_NO_FATAL_FAILURE
+  // should succeed.
+  CheckTestFailureCount(1);
+}
+
+TEST(FatalFailureTest, ExpectFatalFailureIgnoresFailuresInOtherThreads) {
+  // This statement should fail, since the current thread doesn't generate a
+  // fatal failure, only another one does.
+  EXPECT_FATAL_FAILURE(GenerateFatalFailureInAnotherThread(true), "expected");
+  CheckTestFailureCount(2);
+}
+
+TEST(FatalFailureOnAllThreadsTest, ExpectFatalFailureOnAllThreads) {
+  // This statement should succeed, because failures in all threads are
+  // considered.
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(
+      GenerateFatalFailureInAnotherThread(true), "expected");
+  CheckTestFailureCount(0);
+  // We need to add a failure, because main() checks that there are failures.
+  // But when only this test is run, we shouldn't have any failures.
+  ADD_FAILURE() << "This is an expected non-fatal failure.";
+}
+
+TEST(NonFatalFailureTest, ExpectNonFatalFailureIgnoresFailuresInOtherThreads) {
+  // This statement should fail, since the current thread doesn't generate a
+  // fatal failure, only another one does.
+  EXPECT_NONFATAL_FAILURE(GenerateFatalFailureInAnotherThread(false),
+                          "expected");
+  CheckTestFailureCount(2);
+}
+
+TEST(NonFatalFailureOnAllThreadsTest, ExpectNonFatalFailureOnAllThreads) {
+  // This statement should succeed, because failures in all threads are
+  // considered.
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(
+      GenerateFatalFailureInAnotherThread(false), "expected");
+  CheckTestFailureCount(0);
+  // We need to add a failure, because main() checks that there are failures,
+  // But when only this test is run, we shouldn't have any failures.
+  ADD_FAILURE() << "This is an expected non-fatal failure.";
+}
+
+}  // namespace
+}  // namespace testing
+
+int main(int argc, char **argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  const int result = RUN_ALL_TESTS();  // Expected to fail.
+  GTEST_CHECK_(result == 1) << "RUN_ALL_TESTS() did not fail as expected";
+
+  printf("\nPASS\n");
+  return 0;
+}
+
+#else
+TEST(StressTest,
+     DISABLED_ThreadSafetyTestsAreSkippedWhenGoogleTestIsNotThreadSafe) {
+}
+
+int main(int argc, char **argv) {
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+#endif  // GTEST_IS_THREADSAFE
diff --git a/third_party/googletest/src/test/gtest_test_utils.py b/third_party/googletest/src/test/gtest_test_utils.py
new file mode 100755 (executable)
index 0000000..4e897bd
--- /dev/null
@@ -0,0 +1,305 @@
+#!/usr/bin/env python
+#
+# Copyright 2006, 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.
+
+"""Unit test utilities for Google C++ Testing Framework."""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import atexit
+import os
+import shutil
+import sys
+import tempfile
+import unittest
+_test_module = unittest
+
+# Suppresses the 'Import not at the top of the file' lint complaint.
+# pylint: disable-msg=C6204
+try:
+  import subprocess
+  _SUBPROCESS_MODULE_AVAILABLE = True
+except:
+  import popen2
+  _SUBPROCESS_MODULE_AVAILABLE = False
+# pylint: enable-msg=C6204
+
+GTEST_OUTPUT_VAR_NAME = 'GTEST_OUTPUT'
+
+IS_WINDOWS = os.name == 'nt'
+IS_CYGWIN = os.name == 'posix' and 'CYGWIN' in os.uname()[0]
+
+# Here we expose a class from a particular module, depending on the
+# environment. The comment suppresses the 'Invalid variable name' lint
+# complaint.
+TestCase = _test_module.TestCase  # pylint: disable-msg=C6409
+
+# Initially maps a flag to its default value. After
+# _ParseAndStripGTestFlags() is called, maps a flag to its actual value.
+_flag_map = {'source_dir': os.path.dirname(sys.argv[0]),
+             'build_dir': os.path.dirname(sys.argv[0])}
+_gtest_flags_are_parsed = False
+
+
+def _ParseAndStripGTestFlags(argv):
+  """Parses and strips Google Test flags from argv.  This is idempotent."""
+
+  # Suppresses the lint complaint about a global variable since we need it
+  # here to maintain module-wide state.
+  global _gtest_flags_are_parsed  # pylint: disable-msg=W0603
+  if _gtest_flags_are_parsed:
+    return
+
+  _gtest_flags_are_parsed = True
+  for flag in _flag_map:
+    # The environment variable overrides the default value.
+    if flag.upper() in os.environ:
+      _flag_map[flag] = os.environ[flag.upper()]
+
+    # The command line flag overrides the environment variable.
+    i = 1  # Skips the program name.
+    while i < len(argv):
+      prefix = '--' + flag + '='
+      if argv[i].startswith(prefix):
+        _flag_map[flag] = argv[i][len(prefix):]
+        del argv[i]
+        break
+      else:
+        # We don't increment i in case we just found a --gtest_* flag
+        # and removed it from argv.
+        i += 1
+
+
+def GetFlag(flag):
+  """Returns the value of the given flag."""
+
+  # In case GetFlag() is called before Main(), we always call
+  # _ParseAndStripGTestFlags() here to make sure the --gtest_* flags
+  # are parsed.
+  _ParseAndStripGTestFlags(sys.argv)
+
+  return _flag_map[flag]
+
+
+def GetSourceDir():
+  """Returns the absolute path of the directory where the .py files are."""
+
+  return os.path.abspath(GetFlag('source_dir'))
+
+
+def GetBuildDir():
+  """Returns the absolute path of the directory where the test binaries are."""
+
+  return os.path.abspath(GetFlag('build_dir'))
+
+
+_temp_dir = None
+
+def _RemoveTempDir():
+  if _temp_dir:
+    shutil.rmtree(_temp_dir, ignore_errors=True)
+
+atexit.register(_RemoveTempDir)
+
+
+def GetTempDir():
+  """Returns a directory for temporary files."""
+
+  global _temp_dir
+  if not _temp_dir:
+    _temp_dir = tempfile.mkdtemp()
+  return _temp_dir
+
+
+def GetTestExecutablePath(executable_name, build_dir=None):
+  """Returns the absolute path of the test binary given its name.
+
+  The function will print a message and abort the program if the resulting file
+  doesn't exist.
+
+  Args:
+    executable_name: name of the test binary that the test script runs.
+    build_dir:       directory where to look for executables, by default
+                     the result of GetBuildDir().
+
+  Returns:
+    The absolute path of the test binary.
+  """
+
+  path = os.path.abspath(os.path.join(build_dir or GetBuildDir(),
+                                      executable_name))
+  if (IS_WINDOWS or IS_CYGWIN) and not path.endswith('.exe'):
+    path += '.exe'
+
+  if not os.path.exists(path):
+    message = (
+        'Unable to find the test binary. Please make sure to provide path\n'
+        'to the binary via the --build_dir flag or the BUILD_DIR\n'
+        'environment variable.')
+    print >> sys.stderr, message
+    sys.exit(1)
+
+  return path
+
+
+def GetExitStatus(exit_code):
+  """Returns the argument to exit(), or -1 if exit() wasn't called.
+
+  Args:
+    exit_code: the result value of os.system(command).
+  """
+
+  if os.name == 'nt':
+    # On Windows, os.WEXITSTATUS() doesn't work and os.system() returns
+    # the argument to exit() directly.
+    return exit_code
+  else:
+    # On Unix, os.WEXITSTATUS() must be used to extract the exit status
+    # from the result of os.system().
+    if os.WIFEXITED(exit_code):
+      return os.WEXITSTATUS(exit_code)
+    else:
+      return -1
+
+
+class Subprocess:
+  def __init__(self, command, working_dir=None, capture_stderr=True, env=None):
+    """Changes into a specified directory, if provided, and executes a command.
+
+    Restores the old directory afterwards.
+
+    Args:
+      command:        The command to run, in the form of sys.argv.
+      working_dir:    The directory to change into.
+      capture_stderr: Determines whether to capture stderr in the output member
+                      or to discard it.
+      env:            Dictionary with environment to pass to the subprocess.
+
+    Returns:
+      An object that represents outcome of the executed process. It has the
+      following attributes:
+        terminated_by_signal   True iff the child process has been terminated
+                               by a signal.
+        signal                 Sygnal that terminated the child process.
+        exited                 True iff the child process exited normally.
+        exit_code              The code with which the child process exited.
+        output                 Child process's stdout and stderr output
+                               combined in a string.
+    """
+
+    # The subprocess module is the preferrable way of running programs
+    # since it is available and behaves consistently on all platforms,
+    # including Windows. But it is only available starting in python 2.4.
+    # In earlier python versions, we revert to the popen2 module, which is
+    # available in python 2.0 and later but doesn't provide required
+    # functionality (Popen4) under Windows. This allows us to support Mac
+    # OS X 10.4 Tiger, which has python 2.3 installed.
+    if _SUBPROCESS_MODULE_AVAILABLE:
+      if capture_stderr:
+        stderr = subprocess.STDOUT
+      else:
+        stderr = subprocess.PIPE
+
+      p = subprocess.Popen(command,
+                           stdout=subprocess.PIPE, stderr=stderr,
+                           cwd=working_dir, universal_newlines=True, env=env)
+      # communicate returns a tuple with the file obect for the child's
+      # output.
+      self.output = p.communicate()[0]
+      self._return_code = p.returncode
+    else:
+      old_dir = os.getcwd()
+
+      def _ReplaceEnvDict(dest, src):
+        # Changes made by os.environ.clear are not inheritable by child
+        # processes until Python 2.6. To produce inheritable changes we have
+        # to delete environment items with the del statement.
+        for key in dest:
+          del dest[key]
+        dest.update(src)
+
+      # When 'env' is not None, backup the environment variables and replace
+      # them with the passed 'env'. When 'env' is None, we simply use the
+      # current 'os.environ' for compatibility with the subprocess.Popen
+      # semantics used above.
+      if env is not None:
+        old_environ = os.environ.copy()
+        _ReplaceEnvDict(os.environ, env)
+
+      try:
+        if working_dir is not None:
+          os.chdir(working_dir)
+        if capture_stderr:
+          p = popen2.Popen4(command)
+        else:
+          p = popen2.Popen3(command)
+        p.tochild.close()
+        self.output = p.fromchild.read()
+        ret_code = p.wait()
+      finally:
+        os.chdir(old_dir)
+
+        # Restore the old environment variables
+        # if they were replaced.
+        if env is not None:
+          _ReplaceEnvDict(os.environ, old_environ)
+
+      # Converts ret_code to match the semantics of
+      # subprocess.Popen.returncode.
+      if os.WIFSIGNALED(ret_code):
+        self._return_code = -os.WTERMSIG(ret_code)
+      else:  # os.WIFEXITED(ret_code) should return True here.
+        self._return_code = os.WEXITSTATUS(ret_code)
+
+    if self._return_code < 0:
+      self.terminated_by_signal = True
+      self.exited = False
+      self.signal = -self._return_code
+    else:
+      self.terminated_by_signal = False
+      self.exited = True
+      self.exit_code = self._return_code
+
+
+def Main():
+  """Runs the unit test."""
+
+  # We must call _ParseAndStripGTestFlags() before calling
+  # unittest.main().  Otherwise the latter will be confused by the
+  # --gtest_* flags.
+  _ParseAndStripGTestFlags(sys.argv)
+  # The tested binaries should not be writing XML output files unless the
+  # script explicitly instructs them to.
+  # TODO(vladl@google.com): Move this into Subprocess when we implement
+  # passing environment into it as a parameter.
+  if GTEST_OUTPUT_VAR_NAME in os.environ:
+    del os.environ[GTEST_OUTPUT_VAR_NAME]
+
+  _test_module.main()
diff --git a/third_party/googletest/src/test/gtest_throw_on_failure_ex_test.cc b/third_party/googletest/src/test/gtest_throw_on_failure_ex_test.cc
new file mode 100644 (file)
index 0000000..8d46c76
--- /dev/null
@@ -0,0 +1,92 @@
+// Copyright 2009, 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: wan@google.com (Zhanyong Wan)
+
+// Tests Google Test's throw-on-failure mode with exceptions enabled.
+
+#include "gtest/gtest.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdexcept>
+
+// Prints the given failure message and exits the program with
+// non-zero.  We use this instead of a Google Test assertion to
+// indicate a failure, as the latter is been tested and cannot be
+// relied on.
+void Fail(const char* msg) {
+  printf("FAILURE: %s\n", msg);
+  fflush(stdout);
+  exit(1);
+}
+
+// Tests that an assertion failure throws a subclass of
+// std::runtime_error.
+void TestFailureThrowsRuntimeError() {
+  testing::GTEST_FLAG(throw_on_failure) = true;
+
+  // A successful assertion shouldn't throw.
+  try {
+    EXPECT_EQ(3, 3);
+  } catch(...) {
+    Fail("A successful assertion wrongfully threw.");
+  }
+
+  // A failed assertion should throw a subclass of std::runtime_error.
+  try {
+    EXPECT_EQ(2, 3) << "Expected failure";
+  } catch(const std::runtime_error& e) {
+    if (strstr(e.what(), "Expected failure") != NULL)
+      return;
+
+    printf("%s",
+           "A failed assertion did throw an exception of the right type, "
+           "but the message is incorrect.  Instead of containing \"Expected "
+           "failure\", it is:\n");
+    Fail(e.what());
+  } catch(...) {
+    Fail("A failed assertion threw the wrong type of exception.");
+  }
+  Fail("A failed assertion should've thrown but didn't.");
+}
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  // We want to ensure that people can use Google Test assertions in
+  // other testing frameworks, as long as they initialize Google Test
+  // properly and set the thrown-on-failure mode.  Therefore, we don't
+  // use Google Test's constructs for defining and running tests
+  // (e.g. TEST and RUN_ALL_TESTS) here.
+
+  TestFailureThrowsRuntimeError();
+  return 0;
+}
diff --git a/third_party/googletest/src/test/gtest_throw_on_failure_test.py b/third_party/googletest/src/test/gtest_throw_on_failure_test.py
new file mode 100755 (executable)
index 0000000..5678ffe
--- /dev/null
@@ -0,0 +1,171 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, 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.
+
+"""Tests Google Test's throw-on-failure mode with exceptions disabled.
+
+This script invokes gtest_throw_on_failure_test_ (a program written with
+Google Test) with different environments and command line flags.
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import gtest_test_utils
+
+
+# Constants.
+
+# The command line flag for enabling/disabling the throw-on-failure mode.
+THROW_ON_FAILURE = 'gtest_throw_on_failure'
+
+# Path to the gtest_throw_on_failure_test_ program, compiled with
+# exceptions disabled.
+EXE_PATH = gtest_test_utils.GetTestExecutablePath(
+    'gtest_throw_on_failure_test_')
+
+
+# Utilities.
+
+
+def SetEnvVar(env_var, value):
+  """Sets an environment variable to a given value; unsets it when the
+  given value is None.
+  """
+
+  env_var = env_var.upper()
+  if value is not None:
+    os.environ[env_var] = value
+  elif env_var in os.environ:
+    del os.environ[env_var]
+
+
+def Run(command):
+  """Runs a command; returns True/False if its exit code is/isn't 0."""
+
+  print 'Running "%s". . .' % ' '.join(command)
+  p = gtest_test_utils.Subprocess(command)
+  return p.exited and p.exit_code == 0
+
+
+# The tests.  TODO(wan@google.com): refactor the class to share common
+# logic with code in gtest_break_on_failure_unittest.py.
+class ThrowOnFailureTest(gtest_test_utils.TestCase):
+  """Tests the throw-on-failure mode."""
+
+  def RunAndVerify(self, env_var_value, flag_value, should_fail):
+    """Runs gtest_throw_on_failure_test_ and verifies that it does
+    (or does not) exit with a non-zero code.
+
+    Args:
+      env_var_value:    value of the GTEST_BREAK_ON_FAILURE environment
+                        variable; None if the variable should be unset.
+      flag_value:       value of the --gtest_break_on_failure flag;
+                        None if the flag should not be present.
+      should_fail:      True iff the program is expected to fail.
+    """
+
+    SetEnvVar(THROW_ON_FAILURE, env_var_value)
+
+    if env_var_value is None:
+      env_var_value_msg = ' is not set'
+    else:
+      env_var_value_msg = '=' + env_var_value
+
+    if flag_value is None:
+      flag = ''
+    elif flag_value == '0':
+      flag = '--%s=0' % THROW_ON_FAILURE
+    else:
+      flag = '--%s' % THROW_ON_FAILURE
+
+    command = [EXE_PATH]
+    if flag:
+      command.append(flag)
+
+    if should_fail:
+      should_or_not = 'should'
+    else:
+      should_or_not = 'should not'
+
+    failed = not Run(command)
+
+    SetEnvVar(THROW_ON_FAILURE, None)
+
+    msg = ('when %s%s, an assertion failure in "%s" %s cause a non-zero '
+           'exit code.' %
+           (THROW_ON_FAILURE, env_var_value_msg, ' '.join(command),
+            should_or_not))
+    self.assert_(failed == should_fail, msg)
+
+  def testDefaultBehavior(self):
+    """Tests the behavior of the default mode."""
+
+    self.RunAndVerify(env_var_value=None, flag_value=None, should_fail=False)
+
+  def testThrowOnFailureEnvVar(self):
+    """Tests using the GTEST_THROW_ON_FAILURE environment variable."""
+
+    self.RunAndVerify(env_var_value='0',
+                      flag_value=None,
+                      should_fail=False)
+    self.RunAndVerify(env_var_value='1',
+                      flag_value=None,
+                      should_fail=True)
+
+  def testThrowOnFailureFlag(self):
+    """Tests using the --gtest_throw_on_failure flag."""
+
+    self.RunAndVerify(env_var_value=None,
+                      flag_value='0',
+                      should_fail=False)
+    self.RunAndVerify(env_var_value=None,
+                      flag_value='1',
+                      should_fail=True)
+
+  def testThrowOnFailureFlagOverridesEnvVar(self):
+    """Tests that --gtest_throw_on_failure overrides GTEST_THROW_ON_FAILURE."""
+
+    self.RunAndVerify(env_var_value='0',
+                      flag_value='0',
+                      should_fail=False)
+    self.RunAndVerify(env_var_value='0',
+                      flag_value='1',
+                      should_fail=True)
+    self.RunAndVerify(env_var_value='1',
+                      flag_value='0',
+                      should_fail=False)
+    self.RunAndVerify(env_var_value='1',
+                      flag_value='1',
+                      should_fail=True)
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/src/test/gtest_throw_on_failure_test_.cc b/third_party/googletest/src/test/gtest_throw_on_failure_test_.cc
new file mode 100644 (file)
index 0000000..03776ec
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright 2009, 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: wan@google.com (Zhanyong Wan)
+
+// Tests Google Test's throw-on-failure mode with exceptions disabled.
+//
+// This program must be compiled with exceptions disabled.  It will be
+// invoked by gtest_throw_on_failure_test.py, and is expected to exit
+// with non-zero in the throw-on-failure mode or 0 otherwise.
+
+#include "gtest/gtest.h"
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+
+  // We want to ensure that people can use Google Test assertions in
+  // other testing frameworks, as long as they initialize Google Test
+  // properly and set the thrown-on-failure mode.  Therefore, we don't
+  // use Google Test's constructs for defining and running tests
+  // (e.g. TEST and RUN_ALL_TESTS) here.
+
+  // In the throw-on-failure mode with exceptions disabled, this
+  // assertion will cause the program to exit with a non-zero code.
+  EXPECT_EQ(2, 3);
+
+  // When not in the throw-on-failure mode, the control will reach
+  // here.
+  return 0;
+}
diff --git a/third_party/googletest/src/test/gtest_uninitialized_test.py b/third_party/googletest/src/test/gtest_uninitialized_test.py
new file mode 100755 (executable)
index 0000000..6ae57ee
--- /dev/null
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, 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.
+
+"""Verifies that Google Test warns the user when not initialized properly."""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import gtest_test_utils
+
+
+COMMAND = gtest_test_utils.GetTestExecutablePath('gtest_uninitialized_test_')
+
+
+def Assert(condition):
+  if not condition:
+    raise AssertionError
+
+
+def AssertEq(expected, actual):
+  if expected != actual:
+    print 'Expected: %s' % (expected,)
+    print '  Actual: %s' % (actual,)
+    raise AssertionError
+
+
+def TestExitCodeAndOutput(command):
+  """Runs the given command and verifies its exit code and output."""
+
+  # Verifies that 'command' exits with code 1.
+  p = gtest_test_utils.Subprocess(command)
+  Assert(p.exited)
+  AssertEq(1, p.exit_code)
+  Assert('InitGoogleTest' in p.output)
+
+
+class GTestUninitializedTest(gtest_test_utils.TestCase):
+  def testExitCodeAndOutput(self):
+    TestExitCodeAndOutput(COMMAND)
+
+
+if __name__ == '__main__':
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/src/test/gtest_uninitialized_test_.cc b/third_party/googletest/src/test/gtest_uninitialized_test_.cc
new file mode 100644 (file)
index 0000000..4431698
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2008, 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: wan@google.com (Zhanyong Wan)
+
+#include "gtest/gtest.h"
+
+TEST(DummyTest, Dummy) {
+  // This test doesn't verify anything.  We just need it to create a
+  // realistic stage for testing the behavior of Google Test when
+  // RUN_ALL_TESTS() is called without testing::InitGoogleTest() being
+  // called first.
+}
+
+int main() {
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/src/test/gtest_unittest.cc b/third_party/googletest/src/test/gtest_unittest.cc
new file mode 100644 (file)
index 0000000..23d6860
--- /dev/null
@@ -0,0 +1,7337 @@
+// Copyright 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: wan@google.com (Zhanyong Wan)
+//
+// Tests for Google Test itself.  This verifies that the basic constructs of
+// Google Test work.
+
+#include "gtest/gtest.h"
+#include <vector>
+#include <ostream>
+
+// Verifies that the command line flag variables can be accessed
+// in code once <gtest/gtest.h> has been #included.
+// Do not move it after other #includes.
+TEST(CommandLineFlagsTest, CanBeAccessedInCodeOnceGTestHIsIncluded) {
+  bool dummy = testing::GTEST_FLAG(also_run_disabled_tests)
+      || testing::GTEST_FLAG(break_on_failure)
+      || testing::GTEST_FLAG(catch_exceptions)
+      || testing::GTEST_FLAG(color) != "unknown"
+      || testing::GTEST_FLAG(filter) != "unknown"
+      || testing::GTEST_FLAG(list_tests)
+      || testing::GTEST_FLAG(output) != "unknown"
+      || testing::GTEST_FLAG(print_time)
+      || testing::GTEST_FLAG(random_seed)
+      || testing::GTEST_FLAG(repeat) > 0
+      || testing::GTEST_FLAG(show_internal_stack_frames)
+      || testing::GTEST_FLAG(shuffle)
+      || testing::GTEST_FLAG(stack_trace_depth) > 0
+      || testing::GTEST_FLAG(stream_result_to) != "unknown"
+      || testing::GTEST_FLAG(throw_on_failure);
+  EXPECT_TRUE(dummy || !dummy);  // Suppresses warning that dummy is unused.
+}
+
+#include "gtest/gtest-spi.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+#include <limits.h>  // For INT_MAX.
+#include <stdlib.h>
+#include <time.h>
+
+#include <map>
+
+namespace testing {
+namespace internal {
+
+// Provides access to otherwise private parts of the TestEventListeners class
+// that are needed to test it.
+class TestEventListenersAccessor {
+ public:
+  static TestEventListener* GetRepeater(TestEventListeners* listeners) {
+    return listeners->repeater();
+  }
+
+  static void SetDefaultResultPrinter(TestEventListeners* listeners,
+                                      TestEventListener* listener) {
+    listeners->SetDefaultResultPrinter(listener);
+  }
+  static void SetDefaultXmlGenerator(TestEventListeners* listeners,
+                                     TestEventListener* listener) {
+    listeners->SetDefaultXmlGenerator(listener);
+  }
+
+  static bool EventForwardingEnabled(const TestEventListeners& listeners) {
+    return listeners.EventForwardingEnabled();
+  }
+
+  static void SuppressEventForwarding(TestEventListeners* listeners) {
+    listeners->SuppressEventForwarding();
+  }
+};
+
+}  // namespace internal
+}  // namespace testing
+
+using testing::AssertionFailure;
+using testing::AssertionResult;
+using testing::AssertionSuccess;
+using testing::DoubleLE;
+using testing::EmptyTestEventListener;
+using testing::FloatLE;
+using testing::GTEST_FLAG(also_run_disabled_tests);
+using testing::GTEST_FLAG(break_on_failure);
+using testing::GTEST_FLAG(catch_exceptions);
+using testing::GTEST_FLAG(color);
+using testing::GTEST_FLAG(death_test_use_fork);
+using testing::GTEST_FLAG(filter);
+using testing::GTEST_FLAG(list_tests);
+using testing::GTEST_FLAG(output);
+using testing::GTEST_FLAG(print_time);
+using testing::GTEST_FLAG(random_seed);
+using testing::GTEST_FLAG(repeat);
+using testing::GTEST_FLAG(show_internal_stack_frames);
+using testing::GTEST_FLAG(shuffle);
+using testing::GTEST_FLAG(stack_trace_depth);
+using testing::GTEST_FLAG(stream_result_to);
+using testing::GTEST_FLAG(throw_on_failure);
+using testing::IsNotSubstring;
+using testing::IsSubstring;
+using testing::Message;
+using testing::ScopedFakeTestPartResultReporter;
+using testing::StaticAssertTypeEq;
+using testing::Test;
+using testing::TestCase;
+using testing::TestEventListeners;
+using testing::TestPartResult;
+using testing::TestPartResultArray;
+using testing::TestProperty;
+using testing::TestResult;
+using testing::UnitTest;
+using testing::kMaxStackTraceDepth;
+using testing::internal::AddReference;
+using testing::internal::AlwaysFalse;
+using testing::internal::AlwaysTrue;
+using testing::internal::AppendUserMessage;
+using testing::internal::ArrayAwareFind;
+using testing::internal::ArrayEq;
+using testing::internal::CodePointToUtf8;
+using testing::internal::CompileAssertTypesEqual;
+using testing::internal::CopyArray;
+using testing::internal::CountIf;
+using testing::internal::EqFailure;
+using testing::internal::FloatingPoint;
+using testing::internal::ForEach;
+using testing::internal::FormatTimeInMillisAsSeconds;
+using testing::internal::GTestFlagSaver;
+using testing::internal::GetCurrentOsStackTraceExceptTop;
+using testing::internal::GetElementOr;
+using testing::internal::GetNextRandomSeed;
+using testing::internal::GetRandomSeedFromFlag;
+using testing::internal::GetTestTypeId;
+using testing::internal::GetTypeId;
+using testing::internal::GetUnitTestImpl;
+using testing::internal::ImplicitlyConvertible;
+using testing::internal::Int32;
+using testing::internal::Int32FromEnvOrDie;
+using testing::internal::IsAProtocolMessage;
+using testing::internal::IsContainer;
+using testing::internal::IsContainerTest;
+using testing::internal::IsNotContainer;
+using testing::internal::NativeArray;
+using testing::internal::ParseInt32Flag;
+using testing::internal::RemoveConst;
+using testing::internal::RemoveReference;
+using testing::internal::ShouldRunTestOnShard;
+using testing::internal::ShouldShard;
+using testing::internal::ShouldUseColor;
+using testing::internal::Shuffle;
+using testing::internal::ShuffleRange;
+using testing::internal::SkipPrefix;
+using testing::internal::StreamableToString;
+using testing::internal::String;
+using testing::internal::TestEventListenersAccessor;
+using testing::internal::TestResultAccessor;
+using testing::internal::UInt32;
+using testing::internal::WideStringToUtf8;
+using testing::internal::kCopy;
+using testing::internal::kMaxRandomSeed;
+using testing::internal::kReference;
+using testing::internal::kTestTypeIdInGoogleTest;
+using testing::internal::scoped_ptr;
+
+#if GTEST_HAS_STREAM_REDIRECTION
+using testing::internal::CaptureStdout;
+using testing::internal::GetCapturedStdout;
+#endif
+
+#if GTEST_IS_THREADSAFE
+using testing::internal::ThreadWithParam;
+#endif
+
+class TestingVector : public std::vector<int> {
+};
+
+::std::ostream& operator<<(::std::ostream& os,
+                           const TestingVector& vector) {
+  os << "{ ";
+  for (size_t i = 0; i < vector.size(); i++) {
+    os << vector[i] << " ";
+  }
+  os << "}";
+  return os;
+}
+
+// This line tests that we can define tests in an unnamed namespace.
+namespace {
+
+TEST(GetRandomSeedFromFlagTest, HandlesZero) {
+  const int seed = GetRandomSeedFromFlag(0);
+  EXPECT_LE(1, seed);
+  EXPECT_LE(seed, static_cast<int>(kMaxRandomSeed));
+}
+
+TEST(GetRandomSeedFromFlagTest, PreservesValidSeed) {
+  EXPECT_EQ(1, GetRandomSeedFromFlag(1));
+  EXPECT_EQ(2, GetRandomSeedFromFlag(2));
+  EXPECT_EQ(kMaxRandomSeed - 1, GetRandomSeedFromFlag(kMaxRandomSeed - 1));
+  EXPECT_EQ(static_cast<int>(kMaxRandomSeed),
+            GetRandomSeedFromFlag(kMaxRandomSeed));
+}
+
+TEST(GetRandomSeedFromFlagTest, NormalizesInvalidSeed) {
+  const int seed1 = GetRandomSeedFromFlag(-1);
+  EXPECT_LE(1, seed1);
+  EXPECT_LE(seed1, static_cast<int>(kMaxRandomSeed));
+
+  const int seed2 = GetRandomSeedFromFlag(kMaxRandomSeed + 1);
+  EXPECT_LE(1, seed2);
+  EXPECT_LE(seed2, static_cast<int>(kMaxRandomSeed));
+}
+
+TEST(GetNextRandomSeedTest, WorksForValidInput) {
+  EXPECT_EQ(2, GetNextRandomSeed(1));
+  EXPECT_EQ(3, GetNextRandomSeed(2));
+  EXPECT_EQ(static_cast<int>(kMaxRandomSeed),
+            GetNextRandomSeed(kMaxRandomSeed - 1));
+  EXPECT_EQ(1, GetNextRandomSeed(kMaxRandomSeed));
+
+  // We deliberately don't test GetNextRandomSeed() with invalid
+  // inputs, as that requires death tests, which are expensive.  This
+  // is fine as GetNextRandomSeed() is internal and has a
+  // straightforward definition.
+}
+
+static void ClearCurrentTestPartResults() {
+  TestResultAccessor::ClearTestPartResults(
+      GetUnitTestImpl()->current_test_result());
+}
+
+// Tests GetTypeId.
+
+TEST(GetTypeIdTest, ReturnsSameValueForSameType) {
+  EXPECT_EQ(GetTypeId<int>(), GetTypeId<int>());
+  EXPECT_EQ(GetTypeId<Test>(), GetTypeId<Test>());
+}
+
+class SubClassOfTest : public Test {};
+class AnotherSubClassOfTest : public Test {};
+
+TEST(GetTypeIdTest, ReturnsDifferentValuesForDifferentTypes) {
+  EXPECT_NE(GetTypeId<int>(), GetTypeId<const int>());
+  EXPECT_NE(GetTypeId<int>(), GetTypeId<char>());
+  EXPECT_NE(GetTypeId<int>(), GetTestTypeId());
+  EXPECT_NE(GetTypeId<SubClassOfTest>(), GetTestTypeId());
+  EXPECT_NE(GetTypeId<AnotherSubClassOfTest>(), GetTestTypeId());
+  EXPECT_NE(GetTypeId<AnotherSubClassOfTest>(), GetTypeId<SubClassOfTest>());
+}
+
+// Verifies that GetTestTypeId() returns the same value, no matter it
+// is called from inside Google Test or outside of it.
+TEST(GetTestTypeIdTest, ReturnsTheSameValueInsideOrOutsideOfGoogleTest) {
+  EXPECT_EQ(kTestTypeIdInGoogleTest, GetTestTypeId());
+}
+
+// Tests FormatTimeInMillisAsSeconds().
+
+TEST(FormatTimeInMillisAsSecondsTest, FormatsZero) {
+  EXPECT_EQ("0", FormatTimeInMillisAsSeconds(0));
+}
+
+TEST(FormatTimeInMillisAsSecondsTest, FormatsPositiveNumber) {
+  EXPECT_EQ("0.003", FormatTimeInMillisAsSeconds(3));
+  EXPECT_EQ("0.01", FormatTimeInMillisAsSeconds(10));
+  EXPECT_EQ("0.2", FormatTimeInMillisAsSeconds(200));
+  EXPECT_EQ("1.2", FormatTimeInMillisAsSeconds(1200));
+  EXPECT_EQ("3", FormatTimeInMillisAsSeconds(3000));
+}
+
+TEST(FormatTimeInMillisAsSecondsTest, FormatsNegativeNumber) {
+  EXPECT_EQ("-0.003", FormatTimeInMillisAsSeconds(-3));
+  EXPECT_EQ("-0.01", FormatTimeInMillisAsSeconds(-10));
+  EXPECT_EQ("-0.2", FormatTimeInMillisAsSeconds(-200));
+  EXPECT_EQ("-1.2", FormatTimeInMillisAsSeconds(-1200));
+  EXPECT_EQ("-3", FormatTimeInMillisAsSeconds(-3000));
+}
+
+#if GTEST_CAN_COMPARE_NULL
+
+# ifdef __BORLANDC__
+// Silences warnings: "Condition is always true", "Unreachable code"
+#  pragma option push -w-ccc -w-rch
+# endif
+
+// Tests that GTEST_IS_NULL_LITERAL_(x) is true when x is a null
+// pointer literal.
+TEST(NullLiteralTest, IsTrueForNullLiterals) {
+  EXPECT_TRUE(GTEST_IS_NULL_LITERAL_(NULL));
+  EXPECT_TRUE(GTEST_IS_NULL_LITERAL_(0));
+  EXPECT_TRUE(GTEST_IS_NULL_LITERAL_(0U));
+  EXPECT_TRUE(GTEST_IS_NULL_LITERAL_(0L));
+
+# ifndef __BORLANDC__
+
+  // Some compilers may fail to detect some null pointer literals;
+  // as long as users of the framework don't use such literals, this
+  // is harmless.
+  EXPECT_TRUE(GTEST_IS_NULL_LITERAL_(1 - 1));
+
+# endif
+}
+
+// Tests that GTEST_IS_NULL_LITERAL_(x) is false when x is not a null
+// pointer literal.
+TEST(NullLiteralTest, IsFalseForNonNullLiterals) {
+  EXPECT_FALSE(GTEST_IS_NULL_LITERAL_(1));
+  EXPECT_FALSE(GTEST_IS_NULL_LITERAL_(0.0));
+  EXPECT_FALSE(GTEST_IS_NULL_LITERAL_('a'));
+  EXPECT_FALSE(GTEST_IS_NULL_LITERAL_(static_cast<void*>(NULL)));
+}
+
+# ifdef __BORLANDC__
+// Restores warnings after previous "#pragma option push" suppressed them.
+#  pragma option pop
+# endif
+
+#endif  // GTEST_CAN_COMPARE_NULL
+//
+// Tests CodePointToUtf8().
+
+// Tests that the NUL character L'\0' is encoded correctly.
+TEST(CodePointToUtf8Test, CanEncodeNul) {
+  char buffer[32];
+  EXPECT_STREQ("", CodePointToUtf8(L'\0', buffer));
+}
+
+// Tests that ASCII characters are encoded correctly.
+TEST(CodePointToUtf8Test, CanEncodeAscii) {
+  char buffer[32];
+  EXPECT_STREQ("a", CodePointToUtf8(L'a', buffer));
+  EXPECT_STREQ("Z", CodePointToUtf8(L'Z', buffer));
+  EXPECT_STREQ("&", CodePointToUtf8(L'&', buffer));
+  EXPECT_STREQ("\x7F", CodePointToUtf8(L'\x7F', buffer));
+}
+
+// Tests that Unicode code-points that have 8 to 11 bits are encoded
+// as 110xxxxx 10xxxxxx.
+TEST(CodePointToUtf8Test, CanEncode8To11Bits) {
+  char buffer[32];
+  // 000 1101 0011 => 110-00011 10-010011
+  EXPECT_STREQ("\xC3\x93", CodePointToUtf8(L'\xD3', buffer));
+
+  // 101 0111 0110 => 110-10101 10-110110
+  // Some compilers (e.g., GCC on MinGW) cannot handle non-ASCII codepoints
+  // in wide strings and wide chars. In order to accomodate them, we have to
+  // introduce such character constants as integers.
+  EXPECT_STREQ("\xD5\xB6",
+               CodePointToUtf8(static_cast<wchar_t>(0x576), buffer));
+}
+
+// Tests that Unicode code-points that have 12 to 16 bits are encoded
+// as 1110xxxx 10xxxxxx 10xxxxxx.
+TEST(CodePointToUtf8Test, CanEncode12To16Bits) {
+  char buffer[32];
+  // 0000 1000 1101 0011 => 1110-0000 10-100011 10-010011
+  EXPECT_STREQ("\xE0\xA3\x93",
+               CodePointToUtf8(static_cast<wchar_t>(0x8D3), buffer));
+
+  // 1100 0111 0100 1101 => 1110-1100 10-011101 10-001101
+  EXPECT_STREQ("\xEC\x9D\x8D",
+               CodePointToUtf8(static_cast<wchar_t>(0xC74D), buffer));
+}
+
+#if !GTEST_WIDE_STRING_USES_UTF16_
+// Tests in this group require a wchar_t to hold > 16 bits, and thus
+// are skipped on Windows, Cygwin, and Symbian, where a wchar_t is
+// 16-bit wide. This code may not compile on those systems.
+
+// Tests that Unicode code-points that have 17 to 21 bits are encoded
+// as 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx.
+TEST(CodePointToUtf8Test, CanEncode17To21Bits) {
+  char buffer[32];
+  // 0 0001 0000 1000 1101 0011 => 11110-000 10-010000 10-100011 10-010011
+  EXPECT_STREQ("\xF0\x90\xA3\x93", CodePointToUtf8(L'\x108D3', buffer));
+
+  // 0 0001 0000 0100 0000 0000 => 11110-000 10-010000 10-010000 10-000000
+  EXPECT_STREQ("\xF0\x90\x90\x80", CodePointToUtf8(L'\x10400', buffer));
+
+  // 1 0000 1000 0110 0011 0100 => 11110-100 10-001000 10-011000 10-110100
+  EXPECT_STREQ("\xF4\x88\x98\xB4", CodePointToUtf8(L'\x108634', buffer));
+}
+
+// Tests that encoding an invalid code-point generates the expected result.
+TEST(CodePointToUtf8Test, CanEncodeInvalidCodePoint) {
+  char buffer[32];
+  EXPECT_STREQ("(Invalid Unicode 0x1234ABCD)",
+               CodePointToUtf8(L'\x1234ABCD', buffer));
+}
+
+#endif  // !GTEST_WIDE_STRING_USES_UTF16_
+
+// Tests WideStringToUtf8().
+
+// Tests that the NUL character L'\0' is encoded correctly.
+TEST(WideStringToUtf8Test, CanEncodeNul) {
+  EXPECT_STREQ("", WideStringToUtf8(L"", 0).c_str());
+  EXPECT_STREQ("", WideStringToUtf8(L"", -1).c_str());
+}
+
+// Tests that ASCII strings are encoded correctly.
+TEST(WideStringToUtf8Test, CanEncodeAscii) {
+  EXPECT_STREQ("a", WideStringToUtf8(L"a", 1).c_str());
+  EXPECT_STREQ("ab", WideStringToUtf8(L"ab", 2).c_str());
+  EXPECT_STREQ("a", WideStringToUtf8(L"a", -1).c_str());
+  EXPECT_STREQ("ab", WideStringToUtf8(L"ab", -1).c_str());
+}
+
+// Tests that Unicode code-points that have 8 to 11 bits are encoded
+// as 110xxxxx 10xxxxxx.
+TEST(WideStringToUtf8Test, CanEncode8To11Bits) {
+  // 000 1101 0011 => 110-00011 10-010011
+  EXPECT_STREQ("\xC3\x93", WideStringToUtf8(L"\xD3", 1).c_str());
+  EXPECT_STREQ("\xC3\x93", WideStringToUtf8(L"\xD3", -1).c_str());
+
+  // 101 0111 0110 => 110-10101 10-110110
+  const wchar_t s[] = { 0x576, '\0' };
+  EXPECT_STREQ("\xD5\xB6", WideStringToUtf8(s, 1).c_str());
+  EXPECT_STREQ("\xD5\xB6", WideStringToUtf8(s, -1).c_str());
+}
+
+// Tests that Unicode code-points that have 12 to 16 bits are encoded
+// as 1110xxxx 10xxxxxx 10xxxxxx.
+TEST(WideStringToUtf8Test, CanEncode12To16Bits) {
+  // 0000 1000 1101 0011 => 1110-0000 10-100011 10-010011
+  const wchar_t s1[] = { 0x8D3, '\0' };
+  EXPECT_STREQ("\xE0\xA3\x93", WideStringToUtf8(s1, 1).c_str());
+  EXPECT_STREQ("\xE0\xA3\x93", WideStringToUtf8(s1, -1).c_str());
+
+  // 1100 0111 0100 1101 => 1110-1100 10-011101 10-001101
+  const wchar_t s2[] = { 0xC74D, '\0' };
+  EXPECT_STREQ("\xEC\x9D\x8D", WideStringToUtf8(s2, 1).c_str());
+  EXPECT_STREQ("\xEC\x9D\x8D", WideStringToUtf8(s2, -1).c_str());
+}
+
+// Tests that the conversion stops when the function encounters \0 character.
+TEST(WideStringToUtf8Test, StopsOnNulCharacter) {
+  EXPECT_STREQ("ABC", WideStringToUtf8(L"ABC\0XYZ", 100).c_str());
+}
+
+// Tests that the conversion stops when the function reaches the limit
+// specified by the 'length' parameter.
+TEST(WideStringToUtf8Test, StopsWhenLengthLimitReached) {
+  EXPECT_STREQ("ABC", WideStringToUtf8(L"ABCDEF", 3).c_str());
+}
+
+#if !GTEST_WIDE_STRING_USES_UTF16_
+// Tests that Unicode code-points that have 17 to 21 bits are encoded
+// as 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx. This code may not compile
+// on the systems using UTF-16 encoding.
+TEST(WideStringToUtf8Test, CanEncode17To21Bits) {
+  // 0 0001 0000 1000 1101 0011 => 11110-000 10-010000 10-100011 10-010011
+  EXPECT_STREQ("\xF0\x90\xA3\x93", WideStringToUtf8(L"\x108D3", 1).c_str());
+  EXPECT_STREQ("\xF0\x90\xA3\x93", WideStringToUtf8(L"\x108D3", -1).c_str());
+
+  // 1 0000 1000 0110 0011 0100 => 11110-100 10-001000 10-011000 10-110100
+  EXPECT_STREQ("\xF4\x88\x98\xB4", WideStringToUtf8(L"\x108634", 1).c_str());
+  EXPECT_STREQ("\xF4\x88\x98\xB4", WideStringToUtf8(L"\x108634", -1).c_str());
+}
+
+// Tests that encoding an invalid code-point generates the expected result.
+TEST(WideStringToUtf8Test, CanEncodeInvalidCodePoint) {
+  EXPECT_STREQ("(Invalid Unicode 0xABCDFF)",
+               WideStringToUtf8(L"\xABCDFF", -1).c_str());
+}
+#else  // !GTEST_WIDE_STRING_USES_UTF16_
+// Tests that surrogate pairs are encoded correctly on the systems using
+// UTF-16 encoding in the wide strings.
+TEST(WideStringToUtf8Test, CanEncodeValidUtf16SUrrogatePairs) {
+  const wchar_t s[] = { 0xD801, 0xDC00, '\0' };
+  EXPECT_STREQ("\xF0\x90\x90\x80", WideStringToUtf8(s, -1).c_str());
+}
+
+// Tests that encoding an invalid UTF-16 surrogate pair
+// generates the expected result.
+TEST(WideStringToUtf8Test, CanEncodeInvalidUtf16SurrogatePair) {
+  // Leading surrogate is at the end of the string.
+  const wchar_t s1[] = { 0xD800, '\0' };
+  EXPECT_STREQ("\xED\xA0\x80", WideStringToUtf8(s1, -1).c_str());
+  // Leading surrogate is not followed by the trailing surrogate.
+  const wchar_t s2[] = { 0xD800, 'M', '\0' };
+  EXPECT_STREQ("\xED\xA0\x80M", WideStringToUtf8(s2, -1).c_str());
+  // Trailing surrogate appearas without a leading surrogate.
+  const wchar_t s3[] = { 0xDC00, 'P', 'Q', 'R', '\0' };
+  EXPECT_STREQ("\xED\xB0\x80PQR", WideStringToUtf8(s3, -1).c_str());
+}
+#endif  // !GTEST_WIDE_STRING_USES_UTF16_
+
+// Tests that codepoint concatenation works correctly.
+#if !GTEST_WIDE_STRING_USES_UTF16_
+TEST(WideStringToUtf8Test, ConcatenatesCodepointsCorrectly) {
+  const wchar_t s[] = { 0x108634, 0xC74D, '\n', 0x576, 0x8D3, 0x108634, '\0'};
+  EXPECT_STREQ(
+      "\xF4\x88\x98\xB4"
+          "\xEC\x9D\x8D"
+          "\n"
+          "\xD5\xB6"
+          "\xE0\xA3\x93"
+          "\xF4\x88\x98\xB4",
+      WideStringToUtf8(s, -1).c_str());
+}
+#else
+TEST(WideStringToUtf8Test, ConcatenatesCodepointsCorrectly) {
+  const wchar_t s[] = { 0xC74D, '\n', 0x576, 0x8D3, '\0'};
+  EXPECT_STREQ(
+      "\xEC\x9D\x8D" "\n" "\xD5\xB6" "\xE0\xA3\x93",
+      WideStringToUtf8(s, -1).c_str());
+}
+#endif  // !GTEST_WIDE_STRING_USES_UTF16_
+
+// Tests the Random class.
+
+TEST(RandomDeathTest, GeneratesCrashesOnInvalidRange) {
+  testing::internal::Random random(42);
+  EXPECT_DEATH_IF_SUPPORTED(
+      random.Generate(0),
+      "Cannot generate a number in the range \\[0, 0\\)");
+  EXPECT_DEATH_IF_SUPPORTED(
+      random.Generate(testing::internal::Random::kMaxRange + 1),
+      "Generation of a number in \\[0, 2147483649\\) was requested, "
+      "but this can only generate numbers in \\[0, 2147483648\\)");
+}
+
+TEST(RandomTest, GeneratesNumbersWithinRange) {
+  const UInt32 kRange = 10000;
+  testing::internal::Random random(12345);
+  for (int i = 0; i < 10; i++) {
+    EXPECT_LT(random.Generate(kRange), kRange) << " for iteration " << i;
+  }
+
+  testing::internal::Random random2(testing::internal::Random::kMaxRange);
+  for (int i = 0; i < 10; i++) {
+    EXPECT_LT(random2.Generate(kRange), kRange) << " for iteration " << i;
+  }
+}
+
+TEST(RandomTest, RepeatsWhenReseeded) {
+  const int kSeed = 123;
+  const int kArraySize = 10;
+  const UInt32 kRange = 10000;
+  UInt32 values[kArraySize];
+
+  testing::internal::Random random(kSeed);
+  for (int i = 0; i < kArraySize; i++) {
+    values[i] = random.Generate(kRange);
+  }
+
+  random.Reseed(kSeed);
+  for (int i = 0; i < kArraySize; i++) {
+    EXPECT_EQ(values[i], random.Generate(kRange)) << " for iteration " << i;
+  }
+}
+
+// Tests STL container utilities.
+
+// Tests CountIf().
+
+static bool IsPositive(int n) { return n > 0; }
+
+TEST(ContainerUtilityTest, CountIf) {
+  std::vector<int> v;
+  EXPECT_EQ(0, CountIf(v, IsPositive));  // Works for an empty container.
+
+  v.push_back(-1);
+  v.push_back(0);
+  EXPECT_EQ(0, CountIf(v, IsPositive));  // Works when no value satisfies.
+
+  v.push_back(2);
+  v.push_back(-10);
+  v.push_back(10);
+  EXPECT_EQ(2, CountIf(v, IsPositive));
+}
+
+// Tests ForEach().
+
+static int g_sum = 0;
+static void Accumulate(int n) { g_sum += n; }
+
+TEST(ContainerUtilityTest, ForEach) {
+  std::vector<int> v;
+  g_sum = 0;
+  ForEach(v, Accumulate);
+  EXPECT_EQ(0, g_sum);  // Works for an empty container;
+
+  g_sum = 0;
+  v.push_back(1);
+  ForEach(v, Accumulate);
+  EXPECT_EQ(1, g_sum);  // Works for a container with one element.
+
+  g_sum = 0;
+  v.push_back(20);
+  v.push_back(300);
+  ForEach(v, Accumulate);
+  EXPECT_EQ(321, g_sum);
+}
+
+// Tests GetElementOr().
+TEST(ContainerUtilityTest, GetElementOr) {
+  std::vector<char> a;
+  EXPECT_EQ('x', GetElementOr(a, 0, 'x'));
+
+  a.push_back('a');
+  a.push_back('b');
+  EXPECT_EQ('a', GetElementOr(a, 0, 'x'));
+  EXPECT_EQ('b', GetElementOr(a, 1, 'x'));
+  EXPECT_EQ('x', GetElementOr(a, -2, 'x'));
+  EXPECT_EQ('x', GetElementOr(a, 2, 'x'));
+}
+
+TEST(ContainerUtilityDeathTest, ShuffleRange) {
+  std::vector<int> a;
+  a.push_back(0);
+  a.push_back(1);
+  a.push_back(2);
+  testing::internal::Random random(1);
+
+  EXPECT_DEATH_IF_SUPPORTED(
+      ShuffleRange(&random, -1, 1, &a),
+      "Invalid shuffle range start -1: must be in range \\[0, 3\\]");
+  EXPECT_DEATH_IF_SUPPORTED(
+      ShuffleRange(&random, 4, 4, &a),
+      "Invalid shuffle range start 4: must be in range \\[0, 3\\]");
+  EXPECT_DEATH_IF_SUPPORTED(
+      ShuffleRange(&random, 3, 2, &a),
+      "Invalid shuffle range finish 2: must be in range \\[3, 3\\]");
+  EXPECT_DEATH_IF_SUPPORTED(
+      ShuffleRange(&random, 3, 4, &a),
+      "Invalid shuffle range finish 4: must be in range \\[3, 3\\]");
+}
+
+class VectorShuffleTest : public Test {
+ protected:
+  static const int kVectorSize = 20;
+
+  VectorShuffleTest() : random_(1) {
+    for (int i = 0; i < kVectorSize; i++) {
+      vector_.push_back(i);
+    }
+  }
+
+  static bool VectorIsCorrupt(const TestingVector& vector) {
+    if (kVectorSize != static_cast<int>(vector.size())) {
+      return true;
+    }
+
+    bool found_in_vector[kVectorSize] = { false };
+    for (size_t i = 0; i < vector.size(); i++) {
+      const int e = vector[i];
+      if (e < 0 || e >= kVectorSize || found_in_vector[e]) {
+        return true;
+      }
+      found_in_vector[e] = true;
+    }
+
+    // Vector size is correct, elements' range is correct, no
+    // duplicate elements.  Therefore no corruption has occurred.
+    return false;
+  }
+
+  static bool VectorIsNotCorrupt(const TestingVector& vector) {
+    return !VectorIsCorrupt(vector);
+  }
+
+  static bool RangeIsShuffled(const TestingVector& vector, int begin, int end) {
+    for (int i = begin; i < end; i++) {
+      if (i != vector[i]) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  static bool RangeIsUnshuffled(
+      const TestingVector& vector, int begin, int end) {
+    return !RangeIsShuffled(vector, begin, end);
+  }
+
+  static bool VectorIsShuffled(const TestingVector& vector) {
+    return RangeIsShuffled(vector, 0, static_cast<int>(vector.size()));
+  }
+
+  static bool VectorIsUnshuffled(const TestingVector& vector) {
+    return !VectorIsShuffled(vector);
+  }
+
+  testing::internal::Random random_;
+  TestingVector vector_;
+};  // class VectorShuffleTest
+
+const int VectorShuffleTest::kVectorSize;
+
+TEST_F(VectorShuffleTest, HandlesEmptyRange) {
+  // Tests an empty range at the beginning...
+  ShuffleRange(&random_, 0, 0, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+
+  // ...in the middle...
+  ShuffleRange(&random_, kVectorSize/2, kVectorSize/2, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+
+  // ...at the end...
+  ShuffleRange(&random_, kVectorSize - 1, kVectorSize - 1, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+
+  // ...and past the end.
+  ShuffleRange(&random_, kVectorSize, kVectorSize, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+}
+
+TEST_F(VectorShuffleTest, HandlesRangeOfSizeOne) {
+  // Tests a size one range at the beginning...
+  ShuffleRange(&random_, 0, 1, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+
+  // ...in the middle...
+  ShuffleRange(&random_, kVectorSize/2, kVectorSize/2 + 1, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+
+  // ...and at the end.
+  ShuffleRange(&random_, kVectorSize - 1, kVectorSize, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsUnshuffled, vector_);
+}
+
+// Because we use our own random number generator and a fixed seed,
+// we can guarantee that the following "random" tests will succeed.
+
+TEST_F(VectorShuffleTest, ShufflesEntireVector) {
+  Shuffle(&random_, &vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  EXPECT_FALSE(VectorIsUnshuffled(vector_)) << vector_;
+
+  // Tests the first and last elements in particular to ensure that
+  // there are no off-by-one problems in our shuffle algorithm.
+  EXPECT_NE(0, vector_[0]);
+  EXPECT_NE(kVectorSize - 1, vector_[kVectorSize - 1]);
+}
+
+TEST_F(VectorShuffleTest, ShufflesStartOfVector) {
+  const int kRangeSize = kVectorSize/2;
+
+  ShuffleRange(&random_, 0, kRangeSize, &vector_);
+
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  EXPECT_PRED3(RangeIsShuffled, vector_, 0, kRangeSize);
+  EXPECT_PRED3(RangeIsUnshuffled, vector_, kRangeSize, kVectorSize);
+}
+
+TEST_F(VectorShuffleTest, ShufflesEndOfVector) {
+  const int kRangeSize = kVectorSize / 2;
+  ShuffleRange(&random_, kRangeSize, kVectorSize, &vector_);
+
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  EXPECT_PRED3(RangeIsUnshuffled, vector_, 0, kRangeSize);
+  EXPECT_PRED3(RangeIsShuffled, vector_, kRangeSize, kVectorSize);
+}
+
+TEST_F(VectorShuffleTest, ShufflesMiddleOfVector) {
+  int kRangeSize = kVectorSize/3;
+  ShuffleRange(&random_, kRangeSize, 2*kRangeSize, &vector_);
+
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  EXPECT_PRED3(RangeIsUnshuffled, vector_, 0, kRangeSize);
+  EXPECT_PRED3(RangeIsShuffled, vector_, kRangeSize, 2*kRangeSize);
+  EXPECT_PRED3(RangeIsUnshuffled, vector_, 2*kRangeSize, kVectorSize);
+}
+
+TEST_F(VectorShuffleTest, ShufflesRepeatably) {
+  TestingVector vector2;
+  for (int i = 0; i < kVectorSize; i++) {
+    vector2.push_back(i);
+  }
+
+  random_.Reseed(1234);
+  Shuffle(&random_, &vector_);
+  random_.Reseed(1234);
+  Shuffle(&random_, &vector2);
+
+  ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+  ASSERT_PRED1(VectorIsNotCorrupt, vector2);
+
+  for (int i = 0; i < kVectorSize; i++) {
+    EXPECT_EQ(vector_[i], vector2[i]) << " where i is " << i;
+  }
+}
+
+// Tests the size of the AssertHelper class.
+
+TEST(AssertHelperTest, AssertHelperIsSmall) {
+  // To avoid breaking clients that use lots of assertions in one
+  // function, we cannot grow the size of AssertHelper.
+  EXPECT_LE(sizeof(testing::internal::AssertHelper), sizeof(void*));
+}
+
+// Tests the String class.
+
+// Tests String's constructors.
+TEST(StringTest, Constructors) {
+  // Default ctor.
+  String s1;
+  // We aren't using EXPECT_EQ(NULL, s1.c_str()) because comparing
+  // pointers with NULL isn't supported on all platforms.
+  EXPECT_EQ(0U, s1.length());
+  EXPECT_TRUE(NULL == s1.c_str());
+
+  // Implicitly constructs from a C-string.
+  String s2 = "Hi";
+  EXPECT_EQ(2U, s2.length());
+  EXPECT_STREQ("Hi", s2.c_str());
+
+  // Constructs from a C-string and a length.
+  String s3("hello", 3);
+  EXPECT_EQ(3U, s3.length());
+  EXPECT_STREQ("hel", s3.c_str());
+
+  // The empty String should be created when String is constructed with
+  // a NULL pointer and length 0.
+  EXPECT_EQ(0U, String(NULL, 0).length());
+  EXPECT_FALSE(String(NULL, 0).c_str() == NULL);
+
+  // Constructs a String that contains '\0'.
+  String s4("a\0bcd", 4);
+  EXPECT_EQ(4U, s4.length());
+  EXPECT_EQ('a', s4.c_str()[0]);
+  EXPECT_EQ('\0', s4.c_str()[1]);
+  EXPECT_EQ('b', s4.c_str()[2]);
+  EXPECT_EQ('c', s4.c_str()[3]);
+
+  // Copy ctor where the source is NULL.
+  const String null_str;
+  String s5 = null_str;
+  EXPECT_TRUE(s5.c_str() == NULL);
+
+  // Copy ctor where the source isn't NULL.
+  String s6 = s3;
+  EXPECT_EQ(3U, s6.length());
+  EXPECT_STREQ("hel", s6.c_str());
+
+  // Copy ctor where the source contains '\0'.
+  String s7 = s4;
+  EXPECT_EQ(4U, s7.length());
+  EXPECT_EQ('a', s7.c_str()[0]);
+  EXPECT_EQ('\0', s7.c_str()[1]);
+  EXPECT_EQ('b', s7.c_str()[2]);
+  EXPECT_EQ('c', s7.c_str()[3]);
+}
+
+TEST(StringTest, ConvertsFromStdString) {
+  // An empty std::string.
+  const std::string src1("");
+  const String dest1 = src1;
+  EXPECT_EQ(0U, dest1.length());
+  EXPECT_STREQ("", dest1.c_str());
+
+  // A normal std::string.
+  const std::string src2("Hi");
+  const String dest2 = src2;
+  EXPECT_EQ(2U, dest2.length());
+  EXPECT_STREQ("Hi", dest2.c_str());
+
+  // An std::string with an embedded NUL character.
+  const char src3[] = "a\0b";
+  const String dest3 = std::string(src3, sizeof(src3));
+  EXPECT_EQ(sizeof(src3), dest3.length());
+  EXPECT_EQ('a', dest3.c_str()[0]);
+  EXPECT_EQ('\0', dest3.c_str()[1]);
+  EXPECT_EQ('b', dest3.c_str()[2]);
+}
+
+TEST(StringTest, ConvertsToStdString) {
+  // An empty String.
+  const String src1("");
+  const std::string dest1 = src1;
+  EXPECT_EQ("", dest1);
+
+  // A normal String.
+  const String src2("Hi");
+  const std::string dest2 = src2;
+  EXPECT_EQ("Hi", dest2);
+
+  // A String containing a '\0'.
+  const String src3("x\0y", 3);
+  const std::string dest3 = src3;
+  EXPECT_EQ(std::string("x\0y", 3), dest3);
+}
+
+#if GTEST_HAS_GLOBAL_STRING
+
+TEST(StringTest, ConvertsFromGlobalString) {
+  // An empty ::string.
+  const ::string src1("");
+  const String dest1 = src1;
+  EXPECT_EQ(0U, dest1.length());
+  EXPECT_STREQ("", dest1.c_str());
+
+  // A normal ::string.
+  const ::string src2("Hi");
+  const String dest2 = src2;
+  EXPECT_EQ(2U, dest2.length());
+  EXPECT_STREQ("Hi", dest2.c_str());
+
+  // An ::string with an embedded NUL character.
+  const char src3[] = "x\0y";
+  const String dest3 = ::string(src3, sizeof(src3));
+  EXPECT_EQ(sizeof(src3), dest3.length());
+  EXPECT_EQ('x', dest3.c_str()[0]);
+  EXPECT_EQ('\0', dest3.c_str()[1]);
+  EXPECT_EQ('y', dest3.c_str()[2]);
+}
+
+TEST(StringTest, ConvertsToGlobalString) {
+  // An empty String.
+  const String src1("");
+  const ::string dest1 = src1;
+  EXPECT_EQ("", dest1);
+
+  // A normal String.
+  const String src2("Hi");
+  const ::string dest2 = src2;
+  EXPECT_EQ("Hi", dest2);
+
+  const String src3("x\0y", 3);
+  const ::string dest3 = src3;
+  EXPECT_EQ(::string("x\0y", 3), dest3);
+}
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+// Tests String::ShowCStringQuoted().
+TEST(StringTest, ShowCStringQuoted) {
+  EXPECT_STREQ("(null)",
+               String::ShowCStringQuoted(NULL).c_str());
+  EXPECT_STREQ("\"\"",
+               String::ShowCStringQuoted("").c_str());
+  EXPECT_STREQ("\"foo\"",
+               String::ShowCStringQuoted("foo").c_str());
+}
+
+// Tests String::empty().
+TEST(StringTest, Empty) {
+  EXPECT_TRUE(String("").empty());
+  EXPECT_FALSE(String().empty());
+  EXPECT_FALSE(String(NULL).empty());
+  EXPECT_FALSE(String("a").empty());
+  EXPECT_FALSE(String("\0", 1).empty());
+}
+
+// Tests String::Compare().
+TEST(StringTest, Compare) {
+  // NULL vs NULL.
+  EXPECT_EQ(0, String().Compare(String()));
+
+  // NULL vs non-NULL.
+  EXPECT_EQ(-1, String().Compare(String("")));
+
+  // Non-NULL vs NULL.
+  EXPECT_EQ(1, String("").Compare(String()));
+
+  // The following covers non-NULL vs non-NULL.
+
+  // "" vs "".
+  EXPECT_EQ(0, String("").Compare(String("")));
+
+  // "" vs non-"".
+  EXPECT_EQ(-1, String("").Compare(String("\0", 1)));
+  EXPECT_EQ(-1, String("").Compare(" "));
+
+  // Non-"" vs "".
+  EXPECT_EQ(1, String("a").Compare(String("")));
+
+  // The following covers non-"" vs non-"".
+
+  // Same length and equal.
+  EXPECT_EQ(0, String("a").Compare(String("a")));
+
+  // Same length and different.
+  EXPECT_EQ(-1, String("a\0b", 3).Compare(String("a\0c", 3)));
+  EXPECT_EQ(1, String("b").Compare(String("a")));
+
+  // Different lengths.
+  EXPECT_EQ(-1, String("a").Compare(String("ab")));
+  EXPECT_EQ(-1, String("a").Compare(String("a\0", 2)));
+  EXPECT_EQ(1, String("abc").Compare(String("aacd")));
+}
+
+// Tests String::operator==().
+TEST(StringTest, Equals) {
+  const String null(NULL);
+  EXPECT_TRUE(null == NULL);  // NOLINT
+  EXPECT_FALSE(null == "");  // NOLINT
+  EXPECT_FALSE(null == "bar");  // NOLINT
+
+  const String empty("");
+  EXPECT_FALSE(empty == NULL);  // NOLINT
+  EXPECT_TRUE(empty == "");  // NOLINT
+  EXPECT_FALSE(empty == "bar");  // NOLINT
+
+  const String foo("foo");
+  EXPECT_FALSE(foo == NULL);  // NOLINT
+  EXPECT_FALSE(foo == "");  // NOLINT
+  EXPECT_FALSE(foo == "bar");  // NOLINT
+  EXPECT_TRUE(foo == "foo");  // NOLINT
+
+  const String bar("x\0y", 3);
+  EXPECT_FALSE(bar == "x");
+}
+
+// Tests String::operator!=().
+TEST(StringTest, NotEquals) {
+  const String null(NULL);
+  EXPECT_FALSE(null != NULL);  // NOLINT
+  EXPECT_TRUE(null != "");  // NOLINT
+  EXPECT_TRUE(null != "bar");  // NOLINT
+
+  const String empty("");
+  EXPECT_TRUE(empty != NULL);  // NOLINT
+  EXPECT_FALSE(empty != "");  // NOLINT
+  EXPECT_TRUE(empty != "bar");  // NOLINT
+
+  const String foo("foo");
+  EXPECT_TRUE(foo != NULL);  // NOLINT
+  EXPECT_TRUE(foo != "");  // NOLINT
+  EXPECT_TRUE(foo != "bar");  // NOLINT
+  EXPECT_FALSE(foo != "foo");  // NOLINT
+
+  const String bar("x\0y", 3);
+  EXPECT_TRUE(bar != "x");
+}
+
+// Tests String::length().
+TEST(StringTest, Length) {
+  EXPECT_EQ(0U, String().length());
+  EXPECT_EQ(0U, String("").length());
+  EXPECT_EQ(2U, String("ab").length());
+  EXPECT_EQ(3U, String("a\0b", 3).length());
+}
+
+// Tests String::EndsWith().
+TEST(StringTest, EndsWith) {
+  EXPECT_TRUE(String("foobar").EndsWith("bar"));
+  EXPECT_TRUE(String("foobar").EndsWith(""));
+  EXPECT_TRUE(String("").EndsWith(""));
+
+  EXPECT_FALSE(String("foobar").EndsWith("foo"));
+  EXPECT_FALSE(String("").EndsWith("foo"));
+}
+
+// Tests String::EndsWithCaseInsensitive().
+TEST(StringTest, EndsWithCaseInsensitive) {
+  EXPECT_TRUE(String("foobar").EndsWithCaseInsensitive("BAR"));
+  EXPECT_TRUE(String("foobaR").EndsWithCaseInsensitive("bar"));
+  EXPECT_TRUE(String("foobar").EndsWithCaseInsensitive(""));
+  EXPECT_TRUE(String("").EndsWithCaseInsensitive(""));
+
+  EXPECT_FALSE(String("Foobar").EndsWithCaseInsensitive("foo"));
+  EXPECT_FALSE(String("foobar").EndsWithCaseInsensitive("Foo"));
+  EXPECT_FALSE(String("").EndsWithCaseInsensitive("foo"));
+}
+
+// C++Builder's preprocessor is buggy; it fails to expand macros that
+// appear in macro parameters after wide char literals.  Provide an alias
+// for NULL as a workaround.
+static const wchar_t* const kNull = NULL;
+
+// Tests String::CaseInsensitiveWideCStringEquals
+TEST(StringTest, CaseInsensitiveWideCStringEquals) {
+  EXPECT_TRUE(String::CaseInsensitiveWideCStringEquals(NULL, NULL));
+  EXPECT_FALSE(String::CaseInsensitiveWideCStringEquals(kNull, L""));
+  EXPECT_FALSE(String::CaseInsensitiveWideCStringEquals(L"", kNull));
+  EXPECT_FALSE(String::CaseInsensitiveWideCStringEquals(kNull, L"foobar"));
+  EXPECT_FALSE(String::CaseInsensitiveWideCStringEquals(L"foobar", kNull));
+  EXPECT_TRUE(String::CaseInsensitiveWideCStringEquals(L"foobar", L"foobar"));
+  EXPECT_TRUE(String::CaseInsensitiveWideCStringEquals(L"foobar", L"FOOBAR"));
+  EXPECT_TRUE(String::CaseInsensitiveWideCStringEquals(L"FOOBAR", L"foobar"));
+}
+
+// Tests that NULL can be assigned to a String.
+TEST(StringTest, CanBeAssignedNULL) {
+  const String src(NULL);
+  String dest;
+
+  dest = src;
+  EXPECT_STREQ(NULL, dest.c_str());
+}
+
+// Tests that the empty string "" can be assigned to a String.
+TEST(StringTest, CanBeAssignedEmpty) {
+  const String src("");
+  String dest;
+
+  dest = src;
+  EXPECT_STREQ("", dest.c_str());
+}
+
+// Tests that a non-empty string can be assigned to a String.
+TEST(StringTest, CanBeAssignedNonEmpty) {
+  const String src("hello");
+  String dest;
+  dest = src;
+  EXPECT_EQ(5U, dest.length());
+  EXPECT_STREQ("hello", dest.c_str());
+
+  const String src2("x\0y", 3);
+  String dest2;
+  dest2 = src2;
+  EXPECT_EQ(3U, dest2.length());
+  EXPECT_EQ('x', dest2.c_str()[0]);
+  EXPECT_EQ('\0', dest2.c_str()[1]);
+  EXPECT_EQ('y', dest2.c_str()[2]);
+}
+
+// Tests that a String can be assigned to itself.
+TEST(StringTest, CanBeAssignedSelf) {
+  String dest("hello");
+
+  // Use explicit function call notation here to suppress self-assign warning.
+  dest.operator=(dest);
+  EXPECT_STREQ("hello", dest.c_str());
+}
+
+// Sun Studio < 12 incorrectly rejects this code due to an overloading
+// ambiguity.
+#if !(defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
+// Tests streaming a String.
+TEST(StringTest, Streams) {
+  EXPECT_EQ(StreamableToString(String()), "(null)");
+  EXPECT_EQ(StreamableToString(String("")), "");
+  EXPECT_EQ(StreamableToString(String("a\0b", 3)), "a\\0b");
+}
+#endif
+
+// Tests that String::Format() works.
+TEST(StringTest, FormatWorks) {
+  // Normal case: the format spec is valid, the arguments match the
+  // spec, and the result is < 4095 characters.
+  EXPECT_STREQ("Hello, 42", String::Format("%s, %d", "Hello", 42).c_str());
+
+  // Edge case: the result is 4095 characters.
+  char buffer[4096];
+  const size_t kSize = sizeof(buffer);
+  memset(buffer, 'a', kSize - 1);
+  buffer[kSize - 1] = '\0';
+  EXPECT_STREQ(buffer, String::Format("%s", buffer).c_str());
+
+  // The result needs to be 4096 characters, exceeding Format()'s limit.
+  EXPECT_STREQ("<formatting error or buffer exceeded>",
+               String::Format("x%s", buffer).c_str());
+
+#if GTEST_OS_LINUX
+  // On Linux, invalid format spec should lead to an error message.
+  // In other environment (e.g. MSVC on Windows), String::Format() may
+  // simply ignore a bad format spec, so this assertion is run on
+  // Linux only.
+  EXPECT_STREQ("<formatting error or buffer exceeded>",
+               String::Format("%").c_str());
+#endif
+}
+
+#if GTEST_OS_WINDOWS
+
+// Tests String::ShowWideCString().
+TEST(StringTest, ShowWideCString) {
+  EXPECT_STREQ("(null)",
+               String::ShowWideCString(NULL).c_str());
+  EXPECT_STREQ("", String::ShowWideCString(L"").c_str());
+  EXPECT_STREQ("foo", String::ShowWideCString(L"foo").c_str());
+}
+
+// Tests String::ShowWideCStringQuoted().
+TEST(StringTest, ShowWideCStringQuoted) {
+  EXPECT_STREQ("(null)",
+               String::ShowWideCStringQuoted(NULL).c_str());
+  EXPECT_STREQ("L\"\"",
+               String::ShowWideCStringQuoted(L"").c_str());
+  EXPECT_STREQ("L\"foo\"",
+               String::ShowWideCStringQuoted(L"foo").c_str());
+}
+
+# if GTEST_OS_WINDOWS_MOBILE
+TEST(StringTest, AnsiAndUtf16Null) {
+  EXPECT_EQ(NULL, String::AnsiToUtf16(NULL));
+  EXPECT_EQ(NULL, String::Utf16ToAnsi(NULL));
+}
+
+TEST(StringTest, AnsiAndUtf16ConvertBasic) {
+  const char* ansi = String::Utf16ToAnsi(L"str");
+  EXPECT_STREQ("str", ansi);
+  delete [] ansi;
+  const WCHAR* utf16 = String::AnsiToUtf16("str");
+  EXPECT_EQ(0, wcsncmp(L"str", utf16, 3));
+  delete [] utf16;
+}
+
+TEST(StringTest, AnsiAndUtf16ConvertPathChars) {
+  const char* ansi = String::Utf16ToAnsi(L".:\\ \"*?");
+  EXPECT_STREQ(".:\\ \"*?", ansi);
+  delete [] ansi;
+  const WCHAR* utf16 = String::AnsiToUtf16(".:\\ \"*?");
+  EXPECT_EQ(0, wcsncmp(L".:\\ \"*?", utf16, 3));
+  delete [] utf16;
+}
+# endif  // GTEST_OS_WINDOWS_MOBILE
+
+#endif  // GTEST_OS_WINDOWS
+
+// Tests TestProperty construction.
+TEST(TestPropertyTest, StringValue) {
+  TestProperty property("key", "1");
+  EXPECT_STREQ("key", property.key());
+  EXPECT_STREQ("1", property.value());
+}
+
+// Tests TestProperty replacing a value.
+TEST(TestPropertyTest, ReplaceStringValue) {
+  TestProperty property("key", "1");
+  EXPECT_STREQ("1", property.value());
+  property.SetValue("2");
+  EXPECT_STREQ("2", property.value());
+}
+
+// AddFatalFailure() and AddNonfatalFailure() must be stand-alone
+// functions (i.e. their definitions cannot be inlined at the call
+// sites), or C++Builder won't compile the code.
+static void AddFatalFailure() {
+  FAIL() << "Expected fatal failure.";
+}
+
+static void AddNonfatalFailure() {
+  ADD_FAILURE() << "Expected non-fatal failure.";
+}
+
+class ScopedFakeTestPartResultReporterTest : public Test {
+ public:  // Must be public and not protected due to a bug in g++ 3.4.2.
+  enum FailureMode {
+    FATAL_FAILURE,
+    NONFATAL_FAILURE
+  };
+  static void AddFailure(FailureMode failure) {
+    if (failure == FATAL_FAILURE) {
+      AddFatalFailure();
+    } else {
+      AddNonfatalFailure();
+    }
+  }
+};
+
+// Tests that ScopedFakeTestPartResultReporter intercepts test
+// failures.
+TEST_F(ScopedFakeTestPartResultReporterTest, InterceptsTestFailures) {
+  TestPartResultArray results;
+  {
+    ScopedFakeTestPartResultReporter reporter(
+        ScopedFakeTestPartResultReporter::INTERCEPT_ONLY_CURRENT_THREAD,
+        &results);
+    AddFailure(NONFATAL_FAILURE);
+    AddFailure(FATAL_FAILURE);
+  }
+
+  EXPECT_EQ(2, results.size());
+  EXPECT_TRUE(results.GetTestPartResult(0).nonfatally_failed());
+  EXPECT_TRUE(results.GetTestPartResult(1).fatally_failed());
+}
+
+TEST_F(ScopedFakeTestPartResultReporterTest, DeprecatedConstructor) {
+  TestPartResultArray results;
+  {
+    // Tests, that the deprecated constructor still works.
+    ScopedFakeTestPartResultReporter reporter(&results);
+    AddFailure(NONFATAL_FAILURE);
+  }
+  EXPECT_EQ(1, results.size());
+}
+
+#if GTEST_IS_THREADSAFE
+
+class ScopedFakeTestPartResultReporterWithThreadsTest
+  : public ScopedFakeTestPartResultReporterTest {
+ protected:
+  static void AddFailureInOtherThread(FailureMode failure) {
+    ThreadWithParam<FailureMode> thread(&AddFailure, failure, NULL);
+    thread.Join();
+  }
+};
+
+TEST_F(ScopedFakeTestPartResultReporterWithThreadsTest,
+       InterceptsTestFailuresInAllThreads) {
+  TestPartResultArray results;
+  {
+    ScopedFakeTestPartResultReporter reporter(
+        ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, &results);
+    AddFailure(NONFATAL_FAILURE);
+    AddFailure(FATAL_FAILURE);
+    AddFailureInOtherThread(NONFATAL_FAILURE);
+    AddFailureInOtherThread(FATAL_FAILURE);
+  }
+
+  EXPECT_EQ(4, results.size());
+  EXPECT_TRUE(results.GetTestPartResult(0).nonfatally_failed());
+  EXPECT_TRUE(results.GetTestPartResult(1).fatally_failed());
+  EXPECT_TRUE(results.GetTestPartResult(2).nonfatally_failed());
+  EXPECT_TRUE(results.GetTestPartResult(3).fatally_failed());
+}
+
+#endif  // GTEST_IS_THREADSAFE
+
+// Tests EXPECT_FATAL_FAILURE{,ON_ALL_THREADS}.  Makes sure that they
+// work even if the failure is generated in a called function rather than
+// the current context.
+
+typedef ScopedFakeTestPartResultReporterTest ExpectFatalFailureTest;
+
+TEST_F(ExpectFatalFailureTest, CatchesFatalFaliure) {
+  EXPECT_FATAL_FAILURE(AddFatalFailure(), "Expected fatal failure.");
+}
+
+#if GTEST_HAS_GLOBAL_STRING
+TEST_F(ExpectFatalFailureTest, AcceptsStringObject) {
+  EXPECT_FATAL_FAILURE(AddFatalFailure(), ::string("Expected fatal failure."));
+}
+#endif
+
+TEST_F(ExpectFatalFailureTest, AcceptsStdStringObject) {
+  EXPECT_FATAL_FAILURE(AddFatalFailure(),
+                       ::std::string("Expected fatal failure."));
+}
+
+TEST_F(ExpectFatalFailureTest, CatchesFatalFailureOnAllThreads) {
+  // We have another test below to verify that the macro catches fatal
+  // failures generated on another thread.
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(AddFatalFailure(),
+                                      "Expected fatal failure.");
+}
+
+#ifdef __BORLANDC__
+// Silences warnings: "Condition is always true"
+# pragma option push -w-ccc
+#endif
+
+// Tests that EXPECT_FATAL_FAILURE() can be used in a non-void
+// function even when the statement in it contains ASSERT_*.
+
+int NonVoidFunction() {
+  EXPECT_FATAL_FAILURE(ASSERT_TRUE(false), "");
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(FAIL(), "");
+  return 0;
+}
+
+TEST_F(ExpectFatalFailureTest, CanBeUsedInNonVoidFunction) {
+  NonVoidFunction();
+}
+
+// Tests that EXPECT_FATAL_FAILURE(statement, ...) doesn't abort the
+// current function even though 'statement' generates a fatal failure.
+
+void DoesNotAbortHelper(bool* aborted) {
+  EXPECT_FATAL_FAILURE(ASSERT_TRUE(false), "");
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(FAIL(), "");
+
+  *aborted = false;
+}
+
+#ifdef __BORLANDC__
+// Restores warnings after previous "#pragma option push" suppressed them.
+# pragma option pop
+#endif
+
+TEST_F(ExpectFatalFailureTest, DoesNotAbort) {
+  bool aborted = true;
+  DoesNotAbortHelper(&aborted);
+  EXPECT_FALSE(aborted);
+}
+
+// Tests that the EXPECT_FATAL_FAILURE{,_ON_ALL_THREADS} accepts a
+// statement that contains a macro which expands to code containing an
+// unprotected comma.
+
+static int global_var = 0;
+#define GTEST_USE_UNPROTECTED_COMMA_ global_var++, global_var++
+
+TEST_F(ExpectFatalFailureTest, AcceptsMacroThatExpandsToUnprotectedComma) {
+#ifndef __BORLANDC__
+  // ICE's in C++Builder.
+  EXPECT_FATAL_FAILURE({
+    GTEST_USE_UNPROTECTED_COMMA_;
+    AddFatalFailure();
+  }, "");
+#endif
+
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS({
+    GTEST_USE_UNPROTECTED_COMMA_;
+    AddFatalFailure();
+  }, "");
+}
+
+// Tests EXPECT_NONFATAL_FAILURE{,ON_ALL_THREADS}.
+
+typedef ScopedFakeTestPartResultReporterTest ExpectNonfatalFailureTest;
+
+TEST_F(ExpectNonfatalFailureTest, CatchesNonfatalFailure) {
+  EXPECT_NONFATAL_FAILURE(AddNonfatalFailure(),
+                          "Expected non-fatal failure.");
+}
+
+#if GTEST_HAS_GLOBAL_STRING
+TEST_F(ExpectNonfatalFailureTest, AcceptsStringObject) {
+  EXPECT_NONFATAL_FAILURE(AddNonfatalFailure(),
+                          ::string("Expected non-fatal failure."));
+}
+#endif
+
+TEST_F(ExpectNonfatalFailureTest, AcceptsStdStringObject) {
+  EXPECT_NONFATAL_FAILURE(AddNonfatalFailure(),
+                          ::std::string("Expected non-fatal failure."));
+}
+
+TEST_F(ExpectNonfatalFailureTest, CatchesNonfatalFailureOnAllThreads) {
+  // We have another test below to verify that the macro catches
+  // non-fatal failures generated on another thread.
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(AddNonfatalFailure(),
+                                         "Expected non-fatal failure.");
+}
+
+// Tests that the EXPECT_NONFATAL_FAILURE{,_ON_ALL_THREADS} accepts a
+// statement that contains a macro which expands to code containing an
+// unprotected comma.
+TEST_F(ExpectNonfatalFailureTest, AcceptsMacroThatExpandsToUnprotectedComma) {
+  EXPECT_NONFATAL_FAILURE({
+    GTEST_USE_UNPROTECTED_COMMA_;
+    AddNonfatalFailure();
+  }, "");
+
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS({
+    GTEST_USE_UNPROTECTED_COMMA_;
+    AddNonfatalFailure();
+  }, "");
+}
+
+#if GTEST_IS_THREADSAFE
+
+typedef ScopedFakeTestPartResultReporterWithThreadsTest
+    ExpectFailureWithThreadsTest;
+
+TEST_F(ExpectFailureWithThreadsTest, ExpectFatalFailureOnAllThreads) {
+  EXPECT_FATAL_FAILURE_ON_ALL_THREADS(AddFailureInOtherThread(FATAL_FAILURE),
+                                      "Expected fatal failure.");
+}
+
+TEST_F(ExpectFailureWithThreadsTest, ExpectNonFatalFailureOnAllThreads) {
+  EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(
+      AddFailureInOtherThread(NONFATAL_FAILURE), "Expected non-fatal failure.");
+}
+
+#endif  // GTEST_IS_THREADSAFE
+
+// Tests the TestProperty class.
+
+TEST(TestPropertyTest, ConstructorWorks) {
+  const TestProperty property("key", "value");
+  EXPECT_STREQ("key", property.key());
+  EXPECT_STREQ("value", property.value());
+}
+
+TEST(TestPropertyTest, SetValue) {
+  TestProperty property("key", "value_1");
+  EXPECT_STREQ("key", property.key());
+  property.SetValue("value_2");
+  EXPECT_STREQ("key", property.key());
+  EXPECT_STREQ("value_2", property.value());
+}
+
+// Tests the TestResult class
+
+// The test fixture for testing TestResult.
+class TestResultTest : public Test {
+ protected:
+  typedef std::vector<TestPartResult> TPRVector;
+
+  // We make use of 2 TestPartResult objects,
+  TestPartResult * pr1, * pr2;
+
+  // ... and 3 TestResult objects.
+  TestResult * r0, * r1, * r2;
+
+  virtual void SetUp() {
+    // pr1 is for success.
+    pr1 = new TestPartResult(TestPartResult::kSuccess,
+                             "foo/bar.cc",
+                             10,
+                             "Success!");
+
+    // pr2 is for fatal failure.
+    pr2 = new TestPartResult(TestPartResult::kFatalFailure,
+                             "foo/bar.cc",
+                             -1,  // This line number means "unknown"
+                             "Failure!");
+
+    // Creates the TestResult objects.
+    r0 = new TestResult();
+    r1 = new TestResult();
+    r2 = new TestResult();
+
+    // In order to test TestResult, we need to modify its internal
+    // state, in particular the TestPartResult vector it holds.
+    // test_part_results() returns a const reference to this vector.
+    // We cast it to a non-const object s.t. it can be modified (yes,
+    // this is a hack).
+    TPRVector* results1 = const_cast<TPRVector*>(
+        &TestResultAccessor::test_part_results(*r1));
+    TPRVector* results2 = const_cast<TPRVector*>(
+        &TestResultAccessor::test_part_results(*r2));
+
+    // r0 is an empty TestResult.
+
+    // r1 contains a single SUCCESS TestPartResult.
+    results1->push_back(*pr1);
+
+    // r2 contains a SUCCESS, and a FAILURE.
+    results2->push_back(*pr1);
+    results2->push_back(*pr2);
+  }
+
+  virtual void TearDown() {
+    delete pr1;
+    delete pr2;
+
+    delete r0;
+    delete r1;
+    delete r2;
+  }
+
+  // Helper that compares two two TestPartResults.
+  static void CompareTestPartResult(const TestPartResult& expected,
+                                    const TestPartResult& actual) {
+    EXPECT_EQ(expected.type(), actual.type());
+    EXPECT_STREQ(expected.file_name(), actual.file_name());
+    EXPECT_EQ(expected.line_number(), actual.line_number());
+    EXPECT_STREQ(expected.summary(), actual.summary());
+    EXPECT_STREQ(expected.message(), actual.message());
+    EXPECT_EQ(expected.passed(), actual.passed());
+    EXPECT_EQ(expected.failed(), actual.failed());
+    EXPECT_EQ(expected.nonfatally_failed(), actual.nonfatally_failed());
+    EXPECT_EQ(expected.fatally_failed(), actual.fatally_failed());
+  }
+};
+
+// Tests TestResult::total_part_count().
+TEST_F(TestResultTest, total_part_count) {
+  ASSERT_EQ(0, r0->total_part_count());
+  ASSERT_EQ(1, r1->total_part_count());
+  ASSERT_EQ(2, r2->total_part_count());
+}
+
+// Tests TestResult::Passed().
+TEST_F(TestResultTest, Passed) {
+  ASSERT_TRUE(r0->Passed());
+  ASSERT_TRUE(r1->Passed());
+  ASSERT_FALSE(r2->Passed());
+}
+
+// Tests TestResult::Failed().
+TEST_F(TestResultTest, Failed) {
+  ASSERT_FALSE(r0->Failed());
+  ASSERT_FALSE(r1->Failed());
+  ASSERT_TRUE(r2->Failed());
+}
+
+// Tests TestResult::GetTestPartResult().
+
+typedef TestResultTest TestResultDeathTest;
+
+TEST_F(TestResultDeathTest, GetTestPartResult) {
+  CompareTestPartResult(*pr1, r2->GetTestPartResult(0));
+  CompareTestPartResult(*pr2, r2->GetTestPartResult(1));
+  EXPECT_DEATH_IF_SUPPORTED(r2->GetTestPartResult(2), "");
+  EXPECT_DEATH_IF_SUPPORTED(r2->GetTestPartResult(-1), "");
+}
+
+// Tests TestResult has no properties when none are added.
+TEST(TestResultPropertyTest, NoPropertiesFoundWhenNoneAreAdded) {
+  TestResult test_result;
+  ASSERT_EQ(0, test_result.test_property_count());
+}
+
+// Tests TestResult has the expected property when added.
+TEST(TestResultPropertyTest, OnePropertyFoundWhenAdded) {
+  TestResult test_result;
+  TestProperty property("key_1", "1");
+  TestResultAccessor::RecordProperty(&test_result, property);
+  ASSERT_EQ(1, test_result.test_property_count());
+  const TestProperty& actual_property = test_result.GetTestProperty(0);
+  EXPECT_STREQ("key_1", actual_property.key());
+  EXPECT_STREQ("1", actual_property.value());
+}
+
+// Tests TestResult has multiple properties when added.
+TEST(TestResultPropertyTest, MultiplePropertiesFoundWhenAdded) {
+  TestResult test_result;
+  TestProperty property_1("key_1", "1");
+  TestProperty property_2("key_2", "2");
+  TestResultAccessor::RecordProperty(&test_result, property_1);
+  TestResultAccessor::RecordProperty(&test_result, property_2);
+  ASSERT_EQ(2, test_result.test_property_count());
+  const TestProperty& actual_property_1 = test_result.GetTestProperty(0);
+  EXPECT_STREQ("key_1", actual_property_1.key());
+  EXPECT_STREQ("1", actual_property_1.value());
+
+  const TestProperty& actual_property_2 = test_result.GetTestProperty(1);
+  EXPECT_STREQ("key_2", actual_property_2.key());
+  EXPECT_STREQ("2", actual_property_2.value());
+}
+
+// Tests TestResult::RecordProperty() overrides values for duplicate keys.
+TEST(TestResultPropertyTest, OverridesValuesForDuplicateKeys) {
+  TestResult test_result;
+  TestProperty property_1_1("key_1", "1");
+  TestProperty property_2_1("key_2", "2");
+  TestProperty property_1_2("key_1", "12");
+  TestProperty property_2_2("key_2", "22");
+  TestResultAccessor::RecordProperty(&test_result, property_1_1);
+  TestResultAccessor::RecordProperty(&test_result, property_2_1);
+  TestResultAccessor::RecordProperty(&test_result, property_1_2);
+  TestResultAccessor::RecordProperty(&test_result, property_2_2);
+
+  ASSERT_EQ(2, test_result.test_property_count());
+  const TestProperty& actual_property_1 = test_result.GetTestProperty(0);
+  EXPECT_STREQ("key_1", actual_property_1.key());
+  EXPECT_STREQ("12", actual_property_1.value());
+
+  const TestProperty& actual_property_2 = test_result.GetTestProperty(1);
+  EXPECT_STREQ("key_2", actual_property_2.key());
+  EXPECT_STREQ("22", actual_property_2.value());
+}
+
+// Tests TestResult::GetTestProperty().
+TEST(TestResultPropertyDeathTest, GetTestProperty) {
+  TestResult test_result;
+  TestProperty property_1("key_1", "1");
+  TestProperty property_2("key_2", "2");
+  TestProperty property_3("key_3", "3");
+  TestResultAccessor::RecordProperty(&test_result, property_1);
+  TestResultAccessor::RecordProperty(&test_result, property_2);
+  TestResultAccessor::RecordProperty(&test_result, property_3);
+
+  const TestProperty& fetched_property_1 = test_result.GetTestProperty(0);
+  const TestProperty& fetched_property_2 = test_result.GetTestProperty(1);
+  const TestProperty& fetched_property_3 = test_result.GetTestProperty(2);
+
+  EXPECT_STREQ("key_1", fetched_property_1.key());
+  EXPECT_STREQ("1", fetched_property_1.value());
+
+  EXPECT_STREQ("key_2", fetched_property_2.key());
+  EXPECT_STREQ("2", fetched_property_2.value());
+
+  EXPECT_STREQ("key_3", fetched_property_3.key());
+  EXPECT_STREQ("3", fetched_property_3.value());
+
+  EXPECT_DEATH_IF_SUPPORTED(test_result.GetTestProperty(3), "");
+  EXPECT_DEATH_IF_SUPPORTED(test_result.GetTestProperty(-1), "");
+}
+
+// When a property using a reserved key is supplied to this function, it tests
+// that a non-fatal failure is added, a fatal failure is not added, and that the
+// property is not recorded.
+void ExpectNonFatalFailureRecordingPropertyWithReservedKey(const char* key) {
+  TestResult test_result;
+  TestProperty property(key, "1");
+  EXPECT_NONFATAL_FAILURE(
+      TestResultAccessor::RecordProperty(&test_result, property),
+      "Reserved key");
+  ASSERT_EQ(0, test_result.test_property_count()) << "Not recorded";
+}
+
+// Attempting to recording a property with the Reserved literal "name"
+// should add a non-fatal failure and the property should not be recorded.
+TEST(TestResultPropertyTest, AddFailureWhenUsingReservedKeyCalledName) {
+  ExpectNonFatalFailureRecordingPropertyWithReservedKey("name");
+}
+
+// Attempting to recording a property with the Reserved literal "status"
+// should add a non-fatal failure and the property should not be recorded.
+TEST(TestResultPropertyTest, AddFailureWhenUsingReservedKeyCalledStatus) {
+  ExpectNonFatalFailureRecordingPropertyWithReservedKey("status");
+}
+
+// Attempting to recording a property with the Reserved literal "time"
+// should add a non-fatal failure and the property should not be recorded.
+TEST(TestResultPropertyTest, AddFailureWhenUsingReservedKeyCalledTime) {
+  ExpectNonFatalFailureRecordingPropertyWithReservedKey("time");
+}
+
+// Attempting to recording a property with the Reserved literal "classname"
+// should add a non-fatal failure and the property should not be recorded.
+TEST(TestResultPropertyTest, AddFailureWhenUsingReservedKeyCalledClassname) {
+  ExpectNonFatalFailureRecordingPropertyWithReservedKey("classname");
+}
+
+// Tests that GTestFlagSaver works on Windows and Mac.
+
+class GTestFlagSaverTest : public Test {
+ protected:
+  // Saves the Google Test flags such that we can restore them later, and
+  // then sets them to their default values.  This will be called
+  // before the first test in this test case is run.
+  static void SetUpTestCase() {
+    saver_ = new GTestFlagSaver;
+
+    GTEST_FLAG(also_run_disabled_tests) = false;
+    GTEST_FLAG(break_on_failure) = false;
+    GTEST_FLAG(catch_exceptions) = false;
+    GTEST_FLAG(death_test_use_fork) = false;
+    GTEST_FLAG(color) = "auto";
+    GTEST_FLAG(filter) = "";
+    GTEST_FLAG(list_tests) = false;
+    GTEST_FLAG(output) = "";
+    GTEST_FLAG(print_time) = true;
+    GTEST_FLAG(random_seed) = 0;
+    GTEST_FLAG(repeat) = 1;
+    GTEST_FLAG(shuffle) = false;
+    GTEST_FLAG(stack_trace_depth) = kMaxStackTraceDepth;
+    GTEST_FLAG(stream_result_to) = "";
+    GTEST_FLAG(throw_on_failure) = false;
+  }
+
+  // Restores the Google Test flags that the tests have modified.  This will
+  // be called after the last test in this test case is run.
+  static void TearDownTestCase() {
+    delete saver_;
+    saver_ = NULL;
+  }
+
+  // Verifies that the Google Test flags have their default values, and then
+  // modifies each of them.
+  void VerifyAndModifyFlags() {
+    EXPECT_FALSE(GTEST_FLAG(also_run_disabled_tests));
+    EXPECT_FALSE(GTEST_FLAG(break_on_failure));
+    EXPECT_FALSE(GTEST_FLAG(catch_exceptions));
+    EXPECT_STREQ("auto", GTEST_FLAG(color).c_str());
+    EXPECT_FALSE(GTEST_FLAG(death_test_use_fork));
+    EXPECT_STREQ("", GTEST_FLAG(filter).c_str());
+    EXPECT_FALSE(GTEST_FLAG(list_tests));
+    EXPECT_STREQ("", GTEST_FLAG(output).c_str());
+    EXPECT_TRUE(GTEST_FLAG(print_time));
+    EXPECT_EQ(0, GTEST_FLAG(random_seed));
+    EXPECT_EQ(1, GTEST_FLAG(repeat));
+    EXPECT_FALSE(GTEST_FLAG(shuffle));
+    EXPECT_EQ(kMaxStackTraceDepth, GTEST_FLAG(stack_trace_depth));
+    EXPECT_STREQ("", GTEST_FLAG(stream_result_to).c_str());
+    EXPECT_FALSE(GTEST_FLAG(throw_on_failure));
+
+    GTEST_FLAG(also_run_disabled_tests) = true;
+    GTEST_FLAG(break_on_failure) = true;
+    GTEST_FLAG(catch_exceptions) = true;
+    GTEST_FLAG(color) = "no";
+    GTEST_FLAG(death_test_use_fork) = true;
+    GTEST_FLAG(filter) = "abc";
+    GTEST_FLAG(list_tests) = true;
+    GTEST_FLAG(output) = "xml:foo.xml";
+    GTEST_FLAG(print_time) = false;
+    GTEST_FLAG(random_seed) = 1;
+    GTEST_FLAG(repeat) = 100;
+    GTEST_FLAG(shuffle) = true;
+    GTEST_FLAG(stack_trace_depth) = 1;
+    GTEST_FLAG(stream_result_to) = "localhost:1234";
+    GTEST_FLAG(throw_on_failure) = true;
+  }
+ private:
+  // For saving Google Test flags during this test case.
+  static GTestFlagSaver* saver_;
+};
+
+GTestFlagSaver* GTestFlagSaverTest::saver_ = NULL;
+
+// Google Test doesn't guarantee the order of tests.  The following two
+// tests are designed to work regardless of their order.
+
+// Modifies the Google Test flags in the test body.
+TEST_F(GTestFlagSaverTest, ModifyGTestFlags) {
+  VerifyAndModifyFlags();
+}
+
+// Verifies that the Google Test flags in the body of the previous test were
+// restored to their original values.
+TEST_F(GTestFlagSaverTest, VerifyGTestFlags) {
+  VerifyAndModifyFlags();
+}
+
+// Sets an environment variable with the given name to the given
+// value.  If the value argument is "", unsets the environment
+// variable.  The caller must ensure that both arguments are not NULL.
+static void SetEnv(const char* name, const char* value) {
+#if GTEST_OS_WINDOWS_MOBILE
+  // Environment variables are not supported on Windows CE.
+  return;
+#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
+  // C++Builder's putenv only stores a pointer to its parameter; we have to
+  // ensure that the string remains valid as long as it might be needed.
+  // We use an std::map to do so.
+  static std::map<String, String*> added_env;
+
+  // Because putenv stores a pointer to the string buffer, we can't delete the
+  // previous string (if present) until after it's replaced.
+  String *prev_env = NULL;
+  if (added_env.find(name) != added_env.end()) {
+    prev_env = added_env[name];
+  }
+  added_env[name] = new String((Message() << name << "=" << value).GetString());
+
+  // The standard signature of putenv accepts a 'char*' argument. Other
+  // implementations, like C++Builder's, accept a 'const char*'.
+  // We cast away the 'const' since that would work for both variants.
+  putenv(const_cast<char*>(added_env[name]->c_str()));
+  delete prev_env;
+#elif GTEST_OS_WINDOWS  // If we are on Windows proper.
+  _putenv((Message() << name << "=" << value).GetString().c_str());
+#else
+  if (*value == '\0') {
+    unsetenv(name);
+  } else {
+    setenv(name, value, 1);
+  }
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+#if !GTEST_OS_WINDOWS_MOBILE
+// Environment variables are not supported on Windows CE.
+
+using testing::internal::Int32FromGTestEnv;
+
+// Tests Int32FromGTestEnv().
+
+// Tests that Int32FromGTestEnv() returns the default value when the
+// environment variable is not set.
+TEST(Int32FromGTestEnvTest, ReturnsDefaultWhenVariableIsNotSet) {
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "");
+  EXPECT_EQ(10, Int32FromGTestEnv("temp", 10));
+}
+
+// Tests that Int32FromGTestEnv() returns the default value when the
+// environment variable overflows as an Int32.
+TEST(Int32FromGTestEnvTest, ReturnsDefaultWhenValueOverflows) {
+  printf("(expecting 2 warnings)\n");
+
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "12345678987654321");
+  EXPECT_EQ(20, Int32FromGTestEnv("temp", 20));
+
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "-12345678987654321");
+  EXPECT_EQ(30, Int32FromGTestEnv("temp", 30));
+}
+
+// Tests that Int32FromGTestEnv() returns the default value when the
+// environment variable does not represent a valid decimal integer.
+TEST(Int32FromGTestEnvTest, ReturnsDefaultWhenValueIsInvalid) {
+  printf("(expecting 2 warnings)\n");
+
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "A1");
+  EXPECT_EQ(40, Int32FromGTestEnv("temp", 40));
+
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "12X");
+  EXPECT_EQ(50, Int32FromGTestEnv("temp", 50));
+}
+
+// Tests that Int32FromGTestEnv() parses and returns the value of the
+// environment variable when it represents a valid decimal integer in
+// the range of an Int32.
+TEST(Int32FromGTestEnvTest, ParsesAndReturnsValidValue) {
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "123");
+  EXPECT_EQ(123, Int32FromGTestEnv("temp", 0));
+
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "-321");
+  EXPECT_EQ(-321, Int32FromGTestEnv("temp", 0));
+}
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Tests ParseInt32Flag().
+
+// Tests that ParseInt32Flag() returns false and doesn't change the
+// output value when the flag has wrong format
+TEST(ParseInt32FlagTest, ReturnsFalseForInvalidFlag) {
+  Int32 value = 123;
+  EXPECT_FALSE(ParseInt32Flag("--a=100", "b", &value));
+  EXPECT_EQ(123, value);
+
+  EXPECT_FALSE(ParseInt32Flag("a=100", "a", &value));
+  EXPECT_EQ(123, value);
+}
+
+// Tests that ParseInt32Flag() returns false and doesn't change the
+// output value when the flag overflows as an Int32.
+TEST(ParseInt32FlagTest, ReturnsDefaultWhenValueOverflows) {
+  printf("(expecting 2 warnings)\n");
+
+  Int32 value = 123;
+  EXPECT_FALSE(ParseInt32Flag("--abc=12345678987654321", "abc", &value));
+  EXPECT_EQ(123, value);
+
+  EXPECT_FALSE(ParseInt32Flag("--abc=-12345678987654321", "abc", &value));
+  EXPECT_EQ(123, value);
+}
+
+// Tests that ParseInt32Flag() returns false and doesn't change the
+// output value when the flag does not represent a valid decimal
+// integer.
+TEST(ParseInt32FlagTest, ReturnsDefaultWhenValueIsInvalid) {
+  printf("(expecting 2 warnings)\n");
+
+  Int32 value = 123;
+  EXPECT_FALSE(ParseInt32Flag("--abc=A1", "abc", &value));
+  EXPECT_EQ(123, value);
+
+  EXPECT_FALSE(ParseInt32Flag("--abc=12X", "abc", &value));
+  EXPECT_EQ(123, value);
+}
+
+// Tests that ParseInt32Flag() parses the value of the flag and
+// returns true when the flag represents a valid decimal integer in
+// the range of an Int32.
+TEST(ParseInt32FlagTest, ParsesAndReturnsValidValue) {
+  Int32 value = 123;
+  EXPECT_TRUE(ParseInt32Flag("--" GTEST_FLAG_PREFIX_ "abc=456", "abc", &value));
+  EXPECT_EQ(456, value);
+
+  EXPECT_TRUE(ParseInt32Flag("--" GTEST_FLAG_PREFIX_ "abc=-789",
+                             "abc", &value));
+  EXPECT_EQ(-789, value);
+}
+
+// Tests that Int32FromEnvOrDie() parses the value of the var or
+// returns the correct default.
+// Environment variables are not supported on Windows CE.
+#if !GTEST_OS_WINDOWS_MOBILE
+TEST(Int32FromEnvOrDieTest, ParsesAndReturnsValidValue) {
+  EXPECT_EQ(333, Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", 333));
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", "123");
+  EXPECT_EQ(123, Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", 333));
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", "-123");
+  EXPECT_EQ(-123, Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", 333));
+}
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Tests that Int32FromEnvOrDie() aborts with an error message
+// if the variable is not an Int32.
+TEST(Int32FromEnvOrDieDeathTest, AbortsOnFailure) {
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "VAR", "xxx");
+  EXPECT_DEATH_IF_SUPPORTED(
+      Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "VAR", 123),
+      ".*");
+}
+
+// Tests that Int32FromEnvOrDie() aborts with an error message
+// if the variable cannot be represnted by an Int32.
+TEST(Int32FromEnvOrDieDeathTest, AbortsOnInt32Overflow) {
+  SetEnv(GTEST_FLAG_PREFIX_UPPER_ "VAR", "1234567891234567891234");
+  EXPECT_DEATH_IF_SUPPORTED(
+      Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "VAR", 123),
+      ".*");
+}
+
+// Tests that ShouldRunTestOnShard() selects all tests
+// where there is 1 shard.
+TEST(ShouldRunTestOnShardTest, IsPartitionWhenThereIsOneShard) {
+  EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 0));
+  EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 1));
+  EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 2));
+  EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 3));
+  EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 4));
+}
+
+class ShouldShardTest : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    index_var_ = GTEST_FLAG_PREFIX_UPPER_ "INDEX";
+    total_var_ = GTEST_FLAG_PREFIX_UPPER_ "TOTAL";
+  }
+
+  virtual void TearDown() {
+    SetEnv(index_var_, "");
+    SetEnv(total_var_, "");
+  }
+
+  const char* index_var_;
+  const char* total_var_;
+};
+
+// Tests that sharding is disabled if neither of the environment variables
+// are set.
+TEST_F(ShouldShardTest, ReturnsFalseWhenNeitherEnvVarIsSet) {
+  SetEnv(index_var_, "");
+  SetEnv(total_var_, "");
+
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, false));
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
+}
+
+// Tests that sharding is not enabled if total_shards  == 1.
+TEST_F(ShouldShardTest, ReturnsFalseWhenTotalShardIsOne) {
+  SetEnv(index_var_, "0");
+  SetEnv(total_var_, "1");
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, false));
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
+}
+
+// Tests that sharding is enabled if total_shards > 1 and
+// we are not in a death test subprocess.
+// Environment variables are not supported on Windows CE.
+#if !GTEST_OS_WINDOWS_MOBILE
+TEST_F(ShouldShardTest, WorksWhenShardEnvVarsAreValid) {
+  SetEnv(index_var_, "4");
+  SetEnv(total_var_, "22");
+  EXPECT_TRUE(ShouldShard(total_var_, index_var_, false));
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
+
+  SetEnv(index_var_, "8");
+  SetEnv(total_var_, "9");
+  EXPECT_TRUE(ShouldShard(total_var_, index_var_, false));
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
+
+  SetEnv(index_var_, "0");
+  SetEnv(total_var_, "9");
+  EXPECT_TRUE(ShouldShard(total_var_, index_var_, false));
+  EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
+}
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Tests that we exit in error if the sharding values are not valid.
+
+typedef ShouldShardTest ShouldShardDeathTest;
+
+TEST_F(ShouldShardDeathTest, AbortsWhenShardingEnvVarsAreInvalid) {
+  SetEnv(index_var_, "4");
+  SetEnv(total_var_, "4");
+  EXPECT_DEATH_IF_SUPPORTED(ShouldShard(total_var_, index_var_, false), ".*");
+
+  SetEnv(index_var_, "4");
+  SetEnv(total_var_, "-2");
+  EXPECT_DEATH_IF_SUPPORTED(ShouldShard(total_var_, index_var_, false), ".*");
+
+  SetEnv(index_var_, "5");
+  SetEnv(total_var_, "");
+  EXPECT_DEATH_IF_SUPPORTED(ShouldShard(total_var_, index_var_, false), ".*");
+
+  SetEnv(index_var_, "");
+  SetEnv(total_var_, "5");
+  EXPECT_DEATH_IF_SUPPORTED(ShouldShard(total_var_, index_var_, false), ".*");
+}
+
+// Tests that ShouldRunTestOnShard is a partition when 5
+// shards are used.
+TEST(ShouldRunTestOnShardTest, IsPartitionWhenThereAreFiveShards) {
+  // Choose an arbitrary number of tests and shards.
+  const int num_tests = 17;
+  const int num_shards = 5;
+
+  // Check partitioning: each test should be on exactly 1 shard.
+  for (int test_id = 0; test_id < num_tests; test_id++) {
+    int prev_selected_shard_index = -1;
+    for (int shard_index = 0; shard_index < num_shards; shard_index++) {
+      if (ShouldRunTestOnShard(num_shards, shard_index, test_id)) {
+        if (prev_selected_shard_index < 0) {
+          prev_selected_shard_index = shard_index;
+        } else {
+          ADD_FAILURE() << "Shard " << prev_selected_shard_index << " and "
+            << shard_index << " are both selected to run test " << test_id;
+        }
+      }
+    }
+  }
+
+  // Check balance: This is not required by the sharding protocol, but is a
+  // desirable property for performance.
+  for (int shard_index = 0; shard_index < num_shards; shard_index++) {
+    int num_tests_on_shard = 0;
+    for (int test_id = 0; test_id < num_tests; test_id++) {
+      num_tests_on_shard +=
+        ShouldRunTestOnShard(num_shards, shard_index, test_id);
+    }
+    EXPECT_GE(num_tests_on_shard, num_tests / num_shards);
+  }
+}
+
+// For the same reason we are not explicitly testing everything in the
+// Test class, there are no separate tests for the following classes
+// (except for some trivial cases):
+//
+//   TestCase, UnitTest, UnitTestResultPrinter.
+//
+// Similarly, there are no separate tests for the following macros:
+//
+//   TEST, TEST_F, RUN_ALL_TESTS
+
+TEST(UnitTestTest, CanGetOriginalWorkingDir) {
+  ASSERT_TRUE(UnitTest::GetInstance()->original_working_dir() != NULL);
+  EXPECT_STRNE(UnitTest::GetInstance()->original_working_dir(), "");
+}
+
+// This group of tests is for predicate assertions (ASSERT_PRED*, etc)
+// of various arities.  They do not attempt to be exhaustive.  Rather,
+// view them as smoke tests that can be easily reviewed and verified.
+// A more complete set of tests for predicate assertions can be found
+// in gtest_pred_impl_unittest.cc.
+
+// First, some predicates and predicate-formatters needed by the tests.
+
+// Returns true iff the argument is an even number.
+bool IsEven(int n) {
+  return (n % 2) == 0;
+}
+
+// A functor that returns true iff the argument is an even number.
+struct IsEvenFunctor {
+  bool operator()(int n) { return IsEven(n); }
+};
+
+// A predicate-formatter function that asserts the argument is an even
+// number.
+AssertionResult AssertIsEven(const char* expr, int n) {
+  if (IsEven(n)) {
+    return AssertionSuccess();
+  }
+
+  Message msg;
+  msg << expr << " evaluates to " << n << ", which is not even.";
+  return AssertionFailure(msg);
+}
+
+// A predicate function that returns AssertionResult for use in
+// EXPECT/ASSERT_TRUE/FALSE.
+AssertionResult ResultIsEven(int n) {
+  if (IsEven(n))
+    return AssertionSuccess() << n << " is even";
+  else
+    return AssertionFailure() << n << " is odd";
+}
+
+// A predicate function that returns AssertionResult but gives no
+// explanation why it succeeds. Needed for testing that
+// EXPECT/ASSERT_FALSE handles such functions correctly.
+AssertionResult ResultIsEvenNoExplanation(int n) {
+  if (IsEven(n))
+    return AssertionSuccess();
+  else
+    return AssertionFailure() << n << " is odd";
+}
+
+// A predicate-formatter functor that asserts the argument is an even
+// number.
+struct AssertIsEvenFunctor {
+  AssertionResult operator()(const char* expr, int n) {
+    return AssertIsEven(expr, n);
+  }
+};
+
+// Returns true iff the sum of the arguments is an even number.
+bool SumIsEven2(int n1, int n2) {
+  return IsEven(n1 + n2);
+}
+
+// A functor that returns true iff the sum of the arguments is an even
+// number.
+struct SumIsEven3Functor {
+  bool operator()(int n1, int n2, int n3) {
+    return IsEven(n1 + n2 + n3);
+  }
+};
+
+// A predicate-formatter function that asserts the sum of the
+// arguments is an even number.
+AssertionResult AssertSumIsEven4(
+    const char* e1, const char* e2, const char* e3, const char* e4,
+    int n1, int n2, int n3, int n4) {
+  const int sum = n1 + n2 + n3 + n4;
+  if (IsEven(sum)) {
+    return AssertionSuccess();
+  }
+
+  Message msg;
+  msg << e1 << " + " << e2 << " + " << e3 << " + " << e4
+      << " (" << n1 << " + " << n2 << " + " << n3 << " + " << n4
+      << ") evaluates to " << sum << ", which is not even.";
+  return AssertionFailure(msg);
+}
+
+// A predicate-formatter functor that asserts the sum of the arguments
+// is an even number.
+struct AssertSumIsEven5Functor {
+  AssertionResult operator()(
+      const char* e1, const char* e2, const char* e3, const char* e4,
+      const char* e5, int n1, int n2, int n3, int n4, int n5) {
+    const int sum = n1 + n2 + n3 + n4 + n5;
+    if (IsEven(sum)) {
+      return AssertionSuccess();
+    }
+
+    Message msg;
+    msg << e1 << " + " << e2 << " + " << e3 << " + " << e4 << " + " << e5
+        << " ("
+        << n1 << " + " << n2 << " + " << n3 << " + " << n4 << " + " << n5
+        << ") evaluates to " << sum << ", which is not even.";
+    return AssertionFailure(msg);
+  }
+};
+
+
+// Tests unary predicate assertions.
+
+// Tests unary predicate assertions that don't use a custom formatter.
+TEST(Pred1Test, WithoutFormat) {
+  // Success cases.
+  EXPECT_PRED1(IsEvenFunctor(), 2) << "This failure is UNEXPECTED!";
+  ASSERT_PRED1(IsEven, 4);
+
+  // Failure cases.
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED1(IsEven, 5) << "This failure is expected.";
+  }, "This failure is expected.");
+  EXPECT_FATAL_FAILURE(ASSERT_PRED1(IsEvenFunctor(), 5),
+                       "evaluates to false");
+}
+
+// Tests unary predicate assertions that use a custom formatter.
+TEST(Pred1Test, WithFormat) {
+  // Success cases.
+  EXPECT_PRED_FORMAT1(AssertIsEven, 2);
+  ASSERT_PRED_FORMAT1(AssertIsEvenFunctor(), 4)
+    << "This failure is UNEXPECTED!";
+
+  // Failure cases.
+  const int n = 5;
+  EXPECT_NONFATAL_FAILURE(EXPECT_PRED_FORMAT1(AssertIsEvenFunctor(), n),
+                          "n evaluates to 5, which is not even.");
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT1(AssertIsEven, 5) << "This failure is expected.";
+  }, "This failure is expected.");
+}
+
+// Tests that unary predicate assertions evaluates their arguments
+// exactly once.
+TEST(Pred1Test, SingleEvaluationOnFailure) {
+  // A success case.
+  static int n = 0;
+  EXPECT_PRED1(IsEven, n++);
+  EXPECT_EQ(1, n) << "The argument is not evaluated exactly once.";
+
+  // A failure case.
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT1(AssertIsEvenFunctor(), n++)
+        << "This failure is expected.";
+  }, "This failure is expected.");
+  EXPECT_EQ(2, n) << "The argument is not evaluated exactly once.";
+}
+
+
+// Tests predicate assertions whose arity is >= 2.
+
+// Tests predicate assertions that don't use a custom formatter.
+TEST(PredTest, WithoutFormat) {
+  // Success cases.
+  ASSERT_PRED2(SumIsEven2, 2, 4) << "This failure is UNEXPECTED!";
+  EXPECT_PRED3(SumIsEven3Functor(), 4, 6, 8);
+
+  // Failure cases.
+  const int n1 = 1;
+  const int n2 = 2;
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED2(SumIsEven2, n1, n2) << "This failure is expected.";
+  }, "This failure is expected.");
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED3(SumIsEven3Functor(), 1, 2, 4);
+  }, "evaluates to false");
+}
+
+// Tests predicate assertions that use a custom formatter.
+TEST(PredTest, WithFormat) {
+  // Success cases.
+  ASSERT_PRED_FORMAT4(AssertSumIsEven4, 4, 6, 8, 10) <<
+    "This failure is UNEXPECTED!";
+  EXPECT_PRED_FORMAT5(AssertSumIsEven5Functor(), 2, 4, 6, 8, 10);
+
+  // Failure cases.
+  const int n1 = 1;
+  const int n2 = 2;
+  const int n3 = 4;
+  const int n4 = 6;
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT4(AssertSumIsEven4, n1, n2, n3, n4);
+  }, "evaluates to 13, which is not even.");
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT5(AssertSumIsEven5Functor(), 1, 2, 4, 6, 8)
+        << "This failure is expected.";
+  }, "This failure is expected.");
+}
+
+// Tests that predicate assertions evaluates their arguments
+// exactly once.
+TEST(PredTest, SingleEvaluationOnFailure) {
+  // A success case.
+  int n1 = 0;
+  int n2 = 0;
+  EXPECT_PRED2(SumIsEven2, n1++, n2++);
+  EXPECT_EQ(1, n1) << "Argument 1 is not evaluated exactly once.";
+  EXPECT_EQ(1, n2) << "Argument 2 is not evaluated exactly once.";
+
+  // Another success case.
+  n1 = n2 = 0;
+  int n3 = 0;
+  int n4 = 0;
+  int n5 = 0;
+  ASSERT_PRED_FORMAT5(AssertSumIsEven5Functor(),
+                      n1++, n2++, n3++, n4++, n5++)
+                        << "This failure is UNEXPECTED!";
+  EXPECT_EQ(1, n1) << "Argument 1 is not evaluated exactly once.";
+  EXPECT_EQ(1, n2) << "Argument 2 is not evaluated exactly once.";
+  EXPECT_EQ(1, n3) << "Argument 3 is not evaluated exactly once.";
+  EXPECT_EQ(1, n4) << "Argument 4 is not evaluated exactly once.";
+  EXPECT_EQ(1, n5) << "Argument 5 is not evaluated exactly once.";
+
+  // A failure case.
+  n1 = n2 = n3 = 0;
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED3(SumIsEven3Functor(), ++n1, n2++, n3++)
+        << "This failure is expected.";
+  }, "This failure is expected.");
+  EXPECT_EQ(1, n1) << "Argument 1 is not evaluated exactly once.";
+  EXPECT_EQ(1, n2) << "Argument 2 is not evaluated exactly once.";
+  EXPECT_EQ(1, n3) << "Argument 3 is not evaluated exactly once.";
+
+  // Another failure case.
+  n1 = n2 = n3 = n4 = 0;
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT4(AssertSumIsEven4, ++n1, n2++, n3++, n4++);
+  }, "evaluates to 1, which is not even.");
+  EXPECT_EQ(1, n1) << "Argument 1 is not evaluated exactly once.";
+  EXPECT_EQ(1, n2) << "Argument 2 is not evaluated exactly once.";
+  EXPECT_EQ(1, n3) << "Argument 3 is not evaluated exactly once.";
+  EXPECT_EQ(1, n4) << "Argument 4 is not evaluated exactly once.";
+}
+
+
+// Some helper functions for testing using overloaded/template
+// functions with ASSERT_PREDn and EXPECT_PREDn.
+
+bool IsPositive(double x) {
+  return x > 0;
+}
+
+template <typename T>
+bool IsNegative(T x) {
+  return x < 0;
+}
+
+template <typename T1, typename T2>
+bool GreaterThan(T1 x1, T2 x2) {
+  return x1 > x2;
+}
+
+// Tests that overloaded functions can be used in *_PRED* as long as
+// their types are explicitly specified.
+TEST(PredicateAssertionTest, AcceptsOverloadedFunction) {
+  // C++Builder requires C-style casts rather than static_cast.
+  EXPECT_PRED1((bool (*)(int))(IsPositive), 5);  // NOLINT
+  ASSERT_PRED1((bool (*)(double))(IsPositive), 6.0);  // NOLINT
+}
+
+// Tests that template functions can be used in *_PRED* as long as
+// their types are explicitly specified.
+TEST(PredicateAssertionTest, AcceptsTemplateFunction) {
+  EXPECT_PRED1(IsNegative<int>, -5);
+  // Makes sure that we can handle templates with more than one
+  // parameter.
+  ASSERT_PRED2((GreaterThan<int, int>), 5, 0);
+}
+
+
+// Some helper functions for testing using overloaded/template
+// functions with ASSERT_PRED_FORMATn and EXPECT_PRED_FORMATn.
+
+AssertionResult IsPositiveFormat(const char* /* expr */, int n) {
+  return n > 0 ? AssertionSuccess() :
+      AssertionFailure(Message() << "Failure");
+}
+
+AssertionResult IsPositiveFormat(const char* /* expr */, double x) {
+  return x > 0 ? AssertionSuccess() :
+      AssertionFailure(Message() << "Failure");
+}
+
+template <typename T>
+AssertionResult IsNegativeFormat(const char* /* expr */, T x) {
+  return x < 0 ? AssertionSuccess() :
+      AssertionFailure(Message() << "Failure");
+}
+
+template <typename T1, typename T2>
+AssertionResult EqualsFormat(const char* /* expr1 */, const char* /* expr2 */,
+                             const T1& x1, const T2& x2) {
+  return x1 == x2 ? AssertionSuccess() :
+      AssertionFailure(Message() << "Failure");
+}
+
+// Tests that overloaded functions can be used in *_PRED_FORMAT*
+// without explicitly specifying their types.
+TEST(PredicateFormatAssertionTest, AcceptsOverloadedFunction) {
+  EXPECT_PRED_FORMAT1(IsPositiveFormat, 5);
+  ASSERT_PRED_FORMAT1(IsPositiveFormat, 6.0);
+}
+
+// Tests that template functions can be used in *_PRED_FORMAT* without
+// explicitly specifying their types.
+TEST(PredicateFormatAssertionTest, AcceptsTemplateFunction) {
+  EXPECT_PRED_FORMAT1(IsNegativeFormat, -5);
+  ASSERT_PRED_FORMAT2(EqualsFormat, 3, 3);
+}
+
+
+// Tests string assertions.
+
+// Tests ASSERT_STREQ with non-NULL arguments.
+TEST(StringAssertionTest, ASSERT_STREQ) {
+  const char * const p1 = "good";
+  ASSERT_STREQ(p1, p1);
+
+  // Let p2 have the same content as p1, but be at a different address.
+  const char p2[] = "good";
+  ASSERT_STREQ(p1, p2);
+
+  EXPECT_FATAL_FAILURE(ASSERT_STREQ("bad", "good"),
+                       "Expected: \"bad\"");
+}
+
+// Tests ASSERT_STREQ with NULL arguments.
+TEST(StringAssertionTest, ASSERT_STREQ_Null) {
+  ASSERT_STREQ(static_cast<const char *>(NULL), NULL);
+  EXPECT_FATAL_FAILURE(ASSERT_STREQ(NULL, "non-null"),
+                       "non-null");
+}
+
+// Tests ASSERT_STREQ with NULL arguments.
+TEST(StringAssertionTest, ASSERT_STREQ_Null2) {
+  EXPECT_FATAL_FAILURE(ASSERT_STREQ("non-null", NULL),
+                       "non-null");
+}
+
+// Tests ASSERT_STRNE.
+TEST(StringAssertionTest, ASSERT_STRNE) {
+  ASSERT_STRNE("hi", "Hi");
+  ASSERT_STRNE("Hi", NULL);
+  ASSERT_STRNE(NULL, "Hi");
+  ASSERT_STRNE("", NULL);
+  ASSERT_STRNE(NULL, "");
+  ASSERT_STRNE("", "Hi");
+  ASSERT_STRNE("Hi", "");
+  EXPECT_FATAL_FAILURE(ASSERT_STRNE("Hi", "Hi"),
+                       "\"Hi\" vs \"Hi\"");
+}
+
+// Tests ASSERT_STRCASEEQ.
+TEST(StringAssertionTest, ASSERT_STRCASEEQ) {
+  ASSERT_STRCASEEQ("hi", "Hi");
+  ASSERT_STRCASEEQ(static_cast<const char *>(NULL), NULL);
+
+  ASSERT_STRCASEEQ("", "");
+  EXPECT_FATAL_FAILURE(ASSERT_STRCASEEQ("Hi", "hi2"),
+                       "(ignoring case)");
+}
+
+// Tests ASSERT_STRCASENE.
+TEST(StringAssertionTest, ASSERT_STRCASENE) {
+  ASSERT_STRCASENE("hi1", "Hi2");
+  ASSERT_STRCASENE("Hi", NULL);
+  ASSERT_STRCASENE(NULL, "Hi");
+  ASSERT_STRCASENE("", NULL);
+  ASSERT_STRCASENE(NULL, "");
+  ASSERT_STRCASENE("", "Hi");
+  ASSERT_STRCASENE("Hi", "");
+  EXPECT_FATAL_FAILURE(ASSERT_STRCASENE("Hi", "hi"),
+                       "(ignoring case)");
+}
+
+// Tests *_STREQ on wide strings.
+TEST(StringAssertionTest, STREQ_Wide) {
+  // NULL strings.
+  ASSERT_STREQ(static_cast<const wchar_t *>(NULL), NULL);
+
+  // Empty strings.
+  ASSERT_STREQ(L"", L"");
+
+  // Non-null vs NULL.
+  EXPECT_NONFATAL_FAILURE(EXPECT_STREQ(L"non-null", NULL),
+                          "non-null");
+
+  // Equal strings.
+  EXPECT_STREQ(L"Hi", L"Hi");
+
+  // Unequal strings.
+  EXPECT_NONFATAL_FAILURE(EXPECT_STREQ(L"abc", L"Abc"),
+                          "Abc");
+
+  // Strings containing wide characters.
+  EXPECT_NONFATAL_FAILURE(EXPECT_STREQ(L"abc\x8119", L"abc\x8120"),
+                          "abc");
+}
+
+// Tests *_STRNE on wide strings.
+TEST(StringAssertionTest, STRNE_Wide) {
+  // NULL strings.
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_STRNE(static_cast<const wchar_t *>(NULL), NULL);
+  }, "");
+
+  // Empty strings.
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRNE(L"", L""),
+                          "L\"\"");
+
+  // Non-null vs NULL.
+  ASSERT_STRNE(L"non-null", NULL);
+
+  // Equal strings.
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRNE(L"Hi", L"Hi"),
+                          "L\"Hi\"");
+
+  // Unequal strings.
+  EXPECT_STRNE(L"abc", L"Abc");
+
+  // Strings containing wide characters.
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRNE(L"abc\x8119", L"abc\x8119"),
+                          "abc");
+}
+
+// Tests for ::testing::IsSubstring().
+
+// Tests that IsSubstring() returns the correct result when the input
+// argument type is const char*.
+TEST(IsSubstringTest, ReturnsCorrectResultForCString) {
+  EXPECT_FALSE(IsSubstring("", "", NULL, "a"));
+  EXPECT_FALSE(IsSubstring("", "", "b", NULL));
+  EXPECT_FALSE(IsSubstring("", "", "needle", "haystack"));
+
+  EXPECT_TRUE(IsSubstring("", "", static_cast<const char*>(NULL), NULL));
+  EXPECT_TRUE(IsSubstring("", "", "needle", "two needles"));
+}
+
+// Tests that IsSubstring() returns the correct result when the input
+// argument type is const wchar_t*.
+TEST(IsSubstringTest, ReturnsCorrectResultForWideCString) {
+  EXPECT_FALSE(IsSubstring("", "", kNull, L"a"));
+  EXPECT_FALSE(IsSubstring("", "", L"b", kNull));
+  EXPECT_FALSE(IsSubstring("", "", L"needle", L"haystack"));
+
+  EXPECT_TRUE(IsSubstring("", "", static_cast<const wchar_t*>(NULL), NULL));
+  EXPECT_TRUE(IsSubstring("", "", L"needle", L"two needles"));
+}
+
+// Tests that IsSubstring() generates the correct message when the input
+// argument type is const char*.
+TEST(IsSubstringTest, GeneratesCorrectMessageForCString) {
+  EXPECT_STREQ("Value of: needle_expr\n"
+               "  Actual: \"needle\"\n"
+               "Expected: a substring of haystack_expr\n"
+               "Which is: \"haystack\"",
+               IsSubstring("needle_expr", "haystack_expr",
+                           "needle", "haystack").failure_message());
+}
+
+// Tests that IsSubstring returns the correct result when the input
+// argument type is ::std::string.
+TEST(IsSubstringTest, ReturnsCorrectResultsForStdString) {
+  EXPECT_TRUE(IsSubstring("", "", std::string("hello"), "ahellob"));
+  EXPECT_FALSE(IsSubstring("", "", "hello", std::string("world")));
+}
+
+#if GTEST_HAS_STD_WSTRING
+// Tests that IsSubstring returns the correct result when the input
+// argument type is ::std::wstring.
+TEST(IsSubstringTest, ReturnsCorrectResultForStdWstring) {
+  EXPECT_TRUE(IsSubstring("", "", ::std::wstring(L"needle"), L"two needles"));
+  EXPECT_FALSE(IsSubstring("", "", L"needle", ::std::wstring(L"haystack")));
+}
+
+// Tests that IsSubstring() generates the correct message when the input
+// argument type is ::std::wstring.
+TEST(IsSubstringTest, GeneratesCorrectMessageForWstring) {
+  EXPECT_STREQ("Value of: needle_expr\n"
+               "  Actual: L\"needle\"\n"
+               "Expected: a substring of haystack_expr\n"
+               "Which is: L\"haystack\"",
+               IsSubstring(
+                   "needle_expr", "haystack_expr",
+                   ::std::wstring(L"needle"), L"haystack").failure_message());
+}
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+// Tests for ::testing::IsNotSubstring().
+
+// Tests that IsNotSubstring() returns the correct result when the input
+// argument type is const char*.
+TEST(IsNotSubstringTest, ReturnsCorrectResultForCString) {
+  EXPECT_TRUE(IsNotSubstring("", "", "needle", "haystack"));
+  EXPECT_FALSE(IsNotSubstring("", "", "needle", "two needles"));
+}
+
+// Tests that IsNotSubstring() returns the correct result when the input
+// argument type is const wchar_t*.
+TEST(IsNotSubstringTest, ReturnsCorrectResultForWideCString) {
+  EXPECT_TRUE(IsNotSubstring("", "", L"needle", L"haystack"));
+  EXPECT_FALSE(IsNotSubstring("", "", L"needle", L"two needles"));
+}
+
+// Tests that IsNotSubstring() generates the correct message when the input
+// argument type is const wchar_t*.
+TEST(IsNotSubstringTest, GeneratesCorrectMessageForWideCString) {
+  EXPECT_STREQ("Value of: needle_expr\n"
+               "  Actual: L\"needle\"\n"
+               "Expected: not a substring of haystack_expr\n"
+               "Which is: L\"two needles\"",
+               IsNotSubstring(
+                   "needle_expr", "haystack_expr",
+                   L"needle", L"two needles").failure_message());
+}
+
+// Tests that IsNotSubstring returns the correct result when the input
+// argument type is ::std::string.
+TEST(IsNotSubstringTest, ReturnsCorrectResultsForStdString) {
+  EXPECT_FALSE(IsNotSubstring("", "", std::string("hello"), "ahellob"));
+  EXPECT_TRUE(IsNotSubstring("", "", "hello", std::string("world")));
+}
+
+// Tests that IsNotSubstring() generates the correct message when the input
+// argument type is ::std::string.
+TEST(IsNotSubstringTest, GeneratesCorrectMessageForStdString) {
+  EXPECT_STREQ("Value of: needle_expr\n"
+               "  Actual: \"needle\"\n"
+               "Expected: not a substring of haystack_expr\n"
+               "Which is: \"two needles\"",
+               IsNotSubstring(
+                   "needle_expr", "haystack_expr",
+                   ::std::string("needle"), "two needles").failure_message());
+}
+
+#if GTEST_HAS_STD_WSTRING
+
+// Tests that IsNotSubstring returns the correct result when the input
+// argument type is ::std::wstring.
+TEST(IsNotSubstringTest, ReturnsCorrectResultForStdWstring) {
+  EXPECT_FALSE(
+      IsNotSubstring("", "", ::std::wstring(L"needle"), L"two needles"));
+  EXPECT_TRUE(IsNotSubstring("", "", L"needle", ::std::wstring(L"haystack")));
+}
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+// Tests floating-point assertions.
+
+template <typename RawType>
+class FloatingPointTest : public Test {
+ protected:
+
+  // Pre-calculated numbers to be used by the tests.
+  struct TestValues {
+    RawType close_to_positive_zero;
+    RawType close_to_negative_zero;
+    RawType further_from_negative_zero;
+
+    RawType close_to_one;
+    RawType further_from_one;
+
+    RawType infinity;
+    RawType close_to_infinity;
+    RawType further_from_infinity;
+
+    RawType nan1;
+    RawType nan2;
+  };
+
+  typedef typename testing::internal::FloatingPoint<RawType> Floating;
+  typedef typename Floating::Bits Bits;
+
+  virtual void SetUp() {
+    const size_t max_ulps = Floating::kMaxUlps;
+
+    // The bits that represent 0.0.
+    const Bits zero_bits = Floating(0).bits();
+
+    // Makes some numbers close to 0.0.
+    values_.close_to_positive_zero = Floating::ReinterpretBits(
+        zero_bits + max_ulps/2);
+    values_.close_to_negative_zero = -Floating::ReinterpretBits(
+        zero_bits + max_ulps - max_ulps/2);
+    values_.further_from_negative_zero = -Floating::ReinterpretBits(
+        zero_bits + max_ulps + 1 - max_ulps/2);
+
+    // The bits that represent 1.0.
+    const Bits one_bits = Floating(1).bits();
+
+    // Makes some numbers close to 1.0.
+    values_.close_to_one = Floating::ReinterpretBits(one_bits + max_ulps);
+    values_.further_from_one = Floating::ReinterpretBits(
+        one_bits + max_ulps + 1);
+
+    // +infinity.
+    values_.infinity = Floating::Infinity();
+
+    // The bits that represent +infinity.
+    const Bits infinity_bits = Floating(values_.infinity).bits();
+
+    // Makes some numbers close to infinity.
+    values_.close_to_infinity = Floating::ReinterpretBits(
+        infinity_bits - max_ulps);
+    values_.further_from_infinity = Floating::ReinterpretBits(
+        infinity_bits - max_ulps - 1);
+
+    // Makes some NAN's.  Sets the most significant bit of the fraction so that
+    // our NaN's are quiet; trying to process a signaling NaN would raise an
+    // exception if our environment enables floating point exceptions.
+    values_.nan1 = Floating::ReinterpretBits(Floating::kExponentBitMask
+        | (static_cast<Bits>(1) << (Floating::kFractionBitCount - 1)) | 1);
+    values_.nan2 = Floating::ReinterpretBits(Floating::kExponentBitMask
+        | (static_cast<Bits>(1) << (Floating::kFractionBitCount - 1)) | 200);
+  }
+
+  void TestSize() {
+    EXPECT_EQ(sizeof(RawType), sizeof(Bits));
+  }
+
+  static TestValues values_;
+};
+
+template <typename RawType>
+typename FloatingPointTest<RawType>::TestValues
+    FloatingPointTest<RawType>::values_;
+
+// Instantiates FloatingPointTest for testing *_FLOAT_EQ.
+typedef FloatingPointTest<float> FloatTest;
+
+// Tests that the size of Float::Bits matches the size of float.
+TEST_F(FloatTest, Size) {
+  TestSize();
+}
+
+// Tests comparing with +0 and -0.
+TEST_F(FloatTest, Zeros) {
+  EXPECT_FLOAT_EQ(0.0, -0.0);
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(-0.0, 1.0),
+                          "1.0");
+  EXPECT_FATAL_FAILURE(ASSERT_FLOAT_EQ(0.0, 1.5),
+                       "1.5");
+}
+
+// Tests comparing numbers close to 0.
+//
+// This ensures that *_FLOAT_EQ handles the sign correctly and no
+// overflow occurs when comparing numbers whose absolute value is very
+// small.
+TEST_F(FloatTest, AlmostZeros) {
+  // In C++Builder, names within local classes (such as used by
+  // EXPECT_FATAL_FAILURE) cannot be resolved against static members of the
+  // scoping class.  Use a static local alias as a workaround.
+  // We use the assignment syntax since some compilers, like Sun Studio,
+  // don't allow initializing references using construction syntax
+  // (parentheses).
+  static const FloatTest::TestValues& v = this->values_;
+
+  EXPECT_FLOAT_EQ(0.0, v.close_to_positive_zero);
+  EXPECT_FLOAT_EQ(-0.0, v.close_to_negative_zero);
+  EXPECT_FLOAT_EQ(v.close_to_positive_zero, v.close_to_negative_zero);
+
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_FLOAT_EQ(v.close_to_positive_zero,
+                    v.further_from_negative_zero);
+  }, "v.further_from_negative_zero");
+}
+
+// Tests comparing numbers close to each other.
+TEST_F(FloatTest, SmallDiff) {
+  EXPECT_FLOAT_EQ(1.0, values_.close_to_one);
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(1.0, values_.further_from_one),
+                          "values_.further_from_one");
+}
+
+// Tests comparing numbers far apart.
+TEST_F(FloatTest, LargeDiff) {
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(2.5, 3.0),
+                          "3.0");
+}
+
+// Tests comparing with infinity.
+//
+// This ensures that no overflow occurs when comparing numbers whose
+// absolute value is very large.
+TEST_F(FloatTest, Infinity) {
+  EXPECT_FLOAT_EQ(values_.infinity, values_.close_to_infinity);
+  EXPECT_FLOAT_EQ(-values_.infinity, -values_.close_to_infinity);
+#if !GTEST_OS_SYMBIAN
+  // Nokia's STLport crashes if we try to output infinity or NaN.
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(values_.infinity, -values_.infinity),
+                          "-values_.infinity");
+
+  // This is interesting as the representations of infinity and nan1
+  // are only 1 DLP apart.
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(values_.infinity, values_.nan1),
+                          "values_.nan1");
+#endif  // !GTEST_OS_SYMBIAN
+}
+
+// Tests that comparing with NAN always returns false.
+TEST_F(FloatTest, NaN) {
+#if !GTEST_OS_SYMBIAN
+// Nokia's STLport crashes if we try to output infinity or NaN.
+
+  // In C++Builder, names within local classes (such as used by
+  // EXPECT_FATAL_FAILURE) cannot be resolved against static members of the
+  // scoping class.  Use a static local alias as a workaround.
+  // We use the assignment syntax since some compilers, like Sun Studio,
+  // don't allow initializing references using construction syntax
+  // (parentheses).
+  static const FloatTest::TestValues& v = this->values_;
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(v.nan1, v.nan1),
+                          "v.nan1");
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(v.nan1, v.nan2),
+                          "v.nan2");
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(1.0, v.nan1),
+                          "v.nan1");
+
+  EXPECT_FATAL_FAILURE(ASSERT_FLOAT_EQ(v.nan1, v.infinity),
+                       "v.infinity");
+#endif  // !GTEST_OS_SYMBIAN
+}
+
+// Tests that *_FLOAT_EQ are reflexive.
+TEST_F(FloatTest, Reflexive) {
+  EXPECT_FLOAT_EQ(0.0, 0.0);
+  EXPECT_FLOAT_EQ(1.0, 1.0);
+  ASSERT_FLOAT_EQ(values_.infinity, values_.infinity);
+}
+
+// Tests that *_FLOAT_EQ are commutative.
+TEST_F(FloatTest, Commutative) {
+  // We already tested EXPECT_FLOAT_EQ(1.0, values_.close_to_one).
+  EXPECT_FLOAT_EQ(values_.close_to_one, 1.0);
+
+  // We already tested EXPECT_FLOAT_EQ(1.0, values_.further_from_one).
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(values_.further_from_one, 1.0),
+                          "1.0");
+}
+
+// Tests EXPECT_NEAR.
+TEST_F(FloatTest, EXPECT_NEAR) {
+  EXPECT_NEAR(-1.0f, -1.1f, 0.2f);
+  EXPECT_NEAR(2.0f, 3.0f, 1.0f);
+  EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0f,1.5f, 0.25f),  // NOLINT
+                          "The difference between 1.0f and 1.5f is 0.5, "
+                          "which exceeds 0.25f");
+  // To work around a bug in gcc 2.95.0, there is intentionally no
+  // space after the first comma in the previous line.
+}
+
+// Tests ASSERT_NEAR.
+TEST_F(FloatTest, ASSERT_NEAR) {
+  ASSERT_NEAR(-1.0f, -1.1f, 0.2f);
+  ASSERT_NEAR(2.0f, 3.0f, 1.0f);
+  EXPECT_FATAL_FAILURE(ASSERT_NEAR(1.0f,1.5f, 0.25f),  // NOLINT
+                       "The difference between 1.0f and 1.5f is 0.5, "
+                       "which exceeds 0.25f");
+  // To work around a bug in gcc 2.95.0, there is intentionally no
+  // space after the first comma in the previous line.
+}
+
+// Tests the cases where FloatLE() should succeed.
+TEST_F(FloatTest, FloatLESucceeds) {
+  EXPECT_PRED_FORMAT2(FloatLE, 1.0f, 2.0f);  // When val1 < val2,
+  ASSERT_PRED_FORMAT2(FloatLE, 1.0f, 1.0f);  // val1 == val2,
+
+  // or when val1 is greater than, but almost equals to, val2.
+  EXPECT_PRED_FORMAT2(FloatLE, values_.close_to_positive_zero, 0.0f);
+}
+
+// Tests the cases where FloatLE() should fail.
+TEST_F(FloatTest, FloatLEFails) {
+  // When val1 is greater than val2 by a large margin,
+  EXPECT_NONFATAL_FAILURE(EXPECT_PRED_FORMAT2(FloatLE, 2.0f, 1.0f),
+                          "(2.0f) <= (1.0f)");
+
+  // or by a small yet non-negligible margin,
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT2(FloatLE, values_.further_from_one, 1.0f);
+  }, "(values_.further_from_one) <= (1.0f)");
+
+#if !GTEST_OS_SYMBIAN && !defined(__BORLANDC__)
+  // Nokia's STLport crashes if we try to output infinity or NaN.
+  // C++Builder gives bad results for ordered comparisons involving NaNs
+  // due to compiler bugs.
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT2(FloatLE, values_.nan1, values_.infinity);
+  }, "(values_.nan1) <= (values_.infinity)");
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT2(FloatLE, -values_.infinity, values_.nan1);
+  }, "(-values_.infinity) <= (values_.nan1)");
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT2(FloatLE, values_.nan1, values_.nan1);
+  }, "(values_.nan1) <= (values_.nan1)");
+#endif  // !GTEST_OS_SYMBIAN && !defined(__BORLANDC__)
+}
+
+// Instantiates FloatingPointTest for testing *_DOUBLE_EQ.
+typedef FloatingPointTest<double> DoubleTest;
+
+// Tests that the size of Double::Bits matches the size of double.
+TEST_F(DoubleTest, Size) {
+  TestSize();
+}
+
+// Tests comparing with +0 and -0.
+TEST_F(DoubleTest, Zeros) {
+  EXPECT_DOUBLE_EQ(0.0, -0.0);
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(-0.0, 1.0),
+                          "1.0");
+  EXPECT_FATAL_FAILURE(ASSERT_DOUBLE_EQ(0.0, 1.0),
+                       "1.0");
+}
+
+// Tests comparing numbers close to 0.
+//
+// This ensures that *_DOUBLE_EQ handles the sign correctly and no
+// overflow occurs when comparing numbers whose absolute value is very
+// small.
+TEST_F(DoubleTest, AlmostZeros) {
+  // In C++Builder, names within local classes (such as used by
+  // EXPECT_FATAL_FAILURE) cannot be resolved against static members of the
+  // scoping class.  Use a static local alias as a workaround.
+  // We use the assignment syntax since some compilers, like Sun Studio,
+  // don't allow initializing references using construction syntax
+  // (parentheses).
+  static const DoubleTest::TestValues& v = this->values_;
+
+  EXPECT_DOUBLE_EQ(0.0, v.close_to_positive_zero);
+  EXPECT_DOUBLE_EQ(-0.0, v.close_to_negative_zero);
+  EXPECT_DOUBLE_EQ(v.close_to_positive_zero, v.close_to_negative_zero);
+
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_DOUBLE_EQ(v.close_to_positive_zero,
+                     v.further_from_negative_zero);
+  }, "v.further_from_negative_zero");
+}
+
+// Tests comparing numbers close to each other.
+TEST_F(DoubleTest, SmallDiff) {
+  EXPECT_DOUBLE_EQ(1.0, values_.close_to_one);
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(1.0, values_.further_from_one),
+                          "values_.further_from_one");
+}
+
+// Tests comparing numbers far apart.
+TEST_F(DoubleTest, LargeDiff) {
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(2.0, 3.0),
+                          "3.0");
+}
+
+// Tests comparing with infinity.
+//
+// This ensures that no overflow occurs when comparing numbers whose
+// absolute value is very large.
+TEST_F(DoubleTest, Infinity) {
+  EXPECT_DOUBLE_EQ(values_.infinity, values_.close_to_infinity);
+  EXPECT_DOUBLE_EQ(-values_.infinity, -values_.close_to_infinity);
+#if !GTEST_OS_SYMBIAN
+  // Nokia's STLport crashes if we try to output infinity or NaN.
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(values_.infinity, -values_.infinity),
+                          "-values_.infinity");
+
+  // This is interesting as the representations of infinity_ and nan1_
+  // are only 1 DLP apart.
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(values_.infinity, values_.nan1),
+                          "values_.nan1");
+#endif  // !GTEST_OS_SYMBIAN
+}
+
+// Tests that comparing with NAN always returns false.
+TEST_F(DoubleTest, NaN) {
+#if !GTEST_OS_SYMBIAN
+  // In C++Builder, names within local classes (such as used by
+  // EXPECT_FATAL_FAILURE) cannot be resolved against static members of the
+  // scoping class.  Use a static local alias as a workaround.
+  // We use the assignment syntax since some compilers, like Sun Studio,
+  // don't allow initializing references using construction syntax
+  // (parentheses).
+  static const DoubleTest::TestValues& v = this->values_;
+
+  // Nokia's STLport crashes if we try to output infinity or NaN.
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(v.nan1, v.nan1),
+                          "v.nan1");
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(v.nan1, v.nan2), "v.nan2");
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(1.0, v.nan1), "v.nan1");
+  EXPECT_FATAL_FAILURE(ASSERT_DOUBLE_EQ(v.nan1, v.infinity),
+                       "v.infinity");
+#endif  // !GTEST_OS_SYMBIAN
+}
+
+// Tests that *_DOUBLE_EQ are reflexive.
+TEST_F(DoubleTest, Reflexive) {
+  EXPECT_DOUBLE_EQ(0.0, 0.0);
+  EXPECT_DOUBLE_EQ(1.0, 1.0);
+#if !GTEST_OS_SYMBIAN
+  // Nokia's STLport crashes if we try to output infinity or NaN.
+  ASSERT_DOUBLE_EQ(values_.infinity, values_.infinity);
+#endif  // !GTEST_OS_SYMBIAN
+}
+
+// Tests that *_DOUBLE_EQ are commutative.
+TEST_F(DoubleTest, Commutative) {
+  // We already tested EXPECT_DOUBLE_EQ(1.0, values_.close_to_one).
+  EXPECT_DOUBLE_EQ(values_.close_to_one, 1.0);
+
+  // We already tested EXPECT_DOUBLE_EQ(1.0, values_.further_from_one).
+  EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(values_.further_from_one, 1.0),
+                          "1.0");
+}
+
+// Tests EXPECT_NEAR.
+TEST_F(DoubleTest, EXPECT_NEAR) {
+  EXPECT_NEAR(-1.0, -1.1, 0.2);
+  EXPECT_NEAR(2.0, 3.0, 1.0);
+  EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0, 1.5, 0.25),  // NOLINT
+                          "The difference between 1.0 and 1.5 is 0.5, "
+                          "which exceeds 0.25");
+  // To work around a bug in gcc 2.95.0, there is intentionally no
+  // space after the first comma in the previous statement.
+}
+
+// Tests ASSERT_NEAR.
+TEST_F(DoubleTest, ASSERT_NEAR) {
+  ASSERT_NEAR(-1.0, -1.1, 0.2);
+  ASSERT_NEAR(2.0, 3.0, 1.0);
+  EXPECT_FATAL_FAILURE(ASSERT_NEAR(1.0, 1.5, 0.25),  // NOLINT
+                       "The difference between 1.0 and 1.5 is 0.5, "
+                       "which exceeds 0.25");
+  // To work around a bug in gcc 2.95.0, there is intentionally no
+  // space after the first comma in the previous statement.
+}
+
+// Tests the cases where DoubleLE() should succeed.
+TEST_F(DoubleTest, DoubleLESucceeds) {
+  EXPECT_PRED_FORMAT2(DoubleLE, 1.0, 2.0);  // When val1 < val2,
+  ASSERT_PRED_FORMAT2(DoubleLE, 1.0, 1.0);  // val1 == val2,
+
+  // or when val1 is greater than, but almost equals to, val2.
+  EXPECT_PRED_FORMAT2(DoubleLE, values_.close_to_positive_zero, 0.0);
+}
+
+// Tests the cases where DoubleLE() should fail.
+TEST_F(DoubleTest, DoubleLEFails) {
+  // When val1 is greater than val2 by a large margin,
+  EXPECT_NONFATAL_FAILURE(EXPECT_PRED_FORMAT2(DoubleLE, 2.0, 1.0),
+                          "(2.0) <= (1.0)");
+
+  // or by a small yet non-negligible margin,
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT2(DoubleLE, values_.further_from_one, 1.0);
+  }, "(values_.further_from_one) <= (1.0)");
+
+#if !GTEST_OS_SYMBIAN && !defined(__BORLANDC__)
+  // Nokia's STLport crashes if we try to output infinity or NaN.
+  // C++Builder gives bad results for ordered comparisons involving NaNs
+  // due to compiler bugs.
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT2(DoubleLE, values_.nan1, values_.infinity);
+  }, "(values_.nan1) <= (values_.infinity)");
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_PRED_FORMAT2(DoubleLE, -values_.infinity, values_.nan1);
+  }, " (-values_.infinity) <= (values_.nan1)");
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_PRED_FORMAT2(DoubleLE, values_.nan1, values_.nan1);
+  }, "(values_.nan1) <= (values_.nan1)");
+#endif  // !GTEST_OS_SYMBIAN && !defined(__BORLANDC__)
+}
+
+
+// Verifies that a test or test case whose name starts with DISABLED_ is
+// not run.
+
+// A test whose name starts with DISABLED_.
+// Should not run.
+TEST(DisabledTest, DISABLED_TestShouldNotRun) {
+  FAIL() << "Unexpected failure: Disabled test should not be run.";
+}
+
+// A test whose name does not start with DISABLED_.
+// Should run.
+TEST(DisabledTest, NotDISABLED_TestShouldRun) {
+  EXPECT_EQ(1, 1);
+}
+
+// A test case whose name starts with DISABLED_.
+// Should not run.
+TEST(DISABLED_TestCase, TestShouldNotRun) {
+  FAIL() << "Unexpected failure: Test in disabled test case should not be run.";
+}
+
+// A test case and test whose names start with DISABLED_.
+// Should not run.
+TEST(DISABLED_TestCase, DISABLED_TestShouldNotRun) {
+  FAIL() << "Unexpected failure: Test in disabled test case should not be run.";
+}
+
+// Check that when all tests in a test case are disabled, SetupTestCase() and
+// TearDownTestCase() are not called.
+class DisabledTestsTest : public Test {
+ protected:
+  static void SetUpTestCase() {
+    FAIL() << "Unexpected failure: All tests disabled in test case. "
+              "SetupTestCase() should not be called.";
+  }
+
+  static void TearDownTestCase() {
+    FAIL() << "Unexpected failure: All tests disabled in test case. "
+              "TearDownTestCase() should not be called.";
+  }
+};
+
+TEST_F(DisabledTestsTest, DISABLED_TestShouldNotRun_1) {
+  FAIL() << "Unexpected failure: Disabled test should not be run.";
+}
+
+TEST_F(DisabledTestsTest, DISABLED_TestShouldNotRun_2) {
+  FAIL() << "Unexpected failure: Disabled test should not be run.";
+}
+
+// Tests that disabled typed tests aren't run.
+
+#if GTEST_HAS_TYPED_TEST
+
+template <typename T>
+class TypedTest : public Test {
+};
+
+typedef testing::Types<int, double> NumericTypes;
+TYPED_TEST_CASE(TypedTest, NumericTypes);
+
+TYPED_TEST(TypedTest, DISABLED_ShouldNotRun) {
+  FAIL() << "Unexpected failure: Disabled typed test should not run.";
+}
+
+template <typename T>
+class DISABLED_TypedTest : public Test {
+};
+
+TYPED_TEST_CASE(DISABLED_TypedTest, NumericTypes);
+
+TYPED_TEST(DISABLED_TypedTest, ShouldNotRun) {
+  FAIL() << "Unexpected failure: Disabled typed test should not run.";
+}
+
+#endif  // GTEST_HAS_TYPED_TEST
+
+// Tests that disabled type-parameterized tests aren't run.
+
+#if GTEST_HAS_TYPED_TEST_P
+
+template <typename T>
+class TypedTestP : public Test {
+};
+
+TYPED_TEST_CASE_P(TypedTestP);
+
+TYPED_TEST_P(TypedTestP, DISABLED_ShouldNotRun) {
+  FAIL() << "Unexpected failure: "
+         << "Disabled type-parameterized test should not run.";
+}
+
+REGISTER_TYPED_TEST_CASE_P(TypedTestP, DISABLED_ShouldNotRun);
+
+INSTANTIATE_TYPED_TEST_CASE_P(My, TypedTestP, NumericTypes);
+
+template <typename T>
+class DISABLED_TypedTestP : public Test {
+};
+
+TYPED_TEST_CASE_P(DISABLED_TypedTestP);
+
+TYPED_TEST_P(DISABLED_TypedTestP, ShouldNotRun) {
+  FAIL() << "Unexpected failure: "
+         << "Disabled type-parameterized test should not run.";
+}
+
+REGISTER_TYPED_TEST_CASE_P(DISABLED_TypedTestP, ShouldNotRun);
+
+INSTANTIATE_TYPED_TEST_CASE_P(My, DISABLED_TypedTestP, NumericTypes);
+
+#endif  // GTEST_HAS_TYPED_TEST_P
+
+// Tests that assertion macros evaluate their arguments exactly once.
+
+class SingleEvaluationTest : public Test {
+ public:  // Must be public and not protected due to a bug in g++ 3.4.2.
+  // This helper function is needed by the FailedASSERT_STREQ test
+  // below.  It's public to work around C++Builder's bug with scoping local
+  // classes.
+  static void CompareAndIncrementCharPtrs() {
+    ASSERT_STREQ(p1_++, p2_++);
+  }
+
+  // This helper function is needed by the FailedASSERT_NE test below.  It's
+  // public to work around C++Builder's bug with scoping local classes.
+  static void CompareAndIncrementInts() {
+    ASSERT_NE(a_++, b_++);
+  }
+
+ protected:
+  SingleEvaluationTest() {
+    p1_ = s1_;
+    p2_ = s2_;
+    a_ = 0;
+    b_ = 0;
+  }
+
+  static const char* const s1_;
+  static const char* const s2_;
+  static const char* p1_;
+  static const char* p2_;
+
+  static int a_;
+  static int b_;
+};
+
+const char* const SingleEvaluationTest::s1_ = "01234";
+const char* const SingleEvaluationTest::s2_ = "abcde";
+const char* SingleEvaluationTest::p1_;
+const char* SingleEvaluationTest::p2_;
+int SingleEvaluationTest::a_;
+int SingleEvaluationTest::b_;
+
+// Tests that when ASSERT_STREQ fails, it evaluates its arguments
+// exactly once.
+TEST_F(SingleEvaluationTest, FailedASSERT_STREQ) {
+  EXPECT_FATAL_FAILURE(SingleEvaluationTest::CompareAndIncrementCharPtrs(),
+                       "p2_++");
+  EXPECT_EQ(s1_ + 1, p1_);
+  EXPECT_EQ(s2_ + 1, p2_);
+}
+
+// Tests that string assertion arguments are evaluated exactly once.
+TEST_F(SingleEvaluationTest, ASSERT_STR) {
+  // successful EXPECT_STRNE
+  EXPECT_STRNE(p1_++, p2_++);
+  EXPECT_EQ(s1_ + 1, p1_);
+  EXPECT_EQ(s2_ + 1, p2_);
+
+  // failed EXPECT_STRCASEEQ
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRCASEEQ(p1_++, p2_++),
+                          "ignoring case");
+  EXPECT_EQ(s1_ + 2, p1_);
+  EXPECT_EQ(s2_ + 2, p2_);
+}
+
+// Tests that when ASSERT_NE fails, it evaluates its arguments exactly
+// once.
+TEST_F(SingleEvaluationTest, FailedASSERT_NE) {
+  EXPECT_FATAL_FAILURE(SingleEvaluationTest::CompareAndIncrementInts(),
+                       "(a_++) != (b_++)");
+  EXPECT_EQ(1, a_);
+  EXPECT_EQ(1, b_);
+}
+
+// Tests that assertion arguments are evaluated exactly once.
+TEST_F(SingleEvaluationTest, OtherCases) {
+  // successful EXPECT_TRUE
+  EXPECT_TRUE(0 == a_++);  // NOLINT
+  EXPECT_EQ(1, a_);
+
+  // failed EXPECT_TRUE
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(-1 == a_++), "-1 == a_++");
+  EXPECT_EQ(2, a_);
+
+  // successful EXPECT_GT
+  EXPECT_GT(a_++, b_++);
+  EXPECT_EQ(3, a_);
+  EXPECT_EQ(1, b_);
+
+  // failed EXPECT_LT
+  EXPECT_NONFATAL_FAILURE(EXPECT_LT(a_++, b_++), "(a_++) < (b_++)");
+  EXPECT_EQ(4, a_);
+  EXPECT_EQ(2, b_);
+
+  // successful ASSERT_TRUE
+  ASSERT_TRUE(0 < a_++);  // NOLINT
+  EXPECT_EQ(5, a_);
+
+  // successful ASSERT_GT
+  ASSERT_GT(a_++, b_++);
+  EXPECT_EQ(6, a_);
+  EXPECT_EQ(3, b_);
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+void ThrowAnInteger() {
+  throw 1;
+}
+
+// Tests that assertion arguments are evaluated exactly once.
+TEST_F(SingleEvaluationTest, ExceptionTests) {
+  // successful EXPECT_THROW
+  EXPECT_THROW({  // NOLINT
+    a_++;
+    ThrowAnInteger();
+  }, int);
+  EXPECT_EQ(1, a_);
+
+  // failed EXPECT_THROW, throws different
+  EXPECT_NONFATAL_FAILURE(EXPECT_THROW({  // NOLINT
+    a_++;
+    ThrowAnInteger();
+  }, bool), "throws a different type");
+  EXPECT_EQ(2, a_);
+
+  // failed EXPECT_THROW, throws nothing
+  EXPECT_NONFATAL_FAILURE(EXPECT_THROW(a_++, bool), "throws nothing");
+  EXPECT_EQ(3, a_);
+
+  // successful EXPECT_NO_THROW
+  EXPECT_NO_THROW(a_++);
+  EXPECT_EQ(4, a_);
+
+  // failed EXPECT_NO_THROW
+  EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW({  // NOLINT
+    a_++;
+    ThrowAnInteger();
+  }), "it throws");
+  EXPECT_EQ(5, a_);
+
+  // successful EXPECT_ANY_THROW
+  EXPECT_ANY_THROW({  // NOLINT
+    a_++;
+    ThrowAnInteger();
+  });
+  EXPECT_EQ(6, a_);
+
+  // failed EXPECT_ANY_THROW
+  EXPECT_NONFATAL_FAILURE(EXPECT_ANY_THROW(a_++), "it doesn't");
+  EXPECT_EQ(7, a_);
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// Tests {ASSERT|EXPECT}_NO_FATAL_FAILURE.
+class NoFatalFailureTest : public Test {
+ protected:
+  void Succeeds() {}
+  void FailsNonFatal() {
+    ADD_FAILURE() << "some non-fatal failure";
+  }
+  void Fails() {
+    FAIL() << "some fatal failure";
+  }
+
+  void DoAssertNoFatalFailureOnFails() {
+    ASSERT_NO_FATAL_FAILURE(Fails());
+    ADD_FAILURE() << "shold not reach here.";
+  }
+
+  void DoExpectNoFatalFailureOnFails() {
+    EXPECT_NO_FATAL_FAILURE(Fails());
+    ADD_FAILURE() << "other failure";
+  }
+};
+
+TEST_F(NoFatalFailureTest, NoFailure) {
+  EXPECT_NO_FATAL_FAILURE(Succeeds());
+  ASSERT_NO_FATAL_FAILURE(Succeeds());
+}
+
+TEST_F(NoFatalFailureTest, NonFatalIsNoFailure) {
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_NO_FATAL_FAILURE(FailsNonFatal()),
+      "some non-fatal failure");
+  EXPECT_NONFATAL_FAILURE(
+      ASSERT_NO_FATAL_FAILURE(FailsNonFatal()),
+      "some non-fatal failure");
+}
+
+TEST_F(NoFatalFailureTest, AssertNoFatalFailureOnFatalFailure) {
+  TestPartResultArray gtest_failures;
+  {
+    ScopedFakeTestPartResultReporter gtest_reporter(&gtest_failures);
+    DoAssertNoFatalFailureOnFails();
+  }
+  ASSERT_EQ(2, gtest_failures.size());
+  EXPECT_EQ(TestPartResult::kFatalFailure,
+            gtest_failures.GetTestPartResult(0).type());
+  EXPECT_EQ(TestPartResult::kFatalFailure,
+            gtest_failures.GetTestPartResult(1).type());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "some fatal failure",
+                      gtest_failures.GetTestPartResult(0).message());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "it does",
+                      gtest_failures.GetTestPartResult(1).message());
+}
+
+TEST_F(NoFatalFailureTest, ExpectNoFatalFailureOnFatalFailure) {
+  TestPartResultArray gtest_failures;
+  {
+    ScopedFakeTestPartResultReporter gtest_reporter(&gtest_failures);
+    DoExpectNoFatalFailureOnFails();
+  }
+  ASSERT_EQ(3, gtest_failures.size());
+  EXPECT_EQ(TestPartResult::kFatalFailure,
+            gtest_failures.GetTestPartResult(0).type());
+  EXPECT_EQ(TestPartResult::kNonFatalFailure,
+            gtest_failures.GetTestPartResult(1).type());
+  EXPECT_EQ(TestPartResult::kNonFatalFailure,
+            gtest_failures.GetTestPartResult(2).type());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "some fatal failure",
+                      gtest_failures.GetTestPartResult(0).message());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "it does",
+                      gtest_failures.GetTestPartResult(1).message());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "other failure",
+                      gtest_failures.GetTestPartResult(2).message());
+}
+
+TEST_F(NoFatalFailureTest, MessageIsStreamable) {
+  TestPartResultArray gtest_failures;
+  {
+    ScopedFakeTestPartResultReporter gtest_reporter(&gtest_failures);
+    EXPECT_NO_FATAL_FAILURE(FAIL() << "foo") << "my message";
+  }
+  ASSERT_EQ(2, gtest_failures.size());
+  EXPECT_EQ(TestPartResult::kNonFatalFailure,
+            gtest_failures.GetTestPartResult(0).type());
+  EXPECT_EQ(TestPartResult::kNonFatalFailure,
+            gtest_failures.GetTestPartResult(1).type());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "foo",
+                      gtest_failures.GetTestPartResult(0).message());
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, "my message",
+                      gtest_failures.GetTestPartResult(1).message());
+}
+
+// Tests non-string assertions.
+
+// Tests EqFailure(), used for implementing *EQ* assertions.
+TEST(AssertionTest, EqFailure) {
+  const String foo_val("5"), bar_val("6");
+  const String msg1(
+      EqFailure("foo", "bar", foo_val, bar_val, false)
+      .failure_message());
+  EXPECT_STREQ(
+      "Value of: bar\n"
+      "  Actual: 6\n"
+      "Expected: foo\n"
+      "Which is: 5",
+      msg1.c_str());
+
+  const String msg2(
+      EqFailure("foo", "6", foo_val, bar_val, false)
+      .failure_message());
+  EXPECT_STREQ(
+      "Value of: 6\n"
+      "Expected: foo\n"
+      "Which is: 5",
+      msg2.c_str());
+
+  const String msg3(
+      EqFailure("5", "bar", foo_val, bar_val, false)
+      .failure_message());
+  EXPECT_STREQ(
+      "Value of: bar\n"
+      "  Actual: 6\n"
+      "Expected: 5",
+      msg3.c_str());
+
+  const String msg4(
+      EqFailure("5", "6", foo_val, bar_val, false).failure_message());
+  EXPECT_STREQ(
+      "Value of: 6\n"
+      "Expected: 5",
+      msg4.c_str());
+
+  const String msg5(
+      EqFailure("foo", "bar",
+                String("\"x\""), String("\"y\""),
+                true).failure_message());
+  EXPECT_STREQ(
+      "Value of: bar\n"
+      "  Actual: \"y\"\n"
+      "Expected: foo (ignoring case)\n"
+      "Which is: \"x\"",
+      msg5.c_str());
+}
+
+// Tests AppendUserMessage(), used for implementing the *EQ* macros.
+TEST(AssertionTest, AppendUserMessage) {
+  const String foo("foo");
+
+  Message msg;
+  EXPECT_STREQ("foo",
+               AppendUserMessage(foo, msg).c_str());
+
+  msg << "bar";
+  EXPECT_STREQ("foo\nbar",
+               AppendUserMessage(foo, msg).c_str());
+}
+
+#ifdef __BORLANDC__
+// Silences warnings: "Condition is always true", "Unreachable code"
+# pragma option push -w-ccc -w-rch
+#endif
+
+// Tests ASSERT_TRUE.
+TEST(AssertionTest, ASSERT_TRUE) {
+  ASSERT_TRUE(2 > 1);  // NOLINT
+  EXPECT_FATAL_FAILURE(ASSERT_TRUE(2 < 1),
+                       "2 < 1");
+}
+
+// Tests ASSERT_TRUE(predicate) for predicates returning AssertionResult.
+TEST(AssertionTest, AssertTrueWithAssertionResult) {
+  ASSERT_TRUE(ResultIsEven(2));
+#ifndef __BORLANDC__
+  // ICE's in C++Builder.
+  EXPECT_FATAL_FAILURE(ASSERT_TRUE(ResultIsEven(3)),
+                       "Value of: ResultIsEven(3)\n"
+                       "  Actual: false (3 is odd)\n"
+                       "Expected: true");
+#endif
+  ASSERT_TRUE(ResultIsEvenNoExplanation(2));
+  EXPECT_FATAL_FAILURE(ASSERT_TRUE(ResultIsEvenNoExplanation(3)),
+                       "Value of: ResultIsEvenNoExplanation(3)\n"
+                       "  Actual: false (3 is odd)\n"
+                       "Expected: true");
+}
+
+// Tests ASSERT_FALSE.
+TEST(AssertionTest, ASSERT_FALSE) {
+  ASSERT_FALSE(2 < 1);  // NOLINT
+  EXPECT_FATAL_FAILURE(ASSERT_FALSE(2 > 1),
+                       "Value of: 2 > 1\n"
+                       "  Actual: true\n"
+                       "Expected: false");
+}
+
+// Tests ASSERT_FALSE(predicate) for predicates returning AssertionResult.
+TEST(AssertionTest, AssertFalseWithAssertionResult) {
+  ASSERT_FALSE(ResultIsEven(3));
+#ifndef __BORLANDC__
+  // ICE's in C++Builder.
+  EXPECT_FATAL_FAILURE(ASSERT_FALSE(ResultIsEven(2)),
+                       "Value of: ResultIsEven(2)\n"
+                       "  Actual: true (2 is even)\n"
+                       "Expected: false");
+#endif
+  ASSERT_FALSE(ResultIsEvenNoExplanation(3));
+  EXPECT_FATAL_FAILURE(ASSERT_FALSE(ResultIsEvenNoExplanation(2)),
+                       "Value of: ResultIsEvenNoExplanation(2)\n"
+                       "  Actual: true\n"
+                       "Expected: false");
+}
+
+#ifdef __BORLANDC__
+// Restores warnings after previous "#pragma option push" supressed them
+# pragma option pop
+#endif
+
+// Tests using ASSERT_EQ on double values.  The purpose is to make
+// sure that the specialization we did for integer and anonymous enums
+// isn't used for double arguments.
+TEST(ExpectTest, ASSERT_EQ_Double) {
+  // A success.
+  ASSERT_EQ(5.6, 5.6);
+
+  // A failure.
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(5.1, 5.2),
+                       "5.1");
+}
+
+// Tests ASSERT_EQ.
+TEST(AssertionTest, ASSERT_EQ) {
+  ASSERT_EQ(5, 2 + 3);
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(5, 2*3),
+                       "Value of: 2*3\n"
+                       "  Actual: 6\n"
+                       "Expected: 5");
+}
+
+// Tests ASSERT_EQ(NULL, pointer).
+#if GTEST_CAN_COMPARE_NULL
+TEST(AssertionTest, ASSERT_EQ_NULL) {
+  // A success.
+  const char* p = NULL;
+  // Some older GCC versions may issue a spurious waring in this or the next
+  // assertion statement. This warning should not be suppressed with
+  // static_cast since the test verifies the ability to use bare NULL as the
+  // expected parameter to the macro.
+  ASSERT_EQ(NULL, p);
+
+  // A failure.
+  static int n = 0;
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(NULL, &n),
+                       "Value of: &n\n");
+}
+#endif  // GTEST_CAN_COMPARE_NULL
+
+// Tests ASSERT_EQ(0, non_pointer).  Since the literal 0 can be
+// treated as a null pointer by the compiler, we need to make sure
+// that ASSERT_EQ(0, non_pointer) isn't interpreted by Google Test as
+// ASSERT_EQ(static_cast<void*>(NULL), non_pointer).
+TEST(ExpectTest, ASSERT_EQ_0) {
+  int n = 0;
+
+  // A success.
+  ASSERT_EQ(0, n);
+
+  // A failure.
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(0, 5.6),
+                       "Expected: 0");
+}
+
+// Tests ASSERT_NE.
+TEST(AssertionTest, ASSERT_NE) {
+  ASSERT_NE(6, 7);
+  EXPECT_FATAL_FAILURE(ASSERT_NE('a', 'a'),
+                       "Expected: ('a') != ('a'), "
+                       "actual: 'a' (97, 0x61) vs 'a' (97, 0x61)");
+}
+
+// Tests ASSERT_LE.
+TEST(AssertionTest, ASSERT_LE) {
+  ASSERT_LE(2, 3);
+  ASSERT_LE(2, 2);
+  EXPECT_FATAL_FAILURE(ASSERT_LE(2, 0),
+                       "Expected: (2) <= (0), actual: 2 vs 0");
+}
+
+// Tests ASSERT_LT.
+TEST(AssertionTest, ASSERT_LT) {
+  ASSERT_LT(2, 3);
+  EXPECT_FATAL_FAILURE(ASSERT_LT(2, 2),
+                       "Expected: (2) < (2), actual: 2 vs 2");
+}
+
+// Tests ASSERT_GE.
+TEST(AssertionTest, ASSERT_GE) {
+  ASSERT_GE(2, 1);
+  ASSERT_GE(2, 2);
+  EXPECT_FATAL_FAILURE(ASSERT_GE(2, 3),
+                       "Expected: (2) >= (3), actual: 2 vs 3");
+}
+
+// Tests ASSERT_GT.
+TEST(AssertionTest, ASSERT_GT) {
+  ASSERT_GT(2, 1);
+  EXPECT_FATAL_FAILURE(ASSERT_GT(2, 2),
+                       "Expected: (2) > (2), actual: 2 vs 2");
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+void ThrowNothing() {}
+
+// Tests ASSERT_THROW.
+TEST(AssertionTest, ASSERT_THROW) {
+  ASSERT_THROW(ThrowAnInteger(), int);
+
+# ifndef __BORLANDC__
+
+  // ICE's in C++Builder 2007 and 2009.
+  EXPECT_FATAL_FAILURE(
+      ASSERT_THROW(ThrowAnInteger(), bool),
+      "Expected: ThrowAnInteger() throws an exception of type bool.\n"
+      "  Actual: it throws a different type.");
+# endif
+
+  EXPECT_FATAL_FAILURE(
+      ASSERT_THROW(ThrowNothing(), bool),
+      "Expected: ThrowNothing() throws an exception of type bool.\n"
+      "  Actual: it throws nothing.");
+}
+
+// Tests ASSERT_NO_THROW.
+TEST(AssertionTest, ASSERT_NO_THROW) {
+  ASSERT_NO_THROW(ThrowNothing());
+  EXPECT_FATAL_FAILURE(ASSERT_NO_THROW(ThrowAnInteger()),
+                       "Expected: ThrowAnInteger() doesn't throw an exception."
+                       "\n  Actual: it throws.");
+}
+
+// Tests ASSERT_ANY_THROW.
+TEST(AssertionTest, ASSERT_ANY_THROW) {
+  ASSERT_ANY_THROW(ThrowAnInteger());
+  EXPECT_FATAL_FAILURE(
+      ASSERT_ANY_THROW(ThrowNothing()),
+      "Expected: ThrowNothing() throws an exception.\n"
+      "  Actual: it doesn't.");
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// Makes sure we deal with the precedence of <<.  This test should
+// compile.
+TEST(AssertionTest, AssertPrecedence) {
+  ASSERT_EQ(1 < 2, true);
+  bool false_value = false;
+  ASSERT_EQ(true && false_value, false);
+}
+
+// A subroutine used by the following test.
+void TestEq1(int x) {
+  ASSERT_EQ(1, x);
+}
+
+// Tests calling a test subroutine that's not part of a fixture.
+TEST(AssertionTest, NonFixtureSubroutine) {
+  EXPECT_FATAL_FAILURE(TestEq1(2),
+                       "Value of: x");
+}
+
+// An uncopyable class.
+class Uncopyable {
+ public:
+  explicit Uncopyable(int a_value) : value_(a_value) {}
+
+  int value() const { return value_; }
+  bool operator==(const Uncopyable& rhs) const {
+    return value() == rhs.value();
+  }
+ private:
+  // This constructor deliberately has no implementation, as we don't
+  // want this class to be copyable.
+  Uncopyable(const Uncopyable&);  // NOLINT
+
+  int value_;
+};
+
+::std::ostream& operator<<(::std::ostream& os, const Uncopyable& value) {
+  return os << value.value();
+}
+
+
+bool IsPositiveUncopyable(const Uncopyable& x) {
+  return x.value() > 0;
+}
+
+// A subroutine used by the following test.
+void TestAssertNonPositive() {
+  Uncopyable y(-1);
+  ASSERT_PRED1(IsPositiveUncopyable, y);
+}
+// A subroutine used by the following test.
+void TestAssertEqualsUncopyable() {
+  Uncopyable x(5);
+  Uncopyable y(-1);
+  ASSERT_EQ(x, y);
+}
+
+// Tests that uncopyable objects can be used in assertions.
+TEST(AssertionTest, AssertWorksWithUncopyableObject) {
+  Uncopyable x(5);
+  ASSERT_PRED1(IsPositiveUncopyable, x);
+  ASSERT_EQ(x, x);
+  EXPECT_FATAL_FAILURE(TestAssertNonPositive(),
+    "IsPositiveUncopyable(y) evaluates to false, where\ny evaluates to -1");
+  EXPECT_FATAL_FAILURE(TestAssertEqualsUncopyable(),
+    "Value of: y\n  Actual: -1\nExpected: x\nWhich is: 5");
+}
+
+// Tests that uncopyable objects can be used in expects.
+TEST(AssertionTest, ExpectWorksWithUncopyableObject) {
+  Uncopyable x(5);
+  EXPECT_PRED1(IsPositiveUncopyable, x);
+  Uncopyable y(-1);
+  EXPECT_NONFATAL_FAILURE(EXPECT_PRED1(IsPositiveUncopyable, y),
+    "IsPositiveUncopyable(y) evaluates to false, where\ny evaluates to -1");
+  EXPECT_EQ(x, x);
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(x, y),
+    "Value of: y\n  Actual: -1\nExpected: x\nWhich is: 5");
+}
+
+enum NamedEnum {
+  kE1 = 0,
+  kE2 = 1
+};
+
+TEST(AssertionTest, NamedEnum) {
+  EXPECT_EQ(kE1, kE1);
+  EXPECT_LT(kE1, kE2);
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(kE1, kE2), "Which is: 0");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(kE1, kE2), "Actual: 1");
+}
+
+// The version of gcc used in XCode 2.2 has a bug and doesn't allow
+// anonymous enums in assertions.  Therefore the following test is not
+// done on Mac.
+// Sun Studio and HP aCC also reject this code.
+#if !GTEST_OS_MAC && !defined(__SUNPRO_CC) && !defined(__HP_aCC)
+
+// Tests using assertions with anonymous enums.
+enum {
+  kCaseA = -1,
+
+# if GTEST_OS_LINUX
+
+  // We want to test the case where the size of the anonymous enum is
+  // larger than sizeof(int), to make sure our implementation of the
+  // assertions doesn't truncate the enums.  However, MSVC
+  // (incorrectly) doesn't allow an enum value to exceed the range of
+  // an int, so this has to be conditionally compiled.
+  //
+  // On Linux, kCaseB and kCaseA have the same value when truncated to
+  // int size.  We want to test whether this will confuse the
+  // assertions.
+  kCaseB = testing::internal::kMaxBiggestInt,
+
+# else
+
+  kCaseB = INT_MAX,
+
+# endif  // GTEST_OS_LINUX
+
+  kCaseC = 42
+};
+
+TEST(AssertionTest, AnonymousEnum) {
+# if GTEST_OS_LINUX
+
+  EXPECT_EQ(static_cast<int>(kCaseA), static_cast<int>(kCaseB));
+
+# endif  // GTEST_OS_LINUX
+
+  EXPECT_EQ(kCaseA, kCaseA);
+  EXPECT_NE(kCaseA, kCaseB);
+  EXPECT_LT(kCaseA, kCaseB);
+  EXPECT_LE(kCaseA, kCaseB);
+  EXPECT_GT(kCaseB, kCaseA);
+  EXPECT_GE(kCaseA, kCaseA);
+  EXPECT_NONFATAL_FAILURE(EXPECT_GE(kCaseA, kCaseB),
+                          "(kCaseA) >= (kCaseB)");
+  EXPECT_NONFATAL_FAILURE(EXPECT_GE(kCaseA, kCaseC),
+                          "-1 vs 42");
+
+  ASSERT_EQ(kCaseA, kCaseA);
+  ASSERT_NE(kCaseA, kCaseB);
+  ASSERT_LT(kCaseA, kCaseB);
+  ASSERT_LE(kCaseA, kCaseB);
+  ASSERT_GT(kCaseB, kCaseA);
+  ASSERT_GE(kCaseA, kCaseA);
+
+# ifndef __BORLANDC__
+
+  // ICE's in C++Builder.
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseB),
+                       "Value of: kCaseB");
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseC),
+                       "Actual: 42");
+# endif
+
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseC),
+                       "Which is: -1");
+}
+
+#endif  // !GTEST_OS_MAC && !defined(__SUNPRO_CC)
+
+#if GTEST_OS_WINDOWS
+
+static HRESULT UnexpectedHRESULTFailure() {
+  return E_UNEXPECTED;
+}
+
+static HRESULT OkHRESULTSuccess() {
+  return S_OK;
+}
+
+static HRESULT FalseHRESULTSuccess() {
+  return S_FALSE;
+}
+
+// HRESULT assertion tests test both zero and non-zero
+// success codes as well as failure message for each.
+//
+// Windows CE doesn't support message texts.
+TEST(HRESULTAssertionTest, EXPECT_HRESULT_SUCCEEDED) {
+  EXPECT_HRESULT_SUCCEEDED(S_OK);
+  EXPECT_HRESULT_SUCCEEDED(S_FALSE);
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_HRESULT_SUCCEEDED(UnexpectedHRESULTFailure()),
+    "Expected: (UnexpectedHRESULTFailure()) succeeds.\n"
+    "  Actual: 0x8000FFFF");
+}
+
+TEST(HRESULTAssertionTest, ASSERT_HRESULT_SUCCEEDED) {
+  ASSERT_HRESULT_SUCCEEDED(S_OK);
+  ASSERT_HRESULT_SUCCEEDED(S_FALSE);
+
+  EXPECT_FATAL_FAILURE(ASSERT_HRESULT_SUCCEEDED(UnexpectedHRESULTFailure()),
+    "Expected: (UnexpectedHRESULTFailure()) succeeds.\n"
+    "  Actual: 0x8000FFFF");
+}
+
+TEST(HRESULTAssertionTest, EXPECT_HRESULT_FAILED) {
+  EXPECT_HRESULT_FAILED(E_UNEXPECTED);
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_HRESULT_FAILED(OkHRESULTSuccess()),
+    "Expected: (OkHRESULTSuccess()) fails.\n"
+    "  Actual: 0x00000000");
+  EXPECT_NONFATAL_FAILURE(EXPECT_HRESULT_FAILED(FalseHRESULTSuccess()),
+    "Expected: (FalseHRESULTSuccess()) fails.\n"
+    "  Actual: 0x00000001");
+}
+
+TEST(HRESULTAssertionTest, ASSERT_HRESULT_FAILED) {
+  ASSERT_HRESULT_FAILED(E_UNEXPECTED);
+
+# ifndef __BORLANDC__
+
+  // ICE's in C++Builder 2007 and 2009.
+  EXPECT_FATAL_FAILURE(ASSERT_HRESULT_FAILED(OkHRESULTSuccess()),
+    "Expected: (OkHRESULTSuccess()) fails.\n"
+    "  Actual: 0x00000000");
+# endif
+
+  EXPECT_FATAL_FAILURE(ASSERT_HRESULT_FAILED(FalseHRESULTSuccess()),
+    "Expected: (FalseHRESULTSuccess()) fails.\n"
+    "  Actual: 0x00000001");
+}
+
+// Tests that streaming to the HRESULT macros works.
+TEST(HRESULTAssertionTest, Streaming) {
+  EXPECT_HRESULT_SUCCEEDED(S_OK) << "unexpected failure";
+  ASSERT_HRESULT_SUCCEEDED(S_OK) << "unexpected failure";
+  EXPECT_HRESULT_FAILED(E_UNEXPECTED) << "unexpected failure";
+  ASSERT_HRESULT_FAILED(E_UNEXPECTED) << "unexpected failure";
+
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_HRESULT_SUCCEEDED(E_UNEXPECTED) << "expected failure",
+      "expected failure");
+
+# ifndef __BORLANDC__
+
+  // ICE's in C++Builder 2007 and 2009.
+  EXPECT_FATAL_FAILURE(
+      ASSERT_HRESULT_SUCCEEDED(E_UNEXPECTED) << "expected failure",
+      "expected failure");
+# endif
+
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_HRESULT_FAILED(S_OK) << "expected failure",
+      "expected failure");
+
+  EXPECT_FATAL_FAILURE(
+      ASSERT_HRESULT_FAILED(S_OK) << "expected failure",
+      "expected failure");
+}
+
+#endif  // GTEST_OS_WINDOWS
+
+#ifdef __BORLANDC__
+// Silences warnings: "Condition is always true", "Unreachable code"
+# pragma option push -w-ccc -w-rch
+#endif
+
+// Tests that the assertion macros behave like single statements.
+TEST(AssertionSyntaxTest, BasicAssertionsBehavesLikeSingleStatement) {
+  if (AlwaysFalse())
+    ASSERT_TRUE(false) << "This should never be executed; "
+                          "It's a compilation test only.";
+
+  if (AlwaysTrue())
+    EXPECT_FALSE(false);
+  else
+    ;  // NOLINT
+
+  if (AlwaysFalse())
+    ASSERT_LT(1, 3);
+
+  if (AlwaysFalse())
+    ;  // NOLINT
+  else
+    EXPECT_GT(3, 2) << "";
+}
+
+#if GTEST_HAS_EXCEPTIONS
+// Tests that the compiler will not complain about unreachable code in the
+// EXPECT_THROW/EXPECT_ANY_THROW/EXPECT_NO_THROW macros.
+TEST(ExpectThrowTest, DoesNotGenerateUnreachableCodeWarning) {
+  int n = 0;
+
+  EXPECT_THROW(throw 1, int);
+  EXPECT_NONFATAL_FAILURE(EXPECT_THROW(n++, int), "");
+  EXPECT_NONFATAL_FAILURE(EXPECT_THROW(throw 1, const char*), "");
+  EXPECT_NO_THROW(n++);
+  EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW(throw 1), "");
+  EXPECT_ANY_THROW(throw 1);
+  EXPECT_NONFATAL_FAILURE(EXPECT_ANY_THROW(n++), "");
+}
+
+TEST(AssertionSyntaxTest, ExceptionAssertionsBehavesLikeSingleStatement) {
+  if (AlwaysFalse())
+    EXPECT_THROW(ThrowNothing(), bool);
+
+  if (AlwaysTrue())
+    EXPECT_THROW(ThrowAnInteger(), int);
+  else
+    ;  // NOLINT
+
+  if (AlwaysFalse())
+    EXPECT_NO_THROW(ThrowAnInteger());
+
+  if (AlwaysTrue())
+    EXPECT_NO_THROW(ThrowNothing());
+  else
+    ;  // NOLINT
+
+  if (AlwaysFalse())
+    EXPECT_ANY_THROW(ThrowNothing());
+
+  if (AlwaysTrue())
+    EXPECT_ANY_THROW(ThrowAnInteger());
+  else
+    ;  // NOLINT
+}
+#endif  // GTEST_HAS_EXCEPTIONS
+
+TEST(AssertionSyntaxTest, NoFatalFailureAssertionsBehavesLikeSingleStatement) {
+  if (AlwaysFalse())
+    EXPECT_NO_FATAL_FAILURE(FAIL()) << "This should never be executed. "
+                                    << "It's a compilation test only.";
+  else
+    ;  // NOLINT
+
+  if (AlwaysFalse())
+    ASSERT_NO_FATAL_FAILURE(FAIL()) << "";
+  else
+    ;  // NOLINT
+
+  if (AlwaysTrue())
+    EXPECT_NO_FATAL_FAILURE(SUCCEED());
+  else
+    ;  // NOLINT
+
+  if (AlwaysFalse())
+    ;  // NOLINT
+  else
+    ASSERT_NO_FATAL_FAILURE(SUCCEED());
+}
+
+// Tests that the assertion macros work well with switch statements.
+TEST(AssertionSyntaxTest, WorksWithSwitch) {
+  switch (0) {
+    case 1:
+      break;
+    default:
+      ASSERT_TRUE(true);
+  }
+
+  switch (0)
+    case 0:
+      EXPECT_FALSE(false) << "EXPECT_FALSE failed in switch case";
+
+  // Binary assertions are implemented using a different code path
+  // than the Boolean assertions.  Hence we test them separately.
+  switch (0) {
+    case 1:
+    default:
+      ASSERT_EQ(1, 1) << "ASSERT_EQ failed in default switch handler";
+  }
+
+  switch (0)
+    case 0:
+      EXPECT_NE(1, 2);
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+void ThrowAString() {
+    throw "String";
+}
+
+// Test that the exception assertion macros compile and work with const
+// type qualifier.
+TEST(AssertionSyntaxTest, WorksWithConst) {
+    ASSERT_THROW(ThrowAString(), const char*);
+
+    EXPECT_THROW(ThrowAString(), const char*);
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+}  // namespace
+
+namespace testing {
+
+// Tests that Google Test tracks SUCCEED*.
+TEST(SuccessfulAssertionTest, SUCCEED) {
+  SUCCEED();
+  SUCCEED() << "OK";
+  EXPECT_EQ(2, GetUnitTestImpl()->current_test_result()->total_part_count());
+}
+
+// Tests that Google Test doesn't track successful EXPECT_*.
+TEST(SuccessfulAssertionTest, EXPECT) {
+  EXPECT_TRUE(true);
+  EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
+}
+
+// Tests that Google Test doesn't track successful EXPECT_STR*.
+TEST(SuccessfulAssertionTest, EXPECT_STR) {
+  EXPECT_STREQ("", "");
+  EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
+}
+
+// Tests that Google Test doesn't track successful ASSERT_*.
+TEST(SuccessfulAssertionTest, ASSERT) {
+  ASSERT_TRUE(true);
+  EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
+}
+
+// Tests that Google Test doesn't track successful ASSERT_STR*.
+TEST(SuccessfulAssertionTest, ASSERT_STR) {
+  ASSERT_STREQ("", "");
+  EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
+}
+
+}  // namespace testing
+
+namespace {
+
+// Tests EXPECT_TRUE.
+TEST(ExpectTest, EXPECT_TRUE) {
+  EXPECT_TRUE(2 > 1);  // NOLINT
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(2 < 1),
+                          "Value of: 2 < 1\n"
+                          "  Actual: false\n"
+                          "Expected: true");
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(2 > 3),
+                          "2 > 3");
+}
+
+// Tests EXPECT_TRUE(predicate) for predicates returning AssertionResult.
+TEST(ExpectTest, ExpectTrueWithAssertionResult) {
+  EXPECT_TRUE(ResultIsEven(2));
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(ResultIsEven(3)),
+                          "Value of: ResultIsEven(3)\n"
+                          "  Actual: false (3 is odd)\n"
+                          "Expected: true");
+  EXPECT_TRUE(ResultIsEvenNoExplanation(2));
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(ResultIsEvenNoExplanation(3)),
+                          "Value of: ResultIsEvenNoExplanation(3)\n"
+                          "  Actual: false (3 is odd)\n"
+                          "Expected: true");
+}
+
+// Tests EXPECT_FALSE.
+TEST(ExpectTest, EXPECT_FALSE) {
+  EXPECT_FALSE(2 < 1);  // NOLINT
+  EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(2 > 1),
+                          "Value of: 2 > 1\n"
+                          "  Actual: true\n"
+                          "Expected: false");
+  EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(2 < 3),
+                          "2 < 3");
+}
+
+// Tests EXPECT_FALSE(predicate) for predicates returning AssertionResult.
+TEST(ExpectTest, ExpectFalseWithAssertionResult) {
+  EXPECT_FALSE(ResultIsEven(3));
+  EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(ResultIsEven(2)),
+                          "Value of: ResultIsEven(2)\n"
+                          "  Actual: true (2 is even)\n"
+                          "Expected: false");
+  EXPECT_FALSE(ResultIsEvenNoExplanation(3));
+  EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(ResultIsEvenNoExplanation(2)),
+                          "Value of: ResultIsEvenNoExplanation(2)\n"
+                          "  Actual: true\n"
+                          "Expected: false");
+}
+
+#ifdef __BORLANDC__
+// Restores warnings after previous "#pragma option push" supressed them
+# pragma option pop
+#endif
+
+// Tests EXPECT_EQ.
+TEST(ExpectTest, EXPECT_EQ) {
+  EXPECT_EQ(5, 2 + 3);
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(5, 2*3),
+                          "Value of: 2*3\n"
+                          "  Actual: 6\n"
+                          "Expected: 5");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(5, 2 - 3),
+                          "2 - 3");
+}
+
+// Tests using EXPECT_EQ on double values.  The purpose is to make
+// sure that the specialization we did for integer and anonymous enums
+// isn't used for double arguments.
+TEST(ExpectTest, EXPECT_EQ_Double) {
+  // A success.
+  EXPECT_EQ(5.6, 5.6);
+
+  // A failure.
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(5.1, 5.2),
+                          "5.1");
+}
+
+#if GTEST_CAN_COMPARE_NULL
+// Tests EXPECT_EQ(NULL, pointer).
+TEST(ExpectTest, EXPECT_EQ_NULL) {
+  // A success.
+  const char* p = NULL;
+  // Some older GCC versions may issue a spurious warning in this or the next
+  // assertion statement. This warning should not be suppressed with
+  // static_cast since the test verifies the ability to use bare NULL as the
+  // expected parameter to the macro.
+  EXPECT_EQ(NULL, p);
+
+  // A failure.
+  int n = 0;
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(NULL, &n),
+                          "Value of: &n\n");
+}
+#endif  // GTEST_CAN_COMPARE_NULL
+
+// Tests EXPECT_EQ(0, non_pointer).  Since the literal 0 can be
+// treated as a null pointer by the compiler, we need to make sure
+// that EXPECT_EQ(0, non_pointer) isn't interpreted by Google Test as
+// EXPECT_EQ(static_cast<void*>(NULL), non_pointer).
+TEST(ExpectTest, EXPECT_EQ_0) {
+  int n = 0;
+
+  // A success.
+  EXPECT_EQ(0, n);
+
+  // A failure.
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(0, 5.6),
+                          "Expected: 0");
+}
+
+// Tests EXPECT_NE.
+TEST(ExpectTest, EXPECT_NE) {
+  EXPECT_NE(6, 7);
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_NE('a', 'a'),
+                          "Expected: ('a') != ('a'), "
+                          "actual: 'a' (97, 0x61) vs 'a' (97, 0x61)");
+  EXPECT_NONFATAL_FAILURE(EXPECT_NE(2, 2),
+                          "2");
+  char* const p0 = NULL;
+  EXPECT_NONFATAL_FAILURE(EXPECT_NE(p0, p0),
+                          "p0");
+  // Only way to get the Nokia compiler to compile the cast
+  // is to have a separate void* variable first. Putting
+  // the two casts on the same line doesn't work, neither does
+  // a direct C-style to char*.
+  void* pv1 = (void*)0x1234;  // NOLINT
+  char* const p1 = reinterpret_cast<char*>(pv1);
+  EXPECT_NONFATAL_FAILURE(EXPECT_NE(p1, p1),
+                          "p1");
+}
+
+// Tests EXPECT_LE.
+TEST(ExpectTest, EXPECT_LE) {
+  EXPECT_LE(2, 3);
+  EXPECT_LE(2, 2);
+  EXPECT_NONFATAL_FAILURE(EXPECT_LE(2, 0),
+                          "Expected: (2) <= (0), actual: 2 vs 0");
+  EXPECT_NONFATAL_FAILURE(EXPECT_LE(1.1, 0.9),
+                          "(1.1) <= (0.9)");
+}
+
+// Tests EXPECT_LT.
+TEST(ExpectTest, EXPECT_LT) {
+  EXPECT_LT(2, 3);
+  EXPECT_NONFATAL_FAILURE(EXPECT_LT(2, 2),
+                          "Expected: (2) < (2), actual: 2 vs 2");
+  EXPECT_NONFATAL_FAILURE(EXPECT_LT(2, 1),
+                          "(2) < (1)");
+}
+
+// Tests EXPECT_GE.
+TEST(ExpectTest, EXPECT_GE) {
+  EXPECT_GE(2, 1);
+  EXPECT_GE(2, 2);
+  EXPECT_NONFATAL_FAILURE(EXPECT_GE(2, 3),
+                          "Expected: (2) >= (3), actual: 2 vs 3");
+  EXPECT_NONFATAL_FAILURE(EXPECT_GE(0.9, 1.1),
+                          "(0.9) >= (1.1)");
+}
+
+// Tests EXPECT_GT.
+TEST(ExpectTest, EXPECT_GT) {
+  EXPECT_GT(2, 1);
+  EXPECT_NONFATAL_FAILURE(EXPECT_GT(2, 2),
+                          "Expected: (2) > (2), actual: 2 vs 2");
+  EXPECT_NONFATAL_FAILURE(EXPECT_GT(2, 3),
+                          "(2) > (3)");
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Tests EXPECT_THROW.
+TEST(ExpectTest, EXPECT_THROW) {
+  EXPECT_THROW(ThrowAnInteger(), int);
+  EXPECT_NONFATAL_FAILURE(EXPECT_THROW(ThrowAnInteger(), bool),
+                          "Expected: ThrowAnInteger() throws an exception of "
+                          "type bool.\n  Actual: it throws a different type.");
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_THROW(ThrowNothing(), bool),
+      "Expected: ThrowNothing() throws an exception of type bool.\n"
+      "  Actual: it throws nothing.");
+}
+
+// Tests EXPECT_NO_THROW.
+TEST(ExpectTest, EXPECT_NO_THROW) {
+  EXPECT_NO_THROW(ThrowNothing());
+  EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW(ThrowAnInteger()),
+                          "Expected: ThrowAnInteger() doesn't throw an "
+                          "exception.\n  Actual: it throws.");
+}
+
+// Tests EXPECT_ANY_THROW.
+TEST(ExpectTest, EXPECT_ANY_THROW) {
+  EXPECT_ANY_THROW(ThrowAnInteger());
+  EXPECT_NONFATAL_FAILURE(
+      EXPECT_ANY_THROW(ThrowNothing()),
+      "Expected: ThrowNothing() throws an exception.\n"
+      "  Actual: it doesn't.");
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// Make sure we deal with the precedence of <<.
+TEST(ExpectTest, ExpectPrecedence) {
+  EXPECT_EQ(1 < 2, true);
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(true, true && false),
+                          "Value of: true && false");
+}
+
+
+// Tests the StreamableToString() function.
+
+// Tests using StreamableToString() on a scalar.
+TEST(StreamableToStringTest, Scalar) {
+  EXPECT_STREQ("5", StreamableToString(5).c_str());
+}
+
+// Tests using StreamableToString() on a non-char pointer.
+TEST(StreamableToStringTest, Pointer) {
+  int n = 0;
+  int* p = &n;
+  EXPECT_STRNE("(null)", StreamableToString(p).c_str());
+}
+
+// Tests using StreamableToString() on a NULL non-char pointer.
+TEST(StreamableToStringTest, NullPointer) {
+  int* p = NULL;
+  EXPECT_STREQ("(null)", StreamableToString(p).c_str());
+}
+
+// Tests using StreamableToString() on a C string.
+TEST(StreamableToStringTest, CString) {
+  EXPECT_STREQ("Foo", StreamableToString("Foo").c_str());
+}
+
+// Tests using StreamableToString() on a NULL C string.
+TEST(StreamableToStringTest, NullCString) {
+  char* p = NULL;
+  EXPECT_STREQ("(null)", StreamableToString(p).c_str());
+}
+
+// Tests using streamable values as assertion messages.
+
+// Tests using std::string as an assertion message.
+TEST(StreamableTest, string) {
+  static const std::string str(
+      "This failure message is a std::string, and is expected.");
+  EXPECT_FATAL_FAILURE(FAIL() << str,
+                       str.c_str());
+}
+
+// Tests that we can output strings containing embedded NULs.
+// Limited to Linux because we can only do this with std::string's.
+TEST(StreamableTest, stringWithEmbeddedNUL) {
+  static const char char_array_with_nul[] =
+      "Here's a NUL\0 and some more string";
+  static const std::string string_with_nul(char_array_with_nul,
+                                           sizeof(char_array_with_nul)
+                                           - 1);  // drops the trailing NUL
+  EXPECT_FATAL_FAILURE(FAIL() << string_with_nul,
+                       "Here's a NUL\\0 and some more string");
+}
+
+// Tests that we can output a NUL char.
+TEST(StreamableTest, NULChar) {
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    FAIL() << "A NUL" << '\0' << " and some more string";
+  }, "A NUL\\0 and some more string");
+}
+
+// Tests using int as an assertion message.
+TEST(StreamableTest, int) {
+  EXPECT_FATAL_FAILURE(FAIL() << 900913,
+                       "900913");
+}
+
+// Tests using NULL char pointer as an assertion message.
+//
+// In MSVC, streaming a NULL char * causes access violation.  Google Test
+// implemented a workaround (substituting "(null)" for NULL).  This
+// tests whether the workaround works.
+TEST(StreamableTest, NullCharPtr) {
+  EXPECT_FATAL_FAILURE(FAIL() << static_cast<const char*>(NULL),
+                       "(null)");
+}
+
+// Tests that basic IO manipulators (endl, ends, and flush) can be
+// streamed to testing::Message.
+TEST(StreamableTest, BasicIoManip) {
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    FAIL() << "Line 1." << std::endl
+           << "A NUL char " << std::ends << std::flush << " in line 2.";
+  }, "Line 1.\nA NUL char \\0 in line 2.");
+}
+
+// Tests the macros that haven't been covered so far.
+
+void AddFailureHelper(bool* aborted) {
+  *aborted = true;
+  ADD_FAILURE() << "Failure";
+  *aborted = false;
+}
+
+// Tests ADD_FAILURE.
+TEST(MacroTest, ADD_FAILURE) {
+  bool aborted = true;
+  EXPECT_NONFATAL_FAILURE(AddFailureHelper(&aborted),
+                          "Failure");
+  EXPECT_FALSE(aborted);
+}
+
+// Tests ADD_FAILURE_AT.
+TEST(MacroTest, ADD_FAILURE_AT) {
+  // Verifies that ADD_FAILURE_AT does generate a nonfatal failure and
+  // the failure message contains the user-streamed part.
+  EXPECT_NONFATAL_FAILURE(ADD_FAILURE_AT("foo.cc", 42) << "Wrong!", "Wrong!");
+
+  // Verifies that the user-streamed part is optional.
+  EXPECT_NONFATAL_FAILURE(ADD_FAILURE_AT("foo.cc", 42), "Failed");
+
+  // Unfortunately, we cannot verify that the failure message contains
+  // the right file path and line number the same way, as
+  // EXPECT_NONFATAL_FAILURE() doesn't get to see the file path and
+  // line number.  Instead, we do that in gtest_output_test_.cc.
+}
+
+// Tests FAIL.
+TEST(MacroTest, FAIL) {
+  EXPECT_FATAL_FAILURE(FAIL(),
+                       "Failed");
+  EXPECT_FATAL_FAILURE(FAIL() << "Intentional failure.",
+                       "Intentional failure.");
+}
+
+// Tests SUCCEED
+TEST(MacroTest, SUCCEED) {
+  SUCCEED();
+  SUCCEED() << "Explicit success.";
+}
+
+
+// Tests for EXPECT_EQ() and ASSERT_EQ().
+//
+// These tests fail *intentionally*, s.t. the failure messages can be
+// generated and tested.
+//
+// We have different tests for different argument types.
+
+// Tests using bool values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, Bool) {
+  EXPECT_EQ(true,  true);
+  EXPECT_FATAL_FAILURE({
+      bool false_value = false;
+      ASSERT_EQ(false_value, true);
+    }, "Value of: true");
+}
+
+// Tests using int values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, Int) {
+  ASSERT_EQ(32, 32);
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(32, 33),
+                          "33");
+}
+
+// Tests using time_t values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, Time_T) {
+  EXPECT_EQ(static_cast<time_t>(0),
+            static_cast<time_t>(0));
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(static_cast<time_t>(0),
+                                 static_cast<time_t>(1234)),
+                       "1234");
+}
+
+// Tests using char values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, Char) {
+  ASSERT_EQ('z', 'z');
+  const char ch = 'b';
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ('\0', ch),
+                          "ch");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ('a', ch),
+                          "ch");
+}
+
+// Tests using wchar_t values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, WideChar) {
+  EXPECT_EQ(L'b', L'b');
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(L'\0', L'x'),
+                          "Value of: L'x'\n"
+                          "  Actual: L'x' (120, 0x78)\n"
+                          "Expected: L'\0'\n"
+                          "Which is: L'\0' (0, 0x0)");
+
+  static wchar_t wchar;
+  wchar = L'b';
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(L'a', wchar),
+                          "wchar");
+  wchar = 0x8119;
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(static_cast<wchar_t>(0x8120), wchar),
+                       "Value of: wchar");
+}
+
+// Tests using ::std::string values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, StdString) {
+  // Compares a const char* to an std::string that has identical
+  // content.
+  ASSERT_EQ("Test", ::std::string("Test"));
+
+  // Compares two identical std::strings.
+  static const ::std::string str1("A * in the middle");
+  static const ::std::string str2(str1);
+  EXPECT_EQ(str1, str2);
+
+  // Compares a const char* to an std::string that has different
+  // content
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ("Test", ::std::string("test")),
+                          "::std::string(\"test\")");
+
+  // Compares an std::string to a char* that has different content.
+  char* const p1 = const_cast<char*>("foo");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(::std::string("bar"), p1),
+                          "p1");
+
+  // Compares two std::strings that have different contents, one of
+  // which having a NUL character in the middle.  This should fail.
+  static ::std::string str3(str1);
+  str3.at(2) = '\0';
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(str1, str3),
+                       "Value of: str3\n"
+                       "  Actual: \"A \\0 in the middle\"");
+}
+
+#if GTEST_HAS_STD_WSTRING
+
+// Tests using ::std::wstring values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, StdWideString) {
+  // Compares two identical std::wstrings.
+  const ::std::wstring wstr1(L"A * in the middle");
+  const ::std::wstring wstr2(wstr1);
+  ASSERT_EQ(wstr1, wstr2);
+
+  // Compares an std::wstring to a const wchar_t* that has identical
+  // content.
+  const wchar_t kTestX8119[] = { 'T', 'e', 's', 't', 0x8119, '\0' };
+  EXPECT_EQ(::std::wstring(kTestX8119), kTestX8119);
+
+  // Compares an std::wstring to a const wchar_t* that has different
+  // content.
+  const wchar_t kTestX8120[] = { 'T', 'e', 's', 't', 0x8120, '\0' };
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_EQ(::std::wstring(kTestX8119), kTestX8120);
+  }, "kTestX8120");
+
+  // Compares two std::wstrings that have different contents, one of
+  // which having a NUL character in the middle.
+  ::std::wstring wstr3(wstr1);
+  wstr3.at(2) = L'\0';
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(wstr1, wstr3),
+                          "wstr3");
+
+  // Compares a wchar_t* to an std::wstring that has different
+  // content.
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_EQ(const_cast<wchar_t*>(L"foo"), ::std::wstring(L"bar"));
+  }, "");
+}
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_STRING
+// Tests using ::string values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, GlobalString) {
+  // Compares a const char* to a ::string that has identical content.
+  EXPECT_EQ("Test", ::string("Test"));
+
+  // Compares two identical ::strings.
+  const ::string str1("A * in the middle");
+  const ::string str2(str1);
+  ASSERT_EQ(str1, str2);
+
+  // Compares a ::string to a const char* that has different content.
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(::string("Test"), "test"),
+                          "test");
+
+  // Compares two ::strings that have different contents, one of which
+  // having a NUL character in the middle.
+  ::string str3(str1);
+  str3.at(2) = '\0';
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(str1, str3),
+                          "str3");
+
+  // Compares a ::string to a char* that has different content.
+  EXPECT_FATAL_FAILURE({  // NOLINT
+    ASSERT_EQ(::string("bar"), const_cast<char*>("foo"));
+  }, "");
+}
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+
+// Tests using ::wstring values in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, GlobalWideString) {
+  // Compares two identical ::wstrings.
+  static const ::wstring wstr1(L"A * in the middle");
+  static const ::wstring wstr2(wstr1);
+  EXPECT_EQ(wstr1, wstr2);
+
+  // Compares a const wchar_t* to a ::wstring that has identical content.
+  const wchar_t kTestX8119[] = { 'T', 'e', 's', 't', 0x8119, '\0' };
+  ASSERT_EQ(kTestX8119, ::wstring(kTestX8119));
+
+  // Compares a const wchar_t* to a ::wstring that has different
+  // content.
+  const wchar_t kTestX8120[] = { 'T', 'e', 's', 't', 0x8120, '\0' };
+  EXPECT_NONFATAL_FAILURE({  // NOLINT
+    EXPECT_EQ(kTestX8120, ::wstring(kTestX8119));
+  }, "Test\\x8119");
+
+  // Compares a wchar_t* to a ::wstring that has different content.
+  wchar_t* const p1 = const_cast<wchar_t*>(L"foo");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p1, ::wstring(L"bar")),
+                          "bar");
+
+  // Compares two ::wstrings that have different contents, one of which
+  // having a NUL character in the middle.
+  static ::wstring wstr3;
+  wstr3 = wstr1;
+  wstr3.at(2) = L'\0';
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(wstr1, wstr3),
+                       "wstr3");
+}
+
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+// Tests using char pointers in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, CharPointer) {
+  char* const p0 = NULL;
+  // Only way to get the Nokia compiler to compile the cast
+  // is to have a separate void* variable first. Putting
+  // the two casts on the same line doesn't work, neither does
+  // a direct C-style to char*.
+  void* pv1 = (void*)0x1234;  // NOLINT
+  void* pv2 = (void*)0xABC0;  // NOLINT
+  char* const p1 = reinterpret_cast<char*>(pv1);
+  char* const p2 = reinterpret_cast<char*>(pv2);
+  ASSERT_EQ(p1, p1);
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p0, p2),
+                          "Value of: p2");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p1, p2),
+                          "p2");
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(reinterpret_cast<char*>(0x1234),
+                                 reinterpret_cast<char*>(0xABC0)),
+                       "ABC0");
+}
+
+// Tests using wchar_t pointers in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, WideCharPointer) {
+  wchar_t* const p0 = NULL;
+  // Only way to get the Nokia compiler to compile the cast
+  // is to have a separate void* variable first. Putting
+  // the two casts on the same line doesn't work, neither does
+  // a direct C-style to char*.
+  void* pv1 = (void*)0x1234;  // NOLINT
+  void* pv2 = (void*)0xABC0;  // NOLINT
+  wchar_t* const p1 = reinterpret_cast<wchar_t*>(pv1);
+  wchar_t* const p2 = reinterpret_cast<wchar_t*>(pv2);
+  EXPECT_EQ(p0, p0);
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p0, p2),
+                          "Value of: p2");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p1, p2),
+                          "p2");
+  void* pv3 = (void*)0x1234;  // NOLINT
+  void* pv4 = (void*)0xABC0;  // NOLINT
+  const wchar_t* p3 = reinterpret_cast<const wchar_t*>(pv3);
+  const wchar_t* p4 = reinterpret_cast<const wchar_t*>(pv4);
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p3, p4),
+                          "p4");
+}
+
+// Tests using other types of pointers in {EXPECT|ASSERT}_EQ.
+TEST(EqAssertionTest, OtherPointer) {
+  ASSERT_EQ(static_cast<const int*>(NULL),
+            static_cast<const int*>(NULL));
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(static_cast<const int*>(NULL),
+                                 reinterpret_cast<const int*>(0x1234)),
+                       "0x1234");
+}
+
+// A class that supports binary comparison operators but not streaming.
+class UnprintableChar {
+ public:
+  explicit UnprintableChar(char ch) : char_(ch) {}
+
+  bool operator==(const UnprintableChar& rhs) const {
+    return char_ == rhs.char_;
+  }
+  bool operator!=(const UnprintableChar& rhs) const {
+    return char_ != rhs.char_;
+  }
+  bool operator<(const UnprintableChar& rhs) const {
+    return char_ < rhs.char_;
+  }
+  bool operator<=(const UnprintableChar& rhs) const {
+    return char_ <= rhs.char_;
+  }
+  bool operator>(const UnprintableChar& rhs) const {
+    return char_ > rhs.char_;
+  }
+  bool operator>=(const UnprintableChar& rhs) const {
+    return char_ >= rhs.char_;
+  }
+
+ private:
+  char char_;
+};
+
+// Tests that ASSERT_EQ() and friends don't require the arguments to
+// be printable.
+TEST(ComparisonAssertionTest, AcceptsUnprintableArgs) {
+  const UnprintableChar x('x'), y('y');
+  ASSERT_EQ(x, x);
+  EXPECT_NE(x, y);
+  ASSERT_LT(x, y);
+  EXPECT_LE(x, y);
+  ASSERT_GT(y, x);
+  EXPECT_GE(x, x);
+
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(x, y), "1-byte object <78>");
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(x, y), "1-byte object <79>");
+  EXPECT_NONFATAL_FAILURE(EXPECT_LT(y, y), "1-byte object <79>");
+  EXPECT_NONFATAL_FAILURE(EXPECT_GT(x, y), "1-byte object <78>");
+  EXPECT_NONFATAL_FAILURE(EXPECT_GT(x, y), "1-byte object <79>");
+
+  // Code tested by EXPECT_FATAL_FAILURE cannot reference local
+  // variables, so we have to write UnprintableChar('x') instead of x.
+#ifndef __BORLANDC__
+  // ICE's in C++Builder.
+  EXPECT_FATAL_FAILURE(ASSERT_NE(UnprintableChar('x'), UnprintableChar('x')),
+                       "1-byte object <78>");
+  EXPECT_FATAL_FAILURE(ASSERT_LE(UnprintableChar('y'), UnprintableChar('x')),
+                       "1-byte object <78>");
+#endif
+  EXPECT_FATAL_FAILURE(ASSERT_LE(UnprintableChar('y'), UnprintableChar('x')),
+                       "1-byte object <79>");
+  EXPECT_FATAL_FAILURE(ASSERT_GE(UnprintableChar('x'), UnprintableChar('y')),
+                       "1-byte object <78>");
+  EXPECT_FATAL_FAILURE(ASSERT_GE(UnprintableChar('x'), UnprintableChar('y')),
+                       "1-byte object <79>");
+}
+
+// Tests the FRIEND_TEST macro.
+
+// This class has a private member we want to test.  We will test it
+// both in a TEST and in a TEST_F.
+class Foo {
+ public:
+  Foo() {}
+
+ private:
+  int Bar() const { return 1; }
+
+  // Declares the friend tests that can access the private member
+  // Bar().
+  FRIEND_TEST(FRIEND_TEST_Test, TEST);
+  FRIEND_TEST(FRIEND_TEST_Test2, TEST_F);
+};
+
+// Tests that the FRIEND_TEST declaration allows a TEST to access a
+// class's private members.  This should compile.
+TEST(FRIEND_TEST_Test, TEST) {
+  ASSERT_EQ(1, Foo().Bar());
+}
+
+// The fixture needed to test using FRIEND_TEST with TEST_F.
+class FRIEND_TEST_Test2 : public Test {
+ protected:
+  Foo foo;
+};
+
+// Tests that the FRIEND_TEST declaration allows a TEST_F to access a
+// class's private members.  This should compile.
+TEST_F(FRIEND_TEST_Test2, TEST_F) {
+  ASSERT_EQ(1, foo.Bar());
+}
+
+// Tests the life cycle of Test objects.
+
+// The test fixture for testing the life cycle of Test objects.
+//
+// This class counts the number of live test objects that uses this
+// fixture.
+class TestLifeCycleTest : public Test {
+ protected:
+  // Constructor.  Increments the number of test objects that uses
+  // this fixture.
+  TestLifeCycleTest() { count_++; }
+
+  // Destructor.  Decrements the number of test objects that uses this
+  // fixture.
+  ~TestLifeCycleTest() { count_--; }
+
+  // Returns the number of live test objects that uses this fixture.
+  int count() const { return count_; }
+
+ private:
+  static int count_;
+};
+
+int TestLifeCycleTest::count_ = 0;
+
+// Tests the life cycle of test objects.
+TEST_F(TestLifeCycleTest, Test1) {
+  // There should be only one test object in this test case that's
+  // currently alive.
+  ASSERT_EQ(1, count());
+}
+
+// Tests the life cycle of test objects.
+TEST_F(TestLifeCycleTest, Test2) {
+  // After Test1 is done and Test2 is started, there should still be
+  // only one live test object, as the object for Test1 should've been
+  // deleted.
+  ASSERT_EQ(1, count());
+}
+
+}  // namespace
+
+// Tests that the copy constructor works when it is NOT optimized away by
+// the compiler.
+TEST(AssertionResultTest, CopyConstructorWorksWhenNotOptimied) {
+  // Checks that the copy constructor doesn't try to dereference NULL pointers
+  // in the source object.
+  AssertionResult r1 = AssertionSuccess();
+  AssertionResult r2 = r1;
+  // The following line is added to prevent the compiler from optimizing
+  // away the constructor call.
+  r1 << "abc";
+
+  AssertionResult r3 = r1;
+  EXPECT_EQ(static_cast<bool>(r3), static_cast<bool>(r1));
+  EXPECT_STREQ("abc", r1.message());
+}
+
+// Tests that AssertionSuccess and AssertionFailure construct
+// AssertionResult objects as expected.
+TEST(AssertionResultTest, ConstructionWorks) {
+  AssertionResult r1 = AssertionSuccess();
+  EXPECT_TRUE(r1);
+  EXPECT_STREQ("", r1.message());
+
+  AssertionResult r2 = AssertionSuccess() << "abc";
+  EXPECT_TRUE(r2);
+  EXPECT_STREQ("abc", r2.message());
+
+  AssertionResult r3 = AssertionFailure();
+  EXPECT_FALSE(r3);
+  EXPECT_STREQ("", r3.message());
+
+  AssertionResult r4 = AssertionFailure() << "def";
+  EXPECT_FALSE(r4);
+  EXPECT_STREQ("def", r4.message());
+
+  AssertionResult r5 = AssertionFailure(Message() << "ghi");
+  EXPECT_FALSE(r5);
+  EXPECT_STREQ("ghi", r5.message());
+}
+
+// Tests that the negation flips the predicate result but keeps the message.
+TEST(AssertionResultTest, NegationWorks) {
+  AssertionResult r1 = AssertionSuccess() << "abc";
+  EXPECT_FALSE(!r1);
+  EXPECT_STREQ("abc", (!r1).message());
+
+  AssertionResult r2 = AssertionFailure() << "def";
+  EXPECT_TRUE(!r2);
+  EXPECT_STREQ("def", (!r2).message());
+}
+
+TEST(AssertionResultTest, StreamingWorks) {
+  AssertionResult r = AssertionSuccess();
+  r << "abc" << 'd' << 0 << true;
+  EXPECT_STREQ("abcd0true", r.message());
+}
+
+TEST(AssertionResultTest, CanStreamOstreamManipulators) {
+  AssertionResult r = AssertionSuccess();
+  r << "Data" << std::endl << std::flush << std::ends << "Will be visible";
+  EXPECT_STREQ("Data\n\\0Will be visible", r.message());
+}
+
+// Tests streaming a user type whose definition and operator << are
+// both in the global namespace.
+class Base {
+ public:
+  explicit Base(int an_x) : x_(an_x) {}
+  int x() const { return x_; }
+ private:
+  int x_;
+};
+std::ostream& operator<<(std::ostream& os,
+                         const Base& val) {
+  return os << val.x();
+}
+std::ostream& operator<<(std::ostream& os,
+                         const Base* pointer) {
+  return os << "(" << pointer->x() << ")";
+}
+
+TEST(MessageTest, CanStreamUserTypeInGlobalNameSpace) {
+  Message msg;
+  Base a(1);
+
+  msg << a << &a;  // Uses ::operator<<.
+  EXPECT_STREQ("1(1)", msg.GetString().c_str());
+}
+
+// Tests streaming a user type whose definition and operator<< are
+// both in an unnamed namespace.
+namespace {
+class MyTypeInUnnamedNameSpace : public Base {
+ public:
+  explicit MyTypeInUnnamedNameSpace(int an_x): Base(an_x) {}
+};
+std::ostream& operator<<(std::ostream& os,
+                         const MyTypeInUnnamedNameSpace& val) {
+  return os << val.x();
+}
+std::ostream& operator<<(std::ostream& os,
+                         const MyTypeInUnnamedNameSpace* pointer) {
+  return os << "(" << pointer->x() << ")";
+}
+}  // namespace
+
+TEST(MessageTest, CanStreamUserTypeInUnnamedNameSpace) {
+  Message msg;
+  MyTypeInUnnamedNameSpace a(1);
+
+  msg << a << &a;  // Uses <unnamed_namespace>::operator<<.
+  EXPECT_STREQ("1(1)", msg.GetString().c_str());
+}
+
+// Tests streaming a user type whose definition and operator<< are
+// both in a user namespace.
+namespace namespace1 {
+class MyTypeInNameSpace1 : public Base {
+ public:
+  explicit MyTypeInNameSpace1(int an_x): Base(an_x) {}
+};
+std::ostream& operator<<(std::ostream& os,
+                         const MyTypeInNameSpace1& val) {
+  return os << val.x();
+}
+std::ostream& operator<<(std::ostream& os,
+                         const MyTypeInNameSpace1* pointer) {
+  return os << "(" << pointer->x() << ")";
+}
+}  // namespace namespace1
+
+TEST(MessageTest, CanStreamUserTypeInUserNameSpace) {
+  Message msg;
+  namespace1::MyTypeInNameSpace1 a(1);
+
+  msg << a << &a;  // Uses namespace1::operator<<.
+  EXPECT_STREQ("1(1)", msg.GetString().c_str());
+}
+
+// Tests streaming a user type whose definition is in a user namespace
+// but whose operator<< is in the global namespace.
+namespace namespace2 {
+class MyTypeInNameSpace2 : public ::Base {
+ public:
+  explicit MyTypeInNameSpace2(int an_x): Base(an_x) {}
+};
+}  // namespace namespace2
+std::ostream& operator<<(std::ostream& os,
+                         const namespace2::MyTypeInNameSpace2& val) {
+  return os << val.x();
+}
+std::ostream& operator<<(std::ostream& os,
+                         const namespace2::MyTypeInNameSpace2* pointer) {
+  return os << "(" << pointer->x() << ")";
+}
+
+TEST(MessageTest, CanStreamUserTypeInUserNameSpaceWithStreamOperatorInGlobal) {
+  Message msg;
+  namespace2::MyTypeInNameSpace2 a(1);
+
+  msg << a << &a;  // Uses ::operator<<.
+  EXPECT_STREQ("1(1)", msg.GetString().c_str());
+}
+
+// Tests streaming NULL pointers to testing::Message.
+TEST(MessageTest, NullPointers) {
+  Message msg;
+  char* const p1 = NULL;
+  unsigned char* const p2 = NULL;
+  int* p3 = NULL;
+  double* p4 = NULL;
+  bool* p5 = NULL;
+  Message* p6 = NULL;
+
+  msg << p1 << p2 << p3 << p4 << p5 << p6;
+  ASSERT_STREQ("(null)(null)(null)(null)(null)(null)",
+               msg.GetString().c_str());
+}
+
+// Tests streaming wide strings to testing::Message.
+TEST(MessageTest, WideStrings) {
+  // Streams a NULL of type const wchar_t*.
+  const wchar_t* const_wstr = NULL;
+  EXPECT_STREQ("(null)",
+               (Message() << const_wstr).GetString().c_str());
+
+  // Streams a NULL of type wchar_t*.
+  wchar_t* wstr = NULL;
+  EXPECT_STREQ("(null)",
+               (Message() << wstr).GetString().c_str());
+
+  // Streams a non-NULL of type const wchar_t*.
+  const_wstr = L"abc\x8119";
+  EXPECT_STREQ("abc\xe8\x84\x99",
+               (Message() << const_wstr).GetString().c_str());
+
+  // Streams a non-NULL of type wchar_t*.
+  wstr = const_cast<wchar_t*>(const_wstr);
+  EXPECT_STREQ("abc\xe8\x84\x99",
+               (Message() << wstr).GetString().c_str());
+}
+
+
+// This line tests that we can define tests in the testing namespace.
+namespace testing {
+
+// Tests the TestInfo class.
+
+class TestInfoTest : public Test {
+ protected:
+  static const TestInfo* GetTestInfo(const char* test_name) {
+    const TestCase* const test_case = GetUnitTestImpl()->
+        GetTestCase("TestInfoTest", "", NULL, NULL);
+
+    for (int i = 0; i < test_case->total_test_count(); ++i) {
+      const TestInfo* const test_info = test_case->GetTestInfo(i);
+      if (strcmp(test_name, test_info->name()) == 0)
+        return test_info;
+    }
+    return NULL;
+  }
+
+  static const TestResult* GetTestResult(
+      const TestInfo* test_info) {
+    return test_info->result();
+  }
+};
+
+// Tests TestInfo::test_case_name() and TestInfo::name().
+TEST_F(TestInfoTest, Names) {
+  const TestInfo* const test_info = GetTestInfo("Names");
+
+  ASSERT_STREQ("TestInfoTest", test_info->test_case_name());
+  ASSERT_STREQ("Names", test_info->name());
+}
+
+// Tests TestInfo::result().
+TEST_F(TestInfoTest, result) {
+  const TestInfo* const test_info = GetTestInfo("result");
+
+  // Initially, there is no TestPartResult for this test.
+  ASSERT_EQ(0, GetTestResult(test_info)->total_part_count());
+
+  // After the previous assertion, there is still none.
+  ASSERT_EQ(0, GetTestResult(test_info)->total_part_count());
+}
+
+// Tests setting up and tearing down a test case.
+
+class SetUpTestCaseTest : public Test {
+ protected:
+  // This will be called once before the first test in this test case
+  // is run.
+  static void SetUpTestCase() {
+    printf("Setting up the test case . . .\n");
+
+    // Initializes some shared resource.  In this simple example, we
+    // just create a C string.  More complex stuff can be done if
+    // desired.
+    shared_resource_ = "123";
+
+    // Increments the number of test cases that have been set up.
+    counter_++;
+
+    // SetUpTestCase() should be called only once.
+    EXPECT_EQ(1, counter_);
+  }
+
+  // This will be called once after the last test in this test case is
+  // run.
+  static void TearDownTestCase() {
+    printf("Tearing down the test case . . .\n");
+
+    // Decrements the number of test cases that have been set up.
+    counter_--;
+
+    // TearDownTestCase() should be called only once.
+    EXPECT_EQ(0, counter_);
+
+    // Cleans up the shared resource.
+    shared_resource_ = NULL;
+  }
+
+  // This will be called before each test in this test case.
+  virtual void SetUp() {
+    // SetUpTestCase() should be called only once, so counter_ should
+    // always be 1.
+    EXPECT_EQ(1, counter_);
+  }
+
+  // Number of test cases that have been set up.
+  static int counter_;
+
+  // Some resource to be shared by all tests in this test case.
+  static const char* shared_resource_;
+};
+
+int SetUpTestCaseTest::counter_ = 0;
+const char* SetUpTestCaseTest::shared_resource_ = NULL;
+
+// A test that uses the shared resource.
+TEST_F(SetUpTestCaseTest, Test1) {
+  EXPECT_STRNE(NULL, shared_resource_);
+}
+
+// Another test that uses the shared resource.
+TEST_F(SetUpTestCaseTest, Test2) {
+  EXPECT_STREQ("123", shared_resource_);
+}
+
+// The InitGoogleTestTest test case tests testing::InitGoogleTest().
+
+// The Flags struct stores a copy of all Google Test flags.
+struct Flags {
+  // Constructs a Flags struct where each flag has its default value.
+  Flags() : also_run_disabled_tests(false),
+            break_on_failure(false),
+            catch_exceptions(false),
+            death_test_use_fork(false),
+            filter(""),
+            list_tests(false),
+            output(""),
+            print_time(true),
+            random_seed(0),
+            repeat(1),
+            shuffle(false),
+            stack_trace_depth(kMaxStackTraceDepth),
+            stream_result_to(""),
+            throw_on_failure(false) {}
+
+  // Factory methods.
+
+  // Creates a Flags struct where the gtest_also_run_disabled_tests flag has
+  // the given value.
+  static Flags AlsoRunDisabledTests(bool also_run_disabled_tests) {
+    Flags flags;
+    flags.also_run_disabled_tests = also_run_disabled_tests;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_break_on_failure flag has
+  // the given value.
+  static Flags BreakOnFailure(bool break_on_failure) {
+    Flags flags;
+    flags.break_on_failure = break_on_failure;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_catch_exceptions flag has
+  // the given value.
+  static Flags CatchExceptions(bool catch_exceptions) {
+    Flags flags;
+    flags.catch_exceptions = catch_exceptions;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_death_test_use_fork flag has
+  // the given value.
+  static Flags DeathTestUseFork(bool death_test_use_fork) {
+    Flags flags;
+    flags.death_test_use_fork = death_test_use_fork;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_filter flag has the given
+  // value.
+  static Flags Filter(const char* filter) {
+    Flags flags;
+    flags.filter = filter;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_list_tests flag has the
+  // given value.
+  static Flags ListTests(bool list_tests) {
+    Flags flags;
+    flags.list_tests = list_tests;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_output flag has the given
+  // value.
+  static Flags Output(const char* output) {
+    Flags flags;
+    flags.output = output;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_print_time flag has the given
+  // value.
+  static Flags PrintTime(bool print_time) {
+    Flags flags;
+    flags.print_time = print_time;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_random_seed flag has
+  // the given value.
+  static Flags RandomSeed(Int32 random_seed) {
+    Flags flags;
+    flags.random_seed = random_seed;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_repeat flag has the given
+  // value.
+  static Flags Repeat(Int32 repeat) {
+    Flags flags;
+    flags.repeat = repeat;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_shuffle flag has
+  // the given value.
+  static Flags Shuffle(bool shuffle) {
+    Flags flags;
+    flags.shuffle = shuffle;
+    return flags;
+  }
+
+  // Creates a Flags struct where the GTEST_FLAG(stack_trace_depth) flag has
+  // the given value.
+  static Flags StackTraceDepth(Int32 stack_trace_depth) {
+    Flags flags;
+    flags.stack_trace_depth = stack_trace_depth;
+    return flags;
+  }
+
+  // Creates a Flags struct where the GTEST_FLAG(stream_result_to) flag has
+  // the given value.
+  static Flags StreamResultTo(const char* stream_result_to) {
+    Flags flags;
+    flags.stream_result_to = stream_result_to;
+    return flags;
+  }
+
+  // Creates a Flags struct where the gtest_throw_on_failure flag has
+  // the given value.
+  static Flags ThrowOnFailure(bool throw_on_failure) {
+    Flags flags;
+    flags.throw_on_failure = throw_on_failure;
+    return flags;
+  }
+
+  // These fields store the flag values.
+  bool also_run_disabled_tests;
+  bool break_on_failure;
+  bool catch_exceptions;
+  bool death_test_use_fork;
+  const char* filter;
+  bool list_tests;
+  const char* output;
+  bool print_time;
+  Int32 random_seed;
+  Int32 repeat;
+  bool shuffle;
+  Int32 stack_trace_depth;
+  const char* stream_result_to;
+  bool throw_on_failure;
+};
+
+// Fixture for testing InitGoogleTest().
+class InitGoogleTestTest : public Test {
+ protected:
+  // Clears the flags before each test.
+  virtual void SetUp() {
+    GTEST_FLAG(also_run_disabled_tests) = false;
+    GTEST_FLAG(break_on_failure) = false;
+    GTEST_FLAG(catch_exceptions) = false;
+    GTEST_FLAG(death_test_use_fork) = false;
+    GTEST_FLAG(filter) = "";
+    GTEST_FLAG(list_tests) = false;
+    GTEST_FLAG(output) = "";
+    GTEST_FLAG(print_time) = true;
+    GTEST_FLAG(random_seed) = 0;
+    GTEST_FLAG(repeat) = 1;
+    GTEST_FLAG(shuffle) = false;
+    GTEST_FLAG(stack_trace_depth) = kMaxStackTraceDepth;
+    GTEST_FLAG(stream_result_to) = "";
+    GTEST_FLAG(throw_on_failure) = false;
+  }
+
+  // Asserts that two narrow or wide string arrays are equal.
+  template <typename CharType>
+  static void AssertStringArrayEq(size_t size1, CharType** array1,
+                                  size_t size2, CharType** array2) {
+    ASSERT_EQ(size1, size2) << " Array sizes different.";
+
+    for (size_t i = 0; i != size1; i++) {
+      ASSERT_STREQ(array1[i], array2[i]) << " where i == " << i;
+    }
+  }
+
+  // Verifies that the flag values match the expected values.
+  static void CheckFlags(const Flags& expected) {
+    EXPECT_EQ(expected.also_run_disabled_tests,
+              GTEST_FLAG(also_run_disabled_tests));
+    EXPECT_EQ(expected.break_on_failure, GTEST_FLAG(break_on_failure));
+    EXPECT_EQ(expected.catch_exceptions, GTEST_FLAG(catch_exceptions));
+    EXPECT_EQ(expected.death_test_use_fork, GTEST_FLAG(death_test_use_fork));
+    EXPECT_STREQ(expected.filter, GTEST_FLAG(filter).c_str());
+    EXPECT_EQ(expected.list_tests, GTEST_FLAG(list_tests));
+    EXPECT_STREQ(expected.output, GTEST_FLAG(output).c_str());
+    EXPECT_EQ(expected.print_time, GTEST_FLAG(print_time));
+    EXPECT_EQ(expected.random_seed, GTEST_FLAG(random_seed));
+    EXPECT_EQ(expected.repeat, GTEST_FLAG(repeat));
+    EXPECT_EQ(expected.shuffle, GTEST_FLAG(shuffle));
+    EXPECT_EQ(expected.stack_trace_depth, GTEST_FLAG(stack_trace_depth));
+    EXPECT_STREQ(expected.stream_result_to,
+                 GTEST_FLAG(stream_result_to).c_str());
+    EXPECT_EQ(expected.throw_on_failure, GTEST_FLAG(throw_on_failure));
+  }
+
+  // Parses a command line (specified by argc1 and argv1), then
+  // verifies that the flag values are expected and that the
+  // recognized flags are removed from the command line.
+  template <typename CharType>
+  static void TestParsingFlags(int argc1, const CharType** argv1,
+                               int argc2, const CharType** argv2,
+                               const Flags& expected, bool should_print_help) {
+    const bool saved_help_flag = ::testing::internal::g_help_flag;
+    ::testing::internal::g_help_flag = false;
+
+#if GTEST_HAS_STREAM_REDIRECTION
+    CaptureStdout();
+#endif
+
+    // Parses the command line.
+    internal::ParseGoogleTestFlagsOnly(&argc1, const_cast<CharType**>(argv1));
+
+#if GTEST_HAS_STREAM_REDIRECTION
+    const String captured_stdout = GetCapturedStdout();
+#endif
+
+    // Verifies the flag values.
+    CheckFlags(expected);
+
+    // Verifies that the recognized flags are removed from the command
+    // line.
+    AssertStringArrayEq(argc1 + 1, argv1, argc2 + 1, argv2);
+
+    // ParseGoogleTestFlagsOnly should neither set g_help_flag nor print the
+    // help message for the flags it recognizes.
+    EXPECT_EQ(should_print_help, ::testing::internal::g_help_flag);
+
+#if GTEST_HAS_STREAM_REDIRECTION
+    const char* const expected_help_fragment =
+        "This program contains tests written using";
+    if (should_print_help) {
+      EXPECT_PRED_FORMAT2(IsSubstring, expected_help_fragment, captured_stdout);
+    } else {
+      EXPECT_PRED_FORMAT2(IsNotSubstring,
+                          expected_help_fragment, captured_stdout);
+    }
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+    ::testing::internal::g_help_flag = saved_help_flag;
+  }
+
+  // This macro wraps TestParsingFlags s.t. the user doesn't need
+  // to specify the array sizes.
+
+#define GTEST_TEST_PARSING_FLAGS_(argv1, argv2, expected, should_print_help) \
+  TestParsingFlags(sizeof(argv1)/sizeof(*argv1) - 1, argv1, \
+                   sizeof(argv2)/sizeof(*argv2) - 1, argv2, \
+                   expected, should_print_help)
+};
+
+// Tests parsing an empty command line.
+TEST_F(InitGoogleTestTest, Empty) {
+  const char* argv[] = {
+    NULL
+  };
+
+  const char* argv2[] = {
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags(), false);
+}
+
+// Tests parsing a command line that has no flag.
+TEST_F(InitGoogleTestTest, NoFlag) {
+  const char* argv[] = {
+    "foo.exe",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags(), false);
+}
+
+// Tests parsing a bad --gtest_filter flag.
+TEST_F(InitGoogleTestTest, FilterBad) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_filter",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    "--gtest_filter",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter(""), true);
+}
+
+// Tests parsing an empty --gtest_filter flag.
+TEST_F(InitGoogleTestTest, FilterEmpty) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_filter=",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter(""), false);
+}
+
+// Tests parsing a non-empty --gtest_filter flag.
+TEST_F(InitGoogleTestTest, FilterNonEmpty) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_filter=abc",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter("abc"), false);
+}
+
+// Tests parsing --gtest_break_on_failure.
+TEST_F(InitGoogleTestTest, BreakOnFailureWithoutValue) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_break_on_failure",
+    NULL
+};
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::BreakOnFailure(true), false);
+}
+
+// Tests parsing --gtest_break_on_failure=0.
+TEST_F(InitGoogleTestTest, BreakOnFailureFalse_0) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_break_on_failure=0",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::BreakOnFailure(false), false);
+}
+
+// Tests parsing --gtest_break_on_failure=f.
+TEST_F(InitGoogleTestTest, BreakOnFailureFalse_f) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_break_on_failure=f",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::BreakOnFailure(false), false);
+}
+
+// Tests parsing --gtest_break_on_failure=F.
+TEST_F(InitGoogleTestTest, BreakOnFailureFalse_F) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_break_on_failure=F",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::BreakOnFailure(false), false);
+}
+
+// Tests parsing a --gtest_break_on_failure flag that has a "true"
+// definition.
+TEST_F(InitGoogleTestTest, BreakOnFailureTrue) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_break_on_failure=1",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::BreakOnFailure(true), false);
+}
+
+// Tests parsing --gtest_catch_exceptions.
+TEST_F(InitGoogleTestTest, CatchExceptions) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_catch_exceptions",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::CatchExceptions(true), false);
+}
+
+// Tests parsing --gtest_death_test_use_fork.
+TEST_F(InitGoogleTestTest, DeathTestUseFork) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_death_test_use_fork",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::DeathTestUseFork(true), false);
+}
+
+// Tests having the same flag twice with different values.  The
+// expected behavior is that the one coming last takes precedence.
+TEST_F(InitGoogleTestTest, DuplicatedFlags) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_filter=a",
+    "--gtest_filter=b",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter("b"), false);
+}
+
+// Tests having an unrecognized flag on the command line.
+TEST_F(InitGoogleTestTest, UnrecognizedFlag) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_break_on_failure",
+    "bar",  // Unrecognized by Google Test.
+    "--gtest_filter=b",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    "bar",
+    NULL
+  };
+
+  Flags flags;
+  flags.break_on_failure = true;
+  flags.filter = "b";
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, flags, false);
+}
+
+// Tests having a --gtest_list_tests flag
+TEST_F(InitGoogleTestTest, ListTestsFlag) {
+    const char* argv[] = {
+      "foo.exe",
+      "--gtest_list_tests",
+      NULL
+    };
+
+    const char* argv2[] = {
+      "foo.exe",
+      NULL
+    };
+
+    GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(true), false);
+}
+
+// Tests having a --gtest_list_tests flag with a "true" value
+TEST_F(InitGoogleTestTest, ListTestsTrue) {
+    const char* argv[] = {
+      "foo.exe",
+      "--gtest_list_tests=1",
+      NULL
+    };
+
+    const char* argv2[] = {
+      "foo.exe",
+      NULL
+    };
+
+    GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(true), false);
+}
+
+// Tests having a --gtest_list_tests flag with a "false" value
+TEST_F(InitGoogleTestTest, ListTestsFalse) {
+    const char* argv[] = {
+      "foo.exe",
+      "--gtest_list_tests=0",
+      NULL
+    };
+
+    const char* argv2[] = {
+      "foo.exe",
+      NULL
+    };
+
+    GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(false), false);
+}
+
+// Tests parsing --gtest_list_tests=f.
+TEST_F(InitGoogleTestTest, ListTestsFalse_f) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_list_tests=f",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(false), false);
+}
+
+// Tests parsing --gtest_list_tests=F.
+TEST_F(InitGoogleTestTest, ListTestsFalse_F) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_list_tests=F",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(false), false);
+}
+
+// Tests parsing --gtest_output (invalid).
+TEST_F(InitGoogleTestTest, OutputEmpty) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_output",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    "--gtest_output",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags(), true);
+}
+
+// Tests parsing --gtest_output=xml
+TEST_F(InitGoogleTestTest, OutputXml) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_output=xml",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Output("xml"), false);
+}
+
+// Tests parsing --gtest_output=xml:file
+TEST_F(InitGoogleTestTest, OutputXmlFile) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_output=xml:file",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Output("xml:file"), false);
+}
+
+// Tests parsing --gtest_output=xml:directory/path/
+TEST_F(InitGoogleTestTest, OutputXmlDirectory) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_output=xml:directory/path/",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2,
+                            Flags::Output("xml:directory/path/"), false);
+}
+
+// Tests having a --gtest_print_time flag
+TEST_F(InitGoogleTestTest, PrintTimeFlag) {
+    const char* argv[] = {
+      "foo.exe",
+      "--gtest_print_time",
+      NULL
+    };
+
+    const char* argv2[] = {
+      "foo.exe",
+      NULL
+    };
+
+    GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::PrintTime(true), false);
+}
+
+// Tests having a --gtest_print_time flag with a "true" value
+TEST_F(InitGoogleTestTest, PrintTimeTrue) {
+    const char* argv[] = {
+      "foo.exe",
+      "--gtest_print_time=1",
+      NULL
+    };
+
+    const char* argv2[] = {
+      "foo.exe",
+      NULL
+    };
+
+    GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::PrintTime(true), false);
+}
+
+// Tests having a --gtest_print_time flag with a "false" value
+TEST_F(InitGoogleTestTest, PrintTimeFalse) {
+    const char* argv[] = {
+      "foo.exe",
+      "--gtest_print_time=0",
+      NULL
+    };
+
+    const char* argv2[] = {
+      "foo.exe",
+      NULL
+    };
+
+    GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::PrintTime(false), false);
+}
+
+// Tests parsing --gtest_print_time=f.
+TEST_F(InitGoogleTestTest, PrintTimeFalse_f) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_print_time=f",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::PrintTime(false), false);
+}
+
+// Tests parsing --gtest_print_time=F.
+TEST_F(InitGoogleTestTest, PrintTimeFalse_F) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_print_time=F",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::PrintTime(false), false);
+}
+
+// Tests parsing --gtest_random_seed=number
+TEST_F(InitGoogleTestTest, RandomSeed) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_random_seed=1000",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::RandomSeed(1000), false);
+}
+
+// Tests parsing --gtest_repeat=number
+TEST_F(InitGoogleTestTest, Repeat) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_repeat=1000",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Repeat(1000), false);
+}
+
+// Tests having a --gtest_also_run_disabled_tests flag
+TEST_F(InitGoogleTestTest, AlsoRunDisabledTestsFlag) {
+    const char* argv[] = {
+      "foo.exe",
+      "--gtest_also_run_disabled_tests",
+      NULL
+    };
+
+    const char* argv2[] = {
+      "foo.exe",
+      NULL
+    };
+
+    GTEST_TEST_PARSING_FLAGS_(argv, argv2,
+                              Flags::AlsoRunDisabledTests(true), false);
+}
+
+// Tests having a --gtest_also_run_disabled_tests flag with a "true" value
+TEST_F(InitGoogleTestTest, AlsoRunDisabledTestsTrue) {
+    const char* argv[] = {
+      "foo.exe",
+      "--gtest_also_run_disabled_tests=1",
+      NULL
+    };
+
+    const char* argv2[] = {
+      "foo.exe",
+      NULL
+    };
+
+    GTEST_TEST_PARSING_FLAGS_(argv, argv2,
+                              Flags::AlsoRunDisabledTests(true), false);
+}
+
+// Tests having a --gtest_also_run_disabled_tests flag with a "false" value
+TEST_F(InitGoogleTestTest, AlsoRunDisabledTestsFalse) {
+    const char* argv[] = {
+      "foo.exe",
+      "--gtest_also_run_disabled_tests=0",
+      NULL
+    };
+
+    const char* argv2[] = {
+      "foo.exe",
+      NULL
+    };
+
+    GTEST_TEST_PARSING_FLAGS_(argv, argv2,
+                              Flags::AlsoRunDisabledTests(false), false);
+}
+
+// Tests parsing --gtest_shuffle.
+TEST_F(InitGoogleTestTest, ShuffleWithoutValue) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_shuffle",
+    NULL
+};
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Shuffle(true), false);
+}
+
+// Tests parsing --gtest_shuffle=0.
+TEST_F(InitGoogleTestTest, ShuffleFalse_0) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_shuffle=0",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Shuffle(false), false);
+}
+
+// Tests parsing a --gtest_shuffle flag that has a "true"
+// definition.
+TEST_F(InitGoogleTestTest, ShuffleTrue) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_shuffle=1",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Shuffle(true), false);
+}
+
+// Tests parsing --gtest_stack_trace_depth=number.
+TEST_F(InitGoogleTestTest, StackTraceDepth) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_stack_trace_depth=5",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::StackTraceDepth(5), false);
+}
+
+TEST_F(InitGoogleTestTest, StreamResultTo) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_stream_result_to=localhost:1234",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(
+      argv, argv2, Flags::StreamResultTo("localhost:1234"), false);
+}
+
+// Tests parsing --gtest_throw_on_failure.
+TEST_F(InitGoogleTestTest, ThrowOnFailureWithoutValue) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_throw_on_failure",
+    NULL
+};
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ThrowOnFailure(true), false);
+}
+
+// Tests parsing --gtest_throw_on_failure=0.
+TEST_F(InitGoogleTestTest, ThrowOnFailureFalse_0) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_throw_on_failure=0",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ThrowOnFailure(false), false);
+}
+
+// Tests parsing a --gtest_throw_on_failure flag that has a "true"
+// definition.
+TEST_F(InitGoogleTestTest, ThrowOnFailureTrue) {
+  const char* argv[] = {
+    "foo.exe",
+    "--gtest_throw_on_failure=1",
+    NULL
+  };
+
+  const char* argv2[] = {
+    "foo.exe",
+    NULL
+  };
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ThrowOnFailure(true), false);
+}
+
+#if GTEST_OS_WINDOWS
+// Tests parsing wide strings.
+TEST_F(InitGoogleTestTest, WideStrings) {
+  const wchar_t* argv[] = {
+    L"foo.exe",
+    L"--gtest_filter=Foo*",
+    L"--gtest_list_tests=1",
+    L"--gtest_break_on_failure",
+    L"--non_gtest_flag",
+    NULL
+  };
+
+  const wchar_t* argv2[] = {
+    L"foo.exe",
+    L"--non_gtest_flag",
+    NULL
+  };
+
+  Flags expected_flags;
+  expected_flags.break_on_failure = true;
+  expected_flags.filter = "Foo*";
+  expected_flags.list_tests = true;
+
+  GTEST_TEST_PARSING_FLAGS_(argv, argv2, expected_flags, false);
+}
+#endif  // GTEST_OS_WINDOWS
+
+// Tests current_test_info() in UnitTest.
+class CurrentTestInfoTest : public Test {
+ protected:
+  // Tests that current_test_info() returns NULL before the first test in
+  // the test case is run.
+  static void SetUpTestCase() {
+    // There should be no tests running at this point.
+    const TestInfo* test_info =
+      UnitTest::GetInstance()->current_test_info();
+    EXPECT_TRUE(test_info == NULL)
+        << "There should be no tests running at this point.";
+  }
+
+  // Tests that current_test_info() returns NULL after the last test in
+  // the test case has run.
+  static void TearDownTestCase() {
+    const TestInfo* test_info =
+      UnitTest::GetInstance()->current_test_info();
+    EXPECT_TRUE(test_info == NULL)
+        << "There should be no tests running at this point.";
+  }
+};
+
+// Tests that current_test_info() returns TestInfo for currently running
+// test by checking the expected test name against the actual one.
+TEST_F(CurrentTestInfoTest, WorksForFirstTestInATestCase) {
+  const TestInfo* test_info =
+    UnitTest::GetInstance()->current_test_info();
+  ASSERT_TRUE(NULL != test_info)
+      << "There is a test running so we should have a valid TestInfo.";
+  EXPECT_STREQ("CurrentTestInfoTest", test_info->test_case_name())
+      << "Expected the name of the currently running test case.";
+  EXPECT_STREQ("WorksForFirstTestInATestCase", test_info->name())
+      << "Expected the name of the currently running test.";
+}
+
+// Tests that current_test_info() returns TestInfo for currently running
+// test by checking the expected test name against the actual one.  We
+// use this test to see that the TestInfo object actually changed from
+// the previous invocation.
+TEST_F(CurrentTestInfoTest, WorksForSecondTestInATestCase) {
+  const TestInfo* test_info =
+    UnitTest::GetInstance()->current_test_info();
+  ASSERT_TRUE(NULL != test_info)
+      << "There is a test running so we should have a valid TestInfo.";
+  EXPECT_STREQ("CurrentTestInfoTest", test_info->test_case_name())
+      << "Expected the name of the currently running test case.";
+  EXPECT_STREQ("WorksForSecondTestInATestCase", test_info->name())
+      << "Expected the name of the currently running test.";
+}
+
+}  // namespace testing
+
+// These two lines test that we can define tests in a namespace that
+// has the name "testing" and is nested in another namespace.
+namespace my_namespace {
+namespace testing {
+
+// Makes sure that TEST knows to use ::testing::Test instead of
+// ::my_namespace::testing::Test.
+class Test {};
+
+// Makes sure that an assertion knows to use ::testing::Message instead of
+// ::my_namespace::testing::Message.
+class Message {};
+
+// Makes sure that an assertion knows to use
+// ::testing::AssertionResult instead of
+// ::my_namespace::testing::AssertionResult.
+class AssertionResult {};
+
+// Tests that an assertion that should succeed works as expected.
+TEST(NestedTestingNamespaceTest, Success) {
+  EXPECT_EQ(1, 1) << "This shouldn't fail.";
+}
+
+// Tests that an assertion that should fail works as expected.
+TEST(NestedTestingNamespaceTest, Failure) {
+  EXPECT_FATAL_FAILURE(FAIL() << "This failure is expected.",
+                       "This failure is expected.");
+}
+
+}  // namespace testing
+}  // namespace my_namespace
+
+// Tests that one can call superclass SetUp and TearDown methods--
+// that is, that they are not private.
+// No tests are based on this fixture; the test "passes" if it compiles
+// successfully.
+class ProtectedFixtureMethodsTest : public Test {
+ protected:
+  virtual void SetUp() {
+    Test::SetUp();
+  }
+  virtual void TearDown() {
+    Test::TearDown();
+  }
+};
+
+// StreamingAssertionsTest tests the streaming versions of a representative
+// sample of assertions.
+TEST(StreamingAssertionsTest, Unconditional) {
+  SUCCEED() << "expected success";
+  EXPECT_NONFATAL_FAILURE(ADD_FAILURE() << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(FAIL() << "expected failure",
+                       "expected failure");
+}
+
+#ifdef __BORLANDC__
+// Silences warnings: "Condition is always true", "Unreachable code"
+# pragma option push -w-ccc -w-rch
+#endif
+
+TEST(StreamingAssertionsTest, Truth) {
+  EXPECT_TRUE(true) << "unexpected failure";
+  ASSERT_TRUE(true) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(false) << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_TRUE(false) << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, Truth2) {
+  EXPECT_FALSE(false) << "unexpected failure";
+  ASSERT_FALSE(false) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(true) << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_FALSE(true) << "expected failure",
+                       "expected failure");
+}
+
+#ifdef __BORLANDC__
+// Restores warnings after previous "#pragma option push" supressed them
+# pragma option pop
+#endif
+
+TEST(StreamingAssertionsTest, IntegerEquals) {
+  EXPECT_EQ(1, 1) << "unexpected failure";
+  ASSERT_EQ(1, 1) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_EQ(1, 2) << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_EQ(1, 2) << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, IntegerLessThan) {
+  EXPECT_LT(1, 2) << "unexpected failure";
+  ASSERT_LT(1, 2) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_LT(2, 1) << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_LT(2, 1) << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, StringsEqual) {
+  EXPECT_STREQ("foo", "foo") << "unexpected failure";
+  ASSERT_STREQ("foo", "foo") << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_STREQ("foo", "bar") << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_STREQ("foo", "bar") << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, StringsNotEqual) {
+  EXPECT_STRNE("foo", "bar") << "unexpected failure";
+  ASSERT_STRNE("foo", "bar") << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRNE("foo", "foo") << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_STRNE("foo", "foo") << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, StringsEqualIgnoringCase) {
+  EXPECT_STRCASEEQ("foo", "FOO") << "unexpected failure";
+  ASSERT_STRCASEEQ("foo", "FOO") << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRCASEEQ("foo", "bar") << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_STRCASEEQ("foo", "bar") << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, StringNotEqualIgnoringCase) {
+  EXPECT_STRCASENE("foo", "bar") << "unexpected failure";
+  ASSERT_STRCASENE("foo", "bar") << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_STRCASENE("foo", "FOO") << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_STRCASENE("bar", "BAR") << "expected failure",
+                       "expected failure");
+}
+
+TEST(StreamingAssertionsTest, FloatingPointEquals) {
+  EXPECT_FLOAT_EQ(1.0, 1.0) << "unexpected failure";
+  ASSERT_FLOAT_EQ(1.0, 1.0) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(0.0, 1.0) << "expected failure",
+                          "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_FLOAT_EQ(0.0, 1.0) << "expected failure",
+                       "expected failure");
+}
+
+#if GTEST_HAS_EXCEPTIONS
+
+TEST(StreamingAssertionsTest, Throw) {
+  EXPECT_THROW(ThrowAnInteger(), int) << "unexpected failure";
+  ASSERT_THROW(ThrowAnInteger(), int) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_THROW(ThrowAnInteger(), bool) <<
+                          "expected failure", "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_THROW(ThrowAnInteger(), bool) <<
+                       "expected failure", "expected failure");
+}
+
+TEST(StreamingAssertionsTest, NoThrow) {
+  EXPECT_NO_THROW(ThrowNothing()) << "unexpected failure";
+  ASSERT_NO_THROW(ThrowNothing()) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW(ThrowAnInteger()) <<
+                          "expected failure", "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_NO_THROW(ThrowAnInteger()) <<
+                       "expected failure", "expected failure");
+}
+
+TEST(StreamingAssertionsTest, AnyThrow) {
+  EXPECT_ANY_THROW(ThrowAnInteger()) << "unexpected failure";
+  ASSERT_ANY_THROW(ThrowAnInteger()) << "unexpected failure";
+  EXPECT_NONFATAL_FAILURE(EXPECT_ANY_THROW(ThrowNothing()) <<
+                          "expected failure", "expected failure");
+  EXPECT_FATAL_FAILURE(ASSERT_ANY_THROW(ThrowNothing()) <<
+                       "expected failure", "expected failure");
+}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// Tests that Google Test correctly decides whether to use colors in the output.
+
+TEST(ColoredOutputTest, UsesColorsWhenGTestColorFlagIsYes) {
+  GTEST_FLAG(color) = "yes";
+
+  SetEnv("TERM", "xterm");  // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+  EXPECT_TRUE(ShouldUseColor(false));  // Stdout is not a TTY.
+
+  SetEnv("TERM", "dumb");  // TERM doesn't support colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+  EXPECT_TRUE(ShouldUseColor(false));  // Stdout is not a TTY.
+}
+
+TEST(ColoredOutputTest, UsesColorsWhenGTestColorFlagIsAliasOfYes) {
+  SetEnv("TERM", "dumb");  // TERM doesn't support colors.
+
+  GTEST_FLAG(color) = "True";
+  EXPECT_TRUE(ShouldUseColor(false));  // Stdout is not a TTY.
+
+  GTEST_FLAG(color) = "t";
+  EXPECT_TRUE(ShouldUseColor(false));  // Stdout is not a TTY.
+
+  GTEST_FLAG(color) = "1";
+  EXPECT_TRUE(ShouldUseColor(false));  // Stdout is not a TTY.
+}
+
+TEST(ColoredOutputTest, UsesNoColorWhenGTestColorFlagIsNo) {
+  GTEST_FLAG(color) = "no";
+
+  SetEnv("TERM", "xterm");  // TERM supports colors.
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+  EXPECT_FALSE(ShouldUseColor(false));  // Stdout is not a TTY.
+
+  SetEnv("TERM", "dumb");  // TERM doesn't support colors.
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+  EXPECT_FALSE(ShouldUseColor(false));  // Stdout is not a TTY.
+}
+
+TEST(ColoredOutputTest, UsesNoColorWhenGTestColorFlagIsInvalid) {
+  SetEnv("TERM", "xterm");  // TERM supports colors.
+
+  GTEST_FLAG(color) = "F";
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  GTEST_FLAG(color) = "0";
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  GTEST_FLAG(color) = "unknown";
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+}
+
+TEST(ColoredOutputTest, UsesColorsWhenStdoutIsTty) {
+  GTEST_FLAG(color) = "auto";
+
+  SetEnv("TERM", "xterm");  // TERM supports colors.
+  EXPECT_FALSE(ShouldUseColor(false));  // Stdout is not a TTY.
+  EXPECT_TRUE(ShouldUseColor(true));    // Stdout is a TTY.
+}
+
+TEST(ColoredOutputTest, UsesColorsWhenTermSupportsColors) {
+  GTEST_FLAG(color) = "auto";
+
+#if GTEST_OS_WINDOWS
+  // On Windows, we ignore the TERM variable as it's usually not set.
+
+  SetEnv("TERM", "dumb");
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "");
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "xterm");
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+#else
+  // On non-Windows platforms, we rely on TERM to determine if the
+  // terminal supports colors.
+
+  SetEnv("TERM", "dumb");  // TERM doesn't support colors.
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "emacs");  // TERM doesn't support colors.
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "vt100");  // TERM doesn't support colors.
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "xterm-mono");  // TERM doesn't support colors.
+  EXPECT_FALSE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "xterm");  // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "xterm-color");  // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "xterm-256color");  // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "screen");  // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "linux");  // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+
+  SetEnv("TERM", "cygwin");  // TERM supports colors.
+  EXPECT_TRUE(ShouldUseColor(true));  // Stdout is a TTY.
+#endif  // GTEST_OS_WINDOWS
+}
+
+// Verifies that StaticAssertTypeEq works in a namespace scope.
+
+static bool dummy1 GTEST_ATTRIBUTE_UNUSED_ = StaticAssertTypeEq<bool, bool>();
+static bool dummy2 GTEST_ATTRIBUTE_UNUSED_ =
+    StaticAssertTypeEq<const int, const int>();
+
+// Verifies that StaticAssertTypeEq works in a class.
+
+template <typename T>
+class StaticAssertTypeEqTestHelper {
+ public:
+  StaticAssertTypeEqTestHelper() { StaticAssertTypeEq<bool, T>(); }
+};
+
+TEST(StaticAssertTypeEqTest, WorksInClass) {
+  StaticAssertTypeEqTestHelper<bool>();
+}
+
+// Verifies that StaticAssertTypeEq works inside a function.
+
+typedef int IntAlias;
+
+TEST(StaticAssertTypeEqTest, CompilesForEqualTypes) {
+  StaticAssertTypeEq<int, IntAlias>();
+  StaticAssertTypeEq<int*, IntAlias*>();
+}
+
+TEST(GetCurrentOsStackTraceExceptTopTest, ReturnsTheStackTrace) {
+  testing::UnitTest* const unit_test = testing::UnitTest::GetInstance();
+
+  // We don't have a stack walker in Google Test yet.
+  EXPECT_STREQ("", GetCurrentOsStackTraceExceptTop(unit_test, 0).c_str());
+  EXPECT_STREQ("", GetCurrentOsStackTraceExceptTop(unit_test, 1).c_str());
+}
+
+TEST(HasNonfatalFailureTest, ReturnsFalseWhenThereIsNoFailure) {
+  EXPECT_FALSE(HasNonfatalFailure());
+}
+
+static void FailFatally() { FAIL(); }
+
+TEST(HasNonfatalFailureTest, ReturnsFalseWhenThereIsOnlyFatalFailure) {
+  FailFatally();
+  const bool has_nonfatal_failure = HasNonfatalFailure();
+  ClearCurrentTestPartResults();
+  EXPECT_FALSE(has_nonfatal_failure);
+}
+
+TEST(HasNonfatalFailureTest, ReturnsTrueWhenThereIsNonfatalFailure) {
+  ADD_FAILURE();
+  const bool has_nonfatal_failure = HasNonfatalFailure();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_nonfatal_failure);
+}
+
+TEST(HasNonfatalFailureTest, ReturnsTrueWhenThereAreFatalAndNonfatalFailures) {
+  FailFatally();
+  ADD_FAILURE();
+  const bool has_nonfatal_failure = HasNonfatalFailure();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_nonfatal_failure);
+}
+
+// A wrapper for calling HasNonfatalFailure outside of a test body.
+static bool HasNonfatalFailureHelper() {
+  return testing::Test::HasNonfatalFailure();
+}
+
+TEST(HasNonfatalFailureTest, WorksOutsideOfTestBody) {
+  EXPECT_FALSE(HasNonfatalFailureHelper());
+}
+
+TEST(HasNonfatalFailureTest, WorksOutsideOfTestBody2) {
+  ADD_FAILURE();
+  const bool has_nonfatal_failure = HasNonfatalFailureHelper();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_nonfatal_failure);
+}
+
+TEST(HasFailureTest, ReturnsFalseWhenThereIsNoFailure) {
+  EXPECT_FALSE(HasFailure());
+}
+
+TEST(HasFailureTest, ReturnsTrueWhenThereIsFatalFailure) {
+  FailFatally();
+  const bool has_failure = HasFailure();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_failure);
+}
+
+TEST(HasFailureTest, ReturnsTrueWhenThereIsNonfatalFailure) {
+  ADD_FAILURE();
+  const bool has_failure = HasFailure();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_failure);
+}
+
+TEST(HasFailureTest, ReturnsTrueWhenThereAreFatalAndNonfatalFailures) {
+  FailFatally();
+  ADD_FAILURE();
+  const bool has_failure = HasFailure();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_failure);
+}
+
+// A wrapper for calling HasFailure outside of a test body.
+static bool HasFailureHelper() { return testing::Test::HasFailure(); }
+
+TEST(HasFailureTest, WorksOutsideOfTestBody) {
+  EXPECT_FALSE(HasFailureHelper());
+}
+
+TEST(HasFailureTest, WorksOutsideOfTestBody2) {
+  ADD_FAILURE();
+  const bool has_failure = HasFailureHelper();
+  ClearCurrentTestPartResults();
+  EXPECT_TRUE(has_failure);
+}
+
+class TestListener : public EmptyTestEventListener {
+ public:
+  TestListener() : on_start_counter_(NULL), is_destroyed_(NULL) {}
+  TestListener(int* on_start_counter, bool* is_destroyed)
+      : on_start_counter_(on_start_counter),
+        is_destroyed_(is_destroyed) {}
+
+  virtual ~TestListener() {
+    if (is_destroyed_)
+      *is_destroyed_ = true;
+  }
+
+ protected:
+  virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {
+    if (on_start_counter_ != NULL)
+      (*on_start_counter_)++;
+  }
+
+ private:
+  int* on_start_counter_;
+  bool* is_destroyed_;
+};
+
+// Tests the constructor.
+TEST(TestEventListenersTest, ConstructionWorks) {
+  TestEventListeners listeners;
+
+  EXPECT_TRUE(TestEventListenersAccessor::GetRepeater(&listeners) != NULL);
+  EXPECT_TRUE(listeners.default_result_printer() == NULL);
+  EXPECT_TRUE(listeners.default_xml_generator() == NULL);
+}
+
+// Tests that the TestEventListeners destructor deletes all the listeners it
+// owns.
+TEST(TestEventListenersTest, DestructionWorks) {
+  bool default_result_printer_is_destroyed = false;
+  bool default_xml_printer_is_destroyed = false;
+  bool extra_listener_is_destroyed = false;
+  TestListener* default_result_printer = new TestListener(
+      NULL, &default_result_printer_is_destroyed);
+  TestListener* default_xml_printer = new TestListener(
+      NULL, &default_xml_printer_is_destroyed);
+  TestListener* extra_listener = new TestListener(
+      NULL, &extra_listener_is_destroyed);
+
+  {
+    TestEventListeners listeners;
+    TestEventListenersAccessor::SetDefaultResultPrinter(&listeners,
+                                                        default_result_printer);
+    TestEventListenersAccessor::SetDefaultXmlGenerator(&listeners,
+                                                       default_xml_printer);
+    listeners.Append(extra_listener);
+  }
+  EXPECT_TRUE(default_result_printer_is_destroyed);
+  EXPECT_TRUE(default_xml_printer_is_destroyed);
+  EXPECT_TRUE(extra_listener_is_destroyed);
+}
+
+// Tests that a listener Append'ed to a TestEventListeners list starts
+// receiving events.
+TEST(TestEventListenersTest, Append) {
+  int on_start_counter = 0;
+  bool is_destroyed = false;
+  TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+  {
+    TestEventListeners listeners;
+    listeners.Append(listener);
+    TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+        *UnitTest::GetInstance());
+    EXPECT_EQ(1, on_start_counter);
+  }
+  EXPECT_TRUE(is_destroyed);
+}
+
+// Tests that listeners receive events in the order they were appended to
+// the list, except for *End requests, which must be received in the reverse
+// order.
+class SequenceTestingListener : public EmptyTestEventListener {
+ public:
+  SequenceTestingListener(std::vector<String>* vector, const char* id)
+      : vector_(vector), id_(id) {}
+
+ protected:
+  virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {
+    vector_->push_back(GetEventDescription("OnTestProgramStart"));
+  }
+
+  virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {
+    vector_->push_back(GetEventDescription("OnTestProgramEnd"));
+  }
+
+  virtual void OnTestIterationStart(const UnitTest& /*unit_test*/,
+                                    int /*iteration*/) {
+    vector_->push_back(GetEventDescription("OnTestIterationStart"));
+  }
+
+  virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/,
+                                  int /*iteration*/) {
+    vector_->push_back(GetEventDescription("OnTestIterationEnd"));
+  }
+
+ private:
+  String GetEventDescription(const char* method) {
+    Message message;
+    message << id_ << "." << method;
+    return message.GetString();
+  }
+
+  std::vector<String>* vector_;
+  const char* const id_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(SequenceTestingListener);
+};
+
+TEST(EventListenerTest, AppendKeepsOrder) {
+  std::vector<String> vec;
+  TestEventListeners listeners;
+  listeners.Append(new SequenceTestingListener(&vec, "1st"));
+  listeners.Append(new SequenceTestingListener(&vec, "2nd"));
+  listeners.Append(new SequenceTestingListener(&vec, "3rd"));
+
+  TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+      *UnitTest::GetInstance());
+  ASSERT_EQ(3U, vec.size());
+  EXPECT_STREQ("1st.OnTestProgramStart", vec[0].c_str());
+  EXPECT_STREQ("2nd.OnTestProgramStart", vec[1].c_str());
+  EXPECT_STREQ("3rd.OnTestProgramStart", vec[2].c_str());
+
+  vec.clear();
+  TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramEnd(
+      *UnitTest::GetInstance());
+  ASSERT_EQ(3U, vec.size());
+  EXPECT_STREQ("3rd.OnTestProgramEnd", vec[0].c_str());
+  EXPECT_STREQ("2nd.OnTestProgramEnd", vec[1].c_str());
+  EXPECT_STREQ("1st.OnTestProgramEnd", vec[2].c_str());
+
+  vec.clear();
+  TestEventListenersAccessor::GetRepeater(&listeners)->OnTestIterationStart(
+      *UnitTest::GetInstance(), 0);
+  ASSERT_EQ(3U, vec.size());
+  EXPECT_STREQ("1st.OnTestIterationStart", vec[0].c_str());
+  EXPECT_STREQ("2nd.OnTestIterationStart", vec[1].c_str());
+  EXPECT_STREQ("3rd.OnTestIterationStart", vec[2].c_str());
+
+  vec.clear();
+  TestEventListenersAccessor::GetRepeater(&listeners)->OnTestIterationEnd(
+      *UnitTest::GetInstance(), 0);
+  ASSERT_EQ(3U, vec.size());
+  EXPECT_STREQ("3rd.OnTestIterationEnd", vec[0].c_str());
+  EXPECT_STREQ("2nd.OnTestIterationEnd", vec[1].c_str());
+  EXPECT_STREQ("1st.OnTestIterationEnd", vec[2].c_str());
+}
+
+// Tests that a listener removed from a TestEventListeners list stops receiving
+// events and is not deleted when the list is destroyed.
+TEST(TestEventListenersTest, Release) {
+  int on_start_counter = 0;
+  bool is_destroyed = false;
+  // Although Append passes the ownership of this object to the list,
+  // the following calls release it, and we need to delete it before the
+  // test ends.
+  TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+  {
+    TestEventListeners listeners;
+    listeners.Append(listener);
+    EXPECT_EQ(listener, listeners.Release(listener));
+    TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+        *UnitTest::GetInstance());
+    EXPECT_TRUE(listeners.Release(listener) == NULL);
+  }
+  EXPECT_EQ(0, on_start_counter);
+  EXPECT_FALSE(is_destroyed);
+  delete listener;
+}
+
+// Tests that no events are forwarded when event forwarding is disabled.
+TEST(EventListenerTest, SuppressEventForwarding) {
+  int on_start_counter = 0;
+  TestListener* listener = new TestListener(&on_start_counter, NULL);
+
+  TestEventListeners listeners;
+  listeners.Append(listener);
+  ASSERT_TRUE(TestEventListenersAccessor::EventForwardingEnabled(listeners));
+  TestEventListenersAccessor::SuppressEventForwarding(&listeners);
+  ASSERT_FALSE(TestEventListenersAccessor::EventForwardingEnabled(listeners));
+  TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+      *UnitTest::GetInstance());
+  EXPECT_EQ(0, on_start_counter);
+}
+
+// Tests that events generated by Google Test are not forwarded in
+// death test subprocesses.
+TEST(EventListenerDeathTest, EventsNotForwardedInDeathTestSubprecesses) {
+  EXPECT_DEATH_IF_SUPPORTED({
+      GTEST_CHECK_(TestEventListenersAccessor::EventForwardingEnabled(
+          *GetUnitTestImpl()->listeners())) << "expected failure";},
+      "expected failure");
+}
+
+// Tests that a listener installed via SetDefaultResultPrinter() starts
+// receiving events and is returned via default_result_printer() and that
+// the previous default_result_printer is removed from the list and deleted.
+TEST(EventListenerTest, default_result_printer) {
+  int on_start_counter = 0;
+  bool is_destroyed = false;
+  TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+
+  TestEventListeners listeners;
+  TestEventListenersAccessor::SetDefaultResultPrinter(&listeners, listener);
+
+  EXPECT_EQ(listener, listeners.default_result_printer());
+
+  TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+      *UnitTest::GetInstance());
+
+  EXPECT_EQ(1, on_start_counter);
+
+  // Replacing default_result_printer with something else should remove it
+  // from the list and destroy it.
+  TestEventListenersAccessor::SetDefaultResultPrinter(&listeners, NULL);
+
+  EXPECT_TRUE(listeners.default_result_printer() == NULL);
+  EXPECT_TRUE(is_destroyed);
+
+  // After broadcasting an event the counter is still the same, indicating
+  // the listener is not in the list anymore.
+  TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+      *UnitTest::GetInstance());
+  EXPECT_EQ(1, on_start_counter);
+}
+
+// Tests that the default_result_printer listener stops receiving events
+// when removed via Release and that is not owned by the list anymore.
+TEST(EventListenerTest, RemovingDefaultResultPrinterWorks) {
+  int on_start_counter = 0;
+  bool is_destroyed = false;
+  // Although Append passes the ownership of this object to the list,
+  // the following calls release it, and we need to delete it before the
+  // test ends.
+  TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+  {
+    TestEventListeners listeners;
+    TestEventListenersAccessor::SetDefaultResultPrinter(&listeners, listener);
+
+    EXPECT_EQ(listener, listeners.Release(listener));
+    EXPECT_TRUE(listeners.default_result_printer() == NULL);
+    EXPECT_FALSE(is_destroyed);
+
+    // Broadcasting events now should not affect default_result_printer.
+    TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+        *UnitTest::GetInstance());
+    EXPECT_EQ(0, on_start_counter);
+  }
+  // Destroying the list should not affect the listener now, too.
+  EXPECT_FALSE(is_destroyed);
+  delete listener;
+}
+
+// Tests that a listener installed via SetDefaultXmlGenerator() starts
+// receiving events and is returned via default_xml_generator() and that
+// the previous default_xml_generator is removed from the list and deleted.
+TEST(EventListenerTest, default_xml_generator) {
+  int on_start_counter = 0;
+  bool is_destroyed = false;
+  TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+
+  TestEventListeners listeners;
+  TestEventListenersAccessor::SetDefaultXmlGenerator(&listeners, listener);
+
+  EXPECT_EQ(listener, listeners.default_xml_generator());
+
+  TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+      *UnitTest::GetInstance());
+
+  EXPECT_EQ(1, on_start_counter);
+
+  // Replacing default_xml_generator with something else should remove it
+  // from the list and destroy it.
+  TestEventListenersAccessor::SetDefaultXmlGenerator(&listeners, NULL);
+
+  EXPECT_TRUE(listeners.default_xml_generator() == NULL);
+  EXPECT_TRUE(is_destroyed);
+
+  // After broadcasting an event the counter is still the same, indicating
+  // the listener is not in the list anymore.
+  TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+      *UnitTest::GetInstance());
+  EXPECT_EQ(1, on_start_counter);
+}
+
+// Tests that the default_xml_generator listener stops receiving events
+// when removed via Release and that is not owned by the list anymore.
+TEST(EventListenerTest, RemovingDefaultXmlGeneratorWorks) {
+  int on_start_counter = 0;
+  bool is_destroyed = false;
+  // Although Append passes the ownership of this object to the list,
+  // the following calls release it, and we need to delete it before the
+  // test ends.
+  TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+  {
+    TestEventListeners listeners;
+    TestEventListenersAccessor::SetDefaultXmlGenerator(&listeners, listener);
+
+    EXPECT_EQ(listener, listeners.Release(listener));
+    EXPECT_TRUE(listeners.default_xml_generator() == NULL);
+    EXPECT_FALSE(is_destroyed);
+
+    // Broadcasting events now should not affect default_xml_generator.
+    TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+        *UnitTest::GetInstance());
+    EXPECT_EQ(0, on_start_counter);
+  }
+  // Destroying the list should not affect the listener now, too.
+  EXPECT_FALSE(is_destroyed);
+  delete listener;
+}
+
+// Sanity tests to ensure that the alternative, verbose spellings of
+// some of the macros work.  We don't test them thoroughly as that
+// would be quite involved.  Since their implementations are
+// straightforward, and they are rarely used, we'll just rely on the
+// users to tell us when they are broken.
+GTEST_TEST(AlternativeNameTest, Works) {  // GTEST_TEST is the same as TEST.
+  GTEST_SUCCEED() << "OK";  // GTEST_SUCCEED is the same as SUCCEED.
+
+  // GTEST_FAIL is the same as FAIL.
+  EXPECT_FATAL_FAILURE(GTEST_FAIL() << "An expected failure",
+                       "An expected failure");
+
+  // GTEST_ASSERT_XY is the same as ASSERT_XY.
+
+  GTEST_ASSERT_EQ(0, 0);
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_EQ(0, 1) << "An expected failure",
+                       "An expected failure");
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_EQ(1, 0) << "An expected failure",
+                       "An expected failure");
+
+  GTEST_ASSERT_NE(0, 1);
+  GTEST_ASSERT_NE(1, 0);
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_NE(0, 0) << "An expected failure",
+                       "An expected failure");
+
+  GTEST_ASSERT_LE(0, 0);
+  GTEST_ASSERT_LE(0, 1);
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_LE(1, 0) << "An expected failure",
+                       "An expected failure");
+
+  GTEST_ASSERT_LT(0, 1);
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_LT(0, 0) << "An expected failure",
+                       "An expected failure");
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_LT(1, 0) << "An expected failure",
+                       "An expected failure");
+
+  GTEST_ASSERT_GE(0, 0);
+  GTEST_ASSERT_GE(1, 0);
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_GE(0, 1) << "An expected failure",
+                       "An expected failure");
+
+  GTEST_ASSERT_GT(1, 0);
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_GT(0, 1) << "An expected failure",
+                       "An expected failure");
+  EXPECT_FATAL_FAILURE(GTEST_ASSERT_GT(1, 1) << "An expected failure",
+                       "An expected failure");
+}
+
+// Tests for internal utilities necessary for implementation of the universal
+// printing.
+// TODO(vladl@google.com): Find a better home for them.
+
+class ConversionHelperBase {};
+class ConversionHelperDerived : public ConversionHelperBase {};
+
+// Tests that IsAProtocolMessage<T>::value is a compile-time constant.
+TEST(IsAProtocolMessageTest, ValueIsCompileTimeConstant) {
+  GTEST_COMPILE_ASSERT_(IsAProtocolMessage<ProtocolMessage>::value,
+                        const_true);
+  GTEST_COMPILE_ASSERT_(!IsAProtocolMessage<int>::value, const_false);
+}
+
+// Tests that IsAProtocolMessage<T>::value is true when T is
+// proto2::Message or a sub-class of it.
+TEST(IsAProtocolMessageTest, ValueIsTrueWhenTypeIsAProtocolMessage) {
+  EXPECT_TRUE(IsAProtocolMessage< ::proto2::Message>::value);
+  EXPECT_TRUE(IsAProtocolMessage<ProtocolMessage>::value);
+}
+
+// Tests that IsAProtocolMessage<T>::value is false when T is neither
+// ProtocolMessage nor a sub-class of it.
+TEST(IsAProtocolMessageTest, ValueIsFalseWhenTypeIsNotAProtocolMessage) {
+  EXPECT_FALSE(IsAProtocolMessage<int>::value);
+  EXPECT_FALSE(IsAProtocolMessage<const ConversionHelperBase>::value);
+}
+
+// Tests that CompileAssertTypesEqual compiles when the type arguments are
+// equal.
+TEST(CompileAssertTypesEqual, CompilesWhenTypesAreEqual) {
+  CompileAssertTypesEqual<void, void>();
+  CompileAssertTypesEqual<int*, int*>();
+}
+
+// Tests that RemoveReference does not affect non-reference types.
+TEST(RemoveReferenceTest, DoesNotAffectNonReferenceType) {
+  CompileAssertTypesEqual<int, RemoveReference<int>::type>();
+  CompileAssertTypesEqual<const char, RemoveReference<const char>::type>();
+}
+
+// Tests that RemoveReference removes reference from reference types.
+TEST(RemoveReferenceTest, RemovesReference) {
+  CompileAssertTypesEqual<int, RemoveReference<int&>::type>();
+  CompileAssertTypesEqual<const char, RemoveReference<const char&>::type>();
+}
+
+// Tests GTEST_REMOVE_REFERENCE_.
+
+template <typename T1, typename T2>
+void TestGTestRemoveReference() {
+  CompileAssertTypesEqual<T1, GTEST_REMOVE_REFERENCE_(T2)>();
+}
+
+TEST(RemoveReferenceTest, MacroVersion) {
+  TestGTestRemoveReference<int, int>();
+  TestGTestRemoveReference<const char, const char&>();
+}
+
+
+// Tests that RemoveConst does not affect non-const types.
+TEST(RemoveConstTest, DoesNotAffectNonConstType) {
+  CompileAssertTypesEqual<int, RemoveConst<int>::type>();
+  CompileAssertTypesEqual<char&, RemoveConst<char&>::type>();
+}
+
+// Tests that RemoveConst removes const from const types.
+TEST(RemoveConstTest, RemovesConst) {
+  CompileAssertTypesEqual<int, RemoveConst<const int>::type>();
+  CompileAssertTypesEqual<char[2], RemoveConst<const char[2]>::type>();
+  CompileAssertTypesEqual<char[2][3], RemoveConst<const char[2][3]>::type>();
+}
+
+// Tests GTEST_REMOVE_CONST_.
+
+template <typename T1, typename T2>
+void TestGTestRemoveConst() {
+  CompileAssertTypesEqual<T1, GTEST_REMOVE_CONST_(T2)>();
+}
+
+TEST(RemoveConstTest, MacroVersion) {
+  TestGTestRemoveConst<int, int>();
+  TestGTestRemoveConst<double&, double&>();
+  TestGTestRemoveConst<char, const char>();
+}
+
+// Tests GTEST_REMOVE_REFERENCE_AND_CONST_.
+
+template <typename T1, typename T2>
+void TestGTestRemoveReferenceAndConst() {
+  CompileAssertTypesEqual<T1, GTEST_REMOVE_REFERENCE_AND_CONST_(T2)>();
+}
+
+TEST(RemoveReferenceToConstTest, Works) {
+  TestGTestRemoveReferenceAndConst<int, int>();
+  TestGTestRemoveReferenceAndConst<double, double&>();
+  TestGTestRemoveReferenceAndConst<char, const char>();
+  TestGTestRemoveReferenceAndConst<char, const char&>();
+  TestGTestRemoveReferenceAndConst<const char*, const char*>();
+}
+
+// Tests that AddReference does not affect reference types.
+TEST(AddReferenceTest, DoesNotAffectReferenceType) {
+  CompileAssertTypesEqual<int&, AddReference<int&>::type>();
+  CompileAssertTypesEqual<const char&, AddReference<const char&>::type>();
+}
+
+// Tests that AddReference adds reference to non-reference types.
+TEST(AddReferenceTest, AddsReference) {
+  CompileAssertTypesEqual<int&, AddReference<int>::type>();
+  CompileAssertTypesEqual<const char&, AddReference<const char>::type>();
+}
+
+// Tests GTEST_ADD_REFERENCE_.
+
+template <typename T1, typename T2>
+void TestGTestAddReference() {
+  CompileAssertTypesEqual<T1, GTEST_ADD_REFERENCE_(T2)>();
+}
+
+TEST(AddReferenceTest, MacroVersion) {
+  TestGTestAddReference<int&, int>();
+  TestGTestAddReference<const char&, const char&>();
+}
+
+// Tests GTEST_REFERENCE_TO_CONST_.
+
+template <typename T1, typename T2>
+void TestGTestReferenceToConst() {
+  CompileAssertTypesEqual<T1, GTEST_REFERENCE_TO_CONST_(T2)>();
+}
+
+TEST(GTestReferenceToConstTest, Works) {
+  TestGTestReferenceToConst<const char&, char>();
+  TestGTestReferenceToConst<const int&, const int>();
+  TestGTestReferenceToConst<const double&, double>();
+  TestGTestReferenceToConst<const String&, const String&>();
+}
+
+// Tests that ImplicitlyConvertible<T1, T2>::value is a compile-time constant.
+TEST(ImplicitlyConvertibleTest, ValueIsCompileTimeConstant) {
+  GTEST_COMPILE_ASSERT_((ImplicitlyConvertible<int, int>::value), const_true);
+  GTEST_COMPILE_ASSERT_((!ImplicitlyConvertible<void*, int*>::value),
+                        const_false);
+}
+
+// Tests that ImplicitlyConvertible<T1, T2>::value is true when T1 can
+// be implicitly converted to T2.
+TEST(ImplicitlyConvertibleTest, ValueIsTrueWhenConvertible) {
+  EXPECT_TRUE((ImplicitlyConvertible<int, double>::value));
+  EXPECT_TRUE((ImplicitlyConvertible<double, int>::value));
+  EXPECT_TRUE((ImplicitlyConvertible<int*, void*>::value));
+  EXPECT_TRUE((ImplicitlyConvertible<int*, const int*>::value));
+  EXPECT_TRUE((ImplicitlyConvertible<ConversionHelperDerived&,
+                                     const ConversionHelperBase&>::value));
+  EXPECT_TRUE((ImplicitlyConvertible<const ConversionHelperBase,
+                                     ConversionHelperBase>::value));
+}
+
+// Tests that ImplicitlyConvertible<T1, T2>::value is false when T1
+// cannot be implicitly converted to T2.
+TEST(ImplicitlyConvertibleTest, ValueIsFalseWhenNotConvertible) {
+  EXPECT_FALSE((ImplicitlyConvertible<double, int*>::value));
+  EXPECT_FALSE((ImplicitlyConvertible<void*, int*>::value));
+  EXPECT_FALSE((ImplicitlyConvertible<const int*, int*>::value));
+  EXPECT_FALSE((ImplicitlyConvertible<ConversionHelperBase&,
+                                      ConversionHelperDerived&>::value));
+}
+
+// Tests IsContainerTest.
+
+class NonContainer {};
+
+TEST(IsContainerTestTest, WorksForNonContainer) {
+  EXPECT_EQ(sizeof(IsNotContainer), sizeof(IsContainerTest<int>(0)));
+  EXPECT_EQ(sizeof(IsNotContainer), sizeof(IsContainerTest<char[5]>(0)));
+  EXPECT_EQ(sizeof(IsNotContainer), sizeof(IsContainerTest<NonContainer>(0)));
+}
+
+TEST(IsContainerTestTest, WorksForContainer) {
+  EXPECT_EQ(sizeof(IsContainer),
+            sizeof(IsContainerTest<std::vector<bool> >(0)));
+  EXPECT_EQ(sizeof(IsContainer),
+            sizeof(IsContainerTest<std::map<int, double> >(0)));
+}
+
+// Tests ArrayEq().
+
+TEST(ArrayEqTest, WorksForDegeneratedArrays) {
+  EXPECT_TRUE(ArrayEq(5, 5L));
+  EXPECT_FALSE(ArrayEq('a', 0));
+}
+
+TEST(ArrayEqTest, WorksForOneDimensionalArrays) {
+  const int a[] = { 0, 1 };
+  long b[] = { 0, 1 };
+  EXPECT_TRUE(ArrayEq(a, b));
+  EXPECT_TRUE(ArrayEq(a, 2, b));
+
+  b[0] = 2;
+  EXPECT_FALSE(ArrayEq(a, b));
+  EXPECT_FALSE(ArrayEq(a, 1, b));
+}
+
+TEST(ArrayEqTest, WorksForTwoDimensionalArrays) {
+  const char a[][3] = { "hi", "lo" };
+  const char b[][3] = { "hi", "lo" };
+  const char c[][3] = { "hi", "li" };
+
+  EXPECT_TRUE(ArrayEq(a, b));
+  EXPECT_TRUE(ArrayEq(a, 2, b));
+
+  EXPECT_FALSE(ArrayEq(a, c));
+  EXPECT_FALSE(ArrayEq(a, 2, c));
+}
+
+// Tests ArrayAwareFind().
+
+TEST(ArrayAwareFindTest, WorksForOneDimensionalArray) {
+  const char a[] = "hello";
+  EXPECT_EQ(a + 4, ArrayAwareFind(a, a + 5, 'o'));
+  EXPECT_EQ(a + 5, ArrayAwareFind(a, a + 5, 'x'));
+}
+
+TEST(ArrayAwareFindTest, WorksForTwoDimensionalArray) {
+  int a[][2] = { { 0, 1 }, { 2, 3 }, { 4, 5 } };
+  const int b[2] = { 2, 3 };
+  EXPECT_EQ(a + 1, ArrayAwareFind(a, a + 3, b));
+
+  const int c[2] = { 6, 7 };
+  EXPECT_EQ(a + 3, ArrayAwareFind(a, a + 3, c));
+}
+
+// Tests CopyArray().
+
+TEST(CopyArrayTest, WorksForDegeneratedArrays) {
+  int n = 0;
+  CopyArray('a', &n);
+  EXPECT_EQ('a', n);
+}
+
+TEST(CopyArrayTest, WorksForOneDimensionalArrays) {
+  const char a[3] = "hi";
+  int b[3];
+#ifndef __BORLANDC__  // C++Builder cannot compile some array size deductions.
+  CopyArray(a, &b);
+  EXPECT_TRUE(ArrayEq(a, b));
+#endif
+
+  int c[3];
+  CopyArray(a, 3, c);
+  EXPECT_TRUE(ArrayEq(a, c));
+}
+
+TEST(CopyArrayTest, WorksForTwoDimensionalArrays) {
+  const int a[2][3] = { { 0, 1, 2 }, { 3, 4, 5 } };
+  int b[2][3];
+#ifndef __BORLANDC__  // C++Builder cannot compile some array size deductions.
+  CopyArray(a, &b);
+  EXPECT_TRUE(ArrayEq(a, b));
+#endif
+
+  int c[2][3];
+  CopyArray(a, 2, c);
+  EXPECT_TRUE(ArrayEq(a, c));
+}
+
+// Tests NativeArray.
+
+TEST(NativeArrayTest, ConstructorFromArrayWorks) {
+  const int a[3] = { 0, 1, 2 };
+  NativeArray<int> na(a, 3, kReference);
+  EXPECT_EQ(3U, na.size());
+  EXPECT_EQ(a, na.begin());
+}
+
+TEST(NativeArrayTest, CreatesAndDeletesCopyOfArrayWhenAskedTo) {
+  typedef int Array[2];
+  Array* a = new Array[1];
+  (*a)[0] = 0;
+  (*a)[1] = 1;
+  NativeArray<int> na(*a, 2, kCopy);
+  EXPECT_NE(*a, na.begin());
+  delete[] a;
+  EXPECT_EQ(0, na.begin()[0]);
+  EXPECT_EQ(1, na.begin()[1]);
+
+  // We rely on the heap checker to verify that na deletes the copy of
+  // array.
+}
+
+TEST(NativeArrayTest, TypeMembersAreCorrect) {
+  StaticAssertTypeEq<char, NativeArray<char>::value_type>();
+  StaticAssertTypeEq<int[2], NativeArray<int[2]>::value_type>();
+
+  StaticAssertTypeEq<const char*, NativeArray<char>::const_iterator>();
+  StaticAssertTypeEq<const bool(*)[2], NativeArray<bool[2]>::const_iterator>();
+}
+
+TEST(NativeArrayTest, MethodsWork) {
+  const int a[3] = { 0, 1, 2 };
+  NativeArray<int> na(a, 3, kCopy);
+  ASSERT_EQ(3U, na.size());
+  EXPECT_EQ(3, na.end() - na.begin());
+
+  NativeArray<int>::const_iterator it = na.begin();
+  EXPECT_EQ(0, *it);
+  ++it;
+  EXPECT_EQ(1, *it);
+  it++;
+  EXPECT_EQ(2, *it);
+  ++it;
+  EXPECT_EQ(na.end(), it);
+
+  EXPECT_TRUE(na == na);
+
+  NativeArray<int> na2(a, 3, kReference);
+  EXPECT_TRUE(na == na2);
+
+  const int b1[3] = { 0, 1, 1 };
+  const int b2[4] = { 0, 1, 2, 3 };
+  EXPECT_FALSE(na == NativeArray<int>(b1, 3, kReference));
+  EXPECT_FALSE(na == NativeArray<int>(b2, 4, kCopy));
+}
+
+TEST(NativeArrayTest, WorksForTwoDimensionalArray) {
+  const char a[2][3] = { "hi", "lo" };
+  NativeArray<char[3]> na(a, 2, kReference);
+  ASSERT_EQ(2U, na.size());
+  EXPECT_EQ(a, na.begin());
+}
+
+// Tests SkipPrefix().
+
+TEST(SkipPrefixTest, SkipsWhenPrefixMatches) {
+  const char* const str = "hello";
+
+  const char* p = str;
+  EXPECT_TRUE(SkipPrefix("", &p));
+  EXPECT_EQ(str, p);
+
+  p = str;
+  EXPECT_TRUE(SkipPrefix("hell", &p));
+  EXPECT_EQ(str + 4, p);
+}
+
+TEST(SkipPrefixTest, DoesNotSkipWhenPrefixDoesNotMatch) {
+  const char* const str = "world";
+
+  const char* p = str;
+  EXPECT_FALSE(SkipPrefix("W", &p));
+  EXPECT_EQ(str, p);
+
+  p = str;
+  EXPECT_FALSE(SkipPrefix("world!", &p));
+  EXPECT_EQ(str, p);
+}
diff --git a/third_party/googletest/src/test/gtest_xml_outfile1_test_.cc b/third_party/googletest/src/test/gtest_xml_outfile1_test_.cc
new file mode 100644 (file)
index 0000000..531ced4
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright 2008, 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: keith.ray@gmail.com (Keith Ray)
+//
+// gtest_xml_outfile1_test_ writes some xml via TestProperty used by
+// gtest_xml_outfiles_test.py
+
+#include "gtest/gtest.h"
+
+class PropertyOne : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    RecordProperty("SetUpProp", 1);
+  }
+  virtual void TearDown() {
+    RecordProperty("TearDownProp", 1);
+  }
+};
+
+TEST_F(PropertyOne, TestSomeProperties) {
+  RecordProperty("TestSomeProperty", 1);
+}
diff --git a/third_party/googletest/src/test/gtest_xml_outfile2_test_.cc b/third_party/googletest/src/test/gtest_xml_outfile2_test_.cc
new file mode 100644 (file)
index 0000000..7b400b2
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright 2008, 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: keith.ray@gmail.com (Keith Ray)
+//
+// gtest_xml_outfile2_test_ writes some xml via TestProperty used by
+// gtest_xml_outfiles_test.py
+
+#include "gtest/gtest.h"
+
+class PropertyTwo : public testing::Test {
+ protected:
+  virtual void SetUp() {
+    RecordProperty("SetUpProp", 2);
+  }
+  virtual void TearDown() {
+    RecordProperty("TearDownProp", 2);
+  }
+};
+
+TEST_F(PropertyTwo, TestSomeProperties) {
+  RecordProperty("TestSomeProperty", 2);
+}
diff --git a/third_party/googletest/src/test/gtest_xml_outfiles_test.py b/third_party/googletest/src/test/gtest_xml_outfiles_test.py
new file mode 100755 (executable)
index 0000000..0fe947f
--- /dev/null
@@ -0,0 +1,132 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, 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.
+
+"""Unit test for the gtest_xml_output module."""
+
+__author__ = "keith.ray@gmail.com (Keith Ray)"
+
+import os
+from xml.dom import minidom, Node
+
+import gtest_test_utils
+import gtest_xml_test_utils
+
+
+GTEST_OUTPUT_SUBDIR = "xml_outfiles"
+GTEST_OUTPUT_1_TEST = "gtest_xml_outfile1_test_"
+GTEST_OUTPUT_2_TEST = "gtest_xml_outfile2_test_"
+
+EXPECTED_XML_1 = """<?xml version="1.0" encoding="UTF-8"?>
+<testsuites tests="1" failures="0" disabled="0" errors="0" time="*" name="AllTests">
+  <testsuite name="PropertyOne" tests="1" failures="0" disabled="0" errors="0" time="*">
+    <testcase name="TestSomeProperties" status="run" time="*" classname="PropertyOne" SetUpProp="1" TestSomeProperty="1" TearDownProp="1" />
+  </testsuite>
+</testsuites>
+"""
+
+EXPECTED_XML_2 = """<?xml version="1.0" encoding="UTF-8"?>
+<testsuites tests="1" failures="0" disabled="0" errors="0" time="*" name="AllTests">
+  <testsuite name="PropertyTwo" tests="1" failures="0" disabled="0" errors="0" time="*">
+    <testcase name="TestSomeProperties" status="run" time="*" classname="PropertyTwo" SetUpProp="2" TestSomeProperty="2" TearDownProp="2" />
+  </testsuite>
+</testsuites>
+"""
+
+
+class GTestXMLOutFilesTest(gtest_xml_test_utils.GTestXMLTestCase):
+  """Unit test for Google Test's XML output functionality."""
+
+  def setUp(self):
+    # We want the trailing '/' that the last "" provides in os.path.join, for
+    # telling Google Test to create an output directory instead of a single file
+    # for xml output.
+    self.output_dir_ = os.path.join(gtest_test_utils.GetTempDir(),
+                                    GTEST_OUTPUT_SUBDIR, "")
+    self.DeleteFilesAndDir()
+
+  def tearDown(self):
+    self.DeleteFilesAndDir()
+
+  def DeleteFilesAndDir(self):
+    try:
+      os.remove(os.path.join(self.output_dir_, GTEST_OUTPUT_1_TEST + ".xml"))
+    except os.error:
+      pass
+    try:
+      os.remove(os.path.join(self.output_dir_, GTEST_OUTPUT_2_TEST + ".xml"))
+    except os.error:
+      pass
+    try:
+      os.rmdir(self.output_dir_)
+    except os.error:
+      pass
+
+  def testOutfile1(self):
+    self._TestOutFile(GTEST_OUTPUT_1_TEST, EXPECTED_XML_1)
+
+  def testOutfile2(self):
+    self._TestOutFile(GTEST_OUTPUT_2_TEST, EXPECTED_XML_2)
+
+  def _TestOutFile(self, test_name, expected_xml):
+    gtest_prog_path = gtest_test_utils.GetTestExecutablePath(test_name)
+    command = [gtest_prog_path, "--gtest_output=xml:%s" % self.output_dir_]
+    p = gtest_test_utils.Subprocess(command,
+                                    working_dir=gtest_test_utils.GetTempDir())
+    self.assert_(p.exited)
+    self.assertEquals(0, p.exit_code)
+
+    # TODO(wan@google.com): libtool causes the built test binary to be
+    #   named lt-gtest_xml_outfiles_test_ instead of
+    #   gtest_xml_outfiles_test_.  To account for this possibillity, we
+    #   allow both names in the following code.  We should remove this
+    #   hack when Chandler Carruth's libtool replacement tool is ready.
+    output_file_name1 = test_name + ".xml"
+    output_file1 = os.path.join(self.output_dir_, output_file_name1)
+    output_file_name2 = 'lt-' + output_file_name1
+    output_file2 = os.path.join(self.output_dir_, output_file_name2)
+    self.assert_(os.path.isfile(output_file1) or os.path.isfile(output_file2),
+                 output_file1)
+
+    expected = minidom.parseString(expected_xml)
+    if os.path.isfile(output_file1):
+      actual = minidom.parse(output_file1)
+    else:
+      actual = minidom.parse(output_file2)
+    self.NormalizeXml(actual.documentElement)
+    self.AssertEquivalentNodes(expected.documentElement,
+                               actual.documentElement)
+    expected.unlink()
+    actual.unlink()
+
+
+if __name__ == "__main__":
+  os.environ["GTEST_STACK_TRACE_DEPTH"] = "0"
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/src/test/gtest_xml_output_unittest.py b/third_party/googletest/src/test/gtest_xml_output_unittest.py
new file mode 100755 (executable)
index 0000000..bdd5035
--- /dev/null
@@ -0,0 +1,242 @@
+#!/usr/bin/env python
+#
+# Copyright 2006, 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.
+
+"""Unit test for the gtest_xml_output module"""
+
+__author__ = 'eefacm@gmail.com (Sean Mcafee)'
+
+import errno
+import os
+import sys
+from xml.dom import minidom, Node
+
+import gtest_test_utils
+import gtest_xml_test_utils
+
+
+GTEST_OUTPUT_FLAG         = "--gtest_output"
+GTEST_DEFAULT_OUTPUT_FILE = "test_detail.xml"
+GTEST_PROGRAM_NAME = "gtest_xml_output_unittest_"
+
+SUPPORTS_STACK_TRACES = False
+
+if SUPPORTS_STACK_TRACES:
+  STACK_TRACE_TEMPLATE = "\nStack trace:\n*"
+else:
+  STACK_TRACE_TEMPLATE = ""
+
+EXPECTED_NON_EMPTY_XML = """<?xml version="1.0" encoding="UTF-8"?>
+<testsuites tests="23" failures="4" disabled="2" errors="0" time="*" name="AllTests">
+  <testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" errors="0" time="*">
+    <testcase name="Succeeds" status="run" time="*" classname="SuccessfulTest"/>
+  </testsuite>
+  <testsuite name="FailedTest" tests="1" failures="1" disabled="0" errors="0" time="*">
+    <testcase name="Fails" status="run" time="*" classname="FailedTest">
+      <failure message="Value of: 2&#x0A;Expected: 1" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
+Value of: 2
+Expected: 1%(stack)s]]></failure>
+    </testcase>
+  </testsuite>
+  <testsuite name="MixedResultTest" tests="3" failures="1" disabled="1" errors="0" time="*">
+    <testcase name="Succeeds" status="run" time="*" classname="MixedResultTest"/>
+    <testcase name="Fails" status="run" time="*" classname="MixedResultTest">
+      <failure message="Value of: 2&#x0A;Expected: 1" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
+Value of: 2
+Expected: 1%(stack)s]]></failure>
+      <failure message="Value of: 3&#x0A;Expected: 2" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
+Value of: 3
+Expected: 2%(stack)s]]></failure>
+    </testcase>
+    <testcase name="DISABLED_test" status="notrun" time="*" classname="MixedResultTest"/>
+  </testsuite>
+  <testsuite name="XmlQuotingTest" tests="1" failures="1" disabled="0" errors="0" time="*">
+    <testcase name="OutputsCData" status="run" time="*" classname="XmlQuotingTest">
+      <failure message="Failed&#x0A;XML output: &lt;?xml encoding=&quot;utf-8&quot;&gt;&lt;top&gt;&lt;![CDATA[cdata text]]&gt;&lt;/top&gt;" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
+Failed
+XML output: <?xml encoding="utf-8"><top><![CDATA[cdata text]]>]]&gt;<![CDATA[</top>%(stack)s]]></failure>
+    </testcase>
+  </testsuite>
+  <testsuite name="InvalidCharactersTest" tests="1" failures="1" disabled="0" errors="0" time="*">
+    <testcase name="InvalidCharactersInMessage" status="run" time="*" classname="InvalidCharactersTest">
+      <failure message="Failed&#x0A;Invalid characters in brackets []" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
+Failed
+Invalid characters in brackets []%(stack)s]]></failure>
+    </testcase>
+  </testsuite>
+  <testsuite name="DisabledTest" tests="1" failures="0" disabled="1" errors="0" time="*">
+    <testcase name="DISABLED_test_not_run" status="notrun" time="*" classname="DisabledTest"/>
+  </testsuite>
+  <testsuite name="PropertyRecordingTest" tests="4" failures="0" disabled="0" errors="0" time="*">
+    <testcase name="OneProperty" status="run" time="*" classname="PropertyRecordingTest" key_1="1"/>
+    <testcase name="IntValuedProperty" status="run" time="*" classname="PropertyRecordingTest" key_int="1"/>
+    <testcase name="ThreeProperties" status="run" time="*" classname="PropertyRecordingTest" key_1="1" key_2="2" key_3="3"/>
+    <testcase name="TwoValuesForOneKeyUsesLastValue" status="run" time="*" classname="PropertyRecordingTest" key_1="2"/>
+  </testsuite>
+  <testsuite name="NoFixtureTest" tests="3" failures="0" disabled="0" errors="0" time="*">
+     <testcase name="RecordProperty" status="run" time="*" classname="NoFixtureTest" key="1"/>
+     <testcase name="ExternalUtilityThatCallsRecordIntValuedProperty" status="run" time="*" classname="NoFixtureTest" key_for_utility_int="1"/>
+     <testcase name="ExternalUtilityThatCallsRecordStringValuedProperty" status="run" time="*" classname="NoFixtureTest" key_for_utility_string="1"/>
+  </testsuite>
+  <testsuite name="Single/ValueParamTest" tests="4" failures="0" disabled="0" errors="0" time="*">
+    <testcase name="HasValueParamAttribute/0" value_param="33" status="run" time="*" classname="Single/ValueParamTest" />
+    <testcase name="HasValueParamAttribute/1" value_param="42" status="run" time="*" classname="Single/ValueParamTest" />
+    <testcase name="AnotherTestThatHasValueParamAttribute/0" value_param="33" status="run" time="*" classname="Single/ValueParamTest" />
+    <testcase name="AnotherTestThatHasValueParamAttribute/1" value_param="42" status="run" time="*" classname="Single/ValueParamTest" />
+  </testsuite>
+  <testsuite name="TypedTest/0" tests="1" failures="0" disabled="0" errors="0" time="*">
+    <testcase name="HasTypeParamAttribute" type_param="*" status="run" time="*" classname="TypedTest/0" />
+  </testsuite>
+  <testsuite name="TypedTest/1" tests="1" failures="0" disabled="0" errors="0" time="*">
+    <testcase name="HasTypeParamAttribute" type_param="*" status="run" time="*" classname="TypedTest/1" />
+  </testsuite>
+  <testsuite name="Single/TypeParameterizedTestCase/0" tests="1" failures="0" disabled="0" errors="0" time="*">
+    <testcase name="HasTypeParamAttribute" type_param="*" status="run" time="*" classname="Single/TypeParameterizedTestCase/0" />
+  </testsuite>
+  <testsuite name="Single/TypeParameterizedTestCase/1" tests="1" failures="0" disabled="0" errors="0" time="*">
+    <testcase name="HasTypeParamAttribute" type_param="*" status="run" time="*" classname="Single/TypeParameterizedTestCase/1" />
+  </testsuite>
+</testsuites>""" % {'stack': STACK_TRACE_TEMPLATE}
+
+
+EXPECTED_EMPTY_XML = """<?xml version="1.0" encoding="UTF-8"?>
+<testsuites tests="0" failures="0" disabled="0" errors="0" time="*" name="AllTests">
+</testsuites>"""
+
+
+class GTestXMLOutputUnitTest(gtest_xml_test_utils.GTestXMLTestCase):
+  """
+  Unit test for Google Test's XML output functionality.
+  """
+
+  def testNonEmptyXmlOutput(self):
+    """
+    Runs a test program that generates a non-empty XML output, and
+    tests that the XML output is expected.
+    """
+    self._TestXmlOutput(GTEST_PROGRAM_NAME, EXPECTED_NON_EMPTY_XML, 1)
+
+  def testEmptyXmlOutput(self):
+    """
+    Runs a test program that generates an empty XML output, and
+    tests that the XML output is expected.
+    """
+
+    self._TestXmlOutput("gtest_no_test_unittest",
+                        EXPECTED_EMPTY_XML, 0)
+
+  def testDefaultOutputFile(self):
+    """
+    Confirms that Google Test produces an XML output file with the expected
+    default name if no name is explicitly specified.
+    """
+    output_file = os.path.join(gtest_test_utils.GetTempDir(),
+                               GTEST_DEFAULT_OUTPUT_FILE)
+    gtest_prog_path = gtest_test_utils.GetTestExecutablePath(
+        "gtest_no_test_unittest")
+    try:
+      os.remove(output_file)
+    except OSError, e:
+      if e.errno != errno.ENOENT:
+        raise
+
+    p = gtest_test_utils.Subprocess(
+        [gtest_prog_path, "%s=xml" % GTEST_OUTPUT_FLAG],
+        working_dir=gtest_test_utils.GetTempDir())
+    self.assert_(p.exited)
+    self.assertEquals(0, p.exit_code)
+    self.assert_(os.path.isfile(output_file))
+
+  def testSuppressedXmlOutput(self):
+    """
+    Tests that no XML file is generated if the default XML listener is
+    shut down before RUN_ALL_TESTS is invoked.
+    """
+
+    xml_path = os.path.join(gtest_test_utils.GetTempDir(),
+                            GTEST_PROGRAM_NAME + "out.xml")
+    if os.path.isfile(xml_path):
+      os.remove(xml_path)
+
+    gtest_prog_path = gtest_test_utils.GetTestExecutablePath(GTEST_PROGRAM_NAME)
+
+    command = [gtest_prog_path,
+               "%s=xml:%s" % (GTEST_OUTPUT_FLAG, xml_path),
+               "--shut_down_xml"]
+    p = gtest_test_utils.Subprocess(command)
+    if p.terminated_by_signal:
+      self.assert_(False,
+                   "%s was killed by signal %d" % (gtest_prog_name, p.signal))
+    else:
+      self.assert_(p.exited)
+      self.assertEquals(1, p.exit_code,
+                        "'%s' exited with code %s, which doesn't match "
+                        "the expected exit code %s."
+                        % (command, p.exit_code, 1))
+
+    self.assert_(not os.path.isfile(xml_path))
+
+
+  def _TestXmlOutput(self, gtest_prog_name, expected_xml, expected_exit_code):
+    """
+    Asserts that the XML document generated by running the program
+    gtest_prog_name matches expected_xml, a string containing another
+    XML document.  Furthermore, the program's exit code must be
+    expected_exit_code.
+    """
+    xml_path = os.path.join(gtest_test_utils.GetTempDir(),
+                            gtest_prog_name + "out.xml")
+    gtest_prog_path = gtest_test_utils.GetTestExecutablePath(gtest_prog_name)
+
+    command = [gtest_prog_path, "%s=xml:%s" % (GTEST_OUTPUT_FLAG, xml_path)]
+    p = gtest_test_utils.Subprocess(command)
+    if p.terminated_by_signal:
+      self.assert_(False,
+                   "%s was killed by signal %d" % (gtest_prog_name, p.signal))
+    else:
+      self.assert_(p.exited)
+      self.assertEquals(expected_exit_code, p.exit_code,
+                        "'%s' exited with code %s, which doesn't match "
+                        "the expected exit code %s."
+                        % (command, p.exit_code, expected_exit_code))
+
+    expected = minidom.parseString(expected_xml)
+    actual   = minidom.parse(xml_path)
+    self.NormalizeXml(actual.documentElement)
+    self.AssertEquivalentNodes(expected.documentElement,
+                               actual.documentElement)
+    expected.unlink()
+    actual  .unlink()
+
+
+
+if __name__ == '__main__':
+  os.environ['GTEST_STACK_TRACE_DEPTH'] = '1'
+  gtest_test_utils.Main()
diff --git a/third_party/googletest/src/test/gtest_xml_output_unittest_.cc b/third_party/googletest/src/test/gtest_xml_output_unittest_.cc
new file mode 100644 (file)
index 0000000..741a887
--- /dev/null
@@ -0,0 +1,174 @@
+// Copyright 2006, 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: eefacm@gmail.com (Sean Mcafee)
+
+// Unit test for Google Test XML output.
+//
+// A user can specify XML output in a Google Test program to run via
+// either the GTEST_OUTPUT environment variable or the --gtest_output
+// flag.  This is used for testing such functionality.
+//
+// This program will be invoked from a Python unit test.  Don't run it
+// directly.
+
+#include "gtest/gtest.h"
+
+using ::testing::InitGoogleTest;
+using ::testing::TestEventListeners;
+using ::testing::TestWithParam;
+using ::testing::UnitTest;
+using ::testing::Test;
+using ::testing::Types;
+using ::testing::Values;
+
+class SuccessfulTest : public Test {
+};
+
+TEST_F(SuccessfulTest, Succeeds) {
+  SUCCEED() << "This is a success.";
+  ASSERT_EQ(1, 1);
+}
+
+class FailedTest : public Test {
+};
+
+TEST_F(FailedTest, Fails) {
+  ASSERT_EQ(1, 2);
+}
+
+class DisabledTest : public Test {
+};
+
+TEST_F(DisabledTest, DISABLED_test_not_run) {
+  FAIL() << "Unexpected failure: Disabled test should not be run";
+}
+
+TEST(MixedResultTest, Succeeds) {
+  EXPECT_EQ(1, 1);
+  ASSERT_EQ(1, 1);
+}
+
+TEST(MixedResultTest, Fails) {
+  EXPECT_EQ(1, 2);
+  ASSERT_EQ(2, 3);
+}
+
+TEST(MixedResultTest, DISABLED_test) {
+  FAIL() << "Unexpected failure: Disabled test should not be run";
+}
+
+TEST(XmlQuotingTest, OutputsCData) {
+  FAIL() << "XML output: "
+            "<?xml encoding=\"utf-8\"><top><![CDATA[cdata text]]></top>";
+}
+
+// Helps to test that invalid characters produced by test code do not make
+// it into the XML file.
+TEST(InvalidCharactersTest, InvalidCharactersInMessage) {
+  FAIL() << "Invalid characters in brackets [\x1\x2]";
+}
+
+class PropertyRecordingTest : public Test {
+};
+
+TEST_F(PropertyRecordingTest, OneProperty) {
+  RecordProperty("key_1", "1");
+}
+
+TEST_F(PropertyRecordingTest, IntValuedProperty) {
+  RecordProperty("key_int", 1);
+}
+
+TEST_F(PropertyRecordingTest, ThreeProperties) {
+  RecordProperty("key_1", "1");
+  RecordProperty("key_2", "2");
+  RecordProperty("key_3", "3");
+}
+
+TEST_F(PropertyRecordingTest, TwoValuesForOneKeyUsesLastValue) {
+  RecordProperty("key_1", "1");
+  RecordProperty("key_1", "2");
+}
+
+TEST(NoFixtureTest, RecordProperty) {
+  RecordProperty("key", "1");
+}
+
+void ExternalUtilityThatCallsRecordProperty(const char* key, int value) {
+  testing::Test::RecordProperty(key, value);
+}
+
+void ExternalUtilityThatCallsRecordProperty(const char* key,
+                                            const char* value) {
+  testing::Test::RecordProperty(key, value);
+}
+
+TEST(NoFixtureTest, ExternalUtilityThatCallsRecordIntValuedProperty) {
+  ExternalUtilityThatCallsRecordProperty("key_for_utility_int", 1);
+}
+
+TEST(NoFixtureTest, ExternalUtilityThatCallsRecordStringValuedProperty) {
+  ExternalUtilityThatCallsRecordProperty("key_for_utility_string", "1");
+}
+
+// Verifies that the test parameter value is output in the 'value_param'
+// XML attribute for value-parameterized tests.
+class ValueParamTest : public TestWithParam<int> {};
+TEST_P(ValueParamTest, HasValueParamAttribute) {}
+TEST_P(ValueParamTest, AnotherTestThatHasValueParamAttribute) {}
+INSTANTIATE_TEST_CASE_P(Single, ValueParamTest, Values(33, 42));
+
+// Verifies that the type parameter name is output in the 'type_param'
+// XML attribute for typed tests.
+template <typename T> class TypedTest : public Test {};
+typedef Types<int, long> TypedTestTypes;
+TYPED_TEST_CASE(TypedTest, TypedTestTypes);
+TYPED_TEST(TypedTest, HasTypeParamAttribute) {}
+
+// Verifies that the type parameter name is output in the 'type_param'
+// XML attribute for type-parameterized tests.
+template <typename T> class TypeParameterizedTestCase : public Test {};
+TYPED_TEST_CASE_P(TypeParameterizedTestCase);
+TYPED_TEST_P(TypeParameterizedTestCase, HasTypeParamAttribute) {}
+REGISTER_TYPED_TEST_CASE_P(TypeParameterizedTestCase, HasTypeParamAttribute);
+typedef Types<int, long> TypeParameterizedTestCaseTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(Single,
+                              TypeParameterizedTestCase,
+                              TypeParameterizedTestCaseTypes);
+
+int main(int argc, char** argv) {
+  InitGoogleTest(&argc, argv);
+
+  if (argc > 1 && strcmp(argv[1], "--shut_down_xml") == 0) {
+    TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
+    delete listeners.Release(listeners.default_xml_generator());
+  }
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/googletest/src/test/gtest_xml_test_utils.py b/third_party/googletest/src/test/gtest_xml_test_utils.py
new file mode 100755 (executable)
index 0000000..0f55c16
--- /dev/null
@@ -0,0 +1,179 @@
+#!/usr/bin/env python
+#
+# Copyright 2006, 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.
+
+"""Unit test utilities for gtest_xml_output"""
+
+__author__ = 'eefacm@gmail.com (Sean Mcafee)'
+
+import re
+from xml.dom import minidom, Node
+
+import gtest_test_utils
+
+
+GTEST_OUTPUT_FLAG         = "--gtest_output"
+GTEST_DEFAULT_OUTPUT_FILE = "test_detail.xml"
+
+class GTestXMLTestCase(gtest_test_utils.TestCase):
+  """
+  Base class for tests of Google Test's XML output functionality.
+  """
+
+
+  def AssertEquivalentNodes(self, expected_node, actual_node):
+    """
+    Asserts that actual_node (a DOM node object) is equivalent to
+    expected_node (another DOM node object), in that either both of
+    them are CDATA nodes and have the same value, or both are DOM
+    elements and actual_node meets all of the following conditions:
+
+    *  It has the same tag name as expected_node.
+    *  It has the same set of attributes as expected_node, each with
+       the same value as the corresponding attribute of expected_node.
+       Exceptions are any attribute named "time", which needs only be
+       convertible to a floating-point number and any attribute named
+       "type_param" which only has to be non-empty.
+    *  It has an equivalent set of child nodes (including elements and
+       CDATA sections) as expected_node.  Note that we ignore the
+       order of the children as they are not guaranteed to be in any
+       particular order.
+    """
+
+    if expected_node.nodeType == Node.CDATA_SECTION_NODE:
+      self.assertEquals(Node.CDATA_SECTION_NODE, actual_node.nodeType)
+      self.assertEquals(expected_node.nodeValue, actual_node.nodeValue)
+      return
+
+    self.assertEquals(Node.ELEMENT_NODE, actual_node.nodeType)
+    self.assertEquals(Node.ELEMENT_NODE, expected_node.nodeType)
+    self.assertEquals(expected_node.tagName, actual_node.tagName)
+
+    expected_attributes = expected_node.attributes
+    actual_attributes   = actual_node  .attributes
+    self.assertEquals(
+        expected_attributes.length, actual_attributes.length,
+        "attribute numbers differ in element " + actual_node.tagName)
+    for i in range(expected_attributes.length):
+      expected_attr = expected_attributes.item(i)
+      actual_attr   = actual_attributes.get(expected_attr.name)
+      self.assert_(
+          actual_attr is not None,
+          "expected attribute %s not found in element %s" %
+          (expected_attr.name, actual_node.tagName))
+      self.assertEquals(expected_attr.value, actual_attr.value,
+                        " values of attribute %s in element %s differ" %
+                        (expected_attr.name, actual_node.tagName))
+
+    expected_children = self._GetChildren(expected_node)
+    actual_children = self._GetChildren(actual_node)
+    self.assertEquals(
+        len(expected_children), len(actual_children),
+        "number of child elements differ in element " + actual_node.tagName)
+    for child_id, child in expected_children.iteritems():
+      self.assert_(child_id in actual_children,
+                   '<%s> is not in <%s> (in element %s)' %
+                   (child_id, actual_children, actual_node.tagName))
+      self.AssertEquivalentNodes(child, actual_children[child_id])
+
+  identifying_attribute = {
+    "testsuites": "name",
+    "testsuite": "name",
+    "testcase":  "name",
+    "failure":   "message",
+    }
+
+  def _GetChildren(self, element):
+    """
+    Fetches all of the child nodes of element, a DOM Element object.
+    Returns them as the values of a dictionary keyed by the IDs of the
+    children.  For <testsuites>, <testsuite> and <testcase> elements, the ID
+    is the value of their "name" attribute; for <failure> elements, it is
+    the value of the "message" attribute; CDATA sections and non-whitespace
+    text nodes are concatenated into a single CDATA section with ID
+    "detail".  An exception is raised if any element other than the above
+    four is encountered, if two child elements with the same identifying
+    attributes are encountered, or if any other type of node is encountered.
+    """
+
+    children = {}
+    for child in element.childNodes:
+      if child.nodeType == Node.ELEMENT_NODE:
+        self.assert_(child.tagName in self.identifying_attribute,
+                     "Encountered unknown element <%s>" % child.tagName)
+        childID = child.getAttribute(self.identifying_attribute[child.tagName])
+        self.assert_(childID not in children)
+        children[childID] = child
+      elif child.nodeType in [Node.TEXT_NODE, Node.CDATA_SECTION_NODE]:
+        if "detail" not in children:
+          if (child.nodeType == Node.CDATA_SECTION_NODE or
+              not child.nodeValue.isspace()):
+            children["detail"] = child.ownerDocument.createCDATASection(
+                child.nodeValue)
+        else:
+          children["detail"].nodeValue += child.nodeValue
+      else:
+        self.fail("Encountered unexpected node type %d" % child.nodeType)
+    return children
+
+  def NormalizeXml(self, element):
+    """
+    Normalizes Google Test's XML output to eliminate references to transient
+    information that may change from run to run.
+
+    *  The "time" attribute of <testsuites>, <testsuite> and <testcase>
+       elements is replaced with a single asterisk, if it contains
+       only digit characters.
+    *  The "type_param" attribute of <testcase> elements is replaced with a
+       single asterisk (if it sn non-empty) as it is the type name returned
+       by the compiler and is platform dependent.
+    *  The line number reported in the first line of the "message"
+       attribute of <failure> elements is replaced with a single asterisk.
+    *  The directory names in file paths are removed.
+    *  The stack traces are removed.
+    """
+
+    if element.tagName in ("testsuites", "testsuite", "testcase"):
+      time = element.getAttributeNode("time")
+      time.value = re.sub(r"^\d+(\.\d+)?$", "*", time.value)
+      type_param = element.getAttributeNode("type_param")
+      if type_param and type_param.value:
+        type_param.value = "*"
+    elif element.tagName == "failure":
+      for child in element.childNodes:
+        if child.nodeType == Node.CDATA_SECTION_NODE:
+          # Removes the source line number.
+          cdata = re.sub(r"^.*[/\\](.*:)\d+\n", "\\1*\n", child.nodeValue)
+          # Removes the actual stack trace.
+          child.nodeValue = re.sub(r"\nStack trace:\n(.|\n)*",
+                                   "", cdata)
+    for child in element.childNodes:
+      if child.nodeType == Node.ELEMENT_NODE:
+        self.NormalizeXml(child)
diff --git a/third_party/googletest/src/test/production.cc b/third_party/googletest/src/test/production.cc
new file mode 100644 (file)
index 0000000..8b8a40b
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2006, 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: wan@google.com (Zhanyong Wan)
+//
+// This is part of the unit test for include/gtest/gtest_prod.h.
+
+#include "production.h"
+
+PrivateCode::PrivateCode() : x_(0) {}
diff --git a/third_party/googletest/src/test/production.h b/third_party/googletest/src/test/production.h
new file mode 100644 (file)
index 0000000..98fd5e4
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright 2006, 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: wan@google.com (Zhanyong Wan)
+//
+// This is part of the unit test for include/gtest/gtest_prod.h.
+
+#ifndef GTEST_TEST_PRODUCTION_H_
+#define GTEST_TEST_PRODUCTION_H_
+
+#include "gtest/gtest_prod.h"
+
+class PrivateCode {
+ public:
+  // Declares a friend test that does not use a fixture.
+  FRIEND_TEST(PrivateCodeTest, CanAccessPrivateMembers);
+
+  // Declares a friend test that uses a fixture.
+  FRIEND_TEST(PrivateCodeFixtureTest, CanAccessPrivateMembers);
+
+  PrivateCode();
+
+  int x() const { return x_; }
+ private:
+  void set_x(int an_x) { x_ = an_x; }
+  int x_;
+};
+
+#endif  // GTEST_TEST_PRODUCTION_H_
diff --git a/third_party/googletest/src/xcode/Config/DebugProject.xcconfig b/third_party/googletest/src/xcode/Config/DebugProject.xcconfig
new file mode 100644 (file)
index 0000000..3d68157
--- /dev/null
@@ -0,0 +1,30 @@
+//
+//  DebugProject.xcconfig
+//
+//  These are Debug Configuration project settings for the gtest framework and
+//  examples. It is set in the "Based On:" dropdown in the "Project" info
+//  dialog.
+//  This file is based on the Xcode Configuration files in:
+//  http://code.google.com/p/google-toolbox-for-mac/
+// 
+
+#include "General.xcconfig"
+
+// No optimization
+GCC_OPTIMIZATION_LEVEL = 0
+
+// Deployment postprocessing is what triggers Xcode to strip, turn it off
+DEPLOYMENT_POSTPROCESSING = NO
+
+// Dead code stripping off
+DEAD_CODE_STRIPPING = NO
+
+// Debug symbols should be on obviously
+GCC_GENERATE_DEBUGGING_SYMBOLS = YES
+
+// Define the DEBUG macro in all debug builds
+OTHER_CFLAGS = $(OTHER_CFLAGS) -DDEBUG=1
+
+// These are turned off to avoid STL incompatibilities with client code
+// // Turns on special C++ STL checks to "encourage" good STL use
+// GCC_PREPROCESSOR_DEFINITIONS = $(GCC_PREPROCESSOR_DEFINITIONS) _GLIBCXX_DEBUG_PEDANTIC _GLIBCXX_DEBUG _GLIBCPP_CONCEPT_CHECKS
diff --git a/third_party/googletest/src/xcode/Config/FrameworkTarget.xcconfig b/third_party/googletest/src/xcode/Config/FrameworkTarget.xcconfig
new file mode 100644 (file)
index 0000000..357b1c8
--- /dev/null
@@ -0,0 +1,17 @@
+//
+//  FrameworkTarget.xcconfig
+//
+//  These are Framework target settings for the gtest framework and examples. It
+//  is set in the "Based On:" dropdown in the "Target" info dialog.
+//  This file is based on the Xcode Configuration files in:
+//  http://code.google.com/p/google-toolbox-for-mac/
+// 
+
+// Dynamic libs need to be position independent
+GCC_DYNAMIC_NO_PIC = NO
+
+// Dynamic libs should not have their external symbols stripped.
+STRIP_STYLE = non-global
+
+// Let the user install by specifying the $DSTROOT with xcodebuild
+SKIP_INSTALL = NO
diff --git a/third_party/googletest/src/xcode/Config/General.xcconfig b/third_party/googletest/src/xcode/Config/General.xcconfig
new file mode 100644 (file)
index 0000000..f23e322
--- /dev/null
@@ -0,0 +1,41 @@
+//
+//  General.xcconfig
+//
+//  These are General configuration settings for the gtest framework and
+//  examples.
+//  This file is based on the Xcode Configuration files in:
+//  http://code.google.com/p/google-toolbox-for-mac/
+// 
+
+// Build for PPC and Intel, 32- and 64-bit
+ARCHS = i386 x86_64 ppc ppc64
+
+// Zerolink prevents link warnings so turn it off
+ZERO_LINK = NO
+
+// Prebinding considered unhelpful in 10.3 and later
+PREBINDING = NO
+
+// Strictest warning policy
+WARNING_CFLAGS = -Wall -Werror -Wendif-labels -Wnewline-eof -Wno-sign-compare -Wshadow
+
+// Work around Xcode bugs by using external strip. See:
+// http://lists.apple.com/archives/Xcode-users/2006/Feb/msg00050.html
+SEPARATE_STRIP = YES
+
+// Force C99 dialect
+GCC_C_LANGUAGE_STANDARD = c99
+
+// not sure why apple defaults this on, but it's pretty risky
+ALWAYS_SEARCH_USER_PATHS = NO
+
+// Turn on position dependent code for most cases (overridden where appropriate)
+GCC_DYNAMIC_NO_PIC = YES
+
+// Default SDK and minimum OS version is 10.4
+SDKROOT = $(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk
+MACOSX_DEPLOYMENT_TARGET = 10.4
+GCC_VERSION = 4.0
+
+// VERSIONING BUILD SETTINGS (used in Info.plist)
+GTEST_VERSIONINFO_ABOUT =  © 2008 Google Inc.
diff --git a/third_party/googletest/src/xcode/Config/ReleaseProject.xcconfig b/third_party/googletest/src/xcode/Config/ReleaseProject.xcconfig
new file mode 100644 (file)
index 0000000..5349f0a
--- /dev/null
@@ -0,0 +1,32 @@
+//
+//  ReleaseProject.xcconfig
+//
+//  These are Release Configuration project settings for the gtest framework
+//  and examples. It is set in the "Based On:" dropdown in the "Project" info
+//  dialog.
+//  This file is based on the Xcode Configuration files in:
+//  http://code.google.com/p/google-toolbox-for-mac/
+// 
+
+#include "General.xcconfig"
+
+// subconfig/Release.xcconfig
+
+// Optimize for space and size (Apple recommendation)
+GCC_OPTIMIZATION_LEVEL = s
+
+// Deploment postprocessing is what triggers Xcode to strip
+DEPLOYMENT_POSTPROCESSING = YES
+
+// No symbols
+GCC_GENERATE_DEBUGGING_SYMBOLS = NO
+
+// Dead code strip does not affect ObjC code but can help for C
+DEAD_CODE_STRIPPING = YES
+
+// NDEBUG is used by things like assert.h, so define it for general compat.
+// ASSERT going away in release tends to create unused vars.
+OTHER_CFLAGS = $(OTHER_CFLAGS) -DNDEBUG=1 -Wno-unused-variable
+
+// When we strip we want to strip all symbols in release, but save externals.
+STRIP_STYLE = all
diff --git a/third_party/googletest/src/xcode/Config/StaticLibraryTarget.xcconfig b/third_party/googletest/src/xcode/Config/StaticLibraryTarget.xcconfig
new file mode 100644 (file)
index 0000000..3922fa5
--- /dev/null
@@ -0,0 +1,18 @@
+//
+//  StaticLibraryTarget.xcconfig
+//
+//  These are static library target settings for libgtest.a. It
+//  is set in the "Based On:" dropdown in the "Target" info dialog.
+//  This file is based on the Xcode Configuration files in:
+//  http://code.google.com/p/google-toolbox-for-mac/
+// 
+
+// Static libs can be included in bundles so make them position independent
+GCC_DYNAMIC_NO_PIC = NO
+
+// Static libs should not have their internal globals or external symbols
+// stripped.
+STRIP_STYLE = debugging
+
+// Let the user install by specifying the $DSTROOT with xcodebuild
+SKIP_INSTALL = NO
diff --git a/third_party/googletest/src/xcode/Config/TestTarget.xcconfig b/third_party/googletest/src/xcode/Config/TestTarget.xcconfig
new file mode 100644 (file)
index 0000000..e6652ba
--- /dev/null
@@ -0,0 +1,8 @@
+//
+//  TestTarget.xcconfig
+//
+//  These are Test target settings for the gtest framework and examples. It
+//  is set in the "Based On:" dropdown in the "Target" info dialog.
+
+PRODUCT_NAME = $(TARGET_NAME)
+HEADER_SEARCH_PATHS = ../include
diff --git a/third_party/googletest/src/xcode/Resources/Info.plist b/third_party/googletest/src/xcode/Resources/Info.plist
new file mode 100644 (file)
index 0000000..9dd28ea
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundleExecutable</key>
+       <string>${EXECUTABLE_NAME}</string>
+       <key>CFBundleIconFile</key>
+       <string></string>
+       <key>CFBundleIdentifier</key>
+       <string>com.google.${PRODUCT_NAME}</string>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundlePackageType</key>
+       <string>FMWK</string>
+       <key>CFBundleSignature</key>
+       <string>????</string>
+       <key>CFBundleVersion</key>
+       <string>GTEST_VERSIONINFO_LONG</string>
+       <key>CFBundleShortVersionString</key>
+       <string>GTEST_VERSIONINFO_SHORT</string>
+       <key>CFBundleGetInfoString</key>
+       <string>${PRODUCT_NAME} GTEST_VERSIONINFO_LONG, ${GTEST_VERSIONINFO_ABOUT}</string>
+       <key>NSHumanReadableCopyright</key>
+       <string>${GTEST_VERSIONINFO_ABOUT}</string>
+       <key>CSResourcesFileMapped</key>
+       <true/>
+</dict>
+</plist>
diff --git a/third_party/googletest/src/xcode/Samples/FrameworkSample/Info.plist b/third_party/googletest/src/xcode/Samples/FrameworkSample/Info.plist
new file mode 100644 (file)
index 0000000..f3852ed
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundleExecutable</key>
+       <string>${EXECUTABLE_NAME}</string>
+       <key>CFBundleIconFile</key>
+       <string></string>
+       <key>CFBundleIdentifier</key>
+       <string>com.google.gtest.${PRODUCT_NAME:identifier}</string>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundleName</key>
+       <string>${PRODUCT_NAME}</string>
+       <key>CFBundlePackageType</key>
+       <string>FMWK</string>
+       <key>CFBundleShortVersionString</key>
+       <string>1.0</string>
+       <key>CFBundleSignature</key>
+       <string>????</string>
+       <key>CFBundleVersion</key>
+       <string>1.0</string>
+       <key>CSResourcesFileMapped</key>
+       <true/>
+</dict>
+</plist>
diff --git a/third_party/googletest/src/xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj b/third_party/googletest/src/xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj
new file mode 100644 (file)
index 0000000..497617e
--- /dev/null
@@ -0,0 +1,457 @@
+// !$*UTF8*$!
+{
+       archiveVersion = 1;
+       classes = {
+       };
+       objectVersion = 42;
+       objects = {
+
+/* Begin PBXAggregateTarget section */
+               4024D162113D7D2400C7059E /* Test */ = {
+                       isa = PBXAggregateTarget;
+                       buildConfigurationList = 4024D169113D7D4600C7059E /* Build configuration list for PBXAggregateTarget "Test" */;
+                       buildPhases = (
+                               4024D161113D7D2400C7059E /* ShellScript */,
+                       );
+                       dependencies = (
+                               4024D166113D7D3100C7059E /* PBXTargetDependency */,
+                       );
+                       name = Test;
+                       productName = TestAndBuild;
+               };
+               4024D1E9113D83FF00C7059E /* TestAndBuild */ = {
+                       isa = PBXAggregateTarget;
+                       buildConfigurationList = 4024D1F0113D842B00C7059E /* Build configuration list for PBXAggregateTarget "TestAndBuild" */;
+                       buildPhases = (
+                       );
+                       dependencies = (
+                               4024D1ED113D840900C7059E /* PBXTargetDependency */,
+                               4024D1EF113D840D00C7059E /* PBXTargetDependency */,
+                       );
+                       name = TestAndBuild;
+                       productName = TestAndBuild;
+               };
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+               3B7EB1250E5AEE3500C7F239 /* widget.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3B7EB1230E5AEE3500C7F239 /* widget.cc */; };
+               3B7EB1260E5AEE3500C7F239 /* widget.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B7EB1240E5AEE3500C7F239 /* widget.h */; settings = {ATTRIBUTES = (Public, ); }; };
+               3B7EB1280E5AEE4600C7F239 /* widget_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3B7EB1270E5AEE4600C7F239 /* widget_test.cc */; };
+               3B7EB1480E5AF3B400C7F239 /* Widget.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D07F2C80486CC7A007CD1D0 /* Widget.framework */; };
+               4024D188113D7D7800C7059E /* libgtest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4024D185113D7D5500C7059E /* libgtest.a */; };
+               4024D189113D7D7A00C7059E /* libgtest_main.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4024D183113D7D5500C7059E /* libgtest_main.a */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+               3B07BDF00E3F3FAE00647869 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 8D07F2BC0486CC7A007CD1D0;
+                       remoteInfo = gTestExample;
+               };
+               4024D165113D7D3100C7059E /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 3B07BDE90E3F3F9E00647869;
+                       remoteInfo = WidgetFrameworkTest;
+               };
+               4024D1EC113D840900C7059E /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 8D07F2BC0486CC7A007CD1D0;
+                       remoteInfo = WidgetFramework;
+               };
+               4024D1EE113D840D00C7059E /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 4024D162113D7D2400C7059E;
+                       remoteInfo = Test;
+               };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+               3B07BDEA0E3F3F9E00647869 /* WidgetFrameworkTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = WidgetFrameworkTest; sourceTree = BUILT_PRODUCTS_DIR; };
+               3B7EB1230E5AEE3500C7F239 /* widget.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = widget.cc; sourceTree = "<group>"; };
+               3B7EB1240E5AEE3500C7F239 /* widget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = widget.h; sourceTree = "<group>"; };
+               3B7EB1270E5AEE4600C7F239 /* widget_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = widget_test.cc; sourceTree = "<group>"; };
+               4024D183113D7D5500C7059E /* libgtest_main.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgtest_main.a; path = /usr/local/lib/libgtest_main.a; sourceTree = "<absolute>"; };
+               4024D185113D7D5500C7059E /* libgtest.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgtest.a; path = /usr/local/lib/libgtest.a; sourceTree = "<absolute>"; };
+               4024D1E2113D838200C7059E /* runtests.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = runtests.sh; sourceTree = "<group>"; };
+               8D07F2C70486CC7A007CD1D0 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
+               8D07F2C80486CC7A007CD1D0 /* Widget.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Widget.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+               3B07BDE80E3F3F9E00647869 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               4024D189113D7D7A00C7059E /* libgtest_main.a in Frameworks */,
+                               4024D188113D7D7800C7059E /* libgtest.a in Frameworks */,
+                               3B7EB1480E5AF3B400C7F239 /* Widget.framework in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               8D07F2C30486CC7A007CD1D0 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+               034768DDFF38A45A11DB9C8B /* Products */ = {
+                       isa = PBXGroup;
+                       children = (
+                               8D07F2C80486CC7A007CD1D0 /* Widget.framework */,
+                               3B07BDEA0E3F3F9E00647869 /* WidgetFrameworkTest */,
+                       );
+                       name = Products;
+                       sourceTree = "<group>";
+               };
+               0867D691FE84028FC02AAC07 /* gTestExample */ = {
+                       isa = PBXGroup;
+                       children = (
+                               4024D1E1113D836C00C7059E /* Scripts */,
+                               08FB77ACFE841707C02AAC07 /* Source */,
+                               089C1665FE841158C02AAC07 /* Resources */,
+                               3B07BE350E4094E400647869 /* Test */,
+                               0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
+                               034768DDFF38A45A11DB9C8B /* Products */,
+                       );
+                       name = gTestExample;
+                       sourceTree = "<group>";
+               };
+               0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = {
+                       isa = PBXGroup;
+                       children = (
+                               4024D183113D7D5500C7059E /* libgtest_main.a */,
+                               4024D185113D7D5500C7059E /* libgtest.a */,
+                       );
+                       name = "External Frameworks and Libraries";
+                       sourceTree = "<group>";
+               };
+               089C1665FE841158C02AAC07 /* Resources */ = {
+                       isa = PBXGroup;
+                       children = (
+                               8D07F2C70486CC7A007CD1D0 /* Info.plist */,
+                       );
+                       name = Resources;
+                       sourceTree = "<group>";
+               };
+               08FB77ACFE841707C02AAC07 /* Source */ = {
+                       isa = PBXGroup;
+                       children = (
+                               3B7EB1230E5AEE3500C7F239 /* widget.cc */,
+                               3B7EB1240E5AEE3500C7F239 /* widget.h */,
+                       );
+                       name = Source;
+                       sourceTree = "<group>";
+               };
+               3B07BE350E4094E400647869 /* Test */ = {
+                       isa = PBXGroup;
+                       children = (
+                               3B7EB1270E5AEE4600C7F239 /* widget_test.cc */,
+                       );
+                       name = Test;
+                       sourceTree = "<group>";
+               };
+               4024D1E1113D836C00C7059E /* Scripts */ = {
+                       isa = PBXGroup;
+                       children = (
+                               4024D1E2113D838200C7059E /* runtests.sh */,
+                       );
+                       name = Scripts;
+                       sourceTree = "<group>";
+               };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+               8D07F2BD0486CC7A007CD1D0 /* Headers */ = {
+                       isa = PBXHeadersBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               3B7EB1260E5AEE3500C7F239 /* widget.h in Headers */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+               3B07BDE90E3F3F9E00647869 /* WidgetFrameworkTest */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 3B07BDF40E3F3FB600647869 /* Build configuration list for PBXNativeTarget "WidgetFrameworkTest" */;
+                       buildPhases = (
+                               3B07BDE70E3F3F9E00647869 /* Sources */,
+                               3B07BDE80E3F3F9E00647869 /* Frameworks */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               3B07BDF10E3F3FAE00647869 /* PBXTargetDependency */,
+                       );
+                       name = WidgetFrameworkTest;
+                       productName = gTestExampleTest;
+                       productReference = 3B07BDEA0E3F3F9E00647869 /* WidgetFrameworkTest */;
+                       productType = "com.apple.product-type.tool";
+               };
+               8D07F2BC0486CC7A007CD1D0 /* WidgetFramework */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 4FADC24208B4156D00ABE55E /* Build configuration list for PBXNativeTarget "WidgetFramework" */;
+                       buildPhases = (
+                               8D07F2C10486CC7A007CD1D0 /* Sources */,
+                               8D07F2C30486CC7A007CD1D0 /* Frameworks */,
+                               8D07F2BD0486CC7A007CD1D0 /* Headers */,
+                               8D07F2BF0486CC7A007CD1D0 /* Resources */,
+                               8D07F2C50486CC7A007CD1D0 /* Rez */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                       );
+                       name = WidgetFramework;
+                       productInstallPath = "$(HOME)/Library/Frameworks";
+                       productName = gTestExample;
+                       productReference = 8D07F2C80486CC7A007CD1D0 /* Widget.framework */;
+                       productType = "com.apple.product-type.framework";
+               };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+               0867D690FE84028FC02AAC07 /* Project object */ = {
+                       isa = PBXProject;
+                       buildConfigurationList = 4FADC24608B4156D00ABE55E /* Build configuration list for PBXProject "WidgetFramework" */;
+                       compatibilityVersion = "Xcode 2.4";
+                       hasScannedForEncodings = 1;
+                       mainGroup = 0867D691FE84028FC02AAC07 /* gTestExample */;
+                       productRefGroup = 034768DDFF38A45A11DB9C8B /* Products */;
+                       projectDirPath = "";
+                       projectRoot = "";
+                       targets = (
+                               8D07F2BC0486CC7A007CD1D0 /* WidgetFramework */,
+                               3B07BDE90E3F3F9E00647869 /* WidgetFrameworkTest */,
+                               4024D162113D7D2400C7059E /* Test */,
+                               4024D1E9113D83FF00C7059E /* TestAndBuild */,
+                       );
+               };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+               8D07F2BF0486CC7A007CD1D0 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXRezBuildPhase section */
+               8D07F2C50486CC7A007CD1D0 /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXRezBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+               4024D161113D7D2400C7059E /* ShellScript */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "/bin/bash $SRCROOT/runtests.sh $BUILT_PRODUCTS_DIR/WidgetFrameworkTest\n";
+               };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+               3B07BDE70E3F3F9E00647869 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               3B7EB1280E5AEE4600C7F239 /* widget_test.cc in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               8D07F2C10486CC7A007CD1D0 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               3B7EB1250E5AEE3500C7F239 /* widget.cc in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+               3B07BDF10E3F3FAE00647869 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 8D07F2BC0486CC7A007CD1D0 /* WidgetFramework */;
+                       targetProxy = 3B07BDF00E3F3FAE00647869 /* PBXContainerItemProxy */;
+               };
+               4024D166113D7D3100C7059E /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 3B07BDE90E3F3F9E00647869 /* WidgetFrameworkTest */;
+                       targetProxy = 4024D165113D7D3100C7059E /* PBXContainerItemProxy */;
+               };
+               4024D1ED113D840900C7059E /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 8D07F2BC0486CC7A007CD1D0 /* WidgetFramework */;
+                       targetProxy = 4024D1EC113D840900C7059E /* PBXContainerItemProxy */;
+               };
+               4024D1EF113D840D00C7059E /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 4024D162113D7D2400C7059E /* Test */;
+                       targetProxy = 4024D1EE113D840D00C7059E /* PBXContainerItemProxy */;
+               };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+               3B07BDEC0E3F3F9F00647869 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = WidgetFrameworkTest;
+                       };
+                       name = Debug;
+               };
+               3B07BDED0E3F3F9F00647869 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = WidgetFrameworkTest;
+                       };
+                       name = Release;
+               };
+               4024D163113D7D2400C7059E /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = TestAndBuild;
+                       };
+                       name = Debug;
+               };
+               4024D164113D7D2400C7059E /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = TestAndBuild;
+                       };
+                       name = Release;
+               };
+               4024D1EA113D83FF00C7059E /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = TestAndBuild;
+                       };
+                       name = Debug;
+               };
+               4024D1EB113D83FF00C7059E /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = TestAndBuild;
+                       };
+                       name = Release;
+               };
+               4FADC24308B4156D00ABE55E /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               DYLIB_COMPATIBILITY_VERSION = 1;
+                               DYLIB_CURRENT_VERSION = 1;
+                               FRAMEWORK_VERSION = A;
+                               INFOPLIST_FILE = Info.plist;
+                               INSTALL_PATH = "@loader_path/../Frameworks";
+                               PRODUCT_NAME = Widget;
+                       };
+                       name = Debug;
+               };
+               4FADC24408B4156D00ABE55E /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               DYLIB_COMPATIBILITY_VERSION = 1;
+                               DYLIB_CURRENT_VERSION = 1;
+                               FRAMEWORK_VERSION = A;
+                               INFOPLIST_FILE = Info.plist;
+                               INSTALL_PATH = "@loader_path/../Frameworks";
+                               PRODUCT_NAME = Widget;
+                       };
+                       name = Release;
+               };
+               4FADC24708B4156D00ABE55E /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_VERSION = 4.0;
+                               SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+                       };
+                       name = Debug;
+               };
+               4FADC24808B4156D00ABE55E /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_VERSION = 4.0;
+                               SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+                       };
+                       name = Release;
+               };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+               3B07BDF40E3F3FB600647869 /* Build configuration list for PBXNativeTarget "WidgetFrameworkTest" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               3B07BDEC0E3F3F9F00647869 /* Debug */,
+                               3B07BDED0E3F3F9F00647869 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               4024D169113D7D4600C7059E /* Build configuration list for PBXAggregateTarget "Test" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               4024D163113D7D2400C7059E /* Debug */,
+                               4024D164113D7D2400C7059E /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               4024D1F0113D842B00C7059E /* Build configuration list for PBXAggregateTarget "TestAndBuild" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               4024D1EA113D83FF00C7059E /* Debug */,
+                               4024D1EB113D83FF00C7059E /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               4FADC24208B4156D00ABE55E /* Build configuration list for PBXNativeTarget "WidgetFramework" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               4FADC24308B4156D00ABE55E /* Debug */,
+                               4FADC24408B4156D00ABE55E /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               4FADC24608B4156D00ABE55E /* Build configuration list for PBXProject "WidgetFramework" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               4FADC24708B4156D00ABE55E /* Debug */,
+                               4FADC24808B4156D00ABE55E /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+/* End XCConfigurationList section */
+       };
+       rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
+}
diff --git a/third_party/googletest/src/xcode/Samples/FrameworkSample/runtests.sh b/third_party/googletest/src/xcode/Samples/FrameworkSample/runtests.sh
new file mode 100755 (executable)
index 0000000..4a0d413
--- /dev/null
@@ -0,0 +1,62 @@
+#!/bin/bash
+#
+# Copyright 2008, 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.
+
+# Executes the samples and tests for the Google Test Framework.
+
+# Help the dynamic linker find the path to the libraries.
+export DYLD_FRAMEWORK_PATH=$BUILT_PRODUCTS_DIR
+export DYLD_LIBRARY_PATH=$BUILT_PRODUCTS_DIR
+
+# Create some executables.
+test_executables=$@
+
+# Now execute each one in turn keeping track of how many succeeded and failed.
+succeeded=0
+failed=0
+failed_list=()
+for test in ${test_executables[*]}; do
+  "$test"
+  result=$?
+  if [ $result -eq 0 ]; then
+    succeeded=$(( $succeeded + 1 ))
+  else
+    failed=$(( failed + 1 ))
+    failed_list="$failed_list $test"
+  fi
+done
+
+# Report the successes and failures to the console.
+echo "Tests complete with $succeeded successes and $failed failures."
+if [ $failed -ne 0 ]; then
+  echo "The following tests failed:"
+  echo $failed_list
+fi
+exit $failed
diff --git a/third_party/googletest/src/xcode/Samples/FrameworkSample/widget.cc b/third_party/googletest/src/xcode/Samples/FrameworkSample/widget.cc
new file mode 100644 (file)
index 0000000..bfc4e7f
--- /dev/null
@@ -0,0 +1,63 @@
+// Copyright 2008, 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: preston.a.jackson@gmail.com (Preston Jackson)
+//
+// Google Test - FrameworkSample
+// widget.cc
+//
+
+// Widget is a very simple class used for demonstrating the use of gtest
+
+#include "widget.h"
+
+Widget::Widget(int number, const std::string& name)
+    : number_(number),
+      name_(name) {}
+
+Widget::~Widget() {}
+
+float Widget::GetFloatValue() const {
+  return number_;
+}
+
+int Widget::GetIntValue() const {
+  return static_cast<int>(number_);
+}
+
+std::string Widget::GetStringValue() const {
+  return name_;
+}
+
+void Widget::GetCharPtrValue(char* buffer, size_t max_size) const {
+  // Copy the char* representation of name_ into buffer, up to max_size.
+  strncpy(buffer, name_.c_str(), max_size-1);
+  buffer[max_size-1] = '\0';
+  return;
+}
diff --git a/third_party/googletest/src/xcode/Samples/FrameworkSample/widget.h b/third_party/googletest/src/xcode/Samples/FrameworkSample/widget.h
new file mode 100644 (file)
index 0000000..0c55cdc
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright 2008, 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: preston.a.jackson@gmail.com (Preston Jackson)
+//
+// Google Test - FrameworkSample
+// widget.h
+//
+
+// Widget is a very simple class used for demonstrating the use of gtest. It
+// simply stores two values a string and an integer, which are returned via
+// public accessors in multiple forms.
+
+#import <string>
+
+class Widget {
+ public:
+  Widget(int number, const std::string& name);
+  ~Widget();
+
+  // Public accessors to number data
+  float GetFloatValue() const;
+  int GetIntValue() const;
+
+  // Public accessors to the string data
+  std::string GetStringValue() const;
+  void GetCharPtrValue(char* buffer, size_t max_size) const;
+
+ private:
+  // Data members
+  float number_;
+  std::string name_;
+};
diff --git a/third_party/googletest/src/xcode/Samples/FrameworkSample/widget_test.cc b/third_party/googletest/src/xcode/Samples/FrameworkSample/widget_test.cc
new file mode 100644 (file)
index 0000000..8725994
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright 2008, 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: preston.a.jackson@gmail.com (Preston Jackson)
+//
+// Google Test - FrameworkSample
+// widget_test.cc
+//
+
+// This is a simple test file for the Widget class in the Widget.framework
+
+#include <string>
+#include "gtest/gtest.h"
+
+#include <Widget/widget.h>
+
+// This test verifies that the constructor sets the internal state of the
+// Widget class correctly.
+TEST(WidgetInitializerTest, TestConstructor) {
+  Widget widget(1.0f, "name");
+  EXPECT_FLOAT_EQ(1.0f, widget.GetFloatValue());
+  EXPECT_EQ(std::string("name"), widget.GetStringValue());
+}
+
+// This test verifies the conversion of the float and string values to int and
+// char*, respectively.
+TEST(WidgetInitializerTest, TestConversion) {
+  Widget widget(1.0f, "name");
+  EXPECT_EQ(1, widget.GetIntValue());
+
+  size_t max_size = 128;
+  char buffer[max_size];
+  widget.GetCharPtrValue(buffer, max_size);
+  EXPECT_STREQ("name", buffer);
+}
+
+// Use the Google Test main that is linked into the framework. It does something
+// like this:
+// int main(int argc, char** argv) {
+//   testing::InitGoogleTest(&argc, argv);
+//   return RUN_ALL_TESTS();
+// }
diff --git a/third_party/googletest/src/xcode/Scripts/runtests.sh b/third_party/googletest/src/xcode/Scripts/runtests.sh
new file mode 100755 (executable)
index 0000000..3fc229f
--- /dev/null
@@ -0,0 +1,65 @@
+#!/bin/bash
+#
+# Copyright 2008, 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.
+
+# Executes the samples and tests for the Google Test Framework.
+
+# Help the dynamic linker find the path to the libraries.
+export DYLD_FRAMEWORK_PATH=$BUILT_PRODUCTS_DIR
+export DYLD_LIBRARY_PATH=$BUILT_PRODUCTS_DIR
+
+# Create some executables.
+test_executables=("$BUILT_PRODUCTS_DIR/gtest_unittest-framework"
+                  "$BUILT_PRODUCTS_DIR/gtest_unittest"
+                  "$BUILT_PRODUCTS_DIR/sample1_unittest-framework"
+                  "$BUILT_PRODUCTS_DIR/sample1_unittest-static")
+
+# Now execute each one in turn keeping track of how many succeeded and failed. 
+succeeded=0
+failed=0
+failed_list=()
+for test in ${test_executables[*]}; do
+  "$test"
+  result=$?
+  if [ $result -eq 0 ]; then
+    succeeded=$(( $succeeded + 1 ))
+  else
+    failed=$(( failed + 1 ))
+    failed_list="$failed_list $test"
+  fi
+done
+
+# Report the successes and failures to the console.
+echo "Tests complete with $succeeded successes and $failed failures."
+if [ $failed -ne 0 ]; then
+  echo "The following tests failed:"
+  echo $failed_list
+fi
+exit $failed
diff --git a/third_party/googletest/src/xcode/Scripts/versiongenerate.py b/third_party/googletest/src/xcode/Scripts/versiongenerate.py
new file mode 100755 (executable)
index 0000000..81de8c9
--- /dev/null
@@ -0,0 +1,100 @@
+#!/usr/bin/env python
+#
+# Copyright 2008, 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.
+
+"""A script to prepare version informtion for use the gtest Info.plist file.
+
+  This script extracts the version information from the configure.ac file and
+  uses it to generate a header file containing the same information. The
+  #defines in this header file will be included in during the generation of
+  the Info.plist of the framework, giving the correct value to the version
+  shown in the Finder.
+
+  This script makes the following assumptions (these are faults of the script,
+  not problems with the Autoconf):
+    1. The AC_INIT macro will be contained within the first 1024 characters
+       of configure.ac
+    2. The version string will be 3 integers separated by periods and will be
+       surrounded by squre brackets, "[" and "]" (e.g. [1.0.1]). The first
+       segment represents the major version, the second represents the minor
+       version and the third represents the fix version.
+    3. No ")" character exists between the opening "(" and closing ")" of
+       AC_INIT, including in comments and character strings.
+"""
+
+import sys
+import re
+
+# Read the command line argument (the output directory for Version.h)
+if (len(sys.argv) < 3):
+  print "Usage: versiongenerate.py input_dir output_dir"
+  sys.exit(1)
+else:
+  input_dir = sys.argv[1]
+  output_dir = sys.argv[2]
+
+# Read the first 1024 characters of the configure.ac file
+config_file = open("%s/configure.ac" % input_dir, 'r')
+buffer_size = 1024
+opening_string = config_file.read(buffer_size)
+config_file.close()
+
+# Extract the version string from the AC_INIT macro
+#   The following init_expression means:
+#     Extract three integers separated by periods and surrounded by squre
+#     brackets(e.g. "[1.0.1]") between "AC_INIT(" and ")". Do not be greedy
+#     (*? is the non-greedy flag) since that would pull in everything between
+#     the first "(" and the last ")" in the file.
+version_expression = re.compile(r"AC_INIT\(.*?\[(\d+)\.(\d+)\.(\d+)\].*?\)",
+                                re.DOTALL)
+version_values = version_expression.search(opening_string)
+major_version = version_values.group(1)
+minor_version = version_values.group(2)
+fix_version = version_values.group(3)
+
+# Write the version information to a header file to be included in the
+# Info.plist file.
+file_data = """//
+// DO NOT MODIFY THIS FILE (but you can delete it)
+//
+// This file is autogenerated by the versiongenerate.py script. This script
+// is executed in a "Run Script" build phase when creating gtest.framework. This
+// header file is not used during compilation of C-source. Rather, it simply
+// defines some version strings for substitution in the Info.plist. Because of
+// this, we are not not restricted to C-syntax nor are we using include guards.
+//
+
+#define GTEST_VERSIONINFO_SHORT %s.%s
+#define GTEST_VERSIONINFO_LONG %s.%s.%s
+
+""" % (major_version, minor_version, major_version, minor_version, fix_version)
+version_file = open("%s/Version.h" % output_dir, 'w')
+version_file.write(file_data)
+version_file.close()
diff --git a/third_party/googletest/src/xcode/gtest.xcodeproj/project.pbxproj b/third_party/googletest/src/xcode/gtest.xcodeproj/project.pbxproj
new file mode 100644 (file)
index 0000000..74a7815
--- /dev/null
@@ -0,0 +1,1084 @@
+// !$*UTF8*$!
+{
+       archiveVersion = 1;
+       classes = {
+       };
+       objectVersion = 42;
+       objects = {
+
+/* Begin PBXAggregateTarget section */
+               3B238F5F0E828B5400846E11 /* Check */ = {
+                       isa = PBXAggregateTarget;
+                       buildConfigurationList = 3B238FA30E828BB600846E11 /* Build configuration list for PBXAggregateTarget "Check" */;
+                       buildPhases = (
+                               3B238F5E0E828B5400846E11 /* ShellScript */,
+                       );
+                       dependencies = (
+                               40899F9D0FFA740F000B29AE /* PBXTargetDependency */,
+                               40C849F7101A43440083642A /* PBXTargetDependency */,
+                               4089A0980FFAD34A000B29AE /* PBXTargetDependency */,
+                               40C849F9101A43490083642A /* PBXTargetDependency */,
+                       );
+                       name = Check;
+                       productName = Check;
+               };
+               40C44ADC0E3798F4008FCC51 /* Version Info */ = {
+                       isa = PBXAggregateTarget;
+                       buildConfigurationList = 40C44AE40E379905008FCC51 /* Build configuration list for PBXAggregateTarget "Version Info" */;
+                       buildPhases = (
+                               40C44ADB0E3798F4008FCC51 /* Generate Version.h */,
+                       );
+                       comments = "The generation of Version.h must be performed in its own target. Since the Info.plist is preprocessed before any of the other build phases in gtest, the Version.h file would not be ready if included as a build phase of that target.";
+                       dependencies = (
+                       );
+                       name = "Version Info";
+                       productName = Version.h;
+               };
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+               224A12A30E9EADCC00BD17FD /* gtest-test-part.h in Headers */ = {isa = PBXBuildFile; fileRef = 224A12A20E9EADCC00BD17FD /* gtest-test-part.h */; settings = {ATTRIBUTES = (Public, ); }; };
+               3BF6F2A00E79B5AD000F2EEE /* gtest-type-util.h in Copy Headers Internal */ = {isa = PBXBuildFile; fileRef = 3BF6F29F0E79B5AD000F2EEE /* gtest-type-util.h */; };
+               3BF6F2A50E79B616000F2EEE /* gtest-typed-test.h in Headers */ = {isa = PBXBuildFile; fileRef = 3BF6F2A40E79B616000F2EEE /* gtest-typed-test.h */; settings = {ATTRIBUTES = (Public, ); }; };
+               404884380E2F799B00CF7658 /* gtest-death-test.h in Headers */ = {isa = PBXBuildFile; fileRef = 404883DB0E2F799B00CF7658 /* gtest-death-test.h */; settings = {ATTRIBUTES = (Public, ); }; };
+               404884390E2F799B00CF7658 /* gtest-message.h in Headers */ = {isa = PBXBuildFile; fileRef = 404883DC0E2F799B00CF7658 /* gtest-message.h */; settings = {ATTRIBUTES = (Public, ); }; };
+               4048843A0E2F799B00CF7658 /* gtest-spi.h in Headers */ = {isa = PBXBuildFile; fileRef = 404883DD0E2F799B00CF7658 /* gtest-spi.h */; settings = {ATTRIBUTES = (Public, ); }; };
+               4048843B0E2F799B00CF7658 /* gtest.h in Headers */ = {isa = PBXBuildFile; fileRef = 404883DE0E2F799B00CF7658 /* gtest.h */; settings = {ATTRIBUTES = (Public, ); }; };
+               4048843C0E2F799B00CF7658 /* gtest_pred_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 404883DF0E2F799B00CF7658 /* gtest_pred_impl.h */; settings = {ATTRIBUTES = (Public, ); }; };
+               4048843D0E2F799B00CF7658 /* gtest_prod.h in Headers */ = {isa = PBXBuildFile; fileRef = 404883E00E2F799B00CF7658 /* gtest_prod.h */; settings = {ATTRIBUTES = (Public, ); }; };
+               404884500E2F799B00CF7658 /* README in Resources */ = {isa = PBXBuildFile; fileRef = 404883F60E2F799B00CF7658 /* README */; };
+               404884A00E2F7BE600CF7658 /* gtest-death-test-internal.h in Copy Headers Internal */ = {isa = PBXBuildFile; fileRef = 404883E20E2F799B00CF7658 /* gtest-death-test-internal.h */; };
+               404884A10E2F7BE600CF7658 /* gtest-filepath.h in Copy Headers Internal */ = {isa = PBXBuildFile; fileRef = 404883E30E2F799B00CF7658 /* gtest-filepath.h */; };
+               404884A20E2F7BE600CF7658 /* gtest-internal.h in Copy Headers Internal */ = {isa = PBXBuildFile; fileRef = 404883E40E2F799B00CF7658 /* gtest-internal.h */; };
+               404884A30E2F7BE600CF7658 /* gtest-port.h in Copy Headers Internal */ = {isa = PBXBuildFile; fileRef = 404883E50E2F799B00CF7658 /* gtest-port.h */; };
+               404884A40E2F7BE600CF7658 /* gtest-string.h in Copy Headers Internal */ = {isa = PBXBuildFile; fileRef = 404883E60E2F799B00CF7658 /* gtest-string.h */; };
+               404884AC0E2F7CD900CF7658 /* CHANGES in Resources */ = {isa = PBXBuildFile; fileRef = 404884A90E2F7CD900CF7658 /* CHANGES */; };
+               404884AD0E2F7CD900CF7658 /* CONTRIBUTORS in Resources */ = {isa = PBXBuildFile; fileRef = 404884AA0E2F7CD900CF7658 /* CONTRIBUTORS */; };
+               404884AE0E2F7CD900CF7658 /* COPYING in Resources */ = {isa = PBXBuildFile; fileRef = 404884AB0E2F7CD900CF7658 /* COPYING */; };
+               40899F3A0FFA70D4000B29AE /* gtest-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = 224A12A10E9EADA700BD17FD /* gtest-all.cc */; };
+               40899F500FFA7281000B29AE /* gtest-tuple.h in Copy Headers Internal */ = {isa = PBXBuildFile; fileRef = 40899F4D0FFA7271000B29AE /* gtest-tuple.h */; };
+               40899F530FFA72A0000B29AE /* gtest_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3B238C120E7FE13C00846E11 /* gtest_unittest.cc */; };
+               4089A0440FFAD1BE000B29AE /* sample1.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4089A02C0FFACF7F000B29AE /* sample1.cc */; };
+               4089A0460FFAD1BE000B29AE /* sample1_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4089A02E0FFACF7F000B29AE /* sample1_unittest.cc */; };
+               40C848FF101A21150083642A /* gtest-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = 224A12A10E9EADA700BD17FD /* gtest-all.cc */; };
+               40C84915101A21DF0083642A /* gtest_main.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4048840D0E2F799B00CF7658 /* gtest_main.cc */; };
+               40C84916101A235B0083642A /* libgtest_main.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 40C8490B101A217E0083642A /* libgtest_main.a */; };
+               40C84921101A23AD0083642A /* libgtest_main.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 40C8490B101A217E0083642A /* libgtest_main.a */; };
+               40C84978101A36540083642A /* libgtest_main.a in Resources */ = {isa = PBXBuildFile; fileRef = 40C8490B101A217E0083642A /* libgtest_main.a */; };
+               40C84980101A36850083642A /* gtest_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3B238C120E7FE13C00846E11 /* gtest_unittest.cc */; };
+               40C84982101A36850083642A /* libgtest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 40C848FA101A209C0083642A /* libgtest.a */; };
+               40C84983101A36850083642A /* libgtest_main.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 40C8490B101A217E0083642A /* libgtest_main.a */; };
+               40C8498F101A36A60083642A /* sample1.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4089A02C0FFACF7F000B29AE /* sample1.cc */; };
+               40C84990101A36A60083642A /* sample1_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4089A02E0FFACF7F000B29AE /* sample1_unittest.cc */; };
+               40C84992101A36A60083642A /* libgtest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 40C848FA101A209C0083642A /* libgtest.a */; };
+               40C84993101A36A60083642A /* libgtest_main.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 40C8490B101A217E0083642A /* libgtest_main.a */; };
+               40C849A2101A37050083642A /* gtest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4539C8FF0EC27F6400A70F4C /* gtest.framework */; };
+               40C849A4101A37150083642A /* gtest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4539C8FF0EC27F6400A70F4C /* gtest.framework */; };
+               4539C9340EC280AE00A70F4C /* gtest-param-test.h in Headers */ = {isa = PBXBuildFile; fileRef = 4539C9330EC280AE00A70F4C /* gtest-param-test.h */; settings = {ATTRIBUTES = (Public, ); }; };
+               4539C9380EC280E200A70F4C /* gtest-linked_ptr.h in Copy Headers Internal */ = {isa = PBXBuildFile; fileRef = 4539C9350EC280E200A70F4C /* gtest-linked_ptr.h */; };
+               4539C9390EC280E200A70F4C /* gtest-param-util-generated.h in Copy Headers Internal */ = {isa = PBXBuildFile; fileRef = 4539C9360EC280E200A70F4C /* gtest-param-util-generated.h */; };
+               4539C93A0EC280E200A70F4C /* gtest-param-util.h in Copy Headers Internal */ = {isa = PBXBuildFile; fileRef = 4539C9370EC280E200A70F4C /* gtest-param-util.h */; };
+               4567C8181264FF71007740BE /* gtest-printers.h in Headers */ = {isa = PBXBuildFile; fileRef = 4567C8171264FF71007740BE /* gtest-printers.h */; settings = {ATTRIBUTES = (Public, ); }; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+               40899F9C0FFA740F000B29AE /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 40899F420FFA7184000B29AE;
+                       remoteInfo = gtest_unittest;
+               };
+               4089A0970FFAD34A000B29AE /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 4089A0120FFACEFC000B29AE;
+                       remoteInfo = sample1_unittest;
+               };
+               408BEC0F1046CFE900DEF522 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 40C848F9101A209C0083642A;
+                       remoteInfo = "gtest-static";
+               };
+               40C44AE50E379922008FCC51 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 40C44ADC0E3798F4008FCC51;
+                       remoteInfo = Version.h;
+               };
+               40C8497C101A36850083642A /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 40C848F9101A209C0083642A;
+                       remoteInfo = "gtest-static";
+               };
+               40C8497E101A36850083642A /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 40C8490A101A217E0083642A;
+                       remoteInfo = "gtest_main-static";
+               };
+               40C8498B101A36A60083642A /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 40C848F9101A209C0083642A;
+                       remoteInfo = "gtest-static";
+               };
+               40C8498D101A36A60083642A /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 40C8490A101A217E0083642A;
+                       remoteInfo = "gtest_main-static";
+               };
+               40C8499B101A36DC0083642A /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 40C8490A101A217E0083642A;
+                       remoteInfo = "gtest_main-static";
+               };
+               40C8499D101A36E50083642A /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 8D07F2BC0486CC7A007CD1D0;
+                       remoteInfo = "gtest-framework";
+               };
+               40C8499F101A36F10083642A /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 8D07F2BC0486CC7A007CD1D0;
+                       remoteInfo = "gtest-framework";
+               };
+               40C849F6101A43440083642A /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 40C8497A101A36850083642A;
+                       remoteInfo = "gtest_unittest-static";
+               };
+               40C849F8101A43490083642A /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 40C84989101A36A60083642A;
+                       remoteInfo = "sample1_unittest-static";
+               };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+               404884A50E2F7C0400CF7658 /* Copy Headers Internal */ = {
+                       isa = PBXCopyFilesBuildPhase;
+                       buildActionMask = 2147483647;
+                       dstPath = Headers/internal;
+                       dstSubfolderSpec = 6;
+                       files = (
+                               404884A00E2F7BE600CF7658 /* gtest-death-test-internal.h in Copy Headers Internal */,
+                               404884A10E2F7BE600CF7658 /* gtest-filepath.h in Copy Headers Internal */,
+                               404884A20E2F7BE600CF7658 /* gtest-internal.h in Copy Headers Internal */,
+                               4539C9380EC280E200A70F4C /* gtest-linked_ptr.h in Copy Headers Internal */,
+                               4539C9390EC280E200A70F4C /* gtest-param-util-generated.h in Copy Headers Internal */,
+                               4539C93A0EC280E200A70F4C /* gtest-param-util.h in Copy Headers Internal */,
+                               404884A30E2F7BE600CF7658 /* gtest-port.h in Copy Headers Internal */,
+                               404884A40E2F7BE600CF7658 /* gtest-string.h in Copy Headers Internal */,
+                               40899F500FFA7281000B29AE /* gtest-tuple.h in Copy Headers Internal */,
+                               3BF6F2A00E79B5AD000F2EEE /* gtest-type-util.h in Copy Headers Internal */,
+                       );
+                       name = "Copy Headers Internal";
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+               224A12A10E9EADA700BD17FD /* gtest-all.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = "gtest-all.cc"; sourceTree = "<group>"; };
+               224A12A20E9EADCC00BD17FD /* gtest-test-part.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "gtest-test-part.h"; sourceTree = "<group>"; };
+               3B238C120E7FE13C00846E11 /* gtest_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gtest_unittest.cc; sourceTree = "<group>"; };
+               3B87D2100E96B92E000D1852 /* runtests.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = runtests.sh; sourceTree = "<group>"; };
+               3BF6F29F0E79B5AD000F2EEE /* gtest-type-util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-type-util.h"; sourceTree = "<group>"; };
+               3BF6F2A40E79B616000F2EEE /* gtest-typed-test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-typed-test.h"; sourceTree = "<group>"; };
+               403EE37C0E377822004BD1E2 /* versiongenerate.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = versiongenerate.py; sourceTree = "<group>"; };
+               404883DB0E2F799B00CF7658 /* gtest-death-test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-death-test.h"; sourceTree = "<group>"; };
+               404883DC0E2F799B00CF7658 /* gtest-message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-message.h"; sourceTree = "<group>"; };
+               404883DD0E2F799B00CF7658 /* gtest-spi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-spi.h"; sourceTree = "<group>"; };
+               404883DE0E2F799B00CF7658 /* gtest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gtest.h; sourceTree = "<group>"; };
+               404883DF0E2F799B00CF7658 /* gtest_pred_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gtest_pred_impl.h; sourceTree = "<group>"; };
+               404883E00E2F799B00CF7658 /* gtest_prod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gtest_prod.h; sourceTree = "<group>"; };
+               404883E20E2F799B00CF7658 /* gtest-death-test-internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-death-test-internal.h"; sourceTree = "<group>"; };
+               404883E30E2F799B00CF7658 /* gtest-filepath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-filepath.h"; sourceTree = "<group>"; };
+               404883E40E2F799B00CF7658 /* gtest-internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-internal.h"; sourceTree = "<group>"; };
+               404883E50E2F799B00CF7658 /* gtest-port.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-port.h"; sourceTree = "<group>"; };
+               404883E60E2F799B00CF7658 /* gtest-string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-string.h"; sourceTree = "<group>"; };
+               404883F60E2F799B00CF7658 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README; path = ../README; sourceTree = SOURCE_ROOT; };
+               4048840D0E2F799B00CF7658 /* gtest_main.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gtest_main.cc; sourceTree = "<group>"; };
+               404884A90E2F7CD900CF7658 /* CHANGES */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = CHANGES; path = ../CHANGES; sourceTree = SOURCE_ROOT; };
+               404884AA0E2F7CD900CF7658 /* CONTRIBUTORS */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = CONTRIBUTORS; path = ../CONTRIBUTORS; sourceTree = SOURCE_ROOT; };
+               404884AB0E2F7CD900CF7658 /* COPYING */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = COPYING; path = ../COPYING; sourceTree = SOURCE_ROOT; };
+               40899F430FFA7184000B29AE /* gtest_unittest-framework */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "gtest_unittest-framework"; sourceTree = BUILT_PRODUCTS_DIR; };
+               40899F4D0FFA7271000B29AE /* gtest-tuple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-tuple.h"; sourceTree = "<group>"; };
+               40899FB30FFA7567000B29AE /* StaticLibraryTarget.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = StaticLibraryTarget.xcconfig; sourceTree = "<group>"; };
+               4089A0130FFACEFC000B29AE /* sample1_unittest-framework */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "sample1_unittest-framework"; sourceTree = BUILT_PRODUCTS_DIR; };
+               4089A02C0FFACF7F000B29AE /* sample1.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sample1.cc; sourceTree = "<group>"; };
+               4089A02D0FFACF7F000B29AE /* sample1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sample1.h; sourceTree = "<group>"; };
+               4089A02E0FFACF7F000B29AE /* sample1_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sample1_unittest.cc; sourceTree = "<group>"; };
+               40C848FA101A209C0083642A /* libgtest.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libgtest.a; sourceTree = BUILT_PRODUCTS_DIR; };
+               40C8490B101A217E0083642A /* libgtest_main.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libgtest_main.a; sourceTree = BUILT_PRODUCTS_DIR; };
+               40C84987101A36850083642A /* gtest_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = gtest_unittest; sourceTree = BUILT_PRODUCTS_DIR; };
+               40C84997101A36A60083642A /* sample1_unittest-static */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "sample1_unittest-static"; sourceTree = BUILT_PRODUCTS_DIR; };
+               40D4CDF10E30E07400294801 /* DebugProject.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DebugProject.xcconfig; sourceTree = "<group>"; };
+               40D4CDF20E30E07400294801 /* FrameworkTarget.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = FrameworkTarget.xcconfig; sourceTree = "<group>"; };
+               40D4CDF30E30E07400294801 /* General.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = General.xcconfig; sourceTree = "<group>"; };
+               40D4CDF40E30E07400294801 /* ReleaseProject.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ReleaseProject.xcconfig; sourceTree = "<group>"; };
+               40D4CF510E30F5E200294801 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+               4539C8FF0EC27F6400A70F4C /* gtest.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = gtest.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+               4539C9330EC280AE00A70F4C /* gtest-param-test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-param-test.h"; sourceTree = "<group>"; };
+               4539C9350EC280E200A70F4C /* gtest-linked_ptr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-linked_ptr.h"; sourceTree = "<group>"; };
+               4539C9360EC280E200A70F4C /* gtest-param-util-generated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-param-util-generated.h"; sourceTree = "<group>"; };
+               4539C9370EC280E200A70F4C /* gtest-param-util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-param-util.h"; sourceTree = "<group>"; };
+               4567C8171264FF71007740BE /* gtest-printers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "gtest-printers.h"; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+               40899F410FFA7184000B29AE /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               40C849A4101A37150083642A /* gtest.framework in Frameworks */,
+                               40C84916101A235B0083642A /* libgtest_main.a in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               4089A0110FFACEFC000B29AE /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               40C849A2101A37050083642A /* gtest.framework in Frameworks */,
+                               40C84921101A23AD0083642A /* libgtest_main.a in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               40C84981101A36850083642A /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               40C84982101A36850083642A /* libgtest.a in Frameworks */,
+                               40C84983101A36850083642A /* libgtest_main.a in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               40C84991101A36A60083642A /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               40C84992101A36A60083642A /* libgtest.a in Frameworks */,
+                               40C84993101A36A60083642A /* libgtest_main.a in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+               034768DDFF38A45A11DB9C8B /* Products */ = {
+                       isa = PBXGroup;
+                       children = (
+                               4539C8FF0EC27F6400A70F4C /* gtest.framework */,
+                               40C848FA101A209C0083642A /* libgtest.a */,
+                               40C8490B101A217E0083642A /* libgtest_main.a */,
+                               40899F430FFA7184000B29AE /* gtest_unittest-framework */,
+                               40C84987101A36850083642A /* gtest_unittest */,
+                               4089A0130FFACEFC000B29AE /* sample1_unittest-framework */,
+                               40C84997101A36A60083642A /* sample1_unittest-static */,
+                       );
+                       name = Products;
+                       sourceTree = "<group>";
+               };
+               0867D691FE84028FC02AAC07 /* gtest */ = {
+                       isa = PBXGroup;
+                       children = (
+                               40D4CDF00E30E07400294801 /* Config */,
+                               08FB77ACFE841707C02AAC07 /* Source */,
+                               40D4CF4E0E30F5E200294801 /* Resources */,
+                               403EE37B0E377822004BD1E2 /* Scripts */,
+                               034768DDFF38A45A11DB9C8B /* Products */,
+                       );
+                       name = gtest;
+                       sourceTree = "<group>";
+               };
+               08FB77ACFE841707C02AAC07 /* Source */ = {
+                       isa = PBXGroup;
+                       children = (
+                               404884A90E2F7CD900CF7658 /* CHANGES */,
+                               404884AA0E2F7CD900CF7658 /* CONTRIBUTORS */,
+                               404884AB0E2F7CD900CF7658 /* COPYING */,
+                               404883F60E2F799B00CF7658 /* README */,
+                               404883D90E2F799B00CF7658 /* include */,
+                               4089A02F0FFACF84000B29AE /* samples */,
+                               404884070E2F799B00CF7658 /* src */,
+                               3B238BF00E7FE13B00846E11 /* test */,
+                       );
+                       name = Source;
+                       sourceTree = "<group>";
+               };
+               3B238BF00E7FE13B00846E11 /* test */ = {
+                       isa = PBXGroup;
+                       children = (
+                               3B238C120E7FE13C00846E11 /* gtest_unittest.cc */,
+                       );
+                       name = test;
+                       path = ../test;
+                       sourceTree = SOURCE_ROOT;
+               };
+               403EE37B0E377822004BD1E2 /* Scripts */ = {
+                       isa = PBXGroup;
+                       children = (
+                               403EE37C0E377822004BD1E2 /* versiongenerate.py */,
+                               3B87D2100E96B92E000D1852 /* runtests.sh */,
+                       );
+                       path = Scripts;
+                       sourceTree = "<group>";
+               };
+               404883D90E2F799B00CF7658 /* include */ = {
+                       isa = PBXGroup;
+                       children = (
+                               404883DA0E2F799B00CF7658 /* gtest */,
+                       );
+                       name = include;
+                       path = ../include;
+                       sourceTree = SOURCE_ROOT;
+               };
+               404883DA0E2F799B00CF7658 /* gtest */ = {
+                       isa = PBXGroup;
+                       children = (
+                               404883E10E2F799B00CF7658 /* internal */,
+                               224A12A20E9EADCC00BD17FD /* gtest-test-part.h */,
+                               404883DB0E2F799B00CF7658 /* gtest-death-test.h */,
+                               404883DC0E2F799B00CF7658 /* gtest-message.h */,
+                               4539C9330EC280AE00A70F4C /* gtest-param-test.h */,
+                               4567C8171264FF71007740BE /* gtest-printers.h */,
+                               404883DD0E2F799B00CF7658 /* gtest-spi.h */,
+                               404883DE0E2F799B00CF7658 /* gtest.h */,
+                               404883DF0E2F799B00CF7658 /* gtest_pred_impl.h */,
+                               404883E00E2F799B00CF7658 /* gtest_prod.h */,
+                               3BF6F2A40E79B616000F2EEE /* gtest-typed-test.h */,
+                       );
+                       path = gtest;
+                       sourceTree = "<group>";
+               };
+               404883E10E2F799B00CF7658 /* internal */ = {
+                       isa = PBXGroup;
+                       children = (
+                               404883E20E2F799B00CF7658 /* gtest-death-test-internal.h */,
+                               404883E30E2F799B00CF7658 /* gtest-filepath.h */,
+                               404883E40E2F799B00CF7658 /* gtest-internal.h */,
+                               4539C9350EC280E200A70F4C /* gtest-linked_ptr.h */,
+                               4539C9360EC280E200A70F4C /* gtest-param-util-generated.h */,
+                               4539C9370EC280E200A70F4C /* gtest-param-util.h */,
+                               404883E50E2F799B00CF7658 /* gtest-port.h */,
+                               404883E60E2F799B00CF7658 /* gtest-string.h */,
+                               40899F4D0FFA7271000B29AE /* gtest-tuple.h */,
+                               3BF6F29F0E79B5AD000F2EEE /* gtest-type-util.h */,
+                       );
+                       path = internal;
+                       sourceTree = "<group>";
+               };
+               404884070E2F799B00CF7658 /* src */ = {
+                       isa = PBXGroup;
+                       children = (
+                               224A12A10E9EADA700BD17FD /* gtest-all.cc */,
+                               4048840D0E2F799B00CF7658 /* gtest_main.cc */,
+                       );
+                       name = src;
+                       path = ../src;
+                       sourceTree = SOURCE_ROOT;
+               };
+               4089A02F0FFACF84000B29AE /* samples */ = {
+                       isa = PBXGroup;
+                       children = (
+                               4089A02C0FFACF7F000B29AE /* sample1.cc */,
+                               4089A02D0FFACF7F000B29AE /* sample1.h */,
+                               4089A02E0FFACF7F000B29AE /* sample1_unittest.cc */,
+                       );
+                       name = samples;
+                       path = ../samples;
+                       sourceTree = SOURCE_ROOT;
+               };
+               40D4CDF00E30E07400294801 /* Config */ = {
+                       isa = PBXGroup;
+                       children = (
+                               40D4CDF10E30E07400294801 /* DebugProject.xcconfig */,
+                               40D4CDF20E30E07400294801 /* FrameworkTarget.xcconfig */,
+                               40D4CDF30E30E07400294801 /* General.xcconfig */,
+                               40D4CDF40E30E07400294801 /* ReleaseProject.xcconfig */,
+                               40899FB30FFA7567000B29AE /* StaticLibraryTarget.xcconfig */,
+                       );
+                       path = Config;
+                       sourceTree = "<group>";
+               };
+               40D4CF4E0E30F5E200294801 /* Resources */ = {
+                       isa = PBXGroup;
+                       children = (
+                               40D4CF510E30F5E200294801 /* Info.plist */,
+                       );
+                       path = Resources;
+                       sourceTree = "<group>";
+               };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+               8D07F2BD0486CC7A007CD1D0 /* Headers */ = {
+                       isa = PBXHeadersBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               404884380E2F799B00CF7658 /* gtest-death-test.h in Headers */,
+                               404884390E2F799B00CF7658 /* gtest-message.h in Headers */,
+                               4539C9340EC280AE00A70F4C /* gtest-param-test.h in Headers */,
+                               4567C8181264FF71007740BE /* gtest-printers.h in Headers */,
+                               3BF6F2A50E79B616000F2EEE /* gtest-typed-test.h in Headers */,
+                               4048843A0E2F799B00CF7658 /* gtest-spi.h in Headers */,
+                               4048843B0E2F799B00CF7658 /* gtest.h in Headers */,
+                               4048843C0E2F799B00CF7658 /* gtest_pred_impl.h in Headers */,
+                               4048843D0E2F799B00CF7658 /* gtest_prod.h in Headers */,
+                               224A12A30E9EADCC00BD17FD /* gtest-test-part.h in Headers */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+               40899F420FFA7184000B29AE /* gtest_unittest-framework */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 40899F4A0FFA71BC000B29AE /* Build configuration list for PBXNativeTarget "gtest_unittest-framework" */;
+                       buildPhases = (
+                               40899F400FFA7184000B29AE /* Sources */,
+                               40899F410FFA7184000B29AE /* Frameworks */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               40C849A0101A36F10083642A /* PBXTargetDependency */,
+                       );
+                       name = "gtest_unittest-framework";
+                       productName = gtest_unittest;
+                       productReference = 40899F430FFA7184000B29AE /* gtest_unittest-framework */;
+                       productType = "com.apple.product-type.tool";
+               };
+               4089A0120FFACEFC000B29AE /* sample1_unittest-framework */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 4089A0240FFACF01000B29AE /* Build configuration list for PBXNativeTarget "sample1_unittest-framework" */;
+                       buildPhases = (
+                               4089A0100FFACEFC000B29AE /* Sources */,
+                               4089A0110FFACEFC000B29AE /* Frameworks */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               40C8499E101A36E50083642A /* PBXTargetDependency */,
+                       );
+                       name = "sample1_unittest-framework";
+                       productName = sample1_unittest;
+                       productReference = 4089A0130FFACEFC000B29AE /* sample1_unittest-framework */;
+                       productType = "com.apple.product-type.tool";
+               };
+               40C848F9101A209C0083642A /* gtest-static */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 40C84902101A212E0083642A /* Build configuration list for PBXNativeTarget "gtest-static" */;
+                       buildPhases = (
+                               40C848F7101A209C0083642A /* Sources */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                       );
+                       name = "gtest-static";
+                       productName = "gtest-static";
+                       productReference = 40C848FA101A209C0083642A /* libgtest.a */;
+                       productType = "com.apple.product-type.library.static";
+               };
+               40C8490A101A217E0083642A /* gtest_main-static */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 40C84912101A21D20083642A /* Build configuration list for PBXNativeTarget "gtest_main-static" */;
+                       buildPhases = (
+                               40C84908101A217E0083642A /* Sources */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                       );
+                       name = "gtest_main-static";
+                       productName = "gtest_main-static";
+                       productReference = 40C8490B101A217E0083642A /* libgtest_main.a */;
+                       productType = "com.apple.product-type.library.static";
+               };
+               40C8497A101A36850083642A /* gtest_unittest-static */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 40C84984101A36850083642A /* Build configuration list for PBXNativeTarget "gtest_unittest-static" */;
+                       buildPhases = (
+                               40C8497F101A36850083642A /* Sources */,
+                               40C84981101A36850083642A /* Frameworks */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               40C8497B101A36850083642A /* PBXTargetDependency */,
+                               40C8497D101A36850083642A /* PBXTargetDependency */,
+                       );
+                       name = "gtest_unittest-static";
+                       productName = gtest_unittest;
+                       productReference = 40C84987101A36850083642A /* gtest_unittest */;
+                       productType = "com.apple.product-type.tool";
+               };
+               40C84989101A36A60083642A /* sample1_unittest-static */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 40C84994101A36A60083642A /* Build configuration list for PBXNativeTarget "sample1_unittest-static" */;
+                       buildPhases = (
+                               40C8498E101A36A60083642A /* Sources */,
+                               40C84991101A36A60083642A /* Frameworks */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               40C8498A101A36A60083642A /* PBXTargetDependency */,
+                               40C8498C101A36A60083642A /* PBXTargetDependency */,
+                       );
+                       name = "sample1_unittest-static";
+                       productName = sample1_unittest;
+                       productReference = 40C84997101A36A60083642A /* sample1_unittest-static */;
+                       productType = "com.apple.product-type.tool";
+               };
+               8D07F2BC0486CC7A007CD1D0 /* gtest-framework */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 4FADC24208B4156D00ABE55E /* Build configuration list for PBXNativeTarget "gtest-framework" */;
+                       buildPhases = (
+                               8D07F2C10486CC7A007CD1D0 /* Sources */,
+                               8D07F2BD0486CC7A007CD1D0 /* Headers */,
+                               404884A50E2F7C0400CF7658 /* Copy Headers Internal */,
+                               8D07F2BF0486CC7A007CD1D0 /* Resources */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               40C44AE60E379922008FCC51 /* PBXTargetDependency */,
+                               408BEC101046CFE900DEF522 /* PBXTargetDependency */,
+                               40C8499C101A36DC0083642A /* PBXTargetDependency */,
+                       );
+                       name = "gtest-framework";
+                       productInstallPath = "$(HOME)/Library/Frameworks";
+                       productName = gtest;
+                       productReference = 4539C8FF0EC27F6400A70F4C /* gtest.framework */;
+                       productType = "com.apple.product-type.framework";
+               };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+               0867D690FE84028FC02AAC07 /* Project object */ = {
+                       isa = PBXProject;
+                       buildConfigurationList = 4FADC24608B4156D00ABE55E /* Build configuration list for PBXProject "gtest" */;
+                       compatibilityVersion = "Xcode 2.4";
+                       hasScannedForEncodings = 1;
+                       knownRegions = (
+                               English,
+                               Japanese,
+                               French,
+                               German,
+                               en,
+                       );
+                       mainGroup = 0867D691FE84028FC02AAC07 /* gtest */;
+                       productRefGroup = 034768DDFF38A45A11DB9C8B /* Products */;
+                       projectDirPath = "";
+                       projectRoot = "";
+                       targets = (
+                               8D07F2BC0486CC7A007CD1D0 /* gtest-framework */,
+                               40C848F9101A209C0083642A /* gtest-static */,
+                               40C8490A101A217E0083642A /* gtest_main-static */,
+                               40899F420FFA7184000B29AE /* gtest_unittest-framework */,
+                               40C8497A101A36850083642A /* gtest_unittest-static */,
+                               4089A0120FFACEFC000B29AE /* sample1_unittest-framework */,
+                               40C84989101A36A60083642A /* sample1_unittest-static */,
+                               3B238F5F0E828B5400846E11 /* Check */,
+                               40C44ADC0E3798F4008FCC51 /* Version Info */,
+                       );
+               };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+               8D07F2BF0486CC7A007CD1D0 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               404884500E2F799B00CF7658 /* README in Resources */,
+                               404884AC0E2F7CD900CF7658 /* CHANGES in Resources */,
+                               404884AD0E2F7CD900CF7658 /* CONTRIBUTORS in Resources */,
+                               404884AE0E2F7CD900CF7658 /* COPYING in Resources */,
+                               40C84978101A36540083642A /* libgtest_main.a in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+               3B238F5E0E828B5400846E11 /* ShellScript */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "# Remember, this \"Run Script\" build phase will be executed from $SRCROOT\n/bin/bash Scripts/runtests.sh";
+               };
+               40C44ADB0E3798F4008FCC51 /* Generate Version.h */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "$(SRCROOT)/Scripts/versiongenerate.py",
+                               "$(SRCROOT)/../configure.ac",
+                       );
+                       name = "Generate Version.h";
+                       outputPaths = (
+                               "$(PROJECT_TEMP_DIR)/Version.h",
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "# Remember, this \"Run Script\" build phase will be executed from $SRCROOT\n/usr/bin/python Scripts/versiongenerate.py ../ $PROJECT_TEMP_DIR";
+               };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+               40899F400FFA7184000B29AE /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               40899F530FFA72A0000B29AE /* gtest_unittest.cc in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               4089A0100FFACEFC000B29AE /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               4089A0440FFAD1BE000B29AE /* sample1.cc in Sources */,
+                               4089A0460FFAD1BE000B29AE /* sample1_unittest.cc in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               40C848F7101A209C0083642A /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               40C848FF101A21150083642A /* gtest-all.cc in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               40C84908101A217E0083642A /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               40C84915101A21DF0083642A /* gtest_main.cc in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               40C8497F101A36850083642A /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               40C84980101A36850083642A /* gtest_unittest.cc in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               40C8498E101A36A60083642A /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               40C8498F101A36A60083642A /* sample1.cc in Sources */,
+                               40C84990101A36A60083642A /* sample1_unittest.cc in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               8D07F2C10486CC7A007CD1D0 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               40899F3A0FFA70D4000B29AE /* gtest-all.cc in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+               40899F9D0FFA740F000B29AE /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 40899F420FFA7184000B29AE /* gtest_unittest-framework */;
+                       targetProxy = 40899F9C0FFA740F000B29AE /* PBXContainerItemProxy */;
+               };
+               4089A0980FFAD34A000B29AE /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 4089A0120FFACEFC000B29AE /* sample1_unittest-framework */;
+                       targetProxy = 4089A0970FFAD34A000B29AE /* PBXContainerItemProxy */;
+               };
+               408BEC101046CFE900DEF522 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 40C848F9101A209C0083642A /* gtest-static */;
+                       targetProxy = 408BEC0F1046CFE900DEF522 /* PBXContainerItemProxy */;
+               };
+               40C44AE60E379922008FCC51 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 40C44ADC0E3798F4008FCC51 /* Version Info */;
+                       targetProxy = 40C44AE50E379922008FCC51 /* PBXContainerItemProxy */;
+               };
+               40C8497B101A36850083642A /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 40C848F9101A209C0083642A /* gtest-static */;
+                       targetProxy = 40C8497C101A36850083642A /* PBXContainerItemProxy */;
+               };
+               40C8497D101A36850083642A /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 40C8490A101A217E0083642A /* gtest_main-static */;
+                       targetProxy = 40C8497E101A36850083642A /* PBXContainerItemProxy */;
+               };
+               40C8498A101A36A60083642A /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 40C848F9101A209C0083642A /* gtest-static */;
+                       targetProxy = 40C8498B101A36A60083642A /* PBXContainerItemProxy */;
+               };
+               40C8498C101A36A60083642A /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 40C8490A101A217E0083642A /* gtest_main-static */;
+                       targetProxy = 40C8498D101A36A60083642A /* PBXContainerItemProxy */;
+               };
+               40C8499C101A36DC0083642A /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 40C8490A101A217E0083642A /* gtest_main-static */;
+                       targetProxy = 40C8499B101A36DC0083642A /* PBXContainerItemProxy */;
+               };
+               40C8499E101A36E50083642A /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 8D07F2BC0486CC7A007CD1D0 /* gtest-framework */;
+                       targetProxy = 40C8499D101A36E50083642A /* PBXContainerItemProxy */;
+               };
+               40C849A0101A36F10083642A /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 8D07F2BC0486CC7A007CD1D0 /* gtest-framework */;
+                       targetProxy = 40C8499F101A36F10083642A /* PBXContainerItemProxy */;
+               };
+               40C849F7101A43440083642A /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 40C8497A101A36850083642A /* gtest_unittest-static */;
+                       targetProxy = 40C849F6101A43440083642A /* PBXContainerItemProxy */;
+               };
+               40C849F9101A43490083642A /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 40C84989101A36A60083642A /* sample1_unittest-static */;
+                       targetProxy = 40C849F8101A43490083642A /* PBXContainerItemProxy */;
+               };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+               3B238F600E828B5400846E11 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               COPY_PHASE_STRIP = NO;
+                               GCC_DYNAMIC_NO_PIC = NO;
+                               GCC_OPTIMIZATION_LEVEL = 0;
+                               PRODUCT_NAME = Check;
+                       };
+                       name = Debug;
+               };
+               3B238F610E828B5400846E11 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               COPY_PHASE_STRIP = YES;
+                               DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+                               GCC_ENABLE_FIX_AND_CONTINUE = NO;
+                               PRODUCT_NAME = Check;
+                               ZERO_LINK = NO;
+                       };
+                       name = Release;
+               };
+               40899F450FFA7185000B29AE /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               HEADER_SEARCH_PATHS = ../;
+                               PRODUCT_NAME = "gtest_unittest-framework";
+                       };
+                       name = Debug;
+               };
+               40899F460FFA7185000B29AE /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               HEADER_SEARCH_PATHS = ../;
+                               PRODUCT_NAME = "gtest_unittest-framework";
+                       };
+                       name = Release;
+               };
+               4089A0150FFACEFD000B29AE /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = "sample1_unittest-framework";
+                       };
+                       name = Debug;
+               };
+               4089A0160FFACEFD000B29AE /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = "sample1_unittest-framework";
+                       };
+                       name = Release;
+               };
+               40C44ADF0E3798F4008FCC51 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = gtest;
+                               TARGET_NAME = gtest;
+                       };
+                       name = Debug;
+               };
+               40C44AE00E3798F4008FCC51 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = gtest;
+                               TARGET_NAME = gtest;
+                       };
+                       name = Release;
+               };
+               40C848FB101A209D0083642A /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 40899FB30FFA7567000B29AE /* StaticLibraryTarget.xcconfig */;
+                       buildSettings = {
+                               GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
+                               GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+                               HEADER_SEARCH_PATHS = (
+                                       ../,
+                                       ../include/,
+                               );
+                               PRODUCT_NAME = gtest;
+                       };
+                       name = Debug;
+               };
+               40C848FC101A209D0083642A /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 40899FB30FFA7567000B29AE /* StaticLibraryTarget.xcconfig */;
+                       buildSettings = {
+                               GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
+                               GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+                               HEADER_SEARCH_PATHS = (
+                                       ../,
+                                       ../include/,
+                               );
+                               PRODUCT_NAME = gtest;
+                       };
+                       name = Release;
+               };
+               40C8490E101A217F0083642A /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 40899FB30FFA7567000B29AE /* StaticLibraryTarget.xcconfig */;
+                       buildSettings = {
+                               HEADER_SEARCH_PATHS = (
+                                       ../,
+                                       ../include/,
+                               );
+                               PRODUCT_NAME = gtest_main;
+                       };
+                       name = Debug;
+               };
+               40C8490F101A217F0083642A /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 40899FB30FFA7567000B29AE /* StaticLibraryTarget.xcconfig */;
+                       buildSettings = {
+                               HEADER_SEARCH_PATHS = (
+                                       ../,
+                                       ../include/,
+                               );
+                               PRODUCT_NAME = gtest_main;
+                       };
+                       name = Release;
+               };
+               40C84985101A36850083642A /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               HEADER_SEARCH_PATHS = ../;
+                               PRODUCT_NAME = gtest_unittest;
+                       };
+                       name = Debug;
+               };
+               40C84986101A36850083642A /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               HEADER_SEARCH_PATHS = ../;
+                               PRODUCT_NAME = gtest_unittest;
+                       };
+                       name = Release;
+               };
+               40C84995101A36A60083642A /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = "sample1_unittest-static";
+                       };
+                       name = Debug;
+               };
+               40C84996101A36A60083642A /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = "sample1_unittest-static";
+                       };
+                       name = Release;
+               };
+               4FADC24308B4156D00ABE55E /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 40D4CDF20E30E07400294801 /* FrameworkTarget.xcconfig */;
+                       buildSettings = {
+                               DYLIB_COMPATIBILITY_VERSION = 1;
+                               DYLIB_CURRENT_VERSION = 1;
+                               HEADER_SEARCH_PATHS = (
+                                       ../,
+                                       ../include/,
+                               );
+                               INFOPLIST_FILE = Resources/Info.plist;
+                               INFOPLIST_PREFIX_HEADER = "$(PROJECT_TEMP_DIR)/Version.h";
+                               INFOPLIST_PREPROCESS = YES;
+                               PRODUCT_NAME = gtest;
+                               VERSIONING_SYSTEM = "apple-generic";
+                       };
+                       name = Debug;
+               };
+               4FADC24408B4156D00ABE55E /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 40D4CDF20E30E07400294801 /* FrameworkTarget.xcconfig */;
+                       buildSettings = {
+                               DYLIB_COMPATIBILITY_VERSION = 1;
+                               DYLIB_CURRENT_VERSION = 1;
+                               HEADER_SEARCH_PATHS = (
+                                       ../,
+                                       ../include/,
+                               );
+                               INFOPLIST_FILE = Resources/Info.plist;
+                               INFOPLIST_PREFIX_HEADER = "$(PROJECT_TEMP_DIR)/Version.h";
+                               INFOPLIST_PREPROCESS = YES;
+                               PRODUCT_NAME = gtest;
+                               VERSIONING_SYSTEM = "apple-generic";
+                       };
+                       name = Release;
+               };
+               4FADC24708B4156D00ABE55E /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 40D4CDF10E30E07400294801 /* DebugProject.xcconfig */;
+                       buildSettings = {
+                       };
+                       name = Debug;
+               };
+               4FADC24808B4156D00ABE55E /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 40D4CDF40E30E07400294801 /* ReleaseProject.xcconfig */;
+                       buildSettings = {
+                       };
+                       name = Release;
+               };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+               3B238FA30E828BB600846E11 /* Build configuration list for PBXAggregateTarget "Check" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               3B238F600E828B5400846E11 /* Debug */,
+                               3B238F610E828B5400846E11 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               40899F4A0FFA71BC000B29AE /* Build configuration list for PBXNativeTarget "gtest_unittest-framework" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               40899F450FFA7185000B29AE /* Debug */,
+                               40899F460FFA7185000B29AE /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               4089A0240FFACF01000B29AE /* Build configuration list for PBXNativeTarget "sample1_unittest-framework" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               4089A0150FFACEFD000B29AE /* Debug */,
+                               4089A0160FFACEFD000B29AE /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               40C44AE40E379905008FCC51 /* Build configuration list for PBXAggregateTarget "Version Info" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               40C44ADF0E3798F4008FCC51 /* Debug */,
+                               40C44AE00E3798F4008FCC51 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               40C84902101A212E0083642A /* Build configuration list for PBXNativeTarget "gtest-static" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               40C848FB101A209D0083642A /* Debug */,
+                               40C848FC101A209D0083642A /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               40C84912101A21D20083642A /* Build configuration list for PBXNativeTarget "gtest_main-static" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               40C8490E101A217F0083642A /* Debug */,
+                               40C8490F101A217F0083642A /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               40C84984101A36850083642A /* Build configuration list for PBXNativeTarget "gtest_unittest-static" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               40C84985101A36850083642A /* Debug */,
+                               40C84986101A36850083642A /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               40C84994101A36A60083642A /* Build configuration list for PBXNativeTarget "sample1_unittest-static" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               40C84995101A36A60083642A /* Debug */,
+                               40C84996101A36A60083642A /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               4FADC24208B4156D00ABE55E /* Build configuration list for PBXNativeTarget "gtest-framework" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               4FADC24308B4156D00ABE55E /* Debug */,
+                               4FADC24408B4156D00ABE55E /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               4FADC24608B4156D00ABE55E /* Build configuration list for PBXProject "gtest" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               4FADC24708B4156D00ABE55E /* Debug */,
+                               4FADC24808B4156D00ABE55E /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+/* End XCConfigurationList section */
+       };
+       rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
+}
diff --git a/third_party/libyuv/README.webm b/third_party/libyuv/README.webm
new file mode 100644 (file)
index 0000000..d3495ca
--- /dev/null
@@ -0,0 +1,17 @@
+Name: libyuv
+URL: http://code.google.com/p/libyuv/
+Version: 102
+License: BSD
+License File: LICENSE
+
+Description:
+libyuv is an open source project that includes YUV conversion and scaling
+functionality.
+
+The optimized scaler in libyuv is used in multiple resolution encoder example,
+which down-samples the original input video (f.g. 1280x720) a number of times
+in order to encode multiple resolution bit streams.
+
+Local Modifications:
+Modified the original scaler code from C++ to C to fit in our current build
+system. This is a temporal solution, and will be improved later.
\ No newline at end of file
diff --git a/third_party/libyuv/include/libyuv/basic_types.h b/third_party/libyuv/include/libyuv/basic_types.h
new file mode 100644 (file)
index 0000000..30504ce
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ *  Copyright (c) 2011 The LibYuv project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef INCLUDE_LIBYUV_BASIC_TYPES_H_
+#define INCLUDE_LIBYUV_BASIC_TYPES_H_
+
+#include <stddef.h>  // for NULL, size_t
+
+#if !(defined(_MSC_VER) && (_MSC_VER < 1600))
+#include <stdint.h>  // for uintptr_t
+#endif
+
+#ifndef INT_TYPES_DEFINED
+#define INT_TYPES_DEFINED
+#ifdef COMPILER_MSVC
+typedef unsigned __int64 uint64;
+typedef __int64 int64;
+#ifndef INT64_C
+#define INT64_C(x) x ## I64
+#endif
+#ifndef UINT64_C
+#define UINT64_C(x) x ## UI64
+#endif
+#define INT64_F "I64"
+#else  // COMPILER_MSVC
+#ifdef __LP64__
+typedef unsigned long uint64;
+typedef long int64;
+#ifndef INT64_C
+#define INT64_C(x) x ## L
+#endif
+#ifndef UINT64_C
+#define UINT64_C(x) x ## UL
+#endif
+#define INT64_F "l"
+#else  // __LP64__
+typedef unsigned long long uint64;
+typedef long long int64;
+#ifndef INT64_C
+#define INT64_C(x) x ## LL
+#endif
+#ifndef UINT64_C
+#define UINT64_C(x) x ## ULL
+#endif
+#define INT64_F "ll"
+#endif  // __LP64__
+#endif  // COMPILER_MSVC
+typedef unsigned int uint32;
+typedef int int32;
+typedef unsigned short uint16;
+typedef short int16;
+typedef unsigned char uint8;
+typedef char int8;
+#endif  // INT_TYPES_DEFINED
+
+// Detect compiler is for x86 or x64.
+#if defined(__x86_64__) || defined(_M_X64) || \
+    defined(__i386__) || defined(_M_IX86)
+#define CPU_X86 1
+#endif
+
+#define ALIGNP(p, t) \
+  ((uint8*)((((uintptr_t)(p) + \
+  ((t)-1)) & ~((t)-1))))
+
+#endif // INCLUDE_LIBYUV_BASIC_TYPES_H_
diff --git a/third_party/libyuv/include/libyuv/cpu_id.h b/third_party/libyuv/include/libyuv/cpu_id.h
new file mode 100644 (file)
index 0000000..4a53b5b
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ *  Copyright (c) 2011 The LibYuv project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef INCLUDE_LIBYUV_CPU_ID_H_
+#define INCLUDE_LIBYUV_CPU_ID_H_
+
+#ifdef __cplusplus
+namespace libyuv {
+extern "C" {
+#endif
+
+// These flags are only valid on x86 processors
+static const int kCpuHasSSE2 = 1;
+static const int kCpuHasSSSE3 = 2;
+
+// These flags are only valid on ARM processors
+static const int kCpuHasNEON = 4;
+
+// Internal flag to indicate cpuid is initialized.
+static const int kCpuInitialized = 8;
+
+// Detect CPU has SSE2 etc.
+// test_flag parameter should be one of kCpuHas constants above
+// returns non-zero if instruction set is detected
+static __inline int TestCpuFlag(int test_flag) {
+  extern int cpu_info_;
+  extern int InitCpuFlags();
+  return (cpu_info_ ? cpu_info_ : InitCpuFlags()) & test_flag;
+}
+
+// For testing, allow CPU flags to be disabled.
+// ie MaskCpuFlags(~kCpuHasSSSE3) to disable SSSE3.
+// -1 to enable all cpu specific optimizations.
+// 0 to disable all cpu specific optimizations.
+void MaskCpuFlags(int enable_flags);
+
+#ifdef __cplusplus
+}  // extern "C"
+}  // namespace libyuv
+#endif
+
+#endif  // INCLUDE_LIBYUV_CPU_ID_H_
diff --git a/third_party/libyuv/include/libyuv/scale.h b/third_party/libyuv/include/libyuv/scale.h
new file mode 100644 (file)
index 0000000..21fe360
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ *  Copyright (c) 2011 The LibYuv project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef INCLUDE_LIBYUV_SCALE_H_
+#define INCLUDE_LIBYUV_SCALE_H_
+
+#include "third_party/libyuv/include/libyuv/basic_types.h"
+
+#ifdef __cplusplus
+namespace libyuv {
+extern "C" {
+#endif
+
+// Supported filtering
+typedef enum {
+  kFilterNone = 0,  // Point sample; Fastest
+  kFilterBilinear = 1,  // Faster than box, but lower quality scaling down.
+  kFilterBox = 2  // Highest quality
+}FilterMode;
+
+// Scales a YUV 4:2:0 image from the src width and height to the
+// dst width and height.
+// If filtering is kFilterNone, a simple nearest-neighbor algorithm is
+// used. This produces basic (blocky) quality at the fastest speed.
+// If filtering is kFilterBilinear, interpolation is used to produce a better
+// quality image, at the expense of speed.
+// If filtering is kFilterBox, averaging is used to produce ever better
+// quality image, at further expense of speed.
+// Returns 0 if successful.
+
+int I420Scale(const uint8* src_y, int src_stride_y,
+              const uint8* src_u, int src_stride_u,
+              const uint8* src_v, int src_stride_v,
+              int src_width, int src_height,
+              uint8* dst_y, int dst_stride_y,
+              uint8* dst_u, int dst_stride_u,
+              uint8* dst_v, int dst_stride_v,
+              int dst_width, int dst_height,
+              FilterMode filtering);
+
+// Legacy API.  Deprecated
+int Scale(const uint8* src_y, const uint8* src_u, const uint8* src_v,
+          int src_stride_y, int src_stride_u, int src_stride_v,
+          int src_width, int src_height,
+          uint8* dst_y, uint8* dst_u, uint8* dst_v,
+          int dst_stride_y, int dst_stride_u, int dst_stride_v,
+          int dst_width, int dst_height,
+          int interpolate);
+
+// Legacy API.  Deprecated
+int ScaleOffset(const uint8* src, int src_width, int src_height,
+                uint8* dst, int dst_width, int dst_height, int dst_yoffset,
+                int interpolate);
+
+// For testing, allow disabling of optimizations.
+void SetUseReferenceImpl(int use);
+
+#ifdef __cplusplus
+}  // extern "C"
+}  // namespace libyuv
+#endif
+
+#endif // INCLUDE_LIBYUV_SCALE_H_
diff --git a/third_party/libyuv/source/cpu_id.c b/third_party/libyuv/source/cpu_id.c
new file mode 100644 (file)
index 0000000..fccf3dd
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ *  Copyright (c) 2011 The LibYuv project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "third_party/libyuv/include/libyuv/cpu_id.h"
+
+#ifdef _MSC_VER
+#include <intrin.h>
+#endif
+#ifdef __ANDROID__
+#include <cpu-features.h>
+#endif
+
+#include "third_party/libyuv/include/libyuv/basic_types.h"  // for CPU_X86
+
+// TODO(fbarchard): Use cpuid.h when gcc 4.4 is used on OSX and Linux.
+#if (defined(__pic__) || defined(__APPLE__)) && defined(__i386__)
+static inline void __cpuid(int cpu_info[4], int info_type) {
+  asm volatile (
+    "mov %%ebx, %%edi                          \n"
+    "cpuid                                     \n"
+    "xchg %%edi, %%ebx                         \n"
+    : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
+    : "a"(info_type)
+  );
+}
+#elif defined(__i386__) || defined(__x86_64__)
+static inline void __cpuid(int cpu_info[4], int info_type) {
+  asm volatile (
+    "cpuid                                     \n"
+    : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
+    : "a"(info_type)
+  );
+}
+#endif
+
+#ifdef __cplusplus
+namespace libyuv {
+extern "C" {
+#endif
+
+// CPU detect function for SIMD instruction sets.
+int cpu_info_ = 0;
+
+int InitCpuFlags() {
+#ifdef CPU_X86
+  int cpu_info[4];
+  __cpuid(cpu_info, 1);
+  cpu_info_ = (cpu_info[3] & 0x04000000 ? kCpuHasSSE2 : 0) |
+              (cpu_info[2] & 0x00000200 ? kCpuHasSSSE3 : 0) |
+              kCpuInitialized;
+#elif defined(__ANDROID__) && defined(__ARM_NEON__)
+  uint64_t features = android_getCpuFeatures();
+  cpu_info_ = ((features & ANDROID_CPU_ARM_FEATURE_NEON) ? kCpuHasNEON : 0) |
+              kCpuInitialized;
+#elif defined(__ARM_NEON__)
+  // gcc -mfpu=neon defines __ARM_NEON__
+  // Enable Neon if you want support for Neon and Arm, and use MaskCpuFlags
+  // to disable Neon on devices that do not have it.
+  cpu_info_ = kCpuHasNEON | kCpuInitialized;
+#else
+  cpu_info_ = kCpuInitialized;
+#endif
+  return cpu_info_;
+}
+
+void MaskCpuFlags(int enable_flags) {
+  InitCpuFlags();
+  cpu_info_ = (cpu_info_ & enable_flags) | kCpuInitialized;
+}
+
+#ifdef __cplusplus
+}  // extern "C"
+}  // namespace libyuv
+#endif
diff --git a/third_party/libyuv/source/row.h b/third_party/libyuv/source/row.h
new file mode 100644 (file)
index 0000000..eabe180
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ *  Copyright (c) 2011 The LibYuv project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef LIBYUV_SOURCE_ROW_H_
+#define LIBYUV_SOURCE_ROW_H_
+
+#include "third_party/libyuv/include/libyuv/basic_types.h"
+
+#define kMaxStride (2048 * 4)
+#define IS_ALIGNED(p, a) (!((uintptr_t)(p) & ((a) - 1)))
+
+#if defined(COVERAGE_ENABLED) || defined(TARGET_IPHONE_SIMULATOR)
+#define YUV_DISABLE_ASM
+#endif
+
+#if defined(__ARM_NEON__) && !defined(YUV_DISABLE_ASM)
+#define HAS_FASTCONVERTYUVTOARGBROW_NEON
+void FastConvertYUVToARGBRow_NEON(const uint8* y_buf,
+                                  const uint8* u_buf,
+                                  const uint8* v_buf,
+                                  uint8* rgb_buf,
+                                  int width);
+#define HAS_FASTCONVERTYUVTOBGRAROW_NEON
+void FastConvertYUVToBGRARow_NEON(const uint8* y_buf,
+                                  const uint8* u_buf,
+                                  const uint8* v_buf,
+                                  uint8* rgb_buf,
+                                  int width);
+#define HAS_FASTCONVERTYUVTOABGRROW_NEON
+void FastConvertYUVToABGRRow_NEON(const uint8* y_buf,
+                                  const uint8* u_buf,
+                                  const uint8* v_buf,
+                                  uint8* rgb_buf,
+                                  int width);
+#endif
+
+// The following are available on all x86 platforms
+#if (defined(_M_IX86) || defined(__x86_64__) || defined(__i386__)) && \
+    !defined(YUV_DISABLE_ASM)
+#define HAS_ABGRTOARGBROW_SSSE3
+#define HAS_BGRATOARGBROW_SSSE3
+#define HAS_BG24TOARGBROW_SSSE3
+#define HAS_RAWTOARGBROW_SSSE3
+#define HAS_RGB24TOYROW_SSSE3
+#define HAS_RAWTOYROW_SSSE3
+#define HAS_RGB24TOUVROW_SSSE3
+#define HAS_RAWTOUVROW_SSSE3
+#define HAS_ARGBTOYROW_SSSE3
+#define HAS_BGRATOYROW_SSSE3
+#define HAS_ABGRTOYROW_SSSE3
+#define HAS_ARGBTOUVROW_SSSE3
+#define HAS_BGRATOUVROW_SSSE3
+#define HAS_ABGRTOUVROW_SSSE3
+#define HAS_I400TOARGBROW_SSE2
+#define HAS_FASTCONVERTYTOARGBROW_SSE2
+#define HAS_FASTCONVERTYUVTOARGBROW_SSSE3
+#define HAS_FASTCONVERTYUVTOBGRAROW_SSSE3
+#define HAS_FASTCONVERTYUVTOABGRROW_SSSE3
+#define HAS_FASTCONVERTYUV444TOARGBROW_SSSE3
+#define HAS_REVERSE_ROW_SSSE3
+#endif
+
+// The following are available on Neon platforms
+#if defined(__ARM_NEON__) && !defined(YUV_DISABLE_ASM)
+#define HAS_REVERSE_ROW_NEON
+#endif
+
+#ifdef __cplusplus
+namespace libyuv {
+extern "C" {
+#endif
+
+#ifdef HAS_ARGBTOYROW_SSSE3
+void ARGBToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix);
+void BGRAToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix);
+void ABGRToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix);
+void ARGBToUVRow_SSSE3(const uint8* src_argb0, int src_stride_argb,
+                       uint8* dst_u, uint8* dst_v, int width);
+void BGRAToUVRow_SSSE3(const uint8* src_argb0, int src_stride_argb,
+                       uint8* dst_u, uint8* dst_v, int width);
+void ABGRToUVRow_SSSE3(const uint8* src_argb0, int src_stride_argb,
+                       uint8* dst_u, uint8* dst_v, int width);
+#endif
+#if defined(HAS_BG24TOARGBROW_SSSE3) && defined(HAS_ARGBTOYROW_SSSE3)
+#define HASRGB24TOYROW_SSSE3
+#endif
+#ifdef HASRGB24TOYROW_SSSE3
+void RGB24ToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix);
+void RAWToYRow_SSSE3(const uint8* src_argb, uint8* dst_y, int pix);
+void RGB24ToUVRow_SSSE3(const uint8* src_argb0, int src_stride_argb,
+                        uint8* dst_u, uint8* dst_v, int width);
+void RAWToUVRow_SSSE3(const uint8* src_argb0, int src_stride_argb,
+                      uint8* dst_u, uint8* dst_v, int width);
+#endif
+#ifdef HAS_REVERSE_ROW_SSSE3
+void ReverseRow_SSSE3(const uint8* src, uint8* dst, int width);
+#endif
+#ifdef HAS_REVERSE_ROW_NEON
+void ReverseRow_NEON(const uint8* src, uint8* dst, int width);
+#endif
+void ReverseRow_C(const uint8* src, uint8* dst, int width);
+
+void ARGBToYRow_C(const uint8* src_argb, uint8* dst_y, int pix);
+void BGRAToYRow_C(const uint8* src_argb, uint8* dst_y, int pix);
+void ABGRToYRow_C(const uint8* src_argb, uint8* dst_y, int pix);
+void RGB24ToYRow_C(const uint8* src_argb, uint8* dst_y, int pix);
+void RAWToYRow_C(const uint8* src_argb, uint8* dst_y, int pix);
+void ARGBToUVRow_C(const uint8* src_argb0, int src_stride_argb,
+                   uint8* dst_u, uint8* dst_v, int width);
+void BGRAToUVRow_C(const uint8* src_argb0, int src_stride_argb,
+                   uint8* dst_u, uint8* dst_v, int width);
+void ABGRToUVRow_C(const uint8* src_argb0, int src_stride_argb,
+                   uint8* dst_u, uint8* dst_v, int width);
+void RGB24ToUVRow_C(const uint8* src_argb0, int src_stride_argb,
+                    uint8* dst_u, uint8* dst_v, int width);
+void RAWToUVRow_C(const uint8* src_argb0, int src_stride_argb,
+                  uint8* dst_u, uint8* dst_v, int width);
+
+#ifdef HAS_BG24TOARGBROW_SSSE3
+void ABGRToARGBRow_SSSE3(const uint8* src_abgr, uint8* dst_argb, int pix);
+void BGRAToARGBRow_SSSE3(const uint8* src_bgra, uint8* dst_argb, int pix);
+void BG24ToARGBRow_SSSE3(const uint8* src_bg24, uint8* dst_argb, int pix);
+void RAWToARGBRow_SSSE3(const uint8* src_bg24, uint8* dst_argb, int pix);
+#endif
+void ABGRToARGBRow_C(const uint8* src_abgr, uint8* dst_argb, int pix);
+void BGRAToARGBRow_C(const uint8* src_bgra, uint8* dst_argb, int pix);
+void BG24ToARGBRow_C(const uint8* src_bg24, uint8* dst_argb, int pix);
+void RAWToARGBRow_C(const uint8* src_bg24, uint8* dst_argb, int pix);
+
+#ifdef HAS_I400TOARGBROW_SSE2
+void I400ToARGBRow_SSE2(const uint8* src_y, uint8* dst_argb, int pix);
+#endif
+void I400ToARGBRow_C(const uint8* src_y, uint8* dst_argb, int pix);
+
+#if defined(_MSC_VER)
+#define SIMD_ALIGNED(var) __declspec(align(16)) var
+typedef __declspec(align(16)) signed char vec8[16];
+typedef __declspec(align(16)) unsigned char uvec8[16];
+typedef __declspec(align(16)) signed short vec16[8];
+#else // __GNUC__
+#define SIMD_ALIGNED(var) var __attribute__((aligned(16)))
+typedef signed char __attribute__((vector_size(16))) vec8;
+typedef unsigned char __attribute__((vector_size(16))) uvec8;
+typedef signed short __attribute__((vector_size(16))) vec16;
+#endif
+
+//extern "C"
+SIMD_ALIGNED(const int16 kCoefficientsRgbY[768][4]);
+//extern "C"
+SIMD_ALIGNED(const int16 kCoefficientsBgraY[768][4]);
+//extern "C"
+SIMD_ALIGNED(const int16 kCoefficientsAbgrY[768][4]);
+
+void FastConvertYUVToARGBRow_C(const uint8* y_buf,
+                               const uint8* u_buf,
+                               const uint8* v_buf,
+                               uint8* rgb_buf,
+                               int width);
+
+void FastConvertYUVToBGRARow_C(const uint8* y_buf,
+                               const uint8* u_buf,
+                               const uint8* v_buf,
+                               uint8* rgb_buf,
+                               int width);
+
+void FastConvertYUVToABGRRow_C(const uint8* y_buf,
+                               const uint8* u_buf,
+                               const uint8* v_buf,
+                               uint8* rgb_buf,
+                               int width);
+
+void FastConvertYUV444ToARGBRow_C(const uint8* y_buf,
+                                  const uint8* u_buf,
+                                  const uint8* v_buf,
+                                  uint8* rgb_buf,
+                                  int width);
+
+void FastConvertYToARGBRow_C(const uint8* y_buf,
+                             uint8* rgb_buf,
+                             int width);
+
+#ifdef HAS_FASTCONVERTYUVTOARGBROW_SSE2
+void FastConvertYUVToARGBRow_SSE2(const uint8* y_buf,
+                                  const uint8* u_buf,
+                                  const uint8* v_buf,
+                                  uint8* rgb_buf,
+                                  int width);
+
+void FastConvertYUVToARGBRow4_SSE2(const uint8* y_buf,
+                                   const uint8* u_buf,
+                                   const uint8* v_buf,
+                                   uint8* rgb_buf,
+                                   int width);
+
+void FastConvertYUVToBGRARow_SSE2(const uint8* y_buf,
+                                  const uint8* u_buf,
+                                  const uint8* v_buf,
+                                  uint8* rgb_buf,
+                                  int width);
+
+void FastConvertYUVToABGRRow_SSE2(const uint8* y_buf,
+                                  const uint8* u_buf,
+                                  const uint8* v_buf,
+                                  uint8* rgb_buf,
+                                  int width);
+
+void FastConvertYUV444ToARGBRow_SSE2(const uint8* y_buf,
+                                     const uint8* u_buf,
+                                     const uint8* v_buf,
+                                     uint8* rgb_buf,
+                                     int width);
+
+void FastConvertYToARGBRow_SSE2(const uint8* y_buf,
+                                uint8* rgb_buf,
+                                int width);
+#endif
+
+#ifdef HAS_FASTCONVERTYUVTOARGBROW_SSSE3
+void FastConvertYUVToARGBRow_SSSE3(const uint8* y_buf,
+                                   const uint8* u_buf,
+                                   const uint8* v_buf,
+                                   uint8* rgb_buf,
+                                   int width);
+
+void FastConvertYUVToBGRARow_SSSE3(const uint8* y_buf,
+                                   const uint8* u_buf,
+                                   const uint8* v_buf,
+                                   uint8* rgb_buf,
+                                   int width);
+
+void FastConvertYUVToABGRRow_SSSE3(const uint8* y_buf,
+                                   const uint8* u_buf,
+                                   const uint8* v_buf,
+                                   uint8* rgb_buf,
+                                   int width);
+
+void FastConvertYUV444ToARGBRow_SSSE3(const uint8* y_buf,
+                                      const uint8* u_buf,
+                                      const uint8* v_buf,
+                                      uint8* rgb_buf,
+                                      int width);
+
+#endif
+
+#ifdef HAS_FASTCONVERTYTOARGBROW_SSE2
+void FastConvertYToARGBRow_SSE2(const uint8* y_buf,
+                                uint8* rgb_buf,
+                                int width);
+
+#endif
+
+#ifdef __cplusplus
+}  // extern "C"
+}  // namespace libyuv
+#endif
+
+#endif  // LIBYUV_SOURCE_ROW_H_
diff --git a/third_party/libyuv/source/scale.c b/third_party/libyuv/source/scale.c
new file mode 100644 (file)
index 0000000..930a7ae
--- /dev/null
@@ -0,0 +1,3884 @@
+/*
+ *  Copyright (c) 2011 The LibYuv project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "third_party/libyuv/include/libyuv/scale.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include "third_party/libyuv/include/libyuv/cpu_id.h"
+#include "third_party/libyuv/source/row.h"
+
+#ifdef __cplusplus
+namespace libyuv {
+extern "C" {
+#endif
+
+/*
+ * Note: Defining YUV_DISABLE_ASM allows to use c version.
+ */
+//#define YUV_DISABLE_ASM
+
+#if defined(_MSC_VER)
+#define ALIGN16(var) __declspec(align(16)) var
+#else
+#define ALIGN16(var) var __attribute__((aligned(16)))
+#endif
+
+// Note: A Neon reference manual
+// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204j/CJAJIIGG.html
+// Note: Some SSE2 reference manuals
+// cpuvol1.pdf agner_instruction_tables.pdf 253666.pdf 253667.pdf
+
+// Set the following flag to true to revert to only
+// using the reference implementation ScalePlaneBox(), and
+// NOT the optimized versions. Useful for debugging and
+// when comparing the quality of the resulting YUV planes
+// as produced by the optimized and non-optimized versions.
+
+static int use_reference_impl_ = 0;
+
+void SetUseReferenceImpl(int use) {
+  use_reference_impl_ = use;
+}
+
+// ScaleRowDown2Int also used by planar functions
+
+/**
+ * NEON downscalers with interpolation.
+ *
+ * Provided by Fritz Koenig
+ *
+ */
+
+#if defined(__ARM_NEON__) && !defined(YUV_DISABLE_ASM)
+#define HAS_SCALEROWDOWN2_NEON
+void ScaleRowDown2_NEON(const uint8* src_ptr, int /* src_stride */,
+                        uint8* dst, int dst_width) {
+  asm volatile (
+    "1:                                        \n"
+    "vld2.u8    {q0,q1}, [%0]!                 \n"  // load even pixels into q0, odd into q1
+    "vst1.u8    {q0}, [%1]!                    \n"  // store even pixels
+    "subs       %2, %2, #16                    \n"  // 16 processed per loop
+    "bhi        1b                             \n"
+    : "+r"(src_ptr),          // %0
+      "+r"(dst),              // %1
+      "+r"(dst_width)         // %2
+    :
+    : "q0", "q1"              // Clobber List
+  );
+}
+
+void ScaleRowDown2Int_NEON(const uint8* src_ptr, int src_stride,
+                           uint8* dst, int dst_width) {
+  asm volatile (
+    "add        %1, %0                         \n"  // change the stride to row 2 pointer
+    "1:                                        \n"
+    "vld1.u8    {q0,q1}, [%0]!                 \n"  // load row 1 and post increment
+    "vld1.u8    {q2,q3}, [%1]!                 \n"  // load row 2 and post increment
+    "vpaddl.u8  q0, q0                         \n"  // row 1 add adjacent
+    "vpaddl.u8  q1, q1                         \n"
+    "vpadal.u8  q0, q2                         \n"  // row 2 add adjacent, add row 1 to row 2
+    "vpadal.u8  q1, q3                         \n"
+    "vrshrn.u16 d0, q0, #2                     \n"  // downshift, round and pack
+    "vrshrn.u16 d1, q1, #2                     \n"
+    "vst1.u8    {q0}, [%2]!                    \n"
+    "subs       %3, %3, #16                    \n"  // 16 processed per loop
+    "bhi        1b                             \n"
+    : "+r"(src_ptr),          // %0
+      "+r"(src_stride),       // %1
+      "+r"(dst),              // %2
+      "+r"(dst_width)         // %3
+    :
+    : "q0", "q1", "q2", "q3"     // Clobber List
+   );
+}
+
+#define HAS_SCALEROWDOWN4_NEON
+static void ScaleRowDown4_NEON(const uint8* src_ptr, int /* src_stride */,
+                               uint8* dst_ptr, int dst_width) {
+  asm volatile (
+    "1:                                        \n"
+    "vld2.u8    {d0, d1}, [%0]!                \n"
+    "vtrn.u8    d1, d0                         \n"
+    "vshrn.u16  d0, q0, #8                     \n"
+    "vst1.u32   {d0[1]}, [%1]!                 \n"
+
+    "subs       %2, #4                         \n"
+    "bhi        1b                             \n"
+    : "+r"(src_ptr),          // %0
+      "+r"(dst_ptr),          // %1
+      "+r"(dst_width)         // %2
+    :
+    : "q0", "q1", "memory", "cc"
+  );
+}
+
+static void ScaleRowDown4Int_NEON(const uint8* src_ptr, int src_stride,
+                                  uint8* dst_ptr, int dst_width) {
+  asm volatile (
+    "add        r4, %0, %3                     \n"
+    "add        r5, r4, %3                     \n"
+    "add        %3, r5, %3                     \n"
+    "1:                                        \n"
+    "vld1.u8    {q0}, [%0]!                    \n"   // load up 16x4 block of input data
+    "vld1.u8    {q1}, [r4]!                    \n"
+    "vld1.u8    {q2}, [r5]!                    \n"
+    "vld1.u8    {q3}, [%3]!                    \n"
+
+    "vpaddl.u8  q0, q0                         \n"
+    "vpadal.u8  q0, q1                         \n"
+    "vpadal.u8  q0, q2                         \n"
+    "vpadal.u8  q0, q3                         \n"
+
+    "vpaddl.u16 q0, q0                         \n"
+
+    "vrshrn.u32 d0, q0, #4                     \n"   // divide by 16 w/rounding
+
+    "vmovn.u16  d0, q0                         \n"
+    "vst1.u32   {d0[0]}, [%1]!                 \n"
+
+    "subs       %2, #4                         \n"
+    "bhi        1b                             \n"
+
+    : "+r"(src_ptr),          // %0
+      "+r"(dst_ptr),          // %1
+      "+r"(dst_width)         // %2
+    : "r"(src_stride)         // %3
+    : "r4", "r5", "q0", "q1", "q2", "q3", "memory", "cc"
+  );
+}
+
+#define HAS_SCALEROWDOWN34_NEON
+// Down scale from 4 to 3 pixels.  Use the neon multilane read/write
+//  to load up the every 4th pixel into a 4 different registers.
+// Point samples 32 pixels to 24 pixels.
+static void ScaleRowDown34_NEON(const uint8* src_ptr, int /* src_stride */,
+                                uint8* dst_ptr, int dst_width) {
+  asm volatile (
+    "1:                                        \n"
+    "vld4.u8      {d0, d1, d2, d3}, [%0]!      \n" // src line 0
+    "vmov         d2, d3                       \n" // order needs to be d0, d1, d2
+    "vst3.u8      {d0, d1, d2}, [%1]!          \n"
+    "subs         %2, #24                      \n"
+    "bhi          1b                           \n"
+    : "+r"(src_ptr),          // %0
+      "+r"(dst_ptr),          // %1
+      "+r"(dst_width)         // %2
+    :
+    : "d0", "d1", "d2", "d3", "memory", "cc"
+  );
+}
+
+static void ScaleRowDown34_0_Int_NEON(const uint8* src_ptr, int src_stride,
+                                      uint8* dst_ptr, int dst_width) {
+  asm volatile (
+    "vmov.u8      d24, #3                      \n"
+    "add          %3, %0                       \n"
+    "1:                                        \n"
+    "vld4.u8      {d0, d1, d2, d3}, [%0]!      \n" // src line 0
+    "vld4.u8      {d4, d5, d6, d7}, [%3]!      \n" // src line 1
+
+    // filter src line 0 with src line 1
+    // expand chars to shorts to allow for room
+    // when adding lines together
+    "vmovl.u8     q8, d4                       \n"
+    "vmovl.u8     q9, d5                       \n"
+    "vmovl.u8     q10, d6                      \n"
+    "vmovl.u8     q11, d7                      \n"
+
+    // 3 * line_0 + line_1
+    "vmlal.u8     q8, d0, d24                  \n"
+    "vmlal.u8     q9, d1, d24                  \n"
+    "vmlal.u8     q10, d2, d24                 \n"
+    "vmlal.u8     q11, d3, d24                 \n"
+
+    // (3 * line_0 + line_1) >> 2
+    "vqrshrn.u16  d0, q8, #2                   \n"
+    "vqrshrn.u16  d1, q9, #2                   \n"
+    "vqrshrn.u16  d2, q10, #2                  \n"
+    "vqrshrn.u16  d3, q11, #2                  \n"
+
+    // a0 = (src[0] * 3 + s[1] * 1) >> 2
+    "vmovl.u8     q8, d1                       \n"
+    "vmlal.u8     q8, d0, d24                  \n"
+    "vqrshrn.u16  d0, q8, #2                   \n"
+
+    // a1 = (src[1] * 1 + s[2] * 1) >> 1
+    "vrhadd.u8    d1, d1, d2                   \n"
+
+    // a2 = (src[2] * 1 + s[3] * 3) >> 2
+    "vmovl.u8     q8, d2                       \n"
+    "vmlal.u8     q8, d3, d24                  \n"
+    "vqrshrn.u16  d2, q8, #2                   \n"
+
+    "vst3.u8      {d0, d1, d2}, [%1]!          \n"
+
+    "subs         %2, #24                      \n"
+    "bhi          1b                           \n"
+    : "+r"(src_ptr),          // %0
+      "+r"(dst_ptr),          // %1
+      "+r"(dst_width),        // %2
+      "+r"(src_stride)        // %3
+    :
+    : "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "d24", "memory", "cc"
+  );
+}
+
+static void ScaleRowDown34_1_Int_NEON(const uint8* src_ptr, int src_stride,
+                                      uint8* dst_ptr, int dst_width) {
+  asm volatile (
+    "vmov.u8      d24, #3                      \n"
+    "add          %3, %0                       \n"
+    "1:                                        \n"
+    "vld4.u8      {d0, d1, d2, d3}, [%0]!      \n" // src line 0
+    "vld4.u8      {d4, d5, d6, d7}, [%3]!      \n" // src line 1
+
+    // average src line 0 with src line 1
+    "vrhadd.u8    q0, q0, q2                   \n"
+    "vrhadd.u8    q1, q1, q3                   \n"
+
+    // a0 = (src[0] * 3 + s[1] * 1) >> 2
+    "vmovl.u8     q3, d1                       \n"
+    "vmlal.u8     q3, d0, d24                  \n"
+    "vqrshrn.u16  d0, q3, #2                   \n"
+
+    // a1 = (src[1] * 1 + s[2] * 1) >> 1
+    "vrhadd.u8    d1, d1, d2                   \n"
+
+    // a2 = (src[2] * 1 + s[3] * 3) >> 2
+    "vmovl.u8     q3, d2                       \n"
+    "vmlal.u8     q3, d3, d24                  \n"
+    "vqrshrn.u16  d2, q3, #2                   \n"
+
+    "vst3.u8      {d0, d1, d2}, [%1]!          \n"
+
+    "subs         %2, #24                      \n"
+    "bhi          1b                           \n"
+    : "+r"(src_ptr),          // %0
+      "+r"(dst_ptr),          // %1
+      "+r"(dst_width),        // %2
+      "+r"(src_stride)        // %3
+    :
+    : "r4", "q0", "q1", "q2", "q3", "d24", "memory", "cc"
+  );
+}
+
+#define HAS_SCALEROWDOWN38_NEON
+const uint8 shuf38[16] __attribute__ ((aligned(16))) =
+  { 0, 3, 6, 8, 11, 14, 16, 19, 22, 24, 27, 30, 0, 0, 0, 0 };
+const uint8 shuf38_2[16] __attribute__ ((aligned(16))) =
+  { 0, 8, 16, 2, 10, 17, 4, 12, 18, 6, 14, 19, 0, 0, 0, 0 };
+const unsigned short mult38_div6[8] __attribute__ ((aligned(16))) =
+  { 65536 / 12, 65536 / 12, 65536 / 12, 65536 / 12,
+    65536 / 12, 65536 / 12, 65536 / 12, 65536 / 12 };
+const unsigned short mult38_div9[8] __attribute__ ((aligned(16))) =
+  { 65536 / 18, 65536 / 18, 65536 / 18, 65536 / 18,
+    65536 / 18, 65536 / 18, 65536 / 18, 65536 / 18 };
+
+// 32 -> 12
+static void ScaleRowDown38_NEON(const uint8* src_ptr, int,
+                                uint8* dst_ptr, int dst_width) {
+  asm volatile (
+    "vld1.u8      {q3}, [%3]                   \n"
+    "1:                                        \n"
+    "vld1.u8      {d0, d1, d2, d3}, [%0]!      \n"
+    "vtbl.u8      d4, {d0, d1, d2, d3}, d6     \n"
+    "vtbl.u8      d5, {d0, d1, d2, d3}, d7     \n"
+    "vst1.u8      {d4}, [%1]!                  \n"
+    "vst1.u32     {d5[0]}, [%1]!               \n"
+    "subs         %2, #12                      \n"
+    "bhi          1b                           \n"
+    : "+r"(src_ptr),          // %0
+      "+r"(dst_ptr),          // %1
+      "+r"(dst_width)         // %2
+    : "r"(shuf38)             // %3
+    : "d0", "d1", "d2", "d3", "d4", "d5", "memory", "cc"
+  );
+}
+
+// 32x3 -> 12x1
+static void ScaleRowDown38_3_Int_NEON(const uint8* src_ptr, int src_stride,
+                                      uint8* dst_ptr, int dst_width) {
+  asm volatile (
+    "vld1.u16     {q13}, [%4]                  \n"
+    "vld1.u8      {q14}, [%5]                  \n"
+    "vld1.u8      {q15}, [%6]                  \n"
+    "add          r4, %0, %3, lsl #1           \n"
+    "add          %3, %0                       \n"
+    "1:                                        \n"
+
+    // d0 = 00 40 01 41 02 42 03 43
+    // d1 = 10 50 11 51 12 52 13 53
+    // d2 = 20 60 21 61 22 62 23 63
+    // d3 = 30 70 31 71 32 72 33 73
+    "vld4.u8      {d0, d1, d2, d3}, [%0]!      \n"
+    "vld4.u8      {d4, d5, d6, d7}, [%3]!      \n"
+    "vld4.u8      {d16, d17, d18, d19}, [r4]!  \n"
+
+    // Shuffle the input data around to get align the data
+    //  so adjacent data can be added.  0,1 - 2,3 - 4,5 - 6,7
+    // d0 = 00 10 01 11 02 12 03 13
+    // d1 = 40 50 41 51 42 52 43 53
+    "vtrn.u8      d0, d1                       \n"
+    "vtrn.u8      d4, d5                       \n"
+    "vtrn.u8      d16, d17                     \n"
+
+    // d2 = 20 30 21 31 22 32 23 33
+    // d3 = 60 70 61 71 62 72 63 73
+    "vtrn.u8      d2, d3                       \n"
+    "vtrn.u8      d6, d7                       \n"
+    "vtrn.u8      d18, d19                     \n"
+
+    // d0 = 00+10 01+11 02+12 03+13
+    // d2 = 40+50 41+51 42+52 43+53
+    "vpaddl.u8    q0, q0                       \n"
+    "vpaddl.u8    q2, q2                       \n"
+    "vpaddl.u8    q8, q8                       \n"
+
+    // d3 = 60+70 61+71 62+72 63+73
+    "vpaddl.u8    d3, d3                       \n"
+    "vpaddl.u8    d7, d7                       \n"
+    "vpaddl.u8    d19, d19                     \n"
+
+    // combine source lines
+    "vadd.u16     q0, q2                       \n"
+    "vadd.u16     q0, q8                       \n"
+    "vadd.u16     d4, d3, d7                   \n"
+    "vadd.u16     d4, d19                      \n"
+
+    // dst_ptr[3] = (s[6 + st * 0] + s[7 + st * 0]
+    //             + s[6 + st * 1] + s[7 + st * 1]
+    //             + s[6 + st * 2] + s[7 + st * 2]) / 6
+    "vqrdmulh.s16 q2, q13                      \n"
+    "vmovn.u16    d4, q2                       \n"
+
+    // Shuffle 2,3 reg around so that 2 can be added to the
+    //  0,1 reg and 3 can be added to the 4,5 reg.  This
+    //  requires expanding from u8 to u16 as the 0,1 and 4,5
+    //  registers are already expanded.  Then do transposes
+    //  to get aligned.
+    // q2 = xx 20 xx 30 xx 21 xx 31 xx 22 xx 32 xx 23 xx 33
+    "vmovl.u8     q1, d2                       \n"
+    "vmovl.u8     q3, d6                       \n"
+    "vmovl.u8     q9, d18                      \n"
+
+    // combine source lines
+    "vadd.u16     q1, q3                       \n"
+    "vadd.u16     q1, q9                       \n"
+
+    // d4 = xx 20 xx 30 xx 22 xx 32
+    // d5 = xx 21 xx 31 xx 23 xx 33
+    "vtrn.u32     d2, d3                       \n"
+
+    // d4 = xx 20 xx 21 xx 22 xx 23
+    // d5 = xx 30 xx 31 xx 32 xx 33
+    "vtrn.u16     d2, d3                       \n"
+
+    // 0+1+2, 3+4+5
+    "vadd.u16     q0, q1                       \n"
+
+    // Need to divide, but can't downshift as the the value
+    //  isn't a power of 2.  So multiply by 65536 / n
+    //  and take the upper 16 bits.
+    "vqrdmulh.s16 q0, q15                      \n"
+
+    // Align for table lookup, vtbl requires registers to
+    //  be adjacent
+    "vmov.u8      d2, d4                       \n"
+
+    "vtbl.u8      d3, {d0, d1, d2}, d28        \n"
+    "vtbl.u8      d4, {d0, d1, d2}, d29        \n"
+
+    "vst1.u8      {d3}, [%1]!                  \n"
+    "vst1.u32     {d4[0]}, [%1]!               \n"
+    "subs         %2, #12                      \n"
+    "bhi          1b                           \n"
+    : "+r"(src_ptr),          // %0
+      "+r"(dst_ptr),          // %1
+      "+r"(dst_width),        // %2
+      "+r"(src_stride)        // %3
+    : "r"(mult38_div6),       // %4
+      "r"(shuf38_2),          // %5
+      "r"(mult38_div9)        // %6
+    : "r4", "q0", "q1", "q2", "q3", "q8", "q9",
+      "q13", "q14", "q15", "memory", "cc"
+  );
+}
+
+// 32x2 -> 12x1
+static void ScaleRowDown38_2_Int_NEON(const uint8* src_ptr, int src_stride,
+                                      uint8* dst_ptr, int dst_width) {
+  asm volatile (
+    "vld1.u16     {q13}, [%4]                  \n"
+    "vld1.u8      {q14}, [%5]                  \n"
+    "add          %3, %0                       \n"
+    "1:                                        \n"
+
+    // d0 = 00 40 01 41 02 42 03 43
+    // d1 = 10 50 11 51 12 52 13 53
+    // d2 = 20 60 21 61 22 62 23 63
+    // d3 = 30 70 31 71 32 72 33 73
+    "vld4.u8      {d0, d1, d2, d3}, [%0]!      \n"
+    "vld4.u8      {d4, d5, d6, d7}, [%3]!      \n"
+
+    // Shuffle the input data around to get align the data
+    //  so adjacent data can be added.  0,1 - 2,3 - 4,5 - 6,7
+    // d0 = 00 10 01 11 02 12 03 13
+    // d1 = 40 50 41 51 42 52 43 53
+    "vtrn.u8      d0, d1                       \n"
+    "vtrn.u8      d4, d5                       \n"
+
+    // d2 = 20 30 21 31 22 32 23 33
+    // d3 = 60 70 61 71 62 72 63 73
+    "vtrn.u8      d2, d3                       \n"
+    "vtrn.u8      d6, d7                       \n"
+
+    // d0 = 00+10 01+11 02+12 03+13
+    // d2 = 40+50 41+51 42+52 43+53
+    "vpaddl.u8    q0, q0                       \n"
+    "vpaddl.u8    q2, q2                       \n"
+
+    // d3 = 60+70 61+71 62+72 63+73
+    "vpaddl.u8    d3, d3                       \n"
+    "vpaddl.u8    d7, d7                       \n"
+
+    // combine source lines
+    "vadd.u16     q0, q2                       \n"
+    "vadd.u16     d4, d3, d7                   \n"
+
+    // dst_ptr[3] = (s[6] + s[7] + s[6+st] + s[7+st]) / 4
+    "vqrshrn.u16  d4, q2, #2                   \n"
+
+    // Shuffle 2,3 reg around so that 2 can be added to the
+    //  0,1 reg and 3 can be added to the 4,5 reg.  This
+    //  requires expanding from u8 to u16 as the 0,1 and 4,5
+    //  registers are already expanded.  Then do transposes
+    //  to get aligned.
+    // q2 = xx 20 xx 30 xx 21 xx 31 xx 22 xx 32 xx 23 xx 33
+    "vmovl.u8     q1, d2                       \n"
+    "vmovl.u8     q3, d6                       \n"
+
+    // combine source lines
+    "vadd.u16     q1, q3                       \n"
+
+    // d4 = xx 20 xx 30 xx 22 xx 32
+    // d5 = xx 21 xx 31 xx 23 xx 33
+    "vtrn.u32     d2, d3                       \n"
+
+    // d4 = xx 20 xx 21 xx 22 xx 23
+    // d5 = xx 30 xx 31 xx 32 xx 33
+    "vtrn.u16     d2, d3                       \n"
+
+    // 0+1+2, 3+4+5
+    "vadd.u16     q0, q1                       \n"
+
+    // Need to divide, but can't downshift as the the value
+    //  isn't a power of 2.  So multiply by 65536 / n
+    //  and take the upper 16 bits.
+    "vqrdmulh.s16 q0, q13                      \n"
+
+    // Align for table lookup, vtbl requires registers to
+    //  be adjacent
+    "vmov.u8      d2, d4                       \n"
+
+    "vtbl.u8      d3, {d0, d1, d2}, d28        \n"
+    "vtbl.u8      d4, {d0, d1, d2}, d29        \n"
+
+    "vst1.u8      {d3}, [%1]!                  \n"
+    "vst1.u32     {d4[0]}, [%1]!               \n"
+    "subs         %2, #12                      \n"
+    "bhi          1b                           \n"
+    : "+r"(src_ptr),          // %0
+      "+r"(dst_ptr),          // %1
+      "+r"(dst_width),        // %2
+      "+r"(src_stride)        // %3
+    : "r"(mult38_div6),       // %4
+      "r"(shuf38_2)           // %5
+    : "q0", "q1", "q2", "q3", "q13", "q14", "memory", "cc"
+  );
+}
+
+/**
+ * SSE2 downscalers with interpolation.
+ *
+ * Provided by Frank Barchard (fbarchard@google.com)
+ *
+ */
+
+// Constants for SSE2 code
+#elif (defined(_M_IX86) || defined(__i386__) || defined(__x86_64__)) && \
+    !defined(YUV_DISABLE_ASM)
+#if defined(_MSC_VER)
+#define TALIGN16(t, var) __declspec(align(16)) t _ ## var
+#elif (defined(__APPLE__) || defined(__MINGW32__) || defined(__CYGWIN__)) && defined(__i386__)
+#define TALIGN16(t, var) t var __attribute__((aligned(16)))
+#else
+#define TALIGN16(t, var) t _ ## var __attribute__((aligned(16)))
+#endif
+
+#if (defined(__APPLE__) || defined(__MINGW32__) || defined(__CYGWIN__)) && \
+    defined(__i386__)
+#define DECLARE_FUNCTION(name)                                                 \
+    ".text                                     \n"                             \
+    ".globl _" #name "                         \n"                             \
+"_" #name ":                                   \n"
+#else
+#define DECLARE_FUNCTION(name)                                                 \
+    ".text                                     \n"                             \
+    ".global " #name "                         \n"                             \
+#name ":                                       \n"
+#endif
+
+
+// Offsets for source bytes 0 to 9
+//extern "C"
+TALIGN16(const uint8, shuf0[16]) =
+  { 0, 1, 3, 4, 5, 7, 8, 9, 128, 128, 128, 128, 128, 128, 128, 128 };
+
+// Offsets for source bytes 11 to 20 with 8 subtracted = 3 to 12.
+//extern "C"
+TALIGN16(const uint8, shuf1[16]) =
+  { 3, 4, 5, 7, 8, 9, 11, 12, 128, 128, 128, 128, 128, 128, 128, 128 };
+
+// Offsets for source bytes 21 to 31 with 16 subtracted = 5 to 31.
+//extern "C"
+TALIGN16(const uint8, shuf2[16]) =
+  { 5, 7, 8, 9, 11, 12, 13, 15, 128, 128, 128, 128, 128, 128, 128, 128 };
+
+// Offsets for source bytes 0 to 10
+//extern "C"
+TALIGN16(const uint8, shuf01[16]) =
+  { 0, 1, 1, 2, 2, 3, 4, 5, 5, 6, 6, 7, 8, 9, 9, 10 };
+
+// Offsets for source bytes 10 to 21 with 8 subtracted = 3 to 13.
+//extern "C"
+TALIGN16(const uint8, shuf11[16]) =
+  { 2, 3, 4, 5, 5, 6, 6, 7, 8, 9, 9, 10, 10, 11, 12, 13 };
+
+// Offsets for source bytes 21 to 31 with 16 subtracted = 5 to 31.
+//extern "C"
+TALIGN16(const uint8, shuf21[16]) =
+  { 5, 6, 6, 7, 8, 9, 9, 10, 10, 11, 12, 13, 13, 14, 14, 15 };
+
+// Coefficients for source bytes 0 to 10
+//extern "C"
+TALIGN16(const uint8, madd01[16]) =
+  { 3, 1, 2, 2, 1, 3, 3, 1, 2, 2, 1, 3, 3, 1, 2, 2 };
+
+// Coefficients for source bytes 10 to 21
+//extern "C"
+TALIGN16(const uint8, madd11[16]) =
+  { 1, 3, 3, 1, 2, 2, 1, 3, 3, 1, 2, 2, 1, 3, 3, 1 };
+
+// Coefficients for source bytes 21 to 31
+//extern "C"
+TALIGN16(const uint8, madd21[16]) =
+  { 2, 2, 1, 3, 3, 1, 2, 2, 1, 3, 3, 1, 2, 2, 1, 3 };
+
+// Coefficients for source bytes 21 to 31
+//extern "C"
+TALIGN16(const int16, round34[8]) =
+  { 2, 2, 2, 2, 2, 2, 2, 2 };
+
+//extern "C"
+TALIGN16(const uint8, shuf38a[16]) =
+  { 0, 3, 6, 8, 11, 14, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 };
+
+//extern "C"
+TALIGN16(const uint8, shuf38b[16]) =
+  { 128, 128, 128, 128, 128, 128, 0, 3, 6, 8, 11, 14, 128, 128, 128, 128 };
+
+// Arrange words 0,3,6 into 0,1,2
+//extern "C"
+TALIGN16(const uint8, shufac0[16]) =
+  { 0, 1, 6, 7, 12, 13, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 };
+
+// Arrange words 0,3,6 into 3,4,5
+//extern "C"
+TALIGN16(const uint8, shufac3[16]) =
+  { 128, 128, 128, 128, 128, 128, 0, 1, 6, 7, 12, 13, 128, 128, 128, 128 };
+
+// Scaling values for boxes of 3x3 and 2x3
+//extern "C"
+TALIGN16(const uint16, scaleac3[8]) =
+  { 65536 / 9, 65536 / 9, 65536 / 6, 65536 / 9, 65536 / 9, 65536 / 6, 0, 0 };
+
+// Arrange first value for pixels 0,1,2,3,4,5
+//extern "C"
+TALIGN16(const uint8, shufab0[16]) =
+  { 0, 128, 3, 128, 6, 128, 8, 128, 11, 128, 14, 128, 128, 128, 128, 128 };
+
+// Arrange second value for pixels 0,1,2,3,4,5
+//extern "C"
+TALIGN16(const uint8, shufab1[16]) =
+  { 1, 128, 4, 128, 7, 128, 9, 128, 12, 128, 15, 128, 128, 128, 128, 128 };
+
+// Arrange third value for pixels 0,1,2,3,4,5
+//extern "C"
+TALIGN16(const uint8, shufab2[16]) =
+  { 2, 128, 5, 128, 128, 128, 10, 128, 13, 128, 128, 128, 128, 128, 128, 128 };
+
+// Scaling values for boxes of 3x2 and 2x2
+//extern "C"
+TALIGN16(const uint16, scaleab2[8]) =
+  { 65536 / 3, 65536 / 3, 65536 / 2, 65536 / 3, 65536 / 3, 65536 / 2, 0, 0 };
+#endif
+
+#if defined(_M_IX86) && !defined(YUV_DISABLE_ASM)
+
+#define HAS_SCALEROWDOWN2_SSE2
+// Reads 32 pixels, throws half away and writes 16 pixels.
+// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 16 byte aligned.
+__declspec(naked)
+static void ScaleRowDown2_SSE2(const uint8* src_ptr, int src_stride,
+                               uint8* dst_ptr, int dst_width) {
+  __asm {
+    mov        eax, [esp + 4]        // src_ptr
+                                     // src_stride ignored
+    mov        edx, [esp + 12]       // dst_ptr
+    mov        ecx, [esp + 16]       // dst_width
+    pcmpeqb    xmm5, xmm5            // generate mask 0x00ff00ff
+    psrlw      xmm5, 8
+
+  wloop:
+    movdqa     xmm0, [eax]
+    movdqa     xmm1, [eax + 16]
+    lea        eax,  [eax + 32]
+    pand       xmm0, xmm5
+    pand       xmm1, xmm5
+    packuswb   xmm0, xmm1
+    movdqa     [edx], xmm0
+    lea        edx, [edx + 16]
+    sub        ecx, 16
+    ja         wloop
+
+    ret
+  }
+}
+// Blends 32x2 rectangle to 16x1.
+// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 16 byte aligned.
+__declspec(naked)
+void ScaleRowDown2Int_SSE2(const uint8* src_ptr, int src_stride,
+                           uint8* dst_ptr, int dst_width) {
+  __asm {
+    push       esi
+    mov        eax, [esp + 4 + 4]    // src_ptr
+    mov        esi, [esp + 4 + 8]    // src_stride
+    mov        edx, [esp + 4 + 12]   // dst_ptr
+    mov        ecx, [esp + 4 + 16]   // dst_width
+    pcmpeqb    xmm5, xmm5            // generate mask 0x00ff00ff
+    psrlw      xmm5, 8
+
+  wloop:
+    movdqa     xmm0, [eax]
+    movdqa     xmm1, [eax + 16]
+    movdqa     xmm2, [eax + esi]
+    movdqa     xmm3, [eax + esi + 16]
+    lea        eax,  [eax + 32]
+    pavgb      xmm0, xmm2            // average rows
+    pavgb      xmm1, xmm3
+
+    movdqa     xmm2, xmm0            // average columns (32 to 16 pixels)
+    psrlw      xmm0, 8
+    movdqa     xmm3, xmm1
+    psrlw      xmm1, 8
+    pand       xmm2, xmm5
+    pand       xmm3, xmm5
+    pavgw      xmm0, xmm2
+    pavgw      xmm1, xmm3
+    packuswb   xmm0, xmm1
+
+    movdqa     [edx], xmm0
+    lea        edx, [edx + 16]
+    sub        ecx, 16
+    ja         wloop
+
+    pop        esi
+    ret
+  }
+}
+
+#define HAS_SCALEROWDOWN4_SSE2
+// Point samples 32 pixels to 8 pixels.
+// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 8 byte aligned.
+__declspec(naked)
+static void ScaleRowDown4_SSE2(const uint8* src_ptr, int src_stride,
+                               uint8* dst_ptr, int dst_width) {
+  __asm {
+    pushad
+    mov        esi, [esp + 32 + 4]   // src_ptr
+                                     // src_stride ignored
+    mov        edi, [esp + 32 + 12]  // dst_ptr
+    mov        ecx, [esp + 32 + 16]  // dst_width
+    pcmpeqb    xmm5, xmm5            // generate mask 0x000000ff
+    psrld      xmm5, 24
+
+  wloop:
+    movdqa     xmm0, [esi]
+    movdqa     xmm1, [esi + 16]
+    lea        esi,  [esi + 32]
+    pand       xmm0, xmm5
+    pand       xmm1, xmm5
+    packuswb   xmm0, xmm1
+    packuswb   xmm0, xmm0
+    movq       qword ptr [edi], xmm0
+    lea        edi, [edi + 8]
+    sub        ecx, 8
+    ja         wloop
+
+    popad
+    ret
+  }
+}
+
+// Blends 32x4 rectangle to 8x1.
+// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 8 byte aligned.
+__declspec(naked)
+static void ScaleRowDown4Int_SSE2(const uint8* src_ptr, int src_stride,
+                                  uint8* dst_ptr, int dst_width) {
+  __asm {
+    pushad
+    mov        esi, [esp + 32 + 4]   // src_ptr
+    mov        ebx, [esp + 32 + 8]   // src_stride
+    mov        edi, [esp + 32 + 12]  // dst_ptr
+    mov        ecx, [esp + 32 + 16]  // dst_width
+    pcmpeqb    xmm7, xmm7            // generate mask 0x00ff00ff
+    psrlw      xmm7, 8
+    lea        edx, [ebx + ebx * 2]  // src_stride * 3
+
+  wloop:
+    movdqa     xmm0, [esi]
+    movdqa     xmm1, [esi + 16]
+    movdqa     xmm2, [esi + ebx]
+    movdqa     xmm3, [esi + ebx + 16]
+    pavgb      xmm0, xmm2            // average rows
+    pavgb      xmm1, xmm3
+    movdqa     xmm2, [esi + ebx * 2]
+    movdqa     xmm3, [esi + ebx * 2 + 16]
+    movdqa     xmm4, [esi + edx]
+    movdqa     xmm5, [esi + edx + 16]
+    lea        esi, [esi + 32]
+    pavgb      xmm2, xmm4
+    pavgb      xmm3, xmm5
+    pavgb      xmm0, xmm2
+    pavgb      xmm1, xmm3
+
+    movdqa     xmm2, xmm0            // average columns (32 to 16 pixels)
+    psrlw      xmm0, 8
+    movdqa     xmm3, xmm1
+    psrlw      xmm1, 8
+    pand       xmm2, xmm7
+    pand       xmm3, xmm7
+    pavgw      xmm0, xmm2
+    pavgw      xmm1, xmm3
+    packuswb   xmm0, xmm1
+
+    movdqa     xmm2, xmm0            // average columns (16 to 8 pixels)
+    psrlw      xmm0, 8
+    pand       xmm2, xmm7
+    pavgw      xmm0, xmm2
+    packuswb   xmm0, xmm0
+
+    movq       qword ptr [edi], xmm0
+    lea        edi, [edi + 8]
+    sub        ecx, 8
+    ja         wloop
+
+    popad
+    ret
+  }
+}
+
+#define HAS_SCALEROWDOWN8_SSE2
+// Point samples 32 pixels to 4 pixels.
+// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 4 byte aligned.
+__declspec(naked)
+static void ScaleRowDown8_SSE2(const uint8* src_ptr, int src_stride,
+                               uint8* dst_ptr, int dst_width) {
+  __asm {
+    pushad
+    mov        esi, [esp + 32 + 4]   // src_ptr
+                                     // src_stride ignored
+    mov        edi, [esp + 32 + 12]  // dst_ptr
+    mov        ecx, [esp + 32 + 16]  // dst_width
+    pcmpeqb    xmm5, xmm5            // generate mask isolating 1 src 8 bytes
+    psrlq      xmm5, 56
+
+  wloop:
+    movdqa     xmm0, [esi]
+    movdqa     xmm1, [esi + 16]
+    lea        esi,  [esi + 32]
+    pand       xmm0, xmm5
+    pand       xmm1, xmm5
+    packuswb   xmm0, xmm1  // 32->16
+    packuswb   xmm0, xmm0  // 16->8
+    packuswb   xmm0, xmm0  // 8->4
+    movd       dword ptr [edi], xmm0
+    lea        edi, [edi + 4]
+    sub        ecx, 4
+    ja         wloop
+
+    popad
+    ret
+  }
+}
+
+// Blends 32x8 rectangle to 4x1.
+// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 4 byte aligned.
+__declspec(naked)
+static void ScaleRowDown8Int_SSE2(const uint8* src_ptr, int src_stride,
+                                  uint8* dst_ptr, int dst_width) {
+  __asm {
+    pushad
+    mov        esi, [esp + 32 + 4]   // src_ptr
+    mov        ebx, [esp + 32 + 8]   // src_stride
+    mov        edi, [esp + 32 + 12]  // dst_ptr
+    mov        ecx, [esp + 32 + 16]  // dst_width
+    lea        edx, [ebx + ebx * 2]  // src_stride * 3
+    pxor       xmm7, xmm7
+
+  wloop:
+    movdqa     xmm0, [esi]           // average 8 rows to 1
+    movdqa     xmm1, [esi + 16]
+    movdqa     xmm2, [esi + ebx]
+    movdqa     xmm3, [esi + ebx + 16]
+    pavgb      xmm0, xmm2
+    pavgb      xmm1, xmm3
+    movdqa     xmm2, [esi + ebx * 2]
+    movdqa     xmm3, [esi + ebx * 2 + 16]
+    movdqa     xmm4, [esi + edx]
+    movdqa     xmm5, [esi + edx + 16]
+    lea        ebp, [esi + ebx * 4]
+    lea        esi, [esi + 32]
+    pavgb      xmm2, xmm4
+    pavgb      xmm3, xmm5
+    pavgb      xmm0, xmm2
+    pavgb      xmm1, xmm3
+
+    movdqa     xmm2, [ebp]
+    movdqa     xmm3, [ebp + 16]
+    movdqa     xmm4, [ebp + ebx]
+    movdqa     xmm5, [ebp + ebx + 16]
+    pavgb      xmm2, xmm4
+    pavgb      xmm3, xmm5
+    movdqa     xmm4, [ebp + ebx * 2]
+    movdqa     xmm5, [ebp + ebx * 2 + 16]
+    movdqa     xmm6, [ebp + edx]
+    pavgb      xmm4, xmm6
+    movdqa     xmm6, [ebp + edx + 16]
+    pavgb      xmm5, xmm6
+    pavgb      xmm2, xmm4
+    pavgb      xmm3, xmm5
+    pavgb      xmm0, xmm2
+    pavgb      xmm1, xmm3
+
+    psadbw     xmm0, xmm7            // average 32 pixels to 4
+    psadbw     xmm1, xmm7
+    pshufd     xmm0, xmm0, 0xd8      // x1x0 -> xx01
+    pshufd     xmm1, xmm1, 0x8d      // x3x2 -> 32xx
+    por        xmm0, xmm1            //      -> 3201
+    psrlw      xmm0, 3
+    packuswb   xmm0, xmm0
+    packuswb   xmm0, xmm0
+    movd       dword ptr [edi], xmm0
+
+    lea        edi, [edi + 4]
+    sub        ecx, 4
+    ja         wloop
+
+    popad
+    ret
+  }
+}
+
+#define HAS_SCALEROWDOWN34_SSSE3
+// Point samples 32 pixels to 24 pixels.
+// Produces three 8 byte values.  For each 8 bytes, 16 bytes are read.
+// Then shuffled to do the scaling.
+
+// Note that movdqa+palign may be better than movdqu.
+// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 8 byte aligned.
+__declspec(naked)
+static void ScaleRowDown34_SSSE3(const uint8* src_ptr, int src_stride,
+                                 uint8* dst_ptr, int dst_width) {
+  __asm {
+    pushad
+    mov        esi, [esp + 32 + 4]   // src_ptr
+                                     // src_stride ignored
+    mov        edi, [esp + 32 + 12]  // dst_ptr
+    mov        ecx, [esp + 32 + 16]  // dst_width
+    movdqa     xmm3, _shuf0
+    movdqa     xmm4, _shuf1
+    movdqa     xmm5, _shuf2
+
+  wloop:
+    movdqa     xmm0, [esi]
+    movdqa     xmm1, [esi + 16]
+    lea        esi,  [esi + 32]
+    movdqa     xmm2, xmm1
+    palignr    xmm1, xmm0, 8
+    pshufb     xmm0, xmm3
+    pshufb     xmm1, xmm4
+    pshufb     xmm2, xmm5
+    movq       qword ptr [edi], xmm0
+    movq       qword ptr [edi + 8], xmm1
+    movq       qword ptr [edi + 16], xmm2
+    lea        edi, [edi + 24]
+    sub        ecx, 24
+    ja         wloop
+
+    popad
+    ret
+  }
+}
+
+// Blends 32x2 rectangle to 24x1
+// Produces three 8 byte values.  For each 8 bytes, 16 bytes are read.
+// Then shuffled to do the scaling.
+
+// Register usage:
+// xmm0 src_row 0
+// xmm1 src_row 1
+// xmm2 shuf 0
+// xmm3 shuf 1
+// xmm4 shuf 2
+// xmm5 madd 0
+// xmm6 madd 1
+// xmm7 round34
+
+// Note that movdqa+palign may be better than movdqu.
+// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 8 byte aligned.
+__declspec(naked)
+static void ScaleRowDown34_1_Int_SSSE3(const uint8* src_ptr, int src_stride,
+                                       uint8* dst_ptr, int dst_width) {
+  __asm {
+    pushad
+    mov        esi, [esp + 32 + 4]   // src_ptr
+    mov        ebx, [esp + 32 + 8]   // src_stride
+    mov        edi, [esp + 32 + 12]  // dst_ptr
+    mov        ecx, [esp + 32 + 16]  // dst_width
+    movdqa     xmm2, _shuf01
+    movdqa     xmm3, _shuf11
+    movdqa     xmm4, _shuf21
+    movdqa     xmm5, _madd01
+    movdqa     xmm6, _madd11
+    movdqa     xmm7, _round34
+
+  wloop:
+    movdqa     xmm0, [esi]           // pixels 0..7
+    movdqa     xmm1, [esi+ebx]
+    pavgb      xmm0, xmm1
+    pshufb     xmm0, xmm2
+    pmaddubsw  xmm0, xmm5
+    paddsw     xmm0, xmm7
+    psrlw      xmm0, 2
+    packuswb   xmm0, xmm0
+    movq       qword ptr [edi], xmm0
+    movdqu     xmm0, [esi+8]         // pixels 8..15
+    movdqu     xmm1, [esi+ebx+8]
+    pavgb      xmm0, xmm1
+    pshufb     xmm0, xmm3
+    pmaddubsw  xmm0, xmm6
+    paddsw     xmm0, xmm7
+    psrlw      xmm0, 2
+    packuswb   xmm0, xmm0
+    movq       qword ptr [edi+8], xmm0
+    movdqa     xmm0, [esi+16]        // pixels 16..23
+    movdqa     xmm1, [esi+ebx+16]
+    lea        esi, [esi+32]
+    pavgb      xmm0, xmm1
+    pshufb     xmm0, xmm4
+    movdqa     xmm1, _madd21
+    pmaddubsw  xmm0, xmm1
+    paddsw     xmm0, xmm7
+    psrlw      xmm0, 2
+    packuswb   xmm0, xmm0
+    movq       qword ptr [edi+16], xmm0
+    lea        edi, [edi+24]
+    sub        ecx, 24
+    ja         wloop
+
+    popad
+    ret
+  }
+}
+
+// Note that movdqa+palign may be better than movdqu.
+// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 8 byte aligned.
+__declspec(naked)
+static void ScaleRowDown34_0_Int_SSSE3(const uint8* src_ptr, int src_stride,
+                                       uint8* dst_ptr, int dst_width) {
+  __asm {
+    pushad
+    mov        esi, [esp + 32 + 4]   // src_ptr
+    mov        ebx, [esp + 32 + 8]   // src_stride
+    mov        edi, [esp + 32 + 12]  // dst_ptr
+    mov        ecx, [esp + 32 + 16]  // dst_width
+    movdqa     xmm2, _shuf01
+    movdqa     xmm3, _shuf11
+    movdqa     xmm4, _shuf21
+    movdqa     xmm5, _madd01
+    movdqa     xmm6, _madd11
+    movdqa     xmm7, _round34
+
+  wloop:
+    movdqa     xmm0, [esi]           // pixels 0..7
+    movdqa     xmm1, [esi+ebx]
+    pavgb      xmm1, xmm0
+    pavgb      xmm0, xmm1
+    pshufb     xmm0, xmm2
+    pmaddubsw  xmm0, xmm5
+    paddsw     xmm0, xmm7
+    psrlw      xmm0, 2
+    packuswb   xmm0, xmm0
+    movq       qword ptr [edi], xmm0
+    movdqu     xmm0, [esi+8]         // pixels 8..15
+    movdqu     xmm1, [esi+ebx+8]
+    pavgb      xmm1, xmm0
+    pavgb      xmm0, xmm1
+    pshufb     xmm0, xmm3
+    pmaddubsw  xmm0, xmm6
+    paddsw     xmm0, xmm7
+    psrlw      xmm0, 2
+    packuswb   xmm0, xmm0
+    movq       qword ptr [edi+8], xmm0
+    movdqa     xmm0, [esi+16]        // pixels 16..23
+    movdqa     xmm1, [esi+ebx+16]
+    lea        esi, [esi+32]
+    pavgb      xmm1, xmm0
+    pavgb      xmm0, xmm1
+    pshufb     xmm0, xmm4
+    movdqa     xmm1, _madd21
+    pmaddubsw  xmm0, xmm1
+    paddsw     xmm0, xmm7
+    psrlw      xmm0, 2
+    packuswb   xmm0, xmm0
+    movq       qword ptr [edi+16], xmm0
+    lea        edi, [edi+24]
+    sub        ecx, 24
+    ja         wloop
+
+    popad
+    ret
+  }
+}
+
+#define HAS_SCALEROWDOWN38_SSSE3
+// 3/8 point sampler
+
+// Scale 32 pixels to 12
+__declspec(naked)
+static void ScaleRowDown38_SSSE3(const uint8* src_ptr, int src_stride,
+                                 uint8* dst_ptr, int dst_width) {
+  __asm {
+    pushad
+    mov        esi, [esp + 32 + 4]   // src_ptr
+    mov        edx, [esp + 32 + 8]   // src_stride
+    mov        edi, [esp + 32 + 12]  // dst_ptr
+    mov        ecx, [esp + 32 + 16]  // dst_width
+    movdqa     xmm4, _shuf38a
+    movdqa     xmm5, _shuf38b
+
+  xloop:
+    movdqa     xmm0, [esi]           // 16 pixels -> 0,1,2,3,4,5
+    movdqa     xmm1, [esi + 16]      // 16 pixels -> 6,7,8,9,10,11
+    lea        esi, [esi + 32]
+    pshufb     xmm0, xmm4
+    pshufb     xmm1, xmm5
+    paddusb    xmm0, xmm1
+
+    movq       qword ptr [edi], xmm0 // write 12 pixels
+    movhlps    xmm1, xmm0
+    movd       [edi + 8], xmm1
+    lea        edi, [edi + 12]
+    sub        ecx, 12
+    ja         xloop
+
+    popad
+    ret
+  }
+}
+
+// Scale 16x3 pixels to 6x1 with interpolation
+__declspec(naked)
+static void ScaleRowDown38_3_Int_SSSE3(const uint8* src_ptr, int src_stride,
+                                       uint8* dst_ptr, int dst_width) {
+  __asm {
+    pushad
+    mov        esi, [esp + 32 + 4]   // src_ptr
+    mov        edx, [esp + 32 + 8]   // src_stride
+    mov        edi, [esp + 32 + 12]  // dst_ptr
+    mov        ecx, [esp + 32 + 16]  // dst_width
+    movdqa     xmm4, _shufac0
+    movdqa     xmm5, _shufac3
+    movdqa     xmm6, _scaleac3
+    pxor       xmm7, xmm7
+
+  xloop:
+    movdqa     xmm0, [esi]           // sum up 3 rows into xmm0/1
+    movdqa     xmm2, [esi + edx]
+    movhlps    xmm1, xmm0
+    movhlps    xmm3, xmm2
+    punpcklbw  xmm0, xmm7
+    punpcklbw  xmm1, xmm7
+    punpcklbw  xmm2, xmm7
+    punpcklbw  xmm3, xmm7
+    paddusw    xmm0, xmm2
+    paddusw    xmm1, xmm3
+    movdqa     xmm2, [esi + edx * 2]
+    lea        esi, [esi + 16]
+    movhlps    xmm3, xmm2
+    punpcklbw  xmm2, xmm7
+    punpcklbw  xmm3, xmm7
+    paddusw    xmm0, xmm2
+    paddusw    xmm1, xmm3
+
+    movdqa     xmm2, xmm0            // 8 pixels -> 0,1,2 of xmm2
+    psrldq     xmm0, 2
+    paddusw    xmm2, xmm0
+    psrldq     xmm0, 2
+    paddusw    xmm2, xmm0
+    pshufb     xmm2, xmm4
+
+    movdqa     xmm3, xmm1            // 8 pixels -> 3,4,5 of xmm2
+    psrldq     xmm1, 2
+    paddusw    xmm3, xmm1
+    psrldq     xmm1, 2
+    paddusw    xmm3, xmm1
+    pshufb     xmm3, xmm5
+    paddusw    xmm2, xmm3
+
+    pmulhuw    xmm2, xmm6            // divide by 9,9,6, 9,9,6
+    packuswb   xmm2, xmm2
+
+    movd       [edi], xmm2           // write 6 pixels
+    pextrw     eax, xmm2, 2
+    mov        [edi + 4], ax
+    lea        edi, [edi + 6]
+    sub        ecx, 6
+    ja         xloop
+
+    popad
+    ret
+  }
+}
+
+// Scale 16x2 pixels to 6x1 with interpolation
+__declspec(naked)
+static void ScaleRowDown38_2_Int_SSSE3(const uint8* src_ptr, int src_stride,
+                                       uint8* dst_ptr, int dst_width) {
+  __asm {
+    pushad
+    mov        esi, [esp + 32 + 4]   // src_ptr
+    mov        edx, [esp + 32 + 8]   // src_stride
+    mov        edi, [esp + 32 + 12]  // dst_ptr
+    mov        ecx, [esp + 32 + 16]  // dst_width
+    movdqa     xmm4, _shufab0
+    movdqa     xmm5, _shufab1
+    movdqa     xmm6, _shufab2
+    movdqa     xmm7, _scaleab2
+
+  xloop:
+    movdqa     xmm2, [esi]           // average 2 rows into xmm2
+    pavgb      xmm2, [esi + edx]
+    lea        esi, [esi + 16]
+
+    movdqa     xmm0, xmm2            // 16 pixels -> 0,1,2,3,4,5 of xmm0
+    pshufb     xmm0, xmm4
+    movdqa     xmm1, xmm2
+    pshufb     xmm1, xmm5
+    paddusw    xmm0, xmm1
+    pshufb     xmm2, xmm6
+    paddusw    xmm0, xmm2
+
+    pmulhuw    xmm0, xmm7            // divide by 3,3,2, 3,3,2
+    packuswb   xmm0, xmm0
+
+    movd       [edi], xmm0           // write 6 pixels
+    pextrw     eax, xmm0, 2
+    mov        [edi + 4], ax
+    lea        edi, [edi + 6]
+    sub        ecx, 6
+    ja         xloop
+
+    popad
+    ret
+  }
+}
+
+#define HAS_SCALEADDROWS_SSE2
+
+// Reads 8xN bytes and produces 16 shorts at a time.
+__declspec(naked)
+static void ScaleAddRows_SSE2(const uint8* src_ptr, int src_stride,
+                              uint16* dst_ptr, int src_width,
+                              int src_height) {
+  __asm {
+    pushad
+    mov        esi, [esp + 32 + 4]   // src_ptr
+    mov        edx, [esp + 32 + 8]   // src_stride
+    mov        edi, [esp + 32 + 12]  // dst_ptr
+    mov        ecx, [esp + 32 + 16]  // dst_width
+    mov        ebx, [esp + 32 + 20]  // height
+    pxor       xmm5, xmm5
+    dec        ebx
+
+  xloop:
+    // first row
+    movdqa     xmm2, [esi]
+    lea        eax, [esi + edx]
+    movhlps    xmm3, xmm2
+    mov        ebp, ebx
+    punpcklbw  xmm2, xmm5
+    punpcklbw  xmm3, xmm5
+
+    // sum remaining rows
+  yloop:
+    movdqa     xmm0, [eax]       // read 16 pixels
+    lea        eax, [eax + edx]  // advance to next row
+    movhlps    xmm1, xmm0
+    punpcklbw  xmm0, xmm5
+    punpcklbw  xmm1, xmm5
+    paddusw    xmm2, xmm0        // sum 16 words
+    paddusw    xmm3, xmm1
+    sub        ebp, 1
+    ja         yloop
+
+    movdqa     [edi], xmm2
+    movdqa     [edi + 16], xmm3
+    lea        edi, [edi + 32]
+    lea        esi, [esi + 16]
+
+    sub        ecx, 16
+    ja         xloop
+
+    popad
+    ret
+  }
+}
+
+// Bilinear row filtering combines 16x2 -> 16x1. SSE2 version.
+#define HAS_SCALEFILTERROWS_SSE2
+__declspec(naked)
+static void ScaleFilterRows_SSE2(uint8* dst_ptr, const uint8* src_ptr,
+                                 int src_stride, int dst_width,
+                                 int source_y_fraction) {
+  __asm {
+    push       esi
+    push       edi
+    mov        edi, [esp + 8 + 4]   // dst_ptr
+    mov        esi, [esp + 8 + 8]   // src_ptr
+    mov        edx, [esp + 8 + 12]  // src_stride
+    mov        ecx, [esp + 8 + 16]  // dst_width
+    mov        eax, [esp + 8 + 20]  // source_y_fraction (0..255)
+    cmp        eax, 0
+    je         xloop1
+    cmp        eax, 128
+    je         xloop2
+
+    movd       xmm6, eax            // xmm6 = y fraction
+    punpcklwd  xmm6, xmm6
+    pshufd     xmm6, xmm6, 0
+    neg        eax                  // xmm5 = 256 - y fraction
+    add        eax, 256
+    movd       xmm5, eax
+    punpcklwd  xmm5, xmm5
+    pshufd     xmm5, xmm5, 0
+    pxor       xmm7, xmm7
+
+  xloop:
+    movdqa     xmm0, [esi]
+    movdqa     xmm2, [esi + edx]
+    lea        esi, [esi + 16]
+    movdqa     xmm1, xmm0
+    movdqa     xmm3, xmm2
+    punpcklbw  xmm0, xmm7
+    punpcklbw  xmm2, xmm7
+    punpckhbw  xmm1, xmm7
+    punpckhbw  xmm3, xmm7
+    pmullw     xmm0, xmm5           // scale row 0
+    pmullw     xmm1, xmm5
+    pmullw     xmm2, xmm6           // scale row 1
+    pmullw     xmm3, xmm6
+    paddusw    xmm0, xmm2           // sum rows
+    paddusw    xmm1, xmm3
+    psrlw      xmm0, 8
+    psrlw      xmm1, 8
+    packuswb   xmm0, xmm1
+    movdqa     [edi], xmm0
+    lea        edi, [edi + 16]
+    sub        ecx, 16
+    ja         xloop
+
+    mov        al, [edi - 1]
+    mov        [edi], al
+    pop        edi
+    pop        esi
+    ret
+
+  xloop1:
+    movdqa     xmm0, [esi]
+    lea        esi, [esi + 16]
+    movdqa     [edi], xmm0
+    lea        edi, [edi + 16]
+    sub        ecx, 16
+    ja         xloop1
+
+    mov        al, [edi - 1]
+    mov        [edi], al
+    pop        edi
+    pop        esi
+    ret
+
+  xloop2:
+    movdqa     xmm0, [esi]
+    movdqa     xmm2, [esi + edx]
+    lea        esi, [esi + 16]
+    pavgb      xmm0, xmm2
+    movdqa     [edi], xmm0
+    lea        edi, [edi + 16]
+    sub        ecx, 16
+    ja         xloop2
+
+    mov        al, [edi - 1]
+    mov        [edi], al
+    pop        edi
+    pop        esi
+    ret
+  }
+}
+
+// Bilinear row filtering combines 16x2 -> 16x1. SSSE3 version.
+#define HAS_SCALEFILTERROWS_SSSE3
+__declspec(naked)
+static void ScaleFilterRows_SSSE3(uint8* dst_ptr, const uint8* src_ptr,
+                                  int src_stride, int dst_width,
+                                  int source_y_fraction) {
+  __asm {
+    push       esi
+    push       edi
+    mov        edi, [esp + 8 + 4]   // dst_ptr
+    mov        esi, [esp + 8 + 8]   // src_ptr
+    mov        edx, [esp + 8 + 12]  // src_stride
+    mov        ecx, [esp + 8 + 16]  // dst_width
+    mov        eax, [esp + 8 + 20]  // source_y_fraction (0..255)
+    cmp        eax, 0
+    je         xloop1
+    cmp        eax, 128
+    je         xloop2
+
+    shr        eax, 1
+    mov        ah,al
+    neg        al
+    add        al, 128
+    movd       xmm5, eax
+    punpcklwd  xmm5, xmm5
+    pshufd     xmm5, xmm5, 0
+
+  xloop:
+    movdqa     xmm0, [esi]
+    movdqa     xmm2, [esi + edx]
+    lea        esi, [esi + 16]
+    movdqa     xmm1, xmm0
+    punpcklbw  xmm0, xmm2
+    punpckhbw  xmm1, xmm2
+    pmaddubsw  xmm0, xmm5
+    pmaddubsw  xmm1, xmm5
+    psrlw      xmm0, 7
+    psrlw      xmm1, 7
+    packuswb   xmm0, xmm1
+    movdqa     [edi], xmm0
+    lea        edi, [edi + 16]
+    sub        ecx, 16
+    ja         xloop
+
+    mov        al, [edi - 1]
+    mov        [edi], al
+    pop        edi
+    pop        esi
+    ret
+
+  xloop1:
+    movdqa     xmm0, [esi]
+    lea        esi, [esi + 16]
+    movdqa     [edi], xmm0
+    lea        edi, [edi + 16]
+    sub        ecx, 16
+    ja         xloop1
+
+    mov        al, [edi - 1]
+    mov        [edi], al
+    pop        edi
+    pop        esi
+    ret
+
+  xloop2:
+    movdqa     xmm0, [esi]
+    movdqa     xmm2, [esi + edx]
+    lea        esi, [esi + 16]
+    pavgb      xmm0, xmm2
+    movdqa     [edi], xmm0
+    lea        edi, [edi + 16]
+    sub        ecx, 16
+    ja         xloop2
+
+    mov        al, [edi - 1]
+    mov        [edi], al
+    pop        edi
+    pop        esi
+    ret
+
+  }
+}
+
+// Note that movdqa+palign may be better than movdqu.
+// Alignment requirement: src_ptr 16 byte aligned, dst_ptr 8 byte aligned.
+__declspec(naked)
+static void ScaleFilterCols34_SSSE3(uint8* dst_ptr, const uint8* src_ptr,
+                                    int dst_width) {
+  __asm {
+    mov        edx, [esp + 4]    // dst_ptr
+    mov        eax, [esp + 8]    // src_ptr
+    mov        ecx, [esp + 12]   // dst_width
+    movdqa     xmm1, _round34
+    movdqa     xmm2, _shuf01
+    movdqa     xmm3, _shuf11
+    movdqa     xmm4, _shuf21
+    movdqa     xmm5, _madd01
+    movdqa     xmm6, _madd11
+    movdqa     xmm7, _madd21
+
+  wloop:
+    movdqa     xmm0, [eax]           // pixels 0..7
+    pshufb     xmm0, xmm2
+    pmaddubsw  xmm0, xmm5
+    paddsw     xmm0, xmm1
+    psrlw      xmm0, 2
+    packuswb   xmm0, xmm0
+    movq       qword ptr [edx], xmm0
+    movdqu     xmm0, [eax+8]         // pixels 8..15
+    pshufb     xmm0, xmm3
+    pmaddubsw  xmm0, xmm6
+    paddsw     xmm0, xmm1
+    psrlw      xmm0, 2
+    packuswb   xmm0, xmm0
+    movq       qword ptr [edx+8], xmm0
+    movdqa     xmm0, [eax+16]        // pixels 16..23
+    lea        eax, [eax+32]
+    pshufb     xmm0, xmm4
+    pmaddubsw  xmm0, xmm7
+    paddsw     xmm0, xmm1
+    psrlw      xmm0, 2
+    packuswb   xmm0, xmm0
+    movq       qword ptr [edx+16], xmm0
+    lea        edx, [edx+24]
+    sub        ecx, 24
+    ja         wloop
+    ret
+  }
+}
+
+#elif (defined(__x86_64__) || defined(__i386__)) && !defined(YUV_DISABLE_ASM)
+
+// GCC versions of row functions are verbatim conversions from Visual C.
+// Generated using gcc disassembly on Visual C object file:
+// objdump -D yuvscaler.obj >yuvscaler.txt
+#define HAS_SCALEROWDOWN2_SSE2
+static void ScaleRowDown2_SSE2(const uint8* src_ptr, int src_stride,
+                               uint8* dst_ptr, int dst_width) {
+  asm volatile (
+  "pcmpeqb    %%xmm5,%%xmm5                    \n"
+  "psrlw      $0x8,%%xmm5                      \n"
+"1:"
+  "movdqa     (%0),%%xmm0                      \n"
+  "movdqa     0x10(%0),%%xmm1                  \n"
+  "lea        0x20(%0),%0                      \n"
+  "pand       %%xmm5,%%xmm0                    \n"
+  "pand       %%xmm5,%%xmm1                    \n"
+  "packuswb   %%xmm1,%%xmm0                    \n"
+  "movdqa     %%xmm0,(%1)                      \n"
+  "lea        0x10(%1),%1                      \n"
+  "sub        $0x10,%2                         \n"
+  "ja         1b                               \n"
+  : "+r"(src_ptr),    // %0
+    "+r"(dst_ptr),    // %1
+    "+r"(dst_width)   // %2
+  :
+  : "memory", "cc"
+);
+}
+
+static void ScaleRowDown2Int_SSE2(const uint8* src_ptr, int src_stride,
+                                  uint8* dst_ptr, int dst_width) {
+  asm volatile (
+  "pcmpeqb    %%xmm5,%%xmm5                    \n"
+  "psrlw      $0x8,%%xmm5                      \n"
+"1:"
+  "movdqa     (%0),%%xmm0                      \n"
+  "movdqa     0x10(%0),%%xmm1                  \n"
+  "movdqa     (%0,%3,1),%%xmm2                 \n"
+  "movdqa     0x10(%0,%3,1),%%xmm3             \n"
+  "lea        0x20(%0),%0                      \n"
+  "pavgb      %%xmm2,%%xmm0                    \n"
+  "pavgb      %%xmm3,%%xmm1                    \n"
+  "movdqa     %%xmm0,%%xmm2                    \n"
+  "psrlw      $0x8,%%xmm0                      \n"
+  "movdqa     %%xmm1,%%xmm3                    \n"
+  "psrlw      $0x8,%%xmm1                      \n"
+  "pand       %%xmm5,%%xmm2                    \n"
+  "pand       %%xmm5,%%xmm3                    \n"
+  "pavgw      %%xmm2,%%xmm0                    \n"
+  "pavgw      %%xmm3,%%xmm1                    \n"
+  "packuswb   %%xmm1,%%xmm0                    \n"
+  "movdqa     %%xmm0,(%1)                      \n"
+  "lea        0x10(%1),%1                      \n"
+  "sub        $0x10,%2                         \n"
+  "ja         1b                               \n"
+  : "+r"(src_ptr),    // %0
+    "+r"(dst_ptr),    // %1
+    "+r"(dst_width)   // %2
+  : "r"((intptr_t)(src_stride))   // %3
+  : "memory", "cc"
+);
+}
+
+#define HAS_SCALEROWDOWN4_SSE2
+static void ScaleRowDown4_SSE2(const uint8* src_ptr, int src_stride,
+                               uint8* dst_ptr, int dst_width) {
+  asm volatile (
+  "pcmpeqb    %%xmm5,%%xmm5                    \n"
+  "psrld      $0x18,%%xmm5                     \n"
+"1:"
+  "movdqa     (%0),%%xmm0                      \n"
+  "movdqa     0x10(%0),%%xmm1                  \n"
+  "lea        0x20(%0),%0                      \n"
+  "pand       %%xmm5,%%xmm0                    \n"
+  "pand       %%xmm5,%%xmm1                    \n"
+  "packuswb   %%xmm1,%%xmm0                    \n"
+  "packuswb   %%xmm0,%%xmm0                    \n"
+  "movq       %%xmm0,(%1)                      \n"
+  "lea        0x8(%1),%1                       \n"
+  "sub        $0x8,%2                          \n"
+  "ja         1b                               \n"
+  : "+r"(src_ptr),    // %0
+    "+r"(dst_ptr),    // %1
+    "+r"(dst_width)   // %2
+  :
+  : "memory", "cc"
+);
+}
+
+static void ScaleRowDown4Int_SSE2(const uint8* src_ptr, int src_stride,
+                                  uint8* dst_ptr, int dst_width) {
+  intptr_t temp = 0;
+  asm volatile (
+  "pcmpeqb    %%xmm7,%%xmm7                    \n"
+  "psrlw      $0x8,%%xmm7                      \n"
+  "lea        (%4,%4,2),%3                     \n"
+"1:"
+  "movdqa     (%0),%%xmm0                      \n"
+  "movdqa     0x10(%0),%%xmm1                  \n"
+  "movdqa     (%0,%4,1),%%xmm2                 \n"
+  "movdqa     0x10(%0,%4,1),%%xmm3             \n"
+  "pavgb      %%xmm2,%%xmm0                    \n"
+  "pavgb      %%xmm3,%%xmm1                    \n"
+  "movdqa     (%0,%4,2),%%xmm2                 \n"
+  "movdqa     0x10(%0,%4,2),%%xmm3             \n"
+  "movdqa     (%0,%3,1),%%xmm4                 \n"
+  "movdqa     0x10(%0,%3,1),%%xmm5             \n"
+  "lea        0x20(%0),%0                      \n"
+  "pavgb      %%xmm4,%%xmm2                    \n"
+  "pavgb      %%xmm2,%%xmm0                    \n"
+  "pavgb      %%xmm5,%%xmm3                    \n"
+  "pavgb      %%xmm3,%%xmm1                    \n"
+  "movdqa     %%xmm0,%%xmm2                    \n"
+  "psrlw      $0x8,%%xmm0                      \n"
+  "movdqa     %%xmm1,%%xmm3                    \n"
+  "psrlw      $0x8,%%xmm1                      \n"
+  "pand       %%xmm7,%%xmm2                    \n"
+  "pand       %%xmm7,%%xmm3                    \n"
+  "pavgw      %%xmm2,%%xmm0                    \n"
+  "pavgw      %%xmm3,%%xmm1                    \n"
+  "packuswb   %%xmm1,%%xmm0                    \n"
+  "movdqa     %%xmm0,%%xmm2                    \n"
+  "psrlw      $0x8,%%xmm0                      \n"
+  "pand       %%xmm7,%%xmm2                    \n"
+  "pavgw      %%xmm2,%%xmm0                    \n"
+  "packuswb   %%xmm0,%%xmm0                    \n"
+  "movq       %%xmm0,(%1)                      \n"
+  "lea        0x8(%1),%1                       \n"
+  "sub        $0x8,%2                          \n"
+  "ja         1b                               \n"
+  : "+r"(src_ptr),     // %0
+    "+r"(dst_ptr),     // %1
+    "+r"(dst_width),   // %2
+    "+r"(temp)         // %3
+  : "r"((intptr_t)(src_stride))    // %4
+  : "memory", "cc"
+#if defined(__x86_64__)
+    , "xmm6", "xmm7"
+#endif
+);
+}
+
+#define HAS_SCALEROWDOWN8_SSE2
+static void ScaleRowDown8_SSE2(const uint8* src_ptr, int src_stride,
+                               uint8* dst_ptr, int dst_width) {
+  asm volatile (
+  "pcmpeqb    %%xmm5,%%xmm5                    \n"
+  "psrlq      $0x38,%%xmm5                     \n"
+"1:"
+  "movdqa     (%0),%%xmm0                      \n"
+  "movdqa     0x10(%0),%%xmm1                  \n"
+  "lea        0x20(%0),%0                      \n"
+  "pand       %%xmm5,%%xmm0                    \n"
+  "pand       %%xmm5,%%xmm1                    \n"
+  "packuswb   %%xmm1,%%xmm0                    \n"
+  "packuswb   %%xmm0,%%xmm0                    \n"
+  "packuswb   %%xmm0,%%xmm0                    \n"
+  "movd       %%xmm0,(%1)                      \n"
+  "lea        0x4(%1),%1                       \n"
+  "sub        $0x4,%2                          \n"
+  "ja         1b                               \n"
+  : "+r"(src_ptr),    // %0
+    "+r"(dst_ptr),    // %1
+    "+r"(dst_width)   // %2
+  :
+  : "memory", "cc"
+);
+}
+
+#if defined(__i386__)
+void ScaleRowDown8Int_SSE2(const uint8* src_ptr, int src_stride,
+                                      uint8* dst_ptr, int dst_width);
+  asm(
+    DECLARE_FUNCTION(ScaleRowDown8Int_SSE2)
+    "pusha                                     \n"
+    "mov    0x24(%esp),%esi                    \n"
+    "mov    0x28(%esp),%ebx                    \n"
+    "mov    0x2c(%esp),%edi                    \n"
+    "mov    0x30(%esp),%ecx                    \n"
+    "lea    (%ebx,%ebx,2),%edx                 \n"
+    "pxor   %xmm7,%xmm7                        \n"
+
+"1:"
+    "movdqa (%esi),%xmm0                       \n"
+    "movdqa 0x10(%esi),%xmm1                   \n"
+    "movdqa (%esi,%ebx,1),%xmm2                \n"
+    "movdqa 0x10(%esi,%ebx,1),%xmm3            \n"
+    "pavgb  %xmm2,%xmm0                        \n"
+    "pavgb  %xmm3,%xmm1                        \n"
+    "movdqa (%esi,%ebx,2),%xmm2                \n"
+    "movdqa 0x10(%esi,%ebx,2),%xmm3            \n"
+    "movdqa (%esi,%edx,1),%xmm4                \n"
+    "movdqa 0x10(%esi,%edx,1),%xmm5            \n"
+    "lea    (%esi,%ebx,4),%ebp                 \n"
+    "lea    0x20(%esi),%esi                    \n"
+    "pavgb  %xmm4,%xmm2                        \n"
+    "pavgb  %xmm5,%xmm3                        \n"
+    "pavgb  %xmm2,%xmm0                        \n"
+    "pavgb  %xmm3,%xmm1                        \n"
+    "movdqa 0x0(%ebp),%xmm2                    \n"
+    "movdqa 0x10(%ebp),%xmm3                   \n"
+    "movdqa 0x0(%ebp,%ebx,1),%xmm4             \n"
+    "movdqa 0x10(%ebp,%ebx,1),%xmm5            \n"
+    "pavgb  %xmm4,%xmm2                        \n"
+    "pavgb  %xmm5,%xmm3                        \n"
+    "movdqa 0x0(%ebp,%ebx,2),%xmm4             \n"
+    "movdqa 0x10(%ebp,%ebx,2),%xmm5            \n"
+    "movdqa 0x0(%ebp,%edx,1),%xmm6             \n"
+    "pavgb  %xmm6,%xmm4                        \n"
+    "movdqa 0x10(%ebp,%edx,1),%xmm6            \n"
+    "pavgb  %xmm6,%xmm5                        \n"
+    "pavgb  %xmm4,%xmm2                        \n"
+    "pavgb  %xmm5,%xmm3                        \n"
+    "pavgb  %xmm2,%xmm0                        \n"
+    "pavgb  %xmm3,%xmm1                        \n"
+    "psadbw %xmm7,%xmm0                        \n"
+    "psadbw %xmm7,%xmm1                        \n"
+    "pshufd $0xd8,%xmm0,%xmm0                  \n"
+    "pshufd $0x8d,%xmm1,%xmm1                  \n"
+    "por    %xmm1,%xmm0                        \n"
+    "psrlw  $0x3,%xmm0                         \n"
+    "packuswb %xmm0,%xmm0                      \n"
+    "packuswb %xmm0,%xmm0                      \n"
+    "movd   %xmm0,(%edi)                       \n"
+    "lea    0x4(%edi),%edi                     \n"
+    "sub    $0x4,%ecx                          \n"
+    "ja     1b                                 \n"
+    "popa                                      \n"
+    "ret                                       \n"
+);
+
+// fpic is used for magiccam plugin
+#if !defined(__PIC__)
+#define HAS_SCALEROWDOWN34_SSSE3
+void ScaleRowDown34_SSSE3(const uint8* src_ptr, int src_stride,
+                                     uint8* dst_ptr, int dst_width);
+  asm(
+    DECLARE_FUNCTION(ScaleRowDown34_SSSE3)
+    "pusha                                     \n"
+    "mov    0x24(%esp),%esi                    \n"
+    "mov    0x2c(%esp),%edi                    \n"
+    "mov    0x30(%esp),%ecx                    \n"
+    "movdqa _shuf0,%xmm3                       \n"
+    "movdqa _shuf1,%xmm4                       \n"
+    "movdqa _shuf2,%xmm5                       \n"
+
+"1:"
+    "movdqa (%esi),%xmm0                       \n"
+    "movdqa 0x10(%esi),%xmm2                   \n"
+    "lea    0x20(%esi),%esi                    \n"
+    "movdqa %xmm2,%xmm1                        \n"
+    "palignr $0x8,%xmm0,%xmm1                  \n"
+    "pshufb %xmm3,%xmm0                        \n"
+    "pshufb %xmm4,%xmm1                        \n"
+    "pshufb %xmm5,%xmm2                        \n"
+    "movq   %xmm0,(%edi)                       \n"
+    "movq   %xmm1,0x8(%edi)                    \n"
+    "movq   %xmm2,0x10(%edi)                   \n"
+    "lea    0x18(%edi),%edi                    \n"
+    "sub    $0x18,%ecx                         \n"
+    "ja     1b                                 \n"
+    "popa                                      \n"
+    "ret                                       \n"
+);
+
+void ScaleRowDown34_1_Int_SSSE3(const uint8* src_ptr, int src_stride,
+                                           uint8* dst_ptr, int dst_width);
+  asm(
+    DECLARE_FUNCTION(ScaleRowDown34_1_Int_SSSE3)
+    "pusha                                     \n"
+    "mov    0x24(%esp),%esi                    \n"
+    "mov    0x28(%esp),%ebp                    \n"
+    "mov    0x2c(%esp),%edi                    \n"
+    "mov    0x30(%esp),%ecx                    \n"
+    "movdqa _shuf01,%xmm2                      \n"
+    "movdqa _shuf11,%xmm3                      \n"
+    "movdqa _shuf21,%xmm4                      \n"
+    "movdqa _madd01,%xmm5                      \n"
+    "movdqa _madd11,%xmm6                      \n"
+    "movdqa _round34,%xmm7                     \n"
+
+"1:"
+    "movdqa (%esi),%xmm0                       \n"
+    "movdqa (%esi,%ebp),%xmm1                  \n"
+    "pavgb  %xmm1,%xmm0                        \n"
+    "pshufb %xmm2,%xmm0                        \n"
+    "pmaddubsw %xmm5,%xmm0                     \n"
+    "paddsw %xmm7,%xmm0                        \n"
+    "psrlw  $0x2,%xmm0                         \n"
+    "packuswb %xmm0,%xmm0                      \n"
+    "movq   %xmm0,(%edi)                       \n"
+    "movdqu 0x8(%esi),%xmm0                    \n"
+    "movdqu 0x8(%esi,%ebp),%xmm1               \n"
+    "pavgb  %xmm1,%xmm0                        \n"
+    "pshufb %xmm3,%xmm0                        \n"
+    "pmaddubsw %xmm6,%xmm0                     \n"
+    "paddsw %xmm7,%xmm0                        \n"
+    "psrlw  $0x2,%xmm0                         \n"
+    "packuswb %xmm0,%xmm0                      \n"
+    "movq   %xmm0,0x8(%edi)                    \n"
+    "movdqa 0x10(%esi),%xmm0                   \n"
+    "movdqa 0x10(%esi,%ebp),%xmm1              \n"
+    "lea    0x20(%esi),%esi                    \n"
+    "pavgb  %xmm1,%xmm0                        \n"
+    "pshufb %xmm4,%xmm0                        \n"
+    "movdqa  _madd21,%xmm1                     \n"
+    "pmaddubsw %xmm1,%xmm0                     \n"
+    "paddsw %xmm7,%xmm0                        \n"
+    "psrlw  $0x2,%xmm0                         \n"
+    "packuswb %xmm0,%xmm0                      \n"
+    "movq   %xmm0,0x10(%edi)                   \n"
+    "lea    0x18(%edi),%edi                    \n"
+    "sub    $0x18,%ecx                         \n"
+    "ja     1b                                 \n"
+
+    "popa                                      \n"
+    "ret                                       \n"
+);
+
+void ScaleRowDown34_0_Int_SSSE3(const uint8* src_ptr, int src_stride,
+                                           uint8* dst_ptr, int dst_width);
+  asm(
+    DECLARE_FUNCTION(ScaleRowDown34_0_Int_SSSE3)
+    "pusha                                     \n"
+    "mov    0x24(%esp),%esi                    \n"
+    "mov    0x28(%esp),%ebp                    \n"
+    "mov    0x2c(%esp),%edi                    \n"
+    "mov    0x30(%esp),%ecx                    \n"
+    "movdqa _shuf01,%xmm2                      \n"
+    "movdqa _shuf11,%xmm3                      \n"
+    "movdqa _shuf21,%xmm4                      \n"
+    "movdqa _madd01,%xmm5                      \n"
+    "movdqa _madd11,%xmm6                      \n"
+    "movdqa _round34,%xmm7                     \n"
+
+"1:"
+    "movdqa (%esi),%xmm0                       \n"
+    "movdqa (%esi,%ebp,1),%xmm1                \n"
+    "pavgb  %xmm0,%xmm1                        \n"
+    "pavgb  %xmm1,%xmm0                        \n"
+    "pshufb %xmm2,%xmm0                        \n"
+    "pmaddubsw %xmm5,%xmm0                     \n"
+    "paddsw %xmm7,%xmm0                        \n"
+    "psrlw  $0x2,%xmm0                         \n"
+    "packuswb %xmm0,%xmm0                      \n"
+    "movq   %xmm0,(%edi)                       \n"
+    "movdqu 0x8(%esi),%xmm0                    \n"
+    "movdqu 0x8(%esi,%ebp,1),%xmm1             \n"
+    "pavgb  %xmm0,%xmm1                        \n"
+    "pavgb  %xmm1,%xmm0                        \n"
+    "pshufb %xmm3,%xmm0                        \n"
+    "pmaddubsw %xmm6,%xmm0                     \n"
+    "paddsw %xmm7,%xmm0                        \n"
+    "psrlw  $0x2,%xmm0                         \n"
+    "packuswb %xmm0,%xmm0                      \n"
+    "movq   %xmm0,0x8(%edi)                    \n"
+    "movdqa 0x10(%esi),%xmm0                   \n"
+    "movdqa 0x10(%esi,%ebp,1),%xmm1            \n"
+    "lea    0x20(%esi),%esi                    \n"
+    "pavgb  %xmm0,%xmm1                        \n"
+    "pavgb  %xmm1,%xmm0                        \n"
+    "pshufb %xmm4,%xmm0                        \n"
+    "movdqa  _madd21,%xmm1                     \n"
+    "pmaddubsw %xmm1,%xmm0                     \n"
+    "paddsw %xmm7,%xmm0                        \n"
+    "psrlw  $0x2,%xmm0                         \n"
+    "packuswb %xmm0,%xmm0                      \n"
+    "movq   %xmm0,0x10(%edi)                   \n"
+    "lea    0x18(%edi),%edi                    \n"
+    "sub    $0x18,%ecx                         \n"
+    "ja     1b                                 \n"
+    "popa                                      \n"
+    "ret                                       \n"
+);
+
+#define HAS_SCALEROWDOWN38_SSSE3
+void ScaleRowDown38_SSSE3(const uint8* src_ptr, int src_stride,
+                                     uint8* dst_ptr, int dst_width);
+  asm(
+    DECLARE_FUNCTION(ScaleRowDown38_SSSE3)
+    "pusha                                     \n"
+    "mov    0x24(%esp),%esi                    \n"
+    "mov    0x28(%esp),%edx                    \n"
+    "mov    0x2c(%esp),%edi                    \n"
+    "mov    0x30(%esp),%ecx                    \n"
+    "movdqa _shuf38a ,%xmm4                    \n"
+    "movdqa _shuf38b ,%xmm5                    \n"
+
+"1:"
+    "movdqa (%esi),%xmm0                       \n"
+    "movdqa 0x10(%esi),%xmm1                   \n"
+    "lea    0x20(%esi),%esi                    \n"
+    "pshufb %xmm4,%xmm0                        \n"
+    "pshufb %xmm5,%xmm1                        \n"
+    "paddusb %xmm1,%xmm0                       \n"
+    "movq   %xmm0,(%edi)                       \n"
+    "movhlps %xmm0,%xmm1                       \n"
+    "movd   %xmm1,0x8(%edi)                    \n"
+    "lea    0xc(%edi),%edi                     \n"
+    "sub    $0xc,%ecx                          \n"
+    "ja     1b                                 \n"
+    "popa                                      \n"
+    "ret                                       \n"
+);
+
+void ScaleRowDown38_3_Int_SSSE3(const uint8* src_ptr, int src_stride,
+                                           uint8* dst_ptr, int dst_width);
+  asm(
+    DECLARE_FUNCTION(ScaleRowDown38_3_Int_SSSE3)
+    "pusha                                     \n"
+    "mov    0x24(%esp),%esi                    \n"
+    "mov    0x28(%esp),%edx                    \n"
+    "mov    0x2c(%esp),%edi                    \n"
+    "mov    0x30(%esp),%ecx                    \n"
+    "movdqa _shufac0,%xmm4                     \n"
+    "movdqa _shufac3,%xmm5                     \n"
+    "movdqa _scaleac3,%xmm6                    \n"
+    "pxor   %xmm7,%xmm7                        \n"
+
+"1:"
+    "movdqa (%esi),%xmm0                       \n"
+    "movdqa (%esi,%edx,1),%xmm2                \n"
+    "movhlps %xmm0,%xmm1                       \n"
+    "movhlps %xmm2,%xmm3                       \n"
+    "punpcklbw %xmm7,%xmm0                     \n"
+    "punpcklbw %xmm7,%xmm1                     \n"
+    "punpcklbw %xmm7,%xmm2                     \n"
+    "punpcklbw %xmm7,%xmm3                     \n"
+    "paddusw %xmm2,%xmm0                       \n"
+    "paddusw %xmm3,%xmm1                       \n"
+    "movdqa (%esi,%edx,2),%xmm2                \n"
+    "lea    0x10(%esi),%esi                    \n"
+    "movhlps %xmm2,%xmm3                       \n"
+    "punpcklbw %xmm7,%xmm2                     \n"
+    "punpcklbw %xmm7,%xmm3                     \n"
+    "paddusw %xmm2,%xmm0                       \n"
+    "paddusw %xmm3,%xmm1                       \n"
+    "movdqa %xmm0,%xmm2                        \n"
+    "psrldq $0x2,%xmm0                         \n"
+    "paddusw %xmm0,%xmm2                       \n"
+    "psrldq $0x2,%xmm0                         \n"
+    "paddusw %xmm0,%xmm2                       \n"
+    "pshufb %xmm4,%xmm2                        \n"
+    "movdqa %xmm1,%xmm3                        \n"
+    "psrldq $0x2,%xmm1                         \n"
+    "paddusw %xmm1,%xmm3                       \n"
+    "psrldq $0x2,%xmm1                         \n"
+    "paddusw %xmm1,%xmm3                       \n"
+    "pshufb %xmm5,%xmm3                        \n"
+    "paddusw %xmm3,%xmm2                       \n"
+    "pmulhuw %xmm6,%xmm2                       \n"
+    "packuswb %xmm2,%xmm2                      \n"
+    "movd   %xmm2,(%edi)                       \n"
+    "pextrw $0x2,%xmm2,%eax                    \n"
+    "mov    %ax,0x4(%edi)                      \n"
+    "lea    0x6(%edi),%edi                     \n"
+    "sub    $0x6,%ecx                          \n"
+    "ja     1b                                 \n"
+    "popa                                      \n"
+    "ret                                       \n"
+);
+
+void ScaleRowDown38_2_Int_SSSE3(const uint8* src_ptr, int src_stride,
+                                           uint8* dst_ptr, int dst_width);
+  asm(
+    DECLARE_FUNCTION(ScaleRowDown38_2_Int_SSSE3)
+    "pusha                                     \n"
+    "mov    0x24(%esp),%esi                    \n"
+    "mov    0x28(%esp),%edx                    \n"
+    "mov    0x2c(%esp),%edi                    \n"
+    "mov    0x30(%esp),%ecx                    \n"
+    "movdqa _shufab0,%xmm4                     \n"
+    "movdqa _shufab1,%xmm5                     \n"
+    "movdqa _shufab2,%xmm6                     \n"
+    "movdqa _scaleab2,%xmm7                    \n"
+
+"1:"
+    "movdqa (%esi),%xmm2                       \n"
+    "pavgb  (%esi,%edx,1),%xmm2                \n"
+    "lea    0x10(%esi),%esi                    \n"
+    "movdqa %xmm2,%xmm0                        \n"
+    "pshufb %xmm4,%xmm0                        \n"
+    "movdqa %xmm2,%xmm1                        \n"
+    "pshufb %xmm5,%xmm1                        \n"
+    "paddusw %xmm1,%xmm0                       \n"
+    "pshufb %xmm6,%xmm2                        \n"
+    "paddusw %xmm2,%xmm0                       \n"
+    "pmulhuw %xmm7,%xmm0                       \n"
+    "packuswb %xmm0,%xmm0                      \n"
+    "movd   %xmm0,(%edi)                       \n"
+    "pextrw $0x2,%xmm0,%eax                    \n"
+    "mov    %ax,0x4(%edi)                      \n"
+    "lea    0x6(%edi),%edi                     \n"
+    "sub    $0x6,%ecx                          \n"
+    "ja     1b                                 \n"
+    "popa                                      \n"
+    "ret                                       \n"
+);
+#endif // __PIC__
+
+#define HAS_SCALEADDROWS_SSE2
+void ScaleAddRows_SSE2(const uint8* src_ptr, int src_stride,
+                                  uint16* dst_ptr, int src_width,
+                                  int src_height);
+  asm(
+    DECLARE_FUNCTION(ScaleAddRows_SSE2)
+    "pusha                                     \n"
+    "mov    0x24(%esp),%esi                    \n"
+    "mov    0x28(%esp),%edx                    \n"
+    "mov    0x2c(%esp),%edi                    \n"
+    "mov    0x30(%esp),%ecx                    \n"
+    "mov    0x34(%esp),%ebx                    \n"
+    "pxor   %xmm5,%xmm5                        \n"
+
+"1:"
+    "movdqa (%esi),%xmm2                       \n"
+    "lea    (%esi,%edx,1),%eax                 \n"
+    "movhlps %xmm2,%xmm3                       \n"
+    "lea    -0x1(%ebx),%ebp                    \n"
+    "punpcklbw %xmm5,%xmm2                     \n"
+    "punpcklbw %xmm5,%xmm3                     \n"
+
+"2:"
+    "movdqa (%eax),%xmm0                       \n"
+    "lea    (%eax,%edx,1),%eax                 \n"
+    "movhlps %xmm0,%xmm1                       \n"
+    "punpcklbw %xmm5,%xmm0                     \n"
+    "punpcklbw %xmm5,%xmm1                     \n"
+    "paddusw %xmm0,%xmm2                       \n"
+    "paddusw %xmm1,%xmm3                       \n"
+    "sub    $0x1,%ebp                          \n"
+    "ja     2b                                 \n"
+
+    "movdqa %xmm2,(%edi)                       \n"
+    "movdqa %xmm3,0x10(%edi)                   \n"
+    "lea    0x20(%edi),%edi                    \n"
+    "lea    0x10(%esi),%esi                    \n"
+    "sub    $0x10,%ecx                         \n"
+    "ja     1b                                 \n"
+    "popa                                      \n"
+    "ret                                       \n"
+);
+
+// Bilinear row filtering combines 16x2 -> 16x1. SSE2 version
+#define HAS_SCALEFILTERROWS_SSE2
+void ScaleFilterRows_SSE2(uint8* dst_ptr,
+                                     const uint8* src_ptr, int src_stride,
+                                     int dst_width, int source_y_fraction);
+  asm(
+    DECLARE_FUNCTION(ScaleFilterRows_SSE2)
+    "push   %esi                               \n"
+    "push   %edi                               \n"
+    "mov    0xc(%esp),%edi                     \n"
+    "mov    0x10(%esp),%esi                    \n"
+    "mov    0x14(%esp),%edx                    \n"
+    "mov    0x18(%esp),%ecx                    \n"
+    "mov    0x1c(%esp),%eax                    \n"
+    "cmp    $0x0,%eax                          \n"
+    "je     2f                                 \n"
+    "cmp    $0x80,%eax                         \n"
+    "je     3f                                 \n"
+    "movd   %eax,%xmm6                         \n"
+    "punpcklwd %xmm6,%xmm6                     \n"
+    "pshufd $0x0,%xmm6,%xmm6                   \n"
+    "neg    %eax                               \n"
+    "add    $0x100,%eax                        \n"
+    "movd   %eax,%xmm5                         \n"
+    "punpcklwd %xmm5,%xmm5                     \n"
+    "pshufd $0x0,%xmm5,%xmm5                   \n"
+    "pxor   %xmm7,%xmm7                        \n"
+
+"1:"
+    "movdqa (%esi),%xmm0                       \n"
+    "movdqa (%esi,%edx,1),%xmm2                \n"
+    "lea    0x10(%esi),%esi                    \n"
+    "movdqa %xmm0,%xmm1                        \n"
+    "movdqa %xmm2,%xmm3                        \n"
+    "punpcklbw %xmm7,%xmm0                     \n"
+    "punpcklbw %xmm7,%xmm2                     \n"
+    "punpckhbw %xmm7,%xmm1                     \n"
+    "punpckhbw %xmm7,%xmm3                     \n"
+    "pmullw %xmm5,%xmm0                        \n"
+    "pmullw %xmm5,%xmm1                        \n"
+    "pmullw %xmm6,%xmm2                        \n"
+    "pmullw %xmm6,%xmm3                        \n"
+    "paddusw %xmm2,%xmm0                       \n"
+    "paddusw %xmm3,%xmm1                       \n"
+    "psrlw  $0x8,%xmm0                         \n"
+    "psrlw  $0x8,%xmm1                         \n"
+    "packuswb %xmm1,%xmm0                      \n"
+    "movdqa %xmm0,(%edi)                       \n"
+    "lea    0x10(%edi),%edi                    \n"
+    "sub    $0x10,%ecx                         \n"
+    "ja     1b                                 \n"
+    "mov    -0x1(%edi),%al                     \n"
+    "mov    %al,(%edi)                         \n"
+    "pop    %edi                               \n"
+    "pop    %esi                               \n"
+    "ret                                       \n"
+
+"2:"
+    "movdqa (%esi),%xmm0                       \n"
+    "lea    0x10(%esi),%esi                    \n"
+    "movdqa %xmm0,(%edi)                       \n"
+    "lea    0x10(%edi),%edi                    \n"
+    "sub    $0x10,%ecx                         \n"
+    "ja     2b                                 \n"
+
+    "mov    -0x1(%edi),%al                     \n"
+    "mov    %al,(%edi)                         \n"
+    "pop    %edi                               \n"
+    "pop    %esi                               \n"
+    "ret                                       \n"
+
+"3:"
+    "movdqa (%esi),%xmm0                       \n"
+    "movdqa (%esi,%edx,1),%xmm2                \n"
+    "lea    0x10(%esi),%esi                    \n"
+    "pavgb  %xmm2,%xmm0                        \n"
+    "movdqa %xmm0,(%edi)                       \n"
+    "lea    0x10(%edi),%edi                    \n"
+    "sub    $0x10,%ecx                         \n"
+    "ja     3b                                 \n"
+
+    "mov    -0x1(%edi),%al                     \n"
+    "mov    %al,(%edi)                         \n"
+    "pop    %edi                               \n"
+    "pop    %esi                               \n"
+    "ret                                       \n"
+);
+
+// Bilinear row filtering combines 16x2 -> 16x1. SSSE3 version
+#define HAS_SCALEFILTERROWS_SSSE3
+void ScaleFilterRows_SSSE3(uint8* dst_ptr,
+                                      const uint8* src_ptr, int src_stride,
+                                      int dst_width, int source_y_fraction);
+  asm(
+    DECLARE_FUNCTION(ScaleFilterRows_SSSE3)
+    "push   %esi                               \n"
+    "push   %edi                               \n"
+    "mov    0xc(%esp),%edi                     \n"
+    "mov    0x10(%esp),%esi                    \n"
+    "mov    0x14(%esp),%edx                    \n"
+    "mov    0x18(%esp),%ecx                    \n"
+    "mov    0x1c(%esp),%eax                    \n"
+    "cmp    $0x0,%eax                          \n"
+    "je     2f                                 \n"
+    "cmp    $0x80,%eax                         \n"
+    "je     3f                                 \n"
+    "shr    %eax                               \n"
+    "mov    %al,%ah                            \n"
+    "neg    %al                                \n"
+    "add    $0x80,%al                          \n"
+    "movd   %eax,%xmm5                         \n"
+    "punpcklwd %xmm5,%xmm5                     \n"
+    "pshufd $0x0,%xmm5,%xmm5                   \n"
+
+"1:"
+    "movdqa (%esi),%xmm0                       \n"
+    "movdqa (%esi,%edx,1),%xmm2                \n"
+    "lea    0x10(%esi),%esi                    \n"
+    "movdqa %xmm0,%xmm1                        \n"
+    "punpcklbw %xmm2,%xmm0                     \n"
+    "punpckhbw %xmm2,%xmm1                     \n"
+    "pmaddubsw %xmm5,%xmm0                     \n"
+    "pmaddubsw %xmm5,%xmm1                     \n"
+    "psrlw  $0x7,%xmm0                         \n"
+    "psrlw  $0x7,%xmm1                         \n"
+    "packuswb %xmm1,%xmm0                      \n"
+    "movdqa %xmm0,(%edi)                       \n"
+    "lea    0x10(%edi),%edi                    \n"
+    "sub    $0x10,%ecx                         \n"
+    "ja     1b                                 \n"
+    "mov    -0x1(%edi),%al                     \n"
+    "mov    %al,(%edi)                         \n"
+    "pop    %edi                               \n"
+    "pop    %esi                               \n"
+    "ret                                       \n"
+
+"2:"
+    "movdqa (%esi),%xmm0                       \n"
+    "lea    0x10(%esi),%esi                    \n"
+    "movdqa %xmm0,(%edi)                       \n"
+    "lea    0x10(%edi),%edi                    \n"
+    "sub    $0x10,%ecx                         \n"
+    "ja     2b                                 \n"
+    "mov    -0x1(%edi),%al                     \n"
+    "mov    %al,(%edi)                         \n"
+    "pop    %edi                               \n"
+    "pop    %esi                               \n"
+    "ret                                       \n"
+
+"3:"
+    "movdqa (%esi),%xmm0                       \n"
+    "movdqa (%esi,%edx,1),%xmm2                \n"
+    "lea    0x10(%esi),%esi                    \n"
+    "pavgb  %xmm2,%xmm0                        \n"
+    "movdqa %xmm0,(%edi)                       \n"
+    "lea    0x10(%edi),%edi                    \n"
+    "sub    $0x10,%ecx                         \n"
+    "ja     3b                                 \n"
+    "mov    -0x1(%edi),%al                     \n"
+    "mov    %al,(%edi)                         \n"
+    "pop    %edi                               \n"
+    "pop    %esi                               \n"
+    "ret                                       \n"
+);
+
+#elif defined(__x86_64__)
+static void ScaleRowDown8Int_SSE2(const uint8* src_ptr, int src_stride,
+                                  uint8* dst_ptr, int dst_width) {
+  asm volatile (
+  "lea        (%3,%3,2),%%r10                  \n"
+  "pxor       %%xmm7,%%xmm7                    \n"
+"1:"
+  "movdqa     (%0),%%xmm0                      \n"
+  "movdqa     0x10(%0),%%xmm1                  \n"
+  "movdqa     (%0,%3,1),%%xmm2                 \n"
+  "movdqa     0x10(%0,%3,1),%%xmm3             \n"
+  "pavgb      %%xmm2,%%xmm0                    \n"
+  "pavgb      %%xmm3,%%xmm1                    \n"
+  "movdqa     (%0,%3,2),%%xmm2                 \n"
+  "movdqa     0x10(%0,%3,2),%%xmm3             \n"
+  "movdqa     (%0,%%r10,1),%%xmm4              \n"
+  "movdqa     0x10(%0,%%r10,1),%%xmm5          \n"
+  "lea        (%0,%3,4),%%r11                  \n"
+  "lea        0x20(%0),%0                      \n"
+  "pavgb      %%xmm4,%%xmm2                    \n"
+  "pavgb      %%xmm5,%%xmm3                    \n"
+  "pavgb      %%xmm2,%%xmm0                    \n"
+  "pavgb      %%xmm3,%%xmm1                    \n"
+  "movdqa     0x0(%%r11),%%xmm2                \n"
+  "movdqa     0x10(%%r11),%%xmm3               \n"
+  "movdqa     0x0(%%r11,%3,1),%%xmm4           \n"
+  "movdqa     0x10(%%r11,%3,1),%%xmm5          \n"
+  "pavgb      %%xmm4,%%xmm2                    \n"
+  "pavgb      %%xmm5,%%xmm3                    \n"
+  "movdqa     0x0(%%r11,%3,2),%%xmm4           \n"
+  "movdqa     0x10(%%r11,%3,2),%%xmm5          \n"
+  "movdqa     0x0(%%r11,%%r10,1),%%xmm6        \n"
+  "pavgb      %%xmm6,%%xmm4                    \n"
+  "movdqa     0x10(%%r11,%%r10,1),%%xmm6       \n"
+  "pavgb      %%xmm6,%%xmm5                    \n"
+  "pavgb      %%xmm4,%%xmm2                    \n"
+  "pavgb      %%xmm5,%%xmm3                    \n"
+  "pavgb      %%xmm2,%%xmm0                    \n"
+  "pavgb      %%xmm3,%%xmm1                    \n"
+  "psadbw     %%xmm7,%%xmm0                    \n"
+  "psadbw     %%xmm7,%%xmm1                    \n"
+  "pshufd     $0xd8,%%xmm0,%%xmm0              \n"
+  "pshufd     $0x8d,%%xmm1,%%xmm1              \n"
+  "por        %%xmm1,%%xmm0                    \n"
+  "psrlw      $0x3,%%xmm0                      \n"
+  "packuswb   %%xmm0,%%xmm0                    \n"
+  "packuswb   %%xmm0,%%xmm0                    \n"
+  "movd       %%xmm0,(%1)                      \n"
+  "lea        0x4(%1),%1                       \n"
+  "sub        $0x4,%2                          \n"
+  "ja         1b                               \n"
+  : "+r"(src_ptr),     // %0
+    "+r"(dst_ptr),     // %1
+    "+r"(dst_width)    // %2
+  : "r"((intptr_t)(src_stride))   // %3
+  : "memory", "cc", "r10", "r11", "xmm6", "xmm7"
+);
+}
+
+#define HAS_SCALEROWDOWN34_SSSE3
+static void ScaleRowDown34_SSSE3(const uint8* src_ptr, int src_stride,
+                                 uint8* dst_ptr, int dst_width) {
+  asm volatile (
+  "movdqa     (%3),%%xmm3                      \n"
+  "movdqa     (%4),%%xmm4                      \n"
+  "movdqa     (%5),%%xmm5                      \n"
+"1:"
+  "movdqa     (%0),%%xmm0                      \n"
+  "movdqa     0x10(%0),%%xmm2                  \n"
+  "lea        0x20(%0),%0                      \n"
+  "movdqa     %%xmm2,%%xmm1                    \n"
+  "palignr    $0x8,%%xmm0,%%xmm1               \n"
+  "pshufb     %%xmm3,%%xmm0                    \n"
+  "pshufb     %%xmm4,%%xmm1                    \n"
+  "pshufb     %%xmm5,%%xmm2                    \n"
+  "movq       %%xmm0,(%1)                      \n"
+  "movq       %%xmm1,0x8(%1)                   \n"
+  "movq       %%xmm2,0x10(%1)                  \n"
+  "lea        0x18(%1),%1                      \n"
+  "sub        $0x18,%2                         \n"
+  "ja         1b                               \n"
+  : "+r"(src_ptr),     // %0
+    "+r"(dst_ptr),     // %1
+    "+r"(dst_width)    // %2
+  : "r"(_shuf0),   // %3
+    "r"(_shuf1),   // %4
+    "r"(_shuf2)    // %5
+  : "memory", "cc"
+);
+}
+
+static void ScaleRowDown34_1_Int_SSSE3(const uint8* src_ptr, int src_stride,
+                                       uint8* dst_ptr, int dst_width) {
+  asm volatile (
+  "movdqa     (%4),%%xmm2                      \n"  // _shuf01
+  "movdqa     (%5),%%xmm3                      \n"  // _shuf11
+  "movdqa     (%6),%%xmm4                      \n"  // _shuf21
+  "movdqa     (%7),%%xmm5                      \n"  // _madd01
+  "movdqa     (%8),%%xmm6                      \n"  // _madd11
+  "movdqa     (%9),%%xmm7                      \n"  // _round34
+  "movdqa     (%10),%%xmm8                     \n"  // _madd21
+"1:"
+  "movdqa     (%0),%%xmm0                      \n"
+  "movdqa     (%0,%3),%%xmm1                   \n"
+  "pavgb      %%xmm1,%%xmm0                    \n"
+  "pshufb     %%xmm2,%%xmm0                    \n"
+  "pmaddubsw  %%xmm5,%%xmm0                    \n"
+  "paddsw     %%xmm7,%%xmm0                    \n"
+  "psrlw      $0x2,%%xmm0                      \n"
+  "packuswb   %%xmm0,%%xmm0                    \n"
+  "movq       %%xmm0,(%1)                      \n"
+  "movdqu     0x8(%0),%%xmm0                   \n"
+  "movdqu     0x8(%0,%3),%%xmm1                \n"
+  "pavgb      %%xmm1,%%xmm0                    \n"
+  "pshufb     %%xmm3,%%xmm0                    \n"
+  "pmaddubsw  %%xmm6,%%xmm0                    \n"
+  "paddsw     %%xmm7,%%xmm0                    \n"
+  "psrlw      $0x2,%%xmm0                      \n"
+  "packuswb   %%xmm0,%%xmm0                    \n"
+  "movq       %%xmm0,0x8(%1)                   \n"
+  "movdqa     0x10(%0),%%xmm0                  \n"
+  "movdqa     0x10(%0,%3),%%xmm1               \n"
+  "lea        0x20(%0),%0                      \n"
+  "pavgb      %%xmm1,%%xmm0                    \n"
+  "pshufb     %%xmm4,%%xmm0                    \n"
+  "pmaddubsw  %%xmm8,%%xmm0                    \n"
+  "paddsw     %%xmm7,%%xmm0                    \n"
+  "psrlw      $0x2,%%xmm0                      \n"
+  "packuswb   %%xmm0,%%xmm0                    \n"
+  "movq       %%xmm0,0x10(%1)                  \n"
+  "lea        0x18(%1),%1                      \n"
+  "sub        $0x18,%2                         \n"
+  "ja         1b                               \n"
+  : "+r"(src_ptr),     // %0
+    "+r"(dst_ptr),     // %1
+    "+r"(dst_width)    // %2
+  : "r"((intptr_t)(src_stride)),  // %3
+    "r"(_shuf01),   // %4
+    "r"(_shuf11),   // %5
+    "r"(_shuf21),   // %6
+    "r"(_madd01),   // %7
+    "r"(_madd11),   // %8
+    "r"(_round34),  // %9
+    "r"(_madd21)    // %10
+  : "memory", "cc", "xmm6", "xmm7", "xmm8"
+);
+}
+
+static void ScaleRowDown34_0_Int_SSSE3(const uint8* src_ptr, int src_stride,
+                                       uint8* dst_ptr, int dst_width) {
+  asm volatile (
+  "movdqa     (%4),%%xmm2                      \n"  // _shuf01
+  "movdqa     (%5),%%xmm3                      \n"  // _shuf11
+  "movdqa     (%6),%%xmm4                      \n"  // _shuf21
+  "movdqa     (%7),%%xmm5                      \n"  // _madd01
+  "movdqa     (%8),%%xmm6                      \n"  // _madd11
+  "movdqa     (%9),%%xmm7                      \n"  // _round34
+  "movdqa     (%10),%%xmm8                     \n"  // _madd21
+"1:"
+  "movdqa     (%0),%%xmm0                      \n"
+  "movdqa     (%0,%3,1),%%xmm1                 \n"
+  "pavgb      %%xmm0,%%xmm1                    \n"
+  "pavgb      %%xmm1,%%xmm0                    \n"
+  "pshufb     %%xmm2,%%xmm0                    \n"
+  "pmaddubsw  %%xmm5,%%xmm0                    \n"
+  "paddsw     %%xmm7,%%xmm0                    \n"
+  "psrlw      $0x2,%%xmm0                      \n"
+  "packuswb   %%xmm0,%%xmm0                    \n"
+  "movq       %%xmm0,(%1)                      \n"
+  "movdqu     0x8(%0),%%xmm0                   \n"
+  "movdqu     0x8(%0,%3,1),%%xmm1              \n"
+  "pavgb      %%xmm0,%%xmm1                    \n"
+  "pavgb      %%xmm1,%%xmm0                    \n"
+  "pshufb     %%xmm3,%%xmm0                    \n"
+  "pmaddubsw  %%xmm6,%%xmm0                    \n"
+  "paddsw     %%xmm7,%%xmm0                    \n"
+  "psrlw      $0x2,%%xmm0                      \n"
+  "packuswb   %%xmm0,%%xmm0                    \n"
+  "movq       %%xmm0,0x8(%1)                   \n"
+  "movdqa     0x10(%0),%%xmm0                  \n"
+  "movdqa     0x10(%0,%3,1),%%xmm1             \n"
+  "lea        0x20(%0),%0                      \n"
+  "pavgb      %%xmm0,%%xmm1                    \n"
+  "pavgb      %%xmm1,%%xmm0                    \n"
+  "pshufb     %%xmm4,%%xmm0                    \n"
+  "pmaddubsw  %%xmm8,%%xmm0                    \n"
+  "paddsw     %%xmm7,%%xmm0                    \n"
+  "psrlw      $0x2,%%xmm0                      \n"
+  "packuswb   %%xmm0,%%xmm0                    \n"
+  "movq       %%xmm0,0x10(%1)                  \n"
+  "lea        0x18(%1),%1                      \n"
+  "sub        $0x18,%2                         \n"
+  "ja         1b                               \n"
+  : "+r"(src_ptr),     // %0
+    "+r"(dst_ptr),     // %1
+    "+r"(dst_width)    // %2
+  : "r"((intptr_t)(src_stride)),  // %3
+    "r"(_shuf01),   // %4
+    "r"(_shuf11),   // %5
+    "r"(_shuf21),   // %6
+    "r"(_madd01),   // %7
+    "r"(_madd11),   // %8
+    "r"(_round34),  // %9
+    "r"(_madd21)    // %10
+  : "memory", "cc", "xmm6", "xmm7", "xmm8"
+);
+}
+
+#define HAS_SCALEROWDOWN38_SSSE3
+static void ScaleRowDown38_SSSE3(const uint8* src_ptr, int src_stride,
+                                 uint8* dst_ptr, int dst_width) {
+  asm volatile (
+  "movdqa     (%3),%%xmm4                      \n"
+  "movdqa     (%4),%%xmm5                      \n"
+"1:"
+  "movdqa     (%0),%%xmm0                      \n"
+  "movdqa     0x10(%0),%%xmm1                  \n"
+  "lea        0x20(%0),%0                      \n"
+  "pshufb     %%xmm4,%%xmm0                    \n"
+  "pshufb     %%xmm5,%%xmm1                    \n"
+  "paddusb    %%xmm1,%%xmm0                    \n"
+  "movq       %%xmm0,(%1)                      \n"
+  "movhlps    %%xmm0,%%xmm1                    \n"
+  "movd       %%xmm1,0x8(%1)                   \n"
+  "lea        0xc(%1),%1                       \n"
+  "sub        $0xc,%2                          \n"
+  "ja         1b                               \n"
+  : "+r"(src_ptr),     // %0
+    "+r"(dst_ptr),     // %1
+    "+r"(dst_width)    // %2
+  : "r"(_shuf38a),  // %3
+    "r"(_shuf38b)   // %4
+  : "memory", "cc"
+);
+}
+
+static void ScaleRowDown38_3_Int_SSSE3(const uint8* src_ptr, int src_stride,
+                                       uint8* dst_ptr, int dst_width) {
+  asm volatile (
+  "movdqa     (%4),%%xmm4                      \n"
+  "movdqa     (%5),%%xmm5                      \n"
+  "movdqa     (%6),%%xmm6                      \n"
+  "pxor       %%xmm7,%%xmm7                    \n"
+"1:"
+  "movdqa     (%0),%%xmm0                      \n"
+  "movdqa     (%0,%3,1),%%xmm2                 \n"
+  "movhlps    %%xmm0,%%xmm1                    \n"
+  "movhlps    %%xmm2,%%xmm3                    \n"
+  "punpcklbw  %%xmm7,%%xmm0                    \n"
+  "punpcklbw  %%xmm7,%%xmm1                    \n"
+  "punpcklbw  %%xmm7,%%xmm2                    \n"
+  "punpcklbw  %%xmm7,%%xmm3                    \n"
+  "paddusw    %%xmm2,%%xmm0                    \n"
+  "paddusw    %%xmm3,%%xmm1                    \n"
+  "movdqa     (%0,%3,2),%%xmm2                 \n"
+  "lea        0x10(%0),%0                      \n"
+  "movhlps    %%xmm2,%%xmm3                    \n"
+  "punpcklbw  %%xmm7,%%xmm2                    \n"
+  "punpcklbw  %%xmm7,%%xmm3                    \n"
+  "paddusw    %%xmm2,%%xmm0                    \n"
+  "paddusw    %%xmm3,%%xmm1                    \n"
+  "movdqa     %%xmm0,%%xmm2                    \n"
+  "psrldq     $0x2,%%xmm0                      \n"
+  "paddusw    %%xmm0,%%xmm2                    \n"
+  "psrldq     $0x2,%%xmm0                      \n"
+  "paddusw    %%xmm0,%%xmm2                    \n"
+  "pshufb     %%xmm4,%%xmm2                    \n"
+  "movdqa     %%xmm1,%%xmm3                    \n"
+  "psrldq     $0x2,%%xmm1                      \n"
+  "paddusw    %%xmm1,%%xmm3                    \n"
+  "psrldq     $0x2,%%xmm1                      \n"
+  "paddusw    %%xmm1,%%xmm3                    \n"
+  "pshufb     %%xmm5,%%xmm3                    \n"
+  "paddusw    %%xmm3,%%xmm2                    \n"
+  "pmulhuw    %%xmm6,%%xmm2                    \n"
+  "packuswb   %%xmm2,%%xmm2                    \n"
+  "movd       %%xmm2,(%1)                      \n"
+  "pextrw     $0x2,%%xmm2,%%eax                \n"
+  "mov        %%ax,0x4(%1)                     \n"
+  "lea        0x6(%1),%1                       \n"
+  "sub        $0x6,%2                          \n"
+  "ja         1b                               \n"
+  : "+r"(src_ptr),     // %0
+    "+r"(dst_ptr),     // %1
+    "+r"(dst_width)    // %2
+  : "r"((intptr_t)(src_stride)),  // %3
+    "r"(_shufac0),   // %4
+    "r"(_shufac3),   // %5
+    "r"(_scaleac3)   // %6
+  : "memory", "cc", "rax", "xmm6", "xmm7"
+);
+}
+
+static void ScaleRowDown38_2_Int_SSSE3(const uint8* src_ptr, int src_stride,
+                                       uint8* dst_ptr, int dst_width) {
+  asm volatile (
+  "movdqa     (%4),%%xmm4                      \n"
+  "movdqa     (%5),%%xmm5                      \n"
+  "movdqa     (%6),%%xmm6                      \n"
+  "movdqa     (%7),%%xmm7                      \n"
+"1:"
+  "movdqa     (%0),%%xmm2                      \n"
+  "pavgb      (%0,%3,1),%%xmm2                 \n"
+  "lea        0x10(%0),%0                      \n"
+  "movdqa     %%xmm2,%%xmm0                    \n"
+  "pshufb     %%xmm4,%%xmm0                    \n"
+  "movdqa     %%xmm2,%%xmm1                    \n"
+  "pshufb     %%xmm5,%%xmm1                    \n"
+  "paddusw    %%xmm1,%%xmm0                    \n"
+  "pshufb     %%xmm6,%%xmm2                    \n"
+  "paddusw    %%xmm2,%%xmm0                    \n"
+  "pmulhuw    %%xmm7,%%xmm0                    \n"
+  "packuswb   %%xmm0,%%xmm0                    \n"
+  "movd       %%xmm0,(%1)                      \n"
+  "pextrw     $0x2,%%xmm0,%%eax                \n"
+  "mov        %%ax,0x4(%1)                     \n"
+  "lea        0x6(%1),%1                       \n"
+  "sub        $0x6,%2                          \n"
+  "ja         1b                               \n"
+  : "+r"(src_ptr),     // %0
+    "+r"(dst_ptr),     // %1
+    "+r"(dst_width)    // %2
+  : "r"((intptr_t)(src_stride)),  // %3
+    "r"(_shufab0),   // %4
+    "r"(_shufab1),   // %5
+    "r"(_shufab2),   // %6
+    "r"(_scaleab2)   // %7
+  : "memory", "cc", "rax", "xmm6", "xmm7"
+);
+}
+
+#define HAS_SCALEADDROWS_SSE2
+static void ScaleAddRows_SSE2(const uint8* src_ptr, int src_stride,
+                              uint16* dst_ptr, int src_width,
+                              int src_height) {
+  asm volatile (
+  "pxor       %%xmm5,%%xmm5                    \n"
+"1:"
+  "movdqa     (%0),%%xmm2                      \n"
+  "lea        (%0,%4,1),%%r10                  \n"
+  "movhlps    %%xmm2,%%xmm3                    \n"
+  "lea        -0x1(%3),%%r11                   \n"
+  "punpcklbw  %%xmm5,%%xmm2                    \n"
+  "punpcklbw  %%xmm5,%%xmm3                    \n"
+
+"2:"
+  "movdqa     (%%r10),%%xmm0                   \n"
+  "lea        (%%r10,%4,1),%%r10               \n"
+  "movhlps    %%xmm0,%%xmm1                    \n"
+  "punpcklbw  %%xmm5,%%xmm0                    \n"
+  "punpcklbw  %%xmm5,%%xmm1                    \n"
+  "paddusw    %%xmm0,%%xmm2                    \n"
+  "paddusw    %%xmm1,%%xmm3                    \n"
+  "sub        $0x1,%%r11                       \n"
+  "ja         2b                               \n"
+
+  "movdqa     %%xmm2,(%1)                      \n"
+  "movdqa     %%xmm3,0x10(%1)                  \n"
+  "lea        0x20(%1),%1                      \n"
+  "lea        0x10(%0),%0                      \n"
+  "sub        $0x10,%2                         \n"
+  "ja         1b                               \n"
+  : "+r"(src_ptr),     // %0
+    "+r"(dst_ptr),     // %1
+    "+r"(src_width),   // %2
+    "+r"(src_height)   // %3
+  : "r"((intptr_t)(src_stride))  // %4
+  : "memory", "cc", "r10", "r11"
+);
+}
+
+// Bilinear row filtering combines 16x2 -> 16x1. SSE2 version
+#define HAS_SCALEFILTERROWS_SSE2
+static void ScaleFilterRows_SSE2(uint8* dst_ptr,
+                                 const uint8* src_ptr, int src_stride,
+                                 int dst_width, int source_y_fraction) {
+  if (source_y_fraction == 0) {
+    asm volatile (
+    "1:"
+      "movdqa     (%1),%%xmm0                  \n"
+      "lea        0x10(%1),%1                  \n"
+      "movdqa     %%xmm0,(%0)                  \n"
+      "lea        0x10(%0),%0                  \n"
+      "sub        $0x10,%2                     \n"
+      "ja         1b                           \n"
+      "mov        -0x1(%0),%%al                \n"
+      "mov        %%al,(%0)                    \n"
+      : "+r"(dst_ptr),     // %0
+        "+r"(src_ptr),     // %1
+        "+r"(dst_width)    // %2
+      :
+      : "memory", "cc", "rax"
+    );
+    return;
+  } else if (source_y_fraction == 128) {
+    asm volatile (
+    "1:"
+      "movdqa     (%1),%%xmm0                  \n"
+      "movdqa     (%1,%3,1),%%xmm2             \n"
+      "lea        0x10(%1),%1                  \n"
+      "pavgb      %%xmm2,%%xmm0                \n"
+      "movdqa     %%xmm0,(%0)                  \n"
+      "lea        0x10(%0),%0                  \n"
+      "sub        $0x10,%2                     \n"
+      "ja         1b                           \n"
+      "mov        -0x1(%0),%%al                \n"
+      "mov        %%al,(%0)                    \n"
+      : "+r"(dst_ptr),     // %0
+        "+r"(src_ptr),     // %1
+        "+r"(dst_width)    // %2
+      : "r"((intptr_t)(src_stride))  // %3
+      : "memory", "cc", "rax"
+    );
+    return;
+  } else {
+    asm volatile (
+      "mov        %3,%%eax                     \n"
+      "movd       %%eax,%%xmm6                 \n"
+      "punpcklwd  %%xmm6,%%xmm6                \n"
+      "pshufd     $0x0,%%xmm6,%%xmm6           \n"
+      "neg        %%eax                        \n"
+      "add        $0x100,%%eax                 \n"
+      "movd       %%eax,%%xmm5                 \n"
+      "punpcklwd  %%xmm5,%%xmm5                \n"
+      "pshufd     $0x0,%%xmm5,%%xmm5           \n"
+      "pxor       %%xmm7,%%xmm7                \n"
+    "1:"
+      "movdqa     (%1),%%xmm0                  \n"
+      "movdqa     (%1,%4,1),%%xmm2             \n"
+      "lea        0x10(%1),%1                  \n"
+      "movdqa     %%xmm0,%%xmm1                \n"
+      "movdqa     %%xmm2,%%xmm3                \n"
+      "punpcklbw  %%xmm7,%%xmm0                \n"
+      "punpcklbw  %%xmm7,%%xmm2                \n"
+      "punpckhbw  %%xmm7,%%xmm1                \n"
+      "punpckhbw  %%xmm7,%%xmm3                \n"
+      "pmullw     %%xmm5,%%xmm0                \n"
+      "pmullw     %%xmm5,%%xmm1                \n"
+      "pmullw     %%xmm6,%%xmm2                \n"
+      "pmullw     %%xmm6,%%xmm3                \n"
+      "paddusw    %%xmm2,%%xmm0                \n"
+      "paddusw    %%xmm3,%%xmm1                \n"
+      "psrlw      $0x8,%%xmm0                  \n"
+      "psrlw      $0x8,%%xmm1                  \n"
+      "packuswb   %%xmm1,%%xmm0                \n"
+      "movdqa     %%xmm0,(%0)                  \n"
+      "lea        0x10(%0),%0                  \n"
+      "sub        $0x10,%2                     \n"
+      "ja         1b                           \n"
+      "mov        -0x1(%0),%%al                \n"
+      "mov        %%al,(%0)                    \n"
+      : "+r"(dst_ptr),     // %0
+        "+r"(src_ptr),     // %1
+        "+r"(dst_width),   // %2
+        "+r"(source_y_fraction)  // %3
+      : "r"((intptr_t)(src_stride))  // %4
+      : "memory", "cc", "rax", "xmm6", "xmm7"
+    );
+  }
+  return;
+}
+
+// Bilinear row filtering combines 16x2 -> 16x1. SSSE3 version
+#define HAS_SCALEFILTERROWS_SSSE3
+static void ScaleFilterRows_SSSE3(uint8* dst_ptr,
+                                  const uint8* src_ptr, int src_stride,
+                                  int dst_width, int source_y_fraction) {
+  if (source_y_fraction == 0) {
+    asm volatile (
+   "1:"
+      "movdqa     (%1),%%xmm0                  \n"
+      "lea        0x10(%1),%1                  \n"
+      "movdqa     %%xmm0,(%0)                  \n"
+      "lea        0x10(%0),%0                  \n"
+      "sub        $0x10,%2                     \n"
+      "ja         1b                           \n"
+      "mov        -0x1(%0),%%al                \n"
+      "mov        %%al,(%0)                    \n"
+      : "+r"(dst_ptr),     // %0
+        "+r"(src_ptr),     // %1
+        "+r"(dst_width)    // %2
+      :
+      : "memory", "cc", "rax"
+    );
+    return;
+  } else if (source_y_fraction == 128) {
+    asm volatile (
+    "1:"
+      "movdqa     (%1),%%xmm0                  \n"
+      "movdqa     (%1,%3,1),%%xmm2             \n"
+      "lea        0x10(%1),%1                  \n"
+      "pavgb      %%xmm2,%%xmm0                \n"
+      "movdqa     %%xmm0,(%0)                  \n"
+      "lea        0x10(%0),%0                  \n"
+      "sub        $0x10,%2                     \n"
+      "ja         1b                           \n"
+      "mov        -0x1(%0),%%al                \n"
+      "mov        %%al,(%0)                    \n"
+      : "+r"(dst_ptr),     // %0
+        "+r"(src_ptr),     // %1
+        "+r"(dst_width)    // %2
+      : "r"((intptr_t)(src_stride))  // %3
+     : "memory", "cc", "rax"
+    );
+    return;
+  } else {
+    asm volatile (
+      "mov        %3,%%eax                     \n"
+      "shr        %%eax                        \n"
+      "mov        %%al,%%ah                    \n"
+      "neg        %%al                         \n"
+      "add        $0x80,%%al                   \n"
+      "movd       %%eax,%%xmm5                 \n"
+      "punpcklwd  %%xmm5,%%xmm5                \n"
+      "pshufd     $0x0,%%xmm5,%%xmm5           \n"
+    "1:"
+      "movdqa     (%1),%%xmm0                  \n"
+      "movdqa     (%1,%4,1),%%xmm2             \n"
+      "lea        0x10(%1),%1                  \n"
+      "movdqa     %%xmm0,%%xmm1                \n"
+      "punpcklbw  %%xmm2,%%xmm0                \n"
+      "punpckhbw  %%xmm2,%%xmm1                \n"
+      "pmaddubsw  %%xmm5,%%xmm0                \n"
+      "pmaddubsw  %%xmm5,%%xmm1                \n"
+      "psrlw      $0x7,%%xmm0                  \n"
+      "psrlw      $0x7,%%xmm1                  \n"
+      "packuswb   %%xmm1,%%xmm0                \n"
+      "movdqa     %%xmm0,(%0)                  \n"
+      "lea        0x10(%0),%0                  \n"
+      "sub        $0x10,%2                     \n"
+      "ja         1b                           \n"
+      "mov        -0x1(%0),%%al                \n"
+      "mov        %%al,(%0)                    \n"
+      : "+r"(dst_ptr),     // %0
+        "+r"(src_ptr),     // %1
+        "+r"(dst_width),   // %2
+        "+r"(source_y_fraction)  // %3
+      : "r"((intptr_t)(src_stride))  // %4
+      : "memory", "cc", "rax"
+    );
+  }
+  return;
+}
+#endif
+#endif
+
+// CPU agnostic row functions
+static void ScaleRowDown2_C(const uint8* src_ptr, int src_stride,
+                            uint8* dst, int dst_width) {
+  int x;
+  for (x = 0; x < dst_width; ++x) {
+    *dst++ = *src_ptr;
+    src_ptr += 2;
+  }
+}
+
+static void ScaleRowDown2Int_C(const uint8* src_ptr, int src_stride,
+                               uint8* dst, int dst_width) {
+  int x;
+  for (x = 0; x < dst_width; ++x) {
+    *dst++ = (src_ptr[0] + src_ptr[1] +
+              src_ptr[src_stride] + src_ptr[src_stride + 1] + 2) >> 2;
+    src_ptr += 2;
+  }
+}
+
+static void ScaleRowDown4_C(const uint8* src_ptr, int src_stride,
+                            uint8* dst, int dst_width) {
+  int x;
+  for (x = 0; x < dst_width; ++x) {
+    *dst++ = *src_ptr;
+    src_ptr += 4;
+  }
+}
+
+static void ScaleRowDown4Int_C(const uint8* src_ptr, int src_stride,
+                               uint8* dst, int dst_width) {
+  int x;
+  for (x = 0; x < dst_width; ++x) {
+    *dst++ = (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[3] +
+              src_ptr[src_stride + 0] + src_ptr[src_stride + 1] +
+              src_ptr[src_stride + 2] + src_ptr[src_stride + 3] +
+              src_ptr[src_stride * 2 + 0] + src_ptr[src_stride * 2 + 1] +
+              src_ptr[src_stride * 2 + 2] + src_ptr[src_stride * 2 + 3] +
+              src_ptr[src_stride * 3 + 0] + src_ptr[src_stride * 3 + 1] +
+              src_ptr[src_stride * 3 + 2] + src_ptr[src_stride * 3 + 3] +
+              8) >> 4;
+    src_ptr += 4;
+  }
+}
+
+// 640 output pixels is enough to allow 5120 input pixels with 1/8 scale down.
+// Keeping the total buffer under 4096 bytes avoids a stackcheck, saving 4% cpu.
+// The following 2 lines cause error on Windows.
+//static const int kMaxOutputWidth = 640;
+//static const int kMaxRow12 = 1280;         //kMaxOutputWidth * 2;
+#define kMaxOutputWidth   640
+#define kMaxRow12         1280
+
+static void ScaleRowDown8_C(const uint8* src_ptr, int src_stride,
+                            uint8* dst, int dst_width) {
+  int x;
+  for (x = 0; x < dst_width; ++x) {
+    *dst++ = *src_ptr;
+    src_ptr += 8;
+  }
+}
+
+// Note calling code checks width is less than max and if not
+// uses ScaleRowDown8_C instead.
+static void ScaleRowDown8Int_C(const uint8* src_ptr, int src_stride,
+                               uint8* dst, int dst_width) {
+  ALIGN16(uint8 src_row[kMaxRow12 * 2]);
+  assert(dst_width <= kMaxOutputWidth);
+  ScaleRowDown4Int_C(src_ptr, src_stride, src_row, dst_width * 2);
+  ScaleRowDown4Int_C(src_ptr + src_stride * 4, src_stride,
+                     src_row + kMaxOutputWidth,
+                     dst_width * 2);
+  ScaleRowDown2Int_C(src_row, kMaxOutputWidth, dst, dst_width);
+}
+
+static void ScaleRowDown34_C(const uint8* src_ptr, int src_stride,
+                             uint8* dst, int dst_width) {
+  uint8* dend;
+  assert((dst_width % 3 == 0) && (dst_width > 0));
+  dend = dst + dst_width;
+  do {
+    dst[0] = src_ptr[0];
+    dst[1] = src_ptr[1];
+    dst[2] = src_ptr[3];
+    dst += 3;
+    src_ptr += 4;
+  } while (dst < dend);
+}
+
+// Filter rows 0 and 1 together, 3 : 1
+static void ScaleRowDown34_0_Int_C(const uint8* src_ptr, int src_stride,
+                                   uint8* d, int dst_width) {
+  uint8* dend;
+  const uint8* s;
+  const uint8* t;
+  assert((dst_width % 3 == 0) && (dst_width > 0));
+  dend = d + dst_width;
+  s = src_ptr;
+  t = src_ptr + src_stride;
+  do {
+    uint8 a0 = (s[0] * 3 + s[1] * 1 + 2) >> 2;
+    uint8 a1 = (s[1] * 1 + s[2] * 1 + 1) >> 1;
+    uint8 a2 = (s[2] * 1 + s[3] * 3 + 2) >> 2;
+    uint8 b0 = (t[0] * 3 + t[1] * 1 + 2) >> 2;
+    uint8 b1 = (t[1] * 1 + t[2] * 1 + 1) >> 1;
+    uint8 b2 = (t[2] * 1 + t[3] * 3 + 2) >> 2;
+    d[0] = (a0 * 3 + b0 + 2) >> 2;
+    d[1] = (a1 * 3 + b1 + 2) >> 2;
+    d[2] = (a2 * 3 + b2 + 2) >> 2;
+    d += 3;
+    s += 4;
+    t += 4;
+  } while (d < dend);
+}
+
+// Filter rows 1 and 2 together, 1 : 1
+static void ScaleRowDown34_1_Int_C(const uint8* src_ptr, int src_stride,
+                                   uint8* d, int dst_width) {
+  uint8* dend;
+  const uint8* s;
+  const uint8* t;
+  assert((dst_width % 3 == 0) && (dst_width > 0));
+  dend = d + dst_width;
+  s = src_ptr;
+  t = src_ptr + src_stride;
+  do {
+    uint8 a0 = (s[0] * 3 + s[1] * 1 + 2) >> 2;
+    uint8 a1 = (s[1] * 1 + s[2] * 1 + 1) >> 1;
+    uint8 a2 = (s[2] * 1 + s[3] * 3 + 2) >> 2;
+    uint8 b0 = (t[0] * 3 + t[1] * 1 + 2) >> 2;
+    uint8 b1 = (t[1] * 1 + t[2] * 1 + 1) >> 1;
+    uint8 b2 = (t[2] * 1 + t[3] * 3 + 2) >> 2;
+    d[0] = (a0 + b0 + 1) >> 1;
+    d[1] = (a1 + b1 + 1) >> 1;
+    d[2] = (a2 + b2 + 1) >> 1;
+    d += 3;
+    s += 4;
+    t += 4;
+  } while (d < dend);
+}
+
+#if defined(HAS_SCALEFILTERROWS_SSE2)
+// Filter row to 3/4
+static void ScaleFilterCols34_C(uint8* dst_ptr, const uint8* src_ptr,
+                                int dst_width) {
+  uint8* dend;
+  const uint8* s;
+  assert((dst_width % 3 == 0) && (dst_width > 0));
+  dend = dst_ptr + dst_width;
+  s = src_ptr;
+  do {
+    dst_ptr[0] = (s[0] * 3 + s[1] * 1 + 2) >> 2;
+    dst_ptr[1] = (s[1] * 1 + s[2] * 1 + 1) >> 1;
+    dst_ptr[2] = (s[2] * 1 + s[3] * 3 + 2) >> 2;
+    dst_ptr += 3;
+    s += 4;
+  } while (dst_ptr < dend);
+}
+#endif
+
+static void ScaleFilterCols_C(uint8* dst_ptr, const uint8* src_ptr,
+                              int dst_width, int dx) {
+  int x = 0;
+  int j;
+  for (j = 0; j < dst_width; ++j) {
+    int xi = x >> 16;
+    int xf1 = x & 0xffff;
+    int xf0 = 65536 - xf1;
+
+    *dst_ptr++ = (src_ptr[xi] * xf0 + src_ptr[xi + 1] * xf1) >> 16;
+    x += dx;
+  }
+}
+
+//Not work on Windows
+//static const int kMaxInputWidth = 2560;
+#define kMaxInputWidth    2560
+#if defined(HAS_SCALEFILTERROWS_SSE2)
+#define HAS_SCALEROWDOWN34_SSE2
+// Filter rows 0 and 1 together, 3 : 1
+static void ScaleRowDown34_0_Int_SSE2(const uint8* src_ptr, int src_stride,
+                                      uint8* dst_ptr, int dst_width) {
+  ALIGN16(uint8 row[kMaxInputWidth]);
+  assert((dst_width % 3 == 0) && (dst_width > 0));
+  ScaleFilterRows_SSE2(row, src_ptr, src_stride, dst_width * 4 / 3, 256 / 4);
+  ScaleFilterCols34_C(dst_ptr, row, dst_width);
+}
+
+// Filter rows 1 and 2 together, 1 : 1
+static void ScaleRowDown34_1_Int_SSE2(const uint8* src_ptr, int src_stride,
+                                      uint8* dst_ptr, int dst_width) {
+  ALIGN16(uint8 row[kMaxInputWidth]);
+  assert((dst_width % 3 == 0) && (dst_width > 0));
+  ScaleFilterRows_SSE2(row, src_ptr, src_stride, dst_width * 4 / 3, 256 / 2);
+  ScaleFilterCols34_C(dst_ptr, row, dst_width);
+}
+#endif
+
+static void ScaleRowDown38_C(const uint8* src_ptr, int src_stride,
+                             uint8* dst, int dst_width) {
+  int x;
+  assert(dst_width % 3 == 0);
+  for (x = 0; x < dst_width; x += 3) {
+    dst[0] = src_ptr[0];
+    dst[1] = src_ptr[3];
+    dst[2] = src_ptr[6];
+    dst += 3;
+    src_ptr += 8;
+  }
+}
+
+// 8x3 -> 3x1
+static void ScaleRowDown38_3_Int_C(const uint8* src_ptr, int src_stride,
+                                   uint8* dst_ptr, int dst_width) {
+  int i;
+  assert((dst_width % 3 == 0) && (dst_width > 0));
+  for (i = 0; i < dst_width; i+=3) {
+    dst_ptr[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] +
+        src_ptr[src_stride + 0] + src_ptr[src_stride + 1] +
+        src_ptr[src_stride + 2] + src_ptr[src_stride * 2 + 0] +
+        src_ptr[src_stride * 2 + 1] + src_ptr[src_stride * 2 + 2]) *
+        (65536 / 9) >> 16;
+    dst_ptr[1] = (src_ptr[3] + src_ptr[4] + src_ptr[5] +
+        src_ptr[src_stride + 3] + src_ptr[src_stride + 4] +
+        src_ptr[src_stride + 5] + src_ptr[src_stride * 2 + 3] +
+        src_ptr[src_stride * 2 + 4] + src_ptr[src_stride * 2 + 5]) *
+        (65536 / 9) >> 16;
+    dst_ptr[2] = (src_ptr[6] + src_ptr[7] +
+        src_ptr[src_stride + 6] + src_ptr[src_stride + 7] +
+        src_ptr[src_stride * 2 + 6] + src_ptr[src_stride * 2 + 7]) *
+        (65536 / 6) >> 16;
+    src_ptr += 8;
+    dst_ptr += 3;
+  }
+}
+
+// 8x2 -> 3x1
+static void ScaleRowDown38_2_Int_C(const uint8* src_ptr, int src_stride,
+                                   uint8* dst_ptr, int dst_width) {
+  int i;
+  assert((dst_width % 3 == 0) && (dst_width > 0));
+  for (i = 0; i < dst_width; i+=3) {
+    dst_ptr[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] +
+        src_ptr[src_stride + 0] + src_ptr[src_stride + 1] +
+        src_ptr[src_stride + 2]) * (65536 / 6) >> 16;
+    dst_ptr[1] = (src_ptr[3] + src_ptr[4] + src_ptr[5] +
+        src_ptr[src_stride + 3] + src_ptr[src_stride + 4] +
+        src_ptr[src_stride + 5]) * (65536 / 6) >> 16;
+    dst_ptr[2] = (src_ptr[6] + src_ptr[7] +
+        src_ptr[src_stride + 6] + src_ptr[src_stride + 7]) *
+        (65536 / 4) >> 16;
+    src_ptr += 8;
+    dst_ptr += 3;
+  }
+}
+
+// C version 8x2 -> 8x1
+static void ScaleFilterRows_C(uint8* dst_ptr,
+                              const uint8* src_ptr, int src_stride,
+                              int dst_width, int source_y_fraction) {
+  int y1_fraction;
+  int y0_fraction;
+  const uint8* src_ptr1;
+  uint8* end;
+  assert(dst_width > 0);
+  y1_fraction = source_y_fraction;
+  y0_fraction = 256 - y1_fraction;
+  src_ptr1 = src_ptr + src_stride;
+  end = dst_ptr + dst_width;
+  do {
+    dst_ptr[0] = (src_ptr[0] * y0_fraction + src_ptr1[0] * y1_fraction) >> 8;
+    dst_ptr[1] = (src_ptr[1] * y0_fraction + src_ptr1[1] * y1_fraction) >> 8;
+    dst_ptr[2] = (src_ptr[2] * y0_fraction + src_ptr1[2] * y1_fraction) >> 8;
+    dst_ptr[3] = (src_ptr[3] * y0_fraction + src_ptr1[3] * y1_fraction) >> 8;
+    dst_ptr[4] = (src_ptr[4] * y0_fraction + src_ptr1[4] * y1_fraction) >> 8;
+    dst_ptr[5] = (src_ptr[5] * y0_fraction + src_ptr1[5] * y1_fraction) >> 8;
+    dst_ptr[6] = (src_ptr[6] * y0_fraction + src_ptr1[6] * y1_fraction) >> 8;
+    dst_ptr[7] = (src_ptr[7] * y0_fraction + src_ptr1[7] * y1_fraction) >> 8;
+    src_ptr += 8;
+    src_ptr1 += 8;
+    dst_ptr += 8;
+  } while (dst_ptr < end);
+  dst_ptr[0] = dst_ptr[-1];
+}
+
+void ScaleAddRows_C(const uint8* src_ptr, int src_stride,
+                    uint16* dst_ptr, int src_width, int src_height) {
+  int x,y;
+  assert(src_width > 0);
+  assert(src_height > 0);
+  for (x = 0; x < src_width; ++x) {
+    const uint8* s = src_ptr + x;
+    int sum = 0;
+    for (y = 0; y < src_height; ++y) {
+      sum += s[0];
+      s += src_stride;
+    }
+    dst_ptr[x] = sum;
+  }
+}
+
+/**
+ * Scale plane, 1/2
+ *
+ * This is an optimized version for scaling down a plane to 1/2 of
+ * its original size.
+ *
+ */
+static void ScalePlaneDown2(int src_width, int src_height,
+                            int dst_width, int dst_height,
+                            int src_stride, int dst_stride,
+                            const uint8* src_ptr, uint8* dst_ptr,
+                            FilterMode filtering) {
+  void (*ScaleRowDown2)(const uint8* src_ptr, int src_stride,
+                        uint8* dst_ptr, int dst_width);
+  assert(IS_ALIGNED(src_width, 2));
+  assert(IS_ALIGNED(src_height, 2));
+
+#if defined(HAS_SCALEROWDOWN2_NEON)
+  if (TestCpuFlag(kCpuHasNEON) &&
+      IS_ALIGNED(dst_width, 16)) {
+    ScaleRowDown2 = filtering ? ScaleRowDown2Int_NEON : ScaleRowDown2_NEON;
+  } else
+#endif
+#if defined(HAS_SCALEROWDOWN2_SSE2)
+  if (TestCpuFlag(kCpuHasSSE2) &&
+      IS_ALIGNED(dst_width, 16) &&
+      IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16) &&
+      IS_ALIGNED(dst_ptr, 16) && IS_ALIGNED(dst_stride, 16)) {
+    ScaleRowDown2 = filtering ? ScaleRowDown2Int_SSE2 : ScaleRowDown2_SSE2;
+  } else
+#endif
+  {
+    ScaleRowDown2 = filtering ? ScaleRowDown2Int_C : ScaleRowDown2_C;
+  }
+
+  {
+    int y;
+    for (y = 0; y < dst_height; ++y) {
+      ScaleRowDown2(src_ptr, src_stride, dst_ptr, dst_width);
+      src_ptr += (src_stride << 1);
+      dst_ptr += dst_stride;
+    }
+  }
+}
+
+/**
+ * Scale plane, 1/4
+ *
+ * This is an optimized version for scaling down a plane to 1/4 of
+ * its original size.
+ */
+static void ScalePlaneDown4(int src_width, int src_height,
+                            int dst_width, int dst_height,
+                            int src_stride, int dst_stride,
+                            const uint8* src_ptr, uint8* dst_ptr,
+                            FilterMode filtering) {
+  void (*ScaleRowDown4)(const uint8* src_ptr, int src_stride,
+                        uint8* dst_ptr, int dst_width);
+  assert(IS_ALIGNED(src_width, 4));
+  assert(IS_ALIGNED(src_height, 4));
+
+#if defined(HAS_SCALEROWDOWN4_NEON)
+  if (TestCpuFlag(kCpuHasNEON) &&
+      IS_ALIGNED(dst_width, 4)) {
+    ScaleRowDown4 = filtering ? ScaleRowDown4Int_NEON : ScaleRowDown4_NEON;
+  } else
+#endif
+#if defined(HAS_SCALEROWDOWN4_SSE2)
+  if (TestCpuFlag(kCpuHasSSE2) &&
+      IS_ALIGNED(dst_width, 8) &&
+      IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16) &&
+      IS_ALIGNED(dst_ptr, 8) && IS_ALIGNED(dst_stride, 8)) {
+    ScaleRowDown4 = filtering ? ScaleRowDown4Int_SSE2 : ScaleRowDown4_SSE2;
+  } else
+#endif
+  {
+    ScaleRowDown4 = filtering ? ScaleRowDown4Int_C : ScaleRowDown4_C;
+  }
+
+  {
+    int y;
+    for (y = 0; y < dst_height; ++y) {
+      ScaleRowDown4(src_ptr, src_stride, dst_ptr, dst_width);
+      src_ptr += (src_stride << 2);
+      dst_ptr += dst_stride;
+    }
+  }
+}
+
+/**
+ * Scale plane, 1/8
+ *
+ * This is an optimized version for scaling down a plane to 1/8
+ * of its original size.
+ *
+ */
+static void ScalePlaneDown8(int src_width, int src_height,
+                            int dst_width, int dst_height,
+                            int src_stride, int dst_stride,
+                            const uint8* src_ptr, uint8* dst_ptr,
+                            FilterMode filtering) {
+  void (*ScaleRowDown8)(const uint8* src_ptr, int src_stride,
+                        uint8* dst_ptr, int dst_width);
+  assert(IS_ALIGNED(src_width, 8));
+  assert(IS_ALIGNED(src_height, 8));
+
+#if defined(HAS_SCALEROWDOWN8_SSE2)
+  if (TestCpuFlag(kCpuHasSSE2) &&
+      IS_ALIGNED(dst_width, 4) &&
+      IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16) &&
+      IS_ALIGNED(dst_ptr, 4) && IS_ALIGNED(dst_stride, 4)) {
+    ScaleRowDown8 = filtering ? ScaleRowDown8Int_SSE2 : ScaleRowDown8_SSE2;
+  } else
+#endif
+  {
+    ScaleRowDown8 = filtering && (dst_width <= kMaxOutputWidth) ?
+        ScaleRowDown8Int_C : ScaleRowDown8_C;
+  }
+
+  {
+    int y;
+    for (y = 0; y < dst_height; ++y) {
+      ScaleRowDown8(src_ptr, src_stride, dst_ptr, dst_width);
+      src_ptr += (src_stride << 3);
+      dst_ptr += dst_stride;
+    }
+  }
+}
+
+/**
+ * Scale plane down, 3/4
+ *
+ * Provided by Frank Barchard (fbarchard@google.com)
+ *
+ */
+static void ScalePlaneDown34(int src_width, int src_height,
+                             int dst_width, int dst_height,
+                             int src_stride, int dst_stride,
+                             const uint8* src_ptr, uint8* dst_ptr,
+                             FilterMode filtering) {
+  void (*ScaleRowDown34_0)(const uint8* src_ptr, int src_stride,
+                           uint8* dst_ptr, int dst_width);
+  void (*ScaleRowDown34_1)(const uint8* src_ptr, int src_stride,
+                           uint8* dst_ptr, int dst_width);
+  assert(dst_width % 3 == 0);
+#if defined(HAS_SCALEROWDOWN34_NEON)
+  if (TestCpuFlag(kCpuHasNEON) &&
+      (dst_width % 24 == 0)) {
+    if (!filtering) {
+      ScaleRowDown34_0 = ScaleRowDown34_NEON;
+      ScaleRowDown34_1 = ScaleRowDown34_NEON;
+    } else {
+      ScaleRowDown34_0 = ScaleRowDown34_0_Int_NEON;
+      ScaleRowDown34_1 = ScaleRowDown34_1_Int_NEON;
+    }
+  } else
+#endif
+
+#if defined(HAS_SCALEROWDOWN34_SSSE3)
+  if (TestCpuFlag(kCpuHasSSSE3) &&
+      (dst_width % 24 == 0) &&
+      IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(src_stride, 16) &&
+      IS_ALIGNED(dst_ptr, 8) && IS_ALIGNED(dst_stride, 8)) {
+    if (!filtering) {
+      ScaleRowDown34_0 = ScaleRowDown34_SSSE3;
+      ScaleRowDown34_1 = ScaleRowDown34_SSSE3;
+    } else {
+      ScaleRowDown34_0 = ScaleRowDown34_0_Int_SSSE3;
+      ScaleRowDown34_1 = ScaleRowDown34_1_Int_SSSE3;
+    }
+  } else
+#endif
+#if defined(HAS_SCALEROWDOWN34_SSE2)
+  if (TestCpuFlag(kCpuHasSSE2) &&
+      (dst_width % 24 == 0) && IS_ALIGNED(src_stride, 16) &&
+      IS_ALIGNED(dst_stride, 8) &&
+      IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(dst_ptr, 8) &&
+      filtering) {
+    ScaleRowDown34_0 = ScaleRowDown34_0_Int_SSE2;
+    ScaleRowDown34_1 = ScaleRowDown34_1_Int_SSE2;
+  } else
+#endif
+  {
+    if (!filtering) {
+      ScaleRowDown34_0 = ScaleRowDown34_C;
+      ScaleRowDown34_1 = ScaleRowDown34_C;
+    } else {
+      ScaleRowDown34_0 = ScaleRowDown34_0_Int_C;
+      ScaleRowDown34_1 = ScaleRowDown34_1_Int_C;
+    }
+  }
+  {
+  int src_row = 0;
+    int y;
+    for (y = 0; y < dst_height; ++y) {
+    switch (src_row) {
+      case 0:
+        ScaleRowDown34_0(src_ptr, src_stride, dst_ptr, dst_width);
+        break;
+
+      case 1:
+        ScaleRowDown34_1(src_ptr, src_stride, dst_ptr, dst_width);
+        break;
+
+      case 2:
+        ScaleRowDown34_0(src_ptr + src_stride, -src_stride,
+                         dst_ptr, dst_width);
+        break;
+    }
+    ++src_row;
+    src_ptr += src_stride;
+    dst_ptr += dst_stride;
+    if (src_row >= 3) {
+      src_ptr += src_stride;
+      src_row = 0;
+    }
+  }
+}
+}
+
+/**
+ * Scale plane, 3/8
+ *
+ * This is an optimized version for scaling down a plane to 3/8
+ * of its original size.
+ *
+ * Reduces 16x3 to 6x1
+ */
+static void ScalePlaneDown38(int src_width, int src_height,
+                             int dst_width, int dst_height,
+                             int src_stride, int dst_stride,
+                             const uint8* src_ptr, uint8* dst_ptr,
+                             FilterMode filtering) {
+  void (*ScaleRowDown38_3)(const uint8* src_ptr, int src_stride,
+                           uint8* dst_ptr, int dst_width);
+  void (*ScaleRowDown38_2)(const uint8* src_ptr, int src_stride,
+                           uint8* dst_ptr, int dst_width);
+  assert(dst_width % 3 == 0);
+#if defined(HAS_SCALEROWDOWN38_NEON)
+  if (TestCpuFlag(kCpuHasNEON) &&
+      (dst_width % 12 == 0)) {
+    if (!filtering) {
+      ScaleRowDown38_3 = ScaleRowDown38_NEON;
+      ScaleRowDown38_2 = ScaleRowDown38_NEON;
+    } else {
+      ScaleRowDown38_3 = ScaleRowDown38_3_Int_NEON;
+      ScaleRowDown38_2 = ScaleRowDown38_2_Int_NEON;
+    }
+  } else
+#endif
+
+#if defined(HAS_SCALEROWDOWN38_SSSE3)
+  if (TestCpuFlag(kCpuHasSSSE3) &&
+      (dst_width % 24 == 0) && IS_ALIGNED(src_stride, 16) &&
+      IS_ALIGNED(dst_stride, 8) &&
+      IS_ALIGNED(src_ptr, 16) && IS_ALIGNED(dst_ptr, 8)) {
+    if (!filtering) {
+      ScaleRowDown38_3 = ScaleRowDown38_SSSE3;
+      ScaleRowDown38_2 = ScaleRowDown38_SSSE3;
+    } else {
+      ScaleRowDown38_3 = ScaleRowDown38_3_Int_SSSE3;
+      ScaleRowDown38_2 = ScaleRowDown38_2_Int_SSSE3;
+    }
+  } else
+#endif
+  {
+    if (!filtering) {
+      ScaleRowDown38_3 = ScaleRowDown38_C;
+      ScaleRowDown38_2 = ScaleRowDown38_C;
+    } else {
+      ScaleRowDown38_3 = ScaleRowDown38_3_Int_C;
+      ScaleRowDown38_2 = ScaleRowDown38_2_Int_C;
+    }
+  }
+  {
+  int src_row = 0;
+    int y;
+    for (y = 0; y < dst_height; ++y) {
+    switch (src_row) {
+      case 0:
+      case 1:
+        ScaleRowDown38_3(src_ptr, src_stride, dst_ptr, dst_width);
+        src_ptr += src_stride * 3;
+        ++src_row;
+        break;
+
+      case 2:
+        ScaleRowDown38_2(src_ptr, src_stride, dst_ptr, dst_width);
+        src_ptr += src_stride * 2;
+        src_row = 0;
+        break;
+    }
+    dst_ptr += dst_stride;
+  }
+}
+}
+
+__inline static uint32 SumBox(int iboxwidth, int iboxheight,
+                            int src_stride, const uint8* src_ptr) {
+  int x, y;
+  uint32 sum;
+  assert(iboxwidth > 0);
+  assert(iboxheight > 0);
+  sum = 0u;
+  for (y = 0; y < iboxheight; ++y) {
+    for (x = 0; x < iboxwidth; ++x) {
+      sum += src_ptr[x];
+    }
+    src_ptr += src_stride;
+  }
+  return sum;
+}
+
+static void ScalePlaneBoxRow(int dst_width, int boxheight,
+                             int dx, int src_stride,
+                             const uint8* src_ptr, uint8* dst_ptr) {
+  int x = 0;
+  int i;
+  for (i = 0; i < dst_width; ++i) {
+    int ix = x >> 16;
+    int boxwidth;
+    x += dx;
+    boxwidth = (x >> 16) - ix;
+    *dst_ptr++ = SumBox(boxwidth, boxheight, src_stride, src_ptr + ix) /
+        (boxwidth * boxheight);
+  }
+}
+
+__inline static uint32 SumPixels(int iboxwidth, const uint16* src_ptr) {
+  uint32 sum;
+  int x;
+  assert(iboxwidth > 0);
+  sum = 0u;
+  for (x = 0; x < iboxwidth; ++x) {
+    sum += src_ptr[x];
+  }
+  return sum;
+}
+
+static void ScaleAddCols2_C(int dst_width, int boxheight, int dx,
+                            const uint16* src_ptr, uint8* dst_ptr) {
+  int scaletbl[2];
+  int minboxwidth = (dx >> 16);
+  scaletbl[0] = 65536 / (minboxwidth * boxheight);
+  scaletbl[1] = 65536 / ((minboxwidth + 1) * boxheight);
+  {
+  int *scaleptr = scaletbl - minboxwidth;
+  int x = 0;
+    int i;
+    for (i = 0; i < dst_width; ++i) {
+    int ix = x >> 16;
+      int boxwidth;
+    x += dx;
+      boxwidth = (x >> 16) - ix;
+    *dst_ptr++ = SumPixels(boxwidth, src_ptr + ix) * scaleptr[boxwidth] >> 16;
+    }
+  }
+}
+
+static void ScaleAddCols1_C(int dst_width, int boxheight, int dx,
+                            const uint16* src_ptr, uint8* dst_ptr) {
+  int boxwidth = (dx >> 16);
+  int scaleval = 65536 / (boxwidth * boxheight);
+  int x = 0;
+  int i;
+  for (i = 0; i < dst_width; ++i) {
+    *dst_ptr++ = SumPixels(boxwidth, src_ptr + x) * scaleval >> 16;
+    x += boxwidth;
+  }
+}
+
+/**
+ * Scale plane down to any dimensions, with interpolation.
+ * (boxfilter).
+ *
+ * Same method as SimpleScale, which is fixed point, outputting
+ * one pixel of destination using fixed point (16.16) to step
+ * through source, sampling a box of pixel with simple
+ * averaging.
+ */
+static void ScalePlaneBox(int src_width, int src_height,
+                          int dst_width, int dst_height,
+                          int src_stride, int dst_stride,
+                          const uint8* src_ptr, uint8* dst_ptr) {
+  int dx, dy;
+  assert(dst_width > 0);
+  assert(dst_height > 0);
+  dy = (src_height << 16) / dst_height;
+  dx = (src_width << 16) / dst_width;
+  if (!IS_ALIGNED(src_width, 16) || (src_width > kMaxInputWidth) ||
+      dst_height * 2 > src_height) {
+    uint8* dst = dst_ptr;
+    int dy = (src_height << 16) / dst_height;
+    int dx = (src_width << 16) / dst_width;
+    int y = 0;
+    int j;
+    for (j = 0; j < dst_height; ++j) {
+      int iy = y >> 16;
+      const uint8* const src = src_ptr + iy * src_stride;
+      int boxheight;
+      y += dy;
+      if (y > (src_height << 16)) {
+        y = (src_height << 16);
+      }
+      boxheight = (y >> 16) - iy;
+      ScalePlaneBoxRow(dst_width, boxheight,
+                       dx, src_stride,
+                       src, dst);
+
+      dst += dst_stride;
+    }
+  } else {
+    ALIGN16(uint16 row[kMaxInputWidth]);
+    void (*ScaleAddRows)(const uint8* src_ptr, int src_stride,
+                         uint16* dst_ptr, int src_width, int src_height);
+    void (*ScaleAddCols)(int dst_width, int boxheight, int dx,
+                         const uint16* src_ptr, uint8* dst_ptr);
+#if defined(HAS_SCALEADDROWS_SSE2)
+    if (TestCpuFlag(kCpuHasSSE2) &&
+        IS_ALIGNED(src_stride, 16) && IS_ALIGNED(src_ptr, 16) &&
+        IS_ALIGNED(src_width, 16)) {
+      ScaleAddRows = ScaleAddRows_SSE2;
+    } else
+#endif
+    {
+      ScaleAddRows = ScaleAddRows_C;
+    }
+    if (dx & 0xffff) {
+      ScaleAddCols = ScaleAddCols2_C;
+    } else {
+      ScaleAddCols = ScaleAddCols1_C;
+    }
+
+    {
+    int y = 0;
+      int j;
+      for (j = 0; j < dst_height; ++j) {
+      int iy = y >> 16;
+      const uint8* const src = src_ptr + iy * src_stride;
+        int boxheight;
+      y += dy;
+      if (y > (src_height << 16)) {
+        y = (src_height << 16);
+      }
+        boxheight = (y >> 16) - iy;
+      ScaleAddRows(src, src_stride, row, src_width, boxheight);
+      ScaleAddCols(dst_width, boxheight, dx, row, dst_ptr);
+      dst_ptr += dst_stride;
+      }
+    }
+  }
+}
+
+/**
+ * Scale plane to/from any dimensions, with interpolation.
+ */
+static void ScalePlaneBilinearSimple(int src_width, int src_height,
+                                     int dst_width, int dst_height,
+                                     int src_stride, int dst_stride,
+                                     const uint8* src_ptr, uint8* dst_ptr) {
+  int i, j;
+  uint8* dst = dst_ptr;
+  int dx = (src_width << 16) / dst_width;
+  int dy = (src_height << 16) / dst_height;
+  int maxx = ((src_width - 1) << 16) - 1;
+  int maxy = ((src_height - 1) << 16) - 1;
+  int y = (dst_height < src_height) ? 32768 :
+      (src_height << 16) / dst_height - 32768;
+  for (i = 0; i < dst_height; ++i) {
+    int cy = (y < 0) ? 0 : y;
+    int yi = cy >> 16;
+    int yf = cy & 0xffff;
+    const uint8* const src = src_ptr + yi * src_stride;
+    int x = (dst_width < src_width) ? 32768 :
+        (src_width << 16) / dst_width - 32768;
+    for (j = 0; j < dst_width; ++j) {
+      int cx = (x < 0) ? 0 : x;
+      int xi = cx >> 16;
+      int xf = cx & 0xffff;
+      int r0 = (src[xi] * (65536 - xf) + src[xi + 1] * xf) >> 16;
+      int r1 = (src[xi + src_stride] * (65536 - xf) +
+          src[xi + src_stride + 1] * xf) >> 16;
+      *dst++ = (r0 * (65536 - yf) + r1 * yf) >> 16;
+      x += dx;
+      if (x > maxx)
+        x = maxx;
+    }
+    dst += dst_stride - dst_width;
+    y += dy;
+    if (y > maxy)
+      y = maxy;
+  }
+}
+
+/**
+ * Scale plane to/from any dimensions, with bilinear
+ * interpolation.
+ */
+static void ScalePlaneBilinear(int src_width, int src_height,
+                               int dst_width, int dst_height,
+                               int src_stride, int dst_stride,
+                               const uint8* src_ptr, uint8* dst_ptr) {
+  int dy;
+  int dx;
+  assert(dst_width > 0);
+  assert(dst_height > 0);
+  dy = (src_height << 16) / dst_height;
+  dx = (src_width << 16) / dst_width;
+  if (!IS_ALIGNED(src_width, 8) || (src_width > kMaxInputWidth)) {
+    ScalePlaneBilinearSimple(src_width, src_height, dst_width, dst_height,
+                             src_stride, dst_stride, src_ptr, dst_ptr);
+
+  } else {
+    ALIGN16(uint8 row[kMaxInputWidth + 1]);
+    void (*ScaleFilterRows)(uint8* dst_ptr, const uint8* src_ptr,
+                            int src_stride,
+                            int dst_width, int source_y_fraction);
+    void (*ScaleFilterCols)(uint8* dst_ptr, const uint8* src_ptr,
+                            int dst_width, int dx);
+#if defined(HAS_SCALEFILTERROWS_SSSE3)
+    if (TestCpuFlag(kCpuHasSSSE3) &&
+        IS_ALIGNED(src_stride, 16) && IS_ALIGNED(src_ptr, 16) &&
+        IS_ALIGNED(src_width, 16)) {
+      ScaleFilterRows = ScaleFilterRows_SSSE3;
+    } else
+#endif
+#if defined(HAS_SCALEFILTERROWS_SSE2)
+    if (TestCpuFlag(kCpuHasSSE2) &&
+        IS_ALIGNED(src_stride, 16) && IS_ALIGNED(src_ptr, 16) &&
+        IS_ALIGNED(src_width, 16)) {
+      ScaleFilterRows = ScaleFilterRows_SSE2;
+    } else
+#endif
+    {
+      ScaleFilterRows = ScaleFilterRows_C;
+    }
+    ScaleFilterCols = ScaleFilterCols_C;
+
+    {
+    int y = 0;
+    int maxy = ((src_height - 1) << 16) - 1; // max is filter of last 2 rows.
+      int j;
+      for (j = 0; j < dst_height; ++j) {
+      int iy = y >> 16;
+      int fy = (y >> 8) & 255;
+      const uint8* const src = src_ptr + iy * src_stride;
+      ScaleFilterRows(row, src, src_stride, src_width, fy);
+      ScaleFilterCols(dst_ptr, row, dst_width, dx);
+      dst_ptr += dst_stride;
+      y += dy;
+      if (y > maxy) {
+        y = maxy;
+      }
+    }
+  }
+}
+}
+
+/**
+ * Scale plane to/from any dimensions, without interpolation.
+ * Fixed point math is used for performance: The upper 16 bits
+ * of x and dx is the integer part of the source position and
+ * the lower 16 bits are the fixed decimal part.
+ */
+static void ScalePlaneSimple(int src_width, int src_height,
+                             int dst_width, int dst_height,
+                             int src_stride, int dst_stride,
+                             const uint8* src_ptr, uint8* dst_ptr) {
+  uint8* dst = dst_ptr;
+  int dx = (src_width << 16) / dst_width;
+  int y;
+  for (y = 0; y < dst_height; ++y) {
+    const uint8* const src = src_ptr + (y * src_height / dst_height) *
+        src_stride;
+    // TODO(fbarchard): Round X coordinate by setting x=0x8000.
+    int x = 0;
+    int i;
+    for (i = 0; i < dst_width; ++i) {
+      *dst++ = src[x >> 16];
+      x += dx;
+    }
+    dst += dst_stride - dst_width;
+  }
+}
+
+/**
+ * Scale plane to/from any dimensions.
+ */
+static void ScalePlaneAnySize(int src_width, int src_height,
+                              int dst_width, int dst_height,
+                              int src_stride, int dst_stride,
+                              const uint8* src_ptr, uint8* dst_ptr,
+                              FilterMode filtering) {
+  if (!filtering) {
+    ScalePlaneSimple(src_width, src_height, dst_width, dst_height,
+                     src_stride, dst_stride, src_ptr, dst_ptr);
+  } else {
+    // fall back to non-optimized version
+    ScalePlaneBilinear(src_width, src_height, dst_width, dst_height,
+                       src_stride, dst_stride, src_ptr, dst_ptr);
+  }
+}
+
+/**
+ * Scale plane down, any size
+ *
+ * This is an optimized version for scaling down a plane to any size.
+ * The current implementation is ~10 times faster compared to the
+ * reference implementation for e.g. XGA->LowResPAL
+ *
+ */
+static void ScalePlaneDown(int src_width, int src_height,
+                           int dst_width, int dst_height,
+                           int src_stride, int dst_stride,
+                           const uint8* src_ptr, uint8* dst_ptr,
+                           FilterMode filtering) {
+  if (!filtering) {
+    ScalePlaneSimple(src_width, src_height, dst_width, dst_height,
+                     src_stride, dst_stride, src_ptr, dst_ptr);
+  } else if (filtering == kFilterBilinear || src_height * 2 > dst_height) {
+    // between 1/2x and 1x use bilinear
+    ScalePlaneBilinear(src_width, src_height, dst_width, dst_height,
+                       src_stride, dst_stride, src_ptr, dst_ptr);
+  } else {
+    ScalePlaneBox(src_width, src_height, dst_width, dst_height,
+                  src_stride, dst_stride, src_ptr, dst_ptr);
+  }
+}
+
+/**
+ * Copy plane, no scaling
+ *
+ * This simply copies the given plane without scaling.
+ * The current implementation is ~115 times faster
+ * compared to the reference implementation.
+ *
+ */
+static void CopyPlane(int src_width, int src_height,
+                      int dst_width, int dst_height,
+                      int src_stride, int dst_stride,
+                      const uint8* src_ptr, uint8* dst_ptr) {
+  if (src_stride == src_width && dst_stride == dst_width) {
+    // All contiguous, so can use REALLY fast path.
+    memcpy(dst_ptr, src_ptr, src_width * src_height);
+  } else {
+    // Not all contiguous; must copy scanlines individually
+    const uint8* src = src_ptr;
+    uint8* dst = dst_ptr;
+    int i;
+    for (i = 0; i < src_height; ++i) {
+      memcpy(dst, src, src_width);
+      dst += dst_stride;
+      src += src_stride;
+    }
+  }
+}
+
+static void ScalePlane(const uint8* src, int src_stride,
+                       int src_width, int src_height,
+                       uint8* dst, int dst_stride,
+                       int dst_width, int dst_height,
+                       FilterMode filtering, int use_ref) {
+  // Use specialized scales to improve performance for common resolutions.
+  // For example, all the 1/2 scalings will use ScalePlaneDown2()
+  if (dst_width == src_width && dst_height == src_height) {
+    // Straight copy.
+    CopyPlane(src_width, src_height, dst_width, dst_height, src_stride,
+              dst_stride, src, dst);
+  } else if (dst_width <= src_width && dst_height <= src_height) {
+    // Scale down.
+    if (use_ref) {
+      // For testing, allow the optimized versions to be disabled.
+      ScalePlaneDown(src_width, src_height, dst_width, dst_height,
+                     src_stride, dst_stride, src, dst, filtering);
+    } else if (4 * dst_width == 3 * src_width &&
+               4 * dst_height == 3 * src_height) {
+      // optimized, 3/4
+      ScalePlaneDown34(src_width, src_height, dst_width, dst_height,
+                       src_stride, dst_stride, src, dst, filtering);
+    } else if (2 * dst_width == src_width && 2 * dst_height == src_height) {
+      // optimized, 1/2
+      ScalePlaneDown2(src_width, src_height, dst_width, dst_height,
+                      src_stride, dst_stride, src, dst, filtering);
+    // 3/8 rounded up for odd sized chroma height.
+    } else if (8 * dst_width == 3 * src_width &&
+               dst_height == ((src_height * 3 + 7) / 8)) {
+      // optimized, 3/8
+      ScalePlaneDown38(src_width, src_height, dst_width, dst_height,
+                       src_stride, dst_stride, src, dst, filtering);
+    } else if (4 * dst_width == src_width && 4 * dst_height == src_height) {
+      // optimized, 1/4
+      ScalePlaneDown4(src_width, src_height, dst_width, dst_height,
+                      src_stride, dst_stride, src, dst, filtering);
+    } else if (8 * dst_width == src_width && 8 * dst_height == src_height) {
+      // optimized, 1/8
+      ScalePlaneDown8(src_width, src_height, dst_width, dst_height,
+                      src_stride, dst_stride, src, dst, filtering);
+    } else {
+      // Arbitrary downsample
+      ScalePlaneDown(src_width, src_height, dst_width, dst_height,
+                     src_stride, dst_stride, src, dst, filtering);
+    }
+  } else {
+    // Arbitrary scale up and/or down.
+    ScalePlaneAnySize(src_width, src_height, dst_width, dst_height,
+                      src_stride, dst_stride, src, dst, filtering);
+  }
+}
+
+/**
+ * Scale a plane.
+ *
+ * This function in turn calls a scaling function
+ * suitable for handling the desired resolutions.
+ *
+ */
+
+int I420Scale(const uint8* src_y, int src_stride_y,
+              const uint8* src_u, int src_stride_u,
+              const uint8* src_v, int src_stride_v,
+              int src_width, int src_height,
+              uint8* dst_y, int dst_stride_y,
+              uint8* dst_u, int dst_stride_u,
+              uint8* dst_v, int dst_stride_v,
+              int dst_width, int dst_height,
+              FilterMode filtering) {
+  if (!src_y || !src_u || !src_v || src_width <= 0 || src_height == 0 ||
+      !dst_y || !dst_u || !dst_v || dst_width <= 0 || dst_height <= 0) {
+    return -1;
+  }
+  // Negative height means invert the image.
+  if (src_height < 0) {
+    int halfheight;
+    src_height = -src_height;
+    halfheight = (src_height + 1) >> 1;
+    src_y = src_y + (src_height - 1) * src_stride_y;
+    src_u = src_u + (halfheight - 1) * src_stride_u;
+    src_v = src_v + (halfheight - 1) * src_stride_v;
+    src_stride_y = -src_stride_y;
+    src_stride_u = -src_stride_u;
+    src_stride_v = -src_stride_v;
+  }
+  {
+  int src_halfwidth = (src_width + 1) >> 1;
+  int src_halfheight = (src_height + 1) >> 1;
+  int dst_halfwidth = (dst_width + 1) >> 1;
+  int dst_halfheight = (dst_height + 1) >> 1;
+
+    ScalePlane(src_y, src_stride_y, src_width, src_height,
+               dst_y, dst_stride_y, dst_width, dst_height,
+               filtering, use_reference_impl_);
+  ScalePlane(src_u, src_stride_u, src_halfwidth, src_halfheight,
+             dst_u, dst_stride_u, dst_halfwidth, dst_halfheight,
+             filtering, use_reference_impl_);
+  ScalePlane(src_v, src_stride_v, src_halfwidth, src_halfheight,
+             dst_v, dst_stride_v, dst_halfwidth, dst_halfheight,
+             filtering, use_reference_impl_);
+  }
+  return 0;
+}
+
+// Deprecated api
+int Scale(const uint8* src_y, const uint8* src_u, const uint8* src_v,
+          int src_stride_y, int src_stride_u, int src_stride_v,
+          int src_width, int src_height,
+          uint8* dst_y, uint8* dst_u, uint8* dst_v,
+          int dst_stride_y, int dst_stride_u, int dst_stride_v,
+          int dst_width, int dst_height,
+          int interpolate) {
+  if (!src_y || !src_u || !src_v || src_width <= 0 || src_height == 0 ||
+      !dst_y || !dst_u || !dst_v || dst_width <= 0 || dst_height <= 0) {
+    return -1;
+  }
+  // Negative height means invert the image.
+  if (src_height < 0) {
+    int halfheight;
+    src_height = -src_height;
+    halfheight = (src_height + 1) >> 1;
+    src_y = src_y + (src_height - 1) * src_stride_y;
+    src_u = src_u + (halfheight - 1) * src_stride_u;
+    src_v = src_v + (halfheight - 1) * src_stride_v;
+    src_stride_y = -src_stride_y;
+    src_stride_u = -src_stride_u;
+    src_stride_v = -src_stride_v;
+  }
+  {
+  int src_halfwidth = (src_width + 1) >> 1;
+  int src_halfheight = (src_height + 1) >> 1;
+  int dst_halfwidth = (dst_width + 1) >> 1;
+  int dst_halfheight = (dst_height + 1) >> 1;
+  FilterMode filtering = interpolate ? kFilterBox : kFilterNone;
+
+  ScalePlane(src_y, src_stride_y, src_width, src_height,
+             dst_y, dst_stride_y, dst_width, dst_height,
+             filtering, use_reference_impl_);
+  ScalePlane(src_u, src_stride_u, src_halfwidth, src_halfheight,
+             dst_u, dst_stride_u, dst_halfwidth, dst_halfheight,
+             filtering, use_reference_impl_);
+  ScalePlane(src_v, src_stride_v, src_halfwidth, src_halfheight,
+             dst_v, dst_stride_v, dst_halfwidth, dst_halfheight,
+             filtering, use_reference_impl_);
+  }
+  return 0;
+}
+
+// Deprecated api
+int ScaleOffset(const uint8* src, int src_width, int src_height,
+                uint8* dst, int dst_width, int dst_height, int dst_yoffset,
+          int interpolate) {
+  if (!src || src_width <= 0 || src_height <= 0 ||
+      !dst || dst_width <= 0 || dst_height <= 0 || dst_yoffset < 0 ||
+      dst_yoffset >= dst_height) {
+    return -1;
+  }
+  dst_yoffset = dst_yoffset & ~1;  // chroma requires offset to multiple of 2.
+  {
+  int src_halfwidth = (src_width + 1) >> 1;
+  int src_halfheight = (src_height + 1) >> 1;
+  int dst_halfwidth = (dst_width + 1) >> 1;
+  int dst_halfheight = (dst_height + 1) >> 1;
+  int aheight = dst_height - dst_yoffset * 2;  // actual output height
+  const uint8* const src_y = src;
+  const uint8* const src_u = src + src_width * src_height;
+  const uint8* const src_v = src + src_width * src_height +
+                             src_halfwidth * src_halfheight;
+  uint8* dst_y = dst + dst_yoffset * dst_width;
+  uint8* dst_u = dst + dst_width * dst_height +
+                 (dst_yoffset >> 1) * dst_halfwidth;
+  uint8* dst_v = dst + dst_width * dst_height + dst_halfwidth * dst_halfheight +
+                 (dst_yoffset >> 1) * dst_halfwidth;
+  return Scale(src_y, src_u, src_v, src_width, src_halfwidth, src_halfwidth,
+               src_width, src_height, dst_y, dst_u, dst_v, dst_width,
+               dst_halfwidth, dst_halfwidth, dst_width, aheight, interpolate);
+  }
+}
+
+#ifdef __cplusplus
+}  // extern "C"
+}  // namespace libyuv
+#endif
diff --git a/tools/author_first_release.sh b/tools/author_first_release.sh
new file mode 100755 (executable)
index 0000000..7b0b797
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/bash
+##
+## List the release each author first contributed to.
+##
+## Usage: author_first_release.sh [TAGS]
+##
+## If the TAGS arguments are unspecified, all tags reported by `git tag`
+## will be considered.
+##
+tags=${@:-$(git tag)}
+for tag in $tags; do
+  git shortlog -n -e -s $tag |
+      cut -f2- |
+      awk "{print \"${tag#v}\t\"\$0}"
+done | sort -k2  | uniq -f2
diff --git a/tools/ftfy.sh b/tools/ftfy.sh
new file mode 100755 (executable)
index 0000000..95fd397
--- /dev/null
@@ -0,0 +1,160 @@
+#!/bin/sh
+self="$0"
+dirname_self=$(dirname "$self")
+
+usage() {
+  cat <<EOF >&2
+Usage: $self [option]
+
+This script applies a whitespace transformation to the commit at HEAD. If no
+options are given, then the modified files are left in the working tree.
+
+Options:
+  -h, --help     Shows this message
+  -n, --dry-run  Shows a diff of the changes to be made.
+  --amend        Squashes the changes into the commit at HEAD
+                     This option will also reformat the commit message.
+  --commit       Creates a new commit containing only the whitespace changes
+  --msg-only     Reformat the commit message only, ignore the patch itself.
+
+EOF
+  rm -f ${CLEAN_FILES}
+  exit 1
+}
+
+
+log() {
+  echo "${self##*/}: $@" >&2
+}
+
+
+vpx_style() {
+  astyle --style=bsd --min-conditional-indent=0 --break-blocks \
+         --pad-oper --pad-header --unpad-paren \
+         --align-pointer=name \
+         --indent-preprocessor --convert-tabs --indent-labels \
+         --suffix=none --quiet "$@"
+  sed -i 's/[[:space:]]\{1,\},/,/g' "$@"
+}
+
+
+apply() {
+  [ $INTERSECT_RESULT -ne 0 ] && patch -p1 < "$1"
+}
+
+
+commit() {
+  LAST_CHANGEID=$(git show | awk '/Change-Id:/{print $2}')
+  if [ -z "$LAST_CHANGEID" ]; then
+    log "HEAD doesn't have a Change-Id, unable to generate a new commit"
+    exit 1
+  fi
+
+  # Build a deterministic Change-Id from the parent's
+  NEW_CHANGEID=${LAST_CHANGEID}-styled
+  NEW_CHANGEID=I$(echo $NEW_CHANGEID | git hash-object --stdin)
+
+  # Commit, preserving authorship from the parent commit.
+  git commit -a -C HEAD > /dev/null
+  git commit --amend -F- << EOF
+Cosmetic: Fix whitespace in change ${LAST_CHANGEID:0:9}
+
+Change-Id: ${NEW_CHANGEID}
+EOF
+}
+
+
+show_commit_msg_diff() {
+  if [ $DIFF_MSG_RESULT -ne 0 ]; then
+    log "Modified commit message:"
+    diff -u "$ORIG_COMMIT_MSG" "$NEW_COMMIT_MSG" | tail -n +3
+  fi
+}
+
+
+amend() {
+  show_commit_msg_diff
+  if [ $DIFF_MSG_RESULT -ne 0 ] || [ $INTERSECT_RESULT -ne 0 ]; then
+    git commit -a --amend -F "$NEW_COMMIT_MSG"
+  fi
+}
+
+
+diff_msg() {
+  git log -1 --format=%B > "$ORIG_COMMIT_MSG"
+  "${dirname_self}"/wrap-commit-msg.py \
+      < "$ORIG_COMMIT_MSG" > "$NEW_COMMIT_MSG"
+  cmp -s "$ORIG_COMMIT_MSG" "$NEW_COMMIT_MSG"
+  DIFF_MSG_RESULT=$?
+}
+
+
+# Temporary files
+ORIG_DIFF=orig.diff.$$
+MODIFIED_DIFF=modified.diff.$$
+FINAL_DIFF=final.diff.$$
+ORIG_COMMIT_MSG=orig.commit-msg.$$
+NEW_COMMIT_MSG=new.commit-msg.$$
+CLEAN_FILES="${ORIG_DIFF} ${MODIFIED_DIFF} ${FINAL_DIFF}"
+CLEAN_FILES="${CLEAN_FILES} ${ORIG_COMMIT_MSG} ${NEW_COMMIT_MSG}"
+
+# Preconditions
+[ $# -lt 2 ] || usage
+
+# Check that astyle supports pad-header and align-pointer=name
+if ! astyle --pad-header --align-pointer=name < /dev/null; then
+  log "Install astyle v1.24 or newer"
+  exit 1
+fi
+
+if ! git diff --quiet HEAD; then
+  log "Working tree is dirty, commit your changes first"
+  exit 1
+fi
+
+# Need to be in the root
+cd "$(git rev-parse --show-toplevel)"
+
+# Collect the original diff
+git show > "${ORIG_DIFF}"
+
+# Apply the style guide on new and modified files and collect its diff
+for f in $(git diff HEAD^ --name-only -M90 --diff-filter=AM \
+           | grep '\.[ch]$'); do
+  case "$f" in
+    third_party/*) continue;;
+    nestegg/*) continue;;
+  esac
+  vpx_style "$f"
+done
+git diff --no-color --no-ext-diff > "${MODIFIED_DIFF}"
+
+# Intersect the two diffs
+"${dirname_self}"/intersect-diffs.py \
+    "${ORIG_DIFF}" "${MODIFIED_DIFF}" > "${FINAL_DIFF}"
+INTERSECT_RESULT=$?
+git reset --hard >/dev/null
+
+# Fixup the commit message
+diff_msg
+
+# Handle options
+if [ -n "$1" ]; then
+  case "$1" in
+    -h|--help) usage;;
+    -n|--dry-run) cat "${FINAL_DIFF}"; show_commit_msg_diff;;
+    --commit) apply "${FINAL_DIFF}"; commit;;
+    --amend) apply "${FINAL_DIFF}"; amend;;
+    --msg-only) amend;;
+    *) usage;;
+  esac
+else
+  apply "${FINAL_DIFF}"
+  if ! git diff --quiet; then
+    log "Formatting changes applied, verify and commit."
+    log "See also: http://www.webmproject.org/code/contribute/conventions/"
+    git diff --stat
+  fi
+fi
+
+rm -f ${CLEAN_FILES}
diff --git a/tools/gen_authors.sh b/tools/gen_authors.sh
new file mode 100755 (executable)
index 0000000..e1246f0
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# Add organization names manually.
+
+cat <<EOF
+# This file is automatically generated from the git commit history
+# by tools/gen_authors.sh.
+
+$(git log --pretty=format:"%aN <%aE>" | sort | uniq)
+Google Inc.
+The Mozilla Foundation
+The Xiph.Org Foundation
+EOF
diff --git a/tools/intersect-diffs.py b/tools/intersect-diffs.py
new file mode 100755 (executable)
index 0000000..be9dea5
--- /dev/null
@@ -0,0 +1,188 @@
+#!/usr/bin/env python
+##  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+"""Calculates the "intersection" of two unified diffs.
+
+Given two diffs, A and B, it finds all hunks in B that had non-context lines
+in A and prints them to stdout. This is useful to determine the hunks in B that
+are relevant to A. The resulting file can be applied with patch(1) on top of A.
+"""
+
+__author__ = "jkoleszar@google.com"
+
+import re
+import sys
+
+
+class DiffLines(object):
+    """A container for one half of a diff."""
+
+    def __init__(self, filename, offset, length):
+        self.filename = filename
+        self.offset = offset
+        self.length = length
+        self.lines = []
+        self.delta_line_nums = []
+
+    def Append(self, line):
+        l = len(self.lines)
+        if line[0] != " ":
+            self.delta_line_nums.append(self.offset + l)
+        self.lines.append(line[1:])
+        assert l+1 <= self.length
+
+    def Complete(self):
+        return len(self.lines) == self.length
+
+    def __contains__(self, item):
+        return item >= self.offset and item <= self.offset + self.length - 1
+
+
+class DiffHunk(object):
+    """A container for one diff hunk, consisting of two DiffLines."""
+
+    def __init__(self, header, file_a, file_b, start_a, len_a, start_b, len_b):
+        self.header = header
+        self.left = DiffLines(file_a, start_a, len_a)
+        self.right = DiffLines(file_b, start_b, len_b)
+        self.lines = []
+
+    def Append(self, line):
+        """Adds a line to the DiffHunk and its DiffLines children."""
+        if line[0] == "-":
+            self.left.Append(line)
+        elif line[0] == "+":
+            self.right.Append(line)
+        elif line[0] == " ":
+            self.left.Append(line)
+            self.right.Append(line)
+        else:
+            assert False, ("Unrecognized character at start of diff line "
+                           "%r" % line[0])
+        self.lines.append(line)
+
+    def Complete(self):
+        return self.left.Complete() and self.right.Complete()
+
+    def __repr__(self):
+        return "DiffHunk(%s, %s, len %d)" % (
+            self.left.filename, self.right.filename,
+            max(self.left.length, self.right.length))
+
+
+def ParseDiffHunks(stream):
+    """Walk a file-like object, yielding DiffHunks as they're parsed."""
+
+    file_regex = re.compile(r"(\+\+\+|---) (\S+)")
+    range_regex = re.compile(r"@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))?")
+    hunk = None
+    while True:
+        line = stream.readline()
+        if not line:
+            break
+
+        if hunk is None:
+            # Parse file names
+            diff_file = file_regex.match(line)
+            if diff_file:
+              if line.startswith("---"):
+                  a_line = line
+                  a = diff_file.group(2)
+                  continue
+              if line.startswith("+++"):
+                  b_line = line
+                  b = diff_file.group(2)
+                  continue
+
+            # Parse offset/lengths
+            diffrange = range_regex.match(line)
+            if diffrange:
+                if diffrange.group(2):
+                    start_a = int(diffrange.group(1))
+                    len_a = int(diffrange.group(3))
+                else:
+                    start_a = 1
+                    len_a = int(diffrange.group(1))
+
+                if diffrange.group(5):
+                    start_b = int(diffrange.group(4))
+                    len_b = int(diffrange.group(6))
+                else:
+                    start_b = 1
+                    len_b = int(diffrange.group(4))
+
+                header = [a_line, b_line, line]
+                hunk = DiffHunk(header, a, b, start_a, len_a, start_b, len_b)
+        else:
+            # Add the current line to the hunk
+            hunk.Append(line)
+
+            # See if the whole hunk has been parsed. If so, yield it and prepare
+            # for the next hunk.
+            if hunk.Complete():
+                yield hunk
+                hunk = None
+
+    # Partial hunks are a parse error
+    assert hunk is None
+
+
+def FormatDiffHunks(hunks):
+    """Re-serialize a list of DiffHunks."""
+    r = []
+    last_header = None
+    for hunk in hunks:
+        this_header = hunk.header[0:2]
+        if last_header != this_header:
+            r.extend(hunk.header)
+            last_header = this_header
+        else:
+            r.extend(hunk.header[2])
+        r.extend(hunk.lines)
+        r.append("\n")
+    return "".join(r)
+
+
+def ZipHunks(rhs_hunks, lhs_hunks):
+    """Join two hunk lists on filename."""
+    for rhs_hunk in rhs_hunks:
+        rhs_file = rhs_hunk.right.filename.split("/")[1:]
+
+        for lhs_hunk in lhs_hunks:
+            lhs_file = lhs_hunk.left.filename.split("/")[1:]
+            if lhs_file != rhs_file:
+                continue
+            yield (rhs_hunk, lhs_hunk)
+
+
+def main():
+    old_hunks = [x for x in ParseDiffHunks(open(sys.argv[1], "r"))]
+    new_hunks = [x for x in ParseDiffHunks(open(sys.argv[2], "r"))]
+    out_hunks = []
+
+    # Join the right hand side of the older diff with the left hand side of the
+    # newer diff.
+    for old_hunk, new_hunk in ZipHunks(old_hunks, new_hunks):
+        if new_hunk in out_hunks:
+            continue
+        old_lines = old_hunk.right
+        new_lines = new_hunk.left
+
+        # Determine if this hunk overlaps any non-context line from the other
+        for i in old_lines.delta_line_nums:
+            if i in new_lines:
+                out_hunks.append(new_hunk)
+                break
+
+    if out_hunks:
+        print FormatDiffHunks(out_hunks)
+        sys.exit(1)
+
+if __name__ == "__main__":
+    main()
diff --git a/tools/wrap-commit-msg.py b/tools/wrap-commit-msg.py
new file mode 100755 (executable)
index 0000000..d5b4b04
--- /dev/null
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+##  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+"""Wraps paragraphs of text, preserving manual formatting
+
+This is like fold(1), but has the special convention of not modifying lines
+that start with whitespace. This allows you to intersperse blocks with
+special formatting, like code blocks, with written prose. The prose will
+be wordwrapped, and the manual formatting will be preserved.
+
+ * This won't handle the case of a bulleted (or ordered) list specially, so
+   manual wrapping must be done.
+
+Occasionally it's useful to put something with explicit formatting that
+doesn't look at all like a block of text inline.
+
+  indicator = has_leading_whitespace(line);
+  if (indicator)
+    preserve_formatting(line);
+
+The intent is that this docstring would make it through the transform
+and still be legible and presented as it is in the source. If additional
+cases are handled, update this doc to describe the effect.
+"""
+
+__author__ = "jkoleszar@google.com"
+import textwrap
+import sys
+
+def wrap(text):
+    if text:
+        return textwrap.fill(text, break_long_words=False) + '\n'
+    return ""
+
+
+def main(fileobj):
+    text = ""
+    output = ""
+    while True:
+        line = fileobj.readline()
+        if not line:
+            break
+
+        if line.lstrip() == line:
+            text += line
+        else:
+            output += wrap(text)
+            text=""
+            output += line
+    output += wrap(text)
+
+    # Replace the file or write to stdout.
+    if fileobj == sys.stdin:
+        fileobj = sys.stdout
+    else:
+        fileobj.seek(0)
+        fileobj.truncate(0)
+    fileobj.write(output)
+
+if __name__ == "__main__":
+    if len(sys.argv) > 1:
+        main(open(sys.argv[1], "r+"))
+    else:
+        main(sys.stdin)
diff --git a/tools_common.c b/tools_common.c
new file mode 100644 (file)
index 0000000..6f95028
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#include <stdio.h>
+#include "tools_common.h"
+#if defined(_WIN32) || defined(__OS2__)
+#include <io.h>
+#include <fcntl.h>
+
+#ifdef __OS2__
+#define _setmode    setmode
+#define _fileno     fileno
+#define _O_BINARY   O_BINARY
+#endif
+#endif
+
+FILE* set_binary_mode(FILE *stream)
+{
+    (void)stream;
+#if defined(_WIN32) || defined(__OS2__)
+    _setmode(_fileno(stream), _O_BINARY);
+#endif
+    return stream;
+}
diff --git a/tools_common.h b/tools_common.h
new file mode 100644 (file)
index 0000000..80c9747
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TOOLS_COMMON_H
+#define TOOLS_COMMON_H
+
+/* Sets a stdio stream into binary mode */
+FILE* set_binary_mode(FILE *stream);
+
+#endif
diff --git a/usage.dox b/usage.dox
new file mode 100644 (file)
index 0000000..92fd6b2
--- /dev/null
+++ b/usage.dox
@@ -0,0 +1,208 @@
+/*!\page usage Usage
+
+    The vpx multi-format codec SDK provides a unified interface amongst its
+    supported codecs. This abstraction allows applications using this SDK to
+    easily support multiple video formats with minimal code duplication or
+    "special casing." This section describes the interface common to all codecs.
+    For codec-specific details, see the \ref codecs page.
+
+    The following sections are common to all codecs:
+    - \ref usage_types
+    - \ref usage_features
+    - \ref usage_init
+    - \ref usage_errors
+
+    Fore more information on decoder and encoder specific usage, see the
+    following pages:
+    \if decoder
+    - \subpage usage_decode
+    \endif
+    \if decoder
+    - \subpage usage_encode
+    \endif
+
+    \section usage_types Important Data Types
+    There are two important data structures to consider in this interface.
+
+    \subsection usage_ctxs Contexts
+    A context is a storage area allocated by the calling application that the
+    codec may write into to store details about a single instance of that codec.
+    Most of the context is implementation specific, and thus opaque to the
+    application. The context structure as seen by the application is of fixed
+    size, and thus can be allocated with automatic storage or dynamically
+    on the heap.
+
+    Most operations require an initialized codec context. Codec context
+    instances are codec specific. That is, the codec to be used for the encoded
+    video must be known at initialization time. See #vpx_codec_ctx_t for further
+    information.
+
+    \subsection usage_ifaces Interfaces
+    A codec interface is an opaque structure that controls how function calls
+    into the generic interface are dispatched to their codec-specific
+    implementations. Applications \ref MUSTNOT attempt to examine or override
+    this storage, as it contains internal implementation details likely to
+    change from release to release.
+
+    Each supported codec will expose an interface structure to the application
+    as an <code>extern</code> reference to a structure of the incomplete type
+    #vpx_codec_iface_t.
+
+    \section usage_features Features
+    Several "features" are defined that are optionally implemented by codec
+    algorithms. Indeed, the same algorithm may support different features on
+    different platforms. The purpose of defining these features is that when
+    they are implemented, they conform to a common interface. The features, or
+    capabilities, of an algorithm can be queried from it's interface by using
+    the vpx_codec_get_caps() method. Attempts to invoke features not supported
+    by an algorithm will generally result in #VPX_CODEC_INCAPABLE.
+
+    Currently defined features available in both encoders and decoders include:
+    - \subpage usage_xma
+
+    \if decoder
+    Currently defined decoder features include:
+    - \ref usage_cb
+    - \ref usage_postproc
+    \endif
+
+    \section usage_init Initialization
+    To initialize a codec instance, the address of the codec context
+    and interface structures are passed to an initialization function. Depending
+    on the \ref usage_features that the codec supports, the codec could be
+    initialized in different modes. Most notably, the application may choose to
+    use \ref usage_xma mode to gain fine grained control over how and where
+    memory is allocated for the codec.
+
+    To prevent cases of confusion where the ABI of the library changes,
+    the ABI is versioned. The ABI version number must be passed at
+    initialization time to ensure the application is using a header file that
+    matches the library. The current ABI version number is stored in the
+    preprocessor macros #VPX_CODEC_ABI_VERSION, #VPX_ENCODER_ABI_VERSION, and
+    #VPX_DECODER_ABI_VERSION. For convenience, each initialization function has
+    a wrapper macro that inserts the correct version number. These macros are
+    named like the initialization methods, but without the _ver suffix.
+
+
+    The available initialization methods are:
+    \if encoder - #vpx_codec_enc_init (calls vpx_codec_enc_init_ver()) \endif
+    \if multi-encoder - #vpx_codec_enc_init_multi (calls vpx_codec_enc_init_multi_ver()) \endif
+    \if decoder - #vpx_codec_dec_init (calls vpx_codec_dec_init_ver()) \endif
+
+
+
+    \section usage_errors Error Handling
+    Almost all codec functions return an error status of type #vpx_codec_err_t.
+    The semantics of how each error condition should be processed is clearly
+    defined in the definitions of each enumerated value. Error values can be
+    converted into ASCII strings with the vpx_codec_error() and
+    vpx_codec_err_to_string() methods. The difference between these two methods is
+    that vpx_codec_error() returns the error state from an initialized context,
+    whereas vpx_codec_err_to_string() can be used in cases where an error occurs
+    outside any context. The enumerated value returned from the last call can be
+    retrieved from the <code>err</code> member of the decoder context as well.
+    Finally, more detailed error information may be able to be obtained by using
+    the vpx_codec_error_detail() method. Not all errors produce detailed error
+    information.
+
+    In addition to error information, the codec library's build configuration
+    is available at runtime on some platforms. This information can be returned
+    by calling vpx_codec_build_config(), and is formatted as a base64 coded string
+    (comprised of characters in the set [a-z_a-Z0-9+/]). This information is not
+    useful to an application at runtime, but may be of use to vpx for support.
+
+
+    \section usage_deadline Deadline
+    Both the encoding and decoding functions have a <code>deadline</code>
+    parameter. This parameter indicates the amount of time, in microseconds
+    (us), that the application wants the codec to spend processing before
+    returning. This is a soft deadline -- that is, the semantics of the
+    requested operation take precedence over meeting the deadline. If, for
+    example, an application sets a <code>deadline</code> of 1000us, and the
+    frame takes 2000us to decode, the call to vpx_codec_decode() will return
+    after 2000us. In this case the deadline is not met, but the semantics of the
+    function are preserved. If, for the same frame, an application instead sets
+    a <code>deadline</code> of 5000us, the decoder will see that it has 3000us
+    remaining in its time slice when decoding completes. It could then choose to
+    run a set of \ref usage_postproc filters, and perhaps would return after
+    4000us (instead of the allocated 5000us). In this case the deadline is met,
+    and the semantics of the call are preserved, as before.
+
+    The special value <code>0</code> is reserved to represent an infinite
+    deadline. In this case, the codec will perform as much processing as
+    possible to yield the highest quality frame.
+
+    By convention, the value <code>1</code> is used to mean "return as fast as
+    possible."
+
+*/
+
+
+/*! \page usage_xma External Memory Allocation
+    Applications that wish to have fine grained control over how and where
+    decoders allocate memory \ref MAY make use of the eXternal Memory Allocation
+    (XMA) interface. Not all codecs support the XMA \ref usage_features.
+
+    To use a decoder in XMA mode, the decoder \ref MUST be initialized with the
+    vpx_codec_xma_init_ver() function. The amount of memory a decoder needs to
+    allocate is heavily dependent on the size of the encoded video frames. The
+    size of the video must be known before requesting the decoder's memory map.
+    This stream information can be obtained with the vpx_codec_peek_stream_info()
+    function, which does not require a constructed decoder context. If the exact
+    stream is not known, a stream info structure can be created that reflects
+    the maximum size that the decoder instance is required to support.
+
+    Once the decoder instance has been initialized and the stream information
+    determined, the application calls the vpx_codec_get_mem_map() iterator
+    repeatedly to get a list of the memory segments requested by the decoder.
+    The iterator value should be initialized to NULL to request the first
+    element, and the function will return #VPX_CODEC_LIST_END to signal the end of
+    the list.
+
+    After each segment is identified, it must be passed to the codec through the
+    vpx_codec_set_mem_map() function. Segments \ref MUST be passed in the same
+    order as they are returned from vpx_codec_get_mem_map(), but there is no
+    requirement that vpx_codec_get_mem_map() must finish iterating before
+    vpx_codec_set_mem_map() is called. For instance, some applications may choose
+    to get a list of all requests, construct an optimal heap, and then set all
+    maps at once with one call. Other applications may set one map at a time,
+    allocating it immediately after it is returned from vpx_codec_get_mem_map().
+
+    After all segments have been set using vpx_codec_set_mem_map(), the codec may
+    be used as it would be in normal internal allocation mode.
+
+    \section usage_xma_seg_id Segment Identifiers
+    Each requested segment is identified by an identifier unique to
+    that decoder type. Some of these identifiers are private, while others are
+    enumerated for application use. Identifiers not enumerated publicly are
+    subject to change. Identifiers are non-consecutive.
+
+    \section usage_xma_seg_szalign Segment Size and Alignment
+    The sz (size) and align (alignment) parameters describe the required size
+    and alignment of the requested segment. Alignment will always be a power of
+    two. Applications \ref MUST honor the alignment requested. Failure to do so
+    could result in program crashes or may incur a speed penalty.
+
+    \section usage_xma_seg_flags Segment Flags
+    The flags member of the segment structure indicates any requirements or
+    desires of the codec for the particular segment. The #VPX_CODEC_MEM_ZERO flag
+    indicates that the segment \ref MUST be zeroed by the application prior to
+    passing it to the application. The #VPX_CODEC_MEM_WRONLY flag indicates that
+    the segment will only be written into by the decoder, not read. If this flag
+    is not set, the application \ref MUST insure that the memory segment is
+    readable. On some platforms, framebuffer memory is writable but not
+    readable, for example. The #VPX_CODEC_MEM_FAST flag indicates that the segment
+    will be frequently accessed, and that it should be placed into fast memory,
+    if any is available. The application \ref MAY choose to place other segments
+    in fast memory as well, but the most critical segments will be identified by
+    this flag.
+
+    \section usage_xma_seg_basedtor Segment Base Address and Destructor
+    For each requested memory segment, the application must determine the
+    address of a memory segment that meets the requirements of the codec. This
+    address is set in the <code>base</code> member of the #vpx_codec_mmap
+    structure. If the application requires processing when the segment is no
+    longer used by the codec (for instance to deallocate it or close an
+    associated file descriptor) the <code>dtor</code> and <code>priv</code>
+    members can be set.
+*/
diff --git a/usage_cx.dox b/usage_cx.dox
new file mode 100644 (file)
index 0000000..62f3e45
--- /dev/null
@@ -0,0 +1,13 @@
+/*! \page usage_encode Encode
+
+    The vpx_codec_encode() function is at the core of the encode loop. It
+    processes raw images passed by the application, producing packets of
+    compressed data. The <code>deadline</code> parameter controls the amount
+    of time in microseconds the encoder should spend working on the frame. For
+    more information on the <code>deadline</code> parameter, see
+    \ref usage_deadline.
+
+
+    \ref samples
+
+*/
diff --git a/usage_dx.dox b/usage_dx.dox
new file mode 100644 (file)
index 0000000..883ce24
--- /dev/null
@@ -0,0 +1,62 @@
+/*! \page usage_decode Decoding
+
+    The vpx_codec_decode() function is at the core of the decode loop. It
+    processes packets of compressed data passed by the application, producing
+    decoded images. The decoder expects packets to comprise exactly one image
+    frame of data. Packets \ref MUST be passed in decode order. If the
+    application wishes to associate some data with the frame, the
+    <code>user_priv</code> member may be set. The <code>deadline</code>
+    parameter controls the amount of time in microseconds the decoder should
+    spend working on the frame. This is typically used to support adaptive
+    \ref usage_postproc based on the amount of free CPU time. For more
+    information on the <code>deadline</code> parameter, see \ref usage_deadline.
+
+    \ref samples
+
+
+    \section usage_cb Callback Based Decoding
+    There are two methods for the application to access decoded frame data. Some
+    codecs support asynchronous (callback-based) decoding \ref usage_features
+    that allow the application to register a callback to be invoked by the
+    decoder when decoded data becomes available. Decoders are not required to
+    support this feature, however. Like all \ref usage_features, support can be
+    determined by calling vpx_codec_get_caps(). Callbacks are available in both
+    frame-based and slice-based variants. Frame based callbacks conform to the
+    signature of #vpx_codec_put_frame_cb_fn_t and are invoked once the entire
+    frame has been decoded. Slice based callbacks conform to the signature of
+    #vpx_codec_put_slice_cb_fn_t and are invoked after a subsection of the frame
+    is decoded. For example, a slice callback could be issued for each
+    macroblock row. However, the number and size of slices to return is
+    implementation specific. Also, the image data passed in a slice callback is
+    not necessarily in the same memory segment as the data will be when it is
+    assembled into a full frame. For this reason, the application \ref MUST
+    examine the rectangles that describe what data is valid to access and what
+    data has been updated in this call. For all their additional complexity,
+    slice based decoding callbacks provide substantial speed gains to the
+    overall application in some cases, due to improved cache behavior.
+
+
+    \section usage_frame_iter Frame Iterator Based Decoding
+    If the codec does not support callback based decoding, or the application
+    chooses not to make use of that feature, decoded frames are made available
+    through the vpx_codec_get_frame() iterator. The application initializes the
+    iterator storage (of type #vpx_codec_iter_t) to NULL, then calls
+    vpx_codec_get_frame repeatedly until it returns NULL, indicating that all
+    images have been returned. This process may result in zero, one, or many
+    frames that are ready for display, depending on the codec.
+
+
+    \section usage_postproc Postprocessing
+    Postprocessing is a process that is applied after a frame is decoded to
+    enhance the image's appearance by removing artifacts introduced in the
+    compression process. It is not required to properly decode the frame, and
+    is generally done only when there is enough spare CPU time to execute
+    the required filters. Codecs may support a number of different
+    postprocessing filters, and the available filters may differ from platform
+    to platform. Embedded devices often do not have enough CPU to implement
+    postprocessing in software. The filter selection is generally handled
+    automatically by the codec, depending on the amount of time remaining before
+    hitting the user-specified \ref usage_deadline after decoding the frame.
+
+
+*/
diff --git a/vp8/common/alloccommon.c b/vp8/common/alloccommon.c
new file mode 100644 (file)
index 0000000..d58e49c
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "blockd.h"
+#include "vpx_mem/vpx_mem.h"
+#include "onyxc_int.h"
+#include "findnearmv.h"
+#include "entropymode.h"
+#include "systemdependent.h"
+
+
+extern  void vp8_init_scan_order_mask();
+
+static void update_mode_info_border(MODE_INFO *mi, int rows, int cols)
+{
+    int i;
+    vpx_memset(mi - cols - 2, 0, sizeof(MODE_INFO) * (cols + 1));
+
+    for (i = 0; i < rows; i++)
+    {
+        /* TODO(holmer): Bug? This updates the last element of each row
+         * rather than the border element!
+         */
+        vpx_memset(&mi[i*cols-1], 0, sizeof(MODE_INFO));
+    }
+}
+
+void vp8_de_alloc_frame_buffers(VP8_COMMON *oci)
+{
+    int i;
+    for (i = 0; i < NUM_YV12_BUFFERS; i++)
+        vp8_yv12_de_alloc_frame_buffer(&oci->yv12_fb[i]);
+
+    vp8_yv12_de_alloc_frame_buffer(&oci->temp_scale_frame);
+#if CONFIG_POSTPROC
+    vp8_yv12_de_alloc_frame_buffer(&oci->post_proc_buffer);
+    if (oci->post_proc_buffer_int_used)
+        vp8_yv12_de_alloc_frame_buffer(&oci->post_proc_buffer_int);
+#endif
+
+    vpx_free(oci->above_context);
+    vpx_free(oci->mip);
+    vpx_free(oci->prev_mip);
+
+    oci->above_context = 0;
+    oci->mip = 0;
+    oci->prev_mip = 0;
+
+}
+
+int vp8_alloc_frame_buffers(VP8_COMMON *oci, int width, int height)
+{
+    int i;
+
+    vp8_de_alloc_frame_buffers(oci);
+
+    /* our internal buffers are always multiples of 16 */
+    if ((width & 0xf) != 0)
+        width += 16 - (width & 0xf);
+
+    if ((height & 0xf) != 0)
+        height += 16 - (height & 0xf);
+
+
+    for (i = 0; i < NUM_YV12_BUFFERS; i++)
+    {
+        oci->fb_idx_ref_cnt[i] = 0;
+        oci->yv12_fb[i].flags = 0;
+        if (vp8_yv12_alloc_frame_buffer(&oci->yv12_fb[i], width, height, VP8BORDERINPIXELS) < 0)
+        {
+            vp8_de_alloc_frame_buffers(oci);
+            return 1;
+        }
+    }
+
+    oci->new_fb_idx = 0;
+    oci->lst_fb_idx = 1;
+    oci->gld_fb_idx = 2;
+    oci->alt_fb_idx = 3;
+
+    oci->fb_idx_ref_cnt[0] = 1;
+    oci->fb_idx_ref_cnt[1] = 1;
+    oci->fb_idx_ref_cnt[2] = 1;
+    oci->fb_idx_ref_cnt[3] = 1;
+
+    if (vp8_yv12_alloc_frame_buffer(&oci->temp_scale_frame,   width, 16, VP8BORDERINPIXELS) < 0)
+    {
+        vp8_de_alloc_frame_buffers(oci);
+        return 1;
+    }
+
+#if CONFIG_POSTPROC
+    if (vp8_yv12_alloc_frame_buffer(&oci->post_proc_buffer, width, height, VP8BORDERINPIXELS) < 0)
+    {
+        vp8_de_alloc_frame_buffers(oci);
+        return 1;
+    }
+
+    oci->post_proc_buffer_int_used = 0;
+    vpx_memset(&oci->postproc_state, 0, sizeof(oci->postproc_state));
+    vpx_memset((&oci->post_proc_buffer)->buffer_alloc,128,(&oci->post_proc_buffer)->frame_size);
+#endif
+
+    oci->mb_rows = height >> 4;
+    oci->mb_cols = width >> 4;
+    oci->MBs = oci->mb_rows * oci->mb_cols;
+    oci->mode_info_stride = oci->mb_cols + 1;
+    oci->mip = vpx_calloc((oci->mb_cols + 1) * (oci->mb_rows + 1), sizeof(MODE_INFO));
+
+    if (!oci->mip)
+    {
+        vp8_de_alloc_frame_buffers(oci);
+        return 1;
+    }
+
+    oci->mi = oci->mip + oci->mode_info_stride + 1;
+
+    /* allocate memory for last frame MODE_INFO array */
+#if CONFIG_ERROR_CONCEALMENT
+    oci->prev_mip = vpx_calloc((oci->mb_cols + 1) * (oci->mb_rows + 1), sizeof(MODE_INFO));
+
+    if (!oci->prev_mip)
+    {
+        vp8_de_alloc_frame_buffers(oci);
+        return 1;
+    }
+
+    oci->prev_mi = oci->prev_mip + oci->mode_info_stride + 1;
+#else
+    oci->prev_mip = NULL;
+    oci->prev_mi = NULL;
+#endif
+
+    oci->above_context = vpx_calloc(sizeof(ENTROPY_CONTEXT_PLANES) * oci->mb_cols, 1);
+
+    if (!oci->above_context)
+    {
+        vp8_de_alloc_frame_buffers(oci);
+        return 1;
+    }
+
+    update_mode_info_border(oci->mi, oci->mb_rows, oci->mb_cols);
+#if CONFIG_ERROR_CONCEALMENT
+    update_mode_info_border(oci->prev_mi, oci->mb_rows, oci->mb_cols);
+#endif
+
+    return 0;
+}
+void vp8_setup_version(VP8_COMMON *cm)
+{
+    switch (cm->version)
+    {
+    case 0:
+        cm->no_lpf = 0;
+        cm->filter_type = NORMAL_LOOPFILTER;
+        cm->use_bilinear_mc_filter = 0;
+        cm->full_pixel = 0;
+        break;
+    case 1:
+        cm->no_lpf = 0;
+        cm->filter_type = SIMPLE_LOOPFILTER;
+        cm->use_bilinear_mc_filter = 1;
+        cm->full_pixel = 0;
+        break;
+    case 2:
+        cm->no_lpf = 1;
+        cm->filter_type = NORMAL_LOOPFILTER;
+        cm->use_bilinear_mc_filter = 1;
+        cm->full_pixel = 0;
+        break;
+    case 3:
+        cm->no_lpf = 1;
+        cm->filter_type = SIMPLE_LOOPFILTER;
+        cm->use_bilinear_mc_filter = 1;
+        cm->full_pixel = 1;
+        break;
+    default:
+        /*4,5,6,7 are reserved for future use*/
+        cm->no_lpf = 0;
+        cm->filter_type = NORMAL_LOOPFILTER;
+        cm->use_bilinear_mc_filter = 0;
+        cm->full_pixel = 0;
+        break;
+    }
+}
+void vp8_create_common(VP8_COMMON *oci)
+{
+    vp8_machine_specific_config(oci);
+
+    vp8_init_mbmode_probs(oci);
+    vp8_default_bmode_probs(oci->fc.bmode_prob);
+
+    oci->mb_no_coeff_skip = 1;
+    oci->no_lpf = 0;
+    oci->filter_type = NORMAL_LOOPFILTER;
+    oci->use_bilinear_mc_filter = 0;
+    oci->full_pixel = 0;
+    oci->multi_token_partition = ONE_PARTITION;
+    oci->clr_type = REG_YUV;
+    oci->clamp_type = RECON_CLAMP_REQUIRED;
+
+    /* Initialize reference frame sign bias structure to defaults */
+    vpx_memset(oci->ref_frame_sign_bias, 0, sizeof(oci->ref_frame_sign_bias));
+
+    /* Default disable buffer to buffer copying */
+    oci->copy_buffer_to_gf = 0;
+    oci->copy_buffer_to_arf = 0;
+}
+
+void vp8_remove_common(VP8_COMMON *oci)
+{
+    vp8_de_alloc_frame_buffers(oci);
+}
diff --git a/vp8/common/alloccommon.h b/vp8/common/alloccommon.h
new file mode 100644 (file)
index 0000000..ea93c25
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_ALLOCCOMMON_H
+#define __INC_ALLOCCOMMON_H
+
+#include "onyxc_int.h"
+
+void vp8_create_common(VP8_COMMON *oci);
+void vp8_remove_common(VP8_COMMON *oci);
+void vp8_de_alloc_frame_buffers(VP8_COMMON *oci);
+int vp8_alloc_frame_buffers(VP8_COMMON *oci, int width, int height);
+void vp8_setup_version(VP8_COMMON *oci);
+
+#endif
diff --git a/vp8/common/arm/armv6/bilinearfilter_v6.asm b/vp8/common/arm/armv6/bilinearfilter_v6.asm
new file mode 100644 (file)
index 0000000..9704b42
--- /dev/null
@@ -0,0 +1,237 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_filter_block2d_bil_first_pass_armv6|
+    EXPORT  |vp8_filter_block2d_bil_second_pass_armv6|
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+
+;-------------------------------------
+; r0    unsigned char  *src_ptr,
+; r1    unsigned short *dst_ptr,
+; r2    unsigned int    src_pitch,
+; r3    unsigned int    height,
+; stack unsigned int    width,
+; stack const short    *vp8_filter
+;-------------------------------------
+; The output is transposed stroed in output array to make it easy for second pass filtering.
+|vp8_filter_block2d_bil_first_pass_armv6| PROC
+    stmdb   sp!, {r4 - r11, lr}
+
+    ldr     r11, [sp, #40]                  ; vp8_filter address
+    ldr     r4, [sp, #36]                   ; width
+
+    mov     r12, r3                         ; outer-loop counter
+
+    add     r7, r2, r4                      ; preload next row
+    pld     [r0, r7]
+
+    sub     r2, r2, r4                      ; src increment for height loop
+
+    ldr     r5, [r11]                       ; load up filter coefficients
+
+    mov     r3, r3, lsl #1                  ; height*2
+    add     r3, r3, #2                      ; plus 2 to make output buffer 4-bit aligned since height is actually (height+1)
+
+    mov     r11, r1                         ; save dst_ptr for each row
+
+    cmp     r5, #128                        ; if filter coef = 128, then skip the filter
+    beq     bil_null_1st_filter
+
+|bil_height_loop_1st_v6|
+    ldrb    r6, [r0]                        ; load source data
+    ldrb    r7, [r0, #1]
+    ldrb    r8, [r0, #2]
+    mov     lr, r4, lsr #2                  ; 4-in-parellel loop counter
+
+|bil_width_loop_1st_v6|
+    ldrb    r9, [r0, #3]
+    ldrb    r10, [r0, #4]
+
+    pkhbt   r6, r6, r7, lsl #16             ; src[1] | src[0]
+    pkhbt   r7, r7, r8, lsl #16             ; src[2] | src[1]
+
+    smuad   r6, r6, r5                      ; apply the filter
+    pkhbt   r8, r8, r9, lsl #16             ; src[3] | src[2]
+    smuad   r7, r7, r5
+    pkhbt   r9, r9, r10, lsl #16            ; src[4] | src[3]
+
+    smuad   r8, r8, r5
+    smuad   r9, r9, r5
+
+    add     r0, r0, #4
+    subs    lr, lr, #1
+
+    add     r6, r6, #0x40                   ; round_shift_and_clamp
+    add     r7, r7, #0x40
+    usat    r6, #16, r6, asr #7
+    usat    r7, #16, r7, asr #7
+
+    strh    r6, [r1], r3                    ; result is transposed and stored
+
+    add     r8, r8, #0x40                   ; round_shift_and_clamp
+    strh    r7, [r1], r3
+    add     r9, r9, #0x40
+    usat    r8, #16, r8, asr #7
+    usat    r9, #16, r9, asr #7
+
+    strh    r8, [r1], r3                    ; result is transposed and stored
+
+    ldrneb  r6, [r0]                        ; load source data
+    strh    r9, [r1], r3
+
+    ldrneb  r7, [r0, #1]
+    ldrneb  r8, [r0, #2]
+
+    bne     bil_width_loop_1st_v6
+
+    add     r0, r0, r2                      ; move to next input row
+    subs    r12, r12, #1
+
+    add     r9, r2, r4, lsl #1              ; adding back block width
+    pld     [r0, r9]                        ; preload next row
+
+    add     r11, r11, #2                    ; move over to next column
+    mov     r1, r11
+
+    bne     bil_height_loop_1st_v6
+
+    ldmia   sp!, {r4 - r11, pc}
+
+|bil_null_1st_filter|
+|bil_height_loop_null_1st|
+    mov     lr, r4, lsr #2                  ; loop counter
+
+|bil_width_loop_null_1st|
+    ldrb    r6, [r0]                        ; load data
+    ldrb    r7, [r0, #1]
+    ldrb    r8, [r0, #2]
+    ldrb    r9, [r0, #3]
+
+    strh    r6, [r1], r3                    ; store it to immediate buffer
+    add     r0, r0, #4
+    strh    r7, [r1], r3
+    subs    lr, lr, #1
+    strh    r8, [r1], r3
+    strh    r9, [r1], r3
+
+    bne     bil_width_loop_null_1st
+
+    subs    r12, r12, #1
+    add     r0, r0, r2                      ; move to next input line
+    add     r11, r11, #2                    ; move over to next column
+    mov     r1, r11
+
+    bne     bil_height_loop_null_1st
+
+    ldmia   sp!, {r4 - r11, pc}
+
+    ENDP  ; |vp8_filter_block2d_bil_first_pass_armv6|
+
+
+;---------------------------------
+; r0    unsigned short *src_ptr,
+; r1    unsigned char  *dst_ptr,
+; r2    int             dst_pitch,
+; r3    unsigned int    height,
+; stack unsigned int    width,
+; stack const short    *vp8_filter
+;---------------------------------
+|vp8_filter_block2d_bil_second_pass_armv6| PROC
+    stmdb   sp!, {r4 - r11, lr}
+
+    ldr     r11, [sp, #40]                  ; vp8_filter address
+    ldr     r4, [sp, #36]                   ; width
+
+    ldr     r5, [r11]                       ; load up filter coefficients
+    mov     r12, r4                         ; outer-loop counter = width, since we work on transposed data matrix
+    mov     r11, r1
+
+    cmp     r5, #128                        ; if filter coef = 128, then skip the filter
+    beq     bil_null_2nd_filter
+
+|bil_height_loop_2nd|
+    ldr     r6, [r0]                        ; load the data
+    ldr     r8, [r0, #4]
+    ldrh    r10, [r0, #8]
+    mov     lr, r3, lsr #2                  ; loop counter
+
+|bil_width_loop_2nd|
+    pkhtb   r7, r6, r8                      ; src[1] | src[2]
+    pkhtb   r9, r8, r10                     ; src[3] | src[4]
+
+    smuad   r6, r6, r5                      ; apply filter
+    smuad   r8, r8, r5                      ; apply filter
+
+    subs    lr, lr, #1
+
+    smuadx  r7, r7, r5                      ; apply filter
+    smuadx  r9, r9, r5                      ; apply filter
+
+    add     r0, r0, #8
+
+    add     r6, r6, #0x40                   ; round_shift_and_clamp
+    add     r7, r7, #0x40
+    usat    r6, #8, r6, asr #7
+    usat    r7, #8, r7, asr #7
+    strb    r6, [r1], r2                    ; the result is transposed back and stored
+
+    add     r8, r8, #0x40                   ; round_shift_and_clamp
+    strb    r7, [r1], r2
+    add     r9, r9, #0x40
+    usat    r8, #8, r8, asr #7
+    usat    r9, #8, r9, asr #7
+    strb    r8, [r1], r2                    ; the result is transposed back and stored
+
+    ldrne   r6, [r0]                        ; load data
+    strb    r9, [r1], r2
+    ldrne   r8, [r0, #4]
+    ldrneh  r10, [r0, #8]
+
+    bne     bil_width_loop_2nd
+
+    subs    r12, r12, #1
+    add     r0, r0, #4                      ; update src for next row
+    add     r11, r11, #1
+    mov     r1, r11
+
+    bne     bil_height_loop_2nd
+    ldmia   sp!, {r4 - r11, pc}
+
+|bil_null_2nd_filter|
+|bil_height_loop_null_2nd|
+    mov     lr, r3, lsr #2
+
+|bil_width_loop_null_2nd|
+    ldr     r6, [r0], #4                    ; load data
+    subs    lr, lr, #1
+    ldr     r8, [r0], #4
+
+    strb    r6, [r1], r2                    ; store data
+    mov     r7, r6, lsr #16
+    strb    r7, [r1], r2
+    mov     r9, r8, lsr #16
+    strb    r8, [r1], r2
+    strb    r9, [r1], r2
+
+    bne     bil_width_loop_null_2nd
+
+    subs    r12, r12, #1
+    add     r0, r0, #4
+    add     r11, r11, #1
+    mov     r1, r11
+
+    bne     bil_height_loop_null_2nd
+
+    ldmia   sp!, {r4 - r11, pc}
+    ENDP  ; |vp8_filter_block2d_second_pass_armv6|
+
+    END
diff --git a/vp8/common/arm/armv6/copymem16x16_v6.asm b/vp8/common/arm/armv6/copymem16x16_v6.asm
new file mode 100644 (file)
index 0000000..abf048c
--- /dev/null
@@ -0,0 +1,186 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_copy_mem16x16_v6|
+    ; ARM
+    ; REQUIRE8
+    ; PRESERVE8
+
+    AREA    Block, CODE, READONLY ; name this block of code
+;void copy_mem16x16_v6( unsigned char *src, int src_stride, unsigned char *dst, int dst_stride)
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+|vp8_copy_mem16x16_v6| PROC
+    stmdb       sp!, {r4 - r7}
+    ;push   {r4-r7}
+
+    ;preload
+    pld     [r0, #31]                ; preload for next 16x16 block
+
+    ands    r4, r0, #15
+    beq     copy_mem16x16_fast
+
+    ands    r4, r0, #7
+    beq     copy_mem16x16_8
+
+    ands    r4, r0, #3
+    beq     copy_mem16x16_4
+
+    ;copy one byte each time
+    ldrb    r4, [r0]
+    ldrb    r5, [r0, #1]
+    ldrb    r6, [r0, #2]
+    ldrb    r7, [r0, #3]
+
+    mov     r12, #16
+
+copy_mem16x16_1_loop
+    strb    r4, [r2]
+    strb    r5, [r2, #1]
+    strb    r6, [r2, #2]
+    strb    r7, [r2, #3]
+
+    ldrb    r4, [r0, #4]
+    ldrb    r5, [r0, #5]
+    ldrb    r6, [r0, #6]
+    ldrb    r7, [r0, #7]
+
+    subs    r12, r12, #1
+
+    strb    r4, [r2, #4]
+    strb    r5, [r2, #5]
+    strb    r6, [r2, #6]
+    strb    r7, [r2, #7]
+
+    ldrb    r4, [r0, #8]
+    ldrb    r5, [r0, #9]
+    ldrb    r6, [r0, #10]
+    ldrb    r7, [r0, #11]
+
+    strb    r4, [r2, #8]
+    strb    r5, [r2, #9]
+    strb    r6, [r2, #10]
+    strb    r7, [r2, #11]
+
+    ldrb    r4, [r0, #12]
+    ldrb    r5, [r0, #13]
+    ldrb    r6, [r0, #14]
+    ldrb    r7, [r0, #15]
+
+    add     r0, r0, r1
+
+    strb    r4, [r2, #12]
+    strb    r5, [r2, #13]
+    strb    r6, [r2, #14]
+    strb    r7, [r2, #15]
+
+    add     r2, r2, r3
+
+    ldrneb  r4, [r0]
+    ldrneb  r5, [r0, #1]
+    ldrneb  r6, [r0, #2]
+    ldrneb  r7, [r0, #3]
+
+    pld     [r0, #31]               ; preload for next 16x16 block
+
+    bne     copy_mem16x16_1_loop
+
+    ldmia       sp!, {r4 - r7}
+    ;pop        {r4-r7}
+    mov     pc, lr
+
+;copy 4 bytes each time
+copy_mem16x16_4
+    ldr     r4, [r0]
+    ldr     r5, [r0, #4]
+    ldr     r6, [r0, #8]
+    ldr     r7, [r0, #12]
+
+    mov     r12, #16
+
+copy_mem16x16_4_loop
+    subs    r12, r12, #1
+    add     r0, r0, r1
+
+    str     r4, [r2]
+    str     r5, [r2, #4]
+    str     r6, [r2, #8]
+    str     r7, [r2, #12]
+
+    add     r2, r2, r3
+
+    ldrne   r4, [r0]
+    ldrne   r5, [r0, #4]
+    ldrne   r6, [r0, #8]
+    ldrne   r7, [r0, #12]
+
+    pld     [r0, #31]               ; preload for next 16x16 block
+
+    bne     copy_mem16x16_4_loop
+
+    ldmia       sp!, {r4 - r7}
+    ;pop        {r4-r7}
+    mov     pc, lr
+
+;copy 8 bytes each time
+copy_mem16x16_8
+    sub     r1, r1, #16
+    sub     r3, r3, #16
+
+    mov     r12, #16
+
+copy_mem16x16_8_loop
+    ldmia   r0!, {r4-r5}
+    ;ldm        r0, {r4-r5}
+    ldmia   r0!, {r6-r7}
+
+    add     r0, r0, r1
+
+    stmia   r2!, {r4-r5}
+    subs    r12, r12, #1
+    ;stm        r2, {r4-r5}
+    stmia   r2!, {r6-r7}
+
+    add     r2, r2, r3
+
+    pld     [r0, #31]               ; preload for next 16x16 block
+    bne     copy_mem16x16_8_loop
+
+    ldmia       sp!, {r4 - r7}
+    ;pop        {r4-r7}
+    mov     pc, lr
+
+;copy 16 bytes each time
+copy_mem16x16_fast
+    ;sub        r1, r1, #16
+    ;sub        r3, r3, #16
+
+    mov     r12, #16
+
+copy_mem16x16_fast_loop
+    ldmia   r0, {r4-r7}
+    ;ldm        r0, {r4-r7}
+    add     r0, r0, r1
+
+    subs    r12, r12, #1
+    stmia   r2, {r4-r7}
+    ;stm        r2, {r4-r7}
+    add     r2, r2, r3
+
+    pld     [r0, #31]               ; preload for next 16x16 block
+    bne     copy_mem16x16_fast_loop
+
+    ldmia       sp!, {r4 - r7}
+    ;pop        {r4-r7}
+    mov     pc, lr
+
+    ENDP  ; |vp8_copy_mem16x16_v6|
+
+    END
diff --git a/vp8/common/arm/armv6/copymem8x4_v6.asm b/vp8/common/arm/armv6/copymem8x4_v6.asm
new file mode 100644 (file)
index 0000000..d8362ef
--- /dev/null
@@ -0,0 +1,128 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_copy_mem8x4_v6|
+    ; ARM
+    ; REQUIRE8
+    ; PRESERVE8
+
+    AREA    Block, CODE, READONLY ; name this block of code
+;void vp8_copy_mem8x4_v6( unsigned char *src, int src_stride, unsigned char *dst, int dst_stride)
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+|vp8_copy_mem8x4_v6| PROC
+    ;push   {r4-r5}
+    stmdb  sp!, {r4-r5}
+
+    ;preload
+    pld     [r0]
+    pld     [r0, r1]
+    pld     [r0, r1, lsl #1]
+
+    ands    r4, r0, #7
+    beq     copy_mem8x4_fast
+
+    ands    r4, r0, #3
+    beq     copy_mem8x4_4
+
+    ;copy 1 byte each time
+    ldrb    r4, [r0]
+    ldrb    r5, [r0, #1]
+
+    mov     r12, #4
+
+copy_mem8x4_1_loop
+    strb    r4, [r2]
+    strb    r5, [r2, #1]
+
+    ldrb    r4, [r0, #2]
+    ldrb    r5, [r0, #3]
+
+    subs    r12, r12, #1
+
+    strb    r4, [r2, #2]
+    strb    r5, [r2, #3]
+
+    ldrb    r4, [r0, #4]
+    ldrb    r5, [r0, #5]
+
+    strb    r4, [r2, #4]
+    strb    r5, [r2, #5]
+
+    ldrb    r4, [r0, #6]
+    ldrb    r5, [r0, #7]
+
+    add     r0, r0, r1
+
+    strb    r4, [r2, #6]
+    strb    r5, [r2, #7]
+
+    add     r2, r2, r3
+
+    ldrneb  r4, [r0]
+    ldrneb  r5, [r0, #1]
+
+    bne     copy_mem8x4_1_loop
+
+    ldmia       sp!, {r4 - r5}
+    ;pop        {r4-r5}
+    mov     pc, lr
+
+;copy 4 bytes each time
+copy_mem8x4_4
+    ldr     r4, [r0]
+    ldr     r5, [r0, #4]
+
+    mov     r12, #4
+
+copy_mem8x4_4_loop
+    subs    r12, r12, #1
+    add     r0, r0, r1
+
+    str     r4, [r2]
+    str     r5, [r2, #4]
+
+    add     r2, r2, r3
+
+    ldrne   r4, [r0]
+    ldrne   r5, [r0, #4]
+
+    bne     copy_mem8x4_4_loop
+
+    ldmia  sp!, {r4-r5}
+    ;pop        {r4-r5}
+    mov     pc, lr
+
+;copy 8 bytes each time
+copy_mem8x4_fast
+    ;sub        r1, r1, #8
+    ;sub        r3, r3, #8
+
+    mov     r12, #4
+
+copy_mem8x4_fast_loop
+    ldmia   r0, {r4-r5}
+    ;ldm        r0, {r4-r5}
+    add     r0, r0, r1
+
+    subs    r12, r12, #1
+    stmia   r2, {r4-r5}
+    ;stm        r2, {r4-r5}
+    add     r2, r2, r3
+
+    bne     copy_mem8x4_fast_loop
+
+    ldmia  sp!, {r4-r5}
+    ;pop        {r4-r5}
+    mov     pc, lr
+
+    ENDP  ; |vp8_copy_mem8x4_v6|
+
+    END
diff --git a/vp8/common/arm/armv6/copymem8x8_v6.asm b/vp8/common/arm/armv6/copymem8x8_v6.asm
new file mode 100644 (file)
index 0000000..c6a60c6
--- /dev/null
@@ -0,0 +1,128 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_copy_mem8x8_v6|
+    ; ARM
+    ; REQUIRE8
+    ; PRESERVE8
+
+    AREA    Block, CODE, READONLY ; name this block of code
+;void copy_mem8x8_v6( unsigned char *src, int src_stride, unsigned char *dst, int dst_stride)
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+|vp8_copy_mem8x8_v6| PROC
+    ;push   {r4-r5}
+    stmdb  sp!, {r4-r5}
+
+    ;preload
+    pld     [r0]
+    pld     [r0, r1]
+    pld     [r0, r1, lsl #1]
+
+    ands    r4, r0, #7
+    beq     copy_mem8x8_fast
+
+    ands    r4, r0, #3
+    beq     copy_mem8x8_4
+
+    ;copy 1 byte each time
+    ldrb    r4, [r0]
+    ldrb    r5, [r0, #1]
+
+    mov     r12, #8
+
+copy_mem8x8_1_loop
+    strb    r4, [r2]
+    strb    r5, [r2, #1]
+
+    ldrb    r4, [r0, #2]
+    ldrb    r5, [r0, #3]
+
+    subs    r12, r12, #1
+
+    strb    r4, [r2, #2]
+    strb    r5, [r2, #3]
+
+    ldrb    r4, [r0, #4]
+    ldrb    r5, [r0, #5]
+
+    strb    r4, [r2, #4]
+    strb    r5, [r2, #5]
+
+    ldrb    r4, [r0, #6]
+    ldrb    r5, [r0, #7]
+
+    add     r0, r0, r1
+
+    strb    r4, [r2, #6]
+    strb    r5, [r2, #7]
+
+    add     r2, r2, r3
+
+    ldrneb  r4, [r0]
+    ldrneb  r5, [r0, #1]
+
+    bne     copy_mem8x8_1_loop
+
+    ldmia       sp!, {r4 - r5}
+    ;pop        {r4-r5}
+    mov     pc, lr
+
+;copy 4 bytes each time
+copy_mem8x8_4
+    ldr     r4, [r0]
+    ldr     r5, [r0, #4]
+
+    mov     r12, #8
+
+copy_mem8x8_4_loop
+    subs    r12, r12, #1
+    add     r0, r0, r1
+
+    str     r4, [r2]
+    str     r5, [r2, #4]
+
+    add     r2, r2, r3
+
+    ldrne   r4, [r0]
+    ldrne   r5, [r0, #4]
+
+    bne     copy_mem8x8_4_loop
+
+    ldmia       sp!, {r4 - r5}
+    ;pop        {r4-r5}
+    mov     pc, lr
+
+;copy 8 bytes each time
+copy_mem8x8_fast
+    ;sub        r1, r1, #8
+    ;sub        r3, r3, #8
+
+    mov     r12, #8
+
+copy_mem8x8_fast_loop
+    ldmia   r0, {r4-r5}
+    ;ldm        r0, {r4-r5}
+    add     r0, r0, r1
+
+    subs    r12, r12, #1
+    stmia   r2, {r4-r5}
+    ;stm        r2, {r4-r5}
+    add     r2, r2, r3
+
+    bne     copy_mem8x8_fast_loop
+
+    ldmia  sp!, {r4-r5}
+    ;pop        {r4-r5}
+    mov     pc, lr
+
+    ENDP  ; |vp8_copy_mem8x8_v6|
+
+    END
diff --git a/vp8/common/arm/armv6/dc_only_idct_add_v6.asm b/vp8/common/arm/armv6/dc_only_idct_add_v6.asm
new file mode 100644 (file)
index 0000000..9aa659f
--- /dev/null
@@ -0,0 +1,70 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license and patent
+;  grant that can be found in the LICENSE file in the root of the source
+;  tree. All contributing project authors may be found in the AUTHORS
+;  file in the root of the source tree.
+;
+
+    EXPORT  |vp8_dc_only_idct_add_v6|
+
+    AREA    |.text|, CODE, READONLY
+
+;void vp8_dc_only_idct_add_c(short input_dc, unsigned char *pred_ptr,
+;                            int pred_stride, unsigned char *dst_ptr,
+;                            int dst_stride)
+; r0  input_dc
+; r1  pred_ptr
+; r2  pred_stride
+; r3  dst_ptr
+; sp  dst_stride
+
+|vp8_dc_only_idct_add_v6| PROC
+    stmdb       sp!, {r4 - r7}
+
+    add         r0, r0, #4                ; input_dc += 4
+    ldr         r12, c0x0000FFFF
+    ldr         r4, [r1], r2
+    and         r0, r12, r0, asr #3       ; input_dc >> 3 + mask
+    ldr         r6, [r1], r2
+    orr         r0, r0, r0, lsl #16       ; a1 | a1
+
+    ldr         r12, [sp, #16]            ; dst stride
+
+    uxtab16     r5, r0, r4                ; a1+2 | a1+0
+    uxtab16     r4, r0, r4, ror #8        ; a1+3 | a1+1
+    uxtab16     r7, r0, r6
+    uxtab16     r6, r0, r6, ror #8
+    usat16      r5, #8, r5
+    usat16      r4, #8, r4
+    usat16      r7, #8, r7
+    usat16      r6, #8, r6
+    orr         r5, r5, r4, lsl #8
+    orr         r7, r7, r6, lsl #8
+    ldr         r4, [r1], r2
+    str         r5, [r3], r12
+    ldr         r6, [r1]
+    str         r7, [r3], r12
+
+    uxtab16     r5, r0, r4
+    uxtab16     r4, r0, r4, ror #8
+    uxtab16     r7, r0, r6
+    uxtab16     r6, r0, r6, ror #8
+    usat16      r5, #8, r5
+    usat16      r4, #8, r4
+    usat16      r7, #8, r7
+    usat16      r6, #8, r6
+    orr         r5, r5, r4, lsl #8
+    orr         r7, r7, r6, lsl #8
+    str         r5, [r3], r12
+    str         r7, [r3]
+
+    ldmia       sp!, {r4 - r7}
+    bx          lr
+
+    ENDP  ; |vp8_dc_only_idct_add_v6|
+
+; Constant Pool
+c0x0000FFFF DCD 0x0000FFFF
+    END
diff --git a/vp8/common/arm/armv6/dequant_idct_v6.asm b/vp8/common/arm/armv6/dequant_idct_v6.asm
new file mode 100644 (file)
index 0000000..2510ad8
--- /dev/null
@@ -0,0 +1,190 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license and patent
+;  grant that can be found in the LICENSE file in the root of the source
+;  tree. All contributing project authors may be found in the AUTHORS
+;  file in the root of the source tree.
+;
+
+    EXPORT |vp8_dequant_idct_add_v6|
+
+    AREA |.text|, CODE, READONLY
+;void vp8_dequant_idct_v6(short *input, short *dq,
+;                         unsigned char *dest, int stride)
+; r0 = q
+; r1 = dq
+; r2 = dst
+; r3 = stride
+
+|vp8_dequant_idct_add_v6| PROC
+    stmdb   sp!, {r4-r11, lr}
+
+    ldr     r4, [r0]                ;input
+    ldr     r5, [r1], #4            ;dq
+
+    sub     sp, sp, #4
+    str     r3, [sp]
+
+    mov     r12, #4
+
+vp8_dequant_add_loop
+    smulbb  r6, r4, r5
+    smultt  r7, r4, r5
+
+    ldr     r4, [r0, #4]            ;input
+    ldr     r5, [r1], #4            ;dq
+
+    strh    r6, [r0], #2
+    strh    r7, [r0], #2
+
+    smulbb  r6, r4, r5
+    smultt  r7, r4, r5
+
+    subs    r12, r12, #1
+
+    ldrne   r4, [r0, #4]
+    ldrne   r5, [r1], #4
+
+    strh    r6, [r0], #2
+    strh    r7, [r0], #2
+
+    bne     vp8_dequant_add_loop
+
+    sub     r0, r0, #32
+    mov     r1, r0
+
+; short_idct4x4llm_v6_dual
+    ldr     r3, cospi8sqrt2minus1
+    ldr     r4, sinpi8sqrt2
+    ldr     r6, [r0, #8]
+    mov     r5, #2
+vp8_dequant_idct_loop1_v6
+    ldr     r12, [r0, #24]
+    ldr     r14, [r0, #16]
+    smulwt  r9, r3, r6
+    smulwb  r7, r3, r6
+    smulwt  r10, r4, r6
+    smulwb  r8, r4, r6
+    pkhbt   r7, r7, r9, lsl #16
+    smulwt  r11, r3, r12
+    pkhbt   r8, r8, r10, lsl #16
+    uadd16  r6, r6, r7
+    smulwt  r7, r4, r12
+    smulwb  r9, r3, r12
+    smulwb  r10, r4, r12
+    subs    r5, r5, #1
+    pkhbt   r9, r9, r11, lsl #16
+    ldr     r11, [r0], #4
+    pkhbt   r10, r10, r7, lsl #16
+    uadd16  r7, r12, r9
+    usub16  r7, r8, r7
+    uadd16  r6, r6, r10
+    uadd16  r10, r11, r14
+    usub16  r8, r11, r14
+    uadd16  r9, r10, r6
+    usub16  r10, r10, r6
+    uadd16  r6, r8, r7
+    usub16  r7, r8, r7
+    str     r6, [r1, #8]
+    ldrne   r6, [r0, #8]
+    str     r7, [r1, #16]
+    str     r10, [r1, #24]
+    str     r9, [r1], #4
+    bne     vp8_dequant_idct_loop1_v6
+
+    mov     r5, #2
+    sub     r0, r1, #8
+vp8_dequant_idct_loop2_v6
+    ldr     r6, [r0], #4
+    ldr     r7, [r0], #4
+    ldr     r8, [r0], #4
+    ldr     r9, [r0], #4
+    smulwt  r1, r3, r6
+    smulwt  r12, r4, r6
+    smulwt  lr, r3, r8
+    smulwt  r10, r4, r8
+    pkhbt   r11, r8, r6, lsl #16
+    pkhbt   r1, lr, r1, lsl #16
+    pkhbt   r12, r10, r12, lsl #16
+    pkhtb   r6, r6, r8, asr #16
+    uadd16  r6, r1, r6
+    pkhbt   lr, r9, r7, lsl #16
+    uadd16  r10, r11, lr
+    usub16  lr, r11, lr
+    pkhtb   r8, r7, r9, asr #16
+    subs    r5, r5, #1
+    smulwt  r1, r3, r8
+    smulwb  r7, r3, r8
+    smulwt  r11, r4, r8
+    smulwb  r9, r4, r8
+    pkhbt   r1, r7, r1, lsl #16
+    uadd16  r8, r1, r8
+    pkhbt   r11, r9, r11, lsl #16
+    usub16  r1, r12, r8
+    uadd16  r8, r11, r6
+    ldr     r9, c0x00040004
+    ldr     r12, [sp]               ; get stride from stack
+    uadd16  r6, r10, r8
+    usub16  r7, r10, r8
+    uadd16  r7, r7, r9
+    uadd16  r6, r6, r9
+    uadd16  r10, r14, r1
+    usub16  r1, r14, r1
+    uadd16  r10, r10, r9
+    uadd16  r1, r1, r9
+    ldr     r11, [r2]               ; load input from dst
+    mov     r8, r7, asr #3
+    pkhtb   r9, r8, r10, asr #19
+    mov     r8, r1, asr #3
+    pkhtb   r8, r8, r6, asr #19
+    uxtb16  lr, r11, ror #8
+    qadd16  r9, r9, lr
+    uxtb16  lr, r11
+    qadd16  r8, r8, lr
+    usat16  r9, #8, r9
+    usat16  r8, #8, r8
+    orr     r9, r8, r9, lsl #8
+    ldr     r11, [r2, r12]          ; load input from dst
+    mov     r7, r7, lsl #16
+    mov     r1, r1, lsl #16
+    mov     r10, r10, lsl #16
+    mov     r6, r6, lsl #16
+    mov     r7, r7, asr #3
+    pkhtb   r7, r7, r10, asr #19
+    mov     r1, r1, asr #3
+    pkhtb   r1, r1, r6, asr #19
+    uxtb16  r8, r11, ror #8
+    qadd16  r7, r7, r8
+    uxtb16  r8, r11
+    qadd16  r1, r1, r8
+    usat16  r7, #8, r7
+    usat16  r1, #8, r1
+    orr     r1, r1, r7, lsl #8
+    str     r9, [r2], r12           ; store output to dst
+    str     r1, [r2], r12           ; store output to dst
+    bne     vp8_dequant_idct_loop2_v6
+
+; vpx_memset
+    sub     r0, r0, #32
+    add     sp, sp, #4
+
+    mov     r12, #0
+    str     r12, [r0]
+    str     r12, [r0, #4]
+    str     r12, [r0, #8]
+    str     r12, [r0, #12]
+    str     r12, [r0, #16]
+    str     r12, [r0, #20]
+    str     r12, [r0, #24]
+    str     r12, [r0, #28]
+
+    ldmia   sp!, {r4 - r11, pc}
+    ENDP    ; |vp8_dequant_idct_add_v6|
+
+; Constant Pool
+cospi8sqrt2minus1 DCD 0x00004E7B
+sinpi8sqrt2       DCD 0x00008A8C
+c0x00040004       DCD 0x00040004
+
+    END
diff --git a/vp8/common/arm/armv6/dequantize_v6.asm b/vp8/common/arm/armv6/dequantize_v6.asm
new file mode 100644 (file)
index 0000000..72f7e0e
--- /dev/null
@@ -0,0 +1,69 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_dequantize_b_loop_v6|
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+;-------------------------------
+;void   vp8_dequantize_b_loop_v6(short *Q, short *DQC, short *DQ);
+; r0    short *Q,
+; r1    short *DQC
+; r2    short *DQ
+|vp8_dequantize_b_loop_v6| PROC
+    stmdb   sp!, {r4-r9, lr}
+
+    ldr     r3, [r0]                ;load Q
+    ldr     r4, [r1]                ;load DQC
+    ldr     r5, [r0, #4]
+    ldr     r6, [r1, #4]
+
+    mov     r12, #2                 ;loop counter
+
+dequant_loop
+    smulbb  r7, r3, r4              ;multiply
+    smultt  r8, r3, r4
+    smulbb  r9, r5, r6
+    smultt  lr, r5, r6
+
+    ldr     r3, [r0, #8]
+    ldr     r4, [r1, #8]
+    ldr     r5, [r0, #12]
+    ldr     r6, [r1, #12]
+
+    strh    r7, [r2], #2            ;store result
+    smulbb  r7, r3, r4              ;multiply
+    strh    r8, [r2], #2
+    smultt  r8, r3, r4
+    strh    r9, [r2], #2
+    smulbb  r9, r5, r6
+    strh    lr, [r2], #2
+    smultt  lr, r5, r6
+
+    subs    r12, r12, #1
+
+    add     r0, r0, #16
+    add     r1, r1, #16
+
+    ldrne       r3, [r0]
+    strh    r7, [r2], #2            ;store result
+    ldrne       r4, [r1]
+    strh    r8, [r2], #2
+    ldrne       r5, [r0, #4]
+    strh    r9, [r2], #2
+    ldrne       r6, [r1, #4]
+    strh    lr, [r2], #2
+
+    bne     dequant_loop
+
+    ldmia   sp!, {r4-r9, pc}
+    ENDP    ;|vp8_dequantize_b_loop_v6|
+
+    END
diff --git a/vp8/common/arm/armv6/filter_v6.asm b/vp8/common/arm/armv6/filter_v6.asm
new file mode 100644 (file)
index 0000000..1ba91dd
--- /dev/null
@@ -0,0 +1,624 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_filter_block2d_first_pass_armv6|
+    EXPORT  |vp8_filter_block2d_first_pass_16x16_armv6|
+    EXPORT  |vp8_filter_block2d_first_pass_8x8_armv6|
+    EXPORT  |vp8_filter_block2d_second_pass_armv6|
+    EXPORT  |vp8_filter4_block2d_second_pass_armv6|
+    EXPORT  |vp8_filter_block2d_first_pass_only_armv6|
+    EXPORT  |vp8_filter_block2d_second_pass_only_armv6|
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+;-------------------------------------
+; r0    unsigned char *src_ptr
+; r1    short         *output_ptr
+; r2    unsigned int src_pixels_per_line
+; r3    unsigned int output_width
+; stack unsigned int output_height
+; stack const short *vp8_filter
+;-------------------------------------
+; vp8_filter the input and put in the output array.  Apply the 6 tap FIR filter with
+; the output being a 2 byte value and the intput being a 1 byte value.
+|vp8_filter_block2d_first_pass_armv6| PROC
+    stmdb   sp!, {r4 - r11, lr}
+
+    ldr     r11, [sp, #40]                  ; vp8_filter address
+    ldr     r7, [sp, #36]                   ; output height
+
+    sub     r2, r2, r3                      ; inside loop increments input array,
+                                            ; so the height loop only needs to add
+                                            ; r2 - width to the input pointer
+
+    mov     r3, r3, lsl #1                  ; multiply width by 2 because using shorts
+    add     r12, r3, #16                    ; square off the output
+    sub     sp, sp, #4
+
+    ldr     r4, [r11]                       ; load up packed filter coefficients
+    ldr     r5, [r11, #4]
+    ldr     r6, [r11, #8]
+
+    str     r1, [sp]                        ; push destination to stack
+    mov     r7, r7, lsl #16                 ; height is top part of counter
+
+; six tap filter
+|height_loop_1st_6|
+    ldrb    r8, [r0, #-2]                   ; load source data
+    ldrb    r9, [r0, #-1]
+    ldrb    r10, [r0], #2
+    orr     r7, r7, r3, lsr #2              ; construct loop counter
+
+|width_loop_1st_6|
+    ldrb    r11, [r0, #-1]
+
+    pkhbt   lr, r8, r9, lsl #16             ; r9 | r8
+    pkhbt   r8, r9, r10, lsl #16            ; r10 | r9
+
+    ldrb    r9, [r0]
+
+    smuad   lr, lr, r4                      ; apply the filter
+    pkhbt   r10, r10, r11, lsl #16          ; r11 | r10
+    smuad   r8, r8, r4
+    pkhbt   r11, r11, r9, lsl #16           ; r9 | r11
+
+    smlad   lr, r10, r5, lr
+    ldrb    r10, [r0, #1]
+    smlad   r8, r11, r5, r8
+    ldrb    r11, [r0, #2]
+
+    sub     r7, r7, #1
+
+    pkhbt   r9, r9, r10, lsl #16            ; r10 | r9
+    pkhbt   r10, r10, r11, lsl #16          ; r11 | r10
+
+    smlad   lr, r9, r6, lr
+    smlad   r11, r10, r6, r8
+
+    ands    r10, r7, #0xff                  ; test loop counter
+
+    add     lr, lr, #0x40                   ; round_shift_and_clamp
+    ldrneb  r8, [r0, #-2]                   ; load data for next loop
+    usat    lr, #8, lr, asr #7
+    add     r11, r11, #0x40
+    ldrneb  r9, [r0, #-1]
+    usat    r11, #8, r11, asr #7
+
+    strh    lr, [r1], r12                   ; result is transposed and stored, which
+                                            ; will make second pass filtering easier.
+    ldrneb  r10, [r0], #2
+    strh    r11, [r1], r12
+
+    bne     width_loop_1st_6
+
+    ldr     r1, [sp]                        ; load and update dst address
+    subs    r7, r7, #0x10000
+    add     r0, r0, r2                      ; move to next input line
+
+    add     r1, r1, #2                      ; move over to next column
+    str     r1, [sp]
+
+    bne     height_loop_1st_6
+
+    add     sp, sp, #4
+    ldmia   sp!, {r4 - r11, pc}
+
+    ENDP
+
+; --------------------------
+; 16x16 version
+; -----------------------------
+|vp8_filter_block2d_first_pass_16x16_armv6| PROC
+    stmdb   sp!, {r4 - r11, lr}
+
+    ldr     r11, [sp, #40]                  ; vp8_filter address
+    ldr     r7, [sp, #36]                   ; output height
+
+    add     r4, r2, #18                     ; preload next low
+    pld     [r0, r4]
+
+    sub     r2, r2, r3                      ; inside loop increments input array,
+                                            ; so the height loop only needs to add
+                                            ; r2 - width to the input pointer
+
+    mov     r3, r3, lsl #1                  ; multiply width by 2 because using shorts
+    add     r12, r3, #16                    ; square off the output
+    sub     sp, sp, #4
+
+    ldr     r4, [r11]                       ; load up packed filter coefficients
+    ldr     r5, [r11, #4]
+    ldr     r6, [r11, #8]
+
+    str     r1, [sp]                        ; push destination to stack
+    mov     r7, r7, lsl #16                 ; height is top part of counter
+
+; six tap filter
+|height_loop_1st_16_6|
+    ldrb    r8, [r0, #-2]                   ; load source data
+    ldrb    r9, [r0, #-1]
+    ldrb    r10, [r0], #2
+    orr     r7, r7, r3, lsr #2              ; construct loop counter
+
+|width_loop_1st_16_6|
+    ldrb    r11, [r0, #-1]
+
+    pkhbt   lr, r8, r9, lsl #16             ; r9 | r8
+    pkhbt   r8, r9, r10, lsl #16            ; r10 | r9
+
+    ldrb    r9, [r0]
+
+    smuad   lr, lr, r4                      ; apply the filter
+    pkhbt   r10, r10, r11, lsl #16          ; r11 | r10
+    smuad   r8, r8, r4
+    pkhbt   r11, r11, r9, lsl #16           ; r9 | r11
+
+    smlad   lr, r10, r5, lr
+    ldrb    r10, [r0, #1]
+    smlad   r8, r11, r5, r8
+    ldrb    r11, [r0, #2]
+
+    sub     r7, r7, #1
+
+    pkhbt   r9, r9, r10, lsl #16            ; r10 | r9
+    pkhbt   r10, r10, r11, lsl #16          ; r11 | r10
+
+    smlad   lr, r9, r6, lr
+    smlad   r11, r10, r6, r8
+
+    ands    r10, r7, #0xff                  ; test loop counter
+
+    add     lr, lr, #0x40                   ; round_shift_and_clamp
+    ldrneb  r8, [r0, #-2]                   ; load data for next loop
+    usat    lr, #8, lr, asr #7
+    add     r11, r11, #0x40
+    ldrneb  r9, [r0, #-1]
+    usat    r11, #8, r11, asr #7
+
+    strh    lr, [r1], r12                   ; result is transposed and stored, which
+                                            ; will make second pass filtering easier.
+    ldrneb  r10, [r0], #2
+    strh    r11, [r1], r12
+
+    bne     width_loop_1st_16_6
+
+    ldr     r1, [sp]                        ; load and update dst address
+    subs    r7, r7, #0x10000
+    add     r0, r0, r2                      ; move to next input line
+
+    add     r11, r2, #34                    ; adding back block width(=16)
+    pld     [r0, r11]                       ; preload next low
+
+    add     r1, r1, #2                      ; move over to next column
+    str     r1, [sp]
+
+    bne     height_loop_1st_16_6
+
+    add     sp, sp, #4
+    ldmia   sp!, {r4 - r11, pc}
+
+    ENDP
+
+; --------------------------
+; 8x8 version
+; -----------------------------
+|vp8_filter_block2d_first_pass_8x8_armv6| PROC
+    stmdb   sp!, {r4 - r11, lr}
+
+    ldr     r11, [sp, #40]                  ; vp8_filter address
+    ldr     r7, [sp, #36]                   ; output height
+
+    add     r4, r2, #10                     ; preload next low
+    pld     [r0, r4]
+
+    sub     r2, r2, r3                      ; inside loop increments input array,
+                                            ; so the height loop only needs to add
+                                            ; r2 - width to the input pointer
+
+    mov     r3, r3, lsl #1                  ; multiply width by 2 because using shorts
+    add     r12, r3, #16                    ; square off the output
+    sub     sp, sp, #4
+
+    ldr     r4, [r11]                       ; load up packed filter coefficients
+    ldr     r5, [r11, #4]
+    ldr     r6, [r11, #8]
+
+    str     r1, [sp]                        ; push destination to stack
+    mov     r7, r7, lsl #16                 ; height is top part of counter
+
+; six tap filter
+|height_loop_1st_8_6|
+    ldrb    r8, [r0, #-2]                   ; load source data
+    ldrb    r9, [r0, #-1]
+    ldrb    r10, [r0], #2
+    orr     r7, r7, r3, lsr #2              ; construct loop counter
+
+|width_loop_1st_8_6|
+    ldrb    r11, [r0, #-1]
+
+    pkhbt   lr, r8, r9, lsl #16             ; r9 | r8
+    pkhbt   r8, r9, r10, lsl #16            ; r10 | r9
+
+    ldrb    r9, [r0]
+
+    smuad   lr, lr, r4                      ; apply the filter
+    pkhbt   r10, r10, r11, lsl #16          ; r11 | r10
+    smuad   r8, r8, r4
+    pkhbt   r11, r11, r9, lsl #16           ; r9 | r11
+
+    smlad   lr, r10, r5, lr
+    ldrb    r10, [r0, #1]
+    smlad   r8, r11, r5, r8
+    ldrb    r11, [r0, #2]
+
+    sub     r7, r7, #1
+
+    pkhbt   r9, r9, r10, lsl #16            ; r10 | r9
+    pkhbt   r10, r10, r11, lsl #16          ; r11 | r10
+
+    smlad   lr, r9, r6, lr
+    smlad   r11, r10, r6, r8
+
+    ands    r10, r7, #0xff                  ; test loop counter
+
+    add     lr, lr, #0x40                   ; round_shift_and_clamp
+    ldrneb  r8, [r0, #-2]                   ; load data for next loop
+    usat    lr, #8, lr, asr #7
+    add     r11, r11, #0x40
+    ldrneb  r9, [r0, #-1]
+    usat    r11, #8, r11, asr #7
+
+    strh    lr, [r1], r12                   ; result is transposed and stored, which
+                                            ; will make second pass filtering easier.
+    ldrneb  r10, [r0], #2
+    strh    r11, [r1], r12
+
+    bne     width_loop_1st_8_6
+
+    ldr     r1, [sp]                        ; load and update dst address
+    subs    r7, r7, #0x10000
+    add     r0, r0, r2                      ; move to next input line
+
+    add     r11, r2, #18                    ; adding back block width(=8)
+    pld     [r0, r11]                       ; preload next low
+
+    add     r1, r1, #2                      ; move over to next column
+    str     r1, [sp]
+
+    bne     height_loop_1st_8_6
+
+    add     sp, sp, #4
+    ldmia   sp!, {r4 - r11, pc}
+
+    ENDP
+
+;---------------------------------
+; r0    short         *src_ptr,
+; r1    unsigned char *output_ptr,
+; r2    unsigned int output_pitch,
+; r3    unsigned int cnt,
+; stack const short *vp8_filter
+;---------------------------------
+|vp8_filter_block2d_second_pass_armv6| PROC
+    stmdb   sp!, {r4 - r11, lr}
+
+    ldr     r11, [sp, #36]                  ; vp8_filter address
+    sub     sp, sp, #4
+    mov     r7, r3, lsl #16                 ; height is top part of counter
+    str     r1, [sp]                        ; push destination to stack
+
+    ldr     r4, [r11]                       ; load up packed filter coefficients
+    ldr     r5, [r11, #4]
+    ldr     r6, [r11, #8]
+
+    pkhbt   r12, r5, r4                     ; pack the filter differently
+    pkhbt   r11, r6, r5
+
+    sub     r0, r0, #4                      ; offset input buffer
+
+|height_loop_2nd|
+    ldr     r8, [r0]                        ; load the data
+    ldr     r9, [r0, #4]
+    orr     r7, r7, r3, lsr #1              ; loop counter
+
+|width_loop_2nd|
+    smuad   lr, r4, r8                      ; apply filter
+    sub     r7, r7, #1
+    smulbt  r8, r4, r8
+
+    ldr     r10, [r0, #8]
+
+    smlad   lr, r5, r9, lr
+    smladx  r8, r12, r9, r8
+
+    ldrh    r9, [r0, #12]
+
+    smlad   lr, r6, r10, lr
+    smladx  r8, r11, r10, r8
+
+    add     r0, r0, #4
+    smlatb  r10, r6, r9, r8
+
+    add     lr, lr, #0x40                   ; round_shift_and_clamp
+    ands    r8, r7, #0xff
+    usat    lr, #8, lr, asr #7
+    add     r10, r10, #0x40
+    strb    lr, [r1], r2                    ; the result is transposed back and stored
+    usat    r10, #8, r10, asr #7
+
+    ldrne   r8, [r0]                        ; load data for next loop
+    ldrne   r9, [r0, #4]
+    strb    r10, [r1], r2
+
+    bne     width_loop_2nd
+
+    ldr     r1, [sp]                        ; update dst for next loop
+    subs    r7, r7, #0x10000
+    add     r0, r0, #16                     ; updata src for next loop
+    add     r1, r1, #1
+    str     r1, [sp]
+
+    bne     height_loop_2nd
+
+    add     sp, sp, #4
+    ldmia   sp!, {r4 - r11, pc}
+
+    ENDP
+
+;---------------------------------
+; r0    short         *src_ptr,
+; r1    unsigned char *output_ptr,
+; r2    unsigned int output_pitch,
+; r3    unsigned int cnt,
+; stack const short *vp8_filter
+;---------------------------------
+|vp8_filter4_block2d_second_pass_armv6| PROC
+    stmdb   sp!, {r4 - r11, lr}
+
+    ldr     r11, [sp, #36]                  ; vp8_filter address
+    mov     r7, r3, lsl #16                 ; height is top part of counter
+
+    ldr     r4, [r11]                       ; load up packed filter coefficients
+    add     lr, r1, r3                      ; save final destination pointer
+    ldr     r5, [r11, #4]
+    ldr     r6, [r11, #8]
+
+    pkhbt   r12, r5, r4                     ; pack the filter differently
+    pkhbt   r11, r6, r5
+    mov     r4, #0x40                       ; rounding factor (for smlad{x})
+
+|height_loop_2nd_4|
+    ldrd    r8, [r0, #-4]                   ; load the data
+    orr     r7, r7, r3, lsr #1              ; loop counter
+
+|width_loop_2nd_4|
+    ldr     r10, [r0, #4]!
+    smladx  r6, r9, r12, r4                 ; apply filter
+    pkhbt   r8, r9, r8
+    smlad   r5, r8, r12, r4
+    pkhbt   r8, r10, r9
+    smladx  r6, r10, r11, r6
+    sub     r7, r7, #1
+    smlad   r5, r8, r11, r5
+
+    mov     r8, r9                          ; shift the data for the next loop
+    mov     r9, r10
+
+    usat    r6, #8, r6, asr #7              ; shift and clamp
+    usat    r5, #8, r5, asr #7
+
+    strb    r5, [r1], r2                    ; the result is transposed back and stored
+    tst     r7, #0xff
+    strb    r6, [r1], r2
+
+    bne     width_loop_2nd_4
+
+    subs    r7, r7, #0x10000
+    add     r0, r0, #16                     ; update src for next loop
+    sub     r1, lr, r7, lsr #16             ; update dst for next loop
+
+    bne     height_loop_2nd_4
+
+    ldmia   sp!, {r4 - r11, pc}
+
+    ENDP
+
+;------------------------------------
+; r0    unsigned char *src_ptr
+; r1    unsigned char *output_ptr,
+; r2    unsigned int src_pixels_per_line
+; r3    unsigned int cnt,
+; stack unsigned int output_pitch,
+; stack const short *vp8_filter
+;------------------------------------
+|vp8_filter_block2d_first_pass_only_armv6| PROC
+    stmdb   sp!, {r4 - r11, lr}
+
+    add     r7, r2, r3                      ; preload next low
+    add     r7, r7, #2
+    pld     [r0, r7]
+
+    ldr     r4, [sp, #36]                   ; output pitch
+    ldr     r11, [sp, #40]                  ; HFilter address
+    sub     sp, sp, #8
+
+    mov     r7, r3
+    sub     r2, r2, r3                      ; inside loop increments input array,
+                                            ; so the height loop only needs to add
+                                            ; r2 - width to the input pointer
+
+    sub     r4, r4, r3
+    str     r4, [sp]                        ; save modified output pitch
+    str     r2, [sp, #4]
+
+    mov     r2, #0x40
+
+    ldr     r4, [r11]                       ; load up packed filter coefficients
+    ldr     r5, [r11, #4]
+    ldr     r6, [r11, #8]
+
+; six tap filter
+|height_loop_1st_only_6|
+    ldrb    r8, [r0, #-2]                   ; load data
+    ldrb    r9, [r0, #-1]
+    ldrb    r10, [r0], #2
+
+    mov     r12, r3, lsr #1                 ; loop counter
+
+|width_loop_1st_only_6|
+    ldrb    r11, [r0, #-1]
+
+    pkhbt   lr, r8, r9, lsl #16             ; r9 | r8
+    pkhbt   r8, r9, r10, lsl #16            ; r10 | r9
+
+    ldrb    r9, [r0]
+
+;;  smuad   lr, lr, r4
+    smlad   lr, lr, r4, r2
+    pkhbt   r10, r10, r11, lsl #16          ; r11 | r10
+;;  smuad   r8, r8, r4
+    smlad   r8, r8, r4, r2
+    pkhbt   r11, r11, r9, lsl #16           ; r9 | r11
+
+    smlad   lr, r10, r5, lr
+    ldrb    r10, [r0, #1]
+    smlad   r8, r11, r5, r8
+    ldrb    r11, [r0, #2]
+
+    subs    r12, r12, #1
+
+    pkhbt   r9, r9, r10, lsl #16            ; r10 | r9
+    pkhbt   r10, r10, r11, lsl #16          ; r11 | r10
+
+    smlad   lr, r9, r6, lr
+    smlad   r10, r10, r6, r8
+
+;;  add     lr, lr, #0x40                   ; round_shift_and_clamp
+    ldrneb  r8, [r0, #-2]                   ; load data for next loop
+    usat    lr, #8, lr, asr #7
+;;  add     r10, r10, #0x40
+    strb    lr, [r1], #1                    ; store the result
+    usat    r10, #8, r10, asr #7
+
+    ldrneb  r9, [r0, #-1]
+    strb    r10, [r1], #1
+    ldrneb  r10, [r0], #2
+
+    bne     width_loop_1st_only_6
+
+    ldr     lr, [sp]                        ; load back output pitch
+    ldr     r12, [sp, #4]                   ; load back output pitch
+    subs    r7, r7, #1
+    add     r0, r0, r12                     ; updata src for next loop
+
+    add     r11, r12, r3                    ; preload next low
+    add     r11, r11, #2
+    pld     [r0, r11]
+
+    add     r1, r1, lr                      ; update dst for next loop
+
+    bne     height_loop_1st_only_6
+
+    add     sp, sp, #8
+    ldmia   sp!, {r4 - r11, pc}
+    ENDP  ; |vp8_filter_block2d_first_pass_only_armv6|
+
+
+;------------------------------------
+; r0    unsigned char *src_ptr,
+; r1    unsigned char *output_ptr,
+; r2    unsigned int src_pixels_per_line
+; r3    unsigned int cnt,
+; stack unsigned int output_pitch,
+; stack const short *vp8_filter
+;------------------------------------
+|vp8_filter_block2d_second_pass_only_armv6| PROC
+    stmdb   sp!, {r4 - r11, lr}
+
+    ldr     r11, [sp, #40]                  ; VFilter address
+    ldr     r12, [sp, #36]                  ; output pitch
+
+    mov     r7, r3, lsl #16                 ; height is top part of counter
+    sub     r0, r0, r2, lsl #1              ; need 6 elements for filtering, 2 before, 3 after
+
+    sub     sp, sp, #8
+
+    ldr     r4, [r11]                       ; load up packed filter coefficients
+    ldr     r5, [r11, #4]
+    ldr     r6, [r11, #8]
+
+    str     r0, [sp]                        ; save r0 to stack
+    str     r1, [sp, #4]                    ; save dst to stack
+
+; six tap filter
+|width_loop_2nd_only_6|
+    ldrb    r8, [r0], r2                    ; load data
+    orr     r7, r7, r3                      ; loop counter
+    ldrb    r9, [r0], r2
+    ldrb    r10, [r0], r2
+
+|height_loop_2nd_only_6|
+    ; filter first column in this inner loop, than, move to next colum.
+    ldrb    r11, [r0], r2
+
+    pkhbt   lr, r8, r9, lsl #16             ; r9 | r8
+    pkhbt   r8, r9, r10, lsl #16            ; r10 | r9
+
+    ldrb    r9, [r0], r2
+
+    smuad   lr, lr, r4
+    pkhbt   r10, r10, r11, lsl #16          ; r11 | r10
+    smuad   r8, r8, r4
+    pkhbt   r11, r11, r9, lsl #16           ; r9 | r11
+
+    smlad   lr, r10, r5, lr
+    ldrb    r10, [r0], r2
+    smlad   r8, r11, r5, r8
+    ldrb    r11, [r0]
+
+    sub     r7, r7, #2
+    sub     r0, r0, r2, lsl #2
+
+    pkhbt   r9, r9, r10, lsl #16            ; r10 | r9
+    pkhbt   r10, r10, r11, lsl #16          ; r11 | r10
+
+    smlad   lr, r9, r6, lr
+    smlad   r10, r10, r6, r8
+
+    ands    r9, r7, #0xff
+
+    add     lr, lr, #0x40                   ; round_shift_and_clamp
+    ldrneb  r8, [r0], r2                    ; load data for next loop
+    usat    lr, #8, lr, asr #7
+    add     r10, r10, #0x40
+    strb    lr, [r1], r12                   ; store the result for the column
+    usat    r10, #8, r10, asr #7
+
+    ldrneb  r9, [r0], r2
+    strb    r10, [r1], r12
+    ldrneb  r10, [r0], r2
+
+    bne     height_loop_2nd_only_6
+
+    ldr     r0, [sp]
+    ldr     r1, [sp, #4]
+    subs    r7, r7, #0x10000
+    add     r0, r0, #1                      ; move to filter next column
+    str     r0, [sp]
+    add     r1, r1, #1
+    str     r1, [sp, #4]
+
+    bne     width_loop_2nd_only_6
+
+    add     sp, sp, #8
+
+    ldmia   sp!, {r4 - r11, pc}
+    ENDP  ; |vp8_filter_block2d_second_pass_only_armv6|
+
+    END
diff --git a/vp8/common/arm/armv6/idct_blk_v6.c b/vp8/common/arm/armv6/idct_blk_v6.c
new file mode 100644 (file)
index 0000000..6002c0f
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+
+
+void vp8_dequant_idct_add_y_block_v6(short *q, short *dq,
+                                     unsigned char *dst,
+                                     int stride, char *eobs)
+{
+    int i;
+
+    for (i = 0; i < 4; i++)
+    {
+        if (eobs[0] > 1)
+            vp8_dequant_idct_add_v6 (q, dq, dst, stride);
+        else if (eobs[0] == 1)
+        {
+            vp8_dc_only_idct_add_v6 (q[0]*dq[0], dst, stride, dst, stride);
+            ((int *)q)[0] = 0;
+        }
+
+        if (eobs[1] > 1)
+            vp8_dequant_idct_add_v6 (q+16, dq, dst+4, stride);
+        else if (eobs[1] == 1)
+        {
+            vp8_dc_only_idct_add_v6 (q[16]*dq[0], dst+4, stride, dst+4, stride);
+            ((int *)(q+16))[0] = 0;
+        }
+
+        if (eobs[2] > 1)
+            vp8_dequant_idct_add_v6 (q+32, dq, dst+8, stride);
+        else if (eobs[2] == 1)
+        {
+            vp8_dc_only_idct_add_v6 (q[32]*dq[0], dst+8, stride, dst+8, stride);
+            ((int *)(q+32))[0] = 0;
+        }
+
+        if (eobs[3] > 1)
+            vp8_dequant_idct_add_v6 (q+48, dq, dst+12, stride);
+        else if (eobs[3] == 1)
+        {
+            vp8_dc_only_idct_add_v6 (q[48]*dq[0], dst+12, stride,dst+12,stride);
+            ((int *)(q+48))[0] = 0;
+        }
+
+        q    += 64;
+        dst  += 4*stride;
+        eobs += 4;
+    }
+}
+
+void vp8_dequant_idct_add_uv_block_v6(short *q, short *dq,
+                                      unsigned char *dstu,
+                                      unsigned char *dstv,
+                                      int stride, char *eobs)
+{
+    int i;
+
+    for (i = 0; i < 2; i++)
+    {
+        if (eobs[0] > 1)
+            vp8_dequant_idct_add_v6 (q, dq, dstu, stride);
+        else if (eobs[0] == 1)
+        {
+            vp8_dc_only_idct_add_v6 (q[0]*dq[0], dstu, stride, dstu, stride);
+            ((int *)q)[0] = 0;
+        }
+
+        if (eobs[1] > 1)
+            vp8_dequant_idct_add_v6 (q+16, dq, dstu+4, stride);
+        else if (eobs[1] == 1)
+        {
+            vp8_dc_only_idct_add_v6 (q[16]*dq[0], dstu+4, stride,
+                                                  dstu+4, stride);
+            ((int *)(q+16))[0] = 0;
+        }
+
+        q    += 32;
+        dstu += 4*stride;
+        eobs += 2;
+    }
+
+    for (i = 0; i < 2; i++)
+    {
+        if (eobs[0] > 1)
+            vp8_dequant_idct_add_v6 (q, dq, dstv, stride);
+        else if (eobs[0] == 1)
+        {
+            vp8_dc_only_idct_add_v6 (q[0]*dq[0], dstv, stride, dstv, stride);
+            ((int *)q)[0] = 0;
+        }
+
+        if (eobs[1] > 1)
+            vp8_dequant_idct_add_v6 (q+16, dq, dstv+4, stride);
+        else if (eobs[1] == 1)
+        {
+            vp8_dc_only_idct_add_v6 (q[16]*dq[0], dstv+4, stride,
+                                                  dstv+4, stride);
+            ((int *)(q+16))[0] = 0;
+        }
+
+        q    += 32;
+        dstv += 4*stride;
+        eobs += 2;
+    }
+}
diff --git a/vp8/common/arm/armv6/idct_v6.asm b/vp8/common/arm/armv6/idct_v6.asm
new file mode 100644 (file)
index 0000000..b4d44cb
--- /dev/null
@@ -0,0 +1,202 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_short_idct4x4llm_v6_dual|
+
+    AREA    |.text|, CODE, READONLY
+
+
+; void vp8_short_idct4x4llm_c(short *input, unsigned char *pred, int pitch,
+;                             unsigned char *dst, int stride)
+; r0    short* input
+; r1    unsigned char* pred
+; r2    int pitch
+; r3    unsigned char* dst
+; sp    int stride
+
+|vp8_short_idct4x4llm_v6_dual| PROC
+    stmdb   sp!, {r4-r11, lr}
+
+    sub     sp, sp, #4
+
+    mov     r4, #0x00008A00         ; sin
+    orr     r4, r4, #0x0000008C     ; sinpi8sqrt2
+
+    mov     r5, #0x00004E00         ; cos
+    orr     r5, r5, #0x0000007B     ; cospi8sqrt2minus1
+    orr     r5, r5, #1<<31          ; loop counter on top bit
+
+loop1_dual
+    ldr     r6, [r0, #(4*2)]        ; i5 | i4
+    ldr     r12, [r0, #(12*2)]      ; i13|i12
+    ldr     r14, [r0, #(8*2)]       ; i9 | i8
+
+    smulbt  r9, r5, r6              ; (ip[5] * cospi8sqrt2minus1) >> 16
+    smulbb  r7, r5, r6              ; (ip[4] * cospi8sqrt2minus1) >> 16
+    smulwt  r10, r4, r6             ; (ip[5] * sinpi8sqrt2) >> 16
+    smulwb  r8, r4, r6              ; (ip[4] * sinpi8sqrt2) >> 16
+
+    smulbt  r11, r5, r12            ; (ip[13] * cospi8sqrt2minus1) >> 16
+    pkhtb   r7, r9, r7, asr #16     ; 5c | 4c
+    pkhbt   r8, r8, r10, lsl #16    ; 5s | 4s
+    uadd16  r6, r6, r7              ; 5c+5 | 4c+4
+
+    smulwt  r7, r4, r12             ; (ip[13] * sinpi8sqrt2) >> 16
+    smulbb  r9, r5, r12             ; (ip[12] * cospi8sqrt2minus1) >> 16
+    smulwb  r10, r4, r12            ; (ip[12] * sinpi8sqrt2) >> 16
+
+    subs    r5, r5, #1<<31          ; i--
+
+    pkhtb   r9, r11, r9, asr #16    ; 13c | 12c
+    ldr     r11, [r0]               ; i1 | i0
+    pkhbt   r10, r10, r7, lsl #16   ; 13s | 12s
+    uadd16  r7, r12, r9             ; 13c+13 | 12c+12
+
+    usub16  r7, r8, r7              ; c
+    uadd16  r6, r6, r10             ; d
+    uadd16  r10, r11, r14           ; a
+    usub16  r8, r11, r14            ; b
+
+    uadd16  r9, r10, r6             ; a+d
+    usub16  r10, r10, r6            ; a-d
+    uadd16  r6, r8, r7              ; b+c
+    usub16  r7, r8, r7              ; b-c
+
+    ; use input buffer to store intermediate results
+    str      r6, [r0, #(4*2)]       ; o5 | o4
+    str      r7, [r0, #(8*2)]       ; o9 | o8
+    str      r10,[r0, #(12*2)]      ; o13|o12
+    str      r9, [r0], #4           ; o1 | o0
+
+    bcs loop1_dual
+
+    sub     r0, r0, #8              ; reset input/output
+    str     r0, [sp]
+
+loop2_dual
+
+    ldr     r6, [r0, #(4*2)]        ; i5 | i4
+    ldr     r12,[r0, #(2*2)]        ; i3 | i2
+    ldr     r14,[r0, #(6*2)]        ; i7 | i6
+    ldr     r0, [r0, #(0*2)]        ; i1 | i0
+
+    smulbt  r9, r5, r6              ; (ip[5] * cospi8sqrt2minus1) >> 16
+    smulbt  r7, r5, r0              ; (ip[1] * cospi8sqrt2minus1) >> 16
+    smulwt  r10, r4, r6             ; (ip[5] * sinpi8sqrt2) >> 16
+    smulwt  r8, r4, r0              ; (ip[1] * sinpi8sqrt2) >> 16
+
+    pkhbt   r11, r6, r0, lsl #16    ; i0 | i4
+    pkhtb   r7, r7, r9, asr #16     ; 1c | 5c
+    pkhtb   r0, r0, r6, asr #16     ; i1 | i5
+    pkhbt   r8, r10, r8, lsl #16    ; 1s | 5s = temp1
+
+    uadd16  r0, r7, r0              ; 1c+1 | 5c+5 = temp2
+    pkhbt   r9, r14, r12, lsl #16   ; i2 | i6
+    uadd16  r10, r11, r9            ; a
+    usub16  r9, r11, r9             ; b
+    pkhtb   r6, r12, r14, asr #16   ; i3 | i7
+
+    subs    r5, r5, #1<<31          ; i--
+
+    smulbt  r7, r5, r6              ; (ip[3] * cospi8sqrt2minus1) >> 16
+    smulwt  r11, r4, r6             ; (ip[3] * sinpi8sqrt2) >> 16
+    smulbb  r12, r5, r6             ; (ip[7] * cospi8sqrt2minus1) >> 16
+    smulwb  r14, r4, r6             ; (ip[7] * sinpi8sqrt2) >> 16
+
+    pkhtb   r7, r7, r12, asr #16    ; 3c | 7c
+    pkhbt   r11, r14, r11, lsl #16  ; 3s | 7s = temp1
+
+    uadd16  r6, r7, r6              ; 3c+3 | 7c+7 = temp2
+    usub16  r12, r8, r6             ; c (o1 | o5)
+    uadd16  r6, r11, r0             ; d (o3 | o7)
+    uadd16  r7, r10, r6             ; a+d
+
+    mov     r8, #4                  ; set up 4's
+    orr     r8, r8, #0x40000        ; 4|4
+
+    usub16  r6, r10, r6             ; a-d
+    uadd16  r6, r6, r8              ; a-d+4, 3|7
+    uadd16  r7, r7, r8              ; a+d+4, 0|4
+    uadd16  r10, r9, r12            ; b+c
+    usub16  r0, r9, r12             ; b-c
+    uadd16  r10, r10, r8            ; b+c+4, 1|5
+    uadd16  r8, r0, r8              ; b-c+4, 2|6
+
+    ldr     lr, [sp, #40]           ; dst stride
+
+    ldrb    r0, [r1]                ; pred p0
+    ldrb    r11, [r1, #1]           ; pred p1
+    ldrb    r12, [r1, #2]           ; pred p2
+
+    add     r0, r0, r7, asr #19     ; p0 + o0
+    add     r11, r11, r10, asr #19  ; p1 + o1
+    add     r12, r12, r8, asr #19   ; p2 + o2
+
+    usat    r0, #8, r0              ; d0 = clip8(p0 + o0)
+    usat    r11, #8, r11            ; d1 = clip8(p1 + o1)
+    usat    r12, #8, r12            ; d2 = clip8(p2 + o2)
+
+    add     r0, r0, r11, lsl #8     ; |--|--|d1|d0|
+
+    ldrb    r11, [r1, #3]           ; pred p3
+
+    add     r0, r0, r12, lsl #16    ; |--|d2|d1|d0|
+
+    add     r11, r11, r6, asr #19   ; p3 + o3
+
+    sxth    r7, r7                  ;
+    sxth    r10, r10                ;
+
+    usat    r11, #8, r11            ; d3 = clip8(p3 + o3)
+
+    sxth    r8, r8                  ;
+    sxth    r6, r6                  ;
+
+    add     r0, r0, r11, lsl #24    ; |d3|d2|d1|d0|
+
+    ldrb    r12, [r1, r2]!          ; pred p4
+    str     r0, [r3], lr
+    ldrb    r11, [r1, #1]           ; pred p5
+
+    add     r12, r12, r7, asr #3    ; p4 + o4
+    add     r11, r11, r10, asr #3   ; p5 + o5
+
+    usat    r12, #8, r12            ; d4 = clip8(p4 + o4)
+    usat    r11, #8, r11            ; d5 = clip8(p5 + o5)
+
+    ldrb    r7, [r1, #2]            ; pred p6
+    ldrb    r10, [r1, #3]           ; pred p6
+
+    add     r12, r12, r11, lsl #8   ; |--|--|d5|d4|
+
+    add     r7, r7, r8, asr #3      ; p6 + o6
+    add     r10, r10, r6, asr #3    ; p7 + o7
+
+    ldr     r0, [sp]                ; load input pointer
+
+    usat    r7, #8, r7              ; d6 = clip8(p6 + o6)
+    usat    r10, #8, r10            ; d7 = clip8(p7 + o7)
+
+    add     r12, r12, r7, lsl #16   ; |--|d6|d5|d4|
+    add     r12, r12, r10, lsl #24  ; |d7|d6|d5|d4|
+
+    str     r12, [r3], lr
+    add     r0, r0, #16
+    add     r1, r1, r2              ; pred + pitch
+
+    bcs loop2_dual
+
+    add     sp, sp, #4              ; idct_output buffer
+    ldmia   sp!, {r4 - r11, pc}
+
+    ENDP
+
+    END
diff --git a/vp8/common/arm/armv6/intra4x4_predict_v6.asm b/vp8/common/arm/armv6/intra4x4_predict_v6.asm
new file mode 100644 (file)
index 0000000..a974cd1
--- /dev/null
@@ -0,0 +1,606 @@
+;
+;  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_intra4x4_predict_armv6|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+
+;void vp8_intra4x4_predict(unsigned char *src, int src_stride, int b_mode,
+;                          unsigned char *dst, int dst_stride)
+
+|vp8_intra4x4_predict_armv6| PROC
+    push        {r4-r12, lr}
+
+
+    cmp         r2, #10
+    addlt       pc, pc, r2, lsl #2       ; position independent switch
+    pop         {r4-r12, pc}             ; default
+    b           b_dc_pred
+    b           b_tm_pred
+    b           b_ve_pred
+    b           b_he_pred
+    b           b_ld_pred
+    b           b_rd_pred
+    b           b_vr_pred
+    b           b_vl_pred
+    b           b_hd_pred
+    b           b_hu_pred
+
+b_dc_pred
+    ; load values
+    ldr         r8, [r0, -r1]            ; Above
+    ldrb        r4, [r0, #-1]!           ; Left[0]
+    mov         r9, #0
+    ldrb        r5, [r0, r1]             ; Left[1]
+    ldrb        r6, [r0, r1, lsl #1]!    ; Left[2]
+    usad8       r12, r8, r9
+    ldrb        r7, [r0, r1]             ; Left[3]
+
+    ; calculate dc
+    add         r4, r4, r5
+    add         r4, r4, r6
+    add         r4, r4, r7
+    add         r4, r4, r12
+    add         r4, r4, #4
+    ldr         r0, [sp, #40]           ; load stride
+    mov         r12, r4, asr #3         ; (expected_dc + 4) >> 3
+
+    add         r12, r12, r12, lsl #8
+    add         r3, r3, r0
+    add         r12, r12, r12, lsl #16
+
+    ; store values
+    str         r12, [r3, -r0]
+    str         r12, [r3]
+    str         r12, [r3, r0]
+    str         r12, [r3, r0, lsl #1]
+
+    pop        {r4-r12, pc}
+
+b_tm_pred
+    sub         r10, r0, #1             ; Left
+    ldr         r8, [r0, -r1]           ; Above
+    ldrb        r9, [r10, -r1]          ; top_left
+    ldrb        r4, [r0, #-1]!          ; Left[0]
+    ldrb        r5, [r10, r1]!          ; Left[1]
+    ldrb        r6, [r0, r1, lsl #1]    ; Left[2]
+    ldrb        r7, [r10, r1, lsl #1]   ; Left[3]
+    ldr         r0, [sp, #40]           ; load stride
+
+
+    add         r9, r9, r9, lsl #16     ; [tl|tl]
+    uxtb16      r10, r8                 ; a[2|0]
+    uxtb16      r11, r8, ror #8         ; a[3|1]
+    ssub16      r10, r10, r9            ; a[2|0] - [tl|tl]
+    ssub16      r11, r11, r9            ; a[3|1] - [tl|tl]
+
+    add         r4, r4, r4, lsl #16     ; l[0|0]
+    add         r5, r5, r5, lsl #16     ; l[1|1]
+    add         r6, r6, r6, lsl #16     ; l[2|2]
+    add         r7, r7, r7, lsl #16     ; l[3|3]
+
+    sadd16      r1, r4, r10             ; l[0|0] + a[2|0] - [tl|tl]
+    sadd16      r2, r4, r11             ; l[0|0] + a[3|1] - [tl|tl]
+    usat16      r1, #8, r1
+    usat16      r2, #8, r2
+
+    sadd16      r4, r5, r10             ; l[1|1] + a[2|0] - [tl|tl]
+    sadd16      r5, r5, r11             ; l[1|1] + a[3|1] - [tl|tl]
+
+    add         r12, r1, r2, lsl #8     ; [3|2|1|0]
+    str         r12, [r3], r0
+
+    usat16      r4, #8, r4
+    usat16      r5, #8, r5
+
+    sadd16      r1, r6, r10             ; l[2|2] + a[2|0] - [tl|tl]
+    sadd16      r2, r6, r11             ; l[2|2] + a[3|1] - [tl|tl]
+
+    add         r12, r4, r5, lsl #8     ; [3|2|1|0]
+    str         r12, [r3], r0
+
+    usat16      r1, #8, r1
+    usat16      r2, #8, r2
+
+    sadd16      r4, r7, r10             ; l[3|3] + a[2|0] - [tl|tl]
+    sadd16      r5, r7, r11             ; l[3|3] + a[3|1] - [tl|tl]
+
+    add         r12, r1, r2, lsl #8     ; [3|2|1|0]
+
+    usat16      r4, #8, r4
+    usat16      r5, #8, r5
+
+    str         r12, [r3], r0
+
+    add         r12, r4, r5, lsl #8     ; [3|2|1|0]
+    str         r12, [r3], r0
+
+    pop        {r4-r12, pc}
+
+b_ve_pred
+    ldr         r8, [r0, -r1]!          ; a[3|2|1|0]
+    ldr         r11, c00FF00FF
+    ldrb        r9, [r0, #-1]           ; top_left
+    ldrb        r10, [r0, #4]           ; a[4]
+
+    ldr         r0, c00020002
+
+    uxtb16      r4, r8                  ; a[2|0]
+    uxtb16      r5, r8, ror #8          ; a[3|1]
+    ldr         r2, [sp, #40]           ; stride
+    pkhbt       r9, r9, r5, lsl #16     ; a[1|-1]
+
+    add         r9, r9, r4, lsl #1      ;[a[1]+2*a[2]       | tl+2*a[0]       ]
+    uxtab16     r9, r9, r5              ;[a[1]+2*a[2]+a[3]  | tl+2*a[0]+a[1]  ]
+    uxtab16     r9, r9, r0              ;[a[1]+2*a[2]+a[3]+2| tl+2*a[0]+a[1]+2]
+
+    add         r0, r0, r10, lsl #16    ;[a[4]+2            |                 2]
+    add         r0, r0, r4, asr #16     ;[a[4]+2            |            a[2]+2]
+    add         r0, r0, r5, lsl #1      ;[a[4]+2*a[3]+2     |     a[2]+2*a[1]+2]
+    uadd16      r4, r4, r0              ;[a[4]+2*a[3]+a[2]+2|a[2]+2*a[1]+a[0]+2]
+
+    and         r9, r11, r9, asr #2
+    and         r4, r11, r4, asr #2
+    add         r3, r3, r2              ; dst + dst_stride
+    add         r9, r9, r4, lsl #8
+
+    ; store values
+    str         r9, [r3, -r2]
+    str         r9, [r3]
+    str         r9, [r3, r2]
+    str         r9, [r3, r2, lsl #1]
+
+    pop        {r4-r12, pc}
+
+
+b_he_pred
+    sub         r10, r0, #1             ; Left
+    ldrb        r4, [r0, #-1]!          ; Left[0]
+    ldrb        r8, [r10, -r1]          ; top_left
+    ldrb        r5, [r10, r1]!          ; Left[1]
+    ldrb        r6, [r0, r1, lsl #1]    ; Left[2]
+    ldrb        r7, [r10, r1, lsl #1]   ; Left[3]
+
+    add         r8, r8, r4              ; tl   + l[0]
+    add         r9, r4, r5              ; l[0] + l[1]
+    add         r10, r5, r6             ; l[1] + l[2]
+    add         r11, r6, r7             ; l[2] + l[3]
+
+    mov         r0, #2<<14
+
+    add         r8, r8, r9              ; tl + 2*l[0] + l[1]
+    add         r4, r9, r10             ; l[0] + 2*l[1] + l[2]
+    add         r5, r10, r11            ; l[1] + 2*l[2] + l[3]
+    add         r6, r11, r7, lsl #1     ; l[2] + 2*l[3] + l[3]
+
+
+    add         r8, r0, r8, lsl #14     ; (tl + 2*l[0] + l[1])>>2 in top half
+    add         r9, r0, r4, lsl #14     ; (l[0] + 2*l[1] + l[2])>>2 in top half
+    add         r10,r0, r5, lsl #14     ; (l[1] + 2*l[2] + l[3])>>2 in top half
+    add         r11,r0, r6, lsl #14     ; (l[2] + 2*l[3] + l[3])>>2 in top half
+
+    pkhtb       r8, r8, r8, asr #16     ; l[-|0|-|0]
+    pkhtb       r9, r9, r9, asr #16     ; l[-|1|-|1]
+    pkhtb       r10, r10, r10, asr #16  ; l[-|2|-|2]
+    pkhtb       r11, r11, r11, asr #16  ; l[-|3|-|3]
+
+    ldr         r0, [sp, #40]           ; stride
+
+    add         r8, r8, r8, lsl #8      ; l[0|0|0|0]
+    add         r9, r9, r9, lsl #8      ; l[1|1|1|1]
+    add         r10, r10, r10, lsl #8   ; l[2|2|2|2]
+    add         r11, r11, r11, lsl #8   ; l[3|3|3|3]
+
+    ; store values
+    str         r8, [r3], r0
+    str         r9, [r3]
+    str         r10, [r3, r0]
+    str         r11, [r3, r0, lsl #1]
+
+    pop        {r4-r12, pc}
+
+b_ld_pred
+    ldr         r4, [r0, -r1]!          ; Above
+    ldr         r12, c00020002
+    ldr         r5, [r0, #4]
+    ldr         lr,  c00FF00FF
+
+    uxtb16      r6, r4                  ; a[2|0]
+    uxtb16      r7, r4, ror #8          ; a[3|1]
+    uxtb16      r8, r5                  ; a[6|4]
+    uxtb16      r9, r5, ror #8          ; a[7|5]
+    pkhtb       r10, r6, r8             ; a[2|4]
+    pkhtb       r11, r7, r9             ; a[3|5]
+
+
+    add         r4, r6, r7, lsl #1      ; [a2+2*a3      |      a0+2*a1]
+    add         r4, r4, r10, ror #16    ; [a2+2*a3+a4   |   a0+2*a1+a2]
+    uxtab16     r4, r4, r12             ; [a2+2*a3+a4+2 | a0+2*a1+a2+2]
+
+    add         r5, r7, r10, ror #15    ; [a3+2*a4      |      a1+2*a2]
+    add         r5, r5, r11, ror #16    ; [a3+2*a4+a5   |   a1+2*a2+a3]
+    uxtab16     r5, r5, r12             ; [a3+2*a4+a5+2 | a1+2*a2+a3+2]
+
+    pkhtb       r7, r9, r8, asr #16
+    add         r6, r8, r9, lsl #1      ; [a6+2*a7      |      a4+2*a5]
+    uadd16      r6, r6, r7              ; [a6+2*a7+a7   |   a4+2*a5+a6]
+    uxtab16     r6, r6, r12             ; [a6+2*a7+a7+2 | a4+2*a5+a6+2]
+
+    uxth        r7, r9                  ; [                         a5]
+    add         r7, r7, r8, asr #15     ; [                    a5+2*a6]
+    add         r7, r7, r9, asr #16     ; [                 a5+2*a6+a7]
+    uxtah       r7, r7, r12             ; [               a5+2*a6+a7+2]
+
+    ldr         r0, [sp, #40]           ; stride
+
+    ; scale down
+    and         r4, lr, r4, asr #2
+    and         r5, lr, r5, asr #2
+    and         r6, lr, r6, asr #2
+    mov         r7, r7, asr #2
+
+    add         r8, r4, r5, lsl #8      ; [3|2|1|0]
+    str         r8, [r3], r0
+
+    mov         r9, r8, lsr #8
+    add         r9, r9, r6, lsl #24     ; [4|3|2|1]
+    str         r9, [r3], r0
+
+    mov         r10, r9, lsr #8
+    add         r10, r10, r7, lsl #24   ; [5|4|3|2]
+    str         r10, [r3], r0
+
+    mov         r6, r6, lsr #16
+    mov         r11, r10, lsr #8
+    add         r11, r11, r6, lsl #24   ; [6|5|4|3]
+    str         r11, [r3], r0
+
+    pop        {r4-r12, pc}
+
+b_rd_pred
+    sub         r12, r0, r1             ; Above = src - src_stride
+    ldrb        r7, [r0, #-1]!          ; l[0] = pp[3]
+    ldr         lr, [r12]               ; Above = pp[8|7|6|5]
+    ldrb        r8, [r12, #-1]!         ; tl   = pp[4]
+    ldrb        r6, [r12, r1, lsl #1]   ; l[1] = pp[2]
+    ldrb        r5, [r0, r1, lsl #1]    ; l[2] = pp[1]
+    ldrb        r4, [r12, r1, lsl #2]   ; l[3] = pp[0]
+
+
+    uxtb16      r9, lr                  ; p[7|5]
+    uxtb16      r10, lr, ror #8         ; p[8|6]
+    add         r4, r4, r6, lsl #16     ; p[2|0]
+    add         r5, r5, r7, lsl #16     ; p[3|1]
+    add         r6, r6, r8, lsl #16     ; p[4|2]
+    pkhbt       r7, r7, r9, lsl #16     ; p[5|3]
+    pkhbt       r8, r8, r10, lsl #16    ; p[6|4]
+
+    ldr         r12, c00020002
+    ldr         lr,  c00FF00FF
+
+    add         r4, r4, r5, lsl #1      ; [p2+2*p3      |      p0+2*p1]
+    add         r4, r4, r6              ; [p2+2*p3+p4   |   p0+2*p1+p2]
+    uxtab16     r4, r4, r12             ; [p2+2*p3+p4+2 | p0+2*p1+p2+2]
+
+    add         r5, r5, r6, lsl #1      ; [p3+2*p4      |      p1+2*p2]
+    add         r5, r5, r7              ; [p3+2*p4+p5   |   p1+2*p2+p3]
+    uxtab16     r5, r5, r12             ; [p3+2*p4+p5+2 | p1+2*p2+p3+2]
+
+    add         r6, r7, r8, lsl #1      ; [p5+2*p6      |      p3+2*p4]
+    add         r6, r6, r9              ; [p5+2*p6+p7   |   p3+2*p4+p5]
+    uxtab16     r6, r6, r12             ; [p5+2*p6+p7+2 | p3+2*p4+p5+2]
+
+    add         r7, r8, r9, lsl #1      ; [p6+2*p7      |      p4+2*p5]
+    add         r7, r7, r10             ; [p6+2*p7+p8   |   p4+2*p5+p6]
+    uxtab16     r7, r7, r12             ; [p6+2*p7+p8+2 | p4+2*p5+p6+2]
+
+    ldr         r0, [sp, #40]           ; stride
+
+    ; scale down
+    and         r7, lr, r7, asr #2
+    and         r6, lr, r6, asr #2
+    and         r5, lr, r5, asr #2
+    and         r4, lr, r4, asr #2
+
+    add         r8, r6, r7, lsl #8      ; [6|5|4|3]
+    str         r8, [r3], r0
+
+    mov         r9, r8, lsl #8          ; [5|4|3|-]
+    uxtab       r9, r9, r4, ror #16     ; [5|4|3|2]
+    str         r9, [r3], r0
+
+    mov         r10, r9, lsl #8         ; [4|3|2|-]
+    uxtab       r10, r10, r5            ; [4|3|2|1]
+    str         r10, [r3], r0
+
+    mov         r11, r10, lsl #8        ; [3|2|1|-]
+    uxtab       r11, r11, r4            ; [3|2|1|0]
+    str         r11, [r3], r0
+
+    pop        {r4-r12, pc}
+
+b_vr_pred
+    sub         r12, r0, r1             ; Above = src - src_stride
+    ldrb        r7, [r0, #-1]!          ; l[0] = pp[3]
+    ldr         lr, [r12]               ; Above = pp[8|7|6|5]
+    ldrb        r8, [r12, #-1]!         ; tl   = pp[4]
+    ldrb        r6, [r12, r1, lsl #1]   ; l[1] = pp[2]
+    ldrb        r5, [r0, r1, lsl #1]    ; l[2] = pp[1]
+    ldrb        r4, [r12, r1, lsl #2]   ; l[3] = pp[0]
+
+    add         r5, r5, r7, lsl #16     ; p[3|1]
+    add         r6, r6, r8, lsl #16     ; p[4|2]
+    uxtb16      r9, lr                  ; p[7|5]
+    uxtb16      r10, lr, ror #8         ; p[8|6]
+    pkhbt       r7, r7, r9, lsl #16     ; p[5|3]
+    pkhbt       r8, r8, r10, lsl #16    ; p[6|4]
+
+    ldr         r4,  c00010001
+    ldr         r12, c00020002
+    ldr         lr,  c00FF00FF
+
+    add         r5, r5, r6, lsl #1      ; [p3+2*p4      |      p1+2*p2]
+    add         r5, r5, r7              ; [p3+2*p4+p5   |   p1+2*p2+p3]
+    uxtab16     r5, r5, r12             ; [p3+2*p4+p5+2 | p1+2*p2+p3+2]
+
+    add         r6, r6, r7, lsl #1      ; [p4+2*p5      |      p2+2*p3]
+    add         r6, r6, r8              ; [p4+2*p5+p6   |   p2+2*p3+p4]
+    uxtab16     r6, r6, r12             ; [p4+2*p5+p6+2 | p2+2*p3+p4+2]
+
+    uadd16      r11, r8, r9             ; [p6+p7        |        p4+p5]
+    uhadd16     r11, r11, r4            ; [(p6+p7+1)>>1 | (p4+p5+1)>>1]
+                                        ; [F|E]
+
+    add         r7, r7, r8, lsl #1      ; [p5+2*p6      |      p3+2*p4]
+    add         r7, r7, r9              ; [p5+2*p6+p7   |   p3+2*p4+p5]
+    uxtab16     r7, r7, r12             ; [p5+2*p6+p7+2 | p3+2*p4+p5+2]
+
+    uadd16      r2, r9, r10             ; [p7+p8        |        p5+p6]
+    uhadd16     r2, r2, r4              ; [(p7+p8+1)>>1 | (p5+p6+1)>>1]
+                                        ; [J|I]
+
+    add         r8, r8, r9, lsl #1      ; [p6+2*p7      |      p4+2*p5]
+    add         r8, r8, r10             ; [p6+2*p7+p8   |   p4+2*p5+p6]
+    uxtab16     r8, r8, r12             ; [p6+2*p7+p8+2 | p4+2*p5+p6+2]
+
+    ldr         r0, [sp, #40]           ; stride
+
+    ; scale down
+    and         r5, lr, r5, asr #2      ; [B|A]
+    and         r6, lr, r6, asr #2      ; [D|C]
+    and         r7, lr, r7, asr #2      ; [H|G]
+    and         r8, lr, r8, asr #2      ; [L|K]
+
+    add         r12, r11, r2, lsl #8    ; [J|F|I|E]
+    str         r12, [r3], r0
+
+    add         r12, r7, r8, lsl #8     ; [L|H|K|G]
+    str         r12, [r3], r0
+
+    pkhbt       r2, r6, r2, lsl #16     ; [-|I|-|C]
+    add         r2, r2, r11, lsl #8     ; [F|I|E|C]
+
+    pkhtb       r12, r6, r5             ; [-|D|-|A]
+    pkhtb       r10, r7, r5, asr #16    ; [-|H|-|B]
+    str         r2, [r3], r0
+    add         r12, r12, r10, lsl #8   ; [H|D|B|A]
+    str         r12, [r3], r0
+
+    pop        {r4-r12, pc}
+
+b_vl_pred
+    ldr         r4, [r0, -r1]!          ; [3|2|1|0]
+    ldr         r12, c00020002
+    ldr         r5, [r0, #4]            ; [7|6|5|4]
+    ldr         lr,  c00FF00FF
+    ldr         r2,  c00010001
+
+    mov         r0, r4, lsr #16         ; [-|-|3|2]
+    add         r0, r0, r5, lsl #16     ; [5|4|3|2]
+    uxtb16      r6, r4                  ; [2|0]
+    uxtb16      r7, r4, ror #8          ; [3|1]
+    uxtb16      r8, r0                  ; [4|2]
+    uxtb16      r9, r0, ror #8          ; [5|3]
+    uxtb16      r10, r5                 ; [6|4]
+    uxtb16      r11, r5, ror #8         ; [7|5]
+
+    uadd16      r4, r6, r7              ; [p2+p3        |        p0+p1]
+    uhadd16     r4, r4, r2              ; [(p2+p3+1)>>1 | (p0+p1+1)>>1]
+                                        ; [B|A]
+
+    add         r5, r6, r7, lsl #1      ; [p2+2*p3      |      p0+2*p1]
+    add         r5, r5, r8              ; [p2+2*p3+p4   |   p0+2*p1+p2]
+    uxtab16     r5, r5, r12             ; [p2+2*p3+p4+2 | p0+2*p1+p2+2]
+
+    uadd16      r6, r7, r8              ; [p3+p4        |        p1+p2]
+    uhadd16     r6, r6, r2              ; [(p3+p4+1)>>1 | (p1+p2+1)>>1]
+                                        ; [F|E]
+
+    add         r7, r7, r8, lsl #1      ; [p3+2*p4      |      p1+2*p2]
+    add         r7, r7, r9              ; [p3+2*p4+p5   |   p1+2*p2+p3]
+    uxtab16     r7, r7, r12             ; [p3+2*p4+p5+2 | p1+2*p2+p3+2]
+
+    add         r8, r8, r9, lsl #1      ; [p4+2*p5      |      p2+2*p3]
+    add         r8, r8, r10             ; [p4+2*p5+p6   |   p2+2*p3+p4]
+    uxtab16     r8, r8, r12             ; [p4+2*p5+p6+2 | p2+2*p3+p4+2]
+
+    add         r9, r9, r10, lsl #1     ; [p5+2*p6      |      p3+2*p4]
+    add         r9, r9, r11             ; [p5+2*p6+p7   |   p3+2*p4+p5]
+    uxtab16     r9, r9, r12             ; [p5+2*p6+p7+2 | p3+2*p4+p5+2]
+
+    ldr         r0, [sp, #40]           ; stride
+
+    ; scale down
+    and         r5, lr, r5, asr #2      ; [D|C]
+    and         r7, lr, r7, asr #2      ; [H|G]
+    and         r8, lr, r8, asr #2      ; [I|D]
+    and         r9, lr, r9, asr #2      ; [J|H]
+
+
+    add         r10, r4, r6, lsl #8     ; [F|B|E|A]
+    str         r10, [r3], r0
+
+    add         r5, r5, r7, lsl #8      ; [H|C|G|D]
+    str         r5, [r3], r0
+
+    pkhtb       r12, r8, r4, asr #16    ; [-|I|-|B]
+    pkhtb       r10, r9, r8             ; [-|J|-|D]
+
+    add         r12, r6, r12, lsl #8    ; [I|F|B|E]
+    str         r12, [r3], r0
+
+    add         r10, r7, r10, lsl #8    ; [J|H|D|G]
+    str         r10, [r3], r0
+
+    pop        {r4-r12, pc}
+
+b_hd_pred
+    sub         r12, r0, r1             ; Above = src - src_stride
+    ldrb        r7, [r0, #-1]!          ; l[0] = pp[3]
+    ldr         lr, [r12]               ; Above = pp[8|7|6|5]
+    ldrb        r8, [r12, #-1]!         ; tl   = pp[4]
+    ldrb        r6, [r0, r1]            ; l[1] = pp[2]
+    ldrb        r5, [r0, r1, lsl #1]    ; l[2] = pp[1]
+    ldrb        r4, [r12, r1, lsl #2]   ; l[3] = pp[0]
+
+    uxtb16      r9, lr                  ; p[7|5]
+    uxtb16      r10, lr, ror #8         ; p[8|6]
+
+    add         r4, r4, r5, lsl #16     ; p[1|0]
+    add         r5, r5, r6, lsl #16     ; p[2|1]
+    add         r6, r6, r7, lsl #16     ; p[3|2]
+    add         r7, r7, r8, lsl #16     ; p[4|3]
+
+    ldr         r12, c00020002
+    ldr         lr,  c00FF00FF
+    ldr         r2,  c00010001
+
+    pkhtb       r8, r7, r9              ; p[4|5]
+    pkhtb       r1, r9, r10             ; p[7|6]
+    pkhbt       r10, r8, r10, lsl #16   ; p[6|5]
+
+
+    uadd16      r11, r4, r5             ; [p1+p2        |        p0+p1]
+    uhadd16     r11, r11, r2            ; [(p1+p2+1)>>1 | (p0+p1+1)>>1]
+                                        ; [B|A]
+
+    add         r4, r4, r5, lsl #1      ; [p1+2*p2      |      p0+2*p1]
+    add         r4, r4, r6              ; [p1+2*p2+p3   |   p0+2*p1+p2]
+    uxtab16     r4, r4, r12             ; [p1+2*p2+p3+2 | p0+2*p1+p2+2]
+
+    uadd16      r0, r6, r7              ; [p3+p4        |        p2+p3]
+    uhadd16     r0, r0, r2              ; [(p3+p4+1)>>1 | (p2+p3+1)>>1]
+                                        ; [F|E]
+
+    add         r5, r6, r7, lsl #1      ; [p3+2*p4      |      p2+2*p3]
+    add         r5, r5, r8, ror #16     ; [p3+2*p4+p5   |   p2+2*p3+p4]
+    uxtab16     r5, r5, r12             ; [p3+2*p4+p5+2 | p2+2*p3+p4+2]
+
+    add         r6, r12, r8, ror #16    ; [p5+2         |         p4+2]
+    add         r6, r6, r10, lsl #1     ; [p5+2+2*p6    |    p4+2+2*p5]
+    uxtab16     r6, r6, r1              ; [p5+2+2*p6+p7 | p4+2+2*p5+p6]
+
+    ; scale down
+    and         r4, lr, r4, asr #2      ; [D|C]
+    and         r5, lr, r5, asr #2      ; [H|G]
+    and         r6, lr, r6, asr #2      ; [J|I]
+
+    ldr         lr, [sp, #40]           ; stride
+
+    pkhtb       r2, r0, r6              ; [-|F|-|I]
+    pkhtb       r12, r6, r5, asr #16    ; [-|J|-|H]
+    add         r12, r12, r2, lsl #8    ; [F|J|I|H]
+    add         r2, r0, r5, lsl #8      ; [H|F|G|E]
+    mov         r12, r12, ror #24       ; [J|I|H|F]
+    str         r12, [r3], lr
+
+
+    mov         r7, r11, asr #16        ; [-|-|-|B]
+    str         r2, [r3], lr
+    add         r7, r7, r0, lsl #16     ; [-|E|-|B]
+    add         r7, r7, r4, asr #8      ; [-|E|D|B]
+    add         r7, r7, r5, lsl #24     ; [G|E|D|B]
+    str         r7, [r3], lr
+
+    add         r5, r11, r4, lsl #8     ; [D|B|C|A]
+    str         r5, [r3], lr
+
+    pop        {r4-r12, pc}
+
+
+
+b_hu_pred
+    ldrb        r4, [r0, #-1]!          ; Left[0]
+    ldr         r12, c00020002
+    ldrb        r5, [r0, r1]!           ; Left[1]
+    ldr         lr,  c00FF00FF
+    ldrb        r6, [r0, r1]!           ; Left[2]
+    ldr         r2,  c00010001
+    ldrb        r7, [r0, r1]            ; Left[3]
+
+
+    add         r4, r4, r5, lsl #16     ; [1|0]
+    add         r5, r5, r6, lsl #16     ; [2|1]
+    add         r9, r6, r7, lsl #16     ; [3|2]
+
+    uadd16      r8, r4, r5              ; [p1+p2        |        p0+p1]
+    uhadd16     r8, r8, r2              ; [(p1+p2+1)>>1 | (p0+p1+1)>>1]
+                                        ; [B|A]
+
+    add         r4, r4, r5, lsl #1      ; [p1+2*p2      |      p0+2*p1]
+    add         r4, r4, r9              ; [p1+2*p2+p3   |   p0+2*p1+p2]
+    uxtab16     r4, r4, r12             ; [p1+2*p2+p3+2 | p0+2*p1+p2+2]
+    ldr         r2, [sp, #40]           ; stride
+    and         r4, lr, r4, asr #2      ; [D|C]
+
+    add         r10, r6, r7             ; [p2+p3]
+    add         r11, r10, r7, lsl #1    ; [p2+3*p3]
+    add         r10, r10, #1
+    add         r11, r11, #2
+    mov         r10, r10, asr #1        ; [E]
+    mov         r11, r11, asr #2        ; [F]
+
+    add         r9, r7, r9, asr #8      ; [-|-|G|G]
+    add         r0, r8, r4, lsl #8      ; [D|B|C|A]
+    add         r7, r9, r9, lsl #16     ; [G|G|G|G]
+
+    str         r0, [r3], r2
+
+    mov         r1, r8, asr #16         ; [-|-|-|B]
+    add         r1, r1, r4, asr #8      ; [-|-|D|B]
+    add         r1, r1, r10, lsl #16    ; [-|E|D|B]
+    add         r1, r1, r11, lsl #24    ; [F|E|D|B]
+    str         r1, [r3], r2
+
+    add         r10, r11, lsl #8        ; [-|-|F|E]
+    add         r10, r10, r9, lsl #16   ; [G|G|F|E]
+    str         r10, [r3]
+
+    str         r7, [r3, r2]
+
+    pop        {r4-r12, pc}
+
+    ENDP
+
+; constants
+c00010001
+    DCD         0x00010001
+c00020002
+    DCD         0x00020002
+c00FF00FF
+    DCD         0x00FF00FF
+
+    END
diff --git a/vp8/common/arm/armv6/iwalsh_v6.asm b/vp8/common/arm/armv6/iwalsh_v6.asm
new file mode 100644 (file)
index 0000000..31ef09c
--- /dev/null
@@ -0,0 +1,136 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+    EXPORT |vp8_short_inv_walsh4x4_v6|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+
+;short vp8_short_inv_walsh4x4_v6(short *input, short *mb_dqcoeff)
+|vp8_short_inv_walsh4x4_v6| PROC
+
+    stmdb       sp!, {r4 - r12, lr}
+
+    ldr         r2, [r0, #0]         ; [1  |  0]
+    ldr         r3, [r0, #4]         ; [3  |  2]
+    ldr         r4, [r0, #8]         ; [5  |  4]
+    ldr         r5, [r0, #12]        ; [7  |  6]
+    ldr         r6, [r0, #16]        ; [9  |  8]
+    ldr         r7, [r0, #20]        ; [11 | 10]
+    ldr         r8, [r0, #24]        ; [13 | 12]
+    ldr         r9, [r0, #28]        ; [15 | 14]
+
+    qadd16      r10, r2, r8          ; a1 [1+13  |  0+12]
+    qadd16      r11, r4, r6          ; b1 [5+9   |  4+8]
+    qsub16      r12, r4, r6          ; c1 [5-9   |  4-8]
+    qsub16      lr, r2, r8           ; d1 [1-13  |  0-12]
+
+    qadd16      r2, r10, r11         ; a1 + b1 [1  |  0]
+    qadd16      r4, r12, lr          ; c1 + d1 [5  |  4]
+    qsub16      r6, r10, r11         ; a1 - b1 [9  |  8]
+    qsub16      r8, lr, r12          ; d1 - c1 [13 | 12]
+
+    qadd16      r10, r3, r9          ; a1 [3+15  |  2+14]
+    qadd16      r11, r5, r7          ; b1 [7+11  |  6+10]
+    qsub16      r12, r5, r7          ; c1 [7-11  |  6-10]
+    qsub16      lr, r3, r9           ; d1 [3-15  |  2-14]
+
+    qadd16      r3, r10, r11         ; a1 + b1 [3  |  2]
+    qadd16      r5, r12, lr          ; c1 + d1 [7  |  6]
+    qsub16      r7, r10, r11         ; a1 - b1 [11 | 10]
+    qsub16      r9, lr, r12          ; d1 - c1 [15 | 14]
+
+    ; first transform complete
+
+    qsubaddx    r10, r2, r3          ; [c1|a1] [1-2   |   0+3]
+    qaddsubx    r11, r2, r3          ; [b1|d1] [1+2   |   0-3]
+    qsubaddx    r12, r4, r5          ; [c1|a1] [5-6   |   4+7]
+    qaddsubx    lr, r4, r5           ; [b1|d1] [5+6   |   4-7]
+
+    qaddsubx    r2, r10, r11         ; [b2|c2] [c1+d1 | a1-b1]
+    qaddsubx    r3, r11, r10         ; [a2|d2] [b1+a1 | d1-c1]
+    ldr         r10, c0x00030003
+    qaddsubx    r4, r12, lr          ; [b2|c2] [c1+d1 | a1-b1]
+    qaddsubx    r5, lr, r12          ; [a2|d2] [b1+a1 | d1-c1]
+
+    qadd16      r2, r2, r10          ; [b2+3|c2+3]
+    qadd16      r3, r3, r10          ; [a2+3|d2+3]
+    qadd16      r4, r4, r10          ; [b2+3|c2+3]
+    qadd16      r5, r5, r10          ; [a2+3|d2+3]
+
+    asr         r12, r3, #19         ; [0]
+    strh        r12, [r1], #32
+    asr         lr, r2, #19          ; [1]
+    strh        lr, [r1], #32
+    sxth        r2, r2
+    sxth        r3, r3
+    asr         r2, r2, #3           ; [2]
+    strh        r2, [r1], #32
+    asr         r3, r3, #3           ; [3]
+    strh        r3, [r1], #32
+
+    asr         r12, r5, #19         ; [4]
+    strh        r12, [r1], #32
+    asr         lr, r4, #19          ; [5]
+    strh        lr, [r1], #32
+    sxth        r4, r4
+    sxth        r5, r5
+    asr         r4, r4, #3           ; [6]
+    strh        r4, [r1], #32
+    asr         r5, r5, #3           ; [7]
+    strh        r5, [r1], #32
+
+    qsubaddx    r2, r6, r7           ; [c1|a1] [9-10  |  8+11]
+    qaddsubx    r3, r6, r7           ; [b1|d1] [9+10  |  8-11]
+    qsubaddx    r4, r8, r9           ; [c1|a1] [13-14 | 12+15]
+    qaddsubx    r5, r8, r9           ; [b1|d1] [13+14 | 12-15]
+
+    qaddsubx    r6, r2, r3           ; [b2|c2] [c1+d1 | a1-b1]
+    qaddsubx    r7, r3, r2           ; [a2|d2] [b1+a1 | d1-c1]
+    qaddsubx    r8, r4, r5           ; [b2|c2] [c1+d1 | a1-b1]
+    qaddsubx    r9, r5, r4           ; [a2|d2] [b1+a1 | d1-c1]
+
+    qadd16      r6, r6, r10          ; [b2+3|c2+3]
+    qadd16      r7, r7, r10          ; [a2+3|d2+3]
+    qadd16      r8, r8, r10          ; [b2+3|c2+3]
+    qadd16      r9, r9, r10          ; [a2+3|d2+3]
+
+    asr         r12, r7, #19         ; [8]
+    strh        r12, [r1], #32
+    asr         lr, r6, #19          ; [9]
+    strh        lr, [r1], #32
+    sxth        r6, r6
+    sxth        r7, r7
+    asr         r6, r6, #3           ; [10]
+    strh        r6, [r1], #32
+    asr         r7, r7, #3           ; [11]
+    strh        r7, [r1], #32
+
+    asr         r12, r9, #19         ; [12]
+    strh        r12, [r1], #32
+    asr         lr, r8, #19          ; [13]
+    strh        lr, [r1], #32
+    sxth        r8, r8
+    sxth        r9, r9
+    asr         r8, r8, #3           ; [14]
+    strh        r8, [r1], #32
+    asr         r9, r9, #3           ; [15]
+    strh        r9, [r1], #32
+
+    ldmia       sp!, {r4 - r12, pc}
+    ENDP        ; |vp8_short_inv_walsh4x4_v6|
+
+
+; Constant Pool
+c0x00030003 DCD 0x00030003
+    END
diff --git a/vp8/common/arm/armv6/loopfilter_v6.asm b/vp8/common/arm/armv6/loopfilter_v6.asm
new file mode 100644 (file)
index 0000000..1cbbbcd
--- /dev/null
@@ -0,0 +1,1282 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT |vp8_loop_filter_horizontal_edge_armv6|
+    EXPORT |vp8_mbloop_filter_horizontal_edge_armv6|
+    EXPORT |vp8_loop_filter_vertical_edge_armv6|
+    EXPORT |vp8_mbloop_filter_vertical_edge_armv6|
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+
+    MACRO
+    TRANSPOSE_MATRIX $a0, $a1, $a2, $a3, $b0, $b1, $b2, $b3
+    ; input: $a0, $a1, $a2, $a3; output: $b0, $b1, $b2, $b3
+    ; a0: 03 02 01 00
+    ; a1: 13 12 11 10
+    ; a2: 23 22 21 20
+    ; a3: 33 32 31 30
+    ;     b3 b2 b1 b0
+
+    uxtb16      $b1, $a1                    ; xx 12 xx 10
+    uxtb16      $b0, $a0                    ; xx 02 xx 00
+    uxtb16      $b3, $a3                    ; xx 32 xx 30
+    uxtb16      $b2, $a2                    ; xx 22 xx 20
+    orr         $b1, $b0, $b1, lsl #8       ; 12 02 10 00
+    orr         $b3, $b2, $b3, lsl #8       ; 32 22 30 20
+
+    uxtb16      $a1, $a1, ror #8            ; xx 13 xx 11
+    uxtb16      $a3, $a3, ror #8            ; xx 33 xx 31
+    uxtb16      $a0, $a0, ror #8            ; xx 03 xx 01
+    uxtb16      $a2, $a2, ror #8            ; xx 23 xx 21
+    orr         $a0, $a0, $a1, lsl #8       ; 13 03 11 01
+    orr         $a2, $a2, $a3, lsl #8       ; 33 23 31 21
+
+    pkhtb       $b2, $b3, $b1, asr #16      ; 32 22 12 02   -- p1
+    pkhbt       $b0, $b1, $b3, lsl #16      ; 30 20 10 00   -- p3
+
+    pkhtb       $b3, $a2, $a0, asr #16      ; 33 23 13 03   -- p0
+    pkhbt       $b1, $a0, $a2, lsl #16      ; 31 21 11 01   -- p2
+    MEND
+
+
+src         RN  r0
+pstep       RN  r1
+count       RN  r5
+
+;r0     unsigned char *src_ptr,
+;r1     int src_pixel_step,
+;r2     const char *blimit,
+;r3     const char *limit,
+;stack  const char *thresh,
+;stack  int  count
+
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+|vp8_loop_filter_horizontal_edge_armv6| PROC
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+    stmdb       sp!, {r4 - r11, lr}
+
+    sub         src, src, pstep, lsl #2     ; move src pointer down by 4 lines
+    ldr         count, [sp, #40]            ; count for 8-in-parallel
+    ldr         r6, [sp, #36]               ; load thresh address
+    sub         sp, sp, #16                 ; create temp buffer
+
+    ldr         r9, [src], pstep            ; p3
+    ldrb        r4, [r2]                    ; blimit
+    ldr         r10, [src], pstep           ; p2
+    ldrb        r2, [r3]                    ; limit
+    ldr         r11, [src], pstep           ; p1
+    orr         r4, r4, r4, lsl #8
+    ldrb        r3, [r6]                    ; thresh
+    orr         r2, r2, r2, lsl #8
+    mov         count, count, lsl #1        ; 4-in-parallel
+    orr         r4, r4, r4, lsl #16
+    orr         r3, r3, r3, lsl #8
+    orr         r2, r2, r2, lsl #16
+    orr         r3, r3, r3, lsl #16
+
+|Hnext8|
+    ; vp8_filter_mask() function
+    ; calculate breakout conditions
+    ldr         r12, [src], pstep           ; p0
+
+    uqsub8      r6, r9, r10                 ; p3 - p2
+    uqsub8      r7, r10, r9                 ; p2 - p3
+    uqsub8      r8, r10, r11                ; p2 - p1
+    uqsub8      r10, r11, r10               ; p1 - p2
+
+    orr         r6, r6, r7                  ; abs (p3-p2)
+    orr         r8, r8, r10                 ; abs (p2-p1)
+    uqsub8      lr, r6, r2                  ; compare to limit. lr: vp8_filter_mask
+    uqsub8      r8, r8, r2                  ; compare to limit
+    uqsub8      r6, r11, r12                ; p1 - p0
+    orr         lr, lr, r8
+    uqsub8      r7, r12, r11                ; p0 - p1
+    ldr         r9, [src], pstep            ; q0
+    ldr         r10, [src], pstep           ; q1
+    orr         r6, r6, r7                  ; abs (p1-p0)
+    uqsub8      r7, r6, r2                  ; compare to limit
+    uqsub8      r8, r6, r3                  ; compare to thresh  -- save r8 for later
+    orr         lr, lr, r7
+
+    uqsub8      r6, r11, r10                ; p1 - q1
+    uqsub8      r7, r10, r11                ; q1 - p1
+    uqsub8      r11, r12, r9                ; p0 - q0
+    uqsub8      r12, r9, r12                ; q0 - p0
+    orr         r6, r6, r7                  ; abs (p1-q1)
+    ldr         r7, c0x7F7F7F7F
+    orr         r12, r11, r12               ; abs (p0-q0)
+    ldr         r11, [src], pstep           ; q2
+    uqadd8      r12, r12, r12               ; abs (p0-q0) * 2
+    and         r6, r7, r6, lsr #1          ; abs (p1-q1) / 2
+    uqsub8      r7, r9, r10                 ; q0 - q1
+    uqadd8      r12, r12, r6                ; abs (p0-q0)*2 + abs (p1-q1)/2
+    uqsub8      r6, r10, r9                 ; q1 - q0
+    uqsub8      r12, r12, r4                ; compare to flimit
+    uqsub8      r9, r11, r10                ; q2 - q1
+
+    orr         lr, lr, r12
+
+    ldr         r12, [src], pstep           ; q3
+    uqsub8      r10, r10, r11               ; q1 - q2
+    orr         r6, r7, r6                  ; abs (q1-q0)
+    orr         r10, r9, r10                ; abs (q2-q1)
+    uqsub8      r7, r6, r2                  ; compare to limit
+    uqsub8      r10, r10, r2                ; compare to limit
+    uqsub8      r6, r6, r3                  ; compare to thresh -- save r6 for later
+    orr         lr, lr, r7
+    orr         lr, lr, r10
+
+    uqsub8      r10, r12, r11               ; q3 - q2
+    uqsub8      r9, r11, r12                ; q2 - q3
+
+    mvn         r11, #0                     ; r11 == -1
+
+    orr         r10, r10, r9                ; abs (q3-q2)
+    uqsub8      r10, r10, r2                ; compare to limit
+
+    mov         r12, #0
+    orr         lr, lr, r10
+    sub         src, src, pstep, lsl #2
+
+    usub8       lr, r12, lr                 ; use usub8 instead of ssub8
+    sel         lr, r11, r12                ; filter mask: lr
+
+    cmp         lr, #0
+    beq         hskip_filter                 ; skip filtering
+
+    sub         src, src, pstep, lsl #1     ; move src pointer down by 6 lines
+
+    ;vp8_hevmask() function
+    ;calculate high edge variance
+    orr         r10, r6, r8                 ; calculate vp8_hevmask
+
+    ldr         r7, [src], pstep            ; p1
+
+    usub8       r10, r12, r10               ; use usub8 instead of ssub8
+    sel         r6, r12, r11                ; obtain vp8_hevmask: r6
+
+    ;vp8_filter() function
+    ldr         r8, [src], pstep            ; p0
+    ldr         r12, c0x80808080
+    ldr         r9, [src], pstep            ; q0
+    ldr         r10, [src], pstep           ; q1
+
+    eor         r7, r7, r12                 ; p1 offset to convert to a signed value
+    eor         r8, r8, r12                 ; p0 offset to convert to a signed value
+    eor         r9, r9, r12                 ; q0 offset to convert to a signed value
+    eor         r10, r10, r12               ; q1 offset to convert to a signed value
+
+    str         r9, [sp]                    ; store qs0 temporarily
+    str         r8, [sp, #4]                ; store ps0 temporarily
+    str         r10, [sp, #8]               ; store qs1 temporarily
+    str         r7, [sp, #12]               ; store ps1 temporarily
+
+    qsub8       r7, r7, r10                 ; vp8_signed_char_clamp(ps1-qs1)
+    qsub8       r8, r9, r8                  ; vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+
+    and         r7, r7, r6                  ; vp8_filter (r7) &= hev
+
+    qadd8       r7, r7, r8
+    ldr         r9, c0x03030303             ; r9 = 3 --modified for vp8
+
+    qadd8       r7, r7, r8
+    ldr         r10, c0x04040404
+
+    qadd8       r7, r7, r8
+    and         r7, r7, lr                  ; vp8_filter &= mask;
+
+    ;modify code for vp8 -- Filter1 = vp8_filter (r7)
+    qadd8       r8 , r7 , r9                ; Filter2 (r8) = vp8_signed_char_clamp(vp8_filter+3)
+    qadd8       r7 , r7 , r10               ; vp8_filter = vp8_signed_char_clamp(vp8_filter+4)
+
+    mov         r9, #0
+    shadd8      r8 , r8 , r9                ; Filter2 >>= 3
+    shadd8      r7 , r7 , r9                ; vp8_filter >>= 3
+    shadd8      r8 , r8 , r9
+    shadd8      r7 , r7 , r9
+    shadd8      lr , r8 , r9                ; lr: Filter2
+    shadd8      r7 , r7 , r9                ; r7: filter
+
+    ;usub8      lr, r8, r10                 ; s = (s==4)*-1
+    ;sel        lr, r11, r9
+    ;usub8      r8, r10, r8
+    ;sel        r8, r11, r9
+    ;and        r8, r8, lr                  ; -1 for each element that equals 4
+
+    ;calculate output
+    ;qadd8      lr, r8, r7                  ; u = vp8_signed_char_clamp(s + vp8_filter)
+
+    ldr         r8, [sp]                    ; load qs0
+    ldr         r9, [sp, #4]                ; load ps0
+
+    ldr         r10, c0x01010101
+
+    qsub8       r8 ,r8, r7                  ; u = vp8_signed_char_clamp(qs0 - vp8_filter)
+    qadd8       r9, r9, lr                  ; u = vp8_signed_char_clamp(ps0 + Filter2)
+
+    ;end of modification for vp8
+
+    mov         lr, #0
+    sadd8       r7, r7 , r10                ; vp8_filter += 1
+    shadd8      r7, r7, lr                  ; vp8_filter >>= 1
+
+    ldr         r11, [sp, #12]              ; load ps1
+    ldr         r10, [sp, #8]               ; load qs1
+
+    bic         r7, r7, r6                  ; vp8_filter &= ~hev
+    sub         src, src, pstep, lsl #2
+
+    qadd8       r11, r11, r7                ; u = vp8_signed_char_clamp(ps1 + vp8_filter)
+    qsub8       r10, r10,r7                 ; u = vp8_signed_char_clamp(qs1 - vp8_filter)
+
+    eor         r11, r11, r12               ; *op1 = u^0x80
+    str         r11, [src], pstep           ; store op1
+    eor         r9, r9, r12                 ; *op0 = u^0x80
+    str         r9, [src], pstep            ; store op0 result
+    eor         r8, r8, r12                 ; *oq0 = u^0x80
+    str         r8, [src], pstep            ; store oq0 result
+    eor         r10, r10, r12               ; *oq1 = u^0x80
+    str         r10, [src], pstep           ; store oq1
+
+    sub         src, src, pstep, lsl #1
+
+|hskip_filter|
+    add         src, src, #4
+    sub         src, src, pstep, lsl #2
+
+    subs        count, count, #1
+
+    ldrne       r9, [src], pstep            ; p3
+    ldrne       r10, [src], pstep           ; p2
+    ldrne       r11, [src], pstep           ; p1
+
+    bne         Hnext8
+
+    add         sp, sp, #16
+    ldmia       sp!, {r4 - r11, pc}
+    ENDP        ; |vp8_loop_filter_horizontal_edge_armv6|
+
+
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+|vp8_mbloop_filter_horizontal_edge_armv6| PROC
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+    stmdb       sp!, {r4 - r11, lr}
+
+    sub         src, src, pstep, lsl #2     ; move src pointer down by 4 lines
+    ldr         count, [sp, #40]            ; count for 8-in-parallel
+    ldr         r6, [sp, #36]               ; load thresh address
+    sub         sp, sp, #16                 ; create temp buffer
+
+    ldr         r9, [src], pstep            ; p3
+    ldrb        r4, [r2]                    ; blimit
+    ldr         r10, [src], pstep           ; p2
+    ldrb        r2, [r3]                    ; limit
+    ldr         r11, [src], pstep           ; p1
+    orr         r4, r4, r4, lsl #8
+    ldrb        r3, [r6]                    ; thresh
+    orr         r2, r2, r2, lsl #8
+    mov         count, count, lsl #1        ; 4-in-parallel
+    orr         r4, r4, r4, lsl #16
+    orr         r3, r3, r3, lsl #8
+    orr         r2, r2, r2, lsl #16
+    orr         r3, r3, r3, lsl #16
+
+|MBHnext8|
+
+    ; vp8_filter_mask() function
+    ; calculate breakout conditions
+    ldr         r12, [src], pstep           ; p0
+
+    uqsub8      r6, r9, r10                 ; p3 - p2
+    uqsub8      r7, r10, r9                 ; p2 - p3
+    uqsub8      r8, r10, r11                ; p2 - p1
+    uqsub8      r10, r11, r10               ; p1 - p2
+
+    orr         r6, r6, r7                  ; abs (p3-p2)
+    orr         r8, r8, r10                 ; abs (p2-p1)
+    uqsub8      lr, r6, r2                  ; compare to limit. lr: vp8_filter_mask
+    uqsub8      r8, r8, r2                  ; compare to limit
+
+    uqsub8      r6, r11, r12                ; p1 - p0
+    orr         lr, lr, r8
+    uqsub8      r7, r12, r11                ; p0 - p1
+    ldr         r9, [src], pstep            ; q0
+    ldr         r10, [src], pstep           ; q1
+    orr         r6, r6, r7                  ; abs (p1-p0)
+    uqsub8      r7, r6, r2                  ; compare to limit
+    uqsub8      r8, r6, r3                  ; compare to thresh  -- save r8 for later
+    orr         lr, lr, r7
+
+    uqsub8      r6, r11, r10                ; p1 - q1
+    uqsub8      r7, r10, r11                ; q1 - p1
+    uqsub8      r11, r12, r9                ; p0 - q0
+    uqsub8      r12, r9, r12                ; q0 - p0
+    orr         r6, r6, r7                  ; abs (p1-q1)
+    ldr         r7, c0x7F7F7F7F
+    orr         r12, r11, r12               ; abs (p0-q0)
+    ldr         r11, [src], pstep           ; q2
+    uqadd8      r12, r12, r12               ; abs (p0-q0) * 2
+    and         r6, r7, r6, lsr #1          ; abs (p1-q1) / 2
+    uqsub8      r7, r9, r10                 ; q0 - q1
+    uqadd8      r12, r12, r6                ; abs (p0-q0)*2 + abs (p1-q1)/2
+    uqsub8      r6, r10, r9                 ; q1 - q0
+    uqsub8      r12, r12, r4                ; compare to flimit
+    uqsub8      r9, r11, r10                ; q2 - q1
+
+    orr         lr, lr, r12
+
+    ldr         r12, [src], pstep           ; q3
+
+    uqsub8      r10, r10, r11               ; q1 - q2
+    orr         r6, r7, r6                  ; abs (q1-q0)
+    orr         r10, r9, r10                ; abs (q2-q1)
+    uqsub8      r7, r6, r2                  ; compare to limit
+    uqsub8      r10, r10, r2                ; compare to limit
+    uqsub8      r6, r6, r3                  ; compare to thresh -- save r6 for later
+    orr         lr, lr, r7
+    orr         lr, lr, r10
+
+    uqsub8      r10, r12, r11               ; q3 - q2
+    uqsub8      r9, r11, r12                ; q2 - q3
+
+    mvn         r11, #0                     ; r11 == -1
+
+    orr         r10, r10, r9                ; abs (q3-q2)
+    uqsub8      r10, r10, r2                ; compare to limit
+
+    mov         r12, #0
+
+    orr         lr, lr, r10
+
+    usub8       lr, r12, lr                 ; use usub8 instead of ssub8
+    sel         lr, r11, r12                ; filter mask: lr
+
+    cmp         lr, #0
+    beq         mbhskip_filter               ; skip filtering
+
+    ;vp8_hevmask() function
+    ;calculate high edge variance
+    sub         src, src, pstep, lsl #2     ; move src pointer down by 6 lines
+    sub         src, src, pstep, lsl #1
+
+    orr         r10, r6, r8
+    ldr         r7, [src], pstep            ; p1
+
+    usub8       r10, r12, r10
+    sel         r6, r12, r11                ; hev mask: r6
+
+    ;vp8_mbfilter() function
+    ;p2, q2 are only needed at the end. Don't need to load them in now.
+    ldr         r8, [src], pstep            ; p0
+    ldr         r12, c0x80808080
+    ldr         r9, [src], pstep            ; q0
+    ldr         r10, [src]                  ; q1
+
+    eor         r7, r7, r12                 ; ps1
+    eor         r8, r8, r12                 ; ps0
+    eor         r9, r9, r12                 ; qs0
+    eor         r10, r10, r12               ; qs1
+
+    qsub8       r12, r9, r8                 ; vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+    str         r7, [sp, #12]               ; store ps1 temporarily
+    qsub8       r7, r7, r10                 ; vp8_signed_char_clamp(ps1-qs1)
+    str         r10, [sp, #8]               ; store qs1 temporarily
+    qadd8       r7, r7, r12
+    str         r9, [sp]                    ; store qs0 temporarily
+    qadd8       r7, r7, r12
+    str         r8, [sp, #4]                ; store ps0 temporarily
+    qadd8       r7, r7, r12                 ; vp8_filter: r7
+
+    ldr         r10, c0x03030303            ; r10 = 3 --modified for vp8
+    ldr         r9, c0x04040404
+
+    and         r7, r7, lr                  ; vp8_filter &= mask (lr is free)
+
+    mov         r12, r7                     ; Filter2: r12
+    and         r12, r12, r6                ; Filter2 &= hev
+
+    ;modify code for vp8
+    ;save bottom 3 bits so that we round one side +4 and the other +3
+    qadd8       r8 , r12 , r9               ; Filter1 (r8) = vp8_signed_char_clamp(Filter2+4)
+    qadd8       r12 , r12 , r10             ; Filter2 (r12) = vp8_signed_char_clamp(Filter2+3)
+
+    mov         r10, #0
+    shadd8      r8 , r8 , r10               ; Filter1 >>= 3
+    shadd8      r12 , r12 , r10             ; Filter2 >>= 3
+    shadd8      r8 , r8 , r10
+    shadd8      r12 , r12 , r10
+    shadd8      r8 , r8 , r10               ; r8: Filter1
+    shadd8      r12 , r12 , r10             ; r12: Filter2
+
+    ldr         r9, [sp]                    ; load qs0
+    ldr         r11, [sp, #4]               ; load ps0
+
+    qsub8       r9 , r9, r8                 ; qs0 = vp8_signed_char_clamp(qs0 - Filter1)
+    qadd8       r11, r11, r12               ; ps0 = vp8_signed_char_clamp(ps0 + Filter2)
+
+    ;save bottom 3 bits so that we round one side +4 and the other +3
+    ;and            r8, r12, r10                ; s = Filter2 & 7 (s: r8)
+    ;qadd8      r12 , r12 , r9              ; Filter2 = vp8_signed_char_clamp(Filter2+4)
+    ;mov            r10, #0
+    ;shadd8     r12 , r12 , r10             ; Filter2 >>= 3
+    ;usub8      lr, r8, r9                  ; s = (s==4)*-1
+    ;sel            lr, r11, r10
+    ;shadd8     r12 , r12 , r10
+    ;usub8      r8, r9, r8
+    ;sel            r8, r11, r10
+    ;ldr            r9, [sp]                    ; load qs0
+    ;ldr            r11, [sp, #4]               ; load ps0
+    ;shadd8     r12 , r12 , r10
+    ;and            r8, r8, lr                  ; -1 for each element that equals 4
+    ;qadd8      r10, r8, r12                ; u = vp8_signed_char_clamp(s + Filter2)
+    ;qsub8      r9 , r9, r12                ; qs0 = vp8_signed_char_clamp(qs0 - Filter2)
+    ;qadd8      r11, r11, r10               ; ps0 = vp8_signed_char_clamp(ps0 + u)
+
+    ;end of modification for vp8
+
+    bic         r12, r7, r6                 ; vp8_filter &= ~hev    ( r6 is free)
+    ;mov        r12, r7
+
+    ;roughly 3/7th difference across boundary
+    mov         lr, #0x1b                   ; 27
+    mov         r7, #0x3f                   ; 63
+
+    sxtb16      r6, r12
+    sxtb16      r10, r12, ror #8
+    smlabb      r8, r6, lr, r7
+    smlatb      r6, r6, lr, r7
+    smlabb      r7, r10, lr, r7
+    smultb      r10, r10, lr
+    ssat        r8, #8, r8, asr #7
+    ssat        r6, #8, r6, asr #7
+    add         r10, r10, #63
+    ssat        r7, #8, r7, asr #7
+    ssat        r10, #8, r10, asr #7
+
+    ldr         lr, c0x80808080
+
+    pkhbt       r6, r8, r6, lsl #16
+    pkhbt       r10, r7, r10, lsl #16
+    uxtb16      r6, r6
+    uxtb16      r10, r10
+
+    sub         src, src, pstep
+
+    orr         r10, r6, r10, lsl #8        ; u = vp8_signed_char_clamp((63 + Filter2 * 27)>>7)
+
+    qsub8       r8, r9, r10                 ; s = vp8_signed_char_clamp(qs0 - u)
+    qadd8       r10, r11, r10               ; s = vp8_signed_char_clamp(ps0 + u)
+    eor         r8, r8, lr                  ; *oq0 = s^0x80
+    str         r8, [src]                   ; store *oq0
+    sub         src, src, pstep
+    eor         r10, r10, lr                ; *op0 = s^0x80
+    str         r10, [src]                  ; store *op0
+
+    ;roughly 2/7th difference across boundary
+    mov         lr, #0x12                   ; 18
+    mov         r7, #0x3f                   ; 63
+
+    sxtb16      r6, r12
+    sxtb16      r10, r12, ror #8
+    smlabb      r8, r6, lr, r7
+    smlatb      r6, r6, lr, r7
+    smlabb      r9, r10, lr, r7
+    smlatb      r10, r10, lr, r7
+    ssat        r8, #8, r8, asr #7
+    ssat        r6, #8, r6, asr #7
+    ssat        r9, #8, r9, asr #7
+    ssat        r10, #8, r10, asr #7
+
+    ldr         lr, c0x80808080
+
+    pkhbt       r6, r8, r6, lsl #16
+    pkhbt       r10, r9, r10, lsl #16
+
+    ldr         r9, [sp, #8]                ; load qs1
+    ldr         r11, [sp, #12]              ; load ps1
+
+    uxtb16      r6, r6
+    uxtb16      r10, r10
+
+    sub         src, src, pstep
+
+    orr         r10, r6, r10, lsl #8        ; u = vp8_signed_char_clamp((63 + Filter2 * 18)>>7)
+
+    qadd8       r11, r11, r10               ; s = vp8_signed_char_clamp(ps1 + u)
+    qsub8       r8, r9, r10                 ; s = vp8_signed_char_clamp(qs1 - u)
+    eor         r11, r11, lr                ; *op1 = s^0x80
+    str         r11, [src], pstep           ; store *op1
+    eor         r8, r8, lr                  ; *oq1 = s^0x80
+    add         src, src, pstep, lsl #1
+
+    mov         r7, #0x3f                   ; 63
+
+    str         r8, [src], pstep            ; store *oq1
+
+    ;roughly 1/7th difference across boundary
+    mov         lr, #0x9                    ; 9
+    ldr         r9, [src]                   ; load q2
+
+    sxtb16      r6, r12
+    sxtb16      r10, r12, ror #8
+    smlabb      r8, r6, lr, r7
+    smlatb      r6, r6, lr, r7
+    smlabb      r12, r10, lr, r7
+    smlatb      r10, r10, lr, r7
+    ssat        r8, #8, r8, asr #7
+    ssat        r6, #8, r6, asr #7
+    ssat        r12, #8, r12, asr #7
+    ssat        r10, #8, r10, asr #7
+
+    sub         src, src, pstep, lsl #2
+
+    pkhbt       r6, r8, r6, lsl #16
+    pkhbt       r10, r12, r10, lsl #16
+
+    sub         src, src, pstep
+    ldr         lr, c0x80808080
+
+    ldr         r11, [src]                  ; load p2
+
+    uxtb16      r6, r6
+    uxtb16      r10, r10
+
+    eor         r9, r9, lr
+    eor         r11, r11, lr
+
+    orr         r10, r6, r10, lsl #8        ; u = vp8_signed_char_clamp((63 + Filter2 * 9)>>7)
+
+    qadd8       r8, r11, r10                ; s = vp8_signed_char_clamp(ps2 + u)
+    qsub8       r10, r9, r10                ; s = vp8_signed_char_clamp(qs2 - u)
+    eor         r8, r8, lr                  ; *op2 = s^0x80
+    str         r8, [src], pstep, lsl #2    ; store *op2
+    add         src, src, pstep
+    eor         r10, r10, lr                ; *oq2 = s^0x80
+    str         r10, [src], pstep, lsl #1   ; store *oq2
+
+|mbhskip_filter|
+    add         src, src, #4
+    sub         src, src, pstep, lsl #3
+    subs        count, count, #1
+
+    ldrne       r9, [src], pstep            ; p3
+    ldrne       r10, [src], pstep           ; p2
+    ldrne       r11, [src], pstep           ; p1
+
+    bne         MBHnext8
+
+    add         sp, sp, #16
+    ldmia       sp!, {r4 - r11, pc}
+    ENDP        ; |vp8_mbloop_filter_horizontal_edge_armv6|
+
+
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+|vp8_loop_filter_vertical_edge_armv6| PROC
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+    stmdb       sp!, {r4 - r11, lr}
+
+    sub         src, src, #4                ; move src pointer down by 4
+    ldr         count, [sp, #40]            ; count for 8-in-parallel
+    ldr         r12, [sp, #36]              ; load thresh address
+    sub         sp, sp, #16                 ; create temp buffer
+
+    ldr         r6, [src], pstep            ; load source data
+    ldrb        r4, [r2]                    ; blimit
+    ldr         r7, [src], pstep
+    ldrb        r2, [r3]                    ; limit
+    ldr         r8, [src], pstep
+    orr         r4, r4, r4, lsl #8
+    ldrb        r3, [r12]                   ; thresh
+    orr         r2, r2, r2, lsl #8
+    ldr         lr, [src], pstep
+    mov         count, count, lsl #1        ; 4-in-parallel
+    orr         r4, r4, r4, lsl #16
+    orr         r3, r3, r3, lsl #8
+    orr         r2, r2, r2, lsl #16
+    orr         r3, r3, r3, lsl #16
+
+|Vnext8|
+
+    ; vp8_filter_mask() function
+    ; calculate breakout conditions
+    ; transpose the source data for 4-in-parallel operation
+    TRANSPOSE_MATRIX r6, r7, r8, lr, r9, r10, r11, r12
+
+    uqsub8      r7, r9, r10                 ; p3 - p2
+    uqsub8      r8, r10, r9                 ; p2 - p3
+    uqsub8      r9, r10, r11                ; p2 - p1
+    uqsub8      r10, r11, r10               ; p1 - p2
+    orr         r7, r7, r8                  ; abs (p3-p2)
+    orr         r10, r9, r10                ; abs (p2-p1)
+    uqsub8      lr, r7, r2                  ; compare to limit. lr: vp8_filter_mask
+    uqsub8      r10, r10, r2                ; compare to limit
+
+    sub         src, src, pstep, lsl #2     ; move src pointer down by 4 lines
+
+    orr         lr, lr, r10
+
+    uqsub8      r6, r11, r12                ; p1 - p0
+    uqsub8      r7, r12, r11                ; p0 - p1
+    add         src, src, #4                ; move src pointer up by 4
+    orr         r6, r6, r7                  ; abs (p1-p0)
+    str         r11, [sp, #12]              ; save p1
+    uqsub8      r10, r6, r2                 ; compare to limit
+    uqsub8      r11, r6, r3                 ; compare to thresh
+    orr         lr, lr, r10
+
+    ; transpose uses 8 regs(r6 - r12 and lr). Need to save reg value now
+    ; transpose the source data for 4-in-parallel operation
+    ldr         r6, [src], pstep            ; load source data
+    str         r11, [sp]                   ; push r11 to stack
+    ldr         r7, [src], pstep
+    str         r12, [sp, #4]               ; save current reg before load q0 - q3 data
+    ldr         r8, [src], pstep
+    str         lr, [sp, #8]
+    ldr         lr, [src], pstep
+
+    TRANSPOSE_MATRIX r6, r7, r8, lr, r9, r10, r11, r12
+
+    ldr         lr, [sp, #8]                ; load back (f)limit accumulator
+
+    uqsub8      r6, r12, r11                ; q3 - q2
+    uqsub8      r7, r11, r12                ; q2 - q3
+    uqsub8      r12, r11, r10               ; q2 - q1
+    uqsub8      r11, r10, r11               ; q1 - q2
+    orr         r6, r6, r7                  ; abs (q3-q2)
+    orr         r7, r12, r11                ; abs (q2-q1)
+    uqsub8      r6, r6, r2                  ; compare to limit
+    uqsub8      r7, r7, r2                  ; compare to limit
+    ldr         r11, [sp, #4]               ; load back p0
+    ldr         r12, [sp, #12]              ; load back p1
+    orr         lr, lr, r6
+    orr         lr, lr, r7
+
+    uqsub8      r6, r11, r9                 ; p0 - q0
+    uqsub8      r7, r9, r11                 ; q0 - p0
+    uqsub8      r8, r12, r10                ; p1 - q1
+    uqsub8      r11, r10, r12               ; q1 - p1
+    orr         r6, r6, r7                  ; abs (p0-q0)
+    ldr         r7, c0x7F7F7F7F
+    orr         r8, r8, r11                 ; abs (p1-q1)
+    uqadd8      r6, r6, r6                  ; abs (p0-q0) * 2
+    and         r8, r7, r8, lsr #1          ; abs (p1-q1) / 2
+    uqsub8      r11, r10, r9                ; q1 - q0
+    uqadd8      r6, r8, r6                  ; abs (p0-q0)*2 + abs (p1-q1)/2
+    uqsub8      r12, r9, r10                ; q0 - q1
+    uqsub8      r6, r6, r4                  ; compare to flimit
+
+    orr         r9, r11, r12                ; abs (q1-q0)
+    uqsub8      r8, r9, r2                  ; compare to limit
+    uqsub8      r10, r9, r3                 ; compare to thresh
+    orr         lr, lr, r6
+    orr         lr, lr, r8
+
+    mvn         r11, #0                     ; r11 == -1
+    mov         r12, #0
+
+    usub8       lr, r12, lr
+    ldr         r9, [sp]                    ; load the compared result
+    sel         lr, r11, r12                ; filter mask: lr
+
+    cmp         lr, #0
+    beq         vskip_filter                 ; skip filtering
+
+    ;vp8_hevmask() function
+    ;calculate high edge variance
+
+    sub         src, src, pstep, lsl #2     ; move src pointer down by 4 lines
+
+    orr         r9, r9, r10
+
+    ldrh        r7, [src, #-2]
+    ldrh        r8, [src], pstep
+
+    usub8       r9, r12, r9
+    sel         r6, r12, r11                ; hev mask: r6
+
+    ;vp8_filter() function
+    ; load soure data to r6, r11, r12, lr
+    ldrh        r9, [src, #-2]
+    ldrh        r10, [src], pstep
+
+    pkhbt       r12, r7, r8, lsl #16
+
+    ldrh        r7, [src, #-2]
+    ldrh        r8, [src], pstep
+
+    pkhbt       r11, r9, r10, lsl #16
+
+    ldrh        r9, [src, #-2]
+    ldrh        r10, [src], pstep
+
+    ; Transpose needs 8 regs(r6 - r12, and lr). Save r6 and lr first
+    str         r6, [sp]
+    str         lr, [sp, #4]
+
+    pkhbt       r6, r7, r8, lsl #16
+    pkhbt       lr, r9, r10, lsl #16
+
+    ;transpose r12, r11, r6, lr to r7, r8, r9, r10
+    TRANSPOSE_MATRIX r12, r11, r6, lr, r7, r8, r9, r10
+
+    ;load back hev_mask r6 and filter_mask lr
+    ldr         r12, c0x80808080
+    ldr         r6, [sp]
+    ldr         lr, [sp, #4]
+
+    eor         r7, r7, r12                 ; p1 offset to convert to a signed value
+    eor         r8, r8, r12                 ; p0 offset to convert to a signed value
+    eor         r9, r9, r12                 ; q0 offset to convert to a signed value
+    eor         r10, r10, r12               ; q1 offset to convert to a signed value
+
+    str         r9, [sp]                    ; store qs0 temporarily
+    str         r8, [sp, #4]                ; store ps0 temporarily
+    str         r10, [sp, #8]               ; store qs1 temporarily
+    str         r7, [sp, #12]               ; store ps1 temporarily
+
+    qsub8       r7, r7, r10                 ; vp8_signed_char_clamp(ps1-qs1)
+    qsub8       r8, r9, r8                  ; vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+
+    and         r7, r7, r6                  ;  vp8_filter (r7) &= hev (r7 : filter)
+
+    qadd8       r7, r7, r8
+    ldr         r9, c0x03030303             ; r9 = 3 --modified for vp8
+
+    qadd8       r7, r7, r8
+    ldr         r10, c0x04040404
+
+    qadd8       r7, r7, r8
+    ;mvn         r11, #0                     ; r11 == -1
+
+    and         r7, r7, lr                  ; vp8_filter &= mask
+
+    ;modify code for vp8 -- Filter1 = vp8_filter (r7)
+    qadd8       r8 , r7 , r9                ; Filter2 (r8) = vp8_signed_char_clamp(vp8_filter+3)
+    qadd8       r7 , r7 , r10               ; vp8_filter = vp8_signed_char_clamp(vp8_filter+4)
+
+    mov         r9, #0
+    shadd8      r8 , r8 , r9                ; Filter2 >>= 3
+    shadd8      r7 , r7 , r9                ; vp8_filter >>= 3
+    shadd8      r8 , r8 , r9
+    shadd8      r7 , r7 , r9
+    shadd8      lr , r8 , r9                ; lr: filter2
+    shadd8      r7 , r7 , r9                ; r7: filter
+
+    ;usub8      lr, r8, r10                 ; s = (s==4)*-1
+    ;sel            lr, r11, r9
+    ;usub8      r8, r10, r8
+    ;sel            r8, r11, r9
+    ;and            r8, r8, lr                  ; -1 for each element that equals 4 -- r8: s
+
+    ;calculate output
+    ;qadd8      lr, r8, r7                  ; u = vp8_signed_char_clamp(s + vp8_filter)
+
+    ldr         r8, [sp]                    ; load qs0
+    ldr         r9, [sp, #4]                ; load ps0
+
+    ldr         r10, c0x01010101
+
+    qsub8       r8, r8, r7                  ; u = vp8_signed_char_clamp(qs0 - vp8_filter)
+    qadd8       r9, r9, lr                  ; u = vp8_signed_char_clamp(ps0 + Filter2)
+    ;end of modification for vp8
+
+    eor         r8, r8, r12
+    eor         r9, r9, r12
+
+    mov         lr, #0
+
+    sadd8       r7, r7, r10
+    shadd8      r7, r7, lr
+
+    ldr         r10, [sp, #8]               ; load qs1
+    ldr         r11, [sp, #12]              ; load ps1
+
+    bic         r7, r7, r6                  ; r7: vp8_filter
+
+    qsub8       r10 , r10, r7               ; u = vp8_signed_char_clamp(qs1 - vp8_filter)
+    qadd8       r11, r11, r7                ; u = vp8_signed_char_clamp(ps1 + vp8_filter)
+    eor         r10, r10, r12
+    eor         r11, r11, r12
+
+    sub         src, src, pstep, lsl #2
+
+    ;we can use TRANSPOSE_MATRIX macro to transpose output - input: q1, q0, p0, p1
+    ;output is b0, b1, b2, b3
+    ;b0: 03 02 01 00
+    ;b1: 13 12 11 10
+    ;b2: 23 22 21 20
+    ;b3: 33 32 31 30
+    ;    p1 p0 q0 q1
+    ;   (a3 a2 a1 a0)
+    TRANSPOSE_MATRIX r11, r9, r8, r10, r6, r7, r12, lr
+
+    strh        r6, [src, #-2]              ; store the result
+    mov         r6, r6, lsr #16
+    strh        r6, [src], pstep
+
+    strh        r7, [src, #-2]
+    mov         r7, r7, lsr #16
+    strh        r7, [src], pstep
+
+    strh        r12, [src, #-2]
+    mov         r12, r12, lsr #16
+    strh        r12, [src], pstep
+
+    strh        lr, [src, #-2]
+    mov         lr, lr, lsr #16
+    strh        lr, [src], pstep
+
+|vskip_filter|
+    sub         src, src, #4
+    subs        count, count, #1
+
+    ldrne       r6, [src], pstep            ; load source data
+    ldrne       r7, [src], pstep
+    ldrne       r8, [src], pstep
+    ldrne       lr, [src], pstep
+
+    bne         Vnext8
+
+    add         sp, sp, #16
+
+    ldmia       sp!, {r4 - r11, pc}
+    ENDP        ; |vp8_loop_filter_vertical_edge_armv6|
+
+
+
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+|vp8_mbloop_filter_vertical_edge_armv6| PROC
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+    stmdb       sp!, {r4 - r11, lr}
+
+    sub         src, src, #4                ; move src pointer down by 4
+    ldr         count, [sp, #40]            ; count for 8-in-parallel
+    ldr         r12, [sp, #36]              ; load thresh address
+    pld         [src, #23]                  ; preload for next block
+    sub         sp, sp, #16                 ; create temp buffer
+
+    ldr         r6, [src], pstep            ; load source data
+    ldrb        r4, [r2]                    ; blimit
+    pld         [src, #23]
+    ldr         r7, [src], pstep
+    ldrb        r2, [r3]                    ; limit
+    pld         [src, #23]
+    ldr         r8, [src], pstep
+    orr         r4, r4, r4, lsl #8
+    ldrb        r3, [r12]                   ; thresh
+    orr         r2, r2, r2, lsl #8
+    pld         [src, #23]
+    ldr         lr, [src], pstep
+    mov         count, count, lsl #1        ; 4-in-parallel
+    orr         r4, r4, r4, lsl #16
+    orr         r3, r3, r3, lsl #8
+    orr         r2, r2, r2, lsl #16
+    orr         r3, r3, r3, lsl #16
+
+|MBVnext8|
+    ; vp8_filter_mask() function
+    ; calculate breakout conditions
+    ; transpose the source data for 4-in-parallel operation
+    TRANSPOSE_MATRIX r6, r7, r8, lr, r9, r10, r11, r12
+
+    uqsub8      r7, r9, r10                 ; p3 - p2
+    uqsub8      r8, r10, r9                 ; p2 - p3
+    uqsub8      r9, r10, r11                ; p2 - p1
+    uqsub8      r10, r11, r10               ; p1 - p2
+    orr         r7, r7, r8                  ; abs (p3-p2)
+    orr         r10, r9, r10                ; abs (p2-p1)
+    uqsub8      lr, r7, r2                  ; compare to limit. lr: vp8_filter_mask
+    uqsub8      r10, r10, r2                ; compare to limit
+
+    sub         src, src, pstep, lsl #2     ; move src pointer down by 4 lines
+
+    orr         lr, lr, r10
+
+    uqsub8      r6, r11, r12                ; p1 - p0
+    uqsub8      r7, r12, r11                ; p0 - p1
+    add         src, src, #4                ; move src pointer up by 4
+    orr         r6, r6, r7                  ; abs (p1-p0)
+    str         r11, [sp, #12]              ; save p1
+    uqsub8      r10, r6, r2                 ; compare to limit
+    uqsub8      r11, r6, r3                 ; compare to thresh
+    orr         lr, lr, r10
+
+    ; transpose uses 8 regs(r6 - r12 and lr). Need to save reg value now
+    ; transpose the source data for 4-in-parallel operation
+    ldr         r6, [src], pstep            ; load source data
+    str         r11, [sp]                   ; push r11 to stack
+    ldr         r7, [src], pstep
+    str         r12, [sp, #4]               ; save current reg before load q0 - q3 data
+    ldr         r8, [src], pstep
+    str         lr, [sp, #8]
+    ldr         lr, [src], pstep
+
+
+    TRANSPOSE_MATRIX r6, r7, r8, lr, r9, r10, r11, r12
+
+    ldr         lr, [sp, #8]                ; load back (f)limit accumulator
+
+    uqsub8      r6, r12, r11                ; q3 - q2
+    uqsub8      r7, r11, r12                ; q2 - q3
+    uqsub8      r12, r11, r10               ; q2 - q1
+    uqsub8      r11, r10, r11               ; q1 - q2
+    orr         r6, r6, r7                  ; abs (q3-q2)
+    orr         r7, r12, r11                ; abs (q2-q1)
+    uqsub8      r6, r6, r2                  ; compare to limit
+    uqsub8      r7, r7, r2                  ; compare to limit
+    ldr         r11, [sp, #4]               ; load back p0
+    ldr         r12, [sp, #12]              ; load back p1
+    orr         lr, lr, r6
+    orr         lr, lr, r7
+
+    uqsub8      r6, r11, r9                 ; p0 - q0
+    uqsub8      r7, r9, r11                 ; q0 - p0
+    uqsub8      r8, r12, r10                ; p1 - q1
+    uqsub8      r11, r10, r12               ; q1 - p1
+    orr         r6, r6, r7                  ; abs (p0-q0)
+    ldr         r7, c0x7F7F7F7F
+    orr         r8, r8, r11                 ; abs (p1-q1)
+    uqadd8      r6, r6, r6                  ; abs (p0-q0) * 2
+    and         r8, r7, r8, lsr #1          ; abs (p1-q1) / 2
+    uqsub8      r11, r10, r9                ; q1 - q0
+    uqadd8      r6, r8, r6                  ; abs (p0-q0)*2 + abs (p1-q1)/2
+    uqsub8      r12, r9, r10                ; q0 - q1
+    uqsub8      r6, r6, r4                  ; compare to flimit
+
+    orr         r9, r11, r12                ; abs (q1-q0)
+    uqsub8      r8, r9, r2                  ; compare to limit
+    uqsub8      r10, r9, r3                 ; compare to thresh
+    orr         lr, lr, r6
+    orr         lr, lr, r8
+
+    mvn         r11, #0                     ; r11 == -1
+    mov         r12, #0
+
+    usub8       lr, r12, lr
+    ldr         r9, [sp]                    ; load the compared result
+    sel         lr, r11, r12                ; filter mask: lr
+
+    cmp         lr, #0
+    beq         mbvskip_filter               ; skip filtering
+
+
+
+    ;vp8_hevmask() function
+    ;calculate high edge variance
+
+    sub         src, src, pstep, lsl #2     ; move src pointer down by 4 lines
+
+    orr         r9, r9, r10
+
+    ldrh        r7, [src, #-2]
+    ldrh        r8, [src], pstep
+
+    usub8       r9, r12, r9
+    sel         r6, r12, r11                ; hev mask: r6
+
+
+    ; vp8_mbfilter() function
+    ; p2, q2 are only needed at the end. Don't need to load them in now.
+    ; Transpose needs 8 regs(r6 - r12, and lr). Save r6 and lr first
+    ; load soure data to r6, r11, r12, lr
+    ldrh        r9, [src, #-2]
+    ldrh        r10, [src], pstep
+
+    pkhbt       r12, r7, r8, lsl #16
+
+    ldrh        r7, [src, #-2]
+    ldrh        r8, [src], pstep
+
+    pkhbt       r11, r9, r10, lsl #16
+
+    ldrh        r9, [src, #-2]
+    ldrh        r10, [src], pstep
+
+    str         r6, [sp]                    ; save r6
+    str         lr, [sp, #4]                ; save lr
+
+    pkhbt       r6, r7, r8, lsl #16
+    pkhbt       lr, r9, r10, lsl #16
+
+    ;transpose r12, r11, r6, lr to p1, p0, q0, q1
+    TRANSPOSE_MATRIX r12, r11, r6, lr, r7, r8, r9, r10
+
+    ;load back hev_mask r6 and filter_mask lr
+    ldr         r12, c0x80808080
+    ldr         r6, [sp]
+    ldr         lr, [sp, #4]
+
+    eor         r7, r7, r12                 ; ps1
+    eor         r8, r8, r12                 ; ps0
+    eor         r9, r9, r12                 ; qs0
+    eor         r10, r10, r12               ; qs1
+
+    qsub8       r12, r9, r8                 ; vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+    str         r7, [sp, #12]               ; store ps1 temporarily
+    qsub8       r7, r7, r10                 ; vp8_signed_char_clamp(ps1-qs1)
+    str         r10, [sp, #8]               ; store qs1 temporarily
+    qadd8       r7, r7, r12
+    str         r9, [sp]                    ; store qs0 temporarily
+    qadd8       r7, r7, r12
+    str         r8, [sp, #4]                ; store ps0 temporarily
+    qadd8       r7, r7, r12                 ; vp8_filter: r7
+
+    ldr         r10, c0x03030303            ; r10 = 3 --modified for vp8
+    ldr         r9, c0x04040404
+    ;mvn         r11, #0                     ; r11 == -1
+
+    and         r7, r7, lr                  ; vp8_filter &= mask (lr is free)
+
+    mov         r12, r7                     ; Filter2: r12
+    and         r12, r12, r6                ; Filter2 &= hev
+
+    ;modify code for vp8
+    ;save bottom 3 bits so that we round one side +4 and the other +3
+    qadd8       r8 , r12 , r9               ; Filter1 (r8) = vp8_signed_char_clamp(Filter2+4)
+    qadd8       r12 , r12 , r10             ; Filter2 (r12) = vp8_signed_char_clamp(Filter2+3)
+
+    mov         r10, #0
+    shadd8      r8 , r8 , r10               ; Filter1 >>= 3
+    shadd8      r12 , r12 , r10             ; Filter2 >>= 3
+    shadd8      r8 , r8 , r10
+    shadd8      r12 , r12 , r10
+    shadd8      r8 , r8 , r10               ; r8: Filter1
+    shadd8      r12 , r12 , r10             ; r12: Filter2
+
+    ldr         r9, [sp]                    ; load qs0
+    ldr         r11, [sp, #4]               ; load ps0
+
+    qsub8       r9 , r9, r8                 ; qs0 = vp8_signed_char_clamp(qs0 - Filter1)
+    qadd8       r11, r11, r12               ; ps0 = vp8_signed_char_clamp(ps0 + Filter2)
+
+    ;save bottom 3 bits so that we round one side +4 and the other +3
+    ;and            r8, r12, r10                ; s = Filter2 & 7 (s: r8)
+    ;qadd8      r12 , r12 , r9              ; Filter2 = vp8_signed_char_clamp(Filter2+4)
+    ;mov            r10, #0
+    ;shadd8     r12 , r12 , r10             ; Filter2 >>= 3
+    ;usub8      lr, r8, r9                  ; s = (s==4)*-1
+    ;sel            lr, r11, r10
+    ;shadd8     r12 , r12 , r10
+    ;usub8      r8, r9, r8
+    ;sel            r8, r11, r10
+    ;ldr            r9, [sp]                    ; load qs0
+    ;ldr            r11, [sp, #4]               ; load ps0
+    ;shadd8     r12 , r12 , r10
+    ;and            r8, r8, lr                  ; -1 for each element that equals 4
+    ;qadd8      r10, r8, r12                ; u = vp8_signed_char_clamp(s + Filter2)
+    ;qsub8      r9 , r9, r12                ; qs0 = vp8_signed_char_clamp(qs0 - Filter2)
+    ;qadd8      r11, r11, r10               ; ps0 = vp8_signed_char_clamp(ps0 + u)
+
+    ;end of modification for vp8
+
+    bic         r12, r7, r6                 ;vp8_filter &= ~hev    ( r6 is free)
+    ;mov            r12, r7
+
+    ;roughly 3/7th difference across boundary
+    mov         lr, #0x1b                   ; 27
+    mov         r7, #0x3f                   ; 63
+
+    sxtb16      r6, r12
+    sxtb16      r10, r12, ror #8
+    smlabb      r8, r6, lr, r7
+    smlatb      r6, r6, lr, r7
+    smlabb      r7, r10, lr, r7
+    smultb      r10, r10, lr
+    ssat        r8, #8, r8, asr #7
+    ssat        r6, #8, r6, asr #7
+    add         r10, r10, #63
+    ssat        r7, #8, r7, asr #7
+    ssat        r10, #8, r10, asr #7
+
+    ldr         lr, c0x80808080
+
+    pkhbt       r6, r8, r6, lsl #16
+    pkhbt       r10, r7, r10, lsl #16
+    uxtb16      r6, r6
+    uxtb16      r10, r10
+
+    sub         src, src, pstep, lsl #2     ; move src pointer down by 4 lines
+
+    orr         r10, r6, r10, lsl #8        ; u = vp8_signed_char_clamp((63 + Filter2 * 27)>>7)
+
+    qsub8       r8, r9, r10                 ; s = vp8_signed_char_clamp(qs0 - u)
+    qadd8       r10, r11, r10               ; s = vp8_signed_char_clamp(ps0 + u)
+    eor         r8, r8, lr                  ; *oq0 = s^0x80
+    eor         r10, r10, lr                ; *op0 = s^0x80
+
+    strb        r10, [src, #-1]             ; store op0 result
+    strb        r8, [src], pstep            ; store oq0 result
+    mov         r10, r10, lsr #8
+    mov         r8, r8, lsr #8
+    strb        r10, [src, #-1]
+    strb        r8, [src], pstep
+    mov         r10, r10, lsr #8
+    mov         r8, r8, lsr #8
+    strb        r10, [src, #-1]
+    strb        r8, [src], pstep
+    mov         r10, r10, lsr #8
+    mov         r8, r8, lsr #8
+    strb        r10, [src, #-1]
+    strb        r8, [src], pstep
+
+    ;roughly 2/7th difference across boundary
+    mov         lr, #0x12                   ; 18
+    mov         r7, #0x3f                   ; 63
+
+    sxtb16      r6, r12
+    sxtb16      r10, r12, ror #8
+    smlabb      r8, r6, lr, r7
+    smlatb      r6, r6, lr, r7
+    smlabb      r9, r10, lr, r7
+
+    smlatb      r10, r10, lr, r7
+    ssat        r8, #8, r8, asr #7
+    ssat        r6, #8, r6, asr #7
+    ssat        r9, #8, r9, asr #7
+    ssat        r10, #8, r10, asr #7
+
+    sub         src, src, pstep, lsl #2     ; move src pointer down by 4 lines
+
+    pkhbt       r6, r8, r6, lsl #16
+    pkhbt       r10, r9, r10, lsl #16
+
+    ldr         r9, [sp, #8]                ; load qs1
+    ldr         r11, [sp, #12]              ; load ps1
+    ldr         lr, c0x80808080
+
+    uxtb16      r6, r6
+    uxtb16      r10, r10
+
+    add         src, src, #2
+
+    orr         r10, r6, r10, lsl #8        ; u = vp8_signed_char_clamp((63 + Filter2 * 18)>>7)
+
+    qsub8       r8, r9, r10                 ; s = vp8_signed_char_clamp(qs1 - u)
+    qadd8       r10, r11, r10               ; s = vp8_signed_char_clamp(ps1 + u)
+    eor         r8, r8, lr                  ; *oq1 = s^0x80
+    eor         r10, r10, lr                ; *op1 = s^0x80
+
+    ldrb        r11, [src, #-5]             ; load p2 for 1/7th difference across boundary
+    strb        r10, [src, #-4]             ; store op1
+    strb        r8, [src, #-1]              ; store oq1
+    ldrb        r9, [src], pstep            ; load q2 for 1/7th difference across boundary
+
+    mov         r10, r10, lsr #8
+    mov         r8, r8, lsr #8
+
+    ldrb        r6, [src, #-5]
+    strb        r10, [src, #-4]
+    strb        r8, [src, #-1]
+    ldrb        r7, [src], pstep
+
+    mov         r10, r10, lsr #8
+    mov         r8, r8, lsr #8
+    orr         r11, r11, r6, lsl #8
+    orr         r9, r9, r7, lsl #8
+
+    ldrb        r6, [src, #-5]
+    strb        r10, [src, #-4]
+    strb        r8, [src, #-1]
+    ldrb        r7, [src], pstep
+
+    mov         r10, r10, lsr #8
+    mov         r8, r8, lsr #8
+    orr         r11, r11, r6, lsl #16
+    orr         r9, r9, r7, lsl #16
+
+    ldrb        r6, [src, #-5]
+    strb        r10, [src, #-4]
+    strb        r8, [src, #-1]
+    ldrb        r7, [src], pstep
+    orr         r11, r11, r6, lsl #24
+    orr         r9, r9, r7, lsl #24
+
+    ;roughly 1/7th difference across boundary
+    eor         r9, r9, lr
+    eor         r11, r11, lr
+
+    mov         lr, #0x9                    ; 9
+    mov         r7, #0x3f                   ; 63
+
+    sxtb16      r6, r12
+    sxtb16      r10, r12, ror #8
+    smlabb      r8, r6, lr, r7
+    smlatb      r6, r6, lr, r7
+    smlabb      r12, r10, lr, r7
+    smlatb      r10, r10, lr, r7
+    ssat        r8, #8, r8, asr #7
+    ssat        r6, #8, r6, asr #7
+    ssat        r12, #8, r12, asr #7
+    ssat        r10, #8, r10, asr #7
+
+    sub         src, src, pstep, lsl #2
+
+    pkhbt       r6, r8, r6, lsl #16
+    pkhbt       r10, r12, r10, lsl #16
+
+    uxtb16      r6, r6
+    uxtb16      r10, r10
+
+    ldr         lr, c0x80808080
+
+    orr         r10, r6, r10, lsl #8        ; u = vp8_signed_char_clamp((63 + Filter2 * 9)>>7)
+
+    qadd8       r8, r11, r10                ; s = vp8_signed_char_clamp(ps2 + u)
+    qsub8       r10, r9, r10                ; s = vp8_signed_char_clamp(qs2 - u)
+    eor         r8, r8, lr                  ; *op2 = s^0x80
+    eor         r10, r10, lr                ; *oq2 = s^0x80
+
+    strb        r8, [src, #-5]              ; store *op2
+    strb        r10, [src], pstep           ; store *oq2
+    mov         r8, r8, lsr #8
+    mov         r10, r10, lsr #8
+    strb        r8, [src, #-5]
+    strb        r10, [src], pstep
+    mov         r8, r8, lsr #8
+    mov         r10, r10, lsr #8
+    strb        r8, [src, #-5]
+    strb        r10, [src], pstep
+    mov         r8, r8, lsr #8
+    mov         r10, r10, lsr #8
+    strb        r8, [src, #-5]
+    strb        r10, [src], pstep
+
+    ;adjust src pointer for next loop
+    sub         src, src, #2
+
+|mbvskip_filter|
+    sub         src, src, #4
+    subs        count, count, #1
+
+    pld         [src, #23]                  ; preload for next block
+    ldrne       r6, [src], pstep            ; load source data
+    pld         [src, #23]
+    ldrne       r7, [src], pstep
+    pld         [src, #23]
+    ldrne       r8, [src], pstep
+    pld         [src, #23]
+    ldrne       lr, [src], pstep
+
+    bne         MBVnext8
+
+    add         sp, sp, #16
+
+    ldmia       sp!, {r4 - r11, pc}
+    ENDP        ; |vp8_mbloop_filter_vertical_edge_armv6|
+
+; Constant Pool
+c0x80808080 DCD     0x80808080
+c0x03030303 DCD     0x03030303
+c0x04040404 DCD     0x04040404
+c0x01010101 DCD     0x01010101
+c0x7F7F7F7F DCD     0x7F7F7F7F
+
+    END
diff --git a/vp8/common/arm/armv6/simpleloopfilter_v6.asm b/vp8/common/arm/armv6/simpleloopfilter_v6.asm
new file mode 100644 (file)
index 0000000..5e00cf0
--- /dev/null
@@ -0,0 +1,286 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT |vp8_loop_filter_simple_horizontal_edge_armv6|
+    EXPORT |vp8_loop_filter_simple_vertical_edge_armv6|
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+
+    MACRO
+    TRANSPOSE_MATRIX $a0, $a1, $a2, $a3, $b0, $b1, $b2, $b3
+    ; input: $a0, $a1, $a2, $a3; output: $b0, $b1, $b2, $b3
+    ; a0: 03 02 01 00
+    ; a1: 13 12 11 10
+    ; a2: 23 22 21 20
+    ; a3: 33 32 31 30
+    ;     b3 b2 b1 b0
+
+    uxtb16      $b1, $a1                    ; xx 12 xx 10
+    uxtb16      $b0, $a0                    ; xx 02 xx 00
+    uxtb16      $b3, $a3                    ; xx 32 xx 30
+    uxtb16      $b2, $a2                    ; xx 22 xx 20
+    orr         $b1, $b0, $b1, lsl #8       ; 12 02 10 00
+    orr         $b3, $b2, $b3, lsl #8       ; 32 22 30 20
+
+    uxtb16      $a1, $a1, ror #8            ; xx 13 xx 11
+    uxtb16      $a3, $a3, ror #8            ; xx 33 xx 31
+    uxtb16      $a0, $a0, ror #8            ; xx 03 xx 01
+    uxtb16      $a2, $a2, ror #8            ; xx 23 xx 21
+    orr         $a0, $a0, $a1, lsl #8       ; 13 03 11 01
+    orr         $a2, $a2, $a3, lsl #8       ; 33 23 31 21
+
+    pkhtb       $b2, $b3, $b1, asr #16      ; 32 22 12 02   -- p1
+    pkhbt       $b0, $b1, $b3, lsl #16      ; 30 20 10 00   -- p3
+
+    pkhtb       $b3, $a2, $a0, asr #16      ; 33 23 13 03   -- p0
+    pkhbt       $b1, $a0, $a2, lsl #16      ; 31 21 11 01   -- p2
+    MEND
+
+
+
+src         RN  r0
+pstep       RN  r1
+
+;r0     unsigned char *src_ptr,
+;r1     int src_pixel_step,
+;r2     const char *blimit
+
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+|vp8_loop_filter_simple_horizontal_edge_armv6| PROC
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+    stmdb       sp!, {r4 - r11, lr}
+
+    ldrb        r12, [r2]                   ; blimit
+    ldr         r3, [src, -pstep, lsl #1]   ; p1
+    ldr         r4, [src, -pstep]           ; p0
+    ldr         r5, [src]                   ; q0
+    ldr         r6, [src, pstep]            ; q1
+    orr         r12, r12, r12, lsl #8       ; blimit
+    ldr         r2, c0x80808080
+    orr         r12, r12, r12, lsl #16      ; blimit
+    mov         r9, #4                      ; double the count. we're doing 4 at a time
+    mov         lr, #0                      ; need 0 in a couple places
+
+|simple_hnext8|
+    ; vp8_simple_filter_mask()
+
+    uqsub8      r7, r3, r6                  ; p1 - q1
+    uqsub8      r8, r6, r3                  ; q1 - p1
+    uqsub8      r10, r4, r5                 ; p0 - q0
+    uqsub8      r11, r5, r4                 ; q0 - p0
+    orr         r8, r8, r7                  ; abs(p1 - q1)
+    orr         r10, r10, r11               ; abs(p0 - q0)
+    uqadd8      r10, r10, r10               ; abs(p0 - q0) * 2
+    uhadd8      r8, r8, lr                  ; abs(p1 - q2) >> 1
+    uqadd8      r10, r10, r8                ; abs(p0 - q0)*2 + abs(p1 - q1)/2
+    mvn         r8, #0
+    usub8       r10, r12, r10               ; compare to flimit. usub8 sets GE flags
+    sel         r10, r8, lr                 ; filter mask: F or 0
+    cmp         r10, #0
+    beq         simple_hskip_filter         ; skip filtering if all masks are 0x00
+
+    ;vp8_simple_filter()
+
+    eor         r3, r3, r2                  ; p1 offset to convert to a signed value
+    eor         r6, r6, r2                  ; q1 offset to convert to a signed value
+    eor         r4, r4, r2                  ; p0 offset to convert to a signed value
+    eor         r5, r5, r2                  ; q0 offset to convert to a signed value
+
+    qsub8       r3, r3, r6                  ; vp8_filter = p1 - q1
+    qsub8       r6, r5, r4                  ; q0 - p0
+    qadd8       r3, r3, r6                  ; += q0 - p0
+    ldr         r7, c0x04040404
+    qadd8       r3, r3, r6                  ; += q0 - p0
+    ldr         r8, c0x03030303
+    qadd8       r3, r3, r6                  ; vp8_filter = p1-q1 + 3*(q0-p0))
+    ;STALL
+    and         r3, r3, r10                 ; vp8_filter &= mask
+
+    qadd8       r7 , r3 , r7                ; Filter1 = vp8_filter + 4
+    qadd8       r8 , r3 , r8                ; Filter2 = vp8_filter + 3
+
+    shadd8      r7 , r7 , lr
+    shadd8      r8 , r8 , lr
+    shadd8      r7 , r7 , lr
+    shadd8      r8 , r8 , lr
+    shadd8      r7 , r7 , lr                ; Filter1 >>= 3
+    shadd8      r8 , r8 , lr                ; Filter2 >>= 3
+
+    qsub8       r5 ,r5, r7                  ; u = q0 - Filter1
+    qadd8       r4, r4, r8                  ; u = p0 + Filter2
+    eor         r5, r5, r2                  ; *oq0 = u^0x80
+    str         r5, [src]                   ; store oq0 result
+    eor         r4, r4, r2                  ; *op0 = u^0x80
+    str         r4, [src, -pstep]           ; store op0 result
+
+|simple_hskip_filter|
+    subs        r9, r9, #1
+    addne       src, src, #4                ; next row
+
+    ldrne       r3, [src, -pstep, lsl #1]   ; p1
+    ldrne       r4, [src, -pstep]           ; p0
+    ldrne       r5, [src]                   ; q0
+    ldrne       r6, [src, pstep]            ; q1
+
+    bne         simple_hnext8
+
+    ldmia       sp!, {r4 - r11, pc}
+    ENDP        ; |vp8_loop_filter_simple_horizontal_edge_armv6|
+
+
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+|vp8_loop_filter_simple_vertical_edge_armv6| PROC
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+    stmdb       sp!, {r4 - r11, lr}
+
+    ldrb        r12, [r2]                   ; r12: blimit
+    ldr         r2, c0x80808080
+    orr         r12, r12, r12, lsl #8
+
+    ; load soure data to r7, r8, r9, r10
+    ldrh        r3, [src, #-2]
+    pld         [src, #23]                  ; preload for next block
+    ldrh        r4, [src], pstep
+    orr         r12, r12, r12, lsl #16
+
+    ldrh        r5, [src, #-2]
+    pld         [src, #23]
+    ldrh        r6, [src], pstep
+
+    pkhbt       r7, r3, r4, lsl #16
+
+    ldrh        r3, [src, #-2]
+    pld         [src, #23]
+    ldrh        r4, [src], pstep
+
+    pkhbt       r8, r5, r6, lsl #16
+
+    ldrh        r5, [src, #-2]
+    pld         [src, #23]
+    ldrh        r6, [src], pstep
+    mov         r11, #4                     ; double the count. we're doing 4 at a time
+
+|simple_vnext8|
+    ; vp8_simple_filter_mask() function
+    pkhbt       r9, r3, r4, lsl #16
+    pkhbt       r10, r5, r6, lsl #16
+
+    ;transpose r7, r8, r9, r10 to r3, r4, r5, r6
+    TRANSPOSE_MATRIX r7, r8, r9, r10, r3, r4, r5, r6
+
+    uqsub8      r7, r3, r6                  ; p1 - q1
+    uqsub8      r8, r6, r3                  ; q1 - p1
+    uqsub8      r9, r4, r5                  ; p0 - q0
+    uqsub8      r10, r5, r4                 ; q0 - p0
+    orr         r7, r7, r8                  ; abs(p1 - q1)
+    orr         r9, r9, r10                 ; abs(p0 - q0)
+    mov         r8, #0
+    uqadd8      r9, r9, r9                  ; abs(p0 - q0) * 2
+    uhadd8      r7, r7, r8                  ; abs(p1 - q1) / 2
+    uqadd8      r7, r7, r9                  ; abs(p0 - q0)*2 + abs(p1 - q1)/2
+    mvn         r10, #0                     ; r10 == -1
+
+    usub8       r7, r12, r7                 ; compare to flimit
+    sel         lr, r10, r8                 ; filter mask
+
+    cmp         lr, #0
+    beq         simple_vskip_filter         ; skip filtering
+
+    ;vp8_simple_filter() function
+    eor         r3, r3, r2                  ; p1 offset to convert to a signed value
+    eor         r6, r6, r2                  ; q1 offset to convert to a signed value
+    eor         r4, r4, r2                  ; p0 offset to convert to a signed value
+    eor         r5, r5, r2                  ; q0 offset to convert to a signed value
+
+    qsub8       r3, r3, r6                  ; vp8_filter = p1 - q1
+    qsub8       r6, r5, r4                  ; q0 - p0
+
+    qadd8       r3, r3, r6                  ; vp8_filter += q0 - p0
+    ldr         r9, c0x03030303             ; r9 = 3
+
+    qadd8       r3, r3, r6                  ; vp8_filter += q0 - p0
+    ldr         r7, c0x04040404
+
+    qadd8       r3, r3, r6                  ; vp8_filter = p1-q1 + 3*(q0-p0))
+    ;STALL
+    and         r3, r3, lr                  ; vp8_filter &= mask
+
+    qadd8       r9 , r3 , r9                ; Filter2 = vp8_filter + 3
+    qadd8       r3 , r3 , r7                ; Filter1 = vp8_filter + 4
+
+    shadd8      r9 , r9 , r8
+    shadd8      r3 , r3 , r8
+    shadd8      r9 , r9 , r8
+    shadd8      r3 , r3 , r8
+    shadd8      r9 , r9 , r8                ; Filter2 >>= 3
+    shadd8      r3 , r3 , r8                ; Filter1 >>= 3
+
+    ;calculate output
+    sub         src, src, pstep, lsl #2
+
+    qadd8       r4, r4, r9                  ; u = p0 + Filter2
+    qsub8       r5, r5, r3                  ; u = q0 - Filter1
+    eor         r4, r4, r2                  ; *op0 = u^0x80
+    eor         r5, r5, r2                  ; *oq0 = u^0x80
+
+    strb        r4, [src, #-1]              ; store the result
+    mov         r4, r4, lsr #8
+    strb        r5, [src], pstep
+    mov         r5, r5, lsr #8
+
+    strb        r4, [src, #-1]
+    mov         r4, r4, lsr #8
+    strb        r5, [src], pstep
+    mov         r5, r5, lsr #8
+
+    strb        r4, [src, #-1]
+    mov         r4, r4, lsr #8
+    strb        r5, [src], pstep
+    mov         r5, r5, lsr #8
+
+    strb        r4, [src, #-1]
+    strb        r5, [src], pstep
+
+|simple_vskip_filter|
+    subs        r11, r11, #1
+
+    ; load soure data to r7, r8, r9, r10
+    ldrneh      r3, [src, #-2]
+    pld         [src, #23]                  ; preload for next block
+    ldrneh      r4, [src], pstep
+
+    ldrneh      r5, [src, #-2]
+    pld         [src, #23]
+    ldrneh      r6, [src], pstep
+
+    pkhbt       r7, r3, r4, lsl #16
+
+    ldrneh      r3, [src, #-2]
+    pld         [src, #23]
+    ldrneh      r4, [src], pstep
+
+    pkhbt       r8, r5, r6, lsl #16
+
+    ldrneh      r5, [src, #-2]
+    pld         [src, #23]
+    ldrneh      r6, [src], pstep
+
+    bne         simple_vnext8
+
+    ldmia       sp!, {r4 - r11, pc}
+    ENDP        ; |vp8_loop_filter_simple_vertical_edge_armv6|
+
+; Constant Pool
+c0x80808080 DCD     0x80808080
+c0x03030303 DCD     0x03030303
+c0x04040404 DCD     0x04040404
+
+    END
diff --git a/vp8/common/arm/armv6/sixtappredict8x4_v6.asm b/vp8/common/arm/armv6/sixtappredict8x4_v6.asm
new file mode 100644 (file)
index 0000000..e81aef5
--- /dev/null
@@ -0,0 +1,273 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_sixtap_predict8x4_armv6|
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+;-------------------------------------
+; r0    unsigned char *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; stack unsigned char *dst_ptr,
+; stack int  dst_pitch
+;-------------------------------------
+;note: In first pass, store the result in transpose(8linesx9columns) on stack. Temporary stack size is 184.
+;Line width is 20 that is 9 short data plus 2 to make it 4bytes aligned. In second pass, load data from stack,
+;and the result is stored in transpose.
+|vp8_sixtap_predict8x4_armv6| PROC
+    stmdb       sp!, {r4 - r11, lr}
+    str         r3, [sp, #-184]!            ;reserve space on stack for temporary storage, store yoffset
+
+    cmp         r2, #0                      ;skip first_pass filter if xoffset=0
+    add         lr, sp, #4                  ;point to temporary buffer
+    beq         skip_firstpass_filter
+
+;first-pass filter
+    adr         r12, filter8_coeff
+    sub         r0, r0, r1, lsl #1
+
+    add         r3, r1, #10                 ; preload next low
+    pld         [r0, r3]
+
+    add         r2, r12, r2, lsl #4         ;calculate filter location
+    add         r0, r0, #3                  ;adjust src only for loading convinience
+
+    ldr         r3, [r2]                    ; load up packed filter coefficients
+    ldr         r4, [r2, #4]
+    ldr         r5, [r2, #8]
+
+    mov         r2, #0x90000                ; height=9 is top part of counter
+
+    sub         r1, r1, #8
+
+|first_pass_hloop_v6|
+    ldrb        r6, [r0, #-5]               ; load source data
+    ldrb        r7, [r0, #-4]
+    ldrb        r8, [r0, #-3]
+    ldrb        r9, [r0, #-2]
+    ldrb        r10, [r0, #-1]
+
+    orr         r2, r2, #0x4                ; construct loop counter. width=8=4x2
+
+    pkhbt       r6, r6, r7, lsl #16         ; r7 | r6
+    pkhbt       r7, r7, r8, lsl #16         ; r8 | r7
+
+    pkhbt       r8, r8, r9, lsl #16         ; r9 | r8
+    pkhbt       r9, r9, r10, lsl #16        ; r10 | r9
+
+|first_pass_wloop_v6|
+    smuad       r11, r6, r3                 ; vp8_filter[0], vp8_filter[1]
+    smuad       r12, r7, r3
+
+    ldrb        r6, [r0], #1
+
+    smlad       r11, r8, r4, r11            ; vp8_filter[2], vp8_filter[3]
+    ldrb        r7, [r0], #1
+    smlad       r12, r9, r4, r12
+
+    pkhbt       r10, r10, r6, lsl #16       ; r10 | r9
+    pkhbt       r6, r6, r7, lsl #16         ; r11 | r10
+    smlad       r11, r10, r5, r11           ; vp8_filter[4], vp8_filter[5]
+    smlad       r12, r6, r5, r12
+
+    sub         r2, r2, #1
+
+    add         r11, r11, #0x40             ; round_shift_and_clamp
+    tst         r2, #0xff                   ; test loop counter
+    usat        r11, #8, r11, asr #7
+    add         r12, r12, #0x40
+    strh        r11, [lr], #20              ; result is transposed and stored, which
+    usat        r12, #8, r12, asr #7
+
+    strh        r12, [lr], #20
+
+    movne       r11, r6
+    movne       r12, r7
+
+    movne       r6, r8
+    movne       r7, r9
+    movne       r8, r10
+    movne       r9, r11
+    movne       r10, r12
+
+    bne         first_pass_wloop_v6
+
+    ;;add       r9, ppl, #30                ; attempt to load 2 adjacent cache lines
+    ;;IF ARCHITECTURE=6
+    ;pld        [src, ppl]
+    ;;pld       [src, r9]
+    ;;ENDIF
+
+    subs        r2, r2, #0x10000
+
+    sub         lr, lr, #158
+
+    add         r0, r0, r1                  ; move to next input line
+
+    add         r11, r1, #18                ; preload next low. adding back block width(=8), which is subtracted earlier
+    pld         [r0, r11]
+
+    bne         first_pass_hloop_v6
+
+;second pass filter
+secondpass_filter
+    ldr         r3, [sp], #4                ; load back yoffset
+    ldr         r0, [sp, #216]              ; load dst address from stack 180+36
+    ldr         r1, [sp, #220]              ; load dst stride from stack 180+40
+
+    cmp         r3, #0
+    beq         skip_secondpass_filter
+
+    adr         r12, filter8_coeff
+    add         lr, r12, r3, lsl #4         ;calculate filter location
+
+    mov         r2, #0x00080000
+
+    ldr         r3, [lr]                    ; load up packed filter coefficients
+    ldr         r4, [lr, #4]
+    ldr         r5, [lr, #8]
+
+    pkhbt       r12, r4, r3                 ; pack the filter differently
+    pkhbt       r11, r5, r4
+
+second_pass_hloop_v6
+    ldr         r6, [sp]                    ; load the data
+    ldr         r7, [sp, #4]
+
+    orr         r2, r2, #2                  ; loop counter
+
+second_pass_wloop_v6
+    smuad       lr, r3, r6                  ; apply filter
+    smulbt      r10, r3, r6
+
+    ldr         r8, [sp, #8]
+
+    smlad       lr, r4, r7, lr
+    smladx      r10, r12, r7, r10
+
+    ldrh        r9, [sp, #12]
+
+    smlad       lr, r5, r8, lr
+    smladx      r10, r11, r8, r10
+
+    add         sp, sp, #4
+    smlatb      r10, r5, r9, r10
+
+    sub         r2, r2, #1
+
+    add         lr, lr, #0x40               ; round_shift_and_clamp
+    tst         r2, #0xff
+    usat        lr, #8, lr, asr #7
+    add         r10, r10, #0x40
+    strb        lr, [r0], r1                ; the result is transposed back and stored
+    usat        r10, #8, r10, asr #7
+
+    strb        r10, [r0],r1
+
+    movne       r6, r7
+    movne       r7, r8
+
+    bne         second_pass_wloop_v6
+
+    subs        r2, r2, #0x10000
+    add         sp, sp, #12                 ; updata src for next loop (20-8)
+    sub         r0, r0, r1, lsl #2
+    add         r0, r0, #1
+
+    bne         second_pass_hloop_v6
+
+    add         sp, sp, #20
+    ldmia       sp!, {r4 - r11, pc}
+
+;--------------------
+skip_firstpass_filter
+    sub         r0, r0, r1, lsl #1
+    sub         r1, r1, #8
+    mov         r2, #9
+
+skip_firstpass_hloop
+    ldrb        r4, [r0], #1                ; load data
+    subs        r2, r2, #1
+    ldrb        r5, [r0], #1
+    strh        r4, [lr], #20               ; store it to immediate buffer
+    ldrb        r6, [r0], #1                ; load data
+    strh        r5, [lr], #20
+    ldrb        r7, [r0], #1
+    strh        r6, [lr], #20
+    ldrb        r8, [r0], #1
+    strh        r7, [lr], #20
+    ldrb        r9, [r0], #1
+    strh        r8, [lr], #20
+    ldrb        r10, [r0], #1
+    strh        r9, [lr], #20
+    ldrb        r11, [r0], #1
+    strh        r10, [lr], #20
+    add         r0, r0, r1                  ; move to next input line
+    strh        r11, [lr], #20
+
+    sub         lr, lr, #158                ; move over to next column
+    bne         skip_firstpass_hloop
+
+    b           secondpass_filter
+
+;--------------------
+skip_secondpass_filter
+    mov         r2, #8
+    add         sp, sp, #4                  ;start from src[0] instead of src[-2]
+
+skip_secondpass_hloop
+    ldr         r6, [sp], #4
+    subs        r2, r2, #1
+    ldr         r8, [sp], #4
+
+    mov         r7, r6, lsr #16             ; unpack
+    strb        r6, [r0], r1
+    mov         r9, r8, lsr #16
+    strb        r7, [r0], r1
+    add         sp, sp, #12                 ; 20-8
+    strb        r8, [r0], r1
+    strb        r9, [r0], r1
+
+    sub         r0, r0, r1, lsl #2
+    add         r0, r0, #1
+
+    bne         skip_secondpass_hloop
+
+    add         sp, sp, #16                 ; 180 - (160 +4)
+
+    ldmia       sp!, {r4 - r11, pc}
+
+    ENDP
+
+;-----------------
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+filter8_coeff
+    DCD     0x00000000,     0x00000080,     0x00000000,     0x00000000
+    DCD     0xfffa0000,     0x000c007b,     0x0000ffff,     0x00000000
+    DCD     0xfff50002,     0x0024006c,     0x0001fff8,     0x00000000
+    DCD     0xfff70000,     0x0032005d,     0x0000fffa,     0x00000000
+    DCD     0xfff00003,     0x004d004d,     0x0003fff0,     0x00000000
+    DCD     0xfffa0000,     0x005d0032,     0x0000fff7,     0x00000000
+    DCD     0xfff80001,     0x006c0024,     0x0002fff5,     0x00000000
+    DCD     0xffff0000,     0x007b000c,     0x0000fffa,     0x00000000
+
+    ;DCD        0,  0,  128,    0,   0,  0
+    ;DCD        0, -6,  123,   12,  -1,  0
+    ;DCD        2, -11, 108,   36,  -8,  1
+    ;DCD        0, -9,   93,   50,  -6,  0
+    ;DCD        3, -16,  77,   77, -16,  3
+    ;DCD        0, -6,   50,   93,  -9,  0
+    ;DCD        1, -8,   36,  108, -11,  2
+    ;DCD        0, -1,   12,  123,  -6,  0
+
+    END
diff --git a/vp8/common/arm/armv6/vp8_sad16x16_armv6.asm b/vp8/common/arm/armv6/vp8_sad16x16_armv6.asm
new file mode 100644 (file)
index 0000000..1b4f5cf
--- /dev/null
@@ -0,0 +1,96 @@
+;
+;  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_sad16x16_armv6|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    const unsigned char *src_ptr
+; r1    int  src_stride
+; r2    const unsigned char *ref_ptr
+; r3    int  ref_stride
+; stack max_sad (not used)
+|vp8_sad16x16_armv6| PROC
+    stmfd   sp!, {r4-r12, lr}
+
+    pld     [r0, r1, lsl #0]
+    pld     [r2, r3, lsl #0]
+    pld     [r0, r1, lsl #1]
+    pld     [r2, r3, lsl #1]
+
+    mov     r4, #0              ; sad = 0;
+    mov     r5, #8              ; loop count
+
+loop
+    ; 1st row
+    ldr     r6, [r0, #0x0]      ; load 4 src pixels (1A)
+    ldr     r8, [r2, #0x0]      ; load 4 ref pixels (1A)
+    ldr     r7, [r0, #0x4]      ; load 4 src pixels (1A)
+    ldr     r9, [r2, #0x4]      ; load 4 ref pixels (1A)
+    ldr     r10, [r0, #0x8]     ; load 4 src pixels (1B)
+    ldr     r11, [r0, #0xC]     ; load 4 src pixels (1B)
+
+    usada8  r4, r8, r6, r4      ; calculate sad for 4 pixels
+    usad8   r8, r7, r9          ; calculate sad for 4 pixels
+
+    ldr     r12, [r2, #0x8]     ; load 4 ref pixels (1B)
+    ldr     lr, [r2, #0xC]      ; load 4 ref pixels (1B)
+
+    add     r0, r0, r1          ; set src pointer to next row
+    add     r2, r2, r3          ; set dst pointer to next row
+
+    pld     [r0, r1, lsl #1]
+    pld     [r2, r3, lsl #1]
+
+    usada8  r4, r10, r12, r4    ; calculate sad for 4 pixels
+    usada8  r8, r11, lr, r8     ; calculate sad for 4 pixels
+
+    ldr     r6, [r0, #0x0]      ; load 4 src pixels (2A)
+    ldr     r7, [r0, #0x4]      ; load 4 src pixels (2A)
+    add     r4, r4, r8          ; add partial sad values
+
+    ; 2nd row
+    ldr     r8, [r2, #0x0]      ; load 4 ref pixels (2A)
+    ldr     r9, [r2, #0x4]      ; load 4 ref pixels (2A)
+    ldr     r10, [r0, #0x8]     ; load 4 src pixels (2B)
+    ldr     r11, [r0, #0xC]     ; load 4 src pixels (2B)
+
+    usada8  r4, r6, r8, r4      ; calculate sad for 4 pixels
+    usad8   r8, r7, r9          ; calculate sad for 4 pixels
+
+    ldr     r12, [r2, #0x8]     ; load 4 ref pixels (2B)
+    ldr     lr, [r2, #0xC]      ; load 4 ref pixels (2B)
+
+    add     r0, r0, r1          ; set src pointer to next row
+    add     r2, r2, r3          ; set dst pointer to next row
+
+    usada8  r4, r10, r12, r4    ; calculate sad for 4 pixels
+    usada8  r8, r11, lr, r8     ; calculate sad for 4 pixels
+
+    pld     [r0, r1, lsl #1]
+    pld     [r2, r3, lsl #1]
+
+    subs    r5, r5, #1          ; decrement loop counter
+    add     r4, r4, r8          ; add partial sad values
+
+    bne     loop
+
+    mov     r0, r4              ; return sad
+    ldmfd   sp!, {r4-r12, pc}
+
+    ENDP
+
+    END
+
diff --git a/vp8/common/arm/armv6/vp8_variance16x16_armv6.asm b/vp8/common/arm/armv6/vp8_variance16x16_armv6.asm
new file mode 100644 (file)
index 0000000..dc84c30
--- /dev/null
@@ -0,0 +1,154 @@
+;
+;  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_variance16x16_armv6|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    unsigned char *src_ptr
+; r1    int source_stride
+; r2    unsigned char *ref_ptr
+; r3    int  recon_stride
+; stack unsigned int *sse
+|vp8_variance16x16_armv6| PROC
+
+    stmfd   sp!, {r4-r12, lr}
+
+    pld     [r0, r1, lsl #0]
+    pld     [r2, r3, lsl #0]
+
+    mov     r8, #0              ; initialize sum = 0
+    mov     r11, #0             ; initialize sse = 0
+    mov     r12, #16            ; set loop counter to 16 (=block height)
+
+loop
+    ; 1st 4 pixels
+    ldr     r4, [r0, #0]        ; load 4 src pixels
+    ldr     r5, [r2, #0]        ; load 4 ref pixels
+
+    mov     lr, #0              ; constant zero
+
+    usub8   r6, r4, r5          ; calculate difference
+    pld     [r0, r1, lsl #1]
+    sel     r7, r6, lr          ; select bytes with positive difference
+    usub8   r9, r5, r4          ; calculate difference with reversed operands
+    pld     [r2, r3, lsl #1]
+    sel     r6, r9, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r4, r7, lr          ; calculate sum of positive differences
+    usad8   r5, r6, lr          ; calculate sum of negative differences
+    orr     r6, r6, r7          ; differences of all 4 pixels
+    ; calculate total sum
+    adds    r8, r8, r4          ; add positive differences to sum
+    subs    r8, r8, r5          ; substract negative differences from sum
+
+    ; calculate sse
+    uxtb16  r5, r6              ; byte (two pixels) to halfwords
+    uxtb16  r10, r6, ror #8     ; another two pixels to halfwords
+    smlad   r11, r5, r5, r11    ; dual signed multiply, add and accumulate (1)
+
+    ; 2nd 4 pixels
+    ldr     r4, [r0, #4]        ; load 4 src pixels
+    ldr     r5, [r2, #4]        ; load 4 ref pixels
+    smlad   r11, r10, r10, r11  ; dual signed multiply, add and accumulate (2)
+
+    usub8   r6, r4, r5          ; calculate difference
+    sel     r7, r6, lr          ; select bytes with positive difference
+    usub8   r9, r5, r4          ; calculate difference with reversed operands
+    sel     r6, r9, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r4, r7, lr          ; calculate sum of positive differences
+    usad8   r5, r6, lr          ; calculate sum of negative differences
+    orr     r6, r6, r7          ; differences of all 4 pixels
+
+    ; calculate total sum
+    add     r8, r8, r4          ; add positive differences to sum
+    sub     r8, r8, r5          ; substract negative differences from sum
+
+    ; calculate sse
+    uxtb16  r5, r6              ; byte (two pixels) to halfwords
+    uxtb16  r10, r6, ror #8     ; another two pixels to halfwords
+    smlad   r11, r5, r5, r11    ; dual signed multiply, add and accumulate (1)
+
+    ; 3rd 4 pixels
+    ldr     r4, [r0, #8]        ; load 4 src pixels
+    ldr     r5, [r2, #8]        ; load 4 ref pixels
+    smlad   r11, r10, r10, r11  ; dual signed multiply, add and accumulate (2)
+
+    usub8   r6, r4, r5          ; calculate difference
+    sel     r7, r6, lr          ; select bytes with positive difference
+    usub8   r9, r5, r4          ; calculate difference with reversed operands
+    sel     r6, r9, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r4, r7, lr          ; calculate sum of positive differences
+    usad8   r5, r6, lr          ; calculate sum of negative differences
+    orr     r6, r6, r7          ; differences of all 4 pixels
+
+    ; calculate total sum
+    add     r8, r8, r4          ; add positive differences to sum
+    sub     r8, r8, r5          ; substract negative differences from sum
+
+    ; calculate sse
+    uxtb16  r5, r6              ; byte (two pixels) to halfwords
+    uxtb16  r10, r6, ror #8     ; another two pixels to halfwords
+    smlad   r11, r5, r5, r11    ; dual signed multiply, add and accumulate (1)
+
+    ; 4th 4 pixels
+    ldr     r4, [r0, #12]       ; load 4 src pixels
+    ldr     r5, [r2, #12]       ; load 4 ref pixels
+    smlad   r11, r10, r10, r11  ; dual signed multiply, add and accumulate (2)
+
+    usub8   r6, r4, r5          ; calculate difference
+    add     r0, r0, r1          ; set src_ptr to next row
+    sel     r7, r6, lr          ; select bytes with positive difference
+    usub8   r9, r5, r4          ; calculate difference with reversed operands
+    add     r2, r2, r3          ; set dst_ptr to next row
+    sel     r6, r9, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r4, r7, lr          ; calculate sum of positive differences
+    usad8   r5, r6, lr          ; calculate sum of negative differences
+    orr     r6, r6, r7          ; differences of all 4 pixels
+
+    ; calculate total sum
+    add     r8, r8, r4          ; add positive differences to sum
+    sub     r8, r8, r5          ; substract negative differences from sum
+
+    ; calculate sse
+    uxtb16  r5, r6              ; byte (two pixels) to halfwords
+    uxtb16  r10, r6, ror #8     ; another two pixels to halfwords
+    smlad   r11, r5, r5, r11    ; dual signed multiply, add and accumulate (1)
+    smlad   r11, r10, r10, r11  ; dual signed multiply, add and accumulate (2)
+
+
+    subs    r12, r12, #1
+
+    bne     loop
+
+    ; return stuff
+    ldr     r6, [sp, #40]       ; get address of sse
+    mul     r0, r8, r8          ; sum * sum
+    str     r11, [r6]           ; store sse
+    sub     r0, r11, r0, lsr #8 ; return (sse - ((sum * sum) >> 8))
+
+    ldmfd   sp!, {r4-r12, pc}
+
+    ENDP
+
+    END
+
diff --git a/vp8/common/arm/armv6/vp8_variance8x8_armv6.asm b/vp8/common/arm/armv6/vp8_variance8x8_armv6.asm
new file mode 100644 (file)
index 0000000..adc353d
--- /dev/null
@@ -0,0 +1,101 @@
+;
+;  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_variance8x8_armv6|
+
+    ARM
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    unsigned char *src_ptr
+; r1    int source_stride
+; r2    unsigned char *ref_ptr
+; r3    int  recon_stride
+; stack unsigned int *sse
+|vp8_variance8x8_armv6| PROC
+
+    push    {r4-r10, lr}
+
+    pld     [r0, r1, lsl #0]
+    pld     [r2, r3, lsl #0]
+
+    mov     r12, #8             ; set loop counter to 8 (=block height)
+    mov     r4, #0              ; initialize sum = 0
+    mov     r5, #0              ; initialize sse = 0
+
+loop
+    ; 1st 4 pixels
+    ldr     r6, [r0, #0x0]      ; load 4 src pixels
+    ldr     r7, [r2, #0x0]      ; load 4 ref pixels
+
+    mov     lr, #0              ; constant zero
+
+    usub8   r8, r6, r7          ; calculate difference
+    pld     [r0, r1, lsl #1]
+    sel     r10, r8, lr         ; select bytes with positive difference
+    usub8   r9, r7, r6          ; calculate difference with reversed operands
+    pld     [r2, r3, lsl #1]
+    sel     r8, r9, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r6, r10, lr         ; calculate sum of positive differences
+    usad8   r7, r8, lr          ; calculate sum of negative differences
+    orr     r8, r8, r10         ; differences of all 4 pixels
+    ; calculate total sum
+    add    r4, r4, r6           ; add positive differences to sum
+    sub    r4, r4, r7           ; substract negative differences from sum
+
+    ; calculate sse
+    uxtb16  r7, r8              ; byte (two pixels) to halfwords
+    uxtb16  r10, r8, ror #8     ; another two pixels to halfwords
+    smlad   r5, r7, r7, r5      ; dual signed multiply, add and accumulate (1)
+
+    ; 2nd 4 pixels
+    ldr     r6, [r0, #0x4]      ; load 4 src pixels
+    ldr     r7, [r2, #0x4]      ; load 4 ref pixels
+    smlad   r5, r10, r10, r5    ; dual signed multiply, add and accumulate (2)
+
+    usub8   r8, r6, r7          ; calculate difference
+    add     r0, r0, r1          ; set src_ptr to next row
+    sel     r10, r8, lr         ; select bytes with positive difference
+    usub8   r9, r7, r6          ; calculate difference with reversed operands
+    add     r2, r2, r3          ; set dst_ptr to next row
+    sel     r8, r9, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r6, r10, lr         ; calculate sum of positive differences
+    usad8   r7, r8, lr          ; calculate sum of negative differences
+    orr     r8, r8, r10         ; differences of all 4 pixels
+
+    ; calculate total sum
+    add     r4, r4, r6          ; add positive differences to sum
+    sub     r4, r4, r7          ; substract negative differences from sum
+
+    ; calculate sse
+    uxtb16  r7, r8              ; byte (two pixels) to halfwords
+    uxtb16  r10, r8, ror #8     ; another two pixels to halfwords
+    smlad   r5, r7, r7, r5      ; dual signed multiply, add and accumulate (1)
+    subs    r12, r12, #1        ; next row
+    smlad   r5, r10, r10, r5    ; dual signed multiply, add and accumulate (2)
+
+    bne     loop
+
+    ; return stuff
+    ldr     r8, [sp, #32]       ; get address of sse
+    mul     r1, r4, r4          ; sum * sum
+    str     r5, [r8]            ; store sse
+    sub     r0, r5, r1, ASR #6  ; return (sse - ((sum * sum) >> 6))
+
+    pop     {r4-r10, pc}
+
+    ENDP
+
+    END
diff --git a/vp8/common/arm/armv6/vp8_variance_halfpixvar16x16_h_armv6.asm b/vp8/common/arm/armv6/vp8_variance_halfpixvar16x16_h_armv6.asm
new file mode 100644 (file)
index 0000000..dd2ce68
--- /dev/null
@@ -0,0 +1,182 @@
+;
+;  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_variance_halfpixvar16x16_h_armv6|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    unsigned char *src_ptr
+; r1    int source_stride
+; r2    unsigned char *ref_ptr
+; r3    int  recon_stride
+; stack unsigned int *sse
+|vp8_variance_halfpixvar16x16_h_armv6| PROC
+
+    stmfd   sp!, {r4-r12, lr}
+
+    pld     [r0, r1, lsl #0]
+    pld     [r2, r3, lsl #0]
+
+    mov     r8, #0              ; initialize sum = 0
+    ldr     r10, c80808080
+    mov     r11, #0             ; initialize sse = 0
+    mov     r12, #16            ; set loop counter to 16 (=block height)
+    mov     lr, #0              ; constant zero
+loop
+    ; 1st 4 pixels
+    ldr     r4, [r0, #0]        ; load 4 src pixels
+    ldr     r6, [r0, #1]        ; load 4 src pixels with 1 byte offset
+    ldr     r5, [r2, #0]        ; load 4 ref pixels
+
+    ; bilinear interpolation
+    mvn     r6, r6
+    uhsub8  r4, r4, r6
+    eor     r4, r4, r10
+
+    usub8   r6, r4, r5          ; calculate difference
+    pld     [r0, r1, lsl #1]
+    sel     r7, r6, lr          ; select bytes with positive difference
+    usub8   r6, r5, r4          ; calculate difference with reversed operands
+    pld     [r2, r3, lsl #1]
+    sel     r6, r6, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r4, r7, lr          ; calculate sum of positive differences
+    usad8   r5, r6, lr          ; calculate sum of negative differences
+    orr     r6, r6, r7          ; differences of all 4 pixels
+    ; calculate total sum
+    adds    r8, r8, r4          ; add positive differences to sum
+    subs    r8, r8, r5          ; substract negative differences from sum
+
+    ; calculate sse
+    uxtb16  r5, r6              ; byte (two pixels) to halfwords
+    uxtb16  r7, r6, ror #8      ; another two pixels to halfwords
+    smlad   r11, r5, r5, r11    ; dual signed multiply, add and accumulate (1)
+
+    ; 2nd 4 pixels
+    ldr     r4, [r0, #4]        ; load 4 src pixels
+    ldr     r6, [r0, #5]        ; load 4 src pixels with 1 byte offset
+    ldr     r5, [r2, #4]        ; load 4 ref pixels
+
+    ; bilinear interpolation
+    mvn     r6, r6
+    uhsub8  r4, r4, r6
+    eor     r4, r4, r10
+
+    smlad   r11, r7, r7, r11    ; dual signed multiply, add and accumulate (2)
+
+    usub8   r6, r4, r5          ; calculate difference
+    sel     r7, r6, lr          ; select bytes with positive difference
+    usub8   r6, r5, r4          ; calculate difference with reversed operands
+    sel     r6, r6, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r4, r7, lr          ; calculate sum of positive differences
+    usad8   r5, r6, lr          ; calculate sum of negative differences
+    orr     r6, r6, r7          ; differences of all 4 pixels
+
+    ; calculate total sum
+    add     r8, r8, r4          ; add positive differences to sum
+    sub     r8, r8, r5          ; substract negative differences from sum
+
+    ; calculate sse
+    uxtb16  r5, r6              ; byte (two pixels) to halfwords
+    uxtb16  r7, r6, ror #8      ; another two pixels to halfwords
+    smlad   r11, r5, r5, r11    ; dual signed multiply, add and accumulate (1)
+
+    ; 3rd 4 pixels
+    ldr     r4, [r0, #8]        ; load 4 src pixels
+    ldr     r6, [r0, #9]        ; load 4 src pixels with 1 byte offset
+    ldr     r5, [r2, #8]        ; load 4 ref pixels
+
+    ; bilinear interpolation
+    mvn     r6, r6
+    uhsub8  r4, r4, r6
+    eor     r4, r4, r10
+
+    smlad   r11, r7, r7, r11  ; dual signed multiply, add and accumulate (2)
+
+    usub8   r6, r4, r5          ; calculate difference
+    sel     r7, r6, lr          ; select bytes with positive difference
+    usub8   r6, r5, r4          ; calculate difference with reversed operands
+    sel     r6, r6, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r4, r7, lr          ; calculate sum of positive differences
+    usad8   r5, r6, lr          ; calculate sum of negative differences
+    orr     r6, r6, r7          ; differences of all 4 pixels
+
+    ; calculate total sum
+    add     r8, r8, r4          ; add positive differences to sum
+    sub     r8, r8, r5          ; substract negative differences from sum
+
+    ; calculate sse
+    uxtb16  r5, r6              ; byte (two pixels) to halfwords
+    uxtb16  r7, r6, ror #8      ; another two pixels to halfwords
+    smlad   r11, r5, r5, r11    ; dual signed multiply, add and accumulate (1)
+
+    ; 4th 4 pixels
+    ldr     r4, [r0, #12]       ; load 4 src pixels
+    ldr     r6, [r0, #13]       ; load 4 src pixels with 1 byte offset
+    ldr     r5, [r2, #12]       ; load 4 ref pixels
+
+    ; bilinear interpolation
+    mvn     r6, r6
+    uhsub8  r4, r4, r6
+    eor     r4, r4, r10
+
+    smlad   r11, r7, r7, r11    ; dual signed multiply, add and accumulate (2)
+
+    usub8   r6, r4, r5          ; calculate difference
+    add     r0, r0, r1          ; set src_ptr to next row
+    sel     r7, r6, lr          ; select bytes with positive difference
+    usub8   r6, r5, r4          ; calculate difference with reversed operands
+    add     r2, r2, r3          ; set dst_ptr to next row
+    sel     r6, r6, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r4, r7, lr          ; calculate sum of positive differences
+    usad8   r5, r6, lr          ; calculate sum of negative differences
+    orr     r6, r6, r7          ; differences of all 4 pixels
+
+    ; calculate total sum
+    add     r8, r8, r4          ; add positive differences to sum
+    sub     r8, r8, r5          ; substract negative differences from sum
+
+    ; calculate sse
+    uxtb16  r5, r6              ; byte (two pixels) to halfwords
+    uxtb16  r7, r6, ror #8      ; another two pixels to halfwords
+    smlad   r11, r5, r5, r11    ; dual signed multiply, add and accumulate (1)
+    smlad   r11, r7, r7, r11    ; dual signed multiply, add and accumulate (2)
+
+    subs    r12, r12, #1
+
+    bne     loop
+
+    ; return stuff
+    ldr     r6, [sp, #40]       ; get address of sse
+    mul     r0, r8, r8          ; sum * sum
+    str     r11, [r6]           ; store sse
+    sub     r0, r11, r0, lsr #8 ; return (sse - ((sum * sum) >> 8))
+
+    ldmfd   sp!, {r4-r12, pc}
+
+    ENDP
+
+c80808080
+    DCD     0x80808080
+
+    END
+
diff --git a/vp8/common/arm/armv6/vp8_variance_halfpixvar16x16_hv_armv6.asm b/vp8/common/arm/armv6/vp8_variance_halfpixvar16x16_hv_armv6.asm
new file mode 100644 (file)
index 0000000..f972d9b
--- /dev/null
@@ -0,0 +1,222 @@
+;
+;  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_variance_halfpixvar16x16_hv_armv6|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    unsigned char *src_ptr
+; r1    int source_stride
+; r2    unsigned char *ref_ptr
+; r3    int  recon_stride
+; stack unsigned int *sse
+|vp8_variance_halfpixvar16x16_hv_armv6| PROC
+
+    stmfd   sp!, {r4-r12, lr}
+
+    pld     [r0, r1, lsl #0]
+    pld     [r2, r3, lsl #0]
+
+    mov     r8, #0              ; initialize sum = 0
+    ldr     r10, c80808080
+    mov     r11, #0             ; initialize sse = 0
+    mov     r12, #16            ; set loop counter to 16 (=block height)
+    mov     lr, #0              ; constant zero
+loop
+    add     r9, r0, r1          ; pointer to pixels on the next row
+    ; 1st 4 pixels
+    ldr     r4, [r0, #0]        ; load source pixels a, row N
+    ldr     r6, [r0, #1]        ; load source pixels b, row N
+    ldr     r5, [r9, #0]        ; load source pixels c, row N+1
+    ldr     r7, [r9, #1]        ; load source pixels d, row N+1
+
+    ; x = (a + b + 1) >> 1, interpolate pixels horizontally on row N
+    mvn     r6, r6
+    uhsub8  r4, r4, r6
+    eor     r4, r4, r10
+    ; y = (c + d + 1) >> 1, interpolate pixels horizontally on row N+1
+    mvn     r7, r7
+    uhsub8  r5, r5, r7
+    eor     r5, r5, r10
+    ; z = (x + y + 1) >> 1, interpolate half pixel values vertically
+    mvn     r5, r5
+    uhsub8  r4, r4, r5
+    ldr     r5, [r2, #0]        ; load 4 ref pixels
+    eor     r4, r4, r10
+
+    usub8   r6, r4, r5          ; calculate difference
+    pld     [r0, r1, lsl #1]
+    sel     r7, r6, lr          ; select bytes with positive difference
+    usub8   r6, r5, r4          ; calculate difference with reversed operands
+    pld     [r2, r3, lsl #1]
+    sel     r6, r6, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r4, r7, lr          ; calculate sum of positive differences
+    usad8   r5, r6, lr          ; calculate sum of negative differences
+    orr     r6, r6, r7          ; differences of all 4 pixels
+    ; calculate total sum
+    adds    r8, r8, r4          ; add positive differences to sum
+    subs    r8, r8, r5          ; substract negative differences from sum
+
+    ; calculate sse
+    uxtb16  r5, r6              ; byte (two pixels) to halfwords
+    uxtb16  r7, r6, ror #8      ; another two pixels to halfwords
+    smlad   r11, r5, r5, r11    ; dual signed multiply, add and accumulate (1)
+
+    ; 2nd 4 pixels
+    ldr     r4, [r0, #4]        ; load source pixels a, row N
+    ldr     r6, [r0, #5]        ; load source pixels b, row N
+    ldr     r5, [r9, #4]        ; load source pixels c, row N+1
+
+    smlad   r11, r7, r7, r11    ; dual signed multiply, add and accumulate (2)
+
+    ldr     r7, [r9, #5]        ; load source pixels d, row N+1
+
+    ; x = (a + b + 1) >> 1, interpolate pixels horizontally on row N
+    mvn     r6, r6
+    uhsub8  r4, r4, r6
+    eor     r4, r4, r10
+    ; y = (c + d + 1) >> 1, interpolate pixels horizontally on row N+1
+    mvn     r7, r7
+    uhsub8  r5, r5, r7
+    eor     r5, r5, r10
+    ; z = (x + y + 1) >> 1, interpolate half pixel values vertically
+    mvn     r5, r5
+    uhsub8  r4, r4, r5
+    ldr     r5, [r2, #4]        ; load 4 ref pixels
+    eor     r4, r4, r10
+
+    usub8   r6, r4, r5          ; calculate difference
+    sel     r7, r6, lr          ; select bytes with positive difference
+    usub8   r6, r5, r4          ; calculate difference with reversed operands
+    sel     r6, r6, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r4, r7, lr          ; calculate sum of positive differences
+    usad8   r5, r6, lr          ; calculate sum of negative differences
+    orr     r6, r6, r7          ; differences of all 4 pixels
+
+    ; calculate total sum
+    add     r8, r8, r4          ; add positive differences to sum
+    sub     r8, r8, r5          ; substract negative differences from sum
+
+    ; calculate sse
+    uxtb16  r5, r6              ; byte (two pixels) to halfwords
+    uxtb16  r7, r6, ror #8      ; another two pixels to halfwords
+    smlad   r11, r5, r5, r11    ; dual signed multiply, add and accumulate (1)
+
+    ; 3rd 4 pixels
+    ldr     r4, [r0, #8]        ; load source pixels a, row N
+    ldr     r6, [r0, #9]        ; load source pixels b, row N
+    ldr     r5, [r9, #8]        ; load source pixels c, row N+1
+
+    smlad   r11, r7, r7, r11    ; dual signed multiply, add and accumulate (2)
+
+    ldr     r7, [r9, #9]        ; load source pixels d, row N+1
+
+    ; x = (a + b + 1) >> 1, interpolate pixels horizontally on row N
+    mvn     r6, r6
+    uhsub8  r4, r4, r6
+    eor     r4, r4, r10
+    ; y = (c + d + 1) >> 1, interpolate pixels horizontally on row N+1
+    mvn     r7, r7
+    uhsub8  r5, r5, r7
+    eor     r5, r5, r10
+    ; z = (x + y + 1) >> 1, interpolate half pixel values vertically
+    mvn     r5, r5
+    uhsub8  r4, r4, r5
+    ldr     r5, [r2, #8]        ; load 4 ref pixels
+    eor     r4, r4, r10
+
+    usub8   r6, r4, r5          ; calculate difference
+    sel     r7, r6, lr          ; select bytes with positive difference
+    usub8   r6, r5, r4          ; calculate difference with reversed operands
+    sel     r6, r6, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r4, r7, lr          ; calculate sum of positive differences
+    usad8   r5, r6, lr          ; calculate sum of negative differences
+    orr     r6, r6, r7          ; differences of all 4 pixels
+
+    ; calculate total sum
+    add     r8, r8, r4          ; add positive differences to sum
+    sub     r8, r8, r5          ; substract negative differences from sum
+
+    ; calculate sse
+    uxtb16  r5, r6              ; byte (two pixels) to halfwords
+    uxtb16  r7, r6, ror #8      ; another two pixels to halfwords
+    smlad   r11, r5, r5, r11    ; dual signed multiply, add and accumulate (1)
+
+    ; 4th 4 pixels
+    ldr     r4, [r0, #12]       ; load source pixels a, row N
+    ldr     r6, [r0, #13]       ; load source pixels b, row N
+    ldr     r5, [r9, #12]       ; load source pixels c, row N+1
+    smlad   r11, r7, r7, r11    ; dual signed multiply, add and accumulate (2)
+    ldr     r7, [r9, #13]       ; load source pixels d, row N+1
+
+    ; x = (a + b + 1) >> 1, interpolate pixels horizontally on row N
+    mvn     r6, r6
+    uhsub8  r4, r4, r6
+    eor     r4, r4, r10
+    ; y = (c + d + 1) >> 1, interpolate pixels horizontally on row N+1
+    mvn     r7, r7
+    uhsub8  r5, r5, r7
+    eor     r5, r5, r10
+    ; z = (x + y + 1) >> 1, interpolate half pixel values vertically
+    mvn     r5, r5
+    uhsub8  r4, r4, r5
+    ldr     r5, [r2, #12]       ; load 4 ref pixels
+    eor     r4, r4, r10
+
+    usub8   r6, r4, r5          ; calculate difference
+    add     r0, r0, r1          ; set src_ptr to next row
+    sel     r7, r6, lr          ; select bytes with positive difference
+    usub8   r6, r5, r4          ; calculate difference with reversed operands
+    add     r2, r2, r3          ; set dst_ptr to next row
+    sel     r6, r6, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r4, r7, lr          ; calculate sum of positive differences
+    usad8   r5, r6, lr          ; calculate sum of negative differences
+    orr     r6, r6, r7          ; differences of all 4 pixels
+
+    ; calculate total sum
+    add     r8, r8, r4          ; add positive differences to sum
+    sub     r8, r8, r5          ; substract negative differences from sum
+
+    ; calculate sse
+    uxtb16  r5, r6              ; byte (two pixels) to halfwords
+    uxtb16  r7, r6, ror #8      ; another two pixels to halfwords
+    smlad   r11, r5, r5, r11    ; dual signed multiply, add and accumulate (1)
+    subs    r12, r12, #1
+    smlad   r11, r7, r7, r11    ; dual signed multiply, add and accumulate (2)
+
+    bne     loop
+
+    ; return stuff
+    ldr     r6, [sp, #40]       ; get address of sse
+    mul     r0, r8, r8          ; sum * sum
+    str     r11, [r6]           ; store sse
+    sub     r0, r11, r0, lsr #8 ; return (sse - ((sum * sum) >> 8))
+
+    ldmfd   sp!, {r4-r12, pc}
+
+    ENDP
+
+c80808080
+    DCD     0x80808080
+
+    END
diff --git a/vp8/common/arm/armv6/vp8_variance_halfpixvar16x16_v_armv6.asm b/vp8/common/arm/armv6/vp8_variance_halfpixvar16x16_v_armv6.asm
new file mode 100644 (file)
index 0000000..f5da9c0
--- /dev/null
@@ -0,0 +1,184 @@
+;
+;  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_variance_halfpixvar16x16_v_armv6|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    unsigned char *src_ptr
+; r1    int source_stride
+; r2    unsigned char *ref_ptr
+; r3    int  recon_stride
+; stack unsigned int *sse
+|vp8_variance_halfpixvar16x16_v_armv6| PROC
+
+    stmfd   sp!, {r4-r12, lr}
+
+    pld     [r0, r1, lsl #0]
+    pld     [r2, r3, lsl #0]
+
+    mov     r8, #0              ; initialize sum = 0
+    ldr     r10, c80808080
+    mov     r11, #0             ; initialize sse = 0
+    mov     r12, #16            ; set loop counter to 16 (=block height)
+    mov     lr, #0              ; constant zero
+loop
+    add     r9, r0, r1          ; set src pointer to next row
+    ; 1st 4 pixels
+    ldr     r4, [r0, #0]        ; load 4 src pixels
+    ldr     r6, [r9, #0]        ; load 4 src pixels from next row
+    ldr     r5, [r2, #0]        ; load 4 ref pixels
+
+    ; bilinear interpolation
+    mvn     r6, r6
+    uhsub8  r4, r4, r6
+    eor     r4, r4, r10
+
+    usub8   r6, r4, r5          ; calculate difference
+    pld     [r0, r1, lsl #1]
+    sel     r7, r6, lr          ; select bytes with positive difference
+    usub8   r6, r5, r4          ; calculate difference with reversed operands
+    pld     [r2, r3, lsl #1]
+    sel     r6, r6, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r4, r7, lr          ; calculate sum of positive differences
+    usad8   r5, r6, lr          ; calculate sum of negative differences
+    orr     r6, r6, r7          ; differences of all 4 pixels
+    ; calculate total sum
+    adds    r8, r8, r4          ; add positive differences to sum
+    subs    r8, r8, r5          ; substract negative differences from sum
+
+    ; calculate sse
+    uxtb16  r5, r6              ; byte (two pixels) to halfwords
+    uxtb16  r7, r6, ror #8      ; another two pixels to halfwords
+    smlad   r11, r5, r5, r11    ; dual signed multiply, add and accumulate (1)
+
+    ; 2nd 4 pixels
+    ldr     r4, [r0, #4]        ; load 4 src pixels
+    ldr     r6, [r9, #4]        ; load 4 src pixels from next row
+    ldr     r5, [r2, #4]        ; load 4 ref pixels
+
+    ; bilinear interpolation
+    mvn     r6, r6
+    uhsub8  r4, r4, r6
+    eor     r4, r4, r10
+
+    smlad   r11, r7, r7, r11    ; dual signed multiply, add and accumulate (2)
+
+    usub8   r6, r4, r5          ; calculate difference
+    sel     r7, r6, lr          ; select bytes with positive difference
+    usub8   r6, r5, r4          ; calculate difference with reversed operands
+    sel     r6, r6, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r4, r7, lr          ; calculate sum of positive differences
+    usad8   r5, r6, lr          ; calculate sum of negative differences
+    orr     r6, r6, r7          ; differences of all 4 pixels
+
+    ; calculate total sum
+    add     r8, r8, r4          ; add positive differences to sum
+    sub     r8, r8, r5          ; substract negative differences from sum
+
+    ; calculate sse
+    uxtb16  r5, r6              ; byte (two pixels) to halfwords
+    uxtb16  r7, r6, ror #8      ; another two pixels to halfwords
+    smlad   r11, r5, r5, r11    ; dual signed multiply, add and accumulate (1)
+
+    ; 3rd 4 pixels
+    ldr     r4, [r0, #8]        ; load 4 src pixels
+    ldr     r6, [r9, #8]        ; load 4 src pixels from next row
+    ldr     r5, [r2, #8]        ; load 4 ref pixels
+
+    ; bilinear interpolation
+    mvn     r6, r6
+    uhsub8  r4, r4, r6
+    eor     r4, r4, r10
+
+    smlad   r11, r7, r7, r11    ; dual signed multiply, add and accumulate (2)
+
+    usub8   r6, r4, r5          ; calculate difference
+    sel     r7, r6, lr          ; select bytes with positive difference
+    usub8   r6, r5, r4          ; calculate difference with reversed operands
+    sel     r6, r6, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r4, r7, lr          ; calculate sum of positive differences
+    usad8   r5, r6, lr          ; calculate sum of negative differences
+    orr     r6, r6, r7          ; differences of all 4 pixels
+
+    ; calculate total sum
+    add     r8, r8, r4          ; add positive differences to sum
+    sub     r8, r8, r5          ; substract negative differences from sum
+
+    ; calculate sse
+    uxtb16  r5, r6              ; byte (two pixels) to halfwords
+    uxtb16  r7, r6, ror #8      ; another two pixels to halfwords
+    smlad   r11, r5, r5, r11    ; dual signed multiply, add and accumulate (1)
+
+    ; 4th 4 pixels
+    ldr     r4, [r0, #12]       ; load 4 src pixels
+    ldr     r6, [r9, #12]       ; load 4 src pixels from next row
+    ldr     r5, [r2, #12]       ; load 4 ref pixels
+
+    ; bilinear interpolation
+    mvn     r6, r6
+    uhsub8  r4, r4, r6
+    eor     r4, r4, r10
+
+    smlad   r11, r7, r7, r11    ; dual signed multiply, add and accumulate (2)
+
+    usub8   r6, r4, r5          ; calculate difference
+    add     r0, r0, r1          ; set src_ptr to next row
+    sel     r7, r6, lr          ; select bytes with positive difference
+    usub8   r6, r5, r4          ; calculate difference with reversed operands
+    add     r2, r2, r3          ; set dst_ptr to next row
+    sel     r6, r6, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r4, r7, lr          ; calculate sum of positive differences
+    usad8   r5, r6, lr          ; calculate sum of negative differences
+    orr     r6, r6, r7          ; differences of all 4 pixels
+
+    ; calculate total sum
+    add     r8, r8, r4          ; add positive differences to sum
+    sub     r8, r8, r5          ; substract negative differences from sum
+
+    ; calculate sse
+    uxtb16  r5, r6              ; byte (two pixels) to halfwords
+    uxtb16  r7, r6, ror #8      ; another two pixels to halfwords
+    smlad   r11, r5, r5, r11    ; dual signed multiply, add and accumulate (1)
+    smlad   r11, r7, r7, r11    ; dual signed multiply, add and accumulate (2)
+
+
+    subs    r12, r12, #1
+
+    bne     loop
+
+    ; return stuff
+    ldr     r6, [sp, #40]       ; get address of sse
+    mul     r0, r8, r8          ; sum * sum
+    str     r11, [r6]           ; store sse
+    sub     r0, r11, r0, lsr #8 ; return (sse - ((sum * sum) >> 8))
+
+    ldmfd   sp!, {r4-r12, pc}
+
+    ENDP
+
+c80808080
+    DCD     0x80808080
+
+    END
+
diff --git a/vp8/common/arm/bilinearfilter_arm.c b/vp8/common/arm/bilinearfilter_arm.c
new file mode 100644 (file)
index 0000000..c63073c
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include <math.h>
+#include "vp8/common/filter.h"
+#include "bilinearfilter_arm.h"
+
+void vp8_filter_block2d_bil_armv6
+(
+    unsigned char *src_ptr,
+    unsigned char *dst_ptr,
+    unsigned int   src_pitch,
+    unsigned int   dst_pitch,
+    const short   *HFilter,
+    const short   *VFilter,
+    int            Width,
+    int            Height
+)
+{
+    unsigned short FData[36*16]; /* Temp data buffer used in filtering */
+
+    /* First filter 1-D horizontally... */
+    vp8_filter_block2d_bil_first_pass_armv6(src_ptr, FData, src_pitch, Height + 1, Width, HFilter);
+
+    /* then 1-D vertically... */
+    vp8_filter_block2d_bil_second_pass_armv6(FData, dst_ptr, dst_pitch, Height, Width, VFilter);
+}
+
+
+void vp8_bilinear_predict4x4_armv6
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+
+    HFilter = vp8_bilinear_filters[xoffset];
+    VFilter = vp8_bilinear_filters[yoffset];
+
+    vp8_filter_block2d_bil_armv6(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 4, 4);
+}
+
+void vp8_bilinear_predict8x8_armv6
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+
+    HFilter = vp8_bilinear_filters[xoffset];
+    VFilter = vp8_bilinear_filters[yoffset];
+
+    vp8_filter_block2d_bil_armv6(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 8, 8);
+}
+
+void vp8_bilinear_predict8x4_armv6
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+
+    HFilter = vp8_bilinear_filters[xoffset];
+    VFilter = vp8_bilinear_filters[yoffset];
+
+    vp8_filter_block2d_bil_armv6(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 8, 4);
+}
+
+void vp8_bilinear_predict16x16_armv6
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+
+    HFilter = vp8_bilinear_filters[xoffset];
+    VFilter = vp8_bilinear_filters[yoffset];
+
+    vp8_filter_block2d_bil_armv6(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 16, 16);
+}
diff --git a/vp8/common/arm/bilinearfilter_arm.h b/vp8/common/arm/bilinearfilter_arm.h
new file mode 100644 (file)
index 0000000..b7155d3
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef BILINEARFILTER_ARM_H
+#define BILINEARFILTER_ARM_H
+
+extern void vp8_filter_block2d_bil_first_pass_armv6
+(
+    const unsigned char  *src_ptr,
+    unsigned short       *dst_ptr,
+    unsigned int          src_pitch,
+    unsigned int          height,
+    unsigned int          width,
+    const short          *vp8_filter
+);
+
+extern void vp8_filter_block2d_bil_second_pass_armv6
+(
+    const unsigned short *src_ptr,
+    unsigned char        *dst_ptr,
+    int                   dst_pitch,
+    unsigned int          height,
+    unsigned int          width,
+    const short         *vp8_filter
+);
+
+#endif /* BILINEARFILTER_ARM_H */
diff --git a/vp8/common/arm/dequantize_arm.c b/vp8/common/arm/dequantize_arm.c
new file mode 100644 (file)
index 0000000..70e72aa
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vp8/common/blockd.h"
+
+#if HAVE_NEON
+extern void vp8_dequantize_b_loop_neon(short *Q, short *DQC, short *DQ);
+#endif
+
+#if HAVE_MEDIA
+extern void vp8_dequantize_b_loop_v6(short *Q, short *DQC, short *DQ);
+#endif
+
+#if HAVE_NEON
+
+void vp8_dequantize_b_neon(BLOCKD *d, short *DQC)
+{
+    short *DQ  = d->dqcoeff;
+    short *Q   = d->qcoeff;
+
+    vp8_dequantize_b_loop_neon(Q, DQC, DQ);
+}
+#endif
+
+#if HAVE_MEDIA
+void vp8_dequantize_b_v6(BLOCKD *d, short *DQC)
+{
+    short *DQ  = d->dqcoeff;
+    short *Q   = d->qcoeff;
+
+    vp8_dequantize_b_loop_v6(Q, DQC, DQ);
+}
+#endif
diff --git a/vp8/common/arm/filter_arm.c b/vp8/common/arm/filter_arm.c
new file mode 100644 (file)
index 0000000..148951a
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include <math.h>
+#include "vp8/common/filter.h"
+#include "vpx_ports/mem.h"
+
+extern void vp8_filter_block2d_first_pass_armv6
+(
+    unsigned char *src_ptr,
+    short         *output_ptr,
+    unsigned int src_pixels_per_line,
+    unsigned int output_width,
+    unsigned int output_height,
+    const short *vp8_filter
+);
+
+// 8x8
+extern void vp8_filter_block2d_first_pass_8x8_armv6
+(
+    unsigned char *src_ptr,
+    short         *output_ptr,
+    unsigned int src_pixels_per_line,
+    unsigned int output_width,
+    unsigned int output_height,
+    const short *vp8_filter
+);
+
+// 16x16
+extern void vp8_filter_block2d_first_pass_16x16_armv6
+(
+    unsigned char *src_ptr,
+    short         *output_ptr,
+    unsigned int src_pixels_per_line,
+    unsigned int output_width,
+    unsigned int output_height,
+    const short *vp8_filter
+);
+
+extern void vp8_filter_block2d_second_pass_armv6
+(
+    short         *src_ptr,
+    unsigned char *output_ptr,
+    unsigned int output_pitch,
+    unsigned int cnt,
+    const short *vp8_filter
+);
+
+extern void vp8_filter4_block2d_second_pass_armv6
+(
+    short         *src_ptr,
+    unsigned char *output_ptr,
+    unsigned int output_pitch,
+    unsigned int cnt,
+    const short *vp8_filter
+);
+
+extern void vp8_filter_block2d_first_pass_only_armv6
+(
+    unsigned char *src_ptr,
+    unsigned char *output_ptr,
+    unsigned int src_pixels_per_line,
+    unsigned int cnt,
+    unsigned int output_pitch,
+    const short *vp8_filter
+);
+
+
+extern void vp8_filter_block2d_second_pass_only_armv6
+(
+    unsigned char *src_ptr,
+    unsigned char *output_ptr,
+    unsigned int src_pixels_per_line,
+    unsigned int cnt,
+    unsigned int output_pitch,
+    const short *vp8_filter
+);
+
+#if HAVE_MEDIA
+void vp8_sixtap_predict4x4_armv6
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    DECLARE_ALIGNED_ARRAY(4, short, FData, 12*4); /* Temp data buffer used in filtering */
+
+
+    HFilter = vp8_sub_pel_filters[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters[yoffset];   /* 6 tap */
+
+    /* Vfilter is null. First pass only */
+    if (xoffset && !yoffset)
+    {
+        /*vp8_filter_block2d_first_pass_armv6 ( src_ptr, FData+2, src_pixels_per_line, 4, 4, HFilter );
+        vp8_filter_block2d_second_pass_armv6 ( FData+2, dst_ptr, dst_pitch, 4, VFilter );*/
+
+        vp8_filter_block2d_first_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 4, dst_pitch, HFilter);
+    }
+    /* Hfilter is null. Second pass only */
+    else if (!xoffset && yoffset)
+    {
+        vp8_filter_block2d_second_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 4, dst_pitch, VFilter);
+    }
+    else
+    {
+        /* Vfilter is a 4 tap filter */
+        if (yoffset & 0x1)
+        {
+            vp8_filter_block2d_first_pass_armv6(src_ptr - src_pixels_per_line, FData + 1, src_pixels_per_line, 4, 7, HFilter);
+            vp8_filter4_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 4, VFilter);
+        }
+        /* Vfilter is 6 tap filter */
+        else
+        {
+            vp8_filter_block2d_first_pass_armv6(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 4, 9, HFilter);
+            vp8_filter_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 4, VFilter);
+        }
+    }
+}
+
+void vp8_sixtap_predict8x8_armv6
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    DECLARE_ALIGNED_ARRAY(4, short, FData, 16*8); /* Temp data buffer used in filtering */
+
+    HFilter = vp8_sub_pel_filters[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters[yoffset];   /* 6 tap */
+
+    if (xoffset && !yoffset)
+    {
+        vp8_filter_block2d_first_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 8, dst_pitch, HFilter);
+    }
+    /* Hfilter is null. Second pass only */
+    else if (!xoffset && yoffset)
+    {
+        vp8_filter_block2d_second_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 8, dst_pitch, VFilter);
+    }
+    else
+    {
+        if (yoffset & 0x1)
+        {
+            vp8_filter_block2d_first_pass_8x8_armv6(src_ptr - src_pixels_per_line, FData + 1, src_pixels_per_line, 8, 11, HFilter);
+            vp8_filter4_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 8, VFilter);
+        }
+        else
+        {
+            vp8_filter_block2d_first_pass_8x8_armv6(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 8, 13, HFilter);
+            vp8_filter_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 8, VFilter);
+        }
+    }
+}
+
+
+void vp8_sixtap_predict16x16_armv6
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    DECLARE_ALIGNED_ARRAY(4, short, FData, 24*16);    /* Temp data buffer used in filtering */
+
+    HFilter = vp8_sub_pel_filters[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters[yoffset];   /* 6 tap */
+
+    if (xoffset && !yoffset)
+    {
+        vp8_filter_block2d_first_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 16, dst_pitch, HFilter);
+    }
+    /* Hfilter is null. Second pass only */
+    else if (!xoffset && yoffset)
+    {
+        vp8_filter_block2d_second_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 16, dst_pitch, VFilter);
+    }
+    else
+    {
+        if (yoffset & 0x1)
+        {
+            vp8_filter_block2d_first_pass_16x16_armv6(src_ptr - src_pixels_per_line, FData + 1, src_pixels_per_line, 16, 19, HFilter);
+            vp8_filter4_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 16, VFilter);
+        }
+        else
+        {
+            vp8_filter_block2d_first_pass_16x16_armv6(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 16, 21, HFilter);
+            vp8_filter_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 16, VFilter);
+        }
+    }
+
+}
+#endif
diff --git a/vp8/common/arm/loopfilter_arm.c b/vp8/common/arm/loopfilter_arm.c
new file mode 100644 (file)
index 0000000..b8f9bd9
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "vp8/common/loopfilter.h"
+#include "vp8/common/onyxc_int.h"
+
+#define prototype_loopfilter(sym) \
+    void sym(unsigned char *src, int pitch, const unsigned char *blimit,\
+             const unsigned char *limit, const unsigned char *thresh, int count)
+
+#if HAVE_MEDIA
+extern prototype_loopfilter(vp8_loop_filter_horizontal_edge_armv6);
+extern prototype_loopfilter(vp8_loop_filter_vertical_edge_armv6);
+extern prototype_loopfilter(vp8_mbloop_filter_horizontal_edge_armv6);
+extern prototype_loopfilter(vp8_mbloop_filter_vertical_edge_armv6);
+#endif
+
+#if HAVE_NEON
+typedef void loopfilter_y_neon(unsigned char *src, int pitch,
+        unsigned char blimit, unsigned char limit, unsigned char thresh);
+typedef void loopfilter_uv_neon(unsigned char *u, int pitch,
+        unsigned char blimit, unsigned char limit, unsigned char thresh,
+        unsigned char *v);
+
+extern loopfilter_y_neon vp8_loop_filter_horizontal_edge_y_neon;
+extern loopfilter_y_neon vp8_loop_filter_vertical_edge_y_neon;
+extern loopfilter_y_neon vp8_mbloop_filter_horizontal_edge_y_neon;
+extern loopfilter_y_neon vp8_mbloop_filter_vertical_edge_y_neon;
+
+extern loopfilter_uv_neon vp8_loop_filter_horizontal_edge_uv_neon;
+extern loopfilter_uv_neon vp8_loop_filter_vertical_edge_uv_neon;
+extern loopfilter_uv_neon vp8_mbloop_filter_horizontal_edge_uv_neon;
+extern loopfilter_uv_neon vp8_mbloop_filter_vertical_edge_uv_neon;
+#endif
+
+#if HAVE_MEDIA
+/* ARMV6/MEDIA loopfilter functions*/
+/* Horizontal MB filtering */
+void vp8_loop_filter_mbh_armv6(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                               int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    vp8_mbloop_filter_horizontal_edge_armv6(y_ptr, y_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 2);
+
+    if (u_ptr)
+        vp8_mbloop_filter_horizontal_edge_armv6(u_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
+
+    if (v_ptr)
+        vp8_mbloop_filter_horizontal_edge_armv6(v_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
+}
+
+/* Vertical MB Filtering */
+void vp8_loop_filter_mbv_armv6(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                               int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    vp8_mbloop_filter_vertical_edge_armv6(y_ptr, y_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 2);
+
+    if (u_ptr)
+        vp8_mbloop_filter_vertical_edge_armv6(u_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
+
+    if (v_ptr)
+        vp8_mbloop_filter_vertical_edge_armv6(v_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
+}
+
+/* Horizontal B Filtering */
+void vp8_loop_filter_bh_armv6(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                              int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    vp8_loop_filter_horizontal_edge_armv6(y_ptr + 4 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+    vp8_loop_filter_horizontal_edge_armv6(y_ptr + 8 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+    vp8_loop_filter_horizontal_edge_armv6(y_ptr + 12 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+
+    if (u_ptr)
+        vp8_loop_filter_horizontal_edge_armv6(u_ptr + 4 * uv_stride, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
+
+    if (v_ptr)
+        vp8_loop_filter_horizontal_edge_armv6(v_ptr + 4 * uv_stride, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
+}
+
+void vp8_loop_filter_bhs_armv6(unsigned char *y_ptr, int y_stride,
+                               const unsigned char *blimit)
+{
+    vp8_loop_filter_simple_horizontal_edge_armv6(y_ptr + 4 * y_stride, y_stride, blimit);
+    vp8_loop_filter_simple_horizontal_edge_armv6(y_ptr + 8 * y_stride, y_stride, blimit);
+    vp8_loop_filter_simple_horizontal_edge_armv6(y_ptr + 12 * y_stride, y_stride, blimit);
+}
+
+/* Vertical B Filtering */
+void vp8_loop_filter_bv_armv6(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                              int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    vp8_loop_filter_vertical_edge_armv6(y_ptr + 4, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+    vp8_loop_filter_vertical_edge_armv6(y_ptr + 8, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+    vp8_loop_filter_vertical_edge_armv6(y_ptr + 12, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+
+    if (u_ptr)
+        vp8_loop_filter_vertical_edge_armv6(u_ptr + 4, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
+
+    if (v_ptr)
+        vp8_loop_filter_vertical_edge_armv6(v_ptr + 4, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
+}
+
+void vp8_loop_filter_bvs_armv6(unsigned char *y_ptr, int y_stride,
+                               const unsigned char *blimit)
+{
+    vp8_loop_filter_simple_vertical_edge_armv6(y_ptr + 4, y_stride, blimit);
+    vp8_loop_filter_simple_vertical_edge_armv6(y_ptr + 8, y_stride, blimit);
+    vp8_loop_filter_simple_vertical_edge_armv6(y_ptr + 12, y_stride, blimit);
+}
+#endif
+
+#if HAVE_NEON
+/* NEON loopfilter functions */
+/* Horizontal MB filtering */
+void vp8_loop_filter_mbh_neon(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                              int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    unsigned char mblim = *lfi->mblim;
+    unsigned char lim = *lfi->lim;
+    unsigned char hev_thr = *lfi->hev_thr;
+    vp8_mbloop_filter_horizontal_edge_y_neon(y_ptr, y_stride, mblim, lim, hev_thr);
+
+    if (u_ptr)
+        vp8_mbloop_filter_horizontal_edge_uv_neon(u_ptr, uv_stride, mblim, lim, hev_thr, v_ptr);
+}
+
+/* Vertical MB Filtering */
+void vp8_loop_filter_mbv_neon(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                              int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    unsigned char mblim = *lfi->mblim;
+    unsigned char lim = *lfi->lim;
+    unsigned char hev_thr = *lfi->hev_thr;
+
+    vp8_mbloop_filter_vertical_edge_y_neon(y_ptr, y_stride, mblim, lim, hev_thr);
+
+    if (u_ptr)
+        vp8_mbloop_filter_vertical_edge_uv_neon(u_ptr, uv_stride, mblim, lim, hev_thr, v_ptr);
+}
+
+/* Horizontal B Filtering */
+void vp8_loop_filter_bh_neon(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                             int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    unsigned char blim = *lfi->blim;
+    unsigned char lim = *lfi->lim;
+    unsigned char hev_thr = *lfi->hev_thr;
+
+    vp8_loop_filter_horizontal_edge_y_neon(y_ptr + 4 * y_stride, y_stride, blim, lim, hev_thr);
+    vp8_loop_filter_horizontal_edge_y_neon(y_ptr + 8 * y_stride, y_stride, blim, lim, hev_thr);
+    vp8_loop_filter_horizontal_edge_y_neon(y_ptr + 12 * y_stride, y_stride, blim, lim, hev_thr);
+
+    if (u_ptr)
+        vp8_loop_filter_horizontal_edge_uv_neon(u_ptr + 4 * uv_stride, uv_stride, blim, lim, hev_thr, v_ptr + 4 * uv_stride);
+}
+
+/* Vertical B Filtering */
+void vp8_loop_filter_bv_neon(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                             int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    unsigned char blim = *lfi->blim;
+    unsigned char lim = *lfi->lim;
+    unsigned char hev_thr = *lfi->hev_thr;
+
+    vp8_loop_filter_vertical_edge_y_neon(y_ptr + 4, y_stride, blim, lim, hev_thr);
+    vp8_loop_filter_vertical_edge_y_neon(y_ptr + 8, y_stride, blim, lim, hev_thr);
+    vp8_loop_filter_vertical_edge_y_neon(y_ptr + 12, y_stride, blim, lim, hev_thr);
+
+    if (u_ptr)
+        vp8_loop_filter_vertical_edge_uv_neon(u_ptr + 4, uv_stride, blim, lim, hev_thr, v_ptr + 4);
+}
+#endif
diff --git a/vp8/common/arm/neon/bilinearpredict16x16_neon.asm b/vp8/common/arm/neon/bilinearpredict16x16_neon.asm
new file mode 100644 (file)
index 0000000..e392786
--- /dev/null
@@ -0,0 +1,357 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_bilinear_predict16x16_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; r4    unsigned char *dst_ptr,
+; stack(r5) int  dst_pitch
+
+|vp8_bilinear_predict16x16_neon| PROC
+    push            {r4-r5, lr}
+
+    adr             r12, bifilter16_coeff
+    ldr             r4, [sp, #12]           ;load parameters from stack
+    ldr             r5, [sp, #16]           ;load parameters from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             secondpass_bfilter16x16_only
+
+    add             r2, r12, r2, lsl #3     ;calculate filter location
+
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+
+    vld1.s32        {d31}, [r2]             ;load first_pass filter
+
+    beq             firstpass_bfilter16x16_only
+
+    sub             sp, sp, #272            ;reserve space on stack for temporary storage
+    vld1.u8         {d2, d3, d4}, [r0], r1      ;load src data
+    mov             lr, sp
+    vld1.u8         {d5, d6, d7}, [r0], r1
+
+    mov             r2, #3                  ;loop counter
+    vld1.u8         {d8, d9, d10}, [r0], r1
+
+    vdup.8          d0, d31[0]              ;first_pass filter (d0 d1)
+    vld1.u8         {d11, d12, d13}, [r0], r1
+
+    vdup.8          d1, d31[4]
+
+;First Pass: output_height lines x output_width columns (17x16)
+filt_blk2d_fp16x16_loop_neon
+    pld             [r0]
+    pld             [r0, r1]
+    pld             [r0, r1, lsl #1]
+
+    vmull.u8        q7, d2, d0              ;(src_ptr[0] * vp8_filter[0])
+    vmull.u8        q8, d3, d0
+    vmull.u8        q9, d5, d0
+    vmull.u8        q10, d6, d0
+    vmull.u8        q11, d8, d0
+    vmull.u8        q12, d9, d0
+    vmull.u8        q13, d11, d0
+    vmull.u8        q14, d12, d0
+
+    vext.8          d2, d2, d3, #1          ;construct src_ptr[1]
+    vext.8          d5, d5, d6, #1
+    vext.8          d8, d8, d9, #1
+    vext.8          d11, d11, d12, #1
+
+    vmlal.u8        q7, d2, d1              ;(src_ptr[0] * vp8_filter[1])
+    vmlal.u8        q9, d5, d1
+    vmlal.u8        q11, d8, d1
+    vmlal.u8        q13, d11, d1
+
+    vext.8          d3, d3, d4, #1
+    vext.8          d6, d6, d7, #1
+    vext.8          d9, d9, d10, #1
+    vext.8          d12, d12, d13, #1
+
+    vmlal.u8        q8, d3, d1              ;(src_ptr[0] * vp8_filter[1])
+    vmlal.u8        q10, d6, d1
+    vmlal.u8        q12, d9, d1
+    vmlal.u8        q14, d12, d1
+
+    subs            r2, r2, #1
+
+    vqrshrn.u16    d14, q7, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d15, q8, #7
+    vqrshrn.u16    d16, q9, #7
+    vqrshrn.u16    d17, q10, #7
+    vqrshrn.u16    d18, q11, #7
+    vqrshrn.u16    d19, q12, #7
+    vqrshrn.u16    d20, q13, #7
+
+    vld1.u8         {d2, d3, d4}, [r0], r1      ;load src data
+    vqrshrn.u16    d21, q14, #7
+    vld1.u8         {d5, d6, d7}, [r0], r1
+
+    vst1.u8         {d14, d15, d16, d17}, [lr]!     ;store result
+    vld1.u8         {d8, d9, d10}, [r0], r1
+    vst1.u8         {d18, d19, d20, d21}, [lr]!
+    vld1.u8         {d11, d12, d13}, [r0], r1
+
+    bne             filt_blk2d_fp16x16_loop_neon
+
+;First-pass filtering for rest 5 lines
+    vld1.u8         {d14, d15, d16}, [r0], r1
+
+    vmull.u8        q9, d2, d0              ;(src_ptr[0] * vp8_filter[0])
+    vmull.u8        q10, d3, d0
+    vmull.u8        q11, d5, d0
+    vmull.u8        q12, d6, d0
+    vmull.u8        q13, d8, d0
+    vmull.u8        q14, d9, d0
+
+    vext.8          d2, d2, d3, #1          ;construct src_ptr[1]
+    vext.8          d5, d5, d6, #1
+    vext.8          d8, d8, d9, #1
+
+    vmlal.u8        q9, d2, d1              ;(src_ptr[0] * vp8_filter[1])
+    vmlal.u8        q11, d5, d1
+    vmlal.u8        q13, d8, d1
+
+    vext.8          d3, d3, d4, #1
+    vext.8          d6, d6, d7, #1
+    vext.8          d9, d9, d10, #1
+
+    vmlal.u8        q10, d3, d1             ;(src_ptr[0] * vp8_filter[1])
+    vmlal.u8        q12, d6, d1
+    vmlal.u8        q14, d9, d1
+
+    vmull.u8        q1, d11, d0
+    vmull.u8        q2, d12, d0
+    vmull.u8        q3, d14, d0
+    vmull.u8        q4, d15, d0
+
+    vext.8          d11, d11, d12, #1       ;construct src_ptr[1]
+    vext.8          d14, d14, d15, #1
+
+    vmlal.u8        q1, d11, d1             ;(src_ptr[0] * vp8_filter[1])
+    vmlal.u8        q3, d14, d1
+
+    vext.8          d12, d12, d13, #1
+    vext.8          d15, d15, d16, #1
+
+    vmlal.u8        q2, d12, d1             ;(src_ptr[0] * vp8_filter[1])
+    vmlal.u8        q4, d15, d1
+
+    vqrshrn.u16    d10, q9, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d11, q10, #7
+    vqrshrn.u16    d12, q11, #7
+    vqrshrn.u16    d13, q12, #7
+    vqrshrn.u16    d14, q13, #7
+    vqrshrn.u16    d15, q14, #7
+    vqrshrn.u16    d16, q1, #7
+    vqrshrn.u16    d17, q2, #7
+    vqrshrn.u16    d18, q3, #7
+    vqrshrn.u16    d19, q4, #7
+
+    vst1.u8         {d10, d11, d12, d13}, [lr]!         ;store result
+    vst1.u8         {d14, d15, d16, d17}, [lr]!
+    vst1.u8         {d18, d19}, [lr]!
+
+;Second pass: 16x16
+;secondpass_filter
+    add             r3, r12, r3, lsl #3
+    sub             lr, lr, #272
+
+    vld1.u32        {d31}, [r3]             ;load second_pass filter
+
+    vld1.u8         {d22, d23}, [lr]!       ;load src data
+
+    vdup.8          d0, d31[0]              ;second_pass filter parameters (d0 d1)
+    vdup.8          d1, d31[4]
+    mov             r12, #4                 ;loop counter
+
+filt_blk2d_sp16x16_loop_neon
+    vld1.u8         {d24, d25}, [lr]!
+    vmull.u8        q1, d22, d0             ;(src_ptr[0] * vp8_filter[0])
+    vld1.u8         {d26, d27}, [lr]!
+    vmull.u8        q2, d23, d0
+    vld1.u8         {d28, d29}, [lr]!
+    vmull.u8        q3, d24, d0
+    vld1.u8         {d30, d31}, [lr]!
+
+    vmull.u8        q4, d25, d0
+    vmull.u8        q5, d26, d0
+    vmull.u8        q6, d27, d0
+    vmull.u8        q7, d28, d0
+    vmull.u8        q8, d29, d0
+
+    vmlal.u8        q1, d24, d1             ;(src_ptr[pixel_step] * vp8_filter[1])
+    vmlal.u8        q2, d25, d1
+    vmlal.u8        q3, d26, d1
+    vmlal.u8        q4, d27, d1
+    vmlal.u8        q5, d28, d1
+    vmlal.u8        q6, d29, d1
+    vmlal.u8        q7, d30, d1
+    vmlal.u8        q8, d31, d1
+
+    subs            r12, r12, #1
+
+    vqrshrn.u16    d2, q1, #7               ;shift/round/saturate to u8
+    vqrshrn.u16    d3, q2, #7
+    vqrshrn.u16    d4, q3, #7
+    vqrshrn.u16    d5, q4, #7
+    vqrshrn.u16    d6, q5, #7
+    vqrshrn.u16    d7, q6, #7
+    vqrshrn.u16    d8, q7, #7
+    vqrshrn.u16    d9, q8, #7
+
+    vst1.u8         {d2, d3}, [r4], r5      ;store result
+    vst1.u8         {d4, d5}, [r4], r5
+    vst1.u8         {d6, d7}, [r4], r5
+    vmov            q11, q15
+    vst1.u8         {d8, d9}, [r4], r5
+
+    bne             filt_blk2d_sp16x16_loop_neon
+
+    add             sp, sp, #272
+
+    pop             {r4-r5,pc}
+
+;--------------------
+firstpass_bfilter16x16_only
+    mov             r2, #4                      ;loop counter
+    vdup.8          d0, d31[0]                  ;first_pass filter (d0 d1)
+    vdup.8          d1, d31[4]
+
+;First Pass: output_height lines x output_width columns (16x16)
+filt_blk2d_fpo16x16_loop_neon
+    vld1.u8         {d2, d3, d4}, [r0], r1      ;load src data
+    vld1.u8         {d5, d6, d7}, [r0], r1
+    vld1.u8         {d8, d9, d10}, [r0], r1
+    vld1.u8         {d11, d12, d13}, [r0], r1
+
+    pld             [r0]
+    pld             [r0, r1]
+    pld             [r0, r1, lsl #1]
+
+    vmull.u8        q7, d2, d0              ;(src_ptr[0] * vp8_filter[0])
+    vmull.u8        q8, d3, d0
+    vmull.u8        q9, d5, d0
+    vmull.u8        q10, d6, d0
+    vmull.u8        q11, d8, d0
+    vmull.u8        q12, d9, d0
+    vmull.u8        q13, d11, d0
+    vmull.u8        q14, d12, d0
+
+    vext.8          d2, d2, d3, #1          ;construct src_ptr[1]
+    vext.8          d5, d5, d6, #1
+    vext.8          d8, d8, d9, #1
+    vext.8          d11, d11, d12, #1
+
+    vmlal.u8        q7, d2, d1              ;(src_ptr[0] * vp8_filter[1])
+    vmlal.u8        q9, d5, d1
+    vmlal.u8        q11, d8, d1
+    vmlal.u8        q13, d11, d1
+
+    vext.8          d3, d3, d4, #1
+    vext.8          d6, d6, d7, #1
+    vext.8          d9, d9, d10, #1
+    vext.8          d12, d12, d13, #1
+
+    vmlal.u8        q8, d3, d1              ;(src_ptr[0] * vp8_filter[1])
+    vmlal.u8        q10, d6, d1
+    vmlal.u8        q12, d9, d1
+    vmlal.u8        q14, d12, d1
+
+    subs            r2, r2, #1
+
+    vqrshrn.u16    d14, q7, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d15, q8, #7
+    vqrshrn.u16    d16, q9, #7
+    vqrshrn.u16    d17, q10, #7
+    vqrshrn.u16    d18, q11, #7
+    vqrshrn.u16    d19, q12, #7
+    vqrshrn.u16    d20, q13, #7
+    vst1.u8         {d14, d15}, [r4], r5        ;store result
+    vqrshrn.u16    d21, q14, #7
+
+    vst1.u8         {d16, d17}, [r4], r5
+    vst1.u8         {d18, d19}, [r4], r5
+    vst1.u8         {d20, d21}, [r4], r5
+
+    bne             filt_blk2d_fpo16x16_loop_neon
+    pop             {r4-r5,pc}
+
+;---------------------
+secondpass_bfilter16x16_only
+;Second pass: 16x16
+;secondpass_filter
+    add             r3, r12, r3, lsl #3
+    mov             r12, #4                     ;loop counter
+    vld1.u32        {d31}, [r3]                 ;load second_pass filter
+    vld1.u8         {d22, d23}, [r0], r1        ;load src data
+
+    vdup.8          d0, d31[0]                  ;second_pass filter parameters (d0 d1)
+    vdup.8          d1, d31[4]
+
+filt_blk2d_spo16x16_loop_neon
+    vld1.u8         {d24, d25}, [r0], r1
+    vmull.u8        q1, d22, d0             ;(src_ptr[0] * vp8_filter[0])
+    vld1.u8         {d26, d27}, [r0], r1
+    vmull.u8        q2, d23, d0
+    vld1.u8         {d28, d29}, [r0], r1
+    vmull.u8        q3, d24, d0
+    vld1.u8         {d30, d31}, [r0], r1
+
+    vmull.u8        q4, d25, d0
+    vmull.u8        q5, d26, d0
+    vmull.u8        q6, d27, d0
+    vmull.u8        q7, d28, d0
+    vmull.u8        q8, d29, d0
+
+    vmlal.u8        q1, d24, d1             ;(src_ptr[pixel_step] * vp8_filter[1])
+    vmlal.u8        q2, d25, d1
+    vmlal.u8        q3, d26, d1
+    vmlal.u8        q4, d27, d1
+    vmlal.u8        q5, d28, d1
+    vmlal.u8        q6, d29, d1
+    vmlal.u8        q7, d30, d1
+    vmlal.u8        q8, d31, d1
+
+    vqrshrn.u16    d2, q1, #7               ;shift/round/saturate to u8
+    vqrshrn.u16    d3, q2, #7
+    vqrshrn.u16    d4, q3, #7
+    vqrshrn.u16    d5, q4, #7
+    vqrshrn.u16    d6, q5, #7
+    vqrshrn.u16    d7, q6, #7
+    vqrshrn.u16    d8, q7, #7
+    vqrshrn.u16    d9, q8, #7
+
+    vst1.u8         {d2, d3}, [r4], r5      ;store result
+    subs            r12, r12, #1
+    vst1.u8         {d4, d5}, [r4], r5
+    vmov            q11, q15
+    vst1.u8         {d6, d7}, [r4], r5
+    vst1.u8         {d8, d9}, [r4], r5
+
+    bne             filt_blk2d_spo16x16_loop_neon
+    pop             {r4-r5,pc}
+
+    ENDP
+
+;-----------------
+
+bifilter16_coeff
+    DCD     128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112
+
+    END
diff --git a/vp8/common/arm/neon/bilinearpredict4x4_neon.asm b/vp8/common/arm/neon/bilinearpredict4x4_neon.asm
new file mode 100644 (file)
index 0000000..0ac6243
--- /dev/null
@@ -0,0 +1,130 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_bilinear_predict4x4_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; r4    unsigned char *dst_ptr,
+; stack(lr) int  dst_pitch
+
+|vp8_bilinear_predict4x4_neon| PROC
+    push            {r4, lr}
+
+    adr             r12, bifilter4_coeff
+    ldr             r4, [sp, #8]            ;load parameters from stack
+    ldr             lr, [sp, #12]           ;load parameters from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             skip_firstpass_filter
+
+;First pass: output_height lines x output_width columns (5x4)
+    vld1.u8         {d2}, [r0], r1          ;load src data
+    add             r2, r12, r2, lsl #3     ;calculate Hfilter location (2coeffsx4bytes=8bytes)
+
+    vld1.u8         {d3}, [r0], r1
+    vld1.u32        {d31}, [r2]             ;first_pass filter
+
+    vld1.u8         {d4}, [r0], r1
+    vdup.8          d0, d31[0]              ;first_pass filter (d0-d1)
+    vld1.u8         {d5}, [r0], r1
+    vdup.8          d1, d31[4]
+    vld1.u8         {d6}, [r0], r1
+
+    vshr.u64        q4, q1, #8              ;construct src_ptr[1]
+    vshr.u64        q5, q2, #8
+    vshr.u64        d12, d6, #8
+
+    vzip.32         d2, d3                  ;put 2-line data in 1 register (src_ptr[0])
+    vzip.32         d4, d5
+    vzip.32         d8, d9                  ;put 2-line data in 1 register (src_ptr[1])
+    vzip.32         d10, d11
+
+    vmull.u8        q7, d2, d0              ;(src_ptr[0] * vp8_filter[0])
+    vmull.u8        q8, d4, d0
+    vmull.u8        q9, d6, d0
+
+    vmlal.u8        q7, d8, d1              ;(src_ptr[1] * vp8_filter[1])
+    vmlal.u8        q8, d10, d1
+    vmlal.u8        q9, d12, d1
+
+    vqrshrn.u16    d28, q7, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d29, q8, #7
+    vqrshrn.u16    d30, q9, #7
+
+;Second pass: 4x4
+secondpass_filter
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+    beq             skip_secondpass_filter
+
+    add             r3, r12, r3, lsl #3 ;calculate Vfilter location
+    vld1.u32        {d31}, [r3]         ;load second_pass filter
+
+    vdup.8          d0, d31[0]              ;second_pass filter parameters (d0-d5)
+    vdup.8          d1, d31[4]
+
+    vmull.u8        q1, d28, d0
+    vmull.u8        q2, d29, d0
+
+    vext.8          d26, d28, d29, #4       ;construct src_ptr[pixel_step]
+    vext.8          d27, d29, d30, #4
+
+    vmlal.u8        q1, d26, d1
+    vmlal.u8        q2, d27, d1
+
+    add             r0, r4, lr
+    add             r1, r0, lr
+    add             r2, r1, lr
+
+    vqrshrn.u16    d2, q1, #7               ;shift/round/saturate to u8
+    vqrshrn.u16    d3, q2, #7
+
+    vst1.32         {d2[0]}, [r4]           ;store result
+    vst1.32         {d2[1]}, [r0]
+    vst1.32         {d3[0]}, [r1]
+    vst1.32         {d3[1]}, [r2]
+
+    pop             {r4, pc}
+
+;--------------------
+skip_firstpass_filter
+
+    vld1.32         {d28[0]}, [r0], r1      ;load src data
+    vld1.32         {d28[1]}, [r0], r1
+    vld1.32         {d29[0]}, [r0], r1
+    vld1.32         {d29[1]}, [r0], r1
+    vld1.32         {d30[0]}, [r0], r1
+
+    b               secondpass_filter
+
+;---------------------
+skip_secondpass_filter
+    vst1.32         {d28[0]}, [r4], lr      ;store result
+    vst1.32         {d28[1]}, [r4], lr
+    vst1.32         {d29[0]}, [r4], lr
+    vst1.32         {d29[1]}, [r4], lr
+
+    pop             {r4, pc}
+
+    ENDP
+
+;-----------------
+
+bifilter4_coeff
+    DCD     128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112
+
+    END
diff --git a/vp8/common/arm/neon/bilinearpredict8x4_neon.asm b/vp8/common/arm/neon/bilinearpredict8x4_neon.asm
new file mode 100644 (file)
index 0000000..41f5c45
--- /dev/null
@@ -0,0 +1,135 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_bilinear_predict8x4_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; r4    unsigned char *dst_ptr,
+; stack(lr) int  dst_pitch
+
+|vp8_bilinear_predict8x4_neon| PROC
+    push            {r4, lr}
+
+    adr             r12, bifilter8x4_coeff
+    ldr             r4, [sp, #8]            ;load parameters from stack
+    ldr             lr, [sp, #12]           ;load parameters from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             skip_firstpass_filter
+
+;First pass: output_height lines x output_width columns (5x8)
+    add             r2, r12, r2, lsl #3     ;calculate filter location
+
+    vld1.u8         {q1}, [r0], r1          ;load src data
+    vld1.u32        {d31}, [r2]             ;load first_pass filter
+    vld1.u8         {q2}, [r0], r1
+    vdup.8          d0, d31[0]              ;first_pass filter (d0 d1)
+    vld1.u8         {q3}, [r0], r1
+    vdup.8          d1, d31[4]
+    vld1.u8         {q4}, [r0], r1
+
+    vmull.u8        q6, d2, d0              ;(src_ptr[0] * vp8_filter[0])
+    vld1.u8         {q5}, [r0], r1
+    vmull.u8        q7, d4, d0
+    vmull.u8        q8, d6, d0
+    vmull.u8        q9, d8, d0
+    vmull.u8        q10, d10, d0
+
+    vext.8          d3, d2, d3, #1          ;construct src_ptr[-1]
+    vext.8          d5, d4, d5, #1
+    vext.8          d7, d6, d7, #1
+    vext.8          d9, d8, d9, #1
+    vext.8          d11, d10, d11, #1
+
+    vmlal.u8        q6, d3, d1              ;(src_ptr[1] * vp8_filter[1])
+    vmlal.u8        q7, d5, d1
+    vmlal.u8        q8, d7, d1
+    vmlal.u8        q9, d9, d1
+    vmlal.u8        q10, d11, d1
+
+    vqrshrn.u16    d22, q6, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d23, q7, #7
+    vqrshrn.u16    d24, q8, #7
+    vqrshrn.u16    d25, q9, #7
+    vqrshrn.u16    d26, q10, #7
+
+;Second pass: 4x8
+secondpass_filter
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+    beq             skip_secondpass_filter
+
+    add             r3, r12, r3, lsl #3
+    add             r0, r4, lr
+
+    vld1.u32        {d31}, [r3]             ;load second_pass filter
+    add             r1, r0, lr
+
+    vdup.8          d0, d31[0]              ;second_pass filter parameters (d0 d1)
+    vdup.8          d1, d31[4]
+
+    vmull.u8        q1, d22, d0             ;(src_ptr[0] * vp8_filter[0])
+    vmull.u8        q2, d23, d0
+    vmull.u8        q3, d24, d0
+    vmull.u8        q4, d25, d0
+
+    vmlal.u8        q1, d23, d1             ;(src_ptr[pixel_step] * vp8_filter[1])
+    vmlal.u8        q2, d24, d1
+    vmlal.u8        q3, d25, d1
+    vmlal.u8        q4, d26, d1
+
+    add             r2, r1, lr
+
+    vqrshrn.u16    d2, q1, #7               ;shift/round/saturate to u8
+    vqrshrn.u16    d3, q2, #7
+    vqrshrn.u16    d4, q3, #7
+    vqrshrn.u16    d5, q4, #7
+
+    vst1.u8         {d2}, [r4]              ;store result
+    vst1.u8         {d3}, [r0]
+    vst1.u8         {d4}, [r1]
+    vst1.u8         {d5}, [r2]
+
+    pop             {r4, pc}
+
+;--------------------
+skip_firstpass_filter
+    vld1.u8         {d22}, [r0], r1         ;load src data
+    vld1.u8         {d23}, [r0], r1
+    vld1.u8         {d24}, [r0], r1
+    vld1.u8         {d25}, [r0], r1
+    vld1.u8         {d26}, [r0], r1
+
+    b               secondpass_filter
+
+;---------------------
+skip_secondpass_filter
+    vst1.u8         {d22}, [r4], lr         ;store result
+    vst1.u8         {d23}, [r4], lr
+    vst1.u8         {d24}, [r4], lr
+    vst1.u8         {d25}, [r4], lr
+
+    pop             {r4, pc}
+
+    ENDP
+
+;-----------------
+
+bifilter8x4_coeff
+    DCD     128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112
+
+    END
diff --git a/vp8/common/arm/neon/bilinearpredict8x8_neon.asm b/vp8/common/arm/neon/bilinearpredict8x8_neon.asm
new file mode 100644 (file)
index 0000000..c4711bc
--- /dev/null
@@ -0,0 +1,183 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_bilinear_predict8x8_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; r4    unsigned char *dst_ptr,
+; stack(lr) int  dst_pitch
+
+|vp8_bilinear_predict8x8_neon| PROC
+    push            {r4, lr}
+
+    adr             r12, bifilter8_coeff
+    ldr             r4, [sp, #8]            ;load parameters from stack
+    ldr             lr, [sp, #12]           ;load parameters from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             skip_firstpass_filter
+
+;First pass: output_height lines x output_width columns (9x8)
+    add             r2, r12, r2, lsl #3     ;calculate filter location
+
+    vld1.u8         {q1}, [r0], r1          ;load src data
+    vld1.u32        {d31}, [r2]             ;load first_pass filter
+    vld1.u8         {q2}, [r0], r1
+    vdup.8          d0, d31[0]              ;first_pass filter (d0 d1)
+    vld1.u8         {q3}, [r0], r1
+    vdup.8          d1, d31[4]
+    vld1.u8         {q4}, [r0], r1
+
+    vmull.u8        q6, d2, d0              ;(src_ptr[0] * vp8_filter[0])
+    vmull.u8        q7, d4, d0
+    vmull.u8        q8, d6, d0
+    vmull.u8        q9, d8, d0
+
+    vext.8          d3, d2, d3, #1          ;construct src_ptr[-1]
+    vext.8          d5, d4, d5, #1
+    vext.8          d7, d6, d7, #1
+    vext.8          d9, d8, d9, #1
+
+    vmlal.u8        q6, d3, d1              ;(src_ptr[1] * vp8_filter[1])
+    vmlal.u8        q7, d5, d1
+    vmlal.u8        q8, d7, d1
+    vmlal.u8        q9, d9, d1
+
+    vld1.u8         {q1}, [r0], r1          ;load src data
+    vqrshrn.u16    d22, q6, #7              ;shift/round/saturate to u8
+    vld1.u8         {q2}, [r0], r1
+    vqrshrn.u16    d23, q7, #7
+    vld1.u8         {q3}, [r0], r1
+    vqrshrn.u16    d24, q8, #7
+    vld1.u8         {q4}, [r0], r1
+    vqrshrn.u16    d25, q9, #7
+
+    ;first_pass filtering on the rest 5-line data
+    vld1.u8         {q5}, [r0], r1
+
+    vmull.u8        q6, d2, d0              ;(src_ptr[0] * vp8_filter[0])
+    vmull.u8        q7, d4, d0
+    vmull.u8        q8, d6, d0
+    vmull.u8        q9, d8, d0
+    vmull.u8        q10, d10, d0
+
+    vext.8          d3, d2, d3, #1          ;construct src_ptr[-1]
+    vext.8          d5, d4, d5, #1
+    vext.8          d7, d6, d7, #1
+    vext.8          d9, d8, d9, #1
+    vext.8          d11, d10, d11, #1
+
+    vmlal.u8        q6, d3, d1              ;(src_ptr[1] * vp8_filter[1])
+    vmlal.u8        q7, d5, d1
+    vmlal.u8        q8, d7, d1
+    vmlal.u8        q9, d9, d1
+    vmlal.u8        q10, d11, d1
+
+    vqrshrn.u16    d26, q6, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d27, q7, #7
+    vqrshrn.u16    d28, q8, #7
+    vqrshrn.u16    d29, q9, #7
+    vqrshrn.u16    d30, q10, #7
+
+;Second pass: 8x8
+secondpass_filter
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+    beq             skip_secondpass_filter
+
+    add             r3, r12, r3, lsl #3
+    add             r0, r4, lr
+
+    vld1.u32        {d31}, [r3]             ;load second_pass filter
+    add             r1, r0, lr
+
+    vdup.8          d0, d31[0]              ;second_pass filter parameters (d0 d1)
+    vdup.8          d1, d31[4]
+
+    vmull.u8        q1, d22, d0             ;(src_ptr[0] * vp8_filter[0])
+    vmull.u8        q2, d23, d0
+    vmull.u8        q3, d24, d0
+    vmull.u8        q4, d25, d0
+    vmull.u8        q5, d26, d0
+    vmull.u8        q6, d27, d0
+    vmull.u8        q7, d28, d0
+    vmull.u8        q8, d29, d0
+
+    vmlal.u8        q1, d23, d1             ;(src_ptr[pixel_step] * vp8_filter[1])
+    vmlal.u8        q2, d24, d1
+    vmlal.u8        q3, d25, d1
+    vmlal.u8        q4, d26, d1
+    vmlal.u8        q5, d27, d1
+    vmlal.u8        q6, d28, d1
+    vmlal.u8        q7, d29, d1
+    vmlal.u8        q8, d30, d1
+
+    vqrshrn.u16    d2, q1, #7               ;shift/round/saturate to u8
+    vqrshrn.u16    d3, q2, #7
+    vqrshrn.u16    d4, q3, #7
+    vqrshrn.u16    d5, q4, #7
+    vqrshrn.u16    d6, q5, #7
+    vqrshrn.u16    d7, q6, #7
+    vqrshrn.u16    d8, q7, #7
+    vqrshrn.u16    d9, q8, #7
+
+    vst1.u8         {d2}, [r4]              ;store result
+    vst1.u8         {d3}, [r0]
+    vst1.u8         {d4}, [r1], lr
+    vst1.u8         {d5}, [r1], lr
+    vst1.u8         {d6}, [r1], lr
+    vst1.u8         {d7}, [r1], lr
+    vst1.u8         {d8}, [r1], lr
+    vst1.u8         {d9}, [r1], lr
+
+    pop             {r4, pc}
+
+;--------------------
+skip_firstpass_filter
+    vld1.u8         {d22}, [r0], r1         ;load src data
+    vld1.u8         {d23}, [r0], r1
+    vld1.u8         {d24}, [r0], r1
+    vld1.u8         {d25}, [r0], r1
+    vld1.u8         {d26}, [r0], r1
+    vld1.u8         {d27}, [r0], r1
+    vld1.u8         {d28}, [r0], r1
+    vld1.u8         {d29}, [r0], r1
+    vld1.u8         {d30}, [r0], r1
+
+    b               secondpass_filter
+
+;---------------------
+skip_secondpass_filter
+    vst1.u8         {d22}, [r4], lr         ;store result
+    vst1.u8         {d23}, [r4], lr
+    vst1.u8         {d24}, [r4], lr
+    vst1.u8         {d25}, [r4], lr
+    vst1.u8         {d26}, [r4], lr
+    vst1.u8         {d27}, [r4], lr
+    vst1.u8         {d28}, [r4], lr
+    vst1.u8         {d29}, [r4], lr
+
+    pop             {r4, pc}
+
+    ENDP
+
+;-----------------
+
+bifilter8_coeff
+    DCD     128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112
+
+    END
diff --git a/vp8/common/arm/neon/buildintrapredictorsmby_neon.asm b/vp8/common/arm/neon/buildintrapredictorsmby_neon.asm
new file mode 100644 (file)
index 0000000..e3ea91f
--- /dev/null
@@ -0,0 +1,584 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_build_intra_predictors_mby_neon_func|
+    EXPORT  |vp8_build_intra_predictors_mby_s_neon_func|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; r0    unsigned char *y_buffer
+; r1    unsigned char *ypred_ptr
+; r2    int y_stride
+; r3    int mode
+; stack int Up
+; stack int Left
+
+|vp8_build_intra_predictors_mby_neon_func| PROC
+    push            {r4-r8, lr}
+
+    cmp             r3, #0
+    beq             case_dc_pred
+    cmp             r3, #1
+    beq             case_v_pred
+    cmp             r3, #2
+    beq             case_h_pred
+    cmp             r3, #3
+    beq             case_tm_pred
+
+case_dc_pred
+    ldr             r4, [sp, #24]       ; Up
+    ldr             r5, [sp, #28]       ; Left
+
+    ; Default the DC average to 128
+    mov             r12, #128
+    vdup.u8         q0, r12
+
+    ; Zero out running sum
+    mov             r12, #0
+
+    ; compute shift and jump
+    adds            r7, r4, r5
+    beq             skip_dc_pred_up_left
+
+    ; Load above row, if it exists
+    cmp             r4, #0
+    beq             skip_dc_pred_up
+
+    sub             r6, r0, r2
+    vld1.8          {q1}, [r6]
+    vpaddl.u8       q2, q1
+    vpaddl.u16      q3, q2
+    vpaddl.u32      q4, q3
+
+    vmov.32         r4, d8[0]
+    vmov.32         r6, d9[0]
+
+    add             r12, r4, r6
+
+    ; Move back to interger registers
+
+skip_dc_pred_up
+
+    cmp             r5, #0
+    beq             skip_dc_pred_left
+
+    sub             r0, r0, #1
+
+    ; Load left row, if it exists
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+
+    add             r12, r12, r3
+    add             r12, r12, r4
+    add             r12, r12, r5
+    add             r12, r12, r6
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+
+    add             r12, r12, r3
+    add             r12, r12, r4
+    add             r12, r12, r5
+    add             r12, r12, r6
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+
+    add             r12, r12, r3
+    add             r12, r12, r4
+    add             r12, r12, r5
+    add             r12, r12, r6
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0]
+
+    add             r12, r12, r3
+    add             r12, r12, r4
+    add             r12, r12, r5
+    add             r12, r12, r6
+
+skip_dc_pred_left
+    add             r7, r7, #3          ; Shift
+    sub             r4, r7, #1
+    mov             r5, #1
+    add             r12, r12, r5, lsl r4
+    mov             r5, r12, lsr r7     ; expected_dc
+
+    vdup.u8         q0, r5
+
+skip_dc_pred_up_left
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+
+    pop             {r4-r8,pc}
+case_v_pred
+    ; Copy down above row
+    sub             r6, r0, r2
+    vld1.8          {q0}, [r6]
+
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    pop             {r4-r8,pc}
+
+case_h_pred
+    ; Load 4x yleft_col
+    sub             r0, r0, #1
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+    vdup.u8         q0, r3
+    vdup.u8         q1, r4
+    vdup.u8         q2, r5
+    vdup.u8         q3, r6
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q1}, [r1]!
+    vst1.u8         {q2}, [r1]!
+    vst1.u8         {q3}, [r1]!
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+    vdup.u8         q0, r3
+    vdup.u8         q1, r4
+    vdup.u8         q2, r5
+    vdup.u8         q3, r6
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q1}, [r1]!
+    vst1.u8         {q2}, [r1]!
+    vst1.u8         {q3}, [r1]!
+
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+    vdup.u8         q0, r3
+    vdup.u8         q1, r4
+    vdup.u8         q2, r5
+    vdup.u8         q3, r6
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q1}, [r1]!
+    vst1.u8         {q2}, [r1]!
+    vst1.u8         {q3}, [r1]!
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+    vdup.u8         q0, r3
+    vdup.u8         q1, r4
+    vdup.u8         q2, r5
+    vdup.u8         q3, r6
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q1}, [r1]!
+    vst1.u8         {q2}, [r1]!
+    vst1.u8         {q3}, [r1]!
+
+    pop             {r4-r8,pc}
+
+case_tm_pred
+    ; Load yabove_row
+    sub             r3, r0, r2
+    vld1.8          {q8}, [r3]
+
+    ; Load ytop_left
+    sub             r3, r3, #1
+    ldrb            r7, [r3]
+
+    vdup.u16        q7, r7
+
+    ; Compute yabove_row - ytop_left
+    mov             r3, #1
+    vdup.u8         q0, r3
+
+    vmull.u8        q4, d16, d0
+    vmull.u8        q5, d17, d0
+
+    vsub.s16        q4, q4, q7
+    vsub.s16        q5, q5, q7
+
+    ; Load 4x yleft_col
+    sub             r0, r0, #1
+    mov             r12, #4
+
+case_tm_pred_loop
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+    vdup.u16        q0, r3
+    vdup.u16        q1, r4
+    vdup.u16        q2, r5
+    vdup.u16        q3, r6
+
+    vqadd.s16       q8, q0, q4
+    vqadd.s16       q9, q0, q5
+
+    vqadd.s16       q10, q1, q4
+    vqadd.s16       q11, q1, q5
+
+    vqadd.s16       q12, q2, q4
+    vqadd.s16       q13, q2, q5
+
+    vqadd.s16       q14, q3, q4
+    vqadd.s16       q15, q3, q5
+
+    vqshrun.s16     d0, q8, #0
+    vqshrun.s16     d1, q9, #0
+
+    vqshrun.s16     d2, q10, #0
+    vqshrun.s16     d3, q11, #0
+
+    vqshrun.s16     d4, q12, #0
+    vqshrun.s16     d5, q13, #0
+
+    vqshrun.s16     d6, q14, #0
+    vqshrun.s16     d7, q15, #0
+
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q1}, [r1]!
+    vst1.u8         {q2}, [r1]!
+    vst1.u8         {q3}, [r1]!
+
+    subs            r12, r12, #1
+    bne             case_tm_pred_loop
+
+    pop             {r4-r8,pc}
+
+    ENDP
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; r0    unsigned char *y_buffer
+; r1    unsigned char *ypred_ptr
+; r2    int y_stride
+; r3    int mode
+; stack int Up
+; stack int Left
+
+|vp8_build_intra_predictors_mby_s_neon_func| PROC
+    push            {r4-r8, lr}
+
+    mov             r1, r0      ;   unsigned char *ypred_ptr = x->dst.y_buffer; //x->Predictor;
+
+    cmp             r3, #0
+    beq             case_dc_pred_s
+    cmp             r3, #1
+    beq             case_v_pred_s
+    cmp             r3, #2
+    beq             case_h_pred_s
+    cmp             r3, #3
+    beq             case_tm_pred_s
+
+case_dc_pred_s
+    ldr             r4, [sp, #24]       ; Up
+    ldr             r5, [sp, #28]       ; Left
+
+    ; Default the DC average to 128
+    mov             r12, #128
+    vdup.u8         q0, r12
+
+    ; Zero out running sum
+    mov             r12, #0
+
+    ; compute shift and jump
+    adds            r7, r4, r5
+    beq             skip_dc_pred_up_left_s
+
+    ; Load above row, if it exists
+    cmp             r4, #0
+    beq             skip_dc_pred_up_s
+
+    sub             r6, r0, r2
+    vld1.8          {q1}, [r6]
+    vpaddl.u8       q2, q1
+    vpaddl.u16      q3, q2
+    vpaddl.u32      q4, q3
+
+    vmov.32         r4, d8[0]
+    vmov.32         r6, d9[0]
+
+    add             r12, r4, r6
+
+    ; Move back to interger registers
+
+skip_dc_pred_up_s
+
+    cmp             r5, #0
+    beq             skip_dc_pred_left_s
+
+    sub             r0, r0, #1
+
+    ; Load left row, if it exists
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+
+    add             r12, r12, r3
+    add             r12, r12, r4
+    add             r12, r12, r5
+    add             r12, r12, r6
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+
+    add             r12, r12, r3
+    add             r12, r12, r4
+    add             r12, r12, r5
+    add             r12, r12, r6
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+
+    add             r12, r12, r3
+    add             r12, r12, r4
+    add             r12, r12, r5
+    add             r12, r12, r6
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0]
+
+    add             r12, r12, r3
+    add             r12, r12, r4
+    add             r12, r12, r5
+    add             r12, r12, r6
+
+skip_dc_pred_left_s
+    add             r7, r7, #3          ; Shift
+    sub             r4, r7, #1
+    mov             r5, #1
+    add             r12, r12, r5, lsl r4
+    mov             r5, r12, lsr r7     ; expected_dc
+
+    vdup.u8         q0, r5
+
+skip_dc_pred_up_left_s
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+
+    pop             {r4-r8,pc}
+case_v_pred_s
+    ; Copy down above row
+    sub             r6, r0, r2
+    vld1.8          {q0}, [r6]
+
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    pop             {r4-r8,pc}
+
+case_h_pred_s
+    ; Load 4x yleft_col
+    sub             r0, r0, #1
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+    vdup.u8         q0, r3
+    vdup.u8         q1, r4
+    vdup.u8         q2, r5
+    vdup.u8         q3, r6
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q1}, [r1], r2
+    vst1.u8         {q2}, [r1], r2
+    vst1.u8         {q3}, [r1], r2
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+    vdup.u8         q0, r3
+    vdup.u8         q1, r4
+    vdup.u8         q2, r5
+    vdup.u8         q3, r6
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q1}, [r1], r2
+    vst1.u8         {q2}, [r1], r2
+    vst1.u8         {q3}, [r1], r2
+
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+    vdup.u8         q0, r3
+    vdup.u8         q1, r4
+    vdup.u8         q2, r5
+    vdup.u8         q3, r6
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q1}, [r1], r2
+    vst1.u8         {q2}, [r1], r2
+    vst1.u8         {q3}, [r1], r2
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+    vdup.u8         q0, r3
+    vdup.u8         q1, r4
+    vdup.u8         q2, r5
+    vdup.u8         q3, r6
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q1}, [r1], r2
+    vst1.u8         {q2}, [r1], r2
+    vst1.u8         {q3}, [r1], r2
+
+    pop             {r4-r8,pc}
+
+case_tm_pred_s
+    ; Load yabove_row
+    sub             r3, r0, r2
+    vld1.8          {q8}, [r3]
+
+    ; Load ytop_left
+    sub             r3, r3, #1
+    ldrb            r7, [r3]
+
+    vdup.u16        q7, r7
+
+    ; Compute yabove_row - ytop_left
+    mov             r3, #1
+    vdup.u8         q0, r3
+
+    vmull.u8        q4, d16, d0
+    vmull.u8        q5, d17, d0
+
+    vsub.s16        q4, q4, q7
+    vsub.s16        q5, q5, q7
+
+    ; Load 4x yleft_col
+    sub             r0, r0, #1
+    mov             r12, #4
+
+case_tm_pred_loop_s
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+    vdup.u16        q0, r3
+    vdup.u16        q1, r4
+    vdup.u16        q2, r5
+    vdup.u16        q3, r6
+
+    vqadd.s16       q8, q0, q4
+    vqadd.s16       q9, q0, q5
+
+    vqadd.s16       q10, q1, q4
+    vqadd.s16       q11, q1, q5
+
+    vqadd.s16       q12, q2, q4
+    vqadd.s16       q13, q2, q5
+
+    vqadd.s16       q14, q3, q4
+    vqadd.s16       q15, q3, q5
+
+    vqshrun.s16     d0, q8, #0
+    vqshrun.s16     d1, q9, #0
+
+    vqshrun.s16     d2, q10, #0
+    vqshrun.s16     d3, q11, #0
+
+    vqshrun.s16     d4, q12, #0
+    vqshrun.s16     d5, q13, #0
+
+    vqshrun.s16     d6, q14, #0
+    vqshrun.s16     d7, q15, #0
+
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q1}, [r1], r2
+    vst1.u8         {q2}, [r1], r2
+    vst1.u8         {q3}, [r1], r2
+
+    subs            r12, r12, #1
+    bne             case_tm_pred_loop_s
+
+    pop             {r4-r8,pc}
+
+    ENDP
+
+
+    END
diff --git a/vp8/common/arm/neon/copymem16x16_neon.asm b/vp8/common/arm/neon/copymem16x16_neon.asm
new file mode 100644 (file)
index 0000000..bda4b96
--- /dev/null
@@ -0,0 +1,59 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_copy_mem16x16_neon|
+    ; ARM
+    ; REQUIRE8
+    ; PRESERVE8
+
+    AREA    Block, CODE, READONLY ; name this block of code
+;void copy_mem16x16_neon( unsigned char *src, int src_stride, unsigned char *dst, int dst_stride)
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+|vp8_copy_mem16x16_neon| PROC
+
+    vld1.u8     {q0}, [r0], r1
+    vld1.u8     {q1}, [r0], r1
+    vld1.u8     {q2}, [r0], r1
+    vst1.u8     {q0}, [r2], r3
+    vld1.u8     {q3}, [r0], r1
+    vst1.u8     {q1}, [r2], r3
+    vld1.u8     {q4}, [r0], r1
+    vst1.u8     {q2}, [r2], r3
+    vld1.u8     {q5}, [r0], r1
+    vst1.u8     {q3}, [r2], r3
+    vld1.u8     {q6}, [r0], r1
+    vst1.u8     {q4}, [r2], r3
+    vld1.u8     {q7}, [r0], r1
+    vst1.u8     {q5}, [r2], r3
+    vld1.u8     {q8}, [r0], r1
+    vst1.u8     {q6}, [r2], r3
+    vld1.u8     {q9}, [r0], r1
+    vst1.u8     {q7}, [r2], r3
+    vld1.u8     {q10}, [r0], r1
+    vst1.u8     {q8}, [r2], r3
+    vld1.u8     {q11}, [r0], r1
+    vst1.u8     {q9}, [r2], r3
+    vld1.u8     {q12}, [r0], r1
+    vst1.u8     {q10}, [r2], r3
+    vld1.u8     {q13}, [r0], r1
+    vst1.u8     {q11}, [r2], r3
+    vld1.u8     {q14}, [r0], r1
+    vst1.u8     {q12}, [r2], r3
+    vld1.u8     {q15}, [r0], r1
+    vst1.u8     {q13}, [r2], r3
+    vst1.u8     {q14}, [r2], r3
+    vst1.u8     {q15}, [r2], r3
+
+    mov     pc, lr
+
+    ENDP  ; |vp8_copy_mem16x16_neon|
+
+    END
diff --git a/vp8/common/arm/neon/copymem8x4_neon.asm b/vp8/common/arm/neon/copymem8x4_neon.asm
new file mode 100644 (file)
index 0000000..35c0f67
--- /dev/null
@@ -0,0 +1,34 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_copy_mem8x4_neon|
+    ; ARM
+    ; REQUIRE8
+    ; PRESERVE8
+
+    AREA    Block, CODE, READONLY ; name this block of code
+;void copy_mem8x4_neon( unsigned char *src, int src_stride, unsigned char *dst, int dst_stride)
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+|vp8_copy_mem8x4_neon| PROC
+    vld1.u8     {d0}, [r0], r1
+    vld1.u8     {d1}, [r0], r1
+    vst1.u8     {d0}, [r2], r3
+    vld1.u8     {d2}, [r0], r1
+    vst1.u8     {d1}, [r2], r3
+    vld1.u8     {d3}, [r0], r1
+    vst1.u8     {d2}, [r2], r3
+    vst1.u8     {d3}, [r2], r3
+
+    mov     pc, lr
+
+    ENDP  ; |vp8_copy_mem8x4_neon|
+
+    END
diff --git a/vp8/common/arm/neon/copymem8x8_neon.asm b/vp8/common/arm/neon/copymem8x8_neon.asm
new file mode 100644 (file)
index 0000000..1f5b941
--- /dev/null
@@ -0,0 +1,43 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_copy_mem8x8_neon|
+    ; ARM
+    ; REQUIRE8
+    ; PRESERVE8
+
+    AREA    Block, CODE, READONLY ; name this block of code
+;void copy_mem8x8_neon( unsigned char *src, int src_stride, unsigned char *dst, int dst_stride)
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+|vp8_copy_mem8x8_neon| PROC
+
+    vld1.u8     {d0}, [r0], r1
+    vld1.u8     {d1}, [r0], r1
+    vst1.u8     {d0}, [r2], r3
+    vld1.u8     {d2}, [r0], r1
+    vst1.u8     {d1}, [r2], r3
+    vld1.u8     {d3}, [r0], r1
+    vst1.u8     {d2}, [r2], r3
+    vld1.u8     {d4}, [r0], r1
+    vst1.u8     {d3}, [r2], r3
+    vld1.u8     {d5}, [r0], r1
+    vst1.u8     {d4}, [r2], r3
+    vld1.u8     {d6}, [r0], r1
+    vst1.u8     {d5}, [r2], r3
+    vld1.u8     {d7}, [r0], r1
+    vst1.u8     {d6}, [r2], r3
+    vst1.u8     {d7}, [r2], r3
+
+    mov     pc, lr
+
+    ENDP  ; |vp8_copy_mem8x8_neon|
+
+    END
diff --git a/vp8/common/arm/neon/dc_only_idct_add_neon.asm b/vp8/common/arm/neon/dc_only_idct_add_neon.asm
new file mode 100644 (file)
index 0000000..65a4680
--- /dev/null
@@ -0,0 +1,54 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license and patent
+;  grant that can be found in the LICENSE file in the root of the source
+;  tree. All contributing project authors may be found in the AUTHORS
+;  file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_dc_only_idct_add_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+;void vp8_dc_only_idct_add_c(short input_dc, unsigned char *pred_ptr,
+;                            int pred_stride, unsigned char *dst_ptr,
+;                            int dst_stride)
+
+; r0  input_dc
+; r1  pred_ptr
+; r2  pred_stride
+; r3  dst_ptr
+; sp  dst_stride
+
+|vp8_dc_only_idct_add_neon| PROC
+    add             r0, r0, #4
+    asr             r0, r0, #3
+    ldr             r12, [sp]
+    vdup.16         q0, r0
+
+    vld1.32         {d2[0]}, [r1], r2
+    vld1.32         {d2[1]}, [r1], r2
+    vld1.32         {d4[0]}, [r1], r2
+    vld1.32         {d4[1]}, [r1]
+
+    vaddw.u8        q1, q0, d2
+    vaddw.u8        q2, q0, d4
+
+    vqmovun.s16     d2, q1
+    vqmovun.s16     d4, q2
+
+    vst1.32         {d2[0]}, [r3], r12
+    vst1.32         {d2[1]}, [r3], r12
+    vst1.32         {d4[0]}, [r3], r12
+    vst1.32         {d4[1]}, [r3]
+    bx              lr
+
+    ENDP
+
+    END
diff --git a/vp8/common/arm/neon/dequant_idct_neon.asm b/vp8/common/arm/neon/dequant_idct_neon.asm
new file mode 100644 (file)
index 0000000..602cce6
--- /dev/null
@@ -0,0 +1,131 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_dequant_idct_add_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;void vp8_dequant_idct_add_neon(short *input, short *dq,
+;                           unsigned char *dest, int stride)
+; r0    short *input,
+; r1    short *dq,
+; r2    unsigned char *dest
+; r3    int stride
+
+|vp8_dequant_idct_add_neon| PROC
+    vld1.16         {q3, q4}, [r0]
+    vld1.16         {q5, q6}, [r1]
+
+    add             r1, r2, r3              ; r1 = dest + stride
+    lsl             r3, #1                  ; 2x stride
+
+    vld1.32         {d14[0]}, [r2], r3
+    vld1.32         {d14[1]}, [r1], r3
+    vld1.32         {d15[0]}, [r2]
+    vld1.32         {d15[1]}, [r1]
+
+    adr             r12, cospi8sqrt2minus1  ; pointer to the first constant
+
+    vmul.i16        q1, q3, q5              ;input for short_idct4x4llm_neon
+    vmul.i16        q2, q4, q6
+
+;|short_idct4x4llm_neon| PROC
+    vld1.16         {d0}, [r12]
+    vswp            d3, d4                  ;q2(vp[4] vp[12])
+
+    vqdmulh.s16     q3, q2, d0[2]
+    vqdmulh.s16     q4, q2, d0[0]
+
+    vqadd.s16       d12, d2, d3             ;a1
+    vqsub.s16       d13, d2, d3             ;b1
+
+    vshr.s16        q3, q3, #1
+    vshr.s16        q4, q4, #1
+
+    vqadd.s16       q3, q3, q2
+    vqadd.s16       q4, q4, q2
+
+    vqsub.s16       d10, d6, d9             ;c1
+    vqadd.s16       d11, d7, d8             ;d1
+
+    vqadd.s16       d2, d12, d11
+    vqadd.s16       d3, d13, d10
+    vqsub.s16       d4, d13, d10
+    vqsub.s16       d5, d12, d11
+
+    vtrn.32         d2, d4
+    vtrn.32         d3, d5
+    vtrn.16         d2, d3
+    vtrn.16         d4, d5
+
+; memset(input, 0, 32) -- 32bytes
+    vmov.i16        q14, #0
+
+    vswp            d3, d4
+    vqdmulh.s16     q3, q2, d0[2]
+    vqdmulh.s16     q4, q2, d0[0]
+
+    vqadd.s16       d12, d2, d3             ;a1
+    vqsub.s16       d13, d2, d3             ;b1
+
+    vmov            q15, q14
+
+    vshr.s16        q3, q3, #1
+    vshr.s16        q4, q4, #1
+
+    vqadd.s16       q3, q3, q2
+    vqadd.s16       q4, q4, q2
+
+    vqsub.s16       d10, d6, d9             ;c1
+    vqadd.s16       d11, d7, d8             ;d1
+
+    vqadd.s16       d2, d12, d11
+    vqadd.s16       d3, d13, d10
+    vqsub.s16       d4, d13, d10
+    vqsub.s16       d5, d12, d11
+
+    vst1.16         {q14, q15}, [r0]
+
+    vrshr.s16       d2, d2, #3
+    vrshr.s16       d3, d3, #3
+    vrshr.s16       d4, d4, #3
+    vrshr.s16       d5, d5, #3
+
+    vtrn.32         d2, d4
+    vtrn.32         d3, d5
+    vtrn.16         d2, d3
+    vtrn.16         d4, d5
+
+    vaddw.u8        q1, q1, d14
+    vaddw.u8        q2, q2, d15
+
+    sub             r2, r2, r3
+    sub             r1, r1, r3
+
+    vqmovun.s16     d0, q1
+    vqmovun.s16     d1, q2
+
+    vst1.32         {d0[0]}, [r2], r3
+    vst1.32         {d0[1]}, [r1], r3
+    vst1.32         {d1[0]}, [r2]
+    vst1.32         {d1[1]}, [r1]
+
+    bx             lr
+
+    ENDP           ; |vp8_dequant_idct_add_neon|
+
+; Constant Pool
+cospi8sqrt2minus1 DCD 0x4e7b4e7b
+sinpi8sqrt2       DCD 0x8a8c8a8c
+
+    END
diff --git a/vp8/common/arm/neon/dequantizeb_neon.asm b/vp8/common/arm/neon/dequantizeb_neon.asm
new file mode 100644 (file)
index 0000000..c8e0c31
--- /dev/null
@@ -0,0 +1,34 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_dequantize_b_loop_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; r0    short *Q,
+; r1    short *DQC
+; r2    short *DQ
+|vp8_dequantize_b_loop_neon| PROC
+    vld1.16         {q0, q1}, [r0]
+    vld1.16         {q2, q3}, [r1]
+
+    vmul.i16        q4, q0, q2
+    vmul.i16        q5, q1, q3
+
+    vst1.16         {q4, q5}, [r2]
+
+    bx             lr
+
+    ENDP
+
+    END
diff --git a/vp8/common/arm/neon/idct_blk_neon.c b/vp8/common/arm/neon/idct_blk_neon.c
new file mode 100644 (file)
index 0000000..ee7f223
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+
+/* place these declarations here because we don't want to maintain them
+ * outside of this scope
+ */
+void idct_dequant_full_2x_neon(short *q, short *dq,
+                               unsigned char *dst, int stride);
+void idct_dequant_0_2x_neon(short *q, short dq,
+                            unsigned char *dst, int stride);
+
+
+void vp8_dequant_idct_add_y_block_neon(short *q, short *dq,
+                                       unsigned char *dst,
+                                       int stride, char *eobs)
+{
+    int i;
+
+    for (i = 0; i < 4; i++)
+    {
+        if (((short *)(eobs))[0])
+        {
+            if (((short *)eobs)[0] & 0xfefe)
+                idct_dequant_full_2x_neon (q, dq, dst, stride);
+            else
+                idct_dequant_0_2x_neon (q, dq[0], dst, stride);
+        }
+
+        if (((short *)(eobs))[1])
+        {
+            if (((short *)eobs)[1] & 0xfefe)
+                idct_dequant_full_2x_neon (q+32, dq, dst+8, stride);
+            else
+                idct_dequant_0_2x_neon (q+32, dq[0], dst+8, stride);
+        }
+        q    += 64;
+        dst  += 4*stride;
+        eobs += 4;
+    }
+}
+
+void vp8_dequant_idct_add_uv_block_neon(short *q, short *dq,
+                                        unsigned char *dstu,
+                                        unsigned char *dstv,
+                                        int stride, char *eobs)
+{
+    if (((short *)(eobs))[0])
+    {
+        if (((short *)eobs)[0] & 0xfefe)
+            idct_dequant_full_2x_neon (q, dq, dstu, stride);
+        else
+            idct_dequant_0_2x_neon (q, dq[0], dstu, stride);
+    }
+
+    q    += 32;
+    dstu += 4*stride;
+
+    if (((short *)(eobs))[1])
+    {
+        if (((short *)eobs)[1] & 0xfefe)
+            idct_dequant_full_2x_neon (q, dq, dstu, stride);
+        else
+            idct_dequant_0_2x_neon (q, dq[0], dstu, stride);
+    }
+
+    q += 32;
+
+    if (((short *)(eobs))[2])
+    {
+        if (((short *)eobs)[2] & 0xfefe)
+            idct_dequant_full_2x_neon (q, dq, dstv, stride);
+        else
+            idct_dequant_0_2x_neon (q, dq[0], dstv, stride);
+    }
+
+    q    += 32;
+    dstv += 4*stride;
+
+    if (((short *)(eobs))[3])
+    {
+        if (((short *)eobs)[3] & 0xfefe)
+            idct_dequant_full_2x_neon (q, dq, dstv, stride);
+        else
+            idct_dequant_0_2x_neon (q, dq[0], dstv, stride);
+    }
+}
diff --git a/vp8/common/arm/neon/idct_dequant_0_2x_neon.asm b/vp8/common/arm/neon/idct_dequant_0_2x_neon.asm
new file mode 100644 (file)
index 0000000..6c29c55
--- /dev/null
@@ -0,0 +1,79 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license and patent
+;  grant that can be found in the LICENSE file in the root of the source
+;  tree. All contributing project authors may be found in the AUTHORS
+;  file in the root of the source tree.
+;
+
+
+    EXPORT  |idct_dequant_0_2x_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;void idct_dequant_0_2x_neon(short *q, short dq,
+;                            unsigned char *dst, int stride);
+; r0   *q
+; r1   dq
+; r2   *dst
+; r3   stride
+|idct_dequant_0_2x_neon| PROC
+    push            {r4, r5}
+
+    add             r12, r2, #4
+    vld1.32         {d2[0]}, [r2], r3
+    vld1.32         {d8[0]}, [r12], r3
+    vld1.32         {d2[1]}, [r2], r3
+    vld1.32         {d8[1]}, [r12], r3
+    vld1.32         {d4[0]}, [r2], r3
+    vld1.32         {d10[0]}, [r12], r3
+    vld1.32         {d4[1]}, [r2], r3
+    vld1.32         {d10[1]}, [r12], r3
+
+    ldrh            r12, [r0]               ; lo q
+    ldrh            r4, [r0, #32]           ; hi q
+    mov             r5, #0
+    strh            r5, [r0]
+    strh            r5, [r0, #32]
+
+    sxth            r12, r12                ; lo
+    mul             r0, r12, r1
+    add             r0, r0, #4
+    asr             r0, r0, #3
+    vdup.16         q0, r0
+    sxth            r4, r4                  ; hi
+    mul             r0, r4, r1
+    add             r0, r0, #4
+    asr             r0, r0, #3
+    vdup.16         q3, r0
+
+    vaddw.u8        q1, q0, d2              ; lo
+    vaddw.u8        q2, q0, d4
+    vaddw.u8        q4, q3, d8              ; hi
+    vaddw.u8        q5, q3, d10
+
+    sub             r2, r2, r3, lsl #2      ; dst - 4*stride
+    add             r0, r2, #4
+
+    vqmovun.s16     d2, q1                  ; lo
+    vqmovun.s16     d4, q2
+    vqmovun.s16     d8, q4                  ; hi
+    vqmovun.s16     d10, q5
+
+    vst1.32         {d2[0]}, [r2], r3       ; lo
+    vst1.32         {d8[0]}, [r0], r3       ; hi
+    vst1.32         {d2[1]}, [r2], r3
+    vst1.32         {d8[1]}, [r0], r3
+    vst1.32         {d4[0]}, [r2], r3
+    vst1.32         {d10[0]}, [r0], r3
+    vst1.32         {d4[1]}, [r2]
+    vst1.32         {d10[1]}, [r0]
+
+    pop             {r4, r5}
+    bx              lr
+
+    ENDP            ; |idct_dequant_0_2x_neon|
+    END
diff --git a/vp8/common/arm/neon/idct_dequant_full_2x_neon.asm b/vp8/common/arm/neon/idct_dequant_full_2x_neon.asm
new file mode 100644 (file)
index 0000000..d5dce63
--- /dev/null
@@ -0,0 +1,196 @@
+;
+;  Copyright (c) 2010 The Webm project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |idct_dequant_full_2x_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;void idct_dequant_full_2x_neon(short *q, short *dq,
+;                               unsigned char *dst, int stride);
+; r0    *q,
+; r1    *dq,
+; r2    *dst
+; r3    stride
+|idct_dequant_full_2x_neon| PROC
+    vld1.16         {q0, q1}, [r1]          ; dq (same l/r)
+    vld1.16         {q2, q3}, [r0]          ; l q
+    add             r0, r0, #32
+    vld1.16         {q4, q5}, [r0]          ; r q
+    add             r12, r2, #4
+
+    ; interleave the predictors
+    vld1.32         {d28[0]}, [r2],  r3     ; l pre
+    vld1.32         {d28[1]}, [r12], r3     ; r pre
+    vld1.32         {d29[0]}, [r2],  r3
+    vld1.32         {d29[1]}, [r12], r3
+    vld1.32         {d30[0]}, [r2],  r3
+    vld1.32         {d30[1]}, [r12], r3
+    vld1.32         {d31[0]}, [r2],  r3
+    vld1.32         {d31[1]}, [r12]
+
+    adr             r1, cospi8sqrt2minus1   ; pointer to the first constant
+
+    ; dequant: q[i] = q[i] * dq[i]
+    vmul.i16        q2, q2, q0
+    vmul.i16        q3, q3, q1
+    vmul.i16        q4, q4, q0
+    vmul.i16        q5, q5, q1
+
+    vld1.16         {d0}, [r1]
+
+    ; q2: l0r0  q3: l8r8
+    ; q4: l4r4  q5: l12r12
+    vswp            d5, d8
+    vswp            d7, d10
+
+    ; _CONSTANTS_ * 4,12 >> 16
+    ; q6:  4 * sinpi : c1/temp1
+    ; q7: 12 * sinpi : d1/temp2
+    ; q8:  4 * cospi
+    ; q9: 12 * cospi
+    vqdmulh.s16     q6, q4, d0[2]           ; sinpi8sqrt2
+    vqdmulh.s16     q7, q5, d0[2]
+    vqdmulh.s16     q8, q4, d0[0]           ; cospi8sqrt2minus1
+    vqdmulh.s16     q9, q5, d0[0]
+
+    vqadd.s16       q10, q2, q3             ; a1 = 0 + 8
+    vqsub.s16       q11, q2, q3             ; b1 = 0 - 8
+
+    ; vqdmulh only accepts signed values. this was a problem because
+    ; our constant had the high bit set, and was treated as a negative value.
+    ; vqdmulh also doubles the value before it shifts by 16. we need to
+    ; compensate for this. in the case of sinpi8sqrt2, the lowest bit is 0,
+    ; so we can shift the constant without losing precision. this avoids
+    ; shift again afterward, but also avoids the sign issue. win win!
+    ; for cospi8sqrt2minus1 the lowest bit is 1, so we lose precision if we
+    ; pre-shift it
+    vshr.s16        q8, q8, #1
+    vshr.s16        q9, q9, #1
+
+    ; q4:  4 +  4 * cospi : d1/temp1
+    ; q5: 12 + 12 * cospi : c1/temp2
+    vqadd.s16       q4, q4, q8
+    vqadd.s16       q5, q5, q9
+
+    ; c1 = temp1 - temp2
+    ; d1 = temp1 + temp2
+    vqsub.s16       q2, q6, q5
+    vqadd.s16       q3, q4, q7
+
+    ; [0]: a1+d1
+    ; [1]: b1+c1
+    ; [2]: b1-c1
+    ; [3]: a1-d1
+    vqadd.s16       q4, q10, q3
+    vqadd.s16       q5, q11, q2
+    vqsub.s16       q6, q11, q2
+    vqsub.s16       q7, q10, q3
+
+    ; rotate
+    vtrn.32         q4, q6
+    vtrn.32         q5, q7
+    vtrn.16         q4, q5
+    vtrn.16         q6, q7
+    ; idct loop 2
+    ; q4: l 0, 4, 8,12 r 0, 4, 8,12
+    ; q5: l 1, 5, 9,13 r 1, 5, 9,13
+    ; q6: l 2, 6,10,14 r 2, 6,10,14
+    ; q7: l 3, 7,11,15 r 3, 7,11,15
+
+    ; q8:  1 * sinpi : c1/temp1
+    ; q9:  3 * sinpi : d1/temp2
+    ; q10: 1 * cospi
+    ; q11: 3 * cospi
+    vqdmulh.s16     q8, q5, d0[2]           ; sinpi8sqrt2
+    vqdmulh.s16     q9, q7, d0[2]
+    vqdmulh.s16     q10, q5, d0[0]          ; cospi8sqrt2minus1
+    vqdmulh.s16     q11, q7, d0[0]
+
+    vqadd.s16       q2, q4, q6             ; a1 = 0 + 2
+    vqsub.s16       q3, q4, q6             ; b1 = 0 - 2
+
+    ; see note on shifting above
+    vshr.s16        q10, q10, #1
+    vshr.s16        q11, q11, #1
+
+    ; q10: 1 + 1 * cospi : d1/temp1
+    ; q11: 3 + 3 * cospi : c1/temp2
+    vqadd.s16       q10, q5, q10
+    vqadd.s16       q11, q7, q11
+
+    ; q8: c1 = temp1 - temp2
+    ; q9: d1 = temp1 + temp2
+    vqsub.s16       q8, q8, q11
+    vqadd.s16       q9, q10, q9
+
+    ; a1+d1
+    ; b1+c1
+    ; b1-c1
+    ; a1-d1
+    vqadd.s16       q4, q2, q9
+    vqadd.s16       q5, q3, q8
+    vqsub.s16       q6, q3, q8
+    vqsub.s16       q7, q2, q9
+
+    ; +4 >> 3 (rounding)
+    vrshr.s16       q4, q4, #3              ; lo
+    vrshr.s16       q5, q5, #3
+    vrshr.s16       q6, q6, #3              ; hi
+    vrshr.s16       q7, q7, #3
+
+    vtrn.32         q4, q6
+    vtrn.32         q5, q7
+    vtrn.16         q4, q5
+    vtrn.16         q6, q7
+
+    ; adding pre
+    ; input is still packed. pre was read interleaved
+    vaddw.u8        q4, q4, d28
+    vaddw.u8        q5, q5, d29
+    vaddw.u8        q6, q6, d30
+    vaddw.u8        q7, q7, d31
+
+    vmov.i16        q14, #0
+    vmov            q15, q14
+    vst1.16         {q14, q15}, [r0]        ; write over high input
+    sub             r0, r0, #32
+    vst1.16         {q14, q15}, [r0]        ; write over low input
+
+    sub             r2, r2, r3, lsl #2      ; dst - 4*stride
+    add             r1, r2, #4              ; hi
+
+    ;saturate and narrow
+    vqmovun.s16     d0, q4                  ; lo
+    vqmovun.s16     d1, q5
+    vqmovun.s16     d2, q6                  ; hi
+    vqmovun.s16     d3, q7
+
+    vst1.32         {d0[0]}, [r2], r3       ; lo
+    vst1.32         {d0[1]}, [r1], r3       ; hi
+    vst1.32         {d1[0]}, [r2], r3
+    vst1.32         {d1[1]}, [r1], r3
+    vst1.32         {d2[0]}, [r2], r3
+    vst1.32         {d2[1]}, [r1], r3
+    vst1.32         {d3[0]}, [r2]
+    vst1.32         {d3[1]}, [r1]
+
+    bx             lr
+
+    ENDP           ; |idct_dequant_full_2x_neon|
+
+; Constant Pool
+cospi8sqrt2minus1 DCD 0x4e7b
+; because the lowest bit in 0x8a8c is 0, we can pre-shift this
+sinpi8sqrt2       DCD 0x4546
+
+    END
diff --git a/vp8/common/arm/neon/iwalsh_neon.asm b/vp8/common/arm/neon/iwalsh_neon.asm
new file mode 100644 (file)
index 0000000..e8ea2a6
--- /dev/null
@@ -0,0 +1,87 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+    EXPORT  |vp8_short_inv_walsh4x4_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+
+;short vp8_short_inv_walsh4x4_neon(short *input, short *mb_dqcoeff)
+|vp8_short_inv_walsh4x4_neon| PROC
+
+    ; read in all four lines of values: d0->d3
+    vld1.i16 {q0-q1}, [r0@128]
+
+    ; first for loop
+    vadd.s16 d4, d0, d3 ;a = [0] + [12]
+    vadd.s16 d6, d1, d2 ;b = [4] + [8]
+    vsub.s16 d5, d0, d3 ;d = [0] - [12]
+    vsub.s16 d7, d1, d2 ;c = [4] - [8]
+
+    vadd.s16 q0, q2, q3 ; a+b d+c
+    vsub.s16 q1, q2, q3 ; a-b d-c
+
+    vtrn.32 d0, d2 ;d0:  0  1  8  9
+                   ;d2:  2  3 10 11
+    vtrn.32 d1, d3 ;d1:  4  5 12 13
+                   ;d3:  6  7 14 15
+
+    vtrn.16 d0, d1 ;d0:  0  4  8 12
+                   ;d1:  1  5  9 13
+    vtrn.16 d2, d3 ;d2:  2  6 10 14
+                   ;d3:  3  7 11 15
+
+    ; second for loop
+
+    vadd.s16 d4, d0, d3 ;a = [0] + [3]
+    vadd.s16 d6, d1, d2 ;b = [1] + [2]
+    vsub.s16 d5, d0, d3 ;d = [0] - [3]
+    vsub.s16 d7, d1, d2 ;c = [1] - [2]
+
+    vmov.i16 q8, #3
+
+    vadd.s16 q0, q2, q3 ; a+b d+c
+    vsub.s16 q1, q2, q3 ; a-b d-c
+
+    vadd.i16 q0, q0, q8 ;e/f += 3
+    vadd.i16 q1, q1, q8 ;g/h += 3
+
+    vshr.s16 q0, q0, #3 ;e/f >> 3
+    vshr.s16 q1, q1, #3 ;g/h >> 3
+
+    mov      r2, #64
+    add      r3, r1, #32
+
+    vst1.i16 d0[0], [r1],r2
+    vst1.i16 d1[0], [r3],r2
+    vst1.i16 d2[0], [r1],r2
+    vst1.i16 d3[0], [r3],r2
+
+    vst1.i16 d0[1], [r1],r2
+    vst1.i16 d1[1], [r3],r2
+    vst1.i16 d2[1], [r1],r2
+    vst1.i16 d3[1], [r3],r2
+
+    vst1.i16 d0[2], [r1],r2
+    vst1.i16 d1[2], [r3],r2
+    vst1.i16 d2[2], [r1],r2
+    vst1.i16 d3[2], [r3],r2
+
+    vst1.i16 d0[3], [r1],r2
+    vst1.i16 d1[3], [r3],r2
+    vst1.i16 d2[3], [r1]
+    vst1.i16 d3[3], [r3]
+
+    bx lr
+    ENDP    ; |vp8_short_inv_walsh4x4_neon|
+
+    END
diff --git a/vp8/common/arm/neon/loopfilter_neon.asm b/vp8/common/arm/neon/loopfilter_neon.asm
new file mode 100644 (file)
index 0000000..e44be0a
--- /dev/null
@@ -0,0 +1,397 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_loop_filter_horizontal_edge_y_neon|
+    EXPORT  |vp8_loop_filter_horizontal_edge_uv_neon|
+    EXPORT  |vp8_loop_filter_vertical_edge_y_neon|
+    EXPORT  |vp8_loop_filter_vertical_edge_uv_neon|
+    ARM
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    unsigned char *src
+; r1    int pitch
+; r2    unsigned char blimit
+; r3    unsigned char limit
+; sp    unsigned char thresh,
+|vp8_loop_filter_horizontal_edge_y_neon| PROC
+    push        {lr}
+    vdup.u8     q0, r2                     ; duplicate blimit
+    vdup.u8     q1, r3                     ; duplicate limit
+    sub         r2, r0, r1, lsl #2         ; move src pointer down by 4 lines
+    ldr         r3, [sp, #4]               ; load thresh
+    add         r12, r2, r1
+    add         r1, r1, r1
+
+    vdup.u8     q2, r3                     ; duplicate thresh
+
+    vld1.u8     {q3}, [r2@128], r1              ; p3
+    vld1.u8     {q4}, [r12@128], r1             ; p2
+    vld1.u8     {q5}, [r2@128], r1              ; p1
+    vld1.u8     {q6}, [r12@128], r1             ; p0
+    vld1.u8     {q7}, [r2@128], r1              ; q0
+    vld1.u8     {q8}, [r12@128], r1             ; q1
+    vld1.u8     {q9}, [r2@128]                  ; q2
+    vld1.u8     {q10}, [r12@128]                ; q3
+
+    sub         r2, r2, r1, lsl #1
+    sub         r12, r12, r1, lsl #1
+
+    bl          vp8_loop_filter_neon
+
+    vst1.u8     {q5}, [r2@128], r1              ; store op1
+    vst1.u8     {q6}, [r12@128], r1             ; store op0
+    vst1.u8     {q7}, [r2@128], r1              ; store oq0
+    vst1.u8     {q8}, [r12@128], r1             ; store oq1
+
+    pop         {pc}
+    ENDP        ; |vp8_loop_filter_horizontal_edge_y_neon|
+
+
+; r0    unsigned char *u,
+; r1    int pitch,
+; r2    unsigned char blimit
+; r3    unsigned char limit
+; sp    unsigned char thresh,
+; sp+4  unsigned char *v
+|vp8_loop_filter_horizontal_edge_uv_neon| PROC
+    push        {lr}
+    vdup.u8     q0, r2                      ; duplicate blimit
+    vdup.u8     q1, r3                      ; duplicate limit
+    ldr         r12, [sp, #4]               ; load thresh
+    ldr         r2, [sp, #8]                ; load v ptr
+    vdup.u8     q2, r12                     ; duplicate thresh
+
+    sub         r3, r0, r1, lsl #2          ; move u pointer down by 4 lines
+    sub         r12, r2, r1, lsl #2         ; move v pointer down by 4 lines
+
+    vld1.u8     {d6}, [r3@64], r1              ; p3
+    vld1.u8     {d7}, [r12@64], r1             ; p3
+    vld1.u8     {d8}, [r3@64], r1              ; p2
+    vld1.u8     {d9}, [r12@64], r1             ; p2
+    vld1.u8     {d10}, [r3@64], r1             ; p1
+    vld1.u8     {d11}, [r12@64], r1            ; p1
+    vld1.u8     {d12}, [r3@64], r1             ; p0
+    vld1.u8     {d13}, [r12@64], r1            ; p0
+    vld1.u8     {d14}, [r3@64], r1             ; q0
+    vld1.u8     {d15}, [r12@64], r1            ; q0
+    vld1.u8     {d16}, [r3@64], r1             ; q1
+    vld1.u8     {d17}, [r12@64], r1            ; q1
+    vld1.u8     {d18}, [r3@64], r1             ; q2
+    vld1.u8     {d19}, [r12@64], r1            ; q2
+    vld1.u8     {d20}, [r3@64]                 ; q3
+    vld1.u8     {d21}, [r12@64]                ; q3
+
+    bl          vp8_loop_filter_neon
+
+    sub         r0, r0, r1, lsl #1
+    sub         r2, r2, r1, lsl #1
+
+    vst1.u8     {d10}, [r0@64], r1             ; store u op1
+    vst1.u8     {d11}, [r2@64], r1             ; store v op1
+    vst1.u8     {d12}, [r0@64], r1             ; store u op0
+    vst1.u8     {d13}, [r2@64], r1             ; store v op0
+    vst1.u8     {d14}, [r0@64], r1             ; store u oq0
+    vst1.u8     {d15}, [r2@64], r1             ; store v oq0
+    vst1.u8     {d16}, [r0@64]                 ; store u oq1
+    vst1.u8     {d17}, [r2@64]                 ; store v oq1
+
+    pop         {pc}
+    ENDP        ; |vp8_loop_filter_horizontal_edge_uv_neon|
+
+; void vp8_loop_filter_vertical_edge_y_neon(unsigned char *src, int pitch,
+;                                           const signed char *flimit,
+;                                           const signed char *limit,
+;                                           const signed char *thresh,
+;                                           int count)
+; r0    unsigned char *src
+; r1    int pitch
+; r2    unsigned char blimit
+; r3    unsigned char limit
+; sp    unsigned char thresh,
+
+|vp8_loop_filter_vertical_edge_y_neon| PROC
+    push        {lr}
+    vdup.u8     q0, r2                     ; duplicate blimit
+    vdup.u8     q1, r3                     ; duplicate limit
+    sub         r2, r0, #4                 ; src ptr down by 4 columns
+    add         r1, r1, r1
+    ldr         r3, [sp, #4]               ; load thresh
+    add         r12, r2, r1, asr #1
+
+    vld1.u8     {d6}, [r2], r1
+    vld1.u8     {d8}, [r12], r1
+    vld1.u8     {d10}, [r2], r1
+    vld1.u8     {d12}, [r12], r1
+    vld1.u8     {d14}, [r2], r1
+    vld1.u8     {d16}, [r12], r1
+    vld1.u8     {d18}, [r2], r1
+    vld1.u8     {d20}, [r12], r1
+
+    vld1.u8     {d7}, [r2], r1              ; load second 8-line src data
+    vld1.u8     {d9}, [r12], r1
+    vld1.u8     {d11}, [r2], r1
+    vld1.u8     {d13}, [r12], r1
+    vld1.u8     {d15}, [r2], r1
+    vld1.u8     {d17}, [r12], r1
+    vld1.u8     {d19}, [r2]
+    vld1.u8     {d21}, [r12]
+
+    ;transpose to 8x16 matrix
+    vtrn.32     q3, q7
+    vtrn.32     q4, q8
+    vtrn.32     q5, q9
+    vtrn.32     q6, q10
+
+    vdup.u8     q2, r3                     ; duplicate thresh
+
+    vtrn.16     q3, q5
+    vtrn.16     q4, q6
+    vtrn.16     q7, q9
+    vtrn.16     q8, q10
+
+    vtrn.8      q3, q4
+    vtrn.8      q5, q6
+    vtrn.8      q7, q8
+    vtrn.8      q9, q10
+
+    bl          vp8_loop_filter_neon
+
+    vswp        d12, d11
+    vswp        d16, d13
+
+    sub         r0, r0, #2                 ; dst ptr
+
+    vswp        d14, d12
+    vswp        d16, d15
+
+    add         r12, r0, r1, asr #1
+
+    ;store op1, op0, oq0, oq1
+    vst4.8      {d10[0], d11[0], d12[0], d13[0]}, [r0], r1
+    vst4.8      {d10[1], d11[1], d12[1], d13[1]}, [r12], r1
+    vst4.8      {d10[2], d11[2], d12[2], d13[2]}, [r0], r1
+    vst4.8      {d10[3], d11[3], d12[3], d13[3]}, [r12], r1
+    vst4.8      {d10[4], d11[4], d12[4], d13[4]}, [r0], r1
+    vst4.8      {d10[5], d11[5], d12[5], d13[5]}, [r12], r1
+    vst4.8      {d10[6], d11[6], d12[6], d13[6]}, [r0], r1
+    vst4.8      {d10[7], d11[7], d12[7], d13[7]}, [r12], r1
+
+    vst4.8      {d14[0], d15[0], d16[0], d17[0]}, [r0], r1
+    vst4.8      {d14[1], d15[1], d16[1], d17[1]}, [r12], r1
+    vst4.8      {d14[2], d15[2], d16[2], d17[2]}, [r0], r1
+    vst4.8      {d14[3], d15[3], d16[3], d17[3]}, [r12], r1
+    vst4.8      {d14[4], d15[4], d16[4], d17[4]}, [r0], r1
+    vst4.8      {d14[5], d15[5], d16[5], d17[5]}, [r12], r1
+    vst4.8      {d14[6], d15[6], d16[6], d17[6]}, [r0]
+    vst4.8      {d14[7], d15[7], d16[7], d17[7]}, [r12]
+
+    pop         {pc}
+    ENDP        ; |vp8_loop_filter_vertical_edge_y_neon|
+
+; void vp8_loop_filter_vertical_edge_uv_neon(unsigned char *u, int pitch
+;                                            const signed char *flimit,
+;                                            const signed char *limit,
+;                                            const signed char *thresh,
+;                                            unsigned char *v)
+; r0    unsigned char *u,
+; r1    int pitch,
+; r2    unsigned char blimit
+; r3    unsigned char limit
+; sp    unsigned char thresh,
+; sp+4  unsigned char *v
+|vp8_loop_filter_vertical_edge_uv_neon| PROC
+    push        {lr}
+    vdup.u8     q0, r2                      ; duplicate blimit
+    sub         r12, r0, #4                 ; move u pointer down by 4 columns
+    ldr         r2, [sp, #8]                ; load v ptr
+    vdup.u8     q1, r3                      ; duplicate limit
+    sub         r3, r2, #4                  ; move v pointer down by 4 columns
+
+    vld1.u8     {d6}, [r12], r1             ;load u data
+    vld1.u8     {d7}, [r3], r1              ;load v data
+    vld1.u8     {d8}, [r12], r1
+    vld1.u8     {d9}, [r3], r1
+    vld1.u8     {d10}, [r12], r1
+    vld1.u8     {d11}, [r3], r1
+    vld1.u8     {d12}, [r12], r1
+    vld1.u8     {d13}, [r3], r1
+    vld1.u8     {d14}, [r12], r1
+    vld1.u8     {d15}, [r3], r1
+    vld1.u8     {d16}, [r12], r1
+    vld1.u8     {d17}, [r3], r1
+    vld1.u8     {d18}, [r12], r1
+    vld1.u8     {d19}, [r3], r1
+    vld1.u8     {d20}, [r12]
+    vld1.u8     {d21}, [r3]
+
+    ldr        r12, [sp, #4]               ; load thresh
+
+    ;transpose to 8x16 matrix
+    vtrn.32     q3, q7
+    vtrn.32     q4, q8
+    vtrn.32     q5, q9
+    vtrn.32     q6, q10
+
+    vdup.u8     q2, r12                     ; duplicate thresh
+
+    vtrn.16     q3, q5
+    vtrn.16     q4, q6
+    vtrn.16     q7, q9
+    vtrn.16     q8, q10
+
+    vtrn.8      q3, q4
+    vtrn.8      q5, q6
+    vtrn.8      q7, q8
+    vtrn.8      q9, q10
+
+    bl          vp8_loop_filter_neon
+
+    vswp        d12, d11
+    vswp        d16, d13
+    vswp        d14, d12
+    vswp        d16, d15
+
+    sub         r0, r0, #2
+    sub         r2, r2, #2
+
+    ;store op1, op0, oq0, oq1
+    vst4.8      {d10[0], d11[0], d12[0], d13[0]}, [r0], r1
+    vst4.8      {d14[0], d15[0], d16[0], d17[0]}, [r2], r1
+    vst4.8      {d10[1], d11[1], d12[1], d13[1]}, [r0], r1
+    vst4.8      {d14[1], d15[1], d16[1], d17[1]}, [r2], r1
+    vst4.8      {d10[2], d11[2], d12[2], d13[2]}, [r0], r1
+    vst4.8      {d14[2], d15[2], d16[2], d17[2]}, [r2], r1
+    vst4.8      {d10[3], d11[3], d12[3], d13[3]}, [r0], r1
+    vst4.8      {d14[3], d15[3], d16[3], d17[3]}, [r2], r1
+    vst4.8      {d10[4], d11[4], d12[4], d13[4]}, [r0], r1
+    vst4.8      {d14[4], d15[4], d16[4], d17[4]}, [r2], r1
+    vst4.8      {d10[5], d11[5], d12[5], d13[5]}, [r0], r1
+    vst4.8      {d14[5], d15[5], d16[5], d17[5]}, [r2], r1
+    vst4.8      {d10[6], d11[6], d12[6], d13[6]}, [r0], r1
+    vst4.8      {d14[6], d15[6], d16[6], d17[6]}, [r2], r1
+    vst4.8      {d10[7], d11[7], d12[7], d13[7]}, [r0]
+    vst4.8      {d14[7], d15[7], d16[7], d17[7]}, [r2]
+
+    pop         {pc}
+    ENDP        ; |vp8_loop_filter_vertical_edge_uv_neon|
+
+; void vp8_loop_filter_neon();
+; This is a helper function for the loopfilters. The invidual functions do the
+; necessary load, transpose (if necessary) and store.
+
+; r0-r3 PRESERVE
+; q0    flimit
+; q1    limit
+; q2    thresh
+; q3    p3
+; q4    p2
+; q5    p1
+; q6    p0
+; q7    q0
+; q8    q1
+; q9    q2
+; q10   q3
+|vp8_loop_filter_neon| PROC
+
+    ; vp8_filter_mask
+    vabd.u8     q11, q3, q4                 ; abs(p3 - p2)
+    vabd.u8     q12, q4, q5                 ; abs(p2 - p1)
+    vabd.u8     q13, q5, q6                 ; abs(p1 - p0)
+    vabd.u8     q14, q8, q7                 ; abs(q1 - q0)
+    vabd.u8     q3, q9, q8                  ; abs(q2 - q1)
+    vabd.u8     q4, q10, q9                 ; abs(q3 - q2)
+
+    vmax.u8     q11, q11, q12
+    vmax.u8     q12, q13, q14
+    vmax.u8     q3, q3, q4
+    vmax.u8     q15, q11, q12
+
+    vabd.u8     q9, q6, q7                  ; abs(p0 - q0)
+
+    ; vp8_hevmask
+    vcgt.u8     q13, q13, q2                ; (abs(p1 - p0) > thresh)*-1
+    vcgt.u8     q14, q14, q2                ; (abs(q1 - q0) > thresh)*-1
+    vmax.u8     q15, q15, q3
+
+    vmov.u8     q10, #0x80                   ; 0x80
+
+    vabd.u8     q2, q5, q8                  ; a = abs(p1 - q1)
+    vqadd.u8    q9, q9, q9                  ; b = abs(p0 - q0) * 2
+
+    vcge.u8     q15, q1, q15
+
+    ; vp8_filter() function
+    ; convert to signed
+    veor        q7, q7, q10                 ; qs0
+    vshr.u8     q2, q2, #1                  ; a = a / 2
+    veor        q6, q6, q10                 ; ps0
+
+    veor        q5, q5, q10                 ; ps1
+    vqadd.u8    q9, q9, q2                  ; a = b + a
+
+    veor        q8, q8, q10                 ; qs1
+
+    vmov.u8     q10, #3                     ; #3
+
+    vsubl.s8    q2, d14, d12                ; ( qs0 - ps0)
+    vsubl.s8    q11, d15, d13
+
+    vcge.u8     q9, q0, q9                  ; (a > flimit * 2 + limit) * -1
+
+    vmovl.u8    q4, d20
+
+    vqsub.s8    q1, q5, q8                  ; vp8_filter = clamp(ps1-qs1)
+    vorr        q14, q13, q14               ; vp8_hevmask
+
+    vmul.i16    q2, q2, q4                  ; 3 * ( qs0 - ps0)
+    vmul.i16    q11, q11, q4
+
+    vand        q1, q1, q14                 ; vp8_filter &= hev
+    vand        q15, q15, q9                ; vp8_filter_mask
+
+    vaddw.s8    q2, q2, d2
+    vaddw.s8    q11, q11, d3
+
+    vmov.u8     q9, #4                      ; #4
+
+    ; vp8_filter = clamp(vp8_filter + 3 * ( qs0 - ps0))
+    vqmovn.s16  d2, q2
+    vqmovn.s16  d3, q11
+    vand        q1, q1, q15                 ; vp8_filter &= mask
+
+    vqadd.s8    q2, q1, q10                 ; Filter2 = clamp(vp8_filter+3)
+    vqadd.s8    q1, q1, q9                  ; Filter1 = clamp(vp8_filter+4)
+    vshr.s8     q2, q2, #3                  ; Filter2 >>= 3
+    vshr.s8     q1, q1, #3                  ; Filter1 >>= 3
+
+
+    vqadd.s8    q11, q6, q2                 ; u = clamp(ps0 + Filter2)
+    vqsub.s8    q10, q7, q1                 ; u = clamp(qs0 - Filter1)
+
+    ; outer tap adjustments: ++vp8_filter >> 1
+    vrshr.s8    q1, q1, #1
+    vbic        q1, q1, q14                 ; vp8_filter &= ~hev
+    vmov.u8     q0, #0x80                   ; 0x80
+    vqadd.s8    q13, q5, q1                 ; u = clamp(ps1 + vp8_filter)
+    vqsub.s8    q12, q8, q1                 ; u = clamp(qs1 - vp8_filter)
+
+    veor        q6, q11, q0                 ; *op0 = u^0x80
+    veor        q7, q10, q0                 ; *oq0 = u^0x80
+    veor        q5, q13, q0                 ; *op1 = u^0x80
+    veor        q8, q12, q0                 ; *oq1 = u^0x80
+
+    bx          lr
+    ENDP        ; |vp8_loop_filter_horizontal_edge_y_neon|
+
+;-----------------
+
+    END
diff --git a/vp8/common/arm/neon/loopfiltersimplehorizontaledge_neon.asm b/vp8/common/arm/neon/loopfiltersimplehorizontaledge_neon.asm
new file mode 100644 (file)
index 0000000..adf848b
--- /dev/null
@@ -0,0 +1,117 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    ;EXPORT  |vp8_loop_filter_simple_horizontal_edge_neon|
+    EXPORT  |vp8_loop_filter_bhs_neon|
+    EXPORT  |vp8_loop_filter_mbhs_neon|
+    ARM
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    unsigned char *s, PRESERVE
+; r1    int p, PRESERVE
+; q1    limit, PRESERVE
+
+|vp8_loop_filter_simple_horizontal_edge_neon| PROC
+
+    sub         r3, r0, r1, lsl #1          ; move src pointer down by 2 lines
+
+    vld1.u8     {q7}, [r0@128], r1          ; q0
+    vld1.u8     {q5}, [r3@128], r1          ; p0
+    vld1.u8     {q8}, [r0@128]              ; q1
+    vld1.u8     {q6}, [r3@128]              ; p1
+
+    vabd.u8     q15, q6, q7                 ; abs(p0 - q0)
+    vabd.u8     q14, q5, q8                 ; abs(p1 - q1)
+
+    vqadd.u8    q15, q15, q15               ; abs(p0 - q0) * 2
+    vshr.u8     q14, q14, #1                ; abs(p1 - q1) / 2
+    vmov.u8     q0, #0x80                   ; 0x80
+    vmov.s16    q13, #3
+    vqadd.u8    q15, q15, q14               ; abs(p0 - q0) * 2 + abs(p1 - q1) / 2
+
+    veor        q7, q7, q0                  ; qs0: q0 offset to convert to a signed value
+    veor        q6, q6, q0                  ; ps0: p0 offset to convert to a signed value
+    veor        q5, q5, q0                  ; ps1: p1 offset to convert to a signed value
+    veor        q8, q8, q0                  ; qs1: q1 offset to convert to a signed value
+
+    vcge.u8     q15, q1, q15                ; (abs(p0 - q0)*2 + abs(p1-q1)/2 > limit)*-1
+
+    vsubl.s8    q2, d14, d12                ; ( qs0 - ps0)
+    vsubl.s8    q3, d15, d13
+
+    vqsub.s8    q4, q5, q8                  ; q4: vp8_filter = vp8_signed_char_clamp(ps1-qs1)
+
+    vmul.s16    q2, q2, q13                 ;  3 * ( qs0 - ps0)
+    vmul.s16    q3, q3, q13
+
+    vmov.u8     q10, #0x03                  ; 0x03
+    vmov.u8     q9, #0x04                   ; 0x04
+
+    vaddw.s8    q2, q2, d8                  ; vp8_filter + 3 * ( qs0 - ps0)
+    vaddw.s8    q3, q3, d9
+
+    vqmovn.s16  d8, q2                      ; vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+    vqmovn.s16  d9, q3
+
+    vand        q14, q4, q15                ; vp8_filter &= mask
+
+    vqadd.s8    q2, q14, q10                ; Filter2 = vp8_signed_char_clamp(vp8_filter+3)
+    vqadd.s8    q3, q14, q9                 ; Filter1 = vp8_signed_char_clamp(vp8_filter+4)
+    vshr.s8     q2, q2, #3                  ; Filter2 >>= 3
+    vshr.s8     q4, q3, #3                  ; Filter1 >>= 3
+
+    sub         r0, r0, r1
+
+    ;calculate output
+    vqadd.s8    q11, q6, q2                 ; u = vp8_signed_char_clamp(ps0 + Filter2)
+    vqsub.s8    q10, q7, q4                 ; u = vp8_signed_char_clamp(qs0 - Filter1)
+
+    veor        q6, q11, q0                 ; *op0 = u^0x80
+    veor        q7, q10, q0                 ; *oq0 = u^0x80
+
+    vst1.u8     {q6}, [r3@128]              ; store op0
+    vst1.u8     {q7}, [r0@128]              ; store oq0
+
+    bx          lr
+    ENDP        ; |vp8_loop_filter_simple_horizontal_edge_neon|
+
+; r0    unsigned char *y
+; r1    int ystride
+; r2    const unsigned char *blimit
+
+|vp8_loop_filter_bhs_neon| PROC
+    push        {r4, lr}
+    ldrb        r3, [r2]                    ; load blim from mem
+    vdup.s8     q1, r3                      ; duplicate blim
+
+    add         r0, r0, r1, lsl #2          ; src = y_ptr + 4 * y_stride
+    bl          vp8_loop_filter_simple_horizontal_edge_neon
+    ; vp8_loop_filter_simple_horizontal_edge_neon preserves r0, r1 and q1
+    add         r0, r0, r1, lsl #2          ; src = y_ptr + 8* y_stride
+    bl          vp8_loop_filter_simple_horizontal_edge_neon
+    add         r0, r0, r1, lsl #2          ; src = y_ptr + 12 * y_stride
+    pop         {r4, lr}
+    b           vp8_loop_filter_simple_horizontal_edge_neon
+    ENDP        ;|vp8_loop_filter_bhs_neon|
+
+; r0    unsigned char *y
+; r1    int ystride
+; r2    const unsigned char *blimit
+
+|vp8_loop_filter_mbhs_neon| PROC
+    ldrb        r3, [r2]                   ; load blim from mem
+    vdup.s8     q1, r3                     ; duplicate mblim
+    b           vp8_loop_filter_simple_horizontal_edge_neon
+    ENDP        ;|vp8_loop_filter_bhs_neon|
+
+    END
diff --git a/vp8/common/arm/neon/loopfiltersimpleverticaledge_neon.asm b/vp8/common/arm/neon/loopfiltersimpleverticaledge_neon.asm
new file mode 100644 (file)
index 0000000..e690df2
--- /dev/null
@@ -0,0 +1,154 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    ;EXPORT  |vp8_loop_filter_simple_vertical_edge_neon|
+    EXPORT |vp8_loop_filter_bvs_neon|
+    EXPORT |vp8_loop_filter_mbvs_neon|
+    ARM
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    unsigned char *s, PRESERVE
+; r1    int p, PRESERVE
+; q1    limit, PRESERVE
+
+|vp8_loop_filter_simple_vertical_edge_neon| PROC
+    sub         r0, r0, #2                  ; move src pointer down by 2 columns
+    add         r12, r1, r1
+    add         r3, r0, r1
+
+    vld4.8      {d6[0], d7[0], d8[0], d9[0]}, [r0], r12
+    vld4.8      {d6[1], d7[1], d8[1], d9[1]}, [r3], r12
+    vld4.8      {d6[2], d7[2], d8[2], d9[2]}, [r0], r12
+    vld4.8      {d6[3], d7[3], d8[3], d9[3]}, [r3], r12
+    vld4.8      {d6[4], d7[4], d8[4], d9[4]}, [r0], r12
+    vld4.8      {d6[5], d7[5], d8[5], d9[5]}, [r3], r12
+    vld4.8      {d6[6], d7[6], d8[6], d9[6]}, [r0], r12
+    vld4.8      {d6[7], d7[7], d8[7], d9[7]}, [r3], r12
+
+    vld4.8      {d10[0], d11[0], d12[0], d13[0]}, [r0], r12
+    vld4.8      {d10[1], d11[1], d12[1], d13[1]}, [r3], r12
+    vld4.8      {d10[2], d11[2], d12[2], d13[2]}, [r0], r12
+    vld4.8      {d10[3], d11[3], d12[3], d13[3]}, [r3], r12
+    vld4.8      {d10[4], d11[4], d12[4], d13[4]}, [r0], r12
+    vld4.8      {d10[5], d11[5], d12[5], d13[5]}, [r3], r12
+    vld4.8      {d10[6], d11[6], d12[6], d13[6]}, [r0], r12
+    vld4.8      {d10[7], d11[7], d12[7], d13[7]}, [r3]
+
+    vswp        d7, d10
+    vswp        d12, d9
+
+    ;vp8_filter_mask() function
+    ;vp8_hevmask() function
+    sub         r0, r0, r1, lsl #4
+    vabd.u8     q15, q5, q4                 ; abs(p0 - q0)
+    vabd.u8     q14, q3, q6                 ; abs(p1 - q1)
+
+    vqadd.u8    q15, q15, q15               ; abs(p0 - q0) * 2
+    vshr.u8     q14, q14, #1                ; abs(p1 - q1) / 2
+    vmov.u8     q0, #0x80                   ; 0x80
+    vmov.s16    q11, #3
+    vqadd.u8    q15, q15, q14               ; abs(p0 - q0) * 2 + abs(p1 - q1) / 2
+
+    veor        q4, q4, q0                  ; qs0: q0 offset to convert to a signed value
+    veor        q5, q5, q0                  ; ps0: p0 offset to convert to a signed value
+    veor        q3, q3, q0                  ; ps1: p1 offset to convert to a signed value
+    veor        q6, q6, q0                  ; qs1: q1 offset to convert to a signed value
+
+    vcge.u8     q15, q1, q15                ; abs(p0 - q0)*2 + abs(p1-q1)/2 > flimit*2 + limit)*-1
+
+    vsubl.s8    q2, d8, d10                 ; ( qs0 - ps0)
+    vsubl.s8    q13, d9, d11
+
+    vqsub.s8    q14, q3, q6                  ; vp8_filter = vp8_signed_char_clamp(ps1-qs1)
+
+    vmul.s16    q2, q2, q11                 ;  3 * ( qs0 - ps0)
+    vmul.s16    q13, q13, q11
+
+    vmov.u8     q11, #0x03                  ; 0x03
+    vmov.u8     q12, #0x04                  ; 0x04
+
+    vaddw.s8    q2, q2, d28                  ; vp8_filter + 3 * ( qs0 - ps0)
+    vaddw.s8    q13, q13, d29
+
+    vqmovn.s16  d28, q2                      ; vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+    vqmovn.s16  d29, q13
+
+    add         r0, r0, #1
+    add         r3, r0, r1
+
+    vand        q14, q14, q15                 ; vp8_filter &= mask
+
+    vqadd.s8    q2, q14, q11                 ; Filter2 = vp8_signed_char_clamp(vp8_filter+3)
+    vqadd.s8    q3, q14, q12                 ; Filter1 = vp8_signed_char_clamp(vp8_filter+4)
+    vshr.s8     q2, q2, #3                  ; Filter2 >>= 3
+    vshr.s8     q14, q3, #3                  ; Filter1 >>= 3
+
+    ;calculate output
+    vqadd.s8    q11, q5, q2                 ; u = vp8_signed_char_clamp(ps0 + Filter2)
+    vqsub.s8    q10, q4, q14                 ; u = vp8_signed_char_clamp(qs0 - Filter1)
+
+    veor        q6, q11, q0                 ; *op0 = u^0x80
+    veor        q7, q10, q0                 ; *oq0 = u^0x80
+    add         r12, r1, r1
+    vswp        d13, d14
+
+    ;store op1, op0, oq0, oq1
+    vst2.8      {d12[0], d13[0]}, [r0], r12
+    vst2.8      {d12[1], d13[1]}, [r3], r12
+    vst2.8      {d12[2], d13[2]}, [r0], r12
+    vst2.8      {d12[3], d13[3]}, [r3], r12
+    vst2.8      {d12[4], d13[4]}, [r0], r12
+    vst2.8      {d12[5], d13[5]}, [r3], r12
+    vst2.8      {d12[6], d13[6]}, [r0], r12
+    vst2.8      {d12[7], d13[7]}, [r3], r12
+    vst2.8      {d14[0], d15[0]}, [r0], r12
+    vst2.8      {d14[1], d15[1]}, [r3], r12
+    vst2.8      {d14[2], d15[2]}, [r0], r12
+    vst2.8      {d14[3], d15[3]}, [r3], r12
+    vst2.8      {d14[4], d15[4]}, [r0], r12
+    vst2.8      {d14[5], d15[5]}, [r3], r12
+    vst2.8      {d14[6], d15[6]}, [r0], r12
+    vst2.8      {d14[7], d15[7]}, [r3]
+
+    bx          lr
+    ENDP        ; |vp8_loop_filter_simple_vertical_edge_neon|
+
+; r0    unsigned char *y
+; r1    int ystride
+; r2    const unsigned char *blimit
+
+|vp8_loop_filter_bvs_neon| PROC
+    push        {r4, lr}
+    ldrb        r3, [r2]                   ; load blim from mem
+    mov         r4, r0
+    add         r0, r0, #4
+    vdup.s8     q1, r3                     ; duplicate blim
+    bl          vp8_loop_filter_simple_vertical_edge_neon
+    ; vp8_loop_filter_simple_vertical_edge_neon preserves  r1 and q1
+    add         r0, r4, #8
+    bl          vp8_loop_filter_simple_vertical_edge_neon
+    add         r0, r4, #12
+    pop         {r4, lr}
+    b           vp8_loop_filter_simple_vertical_edge_neon
+    ENDP        ;|vp8_loop_filter_bvs_neon|
+
+; r0    unsigned char *y
+; r1    int ystride
+; r2    const unsigned char *blimit
+
+|vp8_loop_filter_mbvs_neon| PROC
+    ldrb        r3, [r2]                   ; load mblim from mem
+    vdup.s8     q1, r3                     ; duplicate mblim
+    b           vp8_loop_filter_simple_vertical_edge_neon
+    ENDP        ;|vp8_loop_filter_bvs_neon|
+    END
diff --git a/vp8/common/arm/neon/mbloopfilter_neon.asm b/vp8/common/arm/neon/mbloopfilter_neon.asm
new file mode 100644 (file)
index 0000000..f41c156
--- /dev/null
@@ -0,0 +1,469 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_mbloop_filter_horizontal_edge_y_neon|
+    EXPORT  |vp8_mbloop_filter_horizontal_edge_uv_neon|
+    EXPORT  |vp8_mbloop_filter_vertical_edge_y_neon|
+    EXPORT  |vp8_mbloop_filter_vertical_edge_uv_neon|
+    ARM
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; void vp8_mbloop_filter_horizontal_edge_y_neon(unsigned char *src, int pitch,
+;                                               const unsigned char *blimit,
+;                                               const unsigned char *limit,
+;                                               const unsigned char *thresh)
+; r0    unsigned char *src,
+; r1    int pitch,
+; r2    unsigned char blimit
+; r3    unsigned char limit
+; sp    unsigned char thresh,
+|vp8_mbloop_filter_horizontal_edge_y_neon| PROC
+    push        {lr}
+    add         r1, r1, r1                  ; double stride
+    ldr         r12, [sp, #4]               ; load thresh
+    sub         r0, r0, r1, lsl #1          ; move src pointer down by 4 lines
+    vdup.u8     q2, r12                     ; thresh
+    add         r12, r0, r1,  lsr #1        ; move src pointer up by 1 line
+
+    vld1.u8     {q3}, [r0@128], r1              ; p3
+    vld1.u8     {q4}, [r12@128], r1             ; p2
+    vld1.u8     {q5}, [r0@128], r1              ; p1
+    vld1.u8     {q6}, [r12@128], r1             ; p0
+    vld1.u8     {q7}, [r0@128], r1              ; q0
+    vld1.u8     {q8}, [r12@128], r1             ; q1
+    vld1.u8     {q9}, [r0@128], r1              ; q2
+    vld1.u8     {q10}, [r12@128], r1            ; q3
+
+    bl          vp8_mbloop_filter_neon
+
+    sub         r12, r12, r1, lsl #2
+    add         r0, r12, r1, lsr #1
+
+    vst1.u8     {q4}, [r12@128],r1         ; store op2
+    vst1.u8     {q5}, [r0@128],r1          ; store op1
+    vst1.u8     {q6}, [r12@128], r1        ; store op0
+    vst1.u8     {q7}, [r0@128],r1          ; store oq0
+    vst1.u8     {q8}, [r12@128]            ; store oq1
+    vst1.u8     {q9}, [r0@128]             ; store oq2
+
+    pop         {pc}
+    ENDP        ; |vp8_mbloop_filter_horizontal_edge_y_neon|
+
+; void vp8_mbloop_filter_horizontal_edge_uv_neon(unsigned char *u, int pitch,
+;                                                const unsigned char *blimit,
+;                                                const unsigned char *limit,
+;                                                const unsigned char *thresh,
+;                                                unsigned char *v)
+; r0    unsigned char *u,
+; r1    int pitch,
+; r2    unsigned char blimit
+; r3    unsigned char limit
+; sp    unsigned char thresh,
+; sp+4  unsigned char *v
+
+|vp8_mbloop_filter_horizontal_edge_uv_neon| PROC
+    push        {lr}
+    ldr         r12, [sp, #4]                 ; load thresh
+    sub         r0, r0, r1, lsl #2            ; move u pointer down by 4 lines
+    vdup.u8     q2, r12                       ; thresh
+    ldr         r12, [sp, #8]                 ; load v ptr
+    sub         r12, r12, r1, lsl #2          ; move v pointer down by 4 lines
+
+    vld1.u8     {d6}, [r0@64], r1              ; p3
+    vld1.u8     {d7}, [r12@64], r1              ; p3
+    vld1.u8     {d8}, [r0@64], r1              ; p2
+    vld1.u8     {d9}, [r12@64], r1              ; p2
+    vld1.u8     {d10}, [r0@64], r1             ; p1
+    vld1.u8     {d11}, [r12@64], r1             ; p1
+    vld1.u8     {d12}, [r0@64], r1             ; p0
+    vld1.u8     {d13}, [r12@64], r1             ; p0
+    vld1.u8     {d14}, [r0@64], r1             ; q0
+    vld1.u8     {d15}, [r12@64], r1             ; q0
+    vld1.u8     {d16}, [r0@64], r1             ; q1
+    vld1.u8     {d17}, [r12@64], r1             ; q1
+    vld1.u8     {d18}, [r0@64], r1             ; q2
+    vld1.u8     {d19}, [r12@64], r1             ; q2
+    vld1.u8     {d20}, [r0@64], r1             ; q3
+    vld1.u8     {d21}, [r12@64], r1             ; q3
+
+    bl          vp8_mbloop_filter_neon
+
+    sub         r0, r0, r1, lsl #3
+    sub         r12, r12, r1, lsl #3
+
+    add         r0, r0, r1
+    add         r12, r12, r1
+
+    vst1.u8     {d8}, [r0@64], r1              ; store u op2
+    vst1.u8     {d9}, [r12@64], r1              ; store v op2
+    vst1.u8     {d10}, [r0@64], r1             ; store u op1
+    vst1.u8     {d11}, [r12@64], r1             ; store v op1
+    vst1.u8     {d12}, [r0@64], r1             ; store u op0
+    vst1.u8     {d13}, [r12@64], r1             ; store v op0
+    vst1.u8     {d14}, [r0@64], r1             ; store u oq0
+    vst1.u8     {d15}, [r12@64], r1             ; store v oq0
+    vst1.u8     {d16}, [r0@64], r1             ; store u oq1
+    vst1.u8     {d17}, [r12@64], r1             ; store v oq1
+    vst1.u8     {d18}, [r0@64], r1             ; store u oq2
+    vst1.u8     {d19}, [r12@64], r1             ; store v oq2
+
+    pop         {pc}
+    ENDP        ; |vp8_mbloop_filter_horizontal_edge_uv_neon|
+
+; void vp8_mbloop_filter_vertical_edge_y_neon(unsigned char *src, int pitch,
+;                                             const unsigned char *blimit,
+;                                             const unsigned char *limit,
+;                                             const unsigned char *thresh)
+; r0    unsigned char *src,
+; r1    int pitch,
+; r2    unsigned char blimit
+; r3    unsigned char limit
+; sp    unsigned char thresh,
+|vp8_mbloop_filter_vertical_edge_y_neon| PROC
+    push        {lr}
+    ldr         r12, [sp, #4]               ; load thresh
+    sub         r0, r0, #4                  ; move src pointer down by 4 columns
+    vdup.s8     q2, r12                     ; thresh
+    add         r12, r0, r1, lsl #3         ; move src pointer down by 8 lines
+
+    vld1.u8     {d6}, [r0], r1              ; load first 8-line src data
+    vld1.u8     {d7}, [r12], r1             ; load second 8-line src data
+    vld1.u8     {d8}, [r0], r1
+    vld1.u8     {d9}, [r12], r1
+    vld1.u8     {d10}, [r0], r1
+    vld1.u8     {d11}, [r12], r1
+    vld1.u8     {d12}, [r0], r1
+    vld1.u8     {d13}, [r12], r1
+    vld1.u8     {d14}, [r0], r1
+    vld1.u8     {d15}, [r12], r1
+    vld1.u8     {d16}, [r0], r1
+    vld1.u8     {d17}, [r12], r1
+    vld1.u8     {d18}, [r0], r1
+    vld1.u8     {d19}, [r12], r1
+    vld1.u8     {d20}, [r0], r1
+    vld1.u8     {d21}, [r12], r1
+
+    ;transpose to 8x16 matrix
+    vtrn.32     q3, q7
+    vtrn.32     q4, q8
+    vtrn.32     q5, q9
+    vtrn.32     q6, q10
+
+    vtrn.16     q3, q5
+    vtrn.16     q4, q6
+    vtrn.16     q7, q9
+    vtrn.16     q8, q10
+
+    vtrn.8      q3, q4
+    vtrn.8      q5, q6
+    vtrn.8      q7, q8
+    vtrn.8      q9, q10
+
+    sub         r0, r0, r1, lsl #3
+
+    bl          vp8_mbloop_filter_neon
+
+    sub         r12, r12, r1, lsl #3
+
+    ;transpose to 16x8 matrix
+    vtrn.32     q3, q7
+    vtrn.32     q4, q8
+    vtrn.32     q5, q9
+    vtrn.32     q6, q10
+
+    vtrn.16     q3, q5
+    vtrn.16     q4, q6
+    vtrn.16     q7, q9
+    vtrn.16     q8, q10
+
+    vtrn.8      q3, q4
+    vtrn.8      q5, q6
+    vtrn.8      q7, q8
+    vtrn.8      q9, q10
+
+    ;store op2, op1, op0, oq0, oq1, oq2
+    vst1.8      {d6}, [r0], r1
+    vst1.8      {d7}, [r12], r1
+    vst1.8      {d8}, [r0], r1
+    vst1.8      {d9}, [r12], r1
+    vst1.8      {d10}, [r0], r1
+    vst1.8      {d11}, [r12], r1
+    vst1.8      {d12}, [r0], r1
+    vst1.8      {d13}, [r12], r1
+    vst1.8      {d14}, [r0], r1
+    vst1.8      {d15}, [r12], r1
+    vst1.8      {d16}, [r0], r1
+    vst1.8      {d17}, [r12], r1
+    vst1.8      {d18}, [r0], r1
+    vst1.8      {d19}, [r12], r1
+    vst1.8      {d20}, [r0]
+    vst1.8      {d21}, [r12]
+
+    pop         {pc}
+    ENDP        ; |vp8_mbloop_filter_vertical_edge_y_neon|
+
+; void vp8_mbloop_filter_vertical_edge_uv_neon(unsigned char *u, int pitch,
+;                                              const unsigned char *blimit,
+;                                              const unsigned char *limit,
+;                                              const unsigned char *thresh,
+;                                              unsigned char *v)
+; r0    unsigned char *u,
+; r1    int pitch,
+; r2    const signed char *flimit,
+; r3    const signed char *limit,
+; sp    const signed char *thresh,
+; sp+4  unsigned char *v
+|vp8_mbloop_filter_vertical_edge_uv_neon| PROC
+    push        {lr}
+    ldr         r12, [sp, #4]               ; load thresh
+    sub         r0, r0, #4                  ; move u pointer down by 4 columns
+    vdup.u8     q2, r12                     ; thresh
+    ldr         r12, [sp, #8]               ; load v ptr
+    sub         r12, r12, #4                ; move v pointer down by 4 columns
+
+    vld1.u8     {d6}, [r0], r1              ;load u data
+    vld1.u8     {d7}, [r12], r1             ;load v data
+    vld1.u8     {d8}, [r0], r1
+    vld1.u8     {d9}, [r12], r1
+    vld1.u8     {d10}, [r0], r1
+    vld1.u8     {d11}, [r12], r1
+    vld1.u8     {d12}, [r0], r1
+    vld1.u8     {d13}, [r12], r1
+    vld1.u8     {d14}, [r0], r1
+    vld1.u8     {d15}, [r12], r1
+    vld1.u8     {d16}, [r0], r1
+    vld1.u8     {d17}, [r12], r1
+    vld1.u8     {d18}, [r0], r1
+    vld1.u8     {d19}, [r12], r1
+    vld1.u8     {d20}, [r0], r1
+    vld1.u8     {d21}, [r12], r1
+
+    ;transpose to 8x16 matrix
+    vtrn.32     q3, q7
+    vtrn.32     q4, q8
+    vtrn.32     q5, q9
+    vtrn.32     q6, q10
+
+    vtrn.16     q3, q5
+    vtrn.16     q4, q6
+    vtrn.16     q7, q9
+    vtrn.16     q8, q10
+
+    vtrn.8      q3, q4
+    vtrn.8      q5, q6
+    vtrn.8      q7, q8
+    vtrn.8      q9, q10
+
+    sub         r0, r0, r1, lsl #3
+
+    bl          vp8_mbloop_filter_neon
+
+    sub         r12, r12, r1, lsl #3
+
+    ;transpose to 16x8 matrix
+    vtrn.32     q3, q7
+    vtrn.32     q4, q8
+    vtrn.32     q5, q9
+    vtrn.32     q6, q10
+
+    vtrn.16     q3, q5
+    vtrn.16     q4, q6
+    vtrn.16     q7, q9
+    vtrn.16     q8, q10
+
+    vtrn.8      q3, q4
+    vtrn.8      q5, q6
+    vtrn.8      q7, q8
+    vtrn.8      q9, q10
+
+    ;store op2, op1, op0, oq0, oq1, oq2
+    vst1.8      {d6}, [r0], r1
+    vst1.8      {d7}, [r12], r1
+    vst1.8      {d8}, [r0], r1
+    vst1.8      {d9}, [r12], r1
+    vst1.8      {d10}, [r0], r1
+    vst1.8      {d11}, [r12], r1
+    vst1.8      {d12}, [r0], r1
+    vst1.8      {d13}, [r12], r1
+    vst1.8      {d14}, [r0], r1
+    vst1.8      {d15}, [r12], r1
+    vst1.8      {d16}, [r0], r1
+    vst1.8      {d17}, [r12], r1
+    vst1.8      {d18}, [r0], r1
+    vst1.8      {d19}, [r12], r1
+    vst1.8      {d20}, [r0]
+    vst1.8      {d21}, [r12]
+
+    pop         {pc}
+    ENDP        ; |vp8_mbloop_filter_vertical_edge_uv_neon|
+
+; void vp8_mbloop_filter_neon()
+; This is a helper function for the macroblock loopfilters. The individual
+; functions do the necessary load, transpose (if necessary), preserve (if
+; necessary) and store.
+
+; r0,r1 PRESERVE
+; r2    mblimit
+; r3    limit
+
+; q2    thresh
+; q3    p3 PRESERVE
+; q4    p2
+; q5    p1
+; q6    p0
+; q7    q0
+; q8    q1
+; q9    q2
+; q10   q3 PRESERVE
+
+|vp8_mbloop_filter_neon| PROC
+
+    ; vp8_filter_mask
+    vabd.u8     q11, q3, q4                 ; abs(p3 - p2)
+    vabd.u8     q12, q4, q5                 ; abs(p2 - p1)
+    vabd.u8     q13, q5, q6                 ; abs(p1 - p0)
+    vabd.u8     q14, q8, q7                 ; abs(q1 - q0)
+    vabd.u8     q1, q9, q8                  ; abs(q2 - q1)
+    vabd.u8     q0, q10, q9                 ; abs(q3 - q2)
+
+    vmax.u8     q11, q11, q12
+    vmax.u8     q12, q13, q14
+    vmax.u8     q1, q1, q0
+    vmax.u8     q15, q11, q12
+
+    vabd.u8     q12, q6, q7                 ; abs(p0 - q0)
+
+    ; vp8_hevmask
+    vcgt.u8     q13, q13, q2                ; (abs(p1 - p0) > thresh) * -1
+    vcgt.u8     q14, q14, q2                ; (abs(q1 - q0) > thresh) * -1
+    vmax.u8     q15, q15, q1
+
+    vdup.u8     q1, r3                      ; limit
+    vdup.u8     q2, r2                      ; mblimit
+
+    vmov.u8     q0, #0x80                   ; 0x80
+
+    vcge.u8     q15, q1, q15
+
+    vabd.u8     q1, q5, q8                  ; a = abs(p1 - q1)
+    vqadd.u8    q12, q12, q12               ; b = abs(p0 - q0) * 2
+    vmov.u16    q11, #3                     ; #3
+
+    ; vp8_filter
+    ; convert to signed
+    veor        q7, q7, q0                  ; qs0
+    vshr.u8     q1, q1, #1                  ; a = a / 2
+    veor        q6, q6, q0                  ; ps0
+    veor        q5, q5, q0                  ; ps1
+
+    vqadd.u8    q12, q12, q1                ; a = b + a
+
+    veor        q8, q8, q0                  ; qs1
+    veor        q4, q4, q0                  ; ps2
+    veor        q9, q9, q0                  ; qs2
+
+    vorr        q14, q13, q14               ; vp8_hevmask
+
+    vcge.u8     q12, q2, q12                ; (a > flimit * 2 + limit) * -1
+
+    vsubl.s8    q2, d14, d12                ; qs0 - ps0
+    vsubl.s8    q13, d15, d13
+
+    vqsub.s8    q1, q5, q8                  ; vp8_filter = clamp(ps1-qs1)
+
+    vmul.i16    q2, q2, q11                 ; 3 * ( qs0 - ps0)
+
+    vand        q15, q15, q12               ; vp8_filter_mask
+
+    vmul.i16    q13, q13, q11
+
+    vmov.u8     q12, #3                     ; #3
+
+    vaddw.s8    q2, q2, d2                  ; vp8_filter + 3 * ( qs0 - ps0)
+    vaddw.s8    q13, q13, d3
+
+    vmov.u8     q11, #4                     ; #4
+
+    ; vp8_filter = clamp(vp8_filter + 3 * ( qs0 - ps0))
+    vqmovn.s16  d2, q2
+    vqmovn.s16  d3, q13
+
+    vand        q1, q1, q15                 ; vp8_filter &= mask
+
+    vmov.u16    q15, #63                    ; #63
+
+    vand        q13, q1, q14                ; Filter2 &= hev
+
+    vqadd.s8    q2, q13, q11                ; Filter1 = clamp(Filter2+4)
+    vqadd.s8    q13, q13, q12               ; Filter2 = clamp(Filter2+3)
+
+    vmov        q0, q15
+
+    vshr.s8     q2, q2, #3                  ; Filter1 >>= 3
+    vshr.s8     q13, q13, #3                ; Filter2 >>= 3
+
+    vmov        q11, q15
+    vmov        q12, q15
+
+    vqsub.s8    q7, q7, q2                  ; qs0 = clamp(qs0 - Filter1)
+
+    vqadd.s8    q6, q6, q13                 ; ps0 = clamp(ps0 + Filter2)
+
+    vbic        q1, q1, q14                 ; vp8_filter &= ~hev
+
+    ; roughly 1/7th difference across boundary
+    ; roughly 2/7th difference across boundary
+    ; roughly 3/7th difference across boundary
+
+    vmov.u8     d5, #9                      ; #9
+    vmov.u8     d4, #18                     ; #18
+
+    vmov        q13, q15
+    vmov        q14, q15
+
+    vmlal.s8    q0, d2, d5                  ; 63 + Filter2 * 9
+    vmlal.s8    q11, d3, d5
+    vmov.u8     d5, #27                     ; #27
+    vmlal.s8    q12, d2, d4                 ; 63 + Filter2 * 18
+    vmlal.s8    q13, d3, d4
+    vmlal.s8    q14, d2, d5                 ; 63 + Filter2 * 27
+    vmlal.s8    q15, d3, d5
+
+    vqshrn.s16  d0, q0, #7                  ; u = clamp((63 + Filter2 * 9)>>7)
+    vqshrn.s16  d1, q11, #7
+    vqshrn.s16  d24, q12, #7                ; u = clamp((63 + Filter2 * 18)>>7)
+    vqshrn.s16  d25, q13, #7
+    vqshrn.s16  d28, q14, #7                ; u = clamp((63 + Filter2 * 27)>>7)
+    vqshrn.s16  d29, q15, #7
+
+    vmov.u8     q1, #0x80                   ; 0x80
+
+    vqsub.s8    q11, q9, q0                 ; s = clamp(qs2 - u)
+    vqadd.s8    q0, q4, q0                  ; s = clamp(ps2 + u)
+    vqsub.s8    q13, q8, q12                ; s = clamp(qs1 - u)
+    vqadd.s8    q12, q5, q12                ; s = clamp(ps1 + u)
+    vqsub.s8    q15, q7, q14                ; s = clamp(qs0 - u)
+    vqadd.s8    q14, q6, q14                ; s = clamp(ps0 + u)
+
+    veor        q9, q11, q1                 ; *oq2 = s^0x80
+    veor        q4, q0, q1                  ; *op2 = s^0x80
+    veor        q8, q13, q1                 ; *oq1 = s^0x80
+    veor        q5, q12, q1                 ; *op2 = s^0x80
+    veor        q7, q15, q1                 ; *oq0 = s^0x80
+    veor        q6, q14, q1                 ; *op0 = s^0x80
+
+    bx          lr
+    ENDP        ; |vp8_mbloop_filter_neon|
+
+;-----------------
+
+    END
diff --git a/vp8/common/arm/neon/sad16_neon.asm b/vp8/common/arm/neon/sad16_neon.asm
new file mode 100644 (file)
index 0000000..d7c590e
--- /dev/null
@@ -0,0 +1,207 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_sad16x16_neon|
+    EXPORT  |vp8_sad16x8_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    unsigned char *src_ptr
+; r1    int  src_stride
+; r2    unsigned char *ref_ptr
+; r3    int  ref_stride
+|vp8_sad16x16_neon| PROC
+;;
+    vld1.8          {q0}, [r0], r1
+    vld1.8          {q4}, [r2], r3
+
+    vld1.8          {q1}, [r0], r1
+    vld1.8          {q5}, [r2], r3
+
+    vabdl.u8        q12, d0, d8
+    vabdl.u8        q13, d1, d9
+
+    vld1.8          {q2}, [r0], r1
+    vld1.8          {q6}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+    vabal.u8        q13, d3, d11
+
+    vld1.8          {q3}, [r0], r1
+    vld1.8          {q7}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+    vabal.u8        q13, d5, d13
+
+;;
+    vld1.8          {q0}, [r0], r1
+    vld1.8          {q4}, [r2], r3
+
+    vabal.u8        q12, d6, d14
+    vabal.u8        q13, d7, d15
+
+    vld1.8          {q1}, [r0], r1
+    vld1.8          {q5}, [r2], r3
+
+    vabal.u8        q12, d0, d8
+    vabal.u8        q13, d1, d9
+
+    vld1.8          {q2}, [r0], r1
+    vld1.8          {q6}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+    vabal.u8        q13, d3, d11
+
+    vld1.8          {q3}, [r0], r1
+    vld1.8          {q7}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+    vabal.u8        q13, d5, d13
+
+;;
+    vld1.8          {q0}, [r0], r1
+    vld1.8          {q4}, [r2], r3
+
+    vabal.u8        q12, d6, d14
+    vabal.u8        q13, d7, d15
+
+    vld1.8          {q1}, [r0], r1
+    vld1.8          {q5}, [r2], r3
+
+    vabal.u8        q12, d0, d8
+    vabal.u8        q13, d1, d9
+
+    vld1.8          {q2}, [r0], r1
+    vld1.8          {q6}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+    vabal.u8        q13, d3, d11
+
+    vld1.8          {q3}, [r0], r1
+    vld1.8          {q7}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+    vabal.u8        q13, d5, d13
+
+;;
+    vld1.8          {q0}, [r0], r1
+    vld1.8          {q4}, [r2], r3
+
+    vabal.u8        q12, d6, d14
+    vabal.u8        q13, d7, d15
+
+    vld1.8          {q1}, [r0], r1
+    vld1.8          {q5}, [r2], r3
+
+    vabal.u8        q12, d0, d8
+    vabal.u8        q13, d1, d9
+
+    vld1.8          {q2}, [r0], r1
+    vld1.8          {q6}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+    vabal.u8        q13, d3, d11
+
+    vld1.8          {q3}, [r0]
+    vld1.8          {q7}, [r2]
+
+    vabal.u8        q12, d4, d12
+    vabal.u8        q13, d5, d13
+
+    vabal.u8        q12, d6, d14
+    vabal.u8        q13, d7, d15
+
+    vadd.u16        q0, q12, q13
+
+    vpaddl.u16      q1, q0
+    vpaddl.u32      q0, q1
+
+    vadd.u32        d0, d0, d1
+
+    vmov.32         r0, d0[0]
+
+    bx              lr
+
+    ENDP
+
+;==============================
+;unsigned int vp8_sad16x8_c(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+|vp8_sad16x8_neon| PROC
+    vld1.8          {q0}, [r0], r1
+    vld1.8          {q4}, [r2], r3
+
+    vld1.8          {q1}, [r0], r1
+    vld1.8          {q5}, [r2], r3
+
+    vabdl.u8        q12, d0, d8
+    vabdl.u8        q13, d1, d9
+
+    vld1.8          {q2}, [r0], r1
+    vld1.8          {q6}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+    vabal.u8        q13, d3, d11
+
+    vld1.8          {q3}, [r0], r1
+    vld1.8          {q7}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+    vabal.u8        q13, d5, d13
+
+    vld1.8          {q0}, [r0], r1
+    vld1.8          {q4}, [r2], r3
+
+    vabal.u8        q12, d6, d14
+    vabal.u8        q13, d7, d15
+
+    vld1.8          {q1}, [r0], r1
+    vld1.8          {q5}, [r2], r3
+
+    vabal.u8        q12, d0, d8
+    vabal.u8        q13, d1, d9
+
+    vld1.8          {q2}, [r0], r1
+    vld1.8          {q6}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+    vabal.u8        q13, d3, d11
+
+    vld1.8          {q3}, [r0], r1
+    vld1.8          {q7}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+    vabal.u8        q13, d5, d13
+
+    vabal.u8        q12, d6, d14
+    vabal.u8        q13, d7, d15
+
+    vadd.u16        q0, q12, q13
+
+    vpaddl.u16      q1, q0
+    vpaddl.u32      q0, q1
+
+    vadd.u32        d0, d0, d1
+
+    vmov.32         r0, d0[0]
+
+    bx              lr
+
+    ENDP
+
+    END
diff --git a/vp8/common/arm/neon/sad8_neon.asm b/vp8/common/arm/neon/sad8_neon.asm
new file mode 100644 (file)
index 0000000..23ba6df
--- /dev/null
@@ -0,0 +1,209 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_sad8x8_neon|
+    EXPORT  |vp8_sad8x16_neon|
+    EXPORT  |vp8_sad4x4_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; unsigned int vp8_sad8x8_c(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+
+|vp8_sad8x8_neon| PROC
+    vld1.8          {d0}, [r0], r1
+    vld1.8          {d8}, [r2], r3
+
+    vld1.8          {d2}, [r0], r1
+    vld1.8          {d10}, [r2], r3
+
+    vabdl.u8        q12, d0, d8
+
+    vld1.8          {d4}, [r0], r1
+    vld1.8          {d12}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+
+    vld1.8          {d6}, [r0], r1
+    vld1.8          {d14}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+
+    vld1.8          {d0}, [r0], r1
+    vld1.8          {d8}, [r2], r3
+
+    vabal.u8        q12, d6, d14
+
+    vld1.8          {d2}, [r0], r1
+    vld1.8          {d10}, [r2], r3
+
+    vabal.u8        q12, d0, d8
+
+    vld1.8          {d4}, [r0], r1
+    vld1.8          {d12}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+
+    vld1.8          {d6}, [r0], r1
+    vld1.8          {d14}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+    vabal.u8        q12, d6, d14
+
+    vpaddl.u16      q1, q12
+    vpaddl.u32      q0, q1
+    vadd.u32        d0, d0, d1
+
+    vmov.32         r0, d0[0]
+
+    bx              lr
+
+    ENDP
+
+;============================
+;unsigned int vp8_sad8x16_c(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+
+|vp8_sad8x16_neon| PROC
+    vld1.8          {d0}, [r0], r1
+    vld1.8          {d8}, [r2], r3
+
+    vld1.8          {d2}, [r0], r1
+    vld1.8          {d10}, [r2], r3
+
+    vabdl.u8        q12, d0, d8
+
+    vld1.8          {d4}, [r0], r1
+    vld1.8          {d12}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+
+    vld1.8          {d6}, [r0], r1
+    vld1.8          {d14}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+
+    vld1.8          {d0}, [r0], r1
+    vld1.8          {d8}, [r2], r3
+
+    vabal.u8        q12, d6, d14
+
+    vld1.8          {d2}, [r0], r1
+    vld1.8          {d10}, [r2], r3
+
+    vabal.u8        q12, d0, d8
+
+    vld1.8          {d4}, [r0], r1
+    vld1.8          {d12}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+
+    vld1.8          {d6}, [r0], r1
+    vld1.8          {d14}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+
+    vld1.8          {d0}, [r0], r1
+    vld1.8          {d8}, [r2], r3
+
+    vabal.u8        q12, d6, d14
+
+    vld1.8          {d2}, [r0], r1
+    vld1.8          {d10}, [r2], r3
+
+    vabal.u8        q12, d0, d8
+
+    vld1.8          {d4}, [r0], r1
+    vld1.8          {d12}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+
+    vld1.8          {d6}, [r0], r1
+    vld1.8          {d14}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+
+    vld1.8          {d0}, [r0], r1
+    vld1.8          {d8}, [r2], r3
+
+    vabal.u8        q12, d6, d14
+
+    vld1.8          {d2}, [r0], r1
+    vld1.8          {d10}, [r2], r3
+
+    vabal.u8        q12, d0, d8
+
+    vld1.8          {d4}, [r0], r1
+    vld1.8          {d12}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+
+    vld1.8          {d6}, [r0], r1
+    vld1.8          {d14}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+    vabal.u8        q12, d6, d14
+
+    vpaddl.u16      q1, q12
+    vpaddl.u32      q0, q1
+    vadd.u32        d0, d0, d1
+
+    vmov.32         r0, d0[0]
+
+    bx              lr
+
+    ENDP
+
+;===========================
+;unsigned int vp8_sad4x4_c(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+
+|vp8_sad4x4_neon| PROC
+    vld1.8          {d0}, [r0], r1
+    vld1.8          {d8}, [r2], r3
+
+    vld1.8          {d2}, [r0], r1
+    vld1.8          {d10}, [r2], r3
+
+    vabdl.u8        q12, d0, d8
+
+    vld1.8          {d4}, [r0], r1
+    vld1.8          {d12}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+
+    vld1.8          {d6}, [r0], r1
+    vld1.8          {d14}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+    vabal.u8        q12, d6, d14
+
+    vpaddl.u16      d1, d24
+    vpaddl.u32      d0, d1
+    vmov.32         r0, d0[0]
+
+    bx              lr
+
+    ENDP
+
+    END
diff --git a/vp8/common/arm/neon/save_reg_neon.asm b/vp8/common/arm/neon/save_reg_neon.asm
new file mode 100644 (file)
index 0000000..fd7002e
--- /dev/null
@@ -0,0 +1,36 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_push_neon|
+    EXPORT  |vp8_pop_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+|vp8_push_neon| PROC
+    vst1.i64            {d8, d9, d10, d11}, [r0]!
+    vst1.i64            {d12, d13, d14, d15}, [r0]!
+    bx              lr
+
+    ENDP
+
+|vp8_pop_neon| PROC
+    vld1.i64            {d8, d9, d10, d11}, [r0]!
+    vld1.i64            {d12, d13, d14, d15}, [r0]!
+    bx              lr
+
+    ENDP
+
+    END
+
diff --git a/vp8/common/arm/neon/shortidct4x4llm_neon.asm b/vp8/common/arm/neon/shortidct4x4llm_neon.asm
new file mode 100644 (file)
index 0000000..67d2ab0
--- /dev/null
@@ -0,0 +1,139 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_short_idct4x4llm_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+;*************************************************************
+;void vp8_short_idct4x4llm_c(short *input, unsigned char *pred, int pitch,
+;                            unsigned char *dst, int stride)
+;r0 short * input
+;r1 short * pred
+;r2 int pitch
+;r3 unsigned char dst
+;sp int stride
+;*************************************************************
+
+; static const int cospi8sqrt2minus1=20091;
+; static const int sinpi8sqrt2      =35468;
+; static const int rounding = 0;
+
+; Optimization note: The resulted data from dequantization are signed
+; 13-bit data that is in the range of [-4096, 4095]. This allows to
+; use "vqdmulh"(neon) instruction since it won't go out of range
+; (13+16+1=30bits<32bits). This instruction gives the high half
+; result of the multiplication that is needed in IDCT.
+
+|vp8_short_idct4x4llm_neon| PROC
+    adr             r12, idct_coeff
+    vld1.16         {q1, q2}, [r0]
+    vld1.16         {d0}, [r12]
+
+    vswp            d3, d4                  ;q2(vp[4] vp[12])
+    ldr             r0, [sp]                ; stride
+
+    vqdmulh.s16     q3, q2, d0[2]
+    vqdmulh.s16     q4, q2, d0[0]
+
+    vqadd.s16       d12, d2, d3             ;a1
+    vqsub.s16       d13, d2, d3             ;b1
+
+    vshr.s16        q3, q3, #1
+    vshr.s16        q4, q4, #1
+
+    vqadd.s16       q3, q3, q2              ;modify since sinpi8sqrt2 > 65536/2 (negtive number)
+    vqadd.s16       q4, q4, q2
+
+    ;d6 - c1:temp1
+    ;d7 - d1:temp2
+    ;d8 - d1:temp1
+    ;d9 - c1:temp2
+
+    vqsub.s16       d10, d6, d9             ;c1
+    vqadd.s16       d11, d7, d8             ;d1
+
+    vqadd.s16       d2, d12, d11
+    vqadd.s16       d3, d13, d10
+    vqsub.s16       d4, d13, d10
+    vqsub.s16       d5, d12, d11
+
+    vtrn.32         d2, d4
+    vtrn.32         d3, d5
+    vtrn.16         d2, d3
+    vtrn.16         d4, d5
+
+    vswp            d3, d4
+
+    vqdmulh.s16     q3, q2, d0[2]
+    vqdmulh.s16     q4, q2, d0[0]
+
+    vqadd.s16       d12, d2, d3             ;a1
+    vqsub.s16       d13, d2, d3             ;b1
+
+    vshr.s16        q3, q3, #1
+    vshr.s16        q4, q4, #1
+
+    vqadd.s16       q3, q3, q2              ;modify since sinpi8sqrt2 > 65536/2 (negtive number)
+    vqadd.s16       q4, q4, q2
+
+    vqsub.s16       d10, d6, d9             ;c1
+    vqadd.s16       d11, d7, d8             ;d1
+
+    vqadd.s16       d2, d12, d11
+    vqadd.s16       d3, d13, d10
+    vqsub.s16       d4, d13, d10
+    vqsub.s16       d5, d12, d11
+
+    vrshr.s16       d2, d2, #3
+    vrshr.s16       d3, d3, #3
+    vrshr.s16       d4, d4, #3
+    vrshr.s16       d5, d5, #3
+
+    vtrn.32         d2, d4
+    vtrn.32         d3, d5
+    vtrn.16         d2, d3
+    vtrn.16         d4, d5
+
+    ; load prediction data
+    vld1.32         d6[0], [r1], r2
+    vld1.32         d6[1], [r1], r2
+    vld1.32         d7[0], [r1], r2
+    vld1.32         d7[1], [r1], r2
+
+    ; add prediction and residual
+    vaddw.u8        q1, q1, d6
+    vaddw.u8        q2, q2, d7
+
+    vqmovun.s16     d1, q1
+    vqmovun.s16     d2, q2
+
+    ; store to destination
+    vst1.32         d1[0], [r3], r0
+    vst1.32         d1[1], [r3], r0
+    vst1.32         d2[0], [r3], r0
+    vst1.32         d2[1], [r3], r0
+
+    bx              lr
+
+    ENDP
+
+;-----------------
+
+idct_coeff
+    DCD     0x4e7b4e7b, 0x8a8c8a8c
+
+;20091, 20091, 35468, 35468
+
+    END
diff --git a/vp8/common/arm/neon/sixtappredict16x16_neon.asm b/vp8/common/arm/neon/sixtappredict16x16_neon.asm
new file mode 100644 (file)
index 0000000..9fdafd3
--- /dev/null
@@ -0,0 +1,490 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_sixtap_predict16x16_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+filter16_coeff
+    DCD     0,  0,  128,    0,   0,  0,   0,  0
+    DCD     0, -6,  123,   12,  -1,  0,   0,  0
+    DCD     2, -11, 108,   36,  -8,  1,   0,  0
+    DCD     0, -9,   93,   50,  -6,  0,   0,  0
+    DCD     3, -16,  77,   77, -16,  3,   0,  0
+    DCD     0, -6,   50,   93,  -9,  0,   0,  0
+    DCD     1, -8,   36,  108, -11,  2,   0,  0
+    DCD     0, -1,   12,  123,  -6,   0,  0,  0
+
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; r4    unsigned char *dst_ptr,
+; stack(r5) int  dst_pitch
+
+;Note: To take advantage of 8-bit mulplication instruction in NEON. First apply abs() to
+; filter coeffs to make them u8. Then, use vmlsl for negtive coeffs. After multiplication,
+; the result can be negtive. So, I treat the result as s16. But, since it is also possible
+; that the result can be a large positive number (> 2^15-1), which could be confused as a
+; negtive number. To avoid that error, apply filter coeffs in the order of 0, 1, 4 ,5 ,2,
+; which ensures that the result stays in s16 range. Finally, saturated add the result by
+; applying 3rd filter coeff. Same applys to other filter functions.
+
+|vp8_sixtap_predict16x16_neon| PROC
+    push            {r4-r5, lr}
+
+    adr             r12, filter16_coeff
+    ldr             r4, [sp, #12]           ;load parameters from stack
+    ldr             r5, [sp, #16]           ;load parameters from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             secondpass_filter16x16_only
+
+    add             r2, r12, r2, lsl #5     ;calculate filter location
+
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+
+    vld1.s32        {q14, q15}, [r2]        ;load first_pass filter
+
+    beq             firstpass_filter16x16_only
+
+    sub             sp, sp, #336            ;reserve space on stack for temporary storage
+    mov             lr, sp
+
+    vabs.s32        q12, q14
+    vabs.s32        q13, q15
+
+    mov             r2, #7                  ;loop counter
+    sub             r0, r0, #2              ;move srcptr back to (line-2) and (column-2)
+    sub             r0, r0, r1, lsl #1
+
+    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
+    vdup.8          d1, d24[4]
+    vdup.8          d2, d25[0]
+    vdup.8          d3, d25[4]
+    vdup.8          d4, d26[0]
+    vdup.8          d5, d26[4]
+
+;First Pass: output_height lines x output_width columns (21x16)
+filt_blk2d_fp16x16_loop_neon
+    vld1.u8         {d6, d7, d8}, [r0], r1      ;load src data
+    vld1.u8         {d9, d10, d11}, [r0], r1
+    vld1.u8         {d12, d13, d14}, [r0], r1
+
+    pld             [r0]
+    pld             [r0, r1]
+    pld             [r0, r1, lsl #1]
+
+    vmull.u8        q8, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q9, d7, d0
+    vmull.u8        q10, d9, d0
+    vmull.u8        q11, d10, d0
+    vmull.u8        q12, d12, d0
+    vmull.u8        q13, d13, d0
+
+    vext.8          d28, d6, d7, #1         ;construct src_ptr[-1]
+    vext.8          d29, d9, d10, #1
+    vext.8          d30, d12, d13, #1
+
+    vmlsl.u8        q8, d28, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q10, d29, d1
+    vmlsl.u8        q12, d30, d1
+
+    vext.8          d28, d7, d8, #1
+    vext.8          d29, d10, d11, #1
+    vext.8          d30, d13, d14, #1
+
+    vmlsl.u8        q9, d28, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q11, d29, d1
+    vmlsl.u8        q13, d30, d1
+
+    vext.8          d28, d6, d7, #4         ;construct src_ptr[2]
+    vext.8          d29, d9, d10, #4
+    vext.8          d30, d12, d13, #4
+
+    vmlsl.u8        q8, d28, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q10, d29, d4
+    vmlsl.u8        q12, d30, d4
+
+    vext.8          d28, d7, d8, #4
+    vext.8          d29, d10, d11, #4
+    vext.8          d30, d13, d14, #4
+
+    vmlsl.u8        q9, d28, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q11, d29, d4
+    vmlsl.u8        q13, d30, d4
+
+    vext.8          d28, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d29, d9, d10, #5
+    vext.8          d30, d12, d13, #5
+
+    vmlal.u8        q8, d28, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q10, d29, d5
+    vmlal.u8        q12, d30, d5
+
+    vext.8          d28, d7, d8, #5
+    vext.8          d29, d10, d11, #5
+    vext.8          d30, d13, d14, #5
+
+    vmlal.u8        q9, d28, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q11, d29, d5
+    vmlal.u8        q13, d30, d5
+
+    vext.8          d28, d6, d7, #2         ;construct src_ptr[0]
+    vext.8          d29, d9, d10, #2
+    vext.8          d30, d12, d13, #2
+
+    vmlal.u8        q8, d28, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q10, d29, d2
+    vmlal.u8        q12, d30, d2
+
+    vext.8          d28, d7, d8, #2
+    vext.8          d29, d10, d11, #2
+    vext.8          d30, d13, d14, #2
+
+    vmlal.u8        q9, d28, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q11, d29, d2
+    vmlal.u8        q13, d30, d2
+
+    vext.8          d28, d6, d7, #3         ;construct src_ptr[1]
+    vext.8          d29, d9, d10, #3
+    vext.8          d30, d12, d13, #3
+
+    vext.8          d15, d7, d8, #3
+    vext.8          d31, d10, d11, #3
+    vext.8          d6, d13, d14, #3
+
+    vmull.u8        q4, d28, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q5, d29, d3
+    vmull.u8        q6, d30, d3
+
+    vqadd.s16       q8, q4                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q10, q5
+    vqadd.s16       q12, q6
+
+    vmull.u8        q6, d15, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q7, d31, d3
+    vmull.u8        q3, d6, d3
+
+    subs            r2, r2, #1
+
+    vqadd.s16       q9, q6
+    vqadd.s16       q11, q7
+    vqadd.s16       q13, q3
+
+    vqrshrun.s16    d6, q8, #7              ;shift/round/saturate to u8
+    vqrshrun.s16    d7, q9, #7
+    vqrshrun.s16    d8, q10, #7
+    vqrshrun.s16    d9, q11, #7
+    vqrshrun.s16    d10, q12, #7
+    vqrshrun.s16    d11, q13, #7
+
+    vst1.u8         {d6, d7, d8}, [lr]!     ;store result
+    vst1.u8         {d9, d10, d11}, [lr]!
+
+    bne             filt_blk2d_fp16x16_loop_neon
+
+;Second pass: 16x16
+;secondpass_filter - do first 8-columns and then second 8-columns
+    add             r3, r12, r3, lsl #5
+    sub             lr, lr, #336
+
+    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
+    mov             r3, #2                  ;loop counter
+
+    vabs.s32        q7, q5
+    vabs.s32        q8, q6
+
+    mov             r2, #16
+
+    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
+    vdup.8          d1, d14[4]
+    vdup.8          d2, d15[0]
+    vdup.8          d3, d15[4]
+    vdup.8          d4, d16[0]
+    vdup.8          d5, d16[4]
+
+filt_blk2d_sp16x16_outloop_neon
+    vld1.u8         {d18}, [lr], r2         ;load src data
+    vld1.u8         {d19}, [lr], r2
+    vld1.u8         {d20}, [lr], r2
+    vld1.u8         {d21}, [lr], r2
+    mov             r12, #4                 ;loop counter
+    vld1.u8         {d22}, [lr], r2
+
+secondpass_inner_loop_neon
+    vld1.u8         {d23}, [lr], r2         ;load src data
+    vld1.u8         {d24}, [lr], r2
+    vld1.u8         {d25}, [lr], r2
+    vld1.u8         {d26}, [lr], r2
+
+    vmull.u8        q3, d18, d0             ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q4, d19, d0
+    vmull.u8        q5, d20, d0
+    vmull.u8        q6, d21, d0
+
+    vmlsl.u8        q3, d19, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q4, d20, d1
+    vmlsl.u8        q5, d21, d1
+    vmlsl.u8        q6, d22, d1
+
+    vmlsl.u8        q3, d22, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q4, d23, d4
+    vmlsl.u8        q5, d24, d4
+    vmlsl.u8        q6, d25, d4
+
+    vmlal.u8        q3, d20, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q4, d21, d2
+    vmlal.u8        q5, d22, d2
+    vmlal.u8        q6, d23, d2
+
+    vmlal.u8        q3, d23, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q4, d24, d5
+    vmlal.u8        q5, d25, d5
+    vmlal.u8        q6, d26, d5
+
+    vmull.u8        q7, d21, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q8, d22, d3
+    vmull.u8        q9, d23, d3
+    vmull.u8        q10, d24, d3
+
+    subs            r12, r12, #1
+
+    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q4
+    vqadd.s16       q9, q5
+    vqadd.s16       q10, q6
+
+    vqrshrun.s16    d6, q7, #7              ;shift/round/saturate to u8
+    vqrshrun.s16    d7, q8, #7
+    vqrshrun.s16    d8, q9, #7
+    vqrshrun.s16    d9, q10, #7
+
+    vst1.u8         {d6}, [r4], r5          ;store result
+    vmov            q9, q11
+    vst1.u8         {d7}, [r4], r5
+    vmov            q10, q12
+    vst1.u8         {d8}, [r4], r5
+    vmov            d22, d26
+    vst1.u8         {d9}, [r4], r5
+
+    bne             secondpass_inner_loop_neon
+
+    subs            r3, r3, #1
+    sub             lr, lr, #336
+    add             lr, lr, #8
+
+    sub             r4, r4, r5, lsl #4
+    add             r4, r4, #8
+
+    bne filt_blk2d_sp16x16_outloop_neon
+
+    add             sp, sp, #336
+    pop             {r4-r5,pc}
+
+;--------------------
+firstpass_filter16x16_only
+    vabs.s32        q12, q14
+    vabs.s32        q13, q15
+
+    mov             r2, #8                  ;loop counter
+    sub             r0, r0, #2              ;move srcptr back to (column-2)
+
+    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
+    vdup.8          d1, d24[4]
+    vdup.8          d2, d25[0]
+    vdup.8          d3, d25[4]
+    vdup.8          d4, d26[0]
+    vdup.8          d5, d26[4]
+
+;First Pass: output_height lines x output_width columns (16x16)
+filt_blk2d_fpo16x16_loop_neon
+    vld1.u8         {d6, d7, d8}, [r0], r1      ;load src data
+    vld1.u8         {d9, d10, d11}, [r0], r1
+
+    pld             [r0]
+    pld             [r0, r1]
+
+    vmull.u8        q6, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q7, d7, d0
+    vmull.u8        q8, d9, d0
+    vmull.u8        q9, d10, d0
+
+    vext.8          d20, d6, d7, #1         ;construct src_ptr[-1]
+    vext.8          d21, d9, d10, #1
+    vext.8          d22, d7, d8, #1
+    vext.8          d23, d10, d11, #1
+    vext.8          d24, d6, d7, #4         ;construct src_ptr[2]
+    vext.8          d25, d9, d10, #4
+    vext.8          d26, d7, d8, #4
+    vext.8          d27, d10, d11, #4
+    vext.8          d28, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d29, d9, d10, #5
+
+    vmlsl.u8        q6, d20, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q8, d21, d1
+    vmlsl.u8        q7, d22, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q9, d23, d1
+    vmlsl.u8        q6, d24, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q8, d25, d4
+    vmlsl.u8        q7, d26, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q9, d27, d4
+    vmlal.u8        q6, d28, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q8, d29, d5
+
+    vext.8          d20, d7, d8, #5
+    vext.8          d21, d10, d11, #5
+    vext.8          d22, d6, d7, #2         ;construct src_ptr[0]
+    vext.8          d23, d9, d10, #2
+    vext.8          d24, d7, d8, #2
+    vext.8          d25, d10, d11, #2
+
+    vext.8          d26, d6, d7, #3         ;construct src_ptr[1]
+    vext.8          d27, d9, d10, #3
+    vext.8          d28, d7, d8, #3
+    vext.8          d29, d10, d11, #3
+
+    vmlal.u8        q7, d20, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q9, d21, d5
+    vmlal.u8        q6, d22, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q8, d23, d2
+    vmlal.u8        q7, d24, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q9, d25, d2
+
+    vmull.u8        q10, d26, d3            ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q11, d27, d3
+    vmull.u8        q12, d28, d3            ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q15, d29, d3
+
+    vqadd.s16       q6, q10                 ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q11
+    vqadd.s16       q7, q12
+    vqadd.s16       q9, q15
+
+    subs            r2, r2, #1
+
+    vqrshrun.s16    d6, q6, #7              ;shift/round/saturate to u8
+    vqrshrun.s16    d7, q7, #7
+    vqrshrun.s16    d8, q8, #7
+    vqrshrun.s16    d9, q9, #7
+
+    vst1.u8         {q3}, [r4], r5              ;store result
+    vst1.u8         {q4}, [r4], r5
+
+    bne             filt_blk2d_fpo16x16_loop_neon
+
+    pop             {r4-r5,pc}
+
+;--------------------
+secondpass_filter16x16_only
+;Second pass: 16x16
+    add             r3, r12, r3, lsl #5
+    sub             r0, r0, r1, lsl #1
+
+    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
+    mov             r3, #2                  ;loop counter
+
+    vabs.s32        q7, q5
+    vabs.s32        q8, q6
+
+    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
+    vdup.8          d1, d14[4]
+    vdup.8          d2, d15[0]
+    vdup.8          d3, d15[4]
+    vdup.8          d4, d16[0]
+    vdup.8          d5, d16[4]
+
+filt_blk2d_spo16x16_outloop_neon
+    vld1.u8         {d18}, [r0], r1         ;load src data
+    vld1.u8         {d19}, [r0], r1
+    vld1.u8         {d20}, [r0], r1
+    vld1.u8         {d21}, [r0], r1
+    mov             r12, #4                 ;loop counter
+    vld1.u8         {d22}, [r0], r1
+
+secondpass_only_inner_loop_neon
+    vld1.u8         {d23}, [r0], r1         ;load src data
+    vld1.u8         {d24}, [r0], r1
+    vld1.u8         {d25}, [r0], r1
+    vld1.u8         {d26}, [r0], r1
+
+    vmull.u8        q3, d18, d0             ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q4, d19, d0
+    vmull.u8        q5, d20, d0
+    vmull.u8        q6, d21, d0
+
+    vmlsl.u8        q3, d19, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q4, d20, d1
+    vmlsl.u8        q5, d21, d1
+    vmlsl.u8        q6, d22, d1
+
+    vmlsl.u8        q3, d22, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q4, d23, d4
+    vmlsl.u8        q5, d24, d4
+    vmlsl.u8        q6, d25, d4
+
+    vmlal.u8        q3, d20, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q4, d21, d2
+    vmlal.u8        q5, d22, d2
+    vmlal.u8        q6, d23, d2
+
+    vmlal.u8        q3, d23, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q4, d24, d5
+    vmlal.u8        q5, d25, d5
+    vmlal.u8        q6, d26, d5
+
+    vmull.u8        q7, d21, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q8, d22, d3
+    vmull.u8        q9, d23, d3
+    vmull.u8        q10, d24, d3
+
+    subs            r12, r12, #1
+
+    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q4
+    vqadd.s16       q9, q5
+    vqadd.s16       q10, q6
+
+    vqrshrun.s16    d6, q7, #7              ;shift/round/saturate to u8
+    vqrshrun.s16    d7, q8, #7
+    vqrshrun.s16    d8, q9, #7
+    vqrshrun.s16    d9, q10, #7
+
+    vst1.u8         {d6}, [r4], r5          ;store result
+    vmov            q9, q11
+    vst1.u8         {d7}, [r4], r5
+    vmov            q10, q12
+    vst1.u8         {d8}, [r4], r5
+    vmov            d22, d26
+    vst1.u8         {d9}, [r4], r5
+
+    bne             secondpass_only_inner_loop_neon
+
+    subs            r3, r3, #1
+    sub             r0, r0, r1, lsl #4
+    sub             r0, r0, r1, lsl #2
+    sub             r0, r0, r1
+    add             r0, r0, #8
+
+    sub             r4, r4, r5, lsl #4
+    add             r4, r4, #8
+
+    bne filt_blk2d_spo16x16_outloop_neon
+
+    pop             {r4-r5,pc}
+
+    ENDP
+
+;-----------------
+    END
diff --git a/vp8/common/arm/neon/sixtappredict4x4_neon.asm b/vp8/common/arm/neon/sixtappredict4x4_neon.asm
new file mode 100644 (file)
index 0000000..a4222bc
--- /dev/null
@@ -0,0 +1,422 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_sixtap_predict4x4_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+filter4_coeff
+    DCD     0,  0,  128,    0,   0,  0,   0,  0
+    DCD     0, -6,  123,   12,  -1,  0,   0,  0
+    DCD     2, -11, 108,   36,  -8,  1,   0,  0
+    DCD     0, -9,   93,   50,  -6,  0,   0,  0
+    DCD     3, -16,  77,   77, -16,  3,   0,  0
+    DCD     0, -6,   50,   93,  -9,  0,   0,  0
+    DCD     1, -8,   36,  108, -11,  2,   0,  0
+    DCD     0, -1,   12,  123,  -6,   0,  0,  0
+
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; stack(r4) unsigned char *dst_ptr,
+; stack(lr) int  dst_pitch
+
+|vp8_sixtap_predict4x4_neon| PROC
+    push            {r4, lr}
+
+    adr             r12, filter4_coeff
+    ldr             r4, [sp, #8]            ;load parameters from stack
+    ldr             lr, [sp, #12]           ;load parameters from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             secondpass_filter4x4_only
+
+    add             r2, r12, r2, lsl #5     ;calculate filter location
+
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+    vld1.s32        {q14, q15}, [r2]        ;load first_pass filter
+
+    beq             firstpass_filter4x4_only
+
+    vabs.s32        q12, q14                ;get abs(filer_parameters)
+    vabs.s32        q13, q15
+
+    sub             r0, r0, #2              ;go back 2 columns of src data
+    sub             r0, r0, r1, lsl #1      ;go back 2 lines of src data
+
+;First pass: output_height lines x output_width columns (9x4)
+    vld1.u8         {q3}, [r0], r1          ;load first 4-line src data
+    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
+    vld1.u8         {q4}, [r0], r1
+    vdup.8          d1, d24[4]
+    vld1.u8         {q5}, [r0], r1
+    vdup.8          d2, d25[0]
+    vld1.u8         {q6}, [r0], r1
+    vdup.8          d3, d25[4]
+    vdup.8          d4, d26[0]
+    vdup.8          d5, d26[4]
+
+    pld             [r0]
+    pld             [r0, r1]
+    pld             [r0, r1, lsl #1]
+
+    vext.8          d18, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d19, d8, d9, #5
+    vext.8          d20, d10, d11, #5
+    vext.8          d21, d12, d13, #5
+
+    vswp            d7, d8                  ;discard 2nd half data after src_ptr[3] is done
+    vswp            d11, d12
+
+    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[3])
+    vzip.32         d20, d21
+    vmull.u8        q7, d18, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmull.u8        q8, d20, d5
+
+    vmov            q4, q3                  ;keep original src data in q4 q6
+    vmov            q6, q5
+
+    vzip.32         d6, d7                  ;construct src_ptr[-2], and put 2-line data together
+    vzip.32         d10, d11
+    vshr.u64        q9, q4, #8              ;construct src_ptr[-1]
+    vshr.u64        q10, q6, #8
+    vmlal.u8        q7, d6, d0              ;+(src_ptr[-2] * vp8_filter[0])
+    vmlal.u8        q8, d10, d0
+
+    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[-1])
+    vzip.32         d20, d21
+    vshr.u64        q3, q4, #32             ;construct src_ptr[2]
+    vshr.u64        q5, q6, #32
+    vmlsl.u8        q7, d18, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q8, d20, d1
+
+    vzip.32         d6, d7                  ;put 2-line data in 1 register (src_ptr[2])
+    vzip.32         d10, d11
+    vshr.u64        q9, q4, #16             ;construct src_ptr[0]
+    vshr.u64        q10, q6, #16
+    vmlsl.u8        q7, d6, d4              ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q8, d10, d4
+
+    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[0])
+    vzip.32         d20, d21
+    vshr.u64        q3, q4, #24             ;construct src_ptr[1]
+    vshr.u64        q5, q6, #24
+    vmlal.u8        q7, d18, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q8, d20, d2
+
+    vzip.32         d6, d7                  ;put 2-line data in 1 register (src_ptr[1])
+    vzip.32         d10, d11
+    vmull.u8        q9, d6, d3              ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q10, d10, d3
+
+    vld1.u8         {q3}, [r0], r1          ;load rest 5-line src data
+    vld1.u8         {q4}, [r0], r1
+
+    vqadd.s16       q7, q9                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q10
+
+    vld1.u8         {q5}, [r0], r1
+    vld1.u8         {q6}, [r0], r1
+
+    vqrshrun.s16    d27, q7, #7             ;shift/round/saturate to u8
+    vqrshrun.s16    d28, q8, #7
+
+    ;First Pass on rest 5-line data
+    vld1.u8         {q11}, [r0], r1
+
+    vext.8          d18, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d19, d8, d9, #5
+    vext.8          d20, d10, d11, #5
+    vext.8          d21, d12, d13, #5
+
+    vswp            d7, d8                  ;discard 2nd half data after src_ptr[3] is done
+    vswp            d11, d12
+
+    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[3])
+    vzip.32         d20, d21
+    vext.8          d31, d22, d23, #5       ;construct src_ptr[3]
+    vmull.u8        q7, d18, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmull.u8        q8, d20, d5
+    vmull.u8        q12, d31, d5            ;(src_ptr[3] * vp8_filter[5])
+
+    vmov            q4, q3                  ;keep original src data in q4 q6
+    vmov            q6, q5
+
+    vzip.32         d6, d7                  ;construct src_ptr[-2], and put 2-line data together
+    vzip.32         d10, d11
+    vshr.u64        q9, q4, #8              ;construct src_ptr[-1]
+    vshr.u64        q10, q6, #8
+
+    vmlal.u8        q7, d6, d0              ;+(src_ptr[-2] * vp8_filter[0])
+    vmlal.u8        q8, d10, d0
+    vmlal.u8        q12, d22, d0            ;(src_ptr[-2] * vp8_filter[0])
+
+    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[-1])
+    vzip.32         d20, d21
+    vshr.u64        q3, q4, #32             ;construct src_ptr[2]
+    vshr.u64        q5, q6, #32
+    vext.8          d31, d22, d23, #1       ;construct src_ptr[-1]
+
+    vmlsl.u8        q7, d18, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q8, d20, d1
+    vmlsl.u8        q12, d31, d1            ;-(src_ptr[-1] * vp8_filter[1])
+
+    vzip.32         d6, d7                  ;put 2-line data in 1 register (src_ptr[2])
+    vzip.32         d10, d11
+    vshr.u64        q9, q4, #16             ;construct src_ptr[0]
+    vshr.u64        q10, q6, #16
+    vext.8          d31, d22, d23, #4       ;construct src_ptr[2]
+
+    vmlsl.u8        q7, d6, d4              ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q8, d10, d4
+    vmlsl.u8        q12, d31, d4            ;-(src_ptr[2] * vp8_filter[4])
+
+    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[0])
+    vzip.32         d20, d21
+    vshr.u64        q3, q4, #24             ;construct src_ptr[1]
+    vshr.u64        q5, q6, #24
+    vext.8          d31, d22, d23, #2       ;construct src_ptr[0]
+
+    vmlal.u8        q7, d18, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q8, d20, d2
+    vmlal.u8        q12, d31, d2            ;(src_ptr[0] * vp8_filter[2])
+
+    vzip.32         d6, d7                  ;put 2-line data in 1 register (src_ptr[1])
+    vzip.32         d10, d11
+    vext.8          d31, d22, d23, #3       ;construct src_ptr[1]
+    vmull.u8        q9, d6, d3              ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q10, d10, d3
+    vmull.u8        q11, d31, d3            ;(src_ptr[1] * vp8_filter[3])
+
+    add             r3, r12, r3, lsl #5
+
+    vqadd.s16       q7, q9                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q10
+    vqadd.s16       q12, q11
+
+    vext.8          d23, d27, d28, #4
+    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
+
+    vqrshrun.s16    d29, q7, #7             ;shift/round/saturate to u8
+    vqrshrun.s16    d30, q8, #7
+    vqrshrun.s16    d31, q12, #7
+
+;Second pass: 4x4
+    vabs.s32        q7, q5
+    vabs.s32        q8, q6
+
+    vext.8          d24, d28, d29, #4
+    vext.8          d25, d29, d30, #4
+    vext.8          d26, d30, d31, #4
+
+    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
+    vdup.8          d1, d14[4]
+    vdup.8          d2, d15[0]
+    vdup.8          d3, d15[4]
+    vdup.8          d4, d16[0]
+    vdup.8          d5, d16[4]
+
+    vmull.u8        q3, d27, d0             ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q4, d28, d0
+
+    vmull.u8        q5, d25, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmull.u8        q6, d26, d5
+
+    vmlsl.u8        q3, d29, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q4, d30, d4
+
+    vmlsl.u8        q5, d23, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q6, d24, d1
+
+    vmlal.u8        q3, d28, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q4, d29, d2
+
+    vmlal.u8        q5, d24, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmlal.u8        q6, d25, d3
+
+    add             r0, r4, lr
+    add             r1, r0, lr
+    add             r2, r1, lr
+
+    vqadd.s16       q5, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q6, q4
+
+    vqrshrun.s16    d3, q5, #7              ;shift/round/saturate to u8
+    vqrshrun.s16    d4, q6, #7
+
+    vst1.32         {d3[0]}, [r4]           ;store result
+    vst1.32         {d3[1]}, [r0]
+    vst1.32         {d4[0]}, [r1]
+    vst1.32         {d4[1]}, [r2]
+
+    pop             {r4, pc}
+
+
+;---------------------
+firstpass_filter4x4_only
+    vabs.s32        q12, q14                ;get abs(filer_parameters)
+    vabs.s32        q13, q15
+
+    sub             r0, r0, #2              ;go back 2 columns of src data
+
+;First pass: output_height lines x output_width columns (4x4)
+    vld1.u8         {q3}, [r0], r1          ;load first 4-line src data
+    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
+    vld1.u8         {q4}, [r0], r1
+    vdup.8          d1, d24[4]
+    vld1.u8         {q5}, [r0], r1
+    vdup.8          d2, d25[0]
+    vld1.u8         {q6}, [r0], r1
+
+    vdup.8          d3, d25[4]
+    vdup.8          d4, d26[0]
+    vdup.8          d5, d26[4]
+
+    vext.8          d18, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d19, d8, d9, #5
+    vext.8          d20, d10, d11, #5
+    vext.8          d21, d12, d13, #5
+
+    vswp            d7, d8                  ;discard 2nd half data after src_ptr[3] is done
+    vswp            d11, d12
+
+    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[3])
+    vzip.32         d20, d21
+    vmull.u8        q7, d18, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmull.u8        q8, d20, d5
+
+    vmov            q4, q3                  ;keep original src data in q4 q6
+    vmov            q6, q5
+
+    vzip.32         d6, d7                  ;construct src_ptr[-2], and put 2-line data together
+    vzip.32         d10, d11
+    vshr.u64        q9, q4, #8              ;construct src_ptr[-1]
+    vshr.u64        q10, q6, #8
+    vmlal.u8        q7, d6, d0              ;+(src_ptr[-2] * vp8_filter[0])
+    vmlal.u8        q8, d10, d0
+
+    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[-1])
+    vzip.32         d20, d21
+    vshr.u64        q3, q4, #32             ;construct src_ptr[2]
+    vshr.u64        q5, q6, #32
+    vmlsl.u8        q7, d18, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q8, d20, d1
+
+    vzip.32         d6, d7                  ;put 2-line data in 1 register (src_ptr[2])
+    vzip.32         d10, d11
+    vshr.u64        q9, q4, #16             ;construct src_ptr[0]
+    vshr.u64        q10, q6, #16
+    vmlsl.u8        q7, d6, d4              ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q8, d10, d4
+
+    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[0])
+    vzip.32         d20, d21
+    vshr.u64        q3, q4, #24             ;construct src_ptr[1]
+    vshr.u64        q5, q6, #24
+    vmlal.u8        q7, d18, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q8, d20, d2
+
+    vzip.32         d6, d7                  ;put 2-line data in 1 register (src_ptr[1])
+    vzip.32         d10, d11
+    vmull.u8        q9, d6, d3              ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q10, d10, d3
+
+    add             r0, r4, lr
+    add             r1, r0, lr
+    add             r2, r1, lr
+
+    vqadd.s16       q7, q9                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q10
+
+    vqrshrun.s16    d27, q7, #7             ;shift/round/saturate to u8
+    vqrshrun.s16    d28, q8, #7
+
+    vst1.32         {d27[0]}, [r4]          ;store result
+    vst1.32         {d27[1]}, [r0]
+    vst1.32         {d28[0]}, [r1]
+    vst1.32         {d28[1]}, [r2]
+
+    pop             {r4, pc}
+
+
+;---------------------
+secondpass_filter4x4_only
+    sub             r0, r0, r1, lsl #1
+    add             r3, r12, r3, lsl #5
+
+    vld1.32         {d27[0]}, [r0], r1      ;load src data
+    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
+    vld1.32         {d27[1]}, [r0], r1
+    vabs.s32        q7, q5
+    vld1.32         {d28[0]}, [r0], r1
+    vabs.s32        q8, q6
+    vld1.32         {d28[1]}, [r0], r1
+    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
+    vld1.32         {d29[0]}, [r0], r1
+    vdup.8          d1, d14[4]
+    vld1.32         {d29[1]}, [r0], r1
+    vdup.8          d2, d15[0]
+    vld1.32         {d30[0]}, [r0], r1
+    vdup.8          d3, d15[4]
+    vld1.32         {d30[1]}, [r0], r1
+    vdup.8          d4, d16[0]
+    vld1.32         {d31[0]}, [r0], r1
+    vdup.8          d5, d16[4]
+
+    vext.8          d23, d27, d28, #4
+    vext.8          d24, d28, d29, #4
+    vext.8          d25, d29, d30, #4
+    vext.8          d26, d30, d31, #4
+
+    vmull.u8        q3, d27, d0             ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q4, d28, d0
+
+    vmull.u8        q5, d25, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmull.u8        q6, d26, d5
+
+    vmlsl.u8        q3, d29, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q4, d30, d4
+
+    vmlsl.u8        q5, d23, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q6, d24, d1
+
+    vmlal.u8        q3, d28, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q4, d29, d2
+
+    vmlal.u8        q5, d24, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmlal.u8        q6, d25, d3
+
+    add             r0, r4, lr
+    add             r1, r0, lr
+    add             r2, r1, lr
+
+    vqadd.s16       q5, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q6, q4
+
+    vqrshrun.s16    d3, q5, #7              ;shift/round/saturate to u8
+    vqrshrun.s16    d4, q6, #7
+
+    vst1.32         {d3[0]}, [r4]           ;store result
+    vst1.32         {d3[1]}, [r0]
+    vst1.32         {d4[0]}, [r1]
+    vst1.32         {d4[1]}, [r2]
+
+    pop             {r4, pc}
+
+    ENDP
+
+;-----------------
+
+    END
diff --git a/vp8/common/arm/neon/sixtappredict8x4_neon.asm b/vp8/common/arm/neon/sixtappredict8x4_neon.asm
new file mode 100644 (file)
index 0000000..a57ec01
--- /dev/null
@@ -0,0 +1,473 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_sixtap_predict8x4_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+filter8_coeff
+    DCD     0,  0,  128,    0,   0,  0,   0,  0
+    DCD     0, -6,  123,   12,  -1,  0,   0,  0
+    DCD     2, -11, 108,   36,  -8,  1,   0,  0
+    DCD     0, -9,   93,   50,  -6,  0,   0,  0
+    DCD     3, -16,  77,   77, -16,  3,   0,  0
+    DCD     0, -6,   50,   93,  -9,  0,   0,  0
+    DCD     1, -8,   36,  108, -11,  2,   0,  0
+    DCD     0, -1,   12,  123,  -6,   0,  0,  0
+
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; r4    unsigned char *dst_ptr,
+; stack(r5) int  dst_pitch
+
+|vp8_sixtap_predict8x4_neon| PROC
+    push            {r4-r5, lr}
+
+    adr             r12, filter8_coeff
+    ldr             r4, [sp, #12]           ;load parameters from stack
+    ldr             r5, [sp, #16]           ;load parameters from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             secondpass_filter8x4_only
+
+    add             r2, r12, r2, lsl #5     ;calculate filter location
+
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+
+    vld1.s32        {q14, q15}, [r2]        ;load first_pass filter
+
+    beq             firstpass_filter8x4_only
+
+    sub             sp, sp, #32             ;reserve space on stack for temporary storage
+    vabs.s32        q12, q14
+    vabs.s32        q13, q15
+
+    sub             r0, r0, #2              ;move srcptr back to (line-2) and (column-2)
+    mov             lr, sp
+    sub             r0, r0, r1, lsl #1
+
+    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
+    vdup.8          d1, d24[4]
+    vdup.8          d2, d25[0]
+
+;First pass: output_height lines x output_width columns (9x8)
+    vld1.u8         {q3}, [r0], r1          ;load src data
+    vdup.8          d3, d25[4]
+    vld1.u8         {q4}, [r0], r1
+    vdup.8          d4, d26[0]
+    vld1.u8         {q5}, [r0], r1
+    vdup.8          d5, d26[4]
+    vld1.u8         {q6}, [r0], r1
+
+    pld             [r0]
+    pld             [r0, r1]
+    pld             [r0, r1, lsl #1]
+
+    vmull.u8        q7, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q8, d8, d0
+    vmull.u8        q9, d10, d0
+    vmull.u8        q10, d12, d0
+
+    vext.8          d28, d6, d7, #1         ;construct src_ptr[-1]
+    vext.8          d29, d8, d9, #1
+    vext.8          d30, d10, d11, #1
+    vext.8          d31, d12, d13, #1
+
+    vmlsl.u8        q7, d28, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q8, d29, d1
+    vmlsl.u8        q9, d30, d1
+    vmlsl.u8        q10, d31, d1
+
+    vext.8          d28, d6, d7, #4         ;construct src_ptr[2]
+    vext.8          d29, d8, d9, #4
+    vext.8          d30, d10, d11, #4
+    vext.8          d31, d12, d13, #4
+
+    vmlsl.u8        q7, d28, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q8, d29, d4
+    vmlsl.u8        q9, d30, d4
+    vmlsl.u8        q10, d31, d4
+
+    vext.8          d28, d6, d7, #2         ;construct src_ptr[0]
+    vext.8          d29, d8, d9, #2
+    vext.8          d30, d10, d11, #2
+    vext.8          d31, d12, d13, #2
+
+    vmlal.u8        q7, d28, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q8, d29, d2
+    vmlal.u8        q9, d30, d2
+    vmlal.u8        q10, d31, d2
+
+    vext.8          d28, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d29, d8, d9, #5
+    vext.8          d30, d10, d11, #5
+    vext.8          d31, d12, d13, #5
+
+    vmlal.u8        q7, d28, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q8, d29, d5
+    vmlal.u8        q9, d30, d5
+    vmlal.u8        q10, d31, d5
+
+    vext.8          d28, d6, d7, #3         ;construct src_ptr[1]
+    vext.8          d29, d8, d9, #3
+    vext.8          d30, d10, d11, #3
+    vext.8          d31, d12, d13, #3
+
+    vmull.u8        q3, d28, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q4, d29, d3
+    vmull.u8        q5, d30, d3
+    vmull.u8        q6, d31, d3
+
+    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q4
+    vqadd.s16       q9, q5
+    vqadd.s16       q10, q6
+
+    vld1.u8         {q3}, [r0], r1          ;load src data
+
+    vqrshrun.s16    d22, q7, #7             ;shift/round/saturate to u8
+    vqrshrun.s16    d23, q8, #7
+    vqrshrun.s16    d24, q9, #7
+    vqrshrun.s16    d25, q10, #7
+
+    vld1.u8         {q4}, [r0], r1
+    vst1.u8         {d22}, [lr]!            ;store result
+    vld1.u8         {q5}, [r0], r1
+    vst1.u8         {d23}, [lr]!
+    vld1.u8         {q6}, [r0], r1
+    vst1.u8         {d24}, [lr]!
+    vld1.u8         {q7}, [r0], r1
+    vst1.u8         {d25}, [lr]!
+
+    ;first_pass filtering on the rest 5-line data
+    vmull.u8        q8, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q9, d8, d0
+    vmull.u8        q10, d10, d0
+    vmull.u8        q11, d12, d0
+    vmull.u8        q12, d14, d0
+
+    vext.8          d27, d6, d7, #1         ;construct src_ptr[-1]
+    vext.8          d28, d8, d9, #1
+    vext.8          d29, d10, d11, #1
+    vext.8          d30, d12, d13, #1
+    vext.8          d31, d14, d15, #1
+
+    vmlsl.u8        q8, d27, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q9, d28, d1
+    vmlsl.u8        q10, d29, d1
+    vmlsl.u8        q11, d30, d1
+    vmlsl.u8        q12, d31, d1
+
+    vext.8          d27, d6, d7, #4         ;construct src_ptr[2]
+    vext.8          d28, d8, d9, #4
+    vext.8          d29, d10, d11, #4
+    vext.8          d30, d12, d13, #4
+    vext.8          d31, d14, d15, #4
+
+    vmlsl.u8        q8, d27, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q9, d28, d4
+    vmlsl.u8        q10, d29, d4
+    vmlsl.u8        q11, d30, d4
+    vmlsl.u8        q12, d31, d4
+
+    vext.8          d27, d6, d7, #2         ;construct src_ptr[0]
+    vext.8          d28, d8, d9, #2
+    vext.8          d29, d10, d11, #2
+    vext.8          d30, d12, d13, #2
+    vext.8          d31, d14, d15, #2
+
+    vmlal.u8        q8, d27, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q9, d28, d2
+    vmlal.u8        q10, d29, d2
+    vmlal.u8        q11, d30, d2
+    vmlal.u8        q12, d31, d2
+
+    vext.8          d27, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d28, d8, d9, #5
+    vext.8          d29, d10, d11, #5
+    vext.8          d30, d12, d13, #5
+    vext.8          d31, d14, d15, #5
+
+    vmlal.u8        q8, d27, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q9, d28, d5
+    vmlal.u8        q10, d29, d5
+    vmlal.u8        q11, d30, d5
+    vmlal.u8        q12, d31, d5
+
+    vext.8          d27, d6, d7, #3         ;construct src_ptr[1]
+    vext.8          d28, d8, d9, #3
+    vext.8          d29, d10, d11, #3
+    vext.8          d30, d12, d13, #3
+    vext.8          d31, d14, d15, #3
+
+    vmull.u8        q3, d27, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q4, d28, d3
+    vmull.u8        q5, d29, d3
+    vmull.u8        q6, d30, d3
+    vmull.u8        q7, d31, d3
+
+    vqadd.s16       q8, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q9, q4
+    vqadd.s16       q10, q5
+    vqadd.s16       q11, q6
+    vqadd.s16       q12, q7
+
+    vqrshrun.s16    d26, q8, #7             ;shift/round/saturate to u8
+    vqrshrun.s16    d27, q9, #7
+    vqrshrun.s16    d28, q10, #7
+    vqrshrun.s16    d29, q11, #7                ;load intermediate data from stack
+    vqrshrun.s16    d30, q12, #7
+
+;Second pass: 8x4
+;secondpass_filter
+    add             r3, r12, r3, lsl #5
+    sub             lr, lr, #32
+
+    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
+    vld1.u8         {q11}, [lr]!
+
+    vabs.s32        q7, q5
+    vabs.s32        q8, q6
+
+    vld1.u8         {q12}, [lr]!
+
+    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
+    vdup.8          d1, d14[4]
+    vdup.8          d2, d15[0]
+    vdup.8          d3, d15[4]
+    vdup.8          d4, d16[0]
+    vdup.8          d5, d16[4]
+
+    vmull.u8        q3, d22, d0             ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q4, d23, d0
+    vmull.u8        q5, d24, d0
+    vmull.u8        q6, d25, d0
+
+    vmlsl.u8        q3, d23, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q4, d24, d1
+    vmlsl.u8        q5, d25, d1
+    vmlsl.u8        q6, d26, d1
+
+    vmlsl.u8        q3, d26, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q4, d27, d4
+    vmlsl.u8        q5, d28, d4
+    vmlsl.u8        q6, d29, d4
+
+    vmlal.u8        q3, d24, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q4, d25, d2
+    vmlal.u8        q5, d26, d2
+    vmlal.u8        q6, d27, d2
+
+    vmlal.u8        q3, d27, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q4, d28, d5
+    vmlal.u8        q5, d29, d5
+    vmlal.u8        q6, d30, d5
+
+    vmull.u8        q7, d25, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q8, d26, d3
+    vmull.u8        q9, d27, d3
+    vmull.u8        q10, d28, d3
+
+    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q4
+    vqadd.s16       q9, q5
+    vqadd.s16       q10, q6
+
+    vqrshrun.s16    d6, q7, #7              ;shift/round/saturate to u8
+    vqrshrun.s16    d7, q8, #7
+    vqrshrun.s16    d8, q9, #7
+    vqrshrun.s16    d9, q10, #7
+
+    vst1.u8         {d6}, [r4], r5          ;store result
+    vst1.u8         {d7}, [r4], r5
+    vst1.u8         {d8}, [r4], r5
+    vst1.u8         {d9}, [r4], r5
+
+    add             sp, sp, #32
+    pop             {r4-r5,pc}
+
+;--------------------
+firstpass_filter8x4_only
+    vabs.s32        q12, q14
+    vabs.s32        q13, q15
+
+    sub             r0, r0, #2              ;move srcptr back to (line-2) and (column-2)
+    vld1.u8         {q3}, [r0], r1          ;load src data
+
+    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
+    vld1.u8         {q4}, [r0], r1
+    vdup.8          d1, d24[4]
+    vld1.u8         {q5}, [r0], r1
+    vdup.8          d2, d25[0]
+    vld1.u8         {q6}, [r0], r1
+    vdup.8          d3, d25[4]
+    vdup.8          d4, d26[0]
+    vdup.8          d5, d26[4]
+
+;First pass: output_height lines x output_width columns (4x8)
+    pld             [r0]
+    pld             [r0, r1]
+    pld             [r0, r1, lsl #1]
+
+    vmull.u8        q7, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q8, d8, d0
+    vmull.u8        q9, d10, d0
+    vmull.u8        q10, d12, d0
+
+    vext.8          d28, d6, d7, #1         ;construct src_ptr[-1]
+    vext.8          d29, d8, d9, #1
+    vext.8          d30, d10, d11, #1
+    vext.8          d31, d12, d13, #1
+
+    vmlsl.u8        q7, d28, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q8, d29, d1
+    vmlsl.u8        q9, d30, d1
+    vmlsl.u8        q10, d31, d1
+
+    vext.8          d28, d6, d7, #4         ;construct src_ptr[2]
+    vext.8          d29, d8, d9, #4
+    vext.8          d30, d10, d11, #4
+    vext.8          d31, d12, d13, #4
+
+    vmlsl.u8        q7, d28, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q8, d29, d4
+    vmlsl.u8        q9, d30, d4
+    vmlsl.u8        q10, d31, d4
+
+    vext.8          d28, d6, d7, #2         ;construct src_ptr[0]
+    vext.8          d29, d8, d9, #2
+    vext.8          d30, d10, d11, #2
+    vext.8          d31, d12, d13, #2
+
+    vmlal.u8        q7, d28, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q8, d29, d2
+    vmlal.u8        q9, d30, d2
+    vmlal.u8        q10, d31, d2
+
+    vext.8          d28, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d29, d8, d9, #5
+    vext.8          d30, d10, d11, #5
+    vext.8          d31, d12, d13, #5
+
+    vmlal.u8        q7, d28, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q8, d29, d5
+    vmlal.u8        q9, d30, d5
+    vmlal.u8        q10, d31, d5
+
+    vext.8          d28, d6, d7, #3         ;construct src_ptr[1]
+    vext.8          d29, d8, d9, #3
+    vext.8          d30, d10, d11, #3
+    vext.8          d31, d12, d13, #3
+
+    vmull.u8        q3, d28, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q4, d29, d3
+    vmull.u8        q5, d30, d3
+    vmull.u8        q6, d31, d3
+
+    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q4
+    vqadd.s16       q9, q5
+    vqadd.s16       q10, q6
+
+    vqrshrun.s16    d22, q7, #7             ;shift/round/saturate to u8
+    vqrshrun.s16    d23, q8, #7
+    vqrshrun.s16    d24, q9, #7
+    vqrshrun.s16    d25, q10, #7
+
+    vst1.u8         {d22}, [r4], r5         ;store result
+    vst1.u8         {d23}, [r4], r5
+    vst1.u8         {d24}, [r4], r5
+    vst1.u8         {d25}, [r4], r5
+
+    pop             {r4-r5,pc}
+
+;---------------------
+secondpass_filter8x4_only
+;Second pass: 8x4
+    add             r3, r12, r3, lsl #5
+    sub             r0, r0, r1, lsl #1
+    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
+    vabs.s32        q7, q5
+    vabs.s32        q8, q6
+
+    vld1.u8         {d22}, [r0], r1
+    vld1.u8         {d23}, [r0], r1
+    vld1.u8         {d24}, [r0], r1
+    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
+    vld1.u8         {d25}, [r0], r1
+    vdup.8          d1, d14[4]
+    vld1.u8         {d26}, [r0], r1
+    vdup.8          d2, d15[0]
+    vld1.u8         {d27}, [r0], r1
+    vdup.8          d3, d15[4]
+    vld1.u8         {d28}, [r0], r1
+    vdup.8          d4, d16[0]
+    vld1.u8         {d29}, [r0], r1
+    vdup.8          d5, d16[4]
+    vld1.u8         {d30}, [r0], r1
+
+    vmull.u8        q3, d22, d0             ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q4, d23, d0
+    vmull.u8        q5, d24, d0
+    vmull.u8        q6, d25, d0
+
+    vmlsl.u8        q3, d23, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q4, d24, d1
+    vmlsl.u8        q5, d25, d1
+    vmlsl.u8        q6, d26, d1
+
+    vmlsl.u8        q3, d26, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q4, d27, d4
+    vmlsl.u8        q5, d28, d4
+    vmlsl.u8        q6, d29, d4
+
+    vmlal.u8        q3, d24, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q4, d25, d2
+    vmlal.u8        q5, d26, d2
+    vmlal.u8        q6, d27, d2
+
+    vmlal.u8        q3, d27, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q4, d28, d5
+    vmlal.u8        q5, d29, d5
+    vmlal.u8        q6, d30, d5
+
+    vmull.u8        q7, d25, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q8, d26, d3
+    vmull.u8        q9, d27, d3
+    vmull.u8        q10, d28, d3
+
+    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q4
+    vqadd.s16       q9, q5
+    vqadd.s16       q10, q6
+
+    vqrshrun.s16    d6, q7, #7              ;shift/round/saturate to u8
+    vqrshrun.s16    d7, q8, #7
+    vqrshrun.s16    d8, q9, #7
+    vqrshrun.s16    d9, q10, #7
+
+    vst1.u8         {d6}, [r4], r5          ;store result
+    vst1.u8         {d7}, [r4], r5
+    vst1.u8         {d8}, [r4], r5
+    vst1.u8         {d9}, [r4], r5
+
+    pop             {r4-r5,pc}
+
+    ENDP
+
+;-----------------
+
+    END
diff --git a/vp8/common/arm/neon/sixtappredict8x8_neon.asm b/vp8/common/arm/neon/sixtappredict8x8_neon.asm
new file mode 100644 (file)
index 0000000..00ed5ae
--- /dev/null
@@ -0,0 +1,524 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_sixtap_predict8x8_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+filter8_coeff
+    DCD     0,  0,  128,    0,   0,  0,   0,  0
+    DCD     0, -6,  123,   12,  -1,  0,   0,  0
+    DCD     2, -11, 108,   36,  -8,  1,   0,  0
+    DCD     0, -9,   93,   50,  -6,  0,   0,  0
+    DCD     3, -16,  77,   77, -16,  3,   0,  0
+    DCD     0, -6,   50,   93,  -9,  0,   0,  0
+    DCD     1, -8,   36,  108, -11,  2,   0,  0
+    DCD     0, -1,   12,  123,  -6,   0,  0,  0
+
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; stack(r4) unsigned char *dst_ptr,
+; stack(r5) int  dst_pitch
+
+|vp8_sixtap_predict8x8_neon| PROC
+    push            {r4-r5, lr}
+
+    adr             r12, filter8_coeff
+
+    ldr             r4, [sp, #12]           ;load parameters from stack
+    ldr             r5, [sp, #16]           ;load parameters from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             secondpass_filter8x8_only
+
+    add             r2, r12, r2, lsl #5     ;calculate filter location
+
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+
+    vld1.s32        {q14, q15}, [r2]        ;load first_pass filter
+
+    beq             firstpass_filter8x8_only
+
+    sub             sp, sp, #64             ;reserve space on stack for temporary storage
+    mov             lr, sp
+
+    vabs.s32        q12, q14
+    vabs.s32        q13, q15
+
+    mov             r2, #2                  ;loop counter
+    sub             r0, r0, #2              ;move srcptr back to (line-2) and (column-2)
+    sub             r0, r0, r1, lsl #1
+
+    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
+    vdup.8          d1, d24[4]
+    vdup.8          d2, d25[0]
+
+;First pass: output_height lines x output_width columns (13x8)
+    vld1.u8         {q3}, [r0], r1          ;load src data
+    vdup.8          d3, d25[4]
+    vld1.u8         {q4}, [r0], r1
+    vdup.8          d4, d26[0]
+    vld1.u8         {q5}, [r0], r1
+    vdup.8          d5, d26[4]
+    vld1.u8         {q6}, [r0], r1
+
+filt_blk2d_fp8x8_loop_neon
+    pld             [r0]
+    pld             [r0, r1]
+    pld             [r0, r1, lsl #1]
+
+    vmull.u8        q7, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q8, d8, d0
+    vmull.u8        q9, d10, d0
+    vmull.u8        q10, d12, d0
+
+    vext.8          d28, d6, d7, #1         ;construct src_ptr[-1]
+    vext.8          d29, d8, d9, #1
+    vext.8          d30, d10, d11, #1
+    vext.8          d31, d12, d13, #1
+
+    vmlsl.u8        q7, d28, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q8, d29, d1
+    vmlsl.u8        q9, d30, d1
+    vmlsl.u8        q10, d31, d1
+
+    vext.8          d28, d6, d7, #4         ;construct src_ptr[2]
+    vext.8          d29, d8, d9, #4
+    vext.8          d30, d10, d11, #4
+    vext.8          d31, d12, d13, #4
+
+    vmlsl.u8        q7, d28, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q8, d29, d4
+    vmlsl.u8        q9, d30, d4
+    vmlsl.u8        q10, d31, d4
+
+    vext.8          d28, d6, d7, #2         ;construct src_ptr[0]
+    vext.8          d29, d8, d9, #2
+    vext.8          d30, d10, d11, #2
+    vext.8          d31, d12, d13, #2
+
+    vmlal.u8        q7, d28, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q8, d29, d2
+    vmlal.u8        q9, d30, d2
+    vmlal.u8        q10, d31, d2
+
+    vext.8          d28, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d29, d8, d9, #5
+    vext.8          d30, d10, d11, #5
+    vext.8          d31, d12, d13, #5
+
+    vmlal.u8        q7, d28, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q8, d29, d5
+    vmlal.u8        q9, d30, d5
+    vmlal.u8        q10, d31, d5
+
+    vext.8          d28, d6, d7, #3         ;construct src_ptr[1]
+    vext.8          d29, d8, d9, #3
+    vext.8          d30, d10, d11, #3
+    vext.8          d31, d12, d13, #3
+
+    vmull.u8        q3, d28, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q4, d29, d3
+    vmull.u8        q5, d30, d3
+    vmull.u8        q6, d31, d3
+
+    subs            r2, r2, #1
+
+    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q4
+    vqadd.s16       q9, q5
+    vqadd.s16       q10, q6
+
+    vld1.u8         {q3}, [r0], r1          ;load src data
+
+    vqrshrun.s16    d22, q7, #7             ;shift/round/saturate to u8
+    vqrshrun.s16    d23, q8, #7
+    vqrshrun.s16    d24, q9, #7
+    vqrshrun.s16    d25, q10, #7
+
+    vst1.u8         {d22}, [lr]!            ;store result
+    vld1.u8         {q4}, [r0], r1
+    vst1.u8         {d23}, [lr]!
+    vld1.u8         {q5}, [r0], r1
+    vst1.u8         {d24}, [lr]!
+    vld1.u8         {q6}, [r0], r1
+    vst1.u8         {d25}, [lr]!
+
+    bne             filt_blk2d_fp8x8_loop_neon
+
+    ;first_pass filtering on the rest 5-line data
+    ;vld1.u8            {q3}, [r0], r1          ;load src data
+    ;vld1.u8            {q4}, [r0], r1
+    ;vld1.u8            {q5}, [r0], r1
+    ;vld1.u8            {q6}, [r0], r1
+    vld1.u8         {q7}, [r0], r1
+
+    vmull.u8        q8, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q9, d8, d0
+    vmull.u8        q10, d10, d0
+    vmull.u8        q11, d12, d0
+    vmull.u8        q12, d14, d0
+
+    vext.8          d27, d6, d7, #1         ;construct src_ptr[-1]
+    vext.8          d28, d8, d9, #1
+    vext.8          d29, d10, d11, #1
+    vext.8          d30, d12, d13, #1
+    vext.8          d31, d14, d15, #1
+
+    vmlsl.u8        q8, d27, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q9, d28, d1
+    vmlsl.u8        q10, d29, d1
+    vmlsl.u8        q11, d30, d1
+    vmlsl.u8        q12, d31, d1
+
+    vext.8          d27, d6, d7, #4         ;construct src_ptr[2]
+    vext.8          d28, d8, d9, #4
+    vext.8          d29, d10, d11, #4
+    vext.8          d30, d12, d13, #4
+    vext.8          d31, d14, d15, #4
+
+    vmlsl.u8        q8, d27, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q9, d28, d4
+    vmlsl.u8        q10, d29, d4
+    vmlsl.u8        q11, d30, d4
+    vmlsl.u8        q12, d31, d4
+
+    vext.8          d27, d6, d7, #2         ;construct src_ptr[0]
+    vext.8          d28, d8, d9, #2
+    vext.8          d29, d10, d11, #2
+    vext.8          d30, d12, d13, #2
+    vext.8          d31, d14, d15, #2
+
+    vmlal.u8        q8, d27, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q9, d28, d2
+    vmlal.u8        q10, d29, d2
+    vmlal.u8        q11, d30, d2
+    vmlal.u8        q12, d31, d2
+
+    vext.8          d27, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d28, d8, d9, #5
+    vext.8          d29, d10, d11, #5
+    vext.8          d30, d12, d13, #5
+    vext.8          d31, d14, d15, #5
+
+    vmlal.u8        q8, d27, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q9, d28, d5
+    vmlal.u8        q10, d29, d5
+    vmlal.u8        q11, d30, d5
+    vmlal.u8        q12, d31, d5
+
+    vext.8          d27, d6, d7, #3         ;construct src_ptr[1]
+    vext.8          d28, d8, d9, #3
+    vext.8          d29, d10, d11, #3
+    vext.8          d30, d12, d13, #3
+    vext.8          d31, d14, d15, #3
+
+    vmull.u8        q3, d27, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q4, d28, d3
+    vmull.u8        q5, d29, d3
+    vmull.u8        q6, d30, d3
+    vmull.u8        q7, d31, d3
+
+    vqadd.s16       q8, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q9, q4
+    vqadd.s16       q10, q5
+    vqadd.s16       q11, q6
+    vqadd.s16       q12, q7
+
+    add             r3, r12, r3, lsl #5
+
+    vqrshrun.s16    d26, q8, #7             ;shift/round/saturate to u8
+    sub             lr, lr, #64
+    vqrshrun.s16    d27, q9, #7
+    vld1.u8         {q9}, [lr]!             ;load intermediate data from stack
+    vqrshrun.s16    d28, q10, #7
+    vld1.u8         {q10}, [lr]!
+
+    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
+
+    vqrshrun.s16    d29, q11, #7
+    vld1.u8         {q11}, [lr]!
+
+    vabs.s32        q7, q5
+    vabs.s32        q8, q6
+
+    vqrshrun.s16    d30, q12, #7
+    vld1.u8         {q12}, [lr]!
+
+;Second pass: 8x8
+    mov             r3, #2                  ;loop counter
+
+    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
+    vdup.8          d1, d14[4]
+    vdup.8          d2, d15[0]
+    vdup.8          d3, d15[4]
+    vdup.8          d4, d16[0]
+    vdup.8          d5, d16[4]
+
+filt_blk2d_sp8x8_loop_neon
+    vmull.u8        q3, d18, d0             ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q4, d19, d0
+    vmull.u8        q5, d20, d0
+    vmull.u8        q6, d21, d0
+
+    vmlsl.u8        q3, d19, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q4, d20, d1
+    vmlsl.u8        q5, d21, d1
+    vmlsl.u8        q6, d22, d1
+
+    vmlsl.u8        q3, d22, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q4, d23, d4
+    vmlsl.u8        q5, d24, d4
+    vmlsl.u8        q6, d25, d4
+
+    vmlal.u8        q3, d20, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q4, d21, d2
+    vmlal.u8        q5, d22, d2
+    vmlal.u8        q6, d23, d2
+
+    vmlal.u8        q3, d23, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q4, d24, d5
+    vmlal.u8        q5, d25, d5
+    vmlal.u8        q6, d26, d5
+
+    vmull.u8        q7, d21, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q8, d22, d3
+    vmull.u8        q9, d23, d3
+    vmull.u8        q10, d24, d3
+
+    subs            r3, r3, #1
+
+    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q4
+    vqadd.s16       q9, q5
+    vqadd.s16       q10, q6
+
+    vqrshrun.s16    d6, q7, #7              ;shift/round/saturate to u8
+    vqrshrun.s16    d7, q8, #7
+    vqrshrun.s16    d8, q9, #7
+    vqrshrun.s16    d9, q10, #7
+
+    vmov            q9, q11
+    vst1.u8         {d6}, [r4], r5          ;store result
+    vmov            q10, q12
+    vst1.u8         {d7}, [r4], r5
+    vmov            q11, q13
+    vst1.u8         {d8}, [r4], r5
+    vmov            q12, q14
+    vst1.u8         {d9}, [r4], r5
+    vmov            d26, d30
+
+    bne filt_blk2d_sp8x8_loop_neon
+
+    add             sp, sp, #64
+    pop             {r4-r5,pc}
+
+;---------------------
+firstpass_filter8x8_only
+    ;add                r2, r12, r2, lsl #5     ;calculate filter location
+    ;vld1.s32       {q14, q15}, [r2]        ;load first_pass filter
+    vabs.s32        q12, q14
+    vabs.s32        q13, q15
+
+    mov             r2, #2                  ;loop counter
+    sub             r0, r0, #2              ;move srcptr back to (line-2) and (column-2)
+
+    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
+    vdup.8          d1, d24[4]
+    vdup.8          d2, d25[0]
+    vdup.8          d3, d25[4]
+    vdup.8          d4, d26[0]
+    vdup.8          d5, d26[4]
+
+;First pass: output_height lines x output_width columns (8x8)
+filt_blk2d_fpo8x8_loop_neon
+    vld1.u8         {q3}, [r0], r1          ;load src data
+    vld1.u8         {q4}, [r0], r1
+    vld1.u8         {q5}, [r0], r1
+    vld1.u8         {q6}, [r0], r1
+
+    pld             [r0]
+    pld             [r0, r1]
+    pld             [r0, r1, lsl #1]
+
+    vmull.u8        q7, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q8, d8, d0
+    vmull.u8        q9, d10, d0
+    vmull.u8        q10, d12, d0
+
+    vext.8          d28, d6, d7, #1         ;construct src_ptr[-1]
+    vext.8          d29, d8, d9, #1
+    vext.8          d30, d10, d11, #1
+    vext.8          d31, d12, d13, #1
+
+    vmlsl.u8        q7, d28, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q8, d29, d1
+    vmlsl.u8        q9, d30, d1
+    vmlsl.u8        q10, d31, d1
+
+    vext.8          d28, d6, d7, #4         ;construct src_ptr[2]
+    vext.8          d29, d8, d9, #4
+    vext.8          d30, d10, d11, #4
+    vext.8          d31, d12, d13, #4
+
+    vmlsl.u8        q7, d28, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q8, d29, d4
+    vmlsl.u8        q9, d30, d4
+    vmlsl.u8        q10, d31, d4
+
+    vext.8          d28, d6, d7, #2         ;construct src_ptr[0]
+    vext.8          d29, d8, d9, #2
+    vext.8          d30, d10, d11, #2
+    vext.8          d31, d12, d13, #2
+
+    vmlal.u8        q7, d28, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q8, d29, d2
+    vmlal.u8        q9, d30, d2
+    vmlal.u8        q10, d31, d2
+
+    vext.8          d28, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d29, d8, d9, #5
+    vext.8          d30, d10, d11, #5
+    vext.8          d31, d12, d13, #5
+
+    vmlal.u8        q7, d28, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q8, d29, d5
+    vmlal.u8        q9, d30, d5
+    vmlal.u8        q10, d31, d5
+
+    vext.8          d28, d6, d7, #3         ;construct src_ptr[1]
+    vext.8          d29, d8, d9, #3
+    vext.8          d30, d10, d11, #3
+    vext.8          d31, d12, d13, #3
+
+    vmull.u8        q3, d28, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q4, d29, d3
+    vmull.u8        q5, d30, d3
+    vmull.u8        q6, d31, d3
+ ;
+    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q4
+    vqadd.s16       q9, q5
+    vqadd.s16       q10, q6
+
+    subs            r2, r2, #1
+
+    vqrshrun.s16    d22, q7, #7             ;shift/round/saturate to u8
+    vqrshrun.s16    d23, q8, #7
+    vqrshrun.s16    d24, q9, #7
+    vqrshrun.s16    d25, q10, #7
+
+    vst1.u8         {d22}, [r4], r5         ;store result
+    vst1.u8         {d23}, [r4], r5
+    vst1.u8         {d24}, [r4], r5
+    vst1.u8         {d25}, [r4], r5
+
+    bne             filt_blk2d_fpo8x8_loop_neon
+
+    pop             {r4-r5,pc}
+
+;---------------------
+secondpass_filter8x8_only
+    sub             r0, r0, r1, lsl #1
+    add             r3, r12, r3, lsl #5
+
+    vld1.u8         {d18}, [r0], r1         ;load src data
+    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
+    vld1.u8         {d19}, [r0], r1
+    vabs.s32        q7, q5
+    vld1.u8         {d20}, [r0], r1
+    vabs.s32        q8, q6
+    vld1.u8         {d21}, [r0], r1
+    mov             r3, #2                  ;loop counter
+    vld1.u8         {d22}, [r0], r1
+    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
+    vld1.u8         {d23}, [r0], r1
+    vdup.8          d1, d14[4]
+    vld1.u8         {d24}, [r0], r1
+    vdup.8          d2, d15[0]
+    vld1.u8         {d25}, [r0], r1
+    vdup.8          d3, d15[4]
+    vld1.u8         {d26}, [r0], r1
+    vdup.8          d4, d16[0]
+    vld1.u8         {d27}, [r0], r1
+    vdup.8          d5, d16[4]
+    vld1.u8         {d28}, [r0], r1
+    vld1.u8         {d29}, [r0], r1
+    vld1.u8         {d30}, [r0], r1
+
+;Second pass: 8x8
+filt_blk2d_spo8x8_loop_neon
+    vmull.u8        q3, d18, d0             ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q4, d19, d0
+    vmull.u8        q5, d20, d0
+    vmull.u8        q6, d21, d0
+
+    vmlsl.u8        q3, d19, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q4, d20, d1
+    vmlsl.u8        q5, d21, d1
+    vmlsl.u8        q6, d22, d1
+
+    vmlsl.u8        q3, d22, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q4, d23, d4
+    vmlsl.u8        q5, d24, d4
+    vmlsl.u8        q6, d25, d4
+
+    vmlal.u8        q3, d20, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q4, d21, d2
+    vmlal.u8        q5, d22, d2
+    vmlal.u8        q6, d23, d2
+
+    vmlal.u8        q3, d23, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q4, d24, d5
+    vmlal.u8        q5, d25, d5
+    vmlal.u8        q6, d26, d5
+
+    vmull.u8        q7, d21, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q8, d22, d3
+    vmull.u8        q9, d23, d3
+    vmull.u8        q10, d24, d3
+
+    subs            r3, r3, #1
+
+    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q4
+    vqadd.s16       q9, q5
+    vqadd.s16       q10, q6
+
+    vqrshrun.s16    d6, q7, #7              ;shift/round/saturate to u8
+    vqrshrun.s16    d7, q8, #7
+    vqrshrun.s16    d8, q9, #7
+    vqrshrun.s16    d9, q10, #7
+
+    vmov            q9, q11
+    vst1.u8         {d6}, [r4], r5          ;store result
+    vmov            q10, q12
+    vst1.u8         {d7}, [r4], r5
+    vmov            q11, q13
+    vst1.u8         {d8}, [r4], r5
+    vmov            q12, q14
+    vst1.u8         {d9}, [r4], r5
+    vmov            d26, d30
+
+    bne filt_blk2d_spo8x8_loop_neon
+
+    pop             {r4-r5,pc}
+
+    ENDP
+
+;-----------------
+
+    END
diff --git a/vp8/common/arm/neon/variance_neon.asm b/vp8/common/arm/neon/variance_neon.asm
new file mode 100644 (file)
index 0000000..e3b4832
--- /dev/null
@@ -0,0 +1,276 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_variance16x16_neon|
+    EXPORT  |vp8_variance16x8_neon|
+    EXPORT  |vp8_variance8x16_neon|
+    EXPORT  |vp8_variance8x8_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    unsigned char *src_ptr
+; r1    int source_stride
+; r2    unsigned char *ref_ptr
+; r3    int  recon_stride
+; stack unsigned int *sse
+|vp8_variance16x16_neon| PROC
+    vmov.i8         q8, #0                      ;q8 - sum
+    vmov.i8         q9, #0                      ;q9, q10 - sse
+    vmov.i8         q10, #0
+
+    mov             r12, #8
+
+variance16x16_neon_loop
+    vld1.8          {q0}, [r0], r1              ;Load up source and reference
+    vld1.8          {q2}, [r2], r3
+    vld1.8          {q1}, [r0], r1
+    vld1.8          {q3}, [r2], r3
+
+    vsubl.u8        q11, d0, d4                 ;calculate diff
+    vsubl.u8        q12, d1, d5
+    vsubl.u8        q13, d2, d6
+    vsubl.u8        q14, d3, d7
+
+    ;VPADAL adds adjacent pairs of elements of a vector, and accumulates
+    ;the results into the elements of the destination vector. The explanation
+    ;in ARM guide is wrong.
+    vpadal.s16      q8, q11                     ;calculate sum
+    vmlal.s16       q9, d22, d22                ;calculate sse
+    vmlal.s16       q10, d23, d23
+
+    subs            r12, r12, #1
+
+    vpadal.s16      q8, q12
+    vmlal.s16       q9, d24, d24
+    vmlal.s16       q10, d25, d25
+    vpadal.s16      q8, q13
+    vmlal.s16       q9, d26, d26
+    vmlal.s16       q10, d27, d27
+    vpadal.s16      q8, q14
+    vmlal.s16       q9, d28, d28
+    vmlal.s16       q10, d29, d29
+
+    bne             variance16x16_neon_loop
+
+    vadd.u32        q10, q9, q10                ;accumulate sse
+    vpaddl.s32      q0, q8                      ;accumulate sum
+
+    ldr             r12, [sp]                   ;load *sse from stack
+
+    vpaddl.u32      q1, q10
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    ;vmov.32        r0, d0[0]                   ;this instruction costs a lot
+    ;vmov.32        r1, d1[0]
+    ;mul            r0, r0, r0
+    ;str            r1, [r12]
+    ;sub            r0, r1, r0, lsr #8
+
+    ; while sum is signed, sum * sum is always positive and must be treated as
+    ; unsigned to avoid propagating the sign bit.
+    vmull.s32       q5, d0, d0
+    vst1.32         {d1[0]}, [r12]              ;store sse
+    vshr.u32        d10, d10, #8
+    vsub.u32        d0, d1, d10
+
+    vmov.32         r0, d0[0]                   ;return
+    bx              lr
+
+    ENDP
+
+;================================
+;unsigned int vp8_variance16x8_c(
+;    unsigned char *src_ptr,
+;    int  source_stride,
+;    unsigned char *ref_ptr,
+;    int  recon_stride,
+;   unsigned int *sse)
+|vp8_variance16x8_neon| PROC
+    vmov.i8         q8, #0                      ;q8 - sum
+    vmov.i8         q9, #0                      ;q9, q10 - sse
+    vmov.i8         q10, #0
+
+    mov             r12, #4
+
+variance16x8_neon_loop
+    vld1.8          {q0}, [r0], r1              ;Load up source and reference
+    vld1.8          {q2}, [r2], r3
+    vld1.8          {q1}, [r0], r1
+    vld1.8          {q3}, [r2], r3
+
+    vsubl.u8        q11, d0, d4                 ;calculate diff
+    vsubl.u8        q12, d1, d5
+    vsubl.u8        q13, d2, d6
+    vsubl.u8        q14, d3, d7
+
+    vpadal.s16      q8, q11                     ;calculate sum
+    vmlal.s16       q9, d22, d22                ;calculate sse
+    vmlal.s16       q10, d23, d23
+
+    subs            r12, r12, #1
+
+    vpadal.s16      q8, q12
+    vmlal.s16       q9, d24, d24
+    vmlal.s16       q10, d25, d25
+    vpadal.s16      q8, q13
+    vmlal.s16       q9, d26, d26
+    vmlal.s16       q10, d27, d27
+    vpadal.s16      q8, q14
+    vmlal.s16       q9, d28, d28
+    vmlal.s16       q10, d29, d29
+
+    bne             variance16x8_neon_loop
+
+    vadd.u32        q10, q9, q10                ;accumulate sse
+    vpaddl.s32      q0, q8                      ;accumulate sum
+
+    ldr             r12, [sp]                   ;load *sse from stack
+
+    vpaddl.u32      q1, q10
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    vmull.s32       q5, d0, d0
+    vst1.32         {d1[0]}, [r12]              ;store sse
+    vshr.u32        d10, d10, #7
+    vsub.u32        d0, d1, d10
+
+    vmov.32         r0, d0[0]                   ;return
+    bx              lr
+
+    ENDP
+
+;=================================
+;unsigned int vp8_variance8x16_c(
+;    unsigned char *src_ptr,
+;    int  source_stride,
+;    unsigned char *ref_ptr,
+;    int  recon_stride,
+;   unsigned int *sse)
+
+|vp8_variance8x16_neon| PROC
+    vmov.i8         q8, #0                      ;q8 - sum
+    vmov.i8         q9, #0                      ;q9, q10 - sse
+    vmov.i8         q10, #0
+
+    mov             r12, #8
+
+variance8x16_neon_loop
+    vld1.8          {d0}, [r0], r1              ;Load up source and reference
+    vld1.8          {d4}, [r2], r3
+    vld1.8          {d2}, [r0], r1
+    vld1.8          {d6}, [r2], r3
+
+    vsubl.u8        q11, d0, d4                 ;calculate diff
+    vsubl.u8        q12, d2, d6
+
+    vpadal.s16      q8, q11                     ;calculate sum
+    vmlal.s16       q9, d22, d22                ;calculate sse
+    vmlal.s16       q10, d23, d23
+
+    subs            r12, r12, #1
+
+    vpadal.s16      q8, q12
+    vmlal.s16       q9, d24, d24
+    vmlal.s16       q10, d25, d25
+
+    bne             variance8x16_neon_loop
+
+    vadd.u32        q10, q9, q10                ;accumulate sse
+    vpaddl.s32      q0, q8                      ;accumulate sum
+
+    ldr             r12, [sp]                   ;load *sse from stack
+
+    vpaddl.u32      q1, q10
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    vmull.s32       q5, d0, d0
+    vst1.32         {d1[0]}, [r12]              ;store sse
+    vshr.u32        d10, d10, #7
+    vsub.u32        d0, d1, d10
+
+    vmov.32         r0, d0[0]                   ;return
+    bx              lr
+
+    ENDP
+
+;==================================
+; r0    unsigned char *src_ptr
+; r1    int source_stride
+; r2    unsigned char *ref_ptr
+; r3    int  recon_stride
+; stack unsigned int *sse
+|vp8_variance8x8_neon| PROC
+    vmov.i8         q8, #0                      ;q8 - sum
+    vmov.i8         q9, #0                      ;q9, q10 - sse
+    vmov.i8         q10, #0
+
+    mov             r12, #2
+
+variance8x8_neon_loop
+    vld1.8          {d0}, [r0], r1              ;Load up source and reference
+    vld1.8          {d4}, [r2], r3
+    vld1.8          {d1}, [r0], r1
+    vld1.8          {d5}, [r2], r3
+    vld1.8          {d2}, [r0], r1
+    vld1.8          {d6}, [r2], r3
+    vld1.8          {d3}, [r0], r1
+    vld1.8          {d7}, [r2], r3
+
+    vsubl.u8        q11, d0, d4                 ;calculate diff
+    vsubl.u8        q12, d1, d5
+    vsubl.u8        q13, d2, d6
+    vsubl.u8        q14, d3, d7
+
+    vpadal.s16      q8, q11                     ;calculate sum
+    vmlal.s16       q9, d22, d22                ;calculate sse
+    vmlal.s16       q10, d23, d23
+
+    subs            r12, r12, #1
+
+    vpadal.s16      q8, q12
+    vmlal.s16       q9, d24, d24
+    vmlal.s16       q10, d25, d25
+    vpadal.s16      q8, q13
+    vmlal.s16       q9, d26, d26
+    vmlal.s16       q10, d27, d27
+    vpadal.s16      q8, q14
+    vmlal.s16       q9, d28, d28
+    vmlal.s16       q10, d29, d29
+
+    bne             variance8x8_neon_loop
+
+    vadd.u32        q10, q9, q10                ;accumulate sse
+    vpaddl.s32      q0, q8                      ;accumulate sum
+
+    ldr             r12, [sp]                   ;load *sse from stack
+
+    vpaddl.u32      q1, q10
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    vmull.s32       q5, d0, d0
+    vst1.32         {d1[0]}, [r12]              ;store sse
+    vshr.u32        d10, d10, #6
+    vsub.u32        d0, d1, d10
+
+    vmov.32         r0, d0[0]                   ;return
+    bx              lr
+
+    ENDP
+
+    END
diff --git a/vp8/common/arm/neon/vp8_subpixelvariance16x16_neon.asm b/vp8/common/arm/neon/vp8_subpixelvariance16x16_neon.asm
new file mode 100644 (file)
index 0000000..e7a3ed1
--- /dev/null
@@ -0,0 +1,423 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+bilinear_taps_coeff
+    DCD     128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112
+
+;-----------------
+
+    EXPORT  |vp8_sub_pixel_variance16x16_neon_func|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; stack(r4) unsigned char *dst_ptr,
+; stack(r5) int dst_pixels_per_line,
+; stack(r6) unsigned int *sse
+;note: most of the code is copied from bilinear_predict16x16_neon and vp8_variance16x16_neon.
+
+|vp8_sub_pixel_variance16x16_neon_func| PROC
+    push            {r4-r6, lr}
+
+    adr             r12, bilinear_taps_coeff
+    ldr             r4, [sp, #16]           ;load *dst_ptr from stack
+    ldr             r5, [sp, #20]           ;load dst_pixels_per_line from stack
+    ldr             r6, [sp, #24]           ;load *sse from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             secondpass_bfilter16x16_only
+
+    add             r2, r12, r2, lsl #3     ;calculate filter location
+
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+
+    vld1.s32        {d31}, [r2]             ;load first_pass filter
+
+    beq             firstpass_bfilter16x16_only
+
+    sub             sp, sp, #272            ;reserve space on stack for temporary storage
+    vld1.u8         {d2, d3, d4}, [r0], r1      ;load src data
+    mov             lr, sp
+    vld1.u8         {d5, d6, d7}, [r0], r1
+
+    mov             r2, #3                  ;loop counter
+    vld1.u8         {d8, d9, d10}, [r0], r1
+
+    vdup.8          d0, d31[0]              ;first_pass filter (d0 d1)
+    vld1.u8         {d11, d12, d13}, [r0], r1
+
+    vdup.8          d1, d31[4]
+
+;First Pass: output_height lines x output_width columns (17x16)
+vp8e_filt_blk2d_fp16x16_loop_neon
+    pld             [r0]
+    pld             [r0, r1]
+    pld             [r0, r1, lsl #1]
+
+    vmull.u8        q7, d2, d0              ;(src_ptr[0] * Filter[0])
+    vmull.u8        q8, d3, d0
+    vmull.u8        q9, d5, d0
+    vmull.u8        q10, d6, d0
+    vmull.u8        q11, d8, d0
+    vmull.u8        q12, d9, d0
+    vmull.u8        q13, d11, d0
+    vmull.u8        q14, d12, d0
+
+    vext.8          d2, d2, d3, #1          ;construct src_ptr[1]
+    vext.8          d5, d5, d6, #1
+    vext.8          d8, d8, d9, #1
+    vext.8          d11, d11, d12, #1
+
+    vmlal.u8        q7, d2, d1              ;(src_ptr[0] * Filter[1])
+    vmlal.u8        q9, d5, d1
+    vmlal.u8        q11, d8, d1
+    vmlal.u8        q13, d11, d1
+
+    vext.8          d3, d3, d4, #1
+    vext.8          d6, d6, d7, #1
+    vext.8          d9, d9, d10, #1
+    vext.8          d12, d12, d13, #1
+
+    vmlal.u8        q8, d3, d1              ;(src_ptr[0] * Filter[1])
+    vmlal.u8        q10, d6, d1
+    vmlal.u8        q12, d9, d1
+    vmlal.u8        q14, d12, d1
+
+    subs            r2, r2, #1
+
+    vqrshrn.u16    d14, q7, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d15, q8, #7
+    vqrshrn.u16    d16, q9, #7
+    vqrshrn.u16    d17, q10, #7
+    vqrshrn.u16    d18, q11, #7
+    vqrshrn.u16    d19, q12, #7
+    vqrshrn.u16    d20, q13, #7
+
+    vld1.u8         {d2, d3, d4}, [r0], r1      ;load src data
+    vqrshrn.u16    d21, q14, #7
+    vld1.u8         {d5, d6, d7}, [r0], r1
+
+    vst1.u8         {d14, d15, d16, d17}, [lr]!     ;store result
+    vld1.u8         {d8, d9, d10}, [r0], r1
+    vst1.u8         {d18, d19, d20, d21}, [lr]!
+    vld1.u8         {d11, d12, d13}, [r0], r1
+
+    bne             vp8e_filt_blk2d_fp16x16_loop_neon
+
+;First-pass filtering for rest 5 lines
+    vld1.u8         {d14, d15, d16}, [r0], r1
+
+    vmull.u8        q9, d2, d0              ;(src_ptr[0] * Filter[0])
+    vmull.u8        q10, d3, d0
+    vmull.u8        q11, d5, d0
+    vmull.u8        q12, d6, d0
+    vmull.u8        q13, d8, d0
+    vmull.u8        q14, d9, d0
+
+    vext.8          d2, d2, d3, #1          ;construct src_ptr[1]
+    vext.8          d5, d5, d6, #1
+    vext.8          d8, d8, d9, #1
+
+    vmlal.u8        q9, d2, d1              ;(src_ptr[0] * Filter[1])
+    vmlal.u8        q11, d5, d1
+    vmlal.u8        q13, d8, d1
+
+    vext.8          d3, d3, d4, #1
+    vext.8          d6, d6, d7, #1
+    vext.8          d9, d9, d10, #1
+
+    vmlal.u8        q10, d3, d1             ;(src_ptr[0] * Filter[1])
+    vmlal.u8        q12, d6, d1
+    vmlal.u8        q14, d9, d1
+
+    vmull.u8        q1, d11, d0
+    vmull.u8        q2, d12, d0
+    vmull.u8        q3, d14, d0
+    vmull.u8        q4, d15, d0
+
+    vext.8          d11, d11, d12, #1       ;construct src_ptr[1]
+    vext.8          d14, d14, d15, #1
+
+    vmlal.u8        q1, d11, d1             ;(src_ptr[0] * Filter[1])
+    vmlal.u8        q3, d14, d1
+
+    vext.8          d12, d12, d13, #1
+    vext.8          d15, d15, d16, #1
+
+    vmlal.u8        q2, d12, d1             ;(src_ptr[0] * Filter[1])
+    vmlal.u8        q4, d15, d1
+
+    vqrshrn.u16    d10, q9, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d11, q10, #7
+    vqrshrn.u16    d12, q11, #7
+    vqrshrn.u16    d13, q12, #7
+    vqrshrn.u16    d14, q13, #7
+    vqrshrn.u16    d15, q14, #7
+    vqrshrn.u16    d16, q1, #7
+    vqrshrn.u16    d17, q2, #7
+    vqrshrn.u16    d18, q3, #7
+    vqrshrn.u16    d19, q4, #7
+
+    vst1.u8         {d10, d11, d12, d13}, [lr]!         ;store result
+    vst1.u8         {d14, d15, d16, d17}, [lr]!
+    vst1.u8         {d18, d19}, [lr]!
+
+;Second pass: 16x16
+;secondpass_filter
+    add             r3, r12, r3, lsl #3
+    sub             lr, lr, #272
+
+    vld1.u32        {d31}, [r3]             ;load second_pass filter
+
+    sub             sp, sp, #256
+    mov             r3, sp
+
+    vld1.u8         {d22, d23}, [lr]!       ;load src data
+
+    vdup.8          d0, d31[0]              ;second_pass filter parameters (d0 d1)
+    vdup.8          d1, d31[4]
+    mov             r12, #4                 ;loop counter
+
+vp8e_filt_blk2d_sp16x16_loop_neon
+    vld1.u8         {d24, d25}, [lr]!
+    vmull.u8        q1, d22, d0             ;(src_ptr[0] * Filter[0])
+    vld1.u8         {d26, d27}, [lr]!
+    vmull.u8        q2, d23, d0
+    vld1.u8         {d28, d29}, [lr]!
+    vmull.u8        q3, d24, d0
+    vld1.u8         {d30, d31}, [lr]!
+
+    vmull.u8        q4, d25, d0
+    vmull.u8        q5, d26, d0
+    vmull.u8        q6, d27, d0
+    vmull.u8        q7, d28, d0
+    vmull.u8        q8, d29, d0
+
+    vmlal.u8        q1, d24, d1             ;(src_ptr[pixel_step] * Filter[1])
+    vmlal.u8        q2, d25, d1
+    vmlal.u8        q3, d26, d1
+    vmlal.u8        q4, d27, d1
+    vmlal.u8        q5, d28, d1
+    vmlal.u8        q6, d29, d1
+    vmlal.u8        q7, d30, d1
+    vmlal.u8        q8, d31, d1
+
+    subs            r12, r12, #1
+
+    vqrshrn.u16    d2, q1, #7               ;shift/round/saturate to u8
+    vqrshrn.u16    d3, q2, #7
+    vqrshrn.u16    d4, q3, #7
+    vqrshrn.u16    d5, q4, #7
+    vqrshrn.u16    d6, q5, #7
+    vqrshrn.u16    d7, q6, #7
+    vqrshrn.u16    d8, q7, #7
+    vqrshrn.u16    d9, q8, #7
+
+    vst1.u8         {d2, d3}, [r3]!         ;store result
+    vst1.u8         {d4, d5}, [r3]!
+    vst1.u8         {d6, d7}, [r3]!
+    vmov            q11, q15
+    vst1.u8         {d8, d9}, [r3]!
+
+    bne             vp8e_filt_blk2d_sp16x16_loop_neon
+
+    b               sub_pixel_variance16x16_neon
+
+;--------------------
+firstpass_bfilter16x16_only
+    mov             r2, #4                      ;loop counter
+    sub             sp, sp, #528            ;reserve space on stack for temporary storage
+    vdup.8          d0, d31[0]                  ;first_pass filter (d0 d1)
+    vdup.8          d1, d31[4]
+    mov             r3, sp
+
+;First Pass: output_height lines x output_width columns (16x16)
+vp8e_filt_blk2d_fpo16x16_loop_neon
+    vld1.u8         {d2, d3, d4}, [r0], r1      ;load src data
+    vld1.u8         {d5, d6, d7}, [r0], r1
+    vld1.u8         {d8, d9, d10}, [r0], r1
+    vld1.u8         {d11, d12, d13}, [r0], r1
+
+    pld             [r0]
+    pld             [r0, r1]
+    pld             [r0, r1, lsl #1]
+
+    vmull.u8        q7, d2, d0              ;(src_ptr[0] * Filter[0])
+    vmull.u8        q8, d3, d0
+    vmull.u8        q9, d5, d0
+    vmull.u8        q10, d6, d0
+    vmull.u8        q11, d8, d0
+    vmull.u8        q12, d9, d0
+    vmull.u8        q13, d11, d0
+    vmull.u8        q14, d12, d0
+
+    vext.8          d2, d2, d3, #1          ;construct src_ptr[1]
+    vext.8          d5, d5, d6, #1
+    vext.8          d8, d8, d9, #1
+    vext.8          d11, d11, d12, #1
+
+    vmlal.u8        q7, d2, d1              ;(src_ptr[0] * Filter[1])
+    vmlal.u8        q9, d5, d1
+    vmlal.u8        q11, d8, d1
+    vmlal.u8        q13, d11, d1
+
+    vext.8          d3, d3, d4, #1
+    vext.8          d6, d6, d7, #1
+    vext.8          d9, d9, d10, #1
+    vext.8          d12, d12, d13, #1
+
+    vmlal.u8        q8, d3, d1              ;(src_ptr[0] * Filter[1])
+    vmlal.u8        q10, d6, d1
+    vmlal.u8        q12, d9, d1
+    vmlal.u8        q14, d12, d1
+
+    subs            r2, r2, #1
+
+    vqrshrn.u16    d14, q7, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d15, q8, #7
+    vqrshrn.u16    d16, q9, #7
+    vqrshrn.u16    d17, q10, #7
+    vqrshrn.u16    d18, q11, #7
+    vqrshrn.u16    d19, q12, #7
+    vqrshrn.u16    d20, q13, #7
+    vst1.u8         {d14, d15}, [r3]!       ;store result
+    vqrshrn.u16    d21, q14, #7
+
+    vst1.u8         {d16, d17}, [r3]!
+    vst1.u8         {d18, d19}, [r3]!
+    vst1.u8         {d20, d21}, [r3]!
+
+    bne             vp8e_filt_blk2d_fpo16x16_loop_neon
+
+    b               sub_pixel_variance16x16_neon
+
+;---------------------
+secondpass_bfilter16x16_only
+;Second pass: 16x16
+;secondpass_filter
+    sub             sp, sp, #528            ;reserve space on stack for temporary storage
+    add             r3, r12, r3, lsl #3
+    mov             r12, #4                     ;loop counter
+    vld1.u32        {d31}, [r3]                 ;load second_pass filter
+    vld1.u8         {d22, d23}, [r0], r1        ;load src data
+    mov             r3, sp
+
+    vdup.8          d0, d31[0]                  ;second_pass filter parameters (d0 d1)
+    vdup.8          d1, d31[4]
+
+vp8e_filt_blk2d_spo16x16_loop_neon
+    vld1.u8         {d24, d25}, [r0], r1
+    vmull.u8        q1, d22, d0             ;(src_ptr[0] * Filter[0])
+    vld1.u8         {d26, d27}, [r0], r1
+    vmull.u8        q2, d23, d0
+    vld1.u8         {d28, d29}, [r0], r1
+    vmull.u8        q3, d24, d0
+    vld1.u8         {d30, d31}, [r0], r1
+
+    vmull.u8        q4, d25, d0
+    vmull.u8        q5, d26, d0
+    vmull.u8        q6, d27, d0
+    vmull.u8        q7, d28, d0
+    vmull.u8        q8, d29, d0
+
+    vmlal.u8        q1, d24, d1             ;(src_ptr[pixel_step] * Filter[1])
+    vmlal.u8        q2, d25, d1
+    vmlal.u8        q3, d26, d1
+    vmlal.u8        q4, d27, d1
+    vmlal.u8        q5, d28, d1
+    vmlal.u8        q6, d29, d1
+    vmlal.u8        q7, d30, d1
+    vmlal.u8        q8, d31, d1
+
+    vqrshrn.u16    d2, q1, #7               ;shift/round/saturate to u8
+    vqrshrn.u16    d3, q2, #7
+    vqrshrn.u16    d4, q3, #7
+    vqrshrn.u16    d5, q4, #7
+    vqrshrn.u16    d6, q5, #7
+    vqrshrn.u16    d7, q6, #7
+    vqrshrn.u16    d8, q7, #7
+    vqrshrn.u16    d9, q8, #7
+
+    vst1.u8         {d2, d3}, [r3]!         ;store result
+    subs            r12, r12, #1
+    vst1.u8         {d4, d5}, [r3]!
+    vmov            q11, q15
+    vst1.u8         {d6, d7}, [r3]!
+    vst1.u8         {d8, d9}, [r3]!
+
+    bne             vp8e_filt_blk2d_spo16x16_loop_neon
+
+    b               sub_pixel_variance16x16_neon
+
+;----------------------------
+;variance16x16
+sub_pixel_variance16x16_neon
+    vmov.i8         q8, #0                      ;q8 - sum
+    vmov.i8         q9, #0                      ;q9, q10 - sse
+    vmov.i8         q10, #0
+
+    sub             r3, r3, #256
+    mov             r12, #8
+
+sub_pixel_variance16x16_neon_loop
+    vld1.8          {q0}, [r3]!                 ;Load up source and reference
+    vld1.8          {q2}, [r4], r5
+    vld1.8          {q1}, [r3]!
+    vld1.8          {q3}, [r4], r5
+
+    vsubl.u8        q11, d0, d4                 ;diff
+    vsubl.u8        q12, d1, d5
+    vsubl.u8        q13, d2, d6
+    vsubl.u8        q14, d3, d7
+
+    vpadal.s16      q8, q11                     ;sum
+    vmlal.s16       q9, d22, d22                ;sse
+    vmlal.s16       q10, d23, d23
+
+    subs            r12, r12, #1
+
+    vpadal.s16      q8, q12
+    vmlal.s16       q9, d24, d24
+    vmlal.s16       q10, d25, d25
+    vpadal.s16      q8, q13
+    vmlal.s16       q9, d26, d26
+    vmlal.s16       q10, d27, d27
+    vpadal.s16      q8, q14
+    vmlal.s16       q9, d28, d28
+    vmlal.s16       q10, d29, d29
+
+    bne             sub_pixel_variance16x16_neon_loop
+
+    vadd.u32        q10, q9, q10                ;accumulate sse
+    vpaddl.s32      q0, q8                      ;accumulate sum
+
+    vpaddl.u32      q1, q10
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    vmull.s32       q5, d0, d0
+    vst1.32         {d1[0]}, [r6]               ;store sse
+    vshr.u32        d10, d10, #8
+    vsub.u32        d0, d1, d10
+
+    add             sp, sp, #528
+    vmov.32         r0, d0[0]                   ;return
+
+    pop             {r4-r6,pc}
+
+    ENDP
+
+    END
diff --git a/vp8/common/arm/neon/vp8_subpixelvariance16x16s_neon.asm b/vp8/common/arm/neon/vp8_subpixelvariance16x16s_neon.asm
new file mode 100644 (file)
index 0000000..155be4f
--- /dev/null
@@ -0,0 +1,572 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_variance_halfpixvar16x16_h_neon|
+    EXPORT  |vp8_variance_halfpixvar16x16_v_neon|
+    EXPORT  |vp8_variance_halfpixvar16x16_hv_neon|
+    EXPORT  |vp8_sub_pixel_variance16x16s_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+;================================================
+;unsigned int vp8_variance_halfpixvar16x16_h_neon
+;(
+;    unsigned char  *src_ptr, r0
+;    int  src_pixels_per_line,  r1
+;    unsigned char *dst_ptr,  r2
+;    int dst_pixels_per_line,   r3
+;    unsigned int *sse
+;);
+;================================================
+|vp8_variance_halfpixvar16x16_h_neon| PROC
+    push            {lr}
+
+    mov             r12, #4                  ;loop counter
+    ldr             lr, [sp, #4]           ;load *sse from stack
+    vmov.i8         q8, #0                      ;q8 - sum
+    vmov.i8         q9, #0                      ;q9, q10 - sse
+    vmov.i8         q10, #0
+
+;First Pass: output_height lines x output_width columns (16x16)
+vp8_filt_fpo16x16s_4_0_loop_neon
+    vld1.u8         {d0, d1, d2, d3}, [r0], r1      ;load src data
+    vld1.8          {q11}, [r2], r3
+    vld1.u8         {d4, d5, d6, d7}, [r0], r1
+    vld1.8          {q12}, [r2], r3
+    vld1.u8         {d8, d9, d10, d11}, [r0], r1
+    vld1.8          {q13}, [r2], r3
+    vld1.u8         {d12, d13, d14, d15}, [r0], r1
+
+    ;pld                [r0]
+    ;pld                [r0, r1]
+    ;pld                [r0, r1, lsl #1]
+
+    vext.8          q1, q0, q1, #1          ;construct src_ptr[1]
+    vext.8          q3, q2, q3, #1
+    vext.8          q5, q4, q5, #1
+    vext.8          q7, q6, q7, #1
+
+    vrhadd.u8       q0, q0, q1              ;(src_ptr[0]+src_ptr[1])/round/shift right 1
+    vld1.8          {q14}, [r2], r3
+    vrhadd.u8       q1, q2, q3
+    vrhadd.u8       q2, q4, q5
+    vrhadd.u8       q3, q6, q7
+
+    vsubl.u8        q4, d0, d22                 ;diff
+    vsubl.u8        q5, d1, d23
+    vsubl.u8        q6, d2, d24
+    vsubl.u8        q7, d3, d25
+    vsubl.u8        q0, d4, d26
+    vsubl.u8        q1, d5, d27
+    vsubl.u8        q2, d6, d28
+    vsubl.u8        q3, d7, d29
+
+    vpadal.s16      q8, q4                     ;sum
+    vmlal.s16       q9, d8, d8                ;sse
+    vmlal.s16       q10, d9, d9
+
+    subs            r12, r12, #1
+
+    vpadal.s16      q8, q5
+    vmlal.s16       q9, d10, d10
+    vmlal.s16       q10, d11, d11
+    vpadal.s16      q8, q6
+    vmlal.s16       q9, d12, d12
+    vmlal.s16       q10, d13, d13
+    vpadal.s16      q8, q7
+    vmlal.s16       q9, d14, d14
+    vmlal.s16       q10, d15, d15
+
+    vpadal.s16      q8, q0                     ;sum
+    vmlal.s16       q9, d0, d0                ;sse
+    vmlal.s16       q10, d1, d1
+    vpadal.s16      q8, q1
+    vmlal.s16       q9, d2, d2
+    vmlal.s16       q10, d3, d3
+    vpadal.s16      q8, q2
+    vmlal.s16       q9, d4, d4
+    vmlal.s16       q10, d5, d5
+    vpadal.s16      q8, q3
+    vmlal.s16       q9, d6, d6
+    vmlal.s16       q10, d7, d7
+
+    bne             vp8_filt_fpo16x16s_4_0_loop_neon
+
+    vadd.u32        q10, q9, q10                ;accumulate sse
+    vpaddl.s32      q0, q8                      ;accumulate sum
+
+    vpaddl.u32      q1, q10
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    vmull.s32       q5, d0, d0
+    vst1.32         {d1[0]}, [lr]               ;store sse
+    vshr.u32        d10, d10, #8
+    vsub.u32        d0, d1, d10
+
+    vmov.32         r0, d0[0]                   ;return
+    pop             {pc}
+    ENDP
+
+;================================================
+;unsigned int vp8_variance_halfpixvar16x16_v_neon
+;(
+;    unsigned char  *src_ptr, r0
+;    int  src_pixels_per_line,  r1
+;    unsigned char *dst_ptr,  r2
+;    int dst_pixels_per_line,   r3
+;    unsigned int *sse
+;);
+;================================================
+|vp8_variance_halfpixvar16x16_v_neon| PROC
+    push            {lr}
+
+    mov             r12, #4                     ;loop counter
+
+    vld1.u8         {q0}, [r0], r1              ;load src data
+    ldr             lr, [sp, #4]                ;load *sse from stack
+
+    vmov.i8         q8, #0                      ;q8 - sum
+    vmov.i8         q9, #0                      ;q9, q10 - sse
+    vmov.i8         q10, #0
+
+vp8_filt_spo16x16s_0_4_loop_neon
+    vld1.u8         {q2}, [r0], r1
+    vld1.8          {q1}, [r2], r3
+    vld1.u8         {q4}, [r0], r1
+    vld1.8          {q3}, [r2], r3
+    vld1.u8         {q6}, [r0], r1
+    vld1.8          {q5}, [r2], r3
+    vld1.u8         {q15}, [r0], r1
+
+    vrhadd.u8       q0, q0, q2
+    vld1.8          {q7}, [r2], r3
+    vrhadd.u8       q2, q2, q4
+    vrhadd.u8       q4, q4, q6
+    vrhadd.u8       q6, q6, q15
+
+    vsubl.u8        q11, d0, d2                 ;diff
+    vsubl.u8        q12, d1, d3
+    vsubl.u8        q13, d4, d6
+    vsubl.u8        q14, d5, d7
+    vsubl.u8        q0, d8, d10
+    vsubl.u8        q1, d9, d11
+    vsubl.u8        q2, d12, d14
+    vsubl.u8        q3, d13, d15
+
+    vpadal.s16      q8, q11                     ;sum
+    vmlal.s16       q9, d22, d22                ;sse
+    vmlal.s16       q10, d23, d23
+
+    subs            r12, r12, #1
+
+    vpadal.s16      q8, q12
+    vmlal.s16       q9, d24, d24
+    vmlal.s16       q10, d25, d25
+    vpadal.s16      q8, q13
+    vmlal.s16       q9, d26, d26
+    vmlal.s16       q10, d27, d27
+    vpadal.s16      q8, q14
+    vmlal.s16       q9, d28, d28
+    vmlal.s16       q10, d29, d29
+
+    vpadal.s16      q8, q0                     ;sum
+    vmlal.s16       q9, d0, d0                 ;sse
+    vmlal.s16       q10, d1, d1
+    vpadal.s16      q8, q1
+    vmlal.s16       q9, d2, d2
+    vmlal.s16       q10, d3, d3
+    vpadal.s16      q8, q2
+    vmlal.s16       q9, d4, d4
+    vmlal.s16       q10, d5, d5
+
+    vmov            q0, q15
+
+    vpadal.s16      q8, q3
+    vmlal.s16       q9, d6, d6
+    vmlal.s16       q10, d7, d7
+
+    bne             vp8_filt_spo16x16s_0_4_loop_neon
+
+    vadd.u32        q10, q9, q10                ;accumulate sse
+    vpaddl.s32      q0, q8                      ;accumulate sum
+
+    vpaddl.u32      q1, q10
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    vmull.s32       q5, d0, d0
+    vst1.32         {d1[0]}, [lr]               ;store sse
+    vshr.u32        d10, d10, #8
+    vsub.u32        d0, d1, d10
+
+    vmov.32         r0, d0[0]                   ;return
+    pop             {pc}
+    ENDP
+
+;================================================
+;unsigned int vp8_variance_halfpixvar16x16_hv_neon
+;(
+;    unsigned char  *src_ptr, r0
+;    int  src_pixels_per_line,  r1
+;    unsigned char *dst_ptr,  r2
+;    int dst_pixels_per_line,   r3
+;    unsigned int *sse
+;);
+;================================================
+|vp8_variance_halfpixvar16x16_hv_neon| PROC
+    push            {lr}
+
+    vld1.u8         {d0, d1, d2, d3}, [r0], r1      ;load src data
+
+    ldr             lr, [sp, #4]           ;load *sse from stack
+    vmov.i8         q13, #0                      ;q8 - sum
+    vext.8          q1, q0, q1, #1          ;construct src_ptr[1]
+
+    vmov.i8         q14, #0                      ;q9, q10 - sse
+    vmov.i8         q15, #0
+
+    mov             r12, #4                  ;loop counter
+    vrhadd.u8       q0, q0, q1              ;(src_ptr[0]+src_ptr[1])/round/shift right 1
+
+;First Pass: output_height lines x output_width columns (17x16)
+vp8_filt16x16s_4_4_loop_neon
+    vld1.u8         {d4, d5, d6, d7}, [r0], r1
+    vld1.u8         {d8, d9, d10, d11}, [r0], r1
+    vld1.u8         {d12, d13, d14, d15}, [r0], r1
+    vld1.u8         {d16, d17, d18, d19}, [r0], r1
+
+    ;pld                [r0]
+    ;pld                [r0, r1]
+    ;pld                [r0, r1, lsl #1]
+
+    vext.8          q3, q2, q3, #1          ;construct src_ptr[1]
+    vext.8          q5, q4, q5, #1
+    vext.8          q7, q6, q7, #1
+    vext.8          q9, q8, q9, #1
+
+    vrhadd.u8       q1, q2, q3              ;(src_ptr[0]+src_ptr[1])/round/shift right 1
+    vrhadd.u8       q2, q4, q5
+    vrhadd.u8       q3, q6, q7
+    vrhadd.u8       q4, q8, q9
+
+    vld1.8          {q5}, [r2], r3
+    vrhadd.u8       q0, q0, q1
+    vld1.8          {q6}, [r2], r3
+    vrhadd.u8       q1, q1, q2
+    vld1.8          {q7}, [r2], r3
+    vrhadd.u8       q2, q2, q3
+    vld1.8          {q8}, [r2], r3
+    vrhadd.u8       q3, q3, q4
+
+    vsubl.u8        q9, d0, d10                 ;diff
+    vsubl.u8        q10, d1, d11
+    vsubl.u8        q11, d2, d12
+    vsubl.u8        q12, d3, d13
+
+    vsubl.u8        q0, d4, d14                 ;diff
+    vsubl.u8        q1, d5, d15
+    vsubl.u8        q5, d6, d16
+    vsubl.u8        q6, d7, d17
+
+    vpadal.s16      q13, q9                     ;sum
+    vmlal.s16       q14, d18, d18                ;sse
+    vmlal.s16       q15, d19, d19
+
+    vpadal.s16      q13, q10                     ;sum
+    vmlal.s16       q14, d20, d20                ;sse
+    vmlal.s16       q15, d21, d21
+
+    vpadal.s16      q13, q11                     ;sum
+    vmlal.s16       q14, d22, d22                ;sse
+    vmlal.s16       q15, d23, d23
+
+    vpadal.s16      q13, q12                     ;sum
+    vmlal.s16       q14, d24, d24                ;sse
+    vmlal.s16       q15, d25, d25
+
+    subs            r12, r12, #1
+
+    vpadal.s16      q13, q0                     ;sum
+    vmlal.s16       q14, d0, d0                ;sse
+    vmlal.s16       q15, d1, d1
+
+    vpadal.s16      q13, q1                     ;sum
+    vmlal.s16       q14, d2, d2                ;sse
+    vmlal.s16       q15, d3, d3
+
+    vpadal.s16      q13, q5                     ;sum
+    vmlal.s16       q14, d10, d10                ;sse
+    vmlal.s16       q15, d11, d11
+
+    vmov            q0, q4
+
+    vpadal.s16      q13, q6                     ;sum
+    vmlal.s16       q14, d12, d12                ;sse
+    vmlal.s16       q15, d13, d13
+
+    bne             vp8_filt16x16s_4_4_loop_neon
+
+    vadd.u32        q15, q14, q15                ;accumulate sse
+    vpaddl.s32      q0, q13                      ;accumulate sum
+
+    vpaddl.u32      q1, q15
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    vmull.s32       q5, d0, d0
+    vst1.32         {d1[0]}, [lr]               ;store sse
+    vshr.u32        d10, d10, #8
+    vsub.u32        d0, d1, d10
+
+    vmov.32         r0, d0[0]                   ;return
+    pop             {pc}
+    ENDP
+
+;==============================
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; stack unsigned char *dst_ptr,
+; stack int dst_pixels_per_line,
+; stack unsigned int *sse
+;note: in vp8_find_best_half_pixel_step()(called when 8<Speed<15), and first call of vp8_find_best_sub_pixel_step()
+;(called when speed<=8). xoffset/yoffset can only be 4 or 0, which means either by pass the filter,
+;or filter coeff is {64, 64}. This simplified program only works in this situation.
+;note: It happens that both xoffset and yoffset are zero. This can be handled in c code later.
+
+|vp8_sub_pixel_variance16x16s_neon| PROC
+    push            {r4, lr}
+
+    ldr             r4, [sp, #8]            ;load *dst_ptr from stack
+    ldr             r12, [sp, #12]          ;load dst_pixels_per_line from stack
+    ldr             lr, [sp, #16]           ;load *sse from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             secondpass_bfilter16x16s_only
+
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+    beq             firstpass_bfilter16x16s_only
+
+    vld1.u8         {d0, d1, d2, d3}, [r0], r1      ;load src data
+    sub             sp, sp, #256            ;reserve space on stack for temporary storage
+    vext.8          q1, q0, q1, #1          ;construct src_ptr[1]
+    mov             r3, sp
+    mov             r2, #4                  ;loop counter
+    vrhadd.u8       q0, q0, q1              ;(src_ptr[0]+src_ptr[1])/round/shift right 1
+
+;First Pass: output_height lines x output_width columns (17x16)
+vp8e_filt_blk2d_fp16x16s_loop_neon
+    vld1.u8         {d4, d5, d6, d7}, [r0], r1
+    vld1.u8         {d8, d9, d10, d11}, [r0], r1
+    vld1.u8         {d12, d13, d14, d15}, [r0], r1
+    vld1.u8         {d16, d17, d18, d19}, [r0], r1
+
+    ;pld                [r0]
+    ;pld                [r0, r1]
+    ;pld                [r0, r1, lsl #1]
+
+    vext.8          q3, q2, q3, #1          ;construct src_ptr[1]
+    vext.8          q5, q4, q5, #1
+    vext.8          q7, q6, q7, #1
+    vext.8          q9, q8, q9, #1
+
+    vrhadd.u8       q1, q2, q3              ;(src_ptr[0]+src_ptr[1])/round/shift right 1
+    vrhadd.u8       q2, q4, q5
+    vrhadd.u8       q3, q6, q7
+    vrhadd.u8       q4, q8, q9
+
+    vrhadd.u8       q0, q0, q1
+    vrhadd.u8       q1, q1, q2
+    vrhadd.u8       q2, q2, q3
+    vrhadd.u8       q3, q3, q4
+
+    subs            r2, r2, #1
+    vst1.u8         {d0, d1 ,d2, d3}, [r3]!         ;store result
+    vmov            q0, q4
+    vst1.u8         {d4, d5, d6, d7}, [r3]!
+
+    bne             vp8e_filt_blk2d_fp16x16s_loop_neon
+
+    b               sub_pixel_variance16x16s_neon
+
+;--------------------
+firstpass_bfilter16x16s_only
+    mov             r2, #2                  ;loop counter
+    sub             sp, sp, #256            ;reserve space on stack for temporary storage
+    mov             r3, sp
+
+;First Pass: output_height lines x output_width columns (16x16)
+vp8e_filt_blk2d_fpo16x16s_loop_neon
+    vld1.u8         {d0, d1, d2, d3}, [r0], r1      ;load src data
+    vld1.u8         {d4, d5, d6, d7}, [r0], r1
+    vld1.u8         {d8, d9, d10, d11}, [r0], r1
+    vld1.u8         {d12, d13, d14, d15}, [r0], r1
+
+    ;pld                [r0]
+    ;pld                [r0, r1]
+    ;pld                [r0, r1, lsl #1]
+
+    vext.8          q1, q0, q1, #1          ;construct src_ptr[1]
+    vld1.u8         {d16, d17, d18, d19}, [r0], r1
+    vext.8          q3, q2, q3, #1
+    vld1.u8         {d20, d21, d22, d23}, [r0], r1
+    vext.8          q5, q4, q5, #1
+    vld1.u8         {d24, d25, d26, d27}, [r0], r1
+    vext.8          q7, q6, q7, #1
+    vld1.u8         {d28, d29, d30, d31}, [r0], r1
+    vext.8          q9, q8, q9, #1
+    vext.8          q11, q10, q11, #1
+    vext.8          q13, q12, q13, #1
+    vext.8          q15, q14, q15, #1
+
+    vrhadd.u8       q0, q0, q1              ;(src_ptr[0]+src_ptr[1])/round/shift right 1
+    vrhadd.u8       q1, q2, q3
+    vrhadd.u8       q2, q4, q5
+    vrhadd.u8       q3, q6, q7
+    vrhadd.u8       q4, q8, q9
+    vrhadd.u8       q5, q10, q11
+    vrhadd.u8       q6, q12, q13
+    vrhadd.u8       q7, q14, q15
+
+    subs            r2, r2, #1
+
+    vst1.u8         {d0, d1, d2, d3}, [r3]!         ;store result
+    vst1.u8         {d4, d5, d6, d7}, [r3]!
+    vst1.u8         {d8, d9, d10, d11}, [r3]!
+    vst1.u8         {d12, d13, d14, d15}, [r3]!
+
+    bne             vp8e_filt_blk2d_fpo16x16s_loop_neon
+
+    b               sub_pixel_variance16x16s_neon
+
+;---------------------
+secondpass_bfilter16x16s_only
+    sub             sp, sp, #256            ;reserve space on stack for temporary storage
+
+    mov             r2, #2                  ;loop counter
+    vld1.u8         {d0, d1}, [r0], r1      ;load src data
+    mov             r3, sp
+
+vp8e_filt_blk2d_spo16x16s_loop_neon
+    vld1.u8         {d2, d3}, [r0], r1
+    vld1.u8         {d4, d5}, [r0], r1
+    vld1.u8         {d6, d7}, [r0], r1
+    vld1.u8         {d8, d9}, [r0], r1
+
+    vrhadd.u8       q0, q0, q1
+    vld1.u8         {d10, d11}, [r0], r1
+    vrhadd.u8       q1, q1, q2
+    vld1.u8         {d12, d13}, [r0], r1
+    vrhadd.u8       q2, q2, q3
+    vld1.u8         {d14, d15}, [r0], r1
+    vrhadd.u8       q3, q3, q4
+    vld1.u8         {d16, d17}, [r0], r1
+    vrhadd.u8       q4, q4, q5
+    vrhadd.u8       q5, q5, q6
+    vrhadd.u8       q6, q6, q7
+    vrhadd.u8       q7, q7, q8
+
+    subs            r2, r2, #1
+
+    vst1.u8         {d0, d1, d2, d3}, [r3]!         ;store result
+    vmov            q0, q8
+    vst1.u8         {d4, d5, d6, d7}, [r3]!
+    vst1.u8         {d8, d9, d10, d11}, [r3]!           ;store result
+    vst1.u8         {d12, d13, d14, d15}, [r3]!
+
+    bne             vp8e_filt_blk2d_spo16x16s_loop_neon
+
+    b               sub_pixel_variance16x16s_neon
+
+;----------------------------
+;variance16x16
+sub_pixel_variance16x16s_neon
+    vmov.i8         q8, #0                      ;q8 - sum
+    vmov.i8         q9, #0                      ;q9, q10 - sse
+    vmov.i8         q10, #0
+
+    sub             r3, r3, #256
+    mov             r2, #4
+
+sub_pixel_variance16x16s_neon_loop
+    vld1.8          {q0}, [r3]!                 ;Load up source and reference
+    vld1.8          {q1}, [r4], r12
+    vld1.8          {q2}, [r3]!
+    vld1.8          {q3}, [r4], r12
+    vld1.8          {q4}, [r3]!
+    vld1.8          {q5}, [r4], r12
+    vld1.8          {q6}, [r3]!
+    vld1.8          {q7}, [r4], r12
+
+    vsubl.u8        q11, d0, d2                 ;diff
+    vsubl.u8        q12, d1, d3
+    vsubl.u8        q13, d4, d6
+    vsubl.u8        q14, d5, d7
+    vsubl.u8        q0, d8, d10
+    vsubl.u8        q1, d9, d11
+    vsubl.u8        q2, d12, d14
+    vsubl.u8        q3, d13, d15
+
+    vpadal.s16      q8, q11                     ;sum
+    vmlal.s16       q9, d22, d22                ;sse
+    vmlal.s16       q10, d23, d23
+
+    subs            r2, r2, #1
+
+    vpadal.s16      q8, q12
+    vmlal.s16       q9, d24, d24
+    vmlal.s16       q10, d25, d25
+    vpadal.s16      q8, q13
+    vmlal.s16       q9, d26, d26
+    vmlal.s16       q10, d27, d27
+    vpadal.s16      q8, q14
+    vmlal.s16       q9, d28, d28
+    vmlal.s16       q10, d29, d29
+
+    vpadal.s16      q8, q0                     ;sum
+    vmlal.s16       q9, d0, d0                ;sse
+    vmlal.s16       q10, d1, d1
+    vpadal.s16      q8, q1
+    vmlal.s16       q9, d2, d2
+    vmlal.s16       q10, d3, d3
+    vpadal.s16      q8, q2
+    vmlal.s16       q9, d4, d4
+    vmlal.s16       q10, d5, d5
+    vpadal.s16      q8, q3
+    vmlal.s16       q9, d6, d6
+    vmlal.s16       q10, d7, d7
+
+    bne             sub_pixel_variance16x16s_neon_loop
+
+    vadd.u32        q10, q9, q10                ;accumulate sse
+    vpaddl.s32      q0, q8                      ;accumulate sum
+
+    vpaddl.u32      q1, q10
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    vmull.s32       q5, d0, d0
+    vst1.32         {d1[0]}, [lr]               ;store sse
+    vshr.u32        d10, d10, #8
+    vsub.u32        d0, d1, d10
+
+    add             sp, sp, #256
+    vmov.32         r0, d0[0]                   ;return
+
+    pop             {r4, pc}
+    ENDP
+
+    END
diff --git a/vp8/common/arm/neon/vp8_subpixelvariance8x8_neon.asm b/vp8/common/arm/neon/vp8_subpixelvariance8x8_neon.asm
new file mode 100644 (file)
index 0000000..f6b6847
--- /dev/null
@@ -0,0 +1,222 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_sub_pixel_variance8x8_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; stack(r4) unsigned char *dst_ptr,
+; stack(r5) int dst_pixels_per_line,
+; stack(r6) unsigned int *sse
+;note: most of the code is copied from bilinear_predict8x8_neon and vp8_variance8x8_neon.
+
+|vp8_sub_pixel_variance8x8_neon| PROC
+    push            {r4-r5, lr}
+
+    adr             r12, bilinear_taps_coeff
+    ldr             r4, [sp, #12]           ;load *dst_ptr from stack
+    ldr             r5, [sp, #16]           ;load dst_pixels_per_line from stack
+    ldr             lr, [sp, #20]           ;load *sse from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             skip_firstpass_filter
+
+;First pass: output_height lines x output_width columns (9x8)
+    add             r2, r12, r2, lsl #3     ;calculate filter location
+
+    vld1.u8         {q1}, [r0], r1          ;load src data
+    vld1.u32        {d31}, [r2]             ;load first_pass filter
+    vld1.u8         {q2}, [r0], r1
+    vdup.8          d0, d31[0]              ;first_pass filter (d0 d1)
+    vld1.u8         {q3}, [r0], r1
+    vdup.8          d1, d31[4]
+    vld1.u8         {q4}, [r0], r1
+
+    vmull.u8        q6, d2, d0              ;(src_ptr[0] * Filter[0])
+    vmull.u8        q7, d4, d0
+    vmull.u8        q8, d6, d0
+    vmull.u8        q9, d8, d0
+
+    vext.8          d3, d2, d3, #1          ;construct src_ptr[-1]
+    vext.8          d5, d4, d5, #1
+    vext.8          d7, d6, d7, #1
+    vext.8          d9, d8, d9, #1
+
+    vmlal.u8        q6, d3, d1              ;(src_ptr[1] * Filter[1])
+    vmlal.u8        q7, d5, d1
+    vmlal.u8        q8, d7, d1
+    vmlal.u8        q9, d9, d1
+
+    vld1.u8         {q1}, [r0], r1          ;load src data
+    vqrshrn.u16    d22, q6, #7              ;shift/round/saturate to u8
+    vld1.u8         {q2}, [r0], r1
+    vqrshrn.u16    d23, q7, #7
+    vld1.u8         {q3}, [r0], r1
+    vqrshrn.u16    d24, q8, #7
+    vld1.u8         {q4}, [r0], r1
+    vqrshrn.u16    d25, q9, #7
+
+    ;first_pass filtering on the rest 5-line data
+    vld1.u8         {q5}, [r0], r1
+
+    vmull.u8        q6, d2, d0              ;(src_ptr[0] * Filter[0])
+    vmull.u8        q7, d4, d0
+    vmull.u8        q8, d6, d0
+    vmull.u8        q9, d8, d0
+    vmull.u8        q10, d10, d0
+
+    vext.8          d3, d2, d3, #1          ;construct src_ptr[-1]
+    vext.8          d5, d4, d5, #1
+    vext.8          d7, d6, d7, #1
+    vext.8          d9, d8, d9, #1
+    vext.8          d11, d10, d11, #1
+
+    vmlal.u8        q6, d3, d1              ;(src_ptr[1] * Filter[1])
+    vmlal.u8        q7, d5, d1
+    vmlal.u8        q8, d7, d1
+    vmlal.u8        q9, d9, d1
+    vmlal.u8        q10, d11, d1
+
+    vqrshrn.u16    d26, q6, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d27, q7, #7
+    vqrshrn.u16    d28, q8, #7
+    vqrshrn.u16    d29, q9, #7
+    vqrshrn.u16    d30, q10, #7
+
+;Second pass: 8x8
+secondpass_filter
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+    ;skip_secondpass_filter
+    beq             sub_pixel_variance8x8_neon
+
+    add             r3, r12, r3, lsl #3
+
+    vld1.u32        {d31}, [r3]             ;load second_pass filter
+
+    vdup.8          d0, d31[0]              ;second_pass filter parameters (d0 d1)
+    vdup.8          d1, d31[4]
+
+    vmull.u8        q1, d22, d0             ;(src_ptr[0] * Filter[0])
+    vmull.u8        q2, d23, d0
+    vmull.u8        q3, d24, d0
+    vmull.u8        q4, d25, d0
+    vmull.u8        q5, d26, d0
+    vmull.u8        q6, d27, d0
+    vmull.u8        q7, d28, d0
+    vmull.u8        q8, d29, d0
+
+    vmlal.u8        q1, d23, d1             ;(src_ptr[pixel_step] * Filter[1])
+    vmlal.u8        q2, d24, d1
+    vmlal.u8        q3, d25, d1
+    vmlal.u8        q4, d26, d1
+    vmlal.u8        q5, d27, d1
+    vmlal.u8        q6, d28, d1
+    vmlal.u8        q7, d29, d1
+    vmlal.u8        q8, d30, d1
+
+    vqrshrn.u16    d22, q1, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d23, q2, #7
+    vqrshrn.u16    d24, q3, #7
+    vqrshrn.u16    d25, q4, #7
+    vqrshrn.u16    d26, q5, #7
+    vqrshrn.u16    d27, q6, #7
+    vqrshrn.u16    d28, q7, #7
+    vqrshrn.u16    d29, q8, #7
+
+    b               sub_pixel_variance8x8_neon
+
+;--------------------
+skip_firstpass_filter
+    vld1.u8         {d22}, [r0], r1         ;load src data
+    vld1.u8         {d23}, [r0], r1
+    vld1.u8         {d24}, [r0], r1
+    vld1.u8         {d25}, [r0], r1
+    vld1.u8         {d26}, [r0], r1
+    vld1.u8         {d27}, [r0], r1
+    vld1.u8         {d28}, [r0], r1
+    vld1.u8         {d29}, [r0], r1
+    vld1.u8         {d30}, [r0], r1
+
+    b               secondpass_filter
+
+;----------------------
+;vp8_variance8x8_neon
+sub_pixel_variance8x8_neon
+    vmov.i8         q8, #0                      ;q8 - sum
+    vmov.i8         q9, #0                      ;q9, q10 - sse
+    vmov.i8         q10, #0
+
+    mov             r12, #2
+
+sub_pixel_variance8x8_neon_loop
+    vld1.8          {d0}, [r4], r5              ;load dst data
+    subs            r12, r12, #1
+    vld1.8          {d1}, [r4], r5
+    vld1.8          {d2}, [r4], r5
+    vsubl.u8        q4, d22, d0                 ;calculate diff
+    vld1.8          {d3}, [r4], r5
+
+    vsubl.u8        q5, d23, d1
+    vsubl.u8        q6, d24, d2
+
+    vpadal.s16      q8, q4                      ;sum
+    vmlal.s16       q9, d8, d8                  ;sse
+    vmlal.s16       q10, d9, d9
+
+    vsubl.u8        q7, d25, d3
+
+    vpadal.s16      q8, q5
+    vmlal.s16       q9, d10, d10
+    vmlal.s16       q10, d11, d11
+
+    vmov            q11, q13
+
+    vpadal.s16      q8, q6
+    vmlal.s16       q9, d12, d12
+    vmlal.s16       q10, d13, d13
+
+    vmov            q12, q14
+
+    vpadal.s16      q8, q7
+    vmlal.s16       q9, d14, d14
+    vmlal.s16       q10, d15, d15
+
+    bne             sub_pixel_variance8x8_neon_loop
+
+    vadd.u32        q10, q9, q10                ;accumulate sse
+    vpaddl.s32      q0, q8                      ;accumulate sum
+
+    vpaddl.u32      q1, q10
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    vmull.s32       q5, d0, d0
+    vst1.32         {d1[0]}, [lr]               ;store sse
+    vshr.u32        d10, d10, #6
+    vsub.u32        d0, d1, d10
+
+    vmov.32         r0, d0[0]                   ;return
+    pop             {r4-r5, pc}
+
+    ENDP
+
+;-----------------
+
+bilinear_taps_coeff
+    DCD     128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112
+
+    END
diff --git a/vp8/common/arm/reconintra_arm.c b/vp8/common/arm/reconintra_arm.c
new file mode 100644 (file)
index 0000000..121e090
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "vp8/common/blockd.h"
+#include "vpx_mem/vpx_mem.h"
+
+#if HAVE_NEON
+extern void vp8_build_intra_predictors_mby_neon_func(
+    unsigned char *y_buffer,
+    unsigned char *ypred_ptr,
+    int y_stride,
+    int mode,
+    int Up,
+    int Left);
+
+void vp8_build_intra_predictors_mby_neon(MACROBLOCKD *x)
+{
+    unsigned char *y_buffer = x->dst.y_buffer;
+    unsigned char *ypred_ptr = x->predictor;
+    int y_stride = x->dst.y_stride;
+    int mode = x->mode_info_context->mbmi.mode;
+    int Up = x->up_available;
+    int Left = x->left_available;
+
+    vp8_build_intra_predictors_mby_neon_func(y_buffer, ypred_ptr, y_stride, mode, Up, Left);
+}
+
+extern void vp8_build_intra_predictors_mby_s_neon_func(
+    unsigned char *y_buffer,
+    unsigned char *ypred_ptr,
+    int y_stride,
+    int mode,
+    int Up,
+    int Left);
+
+void vp8_build_intra_predictors_mby_s_neon(MACROBLOCKD *x)
+{
+    unsigned char *y_buffer = x->dst.y_buffer;
+    unsigned char *ypred_ptr = x->predictor;
+    int y_stride = x->dst.y_stride;
+    int mode = x->mode_info_context->mbmi.mode;
+    int Up = x->up_available;
+    int Left = x->left_available;
+
+    vp8_build_intra_predictors_mby_s_neon_func(y_buffer, ypred_ptr, y_stride, mode, Up, Left);
+}
+
+#endif
diff --git a/vp8/common/arm/variance_arm.c b/vp8/common/arm/variance_arm.c
new file mode 100644 (file)
index 0000000..891d767
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "vp8/common/variance.h"
+#include "vp8/common/filter.h"
+
+#if HAVE_MEDIA
+#include "vp8/common/arm/bilinearfilter_arm.h"
+
+unsigned int vp8_sub_pixel_variance8x8_armv6
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    unsigned short first_pass[10*8];
+    unsigned char  second_pass[8*8];
+    const short *HFilter, *VFilter;
+
+    HFilter = vp8_bilinear_filters[xoffset];
+    VFilter = vp8_bilinear_filters[yoffset];
+
+    vp8_filter_block2d_bil_first_pass_armv6(src_ptr, first_pass,
+                                            src_pixels_per_line,
+                                            9, 8, HFilter);
+    vp8_filter_block2d_bil_second_pass_armv6(first_pass, second_pass,
+                                             8, 8, 8, VFilter);
+
+    return vp8_variance8x8_armv6(second_pass, 8, dst_ptr,
+                                   dst_pixels_per_line, sse);
+}
+
+unsigned int vp8_sub_pixel_variance16x16_armv6
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    unsigned short first_pass[36*16];
+    unsigned char  second_pass[20*16];
+    const short *HFilter, *VFilter;
+    unsigned int var;
+
+    if (xoffset == 4 && yoffset == 0)
+    {
+        var = vp8_variance_halfpixvar16x16_h_armv6(src_ptr, src_pixels_per_line,
+                                                   dst_ptr, dst_pixels_per_line, sse);
+    }
+    else if (xoffset == 0 && yoffset == 4)
+    {
+        var = vp8_variance_halfpixvar16x16_v_armv6(src_ptr, src_pixels_per_line,
+                                                   dst_ptr, dst_pixels_per_line, sse);
+    }
+    else if (xoffset == 4 && yoffset == 4)
+    {
+        var = vp8_variance_halfpixvar16x16_hv_armv6(src_ptr, src_pixels_per_line,
+                                                   dst_ptr, dst_pixels_per_line, sse);
+    }
+    else
+    {
+        HFilter = vp8_bilinear_filters[xoffset];
+        VFilter = vp8_bilinear_filters[yoffset];
+
+        vp8_filter_block2d_bil_first_pass_armv6(src_ptr, first_pass,
+                                                src_pixels_per_line,
+                                                17, 16, HFilter);
+        vp8_filter_block2d_bil_second_pass_armv6(first_pass, second_pass,
+                                                 16, 16, 16, VFilter);
+
+        var = vp8_variance16x16_armv6(second_pass, 16, dst_ptr,
+                                       dst_pixels_per_line, sse);
+    }
+    return var;
+}
+
+#endif /* HAVE_MEDIA */
+
+
+#if HAVE_NEON
+
+extern unsigned int vp8_sub_pixel_variance16x16_neon_func
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+);
+
+unsigned int vp8_sub_pixel_variance16x16_neon
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+  if (xoffset == 4 && yoffset == 0)
+    return vp8_variance_halfpixvar16x16_h_neon(src_ptr, src_pixels_per_line, dst_ptr, dst_pixels_per_line, sse);
+  else if (xoffset == 0 && yoffset == 4)
+    return vp8_variance_halfpixvar16x16_v_neon(src_ptr, src_pixels_per_line, dst_ptr, dst_pixels_per_line, sse);
+  else if (xoffset == 4 && yoffset == 4)
+    return vp8_variance_halfpixvar16x16_hv_neon(src_ptr, src_pixels_per_line, dst_ptr, dst_pixels_per_line, sse);
+  else
+    return vp8_sub_pixel_variance16x16_neon_func(src_ptr, src_pixels_per_line, xoffset, yoffset, dst_ptr, dst_pixels_per_line, sse);
+}
+
+#endif
diff --git a/vp8/common/asm_com_offsets.c b/vp8/common/asm_com_offsets.c
new file mode 100644 (file)
index 0000000..ae22b5f
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vpx/vpx_codec.h"
+#include "vpx_ports/asm_offsets.h"
+#include "vpx_scale/yv12config.h"
+#include "vp8/common/blockd.h"
+
+#if CONFIG_POSTPROC
+#include "postproc.h"
+#endif /* CONFIG_POSTPROC */
+
+BEGIN
+
+/* vpx_scale */
+DEFINE(yv12_buffer_config_y_width,              offsetof(YV12_BUFFER_CONFIG, y_width));
+DEFINE(yv12_buffer_config_y_height,             offsetof(YV12_BUFFER_CONFIG, y_height));
+DEFINE(yv12_buffer_config_y_stride,             offsetof(YV12_BUFFER_CONFIG, y_stride));
+DEFINE(yv12_buffer_config_uv_width,             offsetof(YV12_BUFFER_CONFIG, uv_width));
+DEFINE(yv12_buffer_config_uv_height,            offsetof(YV12_BUFFER_CONFIG, uv_height));
+DEFINE(yv12_buffer_config_uv_stride,            offsetof(YV12_BUFFER_CONFIG, uv_stride));
+DEFINE(yv12_buffer_config_y_buffer,             offsetof(YV12_BUFFER_CONFIG, y_buffer));
+DEFINE(yv12_buffer_config_u_buffer,             offsetof(YV12_BUFFER_CONFIG, u_buffer));
+DEFINE(yv12_buffer_config_v_buffer,             offsetof(YV12_BUFFER_CONFIG, v_buffer));
+DEFINE(yv12_buffer_config_border,               offsetof(YV12_BUFFER_CONFIG, border));
+DEFINE(VP8BORDERINPIXELS_VAL,                   VP8BORDERINPIXELS);
+
+#if CONFIG_POSTPROC
+/* mfqe.c / filter_by_weight */
+DEFINE(MFQE_PRECISION_VAL,                      MFQE_PRECISION);
+#endif /* CONFIG_POSTPROC */
+
+END
+
+/* add asserts for any offset that is not supported by assembly code */
+/* add asserts for any size that is not supported by assembly code */
+
+#if HAVE_MEDIA
+/* switch case in vp8_intra4x4_predict_armv6 is based on these enumerated values */
+ct_assert(B_DC_PRED, B_DC_PRED == 0);
+ct_assert(B_TM_PRED, B_TM_PRED == 1);
+ct_assert(B_VE_PRED, B_VE_PRED == 2);
+ct_assert(B_HE_PRED, B_HE_PRED == 3);
+ct_assert(B_LD_PRED, B_LD_PRED == 4);
+ct_assert(B_RD_PRED, B_RD_PRED == 5);
+ct_assert(B_VR_PRED, B_VR_PRED == 6);
+ct_assert(B_VL_PRED, B_VL_PRED == 7);
+ct_assert(B_HD_PRED, B_HD_PRED == 8);
+ct_assert(B_HU_PRED, B_HU_PRED == 9);
+#endif
+
+#if HAVE_NEON
+/* vp8_yv12_extend_frame_borders_neon makes several assumptions based on this */
+ct_assert(VP8BORDERINPIXELS_VAL, VP8BORDERINPIXELS == 32)
+#endif
+
+#if HAVE_SSE2
+#if CONFIG_POSTPROC
+/* vp8_filter_by_weight16x16 and 8x8 */
+ct_assert(MFQE_PRECISION_VAL, MFQE_PRECISION == 4)
+#endif /* CONFIG_POSTPROC */
+#endif /* HAVE_SSE2 */
diff --git a/vp8/common/blockd.c b/vp8/common/blockd.c
new file mode 100644 (file)
index 0000000..1fc3cd0
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "blockd.h"
+#include "vpx_mem/vpx_mem.h"
+
+const unsigned char vp8_block2left[25] =
+{
+    0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8
+};
+const unsigned char vp8_block2above[25] =
+{
+    0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8
+};
diff --git a/vp8/common/blockd.h b/vp8/common/blockd.h
new file mode 100644 (file)
index 0000000..a4c1d92
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_BLOCKD_H
+#define __INC_BLOCKD_H
+
+void vpx_log(const char *format, ...);
+
+#include "vpx_config.h"
+#include "vpx_scale/yv12config.h"
+#include "mv.h"
+#include "treecoder.h"
+#include "vpx_ports/mem.h"
+
+/*#define DCPRED 1*/
+#define DCPREDSIMTHRESH 0
+#define DCPREDCNTTHRESH 3
+
+#define MB_FEATURE_TREE_PROBS   3
+#define MAX_MB_SEGMENTS         4
+
+#define MAX_REF_LF_DELTAS       4
+#define MAX_MODE_LF_DELTAS      4
+
+/* Segment Feature Masks */
+#define SEGMENT_DELTADATA   0
+#define SEGMENT_ABSDATA     1
+
+typedef struct
+{
+    int r, c;
+} POS;
+
+#define PLANE_TYPE_Y_NO_DC    0
+#define PLANE_TYPE_Y2         1
+#define PLANE_TYPE_UV         2
+#define PLANE_TYPE_Y_WITH_DC  3
+
+
+typedef char ENTROPY_CONTEXT;
+typedef struct
+{
+    ENTROPY_CONTEXT y1[4];
+    ENTROPY_CONTEXT u[2];
+    ENTROPY_CONTEXT v[2];
+    ENTROPY_CONTEXT y2;
+} ENTROPY_CONTEXT_PLANES;
+
+extern const unsigned char vp8_block2left[25];
+extern const unsigned char vp8_block2above[25];
+
+#define VP8_COMBINEENTROPYCONTEXTS( Dest, A, B) \
+    Dest = (A)+(B);
+
+
+typedef enum
+{
+    KEY_FRAME = 0,
+    INTER_FRAME = 1
+} FRAME_TYPE;
+
+typedef enum
+{
+    DC_PRED,            /* average of above and left pixels */
+    V_PRED,             /* vertical prediction */
+    H_PRED,             /* horizontal prediction */
+    TM_PRED,            /* Truemotion prediction */
+    B_PRED,             /* block based prediction, each block has its own prediction mode */
+
+    NEARESTMV,
+    NEARMV,
+    ZEROMV,
+    NEWMV,
+    SPLITMV,
+
+    MB_MODE_COUNT
+} MB_PREDICTION_MODE;
+
+/* Macroblock level features */
+typedef enum
+{
+    MB_LVL_ALT_Q = 0,               /* Use alternate Quantizer .... */
+    MB_LVL_ALT_LF = 1,              /* Use alternate loop filter value... */
+    MB_LVL_MAX = 2                  /* Number of MB level features supported */
+
+} MB_LVL_FEATURES;
+
+/* Segment Feature Masks */
+#define SEGMENT_ALTQ    0x01
+#define SEGMENT_ALT_LF  0x02
+
+#define VP8_YMODES  (B_PRED + 1)
+#define VP8_UV_MODES (TM_PRED + 1)
+
+#define VP8_MVREFS (1 + SPLITMV - NEARESTMV)
+
+typedef enum
+{
+    B_DC_PRED,          /* average of above and left pixels */
+    B_TM_PRED,
+
+    B_VE_PRED,           /* vertical prediction */
+    B_HE_PRED,           /* horizontal prediction */
+
+    B_LD_PRED,
+    B_RD_PRED,
+
+    B_VR_PRED,
+    B_VL_PRED,
+    B_HD_PRED,
+    B_HU_PRED,
+
+    LEFT4X4,
+    ABOVE4X4,
+    ZERO4X4,
+    NEW4X4,
+
+    B_MODE_COUNT
+} B_PREDICTION_MODE;
+
+#define VP8_BINTRAMODES (B_HU_PRED + 1)  /* 10 */
+#define VP8_SUBMVREFS (1 + NEW4X4 - LEFT4X4)
+
+/* For keyframes, intra block modes are predicted by the (already decoded)
+   modes for the Y blocks to the left and above us; for interframes, there
+   is a single probability table. */
+
+union b_mode_info
+{
+    B_PREDICTION_MODE as_mode;
+    int_mv mv;
+};
+
+typedef enum
+{
+    INTRA_FRAME = 0,
+    LAST_FRAME = 1,
+    GOLDEN_FRAME = 2,
+    ALTREF_FRAME = 3,
+    MAX_REF_FRAMES = 4
+} MV_REFERENCE_FRAME;
+
+typedef struct
+{
+    uint8_t mode, uv_mode;
+    uint8_t ref_frame;
+    uint8_t is_4x4;
+    int_mv mv;
+
+    uint8_t partitioning;
+    uint8_t mb_skip_coeff;                                /* does this mb has coefficients at all, 1=no coefficients, 0=need decode tokens */
+    uint8_t need_to_clamp_mvs;
+    uint8_t segment_id;                  /* Which set of segmentation parameters should be used for this MB */
+} MB_MODE_INFO;
+
+typedef struct
+{
+    MB_MODE_INFO mbmi;
+    union b_mode_info bmi[16];
+} MODE_INFO;
+
+#if CONFIG_MULTI_RES_ENCODING
+/* The information needed to be stored for higher-resolution encoder */
+typedef struct
+{
+    MB_PREDICTION_MODE mode;
+    MV_REFERENCE_FRAME ref_frame;
+    int_mv mv;
+    //union b_mode_info bmi[16];
+    int dissim;    // dissimilarity level of the macroblock
+} LOWER_RES_INFO;
+#endif
+
+typedef struct blockd
+{
+    short *qcoeff;
+    short *dqcoeff;
+    unsigned char  *predictor;
+    short *dequant;
+
+    int offset;
+    char *eob;
+
+    union b_mode_info bmi;
+} BLOCKD;
+
+typedef void (*vp8_subpix_fn_t)(unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch);
+
+typedef struct macroblockd
+{
+    DECLARE_ALIGNED(16, unsigned char,  predictor[384]);
+    DECLARE_ALIGNED(16, short, qcoeff[400]);
+    DECLARE_ALIGNED(16, short, dqcoeff[400]);
+    DECLARE_ALIGNED(16, char,  eobs[25]);
+
+    DECLARE_ALIGNED(16, short,  dequant_y1[16]);
+    DECLARE_ALIGNED(16, short,  dequant_y1_dc[16]);
+    DECLARE_ALIGNED(16, short,  dequant_y2[16]);
+    DECLARE_ALIGNED(16, short,  dequant_uv[16]);
+
+    /* 16 Y blocks, 4 U, 4 V, 1 DC 2nd order block, each with 16 entries. */
+    BLOCKD block[25];
+    int fullpixel_mask;
+
+    YV12_BUFFER_CONFIG pre; /* Filtered copy of previous frame reconstruction */
+    YV12_BUFFER_CONFIG dst;
+
+    MODE_INFO *mode_info_context;
+    int mode_info_stride;
+
+#if CONFIG_TEMPORAL_DENOISING
+    MB_PREDICTION_MODE best_sse_inter_mode;
+    int_mv best_sse_mv;
+    unsigned char need_to_clamp_best_mvs;
+#endif
+
+    FRAME_TYPE frame_type;
+
+    int up_available;
+    int left_available;
+
+    unsigned char *recon_above[3];
+    unsigned char *recon_left[3];
+    int recon_left_stride[2];
+
+    /* Y,U,V,Y2 */
+    ENTROPY_CONTEXT_PLANES *above_context;
+    ENTROPY_CONTEXT_PLANES *left_context;
+
+    /* 0 indicates segmentation at MB level is not enabled. Otherwise the individual bits indicate which features are active. */
+    unsigned char segmentation_enabled;
+
+    /* 0 (do not update) 1 (update) the macroblock segmentation map. */
+    unsigned char update_mb_segmentation_map;
+
+    /* 0 (do not update) 1 (update) the macroblock segmentation feature data. */
+    unsigned char update_mb_segmentation_data;
+
+    /* 0 (do not update) 1 (update) the macroblock segmentation feature data. */
+    unsigned char mb_segement_abs_delta;
+
+    /* Per frame flags that define which MB level features (such as quantizer or loop filter level) */
+    /* are enabled and when enabled the proabilities used to decode the per MB flags in MB_MODE_INFO */
+    vp8_prob mb_segment_tree_probs[MB_FEATURE_TREE_PROBS];         /* Probability Tree used to code Segment number */
+
+    signed char segment_feature_data[MB_LVL_MAX][MAX_MB_SEGMENTS];            /* Segment parameters */
+
+    /* mode_based Loop filter adjustment */
+    unsigned char mode_ref_lf_delta_enabled;
+    unsigned char mode_ref_lf_delta_update;
+
+    /* Delta values have the range +/- MAX_LOOP_FILTER */
+    signed char last_ref_lf_deltas[MAX_REF_LF_DELTAS];                /* 0 = Intra, Last, GF, ARF */
+    signed char ref_lf_deltas[MAX_REF_LF_DELTAS];                     /* 0 = Intra, Last, GF, ARF */
+    signed char last_mode_lf_deltas[MAX_MODE_LF_DELTAS];                      /* 0 = BPRED, ZERO_MV, MV, SPLIT */
+    signed char mode_lf_deltas[MAX_MODE_LF_DELTAS];                           /* 0 = BPRED, ZERO_MV, MV, SPLIT */
+
+    /* Distance of MB away from frame edges */
+    int mb_to_left_edge;
+    int mb_to_right_edge;
+    int mb_to_top_edge;
+    int mb_to_bottom_edge;
+
+
+
+    vp8_subpix_fn_t  subpixel_predict;
+    vp8_subpix_fn_t  subpixel_predict8x4;
+    vp8_subpix_fn_t  subpixel_predict8x8;
+    vp8_subpix_fn_t  subpixel_predict16x16;
+
+    void *current_bc;
+
+    int corrupted;
+
+#if ARCH_X86 || ARCH_X86_64
+    /* This is an intermediate buffer currently used in sub-pixel motion search
+     * to keep a copy of the reference area. This buffer can be used for other
+     * purpose.
+     */
+    DECLARE_ALIGNED(32, unsigned char, y_buf[22*32]);
+#endif
+} MACROBLOCKD;
+
+
+extern void vp8_build_block_doffsets(MACROBLOCKD *x);
+extern void vp8_setup_block_dptrs(MACROBLOCKD *x);
+
+#endif  /* __INC_BLOCKD_H */
diff --git a/vp8/common/coefupdateprobs.h b/vp8/common/coefupdateprobs.h
new file mode 100644 (file)
index 0000000..9e194dc
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/* Update probabilities for the nodes in the token entropy tree.
+   Generated file included by entropy.c */
+
+const vp8_prob vp8_coef_update_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES] =
+{
+    {
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255, },
+            {250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+    },
+    {
+        {
+            {217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255, },
+            {234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255, },
+        },
+        {
+            {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+    },
+    {
+        {
+            {186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255, },
+            {251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255, },
+        },
+        {
+            {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+    },
+    {
+        {
+            {248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255, },
+            {248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+    },
+};
diff --git a/vp8/common/common.h b/vp8/common/common.h
new file mode 100644 (file)
index 0000000..2cc1c54
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef common_h
+#define common_h 1
+
+#include <assert.h>
+
+/* Interface header for common constant data structures and lookup tables */
+
+#include "vpx_mem/vpx_mem.h"
+
+/* Only need this for fixed-size arrays, for structs just assign. */
+
+#define vp8_copy( Dest, Src) { \
+        assert( sizeof( Dest) == sizeof( Src)); \
+        vpx_memcpy( Dest, Src, sizeof( Src)); \
+    }
+
+/* Use this for variably-sized arrays. */
+
+#define vp8_copy_array( Dest, Src, N) { \
+        assert( sizeof( *Dest) == sizeof( *Src)); \
+        vpx_memcpy( Dest, Src, N * sizeof( *Src)); \
+    }
+
+#define vp8_zero( Dest)  vpx_memset( &Dest, 0, sizeof( Dest));
+
+#define vp8_zero_array( Dest, N)  vpx_memset( Dest, 0, N * sizeof( *Dest));
+
+
+#endif  /* common_h */
diff --git a/vp8/common/context.c b/vp8/common/context.c
new file mode 100644 (file)
index 0000000..99e95d3
--- /dev/null
@@ -0,0 +1,399 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "entropy.h"
+
+/* *** GENERATED FILE: DO NOT EDIT *** */
+
+#if 0
+int Contexts[vp8_coef_counter_dimen];
+
+const int default_contexts[vp8_coef_counter_dimen] =
+{
+    {
+        // Block Type ( 0 )
+        {
+            // Coeff Band ( 0 )
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+        },
+        {
+            // Coeff Band ( 1 )
+            {30190, 26544, 225,  24,   4,   0,   0,   0,   0,   0,   0, 4171593,},
+            {26846, 25157, 1241, 130,  26,   6,   1,   0,   0,   0,   0, 149987,},
+            {10484, 9538, 1006, 160,  36,  18,   0,   0,   0,   0,   0, 15104,},
+        },
+        {
+            // Coeff Band ( 2 )
+            {25842, 40456, 1126,  83,  11,   2,   0,   0,   0,   0,   0,   0,},
+            {9338, 8010, 512,  73,   7,   3,   2,   0,   0,   0,   0, 43294,},
+            {1047, 751, 149,  31,  13,   6,   1,   0,   0,   0,   0, 879,},
+        },
+        {
+            // Coeff Band ( 3 )
+            {26136, 9826, 252,  13,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {8134, 5574, 191,  14,   2,   0,   0,   0,   0,   0,   0, 35302,},
+            { 605, 677, 116,   9,   1,   0,   0,   0,   0,   0,   0, 611,},
+        },
+        {
+            // Coeff Band ( 4 )
+            {10263, 15463, 283,  17,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {2773, 2191, 128,   9,   2,   2,   0,   0,   0,   0,   0, 10073,},
+            { 134, 125,  32,   4,   0,   2,   0,   0,   0,   0,   0,  50,},
+        },
+        {
+            // Coeff Band ( 5 )
+            {10483, 2663,  23,   1,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {2137, 1251,  27,   1,   1,   0,   0,   0,   0,   0,   0, 14362,},
+            { 116, 156,  14,   2,   1,   0,   0,   0,   0,   0,   0, 190,},
+        },
+        {
+            // Coeff Band ( 6 )
+            {40977, 27614, 412,  28,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {6113, 5213, 261,  22,   3,   0,   0,   0,   0,   0,   0, 26164,},
+            { 382, 312,  50,  14,   2,   0,   0,   0,   0,   0,   0, 345,},
+        },
+        {
+            // Coeff Band ( 7 )
+            {   0,  26,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,  13,   0,   0,   0,   0,   0,   0,   0,   0,   0, 319,},
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   8,},
+        },
+    },
+    {
+        // Block Type ( 1 )
+        {
+            // Coeff Band ( 0 )
+            {3268, 19382, 1043, 250,  93,  82,  49,  26,  17,   8,  25, 82289,},
+            {8758, 32110, 5436, 1832, 827, 668, 420, 153,  24,   0,   3, 52914,},
+            {9337, 23725, 8487, 3954, 2107, 1836, 1069, 399,  59,   0,   0, 18620,},
+        },
+        {
+            // Coeff Band ( 1 )
+            {12419, 8420, 452,  62,   9,   1,   0,   0,   0,   0,   0,   0,},
+            {11715, 8705, 693,  92,  15,   7,   2,   0,   0,   0,   0, 53988,},
+            {7603, 8585, 2306, 778, 270, 145,  39,   5,   0,   0,   0, 9136,},
+        },
+        {
+            // Coeff Band ( 2 )
+            {15938, 14335, 1207, 184,  55,  13,   4,   1,   0,   0,   0,   0,},
+            {7415, 6829, 1138, 244,  71,  26,   7,   0,   0,   0,   0, 9980,},
+            {1580, 1824, 655, 241,  89,  46,  10,   2,   0,   0,   0, 429,},
+        },
+        {
+            // Coeff Band ( 3 )
+            {19453, 5260, 201,  19,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {9173, 3758, 213,  22,   1,   1,   0,   0,   0,   0,   0, 9820,},
+            {1689, 1277, 276,  51,  17,   4,   0,   0,   0,   0,   0, 679,},
+        },
+        {
+            // Coeff Band ( 4 )
+            {12076, 10667, 620,  85,  19,   9,   5,   0,   0,   0,   0,   0,},
+            {4665, 3625, 423,  55,  19,   9,   0,   0,   0,   0,   0, 5127,},
+            { 415, 440, 143,  34,  20,   7,   2,   0,   0,   0,   0, 101,},
+        },
+        {
+            // Coeff Band ( 5 )
+            {12183, 4846, 115,  11,   1,   0,   0,   0,   0,   0,   0,   0,},
+            {4226, 3149, 177,  21,   2,   0,   0,   0,   0,   0,   0, 7157,},
+            { 375, 621, 189,  51,  11,   4,   1,   0,   0,   0,   0, 198,},
+        },
+        {
+            // Coeff Band ( 6 )
+            {61658, 37743, 1203,  94,  10,   3,   0,   0,   0,   0,   0,   0,},
+            {15514, 11563, 903, 111,  14,   5,   0,   0,   0,   0,   0, 25195,},
+            { 929, 1077, 291,  78,  14,   7,   1,   0,   0,   0,   0, 507,},
+        },
+        {
+            // Coeff Band ( 7 )
+            {   0, 990,  15,   3,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0, 412,  13,   0,   0,   0,   0,   0,   0,   0,   0, 1641,},
+            {   0,  18,   7,   1,   0,   0,   0,   0,   0,   0,   0,  30,},
+        },
+    },
+    {
+        // Block Type ( 2 )
+        {
+            // Coeff Band ( 0 )
+            { 953, 24519, 628, 120,  28,  12,   4,   0,   0,   0,   0, 2248798,},
+            {1525, 25654, 2647, 617, 239, 143,  42,   5,   0,   0,   0, 66837,},
+            {1180, 11011, 3001, 1237, 532, 448, 239,  54,   5,   0,   0, 7122,},
+        },
+        {
+            // Coeff Band ( 1 )
+            {1356, 2220,  67,  10,   4,   1,   0,   0,   0,   0,   0,   0,},
+            {1450, 2544, 102,  18,   4,   3,   0,   0,   0,   0,   0, 57063,},
+            {1182, 2110, 470, 130,  41,  21,   0,   0,   0,   0,   0, 6047,},
+        },
+        {
+            // Coeff Band ( 2 )
+            { 370, 3378, 200,  30,   5,   4,   1,   0,   0,   0,   0,   0,},
+            { 293, 1006, 131,  29,  11,   0,   0,   0,   0,   0,   0, 5404,},
+            { 114, 387,  98,  23,   4,   8,   1,   0,   0,   0,   0, 236,},
+        },
+        {
+            // Coeff Band ( 3 )
+            { 579, 194,   4,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            { 395, 213,   5,   1,   0,   0,   0,   0,   0,   0,   0, 4157,},
+            { 119, 122,   4,   0,   0,   0,   0,   0,   0,   0,   0, 300,},
+        },
+        {
+            // Coeff Band ( 4 )
+            {  38, 557,  19,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {  21, 114,  12,   1,   0,   0,   0,   0,   0,   0,   0, 427,},
+            {   0,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   7,},
+        },
+        {
+            // Coeff Band ( 5 )
+            {  52,   7,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {  18,   6,   0,   0,   0,   0,   0,   0,   0,   0,   0, 652,},
+            {   1,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,  30,},
+        },
+        {
+            // Coeff Band ( 6 )
+            { 640, 569,  10,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {  25,  77,   2,   0,   0,   0,   0,   0,   0,   0,   0, 517,},
+            {   4,   7,   0,   0,   0,   0,   0,   0,   0,   0,   0,   3,},
+        },
+        {
+            // Coeff Band ( 7 )
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+        },
+    },
+    {
+        // Block Type ( 3 )
+        {
+            // Coeff Band ( 0 )
+            {2506, 20161, 2707, 767, 261, 178, 107,  30,  14,   3,   0, 100694,},
+            {8806, 36478, 8817, 3268, 1280, 850, 401, 114,  42,   0,   0, 58572,},
+            {11003, 27214, 11798, 5716, 2482, 2072, 1048, 175,  32,   0,   0, 19284,},
+        },
+        {
+            // Coeff Band ( 1 )
+            {9738, 11313, 959, 205,  70,  18,  11,   1,   0,   0,   0,   0,},
+            {12628, 15085, 1507, 273,  52,  19,   9,   0,   0,   0,   0, 54280,},
+            {10701, 15846, 5561, 1926, 813, 570, 249,  36,   0,   0,   0, 6460,},
+        },
+        {
+            // Coeff Band ( 2 )
+            {6781, 22539, 2784, 634, 182, 123,  20,   4,   0,   0,   0,   0,},
+            {6263, 11544, 2649, 790, 259, 168,  27,   5,   0,   0,   0, 20539,},
+            {3109, 4075, 2031, 896, 457, 386, 158,  29,   0,   0,   0, 1138,},
+        },
+        {
+            // Coeff Band ( 3 )
+            {11515, 4079, 465,  73,   5,  14,   2,   0,   0,   0,   0,   0,},
+            {9361, 5834, 650,  96,  24,   8,   4,   0,   0,   0,   0, 22181,},
+            {4343, 3974, 1360, 415, 132,  96,  14,   1,   0,   0,   0, 1267,},
+        },
+        {
+            // Coeff Band ( 4 )
+            {4787, 9297, 823, 168,  44,  12,   4,   0,   0,   0,   0,   0,},
+            {3619, 4472, 719, 198,  60,  31,   3,   0,   0,   0,   0, 8401,},
+            {1157, 1175, 483, 182,  88,  31,   8,   0,   0,   0,   0, 268,},
+        },
+        {
+            // Coeff Band ( 5 )
+            {8299, 1226,  32,   5,   1,   0,   0,   0,   0,   0,   0,   0,},
+            {3502, 1568,  57,   4,   1,   1,   0,   0,   0,   0,   0, 9811,},
+            {1055, 1070, 166,  29,   6,   1,   0,   0,   0,   0,   0, 527,},
+        },
+        {
+            // Coeff Band ( 6 )
+            {27414, 27927, 1989, 347,  69,  26,   0,   0,   0,   0,   0,   0,},
+            {5876, 10074, 1574, 341,  91,  24,   4,   0,   0,   0,   0, 21954,},
+            {1571, 2171, 778, 324, 124,  65,  16,   0,   0,   0,   0, 979,},
+        },
+        {
+            // Coeff Band ( 7 )
+            {   0,  29,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,  23,   0,   0,   0,   0,   0,   0,   0,   0,   0, 459,},
+            {   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,  13,},
+        },
+    },
+};
+
+//Update probabilities for the nodes in the token entropy tree.
+const vp8_prob tree_update_probs[vp8_coef_tree_dimen] =
+{
+    {
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255, },
+            {250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+    },
+    {
+        {
+            {217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255, },
+            {234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255, },
+        },
+        {
+            {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+    },
+    {
+        {
+            {186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255, },
+            {251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255, },
+        },
+        {
+            {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+    },
+    {
+        {
+            {248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255, },
+            {248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+    },
+};
+#endif
diff --git a/vp8/common/debugmodes.c b/vp8/common/debugmodes.c
new file mode 100644 (file)
index 0000000..46064e6
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include <stdio.h>
+#include "blockd.h"
+
+
+void vp8_print_modes_and_motion_vectors(MODE_INFO *mi, int rows, int cols, int frame)
+{
+
+    int mb_row;
+    int mb_col;
+    int mb_index = 0;
+    FILE *mvs = fopen("mvs.stt", "a");
+
+    /* print out the macroblock Y modes */
+    mb_index = 0;
+    fprintf(mvs, "Mb Modes for Frame %d\n", frame);
+
+    for (mb_row = 0; mb_row < rows; mb_row++)
+    {
+        for (mb_col = 0; mb_col < cols; mb_col++)
+        {
+
+            fprintf(mvs, "%2d ", mi[mb_index].mbmi.mode);
+
+            mb_index++;
+        }
+
+        fprintf(mvs, "\n");
+        mb_index++;
+    }
+
+    fprintf(mvs, "\n");
+
+    mb_index = 0;
+    fprintf(mvs, "Mb mv ref for Frame %d\n", frame);
+
+    for (mb_row = 0; mb_row < rows; mb_row++)
+    {
+        for (mb_col = 0; mb_col < cols; mb_col++)
+        {
+
+            fprintf(mvs, "%2d ", mi[mb_index].mbmi.ref_frame);
+
+            mb_index++;
+        }
+
+        fprintf(mvs, "\n");
+        mb_index++;
+    }
+
+    fprintf(mvs, "\n");
+
+    /* print out the macroblock UV modes */
+    mb_index = 0;
+    fprintf(mvs, "UV Modes for Frame %d\n", frame);
+
+    for (mb_row = 0; mb_row < rows; mb_row++)
+    {
+        for (mb_col = 0; mb_col < cols; mb_col++)
+        {
+
+            fprintf(mvs, "%2d ", mi[mb_index].mbmi.uv_mode);
+
+            mb_index++;
+        }
+
+        mb_index++;
+        fprintf(mvs, "\n");
+    }
+
+    fprintf(mvs, "\n");
+
+    /* print out the block modes */
+    mb_index = 0;
+    fprintf(mvs, "Mbs for Frame %d\n", frame);
+    {
+        int b_row;
+
+        for (b_row = 0; b_row < 4 * rows; b_row++)
+        {
+            int b_col;
+            int bindex;
+
+            for (b_col = 0; b_col < 4 * cols; b_col++)
+            {
+                mb_index = (b_row >> 2) * (cols + 1) + (b_col >> 2);
+                bindex = (b_row & 3) * 4 + (b_col & 3);
+
+                if (mi[mb_index].mbmi.mode == B_PRED)
+                    fprintf(mvs, "%2d ", mi[mb_index].bmi[bindex].as_mode);
+                else
+                    fprintf(mvs, "xx ");
+
+            }
+
+            fprintf(mvs, "\n");
+        }
+    }
+    fprintf(mvs, "\n");
+
+    /* print out the macroblock mvs */
+    mb_index = 0;
+    fprintf(mvs, "MVs for Frame %d\n", frame);
+
+    for (mb_row = 0; mb_row < rows; mb_row++)
+    {
+        for (mb_col = 0; mb_col < cols; mb_col++)
+        {
+            fprintf(mvs, "%5d:%-5d", mi[mb_index].mbmi.mv.as_mv.row / 2, mi[mb_index].mbmi.mv.as_mv.col / 2);
+
+            mb_index++;
+        }
+
+        mb_index++;
+        fprintf(mvs, "\n");
+    }
+
+    fprintf(mvs, "\n");
+
+
+    /* print out the block modes */
+    mb_index = 0;
+    fprintf(mvs, "MVs for Frame %d\n", frame);
+    {
+        int b_row;
+
+        for (b_row = 0; b_row < 4 * rows; b_row++)
+        {
+            int b_col;
+            int bindex;
+
+            for (b_col = 0; b_col < 4 * cols; b_col++)
+            {
+                mb_index = (b_row >> 2) * (cols + 1) + (b_col >> 2);
+                bindex = (b_row & 3) * 4 + (b_col & 3);
+                fprintf(mvs, "%3d:%-3d ", mi[mb_index].bmi[bindex].mv.as_mv.row, mi[mb_index].bmi[bindex].mv.as_mv.col);
+
+            }
+
+            fprintf(mvs, "\n");
+        }
+    }
+    fprintf(mvs, "\n");
+
+
+    fclose(mvs);
+}
diff --git a/vp8/common/default_coef_probs.h b/vp8/common/default_coef_probs.h
new file mode 100644 (file)
index 0000000..0d19563
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+*/
+
+
+/*Generated file, included by entropy.c*/
+
+
+static const vp8_prob default_coef_probs [BLOCK_TYPES]
+                                         [COEF_BANDS]
+                                         [PREV_COEF_CONTEXTS]
+                                         [ENTROPY_NODES] =
+{
+    { /* Block Type ( 0 ) */
+        { /* Coeff Band ( 0 )*/
+            { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
+            { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
+            { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
+        },
+        { /* Coeff Band ( 1 )*/
+            { 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 },
+            { 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 },
+            { 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128 }
+        },
+        { /* Coeff Band ( 2 )*/
+            {   1,  98, 248, 255, 236, 226, 255, 255, 128, 128, 128 },
+            { 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 },
+            {  78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 }
+        },
+        { /* Coeff Band ( 3 )*/
+            {   1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 },
+            { 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 },
+            {  77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 }
+        },
+        { /* Coeff Band ( 4 )*/
+            {   1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 },
+            { 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 },
+            {  37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 }
+        },
+        { /* Coeff Band ( 5 )*/
+            {   1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 },
+            { 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 },
+            { 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 }
+        },
+        { /* Coeff Band ( 6 )*/
+            {   1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 },
+            { 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 },
+            {  80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 }
+        },
+        { /* Coeff Band ( 7 )*/
+            {   1,   1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
+            { 246,   1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
+            { 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
+        }
+    },
+    { /* Block Type ( 1 ) */
+        { /* Coeff Band ( 0 )*/
+            { 198,  35, 237, 223, 193, 187, 162, 160, 145, 155,  62 },
+            { 131,  45, 198, 221, 172, 176, 220, 157, 252, 221,   1 },
+            {  68,  47, 146, 208, 149, 167, 221, 162, 255, 223, 128 }
+        },
+        { /* Coeff Band ( 1 )*/
+            {   1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 },
+            { 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 },
+            {  81,  99, 181, 242, 176, 190, 249, 202, 255, 255, 128 }
+        },
+        { /* Coeff Band ( 2 )*/
+            {   1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 },
+            {  99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 },
+            {  23,  91, 163, 242, 170, 187, 247, 210, 255, 255, 128 }
+        },
+        { /* Coeff Band ( 3 )*/
+            {   1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 },
+            { 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 },
+            {  44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 }
+        },
+        { /* Coeff Band ( 4 )*/
+            {   1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 },
+            {  94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 },
+            {  22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 }
+        },
+        { /* Coeff Band ( 5 )*/
+            {   1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 },
+            { 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 },
+            {  35,  77, 181, 251, 193, 211, 255, 205, 128, 128, 128 }
+        },
+        { /* Coeff Band ( 6 )*/
+            {   1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 },
+            { 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 },
+            {  45,  99, 188, 251, 195, 217, 255, 224, 128, 128, 128 }
+        },
+        { /* Coeff Band ( 7 )*/
+            {   1,   1, 251, 255, 213, 255, 128, 128, 128, 128, 128 },
+            { 203,   1, 248, 255, 255, 128, 128, 128, 128, 128, 128 },
+            { 137,   1, 177, 255, 224, 255, 128, 128, 128, 128, 128 }
+        }
+    },
+    { /* Block Type ( 2 ) */
+        { /* Coeff Band ( 0 )*/
+            { 253,   9, 248, 251, 207, 208, 255, 192, 128, 128, 128 },
+            { 175,  13, 224, 243, 193, 185, 249, 198, 255, 255, 128 },
+            {  73,  17, 171, 221, 161, 179, 236, 167, 255, 234, 128 }
+        },
+        { /* Coeff Band ( 1 )*/
+            {   1,  95, 247, 253, 212, 183, 255, 255, 128, 128, 128 },
+            { 239,  90, 244, 250, 211, 209, 255, 255, 128, 128, 128 },
+            { 155,  77, 195, 248, 188, 195, 255, 255, 128, 128, 128 }
+        },
+        { /* Coeff Band ( 2 )*/
+            {   1,  24, 239, 251, 218, 219, 255, 205, 128, 128, 128 },
+            { 201,  51, 219, 255, 196, 186, 128, 128, 128, 128, 128 },
+            {  69,  46, 190, 239, 201, 218, 255, 228, 128, 128, 128 }
+        },
+        { /* Coeff Band ( 3 )*/
+            {   1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 },
+            { 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 },
+            { 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 }
+        },
+        { /* Coeff Band ( 4 )*/
+            {   1,  16, 248, 255, 255, 128, 128, 128, 128, 128, 128 },
+            { 190,  36, 230, 255, 236, 255, 128, 128, 128, 128, 128 },
+            { 149,   1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
+        },
+        { /* Coeff Band ( 5 )*/
+            {   1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
+            { 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
+            { 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
+        },
+        { /* Coeff Band ( 6 )*/
+            {   1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 },
+            { 213,  62, 250, 255, 255, 128, 128, 128, 128, 128, 128 },
+            {  55,  93, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
+        },
+        { /* Coeff Band ( 7 )*/
+            { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
+            { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
+            { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
+        }
+    },
+    { /* Block Type ( 3 ) */
+        { /* Coeff Band ( 0 )*/
+            { 202,  24, 213, 235, 186, 191, 220, 160, 240, 175, 255 },
+            { 126,  38, 182, 232, 169, 184, 228, 174, 255, 187, 128 },
+            {  61,  46, 138, 219, 151, 178, 240, 170, 255, 216, 128 }
+        },
+        { /* Coeff Band ( 1 )*/
+            {   1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 },
+            { 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128 },
+            {  39,  77, 162, 232, 172, 180, 245, 178, 255, 255, 128 }
+        },
+        { /* Coeff Band ( 2 )*/
+            {   1,  52, 220, 246, 198, 199, 249, 220, 255, 255, 128 },
+            { 124,  74, 191, 243, 183, 193, 250, 221, 255, 255, 128 },
+            {  24,  71, 130, 219, 154, 170, 243, 182, 255, 255, 128 }
+        },
+        { /* Coeff Band ( 3 )*/
+            {   1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 },
+            { 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128 },
+            {  28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 }
+        },
+        { /* Coeff Band ( 4 )*/
+            {   1,  81, 230, 252, 204, 203, 255, 192, 128, 128, 128 },
+            { 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128 },
+            {  20,  95, 153, 243, 164, 173, 255, 203, 128, 128, 128 }
+        },
+        { /* Coeff Band ( 5 )*/
+            {   1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 },
+            { 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128 },
+            {  47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 }
+        },
+        { /* Coeff Band ( 6 )*/
+            {   1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 },
+            { 141,  84, 213, 252, 201, 202, 255, 219, 128, 128, 128 },
+            {  42,  80, 160, 240, 162, 185, 255, 205, 128, 128, 128 }
+        },
+        { /* Coeff Band ( 7 )*/
+            {   1,   1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
+            { 244,   1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
+            { 238,   1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
+        }
+    }
+};
diff --git a/vp8/common/dequantize.c b/vp8/common/dequantize.c
new file mode 100644 (file)
index 0000000..8eda486
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "vp8/common/blockd.h"
+#include "vpx_mem/vpx_mem.h"
+
+void vp8_dequantize_b_c(BLOCKD *d, short *DQC)
+{
+    int i;
+    short *DQ  = d->dqcoeff;
+    short *Q   = d->qcoeff;
+
+    for (i = 0; i < 16; i++)
+    {
+        DQ[i] = Q[i] * DQC[i];
+    }
+}
+
+void vp8_dequant_idct_add_c(short *input, short *dq,
+                            unsigned char *dest, int stride)
+{
+    int i;
+
+    for (i = 0; i < 16; i++)
+    {
+        input[i] = dq[i] * input[i];
+    }
+
+    vp8_short_idct4x4llm_c(input, dest, stride, dest, stride);
+
+    vpx_memset(input, 0, 32);
+
+}
diff --git a/vp8/common/entropy.c b/vp8/common/entropy.c
new file mode 100644 (file)
index 0000000..a95a923
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "entropy.h"
+#include "blockd.h"
+#include "onyxc_int.h"
+#include "vpx_mem/vpx_mem.h"
+
+#include "coefupdateprobs.h"
+
+DECLARE_ALIGNED(16, const unsigned char, vp8_norm[256]) =
+{
+    0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+    2, 2, 2, 2, 2, 2, 2, 2, 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,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+DECLARE_ALIGNED(16, const unsigned char, vp8_coef_bands[16]) =
+{ 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7};
+
+DECLARE_ALIGNED(16, const unsigned char,
+                vp8_prev_token_class[MAX_ENTROPY_TOKENS]) =
+{ 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0};
+
+DECLARE_ALIGNED(16, const int, vp8_default_zig_zag1d[16]) =
+{
+    0,  1,  4,  8,
+    5,  2,  3,  6,
+    9, 12, 13, 10,
+    7, 11, 14, 15,
+};
+
+DECLARE_ALIGNED(16, const short, vp8_default_inv_zig_zag[16]) =
+{
+    1,  2,  6,  7,
+    3,  5,  8, 13,
+    4,  9, 12, 14,
+   10, 11, 15, 16
+};
+
+/* vp8_default_zig_zag_mask generated with:
+
+    void vp8_init_scan_order_mask()
+    {
+        int i;
+
+        for (i = 0; i < 16; i++)
+        {
+            vp8_default_zig_zag_mask[vp8_default_zig_zag1d[i]] = 1 << i;
+        }
+
+    }
+*/
+DECLARE_ALIGNED(16, const short, vp8_default_zig_zag_mask[16]) =
+{
+     1,    2,    32,     64,
+     4,   16,   128,   4096,
+     8,  256,  2048,   8192,
+   512, 1024, 16384, -32768
+};
+
+const int vp8_mb_feature_data_bits[MB_LVL_MAX] = {7, 6};
+
+/* Array indices are identical to previously-existing CONTEXT_NODE indices */
+
+const vp8_tree_index vp8_coef_tree[ 22] =     /* corresponding _CONTEXT_NODEs */
+{
+    -DCT_EOB_TOKEN, 2,                             /* 0 = EOB */
+    -ZERO_TOKEN, 4,                               /* 1 = ZERO */
+    -ONE_TOKEN, 6,                               /* 2 = ONE */
+    8, 12,                                      /* 3 = LOW_VAL */
+    -TWO_TOKEN, 10,                            /* 4 = TWO */
+    -THREE_TOKEN, -FOUR_TOKEN,                /* 5 = THREE */
+    14, 16,                                    /* 6 = HIGH_LOW */
+    -DCT_VAL_CATEGORY1, -DCT_VAL_CATEGORY2,   /* 7 = CAT_ONE */
+    18, 20,                                   /* 8 = CAT_THREEFOUR */
+    -DCT_VAL_CATEGORY3, -DCT_VAL_CATEGORY4,  /* 9 = CAT_THREE */
+    -DCT_VAL_CATEGORY5, -DCT_VAL_CATEGORY6   /* 10 = CAT_FIVE */
+};
+
+/* vp8_coef_encodings generated with:
+    vp8_tokens_from_tree(vp8_coef_encodings, vp8_coef_tree);
+*/
+const vp8_token vp8_coef_encodings[MAX_ENTROPY_TOKENS] =
+{
+    {2, 2},
+    {6, 3},
+    {28, 5},
+    {58, 6},
+    {59, 6},
+    {60, 6},
+    {61, 6},
+    {124, 7},
+    {125, 7},
+    {126, 7},
+    {127, 7},
+    {0, 1}
+};
+
+/* Trees for extra bits.  Probabilities are constant and
+   do not depend on previously encoded bits */
+
+static const vp8_prob Pcat1[] = { 159};
+static const vp8_prob Pcat2[] = { 165, 145};
+static const vp8_prob Pcat3[] = { 173, 148, 140};
+static const vp8_prob Pcat4[] = { 176, 155, 140, 135};
+static const vp8_prob Pcat5[] = { 180, 157, 141, 134, 130};
+static const vp8_prob Pcat6[] =
+{ 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129};
+
+
+/* tree index tables generated with:
+
+    void init_bit_tree(vp8_tree_index *p, int n)
+    {
+        int i = 0;
+
+        while (++i < n)
+        {
+            p[0] = p[1] = i << 1;
+            p += 2;
+        }
+
+        p[0] = p[1] = 0;
+    }
+
+    void init_bit_trees()
+    {
+        init_bit_tree(cat1, 1);
+        init_bit_tree(cat2, 2);
+        init_bit_tree(cat3, 3);
+        init_bit_tree(cat4, 4);
+        init_bit_tree(cat5, 5);
+        init_bit_tree(cat6, 11);
+    }
+*/
+
+static const vp8_tree_index cat1[2] = { 0, 0 };
+static const vp8_tree_index cat2[4] = { 2, 2, 0, 0 };
+static const vp8_tree_index cat3[6] = { 2, 2, 4, 4, 0, 0 };
+static const vp8_tree_index cat4[8] = { 2, 2, 4, 4, 6, 6, 0, 0 };
+static const vp8_tree_index cat5[10] = { 2, 2, 4, 4, 6, 6, 8, 8, 0, 0 };
+static const vp8_tree_index cat6[22] = { 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12,
+                                        14, 14, 16, 16, 18, 18, 20, 20, 0, 0 };
+
+const vp8_extra_bit_struct vp8_extra_bits[12] =
+{
+    { 0, 0, 0, 0},
+    { 0, 0, 0, 1},
+    { 0, 0, 0, 2},
+    { 0, 0, 0, 3},
+    { 0, 0, 0, 4},
+    { cat1, Pcat1, 1, 5},
+    { cat2, Pcat2, 2, 7},
+    { cat3, Pcat3, 3, 11},
+    { cat4, Pcat4, 4, 19},
+    { cat5, Pcat5, 5, 35},
+    { cat6, Pcat6, 11, 67},
+    { 0, 0, 0, 0}
+};
+
+#include "default_coef_probs.h"
+
+void vp8_default_coef_probs(VP8_COMMON *pc)
+{
+    vpx_memcpy(pc->fc.coef_probs, default_coef_probs,
+                   sizeof(default_coef_probs));
+}
+
diff --git a/vp8/common/entropy.h b/vp8/common/entropy.h
new file mode 100644 (file)
index 0000000..5389bc1
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_ENTROPY_H
+#define __INC_ENTROPY_H
+
+#include "treecoder.h"
+#include "blockd.h"
+
+/* Coefficient token alphabet */
+
+#define ZERO_TOKEN              0       /* 0         Extra Bits 0+0 */
+#define ONE_TOKEN               1       /* 1         Extra Bits 0+1 */
+#define TWO_TOKEN               2       /* 2         Extra Bits 0+1 */
+#define THREE_TOKEN             3       /* 3         Extra Bits 0+1 */
+#define FOUR_TOKEN              4       /* 4         Extra Bits 0+1 */
+#define DCT_VAL_CATEGORY1       5       /* 5-6       Extra Bits 1+1 */
+#define DCT_VAL_CATEGORY2       6       /* 7-10      Extra Bits 2+1 */
+#define DCT_VAL_CATEGORY3       7       /* 11-18     Extra Bits 3+1 */
+#define DCT_VAL_CATEGORY4       8       /* 19-34     Extra Bits 4+1 */
+#define DCT_VAL_CATEGORY5       9       /* 35-66     Extra Bits 5+1 */
+#define DCT_VAL_CATEGORY6       10      /* 67+       Extra Bits 11+1 */
+#define DCT_EOB_TOKEN           11      /* EOB       Extra Bits 0+0 */
+
+#define MAX_ENTROPY_TOKENS 12
+#define ENTROPY_NODES 11
+
+extern const vp8_tree_index vp8_coef_tree[];
+
+extern const struct vp8_token_struct vp8_coef_encodings[MAX_ENTROPY_TOKENS];
+
+typedef struct
+{
+    vp8_tree_p tree;
+    const vp8_prob *prob;
+    int Len;
+    int base_val;
+} vp8_extra_bit_struct;
+
+extern const vp8_extra_bit_struct vp8_extra_bits[12];    /* indexed by token value */
+
+#define PROB_UPDATE_BASELINE_COST   7
+
+#define MAX_PROB                255
+#define DCT_MAX_VALUE           2048
+
+
+/* Coefficients are predicted via a 3-dimensional probability table. */
+
+/* Outside dimension.  0 = Y no DC, 1 = Y2, 2 = UV, 3 = Y with DC */
+
+#define BLOCK_TYPES 4
+
+/* Middle dimension is a coarsening of the coefficient's
+   position within the 4x4 DCT. */
+
+#define COEF_BANDS 8
+extern DECLARE_ALIGNED(16, const unsigned char, vp8_coef_bands[16]);
+
+/* Inside dimension is 3-valued measure of nearby complexity, that is,
+   the extent to which nearby coefficients are nonzero.  For the first
+   coefficient (DC, unless block type is 0), we look at the (already encoded)
+   blocks above and to the left of the current block.  The context index is
+   then the number (0,1,or 2) of these blocks having nonzero coefficients.
+   After decoding a coefficient, the measure is roughly the size of the
+   most recently decoded coefficient (0 for 0, 1 for 1, 2 for >1).
+   Note that the intuitive meaning of this measure changes as coefficients
+   are decoded, e.g., prior to the first token, a zero means that my neighbors
+   are empty while, after the first token, because of the use of end-of-block,
+   a zero means we just decoded a zero and hence guarantees that a non-zero
+   coefficient will appear later in this block.  However, this shift
+   in meaning is perfectly OK because our context depends also on the
+   coefficient band (and since zigzag positions 0, 1, and 2 are in
+   distinct bands). */
+
+/*# define DC_TOKEN_CONTEXTS        3*/ /* 00, 0!0, !0!0 */
+#   define PREV_COEF_CONTEXTS       3
+
+extern DECLARE_ALIGNED(16, const unsigned char, vp8_prev_token_class[MAX_ENTROPY_TOKENS]);
+
+extern const vp8_prob vp8_coef_update_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES];
+
+
+struct VP8Common;
+void vp8_default_coef_probs(struct VP8Common *);
+
+extern DECLARE_ALIGNED(16, const int, vp8_default_zig_zag1d[16]);
+extern DECLARE_ALIGNED(16, const short, vp8_default_inv_zig_zag[16]);
+extern DECLARE_ALIGNED(16, const short, vp8_default_zig_zag_mask[16]);
+extern const int vp8_mb_feature_data_bits[MB_LVL_MAX];
+
+void vp8_coef_tree_initialize(void);
+#endif
diff --git a/vp8/common/entropymode.c b/vp8/common/entropymode.c
new file mode 100644 (file)
index 0000000..de7e828
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#define USE_PREBUILT_TABLES
+
+#include "entropymode.h"
+#include "entropy.h"
+#include "vpx_mem/vpx_mem.h"
+
+#include "vp8_entropymodedata.h"
+
+int vp8_mv_cont(const int_mv *l, const int_mv *a)
+{
+    int lez = (l->as_int == 0);
+    int aez = (a->as_int == 0);
+    int lea = (l->as_int == a->as_int);
+
+    if (lea && lez)
+        return SUBMVREF_LEFT_ABOVE_ZED;
+
+    if (lea)
+        return SUBMVREF_LEFT_ABOVE_SAME;
+
+    if (aez)
+        return SUBMVREF_ABOVE_ZED;
+
+    if (lez)
+        return SUBMVREF_LEFT_ZED;
+
+    return SUBMVREF_NORMAL;
+}
+
+static const vp8_prob sub_mv_ref_prob [VP8_SUBMVREFS-1] = { 180, 162, 25};
+
+const vp8_prob vp8_sub_mv_ref_prob2 [SUBMVREF_COUNT][VP8_SUBMVREFS-1] =
+{
+    { 147, 136, 18 },
+    { 106, 145, 1  },
+    { 179, 121, 1  },
+    { 223, 1  , 34 },
+    { 208, 1  , 1  }
+};
+
+
+
+const vp8_mbsplit vp8_mbsplits [VP8_NUMMBSPLITS] =
+{
+    {
+        0,  0,  0,  0,
+        0,  0,  0,  0,
+        1,  1,  1,  1,
+        1,  1,  1,  1,
+    },
+    {
+        0,  0,  1,  1,
+        0,  0,  1,  1,
+        0,  0,  1,  1,
+        0,  0,  1,  1,
+    },
+    {
+        0,  0,  1,  1,
+        0,  0,  1,  1,
+        2,  2,  3,  3,
+        2,  2,  3,  3,
+    },
+    {
+        0,  1,  2,  3,
+        4,  5,  6,  7,
+        8,  9,  10, 11,
+        12, 13, 14, 15,
+    }
+};
+
+const int vp8_mbsplit_count [VP8_NUMMBSPLITS] = { 2, 2, 4, 16};
+
+const vp8_prob vp8_mbsplit_probs [VP8_NUMMBSPLITS-1] = { 110, 111, 150};
+
+
+/* Array indices are identical to previously-existing INTRAMODECONTEXTNODES. */
+
+const vp8_tree_index vp8_bmode_tree[18] =     /* INTRAMODECONTEXTNODE value */
+{
+    -B_DC_PRED, 2,                             /* 0 = DC_NODE */
+    -B_TM_PRED, 4,                            /* 1 = TM_NODE */
+    -B_VE_PRED, 6,                           /* 2 = VE_NODE */
+    8, 12,                                  /* 3 = COM_NODE */
+    -B_HE_PRED, 10,                        /* 4 = HE_NODE */
+    -B_RD_PRED, -B_VR_PRED,               /* 5 = RD_NODE */
+    -B_LD_PRED, 14,                        /* 6 = LD_NODE */
+    -B_VL_PRED, 16,                      /* 7 = VL_NODE */
+    -B_HD_PRED, -B_HU_PRED             /* 8 = HD_NODE */
+};
+
+/* Again, these trees use the same probability indices as their
+   explicitly-programmed predecessors. */
+
+const vp8_tree_index vp8_ymode_tree[8] =
+{
+    -DC_PRED, 2,
+    4, 6,
+    -V_PRED, -H_PRED,
+    -TM_PRED, -B_PRED
+};
+
+const vp8_tree_index vp8_kf_ymode_tree[8] =
+{
+    -B_PRED, 2,
+    4, 6,
+    -DC_PRED, -V_PRED,
+    -H_PRED, -TM_PRED
+};
+
+const vp8_tree_index vp8_uv_mode_tree[6] =
+{
+    -DC_PRED, 2,
+    -V_PRED, 4,
+    -H_PRED, -TM_PRED
+};
+
+const vp8_tree_index vp8_mbsplit_tree[6] =
+{
+    -3, 2,
+    -2, 4,
+    -0, -1
+};
+
+const vp8_tree_index vp8_mv_ref_tree[8] =
+{
+    -ZEROMV, 2,
+    -NEARESTMV, 4,
+    -NEARMV, 6,
+    -NEWMV, -SPLITMV
+};
+
+const vp8_tree_index vp8_sub_mv_ref_tree[6] =
+{
+    -LEFT4X4, 2,
+    -ABOVE4X4, 4,
+    -ZERO4X4, -NEW4X4
+};
+
+const vp8_tree_index vp8_small_mvtree [14] =
+{
+    2, 8,
+    4, 6,
+    -0, -1,
+    -2, -3,
+    10, 12,
+    -4, -5,
+    -6, -7
+};
+
+void vp8_init_mbmode_probs(VP8_COMMON *x)
+{
+    vpx_memcpy(x->fc.ymode_prob, vp8_ymode_prob, sizeof(vp8_ymode_prob));
+    vpx_memcpy(x->kf_ymode_prob, vp8_kf_ymode_prob, sizeof(vp8_kf_ymode_prob));
+    vpx_memcpy(x->fc.uv_mode_prob, vp8_uv_mode_prob, sizeof(vp8_uv_mode_prob));
+    vpx_memcpy(x->kf_uv_mode_prob, vp8_kf_uv_mode_prob, sizeof(vp8_kf_uv_mode_prob));
+    vpx_memcpy(x->fc.sub_mv_ref_prob, sub_mv_ref_prob, sizeof(sub_mv_ref_prob));
+}
+
+void vp8_default_bmode_probs(vp8_prob p [VP8_BINTRAMODES-1])
+{
+    vpx_memcpy(p, vp8_bmode_prob, sizeof(vp8_bmode_prob));
+}
+
+void vp8_kf_default_bmode_probs(vp8_prob p [VP8_BINTRAMODES] [VP8_BINTRAMODES] [VP8_BINTRAMODES-1])
+{
+    vpx_memcpy(p, vp8_kf_bmode_prob, sizeof(vp8_kf_bmode_prob));
+}
diff --git a/vp8/common/entropymode.h b/vp8/common/entropymode.h
new file mode 100644 (file)
index 0000000..70200cb
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_ENTROPYMODE_H
+#define __INC_ENTROPYMODE_H
+
+#include "onyxc_int.h"
+#include "treecoder.h"
+
+typedef enum
+{
+    SUBMVREF_NORMAL,
+    SUBMVREF_LEFT_ZED,
+    SUBMVREF_ABOVE_ZED,
+    SUBMVREF_LEFT_ABOVE_SAME,
+    SUBMVREF_LEFT_ABOVE_ZED
+} sumvfref_t;
+
+typedef const int vp8_mbsplit[16];
+
+#define VP8_NUMMBSPLITS 4
+
+extern vp8_mbsplit vp8_mbsplits [VP8_NUMMBSPLITS];
+
+extern const int vp8_mbsplit_count [VP8_NUMMBSPLITS];    /* # of subsets */
+
+extern const vp8_prob vp8_mbsplit_probs [VP8_NUMMBSPLITS-1];
+
+extern int vp8_mv_cont(const int_mv *l, const int_mv *a);
+#define SUBMVREF_COUNT 5
+extern const vp8_prob vp8_sub_mv_ref_prob2 [SUBMVREF_COUNT][VP8_SUBMVREFS-1];
+
+
+extern const unsigned int vp8_kf_default_bmode_counts [VP8_BINTRAMODES] [VP8_BINTRAMODES] [VP8_BINTRAMODES];
+
+
+extern const vp8_tree_index vp8_bmode_tree[];
+
+extern const vp8_tree_index  vp8_ymode_tree[];
+extern const vp8_tree_index  vp8_kf_ymode_tree[];
+extern const vp8_tree_index  vp8_uv_mode_tree[];
+
+extern const vp8_tree_index  vp8_mbsplit_tree[];
+extern const vp8_tree_index  vp8_mv_ref_tree[];
+extern const vp8_tree_index  vp8_sub_mv_ref_tree[];
+
+extern const struct vp8_token_struct vp8_bmode_encodings[VP8_BINTRAMODES];
+extern const struct vp8_token_struct vp8_ymode_encodings[VP8_YMODES];
+extern const struct vp8_token_struct vp8_kf_ymode_encodings[VP8_YMODES];
+extern const struct vp8_token_struct vp8_uv_mode_encodings[VP8_UV_MODES];
+extern const struct vp8_token_struct vp8_mbsplit_encodings[VP8_NUMMBSPLITS];
+
+/* Inter mode values do not start at zero */
+
+extern const struct vp8_token_struct vp8_mv_ref_encoding_array[VP8_MVREFS];
+extern const struct vp8_token_struct vp8_sub_mv_ref_encoding_array[VP8_SUBMVREFS];
+
+extern const vp8_tree_index vp8_small_mvtree[];
+
+extern const struct vp8_token_struct vp8_small_mvencodings[8];
+
+void vp8_init_mbmode_probs(VP8_COMMON *x);
+
+void   vp8_default_bmode_probs(vp8_prob dest [VP8_BINTRAMODES-1]);
+void vp8_kf_default_bmode_probs(vp8_prob dest [VP8_BINTRAMODES] [VP8_BINTRAMODES] [VP8_BINTRAMODES-1]);
+
+#endif
diff --git a/vp8/common/entropymv.c b/vp8/common/entropymv.c
new file mode 100644 (file)
index 0000000..e5df1f0
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "entropymv.h"
+
+const MV_CONTEXT vp8_mv_update_probs[2] =
+{
+    {{
+        237,
+        246,
+        253, 253, 254, 254, 254, 254, 254,
+        254, 254, 254, 254, 254, 250, 250, 252, 254, 254
+    }},
+    {{
+        231,
+        243,
+        245, 253, 254, 254, 254, 254, 254,
+        254, 254, 254, 254, 254, 251, 251, 254, 254, 254
+    }}
+};
+const MV_CONTEXT vp8_default_mv_context[2] =
+{
+    {{
+        /* row */
+        162,                                        /* is short */
+        128,                                        /* sign */
+        225, 146, 172, 147, 214,  39, 156,          /* short tree */
+        128, 129, 132,  75, 145, 178, 206, 239, 254, 254 /* long bits */
+    }},
+
+
+
+    {{
+        /* same for column */
+        164,                                        /* is short */
+        128,
+        204, 170, 119, 235, 140, 230, 228,
+        128, 130, 130,  74, 148, 180, 203, 236, 254, 254 /* long bits */
+
+    }}
+};
diff --git a/vp8/common/entropymv.h b/vp8/common/entropymv.h
new file mode 100644 (file)
index 0000000..2db1e38
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_ENTROPYMV_H
+#define __INC_ENTROPYMV_H
+
+#include "treecoder.h"
+
+enum
+{
+    mv_max  = 1023,              /* max absolute value of a MV component */
+    MVvals = (2 * mv_max) + 1,   /* # possible values "" */
+    mvfp_max  = 255,              /* max absolute value of a full pixel MV component */
+    MVfpvals = (2 * mvfp_max) +1, /* # possible full pixel MV values */
+
+    mvlong_width = 10,       /* Large MVs have 9 bit magnitudes */
+    mvnum_short = 8,         /* magnitudes 0 through 7 */
+
+    /* probability offsets for coding each MV component */
+
+    mvpis_short = 0,         /* short (<= 7) vs long (>= 8) */
+    MVPsign,                /* sign for non-zero */
+    MVPshort,               /* 8 short values = 7-position tree */
+
+    MVPbits = MVPshort + mvnum_short - 1, /* mvlong_width long value bits */
+    MVPcount = MVPbits + mvlong_width    /* (with independent probabilities) */
+};
+
+typedef struct mv_context
+{
+    vp8_prob prob[MVPcount];  /* often come in row, col pairs */
+} MV_CONTEXT;
+
+extern const MV_CONTEXT vp8_mv_update_probs[2], vp8_default_mv_context[2];
+
+#endif
diff --git a/vp8/common/extend.c b/vp8/common/extend.c
new file mode 100644 (file)
index 0000000..9089e16
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "extend.h"
+#include "vpx_mem/vpx_mem.h"
+
+
+static void copy_and_extend_plane
+(
+    unsigned char *s, /* source */
+    int sp,           /* source pitch */
+    unsigned char *d, /* destination */
+    int dp,           /* destination pitch */
+    int h,            /* height */
+    int w,            /* width */
+    int et,           /* extend top border */
+    int el,           /* extend left border */
+    int eb,           /* extend bottom border */
+    int er            /* extend right border */
+)
+{
+    int i;
+    unsigned char *src_ptr1, *src_ptr2;
+    unsigned char *dest_ptr1, *dest_ptr2;
+    int linesize;
+
+    /* copy the left and right most columns out */
+    src_ptr1 = s;
+    src_ptr2 = s + w - 1;
+    dest_ptr1 = d - el;
+    dest_ptr2 = d + w;
+
+    for (i = 0; i < h; i++)
+    {
+        vpx_memset(dest_ptr1, src_ptr1[0], el);
+        vpx_memcpy(dest_ptr1 + el, src_ptr1, w);
+        vpx_memset(dest_ptr2, src_ptr2[0], er);
+        src_ptr1  += sp;
+        src_ptr2  += sp;
+        dest_ptr1 += dp;
+        dest_ptr2 += dp;
+    }
+
+    /* Now copy the top and bottom lines into each line of the respective
+     * borders
+     */
+    src_ptr1 = d - el;
+    src_ptr2 = d + dp * (h - 1) - el;
+    dest_ptr1 = d + dp * (-et) - el;
+    dest_ptr2 = d + dp * (h) - el;
+    linesize = el + er + w;
+
+    for (i = 0; i < et; i++)
+    {
+        vpx_memcpy(dest_ptr1, src_ptr1, linesize);
+        dest_ptr1 += dp;
+    }
+
+    for (i = 0; i < eb; i++)
+    {
+        vpx_memcpy(dest_ptr2, src_ptr2, linesize);
+        dest_ptr2 += dp;
+    }
+}
+
+
+void vp8_copy_and_extend_frame(YV12_BUFFER_CONFIG *src,
+                               YV12_BUFFER_CONFIG *dst)
+{
+    int et = dst->border;
+    int el = dst->border;
+    int eb = dst->border + dst->y_height - src->y_height;
+    int er = dst->border + dst->y_width - src->y_width;
+
+    copy_and_extend_plane(src->y_buffer, src->y_stride,
+                          dst->y_buffer, dst->y_stride,
+                          src->y_height, src->y_width,
+                          et, el, eb, er);
+
+    et = dst->border >> 1;
+    el = dst->border >> 1;
+    eb = (dst->border >> 1) + dst->uv_height - src->uv_height;
+    er = (dst->border >> 1) + dst->uv_width - src->uv_width;
+
+    copy_and_extend_plane(src->u_buffer, src->uv_stride,
+                          dst->u_buffer, dst->uv_stride,
+                          src->uv_height, src->uv_width,
+                          et, el, eb, er);
+
+    copy_and_extend_plane(src->v_buffer, src->uv_stride,
+                          dst->v_buffer, dst->uv_stride,
+                          src->uv_height, src->uv_width,
+                          et, el, eb, er);
+}
+
+
+void vp8_copy_and_extend_frame_with_rect(YV12_BUFFER_CONFIG *src,
+                                         YV12_BUFFER_CONFIG *dst,
+                                         int srcy, int srcx,
+                                         int srch, int srcw)
+{
+    int et = dst->border;
+    int el = dst->border;
+    int eb = dst->border + dst->y_height - src->y_height;
+    int er = dst->border + dst->y_width - src->y_width;
+    int src_y_offset = srcy * src->y_stride + srcx;
+    int dst_y_offset = srcy * dst->y_stride + srcx;
+    int src_uv_offset = ((srcy * src->uv_stride) >> 1) + (srcx >> 1);
+    int dst_uv_offset = ((srcy * dst->uv_stride) >> 1) + (srcx >> 1);
+
+    // If the side is not touching the bounder then don't extend.
+    if (srcy)
+      et = 0;
+    if (srcx)
+      el = 0;
+    if (srcy + srch != src->y_height)
+      eb = 0;
+    if (srcx + srcw != src->y_width)
+      er = 0;
+
+    copy_and_extend_plane(src->y_buffer + src_y_offset,
+                          src->y_stride,
+                          dst->y_buffer + dst_y_offset,
+                          dst->y_stride,
+                          srch, srcw,
+                          et, el, eb, er);
+
+    et = (et + 1) >> 1;
+    el = (el + 1) >> 1;
+    eb = (eb + 1) >> 1;
+    er = (er + 1) >> 1;
+    srch = (srch + 1) >> 1;
+    srcw = (srcw + 1) >> 1;
+
+    copy_and_extend_plane(src->u_buffer + src_uv_offset,
+                          src->uv_stride,
+                          dst->u_buffer + dst_uv_offset,
+                          dst->uv_stride,
+                          srch, srcw,
+                          et, el, eb, er);
+
+    copy_and_extend_plane(src->v_buffer + src_uv_offset,
+                          src->uv_stride,
+                          dst->v_buffer + dst_uv_offset,
+                          dst->uv_stride,
+                          srch, srcw,
+                          et, el, eb, er);
+}
+
+
+/* note the extension is only for the last row, for intra prediction purpose */
+void vp8_extend_mb_row(YV12_BUFFER_CONFIG *ybf, unsigned char *YPtr, unsigned char *UPtr, unsigned char *VPtr)
+{
+    int i;
+
+    YPtr += ybf->y_stride * 14;
+    UPtr += ybf->uv_stride * 6;
+    VPtr += ybf->uv_stride * 6;
+
+    for (i = 0; i < 4; i++)
+    {
+        YPtr[i] = YPtr[-1];
+        UPtr[i] = UPtr[-1];
+        VPtr[i] = VPtr[-1];
+    }
+
+    YPtr += ybf->y_stride;
+    UPtr += ybf->uv_stride;
+    VPtr += ybf->uv_stride;
+
+    for (i = 0; i < 4; i++)
+    {
+        YPtr[i] = YPtr[-1];
+        UPtr[i] = UPtr[-1];
+        VPtr[i] = VPtr[-1];
+    }
+}
diff --git a/vp8/common/extend.h b/vp8/common/extend.h
new file mode 100644 (file)
index 0000000..74a0b17
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_EXTEND_H
+#define __INC_EXTEND_H
+
+#include "vpx_scale/yv12config.h"
+
+void vp8_extend_mb_row(YV12_BUFFER_CONFIG *ybf, unsigned char *YPtr, unsigned char *UPtr, unsigned char *VPtr);
+void vp8_copy_and_extend_frame(YV12_BUFFER_CONFIG *src,
+                               YV12_BUFFER_CONFIG *dst);
+void vp8_copy_and_extend_frame_with_rect(YV12_BUFFER_CONFIG *src,
+                                         YV12_BUFFER_CONFIG *dst,
+                                         int srcy, int srcx,
+                                         int srch, int srcw);
+
+#endif
diff --git a/vp8/common/filter.c b/vp8/common/filter.c
new file mode 100644 (file)
index 0000000..1901ea3
--- /dev/null
@@ -0,0 +1,494 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include <stdlib.h>
+#include "filter.h"
+#include "vpx_ports/mem.h"
+
+DECLARE_ALIGNED(16, const short, vp8_bilinear_filters[8][2]) =
+{
+    { 128,   0 },
+    { 112,  16 },
+    {  96,  32 },
+    {  80,  48 },
+    {  64,  64 },
+    {  48,  80 },
+    {  32,  96 },
+    {  16, 112 }
+};
+
+DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters[8][6]) =
+{
+
+    { 0,  0,  128,    0,   0,  0 },         /* note that 1/8 pel positions are just as per alpha -0.5 bicubic */
+    { 0, -6,  123,   12,  -1,  0 },
+    { 2, -11, 108,   36,  -8,  1 },         /* New 1/4 pel 6 tap filter */
+    { 0, -9,   93,   50,  -6,  0 },
+    { 3, -16,  77,   77, -16,  3 },         /* New 1/2 pel 6 tap filter */
+    { 0, -6,   50,   93,  -9,  0 },
+    { 1, -8,   36,  108, -11,  2 },         /* New 1/4 pel 6 tap filter */
+    { 0, -1,   12,  123,  -6,  0 },
+};
+
+static void filter_block2d_first_pass
+(
+    unsigned char *src_ptr,
+    int *output_ptr,
+    unsigned int src_pixels_per_line,
+    unsigned int pixel_step,
+    unsigned int output_height,
+    unsigned int output_width,
+    const short *vp8_filter
+)
+{
+    unsigned int i, j;
+    int  Temp;
+
+    for (i = 0; i < output_height; i++)
+    {
+        for (j = 0; j < output_width; j++)
+        {
+            Temp = ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[0]) +
+                   ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[1]) +
+                   ((int)src_ptr[0]                 * vp8_filter[2]) +
+                   ((int)src_ptr[pixel_step]         * vp8_filter[3]) +
+                   ((int)src_ptr[2*pixel_step]       * vp8_filter[4]) +
+                   ((int)src_ptr[3*pixel_step]       * vp8_filter[5]) +
+                   (VP8_FILTER_WEIGHT >> 1);      /* Rounding */
+
+            /* Normalize back to 0-255 */
+            Temp = Temp >> VP8_FILTER_SHIFT;
+
+            if (Temp < 0)
+                Temp = 0;
+            else if (Temp > 255)
+                Temp = 255;
+
+            output_ptr[j] = Temp;
+            src_ptr++;
+        }
+
+        /* Next row... */
+        src_ptr    += src_pixels_per_line - output_width;
+        output_ptr += output_width;
+    }
+}
+
+static void filter_block2d_second_pass
+(
+    int *src_ptr,
+    unsigned char *output_ptr,
+    int output_pitch,
+    unsigned int src_pixels_per_line,
+    unsigned int pixel_step,
+    unsigned int output_height,
+    unsigned int output_width,
+    const short *vp8_filter
+)
+{
+    unsigned int i, j;
+    int  Temp;
+
+    for (i = 0; i < output_height; i++)
+    {
+        for (j = 0; j < output_width; j++)
+        {
+            /* Apply filter */
+            Temp = ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[0]) +
+                   ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[1]) +
+                   ((int)src_ptr[0]                 * vp8_filter[2]) +
+                   ((int)src_ptr[pixel_step]         * vp8_filter[3]) +
+                   ((int)src_ptr[2*pixel_step]       * vp8_filter[4]) +
+                   ((int)src_ptr[3*pixel_step]       * vp8_filter[5]) +
+                   (VP8_FILTER_WEIGHT >> 1);   /* Rounding */
+
+            /* Normalize back to 0-255 */
+            Temp = Temp >> VP8_FILTER_SHIFT;
+
+            if (Temp < 0)
+                Temp = 0;
+            else if (Temp > 255)
+                Temp = 255;
+
+            output_ptr[j] = (unsigned char)Temp;
+            src_ptr++;
+        }
+
+        /* Start next row */
+        src_ptr    += src_pixels_per_line - output_width;
+        output_ptr += output_pitch;
+    }
+}
+
+
+static void filter_block2d
+(
+    unsigned char  *src_ptr,
+    unsigned char  *output_ptr,
+    unsigned int src_pixels_per_line,
+    int output_pitch,
+    const short  *HFilter,
+    const short  *VFilter
+)
+{
+    int FData[9*4]; /* Temp data buffer used in filtering */
+
+    /* First filter 1-D horizontally... */
+    filter_block2d_first_pass(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 1, 9, 4, HFilter);
+
+    /* then filter verticaly... */
+    filter_block2d_second_pass(FData + 8, output_ptr, output_pitch, 4, 4, 4, 4, VFilter);
+}
+
+
+void vp8_sixtap_predict4x4_c
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+
+    HFilter = vp8_sub_pel_filters[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters[yoffset];   /* 6 tap */
+
+    filter_block2d(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter);
+}
+void vp8_sixtap_predict8x8_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    int FData[13*16];   /* Temp data buffer used in filtering */
+
+    HFilter = vp8_sub_pel_filters[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters[yoffset];   /* 6 tap */
+
+    /* First filter 1-D horizontally... */
+    filter_block2d_first_pass(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 1, 13, 8, HFilter);
+
+
+    /* then filter verticaly... */
+    filter_block2d_second_pass(FData + 16, dst_ptr, dst_pitch, 8, 8, 8, 8, VFilter);
+
+}
+
+void vp8_sixtap_predict8x4_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    int FData[13*16];   /* Temp data buffer used in filtering */
+
+    HFilter = vp8_sub_pel_filters[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters[yoffset];   /* 6 tap */
+
+    /* First filter 1-D horizontally... */
+    filter_block2d_first_pass(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 1, 9, 8, HFilter);
+
+
+    /* then filter verticaly... */
+    filter_block2d_second_pass(FData + 16, dst_ptr, dst_pitch, 8, 8, 4, 8, VFilter);
+
+}
+
+void vp8_sixtap_predict16x16_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    int FData[21*24];   /* Temp data buffer used in filtering */
+
+
+    HFilter = vp8_sub_pel_filters[xoffset];   /* 6 tap */
+    VFilter = vp8_sub_pel_filters[yoffset];   /* 6 tap */
+
+    /* First filter 1-D horizontally... */
+    filter_block2d_first_pass(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 1, 21, 16, HFilter);
+
+    /* then filter verticaly... */
+    filter_block2d_second_pass(FData + 32, dst_ptr, dst_pitch, 16, 16, 16, 16, VFilter);
+
+}
+
+
+/****************************************************************************
+ *
+ *  ROUTINE       : filter_block2d_bil_first_pass
+ *
+ *  INPUTS        : UINT8  *src_ptr    : Pointer to source block.
+ *                  UINT32  src_stride : Stride of source block.
+ *                  UINT32  height     : Block height.
+ *                  UINT32  width      : Block width.
+ *                  INT32  *vp8_filter : Array of 2 bi-linear filter taps.
+ *
+ *  OUTPUTS       : INT32  *dst_ptr    : Pointer to filtered block.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Applies a 1-D 2-tap bi-linear filter to the source block
+ *                  in the horizontal direction to produce the filtered output
+ *                  block. Used to implement first-pass of 2-D separable filter.
+ *
+ *  SPECIAL NOTES : Produces INT32 output to retain precision for next pass.
+ *                  Two filter taps should sum to VP8_FILTER_WEIGHT.
+ *
+ ****************************************************************************/
+static void filter_block2d_bil_first_pass
+(
+    unsigned char  *src_ptr,
+    unsigned short *dst_ptr,
+    unsigned int    src_stride,
+    unsigned int    height,
+    unsigned int    width,
+    const short    *vp8_filter
+)
+{
+    unsigned int i, j;
+
+    for (i = 0; i < height; i++)
+    {
+        for (j = 0; j < width; j++)
+        {
+            /* Apply bilinear filter */
+            dst_ptr[j] = (((int)src_ptr[0] * vp8_filter[0]) +
+                          ((int)src_ptr[1] * vp8_filter[1]) +
+                          (VP8_FILTER_WEIGHT / 2)) >> VP8_FILTER_SHIFT;
+            src_ptr++;
+        }
+
+        /* Next row... */
+        src_ptr += src_stride - width;
+        dst_ptr += width;
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : filter_block2d_bil_second_pass
+ *
+ *  INPUTS        : INT32  *src_ptr    : Pointer to source block.
+ *                  UINT32  dst_pitch  : Destination block pitch.
+ *                  UINT32  height     : Block height.
+ *                  UINT32  width      : Block width.
+ *                  INT32  *vp8_filter : Array of 2 bi-linear filter taps.
+ *
+ *  OUTPUTS       : UINT16 *dst_ptr    : Pointer to filtered block.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Applies a 1-D 2-tap bi-linear filter to the source block
+ *                  in the vertical direction to produce the filtered output
+ *                  block. Used to implement second-pass of 2-D separable filter.
+ *
+ *  SPECIAL NOTES : Requires 32-bit input as produced by filter_block2d_bil_first_pass.
+ *                  Two filter taps should sum to VP8_FILTER_WEIGHT.
+ *
+ ****************************************************************************/
+static void filter_block2d_bil_second_pass
+(
+    unsigned short *src_ptr,
+    unsigned char  *dst_ptr,
+    int             dst_pitch,
+    unsigned int    height,
+    unsigned int    width,
+    const short    *vp8_filter
+)
+{
+    unsigned int  i, j;
+    int  Temp;
+
+    for (i = 0; i < height; i++)
+    {
+        for (j = 0; j < width; j++)
+        {
+            /* Apply filter */
+            Temp = ((int)src_ptr[0]     * vp8_filter[0]) +
+                   ((int)src_ptr[width] * vp8_filter[1]) +
+                   (VP8_FILTER_WEIGHT / 2);
+            dst_ptr[j] = (unsigned int)(Temp >> VP8_FILTER_SHIFT);
+            src_ptr++;
+        }
+
+        /* Next row... */
+        dst_ptr += dst_pitch;
+    }
+}
+
+
+/****************************************************************************
+ *
+ *  ROUTINE       : filter_block2d_bil
+ *
+ *  INPUTS        : UINT8  *src_ptr          : Pointer to source block.
+ *                  UINT32  src_pitch        : Stride of source block.
+ *                  UINT32  dst_pitch        : Stride of destination block.
+ *                  INT32  *HFilter          : Array of 2 horizontal filter taps.
+ *                  INT32  *VFilter          : Array of 2 vertical filter taps.
+ *                  INT32  Width             : Block width
+ *                  INT32  Height            : Block height
+ *
+ *  OUTPUTS       : UINT16 *dst_ptr       : Pointer to filtered block.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : 2-D filters an input block by applying a 2-tap
+ *                  bi-linear filter horizontally followed by a 2-tap
+ *                  bi-linear filter vertically on the result.
+ *
+ *  SPECIAL NOTES : The largest block size can be handled here is 16x16
+ *
+ ****************************************************************************/
+static void filter_block2d_bil
+(
+    unsigned char *src_ptr,
+    unsigned char *dst_ptr,
+    unsigned int   src_pitch,
+    unsigned int   dst_pitch,
+    const short   *HFilter,
+    const short   *VFilter,
+    int            Width,
+    int            Height
+)
+{
+
+    unsigned short FData[17*16];    /* Temp data buffer used in filtering */
+
+    /* First filter 1-D horizontally... */
+    filter_block2d_bil_first_pass(src_ptr, FData, src_pitch, Height + 1, Width, HFilter);
+
+    /* then 1-D vertically... */
+    filter_block2d_bil_second_pass(FData, dst_ptr, dst_pitch, Height, Width, VFilter);
+}
+
+
+void vp8_bilinear_predict4x4_c
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+    const short *HFilter;
+    const short *VFilter;
+
+    HFilter = vp8_bilinear_filters[xoffset];
+    VFilter = vp8_bilinear_filters[yoffset];
+#if 0
+    {
+        int i;
+        unsigned char temp1[16];
+        unsigned char temp2[16];
+
+        bilinear_predict4x4_mmx(src_ptr, src_pixels_per_line, xoffset, yoffset, temp1, 4);
+        filter_block2d_bil(src_ptr, temp2, src_pixels_per_line, 4, HFilter, VFilter, 4, 4);
+
+        for (i = 0; i < 16; i++)
+        {
+            if (temp1[i] != temp2[i])
+            {
+                bilinear_predict4x4_mmx(src_ptr, src_pixels_per_line, xoffset, yoffset, temp1, 4);
+                filter_block2d_bil(src_ptr, temp2, src_pixels_per_line, 4, HFilter, VFilter, 4, 4);
+            }
+        }
+    }
+#endif
+    filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 4, 4);
+
+}
+
+void vp8_bilinear_predict8x8_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short *HFilter;
+    const short *VFilter;
+
+    HFilter = vp8_bilinear_filters[xoffset];
+    VFilter = vp8_bilinear_filters[yoffset];
+
+    filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 8, 8);
+
+}
+
+void vp8_bilinear_predict8x4_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short *HFilter;
+    const short *VFilter;
+
+    HFilter = vp8_bilinear_filters[xoffset];
+    VFilter = vp8_bilinear_filters[yoffset];
+
+    filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 8, 4);
+
+}
+
+void vp8_bilinear_predict16x16_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short *HFilter;
+    const short *VFilter;
+
+    HFilter = vp8_bilinear_filters[xoffset];
+    VFilter = vp8_bilinear_filters[yoffset];
+
+    filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 16, 16);
+}
diff --git a/vp8/common/filter.h b/vp8/common/filter.h
new file mode 100644 (file)
index 0000000..0f225c2
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef FILTER_H
+#define FILTER_H
+
+#define BLOCK_HEIGHT_WIDTH 4
+#define VP8_FILTER_WEIGHT 128
+#define VP8_FILTER_SHIFT  7
+
+extern const short vp8_bilinear_filters[8][2];
+extern const short vp8_sub_pel_filters[8][6];
+
+#endif //FILTER_H
diff --git a/vp8/common/findnearmv.c b/vp8/common/findnearmv.c
new file mode 100644 (file)
index 0000000..e8ee40f
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "findnearmv.h"
+
+const unsigned char vp8_mbsplit_offset[4][16] = {
+    { 0,  8,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0},
+    { 0,  2,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0},
+    { 0,  2,  8, 10,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0},
+    { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15}
+};
+
+/* Predict motion vectors using those from already-decoded nearby blocks.
+   Note that we only consider one 4x4 subblock from each candidate 16x16
+   macroblock.   */
+void vp8_find_near_mvs
+(
+    MACROBLOCKD *xd,
+    const MODE_INFO *here,
+    int_mv *nearest,
+    int_mv *nearby,
+    int_mv *best_mv,
+    int cnt[4],
+    int refframe,
+    int *ref_frame_sign_bias
+)
+{
+    const MODE_INFO *above = here - xd->mode_info_stride;
+    const MODE_INFO *left = here - 1;
+    const MODE_INFO *aboveleft = above - 1;
+    int_mv            near_mvs[4];
+    int_mv           *mv = near_mvs;
+    int             *cntx = cnt;
+    enum {CNT_INTRA, CNT_NEAREST, CNT_NEAR, CNT_SPLITMV};
+
+    /* Zero accumulators */
+    mv[0].as_int = mv[1].as_int = mv[2].as_int = 0;
+    cnt[0] = cnt[1] = cnt[2] = cnt[3] = 0;
+
+    /* Process above */
+    if (above->mbmi.ref_frame != INTRA_FRAME)
+    {
+        if (above->mbmi.mv.as_int)
+        {
+            (++mv)->as_int = above->mbmi.mv.as_int;
+            mv_bias(ref_frame_sign_bias[above->mbmi.ref_frame], refframe, mv, ref_frame_sign_bias);
+            ++cntx;
+        }
+
+        *cntx += 2;
+    }
+
+    /* Process left */
+    if (left->mbmi.ref_frame != INTRA_FRAME)
+    {
+        if (left->mbmi.mv.as_int)
+        {
+            int_mv this_mv;
+
+            this_mv.as_int = left->mbmi.mv.as_int;
+            mv_bias(ref_frame_sign_bias[left->mbmi.ref_frame], refframe, &this_mv, ref_frame_sign_bias);
+
+            if (this_mv.as_int != mv->as_int)
+            {
+                (++mv)->as_int = this_mv.as_int;
+                ++cntx;
+            }
+
+            *cntx += 2;
+        }
+        else
+            cnt[CNT_INTRA] += 2;
+    }
+
+    /* Process above left */
+    if (aboveleft->mbmi.ref_frame != INTRA_FRAME)
+    {
+        if (aboveleft->mbmi.mv.as_int)
+        {
+            int_mv this_mv;
+
+            this_mv.as_int = aboveleft->mbmi.mv.as_int;
+            mv_bias(ref_frame_sign_bias[aboveleft->mbmi.ref_frame], refframe, &this_mv, ref_frame_sign_bias);
+
+            if (this_mv.as_int != mv->as_int)
+            {
+                (++mv)->as_int = this_mv.as_int;
+                ++cntx;
+            }
+
+            *cntx += 1;
+        }
+        else
+            cnt[CNT_INTRA] += 1;
+    }
+
+    /* If we have three distinct MV's ... */
+    if (cnt[CNT_SPLITMV])
+    {
+        /* See if above-left MV can be merged with NEAREST */
+        if (mv->as_int == near_mvs[CNT_NEAREST].as_int)
+            cnt[CNT_NEAREST] += 1;
+    }
+
+    cnt[CNT_SPLITMV] = ((above->mbmi.mode == SPLITMV)
+                        + (left->mbmi.mode == SPLITMV)) * 2
+                       + (aboveleft->mbmi.mode == SPLITMV);
+
+    /* Swap near and nearest if necessary */
+    if (cnt[CNT_NEAR] > cnt[CNT_NEAREST])
+    {
+        int tmp;
+        tmp = cnt[CNT_NEAREST];
+        cnt[CNT_NEAREST] = cnt[CNT_NEAR];
+        cnt[CNT_NEAR] = tmp;
+        tmp = near_mvs[CNT_NEAREST].as_int;
+        near_mvs[CNT_NEAREST].as_int = near_mvs[CNT_NEAR].as_int;
+        near_mvs[CNT_NEAR].as_int = tmp;
+    }
+
+    /* Use near_mvs[0] to store the "best" MV */
+    if (cnt[CNT_NEAREST] >= cnt[CNT_INTRA])
+        near_mvs[CNT_INTRA] = near_mvs[CNT_NEAREST];
+
+    /* Set up return values */
+    best_mv->as_int = near_mvs[0].as_int;
+    nearest->as_int = near_mvs[CNT_NEAREST].as_int;
+    nearby->as_int = near_mvs[CNT_NEAR].as_int;
+}
+
+
+static void invert_and_clamp_mvs(int_mv *inv, int_mv *src, MACROBLOCKD *xd)
+{
+    inv->as_mv.row = src->as_mv.row * -1;
+    inv->as_mv.col = src->as_mv.col * -1;
+    vp8_clamp_mv2(inv, xd);
+    vp8_clamp_mv2(src, xd);
+}
+
+
+int vp8_find_near_mvs_bias
+(
+    MACROBLOCKD *xd,
+    const MODE_INFO *here,
+    int_mv mode_mv_sb[2][MB_MODE_COUNT],
+    int_mv best_mv_sb[2],
+    int cnt[4],
+    int refframe,
+    int *ref_frame_sign_bias
+)
+{
+    int sign_bias = ref_frame_sign_bias[refframe];
+
+    vp8_find_near_mvs(xd,
+                      here,
+                      &mode_mv_sb[sign_bias][NEARESTMV],
+                      &mode_mv_sb[sign_bias][NEARMV],
+                      &best_mv_sb[sign_bias],
+                      cnt,
+                      refframe,
+                      ref_frame_sign_bias);
+
+    invert_and_clamp_mvs(&mode_mv_sb[!sign_bias][NEARESTMV],
+                         &mode_mv_sb[sign_bias][NEARESTMV], xd);
+    invert_and_clamp_mvs(&mode_mv_sb[!sign_bias][NEARMV],
+                         &mode_mv_sb[sign_bias][NEARMV], xd);
+    invert_and_clamp_mvs(&best_mv_sb[!sign_bias],
+                         &best_mv_sb[sign_bias], xd);
+
+    return sign_bias;
+}
+
+
+vp8_prob *vp8_mv_ref_probs(
+    vp8_prob p[VP8_MVREFS-1], const int near_mv_ref_ct[4]
+)
+{
+    p[0] = vp8_mode_contexts [near_mv_ref_ct[0]] [0];
+    p[1] = vp8_mode_contexts [near_mv_ref_ct[1]] [1];
+    p[2] = vp8_mode_contexts [near_mv_ref_ct[2]] [2];
+    p[3] = vp8_mode_contexts [near_mv_ref_ct[3]] [3];
+    /*p[3] = vp8_mode_contexts [near_mv_ref_ct[1] + near_mv_ref_ct[2] + near_mv_ref_ct[3]] [3];*/
+    return p;
+}
+
diff --git a/vp8/common/findnearmv.h b/vp8/common/findnearmv.h
new file mode 100644 (file)
index 0000000..06ef060
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_FINDNEARMV_H
+#define __INC_FINDNEARMV_H
+
+#include "mv.h"
+#include "blockd.h"
+#include "modecont.h"
+#include "treecoder.h"
+
+
+static void mv_bias(int refmb_ref_frame_sign_bias, int refframe, int_mv *mvp,
+                    const int *ref_frame_sign_bias)
+{
+    if (refmb_ref_frame_sign_bias != ref_frame_sign_bias[refframe])
+    {
+        mvp->as_mv.row *= -1;
+        mvp->as_mv.col *= -1;
+    }
+}
+
+#define LEFT_TOP_MARGIN (16 << 3)
+#define RIGHT_BOTTOM_MARGIN (16 << 3)
+static void vp8_clamp_mv2(int_mv *mv, const MACROBLOCKD *xd)
+{
+    if (mv->as_mv.col < (xd->mb_to_left_edge - LEFT_TOP_MARGIN))
+        mv->as_mv.col = xd->mb_to_left_edge - LEFT_TOP_MARGIN;
+    else if (mv->as_mv.col > xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN)
+        mv->as_mv.col = xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN;
+
+    if (mv->as_mv.row < (xd->mb_to_top_edge - LEFT_TOP_MARGIN))
+        mv->as_mv.row = xd->mb_to_top_edge - LEFT_TOP_MARGIN;
+    else if (mv->as_mv.row > xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN)
+        mv->as_mv.row = xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN;
+}
+
+static void vp8_clamp_mv(int_mv *mv, int mb_to_left_edge, int mb_to_right_edge,
+                         int mb_to_top_edge, int mb_to_bottom_edge)
+{
+    mv->as_mv.col = (mv->as_mv.col < mb_to_left_edge) ?
+        mb_to_left_edge : mv->as_mv.col;
+    mv->as_mv.col = (mv->as_mv.col > mb_to_right_edge) ?
+        mb_to_right_edge : mv->as_mv.col;
+    mv->as_mv.row = (mv->as_mv.row < mb_to_top_edge) ?
+        mb_to_top_edge : mv->as_mv.row;
+    mv->as_mv.row = (mv->as_mv.row > mb_to_bottom_edge) ?
+        mb_to_bottom_edge : mv->as_mv.row;
+}
+static unsigned int vp8_check_mv_bounds(int_mv *mv, int mb_to_left_edge,
+                                int mb_to_right_edge, int mb_to_top_edge,
+                                int mb_to_bottom_edge)
+{
+    unsigned int need_to_clamp;
+    need_to_clamp = (mv->as_mv.col < mb_to_left_edge);
+    need_to_clamp |= (mv->as_mv.col > mb_to_right_edge);
+    need_to_clamp |= (mv->as_mv.row < mb_to_top_edge);
+    need_to_clamp |= (mv->as_mv.row > mb_to_bottom_edge);
+    return need_to_clamp;
+}
+
+void vp8_find_near_mvs
+(
+    MACROBLOCKD *xd,
+    const MODE_INFO *here,
+    int_mv *nearest, int_mv *nearby, int_mv *best,
+    int near_mv_ref_cts[4],
+    int refframe,
+    int *ref_frame_sign_bias
+);
+
+
+int vp8_find_near_mvs_bias
+(
+    MACROBLOCKD *xd,
+    const MODE_INFO *here,
+    int_mv mode_mv_sb[2][MB_MODE_COUNT],
+    int_mv best_mv_sb[2],
+    int cnt[4],
+    int refframe,
+    int *ref_frame_sign_bias
+);
+
+
+vp8_prob *vp8_mv_ref_probs(
+    vp8_prob p[VP8_MVREFS-1], const int near_mv_ref_ct[4]
+);
+
+extern const unsigned char vp8_mbsplit_offset[4][16];
+
+
+static int left_block_mv(const MODE_INFO *cur_mb, int b)
+{
+    if (!(b & 3))
+    {
+        /* On L edge, get from MB to left of us */
+        --cur_mb;
+
+        if(cur_mb->mbmi.mode != SPLITMV)
+            return cur_mb->mbmi.mv.as_int;
+        b += 4;
+    }
+
+    return (cur_mb->bmi + b - 1)->mv.as_int;
+}
+
+static int above_block_mv(const MODE_INFO *cur_mb, int b, int mi_stride)
+{
+    if (!(b >> 2))
+    {
+        /* On top edge, get from MB above us */
+        cur_mb -= mi_stride;
+
+        if(cur_mb->mbmi.mode != SPLITMV)
+            return cur_mb->mbmi.mv.as_int;
+        b += 16;
+    }
+
+    return (cur_mb->bmi + b - 4)->mv.as_int;
+}
+static B_PREDICTION_MODE left_block_mode(const MODE_INFO *cur_mb, int b)
+{
+    if (!(b & 3))
+    {
+        /* On L edge, get from MB to left of us */
+        --cur_mb;
+        switch (cur_mb->mbmi.mode)
+        {
+            case B_PRED:
+              return (cur_mb->bmi + b + 3)->as_mode;
+            case DC_PRED:
+                return B_DC_PRED;
+            case V_PRED:
+                return B_VE_PRED;
+            case H_PRED:
+                return B_HE_PRED;
+            case TM_PRED:
+                return B_TM_PRED;
+            default:
+                return B_DC_PRED;
+        }
+    }
+
+    return (cur_mb->bmi + b - 1)->as_mode;
+}
+
+static B_PREDICTION_MODE above_block_mode(const MODE_INFO *cur_mb, int b, int mi_stride)
+{
+    if (!(b >> 2))
+    {
+        /* On top edge, get from MB above us */
+        cur_mb -= mi_stride;
+
+        switch (cur_mb->mbmi.mode)
+        {
+            case B_PRED:
+              return (cur_mb->bmi + b + 12)->as_mode;
+            case DC_PRED:
+                return B_DC_PRED;
+            case V_PRED:
+                return B_VE_PRED;
+            case H_PRED:
+                return B_HE_PRED;
+            case TM_PRED:
+                return B_TM_PRED;
+            default:
+                return B_DC_PRED;
+        }
+    }
+
+    return (cur_mb->bmi + b - 4)->as_mode;
+}
+
+#endif
diff --git a/vp8/common/generic/systemdependent.c b/vp8/common/generic/systemdependent.c
new file mode 100644 (file)
index 0000000..2a30166
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#if ARCH_ARM
+#include "vpx_ports/arm.h"
+#elif ARCH_X86 || ARCH_X86_64
+#include "vpx_ports/x86.h"
+#endif
+#include "vp8/common/onyxc_int.h"
+
+#if CONFIG_MULTITHREAD
+#if HAVE_UNISTD_H && !defined(__OS2__)
+#include <unistd.h>
+#elif defined(_WIN32)
+#include <windows.h>
+typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
+#elif defined(__OS2__)
+#define INCL_DOS
+#define INCL_DOSSPINLOCK
+#include <os2.h>
+#endif
+#endif
+
+#if CONFIG_MULTITHREAD
+static int get_cpu_count()
+{
+    int core_count = 16;
+
+#if HAVE_UNISTD_H && !defined(__OS2__)
+#if defined(_SC_NPROCESSORS_ONLN)
+    core_count = sysconf(_SC_NPROCESSORS_ONLN);
+#elif defined(_SC_NPROC_ONLN)
+    core_count = sysconf(_SC_NPROC_ONLN);
+#endif
+#elif defined(_WIN32)
+    {
+        PGNSI pGNSI;
+        SYSTEM_INFO sysinfo;
+
+        /* Call GetNativeSystemInfo if supported or
+         * GetSystemInfo otherwise. */
+
+        pGNSI = (PGNSI) GetProcAddress(
+                GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo");
+        if (pGNSI != NULL)
+            pGNSI(&sysinfo);
+        else
+            GetSystemInfo(&sysinfo);
+
+        core_count = sysinfo.dwNumberOfProcessors;
+    }
+#elif defined(__OS2__)
+    {
+        ULONG proc_id;
+        ULONG status;
+
+        core_count = 0;
+        for (proc_id = 1; ; proc_id++)
+        {
+            if (DosGetProcessorStatus(proc_id, &status))
+                break;
+
+            if (status == PROC_ONLINE)
+                core_count++;
+        }
+    }
+#else
+    /* other platforms */
+#endif
+
+    return core_count > 0 ? core_count : 1;
+}
+#endif
+
+
+#if HAVE_PTHREAD_H
+#include <pthread.h>
+static void once(void (*func)(void))
+{
+    static pthread_once_t lock = PTHREAD_ONCE_INIT;
+    pthread_once(&lock, func);
+}
+
+
+#elif defined(_WIN32)
+static void once(void (*func)(void))
+{
+    /* Using a static initializer here rather than InitializeCriticalSection()
+     * since there's no race-free context in which to execute it. Protecting
+     * it with an atomic op like InterlockedCompareExchangePointer introduces
+     * an x86 dependency, and InitOnceExecuteOnce requires Vista.
+     */
+    static CRITICAL_SECTION lock = {(void *)-1, -1, 0, 0, 0, 0};
+    static int done;
+
+    EnterCriticalSection(&lock);
+
+    if (!done)
+    {
+        func();
+        done = 1;
+    }
+
+    LeaveCriticalSection(&lock);
+}
+
+
+#else
+/* No-op version that performs no synchronization. vpx_rtcd() is idempotent,
+ * so as long as your platform provides atomic loads/stores of pointers
+ * no synchronization is strictly necessary.
+ */
+
+static void once(void (*func)(void))
+{
+    static int done;
+
+    if(!done)
+    {
+        func();
+        done = 1;
+    }
+}
+#endif
+
+
+void vp8_machine_specific_config(VP8_COMMON *ctx)
+{
+#if CONFIG_MULTITHREAD
+    ctx->processor_core_count = get_cpu_count();
+#endif /* CONFIG_MULTITHREAD */
+
+#if ARCH_ARM
+    ctx->cpu_caps = arm_cpu_caps();
+#elif ARCH_X86 || ARCH_X86_64
+    ctx->cpu_caps = x86_simd_caps();
+#endif
+
+    once(vpx_rtcd);
+}
diff --git a/vp8/common/header.h b/vp8/common/header.h
new file mode 100644 (file)
index 0000000..3e98eeb
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_HEADER_H
+#define __INC_HEADER_H
+
+/* 24 bits total */
+typedef struct
+{
+    unsigned int type: 1;
+    unsigned int version: 3;
+    unsigned int show_frame: 1;
+
+    /* Allow 2^20 bytes = 8 megabits for first partition */
+
+    unsigned int first_partition_length_in_bytes: 19;
+
+#ifdef PACKET_TESTING
+    unsigned int frame_number;
+    unsigned int update_gold: 1;
+    unsigned int uses_gold: 1;
+    unsigned int update_last: 1;
+    unsigned int uses_last: 1;
+#endif
+
+} VP8_HEADER;
+
+#ifdef PACKET_TESTING
+#define VP8_HEADER_SIZE 8
+#else
+#define VP8_HEADER_SIZE 3
+#endif
+
+
+#endif
diff --git a/vp8/common/idct_blk.c b/vp8/common/idct_blk.c
new file mode 100644 (file)
index 0000000..0b058c7
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+
+void vp8_dequant_idct_add_c(short *input, short *dq,
+                            unsigned char *dest, int stride);
+void vp8_dc_only_idct_add_c(short input_dc, unsigned char * pred,
+                            int pred_stride, unsigned char *dst_ptr,
+                            int dst_stride);
+
+void vp8_dequant_idct_add_y_block_c
+            (short *q, short *dq,
+             unsigned char *dst, int stride, char *eobs)
+{
+    int i, j;
+
+    for (i = 0; i < 4; i++)
+    {
+        for (j = 0; j < 4; j++)
+        {
+            if (*eobs++ > 1)
+                vp8_dequant_idct_add_c (q, dq, dst, stride);
+            else
+            {
+                vp8_dc_only_idct_add_c (q[0]*dq[0], dst, stride, dst, stride);
+                ((int *)q)[0] = 0;
+            }
+
+            q   += 16;
+            dst += 4;
+        }
+
+        dst += 4*stride - 16;
+    }
+}
+
+void vp8_dequant_idct_add_uv_block_c
+            (short *q, short *dq,
+             unsigned char *dstu, unsigned char *dstv, int stride, char *eobs)
+{
+    int i, j;
+
+    for (i = 0; i < 2; i++)
+    {
+        for (j = 0; j < 2; j++)
+        {
+            if (*eobs++ > 1)
+                vp8_dequant_idct_add_c (q, dq, dstu, stride);
+            else
+            {
+                vp8_dc_only_idct_add_c (q[0]*dq[0], dstu, stride, dstu, stride);
+                ((int *)q)[0] = 0;
+            }
+
+            q    += 16;
+            dstu += 4;
+        }
+
+        dstu += 4*stride - 8;
+    }
+
+    for (i = 0; i < 2; i++)
+    {
+        for (j = 0; j < 2; j++)
+        {
+            if (*eobs++ > 1)
+                vp8_dequant_idct_add_c (q, dq, dstv, stride);
+            else
+            {
+                vp8_dc_only_idct_add_c (q[0]*dq[0], dstv, stride, dstv, stride);
+                ((int *)q)[0] = 0;
+            }
+
+            q    += 16;
+            dstv += 4;
+        }
+
+        dstv += 4*stride - 8;
+    }
+}
diff --git a/vp8/common/idctllm.c b/vp8/common/idctllm.c
new file mode 100644 (file)
index 0000000..47af52f
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/****************************************************************************
+ * Notes:
+ *
+ * This implementation makes use of 16 bit fixed point verio of two multiply
+ * constants:
+ *         1.   sqrt(2) * cos (pi/8)
+ *         2.   sqrt(2) * sin (pi/8)
+ * Becuase the first constant is bigger than 1, to maintain the same 16 bit
+ * fixed point precision as the second one, we use a trick of
+ *         x * a = x + x*(a-1)
+ * so
+ *         x * sqrt(2) * cos (pi/8) = x + x * (sqrt(2) *cos(pi/8)-1).
+ **************************************************************************/
+static const int cospi8sqrt2minus1 = 20091;
+static const int sinpi8sqrt2      = 35468;
+
+void vp8_short_idct4x4llm_c(short *input, unsigned char *pred_ptr,
+                            int pred_stride, unsigned char *dst_ptr,
+                            int dst_stride)
+{
+    int i;
+    int r, c;
+    int a1, b1, c1, d1;
+    short output[16];
+    short *ip = input;
+    short *op = output;
+    int temp1, temp2;
+    int shortpitch = 4;
+
+    for (i = 0; i < 4; i++)
+    {
+        a1 = ip[0] + ip[8];
+        b1 = ip[0] - ip[8];
+
+        temp1 = (ip[4] * sinpi8sqrt2) >> 16;
+        temp2 = ip[12] + ((ip[12] * cospi8sqrt2minus1) >> 16);
+        c1 = temp1 - temp2;
+
+        temp1 = ip[4] + ((ip[4] * cospi8sqrt2minus1) >> 16);
+        temp2 = (ip[12] * sinpi8sqrt2) >> 16;
+        d1 = temp1 + temp2;
+
+        op[shortpitch*0] = a1 + d1;
+        op[shortpitch*3] = a1 - d1;
+
+        op[shortpitch*1] = b1 + c1;
+        op[shortpitch*2] = b1 - c1;
+
+        ip++;
+        op++;
+    }
+
+    ip = output;
+    op = output;
+
+    for (i = 0; i < 4; i++)
+    {
+        a1 = ip[0] + ip[2];
+        b1 = ip[0] - ip[2];
+
+        temp1 = (ip[1] * sinpi8sqrt2) >> 16;
+        temp2 = ip[3] + ((ip[3] * cospi8sqrt2minus1) >> 16);
+        c1 = temp1 - temp2;
+
+        temp1 = ip[1] + ((ip[1] * cospi8sqrt2minus1) >> 16);
+        temp2 = (ip[3] * sinpi8sqrt2) >> 16;
+        d1 = temp1 + temp2;
+
+
+        op[0] = (a1 + d1 + 4) >> 3;
+        op[3] = (a1 - d1 + 4) >> 3;
+
+        op[1] = (b1 + c1 + 4) >> 3;
+        op[2] = (b1 - c1 + 4) >> 3;
+
+        ip += shortpitch;
+        op += shortpitch;
+    }
+
+    ip = output;
+    for (r = 0; r < 4; r++)
+    {
+        for (c = 0; c < 4; c++)
+        {
+            int a = ip[c] + pred_ptr[c] ;
+
+            if (a < 0)
+                a = 0;
+
+            if (a > 255)
+                a = 255;
+
+            dst_ptr[c] = (unsigned char) a ;
+        }
+        ip += 4;
+        dst_ptr += dst_stride;
+        pred_ptr += pred_stride;
+    }
+}
+
+void vp8_dc_only_idct_add_c(short input_dc, unsigned char *pred_ptr,
+                            int pred_stride, unsigned char *dst_ptr,
+                            int dst_stride)
+{
+    int a1 = ((input_dc + 4) >> 3);
+    int r, c;
+
+    for (r = 0; r < 4; r++)
+    {
+        for (c = 0; c < 4; c++)
+        {
+            int a = a1 + pred_ptr[c] ;
+
+            if (a < 0)
+                a = 0;
+
+            if (a > 255)
+                a = 255;
+
+            dst_ptr[c] = (unsigned char) a ;
+        }
+
+        dst_ptr += dst_stride;
+        pred_ptr += pred_stride;
+    }
+
+}
+
+void vp8_short_inv_walsh4x4_c(short *input, short *mb_dqcoeff)
+{
+    short output[16];
+    int i;
+    int a1, b1, c1, d1;
+    int a2, b2, c2, d2;
+    short *ip = input;
+    short *op = output;
+
+    for (i = 0; i < 4; i++)
+    {
+        a1 = ip[0] + ip[12];
+        b1 = ip[4] + ip[8];
+        c1 = ip[4] - ip[8];
+        d1 = ip[0] - ip[12];
+
+        op[0] = a1 + b1;
+        op[4] = c1 + d1;
+        op[8] = a1 - b1;
+        op[12] = d1 - c1;
+        ip++;
+        op++;
+    }
+
+    ip = output;
+    op = output;
+
+    for (i = 0; i < 4; i++)
+    {
+        a1 = ip[0] + ip[3];
+        b1 = ip[1] + ip[2];
+        c1 = ip[1] - ip[2];
+        d1 = ip[0] - ip[3];
+
+        a2 = a1 + b1;
+        b2 = c1 + d1;
+        c2 = a1 - b1;
+        d2 = d1 - c1;
+
+        op[0] = (a2 + 3) >> 3;
+        op[1] = (b2 + 3) >> 3;
+        op[2] = (c2 + 3) >> 3;
+        op[3] = (d2 + 3) >> 3;
+
+        ip += 4;
+        op += 4;
+    }
+
+    for(i = 0; i < 16; i++)
+    {
+        mb_dqcoeff[i * 16] = output[i];
+    }
+}
+
+void vp8_short_inv_walsh4x4_1_c(short *input, short *mb_dqcoeff)
+{
+    int i;
+    int a1;
+
+    a1 = ((input[0] + 3) >> 3);
+    for(i = 0; i < 16; i++)
+    {
+        mb_dqcoeff[i * 16] = a1;
+    }
+}
diff --git a/vp8/common/idctllm_test.cc b/vp8/common/idctllm_test.cc
new file mode 100755 (executable)
index 0000000..0f6ebe7
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+ extern "C" {
+    void vp8_short_idct4x4llm_c(short *input, unsigned char *pred_ptr,
+                            int pred_stride, unsigned char *dst_ptr,
+                            int dst_stride);
+}
+
+#include "vpx_config.h"
+#include "idctllm_test.h"
+namespace
+{
+
+INSTANTIATE_TEST_CASE_P(C, IDCTTest,
+                        ::testing::Values(vp8_short_idct4x4llm_c));
+
+} // namespace
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/vp8/common/idctllm_test.h b/vp8/common/idctllm_test.h
new file mode 100755 (executable)
index 0000000..a6a694b
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+ #include "third_party/googletest/src/include/gtest/gtest.h"
+typedef void (*idct_fn_t)(short *input, unsigned char *pred_ptr,
+                            int pred_stride, unsigned char *dst_ptr,
+                            int dst_stride);
+namespace {
+class IDCTTest : public ::testing::TestWithParam<idct_fn_t>
+{
+  protected:
+    virtual void SetUp()
+    {
+        int i;
+
+        UUT = GetParam();
+        memset(input, 0, sizeof(input));
+        /* Set up guard blocks */
+        for(i=0; i<256; i++)
+            output[i] = ((i&0xF)<4&&(i<64))?0:-1;
+    }
+
+    idct_fn_t UUT;
+    short input[16];
+    unsigned char output[256];
+    unsigned char predict[256];
+};
+
+TEST_P(IDCTTest, TestGuardBlocks)
+{
+    int i;
+
+    for(i=0; i<256; i++)
+        if((i&0xF) < 4 && i<64)
+            EXPECT_EQ(0, output[i]) << i;
+        else
+            EXPECT_EQ(255, output[i]);
+}
+
+TEST_P(IDCTTest, TestAllZeros)
+{
+    int i;
+
+    UUT(input, output, 16, output, 16);
+
+    for(i=0; i<256; i++)
+        if((i&0xF) < 4 && i<64)
+            EXPECT_EQ(0, output[i]) << "i==" << i;
+        else
+            EXPECT_EQ(255, output[i]) << "i==" << i;
+}
+
+TEST_P(IDCTTest, TestAllOnes)
+{
+    int i;
+
+    input[0] = 4;
+    UUT(input, output, 16, output, 16);
+
+    for(i=0; i<256; i++)
+        if((i&0xF) < 4 && i<64)
+            EXPECT_EQ(1, output[i]) << "i==" << i;
+        else
+            EXPECT_EQ(255, output[i]) << "i==" << i;
+}
+
+TEST_P(IDCTTest, TestAddOne)
+{
+    int i;
+
+    for(i=0; i<256; i++)
+        predict[i] = i;
+
+    input[0] = 4;
+    UUT(input, predict, 16, output, 16);
+
+    for(i=0; i<256; i++)
+        if((i&0xF) < 4 && i<64)
+            EXPECT_EQ(i+1, output[i]) << "i==" << i;
+        else
+            EXPECT_EQ(255, output[i]) << "i==" << i;
+}
+
+TEST_P(IDCTTest, TestWithData)
+{
+    int i;
+
+    for(i=0; i<16; i++)
+        input[i] = i;
+
+    UUT(input, output, 16, output, 16);
+
+    for(i=0; i<256; i++)
+        if((i&0xF) > 3 || i>63)
+            EXPECT_EQ(255, output[i]) << "i==" << i;
+        else if(i == 0)
+            EXPECT_EQ(11, output[i]) << "i==" << i;
+        else if(i == 34)
+            EXPECT_EQ(1, output[i]) << "i==" << i;
+        else if(i == 2 || i == 17 || i == 32)
+            EXPECT_EQ(3, output[i]) << "i==" << i;
+        else
+            EXPECT_EQ(0, output[i]) << "i==" << i;
+}
+}
diff --git a/vp8/common/invtrans.h b/vp8/common/invtrans.h
new file mode 100644 (file)
index 0000000..d048665
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_INVTRANS_H
+#define __INC_INVTRANS_H
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "blockd.h"
+#include "onyxc_int.h"
+
+#if CONFIG_MULTITHREAD
+#include "vpx_mem/vpx_mem.h"
+#endif
+
+static void eob_adjust(char *eobs, short *diff)
+{
+    /* eob adjust.... the idct can only skip if both the dc and eob are zero */
+    int js;
+    for(js = 0; js < 16; js++)
+    {
+        if((eobs[js] == 0) && (diff[0] != 0))
+            eobs[js]++;
+        diff+=16;
+    }
+}
+
+static void vp8_inverse_transform_mby(MACROBLOCKD *xd)
+{
+    short *DQC = xd->dequant_y1;
+
+    if (xd->mode_info_context->mbmi.mode != SPLITMV)
+    {
+        /* do 2nd order transform on the dc block */
+        if (xd->eobs[24] > 1)
+        {
+            vp8_short_inv_walsh4x4
+                (&xd->block[24].dqcoeff[0], xd->qcoeff);
+        }
+        else
+        {
+            vp8_short_inv_walsh4x4_1
+                (&xd->block[24].dqcoeff[0], xd->qcoeff);
+        }
+        eob_adjust(xd->eobs, xd->qcoeff);
+
+        DQC = xd->dequant_y1_dc;
+    }
+    vp8_dequant_idct_add_y_block
+                    (xd->qcoeff, DQC,
+                     xd->dst.y_buffer,
+                     xd->dst.y_stride, xd->eobs);
+}
+#endif
diff --git a/vp8/common/loopfilter.c b/vp8/common/loopfilter.c
new file mode 100644 (file)
index 0000000..3f05efe
--- /dev/null
@@ -0,0 +1,575 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "loopfilter.h"
+#include "onyxc_int.h"
+#include "vpx_mem/vpx_mem.h"
+
+typedef unsigned char uc;
+
+static void lf_init_lut(loop_filter_info_n *lfi)
+{
+    int filt_lvl;
+
+    for (filt_lvl = 0; filt_lvl <= MAX_LOOP_FILTER; filt_lvl++)
+    {
+        if (filt_lvl >= 40)
+        {
+            lfi->hev_thr_lut[KEY_FRAME][filt_lvl] = 2;
+            lfi->hev_thr_lut[INTER_FRAME][filt_lvl] = 3;
+        }
+        else if (filt_lvl >= 20)
+        {
+            lfi->hev_thr_lut[KEY_FRAME][filt_lvl] = 1;
+            lfi->hev_thr_lut[INTER_FRAME][filt_lvl] = 2;
+        }
+        else if (filt_lvl >= 15)
+        {
+            lfi->hev_thr_lut[KEY_FRAME][filt_lvl] = 1;
+            lfi->hev_thr_lut[INTER_FRAME][filt_lvl] = 1;
+        }
+        else
+        {
+            lfi->hev_thr_lut[KEY_FRAME][filt_lvl] = 0;
+            lfi->hev_thr_lut[INTER_FRAME][filt_lvl] = 0;
+        }
+    }
+
+    lfi->mode_lf_lut[DC_PRED] = 1;
+    lfi->mode_lf_lut[V_PRED] = 1;
+    lfi->mode_lf_lut[H_PRED] = 1;
+    lfi->mode_lf_lut[TM_PRED] = 1;
+    lfi->mode_lf_lut[B_PRED]  = 0;
+
+    lfi->mode_lf_lut[ZEROMV]  = 1;
+    lfi->mode_lf_lut[NEARESTMV] = 2;
+    lfi->mode_lf_lut[NEARMV] = 2;
+    lfi->mode_lf_lut[NEWMV] = 2;
+    lfi->mode_lf_lut[SPLITMV] = 3;
+
+}
+
+void vp8_loop_filter_update_sharpness(loop_filter_info_n *lfi,
+                                      int sharpness_lvl)
+{
+    int i;
+
+    /* For each possible value for the loop filter fill out limits */
+    for (i = 0; i <= MAX_LOOP_FILTER; i++)
+    {
+        int filt_lvl = i;
+        int block_inside_limit = 0;
+
+        /* Set loop filter paramaeters that control sharpness. */
+        block_inside_limit = filt_lvl >> (sharpness_lvl > 0);
+        block_inside_limit = block_inside_limit >> (sharpness_lvl > 4);
+
+        if (sharpness_lvl > 0)
+        {
+            if (block_inside_limit > (9 - sharpness_lvl))
+                block_inside_limit = (9 - sharpness_lvl);
+        }
+
+        if (block_inside_limit < 1)
+            block_inside_limit = 1;
+
+        vpx_memset(lfi->lim[i], block_inside_limit, SIMD_WIDTH);
+        vpx_memset(lfi->blim[i], (2 * filt_lvl + block_inside_limit),
+                SIMD_WIDTH);
+        vpx_memset(lfi->mblim[i], (2 * (filt_lvl + 2) + block_inside_limit),
+                SIMD_WIDTH);
+    }
+}
+
+void vp8_loop_filter_init(VP8_COMMON *cm)
+{
+    loop_filter_info_n *lfi = &cm->lf_info;
+    int i;
+
+    /* init limits for given sharpness*/
+    vp8_loop_filter_update_sharpness(lfi, cm->sharpness_level);
+    cm->last_sharpness_level = cm->sharpness_level;
+
+    /* init LUT for lvl  and hev thr picking */
+    lf_init_lut(lfi);
+
+    /* init hev threshold const vectors */
+    for(i = 0; i < 4 ; i++)
+    {
+        vpx_memset(lfi->hev_thr[i], i, SIMD_WIDTH);
+    }
+}
+
+void vp8_loop_filter_frame_init(VP8_COMMON *cm,
+                                MACROBLOCKD *mbd,
+                                int default_filt_lvl)
+{
+    int seg,  /* segment number */
+        ref,  /* index in ref_lf_deltas */
+        mode; /* index in mode_lf_deltas */
+
+    loop_filter_info_n *lfi = &cm->lf_info;
+
+    /* update limits if sharpness has changed */
+    if(cm->last_sharpness_level != cm->sharpness_level)
+    {
+        vp8_loop_filter_update_sharpness(lfi, cm->sharpness_level);
+        cm->last_sharpness_level = cm->sharpness_level;
+    }
+
+    for(seg = 0; seg < MAX_MB_SEGMENTS; seg++)
+    {
+        int lvl_seg = default_filt_lvl;
+        int lvl_ref, lvl_mode;
+
+        /* Note the baseline filter values for each segment */
+        if (mbd->segmentation_enabled)
+        {
+            /* Abs value */
+            if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA)
+            {
+                lvl_seg = mbd->segment_feature_data[MB_LVL_ALT_LF][seg];
+            }
+            else  /* Delta Value */
+            {
+                lvl_seg += mbd->segment_feature_data[MB_LVL_ALT_LF][seg];
+                lvl_seg = (lvl_seg > 0) ? ((lvl_seg > 63) ? 63: lvl_seg) : 0;
+            }
+        }
+
+        if (!mbd->mode_ref_lf_delta_enabled)
+        {
+            /* we could get rid of this if we assume that deltas are set to
+             * zero when not in use; encoder always uses deltas
+             */
+            vpx_memset(lfi->lvl[seg][0], lvl_seg, 4 * 4 );
+            continue;
+        }
+
+        lvl_ref = lvl_seg;
+
+        /* INTRA_FRAME */
+        ref = INTRA_FRAME;
+
+        /* Apply delta for reference frame */
+        lvl_ref += mbd->ref_lf_deltas[ref];
+
+        /* Apply delta for Intra modes */
+        mode = 0; /* B_PRED */
+        /* Only the split mode BPRED has a further special case */
+        lvl_mode = lvl_ref +  mbd->mode_lf_deltas[mode];
+        lvl_mode = (lvl_mode > 0) ? (lvl_mode > 63 ? 63 : lvl_mode) : 0; /* clamp */
+
+        lfi->lvl[seg][ref][mode] = lvl_mode;
+
+        mode = 1; /* all the rest of Intra modes */
+        lvl_mode = (lvl_ref > 0) ? (lvl_ref > 63 ? 63 : lvl_ref)  : 0; /* clamp */
+        lfi->lvl[seg][ref][mode] = lvl_mode;
+
+        /* LAST, GOLDEN, ALT */
+        for(ref = 1; ref < MAX_REF_FRAMES; ref++)
+        {
+            int lvl_ref = lvl_seg;
+
+            /* Apply delta for reference frame */
+            lvl_ref += mbd->ref_lf_deltas[ref];
+
+            /* Apply delta for Inter modes */
+            for (mode = 1; mode < 4; mode++)
+            {
+                lvl_mode = lvl_ref + mbd->mode_lf_deltas[mode];
+                lvl_mode = (lvl_mode > 0) ? (lvl_mode > 63 ? 63 : lvl_mode) : 0; /* clamp */
+
+                lfi->lvl[seg][ref][mode] = lvl_mode;
+            }
+        }
+    }
+}
+
+void vp8_loop_filter_frame
+(
+    VP8_COMMON *cm,
+    MACROBLOCKD *mbd
+)
+{
+    YV12_BUFFER_CONFIG *post = cm->frame_to_show;
+    loop_filter_info_n *lfi_n = &cm->lf_info;
+    loop_filter_info lfi;
+
+    FRAME_TYPE frame_type = cm->frame_type;
+
+    int mb_row;
+    int mb_col;
+    int mb_rows = cm->mb_rows;
+    int mb_cols = cm->mb_cols;
+
+    int filter_level;
+
+    unsigned char *y_ptr, *u_ptr, *v_ptr;
+
+    /* Point at base of Mb MODE_INFO list */
+    const MODE_INFO *mode_info_context = cm->mi;
+    int post_y_stride = post->y_stride;
+    int post_uv_stride = post->uv_stride;
+
+    /* Initialize the loop filter for this frame. */
+    vp8_loop_filter_frame_init(cm, mbd, cm->filter_level);
+
+    /* Set up the buffer pointers */
+    y_ptr = post->y_buffer;
+    u_ptr = post->u_buffer;
+    v_ptr = post->v_buffer;
+
+    /* vp8_filter each macro block */
+    if (cm->filter_type == NORMAL_LOOPFILTER)
+    {
+        for (mb_row = 0; mb_row < mb_rows; mb_row++)
+        {
+            for (mb_col = 0; mb_col < mb_cols; mb_col++)
+            {
+                int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
+                                mode_info_context->mbmi.mode != SPLITMV &&
+                                mode_info_context->mbmi.mb_skip_coeff);
+
+                const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode];
+                const int seg = mode_info_context->mbmi.segment_id;
+                const int ref_frame = mode_info_context->mbmi.ref_frame;
+
+                filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
+
+                if (filter_level)
+                {
+                    const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level];
+                    lfi.mblim = lfi_n->mblim[filter_level];
+                    lfi.blim = lfi_n->blim[filter_level];
+                    lfi.lim = lfi_n->lim[filter_level];
+                    lfi.hev_thr = lfi_n->hev_thr[hev_index];
+
+                    if (mb_col > 0)
+                        vp8_loop_filter_mbv
+                        (y_ptr, u_ptr, v_ptr, post_y_stride, post_uv_stride, &lfi);
+
+                    if (!skip_lf)
+                        vp8_loop_filter_bv
+                        (y_ptr, u_ptr, v_ptr, post_y_stride, post_uv_stride, &lfi);
+
+                    /* don't apply across umv border */
+                    if (mb_row > 0)
+                        vp8_loop_filter_mbh
+                        (y_ptr, u_ptr, v_ptr, post_y_stride, post_uv_stride, &lfi);
+
+                    if (!skip_lf)
+                        vp8_loop_filter_bh
+                        (y_ptr, u_ptr, v_ptr, post_y_stride, post_uv_stride, &lfi);
+                }
+
+                y_ptr += 16;
+                u_ptr += 8;
+                v_ptr += 8;
+
+                mode_info_context++;     /* step to next MB */
+            }
+            y_ptr += post_y_stride  * 16 - post->y_width;
+            u_ptr += post_uv_stride *  8 - post->uv_width;
+            v_ptr += post_uv_stride *  8 - post->uv_width;
+
+            mode_info_context++;         /* Skip border mb */
+
+        }
+    }
+    else /* SIMPLE_LOOPFILTER */
+    {
+        for (mb_row = 0; mb_row < mb_rows; mb_row++)
+        {
+            for (mb_col = 0; mb_col < mb_cols; mb_col++)
+            {
+                int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
+                                mode_info_context->mbmi.mode != SPLITMV &&
+                                mode_info_context->mbmi.mb_skip_coeff);
+
+                const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode];
+                const int seg = mode_info_context->mbmi.segment_id;
+                const int ref_frame = mode_info_context->mbmi.ref_frame;
+
+                filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
+                if (filter_level)
+                {
+                    const unsigned char * mblim = lfi_n->mblim[filter_level];
+                    const unsigned char * blim = lfi_n->blim[filter_level];
+
+                    if (mb_col > 0)
+                        vp8_loop_filter_simple_mbv
+                        (y_ptr, post_y_stride, mblim);
+
+                    if (!skip_lf)
+                        vp8_loop_filter_simple_bv
+                        (y_ptr, post_y_stride, blim);
+
+                    /* don't apply across umv border */
+                    if (mb_row > 0)
+                        vp8_loop_filter_simple_mbh
+                        (y_ptr, post_y_stride, mblim);
+
+                    if (!skip_lf)
+                        vp8_loop_filter_simple_bh
+                        (y_ptr, post_y_stride, blim);
+                }
+
+                y_ptr += 16;
+                u_ptr += 8;
+                v_ptr += 8;
+
+                mode_info_context++;     /* step to next MB */
+            }
+            y_ptr += post_y_stride  * 16 - post->y_width;
+            u_ptr += post_uv_stride *  8 - post->uv_width;
+            v_ptr += post_uv_stride *  8 - post->uv_width;
+
+            mode_info_context++;         /* Skip border mb */
+
+        }
+    }
+}
+
+void vp8_loop_filter_frame_yonly
+(
+    VP8_COMMON *cm,
+    MACROBLOCKD *mbd,
+    int default_filt_lvl
+)
+{
+    YV12_BUFFER_CONFIG *post = cm->frame_to_show;
+
+    unsigned char *y_ptr;
+    int mb_row;
+    int mb_col;
+
+    loop_filter_info_n *lfi_n = &cm->lf_info;
+    loop_filter_info lfi;
+
+    int filter_level;
+    FRAME_TYPE frame_type = cm->frame_type;
+
+    /* Point at base of Mb MODE_INFO list */
+    const MODE_INFO *mode_info_context = cm->mi;
+
+#if 0
+    if(default_filt_lvl == 0) /* no filter applied */
+        return;
+#endif
+
+    /* Initialize the loop filter for this frame. */
+    vp8_loop_filter_frame_init( cm, mbd, default_filt_lvl);
+
+    /* Set up the buffer pointers */
+    y_ptr = post->y_buffer;
+
+    /* vp8_filter each macro block */
+    for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
+    {
+        for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+        {
+            int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
+                            mode_info_context->mbmi.mode != SPLITMV &&
+                            mode_info_context->mbmi.mb_skip_coeff);
+
+            const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode];
+            const int seg = mode_info_context->mbmi.segment_id;
+            const int ref_frame = mode_info_context->mbmi.ref_frame;
+
+            filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
+
+            if (filter_level)
+            {
+                if (cm->filter_type == NORMAL_LOOPFILTER)
+                {
+                    const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level];
+                    lfi.mblim = lfi_n->mblim[filter_level];
+                    lfi.blim = lfi_n->blim[filter_level];
+                    lfi.lim = lfi_n->lim[filter_level];
+                    lfi.hev_thr = lfi_n->hev_thr[hev_index];
+
+                    if (mb_col > 0)
+                        vp8_loop_filter_mbv
+                        (y_ptr, 0, 0, post->y_stride, 0, &lfi);
+
+                    if (!skip_lf)
+                        vp8_loop_filter_bv
+                        (y_ptr, 0, 0, post->y_stride, 0, &lfi);
+
+                    /* don't apply across umv border */
+                    if (mb_row > 0)
+                        vp8_loop_filter_mbh
+                        (y_ptr, 0, 0, post->y_stride, 0, &lfi);
+
+                    if (!skip_lf)
+                        vp8_loop_filter_bh
+                        (y_ptr, 0, 0, post->y_stride, 0, &lfi);
+                }
+                else
+                {
+                    if (mb_col > 0)
+                        vp8_loop_filter_simple_mbv
+                        (y_ptr, post->y_stride, lfi_n->mblim[filter_level]);
+
+                    if (!skip_lf)
+                        vp8_loop_filter_simple_bv
+                        (y_ptr, post->y_stride, lfi_n->blim[filter_level]);
+
+                    /* don't apply across umv border */
+                    if (mb_row > 0)
+                        vp8_loop_filter_simple_mbh
+                        (y_ptr, post->y_stride, lfi_n->mblim[filter_level]);
+
+                    if (!skip_lf)
+                        vp8_loop_filter_simple_bh
+                        (y_ptr, post->y_stride, lfi_n->blim[filter_level]);
+                }
+            }
+
+            y_ptr += 16;
+            mode_info_context ++;        /* step to next MB */
+
+        }
+
+        y_ptr += post->y_stride  * 16 - post->y_width;
+        mode_info_context ++;            /* Skip border mb */
+    }
+
+}
+
+void vp8_loop_filter_partial_frame
+(
+    VP8_COMMON *cm,
+    MACROBLOCKD *mbd,
+    int default_filt_lvl
+)
+{
+    YV12_BUFFER_CONFIG *post = cm->frame_to_show;
+
+    unsigned char *y_ptr;
+    int mb_row;
+    int mb_col;
+    int mb_cols = post->y_width >> 4;
+    int mb_rows = post->y_height >> 4;
+
+    int linestocopy, i;
+
+    loop_filter_info_n *lfi_n = &cm->lf_info;
+    loop_filter_info lfi;
+
+    int filter_level;
+    int alt_flt_enabled = mbd->segmentation_enabled;
+    FRAME_TYPE frame_type = cm->frame_type;
+
+    const MODE_INFO *mode_info_context;
+
+    int lvl_seg[MAX_MB_SEGMENTS];
+
+    /* number of MB rows to use in partial filtering */
+    linestocopy = mb_rows / PARTIAL_FRAME_FRACTION;
+    linestocopy = linestocopy ? linestocopy << 4 : 16;     /* 16 lines per MB */
+
+    /* Note the baseline filter values for each segment */
+    /* See vp8_loop_filter_frame_init. Rather than call that for each change
+     * to default_filt_lvl, copy the relevant calculation here.
+     */
+    if (alt_flt_enabled)
+    {
+        for (i = 0; i < MAX_MB_SEGMENTS; i++)
+        {    /* Abs value */
+            if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA)
+            {
+                lvl_seg[i] = mbd->segment_feature_data[MB_LVL_ALT_LF][i];
+            }
+            /* Delta Value */
+            else
+            {
+                lvl_seg[i] = default_filt_lvl
+                        + mbd->segment_feature_data[MB_LVL_ALT_LF][i];
+                lvl_seg[i] = (lvl_seg[i] > 0) ?
+                        ((lvl_seg[i] > 63) ? 63: lvl_seg[i]) : 0;
+            }
+        }
+    }
+
+    /* Set up the buffer pointers; partial image starts at ~middle of frame */
+    y_ptr = post->y_buffer + ((post->y_height >> 5) * 16) * post->y_stride;
+    mode_info_context = cm->mi + (post->y_height >> 5) * (mb_cols + 1);
+
+    /* vp8_filter each macro block */
+    for (mb_row = 0; mb_row<(linestocopy >> 4); mb_row++)
+    {
+        for (mb_col = 0; mb_col < mb_cols; mb_col++)
+        {
+            int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
+                           mode_info_context->mbmi.mode != SPLITMV &&
+                           mode_info_context->mbmi.mb_skip_coeff);
+
+            if (alt_flt_enabled)
+                filter_level = lvl_seg[mode_info_context->mbmi.segment_id];
+            else
+                filter_level = default_filt_lvl;
+
+            if (filter_level)
+            {
+                if (cm->filter_type == NORMAL_LOOPFILTER)
+                {
+                    const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level];
+                    lfi.mblim = lfi_n->mblim[filter_level];
+                    lfi.blim = lfi_n->blim[filter_level];
+                    lfi.lim = lfi_n->lim[filter_level];
+                    lfi.hev_thr = lfi_n->hev_thr[hev_index];
+
+                    if (mb_col > 0)
+                        vp8_loop_filter_mbv
+                        (y_ptr, 0, 0, post->y_stride, 0, &lfi);
+
+                    if (!skip_lf)
+                        vp8_loop_filter_bv
+                        (y_ptr, 0, 0, post->y_stride, 0, &lfi);
+
+                    vp8_loop_filter_mbh
+                        (y_ptr, 0, 0, post->y_stride, 0, &lfi);
+
+                    if (!skip_lf)
+                        vp8_loop_filter_bh
+                        (y_ptr, 0, 0, post->y_stride, 0, &lfi);
+                }
+                else
+                {
+                    if (mb_col > 0)
+                        vp8_loop_filter_simple_mbv
+                        (y_ptr, post->y_stride, lfi_n->mblim[filter_level]);
+
+                    if (!skip_lf)
+                        vp8_loop_filter_simple_bv
+                        (y_ptr, post->y_stride, lfi_n->blim[filter_level]);
+
+                    vp8_loop_filter_simple_mbh
+                        (y_ptr, post->y_stride, lfi_n->mblim[filter_level]);
+
+                    if (!skip_lf)
+                        vp8_loop_filter_simple_bh
+                        (y_ptr, post->y_stride, lfi_n->blim[filter_level]);
+                }
+            }
+
+            y_ptr += 16;
+            mode_info_context += 1;      /* step to next MB */
+        }
+
+        y_ptr += post->y_stride  * 16 - post->y_width;
+        mode_info_context += 1;          /* Skip border mb */
+    }
+}
diff --git a/vp8/common/loopfilter.h b/vp8/common/loopfilter.h
new file mode 100644 (file)
index 0000000..0fa8375
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef loopfilter_h
+#define loopfilter_h
+
+#include "vpx_ports/mem.h"
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+
+#define MAX_LOOP_FILTER             63
+/* fraction of total macroblock rows to be used in fast filter level picking */
+/* has to be > 2 */
+#define PARTIAL_FRAME_FRACTION      8
+
+typedef enum
+{
+    NORMAL_LOOPFILTER = 0,
+    SIMPLE_LOOPFILTER = 1
+} LOOPFILTERTYPE;
+
+#if ARCH_ARM
+#define SIMD_WIDTH 1
+#else
+#define SIMD_WIDTH 16
+#endif
+
+/* Need to align this structure so when it is declared and
+ * passed it can be loaded into vector registers.
+ */
+typedef struct
+{
+    DECLARE_ALIGNED(SIMD_WIDTH, unsigned char, mblim[MAX_LOOP_FILTER + 1][SIMD_WIDTH]);
+    DECLARE_ALIGNED(SIMD_WIDTH, unsigned char, blim[MAX_LOOP_FILTER + 1][SIMD_WIDTH]);
+    DECLARE_ALIGNED(SIMD_WIDTH, unsigned char, lim[MAX_LOOP_FILTER + 1][SIMD_WIDTH]);
+    DECLARE_ALIGNED(SIMD_WIDTH, unsigned char, hev_thr[4][SIMD_WIDTH]);
+    unsigned char lvl[4][4][4];
+    unsigned char hev_thr_lut[2][MAX_LOOP_FILTER + 1];
+    unsigned char mode_lf_lut[10];
+} loop_filter_info_n;
+
+typedef struct loop_filter_info
+{
+    const unsigned char * mblim;
+    const unsigned char * blim;
+    const unsigned char * lim;
+    const unsigned char * hev_thr;
+} loop_filter_info;
+
+
+typedef void loop_filter_uvfunction
+(
+    unsigned char *u,   /* source pointer */
+    int p,              /* pitch */
+    const unsigned char *blimit,
+    const unsigned char *limit,
+    const unsigned char *thresh,
+    unsigned char *v
+);
+
+/* assorted loopfilter functions which get used elsewhere */
+struct VP8Common;
+struct macroblockd;
+
+void vp8_loop_filter_init(struct VP8Common *cm);
+
+void vp8_loop_filter_frame_init(struct VP8Common *cm,
+                                struct macroblockd *mbd,
+                                int default_filt_lvl);
+
+void vp8_loop_filter_frame(struct VP8Common *cm, struct macroblockd *mbd);
+
+void vp8_loop_filter_partial_frame(struct VP8Common *cm,
+                                   struct macroblockd *mbd,
+                                   int default_filt_lvl);
+
+void vp8_loop_filter_frame_yonly(struct VP8Common *cm,
+                                 struct macroblockd *mbd,
+                                 int default_filt_lvl);
+
+void vp8_loop_filter_update_sharpness(loop_filter_info_n *lfi,
+                                      int sharpness_lvl);
+
+#endif
diff --git a/vp8/common/loopfilter_filters.c b/vp8/common/loopfilter_filters.c
new file mode 100644 (file)
index 0000000..8235f6e
--- /dev/null
@@ -0,0 +1,430 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include <stdlib.h>
+#include "loopfilter.h"
+#include "onyxc_int.h"
+
+typedef unsigned char uc;
+
+static signed char vp8_signed_char_clamp(int t)
+{
+    t = (t < -128 ? -128 : t);
+    t = (t > 127 ? 127 : t);
+    return (signed char) t;
+}
+
+
+/* should we apply any filter at all ( 11111111 yes, 00000000 no) */
+static signed char vp8_filter_mask(uc limit, uc blimit,
+                            uc p3, uc p2, uc p1, uc p0,
+                            uc q0, uc q1, uc q2, uc q3)
+{
+    signed char mask = 0;
+    mask |= (abs(p3 - p2) > limit);
+    mask |= (abs(p2 - p1) > limit);
+    mask |= (abs(p1 - p0) > limit);
+    mask |= (abs(q1 - q0) > limit);
+    mask |= (abs(q2 - q1) > limit);
+    mask |= (abs(q3 - q2) > limit);
+    mask |= (abs(p0 - q0) * 2 + abs(p1 - q1) / 2  > blimit);
+    return mask - 1;
+}
+
+/* is there high variance internal edge ( 11111111 yes, 00000000 no) */
+static signed char vp8_hevmask(uc thresh, uc p1, uc p0, uc q0, uc q1)
+{
+    signed char hev = 0;
+    hev  |= (abs(p1 - p0) > thresh) * -1;
+    hev  |= (abs(q1 - q0) > thresh) * -1;
+    return hev;
+}
+
+static void vp8_filter(signed char mask, uc hev, uc *op1,
+        uc *op0, uc *oq0, uc *oq1)
+
+{
+    signed char ps0, qs0;
+    signed char ps1, qs1;
+    signed char vp8_filter, Filter1, Filter2;
+    signed char u;
+
+    ps1 = (signed char) * op1 ^ 0x80;
+    ps0 = (signed char) * op0 ^ 0x80;
+    qs0 = (signed char) * oq0 ^ 0x80;
+    qs1 = (signed char) * oq1 ^ 0x80;
+
+    /* add outer taps if we have high edge variance */
+    vp8_filter = vp8_signed_char_clamp(ps1 - qs1);
+    vp8_filter &= hev;
+
+    /* inner taps */
+    vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * (qs0 - ps0));
+    vp8_filter &= mask;
+
+    /* save bottom 3 bits so that we round one side +4 and the other +3
+     * if it equals 4 we'll set to adjust by -1 to account for the fact
+     * we'd round 3 the other way
+     */
+    Filter1 = vp8_signed_char_clamp(vp8_filter + 4);
+    Filter2 = vp8_signed_char_clamp(vp8_filter + 3);
+    Filter1 >>= 3;
+    Filter2 >>= 3;
+    u = vp8_signed_char_clamp(qs0 - Filter1);
+    *oq0 = u ^ 0x80;
+    u = vp8_signed_char_clamp(ps0 + Filter2);
+    *op0 = u ^ 0x80;
+    vp8_filter = Filter1;
+
+    /* outer tap adjustments */
+    vp8_filter += 1;
+    vp8_filter >>= 1;
+    vp8_filter &= ~hev;
+
+    u = vp8_signed_char_clamp(qs1 - vp8_filter);
+    *oq1 = u ^ 0x80;
+    u = vp8_signed_char_clamp(ps1 + vp8_filter);
+    *op1 = u ^ 0x80;
+
+}
+void vp8_loop_filter_horizontal_edge_c
+(
+    unsigned char *s,
+    int p, /* pitch */
+    const unsigned char *blimit,
+    const unsigned char *limit,
+    const unsigned char *thresh,
+    int count
+)
+{
+    int  hev = 0; /* high edge variance */
+    signed char mask = 0;
+    int i = 0;
+
+    /* loop filter designed to work using chars so that we can make maximum use
+     * of 8 bit simd instructions.
+     */
+    do
+    {
+        mask = vp8_filter_mask(limit[0], blimit[0],
+                               s[-4*p], s[-3*p], s[-2*p], s[-1*p],
+                               s[0*p], s[1*p], s[2*p], s[3*p]);
+
+        hev = vp8_hevmask(thresh[0], s[-2*p], s[-1*p], s[0*p], s[1*p]);
+
+        vp8_filter(mask, hev, s - 2 * p, s - 1 * p, s, s + 1 * p);
+
+        ++s;
+    }
+    while (++i < count * 8);
+}
+
+void vp8_loop_filter_vertical_edge_c
+(
+    unsigned char *s,
+    int p,
+    const unsigned char *blimit,
+    const unsigned char *limit,
+    const unsigned char *thresh,
+    int count
+)
+{
+    int  hev = 0; /* high edge variance */
+    signed char mask = 0;
+    int i = 0;
+
+    /* loop filter designed to work using chars so that we can make maximum use
+     * of 8 bit simd instructions.
+     */
+    do
+    {
+        mask = vp8_filter_mask(limit[0], blimit[0],
+                               s[-4], s[-3], s[-2], s[-1], s[0], s[1], s[2], s[3]);
+
+        hev = vp8_hevmask(thresh[0], s[-2], s[-1], s[0], s[1]);
+
+        vp8_filter(mask, hev, s - 2, s - 1, s, s + 1);
+
+        s += p;
+    }
+    while (++i < count * 8);
+}
+
+static void vp8_mbfilter(signed char mask, uc hev,
+                           uc *op2, uc *op1, uc *op0, uc *oq0, uc *oq1, uc *oq2)
+{
+    signed char s, u;
+    signed char vp8_filter, Filter1, Filter2;
+    signed char ps2 = (signed char) * op2 ^ 0x80;
+    signed char ps1 = (signed char) * op1 ^ 0x80;
+    signed char ps0 = (signed char) * op0 ^ 0x80;
+    signed char qs0 = (signed char) * oq0 ^ 0x80;
+    signed char qs1 = (signed char) * oq1 ^ 0x80;
+    signed char qs2 = (signed char) * oq2 ^ 0x80;
+
+    /* add outer taps if we have high edge variance */
+    vp8_filter = vp8_signed_char_clamp(ps1 - qs1);
+    vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * (qs0 - ps0));
+    vp8_filter &= mask;
+
+    Filter2 = vp8_filter;
+    Filter2 &= hev;
+
+    /* save bottom 3 bits so that we round one side +4 and the other +3 */
+    Filter1 = vp8_signed_char_clamp(Filter2 + 4);
+    Filter2 = vp8_signed_char_clamp(Filter2 + 3);
+    Filter1 >>= 3;
+    Filter2 >>= 3;
+    qs0 = vp8_signed_char_clamp(qs0 - Filter1);
+    ps0 = vp8_signed_char_clamp(ps0 + Filter2);
+
+
+    /* only apply wider filter if not high edge variance */
+    vp8_filter &= ~hev;
+    Filter2 = vp8_filter;
+
+    /* roughly 3/7th difference across boundary */
+    u = vp8_signed_char_clamp((63 + Filter2 * 27) >> 7);
+    s = vp8_signed_char_clamp(qs0 - u);
+    *oq0 = s ^ 0x80;
+    s = vp8_signed_char_clamp(ps0 + u);
+    *op0 = s ^ 0x80;
+
+    /* roughly 2/7th difference across boundary */
+    u = vp8_signed_char_clamp((63 + Filter2 * 18) >> 7);
+    s = vp8_signed_char_clamp(qs1 - u);
+    *oq1 = s ^ 0x80;
+    s = vp8_signed_char_clamp(ps1 + u);
+    *op1 = s ^ 0x80;
+
+    /* roughly 1/7th difference across boundary */
+    u = vp8_signed_char_clamp((63 + Filter2 * 9) >> 7);
+    s = vp8_signed_char_clamp(qs2 - u);
+    *oq2 = s ^ 0x80;
+    s = vp8_signed_char_clamp(ps2 + u);
+    *op2 = s ^ 0x80;
+}
+
+void vp8_mbloop_filter_horizontal_edge_c
+(
+    unsigned char *s,
+    int p,
+    const unsigned char *blimit,
+    const unsigned char *limit,
+    const unsigned char *thresh,
+    int count
+)
+{
+    signed char hev = 0; /* high edge variance */
+    signed char mask = 0;
+    int i = 0;
+
+    /* loop filter designed to work using chars so that we can make maximum use
+     * of 8 bit simd instructions.
+     */
+    do
+    {
+
+        mask = vp8_filter_mask(limit[0], blimit[0],
+                               s[-4*p], s[-3*p], s[-2*p], s[-1*p],
+                               s[0*p], s[1*p], s[2*p], s[3*p]);
+
+        hev = vp8_hevmask(thresh[0], s[-2*p], s[-1*p], s[0*p], s[1*p]);
+
+        vp8_mbfilter(mask, hev, s - 3 * p, s - 2 * p, s - 1 * p, s, s + 1 * p, s + 2 * p);
+
+        ++s;
+    }
+    while (++i < count * 8);
+
+}
+
+
+void vp8_mbloop_filter_vertical_edge_c
+(
+    unsigned char *s,
+    int p,
+    const unsigned char *blimit,
+    const unsigned char *limit,
+    const unsigned char *thresh,
+    int count
+)
+{
+    signed char hev = 0; /* high edge variance */
+    signed char mask = 0;
+    int i = 0;
+
+    do
+    {
+
+        mask = vp8_filter_mask(limit[0], blimit[0],
+                               s[-4], s[-3], s[-2], s[-1], s[0], s[1], s[2], s[3]);
+
+        hev = vp8_hevmask(thresh[0], s[-2], s[-1], s[0], s[1]);
+
+        vp8_mbfilter(mask, hev, s - 3, s - 2, s - 1, s, s + 1, s + 2);
+
+        s += p;
+    }
+    while (++i < count * 8);
+
+}
+
+/* should we apply any filter at all ( 11111111 yes, 00000000 no) */
+static signed char vp8_simple_filter_mask(uc blimit, uc p1, uc p0, uc q0, uc q1)
+{
+/* Why does this cause problems for win32?
+ * error C2143: syntax error : missing ';' before 'type'
+ *  (void) limit;
+ */
+    signed char mask = (abs(p0 - q0) * 2 + abs(p1 - q1) / 2  <= blimit) * -1;
+    return mask;
+}
+
+static void vp8_simple_filter(signed char mask, uc *op1, uc *op0, uc *oq0, uc *oq1)
+{
+    signed char vp8_filter, Filter1, Filter2;
+    signed char p1 = (signed char) * op1 ^ 0x80;
+    signed char p0 = (signed char) * op0 ^ 0x80;
+    signed char q0 = (signed char) * oq0 ^ 0x80;
+    signed char q1 = (signed char) * oq1 ^ 0x80;
+    signed char u;
+
+    vp8_filter = vp8_signed_char_clamp(p1 - q1);
+    vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * (q0 - p0));
+    vp8_filter &= mask;
+
+    /* save bottom 3 bits so that we round one side +4 and the other +3 */
+    Filter1 = vp8_signed_char_clamp(vp8_filter + 4);
+    Filter1 >>= 3;
+    u = vp8_signed_char_clamp(q0 - Filter1);
+    *oq0  = u ^ 0x80;
+
+    Filter2 = vp8_signed_char_clamp(vp8_filter + 3);
+    Filter2 >>= 3;
+    u = vp8_signed_char_clamp(p0 + Filter2);
+    *op0 = u ^ 0x80;
+}
+
+void vp8_loop_filter_simple_horizontal_edge_c
+(
+    unsigned char *s,
+    int p,
+    const unsigned char *blimit
+)
+{
+    signed char mask = 0;
+    int i = 0;
+
+    do
+    {
+        mask = vp8_simple_filter_mask(blimit[0], s[-2*p], s[-1*p], s[0*p], s[1*p]);
+        vp8_simple_filter(mask, s - 2 * p, s - 1 * p, s, s + 1 * p);
+        ++s;
+    }
+    while (++i < 16);
+}
+
+void vp8_loop_filter_simple_vertical_edge_c
+(
+    unsigned char *s,
+    int p,
+    const unsigned char *blimit
+)
+{
+    signed char mask = 0;
+    int i = 0;
+
+    do
+    {
+        mask = vp8_simple_filter_mask(blimit[0], s[-2], s[-1], s[0], s[1]);
+        vp8_simple_filter(mask, s - 2, s - 1, s, s + 1);
+        s += p;
+    }
+    while (++i < 16);
+
+}
+
+/* Horizontal MB filtering */
+void vp8_loop_filter_mbh_c(unsigned char *y_ptr, unsigned char *u_ptr,
+                           unsigned char *v_ptr, int y_stride, int uv_stride,
+                           loop_filter_info *lfi)
+{
+    vp8_mbloop_filter_horizontal_edge_c(y_ptr, y_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 2);
+
+    if (u_ptr)
+        vp8_mbloop_filter_horizontal_edge_c(u_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
+
+    if (v_ptr)
+        vp8_mbloop_filter_horizontal_edge_c(v_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
+}
+
+/* Vertical MB Filtering */
+void vp8_loop_filter_mbv_c(unsigned char *y_ptr, unsigned char *u_ptr,
+                           unsigned char *v_ptr, int y_stride, int uv_stride,
+                           loop_filter_info *lfi)
+{
+    vp8_mbloop_filter_vertical_edge_c(y_ptr, y_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 2);
+
+    if (u_ptr)
+        vp8_mbloop_filter_vertical_edge_c(u_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
+
+    if (v_ptr)
+        vp8_mbloop_filter_vertical_edge_c(v_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
+}
+
+/* Horizontal B Filtering */
+void vp8_loop_filter_bh_c(unsigned char *y_ptr, unsigned char *u_ptr,
+                          unsigned char *v_ptr, int y_stride, int uv_stride,
+                          loop_filter_info *lfi)
+{
+    vp8_loop_filter_horizontal_edge_c(y_ptr + 4 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+    vp8_loop_filter_horizontal_edge_c(y_ptr + 8 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+    vp8_loop_filter_horizontal_edge_c(y_ptr + 12 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+
+    if (u_ptr)
+        vp8_loop_filter_horizontal_edge_c(u_ptr + 4 * uv_stride, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
+
+    if (v_ptr)
+        vp8_loop_filter_horizontal_edge_c(v_ptr + 4 * uv_stride, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
+}
+
+void vp8_loop_filter_bhs_c(unsigned char *y_ptr, int y_stride,
+                           const unsigned char *blimit)
+{
+    vp8_loop_filter_simple_horizontal_edge_c(y_ptr + 4 * y_stride, y_stride, blimit);
+    vp8_loop_filter_simple_horizontal_edge_c(y_ptr + 8 * y_stride, y_stride, blimit);
+    vp8_loop_filter_simple_horizontal_edge_c(y_ptr + 12 * y_stride, y_stride, blimit);
+}
+
+/* Vertical B Filtering */
+void vp8_loop_filter_bv_c(unsigned char *y_ptr, unsigned char *u_ptr,
+                          unsigned char *v_ptr, int y_stride, int uv_stride,
+                          loop_filter_info *lfi)
+{
+    vp8_loop_filter_vertical_edge_c(y_ptr + 4, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+    vp8_loop_filter_vertical_edge_c(y_ptr + 8, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+    vp8_loop_filter_vertical_edge_c(y_ptr + 12, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+
+    if (u_ptr)
+        vp8_loop_filter_vertical_edge_c(u_ptr + 4, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
+
+    if (v_ptr)
+        vp8_loop_filter_vertical_edge_c(v_ptr + 4, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
+}
+
+void vp8_loop_filter_bvs_c(unsigned char *y_ptr, int y_stride,
+                           const unsigned char *blimit)
+{
+    vp8_loop_filter_simple_vertical_edge_c(y_ptr + 4, y_stride, blimit);
+    vp8_loop_filter_simple_vertical_edge_c(y_ptr + 8, y_stride, blimit);
+    vp8_loop_filter_simple_vertical_edge_c(y_ptr + 12, y_stride, blimit);
+}
diff --git a/vp8/common/mbpitch.c b/vp8/common/mbpitch.c
new file mode 100644 (file)
index 0000000..32e1b66
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "blockd.h"
+
+void vp8_setup_block_dptrs(MACROBLOCKD *x)
+{
+    int r, c;
+
+    for (r = 0; r < 4; r++)
+    {
+        for (c = 0; c < 4; c++)
+        {
+            x->block[r*4+c].predictor = x->predictor + r * 4 * 16 + c * 4;
+        }
+    }
+
+    for (r = 0; r < 2; r++)
+    {
+        for (c = 0; c < 2; c++)
+        {
+            x->block[16+r*2+c].predictor = x->predictor + 256 + r * 4 * 8 + c * 4;
+
+        }
+    }
+
+    for (r = 0; r < 2; r++)
+    {
+        for (c = 0; c < 2; c++)
+        {
+            x->block[20+r*2+c].predictor = x->predictor + 320 + r * 4 * 8 + c * 4;
+
+        }
+    }
+
+    for (r = 0; r < 25; r++)
+    {
+        x->block[r].qcoeff  = x->qcoeff  + r * 16;
+        x->block[r].dqcoeff = x->dqcoeff + r * 16;
+        x->block[r].eob     = x->eobs + r;
+    }
+}
+
+void vp8_build_block_doffsets(MACROBLOCKD *x)
+{
+    int block;
+
+    for (block = 0; block < 16; block++) /* y blocks */
+    {
+        x->block[block].offset =
+            (block >> 2) * 4 * x->dst.y_stride + (block & 3) * 4;
+    }
+
+    for (block = 16; block < 20; block++) /* U and V blocks */
+    {
+        x->block[block+4].offset =
+        x->block[block].offset =
+            ((block - 16) >> 1) * 4 * x->dst.uv_stride + (block & 1) * 4;
+    }
+}
diff --git a/vp8/common/mfqe.c b/vp8/common/mfqe.c
new file mode 100644 (file)
index 0000000..ca67e91
--- /dev/null
@@ -0,0 +1,385 @@
+/*
+ *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/* MFQE: Multiframe Quality Enhancement
+ * In rate limited situations keyframes may cause significant visual artifacts
+ * commonly referred to as "popping." This file implements a postproccesing
+ * algorithm which blends data from the preceeding frame when there is no
+ * motion and the q from the previous frame is lower which indicates that it is
+ * higher quality.
+ */
+
+#include "postproc.h"
+#include "variance.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_rtcd.h"
+#include "vpx_scale/yv12config.h"
+
+#include <limits.h>
+#include <stdlib.h>
+
+static void filter_by_weight(unsigned char *src, int src_stride,
+                             unsigned char *dst, int dst_stride,
+                             int block_size, int src_weight)
+{
+    int dst_weight = (1 << MFQE_PRECISION) - src_weight;
+    int rounding_bit = 1 << (MFQE_PRECISION - 1);
+    int r, c;
+
+    for (r = 0; r < block_size; r++)
+    {
+        for (c = 0; c < block_size; c++)
+        {
+            dst[c] = (src[c] * src_weight +
+                      dst[c] * dst_weight +
+                      rounding_bit) >> MFQE_PRECISION;
+        }
+        src += src_stride;
+        dst += dst_stride;
+    }
+}
+
+void vp8_filter_by_weight16x16_c(unsigned char *src, int src_stride,
+                                 unsigned char *dst, int dst_stride,
+                                 int src_weight)
+{
+    filter_by_weight(src, src_stride, dst, dst_stride, 16, src_weight);
+}
+
+void vp8_filter_by_weight8x8_c(unsigned char *src, int src_stride,
+                               unsigned char *dst, int dst_stride,
+                               int src_weight)
+{
+    filter_by_weight(src, src_stride, dst, dst_stride, 8, src_weight);
+}
+
+void vp8_filter_by_weight4x4_c(unsigned char *src, int src_stride,
+                               unsigned char *dst, int dst_stride,
+                               int src_weight)
+{
+    filter_by_weight(src, src_stride, dst, dst_stride, 4, src_weight);
+}
+
+static void apply_ifactor(unsigned char *y_src,
+                          int y_src_stride,
+                          unsigned char *y_dst,
+                          int y_dst_stride,
+                          unsigned char *u_src,
+                          unsigned char *v_src,
+                          int uv_src_stride,
+                          unsigned char *u_dst,
+                          unsigned char *v_dst,
+                          int uv_dst_stride,
+                          int block_size,
+                          int src_weight)
+{
+    if (block_size == 16)
+    {
+        vp8_filter_by_weight16x16(y_src, y_src_stride, y_dst, y_dst_stride, src_weight);
+        vp8_filter_by_weight8x8(u_src, uv_src_stride, u_dst, uv_dst_stride, src_weight);
+        vp8_filter_by_weight8x8(v_src, uv_src_stride, v_dst, uv_dst_stride, src_weight);
+    }
+    else /* if (block_size == 8) */
+    {
+        vp8_filter_by_weight8x8(y_src, y_src_stride, y_dst, y_dst_stride, src_weight);
+        vp8_filter_by_weight4x4(u_src, uv_src_stride, u_dst, uv_dst_stride, src_weight);
+        vp8_filter_by_weight4x4(v_src, uv_src_stride, v_dst, uv_dst_stride, src_weight);
+    }
+}
+
+static unsigned int int_sqrt(unsigned int x)
+{
+    unsigned int y = x;
+    unsigned int guess;
+    int p = 1;
+    while (y>>=1) p++;
+    p>>=1;
+
+    guess=0;
+    while (p>=0)
+    {
+        guess |= (1<<p);
+        if (x<guess*guess)
+            guess -= (1<<p);
+        p--;
+    }
+    /* choose between guess or guess+1 */
+    return guess+(guess*guess+guess+1<=x);
+}
+
+#define USE_SSD
+static void multiframe_quality_enhance_block
+(
+    int blksize, /* Currently only values supported are 16, 8 */
+    int qcurr,
+    int qprev,
+    unsigned char *y,
+    unsigned char *u,
+    unsigned char *v,
+    int y_stride,
+    int uv_stride,
+    unsigned char *yd,
+    unsigned char *ud,
+    unsigned char *vd,
+    int yd_stride,
+    int uvd_stride
+)
+{
+    static const unsigned char VP8_ZEROS[16]=
+    {
+         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+    };
+    int uvblksize = blksize >> 1;
+    int qdiff = qcurr - qprev;
+
+    int i;
+    unsigned char *up;
+    unsigned char *udp;
+    unsigned char *vp;
+    unsigned char *vdp;
+
+    unsigned int act, actd, sad, usad, vsad, sse, thr, thrsq, actrisk;
+
+    if (blksize == 16)
+    {
+        actd = (vp8_variance16x16(yd, yd_stride, VP8_ZEROS, 0, &sse)+128)>>8;
+        act = (vp8_variance16x16(y, y_stride, VP8_ZEROS, 0, &sse)+128)>>8;
+#ifdef USE_SSD
+        sad = (vp8_variance16x16(y, y_stride, yd, yd_stride, &sse));
+        sad = (sse + 128)>>8;
+        usad = (vp8_variance8x8(u, uv_stride, ud, uvd_stride, &sse));
+        usad = (sse + 32)>>6;
+        vsad = (vp8_variance8x8(v, uv_stride, vd, uvd_stride, &sse));
+        vsad = (sse + 32)>>6;
+#else
+        sad = (vp8_sad16x16(y, y_stride, yd, yd_stride, INT_MAX)+128)>>8;
+        usad = (vp8_sad8x8(u, uv_stride, ud, uvd_stride, INT_MAX)+32)>>6;
+        vsad = (vp8_sad8x8(v, uv_stride, vd, uvd_stride, INT_MAX)+32)>>6;
+#endif
+    }
+    else /* if (blksize == 8) */
+    {
+        actd = (vp8_variance8x8(yd, yd_stride, VP8_ZEROS, 0, &sse)+32)>>6;
+        act = (vp8_variance8x8(y, y_stride, VP8_ZEROS, 0, &sse)+32)>>6;
+#ifdef USE_SSD
+        sad = (vp8_variance8x8(y, y_stride, yd, yd_stride, &sse));
+        sad = (sse + 32)>>6;
+        usad = (vp8_variance4x4(u, uv_stride, ud, uvd_stride, &sse));
+        usad = (sse + 8)>>4;
+        vsad = (vp8_variance4x4(v, uv_stride, vd, uvd_stride, &sse));
+        vsad = (sse + 8)>>4;
+#else
+        sad = (vp8_sad8x8(y, y_stride, yd, yd_stride, INT_MAX)+32)>>6;
+        usad = (vp8_sad4x4(u, uv_stride, ud, uvd_stride, INT_MAX)+8)>>4;
+        vsad = (vp8_sad4x4(v, uv_stride, vd, uvd_stride, INT_MAX)+8)>>4;
+#endif
+    }
+
+    actrisk = (actd > act * 5);
+
+    /* thr = qdiff/8 + log2(act) + log4(qprev) */
+    thr = (qdiff >> 3);
+    while (actd >>= 1) thr++;
+    while (qprev >>= 2) thr++;
+
+#ifdef USE_SSD
+    thrsq = thr * thr;
+    if (sad < thrsq &&
+        /* additional checks for color mismatch and excessive addition of
+         * high-frequencies */
+        4 * usad < thrsq && 4 * vsad < thrsq && !actrisk)
+#else
+    if (sad < thr &&
+        /* additional checks for color mismatch and excessive addition of
+         * high-frequencies */
+        2 * usad < thr && 2 * vsad < thr && !actrisk)
+#endif
+    {
+        int ifactor;
+#ifdef USE_SSD
+        /* TODO: optimize this later to not need sqr root */
+        sad = int_sqrt(sad);
+#endif
+        ifactor = (sad << MFQE_PRECISION) / thr;
+        ifactor >>= (qdiff >> 5);
+
+        if (ifactor)
+        {
+            apply_ifactor(y, y_stride, yd, yd_stride,
+                          u, v, uv_stride,
+                          ud, vd, uvd_stride,
+                          blksize, ifactor);
+        }
+    }
+    else  /* else implicitly copy from previous frame */
+    {
+        if (blksize == 16)
+        {
+            vp8_copy_mem16x16(y, y_stride, yd, yd_stride);
+            vp8_copy_mem8x8(u, uv_stride, ud, uvd_stride);
+            vp8_copy_mem8x8(v, uv_stride, vd, uvd_stride);
+        }
+        else  /* if (blksize == 8) */
+        {
+            vp8_copy_mem8x8(y, y_stride, yd, yd_stride);
+            for (up = u, udp = ud, i = 0; i < uvblksize; ++i, up += uv_stride, udp += uvd_stride)
+                vpx_memcpy(udp, up, uvblksize);
+            for (vp = v, vdp = vd, i = 0; i < uvblksize; ++i, vp += uv_stride, vdp += uvd_stride)
+                vpx_memcpy(vdp, vp, uvblksize);
+        }
+    }
+}
+
+static int qualify_inter_mb(const MODE_INFO *mode_info_context, int *map)
+{
+    if (mode_info_context->mbmi.mb_skip_coeff)
+        map[0] = map[1] = map[2] = map[3] = 1;
+    else if (mode_info_context->mbmi.mode==SPLITMV)
+    {
+        static int ndx[4][4] =
+        {
+            {0, 1, 4, 5},
+            {2, 3, 6, 7},
+            {8, 9, 12, 13},
+            {10, 11, 14, 15}
+        };
+        int i, j;
+        for (i=0; i<4; ++i)
+        {
+            map[i] = 1;
+            for (j=0; j<4 && map[j]; ++j)
+                map[i] &= (mode_info_context->bmi[ndx[i][j]].mv.as_mv.row <= 2 &&
+                           mode_info_context->bmi[ndx[i][j]].mv.as_mv.col <= 2);
+        }
+    }
+    else
+    {
+        map[0] = map[1] = map[2] = map[3] =
+            (mode_info_context->mbmi.mode > B_PRED &&
+             abs(mode_info_context->mbmi.mv.as_mv.row) <= 2 &&
+             abs(mode_info_context->mbmi.mv.as_mv.col) <= 2);
+    }
+    return (map[0]+map[1]+map[2]+map[3]);
+}
+
+void vp8_multiframe_quality_enhance
+(
+    VP8_COMMON *cm
+)
+{
+    YV12_BUFFER_CONFIG *show = cm->frame_to_show;
+    YV12_BUFFER_CONFIG *dest = &cm->post_proc_buffer;
+
+    FRAME_TYPE frame_type = cm->frame_type;
+    /* Point at base of Mb MODE_INFO list has motion vectors etc */
+    const MODE_INFO *mode_info_context = cm->mi;
+    int mb_row;
+    int mb_col;
+    int totmap, map[4];
+    int qcurr = cm->base_qindex;
+    int qprev = cm->postproc_state.last_base_qindex;
+
+    unsigned char *y_ptr, *u_ptr, *v_ptr;
+    unsigned char *yd_ptr, *ud_ptr, *vd_ptr;
+
+    /* Set up the buffer pointers */
+    y_ptr = show->y_buffer;
+    u_ptr = show->u_buffer;
+    v_ptr = show->v_buffer;
+    yd_ptr = dest->y_buffer;
+    ud_ptr = dest->u_buffer;
+    vd_ptr = dest->v_buffer;
+
+    /* postprocess each macro block */
+    for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
+    {
+        for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+        {
+            /* if motion is high there will likely be no benefit */
+            if (frame_type == INTER_FRAME) totmap = qualify_inter_mb(mode_info_context, map);
+            else totmap = (frame_type == KEY_FRAME ? 4 : 0);
+            if (totmap)
+            {
+                if (totmap < 4)
+                {
+                    int i, j;
+                    for (i=0; i<2; ++i)
+                        for (j=0; j<2; ++j)
+                        {
+                            if (map[i*2+j])
+                            {
+                                multiframe_quality_enhance_block(8, qcurr, qprev,
+                                                                 y_ptr + 8*(i*show->y_stride+j),
+                                                                 u_ptr + 4*(i*show->uv_stride+j),
+                                                                 v_ptr + 4*(i*show->uv_stride+j),
+                                                                 show->y_stride,
+                                                                 show->uv_stride,
+                                                                 yd_ptr + 8*(i*dest->y_stride+j),
+                                                                 ud_ptr + 4*(i*dest->uv_stride+j),
+                                                                 vd_ptr + 4*(i*dest->uv_stride+j),
+                                                                 dest->y_stride,
+                                                                 dest->uv_stride);
+                            }
+                            else
+                            {
+                                /* copy a 8x8 block */
+                                int k;
+                                unsigned char *up = u_ptr + 4*(i*show->uv_stride+j);
+                                unsigned char *udp = ud_ptr + 4*(i*dest->uv_stride+j);
+                                unsigned char *vp = v_ptr + 4*(i*show->uv_stride+j);
+                                unsigned char *vdp = vd_ptr + 4*(i*dest->uv_stride+j);
+                                vp8_copy_mem8x8(y_ptr + 8*(i*show->y_stride+j), show->y_stride,
+                                                yd_ptr + 8*(i*dest->y_stride+j), dest->y_stride);
+                                for (k = 0; k < 4; ++k, up += show->uv_stride, udp += dest->uv_stride,
+                                                        vp += show->uv_stride, vdp += dest->uv_stride)
+                                {
+                                    vpx_memcpy(udp, up, 4);
+                                    vpx_memcpy(vdp, vp, 4);
+                                }
+                            }
+                        }
+                }
+                else /* totmap = 4 */
+                {
+                    multiframe_quality_enhance_block(16, qcurr, qprev, y_ptr,
+                                                     u_ptr, v_ptr,
+                                                     show->y_stride,
+                                                     show->uv_stride,
+                                                     yd_ptr, ud_ptr, vd_ptr,
+                                                     dest->y_stride,
+                                                     dest->uv_stride);
+                }
+            }
+            else
+            {
+                vp8_copy_mem16x16(y_ptr, show->y_stride, yd_ptr, dest->y_stride);
+                vp8_copy_mem8x8(u_ptr, show->uv_stride, ud_ptr, dest->uv_stride);
+                vp8_copy_mem8x8(v_ptr, show->uv_stride, vd_ptr, dest->uv_stride);
+            }
+            y_ptr += 16;
+            u_ptr += 8;
+            v_ptr += 8;
+            yd_ptr += 16;
+            ud_ptr += 8;
+            vd_ptr += 8;
+            mode_info_context++;     /* step to next MB */
+        }
+
+        y_ptr += show->y_stride  * 16 - 16 * cm->mb_cols;
+        u_ptr += show->uv_stride *  8 - 8 * cm->mb_cols;
+        v_ptr += show->uv_stride *  8 - 8 * cm->mb_cols;
+        yd_ptr += dest->y_stride  * 16 - 16 * cm->mb_cols;
+        ud_ptr += dest->uv_stride *  8 - 8 * cm->mb_cols;
+        vd_ptr += dest->uv_stride *  8 - 8 * cm->mb_cols;
+
+        mode_info_context++;         /* Skip border mb */
+    }
+}
diff --git a/vp8/common/modecont.c b/vp8/common/modecont.c
new file mode 100644 (file)
index 0000000..86a74bc
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "entropy.h"
+
+const int vp8_mode_contexts[6][4] =
+{
+    {
+        /* 0 */
+        7,     1,     1,   143,
+    },
+    {
+        /* 1 */
+        14,    18,    14,   107,
+    },
+    {
+        /* 2 */
+        135,    64,    57,    68,
+    },
+    {
+        /* 3 */
+        60,    56,   128,    65,
+    },
+    {
+        /* 4 */
+        159,   134,   128,    34,
+    },
+    {
+        /* 5 */
+        234,   188,   128,    28,
+    },
+};
diff --git a/vp8/common/modecont.h b/vp8/common/modecont.h
new file mode 100644 (file)
index 0000000..24db882
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_MODECONT_H
+#define __INC_MODECONT_H
+
+extern const int vp8_mode_contexts[6][4];
+
+#endif
diff --git a/vp8/common/mv.h b/vp8/common/mv.h
new file mode 100644 (file)
index 0000000..b3f919d
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_MV_H
+#define __INC_MV_H
+#include "vpx/vpx_integer.h"
+
+typedef struct
+{
+    short row;
+    short col;
+} MV;
+
+typedef union int_mv
+{
+    uint32_t  as_int;
+    MV        as_mv;
+} int_mv;        /* facilitates faster equality tests and copies */
+
+#endif
diff --git a/vp8/common/onyx.h b/vp8/common/onyx.h
new file mode 100644 (file)
index 0000000..2e282f6
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_VP8_H
+#define __INC_VP8_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "vpx_config.h"
+#include "vpx/internal/vpx_codec_internal.h"
+#include "vpx/vp8cx.h"
+#include "vpx/vpx_encoder.h"
+#include "vpx_scale/yv12config.h"
+#include "ppflags.h"
+
+    struct VP8_COMP;
+
+    /* Create/destroy static data structures. */
+
+    typedef enum
+    {
+        NORMAL      = 0,
+        FOURFIVE    = 1,
+        THREEFIVE   = 2,
+        ONETWO      = 3
+
+    } VPX_SCALING;
+
+    typedef enum
+    {
+        VP8_LAST_FLAG = 1,
+        VP8_GOLD_FLAG = 2,
+        VP8_ALT_FLAG = 4
+    } VP8_REFFRAME;
+
+
+    typedef enum
+    {
+        USAGE_STREAM_FROM_SERVER    = 0x0,
+        USAGE_LOCAL_FILE_PLAYBACK   = 0x1,
+        USAGE_CONSTRAINED_QUALITY   = 0x2
+    } END_USAGE;
+
+
+    typedef enum
+    {
+        MODE_REALTIME       = 0x0,
+        MODE_GOODQUALITY    = 0x1,
+        MODE_BESTQUALITY    = 0x2,
+        MODE_FIRSTPASS      = 0x3,
+        MODE_SECONDPASS     = 0x4,
+        MODE_SECONDPASS_BEST = 0x5
+    } MODE;
+
+    typedef enum
+    {
+        FRAMEFLAGS_KEY    = 1,
+        FRAMEFLAGS_GOLDEN = 2,
+        FRAMEFLAGS_ALTREF = 4
+    } FRAMETYPE_FLAGS;
+
+
+#include <assert.h>
+    static void Scale2Ratio(int mode, int *hr, int *hs)
+    {
+        switch (mode)
+        {
+        case    NORMAL:
+            *hr = 1;
+            *hs = 1;
+            break;
+        case    FOURFIVE:
+            *hr = 4;
+            *hs = 5;
+            break;
+        case    THREEFIVE:
+            *hr = 3;
+            *hs = 5;
+            break;
+        case    ONETWO:
+            *hr = 1;
+            *hs = 2;
+            break;
+        default:
+            *hr = 1;
+            *hs = 1;
+            assert(0);
+            break;
+        }
+    }
+
+    typedef struct
+    {
+        int Version;            // 4 versions of bitstream defined 0 best quality/slowest decode, 3 lowest quality/fastest decode
+        int Width;              // width of data passed to the compressor
+        int Height;             // height of data passed to the compressor
+        struct vpx_rational  timebase;
+        int target_bandwidth;    // bandwidth to be used in kilobits per second
+
+        int noise_sensitivity;   // parameter used for applying pre processing blur: recommendation 0
+        int Sharpness;          // parameter used for sharpening output: recommendation 0:
+        int cpu_used;
+        unsigned int rc_max_intra_bitrate_pct;
+
+        // mode ->
+        //(0)=Realtime/Live Encoding. This mode is optimized for realtim encoding (for example, capturing
+        //    a television signal or feed from a live camera). ( speed setting controls how fast )
+        //(1)=Good Quality Fast Encoding. The encoder balances quality with the amount of time it takes to
+        //    encode the output. ( speed setting controls how fast )
+        //(2)=One Pass - Best Quality. The encoder places priority on the quality of the output over encoding
+        //    speed. The output is compressed at the highest possible quality. This option takes the longest
+        //    amount of time to encode. ( speed setting ignored )
+        //(3)=Two Pass - First Pass. The encoder generates a file of statistics for use in the second encoding
+        //    pass. ( speed setting controls how fast )
+        //(4)=Two Pass - Second Pass. The encoder uses the statistics that were generated in the first encoding
+        //    pass to create the compressed output. ( speed setting controls how fast )
+        //(5)=Two Pass - Second Pass Best.  The encoder uses the statistics that were generated in the first
+        //    encoding pass to create the compressed output using the highest possible quality, and taking a
+        //    longer amount of time to encode.. ( speed setting ignored )
+        int Mode;               //
+
+        // Key Framing Operations
+        int auto_key;            // automatically detect cut scenes and set the keyframes
+        int key_freq;            // maximum distance to key frame.
+
+        int allow_lag;           // allow lagged compression (if 0 lagin frames is ignored)
+        int lag_in_frames;        // how many frames lag before we start encoding
+
+        //----------------------------------------------------------------
+        // DATARATE CONTROL OPTIONS
+
+        int end_usage; // vbr or cbr
+
+        // buffer targeting aggressiveness
+        int under_shoot_pct;
+        int over_shoot_pct;
+
+        // buffering parameters
+        int64_t starting_buffer_level;  // in bytes
+        int64_t optimal_buffer_level;
+        int64_t maximum_buffer_size;
+
+        int64_t starting_buffer_level_in_ms;  // in milli-seconds
+        int64_t optimal_buffer_level_in_ms;
+        int64_t maximum_buffer_size_in_ms;
+
+        // controlling quality
+        int fixed_q;
+        int worst_allowed_q;
+        int best_allowed_q;
+        int cq_level;
+
+        // allow internal resizing ( currently disabled in the build !!!!!)
+        int allow_spatial_resampling;
+        int resample_down_water_mark;
+        int resample_up_water_mark;
+
+        // allow internal frame rate alterations
+        int allow_df;
+        int drop_frames_water_mark;
+
+        // two pass datarate control
+        int two_pass_vbrbias;        // two pass datarate control tweaks
+        int two_pass_vbrmin_section;
+        int two_pass_vbrmax_section;
+        // END DATARATE CONTROL OPTIONS
+        //----------------------------------------------------------------
+
+
+        // these parameters aren't to be used in final build don't use!!!
+        int play_alternate;
+        int alt_freq;
+        int alt_q;
+        int key_q;
+        int gold_q;
+
+
+        int multi_threaded;   // how many threads to run the encoder on
+        int token_partitions; // how many token partitions to create for multi core decoding
+        int encode_breakout;  // early breakout encode threshold : for video conf recommend 800
+
+        unsigned int error_resilient_mode; // Bitfield defining the error
+                                   // resiliency features to enable. Can provide
+                                   // decodable frames after losses in previous
+                                   // frames and decodable partitions after
+                                   // losses in the same frame.
+
+        int arnr_max_frames;
+        int arnr_strength ;
+        int arnr_type     ;
+
+        struct vpx_fixed_buf         two_pass_stats_in;
+        struct vpx_codec_pkt_list  *output_pkt_list;
+
+        vp8e_tuning tuning;
+
+        // Temporal scaling parameters
+        unsigned int number_of_layers;
+        unsigned int target_bitrate[VPX_TS_MAX_PERIODICITY];
+        unsigned int rate_decimator[VPX_TS_MAX_PERIODICITY];
+        unsigned int periodicity;
+        unsigned int layer_id[VPX_TS_MAX_PERIODICITY];
+
+#if CONFIG_MULTI_RES_ENCODING
+        /* Number of total resolutions encoded */
+        unsigned int mr_total_resolutions;
+
+        /* Current encoder ID */
+        unsigned int mr_encoder_id;
+
+        /* Down-sampling factor */
+        vpx_rational_t mr_down_sampling_factor;
+
+        /* Memory location to store low-resolution encoder's mode info */
+        void* mr_low_res_mode_info;
+#endif
+    } VP8_CONFIG;
+
+
+    void vp8_initialize();
+
+    struct VP8_COMP* vp8_create_compressor(VP8_CONFIG *oxcf);
+    void vp8_remove_compressor(struct VP8_COMP* *comp);
+
+    void vp8_init_config(struct VP8_COMP* onyx, VP8_CONFIG *oxcf);
+    void vp8_change_config(struct VP8_COMP* onyx, VP8_CONFIG *oxcf);
+
+// receive a frames worth of data caller can assume that a copy of this frame is made
+// and not just a copy of the pointer..
+    int vp8_receive_raw_frame(struct VP8_COMP* comp, unsigned int frame_flags, YV12_BUFFER_CONFIG *sd, int64_t time_stamp, int64_t end_time_stamp);
+    int vp8_get_compressed_data(struct VP8_COMP* comp, unsigned int *frame_flags, unsigned long *size, unsigned char *dest, unsigned char *dest_end, int64_t *time_stamp, int64_t *time_end, int flush);
+    int vp8_get_preview_raw_frame(struct VP8_COMP* comp, YV12_BUFFER_CONFIG *dest, vp8_ppflags_t *flags);
+
+    int vp8_use_as_reference(struct VP8_COMP* comp, int ref_frame_flags);
+    int vp8_update_reference(struct VP8_COMP* comp, int ref_frame_flags);
+    int vp8_get_reference(struct VP8_COMP* comp, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd);
+    int vp8_set_reference(struct VP8_COMP* comp, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd);
+    int vp8_update_entropy(struct VP8_COMP* comp, int update);
+    int vp8_set_roimap(struct VP8_COMP* comp, unsigned char *map, unsigned int rows, unsigned int cols, int delta_q[4], int delta_lf[4], unsigned int threshold[4]);
+    int vp8_set_active_map(struct VP8_COMP* comp, unsigned char *map, unsigned int rows, unsigned int cols);
+    int vp8_set_internal_size(struct VP8_COMP* comp, VPX_SCALING horiz_mode, VPX_SCALING vert_mode);
+    int vp8_get_quantizer(struct VP8_COMP* c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/vp8/common/onyxc_int.h b/vp8/common/onyxc_int.h
new file mode 100644 (file)
index 0000000..c3215c0
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_VP8C_INT_H
+#define __INC_VP8C_INT_H
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "vpx/internal/vpx_codec_internal.h"
+#include "loopfilter.h"
+#include "entropymv.h"
+#include "entropy.h"
+#if CONFIG_POSTPROC
+#include "postproc.h"
+#endif
+
+/*#ifdef PACKET_TESTING*/
+#include "header.h"
+/*#endif*/
+
+#define MINQ 0
+#define MAXQ 127
+#define QINDEX_RANGE (MAXQ + 1)
+
+#define NUM_YV12_BUFFERS 4
+
+#define MAX_PARTITIONS 9
+
+typedef struct frame_contexts
+{
+    vp8_prob bmode_prob [VP8_BINTRAMODES-1];
+    vp8_prob ymode_prob [VP8_YMODES-1];   /* interframe intra mode probs */
+    vp8_prob uv_mode_prob [VP8_UV_MODES-1];
+    vp8_prob sub_mv_ref_prob [VP8_SUBMVREFS-1];
+    vp8_prob coef_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES];
+    MV_CONTEXT mvc[2];
+    MV_CONTEXT pre_mvc[2];  /* not to caculate the mvcost for the frame if mvc doesn't change. */
+} FRAME_CONTEXT;
+
+typedef enum
+{
+    ONE_PARTITION  = 0,
+    TWO_PARTITION  = 1,
+    FOUR_PARTITION = 2,
+    EIGHT_PARTITION = 3
+} TOKEN_PARTITION;
+
+typedef enum
+{
+    RECON_CLAMP_REQUIRED        = 0,
+    RECON_CLAMP_NOTREQUIRED     = 1
+} CLAMP_TYPE;
+
+typedef enum
+{
+    SIXTAP   = 0,
+    BILINEAR = 1
+} INTERPOLATIONFILTERTYPE;
+
+typedef struct VP8Common
+
+{
+    struct vpx_internal_error_info  error;
+
+    DECLARE_ALIGNED(16, short, Y1dequant[QINDEX_RANGE][2]);
+    DECLARE_ALIGNED(16, short, Y2dequant[QINDEX_RANGE][2]);
+    DECLARE_ALIGNED(16, short, UVdequant[QINDEX_RANGE][2]);
+
+    int Width;
+    int Height;
+    int horiz_scale;
+    int vert_scale;
+
+    YUV_TYPE clr_type;
+    CLAMP_TYPE  clamp_type;
+
+    YV12_BUFFER_CONFIG *frame_to_show;
+
+    YV12_BUFFER_CONFIG yv12_fb[NUM_YV12_BUFFERS];
+    int fb_idx_ref_cnt[NUM_YV12_BUFFERS];
+    int new_fb_idx, lst_fb_idx, gld_fb_idx, alt_fb_idx;
+
+    YV12_BUFFER_CONFIG temp_scale_frame;
+
+#if CONFIG_POSTPROC
+    YV12_BUFFER_CONFIG post_proc_buffer;
+    YV12_BUFFER_CONFIG post_proc_buffer_int;
+    int post_proc_buffer_int_used;
+#endif
+
+    FRAME_TYPE last_frame_type;  /* Save last frame's frame type for motion search. */
+    FRAME_TYPE frame_type;
+
+    int show_frame;
+
+    int frame_flags;
+    int MBs;
+    int mb_rows;
+    int mb_cols;
+    int mode_info_stride;
+
+    /* profile settings */
+    int mb_no_coeff_skip;
+    int no_lpf;
+    int use_bilinear_mc_filter;
+    int full_pixel;
+
+    int base_qindex;
+    int last_kf_gf_q;  /* Q used on the last GF or KF */
+
+    int y1dc_delta_q;
+    int y2dc_delta_q;
+    int y2ac_delta_q;
+    int uvdc_delta_q;
+    int uvac_delta_q;
+
+    unsigned int frames_since_golden;
+    unsigned int frames_till_alt_ref_frame;
+
+    /* We allocate a MODE_INFO struct for each macroblock, together with
+       an extra row on top and column on the left to simplify prediction. */
+
+    MODE_INFO *mip; /* Base of allocated array */
+    MODE_INFO *mi;  /* Corresponds to upper left visible macroblock */
+    MODE_INFO *prev_mip; /* MODE_INFO array 'mip' from last decoded frame */
+    MODE_INFO *prev_mi;  /* 'mi' from last frame (points into prev_mip) */
+
+
+    INTERPOLATIONFILTERTYPE mcomp_filter_type;
+    LOOPFILTERTYPE filter_type;
+
+    loop_filter_info_n lf_info;
+
+    int filter_level;
+    int last_sharpness_level;
+    int sharpness_level;
+
+    int refresh_last_frame;       /* Two state 0 = NO, 1 = YES */
+    int refresh_golden_frame;     /* Two state 0 = NO, 1 = YES */
+    int refresh_alt_ref_frame;     /* Two state 0 = NO, 1 = YES */
+
+    int copy_buffer_to_gf;         /* 0 none, 1 Last to GF, 2 ARF to GF */
+    int copy_buffer_to_arf;        /* 0 none, 1 Last to ARF, 2 GF to ARF */
+
+    int refresh_entropy_probs;    /* Two state 0 = NO, 1 = YES */
+
+    int ref_frame_sign_bias[MAX_REF_FRAMES];    /* Two state 0, 1 */
+
+    /* Y,U,V,Y2 */
+    ENTROPY_CONTEXT_PLANES *above_context;   /* row of context for each plane */
+    ENTROPY_CONTEXT_PLANES left_context;  /* (up to) 4 contexts "" */
+
+
+    /* keyframe block modes are predicted by their above, left neighbors */
+
+    vp8_prob kf_bmode_prob [VP8_BINTRAMODES] [VP8_BINTRAMODES] [VP8_BINTRAMODES-1];
+    vp8_prob kf_ymode_prob [VP8_YMODES-1];  /* keyframe "" */
+    vp8_prob kf_uv_mode_prob [VP8_UV_MODES-1];
+
+
+    FRAME_CONTEXT lfc; /* last frame entropy */
+    FRAME_CONTEXT fc;  /* this frame entropy */
+
+    unsigned int current_video_frame;
+
+    int near_boffset[3];
+    int version;
+
+    TOKEN_PARTITION multi_token_partition;
+
+#ifdef PACKET_TESTING
+    VP8_HEADER oh;
+#endif
+    double bitrate;
+    double framerate;
+
+#if CONFIG_MULTITHREAD
+    int processor_core_count;
+#endif
+#if CONFIG_POSTPROC
+    struct postproc_state  postproc_state;
+#endif
+    int cpu_caps;
+} VP8_COMMON;
+
+#endif
diff --git a/vp8/common/onyxd.h b/vp8/common/onyxd.h
new file mode 100644 (file)
index 0000000..35a8b6e
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_VP8D_H
+#define __INC_VP8D_H
+
+
+/* Create/destroy static data structures. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#include "vpx_scale/yv12config.h"
+#include "ppflags.h"
+#include "vpx_ports/mem.h"
+#include "vpx/vpx_codec.h"
+
+    struct VP8D_COMP;
+
+    typedef struct
+    {
+        int     Width;
+        int     Height;
+        int     Version;
+        int     postprocess;
+        int     max_threads;
+        int     error_concealment;
+        int     input_fragments;
+    } VP8D_CONFIG;
+    typedef enum
+    {
+        VP8_LAST_FLAG = 1,
+        VP8_GOLD_FLAG = 2,
+        VP8_ALT_FLAG = 4
+    } VP8_REFFRAME;
+
+    typedef enum
+    {
+        VP8D_OK = 0
+    } VP8D_SETTING;
+
+    void vp8dx_initialize(void);
+
+    void vp8dx_set_setting(struct VP8D_COMP* comp, VP8D_SETTING oxst, int x);
+
+    int vp8dx_get_setting(struct VP8D_COMP* comp, VP8D_SETTING oxst);
+
+    int vp8dx_receive_compressed_data(struct VP8D_COMP* comp, unsigned long size, const unsigned char *dest, int64_t time_stamp);
+    int vp8dx_get_raw_frame(struct VP8D_COMP* comp, YV12_BUFFER_CONFIG *sd, int64_t *time_stamp, int64_t *time_end_stamp, vp8_ppflags_t *flags);
+
+    vpx_codec_err_t vp8dx_get_reference(struct VP8D_COMP* comp, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd);
+    vpx_codec_err_t vp8dx_set_reference(struct VP8D_COMP* comp, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd);
+
+    struct VP8D_COMP* vp8dx_create_decompressor(VP8D_CONFIG *oxcf);
+
+    void vp8dx_remove_decompressor(struct VP8D_COMP* comp);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/vp8/common/postproc.c b/vp8/common/postproc.c
new file mode 100644 (file)
index 0000000..ccf6ad7
--- /dev/null
@@ -0,0 +1,1173 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "vpx_scale/yv12config.h"
+#include "postproc.h"
+#include "common.h"
+#include "vpx_scale/vpxscale.h"
+#include "systemdependent.h"
+
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define RGB_TO_YUV(t)                                                                       \
+    ( (0.257*(float)(t>>16)) + (0.504*(float)(t>>8&0xff)) + (0.098*(float)(t&0xff)) + 16),  \
+    (-(0.148*(float)(t>>16)) - (0.291*(float)(t>>8&0xff)) + (0.439*(float)(t&0xff)) + 128), \
+    ( (0.439*(float)(t>>16)) - (0.368*(float)(t>>8&0xff)) - (0.071*(float)(t&0xff)) + 128)
+
+/* global constants */
+#if CONFIG_POSTPROC_VISUALIZER
+static const unsigned char MB_PREDICTION_MODE_colors[MB_MODE_COUNT][3] =
+{
+    { RGB_TO_YUV(0x98FB98) },   /* PaleGreen */
+    { RGB_TO_YUV(0x00FF00) },   /* Green */
+    { RGB_TO_YUV(0xADFF2F) },   /* GreenYellow */
+    { RGB_TO_YUV(0x228B22) },   /* ForestGreen */
+    { RGB_TO_YUV(0x006400) },   /* DarkGreen */
+    { RGB_TO_YUV(0x98F5FF) },   /* Cadet Blue */
+    { RGB_TO_YUV(0x6CA6CD) },   /* Sky Blue */
+    { RGB_TO_YUV(0x00008B) },   /* Dark blue */
+    { RGB_TO_YUV(0x551A8B) },   /* Purple */
+    { RGB_TO_YUV(0xFF0000) }    /* Red */
+};
+
+static const unsigned char B_PREDICTION_MODE_colors[B_MODE_COUNT][3] =
+{
+    { RGB_TO_YUV(0x6633ff) },   /* Purple */
+    { RGB_TO_YUV(0xcc33ff) },   /* Magenta */
+    { RGB_TO_YUV(0xff33cc) },   /* Pink */
+    { RGB_TO_YUV(0xff3366) },   /* Coral */
+    { RGB_TO_YUV(0x3366ff) },   /* Blue */
+    { RGB_TO_YUV(0xed00f5) },   /* Dark Blue */
+    { RGB_TO_YUV(0x2e00b8) },   /* Dark Purple */
+    { RGB_TO_YUV(0xff6633) },   /* Orange */
+    { RGB_TO_YUV(0x33ccff) },   /* Light Blue */
+    { RGB_TO_YUV(0x8ab800) },   /* Green */
+    { RGB_TO_YUV(0xffcc33) },   /* Light Orange */
+    { RGB_TO_YUV(0x33ffcc) },   /* Aqua */
+    { RGB_TO_YUV(0x66ff33) },   /* Light Green */
+    { RGB_TO_YUV(0xccff33) },   /* Yellow */
+};
+
+static const unsigned char MV_REFERENCE_FRAME_colors[MAX_REF_FRAMES][3] =
+{
+    { RGB_TO_YUV(0x00ff00) },   /* Blue */
+    { RGB_TO_YUV(0x0000ff) },   /* Green */
+    { RGB_TO_YUV(0xffff00) },   /* Yellow */
+    { RGB_TO_YUV(0xff0000) },   /* Red */
+};
+#endif
+
+static const short kernel5[] =
+{
+    1, 1, 4, 1, 1
+};
+
+const short vp8_rv[] =
+{
+    8, 5, 2, 2, 8, 12, 4, 9, 8, 3,
+    0, 3, 9, 0, 0, 0, 8, 3, 14, 4,
+    10, 1, 11, 14, 1, 14, 9, 6, 12, 11,
+    8, 6, 10, 0, 0, 8, 9, 0, 3, 14,
+    8, 11, 13, 4, 2, 9, 0, 3, 9, 6,
+    1, 2, 3, 14, 13, 1, 8, 2, 9, 7,
+    3, 3, 1, 13, 13, 6, 6, 5, 2, 7,
+    11, 9, 11, 8, 7, 3, 2, 0, 13, 13,
+    14, 4, 12, 5, 12, 10, 8, 10, 13, 10,
+    4, 14, 4, 10, 0, 8, 11, 1, 13, 7,
+    7, 14, 6, 14, 13, 2, 13, 5, 4, 4,
+    0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
+    8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
+    3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
+    3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
+    13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
+    5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
+    9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
+    4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
+    3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
+    11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
+    5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
+    0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
+    10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
+    4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
+    0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
+    8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
+    3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
+    3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
+    13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
+    5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
+    9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
+    4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
+    3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
+    11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
+    5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
+    0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
+    10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
+    4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
+    3, 8, 3, 7, 8, 5, 11, 4, 12, 3,
+    11, 9, 14, 8, 14, 13, 4, 3, 1, 2,
+    14, 6, 5, 4, 4, 11, 4, 6, 2, 1,
+    5, 8, 8, 12, 13, 5, 14, 10, 12, 13,
+    0, 9, 5, 5, 11, 10, 13, 9, 10, 13,
+};
+
+extern void vp8_blit_text(const char *msg, unsigned char *address, const int pitch);
+extern void vp8_blit_line(int x0, int x1, int y0, int y1, unsigned char *image, const int pitch);
+/***********************************************************************************************************
+ */
+void vp8_post_proc_down_and_across_c
+(
+    unsigned char *src_ptr,
+    unsigned char *dst_ptr,
+    int src_pixels_per_line,
+    int dst_pixels_per_line,
+    int rows,
+    int cols,
+    int flimit
+)
+{
+    unsigned char *p_src, *p_dst;
+    int row;
+    int col;
+    int i;
+    int v;
+    int pitch = src_pixels_per_line;
+    unsigned char d[8];
+    (void)dst_pixels_per_line;
+
+    for (row = 0; row < rows; row++)
+    {
+        /* post_proc_down for one row */
+        p_src = src_ptr;
+        p_dst = dst_ptr;
+
+        for (col = 0; col < cols; col++)
+        {
+
+            int kernel = 4;
+            int v = p_src[col];
+
+            for (i = -2; i <= 2; i++)
+            {
+                if (abs(v - p_src[col+i*pitch]) > flimit)
+                    goto down_skip_convolve;
+
+                kernel += kernel5[2+i] * p_src[col+i*pitch];
+            }
+
+            v = (kernel >> 3);
+        down_skip_convolve:
+            p_dst[col] = v;
+        }
+
+        /* now post_proc_across */
+        p_src = dst_ptr;
+        p_dst = dst_ptr;
+
+        for (i = -8; i<0; i++)
+          p_src[i]=p_src[0];
+
+        for (i = cols; i<cols+8; i++)
+          p_src[i]=p_src[cols-1];
+
+        for (i = 0; i < 8; i++)
+            d[i] = p_src[i];
+
+        for (col = 0; col < cols; col++)
+        {
+            int kernel = 4;
+            v = p_src[col];
+
+            d[col&7] = v;
+
+            for (i = -2; i <= 2; i++)
+            {
+                if (abs(v - p_src[col+i]) > flimit)
+                    goto across_skip_convolve;
+
+                kernel += kernel5[2+i] * p_src[col+i];
+            }
+
+            d[col&7] = (kernel >> 3);
+        across_skip_convolve:
+
+            if (col >= 2)
+                p_dst[col-2] = d[(col-2)&7];
+        }
+
+        /* handle the last two pixels */
+        p_dst[col-2] = d[(col-2)&7];
+        p_dst[col-1] = d[(col-1)&7];
+
+
+        /* next row */
+        src_ptr += pitch;
+        dst_ptr += pitch;
+    }
+}
+
+static int q2mbl(int x)
+{
+    if (x < 20) x = 20;
+
+    x = 50 + (x - 50) * 10 / 8;
+    return x * x / 3;
+}
+void vp8_mbpost_proc_across_ip_c(unsigned char *src, int pitch, int rows, int cols, int flimit)
+{
+    int r, c, i;
+
+    unsigned char *s = src;
+    unsigned char d[16];
+
+    for (r = 0; r < rows; r++)
+    {
+        int sumsq = 0;
+        int sum   = 0;
+
+        for (i = -8; i<0; i++)
+          s[i]=s[0];
+
+        // 17 avoids valgrind warning - we buffer values in c in d
+        // and only write them when we've read 8 ahead...
+        for (i = cols; i<cols+17; i++)
+          s[i]=s[cols-1];
+
+        for (i = -8; i <= 6; i++)
+        {
+            sumsq += s[i] * s[i];
+            sum   += s[i];
+            d[i+8] = 0;
+        }
+
+        for (c = 0; c < cols + 8; c++)
+        {
+            int x = s[c+7] - s[c-8];
+            int y = s[c+7] + s[c-8];
+
+            sum  += x;
+            sumsq += x * y;
+
+            d[c&15] = s[c];
+
+            if (sumsq * 15 - sum * sum < flimit)
+            {
+                d[c&15] = (8 + sum + s[c]) >> 4;
+            }
+
+            s[c-8] = d[(c-8)&15];
+        }
+
+        s += pitch;
+    }
+}
+
+
+
+
+
+void vp8_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols, int flimit)
+{
+    int r, c, i;
+    const short *rv3 = &vp8_rv[63&rand()];
+
+    for (c = 0; c < cols; c++ )
+    {
+        unsigned char *s = &dst[c];
+        int sumsq = 0;
+        int sum   = 0;
+        unsigned char d[16];
+        const short *rv2 = rv3 + ((c * 17) & 127);
+
+        for (i = -8; i < 0; i++)
+          s[i*pitch]=s[0];
+
+        // 17 avoids valgrind warning - we buffer values in c in d
+        // and only write them when we've read 8 ahead...
+        for (i = rows; i < rows+17; i++)
+          s[i*pitch]=s[(rows-1)*pitch];
+
+        for (i = -8; i <= 6; i++)
+        {
+            sumsq += s[i*pitch] * s[i*pitch];
+            sum   += s[i*pitch];
+        }
+
+        for (r = 0; r < rows + 8; r++)
+        {
+            sumsq += s[7*pitch] * s[ 7*pitch] - s[-8*pitch] * s[-8*pitch];
+            sum  += s[7*pitch] - s[-8*pitch];
+            d[r&15] = s[0];
+
+            if (sumsq * 15 - sum * sum < flimit)
+            {
+                d[r&15] = (rv2[r&127] + sum + s[0]) >> 4;
+            }
+
+            s[-8*pitch] = d[(r-8)&15];
+            s += pitch;
+        }
+    }
+}
+
+
+static void vp8_deblock_and_de_macro_block(YV12_BUFFER_CONFIG         *source,
+        YV12_BUFFER_CONFIG         *post,
+        int                         q,
+        int                         low_var_thresh,
+        int                         flag)
+{
+    double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
+    int ppl = (int)(level + .5);
+    (void) low_var_thresh;
+    (void) flag;
+
+    vp8_post_proc_down_and_across(source->y_buffer, post->y_buffer, source->y_stride,  post->y_stride, source->y_height, source->y_width,  ppl);
+    vp8_mbpost_proc_across_ip(post->y_buffer, post->y_stride, post->y_height, post->y_width, q2mbl(q));
+    vp8_mbpost_proc_down(post->y_buffer, post->y_stride, post->y_height, post->y_width, q2mbl(q));
+
+    vp8_post_proc_down_and_across(source->u_buffer, post->u_buffer, source->uv_stride, post->uv_stride, source->uv_height, source->uv_width, ppl);
+    vp8_post_proc_down_and_across(source->v_buffer, post->v_buffer, source->uv_stride, post->uv_stride, source->uv_height, source->uv_width, ppl);
+
+}
+
+void vp8_deblock(YV12_BUFFER_CONFIG         *source,
+                 YV12_BUFFER_CONFIG         *post,
+                 int                         q,
+                 int                         low_var_thresh,
+                 int                         flag)
+{
+    double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
+    int ppl = (int)(level + .5);
+    (void) low_var_thresh;
+    (void) flag;
+
+    vp8_post_proc_down_and_across(source->y_buffer, post->y_buffer, source->y_stride,  post->y_stride, source->y_height, source->y_width,   ppl);
+    vp8_post_proc_down_and_across(source->u_buffer, post->u_buffer, source->uv_stride, post->uv_stride,  source->uv_height, source->uv_width, ppl);
+    vp8_post_proc_down_and_across(source->v_buffer, post->v_buffer, source->uv_stride, post->uv_stride, source->uv_height, source->uv_width, ppl);
+}
+
+#if !(CONFIG_TEMPORAL_DENOISING)
+void vp8_de_noise(YV12_BUFFER_CONFIG         *source,
+                  YV12_BUFFER_CONFIG         *post,
+                  int                         q,
+                  int                         low_var_thresh,
+                  int                         flag)
+{
+    double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
+    int ppl = (int)(level + .5);
+    (void) post;
+    (void) low_var_thresh;
+    (void) flag;
+
+    vp8_post_proc_down_and_across(
+        source->y_buffer + 2 * source->y_stride + 2,
+        source->y_buffer + 2 * source->y_stride + 2,
+        source->y_stride,
+        source->y_stride,
+        source->y_height - 4,
+        source->y_width - 4,
+        ppl);
+    vp8_post_proc_down_and_across(
+        source->u_buffer + 2 * source->uv_stride + 2,
+        source->u_buffer + 2 * source->uv_stride + 2,
+        source->uv_stride,
+        source->uv_stride,
+        source->uv_height - 4,
+        source->uv_width - 4, ppl);
+    vp8_post_proc_down_and_across(
+        source->v_buffer + 2 * source->uv_stride + 2,
+        source->v_buffer + 2 * source->uv_stride + 2,
+        source->uv_stride,
+        source->uv_stride,
+        source->uv_height - 4,
+        source->uv_width - 4, ppl);
+
+}
+#endif
+
+double vp8_gaussian(double sigma, double mu, double x)
+{
+    return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
+           (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
+}
+
+static void fillrd(struct postproc_state *state, int q, int a)
+{
+    char char_dist[300];
+
+    double sigma;
+    int ai = a, qi = q, i;
+
+    vp8_clear_system_state();
+
+
+    sigma = ai + .5 + .6 * (63 - qi) / 63.0;
+
+    /* set up a lookup table of 256 entries that matches
+     * a gaussian distribution with sigma determined by q.
+     */
+    {
+        double i;
+        int next, j;
+
+        next = 0;
+
+        for (i = -32; i < 32; i++)
+        {
+            int a = (int)(.5 + 256 * vp8_gaussian(sigma, 0, i));
+
+            if (a)
+            {
+                for (j = 0; j < a; j++)
+                {
+                    char_dist[next+j] = (char) i;
+                }
+
+                next = next + j;
+            }
+
+        }
+
+        for (next = next; next < 256; next++)
+            char_dist[next] = 0;
+
+    }
+
+    for (i = 0; i < 3072; i++)
+    {
+        state->noise[i] = char_dist[rand() & 0xff];
+    }
+
+    for (i = 0; i < 16; i++)
+    {
+        state->blackclamp[i] = -char_dist[0];
+        state->whiteclamp[i] = -char_dist[0];
+        state->bothclamp[i] = -2 * char_dist[0];
+    }
+
+    state->last_q = q;
+    state->last_noise = a;
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : plane_add_noise_c
+ *
+ *  INPUTS        : unsigned char *Start    starting address of buffer to add gaussian
+ *                                  noise to
+ *                  unsigned int Width    width of plane
+ *                  unsigned int Height   height of plane
+ *                  int  Pitch    distance between subsequent lines of frame
+ *                  int  q        quantizer used to determine amount of noise
+ *                                  to add
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void.
+ *
+ *  FUNCTION      : adds gaussian noise to a plane of pixels
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+void vp8_plane_add_noise_c(unsigned char *Start, char *noise,
+                           char blackclamp[16],
+                           char whiteclamp[16],
+                           char bothclamp[16],
+                           unsigned int Width, unsigned int Height, int Pitch)
+{
+    unsigned int i, j;
+
+    for (i = 0; i < Height; i++)
+    {
+        unsigned char *Pos = Start + i * Pitch;
+        char  *Ref = (char *)(noise + (rand() & 0xff));
+
+        for (j = 0; j < Width; j++)
+        {
+            if (Pos[j] < blackclamp[0])
+                Pos[j] = blackclamp[0];
+
+            if (Pos[j] > 255 + whiteclamp[0])
+                Pos[j] = 255 + whiteclamp[0];
+
+            Pos[j] += Ref[j];
+        }
+    }
+}
+
+/* Blend the macro block with a solid colored square.  Leave the
+ * edges unblended to give distinction to macro blocks in areas
+ * filled with the same color block.
+ */
+void vp8_blend_mb_inner_c (unsigned char *y, unsigned char *u, unsigned char *v,
+                        int y1, int u1, int v1, int alpha, int stride)
+{
+    int i, j;
+    int y1_const = y1*((1<<16)-alpha);
+    int u1_const = u1*((1<<16)-alpha);
+    int v1_const = v1*((1<<16)-alpha);
+
+    y += 2*stride + 2;
+    for (i = 0; i < 12; i++)
+    {
+        for (j = 0; j < 12; j++)
+        {
+            y[j] = (y[j]*alpha + y1_const)>>16;
+        }
+        y += stride;
+    }
+
+    stride >>= 1;
+
+    u += stride + 1;
+    v += stride + 1;
+
+    for (i = 0; i < 6; i++)
+    {
+        for (j = 0; j < 6; j++)
+        {
+            u[j] = (u[j]*alpha + u1_const)>>16;
+            v[j] = (v[j]*alpha + v1_const)>>16;
+        }
+        u += stride;
+        v += stride;
+    }
+}
+
+/* Blend only the edge of the macro block.  Leave center
+ * unblended to allow for other visualizations to be layered.
+ */
+void vp8_blend_mb_outer_c (unsigned char *y, unsigned char *u, unsigned char *v,
+                        int y1, int u1, int v1, int alpha, int stride)
+{
+    int i, j;
+    int y1_const = y1*((1<<16)-alpha);
+    int u1_const = u1*((1<<16)-alpha);
+    int v1_const = v1*((1<<16)-alpha);
+
+    for (i = 0; i < 2; i++)
+    {
+        for (j = 0; j < 16; j++)
+        {
+            y[j] = (y[j]*alpha + y1_const)>>16;
+        }
+        y += stride;
+    }
+
+    for (i = 0; i < 12; i++)
+    {
+        y[0]  = (y[0]*alpha  + y1_const)>>16;
+        y[1]  = (y[1]*alpha  + y1_const)>>16;
+        y[14] = (y[14]*alpha + y1_const)>>16;
+        y[15] = (y[15]*alpha + y1_const)>>16;
+        y += stride;
+    }
+
+    for (i = 0; i < 2; i++)
+    {
+        for (j = 0; j < 16; j++)
+        {
+            y[j] = (y[j]*alpha + y1_const)>>16;
+        }
+        y += stride;
+    }
+
+    stride >>= 1;
+
+    for (j = 0; j < 8; j++)
+    {
+        u[j] = (u[j]*alpha + u1_const)>>16;
+        v[j] = (v[j]*alpha + v1_const)>>16;
+    }
+    u += stride;
+    v += stride;
+
+    for (i = 0; i < 6; i++)
+    {
+        u[0] = (u[0]*alpha + u1_const)>>16;
+        v[0] = (v[0]*alpha + v1_const)>>16;
+
+        u[7] = (u[7]*alpha + u1_const)>>16;
+        v[7] = (v[7]*alpha + v1_const)>>16;
+
+        u += stride;
+        v += stride;
+    }
+
+    for (j = 0; j < 8; j++)
+    {
+        u[j] = (u[j]*alpha + u1_const)>>16;
+        v[j] = (v[j]*alpha + v1_const)>>16;
+    }
+}
+
+void vp8_blend_b_c (unsigned char *y, unsigned char *u, unsigned char *v,
+                        int y1, int u1, int v1, int alpha, int stride)
+{
+    int i, j;
+    int y1_const = y1*((1<<16)-alpha);
+    int u1_const = u1*((1<<16)-alpha);
+    int v1_const = v1*((1<<16)-alpha);
+
+    for (i = 0; i < 4; i++)
+    {
+        for (j = 0; j < 4; j++)
+        {
+            y[j] = (y[j]*alpha + y1_const)>>16;
+        }
+        y += stride;
+    }
+
+    stride >>= 1;
+
+    for (i = 0; i < 2; i++)
+    {
+        for (j = 0; j < 2; j++)
+        {
+            u[j] = (u[j]*alpha + u1_const)>>16;
+            v[j] = (v[j]*alpha + v1_const)>>16;
+        }
+        u += stride;
+        v += stride;
+    }
+}
+
+static void constrain_line (int x0, int *x1, int y0, int *y1, int width, int height)
+{
+    int dx;
+    int dy;
+
+    if (*x1 > width)
+    {
+        dx = *x1 - x0;
+        dy = *y1 - y0;
+
+        *x1 = width;
+        if (dx)
+            *y1 = ((width-x0)*dy)/dx + y0;
+    }
+    if (*x1 < 0)
+    {
+        dx = *x1 - x0;
+        dy = *y1 - y0;
+
+        *x1 = 0;
+        if (dx)
+            *y1 = ((0-x0)*dy)/dx + y0;
+    }
+    if (*y1 > height)
+    {
+        dx = *x1 - x0;
+        dy = *y1 - y0;
+
+        *y1 = height;
+        if (dy)
+            *x1 = ((height-y0)*dx)/dy + x0;
+    }
+    if (*y1 < 0)
+    {
+        dx = *x1 - x0;
+        dy = *y1 - y0;
+
+        *y1 = 0;
+        if (dy)
+            *x1 = ((0-y0)*dx)/dy + x0;
+    }
+}
+
+#if CONFIG_POSTPROC
+int vp8_post_proc_frame(VP8_COMMON *oci, YV12_BUFFER_CONFIG *dest, vp8_ppflags_t *ppflags)
+{
+    int q = oci->filter_level * 10 / 6;
+    int flags = ppflags->post_proc_flag;
+    int deblock_level = ppflags->deblocking_level;
+    int noise_level = ppflags->noise_level;
+
+    if (!oci->frame_to_show)
+        return -1;
+
+    if (q > 63)
+        q = 63;
+
+    if (!flags)
+    {
+        *dest = *oci->frame_to_show;
+
+        /* handle problem with extending borders */
+        dest->y_width = oci->Width;
+        dest->y_height = oci->Height;
+        dest->uv_height = dest->y_height / 2;
+        oci->postproc_state.last_base_qindex = oci->base_qindex;
+        oci->postproc_state.last_frame_valid = 1;
+        return 0;
+    }
+
+    /* Allocate post_proc_buffer_int if needed */
+    if ((flags & VP8D_MFQE) && !oci->post_proc_buffer_int_used)
+    {
+        if ((flags & VP8D_DEBLOCK) || (flags & VP8D_DEMACROBLOCK))
+        {
+            int width = (oci->Width + 15) & ~15;
+            int height = (oci->Height + 15) & ~15;
+
+            if (vp8_yv12_alloc_frame_buffer(&oci->post_proc_buffer_int,
+                                            width, height, VP8BORDERINPIXELS))
+                vpx_internal_error(&oci->error, VPX_CODEC_MEM_ERROR,
+                                   "Failed to allocate MFQE framebuffer");
+
+            oci->post_proc_buffer_int_used = 1;
+
+            // insure that postproc is set to all 0's so that post proc
+            // doesn't pull random data in from edge
+            vpx_memset((&oci->post_proc_buffer_int)->buffer_alloc,128,(&oci->post_proc_buffer)->frame_size);
+
+        }
+    }
+
+#if ARCH_X86||ARCH_X86_64
+    vpx_reset_mmx_state();
+#endif
+
+    if ((flags & VP8D_MFQE) &&
+         oci->postproc_state.last_frame_valid &&
+         oci->current_video_frame >= 2 &&
+         oci->base_qindex - oci->postproc_state.last_base_qindex >= 10)
+    {
+        vp8_multiframe_quality_enhance(oci);
+        if (((flags & VP8D_DEBLOCK) || (flags & VP8D_DEMACROBLOCK)) &&
+            oci->post_proc_buffer_int_used)
+        {
+            vp8_yv12_copy_frame(&oci->post_proc_buffer, &oci->post_proc_buffer_int);
+            if (flags & VP8D_DEMACROBLOCK)
+            {
+                vp8_deblock_and_de_macro_block(&oci->post_proc_buffer_int, &oci->post_proc_buffer,
+                                               q + (deblock_level - 5) * 10, 1, 0);
+            }
+            else if (flags & VP8D_DEBLOCK)
+            {
+                vp8_deblock(&oci->post_proc_buffer_int, &oci->post_proc_buffer,
+                            q, 1, 0);
+            }
+        }
+        /* Move partially towards the base q of the previous frame */
+        oci->postproc_state.last_base_qindex = (3*oci->postproc_state.last_base_qindex + oci->base_qindex)>>2;
+    }
+    else if (flags & VP8D_DEMACROBLOCK)
+    {
+        vp8_deblock_and_de_macro_block(oci->frame_to_show, &oci->post_proc_buffer,
+                                       q + (deblock_level - 5) * 10, 1, 0);
+        oci->postproc_state.last_base_qindex = oci->base_qindex;
+    }
+    else if (flags & VP8D_DEBLOCK)
+    {
+        vp8_deblock(oci->frame_to_show, &oci->post_proc_buffer,
+                    q, 1, 0);
+        oci->postproc_state.last_base_qindex = oci->base_qindex;
+    }
+    else
+    {
+        vp8_yv12_copy_frame(oci->frame_to_show, &oci->post_proc_buffer);
+        oci->postproc_state.last_base_qindex = oci->base_qindex;
+    }
+    oci->postproc_state.last_frame_valid = 1;
+
+    if (flags & VP8D_ADDNOISE)
+    {
+        if (oci->postproc_state.last_q != q
+            || oci->postproc_state.last_noise != noise_level)
+        {
+            fillrd(&oci->postproc_state, 63 - q, noise_level);
+        }
+
+        vp8_plane_add_noise
+        (oci->post_proc_buffer.y_buffer,
+         oci->postproc_state.noise,
+         oci->postproc_state.blackclamp,
+         oci->postproc_state.whiteclamp,
+         oci->postproc_state.bothclamp,
+         oci->post_proc_buffer.y_width, oci->post_proc_buffer.y_height,
+         oci->post_proc_buffer.y_stride);
+    }
+
+#if CONFIG_POSTPROC_VISUALIZER
+    if (flags & VP8D_DEBUG_TXT_FRAME_INFO)
+    {
+        char message[512];
+        sprintf(message, "F%1dG%1dQ%3dF%3dP%d_s%dx%d",
+                (oci->frame_type == KEY_FRAME),
+                oci->refresh_golden_frame,
+                oci->base_qindex,
+                oci->filter_level,
+                flags,
+                oci->mb_cols, oci->mb_rows);
+        vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
+    }
+
+    if (flags & VP8D_DEBUG_TXT_MBLK_MODES)
+    {
+        int i, j;
+        unsigned char *y_ptr;
+        YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
+        int mb_rows = post->y_height >> 4;
+        int mb_cols = post->y_width  >> 4;
+        int mb_index = 0;
+        MODE_INFO *mi = oci->mi;
+
+        y_ptr = post->y_buffer + 4 * post->y_stride + 4;
+
+        /* vp8_filter each macro block */
+        for (i = 0; i < mb_rows; i++)
+        {
+            for (j = 0; j < mb_cols; j++)
+            {
+                char zz[4];
+
+                sprintf(zz, "%c", mi[mb_index].mbmi.mode + 'a');
+
+                vp8_blit_text(zz, y_ptr, post->y_stride);
+                mb_index ++;
+                y_ptr += 16;
+            }
+
+            mb_index ++; /* border */
+            y_ptr += post->y_stride  * 16 - post->y_width;
+
+        }
+    }
+
+    if (flags & VP8D_DEBUG_TXT_DC_DIFF)
+    {
+        int i, j;
+        unsigned char *y_ptr;
+        YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
+        int mb_rows = post->y_height >> 4;
+        int mb_cols = post->y_width  >> 4;
+        int mb_index = 0;
+        MODE_INFO *mi = oci->mi;
+
+        y_ptr = post->y_buffer + 4 * post->y_stride + 4;
+
+        /* vp8_filter each macro block */
+        for (i = 0; i < mb_rows; i++)
+        {
+            for (j = 0; j < mb_cols; j++)
+            {
+                char zz[4];
+                int dc_diff = !(mi[mb_index].mbmi.mode != B_PRED &&
+                              mi[mb_index].mbmi.mode != SPLITMV &&
+                              mi[mb_index].mbmi.mb_skip_coeff);
+
+                if (oci->frame_type == KEY_FRAME)
+                    sprintf(zz, "a");
+                else
+                    sprintf(zz, "%c", dc_diff + '0');
+
+                vp8_blit_text(zz, y_ptr, post->y_stride);
+                mb_index ++;
+                y_ptr += 16;
+            }
+
+            mb_index ++; /* border */
+            y_ptr += post->y_stride  * 16 - post->y_width;
+
+        }
+    }
+
+    if (flags & VP8D_DEBUG_TXT_RATE_INFO)
+    {
+        char message[512];
+        sprintf(message, "Bitrate: %10.2f frame_rate: %10.2f ", oci->bitrate, oci->framerate);
+        vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
+    }
+
+    /* Draw motion vectors */
+    if ((flags & VP8D_DEBUG_DRAW_MV) && ppflags->display_mv_flag)
+    {
+        YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
+        int width  = post->y_width;
+        int height = post->y_height;
+        unsigned char *y_buffer = oci->post_proc_buffer.y_buffer;
+        int y_stride = oci->post_proc_buffer.y_stride;
+        MODE_INFO *mi = oci->mi;
+        int x0, y0;
+
+        for (y0 = 0; y0 < height; y0 += 16)
+        {
+            for (x0 = 0; x0 < width; x0 += 16)
+            {
+                int x1, y1;
+
+                if (!(ppflags->display_mv_flag & (1<<mi->mbmi.mode)))
+                {
+                    mi++;
+                    continue;
+                }
+
+                if (mi->mbmi.mode == SPLITMV)
+                {
+                    switch (mi->mbmi.partitioning)
+                    {
+                        case 0 :    /* mv_top_bottom */
+                        {
+                            union b_mode_info *bmi = &mi->bmi[0];
+                            MV *mv = &bmi->mv.as_mv;
+
+                            x1 = x0 + 8 + (mv->col >> 3);
+                            y1 = y0 + 4 + (mv->row >> 3);
+
+                            constrain_line (x0+8, &x1, y0+4, &y1, width, height);
+                            vp8_blit_line  (x0+8,  x1, y0+4,  y1, y_buffer, y_stride);
+
+                            bmi = &mi->bmi[8];
+
+                            x1 = x0 + 8 + (mv->col >> 3);
+                            y1 = y0 +12 + (mv->row >> 3);
+
+                            constrain_line (x0+8, &x1, y0+12, &y1, width, height);
+                            vp8_blit_line  (x0+8,  x1, y0+12,  y1, y_buffer, y_stride);
+
+                            break;
+                        }
+                        case 1 :    /* mv_left_right */
+                        {
+                            union b_mode_info *bmi = &mi->bmi[0];
+                            MV *mv = &bmi->mv.as_mv;
+
+                            x1 = x0 + 4 + (mv->col >> 3);
+                            y1 = y0 + 8 + (mv->row >> 3);
+
+                            constrain_line (x0+4, &x1, y0+8, &y1, width, height);
+                            vp8_blit_line  (x0+4,  x1, y0+8,  y1, y_buffer, y_stride);
+
+                            bmi = &mi->bmi[2];
+
+                            x1 = x0 +12 + (mv->col >> 3);
+                            y1 = y0 + 8 + (mv->row >> 3);
+
+                            constrain_line (x0+12, &x1, y0+8, &y1, width, height);
+                            vp8_blit_line  (x0+12,  x1, y0+8,  y1, y_buffer, y_stride);
+
+                            break;
+                        }
+                        case 2 :    /* mv_quarters   */
+                        {
+                            union b_mode_info *bmi = &mi->bmi[0];
+                            MV *mv = &bmi->mv.as_mv;
+
+                            x1 = x0 + 4 + (mv->col >> 3);
+                            y1 = y0 + 4 + (mv->row >> 3);
+
+                            constrain_line (x0+4, &x1, y0+4, &y1, width, height);
+                            vp8_blit_line  (x0+4,  x1, y0+4,  y1, y_buffer, y_stride);
+
+                            bmi = &mi->bmi[2];
+
+                            x1 = x0 +12 + (mv->col >> 3);
+                            y1 = y0 + 4 + (mv->row >> 3);
+
+                            constrain_line (x0+12, &x1, y0+4, &y1, width, height);
+                            vp8_blit_line  (x0+12,  x1, y0+4,  y1, y_buffer, y_stride);
+
+                            bmi = &mi->bmi[8];
+
+                            x1 = x0 + 4 + (mv->col >> 3);
+                            y1 = y0 +12 + (mv->row >> 3);
+
+                            constrain_line (x0+4, &x1, y0+12, &y1, width, height);
+                            vp8_blit_line  (x0+4,  x1, y0+12,  y1, y_buffer, y_stride);
+
+                            bmi = &mi->bmi[10];
+
+                            x1 = x0 +12 + (mv->col >> 3);
+                            y1 = y0 +12 + (mv->row >> 3);
+
+                            constrain_line (x0+12, &x1, y0+12, &y1, width, height);
+                            vp8_blit_line  (x0+12,  x1, y0+12,  y1, y_buffer, y_stride);
+                            break;
+                        }
+                        default :
+                        {
+                            union b_mode_info *bmi = mi->bmi;
+                            int bx0, by0;
+
+                            for (by0 = y0; by0 < (y0+16); by0 += 4)
+                            {
+                                for (bx0 = x0; bx0 < (x0+16); bx0 += 4)
+                                {
+                                    MV *mv = &bmi->mv.as_mv;
+
+                                    x1 = bx0 + 2 + (mv->col >> 3);
+                                    y1 = by0 + 2 + (mv->row >> 3);
+
+                                    constrain_line (bx0+2, &x1, by0+2, &y1, width, height);
+                                    vp8_blit_line  (bx0+2,  x1, by0+2,  y1, y_buffer, y_stride);
+
+                                    bmi++;
+                                }
+                            }
+                        }
+                    }
+                }
+                else if (mi->mbmi.mode >= NEARESTMV)
+                {
+                    MV *mv = &mi->mbmi.mv.as_mv;
+                    const int lx0 = x0 + 8;
+                    const int ly0 = y0 + 8;
+
+                    x1 = lx0 + (mv->col >> 3);
+                    y1 = ly0 + (mv->row >> 3);
+
+                    if (x1 != lx0 && y1 != ly0)
+                    {
+                        constrain_line (lx0, &x1, ly0-1, &y1, width, height);
+                        vp8_blit_line  (lx0,  x1, ly0-1,  y1, y_buffer, y_stride);
+
+                        constrain_line (lx0, &x1, ly0+1, &y1, width, height);
+                        vp8_blit_line  (lx0,  x1, ly0+1,  y1, y_buffer, y_stride);
+                    }
+                    else
+                        vp8_blit_line  (lx0,  x1, ly0,  y1, y_buffer, y_stride);
+                }
+
+                mi++;
+            }
+            mi++;
+        }
+    }
+
+    /* Color in block modes */
+    if ((flags & VP8D_DEBUG_CLR_BLK_MODES)
+        && (ppflags->display_mb_modes_flag || ppflags->display_b_modes_flag))
+    {
+        int y, x;
+        YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
+        int width  = post->y_width;
+        int height = post->y_height;
+        unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
+        unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
+        unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
+        int y_stride = oci->post_proc_buffer.y_stride;
+        MODE_INFO *mi = oci->mi;
+
+        for (y = 0; y < height; y += 16)
+        {
+            for (x = 0; x < width; x += 16)
+            {
+                int Y = 0, U = 0, V = 0;
+
+                if (mi->mbmi.mode == B_PRED &&
+                    ((ppflags->display_mb_modes_flag & B_PRED) || ppflags->display_b_modes_flag))
+                {
+                    int by, bx;
+                    unsigned char *yl, *ul, *vl;
+                    union b_mode_info *bmi = mi->bmi;
+
+                    yl = y_ptr + x;
+                    ul = u_ptr + (x>>1);
+                    vl = v_ptr + (x>>1);
+
+                    for (by = 0; by < 16; by += 4)
+                    {
+                        for (bx = 0; bx < 16; bx += 4)
+                        {
+                            if ((ppflags->display_b_modes_flag & (1<<mi->mbmi.mode))
+                                || (ppflags->display_mb_modes_flag & B_PRED))
+                            {
+                                Y = B_PREDICTION_MODE_colors[bmi->as_mode][0];
+                                U = B_PREDICTION_MODE_colors[bmi->as_mode][1];
+                                V = B_PREDICTION_MODE_colors[bmi->as_mode][2];
+
+                                vp8_blend_b
+                                    (yl+bx, ul+(bx>>1), vl+(bx>>1), Y, U, V, 0xc000, y_stride);
+                            }
+                            bmi++;
+                        }
+
+                        yl += y_stride*4;
+                        ul += y_stride*1;
+                        vl += y_stride*1;
+                    }
+                }
+                else if (ppflags->display_mb_modes_flag & (1<<mi->mbmi.mode))
+                {
+                    Y = MB_PREDICTION_MODE_colors[mi->mbmi.mode][0];
+                    U = MB_PREDICTION_MODE_colors[mi->mbmi.mode][1];
+                    V = MB_PREDICTION_MODE_colors[mi->mbmi.mode][2];
+
+                    vp8_blend_mb_inner
+                        (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
+                }
+
+                mi++;
+            }
+            y_ptr += y_stride*16;
+            u_ptr += y_stride*4;
+            v_ptr += y_stride*4;
+
+            mi++;
+        }
+    }
+
+    /* Color in frame reference blocks */
+    if ((flags & VP8D_DEBUG_CLR_FRM_REF_BLKS) && ppflags->display_ref_frame_flag)
+    {
+        int y, x;
+        YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
+        int width  = post->y_width;
+        int height = post->y_height;
+        unsigned char *y_ptr = oci->post_proc_buffer.y_buffer;
+        unsigned char *u_ptr = oci->post_proc_buffer.u_buffer;
+        unsigned char *v_ptr = oci->post_proc_buffer.v_buffer;
+        int y_stride = oci->post_proc_buffer.y_stride;
+        MODE_INFO *mi = oci->mi;
+
+        for (y = 0; y < height; y += 16)
+        {
+            for (x = 0; x < width; x +=16)
+            {
+                int Y = 0, U = 0, V = 0;
+
+                if (ppflags->display_ref_frame_flag & (1<<mi->mbmi.ref_frame))
+                {
+                    Y = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][0];
+                    U = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][1];
+                    V = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][2];
+
+                    vp8_blend_mb_outer
+                        (y_ptr+x, u_ptr+(x>>1), v_ptr+(x>>1), Y, U, V, 0xc000, y_stride);
+                }
+
+                mi++;
+            }
+            y_ptr += y_stride*16;
+            u_ptr += y_stride*4;
+            v_ptr += y_stride*4;
+
+            mi++;
+        }
+    }
+#endif
+
+    *dest = oci->post_proc_buffer;
+
+    /* handle problem with extending borders */
+    dest->y_width = oci->Width;
+    dest->y_height = oci->Height;
+    dest->uv_height = dest->y_height / 2;
+    return 0;
+}
+#endif
diff --git a/vp8/common/postproc.h b/vp8/common/postproc.h
new file mode 100644 (file)
index 0000000..6ac788c
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef POSTPROC_H
+#define POSTPROC_H
+
+#include "vpx_ports/mem.h"
+struct postproc_state
+{
+    int           last_q;
+    int           last_noise;
+    char          noise[3072];
+    int           last_base_qindex;
+    int           last_frame_valid;
+    DECLARE_ALIGNED(16, char, blackclamp[16]);
+    DECLARE_ALIGNED(16, char, whiteclamp[16]);
+    DECLARE_ALIGNED(16, char, bothclamp[16]);
+};
+#include "onyxc_int.h"
+#include "ppflags.h"
+int vp8_post_proc_frame(struct VP8Common *oci, YV12_BUFFER_CONFIG *dest,
+                        vp8_ppflags_t *flags);
+
+
+void vp8_de_noise(YV12_BUFFER_CONFIG         *source,
+                  YV12_BUFFER_CONFIG         *post,
+                  int                         q,
+                  int                         low_var_thresh,
+                  int                         flag);
+
+void vp8_deblock(YV12_BUFFER_CONFIG         *source,
+                 YV12_BUFFER_CONFIG         *post,
+                 int                         q,
+                 int                         low_var_thresh,
+                 int                         flag);
+
+#define MFQE_PRECISION 4
+
+void vp8_multiframe_quality_enhance(struct VP8Common *cm);
+#endif
diff --git a/vp8/common/ppc/copy_altivec.asm b/vp8/common/ppc/copy_altivec.asm
new file mode 100644 (file)
index 0000000..a4ce915
--- /dev/null
@@ -0,0 +1,47 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    .globl copy_mem16x16_ppc
+
+;# r3 unsigned char *src
+;# r4 int src_stride
+;# r5 unsigned char *dst
+;# r6 int dst_stride
+
+;# Make the assumption that input will not be aligned,
+;#  but the output will be.  So two reads and a perm
+;#  for the input, but only one store for the output.
+copy_mem16x16_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xe000
+    mtspr   256, r12            ;# set VRSAVE
+
+    li      r10, 16
+    mtctr   r10
+
+cp_16x16_loop:
+    lvsl    v0,  0, r3          ;# permutate value for alignment
+
+    lvx     v1,   0, r3
+    lvx     v2, r10, r3
+
+    vperm   v1, v1, v2, v0
+
+    stvx    v1,  0, r5
+
+    add     r3, r3, r4          ;# increment source pointer
+    add     r5, r5, r6          ;# increment destination pointer
+
+    bdnz    cp_16x16_loop
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
diff --git a/vp8/common/ppc/filter_altivec.asm b/vp8/common/ppc/filter_altivec.asm
new file mode 100644 (file)
index 0000000..4da2e94
--- /dev/null
@@ -0,0 +1,1013 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    .globl sixtap_predict_ppc
+    .globl sixtap_predict8x4_ppc
+    .globl sixtap_predict8x8_ppc
+    .globl sixtap_predict16x16_ppc
+
+.macro load_c V, LABEL, OFF, R0, R1
+    lis     \R0, \LABEL@ha
+    la      \R1, \LABEL@l(\R0)
+    lvx     \V, \OFF, \R1
+.endm
+
+.macro load_hfilter V0, V1
+    load_c \V0, HFilter, r5, r9, r10
+
+    addi    r5,  r5, 16
+    lvx     \V1, r5, r10
+.endm
+
+;# Vertical filtering
+.macro Vprolog
+    load_c v0, VFilter, r6, r3, r10
+
+    vspltish v5, 8
+    vspltish v6, 3
+    vslh    v6, v5, v6      ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    vspltb  v1, v0, 1
+    vspltb  v2, v0, 2
+    vspltb  v3, v0, 3
+    vspltb  v4, v0, 4
+    vspltb  v5, v0, 5
+    vspltb  v0, v0, 0
+.endm
+
+.macro vpre_load
+    Vprolog
+    li      r10,  16
+    lvx     v10,   0, r9    ;# v10..v14 = first 5 rows
+    lvx     v11, r10, r9
+    addi    r9,   r9, 32
+    lvx     v12,   0, r9
+    lvx     v13, r10, r9
+    addi    r9,   r9, 32
+    lvx     v14,   0, r9
+.endm
+
+.macro Msum Re, Ro, V, T, TMP
+                                ;# (Re,Ro) += (V*T)
+    vmuleub \TMP, \V, \T        ;# trashes v8
+    vadduhm \Re, \Re, \TMP      ;# Re = evens, saturation unnecessary
+    vmuloub \TMP, \V, \T
+    vadduhm \Ro, \Ro, \TMP      ;# Ro = odds
+.endm
+
+.macro vinterp_no_store P0 P1 P2 P3 P4 P5
+    vmuleub  v8, \P0, v0        ;# 64 + 4 positive taps
+    vadduhm v16, v6, v8
+    vmuloub  v8, \P0, v0
+    vadduhm v17, v6, v8
+    Msum v16, v17, \P2, v2, v8
+    Msum v16, v17, \P3, v3, v8
+    Msum v16, v17, \P5, v5, v8
+
+    vmuleub v18, \P1, v1        ;# 2 negative taps
+    vmuloub v19, \P1, v1
+    Msum v18, v19, \P4, v4, v8
+
+    vsubuhs v16, v16, v18       ;# subtract neg from pos
+    vsubuhs v17, v17, v19
+    vsrh    v16, v16, v7        ;# divide by 128
+    vsrh    v17, v17, v7        ;# v16 v17 = evens, odds
+    vmrghh  v18, v16, v17       ;# v18 v19 = 16-bit result in order
+    vmrglh  v19, v16, v17
+    vpkuhus  \P0, v18, v19      ;# P0 = 8-bit result
+.endm
+
+.macro vinterp_no_store_8x8 P0 P1 P2 P3 P4 P5
+    vmuleub v24, \P0, v13       ;# 64 + 4 positive taps
+    vadduhm v21, v20, v24
+    vmuloub v24, \P0, v13
+    vadduhm v22, v20, v24
+    Msum v21, v22, \P2, v15, v25
+    Msum v21, v22, \P3, v16, v25
+    Msum v21, v22, \P5, v18, v25
+
+    vmuleub v23, \P1, v14       ;# 2 negative taps
+    vmuloub v24, \P1, v14
+    Msum v23, v24, \P4, v17, v25
+
+    vsubuhs v21, v21, v23       ;# subtract neg from pos
+    vsubuhs v22, v22, v24
+    vsrh    v21, v21, v19       ;# divide by 128
+    vsrh    v22, v22, v19       ;# v16 v17 = evens, odds
+    vmrghh  v23, v21, v22       ;# v18 v19 = 16-bit result in order
+    vmrglh  v24, v21, v22
+    vpkuhus \P0, v23, v24       ;# P0 = 8-bit result
+.endm
+
+
+.macro Vinterp P0 P1 P2 P3 P4 P5
+    vinterp_no_store \P0, \P1, \P2, \P3, \P4, \P5
+    stvx    \P0, 0, r7
+    add     r7, r7, r8      ;# 33 ops per 16 pels
+.endm
+
+
+.macro luma_v P0, P1, P2, P3, P4, P5
+    addi    r9,   r9, 16        ;# P5 = newest input row
+    lvx     \P5,   0, r9
+    Vinterp \P0, \P1, \P2, \P3, \P4, \P5
+.endm
+
+.macro luma_vtwo
+    luma_v v10, v11, v12, v13, v14, v15
+    luma_v v11, v12, v13, v14, v15, v10
+.endm
+
+.macro luma_vfour
+    luma_vtwo
+    luma_v v12, v13, v14, v15, v10, v11
+    luma_v v13, v14, v15, v10, v11, v12
+.endm
+
+.macro luma_vsix
+    luma_vfour
+    luma_v v14, v15, v10, v11, v12, v13
+    luma_v v15, v10, v11, v12, v13, v14
+.endm
+
+.macro Interp4 R I I4
+    vmsummbm \R, v13, \I, v15
+    vmsummbm \R, v14, \I4, \R
+.endm
+
+.macro Read8x8 VD, RS, RP, increment_counter
+    lvsl    v21,  0, \RS        ;# permutate value for alignment
+
+    ;# input to filter is 21 bytes wide, output is 16 bytes.
+    ;#  input will can span three vectors if not aligned correctly.
+    lvx     \VD,   0, \RS
+    lvx     v20, r10, \RS
+
+.if \increment_counter
+    add     \RS, \RS, \RP
+.endif
+
+    vperm   \VD, \VD, v20, v21
+.endm
+
+.macro interp_8x8 R
+    vperm   v20, \R, \R, v16    ;# v20 = 0123 1234 2345 3456
+    vperm   v21, \R, \R, v17    ;# v21 = 4567 5678 6789 789A
+    Interp4 v20, v20,  v21      ;# v20 = result 0 1 2 3
+    vperm   \R, \R, \R, v18     ;# R   = 89AB 9ABC ABCx BCxx
+    Interp4 v21, v21, \R        ;# v21 = result 4 5 6 7
+
+    vpkswus \R, v20, v21        ;#  R = 0 1 2 3 4 5 6 7
+    vsrh    \R, \R, v19
+
+    vpkuhus \R, \R, \R          ;# saturate and pack
+
+.endm
+
+.macro Read4x4 VD, RS, RP, increment_counter
+    lvsl    v21,  0, \RS        ;# permutate value for alignment
+
+    ;# input to filter is 21 bytes wide, output is 16 bytes.
+    ;#  input will can span three vectors if not aligned correctly.
+    lvx     v20,   0, \RS
+
+.if \increment_counter
+    add     \RS, \RS, \RP
+.endif
+
+    vperm   \VD, v20, v20, v21
+.endm
+    .text
+
+    .align 2
+;# r3 unsigned char * src
+;# r4 int src_pitch
+;# r5 int x_offset
+;# r6 int y_offset
+;# r7 unsigned char * dst
+;# r8 int dst_pitch
+sixtap_predict_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xff87
+    ori     r12, r12, 0xffc0
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    slwi.   r5, r5, 5           ;# index into horizontal filter array
+
+    vspltish v19, 7
+
+    ;# If there isn't any filtering to be done for the horizontal, then
+    ;#  just skip to the second pass.
+    beq-    vertical_only_4x4
+
+    ;# load up horizontal filter
+    load_hfilter v13, v14
+
+    ;# rounding added in on the multiply
+    vspltisw v16, 8
+    vspltisw v15, 3
+    vslw    v15, v16, v15       ;# 0x00000040000000400000004000000040
+
+    ;# Load up permutation constants
+    load_c v16, B_0123, 0, r9, r10
+    load_c v17, B_4567, 0, r9, r10
+    load_c v18, B_89AB, 0, r9, r10
+
+    ;# Back off input buffer by 2 bytes.  Need 2 before and 3 after
+    addi    r3, r3, -2
+
+    addi    r9, r3, 0
+    li      r10, 16
+    Read8x8 v2, r3, r4, 1
+    Read8x8 v3, r3, r4, 1
+    Read8x8 v4, r3, r4, 1
+    Read8x8 v5, r3, r4, 1
+
+    slwi.   r6, r6, 4           ;# index into vertical filter array
+
+    ;# filter a line
+    interp_8x8 v2
+    interp_8x8 v3
+    interp_8x8 v4
+    interp_8x8 v5
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional 5 lines that are needed
+    ;#  for the vertical filter.
+    beq-    store_4x4
+
+    ;# only needed if there is a vertical filter present
+    ;# if the second filter is not null then need to back off by 2*pitch
+    sub     r9, r9, r4
+    sub     r9, r9, r4
+
+    Read8x8 v0, r9, r4, 1
+    Read8x8 v1, r9, r4, 0
+    Read8x8 v6, r3, r4, 1
+    Read8x8 v7, r3, r4, 1
+    Read8x8 v8, r3, r4, 0
+
+    interp_8x8 v0
+    interp_8x8 v1
+    interp_8x8 v6
+    interp_8x8 v7
+    interp_8x8 v8
+
+    b       second_pass_4x4
+
+vertical_only_4x4:
+    ;# only needed if there is a vertical filter present
+    ;# if the second filter is not null then need to back off by 2*pitch
+    sub     r3, r3, r4
+    sub     r3, r3, r4
+    li      r10, 16
+
+    Read8x8 v0, r3, r4, 1
+    Read8x8 v1, r3, r4, 1
+    Read8x8 v2, r3, r4, 1
+    Read8x8 v3, r3, r4, 1
+    Read8x8 v4, r3, r4, 1
+    Read8x8 v5, r3, r4, 1
+    Read8x8 v6, r3, r4, 1
+    Read8x8 v7, r3, r4, 1
+    Read8x8 v8, r3, r4, 0
+
+    slwi    r6, r6, 4           ;# index into vertical filter array
+
+second_pass_4x4:
+    load_c   v20, b_hilo_4x4, 0, r9, r10
+    load_c   v21, b_hilo, 0, r9, r10
+
+    ;# reposition input so that it can go through the
+    ;# filtering phase with one pass.
+    vperm   v0, v0, v1, v20     ;# 0 1 x x
+    vperm   v2, v2, v3, v20     ;# 2 3 x x
+    vperm   v4, v4, v5, v20     ;# 4 5 x x
+    vperm   v6, v6, v7, v20     ;# 6 7 x x
+
+    vperm   v0, v0, v2, v21     ;# 0 1 2 3
+    vperm   v4, v4, v6, v21     ;# 4 5 6 7
+
+    vsldoi  v1, v0, v4, 4
+    vsldoi  v2, v0, v4, 8
+    vsldoi  v3, v0, v4, 12
+
+    vsldoi  v5, v4, v8, 4
+
+    load_c   v13, VFilter, r6, r9, r10
+
+    vspltish v15, 8
+    vspltish v20, 3
+    vslh    v20, v15, v20       ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    vspltb  v14, v13, 1
+    vspltb  v15, v13, 2
+    vspltb  v16, v13, 3
+    vspltb  v17, v13, 4
+    vspltb  v18, v13, 5
+    vspltb  v13, v13, 0
+
+    vinterp_no_store_8x8 v0, v1, v2, v3, v4, v5
+
+    stvx    v0, 0, r1
+
+    lwz     r0, 0(r1)
+    stw     r0, 0(r7)
+    add     r7, r7, r8
+
+    lwz     r0, 4(r1)
+    stw     r0, 0(r7)
+    add     r7, r7, r8
+
+    lwz     r0, 8(r1)
+    stw     r0, 0(r7)
+    add     r7, r7, r8
+
+    lwz     r0, 12(r1)
+    stw     r0, 0(r7)
+
+    b       exit_4x4
+
+store_4x4:
+
+    stvx    v2, 0, r1
+    lwz     r0, 0(r1)
+    stw     r0, 0(r7)
+    add     r7, r7, r8
+
+    stvx    v3, 0, r1
+    lwz     r0, 0(r1)
+    stw     r0, 0(r7)
+    add     r7, r7, r8
+
+    stvx    v4, 0, r1
+    lwz     r0, 0(r1)
+    stw     r0, 0(r7)
+    add     r7, r7, r8
+
+    stvx    v5, 0, r1
+    lwz     r0, 0(r1)
+    stw     r0, 0(r7)
+
+exit_4x4:
+
+    addi    r1, r1, 32          ;# recover stack
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+.macro w_8x8 V, D, R, P
+    stvx    \V, 0, r1
+    lwz     \R, 0(r1)
+    stw     \R, 0(r7)
+    lwz     \R, 4(r1)
+    stw     \R, 4(r7)
+    add     \D, \D, \P
+.endm
+
+    .align 2
+;# r3 unsigned char * src
+;# r4 int src_pitch
+;# r5 int x_offset
+;# r6 int y_offset
+;# r7 unsigned char * dst
+;# r8 int dst_pitch
+
+sixtap_predict8x4_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xffc0
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    slwi.   r5, r5, 5           ;# index into horizontal filter array
+
+    vspltish v19, 7
+
+    ;# If there isn't any filtering to be done for the horizontal, then
+    ;#  just skip to the second pass.
+    beq-    second_pass_pre_copy_8x4
+
+    load_hfilter v13, v14
+
+    ;# rounding added in on the multiply
+    vspltisw v16, 8
+    vspltisw v15, 3
+    vslw    v15, v16, v15       ;# 0x00000040000000400000004000000040
+
+    ;# Load up permutation constants
+    load_c v16, B_0123, 0, r9, r10
+    load_c v17, B_4567, 0, r9, r10
+    load_c v18, B_89AB, 0, r9, r10
+
+    ;# Back off input buffer by 2 bytes.  Need 2 before and 3 after
+    addi    r3, r3, -2
+
+    addi    r9, r3, 0
+    li      r10, 16
+    Read8x8 v2, r3, r4, 1
+    Read8x8 v3, r3, r4, 1
+    Read8x8 v4, r3, r4, 1
+    Read8x8 v5, r3, r4, 1
+
+    slwi.   r6, r6, 4           ;# index into vertical filter array
+
+    ;# filter a line
+    interp_8x8 v2
+    interp_8x8 v3
+    interp_8x8 v4
+    interp_8x8 v5
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional 5 lines that are needed
+    ;#  for the vertical filter.
+    beq-    store_8x4
+
+    ;# only needed if there is a vertical filter present
+    ;# if the second filter is not null then need to back off by 2*pitch
+    sub     r9, r9, r4
+    sub     r9, r9, r4
+
+    Read8x8 v0, r9, r4, 1
+    Read8x8 v1, r9, r4, 0
+    Read8x8 v6, r3, r4, 1
+    Read8x8 v7, r3, r4, 1
+    Read8x8 v8, r3, r4, 0
+
+    interp_8x8 v0
+    interp_8x8 v1
+    interp_8x8 v6
+    interp_8x8 v7
+    interp_8x8 v8
+
+    b       second_pass_8x4
+
+second_pass_pre_copy_8x4:
+    ;# only needed if there is a vertical filter present
+    ;# if the second filter is not null then need to back off by 2*pitch
+    sub     r3, r3, r4
+    sub     r3, r3, r4
+    li      r10, 16
+
+    Read8x8 v0,  r3, r4, 1
+    Read8x8 v1,  r3, r4, 1
+    Read8x8 v2,  r3, r4, 1
+    Read8x8 v3,  r3, r4, 1
+    Read8x8 v4,  r3, r4, 1
+    Read8x8 v5,  r3, r4, 1
+    Read8x8 v6,  r3, r4, 1
+    Read8x8 v7,  r3, r4, 1
+    Read8x8 v8,  r3, r4, 1
+
+    slwi    r6, r6, 4           ;# index into vertical filter array
+
+second_pass_8x4:
+    load_c v13, VFilter, r6, r9, r10
+
+    vspltish v15, 8
+    vspltish v20, 3
+    vslh    v20, v15, v20       ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    vspltb  v14, v13, 1
+    vspltb  v15, v13, 2
+    vspltb  v16, v13, 3
+    vspltb  v17, v13, 4
+    vspltb  v18, v13, 5
+    vspltb  v13, v13, 0
+
+    vinterp_no_store_8x8 v0, v1, v2, v3,  v4,  v5
+    vinterp_no_store_8x8 v1, v2, v3, v4,  v5,  v6
+    vinterp_no_store_8x8 v2, v3, v4, v5,  v6,  v7
+    vinterp_no_store_8x8 v3, v4, v5, v6,  v7,  v8
+
+    cmpi    cr0, r8, 8
+    beq     cr0, store_aligned_8x4
+
+    w_8x8   v0, r7, r0, r8
+    w_8x8   v1, r7, r0, r8
+    w_8x8   v2, r7, r0, r8
+    w_8x8   v3, r7, r0, r8
+
+    b       exit_8x4
+
+store_aligned_8x4:
+
+    load_c v10, b_hilo, 0, r9, r10
+
+    vperm   v0, v0, v1, v10
+    vperm   v2, v2, v3, v10
+
+    stvx    v0, 0, r7
+    addi    r7, r7, 16
+    stvx    v2, 0, r7
+
+    b       exit_8x4
+
+store_8x4:
+    cmpi    cr0, r8, 8
+    beq     cr0, store_aligned2_8x4
+
+    w_8x8   v2, r7, r0, r8
+    w_8x8   v3, r7, r0, r8
+    w_8x8   v4, r7, r0, r8
+    w_8x8   v5, r7, r0, r8
+
+    b       exit_8x4
+
+store_aligned2_8x4:
+    load_c v10, b_hilo, 0, r9, r10
+
+    vperm   v2, v2, v3, v10
+    vperm   v4, v4, v5, v10
+
+    stvx    v2, 0, r7
+    addi    r7, r7, 16
+    stvx    v4, 0, r7
+
+exit_8x4:
+
+    addi    r1, r1, 32          ;# recover stack
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+
+    blr
+
+    .align 2
+;# r3 unsigned char * src
+;# r4 int src_pitch
+;# r5 int x_offset
+;# r6 int y_offset
+;# r7 unsigned char * dst
+;# r8 int dst_pitch
+
+;# Because the width that needs to be filtered will fit in a single altivec
+;#  register there is no need to loop.  Everything can stay in registers.
+sixtap_predict8x8_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xffc0
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    slwi.   r5, r5, 5           ;# index into horizontal filter array
+
+    vspltish v19, 7
+
+    ;# If there isn't any filtering to be done for the horizontal, then
+    ;#  just skip to the second pass.
+    beq-    second_pass_pre_copy_8x8
+
+    load_hfilter v13, v14
+
+    ;# rounding added in on the multiply
+    vspltisw v16, 8
+    vspltisw v15, 3
+    vslw    v15, v16, v15       ;# 0x00000040000000400000004000000040
+
+    ;# Load up permutation constants
+    load_c v16, B_0123, 0, r9, r10
+    load_c v17, B_4567, 0, r9, r10
+    load_c v18, B_89AB, 0, r9, r10
+
+    ;# Back off input buffer by 2 bytes.  Need 2 before and 3 after
+    addi    r3, r3, -2
+
+    addi    r9, r3, 0
+    li      r10, 16
+    Read8x8 v2, r3, r4, 1
+    Read8x8 v3, r3, r4, 1
+    Read8x8 v4, r3, r4, 1
+    Read8x8 v5, r3, r4, 1
+    Read8x8 v6, r3, r4, 1
+    Read8x8 v7, r3, r4, 1
+    Read8x8 v8, r3, r4, 1
+    Read8x8 v9, r3, r4, 1
+
+    slwi.   r6, r6, 4           ;# index into vertical filter array
+
+    ;# filter a line
+    interp_8x8 v2
+    interp_8x8 v3
+    interp_8x8 v4
+    interp_8x8 v5
+    interp_8x8 v6
+    interp_8x8 v7
+    interp_8x8 v8
+    interp_8x8 v9
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional 5 lines that are needed
+    ;#  for the vertical filter.
+    beq-    store_8x8
+
+    ;# only needed if there is a vertical filter present
+    ;# if the second filter is not null then need to back off by 2*pitch
+    sub     r9, r9, r4
+    sub     r9, r9, r4
+
+    Read8x8 v0,  r9, r4, 1
+    Read8x8 v1,  r9, r4, 0
+    Read8x8 v10, r3, r4, 1
+    Read8x8 v11, r3, r4, 1
+    Read8x8 v12, r3, r4, 0
+
+    interp_8x8 v0
+    interp_8x8 v1
+    interp_8x8 v10
+    interp_8x8 v11
+    interp_8x8 v12
+
+    b       second_pass_8x8
+
+second_pass_pre_copy_8x8:
+    ;# only needed if there is a vertical filter present
+    ;# if the second filter is not null then need to back off by 2*pitch
+    sub     r3, r3, r4
+    sub     r3, r3, r4
+    li      r10, 16
+
+    Read8x8 v0,  r3, r4, 1
+    Read8x8 v1,  r3, r4, 1
+    Read8x8 v2,  r3, r4, 1
+    Read8x8 v3,  r3, r4, 1
+    Read8x8 v4,  r3, r4, 1
+    Read8x8 v5,  r3, r4, 1
+    Read8x8 v6,  r3, r4, 1
+    Read8x8 v7,  r3, r4, 1
+    Read8x8 v8,  r3, r4, 1
+    Read8x8 v9,  r3, r4, 1
+    Read8x8 v10, r3, r4, 1
+    Read8x8 v11, r3, r4, 1
+    Read8x8 v12, r3, r4, 0
+
+    slwi    r6, r6, 4           ;# index into vertical filter array
+
+second_pass_8x8:
+    load_c v13, VFilter, r6, r9, r10
+
+    vspltish v15, 8
+    vspltish v20, 3
+    vslh    v20, v15, v20       ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    vspltb  v14, v13, 1
+    vspltb  v15, v13, 2
+    vspltb  v16, v13, 3
+    vspltb  v17, v13, 4
+    vspltb  v18, v13, 5
+    vspltb  v13, v13, 0
+
+    vinterp_no_store_8x8 v0, v1, v2, v3,  v4,  v5
+    vinterp_no_store_8x8 v1, v2, v3, v4,  v5,  v6
+    vinterp_no_store_8x8 v2, v3, v4, v5,  v6,  v7
+    vinterp_no_store_8x8 v3, v4, v5, v6,  v7,  v8
+    vinterp_no_store_8x8 v4, v5, v6, v7,  v8,  v9
+    vinterp_no_store_8x8 v5, v6, v7, v8,  v9,  v10
+    vinterp_no_store_8x8 v6, v7, v8, v9,  v10, v11
+    vinterp_no_store_8x8 v7, v8, v9, v10, v11, v12
+
+    cmpi    cr0, r8, 8
+    beq     cr0, store_aligned_8x8
+
+    w_8x8   v0, r7, r0, r8
+    w_8x8   v1, r7, r0, r8
+    w_8x8   v2, r7, r0, r8
+    w_8x8   v3, r7, r0, r8
+    w_8x8   v4, r7, r0, r8
+    w_8x8   v5, r7, r0, r8
+    w_8x8   v6, r7, r0, r8
+    w_8x8   v7, r7, r0, r8
+
+    b       exit_8x8
+
+store_aligned_8x8:
+
+    load_c v10, b_hilo, 0, r9, r10
+
+    vperm   v0, v0, v1, v10
+    vperm   v2, v2, v3, v10
+    vperm   v4, v4, v5, v10
+    vperm   v6, v6, v7, v10
+
+    stvx    v0, 0, r7
+    addi    r7, r7, 16
+    stvx    v2, 0, r7
+    addi    r7, r7, 16
+    stvx    v4, 0, r7
+    addi    r7, r7, 16
+    stvx    v6, 0, r7
+
+    b       exit_8x8
+
+store_8x8:
+    cmpi    cr0, r8, 8
+    beq     cr0, store_aligned2_8x8
+
+    w_8x8   v2, r7, r0, r8
+    w_8x8   v3, r7, r0, r8
+    w_8x8   v4, r7, r0, r8
+    w_8x8   v5, r7, r0, r8
+    w_8x8   v6, r7, r0, r8
+    w_8x8   v7, r7, r0, r8
+    w_8x8   v8, r7, r0, r8
+    w_8x8   v9, r7, r0, r8
+
+    b       exit_8x8
+
+store_aligned2_8x8:
+    load_c v10, b_hilo, 0, r9, r10
+
+    vperm   v2, v2, v3, v10
+    vperm   v4, v4, v5, v10
+    vperm   v6, v6, v7, v10
+    vperm   v8, v8, v9, v10
+
+    stvx    v2, 0, r7
+    addi    r7, r7, 16
+    stvx    v4, 0, r7
+    addi    r7, r7, 16
+    stvx    v6, 0, r7
+    addi    r7, r7, 16
+    stvx    v8, 0, r7
+
+exit_8x8:
+
+    addi    r1, r1, 32          ;# recover stack
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .align 2
+;# r3 unsigned char * src
+;# r4 int src_pitch
+;# r5 int x_offset
+;# r6 int y_offset
+;# r7 unsigned char * dst
+;# r8 int dst_pitch
+
+;# Two pass filtering.  First pass is Horizontal edges, second pass is vertical
+;#  edges.  One of the filters can be null, but both won't be.  Needs to use a
+;#  temporary buffer because the source buffer can't be modified and the buffer
+;#  for the destination is not large enough to hold the temporary data.
+sixtap_predict16x16_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xf000
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-416(r1)         ;# create space on the stack
+
+    ;# Three possiblities
+    ;#  1. First filter is null.  Don't use a temp buffer.
+    ;#  2. Second filter is null.  Don't use a temp buffer.
+    ;#  3. Neither are null, use temp buffer.
+
+    ;# First Pass (horizontal edge)
+    ;#  setup pointers for src
+    ;#  if possiblity (1) then setup the src pointer to be the orginal and jump
+    ;#  to second pass.  this is based on if x_offset is 0.
+
+    ;# load up horizontal filter
+    slwi.   r5, r5, 5           ;# index into horizontal filter array
+
+    load_hfilter v4, v5
+
+    beq-    copy_horizontal_16x21
+
+    ;# Back off input buffer by 2 bytes.  Need 2 before and 3 after
+    addi    r3, r3, -2
+
+    slwi.   r6, r6, 4           ;# index into vertical filter array
+
+    ;# setup constants
+    ;# v14 permutation value for alignment
+    load_c v14, b_hperm, 0, r9, r10
+
+    ;# These statements are guessing that there won't be a second pass,
+    ;#  but if there is then inside the bypass they need to be set
+    li      r0, 16              ;# prepare for no vertical filter
+
+    ;# Change the output pointer and pitch to be the actual
+    ;#  desination instead of a temporary buffer.
+    addi    r9, r7, 0
+    addi    r5, r8, 0
+
+    ;# no vertical filter, so write the output from the first pass
+    ;#  directly into the output buffer.
+    beq-    no_vertical_filter_bypass
+
+    ;# if the second filter is not null then need to back off by 2*pitch
+    sub     r3, r3, r4
+    sub     r3, r3, r4
+
+    ;# setup counter for the number of lines that are going to be filtered
+    li      r0, 21
+
+    ;# use the stack as temporary storage
+    la      r9, 48(r1)
+    li      r5, 16
+
+no_vertical_filter_bypass:
+
+    mtctr   r0
+
+    ;# rounding added in on the multiply
+    vspltisw v10, 8
+    vspltisw v12, 3
+    vslw    v12, v10, v12       ;# 0x00000040000000400000004000000040
+
+    ;# downshift by 7 ( divide by 128 ) at the end
+    vspltish v13, 7
+
+    ;# index to the next set of vectors in the row.
+    li      r10, 16
+    li      r12, 32
+
+horizontal_loop_16x16:
+
+    lvsl    v15,  0, r3         ;# permutate value for alignment
+
+    ;# input to filter is 21 bytes wide, output is 16 bytes.
+    ;#  input will can span three vectors if not aligned correctly.
+    lvx     v1,   0, r3
+    lvx     v2, r10, r3
+    lvx     v3, r12, r3
+
+    vperm   v8, v1, v2, v15
+    vperm   v9, v2, v3, v15     ;# v8 v9 = 21 input pixels left-justified
+
+    vsldoi  v11, v8, v9, 4
+
+    ;# set 0
+    vmsummbm v6, v4, v8, v12    ;# taps times elements
+    vmsummbm v0, v5, v11, v6
+
+    ;# set 1
+    vsldoi  v10, v8, v9, 1
+    vsldoi  v11, v8, v9, 5
+
+    vmsummbm v6, v4, v10, v12
+    vmsummbm v1, v5, v11, v6
+
+    ;# set 2
+    vsldoi  v10, v8, v9, 2
+    vsldoi  v11, v8, v9, 6
+
+    vmsummbm v6, v4, v10, v12
+    vmsummbm v2, v5, v11, v6
+
+    ;# set 3
+    vsldoi  v10, v8, v9, 3
+    vsldoi  v11, v8, v9, 7
+
+    vmsummbm v6, v4, v10, v12
+    vmsummbm v3, v5, v11, v6
+
+    vpkswus v0, v0, v1          ;# v0 = 0 4 8 C 1 5 9 D (16-bit)
+    vpkswus v1, v2, v3          ;# v1 = 2 6 A E 3 7 B F
+
+    vsrh    v0, v0, v13         ;# divide v0, v1 by 128
+    vsrh    v1, v1, v13
+
+    vpkuhus v0, v0, v1          ;# v0 = scrambled 8-bit result
+    vperm   v0, v0, v0, v14     ;# v0 = correctly-ordered result
+
+    stvx    v0,  0, r9
+    add     r9, r9, r5
+
+    add     r3, r3, r4
+
+    bdnz    horizontal_loop_16x16
+
+    ;# check again to see if vertical filter needs to be done.
+    cmpi    cr0, r6, 0
+    beq     cr0, end_16x16
+
+    ;# yes there is, so go to the second pass
+    b       second_pass_16x16
+
+copy_horizontal_16x21:
+    li      r10, 21
+    mtctr   r10
+
+    li      r10, 16
+
+    sub     r3, r3, r4
+    sub     r3, r3, r4
+
+    ;# this is done above if there is a horizontal filter,
+    ;#  if not it needs to be done down here.
+    slwi    r6, r6, 4           ;# index into vertical filter array
+
+    ;# always write to the stack when doing a horizontal copy
+    la      r9, 48(r1)
+
+copy_horizontal_loop_16x21:
+    lvsl    v15,  0, r3         ;# permutate value for alignment
+
+    lvx     v1,   0, r3
+    lvx     v2, r10, r3
+
+    vperm   v8, v1, v2, v15
+
+    stvx    v8,  0, r9
+    addi    r9, r9, 16
+
+    add     r3, r3, r4
+
+    bdnz    copy_horizontal_loop_16x21
+
+second_pass_16x16:
+
+    ;# always read from the stack when doing a vertical filter
+    la      r9, 48(r1)
+
+    ;# downshift by 7 ( divide by 128 ) at the end
+    vspltish v7, 7
+
+    vpre_load
+
+    luma_vsix
+    luma_vsix
+    luma_vfour
+
+end_16x16:
+
+    addi    r1, r1, 416         ;# recover stack
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .data
+
+    .align 4
+HFilter:
+    .byte     0,  0,128,  0,  0,  0,128,  0,  0,  0,128,  0,  0,  0,128,  0
+    .byte     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    .byte     0, -6,123, 12,  0, -6,123, 12,  0, -6,123, 12,  0, -6,123, 12
+    .byte    -1,  0,  0,  0, -1,  0,  0,  0, -1,  0,  0,  0, -1,  0,  0,  0
+    .byte     2,-11,108, 36,  2,-11,108, 36,  2,-11,108, 36,  2,-11,108, 36
+    .byte    -8,  1,  0,  0, -8,  1,  0,  0, -8,  1,  0,  0, -8,  1,  0,  0
+    .byte     0, -9, 93, 50,  0, -9, 93, 50,  0, -9, 93, 50,  0, -9, 93, 50
+    .byte    -6,  0,  0,  0, -6,  0,  0,  0, -6,  0,  0,  0, -6,  0,  0,  0
+    .byte     3,-16, 77, 77,  3,-16, 77, 77,  3,-16, 77, 77,  3,-16, 77, 77
+    .byte   -16,  3,  0,  0,-16,  3,  0,  0,-16,  3,  0,  0,-16,  3,  0,  0
+    .byte     0, -6, 50, 93,  0, -6, 50, 93,  0, -6, 50, 93,  0, -6, 50, 93
+    .byte    -9,  0,  0,  0, -9,  0,  0,  0, -9,  0,  0,  0, -9,  0,  0,  0
+    .byte     1, -8, 36,108,  1, -8, 36,108,  1, -8, 36,108,  1, -8, 36,108
+    .byte   -11,  2,  0,  0,-11,  2,  0,  0,-11,  2,  0,  0,-11,  2,  0,  0
+    .byte     0, -1, 12,123,  0, -1, 12,123,  0, -1, 12,123,  0, -1, 12,123
+    .byte    -6,  0,  0,  0, -6,  0,  0,  0, -6,  0,  0,  0, -6,  0,  0,  0
+
+    .align 4
+VFilter:
+    .byte     0,  0,128,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    .byte     0,  6,123, 12,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    .byte     2, 11,108, 36,  8,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    .byte     0,  9, 93, 50,  6,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    .byte     3, 16, 77, 77, 16,  3,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    .byte     0,  6, 50, 93,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    .byte     1,  8, 36,108, 11,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    .byte     0,  1, 12,123,  6,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+
+    .align 4
+b_hperm:
+    .byte     0,  4,  8, 12,  1,  5,  9, 13,  2,  6, 10, 14,  3,  7, 11, 15
+
+    .align 4
+B_0123:
+    .byte     0,  1,  2,  3,  1,  2,  3,  4,  2,  3,  4,  5,  3,  4,  5,  6
+
+    .align 4
+B_4567:
+    .byte     4,  5,  6,  7,  5,  6,  7,  8,  6,  7,  8,  9,  7,  8,  9, 10
+
+    .align 4
+B_89AB:
+    .byte     8,  9, 10, 11,  9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14
+
+    .align 4
+b_hilo:
+    .byte     0,  1,  2,  3,  4,  5,  6,  7, 16, 17, 18, 19, 20, 21, 22, 23
+
+    .align 4
+b_hilo_4x4:
+    .byte     0,  1,  2,  3, 16, 17, 18, 19,  0,  0,  0,  0,  0,  0,  0,  0
diff --git a/vp8/common/ppc/filter_bilinear_altivec.asm b/vp8/common/ppc/filter_bilinear_altivec.asm
new file mode 100644 (file)
index 0000000..fd8aa66
--- /dev/null
@@ -0,0 +1,677 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    .globl bilinear_predict4x4_ppc
+    .globl bilinear_predict8x4_ppc
+    .globl bilinear_predict8x8_ppc
+    .globl bilinear_predict16x16_ppc
+
+.macro load_c V, LABEL, OFF, R0, R1
+    lis     \R0, \LABEL@ha
+    la      \R1, \LABEL@l(\R0)
+    lvx     \V, \OFF, \R1
+.endm
+
+.macro load_vfilter V0, V1
+    load_c \V0, vfilter_b, r6, r9, r10
+
+    addi    r6,  r6, 16
+    lvx     \V1, r6, r10
+.endm
+
+.macro HProlog jump_label
+    ;# load up horizontal filter
+    slwi.   r5, r5, 4           ;# index into horizontal filter array
+
+    ;# index to the next set of vectors in the row.
+    li      r10, 16
+    li      r12, 32
+
+    ;# downshift by 7 ( divide by 128 ) at the end
+    vspltish v19, 7
+
+    ;# If there isn't any filtering to be done for the horizontal, then
+    ;#  just skip to the second pass.
+    beq     \jump_label
+
+    load_c v20, hfilter_b, r5, r9, r0
+
+    ;# setup constants
+    ;# v14 permutation value for alignment
+    load_c v28, b_hperm_b, 0, r9, r0
+
+    ;# rounding added in on the multiply
+    vspltisw v21, 8
+    vspltisw v18, 3
+    vslw    v18, v21, v18       ;# 0x00000040000000400000004000000040
+
+    slwi.   r6, r6, 5           ;# index into vertical filter array
+.endm
+
+;# Filters a horizontal line
+;# expects:
+;#  r3  src_ptr
+;#  r4  pitch
+;#  r10 16
+;#  r12 32
+;#  v17 perm intput
+;#  v18 rounding
+;#  v19 shift
+;#  v20 filter taps
+;#  v21 tmp
+;#  v22 tmp
+;#  v23 tmp
+;#  v24 tmp
+;#  v25 tmp
+;#  v26 tmp
+;#  v27 tmp
+;#  v28 perm output
+;#
+.macro HFilter V
+    vperm   v24, v21, v21, v10  ;# v20 = 0123 1234 2345 3456
+    vperm   v25, v21, v21, v11  ;# v21 = 4567 5678 6789 789A
+
+    vmsummbm v24, v20, v24, v18
+    vmsummbm v25, v20, v25, v18
+
+    vpkswus v24, v24, v25       ;# v24 = 0 4 8 C 1 5 9 D (16-bit)
+
+    vsrh    v24, v24, v19       ;# divide v0, v1 by 128
+
+    vpkuhus \V, v24, v24        ;# \V = scrambled 8-bit result
+.endm
+
+.macro hfilter_8 V, increment_counter
+    lvsl    v17,  0, r3         ;# permutate value for alignment
+
+    ;# input to filter is 9 bytes wide, output is 8 bytes.
+    lvx     v21,   0, r3
+    lvx     v22, r10, r3
+
+.if \increment_counter
+    add     r3, r3, r4
+.endif
+    vperm   v21, v21, v22, v17
+
+    HFilter \V
+.endm
+
+
+.macro load_and_align_8 V, increment_counter
+    lvsl    v17,  0, r3         ;# permutate value for alignment
+
+    ;# input to filter is 21 bytes wide, output is 16 bytes.
+    ;#  input will can span three vectors if not aligned correctly.
+    lvx     v21,   0, r3
+    lvx     v22, r10, r3
+
+.if \increment_counter
+    add     r3, r3, r4
+.endif
+
+    vperm   \V, v21, v22, v17
+.endm
+
+.macro write_aligned_8 V, increment_counter
+    stvx    \V,  0, r7
+
+.if \increment_counter
+    add     r7, r7, r8
+.endif
+.endm
+
+.macro vfilter_16 P0 P1
+    vmuleub v22, \P0, v20       ;# 64 + 4 positive taps
+    vadduhm v22, v18, v22
+    vmuloub v23, \P0, v20
+    vadduhm v23, v18, v23
+
+    vmuleub v24, \P1, v21
+    vadduhm v22, v22, v24       ;# Re = evens, saturation unnecessary
+    vmuloub v25, \P1, v21
+    vadduhm v23, v23, v25       ;# Ro = odds
+
+    vsrh    v22, v22, v19       ;# divide by 128
+    vsrh    v23, v23, v19       ;# v16 v17 = evens, odds
+    vmrghh  \P0, v22, v23       ;# v18 v19 = 16-bit result in order
+    vmrglh  v23, v22, v23
+    vpkuhus \P0, \P0, v23       ;# P0 = 8-bit result
+.endm
+
+
+.macro w_8x8 V, D, R, P
+    stvx    \V, 0, r1
+    lwz     \R, 0(r1)
+    stw     \R, 0(r7)
+    lwz     \R, 4(r1)
+    stw     \R, 4(r7)
+    add     \D, \D, \P
+.endm
+
+
+    .align 2
+;# r3 unsigned char * src
+;# r4 int src_pitch
+;# r5 int x_offset
+;# r6 int y_offset
+;# r7 unsigned char * dst
+;# r8 int dst_pitch
+bilinear_predict4x4_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xf830
+    ori     r12, r12, 0xfff8
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    HProlog second_pass_4x4_pre_copy_b
+
+    ;# Load up permutation constants
+    load_c v10, b_0123_b, 0, r9, r12
+    load_c v11, b_4567_b, 0, r9, r12
+
+    hfilter_8 v0, 1
+    hfilter_8 v1, 1
+    hfilter_8 v2, 1
+    hfilter_8 v3, 1
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional line that is needed
+    ;#  for the vertical filter.
+    beq     store_out_4x4_b
+
+    hfilter_8 v4, 0
+
+    b   second_pass_4x4_b
+
+second_pass_4x4_pre_copy_b:
+    slwi    r6, r6, 5           ;# index into vertical filter array
+
+    load_and_align_8  v0, 1
+    load_and_align_8  v1, 1
+    load_and_align_8  v2, 1
+    load_and_align_8  v3, 1
+    load_and_align_8  v4, 1
+
+second_pass_4x4_b:
+    vspltish v20, 8
+    vspltish v18, 3
+    vslh    v18, v20, v18   ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    load_vfilter v20, v21
+
+    vfilter_16 v0,  v1
+    vfilter_16 v1,  v2
+    vfilter_16 v2,  v3
+    vfilter_16 v3,  v4
+
+store_out_4x4_b:
+
+    stvx    v0, 0, r1
+    lwz     r0, 0(r1)
+    stw     r0, 0(r7)
+    add     r7, r7, r8
+
+    stvx    v1, 0, r1
+    lwz     r0, 0(r1)
+    stw     r0, 0(r7)
+    add     r7, r7, r8
+
+    stvx    v2, 0, r1
+    lwz     r0, 0(r1)
+    stw     r0, 0(r7)
+    add     r7, r7, r8
+
+    stvx    v3, 0, r1
+    lwz     r0, 0(r1)
+    stw     r0, 0(r7)
+
+exit_4x4:
+
+    addi    r1, r1, 32          ;# recover stack
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .align 2
+;# r3 unsigned char * src
+;# r4 int src_pitch
+;# r5 int x_offset
+;# r6 int y_offset
+;# r7 unsigned char * dst
+;# r8 int dst_pitch
+bilinear_predict8x4_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xf830
+    ori     r12, r12, 0xfff8
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    HProlog second_pass_8x4_pre_copy_b
+
+    ;# Load up permutation constants
+    load_c v10, b_0123_b, 0, r9, r12
+    load_c v11, b_4567_b, 0, r9, r12
+
+    hfilter_8 v0, 1
+    hfilter_8 v1, 1
+    hfilter_8 v2, 1
+    hfilter_8 v3, 1
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional line that is needed
+    ;#  for the vertical filter.
+    beq     store_out_8x4_b
+
+    hfilter_8 v4, 0
+
+    b   second_pass_8x4_b
+
+second_pass_8x4_pre_copy_b:
+    slwi    r6, r6, 5           ;# index into vertical filter array
+
+    load_and_align_8  v0, 1
+    load_and_align_8  v1, 1
+    load_and_align_8  v2, 1
+    load_and_align_8  v3, 1
+    load_and_align_8  v4, 1
+
+second_pass_8x4_b:
+    vspltish v20, 8
+    vspltish v18, 3
+    vslh    v18, v20, v18   ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    load_vfilter v20, v21
+
+    vfilter_16 v0,  v1
+    vfilter_16 v1,  v2
+    vfilter_16 v2,  v3
+    vfilter_16 v3,  v4
+
+store_out_8x4_b:
+
+    cmpi    cr0, r8, 8
+    beq     cr0, store_aligned_8x4_b
+
+    w_8x8   v0, r7, r0, r8
+    w_8x8   v1, r7, r0, r8
+    w_8x8   v2, r7, r0, r8
+    w_8x8   v3, r7, r0, r8
+
+    b       exit_8x4
+
+store_aligned_8x4_b:
+    load_c v10, b_hilo_b, 0, r9, r10
+
+    vperm   v0, v0, v1, v10
+    vperm   v2, v2, v3, v10
+
+    stvx    v0, 0, r7
+    addi    r7, r7, 16
+    stvx    v2, 0, r7
+
+exit_8x4:
+
+    addi    r1, r1, 32          ;# recover stack
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .align 2
+;# r3 unsigned char * src
+;# r4 int src_pitch
+;# r5 int x_offset
+;# r6 int y_offset
+;# r7 unsigned char * dst
+;# r8 int dst_pitch
+bilinear_predict8x8_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xfff0
+    ori     r12, r12, 0xffff
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    HProlog second_pass_8x8_pre_copy_b
+
+    ;# Load up permutation constants
+    load_c v10, b_0123_b, 0, r9, r12
+    load_c v11, b_4567_b, 0, r9, r12
+
+    hfilter_8 v0, 1
+    hfilter_8 v1, 1
+    hfilter_8 v2, 1
+    hfilter_8 v3, 1
+    hfilter_8 v4, 1
+    hfilter_8 v5, 1
+    hfilter_8 v6, 1
+    hfilter_8 v7, 1
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional line that is needed
+    ;#  for the vertical filter.
+    beq     store_out_8x8_b
+
+    hfilter_8 v8, 0
+
+    b   second_pass_8x8_b
+
+second_pass_8x8_pre_copy_b:
+    slwi    r6, r6, 5           ;# index into vertical filter array
+
+    load_and_align_8  v0, 1
+    load_and_align_8  v1, 1
+    load_and_align_8  v2, 1
+    load_and_align_8  v3, 1
+    load_and_align_8  v4, 1
+    load_and_align_8  v5, 1
+    load_and_align_8  v6, 1
+    load_and_align_8  v7, 1
+    load_and_align_8  v8, 0
+
+second_pass_8x8_b:
+    vspltish v20, 8
+    vspltish v18, 3
+    vslh    v18, v20, v18   ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    load_vfilter v20, v21
+
+    vfilter_16 v0,  v1
+    vfilter_16 v1,  v2
+    vfilter_16 v2,  v3
+    vfilter_16 v3,  v4
+    vfilter_16 v4,  v5
+    vfilter_16 v5,  v6
+    vfilter_16 v6,  v7
+    vfilter_16 v7,  v8
+
+store_out_8x8_b:
+
+    cmpi    cr0, r8, 8
+    beq     cr0, store_aligned_8x8_b
+
+    w_8x8   v0, r7, r0, r8
+    w_8x8   v1, r7, r0, r8
+    w_8x8   v2, r7, r0, r8
+    w_8x8   v3, r7, r0, r8
+    w_8x8   v4, r7, r0, r8
+    w_8x8   v5, r7, r0, r8
+    w_8x8   v6, r7, r0, r8
+    w_8x8   v7, r7, r0, r8
+
+    b       exit_8x8
+
+store_aligned_8x8_b:
+    load_c v10, b_hilo_b, 0, r9, r10
+
+    vperm   v0, v0, v1, v10
+    vperm   v2, v2, v3, v10
+    vperm   v4, v4, v5, v10
+    vperm   v6, v6, v7, v10
+
+    stvx    v0, 0, r7
+    addi    r7, r7, 16
+    stvx    v2, 0, r7
+    addi    r7, r7, 16
+    stvx    v4, 0, r7
+    addi    r7, r7, 16
+    stvx    v6, 0, r7
+
+exit_8x8:
+
+    addi    r1, r1, 32          ;# recover stack
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+;# Filters a horizontal line
+;# expects:
+;#  r3  src_ptr
+;#  r4  pitch
+;#  r10 16
+;#  r12 32
+;#  v17 perm intput
+;#  v18 rounding
+;#  v19 shift
+;#  v20 filter taps
+;#  v21 tmp
+;#  v22 tmp
+;#  v23 tmp
+;#  v24 tmp
+;#  v25 tmp
+;#  v26 tmp
+;#  v27 tmp
+;#  v28 perm output
+;#
+.macro hfilter_16 V, increment_counter
+
+    lvsl    v17,  0, r3         ;# permutate value for alignment
+
+    ;# input to filter is 21 bytes wide, output is 16 bytes.
+    ;#  input will can span three vectors if not aligned correctly.
+    lvx     v21,   0, r3
+    lvx     v22, r10, r3
+    lvx     v23, r12, r3
+
+.if \increment_counter
+    add     r3, r3, r4
+.endif
+    vperm   v21, v21, v22, v17
+    vperm   v22, v22, v23, v17  ;# v8 v9 = 21 input pixels left-justified
+
+    ;# set 0
+    vmsummbm v24, v20, v21, v18 ;# taps times elements
+
+    ;# set 1
+    vsldoi  v23, v21, v22, 1
+    vmsummbm v25, v20, v23, v18
+
+    ;# set 2
+    vsldoi  v23, v21, v22, 2
+    vmsummbm v26, v20, v23, v18
+
+    ;# set 3
+    vsldoi  v23, v21, v22, 3
+    vmsummbm v27, v20, v23, v18
+
+    vpkswus v24, v24, v25       ;# v24 = 0 4 8 C 1 5 9 D (16-bit)
+    vpkswus v25, v26, v27       ;# v25 = 2 6 A E 3 7 B F
+
+    vsrh    v24, v24, v19       ;# divide v0, v1 by 128
+    vsrh    v25, v25, v19
+
+    vpkuhus \V, v24, v25        ;# \V = scrambled 8-bit result
+    vperm   \V, \V, v0, v28     ;# \V = correctly-ordered result
+.endm
+
+.macro load_and_align_16 V, increment_counter
+    lvsl    v17,  0, r3         ;# permutate value for alignment
+
+    ;# input to filter is 21 bytes wide, output is 16 bytes.
+    ;#  input will can span three vectors if not aligned correctly.
+    lvx     v21,   0, r3
+    lvx     v22, r10, r3
+
+.if \increment_counter
+    add     r3, r3, r4
+.endif
+
+    vperm   \V, v21, v22, v17
+.endm
+
+.macro write_16 V, increment_counter
+    stvx    \V,  0, r7
+
+.if \increment_counter
+    add     r7, r7, r8
+.endif
+.endm
+
+    .align 2
+;# r3 unsigned char * src
+;# r4 int src_pitch
+;# r5 int x_offset
+;# r6 int y_offset
+;# r7 unsigned char * dst
+;# r8 int dst_pitch
+bilinear_predict16x16_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xfff8
+    mtspr   256, r12            ;# set VRSAVE
+
+    HProlog second_pass_16x16_pre_copy_b
+
+    hfilter_16 v0,  1
+    hfilter_16 v1,  1
+    hfilter_16 v2,  1
+    hfilter_16 v3,  1
+    hfilter_16 v4,  1
+    hfilter_16 v5,  1
+    hfilter_16 v6,  1
+    hfilter_16 v7,  1
+    hfilter_16 v8,  1
+    hfilter_16 v9,  1
+    hfilter_16 v10, 1
+    hfilter_16 v11, 1
+    hfilter_16 v12, 1
+    hfilter_16 v13, 1
+    hfilter_16 v14, 1
+    hfilter_16 v15, 1
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional line that is needed
+    ;#  for the vertical filter.
+    beq     store_out_16x16_b
+
+    hfilter_16 v16, 0
+
+    b   second_pass_16x16_b
+
+second_pass_16x16_pre_copy_b:
+    slwi    r6, r6, 5           ;# index into vertical filter array
+
+    load_and_align_16  v0,  1
+    load_and_align_16  v1,  1
+    load_and_align_16  v2,  1
+    load_and_align_16  v3,  1
+    load_and_align_16  v4,  1
+    load_and_align_16  v5,  1
+    load_and_align_16  v6,  1
+    load_and_align_16  v7,  1
+    load_and_align_16  v8,  1
+    load_and_align_16  v9,  1
+    load_and_align_16  v10, 1
+    load_and_align_16  v11, 1
+    load_and_align_16  v12, 1
+    load_and_align_16  v13, 1
+    load_and_align_16  v14, 1
+    load_and_align_16  v15, 1
+    load_and_align_16  v16, 0
+
+second_pass_16x16_b:
+    vspltish v20, 8
+    vspltish v18, 3
+    vslh    v18, v20, v18   ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    load_vfilter v20, v21
+
+    vfilter_16 v0,  v1
+    vfilter_16 v1,  v2
+    vfilter_16 v2,  v3
+    vfilter_16 v3,  v4
+    vfilter_16 v4,  v5
+    vfilter_16 v5,  v6
+    vfilter_16 v6,  v7
+    vfilter_16 v7,  v8
+    vfilter_16 v8,  v9
+    vfilter_16 v9,  v10
+    vfilter_16 v10, v11
+    vfilter_16 v11, v12
+    vfilter_16 v12, v13
+    vfilter_16 v13, v14
+    vfilter_16 v14, v15
+    vfilter_16 v15, v16
+
+store_out_16x16_b:
+
+    write_16 v0,  1
+    write_16 v1,  1
+    write_16 v2,  1
+    write_16 v3,  1
+    write_16 v4,  1
+    write_16 v5,  1
+    write_16 v6,  1
+    write_16 v7,  1
+    write_16 v8,  1
+    write_16 v9,  1
+    write_16 v10, 1
+    write_16 v11, 1
+    write_16 v12, 1
+    write_16 v13, 1
+    write_16 v14, 1
+    write_16 v15, 0
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .data
+
+    .align 4
+hfilter_b:
+    .byte   128,  0,  0,  0,128,  0,  0,  0,128,  0,  0,  0,128,  0,  0,  0
+    .byte   112, 16,  0,  0,112, 16,  0,  0,112, 16,  0,  0,112, 16,  0,  0
+    .byte    96, 32,  0,  0, 96, 32,  0,  0, 96, 32,  0,  0, 96, 32,  0,  0
+    .byte    80, 48,  0,  0, 80, 48,  0,  0, 80, 48,  0,  0, 80, 48,  0,  0
+    .byte    64, 64,  0,  0, 64, 64,  0,  0, 64, 64,  0,  0, 64, 64,  0,  0
+    .byte    48, 80,  0,  0, 48, 80,  0,  0, 48, 80,  0,  0, 48, 80,  0,  0
+    .byte    32, 96,  0,  0, 32, 96,  0,  0, 32, 96,  0,  0, 32, 96,  0,  0
+    .byte    16,112,  0,  0, 16,112,  0,  0, 16,112,  0,  0, 16,112,  0,  0
+
+    .align 4
+vfilter_b:
+    .byte   128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128
+    .byte     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    .byte   112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112
+    .byte    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
+    .byte    96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96
+    .byte    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
+    .byte    80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80
+    .byte    48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48
+    .byte    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
+    .byte    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
+    .byte    48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48
+    .byte    80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80
+    .byte    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
+    .byte    96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96
+    .byte    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
+    .byte   112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112
+
+    .align 4
+b_hperm_b:
+    .byte     0,  4,  8, 12,  1,  5,  9, 13,  2,  6, 10, 14,  3,  7, 11, 15
+
+    .align 4
+b_0123_b:
+    .byte     0,  1,  2,  3,  1,  2,  3,  4,  2,  3,  4,  5,  3,  4,  5,  6
+
+    .align 4
+b_4567_b:
+    .byte     4,  5,  6,  7,  5,  6,  7,  8,  6,  7,  8,  9,  7,  8,  9, 10
+
+b_hilo_b:
+    .byte     0,  1,  2,  3,  4,  5,  6,  7, 16, 17, 18, 19, 20, 21, 22, 23
diff --git a/vp8/common/ppc/idctllm_altivec.asm b/vp8/common/ppc/idctllm_altivec.asm
new file mode 100644 (file)
index 0000000..117d9cf
--- /dev/null
@@ -0,0 +1,189 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    .globl short_idct4x4llm_ppc
+
+.macro load_c V, LABEL, OFF, R0, R1
+    lis     \R0, \LABEL@ha
+    la      \R1, \LABEL@l(\R0)
+    lvx     \V, \OFF, \R1
+.endm
+
+;# r3 short *input
+;# r4 short *output
+;# r5 int pitch
+    .align 2
+short_idct4x4llm_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xfff8
+    mtspr   256, r12            ;# set VRSAVE
+
+    load_c v8, sinpi8sqrt2, 0, r9, r10
+    load_c v9, cospi8sqrt2minus1, 0, r9, r10
+    load_c v10, hi_hi, 0, r9, r10
+    load_c v11, lo_lo, 0, r9, r10
+    load_c v12, shift_16, 0, r9, r10
+
+    li      r10,  16
+    lvx     v0,   0, r3         ;# input ip[0], ip[ 4]
+    lvx     v1, r10, r3         ;# input ip[8], ip[12]
+
+    ;# first pass
+    vupkhsh v2, v0
+    vupkhsh v3, v1
+    vaddsws v6, v2, v3          ;# a1 = ip[0]+ip[8]
+    vsubsws v7, v2, v3          ;# b1 = ip[0]-ip[8]
+
+    vupklsh v0, v0
+    vmulosh v4, v0, v8
+    vsraw   v4, v4, v12
+    vaddsws v4, v4, v0          ;# ip[ 4] * sin(pi/8) * sqrt(2)
+
+    vupklsh v1, v1
+    vmulosh v5, v1, v9
+    vsraw   v5, v5, v12         ;# ip[12] * cos(pi/8) * sqrt(2)
+    vaddsws v5, v5, v1
+
+    vsubsws v4, v4, v5          ;# c1
+
+    vmulosh v3, v1, v8
+    vsraw   v3, v3, v12
+    vaddsws v3, v3, v1          ;# ip[12] * sin(pi/8) * sqrt(2)
+
+    vmulosh v5, v0, v9
+    vsraw   v5, v5, v12         ;# ip[ 4] * cos(pi/8) * sqrt(2)
+    vaddsws v5, v5, v0
+
+    vaddsws v3, v3, v5          ;# d1
+
+    vaddsws v0, v6, v3          ;# a1 + d1
+    vsubsws v3, v6, v3          ;# a1 - d1
+
+    vaddsws v1, v7, v4          ;# b1 + c1
+    vsubsws v2, v7, v4          ;# b1 - c1
+
+    ;# transpose input
+    vmrghw  v4, v0, v1          ;# a0 b0 a1 b1
+    vmrghw  v5, v2, v3          ;# c0 d0 c1 d1
+
+    vmrglw  v6, v0, v1          ;# a2 b2 a3 b3
+    vmrglw  v7, v2, v3          ;# c2 d2 c3 d3
+
+    vperm   v0, v4, v5, v10     ;# a0 b0 c0 d0
+    vperm   v1, v4, v5, v11     ;# a1 b1 c1 d1
+
+    vperm   v2, v6, v7, v10     ;# a2 b2 c2 d2
+    vperm   v3, v6, v7, v11     ;# a3 b3 c3 d3
+
+    ;# second pass
+    vaddsws v6, v0, v2          ;# a1 = ip[0]+ip[8]
+    vsubsws v7, v0, v2          ;# b1 = ip[0]-ip[8]
+
+    vmulosh v4, v1, v8
+    vsraw   v4, v4, v12
+    vaddsws v4, v4, v1          ;# ip[ 4] * sin(pi/8) * sqrt(2)
+
+    vmulosh v5, v3, v9
+    vsraw   v5, v5, v12         ;# ip[12] * cos(pi/8) * sqrt(2)
+    vaddsws v5, v5, v3
+
+    vsubsws v4, v4, v5          ;# c1
+
+    vmulosh v2, v3, v8
+    vsraw   v2, v2, v12
+    vaddsws v2, v2, v3          ;# ip[12] * sin(pi/8) * sqrt(2)
+
+    vmulosh v5, v1, v9
+    vsraw   v5, v5, v12         ;# ip[ 4] * cos(pi/8) * sqrt(2)
+    vaddsws v5, v5, v1
+
+    vaddsws v3, v2, v5          ;# d1
+
+    vaddsws v0, v6, v3          ;# a1 + d1
+    vsubsws v3, v6, v3          ;# a1 - d1
+
+    vaddsws v1, v7, v4          ;# b1 + c1
+    vsubsws v2, v7, v4          ;# b1 - c1
+
+    vspltish v6, 4
+    vspltish v7, 3
+
+    vpkswss v0, v0, v1
+    vpkswss v1, v2, v3
+
+    vaddshs v0, v0, v6
+    vaddshs v1, v1, v6
+
+    vsrah   v0, v0, v7
+    vsrah   v1, v1, v7
+
+    ;# transpose output
+    vmrghh  v2, v0, v1          ;# a0 c0 a1 c1 a2 c2 a3 c3
+    vmrglh  v3, v0, v1          ;# b0 d0 b1 d1 b2 d2 b3 d3
+
+    vmrghh  v0, v2, v3          ;# a0 b0 c0 d0 a1 b1 c1 d1
+    vmrglh  v1, v2, v3          ;# a2 b2 c2 d2 a3 b3 c3 d3
+
+    stwu    r1,-416(r1)         ;# create space on the stack
+
+    stvx    v0,  0, r1
+    lwz     r6, 0(r1)
+    stw     r6, 0(r4)
+    lwz     r6, 4(r1)
+    stw     r6, 4(r4)
+
+    add     r4, r4, r5
+
+    lwz     r6,  8(r1)
+    stw     r6,  0(r4)
+    lwz     r6, 12(r1)
+    stw     r6,  4(r4)
+
+    add     r4, r4, r5
+
+    stvx    v1,  0, r1
+    lwz     r6, 0(r1)
+    stw     r6, 0(r4)
+    lwz     r6, 4(r1)
+    stw     r6, 4(r4)
+
+    add     r4, r4, r5
+
+    lwz     r6,  8(r1)
+    stw     r6,  0(r4)
+    lwz     r6, 12(r1)
+    stw     r6,  4(r4)
+
+    addi    r1, r1, 416         ;# recover stack
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .align 4
+sinpi8sqrt2:
+    .short  35468, 35468, 35468, 35468, 35468, 35468, 35468, 35468
+
+    .align 4
+cospi8sqrt2minus1:
+    .short  20091, 20091, 20091, 20091, 20091, 20091, 20091, 20091
+
+    .align 4
+shift_16:
+    .long      16,    16,    16,    16
+
+    .align 4
+hi_hi:
+    .byte     0,  1,  2,  3,  4,  5,  6,  7, 16, 17, 18, 19, 20, 21, 22, 23
+
+    .align 4
+lo_lo:
+    .byte     8,  9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31
diff --git a/vp8/common/ppc/loopfilter_altivec.c b/vp8/common/ppc/loopfilter_altivec.c
new file mode 100644 (file)
index 0000000..71bf6e2
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "loopfilter.h"
+#include "onyxc_int.h"
+
+typedef void loop_filter_function_y_ppc
+(
+    unsigned char *s,   // source pointer
+    int p,              // pitch
+    const signed char *flimit,
+    const signed char *limit,
+    const signed char *thresh
+);
+
+typedef void loop_filter_function_uv_ppc
+(
+    unsigned char *u,   // source pointer
+    unsigned char *v,   // source pointer
+    int p,              // pitch
+    const signed char *flimit,
+    const signed char *limit,
+    const signed char *thresh
+);
+
+typedef void loop_filter_function_s_ppc
+(
+    unsigned char *s,   // source pointer
+    int p,              // pitch
+    const signed char *flimit
+);
+
+loop_filter_function_y_ppc mbloop_filter_horizontal_edge_y_ppc;
+loop_filter_function_y_ppc mbloop_filter_vertical_edge_y_ppc;
+loop_filter_function_y_ppc loop_filter_horizontal_edge_y_ppc;
+loop_filter_function_y_ppc loop_filter_vertical_edge_y_ppc;
+
+loop_filter_function_uv_ppc mbloop_filter_horizontal_edge_uv_ppc;
+loop_filter_function_uv_ppc mbloop_filter_vertical_edge_uv_ppc;
+loop_filter_function_uv_ppc loop_filter_horizontal_edge_uv_ppc;
+loop_filter_function_uv_ppc loop_filter_vertical_edge_uv_ppc;
+
+loop_filter_function_s_ppc loop_filter_simple_horizontal_edge_ppc;
+loop_filter_function_s_ppc loop_filter_simple_vertical_edge_ppc;
+
+// Horizontal MB filtering
+void loop_filter_mbh_ppc(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                         int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    mbloop_filter_horizontal_edge_y_ppc(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->thr);
+
+    if (u_ptr)
+        mbloop_filter_horizontal_edge_uv_ppc(u_ptr, v_ptr, uv_stride, lfi->mbflim, lfi->lim, lfi->thr);
+}
+
+void loop_filter_mbhs_ppc(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                          int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    (void)u_ptr;
+    (void)v_ptr;
+    (void)uv_stride;
+    loop_filter_simple_horizontal_edge_ppc(y_ptr, y_stride, lfi->mbflim);
+}
+
+// Vertical MB Filtering
+void loop_filter_mbv_ppc(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                         int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    mbloop_filter_vertical_edge_y_ppc(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->thr);
+
+    if (u_ptr)
+        mbloop_filter_vertical_edge_uv_ppc(u_ptr, v_ptr, uv_stride, lfi->mbflim, lfi->lim, lfi->thr);
+}
+
+void loop_filter_mbvs_ppc(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                          int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    (void)u_ptr;
+    (void)v_ptr;
+    (void)uv_stride;
+    loop_filter_simple_vertical_edge_ppc(y_ptr, y_stride, lfi->mbflim);
+}
+
+// Horizontal B Filtering
+void loop_filter_bh_ppc(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                        int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    // These should all be done at once with one call, instead of 3
+    loop_filter_horizontal_edge_y_ppc(y_ptr + 4 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr);
+    loop_filter_horizontal_edge_y_ppc(y_ptr + 8 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr);
+    loop_filter_horizontal_edge_y_ppc(y_ptr + 12 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr);
+
+    if (u_ptr)
+        loop_filter_horizontal_edge_uv_ppc(u_ptr + 4 * uv_stride, v_ptr + 4 * uv_stride, uv_stride, lfi->flim, lfi->lim, lfi->thr);
+}
+
+void loop_filter_bhs_ppc(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                         int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    (void)u_ptr;
+    (void)v_ptr;
+    (void)uv_stride;
+    loop_filter_simple_horizontal_edge_ppc(y_ptr + 4 * y_stride, y_stride, lfi->flim);
+    loop_filter_simple_horizontal_edge_ppc(y_ptr + 8 * y_stride, y_stride, lfi->flim);
+    loop_filter_simple_horizontal_edge_ppc(y_ptr + 12 * y_stride, y_stride, lfi->flim);
+}
+
+// Vertical B Filtering
+void loop_filter_bv_ppc(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                        int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    loop_filter_vertical_edge_y_ppc(y_ptr, y_stride, lfi->flim, lfi->lim, lfi->thr);
+
+    if (u_ptr)
+        loop_filter_vertical_edge_uv_ppc(u_ptr + 4, v_ptr + 4, uv_stride, lfi->flim, lfi->lim, lfi->thr);
+}
+
+void loop_filter_bvs_ppc(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                         int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    (void)u_ptr;
+    (void)v_ptr;
+    (void)uv_stride;
+    loop_filter_simple_vertical_edge_ppc(y_ptr + 4,  y_stride, lfi->flim);
+    loop_filter_simple_vertical_edge_ppc(y_ptr + 8,  y_stride, lfi->flim);
+    loop_filter_simple_vertical_edge_ppc(y_ptr + 12, y_stride, lfi->flim);
+}
diff --git a/vp8/common/ppc/loopfilter_filters_altivec.asm b/vp8/common/ppc/loopfilter_filters_altivec.asm
new file mode 100644 (file)
index 0000000..61df4e9
--- /dev/null
@@ -0,0 +1,1253 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    .globl mbloop_filter_horizontal_edge_y_ppc
+    .globl loop_filter_horizontal_edge_y_ppc
+    .globl mbloop_filter_vertical_edge_y_ppc
+    .globl loop_filter_vertical_edge_y_ppc
+
+    .globl mbloop_filter_horizontal_edge_uv_ppc
+    .globl loop_filter_horizontal_edge_uv_ppc
+    .globl mbloop_filter_vertical_edge_uv_ppc
+    .globl loop_filter_vertical_edge_uv_ppc
+
+    .globl loop_filter_simple_horizontal_edge_ppc
+    .globl loop_filter_simple_vertical_edge_ppc
+
+    .text
+;# We often need to perform transposes (and other transpose-like operations)
+;#   on matrices of data.  This is simplified by the fact that we usually
+;#   operate on hunks of data whose dimensions are powers of 2, or at least
+;#   divisible by highish powers of 2.
+;#
+;#   These operations can be very confusing.  They become more straightforward
+;#   when we think of them as permutations of address bits: Concatenate a
+;#   group of vector registers and think of it as occupying a block of
+;#   memory beginning at address zero.  The low four bits 0...3 of the
+;#   address then correspond to position within a register, the higher-order
+;#   address bits select the register.
+;#
+;#   Although register selection, at the code level, is arbitrary, things
+;#   are simpler if we use contiguous ranges of register numbers, simpler
+;#   still if the low-order bits of the register number correspond to
+;#   conceptual address bits.  We do this whenever reasonable.
+;#
+;#   A 16x16 transpose can then be thought of as an operation on
+;#   a 256-element block of memory.  It takes 8 bits 0...7 to address this
+;#   memory and the effect of a transpose is to interchange address bit
+;#   0 with 4, 1 with 5, 2 with 6, and 3 with 7.  Bits 0...3 index the
+;#   column, which is interchanged with the row addressed by bits 4..7.
+;#
+;#   The altivec merge instructions provide a rapid means of effecting
+;#   many of these transforms.  They operate at three widths (8,16,32).
+;#   Writing V(x) for vector register #x, paired merges permute address
+;#   indices as follows.
+;#
+;#   0->1  1->2  2->3  3->(4+d)  (4+s)->0:
+;#
+;#      vmrghb  V( x),          V( y), V( y + (1<<s))
+;#      vmrglb  V( x + (1<<d)), V( y), V( y + (1<<s))
+;#
+;#
+;#   =0=   1->2  2->3  3->(4+d)  (4+s)->1:
+;#
+;#      vmrghh  V( x),          V( y), V( y + (1<<s))
+;#      vmrglh  V( x + (1<<d)), V( y), V( y + (1<<s))
+;#
+;#
+;#   =0=   =1=   2->3  3->(4+d)  (4+s)->2:
+;#
+;#      vmrghw  V( x),          V( y), V( y + (1<<s))
+;#      vmrglw  V( x + (1<<d)), V( y), V( y + (1<<s))
+;#
+;#
+;#   Unfortunately, there is no doubleword merge instruction.
+;#   The following sequence uses "vperm" is a substitute.
+;#   Assuming that the selection masks b_hihi and b_lolo (defined in LFppc.c)
+;#   are in registers Vhihi and Vlolo, we can also effect the permutation
+;#
+;#   =0=   =1=   =2=   3->(4+d)  (4+s)->3   by the sequence:
+;#
+;#      vperm   V( x),          V( y), V( y + (1<<s)), Vhihi
+;#      vperm   V( x + (1<<d)), V( y), V( y + (1<<s)), Vlolo
+;#
+;#
+;#   Except for bits s and d, the other relationships between register
+;#   number (= high-order part of address) bits are at the disposal of
+;#   the programmer.
+;#
+
+;# To avoid excess transposes, we filter all 3 vertical luma subblock
+;#   edges together.  This requires a single 16x16 transpose, which, in
+;#   the above language, amounts to the following permutation of address
+;#   indices:  0<->4   1<->5  2<->6  3<->7, which we accomplish by
+;#   4 iterations of the cyclic transform 0->1->2->3->4->5->6->7->0.
+;#
+;#   Except for the fact that the destination registers get written
+;#   before we are done referencing the old contents, the cyclic transform
+;#   is effected by
+;#
+;#      x = 0;  do {
+;#          vmrghb V(2x),   V(x), V(x+8);
+;#          vmrghb V(2x+1), V(x), V(x+8);
+;#      } while( ++x < 8);
+;#
+;#   For clarity, and because we can afford it, we do this transpose
+;#   using all 32 registers, alternating the banks 0..15  and  16 .. 31,
+;#   leaving the final result in 16 .. 31, as the lower registers are
+;#   used in the filtering itself.
+;#
+.macro Tpair A, B, X, Y
+    vmrghb  \A, \X, \Y
+    vmrglb  \B, \X, \Y
+.endm
+
+;# Each step takes 8*2 = 16 instructions
+
+.macro t16_even
+    Tpair v16,v17,  v0,v8
+    Tpair v18,v19,  v1,v9
+    Tpair v20,v21,  v2,v10
+    Tpair v22,v23,  v3,v11
+    Tpair v24,v25,  v4,v12
+    Tpair v26,v27,  v5,v13
+    Tpair v28,v29,  v6,v14
+    Tpair v30,v31,  v7,v15
+.endm
+
+.macro t16_odd
+    Tpair v0,v1, v16,v24
+    Tpair v2,v3, v17,v25
+    Tpair v4,v5, v18,v26
+    Tpair v6,v7, v19,v27
+    Tpair v8,v9, v20,v28
+    Tpair v10,v11, v21,v29
+    Tpair v12,v13, v22,v30
+    Tpair v14,v15, v23,v31
+.endm
+
+;# Whole transpose takes 4*16 = 64 instructions
+
+.macro t16_full
+    t16_odd
+    t16_even
+    t16_odd
+    t16_even
+.endm
+
+;# Vertical edge filtering requires transposes.  For the simple filter,
+;#   we need to convert 16 rows of 4 pels each into 4 registers of 16 pels
+;#   each.  Writing 0 ... 63 for the pixel indices, the desired result is:
+;#
+;#  v0 =  0  1 ... 14 15
+;#  v1 = 16 17 ... 30 31
+;#  v2 = 32 33 ... 47 48
+;#  v3 = 49 50 ... 62 63
+;#
+;#  In frame-buffer memory, the layout is:
+;#
+;#     0  16  32  48
+;#     1  17  33  49
+;#     ...
+;#    15  31  47  63.
+;#
+;#  We begin by reading the data 32 bits at a time (using scalar operations)
+;#  into a temporary array, reading the rows of the array into vector registers,
+;#  with the following layout:
+;#
+;#  v0 =  0 16 32 48  4 20 36 52  8 24 40 56  12 28 44 60
+;#  v1 =  1 17 33 49  5 21 ...                      45 61
+;#  v2 =  2 18 ...                                  46 62
+;#  v3 =  3 19 ...                                  47 63
+;#
+;#  From the "address-bit" perspective discussed above, we simply need to
+;#  interchange bits 0 <-> 4 and 1 <-> 5, leaving bits 2 and 3 alone.
+;#  In other words, we transpose each of the four 4x4 submatrices.
+;#
+;#  This transformation is its own inverse, and we need to perform it
+;#  again before writing the pixels back into the frame buffer.
+;#
+;#  It acts in place on registers v0...v3, uses v4...v7 as temporaries,
+;#  and assumes that v14/v15 contain the b_hihi/b_lolo selectors
+;#  defined above.  We think of both groups of 4 registers as having
+;#  "addresses" {0,1,2,3} * 16.
+;#
+.macro Transpose4times4x4 Vlo, Vhi
+
+    ;# d=s=0        0->1  1->2  2->3  3->4  4->0  =5=
+
+    vmrghb  v4, v0, v1
+    vmrglb  v5, v0, v1
+    vmrghb  v6, v2, v3
+    vmrglb  v7, v2, v3
+
+    ;# d=0 s=1      =0=   1->2  2->3  3->4  4->5  5->1
+
+    vmrghh  v0, v4, v6
+    vmrglh  v1, v4, v6
+    vmrghh  v2, v5, v7
+    vmrglh  v3, v5, v7
+
+    ;# d=s=0        =0=   =1=   2->3  3->4  4->2  =5=
+
+    vmrghw  v4, v0, v1
+    vmrglw  v5, v0, v1
+    vmrghw  v6, v2, v3
+    vmrglw  v7, v2, v3
+
+    ;# d=0  s=1     =0=   =1=   =2=   3->4  4->5  5->3
+
+    vperm   v0, v4, v6, \Vlo
+    vperm   v1, v4, v6, \Vhi
+    vperm   v2, v5, v7, \Vlo
+    vperm   v3, v5, v7, \Vhi
+.endm
+;# end Transpose4times4x4
+
+
+;# Normal mb vertical edge filter transpose.
+;#
+;#   We read 8 columns of data, initially in the following pattern:
+;#
+;#  (0,0)  (1,0) ... (7,0)  (0,1)  (1,1) ... (7,1)
+;#  (0,2)  (1,2) ... (7,2)  (0,3)  (1,3) ... (7,3)
+;#  ...
+;#  (0,14) (1,14) .. (7,14) (0,15) (1,15) .. (7,15)
+;#
+;#   and wish to convert to:
+;#
+;#  (0,0) ... (0,15)
+;#  (1,0) ... (1,15)
+;#  ...
+;#  (7,0) ... (7,15).
+;#
+;#  In "address bit" language, we wish to map
+;#
+;#  0->4  1->5  2->6  3->0  4->1  5->2  6->3, i.e., I -> (I+4) mod 7.
+;#
+;#  This can be accomplished by 4 iterations of the cyclic transform
+;#
+;#  I -> (I+1) mod 7;
+;#
+;#  each iteration can be realized by (d=0, s=2):
+;#
+;#  x = 0;  do  Tpair( V(2x),V(2x+1),  V(x),V(x+4))  while( ++x < 4);
+;#
+;#  The input/output is in registers v0...v7.  We use v10...v17 as mirrors;
+;#  preserving v8 = sign converter.
+;#
+;#  Inverse transpose is similar, except here I -> (I+3) mod 7 and the
+;#  result lands in the "mirror" registers v10...v17
+;#
+.macro t8x16_odd
+    Tpair v10, v11,  v0, v4
+    Tpair v12, v13,  v1, v5
+    Tpair v14, v15,  v2, v6
+    Tpair v16, v17,  v3, v7
+.endm
+
+.macro t8x16_even
+    Tpair v0, v1,  v10, v14
+    Tpair v2, v3,  v11, v15
+    Tpair v4, v5,  v12, v16
+    Tpair v6, v7,  v13, v17
+.endm
+
+.macro transpose8x16_fwd
+    t8x16_odd
+    t8x16_even
+    t8x16_odd
+    t8x16_even
+.endm
+
+.macro transpose8x16_inv
+    t8x16_odd
+    t8x16_even
+    t8x16_odd
+.endm
+
+.macro Transpose16x16
+    vmrghb  v0, v16, v24
+    vmrglb  v1, v16, v24
+    vmrghb  v2, v17, v25
+    vmrglb  v3, v17, v25
+    vmrghb  v4, v18, v26
+    vmrglb  v5, v18, v26
+    vmrghb  v6, v19, v27
+    vmrglb  v7, v19, v27
+    vmrghb  v8, v20, v28
+    vmrglb  v9, v20, v28
+    vmrghb  v10, v21, v29
+    vmrglb  v11, v21, v29
+    vmrghb  v12, v22, v30
+    vmrglb  v13, v22, v30
+    vmrghb  v14, v23, v31
+    vmrglb  v15, v23, v31
+    vmrghb  v16, v0, v8
+    vmrglb  v17, v0, v8
+    vmrghb  v18, v1, v9
+    vmrglb  v19, v1, v9
+    vmrghb  v20, v2, v10
+    vmrglb  v21, v2, v10
+    vmrghb  v22, v3, v11
+    vmrglb  v23, v3, v11
+    vmrghb  v24, v4, v12
+    vmrglb  v25, v4, v12
+    vmrghb  v26, v5, v13
+    vmrglb  v27, v5, v13
+    vmrghb  v28, v6, v14
+    vmrglb  v29, v6, v14
+    vmrghb  v30, v7, v15
+    vmrglb  v31, v7, v15
+    vmrghb  v0, v16, v24
+    vmrglb  v1, v16, v24
+    vmrghb  v2, v17, v25
+    vmrglb  v3, v17, v25
+    vmrghb  v4, v18, v26
+    vmrglb  v5, v18, v26
+    vmrghb  v6, v19, v27
+    vmrglb  v7, v19, v27
+    vmrghb  v8, v20, v28
+    vmrglb  v9, v20, v28
+    vmrghb  v10, v21, v29
+    vmrglb  v11, v21, v29
+    vmrghb  v12, v22, v30
+    vmrglb  v13, v22, v30
+    vmrghb  v14, v23, v31
+    vmrglb  v15, v23, v31
+    vmrghb  v16, v0, v8
+    vmrglb  v17, v0, v8
+    vmrghb  v18, v1, v9
+    vmrglb  v19, v1, v9
+    vmrghb  v20, v2, v10
+    vmrglb  v21, v2, v10
+    vmrghb  v22, v3, v11
+    vmrglb  v23, v3, v11
+    vmrghb  v24, v4, v12
+    vmrglb  v25, v4, v12
+    vmrghb  v26, v5, v13
+    vmrglb  v27, v5, v13
+    vmrghb  v28, v6, v14
+    vmrglb  v29, v6, v14
+    vmrghb  v30, v7, v15
+    vmrglb  v31, v7, v15
+.endm
+
+;# load_g loads a global vector (whose address is in the local variable Gptr)
+;#   into vector register Vreg.  Trashes r0
+.macro load_g Vreg, Gptr
+    lwz     r0, \Gptr
+    lvx     \Vreg, 0, r0
+.endm
+
+;# exploit the saturation here.  if the answer is negative
+;# it will be clamped to 0.  orring 0 with a positive
+;# number will be the positive number (abs)
+;# RES = abs( A-B), trashes TMP
+.macro Abs RES, TMP, A, B
+    vsububs \RES, \A, \B
+    vsububs \TMP, \B, \A
+    vor     \RES, \RES, \TMP
+.endm
+
+;# RES = Max( RES, abs( A-B)), trashes TMP
+.macro max_abs RES, TMP, A, B
+    vsububs \TMP, \A, \B
+    vmaxub  \RES, \RES, \TMP
+    vsububs \TMP, \B, \A
+    vmaxub  \RES, \RES, \TMP
+.endm
+
+.macro Masks
+    ;# build masks
+    ;# input is all 8 bit unsigned (0-255).  need to
+    ;# do abs(vala-valb) > limit.  but no need to compare each
+    ;# value to the limit.  find the max of the absolute differences
+    ;# and compare that to the limit.
+    ;# First hev
+    Abs     v14, v13, v2, v3    ;# |P1 - P0|
+    max_abs  v14, v13, v5, v4    ;# |Q1 - Q0|
+
+    vcmpgtub v10, v14, v10      ;# HEV = true if thresh exceeded
+
+    ;# Next limit
+    max_abs  v14, v13, v0, v1    ;# |P3 - P2|
+    max_abs  v14, v13, v1, v2    ;# |P2 - P1|
+    max_abs  v14, v13, v6, v5    ;# |Q2 - Q1|
+    max_abs  v14, v13, v7, v6    ;# |Q3 - Q2|
+
+    vcmpgtub v9, v14, v9        ;# R = true if limit exceeded
+
+    ;# flimit
+    Abs     v14, v13, v3, v4    ;# |P0 - Q0|
+
+    vcmpgtub v8, v14, v8        ;# X = true if flimit exceeded
+
+    vor     v8, v8, v9          ;# R = true if flimit or limit exceeded
+    ;# done building masks
+.endm
+
+.macro build_constants RFL, RLI, RTH, FL, LI, TH
+    ;# build constants
+    lvx     \FL, 0, \RFL        ;# flimit
+    lvx     \LI, 0, \RLI        ;# limit
+    lvx     \TH, 0, \RTH        ;# thresh
+
+    vspltisb v11, 8
+    vspltisb v12, 4
+    vslb    v11, v11, v12       ;# 0x80808080808080808080808080808080
+.endm
+
+.macro load_data_y
+    ;# setup strides/pointers to be able to access
+    ;# all of the data
+    add     r5, r4, r4          ;# r5 = 2 * stride
+    sub     r6, r3, r5          ;# r6 -> 2 rows back
+    neg     r7, r4              ;# r7 = -stride
+
+    ;# load 16 pixels worth of data to work on
+    sub     r0, r6, r5          ;# r0 -> 4 rows back (temp)
+    lvx     v0,  0, r0          ;# P3  (read only)
+    lvx     v1, r7, r6          ;# P2
+    lvx     v2,  0, r6          ;# P1
+    lvx     v3, r7, r3          ;# P0
+    lvx     v4,  0, r3          ;# Q0
+    lvx     v5, r4, r3          ;# Q1
+    lvx     v6, r5, r3          ;# Q2
+    add     r0, r3, r5          ;# r0 -> 2 rows fwd (temp)
+    lvx     v7, r4, r0          ;# Q3  (read only)
+.endm
+
+;# Expects
+;#  v10 == HEV
+;#  v13 == tmp
+;#  v14 == tmp
+.macro common_adjust P0, Q0, P1, Q1, HEV_PRESENT
+    vxor    \P1, \P1, v11       ;# SP1
+    vxor    \P0, \P0, v11       ;# SP0
+    vxor    \Q0, \Q0, v11       ;# SQ0
+    vxor    \Q1, \Q1, v11       ;# SQ1
+
+    vsubsbs v13, \P1, \Q1       ;# f  = c (P1 - Q1)
+.if \HEV_PRESENT
+    vand    v13, v13, v10       ;# f &= hev
+.endif
+    vsubsbs v14, \Q0, \P0       ;# -126 <=  X = Q0-P0  <= +126
+    vaddsbs v13, v13, v14
+    vaddsbs v13, v13, v14
+    vaddsbs v13, v13, v14       ;# A = c( c(P1-Q1) + 3*(Q0-P0))
+
+    vandc   v13, v13, v8        ;# f &= mask
+
+    vspltisb v8, 3
+    vspltisb v9, 4
+
+    vaddsbs v14, v13, v9        ;# f1 = c (f+4)
+    vaddsbs v15, v13, v8        ;# f2 = c (f+3)
+
+    vsrab   v13, v14, v8        ;# f1 >>= 3
+    vsrab   v15, v15, v8        ;# f2 >>= 3
+
+    vsubsbs \Q0, \Q0, v13       ;# u1 = c (SQ0 - f1)
+    vaddsbs \P0, \P0, v15       ;# u2 = c (SP0 + f2)
+.endm
+
+.macro vp8_mbfilter
+    Masks
+
+    ;# start the fitering here
+    vxor    v1, v1, v11         ;# SP2
+    vxor    v2, v2, v11         ;# SP1
+    vxor    v3, v3, v11         ;# SP0
+    vxor    v4, v4, v11         ;# SQ0
+    vxor    v5, v5, v11         ;# SQ1
+    vxor    v6, v6, v11         ;# SQ2
+
+    ;# add outer taps if we have high edge variance
+    vsubsbs v13, v2, v5         ;# f  = c (SP1-SQ1)
+
+    vsubsbs v14, v4, v3         ;# SQ0-SP0
+    vaddsbs v13, v13, v14
+    vaddsbs v13, v13, v14
+    vaddsbs v13, v13, v14       ;# f  = c( c(SP1-SQ1) + 3*(SQ0-SP0))
+
+    vandc   v13, v13, v8        ;# f &= mask
+    vand    v15, v13, v10       ;# f2 = f & hev
+
+    ;# save bottom 3 bits so that we round one side +4 and the other +3
+    vspltisb v8, 3
+    vspltisb v9, 4
+
+    vaddsbs v14, v15, v9        ;# f1 = c (f+4)
+    vaddsbs v15, v15, v8        ;# f2 = c (f+3)
+
+    vsrab   v14, v14, v8        ;# f1 >>= 3
+    vsrab   v15, v15, v8        ;# f2 >>= 3
+
+    vsubsbs v4, v4, v14         ;# u1 = c (SQ0 - f1)
+    vaddsbs v3, v3, v15         ;# u2 = c (SP0 + f2)
+
+    ;# only apply wider filter if not high edge variance
+    vandc   v13, v13, v10       ;# f &= ~hev
+
+    vspltisb v9, 2
+    vnor    v8, v8, v8
+    vsrb    v9, v8, v9          ;# 0x3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f
+    vupkhsb v9, v9              ;# 0x003f003f003f003f003f003f003f003f
+    vspltisb v8, 9
+
+    ;# roughly 1/7th difference across boundary
+    vspltish v10, 7
+    vmulosb v14, v8, v13        ;# A = c( c(P1-Q1) + 3*(Q0-P0))
+    vmulesb v15, v8, v13
+    vaddshs v14, v14, v9        ;# +=  63
+    vaddshs v15, v15, v9
+    vsrah   v14, v14, v10       ;# >>= 7
+    vsrah   v15, v15, v10
+    vmrglh  v10, v15, v14
+    vmrghh  v15, v15, v14
+
+    vpkshss v10, v15, v10       ;# X = saturated down to bytes
+
+    vsubsbs v6, v6, v10         ;# subtract from Q and add to P
+    vaddsbs v1, v1, v10
+
+    vxor    v6, v6, v11
+    vxor    v1, v1, v11
+
+    ;# roughly 2/7th difference across boundary
+    vspltish v10, 7
+    vaddubm v12, v8, v8
+    vmulosb v14, v12, v13       ;# A = c( c(P1-Q1) + 3*(Q0-P0))
+    vmulesb v15, v12, v13
+    vaddshs v14, v14, v9
+    vaddshs v15, v15, v9
+    vsrah   v14, v14, v10       ;# >>= 7
+    vsrah   v15, v15, v10
+    vmrglh  v10, v15, v14
+    vmrghh  v15, v15, v14
+
+    vpkshss v10, v15, v10       ;# X = saturated down to bytes
+
+    vsubsbs v5, v5, v10         ;# subtract from Q and add to P
+    vaddsbs v2, v2, v10
+
+    vxor    v5, v5, v11
+    vxor    v2, v2, v11
+
+    ;# roughly 3/7th difference across boundary
+    vspltish v10, 7
+    vaddubm v12, v12, v8
+    vmulosb v14, v12, v13       ;# A = c( c(P1-Q1) + 3*(Q0-P0))
+    vmulesb v15, v12, v13
+    vaddshs v14, v14, v9
+    vaddshs v15, v15, v9
+    vsrah   v14, v14, v10       ;# >>= 7
+    vsrah   v15, v15, v10
+    vmrglh  v10, v15, v14
+    vmrghh  v15, v15, v14
+
+    vpkshss v10, v15, v10       ;# X = saturated down to bytes
+
+    vsubsbs v4, v4, v10         ;# subtract from Q and add to P
+    vaddsbs v3, v3, v10
+
+    vxor    v4, v4, v11
+    vxor    v3, v3, v11
+.endm
+
+.macro SBFilter
+    Masks
+
+    common_adjust v3, v4, v2, v5, 1
+
+    ;# outer tap adjustments
+    vspltisb v8, 1
+
+    vaddubm v13, v13, v8        ;# f  += 1
+    vsrab   v13, v13, v8        ;# f >>= 1
+
+    vandc   v13, v13, v10       ;# f &= ~hev
+
+    vsubsbs v5, v5, v13         ;# u1 = c (SQ1 - f)
+    vaddsbs v2, v2, v13         ;# u2 = c (SP1 + f)
+
+    vxor    v2, v2, v11
+    vxor    v3, v3, v11
+    vxor    v4, v4, v11
+    vxor    v5, v5, v11
+.endm
+
+    .align 2
+mbloop_filter_horizontal_edge_y_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    mtspr   256, r12            ;# set VRSAVE
+
+    build_constants r5, r6, r7, v8, v9, v10
+
+    load_data_y
+
+    vp8_mbfilter
+
+    stvx     v1, r7, r6         ;# P2
+    stvx     v2,  0, r6         ;# P1
+    stvx     v3, r7, r3         ;# P0
+    stvx     v4,  0, r3         ;# Q0
+    stvx     v5, r4, r3         ;# Q1
+    stvx     v6, r5, r3         ;# Q2
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .align 2
+;#  r3 unsigned char *s
+;#  r4 int p
+;#  r5 const signed char *flimit
+;#  r6 const signed char *limit
+;#  r7 const signed char *thresh
+loop_filter_horizontal_edge_y_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    mtspr   256, r12            ;# set VRSAVE
+
+    build_constants r5, r6, r7, v8, v9, v10
+
+    load_data_y
+
+    SBFilter
+
+    stvx     v2,  0, r6         ;# P1
+    stvx     v3, r7, r3         ;# P0
+    stvx     v4,  0, r3         ;# Q0
+    stvx     v5, r4, r3         ;# Q1
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+;# Filtering a vertical mb.  Each mb is aligned on a 16 byte boundary.
+;#  So we can read in an entire mb aligned.  However if we want to filter the mb
+;#  edge we run into problems.  For the loopfilter we require 4 bytes before the mb
+;#  and 4 after for a total of 8 bytes.  Reading 16 bytes inorder to get 4 is a bit
+;#  of a waste.  So this is an even uglier way to get around that.
+;# Using the regular register file words are read in and then saved back out to
+;#  memory to align and order them up.  Then they are read in using the
+;#  vector register file.
+.macro RLVmb V, R
+    lwzux   r0, r3, r4
+    stw     r0, 4(\R)
+    lwz     r0,-4(r3)
+    stw     r0, 0(\R)
+    lwzux   r0, r3, r4
+    stw     r0,12(\R)
+    lwz     r0,-4(r3)
+    stw     r0, 8(\R)
+    lvx     \V, 0, \R
+.endm
+
+.macro WLVmb V, R
+    stvx    \V, 0, \R
+    lwz     r0,12(\R)
+    stwux   r0, r3, r4
+    lwz     r0, 8(\R)
+    stw     r0,-4(r3)
+    lwz     r0, 4(\R)
+    stwux   r0, r3, r4
+    lwz     r0, 0(\R)
+    stw     r0,-4(r3)
+.endm
+
+    .align 2
+;#  r3 unsigned char *s
+;#  r4 int p
+;#  r5 const signed char *flimit
+;#  r6 const signed char *limit
+;#  r7 const signed char *thresh
+mbloop_filter_vertical_edge_y_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xc000
+    mtspr   256, r12            ;# set VRSAVE
+
+    la      r9, -48(r1)         ;# temporary space for reading in vectors
+    sub     r3, r3, r4
+
+    RLVmb v0, r9
+    RLVmb v1, r9
+    RLVmb v2, r9
+    RLVmb v3, r9
+    RLVmb v4, r9
+    RLVmb v5, r9
+    RLVmb v6, r9
+    RLVmb v7, r9
+
+    transpose8x16_fwd
+
+    build_constants r5, r6, r7, v8, v9, v10
+
+    vp8_mbfilter
+
+    transpose8x16_inv
+
+    add r3, r3, r4
+    neg r4, r4
+
+    WLVmb v17, r9
+    WLVmb v16, r9
+    WLVmb v15, r9
+    WLVmb v14, r9
+    WLVmb v13, r9
+    WLVmb v12, r9
+    WLVmb v11, r9
+    WLVmb v10, r9
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+.macro RL V, R, P
+    lvx     \V, 0,  \R
+    add     \R, \R, \P
+.endm
+
+.macro WL V, R, P
+    stvx    \V, 0,  \R
+    add     \R, \R, \P
+.endm
+
+.macro Fil P3, P2, P1, P0, Q0, Q1, Q2, Q3
+                                ;# K = |P0-P1| already
+    Abs     v14, v13, \Q0, \Q1  ;# M = |Q0-Q1|
+    vmaxub  v14, v14, v4        ;# M = max( |P0-P1|, |Q0-Q1|)
+    vcmpgtub v10, v14, v0
+
+    Abs     v4, v5, \Q2, \Q3    ;# K = |Q2-Q3| = next |P0-P1]
+
+    max_abs  v14, v13, \Q1, \Q2  ;# M = max( M, |Q1-Q2|)
+    max_abs  v14, v13, \P1, \P2  ;# M = max( M, |P1-P2|)
+    max_abs  v14, v13, \P2, \P3  ;# M = max( M, |P2-P3|)
+
+    vmaxub   v14, v14, v4       ;# M = max interior abs diff
+    vcmpgtub v9, v14, v2        ;# M = true if int_l exceeded
+
+    Abs     v14, v13, \P0, \Q0  ;# X = Abs( P0-Q0)
+    vcmpgtub v8, v14, v3        ;# X = true if edge_l exceeded
+    vor     v8, v8, v9          ;# M = true if edge_l or int_l exceeded
+
+    ;# replace P1,Q1 w/signed versions
+    common_adjust \P0, \Q0, \P1, \Q1, 1
+
+    vaddubm v13, v13, v1        ;# -16 <= M <= 15, saturation irrelevant
+    vsrab   v13, v13, v1
+    vandc   v13, v13, v10       ;# adjust P1,Q1 by (M+1)>>1  if ! hev
+    vsubsbs \Q1, \Q1, v13
+    vaddsbs \P1, \P1, v13
+
+    vxor    \P1, \P1, v11       ;# P1
+    vxor    \P0, \P0, v11       ;# P0
+    vxor    \Q0, \Q0, v11       ;# Q0
+    vxor    \Q1, \Q1, v11       ;# Q1
+.endm
+
+
+    .align 2
+;#  r3 unsigned char *s
+;#  r4 int p
+;#  r5 const signed char *flimit
+;#  r6 const signed char *limit
+;#  r7 const signed char *thresh
+loop_filter_vertical_edge_y_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xffff
+    mtspr   256, r12            ;# set VRSAVE
+
+    addi    r9, r3, 0
+    RL      v16, r9, r4
+    RL      v17, r9, r4
+    RL      v18, r9, r4
+    RL      v19, r9, r4
+    RL      v20, r9, r4
+    RL      v21, r9, r4
+    RL      v22, r9, r4
+    RL      v23, r9, r4
+    RL      v24, r9, r4
+    RL      v25, r9, r4
+    RL      v26, r9, r4
+    RL      v27, r9, r4
+    RL      v28, r9, r4
+    RL      v29, r9, r4
+    RL      v30, r9, r4
+    lvx     v31, 0, r9
+
+    Transpose16x16
+
+    vspltisb v1, 1
+
+    build_constants r5, r6, r7, v3, v2, v0
+
+    Abs v4, v5, v19, v18                            ;# K(v14) = first |P0-P1|
+
+    Fil v16, v17, v18, v19,  v20, v21, v22, v23
+    Fil v20, v21, v22, v23,  v24, v25, v26, v27
+    Fil v24, v25, v26, v27,  v28, v29, v30, v31
+
+    Transpose16x16
+
+    addi    r9, r3, 0
+    WL      v16, r9, r4
+    WL      v17, r9, r4
+    WL      v18, r9, r4
+    WL      v19, r9, r4
+    WL      v20, r9, r4
+    WL      v21, r9, r4
+    WL      v22, r9, r4
+    WL      v23, r9, r4
+    WL      v24, r9, r4
+    WL      v25, r9, r4
+    WL      v26, r9, r4
+    WL      v27, r9, r4
+    WL      v28, r9, r4
+    WL      v29, r9, r4
+    WL      v30, r9, r4
+    stvx    v31, 0, r9
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+;# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- UV FILTERING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+.macro active_chroma_sel V
+    andi.   r7, r3, 8       ;# row origin modulo 16
+    add     r7, r7, r7      ;# selects selectors
+    lis     r12, _chromaSelectors@ha
+    la      r0,  _chromaSelectors@l(r12)
+    lwzux   r0, r7, r0      ;# leave selector addr in r7
+
+    lvx     \V, 0, r0       ;# mask to concatenate active U,V pels
+.endm
+
+.macro hread_uv Dest, U, V, Offs, VMask
+    lvx     \U, \Offs, r3
+    lvx     \V, \Offs, r4
+    vperm   \Dest, \U, \V, \VMask   ;# Dest = active part of U then V
+.endm
+
+.macro hwrite_uv New, U, V, Offs, Umask, Vmask
+    vperm   \U, \New, \U, \Umask    ;# Combine new pels with siblings
+    vperm   \V, \New, \V, \Vmask
+    stvx    \U, \Offs, r3           ;# Write to frame buffer
+    stvx    \V, \Offs, r4
+.endm
+
+;# Process U,V in parallel.
+.macro load_chroma_h
+    neg     r9, r5          ;# r9 = -1 * stride
+    add     r8, r9, r9      ;# r8 = -2 * stride
+    add     r10, r5, r5     ;# r10 = 2 * stride
+
+    active_chroma_sel v12
+
+    ;# P3, Q3 are read-only; need not save addresses or sibling pels
+    add     r6, r8, r8      ;# r6 = -4 * stride
+    hread_uv v0, v14, v15, r6, v12
+    add     r6, r10, r5     ;# r6 =  3 * stride
+    hread_uv v7, v14, v15, r6, v12
+
+    ;# Others are read/write; save addresses and sibling pels
+
+    add     r6, r8, r9      ;# r6 = -3 * stride
+    hread_uv v1, v16, v17, r6,  v12
+    hread_uv v2, v18, v19, r8,  v12
+    hread_uv v3, v20, v21, r9,  v12
+    hread_uv v4, v22, v23, 0,   v12
+    hread_uv v5, v24, v25, r5,  v12
+    hread_uv v6, v26, v27, r10, v12
+.endm
+
+.macro uresult_sel V
+    load_g   \V, 4(r7)
+.endm
+
+.macro vresult_sel V
+    load_g   \V, 8(r7)
+.endm
+
+;# always write P1,P0,Q0,Q1
+.macro store_chroma_h
+    uresult_sel v11
+    vresult_sel v12
+    hwrite_uv v2, v18, v19, r8, v11, v12
+    hwrite_uv v3, v20, v21, r9, v11, v12
+    hwrite_uv v4, v22, v23, 0,  v11, v12
+    hwrite_uv v5, v24, v25, r5, v11, v12
+.endm
+
+    .align 2
+;#  r3 unsigned char *u
+;#  r4 unsigned char *v
+;#  r5 int p
+;#  r6 const signed char *flimit
+;#  r7 const signed char *limit
+;#  r8 const signed char *thresh
+mbloop_filter_horizontal_edge_uv_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xffff
+    mtspr   256, r12            ;# set VRSAVE
+
+    build_constants r6, r7, r8, v8, v9, v10
+
+    load_chroma_h
+
+    vp8_mbfilter
+
+    store_chroma_h
+
+    hwrite_uv v1, v16, v17, r6,  v11, v12    ;# v1 == P2
+    hwrite_uv v6, v26, v27, r10, v11, v12    ;# v6 == Q2
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .align 2
+;#  r3 unsigned char *u
+;#  r4 unsigned char *v
+;#  r5 int p
+;#  r6 const signed char *flimit
+;#  r7 const signed char *limit
+;#  r8 const signed char *thresh
+loop_filter_horizontal_edge_uv_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xffff
+    mtspr   256, r12            ;# set VRSAVE
+
+    build_constants r6, r7, r8, v8, v9, v10
+
+    load_chroma_h
+
+    SBFilter
+
+    store_chroma_h
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+.macro R V, R
+    lwzux   r0, r3, r5
+    stw     r0, 4(\R)
+    lwz     r0,-4(r3)
+    stw     r0, 0(\R)
+    lwzux   r0, r4, r5
+    stw     r0,12(\R)
+    lwz     r0,-4(r4)
+    stw     r0, 8(\R)
+    lvx     \V, 0, \R
+.endm
+
+
+.macro W V, R
+    stvx    \V, 0, \R
+    lwz     r0,12(\R)
+    stwux   r0, r4, r5
+    lwz     r0, 8(\R)
+    stw     r0,-4(r4)
+    lwz     r0, 4(\R)
+    stwux   r0, r3, r5
+    lwz     r0, 0(\R)
+    stw     r0,-4(r3)
+.endm
+
+.macro chroma_vread R
+    sub r3, r3, r5          ;# back up one line for simplicity
+    sub r4, r4, r5
+
+    R v0, \R
+    R v1, \R
+    R v2, \R
+    R v3, \R
+    R v4, \R
+    R v5, \R
+    R v6, \R
+    R v7, \R
+
+    transpose8x16_fwd
+.endm
+
+.macro chroma_vwrite R
+
+    transpose8x16_inv
+
+    add     r3, r3, r5
+    add     r4, r4, r5
+    neg     r5, r5          ;# Write rows back in reverse order
+
+    W v17, \R
+    W v16, \R
+    W v15, \R
+    W v14, \R
+    W v13, \R
+    W v12, \R
+    W v11, \R
+    W v10, \R
+.endm
+
+    .align 2
+;#  r3 unsigned char *u
+;#  r4 unsigned char *v
+;#  r5 int p
+;#  r6 const signed char *flimit
+;#  r7 const signed char *limit
+;#  r8 const signed char *thresh
+mbloop_filter_vertical_edge_uv_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xc000
+    mtspr   256, r12            ;# set VRSAVE
+
+    la      r9, -48(r1)         ;# temporary space for reading in vectors
+
+    chroma_vread r9
+
+    build_constants r6, r7, r8, v8, v9, v10
+
+    vp8_mbfilter
+
+    chroma_vwrite r9
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .align 2
+;#  r3 unsigned char *u
+;#  r4 unsigned char *v
+;#  r5 int p
+;#  r6 const signed char *flimit
+;#  r7 const signed char *limit
+;#  r8 const signed char *thresh
+loop_filter_vertical_edge_uv_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xc000
+    mtspr   256, r12            ;# set VRSAVE
+
+    la      r9, -48(r1)         ;# temporary space for reading in vectors
+
+    chroma_vread r9
+
+    build_constants r6, r7, r8, v8, v9, v10
+
+    SBFilter
+
+    chroma_vwrite r9
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+;# -=-=-=-=-=-=-=-=-=-=-=-=-=-= SIMPLE LOOP FILTER =-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+.macro vp8_simple_filter
+    Abs v14, v13, v1, v2    ;# M = abs( P0 - Q0)
+    vcmpgtub v8, v14, v8    ;# v5 = true if _over_ limit
+
+    ;# preserve unsigned v0 and v3
+    common_adjust v1, v2, v0, v3, 0
+
+    vxor v1, v1, v11
+    vxor v2, v2, v11        ;# cvt Q0, P0 back to pels
+.endm
+
+.macro simple_vertical
+    addi    r8,  0, 16
+    addi    r7, r5, 32
+
+    lvx     v0,  0, r5
+    lvx     v1, r8, r5
+    lvx     v2,  0, r7
+    lvx     v3, r8, r7
+
+    lis     r12, _B_hihi@ha
+    la      r0,  _B_hihi@l(r12)
+    lvx     v16, 0, r0
+
+    lis     r12, _B_lolo@ha
+    la      r0,  _B_lolo@l(r12)
+    lvx     v17, 0, r0
+
+    Transpose4times4x4 v16, v17
+    vp8_simple_filter
+
+    vxor v0, v0, v11
+    vxor v3, v3, v11        ;# cvt Q0, P0 back to pels
+
+    Transpose4times4x4 v16, v17
+
+    stvx    v0,  0, r5
+    stvx    v1, r8, r5
+    stvx    v2,  0, r7
+    stvx    v3, r8, r7
+.endm
+
+    .align 2
+;#  r3 unsigned char *s
+;#  r4 int p
+;#  r5 const signed char *flimit
+loop_filter_simple_horizontal_edge_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    mtspr   256, r12            ;# set VRSAVE
+
+    ;# build constants
+    lvx     v8, 0, r5           ;# flimit
+
+    vspltisb v11, 8
+    vspltisb v12, 4
+    vslb    v11, v11, v12       ;# 0x80808080808080808080808080808080
+
+    neg     r5, r4              ;# r5 = -1 * stride
+    add     r6, r5, r5          ;# r6 = -2 * stride
+
+    lvx     v0, r6, r3          ;# v0 = P1 = 16 pels two rows above edge
+    lvx     v1, r5, r3          ;# v1 = P0 = 16 pels one row  above edge
+    lvx     v2,  0, r3          ;# v2 = Q0 = 16 pels one row  below edge
+    lvx     v3, r4, r3          ;# v3 = Q1 = 16 pels two rows below edge
+
+    vp8_simple_filter
+
+    stvx    v1, r5, r3          ;# store P0
+    stvx    v2,  0, r3          ;# store Q0
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+.macro RLV Offs
+    stw     r0, (\Offs*4)(r5)
+    lwzux   r0, r7, r4
+.endm
+
+.macro WLV Offs
+    lwz     r0, (\Offs*4)(r5)
+    stwux   r0, r7, r4
+.endm
+
+    .align 2
+;#  r3 unsigned char *s
+;#  r4 int p
+;#  r5 const signed char *flimit
+loop_filter_simple_vertical_edge_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xc000
+    mtspr   256, r12            ;# set VRSAVE
+
+    ;# build constants
+    lvx     v8, 0, r5           ;# flimit
+
+    vspltisb v11, 8
+    vspltisb v12, 4
+    vslb    v11, v11, v12       ;# 0x80808080808080808080808080808080
+
+    la r5, -96(r1)              ;# temporary space for reading in vectors
+
+    ;# Store 4 pels at word "Offs" in temp array, then advance r7
+    ;#   to next row and read another 4 pels from the frame buffer.
+
+    subi    r7, r3,  2          ;# r7 -> 2 pels before start
+    lwzx    r0,  0, r7          ;# read first 4 pels
+
+    ;# 16 unaligned word accesses
+    RLV 0
+    RLV 4
+    RLV 8
+    RLV 12
+    RLV 1
+    RLV 5
+    RLV 9
+    RLV 13
+    RLV 2
+    RLV 6
+    RLV 10
+    RLV 14
+    RLV 3
+    RLV 7
+    RLV 11
+
+    stw     r0, (15*4)(r5)      ;# write last 4 pels
+
+    simple_vertical
+
+    ;# Read temp array, write frame buffer.
+    subi    r7, r3,  2          ;# r7 -> 2 pels before start
+    lwzx    r0,  0, r5          ;# read/write first 4 pels
+    stwx    r0,  0, r7
+
+    WLV 4
+    WLV 8
+    WLV 12
+    WLV 1
+    WLV 5
+    WLV 9
+    WLV 13
+    WLV 2
+    WLV 6
+    WLV 10
+    WLV 14
+    WLV 3
+    WLV 7
+    WLV 11
+    WLV 15
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .data
+
+_chromaSelectors:
+    .long   _B_hihi
+    .long   _B_Ures0
+    .long   _B_Vres0
+    .long   0
+    .long   _B_lolo
+    .long   _B_Ures8
+    .long   _B_Vres8
+    .long   0
+
+    .align 4
+_B_Vres8:
+    .byte   16, 17, 18, 19, 20, 21, 22, 23,  8,  9, 10, 11, 12, 13, 14, 15
+
+    .align 4
+_B_Ures8:
+    .byte   16, 17, 18, 19, 20, 21, 22, 23,  0,  1,  2,  3,  4,  5,  6,  7
+
+    .align 4
+_B_lolo:
+    .byte    8,  9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31
+
+    .align 4
+_B_Vres0:
+    .byte    8,  9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31
+    .align 4
+_B_Ures0:
+    .byte    0,  1,  2,  3,  4,  5,  6,  7, 24, 25, 26, 27, 28, 29, 30, 31
+
+    .align 4
+_B_hihi:
+    .byte    0,  1,  2,  3,  4,  5,  6,  7, 16, 17, 18, 19, 20, 21, 22, 23
diff --git a/vp8/common/ppc/platform_altivec.asm b/vp8/common/ppc/platform_altivec.asm
new file mode 100644 (file)
index 0000000..f81d86f
--- /dev/null
@@ -0,0 +1,59 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    .globl save_platform_context
+    .globl restore_platform_context
+
+.macro W V P
+    stvx    \V,  0, \P
+    addi    \P, \P, 16
+.endm
+
+.macro R V P
+    lvx     \V,  0, \P
+    addi    \P, \P, 16
+.endm
+
+;# r3 context_ptr
+    .align 2
+save_platform_contex:
+    W v20, r3
+    W v21, r3
+    W v22, r3
+    W v23, r3
+    W v24, r3
+    W v25, r3
+    W v26, r3
+    W v27, r3
+    W v28, r3
+    W v29, r3
+    W v30, r3
+    W v31, r3
+
+    blr
+
+;# r3 context_ptr
+    .align 2
+restore_platform_context:
+    R v20, r3
+    R v21, r3
+    R v22, r3
+    R v23, r3
+    R v24, r3
+    R v25, r3
+    R v26, r3
+    R v27, r3
+    R v28, r3
+    R v29, r3
+    R v30, r3
+    R v31, r3
+
+    blr
diff --git a/vp8/common/ppc/recon_altivec.asm b/vp8/common/ppc/recon_altivec.asm
new file mode 100644 (file)
index 0000000..dd39e05
--- /dev/null
@@ -0,0 +1,175 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    .globl recon4b_ppc
+    .globl recon2b_ppc
+    .globl recon_b_ppc
+
+.macro row_of16 Diff Pred Dst Stride
+    lvx     v1,  0, \Pred           ;# v1 = pred = p0..p15
+    addi    \Pred, \Pred, 16        ;# next pred
+    vmrghb  v2, v0, v1              ;# v2 = 16-bit p0..p7
+    lvx     v3,  0, \Diff           ;# v3 = d0..d7
+    vaddshs v2, v2, v3              ;# v2 = r0..r7
+    vmrglb  v1, v0, v1              ;# v1 = 16-bit p8..p15
+    lvx     v3, r8, \Diff           ;# v3 = d8..d15
+    addi    \Diff, \Diff, 32        ;# next diff
+    vaddshs v3, v3, v1              ;# v3 = r8..r15
+    vpkshus v2, v2, v3              ;# v2 = 8-bit r0..r15
+    stvx    v2,  0, \Dst            ;# to dst
+    add     \Dst, \Dst, \Stride     ;# next dst
+.endm
+
+    .text
+    .align 2
+;#  r3 = short *diff_ptr,
+;#  r4 = unsigned char *pred_ptr,
+;#  r5 = unsigned char *dst_ptr,
+;#  r6 = int stride
+recon4b_ppc:
+    mfspr   r0, 256                     ;# get old VRSAVE
+    stw     r0, -8(r1)                  ;# save old VRSAVE to stack
+    oris    r0, r0, 0xf000
+    mtspr   256,r0                      ;# set VRSAVE
+
+    vxor    v0, v0, v0
+    li      r8, 16
+
+    row_of16 r3, r4, r5, r6
+    row_of16 r3, r4, r5, r6
+    row_of16 r3, r4, r5, r6
+    row_of16 r3, r4, r5, r6
+
+    lwz     r12, -8(r1)                 ;# restore old VRSAVE from stack
+    mtspr   256, r12                    ;# reset old VRSAVE
+
+    blr
+
+.macro two_rows_of8 Diff Pred Dst Stride write_first_four_pels
+    lvx     v1,  0, \Pred       ;# v1 = pred = p0..p15
+    vmrghb  v2, v0, v1          ;# v2 = 16-bit p0..p7
+    lvx     v3,  0, \Diff       ;# v3 = d0..d7
+    vaddshs v2, v2, v3          ;# v2 = r0..r7
+    vmrglb  v1, v0, v1          ;# v1 = 16-bit p8..p15
+    lvx     v3, r8, \Diff       ;# v2 = d8..d15
+    vaddshs v3, v3, v1          ;# v3 = r8..r15
+    vpkshus v2, v2, v3          ;# v3 = 8-bit r0..r15
+    stvx    v2,  0, r10         ;# 2 rows to dst from buf
+    lwz     r0, 0(r10)
+.if \write_first_four_pels
+    stw     r0, 0(\Dst)
+    .else
+    stwux   r0, \Dst, \Stride
+.endif
+    lwz     r0, 4(r10)
+    stw     r0, 4(\Dst)
+    lwz     r0, 8(r10)
+    stwux   r0, \Dst, \Stride       ;# advance dst to next row
+    lwz     r0, 12(r10)
+    stw     r0, 4(\Dst)
+.endm
+
+    .align 2
+;#  r3 = short *diff_ptr,
+;#  r4 = unsigned char *pred_ptr,
+;#  r5 = unsigned char *dst_ptr,
+;#  r6 = int stride
+
+recon2b_ppc:
+    mfspr   r0, 256                     ;# get old VRSAVE
+    stw     r0, -8(r1)                  ;# save old VRSAVE to stack
+    oris    r0, r0, 0xf000
+    mtspr   256,r0                      ;# set VRSAVE
+
+    vxor    v0, v0, v0
+    li      r8, 16
+
+    la      r10, -48(r1)                ;# buf
+
+    two_rows_of8 r3, r4, r5, r6, 1
+
+    addi    r4, r4, 16;                 ;# next pred
+    addi    r3, r3, 32;                 ;# next diff
+
+    two_rows_of8 r3, r4, r5, r6, 0
+
+    lwz     r12, -8(r1)                 ;# restore old VRSAVE from stack
+    mtspr   256, r12                    ;# reset old VRSAVE
+
+    blr
+
+.macro get_two_diff_rows
+    stw     r0, 0(r10)
+    lwz     r0, 4(r3)
+    stw     r0, 4(r10)
+    lwzu    r0, 32(r3)
+    stw     r0, 8(r10)
+    lwz     r0, 4(r3)
+    stw     r0, 12(r10)
+    lvx     v3, 0, r10
+.endm
+
+    .align 2
+;#  r3 = short *diff_ptr,
+;#  r4 = unsigned char *pred_ptr,
+;#  r5 = unsigned char *dst_ptr,
+;#  r6 = int stride
+recon_b_ppc:
+    mfspr   r0, 256                     ;# get old VRSAVE
+    stw     r0, -8(r1)                  ;# save old VRSAVE to stack
+    oris    r0, r0, 0xf000
+    mtspr   256,r0                      ;# set VRSAVE
+
+    vxor    v0, v0, v0
+
+    la      r10, -48(r1)    ;# buf
+
+    lwz     r0, 0(r4)
+    stw     r0, 0(r10)
+    lwz     r0, 16(r4)
+    stw     r0, 4(r10)
+    lwz     r0, 32(r4)
+    stw     r0, 8(r10)
+    lwz     r0, 48(r4)
+    stw     r0, 12(r10)
+
+    lvx     v1,  0, r10;    ;# v1 = pred = p0..p15
+
+    lwz r0, 0(r3)           ;# v3 = d0..d7
+
+    get_two_diff_rows
+
+    vmrghb  v2, v0, v1;     ;# v2 = 16-bit p0..p7
+    vaddshs v2, v2, v3;     ;# v2 = r0..r7
+
+    lwzu r0, 32(r3)         ;# v3 = d8..d15
+
+    get_two_diff_rows
+
+    vmrglb  v1, v0, v1;     ;# v1 = 16-bit p8..p15
+    vaddshs v3, v3, v1;     ;# v3 = r8..r15
+
+    vpkshus v2, v2, v3;     ;# v2 = 8-bit r0..r15
+    stvx    v2,  0, r10;    ;# 16 pels to dst from buf
+
+    lwz     r0, 0(r10)
+    stw     r0, 0(r5)
+    lwz     r0, 4(r10)
+    stwux   r0, r5, r6
+    lwz     r0, 8(r10)
+    stwux   r0, r5, r6
+    lwz     r0, 12(r10)
+    stwx    r0, r5, r6
+
+    lwz     r12, -8(r1)                 ;# restore old VRSAVE from stack
+    mtspr   256, r12                    ;# reset old VRSAVE
+
+    blr
diff --git a/vp8/common/ppc/sad_altivec.asm b/vp8/common/ppc/sad_altivec.asm
new file mode 100644 (file)
index 0000000..e5f2638
--- /dev/null
@@ -0,0 +1,277 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    .globl vp8_sad16x16_ppc
+    .globl vp8_sad16x8_ppc
+    .globl vp8_sad8x16_ppc
+    .globl vp8_sad8x8_ppc
+    .globl vp8_sad4x4_ppc
+
+.macro load_aligned_16 V R O
+    lvsl    v3,  0, \R          ;# permutate value for alignment
+
+    lvx     v1,  0, \R
+    lvx     v2, \O, \R
+
+    vperm   \V, v1, v2, v3
+.endm
+
+.macro prologue
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffc0
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1, -32(r1)         ;# create space on the stack
+
+    li      r10, 16             ;# load offset and loop counter
+
+    vspltisw v8, 0              ;# zero out total to start
+.endm
+
+.macro epilogue
+    addi    r1, r1, 32          ;# recover stack
+
+    mtspr   256, r11            ;# reset old VRSAVE
+.endm
+
+.macro SAD_16
+    ;# v6 = abs (v4 - v5)
+    vsububs v6, v4, v5
+    vsububs v7, v5, v4
+    vor     v6, v6, v7
+
+    ;# v8 += abs (v4 - v5)
+    vsum4ubs v8, v6, v8
+.endm
+
+.macro sad_16_loop loop_label
+    lvsl    v3,  0, r5          ;# only needs to be done once per block
+
+    ;# preload a line of data before getting into the loop
+    lvx     v4, 0, r3
+    lvx     v1,  0, r5
+    lvx     v2, r10, r5
+
+    add     r5, r5, r6
+    add     r3, r3, r4
+
+    vperm   v5, v1, v2, v3
+
+    .align 4
+\loop_label:
+    ;# compute difference on first row
+    vsububs v6, v4, v5
+    vsububs v7, v5, v4
+
+    ;# load up next set of data
+    lvx     v9, 0, r3
+    lvx     v1,  0, r5
+    lvx     v2, r10, r5
+
+    ;# perform abs() of difference
+    vor     v6, v6, v7
+    add     r3, r3, r4
+
+    ;# add to the running tally
+    vsum4ubs v8, v6, v8
+
+    ;# now onto the next line
+    vperm   v5, v1, v2, v3
+    add     r5, r5, r6
+    lvx     v4, 0, r3
+
+    ;# compute difference on second row
+    vsububs v6, v9, v5
+    lvx     v1,  0, r5
+    vsububs v7, v5, v9
+    lvx     v2, r10, r5
+    vor     v6, v6, v7
+    add     r3, r3, r4
+    vsum4ubs v8, v6, v8
+    vperm   v5, v1, v2, v3
+    add     r5, r5, r6
+
+    bdnz    \loop_label
+
+    vspltisw v7, 0
+
+    vsumsws v8, v8, v7
+
+    stvx    v8, 0, r1
+    lwz     r3, 12(r1)
+.endm
+
+.macro sad_8_loop loop_label
+    .align 4
+\loop_label:
+    ;# only one of the inputs should need to be aligned.
+    load_aligned_16 v4, r3, r10
+    load_aligned_16 v5, r5, r10
+
+    ;# move onto the next line
+    add     r3, r3, r4
+    add     r5, r5, r6
+
+    ;# only one of the inputs should need to be aligned.
+    load_aligned_16 v6, r3, r10
+    load_aligned_16 v7, r5, r10
+
+    ;# move onto the next line
+    add     r3, r3, r4
+    add     r5, r5, r6
+
+    vmrghb  v4, v4, v6
+    vmrghb  v5, v5, v7
+
+    SAD_16
+
+    bdnz    \loop_label
+
+    vspltisw v7, 0
+
+    vsumsws v8, v8, v7
+
+    stvx    v8, 0, r1
+    lwz     r3, 12(r1)
+.endm
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  src_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  ref_stride
+;#
+;# r3 return value
+vp8_sad16x16_ppc:
+
+    prologue
+
+    li      r9, 8
+    mtctr   r9
+
+    sad_16_loop sad16x16_loop
+
+    epilogue
+
+    blr
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  src_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  ref_stride
+;#
+;# r3 return value
+vp8_sad16x8_ppc:
+
+    prologue
+
+    li      r9, 4
+    mtctr   r9
+
+    sad_16_loop sad16x8_loop
+
+    epilogue
+
+    blr
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  src_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  ref_stride
+;#
+;# r3 return value
+vp8_sad8x16_ppc:
+
+    prologue
+
+    li      r9, 8
+    mtctr   r9
+
+    sad_8_loop sad8x16_loop
+
+    epilogue
+
+    blr
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  src_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  ref_stride
+;#
+;# r3 return value
+vp8_sad8x8_ppc:
+
+    prologue
+
+    li      r9, 4
+    mtctr   r9
+
+    sad_8_loop sad8x8_loop
+
+    epilogue
+
+    blr
+
+.macro transfer_4x4 I P
+    lwz     r0, 0(\I)
+    add     \I, \I, \P
+
+    lwz     r7, 0(\I)
+    add     \I, \I, \P
+
+    lwz     r8, 0(\I)
+    add     \I, \I, \P
+
+    lwz     r9, 0(\I)
+
+    stw     r0,  0(r1)
+    stw     r7,  4(r1)
+    stw     r8,  8(r1)
+    stw     r9, 12(r1)
+.endm
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  src_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  ref_stride
+;#
+;# r3 return value
+vp8_sad4x4_ppc:
+
+    prologue
+
+    transfer_4x4 r3, r4
+    lvx     v4, 0, r1
+
+    transfer_4x4 r5, r6
+    lvx     v5, 0, r1
+
+    vspltisw v8, 0              ;# zero out total to start
+
+    ;# v6 = abs (v4 - v5)
+    vsububs v6, v4, v5
+    vsububs v7, v5, v4
+    vor     v6, v6, v7
+
+    ;# v8 += abs (v4 - v5)
+    vsum4ubs v7, v6, v8
+    vsumsws v7, v7, v8
+
+    stvx    v7, 0, r1
+    lwz     r3, 12(r1)
+
+    epilogue
+
+    blr
diff --git a/vp8/common/ppc/systemdependent.c b/vp8/common/ppc/systemdependent.c
new file mode 100644 (file)
index 0000000..7046a63
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "subpixel.h"
+#include "loopfilter.h"
+#include "recon.h"
+#include "idct.h"
+#include "onyxc_int.h"
+
+void (*vp8_short_idct4x4)(short *input, short *output, int pitch);
+void (*vp8_short_idct4x4_1)(short *input, short *output, int pitch);
+void (*vp8_dc_only_idct)(short input_dc, short *output, int pitch);
+
+extern void (*vp8_post_proc_down_and_across)(
+    unsigned char *src_ptr,
+    unsigned char *dst_ptr,
+    int src_pixels_per_line,
+    int dst_pixels_per_line,
+    int rows,
+    int cols,
+    int flimit
+);
+
+extern void (*vp8_mbpost_proc_down)(unsigned char *dst, int pitch, int rows, int cols, int flimit);
+extern void vp8_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols, int flimit);
+extern void (*vp8_mbpost_proc_across_ip)(unsigned char *src, int pitch, int rows, int cols, int flimit);
+extern void vp8_mbpost_proc_across_ip_c(unsigned char *src, int pitch, int rows, int cols, int flimit);
+
+extern void vp8_post_proc_down_and_across_c
+(
+    unsigned char *src_ptr,
+    unsigned char *dst_ptr,
+    int src_pixels_per_line,
+    int dst_pixels_per_line,
+    int rows,
+    int cols,
+    int flimit
+);
+void vp8_plane_add_noise_c(unsigned char *Start, unsigned int Width, unsigned int Height, int Pitch, int q, int a);
+
+extern copy_mem_block_function *vp8_copy_mem16x16;
+extern copy_mem_block_function *vp8_copy_mem8x8;
+extern copy_mem_block_function *vp8_copy_mem8x4;
+
+// PPC
+extern subpixel_predict_function sixtap_predict_ppc;
+extern subpixel_predict_function sixtap_predict8x4_ppc;
+extern subpixel_predict_function sixtap_predict8x8_ppc;
+extern subpixel_predict_function sixtap_predict16x16_ppc;
+extern subpixel_predict_function bilinear_predict4x4_ppc;
+extern subpixel_predict_function bilinear_predict8x4_ppc;
+extern subpixel_predict_function bilinear_predict8x8_ppc;
+extern subpixel_predict_function bilinear_predict16x16_ppc;
+
+extern copy_mem_block_function copy_mem16x16_ppc;
+
+void recon_b_ppc(short *diff_ptr, unsigned char *pred_ptr, unsigned char *dst_ptr, int stride);
+void recon2b_ppc(short *diff_ptr, unsigned char *pred_ptr, unsigned char *dst_ptr, int stride);
+void recon4b_ppc(short *diff_ptr, unsigned char *pred_ptr, unsigned char *dst_ptr, int stride);
+
+extern void short_idct4x4llm_ppc(short *input, short *output, int pitch);
+
+// Generic C
+extern subpixel_predict_function vp8_sixtap_predict_c;
+extern subpixel_predict_function vp8_sixtap_predict8x4_c;
+extern subpixel_predict_function vp8_sixtap_predict8x8_c;
+extern subpixel_predict_function vp8_sixtap_predict16x16_c;
+extern subpixel_predict_function vp8_bilinear_predict4x4_c;
+extern subpixel_predict_function vp8_bilinear_predict8x4_c;
+extern subpixel_predict_function vp8_bilinear_predict8x8_c;
+extern subpixel_predict_function vp8_bilinear_predict16x16_c;
+
+extern copy_mem_block_function vp8_copy_mem16x16_c;
+extern copy_mem_block_function vp8_copy_mem8x8_c;
+extern copy_mem_block_function vp8_copy_mem8x4_c;
+
+void vp8_recon_b_c(short *diff_ptr, unsigned char *pred_ptr, unsigned char *dst_ptr, int stride);
+void vp8_recon2b_c(short *diff_ptr, unsigned char *pred_ptr, unsigned char *dst_ptr, int stride);
+void vp8_recon4b_c(short *diff_ptr, unsigned char *pred_ptr, unsigned char *dst_ptr, int stride);
+
+extern void vp8_short_idct4x4llm_1_c(short *input, short *output, int pitch);
+extern void vp8_short_idct4x4llm_c(short *input, short *output, int pitch);
+extern void vp8_dc_only_idct_c(short input_dc, short *output, int pitch);
+
+// PPC
+extern loop_filter_block_function loop_filter_mbv_ppc;
+extern loop_filter_block_function loop_filter_bv_ppc;
+extern loop_filter_block_function loop_filter_mbh_ppc;
+extern loop_filter_block_function loop_filter_bh_ppc;
+
+extern loop_filter_block_function loop_filter_mbvs_ppc;
+extern loop_filter_block_function loop_filter_bvs_ppc;
+extern loop_filter_block_function loop_filter_mbhs_ppc;
+extern loop_filter_block_function loop_filter_bhs_ppc;
+
+// Generic C
+extern loop_filter_block_function vp8_loop_filter_mbv_c;
+extern loop_filter_block_function vp8_loop_filter_bv_c;
+extern loop_filter_block_function vp8_loop_filter_mbh_c;
+extern loop_filter_block_function vp8_loop_filter_bh_c;
+
+extern loop_filter_block_function vp8_loop_filter_mbvs_c;
+extern loop_filter_block_function vp8_loop_filter_bvs_c;
+extern loop_filter_block_function vp8_loop_filter_mbhs_c;
+extern loop_filter_block_function vp8_loop_filter_bhs_c;
+
+extern loop_filter_block_function *vp8_lf_mbvfull;
+extern loop_filter_block_function *vp8_lf_mbhfull;
+extern loop_filter_block_function *vp8_lf_bvfull;
+extern loop_filter_block_function *vp8_lf_bhfull;
+
+extern loop_filter_block_function *vp8_lf_mbvsimple;
+extern loop_filter_block_function *vp8_lf_mbhsimple;
+extern loop_filter_block_function *vp8_lf_bvsimple;
+extern loop_filter_block_function *vp8_lf_bhsimple;
+
+void vp8_clear_c(void)
+{
+}
+
+void vp8_machine_specific_config(void)
+{
+    // Pure C:
+    vp8_clear_system_state                = vp8_clear_c;
+    vp8_recon_b                          = vp8_recon_b_c;
+    vp8_recon4b                         = vp8_recon4b_c;
+    vp8_recon2b                         = vp8_recon2b_c;
+
+    vp8_bilinear_predict16x16            = bilinear_predict16x16_ppc;
+    vp8_bilinear_predict8x8              = bilinear_predict8x8_ppc;
+    vp8_bilinear_predict8x4              = bilinear_predict8x4_ppc;
+    vp8_bilinear_predict                 = bilinear_predict4x4_ppc;
+
+    vp8_sixtap_predict16x16              = sixtap_predict16x16_ppc;
+    vp8_sixtap_predict8x8                = sixtap_predict8x8_ppc;
+    vp8_sixtap_predict8x4                = sixtap_predict8x4_ppc;
+    vp8_sixtap_predict                   = sixtap_predict_ppc;
+
+    vp8_short_idct4x4_1                  = vp8_short_idct4x4llm_1_c;
+    vp8_short_idct4x4                    = short_idct4x4llm_ppc;
+    vp8_dc_only_idct                      = vp8_dc_only_idct_c;
+
+    vp8_lf_mbvfull                       = loop_filter_mbv_ppc;
+    vp8_lf_bvfull                        = loop_filter_bv_ppc;
+    vp8_lf_mbhfull                       = loop_filter_mbh_ppc;
+    vp8_lf_bhfull                        = loop_filter_bh_ppc;
+
+    vp8_lf_mbvsimple                     = loop_filter_mbvs_ppc;
+    vp8_lf_bvsimple                      = loop_filter_bvs_ppc;
+    vp8_lf_mbhsimple                     = loop_filter_mbhs_ppc;
+    vp8_lf_bhsimple                      = loop_filter_bhs_ppc;
+
+    vp8_post_proc_down_and_across           = vp8_post_proc_down_and_across_c;
+    vp8_mbpost_proc_down                  = vp8_mbpost_proc_down_c;
+    vp8_mbpost_proc_across_ip              = vp8_mbpost_proc_across_ip_c;
+    vp8_plane_add_noise                   = vp8_plane_add_noise_c;
+
+    vp8_copy_mem16x16                    = copy_mem16x16_ppc;
+    vp8_copy_mem8x8                      = vp8_copy_mem8x8_c;
+    vp8_copy_mem8x4                      = vp8_copy_mem8x4_c;
+
+}
diff --git a/vp8/common/ppc/variance_altivec.asm b/vp8/common/ppc/variance_altivec.asm
new file mode 100644 (file)
index 0000000..fb8d5bb
--- /dev/null
@@ -0,0 +1,375 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    .globl vp8_get8x8var_ppc
+    .globl vp8_get16x16var_ppc
+    .globl vp8_mse16x16_ppc
+    .globl vp8_variance16x16_ppc
+    .globl vp8_variance16x8_ppc
+    .globl vp8_variance8x16_ppc
+    .globl vp8_variance8x8_ppc
+    .globl vp8_variance4x4_ppc
+
+.macro load_aligned_16 V R O
+    lvsl    v3,  0, \R          ;# permutate value for alignment
+
+    lvx     v1,  0, \R
+    lvx     v2, \O, \R
+
+    vperm   \V, v1, v2, v3
+.endm
+
+.macro prologue
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffc0
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1, -32(r1)         ;# create space on the stack
+
+    li      r10, 16             ;# load offset and loop counter
+
+    vspltisw v7, 0              ;# zero for merging
+    vspltisw v8, 0              ;# zero out total to start
+    vspltisw v9, 0              ;# zero out total for dif^2
+.endm
+
+.macro epilogue
+    addi    r1, r1, 32          ;# recover stack
+
+    mtspr   256, r11            ;# reset old VRSAVE
+.endm
+
+.macro compute_sum_sse
+    ;# Compute sum first.  Unpack to so signed subract
+    ;#  can be used.  Only have a half word signed
+    ;#  subract.  Do high, then low.
+    vmrghb  v2, v7, v4
+    vmrghb  v3, v7, v5
+    vsubshs v2, v2, v3
+    vsum4shs v8, v2, v8
+
+    vmrglb  v2, v7, v4
+    vmrglb  v3, v7, v5
+    vsubshs v2, v2, v3
+    vsum4shs v8, v2, v8
+
+    ;# Now compute sse.
+    vsububs v2, v4, v5
+    vsububs v3, v5, v4
+    vor     v2, v2, v3
+
+    vmsumubm v9, v2, v2, v9
+.endm
+
+.macro variance_16 DS loop_label store_sum
+\loop_label:
+    ;# only one of the inputs should need to be aligned.
+    load_aligned_16 v4, r3, r10
+    load_aligned_16 v5, r5, r10
+
+    ;# move onto the next line
+    add     r3, r3, r4
+    add     r5, r5, r6
+
+    compute_sum_sse
+
+    bdnz    \loop_label
+
+    vsumsws v8, v8, v7
+    vsumsws v9, v9, v7
+
+    stvx    v8, 0, r1
+    lwz     r3, 12(r1)
+
+    stvx    v9, 0, r1
+    lwz     r4, 12(r1)
+
+.if \store_sum
+    stw     r3, 0(r8)           ;# sum
+.endif
+    stw     r4, 0(r7)           ;# sse
+
+    mullw   r3, r3, r3          ;# sum*sum
+    srlwi   r3, r3, \DS         ;# (sum*sum) >> DS
+    subf    r3, r3, r4          ;# sse - ((sum*sum) >> DS)
+.endm
+
+.macro variance_8 DS loop_label store_sum
+\loop_label:
+    ;# only one of the inputs should need to be aligned.
+    load_aligned_16 v4, r3, r10
+    load_aligned_16 v5, r5, r10
+
+    ;# move onto the next line
+    add     r3, r3, r4
+    add     r5, r5, r6
+
+    ;# only one of the inputs should need to be aligned.
+    load_aligned_16 v6, r3, r10
+    load_aligned_16 v0, r5, r10
+
+    ;# move onto the next line
+    add     r3, r3, r4
+    add     r5, r5, r6
+
+    vmrghb  v4, v4, v6
+    vmrghb  v5, v5, v0
+
+    compute_sum_sse
+
+    bdnz    \loop_label
+
+    vsumsws v8, v8, v7
+    vsumsws v9, v9, v7
+
+    stvx    v8, 0, r1
+    lwz     r3, 12(r1)
+
+    stvx    v9, 0, r1
+    lwz     r4, 12(r1)
+
+.if \store_sum
+    stw     r3, 0(r8)           ;# sum
+.endif
+    stw     r4, 0(r7)           ;# sse
+
+    mullw   r3, r3, r3          ;# sum*sum
+    srlwi   r3, r3, \DS         ;# (sum*sum) >> 8
+    subf    r3, r3, r4          ;# sse - ((sum*sum) >> 8)
+.endm
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  source_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  recon_stride
+;# r7 unsigned int *SSE
+;# r8 int *Sum
+;#
+;# r3 return value
+vp8_get8x8var_ppc:
+
+    prologue
+
+    li      r9, 4
+    mtctr   r9
+
+    variance_8 6, get8x8var_loop, 1
+
+    epilogue
+
+    blr
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  source_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  recon_stride
+;# r7 unsigned int *SSE
+;# r8 int *Sum
+;#
+;# r3 return value
+vp8_get16x16var_ppc:
+
+    prologue
+
+    mtctr   r10
+
+    variance_16 8, get16x16var_loop, 1
+
+    epilogue
+
+    blr
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  source_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  recon_stride
+;# r7 unsigned int *sse
+;#
+;# r 3 return value
+vp8_mse16x16_ppc:
+    prologue
+
+    mtctr   r10
+
+mse16x16_loop:
+    ;# only one of the inputs should need to be aligned.
+    load_aligned_16 v4, r3, r10
+    load_aligned_16 v5, r5, r10
+
+    ;# move onto the next line
+    add     r3, r3, r4
+    add     r5, r5, r6
+
+    ;# Now compute sse.
+    vsububs v2, v4, v5
+    vsububs v3, v5, v4
+    vor     v2, v2, v3
+
+    vmsumubm v9, v2, v2, v9
+
+    bdnz    mse16x16_loop
+
+    vsumsws v9, v9, v7
+
+    stvx    v9, 0, r1
+    lwz     r3, 12(r1)
+
+    stvx    v9, 0, r1
+    lwz     r3, 12(r1)
+
+    stw     r3, 0(r7)           ;# sse
+
+    epilogue
+
+    blr
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  source_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  recon_stride
+;# r7 unsigned int *sse
+;#
+;# r3 return value
+vp8_variance16x16_ppc:
+
+    prologue
+
+    mtctr   r10
+
+    variance_16 8, variance16x16_loop, 0
+
+    epilogue
+
+    blr
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  source_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  recon_stride
+;# r7 unsigned int *sse
+;#
+;# r3 return value
+vp8_variance16x8_ppc:
+
+    prologue
+
+    li      r9, 8
+    mtctr   r9
+
+    variance_16 7, variance16x8_loop, 0
+
+    epilogue
+
+    blr
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  source_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  recon_stride
+;# r7 unsigned int *sse
+;#
+;# r3 return value
+vp8_variance8x16_ppc:
+
+    prologue
+
+    li      r9, 8
+    mtctr   r9
+
+    variance_8 7, variance8x16_loop, 0
+
+    epilogue
+
+    blr
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  source_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  recon_stride
+;# r7 unsigned int *sse
+;#
+;# r3 return value
+vp8_variance8x8_ppc:
+
+    prologue
+
+    li      r9, 4
+    mtctr   r9
+
+    variance_8 6, variance8x8_loop, 0
+
+    epilogue
+
+    blr
+
+.macro transfer_4x4 I P
+    lwz     r0, 0(\I)
+    add     \I, \I, \P
+
+    lwz     r10,0(\I)
+    add     \I, \I, \P
+
+    lwz     r8, 0(\I)
+    add     \I, \I, \P
+
+    lwz     r9, 0(\I)
+
+    stw     r0,  0(r1)
+    stw     r10, 4(r1)
+    stw     r8,  8(r1)
+    stw     r9, 12(r1)
+.endm
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  source_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  recon_stride
+;# r7 unsigned int *sse
+;#
+;# r3 return value
+vp8_variance4x4_ppc:
+
+    prologue
+
+    transfer_4x4 r3, r4
+    lvx     v4, 0, r1
+
+    transfer_4x4 r5, r6
+    lvx     v5, 0, r1
+
+    compute_sum_sse
+
+    vsumsws v8, v8, v7
+    vsumsws v9, v9, v7
+
+    stvx    v8, 0, r1
+    lwz     r3, 12(r1)
+
+    stvx    v9, 0, r1
+    lwz     r4, 12(r1)
+
+    stw     r4, 0(r7)           ;# sse
+
+    mullw   r3, r3, r3          ;# sum*sum
+    srlwi   r3, r3, 4           ;# (sum*sum) >> 4
+    subf    r3, r3, r4          ;# sse - ((sum*sum) >> 4)
+
+    epilogue
+
+    blr
diff --git a/vp8/common/ppc/variance_subpixel_altivec.asm b/vp8/common/ppc/variance_subpixel_altivec.asm
new file mode 100644 (file)
index 0000000..2308373
--- /dev/null
@@ -0,0 +1,865 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    .globl vp8_sub_pixel_variance4x4_ppc
+    .globl vp8_sub_pixel_variance8x8_ppc
+    .globl vp8_sub_pixel_variance8x16_ppc
+    .globl vp8_sub_pixel_variance16x8_ppc
+    .globl vp8_sub_pixel_variance16x16_ppc
+
+.macro load_c V, LABEL, OFF, R0, R1
+    lis     \R0, \LABEL@ha
+    la      \R1, \LABEL@l(\R0)
+    lvx     \V, \OFF, \R1
+.endm
+
+.macro load_vfilter V0, V1
+    load_c \V0, vfilter_b, r6, r12, r10
+
+    addi    r6,  r6, 16
+    lvx     \V1, r6, r10
+.endm
+
+.macro HProlog jump_label
+    ;# load up horizontal filter
+    slwi.   r5, r5, 4           ;# index into horizontal filter array
+
+    ;# index to the next set of vectors in the row.
+    li      r10, 16
+
+    ;# downshift by 7 ( divide by 128 ) at the end
+    vspltish v19, 7
+
+    ;# If there isn't any filtering to be done for the horizontal, then
+    ;#  just skip to the second pass.
+    beq     \jump_label
+
+    load_c v20, hfilter_b, r5, r12, r0
+
+    ;# setup constants
+    ;# v14 permutation value for alignment
+    load_c v28, b_hperm_b, 0, r12, r0
+
+    ;# index to the next set of vectors in the row.
+    li      r12, 32
+
+    ;# rounding added in on the multiply
+    vspltisw v21, 8
+    vspltisw v18, 3
+    vslw    v18, v21, v18       ;# 0x00000040000000400000004000000040
+
+    slwi.   r6, r6, 5           ;# index into vertical filter array
+.endm
+
+;# Filters a horizontal line
+;# expects:
+;#  r3  src_ptr
+;#  r4  pitch
+;#  r10 16
+;#  r12 32
+;#  v17 perm intput
+;#  v18 rounding
+;#  v19 shift
+;#  v20 filter taps
+;#  v21 tmp
+;#  v22 tmp
+;#  v23 tmp
+;#  v24 tmp
+;#  v25 tmp
+;#  v26 tmp
+;#  v27 tmp
+;#  v28 perm output
+;#
+
+.macro hfilter_8 V, hp, lp, increment_counter
+    lvsl    v17,  0, r3         ;# permutate value for alignment
+
+    ;# input to filter is 9 bytes wide, output is 8 bytes.
+    lvx     v21,   0, r3
+    lvx     v22, r10, r3
+
+.if \increment_counter
+    add     r3, r3, r4
+.endif
+    vperm   v21, v21, v22, v17
+
+    vperm   v24, v21, v21, \hp  ;# v20 = 0123 1234 2345 3456
+    vperm   v25, v21, v21, \lp  ;# v21 = 4567 5678 6789 789A
+
+    vmsummbm v24, v20, v24, v18
+    vmsummbm v25, v20, v25, v18
+
+    vpkswus v24, v24, v25       ;# v24 = 0 4 8 C 1 5 9 D (16-bit)
+
+    vsrh    v24, v24, v19       ;# divide v0, v1 by 128
+
+    vpkuhus \V, v24, v24        ;# \V = scrambled 8-bit result
+.endm
+
+.macro vfilter_16 P0 P1
+    vmuleub v22, \P0, v20       ;# 64 + 4 positive taps
+    vadduhm v22, v18, v22
+    vmuloub v23, \P0, v20
+    vadduhm v23, v18, v23
+
+    vmuleub v24, \P1, v21
+    vadduhm v22, v22, v24       ;# Re = evens, saturation unnecessary
+    vmuloub v25, \P1, v21
+    vadduhm v23, v23, v25       ;# Ro = odds
+
+    vsrh    v22, v22, v19       ;# divide by 128
+    vsrh    v23, v23, v19       ;# v16 v17 = evens, odds
+    vmrghh  \P0, v22, v23       ;# v18 v19 = 16-bit result in order
+    vmrglh  v23, v22, v23
+    vpkuhus \P0, \P0, v23       ;# P0 = 8-bit result
+.endm
+
+.macro compute_sum_sse src, ref, sum, sse, t1, t2, z0
+    ;# Compute sum first.  Unpack to so signed subract
+    ;#  can be used.  Only have a half word signed
+    ;#  subract.  Do high, then low.
+    vmrghb  \t1, \z0, \src
+    vmrghb  \t2, \z0, \ref
+    vsubshs \t1, \t1, \t2
+    vsum4shs \sum, \t1, \sum
+
+    vmrglb  \t1, \z0, \src
+    vmrglb  \t2, \z0, \ref
+    vsubshs \t1, \t1, \t2
+    vsum4shs \sum, \t1, \sum
+
+    ;# Now compute sse.
+    vsububs \t1, \src, \ref
+    vsububs \t2, \ref, \src
+    vor     \t1, \t1, \t2
+
+    vmsumubm \sse, \t1, \t1, \sse
+.endm
+
+.macro variance_final sum, sse, z0, DS
+    vsumsws \sum, \sum, \z0
+    vsumsws \sse, \sse, \z0
+
+    stvx    \sum, 0, r1
+    lwz     r3, 12(r1)
+
+    stvx    \sse, 0, r1
+    lwz     r4, 12(r1)
+
+    stw     r4, 0(r9)           ;# sse
+
+    mullw   r3, r3, r3          ;# sum*sum
+    srlwi   r3, r3, \DS         ;# (sum*sum) >> 8
+    subf    r3, r3, r4          ;# sse - ((sum*sum) >> 8)
+.endm
+
+.macro compute_sum_sse_16 V, increment_counter
+    load_and_align_16  v16, r7, r8, \increment_counter
+    compute_sum_sse \V, v16, v18, v19, v20, v21, v23
+.endm
+
+.macro load_and_align_16 V, R, P, increment_counter
+    lvsl    v17,  0, \R         ;# permutate value for alignment
+
+    ;# input to filter is 21 bytes wide, output is 16 bytes.
+    ;#  input will can span three vectors if not aligned correctly.
+    lvx     v21,   0, \R
+    lvx     v22, r10, \R
+
+.if \increment_counter
+    add     \R, \R, \P
+.endif
+
+    vperm   \V, v21, v22, v17
+.endm
+
+    .align 2
+;# r3 unsigned char  *src_ptr
+;# r4 int  src_pixels_per_line
+;# r5 int  xoffset
+;# r6 int  yoffset
+;# r7 unsigned char *dst_ptr
+;# r8 int dst_pixels_per_line
+;# r9 unsigned int *sse
+;#
+;# r3 return value
+vp8_sub_pixel_variance4x4_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xf830
+    ori     r12, r12, 0xfff8
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    HProlog second_pass_4x4_pre_copy_b
+
+    ;# Load up permutation constants
+    load_c v10, b_0123_b, 0, r12, r0
+    load_c v11, b_4567_b, 0, r12, r0
+
+    hfilter_8 v0, v10, v11, 1
+    hfilter_8 v1, v10, v11, 1
+    hfilter_8 v2, v10, v11, 1
+    hfilter_8 v3, v10, v11, 1
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional line that is needed
+    ;#  for the vertical filter.
+    beq     compute_sum_sse_4x4_b
+
+    hfilter_8 v4, v10, v11, 0
+
+    b   second_pass_4x4_b
+
+second_pass_4x4_pre_copy_b:
+    slwi    r6, r6, 5           ;# index into vertical filter array
+
+    load_and_align_16 v0, r3, r4, 1
+    load_and_align_16 v1, r3, r4, 1
+    load_and_align_16 v2, r3, r4, 1
+    load_and_align_16 v3, r3, r4, 1
+    load_and_align_16 v4, r3, r4, 0
+
+second_pass_4x4_b:
+    vspltish v20, 8
+    vspltish v18, 3
+    vslh    v18, v20, v18       ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    load_vfilter v20, v21
+
+    vfilter_16 v0,  v1
+    vfilter_16 v1,  v2
+    vfilter_16 v2,  v3
+    vfilter_16 v3,  v4
+
+compute_sum_sse_4x4_b:
+    vspltish v18, 0             ;# sum
+    vspltish v19, 0             ;# sse
+    vspltish v23, 0             ;# unpack
+    li      r10, 16
+
+    load_and_align_16 v4, r7, r8, 1
+    load_and_align_16 v5, r7, r8, 1
+    load_and_align_16 v6, r7, r8, 1
+    load_and_align_16 v7, r7, r8, 1
+
+    vmrghb  v0, v0, v1
+    vmrghb  v1, v2, v3
+
+    vmrghb  v2, v4, v5
+    vmrghb  v3, v6, v7
+
+    load_c v10, b_hilo_b, 0, r12, r0
+
+    vperm   v0, v0, v1, v10
+    vperm   v1, v2, v3, v10
+
+    compute_sum_sse v0, v1, v18, v19, v20, v21, v23
+
+    variance_final v18, v19, v23, 4
+
+    addi    r1, r1, 32          ;# recover stack
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .align 2
+;# r3 unsigned char  *src_ptr
+;# r4 int  src_pixels_per_line
+;# r5 int  xoffset
+;# r6 int  yoffset
+;# r7 unsigned char *dst_ptr
+;# r8 int dst_pixels_per_line
+;# r9 unsigned int *sse
+;#
+;# r3 return value
+vp8_sub_pixel_variance8x8_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xfff0
+    ori     r12, r12, 0xffff
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    HProlog second_pass_8x8_pre_copy_b
+
+    ;# Load up permutation constants
+    load_c v10, b_0123_b, 0, r12, r0
+    load_c v11, b_4567_b, 0, r12, r0
+
+    hfilter_8 v0, v10, v11, 1
+    hfilter_8 v1, v10, v11, 1
+    hfilter_8 v2, v10, v11, 1
+    hfilter_8 v3, v10, v11, 1
+    hfilter_8 v4, v10, v11, 1
+    hfilter_8 v5, v10, v11, 1
+    hfilter_8 v6, v10, v11, 1
+    hfilter_8 v7, v10, v11, 1
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional line that is needed
+    ;#  for the vertical filter.
+    beq     compute_sum_sse_8x8_b
+
+    hfilter_8 v8, v10, v11, 0
+
+    b   second_pass_8x8_b
+
+second_pass_8x8_pre_copy_b:
+    slwi.   r6, r6, 5           ;# index into vertical filter array
+
+    load_and_align_16 v0, r3, r4, 1
+    load_and_align_16 v1, r3, r4, 1
+    load_and_align_16 v2, r3, r4, 1
+    load_and_align_16 v3, r3, r4, 1
+    load_and_align_16 v4, r3, r4, 1
+    load_and_align_16 v5, r3, r4, 1
+    load_and_align_16 v6, r3, r4, 1
+    load_and_align_16 v7, r3, r4, 1
+    load_and_align_16 v8, r3, r4, 0
+
+    beq     compute_sum_sse_8x8_b
+
+second_pass_8x8_b:
+    vspltish v20, 8
+    vspltish v18, 3
+    vslh    v18, v20, v18   ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    load_vfilter v20, v21
+
+    vfilter_16 v0, v1
+    vfilter_16 v1, v2
+    vfilter_16 v2, v3
+    vfilter_16 v3, v4
+    vfilter_16 v4, v5
+    vfilter_16 v5, v6
+    vfilter_16 v6, v7
+    vfilter_16 v7, v8
+
+compute_sum_sse_8x8_b:
+    vspltish v18, 0             ;# sum
+    vspltish v19, 0             ;# sse
+    vspltish v23, 0             ;# unpack
+    li      r10, 16
+
+    vmrghb  v0, v0, v1
+    vmrghb  v1, v2, v3
+    vmrghb  v2, v4, v5
+    vmrghb  v3, v6, v7
+
+    load_and_align_16 v4,  r7, r8, 1
+    load_and_align_16 v5,  r7, r8, 1
+    load_and_align_16 v6,  r7, r8, 1
+    load_and_align_16 v7,  r7, r8, 1
+    load_and_align_16 v8,  r7, r8, 1
+    load_and_align_16 v9,  r7, r8, 1
+    load_and_align_16 v10, r7, r8, 1
+    load_and_align_16 v11, r7, r8, 0
+
+    vmrghb  v4, v4,  v5
+    vmrghb  v5, v6,  v7
+    vmrghb  v6, v8,  v9
+    vmrghb  v7, v10, v11
+
+    compute_sum_sse v0, v4, v18, v19, v20, v21, v23
+    compute_sum_sse v1, v5, v18, v19, v20, v21, v23
+    compute_sum_sse v2, v6, v18, v19, v20, v21, v23
+    compute_sum_sse v3, v7, v18, v19, v20, v21, v23
+
+    variance_final v18, v19, v23, 6
+
+    addi    r1, r1, 32          ;# recover stack
+    mtspr   256, r11            ;# reset old VRSAVE
+    blr
+
+    .align 2
+;# r3 unsigned char  *src_ptr
+;# r4 int  src_pixels_per_line
+;# r5 int  xoffset
+;# r6 int  yoffset
+;# r7 unsigned char *dst_ptr
+;# r8 int dst_pixels_per_line
+;# r9 unsigned int *sse
+;#
+;# r3 return value
+vp8_sub_pixel_variance8x16_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xfffc
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    HProlog second_pass_8x16_pre_copy_b
+
+    ;# Load up permutation constants
+    load_c v29, b_0123_b, 0, r12, r0
+    load_c v30, b_4567_b, 0, r12, r0
+
+    hfilter_8 v0,  v29, v30, 1
+    hfilter_8 v1,  v29, v30, 1
+    hfilter_8 v2,  v29, v30, 1
+    hfilter_8 v3,  v29, v30, 1
+    hfilter_8 v4,  v29, v30, 1
+    hfilter_8 v5,  v29, v30, 1
+    hfilter_8 v6,  v29, v30, 1
+    hfilter_8 v7,  v29, v30, 1
+    hfilter_8 v8,  v29, v30, 1
+    hfilter_8 v9,  v29, v30, 1
+    hfilter_8 v10, v29, v30, 1
+    hfilter_8 v11, v29, v30, 1
+    hfilter_8 v12, v29, v30, 1
+    hfilter_8 v13, v29, v30, 1
+    hfilter_8 v14, v29, v30, 1
+    hfilter_8 v15, v29, v30, 1
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional line that is needed
+    ;#  for the vertical filter.
+    beq     compute_sum_sse_8x16_b
+
+    hfilter_8 v16, v29, v30, 0
+
+    b   second_pass_8x16_b
+
+second_pass_8x16_pre_copy_b:
+    slwi.   r6, r6, 5           ;# index into vertical filter array
+
+    load_and_align_16 v0,  r3, r4, 1
+    load_and_align_16 v1,  r3, r4, 1
+    load_and_align_16 v2,  r3, r4, 1
+    load_and_align_16 v3,  r3, r4, 1
+    load_and_align_16 v4,  r3, r4, 1
+    load_and_align_16 v5,  r3, r4, 1
+    load_and_align_16 v6,  r3, r4, 1
+    load_and_align_16 v7,  r3, r4, 1
+    load_and_align_16 v8,  r3, r4, 1
+    load_and_align_16 v9,  r3, r4, 1
+    load_and_align_16 v10, r3, r4, 1
+    load_and_align_16 v11, r3, r4, 1
+    load_and_align_16 v12, r3, r4, 1
+    load_and_align_16 v13, r3, r4, 1
+    load_and_align_16 v14, r3, r4, 1
+    load_and_align_16 v15, r3, r4, 1
+    load_and_align_16 v16, r3, r4, 0
+
+    beq     compute_sum_sse_8x16_b
+
+second_pass_8x16_b:
+    vspltish v20, 8
+    vspltish v18, 3
+    vslh    v18, v20, v18   ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    load_vfilter v20, v21
+
+    vfilter_16 v0,  v1
+    vfilter_16 v1,  v2
+    vfilter_16 v2,  v3
+    vfilter_16 v3,  v4
+    vfilter_16 v4,  v5
+    vfilter_16 v5,  v6
+    vfilter_16 v6,  v7
+    vfilter_16 v7,  v8
+    vfilter_16 v8,  v9
+    vfilter_16 v9,  v10
+    vfilter_16 v10, v11
+    vfilter_16 v11, v12
+    vfilter_16 v12, v13
+    vfilter_16 v13, v14
+    vfilter_16 v14, v15
+    vfilter_16 v15, v16
+
+compute_sum_sse_8x16_b:
+    vspltish v18, 0             ;# sum
+    vspltish v19, 0             ;# sse
+    vspltish v23, 0             ;# unpack
+    li      r10, 16
+
+    vmrghb  v0, v0,  v1
+    vmrghb  v1, v2,  v3
+    vmrghb  v2, v4,  v5
+    vmrghb  v3, v6,  v7
+    vmrghb  v4, v8,  v9
+    vmrghb  v5, v10, v11
+    vmrghb  v6, v12, v13
+    vmrghb  v7, v14, v15
+
+    load_and_align_16 v8,  r7, r8, 1
+    load_and_align_16 v9,  r7, r8, 1
+    load_and_align_16 v10, r7, r8, 1
+    load_and_align_16 v11, r7, r8, 1
+    load_and_align_16 v12, r7, r8, 1
+    load_and_align_16 v13, r7, r8, 1
+    load_and_align_16 v14, r7, r8, 1
+    load_and_align_16 v15, r7, r8, 1
+
+    vmrghb  v8,  v8,  v9
+    vmrghb  v9,  v10, v11
+    vmrghb  v10, v12, v13
+    vmrghb  v11, v14, v15
+
+    compute_sum_sse v0, v8,  v18, v19, v20, v21, v23
+    compute_sum_sse v1, v9,  v18, v19, v20, v21, v23
+    compute_sum_sse v2, v10, v18, v19, v20, v21, v23
+    compute_sum_sse v3, v11, v18, v19, v20, v21, v23
+
+    load_and_align_16 v8,  r7, r8, 1
+    load_and_align_16 v9,  r7, r8, 1
+    load_and_align_16 v10, r7, r8, 1
+    load_and_align_16 v11, r7, r8, 1
+    load_and_align_16 v12, r7, r8, 1
+    load_and_align_16 v13, r7, r8, 1
+    load_and_align_16 v14, r7, r8, 1
+    load_and_align_16 v15, r7, r8, 0
+
+    vmrghb  v8,  v8,  v9
+    vmrghb  v9,  v10, v11
+    vmrghb  v10, v12, v13
+    vmrghb  v11, v14, v15
+
+    compute_sum_sse v4, v8,  v18, v19, v20, v21, v23
+    compute_sum_sse v5, v9,  v18, v19, v20, v21, v23
+    compute_sum_sse v6, v10, v18, v19, v20, v21, v23
+    compute_sum_sse v7, v11, v18, v19, v20, v21, v23
+
+    variance_final v18, v19, v23, 7
+
+    addi    r1, r1, 32          ;# recover stack
+    mtspr   256, r11            ;# reset old VRSAVE
+    blr
+
+;# Filters a horizontal line
+;# expects:
+;#  r3  src_ptr
+;#  r4  pitch
+;#  r10 16
+;#  r12 32
+;#  v17 perm intput
+;#  v18 rounding
+;#  v19 shift
+;#  v20 filter taps
+;#  v21 tmp
+;#  v22 tmp
+;#  v23 tmp
+;#  v24 tmp
+;#  v25 tmp
+;#  v26 tmp
+;#  v27 tmp
+;#  v28 perm output
+;#
+.macro hfilter_16 V, increment_counter
+
+    lvsl    v17,  0, r3         ;# permutate value for alignment
+
+    ;# input to filter is 21 bytes wide, output is 16 bytes.
+    ;#  input will can span three vectors if not aligned correctly.
+    lvx     v21,   0, r3
+    lvx     v22, r10, r3
+    lvx     v23, r12, r3
+
+.if \increment_counter
+    add     r3, r3, r4
+.endif
+    vperm   v21, v21, v22, v17
+    vperm   v22, v22, v23, v17  ;# v8 v9 = 21 input pixels left-justified
+
+    ;# set 0
+    vmsummbm v24, v20, v21, v18 ;# taps times elements
+
+    ;# set 1
+    vsldoi  v23, v21, v22, 1
+    vmsummbm v25, v20, v23, v18
+
+    ;# set 2
+    vsldoi  v23, v21, v22, 2
+    vmsummbm v26, v20, v23, v18
+
+    ;# set 3
+    vsldoi  v23, v21, v22, 3
+    vmsummbm v27, v20, v23, v18
+
+    vpkswus v24, v24, v25       ;# v24 = 0 4 8 C 1 5 9 D (16-bit)
+    vpkswus v25, v26, v27       ;# v25 = 2 6 A E 3 7 B F
+
+    vsrh    v24, v24, v19       ;# divide v0, v1 by 128
+    vsrh    v25, v25, v19
+
+    vpkuhus \V, v24, v25        ;# \V = scrambled 8-bit result
+    vperm   \V, \V, v0, v28     ;# \V = correctly-ordered result
+.endm
+
+    .align 2
+;# r3 unsigned char  *src_ptr
+;# r4 int  src_pixels_per_line
+;# r5 int  xoffset
+;# r6 int  yoffset
+;# r7 unsigned char *dst_ptr
+;# r8 int dst_pixels_per_line
+;# r9 unsigned int *sse
+;#
+;# r3 return value
+vp8_sub_pixel_variance16x8_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xfff8
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1, -32(r1)         ;# create space on the stack
+
+    HProlog second_pass_16x8_pre_copy_b
+
+    hfilter_16 v0, 1
+    hfilter_16 v1, 1
+    hfilter_16 v2, 1
+    hfilter_16 v3, 1
+    hfilter_16 v4, 1
+    hfilter_16 v5, 1
+    hfilter_16 v6, 1
+    hfilter_16 v7, 1
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional line that is needed
+    ;#  for the vertical filter.
+    beq     compute_sum_sse_16x8_b
+
+    hfilter_16 v8, 0
+
+    b   second_pass_16x8_b
+
+second_pass_16x8_pre_copy_b:
+    slwi.   r6, r6, 5           ;# index into vertical filter array
+
+    load_and_align_16  v0,  r3, r4, 1
+    load_and_align_16  v1,  r3, r4, 1
+    load_and_align_16  v2,  r3, r4, 1
+    load_and_align_16  v3,  r3, r4, 1
+    load_and_align_16  v4,  r3, r4, 1
+    load_and_align_16  v5,  r3, r4, 1
+    load_and_align_16  v6,  r3, r4, 1
+    load_and_align_16  v7,  r3, r4, 1
+    load_and_align_16  v8,  r3, r4, 1
+
+    beq     compute_sum_sse_16x8_b
+
+second_pass_16x8_b:
+    vspltish v20, 8
+    vspltish v18, 3
+    vslh    v18, v20, v18   ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    load_vfilter v20, v21
+
+    vfilter_16 v0,  v1
+    vfilter_16 v1,  v2
+    vfilter_16 v2,  v3
+    vfilter_16 v3,  v4
+    vfilter_16 v4,  v5
+    vfilter_16 v5,  v6
+    vfilter_16 v6,  v7
+    vfilter_16 v7,  v8
+
+compute_sum_sse_16x8_b:
+    vspltish v18, 0             ;# sum
+    vspltish v19, 0             ;# sse
+    vspltish v23, 0             ;# unpack
+    li      r10, 16
+
+    compute_sum_sse_16 v0, 1
+    compute_sum_sse_16 v1, 1
+    compute_sum_sse_16 v2, 1
+    compute_sum_sse_16 v3, 1
+    compute_sum_sse_16 v4, 1
+    compute_sum_sse_16 v5, 1
+    compute_sum_sse_16 v6, 1
+    compute_sum_sse_16 v7, 0
+
+    variance_final v18, v19, v23, 7
+
+    addi    r1, r1, 32          ;# recover stack
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .align 2
+;# r3 unsigned char  *src_ptr
+;# r4 int  src_pixels_per_line
+;# r5 int  xoffset
+;# r6 int  yoffset
+;# r7 unsigned char *dst_ptr
+;# r8 int dst_pixels_per_line
+;# r9 unsigned int *sse
+;#
+;# r3 return value
+vp8_sub_pixel_variance16x16_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xfff8
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1, -32(r1)         ;# create space on the stack
+
+    HProlog second_pass_16x16_pre_copy_b
+
+    hfilter_16 v0,  1
+    hfilter_16 v1,  1
+    hfilter_16 v2,  1
+    hfilter_16 v3,  1
+    hfilter_16 v4,  1
+    hfilter_16 v5,  1
+    hfilter_16 v6,  1
+    hfilter_16 v7,  1
+    hfilter_16 v8,  1
+    hfilter_16 v9,  1
+    hfilter_16 v10, 1
+    hfilter_16 v11, 1
+    hfilter_16 v12, 1
+    hfilter_16 v13, 1
+    hfilter_16 v14, 1
+    hfilter_16 v15, 1
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional line that is needed
+    ;#  for the vertical filter.
+    beq     compute_sum_sse_16x16_b
+
+    hfilter_16 v16, 0
+
+    b   second_pass_16x16_b
+
+second_pass_16x16_pre_copy_b:
+    slwi.   r6, r6, 5           ;# index into vertical filter array
+
+    load_and_align_16  v0,  r3, r4, 1
+    load_and_align_16  v1,  r3, r4, 1
+    load_and_align_16  v2,  r3, r4, 1
+    load_and_align_16  v3,  r3, r4, 1
+    load_and_align_16  v4,  r3, r4, 1
+    load_and_align_16  v5,  r3, r4, 1
+    load_and_align_16  v6,  r3, r4, 1
+    load_and_align_16  v7,  r3, r4, 1
+    load_and_align_16  v8,  r3, r4, 1
+    load_and_align_16  v9,  r3, r4, 1
+    load_and_align_16  v10, r3, r4, 1
+    load_and_align_16  v11, r3, r4, 1
+    load_and_align_16  v12, r3, r4, 1
+    load_and_align_16  v13, r3, r4, 1
+    load_and_align_16  v14, r3, r4, 1
+    load_and_align_16  v15, r3, r4, 1
+    load_and_align_16  v16, r3, r4, 0
+
+    beq     compute_sum_sse_16x16_b
+
+second_pass_16x16_b:
+    vspltish v20, 8
+    vspltish v18, 3
+    vslh    v18, v20, v18   ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    load_vfilter v20, v21
+
+    vfilter_16 v0,  v1
+    vfilter_16 v1,  v2
+    vfilter_16 v2,  v3
+    vfilter_16 v3,  v4
+    vfilter_16 v4,  v5
+    vfilter_16 v5,  v6
+    vfilter_16 v6,  v7
+    vfilter_16 v7,  v8
+    vfilter_16 v8,  v9
+    vfilter_16 v9,  v10
+    vfilter_16 v10, v11
+    vfilter_16 v11, v12
+    vfilter_16 v12, v13
+    vfilter_16 v13, v14
+    vfilter_16 v14, v15
+    vfilter_16 v15, v16
+
+compute_sum_sse_16x16_b:
+    vspltish v18, 0             ;# sum
+    vspltish v19, 0             ;# sse
+    vspltish v23, 0             ;# unpack
+    li      r10, 16
+
+    compute_sum_sse_16 v0,  1
+    compute_sum_sse_16 v1,  1
+    compute_sum_sse_16 v2,  1
+    compute_sum_sse_16 v3,  1
+    compute_sum_sse_16 v4,  1
+    compute_sum_sse_16 v5,  1
+    compute_sum_sse_16 v6,  1
+    compute_sum_sse_16 v7,  1
+    compute_sum_sse_16 v8,  1
+    compute_sum_sse_16 v9,  1
+    compute_sum_sse_16 v10, 1
+    compute_sum_sse_16 v11, 1
+    compute_sum_sse_16 v12, 1
+    compute_sum_sse_16 v13, 1
+    compute_sum_sse_16 v14, 1
+    compute_sum_sse_16 v15, 0
+
+    variance_final v18, v19, v23, 8
+
+    addi    r1, r1, 32          ;# recover stack
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .data
+
+    .align 4
+hfilter_b:
+    .byte   128,  0,  0,  0,128,  0,  0,  0,128,  0,  0,  0,128,  0,  0,  0
+    .byte   112, 16,  0,  0,112, 16,  0,  0,112, 16,  0,  0,112, 16,  0,  0
+    .byte    96, 32,  0,  0, 96, 32,  0,  0, 96, 32,  0,  0, 96, 32,  0,  0
+    .byte    80, 48,  0,  0, 80, 48,  0,  0, 80, 48,  0,  0, 80, 48,  0,  0
+    .byte    64, 64,  0,  0, 64, 64,  0,  0, 64, 64,  0,  0, 64, 64,  0,  0
+    .byte    48, 80,  0,  0, 48, 80,  0,  0, 48, 80,  0,  0, 48, 80,  0,  0
+    .byte    32, 96,  0,  0, 32, 96,  0,  0, 32, 96,  0,  0, 32, 96,  0,  0
+    .byte    16,112,  0,  0, 16,112,  0,  0, 16,112,  0,  0, 16,112,  0,  0
+
+    .align 4
+vfilter_b:
+    .byte   128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128
+    .byte     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    .byte   112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112
+    .byte    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
+    .byte    96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96
+    .byte    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
+    .byte    80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80
+    .byte    48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48
+    .byte    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
+    .byte    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
+    .byte    48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48
+    .byte    80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80
+    .byte    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
+    .byte    96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96
+    .byte    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
+    .byte   112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112
+
+    .align 4
+b_hperm_b:
+    .byte     0,  4,  8, 12,  1,  5,  9, 13,  2,  6, 10, 14,  3,  7, 11, 15
+
+    .align 4
+b_0123_b:
+    .byte     0,  1,  2,  3,  1,  2,  3,  4,  2,  3,  4,  5,  3,  4,  5,  6
+
+    .align 4
+b_4567_b:
+    .byte     4,  5,  6,  7,  5,  6,  7,  8,  6,  7,  8,  9,  7,  8,  9, 10
+
+b_hilo_b:
+    .byte     0,  1,  2,  3,  4,  5,  6,  7, 16, 17, 18, 19, 20, 21, 22, 23
diff --git a/vp8/common/ppflags.h b/vp8/common/ppflags.h
new file mode 100644 (file)
index 0000000..665e21f
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_PPFLAGS_H
+#define __INC_PPFLAGS_H
+enum
+{
+    VP8D_NOFILTERING            = 0,
+    VP8D_DEBLOCK                = 1<<0,
+    VP8D_DEMACROBLOCK           = 1<<1,
+    VP8D_ADDNOISE               = 1<<2,
+    VP8D_DEBUG_TXT_FRAME_INFO   = 1<<3,
+    VP8D_DEBUG_TXT_MBLK_MODES   = 1<<4,
+    VP8D_DEBUG_TXT_DC_DIFF      = 1<<5,
+    VP8D_DEBUG_TXT_RATE_INFO    = 1<<6,
+    VP8D_DEBUG_DRAW_MV          = 1<<7,
+    VP8D_DEBUG_CLR_BLK_MODES    = 1<<8,
+    VP8D_DEBUG_CLR_FRM_REF_BLKS = 1<<9,
+    VP8D_MFQE                   = 1<<10
+};
+
+typedef struct
+{
+    int post_proc_flag;
+    int deblocking_level;
+    int noise_level;
+    int display_ref_frame_flag;
+    int display_mb_modes_flag;
+    int display_b_modes_flag;
+    int display_mv_flag;
+} vp8_ppflags_t;
+
+#endif
diff --git a/vp8/common/pragmas.h b/vp8/common/pragmas.h
new file mode 100644 (file)
index 0000000..99fee5a
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+
+
+#ifdef __INTEL_COMPILER
+#pragma warning(disable:997 1011 170)
+#endif
+#ifdef _MSC_VER
+#pragma warning(disable:4799)
+#endif
diff --git a/vp8/common/quant_common.c b/vp8/common/quant_common.c
new file mode 100644 (file)
index 0000000..e9833fe
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "quant_common.h"
+
+static const int dc_qlookup[QINDEX_RANGE] =
+{
+    4,    5,    6,    7,    8,    9,   10,   10,   11,   12,   13,   14,   15,   16,   17,   17,
+    18,   19,   20,   20,   21,   21,   22,   22,   23,   23,   24,   25,   25,   26,   27,   28,
+    29,   30,   31,   32,   33,   34,   35,   36,   37,   37,   38,   39,   40,   41,   42,   43,
+    44,   45,   46,   46,   47,   48,   49,   50,   51,   52,   53,   54,   55,   56,   57,   58,
+    59,   60,   61,   62,   63,   64,   65,   66,   67,   68,   69,   70,   71,   72,   73,   74,
+    75,   76,   76,   77,   78,   79,   80,   81,   82,   83,   84,   85,   86,   87,   88,   89,
+    91,   93,   95,   96,   98,  100,  101,  102,  104,  106,  108,  110,  112,  114,  116,  118,
+    122,  124,  126,  128,  130,  132,  134,  136,  138,  140,  143,  145,  148,  151,  154,  157,
+};
+
+static const int ac_qlookup[QINDEX_RANGE] =
+{
+    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,   15,   16,   17,   18,   19,
+    20,   21,   22,   23,   24,   25,   26,   27,   28,   29,   30,   31,   32,   33,   34,   35,
+    36,   37,   38,   39,   40,   41,   42,   43,   44,   45,   46,   47,   48,   49,   50,   51,
+    52,   53,   54,   55,   56,   57,   58,   60,   62,   64,   66,   68,   70,   72,   74,   76,
+    78,   80,   82,   84,   86,   88,   90,   92,   94,   96,   98,  100,  102,  104,  106,  108,
+    110,  112,  114,  116,  119,  122,  125,  128,  131,  134,  137,  140,  143,  146,  149,  152,
+    155,  158,  161,  164,  167,  170,  173,  177,  181,  185,  189,  193,  197,  201,  205,  209,
+    213,  217,  221,  225,  229,  234,  239,  245,  249,  254,  259,  264,  269,  274,  279,  284,
+};
+
+
+int vp8_dc_quant(int QIndex, int Delta)
+{
+    int retval;
+
+    QIndex = QIndex + Delta;
+
+    if (QIndex > 127)
+        QIndex = 127;
+    else if (QIndex < 0)
+        QIndex = 0;
+
+    retval = dc_qlookup[ QIndex ];
+    return retval;
+}
+
+int vp8_dc2quant(int QIndex, int Delta)
+{
+    int retval;
+
+    QIndex = QIndex + Delta;
+
+    if (QIndex > 127)
+        QIndex = 127;
+    else if (QIndex < 0)
+        QIndex = 0;
+
+    retval = dc_qlookup[ QIndex ] * 2;
+    return retval;
+
+}
+int vp8_dc_uv_quant(int QIndex, int Delta)
+{
+    int retval;
+
+    QIndex = QIndex + Delta;
+
+    if (QIndex > 127)
+        QIndex = 127;
+    else if (QIndex < 0)
+        QIndex = 0;
+
+    retval = dc_qlookup[ QIndex ];
+
+    if (retval > 132)
+        retval = 132;
+
+    return retval;
+}
+
+int vp8_ac_yquant(int QIndex)
+{
+    int retval;
+
+    if (QIndex > 127)
+        QIndex = 127;
+    else if (QIndex < 0)
+        QIndex = 0;
+
+    retval = ac_qlookup[ QIndex ];
+    return retval;
+}
+
+int vp8_ac2quant(int QIndex, int Delta)
+{
+    int retval;
+
+    QIndex = QIndex + Delta;
+
+    if (QIndex > 127)
+        QIndex = 127;
+    else if (QIndex < 0)
+        QIndex = 0;
+
+    retval = (ac_qlookup[ QIndex ] * 155) / 100;
+
+    if (retval < 8)
+        retval = 8;
+
+    return retval;
+}
+int vp8_ac_uv_quant(int QIndex, int Delta)
+{
+    int retval;
+
+    QIndex = QIndex + Delta;
+
+    if (QIndex > 127)
+        QIndex = 127;
+    else if (QIndex < 0)
+        QIndex = 0;
+
+    retval = ac_qlookup[ QIndex ];
+    return retval;
+}
diff --git a/vp8/common/quant_common.h b/vp8/common/quant_common.h
new file mode 100644 (file)
index 0000000..cb64d8e
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "string.h"
+#include "blockd.h"
+#include "onyxc_int.h"
+
+extern int vp8_ac_yquant(int QIndex);
+extern int vp8_dc_quant(int QIndex, int Delta);
+extern int vp8_dc2quant(int QIndex, int Delta);
+extern int vp8_ac2quant(int QIndex, int Delta);
+extern int vp8_dc_uv_quant(int QIndex, int Delta);
+extern int vp8_ac_uv_quant(int QIndex, int Delta);
diff --git a/vp8/common/reconinter.c b/vp8/common/reconinter.c
new file mode 100644 (file)
index 0000000..3da3bc7
--- /dev/null
@@ -0,0 +1,595 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include <limits.h>
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "vpx/vpx_integer.h"
+#include "blockd.h"
+#include "reconinter.h"
+#if CONFIG_RUNTIME_CPU_DETECT
+#include "onyxc_int.h"
+#endif
+
+void vp8_copy_mem16x16_c(
+    unsigned char *src,
+    int src_stride,
+    unsigned char *dst,
+    int dst_stride)
+{
+
+    int r;
+
+    for (r = 0; r < 16; r++)
+    {
+#if !(CONFIG_FAST_UNALIGNED)
+        dst[0] = src[0];
+        dst[1] = src[1];
+        dst[2] = src[2];
+        dst[3] = src[3];
+        dst[4] = src[4];
+        dst[5] = src[5];
+        dst[6] = src[6];
+        dst[7] = src[7];
+        dst[8] = src[8];
+        dst[9] = src[9];
+        dst[10] = src[10];
+        dst[11] = src[11];
+        dst[12] = src[12];
+        dst[13] = src[13];
+        dst[14] = src[14];
+        dst[15] = src[15];
+
+#else
+        ((uint32_t *)dst)[0] = ((uint32_t *)src)[0] ;
+        ((uint32_t *)dst)[1] = ((uint32_t *)src)[1] ;
+        ((uint32_t *)dst)[2] = ((uint32_t *)src)[2] ;
+        ((uint32_t *)dst)[3] = ((uint32_t *)src)[3] ;
+
+#endif
+        src += src_stride;
+        dst += dst_stride;
+
+    }
+
+}
+
+void vp8_copy_mem8x8_c(
+    unsigned char *src,
+    int src_stride,
+    unsigned char *dst,
+    int dst_stride)
+{
+    int r;
+
+    for (r = 0; r < 8; r++)
+    {
+#if !(CONFIG_FAST_UNALIGNED)
+        dst[0] = src[0];
+        dst[1] = src[1];
+        dst[2] = src[2];
+        dst[3] = src[3];
+        dst[4] = src[4];
+        dst[5] = src[5];
+        dst[6] = src[6];
+        dst[7] = src[7];
+#else
+        ((uint32_t *)dst)[0] = ((uint32_t *)src)[0] ;
+        ((uint32_t *)dst)[1] = ((uint32_t *)src)[1] ;
+#endif
+        src += src_stride;
+        dst += dst_stride;
+
+    }
+
+}
+
+void vp8_copy_mem8x4_c(
+    unsigned char *src,
+    int src_stride,
+    unsigned char *dst,
+    int dst_stride)
+{
+    int r;
+
+    for (r = 0; r < 4; r++)
+    {
+#if !(CONFIG_FAST_UNALIGNED)
+        dst[0] = src[0];
+        dst[1] = src[1];
+        dst[2] = src[2];
+        dst[3] = src[3];
+        dst[4] = src[4];
+        dst[5] = src[5];
+        dst[6] = src[6];
+        dst[7] = src[7];
+#else
+        ((uint32_t *)dst)[0] = ((uint32_t *)src)[0] ;
+        ((uint32_t *)dst)[1] = ((uint32_t *)src)[1] ;
+#endif
+        src += src_stride;
+        dst += dst_stride;
+
+    }
+
+}
+
+
+void vp8_build_inter_predictors_b(BLOCKD *d, int pitch, unsigned char *base_pre, int pre_stride, vp8_subpix_fn_t sppf)
+{
+    int r;
+    unsigned char *pred_ptr = d->predictor;
+    unsigned char *ptr;
+    ptr = base_pre + d->offset + (d->bmi.mv.as_mv.row >> 3) * pre_stride + (d->bmi.mv.as_mv.col >> 3);
+
+    if (d->bmi.mv.as_mv.row & 7 || d->bmi.mv.as_mv.col & 7)
+    {
+        sppf(ptr, pre_stride, d->bmi.mv.as_mv.col & 7, d->bmi.mv.as_mv.row & 7, pred_ptr, pitch);
+    }
+    else
+    {
+        for (r = 0; r < 4; r++)
+        {
+#if !(CONFIG_FAST_UNALIGNED)
+            pred_ptr[0]  = ptr[0];
+            pred_ptr[1]  = ptr[1];
+            pred_ptr[2]  = ptr[2];
+            pred_ptr[3]  = ptr[3];
+#else
+            *(uint32_t *)pred_ptr = *(uint32_t *)ptr ;
+#endif
+            pred_ptr     += pitch;
+            ptr         += pre_stride;
+        }
+    }
+}
+
+static void build_inter_predictors4b(MACROBLOCKD *x, BLOCKD *d, unsigned char *dst, int dst_stride, unsigned char *base_pre, int pre_stride)
+{
+    unsigned char *ptr;
+    ptr = base_pre + d->offset + (d->bmi.mv.as_mv.row >> 3) * pre_stride + (d->bmi.mv.as_mv.col >> 3);
+
+    if (d->bmi.mv.as_mv.row & 7 || d->bmi.mv.as_mv.col & 7)
+    {
+        x->subpixel_predict8x8(ptr, pre_stride, d->bmi.mv.as_mv.col & 7, d->bmi.mv.as_mv.row & 7, dst, dst_stride);
+    }
+    else
+    {
+        vp8_copy_mem8x8(ptr, pre_stride, dst, dst_stride);
+    }
+}
+
+static void build_inter_predictors2b(MACROBLOCKD *x, BLOCKD *d, unsigned char *dst, int dst_stride, unsigned char *base_pre, int pre_stride)
+{
+    unsigned char *ptr;
+    ptr = base_pre + d->offset + (d->bmi.mv.as_mv.row >> 3) * pre_stride + (d->bmi.mv.as_mv.col >> 3);
+
+    if (d->bmi.mv.as_mv.row & 7 || d->bmi.mv.as_mv.col & 7)
+    {
+        x->subpixel_predict8x4(ptr, pre_stride, d->bmi.mv.as_mv.col & 7, d->bmi.mv.as_mv.row & 7, dst, dst_stride);
+    }
+    else
+    {
+        vp8_copy_mem8x4(ptr, pre_stride, dst, dst_stride);
+    }
+}
+
+static void build_inter_predictors_b(BLOCKD *d, unsigned char *dst, int dst_stride, unsigned char *base_pre, int pre_stride, vp8_subpix_fn_t sppf)
+{
+    int r;
+    unsigned char *ptr;
+    ptr = base_pre + d->offset + (d->bmi.mv.as_mv.row >> 3) * pre_stride + (d->bmi.mv.as_mv.col >> 3);
+
+    if (d->bmi.mv.as_mv.row & 7 || d->bmi.mv.as_mv.col & 7)
+    {
+        sppf(ptr, pre_stride, d->bmi.mv.as_mv.col & 7, d->bmi.mv.as_mv.row & 7, dst, dst_stride);
+    }
+    else
+    {
+        for (r = 0; r < 4; r++)
+        {
+#if !(CONFIG_FAST_UNALIGNED)
+          dst[0]  = ptr[0];
+          dst[1]  = ptr[1];
+          dst[2]  = ptr[2];
+          dst[3]  = ptr[3];
+#else
+            *(uint32_t *)dst = *(uint32_t *)ptr ;
+#endif
+            dst     += dst_stride;
+            ptr     += pre_stride;
+        }
+    }
+}
+
+
+/*encoder only*/
+void vp8_build_inter16x16_predictors_mbuv(MACROBLOCKD *x)
+{
+    unsigned char *uptr, *vptr;
+    unsigned char *upred_ptr = &x->predictor[256];
+    unsigned char *vpred_ptr = &x->predictor[320];
+
+    int mv_row = x->mode_info_context->mbmi.mv.as_mv.row;
+    int mv_col = x->mode_info_context->mbmi.mv.as_mv.col;
+    int offset;
+    int pre_stride = x->pre.uv_stride;
+
+    /* calc uv motion vectors */
+    mv_row += 1 | (mv_row >> (sizeof(int) * CHAR_BIT - 1));
+    mv_col += 1 | (mv_col >> (sizeof(int) * CHAR_BIT - 1));
+    mv_row /= 2;
+    mv_col /= 2;
+    mv_row &= x->fullpixel_mask;
+    mv_col &= x->fullpixel_mask;
+
+    offset = (mv_row >> 3) * pre_stride + (mv_col >> 3);
+    uptr = x->pre.u_buffer + offset;
+    vptr = x->pre.v_buffer + offset;
+
+    if ((mv_row | mv_col) & 7)
+    {
+        x->subpixel_predict8x8(uptr, pre_stride, mv_col & 7, mv_row & 7, upred_ptr, 8);
+        x->subpixel_predict8x8(vptr, pre_stride, mv_col & 7, mv_row & 7, vpred_ptr, 8);
+    }
+    else
+    {
+        vp8_copy_mem8x8(uptr, pre_stride, upred_ptr, 8);
+        vp8_copy_mem8x8(vptr, pre_stride, vpred_ptr, 8);
+    }
+}
+
+/*encoder only*/
+void vp8_build_inter4x4_predictors_mbuv(MACROBLOCKD *x)
+{
+    int i, j;
+    int pre_stride = x->pre.uv_stride;
+    unsigned char *base_pre;
+
+    /* build uv mvs */
+    for (i = 0; i < 2; i++)
+    {
+        for (j = 0; j < 2; j++)
+        {
+            int yoffset = i * 8 + j * 2;
+            int uoffset = 16 + i * 2 + j;
+            int voffset = 20 + i * 2 + j;
+
+            int temp;
+
+            temp = x->block[yoffset  ].bmi.mv.as_mv.row
+                   + x->block[yoffset+1].bmi.mv.as_mv.row
+                   + x->block[yoffset+4].bmi.mv.as_mv.row
+                   + x->block[yoffset+5].bmi.mv.as_mv.row;
+
+            temp += 4 + ((temp >> (sizeof(int) * CHAR_BIT - 1)) << 3);
+
+            x->block[uoffset].bmi.mv.as_mv.row = (temp / 8) & x->fullpixel_mask;
+
+            temp = x->block[yoffset  ].bmi.mv.as_mv.col
+                   + x->block[yoffset+1].bmi.mv.as_mv.col
+                   + x->block[yoffset+4].bmi.mv.as_mv.col
+                   + x->block[yoffset+5].bmi.mv.as_mv.col;
+
+            temp += 4 + ((temp >> (sizeof(int) * CHAR_BIT - 1)) << 3);
+
+            x->block[uoffset].bmi.mv.as_mv.col = (temp / 8) & x->fullpixel_mask;
+
+            x->block[voffset].bmi.mv.as_int = x->block[uoffset].bmi.mv.as_int;
+        }
+    }
+
+    base_pre = x->pre.u_buffer;
+    for (i = 16; i < 20; i += 2)
+    {
+        BLOCKD *d0 = &x->block[i];
+        BLOCKD *d1 = &x->block[i+1];
+
+        if (d0->bmi.mv.as_int == d1->bmi.mv.as_int)
+            build_inter_predictors2b(x, d0, d0->predictor, 8, base_pre, pre_stride);
+        else
+        {
+            vp8_build_inter_predictors_b(d0, 8, base_pre, pre_stride, x->subpixel_predict);
+            vp8_build_inter_predictors_b(d1, 8, base_pre, pre_stride, x->subpixel_predict);
+        }
+    }
+
+    base_pre = x->pre.v_buffer;
+    for (i = 20; i < 24; i += 2)
+    {
+        BLOCKD *d0 = &x->block[i];
+        BLOCKD *d1 = &x->block[i+1];
+
+        if (d0->bmi.mv.as_int == d1->bmi.mv.as_int)
+            build_inter_predictors2b(x, d0, d0->predictor, 8, base_pre, pre_stride);
+        else
+        {
+            vp8_build_inter_predictors_b(d0, 8, base_pre, pre_stride, x->subpixel_predict);
+            vp8_build_inter_predictors_b(d1, 8, base_pre, pre_stride, x->subpixel_predict);
+        }
+    }
+}
+
+
+/*encoder only*/
+void vp8_build_inter16x16_predictors_mby(MACROBLOCKD *x,
+                                         unsigned char *dst_y,
+                                         int dst_ystride)
+{
+    unsigned char *ptr_base;
+    unsigned char *ptr;
+    int mv_row = x->mode_info_context->mbmi.mv.as_mv.row;
+    int mv_col = x->mode_info_context->mbmi.mv.as_mv.col;
+    int pre_stride = x->pre.y_stride;
+
+    ptr_base = x->pre.y_buffer;
+    ptr = ptr_base + (mv_row >> 3) * pre_stride + (mv_col >> 3);
+
+    if ((mv_row | mv_col) & 7)
+    {
+        x->subpixel_predict16x16(ptr, pre_stride, mv_col & 7, mv_row & 7,
+                                 dst_y, dst_ystride);
+    }
+    else
+    {
+        vp8_copy_mem16x16(ptr, pre_stride, dst_y,
+            dst_ystride);
+    }
+}
+
+static void clamp_mv_to_umv_border(MV *mv, const MACROBLOCKD *xd)
+{
+    /* If the MV points so far into the UMV border that no visible pixels
+     * are used for reconstruction, the subpel part of the MV can be
+     * discarded and the MV limited to 16 pixels with equivalent results.
+     *
+     * This limit kicks in at 19 pixels for the top and left edges, for
+     * the 16 pixels plus 3 taps right of the central pixel when subpel
+     * filtering. The bottom and right edges use 16 pixels plus 2 pixels
+     * left of the central pixel when filtering.
+     */
+    if (mv->col < (xd->mb_to_left_edge - (19 << 3)))
+        mv->col = xd->mb_to_left_edge - (16 << 3);
+    else if (mv->col > xd->mb_to_right_edge + (18 << 3))
+        mv->col = xd->mb_to_right_edge + (16 << 3);
+
+    if (mv->row < (xd->mb_to_top_edge - (19 << 3)))
+        mv->row = xd->mb_to_top_edge - (16 << 3);
+    else if (mv->row > xd->mb_to_bottom_edge + (18 << 3))
+        mv->row = xd->mb_to_bottom_edge + (16 << 3);
+}
+
+/* A version of the above function for chroma block MVs.*/
+static void clamp_uvmv_to_umv_border(MV *mv, const MACROBLOCKD *xd)
+{
+    mv->col = (2*mv->col < (xd->mb_to_left_edge - (19 << 3))) ?
+        (xd->mb_to_left_edge - (16 << 3)) >> 1 : mv->col;
+    mv->col = (2*mv->col > xd->mb_to_right_edge + (18 << 3)) ?
+        (xd->mb_to_right_edge + (16 << 3)) >> 1 : mv->col;
+
+    mv->row = (2*mv->row < (xd->mb_to_top_edge - (19 << 3))) ?
+        (xd->mb_to_top_edge - (16 << 3)) >> 1 : mv->row;
+    mv->row = (2*mv->row > xd->mb_to_bottom_edge + (18 << 3)) ?
+        (xd->mb_to_bottom_edge + (16 << 3)) >> 1 : mv->row;
+}
+
+void vp8_build_inter16x16_predictors_mb(MACROBLOCKD *x,
+                                        unsigned char *dst_y,
+                                        unsigned char *dst_u,
+                                        unsigned char *dst_v,
+                                        int dst_ystride,
+                                        int dst_uvstride)
+{
+    int offset;
+    unsigned char *ptr;
+    unsigned char *uptr, *vptr;
+
+    int_mv _16x16mv;
+
+    unsigned char *ptr_base = x->pre.y_buffer;
+    int pre_stride = x->pre.y_stride;
+
+    _16x16mv.as_int = x->mode_info_context->mbmi.mv.as_int;
+
+    if (x->mode_info_context->mbmi.need_to_clamp_mvs)
+    {
+        clamp_mv_to_umv_border(&_16x16mv.as_mv, x);
+    }
+
+    ptr = ptr_base + ( _16x16mv.as_mv.row >> 3) * pre_stride + (_16x16mv.as_mv.col >> 3);
+
+    if ( _16x16mv.as_int & 0x00070007)
+    {
+        x->subpixel_predict16x16(ptr, pre_stride, _16x16mv.as_mv.col & 7,  _16x16mv.as_mv.row & 7, dst_y, dst_ystride);
+    }
+    else
+    {
+        vp8_copy_mem16x16(ptr, pre_stride, dst_y, dst_ystride);
+    }
+
+    /* calc uv motion vectors */
+    _16x16mv.as_mv.row += 1 | (_16x16mv.as_mv.row >> (sizeof(int) * CHAR_BIT - 1));
+    _16x16mv.as_mv.col += 1 | (_16x16mv.as_mv.col >> (sizeof(int) * CHAR_BIT - 1));
+    _16x16mv.as_mv.row /= 2;
+    _16x16mv.as_mv.col /= 2;
+    _16x16mv.as_mv.row &= x->fullpixel_mask;
+    _16x16mv.as_mv.col &= x->fullpixel_mask;
+
+    pre_stride >>= 1;
+    offset = ( _16x16mv.as_mv.row >> 3) * pre_stride + (_16x16mv.as_mv.col >> 3);
+    uptr = x->pre.u_buffer + offset;
+    vptr = x->pre.v_buffer + offset;
+
+    if ( _16x16mv.as_int & 0x00070007)
+    {
+        x->subpixel_predict8x8(uptr, pre_stride, _16x16mv.as_mv.col & 7,  _16x16mv.as_mv.row & 7, dst_u, dst_uvstride);
+        x->subpixel_predict8x8(vptr, pre_stride, _16x16mv.as_mv.col & 7,  _16x16mv.as_mv.row & 7, dst_v, dst_uvstride);
+    }
+    else
+    {
+        vp8_copy_mem8x8(uptr, pre_stride, dst_u, dst_uvstride);
+        vp8_copy_mem8x8(vptr, pre_stride, dst_v, dst_uvstride);
+    }
+}
+
+static void build_inter4x4_predictors_mb(MACROBLOCKD *x)
+{
+    int i;
+    unsigned char *base_dst = x->dst.y_buffer;
+    unsigned char *base_pre = x->pre.y_buffer;
+
+    if (x->mode_info_context->mbmi.partitioning < 3)
+    {
+        BLOCKD *b;
+        int dst_stride = x->dst.y_stride;
+
+        x->block[ 0].bmi = x->mode_info_context->bmi[ 0];
+        x->block[ 2].bmi = x->mode_info_context->bmi[ 2];
+        x->block[ 8].bmi = x->mode_info_context->bmi[ 8];
+        x->block[10].bmi = x->mode_info_context->bmi[10];
+        if (x->mode_info_context->mbmi.need_to_clamp_mvs)
+        {
+            clamp_mv_to_umv_border(&x->block[ 0].bmi.mv.as_mv, x);
+            clamp_mv_to_umv_border(&x->block[ 2].bmi.mv.as_mv, x);
+            clamp_mv_to_umv_border(&x->block[ 8].bmi.mv.as_mv, x);
+            clamp_mv_to_umv_border(&x->block[10].bmi.mv.as_mv, x);
+        }
+
+        b = &x->block[ 0];
+        build_inter_predictors4b(x, b, base_dst + b->offset, dst_stride, base_pre, dst_stride);
+        b = &x->block[ 2];
+        build_inter_predictors4b(x, b, base_dst + b->offset, dst_stride, base_pre, dst_stride);
+        b = &x->block[ 8];
+        build_inter_predictors4b(x, b, base_dst + b->offset, dst_stride, base_pre, dst_stride);
+        b = &x->block[10];
+        build_inter_predictors4b(x, b, base_dst + b->offset, dst_stride, base_pre, dst_stride);
+    }
+    else
+    {
+        for (i = 0; i < 16; i += 2)
+        {
+            BLOCKD *d0 = &x->block[i];
+            BLOCKD *d1 = &x->block[i+1];
+            int dst_stride = x->dst.y_stride;
+
+            x->block[i+0].bmi = x->mode_info_context->bmi[i+0];
+            x->block[i+1].bmi = x->mode_info_context->bmi[i+1];
+            if (x->mode_info_context->mbmi.need_to_clamp_mvs)
+            {
+                clamp_mv_to_umv_border(&x->block[i+0].bmi.mv.as_mv, x);
+                clamp_mv_to_umv_border(&x->block[i+1].bmi.mv.as_mv, x);
+            }
+
+            if (d0->bmi.mv.as_int == d1->bmi.mv.as_int)
+                build_inter_predictors2b(x, d0, base_dst + d0->offset, dst_stride, base_pre, dst_stride);
+            else
+            {
+                build_inter_predictors_b(d0, base_dst + d0->offset, dst_stride, base_pre, dst_stride, x->subpixel_predict);
+                build_inter_predictors_b(d1, base_dst + d1->offset, dst_stride, base_pre, dst_stride, x->subpixel_predict);
+            }
+
+        }
+
+    }
+    base_dst = x->dst.u_buffer;
+    base_pre = x->pre.u_buffer;
+    for (i = 16; i < 20; i += 2)
+    {
+        BLOCKD *d0 = &x->block[i];
+        BLOCKD *d1 = &x->block[i+1];
+        int dst_stride = x->dst.uv_stride;
+
+        /* Note: uv mvs already clamped in build_4x4uvmvs() */
+
+        if (d0->bmi.mv.as_int == d1->bmi.mv.as_int)
+            build_inter_predictors2b(x, d0, base_dst + d0->offset, dst_stride, base_pre, dst_stride);
+        else
+        {
+            build_inter_predictors_b(d0, base_dst + d0->offset, dst_stride, base_pre, dst_stride, x->subpixel_predict);
+            build_inter_predictors_b(d1, base_dst + d1->offset, dst_stride, base_pre, dst_stride, x->subpixel_predict);
+        }
+    }
+
+    base_dst = x->dst.v_buffer;
+    base_pre = x->pre.v_buffer;
+    for (i = 20; i < 24; i += 2)
+    {
+        BLOCKD *d0 = &x->block[i];
+        BLOCKD *d1 = &x->block[i+1];
+        int dst_stride = x->dst.uv_stride;
+
+        /* Note: uv mvs already clamped in build_4x4uvmvs() */
+
+        if (d0->bmi.mv.as_int == d1->bmi.mv.as_int)
+            build_inter_predictors2b(x, d0, base_dst + d0->offset, dst_stride, base_pre, dst_stride);
+        else
+        {
+            build_inter_predictors_b(d0, base_dst + d0->offset, dst_stride, base_pre, dst_stride, x->subpixel_predict);
+            build_inter_predictors_b(d1, base_dst + d1->offset, dst_stride, base_pre, dst_stride, x->subpixel_predict);
+        }
+    }
+}
+
+static
+void build_4x4uvmvs(MACROBLOCKD *x)
+{
+    int i, j;
+
+    for (i = 0; i < 2; i++)
+    {
+        for (j = 0; j < 2; j++)
+        {
+            int yoffset = i * 8 + j * 2;
+            int uoffset = 16 + i * 2 + j;
+            int voffset = 20 + i * 2 + j;
+
+            int temp;
+
+            temp = x->mode_info_context->bmi[yoffset + 0].mv.as_mv.row
+                 + x->mode_info_context->bmi[yoffset + 1].mv.as_mv.row
+                 + x->mode_info_context->bmi[yoffset + 4].mv.as_mv.row
+                 + x->mode_info_context->bmi[yoffset + 5].mv.as_mv.row;
+
+            temp += 4 + ((temp >> (sizeof(int) * CHAR_BIT - 1)) << 3);
+
+            x->block[uoffset].bmi.mv.as_mv.row = (temp / 8) & x->fullpixel_mask;
+
+            temp = x->mode_info_context->bmi[yoffset + 0].mv.as_mv.col
+                 + x->mode_info_context->bmi[yoffset + 1].mv.as_mv.col
+                 + x->mode_info_context->bmi[yoffset + 4].mv.as_mv.col
+                 + x->mode_info_context->bmi[yoffset + 5].mv.as_mv.col;
+
+            temp += 4 + ((temp >> (sizeof(int) * CHAR_BIT - 1)) << 3);
+
+            x->block[uoffset].bmi.mv.as_mv.col = (temp / 8) & x->fullpixel_mask;
+
+            if (x->mode_info_context->mbmi.need_to_clamp_mvs)
+                clamp_uvmv_to_umv_border(&x->block[uoffset].bmi.mv.as_mv, x);
+
+            x->block[voffset].bmi.mv.as_int = x->block[uoffset].bmi.mv.as_int;
+        }
+    }
+}
+
+void vp8_build_inter_predictors_mb(MACROBLOCKD *xd)
+{
+    if (xd->mode_info_context->mbmi.mode != SPLITMV)
+    {
+        vp8_build_inter16x16_predictors_mb(xd, xd->dst.y_buffer,
+                                           xd->dst.u_buffer, xd->dst.v_buffer,
+                                           xd->dst.y_stride, xd->dst.uv_stride);
+    }
+    else
+    {
+        build_4x4uvmvs(xd);
+        build_inter4x4_predictors_mb(xd);
+    }
+}
diff --git a/vp8/common/reconinter.h b/vp8/common/reconinter.h
new file mode 100644 (file)
index 0000000..233c02e
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_RECONINTER_H
+#define __INC_RECONINTER_H
+
+extern void vp8_build_inter_predictors_mb(MACROBLOCKD *x);
+extern void vp8_build_inter16x16_predictors_mb(MACROBLOCKD *x,
+                                               unsigned char *dst_y,
+                                               unsigned char *dst_u,
+                                               unsigned char *dst_v,
+                                               int dst_ystride,
+                                               int dst_uvstride);
+
+
+extern void vp8_build_inter16x16_predictors_mby(MACROBLOCKD *x,
+                                                unsigned char *dst_y,
+                                                int dst_ystride);
+extern void vp8_build_inter_predictors_b(BLOCKD *d, int pitch,
+                                         unsigned char *base_pre,
+                                         int pre_stride,
+                                         vp8_subpix_fn_t sppf);
+
+extern void vp8_build_inter16x16_predictors_mbuv(MACROBLOCKD *x);
+extern void vp8_build_inter4x4_predictors_mbuv(MACROBLOCKD *x);
+
+#endif
diff --git a/vp8/common/reconintra.c b/vp8/common/reconintra.c
new file mode 100644 (file)
index 0000000..4067a68
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "vpx_mem/vpx_mem.h"
+#include "blockd.h"
+
+void vp8_build_intra_predictors_mby_s_c(MACROBLOCKD *x,
+                                          unsigned char * yabove_row,
+                                          unsigned char * yleft,
+                                          int left_stride,
+                                          unsigned char * ypred_ptr,
+                                          int y_stride)
+{
+    unsigned char yleft_col[16];
+    unsigned char ytop_left = yabove_row[-1];
+    int r, c, i;
+
+    for (i = 0; i < 16; i++)
+    {
+        yleft_col[i] = yleft[i* left_stride];
+    }
+
+    /* for Y */
+    switch (x->mode_info_context->mbmi.mode)
+    {
+    case DC_PRED:
+    {
+        int expected_dc;
+        int i;
+        int shift;
+        int average = 0;
+
+
+        if (x->up_available || x->left_available)
+        {
+            if (x->up_available)
+            {
+                for (i = 0; i < 16; i++)
+                {
+                    average += yabove_row[i];
+                }
+            }
+
+            if (x->left_available)
+            {
+
+                for (i = 0; i < 16; i++)
+                {
+                    average += yleft_col[i];
+                }
+
+            }
+
+
+
+            shift = 3 + x->up_available + x->left_available;
+            expected_dc = (average + (1 << (shift - 1))) >> shift;
+        }
+        else
+        {
+            expected_dc = 128;
+        }
+
+        /*vpx_memset(ypred_ptr, expected_dc, 256);*/
+        for (r = 0; r < 16; r++)
+        {
+            vpx_memset(ypred_ptr, expected_dc, 16);
+            ypred_ptr += y_stride;
+        }
+    }
+    break;
+    case V_PRED:
+    {
+
+        for (r = 0; r < 16; r++)
+        {
+
+            ((int *)ypred_ptr)[0] = ((int *)yabove_row)[0];
+            ((int *)ypred_ptr)[1] = ((int *)yabove_row)[1];
+            ((int *)ypred_ptr)[2] = ((int *)yabove_row)[2];
+            ((int *)ypred_ptr)[3] = ((int *)yabove_row)[3];
+            ypred_ptr += y_stride;
+        }
+    }
+    break;
+    case H_PRED:
+    {
+
+        for (r = 0; r < 16; r++)
+        {
+
+            vpx_memset(ypred_ptr, yleft_col[r], 16);
+            ypred_ptr += y_stride;
+        }
+
+    }
+    break;
+    case TM_PRED:
+    {
+
+        for (r = 0; r < 16; r++)
+        {
+            for (c = 0; c < 16; c++)
+            {
+                int pred =  yleft_col[r] + yabove_row[ c] - ytop_left;
+
+                if (pred < 0)
+                    pred = 0;
+
+                if (pred > 255)
+                    pred = 255;
+
+                ypred_ptr[c] = pred;
+            }
+
+            ypred_ptr += y_stride;
+        }
+
+    }
+    break;
+    case B_PRED:
+    case NEARESTMV:
+    case NEARMV:
+    case ZEROMV:
+    case NEWMV:
+    case SPLITMV:
+    case MB_MODE_COUNT:
+        break;
+    }
+}
+
+void vp8_build_intra_predictors_mbuv_s_c(MACROBLOCKD *x,
+                                         unsigned char * uabove_row,
+                                         unsigned char * vabove_row,
+                                         unsigned char * uleft,
+                                         unsigned char * vleft,
+                                         int left_stride,
+                                         unsigned char * upred_ptr,
+                                         unsigned char * vpred_ptr,
+                                         int pred_stride)
+{
+    unsigned char uleft_col[8];
+    unsigned char utop_left = uabove_row[-1];
+    unsigned char vleft_col[8];
+    unsigned char vtop_left = vabove_row[-1];
+
+    int i, j;
+
+    for (i = 0; i < 8; i++)
+    {
+        uleft_col[i] = uleft [i* left_stride];
+        vleft_col[i] = vleft [i* left_stride];
+    }
+
+    switch (x->mode_info_context->mbmi.uv_mode)
+    {
+    case DC_PRED:
+    {
+        int expected_udc;
+        int expected_vdc;
+        int i;
+        int shift;
+        int Uaverage = 0;
+        int Vaverage = 0;
+
+        if (x->up_available)
+        {
+            for (i = 0; i < 8; i++)
+            {
+                Uaverage += uabove_row[i];
+                Vaverage += vabove_row[i];
+            }
+        }
+
+        if (x->left_available)
+        {
+            for (i = 0; i < 8; i++)
+            {
+                Uaverage += uleft_col[i];
+                Vaverage += vleft_col[i];
+            }
+        }
+
+        if (!x->up_available && !x->left_available)
+        {
+            expected_udc = 128;
+            expected_vdc = 128;
+        }
+        else
+        {
+            shift = 2 + x->up_available + x->left_available;
+            expected_udc = (Uaverage + (1 << (shift - 1))) >> shift;
+            expected_vdc = (Vaverage + (1 << (shift - 1))) >> shift;
+        }
+
+
+        /*vpx_memset(upred_ptr,expected_udc,64);*/
+        /*vpx_memset(vpred_ptr,expected_vdc,64);*/
+        for (i = 0; i < 8; i++)
+        {
+            vpx_memset(upred_ptr, expected_udc, 8);
+            vpx_memset(vpred_ptr, expected_vdc, 8);
+            upred_ptr += pred_stride;
+            vpred_ptr += pred_stride;
+        }
+    }
+    break;
+    case V_PRED:
+    {
+        int i;
+
+        for (i = 0; i < 8; i++)
+        {
+            vpx_memcpy(upred_ptr, uabove_row, 8);
+            vpx_memcpy(vpred_ptr, vabove_row, 8);
+            upred_ptr += pred_stride;
+            vpred_ptr += pred_stride;
+        }
+
+    }
+    break;
+    case H_PRED:
+    {
+        int i;
+
+        for (i = 0; i < 8; i++)
+        {
+            vpx_memset(upred_ptr, uleft_col[i], 8);
+            vpx_memset(vpred_ptr, vleft_col[i], 8);
+            upred_ptr += pred_stride;
+            vpred_ptr += pred_stride;
+        }
+    }
+
+    break;
+    case TM_PRED:
+    {
+        int i;
+
+        for (i = 0; i < 8; i++)
+        {
+            for (j = 0; j < 8; j++)
+            {
+                int predu = uleft_col[i] + uabove_row[j] - utop_left;
+                int predv = vleft_col[i] + vabove_row[j] - vtop_left;
+
+                if (predu < 0)
+                    predu = 0;
+
+                if (predu > 255)
+                    predu = 255;
+
+                if (predv < 0)
+                    predv = 0;
+
+                if (predv > 255)
+                    predv = 255;
+
+                upred_ptr[j] = predu;
+                vpred_ptr[j] = predv;
+            }
+
+            upred_ptr += pred_stride;
+            vpred_ptr += pred_stride;
+        }
+
+    }
+    break;
+    case B_PRED:
+    case NEARESTMV:
+    case NEARMV:
+    case ZEROMV:
+    case NEWMV:
+    case SPLITMV:
+    case MB_MODE_COUNT:
+        break;
+    }
+}
diff --git a/vp8/common/reconintra4x4.c b/vp8/common/reconintra4x4.c
new file mode 100644 (file)
index 0000000..dcc35ec
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "blockd.h"
+
+void vp8_intra4x4_predict_d_c(unsigned char *Above,
+                              unsigned char *yleft, int left_stride,
+                              int b_mode,
+                              unsigned char *dst, int dst_stride,
+                              unsigned char top_left)
+{
+    int i, r, c;
+
+    unsigned char Left[4];
+    Left[0] = yleft[0];
+    Left[1] = yleft[left_stride];
+    Left[2] = yleft[2 * left_stride];
+    Left[3] = yleft[3 * left_stride];
+
+    switch (b_mode)
+    {
+    case B_DC_PRED:
+    {
+        int expected_dc = 0;
+
+        for (i = 0; i < 4; i++)
+        {
+            expected_dc += Above[i];
+            expected_dc += Left[i];
+        }
+
+        expected_dc = (expected_dc + 4) >> 3;
+
+        for (r = 0; r < 4; r++)
+        {
+            for (c = 0; c < 4; c++)
+            {
+                dst[c] = expected_dc;
+            }
+
+            dst += dst_stride;
+        }
+    }
+    break;
+    case B_TM_PRED:
+    {
+        /* prediction similar to true_motion prediction */
+        for (r = 0; r < 4; r++)
+        {
+            for (c = 0; c < 4; c++)
+            {
+                int pred = Above[c] - top_left + Left[r];
+
+                if (pred < 0)
+                    pred = 0;
+
+                if (pred > 255)
+                    pred = 255;
+
+                dst[c] = pred;
+            }
+
+            dst += dst_stride;
+        }
+    }
+    break;
+
+    case B_VE_PRED:
+    {
+
+        unsigned int ap[4];
+        ap[0] = (top_left  + 2 * Above[0] + Above[1] + 2) >> 2;
+        ap[1] = (Above[0] + 2 * Above[1] + Above[2] + 2) >> 2;
+        ap[2] = (Above[1] + 2 * Above[2] + Above[3] + 2) >> 2;
+        ap[3] = (Above[2] + 2 * Above[3] + Above[4] + 2) >> 2;
+
+        for (r = 0; r < 4; r++)
+        {
+            for (c = 0; c < 4; c++)
+            {
+
+                dst[c] = ap[c];
+            }
+
+            dst += dst_stride;
+        }
+
+    }
+    break;
+
+
+    case B_HE_PRED:
+    {
+
+        unsigned int lp[4];
+        lp[0] = (top_left + 2 * Left[0] + Left[1] + 2) >> 2;
+        lp[1] = (Left[0] + 2 * Left[1] + Left[2] + 2) >> 2;
+        lp[2] = (Left[1] + 2 * Left[2] + Left[3] + 2) >> 2;
+        lp[3] = (Left[2] + 2 * Left[3] + Left[3] + 2) >> 2;
+
+        for (r = 0; r < 4; r++)
+        {
+            for (c = 0; c < 4; c++)
+            {
+                dst[c] = lp[r];
+            }
+
+            dst += dst_stride;
+        }
+    }
+    break;
+    case B_LD_PRED:
+    {
+        unsigned char *ptr = Above;
+        dst[0 * dst_stride + 0] = (ptr[0] + ptr[1] * 2 + ptr[2] + 2) >> 2;
+        dst[0 * dst_stride + 1] =
+            dst[1 * dst_stride + 0] = (ptr[1] + ptr[2] * 2 + ptr[3] + 2) >> 2;
+        dst[0 * dst_stride + 2] =
+            dst[1 * dst_stride + 1] =
+                dst[2 * dst_stride + 0] = (ptr[2] + ptr[3] * 2 + ptr[4] + 2) >> 2;
+        dst[0 * dst_stride + 3] =
+            dst[1 * dst_stride + 2] =
+                dst[2 * dst_stride + 1] =
+                    dst[3 * dst_stride + 0] = (ptr[3] + ptr[4] * 2 + ptr[5] + 2) >> 2;
+        dst[1 * dst_stride + 3] =
+            dst[2 * dst_stride + 2] =
+                dst[3 * dst_stride + 1] = (ptr[4] + ptr[5] * 2 + ptr[6] + 2) >> 2;
+        dst[2 * dst_stride + 3] =
+            dst[3 * dst_stride + 2] = (ptr[5] + ptr[6] * 2 + ptr[7] + 2) >> 2;
+        dst[3 * dst_stride + 3] = (ptr[6] + ptr[7] * 2 + ptr[7] + 2) >> 2;
+
+    }
+    break;
+    case B_RD_PRED:
+    {
+
+        unsigned char pp[9];
+
+        pp[0] = Left[3];
+        pp[1] = Left[2];
+        pp[2] = Left[1];
+        pp[3] = Left[0];
+        pp[4] = top_left;
+        pp[5] = Above[0];
+        pp[6] = Above[1];
+        pp[7] = Above[2];
+        pp[8] = Above[3];
+
+        dst[3 * dst_stride + 0] = (pp[0] + pp[1] * 2 + pp[2] + 2) >> 2;
+        dst[3 * dst_stride + 1] =
+            dst[2 * dst_stride + 0] = (pp[1] + pp[2] * 2 + pp[3] + 2) >> 2;
+        dst[3 * dst_stride + 2] =
+            dst[2 * dst_stride + 1] =
+                dst[1 * dst_stride + 0] = (pp[2] + pp[3] * 2 + pp[4] + 2) >> 2;
+        dst[3 * dst_stride + 3] =
+            dst[2 * dst_stride + 2] =
+                dst[1 * dst_stride + 1] =
+                    dst[0 * dst_stride + 0] = (pp[3] + pp[4] * 2 + pp[5] + 2) >> 2;
+        dst[2 * dst_stride + 3] =
+            dst[1 * dst_stride + 2] =
+                dst[0 * dst_stride + 1] = (pp[4] + pp[5] * 2 + pp[6] + 2) >> 2;
+        dst[1 * dst_stride + 3] =
+            dst[0 * dst_stride + 2] = (pp[5] + pp[6] * 2 + pp[7] + 2) >> 2;
+        dst[0 * dst_stride + 3] = (pp[6] + pp[7] * 2 + pp[8] + 2) >> 2;
+
+    }
+    break;
+    case B_VR_PRED:
+    {
+
+        unsigned char pp[9];
+
+        pp[0] = Left[3];
+        pp[1] = Left[2];
+        pp[2] = Left[1];
+        pp[3] = Left[0];
+        pp[4] = top_left;
+        pp[5] = Above[0];
+        pp[6] = Above[1];
+        pp[7] = Above[2];
+        pp[8] = Above[3];
+
+
+        dst[3 * dst_stride + 0] = (pp[1] + pp[2] * 2 + pp[3] + 2) >> 2;
+        dst[2 * dst_stride + 0] = (pp[2] + pp[3] * 2 + pp[4] + 2) >> 2;
+        dst[3 * dst_stride + 1] =
+            dst[1 * dst_stride + 0] = (pp[3] + pp[4] * 2 + pp[5] + 2) >> 2;
+        dst[2 * dst_stride + 1] =
+            dst[0 * dst_stride + 0] = (pp[4] + pp[5] + 1) >> 1;
+        dst[3 * dst_stride + 2] =
+            dst[1 * dst_stride + 1] = (pp[4] + pp[5] * 2 + pp[6] + 2) >> 2;
+        dst[2 * dst_stride + 2] =
+            dst[0 * dst_stride + 1] = (pp[5] + pp[6] + 1) >> 1;
+        dst[3 * dst_stride + 3] =
+            dst[1 * dst_stride + 2] = (pp[5] + pp[6] * 2 + pp[7] + 2) >> 2;
+        dst[2 * dst_stride + 3] =
+            dst[0 * dst_stride + 2] = (pp[6] + pp[7] + 1) >> 1;
+        dst[1 * dst_stride + 3] = (pp[6] + pp[7] * 2 + pp[8] + 2) >> 2;
+        dst[0 * dst_stride + 3] = (pp[7] + pp[8] + 1) >> 1;
+
+    }
+    break;
+    case B_VL_PRED:
+    {
+
+        unsigned char *pp = Above;
+
+        dst[0 * dst_stride + 0] = (pp[0] + pp[1] + 1) >> 1;
+        dst[1 * dst_stride + 0] = (pp[0] + pp[1] * 2 + pp[2] + 2) >> 2;
+        dst[2 * dst_stride + 0] =
+            dst[0 * dst_stride + 1] = (pp[1] + pp[2] + 1) >> 1;
+        dst[1 * dst_stride + 1] =
+            dst[3 * dst_stride + 0] = (pp[1] + pp[2] * 2 + pp[3] + 2) >> 2;
+        dst[2 * dst_stride + 1] =
+            dst[0 * dst_stride + 2] = (pp[2] + pp[3] + 1) >> 1;
+        dst[3 * dst_stride + 1] =
+            dst[1 * dst_stride + 2] = (pp[2] + pp[3] * 2 + pp[4] + 2) >> 2;
+        dst[0 * dst_stride + 3] =
+            dst[2 * dst_stride + 2] = (pp[3] + pp[4] + 1) >> 1;
+        dst[1 * dst_stride + 3] =
+            dst[3 * dst_stride + 2] = (pp[3] + pp[4] * 2 + pp[5] + 2) >> 2;
+        dst[2 * dst_stride + 3] = (pp[4] + pp[5] * 2 + pp[6] + 2) >> 2;
+        dst[3 * dst_stride + 3] = (pp[5] + pp[6] * 2 + pp[7] + 2) >> 2;
+    }
+    break;
+
+    case B_HD_PRED:
+    {
+        unsigned char pp[9];
+        pp[0] = Left[3];
+        pp[1] = Left[2];
+        pp[2] = Left[1];
+        pp[3] = Left[0];
+        pp[4] = top_left;
+        pp[5] = Above[0];
+        pp[6] = Above[1];
+        pp[7] = Above[2];
+        pp[8] = Above[3];
+
+
+        dst[3 * dst_stride + 0] = (pp[0] + pp[1] + 1) >> 1;
+        dst[3 * dst_stride + 1] = (pp[0] + pp[1] * 2 + pp[2] + 2) >> 2;
+        dst[2 * dst_stride + 0] =
+            dst[3 * dst_stride + 2] = (pp[1] + pp[2] + 1) >> 1;
+        dst[2 * dst_stride + 1] =
+            dst[3 * dst_stride + 3] = (pp[1] + pp[2] * 2 + pp[3] + 2) >> 2;
+        dst[2 * dst_stride + 2] =
+            dst[1 * dst_stride + 0] = (pp[2] + pp[3] + 1) >> 1;
+        dst[2 * dst_stride + 3] =
+            dst[1 * dst_stride + 1] = (pp[2] + pp[3] * 2 + pp[4] + 2) >> 2;
+        dst[1 * dst_stride + 2] =
+            dst[0 * dst_stride + 0] = (pp[3] + pp[4] + 1) >> 1;
+        dst[1 * dst_stride + 3] =
+            dst[0 * dst_stride + 1] = (pp[3] + pp[4] * 2 + pp[5] + 2) >> 2;
+        dst[0 * dst_stride + 2] = (pp[4] + pp[5] * 2 + pp[6] + 2) >> 2;
+        dst[0 * dst_stride + 3] = (pp[5] + pp[6] * 2 + pp[7] + 2) >> 2;
+    }
+    break;
+
+
+    case B_HU_PRED:
+    {
+        unsigned char *pp = Left;
+        dst[0 * dst_stride + 0] = (pp[0] + pp[1] + 1) >> 1;
+        dst[0 * dst_stride + 1] = (pp[0] + pp[1] * 2 + pp[2] + 2) >> 2;
+        dst[0 * dst_stride + 2] =
+            dst[1 * dst_stride + 0] = (pp[1] + pp[2] + 1) >> 1;
+        dst[0 * dst_stride + 3] =
+            dst[1 * dst_stride + 1] = (pp[1] + pp[2] * 2 + pp[3] + 2) >> 2;
+        dst[1 * dst_stride + 2] =
+            dst[2 * dst_stride + 0] = (pp[2] + pp[3] + 1) >> 1;
+        dst[1 * dst_stride + 3] =
+            dst[2 * dst_stride + 1] = (pp[2] + pp[3] * 2 + pp[3] + 2) >> 2;
+        dst[2 * dst_stride + 2] =
+            dst[2 * dst_stride + 3] =
+                dst[3 * dst_stride + 0] =
+                    dst[3 * dst_stride + 1] =
+                        dst[3 * dst_stride + 2] =
+                            dst[3 * dst_stride + 3] = pp[3];
+    }
+    break;
+
+
+    }
+}
+
+void vp8_intra4x4_predict_c(unsigned char *src, int src_stride,
+                            int b_mode,
+                            unsigned char *dst, int dst_stride)
+{
+    unsigned char *Above = src - src_stride;
+
+    vp8_intra4x4_predict_d_c(Above,
+                             src - 1, src_stride,
+                             b_mode,
+                             dst, dst_stride,
+                             Above[-1]);
+}
diff --git a/vp8/common/reconintra4x4.h b/vp8/common/reconintra4x4.h
new file mode 100644 (file)
index 0000000..d2b0d43
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_RECONINTRA4x4_H
+#define __INC_RECONINTRA4x4_H
+#include "vp8/common/blockd.h"
+
+static void intra_prediction_down_copy(MACROBLOCKD *xd,
+                                             unsigned char *above_right_src)
+{
+    int dst_stride = xd->dst.y_stride;
+    unsigned char *above_right_dst = xd->dst.y_buffer - dst_stride + 16;
+
+    unsigned int *src_ptr = (unsigned int *)above_right_src;
+    unsigned int *dst_ptr0 = (unsigned int *)(above_right_dst + 4 * dst_stride);
+    unsigned int *dst_ptr1 = (unsigned int *)(above_right_dst + 8 * dst_stride);
+    unsigned int *dst_ptr2 = (unsigned int *)(above_right_dst + 12 * dst_stride);
+
+    *dst_ptr0 = *src_ptr;
+    *dst_ptr1 = *src_ptr;
+    *dst_ptr2 = *src_ptr;
+}
+
+#endif
diff --git a/vp8/common/rtcd.c b/vp8/common/rtcd.c
new file mode 100644 (file)
index 0000000..232640d
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#include "vpx_config.h"
+#define RTCD_C
+#include "vpx_rtcd.h"
diff --git a/vp8/common/rtcd_defs.sh b/vp8/common/rtcd_defs.sh
new file mode 100644 (file)
index 0000000..33bf08b
--- /dev/null
@@ -0,0 +1,541 @@
+common_forward_decls() {
+cat <<EOF
+struct blockd;
+struct macroblockd;
+struct loop_filter_info;
+
+/* Encoder forward decls */
+struct block;
+struct macroblock;
+struct variance_vtable;
+union int_mv;
+struct yv12_buffer_config;
+EOF
+}
+forward_decls common_forward_decls
+
+#
+# Dequant
+#
+prototype void vp8_dequantize_b "struct blockd*, short *dqc"
+specialize vp8_dequantize_b mmx media neon
+vp8_dequantize_b_media=vp8_dequantize_b_v6
+
+prototype void vp8_dequant_idct_add "short *input, short *dq, unsigned char *output, int stride"
+specialize vp8_dequant_idct_add mmx media neon
+vp8_dequant_idct_add_media=vp8_dequant_idct_add_v6
+
+prototype void vp8_dequant_idct_add_y_block "short *q, short *dq, unsigned char *dst, int stride, char *eobs"
+specialize vp8_dequant_idct_add_y_block mmx sse2 media neon
+vp8_dequant_idct_add_y_block_media=vp8_dequant_idct_add_y_block_v6
+
+prototype void vp8_dequant_idct_add_uv_block "short *q, short *dq, unsigned char *dst_u, unsigned char *dst_v, int stride, char *eobs"
+specialize vp8_dequant_idct_add_uv_block mmx sse2 media neon
+vp8_dequant_idct_add_uv_block_media=vp8_dequant_idct_add_uv_block_v6
+
+#
+# Loopfilter
+#
+prototype void vp8_loop_filter_mbv "unsigned char *y, unsigned char *u, unsigned char *v, int ystride, int uv_stride, struct loop_filter_info *lfi"
+specialize vp8_loop_filter_mbv mmx sse2 media neon
+vp8_loop_filter_mbv_media=vp8_loop_filter_mbv_armv6
+
+prototype void vp8_loop_filter_bv "unsigned char *y, unsigned char *u, unsigned char *v, int ystride, int uv_stride, struct loop_filter_info *lfi"
+specialize vp8_loop_filter_bv mmx sse2 media neon
+vp8_loop_filter_bv_media=vp8_loop_filter_bv_armv6
+
+prototype void vp8_loop_filter_mbh "unsigned char *y, unsigned char *u, unsigned char *v, int ystride, int uv_stride, struct loop_filter_info *lfi"
+specialize vp8_loop_filter_mbh mmx sse2 media neon
+vp8_loop_filter_mbh_media=vp8_loop_filter_mbh_armv6
+
+prototype void vp8_loop_filter_bh "unsigned char *y, unsigned char *u, unsigned char *v, int ystride, int uv_stride, struct loop_filter_info *lfi"
+specialize vp8_loop_filter_bh mmx sse2 media neon
+vp8_loop_filter_bh_media=vp8_loop_filter_bh_armv6
+
+
+prototype void vp8_loop_filter_simple_mbv "unsigned char *y, int ystride, const unsigned char *blimit"
+specialize vp8_loop_filter_simple_mbv mmx sse2 media neon
+vp8_loop_filter_simple_mbv_c=vp8_loop_filter_simple_vertical_edge_c
+vp8_loop_filter_simple_mbv_mmx=vp8_loop_filter_simple_vertical_edge_mmx
+vp8_loop_filter_simple_mbv_sse2=vp8_loop_filter_simple_vertical_edge_sse2
+vp8_loop_filter_simple_mbv_media=vp8_loop_filter_simple_vertical_edge_armv6
+vp8_loop_filter_simple_mbv_neon=vp8_loop_filter_mbvs_neon
+
+prototype void vp8_loop_filter_simple_mbh "unsigned char *y, int ystride, const unsigned char *blimit"
+specialize vp8_loop_filter_simple_mbh mmx sse2 media neon
+vp8_loop_filter_simple_mbh_c=vp8_loop_filter_simple_horizontal_edge_c
+vp8_loop_filter_simple_mbh_mmx=vp8_loop_filter_simple_horizontal_edge_mmx
+vp8_loop_filter_simple_mbh_sse2=vp8_loop_filter_simple_horizontal_edge_sse2
+vp8_loop_filter_simple_mbh_media=vp8_loop_filter_simple_horizontal_edge_armv6
+vp8_loop_filter_simple_mbh_neon=vp8_loop_filter_mbhs_neon
+
+prototype void vp8_loop_filter_simple_bv "unsigned char *y, int ystride, const unsigned char *blimit"
+specialize vp8_loop_filter_simple_bv mmx sse2 media neon
+vp8_loop_filter_simple_bv_c=vp8_loop_filter_bvs_c
+vp8_loop_filter_simple_bv_mmx=vp8_loop_filter_bvs_mmx
+vp8_loop_filter_simple_bv_sse2=vp8_loop_filter_bvs_sse2
+vp8_loop_filter_simple_bv_media=vp8_loop_filter_bvs_armv6
+vp8_loop_filter_simple_bv_neon=vp8_loop_filter_bvs_neon
+
+prototype void vp8_loop_filter_simple_bh "unsigned char *y, int ystride, const unsigned char *blimit"
+specialize vp8_loop_filter_simple_bh mmx sse2 media neon
+vp8_loop_filter_simple_bh_c=vp8_loop_filter_bhs_c
+vp8_loop_filter_simple_bh_mmx=vp8_loop_filter_bhs_mmx
+vp8_loop_filter_simple_bh_sse2=vp8_loop_filter_bhs_sse2
+vp8_loop_filter_simple_bh_media=vp8_loop_filter_bhs_armv6
+vp8_loop_filter_simple_bh_neon=vp8_loop_filter_bhs_neon
+
+#
+# IDCT
+#
+#idct16
+prototype void vp8_short_idct4x4llm "short *input, unsigned char *pred, int pitch, unsigned char *dst, int dst_stride"
+specialize vp8_short_idct4x4llm mmx media neon
+vp8_short_idct4x4llm_media=vp8_short_idct4x4llm_v6_dual
+
+#iwalsh1
+prototype void vp8_short_inv_walsh4x4_1 "short *input, short *output"
+# no asm yet
+
+#iwalsh16
+prototype void vp8_short_inv_walsh4x4 "short *input, short *output"
+specialize vp8_short_inv_walsh4x4 mmx sse2 media neon
+vp8_short_inv_walsh4x4_media=vp8_short_inv_walsh4x4_v6
+
+#idct1_scalar_add
+prototype void vp8_dc_only_idct_add "short input, unsigned char *pred, int pred_stride, unsigned char *dst, int dst_stride"
+specialize vp8_dc_only_idct_add        mmx media neon
+vp8_dc_only_idct_add_media=vp8_dc_only_idct_add_v6
+
+#
+# RECON
+#
+prototype void vp8_copy_mem16x16 "unsigned char *src, int src_pitch, unsigned char *dst, int dst_pitch"
+specialize vp8_copy_mem16x16 mmx sse2 media neon
+vp8_copy_mem16x16_media=vp8_copy_mem16x16_v6
+
+prototype void vp8_copy_mem8x8 "unsigned char *src, int src_pitch, unsigned char *dst, int dst_pitch"
+specialize vp8_copy_mem8x8 mmx media neon
+vp8_copy_mem8x8_media=vp8_copy_mem8x8_v6
+
+prototype void vp8_copy_mem8x4 "unsigned char *src, int src_pitch, unsigned char *dst, int dst_pitch"
+specialize vp8_copy_mem8x4 mmx media neon
+vp8_copy_mem8x4_media=vp8_copy_mem8x4_v6
+
+prototype void vp8_build_intra_predictors_mby_s "struct macroblockd *x, unsigned char * yabove_row, unsigned char * yleft, int left_stride, unsigned char * ypred_ptr, int y_stride"
+specialize vp8_build_intra_predictors_mby_s sse2 ssse3
+#TODO: fix assembly for neon
+
+prototype void vp8_build_intra_predictors_mbuv_s "struct macroblockd *x, unsigned char * uabove_row, unsigned char * vabove_row,  unsigned char *uleft, unsigned char *vleft, int left_stride, unsigned char * upred_ptr, unsigned char * vpred_ptr, int pred_stride"
+specialize vp8_build_intra_predictors_mbuv_s sse2 ssse3
+
+prototype void vp8_intra4x4_predict_d "unsigned char *above, unsigned char *left, int left_stride, int b_mode, unsigned char *dst, int dst_stride, unsigned char top_left"
+prototype void vp8_intra4x4_predict "unsigned char *src, int src_stride, int b_mode, unsigned char *dst, int dst_stride"
+specialize vp8_intra4x4_predict media
+vp8_intra4x4_predict_media=vp8_intra4x4_predict_armv6
+
+#
+# Postproc
+#
+if [ "$CONFIG_POSTPROC" = "yes" ]; then
+    prototype void vp8_mbpost_proc_down "unsigned char *dst, int pitch, int rows, int cols,int flimit"
+    specialize vp8_mbpost_proc_down mmx sse2
+    vp8_mbpost_proc_down_sse2=vp8_mbpost_proc_down_xmm
+
+    prototype void vp8_mbpost_proc_across_ip "unsigned char *dst, int pitch, int rows, int cols,int flimit"
+    specialize vp8_mbpost_proc_across_ip sse2
+    vp8_mbpost_proc_across_ip_sse2=vp8_mbpost_proc_across_ip_xmm
+
+    prototype void vp8_post_proc_down_and_across "unsigned char *src, unsigned char *dst, int src_pitch, int dst_pitch, int rows, int cols, int flimit"
+    specialize vp8_post_proc_down_and_across mmx sse2
+    vp8_post_proc_down_and_across_sse2=vp8_post_proc_down_and_across_xmm
+
+    prototype void vp8_plane_add_noise "unsigned char *s, char *noise, char blackclamp[16], char whiteclamp[16], char bothclamp[16], unsigned int w, unsigned int h, int pitch"
+    specialize vp8_plane_add_noise mmx sse2
+    vp8_plane_add_noise_sse2=vp8_plane_add_noise_wmt
+
+    prototype void vp8_blend_mb_inner "unsigned char *y, unsigned char *u, unsigned char *v, int y1, int u1, int v1, int alpha, int stride"
+    # no asm yet
+
+    prototype void vp8_blend_mb_outer "unsigned char *y, unsigned char *u, unsigned char *v, int y1, int u1, int v1, int alpha, int stride"
+    # no asm yet
+
+    prototype void vp8_blend_b "unsigned char *y, unsigned char *u, unsigned char *v, int y1, int u1, int v1, int alpha, int stride"
+    # no asm yet
+
+    prototype void vp8_filter_by_weight16x16 "unsigned char *src, int src_stride, unsigned char *dst, int dst_stride, int src_weight"
+    specialize vp8_filter_by_weight16x16 sse2
+
+    prototype void vp8_filter_by_weight8x8 "unsigned char *src, int src_stride, unsigned char *dst, int dst_stride, int src_weight"
+    specialize vp8_filter_by_weight8x8 sse2
+
+    prototype void vp8_filter_by_weight4x4 "unsigned char *src, int src_stride, unsigned char *dst, int dst_stride, int src_weight"
+    # no asm yet
+fi
+
+#
+# Subpixel
+#
+prototype void vp8_sixtap_predict16x16 "unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch"
+specialize vp8_sixtap_predict16x16 mmx sse2 ssse3 media neon
+vp8_sixtap_predict16x16_media=vp8_sixtap_predict16x16_armv6
+
+prototype void vp8_sixtap_predict8x8 "unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch"
+specialize vp8_sixtap_predict8x8 mmx sse2 ssse3 media neon
+vp8_sixtap_predict8x8_media=vp8_sixtap_predict8x8_armv6
+
+prototype void vp8_sixtap_predict8x4 "unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch"
+specialize vp8_sixtap_predict8x4 mmx sse2 ssse3 media neon
+vp8_sixtap_predict8x4_media=vp8_sixtap_predict8x4_armv6
+
+prototype void vp8_sixtap_predict4x4 "unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch"
+specialize vp8_sixtap_predict4x4 mmx ssse3 media neon
+vp8_sixtap_predict4x4_media=vp8_sixtap_predict4x4_armv6
+
+prototype void vp8_bilinear_predict16x16 "unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch"
+specialize vp8_bilinear_predict16x16 mmx sse2 ssse3 media neon
+vp8_bilinear_predict16x16_media=vp8_bilinear_predict16x16_armv6
+
+prototype void vp8_bilinear_predict8x8 "unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch"
+specialize vp8_bilinear_predict8x8 mmx sse2 ssse3 media neon
+vp8_bilinear_predict8x8_media=vp8_bilinear_predict8x8_armv6
+
+prototype void vp8_bilinear_predict8x4 "unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch"
+specialize vp8_bilinear_predict8x4 mmx media neon
+vp8_bilinear_predict8x4_media=vp8_bilinear_predict8x4_armv6
+
+prototype void vp8_bilinear_predict4x4 "unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch"
+specialize vp8_bilinear_predict4x4 mmx media neon
+vp8_bilinear_predict4x4_media=vp8_bilinear_predict4x4_armv6
+
+#
+# Whole-pixel Variance
+#
+prototype unsigned int vp8_variance4x4 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride, unsigned int *sse"
+specialize vp8_variance4x4 mmx sse2
+vp8_variance4x4_sse2=vp8_variance4x4_wmt
+
+prototype unsigned int vp8_variance8x8 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride, unsigned int *sse"
+specialize vp8_variance8x8 mmx sse2 media neon
+vp8_variance8x8_sse2=vp8_variance8x8_wmt
+vp8_variance8x8_media=vp8_variance8x8_armv6
+
+prototype unsigned int vp8_variance8x16 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride, unsigned int *sse"
+specialize vp8_variance8x16 mmx sse2 neon
+vp8_variance8x16_sse2=vp8_variance8x16_wmt
+
+prototype unsigned int vp8_variance16x8 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride, unsigned int *sse"
+specialize vp8_variance16x8 mmx sse2 neon
+vp8_variance16x8_sse2=vp8_variance16x8_wmt
+
+prototype unsigned int vp8_variance16x16 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride, unsigned int *sse"
+specialize vp8_variance16x16 mmx sse2 media neon
+vp8_variance16x16_sse2=vp8_variance16x16_wmt
+vp8_variance16x16_media=vp8_variance16x16_armv6
+
+#
+# Sub-pixel Variance
+#
+prototype unsigned int vp8_sub_pixel_variance4x4 "const unsigned char  *src_ptr, int  source_stride, int  xoffset, int  yoffset, const unsigned char *ref_ptr, int Refstride, unsigned int *sse"
+specialize vp8_sub_pixel_variance4x4 mmx sse2
+vp8_sub_pixel_variance4x4_sse2=vp8_sub_pixel_variance4x4_wmt
+
+prototype unsigned int vp8_sub_pixel_variance8x8 "const unsigned char  *src_ptr, int  source_stride, int  xoffset, int  yoffset, const unsigned char *ref_ptr, int Refstride, unsigned int *sse"
+specialize vp8_sub_pixel_variance8x8 mmx sse2 media neon
+vp8_sub_pixel_variance8x8_sse2=vp8_sub_pixel_variance8x8_wmt
+vp8_sub_pixel_variance8x8_media=vp8_sub_pixel_variance8x8_armv6
+
+prototype unsigned int vp8_sub_pixel_variance8x16 "const unsigned char  *src_ptr, int  source_stride, int  xoffset, int  yoffset, const unsigned char *ref_ptr, int Refstride, unsigned int *sse"
+specialize vp8_sub_pixel_variance8x16 mmx sse2
+vp8_sub_pixel_variance8x16_sse2=vp8_sub_pixel_variance8x16_wmt
+
+prototype unsigned int vp8_sub_pixel_variance16x8 "const unsigned char  *src_ptr, int  source_stride, int  xoffset, int  yoffset, const unsigned char *ref_ptr, int Refstride, unsigned int *sse"
+specialize vp8_sub_pixel_variance16x8 mmx sse2 ssse3
+vp8_sub_pixel_variance16x8_sse2=vp8_sub_pixel_variance16x8_wmt
+
+prototype unsigned int vp8_sub_pixel_variance16x16 "const unsigned char  *src_ptr, int  source_stride, int  xoffset, int  yoffset, const unsigned char *ref_ptr, int Refstride, unsigned int *sse"
+specialize vp8_sub_pixel_variance16x16 mmx sse2 ssse3 media neon
+vp8_sub_pixel_variance16x16_sse2=vp8_sub_pixel_variance16x16_wmt
+vp8_sub_pixel_variance16x16_media=vp8_sub_pixel_variance16x16_armv6
+
+prototype unsigned int vp8_variance_halfpixvar16x16_h "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride, unsigned int *sse"
+specialize vp8_variance_halfpixvar16x16_h mmx sse2 media neon
+vp8_variance_halfpixvar16x16_h_sse2=vp8_variance_halfpixvar16x16_h_wmt
+vp8_variance_halfpixvar16x16_h_media=vp8_variance_halfpixvar16x16_h_armv6
+
+prototype unsigned int vp8_variance_halfpixvar16x16_v "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride, unsigned int *sse"
+specialize vp8_variance_halfpixvar16x16_v mmx sse2 media neon
+vp8_variance_halfpixvar16x16_v_sse2=vp8_variance_halfpixvar16x16_v_wmt
+vp8_variance_halfpixvar16x16_v_media=vp8_variance_halfpixvar16x16_v_armv6
+
+prototype unsigned int vp8_variance_halfpixvar16x16_hv "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride, unsigned int *sse"
+specialize vp8_variance_halfpixvar16x16_hv mmx sse2 media neon
+vp8_variance_halfpixvar16x16_hv_sse2=vp8_variance_halfpixvar16x16_hv_wmt
+vp8_variance_halfpixvar16x16_hv_media=vp8_variance_halfpixvar16x16_hv_armv6
+
+#
+# Single block SAD
+#
+prototype unsigned int vp8_sad4x4 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int ref_stride, int max_sad"
+specialize vp8_sad4x4 mmx sse2 neon
+vp8_sad4x4_sse2=vp8_sad4x4_wmt
+
+prototype unsigned int vp8_sad8x8 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int ref_stride, int max_sad"
+specialize vp8_sad8x8 mmx sse2 neon
+vp8_sad8x8_sse2=vp8_sad8x8_wmt
+
+prototype unsigned int vp8_sad8x16 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int ref_stride, int max_sad"
+specialize vp8_sad8x16 mmx sse2 neon
+vp8_sad8x16_sse2=vp8_sad8x16_wmt
+
+prototype unsigned int vp8_sad16x8 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int ref_stride, int max_sad"
+specialize vp8_sad16x8 mmx sse2 neon
+vp8_sad16x8_sse2=vp8_sad16x8_wmt
+
+prototype unsigned int vp8_sad16x16 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int ref_stride, int max_sad"
+specialize vp8_sad16x16 mmx sse2 sse3 media neon
+vp8_sad16x16_sse2=vp8_sad16x16_wmt
+vp8_sad16x16_media=vp8_sad16x16_armv6
+
+#
+# Multi-block SAD, comparing a reference to N blocks 1 pixel apart horizontally
+#
+prototype void vp8_sad4x4x3 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride, unsigned int *sad_array"
+specialize vp8_sad4x4x3 sse3
+
+prototype void vp8_sad8x8x3 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride, unsigned int *sad_array"
+specialize vp8_sad8x8x3 sse3
+
+prototype void vp8_sad8x16x3 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride, unsigned int *sad_array"
+specialize vp8_sad8x16x3 sse3
+
+prototype void vp8_sad16x8x3 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride, unsigned int *sad_array"
+specialize vp8_sad16x8x3 sse3 ssse3
+
+prototype void vp8_sad16x16x3 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride, unsigned int *sad_array"
+specialize vp8_sad16x16x3 sse3 ssse3
+
+# Note the only difference in the following prototypes is that they return into
+# an array of short
+prototype void vp8_sad4x4x8 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride, unsigned short *sad_array"
+specialize vp8_sad4x4x8 sse4_1
+vp8_sad4x4x8_sse4_1=vp8_sad4x4x8_sse4
+
+prototype void vp8_sad8x8x8 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride, unsigned short *sad_array"
+specialize vp8_sad8x8x8 sse4_1
+vp8_sad8x8x8_sse4_1=vp8_sad8x8x8_sse4
+
+prototype void vp8_sad8x16x8 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride, unsigned short *sad_array"
+specialize vp8_sad8x16x8 sse4_1
+vp8_sad8x16x8_sse4_1=vp8_sad8x16x8_sse4
+
+prototype void vp8_sad16x8x8 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride, unsigned short *sad_array"
+specialize vp8_sad16x8x8 sse4_1
+vp8_sad16x8x8_sse4_1=vp8_sad16x8x8_sse4
+
+prototype void vp8_sad16x16x8 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride, unsigned short *sad_array"
+specialize vp8_sad16x16x8 sse4_1
+vp8_sad16x16x8_sse4_1=vp8_sad16x16x8_sse4
+
+#
+# Multi-block SAD, comparing a reference to N independent blocks
+#
+prototype void vp8_sad4x4x4d "const unsigned char *src_ptr, int source_stride, unsigned char *ref_ptr[4], int  ref_stride, unsigned int *sad_array"
+specialize vp8_sad4x4x4d sse3
+
+prototype void vp8_sad8x8x4d "const unsigned char *src_ptr, int source_stride, unsigned char *ref_ptr[4], int  ref_stride, unsigned int *sad_array"
+specialize vp8_sad8x8x4d sse3
+
+prototype void vp8_sad8x16x4d "const unsigned char *src_ptr, int source_stride, unsigned char *ref_ptr[4], int  ref_stride, unsigned int *sad_array"
+specialize vp8_sad8x16x4d sse3
+
+prototype void vp8_sad16x8x4d "const unsigned char *src_ptr, int source_stride, unsigned char *ref_ptr[4], int  ref_stride, unsigned int *sad_array"
+specialize vp8_sad16x8x4d sse3
+
+prototype void vp8_sad16x16x4d "const unsigned char *src_ptr, int source_stride, unsigned char *ref_ptr[4], int  ref_stride, unsigned int *sad_array"
+specialize vp8_sad16x16x4d sse3
+
+#
+# Encoder functions below this point.
+#
+if [ "$CONFIG_VP8_ENCODER" = "yes" ]; then
+
+#
+# Sum of squares (vector)
+#
+prototype unsigned int vp8_get_mb_ss "const short *"
+specialize vp8_get_mb_ss mmx sse2
+
+#
+# SSE (Sum Squared Error)
+#
+prototype unsigned int vp8_sub_pixel_mse16x16 "const unsigned char  *src_ptr, int  source_stride, int  xoffset, int  yoffset, const unsigned char *ref_ptr, int Refstride, unsigned int *sse"
+specialize vp8_sub_pixel_mse16x16 mmx sse2
+vp8_sub_pixel_mse16x16_sse2=vp8_sub_pixel_mse16x16_wmt
+
+prototype unsigned int vp8_mse16x16 "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride, unsigned int *sse"
+specialize vp8_mse16x16 mmx sse2 media neon
+vp8_mse16x16_sse2=vp8_mse16x16_wmt
+vp8_mse16x16_media=vp8_mse16x16_armv6
+
+prototype unsigned int vp8_get4x4sse_cs "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride"
+specialize vp8_get4x4sse_cs mmx neon
+
+#
+# Block copy
+#
+case $arch in
+    x86*)
+    prototype void vp8_copy32xn "const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int ref_stride, int n"
+    specialize vp8_copy32xn sse2 sse3
+    ;;
+esac
+
+#
+# Structured Similarity (SSIM)
+#
+if [ "$CONFIG_INTERNAL_STATS" = "yes" ]; then
+    [ $arch = "x86_64" ] && sse2_on_x86_64=sse2
+
+    prototype void vp8_ssim_parms_8x8 "unsigned char *s, int sp, unsigned char *r, int rp, unsigned long *sum_s, unsigned long *sum_r, unsigned long *sum_sq_s, unsigned long *sum_sq_r, unsigned long *sum_sxr"
+    specialize vp8_ssim_parms_8x8 $sse2_on_x86_64
+
+    prototype void vp8_ssim_parms_16x16 "unsigned char *s, int sp, unsigned char *r, int rp, unsigned long *sum_s, unsigned long *sum_r, unsigned long *sum_sq_s, unsigned long *sum_sq_r, unsigned long *sum_sxr"
+    specialize vp8_ssim_parms_16x16 $sse2_on_x86_64
+fi
+
+#
+# Forward DCT
+#
+prototype void vp8_short_fdct4x4 "short *input, short *output, int pitch"
+specialize vp8_short_fdct4x4 mmx sse2 media neon
+vp8_short_fdct4x4_media=vp8_short_fdct4x4_armv6
+
+prototype void vp8_short_fdct8x4 "short *input, short *output, int pitch"
+specialize vp8_short_fdct8x4 mmx sse2 media neon
+vp8_short_fdct8x4_media=vp8_short_fdct8x4_armv6
+
+prototype void vp8_short_walsh4x4 "short *input, short *output, int pitch"
+specialize vp8_short_walsh4x4 sse2 media neon
+vp8_short_walsh4x4_media=vp8_short_walsh4x4_armv6
+
+#
+# Quantizer
+#
+prototype void vp8_regular_quantize_b "struct block *, struct blockd *"
+specialize vp8_regular_quantize_b sse2 sse4_1
+vp8_regular_quantize_b_sse4_1=vp8_regular_quantize_b_sse4
+
+prototype void vp8_fast_quantize_b "struct block *, struct blockd *"
+specialize vp8_fast_quantize_b sse2 ssse3 media neon
+vp8_fast_quantize_b_media=vp8_fast_quantize_b_armv6
+
+prototype void vp8_regular_quantize_b_pair "struct block *b1, struct block *b2, struct blockd *d1, struct blockd *d2"
+# no asm yet
+
+prototype void vp8_fast_quantize_b_pair "struct block *b1, struct block *b2, struct blockd *d1, struct blockd *d2"
+specialize vp8_fast_quantize_b_pair neon
+
+prototype void vp8_quantize_mb "struct macroblock *"
+specialize vp8_quantize_mb neon
+
+prototype void vp8_quantize_mby "struct macroblock *"
+specialize vp8_quantize_mby neon
+
+prototype void vp8_quantize_mbuv "struct macroblock *"
+specialize vp8_quantize_mbuv neon
+
+#
+# Block subtraction
+#
+prototype int vp8_block_error "short *coeff, short *dqcoeff"
+specialize vp8_block_error mmx sse2
+vp8_block_error_sse2=vp8_block_error_xmm
+
+prototype int vp8_mbblock_error "struct macroblock *mb, int dc"
+specialize vp8_mbblock_error mmx sse2
+vp8_mbblock_error_sse2=vp8_mbblock_error_xmm
+
+prototype int vp8_mbuverror "struct macroblock *mb"
+specialize vp8_mbuverror mmx sse2
+vp8_mbuverror_sse2=vp8_mbuverror_xmm
+
+prototype void vp8_subtract_b "struct block *be, struct blockd *bd, int pitch"
+specialize vp8_subtract_b mmx sse2 media neon
+vp8_subtract_b_media=vp8_subtract_b_armv6
+
+prototype void vp8_subtract_mby "short *diff, unsigned char *src, int src_stride, unsigned char *pred, int pred_stride"
+specialize vp8_subtract_mby mmx sse2 media neon
+vp8_subtract_mby_media=vp8_subtract_mby_armv6
+
+prototype void vp8_subtract_mbuv "short *diff, unsigned char *usrc, unsigned char *vsrc, int src_stride, unsigned char *upred, unsigned char *vpred, int pred_stride"
+specialize vp8_subtract_mbuv mmx sse2 media neon
+vp8_subtract_mbuv_media=vp8_subtract_mbuv_armv6
+
+#
+# Motion search
+#
+prototype int vp8_full_search_sad "struct macroblock *x, struct block *b, struct blockd *d, union int_mv *ref_mv, int sad_per_bit, int distance, struct variance_vtable *fn_ptr, int *mvcost[2], union int_mv *center_mv"
+specialize vp8_full_search_sad sse3 sse4_1
+vp8_full_search_sad_sse3=vp8_full_search_sadx3
+vp8_full_search_sad_sse4_1=vp8_full_search_sadx8
+
+prototype int vp8_refining_search_sad "struct macroblock *x, struct block *b, struct blockd *d, union int_mv *ref_mv, int sad_per_bit, int distance, struct variance_vtable *fn_ptr, int *mvcost[2], union int_mv *center_mv"
+specialize vp8_refining_search_sad sse3
+vp8_refining_search_sad_sse3=vp8_refining_search_sadx4
+
+prototype int vp8_diamond_search_sad "struct macroblock *x, struct block *b, struct blockd *d, union int_mv *ref_mv, union int_mv *best_mv, int search_param, int sad_per_bit, int *num00, struct variance_vtable *fn_ptr, int *mvcost[2], union int_mv *center_mv"
+vp8_diamond_search_sad_sse3=vp8_diamond_search_sadx4
+
+#
+# Alt-ref Noise Reduction (ARNR)
+#
+if [ "$CONFIG_REALTIME_ONLY" != "yes" ]; then
+    prototype void vp8_temporal_filter_apply "unsigned char *frame1, unsigned int stride, unsigned char *frame2, unsigned int block_size, int strength, int filter_weight, unsigned int *accumulator, unsigned short *count"
+    specialize vp8_temporal_filter_apply sse2
+fi
+
+#
+# Pick Loopfilter
+#
+prototype void vp8_yv12_copy_partial_frame "struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc"
+specialize vp8_yv12_copy_partial_frame neon
+
+# End of encoder only functions
+fi
+
+# Scaler functions
+if [ "CONFIG_SPATIAL_RESAMPLING" != "yes" ]; then
+    prototype void vp8_horizontal_line_4_5_scale "const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width"
+    prototype void vp8_vertical_band_4_5_scale "unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width"
+    prototype void vp8_last_vertical_band_4_5_scale "unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width"
+    prototype void vp8_horizontal_line_2_3_scale "const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width"
+    prototype void vp8_vertical_band_2_3_scale "unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width"
+    prototype void vp8_last_vertical_band_2_3_scale "unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width"
+    prototype void vp8_horizontal_line_3_5_scale "const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width"
+    prototype void vp8_vertical_band_3_5_scale "unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width"
+    prototype void vp8_last_vertical_band_3_5_scale "unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width"
+    prototype void vp8_horizontal_line_3_4_scale "const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width"
+    prototype void vp8_vertical_band_3_4_scale "unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width"
+    prototype void vp8_last_vertical_band_3_4_scale "unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width"
+    prototype void vp8_horizontal_line_1_2_scale "const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width"
+    prototype void vp8_vertical_band_1_2_scale "unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width"
+    prototype void vp8_last_vertical_band_1_2_scale "unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width"
+    prototype void vp8_horizontal_line_5_4_scale "const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width"
+    prototype void vp8_vertical_band_5_4_scale "unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width"
+    prototype void vp8_horizontal_line_5_3_scale "const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width"
+    prototype void vp8_vertical_band_5_3_scale "unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width"
+    prototype void vp8_horizontal_line_2_1_scale "const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width"
+    prototype void vp8_vertical_band_2_1_scale "unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width"
+    prototype void vp8_vertical_band_2_1_scale_i "unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width"
+fi
+
+prototype void vp8_yv12_extend_frame_borders "struct yv12_buffer_config *ybf"
+specialize vp8_yv12_extend_frame_borders neon
+
+prototype void vp8_yv12_copy_frame "struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc"
+specialize vp8_yv12_copy_frame neon
+
+prototype void vp8_yv12_copy_y "struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc"
+specialize vp8_yv12_copy_y neon
+
diff --git a/vp8/common/sad_c.c b/vp8/common/sad_c.c
new file mode 100644 (file)
index 0000000..6a3e889
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include <stdlib.h>
+#include "vpx_config.h"
+#include "vpx/vpx_integer.h"
+
+static
+unsigned int sad_mx_n_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    const unsigned char *ref_ptr,
+    int  ref_stride,
+    int  max_sad,
+    int  m,
+    int  n)
+{
+
+    int r, c;
+    unsigned int sad = 0;
+
+    for (r = 0; r < n; r++)
+    {
+        for (c = 0; c < m; c++)
+        {
+            sad += abs(src_ptr[c] - ref_ptr[c]);
+        }
+
+        if (sad > max_sad)
+          break;
+
+        src_ptr += src_stride;
+        ref_ptr += ref_stride;
+    }
+
+    return sad;
+}
+
+/* max_sad is provided as an optional optimization point. Alternative
+ * implementations of these functions are not required to check it.
+ */
+
+unsigned int vp8_sad16x16_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    const unsigned char *ref_ptr,
+    int  ref_stride,
+    int  max_sad)
+{
+
+    return sad_mx_n_c(src_ptr, src_stride, ref_ptr, ref_stride, max_sad, 16, 16);
+}
+
+
+unsigned int vp8_sad8x8_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    const unsigned char *ref_ptr,
+    int  ref_stride,
+    int  max_sad)
+{
+
+    return sad_mx_n_c(src_ptr, src_stride, ref_ptr, ref_stride, max_sad, 8, 8);
+}
+
+
+unsigned int vp8_sad16x8_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    const unsigned char *ref_ptr,
+    int  ref_stride,
+    int  max_sad)
+{
+
+    return sad_mx_n_c(src_ptr, src_stride, ref_ptr, ref_stride, max_sad, 16, 8);
+
+}
+
+
+unsigned int vp8_sad8x16_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    const unsigned char *ref_ptr,
+    int  ref_stride,
+    int  max_sad)
+{
+
+    return sad_mx_n_c(src_ptr, src_stride, ref_ptr, ref_stride, max_sad, 8, 16);
+}
+
+
+unsigned int vp8_sad4x4_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    const unsigned char *ref_ptr,
+    int  ref_stride,
+    int  max_sad)
+{
+
+    return sad_mx_n_c(src_ptr, src_stride, ref_ptr, ref_stride, max_sad, 4, 4);
+}
+
+void vp8_sad16x16x3_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    const unsigned char *ref_ptr,
+    int  ref_stride,
+    unsigned int *sad_array
+)
+{
+    sad_array[0] = vp8_sad16x16_c(src_ptr, src_stride, ref_ptr  , ref_stride, 0x7fffffff);
+    sad_array[1] = vp8_sad16x16_c(src_ptr, src_stride, ref_ptr + 1, ref_stride, 0x7fffffff);
+    sad_array[2] = vp8_sad16x16_c(src_ptr, src_stride, ref_ptr + 2, ref_stride, 0x7fffffff);
+}
+
+void vp8_sad16x16x8_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    const unsigned char *ref_ptr,
+    int  ref_stride,
+    unsigned short *sad_array
+)
+{
+    sad_array[0] = (unsigned short)vp8_sad16x16_c(src_ptr, src_stride, ref_ptr  , ref_stride, 0x7fffffff);
+    sad_array[1] = (unsigned short)vp8_sad16x16_c(src_ptr, src_stride, ref_ptr + 1, ref_stride, 0x7fffffff);
+    sad_array[2] = (unsigned short)vp8_sad16x16_c(src_ptr, src_stride, ref_ptr + 2, ref_stride, 0x7fffffff);
+    sad_array[3] = (unsigned short)vp8_sad16x16_c(src_ptr, src_stride, ref_ptr + 3 , ref_stride, 0x7fffffff);
+    sad_array[4] = (unsigned short)vp8_sad16x16_c(src_ptr, src_stride, ref_ptr + 4, ref_stride, 0x7fffffff);
+    sad_array[5] = (unsigned short)vp8_sad16x16_c(src_ptr, src_stride, ref_ptr + 5, ref_stride, 0x7fffffff);
+    sad_array[6] = (unsigned short)vp8_sad16x16_c(src_ptr, src_stride, ref_ptr + 6 , ref_stride, 0x7fffffff);
+    sad_array[7] = (unsigned short)vp8_sad16x16_c(src_ptr, src_stride, ref_ptr + 7, ref_stride, 0x7fffffff);
+}
+
+void vp8_sad16x8x3_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    const unsigned char *ref_ptr,
+    int  ref_stride,
+    unsigned int *sad_array
+)
+{
+    sad_array[0] = vp8_sad16x8_c(src_ptr, src_stride, ref_ptr  , ref_stride, 0x7fffffff);
+    sad_array[1] = vp8_sad16x8_c(src_ptr, src_stride, ref_ptr + 1, ref_stride, 0x7fffffff);
+    sad_array[2] = vp8_sad16x8_c(src_ptr, src_stride, ref_ptr + 2, ref_stride, 0x7fffffff);
+}
+
+void vp8_sad16x8x8_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    const unsigned char *ref_ptr,
+    int  ref_stride,
+    unsigned short *sad_array
+)
+{
+    sad_array[0] = (unsigned short)vp8_sad16x8_c(src_ptr, src_stride, ref_ptr  , ref_stride, 0x7fffffff);
+    sad_array[1] = (unsigned short)vp8_sad16x8_c(src_ptr, src_stride, ref_ptr + 1, ref_stride, 0x7fffffff);
+    sad_array[2] = (unsigned short)vp8_sad16x8_c(src_ptr, src_stride, ref_ptr + 2, ref_stride, 0x7fffffff);
+    sad_array[3] = (unsigned short)vp8_sad16x8_c(src_ptr, src_stride, ref_ptr + 3 , ref_stride, 0x7fffffff);
+    sad_array[4] = (unsigned short)vp8_sad16x8_c(src_ptr, src_stride, ref_ptr + 4, ref_stride, 0x7fffffff);
+    sad_array[5] = (unsigned short)vp8_sad16x8_c(src_ptr, src_stride, ref_ptr + 5, ref_stride, 0x7fffffff);
+    sad_array[6] = (unsigned short)vp8_sad16x8_c(src_ptr, src_stride, ref_ptr + 6 , ref_stride, 0x7fffffff);
+    sad_array[7] = (unsigned short)vp8_sad16x8_c(src_ptr, src_stride, ref_ptr + 7, ref_stride, 0x7fffffff);
+}
+
+void vp8_sad8x8x3_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    const unsigned char *ref_ptr,
+    int  ref_stride,
+    unsigned int *sad_array
+)
+{
+    sad_array[0] = vp8_sad8x8_c(src_ptr, src_stride, ref_ptr  , ref_stride, 0x7fffffff);
+    sad_array[1] = vp8_sad8x8_c(src_ptr, src_stride, ref_ptr + 1, ref_stride, 0x7fffffff);
+    sad_array[2] = vp8_sad8x8_c(src_ptr, src_stride, ref_ptr + 2, ref_stride, 0x7fffffff);
+}
+
+void vp8_sad8x8x8_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    const unsigned char *ref_ptr,
+    int  ref_stride,
+    unsigned short *sad_array
+)
+{
+    sad_array[0] = (unsigned short)vp8_sad8x8_c(src_ptr, src_stride, ref_ptr  , ref_stride, 0x7fffffff);
+    sad_array[1] = (unsigned short)vp8_sad8x8_c(src_ptr, src_stride, ref_ptr + 1, ref_stride, 0x7fffffff);
+    sad_array[2] = (unsigned short)vp8_sad8x8_c(src_ptr, src_stride, ref_ptr + 2, ref_stride, 0x7fffffff);
+    sad_array[3] = (unsigned short)vp8_sad8x8_c(src_ptr, src_stride, ref_ptr + 3 , ref_stride, 0x7fffffff);
+    sad_array[4] = (unsigned short)vp8_sad8x8_c(src_ptr, src_stride, ref_ptr + 4, ref_stride, 0x7fffffff);
+    sad_array[5] = (unsigned short)vp8_sad8x8_c(src_ptr, src_stride, ref_ptr + 5, ref_stride, 0x7fffffff);
+    sad_array[6] = (unsigned short)vp8_sad8x8_c(src_ptr, src_stride, ref_ptr + 6 , ref_stride, 0x7fffffff);
+    sad_array[7] = (unsigned short)vp8_sad8x8_c(src_ptr, src_stride, ref_ptr + 7, ref_stride, 0x7fffffff);
+}
+
+void vp8_sad8x16x3_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    const unsigned char *ref_ptr,
+    int  ref_stride,
+    unsigned int *sad_array
+)
+{
+    sad_array[0] = vp8_sad8x16_c(src_ptr, src_stride, ref_ptr  , ref_stride, 0x7fffffff);
+    sad_array[1] = vp8_sad8x16_c(src_ptr, src_stride, ref_ptr + 1, ref_stride, 0x7fffffff);
+    sad_array[2] = vp8_sad8x16_c(src_ptr, src_stride, ref_ptr + 2, ref_stride, 0x7fffffff);
+}
+
+void vp8_sad8x16x8_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    const unsigned char *ref_ptr,
+    int  ref_stride,
+    unsigned short *sad_array
+)
+{
+    sad_array[0] = (unsigned short)vp8_sad8x16_c(src_ptr, src_stride, ref_ptr  , ref_stride, 0x7fffffff);
+    sad_array[1] = (unsigned short)vp8_sad8x16_c(src_ptr, src_stride, ref_ptr + 1, ref_stride, 0x7fffffff);
+    sad_array[2] = (unsigned short)vp8_sad8x16_c(src_ptr, src_stride, ref_ptr + 2, ref_stride, 0x7fffffff);
+    sad_array[3] = (unsigned short)vp8_sad8x16_c(src_ptr, src_stride, ref_ptr + 3 , ref_stride, 0x7fffffff);
+    sad_array[4] = (unsigned short)vp8_sad8x16_c(src_ptr, src_stride, ref_ptr + 4, ref_stride, 0x7fffffff);
+    sad_array[5] = (unsigned short)vp8_sad8x16_c(src_ptr, src_stride, ref_ptr + 5, ref_stride, 0x7fffffff);
+    sad_array[6] = (unsigned short)vp8_sad8x16_c(src_ptr, src_stride, ref_ptr + 6 , ref_stride, 0x7fffffff);
+    sad_array[7] = (unsigned short)vp8_sad8x16_c(src_ptr, src_stride, ref_ptr + 7, ref_stride, 0x7fffffff);
+}
+
+void vp8_sad4x4x3_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    const unsigned char *ref_ptr,
+    int  ref_stride,
+    unsigned int *sad_array
+)
+{
+    sad_array[0] = vp8_sad4x4_c(src_ptr, src_stride, ref_ptr  , ref_stride, 0x7fffffff);
+    sad_array[1] = vp8_sad4x4_c(src_ptr, src_stride, ref_ptr + 1, ref_stride, 0x7fffffff);
+    sad_array[2] = vp8_sad4x4_c(src_ptr, src_stride, ref_ptr + 2, ref_stride, 0x7fffffff);
+}
+
+void vp8_sad4x4x8_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    const unsigned char *ref_ptr,
+    int  ref_stride,
+    unsigned short *sad_array
+)
+{
+    sad_array[0] = (unsigned short)vp8_sad4x4_c(src_ptr, src_stride, ref_ptr  , ref_stride, 0x7fffffff);
+    sad_array[1] = (unsigned short)vp8_sad4x4_c(src_ptr, src_stride, ref_ptr + 1, ref_stride, 0x7fffffff);
+    sad_array[2] = (unsigned short)vp8_sad4x4_c(src_ptr, src_stride, ref_ptr + 2, ref_stride, 0x7fffffff);
+    sad_array[3] = (unsigned short)vp8_sad4x4_c(src_ptr, src_stride, ref_ptr + 3 , ref_stride, 0x7fffffff);
+    sad_array[4] = (unsigned short)vp8_sad4x4_c(src_ptr, src_stride, ref_ptr + 4, ref_stride, 0x7fffffff);
+    sad_array[5] = (unsigned short)vp8_sad4x4_c(src_ptr, src_stride, ref_ptr + 5, ref_stride, 0x7fffffff);
+    sad_array[6] = (unsigned short)vp8_sad4x4_c(src_ptr, src_stride, ref_ptr + 6 , ref_stride, 0x7fffffff);
+    sad_array[7] = (unsigned short)vp8_sad4x4_c(src_ptr, src_stride, ref_ptr + 7, ref_stride, 0x7fffffff);
+}
+
+void vp8_sad16x16x4d_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr[],
+    int  ref_stride,
+    unsigned int *sad_array
+)
+{
+    sad_array[0] = vp8_sad16x16_c(src_ptr, src_stride, ref_ptr[0], ref_stride, 0x7fffffff);
+    sad_array[1] = vp8_sad16x16_c(src_ptr, src_stride, ref_ptr[1], ref_stride, 0x7fffffff);
+    sad_array[2] = vp8_sad16x16_c(src_ptr, src_stride, ref_ptr[2], ref_stride, 0x7fffffff);
+    sad_array[3] = vp8_sad16x16_c(src_ptr, src_stride, ref_ptr[3], ref_stride, 0x7fffffff);
+}
+
+void vp8_sad16x8x4d_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr[],
+    int  ref_stride,
+    unsigned int *sad_array
+)
+{
+    sad_array[0] = vp8_sad16x8_c(src_ptr, src_stride, ref_ptr[0], ref_stride, 0x7fffffff);
+    sad_array[1] = vp8_sad16x8_c(src_ptr, src_stride, ref_ptr[1], ref_stride, 0x7fffffff);
+    sad_array[2] = vp8_sad16x8_c(src_ptr, src_stride, ref_ptr[2], ref_stride, 0x7fffffff);
+    sad_array[3] = vp8_sad16x8_c(src_ptr, src_stride, ref_ptr[3], ref_stride, 0x7fffffff);
+}
+
+void vp8_sad8x8x4d_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr[],
+    int  ref_stride,
+    unsigned int *sad_array
+)
+{
+    sad_array[0] = vp8_sad8x8_c(src_ptr, src_stride, ref_ptr[0], ref_stride, 0x7fffffff);
+    sad_array[1] = vp8_sad8x8_c(src_ptr, src_stride, ref_ptr[1], ref_stride, 0x7fffffff);
+    sad_array[2] = vp8_sad8x8_c(src_ptr, src_stride, ref_ptr[2], ref_stride, 0x7fffffff);
+    sad_array[3] = vp8_sad8x8_c(src_ptr, src_stride, ref_ptr[3], ref_stride, 0x7fffffff);
+}
+
+void vp8_sad8x16x4d_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr[],
+    int  ref_stride,
+    unsigned int *sad_array
+)
+{
+    sad_array[0] = vp8_sad8x16_c(src_ptr, src_stride, ref_ptr[0], ref_stride, 0x7fffffff);
+    sad_array[1] = vp8_sad8x16_c(src_ptr, src_stride, ref_ptr[1], ref_stride, 0x7fffffff);
+    sad_array[2] = vp8_sad8x16_c(src_ptr, src_stride, ref_ptr[2], ref_stride, 0x7fffffff);
+    sad_array[3] = vp8_sad8x16_c(src_ptr, src_stride, ref_ptr[3], ref_stride, 0x7fffffff);
+}
+
+void vp8_sad4x4x4d_c(
+    const unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr[],
+    int  ref_stride,
+    unsigned int *sad_array
+)
+{
+    sad_array[0] = vp8_sad4x4_c(src_ptr, src_stride, ref_ptr[0], ref_stride, 0x7fffffff);
+    sad_array[1] = vp8_sad4x4_c(src_ptr, src_stride, ref_ptr[1], ref_stride, 0x7fffffff);
+    sad_array[2] = vp8_sad4x4_c(src_ptr, src_stride, ref_ptr[2], ref_stride, 0x7fffffff);
+    sad_array[3] = vp8_sad4x4_c(src_ptr, src_stride, ref_ptr[3], ref_stride, 0x7fffffff);
+}
+
+/* Copy 2 macroblocks to a buffer */
+void vp8_copy32xn_c(
+    unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *dst_ptr,
+    int  dst_stride,
+    int height)
+{
+    int r;
+
+    for (r = 0; r < height; r++)
+    {
+#if !(CONFIG_FAST_UNALIGNED)
+        dst_ptr[0] = src_ptr[0];
+        dst_ptr[1] = src_ptr[1];
+        dst_ptr[2] = src_ptr[2];
+        dst_ptr[3] = src_ptr[3];
+        dst_ptr[4] = src_ptr[4];
+        dst_ptr[5] = src_ptr[5];
+        dst_ptr[6] = src_ptr[6];
+        dst_ptr[7] = src_ptr[7];
+        dst_ptr[8] = src_ptr[8];
+        dst_ptr[9] = src_ptr[9];
+        dst_ptr[10] = src_ptr[10];
+        dst_ptr[11] = src_ptr[11];
+        dst_ptr[12] = src_ptr[12];
+        dst_ptr[13] = src_ptr[13];
+        dst_ptr[14] = src_ptr[14];
+        dst_ptr[15] = src_ptr[15];
+        dst_ptr[16] = src_ptr[16];
+        dst_ptr[17] = src_ptr[17];
+        dst_ptr[18] = src_ptr[18];
+        dst_ptr[19] = src_ptr[19];
+        dst_ptr[20] = src_ptr[20];
+        dst_ptr[21] = src_ptr[21];
+        dst_ptr[22] = src_ptr[22];
+        dst_ptr[23] = src_ptr[23];
+        dst_ptr[24] = src_ptr[24];
+        dst_ptr[25] = src_ptr[25];
+        dst_ptr[26] = src_ptr[26];
+        dst_ptr[27] = src_ptr[27];
+        dst_ptr[28] = src_ptr[28];
+        dst_ptr[29] = src_ptr[29];
+        dst_ptr[30] = src_ptr[30];
+        dst_ptr[31] = src_ptr[31];
+#else
+        ((uint32_t *)dst_ptr)[0] = ((uint32_t *)src_ptr)[0] ;
+        ((uint32_t *)dst_ptr)[1] = ((uint32_t *)src_ptr)[1] ;
+        ((uint32_t *)dst_ptr)[2] = ((uint32_t *)src_ptr)[2] ;
+        ((uint32_t *)dst_ptr)[3] = ((uint32_t *)src_ptr)[3] ;
+        ((uint32_t *)dst_ptr)[4] = ((uint32_t *)src_ptr)[4] ;
+        ((uint32_t *)dst_ptr)[5] = ((uint32_t *)src_ptr)[5] ;
+        ((uint32_t *)dst_ptr)[6] = ((uint32_t *)src_ptr)[6] ;
+        ((uint32_t *)dst_ptr)[7] = ((uint32_t *)src_ptr)[7] ;
+#endif
+        src_ptr += src_stride;
+        dst_ptr += dst_stride;
+
+    }
+}
diff --git a/vp8/common/setupintrarecon.c b/vp8/common/setupintrarecon.c
new file mode 100644 (file)
index 0000000..7976e25
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "setupintrarecon.h"
+#include "vpx_mem/vpx_mem.h"
+
+void vp8_setup_intra_recon(YV12_BUFFER_CONFIG *ybf)
+{
+    int i;
+
+    /* set up frame new frame for intra coded blocks */
+    vpx_memset(ybf->y_buffer - 1 - ybf->y_stride, 127, ybf->y_width + 5);
+    for (i = 0; i < ybf->y_height; i++)
+        ybf->y_buffer[ybf->y_stride *i - 1] = (unsigned char) 129;
+
+    vpx_memset(ybf->u_buffer - 1 - ybf->uv_stride, 127, ybf->uv_width + 5);
+    for (i = 0; i < ybf->uv_height; i++)
+        ybf->u_buffer[ybf->uv_stride *i - 1] = (unsigned char) 129;
+
+    vpx_memset(ybf->v_buffer - 1 - ybf->uv_stride, 127, ybf->uv_width + 5);
+    for (i = 0; i < ybf->uv_height; i++)
+        ybf->v_buffer[ybf->uv_stride *i - 1] = (unsigned char) 129;
+
+}
diff --git a/vp8/common/setupintrarecon.h b/vp8/common/setupintrarecon.h
new file mode 100644 (file)
index 0000000..5264fd0
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_scale/yv12config.h"
+extern void vp8_setup_intra_recon(YV12_BUFFER_CONFIG *ybf);
diff --git a/vp8/common/swapyv12buffer.c b/vp8/common/swapyv12buffer.c
new file mode 100644 (file)
index 0000000..73656b3
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "swapyv12buffer.h"
+
+void vp8_swap_yv12_buffer(YV12_BUFFER_CONFIG *new_frame, YV12_BUFFER_CONFIG *last_frame)
+{
+    unsigned char *temp;
+
+    temp = last_frame->buffer_alloc;
+    last_frame->buffer_alloc = new_frame->buffer_alloc;
+    new_frame->buffer_alloc = temp;
+
+    temp = last_frame->y_buffer;
+    last_frame->y_buffer = new_frame->y_buffer;
+    new_frame->y_buffer = temp;
+
+    temp = last_frame->u_buffer;
+    last_frame->u_buffer = new_frame->u_buffer;
+    new_frame->u_buffer = temp;
+
+    temp = last_frame->v_buffer;
+    last_frame->v_buffer = new_frame->v_buffer;
+    new_frame->v_buffer = temp;
+
+}
diff --git a/vp8/common/swapyv12buffer.h b/vp8/common/swapyv12buffer.h
new file mode 100644 (file)
index 0000000..a6473ed
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef SWAPYV12_BUFFER_H
+#define SWAPYV12_BUFFER_H
+
+#include "vpx_scale/yv12config.h"
+
+void vp8_swap_yv12_buffer(YV12_BUFFER_CONFIG *new_frame, YV12_BUFFER_CONFIG *last_frame);
+
+#endif
diff --git a/vp8/common/systemdependent.h b/vp8/common/systemdependent.h
new file mode 100644 (file)
index 0000000..f99c4bb
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#if ARCH_X86 || ARCH_X86_64
+void vpx_reset_mmx_state(void);
+#define vp8_clear_system_state() vpx_reset_mmx_state()
+#else
+#define vp8_clear_system_state()
+#endif
+
+struct VP8Common;
+void vp8_machine_specific_config(struct VP8Common *);
diff --git a/vp8/common/textblit.c b/vp8/common/textblit.c
new file mode 100644 (file)
index 0000000..1756100
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stdlib.h>
+
+
+void vp8_blit_text(const char *msg, unsigned char *address, const int pitch)
+{
+    int letter_bitmap;
+    unsigned char *output_pos = address;
+    int colpos;
+    const int font[] =
+    {
+        0x0, 0x5C00, 0x8020, 0xAFABEA, 0xD7EC0, 0x1111111, 0x1855740, 0x18000,
+        0x45C0, 0x74400, 0x51140, 0x23880, 0xC4000, 0x21080, 0x80000, 0x111110,
+        0xE9D72E, 0x87E40, 0x12AD732, 0xAAD62A, 0x4F94C4, 0x4D6B7, 0x456AA,
+        0x3E8423, 0xAAD6AA, 0xAAD6A2, 0x2800, 0x2A00, 0x8A880, 0x52940, 0x22A20,
+        0x15422, 0x6AD62E, 0x1E4A53E, 0xAAD6BF, 0x8C62E, 0xE8C63F, 0x118D6BF,
+        0x1094BF, 0xCAC62E, 0x1F2109F, 0x118FE31, 0xF8C628, 0x8A89F, 0x108421F,
+        0x1F1105F, 0x1F4105F, 0xE8C62E, 0x2294BF, 0x164C62E, 0x12694BF, 0x8AD6A2,
+        0x10FC21, 0x1F8421F, 0x744107, 0xF8220F, 0x1151151, 0x117041, 0x119D731,
+        0x47E0, 0x1041041, 0xFC400, 0x10440, 0x1084210, 0x820
+    };
+    colpos = 0;
+
+    while (msg[colpos] != 0)
+    {
+        char letter = msg[colpos];
+        int fontcol, fontrow;
+
+        if (letter <= 'Z' && letter >= ' ')
+            letter_bitmap = font[letter-' '];
+        else if (letter <= 'z' && letter >= 'a')
+            letter_bitmap = font[letter-'a'+'A' - ' '];
+        else
+            letter_bitmap = font[0];
+
+        for (fontcol = 6; fontcol >= 0 ; fontcol--)
+            for (fontrow = 0; fontrow < 5; fontrow++)
+                output_pos[fontrow *pitch + fontcol] =
+                    ((letter_bitmap >> (fontcol * 5)) & (1 << fontrow) ? 255 : 0);
+
+        output_pos += 7;
+        colpos++;
+    }
+}
+
+static void plot (const int x, const int y, unsigned char *image, const int pitch)
+{
+    image [x+y*pitch] ^= 255;
+}
+
+/* Bresenham line algorithm */
+void vp8_blit_line(int x0, int x1, int y0, int y1, unsigned char *image, const int pitch)
+{
+    int steep = abs(y1 - y0) > abs(x1 - x0);
+    int deltax, deltay;
+    int error, ystep, y, x;
+
+    if (steep)
+    {
+        int t;
+        t = x0;
+        x0 = y0;
+        y0 = t;
+
+        t = x1;
+        x1 = y1;
+        y1 = t;
+    }
+
+    if (x0 > x1)
+    {
+        int t;
+        t = x0;
+        x0 = x1;
+        x1 = t;
+
+        t = y0;
+        y0 = y1;
+        y1 = t;
+    }
+
+    deltax = x1 - x0;
+    deltay = abs(y1 - y0);
+    error  = deltax / 2;
+
+    y = y0;
+
+    if (y0 < y1)
+        ystep = 1;
+    else
+        ystep = -1;
+
+    if (steep)
+    {
+        for (x = x0; x <= x1; x++)
+        {
+            plot(y,x, image, pitch);
+
+            error = error - deltay;
+            if (error < 0)
+            {
+                y = y + ystep;
+                error = error + deltax;
+            }
+        }
+    }
+    else
+    {
+        for (x = x0; x <= x1; x++)
+        {
+            plot(x,y, image, pitch);
+
+            error = error - deltay;
+            if (error < 0)
+            {
+                y = y + ystep;
+                error = error + deltax;
+            }
+        }
+    }
+}
diff --git a/vp8/common/threading.h b/vp8/common/threading.h
new file mode 100644 (file)
index 0000000..ed9e3e6
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef _PTHREAD_EMULATION
+#define _PTHREAD_EMULATION
+
+#if CONFIG_OS_SUPPORT && CONFIG_MULTITHREAD
+
+/* Thread management macros */
+#ifdef _WIN32
+/* Win32 */
+#include <process.h>
+#include <windows.h>
+#define THREAD_FUNCTION DWORD WINAPI
+#define THREAD_FUNCTION_RETURN DWORD
+#define THREAD_SPECIFIC_INDEX DWORD
+#define pthread_t HANDLE
+#define pthread_attr_t DWORD
+#define pthread_create(thhandle,attr,thfunc,tharg) (int)((*thhandle=(HANDLE)_beginthreadex(NULL,0,(unsigned int (__stdcall *)(void *))thfunc,tharg,0,NULL))==NULL)
+#define pthread_join(thread, result) ((WaitForSingleObject((thread),INFINITE)!=WAIT_OBJECT_0) || !CloseHandle(thread))
+#define pthread_detach(thread) if(thread!=NULL)CloseHandle(thread)
+#define thread_sleep(nms) Sleep(nms)
+#define pthread_cancel(thread) terminate_thread(thread,0)
+#define ts_key_create(ts_key, destructor) {ts_key = TlsAlloc();};
+#define pthread_getspecific(ts_key) TlsGetValue(ts_key)
+#define pthread_setspecific(ts_key, value) TlsSetValue(ts_key, (void *)value)
+#define pthread_self() GetCurrentThreadId()
+
+#elif defined(__OS2__)
+/* OS/2 */
+#define INCL_DOS
+#include <os2.h>
+
+#include <stdlib.h>
+#define THREAD_FUNCTION void
+#define THREAD_FUNCTION_RETURN void
+#define THREAD_SPECIFIC_INDEX PULONG
+#define pthread_t TID
+#define pthread_attr_t ULONG
+#define pthread_create(thhandle,attr,thfunc,tharg) \
+    ((int)((*(thhandle)=_beginthread(thfunc,NULL,1024*1024,tharg))==-1))
+#define pthread_join(thread, result) ((int)DosWaitThread(&(thread),0))
+#define pthread_detach(thread) 0
+#define thread_sleep(nms) DosSleep(nms)
+#define pthread_cancel(thread) DosKillThread(thread)
+#define ts_key_create(ts_key, destructor) \
+    DosAllocThreadLocalMemory(1, &(ts_key));
+#define pthread_getspecific(ts_key) ((void *)(*(ts_key)))
+#define pthread_setspecific(ts_key, value) (*(ts_key)=(ULONG)(value))
+#define pthread_self() _gettid()
+#else
+#ifdef __APPLE__
+#include <mach/mach_init.h>
+#include <mach/semaphore.h>
+#include <mach/task.h>
+#include <time.h>
+#include <unistd.h>
+
+#else
+#include <semaphore.h>
+#endif
+
+#include <pthread.h>
+/* pthreads */
+/* Nearly everything is already defined */
+#define THREAD_FUNCTION void *
+#define THREAD_FUNCTION_RETURN void *
+#define THREAD_SPECIFIC_INDEX pthread_key_t
+#define ts_key_create(ts_key, destructor) pthread_key_create (&(ts_key), destructor);
+#endif
+
+/* Syncrhronization macros: Win32 and Pthreads */
+#ifdef _WIN32
+#define sem_t HANDLE
+#define pause(voidpara) __asm PAUSE
+#define sem_init(sem, sem_attr1, sem_init_value) (int)((*sem = CreateSemaphore(NULL,0,32768,NULL))==NULL)
+#define sem_wait(sem) (int)(WAIT_OBJECT_0 != WaitForSingleObject(*sem,INFINITE))
+#define sem_post(sem) ReleaseSemaphore(*sem,1,NULL)
+#define sem_destroy(sem) if(*sem)((int)(CloseHandle(*sem))==TRUE)
+#define thread_sleep(nms) Sleep(nms)
+
+#elif defined(__OS2__)
+typedef struct
+{
+    HEV  event;
+    HMTX wait_mutex;
+    HMTX count_mutex;
+    int  count;
+} sem_t;
+
+static inline int sem_init(sem_t *sem, int pshared, unsigned int value)
+{
+    DosCreateEventSem(NULL, &sem->event, pshared ? DC_SEM_SHARED : 0,
+                      value > 0 ? TRUE : FALSE);
+    DosCreateMutexSem(NULL, &sem->wait_mutex, 0, FALSE);
+    DosCreateMutexSem(NULL, &sem->count_mutex, 0, FALSE);
+
+    sem->count = value;
+
+    return 0;
+}
+
+static inline int sem_wait(sem_t * sem)
+{
+    DosRequestMutexSem(sem->wait_mutex, -1);
+
+    DosWaitEventSem(sem->event, -1);
+
+    DosRequestMutexSem(sem->count_mutex, -1);
+
+    sem->count--;
+    if (sem->count == 0)
+    {
+        ULONG post_count;
+
+        DosResetEventSem(sem->event, &post_count);
+    }
+
+    DosReleaseMutexSem(sem->count_mutex);
+
+    DosReleaseMutexSem(sem->wait_mutex);
+
+    return 0;
+}
+
+static inline int sem_post(sem_t * sem)
+{
+    DosRequestMutexSem(sem->count_mutex, -1);
+
+    if (sem->count < 32768)
+    {
+        sem->count++;
+        DosPostEventSem(sem->event);
+    }
+
+    DosReleaseMutexSem(sem->count_mutex);
+
+    return 0;
+}
+
+static inline int sem_destroy(sem_t * sem)
+{
+    DosCloseEventSem(sem->event);
+    DosCloseMutexSem(sem->wait_mutex);
+    DosCloseMutexSem(sem->count_mutex);
+
+    return 0;
+}
+
+#define thread_sleep(nms) DosSleep(nms)
+
+#else
+
+#ifdef __APPLE__
+#define sem_t semaphore_t
+#define sem_init(X,Y,Z) semaphore_create(mach_task_self(), X, SYNC_POLICY_FIFO, Z)
+#define sem_wait(sem) (semaphore_wait(*sem) )
+#define sem_post(sem) semaphore_signal(*sem)
+#define sem_destroy(sem) semaphore_destroy(mach_task_self(),*sem)
+#define thread_sleep(nms) /* { struct timespec ts;ts.tv_sec=0; ts.tv_nsec = 1000*nms;nanosleep(&ts, NULL);} */
+#else
+#include <unistd.h>
+#include <sched.h>
+#define thread_sleep(nms) sched_yield();/* {struct timespec ts;ts.tv_sec=0; ts.tv_nsec = 1000*nms;nanosleep(&ts, NULL);} */
+#endif
+/* Not Windows. Assume pthreads */
+
+#endif
+
+#if ARCH_X86 || ARCH_X86_64
+#include "vpx_ports/x86.h"
+#else
+#define x86_pause_hint()
+#endif
+
+#endif /* CONFIG_OS_SUPPORT && CONFIG_MULTITHREAD */
+
+#endif
diff --git a/vp8/common/treecoder.c b/vp8/common/treecoder.c
new file mode 100644 (file)
index 0000000..d80c64b
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#if CONFIG_DEBUG
+#include <assert.h>
+#endif
+#include <stdio.h>
+
+#include "treecoder.h"
+
+static void tree2tok(
+    struct vp8_token_struct *const p,
+    vp8_tree t,
+    int i,
+    int v,
+    int L
+)
+{
+    v += v;
+    ++L;
+
+    do
+    {
+        const vp8_tree_index j = t[i++];
+
+        if (j <= 0)
+        {
+            p[-j].value = v;
+            p[-j].Len = L;
+        }
+        else
+            tree2tok(p, t, j, v, L);
+    }
+    while (++v & 1);
+}
+
+void vp8_tokens_from_tree(struct vp8_token_struct *p, vp8_tree t)
+{
+    tree2tok(p, t, 0, 0, 0);
+}
+
+void vp8_tokens_from_tree_offset(struct vp8_token_struct *p, vp8_tree t,
+                                 int offset)
+{
+    tree2tok(p - offset, t, 0, 0, 0);
+}
+
+static void branch_counts(
+    int n,                      /* n = size of alphabet */
+    vp8_token tok               [ /* n */ ],
+    vp8_tree tree,
+    unsigned int branch_ct       [ /* n-1 */ ] [2],
+    const unsigned int num_events[ /* n */ ]
+)
+{
+    const int tree_len = n - 1;
+    int t = 0;
+
+#if CONFIG_DEBUG
+    assert(tree_len);
+#endif
+
+    do
+    {
+        branch_ct[t][0] = branch_ct[t][1] = 0;
+    }
+    while (++t < tree_len);
+
+    t = 0;
+
+    do
+    {
+        int L = tok[t].Len;
+        const int enc = tok[t].value;
+        const unsigned int ct = num_events[t];
+
+        vp8_tree_index i = 0;
+
+        do
+        {
+            const int b = (enc >> --L) & 1;
+            const int j = i >> 1;
+#if CONFIG_DEBUG
+            assert(j < tree_len  &&  0 <= L);
+#endif
+
+            branch_ct [j] [b] += ct;
+            i = tree[ i + b];
+        }
+        while (i > 0);
+
+#if CONFIG_DEBUG
+        assert(!L);
+#endif
+    }
+    while (++t < n);
+
+}
+
+
+void vp8_tree_probs_from_distribution(
+    int n,                      /* n = size of alphabet */
+    vp8_token tok               [ /* n */ ],
+    vp8_tree tree,
+    vp8_prob probs          [ /* n-1 */ ],
+    unsigned int branch_ct       [ /* n-1 */ ] [2],
+    const unsigned int num_events[ /* n */ ],
+    unsigned int Pfac,
+    int rd
+)
+{
+    const int tree_len = n - 1;
+    int t = 0;
+
+    branch_counts(n, tok, tree, branch_ct, num_events);
+
+    do
+    {
+        const unsigned int *const c = branch_ct[t];
+        const unsigned int tot = c[0] + c[1];
+
+#if CONFIG_DEBUG
+        assert(tot < (1 << 24));        /* no overflow below */
+#endif
+
+        if (tot)
+        {
+            const unsigned int p = ((c[0] * Pfac) + (rd ? tot >> 1 : 0)) / tot;
+            probs[t] = p < 256 ? (p ? p : 1) : 255; /* agree w/old version for now */
+        }
+        else
+            probs[t] = vp8_prob_half;
+    }
+    while (++t < tree_len);
+}
diff --git a/vp8/common/treecoder.h b/vp8/common/treecoder.h
new file mode 100644 (file)
index 0000000..ebf51c5
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_TREECODER_H
+#define __INC_TREECODER_H
+
+typedef unsigned char vp8bc_index_t; /* probability index */
+
+
+typedef unsigned char vp8_prob;
+
+#define vp8_prob_half ( (vp8_prob) 128)
+
+typedef signed char vp8_tree_index;
+struct bool_coder_spec;
+
+typedef struct bool_coder_spec bool_coder_spec;
+typedef struct bool_writer bool_writer;
+typedef struct bool_reader bool_reader;
+
+typedef const bool_coder_spec c_bool_coder_spec;
+typedef const bool_writer c_bool_writer;
+typedef const bool_reader c_bool_reader;
+
+
+
+# define vp8_complement( x) (255 - x)
+
+
+/* We build coding trees compactly in arrays.
+   Each node of the tree is a pair of vp8_tree_indices.
+   Array index often references a corresponding probability table.
+   Index <= 0 means done encoding/decoding and value = -Index,
+   Index > 0 means need another bit, specification at index.
+   Nonnegative indices are always even;  processing begins at node 0. */
+
+typedef const vp8_tree_index vp8_tree[], *vp8_tree_p;
+
+
+typedef const struct vp8_token_struct
+{
+    int value;
+    int Len;
+} vp8_token;
+
+/* Construct encoding array from tree. */
+
+void vp8_tokens_from_tree(struct vp8_token_struct *, vp8_tree);
+void vp8_tokens_from_tree_offset(struct vp8_token_struct *, vp8_tree,
+                                 int offset);
+
+
+/* Convert array of token occurrence counts into a table of probabilities
+   for the associated binary encoding tree.  Also writes count of branches
+   taken for each node on the tree; this facilitiates decisions as to
+   probability updates. */
+
+void vp8_tree_probs_from_distribution(
+    int n,                      /* n = size of alphabet */
+    vp8_token tok               [ /* n */ ],
+    vp8_tree tree,
+    vp8_prob probs          [ /* n-1 */ ],
+    unsigned int branch_ct       [ /* n-1 */ ] [2],
+    const unsigned int num_events[ /* n */ ],
+    unsigned int Pfactor,
+    int Round
+);
+
+/* Variant of above using coder spec rather than hardwired 8-bit probs. */
+
+void vp8bc_tree_probs_from_distribution(
+    int n,                      /* n = size of alphabet */
+    vp8_token tok               [ /* n */ ],
+    vp8_tree tree,
+    vp8_prob probs          [ /* n-1 */ ],
+    unsigned int branch_ct       [ /* n-1 */ ] [2],
+    const unsigned int num_events[ /* n */ ],
+    c_bool_coder_spec *s
+);
+
+
+#endif
diff --git a/vp8/common/variance.h b/vp8/common/variance.h
new file mode 100644 (file)
index 0000000..b77aa28
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef VARIANCE_H
+#define VARIANCE_H
+
+typedef unsigned int(*vp8_sad_fn_t)
+    (
+    const unsigned char *src_ptr,
+    int source_stride,
+    const unsigned char *ref_ptr,
+    int ref_stride,
+    int max_sad
+    );
+
+typedef void (*vp8_copy32xn_fn_t)(
+    const unsigned char *src_ptr,
+    int source_stride,
+    const unsigned char *ref_ptr,
+    int ref_stride,
+    int n);
+
+typedef void (*vp8_sad_multi_fn_t)(
+    const unsigned char *src_ptr,
+    int source_stride,
+    const unsigned char *ref_ptr,
+    int  ref_stride,
+    unsigned int *sad_array);
+
+typedef void (*vp8_sad_multi1_fn_t)
+    (
+     const unsigned char *src_ptr,
+     int source_stride,
+     const unsigned char *ref_ptr,
+     int  ref_stride,
+     unsigned short *sad_array
+    );
+
+typedef void (*vp8_sad_multi_d_fn_t)
+    (
+     const unsigned char *src_ptr,
+     int source_stride,
+     unsigned char *ref_ptr[4],
+     int  ref_stride,
+     unsigned int *sad_array
+    );
+
+typedef unsigned int (*vp8_variance_fn_t)
+    (
+     const unsigned char *src_ptr,
+     int source_stride,
+     const unsigned char *ref_ptr,
+     int  ref_stride,
+     unsigned int *sse
+    );
+
+typedef unsigned int (*vp8_subpixvariance_fn_t)
+    (
+      const unsigned char  *src_ptr,
+      int  source_stride,
+      int  xoffset,
+      int  yoffset,
+      const unsigned char *ref_ptr,
+      int Refstride,
+      unsigned int *sse
+    );
+
+typedef void (*vp8_ssimpf_fn_t)
+      (
+        unsigned char *s,
+        int sp,
+        unsigned char *r,
+        int rp,
+        unsigned long *sum_s,
+        unsigned long *sum_r,
+        unsigned long *sum_sq_s,
+        unsigned long *sum_sq_r,
+        unsigned long *sum_sxr
+      );
+
+typedef unsigned int (*vp8_getmbss_fn_t)(const short *);
+
+typedef unsigned int (*vp8_get16x16prederror_fn_t)
+    (
+     const unsigned char *src_ptr,
+     int source_stride,
+     const unsigned char *ref_ptr,
+     int  ref_stride
+    );
+
+typedef struct variance_vtable
+{
+    vp8_sad_fn_t            sdf;
+    vp8_variance_fn_t       vf;
+    vp8_subpixvariance_fn_t svf;
+    vp8_variance_fn_t       svf_halfpix_h;
+    vp8_variance_fn_t       svf_halfpix_v;
+    vp8_variance_fn_t       svf_halfpix_hv;
+    vp8_sad_multi_fn_t      sdx3f;
+    vp8_sad_multi1_fn_t     sdx8f;
+    vp8_sad_multi_d_fn_t    sdx4df;
+#if ARCH_X86 || ARCH_X86_64
+    vp8_copy32xn_fn_t       copymem;
+#endif
+} vp8_variance_fn_ptr_t;
+
+#endif
diff --git a/vp8/common/variance_c.c b/vp8/common/variance_c.c
new file mode 100644 (file)
index 0000000..996404d
--- /dev/null
@@ -0,0 +1,458 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "variance.h"
+#include "filter.h"
+
+
+unsigned int vp8_get_mb_ss_c
+(
+    const short *src_ptr
+)
+{
+    unsigned int i = 0, sum = 0;
+
+    do
+    {
+        sum += (src_ptr[i] * src_ptr[i]);
+        i++;
+    }
+    while (i < 256);
+
+    return sum;
+}
+
+
+static void variance(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    int  w,
+    int  h,
+    unsigned int *sse,
+    int *sum)
+{
+    int i, j;
+    int diff;
+
+    *sum = 0;
+    *sse = 0;
+
+    for (i = 0; i < h; i++)
+    {
+        for (j = 0; j < w; j++)
+        {
+            diff = src_ptr[j] - ref_ptr[j];
+            *sum += diff;
+            *sse += diff * diff;
+        }
+
+        src_ptr += source_stride;
+        ref_ptr += recon_stride;
+    }
+}
+
+
+unsigned int vp8_variance16x16_c(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int var;
+    int avg;
+
+
+    variance(src_ptr, source_stride, ref_ptr, recon_stride, 16, 16, &var, &avg);
+    *sse = var;
+    return (var - ((unsigned int)(avg * avg) >> 8));
+}
+
+unsigned int vp8_variance8x16_c(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int var;
+    int avg;
+
+
+    variance(src_ptr, source_stride, ref_ptr, recon_stride, 8, 16, &var, &avg);
+    *sse = var;
+    return (var - ((unsigned int)(avg * avg) >> 7));
+}
+
+unsigned int vp8_variance16x8_c(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int var;
+    int avg;
+
+
+    variance(src_ptr, source_stride, ref_ptr, recon_stride, 16, 8, &var, &avg);
+    *sse = var;
+    return (var - ((unsigned int)(avg * avg) >> 7));
+}
+
+
+unsigned int vp8_variance8x8_c(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int var;
+    int avg;
+
+
+    variance(src_ptr, source_stride, ref_ptr, recon_stride, 8, 8, &var, &avg);
+    *sse = var;
+    return (var - ((unsigned int)(avg * avg) >> 6));
+}
+
+unsigned int vp8_variance4x4_c(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int var;
+    int avg;
+
+
+    variance(src_ptr, source_stride, ref_ptr, recon_stride, 4, 4, &var, &avg);
+    *sse = var;
+    return (var - ((unsigned int)(avg * avg) >> 4));
+}
+
+
+unsigned int vp8_mse16x16_c(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int var;
+    int avg;
+
+    variance(src_ptr, source_stride, ref_ptr, recon_stride, 16, 16, &var, &avg);
+    *sse = var;
+    return var;
+}
+
+
+/****************************************************************************
+ *
+ *  ROUTINE       : filter_block2d_bil_first_pass
+ *
+ *  INPUTS        : UINT8  *src_ptr          : Pointer to source block.
+ *                  UINT32 src_pixels_per_line : Stride of input block.
+ *                  UINT32 pixel_step        : Offset between filter input samples (see notes).
+ *                  UINT32 output_height     : Input block height.
+ *                  UINT32 output_width      : Input block width.
+ *                  INT32  *vp8_filter          : Array of 2 bi-linear filter taps.
+ *
+ *  OUTPUTS       : INT32 *output_ptr        : Pointer to filtered block.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Applies a 1-D 2-tap bi-linear filter to the source block in
+ *                  either horizontal or vertical direction to produce the
+ *                  filtered output block. Used to implement first-pass
+ *                  of 2-D separable filter.
+ *
+ *  SPECIAL NOTES : Produces INT32 output to retain precision for next pass.
+ *                  Two filter taps should sum to VP8_FILTER_WEIGHT.
+ *                  pixel_step defines whether the filter is applied
+ *                  horizontally (pixel_step=1) or vertically (pixel_step=stride).
+ *                  It defines the offset required to move from one input
+ *                  to the next.
+ *
+ ****************************************************************************/
+static void var_filter_block2d_bil_first_pass
+(
+    const unsigned char *src_ptr,
+    unsigned short *output_ptr,
+    unsigned int src_pixels_per_line,
+    int pixel_step,
+    unsigned int output_height,
+    unsigned int output_width,
+    const short *vp8_filter
+)
+{
+    unsigned int i, j;
+
+    for (i = 0; i < output_height; i++)
+    {
+        for (j = 0; j < output_width; j++)
+        {
+            // Apply bilinear filter
+            output_ptr[j] = (((int)src_ptr[0]          * vp8_filter[0]) +
+                             ((int)src_ptr[pixel_step] * vp8_filter[1]) +
+                             (VP8_FILTER_WEIGHT / 2)) >> VP8_FILTER_SHIFT;
+            src_ptr++;
+        }
+
+        // Next row...
+        src_ptr    += src_pixels_per_line - output_width;
+        output_ptr += output_width;
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : filter_block2d_bil_second_pass
+ *
+ *  INPUTS        : INT32  *src_ptr          : Pointer to source block.
+ *                  UINT32 src_pixels_per_line : Stride of input block.
+ *                  UINT32 pixel_step        : Offset between filter input samples (see notes).
+ *                  UINT32 output_height     : Input block height.
+ *                  UINT32 output_width      : Input block width.
+ *                  INT32  *vp8_filter          : Array of 2 bi-linear filter taps.
+ *
+ *  OUTPUTS       : UINT16 *output_ptr       : Pointer to filtered block.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Applies a 1-D 2-tap bi-linear filter to the source block in
+ *                  either horizontal or vertical direction to produce the
+ *                  filtered output block. Used to implement second-pass
+ *                  of 2-D separable filter.
+ *
+ *  SPECIAL NOTES : Requires 32-bit input as produced by filter_block2d_bil_first_pass.
+ *                  Two filter taps should sum to VP8_FILTER_WEIGHT.
+ *                  pixel_step defines whether the filter is applied
+ *                  horizontally (pixel_step=1) or vertically (pixel_step=stride).
+ *                  It defines the offset required to move from one input
+ *                  to the next.
+ *
+ ****************************************************************************/
+static void var_filter_block2d_bil_second_pass
+(
+    const unsigned short *src_ptr,
+    unsigned char  *output_ptr,
+    unsigned int  src_pixels_per_line,
+    unsigned int  pixel_step,
+    unsigned int  output_height,
+    unsigned int  output_width,
+    const short *vp8_filter
+)
+{
+    unsigned int  i, j;
+    int  Temp;
+
+    for (i = 0; i < output_height; i++)
+    {
+        for (j = 0; j < output_width; j++)
+        {
+            // Apply filter
+            Temp = ((int)src_ptr[0]         * vp8_filter[0]) +
+                   ((int)src_ptr[pixel_step] * vp8_filter[1]) +
+                   (VP8_FILTER_WEIGHT / 2);
+            output_ptr[j] = (unsigned int)(Temp >> VP8_FILTER_SHIFT);
+            src_ptr++;
+        }
+
+        // Next row...
+        src_ptr    += src_pixels_per_line - output_width;
+        output_ptr += output_width;
+    }
+}
+
+
+unsigned int vp8_sub_pixel_variance4x4_c
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    unsigned char  temp2[20*16];
+    const short *HFilter, *VFilter;
+    unsigned short FData3[5*4]; // Temp data bufffer used in filtering
+
+    HFilter = vp8_bilinear_filters[xoffset];
+    VFilter = vp8_bilinear_filters[yoffset];
+
+    // First filter 1d Horizontal
+    var_filter_block2d_bil_first_pass(src_ptr, FData3, src_pixels_per_line, 1, 5, 4, HFilter);
+
+    // Now filter Verticaly
+    var_filter_block2d_bil_second_pass(FData3, temp2, 4,  4,  4,  4, VFilter);
+
+    return vp8_variance4x4_c(temp2, 4, dst_ptr, dst_pixels_per_line, sse);
+}
+
+
+unsigned int vp8_sub_pixel_variance8x8_c
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    unsigned short FData3[9*8]; // Temp data bufffer used in filtering
+    unsigned char  temp2[20*16];
+    const short *HFilter, *VFilter;
+
+    HFilter = vp8_bilinear_filters[xoffset];
+    VFilter = vp8_bilinear_filters[yoffset];
+
+    var_filter_block2d_bil_first_pass(src_ptr, FData3, src_pixels_per_line, 1, 9, 8, HFilter);
+    var_filter_block2d_bil_second_pass(FData3, temp2, 8, 8, 8, 8, VFilter);
+
+    return vp8_variance8x8_c(temp2, 8, dst_ptr, dst_pixels_per_line, sse);
+}
+
+unsigned int vp8_sub_pixel_variance16x16_c
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    unsigned short FData3[17*16];   // Temp data bufffer used in filtering
+    unsigned char  temp2[20*16];
+    const short *HFilter, *VFilter;
+
+    HFilter = vp8_bilinear_filters[xoffset];
+    VFilter = vp8_bilinear_filters[yoffset];
+
+    var_filter_block2d_bil_first_pass(src_ptr, FData3, src_pixels_per_line, 1, 17, 16, HFilter);
+    var_filter_block2d_bil_second_pass(FData3, temp2, 16, 16, 16, 16, VFilter);
+
+    return vp8_variance16x16_c(temp2, 16, dst_ptr, dst_pixels_per_line, sse);
+}
+
+
+unsigned int vp8_variance_halfpixvar16x16_h_c(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    return vp8_sub_pixel_variance16x16_c(src_ptr, source_stride, 4, 0,
+                                         ref_ptr, recon_stride, sse);
+}
+
+
+unsigned int vp8_variance_halfpixvar16x16_v_c(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    return vp8_sub_pixel_variance16x16_c(src_ptr, source_stride, 0, 4,
+                                         ref_ptr, recon_stride, sse);
+}
+
+
+unsigned int vp8_variance_halfpixvar16x16_hv_c(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    return vp8_sub_pixel_variance16x16_c(src_ptr, source_stride, 4, 4,
+                                         ref_ptr, recon_stride, sse);
+}
+
+
+unsigned int vp8_sub_pixel_mse16x16_c
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    vp8_sub_pixel_variance16x16_c(src_ptr, src_pixels_per_line, xoffset, yoffset, dst_ptr, dst_pixels_per_line, sse);
+    return *sse;
+}
+
+unsigned int vp8_sub_pixel_variance16x8_c
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    unsigned short FData3[16*9];    // Temp data bufffer used in filtering
+    unsigned char  temp2[20*16];
+    const short *HFilter, *VFilter;
+
+    HFilter = vp8_bilinear_filters[xoffset];
+    VFilter = vp8_bilinear_filters[yoffset];
+
+    var_filter_block2d_bil_first_pass(src_ptr, FData3, src_pixels_per_line, 1, 9, 16, HFilter);
+    var_filter_block2d_bil_second_pass(FData3, temp2, 16, 16, 8, 16, VFilter);
+
+    return vp8_variance16x8_c(temp2, 16, dst_ptr, dst_pixels_per_line, sse);
+}
+
+unsigned int vp8_sub_pixel_variance8x16_c
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    unsigned short FData3[9*16];    // Temp data bufffer used in filtering
+    unsigned char  temp2[20*16];
+    const short *HFilter, *VFilter;
+
+
+    HFilter = vp8_bilinear_filters[xoffset];
+    VFilter = vp8_bilinear_filters[yoffset];
+
+
+    var_filter_block2d_bil_first_pass(src_ptr, FData3, src_pixels_per_line, 1, 17, 8, HFilter);
+    var_filter_block2d_bil_second_pass(FData3, temp2, 8, 8, 16, 8, VFilter);
+
+    return vp8_variance8x16_c(temp2, 8, dst_ptr, dst_pixels_per_line, sse);
+}
diff --git a/vp8/common/vp8_entropymodedata.h b/vp8/common/vp8_entropymodedata.h
new file mode 100755 (executable)
index 0000000..13e9a92
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+*/
+
+
+/*Generated file, included by entropymode.c*/
+
+
+const struct vp8_token_struct vp8_bmode_encodings[VP8_BINTRAMODES] =
+{
+    { 0, 1 },
+    { 2, 2 },
+    { 6, 3 },
+    { 28, 5 },
+    { 30, 5 },
+    { 58, 6 },
+    { 59, 6 },
+    { 62, 6 },
+    { 126, 7 },
+    { 127, 7 }
+};
+
+const struct vp8_token_struct vp8_ymode_encodings[VP8_YMODES] =
+{
+    { 0, 1 },
+    { 4, 3 },
+    { 5, 3 },
+    { 6, 3 },
+    { 7, 3 }
+};
+
+const struct vp8_token_struct vp8_kf_ymode_encodings[VP8_YMODES] =
+{
+    { 4, 3 },
+    { 5, 3 },
+    { 6, 3 },
+    { 7, 3 },
+    { 0, 1 }
+};
+
+const struct vp8_token_struct vp8_uv_mode_encodings[VP8_UV_MODES] =
+{
+    { 0, 1 },
+    { 2, 2 },
+    { 6, 3 },
+    { 7, 3 }
+};
+
+const struct vp8_token_struct vp8_mbsplit_encodings[VP8_NUMMBSPLITS] =
+{
+    { 6, 3 },
+    { 7, 3 },
+    { 2, 2 },
+    { 0, 1 }
+};
+
+const struct vp8_token_struct vp8_mv_ref_encoding_array[VP8_MVREFS] =
+{
+    { 2, 2 },
+    { 6, 3 },
+    { 0, 1 },
+    { 14, 4 },
+    { 15, 4 }
+};
+
+const struct vp8_token_struct vp8_sub_mv_ref_encoding_array[VP8_SUBMVREFS] =
+{
+    { 0, 1 },
+    { 2, 2 },
+    { 6, 3 },
+    { 7, 3 }
+};
+
+const struct vp8_token_struct vp8_small_mvencodings[8] =
+{
+    { 0, 3 },
+    { 1, 3 },
+    { 2, 3 },
+    { 3, 3 },
+    { 4, 3 },
+    { 5, 3 },
+    { 6, 3 },
+    { 7, 3 }
+};
+
+const vp8_prob vp8_ymode_prob[VP8_YMODES-1] =
+{
+    112, 86, 140, 37
+};
+
+const vp8_prob vp8_kf_ymode_prob[VP8_YMODES-1] =
+{
+    145, 156, 163, 128
+};
+
+const vp8_prob vp8_uv_mode_prob[VP8_UV_MODES-1] =
+{
+    162, 101, 204
+};
+
+const vp8_prob vp8_kf_uv_mode_prob[VP8_UV_MODES-1] =
+{
+    142, 114, 183
+};
+
+const vp8_prob vp8_bmode_prob[VP8_BINTRAMODES-1] =
+{
+    120, 90, 79, 133, 87, 85, 80, 111, 151
+};
+
+
+
+const vp8_prob vp8_kf_bmode_prob
+[VP8_BINTRAMODES] [VP8_BINTRAMODES] [VP8_BINTRAMODES-1] =
+{
+    {
+        { 231, 120,  48,  89, 115, 113, 120, 152, 112 },
+        { 152, 179,  64, 126, 170, 118,  46,  70,  95 },
+        { 175,  69, 143,  80,  85,  82,  72, 155, 103 },
+        {  56,  58,  10, 171, 218, 189,  17,  13, 152 },
+        { 144,  71,  10,  38, 171, 213, 144,  34,  26 },
+        { 114,  26,  17, 163,  44, 195,  21,  10, 173 },
+        { 121,  24,  80, 195,  26,  62,  44,  64,  85 },
+        { 170,  46,  55,  19, 136, 160,  33, 206,  71 },
+        {  63,  20,   8, 114, 114, 208,  12,   9, 226 },
+        {  81,  40,  11,  96, 182,  84,  29,  16,  36 }
+    },
+    {
+        { 134, 183,  89, 137,  98, 101, 106, 165, 148 },
+        {  72, 187, 100, 130, 157, 111,  32,  75,  80 },
+        {  66, 102, 167,  99,  74,  62,  40, 234, 128 },
+        {  41,  53,   9, 178, 241, 141,  26,   8, 107 },
+        { 104,  79,  12,  27, 217, 255,  87,  17,   7 },
+        {  74,  43,  26, 146,  73, 166,  49,  23, 157 },
+        {  65,  38, 105, 160,  51,  52,  31, 115, 128 },
+        {  87,  68,  71,  44, 114,  51,  15, 186,  23 },
+        {  47,  41,  14, 110, 182, 183,  21,  17, 194 },
+        {  66,  45,  25, 102, 197, 189,  23,  18,  22 }
+    },
+    {
+        {  88,  88, 147, 150,  42,  46,  45, 196, 205 },
+        {  43,  97, 183, 117,  85,  38,  35, 179,  61 },
+        {  39,  53, 200,  87,  26,  21,  43, 232, 171 },
+        {  56,  34,  51, 104, 114, 102,  29,  93,  77 },
+        { 107,  54,  32,  26,  51,   1,  81,  43,  31 },
+        {  39,  28,  85, 171,  58, 165,  90,  98,  64 },
+        {  34,  22, 116, 206,  23,  34,  43, 166,  73 },
+        {  68,  25, 106,  22,  64, 171,  36, 225, 114 },
+        {  34,  19,  21, 102, 132, 188,  16,  76, 124 },
+        {  62,  18,  78,  95,  85,  57,  50,  48,  51 }
+    },
+    {
+        { 193, 101,  35, 159, 215, 111,  89,  46, 111 },
+        {  60, 148,  31, 172, 219, 228,  21,  18, 111 },
+        { 112, 113,  77,  85, 179, 255,  38, 120, 114 },
+        {  40,  42,   1, 196, 245, 209,  10,  25, 109 },
+        { 100,  80,   8,  43, 154,   1,  51,  26,  71 },
+        {  88,  43,  29, 140, 166, 213,  37,  43, 154 },
+        {  61,  63,  30, 155,  67,  45,  68,   1, 209 },
+        { 142,  78,  78,  16, 255, 128,  34, 197, 171 },
+        {  41,  40,   5, 102, 211, 183,   4,   1, 221 },
+        {  51,  50,  17, 168, 209, 192,  23,  25,  82 }
+    },
+    {
+        { 125,  98,  42,  88, 104,  85, 117, 175,  82 },
+        {  95,  84,  53,  89, 128, 100, 113, 101,  45 },
+        {  75,  79, 123,  47,  51, 128,  81, 171,   1 },
+        {  57,  17,   5,  71, 102,  57,  53,  41,  49 },
+        { 115,  21,   2,  10, 102, 255, 166,  23,   6 },
+        {  38,  33,  13, 121,  57,  73,  26,   1,  85 },
+        {  41,  10,  67, 138,  77, 110,  90,  47, 114 },
+        { 101,  29,  16,  10,  85, 128, 101, 196,  26 },
+        {  57,  18,  10, 102, 102, 213,  34,  20,  43 },
+        { 117,  20,  15,  36, 163, 128,  68,   1,  26 }
+    },
+    {
+        { 138,  31,  36, 171,  27, 166,  38,  44, 229 },
+        {  67,  87,  58, 169,  82, 115,  26,  59, 179 },
+        {  63,  59,  90, 180,  59, 166,  93,  73, 154 },
+        {  40,  40,  21, 116, 143, 209,  34,  39, 175 },
+        {  57,  46,  22,  24, 128,   1,  54,  17,  37 },
+        {  47,  15,  16, 183,  34, 223,  49,  45, 183 },
+        {  46,  17,  33, 183,   6,  98,  15,  32, 183 },
+        {  65,  32,  73, 115,  28, 128,  23, 128, 205 },
+        {  40,   3,   9, 115,  51, 192,  18,   6, 223 },
+        {  87,  37,   9, 115,  59,  77,  64,  21,  47 }
+    },
+    {
+        { 104,  55,  44, 218,   9,  54,  53, 130, 226 },
+        {  64,  90,  70, 205,  40,  41,  23,  26,  57 },
+        {  54,  57, 112, 184,   5,  41,  38, 166, 213 },
+        {  30,  34,  26, 133, 152, 116,  10,  32, 134 },
+        {  75,  32,  12,  51, 192, 255, 160,  43,  51 },
+        {  39,  19,  53, 221,  26, 114,  32,  73, 255 },
+        {  31,   9,  65, 234,   2,  15,   1, 118,  73 },
+        {  88,  31,  35,  67, 102,  85,  55, 186,  85 },
+        {  56,  21,  23, 111,  59, 205,  45,  37, 192 },
+        {  55,  38,  70, 124,  73, 102,   1,  34,  98 }
+    },
+    {
+        { 102,  61,  71,  37,  34,  53,  31, 243, 192 },
+        {  69,  60,  71,  38,  73, 119,  28, 222,  37 },
+        {  68,  45, 128,  34,   1,  47,  11, 245, 171 },
+        {  62,  17,  19,  70, 146,  85,  55,  62,  70 },
+        {  75,  15,   9,   9,  64, 255, 184, 119,  16 },
+        {  37,  43,  37, 154, 100, 163,  85, 160,   1 },
+        {  63,   9,  92, 136,  28,  64,  32, 201,  85 },
+        {  86,   6,  28,   5,  64, 255,  25, 248,   1 },
+        {  56,   8,  17, 132, 137, 255,  55, 116, 128 },
+        {  58,  15,  20,  82, 135,  57,  26, 121,  40 }
+    },
+    {
+        { 164,  50,  31, 137, 154, 133,  25,  35, 218 },
+        {  51, 103,  44, 131, 131, 123,  31,   6, 158 },
+        {  86,  40,  64, 135, 148, 224,  45, 183, 128 },
+        {  22,  26,  17, 131, 240, 154,  14,   1, 209 },
+        {  83,  12,  13,  54, 192, 255,  68,  47,  28 },
+        {  45,  16,  21,  91,  64, 222,   7,   1, 197 },
+        {  56,  21,  39, 155,  60, 138,  23, 102, 213 },
+        {  85,  26,  85,  85, 128, 128,  32, 146, 171 },
+        {  18,  11,   7,  63, 144, 171,   4,   4, 246 },
+        {  35,  27,  10, 146, 174, 171,  12,  26, 128 }
+    },
+    {
+        { 190,  80,  35,  99, 180,  80, 126,  54,  45 },
+        {  85, 126,  47,  87, 176,  51,  41,  20,  32 },
+        { 101,  75, 128, 139, 118, 146, 116, 128,  85 },
+        {  56,  41,  15, 176, 236,  85,  37,   9,  62 },
+        { 146,  36,  19,  30, 171, 255,  97,  27,  20 },
+        {  71,  30,  17, 119, 118, 255,  17,  18, 138 },
+        { 101,  38,  60, 138,  55,  70,  43,  26, 142 },
+        { 138,  45,  61,  62, 219,   1,  81, 188,  64 },
+        {  32,  41,  20, 117, 151, 142,  20,  21, 163 },
+        { 112,  19,  12,  61, 195, 128,  48,   4,  24 }
+    }
+};
diff --git a/vp8/common/x86/dequantize_mmx.asm b/vp8/common/x86/dequantize_mmx.asm
new file mode 100644 (file)
index 0000000..de9eba8
--- /dev/null
@@ -0,0 +1,258 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+
+;void vp8_dequantize_b_impl_mmx(short *sq, short *dq, short *q)
+global sym(vp8_dequantize_b_impl_mmx)
+sym(vp8_dequantize_b_impl_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 3
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov       rsi, arg(0) ;sq
+        mov       rdi, arg(1) ;dq
+        mov       rax, arg(2) ;q
+
+        movq      mm1, [rsi]
+        pmullw    mm1, [rax+0]            ; mm4 *= kernel 0 modifiers.
+        movq      [rdi], mm1
+
+        movq      mm1, [rsi+8]
+        pmullw    mm1, [rax+8]            ; mm4 *= kernel 0 modifiers.
+        movq      [rdi+8], mm1
+
+        movq      mm1, [rsi+16]
+        pmullw    mm1, [rax+16]            ; mm4 *= kernel 0 modifiers.
+        movq      [rdi+16], mm1
+
+        movq      mm1, [rsi+24]
+        pmullw    mm1, [rax+24]            ; mm4 *= kernel 0 modifiers.
+        movq      [rdi+24], mm1
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void dequant_idct_add_mmx(
+;short *input,            0
+;short *dq,               1
+;unsigned char *dest,     2
+;int stride)              3
+global sym(vp8_dequant_idct_add_mmx)
+sym(vp8_dequant_idct_add_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    GET_GOT     rbx
+    push        rdi
+    ; end prolog
+
+        mov         rax,    arg(0) ;input
+        mov         rdx,    arg(1) ;dq
+
+
+        movq        mm0,    [rax   ]
+        pmullw      mm0,    [rdx]
+
+        movq        mm1,    [rax +8]
+        pmullw      mm1,    [rdx +8]
+
+        movq        mm2,    [rax+16]
+        pmullw      mm2,    [rdx+16]
+
+        movq        mm3,    [rax+24]
+        pmullw      mm3,    [rdx+24]
+
+        mov         rdx,    arg(2) ;dest
+
+        pxor        mm7,    mm7
+
+
+        movq        [rax],   mm7
+        movq        [rax+8], mm7
+
+        movq        [rax+16],mm7
+        movq        [rax+24],mm7
+
+
+        movsxd      rdi,            dword ptr arg(3) ;stride
+
+        psubw       mm0,            mm2             ; b1= 0-2
+        paddw       mm2,            mm2             ;
+
+        movq        mm5,            mm1
+        paddw       mm2,            mm0             ; a1 =0+2
+
+        pmulhw      mm5,            [GLOBAL(x_s1sqr2)];
+        paddw       mm5,            mm1             ; ip1 * sin(pi/8) * sqrt(2)
+
+        movq        mm7,            mm3             ;
+        pmulhw      mm7,            [GLOBAL(x_c1sqr2less1)];
+
+        paddw       mm7,            mm3             ; ip3 * cos(pi/8) * sqrt(2)
+        psubw       mm7,            mm5             ; c1
+
+        movq        mm5,            mm1
+        movq        mm4,            mm3
+
+        pmulhw      mm5,            [GLOBAL(x_c1sqr2less1)]
+        paddw       mm5,            mm1
+
+        pmulhw      mm3,            [GLOBAL(x_s1sqr2)]
+        paddw       mm3,            mm4
+
+        paddw       mm3,            mm5             ; d1
+        movq        mm6,            mm2             ; a1
+
+        movq        mm4,            mm0             ; b1
+        paddw       mm2,            mm3             ;0
+
+        paddw       mm4,            mm7             ;1
+        psubw       mm0,            mm7             ;2
+
+        psubw       mm6,            mm3             ;3
+
+        movq        mm1,            mm2             ; 03 02 01 00
+        movq        mm3,            mm4             ; 23 22 21 20
+
+        punpcklwd   mm1,            mm0             ; 11 01 10 00
+        punpckhwd   mm2,            mm0             ; 13 03 12 02
+
+        punpcklwd   mm3,            mm6             ; 31 21 30 20
+        punpckhwd   mm4,            mm6             ; 33 23 32 22
+
+        movq        mm0,            mm1             ; 11 01 10 00
+        movq        mm5,            mm2             ; 13 03 12 02
+
+        punpckldq   mm0,            mm3             ; 30 20 10 00
+        punpckhdq   mm1,            mm3             ; 31 21 11 01
+
+        punpckldq   mm2,            mm4             ; 32 22 12 02
+        punpckhdq   mm5,            mm4             ; 33 23 13 03
+
+        movq        mm3,            mm5             ; 33 23 13 03
+
+        psubw       mm0,            mm2             ; b1= 0-2
+        paddw       mm2,            mm2             ;
+
+        movq        mm5,            mm1
+        paddw       mm2,            mm0             ; a1 =0+2
+
+        pmulhw      mm5,            [GLOBAL(x_s1sqr2)];
+        paddw       mm5,            mm1             ; ip1 * sin(pi/8) * sqrt(2)
+
+        movq        mm7,            mm3             ;
+        pmulhw      mm7,            [GLOBAL(x_c1sqr2less1)];
+
+        paddw       mm7,            mm3             ; ip3 * cos(pi/8) * sqrt(2)
+        psubw       mm7,            mm5             ; c1
+
+        movq        mm5,            mm1
+        movq        mm4,            mm3
+
+        pmulhw      mm5,            [GLOBAL(x_c1sqr2less1)]
+        paddw       mm5,            mm1
+
+        pmulhw      mm3,            [GLOBAL(x_s1sqr2)]
+        paddw       mm3,            mm4
+
+        paddw       mm3,            mm5             ; d1
+        paddw       mm0,            [GLOBAL(fours)]
+
+        paddw       mm2,            [GLOBAL(fours)]
+        movq        mm6,            mm2             ; a1
+
+        movq        mm4,            mm0             ; b1
+        paddw       mm2,            mm3             ;0
+
+        paddw       mm4,            mm7             ;1
+        psubw       mm0,            mm7             ;2
+
+        psubw       mm6,            mm3             ;3
+        psraw       mm2,            3
+
+        psraw       mm0,            3
+        psraw       mm4,            3
+
+        psraw       mm6,            3
+
+        movq        mm1,            mm2             ; 03 02 01 00
+        movq        mm3,            mm4             ; 23 22 21 20
+
+        punpcklwd   mm1,            mm0             ; 11 01 10 00
+        punpckhwd   mm2,            mm0             ; 13 03 12 02
+
+        punpcklwd   mm3,            mm6             ; 31 21 30 20
+        punpckhwd   mm4,            mm6             ; 33 23 32 22
+
+        movq        mm0,            mm1             ; 11 01 10 00
+        movq        mm5,            mm2             ; 13 03 12 02
+
+        punpckldq   mm0,            mm3             ; 30 20 10 00
+        punpckhdq   mm1,            mm3             ; 31 21 11 01
+
+        punpckldq   mm2,            mm4             ; 32 22 12 02
+        punpckhdq   mm5,            mm4             ; 33 23 13 03
+
+        pxor        mm7,            mm7
+
+        movd        mm4,            [rdx]
+        punpcklbw   mm4,            mm7
+        paddsw      mm0,            mm4
+        packuswb    mm0,            mm7
+        movd        [rdx],          mm0
+
+        movd        mm4,            [rdx+rdi]
+        punpcklbw   mm4,            mm7
+        paddsw      mm1,            mm4
+        packuswb    mm1,            mm7
+        movd        [rdx+rdi],      mm1
+
+        movd        mm4,            [rdx+2*rdi]
+        punpcklbw   mm4,            mm7
+        paddsw      mm2,            mm4
+        packuswb    mm2,            mm7
+        movd        [rdx+rdi*2],    mm2
+
+        add         rdx,            rdi
+
+        movd        mm4,            [rdx+2*rdi]
+        punpcklbw   mm4,            mm7
+        paddsw      mm5,            mm4
+        packuswb    mm5,            mm7
+        movd        [rdx+rdi*2],    mm5
+
+    ; begin epilog
+    pop rdi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+SECTION_RODATA
+align 16
+x_s1sqr2:
+    times 4 dw 0x8A8C
+align 16
+x_c1sqr2less1:
+    times 4 dw 0x4E7B
+align 16
+fours:
+    times 4 dw 0x0004
diff --git a/vp8/common/x86/filter_x86.c b/vp8/common/x86/filter_x86.c
new file mode 100644 (file)
index 0000000..ebab814
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "vpx_ports/mem.h"
+
+DECLARE_ALIGNED(16, const short, vp8_bilinear_filters_x86_4[8][8]) =
+{
+    { 128, 128, 128, 128,   0,   0,   0,   0 },
+    { 112, 112, 112, 112,  16,  16,  16,  16 },
+    {  96,  96,  96,  96,  32,  32,  32,  32 },
+    {  80,  80,  80,  80,  48,  48,  48,  48 },
+    {  64,  64,  64,  64,  64,  64,  64,  64 },
+    {  48,  48,  48,  48,  80,  80,  80,  80 },
+    {  32,  32,  32,  32,  96,  96,  96,  96 },
+    {  16,  16,  16,  16, 112, 112, 112, 112 }
+};
+
+DECLARE_ALIGNED(16, const short, vp8_bilinear_filters_x86_8[8][16]) =
+{
+    { 128, 128, 128, 128, 128, 128, 128, 128,   0,   0,   0,   0,   0,   0,   0,   0 },
+    { 112, 112, 112, 112, 112, 112, 112, 112,  16,  16,  16,  16,  16,  16,  16,  16 },
+    {  96,  96,  96,  96,  96,  96,  96,  96,  32,  32,  32,  32,  32,  32,  32,  32 },
+    {  80,  80,  80,  80,  80,  80,  80,  80,  48,  48,  48,  48,  48,  48,  48,  48 },
+    {  64,  64,  64,  64,  64,  64,  64,  64,  64,  64,  64,  64,  64,  64,  64,  64 },
+    {  48,  48,  48,  48,  48,  48,  48,  48,  80,  80,  80,  80,  80,  80,  80,  80 },
+    {  32,  32,  32,  32,  32,  32,  32,  32,  96,  96,  96,  96,  96,  96,  96,  96 },
+    {  16,  16,  16,  16,  16,  16,  16,  16, 112, 112, 112, 112, 112, 112, 112, 112 }
+};
diff --git a/vp8/common/x86/filter_x86.h b/vp8/common/x86/filter_x86.h
new file mode 100644 (file)
index 0000000..efcc4dc
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef FILTER_X86_H
+#define FILTER_X86_H
+
+/* x86 assembly specific copy of vp8/common/filter.c:vp8_bilinear_filters with
+ * duplicated values */
+extern const short vp8_bilinear_filters_x86_4[8][8];  /* duplicated 4x */
+extern const short vp8_bilinear_filters_x86_8[8][16]; /* duplicated 8x */
+
+#endif /* FILTER_X86_H */
diff --git a/vp8/common/x86/idct_blk_mmx.c b/vp8/common/x86/idct_blk_mmx.c
new file mode 100644 (file)
index 0000000..4adf3f5
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "vp8/common/blockd.h"
+
+extern void vp8_dequantize_b_impl_mmx(short *sq, short *dq, short *q);
+
+void vp8_dequantize_b_mmx(BLOCKD *d, short *DQC)
+{
+    short *sq = (short *) d->qcoeff;
+    short *dq = (short *) d->dqcoeff;
+
+    vp8_dequantize_b_impl_mmx(sq, dq, DQC);
+}
+
+void vp8_dequant_idct_add_y_block_mmx
+            (short *q, short *dq,
+             unsigned char *dst, int stride, char *eobs)
+{
+    int i;
+
+    for (i = 0; i < 4; i++)
+    {
+        if (eobs[0] > 1)
+            vp8_dequant_idct_add_mmx (q, dq, dst, stride);
+        else if (eobs[0] == 1)
+        {
+            vp8_dc_only_idct_add_mmx (q[0]*dq[0], dst, stride, dst, stride);
+            ((int *)q)[0] = 0;
+        }
+
+        if (eobs[1] > 1)
+            vp8_dequant_idct_add_mmx (q+16, dq, dst+4, stride);
+        else if (eobs[1] == 1)
+        {
+            vp8_dc_only_idct_add_mmx (q[16]*dq[0], dst+4, stride,
+                                      dst+4, stride);
+            ((int *)(q+16))[0] = 0;
+        }
+
+        if (eobs[2] > 1)
+            vp8_dequant_idct_add_mmx (q+32, dq, dst+8, stride);
+        else if (eobs[2] == 1)
+        {
+            vp8_dc_only_idct_add_mmx (q[32]*dq[0], dst+8, stride,
+                                      dst+8, stride);
+            ((int *)(q+32))[0] = 0;
+        }
+
+        if (eobs[3] > 1)
+            vp8_dequant_idct_add_mmx (q+48, dq, dst+12, stride);
+        else if (eobs[3] == 1)
+        {
+            vp8_dc_only_idct_add_mmx (q[48]*dq[0], dst+12, stride,
+                                      dst+12, stride);
+            ((int *)(q+48))[0] = 0;
+        }
+
+        q    += 64;
+        dst  += 4*stride;
+        eobs += 4;
+    }
+}
+
+void vp8_dequant_idct_add_uv_block_mmx
+            (short *q, short *dq,
+             unsigned char *dstu, unsigned char *dstv, int stride, char *eobs)
+{
+    int i;
+
+    for (i = 0; i < 2; i++)
+    {
+        if (eobs[0] > 1)
+            vp8_dequant_idct_add_mmx (q, dq, dstu, stride);
+        else if (eobs[0] == 1)
+        {
+            vp8_dc_only_idct_add_mmx (q[0]*dq[0], dstu, stride, dstu, stride);
+            ((int *)q)[0] = 0;
+        }
+
+        if (eobs[1] > 1)
+            vp8_dequant_idct_add_mmx (q+16, dq, dstu+4, stride);
+        else if (eobs[1] == 1)
+        {
+            vp8_dc_only_idct_add_mmx (q[16]*dq[0], dstu+4, stride,
+                                      dstu+4, stride);
+            ((int *)(q+16))[0] = 0;
+        }
+
+        q    += 32;
+        dstu += 4*stride;
+        eobs += 2;
+    }
+
+    for (i = 0; i < 2; i++)
+    {
+        if (eobs[0] > 1)
+            vp8_dequant_idct_add_mmx (q, dq, dstv, stride);
+        else if (eobs[0] == 1)
+        {
+            vp8_dc_only_idct_add_mmx (q[0]*dq[0], dstv, stride, dstv, stride);
+            ((int *)q)[0] = 0;
+        }
+
+        if (eobs[1] > 1)
+            vp8_dequant_idct_add_mmx (q+16, dq, dstv+4, stride);
+        else if (eobs[1] == 1)
+        {
+            vp8_dc_only_idct_add_mmx (q[16]*dq[0], dstv+4, stride,
+                                      dstv+4, stride);
+            ((int *)(q+16))[0] = 0;
+        }
+
+        q    += 32;
+        dstv += 4*stride;
+        eobs += 2;
+    }
+}
diff --git a/vp8/common/x86/idct_blk_sse2.c b/vp8/common/x86/idct_blk_sse2.c
new file mode 100644 (file)
index 0000000..056e052
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+
+void vp8_idct_dequant_0_2x_sse2
+            (short *q, short *dq ,
+             unsigned char *dst, int dst_stride);
+void vp8_idct_dequant_full_2x_sse2
+            (short *q, short *dq ,
+             unsigned char *dst, int dst_stride);
+
+void vp8_dequant_idct_add_y_block_sse2
+            (short *q, short *dq,
+             unsigned char *dst, int stride, char *eobs)
+{
+    int i;
+
+    for (i = 0; i < 4; i++)
+    {
+        if (((short *)(eobs))[0])
+        {
+            if (((short *)(eobs))[0] & 0xfefe)
+                vp8_idct_dequant_full_2x_sse2 (q, dq, dst, stride);
+            else
+                vp8_idct_dequant_0_2x_sse2 (q, dq, dst, stride);
+        }
+        if (((short *)(eobs))[1])
+        {
+            if (((short *)(eobs))[1] & 0xfefe)
+                vp8_idct_dequant_full_2x_sse2 (q+32, dq, dst+8, stride);
+            else
+                vp8_idct_dequant_0_2x_sse2 (q+32, dq, dst+8, stride);
+        }
+        q    += 64;
+        dst  += stride*4;
+        eobs += 4;
+    }
+}
+
+void vp8_dequant_idct_add_uv_block_sse2
+            (short *q, short *dq,
+             unsigned char *dstu, unsigned char *dstv, int stride, char *eobs)
+{
+    if (((short *)(eobs))[0])
+    {
+        if (((short *)(eobs))[0] & 0xfefe)
+            vp8_idct_dequant_full_2x_sse2 (q, dq, dstu, stride);
+        else
+            vp8_idct_dequant_0_2x_sse2 (q, dq, dstu, stride);
+    }
+    q    += 32;
+    dstu += stride*4;
+
+    if (((short *)(eobs))[1])
+    {
+        if (((short *)(eobs))[1] & 0xfefe)
+            vp8_idct_dequant_full_2x_sse2 (q, dq, dstu, stride);
+        else
+            vp8_idct_dequant_0_2x_sse2 (q, dq, dstu, stride);
+    }
+    q    += 32;
+
+    if (((short *)(eobs))[2])
+    {
+        if (((short *)(eobs))[2] & 0xfefe)
+            vp8_idct_dequant_full_2x_sse2 (q, dq, dstv, stride);
+        else
+            vp8_idct_dequant_0_2x_sse2 (q, dq, dstv, stride);
+    }
+    q    += 32;
+    dstv += stride*4;
+
+    if (((short *)(eobs))[3])
+    {
+      if (((short *)(eobs))[3] & 0xfefe)
+          vp8_idct_dequant_full_2x_sse2 (q, dq, dstv, stride);
+      else
+          vp8_idct_dequant_0_2x_sse2 (q, dq, dstv, stride);
+    }
+}
diff --git a/vp8/common/x86/idctllm_mmx.asm b/vp8/common/x86/idctllm_mmx.asm
new file mode 100644 (file)
index 0000000..0c9c205
--- /dev/null
@@ -0,0 +1,295 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+; /****************************************************************************
+; * Notes:
+; *
+; * This implementation makes use of 16 bit fixed point version of two multiply
+; * constants:
+; *        1.   sqrt(2) * cos (pi/8)
+; *        2.   sqrt(2) * sin (pi/8)
+; * Because the first constant is bigger than 1, to maintain the same 16 bit
+; * fixed point precision as the second one, we use a trick of
+; *        x * a = x + x*(a-1)
+; * so
+; *        x * sqrt(2) * cos (pi/8) = x + x * (sqrt(2) *cos(pi/8)-1).
+; *
+; * For the second constant, because of the 16bit version is 35468, which
+; * is bigger than 32768, in signed 16 bit multiply, it becomes a negative
+; * number.
+; *        (x * (unsigned)35468 >> 16) = x * (signed)35468 >> 16 + x
+; *
+; **************************************************************************/
+
+
+;void vp8_short_idct4x4llm_mmx(short *input, unsigned char *pred,
+;int pitch, unsigned char *dest,int stride)
+global sym(vp8_short_idct4x4llm_mmx)
+sym(vp8_short_idct4x4llm_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    mov         rax,    arg(0)              ;input
+    mov         rsi,    arg(1)              ;pred
+
+    movq        mm0,    [rax   ]
+    movq        mm1,    [rax+ 8]
+    movq        mm2,    [rax+16]
+    movq        mm3,    [rax+24]
+
+%if 0
+    pxor        mm7,    mm7
+    movq        [rax],   mm7
+    movq        [rax+8], mm7
+    movq        [rax+16],mm7
+    movq        [rax+24],mm7
+%endif
+    movsxd      rax,    dword ptr arg(2)    ;pitch
+    mov         rdx,    arg(3)              ;dest
+    movsxd      rdi,    dword ptr arg(4)    ;stride
+
+
+    psubw       mm0,            mm2             ; b1= 0-2
+    paddw       mm2,            mm2             ;
+
+    movq        mm5,            mm1
+    paddw       mm2,            mm0             ; a1 =0+2
+
+    pmulhw      mm5,            [GLOBAL(x_s1sqr2)];
+    paddw       mm5,            mm1             ; ip1 * sin(pi/8) * sqrt(2)
+
+    movq        mm7,            mm3             ;
+    pmulhw      mm7,            [GLOBAL(x_c1sqr2less1)];
+
+    paddw       mm7,            mm3             ; ip3 * cos(pi/8) * sqrt(2)
+    psubw       mm7,            mm5             ; c1
+
+    movq        mm5,            mm1
+    movq        mm4,            mm3
+
+    pmulhw      mm5,            [GLOBAL(x_c1sqr2less1)]
+    paddw       mm5,            mm1
+
+    pmulhw      mm3,            [GLOBAL(x_s1sqr2)]
+    paddw       mm3,            mm4
+
+    paddw       mm3,            mm5             ; d1
+    movq        mm6,            mm2             ; a1
+
+    movq        mm4,            mm0             ; b1
+    paddw       mm2,            mm3             ;0
+
+    paddw       mm4,            mm7             ;1
+    psubw       mm0,            mm7             ;2
+
+    psubw       mm6,            mm3             ;3
+
+    movq        mm1,            mm2             ; 03 02 01 00
+    movq        mm3,            mm4             ; 23 22 21 20
+
+    punpcklwd   mm1,            mm0             ; 11 01 10 00
+    punpckhwd   mm2,            mm0             ; 13 03 12 02
+
+    punpcklwd   mm3,            mm6             ; 31 21 30 20
+    punpckhwd   mm4,            mm6             ; 33 23 32 22
+
+    movq        mm0,            mm1             ; 11 01 10 00
+    movq        mm5,            mm2             ; 13 03 12 02
+
+    punpckldq   mm0,            mm3             ; 30 20 10 00
+    punpckhdq   mm1,            mm3             ; 31 21 11 01
+
+    punpckldq   mm2,            mm4             ; 32 22 12 02
+    punpckhdq   mm5,            mm4             ; 33 23 13 03
+
+    movq        mm3,            mm5             ; 33 23 13 03
+
+    psubw       mm0,            mm2             ; b1= 0-2
+    paddw       mm2,            mm2             ;
+
+    movq        mm5,            mm1
+    paddw       mm2,            mm0             ; a1 =0+2
+
+    pmulhw      mm5,            [GLOBAL(x_s1sqr2)];
+    paddw       mm5,            mm1             ; ip1 * sin(pi/8) * sqrt(2)
+
+    movq        mm7,            mm3             ;
+    pmulhw      mm7,            [GLOBAL(x_c1sqr2less1)];
+
+    paddw       mm7,            mm3             ; ip3 * cos(pi/8) * sqrt(2)
+    psubw       mm7,            mm5             ; c1
+
+    movq        mm5,            mm1
+    movq        mm4,            mm3
+
+    pmulhw      mm5,            [GLOBAL(x_c1sqr2less1)]
+    paddw       mm5,            mm1
+
+    pmulhw      mm3,            [GLOBAL(x_s1sqr2)]
+    paddw       mm3,            mm4
+
+    paddw       mm3,            mm5             ; d1
+    paddw       mm0,            [GLOBAL(fours)]
+
+    paddw       mm2,            [GLOBAL(fours)]
+    movq        mm6,            mm2             ; a1
+
+    movq        mm4,            mm0             ; b1
+    paddw       mm2,            mm3             ;0
+
+    paddw       mm4,            mm7             ;1
+    psubw       mm0,            mm7             ;2
+
+    psubw       mm6,            mm3             ;3
+    psraw       mm2,            3
+
+    psraw       mm0,            3
+    psraw       mm4,            3
+
+    psraw       mm6,            3
+
+    movq        mm1,            mm2             ; 03 02 01 00
+    movq        mm3,            mm4             ; 23 22 21 20
+
+    punpcklwd   mm1,            mm0             ; 11 01 10 00
+    punpckhwd   mm2,            mm0             ; 13 03 12 02
+
+    punpcklwd   mm3,            mm6             ; 31 21 30 20
+    punpckhwd   mm4,            mm6             ; 33 23 32 22
+
+    movq        mm0,            mm1             ; 11 01 10 00
+    movq        mm5,            mm2             ; 13 03 12 02
+
+    punpckldq   mm0,            mm3             ; 30 20 10 00
+    punpckhdq   mm1,            mm3             ; 31 21 11 01
+
+    punpckldq   mm2,            mm4             ; 32 22 12 02
+    punpckhdq   mm5,            mm4             ; 33 23 13 03
+
+    pxor        mm7,            mm7
+
+    movd        mm4,            [rsi]
+    punpcklbw   mm4,            mm7
+    paddsw      mm0,            mm4
+    packuswb    mm0,            mm7
+    movd        [rdx],          mm0
+
+    movd        mm4,            [rsi+rax]
+    punpcklbw   mm4,            mm7
+    paddsw      mm1,            mm4
+    packuswb    mm1,            mm7
+    movd        [rdx+rdi],      mm1
+
+    movd        mm4,            [rsi+2*rax]
+    punpcklbw   mm4,            mm7
+    paddsw      mm2,            mm4
+    packuswb    mm2,            mm7
+    movd        [rdx+rdi*2],    mm2
+
+    add         rdx,            rdi
+    add         rsi,            rax
+
+    movd        mm4,            [rsi+2*rax]
+    punpcklbw   mm4,            mm7
+    paddsw      mm5,            mm4
+    packuswb    mm5,            mm7
+    movd        [rdx+rdi*2],    mm5
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_dc_only_idct_add_mmx(
+;short input_dc,
+;unsigned char *pred_ptr,
+;int pred_stride,
+;unsigned char *dst_ptr,
+;int stride)
+global sym(vp8_dc_only_idct_add_mmx)
+sym(vp8_dc_only_idct_add_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    GET_GOT     rbx
+    ; end prolog
+
+        movd        mm5,            arg(0) ;input_dc
+        mov         rax,            arg(1) ;pred_ptr
+        movsxd      rdx,            dword ptr arg(2) ;pred_stride
+
+        pxor        mm0,            mm0
+
+        paddw       mm5,            [GLOBAL(fours)]
+        lea         rcx,            [rdx + rdx*2]
+
+        psraw       mm5,            3
+
+        punpcklwd   mm5,            mm5
+
+        punpckldq   mm5,            mm5
+
+        movd        mm1,            [rax]
+        movd        mm2,            [rax+rdx]
+        movd        mm3,            [rax+2*rdx]
+        movd        mm4,            [rax+rcx]
+
+        mov         rax,            arg(3) ;d -- destination
+        movsxd      rdx,            dword ptr arg(4) ;dst_stride
+
+        punpcklbw   mm1,            mm0
+        paddsw      mm1,            mm5
+        packuswb    mm1,            mm0              ; pack and unpack to saturate
+        lea         rcx,            [rdx + rdx*2]
+
+        punpcklbw   mm2,            mm0
+        paddsw      mm2,            mm5
+        packuswb    mm2,            mm0              ; pack and unpack to saturate
+
+        punpcklbw   mm3,            mm0
+        paddsw      mm3,            mm5
+        packuswb    mm3,            mm0              ; pack and unpack to saturate
+
+        punpcklbw   mm4,            mm0
+        paddsw      mm4,            mm5
+        packuswb    mm4,            mm0              ; pack and unpack to saturate
+
+        movd        [rax],          mm1
+        movd        [rax+rdx],      mm2
+        movd        [rax+2*rdx],    mm3
+        movd        [rax+rcx],      mm4
+
+    ; begin epilog
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+SECTION_RODATA
+align 16
+x_s1sqr2:
+    times 4 dw 0x8A8C
+align 16
+x_c1sqr2less1:
+    times 4 dw 0x4E7B
+align 16
+fours:
+    times 4 dw 0x0004
diff --git a/vp8/common/x86/idctllm_mmx_test.cc b/vp8/common/x86/idctllm_mmx_test.cc
new file mode 100755 (executable)
index 0000000..8c11533
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+ extern "C" {
+    void vp8_short_idct4x4llm_mmx(short *input, unsigned char *pred_ptr,
+                            int pred_stride, unsigned char *dst_ptr,
+                            int dst_stride);
+}
+
+#include "vp8/common/idctllm_test.h"
+
+namespace
+{
+
+INSTANTIATE_TEST_CASE_P(MMX, IDCTTest,
+                        ::testing::Values(vp8_short_idct4x4llm_mmx));
+
+} // namespace
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/vp8/common/x86/idctllm_sse2.asm b/vp8/common/x86/idctllm_sse2.asm
new file mode 100644 (file)
index 0000000..abeb0b6
--- /dev/null
@@ -0,0 +1,708 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;void vp8_idct_dequant_0_2x_sse2
+; (
+;   short *qcoeff       - 0
+;   short *dequant      - 1
+;   unsigned char *dst  - 2
+;   int dst_stride      - 3
+; )
+
+global sym(vp8_idct_dequant_0_2x_sse2)
+sym(vp8_idct_dequant_0_2x_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    GET_GOT     rbx
+    ; end prolog
+
+        mov         rdx,            arg(1) ; dequant
+        mov         rax,            arg(0) ; qcoeff
+
+        movd        xmm4,           [rax]
+        movd        xmm5,           [rdx]
+
+        pinsrw      xmm4,           [rax+32],   4
+        pinsrw      xmm5,           [rdx],      4
+
+        pmullw      xmm4,           xmm5
+
+    ; Zero out xmm5, for use unpacking
+        pxor        xmm5,           xmm5
+
+    ; clear coeffs
+        movd        [rax],          xmm5
+        movd        [rax+32],       xmm5
+;pshufb
+        mov         rax,            arg(2) ; dst
+        movsxd      rdx,            dword ptr arg(3) ; dst_stride
+
+        pshuflw     xmm4,           xmm4,       00000000b
+        pshufhw     xmm4,           xmm4,       00000000b
+
+        lea         rcx,            [rdx + rdx*2]
+        paddw       xmm4,           [GLOBAL(fours)]
+
+        psraw       xmm4,           3
+
+        movq        xmm0,           [rax]
+        movq        xmm1,           [rax+rdx]
+        movq        xmm2,           [rax+2*rdx]
+        movq        xmm3,           [rax+rcx]
+
+        punpcklbw   xmm0,           xmm5
+        punpcklbw   xmm1,           xmm5
+        punpcklbw   xmm2,           xmm5
+        punpcklbw   xmm3,           xmm5
+
+
+    ; Add to predict buffer
+        paddw       xmm0,           xmm4
+        paddw       xmm1,           xmm4
+        paddw       xmm2,           xmm4
+        paddw       xmm3,           xmm4
+
+    ; pack up before storing
+        packuswb    xmm0,           xmm5
+        packuswb    xmm1,           xmm5
+        packuswb    xmm2,           xmm5
+        packuswb    xmm3,           xmm5
+
+    ; store blocks back out
+        movq        [rax],          xmm0
+        movq        [rax + rdx],    xmm1
+
+        lea         rax,            [rax + 2*rdx]
+
+        movq        [rax],          xmm2
+        movq        [rax + rdx],    xmm3
+
+    ; begin epilog
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_idct_dequant_full_2x_sse2
+; (
+;   short *qcoeff       - 0
+;   short *dequant      - 1
+;   unsigned char *dst  - 2
+;   int dst_stride      - 3
+; )
+global sym(vp8_idct_dequant_full_2x_sse2)
+sym(vp8_idct_dequant_full_2x_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ; special case when 2 blocks have 0 or 1 coeffs
+    ; dc is set as first coeff, so no need to load qcoeff
+        mov         rax,            arg(0) ; qcoeff
+        mov         rdx,            arg(1)  ; dequant
+        mov         rdi,            arg(2) ; dst
+
+
+    ; Zero out xmm7, for use unpacking
+        pxor        xmm7,           xmm7
+
+
+    ; note the transpose of xmm1 and xmm2, necessary for shuffle
+    ;   to spit out sensicle data
+        movdqa      xmm0,           [rax]
+        movdqa      xmm2,           [rax+16]
+        movdqa      xmm1,           [rax+32]
+        movdqa      xmm3,           [rax+48]
+
+    ; Clear out coeffs
+        movdqa      [rax],          xmm7
+        movdqa      [rax+16],       xmm7
+        movdqa      [rax+32],       xmm7
+        movdqa      [rax+48],       xmm7
+
+    ; dequantize qcoeff buffer
+        pmullw      xmm0,           [rdx]
+        pmullw      xmm2,           [rdx+16]
+        pmullw      xmm1,           [rdx]
+        pmullw      xmm3,           [rdx+16]
+        movsxd      rdx,            dword ptr arg(3) ; dst_stride
+
+    ; repack so block 0 row x and block 1 row x are together
+        movdqa      xmm4,           xmm0
+        punpckldq   xmm0,           xmm1
+        punpckhdq   xmm4,           xmm1
+
+        pshufd      xmm0,           xmm0,       11011000b
+        pshufd      xmm1,           xmm4,       11011000b
+
+        movdqa      xmm4,           xmm2
+        punpckldq   xmm2,           xmm3
+        punpckhdq   xmm4,           xmm3
+
+        pshufd      xmm2,           xmm2,       11011000b
+        pshufd      xmm3,           xmm4,       11011000b
+
+    ; first pass
+        psubw       xmm0,           xmm2        ; b1 = 0-2
+        paddw       xmm2,           xmm2        ;
+
+        movdqa      xmm5,           xmm1
+        paddw       xmm2,           xmm0        ; a1 = 0+2
+
+        pmulhw      xmm5,           [GLOBAL(x_s1sqr2)]
+        lea         rcx,            [rdx + rdx*2]   ;dst_stride * 3
+        paddw       xmm5,           xmm1        ; ip1 * sin(pi/8) * sqrt(2)
+
+        movdqa      xmm7,           xmm3
+        pmulhw      xmm7,           [GLOBAL(x_c1sqr2less1)]
+
+        paddw       xmm7,           xmm3        ; ip3 * cos(pi/8) * sqrt(2)
+        psubw       xmm7,           xmm5        ; c1
+
+        movdqa      xmm5,           xmm1
+        movdqa      xmm4,           xmm3
+
+        pmulhw      xmm5,           [GLOBAL(x_c1sqr2less1)]
+        paddw       xmm5,           xmm1
+
+        pmulhw      xmm3,           [GLOBAL(x_s1sqr2)]
+        paddw       xmm3,           xmm4
+
+        paddw       xmm3,           xmm5        ; d1
+        movdqa      xmm6,           xmm2        ; a1
+
+        movdqa      xmm4,           xmm0        ; b1
+        paddw       xmm2,           xmm3        ;0
+
+        paddw       xmm4,           xmm7        ;1
+        psubw       xmm0,           xmm7        ;2
+
+        psubw       xmm6,           xmm3        ;3
+
+    ; transpose for the second pass
+        movdqa      xmm7,           xmm2        ; 103 102 101 100 003 002 001 000
+        punpcklwd   xmm2,           xmm0        ; 007 003 006 002 005 001 004 000
+        punpckhwd   xmm7,           xmm0        ; 107 103 106 102 105 101 104 100
+
+        movdqa      xmm5,           xmm4        ; 111 110 109 108 011 010 009 008
+        punpcklwd   xmm4,           xmm6        ; 015 011 014 010 013 009 012 008
+        punpckhwd   xmm5,           xmm6        ; 115 111 114 110 113 109 112 108
+
+
+        movdqa      xmm1,           xmm2        ; 007 003 006 002 005 001 004 000
+        punpckldq   xmm2,           xmm4        ; 013 009 005 001 012 008 004 000
+        punpckhdq   xmm1,           xmm4        ; 015 011 007 003 014 010 006 002
+
+        movdqa      xmm6,           xmm7        ; 107 103 106 102 105 101 104 100
+        punpckldq   xmm7,           xmm5        ; 113 109 105 101 112 108 104 100
+        punpckhdq   xmm6,           xmm5        ; 115 111 107 103 114 110 106 102
+
+
+        movdqa      xmm5,           xmm2        ; 013 009 005 001 012 008 004 000
+        punpckldq   xmm2,           xmm7        ; 112 108 012 008 104 100 004 000
+        punpckhdq   xmm5,           xmm7        ; 113 109 013 009 105 101 005 001
+
+        movdqa      xmm7,           xmm1        ; 015 011 007 003 014 010 006 002
+        punpckldq   xmm1,           xmm6        ; 114 110 014 010 106 102 006 002
+        punpckhdq   xmm7,           xmm6        ; 115 111 015 011 107 103 007 003
+
+        pshufd      xmm0,           xmm2,       11011000b
+        pshufd      xmm2,           xmm1,       11011000b
+
+        pshufd      xmm1,           xmm5,       11011000b
+        pshufd      xmm3,           xmm7,       11011000b
+
+    ; second pass
+        psubw       xmm0,           xmm2            ; b1 = 0-2
+        paddw       xmm2,           xmm2
+
+        movdqa      xmm5,           xmm1
+        paddw       xmm2,           xmm0            ; a1 = 0+2
+
+        pmulhw      xmm5,           [GLOBAL(x_s1sqr2)]
+        paddw       xmm5,           xmm1            ; ip1 * sin(pi/8) * sqrt(2)
+
+        movdqa      xmm7,           xmm3
+        pmulhw      xmm7,           [GLOBAL(x_c1sqr2less1)]
+
+        paddw       xmm7,           xmm3            ; ip3 * cos(pi/8) * sqrt(2)
+        psubw       xmm7,           xmm5            ; c1
+
+        movdqa      xmm5,           xmm1
+        movdqa      xmm4,           xmm3
+
+        pmulhw      xmm5,           [GLOBAL(x_c1sqr2less1)]
+        paddw       xmm5,           xmm1
+
+        pmulhw      xmm3,           [GLOBAL(x_s1sqr2)]
+        paddw       xmm3,           xmm4
+
+        paddw       xmm3,           xmm5            ; d1
+        paddw       xmm0,           [GLOBAL(fours)]
+
+        paddw       xmm2,           [GLOBAL(fours)]
+        movdqa      xmm6,           xmm2            ; a1
+
+        movdqa      xmm4,           xmm0            ; b1
+        paddw       xmm2,           xmm3            ;0
+
+        paddw       xmm4,           xmm7            ;1
+        psubw       xmm0,           xmm7            ;2
+
+        psubw       xmm6,           xmm3            ;3
+        psraw       xmm2,           3
+
+        psraw       xmm0,           3
+        psraw       xmm4,           3
+
+        psraw       xmm6,           3
+
+    ; transpose to save
+        movdqa      xmm7,           xmm2        ; 103 102 101 100 003 002 001 000
+        punpcklwd   xmm2,           xmm0        ; 007 003 006 002 005 001 004 000
+        punpckhwd   xmm7,           xmm0        ; 107 103 106 102 105 101 104 100
+
+        movdqa      xmm5,           xmm4        ; 111 110 109 108 011 010 009 008
+        punpcklwd   xmm4,           xmm6        ; 015 011 014 010 013 009 012 008
+        punpckhwd   xmm5,           xmm6        ; 115 111 114 110 113 109 112 108
+
+
+        movdqa      xmm1,           xmm2        ; 007 003 006 002 005 001 004 000
+        punpckldq   xmm2,           xmm4        ; 013 009 005 001 012 008 004 000
+        punpckhdq   xmm1,           xmm4        ; 015 011 007 003 014 010 006 002
+
+        movdqa      xmm6,           xmm7        ; 107 103 106 102 105 101 104 100
+        punpckldq   xmm7,           xmm5        ; 113 109 105 101 112 108 104 100
+        punpckhdq   xmm6,           xmm5        ; 115 111 107 103 114 110 106 102
+
+
+        movdqa      xmm5,           xmm2        ; 013 009 005 001 012 008 004 000
+        punpckldq   xmm2,           xmm7        ; 112 108 012 008 104 100 004 000
+        punpckhdq   xmm5,           xmm7        ; 113 109 013 009 105 101 005 001
+
+        movdqa      xmm7,           xmm1        ; 015 011 007 003 014 010 006 002
+        punpckldq   xmm1,           xmm6        ; 114 110 014 010 106 102 006 002
+        punpckhdq   xmm7,           xmm6        ; 115 111 015 011 107 103 007 003
+
+        pshufd      xmm0,           xmm2,       11011000b
+        pshufd      xmm2,           xmm1,       11011000b
+
+        pshufd      xmm1,           xmm5,       11011000b
+        pshufd      xmm3,           xmm7,       11011000b
+
+        pxor        xmm7,           xmm7
+
+    ; Load up predict blocks
+        movq        xmm4,           [rdi]
+        movq        xmm5,           [rdi+rdx]
+
+        punpcklbw   xmm4,           xmm7
+        punpcklbw   xmm5,           xmm7
+
+        paddw       xmm0,           xmm4
+        paddw       xmm1,           xmm5
+
+        movq        xmm4,           [rdi+2*rdx]
+        movq        xmm5,           [rdi+rcx]
+
+        punpcklbw   xmm4,           xmm7
+        punpcklbw   xmm5,           xmm7
+
+        paddw       xmm2,           xmm4
+        paddw       xmm3,           xmm5
+
+.finish:
+
+    ; pack up before storing
+        packuswb    xmm0,           xmm7
+        packuswb    xmm1,           xmm7
+        packuswb    xmm2,           xmm7
+        packuswb    xmm3,           xmm7
+
+    ; store blocks back out
+        movq        [rdi],          xmm0
+        movq        [rdi + rdx],    xmm1
+        movq        [rdi + rdx*2],  xmm2
+        movq        [rdi + rcx],    xmm3
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_idct_dequant_dc_0_2x_sse2
+; (
+;   short *qcoeff       - 0
+;   short *dequant      - 1
+;   unsigned char *dst  - 2
+;   int dst_stride      - 3
+;   short *dc           - 4
+; )
+global sym(vp8_idct_dequant_dc_0_2x_sse2)
+sym(vp8_idct_dequant_dc_0_2x_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    GET_GOT     rbx
+    push        rdi
+    ; end prolog
+
+    ; special case when 2 blocks have 0 or 1 coeffs
+    ; dc is set as first coeff, so no need to load qcoeff
+        mov         rax,            arg(0) ; qcoeff
+
+        mov         rdi,            arg(2) ; dst
+        mov         rdx,            arg(4) ; dc
+
+    ; Zero out xmm5, for use unpacking
+        pxor        xmm5,           xmm5
+
+    ; load up 2 dc words here == 2*16 = doubleword
+        movd        xmm4,           [rdx]
+
+        movsxd      rdx,            dword ptr arg(3) ; dst_stride
+        lea         rcx, [rdx + rdx*2]
+    ; Load up predict blocks
+        movq        xmm0,           [rdi]
+        movq        xmm1,           [rdi+rdx*1]
+        movq        xmm2,           [rdi+rdx*2]
+        movq        xmm3,           [rdi+rcx]
+
+    ; Duplicate and expand dc across
+        punpcklwd   xmm4,           xmm4
+        punpckldq   xmm4,           xmm4
+
+    ; Rounding to dequant and downshift
+        paddw       xmm4,           [GLOBAL(fours)]
+        psraw       xmm4,           3
+
+    ; Predict buffer needs to be expanded from bytes to words
+        punpcklbw   xmm0,           xmm5
+        punpcklbw   xmm1,           xmm5
+        punpcklbw   xmm2,           xmm5
+        punpcklbw   xmm3,           xmm5
+
+    ; Add to predict buffer
+        paddw       xmm0,           xmm4
+        paddw       xmm1,           xmm4
+        paddw       xmm2,           xmm4
+        paddw       xmm3,           xmm4
+
+    ; pack up before storing
+        packuswb    xmm0,           xmm5
+        packuswb    xmm1,           xmm5
+        packuswb    xmm2,           xmm5
+        packuswb    xmm3,           xmm5
+
+    ; store blocks back out
+        movq        [rdi],          xmm0
+        movq        [rdi + rdx],    xmm1
+        movq        [rdi + rdx*2],  xmm2
+        movq        [rdi + rcx],    xmm3
+
+    ; begin epilog
+    pop         rdi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+;void vp8_idct_dequant_dc_full_2x_sse2
+; (
+;   short *qcoeff       - 0
+;   short *dequant      - 1
+;   unsigned char *dst  - 2
+;   int dst_stride      - 3
+;   short *dc           - 4
+; )
+global sym(vp8_idct_dequant_dc_full_2x_sse2)
+sym(vp8_idct_dequant_dc_full_2x_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rdi
+    ; end prolog
+
+    ; special case when 2 blocks have 0 or 1 coeffs
+    ; dc is set as first coeff, so no need to load qcoeff
+        mov         rax,            arg(0) ; qcoeff
+        mov         rdx,            arg(1)  ; dequant
+
+        mov         rdi,            arg(2) ; dst
+
+    ; Zero out xmm7, for use unpacking
+        pxor        xmm7,           xmm7
+
+
+    ; note the transpose of xmm1 and xmm2, necessary for shuffle
+    ;   to spit out sensicle data
+        movdqa      xmm0,           [rax]
+        movdqa      xmm2,           [rax+16]
+        movdqa      xmm1,           [rax+32]
+        movdqa      xmm3,           [rax+48]
+
+    ; Clear out coeffs
+        movdqa      [rax],          xmm7
+        movdqa      [rax+16],       xmm7
+        movdqa      [rax+32],       xmm7
+        movdqa      [rax+48],       xmm7
+
+    ; dequantize qcoeff buffer
+        pmullw      xmm0,           [rdx]
+        pmullw      xmm2,           [rdx+16]
+        pmullw      xmm1,           [rdx]
+        pmullw      xmm3,           [rdx+16]
+
+    ; DC component
+        mov         rdx,            arg(4)
+
+    ; repack so block 0 row x and block 1 row x are together
+        movdqa      xmm4,           xmm0
+        punpckldq   xmm0,           xmm1
+        punpckhdq   xmm4,           xmm1
+
+        pshufd      xmm0,           xmm0,       11011000b
+        pshufd      xmm1,           xmm4,       11011000b
+
+        movdqa      xmm4,           xmm2
+        punpckldq   xmm2,           xmm3
+        punpckhdq   xmm4,           xmm3
+
+        pshufd      xmm2,           xmm2,       11011000b
+        pshufd      xmm3,           xmm4,       11011000b
+
+    ; insert DC component
+        pinsrw      xmm0,           [rdx],      0
+        pinsrw      xmm0,           [rdx+2],    4
+
+    ; first pass
+        psubw       xmm0,           xmm2        ; b1 = 0-2
+        paddw       xmm2,           xmm2        ;
+
+        movdqa      xmm5,           xmm1
+        paddw       xmm2,           xmm0        ; a1 = 0+2
+
+        pmulhw      xmm5,           [GLOBAL(x_s1sqr2)]
+        paddw       xmm5,           xmm1        ; ip1 * sin(pi/8) * sqrt(2)
+
+        movdqa      xmm7,           xmm3
+        pmulhw      xmm7,           [GLOBAL(x_c1sqr2less1)]
+
+        paddw       xmm7,           xmm3        ; ip3 * cos(pi/8) * sqrt(2)
+        psubw       xmm7,           xmm5        ; c1
+
+        movdqa      xmm5,           xmm1
+        movdqa      xmm4,           xmm3
+
+        pmulhw      xmm5,           [GLOBAL(x_c1sqr2less1)]
+        paddw       xmm5,           xmm1
+
+        pmulhw      xmm3,           [GLOBAL(x_s1sqr2)]
+        paddw       xmm3,           xmm4
+
+        paddw       xmm3,           xmm5        ; d1
+        movdqa      xmm6,           xmm2        ; a1
+
+        movdqa      xmm4,           xmm0        ; b1
+        paddw       xmm2,           xmm3        ;0
+
+        paddw       xmm4,           xmm7        ;1
+        psubw       xmm0,           xmm7        ;2
+
+        psubw       xmm6,           xmm3        ;3
+
+    ; transpose for the second pass
+        movdqa      xmm7,           xmm2        ; 103 102 101 100 003 002 001 000
+        punpcklwd   xmm2,           xmm0        ; 007 003 006 002 005 001 004 000
+        punpckhwd   xmm7,           xmm0        ; 107 103 106 102 105 101 104 100
+
+        movdqa      xmm5,           xmm4        ; 111 110 109 108 011 010 009 008
+        punpcklwd   xmm4,           xmm6        ; 015 011 014 010 013 009 012 008
+        punpckhwd   xmm5,           xmm6        ; 115 111 114 110 113 109 112 108
+
+
+        movdqa      xmm1,           xmm2        ; 007 003 006 002 005 001 004 000
+        punpckldq   xmm2,           xmm4        ; 013 009 005 001 012 008 004 000
+        punpckhdq   xmm1,           xmm4        ; 015 011 007 003 014 010 006 002
+
+        movdqa      xmm6,           xmm7        ; 107 103 106 102 105 101 104 100
+        punpckldq   xmm7,           xmm5        ; 113 109 105 101 112 108 104 100
+        punpckhdq   xmm6,           xmm5        ; 115 111 107 103 114 110 106 102
+
+
+        movdqa      xmm5,           xmm2        ; 013 009 005 001 012 008 004 000
+        punpckldq   xmm2,           xmm7        ; 112 108 012 008 104 100 004 000
+        punpckhdq   xmm5,           xmm7        ; 113 109 013 009 105 101 005 001
+
+        movdqa      xmm7,           xmm1        ; 015 011 007 003 014 010 006 002
+        punpckldq   xmm1,           xmm6        ; 114 110 014 010 106 102 006 002
+        punpckhdq   xmm7,           xmm6        ; 115 111 015 011 107 103 007 003
+
+        pshufd      xmm0,           xmm2,       11011000b
+        pshufd      xmm2,           xmm1,       11011000b
+
+        pshufd      xmm1,           xmm5,       11011000b
+        pshufd      xmm3,           xmm7,       11011000b
+
+    ; second pass
+        psubw       xmm0,           xmm2            ; b1 = 0-2
+        paddw       xmm2,           xmm2
+
+        movdqa      xmm5,           xmm1
+        paddw       xmm2,           xmm0            ; a1 = 0+2
+
+        pmulhw      xmm5,           [GLOBAL(x_s1sqr2)]
+        paddw       xmm5,           xmm1            ; ip1 * sin(pi/8) * sqrt(2)
+
+        movdqa      xmm7,           xmm3
+        pmulhw      xmm7,           [GLOBAL(x_c1sqr2less1)]
+
+        paddw       xmm7,           xmm3            ; ip3 * cos(pi/8) * sqrt(2)
+        psubw       xmm7,           xmm5            ; c1
+
+        movdqa      xmm5,           xmm1
+        movdqa      xmm4,           xmm3
+
+        pmulhw      xmm5,           [GLOBAL(x_c1sqr2less1)]
+        paddw       xmm5,           xmm1
+
+        pmulhw      xmm3,           [GLOBAL(x_s1sqr2)]
+        paddw       xmm3,           xmm4
+
+        paddw       xmm3,           xmm5            ; d1
+        paddw       xmm0,           [GLOBAL(fours)]
+
+        paddw       xmm2,           [GLOBAL(fours)]
+        movdqa      xmm6,           xmm2            ; a1
+
+        movdqa      xmm4,           xmm0            ; b1
+        paddw       xmm2,           xmm3            ;0
+
+        paddw       xmm4,           xmm7            ;1
+        psubw       xmm0,           xmm7            ;2
+
+        psubw       xmm6,           xmm3            ;3
+        psraw       xmm2,           3
+
+        psraw       xmm0,           3
+        psraw       xmm4,           3
+
+        psraw       xmm6,           3
+
+    ; transpose to save
+        movdqa      xmm7,           xmm2        ; 103 102 101 100 003 002 001 000
+        punpcklwd   xmm2,           xmm0        ; 007 003 006 002 005 001 004 000
+        punpckhwd   xmm7,           xmm0        ; 107 103 106 102 105 101 104 100
+
+        movdqa      xmm5,           xmm4        ; 111 110 109 108 011 010 009 008
+        punpcklwd   xmm4,           xmm6        ; 015 011 014 010 013 009 012 008
+        punpckhwd   xmm5,           xmm6        ; 115 111 114 110 113 109 112 108
+
+
+        movdqa      xmm1,           xmm2        ; 007 003 006 002 005 001 004 000
+        punpckldq   xmm2,           xmm4        ; 013 009 005 001 012 008 004 000
+        punpckhdq   xmm1,           xmm4        ; 015 011 007 003 014 010 006 002
+
+        movdqa      xmm6,           xmm7        ; 107 103 106 102 105 101 104 100
+        punpckldq   xmm7,           xmm5        ; 113 109 105 101 112 108 104 100
+        punpckhdq   xmm6,           xmm5        ; 115 111 107 103 114 110 106 102
+
+
+        movdqa      xmm5,           xmm2        ; 013 009 005 001 012 008 004 000
+        punpckldq   xmm2,           xmm7        ; 112 108 012 008 104 100 004 000
+        punpckhdq   xmm5,           xmm7        ; 113 109 013 009 105 101 005 001
+
+        movdqa      xmm7,           xmm1        ; 015 011 007 003 014 010 006 002
+        punpckldq   xmm1,           xmm6        ; 114 110 014 010 106 102 006 002
+        punpckhdq   xmm7,           xmm6        ; 115 111 015 011 107 103 007 003
+
+        pshufd      xmm0,           xmm2,       11011000b
+        pshufd      xmm2,           xmm1,       11011000b
+
+        pshufd      xmm1,           xmm5,       11011000b
+        pshufd      xmm3,           xmm7,       11011000b
+
+        pxor        xmm7,           xmm7
+
+    ; Load up predict blocks
+        movsxd      rdx,            dword ptr arg(3) ; dst_stride
+        movq        xmm4,           [rdi]
+        movq        xmm5,           [rdi+rdx]
+        lea         rcx,            [rdx + rdx*2]
+
+        punpcklbw   xmm4,           xmm7
+        punpcklbw   xmm5,           xmm7
+
+        paddw       xmm0,           xmm4
+        paddw       xmm1,           xmm5
+
+        movq        xmm4,           [rdi+rdx*2]
+        movq        xmm5,           [rdi+rcx]
+
+        punpcklbw   xmm4,           xmm7
+        punpcklbw   xmm5,           xmm7
+
+        paddw       xmm2,           xmm4
+        paddw       xmm3,           xmm5
+
+.finish:
+
+    ; pack up before storing
+        packuswb    xmm0,           xmm7
+        packuswb    xmm1,           xmm7
+        packuswb    xmm2,           xmm7
+        packuswb    xmm3,           xmm7
+
+    ; Load destination stride before writing out,
+    ;   doesn't need to persist
+        movsxd      rdx,            dword ptr arg(3) ; dst_stride
+
+    ; store blocks back out
+        movq        [rdi],          xmm0
+        movq        [rdi + rdx],    xmm1
+
+        lea         rdi,            [rdi + 2*rdx]
+
+        movq        [rdi],          xmm2
+        movq        [rdi + rdx],    xmm3
+
+
+    ; begin epilog
+    pop         rdi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+SECTION_RODATA
+align 16
+fours:
+    times 8 dw 0x0004
+align 16
+x_s1sqr2:
+    times 8 dw 0x8A8C
+align 16
+x_c1sqr2less1:
+    times 8 dw 0x4E7B
diff --git a/vp8/common/x86/iwalsh_mmx.asm b/vp8/common/x86/iwalsh_mmx.asm
new file mode 100644 (file)
index 0000000..6582687
--- /dev/null
@@ -0,0 +1,140 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;void vp8_short_inv_walsh4x4_mmx(short *input, short *output)
+global sym(vp8_short_inv_walsh4x4_mmx)
+sym(vp8_short_inv_walsh4x4_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 2
+    ; end prolog
+
+    mov         rdx, arg(0)
+    mov         rax, 30003h
+
+    movq        mm0, [rdx + 0]    ;ip[0]
+    movq        mm1, [rdx + 8]    ;ip[4]
+    movd        mm7, rax
+
+    movq        mm2, [rdx + 16]   ;ip[8]
+    movq        mm3, [rdx + 24]   ;ip[12]
+    punpcklwd   mm7, mm7          ;0003000300030003h
+    mov         rdx, arg(1)
+
+    movq        mm4, mm0
+    movq        mm5, mm1
+
+    paddw       mm4, mm3          ;ip[0] + ip[12] aka al
+    paddw       mm5, mm2          ;ip[4] + ip[8] aka bl
+
+    movq        mm6, mm4          ;temp al
+    paddw       mm4, mm5          ;al + bl
+    psubw       mm6, mm5          ;al - bl
+
+    psubw       mm0, mm3          ;ip[0] - ip[12] aka d1
+    psubw       mm1, mm2          ;ip[4] - ip[8] aka c1
+
+    movq        mm5, mm0          ;temp dl
+    paddw       mm0, mm1          ;dl + cl
+    psubw       mm5, mm1          ;dl - cl
+
+    ; 03 02 01 00
+    ; 13 12 11 10
+    ; 23 22 21 20
+    ; 33 32 31 30
+
+    movq        mm3, mm4          ; 03 02 01 00
+    punpcklwd   mm4, mm0          ; 11 01 10 00
+    punpckhwd   mm3, mm0          ; 13 03 12 02
+
+    movq        mm1, mm6          ; 23 22 21 20
+    punpcklwd   mm6, mm5          ; 31 21 30 20
+    punpckhwd   mm1, mm5          ; 33 23 32 22
+
+    movq        mm0, mm4          ; 11 01 10 00
+    movq        mm2, mm3          ; 13 03 12 02
+
+    punpckldq   mm0, mm6          ; 30 20 10 00 aka ip[0]
+    punpckhdq   mm4, mm6          ; 31 21 11 01 aka ip[4]
+
+    punpckldq   mm2, mm1          ; 32 22 12 02 aka ip[8]
+    punpckhdq   mm3, mm1          ; 33 23 13 03 aka ip[12]
+;~~~~~~~~~~~~~~~~~~~~~
+    movq        mm1, mm0
+    movq        mm5, mm4
+    paddw       mm1, mm3          ;ip[0] + ip[12] aka al
+    paddw       mm5, mm2          ;ip[4] + ip[8] aka bl
+
+    movq        mm6, mm1          ;temp al
+    paddw       mm1, mm5          ;al + bl
+    psubw       mm6, mm5          ;al - bl
+    paddw       mm1, mm7
+    paddw       mm6, mm7
+    psraw       mm1, 3
+    psraw       mm6, 3
+
+    psubw       mm0, mm3          ;ip[0] - ip[12] aka d1
+    psubw       mm4, mm2          ;ip[4] - ip[8] aka c1
+
+    movq        mm5, mm0          ;temp dl
+    paddw       mm0, mm4          ;dl + cl
+    psubw       mm5, mm4          ;dl - cl
+    paddw       mm0, mm7
+    paddw       mm5, mm7
+    psraw       mm0, 3
+    psraw       mm5, 3
+;~~~~~~~~~~~~~~~~~~~~~
+
+    movd        eax, mm1
+    movd        ecx, mm0
+    psrlq       mm0, 32
+    psrlq       mm1, 32
+    mov         word ptr[rdx+32*0], ax
+    mov         word ptr[rdx+32*1], cx
+    shr         eax, 16
+    shr         ecx, 16
+    mov         word ptr[rdx+32*4], ax
+    mov         word ptr[rdx+32*5], cx
+    movd        eax, mm1
+    movd        ecx, mm0
+    mov         word ptr[rdx+32*8], ax
+    mov         word ptr[rdx+32*9], cx
+    shr         eax, 16
+    shr         ecx, 16
+    mov         word ptr[rdx+32*12], ax
+    mov         word ptr[rdx+32*13], cx
+
+    movd        eax, mm6
+    movd        ecx, mm5
+    psrlq       mm5, 32
+    psrlq       mm6, 32
+    mov         word ptr[rdx+32*2], ax
+    mov         word ptr[rdx+32*3], cx
+    shr         eax, 16
+    shr         ecx, 16
+    mov         word ptr[rdx+32*6], ax
+    mov         word ptr[rdx+32*7], cx
+    movd        eax, mm6
+    movd        ecx, mm5
+    mov         word ptr[rdx+32*10], ax
+    mov         word ptr[rdx+32*11], cx
+    shr         eax, 16
+    shr         ecx, 16
+    mov         word ptr[rdx+32*14], ax
+    mov         word ptr[rdx+32*15], cx
+
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
diff --git a/vp8/common/x86/iwalsh_sse2.asm b/vp8/common/x86/iwalsh_sse2.asm
new file mode 100644 (file)
index 0000000..51cb5e2
--- /dev/null
@@ -0,0 +1,121 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;void vp8_short_inv_walsh4x4_sse2(short *input, short *output)
+global sym(vp8_short_inv_walsh4x4_sse2)
+sym(vp8_short_inv_walsh4x4_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 2
+    ; end prolog
+
+    mov         rcx, arg(0)
+    mov         rdx, arg(1)
+    mov         rax, 30003h
+
+    movdqa      xmm0, [rcx + 0]     ;ip[4] ip[0]
+    movdqa      xmm1, [rcx + 16]    ;ip[12] ip[8]
+
+
+    pshufd      xmm2, xmm1, 4eh     ;ip[8] ip[12]
+    movdqa      xmm3, xmm0          ;ip[4] ip[0]
+
+    paddw       xmm0, xmm2          ;ip[4]+ip[8] ip[0]+ip[12] aka b1 a1
+    psubw       xmm3, xmm2          ;ip[4]-ip[8] ip[0]-ip[12] aka c1 d1
+
+    movdqa      xmm4, xmm0
+    punpcklqdq  xmm0, xmm3          ;d1 a1
+    punpckhqdq  xmm4, xmm3          ;c1 b1
+
+    movdqa      xmm1, xmm4          ;c1 b1
+    paddw       xmm4, xmm0          ;dl+cl a1+b1 aka op[4] op[0]
+    psubw       xmm0, xmm1          ;d1-c1 a1-b1 aka op[12] op[8]
+
+    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    ; 13 12 11 10 03 02 01 00
+    ;
+    ; 33 32 31 30 23 22 21 20
+    ;
+    movdqa      xmm3, xmm4          ; 13 12 11 10 03 02 01 00
+    punpcklwd   xmm4, xmm0          ; 23 03 22 02 21 01 20 00
+    punpckhwd   xmm3, xmm0          ; 33 13 32 12 31 11 30 10
+    movdqa      xmm1, xmm4          ; 23 03 22 02 21 01 20 00
+    punpcklwd   xmm4, xmm3          ; 31 21 11 01 30 20 10 00
+    punpckhwd   xmm1, xmm3          ; 33 23 13 03 32 22 12 02
+    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    movd        xmm0, eax
+    pshufd      xmm2, xmm1, 4eh     ;ip[8] ip[12]
+    movdqa      xmm3, xmm4          ;ip[4] ip[0]
+
+    pshufd      xmm0, xmm0, 0       ;03 03 03 03 03 03 03 03
+
+    paddw       xmm4, xmm2          ;ip[4]+ip[8] ip[0]+ip[12] aka b1 a1
+    psubw       xmm3, xmm2          ;ip[4]-ip[8] ip[0]-ip[12] aka c1 d1
+
+    movdqa      xmm5, xmm4
+    punpcklqdq  xmm4, xmm3          ;d1 a1
+    punpckhqdq  xmm5, xmm3          ;c1 b1
+
+    movdqa      xmm1, xmm5          ;c1 b1
+    paddw       xmm5, xmm4          ;dl+cl a1+b1 aka op[4] op[0]
+    psubw       xmm4, xmm1          ;d1-c1 a1-b1 aka op[12] op[8]
+
+    paddw       xmm5, xmm0
+    paddw       xmm4, xmm0
+    psraw       xmm5, 3
+    psraw       xmm4, 3
+
+    movd        eax, xmm5
+    movd        ecx, xmm4
+    psrldq      xmm5, 4
+    psrldq      xmm4, 4
+    mov         word ptr[rdx+32*0], ax
+    mov         word ptr[rdx+32*2], cx
+    shr         eax, 16
+    shr         ecx, 16
+    mov         word ptr[rdx+32*4], ax
+    mov         word ptr[rdx+32*6], cx
+    movd        eax, xmm5
+    movd        ecx, xmm4
+    psrldq      xmm5, 4
+    psrldq      xmm4, 4
+    mov         word ptr[rdx+32*8], ax
+    mov         word ptr[rdx+32*10], cx
+    shr         eax, 16
+    shr         ecx, 16
+    mov         word ptr[rdx+32*12], ax
+    mov         word ptr[rdx+32*14], cx
+
+    movd        eax, xmm5
+    movd        ecx, xmm4
+    psrldq      xmm5, 4
+    psrldq      xmm4, 4
+    mov         word ptr[rdx+32*1], ax
+    mov         word ptr[rdx+32*3], cx
+    shr         eax, 16
+    shr         ecx, 16
+    mov         word ptr[rdx+32*5], ax
+    mov         word ptr[rdx+32*7], cx
+    movd        eax, xmm5
+    movd        ecx, xmm4
+    mov         word ptr[rdx+32*9], ax
+    mov         word ptr[rdx+32*11], cx
+    shr         eax, 16
+    shr         ecx, 16
+    mov         word ptr[rdx+32*13], ax
+    mov         word ptr[rdx+32*15], cx
+
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
diff --git a/vp8/common/x86/loopfilter_block_sse2.asm b/vp8/common/x86/loopfilter_block_sse2.asm
new file mode 100644 (file)
index 0000000..4918eb5
--- /dev/null
@@ -0,0 +1,813 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+%macro LF_ABS 2
+        ; %1 value not preserved
+        ; %2 value preserved
+        ; output in %1
+        movdqa      scratch1, %2            ; v2
+
+        psubusb     scratch1, %1            ; v2 - v1
+        psubusb     %1, %2                  ; v1 - v2
+        por         %1, scratch1            ; abs(v2 - v1)
+%endmacro
+
+%macro LF_FILTER_HEV_MASK 8-9
+
+        LF_ABS      %1, %2                  ; abs(p3 - p2)
+        LF_ABS      %2, %3                  ; abs(p2 - p1)
+        pmaxub      %1, %2                  ; accumulate mask
+%if %0 == 8
+        movdqa      scratch2, %3            ; save p1
+        LF_ABS      scratch2, %4            ; abs(p1 - p0)
+%endif
+        LF_ABS      %4, %5                  ; abs(p0 - q0)
+        LF_ABS      %5, %6                  ; abs(q0 - q1)
+%if %0 == 8
+        pmaxub      %5, scratch2            ; accumulate hev
+%else
+        pmaxub      %5, %9
+%endif
+        pmaxub      %1, %5                  ; accumulate mask
+
+        LF_ABS      %3, %6                  ; abs(p1 - q1)
+        LF_ABS      %6, %7                  ; abs(q1 - q2)
+        pmaxub      %1, %6                  ; accumulate mask
+        LF_ABS      %7, %8                  ; abs(q2 - q3)
+        pmaxub      %1, %7                  ; accumulate mask
+
+        paddusb     %4, %4                  ; 2 * abs(p0 - q0)
+        pand        %3, [GLOBAL(tfe)]
+        psrlw       %3, 1                   ; abs(p1 - q1) / 2
+        paddusb     %4, %3                  ; abs(p0 - q0) * 2 + abs(p1 - q1) / 2
+
+        psubusb     %1, [limit]
+        psubusb     %4, [blimit]
+        por         %1, %4
+        pcmpeqb     %1, zero                ; mask
+
+        psubusb     %5, [thresh]
+        pcmpeqb     %5, zero                ; ~hev
+%endmacro
+
+%macro LF_FILTER 6
+        ; %1-%4: p1-q1
+        ; %5: mask
+        ; %6: hev
+
+        movdqa      scratch2, %6            ; save hev
+
+        pxor        %1, [GLOBAL(t80)]       ; ps1
+        pxor        %4, [GLOBAL(t80)]       ; qs1
+        movdqa      scratch1, %1
+        psubsb      scratch1, %4            ; signed_char_clamp(ps1 - qs1)
+        pandn       scratch2, scratch1      ; vp8_filter &= hev
+
+        pxor        %2, [GLOBAL(t80)]       ; ps0
+        pxor        %3, [GLOBAL(t80)]       ; qs0
+        movdqa      scratch1, %3
+        psubsb      scratch1, %2            ; qs0 - ps0
+        paddsb      scratch2, scratch1      ; vp8_filter += (qs0 - ps0)
+        paddsb      scratch2, scratch1      ; vp8_filter += (qs0 - ps0)
+        paddsb      scratch2, scratch1      ; vp8_filter += (qs0 - ps0)
+        pand        %5, scratch2            ; &= mask
+
+        movdqa      scratch2, %5
+        paddsb      %5, [GLOBAL(t4)]        ; Filter1
+        paddsb      scratch2, [GLOBAL(t3)]  ; Filter2
+
+        ; Filter1 >> 3
+        movdqa      scratch1, zero
+        pcmpgtb     scratch1, %5
+        psrlw       %5, 3
+        pand        scratch1, [GLOBAL(te0)]
+        pand        %5, [GLOBAL(t1f)]
+        por         %5, scratch1
+
+        psubsb      %3, %5                  ; qs0 - Filter1
+        pxor        %3, [GLOBAL(t80)]
+
+        ; Filter2 >> 3
+        movdqa      scratch1, zero
+        pcmpgtb     scratch1, scratch2
+        psrlw       scratch2, 3
+        pand        scratch1, [GLOBAL(te0)]
+        pand        scratch2, [GLOBAL(t1f)]
+        por         scratch2, scratch1
+
+        paddsb      %2, scratch2            ; ps0 + Filter2
+        pxor        %2, [GLOBAL(t80)]
+
+        ; outer tap adjustments
+        paddsb      %5, [GLOBAL(t1)]
+        movdqa      scratch1, zero
+        pcmpgtb     scratch1, %5
+        psrlw       %5, 1
+        pand        scratch1, [GLOBAL(t80)]
+        pand        %5, [GLOBAL(t7f)]
+        por         %5, scratch1
+        pand        %5, %6                  ; vp8_filter &= ~hev
+
+        psubsb      %4, %5                  ; qs1 - vp8_filter
+        pxor        %4, [GLOBAL(t80)]
+
+        paddsb      %1, %5                  ; ps1 + vp8_filter
+        pxor        %1, [GLOBAL(t80)]
+%endmacro
+
+;void vp8_loop_filter_bh_y_sse2
+;(
+;    unsigned char *src_ptr,
+;    int            src_pixel_step,
+;    const char    *blimit,
+;    const char    *limit,
+;    const char    *thresh
+;)
+global sym(vp8_loop_filter_bh_y_sse2)
+sym(vp8_loop_filter_bh_y_sse2):
+
+%ifidn __OUTPUT_FORMAT__,x64
+    %define src      rcx ; src_ptr
+    %define stride   rdx ; src_pixel_step
+    %define blimit   r8
+    %define limit    r9
+    %define thresh   r10
+
+    %define spp      rax
+    %define stride3  r11
+    %define stride5  r12
+    %define stride7  r13
+
+    push    rbp
+    mov     rbp, rsp
+    push    r12
+    push    r13
+    mov     thresh, arg(4)
+%else
+    %define src      rdi ; src_ptr
+    %define stride   rsi ; src_pixel_step
+    %define blimit   rdx
+    %define limit    rcx
+    %define thresh   r8
+
+    %define spp      rax
+    %define stride3  r9
+    %define stride5  r10
+    %define stride7  r11
+%endif
+
+    %define scratch1 xmm5
+    %define scratch2 xmm6
+    %define zero     xmm7
+
+    %define i0       [src]
+    %define i1       [spp]
+    %define i2       [src + 2 * stride]
+    %define i3       [spp + 2 * stride]
+    %define i4       [src + 4 * stride]
+    %define i5       [spp + 4 * stride]
+    %define i6       [src + 2 * stride3]
+    %define i7       [spp + 2 * stride3]
+    %define i8       [src + 8 * stride]
+    %define i9       [spp + 8 * stride]
+    %define i10      [src + 2 * stride5]
+    %define i11      [spp + 2 * stride5]
+    %define i12      [src + 4 * stride3]
+    %define i13      [spp + 4 * stride3]
+    %define i14      [src + 2 * stride7]
+    %define i15      [spp + 2 * stride7]
+
+    ; prep work
+    lea         spp, [src + stride]
+    lea         stride3, [stride + 2 * stride]
+    lea         stride5, [stride3 + 2 * stride]
+    lea         stride7, [stride3 + 4 * stride]
+    pxor        zero, zero
+
+        ; load the first set into registers
+        movdqa       xmm0, i0
+        movdqa       xmm1, i1
+        movdqa       xmm2, i2
+        movdqa       xmm3, i3
+        movdqa       xmm4, i4
+        movdqa       xmm8, i5
+        movdqa       xmm9, i6   ; q2, will contain abs(p1-p0)
+        movdqa       xmm10, i7
+LF_FILTER_HEV_MASK xmm0, xmm1, xmm2, xmm3, xmm4, xmm8, xmm9, xmm10
+
+        movdqa       xmm1, i2
+        movdqa       xmm2, i3
+        movdqa       xmm3, i4
+        movdqa       xmm8, i5
+LF_FILTER xmm1, xmm2, xmm3, xmm8, xmm0, xmm4
+        movdqa       i2, xmm1
+        movdqa       i3, xmm2
+
+; second set
+        movdqa       i4, xmm3
+        movdqa       i5, xmm8
+
+        movdqa       xmm0, i6
+        movdqa       xmm1, i7
+        movdqa       xmm2, i8
+        movdqa       xmm4, i9
+        movdqa       xmm10, i10   ; q2, will contain abs(p1-p0)
+        movdqa       xmm11, i11
+LF_FILTER_HEV_MASK xmm3, xmm8, xmm0, xmm1, xmm2, xmm4, xmm10, xmm11, xmm9
+
+        movdqa       xmm0, i6
+        movdqa       xmm1, i7
+        movdqa       xmm4, i8
+        movdqa       xmm8, i9
+LF_FILTER xmm0, xmm1, xmm4, xmm8, xmm3, xmm2
+        movdqa       i6, xmm0
+        movdqa       i7, xmm1
+
+; last set
+        movdqa       i8, xmm4
+        movdqa       i9, xmm8
+
+        movdqa       xmm0, i10
+        movdqa       xmm1, i11
+        movdqa       xmm2, i12
+        movdqa       xmm3, i13
+        movdqa       xmm9, i14   ; q2, will contain abs(p1-p0)
+        movdqa       xmm11, i15
+LF_FILTER_HEV_MASK xmm4, xmm8, xmm0, xmm1, xmm2, xmm3, xmm9, xmm11, xmm10
+
+        movdqa       xmm0, i10
+        movdqa       xmm1, i11
+        movdqa       xmm3, i12
+        movdqa       xmm8, i13
+LF_FILTER xmm0, xmm1, xmm3, xmm8, xmm4, xmm2
+        movdqa       i10, xmm0
+        movdqa       i11, xmm1
+        movdqa       i12, xmm3
+        movdqa       i13, xmm8
+
+%ifidn __OUTPUT_FORMAT__,x64
+    pop    r13
+    pop    r12
+    pop    rbp
+%endif
+
+    ret
+
+
+;void vp8_loop_filter_bv_y_sse2
+;(
+;    unsigned char *src_ptr,
+;    int            src_pixel_step,
+;    const char    *blimit,
+;    const char    *limit,
+;    const char    *thresh
+;)
+
+global sym(vp8_loop_filter_bv_y_sse2)
+sym(vp8_loop_filter_bv_y_sse2):
+
+%ifidn __OUTPUT_FORMAT__,x64
+    %define src      rcx ; src_ptr
+    %define stride   rdx ; src_pixel_step
+    %define blimit   r8
+    %define limit    r9
+    %define thresh   r10
+
+    %define spp      rax
+    %define stride3  r11
+    %define stride5  r12
+    %define stride7  r13
+
+    push    rbp
+    mov     rbp, rsp
+    SAVE_XMM 15
+    push    r12
+    push    r13
+    mov     thresh, arg(4)
+%else
+    %define src      rdi
+    %define stride   rsi
+    %define blimit   rdx
+    %define limit    rcx
+    %define thresh   r8
+
+    %define spp      rax
+    %define stride3  r9
+    %define stride5  r10
+    %define stride7  r11
+%endif
+
+    %define scratch1 xmm5
+    %define scratch2 xmm6
+    %define zero     xmm7
+
+    %define s0       [src]
+    %define s1       [spp]
+    %define s2       [src + 2 * stride]
+    %define s3       [spp + 2 * stride]
+    %define s4       [src + 4 * stride]
+    %define s5       [spp + 4 * stride]
+    %define s6       [src + 2 * stride3]
+    %define s7       [spp + 2 * stride3]
+    %define s8       [src + 8 * stride]
+    %define s9       [spp + 8 * stride]
+    %define s10      [src + 2 * stride5]
+    %define s11      [spp + 2 * stride5]
+    %define s12      [src + 4 * stride3]
+    %define s13      [spp + 4 * stride3]
+    %define s14      [src + 2 * stride7]
+    %define s15      [spp + 2 * stride7]
+
+    %define i0       [rsp]
+    %define i1       [rsp + 16]
+    %define i2       [rsp + 32]
+    %define i3       [rsp + 48]
+    %define i4       [rsp + 64]
+    %define i5       [rsp + 80]
+    %define i6       [rsp + 96]
+    %define i7       [rsp + 112]
+    %define i8       [rsp + 128]
+    %define i9       [rsp + 144]
+    %define i10      [rsp + 160]
+    %define i11      [rsp + 176]
+    %define i12      [rsp + 192]
+    %define i13      [rsp + 208]
+    %define i14      [rsp + 224]
+    %define i15      [rsp + 240]
+
+    ALIGN_STACK 16, rax
+
+    ; reserve stack space
+    %define      temp_storage  0 ; size is 256 (16*16)
+    %define      stack_size 256
+    sub          rsp, stack_size
+
+    ; prep work
+    lea         spp, [src + stride]
+    lea         stride3, [stride + 2 * stride]
+    lea         stride5, [stride3 + 2 * stride]
+    lea         stride7, [stride3 + 4 * stride]
+
+        ; 8-f
+        movdqa      xmm0, s8
+        movdqa      xmm1, xmm0
+        punpcklbw   xmm0, s9                ; 80 90
+        punpckhbw   xmm1, s9                ; 88 98
+
+        movdqa      xmm2, s10
+        movdqa      xmm3, xmm2
+        punpcklbw   xmm2, s11 ; a0 b0
+        punpckhbw   xmm3, s11 ; a8 b8
+
+        movdqa      xmm4, xmm0
+        punpcklwd   xmm0, xmm2              ; 80 90 a0 b0
+        punpckhwd   xmm4, xmm2              ; 84 94 a4 b4
+
+        movdqa      xmm2, xmm1
+        punpcklwd   xmm1, xmm3              ; 88 98 a8 b8
+        punpckhwd   xmm2, xmm3              ; 8c 9c ac bc
+
+        ; using xmm[0124]
+        ; work on next 4 rows
+
+        movdqa      xmm3, s12
+        movdqa      xmm5, xmm3
+        punpcklbw   xmm3, s13 ; c0 d0
+        punpckhbw   xmm5, s13 ; c8 d8
+
+        movdqa      xmm6, s14
+        movdqa      xmm7, xmm6
+        punpcklbw   xmm6, s15 ; e0 f0
+        punpckhbw   xmm7, s15 ; e8 f8
+
+        movdqa      xmm8, xmm3
+        punpcklwd   xmm3, xmm6              ; c0 d0 e0 f0
+        punpckhwd   xmm8, xmm6              ; c4 d4 e4 f4
+
+        movdqa      xmm6, xmm5
+        punpcklwd   xmm5, xmm7              ; c8 d8 e8 f8
+        punpckhwd   xmm6, xmm7              ; cc dc ec fc
+
+        ; pull the third and fourth sets together
+
+        movdqa      xmm7, xmm0
+        punpckldq   xmm0, xmm3              ; 80 90 a0 b0 c0 d0 e0 f0
+        punpckhdq   xmm7, xmm3              ; 82 92 a2 b2 c2 d2 e2 f2
+
+        movdqa      xmm3, xmm4
+        punpckldq   xmm4, xmm8              ; 84 94 a4 b4 c4 d4 e4 f4
+        punpckhdq   xmm3, xmm8              ; 86 96 a6 b6 c6 d6 e6 f6
+
+        movdqa      xmm8, xmm1
+        punpckldq   xmm1, xmm5              ; 88 88 a8 b8 c8 d8 e8 f8
+        punpckhdq   xmm8, xmm5              ; 8a 9a aa ba ca da ea fa
+
+        movdqa      xmm5, xmm2
+        punpckldq   xmm2, xmm6              ; 8c 9c ac bc cc dc ec fc
+        punpckhdq   xmm5, xmm6              ; 8e 9e ae be ce de ee fe
+
+        ; save the calculations. we only have 15 registers ...
+        movdqa      i0, xmm0
+        movdqa      i1, xmm7
+        movdqa      i2, xmm4
+        movdqa      i3, xmm3
+        movdqa      i4, xmm1
+        movdqa      i5, xmm8
+        movdqa      i6, xmm2
+        movdqa      i7, xmm5
+
+        ; 0-7
+        movdqa      xmm0, s0
+        movdqa      xmm1, xmm0
+        punpcklbw   xmm0, s1 ; 00 10
+        punpckhbw   xmm1, s1 ; 08 18
+
+        movdqa      xmm2, s2
+        movdqa      xmm3, xmm2
+        punpcklbw   xmm2, s3 ; 20 30
+        punpckhbw   xmm3, s3 ; 28 38
+
+        movdqa      xmm4, xmm0
+        punpcklwd   xmm0, xmm2              ; 00 10 20 30
+        punpckhwd   xmm4, xmm2              ; 04 14 24 34
+
+        movdqa      xmm2, xmm1
+        punpcklwd   xmm1, xmm3              ; 08 18 28 38
+        punpckhwd   xmm2, xmm3              ; 0c 1c 2c 3c
+
+        ; using xmm[0124]
+        ; work on next 4 rows
+
+        movdqa      xmm3, s4
+        movdqa      xmm5, xmm3
+        punpcklbw   xmm3, s5 ; 40 50
+        punpckhbw   xmm5, s5 ; 48 58
+
+        movdqa      xmm6, s6
+        movdqa      xmm7, xmm6
+        punpcklbw   xmm6, s7   ; 60 70
+        punpckhbw   xmm7, s7   ; 68 78
+
+        movdqa      xmm8, xmm3
+        punpcklwd   xmm3, xmm6              ; 40 50 60 70
+        punpckhwd   xmm8, xmm6              ; 44 54 64 74
+
+        movdqa      xmm6, xmm5
+        punpcklwd   xmm5, xmm7              ; 48 58 68 78
+        punpckhwd   xmm6, xmm7              ; 4c 5c 6c 7c
+
+        ; pull the first two sets together
+
+        movdqa      xmm7, xmm0
+        punpckldq   xmm0, xmm3              ; 00 10 20 30 40 50 60 70
+        punpckhdq   xmm7, xmm3              ; 02 12 22 32 42 52 62 72
+
+        movdqa      xmm3, xmm4
+        punpckldq   xmm4, xmm8              ; 04 14 24 34 44 54 64 74
+        punpckhdq   xmm3, xmm8              ; 06 16 26 36 46 56 66 76
+
+        movdqa      xmm8, xmm1
+        punpckldq   xmm1, xmm5              ; 08 18 28 38 48 58 68 78
+        punpckhdq   xmm8, xmm5              ; 0a 1a 2a 3a 4a 5a 6a 7a
+
+        movdqa      xmm5, xmm2
+        punpckldq   xmm2, xmm6              ; 0c 1c 2c 3c 4c 5c 6c 7c
+        punpckhdq   xmm5, xmm6              ; 0e 1e 2e 3e 4e 5e 6e 7e
+        ; final combination
+
+        movdqa      xmm6, xmm0
+        punpcklqdq  xmm0, i0
+        punpckhqdq  xmm6, i0
+
+        movdqa      xmm9, xmm7
+        punpcklqdq  xmm7, i1
+        punpckhqdq  xmm9, i1
+
+        movdqa      xmm10, xmm4
+        punpcklqdq  xmm4, i2
+        punpckhqdq  xmm10, i2
+
+        movdqa      xmm11, xmm3
+        punpcklqdq  xmm3, i3
+        punpckhqdq  xmm11, i3
+
+        movdqa      xmm12, xmm1
+        punpcklqdq  xmm1, i4
+        punpckhqdq  xmm12, i4
+
+        movdqa      xmm13, xmm8
+        punpcklqdq  xmm8, i5
+        punpckhqdq  xmm13, i5
+
+        movdqa      xmm14, xmm2
+        punpcklqdq  xmm2, i6
+        punpckhqdq  xmm14, i6
+
+        movdqa      xmm15, xmm5
+        punpcklqdq  xmm5, i7
+        punpckhqdq  xmm15, i7
+
+        movdqa      i0, xmm0
+        movdqa      i1, xmm6
+        movdqa      i2, xmm7
+        movdqa      i3, xmm9
+        movdqa      i4, xmm4
+        movdqa      i5, xmm10
+        movdqa      i6, xmm3
+        movdqa      i7, xmm11
+        movdqa      i8, xmm1
+        movdqa      i9, xmm12
+        movdqa      i10, xmm8
+        movdqa      i11, xmm13
+        movdqa      i12, xmm2
+        movdqa      i13, xmm14
+        movdqa      i14, xmm5
+        movdqa      i15, xmm15
+
+; TRANSPOSED DATA AVAILABLE ON THE STACK
+
+        movdqa      xmm12, xmm6
+        movdqa      xmm13, xmm7
+
+        pxor        zero, zero
+
+LF_FILTER_HEV_MASK xmm0, xmm12, xmm13, xmm9, xmm4, xmm10, xmm3, xmm11
+
+        movdqa       xmm1, i2
+        movdqa       xmm2, i3
+        movdqa       xmm8, i4
+        movdqa       xmm9, i5
+LF_FILTER xmm1, xmm2, xmm8, xmm9, xmm0, xmm4
+        movdqa       i2, xmm1
+        movdqa       i3, xmm2
+
+; second set
+        movdqa       i4, xmm8
+        movdqa       i5, xmm9
+
+        movdqa       xmm0, i6
+        movdqa       xmm1, i7
+        movdqa       xmm2, i8
+        movdqa       xmm4, i9
+        movdqa       xmm10, i10   ; q2, will contain abs(p1-p0)
+        movdqa       xmm11, i11
+LF_FILTER_HEV_MASK xmm8, xmm9, xmm0, xmm1, xmm2, xmm4, xmm10, xmm11, xmm3
+
+        movdqa       xmm0, i6
+        movdqa       xmm1, i7
+        movdqa       xmm3, i8
+        movdqa       xmm4, i9
+LF_FILTER xmm0, xmm1, xmm3, xmm4, xmm8, xmm2
+        movdqa       i6, xmm0
+        movdqa       i7, xmm1
+
+; last set
+        movdqa       i8, xmm3
+        movdqa       i9, xmm4
+
+        movdqa       xmm0, i10
+        movdqa       xmm1, i11
+        movdqa       xmm2, i12
+        movdqa       xmm8, i13
+        movdqa       xmm9, i14   ; q2, will contain abs(p1-p0)
+        movdqa       xmm11, i15
+LF_FILTER_HEV_MASK xmm3, xmm4, xmm0, xmm1, xmm2, xmm8, xmm9, xmm11, xmm10
+
+        movdqa       xmm0, i10
+        movdqa       xmm1, i11
+        movdqa       xmm4, i12
+        movdqa       xmm8, i13
+LF_FILTER xmm0, xmm1, xmm4, xmm8, xmm3, xmm2
+        movdqa       i10, xmm0
+        movdqa       i11, xmm1
+        movdqa       i12, xmm4
+        movdqa       i13, xmm8
+
+
+; RESHUFFLE AND WRITE OUT
+        ; 8-f
+        movdqa      xmm0, i8
+        movdqa      xmm1, xmm0
+        punpcklbw   xmm0, i9                ; 80 90
+        punpckhbw   xmm1, i9                ; 88 98
+
+        movdqa      xmm2, i10
+        movdqa      xmm3, xmm2
+        punpcklbw   xmm2, i11               ; a0 b0
+        punpckhbw   xmm3, i11               ; a8 b8
+
+        movdqa      xmm4, xmm0
+        punpcklwd   xmm0, xmm2              ; 80 90 a0 b0
+        punpckhwd   xmm4, xmm2              ; 84 94 a4 b4
+
+        movdqa      xmm2, xmm1
+        punpcklwd   xmm1, xmm3              ; 88 98 a8 b8
+        punpckhwd   xmm2, xmm3              ; 8c 9c ac bc
+
+        ; using xmm[0124]
+        ; work on next 4 rows
+
+        movdqa      xmm3, i12
+        movdqa      xmm5, xmm3
+        punpcklbw   xmm3, i13               ; c0 d0
+        punpckhbw   xmm5, i13               ; c8 d8
+
+        movdqa      xmm6, i14
+        movdqa      xmm7, xmm6
+        punpcklbw   xmm6, i15               ; e0 f0
+        punpckhbw   xmm7, i15               ; e8 f8
+
+        movdqa      xmm8, xmm3
+        punpcklwd   xmm3, xmm6              ; c0 d0 e0 f0
+        punpckhwd   xmm8, xmm6              ; c4 d4 e4 f4
+
+        movdqa      xmm6, xmm5
+        punpcklwd   xmm5, xmm7              ; c8 d8 e8 f8
+        punpckhwd   xmm6, xmm7              ; cc dc ec fc
+
+        ; pull the third and fourth sets together
+
+        movdqa      xmm7, xmm0
+        punpckldq   xmm0, xmm3              ; 80 90 a0 b0 c0 d0 e0 f0
+        punpckhdq   xmm7, xmm3              ; 82 92 a2 b2 c2 d2 e2 f2
+
+        movdqa      xmm3, xmm4
+        punpckldq   xmm4, xmm8              ; 84 94 a4 b4 c4 d4 e4 f4
+        punpckhdq   xmm3, xmm8              ; 86 96 a6 b6 c6 d6 e6 f6
+
+        movdqa      xmm8, xmm1
+        punpckldq   xmm1, xmm5              ; 88 88 a8 b8 c8 d8 e8 f8
+        punpckhdq   xmm8, xmm5              ; 8a 9a aa ba ca da ea fa
+
+        movdqa      xmm5, xmm2
+        punpckldq   xmm2, xmm6              ; 8c 9c ac bc cc dc ec fc
+        punpckhdq   xmm5, xmm6              ; 8e 9e ae be ce de ee fe
+
+        ; save the calculations. we only have 15 registers ...
+        movdqa      i8, xmm0
+        movdqa      i9, xmm7
+        movdqa      i10, xmm4
+        movdqa      i11, xmm3
+        movdqa      i12, xmm1
+        movdqa      i13, xmm8
+        movdqa      i14, xmm2
+        movdqa      i15, xmm5
+
+        ; 0-7
+        movdqa      xmm0, i0
+        movdqa      xmm1, xmm0
+        punpcklbw   xmm0, i1                ; 00 10
+        punpckhbw   xmm1, i1                ; 08 18
+
+        movdqa      xmm2, i2
+        movdqa      xmm3, xmm2
+        punpcklbw   xmm2, i3                ; 20 30
+        punpckhbw   xmm3, i3                ; 28 38
+
+        movdqa      xmm4, xmm0
+        punpcklwd   xmm0, xmm2              ; 00 10 20 30
+        punpckhwd   xmm4, xmm2              ; 04 14 24 34
+
+        movdqa      xmm2, xmm1
+        punpcklwd   xmm1, xmm3              ; 08 18 28 38
+        punpckhwd   xmm2, xmm3              ; 0c 1c 2c 3c
+
+        ; using xmm[0124]
+        ; work on next 4 rows
+
+        movdqa      xmm3, i4
+        movdqa      xmm5, xmm3
+        punpcklbw   xmm3, i5                ; 40 50
+        punpckhbw   xmm5, i5                ; 48 58
+
+        movdqa      xmm6, i6
+        movdqa      xmm7, xmm6
+        punpcklbw   xmm6, i7                ; 60 70
+        punpckhbw   xmm7, i7                ; 68 78
+
+        movdqa      xmm8, xmm3
+        punpcklwd   xmm3, xmm6              ; 40 50 60 70
+        punpckhwd   xmm8, xmm6              ; 44 54 64 74
+
+        movdqa      xmm6, xmm5
+        punpcklwd   xmm5, xmm7              ; 48 58 68 78
+        punpckhwd   xmm6, xmm7              ; 4c 5c 6c 7c
+
+        ; pull the first two sets together
+
+        movdqa      xmm7, xmm0
+        punpckldq   xmm0, xmm3              ; 00 10 20 30 40 50 60 70
+        punpckhdq   xmm7, xmm3              ; 02 12 22 32 42 52 62 72
+
+        movdqa      xmm3, xmm4
+        punpckldq   xmm4, xmm8              ; 04 14 24 34 44 54 64 74
+        punpckhdq   xmm3, xmm8              ; 06 16 26 36 46 56 66 76
+
+        movdqa      xmm8, xmm1
+        punpckldq   xmm1, xmm5              ; 08 18 28 38 48 58 68 78
+        punpckhdq   xmm8, xmm5              ; 0a 1a 2a 3a 4a 5a 6a 7a
+
+        movdqa      xmm5, xmm2
+        punpckldq   xmm2, xmm6              ; 0c 1c 2c 3c 4c 5c 6c 7c
+        punpckhdq   xmm5, xmm6              ; 0e 1e 2e 3e 4e 5e 6e 7e
+        ; final combination
+
+        movdqa      xmm6, xmm0
+        punpcklqdq  xmm0, i8
+        punpckhqdq  xmm6, i8
+
+        movdqa      xmm9, xmm7
+        punpcklqdq  xmm7, i9
+        punpckhqdq  xmm9, i9
+
+        movdqa      xmm10, xmm4
+        punpcklqdq  xmm4, i10
+        punpckhqdq  xmm10, i10
+
+        movdqa      xmm11, xmm3
+        punpcklqdq  xmm3, i11
+        punpckhqdq  xmm11, i11
+
+        movdqa      xmm12, xmm1
+        punpcklqdq  xmm1, i12
+        punpckhqdq  xmm12, i12
+
+        movdqa      xmm13, xmm8
+        punpcklqdq  xmm8, i13
+        punpckhqdq  xmm13, i13
+
+        movdqa      xmm14, xmm2
+        punpcklqdq  xmm2, i14
+        punpckhqdq  xmm14, i14
+
+        movdqa      xmm15, xmm5
+        punpcklqdq  xmm5, i15
+        punpckhqdq  xmm15, i15
+
+        movdqa      s0, xmm0
+        movdqa      s1, xmm6
+        movdqa      s2, xmm7
+        movdqa      s3, xmm9
+        movdqa      s4, xmm4
+        movdqa      s5, xmm10
+        movdqa      s6, xmm3
+        movdqa      s7, xmm11
+        movdqa      s8, xmm1
+        movdqa      s9, xmm12
+        movdqa      s10, xmm8
+        movdqa      s11, xmm13
+        movdqa      s12, xmm2
+        movdqa      s13, xmm14
+        movdqa      s14, xmm5
+        movdqa      s15, xmm15
+
+    ; free stack space
+    add          rsp, stack_size
+
+    ; un-ALIGN_STACK
+    pop          rsp
+
+%ifidn __OUTPUT_FORMAT__,x64
+    pop    r13
+    pop    r12
+    RESTORE_XMM
+    pop    rbp
+%endif
+
+    ret
+
+SECTION_RODATA
+align 16
+te0:
+    times 16 db 0xe0
+align 16
+t7f:
+    times 16 db 0x7f
+align 16
+tfe:
+    times 16 db 0xfe
+align 16
+t1f:
+    times 16 db 0x1f
+align 16
+t80:
+    times 16 db 0x80
+align 16
+t1:
+    times 16 db 0x01
+align 16
+t3:
+    times 16 db 0x03
+align 16
+t4:
+    times 16 db 0x04
diff --git a/vp8/common/x86/loopfilter_mmx.asm b/vp8/common/x86/loopfilter_mmx.asm
new file mode 100644 (file)
index 0000000..697a5de
--- /dev/null
@@ -0,0 +1,1753 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+
+;void vp8_loop_filter_horizontal_edge_mmx
+;(
+;    unsigned char *src_ptr,
+;    int src_pixel_step,
+;    const char *blimit,
+;    const char *limit,
+;    const char *thresh,
+;    int  count
+;)
+global sym(vp8_loop_filter_horizontal_edge_mmx)
+sym(vp8_loop_filter_horizontal_edge_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub         rsp, 32                         ; reserve 32 bytes
+    %define t0 [rsp + 0]    ;__declspec(align(16)) char t0[8];
+    %define t1 [rsp + 16]   ;__declspec(align(16)) char t1[8];
+
+        mov         rsi, arg(0) ;src_ptr
+        movsxd      rax, dword ptr arg(1) ;src_pixel_step     ; destination pitch?
+
+        movsxd      rcx, dword ptr arg(5) ;count
+.next8_h:
+        mov         rdx, arg(3) ;limit
+        movq        mm7, [rdx]
+        mov         rdi, rsi              ; rdi points to row +1 for indirect addressing
+        add         rdi, rax
+
+        ; calculate breakout conditions
+        movq        mm2, [rdi+2*rax]      ; q3
+        movq        mm1, [rsi+2*rax]      ; q2
+        movq        mm6, mm1              ; q2
+        psubusb     mm1, mm2              ; q2-=q3
+        psubusb     mm2, mm6              ; q3-=q2
+        por         mm1, mm2              ; abs(q3-q2)
+        psubusb     mm1, mm7              ;
+
+
+        movq        mm4, [rsi+rax]        ; q1
+        movq        mm3, mm4              ; q1
+        psubusb     mm4, mm6              ; q1-=q2
+        psubusb     mm6, mm3              ; q2-=q1
+        por         mm4, mm6              ; abs(q2-q1)
+
+        psubusb     mm4, mm7
+        por        mm1, mm4
+
+        movq        mm4, [rsi]            ; q0
+        movq        mm0, mm4              ; q0
+        psubusb     mm4, mm3              ; q0-=q1
+        psubusb     mm3, mm0              ; q1-=q0
+        por         mm4, mm3              ; abs(q0-q1)
+        movq        t0, mm4               ; save to t0
+        psubusb     mm4, mm7
+        por        mm1, mm4
+
+
+        neg         rax                   ; negate pitch to deal with above border
+
+        movq        mm2, [rsi+4*rax]      ; p3
+        movq        mm4, [rdi+4*rax]      ; p2
+        movq        mm5, mm4              ; p2
+        psubusb     mm4, mm2              ; p2-=p3
+        psubusb     mm2, mm5              ; p3-=p2
+        por         mm4, mm2              ; abs(p3 - p2)
+        psubusb     mm4, mm7
+        por        mm1, mm4
+
+
+        movq        mm4, [rsi+2*rax]      ; p1
+        movq        mm3, mm4              ; p1
+        psubusb     mm4, mm5              ; p1-=p2
+        psubusb     mm5, mm3              ; p2-=p1
+        por         mm4, mm5              ; abs(p2 - p1)
+        psubusb     mm4, mm7
+        por        mm1, mm4
+
+        movq        mm2, mm3              ; p1
+
+        movq        mm4, [rsi+rax]        ; p0
+        movq        mm5, mm4              ; p0
+        psubusb     mm4, mm3              ; p0-=p1
+        psubusb     mm3, mm5              ; p1-=p0
+        por         mm4, mm3              ; abs(p1 - p0)
+        movq        t1, mm4               ; save to t1
+        psubusb     mm4, mm7
+        por        mm1, mm4
+
+        movq        mm3, [rdi]            ; q1
+        movq        mm4, mm3              ; q1
+        psubusb     mm3, mm2              ; q1-=p1
+        psubusb     mm2, mm4              ; p1-=q1
+        por         mm2, mm3              ; abs(p1-q1)
+        pand        mm2, [GLOBAL(tfe)]    ; set lsb of each byte to zero
+        psrlw       mm2, 1                ; abs(p1-q1)/2
+
+        movq        mm6, mm5              ; p0
+        movq        mm3, [rsi]            ; q0
+        psubusb     mm5, mm3              ; p0-=q0
+        psubusb     mm3, mm6              ; q0-=p0
+        por         mm5, mm3              ; abs(p0 - q0)
+        paddusb     mm5, mm5              ; abs(p0-q0)*2
+        paddusb     mm5, mm2              ; abs (p0 - q0) *2 + abs(p1-q1)/2
+
+        mov         rdx, arg(2) ;blimit           ; get blimit
+        movq        mm7, [rdx]            ; blimit
+
+        psubusb     mm5,    mm7           ; abs (p0 - q0) *2 + abs(p1-q1)/2  > blimit
+        por         mm1,    mm5
+        pxor        mm5,    mm5
+        pcmpeqb     mm1,    mm5           ; mask mm1
+
+        ; calculate high edge variance
+        mov         rdx, arg(4) ;thresh           ; get thresh
+        movq        mm7, [rdx]            ;
+        movq        mm4, t0               ; get abs (q1 - q0)
+        psubusb     mm4, mm7
+        movq        mm3, t1               ; get abs (p1 - p0)
+        psubusb     mm3, mm7
+        paddb       mm4, mm3              ; abs(q1 - q0) > thresh || abs(p1 - p0) > thresh
+
+        pcmpeqb     mm4,        mm5
+
+        pcmpeqb     mm5,        mm5
+        pxor        mm4,        mm5
+
+
+        ; start work on filters
+        movq        mm2, [rsi+2*rax]      ; p1
+        movq        mm7, [rdi]            ; q1
+        pxor        mm2, [GLOBAL(t80)]    ; p1 offset to convert to signed values
+        pxor        mm7, [GLOBAL(t80)]    ; q1 offset to convert to signed values
+        psubsb      mm2, mm7              ; p1 - q1
+        pand        mm2, mm4              ; high var mask (hvm)(p1 - q1)
+        pxor        mm6, [GLOBAL(t80)]    ; offset to convert to signed values
+        pxor        mm0, [GLOBAL(t80)]    ; offset to convert to signed values
+        movq        mm3, mm0              ; q0
+        psubsb      mm0, mm6              ; q0 - p0
+        paddsb      mm2, mm0              ; 1 * (q0 - p0) + hvm(p1 - q1)
+        paddsb      mm2, mm0              ; 2 * (q0 - p0) + hvm(p1 - q1)
+        paddsb      mm2, mm0              ; 3 * (q0 - p0) + hvm(p1 - q1)
+        pand        mm1, mm2                  ; mask filter values we don't care about
+        movq        mm2, mm1
+        paddsb      mm1, [GLOBAL(t4)]     ; 3* (q0 - p0) + hvm(p1 - q1) + 4
+        paddsb      mm2, [GLOBAL(t3)]     ; 3* (q0 - p0) + hvm(p1 - q1) + 3
+
+        pxor        mm0, mm0             ;
+        pxor        mm5, mm5
+        punpcklbw   mm0, mm2            ;
+        punpckhbw   mm5, mm2            ;
+        psraw       mm0, 11             ;
+        psraw       mm5, 11
+        packsswb    mm0, mm5
+        movq        mm2, mm0            ;  (3* (q0 - p0) + hvm(p1 - q1) + 3) >> 3;
+
+        pxor        mm0, mm0              ; 0
+        movq        mm5, mm1              ; abcdefgh
+        punpcklbw   mm0, mm1              ; e0f0g0h0
+        psraw       mm0, 11               ; sign extended shift right by 3
+        pxor        mm1, mm1              ; 0
+        punpckhbw   mm1, mm5              ; a0b0c0d0
+        psraw       mm1, 11               ; sign extended shift right by 3
+        movq        mm5, mm0              ; save results
+
+        packsswb    mm0, mm1              ; (3* (q0 - p0) + hvm(p1 - q1) + 4) >>3
+        paddsw      mm5, [GLOBAL(ones)]
+        paddsw      mm1, [GLOBAL(ones)]
+        psraw       mm5, 1                ; partial shifted one more time for 2nd tap
+        psraw       mm1, 1                ; partial shifted one more time for 2nd tap
+        packsswb    mm5, mm1              ; (3* (q0 - p0) + hvm(p1 - q1) + 4) >>4
+        pandn       mm4, mm5              ; high edge variance additive
+
+        paddsb      mm6, mm2              ; p0+= p0 add
+        pxor        mm6, [GLOBAL(t80)]    ; unoffset
+        movq        [rsi+rax], mm6        ; write back
+
+        movq        mm6, [rsi+2*rax]      ; p1
+        pxor        mm6, [GLOBAL(t80)]    ; reoffset
+        paddsb      mm6, mm4              ; p1+= p1 add
+        pxor        mm6, [GLOBAL(t80)]    ; unoffset
+        movq        [rsi+2*rax], mm6      ; write back
+
+        psubsb      mm3, mm0              ; q0-= q0 add
+        pxor        mm3, [GLOBAL(t80)]    ; unoffset
+        movq        [rsi], mm3            ; write back
+
+        psubsb      mm7, mm4              ; q1-= q1 add
+        pxor        mm7, [GLOBAL(t80)]    ; unoffset
+        movq        [rdi], mm7            ; write back
+
+        add         rsi,8
+        neg         rax
+        dec         rcx
+        jnz         .next8_h
+
+    add rsp, 32
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_loop_filter_vertical_edge_mmx
+;(
+;    unsigned char *src_ptr,
+;    int  src_pixel_step,
+;    const char *blimit,
+;    const char *limit,
+;    const char *thresh,
+;    int count
+;)
+global sym(vp8_loop_filter_vertical_edge_mmx)
+sym(vp8_loop_filter_vertical_edge_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub          rsp, 64      ; reserve 64 bytes
+    %define t0   [rsp + 0]    ;__declspec(align(16)) char t0[8];
+    %define t1   [rsp + 16]   ;__declspec(align(16)) char t1[8];
+    %define srct [rsp + 32]   ;__declspec(align(16)) char srct[32];
+
+        mov         rsi,        arg(0) ;src_ptr
+        movsxd      rax,        dword ptr arg(1) ;src_pixel_step     ; destination pitch?
+
+        lea         rsi,        [rsi + rax*4 - 4]
+
+        movsxd      rcx,        dword ptr arg(5) ;count
+.next8_v:
+        mov         rdi,        rsi           ; rdi points to row +1 for indirect addressing
+        add         rdi,        rax
+
+
+        ;transpose
+        movq        mm6,        [rsi+2*rax]                 ; 67 66 65 64 63 62 61 60
+        movq        mm7,        mm6                         ; 77 76 75 74 73 72 71 70
+
+        punpckhbw   mm7,        [rdi+2*rax]                 ; 77 67 76 66 75 65 74 64
+        punpcklbw   mm6,        [rdi+2*rax]                 ; 73 63 72 62 71 61 70 60
+
+        movq        mm4,        [rsi]                       ; 47 46 45 44 43 42 41 40
+        movq        mm5,        mm4                         ; 47 46 45 44 43 42 41 40
+
+        punpckhbw   mm5,        [rsi+rax]                   ; 57 47 56 46 55 45 54 44
+        punpcklbw   mm4,        [rsi+rax]                   ; 53 43 52 42 51 41 50 40
+
+        movq        mm3,        mm5                         ; 57 47 56 46 55 45 54 44
+        punpckhwd   mm5,        mm7                         ; 77 67 57 47 76 66 56 46
+
+        punpcklwd   mm3,        mm7                         ; 75 65 55 45 74 64 54 44
+        movq        mm2,        mm4                         ; 53 43 52 42 51 41 50 40
+
+        punpckhwd   mm4,        mm6                         ; 73 63 53 43 72 62 52 42
+        punpcklwd   mm2,        mm6                         ; 71 61 51 41 70 60 50 40
+
+        neg         rax
+        movq        mm6,        [rsi+rax*2]                 ; 27 26 25 24 23 22 21 20
+
+        movq        mm1,        mm6                         ; 27 26 25 24 23 22 21 20
+        punpckhbw   mm6,        [rsi+rax]                   ; 37 27 36 36 35 25 34 24
+
+        punpcklbw   mm1,        [rsi+rax]                   ; 33 23 32 22 31 21 30 20
+        movq        mm7,        [rsi+rax*4];                ; 07 06 05 04 03 02 01 00
+
+        punpckhbw   mm7,        [rdi+rax*4]                 ; 17 07 16 06 15 05 14 04
+        movq        mm0,        mm7                         ; 17 07 16 06 15 05 14 04
+
+        punpckhwd   mm7,        mm6                         ; 37 27 17 07 36 26 16 06
+        punpcklwd   mm0,        mm6                         ; 35 25 15 05 34 24 14 04
+
+        movq        mm6,        mm7                         ; 37 27 17 07 36 26 16 06
+        punpckhdq   mm7,        mm5                         ; 77 67 57 47 37 27 17 07  = q3
+
+        punpckldq   mm6,        mm5                         ; 76 66 56 46 36 26 16 06  = q2
+
+        movq        mm5,        mm6                         ; 76 66 56 46 36 26 16 06
+        psubusb     mm5,        mm7                         ; q2-q3
+
+        psubusb     mm7,        mm6                         ; q3-q2
+        por         mm7,        mm5;                        ; mm7=abs (q3-q2)
+
+        movq        mm5,        mm0                         ; 35 25 15 05 34 24 14 04
+        punpckhdq   mm5,        mm3                         ; 75 65 55 45 35 25 15 05 = q1
+
+        punpckldq   mm0,        mm3                         ; 74 64 54 44 34 24 15 04 = q0
+        movq        mm3,        mm5                         ; 75 65 55 45 35 25 15 05 = q1
+
+        psubusb     mm3,        mm6                         ; q1-q2
+        psubusb     mm6,        mm5                         ; q2-q1
+
+        por         mm6,        mm3                         ; mm6=abs(q2-q1)
+        lea         rdx,        srct
+
+        movq        [rdx+24],   mm5                         ; save q1
+        movq        [rdx+16],   mm0                         ; save q0
+
+        movq        mm3,        [rsi+rax*4]                 ; 07 06 05 04 03 02 01 00
+        punpcklbw   mm3,        [rdi+rax*4]                 ; 13 03 12 02 11 01 10 00
+
+        movq        mm0,        mm3                         ; 13 03 12 02 11 01 10 00
+        punpcklwd   mm0,        mm1                         ; 31 21 11 01 30 20 10 00
+
+        punpckhwd   mm3,        mm1                         ; 33 23 13 03 32 22 12 02
+        movq        mm1,        mm0                         ; 31 21 11 01 30 20 10 00
+
+        punpckldq   mm0,        mm2                         ; 70 60 50 40 30 20 10 00  =p3
+        punpckhdq   mm1,        mm2                         ; 71 61 51 41 31 21 11 01  =p2
+
+        movq        mm2,        mm1                         ; 71 61 51 41 31 21 11 01  =p2
+        psubusb     mm2,        mm0                         ; p2-p3
+
+        psubusb     mm0,        mm1                         ; p3-p2
+        por         mm0,        mm2                         ; mm0=abs(p3-p2)
+
+        movq        mm2,        mm3                         ; 33 23 13 03 32 22 12 02
+        punpckldq   mm2,        mm4                         ; 72 62 52 42 32 22 12 02 = p1
+
+        punpckhdq   mm3,        mm4                         ; 73 63 53 43 33 23 13 03 = p0
+        movq        [rdx+8],    mm3                         ; save p0
+
+        movq        [rdx],      mm2                         ; save p1
+        movq        mm5,        mm2                         ; mm5 = p1
+
+        psubusb     mm2,        mm1                         ; p1-p2
+        psubusb     mm1,        mm5                         ; p2-p1
+
+        por         mm1,        mm2                         ; mm1=abs(p2-p1)
+        mov         rdx,        arg(3) ;limit
+
+        movq        mm4,        [rdx]                       ; mm4 = limit
+        psubusb     mm7,        mm4
+
+        psubusb     mm0,        mm4
+        psubusb     mm1,        mm4
+
+        psubusb     mm6,        mm4
+        por         mm7,        mm6
+
+        por         mm0,        mm1
+        por         mm0,        mm7                         ;   abs(q3-q2) > limit || abs(p3-p2) > limit ||abs(p2-p1) > limit || abs(q2-q1) > limit
+
+        movq        mm1,        mm5                         ; p1
+
+        movq        mm7,        mm3                         ; mm3=mm7=p0
+        psubusb     mm7,        mm5                         ; p0 - p1
+
+        psubusb     mm5,        mm3                         ; p1 - p0
+        por         mm5,        mm7                         ; abs(p1-p0)
+
+        movq        t0,         mm5                         ; save abs(p1-p0)
+        lea         rdx,        srct
+
+        psubusb     mm5,        mm4
+        por         mm0,        mm5                         ; mm0=mask
+
+        movq        mm5,        [rdx+16]                    ; mm5=q0
+        movq        mm7,        [rdx+24]                    ; mm7=q1
+
+        movq        mm6,        mm5                         ; mm6=q0
+        movq        mm2,        mm7                         ; q1
+        psubusb     mm5,        mm7                         ; q0-q1
+
+        psubusb     mm7,        mm6                         ; q1-q0
+        por         mm7,        mm5                         ; abs(q1-q0)
+
+        movq        t1,         mm7                         ; save abs(q1-q0)
+        psubusb     mm7,        mm4
+
+        por         mm0,        mm7                         ; mask
+
+        movq        mm5,        mm2                         ; q1
+        psubusb     mm5,        mm1                         ; q1-=p1
+        psubusb     mm1,        mm2                         ; p1-=q1
+        por         mm5,        mm1                         ; abs(p1-q1)
+        pand        mm5,        [GLOBAL(tfe)]               ; set lsb of each byte to zero
+        psrlw       mm5,        1                           ; abs(p1-q1)/2
+
+        mov         rdx,        arg(2) ;blimit                      ;
+
+        movq        mm4,        [rdx]                       ;blimit
+        movq        mm1,        mm3                         ; mm1=mm3=p0
+
+        movq        mm7,        mm6                         ; mm7=mm6=q0
+        psubusb     mm1,        mm7                         ; p0-q0
+
+        psubusb     mm7,        mm3                         ; q0-p0
+        por         mm1,        mm7                         ; abs(q0-p0)
+        paddusb     mm1,        mm1                         ; abs(q0-p0)*2
+        paddusb     mm1,        mm5                         ; abs (p0 - q0) *2 + abs(p1-q1)/2
+
+        psubusb     mm1,        mm4                         ; abs (p0 - q0) *2 + abs(p1-q1)/2  > blimit
+        por         mm1,        mm0;                        ; mask
+
+        pxor        mm0,        mm0
+        pcmpeqb     mm1,        mm0
+
+        ; calculate high edge variance
+        mov         rdx,        arg(4) ;thresh            ; get thresh
+        movq        mm7,        [rdx]
+        ;
+        movq        mm4,        t0              ; get abs (q1 - q0)
+        psubusb     mm4,        mm7
+
+        movq        mm3,        t1              ; get abs (p1 - p0)
+        psubusb     mm3,        mm7
+
+        por         mm4,        mm3             ; abs(q1 - q0) > thresh || abs(p1 - p0) > thresh
+        pcmpeqb     mm4,        mm0
+
+        pcmpeqb     mm0,        mm0
+        pxor        mm4,        mm0
+
+
+
+        ; start work on filters
+        lea         rdx,        srct
+
+        movq        mm2,        [rdx]           ; p1
+        movq        mm7,        [rdx+24]        ; q1
+
+        movq        mm6,        [rdx+8]         ; p0
+        movq        mm0,        [rdx+16]        ; q0
+
+        pxor        mm2,        [GLOBAL(t80)]   ; p1 offset to convert to signed values
+        pxor        mm7,        [GLOBAL(t80)]   ; q1 offset to convert to signed values
+
+        psubsb      mm2,        mm7             ; p1 - q1
+        pand        mm2,        mm4             ; high var mask (hvm)(p1 - q1)
+
+        pxor        mm6,        [GLOBAL(t80)]   ; offset to convert to signed values
+        pxor        mm0,        [GLOBAL(t80)]   ; offset to convert to signed values
+
+        movq        mm3,        mm0             ; q0
+        psubsb      mm0,        mm6             ; q0 - p0
+
+        paddsb      mm2,        mm0             ; 1 * (q0 - p0) + hvm(p1 - q1)
+        paddsb      mm2,        mm0             ; 2 * (q0 - p0) + hvm(p1 - q1)
+
+        paddsb      mm2,        mm0             ; 3 * (q0 - p0) + hvm(p1 - q1)
+        pand       mm1,        mm2              ; mask filter values we don't care about
+
+        movq        mm2,        mm1
+        paddsb      mm1,        [GLOBAL(t4)]      ; 3* (q0 - p0) + hvm(p1 - q1) + 4
+
+        paddsb      mm2,        [GLOBAL(t3)]      ; 3* (q0 - p0) + hvm(p1 - q1) + 3
+        pxor        mm0,        mm0          ;
+
+        pxor        mm5,        mm5
+        punpcklbw   mm0,        mm2         ;
+
+        punpckhbw   mm5,        mm2         ;
+        psraw       mm0,        11              ;
+
+        psraw       mm5,        11
+        packsswb    mm0,        mm5
+
+        movq        mm2,        mm0         ;  (3* (q0 - p0) + hvm(p1 - q1) + 3) >> 3;
+
+        pxor        mm0,        mm0           ; 0
+        movq        mm5,        mm1           ; abcdefgh
+
+        punpcklbw   mm0,        mm1           ; e0f0g0h0
+        psraw       mm0,        11                ; sign extended shift right by 3
+
+        pxor        mm1,        mm1           ; 0
+        punpckhbw   mm1,        mm5           ; a0b0c0d0
+
+        psraw       mm1,        11                ; sign extended shift right by 3
+        movq        mm5,        mm0              ; save results
+
+        packsswb    mm0,        mm1           ; (3* (q0 - p0) + hvm(p1 - q1) + 4) >>3
+        paddsw      mm5,        [GLOBAL(ones)]
+
+        paddsw      mm1,        [GLOBAL(ones)]
+        psraw       mm5,        1                 ; partial shifted one more time for 2nd tap
+
+        psraw       mm1,        1                 ; partial shifted one more time for 2nd tap
+        packsswb    mm5,        mm1           ; (3* (q0 - p0) + hvm(p1 - q1) + 4) >>4
+
+        pandn       mm4,        mm5             ; high edge variance additive
+
+        paddsb      mm6,        mm2             ; p0+= p0 add
+        pxor        mm6,        [GLOBAL(t80)]   ; unoffset
+
+        ; mm6=p0                               ;
+        movq        mm1,        [rdx]           ; p1
+        pxor        mm1,        [GLOBAL(t80)]   ; reoffset
+
+        paddsb      mm1,        mm4                 ; p1+= p1 add
+        pxor        mm1,        [GLOBAL(t80)]       ; unoffset
+        ; mm6 = p0 mm1 = p1
+
+        psubsb      mm3,        mm0                 ; q0-= q0 add
+        pxor        mm3,        [GLOBAL(t80)]       ; unoffset
+
+        ; mm3 = q0
+        psubsb      mm7,        mm4                 ; q1-= q1 add
+        pxor        mm7,        [GLOBAL(t80)]       ; unoffset
+        ; mm7 = q1
+
+        ; tranpose and write back
+        ; mm1 =    72 62 52 42 32 22 12 02
+        ; mm6 =    73 63 53 43 33 23 13 03
+        ; mm3 =    74 64 54 44 34 24 14 04
+        ; mm7 =    75 65 55 45 35 25 15 05
+
+        movq        mm2,        mm1             ; 72 62 52 42 32 22 12 02
+        punpcklbw   mm2,        mm6             ; 33 32 23 22 13 12 03 02
+
+        movq        mm4,        mm3             ; 74 64 54 44 34 24 14 04
+        punpckhbw   mm1,        mm6             ; 73 72 63 62 53 52 43 42
+
+        punpcklbw   mm4,        mm7             ; 35 34 25 24 15 14 05 04
+        punpckhbw   mm3,        mm7             ; 75 74 65 64 55 54 45 44
+
+        movq        mm6,        mm2             ; 33 32 23 22 13 12 03 02
+        punpcklwd   mm2,        mm4             ; 15 14 13 12 05 04 03 02
+
+        punpckhwd   mm6,        mm4             ; 35 34 33 32 25 24 23 22
+        movq        mm5,        mm1             ; 73 72 63 62 53 52 43 42
+
+        punpcklwd   mm1,        mm3             ; 55 54 53 52 45 44 43 42
+        punpckhwd   mm5,        mm3             ; 75 74 73 72 65 64 63 62
+
+
+        ; mm2 = 15 14 13 12 05 04 03 02
+        ; mm6 = 35 34 33 32 25 24 23 22
+        ; mm5 = 55 54 53 52 45 44 43 42
+        ; mm1 = 75 74 73 72 65 64 63 62
+
+
+
+        movd        [rsi+rax*4+2], mm2
+        psrlq       mm2,        32
+
+        movd        [rdi+rax*4+2], mm2
+        movd        [rsi+rax*2+2], mm6
+
+        psrlq       mm6,        32
+        movd        [rsi+rax+2],mm6
+
+        movd        [rsi+2],    mm1
+        psrlq       mm1,        32
+
+        movd        [rdi+2],    mm1
+        neg         rax
+
+        movd        [rdi+rax+2],mm5
+        psrlq       mm5,        32
+
+        movd        [rdi+rax*2+2], mm5
+
+        lea         rsi,        [rsi+rax*8]
+        dec         rcx
+        jnz         .next8_v
+
+    add rsp, 64
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_mbloop_filter_horizontal_edge_mmx
+;(
+;    unsigned char *src_ptr,
+;    int  src_pixel_step,
+;    const char *blimit,
+;    const char *limit,
+;    const char *thresh,
+;    int count
+;)
+global sym(vp8_mbloop_filter_horizontal_edge_mmx)
+sym(vp8_mbloop_filter_horizontal_edge_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub          rsp, 32      ; reserve 32 bytes
+    %define t0   [rsp + 0]    ;__declspec(align(16)) char t0[8];
+    %define t1   [rsp + 16]   ;__declspec(align(16)) char t1[8];
+
+        mov         rsi, arg(0) ;src_ptr
+        movsxd      rax, dword ptr arg(1) ;src_pixel_step     ; destination pitch?
+
+        movsxd      rcx, dword ptr arg(5) ;count
+.next8_mbh:
+        mov         rdx, arg(3) ;limit
+        movq        mm7, [rdx]
+        mov         rdi, rsi              ; rdi points to row +1 for indirect addressing
+        add         rdi, rax
+
+        ; calculate breakout conditions
+        movq        mm2, [rdi+2*rax]      ; q3
+
+        movq        mm1, [rsi+2*rax]      ; q2
+        movq        mm6, mm1              ; q2
+        psubusb     mm1, mm2              ; q2-=q3
+        psubusb     mm2, mm6              ; q3-=q2
+        por         mm1, mm2              ; abs(q3-q2)
+        psubusb     mm1, mm7
+
+
+        ; mm1 = abs(q3-q2), mm6 =q2, mm7 = limit
+        movq        mm4, [rsi+rax]        ; q1
+        movq        mm3, mm4              ; q1
+        psubusb     mm4, mm6              ; q1-=q2
+        psubusb     mm6, mm3              ; q2-=q1
+        por         mm4, mm6              ; abs(q2-q1)
+        psubusb     mm4, mm7
+        por        mm1, mm4
+
+
+        ; mm1 = mask,      mm3=q1, mm7 = limit
+
+        movq        mm4, [rsi]            ; q0
+        movq        mm0, mm4              ; q0
+        psubusb     mm4, mm3              ; q0-=q1
+        psubusb     mm3, mm0              ; q1-=q0
+        por         mm4, mm3              ; abs(q0-q1)
+        movq        t0, mm4               ; save to t0
+        psubusb     mm4, mm7
+        por        mm1, mm4
+
+
+        ; mm1 = mask, mm0=q0,  mm7 = limit, t0 = abs(q0-q1)
+
+        neg         rax                   ; negate pitch to deal with above border
+
+        movq        mm2, [rsi+4*rax]      ; p3
+        movq        mm4, [rdi+4*rax]      ; p2
+        movq        mm5, mm4              ; p2
+        psubusb     mm4, mm2              ; p2-=p3
+        psubusb     mm2, mm5              ; p3-=p2
+        por         mm4, mm2              ; abs(p3 - p2)
+        psubusb     mm4, mm7
+        por        mm1, mm4
+        ; mm1 = mask, mm0=q0,  mm7 = limit, t0 = abs(q0-q1)
+
+        movq        mm4, [rsi+2*rax]      ; p1
+        movq        mm3, mm4              ; p1
+        psubusb     mm4, mm5              ; p1-=p2
+        psubusb     mm5, mm3              ; p2-=p1
+        por         mm4, mm5              ; abs(p2 - p1)
+        psubusb     mm4, mm7
+        por        mm1, mm4
+
+        movq        mm2, mm3              ; p1
+
+
+        ; mm1 = mask, mm0=q0,  mm7 = limit, t0 = abs(q0-q1)
+
+        movq        mm4, [rsi+rax]        ; p0
+        movq        mm5, mm4              ; p0
+        psubusb     mm4, mm3              ; p0-=p1
+        psubusb     mm3, mm5              ; p1-=p0
+        por         mm4, mm3              ; abs(p1 - p0)
+        movq        t1, mm4               ; save to t1
+        psubusb     mm4, mm7
+        por        mm1, mm4
+        ; mm1 = mask, mm0=q0,  mm7 = limit, t0 = abs(q0-q1) t1 = abs(p1-p0)
+        ; mm5 = p0
+        movq        mm3, [rdi]            ; q1
+        movq        mm4, mm3              ; q1
+        psubusb     mm3, mm2              ; q1-=p1
+        psubusb     mm2, mm4              ; p1-=q1
+        por         mm2, mm3              ; abs(p1-q1)
+        pand        mm2, [GLOBAL(tfe)]    ; set lsb of each byte to zero
+        psrlw       mm2, 1                ; abs(p1-q1)/2
+
+        movq        mm6, mm5              ; p0
+        movq        mm3, mm0              ; q0
+        psubusb     mm5, mm3              ; p0-=q0
+        psubusb     mm3, mm6              ; q0-=p0
+        por         mm5, mm3              ; abs(p0 - q0)
+        paddusb     mm5, mm5              ; abs(p0-q0)*2
+        paddusb     mm5, mm2              ; abs (p0 - q0) *2 + abs(p1-q1)/2
+
+        mov         rdx, arg(2) ;blimit           ; get blimit
+        movq        mm7, [rdx]            ; blimit
+
+        psubusb     mm5,    mm7           ; abs (p0 - q0) *2 + abs(p1-q1)/2  > blimit
+        por         mm1,    mm5
+        pxor        mm5,    mm5
+        pcmpeqb     mm1,    mm5           ; mask mm1
+
+        ; mm1 = mask, mm0=q0,  mm7 = blimit, t0 = abs(q0-q1) t1 = abs(p1-p0)
+        ; mm6 = p0,
+
+        ; calculate high edge variance
+        mov         rdx, arg(4) ;thresh           ; get thresh
+        movq        mm7, [rdx]            ;
+        movq        mm4, t0               ; get abs (q1 - q0)
+        psubusb     mm4, mm7
+        movq        mm3, t1               ; get abs (p1 - p0)
+        psubusb     mm3, mm7
+        paddb       mm4, mm3              ; abs(q1 - q0) > thresh || abs(p1 - p0) > thresh
+
+        pcmpeqb     mm4,        mm5
+
+        pcmpeqb     mm5,        mm5
+        pxor        mm4,        mm5
+
+
+
+        ; mm1 = mask, mm0=q0,  mm7 = thresh, t0 = abs(q0-q1) t1 = abs(p1-p0)
+        ; mm6 = p0, mm4=hev
+        ; start work on filters
+        movq        mm2, [rsi+2*rax]      ; p1
+        movq        mm7, [rdi]            ; q1
+        pxor        mm2, [GLOBAL(t80)]    ; p1 offset to convert to signed values
+        pxor        mm7, [GLOBAL(t80)]    ; q1 offset to convert to signed values
+        psubsb      mm2, mm7              ; p1 - q1
+
+        pxor        mm6, [GLOBAL(t80)]    ; offset to convert to signed values
+        pxor        mm0, [GLOBAL(t80)]    ; offset to convert to signed values
+        movq        mm3, mm0              ; q0
+        psubsb      mm0, mm6              ; q0 - p0
+        paddsb      mm2, mm0              ; 1 * (q0 - p0) + (p1 - q1)
+        paddsb      mm2, mm0              ; 2 * (q0 - p0)
+        paddsb      mm2, mm0              ; 3 * (q0 - p0) + (p1 - q1)
+        pand        mm1, mm2              ; mask filter values we don't care about
+
+
+        ; mm1 = vp8_filter, mm4=hev, mm6=ps0, mm3=qs0
+        movq        mm2, mm1              ; vp8_filter
+        pand        mm2, mm4;             ; Filter2 = vp8_filter & hev
+
+        movq        mm5,        mm2       ;
+        paddsb      mm5,        [GLOBAL(t3)];
+
+        pxor        mm0, mm0              ; 0
+        pxor        mm7, mm7              ; 0
+
+        punpcklbw   mm0, mm5              ; e0f0g0h0
+        psraw       mm0, 11               ; sign extended shift right by 3
+        punpckhbw   mm7, mm5              ; a0b0c0d0
+        psraw       mm7, 11               ; sign extended shift right by 3
+        packsswb    mm0, mm7              ; Filter2 >>=3;
+
+        movq        mm5, mm0              ; Filter2
+
+        paddsb      mm2, [GLOBAL(t4)]     ; vp8_signed_char_clamp(Filter2 + 4)
+        pxor        mm0, mm0              ; 0
+        pxor        mm7, mm7              ; 0
+
+        punpcklbw   mm0, mm2              ; e0f0g0h0
+        psraw       mm0, 11               ; sign extended shift right by 3
+        punpckhbw   mm7, mm2              ; a0b0c0d0
+        psraw       mm7, 11               ; sign extended shift right by 3
+        packsswb    mm0, mm7              ; Filter2 >>=3;
+
+        ; mm0= filter2 mm1 = vp8_filter,  mm3 =qs0 mm5=s mm4 =hev mm6=ps0
+        psubsb      mm3, mm0              ; qs0 =qs0 - filter1
+        paddsb      mm6, mm5              ; ps0 =ps0 + Fitler2
+
+        ; mm1=vp8_filter, mm3=qs0, mm4 =hev mm6=ps0
+        ; vp8_filter &= ~hev;
+        ; Filter2 = vp8_filter;
+        pandn       mm4, mm1              ; vp8_filter&=~hev
+
+
+        ; mm3=qs0, mm4=filter2, mm6=ps0
+
+        ; u = vp8_signed_char_clamp((63 + Filter2 * 27)>>7);
+        ; s = vp8_signed_char_clamp(qs0 - u);
+        ; *oq0 = s^0x80;
+        ; s = vp8_signed_char_clamp(ps0 + u);
+        ; *op0 = s^0x80;
+        pxor        mm0, mm0
+
+        pxor        mm1, mm1
+        pxor        mm2, mm2
+        punpcklbw   mm1, mm4
+        punpckhbw   mm2, mm4
+        pmulhw      mm1, [GLOBAL(s27)]
+        pmulhw      mm2, [GLOBAL(s27)]
+        paddw       mm1, [GLOBAL(s63)]
+        paddw       mm2, [GLOBAL(s63)]
+        psraw       mm1, 7
+        psraw       mm2, 7
+        packsswb    mm1, mm2
+
+        psubsb      mm3, mm1
+        paddsb      mm6, mm1
+
+        pxor        mm3, [GLOBAL(t80)]
+        pxor        mm6, [GLOBAL(t80)]
+        movq        [rsi+rax], mm6
+        movq        [rsi],     mm3
+
+        ; roughly 2/7th difference across boundary
+        ; u = vp8_signed_char_clamp((63 + Filter2 * 18)>>7);
+        ; s = vp8_signed_char_clamp(qs1 - u);
+        ; *oq1 = s^0x80;
+        ; s = vp8_signed_char_clamp(ps1 + u);
+        ; *op1 = s^0x80;
+        pxor        mm1, mm1
+        pxor        mm2, mm2
+        punpcklbw   mm1, mm4
+        punpckhbw   mm2, mm4
+        pmulhw      mm1, [GLOBAL(s18)]
+        pmulhw      mm2, [GLOBAL(s18)]
+        paddw       mm1, [GLOBAL(s63)]
+        paddw       mm2, [GLOBAL(s63)]
+        psraw       mm1, 7
+        psraw       mm2, 7
+        packsswb    mm1, mm2
+
+        movq        mm3, [rdi]
+        movq        mm6, [rsi+rax*2]       ; p1
+
+        pxor        mm3, [GLOBAL(t80)]
+        pxor        mm6, [GLOBAL(t80)]
+
+        paddsb      mm6, mm1
+        psubsb      mm3, mm1
+
+        pxor        mm6, [GLOBAL(t80)]
+        pxor        mm3, [GLOBAL(t80)]
+        movq        [rdi], mm3
+        movq        [rsi+rax*2], mm6
+
+        ; roughly 1/7th difference across boundary
+        ; u = vp8_signed_char_clamp((63 + Filter2 * 9)>>7);
+        ; s = vp8_signed_char_clamp(qs2 - u);
+        ; *oq2 = s^0x80;
+        ; s = vp8_signed_char_clamp(ps2 + u);
+        ; *op2 = s^0x80;
+        pxor        mm1, mm1
+        pxor        mm2, mm2
+        punpcklbw   mm1, mm4
+        punpckhbw   mm2, mm4
+        pmulhw      mm1, [GLOBAL(s9)]
+        pmulhw      mm2, [GLOBAL(s9)]
+        paddw       mm1, [GLOBAL(s63)]
+        paddw       mm2, [GLOBAL(s63)]
+        psraw       mm1, 7
+        psraw       mm2, 7
+        packsswb    mm1, mm2
+
+
+        movq        mm6, [rdi+rax*4]
+        neg         rax
+        movq        mm3, [rdi+rax  ]
+
+        pxor        mm6, [GLOBAL(t80)]
+        pxor        mm3, [GLOBAL(t80)]
+
+        paddsb      mm6, mm1
+        psubsb      mm3, mm1
+
+        pxor        mm6, [GLOBAL(t80)]
+        pxor        mm3, [GLOBAL(t80)]
+        movq        [rdi+rax  ], mm3
+        neg         rax
+        movq        [rdi+rax*4], mm6
+
+;EARLY_BREAK_OUT:
+        neg         rax
+        add         rsi,8
+        dec         rcx
+        jnz         .next8_mbh
+
+    add rsp, 32
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_mbloop_filter_vertical_edge_mmx
+;(
+;    unsigned char *src_ptr,
+;    int  src_pixel_step,
+;    const char *blimit,
+;    const char *limit,
+;    const char *thresh,
+;    int count
+;)
+global sym(vp8_mbloop_filter_vertical_edge_mmx)
+sym(vp8_mbloop_filter_vertical_edge_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub          rsp, 96      ; reserve 96 bytes
+    %define t0   [rsp + 0]    ;__declspec(align(16)) char t0[8];
+    %define t1   [rsp + 16]   ;__declspec(align(16)) char t1[8];
+    %define srct [rsp + 32]   ;__declspec(align(16)) char srct[64];
+
+        mov         rsi,        arg(0) ;src_ptr
+        movsxd      rax,        dword ptr arg(1) ;src_pixel_step     ; destination pitch?
+
+        lea         rsi,        [rsi + rax*4 - 4]
+
+        movsxd      rcx,        dword ptr arg(5) ;count
+.next8_mbv:
+        lea         rdi,        [rsi + rax]  ; rdi points to row +1 for indirect addressing
+
+        ;transpose
+        movq        mm0,        [rdi+2*rax]                 ; 77 76 75 74 73 72 71 70
+        movq        mm6,        [rsi+2*rax]                 ; 67 66 65 64 63 62 61 60
+
+        movq        mm7,        mm6                         ; 77 76 75 74 73 72 71 70
+        punpckhbw   mm7,        mm0                         ; 77 67 76 66 75 65 74 64
+
+        punpcklbw   mm6,        mm0                         ; 73 63 72 62 71 61 70 60
+        movq        mm0,        [rsi+rax]                   ; 57 56 55 54 53 52 51 50
+
+        movq        mm4,        [rsi]                       ; 47 46 45 44 43 42 41 40
+        movq        mm5,        mm4                         ; 47 46 45 44 43 42 41 40
+
+        punpckhbw   mm5,        mm0                         ; 57 47 56 46 55 45 54 44
+        punpcklbw   mm4,        mm0                         ; 53 43 52 42 51 41 50 40
+
+        movq        mm3,        mm5                         ; 57 47 56 46 55 45 54 44
+        punpckhwd   mm5,        mm7                         ; 77 67 57 47 76 66 56 46
+
+        punpcklwd   mm3,        mm7                         ; 75 65 55 45 74 64 54 44
+        movq        mm2,        mm4                         ; 53 43 52 42 51 41 50 40
+
+        punpckhwd   mm4,        mm6                         ; 73 63 53 43 72 62 52 42
+        punpcklwd   mm2,        mm6                         ; 71 61 51 41 70 60 50 40
+
+        neg         rax
+
+        movq        mm7,        [rsi+rax]                   ; 37 36 35 34 33 32 31 30
+        movq        mm6,        [rsi+rax*2]                 ; 27 26 25 24 23 22 21 20
+
+        movq        mm1,        mm6                         ; 27 26 25 24 23 22 21 20
+        punpckhbw   mm6,        mm7                         ; 37 27 36 36 35 25 34 24
+
+        punpcklbw   mm1,        mm7                         ; 33 23 32 22 31 21 30 20
+
+        movq        mm7,        [rsi+rax*4];                ; 07 06 05 04 03 02 01 00
+        punpckhbw   mm7,        [rdi+rax*4]                 ; 17 07 16 06 15 05 14 04
+
+        movq        mm0,        mm7                         ; 17 07 16 06 15 05 14 04
+        punpckhwd   mm7,        mm6                         ; 37 27 17 07 36 26 16 06
+
+        punpcklwd   mm0,        mm6                         ; 35 25 15 05 34 24 14 04
+        movq        mm6,        mm7                         ; 37 27 17 07 36 26 16 06
+
+        punpckhdq   mm7,        mm5                         ; 77 67 57 47 37 27 17 07  = q3
+        punpckldq   mm6,        mm5                         ; 76 66 56 46 36 26 16 06  = q2
+
+        lea         rdx,        srct
+        movq        mm5,        mm6                         ; 76 66 56 46 36 26 16 06
+
+        movq        [rdx+56],   mm7
+        psubusb     mm5,        mm7                         ; q2-q3
+
+
+        movq        [rdx+48],   mm6
+        psubusb     mm7,        mm6                         ; q3-q2
+
+        por         mm7,        mm5;                        ; mm7=abs (q3-q2)
+        movq        mm5,        mm0                         ; 35 25 15 05 34 24 14 04
+
+        punpckhdq   mm5,        mm3                         ; 75 65 55 45 35 25 15 05 = q1
+        punpckldq   mm0,        mm3                         ; 74 64 54 44 34 24 15 04 = q0
+
+        movq        mm3,        mm5                         ; 75 65 55 45 35 25 15 05 = q1
+        psubusb     mm3,        mm6                         ; q1-q2
+
+        psubusb     mm6,        mm5                         ; q2-q1
+        por         mm6,        mm3                         ; mm6=abs(q2-q1)
+
+        movq        [rdx+40],   mm5                         ; save q1
+        movq        [rdx+32],   mm0                         ; save q0
+
+        movq        mm3,        [rsi+rax*4]                 ; 07 06 05 04 03 02 01 00
+        punpcklbw   mm3,        [rdi+rax*4]                 ; 13 03 12 02 11 01 10 00
+
+        movq        mm0,        mm3                         ; 13 03 12 02 11 01 10 00
+        punpcklwd   mm0,        mm1                         ; 31 21 11 01 30 20 10 00
+
+        punpckhwd   mm3,        mm1                         ; 33 23 13 03 32 22 12 02
+        movq        mm1,        mm0                         ; 31 21 11 01 30 20 10 00
+
+        punpckldq   mm0,        mm2                         ; 70 60 50 40 30 20 10 00  =p3
+        punpckhdq   mm1,        mm2                         ; 71 61 51 41 31 21 11 01  =p2
+
+        movq        [rdx],      mm0                         ; save p3
+        movq        [rdx+8],    mm1                         ; save p2
+
+        movq        mm2,        mm1                         ; 71 61 51 41 31 21 11 01  =p2
+        psubusb     mm2,        mm0                         ; p2-p3
+
+        psubusb     mm0,        mm1                         ; p3-p2
+        por         mm0,        mm2                         ; mm0=abs(p3-p2)
+
+        movq        mm2,        mm3                         ; 33 23 13 03 32 22 12 02
+        punpckldq   mm2,        mm4                         ; 72 62 52 42 32 22 12 02 = p1
+
+        punpckhdq   mm3,        mm4                         ; 73 63 53 43 33 23 13 03 = p0
+        movq        [rdx+24],   mm3                         ; save p0
+
+        movq        [rdx+16],   mm2                         ; save p1
+        movq        mm5,        mm2                         ; mm5 = p1
+
+        psubusb     mm2,        mm1                         ; p1-p2
+        psubusb     mm1,        mm5                         ; p2-p1
+
+        por         mm1,        mm2                         ; mm1=abs(p2-p1)
+        mov         rdx,        arg(3) ;limit
+
+        movq        mm4,        [rdx]                       ; mm4 = limit
+        psubusb     mm7,        mm4                         ; abs(q3-q2) > limit
+
+        psubusb     mm0,        mm4                         ; abs(p3-p2) > limit
+        psubusb     mm1,        mm4                         ; abs(p2-p1) > limit
+
+        psubusb     mm6,        mm4                         ; abs(q2-q1) > limit
+        por         mm7,        mm6                         ; or
+
+        por         mm0,        mm1                         ;
+        por         mm0,        mm7                         ; abs(q3-q2) > limit || abs(p3-p2) > limit ||abs(p2-p1) > limit || abs(q2-q1) > limit
+
+        movq        mm1,        mm5                         ; p1
+
+        movq        mm7,        mm3                         ; mm3=mm7=p0
+        psubusb     mm7,        mm5                         ; p0 - p1
+
+        psubusb     mm5,        mm3                         ; p1 - p0
+        por         mm5,        mm7                         ; abs(p1-p0)
+
+        movq        t0,         mm5                         ; save abs(p1-p0)
+        lea         rdx,        srct
+
+        psubusb     mm5,        mm4                         ; mm5 = abs(p1-p0) > limit
+        por         mm0,        mm5                         ; mm0=mask
+
+        movq        mm5,        [rdx+32]                    ; mm5=q0
+        movq        mm7,        [rdx+40]                    ; mm7=q1
+
+        movq        mm6,        mm5                         ; mm6=q0
+        movq        mm2,        mm7                         ; q1
+        psubusb     mm5,        mm7                         ; q0-q1
+
+        psubusb     mm7,        mm6                         ; q1-q0
+        por         mm7,        mm5                         ; abs(q1-q0)
+
+        movq        t1,         mm7                         ; save abs(q1-q0)
+        psubusb     mm7,        mm4                         ; mm7=abs(q1-q0)> limit
+
+        por         mm0,        mm7                         ; mask
+
+        movq        mm5,        mm2                         ; q1
+        psubusb     mm5,        mm1                         ; q1-=p1
+        psubusb     mm1,        mm2                         ; p1-=q1
+        por         mm5,        mm1                         ; abs(p1-q1)
+        pand        mm5,        [GLOBAL(tfe)]               ; set lsb of each byte to zero
+        psrlw       mm5,        1                           ; abs(p1-q1)/2
+
+        mov         rdx,        arg(2) ;blimit                      ;
+
+        movq        mm4,        [rdx]                       ;blimit
+        movq        mm1,        mm3                         ; mm1=mm3=p0
+
+        movq        mm7,        mm6                         ; mm7=mm6=q0
+        psubusb     mm1,        mm7                         ; p0-q0
+
+        psubusb     mm7,        mm3                         ; q0-p0
+        por         mm1,        mm7                         ; abs(q0-p0)
+        paddusb     mm1,        mm1                         ; abs(q0-p0)*2
+        paddusb     mm1,        mm5                         ; abs (p0 - q0) *2 + abs(p1-q1)/2
+
+        psubusb     mm1,        mm4                         ; abs (p0 - q0) *2 + abs(p1-q1)/2  > blimit
+        por         mm1,        mm0;                        ; mask
+
+        pxor        mm0,        mm0
+        pcmpeqb     mm1,        mm0
+
+        ; calculate high edge variance
+        mov         rdx,        arg(4) ;thresh            ; get thresh
+        movq        mm7,        [rdx]
+        ;
+        movq        mm4,        t0              ; get abs (q1 - q0)
+        psubusb     mm4,        mm7             ; abs(q1 - q0) > thresh
+
+        movq        mm3,        t1              ; get abs (p1 - p0)
+        psubusb     mm3,        mm7             ; abs(p1 - p0)> thresh
+
+        por         mm4,        mm3             ; abs(q1 - q0) > thresh || abs(p1 - p0) > thresh
+        pcmpeqb     mm4,        mm0
+
+        pcmpeqb     mm0,        mm0
+        pxor        mm4,        mm0
+
+
+
+
+        ; start work on filters
+        lea         rdx,        srct
+
+        ; start work on filters
+        movq        mm2, [rdx+16]         ; p1
+        movq        mm7, [rdx+40]         ; q1
+        pxor        mm2, [GLOBAL(t80)]    ; p1 offset to convert to signed values
+        pxor        mm7, [GLOBAL(t80)]    ; q1 offset to convert to signed values
+        psubsb      mm2, mm7              ; p1 - q1
+
+        movq        mm6, [rdx+24]         ; p0
+        movq        mm0, [rdx+32]         ; q0
+        pxor        mm6, [GLOBAL(t80)]    ; offset to convert to signed values
+        pxor        mm0, [GLOBAL(t80)]    ; offset to convert to signed values
+
+        movq        mm3, mm0              ; q0
+        psubsb      mm0, mm6              ; q0 - p0
+        paddsb      mm2, mm0              ; 1 * (q0 - p0) + (p1 - q1)
+        paddsb      mm2, mm0              ; 2 * (q0 - p0)
+        paddsb      mm2, mm0              ; 3 * (q0 - p0) + (p1 - q1)
+        pand       mm1, mm2           ; mask filter values we don't care about
+
+        ; mm1 = vp8_filter, mm4=hev, mm6=ps0, mm3=qs0
+        movq        mm2, mm1              ; vp8_filter
+        pand        mm2, mm4;             ; Filter2 = vp8_filter & hev
+
+        movq        mm5,        mm2       ;
+        paddsb      mm5,        [GLOBAL(t3)];
+
+        pxor        mm0, mm0              ; 0
+        pxor        mm7, mm7              ; 0
+
+        punpcklbw   mm0, mm5              ; e0f0g0h0
+        psraw       mm0, 11               ; sign extended shift right by 3
+        punpckhbw   mm7, mm5              ; a0b0c0d0
+        psraw       mm7, 11               ; sign extended shift right by 3
+        packsswb    mm0, mm7              ; Filter2 >>=3;
+
+        movq        mm5, mm0              ; Filter2
+
+        paddsb      mm2, [GLOBAL(t4)]     ; vp8_signed_char_clamp(Filter2 + 4)
+        pxor        mm0, mm0              ; 0
+        pxor        mm7, mm7              ; 0
+
+        punpcklbw   mm0, mm2              ; e0f0g0h0
+        psraw       mm0, 11               ; sign extended shift right by 3
+        punpckhbw   mm7, mm2              ; a0b0c0d0
+        psraw       mm7, 11               ; sign extended shift right by 3
+        packsswb    mm0, mm7              ; Filter2 >>=3;
+
+        ; mm0= filter2 mm1 = vp8_filter,  mm3 =qs0 mm5=s mm4 =hev mm6=ps0
+        psubsb      mm3, mm0              ; qs0 =qs0 - filter1
+        paddsb      mm6, mm5              ; ps0 =ps0 + Fitler2
+
+        ; mm1=vp8_filter, mm3=qs0, mm4 =hev mm6=ps0
+        ; vp8_filter &= ~hev;
+        ; Filter2 = vp8_filter;
+        pandn       mm4, mm1              ; vp8_filter&=~hev
+
+
+        ; mm3=qs0, mm4=filter2, mm6=ps0
+
+        ; u = vp8_signed_char_clamp((63 + Filter2 * 27)>>7);
+        ; s = vp8_signed_char_clamp(qs0 - u);
+        ; *oq0 = s^0x80;
+        ; s = vp8_signed_char_clamp(ps0 + u);
+        ; *op0 = s^0x80;
+        pxor        mm0, mm0
+
+        pxor        mm1, mm1
+        pxor        mm2, mm2
+        punpcklbw   mm1, mm4
+        punpckhbw   mm2, mm4
+        pmulhw      mm1, [GLOBAL(s27)]
+        pmulhw      mm2, [GLOBAL(s27)]
+        paddw       mm1, [GLOBAL(s63)]
+        paddw       mm2, [GLOBAL(s63)]
+        psraw       mm1, 7
+        psraw       mm2, 7
+        packsswb    mm1, mm2
+
+        psubsb      mm3, mm1
+        paddsb      mm6, mm1
+
+        pxor        mm3, [GLOBAL(t80)]
+        pxor        mm6, [GLOBAL(t80)]
+        movq        [rdx+24], mm6
+        movq        [rdx+32], mm3
+
+        ; roughly 2/7th difference across boundary
+        ; u = vp8_signed_char_clamp((63 + Filter2 * 18)>>7);
+        ; s = vp8_signed_char_clamp(qs1 - u);
+        ; *oq1 = s^0x80;
+        ; s = vp8_signed_char_clamp(ps1 + u);
+        ; *op1 = s^0x80;
+        pxor        mm1, mm1
+        pxor        mm2, mm2
+        punpcklbw   mm1, mm4
+        punpckhbw   mm2, mm4
+        pmulhw      mm1, [GLOBAL(s18)]
+        pmulhw      mm2, [GLOBAL(s18)]
+        paddw       mm1, [GLOBAL(s63)]
+        paddw       mm2, [GLOBAL(s63)]
+        psraw       mm1, 7
+        psraw       mm2, 7
+        packsswb    mm1, mm2
+
+        movq        mm3, [rdx + 40]
+        movq        mm6, [rdx + 16]       ; p1
+        pxor        mm3, [GLOBAL(t80)]
+        pxor        mm6, [GLOBAL(t80)]
+
+        paddsb      mm6, mm1
+        psubsb      mm3, mm1
+
+        pxor        mm6, [GLOBAL(t80)]
+        pxor        mm3, [GLOBAL(t80)]
+        movq        [rdx + 40], mm3
+        movq        [rdx + 16], mm6
+
+        ; roughly 1/7th difference across boundary
+        ; u = vp8_signed_char_clamp((63 + Filter2 * 9)>>7);
+        ; s = vp8_signed_char_clamp(qs2 - u);
+        ; *oq2 = s^0x80;
+        ; s = vp8_signed_char_clamp(ps2 + u);
+        ; *op2 = s^0x80;
+        pxor        mm1, mm1
+        pxor        mm2, mm2
+        punpcklbw   mm1, mm4
+        punpckhbw   mm2, mm4
+        pmulhw      mm1, [GLOBAL(s9)]
+        pmulhw      mm2, [GLOBAL(s9)]
+        paddw       mm1, [GLOBAL(s63)]
+        paddw       mm2, [GLOBAL(s63)]
+        psraw       mm1, 7
+        psraw       mm2, 7
+        packsswb    mm1, mm2
+
+        movq        mm6, [rdx+ 8]
+        movq        mm3, [rdx+48]
+
+        pxor        mm6, [GLOBAL(t80)]
+        pxor        mm3, [GLOBAL(t80)]
+
+        paddsb      mm6, mm1
+        psubsb      mm3, mm1
+
+        pxor        mm6, [GLOBAL(t80)]          ; mm6 = 71 61 51 41 31 21 11 01
+        pxor        mm3, [GLOBAL(t80)]          ; mm3 = 76 66 56 46 36 26 15 06
+
+        ; tranpose and write back
+        movq        mm0,    [rdx]               ; mm0 = 70 60 50 40 30 20 10 00
+        movq        mm1,    mm0                 ; mm0 = 70 60 50 40 30 20 10 00
+
+        punpcklbw   mm0,    mm6                 ; mm0 = 31 30 21 20 11 10 01 00
+        punpckhbw   mm1,    mm6                 ; mm3 = 71 70 61 60 51 50 41 40
+
+        movq        mm2,    [rdx+16]            ; mm2 = 72 62 52 42 32 22 12 02
+        movq        mm6,    mm2                 ; mm3 = 72 62 52 42 32 22 12 02
+
+        punpcklbw   mm2,    [rdx+24]            ; mm2 = 33 32 23 22 13 12 03 02
+        punpckhbw   mm6,    [rdx+24]            ; mm3 = 73 72 63 62 53 52 43 42
+
+        movq        mm5,    mm0                 ; mm5 = 31 30 21 20 11 10 01 00
+        punpcklwd   mm0,    mm2                 ; mm0 = 13 12 11 10 03 02 01 00
+
+        punpckhwd   mm5,    mm2                 ; mm5 = 33 32 31 30 23 22 21 20
+        movq        mm4,    mm1                 ; mm4 = 71 70 61 60 51 50 41 40
+
+        punpcklwd   mm1,    mm6                 ; mm1 = 53 52 51 50 43 42 41 40
+        punpckhwd   mm4,    mm6                 ; mm4 = 73 72 71 70 63 62 61 60
+
+        movq        mm2,    [rdx+32]            ; mm2 = 74 64 54 44 34 24 14 04
+        punpcklbw   mm2,    [rdx+40]            ; mm2 = 35 34 25 24 15 14 05 04
+
+        movq        mm6,    mm3                 ; mm6 = 76 66 56 46 36 26 15 06
+        punpcklbw   mm6,    [rdx+56]            ; mm6 = 37 36 27 26 17 16 07 06
+
+        movq        mm7,    mm2                 ; mm7 = 35 34 25 24 15 14 05 04
+        punpcklwd   mm2,    mm6                 ; mm2 = 17 16 15 14 07 06 05 04
+
+        punpckhwd   mm7,    mm6                 ; mm7 = 37 36 35 34 27 26 25 24
+        movq        mm6,    mm0                 ; mm6 = 13 12 11 10 03 02 01 00
+
+        punpckldq   mm0,    mm2                 ; mm0 = 07 06 05 04 03 02 01 00
+        punpckhdq   mm6,    mm2                 ; mm6 = 17 16 15 14 13 12 11 10
+
+        movq        [rsi+rax*4], mm0            ; write out
+        movq        [rdi+rax*4], mm6            ; write out
+
+        movq        mm0,    mm5                 ; mm0 = 33 32 31 30 23 22 21 20
+        punpckldq   mm0,    mm7                 ; mm0 = 27 26 25 24 23 22 20 20
+
+        punpckhdq   mm5,    mm7                 ; mm5 = 37 36 35 34 33 32 31 30
+        movq        [rsi+rax*2], mm0            ; write out
+
+        movq        [rdi+rax*2], mm5            ; write out
+        movq        mm2,    [rdx+32]            ; mm2 = 74 64 54 44 34 24 14 04
+
+        punpckhbw   mm2,    [rdx+40]            ; mm2 = 75 74 65 64 54 54 45 44
+        punpckhbw   mm3,    [rdx+56]            ; mm3 = 77 76 67 66 57 56 47 46
+
+        movq        mm5,    mm2                 ; mm5 = 75 74 65 64 54 54 45 44
+        punpcklwd   mm2,    mm3                 ; mm2 = 57 56 55 54 47 46 45 44
+
+        punpckhwd   mm5,    mm3                 ; mm5 = 77 76 75 74 67 66 65 64
+        movq        mm0,    mm1                 ; mm0=  53 52 51 50 43 42 41 40
+
+        movq        mm3,    mm4                 ; mm4 = 73 72 71 70 63 62 61 60
+        punpckldq   mm0,    mm2                 ; mm0 = 47 46 45 44 43 42 41 40
+
+        punpckhdq   mm1,    mm2                 ; mm1 = 57 56 55 54 53 52 51 50
+        movq        [rsi],  mm0                 ; write out
+
+        movq        [rdi],  mm1                 ; write out
+        neg         rax
+
+        punpckldq   mm3,    mm5                 ; mm3 = 67 66 65 64 63 62 61 60
+        punpckhdq   mm4,    mm5                 ; mm4 = 77 76 75 74 73 72 71 60
+
+        movq        [rsi+rax*2], mm3
+        movq        [rdi+rax*2], mm4
+
+        lea         rsi,        [rsi+rax*8]
+        dec         rcx
+
+        jnz         .next8_mbv
+
+    add rsp, 96
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_loop_filter_simple_horizontal_edge_mmx
+;(
+;    unsigned char *src_ptr,
+;    int  src_pixel_step,
+;    const char *blimit
+;)
+global sym(vp8_loop_filter_simple_horizontal_edge_mmx)
+sym(vp8_loop_filter_simple_horizontal_edge_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 3
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rsi, arg(0) ;src_ptr
+        movsxd      rax, dword ptr arg(1) ;src_pixel_step     ; destination pitch?
+
+        mov         rcx, 2                ; count
+.nexts8_h:
+        mov         rdx, arg(2) ;blimit           ; get blimit
+        movq        mm3, [rdx]            ;
+
+        mov         rdi, rsi              ; rdi points to row +1 for indirect addressing
+        add         rdi, rax
+        neg         rax
+
+        ; calculate mask
+        movq        mm1, [rsi+2*rax]      ; p1
+        movq        mm0, [rdi]            ; q1
+        movq        mm2, mm1
+        movq        mm7, mm0
+        movq        mm4, mm0
+        psubusb     mm0, mm1              ; q1-=p1
+        psubusb     mm1, mm4              ; p1-=q1
+        por         mm1, mm0              ; abs(p1-q1)
+        pand        mm1, [GLOBAL(tfe)]    ; set lsb of each byte to zero
+        psrlw       mm1, 1                ; abs(p1-q1)/2
+
+        movq        mm5, [rsi+rax]        ; p0
+        movq        mm4, [rsi]            ; q0
+        movq        mm0, mm4              ; q0
+        movq        mm6, mm5              ; p0
+        psubusb     mm5, mm4              ; p0-=q0
+        psubusb     mm4, mm6              ; q0-=p0
+        por         mm5, mm4              ; abs(p0 - q0)
+        paddusb     mm5, mm5              ; abs(p0-q0)*2
+        paddusb     mm5, mm1              ; abs (p0 - q0) *2 + abs(p1-q1)/2
+
+        psubusb     mm5, mm3              ; abs(p0 - q0) *2 + abs(p1-q1)/2  > blimit
+        pxor        mm3, mm3
+        pcmpeqb     mm5, mm3
+
+        ; start work on filters
+        pxor        mm2, [GLOBAL(t80)]    ; p1 offset to convert to signed values
+        pxor        mm7, [GLOBAL(t80)]    ; q1 offset to convert to signed values
+        psubsb      mm2, mm7              ; p1 - q1
+
+        pxor        mm6, [GLOBAL(t80)]    ; offset to convert to signed values
+        pxor        mm0, [GLOBAL(t80)]    ; offset to convert to signed values
+        movq        mm3, mm0              ; q0
+        psubsb      mm0, mm6              ; q0 - p0
+        paddsb      mm2, mm0              ; p1 - q1 + 1 * (q0 - p0)
+        paddsb      mm2, mm0              ; p1 - q1 + 2 * (q0 - p0)
+        paddsb      mm2, mm0              ; p1 - q1 + 3 * (q0 - p0)
+        pand        mm5, mm2              ; mask filter values we don't care about
+
+        ; do + 4 side
+        paddsb      mm5, [GLOBAL(t4)]     ; 3* (q0 - p0) + (p1 - q1) + 4
+
+        movq        mm0, mm5              ; get a copy of filters
+        psllw       mm0, 8                ; shift left 8
+        psraw       mm0, 3                ; arithmetic shift right 11
+        psrlw       mm0, 8
+        movq        mm1, mm5              ; get a copy of filters
+        psraw       mm1, 11               ; arithmetic shift right 11
+        psllw       mm1, 8                ; shift left 8 to put it back
+
+        por         mm0, mm1              ; put the two together to get result
+
+        psubsb      mm3, mm0              ; q0-= q0 add
+        pxor        mm3, [GLOBAL(t80)]    ; unoffset
+        movq        [rsi], mm3            ; write back
+
+
+        ; now do +3 side
+        psubsb      mm5, [GLOBAL(t1s)]     ; +3 instead of +4
+
+        movq        mm0, mm5              ; get a copy of filters
+        psllw       mm0, 8                ; shift left 8
+        psraw       mm0, 3                ; arithmetic shift right 11
+        psrlw       mm0, 8
+        psraw       mm5, 11               ; arithmetic shift right 11
+        psllw       mm5, 8                ; shift left 8 to put it back
+        por         mm0, mm5              ; put the two together to get result
+
+
+        paddsb      mm6, mm0              ; p0+= p0 add
+        pxor        mm6, [GLOBAL(t80)]    ; unoffset
+        movq        [rsi+rax], mm6        ; write back
+
+        add         rsi,8
+        neg         rax
+        dec         rcx
+        jnz         .nexts8_h
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_loop_filter_simple_vertical_edge_mmx
+;(
+;    unsigned char *src_ptr,
+;    int  src_pixel_step,
+;    const char *blimit
+;)
+global sym(vp8_loop_filter_simple_vertical_edge_mmx)
+sym(vp8_loop_filter_simple_vertical_edge_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 3
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub          rsp, 32      ; reserve 32 bytes
+    %define t0   [rsp + 0]    ;__declspec(align(16)) char t0[8];
+    %define t1   [rsp + 16]   ;__declspec(align(16)) char t1[8];
+
+        mov         rsi, arg(0) ;src_ptr
+        movsxd      rax, dword ptr arg(1) ;src_pixel_step     ; destination pitch?
+
+        lea         rsi, [rsi + rax*4- 2];  ;
+        mov         rcx, 2                                      ; count
+.nexts8_v:
+
+        lea         rdi,        [rsi + rax];
+        movd        mm0,        [rdi + rax * 2]                 ; xx xx xx xx 73 72 71 70
+
+        movd        mm6,        [rsi + rax * 2]                 ; xx xx xx xx 63 62 61 60
+        punpcklbw   mm6,        mm0                             ; 73 63 72 62 71 61 70 60
+
+        movd        mm0,        [rsi + rax]                     ; xx xx xx xx 53 52 51 50
+        movd        mm4,        [rsi]                           ; xx xx xx xx 43 42 41 40
+
+        punpcklbw   mm4,        mm0                             ; 53 43 52 42 51 41 50 40
+        movq        mm5,        mm4                             ; 53 43 52 42 51 41 50 40
+
+        punpcklwd   mm4,        mm6                             ; 71 61 51 41 70 60 50 40
+        punpckhwd   mm5,        mm6                             ; 73 63 53 43 72 62 52 42
+
+        neg         rax
+
+        movd        mm7,        [rsi + rax]                     ; xx xx xx xx 33 32 31 30
+        movd        mm6,        [rsi + rax * 2]                 ; xx xx xx xx 23 22 21 20
+
+        punpcklbw   mm6,        mm7                             ; 33 23 32 22 31 21 30 20
+        movd        mm1,        [rdi + rax * 4]                 ; xx xx xx xx 13 12 11 10
+
+        movd        mm0,        [rsi + rax * 4]                 ; xx xx xx xx 03 02 01 00
+        punpcklbw   mm0,        mm1                             ; 13 03 12 02 11 01 10 00
+
+        movq        mm2,        mm0                             ; 13 03 12 02 11 01 10 00
+        punpcklwd   mm0,        mm6                             ; 31 21 11 01 30 20 10 00
+
+        punpckhwd   mm2,        mm6                             ; 33 23 13 03 32 22 12 02
+        movq        mm1,        mm0                             ; 13 03 12 02 11 01 10 00
+
+        punpckldq   mm0,        mm4                             ; 70 60 50 40 30 20 10 00       = p1
+        movq        mm3,        mm2                             ; 33 23 13 03 32 22 12 02
+
+        punpckhdq   mm1,        mm4                             ; 71 61 51 41 31 21 11 01       = p0
+        punpckldq   mm2,        mm5                             ; 72 62 52 42 32 22 12 02       = q0
+
+        punpckhdq   mm3,        mm5                             ; 73 63 53 43 33 23 13 03       = q1
+
+
+        ; calculate mask
+        movq        mm6,        mm0                             ; p1
+        movq        mm7,        mm3                             ; q1
+        psubusb     mm7,        mm6                             ; q1-=p1
+        psubusb     mm6,        mm3                             ; p1-=q1
+        por         mm6,        mm7                             ; abs(p1-q1)
+        pand        mm6,        [GLOBAL(tfe)]                   ; set lsb of each byte to zero
+        psrlw       mm6,        1                               ; abs(p1-q1)/2
+
+        movq        mm5,        mm1                             ; p0
+        movq        mm4,        mm2                             ; q0
+
+        psubusb     mm5,        mm2                             ; p0-=q0
+        psubusb     mm4,        mm1                             ; q0-=p0
+
+        por         mm5,        mm4                             ; abs(p0 - q0)
+        paddusb     mm5,        mm5                             ; abs(p0-q0)*2
+        paddusb     mm5,        mm6                             ; abs (p0 - q0) *2 + abs(p1-q1)/2
+
+        mov         rdx,        arg(2) ;blimit                          ; get blimit
+        movq        mm7,        [rdx]
+
+        psubusb     mm5,        mm7                             ; abs(p0 - q0) *2 + abs(p1-q1)/2  > blimit
+        pxor        mm7,        mm7
+        pcmpeqb     mm5,        mm7                             ; mm5 = mask
+
+        ; start work on filters
+        movq        t0,         mm0
+        movq        t1,         mm3
+
+        pxor        mm0,        [GLOBAL(t80)]                   ; p1 offset to convert to signed values
+        pxor        mm3,        [GLOBAL(t80)]                   ; q1 offset to convert to signed values
+
+        psubsb      mm0,        mm3                             ; p1 - q1
+        movq        mm6,        mm1                             ; p0
+
+        movq        mm7,        mm2                             ; q0
+        pxor        mm6,        [GLOBAL(t80)]                   ; offset to convert to signed values
+
+        pxor        mm7,        [GLOBAL(t80)]                   ; offset to convert to signed values
+        movq        mm3,        mm7                             ; offseted ; q0
+
+        psubsb      mm7,        mm6                             ; q0 - p0
+        paddsb      mm0,        mm7                             ; p1 - q1 + 1 * (q0 - p0)
+
+        paddsb      mm0,        mm7                             ; p1 - q1 + 2 * (q0 - p0)
+        paddsb      mm0,        mm7                             ; p1 - q1 + 3 * (q0 - p0)
+
+        pand        mm5,        mm0                             ; mask filter values we don't care about
+
+        paddsb      mm5,        [GLOBAL(t4)]                    ;  3* (q0 - p0) + (p1 - q1) + 4
+
+        movq        mm0,        mm5                             ; get a copy of filters
+        psllw       mm0,        8                               ; shift left 8
+        psraw       mm0,        3                               ; arithmetic shift right 11
+        psrlw       mm0,        8
+
+        movq        mm7,        mm5                             ; get a copy of filters
+        psraw       mm7,        11                              ; arithmetic shift right 11
+        psllw       mm7,        8                               ; shift left 8 to put it back
+
+        por         mm0,        mm7                             ; put the two together to get result
+
+        psubsb      mm3,        mm0                             ; q0-= q0sz add
+        pxor        mm3,        [GLOBAL(t80)]                   ; unoffset
+
+        ; now do +3 side
+        psubsb      mm5, [GLOBAL(t1s)]                          ; +3 instead of +4
+
+        movq        mm0, mm5                                    ; get a copy of filters
+        psllw       mm0, 8                                      ; shift left 8
+        psraw       mm0, 3                                      ; arithmetic shift right 11
+        psrlw       mm0, 8
+
+        psraw       mm5, 11                                     ; arithmetic shift right 11
+        psllw       mm5, 8                                      ; shift left 8 to put it back
+        por         mm0, mm5                                    ; put the two together to get result
+
+        paddsb      mm6, mm0                                    ; p0+= p0 add
+        pxor        mm6, [GLOBAL(t80)]                          ; unoffset
+
+
+        movq        mm0,        t0
+        movq        mm4,        t1
+
+        ; mm0 = 70 60 50 40 30 20 10 00
+        ; mm6 = 71 61 51 41 31 21 11 01
+        ; mm3 = 72 62 52 42 32 22 12 02
+        ; mm4 = 73 63 53 43 33 23 13 03
+        ; transpose back to write out
+
+        movq        mm1,        mm0                         ;
+        punpcklbw   mm0,        mm6                         ; 31 30 21 20 11 10 01 00
+
+        punpckhbw   mm1,        mm6                         ; 71 70 61 60 51 50 41 40
+        movq        mm2,        mm3                         ;
+
+        punpcklbw   mm2,        mm4                         ; 33 32 23 22 13 12 03 02
+        movq        mm5,        mm1                         ; 71 70 61 60 51 50 41 40
+
+        punpckhbw   mm3,        mm4                         ; 73 72 63 62 53 52 43 42
+        movq        mm6,        mm0                         ; 31 30 21 20 11 10 01 00
+
+        punpcklwd   mm0,        mm2                         ; 13 12 11 10 03 02 01 00
+        punpckhwd   mm6,        mm2                         ; 33 32 31 30 23 22 21 20
+
+        movd        [rsi+rax*4], mm0                        ; write 03 02 01 00
+        punpcklwd   mm1,        mm3                         ; 53 52 51 50 43 42 41 40
+
+        psrlq       mm0,        32                          ; xx xx xx xx 13 12 11 10
+        punpckhwd   mm5,        mm3                         ; 73 72 71 70 63 62 61 60
+
+        movd        [rdi+rax*4], mm0                        ; write 13 12 11 10
+        movd        [rsi+rax*2], mm6                        ; write 23 22 21 20
+
+        psrlq       mm6,        32                          ; 33 32 31 30
+        movd        [rsi],      mm1                         ; write 43 42 41 40
+
+        movd        [rsi + rax], mm6                        ; write 33 32 31 30
+        neg         rax
+
+        movd        [rsi + rax*2], mm5                      ; write 63 62 61 60
+        psrlq       mm1,        32                          ; 53 52 51 50
+
+        movd        [rdi],      mm1                         ; write out 53 52 51 50
+        psrlq       mm5,        32                          ; 73 72 71 70
+
+        movd        [rdi + rax*2], mm5                      ; write 73 72 71 70
+
+        lea         rsi,        [rsi+rax*8]                 ; next 8
+
+        dec         rcx
+        jnz         .nexts8_v
+
+    add rsp, 32
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+
+;void fast_loop_filter_vertical_edges_mmx(unsigned char *y_ptr,
+;                  int y_stride,
+;                  loop_filter_info *lfi)
+;{
+;
+;
+;    vp8_loop_filter_simple_vertical_edge_mmx(y_ptr+4, y_stride, lfi->flim,lfi->lim,lfi->thr,2);
+;    vp8_loop_filter_simple_vertical_edge_mmx(y_ptr+8, y_stride, lfi->flim,lfi->lim,lfi->thr,2);
+;    vp8_loop_filter_simple_vertical_edge_mmx(y_ptr+12, y_stride, lfi->flim,lfi->lim,lfi->thr,2);
+;}
+
+SECTION_RODATA
+align 16
+tfe:
+    times 8 db 0xfe
+align 16
+t80:
+    times 8 db 0x80
+align 16
+t1s:
+    times 8 db 0x01
+align 16
+t3:
+    times 8 db 0x03
+align 16
+t4:
+    times 8 db 0x04
+align 16
+ones:
+    times 4 dw 0x0001
+align 16
+s27:
+    times 4 dw 0x1b00
+align 16
+s18:
+    times 4 dw 0x1200
+align 16
+s9:
+    times 4 dw 0x0900
+align 16
+s63:
+    times 4 dw 0x003f
diff --git a/vp8/common/x86/loopfilter_sse2.asm b/vp8/common/x86/loopfilter_sse2.asm
new file mode 100644 (file)
index 0000000..9944c33
--- /dev/null
@@ -0,0 +1,1640 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+%define _t0 0
+%define _t1 _t0 + 16
+%define _p3 _t1 + 16
+%define _p2 _p3 + 16
+%define _p1 _p2 + 16
+%define _p0 _p1 + 16
+%define _q0 _p0 + 16
+%define _q1 _q0 + 16
+%define _q2 _q1 + 16
+%define _q3 _q2 + 16
+%define lf_var_size 160
+
+; Use of pmaxub instead of psubusb to compute filter mask was seen
+; in ffvp8
+
+%macro LFH_FILTER_AND_HEV_MASK 1
+%if %1
+        movdqa      xmm2,                   [rdi+2*rax]       ; q3
+        movdqa      xmm1,                   [rsi+2*rax]       ; q2
+        movdqa      xmm4,                   [rsi+rax]         ; q1
+        movdqa      xmm5,                   [rsi]             ; q0
+        neg         rax                     ; negate pitch to deal with above border
+%else
+        movlps      xmm2,                   [rsi + rcx*2]     ; q3
+        movlps      xmm1,                   [rsi + rcx]       ; q2
+        movlps      xmm4,                   [rsi]             ; q1
+        movlps      xmm5,                   [rsi + rax]       ; q0
+
+        movhps      xmm2,                   [rdi + rcx*2]
+        movhps      xmm1,                   [rdi + rcx]
+        movhps      xmm4,                   [rdi]
+        movhps      xmm5,                   [rdi + rax]
+
+        lea         rsi,                    [rsi + rax*4]
+        lea         rdi,                    [rdi + rax*4]
+
+        movdqa      [rsp+_q2],              xmm1              ; store q2
+        movdqa      [rsp+_q1],              xmm4              ; store q1
+%endif
+        movdqa      xmm7,                   [rdx]             ;limit
+
+        movdqa      xmm6,                   xmm1              ; q2
+        movdqa      xmm3,                   xmm4              ; q1
+
+        psubusb     xmm1,                   xmm2              ; q2-=q3
+        psubusb     xmm2,                   xmm6              ; q3-=q2
+
+        psubusb     xmm4,                   xmm6              ; q1-=q2
+        psubusb     xmm6,                   xmm3              ; q2-=q1
+
+        por         xmm4,                   xmm6              ; abs(q2-q1)
+        por         xmm1,                   xmm2              ; abs(q3-q2)
+
+        movdqa      xmm0,                   xmm5              ; q0
+        pmaxub      xmm1,                   xmm4
+
+        psubusb     xmm5,                   xmm3              ; q0-=q1
+        psubusb     xmm3,                   xmm0              ; q1-=q0
+
+        por         xmm5,                   xmm3              ; abs(q0-q1)
+        movdqa      [rsp+_t0],              xmm5              ; save to t0
+
+        pmaxub      xmm1,                   xmm5
+
+%if %1
+        movdqa      xmm2,                   [rsi+4*rax]       ; p3
+        movdqa      xmm4,                   [rdi+4*rax]       ; p2
+        movdqa      xmm6,                   [rsi+2*rax]       ; p1
+%else
+        movlps      xmm2,                   [rsi + rax]       ; p3
+        movlps      xmm4,                   [rsi]             ; p2
+        movlps      xmm6,                   [rsi + rcx]       ; p1
+
+        movhps      xmm2,                   [rdi + rax]
+        movhps      xmm4,                   [rdi]
+        movhps      xmm6,                   [rdi + rcx]
+
+        movdqa      [rsp+_p2],              xmm4              ; store p2
+        movdqa      [rsp+_p1],              xmm6              ; store p1
+%endif
+
+        movdqa      xmm5,                   xmm4              ; p2
+        movdqa      xmm3,                   xmm6              ; p1
+
+        psubusb     xmm4,                   xmm2              ; p2-=p3
+        psubusb     xmm2,                   xmm5              ; p3-=p2
+
+        psubusb     xmm3,                   xmm5              ; p1-=p2
+        pmaxub      xmm1,                   xmm4              ; abs(p3 - p2)
+
+        psubusb     xmm5,                   xmm6              ; p2-=p1
+        pmaxub      xmm1,                   xmm2              ; abs(p3 - p2)
+
+        pmaxub      xmm1,                   xmm5              ; abs(p2 - p1)
+        movdqa      xmm2,                   xmm6              ; p1
+
+        pmaxub      xmm1,                   xmm3              ; abs(p2 - p1)
+%if %1
+        movdqa      xmm4,                   [rsi+rax]         ; p0
+        movdqa      xmm3,                   [rdi]             ; q1
+%else
+        movlps      xmm4,                   [rsi + rcx*2]     ; p0
+        movhps      xmm4,                   [rdi + rcx*2]
+        movdqa      xmm3,                   [rsp+_q1]                ; q1
+%endif
+
+        movdqa      xmm5,                   xmm4              ; p0
+        psubusb     xmm4,                   xmm6              ; p0-=p1
+
+        psubusb     xmm6,                   xmm5              ; p1-=p0
+
+        por         xmm6,                   xmm4              ; abs(p1 - p0)
+        mov         rdx,                    arg(2)            ; get blimit
+
+        movdqa     [rsp+_t1],               xmm6              ; save to t1
+
+        movdqa      xmm4,                   xmm3              ; q1
+        pmaxub      xmm1,                   xmm6
+
+        psubusb     xmm3,                   xmm2              ; q1-=p1
+        psubusb     xmm2,                   xmm4              ; p1-=q1
+
+        psubusb     xmm1,                   xmm7
+        por         xmm2,                   xmm3              ; abs(p1-q1)
+
+        movdqa      xmm7,                   [rdx]             ; blimit
+        mov         rdx,                    arg(4)            ; hev get thresh
+
+        movdqa      xmm3,                   xmm0              ; q0
+        pand        xmm2,                   [GLOBAL(tfe)]     ; set lsb of each byte to zero
+
+        movdqa      xmm6,                   xmm5              ; p0
+        psrlw       xmm2,                   1                 ; abs(p1-q1)/2
+
+        psubusb     xmm5,                   xmm3              ; p0-=q0
+        psubusb     xmm3,                   xmm6              ; q0-=p0
+        por         xmm5,                   xmm3              ; abs(p0 - q0)
+
+        paddusb     xmm5,                   xmm5              ; abs(p0-q0)*2
+
+        movdqa      xmm4,                   [rsp+_t0]                ; hev get abs (q1 - q0)
+        movdqa      xmm3,                   [rsp+_t1]                ; get abs (p1 - p0)
+
+        paddusb     xmm5,                   xmm2              ; abs (p0 - q0) *2 + abs(p1-q1)/2
+
+        movdqa      xmm2,                   [rdx]             ; hev
+
+        psubusb     xmm5,                   xmm7              ; abs (p0 - q0) *2 + abs(p1-q1)/2  > blimit
+        psubusb     xmm4,                   xmm2              ; hev
+
+        psubusb     xmm3,                   xmm2              ; hev
+        por         xmm1,                   xmm5
+
+        pxor        xmm7,                   xmm7
+        paddb       xmm4,                   xmm3              ; hev abs(q1 - q0) > thresh || abs(p1 - p0) > thresh
+
+        pcmpeqb     xmm4,                   xmm5              ; hev
+        pcmpeqb     xmm3,                   xmm3              ; hev
+
+        pcmpeqb     xmm1,                   xmm7              ; mask xmm1
+        pxor        xmm4,                   xmm3              ; hev
+%endmacro
+
+%macro B_FILTER 1
+        movdqa      xmm3,                   [GLOBAL(t80)]
+%if %1 == 0
+        movdqa      xmm2,                   [rsp+_p1]                ; p1
+        movdqa      xmm7,                   [rsp+_q1]                ; q1
+%elif %1 == 1
+        movdqa      xmm2,                   [rsi+2*rax]       ; p1
+        movdqa      xmm7,                   [rdi]             ; q1
+%elif %1 == 2
+        movdqa      xmm2,                   [rsp+_p1]         ; p1
+        movdqa      xmm6,                   [rsp+_p0]         ; p0
+        movdqa      xmm0,                   [rsp+_q0]         ; q0
+        movdqa      xmm7,                   [rsp+_q1]         ; q1
+%endif
+
+        pxor        xmm2,                   xmm3              ; p1 offset to convert to signed values
+        pxor        xmm7,                   xmm3              ; q1 offset to convert to signed values
+
+        psubsb      xmm2,                   xmm7              ; p1 - q1
+        pxor        xmm6,                   xmm3              ; offset to convert to signed values
+
+        pand        xmm2,                   xmm4              ; high var mask (hvm)(p1 - q1)
+        pxor        xmm0,                   xmm3              ; offset to convert to signed values
+
+        movdqa      xmm3,                   xmm0              ; q0
+        psubsb      xmm0,                   xmm6              ; q0 - p0
+        paddsb      xmm2,                   xmm0              ; 1 * (q0 - p0) + hvm(p1 - q1)
+        paddsb      xmm2,                   xmm0              ; 2 * (q0 - p0) + hvm(p1 - q1)
+        paddsb      xmm2,                   xmm0              ; 3 * (q0 - p0) + hvm(p1 - q1)
+        pand        xmm1,                   xmm2              ; mask filter values we don't care about
+
+        movdqa      xmm2,                   xmm1
+        paddsb      xmm1,                   [GLOBAL(t4)]      ; 3* (q0 - p0) + hvm(p1 - q1) + 4
+        paddsb      xmm2,                   [GLOBAL(t3)]      ; 3* (q0 - p0) + hvm(p1 - q1) + 3
+
+        punpckhbw   xmm5,                   xmm2              ; axbxcxdx
+        punpcklbw   xmm2,                   xmm2              ; exfxgxhx
+
+        punpcklbw   xmm0,                   xmm1              ; exfxgxhx
+        psraw       xmm5,                   11                ; sign extended shift right by 3
+
+        punpckhbw   xmm1,                   xmm1              ; axbxcxdx
+        psraw       xmm2,                   11                ; sign extended shift right by 3
+
+        packsswb    xmm2,                   xmm5              ; (3* (q0 - p0) + hvm(p1 - q1) + 3) >> 3;
+        psraw       xmm0,                   11                ; sign extended shift right by 3
+
+        psraw       xmm1,                   11                ; sign extended shift right by 3
+        movdqa      xmm5,                   xmm0              ; save results
+
+        packsswb    xmm0,                   xmm1              ; (3* (q0 - p0) + hvm(p1 - q1) + 4) >>3
+
+        paddsb      xmm6,                   xmm2              ; p0+= p0 add
+
+        movdqa      xmm2,                   [GLOBAL(ones)]
+        paddsw      xmm5,                   xmm2
+        paddsw      xmm1,                   xmm2
+        psraw       xmm5,                   1                 ; partial shifted one more time for 2nd tap
+        psraw       xmm1,                   1                 ; partial shifted one more time for 2nd tap
+        packsswb    xmm5,                   xmm1              ; (3* (q0 - p0) + hvm(p1 - q1) + 4) >>4
+        movdqa      xmm2,                   [GLOBAL(t80)]
+
+%if %1 == 0
+        movdqa      xmm1,                   [rsp+_p1]         ; p1
+        lea         rsi,                    [rsi + rcx*2]
+        lea         rdi,                    [rdi + rcx*2]
+%elif %1 == 1
+        movdqa      xmm1,                   [rsi+2*rax]       ; p1
+%elif %1 == 2
+        movdqa      xmm1,                   [rsp+_p1]         ; p1
+%endif
+
+        pandn       xmm4,                   xmm5              ; high edge variance additive
+        pxor        xmm6,                   xmm2              ; unoffset
+
+        pxor        xmm1,                   xmm2              ; reoffset
+        psubsb      xmm3,                   xmm0              ; q0-= q0 add
+
+        paddsb      xmm1,                   xmm4              ; p1+= p1 add
+        pxor        xmm3,                   xmm2              ; unoffset
+
+        pxor        xmm1,                   xmm2              ; unoffset
+        psubsb      xmm7,                   xmm4              ; q1-= q1 add
+
+        pxor        xmm7,                   xmm2              ; unoffset
+%if %1 == 0
+        movq        [rsi],                  xmm6              ; p0
+        movhps      [rdi],                  xmm6
+        movq        [rsi + rax],            xmm1              ; p1
+        movhps      [rdi + rax],            xmm1
+        movq        [rsi + rcx],            xmm3              ; q0
+        movhps      [rdi + rcx],            xmm3
+        movq        [rsi + rcx*2],          xmm7              ; q1
+        movhps      [rdi + rcx*2],          xmm7
+%elif %1 == 1
+        movdqa      [rsi+rax],              xmm6              ; write back
+        movdqa      [rsi+2*rax],            xmm1              ; write back
+        movdqa      [rsi],                  xmm3              ; write back
+        movdqa      [rdi],                  xmm7              ; write back
+%endif
+
+%endmacro
+
+%if ABI_IS_32BIT
+
+;void vp8_loop_filter_horizontal_edge_sse2
+;(
+;    unsigned char *src_ptr,
+;    int            src_pixel_step,
+;    const char    *blimit,
+;    const char    *limit,
+;    const char    *thresh,
+;)
+global sym(vp8_loop_filter_horizontal_edge_sse2)
+sym(vp8_loop_filter_horizontal_edge_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub         rsp, lf_var_size
+
+        mov         rsi,                    arg(0)           ;src_ptr
+        movsxd      rax,                    dword ptr arg(1) ;src_pixel_step
+
+        mov         rdx,                    arg(3)           ;limit
+
+        lea         rdi,                    [rsi+rax]        ; rdi points to row +1 for indirect addressing
+
+        ; calculate breakout conditions and high edge variance
+        LFH_FILTER_AND_HEV_MASK 1
+        ; filter and write back the result
+        B_FILTER 1
+
+    add rsp, lf_var_size
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+%endif
+
+;void vp8_loop_filter_horizontal_edge_uv_sse2
+;(
+;    unsigned char *src_ptr,
+;    int            src_pixel_step,
+;    const char    *blimit,
+;    const char    *limit,
+;    const char    *thresh,
+;    int            count
+;)
+global sym(vp8_loop_filter_horizontal_edge_uv_sse2)
+sym(vp8_loop_filter_horizontal_edge_uv_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub         rsp, lf_var_size
+
+        mov         rsi,                    arg(0)             ; u
+        mov         rdi,                    arg(5)             ; v
+        movsxd      rax,                    dword ptr arg(1)   ; src_pixel_step
+        mov         rcx,                    rax
+        neg         rax                     ; negate pitch to deal with above border
+
+        mov         rdx,                    arg(3)             ;limit
+
+        lea         rsi,                    [rsi + rcx]
+        lea         rdi,                    [rdi + rcx]
+
+        ; calculate breakout conditions and high edge variance
+        LFH_FILTER_AND_HEV_MASK 0
+        ; filter and write back the result
+        B_FILTER 0
+
+    add rsp, lf_var_size
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+%macro MB_FILTER_AND_WRITEBACK 1
+        movdqa      xmm3,                   [GLOBAL(t80)]
+%if %1 == 0
+        movdqa      xmm2,                   [rsp+_p1]              ; p1
+        movdqa      xmm7,                   [rsp+_q1]              ; q1
+%elif %1 == 1
+        movdqa      xmm2,                   [rsi+2*rax]     ; p1
+        movdqa      xmm7,                   [rdi]           ; q1
+
+        mov         rcx,                    rax
+        neg         rcx
+%elif %1 == 2
+        movdqa      xmm2,                   [rsp+_p1]       ; p1
+        movdqa      xmm6,                   [rsp+_p0]       ; p0
+        movdqa      xmm0,                   [rsp+_q0]       ; q0
+        movdqa      xmm7,                   [rsp+_q1]       ; q1
+%endif
+
+        pxor        xmm2,                   xmm3            ; p1 offset to convert to signed values
+        pxor        xmm7,                   xmm3            ; q1 offset to convert to signed values
+        pxor        xmm6,                   xmm3            ; offset to convert to signed values
+        pxor        xmm0,                   xmm3            ; offset to convert to signed values
+
+        psubsb      xmm2,                   xmm7            ; p1 - q1
+
+        movdqa      xmm3,                   xmm0            ; q0
+        psubsb      xmm0,                   xmm6            ; q0 - p0
+        paddsb      xmm2,                   xmm0            ; 1 * (q0 - p0) + (p1 - q1)
+        paddsb      xmm2,                   xmm0            ; 2 * (q0 - p0)
+        paddsb      xmm2,                   xmm0            ; 3 * (q0 - p0) + (p1 - q1)
+        pand        xmm1,                   xmm2            ; mask filter values we don't care about
+
+        movdqa      xmm2,                   xmm1            ; vp8_filter
+
+        pand        xmm2,                   xmm4            ; Filter2 = vp8_filter & hev
+        pxor        xmm0,                   xmm0
+
+        pandn       xmm4,                   xmm1            ; vp8_filter&=~hev
+        pxor        xmm1,                   xmm1
+
+        punpcklbw   xmm0,                   xmm4            ; Filter 2 (hi)
+        punpckhbw   xmm1,                   xmm4            ; Filter 2 (lo)
+
+        movdqa      xmm5,                   xmm2
+
+        movdqa      xmm4,                   [GLOBAL(s9)]
+        paddsb      xmm5,                   [GLOBAL(t3)]    ; vp8_signed_char_clamp(Filter2 + 3)
+        paddsb      xmm2,                   [GLOBAL(t4)]    ; vp8_signed_char_clamp(Filter2 + 4)
+
+        pmulhw      xmm1,                   xmm4            ; Filter 2 (lo) * 9
+        pmulhw      xmm0,                   xmm4            ; Filter 2 (hi) * 9
+
+        punpckhbw   xmm7,                   xmm5            ; axbxcxdx
+        punpcklbw   xmm5,                   xmm5            ; exfxgxhx
+
+        psraw       xmm7,                   11              ; sign extended shift right by 3
+
+        psraw       xmm5,                   11              ; sign extended shift right by 3
+        punpckhbw   xmm4,                   xmm2            ; axbxcxdx
+
+        punpcklbw   xmm2,                   xmm2            ; exfxgxhx
+        psraw       xmm4,                   11              ; sign extended shift right by 3
+
+        packsswb    xmm5,                   xmm7            ; Filter2 >>=3;
+        psraw       xmm2,                   11              ; sign extended shift right by 3
+
+        packsswb    xmm2,                   xmm4            ; Filter1 >>=3;
+
+        paddsb      xmm6,                   xmm5            ; ps0 =ps0 + Fitler2
+
+        psubsb      xmm3,                   xmm2            ; qs0 =qs0 - Filter1
+        movdqa      xmm7,                   xmm1
+
+        movdqa      xmm4,                   [GLOBAL(s63)]
+        movdqa      xmm5,                   xmm0
+        movdqa      xmm2,                   xmm5
+        paddw       xmm0,                   xmm4            ; Filter 2 (hi) * 9 + 63
+        paddw       xmm1,                   xmm4            ; Filter 2 (lo) * 9 + 63
+        movdqa      xmm4,                   xmm7
+
+        paddw       xmm5,                   xmm5            ; Filter 2 (hi) * 18
+
+        paddw       xmm7,                   xmm7            ; Filter 2 (lo) * 18
+        paddw       xmm5,                   xmm0            ; Filter 2 (hi) * 27 + 63
+
+        paddw       xmm7,                   xmm1            ; Filter 2 (lo) * 27 + 63
+        paddw       xmm2,                   xmm0            ; Filter 2 (hi) * 18 + 63
+        psraw       xmm0,                   7               ; (Filter 2 (hi) * 9 + 63) >> 7
+
+        paddw       xmm4,                   xmm1            ; Filter 2 (lo) * 18 + 63
+        psraw       xmm1,                   7               ; (Filter 2 (lo) * 9 + 63) >> 7
+        psraw       xmm2,                   7               ; (Filter 2 (hi) * 18 + 63) >> 7
+
+        packsswb    xmm0,                   xmm1            ; u1 = vp8_signed_char_clamp((63 + Filter2 * 9)>>7)
+
+        psraw       xmm4,                   7               ; (Filter 2 (lo) * 18 + 63) >> 7
+        psraw       xmm5,                   7               ; (Filter 2 (hi) * 27 + 63) >> 7
+        psraw       xmm7,                   7               ; (Filter 2 (lo) * 27 + 63) >> 7
+
+        packsswb    xmm5,                   xmm7            ; u3 = vp8_signed_char_clamp((63 + Filter2 * 27)>>7)
+        packsswb    xmm2,                   xmm4            ; u2 = vp8_signed_char_clamp((63 + Filter2 * 18)>>7)
+        movdqa      xmm7,                   [GLOBAL(t80)]
+
+%if %1 == 0
+        movdqa      xmm1,                   [rsp+_q1]       ; q1
+        movdqa      xmm4,                   [rsp+_p1]       ; p1
+        lea         rsi,                    [rsi+rcx*2]
+        lea         rdi,                    [rdi+rcx*2]
+
+%elif %1 == 1
+        movdqa      xmm1,                   [rdi]           ; q1
+        movdqa      xmm4,                   [rsi+rax*2]     ; p1
+%elif %1 == 2
+        movdqa      xmm4,                   [rsp+_p1]       ; p1
+        movdqa      xmm1,                   [rsp+_q1]       ; q1
+%endif
+
+        pxor        xmm1,                   xmm7
+        pxor        xmm4,                   xmm7
+
+        psubsb      xmm3,                   xmm5            ; sq = vp8_signed_char_clamp(qs0 - u3)
+        paddsb      xmm6,                   xmm5            ; sp = vp8_signed_char_clamp(ps0 - u3)
+        psubsb      xmm1,                   xmm2            ; sq = vp8_signed_char_clamp(qs1 - u2)
+        paddsb      xmm4,                   xmm2            ; sp = vp8_signed_char_clamp(ps1 - u2)
+
+%if %1 == 1
+        movdqa      xmm2,                   [rdi+rax*4]     ; p2
+        movdqa      xmm5,                   [rdi+rcx]       ; q2
+%else
+        movdqa      xmm2,                   [rsp+_p2]       ; p2
+        movdqa      xmm5,                   [rsp+_q2]       ; q2
+%endif
+
+        pxor        xmm1,                   xmm7            ; *oq1 = sq^0x80;
+        pxor        xmm4,                   xmm7            ; *op1 = sp^0x80;
+        pxor        xmm2,                   xmm7
+        pxor        xmm5,                   xmm7
+        paddsb      xmm2,                   xmm0            ; sp = vp8_signed_char_clamp(ps2 - u)
+        psubsb      xmm5,                   xmm0            ; sq = vp8_signed_char_clamp(qs2 - u)
+        pxor        xmm2,                   xmm7            ; *op2 = sp^0x80;
+        pxor        xmm5,                   xmm7            ; *oq2 = sq^0x80;
+        pxor        xmm3,                   xmm7            ; *oq0 = sq^0x80
+        pxor        xmm6,                   xmm7            ; *oq0 = sp^0x80
+%if %1 == 0
+        movq        [rsi],                  xmm6            ; p0
+        movhps      [rdi],                  xmm6
+        movq        [rsi + rcx],            xmm3            ; q0
+        movhps      [rdi + rcx],            xmm3
+        lea         rdx,                    [rcx + rcx*2]
+        movq        [rsi+rcx*2],            xmm1            ; q1
+        movhps      [rdi+rcx*2],            xmm1
+
+        movq        [rsi + rax],            xmm4            ; p1
+        movhps      [rdi + rax],            xmm4
+
+        movq        [rsi+rax*2],            xmm2            ; p2
+        movhps      [rdi+rax*2],            xmm2
+
+        movq        [rsi+rdx],              xmm5            ; q2
+        movhps      [rdi+rdx],              xmm5
+%elif %1 == 1
+        movdqa      [rdi+rcx],              xmm5            ; q2
+        movdqa      [rdi],                  xmm1            ; q1
+        movdqa      [rsi],                  xmm3            ; q0
+        movdqa      [rsi+rax  ],            xmm6            ; p0
+        movdqa      [rsi+rax*2],            xmm4            ; p1
+        movdqa      [rdi+rax*4],            xmm2            ; p2
+%elif %1 == 2
+        movdqa      [rsp+_p1],              xmm4            ; p1
+        movdqa      [rsp+_p0],              xmm6            ; p0
+        movdqa      [rsp+_q0],              xmm3            ; q0
+        movdqa      [rsp+_q1],              xmm1            ; q1
+%endif
+
+%endmacro
+
+
+;void vp8_mbloop_filter_horizontal_edge_sse2
+;(
+;    unsigned char *src_ptr,
+;    int            src_pixel_step,
+;    const char    *blimit,
+;    const char    *limit,
+;    const char    *thresh,
+;)
+global sym(vp8_mbloop_filter_horizontal_edge_sse2)
+sym(vp8_mbloop_filter_horizontal_edge_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub         rsp, lf_var_size
+
+        mov         rsi,                    arg(0)            ;src_ptr
+        movsxd      rax,                    dword ptr arg(1)  ;src_pixel_step
+        mov         rdx,                    arg(3)            ;limit
+
+        lea         rdi,                    [rsi+rax]         ; rdi points to row +1 for indirect addressing
+
+        ; calculate breakout conditions and high edge variance
+        LFH_FILTER_AND_HEV_MASK 1
+        ; filter and write back the results
+        MB_FILTER_AND_WRITEBACK 1
+
+    add rsp, lf_var_size
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_mbloop_filter_horizontal_edge_uv_sse2
+;(
+;    unsigned char *u,
+;    int            src_pixel_step,
+;    const char    *blimit,
+;    const char    *limit,
+;    const char    *thresh,
+;    unsigned char *v
+;)
+global sym(vp8_mbloop_filter_horizontal_edge_uv_sse2)
+sym(vp8_mbloop_filter_horizontal_edge_uv_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub         rsp, lf_var_size
+
+        mov         rsi,                    arg(0)             ; u
+        mov         rdi,                    arg(5)             ; v
+        movsxd      rax,                    dword ptr arg(1)   ; src_pixel_step
+        mov         rcx,                    rax
+        neg         rax                     ; negate pitch to deal with above border
+        mov         rdx,                    arg(3)             ;limit
+
+        lea         rsi,                    [rsi + rcx]
+        lea         rdi,                    [rdi + rcx]
+
+        ; calculate breakout conditions and high edge variance
+        LFH_FILTER_AND_HEV_MASK 0
+        ; filter and write back the results
+        MB_FILTER_AND_WRITEBACK 0
+
+    add rsp, lf_var_size
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+%macro TRANSPOSE_16X8 2
+        movq        xmm4,               [rsi]           ; xx xx xx xx xx xx xx xx 07 06 05 04 03 02 01 00
+        movq        xmm1,               [rdi]           ; xx xx xx xx xx xx xx xx 17 16 15 14 13 12 11 10
+        movq        xmm0,               [rsi+2*rax]     ; xx xx xx xx xx xx xx xx 27 26 25 24 23 22 21 20
+        movq        xmm7,               [rdi+2*rax]     ; xx xx xx xx xx xx xx xx 37 36 35 34 33 32 31 30
+        movq        xmm5,               [rsi+4*rax]     ; xx xx xx xx xx xx xx xx 47 46 45 44 43 42 41 40
+        movq        xmm2,               [rdi+4*rax]     ; xx xx xx xx xx xx xx xx 57 56 55 54 53 52 51 50
+
+        punpcklbw   xmm4,               xmm1            ; 17 07 16 06 15 05 14 04 13 03 12 02 11 01 10 00
+
+        movq        xmm1,               [rdi+2*rcx]     ; xx xx xx xx xx xx xx xx 77 76 75 74 73 72 71 70
+
+        movdqa      xmm3,               xmm4            ; 17 07 16 06 15 05 14 04 13 03 12 02 11 01 10 00
+        punpcklbw   xmm0,               xmm7            ; 37 27 36 36 35 25 34 24 33 23 32 22 31 21 30 20
+
+        movq        xmm7,               [rsi+2*rcx]     ; xx xx xx xx xx xx xx xx 67 66 65 64 63 62 61 60
+
+        punpcklbw   xmm5,               xmm2            ; 57 47 56 46 55 45 54 44 53 43 52 42 51 41 50 40
+%if %1
+        lea         rsi,                [rsi+rax*8]
+        lea         rdi,                [rdi+rax*8]
+%else
+        mov         rsi,                arg(5)          ; v_ptr
+%endif
+
+        movdqa      xmm6,               xmm5            ; 57 47 56 46 55 45 54 44 53 43 52 42 51 41 50 40
+        punpcklbw   xmm7,               xmm1            ; 77 67 76 66 75 65 74 64 73 63 72 62 71 61 70 60
+        punpcklwd   xmm5,               xmm7            ; 73 63 53 43 72 62 52 42 71 61 51 41 70 60 50 40
+        punpckhwd   xmm6,               xmm7            ; 77 67 57 47 76 66 56 46 75 65 55 45 74 64 54 44
+        punpcklwd   xmm3,               xmm0            ; 33 23 13 03 32 22 12 02 31 21 11 01 30 20 10 00
+
+%if %1 == 0
+        lea         rdi,                [rsi + rax - 4] ; rdi points to row +1 for indirect addressing
+        lea         rsi,                [rsi - 4]
+%endif
+
+        movdqa      xmm2,               xmm3            ; 33 23 13 03 32 22 12 02 31 21 11 01 30 20 10 00
+        punpckhwd   xmm4,               xmm0            ; 37 27 17 07 36 26 16 06 35 25 15 05 34 24 14 04
+
+        movdqa      xmm7,               xmm4            ; 37 27 17 07 36 26 16 06 35 25 15 05 34 24 14 04
+        punpckhdq   xmm3,               xmm5            ; 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02
+
+        punpckhdq   xmm7,               xmm6            ; 77 67 57 47 37 27 17 07 76 66 56 46 36 26 16 06
+
+        punpckldq   xmm4,               xmm6            ; 75 65 55 45 35 25 15 05 74 64 54 44 34 24 14 04
+
+        punpckldq   xmm2,               xmm5            ; 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00
+
+        movdqa      [rsp+_t0],          xmm2            ; save to free XMM2
+
+        movq        xmm2,               [rsi]           ; xx xx xx xx xx xx xx xx 87 86 85 84 83 82 81 80
+        movq        xmm6,               [rdi]           ; xx xx xx xx xx xx xx xx 97 96 95 94 93 92 91 90
+        movq        xmm0,               [rsi+2*rax]     ; xx xx xx xx xx xx xx xx a7 a6 a5 a4 a3 a2 a1 a0
+        movq        xmm5,               [rdi+2*rax]     ; xx xx xx xx xx xx xx xx b7 b6 b5 b4 b3 b2 b1 b0
+        movq        xmm1,               [rsi+4*rax]     ; xx xx xx xx xx xx xx xx c7 c6 c5 c4 c3 c2 c1 c0
+
+        punpcklbw   xmm2,               xmm6            ; 97 87 96 86 95 85 94 84 93 83 92 82 91 81 90 80
+
+        movq        xmm6,               [rdi+4*rax]     ; xx xx xx xx xx xx xx xx d7 d6 d5 d4 d3 d2 d1 d0
+
+        punpcklbw   xmm0,               xmm5            ; b7 a7 b6 a6 b5 a5 b4 a4 b3 a3 b2 a2 b1 a1 b0 a0
+
+        movq        xmm5,               [rsi+2*rcx]     ; xx xx xx xx xx xx xx xx e7 e6 e5 e4 e3 e2 e1 e0
+
+        punpcklbw   xmm1,               xmm6            ; d7 c7 d6 c6 d5 c5 d4 c4 d3 c3 d2 c2 d1 e1 d0 c0
+
+        movq        xmm6,               [rdi+2*rcx]     ; xx xx xx xx xx xx xx xx f7 f6 f5 f4 f3 f2 f1 f0
+
+        punpcklbw   xmm5,               xmm6            ; f7 e7 f6 e6 f5 e5 f4 e4 f3 e3 f2 e2 f1 e1 f0 e0
+
+        movdqa      xmm6,               xmm1            ;
+        punpckhwd   xmm6,               xmm5            ; f7 e7 d7 c7 f6 e6 d6 c6 f5 e5 d5 c5 f4 e4 d4 c4
+
+        punpcklwd   xmm1,               xmm5            ; f3 e3 d3 c3 f2 e2 d2 c2 f1 e1 d1 c1 f0 e0 d0 c0
+        movdqa      xmm5,               xmm2            ; 97 87 96 86 95 85 94 84 93 83 92 82 91 81 90 80
+
+        punpcklwd   xmm5,               xmm0            ; b3 a3 93 83 b2 a2 92 82 b1 a1 91 81 b0 a0 90 80
+
+        punpckhwd   xmm2,               xmm0            ; b7 a7 97 87 b6 a6 96 86 b5 a5 95 85 b4 a4 94 84
+
+        movdqa      xmm0,               xmm5
+        punpckldq   xmm0,               xmm1            ; f1 e1 d1 c1 b1 a1 91 81 f0 e0 d0 c0 b0 a0 90 80
+
+        punpckhdq   xmm5,               xmm1            ; f3 e3 d3 c3 b3 a3 93 83 f2 e2 d2 c2 b2 a2 92 82
+        movdqa      xmm1,               xmm2            ; b7 a7 97 87 b6 a6 96 86 b5 a5 95 85 b4 a4 94 84
+
+        punpckldq   xmm1,               xmm6            ; f5 e5 d5 c5 b5 a5 95 85 f4 e4 d4 c4 b4 a4 94 84
+
+        punpckhdq   xmm2,               xmm6            ; f7 e7 d7 c7 b7 a7 97 87 f6 e6 d6 c6 b6 a6 96 86
+        movdqa      xmm6,               xmm7            ; 77 67 57 47 37 27 17 07 76 66 56 46 36 26 16 06
+
+        punpcklqdq  xmm6,               xmm2            ; f6 e6 d6 c6 b6 a6 96 86 76 66 56 46 36 26 16 06
+
+        punpckhqdq  xmm7,               xmm2            ; f7 e7 d7 c7 b7 a7 97 87 77 67 57 47 37 27 17 07
+
+%if %2 == 0
+        movdqa      [rsp+_q3],          xmm7            ; save 7
+        movdqa      [rsp+_q2],          xmm6            ; save 6
+%endif
+        movdqa      xmm2,               xmm3            ; 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02
+        punpckhqdq  xmm3,               xmm5            ; f3 e3 d3 c3 b3 a3 93 83 73 63 53 43 33 23 13 03
+        punpcklqdq  xmm2,               xmm5            ; f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
+        movdqa      [rsp+_p1],          xmm2            ; save 2
+
+        movdqa      xmm5,               xmm4            ; 75 65 55 45 35 25 15 05 74 64 54 44 34 24 14 04
+        punpcklqdq  xmm4,               xmm1            ; f4 e4 d4 c4 b4 a4 94 84 74 64 54 44 34 24 14 04
+        movdqa      [rsp+_p0],          xmm3            ; save 3
+
+        punpckhqdq  xmm5,               xmm1            ; f5 e5 d5 c5 b5 a5 95 85 75 65 55 45 35 25 15 05
+
+        movdqa      [rsp+_q0],          xmm4            ; save 4
+        movdqa      [rsp+_q1],          xmm5            ; save 5
+        movdqa      xmm1,               [rsp+_t0]
+
+        movdqa      xmm2,               xmm1            ;
+        punpckhqdq  xmm1,               xmm0            ; f1 e1 d1 c1 b1 a1 91 81 71 61 51 41 31 21 11 01
+        punpcklqdq  xmm2,               xmm0            ; f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00
+
+%if %2 == 0
+        movdqa      [rsp+_p2],          xmm1
+        movdqa      [rsp+_p3],          xmm2
+%endif
+
+%endmacro
+
+%macro LFV_FILTER_MASK_HEV_MASK 0
+        movdqa      xmm0,               xmm6            ; q2
+        psubusb     xmm0,               xmm7            ; q2-q3
+
+        psubusb     xmm7,               xmm6            ; q3-q2
+        movdqa      xmm4,               xmm5            ; q1
+
+        por         xmm7,               xmm0            ; abs (q3-q2)
+        psubusb     xmm4,               xmm6            ; q1-q2
+
+        movdqa      xmm0,               xmm1
+        psubusb     xmm6,               xmm5            ; q2-q1
+
+        por         xmm6,               xmm4            ; abs (q2-q1)
+        psubusb     xmm0,               xmm2            ; p2 - p3;
+
+        psubusb     xmm2,               xmm1            ; p3 - p2;
+        por         xmm0,               xmm2            ; abs(p2-p3)
+
+        movdqa      xmm5,               [rsp+_p1]       ; p1
+        pmaxub      xmm0,               xmm7
+
+        movdqa      xmm2,               xmm5            ; p1
+        psubusb     xmm5,               xmm1            ; p1-p2
+        psubusb     xmm1,               xmm2            ; p2-p1
+
+        movdqa      xmm7,               xmm3            ; p0
+        psubusb     xmm7,               xmm2            ; p0-p1
+
+        por         xmm1,               xmm5            ; abs(p2-p1)
+        pmaxub      xmm0,               xmm6
+
+        pmaxub      xmm0,               xmm1
+        movdqa      xmm1,               xmm2            ; p1
+
+        psubusb     xmm2,               xmm3            ; p1-p0
+
+        por         xmm2,               xmm7            ; abs(p1-p0)
+
+        pmaxub      xmm0,               xmm2
+
+        movdqa      xmm5,               [rsp+_q0]       ; q0
+        movdqa      xmm7,               [rsp+_q1]       ; q1
+
+        mov         rdx,                arg(3)          ; limit
+
+        movdqa      xmm6,               xmm5            ; q0
+        movdqa      xmm4,               xmm7            ; q1
+
+        psubusb     xmm5,               xmm7            ; q0-q1
+        psubusb     xmm7,               xmm6            ; q1-q0
+
+        por         xmm7,               xmm5            ; abs(q1-q0)
+
+        pmaxub      xmm0,               xmm7
+
+        psubusb     xmm0,               [rdx]           ; limit
+
+        mov         rdx,                arg(2)          ; blimit
+        movdqa      xmm5,               xmm4            ; q1
+
+        psubusb     xmm5,               xmm1            ; q1-=p1
+        psubusb     xmm1,               xmm4            ; p1-=q1
+
+        por         xmm5,               xmm1            ; abs(p1-q1)
+        movdqa      xmm1,               xmm3            ; p0
+
+        pand        xmm5,               [GLOBAL(tfe)]   ; set lsb of each byte to zero
+        psubusb     xmm1,               xmm6            ; p0-q0
+
+        movdqa      xmm4,               [rdx]           ; blimit
+        mov         rdx,                arg(4)          ; get thresh
+
+        psrlw       xmm5,               1               ; abs(p1-q1)/2
+        psubusb     xmm6,               xmm3            ; q0-p0
+
+        por         xmm1,               xmm6            ; abs(q0-p0)
+        paddusb     xmm1,               xmm1            ; abs(q0-p0)*2
+        movdqa      xmm3,               [rdx]
+
+        paddusb     xmm1,               xmm5            ; abs (p0 - q0) *2 + abs(p1-q1)/2
+        psubusb     xmm2,               xmm3            ; abs(q1 - q0) > thresh
+
+        psubusb     xmm7,               xmm3            ; abs(p1 - p0)> thresh
+
+        psubusb     xmm1,               xmm4            ; abs (p0 - q0) *2 + abs(p1-q1)/2  > blimit
+        por         xmm2,               xmm7            ; abs(q1 - q0) > thresh || abs(p1 - p0) > thresh
+
+        por         xmm1,               xmm0            ; mask
+        pcmpeqb     xmm2,               xmm0
+
+        pxor        xmm0,               xmm0
+        pcmpeqb     xmm4,               xmm4
+
+        pcmpeqb     xmm1,               xmm0
+        pxor        xmm4,               xmm2
+%endmacro
+
+%macro BV_TRANSPOSE 0
+        ; xmm1 =    f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
+        ; xmm6 =    f3 e3 d3 c3 b3 a3 93 83 73 63 53 43 33 23 13 03
+        ; xmm3 =    f4 e4 d4 c4 b4 a4 94 84 74 64 54 44 34 24 14 04
+        ; xmm7 =    f5 e5 d5 c5 b5 a5 95 85 75 65 55 45 35 25 15 05
+        movdqa      xmm2,               xmm1            ; f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
+        punpcklbw   xmm2,               xmm6            ; 73 72 63 62 53 52 43 42 33 32 23 22 13 12 03 02
+
+        movdqa      xmm4,               xmm3            ; f4 e4 d4 c4 b4 a4 94 84 74 64 54 44 34 24 14 04
+        punpckhbw   xmm1,               xmm6            ; f3 f2 e3 e2 d3 d2 c3 c2 b3 b2 a3 a2 93 92 83 82
+
+        punpcklbw   xmm4,               xmm7            ; 75 74 65 64 55 54 45 44 35 34 25 24 15 14 05 04
+
+        punpckhbw   xmm3,               xmm7            ; f5 f4 e5 e4 d5 d4 c5 c4 b5 b4 a5 a4 95 94 85 84
+
+        movdqa      xmm6,               xmm2            ; 73 72 63 62 53 52 43 42 33 32 23 22 13 12 03 02
+        punpcklwd   xmm2,               xmm4            ; 35 34 33 32 25 24 23 22 15 14 13 12 05 04 03 02
+
+        punpckhwd   xmm6,               xmm4            ; 75 74 73 72 65 64 63 62 55 54 53 52 45 44 43 42
+        movdqa      xmm5,               xmm1            ; f3 f2 e3 e2 d3 d2 c3 c2 b3 b2 a3 a2 93 92 83 82
+
+        punpcklwd   xmm1,               xmm3            ; b5 b4 b3 b2 a5 a4 a3 a2 95 94 93 92 85 84 83 82
+
+        punpckhwd   xmm5,               xmm3            ; f5 f4 f3 f2 e5 e4 e3 e2 d5 d4 d3 d2 c5 c4 c3 c2
+        ; xmm2 = 35 34 33 32 25 24 23 22 15 14 13 12 05 04 03 02
+        ; xmm6 = 75 74 73 72 65 64 63 62 55 54 53 52 45 44 43 42
+        ; xmm1 = b5 b4 b3 b2 a5 a4 a3 a2 95 94 93 92 85 84 83 82
+        ; xmm5 = f5 f4 f3 f2 e5 e4 e3 e2 d5 d4 d3 d2 c5 c4 c3 c2
+%endmacro
+
+%macro BV_WRITEBACK 2
+        movd        [rsi+2],            %1
+        movd        [rsi+4*rax+2],      %2
+        psrldq      %1,                 4
+        psrldq      %2,                 4
+        movd        [rdi+2],            %1
+        movd        [rdi+4*rax+2],      %2
+        psrldq      %1,                 4
+        psrldq      %2,                 4
+        movd        [rsi+2*rax+2],      %1
+        movd        [rsi+2*rcx+2],      %2
+        psrldq      %1,                 4
+        psrldq      %2,                 4
+        movd        [rdi+2*rax+2],      %1
+        movd        [rdi+2*rcx+2],      %2
+%endmacro
+
+%if ABI_IS_32BIT
+
+;void vp8_loop_filter_vertical_edge_sse2
+;(
+;    unsigned char *src_ptr,
+;    int            src_pixel_step,
+;    const char    *blimit,
+;    const char    *limit,
+;    const char    *thresh,
+;)
+global sym(vp8_loop_filter_vertical_edge_sse2)
+sym(vp8_loop_filter_vertical_edge_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub             rsp, lf_var_size
+
+        mov         rsi,        arg(0)                  ; src_ptr
+        movsxd      rax,        dword ptr arg(1)        ; src_pixel_step
+
+        lea         rsi,        [rsi - 4]
+        lea         rdi,        [rsi + rax]             ; rdi points to row +1 for indirect addressing
+        lea         rcx,        [rax*2+rax]
+
+        ;transpose 16x8 to 8x16, and store the 8-line result on stack.
+        TRANSPOSE_16X8 1, 1
+
+        ; calculate filter mask and high edge variance
+        LFV_FILTER_MASK_HEV_MASK
+
+        ; start work on filters
+        B_FILTER 2
+
+        ; tranpose and write back - only work on q1, q0, p0, p1
+        BV_TRANSPOSE
+        ; store 16-line result
+
+        lea         rdx,        [rax]
+        neg         rdx
+
+        BV_WRITEBACK xmm1, xmm5
+
+        lea         rsi,        [rsi+rdx*8]
+        lea         rdi,        [rdi+rdx*8]
+        BV_WRITEBACK xmm2, xmm6
+
+    add rsp, lf_var_size
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+%endif
+
+;void vp8_loop_filter_vertical_edge_uv_sse2
+;(
+;    unsigned char *u,
+;    int            src_pixel_step,
+;    const char    *blimit,
+;    const char    *limit,
+;    const char    *thresh,
+;    unsigned char *v
+;)
+global sym(vp8_loop_filter_vertical_edge_uv_sse2)
+sym(vp8_loop_filter_vertical_edge_uv_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub             rsp, lf_var_size
+
+        mov         rsi,        arg(0)                  ; u_ptr
+        movsxd      rax,        dword ptr arg(1)        ; src_pixel_step
+
+        lea         rsi,        [rsi - 4]
+        lea         rdi,        [rsi + rax]             ; rdi points to row +1 for indirect addressing
+        lea         rcx,        [rax+2*rax]
+
+        ;transpose 16x8 to 8x16, and store the 8-line result on stack.
+        TRANSPOSE_16X8 0, 1
+
+        ; calculate filter mask and high edge variance
+        LFV_FILTER_MASK_HEV_MASK
+
+        ; start work on filters
+        B_FILTER 2
+
+        ; tranpose and write back - only work on q1, q0, p0, p1
+        BV_TRANSPOSE
+
+        lea         rdi,        [rsi + rax]             ; rdi points to row +1 for indirect addressing
+
+        ; store 16-line result
+        BV_WRITEBACK xmm1, xmm5
+
+        mov         rsi,        arg(0)                  ; u_ptr
+        lea         rsi,        [rsi - 4]
+        lea         rdi,        [rsi + rax]             ; rdi points to row +1 for indirect addressing
+        BV_WRITEBACK xmm2, xmm6
+
+    add rsp, lf_var_size
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+%macro MBV_TRANSPOSE 0
+        movdqa      xmm0,               [rsp+_p3]           ; f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00
+        movdqa      xmm1,               xmm0                ; f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00
+
+        punpcklbw   xmm0,               xmm2                ; 71 70 61 60 51 50 41 40 31 30 21 20 11 10 01 00
+        punpckhbw   xmm1,               xmm2                ; f1 f0 e1 e0 d1 d0 c1 c0 b1 b0 a1 a0 91 90 81 80
+
+        movdqa      xmm7,               [rsp+_p1]           ; f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
+        movdqa      xmm6,               xmm7                ; f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
+
+        punpcklbw   xmm7,               [rsp+_p0]           ; 73 72 63 62 53 52 43 42 33 32 23 22 13 12 03 02
+        punpckhbw   xmm6,               [rsp+_p0]           ; f3 f2 e3 e2 d3 d2 c3 c2 b3 b2 a3 a2 93 92 83 82
+
+        movdqa      xmm3,               xmm0                ; 71 70 61 60 51 50 41 40 31 30 21 20 11 10 01 00
+        punpcklwd   xmm0,               xmm7                ; 33 32 31 30 23 22 21 20 13 12 11 10 03 02 01 00
+
+        punpckhwd   xmm3,               xmm7                ; 73 72 71 70 63 62 61 60 53 52 51 50 43 42 41 40
+        movdqa      xmm4,               xmm1                ; f1 f0 e1 e0 d1 d0 c1 c0 b1 b0 a1 a0 91 90 81 80
+
+        punpcklwd   xmm1,               xmm6                ; b3 b2 b1 b0 a3 a2 a1 a0 93 92 91 90 83 82 81 80
+        punpckhwd   xmm4,               xmm6                ; f3 f2 f1 f0 e3 e2 e1 e0 d3 d2 d1 d0 c3 c2 c1 c0
+
+        movdqa      xmm7,               [rsp+_q0]           ; f4 e4 d4 c4 b4 a4 94 84 74 64 54 44 34 24 14 04
+        punpcklbw   xmm7,               [rsp+_q1]           ; 75 74 65 64 55 54 45 44 35 34 25 24 15 14 05 04
+
+        movdqa      xmm6,               xmm5                ; f6 e6 d6 c6 b6 a6 96 86 76 66 56 46 36 26 16 06
+        punpcklbw   xmm6,               [rsp+_q3]           ; 77 76 67 66 57 56 47 46 37 36 27 26 17 16 07 06
+
+        movdqa      xmm2,               xmm7                ; 75 74 65 64 55 54 45 44 35 34 25 24 15 14 05 04
+        punpcklwd   xmm7,               xmm6                ; 37 36 35 34 27 26 25 24 17 16 15 14 07 06 05 04
+
+        punpckhwd   xmm2,               xmm6                ; 77 76 75 74 67 66 65 64 57 56 55 54 47 46 45 44
+        movdqa      xmm6,               xmm0                ; 33 32 31 30 23 22 21 20 13 12 11 10 03 02 01 00
+
+        punpckldq   xmm0,               xmm7                ; 17 16 15 14 13 12 11 10 07 06 05 04 03 02 01 00
+        punpckhdq   xmm6,               xmm7                ; 37 36 35 34 33 32 31 30 27 26 25 24 23 22 21 20
+%endmacro
+
+%macro MBV_WRITEBACK_1 0
+        movq        [rsi],              xmm0
+        movhps      [rdi],              xmm0
+
+        movq        [rsi+2*rax],        xmm6
+        movhps      [rdi+2*rax],        xmm6
+
+        movdqa      xmm0,               xmm3                ; 73 72 71 70 63 62 61 60 53 52 51 50 43 42 41 40
+        punpckldq   xmm0,               xmm2                ; 57 56 55 54 53 52 51 50 47 46 45 44 43 42 41 40
+        punpckhdq   xmm3,               xmm2                ; 77 76 75 74 73 72 71 70 67 66 65 64 63 62 61 60
+
+        movq        [rsi+4*rax],        xmm0
+        movhps      [rdi+4*rax],        xmm0
+
+        movq        [rsi+2*rcx],        xmm3
+        movhps      [rdi+2*rcx],        xmm3
+
+        movdqa      xmm7,               [rsp+_q0]           ; f4 e4 d4 c4 b4 a4 94 84 74 64 54 44 34 24 14 04
+        punpckhbw   xmm7,               [rsp+_q1]           ; f5 f4 e5 e4 d5 d4 c5 c4 b5 b4 a5 a4 95 94 85 84
+        punpckhbw   xmm5,               [rsp+_q3]           ; f7 f6 e7 e6 d7 d6 c7 c6 b7 b6 a7 a6 97 96 87 86
+
+        movdqa      xmm0,               xmm7
+        punpcklwd   xmm0,               xmm5                ; b7 b6 b4 b4 a7 a6 a5 a4 97 96 95 94 87 86 85 84
+        punpckhwd   xmm7,               xmm5                ; f7 f6 f5 f4 e7 e6 e5 e4 d7 d6 d5 d4 c7 c6 c5 c4
+
+        movdqa      xmm5,               xmm1                ; b3 b2 b1 b0 a3 a2 a1 a0 93 92 91 90 83 82 81 80
+        punpckldq   xmm1,               xmm0                ; 97 96 95 94 93 92 91 90 87 86 85 83 84 82 81 80
+        punpckhdq   xmm5,               xmm0                ; b7 b6 b5 b4 b3 b2 b1 b0 a7 a6 a5 a4 a3 a2 a1 a0
+%endmacro
+
+%macro MBV_WRITEBACK_2 0
+        movq        [rsi],              xmm1
+        movhps      [rdi],              xmm1
+
+        movq        [rsi+2*rax],        xmm5
+        movhps      [rdi+2*rax],        xmm5
+
+        movdqa      xmm1,               xmm4                ; f3 f2 f1 f0 e3 e2 e1 e0 d3 d2 d1 d0 c3 c2 c1 c0
+        punpckldq   xmm1,               xmm7                ; d7 d6 d5 d4 d3 d2 d1 d0 c7 c6 c5 c4 c3 c2 c1 c0
+        punpckhdq   xmm4,               xmm7                ; f7 f6 f4 f4 f3 f2 f1 f0 e7 e6 e5 e4 e3 e2 e1 e0
+
+        movq        [rsi+4*rax],        xmm1
+        movhps      [rdi+4*rax],        xmm1
+
+        movq        [rsi+2*rcx],        xmm4
+        movhps      [rdi+2*rcx],        xmm4
+%endmacro
+
+
+;void vp8_mbloop_filter_vertical_edge_sse2
+;(
+;    unsigned char *src_ptr,
+;    int            src_pixel_step,
+;    const char    *blimit,
+;    const char    *limit,
+;    const char    *thresh,
+;)
+global sym(vp8_mbloop_filter_vertical_edge_sse2)
+sym(vp8_mbloop_filter_vertical_edge_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub          rsp, lf_var_size
+
+        mov         rsi,                arg(0)              ; src_ptr
+        movsxd      rax,                dword ptr arg(1)    ; src_pixel_step
+
+        lea         rsi,                [rsi - 4]
+        lea         rdi,                [rsi + rax]         ; rdi points to row +1 for indirect addressing
+        lea         rcx,                [rax*2+rax]
+
+        ; Transpose
+        TRANSPOSE_16X8 1, 0
+
+        ; calculate filter mask and high edge variance
+        LFV_FILTER_MASK_HEV_MASK
+
+        neg         rax
+        ; start work on filters
+        MB_FILTER_AND_WRITEBACK 2
+
+        lea         rsi,                [rsi+rax*8]
+        lea         rdi,                [rdi+rax*8]
+
+        ; transpose and write back
+        MBV_TRANSPOSE
+
+        neg         rax
+
+        MBV_WRITEBACK_1
+
+
+        lea         rsi,                [rsi+rax*8]
+        lea         rdi,                [rdi+rax*8]
+        MBV_WRITEBACK_2
+
+    add rsp, lf_var_size
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_mbloop_filter_vertical_edge_uv_sse2
+;(
+;    unsigned char *u,
+;    int            src_pixel_step,
+;    const char    *blimit,
+;    const char    *limit,
+;    const char    *thresh,
+;    unsigned char *v
+;)
+global sym(vp8_mbloop_filter_vertical_edge_uv_sse2)
+sym(vp8_mbloop_filter_vertical_edge_uv_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub          rsp, lf_var_size
+
+        mov         rsi,                arg(0)              ; u_ptr
+        movsxd      rax,                dword ptr arg(1)    ; src_pixel_step
+
+        lea         rsi,                [rsi - 4]
+        lea         rdi,                [rsi + rax]         ; rdi points to row +1 for indirect addressing
+        lea         rcx,                [rax+2*rax]
+
+        ; Transpose
+        TRANSPOSE_16X8 0, 0
+
+        ; calculate filter mask and high edge variance
+        LFV_FILTER_MASK_HEV_MASK
+
+        ; start work on filters
+        MB_FILTER_AND_WRITEBACK 2
+
+        ; transpose and write back
+        MBV_TRANSPOSE
+
+        mov         rsi,                arg(0)             ;u_ptr
+        lea         rsi,                [rsi - 4]
+        lea         rdi,                [rsi + rax]
+        MBV_WRITEBACK_1
+        mov         rsi,                arg(5)             ;v_ptr
+        lea         rsi,                [rsi - 4]
+        lea         rdi,                [rsi + rax]
+        MBV_WRITEBACK_2
+
+    add rsp, lf_var_size
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_loop_filter_simple_horizontal_edge_sse2
+;(
+;    unsigned char *src_ptr,
+;    int  src_pixel_step,
+;    const char *blimit,
+;)
+global sym(vp8_loop_filter_simple_horizontal_edge_sse2)
+sym(vp8_loop_filter_simple_horizontal_edge_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 3
+    SAVE_XMM 7
+    GET_GOT     rbx
+    ; end prolog
+
+        mov         rcx, arg(0)             ;src_ptr
+        movsxd      rax, dword ptr arg(1)   ;src_pixel_step     ; destination pitch?
+        movdqa      xmm6, [GLOBAL(tfe)]
+        lea         rdx, [rcx + rax]
+        neg         rax
+
+        ; calculate mask
+        movdqa      xmm0, [rdx]             ; q1
+        mov         rdx, arg(2)             ;blimit
+        movdqa      xmm1, [rcx+2*rax]       ; p1
+
+        movdqa      xmm2, xmm1
+        movdqa      xmm3, xmm0
+
+        psubusb     xmm0, xmm1              ; q1-=p1
+        psubusb     xmm1, xmm3              ; p1-=q1
+        por         xmm1, xmm0              ; abs(p1-q1)
+        pand        xmm1, xmm6              ; set lsb of each byte to zero
+        psrlw       xmm1, 1                 ; abs(p1-q1)/2
+
+        movdqa      xmm7, XMMWORD PTR [rdx]
+
+        movdqa      xmm5, [rcx+rax]         ; p0
+        movdqa      xmm4, [rcx]             ; q0
+        movdqa      xmm0, xmm4              ; q0
+        movdqa      xmm6, xmm5              ; p0
+        psubusb     xmm5, xmm4              ; p0-=q0
+        psubusb     xmm4, xmm6              ; q0-=p0
+        por         xmm5, xmm4              ; abs(p0 - q0)
+
+        movdqa      xmm4, [GLOBAL(t80)]
+
+        paddusb     xmm5, xmm5              ; abs(p0-q0)*2
+        paddusb     xmm5, xmm1              ; abs (p0 - q0) *2 + abs(p1-q1)/2
+        psubusb     xmm5, xmm7              ; abs(p0 - q0) *2 + abs(p1-q1)/2  > blimit
+        pxor        xmm7, xmm7
+        pcmpeqb     xmm5, xmm7
+
+
+        ; start work on filters
+        pxor        xmm2, xmm4     ; p1 offset to convert to signed values
+        pxor        xmm3, xmm4     ; q1 offset to convert to signed values
+        psubsb      xmm2, xmm3              ; p1 - q1
+
+        pxor        xmm6, xmm4     ; offset to convert to signed values
+        pxor        xmm0, xmm4     ; offset to convert to signed values
+        movdqa      xmm3, xmm0              ; q0
+        psubsb      xmm0, xmm6              ; q0 - p0
+        paddsb      xmm2, xmm0              ; p1 - q1 + 1 * (q0 - p0)
+        paddsb      xmm2, xmm0              ; p1 - q1 + 2 * (q0 - p0)
+        paddsb      xmm2, xmm0              ; p1 - q1 + 3 * (q0 - p0)
+        pand        xmm5, xmm2              ; mask filter values we don't care about
+
+        movdqa      xmm0, xmm5
+        paddsb      xmm5,        [GLOBAL(t3)]                  ;  3* (q0 - p0) + (p1 - q1) + 4
+        paddsb      xmm0,        [GLOBAL(t4)]                  ; +3 instead of +4
+
+        movdqa      xmm1, [GLOBAL(te0)]
+        movdqa      xmm2, [GLOBAL(t1f)]
+
+;        pxor        xmm7, xmm7
+        pcmpgtb     xmm7, xmm0              ;save sign
+        pand        xmm7, xmm1              ;preserve the upper 3 bits
+        psrlw       xmm0, 3
+        pand        xmm0, xmm2              ;clear out upper 3 bits
+        por         xmm0, xmm7              ;add sign
+        psubsb      xmm3, xmm0              ; q0-= q0sz add
+
+        pxor        xmm7, xmm7
+        pcmpgtb     xmm7, xmm5              ;save sign
+        pand        xmm7, xmm1              ;preserve the upper 3 bits
+        psrlw       xmm5, 3
+        pand        xmm5, xmm2              ;clear out upper 3 bits
+        por         xmm5, xmm7              ;add sign
+        paddsb      xmm6, xmm5              ; p0+= p0 add
+
+        pxor        xmm3, xmm4     ; unoffset
+        movdqa      [rcx], xmm3             ; write back
+
+        pxor        xmm6, xmm4     ; unoffset
+        movdqa      [rcx+rax], xmm6         ; write back
+
+    ; begin epilog
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_loop_filter_simple_vertical_edge_sse2
+;(
+;    unsigned char *src_ptr,
+;    int  src_pixel_step,
+;    const char *blimit,
+;)
+global sym(vp8_loop_filter_simple_vertical_edge_sse2)
+sym(vp8_loop_filter_simple_vertical_edge_sse2):
+    push        rbp         ; save old base pointer value.
+    mov         rbp, rsp    ; set new base pointer value.
+    SHADOW_ARGS_TO_STACK 3
+    SAVE_XMM 7
+    GET_GOT     rbx         ; save callee-saved reg
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub         rsp, 32                         ; reserve 32 bytes
+    %define t0  [rsp + 0]    ;__declspec(align(16)) char t0[16];
+    %define t1  [rsp + 16]   ;__declspec(align(16)) char t1[16];
+
+        mov         rsi, arg(0) ;src_ptr
+        movsxd      rax, dword ptr arg(1) ;src_pixel_step     ; destination pitch?
+
+        lea         rsi,        [rsi - 2 ]
+        lea         rdi,        [rsi + rax]
+        lea         rdx,        [rsi + rax*4]
+        lea         rcx,        [rdx + rax]
+
+        movd        xmm0,       [rsi]                   ; (high 96 bits unused) 03 02 01 00
+        movd        xmm1,       [rdx]                   ; (high 96 bits unused) 43 42 41 40
+        movd        xmm2,       [rdi]                   ; 13 12 11 10
+        movd        xmm3,       [rcx]                   ; 53 52 51 50
+        punpckldq   xmm0,       xmm1                    ; (high 64 bits unused) 43 42 41 40 03 02 01 00
+        punpckldq   xmm2,       xmm3                    ; 53 52 51 50 13 12 11 10
+
+        movd        xmm4,       [rsi + rax*2]           ; 23 22 21 20
+        movd        xmm5,       [rdx + rax*2]           ; 63 62 61 60
+        movd        xmm6,       [rdi + rax*2]           ; 33 32 31 30
+        movd        xmm7,       [rcx + rax*2]           ; 73 72 71 70
+        punpckldq   xmm4,       xmm5                    ; 63 62 61 60 23 22 21 20
+        punpckldq   xmm6,       xmm7                    ; 73 72 71 70 33 32 31 30
+
+        punpcklbw   xmm0,       xmm2                    ; 53 43 52 42 51 41 50 40 13 03 12 02 11 01 10 00
+        punpcklbw   xmm4,       xmm6                    ; 73 63 72 62 71 61 70 60 33 23 32 22 31 21 30 20
+
+        movdqa      xmm1,       xmm0
+        punpcklwd   xmm0,       xmm4                    ; 33 23 13 03 32 22 12 02 31 21 11 01 30 20 10 00
+        punpckhwd   xmm1,       xmm4                    ; 73 63 53 43 72 62 52 42 71 61 51 41 70 60 50 40
+
+        movdqa      xmm2,       xmm0
+        punpckldq   xmm0,       xmm1                    ; 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00
+        punpckhdq   xmm2,       xmm1                    ; 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02
+
+        lea         rsi,        [rsi + rax*8]
+        lea         rdi,        [rsi + rax]
+        lea         rdx,        [rsi + rax*4]
+        lea         rcx,        [rdx + rax]
+
+        movd        xmm4,       [rsi]                   ; 83 82 81 80
+        movd        xmm1,       [rdx]                   ; c3 c2 c1 c0
+        movd        xmm6,       [rdi]                   ; 93 92 91 90
+        movd        xmm3,       [rcx]                   ; d3 d2 d1 d0
+        punpckldq   xmm4,       xmm1                    ; c3 c2 c1 c0 83 82 81 80
+        punpckldq   xmm6,       xmm3                    ; d3 d2 d1 d0 93 92 91 90
+
+        movd        xmm1,       [rsi + rax*2]           ; a3 a2 a1 a0
+        movd        xmm5,       [rdx + rax*2]           ; e3 e2 e1 e0
+        movd        xmm3,       [rdi + rax*2]           ; b3 b2 b1 b0
+        movd        xmm7,       [rcx + rax*2]           ; f3 f2 f1 f0
+        punpckldq   xmm1,       xmm5                    ; e3 e2 e1 e0 a3 a2 a1 a0
+        punpckldq   xmm3,       xmm7                    ; f3 f2 f1 f0 b3 b2 b1 b0
+
+        punpcklbw   xmm4,       xmm6                    ; d3 c3 d2 c2 d1 c1 d0 c0 93 83 92 82 91 81 90 80
+        punpcklbw   xmm1,       xmm3                    ; f3 e3 f2 e2 f1 e1 f0 e0 b3 a3 b2 a2 b1 a1 b0 a0
+
+        movdqa      xmm7,       xmm4
+        punpcklwd   xmm4,       xmm1                    ; b3 a3 93 83 b2 a2 92 82 b1 a1 91 81 b0 a0 90 80
+        punpckhwd   xmm7,       xmm1                    ; f3 e3 d3 c3 f2 e2 d2 c2 f1 e1 d1 c1 f0 e0 d0 c0
+
+        movdqa      xmm6,       xmm4
+        punpckldq   xmm4,       xmm7                    ; f1 e1 d1 c1 b1 a1 91 81 f0 e0 d0 c0 b0 a0 90 80
+        punpckhdq   xmm6,       xmm7                    ; f3 e3 d3 c3 b3 a3 93 83 f2 e2 d2 c2 b2 a2 92 82
+
+        movdqa      xmm1,       xmm0
+        movdqa      xmm3,       xmm2
+
+        punpcklqdq  xmm0,       xmm4                    ; p1  f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00
+        punpckhqdq  xmm1,       xmm4                    ; p0  f1 e1 d1 c1 b1 a1 91 81 71 61 51 41 31 21 11 01
+        punpcklqdq  xmm2,       xmm6                    ; q0  f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
+        punpckhqdq  xmm3,       xmm6                    ; q1  f3 e3 d3 c3 b3 a3 93 83 73 63 53 43 33 23 13 03
+
+        mov         rdx,        arg(2)                          ;blimit
+
+        ; calculate mask
+        movdqa      xmm6,       xmm0                            ; p1
+        movdqa      xmm7,       xmm3                            ; q1
+        psubusb     xmm7,       xmm0                            ; q1-=p1
+        psubusb     xmm6,       xmm3                            ; p1-=q1
+        por         xmm6,       xmm7                            ; abs(p1-q1)
+        pand        xmm6,       [GLOBAL(tfe)]                   ; set lsb of each byte to zero
+        psrlw       xmm6,       1                               ; abs(p1-q1)/2
+
+        movdqa      xmm7, [rdx]
+
+        movdqa      xmm5,       xmm1                            ; p0
+        movdqa      xmm4,       xmm2                            ; q0
+        psubusb     xmm5,       xmm2                            ; p0-=q0
+        psubusb     xmm4,       xmm1                            ; q0-=p0
+        por         xmm5,       xmm4                            ; abs(p0 - q0)
+        paddusb     xmm5,       xmm5                            ; abs(p0-q0)*2
+        paddusb     xmm5,       xmm6                            ; abs (p0 - q0) *2 + abs(p1-q1)/2
+
+        movdqa      xmm4, [GLOBAL(t80)]
+
+        psubusb     xmm5,        xmm7                           ; abs(p0 - q0) *2 + abs(p1-q1)/2  > blimit
+        pxor        xmm7,        xmm7
+        pcmpeqb     xmm5,        xmm7                           ; mm5 = mask
+
+        ; start work on filters
+        movdqa        t0,        xmm0
+        movdqa        t1,        xmm3
+
+        pxor        xmm0,        xmm4                  ; p1 offset to convert to signed values
+        pxor        xmm3,        xmm4                  ; q1 offset to convert to signed values
+        psubsb      xmm0,        xmm3                           ; p1 - q1
+
+        pxor        xmm1,        xmm4                  ; offset to convert to signed values
+        pxor        xmm2,        xmm4                  ; offset to convert to signed values
+
+        movdqa      xmm3,        xmm2                           ; offseted ; q0
+        psubsb      xmm2,        xmm1                           ; q0 - p0
+        paddsb      xmm0,        xmm2                           ; p1 - q1 + 1 * (q0 - p0)
+        paddsb      xmm0,        xmm2                           ; p1 - q1 + 2 * (q0 - p0)
+        paddsb      xmm0,        xmm2                           ; p1 - q1 + 3 * (q0 - p0)
+        pand        xmm5,        xmm0                           ; mask filter values we don't care about
+
+        movdqa      xmm0, xmm5
+        paddsb      xmm5,        [GLOBAL(t3)]                  ;  3* (q0 - p0) + (p1 - q1) + 4
+        paddsb      xmm0,        [GLOBAL(t4)]                  ; +3 instead of +4
+
+        movdqa  xmm6, [GLOBAL(te0)]
+        movdqa  xmm2, [GLOBAL(t1f)]
+
+;        pxor        xmm7, xmm7
+        pcmpgtb     xmm7, xmm0              ;save sign
+        pand        xmm7, xmm6              ;preserve the upper 3 bits
+        psrlw       xmm0, 3
+        pand        xmm0, xmm2              ;clear out upper 3 bits
+        por         xmm0, xmm7              ;add sign
+        psubsb      xmm3, xmm0              ; q0-= q0sz add
+
+        pxor        xmm7, xmm7
+        pcmpgtb     xmm7, xmm5              ;save sign
+        pand        xmm7, xmm6              ;preserve the upper 3 bits
+        psrlw       xmm5, 3
+        pand        xmm5, xmm2              ;clear out upper 3 bits
+        por         xmm5, xmm7              ;add sign
+        paddsb      xmm1, xmm5              ; p0+= p0 add
+
+        pxor        xmm3,        xmm4                  ; unoffset   q0
+        pxor        xmm1,        xmm4                  ; unoffset   p0
+
+        movdqa      xmm0,        t0                             ; p1
+        movdqa      xmm4,        t1                             ; q1
+
+        ; write out order: xmm0 xmm2 xmm1 xmm3
+        lea         rdx,        [rsi + rax*4]
+
+        ; transpose back to write out
+        ; p1  f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00
+        ; p0  f1 e1 d1 c1 b1 a1 91 81 71 61 51 41 31 21 11 01
+        ; q0  f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
+        ; q1  f3 e3 d3 c3 b3 a3 93 83 73 63 53 43 33 23 13 03
+        movdqa      xmm6,       xmm0
+        punpcklbw   xmm0,       xmm1                               ; 71 70 61 60 51 50 41 40 31 30 21 20 11 10 01 00
+        punpckhbw   xmm6,       xmm1                               ; f1 f0 e1 e0 d1 d0 c1 c0 b1 b0 a1 a0 91 90 81 80
+
+        movdqa      xmm5,       xmm3
+        punpcklbw   xmm3,       xmm4                               ; 73 72 63 62 53 52 43 42 33 32 23 22 13 12 03 02
+        punpckhbw   xmm5,       xmm4                               ; f3 f2 e3 e2 d3 d2 c3 c2 b3 b2 a3 a2 93 92 83 82
+
+        movdqa      xmm2,       xmm0
+        punpcklwd   xmm0,       xmm3                               ; 33 32 31 30 23 22 21 20 13 12 11 10 03 02 01 00
+        punpckhwd   xmm2,       xmm3                               ; 73 72 71 70 63 62 61 60 53 52 51 50 43 42 41 40
+
+        movdqa      xmm3,       xmm6
+        punpcklwd   xmm6,       xmm5                               ; b3 b2 b1 b0 a3 a2 a1 a0 93 92 91 90 83 82 81 80
+        punpckhwd   xmm3,       xmm5                               ; f3 f2 f1 f0 e3 e2 e1 e0 d3 d2 d1 d0 c3 c2 c1 c0
+
+        movd        [rsi],      xmm6                               ; write the second 8-line result
+        movd        [rdx],      xmm3
+        psrldq      xmm6,       4
+        psrldq      xmm3,       4
+        movd        [rdi],      xmm6
+        movd        [rcx],      xmm3
+        psrldq      xmm6,       4
+        psrldq      xmm3,       4
+        movd        [rsi + rax*2], xmm6
+        movd        [rdx + rax*2], xmm3
+        psrldq      xmm6,       4
+        psrldq      xmm3,       4
+        movd        [rdi + rax*2], xmm6
+        movd        [rcx + rax*2], xmm3
+
+        neg         rax
+        lea         rsi,        [rsi + rax*8]
+        neg         rax
+        lea         rdi,        [rsi + rax]
+        lea         rdx,        [rsi + rax*4]
+        lea         rcx,        [rdx + rax]
+
+        movd        [rsi],      xmm0                                ; write the first 8-line result
+        movd        [rdx],      xmm2
+        psrldq      xmm0,       4
+        psrldq      xmm2,       4
+        movd        [rdi],      xmm0
+        movd        [rcx],      xmm2
+        psrldq      xmm0,       4
+        psrldq      xmm2,       4
+        movd        [rsi + rax*2], xmm0
+        movd        [rdx + rax*2], xmm2
+        psrldq      xmm0,       4
+        psrldq      xmm2,       4
+        movd        [rdi + rax*2], xmm0
+        movd        [rcx + rax*2], xmm2
+
+    add rsp, 32
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+SECTION_RODATA
+align 16
+tfe:
+    times 16 db 0xfe
+align 16
+t80:
+    times 16 db 0x80
+align 16
+t1s:
+    times 16 db 0x01
+align 16
+t3:
+    times 16 db 0x03
+align 16
+t4:
+    times 16 db 0x04
+align 16
+ones:
+    times 8 dw 0x0001
+align 16
+s9:
+    times 8 dw 0x0900
+align 16
+s63:
+    times 8 dw 0x003f
+align 16
+te0:
+    times 16 db 0xe0
+align 16
+t1f:
+    times 16 db 0x1f
diff --git a/vp8/common/x86/loopfilter_x86.c b/vp8/common/x86/loopfilter_x86.c
new file mode 100644 (file)
index 0000000..6586004
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vp8/common/loopfilter.h"
+
+#define prototype_loopfilter(sym) \
+    void sym(unsigned char *src, int pitch, const unsigned char *blimit,\
+             const unsigned char *limit, const unsigned char *thresh, int count)
+
+#define prototype_loopfilter_nc(sym) \
+    void sym(unsigned char *src, int pitch, const unsigned char *blimit,\
+             const unsigned char *limit, const unsigned char *thresh)
+
+#define prototype_simple_loopfilter(sym) \
+    void sym(unsigned char *y, int ystride, const unsigned char *blimit)
+
+prototype_loopfilter(vp8_mbloop_filter_vertical_edge_mmx);
+prototype_loopfilter(vp8_mbloop_filter_horizontal_edge_mmx);
+prototype_loopfilter(vp8_loop_filter_vertical_edge_mmx);
+prototype_loopfilter(vp8_loop_filter_horizontal_edge_mmx);
+prototype_simple_loopfilter(vp8_loop_filter_simple_horizontal_edge_mmx);
+prototype_simple_loopfilter(vp8_loop_filter_simple_vertical_edge_mmx);
+
+#if HAVE_SSE2 && ARCH_X86_64
+prototype_loopfilter(vp8_loop_filter_bv_y_sse2);
+prototype_loopfilter(vp8_loop_filter_bh_y_sse2);
+#else
+prototype_loopfilter_nc(vp8_loop_filter_vertical_edge_sse2);
+prototype_loopfilter_nc(vp8_loop_filter_horizontal_edge_sse2);
+#endif
+prototype_loopfilter_nc(vp8_mbloop_filter_vertical_edge_sse2);
+prototype_loopfilter_nc(vp8_mbloop_filter_horizontal_edge_sse2);
+
+extern loop_filter_uvfunction vp8_loop_filter_horizontal_edge_uv_sse2;
+extern loop_filter_uvfunction vp8_loop_filter_vertical_edge_uv_sse2;
+extern loop_filter_uvfunction vp8_mbloop_filter_horizontal_edge_uv_sse2;
+extern loop_filter_uvfunction vp8_mbloop_filter_vertical_edge_uv_sse2;
+
+#if HAVE_MMX
+/* Horizontal MB filtering */
+void vp8_loop_filter_mbh_mmx(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                             int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    vp8_mbloop_filter_horizontal_edge_mmx(y_ptr, y_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 2);
+
+    if (u_ptr)
+        vp8_mbloop_filter_horizontal_edge_mmx(u_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
+
+    if (v_ptr)
+        vp8_mbloop_filter_horizontal_edge_mmx(v_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
+}
+
+
+/* Vertical MB Filtering */
+void vp8_loop_filter_mbv_mmx(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                             int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    vp8_mbloop_filter_vertical_edge_mmx(y_ptr, y_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 2);
+
+    if (u_ptr)
+        vp8_mbloop_filter_vertical_edge_mmx(u_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
+
+    if (v_ptr)
+        vp8_mbloop_filter_vertical_edge_mmx(v_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
+}
+
+
+/* Horizontal B Filtering */
+void vp8_loop_filter_bh_mmx(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                            int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    vp8_loop_filter_horizontal_edge_mmx(y_ptr + 4 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+    vp8_loop_filter_horizontal_edge_mmx(y_ptr + 8 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+    vp8_loop_filter_horizontal_edge_mmx(y_ptr + 12 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+
+    if (u_ptr)
+        vp8_loop_filter_horizontal_edge_mmx(u_ptr + 4 * uv_stride, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
+
+    if (v_ptr)
+        vp8_loop_filter_horizontal_edge_mmx(v_ptr + 4 * uv_stride, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
+}
+
+
+void vp8_loop_filter_bhs_mmx(unsigned char *y_ptr, int y_stride, const unsigned char *blimit)
+{
+    vp8_loop_filter_simple_horizontal_edge_mmx(y_ptr + 4 * y_stride, y_stride, blimit);
+    vp8_loop_filter_simple_horizontal_edge_mmx(y_ptr + 8 * y_stride, y_stride, blimit);
+    vp8_loop_filter_simple_horizontal_edge_mmx(y_ptr + 12 * y_stride, y_stride, blimit);
+}
+
+
+/* Vertical B Filtering */
+void vp8_loop_filter_bv_mmx(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                            int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    vp8_loop_filter_vertical_edge_mmx(y_ptr + 4, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+    vp8_loop_filter_vertical_edge_mmx(y_ptr + 8, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+    vp8_loop_filter_vertical_edge_mmx(y_ptr + 12, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+
+    if (u_ptr)
+        vp8_loop_filter_vertical_edge_mmx(u_ptr + 4, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
+
+    if (v_ptr)
+        vp8_loop_filter_vertical_edge_mmx(v_ptr + 4, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
+}
+
+
+void vp8_loop_filter_bvs_mmx(unsigned char *y_ptr, int y_stride, const unsigned char *blimit)
+{
+    vp8_loop_filter_simple_vertical_edge_mmx(y_ptr + 4, y_stride, blimit);
+    vp8_loop_filter_simple_vertical_edge_mmx(y_ptr + 8, y_stride, blimit);
+    vp8_loop_filter_simple_vertical_edge_mmx(y_ptr + 12, y_stride, blimit);
+}
+#endif
+
+
+/* Horizontal MB filtering */
+#if HAVE_SSE2
+void vp8_loop_filter_mbh_sse2(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                              int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    vp8_mbloop_filter_horizontal_edge_sse2(y_ptr, y_stride, lfi->mblim, lfi->lim, lfi->hev_thr);
+
+    if (u_ptr)
+        vp8_mbloop_filter_horizontal_edge_uv_sse2(u_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, v_ptr);
+}
+
+
+/* Vertical MB Filtering */
+void vp8_loop_filter_mbv_sse2(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                              int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+    vp8_mbloop_filter_vertical_edge_sse2(y_ptr, y_stride, lfi->mblim, lfi->lim, lfi->hev_thr);
+
+    if (u_ptr)
+        vp8_mbloop_filter_vertical_edge_uv_sse2(u_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, v_ptr);
+}
+
+
+/* Horizontal B Filtering */
+void vp8_loop_filter_bh_sse2(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                             int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+#if ARCH_X86_64
+    vp8_loop_filter_bh_y_sse2(y_ptr, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+#else
+    vp8_loop_filter_horizontal_edge_sse2(y_ptr + 4 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr);
+    vp8_loop_filter_horizontal_edge_sse2(y_ptr + 8 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr);
+    vp8_loop_filter_horizontal_edge_sse2(y_ptr + 12 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr);
+#endif
+
+    if (u_ptr)
+        vp8_loop_filter_horizontal_edge_uv_sse2(u_ptr + 4 * uv_stride, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, v_ptr + 4 * uv_stride);
+}
+
+
+void vp8_loop_filter_bhs_sse2(unsigned char *y_ptr, int y_stride, const unsigned char *blimit)
+{
+    vp8_loop_filter_simple_horizontal_edge_sse2(y_ptr + 4 * y_stride, y_stride, blimit);
+    vp8_loop_filter_simple_horizontal_edge_sse2(y_ptr + 8 * y_stride, y_stride, blimit);
+    vp8_loop_filter_simple_horizontal_edge_sse2(y_ptr + 12 * y_stride, y_stride, blimit);
+}
+
+
+/* Vertical B Filtering */
+void vp8_loop_filter_bv_sse2(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                             int y_stride, int uv_stride, loop_filter_info *lfi)
+{
+#if ARCH_X86_64
+    vp8_loop_filter_bv_y_sse2(y_ptr, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
+#else
+    vp8_loop_filter_vertical_edge_sse2(y_ptr + 4, y_stride, lfi->blim, lfi->lim, lfi->hev_thr);
+    vp8_loop_filter_vertical_edge_sse2(y_ptr + 8, y_stride, lfi->blim, lfi->lim, lfi->hev_thr);
+    vp8_loop_filter_vertical_edge_sse2(y_ptr + 12, y_stride, lfi->blim, lfi->lim, lfi->hev_thr);
+#endif
+
+    if (u_ptr)
+        vp8_loop_filter_vertical_edge_uv_sse2(u_ptr + 4, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, v_ptr + 4);
+}
+
+
+void vp8_loop_filter_bvs_sse2(unsigned char *y_ptr, int y_stride, const unsigned char *blimit)
+{
+    vp8_loop_filter_simple_vertical_edge_sse2(y_ptr + 4, y_stride, blimit);
+    vp8_loop_filter_simple_vertical_edge_sse2(y_ptr + 8, y_stride, blimit);
+    vp8_loop_filter_simple_vertical_edge_sse2(y_ptr + 12, y_stride, blimit);
+}
+
+#endif
diff --git a/vp8/common/x86/mfqe_sse2.asm b/vp8/common/x86/mfqe_sse2.asm
new file mode 100644 (file)
index 0000000..10d21f3
--- /dev/null
@@ -0,0 +1,281 @@
+;
+;  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;void vp8_filter_by_weight16x16_sse2
+;(
+;    unsigned char *src,
+;    int            src_stride,
+;    unsigned char *dst,
+;    int            dst_stride,
+;    int            src_weight
+;)
+global sym(vp8_filter_by_weight16x16_sse2)
+sym(vp8_filter_by_weight16x16_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    SAVE_XMM 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    movd        xmm0, arg(4)                ; src_weight
+    pshuflw     xmm0, xmm0, 0x0             ; replicate to all low words
+    punpcklqdq  xmm0, xmm0                  ; replicate to all hi words
+
+    movdqa      xmm1, [GLOBAL(tMFQE)]
+    psubw       xmm1, xmm0                  ; dst_weight
+
+    mov         rax, arg(0)                 ; src
+    mov         rsi, arg(1)                 ; src_stride
+    mov         rdx, arg(2)                 ; dst
+    mov         rdi, arg(3)                 ; dst_stride
+
+    mov         rcx, 16                     ; loop count
+    pxor        xmm6, xmm6
+
+.combine
+    movdqa      xmm2, [rax]
+    movdqa      xmm4, [rdx]
+    add         rax, rsi
+
+    ; src * src_weight
+    movdqa      xmm3, xmm2
+    punpcklbw   xmm2, xmm6
+    punpckhbw   xmm3, xmm6
+    pmullw      xmm2, xmm0
+    pmullw      xmm3, xmm0
+
+    ; dst * dst_weight
+    movdqa      xmm5, xmm4
+    punpcklbw   xmm4, xmm6
+    punpckhbw   xmm5, xmm6
+    pmullw      xmm4, xmm1
+    pmullw      xmm5, xmm1
+
+    ; sum, round and shift
+    paddw       xmm2, xmm4
+    paddw       xmm3, xmm5
+    paddw       xmm2, [GLOBAL(tMFQE_round)]
+    paddw       xmm3, [GLOBAL(tMFQE_round)]
+    psrlw       xmm2, 4
+    psrlw       xmm3, 4
+
+    packuswb    xmm2, xmm3
+    movdqa      [rdx], xmm2
+    add         rdx, rdi
+
+    dec         rcx
+    jnz         .combine
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+
+    ret
+
+;void vp8_filter_by_weight8x8_sse2
+;(
+;    unsigned char *src,
+;    int            src_stride,
+;    unsigned char *dst,
+;    int            dst_stride,
+;    int            src_weight
+;)
+global sym(vp8_filter_by_weight8x8_sse2)
+sym(vp8_filter_by_weight8x8_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    movd        xmm0, arg(4)                ; src_weight
+    pshuflw     xmm0, xmm0, 0x0             ; replicate to all low words
+    punpcklqdq  xmm0, xmm0                  ; replicate to all hi words
+
+    movdqa      xmm1, [GLOBAL(tMFQE)]
+    psubw       xmm1, xmm0                  ; dst_weight
+
+    mov         rax, arg(0)                 ; src
+    mov         rsi, arg(1)                 ; src_stride
+    mov         rdx, arg(2)                 ; dst
+    mov         rdi, arg(3)                 ; dst_stride
+
+    mov         rcx, 8                      ; loop count
+    pxor        xmm4, xmm4
+
+.combine
+    movq        xmm2, [rax]
+    movq        xmm3, [rdx]
+    add         rax, rsi
+
+    ; src * src_weight
+    punpcklbw   xmm2, xmm4
+    pmullw      xmm2, xmm0
+
+    ; dst * dst_weight
+    punpcklbw   xmm3, xmm4
+    pmullw      xmm3, xmm1
+
+    ; sum, round and shift
+    paddw       xmm2, xmm3
+    paddw       xmm2, [GLOBAL(tMFQE_round)]
+    psrlw       xmm2, 4
+
+    packuswb    xmm2, xmm4
+    movq        [rdx], xmm2
+    add         rdx, rdi
+
+    dec         rcx
+    jnz         .combine
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+
+    ret
+
+;void vp8_variance_and_sad_16x16_sse2 | arg
+;(
+;    unsigned char *src1,          0
+;    int            stride1,       1
+;    unsigned char *src2,          2
+;    int            stride2,       3
+;    unsigned int  *variance,      4
+;    unsigned int  *sad,           5
+;)
+global sym(vp8_variance_and_sad_16x16_sse2)
+sym(vp8_variance_and_sad_16x16_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    mov         rax,        arg(0)          ; src1
+    mov         rcx,        arg(1)          ; stride1
+    mov         rdx,        arg(2)          ; src2
+    mov         rdi,        arg(3)          ; stride2
+
+    mov         rsi,        16              ; block height
+
+    ; Prep accumulator registers
+    pxor        xmm3, xmm3                  ; SAD
+    pxor        xmm4, xmm4                  ; sum of src2
+    pxor        xmm5, xmm5                  ; sum of src2^2
+
+    ; Because we're working with the actual output frames
+    ; we can't depend on any kind of data alignment.
+.accumulate
+    movdqa      xmm0, [rax]                 ; src1
+    movdqa      xmm1, [rdx]                 ; src2
+    add         rax, rcx                    ; src1 + stride1
+    add         rdx, rdi                    ; src2 + stride2
+
+    ; SAD(src1, src2)
+    psadbw      xmm0, xmm1
+    paddusw     xmm3, xmm0
+
+    ; SUM(src2)
+    pxor        xmm2, xmm2
+    psadbw      xmm2, xmm1                  ; sum src2 by misusing SAD against 0
+    paddusw     xmm4, xmm2
+
+    ; pmaddubsw would be ideal if it took two unsigned values. instead,
+    ; it expects a signed and an unsigned value. so instead we zero extend
+    ; and operate on words.
+    pxor        xmm2, xmm2
+    movdqa      xmm0, xmm1
+    punpcklbw   xmm0, xmm2
+    punpckhbw   xmm1, xmm2
+    pmaddwd     xmm0, xmm0
+    pmaddwd     xmm1, xmm1
+    paddd       xmm5, xmm0
+    paddd       xmm5, xmm1
+
+    sub         rsi,        1
+    jnz         .accumulate
+
+    ; phaddd only operates on adjacent double words.
+    ; Finalize SAD and store
+    movdqa      xmm0, xmm3
+    psrldq      xmm0, 8
+    paddusw     xmm0, xmm3
+    paddd       xmm0, [GLOBAL(t128)]
+    psrld       xmm0, 8
+
+    mov         rax,  arg(5)
+    movd        [rax], xmm0
+
+    ; Accumulate sum of src2
+    movdqa      xmm0, xmm4
+    psrldq      xmm0, 8
+    paddusw     xmm0, xmm4
+    ; Square src2. Ignore high value
+    pmuludq     xmm0, xmm0
+    psrld       xmm0, 8
+
+    ; phaddw could be used to sum adjacent values but we want
+    ; all the values summed. promote to doubles, accumulate,
+    ; shift and sum
+    pxor        xmm2, xmm2
+    movdqa      xmm1, xmm5
+    punpckldq   xmm1, xmm2
+    punpckhdq   xmm5, xmm2
+    paddd       xmm1, xmm5
+    movdqa      xmm2, xmm1
+    psrldq      xmm1, 8
+    paddd       xmm1, xmm2
+
+    psubd       xmm1, xmm0
+
+    ; (variance + 128) >> 8
+    paddd       xmm1, [GLOBAL(t128)]
+    psrld       xmm1, 8
+    mov         rax,  arg(4)
+
+    movd        [rax], xmm1
+
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+SECTION_RODATA
+align 16
+t128:
+    ddq 128
+align 16
+tMFQE: ; 1 << MFQE_PRECISION
+    times 8 dw 0x10
+align 16
+tMFQE_round: ; 1 << (MFQE_PRECISION - 1)
+    times 8 dw 0x08
+
diff --git a/vp8/common/x86/postproc_mmx.asm b/vp8/common/x86/postproc_mmx.asm
new file mode 100644 (file)
index 0000000..d24f740
--- /dev/null
@@ -0,0 +1,579 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+%define VP8_FILTER_WEIGHT 128
+%define VP8_FILTER_SHIFT  7
+
+;void vp8_post_proc_down_and_across_mmx
+;(
+;    unsigned char *src_ptr,
+;    unsigned char *dst_ptr,
+;    int src_pixels_per_line,
+;    int dst_pixels_per_line,
+;    int rows,
+;    int cols,
+;    int flimit
+;)
+global sym(vp8_post_proc_down_and_across_mmx)
+sym(vp8_post_proc_down_and_across_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+%if ABI_IS_32BIT=1 && CONFIG_PIC=1
+    ; move the global rd onto the stack, since we don't have enough registers
+    ; to do PIC addressing
+    movq        mm0, [GLOBAL(rd)]
+    sub         rsp, 8
+    movq        [rsp], mm0
+%define RD [rsp]
+%else
+%define RD [GLOBAL(rd)]
+%endif
+
+        push        rbx
+        lea         rbx, [GLOBAL(Blur)]
+        movd        mm2, dword ptr arg(6) ;flimit
+        punpcklwd   mm2, mm2
+        punpckldq   mm2, mm2
+
+        mov         rsi,        arg(0) ;src_ptr
+        mov         rdi,        arg(1) ;dst_ptr
+
+        movsxd      rcx, DWORD PTR arg(4) ;rows
+        movsxd      rax, DWORD PTR arg(2) ;src_pixels_per_line ; destination pitch?
+        pxor        mm0, mm0              ; mm0 = 00000000
+
+.nextrow:
+
+        xor         rdx,        rdx       ; clear out rdx for use as loop counter
+.nextcol:
+
+        pxor        mm7, mm7              ; mm7 = 00000000
+        movq        mm6, [rbx + 32 ]      ; mm6 = kernel 2 taps
+        movq        mm3, [rsi]            ; mm4 = r0 p0..p7
+        punpcklbw   mm3, mm0              ; mm3 = p0..p3
+        movq        mm1, mm3              ; mm1 = p0..p3
+        pmullw      mm3, mm6              ; mm3 *= kernel 2 modifiers
+
+        movq        mm6, [rbx + 48]       ; mm6 = kernel 3 taps
+        movq        mm5, [rsi + rax]      ; mm4 = r1 p0..p7
+        punpcklbw   mm5, mm0              ; mm5 = r1 p0..p3
+        pmullw      mm6, mm5              ; mm6 *= p0..p3 * kernel 3 modifiers
+        paddusw     mm3, mm6              ; mm3 += mm6
+
+        ; thresholding
+        movq        mm7, mm1              ; mm7 = r0 p0..p3
+        psubusw     mm7, mm5              ; mm7 = r0 p0..p3 - r1 p0..p3
+        psubusw     mm5, mm1              ; mm5 = r1 p0..p3 - r0 p0..p3
+        paddusw     mm7, mm5              ; mm7 = abs(r0 p0..p3 - r1 p0..p3)
+        pcmpgtw     mm7, mm2
+
+        movq        mm6, [rbx + 64 ]      ; mm6 = kernel 4 modifiers
+        movq        mm5, [rsi + 2*rax]    ; mm4 = r2 p0..p7
+        punpcklbw   mm5, mm0              ; mm5 = r2 p0..p3
+        pmullw      mm6, mm5              ; mm5 *= kernel 4 modifiers
+        paddusw     mm3, mm6              ; mm3 += mm5
+
+        ; thresholding
+        movq        mm6, mm1              ; mm6 = r0 p0..p3
+        psubusw     mm6, mm5              ; mm6 = r0 p0..p3 - r2 p0..p3
+        psubusw     mm5, mm1              ; mm5 = r2 p0..p3 - r2 p0..p3
+        paddusw     mm6, mm5              ; mm6 = abs(r0 p0..p3 - r2 p0..p3)
+        pcmpgtw     mm6, mm2
+        por         mm7, mm6              ; accumulate thresholds
+
+
+        neg         rax
+        movq        mm6, [rbx ]           ; kernel 0 taps
+        movq        mm5, [rsi+2*rax]      ; mm4 = r-2 p0..p7
+        punpcklbw   mm5, mm0              ; mm5 = r-2 p0..p3
+        pmullw      mm6, mm5              ; mm5 *= kernel 0 modifiers
+        paddusw     mm3, mm6              ; mm3 += mm5
+
+        ; thresholding
+        movq        mm6, mm1              ; mm6 = r0 p0..p3
+        psubusw     mm6, mm5              ; mm6 = p0..p3 - r-2 p0..p3
+        psubusw     mm5, mm1              ; mm5 = r-2 p0..p3 - p0..p3
+        paddusw     mm6, mm5              ; mm6 = abs(r0 p0..p3 - r-2 p0..p3)
+        pcmpgtw     mm6, mm2
+        por         mm7, mm6              ; accumulate thresholds
+
+        movq        mm6, [rbx + 16]       ; kernel 1 taps
+        movq        mm4, [rsi+rax]        ; mm4 = r-1 p0..p7
+        punpcklbw   mm4, mm0              ; mm4 = r-1 p0..p3
+        pmullw      mm6, mm4              ; mm4 *= kernel 1 modifiers.
+        paddusw     mm3, mm6              ; mm3 += mm5
+
+        ; thresholding
+        movq        mm6, mm1              ; mm6 = r0 p0..p3
+        psubusw     mm6, mm4              ; mm6 = p0..p3 - r-2 p0..p3
+        psubusw     mm4, mm1              ; mm5 = r-1 p0..p3 - p0..p3
+        paddusw     mm6, mm4              ; mm6 = abs(r0 p0..p3 - r-1 p0..p3)
+        pcmpgtw     mm6, mm2
+        por         mm7, mm6              ; accumulate thresholds
+
+
+        paddusw     mm3, RD               ; mm3 += round value
+        psraw       mm3, VP8_FILTER_SHIFT     ; mm3 /= 128
+
+        pand        mm1, mm7              ; mm1 select vals > thresh from source
+        pandn       mm7, mm3              ; mm7 select vals < thresh from blurred result
+        paddusw     mm1, mm7              ; combination
+
+        packuswb    mm1, mm0              ; pack to bytes
+
+        movd        [rdi], mm1            ;
+        neg         rax                   ; pitch is positive
+
+
+        add         rsi, 4
+        add         rdi, 4
+        add         rdx, 4
+
+        cmp         edx, dword ptr arg(5) ;cols
+        jl          .nextcol
+        ; done with the all cols, start the across filtering in place
+        sub         rsi, rdx
+        sub         rdi, rdx
+
+        ; dup the first byte into the left border 8 times
+        movq        mm1,   [rdi]
+        punpcklbw   mm1,   mm1
+        punpcklwd   mm1,   mm1
+        punpckldq   mm1,   mm1
+
+        mov         rdx,    -8
+        movq        [rdi+rdx], mm1
+
+        ; dup the last byte into the right border
+        movsxd      rdx,    dword arg(5)
+        movq        mm1,   [rdi + rdx + -1]
+        punpcklbw   mm1,   mm1
+        punpcklwd   mm1,   mm1
+        punpckldq   mm1,   mm1
+        movq        [rdi+rdx], mm1
+
+
+        push        rax
+        xor         rdx,    rdx
+        mov         rax,    [rdi-4];
+
+.acrossnextcol:
+        pxor        mm7, mm7              ; mm7 = 00000000
+        movq        mm6, [rbx + 32 ]      ;
+        movq        mm4, [rdi+rdx]        ; mm4 = p0..p7
+        movq        mm3, mm4              ; mm3 = p0..p7
+        punpcklbw   mm3, mm0              ; mm3 = p0..p3
+        movq        mm1, mm3              ; mm1 = p0..p3
+        pmullw      mm3, mm6              ; mm3 *= kernel 2 modifiers
+
+        movq        mm6, [rbx + 48]
+        psrlq       mm4, 8                ; mm4 = p1..p7
+        movq        mm5, mm4              ; mm5 = p1..p7
+        punpcklbw   mm5, mm0              ; mm5 = p1..p4
+        pmullw      mm6, mm5              ; mm6 *= p1..p4 * kernel 3 modifiers
+        paddusw     mm3, mm6              ; mm3 += mm6
+
+        ; thresholding
+        movq        mm7, mm1              ; mm7 = p0..p3
+        psubusw     mm7, mm5              ; mm7 = p0..p3 - p1..p4
+        psubusw     mm5, mm1              ; mm5 = p1..p4 - p0..p3
+        paddusw     mm7, mm5              ; mm7 = abs(p0..p3 - p1..p4)
+        pcmpgtw     mm7, mm2
+
+        movq        mm6, [rbx + 64 ]
+        psrlq       mm4, 8                ; mm4 = p2..p7
+        movq        mm5, mm4              ; mm5 = p2..p7
+        punpcklbw   mm5, mm0              ; mm5 = p2..p5
+        pmullw      mm6, mm5              ; mm5 *= kernel 4 modifiers
+        paddusw     mm3, mm6              ; mm3 += mm5
+
+        ; thresholding
+        movq        mm6, mm1              ; mm6 = p0..p3
+        psubusw     mm6, mm5              ; mm6 = p0..p3 - p1..p4
+        psubusw     mm5, mm1              ; mm5 = p1..p4 - p0..p3
+        paddusw     mm6, mm5              ; mm6 = abs(p0..p3 - p1..p4)
+        pcmpgtw     mm6, mm2
+        por         mm7, mm6              ; accumulate thresholds
+
+
+        movq        mm6, [rbx ]
+        movq        mm4, [rdi+rdx-2]      ; mm4 = p-2..p5
+        movq        mm5, mm4              ; mm5 = p-2..p5
+        punpcklbw   mm5, mm0              ; mm5 = p-2..p1
+        pmullw      mm6, mm5              ; mm5 *= kernel 0 modifiers
+        paddusw     mm3, mm6              ; mm3 += mm5
+
+        ; thresholding
+        movq        mm6, mm1              ; mm6 = p0..p3
+        psubusw     mm6, mm5              ; mm6 = p0..p3 - p1..p4
+        psubusw     mm5, mm1              ; mm5 = p1..p4 - p0..p3
+        paddusw     mm6, mm5              ; mm6 = abs(p0..p3 - p1..p4)
+        pcmpgtw     mm6, mm2
+        por         mm7, mm6              ; accumulate thresholds
+
+        movq        mm6, [rbx + 16]
+        psrlq       mm4, 8                ; mm4 = p-1..p5
+        punpcklbw   mm4, mm0              ; mm4 = p-1..p2
+        pmullw      mm6, mm4              ; mm4 *= kernel 1 modifiers.
+        paddusw     mm3, mm6              ; mm3 += mm5
+
+        ; thresholding
+        movq        mm6, mm1              ; mm6 = p0..p3
+        psubusw     mm6, mm4              ; mm6 = p0..p3 - p1..p4
+        psubusw     mm4, mm1              ; mm5 = p1..p4 - p0..p3
+        paddusw     mm6, mm4              ; mm6 = abs(p0..p3 - p1..p4)
+        pcmpgtw     mm6, mm2
+        por         mm7, mm6              ; accumulate thresholds
+
+        paddusw     mm3, RD               ; mm3 += round value
+        psraw       mm3, VP8_FILTER_SHIFT     ; mm3 /= 128
+
+        pand        mm1, mm7              ; mm1 select vals > thresh from source
+        pandn       mm7, mm3              ; mm7 select vals < thresh from blurred result
+        paddusw     mm1, mm7              ; combination
+
+        packuswb    mm1, mm0              ; pack to bytes
+        mov         DWORD PTR [rdi+rdx-4],  eax   ; store previous four bytes
+        movd        eax,    mm1
+
+        add         rdx, 4
+        cmp         edx, dword ptr arg(5) ;cols
+        jl          .acrossnextcol;
+
+        mov         DWORD PTR [rdi+rdx-4],  eax
+        pop         rax
+
+        ; done with this rwo
+        add         rsi,rax               ; next line
+        movsxd      rax, dword ptr arg(3) ;dst_pixels_per_line ; destination pitch?
+        add         rdi,rax               ; next destination
+        movsxd      rax, dword ptr arg(2) ;src_pixels_per_line ; destination pitch?
+
+        dec         rcx                   ; decrement count
+        jnz         .nextrow               ; next row
+        pop         rbx
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+%undef RD
+
+
+;void vp8_mbpost_proc_down_mmx(unsigned char *dst,
+;                             int pitch, int rows, int cols,int flimit)
+extern sym(vp8_rv)
+global sym(vp8_mbpost_proc_down_mmx)
+sym(vp8_mbpost_proc_down_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub         rsp, 136
+
+    ; unsigned char d[16][8] at [rsp]
+    ; create flimit2 at [rsp+128]
+    mov         eax, dword ptr arg(4) ;flimit
+    mov         [rsp+128], eax
+    mov         [rsp+128+4], eax
+%define flimit2 [rsp+128]
+
+%if ABI_IS_32BIT=0
+    lea         r8,       [GLOBAL(sym(vp8_rv))]
+%endif
+
+    ;rows +=8;
+    add         dword ptr arg(2), 8
+
+    ;for(c=0; c<cols; c+=4)
+.loop_col:
+            mov         rsi,        arg(0)  ;s
+            pxor        mm0,        mm0     ;
+
+            movsxd      rax,        dword ptr arg(1) ;pitch       ;
+
+            ; this copies the last row down into the border 8 rows
+            mov         rdi,        rsi
+            mov         rdx,        arg(2)
+            sub         rdx,        9
+            imul        rdx,        rax
+            lea         rdi,        [rdi+rdx]
+            movq        mm1,        QWORD ptr[rdi]              ; first row
+            mov         rcx,        8
+.init_borderd                                                    ; initialize borders
+            lea         rdi,        [rdi + rax]
+            movq        [rdi],      xmm1
+
+            dec         rcx
+            jne         .init_borderd
+
+            neg         rax                                     ; rax = -pitch
+
+            ; this copies the first row up into the border 8 rows
+            mov         rdi,        rsi
+            movq        mm1,        QWORD ptr[rdi]              ; first row
+            mov         rcx,        8
+.init_border                                                    ; initialize borders
+            lea         rdi,        [rdi + rax]
+            movq        [rdi],      mm1
+
+            dec         rcx
+            jne         .init_border
+
+
+            lea         rsi,        [rsi + rax*8];              ; rdi = s[-pitch*8]
+            neg         rax
+
+
+            pxor        mm5,        mm5
+            pxor        mm6,        mm6     ;
+
+            pxor        mm7,        mm7     ;
+            mov         rdi,        rsi
+
+            mov         rcx,        15          ;
+
+.loop_initvar:
+            movd        mm1,        DWORD PTR [rdi];
+            punpcklbw   mm1,        mm0     ;
+
+            paddw       mm5,        mm1     ;
+            pmullw      mm1,        mm1     ;
+
+            movq        mm2,        mm1     ;
+            punpcklwd   mm1,        mm0     ;
+
+            punpckhwd   mm2,        mm0     ;
+            paddd       mm6,        mm1     ;
+
+            paddd       mm7,        mm2     ;
+            lea         rdi,        [rdi+rax]   ;
+
+            dec         rcx
+            jne         .loop_initvar
+            ;save the var and sum
+            xor         rdx,        rdx
+.loop_row:
+            movd        mm1,        DWORD PTR [rsi]     ; [s-pitch*8]
+            movd        mm2,        DWORD PTR [rdi]     ; [s+pitch*7]
+
+            punpcklbw   mm1,        mm0
+            punpcklbw   mm2,        mm0
+
+            paddw       mm5,        mm2
+            psubw       mm5,        mm1
+
+            pmullw      mm2,        mm2
+            movq        mm4,        mm2
+
+            punpcklwd   mm2,        mm0
+            punpckhwd   mm4,        mm0
+
+            paddd       mm6,        mm2
+            paddd       mm7,        mm4
+
+            pmullw      mm1,        mm1
+            movq        mm2,        mm1
+
+            punpcklwd   mm1,        mm0
+            psubd       mm6,        mm1
+
+            punpckhwd   mm2,        mm0
+            psubd       mm7,        mm2
+
+
+            movq        mm3,        mm6
+            pslld       mm3,        4
+
+            psubd       mm3,        mm6
+            movq        mm1,        mm5
+
+            movq        mm4,        mm5
+            pmullw      mm1,        mm1
+
+            pmulhw      mm4,        mm4
+            movq        mm2,        mm1
+
+            punpcklwd   mm1,        mm4
+            punpckhwd   mm2,        mm4
+
+            movq        mm4,        mm7
+            pslld       mm4,        4
+
+            psubd       mm4,        mm7
+
+            psubd       mm3,        mm1
+            psubd       mm4,        mm2
+
+            psubd       mm3,        flimit2
+            psubd       mm4,        flimit2
+
+            psrad       mm3,        31
+            psrad       mm4,        31
+
+            packssdw    mm3,        mm4
+            packsswb    mm3,        mm0
+
+            movd        mm1,        DWORD PTR [rsi+rax*8]
+
+            movq        mm2,        mm1
+            punpcklbw   mm1,        mm0
+
+            paddw       mm1,        mm5
+            mov         rcx,        rdx
+
+            and         rcx,        127
+%if ABI_IS_32BIT=1 && CONFIG_PIC=1
+            push        rax
+            lea         rax,        [GLOBAL(sym(vp8_rv))]
+            movq        mm4,        [rax + rcx*2] ;vp8_rv[rcx*2]
+            pop         rax
+%elif ABI_IS_32BIT=0
+            movq        mm4,        [r8 + rcx*2] ;vp8_rv[rcx*2]
+%else
+            movq        mm4,        [sym(vp8_rv) + rcx*2]
+%endif
+            paddw       mm1,        mm4
+            ;paddw     xmm1,       eight8s
+            psraw       mm1,        4
+
+            packuswb    mm1,        mm0
+            pand        mm1,        mm3
+
+            pandn       mm3,        mm2
+            por         mm1,        mm3
+
+            and         rcx,        15
+            movd        DWORD PTR   [rsp+rcx*4], mm1 ;d[rcx*4]
+
+            mov         rcx,        rdx
+            sub         rcx,        8
+
+            and         rcx,        15
+            movd        mm1,        DWORD PTR [rsp+rcx*4] ;d[rcx*4]
+
+            movd        [rsi],      mm1
+            lea         rsi,        [rsi+rax]
+
+            lea         rdi,        [rdi+rax]
+            add         rdx,        1
+
+            cmp         edx,        dword arg(2) ;rows
+            jl          .loop_row
+
+
+        add         dword arg(0), 4 ; s += 4
+        sub         dword arg(3), 4 ; cols -= 4
+        cmp         dword arg(3), 0
+        jg          .loop_col
+
+    add         rsp, 136
+    pop         rsp
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+%undef flimit2
+
+
+;void vp8_plane_add_noise_mmx (unsigned char *Start, unsigned char *noise,
+;                            unsigned char blackclamp[16],
+;                            unsigned char whiteclamp[16],
+;                            unsigned char bothclamp[16],
+;                            unsigned int Width, unsigned int Height, int Pitch)
+extern sym(rand)
+global sym(vp8_plane_add_noise_mmx)
+sym(vp8_plane_add_noise_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 8
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+.addnoise_loop:
+    call sym(rand) WRT_PLT
+    mov     rcx, arg(1) ;noise
+    and     rax, 0xff
+    add     rcx, rax
+
+    ; we rely on the fact that the clamping vectors are stored contiguously
+    ; in black/white/both order. Note that we have to reload this here because
+    ; rdx could be trashed by rand()
+    mov     rdx, arg(2) ; blackclamp
+
+
+            mov     rdi, rcx
+            movsxd  rcx, dword arg(5) ;[Width]
+            mov     rsi, arg(0) ;Pos
+            xor         rax,rax
+
+.addnoise_nextset:
+            movq        mm1,[rsi+rax]         ; get the source
+
+            psubusb     mm1, [rdx]    ;blackclamp        ; clamp both sides so we don't outrange adding noise
+            paddusb     mm1, [rdx+32] ;bothclamp
+            psubusb     mm1, [rdx+16] ;whiteclamp
+
+            movq        mm2,[rdi+rax]         ; get the noise for this line
+            paddb       mm1,mm2              ; add it in
+            movq        [rsi+rax],mm1         ; store the result
+
+            add         rax,8                 ; move to the next line
+
+            cmp         rax, rcx
+            jl          .addnoise_nextset
+
+    movsxd  rax, dword arg(7) ; Pitch
+    add     arg(0), rax ; Start += Pitch
+    sub     dword arg(6), 1   ; Height -= 1
+    jg      .addnoise_loop
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+SECTION_RODATA
+align 16
+Blur:
+    times 16 dw 16
+    times  8 dw 64
+    times 16 dw 16
+    times  8 dw  0
+
+rd:
+    times 4 dw 0x40
diff --git a/vp8/common/x86/postproc_sse2.asm b/vp8/common/x86/postproc_sse2.asm
new file mode 100644 (file)
index 0000000..966aafd
--- /dev/null
@@ -0,0 +1,759 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;void vp8_post_proc_down_and_across_xmm
+;(
+;    unsigned char *src_ptr,
+;    unsigned char *dst_ptr,
+;    int src_pixels_per_line,
+;    int dst_pixels_per_line,
+;    int rows,
+;    int cols,
+;    int flimit
+;)
+global sym(vp8_post_proc_down_and_across_xmm)
+sym(vp8_post_proc_down_and_across_xmm):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+%if ABI_IS_32BIT=1 && CONFIG_PIC=1
+    ALIGN_STACK 16, rax
+    ; move the global rd onto the stack, since we don't have enough registers
+    ; to do PIC addressing
+    movdqa      xmm0, [GLOBAL(rd42)]
+    sub         rsp, 16
+    movdqa      [rsp], xmm0
+%define RD42 [rsp]
+%else
+%define RD42 [GLOBAL(rd42)]
+%endif
+
+
+        movd        xmm2,       dword ptr arg(6) ;flimit
+        punpcklwd   xmm2,       xmm2
+        punpckldq   xmm2,       xmm2
+        punpcklqdq  xmm2,       xmm2
+
+        mov         rsi,        arg(0) ;src_ptr
+        mov         rdi,        arg(1) ;dst_ptr
+
+        movsxd      rcx,        DWORD PTR arg(4) ;rows
+        movsxd      rax,        DWORD PTR arg(2) ;src_pixels_per_line ; destination pitch?
+        pxor        xmm0,       xmm0              ; mm0 = 00000000
+
+.nextrow:
+
+        xor         rdx,        rdx       ; clear out rdx for use as loop counter
+.nextcol:
+        movq        xmm3,       QWORD PTR [rsi]         ; mm4 = r0 p0..p7
+        punpcklbw   xmm3,       xmm0                    ; mm3 = p0..p3
+        movdqa      xmm1,       xmm3                    ; mm1 = p0..p3
+        psllw       xmm3,       2                       ;
+
+        movq        xmm5,       QWORD PTR [rsi + rax]   ; mm4 = r1 p0..p7
+        punpcklbw   xmm5,       xmm0                    ; mm5 = r1 p0..p3
+        paddusw     xmm3,       xmm5                    ; mm3 += mm6
+
+        ; thresholding
+        movdqa      xmm7,       xmm1                    ; mm7 = r0 p0..p3
+        psubusw     xmm7,       xmm5                    ; mm7 = r0 p0..p3 - r1 p0..p3
+        psubusw     xmm5,       xmm1                    ; mm5 = r1 p0..p3 - r0 p0..p3
+        paddusw     xmm7,       xmm5                    ; mm7 = abs(r0 p0..p3 - r1 p0..p3)
+        pcmpgtw     xmm7,       xmm2
+
+        movq        xmm5,       QWORD PTR [rsi + 2*rax] ; mm4 = r2 p0..p7
+        punpcklbw   xmm5,       xmm0                    ; mm5 = r2 p0..p3
+        paddusw     xmm3,       xmm5                    ; mm3 += mm5
+
+        ; thresholding
+        movdqa      xmm6,       xmm1                    ; mm6 = r0 p0..p3
+        psubusw     xmm6,       xmm5                    ; mm6 = r0 p0..p3 - r2 p0..p3
+        psubusw     xmm5,       xmm1                    ; mm5 = r2 p0..p3 - r2 p0..p3
+        paddusw     xmm6,       xmm5                    ; mm6 = abs(r0 p0..p3 - r2 p0..p3)
+        pcmpgtw     xmm6,       xmm2
+        por         xmm7,       xmm6                    ; accumulate thresholds
+
+
+        neg         rax
+        movq        xmm5,       QWORD PTR [rsi+2*rax]   ; mm4 = r-2 p0..p7
+        punpcklbw   xmm5,       xmm0                    ; mm5 = r-2 p0..p3
+        paddusw     xmm3,       xmm5                    ; mm3 += mm5
+
+        ; thresholding
+        movdqa      xmm6,       xmm1                    ; mm6 = r0 p0..p3
+        psubusw     xmm6,       xmm5                    ; mm6 = p0..p3 - r-2 p0..p3
+        psubusw     xmm5,       xmm1                    ; mm5 = r-2 p0..p3 - p0..p3
+        paddusw     xmm6,       xmm5                    ; mm6 = abs(r0 p0..p3 - r-2 p0..p3)
+        pcmpgtw     xmm6,       xmm2
+        por         xmm7,       xmm6                    ; accumulate thresholds
+
+        movq        xmm4,       QWORD PTR [rsi+rax]     ; mm4 = r-1 p0..p7
+        punpcklbw   xmm4,       xmm0                    ; mm4 = r-1 p0..p3
+        paddusw     xmm3,       xmm4                    ; mm3 += mm5
+
+        ; thresholding
+        movdqa      xmm6,       xmm1                    ; mm6 = r0 p0..p3
+        psubusw     xmm6,       xmm4                    ; mm6 = p0..p3 - r-2 p0..p3
+        psubusw     xmm4,       xmm1                    ; mm5 = r-1 p0..p3 - p0..p3
+        paddusw     xmm6,       xmm4                    ; mm6 = abs(r0 p0..p3 - r-1 p0..p3)
+        pcmpgtw     xmm6,       xmm2
+        por         xmm7,       xmm6                    ; accumulate thresholds
+
+
+        paddusw     xmm3,       RD42                    ; mm3 += round value
+        psraw       xmm3,       3                       ; mm3 /= 8
+
+        pand        xmm1,       xmm7                    ; mm1 select vals > thresh from source
+        pandn       xmm7,       xmm3                    ; mm7 select vals < thresh from blurred result
+        paddusw     xmm1,       xmm7                    ; combination
+
+        packuswb    xmm1,       xmm0                    ; pack to bytes
+        movq        QWORD PTR [rdi], xmm1             ;
+
+        neg         rax                   ; pitch is positive
+        add         rsi,        8
+        add         rdi,        8
+
+        add         rdx,        8
+        cmp         edx,        dword arg(5) ;cols
+
+        jl          .nextcol
+
+        ; done with the all cols, start the across filtering in place
+        sub         rsi,        rdx
+        sub         rdi,        rdx
+
+
+        ; dup the first byte into the left border 8 times
+        movq        mm1,   [rdi]
+        punpcklbw   mm1,   mm1
+        punpcklwd   mm1,   mm1
+        punpckldq   mm1,   mm1
+
+        mov         rdx,    -8
+        movq        [rdi+rdx], mm1
+
+        ; dup the last byte into the right border
+        movsxd      rdx,    dword arg(5)
+        movq        mm1,   [rdi + rdx + -1]
+        punpcklbw   mm1,   mm1
+        punpcklwd   mm1,   mm1
+        punpckldq   mm1,   mm1
+        movq        [rdi+rdx], mm1
+
+        xor         rdx,        rdx
+        movq        mm0,        QWORD PTR [rdi-8];
+
+.acrossnextcol:
+        movq        xmm7,       QWORD PTR [rdi +rdx -2]
+        movd        xmm4,       DWORD PTR [rdi +rdx +6]
+
+        pslldq      xmm4,       8
+        por         xmm4,       xmm7
+
+        movdqa      xmm3,       xmm4
+        psrldq      xmm3,       2
+        punpcklbw   xmm3,       xmm0              ; mm3 = p0..p3
+        movdqa      xmm1,       xmm3              ; mm1 = p0..p3
+        psllw       xmm3,       2
+
+
+        movdqa      xmm5,       xmm4
+        psrldq      xmm5,       3
+        punpcklbw   xmm5,       xmm0              ; mm5 = p1..p4
+        paddusw     xmm3,       xmm5              ; mm3 += mm6
+
+        ; thresholding
+        movdqa      xmm7,       xmm1              ; mm7 = p0..p3
+        psubusw     xmm7,       xmm5              ; mm7 = p0..p3 - p1..p4
+        psubusw     xmm5,       xmm1              ; mm5 = p1..p4 - p0..p3
+        paddusw     xmm7,       xmm5              ; mm7 = abs(p0..p3 - p1..p4)
+        pcmpgtw     xmm7,       xmm2
+
+        movdqa      xmm5,       xmm4
+        psrldq      xmm5,       4
+        punpcklbw   xmm5,       xmm0              ; mm5 = p2..p5
+        paddusw     xmm3,       xmm5              ; mm3 += mm5
+
+        ; thresholding
+        movdqa      xmm6,       xmm1              ; mm6 = p0..p3
+        psubusw     xmm6,       xmm5              ; mm6 = p0..p3 - p1..p4
+        psubusw     xmm5,       xmm1              ; mm5 = p1..p4 - p0..p3
+        paddusw     xmm6,       xmm5              ; mm6 = abs(p0..p3 - p1..p4)
+        pcmpgtw     xmm6,       xmm2
+        por         xmm7,       xmm6              ; accumulate thresholds
+
+
+        movdqa      xmm5,       xmm4              ; mm5 = p-2..p5
+        punpcklbw   xmm5,       xmm0              ; mm5 = p-2..p1
+        paddusw     xmm3,       xmm5              ; mm3 += mm5
+
+        ; thresholding
+        movdqa      xmm6,       xmm1              ; mm6 = p0..p3
+        psubusw     xmm6,       xmm5              ; mm6 = p0..p3 - p1..p4
+        psubusw     xmm5,       xmm1              ; mm5 = p1..p4 - p0..p3
+        paddusw     xmm6,       xmm5              ; mm6 = abs(p0..p3 - p1..p4)
+        pcmpgtw     xmm6,       xmm2
+        por         xmm7,       xmm6              ; accumulate thresholds
+
+        psrldq      xmm4,       1                   ; mm4 = p-1..p5
+        punpcklbw   xmm4,       xmm0              ; mm4 = p-1..p2
+        paddusw     xmm3,       xmm4              ; mm3 += mm5
+
+        ; thresholding
+        movdqa      xmm6,       xmm1              ; mm6 = p0..p3
+        psubusw     xmm6,       xmm4              ; mm6 = p0..p3 - p1..p4
+        psubusw     xmm4,       xmm1              ; mm5 = p1..p4 - p0..p3
+        paddusw     xmm6,       xmm4              ; mm6 = abs(p0..p3 - p1..p4)
+        pcmpgtw     xmm6,       xmm2
+        por         xmm7,       xmm6              ; accumulate thresholds
+
+        paddusw     xmm3,       RD42              ; mm3 += round value
+        psraw       xmm3,       3                 ; mm3 /= 8
+
+        pand        xmm1,       xmm7              ; mm1 select vals > thresh from source
+        pandn       xmm7,       xmm3              ; mm7 select vals < thresh from blurred result
+        paddusw     xmm1,       xmm7              ; combination
+
+        packuswb    xmm1,       xmm0              ; pack to bytes
+        movq        QWORD PTR [rdi+rdx-8],  mm0   ; store previous four bytes
+        movdq2q     mm0,        xmm1
+
+        add         rdx,        8
+        cmp         edx,        dword arg(5) ;cols
+        jl          .acrossnextcol;
+
+        ; last 8 pixels
+        movq        QWORD PTR [rdi+rdx-8],  mm0
+
+        ; done with this rwo
+        add         rsi,rax               ; next line
+        mov         eax, dword arg(3) ;dst_pixels_per_line ; destination pitch?
+        add         rdi,rax               ; next destination
+        mov         eax, dword arg(2) ;src_pixels_per_line ; destination pitch?
+
+        dec         rcx                   ; decrement count
+        jnz         .nextrow              ; next row
+
+%if ABI_IS_32BIT=1 && CONFIG_PIC=1
+    add rsp,16
+    pop rsp
+%endif
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+%undef RD42
+
+
+;void vp8_mbpost_proc_down_xmm(unsigned char *dst,
+;                            int pitch, int rows, int cols,int flimit)
+extern sym(vp8_rv)
+global sym(vp8_mbpost_proc_down_xmm)
+sym(vp8_mbpost_proc_down_xmm):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub         rsp, 128+16
+
+    ; unsigned char d[16][8] at [rsp]
+    ; create flimit2 at [rsp+128]
+    mov         eax, dword ptr arg(4) ;flimit
+    mov         [rsp+128], eax
+    mov         [rsp+128+4], eax
+    mov         [rsp+128+8], eax
+    mov         [rsp+128+12], eax
+%define flimit4 [rsp+128]
+
+%if ABI_IS_32BIT=0
+    lea         r8,       [GLOBAL(sym(vp8_rv))]
+%endif
+
+    ;rows +=8;
+    add         dword arg(2), 8
+
+    ;for(c=0; c<cols; c+=8)
+.loop_col:
+            mov         rsi,        arg(0) ; s
+            pxor        xmm0,       xmm0        ;
+
+            movsxd      rax,        dword ptr arg(1) ;pitch       ;
+
+            ; this copies the last row down into the border 8 rows
+            mov         rdi,        rsi
+            mov         rdx,        arg(2)
+            sub         rdx,        9
+            imul        rdx,        rax
+            lea         rdi,        [rdi+rdx]
+            movq        xmm1,       QWORD ptr[rdi]              ; first row
+            mov         rcx,        8
+.init_borderd                                                    ; initialize borders
+            lea         rdi,        [rdi + rax]
+            movq        [rdi],      xmm1
+
+            dec         rcx
+            jne         .init_borderd
+
+            neg         rax                                     ; rax = -pitch
+
+            ; this copies the first row up into the border 8 rows
+            mov         rdi,        rsi
+            movq        xmm1,       QWORD ptr[rdi]              ; first row
+            mov         rcx,        8
+.init_border                                                    ; initialize borders
+            lea         rdi,        [rdi + rax]
+            movq        [rdi],      xmm1
+
+            dec         rcx
+            jne         .init_border
+
+
+
+            lea         rsi,        [rsi + rax*8];              ; rdi = s[-pitch*8]
+            neg         rax
+
+            pxor        xmm5,       xmm5
+            pxor        xmm6,       xmm6        ;
+
+            pxor        xmm7,       xmm7        ;
+            mov         rdi,        rsi
+
+            mov         rcx,        15          ;
+
+.loop_initvar:
+            movq        xmm1,       QWORD PTR [rdi];
+            punpcklbw   xmm1,       xmm0        ;
+
+            paddw       xmm5,       xmm1        ;
+            pmullw      xmm1,       xmm1        ;
+
+            movdqa      xmm2,       xmm1        ;
+            punpcklwd   xmm1,       xmm0        ;
+
+            punpckhwd   xmm2,       xmm0        ;
+            paddd       xmm6,       xmm1        ;
+
+            paddd       xmm7,       xmm2        ;
+            lea         rdi,        [rdi+rax]   ;
+
+            dec         rcx
+            jne         .loop_initvar
+            ;save the var and sum
+            xor         rdx,        rdx
+.loop_row:
+            movq        xmm1,       QWORD PTR [rsi]     ; [s-pitch*8]
+            movq        xmm2,       QWORD PTR [rdi]     ; [s+pitch*7]
+
+            punpcklbw   xmm1,       xmm0
+            punpcklbw   xmm2,       xmm0
+
+            paddw       xmm5,       xmm2
+            psubw       xmm5,       xmm1
+
+            pmullw      xmm2,       xmm2
+            movdqa      xmm4,       xmm2
+
+            punpcklwd   xmm2,       xmm0
+            punpckhwd   xmm4,       xmm0
+
+            paddd       xmm6,       xmm2
+            paddd       xmm7,       xmm4
+
+            pmullw      xmm1,       xmm1
+            movdqa      xmm2,       xmm1
+
+            punpcklwd   xmm1,       xmm0
+            psubd       xmm6,       xmm1
+
+            punpckhwd   xmm2,       xmm0
+            psubd       xmm7,       xmm2
+
+
+            movdqa      xmm3,       xmm6
+            pslld       xmm3,       4
+
+            psubd       xmm3,       xmm6
+            movdqa      xmm1,       xmm5
+
+            movdqa      xmm4,       xmm5
+            pmullw      xmm1,       xmm1
+
+            pmulhw      xmm4,       xmm4
+            movdqa      xmm2,       xmm1
+
+            punpcklwd   xmm1,       xmm4
+            punpckhwd   xmm2,       xmm4
+
+            movdqa      xmm4,       xmm7
+            pslld       xmm4,       4
+
+            psubd       xmm4,       xmm7
+
+            psubd       xmm3,       xmm1
+            psubd       xmm4,       xmm2
+
+            psubd       xmm3,       flimit4
+            psubd       xmm4,       flimit4
+
+            psrad       xmm3,       31
+            psrad       xmm4,       31
+
+            packssdw    xmm3,       xmm4
+            packsswb    xmm3,       xmm0
+
+            movq        xmm1,       QWORD PTR [rsi+rax*8]
+
+            movq        xmm2,       xmm1
+            punpcklbw   xmm1,       xmm0
+
+            paddw       xmm1,       xmm5
+            mov         rcx,        rdx
+
+            and         rcx,        127
+%if ABI_IS_32BIT=1 && CONFIG_PIC=1
+            push        rax
+            lea         rax,        [GLOBAL(sym(vp8_rv))]
+            movdqu      xmm4,       [rax + rcx*2] ;vp8_rv[rcx*2]
+            pop         rax
+%elif ABI_IS_32BIT=0
+            movdqu      xmm4,       [r8 + rcx*2] ;vp8_rv[rcx*2]
+%else
+            movdqu      xmm4,       [sym(vp8_rv) + rcx*2]
+%endif
+
+            paddw       xmm1,       xmm4
+            ;paddw     xmm1,       eight8s
+            psraw       xmm1,       4
+
+            packuswb    xmm1,       xmm0
+            pand        xmm1,       xmm3
+
+            pandn       xmm3,       xmm2
+            por         xmm1,       xmm3
+
+            and         rcx,        15
+            movq        QWORD PTR   [rsp + rcx*8], xmm1 ;d[rcx*8]
+
+            mov         rcx,        rdx
+            sub         rcx,        8
+
+            and         rcx,        15
+            movq        mm0,        [rsp + rcx*8] ;d[rcx*8]
+
+            movq        [rsi],      mm0
+            lea         rsi,        [rsi+rax]
+
+            lea         rdi,        [rdi+rax]
+            add         rdx,        1
+
+            cmp         edx,        dword arg(2) ;rows
+            jl          .loop_row
+
+        add         dword arg(0), 8 ; s += 8
+        sub         dword arg(3), 8 ; cols -= 8
+        cmp         dword arg(3), 0
+        jg          .loop_col
+
+    add         rsp, 128+16
+    pop         rsp
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+%undef flimit4
+
+
+;void vp8_mbpost_proc_across_ip_xmm(unsigned char *src,
+;                                int pitch, int rows, int cols,int flimit)
+global sym(vp8_mbpost_proc_across_ip_xmm)
+sym(vp8_mbpost_proc_across_ip_xmm):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub         rsp, 16
+
+    ; create flimit4 at [rsp]
+    mov         eax, dword ptr arg(4) ;flimit
+    mov         [rsp], eax
+    mov         [rsp+4], eax
+    mov         [rsp+8], eax
+    mov         [rsp+12], eax
+%define flimit4 [rsp]
+
+
+    ;for(r=0;r<rows;r++)
+.ip_row_loop:
+
+        xor         rdx,    rdx ;sumsq=0;
+        xor         rcx,    rcx ;sum=0;
+        mov         rsi,    arg(0); s
+
+
+        ; dup the first byte into the left border 8 times
+        movq        mm1,   [rsi]
+        punpcklbw   mm1,   mm1
+        punpcklwd   mm1,   mm1
+        punpckldq   mm1,   mm1
+
+        mov         rdi,    -8
+        movq        [rsi+rdi], mm1
+
+        ; dup the last byte into the right border
+        movsxd      rdx,    dword arg(3)
+        movq        mm1,   [rsi + rdx + -1]
+        punpcklbw   mm1,   mm1
+        punpcklwd   mm1,   mm1
+        punpckldq   mm1,   mm1
+        movq        [rsi+rdx], mm1
+
+.ip_var_loop:
+        ;for(i=-8;i<=6;i++)
+        ;{
+        ;    sumsq += s[i]*s[i];
+        ;    sum   += s[i];
+        ;}
+        movzx       eax, byte [rsi+rdi]
+        add         ecx, eax
+        mul         al
+        add         edx, eax
+        add         rdi, 1
+        cmp         rdi, 6
+        jle         .ip_var_loop
+
+
+            ;mov         rax,    sumsq
+            ;movd        xmm7,   rax
+            movd        xmm7,   edx
+
+            ;mov         rax,    sum
+            ;movd        xmm6,   rax
+            movd        xmm6,   ecx
+
+            mov         rsi,    arg(0) ;s
+            xor         rcx,    rcx
+
+            movsxd      rdx,    dword arg(3) ;cols
+            add         rdx,    8
+            pxor        mm0,    mm0
+            pxor        mm1,    mm1
+
+            pxor        xmm0,   xmm0
+.nextcol4:
+
+            movd        xmm1,   DWORD PTR [rsi+rcx-8]   ; -8 -7 -6 -5
+            movd        xmm2,   DWORD PTR [rsi+rcx+7]   ; +7 +8 +9 +10
+
+            punpcklbw   xmm1,   xmm0                    ; expanding
+            punpcklbw   xmm2,   xmm0                    ; expanding
+
+            punpcklwd   xmm1,   xmm0                    ; expanding to dwords
+            punpcklwd   xmm2,   xmm0                    ; expanding to dwords
+
+            psubd       xmm2,   xmm1                    ; 7--8   8--7   9--6 10--5
+            paddd       xmm1,   xmm1                    ; -8*2   -7*2   -6*2 -5*2
+
+            paddd       xmm1,   xmm2                    ; 7+-8   8+-7   9+-6 10+-5
+            pmaddwd     xmm1,   xmm2                    ; squared of 7+-8   8+-7   9+-6 10+-5
+
+            paddd       xmm6,   xmm2
+            paddd       xmm7,   xmm1
+
+            pshufd      xmm6,   xmm6,   0               ; duplicate the last ones
+            pshufd      xmm7,   xmm7,   0               ; duplicate the last ones
+
+            psrldq      xmm1,       4                   ; 8--7   9--6 10--5  0000
+            psrldq      xmm2,       4                   ; 8--7   9--6 10--5  0000
+
+            pshufd      xmm3,   xmm1,   3               ; 0000  8--7   8--7   8--7 squared
+            pshufd      xmm4,   xmm2,   3               ; 0000  8--7   8--7   8--7 squared
+
+            paddd       xmm6,   xmm4
+            paddd       xmm7,   xmm3
+
+            pshufd      xmm3,   xmm1,   01011111b       ; 0000  0000   9--6   9--6 squared
+            pshufd      xmm4,   xmm2,   01011111b       ; 0000  0000   9--6   9--6 squared
+
+            paddd       xmm7,   xmm3
+            paddd       xmm6,   xmm4
+
+            pshufd      xmm3,   xmm1,   10111111b       ; 0000  0000   8--7   8--7 squared
+            pshufd      xmm4,   xmm2,   10111111b       ; 0000  0000   8--7   8--7 squared
+
+            paddd       xmm7,   xmm3
+            paddd       xmm6,   xmm4
+
+            movdqa      xmm3,   xmm6
+            pmaddwd     xmm3,   xmm3
+
+            movdqa      xmm5,   xmm7
+            pslld       xmm5,   4
+
+            psubd       xmm5,   xmm7
+            psubd       xmm5,   xmm3
+
+            psubd       xmm5,   flimit4
+            psrad       xmm5,   31
+
+            packssdw    xmm5,   xmm0
+            packsswb    xmm5,   xmm0
+
+            movd        xmm1,   DWORD PTR [rsi+rcx]
+            movq        xmm2,   xmm1
+
+            punpcklbw   xmm1,   xmm0
+            punpcklwd   xmm1,   xmm0
+
+            paddd       xmm1,   xmm6
+            paddd       xmm1,   [GLOBAL(four8s)]
+
+            psrad       xmm1,   4
+            packssdw    xmm1,   xmm0
+
+            packuswb    xmm1,   xmm0
+            pand        xmm1,   xmm5
+
+            pandn       xmm5,   xmm2
+            por         xmm5,   xmm1
+
+            movd        [rsi+rcx-8],  mm0
+            movq        mm0,    mm1
+
+            movdq2q     mm1,    xmm5
+            psrldq      xmm7,   12
+
+            psrldq      xmm6,   12
+            add         rcx,    4
+
+            cmp         rcx,    rdx
+            jl          .nextcol4
+
+        ;s+=pitch;
+        movsxd rax, dword arg(1)
+        add    arg(0), rax
+
+        sub dword arg(2), 1 ;rows-=1
+        cmp dword arg(2), 0
+        jg .ip_row_loop
+
+    add         rsp, 16
+    pop         rsp
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+%undef flimit4
+
+
+;void vp8_plane_add_noise_wmt (unsigned char *Start, unsigned char *noise,
+;                            unsigned char blackclamp[16],
+;                            unsigned char whiteclamp[16],
+;                            unsigned char bothclamp[16],
+;                            unsigned int Width, unsigned int Height, int Pitch)
+extern sym(rand)
+global sym(vp8_plane_add_noise_wmt)
+sym(vp8_plane_add_noise_wmt):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 8
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+.addnoise_loop:
+    call sym(rand) WRT_PLT
+    mov     rcx, arg(1) ;noise
+    and     rax, 0xff
+    add     rcx, rax
+
+    ; we rely on the fact that the clamping vectors are stored contiguously
+    ; in black/white/both order. Note that we have to reload this here because
+    ; rdx could be trashed by rand()
+    mov     rdx, arg(2) ; blackclamp
+
+
+            mov     rdi, rcx
+            movsxd  rcx, dword arg(5) ;[Width]
+            mov     rsi, arg(0) ;Pos
+            xor         rax,rax
+
+.addnoise_nextset:
+            movdqu      xmm1,[rsi+rax]         ; get the source
+
+            psubusb     xmm1, [rdx]    ;blackclamp        ; clamp both sides so we don't outrange adding noise
+            paddusb     xmm1, [rdx+32] ;bothclamp
+            psubusb     xmm1, [rdx+16] ;whiteclamp
+
+            movdqu      xmm2,[rdi+rax]         ; get the noise for this line
+            paddb       xmm1,xmm2              ; add it in
+            movdqu      [rsi+rax],xmm1         ; store the result
+
+            add         rax,16                 ; move to the next line
+
+            cmp         rax, rcx
+            jl          .addnoise_nextset
+
+    movsxd  rax, dword arg(7) ; Pitch
+    add     arg(0), rax ; Start += Pitch
+    sub     dword arg(6), 1   ; Height -= 1
+    jg      .addnoise_loop
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+SECTION_RODATA
+align 16
+rd42:
+    times 8 dw 0x04
+four8s:
+    times 4 dd 8
diff --git a/vp8/common/x86/postproc_x86.c b/vp8/common/x86/postproc_x86.c
new file mode 100644 (file)
index 0000000..a25921b
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/* On Android NDK, rand is inlined function, but postproc needs rand symbol */
+#if defined(__ANDROID__)
+#define rand __rand
+#include <stdlib.h>
+#undef rand
+
+extern int rand(void)
+{
+  return __rand();
+}
+#endif
diff --git a/vp8/common/x86/recon_mmx.asm b/vp8/common/x86/recon_mmx.asm
new file mode 100644 (file)
index 0000000..19c0faf
--- /dev/null
@@ -0,0 +1,274 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+
+;void copy_mem8x8_mmx(
+;    unsigned char *src,
+;    int src_stride,
+;    unsigned char *dst,
+;    int dst_stride
+;    )
+global sym(vp8_copy_mem8x8_mmx)
+sym(vp8_copy_mem8x8_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rsi,        arg(0) ;src;
+        movq        mm0,        [rsi]
+
+        movsxd      rax,        dword ptr arg(1) ;src_stride;
+        mov         rdi,        arg(2) ;dst;
+
+        movq        mm1,        [rsi+rax]
+        movq        mm2,        [rsi+rax*2]
+
+        movsxd      rcx,        dword ptr arg(3) ;dst_stride
+        lea         rsi,        [rsi+rax*2]
+
+        movq        [rdi],      mm0
+        add         rsi,        rax
+
+        movq        [rdi+rcx],      mm1
+        movq        [rdi+rcx*2],    mm2
+
+
+        lea         rdi,        [rdi+rcx*2]
+        movq        mm3,        [rsi]
+
+        add         rdi,        rcx
+        movq        mm4,        [rsi+rax]
+
+        movq        mm5,        [rsi+rax*2]
+        movq        [rdi],      mm3
+
+        lea         rsi,        [rsi+rax*2]
+        movq        [rdi+rcx],  mm4
+
+        movq        [rdi+rcx*2],    mm5
+        lea         rdi,        [rdi+rcx*2]
+
+        movq        mm0,        [rsi+rax]
+        movq        mm1,        [rsi+rax*2]
+
+        movq        [rdi+rcx],  mm0
+        movq        [rdi+rcx*2],mm1
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void copy_mem8x4_mmx(
+;    unsigned char *src,
+;    int src_stride,
+;    unsigned char *dst,
+;    int dst_stride
+;    )
+global sym(vp8_copy_mem8x4_mmx)
+sym(vp8_copy_mem8x4_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rsi,        arg(0) ;src;
+        movq        mm0,        [rsi]
+
+        movsxd      rax,        dword ptr arg(1) ;src_stride;
+        mov         rdi,        arg(2) ;dst;
+
+        movq        mm1,        [rsi+rax]
+        movq        mm2,        [rsi+rax*2]
+
+        movsxd      rcx,        dword ptr arg(3) ;dst_stride
+        lea         rsi,        [rsi+rax*2]
+
+        movq        [rdi],      mm0
+        movq        [rdi+rcx],      mm1
+
+        movq        [rdi+rcx*2],    mm2
+        lea         rdi,        [rdi+rcx*2]
+
+        movq        mm3,        [rsi+rax]
+        movq        [rdi+rcx],      mm3
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void copy_mem16x16_mmx(
+;    unsigned char *src,
+;    int src_stride,
+;    unsigned char *dst,
+;    int dst_stride
+;    )
+global sym(vp8_copy_mem16x16_mmx)
+sym(vp8_copy_mem16x16_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rsi,        arg(0) ;src;
+        movsxd      rax,        dword ptr arg(1) ;src_stride;
+
+        mov         rdi,        arg(2) ;dst;
+        movsxd      rcx,        dword ptr arg(3) ;dst_stride
+
+        movq        mm0,            [rsi]
+        movq        mm3,            [rsi+8];
+
+        movq        mm1,            [rsi+rax]
+        movq        mm4,            [rsi+rax+8]
+
+        movq        mm2,            [rsi+rax*2]
+        movq        mm5,            [rsi+rax*2+8]
+
+        lea         rsi,            [rsi+rax*2]
+        add         rsi,            rax
+
+        movq        [rdi],          mm0
+        movq        [rdi+8],        mm3
+
+        movq        [rdi+rcx],      mm1
+        movq        [rdi+rcx+8],    mm4
+
+        movq        [rdi+rcx*2],    mm2
+        movq        [rdi+rcx*2+8],  mm5
+
+        lea         rdi,            [rdi+rcx*2]
+        add         rdi,            rcx
+
+        movq        mm0,            [rsi]
+        movq        mm3,            [rsi+8];
+
+        movq        mm1,            [rsi+rax]
+        movq        mm4,            [rsi+rax+8]
+
+        movq        mm2,            [rsi+rax*2]
+        movq        mm5,            [rsi+rax*2+8]
+
+        lea         rsi,            [rsi+rax*2]
+        add         rsi,            rax
+
+        movq        [rdi],          mm0
+        movq        [rdi+8],        mm3
+
+        movq        [rdi+rcx],      mm1
+        movq        [rdi+rcx+8],    mm4
+
+        movq        [rdi+rcx*2],    mm2
+        movq        [rdi+rcx*2+8],  mm5
+
+        lea         rdi,            [rdi+rcx*2]
+        add         rdi,            rcx
+
+        movq        mm0,            [rsi]
+        movq        mm3,            [rsi+8];
+
+        movq        mm1,            [rsi+rax]
+        movq        mm4,            [rsi+rax+8]
+
+        movq        mm2,            [rsi+rax*2]
+        movq        mm5,            [rsi+rax*2+8]
+
+        lea         rsi,            [rsi+rax*2]
+        add         rsi,            rax
+
+        movq        [rdi],          mm0
+        movq        [rdi+8],        mm3
+
+        movq        [rdi+rcx],      mm1
+        movq        [rdi+rcx+8],    mm4
+
+        movq        [rdi+rcx*2],    mm2
+        movq        [rdi+rcx*2+8],  mm5
+
+        lea         rdi,            [rdi+rcx*2]
+        add         rdi,            rcx
+
+        movq        mm0,            [rsi]
+        movq        mm3,            [rsi+8];
+
+        movq        mm1,            [rsi+rax]
+        movq        mm4,            [rsi+rax+8]
+
+        movq        mm2,            [rsi+rax*2]
+        movq        mm5,            [rsi+rax*2+8]
+
+        lea         rsi,            [rsi+rax*2]
+        add         rsi,            rax
+
+        movq        [rdi],          mm0
+        movq        [rdi+8],        mm3
+
+        movq        [rdi+rcx],      mm1
+        movq        [rdi+rcx+8],    mm4
+
+        movq        [rdi+rcx*2],    mm2
+        movq        [rdi+rcx*2+8],  mm5
+
+        lea         rdi,            [rdi+rcx*2]
+        add         rdi,            rcx
+
+        movq        mm0,            [rsi]
+        movq        mm3,            [rsi+8];
+
+        movq        mm1,            [rsi+rax]
+        movq        mm4,            [rsi+rax+8]
+
+        movq        mm2,            [rsi+rax*2]
+        movq        mm5,            [rsi+rax*2+8]
+
+        lea         rsi,            [rsi+rax*2]
+        add         rsi,            rax
+
+        movq        [rdi],          mm0
+        movq        [rdi+8],        mm3
+
+        movq        [rdi+rcx],      mm1
+        movq        [rdi+rcx+8],    mm4
+
+        movq        [rdi+rcx*2],    mm2
+        movq        [rdi+rcx*2+8],  mm5
+
+        lea         rdi,            [rdi+rcx*2]
+        add         rdi,            rcx
+
+        movq        mm0,            [rsi]
+        movq        mm3,            [rsi+8];
+
+        movq        [rdi],          mm0
+        movq        [rdi+8],        mm3
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
diff --git a/vp8/common/x86/recon_sse2.asm b/vp8/common/x86/recon_sse2.asm
new file mode 100644 (file)
index 0000000..7b6e3cf
--- /dev/null
@@ -0,0 +1,1080 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;void copy_mem16x16_sse2(
+;    unsigned char *src,
+;    int src_stride,
+;    unsigned char *dst,
+;    int dst_stride
+;    )
+global sym(vp8_copy_mem16x16_sse2)
+sym(vp8_copy_mem16x16_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rsi,        arg(0) ;src;
+        movdqu      xmm0,       [rsi]
+
+        movsxd      rax,        dword ptr arg(1) ;src_stride;
+        mov         rdi,        arg(2) ;dst;
+
+        movdqu      xmm1,       [rsi+rax]
+        movdqu      xmm2,       [rsi+rax*2]
+
+        movsxd      rcx,        dword ptr arg(3) ;dst_stride
+        lea         rsi,        [rsi+rax*2]
+
+        movdqa      [rdi],      xmm0
+        add         rsi,        rax
+
+        movdqa      [rdi+rcx],  xmm1
+        movdqa      [rdi+rcx*2],xmm2
+
+        lea         rdi,        [rdi+rcx*2]
+        movdqu      xmm3,       [rsi]
+
+        add         rdi,        rcx
+        movdqu      xmm4,       [rsi+rax]
+
+        movdqu      xmm5,       [rsi+rax*2]
+        lea         rsi,        [rsi+rax*2]
+
+        movdqa      [rdi],  xmm3
+        add         rsi,        rax
+
+        movdqa      [rdi+rcx],  xmm4
+        movdqa      [rdi+rcx*2],xmm5
+
+        lea         rdi,        [rdi+rcx*2]
+        movdqu      xmm0,       [rsi]
+
+        add         rdi,        rcx
+        movdqu      xmm1,       [rsi+rax]
+
+        movdqu      xmm2,       [rsi+rax*2]
+        lea         rsi,        [rsi+rax*2]
+
+        movdqa      [rdi],      xmm0
+        add         rsi,        rax
+
+        movdqa      [rdi+rcx],  xmm1
+
+        movdqa      [rdi+rcx*2],    xmm2
+        movdqu      xmm3,       [rsi]
+
+        movdqu      xmm4,       [rsi+rax]
+        lea         rdi,        [rdi+rcx*2]
+
+        add         rdi,        rcx
+        movdqu      xmm5,       [rsi+rax*2]
+
+        lea         rsi,        [rsi+rax*2]
+        movdqa      [rdi],  xmm3
+
+        add         rsi,        rax
+        movdqa      [rdi+rcx],  xmm4
+
+        movdqa      [rdi+rcx*2],xmm5
+        movdqu      xmm0,       [rsi]
+
+        lea         rdi,        [rdi+rcx*2]
+        movdqu      xmm1,       [rsi+rax]
+
+        add         rdi,        rcx
+        movdqu      xmm2,       [rsi+rax*2]
+
+        lea         rsi,        [rsi+rax*2]
+        movdqa      [rdi],      xmm0
+
+        movdqa      [rdi+rcx],  xmm1
+        movdqa      [rdi+rcx*2],xmm2
+
+        movdqu      xmm3,       [rsi+rax]
+        lea         rdi,        [rdi+rcx*2]
+
+        movdqa      [rdi+rcx],  xmm3
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_intra_pred_uv_dc_mmx2(
+;    unsigned char *dst,
+;    int dst_stride
+;    unsigned char *above,
+;    unsigned char *left,
+;    int left_stride,
+;    )
+global sym(vp8_intra_pred_uv_dc_mmx2)
+sym(vp8_intra_pred_uv_dc_mmx2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ; from top
+    mov         rdi,        arg(2) ;above;
+    mov         rsi,        arg(3) ;left;
+    movsxd      rax,        dword ptr arg(4) ;left_stride;
+    pxor        mm0,        mm0
+    movq        mm1,        [rdi]
+    lea         rdi,        [rax*3]
+    psadbw      mm1,        mm0
+    ; from left
+    movzx       ecx,        byte [rsi]
+    movzx       edx,        byte [rsi+rax*1]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rax*2]
+    add         ecx,        edx
+
+    movzx       edx,        byte [rsi+rdi]
+    lea         rsi,        [rsi+rax*4]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rax]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rax*2]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rdi]
+    add         ecx,        edx
+
+    ; add up
+    pextrw      edx,        mm1, 0x0
+    lea         edx,        [edx+ecx+8]
+    sar         edx,        4
+    movd        mm1,        edx
+    movsxd      rcx,        dword ptr arg(1) ;dst_stride
+    pshufw      mm1,        mm1, 0x0
+    mov         rdi,        arg(0) ;dst;
+    packuswb    mm1,        mm1
+
+    ; write out
+    lea         rax,        [rcx*3]
+    lea         rdx,        [rdi+rcx*4]
+
+    movq [rdi      ],       mm1
+    movq [rdi+rcx  ],       mm1
+    movq [rdi+rcx*2],       mm1
+    movq [rdi+rax  ],       mm1
+    movq [rdx      ],       mm1
+    movq [rdx+rcx  ],       mm1
+    movq [rdx+rcx*2],       mm1
+    movq [rdx+rax  ],       mm1
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_intra_pred_uv_dctop_mmx2(
+;    unsigned char *dst,
+;    int dst_stride
+;    unsigned char *above,
+;    unsigned char *left,
+;    int left_stride,
+;    )
+global sym(vp8_intra_pred_uv_dctop_mmx2)
+sym(vp8_intra_pred_uv_dctop_mmx2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ;arg(3), arg(4) not used
+
+    ; from top
+    mov         rsi,        arg(2) ;above;
+    pxor        mm0,        mm0
+    movq        mm1,        [rsi]
+    psadbw      mm1,        mm0
+
+    ; add up
+    paddw       mm1,        [GLOBAL(dc_4)]
+    psraw       mm1,        3
+    pshufw      mm1,        mm1, 0x0
+    packuswb    mm1,        mm1
+
+    ; write out
+    mov         rdi,        arg(0) ;dst;
+    movsxd      rcx,        dword ptr arg(1) ;dst_stride
+    lea         rax,        [rcx*3]
+
+    movq [rdi      ],       mm1
+    movq [rdi+rcx  ],       mm1
+    movq [rdi+rcx*2],       mm1
+    movq [rdi+rax  ],       mm1
+    lea         rdi,        [rdi+rcx*4]
+    movq [rdi      ],       mm1
+    movq [rdi+rcx  ],       mm1
+    movq [rdi+rcx*2],       mm1
+    movq [rdi+rax  ],       mm1
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_intra_pred_uv_dcleft_mmx2(
+;    unsigned char *dst,
+;    int dst_stride
+;    unsigned char *above,
+;    unsigned char *left,
+;    int left_stride,
+;    )
+global sym(vp8_intra_pred_uv_dcleft_mmx2)
+sym(vp8_intra_pred_uv_dcleft_mmx2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ;arg(2) not used
+
+    ; from left
+    mov         rsi,        arg(3) ;left;
+    movsxd      rax,        dword ptr arg(4) ;left_stride;
+    lea         rdi,        [rax*3]
+    movzx       ecx,        byte [rsi]
+    movzx       edx,        byte [rsi+rax]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rax*2]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rdi]
+    add         ecx,        edx
+    lea         rsi,        [rsi+rax*4]
+    movzx       edx,        byte [rsi]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rax]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rax*2]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rdi]
+    lea         edx,        [ecx+edx+4]
+
+    ; add up
+    shr         edx,        3
+    movd        mm1,        edx
+    pshufw      mm1,        mm1, 0x0
+    packuswb    mm1,        mm1
+
+    ; write out
+    mov         rdi,        arg(0) ;dst;
+    movsxd      rcx,        dword ptr arg(1) ;dst_stride
+    lea         rax,        [rcx*3]
+
+    movq [rdi      ],       mm1
+    movq [rdi+rcx  ],       mm1
+    movq [rdi+rcx*2],       mm1
+    movq [rdi+rax  ],       mm1
+    lea         rdi,        [rdi+rcx*4]
+    movq [rdi      ],       mm1
+    movq [rdi+rcx  ],       mm1
+    movq [rdi+rcx*2],       mm1
+    movq [rdi+rax  ],       mm1
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_intra_pred_uv_dc128_mmx(
+;    unsigned char *dst,
+;    int dst_stride
+;    unsigned char *above,
+;    unsigned char *left,
+;    int left_stride,
+;    )
+global sym(vp8_intra_pred_uv_dc128_mmx)
+sym(vp8_intra_pred_uv_dc128_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    GET_GOT     rbx
+    ; end prolog
+
+    ;arg(2), arg(3), arg(4) not used
+
+    ; write out
+    movq        mm1,        [GLOBAL(dc_128)]
+    mov         rax,        arg(0) ;dst;
+    movsxd      rdx,        dword ptr arg(1) ;dst_stride
+    lea         rcx,        [rdx*3]
+
+    movq [rax      ],       mm1
+    movq [rax+rdx  ],       mm1
+    movq [rax+rdx*2],       mm1
+    movq [rax+rcx  ],       mm1
+    lea         rax,        [rax+rdx*4]
+    movq [rax      ],       mm1
+    movq [rax+rdx  ],       mm1
+    movq [rax+rdx*2],       mm1
+    movq [rax+rcx  ],       mm1
+
+    ; begin epilog
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_intra_pred_uv_tm_sse2(
+;    unsigned char *dst,
+;    int dst_stride
+;    unsigned char *above,
+;    unsigned char *left,
+;    int left_stride,
+;    )
+%macro vp8_intra_pred_uv_tm 1
+global sym(vp8_intra_pred_uv_tm_%1)
+sym(vp8_intra_pred_uv_tm_%1):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ; read top row
+    mov         edx,        4
+    mov         rsi,        arg(2) ;above
+    movsxd      rax,        dword ptr arg(4) ;left_stride;
+    pxor        xmm0,       xmm0
+%ifidn %1, ssse3
+    movdqa      xmm2,       [GLOBAL(dc_1024)]
+%endif
+    movq        xmm1,       [rsi]
+    punpcklbw   xmm1,       xmm0
+
+    ; set up left ptrs ans subtract topleft
+    movd        xmm3,       [rsi-1]
+    mov         rsi,        arg(3) ;left;
+%ifidn %1, sse2
+    punpcklbw   xmm3,       xmm0
+    pshuflw     xmm3,       xmm3, 0x0
+    punpcklqdq  xmm3,       xmm3
+%else
+    pshufb      xmm3,       xmm2
+%endif
+    psubw       xmm1,       xmm3
+
+    ; set up dest ptrs
+    mov         rdi,        arg(0) ;dst;
+    movsxd      rcx,        dword ptr arg(1) ;dst_stride
+
+.vp8_intra_pred_uv_tm_%1_loop:
+    movd        xmm3,       [rsi]
+    movd        xmm5,       [rsi+rax]
+%ifidn %1, sse2
+    punpcklbw   xmm3,       xmm0
+    punpcklbw   xmm5,       xmm0
+    pshuflw     xmm3,       xmm3, 0x0
+    pshuflw     xmm5,       xmm5, 0x0
+    punpcklqdq  xmm3,       xmm3
+    punpcklqdq  xmm5,       xmm5
+%else
+    pshufb      xmm3,       xmm2
+    pshufb      xmm5,       xmm2
+%endif
+    paddw       xmm3,       xmm1
+    paddw       xmm5,       xmm1
+    packuswb    xmm3,       xmm5
+    movq  [rdi    ],        xmm3
+    movhps[rdi+rcx],        xmm3
+    lea         rsi,        [rsi+rax*2]
+    lea         rdi,        [rdi+rcx*2]
+    dec         edx
+    jnz .vp8_intra_pred_uv_tm_%1_loop
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+%endmacro
+
+vp8_intra_pred_uv_tm sse2
+vp8_intra_pred_uv_tm ssse3
+
+;void vp8_intra_pred_uv_ve_mmx(
+;    unsigned char *dst,
+;    int dst_stride
+;    unsigned char *above,
+;    unsigned char *left,
+;    int left_stride,
+;    )
+global sym(vp8_intra_pred_uv_ve_mmx)
+sym(vp8_intra_pred_uv_ve_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    ; end prolog
+
+    ; arg(3), arg(4) not used
+
+    ; read from top
+    mov         rax,        arg(2) ;src;
+
+    movq        mm1,        [rax]
+
+    ; write out
+    mov         rax,        arg(0) ;dst;
+    movsxd      rdx,        dword ptr arg(1) ;dst_stride
+    lea         rcx,        [rdx*3]
+
+    movq [rax      ],       mm1
+    movq [rax+rdx  ],       mm1
+    movq [rax+rdx*2],       mm1
+    movq [rax+rcx  ],       mm1
+    lea         rax,        [rax+rdx*4]
+    movq [rax      ],       mm1
+    movq [rax+rdx  ],       mm1
+    movq [rax+rdx*2],       mm1
+    movq [rax+rcx  ],       mm1
+
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_intra_pred_uv_ho_mmx2(
+;    unsigned char *dst,
+;    int dst_stride
+;    unsigned char *above,
+;    unsigned char *left,
+;    int left_stride
+;    )
+%macro vp8_intra_pred_uv_ho 1
+global sym(vp8_intra_pred_uv_ho_%1)
+sym(vp8_intra_pred_uv_ho_%1):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+%ifidn %1, ssse3
+%ifndef GET_GOT_SAVE_ARG
+    push        rbx
+%endif
+    GET_GOT     rbx
+%endif
+    ; end prolog
+
+    ;arg(2) not used
+
+    ; read from left and write out
+%ifidn %1, mmx2
+    mov         edx,        4
+%endif
+    mov         rsi,        arg(3) ;left
+    movsxd      rax,        dword ptr arg(4) ;left_stride;
+    mov         rdi,        arg(0) ;dst;
+    movsxd      rcx,        dword ptr arg(1) ;dst_stride
+%ifidn %1, ssse3
+    lea         rdx,        [rcx*3]
+    movdqa      xmm2,       [GLOBAL(dc_00001111)]
+    lea         rbx,        [rax*3]
+%endif
+
+%ifidn %1, mmx2
+.vp8_intra_pred_uv_ho_%1_loop:
+    movd        mm0,        [rsi]
+    movd        mm1,        [rsi+rax]
+    punpcklbw   mm0,        mm0
+    punpcklbw   mm1,        mm1
+    pshufw      mm0,        mm0, 0x0
+    pshufw      mm1,        mm1, 0x0
+    movq  [rdi    ],        mm0
+    movq  [rdi+rcx],        mm1
+    lea         rsi,        [rsi+rax*2]
+    lea         rdi,        [rdi+rcx*2]
+    dec         edx
+    jnz .vp8_intra_pred_uv_ho_%1_loop
+%else
+    movd        xmm0,       [rsi]
+    movd        xmm3,       [rsi+rax]
+    movd        xmm1,       [rsi+rax*2]
+    movd        xmm4,       [rsi+rbx]
+    punpcklbw   xmm0,       xmm3
+    punpcklbw   xmm1,       xmm4
+    pshufb      xmm0,       xmm2
+    pshufb      xmm1,       xmm2
+    movq   [rdi    ],       xmm0
+    movhps [rdi+rcx],       xmm0
+    movq [rdi+rcx*2],       xmm1
+    movhps [rdi+rdx],       xmm1
+    lea         rsi,        [rsi+rax*4]
+    lea         rdi,        [rdi+rcx*4]
+    movd        xmm0,       [rsi]
+    movd        xmm3,       [rsi+rax]
+    movd        xmm1,       [rsi+rax*2]
+    movd        xmm4,       [rsi+rbx]
+    punpcklbw   xmm0,       xmm3
+    punpcklbw   xmm1,       xmm4
+    pshufb      xmm0,       xmm2
+    pshufb      xmm1,       xmm2
+    movq   [rdi    ],       xmm0
+    movhps [rdi+rcx],       xmm0
+    movq [rdi+rcx*2],       xmm1
+    movhps [rdi+rdx],       xmm1
+%endif
+
+    ; begin epilog
+%ifidn %1, ssse3
+    RESTORE_GOT
+%ifndef GET_GOT_SAVE_ARG
+    pop         rbx
+%endif
+%endif
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+%endmacro
+
+vp8_intra_pred_uv_ho mmx2
+vp8_intra_pred_uv_ho ssse3
+
+;void vp8_intra_pred_y_dc_sse2(
+;    unsigned char *dst,
+;    int dst_stride
+;    unsigned char *above,
+;    unsigned char *left,
+;    int left_stride
+;    )
+global sym(vp8_intra_pred_y_dc_sse2)
+sym(vp8_intra_pred_y_dc_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ; from top
+    mov         rdi,        arg(2) ;above
+    mov         rsi,        arg(3) ;left
+    movsxd      rax,        dword ptr arg(4) ;left_stride;
+
+    pxor        xmm0,       xmm0
+    movdqa      xmm1,       [rdi]
+    psadbw      xmm1,       xmm0
+    movq        xmm2,       xmm1
+    punpckhqdq  xmm1,       xmm1
+    paddw       xmm1,       xmm2
+
+    ; from left
+    lea         rdi,        [rax*3]
+
+    movzx       ecx,        byte [rsi]
+    movzx       edx,        byte [rsi+rax]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rax*2]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rdi]
+    add         ecx,        edx
+    lea         rsi,        [rsi+rax*4]
+
+    movzx       edx,        byte [rsi]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rax]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rax*2]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rdi]
+    add         ecx,        edx
+    lea         rsi,        [rsi+rax*4]
+
+    movzx       edx,        byte [rsi]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rax]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rax*2]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rdi]
+    add         ecx,        edx
+    lea         rsi,        [rsi+rax*4]
+
+    movzx       edx,        byte [rsi]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rax]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rax*2]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rdi]
+    add         ecx,        edx
+
+    ; add up
+    pextrw      edx,        xmm1, 0x0
+    lea         edx,        [edx+ecx+16]
+    sar         edx,        5
+    movd        xmm1,       edx
+    ; FIXME use pshufb for ssse3 version
+    pshuflw     xmm1,       xmm1, 0x0
+    punpcklqdq  xmm1,       xmm1
+    packuswb    xmm1,       xmm1
+
+    ; write out
+    mov         rsi,        2
+    mov         rdi,        arg(0) ;dst;
+    movsxd      rcx,        dword ptr arg(1) ;dst_stride
+    lea         rax,        [rcx*3]
+
+.label
+    movdqa [rdi      ],     xmm1
+    movdqa [rdi+rcx  ],     xmm1
+    movdqa [rdi+rcx*2],     xmm1
+    movdqa [rdi+rax  ],     xmm1
+    lea         rdi,        [rdi+rcx*4]
+    movdqa [rdi      ],     xmm1
+    movdqa [rdi+rcx  ],     xmm1
+    movdqa [rdi+rcx*2],     xmm1
+    movdqa [rdi+rax  ],     xmm1
+    lea         rdi,        [rdi+rcx*4]
+    dec         rsi
+    jnz .label
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_intra_pred_y_dctop_sse2(
+;    unsigned char *dst,
+;    int dst_stride
+;    unsigned char *above,
+;    unsigned char *left,
+;    int left_stride
+;    )
+global sym(vp8_intra_pred_y_dctop_sse2)
+sym(vp8_intra_pred_y_dctop_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    GET_GOT     rbx
+    ; end prolog
+
+    ;arg(3), arg(4) not used
+
+    ; from top
+    mov         rcx,        arg(2) ;above;
+    pxor        xmm0,       xmm0
+    movdqa      xmm1,       [rcx]
+    psadbw      xmm1,       xmm0
+    movdqa      xmm2,       xmm1
+    punpckhqdq  xmm1,       xmm1
+    paddw       xmm1,       xmm2
+
+    ; add up
+    paddw       xmm1,       [GLOBAL(dc_8)]
+    psraw       xmm1,       4
+    ; FIXME use pshufb for ssse3 version
+    pshuflw     xmm1,       xmm1, 0x0
+    punpcklqdq  xmm1,       xmm1
+    packuswb    xmm1,       xmm1
+
+    ; write out
+    mov         rsi,        2
+    mov         rdx,        arg(0) ;dst;
+    movsxd      rcx,        dword ptr arg(1) ;dst_stride
+    lea         rax,        [rcx*3]
+
+.label
+    movdqa [rdx      ],     xmm1
+    movdqa [rdx+rcx  ],     xmm1
+    movdqa [rdx+rcx*2],     xmm1
+    movdqa [rdx+rax  ],     xmm1
+    lea         rdx,        [rdx+rcx*4]
+    movdqa [rdx      ],     xmm1
+    movdqa [rdx+rcx  ],     xmm1
+    movdqa [rdx+rcx*2],     xmm1
+    movdqa [rdx+rax  ],     xmm1
+    lea         rdx,        [rdx+rcx*4]
+    dec         rsi
+    jnz .label
+
+    ; begin epilog
+    RESTORE_GOT
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_intra_pred_y_dcleft_sse2(
+;    unsigned char *dst,
+;    int dst_stride
+;    unsigned char *above,
+;    unsigned char *left,
+;    int left_stride
+;    )
+global sym(vp8_intra_pred_y_dcleft_sse2)
+sym(vp8_intra_pred_y_dcleft_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ;arg(2) not used
+
+    ; from left
+    mov         rsi,        arg(3) ;left;
+    movsxd      rax,        dword ptr arg(4) ;left_stride;
+
+    lea         rdi,        [rax*3]
+    movzx       ecx,        byte [rsi]
+    movzx       edx,        byte [rsi+rax]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rax*2]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rdi]
+    add         ecx,        edx
+    lea         rsi,        [rsi+rax*4]
+    movzx       edx,        byte [rsi]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rax]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rax*2]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rdi]
+    add         ecx,        edx
+    lea         rsi,        [rsi+rax*4]
+    movzx       edx,        byte [rsi]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rax]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rax*2]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rdi]
+    add         ecx,        edx
+    lea         rsi,        [rsi+rax*4]
+    movzx       edx,        byte [rsi]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rax]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rax*2]
+    add         ecx,        edx
+    movzx       edx,        byte [rsi+rdi]
+    lea         edx,        [ecx+edx+8]
+
+    ; add up
+    shr         edx,        4
+    movd        xmm1,       edx
+    ; FIXME use pshufb for ssse3 version
+    pshuflw     xmm1,       xmm1, 0x0
+    punpcklqdq  xmm1,       xmm1
+    packuswb    xmm1,       xmm1
+
+    ; write out
+    mov         rsi,        2
+    mov         rdi,        arg(0) ;dst;
+    movsxd      rcx,        dword ptr arg(1) ;dst_stride
+    lea         rax,        [rcx*3]
+
+.label
+    movdqa [rdi      ],     xmm1
+    movdqa [rdi+rcx  ],     xmm1
+    movdqa [rdi+rcx*2],     xmm1
+    movdqa [rdi+rax  ],     xmm1
+    lea         rdi,        [rdi+rcx*4]
+    movdqa [rdi      ],     xmm1
+    movdqa [rdi+rcx  ],     xmm1
+    movdqa [rdi+rcx*2],     xmm1
+    movdqa [rdi+rax  ],     xmm1
+    lea         rdi,        [rdi+rcx*4]
+    dec         rsi
+    jnz .label
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_intra_pred_y_dc128_sse2(
+;    unsigned char *dst,
+;    int dst_stride
+;    unsigned char *above,
+;    unsigned char *left,
+;    int left_stride
+;    )
+global sym(vp8_intra_pred_y_dc128_sse2)
+sym(vp8_intra_pred_y_dc128_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    GET_GOT     rbx
+    ; end prolog
+
+    ;arg(2), arg(3), arg(4) not used
+
+    ; write out
+    mov         rsi,        2
+    movdqa      xmm1,       [GLOBAL(dc_128)]
+    mov         rax,        arg(0) ;dst;
+    movsxd      rdx,        dword ptr arg(1) ;dst_stride
+    lea         rcx,        [rdx*3]
+
+.label
+    movdqa [rax      ],     xmm1
+    movdqa [rax+rdx  ],     xmm1
+    movdqa [rax+rdx*2],     xmm1
+    movdqa [rax+rcx  ],     xmm1
+    lea         rax,        [rax+rdx*4]
+    movdqa [rax      ],     xmm1
+    movdqa [rax+rdx  ],     xmm1
+    movdqa [rax+rdx*2],     xmm1
+    movdqa [rax+rcx  ],     xmm1
+    lea         rax,        [rax+rdx*4]
+    dec         rsi
+    jnz .label
+
+    ; begin epilog
+    RESTORE_GOT
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_intra_pred_y_tm_sse2(
+;    unsigned char *dst,
+;    int dst_stride
+;    unsigned char *above,
+;    unsigned char *left,
+;    int left_stride
+;    )
+%macro vp8_intra_pred_y_tm 1
+global sym(vp8_intra_pred_y_tm_%1)
+sym(vp8_intra_pred_y_tm_%1):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    GET_GOT     rbx
+    ; end prolog
+
+    ; read top row
+    mov         edx,        8
+    mov         rsi,        arg(2) ;above
+    movsxd      rax,        dword ptr arg(4) ;left_stride;
+    pxor        xmm0,       xmm0
+%ifidn %1, ssse3
+    movdqa      xmm3,       [GLOBAL(dc_1024)]
+%endif
+    movdqa      xmm1,       [rsi]
+    movdqa      xmm2,       xmm1
+    punpcklbw   xmm1,       xmm0
+    punpckhbw   xmm2,       xmm0
+
+    ; set up left ptrs ans subtract topleft
+    movd        xmm4,       [rsi-1]
+    mov         rsi,        arg(3) ;left
+%ifidn %1, sse2
+    punpcklbw   xmm4,       xmm0
+    pshuflw     xmm4,       xmm4, 0x0
+    punpcklqdq  xmm4,       xmm4
+%else
+    pshufb      xmm4,       xmm3
+%endif
+    psubw       xmm1,       xmm4
+    psubw       xmm2,       xmm4
+
+    ; set up dest ptrs
+    mov         rdi,        arg(0) ;dst;
+    movsxd      rcx,        dword ptr arg(1) ;dst_stride
+vp8_intra_pred_y_tm_%1_loop:
+    movd        xmm4,       [rsi]
+    movd        xmm5,       [rsi+rax]
+%ifidn %1, sse2
+    punpcklbw   xmm4,       xmm0
+    punpcklbw   xmm5,       xmm0
+    pshuflw     xmm4,       xmm4, 0x0
+    pshuflw     xmm5,       xmm5, 0x0
+    punpcklqdq  xmm4,       xmm4
+    punpcklqdq  xmm5,       xmm5
+%else
+    pshufb      xmm4,       xmm3
+    pshufb      xmm5,       xmm3
+%endif
+    movdqa      xmm6,       xmm4
+    movdqa      xmm7,       xmm5
+    paddw       xmm4,       xmm1
+    paddw       xmm6,       xmm2
+    paddw       xmm5,       xmm1
+    paddw       xmm7,       xmm2
+    packuswb    xmm4,       xmm6
+    packuswb    xmm5,       xmm7
+    movdqa [rdi    ],       xmm4
+    movdqa [rdi+rcx],       xmm5
+    lea         rsi,        [rsi+rax*2]
+    lea         rdi,        [rdi+rcx*2]
+    dec         edx
+    jnz vp8_intra_pred_y_tm_%1_loop
+
+    ; begin epilog
+    RESTORE_GOT
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+%endmacro
+
+vp8_intra_pred_y_tm sse2
+vp8_intra_pred_y_tm ssse3
+
+;void vp8_intra_pred_y_ve_sse2(
+;    unsigned char *dst,
+;    int dst_stride
+;    unsigned char *above,
+;    unsigned char *left,
+;    int left_stride
+;    )
+global sym(vp8_intra_pred_y_ve_sse2)
+sym(vp8_intra_pred_y_ve_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    ; end prolog
+
+    ;arg(3), arg(4) not used
+
+    mov         rax,        arg(2) ;above;
+    mov         rsi,        2
+    movsxd      rdx,        dword ptr arg(1) ;dst_stride
+
+    ; read from top
+    movdqa      xmm1,       [rax]
+
+    ; write out
+    mov         rax,        arg(0) ;dst;
+    lea         rcx,        [rdx*3]
+
+.label
+    movdqa [rax      ],     xmm1
+    movdqa [rax+rdx  ],     xmm1
+    movdqa [rax+rdx*2],     xmm1
+    movdqa [rax+rcx  ],     xmm1
+    lea         rax,        [rax+rdx*4]
+    movdqa [rax      ],     xmm1
+    movdqa [rax+rdx  ],     xmm1
+    movdqa [rax+rdx*2],     xmm1
+    movdqa [rax+rcx  ],     xmm1
+    lea         rax,        [rax+rdx*4]
+    dec         rsi
+    jnz .label
+
+    ; begin epilog
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_intra_pred_y_ho_sse2(
+;    unsigned char *dst,
+;    int dst_stride
+;    unsigned char *above,
+;    unsigned char *left,
+;    int left_stride,
+;    )
+global sym(vp8_intra_pred_y_ho_sse2)
+sym(vp8_intra_pred_y_ho_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ;arg(2) not used
+
+    ; read from left and write out
+    mov         edx,        8
+    mov         rsi,        arg(3) ;left;
+    movsxd      rax,        dword ptr arg(4) ;left_stride;
+    mov         rdi,        arg(0) ;dst;
+    movsxd      rcx,        dword ptr arg(1) ;dst_stride
+
+vp8_intra_pred_y_ho_sse2_loop:
+    movd        xmm0,       [rsi]
+    movd        xmm1,       [rsi+rax]
+    ; FIXME use pshufb for ssse3 version
+    punpcklbw   xmm0,       xmm0
+    punpcklbw   xmm1,       xmm1
+    pshuflw     xmm0,       xmm0, 0x0
+    pshuflw     xmm1,       xmm1, 0x0
+    punpcklqdq  xmm0,       xmm0
+    punpcklqdq  xmm1,       xmm1
+    movdqa [rdi    ],       xmm0
+    movdqa [rdi+rcx],       xmm1
+    lea         rsi,        [rsi+rax*2]
+    lea         rdi,        [rdi+rcx*2]
+    dec         edx
+    jnz vp8_intra_pred_y_ho_sse2_loop
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+SECTION_RODATA
+align 16
+dc_128:
+    times 16 db 128
+dc_4:
+    times 4 dw 4
+align 16
+dc_8:
+    times 8 dw 8
+align 16
+dc_1024:
+    times 8 dw 0x400
+align 16
+dc_00001111:
+    times 8 db 0
+    times 8 db 1
diff --git a/vp8/common/x86/recon_wrapper_sse2.c b/vp8/common/x86/recon_wrapper_sse2.c
new file mode 100644 (file)
index 0000000..b482faa
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vp8/common/blockd.h"
+
+#define build_intra_predictors_mbuv_prototype(sym) \
+    void sym(unsigned char *dst, int dst_stride, \
+             const unsigned char *above, \
+             const unsigned char *left, int left_stride)
+typedef build_intra_predictors_mbuv_prototype((*build_intra_predictors_mbuv_fn_t));
+
+extern build_intra_predictors_mbuv_prototype(vp8_intra_pred_uv_dc_mmx2);
+extern build_intra_predictors_mbuv_prototype(vp8_intra_pred_uv_dctop_mmx2);
+extern build_intra_predictors_mbuv_prototype(vp8_intra_pred_uv_dcleft_mmx2);
+extern build_intra_predictors_mbuv_prototype(vp8_intra_pred_uv_dc128_mmx);
+extern build_intra_predictors_mbuv_prototype(vp8_intra_pred_uv_ho_mmx2);
+extern build_intra_predictors_mbuv_prototype(vp8_intra_pred_uv_ho_ssse3);
+extern build_intra_predictors_mbuv_prototype(vp8_intra_pred_uv_ve_mmx);
+extern build_intra_predictors_mbuv_prototype(vp8_intra_pred_uv_tm_sse2);
+extern build_intra_predictors_mbuv_prototype(vp8_intra_pred_uv_tm_ssse3);
+
+static void vp8_build_intra_predictors_mbuv_x86(MACROBLOCKD *x,
+                                                unsigned char * uabove_row,
+                                                unsigned char * vabove_row,
+                                                unsigned char *dst_u,
+                                                unsigned char *dst_v,
+                                                int dst_stride,
+                                                unsigned char * uleft,
+                                                unsigned char * vleft,
+                                                int left_stride,
+                                                build_intra_predictors_mbuv_fn_t tm_func,
+                                                build_intra_predictors_mbuv_fn_t ho_func)
+{
+    int mode = x->mode_info_context->mbmi.uv_mode;
+    build_intra_predictors_mbuv_fn_t fn;
+
+    switch (mode) {
+        case  V_PRED: fn = vp8_intra_pred_uv_ve_mmx; break;
+        case  H_PRED: fn = ho_func; break;
+        case TM_PRED: fn = tm_func; break;
+        case DC_PRED:
+            if (x->up_available) {
+                if (x->left_available) {
+                    fn = vp8_intra_pred_uv_dc_mmx2; break;
+                } else {
+                    fn = vp8_intra_pred_uv_dctop_mmx2; break;
+                }
+            } else if (x->left_available) {
+                fn = vp8_intra_pred_uv_dcleft_mmx2; break;
+            } else {
+                fn = vp8_intra_pred_uv_dc128_mmx; break;
+            }
+            break;
+        default: return;
+    }
+
+    fn(dst_u, dst_stride, uabove_row, uleft, left_stride);
+    fn(dst_v, dst_stride, vabove_row, vleft, left_stride);
+}
+
+void vp8_build_intra_predictors_mbuv_s_sse2(MACROBLOCKD *x,
+                                            unsigned char * uabove_row,
+                                            unsigned char * vabove_row,
+                                            unsigned char * uleft,
+                                            unsigned char * vleft,
+                                            int left_stride,
+                                            unsigned char * upred_ptr,
+                                            unsigned char * vpred_ptr,
+                                            int pred_stride)
+{
+    vp8_build_intra_predictors_mbuv_x86(x,
+                                        uabove_row, vabove_row,
+                                        upred_ptr,
+                                        vpred_ptr, pred_stride,
+                                        uleft,
+                                        vleft,
+                                        left_stride,
+                                        vp8_intra_pred_uv_tm_sse2,
+                                        vp8_intra_pred_uv_ho_mmx2);
+}
+
+void vp8_build_intra_predictors_mbuv_s_ssse3(MACROBLOCKD *x,
+                                             unsigned char * uabove_row,
+                                             unsigned char * vabove_row,
+                                             unsigned char * uleft,
+                                             unsigned char * vleft,
+                                             int left_stride,
+                                             unsigned char * upred_ptr,
+                                             unsigned char * vpred_ptr,
+                                             int pred_stride)
+{
+    vp8_build_intra_predictors_mbuv_x86(x,
+                                        uabove_row, vabove_row,
+                                        upred_ptr,
+                                        vpred_ptr, pred_stride,
+                                        uleft,
+                                        vleft,
+                                        left_stride,
+                                        vp8_intra_pred_uv_tm_ssse3,
+                                        vp8_intra_pred_uv_ho_ssse3);
+}
+
+#define build_intra_predictors_mby_prototype(sym) \
+    void sym(unsigned char *dst, int dst_stride, \
+             const unsigned char *above, \
+             const unsigned char *left, int left_stride)
+typedef build_intra_predictors_mby_prototype((*build_intra_predictors_mby_fn_t));
+
+extern build_intra_predictors_mby_prototype(vp8_intra_pred_y_dc_sse2);
+extern build_intra_predictors_mby_prototype(vp8_intra_pred_y_dctop_sse2);
+extern build_intra_predictors_mby_prototype(vp8_intra_pred_y_dcleft_sse2);
+extern build_intra_predictors_mby_prototype(vp8_intra_pred_y_dc128_sse2);
+extern build_intra_predictors_mby_prototype(vp8_intra_pred_y_ho_sse2);
+extern build_intra_predictors_mby_prototype(vp8_intra_pred_y_ve_sse2);
+extern build_intra_predictors_mby_prototype(vp8_intra_pred_y_tm_sse2);
+extern build_intra_predictors_mby_prototype(vp8_intra_pred_y_tm_ssse3);
+
+static void vp8_build_intra_predictors_mby_x86(MACROBLOCKD *x,
+                                               unsigned char * yabove_row,
+                                               unsigned char *dst_y,
+                                               int dst_stride,
+                                               unsigned char * yleft,
+                                               int left_stride,
+                                               build_intra_predictors_mby_fn_t tm_func)
+{
+    int mode = x->mode_info_context->mbmi.mode;
+    build_intra_predictors_mbuv_fn_t fn;
+
+    switch (mode) {
+        case  V_PRED: fn = vp8_intra_pred_y_ve_sse2; break;
+        case  H_PRED: fn = vp8_intra_pred_y_ho_sse2; break;
+        case TM_PRED: fn = tm_func; break;
+        case DC_PRED:
+            if (x->up_available) {
+                if (x->left_available) {
+                    fn = vp8_intra_pred_y_dc_sse2; break;
+                } else {
+                    fn = vp8_intra_pred_y_dctop_sse2; break;
+                }
+            } else if (x->left_available) {
+                fn = vp8_intra_pred_y_dcleft_sse2; break;
+            } else {
+                fn = vp8_intra_pred_y_dc128_sse2; break;
+            }
+            break;
+        default: return;
+    }
+
+    fn(dst_y, dst_stride, yabove_row, yleft, left_stride);
+    return;
+}
+
+void vp8_build_intra_predictors_mby_s_sse2(MACROBLOCKD *x,
+                                           unsigned char * yabove_row,
+                                           unsigned char * yleft,
+                                           int left_stride,
+                                           unsigned char * ypred_ptr,
+                                           int y_stride)
+{
+    vp8_build_intra_predictors_mby_x86(x, yabove_row, ypred_ptr,
+                                       y_stride, yleft, left_stride,
+                                       vp8_intra_pred_y_tm_sse2);
+}
+
+void vp8_build_intra_predictors_mby_s_ssse3(MACROBLOCKD *x,
+                                            unsigned char * yabove_row,
+                                            unsigned char * yleft,
+                                            int left_stride,
+                                            unsigned char * ypred_ptr,
+                                            int y_stride)
+{
+    vp8_build_intra_predictors_mby_x86(x, yabove_row, ypred_ptr,
+                                     y_stride, yleft, left_stride,
+                                       vp8_intra_pred_y_tm_ssse3);
+
+}
diff --git a/vp8/common/x86/sad_mmx.asm b/vp8/common/x86/sad_mmx.asm
new file mode 100644 (file)
index 0000000..407b399
--- /dev/null
@@ -0,0 +1,427 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+global sym(vp8_sad16x16_mmx)
+global sym(vp8_sad8x16_mmx)
+global sym(vp8_sad8x8_mmx)
+global sym(vp8_sad4x4_mmx)
+global sym(vp8_sad16x8_mmx)
+
+;unsigned int vp8_sad16x16_mmx(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+sym(vp8_sad16x16_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push rsi
+    push rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        lea             rcx,        [rsi+rax*8]
+
+        lea             rcx,        [rcx+rax*8]
+        pxor            mm7,        mm7
+
+        pxor            mm6,        mm6
+
+.x16x16sad_mmx_loop:
+
+        movq            mm0,        QWORD PTR [rsi]
+        movq            mm2,        QWORD PTR [rsi+8]
+
+        movq            mm1,        QWORD PTR [rdi]
+        movq            mm3,        QWORD PTR [rdi+8]
+
+        movq            mm4,        mm0
+        movq            mm5,        mm2
+
+        psubusb         mm0,        mm1
+        psubusb         mm1,        mm4
+
+        psubusb         mm2,        mm3
+        psubusb         mm3,        mm5
+
+        por             mm0,        mm1
+        por             mm2,        mm3
+
+        movq            mm1,        mm0
+        movq            mm3,        mm2
+
+        punpcklbw       mm0,        mm6
+        punpcklbw       mm2,        mm6
+
+        punpckhbw       mm1,        mm6
+        punpckhbw       mm3,        mm6
+
+        paddw           mm0,        mm2
+        paddw           mm1,        mm3
+
+
+        lea             rsi,        [rsi+rax]
+        add             rdi,        rdx
+
+        paddw           mm7,        mm0
+        paddw           mm7,        mm1
+
+        cmp             rsi,        rcx
+        jne             .x16x16sad_mmx_loop
+
+
+        movq            mm0,        mm7
+
+        punpcklwd       mm0,        mm6
+        punpckhwd       mm7,        mm6
+
+        paddw           mm0,        mm7
+        movq            mm7,        mm0
+
+
+        psrlq           mm0,        32
+        paddw           mm7,        mm0
+
+        movq            rax,        mm7
+
+    pop rdi
+    pop rsi
+    mov rsp, rbp
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;unsigned int vp8_sad8x16_mmx(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+sym(vp8_sad8x16_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push rsi
+    push rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        lea             rcx,        [rsi+rax*8]
+
+        lea             rcx,        [rcx+rax*8]
+        pxor            mm7,        mm7
+
+        pxor            mm6,        mm6
+
+.x8x16sad_mmx_loop:
+
+        movq            mm0,        QWORD PTR [rsi]
+        movq            mm1,        QWORD PTR [rdi]
+
+        movq            mm2,        mm0
+        psubusb         mm0,        mm1
+
+        psubusb         mm1,        mm2
+        por             mm0,        mm1
+
+        movq            mm2,        mm0
+        punpcklbw       mm0,        mm6
+
+        punpckhbw       mm2,        mm6
+        lea             rsi,        [rsi+rax]
+
+        add             rdi,        rdx
+        paddw           mm7,        mm0
+
+        paddw           mm7,        mm2
+        cmp             rsi,        rcx
+
+        jne             .x8x16sad_mmx_loop
+
+        movq            mm0,        mm7
+        punpcklwd       mm0,        mm6
+
+        punpckhwd       mm7,        mm6
+        paddw           mm0,        mm7
+
+        movq            mm7,        mm0
+        psrlq           mm0,        32
+
+        paddw           mm7,        mm0
+        movq            rax,        mm7
+
+    pop rdi
+    pop rsi
+    mov rsp, rbp
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;unsigned int vp8_sad8x8_mmx(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+sym(vp8_sad8x8_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push rsi
+    push rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        lea             rcx,        [rsi+rax*8]
+        pxor            mm7,        mm7
+
+        pxor            mm6,        mm6
+
+.x8x8sad_mmx_loop:
+
+        movq            mm0,        QWORD PTR [rsi]
+        movq            mm1,        QWORD PTR [rdi]
+
+        movq            mm2,        mm0
+        psubusb         mm0,        mm1
+
+        psubusb         mm1,        mm2
+        por             mm0,        mm1
+
+        movq            mm2,        mm0
+        punpcklbw       mm0,        mm6
+
+        punpckhbw       mm2,        mm6
+        paddw           mm0,        mm2
+
+        lea             rsi,       [rsi+rax]
+        add             rdi,        rdx
+
+        paddw           mm7,       mm0
+        cmp             rsi,        rcx
+
+        jne             .x8x8sad_mmx_loop
+
+        movq            mm0,        mm7
+        punpcklwd       mm0,        mm6
+
+        punpckhwd       mm7,        mm6
+        paddw           mm0,        mm7
+
+        movq            mm7,        mm0
+        psrlq           mm0,        32
+
+        paddw           mm7,        mm0
+        movq            rax,        mm7
+
+    pop rdi
+    pop rsi
+    mov rsp, rbp
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;unsigned int vp8_sad4x4_mmx(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+sym(vp8_sad4x4_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push rsi
+    push rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        movd            mm0,        DWORD PTR [rsi]
+        movd            mm1,        DWORD PTR [rdi]
+
+        movd            mm2,        DWORD PTR [rsi+rax]
+        movd            mm3,        DWORD PTR [rdi+rdx]
+
+        punpcklbw       mm0,        mm2
+        punpcklbw       mm1,        mm3
+
+        movq            mm2,        mm0
+        psubusb         mm0,        mm1
+
+        psubusb         mm1,        mm2
+        por             mm0,        mm1
+
+        movq            mm2,        mm0
+        pxor            mm3,        mm3
+
+        punpcklbw       mm0,        mm3
+        punpckhbw       mm2,        mm3
+
+        paddw           mm0,        mm2
+
+        lea             rsi,        [rsi+rax*2]
+        lea             rdi,        [rdi+rdx*2]
+
+        movd            mm4,        DWORD PTR [rsi]
+        movd            mm5,        DWORD PTR [rdi]
+
+        movd            mm6,        DWORD PTR [rsi+rax]
+        movd            mm7,        DWORD PTR [rdi+rdx]
+
+        punpcklbw       mm4,        mm6
+        punpcklbw       mm5,        mm7
+
+        movq            mm6,        mm4
+        psubusb         mm4,        mm5
+
+        psubusb         mm5,        mm6
+        por             mm4,        mm5
+
+        movq            mm5,        mm4
+        punpcklbw       mm4,        mm3
+
+        punpckhbw       mm5,        mm3
+        paddw           mm4,        mm5
+
+        paddw           mm0,        mm4
+        movq            mm1,        mm0
+
+        punpcklwd       mm0,        mm3
+        punpckhwd       mm1,        mm3
+
+        paddw           mm0,        mm1
+        movq            mm1,        mm0
+
+        psrlq           mm0,        32
+        paddw           mm0,        mm1
+
+        movq            rax,        mm0
+
+    pop rdi
+    pop rsi
+    mov rsp, rbp
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;unsigned int vp8_sad16x8_mmx(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+sym(vp8_sad16x8_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push rsi
+    push rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        lea             rcx,        [rsi+rax*8]
+        pxor            mm7,        mm7
+
+        pxor            mm6,        mm6
+
+.x16x8sad_mmx_loop:
+
+        movq            mm0,       [rsi]
+        movq            mm1,       [rdi]
+
+        movq            mm2,        [rsi+8]
+        movq            mm3,        [rdi+8]
+
+        movq            mm4,        mm0
+        movq            mm5,        mm2
+
+        psubusb         mm0,        mm1
+        psubusb         mm1,        mm4
+
+        psubusb         mm2,        mm3
+        psubusb         mm3,        mm5
+
+        por             mm0,        mm1
+        por             mm2,        mm3
+
+        movq            mm1,        mm0
+        movq            mm3,        mm2
+
+        punpcklbw       mm0,        mm6
+        punpckhbw       mm1,        mm6
+
+        punpcklbw       mm2,        mm6
+        punpckhbw       mm3,        mm6
+
+
+        paddw           mm0,        mm2
+        paddw           mm1,        mm3
+
+        paddw           mm0,        mm1
+        lea             rsi,        [rsi+rax]
+
+        add             rdi,        rdx
+        paddw           mm7,        mm0
+
+        cmp             rsi,        rcx
+        jne             .x16x8sad_mmx_loop
+
+        movq            mm0,        mm7
+        punpcklwd       mm0,        mm6
+
+        punpckhwd       mm7,        mm6
+        paddw           mm0,        mm7
+
+        movq            mm7,        mm0
+        psrlq           mm0,        32
+
+        paddw           mm7,        mm0
+        movq            rax,        mm7
+
+    pop rdi
+    pop rsi
+    mov rsp, rbp
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
diff --git a/vp8/common/x86/sad_sse2.asm b/vp8/common/x86/sad_sse2.asm
new file mode 100644 (file)
index 0000000..0b01d7b
--- /dev/null
@@ -0,0 +1,410 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;unsigned int vp8_sad16x16_wmt(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+global sym(vp8_sad16x16_wmt)
+sym(vp8_sad16x16_wmt):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    SAVE_XMM 6
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        lea             rcx,        [rsi+rax*8]
+
+        lea             rcx,        [rcx+rax*8]
+        pxor            xmm6,       xmm6
+
+.x16x16sad_wmt_loop:
+
+        movq            xmm0,       QWORD PTR [rsi]
+        movq            xmm2,       QWORD PTR [rsi+8]
+
+        movq            xmm1,       QWORD PTR [rdi]
+        movq            xmm3,       QWORD PTR [rdi+8]
+
+        movq            xmm4,       QWORD PTR [rsi+rax]
+        movq            xmm5,       QWORD PTR [rdi+rdx]
+
+
+        punpcklbw       xmm0,       xmm2
+        punpcklbw       xmm1,       xmm3
+
+        psadbw          xmm0,       xmm1
+        movq            xmm2,       QWORD PTR [rsi+rax+8]
+
+        movq            xmm3,       QWORD PTR [rdi+rdx+8]
+        lea             rsi,        [rsi+rax*2]
+
+        lea             rdi,        [rdi+rdx*2]
+        punpcklbw       xmm4,       xmm2
+
+        punpcklbw       xmm5,       xmm3
+        psadbw          xmm4,       xmm5
+
+        paddw           xmm6,       xmm0
+        paddw           xmm6,       xmm4
+
+        cmp             rsi,        rcx
+        jne             .x16x16sad_wmt_loop
+
+        movq            xmm0,       xmm6
+        psrldq          xmm6,       8
+
+        paddw           xmm0,       xmm6
+        movq            rax,        xmm0
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;unsigned int vp8_sad8x16_wmt(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  max_sad)
+global sym(vp8_sad8x16_wmt)
+sym(vp8_sad8x16_wmt):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rbx,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        lea             rcx,        [rsi+rbx*8]
+
+        lea             rcx,        [rcx+rbx*8]
+        pxor            mm7,        mm7
+
+.x8x16sad_wmt_loop:
+
+        movq            rax,        mm7
+        cmp             eax,        arg(4)
+        jg              .x8x16sad_wmt_early_exit
+
+        movq            mm0,        QWORD PTR [rsi]
+        movq            mm1,        QWORD PTR [rdi]
+
+        movq            mm2,        QWORD PTR [rsi+rbx]
+        movq            mm3,        QWORD PTR [rdi+rdx]
+
+        psadbw          mm0,        mm1
+        psadbw          mm2,        mm3
+
+        lea             rsi,        [rsi+rbx*2]
+        lea             rdi,        [rdi+rdx*2]
+
+        paddw           mm7,        mm0
+        paddw           mm7,        mm2
+
+        cmp             rsi,        rcx
+        jne             .x8x16sad_wmt_loop
+
+        movq            rax,        mm7
+
+.x8x16sad_wmt_early_exit:
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    pop         rbx
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;unsigned int vp8_sad8x8_wmt(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+global sym(vp8_sad8x8_wmt)
+sym(vp8_sad8x8_wmt):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rbx,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        lea             rcx,        [rsi+rbx*8]
+        pxor            mm7,        mm7
+
+.x8x8sad_wmt_loop:
+
+        movq            rax,        mm7
+        cmp             eax,        arg(4)
+        jg              .x8x8sad_wmt_early_exit
+
+        movq            mm0,        QWORD PTR [rsi]
+        movq            mm1,        QWORD PTR [rdi]
+
+        psadbw          mm0,        mm1
+        lea             rsi,        [rsi+rbx]
+
+        add             rdi,        rdx
+        paddw           mm7,        mm0
+
+        cmp             rsi,        rcx
+        jne             .x8x8sad_wmt_loop
+
+        movq            rax,        mm7
+.x8x8sad_wmt_early_exit:
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    pop         rbx
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;unsigned int vp8_sad4x4_wmt(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+global sym(vp8_sad4x4_wmt)
+sym(vp8_sad4x4_wmt):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        movd            mm0,        DWORD PTR [rsi]
+        movd            mm1,        DWORD PTR [rdi]
+
+        movd            mm2,        DWORD PTR [rsi+rax]
+        movd            mm3,        DWORD PTR [rdi+rdx]
+
+        punpcklbw       mm0,        mm2
+        punpcklbw       mm1,        mm3
+
+        psadbw          mm0,        mm1
+        lea             rsi,        [rsi+rax*2]
+
+        lea             rdi,        [rdi+rdx*2]
+        movd            mm4,        DWORD PTR [rsi]
+
+        movd            mm5,        DWORD PTR [rdi]
+        movd            mm6,        DWORD PTR [rsi+rax]
+
+        movd            mm7,        DWORD PTR [rdi+rdx]
+        punpcklbw       mm4,        mm6
+
+        punpcklbw       mm5,        mm7
+        psadbw          mm4,        mm5
+
+        paddw           mm0,        mm4
+        movq            rax,        mm0
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;unsigned int vp8_sad16x8_wmt(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+global sym(vp8_sad16x8_wmt)
+sym(vp8_sad16x8_wmt):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rbx,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        lea             rcx,        [rsi+rbx*8]
+        pxor            mm7,        mm7
+
+.x16x8sad_wmt_loop:
+
+        movq            rax,        mm7
+        cmp             eax,        arg(4)
+        jg              .x16x8sad_wmt_early_exit
+
+        movq            mm0,        QWORD PTR [rsi]
+        movq            mm2,        QWORD PTR [rsi+8]
+
+        movq            mm1,        QWORD PTR [rdi]
+        movq            mm3,        QWORD PTR [rdi+8]
+
+        movq            mm4,        QWORD PTR [rsi+rbx]
+        movq            mm5,        QWORD PTR [rdi+rdx]
+
+        psadbw          mm0,        mm1
+        psadbw          mm2,        mm3
+
+        movq            mm1,        QWORD PTR [rsi+rbx+8]
+        movq            mm3,        QWORD PTR [rdi+rdx+8]
+
+        psadbw          mm4,        mm5
+        psadbw          mm1,        mm3
+
+        lea             rsi,        [rsi+rbx*2]
+        lea             rdi,        [rdi+rdx*2]
+
+        paddw           mm0,        mm2
+        paddw           mm4,        mm1
+
+        paddw           mm7,        mm0
+        paddw           mm7,        mm4
+
+        cmp             rsi,        rcx
+        jne             .x16x8sad_wmt_loop
+
+        movq            rax,        mm7
+
+.x16x8sad_wmt_early_exit:
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    pop         rbx
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_copy32xn_sse2(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *dst_ptr,
+;    int  dst_stride,
+;    int height);
+global sym(vp8_copy32xn_sse2)
+sym(vp8_copy32xn_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    SAVE_XMM 7
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;dst_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;dst_stride
+        movsxd          rcx,        dword ptr arg(4) ;height
+
+.block_copy_sse2_loopx4:
+        movdqu          xmm0,       XMMWORD PTR [rsi]
+        movdqu          xmm1,       XMMWORD PTR [rsi + 16]
+        movdqu          xmm2,       XMMWORD PTR [rsi + rax]
+        movdqu          xmm3,       XMMWORD PTR [rsi + rax + 16]
+
+        lea             rsi,        [rsi+rax*2]
+
+        movdqu          xmm4,       XMMWORD PTR [rsi]
+        movdqu          xmm5,       XMMWORD PTR [rsi + 16]
+        movdqu          xmm6,       XMMWORD PTR [rsi + rax]
+        movdqu          xmm7,       XMMWORD PTR [rsi + rax + 16]
+
+        lea             rsi,    [rsi+rax*2]
+
+        movdqa          XMMWORD PTR [rdi], xmm0
+        movdqa          XMMWORD PTR [rdi + 16], xmm1
+        movdqa          XMMWORD PTR [rdi + rdx], xmm2
+        movdqa          XMMWORD PTR [rdi + rdx + 16], xmm3
+
+        lea             rdi,    [rdi+rdx*2]
+
+        movdqa          XMMWORD PTR [rdi], xmm4
+        movdqa          XMMWORD PTR [rdi + 16], xmm5
+        movdqa          XMMWORD PTR [rdi + rdx], xmm6
+        movdqa          XMMWORD PTR [rdi + rdx + 16], xmm7
+
+        lea             rdi,    [rdi+rdx*2]
+
+        sub             rcx,     4
+        cmp             rcx,     4
+        jge             .block_copy_sse2_loopx4
+
+        cmp             rcx, 0
+        je              .copy_is_done
+
+.block_copy_sse2_loop:
+        movdqu          xmm0,       XMMWORD PTR [rsi]
+        movdqu          xmm1,       XMMWORD PTR [rsi + 16]
+        lea             rsi,    [rsi+rax]
+
+        movdqa          XMMWORD PTR [rdi], xmm0
+        movdqa          XMMWORD PTR [rdi + 16], xmm1
+        lea             rdi,    [rdi+rdx]
+
+        sub             rcx,     1
+        jne             .block_copy_sse2_loop
+
+.copy_is_done:
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
diff --git a/vp8/common/x86/sad_sse3.asm b/vp8/common/x86/sad_sse3.asm
new file mode 100644 (file)
index 0000000..c2af3c8
--- /dev/null
@@ -0,0 +1,960 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+%include "vpx_ports/x86_abi_support.asm"
+
+%macro STACK_FRAME_CREATE_X3 0
+%if ABI_IS_32BIT
+  %define     src_ptr       rsi
+  %define     src_stride    rax
+  %define     ref_ptr       rdi
+  %define     ref_stride    rdx
+  %define     end_ptr       rcx
+  %define     ret_var       rbx
+  %define     result_ptr    arg(4)
+  %define     max_sad       arg(4)
+  %define     height        dword ptr arg(4)
+    push        rbp
+    mov         rbp,        rsp
+    push        rsi
+    push        rdi
+    push        rbx
+
+    mov         rsi,        arg(0)              ; src_ptr
+    mov         rdi,        arg(2)              ; ref_ptr
+
+    movsxd      rax,        dword ptr arg(1)    ; src_stride
+    movsxd      rdx,        dword ptr arg(3)    ; ref_stride
+%else
+  %ifidn __OUTPUT_FORMAT__,x64
+    SAVE_XMM 7, u
+    %define     src_ptr     rcx
+    %define     src_stride  rdx
+    %define     ref_ptr     r8
+    %define     ref_stride  r9
+    %define     end_ptr     r10
+    %define     ret_var     r11
+    %define     result_ptr  [rsp+xmm_stack_space+8+4*8]
+    %define     max_sad     [rsp+xmm_stack_space+8+4*8]
+    %define     height      dword ptr [rsp+xmm_stack_space+8+4*8]
+  %else
+    %define     src_ptr     rdi
+    %define     src_stride  rsi
+    %define     ref_ptr     rdx
+    %define     ref_stride  rcx
+    %define     end_ptr     r9
+    %define     ret_var     r10
+    %define     result_ptr  r8
+    %define     max_sad     r8
+    %define     height      r8
+  %endif
+%endif
+
+%endmacro
+
+%macro STACK_FRAME_DESTROY_X3 0
+  %define     src_ptr
+  %define     src_stride
+  %define     ref_ptr
+  %define     ref_stride
+  %define     end_ptr
+  %define     ret_var
+  %define     result_ptr
+  %define     max_sad
+  %define     height
+
+%if ABI_IS_32BIT
+    pop         rbx
+    pop         rdi
+    pop         rsi
+    pop         rbp
+%else
+  %ifidn __OUTPUT_FORMAT__,x64
+    RESTORE_XMM
+  %endif
+%endif
+    ret
+%endmacro
+
+%macro STACK_FRAME_CREATE_X4 0
+%if ABI_IS_32BIT
+  %define     src_ptr       rsi
+  %define     src_stride    rax
+  %define     r0_ptr        rcx
+  %define     r1_ptr        rdx
+  %define     r2_ptr        rbx
+  %define     r3_ptr        rdi
+  %define     ref_stride    rbp
+  %define     result_ptr    arg(4)
+    push        rbp
+    mov         rbp,        rsp
+    push        rsi
+    push        rdi
+    push        rbx
+
+    push        rbp
+    mov         rdi,        arg(2)              ; ref_ptr_base
+
+    LOAD_X4_ADDRESSES rdi, rcx, rdx, rax, rdi
+
+    mov         rsi,        arg(0)              ; src_ptr
+
+    movsxd      rbx,        dword ptr arg(1)    ; src_stride
+    movsxd      rbp,        dword ptr arg(3)    ; ref_stride
+
+    xchg        rbx,        rax
+%else
+  %ifidn __OUTPUT_FORMAT__,x64
+    SAVE_XMM 7, u
+    %define     src_ptr     rcx
+    %define     src_stride  rdx
+    %define     r0_ptr      rsi
+    %define     r1_ptr      r10
+    %define     r2_ptr      r11
+    %define     r3_ptr      r8
+    %define     ref_stride  r9
+    %define     result_ptr  [rsp+xmm_stack_space+16+4*8]
+    push        rsi
+
+    LOAD_X4_ADDRESSES r8, r0_ptr, r1_ptr, r2_ptr, r3_ptr
+  %else
+    %define     src_ptr     rdi
+    %define     src_stride  rsi
+    %define     r0_ptr      r9
+    %define     r1_ptr      r10
+    %define     r2_ptr      r11
+    %define     r3_ptr      rdx
+    %define     ref_stride  rcx
+    %define     result_ptr  r8
+
+    LOAD_X4_ADDRESSES rdx, r0_ptr, r1_ptr, r2_ptr, r3_ptr
+
+  %endif
+%endif
+%endmacro
+
+%macro STACK_FRAME_DESTROY_X4 0
+  %define     src_ptr
+  %define     src_stride
+  %define     r0_ptr
+  %define     r1_ptr
+  %define     r2_ptr
+  %define     r3_ptr
+  %define     ref_stride
+  %define     result_ptr
+
+%if ABI_IS_32BIT
+    pop         rbx
+    pop         rdi
+    pop         rsi
+    pop         rbp
+%else
+  %ifidn __OUTPUT_FORMAT__,x64
+    pop         rsi
+    RESTORE_XMM
+  %endif
+%endif
+    ret
+%endmacro
+
+%macro PROCESS_16X2X3 5
+%if %1==0
+        movdqa          xmm0,       XMMWORD PTR [%2]
+        lddqu           xmm5,       XMMWORD PTR [%3]
+        lddqu           xmm6,       XMMWORD PTR [%3+1]
+        lddqu           xmm7,       XMMWORD PTR [%3+2]
+
+        psadbw          xmm5,       xmm0
+        psadbw          xmm6,       xmm0
+        psadbw          xmm7,       xmm0
+%else
+        movdqa          xmm0,       XMMWORD PTR [%2]
+        lddqu           xmm1,       XMMWORD PTR [%3]
+        lddqu           xmm2,       XMMWORD PTR [%3+1]
+        lddqu           xmm3,       XMMWORD PTR [%3+2]
+
+        psadbw          xmm1,       xmm0
+        psadbw          xmm2,       xmm0
+        psadbw          xmm3,       xmm0
+
+        paddw           xmm5,       xmm1
+        paddw           xmm6,       xmm2
+        paddw           xmm7,       xmm3
+%endif
+        movdqa          xmm0,       XMMWORD PTR [%2+%4]
+        lddqu           xmm1,       XMMWORD PTR [%3+%5]
+        lddqu           xmm2,       XMMWORD PTR [%3+%5+1]
+        lddqu           xmm3,       XMMWORD PTR [%3+%5+2]
+
+%if %1==0 || %1==1
+        lea             %2,         [%2+%4*2]
+        lea             %3,         [%3+%5*2]
+%endif
+
+        psadbw          xmm1,       xmm0
+        psadbw          xmm2,       xmm0
+        psadbw          xmm3,       xmm0
+
+        paddw           xmm5,       xmm1
+        paddw           xmm6,       xmm2
+        paddw           xmm7,       xmm3
+%endmacro
+
+%macro PROCESS_8X2X3 5
+%if %1==0
+        movq            mm0,       QWORD PTR [%2]
+        movq            mm5,       QWORD PTR [%3]
+        movq            mm6,       QWORD PTR [%3+1]
+        movq            mm7,       QWORD PTR [%3+2]
+
+        psadbw          mm5,       mm0
+        psadbw          mm6,       mm0
+        psadbw          mm7,       mm0
+%else
+        movq            mm0,       QWORD PTR [%2]
+        movq            mm1,       QWORD PTR [%3]
+        movq            mm2,       QWORD PTR [%3+1]
+        movq            mm3,       QWORD PTR [%3+2]
+
+        psadbw          mm1,       mm0
+        psadbw          mm2,       mm0
+        psadbw          mm3,       mm0
+
+        paddw           mm5,       mm1
+        paddw           mm6,       mm2
+        paddw           mm7,       mm3
+%endif
+        movq            mm0,       QWORD PTR [%2+%4]
+        movq            mm1,       QWORD PTR [%3+%5]
+        movq            mm2,       QWORD PTR [%3+%5+1]
+        movq            mm3,       QWORD PTR [%3+%5+2]
+
+%if %1==0 || %1==1
+        lea             %2,        [%2+%4*2]
+        lea             %3,        [%3+%5*2]
+%endif
+
+        psadbw          mm1,       mm0
+        psadbw          mm2,       mm0
+        psadbw          mm3,       mm0
+
+        paddw           mm5,       mm1
+        paddw           mm6,       mm2
+        paddw           mm7,       mm3
+%endmacro
+
+%macro LOAD_X4_ADDRESSES 5
+        mov             %2,         [%1+REG_SZ_BYTES*0]
+        mov             %3,         [%1+REG_SZ_BYTES*1]
+
+        mov             %4,         [%1+REG_SZ_BYTES*2]
+        mov             %5,         [%1+REG_SZ_BYTES*3]
+%endmacro
+
+%macro PROCESS_16X2X4 8
+%if %1==0
+        movdqa          xmm0,       XMMWORD PTR [%2]
+        lddqu           xmm4,       XMMWORD PTR [%3]
+        lddqu           xmm5,       XMMWORD PTR [%4]
+        lddqu           xmm6,       XMMWORD PTR [%5]
+        lddqu           xmm7,       XMMWORD PTR [%6]
+
+        psadbw          xmm4,       xmm0
+        psadbw          xmm5,       xmm0
+        psadbw          xmm6,       xmm0
+        psadbw          xmm7,       xmm0
+%else
+        movdqa          xmm0,       XMMWORD PTR [%2]
+        lddqu           xmm1,       XMMWORD PTR [%3]
+        lddqu           xmm2,       XMMWORD PTR [%4]
+        lddqu           xmm3,       XMMWORD PTR [%5]
+
+        psadbw          xmm1,       xmm0
+        psadbw          xmm2,       xmm0
+        psadbw          xmm3,       xmm0
+
+        paddw           xmm4,       xmm1
+        lddqu           xmm1,       XMMWORD PTR [%6]
+        paddw           xmm5,       xmm2
+        paddw           xmm6,       xmm3
+
+        psadbw          xmm1,       xmm0
+        paddw           xmm7,       xmm1
+%endif
+        movdqa          xmm0,       XMMWORD PTR [%2+%7]
+        lddqu           xmm1,       XMMWORD PTR [%3+%8]
+        lddqu           xmm2,       XMMWORD PTR [%4+%8]
+        lddqu           xmm3,       XMMWORD PTR [%5+%8]
+
+        psadbw          xmm1,       xmm0
+        psadbw          xmm2,       xmm0
+        psadbw          xmm3,       xmm0
+
+        paddw           xmm4,       xmm1
+        lddqu           xmm1,       XMMWORD PTR [%6+%8]
+        paddw           xmm5,       xmm2
+        paddw           xmm6,       xmm3
+
+%if %1==0 || %1==1
+        lea             %2,         [%2+%7*2]
+        lea             %3,         [%3+%8*2]
+
+        lea             %4,         [%4+%8*2]
+        lea             %5,         [%5+%8*2]
+
+        lea             %6,         [%6+%8*2]
+%endif
+        psadbw          xmm1,       xmm0
+        paddw           xmm7,       xmm1
+
+%endmacro
+
+%macro PROCESS_8X2X4 8
+%if %1==0
+        movq            mm0,        QWORD PTR [%2]
+        movq            mm4,        QWORD PTR [%3]
+        movq            mm5,        QWORD PTR [%4]
+        movq            mm6,        QWORD PTR [%5]
+        movq            mm7,        QWORD PTR [%6]
+
+        psadbw          mm4,        mm0
+        psadbw          mm5,        mm0
+        psadbw          mm6,        mm0
+        psadbw          mm7,        mm0
+%else
+        movq            mm0,        QWORD PTR [%2]
+        movq            mm1,        QWORD PTR [%3]
+        movq            mm2,        QWORD PTR [%4]
+        movq            mm3,        QWORD PTR [%5]
+
+        psadbw          mm1,        mm0
+        psadbw          mm2,        mm0
+        psadbw          mm3,        mm0
+
+        paddw           mm4,        mm1
+        movq            mm1,        QWORD PTR [%6]
+        paddw           mm5,        mm2
+        paddw           mm6,        mm3
+
+        psadbw          mm1,        mm0
+        paddw           mm7,        mm1
+%endif
+        movq            mm0,        QWORD PTR [%2+%7]
+        movq            mm1,        QWORD PTR [%3+%8]
+        movq            mm2,        QWORD PTR [%4+%8]
+        movq            mm3,        QWORD PTR [%5+%8]
+
+        psadbw          mm1,        mm0
+        psadbw          mm2,        mm0
+        psadbw          mm3,        mm0
+
+        paddw           mm4,        mm1
+        movq            mm1,        QWORD PTR [%6+%8]
+        paddw           mm5,        mm2
+        paddw           mm6,        mm3
+
+%if %1==0 || %1==1
+        lea             %2,         [%2+%7*2]
+        lea             %3,         [%3+%8*2]
+
+        lea             %4,         [%4+%8*2]
+        lea             %5,         [%5+%8*2]
+
+        lea             %6,         [%6+%8*2]
+%endif
+        psadbw          mm1,        mm0
+        paddw           mm7,        mm1
+
+%endmacro
+
+;void int vp8_sad16x16x3_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad16x16x3_sse3)
+sym(vp8_sad16x16x3_sse3):
+
+    STACK_FRAME_CREATE_X3
+
+        PROCESS_16X2X3 0, src_ptr, ref_ptr, src_stride, ref_stride
+        PROCESS_16X2X3 1, src_ptr, ref_ptr, src_stride, ref_stride
+        PROCESS_16X2X3 1, src_ptr, ref_ptr, src_stride, ref_stride
+        PROCESS_16X2X3 1, src_ptr, ref_ptr, src_stride, ref_stride
+        PROCESS_16X2X3 1, src_ptr, ref_ptr, src_stride, ref_stride
+        PROCESS_16X2X3 1, src_ptr, ref_ptr, src_stride, ref_stride
+        PROCESS_16X2X3 1, src_ptr, ref_ptr, src_stride, ref_stride
+        PROCESS_16X2X3 2, src_ptr, ref_ptr, src_stride, ref_stride
+
+        mov             rcx,        result_ptr
+
+        movq            xmm0,       xmm5
+        psrldq          xmm5,       8
+
+        paddw           xmm0,       xmm5
+        movd            [rcx],      xmm0
+;-
+        movq            xmm0,       xmm6
+        psrldq          xmm6,       8
+
+        paddw           xmm0,       xmm6
+        movd            [rcx+4],    xmm0
+;-
+        movq            xmm0,       xmm7
+        psrldq          xmm7,       8
+
+        paddw           xmm0,       xmm7
+        movd            [rcx+8],    xmm0
+
+    STACK_FRAME_DESTROY_X3
+
+;void int vp8_sad16x8x3_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad16x8x3_sse3)
+sym(vp8_sad16x8x3_sse3):
+
+    STACK_FRAME_CREATE_X3
+
+        PROCESS_16X2X3 0, src_ptr, ref_ptr, src_stride, ref_stride
+        PROCESS_16X2X3 1, src_ptr, ref_ptr, src_stride, ref_stride
+        PROCESS_16X2X3 1, src_ptr, ref_ptr, src_stride, ref_stride
+        PROCESS_16X2X3 2, src_ptr, ref_ptr, src_stride, ref_stride
+
+        mov             rcx,        result_ptr
+
+        movq            xmm0,       xmm5
+        psrldq          xmm5,       8
+
+        paddw           xmm0,       xmm5
+        movd            [rcx],      xmm0
+;-
+        movq            xmm0,       xmm6
+        psrldq          xmm6,       8
+
+        paddw           xmm0,       xmm6
+        movd            [rcx+4],    xmm0
+;-
+        movq            xmm0,       xmm7
+        psrldq          xmm7,       8
+
+        paddw           xmm0,       xmm7
+        movd            [rcx+8],    xmm0
+
+    STACK_FRAME_DESTROY_X3
+
+;void int vp8_sad8x16x3_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad8x16x3_sse3)
+sym(vp8_sad8x16x3_sse3):
+
+    STACK_FRAME_CREATE_X3
+
+        PROCESS_8X2X3 0, src_ptr, ref_ptr, src_stride, ref_stride
+        PROCESS_8X2X3 1, src_ptr, ref_ptr, src_stride, ref_stride
+        PROCESS_8X2X3 1, src_ptr, ref_ptr, src_stride, ref_stride
+        PROCESS_8X2X3 1, src_ptr, ref_ptr, src_stride, ref_stride
+        PROCESS_8X2X3 1, src_ptr, ref_ptr, src_stride, ref_stride
+        PROCESS_8X2X3 1, src_ptr, ref_ptr, src_stride, ref_stride
+        PROCESS_8X2X3 1, src_ptr, ref_ptr, src_stride, ref_stride
+        PROCESS_8X2X3 2, src_ptr, ref_ptr, src_stride, ref_stride
+
+        mov             rcx,        result_ptr
+
+        punpckldq       mm5,        mm6
+
+        movq            [rcx],      mm5
+        movd            [rcx+8],    mm7
+
+    STACK_FRAME_DESTROY_X3
+
+;void int vp8_sad8x8x3_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad8x8x3_sse3)
+sym(vp8_sad8x8x3_sse3):
+
+    STACK_FRAME_CREATE_X3
+
+        PROCESS_8X2X3 0, src_ptr, ref_ptr, src_stride, ref_stride
+        PROCESS_8X2X3 1, src_ptr, ref_ptr, src_stride, ref_stride
+        PROCESS_8X2X3 1, src_ptr, ref_ptr, src_stride, ref_stride
+        PROCESS_8X2X3 2, src_ptr, ref_ptr, src_stride, ref_stride
+
+        mov             rcx,        result_ptr
+
+        punpckldq       mm5,        mm6
+
+        movq            [rcx],      mm5
+        movd            [rcx+8],    mm7
+
+    STACK_FRAME_DESTROY_X3
+
+;void int vp8_sad4x4x3_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad4x4x3_sse3)
+sym(vp8_sad4x4x3_sse3):
+
+    STACK_FRAME_CREATE_X3
+
+        movd            mm0,        DWORD PTR [src_ptr]
+        movd            mm1,        DWORD PTR [ref_ptr]
+
+        movd            mm2,        DWORD PTR [src_ptr+src_stride]
+        movd            mm3,        DWORD PTR [ref_ptr+ref_stride]
+
+        punpcklbw       mm0,        mm2
+        punpcklbw       mm1,        mm3
+
+        movd            mm4,        DWORD PTR [ref_ptr+1]
+        movd            mm5,        DWORD PTR [ref_ptr+2]
+
+        movd            mm2,        DWORD PTR [ref_ptr+ref_stride+1]
+        movd            mm3,        DWORD PTR [ref_ptr+ref_stride+2]
+
+        psadbw          mm1,        mm0
+
+        punpcklbw       mm4,        mm2
+        punpcklbw       mm5,        mm3
+
+        psadbw          mm4,        mm0
+        psadbw          mm5,        mm0
+
+        lea             src_ptr,    [src_ptr+src_stride*2]
+        lea             ref_ptr,    [ref_ptr+ref_stride*2]
+
+        movd            mm0,        DWORD PTR [src_ptr]
+        movd            mm2,        DWORD PTR [ref_ptr]
+
+        movd            mm3,        DWORD PTR [src_ptr+src_stride]
+        movd            mm6,        DWORD PTR [ref_ptr+ref_stride]
+
+        punpcklbw       mm0,        mm3
+        punpcklbw       mm2,        mm6
+
+        movd            mm3,        DWORD PTR [ref_ptr+1]
+        movd            mm7,        DWORD PTR [ref_ptr+2]
+
+        psadbw          mm2,        mm0
+
+        paddw           mm1,        mm2
+
+        movd            mm2,        DWORD PTR [ref_ptr+ref_stride+1]
+        movd            mm6,        DWORD PTR [ref_ptr+ref_stride+2]
+
+        punpcklbw       mm3,        mm2
+        punpcklbw       mm7,        mm6
+
+        psadbw          mm3,        mm0
+        psadbw          mm7,        mm0
+
+        paddw           mm3,        mm4
+        paddw           mm7,        mm5
+
+        mov             rcx,        result_ptr
+
+        punpckldq       mm1,        mm3
+
+        movq            [rcx],      mm1
+        movd            [rcx+8],    mm7
+
+    STACK_FRAME_DESTROY_X3
+
+;unsigned int vp8_sad16x16_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  max_sad)
+;%define lddqu movdqu
+global sym(vp8_sad16x16_sse3)
+sym(vp8_sad16x16_sse3):
+
+    STACK_FRAME_CREATE_X3
+
+        mov             end_ptr,    4
+        pxor            xmm7,        xmm7
+
+.vp8_sad16x16_sse3_loop:
+        movdqa          xmm0,       XMMWORD PTR [src_ptr]
+        movdqu          xmm1,       XMMWORD PTR [ref_ptr]
+        movdqa          xmm2,       XMMWORD PTR [src_ptr+src_stride]
+        movdqu          xmm3,       XMMWORD PTR [ref_ptr+ref_stride]
+
+        lea             src_ptr,    [src_ptr+src_stride*2]
+        lea             ref_ptr,    [ref_ptr+ref_stride*2]
+
+        movdqa          xmm4,       XMMWORD PTR [src_ptr]
+        movdqu          xmm5,       XMMWORD PTR [ref_ptr]
+        movdqa          xmm6,       XMMWORD PTR [src_ptr+src_stride]
+
+        psadbw          xmm0,       xmm1
+
+        movdqu          xmm1,       XMMWORD PTR [ref_ptr+ref_stride]
+
+        psadbw          xmm2,       xmm3
+        psadbw          xmm4,       xmm5
+        psadbw          xmm6,       xmm1
+
+        lea             src_ptr,    [src_ptr+src_stride*2]
+        lea             ref_ptr,    [ref_ptr+ref_stride*2]
+
+        paddw           xmm7,        xmm0
+        paddw           xmm7,        xmm2
+        paddw           xmm7,        xmm4
+        paddw           xmm7,        xmm6
+
+        sub             end_ptr,     1
+        jne             .vp8_sad16x16_sse3_loop
+
+        movq            xmm0,       xmm7
+        psrldq          xmm7,       8
+        paddw           xmm0,       xmm7
+        movq            rax,        xmm0
+
+    STACK_FRAME_DESTROY_X3
+
+;void vp8_copy32xn_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *dst_ptr,
+;    int  dst_stride,
+;    int height);
+global sym(vp8_copy32xn_sse3)
+sym(vp8_copy32xn_sse3):
+
+    STACK_FRAME_CREATE_X3
+
+.block_copy_sse3_loopx4:
+        lea             end_ptr,    [src_ptr+src_stride*2]
+
+        movdqu          xmm0,       XMMWORD PTR [src_ptr]
+        movdqu          xmm1,       XMMWORD PTR [src_ptr + 16]
+        movdqu          xmm2,       XMMWORD PTR [src_ptr + src_stride]
+        movdqu          xmm3,       XMMWORD PTR [src_ptr + src_stride + 16]
+        movdqu          xmm4,       XMMWORD PTR [end_ptr]
+        movdqu          xmm5,       XMMWORD PTR [end_ptr + 16]
+        movdqu          xmm6,       XMMWORD PTR [end_ptr + src_stride]
+        movdqu          xmm7,       XMMWORD PTR [end_ptr + src_stride + 16]
+
+        lea             src_ptr,    [src_ptr+src_stride*4]
+
+        lea             end_ptr,    [ref_ptr+ref_stride*2]
+
+        movdqa          XMMWORD PTR [ref_ptr], xmm0
+        movdqa          XMMWORD PTR [ref_ptr + 16], xmm1
+        movdqa          XMMWORD PTR [ref_ptr + ref_stride], xmm2
+        movdqa          XMMWORD PTR [ref_ptr + ref_stride + 16], xmm3
+        movdqa          XMMWORD PTR [end_ptr], xmm4
+        movdqa          XMMWORD PTR [end_ptr + 16], xmm5
+        movdqa          XMMWORD PTR [end_ptr + ref_stride], xmm6
+        movdqa          XMMWORD PTR [end_ptr + ref_stride + 16], xmm7
+
+        lea             ref_ptr,    [ref_ptr+ref_stride*4]
+
+        sub             height,     4
+        cmp             height,     4
+        jge             .block_copy_sse3_loopx4
+
+        ;Check to see if there is more rows need to be copied.
+        cmp             height, 0
+        je              .copy_is_done
+
+.block_copy_sse3_loop:
+        movdqu          xmm0,       XMMWORD PTR [src_ptr]
+        movdqu          xmm1,       XMMWORD PTR [src_ptr + 16]
+        lea             src_ptr,    [src_ptr+src_stride]
+
+        movdqa          XMMWORD PTR [ref_ptr], xmm0
+        movdqa          XMMWORD PTR [ref_ptr + 16], xmm1
+        lea             ref_ptr,    [ref_ptr+ref_stride]
+
+        sub             height,     1
+        jne             .block_copy_sse3_loop
+
+.copy_is_done:
+    STACK_FRAME_DESTROY_X3
+
+;void vp8_sad16x16x4d_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr_base,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad16x16x4d_sse3)
+sym(vp8_sad16x16x4d_sse3):
+
+    STACK_FRAME_CREATE_X4
+
+        PROCESS_16X2X4 0, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+        PROCESS_16X2X4 1, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+        PROCESS_16X2X4 1, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+        PROCESS_16X2X4 1, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+        PROCESS_16X2X4 1, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+        PROCESS_16X2X4 1, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+        PROCESS_16X2X4 1, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+        PROCESS_16X2X4 2, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+
+%if ABI_IS_32BIT
+        pop             rbp
+%endif
+        mov             rcx,        result_ptr
+
+        movq            xmm0,       xmm4
+        psrldq          xmm4,       8
+
+        paddw           xmm0,       xmm4
+        movd            [rcx],      xmm0
+;-
+        movq            xmm0,       xmm5
+        psrldq          xmm5,       8
+
+        paddw           xmm0,       xmm5
+        movd            [rcx+4],    xmm0
+;-
+        movq            xmm0,       xmm6
+        psrldq          xmm6,       8
+
+        paddw           xmm0,       xmm6
+        movd            [rcx+8],    xmm0
+;-
+        movq            xmm0,       xmm7
+        psrldq          xmm7,       8
+
+        paddw           xmm0,       xmm7
+        movd            [rcx+12],   xmm0
+
+    STACK_FRAME_DESTROY_X4
+
+;void vp8_sad16x8x4d_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr_base,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad16x8x4d_sse3)
+sym(vp8_sad16x8x4d_sse3):
+
+    STACK_FRAME_CREATE_X4
+
+        PROCESS_16X2X4 0, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+        PROCESS_16X2X4 1, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+        PROCESS_16X2X4 1, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+        PROCESS_16X2X4 2, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+
+%if ABI_IS_32BIT
+        pop             rbp
+%endif
+        mov             rcx,        result_ptr
+
+        movq            xmm0,       xmm4
+        psrldq          xmm4,       8
+
+        paddw           xmm0,       xmm4
+        movd            [rcx],      xmm0
+;-
+        movq            xmm0,       xmm5
+        psrldq          xmm5,       8
+
+        paddw           xmm0,       xmm5
+        movd            [rcx+4],    xmm0
+;-
+        movq            xmm0,       xmm6
+        psrldq          xmm6,       8
+
+        paddw           xmm0,       xmm6
+        movd            [rcx+8],    xmm0
+;-
+        movq            xmm0,       xmm7
+        psrldq          xmm7,       8
+
+        paddw           xmm0,       xmm7
+        movd            [rcx+12],   xmm0
+
+    STACK_FRAME_DESTROY_X4
+
+;void int vp8_sad8x16x4d_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad8x16x4d_sse3)
+sym(vp8_sad8x16x4d_sse3):
+
+    STACK_FRAME_CREATE_X4
+
+        PROCESS_8X2X4 0, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+        PROCESS_8X2X4 1, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+        PROCESS_8X2X4 1, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+        PROCESS_8X2X4 1, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+        PROCESS_8X2X4 1, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+        PROCESS_8X2X4 1, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+        PROCESS_8X2X4 1, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+        PROCESS_8X2X4 2, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+
+%if ABI_IS_32BIT
+        pop             rbp
+%endif
+        mov             rcx,        result_ptr
+
+        punpckldq       mm4,        mm5
+        punpckldq       mm6,        mm7
+
+        movq            [rcx],      mm4
+        movq            [rcx+8],    mm6
+
+    STACK_FRAME_DESTROY_X4
+
+;void int vp8_sad8x8x4d_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad8x8x4d_sse3)
+sym(vp8_sad8x8x4d_sse3):
+
+    STACK_FRAME_CREATE_X4
+
+        PROCESS_8X2X4 0, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+        PROCESS_8X2X4 1, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+        PROCESS_8X2X4 1, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+        PROCESS_8X2X4 2, src_ptr, r0_ptr, r1_ptr, r2_ptr, r3_ptr, src_stride, ref_stride
+
+%if ABI_IS_32BIT
+        pop             rbp
+%endif
+        mov             rcx,        result_ptr
+
+        punpckldq       mm4,        mm5
+        punpckldq       mm6,        mm7
+
+        movq            [rcx],      mm4
+        movq            [rcx+8],    mm6
+
+    STACK_FRAME_DESTROY_X4
+
+;void int vp8_sad4x4x4d_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad4x4x4d_sse3)
+sym(vp8_sad4x4x4d_sse3):
+
+    STACK_FRAME_CREATE_X4
+
+        movd            mm0,        DWORD PTR [src_ptr]
+        movd            mm1,        DWORD PTR [r0_ptr]
+
+        movd            mm2,        DWORD PTR [src_ptr+src_stride]
+        movd            mm3,        DWORD PTR [r0_ptr+ref_stride]
+
+        punpcklbw       mm0,        mm2
+        punpcklbw       mm1,        mm3
+
+        movd            mm4,        DWORD PTR [r1_ptr]
+        movd            mm5,        DWORD PTR [r2_ptr]
+
+        movd            mm6,        DWORD PTR [r3_ptr]
+        movd            mm2,        DWORD PTR [r1_ptr+ref_stride]
+
+        movd            mm3,        DWORD PTR [r2_ptr+ref_stride]
+        movd            mm7,        DWORD PTR [r3_ptr+ref_stride]
+
+        psadbw          mm1,        mm0
+
+        punpcklbw       mm4,        mm2
+        punpcklbw       mm5,        mm3
+
+        punpcklbw       mm6,        mm7
+        psadbw          mm4,        mm0
+
+        psadbw          mm5,        mm0
+        psadbw          mm6,        mm0
+
+
+
+        lea             src_ptr,    [src_ptr+src_stride*2]
+        lea             r0_ptr,     [r0_ptr+ref_stride*2]
+
+        lea             r1_ptr,     [r1_ptr+ref_stride*2]
+        lea             r2_ptr,     [r2_ptr+ref_stride*2]
+
+        lea             r3_ptr,     [r3_ptr+ref_stride*2]
+
+        movd            mm0,        DWORD PTR [src_ptr]
+        movd            mm2,        DWORD PTR [r0_ptr]
+
+        movd            mm3,        DWORD PTR [src_ptr+src_stride]
+        movd            mm7,        DWORD PTR [r0_ptr+ref_stride]
+
+        punpcklbw       mm0,        mm3
+        punpcklbw       mm2,        mm7
+
+        movd            mm3,        DWORD PTR [r1_ptr]
+        movd            mm7,        DWORD PTR [r2_ptr]
+
+        psadbw          mm2,        mm0
+%if ABI_IS_32BIT
+        mov             rax,        rbp
+
+        pop             rbp
+%define     ref_stride    rax
+%endif
+        mov             rsi,        result_ptr
+
+        paddw           mm1,        mm2
+        movd            [rsi],      mm1
+
+        movd            mm2,        DWORD PTR [r1_ptr+ref_stride]
+        movd            mm1,        DWORD PTR [r2_ptr+ref_stride]
+
+        punpcklbw       mm3,        mm2
+        punpcklbw       mm7,        mm1
+
+        psadbw          mm3,        mm0
+        psadbw          mm7,        mm0
+
+        movd            mm2,        DWORD PTR [r3_ptr]
+        movd            mm1,        DWORD PTR [r3_ptr+ref_stride]
+
+        paddw           mm3,        mm4
+        paddw           mm7,        mm5
+
+        movd            [rsi+4],    mm3
+        punpcklbw       mm2,        mm1
+
+        movd            [rsi+8],    mm7
+        psadbw          mm2,        mm0
+
+        paddw           mm2,        mm6
+        movd            [rsi+12],   mm2
+
+
+    STACK_FRAME_DESTROY_X4
+
diff --git a/vp8/common/x86/sad_sse4.asm b/vp8/common/x86/sad_sse4.asm
new file mode 100644 (file)
index 0000000..03ecec4
--- /dev/null
@@ -0,0 +1,353 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+%macro PROCESS_16X2X8 1
+%if %1
+        movdqa          xmm0,       XMMWORD PTR [rsi]
+        movq            xmm1,       MMWORD PTR [rdi]
+        movq            xmm3,       MMWORD PTR [rdi+8]
+        movq            xmm2,       MMWORD PTR [rdi+16]
+        punpcklqdq      xmm1,       xmm3
+        punpcklqdq      xmm3,       xmm2
+
+        movdqa          xmm2,       xmm1
+        mpsadbw         xmm1,       xmm0,  0x0
+        mpsadbw         xmm2,       xmm0,  0x5
+
+        psrldq          xmm0,       8
+
+        movdqa          xmm4,       xmm3
+        mpsadbw         xmm3,       xmm0,  0x0
+        mpsadbw         xmm4,       xmm0,  0x5
+
+        paddw           xmm1,       xmm2
+        paddw           xmm1,       xmm3
+        paddw           xmm1,       xmm4
+%else
+        movdqa          xmm0,       XMMWORD PTR [rsi]
+        movq            xmm5,       MMWORD PTR [rdi]
+        movq            xmm3,       MMWORD PTR [rdi+8]
+        movq            xmm2,       MMWORD PTR [rdi+16]
+        punpcklqdq      xmm5,       xmm3
+        punpcklqdq      xmm3,       xmm2
+
+        movdqa          xmm2,       xmm5
+        mpsadbw         xmm5,       xmm0,  0x0
+        mpsadbw         xmm2,       xmm0,  0x5
+
+        psrldq          xmm0,       8
+
+        movdqa          xmm4,       xmm3
+        mpsadbw         xmm3,       xmm0,  0x0
+        mpsadbw         xmm4,       xmm0,  0x5
+
+        paddw           xmm5,       xmm2
+        paddw           xmm5,       xmm3
+        paddw           xmm5,       xmm4
+
+        paddw           xmm1,       xmm5
+%endif
+        movdqa          xmm0,       XMMWORD PTR [rsi + rax]
+        movq            xmm5,       MMWORD PTR [rdi+ rdx]
+        movq            xmm3,       MMWORD PTR [rdi+ rdx+8]
+        movq            xmm2,       MMWORD PTR [rdi+ rdx+16]
+        punpcklqdq      xmm5,       xmm3
+        punpcklqdq      xmm3,       xmm2
+
+        lea             rsi,        [rsi+rax*2]
+        lea             rdi,        [rdi+rdx*2]
+
+        movdqa          xmm2,       xmm5
+        mpsadbw         xmm5,       xmm0,  0x0
+        mpsadbw         xmm2,       xmm0,  0x5
+
+        psrldq          xmm0,       8
+        movdqa          xmm4,       xmm3
+        mpsadbw         xmm3,       xmm0,  0x0
+        mpsadbw         xmm4,       xmm0,  0x5
+
+        paddw           xmm5,       xmm2
+        paddw           xmm5,       xmm3
+        paddw           xmm5,       xmm4
+
+        paddw           xmm1,       xmm5
+%endmacro
+
+%macro PROCESS_8X2X8 1
+%if %1
+        movq            xmm0,       MMWORD PTR [rsi]
+        movq            xmm1,       MMWORD PTR [rdi]
+        movq            xmm3,       MMWORD PTR [rdi+8]
+        punpcklqdq      xmm1,       xmm3
+
+        movdqa          xmm2,       xmm1
+        mpsadbw         xmm1,       xmm0,  0x0
+        mpsadbw         xmm2,       xmm0,  0x5
+        paddw           xmm1,       xmm2
+%else
+        movq            xmm0,       MMWORD PTR [rsi]
+        movq            xmm5,       MMWORD PTR [rdi]
+        movq            xmm3,       MMWORD PTR [rdi+8]
+        punpcklqdq      xmm5,       xmm3
+
+        movdqa          xmm2,       xmm5
+        mpsadbw         xmm5,       xmm0,  0x0
+        mpsadbw         xmm2,       xmm0,  0x5
+        paddw           xmm5,       xmm2
+
+        paddw           xmm1,       xmm5
+%endif
+        movq            xmm0,       MMWORD PTR [rsi + rax]
+        movq            xmm5,       MMWORD PTR [rdi+ rdx]
+        movq            xmm3,       MMWORD PTR [rdi+ rdx+8]
+        punpcklqdq      xmm5,       xmm3
+
+        lea             rsi,        [rsi+rax*2]
+        lea             rdi,        [rdi+rdx*2]
+
+        movdqa          xmm2,       xmm5
+        mpsadbw         xmm5,       xmm0,  0x0
+        mpsadbw         xmm2,       xmm0,  0x5
+        paddw           xmm5,       xmm2
+
+        paddw           xmm1,       xmm5
+%endmacro
+
+%macro PROCESS_4X2X8 1
+%if %1
+        movd            xmm0,       [rsi]
+        movq            xmm1,       MMWORD PTR [rdi]
+        movq            xmm3,       MMWORD PTR [rdi+8]
+        punpcklqdq      xmm1,       xmm3
+
+        mpsadbw         xmm1,       xmm0,  0x0
+%else
+        movd            xmm0,       [rsi]
+        movq            xmm5,       MMWORD PTR [rdi]
+        movq            xmm3,       MMWORD PTR [rdi+8]
+        punpcklqdq      xmm5,       xmm3
+
+        mpsadbw         xmm5,       xmm0,  0x0
+
+        paddw           xmm1,       xmm5
+%endif
+        movd            xmm0,       [rsi + rax]
+        movq            xmm5,       MMWORD PTR [rdi+ rdx]
+        movq            xmm3,       MMWORD PTR [rdi+ rdx+8]
+        punpcklqdq      xmm5,       xmm3
+
+        lea             rsi,        [rsi+rax*2]
+        lea             rdi,        [rdi+rdx*2]
+
+        mpsadbw         xmm5,       xmm0,  0x0
+
+        paddw           xmm1,       xmm5
+%endmacro
+
+
+;void vp8_sad16x16x8_sse4(
+;    const unsigned char *src_ptr,
+;    int  src_stride,
+;    const unsigned char *ref_ptr,
+;    int  ref_stride,
+;    unsigned short *sad_array);
+global sym(vp8_sad16x16x8_sse4)
+sym(vp8_sad16x16x8_sse4):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov             rsi,        arg(0)           ;src_ptr
+        mov             rdi,        arg(2)           ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        PROCESS_16X2X8 1
+        PROCESS_16X2X8 0
+        PROCESS_16X2X8 0
+        PROCESS_16X2X8 0
+        PROCESS_16X2X8 0
+        PROCESS_16X2X8 0
+        PROCESS_16X2X8 0
+        PROCESS_16X2X8 0
+
+        mov             rdi,        arg(4)           ;Results
+        movdqa          XMMWORD PTR [rdi],    xmm1
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_sad16x8x8_sse4(
+;    const unsigned char *src_ptr,
+;    int  src_stride,
+;    const unsigned char *ref_ptr,
+;    int  ref_stride,
+;    unsigned short *sad_array
+;);
+global sym(vp8_sad16x8x8_sse4)
+sym(vp8_sad16x8x8_sse4):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov             rsi,        arg(0)           ;src_ptr
+        mov             rdi,        arg(2)           ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        PROCESS_16X2X8 1
+        PROCESS_16X2X8 0
+        PROCESS_16X2X8 0
+        PROCESS_16X2X8 0
+
+        mov             rdi,        arg(4)           ;Results
+        movdqa          XMMWORD PTR [rdi],    xmm1
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_sad8x8x8_sse4(
+;    const unsigned char *src_ptr,
+;    int  src_stride,
+;    const unsigned char *ref_ptr,
+;    int  ref_stride,
+;    unsigned short *sad_array
+;);
+global sym(vp8_sad8x8x8_sse4)
+sym(vp8_sad8x8x8_sse4):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov             rsi,        arg(0)           ;src_ptr
+        mov             rdi,        arg(2)           ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        PROCESS_8X2X8 1
+        PROCESS_8X2X8 0
+        PROCESS_8X2X8 0
+        PROCESS_8X2X8 0
+
+        mov             rdi,        arg(4)           ;Results
+        movdqa          XMMWORD PTR [rdi],    xmm1
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_sad8x16x8_sse4(
+;    const unsigned char *src_ptr,
+;    int  src_stride,
+;    const unsigned char *ref_ptr,
+;    int  ref_stride,
+;    unsigned short *sad_array
+;);
+global sym(vp8_sad8x16x8_sse4)
+sym(vp8_sad8x16x8_sse4):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov             rsi,        arg(0)           ;src_ptr
+        mov             rdi,        arg(2)           ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        PROCESS_8X2X8 1
+        PROCESS_8X2X8 0
+        PROCESS_8X2X8 0
+        PROCESS_8X2X8 0
+        PROCESS_8X2X8 0
+        PROCESS_8X2X8 0
+        PROCESS_8X2X8 0
+        PROCESS_8X2X8 0
+        mov             rdi,        arg(4)           ;Results
+        movdqa          XMMWORD PTR [rdi],    xmm1
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_sad4x4x8_c(
+;    const unsigned char *src_ptr,
+;    int  src_stride,
+;    const unsigned char *ref_ptr,
+;    int  ref_stride,
+;    unsigned short *sad_array
+;);
+global sym(vp8_sad4x4x8_sse4)
+sym(vp8_sad4x4x8_sse4):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov             rsi,        arg(0)           ;src_ptr
+        mov             rdi,        arg(2)           ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        PROCESS_4X2X8 1
+        PROCESS_4X2X8 0
+
+        mov             rdi,        arg(4)           ;Results
+        movdqa          XMMWORD PTR [rdi],    xmm1
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+
+
diff --git a/vp8/common/x86/sad_ssse3.asm b/vp8/common/x86/sad_ssse3.asm
new file mode 100644 (file)
index 0000000..95b6c89
--- /dev/null
@@ -0,0 +1,370 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+%macro PROCESS_16X2X3 1
+%if %1
+        movdqa          xmm0,       XMMWORD PTR [rsi]
+        lddqu           xmm5,       XMMWORD PTR [rdi]
+        lddqu           xmm6,       XMMWORD PTR [rdi+1]
+        lddqu           xmm7,       XMMWORD PTR [rdi+2]
+
+        psadbw          xmm5,       xmm0
+        psadbw          xmm6,       xmm0
+        psadbw          xmm7,       xmm0
+%else
+        movdqa          xmm0,       XMMWORD PTR [rsi]
+        lddqu           xmm1,       XMMWORD PTR [rdi]
+        lddqu           xmm2,       XMMWORD PTR [rdi+1]
+        lddqu           xmm3,       XMMWORD PTR [rdi+2]
+
+        psadbw          xmm1,       xmm0
+        psadbw          xmm2,       xmm0
+        psadbw          xmm3,       xmm0
+
+        paddw           xmm5,       xmm1
+        paddw           xmm6,       xmm2
+        paddw           xmm7,       xmm3
+%endif
+        movdqa          xmm0,       XMMWORD PTR [rsi+rax]
+        lddqu           xmm1,       XMMWORD PTR [rdi+rdx]
+        lddqu           xmm2,       XMMWORD PTR [rdi+rdx+1]
+        lddqu           xmm3,       XMMWORD PTR [rdi+rdx+2]
+
+        lea             rsi,        [rsi+rax*2]
+        lea             rdi,        [rdi+rdx*2]
+
+        psadbw          xmm1,       xmm0
+        psadbw          xmm2,       xmm0
+        psadbw          xmm3,       xmm0
+
+        paddw           xmm5,       xmm1
+        paddw           xmm6,       xmm2
+        paddw           xmm7,       xmm3
+%endmacro
+
+%macro PROCESS_16X2X3_OFFSET 2
+%if %1
+        movdqa          xmm0,       XMMWORD PTR [rsi]
+        movdqa          xmm4,       XMMWORD PTR [rdi]
+        movdqa          xmm7,       XMMWORD PTR [rdi+16]
+
+        movdqa          xmm5,       xmm7
+        palignr         xmm5,       xmm4,       %2
+
+        movdqa          xmm6,       xmm7
+        palignr         xmm6,       xmm4,       (%2+1)
+
+        palignr         xmm7,       xmm4,       (%2+2)
+
+        psadbw          xmm5,       xmm0
+        psadbw          xmm6,       xmm0
+        psadbw          xmm7,       xmm0
+%else
+        movdqa          xmm0,       XMMWORD PTR [rsi]
+        movdqa          xmm4,       XMMWORD PTR [rdi]
+        movdqa          xmm3,       XMMWORD PTR [rdi+16]
+
+        movdqa          xmm1,       xmm3
+        palignr         xmm1,       xmm4,       %2
+
+        movdqa          xmm2,       xmm3
+        palignr         xmm2,       xmm4,       (%2+1)
+
+        palignr         xmm3,       xmm4,       (%2+2)
+
+        psadbw          xmm1,       xmm0
+        psadbw          xmm2,       xmm0
+        psadbw          xmm3,       xmm0
+
+        paddw           xmm5,       xmm1
+        paddw           xmm6,       xmm2
+        paddw           xmm7,       xmm3
+%endif
+        movdqa          xmm0,       XMMWORD PTR [rsi+rax]
+        movdqa          xmm4,       XMMWORD PTR [rdi+rdx]
+        movdqa          xmm3,       XMMWORD PTR [rdi+rdx+16]
+
+        movdqa          xmm1,       xmm3
+        palignr         xmm1,       xmm4,       %2
+
+        movdqa          xmm2,       xmm3
+        palignr         xmm2,       xmm4,       (%2+1)
+
+        palignr         xmm3,       xmm4,       (%2+2)
+
+        lea             rsi,        [rsi+rax*2]
+        lea             rdi,        [rdi+rdx*2]
+
+        psadbw          xmm1,       xmm0
+        psadbw          xmm2,       xmm0
+        psadbw          xmm3,       xmm0
+
+        paddw           xmm5,       xmm1
+        paddw           xmm6,       xmm2
+        paddw           xmm7,       xmm3
+%endmacro
+
+%macro PROCESS_16X16X3_OFFSET 2
+%2_aligned_by_%1:
+
+        sub             rdi,        %1
+
+        PROCESS_16X2X3_OFFSET 1, %1
+        PROCESS_16X2X3_OFFSET 0, %1
+        PROCESS_16X2X3_OFFSET 0, %1
+        PROCESS_16X2X3_OFFSET 0, %1
+        PROCESS_16X2X3_OFFSET 0, %1
+        PROCESS_16X2X3_OFFSET 0, %1
+        PROCESS_16X2X3_OFFSET 0, %1
+        PROCESS_16X2X3_OFFSET 0, %1
+
+        jmp             %2_store_off
+
+%endmacro
+
+%macro PROCESS_16X8X3_OFFSET 2
+%2_aligned_by_%1:
+
+        sub             rdi,        %1
+
+        PROCESS_16X2X3_OFFSET 1, %1
+        PROCESS_16X2X3_OFFSET 0, %1
+        PROCESS_16X2X3_OFFSET 0, %1
+        PROCESS_16X2X3_OFFSET 0, %1
+
+        jmp             %2_store_off
+
+%endmacro
+
+;void int vp8_sad16x16x3_ssse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad16x16x3_ssse3)
+sym(vp8_sad16x16x3_ssse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    SAVE_XMM 7
+    push        rsi
+    push        rdi
+    push        rcx
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        mov             rdx,        0xf
+        and             rdx,        rdi
+
+        jmp .vp8_sad16x16x3_ssse3_skiptable
+.vp8_sad16x16x3_ssse3_jumptable:
+        dd .vp8_sad16x16x3_ssse3_aligned_by_0  - .vp8_sad16x16x3_ssse3_do_jump
+        dd .vp8_sad16x16x3_ssse3_aligned_by_1  - .vp8_sad16x16x3_ssse3_do_jump
+        dd .vp8_sad16x16x3_ssse3_aligned_by_2  - .vp8_sad16x16x3_ssse3_do_jump
+        dd .vp8_sad16x16x3_ssse3_aligned_by_3  - .vp8_sad16x16x3_ssse3_do_jump
+        dd .vp8_sad16x16x3_ssse3_aligned_by_4  - .vp8_sad16x16x3_ssse3_do_jump
+        dd .vp8_sad16x16x3_ssse3_aligned_by_5  - .vp8_sad16x16x3_ssse3_do_jump
+        dd .vp8_sad16x16x3_ssse3_aligned_by_6  - .vp8_sad16x16x3_ssse3_do_jump
+        dd .vp8_sad16x16x3_ssse3_aligned_by_7  - .vp8_sad16x16x3_ssse3_do_jump
+        dd .vp8_sad16x16x3_ssse3_aligned_by_8  - .vp8_sad16x16x3_ssse3_do_jump
+        dd .vp8_sad16x16x3_ssse3_aligned_by_9  - .vp8_sad16x16x3_ssse3_do_jump
+        dd .vp8_sad16x16x3_ssse3_aligned_by_10 - .vp8_sad16x16x3_ssse3_do_jump
+        dd .vp8_sad16x16x3_ssse3_aligned_by_11 - .vp8_sad16x16x3_ssse3_do_jump
+        dd .vp8_sad16x16x3_ssse3_aligned_by_12 - .vp8_sad16x16x3_ssse3_do_jump
+        dd .vp8_sad16x16x3_ssse3_aligned_by_13 - .vp8_sad16x16x3_ssse3_do_jump
+        dd .vp8_sad16x16x3_ssse3_aligned_by_14 - .vp8_sad16x16x3_ssse3_do_jump
+        dd .vp8_sad16x16x3_ssse3_aligned_by_15 - .vp8_sad16x16x3_ssse3_do_jump
+.vp8_sad16x16x3_ssse3_skiptable:
+
+        call .vp8_sad16x16x3_ssse3_do_jump
+.vp8_sad16x16x3_ssse3_do_jump:
+        pop             rcx                         ; get the address of do_jump
+        mov             rax,  .vp8_sad16x16x3_ssse3_jumptable - .vp8_sad16x16x3_ssse3_do_jump
+        add             rax,  rcx  ; get the absolute address of vp8_sad16x16x3_ssse3_jumptable
+
+        movsxd          rax,  dword [rax + 4*rdx]   ; get the 32 bit offset from the jumptable
+        add             rcx,        rax
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        jmp             rcx
+
+        PROCESS_16X16X3_OFFSET 0,  .vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 1,  .vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 2,  .vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 3,  .vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 4,  .vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 5,  .vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 6,  .vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 7,  .vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 8,  .vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 9,  .vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 10, .vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 11, .vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 12, .vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 13, .vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 14, .vp8_sad16x16x3_ssse3
+
+.vp8_sad16x16x3_ssse3_aligned_by_15:
+        PROCESS_16X2X3 1
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+
+.vp8_sad16x16x3_ssse3_store_off:
+        mov             rdi,        arg(4) ;Results
+
+        movq            xmm0,       xmm5
+        psrldq          xmm5,       8
+
+        paddw           xmm0,       xmm5
+        movd            [rdi],      xmm0
+;-
+        movq            xmm0,       xmm6
+        psrldq          xmm6,       8
+
+        paddw           xmm0,       xmm6
+        movd            [rdi+4],    xmm0
+;-
+        movq            xmm0,       xmm7
+        psrldq          xmm7,       8
+
+        paddw           xmm0,       xmm7
+        movd            [rdi+8],    xmm0
+
+    ; begin epilog
+    pop         rcx
+    pop         rdi
+    pop         rsi
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void int vp8_sad16x8x3_ssse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad16x8x3_ssse3)
+sym(vp8_sad16x8x3_ssse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    SAVE_XMM 7
+    push        rsi
+    push        rdi
+    push        rcx
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        mov             rdx,        0xf
+        and             rdx,        rdi
+
+        jmp .vp8_sad16x8x3_ssse3_skiptable
+.vp8_sad16x8x3_ssse3_jumptable:
+        dd .vp8_sad16x8x3_ssse3_aligned_by_0  - .vp8_sad16x8x3_ssse3_do_jump
+        dd .vp8_sad16x8x3_ssse3_aligned_by_1  - .vp8_sad16x8x3_ssse3_do_jump
+        dd .vp8_sad16x8x3_ssse3_aligned_by_2  - .vp8_sad16x8x3_ssse3_do_jump
+        dd .vp8_sad16x8x3_ssse3_aligned_by_3  - .vp8_sad16x8x3_ssse3_do_jump
+        dd .vp8_sad16x8x3_ssse3_aligned_by_4  - .vp8_sad16x8x3_ssse3_do_jump
+        dd .vp8_sad16x8x3_ssse3_aligned_by_5  - .vp8_sad16x8x3_ssse3_do_jump
+        dd .vp8_sad16x8x3_ssse3_aligned_by_6  - .vp8_sad16x8x3_ssse3_do_jump
+        dd .vp8_sad16x8x3_ssse3_aligned_by_7  - .vp8_sad16x8x3_ssse3_do_jump
+        dd .vp8_sad16x8x3_ssse3_aligned_by_8  - .vp8_sad16x8x3_ssse3_do_jump
+        dd .vp8_sad16x8x3_ssse3_aligned_by_9  - .vp8_sad16x8x3_ssse3_do_jump
+        dd .vp8_sad16x8x3_ssse3_aligned_by_10 - .vp8_sad16x8x3_ssse3_do_jump
+        dd .vp8_sad16x8x3_ssse3_aligned_by_11 - .vp8_sad16x8x3_ssse3_do_jump
+        dd .vp8_sad16x8x3_ssse3_aligned_by_12 - .vp8_sad16x8x3_ssse3_do_jump
+        dd .vp8_sad16x8x3_ssse3_aligned_by_13 - .vp8_sad16x8x3_ssse3_do_jump
+        dd .vp8_sad16x8x3_ssse3_aligned_by_14 - .vp8_sad16x8x3_ssse3_do_jump
+        dd .vp8_sad16x8x3_ssse3_aligned_by_15 - .vp8_sad16x8x3_ssse3_do_jump
+.vp8_sad16x8x3_ssse3_skiptable:
+
+        call .vp8_sad16x8x3_ssse3_do_jump
+.vp8_sad16x8x3_ssse3_do_jump:
+        pop             rcx                         ; get the address of do_jump
+        mov             rax,  .vp8_sad16x8x3_ssse3_jumptable - .vp8_sad16x8x3_ssse3_do_jump
+        add             rax,  rcx  ; get the absolute address of vp8_sad16x8x3_ssse3_jumptable
+
+        movsxd          rax,  dword [rax + 4*rdx]   ; get the 32 bit offset from the jumptable
+        add             rcx,        rax
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        jmp             rcx
+
+        PROCESS_16X8X3_OFFSET 0,  .vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 1,  .vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 2,  .vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 3,  .vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 4,  .vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 5,  .vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 6,  .vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 7,  .vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 8,  .vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 9,  .vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 10, .vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 11, .vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 12, .vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 13, .vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 14, .vp8_sad16x8x3_ssse3
+
+.vp8_sad16x8x3_ssse3_aligned_by_15:
+
+        PROCESS_16X2X3 1
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+
+.vp8_sad16x8x3_ssse3_store_off:
+        mov             rdi,        arg(4) ;Results
+
+        movq            xmm0,       xmm5
+        psrldq          xmm5,       8
+
+        paddw           xmm0,       xmm5
+        movd            [rdi],      xmm0
+;-
+        movq            xmm0,       xmm6
+        psrldq          xmm6,       8
+
+        paddw           xmm0,       xmm6
+        movd            [rdi+4],    xmm0
+;-
+        movq            xmm0,       xmm7
+        psrldq          xmm7,       8
+
+        paddw           xmm0,       xmm7
+        movd            [rdi+8],    xmm0
+
+    ; begin epilog
+    pop         rcx
+    pop         rdi
+    pop         rsi
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
diff --git a/vp8/common/x86/subpixel_mmx.asm b/vp8/common/x86/subpixel_mmx.asm
new file mode 100644 (file)
index 0000000..5528fd0
--- /dev/null
@@ -0,0 +1,702 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+extern sym(vp8_bilinear_filters_x86_8)
+
+
+%define BLOCK_HEIGHT_WIDTH 4
+%define vp8_filter_weight 128
+%define VP8_FILTER_SHIFT  7
+
+
+;void vp8_filter_block1d_h6_mmx
+;(
+;    unsigned char   *src_ptr,
+;    unsigned short  *output_ptr,
+;    unsigned int    src_pixels_per_line,
+;    unsigned int    pixel_step,
+;    unsigned int    output_height,
+;    unsigned int    output_width,
+;    short           * vp8_filter
+;)
+global sym(vp8_filter_block1d_h6_mmx)
+sym(vp8_filter_block1d_h6_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rdx,    arg(6) ;vp8_filter
+
+        movq        mm1,    [rdx + 16]             ; do both the negative taps first!!!
+        movq        mm2,    [rdx + 32]         ;
+        movq        mm6,    [rdx + 48]        ;
+        movq        mm7,    [rdx + 64]        ;
+
+        mov         rdi,    arg(1) ;output_ptr
+        mov         rsi,    arg(0) ;src_ptr
+        movsxd      rcx,    dword ptr arg(4) ;output_height
+        movsxd      rax,    dword ptr arg(5) ;output_width      ; destination pitch?
+        pxor        mm0,    mm0              ; mm0 = 00000000
+
+.nextrow:
+        movq        mm3,    [rsi-2]          ; mm3 = p-2..p5
+        movq        mm4,    mm3              ; mm4 = p-2..p5
+        psrlq       mm3,    8                ; mm3 = p-1..p5
+        punpcklbw   mm3,    mm0              ; mm3 = p-1..p2
+        pmullw      mm3,    mm1              ; mm3 *= kernel 1 modifiers.
+
+        movq        mm5,    mm4              ; mm5 = p-2..p5
+        punpckhbw   mm4,    mm0              ; mm5 = p2..p5
+        pmullw      mm4,    mm7              ; mm5 *= kernel 4 modifiers
+        paddsw      mm3,    mm4              ; mm3 += mm5
+
+        movq        mm4,    mm5              ; mm4 = p-2..p5;
+        psrlq       mm5,    16               ; mm5 = p0..p5;
+        punpcklbw   mm5,    mm0              ; mm5 = p0..p3
+        pmullw      mm5,    mm2              ; mm5 *= kernel 2 modifiers
+        paddsw      mm3,    mm5              ; mm3 += mm5
+
+        movq        mm5,    mm4              ; mm5 = p-2..p5
+        psrlq       mm4,    24               ; mm4 = p1..p5
+        punpcklbw   mm4,    mm0              ; mm4 = p1..p4
+        pmullw      mm4,    mm6              ; mm5 *= kernel 3 modifiers
+        paddsw      mm3,    mm4              ; mm3 += mm5
+
+        ; do outer positive taps
+        movd        mm4,    [rsi+3]
+        punpcklbw   mm4,    mm0              ; mm5 = p3..p6
+        pmullw      mm4,    [rdx+80]         ; mm5 *= kernel 0 modifiers
+        paddsw      mm3,    mm4              ; mm3 += mm5
+
+        punpcklbw   mm5,    mm0              ; mm5 = p-2..p1
+        pmullw      mm5,    [rdx]            ; mm5 *= kernel 5 modifiers
+        paddsw      mm3,    mm5              ; mm3 += mm5
+
+        paddsw      mm3,    [GLOBAL(rd)]              ; mm3 += round value
+        psraw       mm3,    VP8_FILTER_SHIFT     ; mm3 /= 128
+        packuswb    mm3,    mm0              ; pack and unpack to saturate
+        punpcklbw   mm3,    mm0              ;
+
+        movq        [rdi],  mm3              ; store the results in the destination
+
+%if ABI_IS_32BIT
+        add         rsi,    dword ptr arg(2) ;src_pixels_per_line ; next line
+        add         rdi,    rax;
+%else
+        movsxd      r8,     dword ptr arg(2) ;src_pixels_per_line
+        add         rdi,    rax;
+
+        add         rsi,    r8               ; next line
+%endif
+
+        dec         rcx                      ; decrement count
+        jnz         .nextrow                 ; next row
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_filter_block1dc_v6_mmx
+;(
+;   short *src_ptr,
+;   unsigned char *output_ptr,
+;    int output_pitch,
+;   unsigned int pixels_per_line,
+;   unsigned int pixel_step,
+;   unsigned int output_height,
+;   unsigned int output_width,
+;   short * vp8_filter
+;)
+global sym(vp8_filter_block1dc_v6_mmx)
+sym(vp8_filter_block1dc_v6_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 8
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        movq      mm5, [GLOBAL(rd)]
+        push        rbx
+        mov         rbx, arg(7) ;vp8_filter
+        movq      mm1, [rbx + 16]             ; do both the negative taps first!!!
+        movq      mm2, [rbx + 32]         ;
+        movq      mm6, [rbx + 48]        ;
+        movq      mm7, [rbx + 64]        ;
+
+        movsxd      rdx, dword ptr arg(3) ;pixels_per_line
+        mov         rdi, arg(1) ;output_ptr
+        mov         rsi, arg(0) ;src_ptr
+        sub         rsi, rdx
+        sub         rsi, rdx
+        movsxd      rcx, DWORD PTR arg(5) ;output_height
+        movsxd      rax, DWORD PTR arg(2) ;output_pitch      ; destination pitch?
+        pxor        mm0, mm0              ; mm0 = 00000000
+
+
+.nextrow_cv:
+        movq        mm3, [rsi+rdx]        ; mm3 = p0..p8  = row -1
+        pmullw      mm3, mm1              ; mm3 *= kernel 1 modifiers.
+
+
+        movq        mm4, [rsi + 4*rdx]      ; mm4 = p0..p3  = row 2
+        pmullw      mm4, mm7              ; mm4 *= kernel 4 modifiers.
+        paddsw      mm3, mm4              ; mm3 += mm4
+
+        movq        mm4, [rsi + 2*rdx]           ; mm4 = p0..p3  = row 0
+        pmullw      mm4, mm2              ; mm4 *= kernel 2 modifiers.
+        paddsw      mm3, mm4              ; mm3 += mm4
+
+        movq        mm4, [rsi]            ; mm4 = p0..p3  = row -2
+        pmullw      mm4, [rbx]            ; mm4 *= kernel 0 modifiers.
+        paddsw      mm3, mm4              ; mm3 += mm4
+
+
+        add         rsi, rdx              ; move source forward 1 line to avoid 3 * pitch
+        movq        mm4, [rsi + 2*rdx]     ; mm4 = p0..p3  = row 1
+        pmullw      mm4, mm6              ; mm4 *= kernel 3 modifiers.
+        paddsw      mm3, mm4              ; mm3 += mm4
+
+        movq        mm4, [rsi + 4*rdx]    ; mm4 = p0..p3  = row 3
+        pmullw      mm4, [rbx +80]        ; mm4 *= kernel 3 modifiers.
+        paddsw      mm3, mm4              ; mm3 += mm4
+
+
+        paddsw      mm3, mm5               ; mm3 += round value
+        psraw       mm3, VP8_FILTER_SHIFT     ; mm3 /= 128
+        packuswb    mm3, mm0              ; pack and saturate
+
+        movd        [rdi],mm3             ; store the results in the destination
+        ; the subsequent iterations repeat 3 out of 4 of these reads.  Since the
+        ; recon block should be in cache this shouldn't cost much.  Its obviously
+        ; avoidable!!!.
+        lea         rdi,  [rdi+rax] ;
+        dec         rcx                   ; decrement count
+        jnz         .nextrow_cv           ; next row
+
+        pop         rbx
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void bilinear_predict8x8_mmx
+;(
+;    unsigned char  *src_ptr,
+;    int   src_pixels_per_line,
+;    int  xoffset,
+;    int  yoffset,
+;   unsigned char *dst_ptr,
+;    int dst_pitch
+;)
+global sym(vp8_bilinear_predict8x8_mmx)
+sym(vp8_bilinear_predict8x8_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ;const short *HFilter = vp8_bilinear_filters_x86_8[xoffset];
+    ;const short *VFilter = vp8_bilinear_filters_x86_8[yoffset];
+
+        movsxd      rax,        dword ptr arg(2) ;xoffset
+        mov         rdi,        arg(4) ;dst_ptr           ;
+
+        shl         rax,        5 ; offset * 32
+        lea         rcx,        [GLOBAL(sym(vp8_bilinear_filters_x86_8))]
+
+        add         rax,        rcx ; HFilter
+        mov         rsi,        arg(0) ;src_ptr              ;
+
+        movsxd      rdx,        dword ptr arg(5) ;dst_pitch
+        movq        mm1,        [rax]               ;
+
+        movq        mm2,        [rax+16]            ;
+        movsxd      rax,        dword ptr arg(3) ;yoffset
+
+        pxor        mm0,        mm0                 ;
+
+        shl         rax,        5 ; offset*32
+        add         rax,        rcx ; VFilter
+
+        lea         rcx,        [rdi+rdx*8]          ;
+        movsxd      rdx,        dword ptr arg(1) ;src_pixels_per_line    ;
+
+
+
+        ; get the first horizontal line done       ;
+        movq        mm3,        [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+        movq        mm4,        mm3                 ; make a copy of current line
+
+        punpcklbw   mm3,        mm0                 ; xx 00 01 02 03 04 05 06
+        punpckhbw   mm4,        mm0                 ;
+
+        pmullw      mm3,        mm1                 ;
+        pmullw      mm4,        mm1                 ;
+
+        movq        mm5,        [rsi+1]             ;
+        movq        mm6,        mm5                 ;
+
+        punpcklbw   mm5,        mm0                 ;
+        punpckhbw   mm6,        mm0                 ;
+
+        pmullw      mm5,        mm2                 ;
+        pmullw      mm6,        mm2                 ;
+
+        paddw       mm3,        mm5                 ;
+        paddw       mm4,        mm6                 ;
+
+        paddw       mm3,        [GLOBAL(rd)]                 ; xmm3 += round value
+        psraw       mm3,        VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       mm4,        [GLOBAL(rd)]                 ;
+        psraw       mm4,        VP8_FILTER_SHIFT        ;
+
+        movq        mm7,        mm3                 ;
+        packuswb    mm7,        mm4                 ;
+
+        add         rsi,        rdx                 ; next line
+.next_row_8x8:
+        movq        mm3,        [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+        movq        mm4,        mm3                 ; make a copy of current line
+
+        punpcklbw   mm3,        mm0                 ; xx 00 01 02 03 04 05 06
+        punpckhbw   mm4,        mm0                 ;
+
+        pmullw      mm3,        mm1                 ;
+        pmullw      mm4,        mm1                 ;
+
+        movq        mm5,        [rsi+1]             ;
+        movq        mm6,        mm5                 ;
+
+        punpcklbw   mm5,        mm0                 ;
+        punpckhbw   mm6,        mm0                 ;
+
+        pmullw      mm5,        mm2                 ;
+        pmullw      mm6,        mm2                 ;
+
+        paddw       mm3,        mm5                 ;
+        paddw       mm4,        mm6                 ;
+
+        movq        mm5,        mm7                 ;
+        movq        mm6,        mm7                 ;
+
+        punpcklbw   mm5,        mm0                 ;
+        punpckhbw   mm6,        mm0
+
+        pmullw      mm5,        [rax]               ;
+        pmullw      mm6,        [rax]               ;
+
+        paddw       mm3,        [GLOBAL(rd)]                 ; xmm3 += round value
+        psraw       mm3,        VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       mm4,        [GLOBAL(rd)]                 ;
+        psraw       mm4,        VP8_FILTER_SHIFT        ;
+
+        movq        mm7,        mm3                 ;
+        packuswb    mm7,        mm4                 ;
+
+
+        pmullw      mm3,        [rax+16]            ;
+        pmullw      mm4,        [rax+16]            ;
+
+        paddw       mm3,        mm5                 ;
+        paddw       mm4,        mm6                 ;
+
+
+        paddw       mm3,        [GLOBAL(rd)]                 ; xmm3 += round value
+        psraw       mm3,        VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       mm4,        [GLOBAL(rd)]                 ;
+        psraw       mm4,        VP8_FILTER_SHIFT        ;
+
+        packuswb    mm3,        mm4
+
+        movq        [rdi],      mm3                 ; store the results in the destination
+
+%if ABI_IS_32BIT
+        add         rsi,        rdx                 ; next line
+        add         rdi,        dword ptr arg(5) ;dst_pitch                   ;
+%else
+        movsxd      r8,         dword ptr arg(5) ;dst_pitch
+        add         rsi,        rdx                 ; next line
+        add         rdi,        r8                  ;dst_pitch
+%endif
+        cmp         rdi,        rcx                 ;
+        jne         .next_row_8x8
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void bilinear_predict8x4_mmx
+;(
+;    unsigned char  *src_ptr,
+;    int   src_pixels_per_line,
+;    int  xoffset,
+;    int  yoffset,
+;    unsigned char *dst_ptr,
+;    int dst_pitch
+;)
+global sym(vp8_bilinear_predict8x4_mmx)
+sym(vp8_bilinear_predict8x4_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ;const short *HFilter = vp8_bilinear_filters_x86_8[xoffset];
+    ;const short *VFilter = vp8_bilinear_filters_x86_8[yoffset];
+
+        movsxd      rax,        dword ptr arg(2) ;xoffset
+        mov         rdi,        arg(4) ;dst_ptr           ;
+
+        lea         rcx,        [GLOBAL(sym(vp8_bilinear_filters_x86_8))]
+        shl         rax,        5
+
+        mov         rsi,        arg(0) ;src_ptr              ;
+        add         rax,        rcx
+
+        movsxd      rdx,        dword ptr arg(5) ;dst_pitch
+        movq        mm1,        [rax]               ;
+
+        movq        mm2,        [rax+16]            ;
+        movsxd      rax,        dword ptr arg(3) ;yoffset
+
+        pxor        mm0,        mm0                 ;
+        shl         rax,        5
+
+        add         rax,        rcx
+        lea         rcx,        [rdi+rdx*4]          ;
+
+        movsxd      rdx,        dword ptr arg(1) ;src_pixels_per_line    ;
+
+        ; get the first horizontal line done       ;
+        movq        mm3,        [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+        movq        mm4,        mm3                 ; make a copy of current line
+
+        punpcklbw   mm3,        mm0                 ; xx 00 01 02 03 04 05 06
+        punpckhbw   mm4,        mm0                 ;
+
+        pmullw      mm3,        mm1                 ;
+        pmullw      mm4,        mm1                 ;
+
+        movq        mm5,        [rsi+1]             ;
+        movq        mm6,        mm5                 ;
+
+        punpcklbw   mm5,        mm0                 ;
+        punpckhbw   mm6,        mm0                 ;
+
+        pmullw      mm5,        mm2                 ;
+        pmullw      mm6,        mm2                 ;
+
+        paddw       mm3,        mm5                 ;
+        paddw       mm4,        mm6                 ;
+
+        paddw       mm3,        [GLOBAL(rd)]                 ; xmm3 += round value
+        psraw       mm3,        VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       mm4,        [GLOBAL(rd)]                 ;
+        psraw       mm4,        VP8_FILTER_SHIFT        ;
+
+        movq        mm7,        mm3                 ;
+        packuswb    mm7,        mm4                 ;
+
+        add         rsi,        rdx                 ; next line
+.next_row_8x4:
+        movq        mm3,        [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+        movq        mm4,        mm3                 ; make a copy of current line
+
+        punpcklbw   mm3,        mm0                 ; xx 00 01 02 03 04 05 06
+        punpckhbw   mm4,        mm0                 ;
+
+        pmullw      mm3,        mm1                 ;
+        pmullw      mm4,        mm1                 ;
+
+        movq        mm5,        [rsi+1]             ;
+        movq        mm6,        mm5                 ;
+
+        punpcklbw   mm5,        mm0                 ;
+        punpckhbw   mm6,        mm0                 ;
+
+        pmullw      mm5,        mm2                 ;
+        pmullw      mm6,        mm2                 ;
+
+        paddw       mm3,        mm5                 ;
+        paddw       mm4,        mm6                 ;
+
+        movq        mm5,        mm7                 ;
+        movq        mm6,        mm7                 ;
+
+        punpcklbw   mm5,        mm0                 ;
+        punpckhbw   mm6,        mm0
+
+        pmullw      mm5,        [rax]               ;
+        pmullw      mm6,        [rax]               ;
+
+        paddw       mm3,        [GLOBAL(rd)]                 ; xmm3 += round value
+        psraw       mm3,        VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       mm4,        [GLOBAL(rd)]                 ;
+        psraw       mm4,        VP8_FILTER_SHIFT        ;
+
+        movq        mm7,        mm3                 ;
+        packuswb    mm7,        mm4                 ;
+
+
+        pmullw      mm3,        [rax+16]            ;
+        pmullw      mm4,        [rax+16]            ;
+
+        paddw       mm3,        mm5                 ;
+        paddw       mm4,        mm6                 ;
+
+
+        paddw       mm3,        [GLOBAL(rd)]                 ; xmm3 += round value
+        psraw       mm3,        VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       mm4,        [GLOBAL(rd)]                 ;
+        psraw       mm4,        VP8_FILTER_SHIFT        ;
+
+        packuswb    mm3,        mm4
+
+        movq        [rdi],      mm3                 ; store the results in the destination
+
+%if ABI_IS_32BIT
+        add         rsi,        rdx                 ; next line
+        add         rdi,        dword ptr arg(5) ;dst_pitch                   ;
+%else
+        movsxd      r8,         dword ptr arg(5) ;dst_pitch
+        add         rsi,        rdx                 ; next line
+        add         rdi,        r8
+%endif
+        cmp         rdi,        rcx                 ;
+        jne         .next_row_8x4
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void bilinear_predict4x4_mmx
+;(
+;    unsigned char  *src_ptr,
+;    int   src_pixels_per_line,
+;    int  xoffset,
+;    int  yoffset,
+;    unsigned char *dst_ptr,
+;    int dst_pitch
+;)
+global sym(vp8_bilinear_predict4x4_mmx)
+sym(vp8_bilinear_predict4x4_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ;const short *HFilter = vp8_bilinear_filters_x86_8[xoffset];
+    ;const short *VFilter = vp8_bilinear_filters_x86_8[yoffset];
+
+        movsxd      rax,        dword ptr arg(2) ;xoffset
+        mov         rdi,        arg(4) ;dst_ptr           ;
+
+        lea         rcx,        [GLOBAL(sym(vp8_bilinear_filters_x86_8))]
+        shl         rax,        5
+
+        add         rax,        rcx ; HFilter
+        mov         rsi,        arg(0) ;src_ptr              ;
+
+        movsxd      rdx,        dword ptr arg(5) ;ldst_pitch
+        movq        mm1,        [rax]               ;
+
+        movq        mm2,        [rax+16]            ;
+        movsxd      rax,        dword ptr arg(3) ;yoffset
+
+        pxor        mm0,        mm0                 ;
+        shl         rax,        5
+
+        add         rax,        rcx
+        lea         rcx,        [rdi+rdx*4]          ;
+
+        movsxd      rdx,        dword ptr arg(1) ;src_pixels_per_line    ;
+
+        ; get the first horizontal line done       ;
+        movd        mm3,        [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+        punpcklbw   mm3,        mm0                 ; xx 00 01 02 03 04 05 06
+
+        pmullw      mm3,        mm1                 ;
+        movd        mm5,        [rsi+1]             ;
+
+        punpcklbw   mm5,        mm0                 ;
+        pmullw      mm5,        mm2                 ;
+
+        paddw       mm3,        mm5                 ;
+        paddw       mm3,        [GLOBAL(rd)]                 ; xmm3 += round value
+
+        psraw       mm3,        VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        movq        mm7,        mm3                 ;
+        packuswb    mm7,        mm0                 ;
+
+        add         rsi,        rdx                 ; next line
+.next_row_4x4:
+        movd        mm3,        [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+        punpcklbw   mm3,        mm0                 ; xx 00 01 02 03 04 05 06
+
+        pmullw      mm3,        mm1                 ;
+        movd        mm5,        [rsi+1]             ;
+
+        punpcklbw   mm5,        mm0                 ;
+        pmullw      mm5,        mm2                 ;
+
+        paddw       mm3,        mm5                 ;
+
+        movq        mm5,        mm7                 ;
+        punpcklbw   mm5,        mm0                 ;
+
+        pmullw      mm5,        [rax]               ;
+        paddw       mm3,        [GLOBAL(rd)]                 ; xmm3 += round value
+
+        psraw       mm3,        VP8_FILTER_SHIFT        ; xmm3 /= 128
+        movq        mm7,        mm3                 ;
+
+        packuswb    mm7,        mm0                 ;
+
+        pmullw      mm3,        [rax+16]            ;
+        paddw       mm3,        mm5                 ;
+
+
+        paddw       mm3,        [GLOBAL(rd)]                 ; xmm3 += round value
+        psraw       mm3,        VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        packuswb    mm3,        mm0
+        movd        [rdi],      mm3                 ; store the results in the destination
+
+%if ABI_IS_32BIT
+        add         rsi,        rdx                 ; next line
+        add         rdi,        dword ptr arg(5) ;dst_pitch                   ;
+%else
+        movsxd      r8,         dword ptr arg(5) ;dst_pitch                   ;
+        add         rsi,        rdx                 ; next line
+        add         rdi,        r8
+%endif
+
+        cmp         rdi,        rcx                 ;
+        jne         .next_row_4x4
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+
+SECTION_RODATA
+align 16
+rd:
+    times 4 dw 0x40
+
+align 16
+global HIDDEN_DATA(sym(vp8_six_tap_mmx))
+sym(vp8_six_tap_mmx):
+    times 8 dw 0
+    times 8 dw 0
+    times 8 dw 128
+    times 8 dw 0
+    times 8 dw 0
+    times 8 dw 0
+
+    times 8 dw 0
+    times 8 dw -6
+    times 8 dw 123
+    times 8 dw 12
+    times 8 dw -1
+    times 8 dw 0
+
+    times 8 dw 2
+    times 8 dw -11
+    times 8 dw 108
+    times 8 dw 36
+    times 8 dw -8
+    times 8 dw 1
+
+    times 8 dw 0
+    times 8 dw -9
+    times 8 dw 93
+    times 8 dw 50
+    times 8 dw -6
+    times 8 dw 0
+
+    times 8 dw 3
+    times 8 dw -16
+    times 8 dw 77
+    times 8 dw 77
+    times 8 dw -16
+    times 8 dw 3
+
+    times 8 dw 0
+    times 8 dw -6
+    times 8 dw 50
+    times 8 dw 93
+    times 8 dw -9
+    times 8 dw 0
+
+    times 8 dw 1
+    times 8 dw -8
+    times 8 dw 36
+    times 8 dw 108
+    times 8 dw -11
+    times 8 dw 2
+
+    times 8 dw 0
+    times 8 dw -1
+    times 8 dw 12
+    times 8 dw 123
+    times 8 dw -6
+    times 8 dw 0
+
+
diff --git a/vp8/common/x86/subpixel_sse2.asm b/vp8/common/x86/subpixel_sse2.asm
new file mode 100644 (file)
index 0000000..cb550af
--- /dev/null
@@ -0,0 +1,1372 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+extern sym(vp8_bilinear_filters_x86_8)
+
+%define BLOCK_HEIGHT_WIDTH 4
+%define VP8_FILTER_WEIGHT 128
+%define VP8_FILTER_SHIFT  7
+
+
+;/************************************************************************************
+; Notes: filter_block1d_h6 applies a 6 tap filter horizontally to the input pixels. The
+; input pixel array has output_height rows. This routine assumes that output_height is an
+; even number. This function handles 8 pixels in horizontal direction, calculating ONE
+; rows each iteration to take advantage of the 128 bits operations.
+;*************************************************************************************/
+;void vp8_filter_block1d8_h6_sse2
+;(
+;    unsigned char  *src_ptr,
+;    unsigned short *output_ptr,
+;    unsigned int    src_pixels_per_line,
+;    unsigned int    pixel_step,
+;    unsigned int    output_height,
+;    unsigned int    output_width,
+;    short           *vp8_filter
+;)
+global sym(vp8_filter_block1d8_h6_sse2)
+sym(vp8_filter_block1d8_h6_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rdx,        arg(6) ;vp8_filter
+        mov         rsi,        arg(0) ;src_ptr
+
+        mov         rdi,        arg(1) ;output_ptr
+
+        movsxd      rcx,        dword ptr arg(4) ;output_height
+        movsxd      rax,        dword ptr arg(2) ;src_pixels_per_line            ; Pitch for Source
+%if ABI_IS_32BIT=0
+        movsxd      r8,         dword ptr arg(5) ;output_width
+%endif
+        pxor        xmm0,       xmm0                        ; clear xmm0 for unpack
+
+.filter_block1d8_h6_rowloop:
+        movq        xmm3,       MMWORD PTR [rsi - 2]
+        movq        xmm1,       MMWORD PTR [rsi + 6]
+
+        prefetcht2  [rsi+rax-2]
+
+        pslldq      xmm1,       8
+        por         xmm1,       xmm3
+
+        movdqa      xmm4,       xmm1
+        movdqa      xmm5,       xmm1
+
+        movdqa      xmm6,       xmm1
+        movdqa      xmm7,       xmm1
+
+        punpcklbw   xmm3,       xmm0                        ; xx05 xx04 xx03 xx02 xx01 xx01 xx-1 xx-2
+        psrldq      xmm4,       1                           ; xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 -1
+
+        pmullw      xmm3,       XMMWORD PTR [rdx]           ; x[-2] * H[-2]; Tap 1
+        punpcklbw   xmm4,       xmm0                        ; xx06 xx05 xx04 xx03 xx02 xx01 xx00 xx-1
+
+        psrldq      xmm5,       2                           ; xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
+        pmullw      xmm4,       XMMWORD PTR [rdx+16]        ; x[-1] * H[-1]; Tap 2
+
+
+        punpcklbw   xmm5,       xmm0                        ; xx07 xx06 xx05 xx04 xx03 xx02 xx01 xx00
+        psrldq      xmm6,       3                           ; xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01
+
+        pmullw      xmm5,       [rdx+32]                    ; x[ 0] * H[ 0]; Tap 3
+
+        punpcklbw   xmm6,       xmm0                        ; xx08 xx07 xx06 xx05 xx04 xx03 xx02 xx01
+        psrldq      xmm7,       4                           ; xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02
+
+        pmullw      xmm6,       [rdx+48]                    ; x[ 1] * h[ 1] ; Tap 4
+
+        punpcklbw   xmm7,       xmm0                        ; xx09 xx08 xx07 xx06 xx05 xx04 xx03 xx02
+        psrldq      xmm1,       5                           ; xx xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03
+
+
+        pmullw      xmm7,       [rdx+64]                    ; x[ 2] * h[ 2] ; Tap 5
+
+        punpcklbw   xmm1,       xmm0                        ; xx0a xx09 xx08 xx07 xx06 xx05 xx04 xx03
+        pmullw      xmm1,       [rdx+80]                    ; x[ 3] * h[ 3] ; Tap 6
+
+
+        paddsw      xmm4,       xmm7
+        paddsw      xmm4,       xmm5
+
+        paddsw      xmm4,       xmm3
+        paddsw      xmm4,       xmm6
+
+        paddsw      xmm4,       xmm1
+        paddsw      xmm4,       [GLOBAL(rd)]
+
+        psraw       xmm4,       7
+
+        packuswb    xmm4,       xmm0
+        punpcklbw   xmm4,       xmm0
+
+        movdqa      XMMWORD Ptr [rdi],         xmm4
+        lea         rsi,        [rsi + rax]
+
+%if ABI_IS_32BIT
+        add         rdi,        DWORD Ptr arg(5) ;[output_width]
+%else
+        add         rdi,        r8
+%endif
+        dec         rcx
+
+        jnz         .filter_block1d8_h6_rowloop                ; next row
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_filter_block1d16_h6_sse2
+;(
+;    unsigned char  *src_ptr,
+;    unsigned short *output_ptr,
+;    unsigned int    src_pixels_per_line,
+;    unsigned int    pixel_step,
+;    unsigned int    output_height,
+;    unsigned int    output_width,
+;    short           *vp8_filter
+;)
+;/************************************************************************************
+; Notes: filter_block1d_h6 applies a 6 tap filter horizontally to the input pixels. The
+; input pixel array has output_height rows. This routine assumes that output_height is an
+; even number. This function handles 8 pixels in horizontal direction, calculating ONE
+; rows each iteration to take advantage of the 128 bits operations.
+;*************************************************************************************/
+global sym(vp8_filter_block1d16_h6_sse2)
+sym(vp8_filter_block1d16_h6_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rdx,        arg(6) ;vp8_filter
+        mov         rsi,        arg(0) ;src_ptr
+
+        mov         rdi,        arg(1) ;output_ptr
+
+        movsxd      rcx,        dword ptr arg(4) ;output_height
+        movsxd      rax,        dword ptr arg(2) ;src_pixels_per_line            ; Pitch for Source
+%if ABI_IS_32BIT=0
+        movsxd      r8,         dword ptr arg(5) ;output_width
+%endif
+
+        pxor        xmm0,       xmm0                        ; clear xmm0 for unpack
+
+.filter_block1d16_h6_sse2_rowloop:
+        movq        xmm3,       MMWORD PTR [rsi - 2]
+        movq        xmm1,       MMWORD PTR [rsi + 6]
+
+        movq        xmm2,       MMWORD PTR [rsi +14]
+        pslldq      xmm2,       8
+
+        por         xmm2,       xmm1
+        prefetcht2  [rsi+rax-2]
+
+        pslldq      xmm1,       8
+        por         xmm1,       xmm3
+
+        movdqa      xmm4,       xmm1
+        movdqa      xmm5,       xmm1
+
+        movdqa      xmm6,       xmm1
+        movdqa      xmm7,       xmm1
+
+        punpcklbw   xmm3,       xmm0                        ; xx05 xx04 xx03 xx02 xx01 xx01 xx-1 xx-2
+        psrldq      xmm4,       1                           ; xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 -1
+
+        pmullw      xmm3,       XMMWORD PTR [rdx]           ; x[-2] * H[-2]; Tap 1
+        punpcklbw   xmm4,       xmm0                        ; xx06 xx05 xx04 xx03 xx02 xx01 xx00 xx-1
+
+        psrldq      xmm5,       2                           ; xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
+        pmullw      xmm4,       XMMWORD PTR [rdx+16]        ; x[-1] * H[-1]; Tap 2
+
+
+        punpcklbw   xmm5,       xmm0                        ; xx07 xx06 xx05 xx04 xx03 xx02 xx01 xx00
+        psrldq      xmm6,       3                           ; xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01
+
+        pmullw      xmm5,       [rdx+32]                    ; x[ 0] * H[ 0]; Tap 3
+
+        punpcklbw   xmm6,       xmm0                        ; xx08 xx07 xx06 xx05 xx04 xx03 xx02 xx01
+        psrldq      xmm7,       4                           ; xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02
+
+        pmullw      xmm6,       [rdx+48]                    ; x[ 1] * h[ 1] ; Tap 4
+
+        punpcklbw   xmm7,       xmm0                        ; xx09 xx08 xx07 xx06 xx05 xx04 xx03 xx02
+        psrldq      xmm1,       5                           ; xx xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03
+
+
+        pmullw      xmm7,       [rdx+64]                    ; x[ 2] * h[ 2] ; Tap 5
+
+        punpcklbw   xmm1,       xmm0                        ; xx0a xx09 xx08 xx07 xx06 xx05 xx04 xx03
+        pmullw      xmm1,       [rdx+80]                    ; x[ 3] * h[ 3] ; Tap 6
+
+        paddsw      xmm4,       xmm7
+        paddsw      xmm4,       xmm5
+
+        paddsw      xmm4,       xmm3
+        paddsw      xmm4,       xmm6
+
+        paddsw      xmm4,       xmm1
+        paddsw      xmm4,       [GLOBAL(rd)]
+
+        psraw       xmm4,       7
+
+        packuswb    xmm4,       xmm0
+        punpcklbw   xmm4,       xmm0
+
+        movdqa      XMMWORD Ptr [rdi],         xmm4
+
+        movdqa      xmm3,       xmm2
+        movdqa      xmm4,       xmm2
+
+        movdqa      xmm5,       xmm2
+        movdqa      xmm6,       xmm2
+
+        movdqa      xmm7,       xmm2
+
+        punpcklbw   xmm3,       xmm0                        ; xx05 xx04 xx03 xx02 xx01 xx01 xx-1 xx-2
+        psrldq      xmm4,       1                           ; xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 -1
+
+        pmullw      xmm3,       XMMWORD PTR [rdx]           ; x[-2] * H[-2]; Tap 1
+        punpcklbw   xmm4,       xmm0                        ; xx06 xx05 xx04 xx03 xx02 xx01 xx00 xx-1
+
+        psrldq      xmm5,       2                           ; xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
+        pmullw      xmm4,       XMMWORD PTR [rdx+16]        ; x[-1] * H[-1]; Tap 2
+
+
+        punpcklbw   xmm5,       xmm0                        ; xx07 xx06 xx05 xx04 xx03 xx02 xx01 xx00
+        psrldq      xmm6,       3                           ; xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01
+
+        pmullw      xmm5,       [rdx+32]                    ; x[ 0] * H[ 0]; Tap 3
+
+        punpcklbw   xmm6,       xmm0                        ; xx08 xx07 xx06 xx05 xx04 xx03 xx02 xx01
+        psrldq      xmm7,       4                           ; xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02
+
+        pmullw      xmm6,       [rdx+48]                    ; x[ 1] * h[ 1] ; Tap 4
+
+        punpcklbw   xmm7,       xmm0                        ; xx09 xx08 xx07 xx06 xx05 xx04 xx03 xx02
+        psrldq      xmm2,       5                           ; xx xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03
+
+        pmullw      xmm7,       [rdx+64]                    ; x[ 2] * h[ 2] ; Tap 5
+
+        punpcklbw   xmm2,       xmm0                        ; xx0a xx09 xx08 xx07 xx06 xx05 xx04 xx03
+        pmullw      xmm2,       [rdx+80]                    ; x[ 3] * h[ 3] ; Tap 6
+
+
+        paddsw      xmm4,       xmm7
+        paddsw      xmm4,       xmm5
+
+        paddsw      xmm4,       xmm3
+        paddsw      xmm4,       xmm6
+
+        paddsw      xmm4,       xmm2
+        paddsw      xmm4,       [GLOBAL(rd)]
+
+        psraw       xmm4,       7
+
+        packuswb    xmm4,       xmm0
+        punpcklbw   xmm4,       xmm0
+
+        movdqa      XMMWORD Ptr [rdi+16],      xmm4
+
+        lea         rsi,        [rsi + rax]
+%if ABI_IS_32BIT
+        add         rdi,        DWORD Ptr arg(5) ;[output_width]
+%else
+        add         rdi,        r8
+%endif
+
+        dec         rcx
+        jnz         .filter_block1d16_h6_sse2_rowloop                ; next row
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_filter_block1d8_v6_sse2
+;(
+;    short *src_ptr,
+;    unsigned char *output_ptr,
+;    int dst_ptich,
+;    unsigned int pixels_per_line,
+;    unsigned int pixel_step,
+;    unsigned int output_height,
+;    unsigned int output_width,
+;    short * vp8_filter
+;)
+;/************************************************************************************
+; Notes: filter_block1d8_v6 applies a 6 tap filter vertically to the input pixels. The
+; input pixel array has output_height rows.
+;*************************************************************************************/
+global sym(vp8_filter_block1d8_v6_sse2)
+sym(vp8_filter_block1d8_v6_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 8
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rax,        arg(7) ;vp8_filter
+        movsxd      rdx,        dword ptr arg(3) ;pixels_per_line
+
+        mov         rdi,        arg(1) ;output_ptr
+        mov         rsi,        arg(0) ;src_ptr
+
+        sub         rsi,        rdx
+        sub         rsi,        rdx
+
+        movsxd      rcx,        DWORD PTR arg(5) ;[output_height]
+        pxor        xmm0,       xmm0                        ; clear xmm0
+
+        movdqa      xmm7,       XMMWORD PTR [GLOBAL(rd)]
+%if ABI_IS_32BIT=0
+        movsxd      r8,         dword ptr arg(2) ; dst_ptich
+%endif
+
+.vp8_filter_block1d8_v6_sse2_loop:
+        movdqa      xmm1,       XMMWORD PTR [rsi]
+        pmullw      xmm1,       [rax]
+
+        movdqa      xmm2,       XMMWORD PTR [rsi + rdx]
+        pmullw      xmm2,       [rax + 16]
+
+        movdqa      xmm3,       XMMWORD PTR [rsi + rdx * 2]
+        pmullw      xmm3,       [rax + 32]
+
+        movdqa      xmm5,       XMMWORD PTR [rsi + rdx * 4]
+        pmullw      xmm5,       [rax + 64]
+
+        add         rsi,        rdx
+        movdqa      xmm4,       XMMWORD PTR [rsi + rdx * 2]
+
+        pmullw      xmm4,       [rax + 48]
+        movdqa      xmm6,       XMMWORD PTR [rsi + rdx * 4]
+
+        pmullw      xmm6,       [rax + 80]
+
+        paddsw      xmm2,       xmm5
+        paddsw      xmm2,       xmm3
+
+        paddsw      xmm2,       xmm1
+        paddsw      xmm2,       xmm4
+
+        paddsw      xmm2,       xmm6
+        paddsw      xmm2,       xmm7
+
+        psraw       xmm2,       7
+        packuswb    xmm2,       xmm0              ; pack and saturate
+
+        movq        QWORD PTR [rdi], xmm2         ; store the results in the destination
+%if ABI_IS_32BIT
+        add         rdi,        DWORD PTR arg(2) ;[dst_ptich]
+%else
+        add         rdi,        r8
+%endif
+        dec         rcx         ; decrement count
+        jnz         .vp8_filter_block1d8_v6_sse2_loop               ; next row
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_filter_block1d16_v6_sse2
+;(
+;    unsigned short *src_ptr,
+;    unsigned char *output_ptr,
+;    int dst_ptich,
+;    unsigned int pixels_per_line,
+;    unsigned int pixel_step,
+;    unsigned int output_height,
+;    unsigned int output_width,
+;    const short    *vp8_filter
+;)
+;/************************************************************************************
+; Notes: filter_block1d16_v6 applies a 6 tap filter vertically to the input pixels. The
+; input pixel array has output_height rows.
+;*************************************************************************************/
+global sym(vp8_filter_block1d16_v6_sse2)
+sym(vp8_filter_block1d16_v6_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 8
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rax,        arg(7) ;vp8_filter
+        movsxd      rdx,        dword ptr arg(3) ;pixels_per_line
+
+        mov         rdi,        arg(1) ;output_ptr
+        mov         rsi,        arg(0) ;src_ptr
+
+        sub         rsi,        rdx
+        sub         rsi,        rdx
+
+        movsxd      rcx,        DWORD PTR arg(5) ;[output_height]
+%if ABI_IS_32BIT=0
+        movsxd      r8,         dword ptr arg(2) ; dst_ptich
+%endif
+
+.vp8_filter_block1d16_v6_sse2_loop:
+; The order for adding 6-tap is 2 5 3 1 4 6. Read in data in that order.
+        movdqa      xmm1,       XMMWORD PTR [rsi + rdx]       ; line 2
+        movdqa      xmm2,       XMMWORD PTR [rsi + rdx + 16]
+        pmullw      xmm1,       [rax + 16]
+        pmullw      xmm2,       [rax + 16]
+
+        movdqa      xmm3,       XMMWORD PTR [rsi + rdx * 4]       ; line 5
+        movdqa      xmm4,       XMMWORD PTR [rsi + rdx * 4 + 16]
+        pmullw      xmm3,       [rax + 64]
+        pmullw      xmm4,       [rax + 64]
+
+        movdqa      xmm5,       XMMWORD PTR [rsi + rdx * 2]       ; line 3
+        movdqa      xmm6,       XMMWORD PTR [rsi + rdx * 2 + 16]
+        pmullw      xmm5,       [rax + 32]
+        pmullw      xmm6,       [rax + 32]
+
+        movdqa      xmm7,       XMMWORD PTR [rsi]       ; line 1
+        movdqa      xmm0,       XMMWORD PTR [rsi + 16]
+        pmullw      xmm7,       [rax]
+        pmullw      xmm0,       [rax]
+
+        paddsw      xmm1,       xmm3
+        paddsw      xmm2,       xmm4
+        paddsw      xmm1,       xmm5
+        paddsw      xmm2,       xmm6
+        paddsw      xmm1,       xmm7
+        paddsw      xmm2,       xmm0
+
+        add         rsi,        rdx
+
+        movdqa      xmm3,       XMMWORD PTR [rsi + rdx * 2]       ; line 4
+        movdqa      xmm4,       XMMWORD PTR [rsi + rdx * 2 + 16]
+        pmullw      xmm3,       [rax + 48]
+        pmullw      xmm4,       [rax + 48]
+
+        movdqa      xmm5,       XMMWORD PTR [rsi + rdx * 4]       ; line 6
+        movdqa      xmm6,       XMMWORD PTR [rsi + rdx * 4 + 16]
+        pmullw      xmm5,       [rax + 80]
+        pmullw      xmm6,       [rax + 80]
+
+        movdqa      xmm7,       XMMWORD PTR [GLOBAL(rd)]
+        pxor        xmm0,       xmm0                        ; clear xmm0
+
+        paddsw      xmm1,       xmm3
+        paddsw      xmm2,       xmm4
+        paddsw      xmm1,       xmm5
+        paddsw      xmm2,       xmm6
+
+        paddsw      xmm1,       xmm7
+        paddsw      xmm2,       xmm7
+
+        psraw       xmm1,       7
+        psraw       xmm2,       7
+
+        packuswb    xmm1,       xmm2              ; pack and saturate
+        movdqa      XMMWORD PTR [rdi], xmm1       ; store the results in the destination
+%if ABI_IS_32BIT
+        add         rdi,        DWORD PTR arg(2) ;[dst_ptich]
+%else
+        add         rdi,        r8
+%endif
+        dec         rcx         ; decrement count
+        jnz         .vp8_filter_block1d16_v6_sse2_loop              ; next row
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_filter_block1d8_h6_only_sse2
+;(
+;    unsigned char  *src_ptr,
+;    unsigned int    src_pixels_per_line,
+;    unsigned char  *output_ptr,
+;    int dst_ptich,
+;    unsigned int    output_height,
+;    const short    *vp8_filter
+;)
+; First-pass filter only when yoffset==0
+global sym(vp8_filter_block1d8_h6_only_sse2)
+sym(vp8_filter_block1d8_h6_only_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rdx,        arg(5) ;vp8_filter
+        mov         rsi,        arg(0) ;src_ptr
+
+        mov         rdi,        arg(2) ;output_ptr
+
+        movsxd      rcx,        dword ptr arg(4) ;output_height
+        movsxd      rax,        dword ptr arg(1) ;src_pixels_per_line            ; Pitch for Source
+%if ABI_IS_32BIT=0
+        movsxd      r8,         dword ptr arg(3) ;dst_ptich
+%endif
+        pxor        xmm0,       xmm0                        ; clear xmm0 for unpack
+
+.filter_block1d8_h6_only_rowloop:
+        movq        xmm3,       MMWORD PTR [rsi - 2]
+        movq        xmm1,       MMWORD PTR [rsi + 6]
+
+        prefetcht2  [rsi+rax-2]
+
+        pslldq      xmm1,       8
+        por         xmm1,       xmm3
+
+        movdqa      xmm4,       xmm1
+        movdqa      xmm5,       xmm1
+
+        movdqa      xmm6,       xmm1
+        movdqa      xmm7,       xmm1
+
+        punpcklbw   xmm3,       xmm0                        ; xx05 xx04 xx03 xx02 xx01 xx01 xx-1 xx-2
+        psrldq      xmm4,       1                           ; xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 -1
+
+        pmullw      xmm3,       XMMWORD PTR [rdx]           ; x[-2] * H[-2]; Tap 1
+        punpcklbw   xmm4,       xmm0                        ; xx06 xx05 xx04 xx03 xx02 xx01 xx00 xx-1
+
+        psrldq      xmm5,       2                           ; xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
+        pmullw      xmm4,       XMMWORD PTR [rdx+16]        ; x[-1] * H[-1]; Tap 2
+
+
+        punpcklbw   xmm5,       xmm0                        ; xx07 xx06 xx05 xx04 xx03 xx02 xx01 xx00
+        psrldq      xmm6,       3                           ; xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01
+
+        pmullw      xmm5,       [rdx+32]                    ; x[ 0] * H[ 0]; Tap 3
+
+        punpcklbw   xmm6,       xmm0                        ; xx08 xx07 xx06 xx05 xx04 xx03 xx02 xx01
+        psrldq      xmm7,       4                           ; xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02
+
+        pmullw      xmm6,       [rdx+48]                    ; x[ 1] * h[ 1] ; Tap 4
+
+        punpcklbw   xmm7,       xmm0                        ; xx09 xx08 xx07 xx06 xx05 xx04 xx03 xx02
+        psrldq      xmm1,       5                           ; xx xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03
+
+
+        pmullw      xmm7,       [rdx+64]                    ; x[ 2] * h[ 2] ; Tap 5
+
+        punpcklbw   xmm1,       xmm0                        ; xx0a xx09 xx08 xx07 xx06 xx05 xx04 xx03
+        pmullw      xmm1,       [rdx+80]                    ; x[ 3] * h[ 3] ; Tap 6
+
+
+        paddsw      xmm4,       xmm7
+        paddsw      xmm4,       xmm5
+
+        paddsw      xmm4,       xmm3
+        paddsw      xmm4,       xmm6
+
+        paddsw      xmm4,       xmm1
+        paddsw      xmm4,       [GLOBAL(rd)]
+
+        psraw       xmm4,       7
+
+        packuswb    xmm4,       xmm0
+
+        movq        QWORD PTR [rdi],   xmm4       ; store the results in the destination
+        lea         rsi,        [rsi + rax]
+
+%if ABI_IS_32BIT
+        add         rdi,        DWORD Ptr arg(3) ;dst_ptich
+%else
+        add         rdi,        r8
+%endif
+        dec         rcx
+
+        jnz         .filter_block1d8_h6_only_rowloop               ; next row
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_filter_block1d16_h6_only_sse2
+;(
+;    unsigned char  *src_ptr,
+;    unsigned int    src_pixels_per_line,
+;    unsigned char  *output_ptr,
+;    int dst_ptich,
+;    unsigned int    output_height,
+;    const short    *vp8_filter
+;)
+; First-pass filter only when yoffset==0
+global sym(vp8_filter_block1d16_h6_only_sse2)
+sym(vp8_filter_block1d16_h6_only_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rdx,        arg(5) ;vp8_filter
+        mov         rsi,        arg(0) ;src_ptr
+
+        mov         rdi,        arg(2) ;output_ptr
+
+        movsxd      rcx,        dword ptr arg(4) ;output_height
+        movsxd      rax,        dword ptr arg(1) ;src_pixels_per_line            ; Pitch for Source
+%if ABI_IS_32BIT=0
+        movsxd      r8,         dword ptr arg(3) ;dst_ptich
+%endif
+
+        pxor        xmm0,       xmm0                        ; clear xmm0 for unpack
+
+.filter_block1d16_h6_only_sse2_rowloop:
+        movq        xmm3,       MMWORD PTR [rsi - 2]
+        movq        xmm1,       MMWORD PTR [rsi + 6]
+
+        movq        xmm2,       MMWORD PTR [rsi +14]
+        pslldq      xmm2,       8
+
+        por         xmm2,       xmm1
+        prefetcht2  [rsi+rax-2]
+
+        pslldq      xmm1,       8
+        por         xmm1,       xmm3
+
+        movdqa      xmm4,       xmm1
+        movdqa      xmm5,       xmm1
+
+        movdqa      xmm6,       xmm1
+        movdqa      xmm7,       xmm1
+
+        punpcklbw   xmm3,       xmm0                        ; xx05 xx04 xx03 xx02 xx01 xx01 xx-1 xx-2
+        psrldq      xmm4,       1                           ; xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 -1
+
+        pmullw      xmm3,       XMMWORD PTR [rdx]           ; x[-2] * H[-2]; Tap 1
+        punpcklbw   xmm4,       xmm0                        ; xx06 xx05 xx04 xx03 xx02 xx01 xx00 xx-1
+
+        psrldq      xmm5,       2                           ; xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
+        pmullw      xmm4,       XMMWORD PTR [rdx+16]        ; x[-1] * H[-1]; Tap 2
+
+        punpcklbw   xmm5,       xmm0                        ; xx07 xx06 xx05 xx04 xx03 xx02 xx01 xx00
+        psrldq      xmm6,       3                           ; xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01
+
+        pmullw      xmm5,       [rdx+32]                    ; x[ 0] * H[ 0]; Tap 3
+
+        punpcklbw   xmm6,       xmm0                        ; xx08 xx07 xx06 xx05 xx04 xx03 xx02 xx01
+        psrldq      xmm7,       4                           ; xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02
+
+        pmullw      xmm6,       [rdx+48]                    ; x[ 1] * h[ 1] ; Tap 4
+
+        punpcklbw   xmm7,       xmm0                        ; xx09 xx08 xx07 xx06 xx05 xx04 xx03 xx02
+        psrldq      xmm1,       5                           ; xx xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03
+
+        pmullw      xmm7,       [rdx+64]                    ; x[ 2] * h[ 2] ; Tap 5
+
+        punpcklbw   xmm1,       xmm0                        ; xx0a xx09 xx08 xx07 xx06 xx05 xx04 xx03
+        pmullw      xmm1,       [rdx+80]                    ; x[ 3] * h[ 3] ; Tap 6
+
+        paddsw      xmm4,       xmm7
+        paddsw      xmm4,       xmm5
+
+        paddsw      xmm4,       xmm3
+        paddsw      xmm4,       xmm6
+
+        paddsw      xmm4,       xmm1
+        paddsw      xmm4,       [GLOBAL(rd)]
+
+        psraw       xmm4,       7
+
+        packuswb    xmm4,       xmm0                        ; lower 8 bytes
+
+        movq        QWORD Ptr [rdi],         xmm4           ; store the results in the destination
+
+        movdqa      xmm3,       xmm2
+        movdqa      xmm4,       xmm2
+
+        movdqa      xmm5,       xmm2
+        movdqa      xmm6,       xmm2
+
+        movdqa      xmm7,       xmm2
+
+        punpcklbw   xmm3,       xmm0                        ; xx05 xx04 xx03 xx02 xx01 xx01 xx-1 xx-2
+        psrldq      xmm4,       1                           ; xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 -1
+
+        pmullw      xmm3,       XMMWORD PTR [rdx]           ; x[-2] * H[-2]; Tap 1
+        punpcklbw   xmm4,       xmm0                        ; xx06 xx05 xx04 xx03 xx02 xx01 xx00 xx-1
+
+        psrldq      xmm5,       2                           ; xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
+        pmullw      xmm4,       XMMWORD PTR [rdx+16]        ; x[-1] * H[-1]; Tap 2
+
+        punpcklbw   xmm5,       xmm0                        ; xx07 xx06 xx05 xx04 xx03 xx02 xx01 xx00
+        psrldq      xmm6,       3                           ; xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01
+
+        pmullw      xmm5,       [rdx+32]                    ; x[ 0] * H[ 0]; Tap 3
+
+        punpcklbw   xmm6,       xmm0                        ; xx08 xx07 xx06 xx05 xx04 xx03 xx02 xx01
+        psrldq      xmm7,       4                           ; xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02
+
+        pmullw      xmm6,       [rdx+48]                    ; x[ 1] * h[ 1] ; Tap 4
+
+        punpcklbw   xmm7,       xmm0                        ; xx09 xx08 xx07 xx06 xx05 xx04 xx03 xx02
+        psrldq      xmm2,       5                           ; xx xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03
+
+        pmullw      xmm7,       [rdx+64]                    ; x[ 2] * h[ 2] ; Tap 5
+
+        punpcklbw   xmm2,       xmm0                        ; xx0a xx09 xx08 xx07 xx06 xx05 xx04 xx03
+        pmullw      xmm2,       [rdx+80]                    ; x[ 3] * h[ 3] ; Tap 6
+
+        paddsw      xmm4,       xmm7
+        paddsw      xmm4,       xmm5
+
+        paddsw      xmm4,       xmm3
+        paddsw      xmm4,       xmm6
+
+        paddsw      xmm4,       xmm2
+        paddsw      xmm4,       [GLOBAL(rd)]
+
+        psraw       xmm4,       7
+
+        packuswb    xmm4,       xmm0                        ; higher 8 bytes
+
+        movq        QWORD Ptr [rdi+8],      xmm4            ; store the results in the destination
+
+        lea         rsi,        [rsi + rax]
+%if ABI_IS_32BIT
+        add         rdi,        DWORD Ptr arg(3) ;dst_ptich
+%else
+        add         rdi,        r8
+%endif
+
+        dec         rcx
+        jnz         .filter_block1d16_h6_only_sse2_rowloop               ; next row
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_filter_block1d8_v6_only_sse2
+;(
+;    unsigned char *src_ptr,
+;    unsigned int    src_pixels_per_line,
+;    unsigned char *output_ptr,
+;    int dst_ptich,
+;    unsigned int output_height,
+;    const short    *vp8_filter
+;)
+; Second-pass filter only when xoffset==0
+global sym(vp8_filter_block1d8_v6_only_sse2)
+sym(vp8_filter_block1d8_v6_only_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rsi,        arg(0) ;src_ptr
+        mov         rdi,        arg(2) ;output_ptr
+
+        movsxd      rcx,        dword ptr arg(4) ;output_height
+        movsxd      rdx,        dword ptr arg(1) ;src_pixels_per_line
+
+        mov         rax,        arg(5) ;vp8_filter
+
+        pxor        xmm0,       xmm0                        ; clear xmm0
+
+        movdqa      xmm7,       XMMWORD PTR [GLOBAL(rd)]
+%if ABI_IS_32BIT=0
+        movsxd      r8,         dword ptr arg(3) ; dst_ptich
+%endif
+
+.vp8_filter_block1d8_v6_only_sse2_loop:
+        movq        xmm1,       MMWORD PTR [rsi]
+        movq        xmm2,       MMWORD PTR [rsi + rdx]
+        movq        xmm3,       MMWORD PTR [rsi + rdx * 2]
+        movq        xmm5,       MMWORD PTR [rsi + rdx * 4]
+        add         rsi,        rdx
+        movq        xmm4,       MMWORD PTR [rsi + rdx * 2]
+        movq        xmm6,       MMWORD PTR [rsi + rdx * 4]
+
+        punpcklbw   xmm1,       xmm0
+        pmullw      xmm1,       [rax]
+
+        punpcklbw   xmm2,       xmm0
+        pmullw      xmm2,       [rax + 16]
+
+        punpcklbw   xmm3,       xmm0
+        pmullw      xmm3,       [rax + 32]
+
+        punpcklbw   xmm5,       xmm0
+        pmullw      xmm5,       [rax + 64]
+
+        punpcklbw   xmm4,       xmm0
+        pmullw      xmm4,       [rax + 48]
+
+        punpcklbw   xmm6,       xmm0
+        pmullw      xmm6,       [rax + 80]
+
+        paddsw      xmm2,       xmm5
+        paddsw      xmm2,       xmm3
+
+        paddsw      xmm2,       xmm1
+        paddsw      xmm2,       xmm4
+
+        paddsw      xmm2,       xmm6
+        paddsw      xmm2,       xmm7
+
+        psraw       xmm2,       7
+        packuswb    xmm2,       xmm0              ; pack and saturate
+
+        movq        QWORD PTR [rdi], xmm2         ; store the results in the destination
+%if ABI_IS_32BIT
+        add         rdi,        DWORD PTR arg(3) ;[dst_ptich]
+%else
+        add         rdi,        r8
+%endif
+        dec         rcx         ; decrement count
+        jnz         .vp8_filter_block1d8_v6_only_sse2_loop              ; next row
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_unpack_block1d16_h6_sse2
+;(
+;    unsigned char  *src_ptr,
+;    unsigned short *output_ptr,
+;    unsigned int    src_pixels_per_line,
+;    unsigned int    output_height,
+;    unsigned int    output_width
+;)
+global sym(vp8_unpack_block1d16_h6_sse2)
+sym(vp8_unpack_block1d16_h6_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rsi,        arg(0) ;src_ptr
+        mov         rdi,        arg(1) ;output_ptr
+
+        movsxd      rcx,        dword ptr arg(3) ;output_height
+        movsxd      rax,        dword ptr arg(2) ;src_pixels_per_line            ; Pitch for Source
+
+        pxor        xmm0,       xmm0                        ; clear xmm0 for unpack
+%if ABI_IS_32BIT=0
+        movsxd      r8,         dword ptr arg(4) ;output_width            ; Pitch for Source
+%endif
+
+.unpack_block1d16_h6_sse2_rowloop:
+        movq        xmm1,       MMWORD PTR [rsi]            ; 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 -1 -2
+        movq        xmm3,       MMWORD PTR [rsi+8]          ; make copy of xmm1
+
+        punpcklbw   xmm3,       xmm0                        ; xx05 xx04 xx03 xx02 xx01 xx01 xx-1 xx-2
+        punpcklbw   xmm1,       xmm0
+
+        movdqa      XMMWORD Ptr [rdi],         xmm1
+        movdqa      XMMWORD Ptr [rdi + 16],    xmm3
+
+        lea         rsi,        [rsi + rax]
+%if ABI_IS_32BIT
+        add         rdi,        DWORD Ptr arg(4) ;[output_width]
+%else
+        add         rdi,        r8
+%endif
+        dec         rcx
+        jnz         .unpack_block1d16_h6_sse2_rowloop               ; next row
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_bilinear_predict16x16_sse2
+;(
+;    unsigned char  *src_ptr,
+;    int   src_pixels_per_line,
+;    int  xoffset,
+;    int  yoffset,
+;    unsigned char *dst_ptr,
+;    int dst_pitch
+;)
+extern sym(vp8_bilinear_filters_x86_8)
+global sym(vp8_bilinear_predict16x16_sse2)
+sym(vp8_bilinear_predict16x16_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ;const short *HFilter = vp8_bilinear_filters_x86_8[xoffset]
+    ;const short *VFilter = vp8_bilinear_filters_x86_8[yoffset]
+
+        lea         rcx,        [GLOBAL(sym(vp8_bilinear_filters_x86_8))]
+        movsxd      rax,        dword ptr arg(2) ;xoffset
+
+        cmp         rax,        0      ;skip first_pass filter if xoffset=0
+        je          .b16x16_sp_only
+
+        shl         rax,        5
+        add         rax,        rcx    ;HFilter
+
+        mov         rdi,        arg(4) ;dst_ptr
+        mov         rsi,        arg(0) ;src_ptr
+        movsxd      rdx,        dword ptr arg(5) ;dst_pitch
+
+        movdqa      xmm1,       [rax]
+        movdqa      xmm2,       [rax+16]
+
+        movsxd      rax,        dword ptr arg(3) ;yoffset
+
+        cmp         rax,        0      ;skip second_pass filter if yoffset=0
+        je          .b16x16_fp_only
+
+        shl         rax,        5
+        add         rax,        rcx    ;VFilter
+
+        lea         rcx,        [rdi+rdx*8]
+        lea         rcx,        [rcx+rdx*8]
+        movsxd      rdx,        dword ptr arg(1) ;src_pixels_per_line
+
+        pxor        xmm0,       xmm0
+
+%if ABI_IS_32BIT=0
+        movsxd      r8,         dword ptr arg(5) ;dst_pitch
+%endif
+        ; get the first horizontal line done
+        movdqu      xmm3,       [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+        movdqa      xmm4,       xmm3                 ; make a copy of current line
+
+        punpcklbw   xmm3,       xmm0                 ; xx 00 01 02 03 04 05 06
+        punpckhbw   xmm4,       xmm0
+
+        pmullw      xmm3,       xmm1
+        pmullw      xmm4,       xmm1
+
+        movdqu      xmm5,       [rsi+1]
+        movdqa      xmm6,       xmm5
+
+        punpcklbw   xmm5,       xmm0
+        punpckhbw   xmm6,       xmm0
+
+        pmullw      xmm5,       xmm2
+        pmullw      xmm6,       xmm2
+
+        paddw       xmm3,       xmm5
+        paddw       xmm4,       xmm6
+
+        paddw       xmm3,       [GLOBAL(rd)]        ; xmm3 += round value
+        psraw       xmm3,       VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       xmm4,       [GLOBAL(rd)]
+        psraw       xmm4,       VP8_FILTER_SHIFT
+
+        movdqa      xmm7,       xmm3
+        packuswb    xmm7,       xmm4
+
+        add         rsi,        rdx                 ; next line
+.next_row:
+        movdqu      xmm3,       [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+        movdqa      xmm4,       xmm3                 ; make a copy of current line
+
+        punpcklbw   xmm3,       xmm0                 ; xx 00 01 02 03 04 05 06
+        punpckhbw   xmm4,       xmm0
+
+        pmullw      xmm3,       xmm1
+        pmullw      xmm4,       xmm1
+
+        movdqu      xmm5,       [rsi+1]
+        movdqa      xmm6,       xmm5
+
+        punpcklbw   xmm5,       xmm0
+        punpckhbw   xmm6,       xmm0
+
+        pmullw      xmm5,       xmm2
+        pmullw      xmm6,       xmm2
+
+        paddw       xmm3,       xmm5
+        paddw       xmm4,       xmm6
+
+        movdqa      xmm5,       xmm7
+        movdqa      xmm6,       xmm7
+
+        punpcklbw   xmm5,       xmm0
+        punpckhbw   xmm6,       xmm0
+
+        pmullw      xmm5,       [rax]
+        pmullw      xmm6,       [rax]
+
+        paddw       xmm3,       [GLOBAL(rd)]        ; xmm3 += round value
+        psraw       xmm3,       VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       xmm4,       [GLOBAL(rd)]
+        psraw       xmm4,       VP8_FILTER_SHIFT
+
+        movdqa      xmm7,       xmm3
+        packuswb    xmm7,       xmm4
+
+        pmullw      xmm3,       [rax+16]
+        pmullw      xmm4,       [rax+16]
+
+        paddw       xmm3,       xmm5
+        paddw       xmm4,       xmm6
+
+        paddw       xmm3,       [GLOBAL(rd)]        ; xmm3 += round value
+        psraw       xmm3,       VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       xmm4,       [GLOBAL(rd)]
+        psraw       xmm4,       VP8_FILTER_SHIFT
+
+        packuswb    xmm3,       xmm4
+        movdqa      [rdi],      xmm3                 ; store the results in the destination
+
+        add         rsi,        rdx                 ; next line
+%if ABI_IS_32BIT
+        add         rdi,        DWORD PTR arg(5) ;dst_pitch
+%else
+        add         rdi,        r8
+%endif
+
+        cmp         rdi,        rcx
+        jne         .next_row
+
+        jmp         .done
+
+.b16x16_sp_only:
+        movsxd      rax,        dword ptr arg(3) ;yoffset
+        shl         rax,        5
+        add         rax,        rcx    ;VFilter
+
+        mov         rdi,        arg(4) ;dst_ptr
+        mov         rsi,        arg(0) ;src_ptr
+        movsxd      rdx,        dword ptr arg(5) ;dst_pitch
+
+        movdqa      xmm1,       [rax]
+        movdqa      xmm2,       [rax+16]
+
+        lea         rcx,        [rdi+rdx*8]
+        lea         rcx,        [rcx+rdx*8]
+        movsxd      rax,        dword ptr arg(1) ;src_pixels_per_line
+
+        pxor        xmm0,       xmm0
+
+        ; get the first horizontal line done
+        movdqu      xmm7,       [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+
+        add         rsi,        rax                 ; next line
+.next_row_spo:
+        movdqu      xmm3,       [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+
+        movdqa      xmm5,       xmm7
+        movdqa      xmm6,       xmm7
+
+        movdqa      xmm4,       xmm3                 ; make a copy of current line
+        movdqa      xmm7,       xmm3
+
+        punpcklbw   xmm5,       xmm0
+        punpckhbw   xmm6,       xmm0
+        punpcklbw   xmm3,       xmm0                 ; xx 00 01 02 03 04 05 06
+        punpckhbw   xmm4,       xmm0
+
+        pmullw      xmm5,       xmm1
+        pmullw      xmm6,       xmm1
+        pmullw      xmm3,       xmm2
+        pmullw      xmm4,       xmm2
+
+        paddw       xmm3,       xmm5
+        paddw       xmm4,       xmm6
+
+        paddw       xmm3,       [GLOBAL(rd)]        ; xmm3 += round value
+        psraw       xmm3,       VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       xmm4,       [GLOBAL(rd)]
+        psraw       xmm4,       VP8_FILTER_SHIFT
+
+        packuswb    xmm3,       xmm4
+        movdqa      [rdi],      xmm3                 ; store the results in the destination
+
+        add         rsi,        rax                 ; next line
+        add         rdi,        rdx                 ;dst_pitch
+        cmp         rdi,        rcx
+        jne         .next_row_spo
+
+        jmp         .done
+
+.b16x16_fp_only:
+        lea         rcx,        [rdi+rdx*8]
+        lea         rcx,        [rcx+rdx*8]
+        movsxd      rax,        dword ptr arg(1) ;src_pixels_per_line
+        pxor        xmm0,       xmm0
+
+.next_row_fpo:
+        movdqu      xmm3,       [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+        movdqa      xmm4,       xmm3                 ; make a copy of current line
+
+        punpcklbw   xmm3,       xmm0                 ; xx 00 01 02 03 04 05 06
+        punpckhbw   xmm4,       xmm0
+
+        pmullw      xmm3,       xmm1
+        pmullw      xmm4,       xmm1
+
+        movdqu      xmm5,       [rsi+1]
+        movdqa      xmm6,       xmm5
+
+        punpcklbw   xmm5,       xmm0
+        punpckhbw   xmm6,       xmm0
+
+        pmullw      xmm5,       xmm2
+        pmullw      xmm6,       xmm2
+
+        paddw       xmm3,       xmm5
+        paddw       xmm4,       xmm6
+
+        paddw       xmm3,       [GLOBAL(rd)]        ; xmm3 += round value
+        psraw       xmm3,       VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       xmm4,       [GLOBAL(rd)]
+        psraw       xmm4,       VP8_FILTER_SHIFT
+
+        packuswb    xmm3,       xmm4
+        movdqa      [rdi],      xmm3                 ; store the results in the destination
+
+        add         rsi,        rax                 ; next line
+        add         rdi,        rdx                 ; dst_pitch
+        cmp         rdi,        rcx
+        jne         .next_row_fpo
+
+.done:
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_bilinear_predict8x8_sse2
+;(
+;    unsigned char  *src_ptr,
+;    int   src_pixels_per_line,
+;    int  xoffset,
+;    int  yoffset,
+;    unsigned char *dst_ptr,
+;    int dst_pitch
+;)
+global sym(vp8_bilinear_predict8x8_sse2)
+sym(vp8_bilinear_predict8x8_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub         rsp, 144                         ; reserve 144 bytes
+
+    ;const short *HFilter = vp8_bilinear_filters_x86_8[xoffset]
+    ;const short *VFilter = vp8_bilinear_filters_x86_8[yoffset]
+        lea         rcx,        [GLOBAL(sym(vp8_bilinear_filters_x86_8))]
+
+        mov         rsi,        arg(0) ;src_ptr
+        movsxd      rdx,        dword ptr arg(1) ;src_pixels_per_line
+
+    ;Read 9-line unaligned data in and put them on stack. This gives a big
+    ;performance boost.
+        movdqu      xmm0,       [rsi]
+        lea         rax,        [rdx + rdx*2]
+        movdqu      xmm1,       [rsi+rdx]
+        movdqu      xmm2,       [rsi+rdx*2]
+        add         rsi,        rax
+        movdqu      xmm3,       [rsi]
+        movdqu      xmm4,       [rsi+rdx]
+        movdqu      xmm5,       [rsi+rdx*2]
+        add         rsi,        rax
+        movdqu      xmm6,       [rsi]
+        movdqu      xmm7,       [rsi+rdx]
+
+        movdqa      XMMWORD PTR [rsp],            xmm0
+
+        movdqu      xmm0,       [rsi+rdx*2]
+
+        movdqa      XMMWORD PTR [rsp+16],         xmm1
+        movdqa      XMMWORD PTR [rsp+32],         xmm2
+        movdqa      XMMWORD PTR [rsp+48],         xmm3
+        movdqa      XMMWORD PTR [rsp+64],         xmm4
+        movdqa      XMMWORD PTR [rsp+80],         xmm5
+        movdqa      XMMWORD PTR [rsp+96],         xmm6
+        movdqa      XMMWORD PTR [rsp+112],        xmm7
+        movdqa      XMMWORD PTR [rsp+128],        xmm0
+
+        movsxd      rax,        dword ptr arg(2) ;xoffset
+        shl         rax,        5
+        add         rax,        rcx    ;HFilter
+
+        mov         rdi,        arg(4) ;dst_ptr
+        movsxd      rdx,        dword ptr arg(5) ;dst_pitch
+
+        movdqa      xmm1,       [rax]
+        movdqa      xmm2,       [rax+16]
+
+        movsxd      rax,        dword ptr arg(3) ;yoffset
+        shl         rax,        5
+        add         rax,        rcx    ;VFilter
+
+        lea         rcx,        [rdi+rdx*8]
+
+        movdqa      xmm5,       [rax]
+        movdqa      xmm6,       [rax+16]
+
+        pxor        xmm0,       xmm0
+
+        ; get the first horizontal line done
+        movdqa      xmm3,       XMMWORD PTR [rsp]
+        movdqa      xmm4,       xmm3                 ; make a copy of current line
+        psrldq      xmm4,       1
+
+        punpcklbw   xmm3,       xmm0                 ; 00 01 02 03 04 05 06 07
+        punpcklbw   xmm4,       xmm0                 ; 01 02 03 04 05 06 07 08
+
+        pmullw      xmm3,       xmm1
+        pmullw      xmm4,       xmm2
+
+        paddw       xmm3,       xmm4
+
+        paddw       xmm3,       [GLOBAL(rd)]        ; xmm3 += round value
+        psraw       xmm3,       VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        movdqa      xmm7,       xmm3
+        add         rsp,        16                 ; next line
+.next_row8x8:
+        movdqa      xmm3,       XMMWORD PTR [rsp]               ; 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
+        movdqa      xmm4,       xmm3                 ; make a copy of current line
+        psrldq      xmm4,       1
+
+        punpcklbw   xmm3,       xmm0                 ; 00 01 02 03 04 05 06 07
+        punpcklbw   xmm4,       xmm0                 ; 01 02 03 04 05 06 07 08
+
+        pmullw      xmm3,       xmm1
+        pmullw      xmm4,       xmm2
+
+        paddw       xmm3,       xmm4
+        pmullw      xmm7,       xmm5
+
+        paddw       xmm3,       [GLOBAL(rd)]        ; xmm3 += round value
+        psraw       xmm3,       VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        movdqa      xmm4,       xmm3
+
+        pmullw      xmm3,       xmm6
+        paddw       xmm3,       xmm7
+
+        movdqa      xmm7,       xmm4
+
+        paddw       xmm3,       [GLOBAL(rd)]        ; xmm3 += round value
+        psraw       xmm3,       VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        packuswb    xmm3,       xmm0
+        movq        [rdi],      xmm3                 ; store the results in the destination
+
+        add         rsp,        16                 ; next line
+        add         rdi,        rdx
+
+        cmp         rdi,        rcx
+        jne         .next_row8x8
+
+    ;add rsp, 144
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+SECTION_RODATA
+align 16
+rd:
+    times 8 dw 0x40
diff --git a/vp8/common/x86/subpixel_ssse3.asm b/vp8/common/x86/subpixel_ssse3.asm
new file mode 100644 (file)
index 0000000..6bca82b
--- /dev/null
@@ -0,0 +1,1507 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+%define BLOCK_HEIGHT_WIDTH 4
+%define VP8_FILTER_WEIGHT 128
+%define VP8_FILTER_SHIFT  7
+
+
+;/************************************************************************************
+; Notes: filter_block1d_h6 applies a 6 tap filter horizontally to the input pixels. The
+; input pixel array has output_height rows. This routine assumes that output_height is an
+; even number. This function handles 8 pixels in horizontal direction, calculating ONE
+; rows each iteration to take advantage of the 128 bits operations.
+;
+; This is an implementation of some of the SSE optimizations first seen in ffvp8
+;
+;*************************************************************************************/
+;void vp8_filter_block1d8_h6_ssse3
+;(
+;    unsigned char  *src_ptr,
+;    unsigned int    src_pixels_per_line,
+;    unsigned char *output_ptr,
+;    unsigned int    output_pitch,
+;    unsigned int    output_height,
+;    unsigned int    vp8_filter_index
+;)
+global sym(vp8_filter_block1d8_h6_ssse3)
+sym(vp8_filter_block1d8_h6_ssse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    movsxd      rdx, DWORD PTR arg(5)   ;table index
+    xor         rsi, rsi
+    shl         rdx, 4
+
+    movdqa      xmm7, [GLOBAL(rd)]
+
+    lea         rax, [GLOBAL(k0_k5)]
+    add         rax, rdx
+    mov         rdi, arg(2)             ;output_ptr
+
+    cmp         esi, DWORD PTR [rax]
+    je          vp8_filter_block1d8_h4_ssse3
+
+    movdqa      xmm4, XMMWORD PTR [rax]         ;k0_k5
+    movdqa      xmm5, XMMWORD PTR [rax+256]     ;k2_k4
+    movdqa      xmm6, XMMWORD PTR [rax+128]     ;k1_k3
+
+    mov         rsi, arg(0)             ;src_ptr
+    movsxd      rax, dword ptr arg(1)   ;src_pixels_per_line
+    movsxd      rcx, dword ptr arg(4)   ;output_height
+
+    movsxd      rdx, dword ptr arg(3)   ;output_pitch
+
+    sub         rdi, rdx
+;xmm3 free
+.filter_block1d8_h6_rowloop_ssse3:
+    movq        xmm0,   MMWORD PTR [rsi - 2]    ; -2 -1  0  1  2  3  4  5
+
+    movq        xmm2,   MMWORD PTR [rsi + 3]    ;  3  4  5  6  7  8  9 10
+
+    punpcklbw   xmm0,   xmm2                    ; -2  3 -1  4  0  5  1  6  2  7  3  8  4  9  5 10
+
+    movdqa      xmm1,   xmm0
+    pmaddubsw   xmm0,   xmm4
+
+    movdqa      xmm2,   xmm1
+    pshufb      xmm1,   [GLOBAL(shuf2bfrom1)]
+
+    pshufb      xmm2,   [GLOBAL(shuf3bfrom1)]
+    pmaddubsw   xmm1,   xmm5
+
+    lea         rdi,    [rdi + rdx]
+    pmaddubsw   xmm2,   xmm6
+
+    lea         rsi,    [rsi + rax]
+    dec         rcx
+
+    paddsw      xmm0,   xmm1
+    paddsw      xmm2,   xmm7
+
+    paddsw      xmm0,   xmm2
+
+    psraw       xmm0,   7
+
+    packuswb    xmm0,   xmm0
+
+    movq        MMWORD Ptr [rdi], xmm0
+    jnz         .filter_block1d8_h6_rowloop_ssse3
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+vp8_filter_block1d8_h4_ssse3:
+    movdqa      xmm5, XMMWORD PTR [rax+256]     ;k2_k4
+    movdqa      xmm6, XMMWORD PTR [rax+128]     ;k1_k3
+
+    movdqa      xmm3, XMMWORD PTR [GLOBAL(shuf2bfrom1)]
+    movdqa      xmm4, XMMWORD PTR [GLOBAL(shuf3bfrom1)]
+
+    mov         rsi, arg(0)             ;src_ptr
+
+    movsxd      rax, dword ptr arg(1)   ;src_pixels_per_line
+    movsxd      rcx, dword ptr arg(4)   ;output_height
+
+    movsxd      rdx, dword ptr arg(3)   ;output_pitch
+
+    sub         rdi, rdx
+
+.filter_block1d8_h4_rowloop_ssse3:
+    movq        xmm0,   MMWORD PTR [rsi - 2]    ; -2 -1  0  1  2  3  4  5
+
+    movq        xmm1,   MMWORD PTR [rsi + 3]    ;  3  4  5  6  7  8  9 10
+
+    punpcklbw   xmm0,   xmm1                    ; -2  3 -1  4  0  5  1  6  2  7  3  8  4  9  5 10
+
+    movdqa      xmm2,   xmm0
+    pshufb      xmm0,   xmm3
+
+    pshufb      xmm2,   xmm4
+    pmaddubsw   xmm0,   xmm5
+
+    lea         rdi,    [rdi + rdx]
+    pmaddubsw   xmm2,   xmm6
+
+    lea         rsi,    [rsi + rax]
+    dec         rcx
+
+    paddsw      xmm0,   xmm7
+
+    paddsw      xmm0,   xmm2
+
+    psraw       xmm0,   7
+
+    packuswb    xmm0,   xmm0
+
+    movq        MMWORD Ptr [rdi], xmm0
+
+    jnz         .filter_block1d8_h4_rowloop_ssse3
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+;void vp8_filter_block1d16_h6_ssse3
+;(
+;    unsigned char  *src_ptr,
+;    unsigned int    src_pixels_per_line,
+;    unsigned char  *output_ptr,
+;    unsigned int    output_pitch,
+;    unsigned int    output_height,
+;    unsigned int    vp8_filter_index
+;)
+global sym(vp8_filter_block1d16_h6_ssse3)
+sym(vp8_filter_block1d16_h6_ssse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    movsxd      rdx, DWORD PTR arg(5)           ;table index
+    xor         rsi, rsi
+    shl         rdx, 4      ;
+
+    lea         rax, [GLOBAL(k0_k5)]
+    add         rax, rdx
+
+    mov         rdi, arg(2)                     ;output_ptr
+
+    mov         rsi, arg(0)                     ;src_ptr
+
+    movdqa      xmm4, XMMWORD PTR [rax]         ;k0_k5
+    movdqa      xmm5, XMMWORD PTR [rax+256]     ;k2_k4
+    movdqa      xmm6, XMMWORD PTR [rax+128]     ;k1_k3
+
+    movsxd      rax, dword ptr arg(1)           ;src_pixels_per_line
+    movsxd      rcx, dword ptr arg(4)           ;output_height
+    movsxd      rdx, dword ptr arg(3)           ;output_pitch
+
+.filter_block1d16_h6_rowloop_ssse3:
+    movq        xmm0,   MMWORD PTR [rsi - 2]    ; -2 -1  0  1  2  3  4  5
+
+    movq        xmm3,   MMWORD PTR [rsi + 3]    ;  3  4  5  6  7  8  9 10
+
+    punpcklbw   xmm0,   xmm3                    ; -2  3 -1  4  0  5  1  6  2  7  3  8  4  9  5 10
+
+    movdqa      xmm1,   xmm0
+    pmaddubsw   xmm0,   xmm4
+
+    movdqa      xmm2,   xmm1
+    pshufb      xmm1,   [GLOBAL(shuf2bfrom1)]
+
+    pshufb      xmm2,   [GLOBAL(shuf3bfrom1)]
+    movq        xmm3,   MMWORD PTR [rsi +  6]
+
+    pmaddubsw   xmm1,   xmm5
+    movq        xmm7,   MMWORD PTR [rsi + 11]
+
+    pmaddubsw   xmm2,   xmm6
+    punpcklbw   xmm3,   xmm7
+
+    paddsw      xmm0,   xmm1
+    movdqa      xmm1,   xmm3
+
+    pmaddubsw   xmm3,   xmm4
+    paddsw      xmm0,   xmm2
+
+    movdqa      xmm2,   xmm1
+    paddsw      xmm0,   [GLOBAL(rd)]
+
+    pshufb      xmm1,   [GLOBAL(shuf2bfrom1)]
+    pshufb      xmm2,   [GLOBAL(shuf3bfrom1)]
+
+    psraw       xmm0,   7
+    pmaddubsw   xmm1,   xmm5
+
+    pmaddubsw   xmm2,   xmm6
+    packuswb    xmm0,   xmm0
+
+    lea         rsi,    [rsi + rax]
+    paddsw      xmm3,   xmm1
+
+    paddsw      xmm3,   xmm2
+
+    paddsw      xmm3,   [GLOBAL(rd)]
+
+    psraw       xmm3,   7
+
+    packuswb    xmm3,   xmm3
+
+    punpcklqdq  xmm0,   xmm3
+
+    movdqa      XMMWORD Ptr [rdi], xmm0
+
+    lea         rdi,    [rdi + rdx]
+    dec         rcx
+    jnz         .filter_block1d16_h6_rowloop_ssse3
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_filter_block1d4_h6_ssse3
+;(
+;    unsigned char  *src_ptr,
+;    unsigned int    src_pixels_per_line,
+;    unsigned char  *output_ptr,
+;    unsigned int    output_pitch,
+;    unsigned int    output_height,
+;    unsigned int    vp8_filter_index
+;)
+global sym(vp8_filter_block1d4_h6_ssse3)
+sym(vp8_filter_block1d4_h6_ssse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    movsxd      rdx, DWORD PTR arg(5)   ;table index
+    xor         rsi, rsi
+    shl         rdx, 4      ;
+
+    lea         rax, [GLOBAL(k0_k5)]
+    add         rax, rdx
+    movdqa      xmm7, [GLOBAL(rd)]
+
+    cmp         esi, DWORD PTR [rax]
+    je          .vp8_filter_block1d4_h4_ssse3
+
+    movdqa      xmm4, XMMWORD PTR [rax]         ;k0_k5
+    movdqa      xmm5, XMMWORD PTR [rax+256]     ;k2_k4
+    movdqa      xmm6, XMMWORD PTR [rax+128]     ;k1_k3
+
+    mov         rsi, arg(0)             ;src_ptr
+    mov         rdi, arg(2)             ;output_ptr
+    movsxd      rax, dword ptr arg(1)   ;src_pixels_per_line
+    movsxd      rcx, dword ptr arg(4)   ;output_height
+
+    movsxd      rdx, dword ptr arg(3)   ;output_pitch
+
+;xmm3 free
+.filter_block1d4_h6_rowloop_ssse3:
+    movdqu      xmm0,   XMMWORD PTR [rsi - 2]
+
+    movdqa      xmm1, xmm0
+    pshufb      xmm0, [GLOBAL(shuf1b)]
+
+    movdqa      xmm2, xmm1
+    pshufb      xmm1, [GLOBAL(shuf2b)]
+    pmaddubsw   xmm0, xmm4
+    pshufb      xmm2, [GLOBAL(shuf3b)]
+    pmaddubsw   xmm1, xmm5
+
+;--
+    pmaddubsw   xmm2, xmm6
+
+    lea         rsi,    [rsi + rax]
+;--
+    paddsw      xmm0, xmm1
+    paddsw      xmm0, xmm7
+    pxor        xmm1, xmm1
+    paddsw      xmm0, xmm2
+    psraw       xmm0, 7
+    packuswb    xmm0, xmm0
+
+    movd        DWORD PTR [rdi], xmm0
+
+    add         rdi, rdx
+    dec         rcx
+    jnz         .filter_block1d4_h6_rowloop_ssse3
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+.vp8_filter_block1d4_h4_ssse3:
+    movdqa      xmm5, XMMWORD PTR [rax+256]     ;k2_k4
+    movdqa      xmm6, XMMWORD PTR [rax+128]     ;k1_k3
+    movdqa      xmm0, XMMWORD PTR [GLOBAL(shuf2b)]
+    movdqa      xmm3, XMMWORD PTR [GLOBAL(shuf3b)]
+
+    mov         rsi, arg(0)             ;src_ptr
+    mov         rdi, arg(2)             ;output_ptr
+    movsxd      rax, dword ptr arg(1)   ;src_pixels_per_line
+    movsxd      rcx, dword ptr arg(4)   ;output_height
+
+    movsxd      rdx, dword ptr arg(3)   ;output_pitch
+
+.filter_block1d4_h4_rowloop_ssse3:
+    movdqu      xmm1,   XMMWORD PTR [rsi - 2]
+
+    movdqa      xmm2, xmm1
+    pshufb      xmm1, xmm0 ;;[GLOBAL(shuf2b)]
+    pshufb      xmm2, xmm3 ;;[GLOBAL(shuf3b)]
+    pmaddubsw   xmm1, xmm5
+
+;--
+    pmaddubsw   xmm2, xmm6
+
+    lea         rsi,    [rsi + rax]
+;--
+    paddsw      xmm1, xmm7
+    paddsw      xmm1, xmm2
+    psraw       xmm1, 7
+    packuswb    xmm1, xmm1
+
+    movd        DWORD PTR [rdi], xmm1
+
+    add         rdi, rdx
+    dec         rcx
+    jnz         .filter_block1d4_h4_rowloop_ssse3
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+
+;void vp8_filter_block1d16_v6_ssse3
+;(
+;    unsigned char *src_ptr,
+;    unsigned int   src_pitch,
+;    unsigned char *output_ptr,
+;    unsigned int   out_pitch,
+;    unsigned int   output_height,
+;    unsigned int   vp8_filter_index
+;)
+global sym(vp8_filter_block1d16_v6_ssse3)
+sym(vp8_filter_block1d16_v6_ssse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    movsxd      rdx, DWORD PTR arg(5)   ;table index
+    xor         rsi, rsi
+    shl         rdx, 4      ;
+
+    lea         rax, [GLOBAL(k0_k5)]
+    add         rax, rdx
+
+    cmp         esi, DWORD PTR [rax]
+    je          .vp8_filter_block1d16_v4_ssse3
+
+    movdqa      xmm5, XMMWORD PTR [rax]         ;k0_k5
+    movdqa      xmm6, XMMWORD PTR [rax+256]     ;k2_k4
+    movdqa      xmm7, XMMWORD PTR [rax+128]     ;k1_k3
+
+    mov         rsi, arg(0)             ;src_ptr
+    movsxd      rdx, DWORD PTR arg(1)   ;pixels_per_line
+    mov         rdi, arg(2)             ;output_ptr
+
+%if ABI_IS_32BIT=0
+    movsxd      r8, DWORD PTR arg(3)    ;out_pitch
+%endif
+    mov         rax, rsi
+    movsxd      rcx, DWORD PTR arg(4)   ;output_height
+    add         rax, rdx
+
+
+.vp8_filter_block1d16_v6_ssse3_loop:
+    movq        xmm1, MMWORD PTR [rsi]                  ;A
+    movq        xmm2, MMWORD PTR [rsi + rdx]            ;B
+    movq        xmm3, MMWORD PTR [rsi + rdx * 2]        ;C
+    movq        xmm4, MMWORD PTR [rax + rdx * 2]        ;D
+    movq        xmm0, MMWORD PTR [rsi + rdx * 4]        ;E
+
+    punpcklbw   xmm2, xmm4                  ;B D
+    punpcklbw   xmm3, xmm0                  ;C E
+
+    movq        xmm0, MMWORD PTR [rax + rdx * 4]        ;F
+
+    pmaddubsw   xmm3, xmm6
+    punpcklbw   xmm1, xmm0                  ;A F
+    pmaddubsw   xmm2, xmm7
+    pmaddubsw   xmm1, xmm5
+
+    paddsw      xmm2, xmm3
+    paddsw      xmm2, xmm1
+    paddsw      xmm2, [GLOBAL(rd)]
+    psraw       xmm2, 7
+    packuswb    xmm2, xmm2
+
+    movq        MMWORD PTR [rdi], xmm2          ;store the results
+
+    movq        xmm1, MMWORD PTR [rsi + 8]                  ;A
+    movq        xmm2, MMWORD PTR [rsi + rdx + 8]            ;B
+    movq        xmm3, MMWORD PTR [rsi + rdx * 2 + 8]        ;C
+    movq        xmm4, MMWORD PTR [rax + rdx * 2 + 8]        ;D
+    movq        xmm0, MMWORD PTR [rsi + rdx * 4 + 8]        ;E
+
+    punpcklbw   xmm2, xmm4                  ;B D
+    punpcklbw   xmm3, xmm0                  ;C E
+
+    movq        xmm0, MMWORD PTR [rax + rdx * 4 + 8]        ;F
+    pmaddubsw   xmm3, xmm6
+    punpcklbw   xmm1, xmm0                  ;A F
+    pmaddubsw   xmm2, xmm7
+    pmaddubsw   xmm1, xmm5
+
+    add         rsi,  rdx
+    add         rax,  rdx
+;--
+;--
+    paddsw      xmm2, xmm3
+    paddsw      xmm2, xmm1
+    paddsw      xmm2, [GLOBAL(rd)]
+    psraw       xmm2, 7
+    packuswb    xmm2, xmm2
+
+    movq        MMWORD PTR [rdi+8], xmm2
+
+%if ABI_IS_32BIT
+    add         rdi,        DWORD PTR arg(3) ;out_pitch
+%else
+    add         rdi,        r8
+%endif
+    dec         rcx
+    jnz         .vp8_filter_block1d16_v6_ssse3_loop
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+.vp8_filter_block1d16_v4_ssse3:
+    movdqa      xmm6, XMMWORD PTR [rax+256]     ;k2_k4
+    movdqa      xmm7, XMMWORD PTR [rax+128]     ;k1_k3
+
+    mov         rsi, arg(0)             ;src_ptr
+    movsxd      rdx, DWORD PTR arg(1)   ;pixels_per_line
+    mov         rdi, arg(2)             ;output_ptr
+
+%if ABI_IS_32BIT=0
+    movsxd      r8, DWORD PTR arg(3)    ;out_pitch
+%endif
+    mov         rax, rsi
+    movsxd      rcx, DWORD PTR arg(4)   ;output_height
+    add         rax, rdx
+
+.vp8_filter_block1d16_v4_ssse3_loop:
+    movq        xmm2, MMWORD PTR [rsi + rdx]            ;B
+    movq        xmm3, MMWORD PTR [rsi + rdx * 2]        ;C
+    movq        xmm4, MMWORD PTR [rax + rdx * 2]        ;D
+    movq        xmm0, MMWORD PTR [rsi + rdx * 4]        ;E
+
+    punpcklbw   xmm2, xmm4                  ;B D
+    punpcklbw   xmm3, xmm0                  ;C E
+
+    pmaddubsw   xmm3, xmm6
+    pmaddubsw   xmm2, xmm7
+    movq        xmm5, MMWORD PTR [rsi + rdx + 8]            ;B
+    movq        xmm1, MMWORD PTR [rsi + rdx * 2 + 8]        ;C
+    movq        xmm4, MMWORD PTR [rax + rdx * 2 + 8]        ;D
+    movq        xmm0, MMWORD PTR [rsi + rdx * 4 + 8]        ;E
+
+    paddsw      xmm2, [GLOBAL(rd)]
+    paddsw      xmm2, xmm3
+    psraw       xmm2, 7
+    packuswb    xmm2, xmm2
+
+    punpcklbw   xmm5, xmm4                  ;B D
+    punpcklbw   xmm1, xmm0                  ;C E
+
+    pmaddubsw   xmm1, xmm6
+    pmaddubsw   xmm5, xmm7
+
+    movdqa      xmm4, [GLOBAL(rd)]
+    add         rsi,  rdx
+    add         rax,  rdx
+;--
+;--
+    paddsw      xmm5, xmm1
+    paddsw      xmm5, xmm4
+    psraw       xmm5, 7
+    packuswb    xmm5, xmm5
+
+    punpcklqdq  xmm2, xmm5
+
+    movdqa       XMMWORD PTR [rdi], xmm2
+
+%if ABI_IS_32BIT
+    add         rdi,        DWORD PTR arg(3) ;out_pitch
+%else
+    add         rdi,        r8
+%endif
+    dec         rcx
+    jnz         .vp8_filter_block1d16_v4_ssse3_loop
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_filter_block1d8_v6_ssse3
+;(
+;    unsigned char *src_ptr,
+;    unsigned int   src_pitch,
+;    unsigned char *output_ptr,
+;    unsigned int   out_pitch,
+;    unsigned int   output_height,
+;    unsigned int   vp8_filter_index
+;)
+global sym(vp8_filter_block1d8_v6_ssse3)
+sym(vp8_filter_block1d8_v6_ssse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    movsxd      rdx, DWORD PTR arg(5)   ;table index
+    xor         rsi, rsi
+    shl         rdx, 4      ;
+
+    lea         rax, [GLOBAL(k0_k5)]
+    add         rax, rdx
+
+    movsxd      rdx, DWORD PTR arg(1)   ;pixels_per_line
+    mov         rdi, arg(2)             ;output_ptr
+%if ABI_IS_32BIT=0
+    movsxd      r8, DWORD PTR arg(3)    ; out_pitch
+%endif
+    movsxd      rcx, DWORD PTR arg(4)   ;[output_height]
+
+    cmp         esi, DWORD PTR [rax]
+    je          .vp8_filter_block1d8_v4_ssse3
+
+    movdqa      xmm5, XMMWORD PTR [rax]         ;k0_k5
+    movdqa      xmm6, XMMWORD PTR [rax+256]     ;k2_k4
+    movdqa      xmm7, XMMWORD PTR [rax+128]     ;k1_k3
+
+    mov         rsi, arg(0)             ;src_ptr
+
+    mov         rax, rsi
+    add         rax, rdx
+
+.vp8_filter_block1d8_v6_ssse3_loop:
+    movq        xmm1, MMWORD PTR [rsi]                  ;A
+    movq        xmm2, MMWORD PTR [rsi + rdx]            ;B
+    movq        xmm3, MMWORD PTR [rsi + rdx * 2]        ;C
+    movq        xmm4, MMWORD PTR [rax + rdx * 2]        ;D
+    movq        xmm0, MMWORD PTR [rsi + rdx * 4]        ;E
+
+    punpcklbw   xmm2, xmm4                  ;B D
+    punpcklbw   xmm3, xmm0                  ;C E
+
+    movq        xmm0, MMWORD PTR [rax + rdx * 4]        ;F
+    movdqa      xmm4, [GLOBAL(rd)]
+
+    pmaddubsw   xmm3, xmm6
+    punpcklbw   xmm1, xmm0                  ;A F
+    pmaddubsw   xmm2, xmm7
+    pmaddubsw   xmm1, xmm5
+    add         rsi,  rdx
+    add         rax,  rdx
+;--
+;--
+    paddsw      xmm2, xmm3
+    paddsw      xmm2, xmm1
+    paddsw      xmm2, xmm4
+    psraw       xmm2, 7
+    packuswb    xmm2, xmm2
+
+    movq        MMWORD PTR [rdi], xmm2
+
+%if ABI_IS_32BIT
+    add         rdi,        DWORD PTR arg(3) ;[out_pitch]
+%else
+    add         rdi,        r8
+%endif
+    dec         rcx
+    jnz         .vp8_filter_block1d8_v6_ssse3_loop
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+.vp8_filter_block1d8_v4_ssse3:
+    movdqa      xmm6, XMMWORD PTR [rax+256]     ;k2_k4
+    movdqa      xmm7, XMMWORD PTR [rax+128]     ;k1_k3
+    movdqa      xmm5, [GLOBAL(rd)]
+
+    mov         rsi, arg(0)             ;src_ptr
+
+    mov         rax, rsi
+    add         rax, rdx
+
+.vp8_filter_block1d8_v4_ssse3_loop:
+    movq        xmm2, MMWORD PTR [rsi + rdx]            ;B
+    movq        xmm3, MMWORD PTR [rsi + rdx * 2]        ;C
+    movq        xmm4, MMWORD PTR [rax + rdx * 2]        ;D
+    movq        xmm0, MMWORD PTR [rsi + rdx * 4]        ;E
+
+    punpcklbw   xmm2, xmm4                  ;B D
+    punpcklbw   xmm3, xmm0                  ;C E
+
+    pmaddubsw   xmm3, xmm6
+    pmaddubsw   xmm2, xmm7
+    add         rsi,  rdx
+    add         rax,  rdx
+;--
+;--
+    paddsw      xmm2, xmm3
+    paddsw      xmm2, xmm5
+    psraw       xmm2, 7
+    packuswb    xmm2, xmm2
+
+    movq        MMWORD PTR [rdi], xmm2
+
+%if ABI_IS_32BIT
+    add         rdi,        DWORD PTR arg(3) ;[out_pitch]
+%else
+    add         rdi,        r8
+%endif
+    dec         rcx
+    jnz         .vp8_filter_block1d8_v4_ssse3_loop
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+;void vp8_filter_block1d4_v6_ssse3
+;(
+;    unsigned char *src_ptr,
+;    unsigned int   src_pitch,
+;    unsigned char *output_ptr,
+;    unsigned int   out_pitch,
+;    unsigned int   output_height,
+;    unsigned int   vp8_filter_index
+;)
+global sym(vp8_filter_block1d4_v6_ssse3)
+sym(vp8_filter_block1d4_v6_ssse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    movsxd      rdx, DWORD PTR arg(5)   ;table index
+    xor         rsi, rsi
+    shl         rdx, 4      ;
+
+    lea         rax, [GLOBAL(k0_k5)]
+    add         rax, rdx
+
+    movsxd      rdx, DWORD PTR arg(1)   ;pixels_per_line
+    mov         rdi, arg(2)             ;output_ptr
+%if ABI_IS_32BIT=0
+    movsxd      r8, DWORD PTR arg(3)    ; out_pitch
+%endif
+    movsxd      rcx, DWORD PTR arg(4)   ;[output_height]
+
+    cmp         esi, DWORD PTR [rax]
+    je          .vp8_filter_block1d4_v4_ssse3
+
+    movq        mm5, MMWORD PTR [rax]         ;k0_k5
+    movq        mm6, MMWORD PTR [rax+256]     ;k2_k4
+    movq        mm7, MMWORD PTR [rax+128]     ;k1_k3
+
+    mov         rsi, arg(0)             ;src_ptr
+
+    mov         rax, rsi
+    add         rax, rdx
+
+.vp8_filter_block1d4_v6_ssse3_loop:
+    movd        mm1, DWORD PTR [rsi]                  ;A
+    movd        mm2, DWORD PTR [rsi + rdx]            ;B
+    movd        mm3, DWORD PTR [rsi + rdx * 2]        ;C
+    movd        mm4, DWORD PTR [rax + rdx * 2]        ;D
+    movd        mm0, DWORD PTR [rsi + rdx * 4]        ;E
+
+    punpcklbw   mm2, mm4                  ;B D
+    punpcklbw   mm3, mm0                  ;C E
+
+    movd        mm0, DWORD PTR [rax + rdx * 4]        ;F
+
+    movq        mm4, [GLOBAL(rd)]
+
+    pmaddubsw   mm3, mm6
+    punpcklbw   mm1, mm0                  ;A F
+    pmaddubsw   mm2, mm7
+    pmaddubsw   mm1, mm5
+    add         rsi,  rdx
+    add         rax,  rdx
+;--
+;--
+    paddsw      mm2, mm3
+    paddsw      mm2, mm1
+    paddsw      mm2, mm4
+    psraw       mm2, 7
+    packuswb    mm2, mm2
+
+    movd        DWORD PTR [rdi], mm2
+
+%if ABI_IS_32BIT
+    add         rdi,        DWORD PTR arg(3) ;[out_pitch]
+%else
+    add         rdi,        r8
+%endif
+    dec         rcx
+    jnz         .vp8_filter_block1d4_v6_ssse3_loop
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+.vp8_filter_block1d4_v4_ssse3:
+    movq        mm6, MMWORD PTR [rax+256]     ;k2_k4
+    movq        mm7, MMWORD PTR [rax+128]     ;k1_k3
+    movq        mm5, MMWORD PTR [GLOBAL(rd)]
+
+    mov         rsi, arg(0)             ;src_ptr
+
+    mov         rax, rsi
+    add         rax, rdx
+
+.vp8_filter_block1d4_v4_ssse3_loop:
+    movd        mm2, DWORD PTR [rsi + rdx]            ;B
+    movd        mm3, DWORD PTR [rsi + rdx * 2]        ;C
+    movd        mm4, DWORD PTR [rax + rdx * 2]        ;D
+    movd        mm0, DWORD PTR [rsi + rdx * 4]        ;E
+
+    punpcklbw   mm2, mm4                  ;B D
+    punpcklbw   mm3, mm0                  ;C E
+
+    pmaddubsw   mm3, mm6
+    pmaddubsw   mm2, mm7
+    add         rsi,  rdx
+    add         rax,  rdx
+;--
+;--
+    paddsw      mm2, mm3
+    paddsw      mm2, mm5
+    psraw       mm2, 7
+    packuswb    mm2, mm2
+
+    movd        DWORD PTR [rdi], mm2
+
+%if ABI_IS_32BIT
+    add         rdi,        DWORD PTR arg(3) ;[out_pitch]
+%else
+    add         rdi,        r8
+%endif
+    dec         rcx
+    jnz         .vp8_filter_block1d4_v4_ssse3_loop
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_bilinear_predict16x16_ssse3
+;(
+;    unsigned char  *src_ptr,
+;    int   src_pixels_per_line,
+;    int  xoffset,
+;    int  yoffset,
+;    unsigned char *dst_ptr,
+;    int dst_pitch
+;)
+global sym(vp8_bilinear_predict16x16_ssse3)
+sym(vp8_bilinear_predict16x16_ssse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        lea         rcx,        [GLOBAL(vp8_bilinear_filters_ssse3)]
+        movsxd      rax,        dword ptr arg(2)    ; xoffset
+
+        cmp         rax,        0                   ; skip first_pass filter if xoffset=0
+        je          .b16x16_sp_only
+
+        shl         rax,        4
+        lea         rax,        [rax + rcx]         ; HFilter
+
+        mov         rdi,        arg(4)              ; dst_ptr
+        mov         rsi,        arg(0)              ; src_ptr
+        movsxd      rdx,        dword ptr arg(5)    ; dst_pitch
+
+        movdqa      xmm1,       [rax]
+
+        movsxd      rax,        dword ptr arg(3)    ; yoffset
+
+        cmp         rax,        0                   ; skip second_pass filter if yoffset=0
+        je          .b16x16_fp_only
+
+        shl         rax,        4
+        lea         rax,        [rax + rcx]         ; VFilter
+
+        lea         rcx,        [rdi+rdx*8]
+        lea         rcx,        [rcx+rdx*8]
+        movsxd      rdx,        dword ptr arg(1)    ; src_pixels_per_line
+
+        movdqa      xmm2,       [rax]
+
+%if ABI_IS_32BIT=0
+        movsxd      r8,         dword ptr arg(5)    ; dst_pitch
+%endif
+        movq        xmm3,       [rsi]               ; 00 01 02 03 04 05 06 07
+        movq        xmm5,       [rsi+1]             ; 01 02 03 04 05 06 07 08
+
+        punpcklbw   xmm3,       xmm5                ; 00 01 01 02 02 03 03 04 04 05 05 06 06 07 07 08
+        movq        xmm4,       [rsi+8]             ; 08 09 10 11 12 13 14 15
+
+        movq        xmm5,       [rsi+9]             ; 09 10 11 12 13 14 15 16
+
+        lea         rsi,        [rsi + rdx]         ; next line
+
+        pmaddubsw   xmm3,       xmm1                ; 00 02 04 06 08 10 12 14
+
+        punpcklbw   xmm4,       xmm5                ; 08 09 09 10 10 11 11 12 12 13 13 14 14 15 15 16
+        pmaddubsw   xmm4,       xmm1                ; 01 03 05 07 09 11 13 15
+
+        paddw       xmm3,       [GLOBAL(rd)]        ; xmm3 += round value
+        psraw       xmm3,       VP8_FILTER_SHIFT    ; xmm3 /= 128
+
+        paddw       xmm4,       [GLOBAL(rd)]        ; xmm4 += round value
+        psraw       xmm4,       VP8_FILTER_SHIFT    ; xmm4 /= 128
+
+        movdqa      xmm7,       xmm3
+        packuswb    xmm7,       xmm4                ; 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
+
+.next_row:
+        movq        xmm6,       [rsi]               ; 00 01 02 03 04 05 06 07
+        movq        xmm5,       [rsi+1]             ; 01 02 03 04 05 06 07 08
+
+        punpcklbw   xmm6,       xmm5
+        movq        xmm4,       [rsi+8]             ; 08 09 10 11 12 13 14 15
+
+        movq        xmm5,       [rsi+9]             ; 09 10 11 12 13 14 15 16
+        lea         rsi,        [rsi + rdx]         ; next line
+
+        pmaddubsw   xmm6,       xmm1
+
+        punpcklbw   xmm4,       xmm5
+        pmaddubsw   xmm4,       xmm1
+
+        paddw       xmm6,       [GLOBAL(rd)]        ; xmm6 += round value
+        psraw       xmm6,       VP8_FILTER_SHIFT    ; xmm6 /= 128
+
+        paddw       xmm4,       [GLOBAL(rd)]        ; xmm4 += round value
+        psraw       xmm4,       VP8_FILTER_SHIFT    ; xmm4 /= 128
+
+        packuswb    xmm6,       xmm4
+        movdqa      xmm5,       xmm7
+
+        punpcklbw   xmm5,       xmm6
+        pmaddubsw   xmm5,       xmm2
+
+        punpckhbw   xmm7,       xmm6
+        pmaddubsw   xmm7,       xmm2
+
+        paddw       xmm5,       [GLOBAL(rd)]        ; xmm5 += round value
+        psraw       xmm5,       VP8_FILTER_SHIFT    ; xmm5 /= 128
+
+        paddw       xmm7,       [GLOBAL(rd)]        ; xmm7 += round value
+        psraw       xmm7,       VP8_FILTER_SHIFT    ; xmm7 /= 128
+
+        packuswb    xmm5,       xmm7
+        movdqa      xmm7,       xmm6
+
+        movdqa      [rdi],      xmm5                ; store the results in the destination
+%if ABI_IS_32BIT
+        add         rdi,        DWORD PTR arg(5)    ; dst_pitch
+%else
+        add         rdi,        r8
+%endif
+
+        cmp         rdi,        rcx
+        jne         .next_row
+
+        jmp         .done
+
+.b16x16_sp_only:
+        movsxd      rax,        dword ptr arg(3)    ; yoffset
+        shl         rax,        4
+        lea         rax,        [rax + rcx]         ; VFilter
+
+        mov         rdi,        arg(4)              ; dst_ptr
+        mov         rsi,        arg(0)              ; src_ptr
+        movsxd      rdx,        dword ptr arg(5)    ; dst_pitch
+
+        movdqa      xmm1,       [rax]               ; VFilter
+
+        lea         rcx,        [rdi+rdx*8]
+        lea         rcx,        [rcx+rdx*8]
+        movsxd      rax,        dword ptr arg(1)    ; src_pixels_per_line
+
+        ; get the first horizontal line done
+        movq        xmm4,       [rsi]               ; load row 0
+        movq        xmm2,       [rsi + 8]           ; load row 0
+
+        lea         rsi,        [rsi + rax]         ; next line
+.next_row_sp:
+        movq        xmm3,       [rsi]               ; load row + 1
+        movq        xmm5,       [rsi + 8]           ; load row + 1
+
+        punpcklbw   xmm4,       xmm3
+        punpcklbw   xmm2,       xmm5
+
+        pmaddubsw   xmm4,       xmm1
+        movq        xmm7,       [rsi + rax]         ; load row + 2
+
+        pmaddubsw   xmm2,       xmm1
+        movq        xmm6,       [rsi + rax + 8]     ; load row + 2
+
+        punpcklbw   xmm3,       xmm7
+        punpcklbw   xmm5,       xmm6
+
+        pmaddubsw   xmm3,       xmm1
+        paddw       xmm4,       [GLOBAL(rd)]
+
+        pmaddubsw   xmm5,       xmm1
+        paddw       xmm2,       [GLOBAL(rd)]
+
+        psraw       xmm4,       VP8_FILTER_SHIFT
+        psraw       xmm2,       VP8_FILTER_SHIFT
+
+        packuswb    xmm4,       xmm2
+        paddw       xmm3,       [GLOBAL(rd)]
+
+        movdqa      [rdi],      xmm4                ; store row 0
+        paddw       xmm5,       [GLOBAL(rd)]
+
+        psraw       xmm3,       VP8_FILTER_SHIFT
+        psraw       xmm5,       VP8_FILTER_SHIFT
+
+        packuswb    xmm3,       xmm5
+        movdqa      xmm4,       xmm7
+
+        movdqa      [rdi + rdx],xmm3                ; store row 1
+        lea         rsi,        [rsi + 2*rax]
+
+        movdqa      xmm2,       xmm6
+        lea         rdi,        [rdi + 2*rdx]
+
+        cmp         rdi,        rcx
+        jne         .next_row_sp
+
+        jmp         .done
+
+.b16x16_fp_only:
+        lea         rcx,        [rdi+rdx*8]
+        lea         rcx,        [rcx+rdx*8]
+        movsxd      rax,        dword ptr arg(1)    ; src_pixels_per_line
+
+.next_row_fp:
+        movq        xmm2,       [rsi]               ; 00 01 02 03 04 05 06 07
+        movq        xmm4,       [rsi+1]             ; 01 02 03 04 05 06 07 08
+
+        punpcklbw   xmm2,       xmm4
+        movq        xmm3,       [rsi+8]             ; 08 09 10 11 12 13 14 15
+
+        pmaddubsw   xmm2,       xmm1
+        movq        xmm4,       [rsi+9]             ; 09 10 11 12 13 14 15 16
+
+        lea         rsi,        [rsi + rax]         ; next line
+        punpcklbw   xmm3,       xmm4
+
+        pmaddubsw   xmm3,       xmm1
+        movq        xmm5,       [rsi]
+
+        paddw       xmm2,       [GLOBAL(rd)]
+        movq        xmm7,       [rsi+1]
+
+        movq        xmm6,       [rsi+8]
+        psraw       xmm2,       VP8_FILTER_SHIFT
+
+        punpcklbw   xmm5,       xmm7
+        movq        xmm7,       [rsi+9]
+
+        paddw       xmm3,       [GLOBAL(rd)]
+        pmaddubsw   xmm5,       xmm1
+
+        psraw       xmm3,       VP8_FILTER_SHIFT
+        punpcklbw   xmm6,       xmm7
+
+        packuswb    xmm2,       xmm3
+        pmaddubsw   xmm6,       xmm1
+
+        movdqa      [rdi],      xmm2                ; store the results in the destination
+        paddw       xmm5,       [GLOBAL(rd)]
+
+        lea         rdi,        [rdi + rdx]         ; dst_pitch
+        psraw       xmm5,       VP8_FILTER_SHIFT
+
+        paddw       xmm6,       [GLOBAL(rd)]
+        psraw       xmm6,       VP8_FILTER_SHIFT
+
+        packuswb    xmm5,       xmm6
+        lea         rsi,        [rsi + rax]         ; next line
+
+        movdqa      [rdi],      xmm5                ; store the results in the destination
+        lea         rdi,        [rdi + rdx]         ; dst_pitch
+
+        cmp         rdi,        rcx
+
+        jne         .next_row_fp
+
+.done:
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_bilinear_predict8x8_ssse3
+;(
+;    unsigned char  *src_ptr,
+;    int   src_pixels_per_line,
+;    int  xoffset,
+;    int  yoffset,
+;    unsigned char *dst_ptr,
+;    int dst_pitch
+;)
+global sym(vp8_bilinear_predict8x8_ssse3)
+sym(vp8_bilinear_predict8x8_ssse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub         rsp, 144                         ; reserve 144 bytes
+
+        lea         rcx,        [GLOBAL(vp8_bilinear_filters_ssse3)]
+
+        mov         rsi,        arg(0) ;src_ptr
+        movsxd      rdx,        dword ptr arg(1) ;src_pixels_per_line
+
+    ;Read 9-line unaligned data in and put them on stack. This gives a big
+    ;performance boost.
+        movdqu      xmm0,       [rsi]
+        lea         rax,        [rdx + rdx*2]
+        movdqu      xmm1,       [rsi+rdx]
+        movdqu      xmm2,       [rsi+rdx*2]
+        add         rsi,        rax
+        movdqu      xmm3,       [rsi]
+        movdqu      xmm4,       [rsi+rdx]
+        movdqu      xmm5,       [rsi+rdx*2]
+        add         rsi,        rax
+        movdqu      xmm6,       [rsi]
+        movdqu      xmm7,       [rsi+rdx]
+
+        movdqa      XMMWORD PTR [rsp],            xmm0
+
+        movdqu      xmm0,       [rsi+rdx*2]
+
+        movdqa      XMMWORD PTR [rsp+16],         xmm1
+        movdqa      XMMWORD PTR [rsp+32],         xmm2
+        movdqa      XMMWORD PTR [rsp+48],         xmm3
+        movdqa      XMMWORD PTR [rsp+64],         xmm4
+        movdqa      XMMWORD PTR [rsp+80],         xmm5
+        movdqa      XMMWORD PTR [rsp+96],         xmm6
+        movdqa      XMMWORD PTR [rsp+112],        xmm7
+        movdqa      XMMWORD PTR [rsp+128],        xmm0
+
+        movsxd      rax,        dword ptr arg(2)    ; xoffset
+        cmp         rax,        0                   ; skip first_pass filter if xoffset=0
+        je          .b8x8_sp_only
+
+        shl         rax,        4
+        add         rax,        rcx                 ; HFilter
+
+        mov         rdi,        arg(4)              ; dst_ptr
+        movsxd      rdx,        dword ptr arg(5)    ; dst_pitch
+
+        movdqa      xmm0,       [rax]
+
+        movsxd      rax,        dword ptr arg(3)    ; yoffset
+        cmp         rax,        0                   ; skip second_pass filter if yoffset=0
+        je          .b8x8_fp_only
+
+        shl         rax,        4
+        lea         rax,        [rax + rcx]         ; VFilter
+
+        lea         rcx,        [rdi+rdx*8]
+
+        movdqa      xmm1,       [rax]
+
+        ; get the first horizontal line done
+        movdqa      xmm3,       [rsp]               ; 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
+        movdqa      xmm5,       xmm3                ; 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 xx
+
+        psrldq      xmm5,       1
+        lea         rsp,        [rsp + 16]          ; next line
+
+        punpcklbw   xmm3,       xmm5                ; 00 01 01 02 02 03 03 04 04 05 05 06 06 07 07 08
+        pmaddubsw   xmm3,       xmm0                ; 00 02 04 06 08 10 12 14
+
+        paddw       xmm3,       [GLOBAL(rd)]        ; xmm3 += round value
+        psraw       xmm3,       VP8_FILTER_SHIFT    ; xmm3 /= 128
+
+        movdqa      xmm7,       xmm3
+        packuswb    xmm7,       xmm7                ; 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
+
+.next_row:
+        movdqa      xmm6,       [rsp]               ; 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
+        lea         rsp,        [rsp + 16]          ; next line
+
+        movdqa      xmm5,       xmm6
+
+        psrldq      xmm5,       1
+
+        punpcklbw   xmm6,       xmm5
+        pmaddubsw   xmm6,       xmm0
+
+        paddw       xmm6,       [GLOBAL(rd)]        ; xmm6 += round value
+        psraw       xmm6,       VP8_FILTER_SHIFT    ; xmm6 /= 128
+
+        packuswb    xmm6,       xmm6
+
+        punpcklbw   xmm7,       xmm6
+        pmaddubsw   xmm7,       xmm1
+
+        paddw       xmm7,       [GLOBAL(rd)]        ; xmm7 += round value
+        psraw       xmm7,       VP8_FILTER_SHIFT    ; xmm7 /= 128
+
+        packuswb    xmm7,       xmm7
+
+        movq        [rdi],      xmm7                ; store the results in the destination
+        lea         rdi,        [rdi + rdx]
+
+        movdqa      xmm7,       xmm6
+
+        cmp         rdi,        rcx
+        jne         .next_row
+
+        jmp         .done8x8
+
+.b8x8_sp_only:
+        movsxd      rax,        dword ptr arg(3)    ; yoffset
+        shl         rax,        4
+        lea         rax,        [rax + rcx]         ; VFilter
+
+        mov         rdi,        arg(4) ;dst_ptr
+        movsxd      rdx,        dword ptr arg(5)    ; dst_pitch
+
+        movdqa      xmm0,       [rax]               ; VFilter
+
+        movq        xmm1,       XMMWORD PTR [rsp]
+        movq        xmm2,       XMMWORD PTR [rsp+16]
+
+        movq        xmm3,       XMMWORD PTR [rsp+32]
+        punpcklbw   xmm1,       xmm2
+
+        movq        xmm4,       XMMWORD PTR [rsp+48]
+        punpcklbw   xmm2,       xmm3
+
+        movq        xmm5,       XMMWORD PTR [rsp+64]
+        punpcklbw   xmm3,       xmm4
+
+        movq        xmm6,       XMMWORD PTR [rsp+80]
+        punpcklbw   xmm4,       xmm5
+
+        movq        xmm7,       XMMWORD PTR [rsp+96]
+        punpcklbw   xmm5,       xmm6
+
+        pmaddubsw   xmm1,       xmm0
+        pmaddubsw   xmm2,       xmm0
+
+        pmaddubsw   xmm3,       xmm0
+        pmaddubsw   xmm4,       xmm0
+
+        pmaddubsw   xmm5,       xmm0
+        punpcklbw   xmm6,       xmm7
+
+        pmaddubsw   xmm6,       xmm0
+        paddw       xmm1,       [GLOBAL(rd)]
+
+        paddw       xmm2,       [GLOBAL(rd)]
+        psraw       xmm1,       VP8_FILTER_SHIFT
+
+        paddw       xmm3,       [GLOBAL(rd)]
+        psraw       xmm2,       VP8_FILTER_SHIFT
+
+        paddw       xmm4,       [GLOBAL(rd)]
+        psraw       xmm3,       VP8_FILTER_SHIFT
+
+        paddw       xmm5,       [GLOBAL(rd)]
+        psraw       xmm4,       VP8_FILTER_SHIFT
+
+        paddw       xmm6,       [GLOBAL(rd)]
+        psraw       xmm5,       VP8_FILTER_SHIFT
+
+        psraw       xmm6,       VP8_FILTER_SHIFT
+        packuswb    xmm1,       xmm1
+
+        packuswb    xmm2,       xmm2
+        movq        [rdi],      xmm1
+
+        packuswb    xmm3,       xmm3
+        movq        [rdi+rdx],  xmm2
+
+        packuswb    xmm4,       xmm4
+        movq        xmm1,       XMMWORD PTR [rsp+112]
+
+        lea         rdi,        [rdi + 2*rdx]
+        movq        xmm2,       XMMWORD PTR [rsp+128]
+
+        packuswb    xmm5,       xmm5
+        movq        [rdi],      xmm3
+
+        packuswb    xmm6,       xmm6
+        movq        [rdi+rdx],  xmm4
+
+        lea         rdi,        [rdi + 2*rdx]
+        punpcklbw   xmm7,       xmm1
+
+        movq        [rdi],      xmm5
+        pmaddubsw   xmm7,       xmm0
+
+        movq        [rdi+rdx],  xmm6
+        punpcklbw   xmm1,       xmm2
+
+        pmaddubsw   xmm1,       xmm0
+        paddw       xmm7,       [GLOBAL(rd)]
+
+        psraw       xmm7,       VP8_FILTER_SHIFT
+        paddw       xmm1,       [GLOBAL(rd)]
+
+        psraw       xmm1,       VP8_FILTER_SHIFT
+        packuswb    xmm7,       xmm7
+
+        packuswb    xmm1,       xmm1
+        lea         rdi,        [rdi + 2*rdx]
+
+        movq        [rdi],      xmm7
+
+        movq        [rdi+rdx],  xmm1
+        lea         rsp,        [rsp + 144]
+
+        jmp         .done8x8
+
+.b8x8_fp_only:
+        lea         rcx,        [rdi+rdx*8]
+
+.next_row_fp:
+        movdqa      xmm1,       XMMWORD PTR [rsp]
+        movdqa      xmm3,       XMMWORD PTR [rsp+16]
+
+        movdqa      xmm2,       xmm1
+        movdqa      xmm5,       XMMWORD PTR [rsp+32]
+
+        psrldq      xmm2,       1
+        movdqa      xmm7,       XMMWORD PTR [rsp+48]
+
+        movdqa      xmm4,       xmm3
+        psrldq      xmm4,       1
+
+        movdqa      xmm6,       xmm5
+        psrldq      xmm6,       1
+
+        punpcklbw   xmm1,       xmm2
+        pmaddubsw   xmm1,       xmm0
+
+        punpcklbw   xmm3,       xmm4
+        pmaddubsw   xmm3,       xmm0
+
+        punpcklbw   xmm5,       xmm6
+        pmaddubsw   xmm5,       xmm0
+
+        movdqa      xmm2,       xmm7
+        psrldq      xmm2,       1
+
+        punpcklbw   xmm7,       xmm2
+        pmaddubsw   xmm7,       xmm0
+
+        paddw       xmm1,       [GLOBAL(rd)]
+        psraw       xmm1,       VP8_FILTER_SHIFT
+
+        paddw       xmm3,       [GLOBAL(rd)]
+        psraw       xmm3,       VP8_FILTER_SHIFT
+
+        paddw       xmm5,       [GLOBAL(rd)]
+        psraw       xmm5,       VP8_FILTER_SHIFT
+
+        paddw       xmm7,       [GLOBAL(rd)]
+        psraw       xmm7,       VP8_FILTER_SHIFT
+
+        packuswb    xmm1,       xmm1
+        packuswb    xmm3,       xmm3
+
+        packuswb    xmm5,       xmm5
+        movq        [rdi],      xmm1
+
+        packuswb    xmm7,       xmm7
+        movq        [rdi+rdx],  xmm3
+
+        lea         rdi,        [rdi + 2*rdx]
+        movq        [rdi],      xmm5
+
+        lea         rsp,        [rsp + 4*16]
+        movq        [rdi+rdx],  xmm7
+
+        lea         rdi,        [rdi + 2*rdx]
+        cmp         rdi,        rcx
+
+        jne         .next_row_fp
+
+        lea         rsp,        [rsp + 16]
+
+.done8x8:
+    ;add rsp, 144
+    pop         rsp
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+SECTION_RODATA
+align 16
+shuf1b:
+    db 0, 5, 1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12
+shuf2b:
+    db 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, 7, 9, 8, 10, 9, 11
+shuf3b:
+    db 1, 3, 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, 7, 9, 8, 10
+
+align 16
+shuf2bfrom1:
+    db  4, 8, 6, 1, 8, 3, 1, 5, 3, 7, 5, 9, 7,11, 9,13
+align 16
+shuf3bfrom1:
+    db  2, 6, 4, 8, 6, 1, 8, 3, 1, 5, 3, 7, 5, 9, 7,11
+
+align 16
+rd:
+    times 8 dw 0x40
+
+align 16
+k0_k5:
+    times 8 db 0, 0             ;placeholder
+    times 8 db 0, 0
+    times 8 db 2, 1
+    times 8 db 0, 0
+    times 8 db 3, 3
+    times 8 db 0, 0
+    times 8 db 1, 2
+    times 8 db 0, 0
+k1_k3:
+    times 8 db  0,    0         ;placeholder
+    times 8 db  -6,  12
+    times 8 db -11,  36
+    times 8 db  -9,  50
+    times 8 db -16,  77
+    times 8 db  -6,  93
+    times 8 db  -8, 108
+    times 8 db  -1, 123
+k2_k4:
+    times 8 db 128,    0        ;placeholder
+    times 8 db 123,   -1
+    times 8 db 108,   -8
+    times 8 db  93,   -6
+    times 8 db  77,  -16
+    times 8 db  50,   -9
+    times 8 db  36,  -11
+    times 8 db  12,   -6
+align 16
+vp8_bilinear_filters_ssse3:
+    times 8 db 128, 0
+    times 8 db 112, 16
+    times 8 db 96,  32
+    times 8 db 80,  48
+    times 8 db 64,  64
+    times 8 db 48,  80
+    times 8 db 32,  96
+    times 8 db 16,  112
+
diff --git a/vp8/common/x86/variance_impl_mmx.asm b/vp8/common/x86/variance_impl_mmx.asm
new file mode 100644 (file)
index 0000000..2be8bbe
--- /dev/null
@@ -0,0 +1,851 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;unsigned int vp8_get_mb_ss_mmx( short *src_ptr )
+global sym(vp8_get_mb_ss_mmx)
+sym(vp8_get_mb_ss_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    sub         rsp, 8
+    ; end prolog
+
+        mov         rax, arg(0) ;src_ptr
+        mov         rcx, 16
+        pxor        mm4, mm4
+
+.NEXTROW:
+        movq        mm0, [rax]
+        movq        mm1, [rax+8]
+        movq        mm2, [rax+16]
+        movq        mm3, [rax+24]
+        pmaddwd     mm0, mm0
+        pmaddwd     mm1, mm1
+        pmaddwd     mm2, mm2
+        pmaddwd     mm3, mm3
+
+        paddd       mm4, mm0
+        paddd       mm4, mm1
+        paddd       mm4, mm2
+        paddd       mm4, mm3
+
+        add         rax, 32
+        dec         rcx
+        ja          .NEXTROW
+        movq        QWORD PTR [rsp], mm4
+
+        ;return sum[0]+sum[1];
+        movsxd      rax, dword ptr [rsp]
+        movsxd      rcx, dword ptr [rsp+4]
+        add         rax, rcx
+
+
+    ; begin epilog
+    add rsp, 8
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;unsigned int vp8_get8x8var_mmx
+;(
+;    unsigned char *src_ptr,
+;    int  source_stride,
+;    unsigned char *ref_ptr,
+;    int  recon_stride,
+;    unsigned int *SSE,
+;    int *Sum
+;)
+global sym(vp8_get8x8var_mmx)
+sym(vp8_get8x8var_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    push rsi
+    push rdi
+    push rbx
+    sub         rsp, 16
+    ; end prolog
+
+
+        pxor        mm5, mm5                    ; Blank mmx6
+        pxor        mm6, mm6                    ; Blank mmx7
+        pxor        mm7, mm7                    ; Blank mmx7
+
+        mov         rax, arg(0) ;[src_ptr]  ; Load base addresses
+        mov         rbx, arg(2) ;[ref_ptr]
+        movsxd      rcx, dword ptr arg(1) ;[source_stride]
+        movsxd      rdx, dword ptr arg(3) ;[recon_stride]
+
+        ; Row 1
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        movq        mm2, mm0                    ; Take copies
+        movq        mm3, mm1                    ; Take copies
+
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        punpckhbw   mm2, mm6                    ; unpack to higher prrcision
+        punpckhbw   mm3, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        psubsw      mm2, mm3                    ; A-B (high order) to MM2
+
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+        paddw       mm5, mm2                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        pmaddwd     mm2, mm2                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+        paddd       mm7, mm2                    ; accumulate in mm7
+
+
+        ; Row 2
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        movq        mm2, mm0                    ; Take copies
+        movq        mm3, mm1                    ; Take copies
+
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        punpckhbw   mm2, mm6                    ; unpack to higher prrcision
+        punpckhbw   mm3, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        psubsw      mm2, mm3                    ; A-B (high order) to MM2
+
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+        paddw       mm5, mm2                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        pmaddwd     mm2, mm2                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+        paddd       mm7, mm2                    ; accumulate in mm7
+
+        ; Row 3
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        movq        mm2, mm0                    ; Take copies
+        movq        mm3, mm1                    ; Take copies
+
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        punpckhbw   mm2, mm6                    ; unpack to higher prrcision
+        punpckhbw   mm3, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        psubsw      mm2, mm3                    ; A-B (high order) to MM2
+
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+        paddw       mm5, mm2                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        pmaddwd     mm2, mm2                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+        paddd       mm7, mm2                    ; accumulate in mm7
+
+        ; Row 4
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        movq        mm2, mm0                    ; Take copies
+        movq        mm3, mm1                    ; Take copies
+
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        punpckhbw   mm2, mm6                    ; unpack to higher prrcision
+        punpckhbw   mm3, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        psubsw      mm2, mm3                    ; A-B (high order) to MM2
+
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+        paddw       mm5, mm2                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        pmaddwd     mm2, mm2                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+        paddd       mm7, mm2                    ; accumulate in mm7
+
+        ; Row 5
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        movq        mm2, mm0                    ; Take copies
+        movq        mm3, mm1                    ; Take copies
+
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        punpckhbw   mm2, mm6                    ; unpack to higher prrcision
+        punpckhbw   mm3, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        psubsw      mm2, mm3                    ; A-B (high order) to MM2
+
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+        paddw       mm5, mm2                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        pmaddwd     mm2, mm2                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        ;              movq        mm4, [rbx + rdx]
+        paddd       mm7, mm0                    ; accumulate in mm7
+        paddd       mm7, mm2                    ; accumulate in mm7
+
+        ; Row 6
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        movq        mm2, mm0                    ; Take copies
+        movq        mm3, mm1                    ; Take copies
+
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        punpckhbw   mm2, mm6                    ; unpack to higher prrcision
+        punpckhbw   mm3, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        psubsw      mm2, mm3                    ; A-B (high order) to MM2
+
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+        paddw       mm5, mm2                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        pmaddwd     mm2, mm2                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+        paddd       mm7, mm2                    ; accumulate in mm7
+
+        ; Row 7
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        movq        mm2, mm0                    ; Take copies
+        movq        mm3, mm1                    ; Take copies
+
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        punpckhbw   mm2, mm6                    ; unpack to higher prrcision
+        punpckhbw   mm3, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        psubsw      mm2, mm3                    ; A-B (high order) to MM2
+
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+        paddw       mm5, mm2                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        pmaddwd     mm2, mm2                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+        paddd       mm7, mm2                    ; accumulate in mm7
+
+        ; Row 8
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        movq        mm2, mm0                    ; Take copies
+        movq        mm3, mm1                    ; Take copies
+
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        punpckhbw   mm2, mm6                    ; unpack to higher prrcision
+        punpckhbw   mm3, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        psubsw      mm2, mm3                    ; A-B (high order) to MM2
+
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+        paddw       mm5, mm2                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        pmaddwd     mm2, mm2                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        paddd       mm7, mm0                    ; accumulate in mm7
+        paddd       mm7, mm2                    ; accumulate in mm7
+
+        ; Now accumulate the final results.
+        movq        QWORD PTR [rsp+8], mm5      ; copy back accumulated results into normal memory
+        movq        QWORD PTR [rsp], mm7        ; copy back accumulated results into normal memory
+        movsx       rdx, WORD PTR [rsp+8]
+        movsx       rcx, WORD PTR [rsp+10]
+        movsx       rbx, WORD PTR [rsp+12]
+        movsx       rax, WORD PTR [rsp+14]
+        add         rdx, rcx
+        add         rbx, rax
+        add         rdx, rbx    ;XSum
+        movsxd      rax, DWORD PTR [rsp]
+        movsxd      rcx, DWORD PTR [rsp+4]
+        add         rax, rcx    ;XXSum
+        mov         rsi, arg(4) ;SSE
+        mov         rdi, arg(5) ;Sum
+        mov         dword ptr [rsi], eax
+        mov         dword ptr [rdi], edx
+        xor         rax, rax    ; return 0
+
+
+    ; begin epilog
+    add rsp, 16
+    pop rbx
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+
+;unsigned int
+;vp8_get4x4var_mmx
+;(
+;    unsigned char *src_ptr,
+;    int  source_stride,
+;    unsigned char *ref_ptr,
+;    int  recon_stride,
+;    unsigned int *SSE,
+;    int *Sum
+;)
+global sym(vp8_get4x4var_mmx)
+sym(vp8_get4x4var_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    push rsi
+    push rdi
+    push rbx
+    sub         rsp, 16
+    ; end prolog
+
+
+        pxor        mm5, mm5                    ; Blank mmx6
+        pxor        mm6, mm6                    ; Blank mmx7
+        pxor        mm7, mm7                    ; Blank mmx7
+
+        mov         rax, arg(0) ;[src_ptr]  ; Load base addresses
+        mov         rbx, arg(2) ;[ref_ptr]
+        movsxd      rcx, dword ptr arg(1) ;[source_stride]
+        movsxd      rdx, dword ptr arg(3) ;[recon_stride]
+
+        ; Row 1
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+
+
+        ; Row 2
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+
+        ; Row 3
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+
+        ; Row 4
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        paddd       mm7, mm0                    ; accumulate in mm7
+
+
+        ; Now accumulate the final results.
+        movq        QWORD PTR [rsp+8], mm5      ; copy back accumulated results into normal memory
+        movq        QWORD PTR [rsp], mm7        ; copy back accumulated results into normal memory
+        movsx       rdx, WORD PTR [rsp+8]
+        movsx       rcx, WORD PTR [rsp+10]
+        movsx       rbx, WORD PTR [rsp+12]
+        movsx       rax, WORD PTR [rsp+14]
+        add         rdx, rcx
+        add         rbx, rax
+        add         rdx, rbx    ;XSum
+        movsxd      rax, DWORD PTR [rsp]
+        movsxd      rcx, DWORD PTR [rsp+4]
+        add         rax, rcx    ;XXSum
+        mov         rsi, arg(4) ;SSE
+        mov         rdi, arg(5) ;Sum
+        mov         dword ptr [rsi], eax
+        mov         dword ptr [rdi], edx
+        xor         rax, rax    ; return 0
+
+
+    ; begin epilog
+    add rsp, 16
+    pop rbx
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+
+;unsigned int
+;vp8_get4x4sse_cs_mmx
+;(
+;    unsigned char *src_ptr,
+;    int  source_stride,
+;    unsigned char *ref_ptr,
+;    int  recon_stride
+;)
+global sym(vp8_get4x4sse_cs_mmx)
+sym(vp8_get4x4sse_cs_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push rsi
+    push rdi
+    push rbx
+    ; end prolog
+
+
+        pxor        mm6, mm6                    ; Blank mmx7
+        pxor        mm7, mm7                    ; Blank mmx7
+
+        mov         rax, arg(0) ;[src_ptr]  ; Load base addresses
+        mov         rbx, arg(2) ;[ref_ptr]
+        movsxd      rcx, dword ptr arg(1) ;[source_stride]
+        movsxd      rdx, dword ptr arg(3) ;[recon_stride]
+        ; Row 1
+        movd        mm0, [rax]                  ; Copy eight bytes to mm0
+        movd        mm1, [rbx]                  ; Copy eight bytes to mm1
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movd        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+
+        ; Row 2
+        movd        mm0, [rax]                  ; Copy eight bytes to mm0
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movd        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+
+        ; Row 3
+        movd        mm0, [rax]                  ; Copy eight bytes to mm0
+        punpcklbw   mm1, mm6
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movd        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+
+        ; Row 4
+        movd        mm0, [rax]                  ; Copy eight bytes to mm0
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        paddd       mm7, mm0                    ; accumulate in mm7
+
+        movq        mm0,    mm7                 ;
+        psrlq       mm7,    32
+
+        paddd       mm0,    mm7
+        movq        rax,    mm0
+
+
+    ; begin epilog
+    pop rbx
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+%define mmx_filter_shift            7
+
+;void vp8_filter_block2d_bil4x4_var_mmx
+;(
+;    unsigned char *ref_ptr,
+;    int ref_pixels_per_line,
+;    unsigned char *src_ptr,
+;    int src_pixels_per_line,
+;    unsigned short *HFilter,
+;    unsigned short *VFilter,
+;    int *sum,
+;    unsigned int *sumsquared
+;)
+global sym(vp8_filter_block2d_bil4x4_var_mmx)
+sym(vp8_filter_block2d_bil4x4_var_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 8
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    sub         rsp, 16
+    ; end prolog
+
+
+        pxor            mm6,            mm6                 ;
+        pxor            mm7,            mm7                 ;
+
+        mov             rax,            arg(4) ;HFilter             ;
+        mov             rdx,            arg(5) ;VFilter             ;
+
+        mov             rsi,            arg(0) ;ref_ptr              ;
+        mov             rdi,            arg(2) ;src_ptr              ;
+
+        mov             rcx,            4                   ;
+        pxor            mm0,            mm0                 ;
+
+        movd            mm1,            [rsi]               ;
+        movd            mm3,            [rsi+1]             ;
+
+        punpcklbw       mm1,            mm0                 ;
+        pmullw          mm1,            [rax]               ;
+
+        punpcklbw       mm3,            mm0                 ;
+        pmullw          mm3,            [rax+8]             ;
+
+        paddw           mm1,            mm3                 ;
+        paddw           mm1,            [GLOBAL(mmx_bi_rd)] ;
+
+        psraw           mm1,            mmx_filter_shift    ;
+        movq            mm5,            mm1
+
+%if ABI_IS_32BIT
+        add             rsi, dword ptr  arg(1) ;ref_pixels_per_line    ;
+%else
+        movsxd          r8, dword ptr  arg(1) ;ref_pixels_per_line    ;
+        add             rsi, r8
+%endif
+
+.filter_block2d_bil4x4_var_mmx_loop:
+
+        movd            mm1,            [rsi]               ;
+        movd            mm3,            [rsi+1]             ;
+
+        punpcklbw       mm1,            mm0                 ;
+        pmullw          mm1,            [rax]               ;
+
+        punpcklbw       mm3,            mm0                 ;
+        pmullw          mm3,            [rax+8]             ;
+
+        paddw           mm1,            mm3                 ;
+        paddw           mm1,            [GLOBAL(mmx_bi_rd)] ;
+
+        psraw           mm1,            mmx_filter_shift    ;
+        movq            mm3,            mm5                 ;
+
+        movq            mm5,            mm1                 ;
+        pmullw          mm3,            [rdx]               ;
+
+        pmullw          mm1,            [rdx+8]             ;
+        paddw           mm1,            mm3                 ;
+
+
+        paddw           mm1,            [GLOBAL(mmx_bi_rd)] ;
+        psraw           mm1,            mmx_filter_shift    ;
+
+        movd            mm3,            [rdi]               ;
+        punpcklbw       mm3,            mm0                 ;
+
+        psubw           mm1,            mm3                 ;
+        paddw           mm6,            mm1                 ;
+
+        pmaddwd         mm1,            mm1                 ;
+        paddd           mm7,            mm1                 ;
+
+%if ABI_IS_32BIT
+        add             rsi,            dword ptr arg(1) ;ref_pixels_per_line    ;
+        add             rdi,            dword ptr arg(3) ;src_pixels_per_line    ;
+%else
+        movsxd          r8,             dword ptr arg(1) ;ref_pixels_per_line
+        movsxd          r9,             dword ptr arg(3) ;src_pixels_per_line
+        add             rsi,            r8
+        add             rdi,            r9
+%endif
+        sub             rcx,            1                   ;
+        jnz             .filter_block2d_bil4x4_var_mmx_loop       ;
+
+
+        pxor            mm3,            mm3                 ;
+        pxor            mm2,            mm2                 ;
+
+        punpcklwd       mm2,            mm6                 ;
+        punpckhwd       mm3,            mm6                 ;
+
+        paddd           mm2,            mm3                 ;
+        movq            mm6,            mm2                 ;
+
+        psrlq           mm6,            32                  ;
+        paddd           mm2,            mm6                 ;
+
+        psrad           mm2,            16                  ;
+        movq            mm4,            mm7                 ;
+
+        psrlq           mm4,            32                  ;
+        paddd           mm4,            mm7                 ;
+
+        mov             rdi,            arg(6) ;sum
+        mov             rsi,            arg(7) ;sumsquared
+
+        movd            dword ptr [rdi],          mm2                 ;
+        movd            dword ptr [rsi],          mm4                 ;
+
+
+
+    ; begin epilog
+    add rsp, 16
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+
+
+;void vp8_filter_block2d_bil_var_mmx
+;(
+;    unsigned char *ref_ptr,
+;    int ref_pixels_per_line,
+;    unsigned char *src_ptr,
+;    int src_pixels_per_line,
+;    unsigned int Height,
+;    unsigned short *HFilter,
+;    unsigned short *VFilter,
+;    int *sum,
+;    unsigned int *sumsquared
+;)
+global sym(vp8_filter_block2d_bil_var_mmx)
+sym(vp8_filter_block2d_bil_var_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 9
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    sub         rsp, 16
+    ; end prolog
+
+        pxor            mm6,            mm6                 ;
+        pxor            mm7,            mm7                 ;
+        mov             rax,            arg(5) ;HFilter             ;
+
+        mov             rdx,            arg(6) ;VFilter             ;
+        mov             rsi,            arg(0) ;ref_ptr              ;
+
+        mov             rdi,            arg(2) ;src_ptr              ;
+        movsxd          rcx,            dword ptr arg(4) ;Height              ;
+
+        pxor            mm0,            mm0                 ;
+        movq            mm1,            [rsi]               ;
+
+        movq            mm3,            [rsi+1]             ;
+        movq            mm2,            mm1                 ;
+
+        movq            mm4,            mm3                 ;
+        punpcklbw       mm1,            mm0                 ;
+
+        punpckhbw       mm2,            mm0                 ;
+        pmullw          mm1,            [rax]               ;
+
+        pmullw          mm2,            [rax]               ;
+        punpcklbw       mm3,            mm0                 ;
+
+        punpckhbw       mm4,            mm0                 ;
+        pmullw          mm3,            [rax+8]             ;
+
+        pmullw          mm4,            [rax+8]             ;
+        paddw           mm1,            mm3                 ;
+
+        paddw           mm2,            mm4                 ;
+        paddw           mm1,            [GLOBAL(mmx_bi_rd)] ;
+
+        psraw           mm1,            mmx_filter_shift    ;
+        paddw           mm2,            [GLOBAL(mmx_bi_rd)] ;
+
+        psraw           mm2,            mmx_filter_shift    ;
+        movq            mm5,            mm1
+
+        packuswb        mm5,            mm2                 ;
+%if ABI_IS_32BIT
+        add             rsi,            dword ptr arg(1) ;ref_pixels_per_line
+%else
+        movsxd          r8,             dword ptr arg(1) ;ref_pixels_per_line
+        add             rsi,            r8
+%endif
+
+.filter_block2d_bil_var_mmx_loop:
+
+        movq            mm1,            [rsi]               ;
+        movq            mm3,            [rsi+1]             ;
+
+        movq            mm2,            mm1                 ;
+        movq            mm4,            mm3                 ;
+
+        punpcklbw       mm1,            mm0                 ;
+        punpckhbw       mm2,            mm0                 ;
+
+        pmullw          mm1,            [rax]               ;
+        pmullw          mm2,            [rax]               ;
+
+        punpcklbw       mm3,            mm0                 ;
+        punpckhbw       mm4,            mm0                 ;
+
+        pmullw          mm3,            [rax+8]             ;
+        pmullw          mm4,            [rax+8]             ;
+
+        paddw           mm1,            mm3                 ;
+        paddw           mm2,            mm4                 ;
+
+        paddw           mm1,            [GLOBAL(mmx_bi_rd)] ;
+        psraw           mm1,            mmx_filter_shift    ;
+
+        paddw           mm2,            [GLOBAL(mmx_bi_rd)] ;
+        psraw           mm2,            mmx_filter_shift    ;
+
+        movq            mm3,            mm5                 ;
+        movq            mm4,            mm5                 ;
+
+        punpcklbw       mm3,            mm0                 ;
+        punpckhbw       mm4,            mm0                 ;
+
+        movq            mm5,            mm1                 ;
+        packuswb        mm5,            mm2                 ;
+
+        pmullw          mm3,            [rdx]               ;
+        pmullw          mm4,            [rdx]               ;
+
+        pmullw          mm1,            [rdx+8]             ;
+        pmullw          mm2,            [rdx+8]             ;
+
+        paddw           mm1,            mm3                 ;
+        paddw           mm2,            mm4                 ;
+
+        paddw           mm1,            [GLOBAL(mmx_bi_rd)] ;
+        paddw           mm2,            [GLOBAL(mmx_bi_rd)] ;
+
+        psraw           mm1,            mmx_filter_shift    ;
+        psraw           mm2,            mmx_filter_shift    ;
+
+        movq            mm3,            [rdi]               ;
+        movq            mm4,            mm3                 ;
+
+        punpcklbw       mm3,            mm0                 ;
+        punpckhbw       mm4,            mm0                 ;
+
+        psubw           mm1,            mm3                 ;
+        psubw           mm2,            mm4                 ;
+
+        paddw           mm6,            mm1                 ;
+        pmaddwd         mm1,            mm1                 ;
+
+        paddw           mm6,            mm2                 ;
+        pmaddwd         mm2,            mm2                 ;
+
+        paddd           mm7,            mm1                 ;
+        paddd           mm7,            mm2                 ;
+
+%if ABI_IS_32BIT
+        add             rsi,            dword ptr arg(1) ;ref_pixels_per_line    ;
+        add             rdi,            dword ptr arg(3) ;src_pixels_per_line    ;
+%else
+        movsxd          r8,             dword ptr arg(1) ;ref_pixels_per_line    ;
+        movsxd          r9,             dword ptr arg(3) ;src_pixels_per_line    ;
+        add             rsi,            r8
+        add             rdi,            r9
+%endif
+        sub             rcx,            1                   ;
+        jnz             .filter_block2d_bil_var_mmx_loop       ;
+
+
+        pxor            mm3,            mm3                 ;
+        pxor            mm2,            mm2                 ;
+
+        punpcklwd       mm2,            mm6                 ;
+        punpckhwd       mm3,            mm6                 ;
+
+        paddd           mm2,            mm3                 ;
+        movq            mm6,            mm2                 ;
+
+        psrlq           mm6,            32                  ;
+        paddd           mm2,            mm6                 ;
+
+        psrad           mm2,            16                  ;
+        movq            mm4,            mm7                 ;
+
+        psrlq           mm4,            32                  ;
+        paddd           mm4,            mm7                 ;
+
+        mov             rdi,            arg(7) ;sum
+        mov             rsi,            arg(8) ;sumsquared
+
+        movd            dword ptr [rdi],          mm2                 ;
+        movd            dword ptr [rsi],          mm4                 ;
+
+    ; begin epilog
+    add rsp, 16
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+SECTION_RODATA
+;short mmx_bi_rd[4] = { 64, 64, 64, 64};
+align 16
+mmx_bi_rd:
+    times 4 dw 64
diff --git a/vp8/common/x86/variance_impl_sse2.asm b/vp8/common/x86/variance_impl_sse2.asm
new file mode 100644 (file)
index 0000000..7629220
--- /dev/null
@@ -0,0 +1,1359 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+%define xmm_filter_shift            7
+
+;unsigned int vp8_get_mb_ss_sse2
+;(
+;    short *src_ptr
+;)
+global sym(vp8_get_mb_ss_sse2)
+sym(vp8_get_mb_ss_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 1
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    sub         rsp, 16
+    ; end prolog
+
+
+        mov         rax, arg(0) ;[src_ptr]
+        mov         rcx, 8
+        pxor        xmm4, xmm4
+
+.NEXTROW:
+        movdqa      xmm0, [rax]
+        movdqa      xmm1, [rax+16]
+        movdqa      xmm2, [rax+32]
+        movdqa      xmm3, [rax+48]
+        pmaddwd     xmm0, xmm0
+        pmaddwd     xmm1, xmm1
+        pmaddwd     xmm2, xmm2
+        pmaddwd     xmm3, xmm3
+
+        paddd       xmm0, xmm1
+        paddd       xmm2, xmm3
+        paddd       xmm4, xmm0
+        paddd       xmm4, xmm2
+
+        add         rax, 0x40
+        dec         rcx
+        ja          .NEXTROW
+
+        movdqa      xmm3,xmm4
+        psrldq      xmm4,8
+        paddd       xmm4,xmm3
+        movdqa      xmm3,xmm4
+        psrldq      xmm4,4
+        paddd       xmm4,xmm3
+        movq        rax,xmm4
+
+
+    ; begin epilog
+    add rsp, 16
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;unsigned int vp8_get16x16var_sse2
+;(
+;    unsigned char   *  src_ptr,
+;    int             source_stride,
+;    unsigned char   *  ref_ptr,
+;    int             recon_stride,
+;    unsigned int    *  SSE,
+;    int             *  Sum
+;)
+global sym(vp8_get16x16var_sse2)
+sym(vp8_get16x16var_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    SAVE_XMM 7
+    push rbx
+    push rsi
+    push rdi
+    ; end prolog
+
+        mov         rsi,            arg(0) ;[src_ptr]
+        mov         rdi,            arg(2) ;[ref_ptr]
+
+        movsxd      rax,            DWORD PTR arg(1) ;[source_stride]
+        movsxd      rdx,            DWORD PTR arg(3) ;[recon_stride]
+
+        ; Prefetch data
+        lea             rcx,    [rax+rax*2]
+        prefetcht0      [rsi]
+        prefetcht0      [rsi+rax]
+        prefetcht0      [rsi+rax*2]
+        prefetcht0      [rsi+rcx]
+        lea             rbx,    [rsi+rax*4]
+        prefetcht0      [rbx]
+        prefetcht0      [rbx+rax]
+        prefetcht0      [rbx+rax*2]
+        prefetcht0      [rbx+rcx]
+
+        lea             rcx,    [rdx+rdx*2]
+        prefetcht0      [rdi]
+        prefetcht0      [rdi+rdx]
+        prefetcht0      [rdi+rdx*2]
+        prefetcht0      [rdi+rcx]
+        lea             rbx,    [rdi+rdx*4]
+        prefetcht0      [rbx]
+        prefetcht0      [rbx+rdx]
+        prefetcht0      [rbx+rdx*2]
+        prefetcht0      [rbx+rcx]
+
+        pxor        xmm0,           xmm0                        ; clear xmm0 for unpack
+        pxor        xmm7,           xmm7                        ; clear xmm7 for accumulating diffs
+
+        pxor        xmm6,           xmm6                        ; clear xmm6 for accumulating sse
+        mov         rcx,            16
+
+.var16loop:
+        movdqu      xmm1,           XMMWORD PTR [rsi]
+        movdqu      xmm2,           XMMWORD PTR [rdi]
+
+        prefetcht0      [rsi+rax*8]
+        prefetcht0      [rdi+rdx*8]
+
+        movdqa      xmm3,           xmm1
+        movdqa      xmm4,           xmm2
+
+
+        punpcklbw   xmm1,           xmm0
+        punpckhbw   xmm3,           xmm0
+
+        punpcklbw   xmm2,           xmm0
+        punpckhbw   xmm4,           xmm0
+
+
+        psubw       xmm1,           xmm2
+        psubw       xmm3,           xmm4
+
+        paddw       xmm7,           xmm1
+        pmaddwd     xmm1,           xmm1
+
+        paddw       xmm7,           xmm3
+        pmaddwd     xmm3,           xmm3
+
+        paddd       xmm6,           xmm1
+        paddd       xmm6,           xmm3
+
+        add         rsi,            rax
+        add         rdi,            rdx
+
+        sub         rcx,            1
+        jnz         .var16loop
+
+
+        movdqa      xmm1,           xmm6
+        pxor        xmm6,           xmm6
+
+        pxor        xmm5,           xmm5
+        punpcklwd   xmm6,           xmm7
+
+        punpckhwd   xmm5,           xmm7
+        psrad       xmm5,           16
+
+        psrad       xmm6,           16
+        paddd       xmm6,           xmm5
+
+        movdqa      xmm2,           xmm1
+        punpckldq   xmm1,           xmm0
+
+        punpckhdq   xmm2,           xmm0
+        movdqa      xmm7,           xmm6
+
+        paddd       xmm1,           xmm2
+        punpckldq   xmm6,           xmm0
+
+        punpckhdq   xmm7,           xmm0
+        paddd       xmm6,           xmm7
+
+        movdqa      xmm2,           xmm1
+        movdqa      xmm7,           xmm6
+
+        psrldq      xmm1,           8
+        psrldq      xmm6,           8
+
+        paddd       xmm7,           xmm6
+        paddd       xmm1,           xmm2
+
+        mov         rax,            arg(5) ;[Sum]
+        mov         rdi,            arg(4) ;[SSE]
+
+        movd DWORD PTR [rax],       xmm7
+        movd DWORD PTR [rdi],       xmm1
+
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    pop rbx
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+
+
+;unsigned int vp8_get8x8var_sse2
+;(
+;    unsigned char   *  src_ptr,
+;    int             source_stride,
+;    unsigned char   *  ref_ptr,
+;    int             recon_stride,
+;    unsigned int    *  SSE,
+;    int             *  Sum
+;)
+global sym(vp8_get8x8var_sse2)
+sym(vp8_get8x8var_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    sub         rsp, 16
+    ; end prolog
+
+        mov         rsi,            arg(0) ;[src_ptr]
+        mov         rdi,            arg(2) ;[ref_ptr]
+
+        movsxd      rax,            DWORD PTR arg(1) ;[source_stride]
+        movsxd      rdx,            DWORD PTR arg(3) ;[recon_stride]
+
+        pxor        xmm0,           xmm0                        ; clear xmm0 for unpack
+        pxor        xmm7,           xmm7                        ; clear xmm7 for accumulating diffs
+
+        movq        xmm1,           QWORD PTR [rsi]
+        movq        xmm2,           QWORD PTR [rdi]
+
+        punpcklbw   xmm1,           xmm0
+        punpcklbw   xmm2,           xmm0
+
+        psubsw      xmm1,           xmm2
+        paddw       xmm7,           xmm1
+
+        pmaddwd     xmm1,           xmm1
+
+        movq        xmm2,           QWORD PTR[rsi + rax]
+        movq        xmm3,           QWORD PTR[rdi + rdx]
+
+        punpcklbw   xmm2,           xmm0
+        punpcklbw   xmm3,           xmm0
+
+        psubsw      xmm2,           xmm3
+        paddw       xmm7,           xmm2
+
+        pmaddwd     xmm2,           xmm2
+        paddd       xmm1,           xmm2
+
+
+        movq        xmm2,           QWORD PTR[rsi + rax * 2]
+        movq        xmm3,           QWORD PTR[rdi + rdx * 2]
+
+        punpcklbw   xmm2,           xmm0
+        punpcklbw   xmm3,           xmm0
+
+        psubsw      xmm2,           xmm3
+        paddw       xmm7,           xmm2
+
+        pmaddwd     xmm2,           xmm2
+        paddd       xmm1,           xmm2
+
+
+        lea         rsi,            [rsi + rax * 2]
+        lea         rdi,            [rdi + rdx * 2]
+        movq        xmm2,           QWORD PTR[rsi + rax]
+        movq        xmm3,           QWORD PTR[rdi + rdx]
+
+        punpcklbw   xmm2,           xmm0
+        punpcklbw   xmm3,           xmm0
+
+        psubsw      xmm2,           xmm3
+        paddw       xmm7,           xmm2
+
+        pmaddwd     xmm2,           xmm2
+        paddd       xmm1,           xmm2
+
+        movq        xmm2,           QWORD PTR[rsi + rax *2]
+        movq        xmm3,           QWORD PTR[rdi + rdx *2]
+
+        punpcklbw   xmm2,           xmm0
+        punpcklbw   xmm3,           xmm0
+
+        psubsw      xmm2,           xmm3
+        paddw       xmm7,           xmm2
+
+        pmaddwd     xmm2,           xmm2
+        paddd       xmm1,           xmm2
+
+
+        lea         rsi,            [rsi + rax * 2]
+        lea         rdi,            [rdi + rdx * 2]
+
+
+        movq        xmm2,           QWORD PTR[rsi + rax]
+        movq        xmm3,           QWORD PTR[rdi + rdx]
+
+        punpcklbw   xmm2,           xmm0
+        punpcklbw   xmm3,           xmm0
+
+        psubsw      xmm2,           xmm3
+        paddw       xmm7,           xmm2
+
+        pmaddwd     xmm2,           xmm2
+        paddd       xmm1,           xmm2
+
+        movq        xmm2,           QWORD PTR[rsi + rax *2]
+        movq        xmm3,           QWORD PTR[rdi + rdx *2]
+
+        punpcklbw   xmm2,           xmm0
+        punpcklbw   xmm3,           xmm0
+
+        psubsw      xmm2,           xmm3
+        paddw       xmm7,           xmm2
+
+        pmaddwd     xmm2,           xmm2
+        paddd       xmm1,           xmm2
+
+
+        lea         rsi,            [rsi + rax * 2]
+        lea         rdi,            [rdi + rdx * 2]
+
+        movq        xmm2,           QWORD PTR[rsi + rax]
+        movq        xmm3,           QWORD PTR[rdi + rdx]
+
+        punpcklbw   xmm2,           xmm0
+        punpcklbw   xmm3,           xmm0
+
+        psubsw      xmm2,           xmm3
+        paddw       xmm7,           xmm2
+
+        pmaddwd     xmm2,           xmm2
+        paddd       xmm1,           xmm2
+
+
+        movdqa      xmm6,           xmm7
+        punpcklwd   xmm6,           xmm0
+
+        punpckhwd   xmm7,           xmm0
+        movdqa      xmm2,           xmm1
+
+        paddw       xmm6,           xmm7
+        punpckldq   xmm1,           xmm0
+
+        punpckhdq   xmm2,           xmm0
+        movdqa      xmm7,           xmm6
+
+        paddd       xmm1,           xmm2
+        punpckldq   xmm6,           xmm0
+
+        punpckhdq   xmm7,           xmm0
+        paddw       xmm6,           xmm7
+
+        movdqa      xmm2,           xmm1
+        movdqa      xmm7,           xmm6
+
+        psrldq      xmm1,           8
+        psrldq      xmm6,           8
+
+        paddw       xmm7,           xmm6
+        paddd       xmm1,           xmm2
+
+        mov         rax,            arg(5) ;[Sum]
+        mov         rdi,            arg(4) ;[SSE]
+
+        movq        rdx,            xmm7
+        movsx       rcx,            dx
+
+        mov  dword ptr [rax],       ecx
+        movd DWORD PTR [rdi],       xmm1
+
+    ; begin epilog
+    add rsp, 16
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_filter_block2d_bil_var_sse2
+;(
+;    unsigned char *ref_ptr,
+;    int ref_pixels_per_line,
+;    unsigned char *src_ptr,
+;    int src_pixels_per_line,
+;    unsigned int Height,
+;    int  xoffset,
+;    int  yoffset,
+;    int *sum,
+;    unsigned int *sumsquared;;
+;
+;)
+global sym(vp8_filter_block2d_bil_var_sse2)
+sym(vp8_filter_block2d_bil_var_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 9
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    push rbx
+    ; end prolog
+
+        pxor            xmm6,           xmm6                 ;
+        pxor            xmm7,           xmm7                 ;
+
+        lea             rsi,            [GLOBAL(xmm_bi_rd)]  ; rounding
+        movdqa          xmm4,           XMMWORD PTR [rsi]
+
+        lea             rcx,            [GLOBAL(vp8_bilinear_filters_sse2)]
+        movsxd          rax,            dword ptr arg(5)     ; xoffset
+
+        cmp             rax,            0                    ; skip first_pass filter if xoffset=0
+        je              filter_block2d_bil_var_sse2_sp_only
+
+        shl             rax,            5                    ; point to filter coeff with xoffset
+        lea             rax,            [rax + rcx]          ; HFilter
+
+        movsxd          rdx,            dword ptr arg(6)     ; yoffset
+
+        cmp             rdx,            0                    ; skip second_pass filter if yoffset=0
+        je              filter_block2d_bil_var_sse2_fp_only
+
+        shl             rdx,            5
+        lea             rdx,            [rdx + rcx]          ; VFilter
+
+        mov             rsi,            arg(0)               ;ref_ptr
+        mov             rdi,            arg(2)               ;src_ptr
+        movsxd          rcx,            dword ptr arg(4)     ;Height
+
+        pxor            xmm0,           xmm0                 ;
+        movq            xmm1,           QWORD PTR [rsi]      ;
+        movq            xmm3,           QWORD PTR [rsi+1]    ;
+
+        punpcklbw       xmm1,           xmm0                 ;
+        pmullw          xmm1,           [rax]                ;
+        punpcklbw       xmm3,           xmm0
+        pmullw          xmm3,           [rax+16]             ;
+
+        paddw           xmm1,           xmm3                 ;
+        paddw           xmm1,           xmm4                 ;
+        psraw           xmm1,           xmm_filter_shift     ;
+        movdqa          xmm5,           xmm1
+
+        movsxd          rbx,            dword ptr arg(1) ;ref_pixels_per_line
+        lea             rsi,            [rsi + rbx]
+%if ABI_IS_32BIT=0
+        movsxd          r9,             dword ptr arg(3) ;src_pixels_per_line
+%endif
+
+filter_block2d_bil_var_sse2_loop:
+        movq            xmm1,           QWORD PTR [rsi]               ;
+        movq            xmm3,           QWORD PTR [rsi+1]             ;
+
+        punpcklbw       xmm1,           xmm0                 ;
+        pmullw          xmm1,           [rax]               ;
+        punpcklbw       xmm3,           xmm0                 ;
+        pmullw          xmm3,           [rax+16]             ;
+
+        paddw           xmm1,           xmm3                 ;
+        paddw           xmm1,           xmm4               ;
+        psraw           xmm1,           xmm_filter_shift    ;
+
+        movdqa          xmm3,           xmm5                 ;
+        movdqa          xmm5,           xmm1                 ;
+
+        pmullw          xmm3,           [rdx]               ;
+        pmullw          xmm1,           [rdx+16]             ;
+        paddw           xmm1,           xmm3                 ;
+        paddw           xmm1,           xmm4                 ;
+        psraw           xmm1,           xmm_filter_shift    ;
+
+        movq            xmm3,           QWORD PTR [rdi]               ;
+        punpcklbw       xmm3,           xmm0                 ;
+
+        psubw           xmm1,           xmm3                 ;
+        paddw           xmm6,           xmm1                 ;
+
+        pmaddwd         xmm1,           xmm1                 ;
+        paddd           xmm7,           xmm1                 ;
+
+        lea             rsi,            [rsi + rbx]          ;ref_pixels_per_line
+%if ABI_IS_32BIT
+        add             rdi,            dword ptr arg(3)     ;src_pixels_per_line
+%else
+        lea             rdi,            [rdi + r9]
+%endif
+
+        sub             rcx,            1                   ;
+        jnz             filter_block2d_bil_var_sse2_loop       ;
+
+        jmp             filter_block2d_bil_variance
+
+filter_block2d_bil_var_sse2_sp_only:
+        movsxd          rdx,            dword ptr arg(6)     ; yoffset
+
+        cmp             rdx,            0                    ; skip all if both xoffset=0 and yoffset=0
+        je              filter_block2d_bil_var_sse2_full_pixel
+
+        shl             rdx,            5
+        lea             rdx,            [rdx + rcx]          ; VFilter
+
+        mov             rsi,            arg(0)               ;ref_ptr
+        mov             rdi,            arg(2)               ;src_ptr
+        movsxd          rcx,            dword ptr arg(4)     ;Height
+        movsxd          rax,            dword ptr arg(1)     ;ref_pixels_per_line
+
+        pxor            xmm0,           xmm0                 ;
+        movq            xmm1,           QWORD PTR [rsi]      ;
+        punpcklbw       xmm1,           xmm0                 ;
+
+        movsxd          rbx,            dword ptr arg(3)     ;src_pixels_per_line
+        lea             rsi,            [rsi + rax]
+
+filter_block2d_bil_sp_only_loop:
+        movq            xmm3,           QWORD PTR [rsi]             ;
+        punpcklbw       xmm3,           xmm0                 ;
+        movdqa          xmm5,           xmm3
+
+        pmullw          xmm1,           [rdx]               ;
+        pmullw          xmm3,           [rdx+16]             ;
+        paddw           xmm1,           xmm3                 ;
+        paddw           xmm1,           xmm4                 ;
+        psraw           xmm1,           xmm_filter_shift    ;
+
+        movq            xmm3,           QWORD PTR [rdi]               ;
+        punpcklbw       xmm3,           xmm0                 ;
+
+        psubw           xmm1,           xmm3                 ;
+        paddw           xmm6,           xmm1                 ;
+
+        pmaddwd         xmm1,           xmm1                 ;
+        paddd           xmm7,           xmm1                 ;
+
+        movdqa          xmm1,           xmm5                 ;
+        lea             rsi,            [rsi + rax]          ;ref_pixels_per_line
+        lea             rdi,            [rdi + rbx]          ;src_pixels_per_line
+
+        sub             rcx,            1                   ;
+        jnz             filter_block2d_bil_sp_only_loop       ;
+
+        jmp             filter_block2d_bil_variance
+
+filter_block2d_bil_var_sse2_full_pixel:
+        mov             rsi,            arg(0)               ;ref_ptr
+        mov             rdi,            arg(2)               ;src_ptr
+        movsxd          rcx,            dword ptr arg(4)     ;Height
+        movsxd          rax,            dword ptr arg(1)     ;ref_pixels_per_line
+        movsxd          rbx,            dword ptr arg(3)     ;src_pixels_per_line
+        pxor            xmm0,           xmm0                 ;
+
+filter_block2d_bil_full_pixel_loop:
+        movq            xmm1,           QWORD PTR [rsi]               ;
+        punpcklbw       xmm1,           xmm0                 ;
+
+        movq            xmm2,           QWORD PTR [rdi]               ;
+        punpcklbw       xmm2,           xmm0                 ;
+
+        psubw           xmm1,           xmm2                 ;
+        paddw           xmm6,           xmm1                 ;
+
+        pmaddwd         xmm1,           xmm1                 ;
+        paddd           xmm7,           xmm1                 ;
+
+        lea             rsi,            [rsi + rax]          ;ref_pixels_per_line
+        lea             rdi,            [rdi + rbx]          ;src_pixels_per_line
+
+        sub             rcx,            1                   ;
+        jnz             filter_block2d_bil_full_pixel_loop       ;
+
+        jmp             filter_block2d_bil_variance
+
+filter_block2d_bil_var_sse2_fp_only:
+        mov             rsi,            arg(0)               ;ref_ptr
+        mov             rdi,            arg(2)               ;src_ptr
+        movsxd          rcx,            dword ptr arg(4)     ;Height
+        movsxd          rdx,            dword ptr arg(1)     ;ref_pixels_per_line
+
+        pxor            xmm0,           xmm0                 ;
+        movsxd          rbx,            dword ptr arg(3)     ;src_pixels_per_line
+
+filter_block2d_bil_fp_only_loop:
+        movq            xmm1,           QWORD PTR [rsi]       ;
+        movq            xmm3,           QWORD PTR [rsi+1]     ;
+
+        punpcklbw       xmm1,           xmm0                 ;
+        pmullw          xmm1,           [rax]               ;
+        punpcklbw       xmm3,           xmm0                 ;
+        pmullw          xmm3,           [rax+16]             ;
+
+        paddw           xmm1,           xmm3                 ;
+        paddw           xmm1,           xmm4  ;
+        psraw           xmm1,           xmm_filter_shift    ;
+
+        movq            xmm3,           QWORD PTR [rdi]     ;
+        punpcklbw       xmm3,           xmm0                 ;
+
+        psubw           xmm1,           xmm3                 ;
+        paddw           xmm6,           xmm1                 ;
+
+        pmaddwd         xmm1,           xmm1                 ;
+        paddd           xmm7,           xmm1                 ;
+        lea             rsi,            [rsi + rdx]
+        lea             rdi,            [rdi + rbx]          ;src_pixels_per_line
+
+        sub             rcx,            1                   ;
+        jnz             filter_block2d_bil_fp_only_loop       ;
+
+        jmp             filter_block2d_bil_variance
+
+filter_block2d_bil_variance:
+        movdq2q         mm6,            xmm6                ;
+        movdq2q         mm7,            xmm7                ;
+
+        psrldq          xmm6,           8
+        psrldq          xmm7,           8
+
+        movdq2q         mm2,            xmm6
+        movdq2q         mm3,            xmm7
+
+        paddw           mm6,            mm2
+        paddd           mm7,            mm3
+
+        pxor            mm3,            mm3                 ;
+        pxor            mm2,            mm2                 ;
+
+        punpcklwd       mm2,            mm6                 ;
+        punpckhwd       mm3,            mm6                 ;
+
+        paddd           mm2,            mm3                 ;
+        movq            mm6,            mm2                 ;
+
+        psrlq           mm6,            32                  ;
+        paddd           mm2,            mm6                 ;
+
+        psrad           mm2,            16                  ;
+        movq            mm4,            mm7                 ;
+
+        psrlq           mm4,            32                  ;
+        paddd           mm4,            mm7                 ;
+
+        mov             rsi,            arg(7) ; sum
+        mov             rdi,            arg(8) ; sumsquared
+
+        movd            [rsi],          mm2    ; xsum
+        movd            [rdi],          mm4    ; xxsum
+
+    ; begin epilog
+    pop rbx
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_half_horiz_vert_variance8x_h_sse2
+;(
+;    unsigned char *ref_ptr,
+;    int ref_pixels_per_line,
+;    unsigned char *src_ptr,
+;    int src_pixels_per_line,
+;    unsigned int Height,
+;    int *sum,
+;    unsigned int *sumsquared
+;)
+global sym(vp8_half_horiz_vert_variance8x_h_sse2)
+sym(vp8_half_horiz_vert_variance8x_h_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    ; end prolog
+
+%if ABI_IS_32BIT=0
+    movsxd          r8, dword ptr arg(1) ;ref_pixels_per_line
+    movsxd          r9, dword ptr arg(3) ;src_pixels_per_line
+%endif
+
+        pxor            xmm6,           xmm6                ;  error accumulator
+        pxor            xmm7,           xmm7                ;  sse eaccumulator
+        mov             rsi,            arg(0) ;ref_ptr              ;
+
+        mov             rdi,            arg(2) ;src_ptr              ;
+        movsxd          rcx,            dword ptr arg(4) ;Height              ;
+        movsxd          rax,            dword ptr arg(1) ;ref_pixels_per_line
+
+        pxor            xmm0,           xmm0                ;
+
+        movq            xmm5,           QWORD PTR [rsi]     ;  xmm5 = s0,s1,s2..s8
+        movq            xmm3,           QWORD PTR [rsi+1]   ;  xmm3 = s1,s2,s3..s9
+        pavgb           xmm5,           xmm3                ;  xmm5 = avg(xmm1,xmm3) horizontal line 1
+
+%if ABI_IS_32BIT
+        add             rsi,            dword ptr arg(1) ;ref_pixels_per_line    ;  next source
+%else
+        add             rsi, r8
+%endif
+
+vp8_half_horiz_vert_variance8x_h_1:
+
+        movq            xmm1,           QWORD PTR [rsi]     ;
+        movq            xmm2,           QWORD PTR [rsi+1]   ;
+        pavgb           xmm1,           xmm2                ;  xmm1 = avg(xmm1,xmm3) horizontal line i+1
+
+        pavgb           xmm5,           xmm1                ;  xmm = vertical average of the above
+        punpcklbw       xmm5,           xmm0                ;  xmm5 = words of above
+
+        movq            xmm3,           QWORD PTR [rdi]     ;  xmm3 = d0,d1,d2..d8
+        punpcklbw       xmm3,           xmm0                ;  xmm3 = words of above
+
+        psubw           xmm5,           xmm3                ;  xmm5 -= xmm3
+        paddw           xmm6,           xmm5                ;  xmm6 += accumulated column differences
+        pmaddwd         xmm5,           xmm5                ;  xmm5 *= xmm5
+        paddd           xmm7,           xmm5                ;  xmm7 += accumulated square column differences
+
+        movdqa          xmm5,           xmm1                ;  save xmm1 for use on the next row
+
+%if ABI_IS_32BIT
+        add             esi,            dword ptr arg(1) ;ref_pixels_per_line    ;  next source
+        add             edi,            dword ptr arg(3) ;src_pixels_per_line    ;  next destination
+%else
+        add             rsi, r8
+        add             rdi, r9
+%endif
+
+        sub             rcx,            1                   ;
+        jnz             vp8_half_horiz_vert_variance8x_h_1     ;
+
+        movdq2q         mm6,            xmm6                ;
+        movdq2q         mm7,            xmm7                ;
+
+        psrldq          xmm6,           8
+        psrldq          xmm7,           8
+
+        movdq2q         mm2,            xmm6
+        movdq2q         mm3,            xmm7
+
+        paddw           mm6,            mm2
+        paddd           mm7,            mm3
+
+        pxor            mm3,            mm3                 ;
+        pxor            mm2,            mm2                 ;
+
+        punpcklwd       mm2,            mm6                 ;
+        punpckhwd       mm3,            mm6                 ;
+
+        paddd           mm2,            mm3                 ;
+        movq            mm6,            mm2                 ;
+
+        psrlq           mm6,            32                  ;
+        paddd           mm2,            mm6                 ;
+
+        psrad           mm2,            16                  ;
+        movq            mm4,            mm7                 ;
+
+        psrlq           mm4,            32                  ;
+        paddd           mm4,            mm7                 ;
+
+        mov             rsi,            arg(5) ; sum
+        mov             rdi,            arg(6) ; sumsquared
+
+        movd            [rsi],          mm2                 ;
+        movd            [rdi],          mm4                 ;
+
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_half_horiz_vert_variance16x_h_sse2
+;(
+;    unsigned char *ref_ptr,
+;    int ref_pixels_per_line,
+;    unsigned char *src_ptr,
+;    int src_pixels_per_line,
+;    unsigned int Height,
+;    int *sum,
+;    unsigned int *sumsquared
+;)
+global sym(vp8_half_horiz_vert_variance16x_h_sse2)
+sym(vp8_half_horiz_vert_variance16x_h_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    ; end prolog
+
+        pxor            xmm6,           xmm6                ;  error accumulator
+        pxor            xmm7,           xmm7                ;  sse eaccumulator
+        mov             rsi,            arg(0) ;ref_ptr              ;
+
+        mov             rdi,            arg(2) ;src_ptr              ;
+        movsxd          rcx,            dword ptr arg(4) ;Height              ;
+        movsxd          rax,            dword ptr arg(1) ;ref_pixels_per_line
+        movsxd          rdx,            dword ptr arg(3)    ;src_pixels_per_line
+
+        pxor            xmm0,           xmm0                ;
+
+        movdqu          xmm5,           XMMWORD PTR [rsi]
+        movdqu          xmm3,           XMMWORD PTR [rsi+1]
+        pavgb           xmm5,           xmm3                ;  xmm5 = avg(xmm1,xmm3) horizontal line 1
+
+        lea             rsi,            [rsi + rax]
+
+vp8_half_horiz_vert_variance16x_h_1:
+        movdqu          xmm1,           XMMWORD PTR [rsi]     ;
+        movdqu          xmm2,           XMMWORD PTR [rsi+1]   ;
+        pavgb           xmm1,           xmm2                ;  xmm1 = avg(xmm1,xmm3) horizontal line i+1
+
+        pavgb           xmm5,           xmm1                ;  xmm = vertical average of the above
+
+        movdqa          xmm4,           xmm5
+        punpcklbw       xmm5,           xmm0                ;  xmm5 = words of above
+        punpckhbw       xmm4,           xmm0
+
+        movq            xmm3,           QWORD PTR [rdi]     ;  xmm3 = d0,d1,d2..d7
+        punpcklbw       xmm3,           xmm0                ;  xmm3 = words of above
+        psubw           xmm5,           xmm3                ;  xmm5 -= xmm3
+
+        movq            xmm3,           QWORD PTR [rdi+8]
+        punpcklbw       xmm3,           xmm0
+        psubw           xmm4,           xmm3
+
+        paddw           xmm6,           xmm5                ;  xmm6 += accumulated column differences
+        paddw           xmm6,           xmm4
+        pmaddwd         xmm5,           xmm5                ;  xmm5 *= xmm5
+        pmaddwd         xmm4,           xmm4
+        paddd           xmm7,           xmm5                ;  xmm7 += accumulated square column differences
+        paddd           xmm7,           xmm4
+
+        movdqa          xmm5,           xmm1                ;  save xmm1 for use on the next row
+
+        lea             rsi,            [rsi + rax]
+        lea             rdi,            [rdi + rdx]
+
+        sub             rcx,            1                   ;
+        jnz             vp8_half_horiz_vert_variance16x_h_1     ;
+
+        pxor        xmm1,           xmm1
+        pxor        xmm5,           xmm5
+
+        punpcklwd   xmm0,           xmm6
+        punpckhwd   xmm1,           xmm6
+        psrad       xmm0,           16
+        psrad       xmm1,           16
+        paddd       xmm0,           xmm1
+        movdqa      xmm1,           xmm0
+
+        movdqa      xmm6,           xmm7
+        punpckldq   xmm6,           xmm5
+        punpckhdq   xmm7,           xmm5
+        paddd       xmm6,           xmm7
+
+        punpckldq   xmm0,           xmm5
+        punpckhdq   xmm1,           xmm5
+        paddd       xmm0,           xmm1
+
+        movdqa      xmm7,           xmm6
+        movdqa      xmm1,           xmm0
+
+        psrldq      xmm7,           8
+        psrldq      xmm1,           8
+
+        paddd       xmm6,           xmm7
+        paddd       xmm0,           xmm1
+
+        mov         rsi,            arg(5) ;[Sum]
+        mov         rdi,            arg(6) ;[SSE]
+
+        movd        [rsi],       xmm0
+        movd        [rdi],       xmm6
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_half_vert_variance8x_h_sse2
+;(
+;    unsigned char *ref_ptr,
+;    int ref_pixels_per_line,
+;    unsigned char *src_ptr,
+;    int src_pixels_per_line,
+;    unsigned int Height,
+;    int *sum,
+;    unsigned int *sumsquared
+;)
+global sym(vp8_half_vert_variance8x_h_sse2)
+sym(vp8_half_vert_variance8x_h_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    ; end prolog
+
+%if ABI_IS_32BIT=0
+    movsxd          r8, dword ptr arg(1) ;ref_pixels_per_line
+    movsxd          r9, dword ptr arg(3) ;src_pixels_per_line
+%endif
+
+        pxor            xmm6,           xmm6                ;  error accumulator
+        pxor            xmm7,           xmm7                ;  sse eaccumulator
+        mov             rsi,            arg(0) ;ref_ptr              ;
+
+        mov             rdi,            arg(2) ;src_ptr              ;
+        movsxd          rcx,            dword ptr arg(4) ;Height              ;
+        movsxd          rax,            dword ptr arg(1) ;ref_pixels_per_line
+
+        pxor            xmm0,           xmm0                ;
+vp8_half_vert_variance8x_h_1:
+        movq            xmm5,           QWORD PTR [rsi]     ;  xmm5 = s0,s1,s2..s8
+        movq            xmm3,           QWORD PTR [rsi+rax] ;  xmm3 = s1,s2,s3..s9
+
+        pavgb           xmm5,           xmm3                ;  xmm5 = avg(xmm1,xmm3)
+        punpcklbw       xmm5,           xmm0                ;  xmm5 = words of above
+
+        movq            xmm3,           QWORD PTR [rdi]     ;  xmm3 = d0,d1,d2..d8
+        punpcklbw       xmm3,           xmm0                ;  xmm3 = words of above
+
+        psubw           xmm5,           xmm3                ;  xmm5 -= xmm3
+        paddw           xmm6,           xmm5                ;  xmm6 += accumulated column differences
+        pmaddwd         xmm5,           xmm5                ;  xmm5 *= xmm5
+        paddd           xmm7,           xmm5                ;  xmm7 += accumulated square column differences
+
+%if ABI_IS_32BIT
+        add             esi,            dword ptr arg(1) ;ref_pixels_per_line    ;  next source
+        add             edi,            dword ptr arg(3) ;src_pixels_per_line    ;  next destination
+%else
+        add             rsi, r8
+        add             rdi, r9
+%endif
+
+        sub             rcx,            1                   ;
+        jnz             vp8_half_vert_variance8x_h_1          ;
+
+        movdq2q         mm6,            xmm6                ;
+        movdq2q         mm7,            xmm7                ;
+
+        psrldq          xmm6,           8
+        psrldq          xmm7,           8
+
+        movdq2q         mm2,            xmm6
+        movdq2q         mm3,            xmm7
+
+        paddw           mm6,            mm2
+        paddd           mm7,            mm3
+
+        pxor            mm3,            mm3                 ;
+        pxor            mm2,            mm2                 ;
+
+        punpcklwd       mm2,            mm6                 ;
+        punpckhwd       mm3,            mm6                 ;
+
+        paddd           mm2,            mm3                 ;
+        movq            mm6,            mm2                 ;
+
+        psrlq           mm6,            32                  ;
+        paddd           mm2,            mm6                 ;
+
+        psrad           mm2,            16                  ;
+        movq            mm4,            mm7                 ;
+
+        psrlq           mm4,            32                  ;
+        paddd           mm4,            mm7                 ;
+
+        mov             rsi,            arg(5) ; sum
+        mov             rdi,            arg(6) ; sumsquared
+
+        movd            [rsi],          mm2                 ;
+        movd            [rdi],          mm4                 ;
+
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_half_vert_variance16x_h_sse2
+;(
+;    unsigned char *ref_ptr,
+;    int ref_pixels_per_line,
+;    unsigned char *src_ptr,
+;    int src_pixels_per_line,
+;    unsigned int Height,
+;    int *sum,
+;    unsigned int *sumsquared
+;)
+global sym(vp8_half_vert_variance16x_h_sse2)
+sym(vp8_half_vert_variance16x_h_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    ; end prolog
+
+        pxor            xmm6,           xmm6                ;  error accumulator
+        pxor            xmm7,           xmm7                ;  sse eaccumulator
+        mov             rsi,            arg(0)              ;ref_ptr
+
+        mov             rdi,            arg(2)              ;src_ptr
+        movsxd          rcx,            dword ptr arg(4)    ;Height
+        movsxd          rax,            dword ptr arg(1)    ;ref_pixels_per_line
+        movsxd          rdx,            dword ptr arg(3)    ;src_pixels_per_line
+
+        movdqu          xmm5,           XMMWORD PTR [rsi]
+        lea             rsi,            [rsi + rax          ]
+        pxor            xmm0,           xmm0
+
+vp8_half_vert_variance16x_h_1:
+        movdqu          xmm3,           XMMWORD PTR [rsi]
+
+        pavgb           xmm5,           xmm3                ;  xmm5 = avg(xmm1,xmm3)
+        movdqa          xmm4,           xmm5
+        punpcklbw       xmm5,           xmm0
+        punpckhbw       xmm4,           xmm0
+
+        movq            xmm2,           QWORD PTR [rdi]
+        punpcklbw       xmm2,           xmm0
+        psubw           xmm5,           xmm2
+        movq            xmm2,           QWORD PTR [rdi+8]
+        punpcklbw       xmm2,           xmm0
+        psubw           xmm4,           xmm2
+
+        paddw           xmm6,           xmm5                ;  xmm6 += accumulated column differences
+        paddw           xmm6,           xmm4
+        pmaddwd         xmm5,           xmm5                ;  xmm5 *= xmm5
+        pmaddwd         xmm4,           xmm4
+        paddd           xmm7,           xmm5                ;  xmm7 += accumulated square column differences
+        paddd           xmm7,           xmm4
+
+        movdqa          xmm5,           xmm3
+
+        lea             rsi,            [rsi + rax]
+        lea             rdi,            [rdi + rdx]
+
+        sub             rcx,            1
+        jnz             vp8_half_vert_variance16x_h_1
+
+        pxor        xmm1,           xmm1
+        pxor        xmm5,           xmm5
+
+        punpcklwd   xmm0,           xmm6
+        punpckhwd   xmm1,           xmm6
+        psrad       xmm0,           16
+        psrad       xmm1,           16
+        paddd       xmm0,           xmm1
+        movdqa      xmm1,           xmm0
+
+        movdqa      xmm6,           xmm7
+        punpckldq   xmm6,           xmm5
+        punpckhdq   xmm7,           xmm5
+        paddd       xmm6,           xmm7
+
+        punpckldq   xmm0,           xmm5
+        punpckhdq   xmm1,           xmm5
+        paddd       xmm0,           xmm1
+
+        movdqa      xmm7,           xmm6
+        movdqa      xmm1,           xmm0
+
+        psrldq      xmm7,           8
+        psrldq      xmm1,           8
+
+        paddd       xmm6,           xmm7
+        paddd       xmm0,           xmm1
+
+        mov         rsi,            arg(5) ;[Sum]
+        mov         rdi,            arg(6) ;[SSE]
+
+        movd        [rsi],       xmm0
+        movd        [rdi],       xmm6
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_half_horiz_variance8x_h_sse2
+;(
+;    unsigned char *ref_ptr,
+;    int ref_pixels_per_line,
+;    unsigned char *src_ptr,
+;    int src_pixels_per_line,
+;    unsigned int Height,
+;    int *sum,
+;    unsigned int *sumsquared
+;)
+global sym(vp8_half_horiz_variance8x_h_sse2)
+sym(vp8_half_horiz_variance8x_h_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    ; end prolog
+
+%if ABI_IS_32BIT=0
+    movsxd          r8, dword ptr arg(1) ;ref_pixels_per_line
+    movsxd          r9, dword ptr arg(3) ;src_pixels_per_line
+%endif
+
+        pxor            xmm6,           xmm6                ;  error accumulator
+        pxor            xmm7,           xmm7                ;  sse eaccumulator
+        mov             rsi,            arg(0) ;ref_ptr              ;
+
+        mov             rdi,            arg(2) ;src_ptr              ;
+        movsxd          rcx,            dword ptr arg(4) ;Height              ;
+
+        pxor            xmm0,           xmm0                ;
+vp8_half_horiz_variance8x_h_1:
+        movq            xmm5,           QWORD PTR [rsi]     ;  xmm5 = s0,s1,s2..s8
+        movq            xmm3,           QWORD PTR [rsi+1]   ;  xmm3 = s1,s2,s3..s9
+
+        pavgb           xmm5,           xmm3                ;  xmm5 = avg(xmm1,xmm3)
+        punpcklbw       xmm5,           xmm0                ;  xmm5 = words of above
+
+        movq            xmm3,           QWORD PTR [rdi]     ;  xmm3 = d0,d1,d2..d8
+        punpcklbw       xmm3,           xmm0                ;  xmm3 = words of above
+
+        psubw           xmm5,           xmm3                ;  xmm5 -= xmm3
+        paddw           xmm6,           xmm5                ;  xmm6 += accumulated column differences
+        pmaddwd         xmm5,           xmm5                ;  xmm5 *= xmm5
+        paddd           xmm7,           xmm5                ;  xmm7 += accumulated square column differences
+
+%if ABI_IS_32BIT
+        add             esi,            dword ptr arg(1) ;ref_pixels_per_line    ;  next source
+        add             edi,            dword ptr arg(3) ;src_pixels_per_line    ;  next destination
+%else
+        add             rsi, r8
+        add             rdi, r9
+%endif
+        sub             rcx,            1                   ;
+        jnz             vp8_half_horiz_variance8x_h_1        ;
+
+        movdq2q         mm6,            xmm6                ;
+        movdq2q         mm7,            xmm7                ;
+
+        psrldq          xmm6,           8
+        psrldq          xmm7,           8
+
+        movdq2q         mm2,            xmm6
+        movdq2q         mm3,            xmm7
+
+        paddw           mm6,            mm2
+        paddd           mm7,            mm3
+
+        pxor            mm3,            mm3                 ;
+        pxor            mm2,            mm2                 ;
+
+        punpcklwd       mm2,            mm6                 ;
+        punpckhwd       mm3,            mm6                 ;
+
+        paddd           mm2,            mm3                 ;
+        movq            mm6,            mm2                 ;
+
+        psrlq           mm6,            32                  ;
+        paddd           mm2,            mm6                 ;
+
+        psrad           mm2,            16                  ;
+        movq            mm4,            mm7                 ;
+
+        psrlq           mm4,            32                  ;
+        paddd           mm4,            mm7                 ;
+
+        mov             rsi,            arg(5) ; sum
+        mov             rdi,            arg(6) ; sumsquared
+
+        movd            [rsi],          mm2                 ;
+        movd            [rdi],          mm4                 ;
+
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_half_horiz_variance16x_h_sse2
+;(
+;    unsigned char *ref_ptr,
+;    int ref_pixels_per_line,
+;    unsigned char *src_ptr,
+;    int src_pixels_per_line,
+;    unsigned int Height,
+;    int *sum,
+;    unsigned int *sumsquared
+;)
+global sym(vp8_half_horiz_variance16x_h_sse2)
+sym(vp8_half_horiz_variance16x_h_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    ; end prolog
+
+        pxor            xmm6,           xmm6                ;  error accumulator
+        pxor            xmm7,           xmm7                ;  sse eaccumulator
+        mov             rsi,            arg(0) ;ref_ptr              ;
+
+        mov             rdi,            arg(2) ;src_ptr              ;
+        movsxd          rcx,            dword ptr arg(4) ;Height              ;
+        movsxd          rax,            dword ptr arg(1) ;ref_pixels_per_line
+        movsxd          rdx,            dword ptr arg(3)    ;src_pixels_per_line
+
+        pxor            xmm0,           xmm0                ;
+
+vp8_half_horiz_variance16x_h_1:
+        movdqu          xmm5,           XMMWORD PTR [rsi]     ;  xmm5 = s0,s1,s2..s15
+        movdqu          xmm3,           XMMWORD PTR [rsi+1]   ;  xmm3 = s1,s2,s3..s16
+
+        pavgb           xmm5,           xmm3                ;  xmm5 = avg(xmm1,xmm3)
+        movdqa          xmm1,           xmm5
+        punpcklbw       xmm5,           xmm0                ;  xmm5 = words of above
+        punpckhbw       xmm1,           xmm0
+
+        movq            xmm3,           QWORD PTR [rdi]     ;  xmm3 = d0,d1,d2..d7
+        punpcklbw       xmm3,           xmm0                ;  xmm3 = words of above
+        movq            xmm2,           QWORD PTR [rdi+8]
+        punpcklbw       xmm2,           xmm0
+
+        psubw           xmm5,           xmm3                ;  xmm5 -= xmm3
+        psubw           xmm1,           xmm2
+        paddw           xmm6,           xmm5                ;  xmm6 += accumulated column differences
+        paddw           xmm6,           xmm1
+        pmaddwd         xmm5,           xmm5                ;  xmm5 *= xmm5
+        pmaddwd         xmm1,           xmm1
+        paddd           xmm7,           xmm5                ;  xmm7 += accumulated square column differences
+        paddd           xmm7,           xmm1
+
+        lea             rsi,            [rsi + rax]
+        lea             rdi,            [rdi + rdx]
+
+        sub             rcx,            1                   ;
+        jnz             vp8_half_horiz_variance16x_h_1        ;
+
+        pxor        xmm1,           xmm1
+        pxor        xmm5,           xmm5
+
+        punpcklwd   xmm0,           xmm6
+        punpckhwd   xmm1,           xmm6
+        psrad       xmm0,           16
+        psrad       xmm1,           16
+        paddd       xmm0,           xmm1
+        movdqa      xmm1,           xmm0
+
+        movdqa      xmm6,           xmm7
+        punpckldq   xmm6,           xmm5
+        punpckhdq   xmm7,           xmm5
+        paddd       xmm6,           xmm7
+
+        punpckldq   xmm0,           xmm5
+        punpckhdq   xmm1,           xmm5
+        paddd       xmm0,           xmm1
+
+        movdqa      xmm7,           xmm6
+        movdqa      xmm1,           xmm0
+
+        psrldq      xmm7,           8
+        psrldq      xmm1,           8
+
+        paddd       xmm6,           xmm7
+        paddd       xmm0,           xmm1
+
+        mov         rsi,            arg(5) ;[Sum]
+        mov         rdi,            arg(6) ;[SSE]
+
+        movd        [rsi],       xmm0
+        movd        [rdi],       xmm6
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+SECTION_RODATA
+;    short xmm_bi_rd[8] = { 64, 64, 64, 64,64, 64, 64, 64};
+align 16
+xmm_bi_rd:
+    times 8 dw 64
+align 16
+vp8_bilinear_filters_sse2:
+    dw 128, 128, 128, 128, 128, 128, 128, 128,  0,  0,  0,  0,  0,  0,  0,  0
+    dw 112, 112, 112, 112, 112, 112, 112, 112, 16, 16, 16, 16, 16, 16, 16, 16
+    dw 96, 96, 96, 96, 96, 96, 96, 96, 32, 32, 32, 32, 32, 32, 32, 32
+    dw 80, 80, 80, 80, 80, 80, 80, 80, 48, 48, 48, 48, 48, 48, 48, 48
+    dw 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
+    dw 48, 48, 48, 48, 48, 48, 48, 48, 80, 80, 80, 80, 80, 80, 80, 80
+    dw 32, 32, 32, 32, 32, 32, 32, 32, 96, 96, 96, 96, 96, 96, 96, 96
+    dw 16, 16, 16, 16, 16, 16, 16, 16, 112, 112, 112, 112, 112, 112, 112, 112
diff --git a/vp8/common/x86/variance_impl_ssse3.asm b/vp8/common/x86/variance_impl_ssse3.asm
new file mode 100644 (file)
index 0000000..97e8b0e
--- /dev/null
@@ -0,0 +1,364 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+%define xmm_filter_shift            7
+
+
+;void vp8_filter_block2d_bil_var_ssse3
+;(
+;    unsigned char *ref_ptr,
+;    int ref_pixels_per_line,
+;    unsigned char *src_ptr,
+;    int src_pixels_per_line,
+;    unsigned int Height,
+;    int  xoffset,
+;    int  yoffset,
+;    int *sum,
+;    unsigned int *sumsquared;;
+;
+;)
+;Note: The filter coefficient at offset=0 is 128. Since the second register
+;for Pmaddubsw is signed bytes, we must calculate zero offset seperately.
+global sym(vp8_filter_block2d_bil_var_ssse3)
+sym(vp8_filter_block2d_bil_var_ssse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 9
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    ; end prolog
+
+        pxor            xmm6,           xmm6
+        pxor            xmm7,           xmm7
+
+        lea             rcx,            [GLOBAL(vp8_bilinear_filters_ssse3)]
+        movsxd          rax,            dword ptr arg(5)     ; xoffset
+
+        cmp             rax,            0                    ; skip first_pass filter if xoffset=0
+        je              .filter_block2d_bil_var_ssse3_sp_only
+
+        shl             rax,            4                    ; point to filter coeff with xoffset
+        lea             rax,            [rax + rcx]          ; HFilter
+
+        movsxd          rdx,            dword ptr arg(6)     ; yoffset
+
+        cmp             rdx,            0                    ; skip second_pass filter if yoffset=0
+        je              .filter_block2d_bil_var_ssse3_fp_only
+
+        shl             rdx,            4
+        lea             rdx,            [rdx + rcx]          ; VFilter
+
+        mov             rsi,            arg(0)               ;ref_ptr
+        mov             rdi,            arg(2)               ;src_ptr
+        movsxd          rcx,            dword ptr arg(4)     ;Height
+
+        movdqu          xmm0,           XMMWORD PTR [rsi]
+        movdqu          xmm1,           XMMWORD PTR [rsi+1]
+        movdqa          xmm2,           xmm0
+
+        punpcklbw       xmm0,           xmm1
+        punpckhbw       xmm2,           xmm1
+        pmaddubsw       xmm0,           [rax]
+        pmaddubsw       xmm2,           [rax]
+
+        paddw           xmm0,           [GLOBAL(xmm_bi_rd)]
+        paddw           xmm2,           [GLOBAL(xmm_bi_rd)]
+        psraw           xmm0,           xmm_filter_shift
+        psraw           xmm2,           xmm_filter_shift
+
+        packuswb        xmm0,           xmm2
+
+%if ABI_IS_32BIT
+        add             rsi,            dword ptr arg(1) ;ref_pixels_per_line
+%else
+        movsxd          r8,             dword ptr arg(1) ;ref_pixels_per_line
+        movsxd          r9,             dword ptr arg(3) ;src_pixels_per_line
+        lea             rsi,            [rsi + r8]
+%endif
+
+.filter_block2d_bil_var_ssse3_loop:
+        movdqu          xmm1,           XMMWORD PTR [rsi]
+        movdqu          xmm2,           XMMWORD PTR [rsi+1]
+        movdqa          xmm3,           xmm1
+
+        punpcklbw       xmm1,           xmm2
+        punpckhbw       xmm3,           xmm2
+        pmaddubsw       xmm1,           [rax]
+        pmaddubsw       xmm3,           [rax]
+
+        paddw           xmm1,           [GLOBAL(xmm_bi_rd)]
+        paddw           xmm3,           [GLOBAL(xmm_bi_rd)]
+        psraw           xmm1,           xmm_filter_shift
+        psraw           xmm3,           xmm_filter_shift
+        packuswb        xmm1,           xmm3
+
+        movdqa          xmm2,           xmm0
+        movdqa          xmm0,           xmm1
+        movdqa          xmm3,           xmm2
+
+        punpcklbw       xmm2,           xmm1
+        punpckhbw       xmm3,           xmm1
+        pmaddubsw       xmm2,           [rdx]
+        pmaddubsw       xmm3,           [rdx]
+
+        paddw           xmm2,           [GLOBAL(xmm_bi_rd)]
+        paddw           xmm3,           [GLOBAL(xmm_bi_rd)]
+        psraw           xmm2,           xmm_filter_shift
+        psraw           xmm3,           xmm_filter_shift
+
+        movq            xmm1,           QWORD PTR [rdi]
+        pxor            xmm4,           xmm4
+        punpcklbw       xmm1,           xmm4
+        movq            xmm5,           QWORD PTR [rdi+8]
+        punpcklbw       xmm5,           xmm4
+
+        psubw           xmm2,           xmm1
+        psubw           xmm3,           xmm5
+        paddw           xmm6,           xmm2
+        paddw           xmm6,           xmm3
+        pmaddwd         xmm2,           xmm2
+        pmaddwd         xmm3,           xmm3
+        paddd           xmm7,           xmm2
+        paddd           xmm7,           xmm3
+
+%if ABI_IS_32BIT
+        add             rsi,            dword ptr arg(1)     ;ref_pixels_per_line
+        add             rdi,            dword ptr arg(3)     ;src_pixels_per_line
+%else
+        lea             rsi,            [rsi + r8]
+        lea             rdi,            [rdi + r9]
+%endif
+
+        sub             rcx,            1
+        jnz             .filter_block2d_bil_var_ssse3_loop
+
+        jmp             .filter_block2d_bil_variance
+
+.filter_block2d_bil_var_ssse3_sp_only:
+        movsxd          rdx,            dword ptr arg(6)     ; yoffset
+
+        cmp             rdx,            0                    ; Both xoffset =0 and yoffset=0
+        je              .filter_block2d_bil_var_ssse3_full_pixel
+
+        shl             rdx,            4
+        lea             rdx,            [rdx + rcx]          ; VFilter
+
+        mov             rsi,            arg(0)               ;ref_ptr
+        mov             rdi,            arg(2)               ;src_ptr
+        movsxd          rcx,            dword ptr arg(4)     ;Height
+        movsxd          rax,            dword ptr arg(1)     ;ref_pixels_per_line
+
+        movdqu          xmm1,           XMMWORD PTR [rsi]
+        movdqa          xmm0,           xmm1
+
+%if ABI_IS_32BIT=0
+        movsxd          r9,             dword ptr arg(3) ;src_pixels_per_line
+%endif
+
+        lea             rsi,            [rsi + rax]
+
+.filter_block2d_bil_sp_only_loop:
+        movdqu          xmm3,           XMMWORD PTR [rsi]
+        movdqa          xmm2,           xmm1
+        movdqa          xmm0,           xmm3
+
+        punpcklbw       xmm1,           xmm3
+        punpckhbw       xmm2,           xmm3
+        pmaddubsw       xmm1,           [rdx]
+        pmaddubsw       xmm2,           [rdx]
+
+        paddw           xmm1,           [GLOBAL(xmm_bi_rd)]
+        paddw           xmm2,           [GLOBAL(xmm_bi_rd)]
+        psraw           xmm1,           xmm_filter_shift
+        psraw           xmm2,           xmm_filter_shift
+
+        movq            xmm3,           QWORD PTR [rdi]
+        pxor            xmm4,           xmm4
+        punpcklbw       xmm3,           xmm4
+        movq            xmm5,           QWORD PTR [rdi+8]
+        punpcklbw       xmm5,           xmm4
+
+        psubw           xmm1,           xmm3
+        psubw           xmm2,           xmm5
+        paddw           xmm6,           xmm1
+        paddw           xmm6,           xmm2
+        pmaddwd         xmm1,           xmm1
+        pmaddwd         xmm2,           xmm2
+        paddd           xmm7,           xmm1
+        paddd           xmm7,           xmm2
+
+        movdqa          xmm1,           xmm0
+        lea             rsi,            [rsi + rax]          ;ref_pixels_per_line
+
+%if ABI_IS_32BIT
+        add             rdi,            dword ptr arg(3)     ;src_pixels_per_line
+%else
+        lea             rdi,            [rdi + r9]
+%endif
+
+        sub             rcx,            1
+        jnz             .filter_block2d_bil_sp_only_loop
+
+        jmp             .filter_block2d_bil_variance
+
+.filter_block2d_bil_var_ssse3_full_pixel:
+        mov             rsi,            arg(0)               ;ref_ptr
+        mov             rdi,            arg(2)               ;src_ptr
+        movsxd          rcx,            dword ptr arg(4)     ;Height
+        movsxd          rax,            dword ptr arg(1)     ;ref_pixels_per_line
+        movsxd          rdx,            dword ptr arg(3)     ;src_pixels_per_line
+        pxor            xmm0,           xmm0
+
+.filter_block2d_bil_full_pixel_loop:
+        movq            xmm1,           QWORD PTR [rsi]
+        punpcklbw       xmm1,           xmm0
+        movq            xmm2,           QWORD PTR [rsi+8]
+        punpcklbw       xmm2,           xmm0
+
+        movq            xmm3,           QWORD PTR [rdi]
+        punpcklbw       xmm3,           xmm0
+        movq            xmm4,           QWORD PTR [rdi+8]
+        punpcklbw       xmm4,           xmm0
+
+        psubw           xmm1,           xmm3
+        psubw           xmm2,           xmm4
+        paddw           xmm6,           xmm1
+        paddw           xmm6,           xmm2
+        pmaddwd         xmm1,           xmm1
+        pmaddwd         xmm2,           xmm2
+        paddd           xmm7,           xmm1
+        paddd           xmm7,           xmm2
+
+        lea             rsi,            [rsi + rax]          ;ref_pixels_per_line
+        lea             rdi,            [rdi + rdx]          ;src_pixels_per_line
+        sub             rcx,            1
+        jnz             .filter_block2d_bil_full_pixel_loop
+
+        jmp             .filter_block2d_bil_variance
+
+.filter_block2d_bil_var_ssse3_fp_only:
+        mov             rsi,            arg(0)               ;ref_ptr
+        mov             rdi,            arg(2)               ;src_ptr
+        movsxd          rcx,            dword ptr arg(4)     ;Height
+        movsxd          rdx,            dword ptr arg(1)     ;ref_pixels_per_line
+
+        pxor            xmm0,           xmm0
+
+%if ABI_IS_32BIT=0
+        movsxd          r9,             dword ptr arg(3) ;src_pixels_per_line
+%endif
+
+.filter_block2d_bil_fp_only_loop:
+        movdqu          xmm1,           XMMWORD PTR [rsi]
+        movdqu          xmm2,           XMMWORD PTR [rsi+1]
+        movdqa          xmm3,           xmm1
+
+        punpcklbw       xmm1,           xmm2
+        punpckhbw       xmm3,           xmm2
+        pmaddubsw       xmm1,           [rax]
+        pmaddubsw       xmm3,           [rax]
+
+        paddw           xmm1,           [GLOBAL(xmm_bi_rd)]
+        paddw           xmm3,           [GLOBAL(xmm_bi_rd)]
+        psraw           xmm1,           xmm_filter_shift
+        psraw           xmm3,           xmm_filter_shift
+
+        movq            xmm2,           XMMWORD PTR [rdi]
+        pxor            xmm4,           xmm4
+        punpcklbw       xmm2,           xmm4
+        movq            xmm5,           QWORD PTR [rdi+8]
+        punpcklbw       xmm5,           xmm4
+
+        psubw           xmm1,           xmm2
+        psubw           xmm3,           xmm5
+        paddw           xmm6,           xmm1
+        paddw           xmm6,           xmm3
+        pmaddwd         xmm1,           xmm1
+        pmaddwd         xmm3,           xmm3
+        paddd           xmm7,           xmm1
+        paddd           xmm7,           xmm3
+
+        lea             rsi,            [rsi + rdx]
+%if ABI_IS_32BIT
+        add             rdi,            dword ptr arg(3)     ;src_pixels_per_line
+%else
+        lea             rdi,            [rdi + r9]
+%endif
+
+        sub             rcx,            1
+        jnz             .filter_block2d_bil_fp_only_loop
+
+        jmp             .filter_block2d_bil_variance
+
+.filter_block2d_bil_variance:
+        pxor        xmm0,           xmm0
+        pxor        xmm1,           xmm1
+        pxor        xmm5,           xmm5
+
+        punpcklwd   xmm0,           xmm6
+        punpckhwd   xmm1,           xmm6
+        psrad       xmm0,           16
+        psrad       xmm1,           16
+        paddd       xmm0,           xmm1
+        movdqa      xmm1,           xmm0
+
+        movdqa      xmm6,           xmm7
+        punpckldq   xmm6,           xmm5
+        punpckhdq   xmm7,           xmm5
+        paddd       xmm6,           xmm7
+
+        punpckldq   xmm0,           xmm5
+        punpckhdq   xmm1,           xmm5
+        paddd       xmm0,           xmm1
+
+        movdqa      xmm7,           xmm6
+        movdqa      xmm1,           xmm0
+
+        psrldq      xmm7,           8
+        psrldq      xmm1,           8
+
+        paddd       xmm6,           xmm7
+        paddd       xmm0,           xmm1
+
+        mov         rsi,            arg(7) ;[Sum]
+        mov         rdi,            arg(8) ;[SSE]
+
+        movd        [rsi],       xmm0
+        movd        [rdi],       xmm6
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+SECTION_RODATA
+align 16
+xmm_bi_rd:
+    times 8 dw 64
+align 16
+vp8_bilinear_filters_ssse3:
+    times 8 db 128, 0
+    times 8 db 112, 16
+    times 8 db 96,  32
+    times 8 db 80,  48
+    times 8 db 64,  64
+    times 8 db 48,  80
+    times 8 db 32,  96
+    times 8 db 16,  112
diff --git a/vp8/common/x86/variance_mmx.c b/vp8/common/x86/variance_mmx.c
new file mode 100644 (file)
index 0000000..0c4dd4a
--- /dev/null
@@ -0,0 +1,398 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "vpx_config.h"
+#include "vp8/common/variance.h"
+#include "vp8/common/pragmas.h"
+#include "vpx_ports/mem.h"
+#include "vp8/common/x86/filter_x86.h"
+
+extern void filter_block1d_h6_mmx
+(
+    const unsigned char *src_ptr,
+    unsigned short *output_ptr,
+    unsigned int src_pixels_per_line,
+    unsigned int pixel_step,
+    unsigned int output_height,
+    unsigned int output_width,
+    short *filter
+);
+extern void filter_block1d_v6_mmx
+(
+    const short *src_ptr,
+    unsigned char *output_ptr,
+    unsigned int pixels_per_line,
+    unsigned int pixel_step,
+    unsigned int output_height,
+    unsigned int output_width,
+    short *filter
+);
+
+extern unsigned int vp8_get_mb_ss_mmx(const short *src_ptr);
+extern unsigned int vp8_get8x8var_mmx
+(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *SSE,
+    int *Sum
+);
+extern unsigned int vp8_get4x4var_mmx
+(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *SSE,
+    int *Sum
+);
+extern void vp8_filter_block2d_bil4x4_var_mmx
+(
+    const unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    const unsigned char *src_ptr,
+    int src_pixels_per_line,
+    const short *HFilter,
+    const short *VFilter,
+    int *sum,
+    unsigned int *sumsquared
+);
+extern void vp8_filter_block2d_bil_var_mmx
+(
+    const unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    const unsigned char *src_ptr,
+    int src_pixels_per_line,
+    unsigned int Height,
+    const short *HFilter,
+    const short *VFilter,
+    int *sum,
+    unsigned int *sumsquared
+);
+
+
+unsigned int vp8_variance4x4_mmx(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int var;
+    int avg;
+
+    vp8_get4x4var_mmx(src_ptr, source_stride, ref_ptr, recon_stride, &var, &avg) ;
+    *sse = var;
+    return (var - ((unsigned int)(avg * avg) >> 4));
+
+}
+
+unsigned int vp8_variance8x8_mmx(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int var;
+    int avg;
+
+    vp8_get8x8var_mmx(src_ptr, source_stride, ref_ptr, recon_stride, &var, &avg) ;
+    *sse = var;
+
+    return (var - ((unsigned int)(avg * avg) >> 6));
+
+}
+
+unsigned int vp8_mse16x16_mmx(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int sse0, sse1, sse2, sse3, var;
+    int sum0, sum1, sum2, sum3;
+
+
+    vp8_get8x8var_mmx(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    vp8_get8x8var_mmx(src_ptr + 8, source_stride, ref_ptr + 8, recon_stride, &sse1, &sum1);
+    vp8_get8x8var_mmx(src_ptr + 8 * source_stride, source_stride, ref_ptr + 8 * recon_stride, recon_stride, &sse2, &sum2) ;
+    vp8_get8x8var_mmx(src_ptr + 8 * source_stride + 8, source_stride, ref_ptr + 8 * recon_stride + 8, recon_stride, &sse3, &sum3);
+
+    var = sse0 + sse1 + sse2 + sse3;
+    *sse = var;
+    return var;
+}
+
+
+unsigned int vp8_variance16x16_mmx(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int sse0, sse1, sse2, sse3, var;
+    int sum0, sum1, sum2, sum3, avg;
+
+
+    vp8_get8x8var_mmx(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    vp8_get8x8var_mmx(src_ptr + 8, source_stride, ref_ptr + 8, recon_stride, &sse1, &sum1);
+    vp8_get8x8var_mmx(src_ptr + 8 * source_stride, source_stride, ref_ptr + 8 * recon_stride, recon_stride, &sse2, &sum2) ;
+    vp8_get8x8var_mmx(src_ptr + 8 * source_stride + 8, source_stride, ref_ptr + 8 * recon_stride + 8, recon_stride, &sse3, &sum3);
+
+    var = sse0 + sse1 + sse2 + sse3;
+    avg = sum0 + sum1 + sum2 + sum3;
+    *sse = var;
+    return (var - ((unsigned int)(avg * avg) >> 8));
+}
+
+unsigned int vp8_variance16x8_mmx(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int sse0, sse1, var;
+    int sum0, sum1, avg;
+
+    vp8_get8x8var_mmx(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    vp8_get8x8var_mmx(src_ptr + 8, source_stride, ref_ptr + 8, recon_stride, &sse1, &sum1);
+
+    var = sse0 + sse1;
+    avg = sum0 + sum1;
+    *sse = var;
+    return (var - ((unsigned int)(avg * avg) >> 7));
+
+}
+
+
+unsigned int vp8_variance8x16_mmx(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int sse0, sse1, var;
+    int sum0, sum1, avg;
+
+    vp8_get8x8var_mmx(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    vp8_get8x8var_mmx(src_ptr + 8 * source_stride, source_stride, ref_ptr + 8 * recon_stride, recon_stride, &sse1, &sum1) ;
+
+    var = sse0 + sse1;
+    avg = sum0 + sum1;
+    *sse = var;
+
+    return (var - ((unsigned int)(avg * avg) >> 7));
+
+}
+
+
+unsigned int vp8_sub_pixel_variance4x4_mmx
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse)
+
+{
+    int xsum;
+    unsigned int xxsum;
+    vp8_filter_block2d_bil4x4_var_mmx(
+        src_ptr, src_pixels_per_line,
+        dst_ptr, dst_pixels_per_line,
+        vp8_bilinear_filters_x86_4[xoffset], vp8_bilinear_filters_x86_4[yoffset],
+        &xsum, &xxsum
+    );
+    *sse = xxsum;
+    return (xxsum - ((unsigned int)(xsum * xsum) >> 4));
+}
+
+
+unsigned int vp8_sub_pixel_variance8x8_mmx
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+
+    int xsum;
+    unsigned int xxsum;
+    vp8_filter_block2d_bil_var_mmx(
+        src_ptr, src_pixels_per_line,
+        dst_ptr, dst_pixels_per_line, 8,
+        vp8_bilinear_filters_x86_4[xoffset], vp8_bilinear_filters_x86_4[yoffset],
+        &xsum, &xxsum
+    );
+    *sse = xxsum;
+    return (xxsum - ((unsigned int)(xsum * xsum) >> 6));
+}
+
+unsigned int vp8_sub_pixel_variance16x16_mmx
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+
+    int xsum0, xsum1;
+    unsigned int xxsum0, xxsum1;
+
+
+    vp8_filter_block2d_bil_var_mmx(
+        src_ptr, src_pixels_per_line,
+        dst_ptr, dst_pixels_per_line, 16,
+        vp8_bilinear_filters_x86_4[xoffset], vp8_bilinear_filters_x86_4[yoffset],
+        &xsum0, &xxsum0
+    );
+
+
+    vp8_filter_block2d_bil_var_mmx(
+        src_ptr + 8, src_pixels_per_line,
+        dst_ptr + 8, dst_pixels_per_line, 16,
+        vp8_bilinear_filters_x86_4[xoffset], vp8_bilinear_filters_x86_4[yoffset],
+        &xsum1, &xxsum1
+    );
+
+    xsum0 += xsum1;
+    xxsum0 += xxsum1;
+
+    *sse = xxsum0;
+    return (xxsum0 - ((unsigned int)(xsum0 * xsum0) >> 8));
+
+
+}
+
+unsigned int vp8_sub_pixel_mse16x16_mmx(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    vp8_sub_pixel_variance16x16_mmx(src_ptr, src_pixels_per_line, xoffset, yoffset, dst_ptr, dst_pixels_per_line, sse);
+    return *sse;
+}
+
+unsigned int vp8_sub_pixel_variance16x8_mmx
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    int xsum0, xsum1;
+    unsigned int xxsum0, xxsum1;
+
+
+    vp8_filter_block2d_bil_var_mmx(
+        src_ptr, src_pixels_per_line,
+        dst_ptr, dst_pixels_per_line, 8,
+        vp8_bilinear_filters_x86_4[xoffset], vp8_bilinear_filters_x86_4[yoffset],
+        &xsum0, &xxsum0
+    );
+
+
+    vp8_filter_block2d_bil_var_mmx(
+        src_ptr + 8, src_pixels_per_line,
+        dst_ptr + 8, dst_pixels_per_line, 8,
+        vp8_bilinear_filters_x86_4[xoffset], vp8_bilinear_filters_x86_4[yoffset],
+        &xsum1, &xxsum1
+    );
+
+    xsum0 += xsum1;
+    xxsum0 += xxsum1;
+
+    *sse = xxsum0;
+    return (xxsum0 - ((unsigned int)(xsum0 * xsum0) >> 7));
+}
+
+unsigned int vp8_sub_pixel_variance8x16_mmx
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    int xsum;
+    unsigned int xxsum;
+    vp8_filter_block2d_bil_var_mmx(
+        src_ptr, src_pixels_per_line,
+        dst_ptr, dst_pixels_per_line, 16,
+        vp8_bilinear_filters_x86_4[xoffset], vp8_bilinear_filters_x86_4[yoffset],
+        &xsum, &xxsum
+    );
+    *sse = xxsum;
+    return (xxsum - ((unsigned int)(xsum * xsum) >> 7));
+}
+
+
+unsigned int vp8_variance_halfpixvar16x16_h_mmx(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    return vp8_sub_pixel_variance16x16_mmx(src_ptr, source_stride, 4, 0,
+                                           ref_ptr, recon_stride, sse);
+}
+
+
+unsigned int vp8_variance_halfpixvar16x16_v_mmx(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    return vp8_sub_pixel_variance16x16_mmx(src_ptr, source_stride, 0, 4,
+                                           ref_ptr, recon_stride, sse);
+}
+
+
+unsigned int vp8_variance_halfpixvar16x16_hv_mmx(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    return vp8_sub_pixel_variance16x16_mmx(src_ptr, source_stride, 4, 4,
+                                           ref_ptr, recon_stride, sse);
+}
diff --git a/vp8/common/x86/variance_sse2.c b/vp8/common/x86/variance_sse2.c
new file mode 100644 (file)
index 0000000..2769a30
--- /dev/null
@@ -0,0 +1,557 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "vpx_config.h"
+#include "vp8/common/variance.h"
+#include "vp8/common/pragmas.h"
+#include "vpx_ports/mem.h"
+#include "vp8/common/x86/filter_x86.h"
+
+extern void filter_block1d_h6_mmx(const unsigned char *src_ptr, unsigned short *output_ptr, unsigned int src_pixels_per_line, unsigned int pixel_step, unsigned int output_height, unsigned int output_width, short *filter);
+extern void filter_block1d_v6_mmx(const short *src_ptr, unsigned char *output_ptr, unsigned int pixels_per_line, unsigned int pixel_step, unsigned int output_height, unsigned int output_width, short *filter);
+extern void filter_block1d8_h6_sse2(const unsigned char *src_ptr, unsigned short *output_ptr, unsigned int src_pixels_per_line, unsigned int pixel_step, unsigned int output_height, unsigned int output_width, short *filter);
+extern void filter_block1d8_v6_sse2(const short *src_ptr, unsigned char *output_ptr, unsigned int pixels_per_line, unsigned int pixel_step, unsigned int output_height, unsigned int output_width, short *filter);
+
+extern void vp8_filter_block2d_bil4x4_var_mmx
+(
+    const unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    const unsigned char *src_ptr,
+    int src_pixels_per_line,
+    const short *HFilter,
+    const short *VFilter,
+    int *sum,
+    unsigned int *sumsquared
+);
+
+extern unsigned int vp8_get4x4var_mmx
+(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *SSE,
+    int *Sum
+);
+
+unsigned int vp8_get_mb_ss_sse2
+(
+    const short *src_ptr
+);
+unsigned int vp8_get16x16var_sse2
+(
+    const unsigned char *src_ptr,
+    int source_stride,
+    const unsigned char *ref_ptr,
+    int recon_stride,
+    unsigned int *SSE,
+    int *Sum
+);
+unsigned int vp8_get8x8var_sse2
+(
+    const unsigned char *src_ptr,
+    int source_stride,
+    const unsigned char *ref_ptr,
+    int recon_stride,
+    unsigned int *SSE,
+    int *Sum
+);
+void vp8_filter_block2d_bil_var_sse2
+(
+    const unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    const unsigned char *src_ptr,
+    int src_pixels_per_line,
+    unsigned int Height,
+    int  xoffset,
+    int  yoffset,
+    int *sum,
+    unsigned int *sumsquared
+);
+void vp8_half_horiz_vert_variance8x_h_sse2
+(
+    const unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    const unsigned char *src_ptr,
+    int src_pixels_per_line,
+    unsigned int Height,
+    int *sum,
+    unsigned int *sumsquared
+);
+void vp8_half_horiz_vert_variance16x_h_sse2
+(
+    const unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    const unsigned char *src_ptr,
+    int src_pixels_per_line,
+    unsigned int Height,
+    int *sum,
+    unsigned int *sumsquared
+);
+void vp8_half_horiz_variance8x_h_sse2
+(
+    const unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    const unsigned char *src_ptr,
+    int src_pixels_per_line,
+    unsigned int Height,
+    int *sum,
+    unsigned int *sumsquared
+);
+void vp8_half_horiz_variance16x_h_sse2
+(
+    const unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    const unsigned char *src_ptr,
+    int src_pixels_per_line,
+    unsigned int Height,
+    int *sum,
+    unsigned int *sumsquared
+);
+void vp8_half_vert_variance8x_h_sse2
+(
+    const unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    const unsigned char *src_ptr,
+    int src_pixels_per_line,
+    unsigned int Height,
+    int *sum,
+    unsigned int *sumsquared
+);
+void vp8_half_vert_variance16x_h_sse2
+(
+    const unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    const unsigned char *src_ptr,
+    int src_pixels_per_line,
+    unsigned int Height,
+    int *sum,
+    unsigned int *sumsquared
+);
+
+unsigned int vp8_variance4x4_wmt(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int var;
+    int avg;
+
+    vp8_get4x4var_mmx(src_ptr, source_stride, ref_ptr, recon_stride, &var, &avg) ;
+    *sse = var;
+    return (var - ((unsigned int)(avg * avg) >> 4));
+
+}
+
+unsigned int vp8_variance8x8_wmt
+(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int var;
+    int avg;
+
+    vp8_get8x8var_sse2(src_ptr, source_stride, ref_ptr, recon_stride, &var, &avg) ;
+    *sse = var;
+    return (var - ((unsigned int)(avg * avg) >> 6));
+
+}
+
+
+unsigned int vp8_variance16x16_wmt
+(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int sse0;
+    int sum0;
+
+
+    vp8_get16x16var_sse2(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    *sse = sse0;
+    return (sse0 - ((unsigned int)(sum0 * sum0) >> 8));
+}
+unsigned int vp8_mse16x16_wmt(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+
+    unsigned int sse0;
+    int sum0;
+    vp8_get16x16var_sse2(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    *sse = sse0;
+    return sse0;
+
+}
+
+
+unsigned int vp8_variance16x8_wmt
+(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int sse0, sse1, var;
+    int sum0, sum1, avg;
+
+    vp8_get8x8var_sse2(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    vp8_get8x8var_sse2(src_ptr + 8, source_stride, ref_ptr + 8, recon_stride, &sse1, &sum1);
+
+    var = sse0 + sse1;
+    avg = sum0 + sum1;
+    *sse = var;
+    return (var - ((unsigned int)(avg * avg) >> 7));
+
+}
+
+unsigned int vp8_variance8x16_wmt
+(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int sse0, sse1, var;
+    int sum0, sum1, avg;
+
+    vp8_get8x8var_sse2(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    vp8_get8x8var_sse2(src_ptr + 8 * source_stride, source_stride, ref_ptr + 8 * recon_stride, recon_stride, &sse1, &sum1) ;
+
+    var = sse0 + sse1;
+    avg = sum0 + sum1;
+    *sse = var;
+    return (var - ((unsigned int)(avg * avg) >> 7));
+
+}
+
+unsigned int vp8_sub_pixel_variance4x4_wmt
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    int xsum;
+    unsigned int xxsum;
+    vp8_filter_block2d_bil4x4_var_mmx(
+        src_ptr, src_pixels_per_line,
+        dst_ptr, dst_pixels_per_line,
+        vp8_bilinear_filters_x86_4[xoffset], vp8_bilinear_filters_x86_4[yoffset],
+        &xsum, &xxsum
+    );
+    *sse = xxsum;
+    return (xxsum - ((unsigned int)(xsum * xsum) >> 4));
+}
+
+
+unsigned int vp8_sub_pixel_variance8x8_wmt
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    int xsum;
+    unsigned int xxsum;
+
+    if (xoffset == 4 && yoffset == 0)
+    {
+        vp8_half_horiz_variance8x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 8,
+            &xsum, &xxsum);
+    }
+    else if (xoffset == 0 && yoffset == 4)
+    {
+        vp8_half_vert_variance8x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 8,
+            &xsum, &xxsum);
+    }
+    else if (xoffset == 4 && yoffset == 4)
+    {
+        vp8_half_horiz_vert_variance8x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 8,
+            &xsum, &xxsum);
+    }
+    else
+    {
+        vp8_filter_block2d_bil_var_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 8,
+            xoffset, yoffset,
+            &xsum, &xxsum);
+    }
+
+    *sse = xxsum;
+    return (xxsum - ((unsigned int)(xsum * xsum) >> 6));
+}
+
+unsigned int vp8_sub_pixel_variance16x16_wmt
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    int xsum0, xsum1;
+    unsigned int xxsum0, xxsum1;
+
+
+    // note we could avoid these if statements if the calling function
+    // just called the appropriate functions inside.
+    if (xoffset == 4 && yoffset == 0)
+    {
+        vp8_half_horiz_variance16x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 16,
+            &xsum0, &xxsum0);
+    }
+    else if (xoffset == 0 && yoffset == 4)
+    {
+        vp8_half_vert_variance16x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 16,
+            &xsum0, &xxsum0);
+    }
+    else if (xoffset == 4 && yoffset == 4)
+    {
+        vp8_half_horiz_vert_variance16x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 16,
+            &xsum0, &xxsum0);
+    }
+    else
+    {
+        vp8_filter_block2d_bil_var_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 16,
+            xoffset, yoffset,
+            &xsum0, &xxsum0
+        );
+
+        vp8_filter_block2d_bil_var_sse2(
+            src_ptr + 8, src_pixels_per_line,
+            dst_ptr + 8, dst_pixels_per_line, 16,
+            xoffset, yoffset,
+            &xsum1, &xxsum1
+        );
+        xsum0 += xsum1;
+        xxsum0 += xxsum1;
+    }
+
+    *sse = xxsum0;
+    return (xxsum0 - ((unsigned int)(xsum0 * xsum0) >> 8));
+}
+
+unsigned int vp8_sub_pixel_mse16x16_wmt(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    vp8_sub_pixel_variance16x16_wmt(src_ptr, src_pixels_per_line, xoffset, yoffset, dst_ptr, dst_pixels_per_line, sse);
+    return *sse;
+}
+
+unsigned int vp8_sub_pixel_variance16x8_wmt
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+
+)
+{
+    int xsum0, xsum1;
+    unsigned int xxsum0, xxsum1;
+
+    if (xoffset == 4 && yoffset == 0)
+    {
+        vp8_half_horiz_variance16x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 8,
+            &xsum0, &xxsum0);
+    }
+    else if (xoffset == 0 && yoffset == 4)
+    {
+        vp8_half_vert_variance16x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 8,
+            &xsum0, &xxsum0);
+    }
+    else if (xoffset == 4 && yoffset == 4)
+    {
+        vp8_half_horiz_vert_variance16x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 8,
+            &xsum0, &xxsum0);
+    }
+    else
+    {
+        vp8_filter_block2d_bil_var_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 8,
+            xoffset, yoffset,
+            &xsum0, &xxsum0);
+
+        vp8_filter_block2d_bil_var_sse2(
+            src_ptr + 8, src_pixels_per_line,
+            dst_ptr + 8, dst_pixels_per_line, 8,
+            xoffset, yoffset,
+            &xsum1, &xxsum1);
+        xsum0 += xsum1;
+        xxsum0 += xxsum1;
+    }
+
+    *sse = xxsum0;
+    return (xxsum0 - ((unsigned int)(xsum0 * xsum0) >> 7));
+}
+
+unsigned int vp8_sub_pixel_variance8x16_wmt
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    int xsum;
+    unsigned int xxsum;
+
+    if (xoffset == 4 && yoffset == 0)
+    {
+        vp8_half_horiz_variance8x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 16,
+            &xsum, &xxsum);
+    }
+    else if (xoffset == 0 && yoffset == 4)
+    {
+        vp8_half_vert_variance8x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 16,
+            &xsum, &xxsum);
+    }
+    else if (xoffset == 4 && yoffset == 4)
+    {
+        vp8_half_horiz_vert_variance8x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 16,
+            &xsum, &xxsum);
+    }
+    else
+    {
+        vp8_filter_block2d_bil_var_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 16,
+            xoffset, yoffset,
+            &xsum, &xxsum);
+    }
+
+    *sse = xxsum;
+    return (xxsum - ((unsigned int)(xsum * xsum) >> 7));
+}
+
+
+unsigned int vp8_variance_halfpixvar16x16_h_wmt(
+    const unsigned char *src_ptr,
+    int  src_pixels_per_line,
+    const unsigned char *dst_ptr,
+    int  dst_pixels_per_line,
+    unsigned int *sse)
+{
+    int xsum0;
+    unsigned int xxsum0;
+
+    vp8_half_horiz_variance16x_h_sse2(
+        src_ptr, src_pixels_per_line,
+        dst_ptr, dst_pixels_per_line, 16,
+        &xsum0, &xxsum0);
+
+    *sse = xxsum0;
+    return (xxsum0 - ((unsigned int)(xsum0 * xsum0) >> 8));
+}
+
+
+unsigned int vp8_variance_halfpixvar16x16_v_wmt(
+    const unsigned char *src_ptr,
+    int  src_pixels_per_line,
+    const unsigned char *dst_ptr,
+    int  dst_pixels_per_line,
+    unsigned int *sse)
+{
+    int xsum0;
+    unsigned int xxsum0;
+    vp8_half_vert_variance16x_h_sse2(
+        src_ptr, src_pixels_per_line,
+        dst_ptr, dst_pixels_per_line, 16,
+        &xsum0, &xxsum0);
+
+    *sse = xxsum0;
+    return (xxsum0 - ((unsigned int)(xsum0 * xsum0) >> 8));
+}
+
+
+unsigned int vp8_variance_halfpixvar16x16_hv_wmt(
+    const unsigned char *src_ptr,
+    int  src_pixels_per_line,
+    const unsigned char *dst_ptr,
+    int  dst_pixels_per_line,
+    unsigned int *sse)
+{
+    int xsum0;
+    unsigned int xxsum0;
+
+    vp8_half_horiz_vert_variance16x_h_sse2(
+        src_ptr, src_pixels_per_line,
+        dst_ptr, dst_pixels_per_line, 16,
+        &xsum0, &xxsum0);
+
+    *sse = xxsum0;
+    return (xxsum0 - ((unsigned int)(xsum0 * xsum0) >> 8));
+}
diff --git a/vp8/common/x86/variance_ssse3.c b/vp8/common/x86/variance_ssse3.c
new file mode 100644 (file)
index 0000000..1be0d92
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "vpx_config.h"
+#include "vp8/common/variance.h"
+#include "vp8/common/pragmas.h"
+#include "vpx_ports/mem.h"
+
+extern unsigned int vp8_get16x16var_sse2
+(
+    const unsigned char *src_ptr,
+    int source_stride,
+    const unsigned char *ref_ptr,
+    int recon_stride,
+    unsigned int *SSE,
+    int *Sum
+);
+extern void vp8_half_horiz_vert_variance16x_h_sse2
+(
+    const unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    const unsigned char *src_ptr,
+    int src_pixels_per_line,
+    unsigned int Height,
+    int *sum,
+    unsigned int *sumsquared
+);
+extern void vp8_half_horiz_variance16x_h_sse2
+(
+    const unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    const unsigned char *src_ptr,
+    int src_pixels_per_line,
+    unsigned int Height,
+    int *sum,
+    unsigned int *sumsquared
+);
+extern void vp8_half_vert_variance16x_h_sse2
+(
+    const unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    const unsigned char *src_ptr,
+    int src_pixels_per_line,
+    unsigned int Height,
+    int *sum,
+    unsigned int *sumsquared
+);
+extern void vp8_filter_block2d_bil_var_ssse3
+(
+    const unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    const unsigned char *src_ptr,
+    int src_pixels_per_line,
+    unsigned int Height,
+    int  xoffset,
+    int  yoffset,
+    int *sum,
+    unsigned int *sumsquared
+);
+
+unsigned int vp8_sub_pixel_variance16x16_ssse3
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    int xsum0;
+    unsigned int xxsum0;
+
+    // note we could avoid these if statements if the calling function
+    // just called the appropriate functions inside.
+    if (xoffset == 4 && yoffset == 0)
+    {
+        vp8_half_horiz_variance16x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 16,
+            &xsum0, &xxsum0);
+    }
+    else if (xoffset == 0 && yoffset == 4)
+    {
+        vp8_half_vert_variance16x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 16,
+            &xsum0, &xxsum0);
+    }
+    else if (xoffset == 4 && yoffset == 4)
+    {
+        vp8_half_horiz_vert_variance16x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 16,
+            &xsum0, &xxsum0);
+    }
+    else
+    {
+        vp8_filter_block2d_bil_var_ssse3(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 16,
+            xoffset, yoffset,
+            &xsum0, &xxsum0);
+    }
+
+    *sse = xxsum0;
+    return (xxsum0 - ((unsigned int)(xsum0 * xsum0) >> 8));
+}
+
+unsigned int vp8_sub_pixel_variance16x8_ssse3
+(
+    const unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    const unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+
+)
+{
+    int xsum0;
+    unsigned int xxsum0;
+
+    if (xoffset == 4 && yoffset == 0)
+    {
+        vp8_half_horiz_variance16x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 8,
+            &xsum0, &xxsum0);
+    }
+    else if (xoffset == 0 && yoffset == 4)
+    {
+        vp8_half_vert_variance16x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 8,
+            &xsum0, &xxsum0);
+    }
+    else if (xoffset == 4 && yoffset == 4)
+    {
+        vp8_half_horiz_vert_variance16x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 8,
+            &xsum0, &xxsum0);
+    }
+    else
+    {
+        vp8_filter_block2d_bil_var_ssse3(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 8,
+            xoffset, yoffset,
+            &xsum0, &xxsum0);
+    }
+
+    *sse = xxsum0;
+    return (xxsum0 - ((unsigned int)(xsum0 * xsum0) >> 7));
+}
diff --git a/vp8/common/x86/vp8_asm_stubs.c b/vp8/common/x86/vp8_asm_stubs.c
new file mode 100644 (file)
index 0000000..23a7fdc
--- /dev/null
@@ -0,0 +1,552 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "vpx_ports/mem.h"
+#include "filter_x86.h"
+
+extern const short vp8_six_tap_mmx[8][6*8];
+
+extern void vp8_filter_block1d_h6_mmx
+(
+    unsigned char   *src_ptr,
+    unsigned short  *output_ptr,
+    unsigned int    src_pixels_per_line,
+    unsigned int    pixel_step,
+    unsigned int    output_height,
+    unsigned int    output_width,
+    const short      *vp8_filter
+);
+extern void vp8_filter_block1dc_v6_mmx
+(
+    unsigned short *src_ptr,
+    unsigned char  *output_ptr,
+    int             output_pitch,
+    unsigned int    pixels_per_line,
+    unsigned int    pixel_step,
+    unsigned int    output_height,
+    unsigned int    output_width,
+    const short    *vp8_filter
+);
+extern void vp8_filter_block1d8_h6_sse2
+(
+    unsigned char  *src_ptr,
+    unsigned short *output_ptr,
+    unsigned int    src_pixels_per_line,
+    unsigned int    pixel_step,
+    unsigned int    output_height,
+    unsigned int    output_width,
+    const short    *vp8_filter
+);
+extern void vp8_filter_block1d16_h6_sse2
+(
+    unsigned char  *src_ptr,
+    unsigned short *output_ptr,
+    unsigned int    src_pixels_per_line,
+    unsigned int    pixel_step,
+    unsigned int    output_height,
+    unsigned int    output_width,
+    const short    *vp8_filter
+);
+extern void vp8_filter_block1d8_v6_sse2
+(
+    unsigned short *src_ptr,
+    unsigned char *output_ptr,
+    int dst_ptich,
+    unsigned int pixels_per_line,
+    unsigned int pixel_step,
+    unsigned int output_height,
+    unsigned int output_width,
+    const short    *vp8_filter
+);
+extern void vp8_filter_block1d16_v6_sse2
+(
+    unsigned short *src_ptr,
+    unsigned char *output_ptr,
+    int dst_ptich,
+    unsigned int pixels_per_line,
+    unsigned int pixel_step,
+    unsigned int output_height,
+    unsigned int output_width,
+    const short    *vp8_filter
+);
+extern void vp8_unpack_block1d16_h6_sse2
+(
+    unsigned char  *src_ptr,
+    unsigned short *output_ptr,
+    unsigned int    src_pixels_per_line,
+    unsigned int    output_height,
+    unsigned int    output_width
+);
+extern void vp8_filter_block1d8_h6_only_sse2
+(
+    unsigned char  *src_ptr,
+    unsigned int    src_pixels_per_line,
+    unsigned char  *output_ptr,
+    int dst_ptich,
+    unsigned int    output_height,
+    const short    *vp8_filter
+);
+extern void vp8_filter_block1d16_h6_only_sse2
+(
+    unsigned char  *src_ptr,
+    unsigned int    src_pixels_per_line,
+    unsigned char  *output_ptr,
+    int dst_ptich,
+    unsigned int    output_height,
+    const short    *vp8_filter
+);
+extern void vp8_filter_block1d8_v6_only_sse2
+(
+    unsigned char *src_ptr,
+    unsigned int   src_pixels_per_line,
+    unsigned char *output_ptr,
+    int dst_ptich,
+    unsigned int   output_height,
+    const short   *vp8_filter
+);
+
+
+#if HAVE_MMX
+void vp8_sixtap_predict4x4_mmx
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+    DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 16*16);  /* Temp data bufffer used in filtering */
+    const short *HFilter, *VFilter;
+    HFilter = vp8_six_tap_mmx[xoffset];
+    vp8_filter_block1d_h6_mmx(src_ptr - (2 * src_pixels_per_line), FData2, src_pixels_per_line, 1, 9, 8, HFilter);
+    VFilter = vp8_six_tap_mmx[yoffset];
+    vp8_filter_block1dc_v6_mmx(FData2 + 8, dst_ptr, dst_pitch, 8, 4 , 4, 4, VFilter);
+
+}
+
+
+void vp8_sixtap_predict16x16_mmx
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+
+    DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 24*24);  /* Temp data bufffer used in filtering */
+
+    const short *HFilter, *VFilter;
+
+
+    HFilter = vp8_six_tap_mmx[xoffset];
+
+    vp8_filter_block1d_h6_mmx(src_ptr - (2 * src_pixels_per_line),    FData2,   src_pixels_per_line, 1, 21, 32, HFilter);
+    vp8_filter_block1d_h6_mmx(src_ptr - (2 * src_pixels_per_line) + 4,  FData2 + 4, src_pixels_per_line, 1, 21, 32, HFilter);
+    vp8_filter_block1d_h6_mmx(src_ptr - (2 * src_pixels_per_line) + 8,  FData2 + 8, src_pixels_per_line, 1, 21, 32, HFilter);
+    vp8_filter_block1d_h6_mmx(src_ptr - (2 * src_pixels_per_line) + 12, FData2 + 12, src_pixels_per_line, 1, 21, 32, HFilter);
+
+    VFilter = vp8_six_tap_mmx[yoffset];
+    vp8_filter_block1dc_v6_mmx(FData2 + 32, dst_ptr,   dst_pitch, 32, 16 , 16, 16, VFilter);
+    vp8_filter_block1dc_v6_mmx(FData2 + 36, dst_ptr + 4, dst_pitch, 32, 16 , 16, 16, VFilter);
+    vp8_filter_block1dc_v6_mmx(FData2 + 40, dst_ptr + 8, dst_pitch, 32, 16 , 16, 16, VFilter);
+    vp8_filter_block1dc_v6_mmx(FData2 + 44, dst_ptr + 12, dst_pitch, 32, 16 , 16, 16, VFilter);
+
+}
+
+
+void vp8_sixtap_predict8x8_mmx
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+
+    DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 256);    /* Temp data bufffer used in filtering */
+
+    const short *HFilter, *VFilter;
+
+    HFilter = vp8_six_tap_mmx[xoffset];
+    vp8_filter_block1d_h6_mmx(src_ptr - (2 * src_pixels_per_line),    FData2,   src_pixels_per_line, 1, 13, 16, HFilter);
+    vp8_filter_block1d_h6_mmx(src_ptr - (2 * src_pixels_per_line) + 4,  FData2 + 4, src_pixels_per_line, 1, 13, 16, HFilter);
+
+    VFilter = vp8_six_tap_mmx[yoffset];
+    vp8_filter_block1dc_v6_mmx(FData2 + 16, dst_ptr,   dst_pitch, 16, 8 , 8, 8, VFilter);
+    vp8_filter_block1dc_v6_mmx(FData2 + 20, dst_ptr + 4, dst_pitch, 16, 8 , 8, 8, VFilter);
+
+}
+
+
+void vp8_sixtap_predict8x4_mmx
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+
+    DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 256);    /* Temp data bufffer used in filtering */
+
+    const short *HFilter, *VFilter;
+
+    HFilter = vp8_six_tap_mmx[xoffset];
+    vp8_filter_block1d_h6_mmx(src_ptr - (2 * src_pixels_per_line),    FData2,   src_pixels_per_line, 1, 9, 16, HFilter);
+    vp8_filter_block1d_h6_mmx(src_ptr - (2 * src_pixels_per_line) + 4,  FData2 + 4, src_pixels_per_line, 1, 9, 16, HFilter);
+
+    VFilter = vp8_six_tap_mmx[yoffset];
+    vp8_filter_block1dc_v6_mmx(FData2 + 16, dst_ptr,   dst_pitch, 16, 8 , 4, 8, VFilter);
+    vp8_filter_block1dc_v6_mmx(FData2 + 20, dst_ptr + 4, dst_pitch, 16, 8 , 4, 8, VFilter);
+
+}
+
+
+
+void vp8_bilinear_predict16x16_mmx
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+    vp8_bilinear_predict8x8_mmx(src_ptr,   src_pixels_per_line, xoffset, yoffset, dst_ptr,   dst_pitch);
+    vp8_bilinear_predict8x8_mmx(src_ptr + 8, src_pixels_per_line, xoffset, yoffset, dst_ptr + 8, dst_pitch);
+    vp8_bilinear_predict8x8_mmx(src_ptr + 8 * src_pixels_per_line,   src_pixels_per_line, xoffset, yoffset, dst_ptr + dst_pitch * 8,   dst_pitch);
+    vp8_bilinear_predict8x8_mmx(src_ptr + 8 * src_pixels_per_line + 8, src_pixels_per_line, xoffset, yoffset, dst_ptr + dst_pitch * 8 + 8, dst_pitch);
+}
+#endif
+
+
+#if HAVE_SSE2
+void vp8_sixtap_predict16x16_sse2
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+
+)
+{
+    DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 24*24);    /* Temp data bufffer used in filtering */
+
+    const short *HFilter, *VFilter;
+
+    if (xoffset)
+    {
+        if (yoffset)
+        {
+            HFilter = vp8_six_tap_mmx[xoffset];
+            vp8_filter_block1d16_h6_sse2(src_ptr - (2 * src_pixels_per_line), FData2,   src_pixels_per_line, 1, 21, 32, HFilter);
+            VFilter = vp8_six_tap_mmx[yoffset];
+            vp8_filter_block1d16_v6_sse2(FData2 + 32, dst_ptr,   dst_pitch, 32, 16 , 16, dst_pitch, VFilter);
+        }
+        else
+        {
+            /* First-pass only */
+            HFilter = vp8_six_tap_mmx[xoffset];
+            vp8_filter_block1d16_h6_only_sse2(src_ptr, src_pixels_per_line, dst_ptr, dst_pitch, 16, HFilter);
+        }
+    }
+    else
+    {
+        /* Second-pass only */
+        VFilter = vp8_six_tap_mmx[yoffset];
+        vp8_unpack_block1d16_h6_sse2(src_ptr - (2 * src_pixels_per_line), FData2,   src_pixels_per_line, 21, 32);
+        vp8_filter_block1d16_v6_sse2(FData2 + 32, dst_ptr,   dst_pitch, 32, 16 , 16, dst_pitch, VFilter);
+    }
+}
+
+
+void vp8_sixtap_predict8x8_sse2
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+    DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 256);  /* Temp data bufffer used in filtering */
+    const short *HFilter, *VFilter;
+
+    if (xoffset)
+    {
+        if (yoffset)
+        {
+            HFilter = vp8_six_tap_mmx[xoffset];
+            vp8_filter_block1d8_h6_sse2(src_ptr - (2 * src_pixels_per_line), FData2,   src_pixels_per_line, 1, 13, 16, HFilter);
+            VFilter = vp8_six_tap_mmx[yoffset];
+            vp8_filter_block1d8_v6_sse2(FData2 + 16, dst_ptr,   dst_pitch, 16, 8 , 8, dst_pitch, VFilter);
+        }
+        else
+        {
+            /* First-pass only */
+            HFilter = vp8_six_tap_mmx[xoffset];
+            vp8_filter_block1d8_h6_only_sse2(src_ptr, src_pixels_per_line, dst_ptr, dst_pitch, 8, HFilter);
+        }
+    }
+    else
+    {
+        /* Second-pass only */
+        VFilter = vp8_six_tap_mmx[yoffset];
+        vp8_filter_block1d8_v6_only_sse2(src_ptr - (2 * src_pixels_per_line), src_pixels_per_line, dst_ptr, dst_pitch, 8, VFilter);
+    }
+}
+
+
+void vp8_sixtap_predict8x4_sse2
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+    DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 256);  /* Temp data bufffer used in filtering */
+    const short *HFilter, *VFilter;
+
+    if (xoffset)
+    {
+        if (yoffset)
+        {
+            HFilter = vp8_six_tap_mmx[xoffset];
+            vp8_filter_block1d8_h6_sse2(src_ptr - (2 * src_pixels_per_line), FData2,   src_pixels_per_line, 1, 9, 16, HFilter);
+            VFilter = vp8_six_tap_mmx[yoffset];
+            vp8_filter_block1d8_v6_sse2(FData2 + 16, dst_ptr,   dst_pitch, 16, 8 , 4, dst_pitch, VFilter);
+        }
+        else
+        {
+            /* First-pass only */
+            HFilter = vp8_six_tap_mmx[xoffset];
+            vp8_filter_block1d8_h6_only_sse2(src_ptr, src_pixels_per_line, dst_ptr, dst_pitch, 4, HFilter);
+        }
+    }
+    else
+    {
+        /* Second-pass only */
+        VFilter = vp8_six_tap_mmx[yoffset];
+        vp8_filter_block1d8_v6_only_sse2(src_ptr - (2 * src_pixels_per_line), src_pixels_per_line, dst_ptr, dst_pitch, 4, VFilter);
+    }
+}
+
+#endif
+
+#if HAVE_SSSE3
+
+extern void vp8_filter_block1d8_h6_ssse3
+(
+    unsigned char  *src_ptr,
+    unsigned int    src_pixels_per_line,
+    unsigned char  *output_ptr,
+    unsigned int    output_pitch,
+    unsigned int    output_height,
+    unsigned int    vp8_filter_index
+);
+
+extern void vp8_filter_block1d16_h6_ssse3
+(
+    unsigned char  *src_ptr,
+    unsigned int    src_pixels_per_line,
+    unsigned char  *output_ptr,
+    unsigned int    output_pitch,
+    unsigned int    output_height,
+    unsigned int    vp8_filter_index
+);
+
+extern void vp8_filter_block1d16_v6_ssse3
+(
+    unsigned char *src_ptr,
+    unsigned int   src_pitch,
+    unsigned char *output_ptr,
+    unsigned int   out_pitch,
+    unsigned int   output_height,
+    unsigned int   vp8_filter_index
+);
+
+extern void vp8_filter_block1d8_v6_ssse3
+(
+    unsigned char *src_ptr,
+    unsigned int   src_pitch,
+    unsigned char *output_ptr,
+    unsigned int   out_pitch,
+    unsigned int   output_height,
+    unsigned int   vp8_filter_index
+);
+
+extern void vp8_filter_block1d4_h6_ssse3
+(
+    unsigned char  *src_ptr,
+    unsigned int    src_pixels_per_line,
+    unsigned char  *output_ptr,
+    unsigned int    output_pitch,
+    unsigned int    output_height,
+    unsigned int    vp8_filter_index
+);
+
+extern void vp8_filter_block1d4_v6_ssse3
+(
+    unsigned char *src_ptr,
+    unsigned int   src_pitch,
+    unsigned char *output_ptr,
+    unsigned int   out_pitch,
+    unsigned int   output_height,
+    unsigned int   vp8_filter_index
+);
+
+void vp8_sixtap_predict16x16_ssse3
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+
+)
+{
+    DECLARE_ALIGNED_ARRAY(16, unsigned char, FData2, 24*24);
+
+    if (xoffset)
+    {
+        if (yoffset)
+        {
+            vp8_filter_block1d16_h6_ssse3(src_ptr - (2 * src_pixels_per_line), src_pixels_per_line, FData2, 16, 21, xoffset);
+            vp8_filter_block1d16_v6_ssse3(FData2 , 16, dst_ptr, dst_pitch, 16, yoffset);
+        }
+        else
+        {
+            /* First-pass only */
+            vp8_filter_block1d16_h6_ssse3(src_ptr, src_pixels_per_line, dst_ptr, dst_pitch, 16, xoffset);
+        }
+    }
+    else
+    {
+        /* Second-pass only */
+        vp8_filter_block1d16_v6_ssse3(src_ptr - (2 * src_pixels_per_line) , src_pixels_per_line, dst_ptr, dst_pitch, 16, yoffset);
+    }
+}
+
+void vp8_sixtap_predict8x8_ssse3
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+    DECLARE_ALIGNED_ARRAY(16, unsigned char, FData2, 256);
+
+    if (xoffset)
+    {
+        if (yoffset)
+        {
+            vp8_filter_block1d8_h6_ssse3(src_ptr - (2 * src_pixels_per_line), src_pixels_per_line, FData2, 8, 13, xoffset);
+            vp8_filter_block1d8_v6_ssse3(FData2, 8, dst_ptr, dst_pitch, 8, yoffset);
+        }
+        else
+        {
+            vp8_filter_block1d8_h6_ssse3(src_ptr, src_pixels_per_line, dst_ptr, dst_pitch, 8, xoffset);
+        }
+    }
+    else
+    {
+        /* Second-pass only */
+        vp8_filter_block1d8_v6_ssse3(src_ptr - (2 * src_pixels_per_line), src_pixels_per_line, dst_ptr, dst_pitch, 8, yoffset);
+    }
+}
+
+
+void vp8_sixtap_predict8x4_ssse3
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+    DECLARE_ALIGNED_ARRAY(16, unsigned char, FData2, 256);
+
+    if (xoffset)
+    {
+        if (yoffset)
+        {
+            vp8_filter_block1d8_h6_ssse3(src_ptr - (2 * src_pixels_per_line), src_pixels_per_line, FData2, 8, 9, xoffset);
+            vp8_filter_block1d8_v6_ssse3(FData2, 8, dst_ptr, dst_pitch, 4, yoffset);
+        }
+        else
+        {
+            /* First-pass only */
+            vp8_filter_block1d8_h6_ssse3(src_ptr, src_pixels_per_line, dst_ptr, dst_pitch, 4, xoffset);
+        }
+    }
+    else
+    {
+        /* Second-pass only */
+        vp8_filter_block1d8_v6_ssse3(src_ptr - (2 * src_pixels_per_line), src_pixels_per_line, dst_ptr, dst_pitch, 4, yoffset);
+    }
+}
+
+void vp8_sixtap_predict4x4_ssse3
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+  DECLARE_ALIGNED_ARRAY(16, unsigned char, FData2, 4*9);
+
+  if (xoffset)
+  {
+      if (yoffset)
+      {
+          vp8_filter_block1d4_h6_ssse3(src_ptr - (2 * src_pixels_per_line), src_pixels_per_line, FData2, 4, 9, xoffset);
+          vp8_filter_block1d4_v6_ssse3(FData2, 4, dst_ptr, dst_pitch, 4, yoffset);
+      }
+      else
+      {
+          vp8_filter_block1d4_h6_ssse3(src_ptr, src_pixels_per_line, dst_ptr, dst_pitch, 4, xoffset);
+      }
+  }
+  else
+  {
+      vp8_filter_block1d4_v6_ssse3(src_ptr - (2 * src_pixels_per_line), src_pixels_per_line, dst_ptr, dst_pitch, 4, yoffset);
+  }
+
+}
+
+#endif
diff --git a/vp8/decoder/asm_dec_offsets.c b/vp8/decoder/asm_dec_offsets.c
new file mode 100644 (file)
index 0000000..842a0d5
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_ports/asm_offsets.h"
+#include "onyxd_int.h"
+
+BEGIN
+
+DEFINE(bool_decoder_user_buffer_end,            offsetof(BOOL_DECODER, user_buffer_end));
+DEFINE(bool_decoder_user_buffer,                offsetof(BOOL_DECODER, user_buffer));
+DEFINE(bool_decoder_value,                      offsetof(BOOL_DECODER, value));
+DEFINE(bool_decoder_count,                      offsetof(BOOL_DECODER, count));
+DEFINE(bool_decoder_range,                      offsetof(BOOL_DECODER, range));
+
+END
+
+/* add asserts for any offset that is not supported by assembly code */
+/* add asserts for any size that is not supported by assembly code */
diff --git a/vp8/decoder/dboolhuff.c b/vp8/decoder/dboolhuff.c
new file mode 100644 (file)
index 0000000..7e7b05a
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "dboolhuff.h"
+#include "vpx_ports/mem.h"
+#include "vpx_mem/vpx_mem.h"
+
+int vp8dx_start_decode(BOOL_DECODER *br,
+                       const unsigned char *source,
+                       unsigned int source_sz)
+{
+    br->user_buffer_end = source+source_sz;
+    br->user_buffer     = source;
+    br->value    = 0;
+    br->count    = -8;
+    br->range    = 255;
+
+    if (source_sz && !source)
+        return 1;
+
+    /* Populate the buffer */
+    vp8dx_bool_decoder_fill(br);
+
+    return 0;
+}
+
+
+void vp8dx_bool_decoder_fill(BOOL_DECODER *br)
+{
+    const unsigned char *bufptr;
+    const unsigned char *bufend;
+    VP8_BD_VALUE         value;
+    int                  count;
+    bufend = br->user_buffer_end;
+    bufptr = br->user_buffer;
+    value = br->value;
+    count = br->count;
+
+    VP8DX_BOOL_DECODER_FILL(count, value, bufptr, bufend);
+
+    br->user_buffer = bufptr;
+    br->value = value;
+    br->count = count;
+}
diff --git a/vp8/decoder/dboolhuff.h b/vp8/decoder/dboolhuff.h
new file mode 100644 (file)
index 0000000..880c185
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef DBOOLHUFF_H
+#define DBOOLHUFF_H
+#include <stddef.h>
+#include <limits.h>
+#include "vpx_config.h"
+#include "vpx_ports/mem.h"
+#include "vpx/vpx_integer.h"
+
+typedef size_t VP8_BD_VALUE;
+
+# define VP8_BD_VALUE_SIZE ((int)sizeof(VP8_BD_VALUE)*CHAR_BIT)
+/*This is meant to be a large, positive constant that can still be efficiently
+   loaded as an immediate (on platforms like ARM, for example).
+  Even relatively modest values like 100 would work fine.*/
+# define VP8_LOTS_OF_BITS (0x40000000)
+
+typedef struct
+{
+    const unsigned char *user_buffer_end;
+    const unsigned char *user_buffer;
+    VP8_BD_VALUE         value;
+    int                  count;
+    unsigned int         range;
+} BOOL_DECODER;
+
+DECLARE_ALIGNED(16, extern const unsigned char, vp8_norm[256]);
+
+int vp8dx_start_decode(BOOL_DECODER *br,
+                       const unsigned char *source,
+                       unsigned int source_sz);
+
+void vp8dx_bool_decoder_fill(BOOL_DECODER *br);
+
+/*The refill loop is used in several places, so define it in a macro to make
+   sure they're all consistent.
+  An inline function would be cleaner, but has a significant penalty, because
+   multiple BOOL_DECODER fields must be modified, and the compiler is not smart
+   enough to eliminate the stores to those fields and the subsequent reloads
+   from them when inlining the function.*/
+#define VP8DX_BOOL_DECODER_FILL(_count,_value,_bufptr,_bufend) \
+    do \
+    { \
+        int shift = VP8_BD_VALUE_SIZE - 8 - ((_count) + 8); \
+        int loop_end, x; \
+        size_t bits_left = ((_bufend)-(_bufptr))*CHAR_BIT; \
+        \
+        x = shift + CHAR_BIT - bits_left; \
+        loop_end = 0; \
+        if(x >= 0) \
+        { \
+            (_count) += VP8_LOTS_OF_BITS; \
+            loop_end = x; \
+            if(!bits_left) break; \
+        } \
+        while(shift >= loop_end) \
+        { \
+            (_count) += CHAR_BIT; \
+            (_value) |= (VP8_BD_VALUE)*(_bufptr)++ << shift; \
+            shift -= CHAR_BIT; \
+        } \
+    } \
+    while(0) \
+
+
+static int vp8dx_decode_bool(BOOL_DECODER *br, int probability) {
+    unsigned int bit = 0;
+    VP8_BD_VALUE value;
+    unsigned int split;
+    VP8_BD_VALUE bigsplit;
+    int count;
+    unsigned int range;
+
+    split = 1 + (((br->range - 1) * probability) >> 8);
+
+    if(br->count < 0)
+        vp8dx_bool_decoder_fill(br);
+
+    value = br->value;
+    count = br->count;
+
+    bigsplit = (VP8_BD_VALUE)split << (VP8_BD_VALUE_SIZE - 8);
+
+    range = split;
+
+    if (value >= bigsplit)
+    {
+        range = br->range - split;
+        value = value - bigsplit;
+        bit = 1;
+    }
+
+    {
+        register unsigned int shift = vp8_norm[range];
+        range <<= shift;
+        value <<= shift;
+        count -= shift;
+    }
+    br->value = value;
+    br->count = count;
+    br->range = range;
+
+    return bit;
+}
+
+static int vp8_decode_value(BOOL_DECODER *br, int bits)
+{
+    int z = 0;
+    int bit;
+
+    for (bit = bits - 1; bit >= 0; bit--)
+    {
+        z |= (vp8dx_decode_bool(br, 0x80) << bit);
+    }
+
+    return z;
+}
+
+static int vp8dx_bool_error(BOOL_DECODER *br)
+{
+    /* Check if we have reached the end of the buffer.
+     *
+     * Variable 'count' stores the number of bits in the 'value' buffer, minus
+     * 8. The top byte is part of the algorithm, and the remainder is buffered
+     * to be shifted into it. So if count == 8, the top 16 bits of 'value' are
+     * occupied, 8 for the algorithm and 8 in the buffer.
+     *
+     * When reading a byte from the user's buffer, count is filled with 8 and
+     * one byte is filled into the value buffer. When we reach the end of the
+     * data, count is additionally filled with VP8_LOTS_OF_BITS. So when
+     * count == VP8_LOTS_OF_BITS - 1, the user's data has been exhausted.
+     */
+    if ((br->count > VP8_BD_VALUE_SIZE) && (br->count < VP8_LOTS_OF_BITS))
+    {
+       /* We have tried to decode bits after the end of
+        * stream was encountered.
+        */
+        return 1;
+    }
+
+    /* No error. */
+    return 0;
+}
+#endif
diff --git a/vp8/decoder/decodemv.c b/vp8/decoder/decodemv.c
new file mode 100644 (file)
index 0000000..51e2420
--- /dev/null
@@ -0,0 +1,666 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "treereader.h"
+#include "vp8/common/entropymv.h"
+#include "vp8/common/entropymode.h"
+#include "onyxd_int.h"
+#include "vp8/common/findnearmv.h"
+
+#if CONFIG_DEBUG
+#include <assert.h>
+#endif
+static B_PREDICTION_MODE read_bmode(vp8_reader *bc, const vp8_prob *p)
+{
+    const int i = vp8_treed_read(bc, vp8_bmode_tree, p);
+
+    return (B_PREDICTION_MODE)i;
+}
+
+static MB_PREDICTION_MODE read_ymode(vp8_reader *bc, const vp8_prob *p)
+{
+    const int i = vp8_treed_read(bc, vp8_ymode_tree, p);
+
+    return (MB_PREDICTION_MODE)i;
+}
+
+static MB_PREDICTION_MODE read_kf_ymode(vp8_reader *bc, const vp8_prob *p)
+{
+    const int i = vp8_treed_read(bc, vp8_kf_ymode_tree, p);
+
+    return (MB_PREDICTION_MODE)i;
+}
+
+static MB_PREDICTION_MODE read_uv_mode(vp8_reader *bc, const vp8_prob *p)
+{
+    const int i = vp8_treed_read(bc, vp8_uv_mode_tree, p);
+
+    return (MB_PREDICTION_MODE)i;
+}
+
+static void read_kf_modes(VP8D_COMP *pbi, MODE_INFO *mi)
+{
+    vp8_reader *const bc = & pbi->bc;
+    const int mis = pbi->common.mode_info_stride;
+
+    mi->mbmi.ref_frame = INTRA_FRAME;
+    mi->mbmi.mode = read_kf_ymode(bc, pbi->common.kf_ymode_prob);
+
+    if (mi->mbmi.mode == B_PRED)
+    {
+        int i = 0;
+        mi->mbmi.is_4x4 = 1;
+
+        do
+        {
+            const B_PREDICTION_MODE A = above_block_mode(mi, i, mis);
+            const B_PREDICTION_MODE L = left_block_mode(mi, i);
+
+            mi->bmi[i].as_mode =
+                read_bmode(bc, pbi->common.kf_bmode_prob [A] [L]);
+        }
+        while (++i < 16);
+    }
+
+    mi->mbmi.uv_mode = read_uv_mode(bc, pbi->common.kf_uv_mode_prob);
+}
+
+static int read_mvcomponent(vp8_reader *r, const MV_CONTEXT *mvc)
+{
+    const vp8_prob *const p = (const vp8_prob *) mvc;
+    int x = 0;
+
+    if (vp8_read(r, p [mvpis_short]))  /* Large */
+    {
+        int i = 0;
+
+        do
+        {
+            x += vp8_read(r, p [MVPbits + i]) << i;
+        }
+        while (++i < 3);
+
+        i = mvlong_width - 1;  /* Skip bit 3, which is sometimes implicit */
+
+        do
+        {
+            x += vp8_read(r, p [MVPbits + i]) << i;
+        }
+        while (--i > 3);
+
+        if (!(x & 0xFFF0)  ||  vp8_read(r, p [MVPbits + 3]))
+            x += 8;
+    }
+    else   /* small */
+        x = vp8_treed_read(r, vp8_small_mvtree, p + MVPshort);
+
+    if (x  &&  vp8_read(r, p [MVPsign]))
+        x = -x;
+
+    return x;
+}
+
+static void read_mv(vp8_reader *r, MV *mv, const MV_CONTEXT *mvc)
+{
+    mv->row = (short)(read_mvcomponent(r,   mvc) << 1);
+    mv->col = (short)(read_mvcomponent(r, ++mvc) << 1);
+}
+
+
+static void read_mvcontexts(vp8_reader *bc, MV_CONTEXT *mvc)
+{
+    int i = 0;
+
+    do
+    {
+        const vp8_prob *up = vp8_mv_update_probs[i].prob;
+        vp8_prob *p = (vp8_prob *)(mvc + i);
+        vp8_prob *const pstop = p + MVPcount;
+
+        do
+        {
+            if (vp8_read(bc, *up++))
+            {
+                const vp8_prob x = (vp8_prob)vp8_read_literal(bc, 7);
+
+                *p = x ? x << 1 : 1;
+            }
+        }
+        while (++p < pstop);
+    }
+    while (++i < 2);
+}
+
+static const unsigned char mbsplit_fill_count[4] = {8, 8, 4, 1};
+static const unsigned char mbsplit_fill_offset[4][16] = {
+    { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15},
+    { 0,  1,  4,  5,  8,  9, 12, 13,  2,  3,   6,  7, 10, 11, 14, 15},
+    { 0,  1,  4,  5,  2,  3,  6,  7,  8,  9,  12, 13, 10, 11, 14, 15},
+    { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15}
+};
+
+
+static void mb_mode_mv_init(VP8D_COMP *pbi)
+{
+    vp8_reader *const bc = & pbi->bc;
+    MV_CONTEXT *const mvc = pbi->common.fc.mvc;
+
+#if CONFIG_ERROR_CONCEALMENT
+    /* Default is that no macroblock is corrupt, therefore we initialize
+     * mvs_corrupt_from_mb to something very big, which we can be sure is
+     * outside the frame. */
+    pbi->mvs_corrupt_from_mb = UINT_MAX;
+#endif
+    pbi->prob_skip_false = 0;
+    if (pbi->common.mb_no_coeff_skip)
+        pbi->prob_skip_false = (vp8_prob)vp8_read_literal(bc, 8);
+
+    if(pbi->common.frame_type != KEY_FRAME)
+    {
+        pbi->prob_intra = (vp8_prob)vp8_read_literal(bc, 8);
+        pbi->prob_last  = (vp8_prob)vp8_read_literal(bc, 8);
+        pbi->prob_gf    = (vp8_prob)vp8_read_literal(bc, 8);
+
+        if (vp8_read_bit(bc))
+        {
+            int i = 0;
+
+            do
+            {
+                pbi->common.fc.ymode_prob[i] =
+                    (vp8_prob) vp8_read_literal(bc, 8);
+            }
+            while (++i < 4);
+        }
+
+        if (vp8_read_bit(bc))
+        {
+            int i = 0;
+
+            do
+            {
+                pbi->common.fc.uv_mode_prob[i] =
+                    (vp8_prob) vp8_read_literal(bc, 8);
+            }
+            while (++i < 3);
+        }
+
+        read_mvcontexts(bc, mvc);
+    }
+}
+
+const vp8_prob vp8_sub_mv_ref_prob3 [8][VP8_SUBMVREFS-1] =
+{
+    { 147, 136, 18 },   /* SUBMVREF_NORMAL          */
+    { 223, 1  , 34 },   /* SUBMVREF_LEFT_ABOVE_SAME */
+    { 106, 145, 1  },   /* SUBMVREF_LEFT_ZED        */
+    { 208, 1  , 1  },   /* SUBMVREF_LEFT_ABOVE_ZED  */
+    { 179, 121, 1  },   /* SUBMVREF_ABOVE_ZED       */
+    { 223, 1  , 34 },   /* SUBMVREF_LEFT_ABOVE_SAME */
+    { 179, 121, 1  },   /* SUBMVREF_ABOVE_ZED       */
+    { 208, 1  , 1  }    /* SUBMVREF_LEFT_ABOVE_ZED  */
+};
+
+static
+const vp8_prob * get_sub_mv_ref_prob(const int left, const int above)
+{
+    int lez = (left == 0);
+    int aez = (above == 0);
+    int lea = (left == above);
+    const vp8_prob * prob;
+
+    prob = vp8_sub_mv_ref_prob3[(aez << 2) |
+                                (lez << 1) |
+                                (lea)];
+
+    return prob;
+}
+
+static void decode_split_mv(vp8_reader *const bc, MODE_INFO *mi,
+                        const MODE_INFO *left_mb, const MODE_INFO *above_mb,
+                        MB_MODE_INFO *mbmi, int_mv best_mv,
+                        MV_CONTEXT *const mvc, int mb_to_left_edge,
+                        int mb_to_right_edge, int mb_to_top_edge,
+                        int mb_to_bottom_edge)
+{
+    int s;      /* split configuration (16x8, 8x16, 8x8, 4x4) */
+    int num_p;  /* number of partitions in the split configuration
+                  (see vp8_mbsplit_count) */
+    int j = 0;
+
+    s = 3;
+    num_p = 16;
+    if( vp8_read(bc, 110) )
+    {
+        s = 2;
+        num_p = 4;
+        if( vp8_read(bc, 111) )
+        {
+            s = vp8_read(bc, 150);
+            num_p = 2;
+        }
+    }
+
+    do  /* for each subset j */
+    {
+        int_mv leftmv, abovemv;
+        int_mv blockmv;
+        int k;  /* first block in subset j */
+
+        const vp8_prob *prob;
+        k = vp8_mbsplit_offset[s][j];
+
+        if (!(k & 3))
+        {
+            /* On L edge, get from MB to left of us */
+            if(left_mb->mbmi.mode != SPLITMV)
+                leftmv.as_int =  left_mb->mbmi.mv.as_int;
+            else
+                leftmv.as_int =  (left_mb->bmi + k + 4 - 1)->mv.as_int;
+        }
+        else
+            leftmv.as_int =  (mi->bmi + k - 1)->mv.as_int;
+
+        if (!(k >> 2))
+        {
+            /* On top edge, get from MB above us */
+            if(above_mb->mbmi.mode != SPLITMV)
+                abovemv.as_int =  above_mb->mbmi.mv.as_int;
+            else
+                abovemv.as_int =  (above_mb->bmi + k + 16 - 4)->mv.as_int;
+        }
+        else
+            abovemv.as_int = (mi->bmi + k - 4)->mv.as_int;
+
+        prob = get_sub_mv_ref_prob(leftmv.as_int, abovemv.as_int);
+
+        if( vp8_read(bc, prob[0]) )
+        {
+            if( vp8_read(bc, prob[1]) )
+            {
+                blockmv.as_int = 0;
+                if( vp8_read(bc, prob[2]) )
+                {
+                    blockmv.as_mv.row = read_mvcomponent(bc, &mvc[0]) << 1;
+                    blockmv.as_mv.row += best_mv.as_mv.row;
+                    blockmv.as_mv.col = read_mvcomponent(bc, &mvc[1]) << 1;
+                    blockmv.as_mv.col += best_mv.as_mv.col;
+
+                    mbmi->need_to_clamp_mvs |= vp8_check_mv_bounds(&blockmv,
+                                                              mb_to_left_edge,
+                                                              mb_to_right_edge,
+                                                              mb_to_top_edge,
+                                                              mb_to_bottom_edge);
+                }
+            }
+            else
+            {
+                blockmv.as_int = abovemv.as_int;
+                mbmi->need_to_clamp_mvs |= above_mb->mbmi.need_to_clamp_mvs;
+            }
+        }
+        else
+        {
+            blockmv.as_int = leftmv.as_int;
+            mbmi->need_to_clamp_mvs |= left_mb->mbmi.need_to_clamp_mvs;
+        }
+
+        {
+            /* Fill (uniform) modes, mvs of jth subset.
+             Must do it here because ensuing subsets can
+             refer back to us via "left" or "above". */
+            const unsigned char *fill_offset;
+            unsigned int fill_count = mbsplit_fill_count[s];
+
+            fill_offset = &mbsplit_fill_offset[s]
+                             [(unsigned char)j * mbsplit_fill_count[s]];
+
+            do {
+                mi->bmi[ *fill_offset].mv.as_int = blockmv.as_int;
+                fill_offset++;
+            }while (--fill_count);
+        }
+
+    }
+    while (++j < num_p);
+
+    mbmi->partitioning = s;
+}
+
+static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi)
+{
+    vp8_reader *const bc = & pbi->bc;
+    mbmi->ref_frame = (MV_REFERENCE_FRAME) vp8_read(bc, pbi->prob_intra);
+    if (mbmi->ref_frame)    /* inter MB */
+    {
+        enum {CNT_INTRA, CNT_NEAREST, CNT_NEAR, CNT_SPLITMV};
+        int cnt[4];
+        int *cntx = cnt;
+        int_mv near_mvs[4];
+        int_mv *nmv = near_mvs;
+        const int mis = pbi->mb.mode_info_stride;
+        const MODE_INFO *above = mi - mis;
+        const MODE_INFO *left = mi - 1;
+        const MODE_INFO *aboveleft = above - 1;
+        int *ref_frame_sign_bias = pbi->common.ref_frame_sign_bias;
+
+        mbmi->need_to_clamp_mvs = 0;
+
+        if (vp8_read(bc, pbi->prob_last))
+        {
+            mbmi->ref_frame =
+                (MV_REFERENCE_FRAME)((int)(2 + vp8_read(bc, pbi->prob_gf)));
+        }
+
+        /* Zero accumulators */
+        nmv[0].as_int = nmv[1].as_int = nmv[2].as_int = 0;
+        cnt[0] = cnt[1] = cnt[2] = cnt[3] = 0;
+
+        /* Process above */
+        if (above->mbmi.ref_frame != INTRA_FRAME)
+        {
+            if (above->mbmi.mv.as_int)
+            {
+                (++nmv)->as_int = above->mbmi.mv.as_int;
+                mv_bias(ref_frame_sign_bias[above->mbmi.ref_frame],
+                        mbmi->ref_frame, nmv, ref_frame_sign_bias);
+                ++cntx;
+            }
+
+            *cntx += 2;
+        }
+
+        /* Process left */
+        if (left->mbmi.ref_frame != INTRA_FRAME)
+        {
+            if (left->mbmi.mv.as_int)
+            {
+                int_mv this_mv;
+
+                this_mv.as_int = left->mbmi.mv.as_int;
+                mv_bias(ref_frame_sign_bias[left->mbmi.ref_frame],
+                        mbmi->ref_frame, &this_mv, ref_frame_sign_bias);
+
+                if (this_mv.as_int != nmv->as_int)
+                {
+                    (++nmv)->as_int = this_mv.as_int;
+                    ++cntx;
+                }
+
+                *cntx += 2;
+            }
+            else
+                cnt[CNT_INTRA] += 2;
+        }
+
+        /* Process above left */
+        if (aboveleft->mbmi.ref_frame != INTRA_FRAME)
+        {
+            if (aboveleft->mbmi.mv.as_int)
+            {
+                int_mv this_mv;
+
+                this_mv.as_int = aboveleft->mbmi.mv.as_int;
+                mv_bias(ref_frame_sign_bias[aboveleft->mbmi.ref_frame],
+                        mbmi->ref_frame, &this_mv, ref_frame_sign_bias);
+
+                if (this_mv.as_int != nmv->as_int)
+                {
+                    (++nmv)->as_int = this_mv.as_int;
+                    ++cntx;
+                }
+
+                *cntx += 1;
+            }
+            else
+                cnt[CNT_INTRA] += 1;
+        }
+
+        if( vp8_read(bc, vp8_mode_contexts [cnt[CNT_INTRA]] [0]) )
+        {
+
+            /* If we have three distinct MV's ... */
+            /* See if above-left MV can be merged with NEAREST */
+            cnt[CNT_NEAREST] += ( (cnt[CNT_SPLITMV] > 0) &
+                (nmv->as_int == near_mvs[CNT_NEAREST].as_int));
+
+            /* Swap near and nearest if necessary */
+            if (cnt[CNT_NEAR] > cnt[CNT_NEAREST])
+            {
+                int tmp;
+                tmp = cnt[CNT_NEAREST];
+                cnt[CNT_NEAREST] = cnt[CNT_NEAR];
+                cnt[CNT_NEAR] = tmp;
+                tmp = near_mvs[CNT_NEAREST].as_int;
+                near_mvs[CNT_NEAREST].as_int = near_mvs[CNT_NEAR].as_int;
+                near_mvs[CNT_NEAR].as_int = tmp;
+            }
+
+            if( vp8_read(bc, vp8_mode_contexts [cnt[CNT_NEAREST]] [1]) )
+            {
+
+                if( vp8_read(bc, vp8_mode_contexts [cnt[CNT_NEAR]] [2]) )
+                {
+                    int mb_to_top_edge;
+                    int mb_to_bottom_edge;
+                    int mb_to_left_edge;
+                    int mb_to_right_edge;
+                    MV_CONTEXT *const mvc = pbi->common.fc.mvc;
+                    int near_index;
+
+                    mb_to_top_edge = pbi->mb.mb_to_top_edge;
+                    mb_to_bottom_edge = pbi->mb.mb_to_bottom_edge;
+                    mb_to_top_edge -= LEFT_TOP_MARGIN;
+                    mb_to_bottom_edge += RIGHT_BOTTOM_MARGIN;
+                    mb_to_right_edge = pbi->mb.mb_to_right_edge;
+                    mb_to_right_edge += RIGHT_BOTTOM_MARGIN;
+                    mb_to_left_edge = pbi->mb.mb_to_left_edge;
+                    mb_to_left_edge -= LEFT_TOP_MARGIN;
+
+                    /* Use near_mvs[0] to store the "best" MV */
+                    near_index = CNT_INTRA +
+                        (cnt[CNT_NEAREST] >= cnt[CNT_INTRA]);
+
+                    vp8_clamp_mv2(&near_mvs[near_index], &pbi->mb);
+
+                    cnt[CNT_SPLITMV] = ((above->mbmi.mode == SPLITMV)
+                                        + (left->mbmi.mode == SPLITMV)) * 2
+                                       + (aboveleft->mbmi.mode == SPLITMV);
+
+                    if( vp8_read(bc, vp8_mode_contexts [cnt[CNT_SPLITMV]] [3]) )
+                    {
+                        decode_split_mv(bc, mi, left, above,
+                                                    mbmi,
+                                                    near_mvs[near_index],
+                                                    mvc, mb_to_left_edge,
+                                                    mb_to_right_edge,
+                                                    mb_to_top_edge,
+                                                    mb_to_bottom_edge);
+                        mbmi->mv.as_int = mi->bmi[15].mv.as_int;
+                        mbmi->mode =  SPLITMV;
+                        mbmi->is_4x4 = 1;
+                    }
+                    else
+                    {
+                        int_mv *const mbmi_mv = & mbmi->mv;
+                        read_mv(bc, &mbmi_mv->as_mv, (const MV_CONTEXT *) mvc);
+                        mbmi_mv->as_mv.row += near_mvs[near_index].as_mv.row;
+                        mbmi_mv->as_mv.col += near_mvs[near_index].as_mv.col;
+
+                        /* Don't need to check this on NEARMV and NEARESTMV
+                         * modes since those modes clamp the MV. The NEWMV mode
+                         * does not, so signal to the prediction stage whether
+                         * special handling may be required.
+                         */
+                        mbmi->need_to_clamp_mvs =
+                            vp8_check_mv_bounds(mbmi_mv, mb_to_left_edge,
+                                                mb_to_right_edge,
+                                                mb_to_top_edge,
+                                                mb_to_bottom_edge);
+                        mbmi->mode =  NEWMV;
+                    }
+                }
+                else
+                {
+                    mbmi->mode =  NEARMV;
+                    vp8_clamp_mv2(&near_mvs[CNT_NEAR], &pbi->mb);
+                    mbmi->mv.as_int = near_mvs[CNT_NEAR].as_int;
+                }
+            }
+            else
+            {
+                mbmi->mode =  NEARESTMV;
+                vp8_clamp_mv2(&near_mvs[CNT_NEAREST], &pbi->mb);
+                mbmi->mv.as_int = near_mvs[CNT_NEAREST].as_int;
+            }
+        }
+        else
+        {
+            mbmi->mode =  ZEROMV;
+            mbmi->mv.as_int = 0;
+        }
+
+#if CONFIG_ERROR_CONCEALMENT
+        if(pbi->ec_enabled && (mbmi->mode != SPLITMV))
+        {
+            mi->bmi[ 0].mv.as_int =
+            mi->bmi[ 1].mv.as_int =
+            mi->bmi[ 2].mv.as_int =
+            mi->bmi[ 3].mv.as_int =
+            mi->bmi[ 4].mv.as_int =
+            mi->bmi[ 5].mv.as_int =
+            mi->bmi[ 6].mv.as_int =
+            mi->bmi[ 7].mv.as_int =
+            mi->bmi[ 8].mv.as_int =
+            mi->bmi[ 9].mv.as_int =
+            mi->bmi[10].mv.as_int =
+            mi->bmi[11].mv.as_int =
+            mi->bmi[12].mv.as_int =
+            mi->bmi[13].mv.as_int =
+            mi->bmi[14].mv.as_int =
+            mi->bmi[15].mv.as_int = mbmi->mv.as_int;
+        }
+#endif
+    }
+    else
+    {
+        /* required for left and above block mv */
+        mbmi->mv.as_int = 0;
+
+        /* MB is intra coded */
+        if ((mbmi->mode = read_ymode(bc, pbi->common.fc.ymode_prob)) == B_PRED)
+        {
+            int j = 0;
+            mbmi->is_4x4 = 1;
+            do
+            {
+                mi->bmi[j].as_mode = read_bmode(bc, pbi->common.fc.bmode_prob);
+            }
+            while (++j < 16);
+        }
+
+        mbmi->uv_mode = read_uv_mode(bc, pbi->common.fc.uv_mode_prob);
+    }
+
+}
+
+static void read_mb_features(vp8_reader *r, MB_MODE_INFO *mi, MACROBLOCKD *x)
+{
+    /* Is segmentation enabled */
+    if (x->segmentation_enabled && x->update_mb_segmentation_map)
+    {
+        /* If so then read the segment id. */
+        if (vp8_read(r, x->mb_segment_tree_probs[0]))
+            mi->segment_id =
+                (unsigned char)(2 + vp8_read(r, x->mb_segment_tree_probs[2]));
+        else
+            mi->segment_id =
+                (unsigned char)(vp8_read(r, x->mb_segment_tree_probs[1]));
+    }
+}
+
+static void decode_mb_mode_mvs(VP8D_COMP *pbi, MODE_INFO *mi,
+                               MB_MODE_INFO *mbmi)
+{
+    /* Read the Macroblock segmentation map if it is being updated explicitly
+     * this frame (reset to 0 above by default)
+     * By default on a key frame reset all MBs to segment 0
+     */
+    if (pbi->mb.update_mb_segmentation_map)
+        read_mb_features(&pbi->bc, &mi->mbmi, &pbi->mb);
+    else if(pbi->common.frame_type == KEY_FRAME)
+        mi->mbmi.segment_id = 0;
+
+    /* Read the macroblock coeff skip flag if this feature is in use,
+     * else default to 0 */
+    if (pbi->common.mb_no_coeff_skip)
+        mi->mbmi.mb_skip_coeff = vp8_read(&pbi->bc, pbi->prob_skip_false);
+    else
+        mi->mbmi.mb_skip_coeff = 0;
+
+    mi->mbmi.is_4x4 = 0;
+    if(pbi->common.frame_type == KEY_FRAME)
+        read_kf_modes(pbi, mi);
+    else
+        read_mb_modes_mv(pbi, mi, &mi->mbmi);
+
+}
+
+void vp8_decode_mode_mvs(VP8D_COMP *pbi)
+{
+    MODE_INFO *mi = pbi->common.mi;
+    int mb_row = -1;
+    int mb_to_right_edge_start;
+
+    mb_mode_mv_init(pbi);
+
+    pbi->mb.mb_to_top_edge = 0;
+    pbi->mb.mb_to_bottom_edge = ((pbi->common.mb_rows - 1) * 16) << 3;
+    mb_to_right_edge_start = ((pbi->common.mb_cols - 1) * 16) << 3;
+
+    while (++mb_row < pbi->common.mb_rows)
+    {
+        int mb_col = -1;
+
+        pbi->mb.mb_to_left_edge =  0;
+        pbi->mb.mb_to_right_edge = mb_to_right_edge_start;
+
+        while (++mb_col < pbi->common.mb_cols)
+        {
+#if CONFIG_ERROR_CONCEALMENT
+            int mb_num = mb_row * pbi->common.mb_cols + mb_col;
+#endif
+
+            decode_mb_mode_mvs(pbi, mi, &mi->mbmi);
+
+#if CONFIG_ERROR_CONCEALMENT
+            /* look for corruption. set mvs_corrupt_from_mb to the current
+             * mb_num if the frame is corrupt from this macroblock. */
+            if (vp8dx_bool_error(&pbi->bc) && mb_num < pbi->mvs_corrupt_from_mb)
+            {
+                pbi->mvs_corrupt_from_mb = mb_num;
+                /* no need to continue since the partition is corrupt from
+                 * here on.
+                 */
+                return;
+            }
+#endif
+
+            pbi->mb.mb_to_left_edge -= (16 << 3);
+            pbi->mb.mb_to_right_edge -= (16 << 3);
+            mi++;       /* next macroblock */
+        }
+        pbi->mb.mb_to_top_edge -= (16 << 3);
+        pbi->mb.mb_to_bottom_edge -= (16 << 3);
+
+        mi++;           /* skip left predictor each row */
+    }
+}
diff --git a/vp8/decoder/decodemv.h b/vp8/decoder/decodemv.h
new file mode 100644 (file)
index 0000000..9403424
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "onyxd_int.h"
+
+void vp8_decode_mode_mvs(VP8D_COMP *);
diff --git a/vp8/decoder/decoderthreading.h b/vp8/decoder/decoderthreading.h
new file mode 100644 (file)
index 0000000..60c39d1
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+
+
+
+#ifndef _DECODER_THREADING_H
+#define _DECODER_THREADING_H
+
+#if CONFIG_MULTITHREAD
+extern void vp8mt_decode_mb_rows(VP8D_COMP *pbi, MACROBLOCKD *xd);
+extern void vp8_decoder_remove_threads(VP8D_COMP *pbi);
+extern void vp8_decoder_create_threads(VP8D_COMP *pbi);
+extern void vp8mt_alloc_temp_buffers(VP8D_COMP *pbi, int width, int prev_mb_rows);
+extern void vp8mt_de_alloc_temp_buffers(VP8D_COMP *pbi, int mb_rows);
+#endif
+
+#endif
diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c
new file mode 100644 (file)
index 0000000..62a068b
--- /dev/null
@@ -0,0 +1,1192 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "onyxd_int.h"
+#include "vp8/common/header.h"
+#include "vp8/common/reconintra4x4.h"
+#include "vp8/common/reconinter.h"
+#include "detokenize.h"
+#include "vp8/common/invtrans.h"
+#include "vp8/common/alloccommon.h"
+#include "vp8/common/entropymode.h"
+#include "vp8/common/quant_common.h"
+#include "vpx_scale/vpxscale.h"
+#include "vp8/common/setupintrarecon.h"
+
+#include "decodemv.h"
+#include "vp8/common/extend.h"
+#if CONFIG_ERROR_CONCEALMENT
+#include "error_concealment.h"
+#endif
+#include "vpx_mem/vpx_mem.h"
+#include "vp8/common/threading.h"
+#include "decoderthreading.h"
+#include "dboolhuff.h"
+
+#include <assert.h>
+#include <stdio.h>
+
+void vp8cx_init_de_quantizer(VP8D_COMP *pbi)
+{
+    int Q;
+    VP8_COMMON *const pc = & pbi->common;
+
+    for (Q = 0; Q < QINDEX_RANGE; Q++)
+    {
+        pc->Y1dequant[Q][0] = (short)vp8_dc_quant(Q, pc->y1dc_delta_q);
+        pc->Y2dequant[Q][0] = (short)vp8_dc2quant(Q, pc->y2dc_delta_q);
+        pc->UVdequant[Q][0] = (short)vp8_dc_uv_quant(Q, pc->uvdc_delta_q);
+
+        pc->Y1dequant[Q][1] = (short)vp8_ac_yquant(Q);
+        pc->Y2dequant[Q][1] = (short)vp8_ac2quant(Q, pc->y2ac_delta_q);
+        pc->UVdequant[Q][1] = (short)vp8_ac_uv_quant(Q, pc->uvac_delta_q);
+    }
+}
+
+void vp8_mb_init_dequantizer(VP8D_COMP *pbi, MACROBLOCKD *xd)
+{
+    int i;
+    int QIndex;
+    MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;
+    VP8_COMMON *const pc = & pbi->common;
+
+    /* Decide whether to use the default or alternate baseline Q value. */
+    if (xd->segmentation_enabled)
+    {
+        /* Abs Value */
+        if (xd->mb_segement_abs_delta == SEGMENT_ABSDATA)
+            QIndex = xd->segment_feature_data[MB_LVL_ALT_Q][mbmi->segment_id];
+
+        /* Delta Value */
+        else
+        {
+            QIndex = pc->base_qindex + xd->segment_feature_data[MB_LVL_ALT_Q][mbmi->segment_id];
+            QIndex = (QIndex >= 0) ? ((QIndex <= MAXQ) ? QIndex : MAXQ) : 0;    /* Clamp to valid range */
+        }
+    }
+    else
+        QIndex = pc->base_qindex;
+
+    /* Set up the macroblock dequant constants */
+    xd->dequant_y1_dc[0] = 1;
+    xd->dequant_y1[0] = pc->Y1dequant[QIndex][0];
+    xd->dequant_y2[0] = pc->Y2dequant[QIndex][0];
+    xd->dequant_uv[0] = pc->UVdequant[QIndex][0];
+
+    for (i = 1; i < 16; i++)
+    {
+        xd->dequant_y1_dc[i] =
+        xd->dequant_y1[i] = pc->Y1dequant[QIndex][1];
+        xd->dequant_y2[i] = pc->Y2dequant[QIndex][1];
+        xd->dequant_uv[i] = pc->UVdequant[QIndex][1];
+    }
+}
+
+static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd,
+                              unsigned int mb_idx)
+{
+    MB_PREDICTION_MODE mode;
+    int i;
+#if CONFIG_ERROR_CONCEALMENT
+    int corruption_detected = 0;
+#endif
+
+    if (xd->mode_info_context->mbmi.mb_skip_coeff)
+    {
+        vp8_reset_mb_tokens_context(xd);
+    }
+    else if (!vp8dx_bool_error(xd->current_bc))
+    {
+        int eobtotal;
+        eobtotal = vp8_decode_mb_tokens(pbi, xd);
+
+        /* Special case:  Force the loopfilter to skip when eobtotal is zero */
+        xd->mode_info_context->mbmi.mb_skip_coeff = (eobtotal==0);
+    }
+
+    mode = xd->mode_info_context->mbmi.mode;
+
+    if (xd->segmentation_enabled)
+        vp8_mb_init_dequantizer(pbi, xd);
+
+
+#if CONFIG_ERROR_CONCEALMENT
+
+    if(pbi->ec_active)
+    {
+        int throw_residual;
+        /* When we have independent partitions we can apply residual even
+         * though other partitions within the frame are corrupt.
+         */
+        throw_residual = (!pbi->independent_partitions &&
+                          pbi->frame_corrupt_residual);
+        throw_residual = (throw_residual || vp8dx_bool_error(xd->current_bc));
+
+        if ((mb_idx >= pbi->mvs_corrupt_from_mb || throw_residual))
+        {
+            /* MB with corrupt residuals or corrupt mode/motion vectors.
+             * Better to use the predictor as reconstruction.
+             */
+            pbi->frame_corrupt_residual = 1;
+            vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
+            vp8_conceal_corrupt_mb(xd);
+
+
+            corruption_detected = 1;
+
+            /* force idct to be skipped for B_PRED and use the
+             * prediction only for reconstruction
+             * */
+            vpx_memset(xd->eobs, 0, 25);
+        }
+    }
+#endif
+
+    /* do prediction */
+    if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME)
+    {
+        vp8_build_intra_predictors_mbuv_s(xd,
+                                          xd->recon_above[1],
+                                          xd->recon_above[2],
+                                          xd->recon_left[1],
+                                          xd->recon_left[2],
+                                          xd->recon_left_stride[1],
+                                          xd->dst.u_buffer, xd->dst.v_buffer,
+                                          xd->dst.uv_stride);
+
+        if (mode != B_PRED)
+        {
+            vp8_build_intra_predictors_mby_s(xd,
+                                                 xd->recon_above[0],
+                                                 xd->recon_left[0],
+                                                 xd->recon_left_stride[0],
+                                                 xd->dst.y_buffer,
+                                                 xd->dst.y_stride);
+        }
+        else
+        {
+            short *DQC = xd->dequant_y1;
+            int dst_stride = xd->dst.y_stride;
+            unsigned char *base_dst = xd->dst.y_buffer;
+
+            /* clear out residual eob info */
+            if(xd->mode_info_context->mbmi.mb_skip_coeff)
+                vpx_memset(xd->eobs, 0, 25);
+
+            intra_prediction_down_copy(xd, xd->recon_above[0] + 16);
+
+            for (i = 0; i < 16; i++)
+            {
+                BLOCKD *b = &xd->block[i];
+                int b_mode = xd->mode_info_context->bmi[i].as_mode;
+                unsigned char *yabove;
+                unsigned char *yleft;
+                int left_stride;
+                unsigned char top_left;
+
+                yabove = base_dst + b->offset - dst_stride;
+                yleft = base_dst + b->offset - 1;
+                left_stride = dst_stride;
+                top_left = yabove[-1];
+
+                //                vp8_intra4x4_predict (base_dst + b->offset, dst_stride, b_mode,
+                  //                                    base_dst + b->offset, dst_stride );
+                vp8_intra4x4_predict_d_c(yabove, yleft, left_stride,
+                                       b_mode,
+                                       base_dst + b->offset, dst_stride,
+                                       top_left);
+
+                if (xd->eobs[i])
+                {
+                    if (xd->eobs[i] > 1)
+                    {
+                    vp8_dequant_idct_add
+                            (b->qcoeff, DQC,
+                                base_dst + b->offset, dst_stride);
+                    }
+                    else
+                    {
+                        vp8_dc_only_idct_add
+                            (b->qcoeff[0] * DQC[0],
+                                base_dst + b->offset, dst_stride,
+                                base_dst + b->offset, dst_stride);
+                        ((int *)b->qcoeff)[0] = 0;
+                    }
+                }
+            }
+        }
+    }
+    else
+    {
+        vp8_build_inter_predictors_mb(xd);
+    }
+
+
+#if CONFIG_ERROR_CONCEALMENT
+    if (corruption_detected)
+    {
+        return;
+    }
+#endif
+
+    if(!xd->mode_info_context->mbmi.mb_skip_coeff)
+    {
+        /* dequantization and idct */
+        if (mode != B_PRED)
+        {
+            short *DQC = xd->dequant_y1;
+
+            if (mode != SPLITMV)
+            {
+                BLOCKD *b = &xd->block[24];
+
+                /* do 2nd order transform on the dc block */
+                if (xd->eobs[24] > 1)
+                {
+                    vp8_dequantize_b(b, xd->dequant_y2);
+
+                    vp8_short_inv_walsh4x4(&b->dqcoeff[0],
+                        xd->qcoeff);
+                    ((int *)b->qcoeff)[0] = 0;
+                    ((int *)b->qcoeff)[1] = 0;
+                    ((int *)b->qcoeff)[2] = 0;
+                    ((int *)b->qcoeff)[3] = 0;
+                    ((int *)b->qcoeff)[4] = 0;
+                    ((int *)b->qcoeff)[5] = 0;
+                    ((int *)b->qcoeff)[6] = 0;
+                    ((int *)b->qcoeff)[7] = 0;
+                }
+                else
+                {
+                    b->dqcoeff[0] = b->qcoeff[0] * xd->dequant_y2[0];
+                    vp8_short_inv_walsh4x4_1(&b->dqcoeff[0],
+                        xd->qcoeff);
+                    ((int *)b->qcoeff)[0] = 0;
+                }
+
+                /* override the dc dequant constant in order to preserve the
+                 * dc components
+                 */
+                DQC = xd->dequant_y1_dc;
+            }
+
+            vp8_dequant_idct_add_y_block
+                            (xd->qcoeff, DQC,
+                             xd->dst.y_buffer,
+                             xd->dst.y_stride, xd->eobs);
+        }
+
+        vp8_dequant_idct_add_uv_block
+                        (xd->qcoeff+16*16, xd->dequant_uv,
+                         xd->dst.u_buffer, xd->dst.v_buffer,
+                         xd->dst.uv_stride, xd->eobs+16);
+    }
+}
+
+static int get_delta_q(vp8_reader *bc, int prev, int *q_update)
+{
+    int ret_val = 0;
+
+    if (vp8_read_bit(bc))
+    {
+        ret_val = vp8_read_literal(bc, 4);
+
+        if (vp8_read_bit(bc))
+            ret_val = -ret_val;
+    }
+
+    /* Trigger a quantizer update if the delta-q value has changed */
+    if (ret_val != prev)
+        *q_update = 1;
+
+    return ret_val;
+}
+
+#ifdef PACKET_TESTING
+#include <stdio.h>
+FILE *vpxlog = 0;
+#endif
+
+static void decode_mb_rows(VP8D_COMP *pbi)
+{
+    VP8_COMMON *const pc = & pbi->common;
+    MACROBLOCKD *const xd  = & pbi->mb;
+
+    int ibc = 0;
+    int num_part = 1 << pc->multi_token_partition;
+
+    int recon_yoffset, recon_uvoffset;
+    int mb_row, mb_col;
+    int mb_idx = 0;
+    int dst_fb_idx = pc->new_fb_idx;
+    int recon_y_stride = pc->yv12_fb[dst_fb_idx].y_stride;
+    int recon_uv_stride = pc->yv12_fb[dst_fb_idx].uv_stride;
+
+    unsigned char *ref_buffer[MAX_REF_FRAMES][3];
+    unsigned char *dst_buffer[3];
+    int i;
+    int ref_fb_index[MAX_REF_FRAMES];
+    int ref_fb_corrupted[MAX_REF_FRAMES];
+
+    ref_fb_corrupted[INTRA_FRAME] = 0;
+
+    ref_fb_index[LAST_FRAME]    = pc->lst_fb_idx;
+    ref_fb_index[GOLDEN_FRAME]  = pc->gld_fb_idx;
+    ref_fb_index[ALTREF_FRAME]  = pc->alt_fb_idx;
+
+    for(i = 1; i < MAX_REF_FRAMES; i++)
+    {
+        ref_buffer[i][0] = pc->yv12_fb[ref_fb_index[i]].y_buffer;
+        ref_buffer[i][1] = pc->yv12_fb[ref_fb_index[i]].u_buffer;
+        ref_buffer[i][2] = pc->yv12_fb[ref_fb_index[i]].v_buffer;
+
+        ref_fb_corrupted[i] = pc->yv12_fb[ref_fb_index[i]].corrupted;
+    }
+
+    dst_buffer[0] = pc->yv12_fb[dst_fb_idx].y_buffer;
+    dst_buffer[1] = pc->yv12_fb[dst_fb_idx].u_buffer;
+    dst_buffer[2] = pc->yv12_fb[dst_fb_idx].v_buffer;
+
+    xd->up_available = 0;
+
+    /* Decode the individual macro block */
+    for (mb_row = 0; mb_row < pc->mb_rows; mb_row++)
+    {
+        if (num_part > 1)
+        {
+            xd->current_bc = & pbi->mbc[ibc];
+            ibc++;
+
+            if (ibc == num_part)
+                ibc = 0;
+        }
+
+        recon_yoffset = mb_row * recon_y_stride * 16;
+        recon_uvoffset = mb_row * recon_uv_stride * 8;
+
+        /* reset contexts */
+        xd->above_context = pc->above_context;
+        vpx_memset(xd->left_context, 0, sizeof(ENTROPY_CONTEXT_PLANES));
+
+        xd->left_available = 0;
+
+        xd->mb_to_top_edge = -((mb_row * 16)) << 3;
+        xd->mb_to_bottom_edge = ((pc->mb_rows - 1 - mb_row) * 16) << 3;
+
+        xd->recon_above[0] = dst_buffer[0] + recon_yoffset;
+        xd->recon_above[1] = dst_buffer[1] + recon_uvoffset;
+        xd->recon_above[2] = dst_buffer[2] + recon_uvoffset;
+
+        xd->recon_left[0] = xd->recon_above[0] - 1;
+        xd->recon_left[1] = xd->recon_above[1] - 1;
+        xd->recon_left[2] = xd->recon_above[2] - 1;
+
+        xd->recon_above[0] -= xd->dst.y_stride;
+        xd->recon_above[1] -= xd->dst.uv_stride;
+        xd->recon_above[2] -= xd->dst.uv_stride;
+
+        //TODO: move to outside row loop
+        xd->recon_left_stride[0] = xd->dst.y_stride;
+        xd->recon_left_stride[1] = xd->dst.uv_stride;
+
+        for (mb_col = 0; mb_col < pc->mb_cols; mb_col++)
+        {
+            /* Distance of Mb to the various image edges.
+             * These are specified to 8th pel as they are always compared to values
+             * that are in 1/8th pel units
+             */
+            xd->mb_to_left_edge = -((mb_col * 16) << 3);
+            xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
+
+#if CONFIG_ERROR_CONCEALMENT
+            {
+                int corrupt_residual = (!pbi->independent_partitions &&
+                                       pbi->frame_corrupt_residual) ||
+                                       vp8dx_bool_error(xd->current_bc);
+                if (pbi->ec_active &&
+                    xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME &&
+                    corrupt_residual)
+                {
+                    /* We have an intra block with corrupt coefficients, better to
+                     * conceal with an inter block. Interpolate MVs from neighboring
+                     * MBs.
+                     *
+                     * Note that for the first mb with corrupt residual in a frame,
+                     * we might not discover that before decoding the residual. That
+                     * happens after this check, and therefore no inter concealment
+                     * will be done.
+                     */
+                    vp8_interpolate_motion(xd,
+                                           mb_row, mb_col,
+                                           pc->mb_rows, pc->mb_cols,
+                                           pc->mode_info_stride);
+                }
+            }
+#endif
+
+            xd->dst.y_buffer = dst_buffer[0] + recon_yoffset;
+            xd->dst.u_buffer = dst_buffer[1] + recon_uvoffset;
+            xd->dst.v_buffer = dst_buffer[2] + recon_uvoffset;
+
+            xd->pre.y_buffer = ref_buffer[xd->mode_info_context->mbmi.ref_frame][0] + recon_yoffset;
+            xd->pre.u_buffer = ref_buffer[xd->mode_info_context->mbmi.ref_frame][1] + recon_uvoffset;
+            xd->pre.v_buffer = ref_buffer[xd->mode_info_context->mbmi.ref_frame][2] + recon_uvoffset;
+
+            /* propagate errors from reference frames */
+            xd->corrupted |= ref_fb_corrupted[xd->mode_info_context->mbmi.ref_frame];
+
+            decode_macroblock(pbi, xd, mb_idx);
+
+            mb_idx++;
+            xd->left_available = 1;
+
+            /* check if the boolean decoder has suffered an error */
+            xd->corrupted |= vp8dx_bool_error(xd->current_bc);
+
+            xd->recon_above[0] += 16;
+            xd->recon_above[1] += 8;
+            xd->recon_above[2] += 8;
+            xd->recon_left[0] += 16;
+            xd->recon_left[1] += 8;
+            xd->recon_left[2] += 8;
+
+
+            recon_yoffset += 16;
+            recon_uvoffset += 8;
+
+            ++xd->mode_info_context;  /* next mb */
+
+            xd->above_context++;
+
+        }
+
+        /* adjust to the next row of mbs */
+        vp8_extend_mb_row(
+            &pc->yv12_fb[dst_fb_idx],
+            xd->dst.y_buffer + 16, xd->dst.u_buffer + 8, xd->dst.v_buffer + 8
+        );
+
+        ++xd->mode_info_context;      /* skip prediction column */
+        xd->up_available = 1;
+
+    }
+}
+
+static unsigned int read_partition_size(const unsigned char *cx_size)
+{
+    const unsigned int size =
+        cx_size[0] + (cx_size[1] << 8) + (cx_size[2] << 16);
+    return size;
+}
+
+static int read_is_valid(const unsigned char *start,
+                         size_t               len,
+                         const unsigned char *end)
+{
+    return (start + len > start && start + len <= end);
+}
+
+static unsigned int read_available_partition_size(
+                                       VP8D_COMP *pbi,
+                                       const unsigned char *token_part_sizes,
+                                       const unsigned char *fragment_start,
+                                       const unsigned char *first_fragment_end,
+                                       const unsigned char *fragment_end,
+                                       int i,
+                                       int num_part)
+{
+    VP8_COMMON* pc = &pbi->common;
+    const unsigned char *partition_size_ptr = token_part_sizes + i * 3;
+    unsigned int partition_size = 0;
+    ptrdiff_t bytes_left = fragment_end - fragment_start;
+    /* Calculate the length of this partition. The last partition
+     * size is implicit. If the partition size can't be read, then
+     * either use the remaining data in the buffer (for EC mode)
+     * or throw an error.
+     */
+    if (i < num_part - 1)
+    {
+        if (read_is_valid(partition_size_ptr, 3, first_fragment_end))
+            partition_size = read_partition_size(partition_size_ptr);
+        else if (pbi->ec_active)
+            partition_size = bytes_left;
+        else
+            vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+                               "Truncated partition size data");
+    }
+    else
+        partition_size = bytes_left;
+
+    /* Validate the calculated partition length. If the buffer
+     * described by the partition can't be fully read, then restrict
+     * it to the portion that can be (for EC mode) or throw an error.
+     */
+    if (!read_is_valid(fragment_start, partition_size, fragment_end))
+    {
+        if (pbi->ec_active)
+            partition_size = bytes_left;
+        else
+            vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+                               "Truncated packet or corrupt partition "
+                               "%d length", i + 1);
+    }
+    return partition_size;
+}
+
+
+static void setup_token_decoder(VP8D_COMP *pbi,
+                                const unsigned char* token_part_sizes)
+{
+    vp8_reader *bool_decoder = &pbi->bc2;
+    unsigned int partition_idx;
+    int fragment_idx;
+    int num_token_partitions;
+    const unsigned char *first_fragment_end = pbi->fragments[0] +
+                                          pbi->fragment_sizes[0];
+
+    TOKEN_PARTITION multi_token_partition =
+            (TOKEN_PARTITION)vp8_read_literal(&pbi->bc, 2);
+    if (!vp8dx_bool_error(&pbi->bc))
+        pbi->common.multi_token_partition = multi_token_partition;
+    num_token_partitions = 1 << pbi->common.multi_token_partition;
+    if (num_token_partitions > 1)
+    {
+        CHECK_MEM_ERROR(pbi->mbc, vpx_malloc(num_token_partitions *
+                                             sizeof(vp8_reader)));
+        bool_decoder = pbi->mbc;
+    }
+
+    /* Check for partitions within the fragments and unpack the fragments
+     * so that each fragment pointer points to its corresponding partition. */
+    for (fragment_idx = 0; fragment_idx < pbi->num_fragments; ++fragment_idx)
+    {
+        unsigned int fragment_size = pbi->fragment_sizes[fragment_idx];
+        const unsigned char *fragment_end = pbi->fragments[fragment_idx] +
+                                            fragment_size;
+        /* Special case for handling the first partition since we have already
+         * read its size. */
+        if (fragment_idx == 0)
+        {
+            /* Size of first partition + token partition sizes element */
+            ptrdiff_t ext_first_part_size = token_part_sizes -
+                pbi->fragments[0] + 3 * (num_token_partitions - 1);
+            fragment_size -= ext_first_part_size;
+            if (fragment_size > 0)
+            {
+                pbi->fragment_sizes[0] = ext_first_part_size;
+                /* The fragment contains an additional partition. Move to
+                 * next. */
+                fragment_idx++;
+                pbi->fragments[fragment_idx] = pbi->fragments[0] +
+                  pbi->fragment_sizes[0];
+            }
+        }
+        /* Split the chunk into partitions read from the bitstream */
+        while (fragment_size > 0)
+        {
+            ptrdiff_t partition_size = read_available_partition_size(
+                                                 pbi,
+                                                 token_part_sizes,
+                                                 pbi->fragments[fragment_idx],
+                                                 first_fragment_end,
+                                                 fragment_end,
+                                                 fragment_idx - 1,
+                                                 num_token_partitions);
+            pbi->fragment_sizes[fragment_idx] = partition_size;
+            fragment_size -= partition_size;
+            assert(fragment_idx <= num_token_partitions);
+            if (fragment_size > 0)
+            {
+                /* The fragment contains an additional partition.
+                 * Move to next. */
+                fragment_idx++;
+                pbi->fragments[fragment_idx] =
+                    pbi->fragments[fragment_idx - 1] + partition_size;
+            }
+        }
+    }
+
+    pbi->num_fragments = num_token_partitions + 1;
+
+    for (partition_idx = 1; partition_idx < pbi->num_fragments; ++partition_idx)
+    {
+        if (vp8dx_start_decode(bool_decoder,
+                               pbi->fragments[partition_idx],
+                               pbi->fragment_sizes[partition_idx]))
+            vpx_internal_error(&pbi->common.error, VPX_CODEC_MEM_ERROR,
+                               "Failed to allocate bool decoder %d",
+                               partition_idx);
+
+        bool_decoder++;
+    }
+
+#if CONFIG_MULTITHREAD
+    /* Clamp number of decoder threads */
+    if (pbi->decoding_thread_count > num_token_partitions - 1)
+        pbi->decoding_thread_count = num_token_partitions - 1;
+#endif
+}
+
+static void stop_token_decoder(VP8D_COMP *pbi)
+{
+    VP8_COMMON *pc = &pbi->common;
+
+    if (pc->multi_token_partition != ONE_PARTITION)
+    {
+        vpx_free(pbi->mbc);
+        pbi->mbc = NULL;
+    }
+}
+
+static void init_frame(VP8D_COMP *pbi)
+{
+    VP8_COMMON *const pc = & pbi->common;
+    MACROBLOCKD *const xd  = & pbi->mb;
+
+    if (pc->frame_type == KEY_FRAME)
+    {
+        /* Various keyframe initializations */
+        vpx_memcpy(pc->fc.mvc, vp8_default_mv_context, sizeof(vp8_default_mv_context));
+
+        vp8_init_mbmode_probs(pc);
+
+        vp8_default_coef_probs(pc);
+        vp8_kf_default_bmode_probs(pc->kf_bmode_prob);
+
+        /* reset the segment feature data to 0 with delta coding (Default state). */
+        vpx_memset(xd->segment_feature_data, 0, sizeof(xd->segment_feature_data));
+        xd->mb_segement_abs_delta = SEGMENT_DELTADATA;
+
+        /* reset the mode ref deltasa for loop filter */
+        vpx_memset(xd->ref_lf_deltas, 0, sizeof(xd->ref_lf_deltas));
+        vpx_memset(xd->mode_lf_deltas, 0, sizeof(xd->mode_lf_deltas));
+
+        /* All buffers are implicitly updated on key frames. */
+        pc->refresh_golden_frame = 1;
+        pc->refresh_alt_ref_frame = 1;
+        pc->copy_buffer_to_gf = 0;
+        pc->copy_buffer_to_arf = 0;
+
+        /* Note that Golden and Altref modes cannot be used on a key frame so
+         * ref_frame_sign_bias[] is undefined and meaningless
+         */
+        pc->ref_frame_sign_bias[GOLDEN_FRAME] = 0;
+        pc->ref_frame_sign_bias[ALTREF_FRAME] = 0;
+    }
+    else
+    {
+        if (!pc->use_bilinear_mc_filter)
+            pc->mcomp_filter_type = SIXTAP;
+        else
+            pc->mcomp_filter_type = BILINEAR;
+
+        /* To enable choice of different interploation filters */
+        if (pc->mcomp_filter_type == SIXTAP)
+        {
+            xd->subpixel_predict        = vp8_sixtap_predict4x4;
+            xd->subpixel_predict8x4     = vp8_sixtap_predict8x4;
+            xd->subpixel_predict8x8     = vp8_sixtap_predict8x8;
+            xd->subpixel_predict16x16   = vp8_sixtap_predict16x16;
+        }
+        else
+        {
+            xd->subpixel_predict        = vp8_bilinear_predict4x4;
+            xd->subpixel_predict8x4     = vp8_bilinear_predict8x4;
+            xd->subpixel_predict8x8     = vp8_bilinear_predict8x8;
+            xd->subpixel_predict16x16   = vp8_bilinear_predict16x16;
+        }
+
+        if (pbi->decoded_key_frame && pbi->ec_enabled && !pbi->ec_active)
+            pbi->ec_active = 1;
+    }
+
+    xd->left_context = &pc->left_context;
+    xd->mode_info_context = pc->mi;
+    xd->frame_type = pc->frame_type;
+    xd->mode_info_context->mbmi.mode = DC_PRED;
+    xd->mode_info_stride = pc->mode_info_stride;
+    xd->corrupted = 0; /* init without corruption */
+
+    xd->fullpixel_mask = 0xffffffff;
+    if(pc->full_pixel)
+        xd->fullpixel_mask = 0xfffffff8;
+
+}
+
+int vp8_decode_frame(VP8D_COMP *pbi)
+{
+    vp8_reader *const bc = & pbi->bc;
+    VP8_COMMON *const pc = & pbi->common;
+    MACROBLOCKD *const xd  = & pbi->mb;
+    const unsigned char *data = pbi->fragments[0];
+    const unsigned char *data_end =  data + pbi->fragment_sizes[0];
+    ptrdiff_t first_partition_length_in_bytes;
+
+    int i, j, k, l;
+    const int *const mb_feature_data_bits = vp8_mb_feature_data_bits;
+    int corrupt_tokens = 0;
+    int prev_independent_partitions = pbi->independent_partitions;
+
+    /* start with no corruption of current frame */
+    xd->corrupted = 0;
+    pc->yv12_fb[pc->new_fb_idx].corrupted = 0;
+
+    if (data_end - data < 3)
+    {
+        if (!pbi->ec_active)
+        {
+            vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+                               "Truncated packet");
+        }
+
+        /* Declare the missing frame as an inter frame since it will
+           be handled as an inter frame when we have estimated its
+           motion vectors. */
+        pc->frame_type = INTER_FRAME;
+        pc->version = 0;
+        pc->show_frame = 1;
+        first_partition_length_in_bytes = 0;
+    }
+    else
+    {
+        pc->frame_type = (FRAME_TYPE)(data[0] & 1);
+        pc->version = (data[0] >> 1) & 7;
+        pc->show_frame = (data[0] >> 4) & 1;
+        first_partition_length_in_bytes =
+            (data[0] | (data[1] << 8) | (data[2] << 16)) >> 5;
+
+        if (!pbi->ec_active && (data + first_partition_length_in_bytes > data_end
+            || data + first_partition_length_in_bytes < data))
+            vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+                               "Truncated packet or corrupt partition 0 length");
+
+        data += 3;
+
+        vp8_setup_version(pc);
+
+        if (pc->frame_type == KEY_FRAME)
+        {
+            const int Width = pc->Width;
+            const int Height = pc->Height;
+
+            /* vet via sync code */
+            /* When error concealment is enabled we should only check the sync
+             * code if we have enough bits available
+             */
+            if (!pbi->ec_active || data + 3 < data_end)
+            {
+                if (data[0] != 0x9d || data[1] != 0x01 || data[2] != 0x2a)
+                    vpx_internal_error(&pc->error, VPX_CODEC_UNSUP_BITSTREAM,
+                                   "Invalid frame sync code");
+            }
+
+            /* If error concealment is enabled we should only parse the new size
+             * if we have enough data. Otherwise we will end up with the wrong
+             * size.
+             */
+            if (!pbi->ec_active || data + 6 < data_end)
+            {
+                pc->Width = (data[3] | (data[4] << 8)) & 0x3fff;
+                pc->horiz_scale = data[4] >> 6;
+                pc->Height = (data[5] | (data[6] << 8)) & 0x3fff;
+                pc->vert_scale = data[6] >> 6;
+            }
+            data += 7;
+
+            if (Width != pc->Width  ||  Height != pc->Height)
+            {
+                int prev_mb_rows = pc->mb_rows;
+
+                if (pc->Width <= 0)
+                {
+                    pc->Width = Width;
+                    vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+                                       "Invalid frame width");
+                }
+
+                if (pc->Height <= 0)
+                {
+                    pc->Height = Height;
+                    vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+                                       "Invalid frame height");
+                }
+
+                if (vp8_alloc_frame_buffers(pc, pc->Width, pc->Height))
+                    vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
+                                       "Failed to allocate frame buffers");
+
+#if CONFIG_ERROR_CONCEALMENT
+                pbi->overlaps = NULL;
+                if (pbi->ec_enabled)
+                {
+                    if (vp8_alloc_overlap_lists(pbi))
+                        vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
+                                           "Failed to allocate overlap lists "
+                                           "for error concealment");
+                }
+#endif
+
+#if CONFIG_MULTITHREAD
+                if (pbi->b_multithreaded_rd)
+                    vp8mt_alloc_temp_buffers(pbi, pc->Width, prev_mb_rows);
+#endif
+            }
+        }
+    }
+
+    if ((!pbi->decoded_key_frame && pc->frame_type != KEY_FRAME) ||
+        pc->Width == 0 || pc->Height == 0)
+    {
+        return -1;
+    }
+
+    init_frame(pbi);
+
+    if (vp8dx_start_decode(bc, data, data_end - data))
+        vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
+                           "Failed to allocate bool decoder 0");
+    if (pc->frame_type == KEY_FRAME) {
+        pc->clr_type    = (YUV_TYPE)vp8_read_bit(bc);
+        pc->clamp_type  = (CLAMP_TYPE)vp8_read_bit(bc);
+    }
+
+    /* Is segmentation enabled */
+    xd->segmentation_enabled = (unsigned char)vp8_read_bit(bc);
+
+    if (xd->segmentation_enabled)
+    {
+        /* Signal whether or not the segmentation map is being explicitly updated this frame. */
+        xd->update_mb_segmentation_map = (unsigned char)vp8_read_bit(bc);
+        xd->update_mb_segmentation_data = (unsigned char)vp8_read_bit(bc);
+
+        if (xd->update_mb_segmentation_data)
+        {
+            xd->mb_segement_abs_delta = (unsigned char)vp8_read_bit(bc);
+
+            vpx_memset(xd->segment_feature_data, 0, sizeof(xd->segment_feature_data));
+
+            /* For each segmentation feature (Quant and loop filter level) */
+            for (i = 0; i < MB_LVL_MAX; i++)
+            {
+                for (j = 0; j < MAX_MB_SEGMENTS; j++)
+                {
+                    /* Frame level data */
+                    if (vp8_read_bit(bc))
+                    {
+                        xd->segment_feature_data[i][j] = (signed char)vp8_read_literal(bc, mb_feature_data_bits[i]);
+
+                        if (vp8_read_bit(bc))
+                            xd->segment_feature_data[i][j] = -xd->segment_feature_data[i][j];
+                    }
+                    else
+                        xd->segment_feature_data[i][j] = 0;
+                }
+            }
+        }
+
+        if (xd->update_mb_segmentation_map)
+        {
+            /* Which macro block level features are enabled */
+            vpx_memset(xd->mb_segment_tree_probs, 255, sizeof(xd->mb_segment_tree_probs));
+
+            /* Read the probs used to decode the segment id for each macro block. */
+            for (i = 0; i < MB_FEATURE_TREE_PROBS; i++)
+            {
+                /* If not explicitly set value is defaulted to 255 by memset above */
+                if (vp8_read_bit(bc))
+                    xd->mb_segment_tree_probs[i] = (vp8_prob)vp8_read_literal(bc, 8);
+            }
+        }
+    }
+    else
+    {
+        /* No segmentation updates on this frame */
+        xd->update_mb_segmentation_map = 0;
+        xd->update_mb_segmentation_data = 0;
+    }
+
+    /* Read the loop filter level and type */
+    pc->filter_type = (LOOPFILTERTYPE) vp8_read_bit(bc);
+    pc->filter_level = vp8_read_literal(bc, 6);
+    pc->sharpness_level = vp8_read_literal(bc, 3);
+
+    /* Read in loop filter deltas applied at the MB level based on mode or ref frame. */
+    xd->mode_ref_lf_delta_update = 0;
+    xd->mode_ref_lf_delta_enabled = (unsigned char)vp8_read_bit(bc);
+
+    if (xd->mode_ref_lf_delta_enabled)
+    {
+        /* Do the deltas need to be updated */
+        xd->mode_ref_lf_delta_update = (unsigned char)vp8_read_bit(bc);
+
+        if (xd->mode_ref_lf_delta_update)
+        {
+            /* Send update */
+            for (i = 0; i < MAX_REF_LF_DELTAS; i++)
+            {
+                if (vp8_read_bit(bc))
+                {
+                    /*sign = vp8_read_bit( bc );*/
+                    xd->ref_lf_deltas[i] = (signed char)vp8_read_literal(bc, 6);
+
+                    if (vp8_read_bit(bc))        /* Apply sign */
+                        xd->ref_lf_deltas[i] = xd->ref_lf_deltas[i] * -1;
+                }
+            }
+
+            /* Send update */
+            for (i = 0; i < MAX_MODE_LF_DELTAS; i++)
+            {
+                if (vp8_read_bit(bc))
+                {
+                    /*sign = vp8_read_bit( bc );*/
+                    xd->mode_lf_deltas[i] = (signed char)vp8_read_literal(bc, 6);
+
+                    if (vp8_read_bit(bc))        /* Apply sign */
+                        xd->mode_lf_deltas[i] = xd->mode_lf_deltas[i] * -1;
+                }
+            }
+        }
+    }
+
+    setup_token_decoder(pbi, data + first_partition_length_in_bytes);
+
+    xd->current_bc = &pbi->bc2;
+
+    /* Read the default quantizers. */
+    {
+        int Q, q_update;
+
+        Q = vp8_read_literal(bc, 7);  /* AC 1st order Q = default */
+        pc->base_qindex = Q;
+        q_update = 0;
+        pc->y1dc_delta_q = get_delta_q(bc, pc->y1dc_delta_q, &q_update);
+        pc->y2dc_delta_q = get_delta_q(bc, pc->y2dc_delta_q, &q_update);
+        pc->y2ac_delta_q = get_delta_q(bc, pc->y2ac_delta_q, &q_update);
+        pc->uvdc_delta_q = get_delta_q(bc, pc->uvdc_delta_q, &q_update);
+        pc->uvac_delta_q = get_delta_q(bc, pc->uvac_delta_q, &q_update);
+
+        if (q_update)
+            vp8cx_init_de_quantizer(pbi);
+
+        /* MB level dequantizer setup */
+        vp8_mb_init_dequantizer(pbi, &pbi->mb);
+    }
+
+    /* Determine if the golden frame or ARF buffer should be updated and how.
+     * For all non key frames the GF and ARF refresh flags and sign bias
+     * flags must be set explicitly.
+     */
+    if (pc->frame_type != KEY_FRAME)
+    {
+        /* Should the GF or ARF be updated from the current frame */
+        pc->refresh_golden_frame = vp8_read_bit(bc);
+#if CONFIG_ERROR_CONCEALMENT
+        /* Assume we shouldn't refresh golden if the bit is missing */
+        xd->corrupted |= vp8dx_bool_error(bc);
+        if (pbi->ec_active && xd->corrupted)
+            pc->refresh_golden_frame = 0;
+#endif
+
+        pc->refresh_alt_ref_frame = vp8_read_bit(bc);
+#if CONFIG_ERROR_CONCEALMENT
+        /* Assume we shouldn't refresh altref if the bit is missing */
+        xd->corrupted |= vp8dx_bool_error(bc);
+        if (pbi->ec_active && xd->corrupted)
+            pc->refresh_alt_ref_frame = 0;
+#endif
+
+        /* Buffer to buffer copy flags. */
+        pc->copy_buffer_to_gf = 0;
+
+        if (!pc->refresh_golden_frame)
+            pc->copy_buffer_to_gf = vp8_read_literal(bc, 2);
+
+#if CONFIG_ERROR_CONCEALMENT
+        /* Assume we shouldn't copy to the golden if the bit is missing */
+        xd->corrupted |= vp8dx_bool_error(bc);
+        if (pbi->ec_active && xd->corrupted)
+            pc->copy_buffer_to_gf = 0;
+#endif
+
+        pc->copy_buffer_to_arf = 0;
+
+        if (!pc->refresh_alt_ref_frame)
+            pc->copy_buffer_to_arf = vp8_read_literal(bc, 2);
+
+#if CONFIG_ERROR_CONCEALMENT
+        /* Assume we shouldn't copy to the alt-ref if the bit is missing */
+        xd->corrupted |= vp8dx_bool_error(bc);
+        if (pbi->ec_active && xd->corrupted)
+            pc->copy_buffer_to_arf = 0;
+#endif
+
+
+        pc->ref_frame_sign_bias[GOLDEN_FRAME] = vp8_read_bit(bc);
+        pc->ref_frame_sign_bias[ALTREF_FRAME] = vp8_read_bit(bc);
+    }
+
+    pc->refresh_entropy_probs = vp8_read_bit(bc);
+#if CONFIG_ERROR_CONCEALMENT
+    /* Assume we shouldn't refresh the probabilities if the bit is
+     * missing */
+    xd->corrupted |= vp8dx_bool_error(bc);
+    if (pbi->ec_active && xd->corrupted)
+        pc->refresh_entropy_probs = 0;
+#endif
+    if (pc->refresh_entropy_probs == 0)
+    {
+        vpx_memcpy(&pc->lfc, &pc->fc, sizeof(pc->fc));
+    }
+
+    pc->refresh_last_frame = pc->frame_type == KEY_FRAME  ||  vp8_read_bit(bc);
+
+#if CONFIG_ERROR_CONCEALMENT
+    /* Assume we should refresh the last frame if the bit is missing */
+    xd->corrupted |= vp8dx_bool_error(bc);
+    if (pbi->ec_active && xd->corrupted)
+        pc->refresh_last_frame = 1;
+#endif
+
+    if (0)
+    {
+        FILE *z = fopen("decodestats.stt", "a");
+        fprintf(z, "%6d F:%d,G:%d,A:%d,L:%d,Q:%d\n",
+                pc->current_video_frame,
+                pc->frame_type,
+                pc->refresh_golden_frame,
+                pc->refresh_alt_ref_frame,
+                pc->refresh_last_frame,
+                pc->base_qindex);
+        fclose(z);
+    }
+
+    {
+        pbi->independent_partitions = 1;
+
+        /* read coef probability tree */
+        for (i = 0; i < BLOCK_TYPES; i++)
+            for (j = 0; j < COEF_BANDS; j++)
+                for (k = 0; k < PREV_COEF_CONTEXTS; k++)
+                    for (l = 0; l < ENTROPY_NODES; l++)
+                    {
+
+                        vp8_prob *const p = pc->fc.coef_probs [i][j][k] + l;
+
+                        if (vp8_read(bc, vp8_coef_update_probs [i][j][k][l]))
+                        {
+                            *p = (vp8_prob)vp8_read_literal(bc, 8);
+
+                        }
+                        if (k > 0 && *p != pc->fc.coef_probs[i][j][k-1][l])
+                            pbi->independent_partitions = 0;
+
+                    }
+    }
+
+    vpx_memcpy(&xd->pre, &pc->yv12_fb[pc->lst_fb_idx], sizeof(YV12_BUFFER_CONFIG));
+    vpx_memcpy(&xd->dst, &pc->yv12_fb[pc->new_fb_idx], sizeof(YV12_BUFFER_CONFIG));
+
+    /* set up frame new frame for intra coded blocks */
+#if CONFIG_MULTITHREAD
+    if (!(pbi->b_multithreaded_rd) || pc->multi_token_partition == ONE_PARTITION || !(pc->filter_level))
+#endif
+        vp8_setup_intra_recon(&pc->yv12_fb[pc->new_fb_idx]);
+
+    vp8_setup_block_dptrs(xd);
+
+    vp8_build_block_doffsets(xd);
+
+    /* clear out the coeff buffer */
+    vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
+
+    /* Read the mb_no_coeff_skip flag */
+    pc->mb_no_coeff_skip = (int)vp8_read_bit(bc);
+
+
+    vp8_decode_mode_mvs(pbi);
+
+#if CONFIG_ERROR_CONCEALMENT
+    if (pbi->ec_active &&
+            pbi->mvs_corrupt_from_mb < (unsigned int)pc->mb_cols * pc->mb_rows)
+    {
+        /* Motion vectors are missing in this frame. We will try to estimate
+         * them and then continue decoding the frame as usual */
+        vp8_estimate_missing_mvs(pbi);
+    }
+#endif
+
+    vpx_memset(pc->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES) * pc->mb_cols);
+    pbi->frame_corrupt_residual = 0;
+
+#if CONFIG_MULTITHREAD
+    if (pbi->b_multithreaded_rd && pc->multi_token_partition != ONE_PARTITION)
+    {
+        int i;
+        vp8mt_decode_mb_rows(pbi, xd);
+        vp8_yv12_extend_frame_borders(&pc->yv12_fb[pc->new_fb_idx]);    /*cm->frame_to_show);*/
+        for (i = 0; i < pbi->decoding_thread_count; ++i)
+            corrupt_tokens |= pbi->mb_row_di[i].mbd.corrupted;
+    }
+    else
+#endif
+    {
+        decode_mb_rows(pbi);
+        corrupt_tokens |= xd->corrupted;
+    }
+
+    stop_token_decoder(pbi);
+
+    /* Collect information about decoder corruption. */
+    /* 1. Check first boolean decoder for errors. */
+    pc->yv12_fb[pc->new_fb_idx].corrupted = vp8dx_bool_error(bc);
+    /* 2. Check the macroblock information */
+    pc->yv12_fb[pc->new_fb_idx].corrupted |= corrupt_tokens;
+
+    if (!pbi->decoded_key_frame)
+    {
+        if (pc->frame_type == KEY_FRAME &&
+            !pc->yv12_fb[pc->new_fb_idx].corrupted)
+            pbi->decoded_key_frame = 1;
+        else
+            vpx_internal_error(&pbi->common.error, VPX_CODEC_CORRUPT_FRAME,
+                               "A stream must start with a complete key frame");
+    }
+
+    /* vpx_log("Decoder: Frame Decoded, Size Roughly:%d bytes  \n",bc->pos+pbi->bc2.pos); */
+
+    /* If this was a kf or Gf note the Q used */
+    if ((pc->frame_type == KEY_FRAME) ||
+         pc->refresh_golden_frame || pc->refresh_alt_ref_frame)
+    {
+        pc->last_kf_gf_q = pc->base_qindex;
+    }
+
+    if (pc->refresh_entropy_probs == 0)
+    {
+        vpx_memcpy(&pc->fc, &pc->lfc, sizeof(pc->fc));
+        pbi->independent_partitions = prev_independent_partitions;
+    }
+
+#ifdef PACKET_TESTING
+    {
+        FILE *f = fopen("decompressor.VP8", "ab");
+        unsigned int size = pbi->bc2.pos + pbi->bc.pos + 8;
+        fwrite((void *) &size, 4, 1, f);
+        fwrite((void *) pbi->Source, size, 1, f);
+        fclose(f);
+    }
+#endif
+
+    return 0;
+}
diff --git a/vp8/decoder/detokenize.c b/vp8/decoder/detokenize.c
new file mode 100644 (file)
index 0000000..0c39848
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vp8/common/blockd.h"
+#include "onyxd_int.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_ports/mem.h"
+#include "detokenize.h"
+
+void vp8_reset_mb_tokens_context(MACROBLOCKD *x)
+{
+    ENTROPY_CONTEXT *a_ctx = ((ENTROPY_CONTEXT *)x->above_context);
+    ENTROPY_CONTEXT *l_ctx = ((ENTROPY_CONTEXT *)x->left_context);
+
+    vpx_memset(a_ctx, 0, sizeof(ENTROPY_CONTEXT_PLANES)-1);
+    vpx_memset(l_ctx, 0, sizeof(ENTROPY_CONTEXT_PLANES)-1);
+
+    /* Clear entropy contexts for Y2 blocks */
+    if (!x->mode_info_context->mbmi.is_4x4)
+    {
+        a_ctx[8] = l_ctx[8] = 0;
+    }
+}
+
+/*
+    ------------------------------------------------------------------------------
+    Residual decoding (Paragraph 13.2 / 13.3)
+*/
+static const uint8_t kBands[16 + 1] = {
+  0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7,
+  0  /* extra entry as sentinel */
+};
+
+static const uint8_t kCat3[] = { 173, 148, 140, 0 };
+static const uint8_t kCat4[] = { 176, 155, 140, 135, 0 };
+static const uint8_t kCat5[] = { 180, 157, 141, 134, 130, 0 };
+static const uint8_t kCat6[] =
+  { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0 };
+static const uint8_t* const kCat3456[] = { kCat3, kCat4, kCat5, kCat6 };
+static const uint8_t kZigzag[16] = {
+  0, 1, 4, 8,  5, 2, 3, 6,  9, 12, 13, 10,  7, 11, 14, 15
+};
+
+#define VP8GetBit vp8dx_decode_bool
+#define NUM_PROBAS  11
+#define NUM_CTX  3
+
+typedef const uint8_t (*ProbaArray)[NUM_CTX][NUM_PROBAS];  // for const-casting
+
+static int GetSigned(BOOL_DECODER *br, int value_to_sign)
+{
+    int split = (br->range + 1) >> 1;
+    VP8_BD_VALUE bigsplit = (VP8_BD_VALUE)split << (VP8_BD_VALUE_SIZE - 8);
+    int v;
+
+    if(br->count < 0)
+        vp8dx_bool_decoder_fill(br);
+
+    if ( br->value < bigsplit )
+    {
+        br->range = split;
+        v= value_to_sign;
+    }
+    else
+    {
+        br->range = br->range-split;
+        br->value = br->value-bigsplit;
+        v = -value_to_sign;
+    }
+    br->range +=br->range;
+    br->value +=br->value;
+    br->count--;
+
+    return v;
+}
+/*
+   Returns the position of the last non-zero coeff plus one
+   (and 0 if there's no coeff at all)
+*/
+static int GetCoeffs(BOOL_DECODER *br, ProbaArray prob,
+                     int ctx, int n, int16_t* out)
+{
+    const uint8_t* p = prob[n][ctx];
+    if (!VP8GetBit(br, p[0]))
+    {   /* first EOB is more a 'CBP' bit. */
+        return 0;
+    }
+    while (1)
+    {
+        ++n;
+        if (!VP8GetBit(br, p[1]))
+        {
+            p = prob[kBands[n]][0];
+        }
+        else
+        {  /* non zero coeff */
+            int v, j;
+            if (!VP8GetBit(br, p[2]))
+            {
+                p = prob[kBands[n]][1];
+                v = 1;
+            }
+            else
+            {
+                if (!VP8GetBit(br, p[3]))
+                {
+                    if (!VP8GetBit(br, p[4]))
+                    {
+                        v = 2;
+                    }
+                    else
+                    {
+                        v = 3 + VP8GetBit(br, p[5]);
+                    }
+                }
+                else
+                {
+                    if (!VP8GetBit(br, p[6]))
+                    {
+                        if (!VP8GetBit(br, p[7]))
+                        {
+                            v = 5 + VP8GetBit(br, 159);
+                        } else
+                        {
+                            v = 7 + 2 * VP8GetBit(br, 165);
+                            v += VP8GetBit(br, 145);
+                        }
+                    }
+                    else
+                    {
+                        const uint8_t* tab;
+                        const int bit1 = VP8GetBit(br, p[8]);
+                        const int bit0 = VP8GetBit(br, p[9 + bit1]);
+                        const int cat = 2 * bit1 + bit0;
+                        v = 0;
+                        for (tab = kCat3456[cat]; *tab; ++tab)
+                        {
+                            v += v + VP8GetBit(br, *tab);
+                        }
+                        v += 3 + (8 << cat);
+                    }
+                }
+                p = prob[kBands[n]][2];
+            }
+            j = kZigzag[n - 1];
+
+            out[j] = GetSigned(br, v);
+
+            if (n == 16 || !VP8GetBit(br, p[0]))
+            {   /* EOB */
+                return n;
+            }
+        }
+        if (n == 16)
+        {
+            return 16;
+        }
+    }
+}
+
+int vp8_decode_mb_tokens(VP8D_COMP *dx, MACROBLOCKD *x)
+{
+    BOOL_DECODER *bc = x->current_bc;
+    const FRAME_CONTEXT * const fc = &dx->common.fc;
+    char *eobs = x->eobs;
+
+    int i;
+    int nonzeros;
+    int eobtotal = 0;
+
+    short *qcoeff_ptr;
+    ProbaArray coef_probs;
+    ENTROPY_CONTEXT *a_ctx = ((ENTROPY_CONTEXT *)x->above_context);
+    ENTROPY_CONTEXT *l_ctx = ((ENTROPY_CONTEXT *)x->left_context);
+    ENTROPY_CONTEXT *a;
+    ENTROPY_CONTEXT *l;
+    int skip_dc = 0;
+
+    qcoeff_ptr = &x->qcoeff[0];
+
+    if (!x->mode_info_context->mbmi.is_4x4)
+    {
+        a = a_ctx + 8;
+        l = l_ctx + 8;
+
+        coef_probs = fc->coef_probs [1];
+
+        nonzeros = GetCoeffs(bc, coef_probs, (*a + *l), 0, qcoeff_ptr + 24 * 16);
+        *a = *l = (nonzeros > 0);
+
+        eobs[24] = nonzeros;
+        eobtotal += nonzeros - 16;
+
+        coef_probs = fc->coef_probs [0];
+        skip_dc = 1;
+    }
+    else
+    {
+        coef_probs = fc->coef_probs [3];
+        skip_dc = 0;
+    }
+
+    for (i = 0; i < 16; ++i)
+    {
+        a = a_ctx + (i&3);
+        l = l_ctx + ((i&0xc)>>2);
+
+        nonzeros = GetCoeffs(bc, coef_probs, (*a + *l), skip_dc, qcoeff_ptr);
+        *a = *l = (nonzeros > 0);
+
+        nonzeros += skip_dc;
+        eobs[i] = nonzeros;
+        eobtotal += nonzeros;
+        qcoeff_ptr += 16;
+    }
+
+    coef_probs = fc->coef_probs [2];
+
+    a_ctx += 4;
+    l_ctx += 4;
+    for (i = 16; i < 24; ++i)
+    {
+        a = a_ctx + ((i > 19)<<1) + (i&1);
+        l = l_ctx + ((i > 19)<<1) + ((i&3)>1);
+
+        nonzeros = GetCoeffs(bc, coef_probs, (*a + *l), 0, qcoeff_ptr);
+        *a = *l = (nonzeros > 0);
+
+        eobs[i] = nonzeros;
+        eobtotal += nonzeros;
+        qcoeff_ptr += 16;
+    }
+
+    return eobtotal;
+}
+
diff --git a/vp8/decoder/detokenize.h b/vp8/decoder/detokenize.h
new file mode 100644 (file)
index 0000000..8640bda
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef DETOKENIZE_H
+#define DETOKENIZE_H
+
+#include "onyxd_int.h"
+
+void vp8_reset_mb_tokens_context(MACROBLOCKD *x);
+int vp8_decode_mb_tokens(VP8D_COMP *, MACROBLOCKD *);
+
+#endif /* DETOKENIZE_H */
diff --git a/vp8/decoder/ec_types.h b/vp8/decoder/ec_types.h
new file mode 100644 (file)
index 0000000..ccb5ddb
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef VP8_DEC_EC_TYPES_H
+#define VP8_DEC_EC_TYPES_H
+
+#define MAX_OVERLAPS 16
+
+
+
+/* The area (pixel area in Q6) the block pointed to by bmi overlaps
+ * another block with.
+ */
+typedef struct
+{
+    int overlap;
+    union b_mode_info *bmi;
+} OVERLAP_NODE;
+
+/* Structure to keep track of overlapping blocks on a block level. */
+typedef struct
+{
+    /* TODO(holmer): This array should be exchanged for a linked list */
+    OVERLAP_NODE overlaps[MAX_OVERLAPS];
+} B_OVERLAP;
+
+/* Structure used to hold all the overlaps of a macroblock. The overlaps of a
+ * macroblock is further divided into block overlaps.
+ */
+typedef struct
+{
+    B_OVERLAP overlaps[16];
+} MB_OVERLAP;
+
+/* Structure for keeping track of motion vectors and which reference frame they
+ * refer to. Used for motion vector interpolation.
+ */
+typedef struct
+{
+    MV mv;
+    MV_REFERENCE_FRAME ref_frame;
+} EC_BLOCK;
+
+#endif /* VP8_DEC_EC_TYPES_H */
diff --git a/vp8/decoder/error_concealment.c b/vp8/decoder/error_concealment.c
new file mode 100644 (file)
index 0000000..7750728
--- /dev/null
@@ -0,0 +1,597 @@
+/*
+ *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "error_concealment.h"
+#include "onyxd_int.h"
+#include "decodemv.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vp8/common/findnearmv.h"
+
+#include <assert.h>
+
+#define MIN(x,y) (((x)<(y))?(x):(y))
+#define MAX(x,y) (((x)>(y))?(x):(y))
+
+#define FLOOR(x,q) ((x) & -(1 << (q)))
+
+#define NUM_NEIGHBORS 20
+
+typedef struct ec_position
+{
+    int row;
+    int col;
+} EC_POS;
+
+/*
+ * Regenerate the table in Matlab with:
+ * x = meshgrid((1:4), (1:4));
+ * y = meshgrid((1:4), (1:4))';
+ * W = round((1./(sqrt(x.^2 + y.^2))*2^7));
+ * W(1,1) = 0;
+ */
+static const int weights_q7[5][5] = {
+       {  0,   128,    64,    43,    32 },
+       {128,    91,    57,    40,    31 },
+       { 64,    57,    45,    36,    29 },
+       { 43,    40,    36,    30,    26 },
+       { 32,    31,    29,    26,    23 }
+};
+
+int vp8_alloc_overlap_lists(VP8D_COMP *pbi)
+{
+    if (pbi->overlaps != NULL)
+    {
+        vpx_free(pbi->overlaps);
+        pbi->overlaps = NULL;
+    }
+    pbi->overlaps = vpx_calloc(pbi->common.mb_rows * pbi->common.mb_cols,
+                               sizeof(MB_OVERLAP));
+    if (pbi->overlaps == NULL)
+        return -1;
+    vpx_memset(pbi->overlaps, 0,
+               sizeof(MB_OVERLAP) * pbi->common.mb_rows * pbi->common.mb_cols);
+    return 0;
+}
+
+void vp8_de_alloc_overlap_lists(VP8D_COMP *pbi)
+{
+    vpx_free(pbi->overlaps);
+    pbi->overlaps = NULL;
+}
+
+/* Inserts a new overlap area value to the list of overlaps of a block */
+static void assign_overlap(OVERLAP_NODE* overlaps,
+                           union b_mode_info *bmi,
+                           int overlap)
+{
+    int i;
+    if (overlap <= 0)
+        return;
+    /* Find and assign to the next empty overlap node in the list of overlaps.
+     * Empty is defined as bmi == NULL */
+    for (i = 0; i < MAX_OVERLAPS; i++)
+    {
+        if (overlaps[i].bmi == NULL)
+        {
+            overlaps[i].bmi = bmi;
+            overlaps[i].overlap = overlap;
+            break;
+        }
+    }
+}
+
+/* Calculates the overlap area between two 4x4 squares, where the first
+ * square has its upper-left corner at (b1_row, b1_col) and the second
+ * square has its upper-left corner at (b2_row, b2_col). Doesn't
+ * properly handle squares which do not overlap.
+ */
+static int block_overlap(int b1_row, int b1_col, int b2_row, int b2_col)
+{
+    const int int_top = MAX(b1_row, b2_row); // top
+    const int int_left = MAX(b1_col, b2_col); // left
+    /* Since each block is 4x4 pixels, adding 4 (Q3) to the left/top edge
+     * gives us the right/bottom edge.
+     */
+    const int int_right = MIN(b1_col + (4<<3), b2_col + (4<<3)); // right
+    const int int_bottom = MIN(b1_row + (4<<3), b2_row + (4<<3)); // bottom
+    return (int_bottom - int_top) * (int_right - int_left);
+}
+
+/* Calculates the overlap area for all blocks in a macroblock at position
+ * (mb_row, mb_col) in macroblocks, which are being overlapped by a given
+ * overlapping block at position (new_row, new_col) (in pixels, Q3). The
+ * first block being overlapped in the macroblock has position (first_blk_row,
+ * first_blk_col) in blocks relative the upper-left corner of the image.
+ */
+static void calculate_overlaps_mb(B_OVERLAP *b_overlaps, union b_mode_info *bmi,
+                                  int new_row, int new_col,
+                                  int mb_row, int mb_col,
+                                  int first_blk_row, int first_blk_col)
+{
+    /* Find the blocks within this MB (defined by mb_row, mb_col) which are
+     * overlapped by bmi and calculate and assign overlap for each of those
+     * blocks. */
+
+    /* Block coordinates relative the upper-left block */
+    const int rel_ol_blk_row = first_blk_row - mb_row * 4;
+    const int rel_ol_blk_col = first_blk_col - mb_col * 4;
+    /* If the block partly overlaps any previous MB, these coordinates
+     * can be < 0. We don't want to access blocks in previous MBs.
+     */
+    const int blk_idx = MAX(rel_ol_blk_row,0) * 4 + MAX(rel_ol_blk_col,0);
+    /* Upper left overlapping block */
+    B_OVERLAP *b_ol_ul = &(b_overlaps[blk_idx]);
+
+    /* Calculate and assign overlaps for all blocks in this MB
+     * which the motion compensated block overlaps
+     */
+    /* Avoid calculating overlaps for blocks in later MBs */
+    int end_row = MIN(4 + mb_row * 4 - first_blk_row, 2);
+    int end_col = MIN(4 + mb_col * 4 - first_blk_col, 2);
+    int row, col;
+
+    /* Check if new_row and new_col are evenly divisible by 4 (Q3),
+     * and if so we shouldn't check neighboring blocks
+     */
+    if (new_row >= 0 && (new_row & 0x1F) == 0)
+        end_row = 1;
+    if (new_col >= 0 && (new_col & 0x1F) == 0)
+        end_col = 1;
+
+    /* Check if the overlapping block partly overlaps a previous MB
+     * and if so, we're overlapping fewer blocks in this MB.
+     */
+    if (new_row < (mb_row*16)<<3)
+        end_row = 1;
+    if (new_col < (mb_col*16)<<3)
+        end_col = 1;
+
+    for (row = 0; row < end_row; ++row)
+    {
+        for (col = 0; col < end_col; ++col)
+        {
+            /* input in Q3, result in Q6 */
+            const int overlap = block_overlap(new_row, new_col,
+                                                  (((first_blk_row + row) *
+                                                      4) << 3),
+                                                  (((first_blk_col + col) *
+                                                      4) << 3));
+            assign_overlap(b_ol_ul[row * 4 + col].overlaps, bmi, overlap);
+        }
+    }
+}
+
+void vp8_calculate_overlaps(MB_OVERLAP *overlap_ul,
+                            int mb_rows, int mb_cols,
+                            union b_mode_info *bmi,
+                            int b_row, int b_col)
+{
+    MB_OVERLAP *mb_overlap;
+    int row, col, rel_row, rel_col;
+    int new_row, new_col;
+    int end_row, end_col;
+    int overlap_b_row, overlap_b_col;
+    int overlap_mb_row, overlap_mb_col;
+
+    /* mb subpixel position */
+    row = (4 * b_row) << 3; /* Q3 */
+    col = (4 * b_col) << 3; /* Q3 */
+
+    /* reverse compensate for motion */
+    new_row = row - bmi->mv.as_mv.row;
+    new_col = col - bmi->mv.as_mv.col;
+
+    if (new_row >= ((16*mb_rows) << 3) || new_col >= ((16*mb_cols) << 3))
+    {
+        /* the new block ended up outside the frame */
+        return;
+    }
+
+    if (new_row <= (-4 << 3) || new_col <= (-4 << 3))
+    {
+        /* outside the frame */
+        return;
+    }
+    /* overlapping block's position in blocks */
+    overlap_b_row = FLOOR(new_row / 4, 3) >> 3;
+    overlap_b_col = FLOOR(new_col / 4, 3) >> 3;
+
+    /* overlapping block's MB position in MBs
+     * operations are done in Q3
+     */
+    overlap_mb_row = FLOOR((overlap_b_row << 3) / 4, 3) >> 3;
+    overlap_mb_col = FLOOR((overlap_b_col << 3) / 4, 3) >> 3;
+
+    end_row = MIN(mb_rows - overlap_mb_row, 2);
+    end_col = MIN(mb_cols - overlap_mb_col, 2);
+
+    /* Don't calculate overlap for MBs we don't overlap */
+    /* Check if the new block row starts at the last block row of the MB */
+    if (abs(new_row - ((16*overlap_mb_row) << 3)) < ((3*4) << 3))
+        end_row = 1;
+    /* Check if the new block col starts at the last block col of the MB */
+    if (abs(new_col - ((16*overlap_mb_col) << 3)) < ((3*4) << 3))
+        end_col = 1;
+
+    /* find the MB(s) this block is overlapping */
+    for (rel_row = 0; rel_row < end_row; ++rel_row)
+    {
+        for (rel_col = 0; rel_col < end_col; ++rel_col)
+        {
+            if (overlap_mb_row + rel_row < 0 ||
+                overlap_mb_col + rel_col < 0)
+                continue;
+            mb_overlap = overlap_ul + (overlap_mb_row + rel_row) * mb_cols +
+                 overlap_mb_col + rel_col;
+
+            calculate_overlaps_mb(mb_overlap->overlaps, bmi,
+                                  new_row, new_col,
+                                  overlap_mb_row + rel_row,
+                                  overlap_mb_col + rel_col,
+                                  overlap_b_row + rel_row,
+                                  overlap_b_col + rel_col);
+        }
+    }
+}
+
+/* Estimates a motion vector given the overlapping blocks' motion vectors.
+ * Filters out all overlapping blocks which do not refer to the correct
+ * reference frame type.
+ */
+static void estimate_mv(const OVERLAP_NODE *overlaps, union b_mode_info *bmi)
+{
+    int i;
+    int overlap_sum = 0;
+    int row_acc = 0;
+    int col_acc = 0;
+
+    bmi->mv.as_int = 0;
+    for (i=0; i < MAX_OVERLAPS; ++i)
+    {
+        if (overlaps[i].bmi == NULL)
+            break;
+        col_acc += overlaps[i].overlap * overlaps[i].bmi->mv.as_mv.col;
+        row_acc += overlaps[i].overlap * overlaps[i].bmi->mv.as_mv.row;
+        overlap_sum += overlaps[i].overlap;
+    }
+    if (overlap_sum > 0)
+    {
+        /* Q9 / Q6 = Q3 */
+        bmi->mv.as_mv.col = col_acc / overlap_sum;
+        bmi->mv.as_mv.row = row_acc / overlap_sum;
+    }
+    else
+    {
+        bmi->mv.as_mv.col = 0;
+        bmi->mv.as_mv.row = 0;
+    }
+}
+
+/* Estimates all motion vectors for a macroblock given the lists of
+ * overlaps for each block. Decides whether or not the MVs must be clamped.
+ */
+static void estimate_mb_mvs(const B_OVERLAP *block_overlaps,
+                            MODE_INFO *mi,
+                            int mb_to_left_edge,
+                            int mb_to_right_edge,
+                            int mb_to_top_edge,
+                            int mb_to_bottom_edge)
+{
+    int row, col;
+    int non_zero_count = 0;
+    MV * const filtered_mv = &(mi->mbmi.mv.as_mv);
+    union b_mode_info * const bmi = mi->bmi;
+    filtered_mv->col = 0;
+    filtered_mv->row = 0;
+    mi->mbmi.need_to_clamp_mvs = 0;
+    for (row = 0; row < 4; ++row)
+    {
+        int this_b_to_top_edge = mb_to_top_edge + ((row*4)<<3);
+        int this_b_to_bottom_edge = mb_to_bottom_edge - ((row*4)<<3);
+        for (col = 0; col < 4; ++col)
+        {
+            int i = row * 4 + col;
+            int this_b_to_left_edge = mb_to_left_edge + ((col*4)<<3);
+            int this_b_to_right_edge = mb_to_right_edge - ((col*4)<<3);
+            /* Estimate vectors for all blocks which are overlapped by this */
+            /* type. Interpolate/extrapolate the rest of the block's MVs */
+            estimate_mv(block_overlaps[i].overlaps, &(bmi[i]));
+            mi->mbmi.need_to_clamp_mvs |= vp8_check_mv_bounds(
+                                                         &bmi[i].mv,
+                                                         this_b_to_left_edge,
+                                                         this_b_to_right_edge,
+                                                         this_b_to_top_edge,
+                                                         this_b_to_bottom_edge);
+            if (bmi[i].mv.as_int != 0)
+            {
+                ++non_zero_count;
+                filtered_mv->col += bmi[i].mv.as_mv.col;
+                filtered_mv->row += bmi[i].mv.as_mv.row;
+            }
+        }
+    }
+    if (non_zero_count > 0)
+    {
+        filtered_mv->col /= non_zero_count;
+        filtered_mv->row /= non_zero_count;
+    }
+}
+
+static void calc_prev_mb_overlaps(MB_OVERLAP *overlaps, MODE_INFO *prev_mi,
+                                    int mb_row, int mb_col,
+                                    int mb_rows, int mb_cols)
+{
+    int sub_row;
+    int sub_col;
+    for (sub_row = 0; sub_row < 4; ++sub_row)
+    {
+        for (sub_col = 0; sub_col < 4; ++sub_col)
+        {
+            vp8_calculate_overlaps(
+                                overlaps, mb_rows, mb_cols,
+                                &(prev_mi->bmi[sub_row * 4 + sub_col]),
+                                4 * mb_row + sub_row,
+                                4 * mb_col + sub_col);
+        }
+    }
+}
+
+/* Estimate all missing motion vectors. This function does the same as the one
+ * above, but has different input arguments. */
+static void estimate_missing_mvs(MB_OVERLAP *overlaps,
+                                 MODE_INFO *mi, MODE_INFO *prev_mi,
+                                 int mb_rows, int mb_cols,
+                                 unsigned int first_corrupt)
+{
+    int mb_row, mb_col;
+    vpx_memset(overlaps, 0, sizeof(MB_OVERLAP) * mb_rows * mb_cols);
+    /* First calculate the overlaps for all blocks */
+    for (mb_row = 0; mb_row < mb_rows; ++mb_row)
+    {
+        for (mb_col = 0; mb_col < mb_cols; ++mb_col)
+        {
+            /* We're only able to use blocks referring to the last frame
+             * when extrapolating new vectors.
+             */
+            if (prev_mi->mbmi.ref_frame == LAST_FRAME)
+            {
+                calc_prev_mb_overlaps(overlaps, prev_mi,
+                                      mb_row, mb_col,
+                                      mb_rows, mb_cols);
+            }
+            ++prev_mi;
+        }
+        ++prev_mi;
+    }
+
+    mb_row = first_corrupt / mb_cols;
+    mb_col = first_corrupt - mb_row * mb_cols;
+    mi += mb_row*(mb_cols + 1) + mb_col;
+    /* Go through all macroblocks in the current image with missing MVs
+     * and calculate new MVs using the overlaps.
+     */
+    for (; mb_row < mb_rows; ++mb_row)
+    {
+        int mb_to_top_edge = -((mb_row * 16)) << 3;
+        int mb_to_bottom_edge = ((mb_rows - 1 - mb_row) * 16) << 3;
+        for (; mb_col < mb_cols; ++mb_col)
+        {
+            int mb_to_left_edge = -((mb_col * 16) << 3);
+            int mb_to_right_edge = ((mb_cols - 1 - mb_col) * 16) << 3;
+            const B_OVERLAP *block_overlaps =
+                    overlaps[mb_row*mb_cols + mb_col].overlaps;
+            mi->mbmi.ref_frame = LAST_FRAME;
+            mi->mbmi.mode = SPLITMV;
+            mi->mbmi.uv_mode = DC_PRED;
+            mi->mbmi.partitioning = 3;
+            mi->mbmi.segment_id = 0;
+            estimate_mb_mvs(block_overlaps,
+                            mi,
+                            mb_to_left_edge,
+                            mb_to_right_edge,
+                            mb_to_top_edge,
+                            mb_to_bottom_edge);
+            ++mi;
+        }
+        mb_col = 0;
+        ++mi;
+    }
+}
+
+void vp8_estimate_missing_mvs(VP8D_COMP *pbi)
+{
+    VP8_COMMON * const pc = &pbi->common;
+    estimate_missing_mvs(pbi->overlaps,
+                         pc->mi, pc->prev_mi,
+                         pc->mb_rows, pc->mb_cols,
+                         pbi->mvs_corrupt_from_mb);
+}
+
+static void assign_neighbor(EC_BLOCK *neighbor, MODE_INFO *mi, int block_idx)
+{
+    assert(mi->mbmi.ref_frame < MAX_REF_FRAMES);
+    neighbor->ref_frame = mi->mbmi.ref_frame;
+    neighbor->mv = mi->bmi[block_idx].mv.as_mv;
+}
+
+/* Finds the neighboring blocks of a macroblocks. In the general case
+ * 20 blocks are found. If a fewer number of blocks are found due to
+ * image boundaries, those positions in the EC_BLOCK array are left "empty".
+ * The neighbors are enumerated with the upper-left neighbor as the first
+ * element, the second element refers to the neighbor to right of the previous
+ * neighbor, and so on. The last element refers to the neighbor below the first
+ * neighbor.
+ */
+static void find_neighboring_blocks(MODE_INFO *mi,
+                                    EC_BLOCK *neighbors,
+                                    int mb_row, int mb_col,
+                                    int mb_rows, int mb_cols,
+                                    int mi_stride)
+{
+    int i = 0;
+    int j;
+    if (mb_row > 0)
+    {
+        /* upper left */
+        if (mb_col > 0)
+            assign_neighbor(&neighbors[i], mi - mi_stride - 1, 15);
+        ++i;
+        /* above */
+        for (j = 12; j < 16; ++j, ++i)
+            assign_neighbor(&neighbors[i], mi - mi_stride, j);
+    }
+    else
+        i += 5;
+    if (mb_col < mb_cols - 1)
+    {
+        /* upper right */
+        if (mb_row > 0)
+            assign_neighbor(&neighbors[i], mi - mi_stride + 1, 12);
+        ++i;
+        /* right */
+        for (j = 0; j <= 12; j += 4, ++i)
+            assign_neighbor(&neighbors[i], mi + 1, j);
+    }
+    else
+        i += 5;
+    if (mb_row < mb_rows - 1)
+    {
+        /* lower right */
+        if (mb_col < mb_cols - 1)
+            assign_neighbor(&neighbors[i], mi + mi_stride + 1, 0);
+        ++i;
+        /* below */
+        for (j = 0; j < 4; ++j, ++i)
+            assign_neighbor(&neighbors[i], mi + mi_stride, j);
+    }
+    else
+        i += 5;
+    if (mb_col > 0)
+    {
+        /* lower left */
+        if (mb_row < mb_rows - 1)
+            assign_neighbor(&neighbors[i], mi + mi_stride - 1, 4);
+        ++i;
+        /* left */
+        for (j = 3; j < 16; j += 4, ++i)
+        {
+            assign_neighbor(&neighbors[i], mi - 1, j);
+        }
+    }
+    else
+        i += 5;
+    assert(i == 20);
+}
+
+/* Interpolates all motion vectors for a macroblock from the neighboring blocks'
+ * motion vectors.
+ */
+static void interpolate_mvs(MACROBLOCKD *mb,
+                         EC_BLOCK *neighbors,
+                         MV_REFERENCE_FRAME dom_ref_frame)
+{
+    int row, col, i;
+    MODE_INFO * const mi = mb->mode_info_context;
+    /* Table with the position of the neighboring blocks relative the position
+     * of the upper left block of the current MB. Starting with the upper left
+     * neighbor and going to the right.
+     */
+    const EC_POS neigh_pos[NUM_NEIGHBORS] = {
+                                        {-1,-1}, {-1,0}, {-1,1}, {-1,2}, {-1,3},
+                                        {-1,4}, {0,4}, {1,4}, {2,4}, {3,4},
+                                        {4,4}, {4,3}, {4,2}, {4,1}, {4,0},
+                                        {4,-1}, {3,-1}, {2,-1}, {1,-1}, {0,-1}
+                                      };
+    mi->mbmi.need_to_clamp_mvs = 0;
+    for (row = 0; row < 4; ++row)
+    {
+        int mb_to_top_edge = mb->mb_to_top_edge + ((row*4)<<3);
+        int mb_to_bottom_edge = mb->mb_to_bottom_edge - ((row*4)<<3);
+        for (col = 0; col < 4; ++col)
+        {
+            int mb_to_left_edge = mb->mb_to_left_edge + ((col*4)<<3);
+            int mb_to_right_edge = mb->mb_to_right_edge - ((col*4)<<3);
+            int w_sum = 0;
+            int mv_row_sum = 0;
+            int mv_col_sum = 0;
+            int_mv * const mv = &(mi->bmi[row*4 + col].mv);
+            mv->as_int = 0;
+            for (i = 0; i < NUM_NEIGHBORS; ++i)
+            {
+                /* Calculate the weighted sum of neighboring MVs referring
+                 * to the dominant frame type.
+                 */
+                const int w = weights_q7[abs(row - neigh_pos[i].row)]
+                                        [abs(col - neigh_pos[i].col)];
+                if (neighbors[i].ref_frame != dom_ref_frame)
+                    continue;
+                w_sum += w;
+                /* Q7 * Q3 = Q10 */
+                mv_row_sum += w*neighbors[i].mv.row;
+                mv_col_sum += w*neighbors[i].mv.col;
+            }
+            if (w_sum > 0)
+            {
+                /* Avoid division by zero.
+                 * Normalize with the sum of the coefficients
+                 * Q3 = Q10 / Q7
+                 */
+                mv->as_mv.row = mv_row_sum / w_sum;
+                mv->as_mv.col = mv_col_sum / w_sum;
+                mi->mbmi.need_to_clamp_mvs |= vp8_check_mv_bounds(
+                                                            mv,
+                                                            mb_to_left_edge,
+                                                            mb_to_right_edge,
+                                                            mb_to_top_edge,
+                                                            mb_to_bottom_edge);
+            }
+        }
+    }
+}
+
+void vp8_interpolate_motion(MACROBLOCKD *mb,
+                        int mb_row, int mb_col,
+                        int mb_rows, int mb_cols,
+                        int mi_stride)
+{
+    /* Find relevant neighboring blocks */
+    EC_BLOCK neighbors[NUM_NEIGHBORS];
+    int i;
+    /* Initialize the array. MAX_REF_FRAMES is interpreted as "doesn't exist" */
+    for (i = 0; i < NUM_NEIGHBORS; ++i)
+    {
+        neighbors[i].ref_frame = MAX_REF_FRAMES;
+        neighbors[i].mv.row = neighbors[i].mv.col = 0;
+    }
+    find_neighboring_blocks(mb->mode_info_context,
+                                neighbors,
+                                mb_row, mb_col,
+                                mb_rows, mb_cols,
+                                mb->mode_info_stride);
+    /* Interpolate MVs for the missing blocks from the surrounding
+     * blocks which refer to the last frame. */
+    interpolate_mvs(mb, neighbors, LAST_FRAME);
+
+    mb->mode_info_context->mbmi.ref_frame = LAST_FRAME;
+    mb->mode_info_context->mbmi.mode = SPLITMV;
+    mb->mode_info_context->mbmi.uv_mode = DC_PRED;
+    mb->mode_info_context->mbmi.partitioning = 3;
+    mb->mode_info_context->mbmi.segment_id = 0;
+}
+
+void vp8_conceal_corrupt_mb(MACROBLOCKD *xd)
+{
+    /* This macroblock has corrupt residual, use the motion compensated
+       image (predictor) for concealment */
+
+    /* The build predictor functions now output directly into the dst buffer,
+     * so the copies are no longer necessary */
+
+}
diff --git a/vp8/decoder/error_concealment.h b/vp8/decoder/error_concealment.h
new file mode 100644 (file)
index 0000000..65ae9d9
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef ERROR_CONCEALMENT_H
+#define ERROR_CONCEALMENT_H
+
+#include "onyxd_int.h"
+#include "ec_types.h"
+
+/* Allocate memory for the overlap lists */
+int vp8_alloc_overlap_lists(VP8D_COMP *pbi);
+
+/* Deallocate the overlap lists */
+void vp8_de_alloc_overlap_lists(VP8D_COMP *pbi);
+
+/* Estimate all missing motion vectors. */
+void vp8_estimate_missing_mvs(VP8D_COMP *pbi);
+
+/* Functions for spatial MV interpolation */
+
+/* Interpolates all motion vectors for a macroblock mb at position
+ * (mb_row, mb_col). */
+void vp8_interpolate_motion(MACROBLOCKD *mb,
+                            int mb_row, int mb_col,
+                            int mb_rows, int mb_cols,
+                            int mi_stride);
+
+/* Conceal a macroblock with corrupt residual.
+ * Copies the prediction signal to the reconstructed image.
+ */
+void vp8_conceal_corrupt_mb(MACROBLOCKD *xd);
+
+#endif
diff --git a/vp8/decoder/onyxd_if.c b/vp8/decoder/onyxd_if.c
new file mode 100644 (file)
index 0000000..c59ce25
--- /dev/null
@@ -0,0 +1,614 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vp8/common/onyxc_int.h"
+#if CONFIG_POSTPROC
+#include "vp8/common/postproc.h"
+#endif
+#include "vp8/common/onyxd.h"
+#include "onyxd_int.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vp8/common/alloccommon.h"
+#include "vp8/common/loopfilter.h"
+#include "vp8/common/swapyv12buffer.h"
+#include "vp8/common/threading.h"
+#include "decoderthreading.h"
+#include <stdio.h>
+#include <assert.h>
+
+#include "vp8/common/quant_common.h"
+#include "vpx_scale/vpxscale.h"
+#include "vp8/common/systemdependent.h"
+#include "vpx_ports/vpx_timer.h"
+#include "detokenize.h"
+#if CONFIG_ERROR_CONCEALMENT
+#include "error_concealment.h"
+#endif
+#if ARCH_ARM
+#include "vpx_ports/arm.h"
+#endif
+
+extern void vp8_init_loop_filter(VP8_COMMON *cm);
+extern void vp8cx_init_de_quantizer(VP8D_COMP *pbi);
+static int get_free_fb (VP8_COMMON *cm);
+static void ref_cnt_fb (int *buf, int *idx, int new_idx);
+
+struct VP8D_COMP * vp8dx_create_decompressor(VP8D_CONFIG *oxcf)
+{
+    VP8D_COMP *pbi = vpx_memalign(32, sizeof(VP8D_COMP));
+
+    if (!pbi)
+        return NULL;
+
+    vpx_memset(pbi, 0, sizeof(VP8D_COMP));
+
+    if (setjmp(pbi->common.error.jmp))
+    {
+        pbi->common.error.setjmp = 0;
+        vp8dx_remove_decompressor(pbi);
+        return 0;
+    }
+
+    pbi->common.error.setjmp = 1;
+
+    vp8_create_common(&pbi->common);
+
+    pbi->common.current_video_frame = 0;
+    pbi->ready_for_new_data = 1;
+
+#if CONFIG_MULTITHREAD
+    pbi->max_threads = oxcf->max_threads;
+    vp8_decoder_create_threads(pbi);
+#endif
+
+    /* vp8cx_init_de_quantizer() is first called here. Add check in frame_init_dequantizer() to avoid
+     *  unnecessary calling of vp8cx_init_de_quantizer() for every frame.
+     */
+    vp8cx_init_de_quantizer(pbi);
+
+    vp8_loop_filter_init(&pbi->common);
+
+    pbi->common.error.setjmp = 0;
+
+#if CONFIG_ERROR_CONCEALMENT
+    pbi->ec_enabled = oxcf->error_concealment;
+#else
+    pbi->ec_enabled = 0;
+#endif
+    /* Error concealment is activated after a key frame has been
+     * decoded without errors when error concealment is enabled.
+     */
+    pbi->ec_active = 0;
+
+    pbi->decoded_key_frame = 0;
+
+    pbi->input_fragments = oxcf->input_fragments;
+    pbi->num_fragments = 0;
+
+    /* Independent partitions is activated when a frame updates the
+     * token probability table to have equal probabilities over the
+     * PREV_COEF context.
+     */
+    pbi->independent_partitions = 0;
+
+    return pbi;
+}
+
+
+void vp8dx_remove_decompressor(VP8D_COMP *pbi)
+{
+    if (!pbi)
+        return;
+
+#if CONFIG_MULTITHREAD
+    if (pbi->b_multithreaded_rd)
+        vp8mt_de_alloc_temp_buffers(pbi, pbi->common.mb_rows);
+    vp8_decoder_remove_threads(pbi);
+#endif
+#if CONFIG_ERROR_CONCEALMENT
+    vp8_de_alloc_overlap_lists(pbi);
+#endif
+    vp8_remove_common(&pbi->common);
+    vpx_free(pbi->mbc);
+    vpx_free(pbi);
+}
+
+
+vpx_codec_err_t vp8dx_get_reference(VP8D_COMP *pbi, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
+{
+    VP8_COMMON *cm = &pbi->common;
+    int ref_fb_idx;
+
+    if (ref_frame_flag == VP8_LAST_FLAG)
+        ref_fb_idx = cm->lst_fb_idx;
+    else if (ref_frame_flag == VP8_GOLD_FLAG)
+        ref_fb_idx = cm->gld_fb_idx;
+    else if (ref_frame_flag == VP8_ALT_FLAG)
+        ref_fb_idx = cm->alt_fb_idx;
+    else{
+        vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
+            "Invalid reference frame");
+        return pbi->common.error.error_code;
+    }
+
+    if(cm->yv12_fb[ref_fb_idx].y_height != sd->y_height ||
+        cm->yv12_fb[ref_fb_idx].y_width != sd->y_width ||
+        cm->yv12_fb[ref_fb_idx].uv_height != sd->uv_height ||
+        cm->yv12_fb[ref_fb_idx].uv_width != sd->uv_width){
+        vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
+            "Incorrect buffer dimensions");
+    }
+    else
+        vp8_yv12_copy_frame(&cm->yv12_fb[ref_fb_idx], sd);
+
+    return pbi->common.error.error_code;
+}
+
+
+vpx_codec_err_t vp8dx_set_reference(VP8D_COMP *pbi, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
+{
+    VP8_COMMON *cm = &pbi->common;
+    int *ref_fb_ptr = NULL;
+    int free_fb;
+
+    if (ref_frame_flag == VP8_LAST_FLAG)
+        ref_fb_ptr = &cm->lst_fb_idx;
+    else if (ref_frame_flag == VP8_GOLD_FLAG)
+        ref_fb_ptr = &cm->gld_fb_idx;
+    else if (ref_frame_flag == VP8_ALT_FLAG)
+        ref_fb_ptr = &cm->alt_fb_idx;
+    else{
+        vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
+            "Invalid reference frame");
+        return pbi->common.error.error_code;
+    }
+
+    if(cm->yv12_fb[*ref_fb_ptr].y_height != sd->y_height ||
+        cm->yv12_fb[*ref_fb_ptr].y_width != sd->y_width ||
+        cm->yv12_fb[*ref_fb_ptr].uv_height != sd->uv_height ||
+        cm->yv12_fb[*ref_fb_ptr].uv_width != sd->uv_width){
+        vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
+            "Incorrect buffer dimensions");
+    }
+    else{
+        /* Find an empty frame buffer. */
+        free_fb = get_free_fb(cm);
+        /* Decrease fb_idx_ref_cnt since it will be increased again in
+         * ref_cnt_fb() below. */
+        cm->fb_idx_ref_cnt[free_fb]--;
+
+        /* Manage the reference counters and copy image. */
+        ref_cnt_fb (cm->fb_idx_ref_cnt, ref_fb_ptr, free_fb);
+        vp8_yv12_copy_frame(sd, &cm->yv12_fb[*ref_fb_ptr]);
+    }
+
+   return pbi->common.error.error_code;
+}
+
+/*For ARM NEON, d8-d15 are callee-saved registers, and need to be saved by us.*/
+#if HAVE_NEON
+extern void vp8_push_neon(int64_t *store);
+extern void vp8_pop_neon(int64_t *store);
+#endif
+
+static int get_free_fb (VP8_COMMON *cm)
+{
+    int i;
+    for (i = 0; i < NUM_YV12_BUFFERS; i++)
+        if (cm->fb_idx_ref_cnt[i] == 0)
+            break;
+
+    assert(i < NUM_YV12_BUFFERS);
+    cm->fb_idx_ref_cnt[i] = 1;
+    return i;
+}
+
+static void ref_cnt_fb (int *buf, int *idx, int new_idx)
+{
+    if (buf[*idx] > 0)
+        buf[*idx]--;
+
+    *idx = new_idx;
+
+    buf[new_idx]++;
+}
+
+/* If any buffer copy / swapping is signalled it should be done here. */
+static int swap_frame_buffers (VP8_COMMON *cm)
+{
+    int err = 0;
+
+    /* The alternate reference frame or golden frame can be updated
+     *  using the new, last, or golden/alt ref frame.  If it
+     *  is updated using the newly decoded frame it is a refresh.
+     *  An update using the last or golden/alt ref frame is a copy.
+     */
+    if (cm->copy_buffer_to_arf)
+    {
+        int new_fb = 0;
+
+        if (cm->copy_buffer_to_arf == 1)
+            new_fb = cm->lst_fb_idx;
+        else if (cm->copy_buffer_to_arf == 2)
+            new_fb = cm->gld_fb_idx;
+        else
+            err = -1;
+
+        ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->alt_fb_idx, new_fb);
+    }
+
+    if (cm->copy_buffer_to_gf)
+    {
+        int new_fb = 0;
+
+        if (cm->copy_buffer_to_gf == 1)
+            new_fb = cm->lst_fb_idx;
+        else if (cm->copy_buffer_to_gf == 2)
+            new_fb = cm->alt_fb_idx;
+        else
+            err = -1;
+
+        ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->gld_fb_idx, new_fb);
+    }
+
+    if (cm->refresh_golden_frame)
+        ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->gld_fb_idx, cm->new_fb_idx);
+
+    if (cm->refresh_alt_ref_frame)
+        ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->alt_fb_idx, cm->new_fb_idx);
+
+    if (cm->refresh_last_frame)
+    {
+        ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->lst_fb_idx, cm->new_fb_idx);
+
+        cm->frame_to_show = &cm->yv12_fb[cm->lst_fb_idx];
+    }
+    else
+        cm->frame_to_show = &cm->yv12_fb[cm->new_fb_idx];
+
+    cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
+
+    return err;
+}
+
+int vp8dx_receive_compressed_data(VP8D_COMP *pbi, unsigned long size, const unsigned char *source, int64_t time_stamp)
+{
+#if HAVE_NEON
+    int64_t dx_store_reg[8];
+#endif
+    VP8_COMMON *cm = &pbi->common;
+    int retcode = 0;
+
+    /*if(pbi->ready_for_new_data == 0)
+        return -1;*/
+
+    if (pbi == 0)
+    {
+        return -1;
+    }
+
+    pbi->common.error.error_code = VPX_CODEC_OK;
+
+    if (pbi->num_fragments == 0)
+    {
+        /* New frame, reset fragment pointers and sizes */
+        vpx_memset(pbi->fragments, 0, sizeof(pbi->fragments));
+        vpx_memset(pbi->fragment_sizes, 0, sizeof(pbi->fragment_sizes));
+    }
+    if (pbi->input_fragments && !(source == NULL && size == 0))
+    {
+        /* Store a pointer to this fragment and return. We haven't
+         * received the complete frame yet, so we will wait with decoding.
+         */
+        assert(pbi->num_fragments < MAX_PARTITIONS);
+        pbi->fragments[pbi->num_fragments] = source;
+        pbi->fragment_sizes[pbi->num_fragments] = size;
+        pbi->num_fragments++;
+        if (pbi->num_fragments > (1 << EIGHT_PARTITION) + 1)
+        {
+            pbi->common.error.error_code = VPX_CODEC_UNSUP_BITSTREAM;
+            pbi->common.error.setjmp = 0;
+            pbi->num_fragments = 0;
+            return -1;
+        }
+        return 0;
+    }
+
+    if (!pbi->input_fragments)
+    {
+        pbi->fragments[0] = source;
+        pbi->fragment_sizes[0] = size;
+        pbi->num_fragments = 1;
+    }
+    assert(pbi->common.multi_token_partition <= EIGHT_PARTITION);
+    if (pbi->num_fragments == 0)
+    {
+        pbi->num_fragments = 1;
+        pbi->fragments[0] = NULL;
+        pbi->fragment_sizes[0] = 0;
+    }
+
+    if (!pbi->ec_active &&
+        pbi->num_fragments <= 1 && pbi->fragment_sizes[0] == 0)
+    {
+        /* If error concealment is disabled we won't signal missing frames
+         * to the decoder.
+         */
+        if (cm->fb_idx_ref_cnt[cm->lst_fb_idx] > 1)
+        {
+            /* The last reference shares buffer with another reference
+             * buffer. Move it to its own buffer before setting it as
+             * corrupt, otherwise we will make multiple buffers corrupt.
+             */
+            const int prev_idx = cm->lst_fb_idx;
+            cm->fb_idx_ref_cnt[prev_idx]--;
+            cm->lst_fb_idx = get_free_fb(cm);
+            vp8_yv12_copy_frame(&cm->yv12_fb[prev_idx],
+                                    &cm->yv12_fb[cm->lst_fb_idx]);
+        }
+        /* This is used to signal that we are missing frames.
+         * We do not know if the missing frame(s) was supposed to update
+         * any of the reference buffers, but we act conservative and
+         * mark only the last buffer as corrupted.
+         */
+        cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
+
+        /* Signal that we have no frame to show. */
+        cm->show_frame = 0;
+
+        pbi->num_fragments = 0;
+
+        /* Nothing more to do. */
+        return 0;
+    }
+
+#if HAVE_NEON
+#if CONFIG_RUNTIME_CPU_DETECT
+    if (cm->cpu_caps & HAS_NEON)
+#endif
+    {
+        vp8_push_neon(dx_store_reg);
+    }
+#endif
+
+    cm->new_fb_idx = get_free_fb (cm);
+
+    if (setjmp(pbi->common.error.jmp))
+    {
+#if HAVE_NEON
+#if CONFIG_RUNTIME_CPU_DETECT
+        if (cm->cpu_caps & HAS_NEON)
+#endif
+        {
+            vp8_pop_neon(dx_store_reg);
+        }
+#endif
+        pbi->common.error.setjmp = 0;
+
+        pbi->num_fragments = 0;
+
+       /* We do not know if the missing frame(s) was supposed to update
+        * any of the reference buffers, but we act conservative and
+        * mark only the last buffer as corrupted.
+        */
+        cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
+
+        if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
+          cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
+        return -1;
+    }
+
+    pbi->common.error.setjmp = 1;
+
+    retcode = vp8_decode_frame(pbi);
+
+    if (retcode < 0)
+    {
+#if HAVE_NEON
+#if CONFIG_RUNTIME_CPU_DETECT
+        if (cm->cpu_caps & HAS_NEON)
+#endif
+        {
+            vp8_pop_neon(dx_store_reg);
+        }
+#endif
+        pbi->common.error.error_code = VPX_CODEC_ERROR;
+        pbi->common.error.setjmp = 0;
+        pbi->num_fragments = 0;
+        if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
+          cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
+        return retcode;
+    }
+
+#if CONFIG_MULTITHREAD
+    if (pbi->b_multithreaded_rd && cm->multi_token_partition != ONE_PARTITION)
+    {
+        if (swap_frame_buffers (cm))
+        {
+#if HAVE_NEON
+#if CONFIG_RUNTIME_CPU_DETECT
+            if (cm->cpu_caps & HAS_NEON)
+#endif
+            {
+                vp8_pop_neon(dx_store_reg);
+            }
+#endif
+            pbi->common.error.error_code = VPX_CODEC_ERROR;
+            pbi->common.error.setjmp = 0;
+            pbi->num_fragments = 0;
+            return -1;
+        }
+    } else
+#endif
+    {
+        if (swap_frame_buffers (cm))
+        {
+#if HAVE_NEON
+#if CONFIG_RUNTIME_CPU_DETECT
+            if (cm->cpu_caps & HAS_NEON)
+#endif
+            {
+                vp8_pop_neon(dx_store_reg);
+            }
+#endif
+            pbi->common.error.error_code = VPX_CODEC_ERROR;
+            pbi->common.error.setjmp = 0;
+            pbi->num_fragments = 0;
+            return -1;
+        }
+
+        if(cm->filter_level)
+        {
+            /* Apply the loop filter if appropriate. */
+            vp8_loop_filter_frame(cm, &pbi->mb);
+        }
+        vp8_yv12_extend_frame_borders(cm->frame_to_show);
+    }
+
+
+    vp8_clear_system_state();
+
+#if CONFIG_ERROR_CONCEALMENT
+    /* swap the mode infos to storage for future error concealment */
+    if (pbi->ec_enabled && pbi->common.prev_mi)
+    {
+        MODE_INFO* tmp = pbi->common.prev_mi;
+        int row, col;
+        pbi->common.prev_mi = pbi->common.mi;
+        pbi->common.mi = tmp;
+
+        /* Propagate the segment_ids to the next frame */
+        for (row = 0; row < pbi->common.mb_rows; ++row)
+        {
+            for (col = 0; col < pbi->common.mb_cols; ++col)
+            {
+                const int i = row*pbi->common.mode_info_stride + col;
+                pbi->common.mi[i].mbmi.segment_id =
+                        pbi->common.prev_mi[i].mbmi.segment_id;
+            }
+        }
+    }
+#endif
+
+    /*vp8_print_modes_and_motion_vectors( cm->mi, cm->mb_rows,cm->mb_cols, cm->current_video_frame);*/
+
+    if (cm->show_frame)
+        cm->current_video_frame++;
+
+    pbi->ready_for_new_data = 0;
+    pbi->last_time_stamp = time_stamp;
+    pbi->num_fragments = 0;
+
+#if 0
+    {
+        int i;
+        int64_t earliest_time = pbi->dr[0].time_stamp;
+        int64_t latest_time = pbi->dr[0].time_stamp;
+        int64_t time_diff = 0;
+        int bytes = 0;
+
+        pbi->dr[pbi->common.current_video_frame&0xf].size = pbi->bc.pos + pbi->bc2.pos + 4;;
+        pbi->dr[pbi->common.current_video_frame&0xf].time_stamp = time_stamp;
+
+        for (i = 0; i < 16; i++)
+        {
+
+            bytes += pbi->dr[i].size;
+
+            if (pbi->dr[i].time_stamp < earliest_time)
+                earliest_time = pbi->dr[i].time_stamp;
+
+            if (pbi->dr[i].time_stamp > latest_time)
+                latest_time = pbi->dr[i].time_stamp;
+        }
+
+        time_diff = latest_time - earliest_time;
+
+        if (time_diff > 0)
+        {
+            pbi->common.bitrate = 80000.00 * bytes / time_diff  ;
+            pbi->common.framerate = 160000000.00 / time_diff ;
+        }
+
+    }
+#endif
+
+#if HAVE_NEON
+#if CONFIG_RUNTIME_CPU_DETECT
+    if (cm->cpu_caps & HAS_NEON)
+#endif
+    {
+        vp8_pop_neon(dx_store_reg);
+    }
+#endif
+    pbi->common.error.setjmp = 0;
+    return retcode;
+}
+int vp8dx_get_raw_frame(VP8D_COMP *pbi, YV12_BUFFER_CONFIG *sd, int64_t *time_stamp, int64_t *time_end_stamp, vp8_ppflags_t *flags)
+{
+    int ret = -1;
+
+    if (pbi->ready_for_new_data == 1)
+        return ret;
+
+    /* ie no raw frame to show!!! */
+    if (pbi->common.show_frame == 0)
+        return ret;
+
+    pbi->ready_for_new_data = 1;
+    *time_stamp = pbi->last_time_stamp;
+    *time_end_stamp = 0;
+
+    sd->clrtype = pbi->common.clr_type;
+#if CONFIG_POSTPROC
+    ret = vp8_post_proc_frame(&pbi->common, sd, flags);
+#else
+
+    if (pbi->common.frame_to_show)
+    {
+        *sd = *pbi->common.frame_to_show;
+        sd->y_width = pbi->common.Width;
+        sd->y_height = pbi->common.Height;
+        sd->uv_height = pbi->common.Height / 2;
+        ret = 0;
+    }
+    else
+    {
+        ret = -1;
+    }
+
+#endif /*!CONFIG_POSTPROC*/
+    vp8_clear_system_state();
+    return ret;
+}
+
+
+/* This function as written isn't decoder specific, but the encoder has
+ * much faster ways of computing this, so it's ok for it to live in a
+ * decode specific file.
+ */
+int vp8dx_references_buffer( VP8_COMMON *oci, int ref_frame )
+{
+    const MODE_INFO *mi = oci->mi;
+    int mb_row, mb_col;
+
+    for (mb_row = 0; mb_row < oci->mb_rows; mb_row++)
+    {
+        for (mb_col = 0; mb_col < oci->mb_cols; mb_col++,mi++)
+        {
+            if( mi->mbmi.ref_frame == ref_frame)
+              return 1;
+        }
+        mi++;
+    }
+    return 0;
+
+}
diff --git a/vp8/decoder/onyxd_int.h b/vp8/decoder/onyxd_int.h
new file mode 100644 (file)
index 0000000..97cf0dc
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_VP8D_INT_H
+#define __INC_VP8D_INT_H
+#include "vpx_config.h"
+#include "vp8/common/onyxd.h"
+#include "treereader.h"
+#include "vp8/common/onyxc_int.h"
+#include "vp8/common/threading.h"
+
+#if CONFIG_ERROR_CONCEALMENT
+#include "ec_types.h"
+#endif
+
+typedef struct
+{
+    int ithread;
+    void *ptr1;
+    void *ptr2;
+} DECODETHREAD_DATA;
+
+typedef struct
+{
+    MACROBLOCKD  mbd;
+    int mb_row;
+} MB_ROW_DEC;
+
+typedef struct
+{
+    int64_t time_stamp;
+    int size;
+} DATARATE;
+
+
+typedef struct VP8D_COMP
+{
+    DECLARE_ALIGNED(16, MACROBLOCKD, mb);
+
+    DECLARE_ALIGNED(16, VP8_COMMON, common);
+
+    vp8_reader bc, bc2;
+
+    VP8D_CONFIG oxcf;
+
+
+    const unsigned char *fragments[MAX_PARTITIONS];
+    unsigned int   fragment_sizes[MAX_PARTITIONS];
+    unsigned int   num_fragments;
+
+#if CONFIG_MULTITHREAD
+    /* variable for threading */
+
+    volatile int b_multithreaded_rd;
+    int max_threads;
+    int current_mb_col_main;
+    int decoding_thread_count;
+    int allocated_decoding_thread_count;
+
+    int mt_baseline_filter_level[MAX_MB_SEGMENTS];
+    int sync_range;
+    int *mt_current_mb_col;                  /* Each row remembers its already decoded column. */
+
+    unsigned char **mt_yabove_row;           /* mb_rows x width */
+    unsigned char **mt_uabove_row;
+    unsigned char **mt_vabove_row;
+    unsigned char **mt_yleft_col;            /* mb_rows x 16 */
+    unsigned char **mt_uleft_col;            /* mb_rows x 8 */
+    unsigned char **mt_vleft_col;            /* mb_rows x 8 */
+
+    MB_ROW_DEC           *mb_row_di;
+    DECODETHREAD_DATA    *de_thread_data;
+
+    pthread_t           *h_decoding_thread;
+    sem_t               *h_event_start_decoding;
+    sem_t                h_event_end_decoding;
+    /* end of threading data */
+#endif
+
+    vp8_reader *mbc;
+    int64_t last_time_stamp;
+    int   ready_for_new_data;
+
+    DATARATE dr[16];
+
+    vp8_prob prob_intra;
+    vp8_prob prob_last;
+    vp8_prob prob_gf;
+    vp8_prob prob_skip_false;
+
+#if CONFIG_ERROR_CONCEALMENT
+    MB_OVERLAP *overlaps;
+    /* the mb num from which modes and mvs (first partition) are corrupt */
+    unsigned int mvs_corrupt_from_mb;
+#endif
+    int ec_enabled;
+    int ec_active;
+    int input_fragments;
+    int decoded_key_frame;
+    int independent_partitions;
+    int frame_corrupt_residual;
+
+} VP8D_COMP;
+
+int vp8_decode_frame(VP8D_COMP *cpi);
+
+#if CONFIG_DEBUG
+#define CHECK_MEM_ERROR(lval,expr) do {\
+        lval = (expr); \
+        if(!lval) \
+            vpx_internal_error(&pbi->common.error, VPX_CODEC_MEM_ERROR,\
+                               "Failed to allocate "#lval" at %s:%d", \
+                               __FILE__,__LINE__);\
+    } while(0)
+#else
+#define CHECK_MEM_ERROR(lval,expr) do {\
+        lval = (expr); \
+        if(!lval) \
+            vpx_internal_error(&pbi->common.error, VPX_CODEC_MEM_ERROR,\
+                               "Failed to allocate "#lval);\
+    } while(0)
+#endif
+
+#endif
diff --git a/vp8/decoder/threading.c b/vp8/decoder/threading.c
new file mode 100644 (file)
index 0000000..47a0349
--- /dev/null
@@ -0,0 +1,922 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#if !defined(WIN32) && CONFIG_OS_SUPPORT == 1
+# include <unistd.h>
+#endif
+#include "onyxd_int.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vp8/common/threading.h"
+
+#include "vp8/common/loopfilter.h"
+#include "vp8/common/extend.h"
+#include "vpx_ports/vpx_timer.h"
+#include "detokenize.h"
+#include "vp8/common/reconintra4x4.h"
+#include "vp8/common/reconinter.h"
+#if CONFIG_ERROR_CONCEALMENT
+#include "error_concealment.h"
+#endif
+
+extern void vp8_mb_init_dequantizer(VP8D_COMP *pbi, MACROBLOCKD *xd);
+
+static void setup_decoding_thread_data(VP8D_COMP *pbi, MACROBLOCKD *xd, MB_ROW_DEC *mbrd, int count)
+{
+    VP8_COMMON *const pc = & pbi->common;
+    int i;
+
+    for (i = 0; i < count; i++)
+    {
+        MACROBLOCKD *mbd = &mbrd[i].mbd;
+        mbd->subpixel_predict        = xd->subpixel_predict;
+        mbd->subpixel_predict8x4     = xd->subpixel_predict8x4;
+        mbd->subpixel_predict8x8     = xd->subpixel_predict8x8;
+        mbd->subpixel_predict16x16   = xd->subpixel_predict16x16;
+
+        mbd->mode_info_context = pc->mi   + pc->mode_info_stride * (i + 1);
+        mbd->mode_info_stride  = pc->mode_info_stride;
+
+        mbd->frame_type = pc->frame_type;
+        mbd->pre = pc->yv12_fb[pc->lst_fb_idx];
+        mbd->dst = pc->yv12_fb[pc->new_fb_idx];
+
+        vp8_setup_block_dptrs(mbd);
+        vp8_build_block_doffsets(mbd);
+        mbd->segmentation_enabled    = xd->segmentation_enabled;
+        mbd->mb_segement_abs_delta     = xd->mb_segement_abs_delta;
+        vpx_memcpy(mbd->segment_feature_data, xd->segment_feature_data, sizeof(xd->segment_feature_data));
+
+        /*signed char ref_lf_deltas[MAX_REF_LF_DELTAS];*/
+        vpx_memcpy(mbd->ref_lf_deltas, xd->ref_lf_deltas, sizeof(xd->ref_lf_deltas));
+        /*signed char mode_lf_deltas[MAX_MODE_LF_DELTAS];*/
+        vpx_memcpy(mbd->mode_lf_deltas, xd->mode_lf_deltas, sizeof(xd->mode_lf_deltas));
+        /*unsigned char mode_ref_lf_delta_enabled;
+        unsigned char mode_ref_lf_delta_update;*/
+        mbd->mode_ref_lf_delta_enabled    = xd->mode_ref_lf_delta_enabled;
+        mbd->mode_ref_lf_delta_update    = xd->mode_ref_lf_delta_update;
+
+        mbd->current_bc = &pbi->bc2;
+
+        vpx_memcpy(mbd->dequant_y1_dc, xd->dequant_y1_dc, sizeof(xd->dequant_y1_dc));
+        vpx_memcpy(mbd->dequant_y1, xd->dequant_y1, sizeof(xd->dequant_y1));
+        vpx_memcpy(mbd->dequant_y2, xd->dequant_y2, sizeof(xd->dequant_y2));
+        vpx_memcpy(mbd->dequant_uv, xd->dequant_uv, sizeof(xd->dequant_uv));
+
+        mbd->fullpixel_mask = 0xffffffff;
+        if(pc->full_pixel)
+            mbd->fullpixel_mask = 0xfffffff8;
+
+    }
+
+    for (i=0; i< pc->mb_rows; i++)
+        pbi->mt_current_mb_col[i]=-1;
+}
+
+static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd, unsigned int mb_idx)
+{
+    MB_PREDICTION_MODE mode;
+    int i;
+#if CONFIG_ERROR_CONCEALMENT
+    int corruption_detected = 0;
+#endif
+
+    if (xd->mode_info_context->mbmi.mb_skip_coeff)
+    {
+        vp8_reset_mb_tokens_context(xd);
+    }
+    else if (!vp8dx_bool_error(xd->current_bc))
+    {
+        int eobtotal;
+        eobtotal = vp8_decode_mb_tokens(pbi, xd);
+
+        /* Special case:  Force the loopfilter to skip when eobtotal is zero */
+        xd->mode_info_context->mbmi.mb_skip_coeff = (eobtotal==0);
+    }
+
+    mode = xd->mode_info_context->mbmi.mode;
+
+    if (xd->segmentation_enabled)
+        vp8_mb_init_dequantizer(pbi, xd);
+
+
+#if CONFIG_ERROR_CONCEALMENT
+
+    if(pbi->ec_active)
+    {
+        int throw_residual;
+        /* When we have independent partitions we can apply residual even
+         * though other partitions within the frame are corrupt.
+         */
+        throw_residual = (!pbi->independent_partitions &&
+                          pbi->frame_corrupt_residual);
+        throw_residual = (throw_residual || vp8dx_bool_error(xd->current_bc));
+
+        if ((mb_idx >= pbi->mvs_corrupt_from_mb || throw_residual))
+        {
+            /* MB with corrupt residuals or corrupt mode/motion vectors.
+             * Better to use the predictor as reconstruction.
+             */
+            pbi->frame_corrupt_residual = 1;
+            vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
+            vp8_conceal_corrupt_mb(xd);
+
+
+            corruption_detected = 1;
+
+            /* force idct to be skipped for B_PRED and use the
+             * prediction only for reconstruction
+             * */
+            vpx_memset(xd->eobs, 0, 25);
+        }
+    }
+#endif
+
+    /* do prediction */
+    if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME)
+    {
+        vp8_build_intra_predictors_mbuv_s(xd,
+                                          xd->recon_above[1],
+                                          xd->recon_above[2],
+                                          xd->recon_left[1],
+                                          xd->recon_left[2],
+                                          xd->recon_left_stride[1],
+                                          xd->dst.u_buffer, xd->dst.v_buffer,
+                                          xd->dst.uv_stride);
+
+        if (mode != B_PRED)
+        {
+            vp8_build_intra_predictors_mby_s(xd,
+                                                 xd->recon_above[0],
+                                                 xd->recon_left[0],
+                                                 xd->recon_left_stride[0],
+                                                 xd->dst.y_buffer,
+                                                 xd->dst.y_stride);
+        }
+        else
+        {
+            short *DQC = xd->dequant_y1;
+            int dst_stride = xd->dst.y_stride;
+            unsigned char *base_dst = xd->dst.y_buffer;
+
+            /* clear out residual eob info */
+            if(xd->mode_info_context->mbmi.mb_skip_coeff)
+                vpx_memset(xd->eobs, 0, 25);
+
+            intra_prediction_down_copy(xd, xd->recon_above[0] + 16);
+
+            for (i = 0; i < 16; i++)
+            {
+                BLOCKD *b = &xd->block[i];
+                int b_mode = xd->mode_info_context->bmi[i].as_mode;
+                unsigned char *yabove;
+                unsigned char *yleft;
+                int left_stride;
+                unsigned char top_left;
+
+                /*Caution: For some b_mode, it needs 8 pixels (4 above + 4 above-right).*/
+                if (i < 4 && pbi->common.filter_level)
+                    yabove = xd->recon_above[0] + b->offset; //i*4;
+                else
+                    yabove = (base_dst - dst_stride) + b->offset;
+
+                if (i%4==0 && pbi->common.filter_level)
+                {
+                    yleft = xd->recon_left[0] + i;
+                    left_stride = 1;
+                }
+                else
+                {
+                    yleft = (base_dst  - 1) + b->offset;
+                    left_stride = dst_stride;
+                }
+
+                if ((i==4 || i==8 || i==12) && pbi->common.filter_level)
+                    top_left = *(xd->recon_left[0] + i - 1);
+                else
+                    top_left = yabove[-1];
+
+                vp8_intra4x4_predict_d_c(yabove, yleft, left_stride,
+                                       b_mode,
+                                       base_dst + b->offset, dst_stride,
+                                       top_left);
+
+                if (xd->eobs[i] )
+                {
+                    if (xd->eobs[i] > 1)
+                    {
+                        vp8_dequant_idct_add
+                            (b->qcoeff, DQC,
+                            base_dst + b->offset, dst_stride);
+                    }
+                    else
+                    {
+                        vp8_dc_only_idct_add
+                            (b->qcoeff[0] * DQC[0],
+                            base_dst + b->offset, dst_stride,
+                            base_dst + b->offset, dst_stride);
+                        ((int *)b->qcoeff)[0] = 0;
+                    }
+                }
+            }
+        }
+    }
+    else
+    {
+        vp8_build_inter_predictors_mb(xd);
+    }
+
+
+#if CONFIG_ERROR_CONCEALMENT
+    if (corruption_detected)
+    {
+        return;
+    }
+#endif
+
+    if(!xd->mode_info_context->mbmi.mb_skip_coeff)
+    {
+        /* dequantization and idct */
+        if (mode != B_PRED)
+        {
+            short *DQC = xd->dequant_y1;
+
+            if (mode != SPLITMV)
+            {
+                BLOCKD *b = &xd->block[24];
+
+                /* do 2nd order transform on the dc block */
+                if (xd->eobs[24] > 1)
+                {
+                    vp8_dequantize_b(b, xd->dequant_y2);
+
+                    vp8_short_inv_walsh4x4(&b->dqcoeff[0],
+                        xd->qcoeff);
+                    ((int *)b->qcoeff)[0] = 0;
+                    ((int *)b->qcoeff)[1] = 0;
+                    ((int *)b->qcoeff)[2] = 0;
+                    ((int *)b->qcoeff)[3] = 0;
+                    ((int *)b->qcoeff)[4] = 0;
+                    ((int *)b->qcoeff)[5] = 0;
+                    ((int *)b->qcoeff)[6] = 0;
+                    ((int *)b->qcoeff)[7] = 0;
+                }
+                else
+                {
+                    b->dqcoeff[0] = b->qcoeff[0] * xd->dequant_y2[0];
+                    vp8_short_inv_walsh4x4_1(&b->dqcoeff[0],
+                        xd->qcoeff);
+                    ((int *)b->qcoeff)[0] = 0;
+                }
+
+                /* override the dc dequant constant in order to preserve the
+                 * dc components
+                 */
+                DQC = xd->dequant_y1_dc;
+            }
+
+            vp8_dequant_idct_add_y_block
+                            (xd->qcoeff, DQC,
+                             xd->dst.y_buffer,
+                             xd->dst.y_stride, xd->eobs);
+        }
+
+        vp8_dequant_idct_add_uv_block
+                        (xd->qcoeff+16*16, xd->dequant_uv,
+                         xd->dst.u_buffer, xd->dst.v_buffer,
+                         xd->dst.uv_stride, xd->eobs+16);
+    }
+}
+
+typedef void (*init_current_bc_fn_t)(VP8D_COMP *pbi, MACROBLOCKD *xd,
+    int start_mb_row, int mb_row, int num_part);
+
+static void init_current_bc(VP8D_COMP *pbi, MACROBLOCKD *xd, int start_mb_row,
+                     int mb_row, int num_part)
+{
+    (void) start_mb_row;
+
+    xd->current_bc = &pbi->mbc[mb_row%num_part];
+}
+
+static void init_current_bc_threads(VP8D_COMP *pbi, MACROBLOCKD *xd,
+                     int start_mb_row, int mb_row, int num_part)
+{
+    (void) xd;
+    pbi->mb_row_di[start_mb_row - 1].mb_row = mb_row;
+    pbi->mb_row_di[start_mb_row - 1].mbd.current_bc =  &pbi->mbc[mb_row%num_part];
+}
+
+
+static void decode_mb_rows(VP8D_COMP *pbi, MACROBLOCKD *xd, int start_mb_row,
+                           init_current_bc_fn_t init_current_bc_fn)
+{
+    volatile int *last_row_current_mb_col = NULL;
+    int mb_row;
+    VP8_COMMON *pc = &pbi->common;
+    int nsync = pbi->sync_range;
+    int num_part = 1 << pbi->common.multi_token_partition;
+
+    int dst_fb_idx = pc->new_fb_idx;
+    unsigned char *ref_buffer[MAX_REF_FRAMES][3];
+    unsigned char *dst_buffer[3];
+    int i;
+    int ref_fb_index[MAX_REF_FRAMES];
+    int ref_fb_corrupted[MAX_REF_FRAMES];
+
+    ref_fb_corrupted[INTRA_FRAME] = 0;
+
+    ref_fb_index[LAST_FRAME]    = pc->lst_fb_idx;
+    ref_fb_index[GOLDEN_FRAME]  = pc->gld_fb_idx;
+    ref_fb_index[ALTREF_FRAME]  = pc->alt_fb_idx;
+
+    for(i = 1; i < MAX_REF_FRAMES; i++)
+    {
+        ref_buffer[i][0] = pc->yv12_fb[ref_fb_index[i]].y_buffer;
+        ref_buffer[i][1] = pc->yv12_fb[ref_fb_index[i]].u_buffer;
+        ref_buffer[i][2] = pc->yv12_fb[ref_fb_index[i]].v_buffer;
+
+        ref_fb_corrupted[i] = pc->yv12_fb[ref_fb_index[i]].corrupted;
+    }
+
+    dst_buffer[0] = pc->yv12_fb[dst_fb_idx].y_buffer;
+    dst_buffer[1] = pc->yv12_fb[dst_fb_idx].u_buffer;
+    dst_buffer[2] = pc->yv12_fb[dst_fb_idx].v_buffer;
+
+    xd->up_available = (start_mb_row != 0);
+
+    for (mb_row = start_mb_row; mb_row < pc->mb_rows; mb_row += (pbi->decoding_thread_count + 1))
+    {
+       int i;
+       int recon_yoffset, recon_uvoffset;
+       int mb_col;
+       int ref_fb_idx = pc->lst_fb_idx;
+       int dst_fb_idx = pc->new_fb_idx;
+       int recon_y_stride = pc->yv12_fb[ref_fb_idx].y_stride;
+       int recon_uv_stride = pc->yv12_fb[ref_fb_idx].uv_stride;
+
+       int filter_level;
+       loop_filter_info_n *lfi_n = &pc->lf_info;
+
+       init_current_bc_fn(pbi, xd, start_mb_row, mb_row, num_part);
+
+       if (mb_row > 0)
+           last_row_current_mb_col = &pbi->mt_current_mb_col[mb_row -1];
+
+       recon_yoffset = mb_row * recon_y_stride * 16;
+       recon_uvoffset = mb_row * recon_uv_stride * 8;
+
+       /* reset contexts */
+       xd->above_context = pc->above_context;
+       vpx_memset(xd->left_context, 0, sizeof(ENTROPY_CONTEXT_PLANES));
+
+       xd->left_available = 0;
+
+       xd->mb_to_top_edge = -((mb_row * 16)) << 3;
+       xd->mb_to_bottom_edge = ((pc->mb_rows - 1 - mb_row) * 16) << 3;
+
+       if (pbi->common.filter_level)
+       {
+          xd->recon_above[0] = pbi->mt_yabove_row[mb_row] + 0*16 +32;
+          xd->recon_above[1] = pbi->mt_uabove_row[mb_row] + 0*8 +16;
+          xd->recon_above[2] = pbi->mt_vabove_row[mb_row] + 0*8 +16;
+
+          xd->recon_left[0] = pbi->mt_yleft_col[mb_row];
+          xd->recon_left[1] = pbi->mt_uleft_col[mb_row];
+          xd->recon_left[2] = pbi->mt_vleft_col[mb_row];
+
+          //TODO: move to outside row loop
+          xd->recon_left_stride[0] = 1;
+          xd->recon_left_stride[1] = 1;
+       }
+       else
+       {
+          xd->recon_above[0] = dst_buffer[0] + recon_yoffset;
+          xd->recon_above[1] = dst_buffer[1] + recon_uvoffset;
+          xd->recon_above[2] = dst_buffer[2] + recon_uvoffset;
+
+          xd->recon_left[0] = xd->recon_above[0] - 1;
+          xd->recon_left[1] = xd->recon_above[1] - 1;
+          xd->recon_left[2] = xd->recon_above[2] - 1;
+
+          xd->recon_above[0] -= xd->dst.y_stride;
+          xd->recon_above[1] -= xd->dst.uv_stride;
+          xd->recon_above[2] -= xd->dst.uv_stride;
+
+          //TODO: move to outside row loop
+          xd->recon_left_stride[0] = xd->dst.y_stride;
+          xd->recon_left_stride[1] = xd->dst.uv_stride;
+       }
+
+       for (mb_col = 0; mb_col < pc->mb_cols; mb_col++)
+       {
+           if ( mb_row > 0 && (mb_col & (nsync-1)) == 0)
+           {
+               while (mb_col > (*last_row_current_mb_col - nsync) && *last_row_current_mb_col != pc->mb_cols - 1)
+               {
+                   x86_pause_hint();
+                   thread_sleep(0);
+               }
+           }
+
+           /* Distance of MB to the various image edges.
+            * These are specified to 8th pel as they are always
+            * compared to values that are in 1/8th pel units.
+            */
+           xd->mb_to_left_edge = -((mb_col * 16) << 3);
+           xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
+
+    #if CONFIG_ERROR_CONCEALMENT
+           {
+               int corrupt_residual =
+                           (!pbi->independent_partitions &&
+                           pbi->frame_corrupt_residual) ||
+                           vp8dx_bool_error(xd->current_bc);
+               if (pbi->ec_active &&
+                   (xd->mode_info_context->mbmi.ref_frame ==
+                                                    INTRA_FRAME) &&
+                   corrupt_residual)
+               {
+                   /* We have an intra block with corrupt
+                    * coefficients, better to conceal with an inter
+                    * block.
+                    * Interpolate MVs from neighboring MBs
+                    *
+                    * Note that for the first mb with corrupt
+                    * residual in a frame, we might not discover
+                    * that before decoding the residual. That
+                    * happens after this check, and therefore no
+                    * inter concealment will be done.
+                    */
+                   vp8_interpolate_motion(xd,
+                                          mb_row, mb_col,
+                                          pc->mb_rows, pc->mb_cols,
+                                          pc->mode_info_stride);
+               }
+           }
+    #endif
+
+
+           xd->dst.y_buffer = dst_buffer[0] + recon_yoffset;
+           xd->dst.u_buffer = dst_buffer[1] + recon_uvoffset;
+           xd->dst.v_buffer = dst_buffer[2] + recon_uvoffset;
+
+           xd->pre.y_buffer = ref_buffer[xd->mode_info_context->mbmi.ref_frame][0] + recon_yoffset;
+           xd->pre.u_buffer = ref_buffer[xd->mode_info_context->mbmi.ref_frame][1] + recon_uvoffset;
+           xd->pre.v_buffer = ref_buffer[xd->mode_info_context->mbmi.ref_frame][2] + recon_uvoffset;
+
+           /* propagate errors from reference frames */
+           xd->corrupted |= ref_fb_corrupted[xd->mode_info_context->mbmi.ref_frame];
+
+           decode_macroblock(pbi, xd, 0);
+
+           xd->left_available = 1;
+
+           /* check if the boolean decoder has suffered an error */
+           xd->corrupted |= vp8dx_bool_error(xd->current_bc);
+
+           xd->recon_above[0] += 16;
+           xd->recon_above[1] += 8;
+           xd->recon_above[2] += 8;
+
+           if (!pbi->common.filter_level)
+           {
+              xd->recon_left[0] += 16;
+              xd->recon_left[1] += 8;
+              xd->recon_left[2] += 8;
+           }
+
+           if (pbi->common.filter_level)
+           {
+               int skip_lf = (xd->mode_info_context->mbmi.mode != B_PRED &&
+                               xd->mode_info_context->mbmi.mode != SPLITMV &&
+                               xd->mode_info_context->mbmi.mb_skip_coeff);
+
+               const int mode_index = lfi_n->mode_lf_lut[xd->mode_info_context->mbmi.mode];
+               const int seg = xd->mode_info_context->mbmi.segment_id;
+               const int ref_frame = xd->mode_info_context->mbmi.ref_frame;
+
+               filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
+
+               if( mb_row != pc->mb_rows-1 )
+               {
+                   /* Save decoded MB last row data for next-row decoding */
+                   vpx_memcpy((pbi->mt_yabove_row[mb_row + 1] + 32 + mb_col*16), (xd->dst.y_buffer + 15 * recon_y_stride), 16);
+                   vpx_memcpy((pbi->mt_uabove_row[mb_row + 1] + 16 + mb_col*8), (xd->dst.u_buffer + 7 * recon_uv_stride), 8);
+                   vpx_memcpy((pbi->mt_vabove_row[mb_row + 1] + 16 + mb_col*8), (xd->dst.v_buffer + 7 * recon_uv_stride), 8);
+               }
+
+               /* save left_col for next MB decoding */
+               if(mb_col != pc->mb_cols-1)
+               {
+                   MODE_INFO *next = xd->mode_info_context +1;
+
+                   if (next->mbmi.ref_frame == INTRA_FRAME)
+                   {
+                       for (i = 0; i < 16; i++)
+                           pbi->mt_yleft_col[mb_row][i] = xd->dst.y_buffer [i* recon_y_stride + 15];
+                       for (i = 0; i < 8; i++)
+                       {
+                           pbi->mt_uleft_col[mb_row][i] = xd->dst.u_buffer [i* recon_uv_stride + 7];
+                           pbi->mt_vleft_col[mb_row][i] = xd->dst.v_buffer [i* recon_uv_stride + 7];
+                       }
+                   }
+               }
+
+               /* loopfilter on this macroblock. */
+               if (filter_level)
+               {
+                   if(pc->filter_type == NORMAL_LOOPFILTER)
+                   {
+                       loop_filter_info lfi;
+                       FRAME_TYPE frame_type = pc->frame_type;
+                       const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level];
+                       lfi.mblim = lfi_n->mblim[filter_level];
+                       lfi.blim = lfi_n->blim[filter_level];
+                       lfi.lim = lfi_n->lim[filter_level];
+                       lfi.hev_thr = lfi_n->hev_thr[hev_index];
+
+                       if (mb_col > 0)
+                           vp8_loop_filter_mbv
+                           (xd->dst.y_buffer, xd->dst.u_buffer, xd->dst.v_buffer, recon_y_stride, recon_uv_stride, &lfi);
+
+                       if (!skip_lf)
+                           vp8_loop_filter_bv
+                           (xd->dst.y_buffer, xd->dst.u_buffer, xd->dst.v_buffer, recon_y_stride, recon_uv_stride, &lfi);
+
+                       /* don't apply across umv border */
+                       if (mb_row > 0)
+                           vp8_loop_filter_mbh
+                           (xd->dst.y_buffer, xd->dst.u_buffer, xd->dst.v_buffer, recon_y_stride, recon_uv_stride, &lfi);
+
+                       if (!skip_lf)
+                           vp8_loop_filter_bh
+                           (xd->dst.y_buffer, xd->dst.u_buffer, xd->dst.v_buffer,  recon_y_stride, recon_uv_stride, &lfi);
+                   }
+                   else
+                   {
+                       if (mb_col > 0)
+                           vp8_loop_filter_simple_mbv
+                           (xd->dst.y_buffer, recon_y_stride, lfi_n->mblim[filter_level]);
+
+                       if (!skip_lf)
+                           vp8_loop_filter_simple_bv
+                           (xd->dst.y_buffer, recon_y_stride, lfi_n->blim[filter_level]);
+
+                       /* don't apply across umv border */
+                       if (mb_row > 0)
+                           vp8_loop_filter_simple_mbh
+                           (xd->dst.y_buffer, recon_y_stride, lfi_n->mblim[filter_level]);
+
+                       if (!skip_lf)
+                           vp8_loop_filter_simple_bh
+                           (xd->dst.y_buffer, recon_y_stride, lfi_n->blim[filter_level]);
+                   }
+               }
+
+           }
+
+           recon_yoffset += 16;
+           recon_uvoffset += 8;
+
+           ++xd->mode_info_context;  /* next mb */
+
+           xd->above_context++;
+
+           /*pbi->mb_row_di[ithread].current_mb_col = mb_col;*/
+           pbi->mt_current_mb_col[mb_row] = mb_col;
+       }
+
+       /* adjust to the next row of mbs */
+       if (pbi->common.filter_level)
+       {
+           if(mb_row != pc->mb_rows-1)
+           {
+               int lasty = pc->yv12_fb[ref_fb_idx].y_width + VP8BORDERINPIXELS;
+               int lastuv = (pc->yv12_fb[ref_fb_idx].y_width>>1) + (VP8BORDERINPIXELS>>1);
+
+               for (i = 0; i < 4; i++)
+               {
+                   pbi->mt_yabove_row[mb_row +1][lasty + i] = pbi->mt_yabove_row[mb_row +1][lasty -1];
+                   pbi->mt_uabove_row[mb_row +1][lastuv + i] = pbi->mt_uabove_row[mb_row +1][lastuv -1];
+                   pbi->mt_vabove_row[mb_row +1][lastuv + i] = pbi->mt_vabove_row[mb_row +1][lastuv -1];
+               }
+           }
+       } else
+           vp8_extend_mb_row(&pc->yv12_fb[dst_fb_idx], xd->dst.y_buffer + 16, xd->dst.u_buffer + 8, xd->dst.v_buffer + 8);
+
+       ++xd->mode_info_context;      /* skip prediction column */
+       xd->up_available = 1;
+
+       /* since we have multithread */
+       xd->mode_info_context += xd->mode_info_stride * pbi->decoding_thread_count;
+    }
+}
+
+
+static THREAD_FUNCTION thread_decoding_proc(void *p_data)
+{
+    int ithread = ((DECODETHREAD_DATA *)p_data)->ithread;
+    VP8D_COMP *pbi = (VP8D_COMP *)(((DECODETHREAD_DATA *)p_data)->ptr1);
+    MB_ROW_DEC *mbrd = (MB_ROW_DEC *)(((DECODETHREAD_DATA *)p_data)->ptr2);
+    ENTROPY_CONTEXT_PLANES mb_row_left_context;
+
+    while (1)
+    {
+        if (pbi->b_multithreaded_rd == 0)
+            break;
+
+        /*if(WaitForSingleObject(pbi->h_event_start_decoding[ithread], INFINITE) == WAIT_OBJECT_0)*/
+        if (sem_wait(&pbi->h_event_start_decoding[ithread]) == 0)
+        {
+            if (pbi->b_multithreaded_rd == 0)
+                break;
+            else
+            {
+                MACROBLOCKD *xd = &mbrd->mbd;
+
+                xd->left_context = &mb_row_left_context;
+
+                decode_mb_rows(pbi, xd, ithread+1, init_current_bc_threads);
+            }
+        }
+
+        /*  add this to each frame */
+        if ((mbrd->mb_row == pbi->common.mb_rows-1) ||
+            ((mbrd->mb_row == pbi->common.mb_rows-2) &&
+                (pbi->common.mb_rows % (pbi->decoding_thread_count+1))==1))
+        {
+            /*SetEvent(pbi->h_event_end_decoding);*/
+            sem_post(&pbi->h_event_end_decoding);
+        }
+    }
+
+    return 0 ;
+}
+
+
+void vp8_decoder_create_threads(VP8D_COMP *pbi)
+{
+    int core_count = 0;
+    int ithread;
+
+    pbi->b_multithreaded_rd = 0;
+    pbi->allocated_decoding_thread_count = 0;
+
+    /* limit decoding threads to the max number of token partitions */
+    core_count = (pbi->max_threads > 8) ? 8 : pbi->max_threads;
+
+    /* limit decoding threads to the available cores */
+    if (core_count > pbi->common.processor_core_count)
+        core_count = pbi->common.processor_core_count;
+
+    if (core_count > 1)
+    {
+        pbi->b_multithreaded_rd = 1;
+        pbi->decoding_thread_count = core_count - 1;
+
+        CHECK_MEM_ERROR(pbi->h_decoding_thread, vpx_malloc(sizeof(pthread_t) * pbi->decoding_thread_count));
+        CHECK_MEM_ERROR(pbi->h_event_start_decoding, vpx_malloc(sizeof(sem_t) * pbi->decoding_thread_count));
+        CHECK_MEM_ERROR(pbi->mb_row_di, vpx_memalign(32, sizeof(MB_ROW_DEC) * pbi->decoding_thread_count));
+        vpx_memset(pbi->mb_row_di, 0, sizeof(MB_ROW_DEC) * pbi->decoding_thread_count);
+        CHECK_MEM_ERROR(pbi->de_thread_data, vpx_malloc(sizeof(DECODETHREAD_DATA) * pbi->decoding_thread_count));
+
+        for (ithread = 0; ithread < pbi->decoding_thread_count; ithread++)
+        {
+            sem_init(&pbi->h_event_start_decoding[ithread], 0, 0);
+
+            pbi->de_thread_data[ithread].ithread  = ithread;
+            pbi->de_thread_data[ithread].ptr1     = (void *)pbi;
+            pbi->de_thread_data[ithread].ptr2     = (void *) &pbi->mb_row_di[ithread];
+
+            pthread_create(&pbi->h_decoding_thread[ithread], 0, thread_decoding_proc, (&pbi->de_thread_data[ithread]));
+        }
+
+        sem_init(&pbi->h_event_end_decoding, 0, 0);
+
+        pbi->allocated_decoding_thread_count = pbi->decoding_thread_count;
+    }
+}
+
+
+void vp8mt_de_alloc_temp_buffers(VP8D_COMP *pbi, int mb_rows)
+{
+    int i;
+
+    if (pbi->b_multithreaded_rd)
+    {
+            vpx_free(pbi->mt_current_mb_col);
+            pbi->mt_current_mb_col = NULL ;
+
+        /* Free above_row buffers. */
+        if (pbi->mt_yabove_row)
+        {
+            for (i=0; i< mb_rows; i++)
+            {
+                    vpx_free(pbi->mt_yabove_row[i]);
+                    pbi->mt_yabove_row[i] = NULL ;
+            }
+            vpx_free(pbi->mt_yabove_row);
+            pbi->mt_yabove_row = NULL ;
+        }
+
+        if (pbi->mt_uabove_row)
+        {
+            for (i=0; i< mb_rows; i++)
+            {
+                    vpx_free(pbi->mt_uabove_row[i]);
+                    pbi->mt_uabove_row[i] = NULL ;
+            }
+            vpx_free(pbi->mt_uabove_row);
+            pbi->mt_uabove_row = NULL ;
+        }
+
+        if (pbi->mt_vabove_row)
+        {
+            for (i=0; i< mb_rows; i++)
+            {
+                    vpx_free(pbi->mt_vabove_row[i]);
+                    pbi->mt_vabove_row[i] = NULL ;
+            }
+            vpx_free(pbi->mt_vabove_row);
+            pbi->mt_vabove_row = NULL ;
+        }
+
+        /* Free left_col buffers. */
+        if (pbi->mt_yleft_col)
+        {
+            for (i=0; i< mb_rows; i++)
+            {
+                    vpx_free(pbi->mt_yleft_col[i]);
+                    pbi->mt_yleft_col[i] = NULL ;
+            }
+            vpx_free(pbi->mt_yleft_col);
+            pbi->mt_yleft_col = NULL ;
+        }
+
+        if (pbi->mt_uleft_col)
+        {
+            for (i=0; i< mb_rows; i++)
+            {
+                    vpx_free(pbi->mt_uleft_col[i]);
+                    pbi->mt_uleft_col[i] = NULL ;
+            }
+            vpx_free(pbi->mt_uleft_col);
+            pbi->mt_uleft_col = NULL ;
+        }
+
+        if (pbi->mt_vleft_col)
+        {
+            for (i=0; i< mb_rows; i++)
+            {
+                    vpx_free(pbi->mt_vleft_col[i]);
+                    pbi->mt_vleft_col[i] = NULL ;
+            }
+            vpx_free(pbi->mt_vleft_col);
+            pbi->mt_vleft_col = NULL ;
+        }
+    }
+}
+
+
+void vp8mt_alloc_temp_buffers(VP8D_COMP *pbi, int width, int prev_mb_rows)
+{
+    VP8_COMMON *const pc = & pbi->common;
+    int i;
+    int uv_width;
+
+    if (pbi->b_multithreaded_rd)
+    {
+        vp8mt_de_alloc_temp_buffers(pbi, prev_mb_rows);
+
+        /* our internal buffers are always multiples of 16 */
+        if ((width & 0xf) != 0)
+            width += 16 - (width & 0xf);
+
+        if (width < 640) pbi->sync_range = 1;
+        else if (width <= 1280) pbi->sync_range = 8;
+        else if (width <= 2560) pbi->sync_range =16;
+        else pbi->sync_range = 32;
+
+        uv_width = width >>1;
+
+        /* Allocate an int for each mb row. */
+        CHECK_MEM_ERROR(pbi->mt_current_mb_col, vpx_malloc(sizeof(int) * pc->mb_rows));
+
+        /* Allocate memory for above_row buffers. */
+        CHECK_MEM_ERROR(pbi->mt_yabove_row, vpx_malloc(sizeof(unsigned char *) * pc->mb_rows));
+        for (i=0; i< pc->mb_rows; i++)
+            CHECK_MEM_ERROR(pbi->mt_yabove_row[i], vpx_memalign(16,sizeof(unsigned char) * (width + (VP8BORDERINPIXELS<<1))));
+
+        CHECK_MEM_ERROR(pbi->mt_uabove_row, vpx_malloc(sizeof(unsigned char *) * pc->mb_rows));
+        for (i=0; i< pc->mb_rows; i++)
+            CHECK_MEM_ERROR(pbi->mt_uabove_row[i], vpx_memalign(16,sizeof(unsigned char) * (uv_width + VP8BORDERINPIXELS)));
+
+        CHECK_MEM_ERROR(pbi->mt_vabove_row, vpx_malloc(sizeof(unsigned char *) * pc->mb_rows));
+        for (i=0; i< pc->mb_rows; i++)
+            CHECK_MEM_ERROR(pbi->mt_vabove_row[i], vpx_memalign(16,sizeof(unsigned char) * (uv_width + VP8BORDERINPIXELS)));
+
+        /* Allocate memory for left_col buffers. */
+        CHECK_MEM_ERROR(pbi->mt_yleft_col, vpx_malloc(sizeof(unsigned char *) * pc->mb_rows));
+        for (i=0; i< pc->mb_rows; i++)
+            CHECK_MEM_ERROR(pbi->mt_yleft_col[i], vpx_calloc(sizeof(unsigned char) * 16, 1));
+
+        CHECK_MEM_ERROR(pbi->mt_uleft_col, vpx_malloc(sizeof(unsigned char *) * pc->mb_rows));
+        for (i=0; i< pc->mb_rows; i++)
+            CHECK_MEM_ERROR(pbi->mt_uleft_col[i], vpx_calloc(sizeof(unsigned char) * 8, 1));
+
+        CHECK_MEM_ERROR(pbi->mt_vleft_col, vpx_malloc(sizeof(unsigned char *) * pc->mb_rows));
+        for (i=0; i< pc->mb_rows; i++)
+            CHECK_MEM_ERROR(pbi->mt_vleft_col[i], vpx_calloc(sizeof(unsigned char) * 8, 1));
+    }
+}
+
+
+void vp8_decoder_remove_threads(VP8D_COMP *pbi)
+{
+    /* shutdown MB Decoding thread; */
+    if (pbi->b_multithreaded_rd)
+    {
+        int i;
+
+        pbi->b_multithreaded_rd = 0;
+
+        /* allow all threads to exit */
+        for (i = 0; i < pbi->allocated_decoding_thread_count; i++)
+        {
+            sem_post(&pbi->h_event_start_decoding[i]);
+            pthread_join(pbi->h_decoding_thread[i], NULL);
+        }
+
+        for (i = 0; i < pbi->allocated_decoding_thread_count; i++)
+        {
+            sem_destroy(&pbi->h_event_start_decoding[i]);
+        }
+
+        sem_destroy(&pbi->h_event_end_decoding);
+
+            vpx_free(pbi->h_decoding_thread);
+            pbi->h_decoding_thread = NULL;
+
+            vpx_free(pbi->h_event_start_decoding);
+            pbi->h_event_start_decoding = NULL;
+
+            vpx_free(pbi->mb_row_di);
+            pbi->mb_row_di = NULL ;
+
+            vpx_free(pbi->de_thread_data);
+            pbi->de_thread_data = NULL;
+    }
+}
+
+void vp8mt_decode_mb_rows( VP8D_COMP *pbi, MACROBLOCKD *xd)
+{
+    VP8_COMMON *pc = &pbi->common;
+    int i;
+
+    int filter_level = pc->filter_level;
+
+    if (filter_level)
+    {
+        /* Set above_row buffer to 127 for decoding first MB row */
+        vpx_memset(pbi->mt_yabove_row[0] + VP8BORDERINPIXELS-1, 127, pc->yv12_fb[pc->lst_fb_idx].y_width + 5);
+        vpx_memset(pbi->mt_uabove_row[0] + (VP8BORDERINPIXELS>>1)-1, 127, (pc->yv12_fb[pc->lst_fb_idx].y_width>>1) +5);
+        vpx_memset(pbi->mt_vabove_row[0] + (VP8BORDERINPIXELS>>1)-1, 127, (pc->yv12_fb[pc->lst_fb_idx].y_width>>1) +5);
+
+        for (i=1; i<pc->mb_rows; i++)
+        {
+            vpx_memset(pbi->mt_yabove_row[i] + VP8BORDERINPIXELS-1, (unsigned char)129, 1);
+            vpx_memset(pbi->mt_uabove_row[i] + (VP8BORDERINPIXELS>>1)-1, (unsigned char)129, 1);
+            vpx_memset(pbi->mt_vabove_row[i] + (VP8BORDERINPIXELS>>1)-1, (unsigned char)129, 1);
+        }
+
+        /* Set left_col to 129 initially */
+        for (i=0; i<pc->mb_rows; i++)
+        {
+            vpx_memset(pbi->mt_yleft_col[i], (unsigned char)129, 16);
+            vpx_memset(pbi->mt_uleft_col[i], (unsigned char)129, 8);
+            vpx_memset(pbi->mt_vleft_col[i], (unsigned char)129, 8);
+        }
+
+        /* Initialize the loop filter for this frame. */
+        vp8_loop_filter_frame_init(pc, &pbi->mb, filter_level);
+    }
+
+    setup_decoding_thread_data(pbi, xd, pbi->mb_row_di, pbi->decoding_thread_count);
+
+    for (i = 0; i < pbi->decoding_thread_count; i++)
+        sem_post(&pbi->h_event_start_decoding[i]);
+
+    decode_mb_rows(pbi, xd, 0, init_current_bc);
+
+    sem_wait(&pbi->h_event_end_decoding);   /* add back for each frame */
+}
diff --git a/vp8/decoder/treereader.h b/vp8/decoder/treereader.h
new file mode 100644 (file)
index 0000000..238ff85
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef tree_reader_h
+#define tree_reader_h 1
+
+#include "vp8/common/treecoder.h"
+
+#include "dboolhuff.h"
+
+typedef BOOL_DECODER vp8_reader;
+
+#define vp8_read vp8dx_decode_bool
+#define vp8_read_literal vp8_decode_value
+#define vp8_read_bit( R) vp8_read( R, vp8_prob_half)
+
+
+/* Intent of tree data structure is to make decoding trivial. */
+
+static int vp8_treed_read(
+    vp8_reader *const r,        /* !!! must return a 0 or 1 !!! */
+    vp8_tree t,
+    const vp8_prob *const p
+)
+{
+    register vp8_tree_index i = 0;
+
+    while ((i = t[ i + vp8_read(r, p[i>>1])]) > 0) ;
+
+    return -i;
+}
+
+#endif /* tree_reader_h */
diff --git a/vp8/encoder/arm/armv5te/boolhuff_armv5te.asm b/vp8/encoder/arm/armv5te/boolhuff_armv5te.asm
new file mode 100644 (file)
index 0000000..a644a00
--- /dev/null
@@ -0,0 +1,310 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT |vp8_start_encode|
+    EXPORT |vp8_encode_bool|
+    EXPORT |vp8_stop_encode|
+    EXPORT |vp8_encode_value|
+    IMPORT |vp8_validate_buffer_arm|
+
+    INCLUDE asm_enc_offsets.asm
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA    |.text|, CODE, READONLY
+
+    ; macro for validating write buffer position
+    ; needs vp8_writer in r0
+    ; start shall not be in r1
+    MACRO
+    VALIDATE_POS $start, $pos
+    push {r0-r3, r12, lr}        ; rest of regs are preserved by subroutine call
+    ldr  r2, [r0, #vp8_writer_buffer_end]
+    ldr  r3, [r0, #vp8_writer_error]
+    mov  r1, $pos
+    mov  r0, $start
+    bl   vp8_validate_buffer_arm
+    pop  {r0-r3, r12, lr}
+    MEND
+
+; r0 BOOL_CODER *br
+; r1 unsigned char *source
+; r2 unsigned char *source_end
+|vp8_start_encode| PROC
+    str     r2,  [r0, #vp8_writer_buffer_end]
+    mov     r12, #0
+    mov     r3,  #255
+    mvn     r2,  #23
+    str     r12, [r0, #vp8_writer_lowvalue]
+    str     r3,  [r0, #vp8_writer_range]
+    str     r2,  [r0, #vp8_writer_count]
+    str     r12, [r0, #vp8_writer_pos]
+    str     r1,  [r0, #vp8_writer_buffer]
+    bx      lr
+    ENDP
+
+; r0 BOOL_CODER *br
+; r1 int bit
+; r2 int probability
+|vp8_encode_bool| PROC
+    push    {r4-r10, lr}
+
+    mov     r4, r2
+
+    ldr     r2, [r0, #vp8_writer_lowvalue]
+    ldr     r5, [r0, #vp8_writer_range]
+    ldr     r3, [r0, #vp8_writer_count]
+
+    sub     r7, r5, #1                  ; range-1
+
+    cmp     r1, #0
+    mul     r6, r4, r7                  ; ((range-1) * probability)
+
+    mov     r7, #1
+    add     r4, r7, r6, lsr #8          ; 1 + (((range-1) * probability) >> 8)
+
+    addne   r2, r2, r4                  ; if  (bit) lowvalue += split
+    subne   r4, r5, r4                  ; if  (bit) range = range-split
+
+    ; Counting the leading zeros is used to normalize range.
+    clz     r6, r4
+    sub     r6, r6, #24                 ; shift
+
+    ; Flag is set on the sum of count.  This flag is used later
+    ; to determine if count >= 0
+    adds    r3, r3, r6                  ; count += shift
+    lsl     r5, r4, r6                  ; range <<= shift
+    bmi     token_count_lt_zero         ; if(count >= 0)
+
+    sub     r6, r6, r3                  ; offset = shift - count
+    sub     r4, r6, #1                  ; offset-1
+    lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
+    bpl     token_high_bit_not_set
+
+    ldr     r4, [r0, #vp8_writer_pos]   ; x
+    sub     r4, r4, #1                  ; x = w->pos-1
+    b       token_zero_while_start
+token_zero_while_loop
+    mov     r9, #0
+    strb    r9, [r7, r4]                ; w->buffer[x] =(unsigned char)0
+    sub     r4, r4, #1                  ; x--
+token_zero_while_start
+    cmp     r4, #0
+    ldrge   r7, [r0, #vp8_writer_buffer]
+    ldrb    r1, [r7, r4]
+    cmpge   r1, #0xff
+    beq     token_zero_while_loop
+
+    ldr     r7, [r0, #vp8_writer_buffer]
+    ldrb    r9, [r7, r4]                ; w->buffer[x]
+    add     r9, r9, #1
+    strb    r9, [r7, r4]                ; w->buffer[x] + 1
+token_high_bit_not_set
+    rsb     r4, r6, #24                 ; 24-offset
+    ldr     r9, [r0, #vp8_writer_buffer]
+    lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
+    ldr     r4, [r0, #vp8_writer_pos]   ; w->pos
+    lsl     r2, r2, r6                  ; lowvalue <<= offset
+    mov     r6, r3                      ; shift = count
+    add     r1, r4, #1                  ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r1, [r0, #vp8_writer_pos]
+    sub     r3, r3, #8                  ; count -= 8
+
+    VALIDATE_POS r9, r1                 ; validate_buffer at pos
+
+    strb    r7, [r9, r4]                ; w->buffer[w->pos++]
+
+token_count_lt_zero
+    lsl     r2, r2, r6                  ; lowvalue <<= shift
+
+    str     r2, [r0, #vp8_writer_lowvalue]
+    str     r5, [r0, #vp8_writer_range]
+    str     r3, [r0, #vp8_writer_count]
+    pop     {r4-r10, pc}
+    ENDP
+
+; r0 BOOL_CODER *br
+|vp8_stop_encode| PROC
+    push    {r4-r10, lr}
+
+    ldr     r2, [r0, #vp8_writer_lowvalue]
+    ldr     r5, [r0, #vp8_writer_range]
+    ldr     r3, [r0, #vp8_writer_count]
+
+    mov     r10, #32
+
+stop_encode_loop
+    sub     r7, r5, #1                  ; range-1
+
+    mov     r4, r7, lsl #7              ; ((range-1) * 128)
+
+    mov     r7, #1
+    add     r4, r7, r4, lsr #8          ; 1 + (((range-1) * 128) >> 8)
+
+    ; Counting the leading zeros is used to normalize range.
+    clz     r6, r4
+    sub     r6, r6, #24                 ; shift
+
+    ; Flag is set on the sum of count.  This flag is used later
+    ; to determine if count >= 0
+    adds    r3, r3, r6                  ; count += shift
+    lsl     r5, r4, r6                  ; range <<= shift
+    bmi     token_count_lt_zero_se      ; if(count >= 0)
+
+    sub     r6, r6, r3                  ; offset = shift - count
+    sub     r4, r6, #1                  ; offset-1
+    lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
+    bpl     token_high_bit_not_set_se
+
+    ldr     r4, [r0, #vp8_writer_pos]   ; x
+    sub     r4, r4, #1                  ; x = w->pos-1
+    b       token_zero_while_start_se
+token_zero_while_loop_se
+    mov     r9, #0
+    strb    r9, [r7, r4]                ; w->buffer[x] =(unsigned char)0
+    sub     r4, r4, #1                  ; x--
+token_zero_while_start_se
+    cmp     r4, #0
+    ldrge   r7, [r0, #vp8_writer_buffer]
+    ldrb    r1, [r7, r4]
+    cmpge   r1, #0xff
+    beq     token_zero_while_loop_se
+
+    ldr     r7, [r0, #vp8_writer_buffer]
+    ldrb    r9, [r7, r4]                ; w->buffer[x]
+    add     r9, r9, #1
+    strb    r9, [r7, r4]                ; w->buffer[x] + 1
+token_high_bit_not_set_se
+    rsb     r4, r6, #24                 ; 24-offset
+    ldr     r9, [r0, #vp8_writer_buffer]
+    lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
+    ldr     r4, [r0, #vp8_writer_pos]   ; w->pos
+    lsl     r2, r2, r6                  ; lowvalue <<= offset
+    mov     r6, r3                      ; shift = count
+    add     r1, r4, #1                  ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r1, [r0, #vp8_writer_pos]
+    sub     r3, r3, #8                  ; count -= 8
+
+    VALIDATE_POS r9, r1                 ; validate_buffer at pos
+
+    strb    r7, [r9, r4]                ; w->buffer[w->pos++]
+
+token_count_lt_zero_se
+    lsl     r2, r2, r6                  ; lowvalue <<= shift
+
+    subs    r10, r10, #1
+    bne     stop_encode_loop
+
+    str     r2, [r0, #vp8_writer_lowvalue]
+    str     r5, [r0, #vp8_writer_range]
+    str     r3, [r0, #vp8_writer_count]
+    pop     {r4-r10, pc}
+
+    ENDP
+
+; r0 BOOL_CODER *br
+; r1 int data
+; r2 int bits
+|vp8_encode_value| PROC
+    push    {r4-r12, lr}
+
+    mov     r10, r2
+
+    ldr     r2, [r0, #vp8_writer_lowvalue]
+    ldr     r5, [r0, #vp8_writer_range]
+    ldr     r3, [r0, #vp8_writer_count]
+
+    rsb     r4, r10, #32                 ; 32-n
+
+    ; v is kept in r1 during the token pack loop
+    lsl     r1, r1, r4                  ; r1 = v << 32 - n
+
+encode_value_loop
+    sub     r7, r5, #1                  ; range-1
+
+    ; Decisions are made based on the bit value shifted
+    ; off of v, so set a flag here based on this.
+    ; This value is refered to as "bb"
+    lsls    r1, r1, #1                  ; bit = v >> n
+    mov     r4, r7, lsl #7              ; ((range-1) * 128)
+
+    mov     r7, #1
+    add     r4, r7, r4, lsr #8          ; 1 + (((range-1) * 128) >> 8)
+
+    addcs   r2, r2, r4                  ; if  (bit) lowvalue += split
+    subcs   r4, r5, r4                  ; if  (bit) range = range-split
+
+    ; Counting the leading zeros is used to normalize range.
+    clz     r6, r4
+    sub     r6, r6, #24                 ; shift
+
+    ; Flag is set on the sum of count.  This flag is used later
+    ; to determine if count >= 0
+    adds    r3, r3, r6                  ; count += shift
+    lsl     r5, r4, r6                  ; range <<= shift
+    bmi     token_count_lt_zero_ev      ; if(count >= 0)
+
+    sub     r6, r6, r3                  ; offset = shift - count
+    sub     r4, r6, #1                  ; offset-1
+    lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
+    bpl     token_high_bit_not_set_ev
+
+    ldr     r4, [r0, #vp8_writer_pos]   ; x
+    sub     r4, r4, #1                  ; x = w->pos-1
+    b       token_zero_while_start_ev
+token_zero_while_loop_ev
+    mov     r9, #0
+    strb    r9, [r7, r4]                ; w->buffer[x] =(unsigned char)0
+    sub     r4, r4, #1                  ; x--
+token_zero_while_start_ev
+    cmp     r4, #0
+    ldrge   r7, [r0, #vp8_writer_buffer]
+    ldrb    r11, [r7, r4]
+    cmpge   r11, #0xff
+    beq     token_zero_while_loop_ev
+
+    ldr     r7, [r0, #vp8_writer_buffer]
+    ldrb    r9, [r7, r4]                ; w->buffer[x]
+    add     r9, r9, #1
+    strb    r9, [r7, r4]                ; w->buffer[x] + 1
+token_high_bit_not_set_ev
+    rsb     r4, r6, #24                 ; 24-offset
+    ldr     r9, [r0, #vp8_writer_buffer]
+    lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
+    ldr     r4, [r0, #vp8_writer_pos]   ; w->pos
+    lsl     r2, r2, r6                  ; lowvalue <<= offset
+    mov     r6, r3                      ; shift = count
+    add     r11, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r11, [r0, #vp8_writer_pos]
+    sub     r3, r3, #8                  ; count -= 8
+
+    VALIDATE_POS r9, r11                ; validate_buffer at pos
+
+    strb    r7, [r9, r4]                ; w->buffer[w->pos++]
+
+token_count_lt_zero_ev
+    lsl     r2, r2, r6                  ; lowvalue <<= shift
+
+    subs    r10, r10, #1
+    bne     encode_value_loop
+
+    str     r2, [r0, #vp8_writer_lowvalue]
+    str     r5, [r0, #vp8_writer_range]
+    str     r3, [r0, #vp8_writer_count]
+    pop     {r4-r12, pc}
+    ENDP
+
+    END
diff --git a/vp8/encoder/arm/armv5te/vp8_packtokens_armv5.asm b/vp8/encoder/arm/armv5te/vp8_packtokens_armv5.asm
new file mode 100644 (file)
index 0000000..a1cd467
--- /dev/null
@@ -0,0 +1,317 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT |vp8cx_pack_tokens_armv5|
+    IMPORT |vp8_validate_buffer_arm|
+
+    INCLUDE asm_enc_offsets.asm
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA    |.text|, CODE, READONLY
+
+
+    ; macro for validating write buffer position
+    ; needs vp8_writer in r0
+    ; start shall not be in r1
+    MACRO
+    VALIDATE_POS $start, $pos
+    push {r0-r3, r12, lr}        ; rest of regs are preserved by subroutine call
+    ldr  r2, [r0, #vp8_writer_buffer_end]
+    ldr  r3, [r0, #vp8_writer_error]
+    mov  r1, $pos
+    mov  r0, $start
+    bl   vp8_validate_buffer_arm
+    pop  {r0-r3, r12, lr}
+    MEND
+
+
+; r0 vp8_writer *w
+; r1 const TOKENEXTRA *p
+; r2 int xcount
+; r3 vp8_coef_encodings
+; s0 vp8_extra_bits
+; s1 vp8_coef_tree
+|vp8cx_pack_tokens_armv5| PROC
+    push    {r4-r12, lr}
+    sub     sp, sp, #16
+
+    ; Add size of xcount * sizeof (TOKENEXTRA) to get stop
+    ;  sizeof (TOKENEXTRA) is 8
+    add     r2, r1, r2, lsl #3          ; stop = p + xcount*sizeof(TOKENEXTRA)
+    str     r2, [sp, #0]
+    str     r3, [sp, #8]                ; save vp8_coef_encodings
+    ldr     r2, [r0, #vp8_writer_lowvalue]
+    ldr     r5, [r0, #vp8_writer_range]
+    ldr     r3, [r0, #vp8_writer_count]
+    b       check_p_lt_stop
+
+while_p_lt_stop
+    ldrb    r6, [r1, #tokenextra_token] ; t
+    ldr     r4, [sp, #8]                ; vp8_coef_encodings
+    mov     lr, #0
+    add     r4, r4, r6, lsl #3          ; a = vp8_coef_encodings + t
+    ldr     r9, [r1, #tokenextra_context_tree]   ; pp
+
+    ldrb    r7, [r1, #tokenextra_skip_eob_node]
+
+    ldr     r6, [r4, #vp8_token_value]  ; v
+    ldr     r8, [r4, #vp8_token_len]    ; n
+
+    ; vp8 specific skip_eob_node
+    cmp     r7, #0
+    movne   lr, #2                      ; i = 2
+    subne   r8, r8, #1                  ; --n
+
+    rsb     r4, r8, #32                 ; 32-n
+    ldr     r10, [sp, #60]              ; vp8_coef_tree
+
+    ; v is kept in r12 during the token pack loop
+    lsl     r12, r6, r4                ; r12 = v << 32 - n
+
+; loop start
+token_loop
+    ldrb    r4, [r9, lr, asr #1]        ; pp [i>>1]
+    sub     r7, r5, #1                  ; range-1
+
+    ; Decisions are made based on the bit value shifted
+    ; off of v, so set a flag here based on this.
+    ; This value is refered to as "bb"
+    lsls    r12, r12, #1                ; bb = v >> n
+    mul     r6, r4, r7                  ; ((range-1) * pp[i>>1]))
+
+    ; bb can only be 0 or 1.  So only execute this statement
+    ; if bb == 1, otherwise it will act like i + 0
+    addcs   lr, lr, #1                  ; i + bb
+
+    mov     r7, #1
+    ldrsb   lr, [r10, lr]               ; i = vp8_coef_tree[i+bb]
+    add     r4, r7, r6, lsr #8          ; 1 + (((range-1) * pp[i>>1]) >> 8)
+
+    addcs   r2, r2, r4                  ; if  (bb) lowvalue += split
+    subcs   r4, r5, r4                  ; if  (bb) range = range-split
+
+    ; Counting the leading zeros is used to normalize range.
+    clz     r6, r4
+    sub     r6, r6, #24                 ; shift
+
+    ; Flag is set on the sum of count.  This flag is used later
+    ; to determine if count >= 0
+    adds    r3, r3, r6                  ; count += shift
+    lsl     r5, r4, r6                  ; range <<= shift
+    bmi     token_count_lt_zero         ; if(count >= 0)
+
+    sub     r6, r6, r3                  ; offset = shift - count
+    sub     r4, r6, #1                  ; offset-1
+    lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
+    bpl     token_high_bit_not_set
+
+    ldr     r4, [r0, #vp8_writer_pos]   ; x
+    sub     r4, r4, #1                  ; x = w->pos-1
+    b       token_zero_while_start
+token_zero_while_loop
+    mov     r10, #0
+    strb    r10, [r7, r4]               ; w->buffer[x] =(unsigned char)0
+    sub     r4, r4, #1                  ; x--
+token_zero_while_start
+    cmp     r4, #0
+    ldrge   r7, [r0, #vp8_writer_buffer]
+    ldrb    r11, [r7, r4]
+    cmpge   r11, #0xff
+    beq     token_zero_while_loop
+
+    ldr     r7, [r0, #vp8_writer_buffer]
+    ldrb    r10, [r7, r4]               ; w->buffer[x]
+    add     r10, r10, #1
+    strb    r10, [r7, r4]               ; w->buffer[x] + 1
+token_high_bit_not_set
+    rsb     r4, r6, #24                 ; 24-offset
+    ldr     r10, [r0, #vp8_writer_buffer]
+    lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
+    ldr     r4, [r0, #vp8_writer_pos]   ; w->pos
+    lsl     r2, r2, r6                  ; lowvalue <<= offset
+    mov     r6, r3                      ; shift = count
+    add     r11, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r11, [r0, #vp8_writer_pos]
+    sub     r3, r3, #8                  ; count -= 8
+
+    VALIDATE_POS r10, r11               ; validate_buffer at pos
+
+    strb    r7, [r10, r4]               ; w->buffer[w->pos++]
+
+    ; r10 is used earlier in the loop, but r10 is used as
+    ; temp variable here.  So after r10 is used, reload
+    ; vp8_coef_tree_dcd into r10
+    ldr     r10, [sp, #60]              ; vp8_coef_tree
+
+token_count_lt_zero
+    lsl     r2, r2, r6                  ; lowvalue <<= shift
+
+    subs    r8, r8, #1                  ; --n
+    bne     token_loop
+
+    ldrb    r6, [r1, #tokenextra_token] ; t
+    ldr     r7, [sp, #56]               ; vp8_extra_bits
+    ; Add t * sizeof (vp8_extra_bit_struct) to get the desired
+    ;  element.  Here vp8_extra_bit_struct == 16
+    add     r12, r7, r6, lsl #4         ; b = vp8_extra_bits + t
+
+    ldr     r4, [r12, #vp8_extra_bit_struct_base_val]
+    cmp     r4, #0
+    beq     skip_extra_bits
+
+;   if( b->base_val)
+    ldr     r8, [r12, #vp8_extra_bit_struct_len] ; L
+    ldrsh   lr, [r1, #tokenextra_extra] ; e = p->Extra
+    cmp     r8, #0                      ; if( L)
+    beq     no_extra_bits
+
+    ldr     r9, [r12, #vp8_extra_bit_struct_prob]
+    asr     r7, lr, #1                  ; v=e>>1
+
+    ldr     r10, [r12, #vp8_extra_bit_struct_tree]
+    str     r10, [sp, #4]               ; b->tree
+
+    rsb     r4, r8, #32
+    lsl     r12, r7, r4
+
+    mov     lr, #0                      ; i = 0
+
+extra_bits_loop
+    ldrb    r4, [r9, lr, asr #1]            ; pp[i>>1]
+    sub     r7, r5, #1                  ; range-1
+    lsls    r12, r12, #1                ; v >> n
+    mul     r6, r4, r7                  ; (range-1) * pp[i>>1]
+    addcs   lr, lr, #1                  ; i + bb
+
+    mov     r7, #1
+    ldrsb   lr, [r10, lr]               ; i = b->tree[i+bb]
+    add     r4, r7, r6, lsr #8          ; split = 1 +  (((range-1) * pp[i>>1]) >> 8)
+
+    addcs   r2, r2, r4                  ; if  (bb) lowvalue += split
+    subcs   r4, r5, r4                  ; if  (bb) range = range-split
+
+    clz     r6, r4
+    sub     r6, r6, #24
+
+    adds    r3, r3, r6                  ; count += shift
+    lsl     r5, r4, r6                  ; range <<= shift
+    bmi     extra_count_lt_zero         ; if(count >= 0)
+
+    sub     r6, r6, r3                  ; offset= shift - count
+    sub     r4, r6, #1                  ; offset-1
+    lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
+    bpl     extra_high_bit_not_set
+
+    ldr     r4, [r0, #vp8_writer_pos]   ; x
+    sub     r4, r4, #1                  ; x = w->pos - 1
+    b       extra_zero_while_start
+extra_zero_while_loop
+    mov     r10, #0
+    strb    r10, [r7, r4]               ; w->buffer[x] =(unsigned char)0
+    sub     r4, r4, #1                  ; x--
+extra_zero_while_start
+    cmp     r4, #0
+    ldrge   r7, [r0, #vp8_writer_buffer]
+    ldrb    r11, [r7, r4]
+    cmpge   r11, #0xff
+    beq     extra_zero_while_loop
+
+    ldr     r7, [r0, #vp8_writer_buffer]
+    ldrb    r10, [r7, r4]
+    add     r10, r10, #1
+    strb    r10, [r7, r4]
+extra_high_bit_not_set
+    rsb     r4, r6, #24                 ; 24-offset
+    ldr     r10, [r0, #vp8_writer_buffer]
+    lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
+    ldr     r4, [r0, #vp8_writer_pos]
+    lsl     r2, r2, r6                  ; lowvalue <<= offset
+    mov     r6, r3                      ; shift = count
+    add     r11, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r11, [r0, #vp8_writer_pos]
+    sub     r3, r3, #8                  ; count -= 8
+
+    VALIDATE_POS r10, r11               ; validate_buffer at pos
+
+    strb    r7, [r10, r4]               ; w->buffer[w->pos++]=(lowvalue >> (24-offset))
+    ldr     r10, [sp, #4]               ; b->tree
+extra_count_lt_zero
+    lsl     r2, r2, r6
+
+    subs    r8, r8, #1                  ; --n
+    bne     extra_bits_loop             ; while (n)
+
+no_extra_bits
+    ldr     lr, [r1, #4]                ; e = p->Extra
+    add     r4, r5, #1                  ; range + 1
+    tst     lr, #1
+    lsr     r4, r4, #1                  ; split = (range + 1) >> 1
+    addne   r2, r2, r4                  ; lowvalue += split
+    subne   r4, r5, r4                  ; range = range-split
+    tst     r2, #0x80000000             ; lowvalue & 0x80000000
+    lsl     r5, r4, #1                  ; range <<= 1
+    beq     end_high_bit_not_set
+
+    ldr     r4, [r0, #vp8_writer_pos]
+    mov     r7, #0
+    sub     r4, r4, #1
+    b       end_zero_while_start
+end_zero_while_loop
+    strb    r7, [r6, r4]
+    sub     r4, r4, #1                  ; x--
+end_zero_while_start
+    cmp     r4, #0
+    ldrge   r6, [r0, #vp8_writer_buffer]
+    ldrb    r12, [r6, r4]
+    cmpge   r12, #0xff
+    beq     end_zero_while_loop
+
+    ldr     r6, [r0, #vp8_writer_buffer]
+    ldrb    r7, [r6, r4]
+    add     r7, r7, #1
+    strb    r7, [r6, r4]
+end_high_bit_not_set
+    adds    r3, r3, #1                  ; ++count
+    lsl     r2, r2, #1                  ; lowvalue  <<= 1
+    bne     end_count_zero
+
+    ldr     r4, [r0, #vp8_writer_pos]
+    mvn     r3, #7
+    ldr     r7, [r0, #vp8_writer_buffer]
+    lsr     r6, r2, #24                 ; lowvalue >> 24
+    add     r12, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r12, [r0, #vp8_writer_pos]
+
+    VALIDATE_POS r7, r12               ; validate_buffer at pos
+
+    strb    r6, [r7, r4]
+end_count_zero
+skip_extra_bits
+    add     r1, r1, #TOKENEXTRA_SZ      ; ++p
+check_p_lt_stop
+    ldr     r4, [sp, #0]                ; stop
+    cmp     r1, r4                      ; while( p < stop)
+    bcc     while_p_lt_stop
+
+    str     r2, [r0, #vp8_writer_lowvalue]
+    str     r5, [r0, #vp8_writer_range]
+    str     r3, [r0, #vp8_writer_count]
+    add     sp, sp, #16
+    pop     {r4-r12, pc}
+    ENDP
+
+    END
diff --git a/vp8/encoder/arm/armv5te/vp8_packtokens_mbrow_armv5.asm b/vp8/encoder/arm/armv5te/vp8_packtokens_mbrow_armv5.asm
new file mode 100644 (file)
index 0000000..1fa5e6c
--- /dev/null
@@ -0,0 +1,352 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT |vp8cx_pack_mb_row_tokens_armv5|
+    IMPORT |vp8_validate_buffer_arm|
+
+    INCLUDE asm_enc_offsets.asm
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA    |.text|, CODE, READONLY
+
+
+    ; macro for validating write buffer position
+    ; needs vp8_writer in r0
+    ; start shall not be in r1
+    MACRO
+    VALIDATE_POS $start, $pos
+    push {r0-r3, r12, lr}        ; rest of regs are preserved by subroutine call
+    ldr  r2, [r0, #vp8_writer_buffer_end]
+    ldr  r3, [r0, #vp8_writer_error]
+    mov  r1, $pos
+    mov  r0, $start
+    bl   vp8_validate_buffer_arm
+    pop  {r0-r3, r12, lr}
+    MEND
+
+; r0 VP8_COMP *cpi
+; r1 vp8_writer *w
+; r2 vp8_coef_encodings
+; r3 vp8_extra_bits
+; s0 vp8_coef_tree
+
+|vp8cx_pack_mb_row_tokens_armv5| PROC
+    push    {r4-r12, lr}
+    sub     sp, sp, #24
+
+    ; Compute address of cpi->common.mb_rows
+    ldr     r4, _VP8_COMP_common_
+    ldr     r6, _VP8_COMMON_MBrows_
+    add     r4, r0, r4
+
+    ldr     r5, [r4, r6]                ; load up mb_rows
+
+    str     r2, [sp, #20]               ; save vp8_coef_encodings
+    str     r5, [sp, #12]               ; save mb_rows
+    str     r3, [sp, #8]                ; save vp8_extra_bits
+
+    ldr     r4, _VP8_COMP_tplist_
+    add     r4, r0, r4
+    ldr     r7, [r4, #0]                ; dereference cpi->tp_list
+
+    mov     r0, r1                      ; keep same as other loops
+
+    ldr     r2, [r0, #vp8_writer_lowvalue]
+    ldr     r5, [r0, #vp8_writer_range]
+    ldr     r3, [r0, #vp8_writer_count]
+
+mb_row_loop
+
+    ldr     r1, [r7, #tokenlist_start]
+    ldr     r9, [r7, #tokenlist_stop]
+    str     r9, [sp, #0]                ; save stop for later comparison
+    str     r7, [sp, #16]               ; tokenlist address for next time
+
+    b       check_p_lt_stop
+
+    ; actuall work gets done here!
+
+while_p_lt_stop
+    ldrb    r6, [r1, #tokenextra_token] ; t
+    ldr     r4, [sp, #20]               ; vp8_coef_encodings
+    mov     lr, #0
+    add     r4, r4, r6, lsl #3          ; a = vp8_coef_encodings + t
+    ldr     r9, [r1, #tokenextra_context_tree]   ; pp
+
+    ldrb    r7, [r1, #tokenextra_skip_eob_node]
+
+    ldr     r6, [r4, #vp8_token_value]  ; v
+    ldr     r8, [r4, #vp8_token_len]    ; n
+
+    ; vp8 specific skip_eob_node
+    cmp     r7, #0
+    movne   lr, #2                      ; i = 2
+    subne   r8, r8, #1                  ; --n
+
+    rsb     r4, r8, #32                 ; 32-n
+    ldr     r10, [sp, #64]              ; vp8_coef_tree
+
+    ; v is kept in r12 during the token pack loop
+    lsl     r12, r6, r4                 ; r12 = v << 32 - n
+
+; loop start
+token_loop
+    ldrb    r4, [r9, lr, asr #1]        ; pp [i>>1]
+    sub     r7, r5, #1                  ; range-1
+
+    ; Decisions are made based on the bit value shifted
+    ; off of v, so set a flag here based on this.
+    ; This value is refered to as "bb"
+    lsls    r12, r12, #1                ; bb = v >> n
+    mul     r6, r4, r7                  ; ((range-1) * pp[i>>1]))
+
+    ; bb can only be 0 or 1.  So only execute this statement
+    ; if bb == 1, otherwise it will act like i + 0
+    addcs   lr, lr, #1                  ; i + bb
+
+    mov     r7, #1
+    ldrsb   lr, [r10, lr]               ; i = vp8_coef_tree[i+bb]
+    add     r4, r7, r6, lsr #8          ; 1 + (((range-1) * pp[i>>1]) >> 8)
+
+    addcs   r2, r2, r4                  ; if  (bb) lowvalue += split
+    subcs   r4, r5, r4                  ; if  (bb) range = range-split
+
+    ; Counting the leading zeros is used to normalize range.
+    clz     r6, r4
+    sub     r6, r6, #24                 ; shift
+
+    ; Flag is set on the sum of count.  This flag is used later
+    ; to determine if count >= 0
+    adds    r3, r3, r6                  ; count += shift
+    lsl     r5, r4, r6                  ; range <<= shift
+    bmi     token_count_lt_zero         ; if(count >= 0)
+
+    sub     r6, r6, r3                  ; offset = shift - count
+    sub     r4, r6, #1                  ; offset-1
+    lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
+    bpl     token_high_bit_not_set
+
+    ldr     r4, [r0, #vp8_writer_pos]   ; x
+    sub     r4, r4, #1                  ; x = w->pos-1
+    b       token_zero_while_start
+token_zero_while_loop
+    mov     r10, #0
+    strb    r10, [r7, r4]               ; w->buffer[x] =(unsigned char)0
+    sub     r4, r4, #1                  ; x--
+token_zero_while_start
+    cmp     r4, #0
+    ldrge   r7, [r0, #vp8_writer_buffer]
+    ldrb    r11, [r7, r4]
+    cmpge   r11, #0xff
+    beq     token_zero_while_loop
+
+    ldr     r7, [r0, #vp8_writer_buffer]
+    ldrb    r10, [r7, r4]               ; w->buffer[x]
+    add     r10, r10, #1
+    strb    r10, [r7, r4]               ; w->buffer[x] + 1
+token_high_bit_not_set
+    rsb     r4, r6, #24                 ; 24-offset
+    ldr     r10, [r0, #vp8_writer_buffer]
+    lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
+    ldr     r4, [r0, #vp8_writer_pos]   ; w->pos
+    lsl     r2, r2, r6                  ; lowvalue <<= offset
+    mov     r6, r3                      ; shift = count
+    add     r11, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r11, [r0, #vp8_writer_pos]
+    sub     r3, r3, #8                  ; count -= 8
+
+    VALIDATE_POS r10, r11               ; validate_buffer at pos
+
+    strb    r7, [r10, r4]               ; w->buffer[w->pos++]
+
+    ; r10 is used earlier in the loop, but r10 is used as
+    ; temp variable here.  So after r10 is used, reload
+    ; vp8_coef_tree_dcd into r10
+    ldr     r10, [sp, #64]              ; vp8_coef_tree
+
+token_count_lt_zero
+    lsl     r2, r2, r6                  ; lowvalue <<= shift
+
+    subs    r8, r8, #1                  ; --n
+    bne     token_loop
+
+    ldrb    r6, [r1, #tokenextra_token] ; t
+    ldr     r7, [sp, #8]                ; vp8_extra_bits
+    ; Add t * sizeof (vp8_extra_bit_struct) to get the desired
+    ;  element.  Here vp8_extra_bit_struct == 16
+    add     r12, r7, r6, lsl #4         ; b = vp8_extra_bits + t
+
+    ldr     r4, [r12, #vp8_extra_bit_struct_base_val]
+    cmp     r4, #0
+    beq     skip_extra_bits
+
+;   if( b->base_val)
+    ldr     r8, [r12, #vp8_extra_bit_struct_len] ; L
+    ldrsh   lr, [r1, #tokenextra_extra] ; e = p->Extra
+    cmp     r8, #0                      ; if( L)
+    beq     no_extra_bits
+
+    ldr     r9, [r12, #vp8_extra_bit_struct_prob]
+    asr     r7, lr, #1                  ; v=e>>1
+
+    ldr     r10, [r12, #vp8_extra_bit_struct_tree]
+    str     r10, [sp, #4]               ; b->tree
+
+    rsb     r4, r8, #32
+    lsl     r12, r7, r4
+
+    mov     lr, #0                      ; i = 0
+
+extra_bits_loop
+    ldrb    r4, [r9, lr, asr #1]            ; pp[i>>1]
+    sub     r7, r5, #1                  ; range-1
+    lsls    r12, r12, #1                ; v >> n
+    mul     r6, r4, r7                  ; (range-1) * pp[i>>1]
+    addcs   lr, lr, #1                  ; i + bb
+
+    mov     r7, #1
+    ldrsb   lr, [r10, lr]               ; i = b->tree[i+bb]
+    add     r4, r7, r6, lsr #8          ; split = 1 +  (((range-1) * pp[i>>1]) >> 8)
+
+    addcs   r2, r2, r4                  ; if  (bb) lowvalue += split
+    subcs   r4, r5, r4                  ; if  (bb) range = range-split
+
+    clz     r6, r4
+    sub     r6, r6, #24
+
+    adds    r3, r3, r6                  ; count += shift
+    lsl     r5, r4, r6                  ; range <<= shift
+    bmi     extra_count_lt_zero         ; if(count >= 0)
+
+    sub     r6, r6, r3                  ; offset= shift - count
+    sub     r4, r6, #1                  ; offset-1
+    lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
+    bpl     extra_high_bit_not_set
+
+    ldr     r4, [r0, #vp8_writer_pos]   ; x
+    sub     r4, r4, #1                  ; x = w->pos - 1
+    b       extra_zero_while_start
+extra_zero_while_loop
+    mov     r10, #0
+    strb    r10, [r7, r4]               ; w->buffer[x] =(unsigned char)0
+    sub     r4, r4, #1                  ; x--
+extra_zero_while_start
+    cmp     r4, #0
+    ldrge   r7, [r0, #vp8_writer_buffer]
+    ldrb    r11, [r7, r4]
+    cmpge   r11, #0xff
+    beq     extra_zero_while_loop
+
+    ldr     r7, [r0, #vp8_writer_buffer]
+    ldrb    r10, [r7, r4]
+    add     r10, r10, #1
+    strb    r10, [r7, r4]
+extra_high_bit_not_set
+    rsb     r4, r6, #24                 ; 24-offset
+    ldr     r10, [r0, #vp8_writer_buffer]
+    lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
+    ldr     r4, [r0, #vp8_writer_pos]
+    lsl     r2, r2, r6                  ; lowvalue <<= offset
+    mov     r6, r3                      ; shift = count
+    add     r11, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r11, [r0, #vp8_writer_pos]
+    sub     r3, r3, #8                  ; count -= 8
+
+    VALIDATE_POS r10, r11               ; validate_buffer at pos
+
+    strb    r7, [r10, r4]               ; w->buffer[w->pos++]=(lowvalue >> (24-offset))
+    ldr     r10, [sp, #4]               ; b->tree
+extra_count_lt_zero
+    lsl     r2, r2, r6
+
+    subs    r8, r8, #1                  ; --n
+    bne     extra_bits_loop             ; while (n)
+
+no_extra_bits
+    ldr     lr, [r1, #4]                ; e = p->Extra
+    add     r4, r5, #1                  ; range + 1
+    tst     lr, #1
+    lsr     r4, r4, #1                  ; split = (range + 1) >> 1
+    addne   r2, r2, r4                  ; lowvalue += split
+    subne   r4, r5, r4                  ; range = range-split
+    tst     r2, #0x80000000             ; lowvalue & 0x80000000
+    lsl     r5, r4, #1                  ; range <<= 1
+    beq     end_high_bit_not_set
+
+    ldr     r4, [r0, #vp8_writer_pos]
+    mov     r7, #0
+    sub     r4, r4, #1
+    b       end_zero_while_start
+end_zero_while_loop
+    strb    r7, [r6, r4]
+    sub     r4, r4, #1                  ; x--
+end_zero_while_start
+    cmp     r4, #0
+    ldrge   r6, [r0, #vp8_writer_buffer]
+    ldrb    r12, [r6, r4]
+    cmpge   r12, #0xff
+    beq     end_zero_while_loop
+
+    ldr     r6, [r0, #vp8_writer_buffer]
+    ldrb    r7, [r6, r4]
+    add     r7, r7, #1
+    strb    r7, [r6, r4]
+end_high_bit_not_set
+    adds    r3, r3, #1                  ; ++count
+    lsl     r2, r2, #1                  ; lowvalue  <<= 1
+    bne     end_count_zero
+
+    ldr     r4, [r0, #vp8_writer_pos]
+    mvn     r3, #7
+    ldr     r7, [r0, #vp8_writer_buffer]
+    lsr     r6, r2, #24                 ; lowvalue >> 24
+    add     r12, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r12, [r0, #vp8_writer_pos]
+
+    VALIDATE_POS r7, r12               ; validate_buffer at pos
+
+    strb    r6, [r7, r4]
+end_count_zero
+skip_extra_bits
+    add     r1, r1, #TOKENEXTRA_SZ      ; ++p
+check_p_lt_stop
+    ldr     r4, [sp, #0]                ; stop
+    cmp     r1, r4                      ; while( p < stop)
+    bcc     while_p_lt_stop
+
+    ldr     r6, [sp, #12]               ; mb_rows
+    ldr     r7, [sp, #16]               ; tokenlist address
+    subs    r6, r6, #1
+    add     r7, r7, #TOKENLIST_SZ       ; next element in the array
+    str     r6, [sp, #12]
+    bne     mb_row_loop
+
+    str     r2, [r0, #vp8_writer_lowvalue]
+    str     r5, [r0, #vp8_writer_range]
+    str     r3, [r0, #vp8_writer_count]
+    add     sp, sp, #24
+    pop     {r4-r12, pc}
+    ENDP
+
+_VP8_COMP_common_
+    DCD     vp8_comp_common
+_VP8_COMMON_MBrows_
+    DCD     vp8_common_mb_rows
+_VP8_COMP_tplist_
+    DCD     vp8_comp_tplist
+
+    END
diff --git a/vp8/encoder/arm/armv5te/vp8_packtokens_partitions_armv5.asm b/vp8/encoder/arm/armv5te/vp8_packtokens_partitions_armv5.asm
new file mode 100644 (file)
index 0000000..90a98fe
--- /dev/null
@@ -0,0 +1,471 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT |vp8cx_pack_tokens_into_partitions_armv5|
+    IMPORT |vp8_validate_buffer_arm|
+
+    INCLUDE asm_enc_offsets.asm
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA    |.text|, CODE, READONLY
+
+    ; macro for validating write buffer position
+    ; needs vp8_writer in r0
+    ; start shall not be in r1
+    MACRO
+    VALIDATE_POS $start, $pos
+    push {r0-r3, r12, lr}        ; rest of regs are preserved by subroutine call
+    ldr  r2, [r0, #vp8_writer_buffer_end]
+    ldr  r3, [r0, #vp8_writer_error]
+    mov  r1, $pos
+    mov  r0, $start
+    bl   vp8_validate_buffer_arm
+    pop  {r0-r3, r12, lr}
+    MEND
+
+; r0 VP8_COMP *cpi
+; r1 unsigned char *cx_data
+; r2 const unsigned char *cx_data_end
+; r3 int num_part
+; s0 vp8_coef_encodings
+; s1 vp8_extra_bits,
+; s2 const vp8_tree_index *
+
+|vp8cx_pack_tokens_into_partitions_armv5| PROC
+    push    {r4-r12, lr}
+    sub     sp, sp, #40
+
+    ; Compute address of cpi->common.mb_rows
+    ldr     r4, _VP8_COMP_common_
+    ldr     r6, _VP8_COMMON_MBrows_
+    add     r4, r0, r4
+
+    ldr     r5, [r4, r6]                ; load up mb_rows
+
+    str     r5, [sp, #36]               ; save mb_rows
+    str     r1, [sp, #24]               ; save ptr = cx_data
+    str     r3, [sp, #20]               ; save num_part
+    str     r2, [sp, #8]                ; save cx_data_end
+
+    ldr     r4, _VP8_COMP_tplist_
+    add     r4, r0, r4
+    ldr     r7, [r4, #0]                ; dereference cpi->tp_list
+    str     r7, [sp, #32]               ; store start of cpi->tp_list
+
+    ldr     r11, _VP8_COMP_bc_          ; load up vp8_writer out of cpi
+    add     r0, r0, r11
+
+    mov     r11, #0
+    str     r11, [sp, #28]              ; i
+
+numparts_loop
+    ldr     r2, _vp8_writer_sz_         ; load up sizeof(vp8_writer)
+    add     r0, r2                      ; bc[i + 1]
+
+    ldr     r10, [sp, #24]              ; ptr
+    ldr     r5,  [sp, #36]              ; move mb_rows to the counting section
+    subs    r5, r5, r11                 ; move start point with each partition
+                                        ; mb_rows starts at i
+    str     r5,  [sp, #12]
+
+    ; Reset all of the VP8 Writer data for each partition that
+    ; is processed.
+    ; start_encode
+
+    ldr     r3, [sp, #8]
+    str     r3, [r0, #vp8_writer_buffer_end]
+
+    mov     r2, #0                      ; vp8_writer_lowvalue
+    mov     r5, #255                    ; vp8_writer_range
+    mvn     r3, #23                     ; vp8_writer_count
+
+    str     r2,  [r0, #vp8_writer_pos]
+    str     r10, [r0, #vp8_writer_buffer]
+
+    ble     end_partition               ; if (mb_rows <= 0) end partition
+
+mb_row_loop
+
+    ldr     r1, [r7, #tokenlist_start]
+    ldr     r9, [r7, #tokenlist_stop]
+    str     r9, [sp, #0]                ; save stop for later comparison
+    str     r7, [sp, #16]               ; tokenlist address for next time
+
+    b       check_p_lt_stop
+
+    ; actual work gets done here!
+
+while_p_lt_stop
+    ldrb    r6, [r1, #tokenextra_token] ; t
+    ldr     r4, [sp, #80]               ; vp8_coef_encodings
+    mov     lr, #0
+    add     r4, r4, r6, lsl #3          ; a = vp8_coef_encodings + t
+    ldr     r9, [r1, #tokenextra_context_tree]   ; pp
+
+    ldrb    r7, [r1, #tokenextra_skip_eob_node]
+
+    ldr     r6, [r4, #vp8_token_value]  ; v
+    ldr     r8, [r4, #vp8_token_len]    ; n
+
+    ; vp8 specific skip_eob_node
+    cmp     r7, #0
+    movne   lr, #2                      ; i = 2
+    subne   r8, r8, #1                  ; --n
+
+    rsb     r4, r8, #32                 ; 32-n
+    ldr     r10, [sp, #88]              ; vp8_coef_tree
+
+    ; v is kept in r12 during the token pack loop
+    lsl     r12, r6, r4                ; r12 = v << 32 - n
+
+; loop start
+token_loop
+    ldrb    r4, [r9, lr, asr #1]        ; pp [i>>1]
+    sub     r7, r5, #1                  ; range-1
+
+    ; Decisions are made based on the bit value shifted
+    ; off of v, so set a flag here based on this.
+    ; This value is refered to as "bb"
+    lsls    r12, r12, #1                ; bb = v >> n
+    mul     r6, r4, r7                  ; ((range-1) * pp[i>>1]))
+
+    ; bb can only be 0 or 1.  So only execute this statement
+    ; if bb == 1, otherwise it will act like i + 0
+    addcs   lr, lr, #1                  ; i + bb
+
+    mov     r7, #1
+    ldrsb   lr, [r10, lr]               ; i = vp8_coef_tree[i+bb]
+    add     r4, r7, r6, lsr #8          ; 1 + (((range-1) * pp[i>>1]) >> 8)
+
+    addcs   r2, r2, r4                  ; if  (bb) lowvalue += split
+    subcs   r4, r5, r4                  ; if  (bb) range = range-split
+
+    ; Counting the leading zeros is used to normalize range.
+    clz     r6, r4
+    sub     r6, r6, #24                 ; shift
+
+    ; Flag is set on the sum of count.  This flag is used later
+    ; to determine if count >= 0
+    adds    r3, r3, r6                  ; count += shift
+    lsl     r5, r4, r6                  ; range <<= shift
+    bmi     token_count_lt_zero         ; if(count >= 0)
+
+    sub     r6, r6, r3                  ; offset = shift - count
+    sub     r4, r6, #1                  ; offset-1
+    lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
+    bpl     token_high_bit_not_set
+
+    ldr     r4, [r0, #vp8_writer_pos]   ; x
+    sub     r4, r4, #1                  ; x = w->pos-1
+    b       token_zero_while_start
+token_zero_while_loop
+    mov     r10, #0
+    strb    r10, [r7, r4]               ; w->buffer[x] =(unsigned char)0
+    sub     r4, r4, #1                  ; x--
+token_zero_while_start
+    cmp     r4, #0
+    ldrge   r7, [r0, #vp8_writer_buffer]
+    ldrb    r11, [r7, r4]
+    cmpge   r11, #0xff
+    beq     token_zero_while_loop
+
+    ldr     r7, [r0, #vp8_writer_buffer]
+    ldrb    r10, [r7, r4]               ; w->buffer[x]
+    add     r10, r10, #1
+    strb    r10, [r7, r4]               ; w->buffer[x] + 1
+token_high_bit_not_set
+    rsb     r4, r6, #24                 ; 24-offset
+    ldr     r10, [r0, #vp8_writer_buffer]
+    lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
+    ldr     r4, [r0, #vp8_writer_pos]   ; w->pos
+    lsl     r2, r2, r6                  ; lowvalue <<= offset
+    mov     r6, r3                      ; shift = count
+    add     r11, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r11, [r0, #vp8_writer_pos]
+    sub     r3, r3, #8                  ; count -= 8
+
+    VALIDATE_POS r10, r11               ; validate_buffer at pos
+
+    strb    r7, [r10, r4]               ; w->buffer[w->pos++]
+
+    ; r10 is used earlier in the loop, but r10 is used as
+    ; temp variable here.  So after r10 is used, reload
+    ; vp8_coef_tree_dcd into r10
+    ldr     r10, [sp, #88]              ; vp8_coef_tree
+
+token_count_lt_zero
+    lsl     r2, r2, r6                  ; lowvalue <<= shift
+
+    subs    r8, r8, #1                  ; --n
+    bne     token_loop
+
+    ldrb    r6, [r1, #tokenextra_token] ; t
+    ldr     r7, [sp, #84]                ; vp8_extra_bits
+    ; Add t * sizeof (vp8_extra_bit_struct) to get the desired
+    ;  element.  Here vp8_extra_bit_struct == 16
+    add     r12, r7, r6, lsl #4         ; b = vp8_extra_bits + t
+
+    ldr     r4, [r12, #vp8_extra_bit_struct_base_val]
+    cmp     r4, #0
+    beq     skip_extra_bits
+
+;   if( b->base_val)
+    ldr     r8, [r12, #vp8_extra_bit_struct_len] ; L
+    ldrsh   lr, [r1, #tokenextra_extra] ; e = p->Extra
+    cmp     r8, #0                      ; if( L)
+    beq     no_extra_bits
+
+    ldr     r9, [r12, #vp8_extra_bit_struct_prob]
+    asr     r7, lr, #1                  ; v=e>>1
+
+    ldr     r10, [r12, #vp8_extra_bit_struct_tree]
+    str     r10, [sp, #4]               ; b->tree
+
+    rsb     r4, r8, #32
+    lsl     r12, r7, r4
+
+    mov     lr, #0                      ; i = 0
+
+extra_bits_loop
+    ldrb    r4, [r9, lr, asr #1]        ; pp[i>>1]
+    sub     r7, r5, #1                  ; range-1
+    lsls    r12, r12, #1                ; v >> n
+    mul     r6, r4, r7                  ; (range-1) * pp[i>>1]
+    addcs   lr, lr, #1                  ; i + bb
+
+    mov     r7, #1
+    ldrsb   lr, [r10, lr]               ; i = b->tree[i+bb]
+    add     r4, r7, r6, lsr #8          ; split = 1 +  (((range-1) * pp[i>>1]) >> 8)
+
+    addcs   r2, r2, r4                  ; if  (bb) lowvalue += split
+    subcs   r4, r5, r4                  ; if  (bb) range = range-split
+
+    clz     r6, r4
+    sub     r6, r6, #24
+
+    adds    r3, r3, r6                  ; count += shift
+    lsl     r5, r4, r6                  ; range <<= shift
+    bmi     extra_count_lt_zero         ; if(count >= 0)
+
+    sub     r6, r6, r3                  ; offset= shift - count
+    sub     r4, r6, #1                  ; offset-1
+    lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
+    bpl     extra_high_bit_not_set
+
+    ldr     r4, [r0, #vp8_writer_pos]   ; x
+    sub     r4, r4, #1                  ; x = w->pos - 1
+    b       extra_zero_while_start
+extra_zero_while_loop
+    mov     r10, #0
+    strb    r10, [r7, r4]               ; w->buffer[x] =(unsigned char)0
+    sub     r4, r4, #1                  ; x--
+extra_zero_while_start
+    cmp     r4, #0
+    ldrge   r7, [r0, #vp8_writer_buffer]
+    ldrb    r11, [r7, r4]
+    cmpge   r11, #0xff
+    beq     extra_zero_while_loop
+
+    ldr     r7, [r0, #vp8_writer_buffer]
+    ldrb    r10, [r7, r4]
+    add     r10, r10, #1
+    strb    r10, [r7, r4]
+extra_high_bit_not_set
+    rsb     r4, r6, #24                 ; 24-offset
+    ldr     r10, [r0, #vp8_writer_buffer]
+    lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
+    ldr     r4, [r0, #vp8_writer_pos]
+    lsl     r2, r2, r6                  ; lowvalue <<= offset
+    mov     r6, r3                      ; shift = count
+    add     r11, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r11, [r0, #vp8_writer_pos]
+    sub     r3, r3, #8                  ; count -= 8
+
+    VALIDATE_POS r10, r11               ; validate_buffer at pos
+
+    strb    r7, [r10, r4]               ; w->buffer[w->pos++]=(lowvalue >> (24-offset))
+    ldr     r10, [sp, #4]               ; b->tree
+extra_count_lt_zero
+    lsl     r2, r2, r6
+
+    subs    r8, r8, #1                  ; --n
+    bne     extra_bits_loop             ; while (n)
+
+no_extra_bits
+    ldr     lr, [r1, #4]                ; e = p->Extra
+    add     r4, r5, #1                  ; range + 1
+    tst     lr, #1
+    lsr     r4, r4, #1                  ; split = (range + 1) >> 1
+    addne   r2, r2, r4                  ; lowvalue += split
+    subne   r4, r5, r4                  ; range = range-split
+    tst     r2, #0x80000000             ; lowvalue & 0x80000000
+    lsl     r5, r4, #1                  ; range <<= 1
+    beq     end_high_bit_not_set
+
+    ldr     r4, [r0, #vp8_writer_pos]
+    mov     r7, #0
+    sub     r4, r4, #1
+    b       end_zero_while_start
+end_zero_while_loop
+    strb    r7, [r6, r4]
+    sub     r4, r4, #1                  ; x--
+end_zero_while_start
+    cmp     r4, #0
+    ldrge   r6, [r0, #vp8_writer_buffer]
+    ldrb    r12, [r6, r4]
+    cmpge   r12, #0xff
+    beq     end_zero_while_loop
+
+    ldr     r6, [r0, #vp8_writer_buffer]
+    ldrb    r7, [r6, r4]
+    add     r7, r7, #1
+    strb    r7, [r6, r4]
+end_high_bit_not_set
+    adds    r3, r3, #1                  ; ++count
+    lsl     r2, r2, #1                  ; lowvalue  <<= 1
+    bne     end_count_zero
+
+    ldr     r4, [r0, #vp8_writer_pos]
+    mvn     r3, #7                      ; count = -8
+    ldr     r7, [r0, #vp8_writer_buffer]
+    lsr     r6, r2, #24                 ; lowvalue >> 24
+    add     r12, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r12, [r0, #vp8_writer_pos]
+
+    VALIDATE_POS r7, r12                ; validate_buffer at pos
+
+    strb    r6, [r7, r4]
+end_count_zero
+skip_extra_bits
+    add     r1, r1, #TOKENEXTRA_SZ      ; ++p
+check_p_lt_stop
+    ldr     r4, [sp, #0]                ; stop
+    cmp     r1, r4                      ; while( p < stop)
+    bcc     while_p_lt_stop
+
+    ldr     r10, [sp, #20]              ; num_parts
+    mov     r1, #TOKENLIST_SZ
+    mul     r1, r10, r1
+
+    ldr     r6, [sp, #12]               ; mb_rows
+    ldr     r7, [sp, #16]               ; tokenlist address
+    subs    r6, r6, r10
+    add     r7, r7, r1                  ; next element in the array
+    str     r6, [sp, #12]
+    bgt     mb_row_loop
+
+end_partition
+    mov     r12, #32
+
+stop_encode_loop
+    sub     r7, r5, #1                  ; range-1
+
+    mov     r4, r7, lsl #7              ; ((range-1) * 128)
+
+    mov     r7, #1
+    add     r4, r7, r4, lsr #8          ; 1 + (((range-1) * 128) >> 8)
+
+    ; Counting the leading zeros is used to normalize range.
+    clz     r6, r4
+    sub     r6, r6, #24                 ; shift
+
+    ; Flag is set on the sum of count.  This flag is used later
+    ; to determine if count >= 0
+    adds    r3, r3, r6                  ; count += shift
+    lsl     r5, r4, r6                  ; range <<= shift
+    bmi     token_count_lt_zero_se      ; if(count >= 0)
+
+    sub     r6, r6, r3                  ; offset = shift - count
+    sub     r4, r6, #1                  ; offset-1
+    lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
+    bpl     token_high_bit_not_set_se
+
+    ldr     r4, [r0, #vp8_writer_pos]   ; x
+    sub     r4, r4, #1                  ; x = w->pos-1
+    b       token_zero_while_start_se
+token_zero_while_loop_se
+    mov     r10, #0
+    strb    r10, [r7, r4]               ; w->buffer[x] =(unsigned char)0
+    sub     r4, r4, #1                  ; x--
+token_zero_while_start_se
+    cmp     r4, #0
+    ldrge   r7, [r0, #vp8_writer_buffer]
+    ldrb    r11, [r7, r4]
+    cmpge   r11, #0xff
+    beq     token_zero_while_loop_se
+
+    ldr     r7, [r0, #vp8_writer_buffer]
+    ldrb    r10, [r7, r4]               ; w->buffer[x]
+    add     r10, r10, #1
+    strb    r10, [r7, r4]               ; w->buffer[x] + 1
+token_high_bit_not_set_se
+    rsb     r4, r6, #24                 ; 24-offset
+    ldr     r10, [r0, #vp8_writer_buffer]
+    lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
+    ldr     r4, [r0, #vp8_writer_pos]   ; w->pos
+    lsl     r2, r2, r6                  ; lowvalue <<= offset
+    mov     r6, r3                      ; shift = count
+    add     r11, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r11, [r0, #vp8_writer_pos]
+    sub     r3, r3, #8                  ; count -= 8
+
+    VALIDATE_POS r10, r11               ; validate_buffer at pos
+
+    strb    r7, [r10, r4]               ; w->buffer[w->pos++]
+
+token_count_lt_zero_se
+    lsl     r2, r2, r6                  ; lowvalue <<= shift
+
+    subs    r12, r12, #1
+    bne     stop_encode_loop
+
+    ldr     r4,  [r0, #vp8_writer_pos]  ; w->pos
+    ldr     r12, [sp, #24]              ; ptr
+    add     r12, r12, r4                ; ptr += w->pos
+    str     r12, [sp, #24]
+
+    ldr     r11, [sp, #28]              ; i
+    ldr     r10, [sp, #20]              ; num_parts
+
+    add     r11, r11, #1                ; i++
+    str     r11, [sp, #28]
+
+    ldr     r7, [sp, #32]               ; cpi->tp_list[i]
+    mov     r1, #TOKENLIST_SZ
+    add     r7, r7, r1                  ; next element in cpi->tp_list
+    str     r7, [sp, #32]               ; cpi->tp_list[i+1]
+
+    cmp     r10, r11
+    bgt     numparts_loop
+
+    add     sp, sp, #40
+    pop     {r4-r12, pc}
+    ENDP
+
+_VP8_COMP_common_
+    DCD     vp8_comp_common
+_VP8_COMMON_MBrows_
+    DCD     vp8_common_mb_rows
+_VP8_COMP_tplist_
+    DCD     vp8_comp_tplist
+_VP8_COMP_bc_
+    DCD     vp8_comp_bc
+_vp8_writer_sz_
+    DCD     vp8_writer_sz
+
+    END
diff --git a/vp8/encoder/arm/armv6/vp8_fast_quantize_b_armv6.asm b/vp8/encoder/arm/armv6/vp8_fast_quantize_b_armv6.asm
new file mode 100644 (file)
index 0000000..d61f5d9
--- /dev/null
@@ -0,0 +1,225 @@
+;
+;  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_fast_quantize_b_armv6|
+
+    INCLUDE asm_enc_offsets.asm
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    BLOCK *b
+; r1    BLOCKD *d
+|vp8_fast_quantize_b_armv6| PROC
+    stmfd   sp!, {r1, r4-r11, lr}
+
+    ldr     r3, [r0, #vp8_block_coeff]      ; coeff
+    ldr     r4, [r0, #vp8_block_quant_fast] ; quant_fast
+    ldr     r5, [r0, #vp8_block_round]      ; round
+    ldr     r6, [r1, #vp8_blockd_qcoeff]    ; qcoeff
+    ldr     r7, [r1, #vp8_blockd_dqcoeff]   ; dqcoeff
+    ldr     r8, [r1, #vp8_blockd_dequant]   ; dequant
+
+    ldr     r2, loop_count          ; loop_count=0x1000000. 'lsls' instruction
+                                    ; is used to update the counter so that
+                                    ; it can be used to mark nonzero
+                                    ; quantized coefficient pairs.
+
+    mov     r1, #0                  ; flags for quantized coeffs
+
+    ; PART 1: quantization and dequantization loop
+loop
+    ldr     r9, [r3], #4            ; [z1 | z0]
+    ldr     r10, [r5], #4           ; [r1 | r0]
+    ldr     r11, [r4], #4           ; [q1 | q0]
+
+    ssat16  lr, #1, r9              ; [sz1 | sz0]
+    eor     r9, r9, lr              ; [z1 ^ sz1 | z0 ^ sz0]
+    ssub16  r9, r9, lr              ; x = (z ^ sz) - sz
+    sadd16  r9, r9, r10             ; [x1+r1 | x0+r0]
+
+    ldr     r12, [r3], #4           ; [z3 | z2]
+
+    smulbb  r0, r9, r11             ; [(x0+r0)*q0]
+    smultt  r9, r9, r11             ; [(x1+r1)*q1]
+
+    ldr     r10, [r5], #4           ; [r3 | r2]
+
+    ssat16  r11, #1, r12            ; [sz3 | sz2]
+    eor     r12, r12, r11           ; [z3 ^ sz3 | z2 ^ sz2]
+    pkhtb   r0, r9, r0, asr #16     ; [y1 | y0]
+    ldr     r9, [r4], #4            ; [q3 | q2]
+    ssub16  r12, r12, r11           ; x = (z ^ sz) - sz
+
+    sadd16  r12, r12, r10           ; [x3+r3 | x2+r2]
+
+    eor     r0, r0, lr              ; [(y1 ^ sz1) | (y0 ^ sz0)]
+
+    smulbb  r10, r12, r9            ; [(x2+r2)*q2]
+    smultt  r12, r12, r9            ; [(x3+r3)*q3]
+
+    ssub16  r0, r0, lr              ; x = (y ^ sz) - sz
+
+    cmp     r0, #0                  ; check if zero
+    orrne   r1, r1, r2, lsr #24     ; add flag for nonzero coeffs
+
+    str     r0, [r6], #4            ; *qcoeff++ = x
+    ldr     r9, [r8], #4            ; [dq1 | dq0]
+
+    pkhtb   r10, r12, r10, asr #16  ; [y3 | y2]
+    eor     r10, r10, r11           ; [(y3 ^ sz3) | (y2 ^ sz2)]
+    ssub16  r10, r10, r11           ; x = (y ^ sz) - sz
+
+    cmp     r10, #0                 ; check if zero
+    orrne   r1, r1, r2, lsr #23     ; add flag for nonzero coeffs
+
+    str     r10, [r6], #4           ; *qcoeff++ = x
+    ldr     r11, [r8], #4           ; [dq3 | dq2]
+
+    smulbb  r12, r0, r9             ; [x0*dq0]
+    smultt  r0, r0, r9              ; [x1*dq1]
+
+    smulbb  r9, r10, r11            ; [x2*dq2]
+    smultt  r10, r10, r11           ; [x3*dq3]
+
+    lsls    r2, r2, #2              ; update loop counter
+    strh    r12, [r7, #0]           ; dqcoeff[0] = [x0*dq0]
+    strh    r0, [r7, #2]            ; dqcoeff[1] = [x1*dq1]
+    strh    r9, [r7, #4]            ; dqcoeff[2] = [x2*dq2]
+    strh    r10, [r7, #6]           ; dqcoeff[3] = [x3*dq3]
+    add     r7, r7, #8              ; dqcoeff += 8
+    bne     loop
+
+    ; PART 2: check position for eob...
+    ldr     r11, [sp, #0]           ; restore BLOCKD pointer
+    mov     lr, #0                  ; init eob
+    cmp     r1, #0                  ; coeffs after quantization?
+    ldr     r12, [r11, #vp8_blockd_eob]
+    beq     end                     ; skip eob calculations if all zero
+
+    ldr     r0, [r11, #vp8_blockd_qcoeff]
+
+    ; check shortcut for nonzero qcoeffs
+    tst    r1, #0x80
+    bne    quant_coeff_15_14
+    tst    r1, #0x20
+    bne    quant_coeff_13_11
+    tst    r1, #0x8
+    bne    quant_coeff_12_7
+    tst    r1, #0x40
+    bne    quant_coeff_10_9
+    tst    r1, #0x10
+    bne    quant_coeff_8_3
+    tst    r1, #0x2
+    bne    quant_coeff_6_5
+    tst    r1, #0x4
+    bne    quant_coeff_4_2
+    b      quant_coeff_1_0
+
+quant_coeff_15_14
+    ldrh    r2, [r0, #30]       ; rc=15, i=15
+    mov     lr, #16
+    cmp     r2, #0
+    bne     end
+
+    ldrh    r3, [r0, #28]       ; rc=14, i=14
+    mov     lr, #15
+    cmp     r3, #0
+    bne     end
+
+quant_coeff_13_11
+    ldrh    r2, [r0, #22]       ; rc=11, i=13
+    mov     lr, #14
+    cmp     r2, #0
+    bne     end
+
+quant_coeff_12_7
+    ldrh    r3, [r0, #14]       ; rc=7,  i=12
+    mov     lr, #13
+    cmp     r3, #0
+    bne     end
+
+    ldrh    r2, [r0, #20]       ; rc=10, i=11
+    mov     lr, #12
+    cmp     r2, #0
+    bne     end
+
+quant_coeff_10_9
+    ldrh    r3, [r0, #26]       ; rc=13, i=10
+    mov     lr, #11
+    cmp     r3, #0
+    bne     end
+
+    ldrh    r2, [r0, #24]       ; rc=12, i=9
+    mov     lr, #10
+    cmp     r2, #0
+    bne     end
+
+quant_coeff_8_3
+    ldrh    r3, [r0, #18]       ; rc=9,  i=8
+    mov     lr, #9
+    cmp     r3, #0
+    bne     end
+
+    ldrh    r2, [r0, #12]       ; rc=6,  i=7
+    mov     lr, #8
+    cmp     r2, #0
+    bne     end
+
+quant_coeff_6_5
+    ldrh    r3, [r0, #6]        ; rc=3,  i=6
+    mov     lr, #7
+    cmp     r3, #0
+    bne     end
+
+    ldrh    r2, [r0, #4]        ; rc=2,  i=5
+    mov     lr, #6
+    cmp     r2, #0
+    bne     end
+
+quant_coeff_4_2
+    ldrh    r3, [r0, #10]       ; rc=5,  i=4
+    mov     lr, #5
+    cmp     r3, #0
+    bne     end
+
+    ldrh    r2, [r0, #16]       ; rc=8,  i=3
+    mov     lr, #4
+    cmp     r2, #0
+    bne     end
+
+    ldrh    r3, [r0, #8]        ; rc=4,  i=2
+    mov     lr, #3
+    cmp     r3, #0
+    bne     end
+
+quant_coeff_1_0
+    ldrh    r2, [r0, #2]        ; rc=1,  i=1
+    mov     lr, #2
+    cmp     r2, #0
+    bne     end
+
+    mov     lr, #1              ; rc=0,  i=0
+
+end
+    strb    lr, [r12]
+    ldmfd   sp!, {r1, r4-r11, pc}
+
+    ENDP
+
+loop_count
+    DCD     0x1000000
+
+    END
+
diff --git a/vp8/encoder/arm/armv6/vp8_mse16x16_armv6.asm b/vp8/encoder/arm/armv6/vp8_mse16x16_armv6.asm
new file mode 100644 (file)
index 0000000..000805d
--- /dev/null
@@ -0,0 +1,138 @@
+;
+;  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_mse16x16_armv6|
+
+    ARM
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    unsigned char *src_ptr
+; r1    int source_stride
+; r2    unsigned char *ref_ptr
+; r3    int  recon_stride
+; stack unsigned int *sse
+;
+;note: Based on vp8_variance16x16_armv6. In this function, sum is never used.
+;      So, we can remove this part of calculation.
+
+|vp8_mse16x16_armv6| PROC
+
+    push    {r4-r9, lr}
+
+    pld     [r0, r1, lsl #0]
+    pld     [r2, r3, lsl #0]
+
+    mov     r12, #16            ; set loop counter to 16 (=block height)
+    mov     r4, #0              ; initialize sse = 0
+
+loop
+    ; 1st 4 pixels
+    ldr     r5, [r0, #0x0]      ; load 4 src pixels
+    ldr     r6, [r2, #0x0]      ; load 4 ref pixels
+
+    mov     lr, #0              ; constant zero
+
+    usub8   r8, r5, r6          ; calculate difference
+    pld     [r0, r1, lsl #1]
+    sel     r7, r8, lr          ; select bytes with positive difference
+    usub8   r9, r6, r5          ; calculate difference with reversed operands
+    pld     [r2, r3, lsl #1]
+    sel     r8, r9, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r5, r7, lr          ; calculate sum of positive differences
+    usad8   r6, r8, lr          ; calculate sum of negative differences
+    orr     r8, r8, r7          ; differences of all 4 pixels
+
+    ldr     r5, [r0, #0x4]      ; load 4 src pixels
+
+    ; calculate sse
+    uxtb16  r6, r8              ; byte (two pixels) to halfwords
+    uxtb16  r7, r8, ror #8      ; another two pixels to halfwords
+    smlad   r4, r6, r6, r4      ; dual signed multiply, add and accumulate (1)
+
+    ; 2nd 4 pixels
+    ldr     r6, [r2, #0x4]      ; load 4 ref pixels
+    smlad   r4, r7, r7, r4      ; dual signed multiply, add and accumulate (2)
+
+    usub8   r8, r5, r6          ; calculate difference
+    sel     r7, r8, lr          ; select bytes with positive difference
+    usub8   r9, r6, r5          ; calculate difference with reversed operands
+    sel     r8, r9, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r5, r7, lr          ; calculate sum of positive differences
+    usad8   r6, r8, lr          ; calculate sum of negative differences
+    orr     r8, r8, r7          ; differences of all 4 pixels
+    ldr     r5, [r0, #0x8]      ; load 4 src pixels
+    ; calculate sse
+    uxtb16  r6, r8              ; byte (two pixels) to halfwords
+    uxtb16  r7, r8, ror #8      ; another two pixels to halfwords
+    smlad   r4, r6, r6, r4      ; dual signed multiply, add and accumulate (1)
+
+    ; 3rd 4 pixels
+    ldr     r6, [r2, #0x8]      ; load 4 ref pixels
+    smlad   r4, r7, r7, r4      ; dual signed multiply, add and accumulate (2)
+
+    usub8   r8, r5, r6          ; calculate difference
+    sel     r7, r8, lr          ; select bytes with positive difference
+    usub8   r9, r6, r5          ; calculate difference with reversed operands
+    sel     r8, r9, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r5, r7, lr          ; calculate sum of positive differences
+    usad8   r6, r8, lr          ; calculate sum of negative differences
+    orr     r8, r8, r7          ; differences of all 4 pixels
+
+    ldr     r5, [r0, #0xc]      ; load 4 src pixels
+
+    ; calculate sse
+    uxtb16  r6, r8              ; byte (two pixels) to halfwords
+    uxtb16  r7, r8, ror #8      ; another two pixels to halfwords
+    smlad   r4, r6, r6, r4      ; dual signed multiply, add and accumulate (1)
+
+    ; 4th 4 pixels
+    ldr     r6, [r2, #0xc]      ; load 4 ref pixels
+    smlad   r4, r7, r7, r4      ; dual signed multiply, add and accumulate (2)
+
+    usub8   r8, r5, r6          ; calculate difference
+    add     r0, r0, r1          ; set src_ptr to next row
+    sel     r7, r8, lr          ; select bytes with positive difference
+    usub8   r9, r6, r5          ; calculate difference with reversed operands
+    add     r2, r2, r3          ; set dst_ptr to next row
+    sel     r8, r9, lr          ; select bytes with negative difference
+
+    ; calculate partial sums
+    usad8   r5, r7, lr          ; calculate sum of positive differences
+    usad8   r6, r8, lr          ; calculate sum of negative differences
+    orr     r8, r8, r7          ; differences of all 4 pixels
+
+    subs    r12, r12, #1        ; next row
+
+    ; calculate sse
+    uxtb16  r6, r8              ; byte (two pixels) to halfwords
+    uxtb16  r7, r8, ror #8      ; another two pixels to halfwords
+    smlad   r4, r6, r6, r4      ; dual signed multiply, add and accumulate (1)
+    smlad   r4, r7, r7, r4      ; dual signed multiply, add and accumulate (2)
+
+    bne     loop
+
+    ; return stuff
+    ldr     r1, [sp, #28]       ; get address of sse
+    mov     r0, r4              ; return sse
+    str     r4, [r1]            ; store sse
+
+    pop     {r4-r9, pc}
+
+    ENDP
+
+    END
diff --git a/vp8/encoder/arm/armv6/vp8_short_fdct4x4_armv6.asm b/vp8/encoder/arm/armv6/vp8_short_fdct4x4_armv6.asm
new file mode 100644 (file)
index 0000000..8034c1d
--- /dev/null
@@ -0,0 +1,262 @@
+;
+;  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+    EXPORT |vp8_short_fdct4x4_armv6|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA    |.text|, CODE, READONLY
+; void vp8_short_fdct4x4_c(short *input, short *output, int pitch)
+|vp8_short_fdct4x4_armv6| PROC
+
+    stmfd       sp!, {r4 - r12, lr}
+
+    ; PART 1
+
+    ; coeffs 0-3
+    ldrd        r4, r5, [r0]        ; [i1 | i0] [i3 | i2]
+
+    ldr         r10, c7500
+    ldr         r11, c14500
+    ldr         r12, c0x22a453a0    ; [2217*4 | 5352*4]
+    ldr         lr, c0x00080008
+    ror         r5, r5, #16         ; [i2 | i3]
+
+    qadd16      r6, r4, r5          ; [i1+i2 | i0+i3] = [b1 | a1] without shift
+    qsub16      r7, r4, r5          ; [i1-i2 | i0-i3] = [c1 | d1] without shift
+
+    add         r0, r0, r2          ; update input pointer
+
+    qadd16      r7, r7, r7          ; 2*[c1|d1] --> we can use smlad and smlsd
+                                    ; with 2217*4 and 5352*4 without losing the
+                                    ; sign bit (overflow)
+
+    smuad       r4, r6, lr          ; o0 = (i1+i2)*8 + (i0+i3)*8
+    smusd       r5, r6, lr          ; o2 = (i1+i2)*8 - (i0+i3)*8
+
+    smlad       r6, r7, r12, r11    ; o1 = (c1 * 2217 + d1 * 5352 +  14500)
+    smlsdx      r7, r7, r12, r10    ; o3 = (d1 * 2217 - c1 * 5352 +   7500)
+
+    ldrd        r8, r9, [r0]        ; [i5 | i4] [i7 | i6]
+
+    pkhbt       r3, r4, r6, lsl #4  ; [o1 | o0], keep in register for PART 2
+    pkhbt       r6, r5, r7, lsl #4  ; [o3 | o2]
+
+    str         r6, [r1, #4]
+
+    ; coeffs 4-7
+    ror         r9, r9, #16         ; [i6 | i7]
+
+    qadd16      r6, r8, r9          ; [i5+i6 | i4+i7] = [b1 | a1] without shift
+    qsub16      r7, r8, r9          ; [i5-i6 | i4-i7] = [c1 | d1] without shift
+
+    add         r0, r0, r2          ; update input pointer
+
+    qadd16      r7, r7, r7          ; 2x[c1|d1] --> we can use smlad and smlsd
+                                    ; with 2217*4 and 5352*4 without losing the
+                                    ; sign bit (overflow)
+
+    smuad       r9, r6, lr          ; o4 = (i5+i6)*8 + (i4+i7)*8
+    smusd       r8, r6, lr          ; o6 = (i5+i6)*8 - (i4+i7)*8
+
+    smlad       r6, r7, r12, r11    ; o5 = (c1 * 2217 + d1 * 5352 +  14500)
+    smlsdx      r7, r7, r12, r10    ; o7 = (d1 * 2217 - c1 * 5352 +   7500)
+
+    ldrd        r4, r5, [r0]        ; [i9 | i8] [i11 | i10]
+
+    pkhbt       r9, r9, r6, lsl #4  ; [o5 | o4], keep in register for PART 2
+    pkhbt       r6, r8, r7, lsl #4  ; [o7 | o6]
+
+    str         r6, [r1, #12]
+
+    ; coeffs 8-11
+    ror         r5, r5, #16         ; [i10 | i11]
+
+    qadd16      r6, r4, r5          ; [i9+i10 | i8+i11]=[b1 | a1] without shift
+    qsub16      r7, r4, r5          ; [i9-i10 | i8-i11]=[c1 | d1] without shift
+
+    add         r0, r0, r2          ; update input pointer
+
+    qadd16      r7, r7, r7          ; 2x[c1|d1] --> we can use smlad and smlsd
+                                    ; with 2217*4 and 5352*4 without losing the
+                                    ; sign bit (overflow)
+
+    smuad       r2, r6, lr          ; o8 = (i9+i10)*8 + (i8+i11)*8
+    smusd       r8, r6, lr          ; o10 = (i9+i10)*8 - (i8+i11)*8
+
+    smlad       r6, r7, r12, r11    ; o9 = (c1 * 2217 + d1 * 5352 +  14500)
+    smlsdx      r7, r7, r12, r10    ; o11 = (d1 * 2217 - c1 * 5352 +   7500)
+
+    ldrd        r4, r5, [r0]        ; [i13 | i12] [i15 | i14]
+
+    pkhbt       r2, r2, r6, lsl #4  ; [o9 | o8], keep in register for PART 2
+    pkhbt       r6, r8, r7, lsl #4  ; [o11 | o10]
+
+    str         r6, [r1, #20]
+
+    ; coeffs 12-15
+    ror         r5, r5, #16         ; [i14 | i15]
+
+    qadd16      r6, r4, r5          ; [i13+i14 | i12+i15]=[b1|a1] without shift
+    qsub16      r7, r4, r5          ; [i13-i14 | i12-i15]=[c1|d1] without shift
+
+    qadd16      r7, r7, r7          ; 2x[c1|d1] --> we can use smlad and smlsd
+                                    ; with 2217*4 and 5352*4 without losing the
+                                    ; sign bit (overflow)
+
+    smuad       r4, r6, lr          ; o12 = (i13+i14)*8 + (i12+i15)*8
+    smusd       r5, r6, lr          ; o14 = (i13+i14)*8 - (i12+i15)*8
+
+    smlad       r6, r7, r12, r11    ; o13 = (c1 * 2217 + d1 * 5352 +  14500)
+    smlsdx      r7, r7, r12, r10    ; o15 = (d1 * 2217 - c1 * 5352 +   7500)
+
+    pkhbt       r0, r4, r6, lsl #4  ; [o13 | o12], keep in register for PART 2
+    pkhbt       r6, r5, r7, lsl #4  ; [o15 | o14]
+
+    str         r6, [r1, #28]
+
+
+    ; PART 2 -------------------------------------------------
+    ldr         r11, c12000
+    ldr         r10, c51000
+    ldr         lr, c0x00070007
+
+    qadd16      r4, r3, r0          ; a1 = [i1+i13 | i0+i12]
+    qadd16      r5, r9, r2          ; b1 = [i5+i9  |  i4+i8]
+    qsub16      r6, r9, r2          ; c1 = [i5-i9  |  i4-i8]
+    qsub16      r7, r3, r0          ; d1 = [i1-i13 | i0-i12]
+
+    qadd16      r4, r4, lr          ; a1 + 7
+
+    add         r0, r11, #0x10000   ; add (d!=0)
+
+    qadd16      r2, r4, r5          ; a1 + b1 + 7
+    qsub16      r3, r4, r5          ; a1 - b1 + 7
+
+    ldr         r12, c0x08a914e8    ; [2217 | 5352]
+
+    lsl         r8, r2, #16         ; prepare bottom halfword for scaling
+    asr         r2, r2, #4          ; scale top halfword
+    lsl         r9, r3, #16         ; prepare bottom halfword for scaling
+    asr         r3, r3, #4          ; scale top halfword
+    pkhtb       r4, r2, r8, asr #20 ; pack and scale bottom halfword
+    pkhtb       r5, r3, r9, asr #20 ; pack and scale bottom halfword
+
+    smulbt      r2, r6, r12         ; [ ------ | c1*2217]
+    str         r4, [r1, #0]        ; [     o1 |      o0]
+    smultt      r3, r6, r12         ; [c1*2217 | ------ ]
+    str         r5, [r1, #16]       ; [     o9 |      o8]
+
+    smlabb      r8, r7, r12, r2     ; [ ------ | d1*5352]
+    smlatb      r9, r7, r12, r3     ; [d1*5352 | ------ ]
+
+    smulbb      r2, r6, r12         ; [ ------ | c1*5352]
+    smultb      r3, r6, r12         ; [c1*5352 | ------ ]
+
+    lsls        r6, r7, #16         ; d1 != 0 ?
+    addeq       r8, r8, r11         ; c1_b*2217+d1_b*5352+12000 + (d==0)
+    addne       r8, r8, r0          ; c1_b*2217+d1_b*5352+12000 + (d!=0)
+    asrs        r6, r7, #16
+    addeq       r9, r9, r11         ; c1_t*2217+d1_t*5352+12000 + (d==0)
+    addne       r9, r9, r0          ; c1_t*2217+d1_t*5352+12000 + (d!=0)
+
+    smlabt      r4, r7, r12, r10    ; [ ------ | d1*2217] + 51000
+    smlatt      r5, r7, r12, r10    ; [d1*2217 | ------ ] + 51000
+
+    pkhtb       r9, r9, r8, asr #16
+
+    sub         r4, r4, r2
+    sub         r5, r5, r3
+
+    ldr         r3, [r1, #4]        ; [i3 | i2]
+
+    pkhtb       r5, r5, r4, asr #16 ; [o13|o12]
+
+    str         r9, [r1, #8]        ; [o5 | 04]
+
+    ldr         r9, [r1, #12]       ; [i7 | i6]
+    ldr         r8, [r1, #28]       ; [i15|i14]
+    ldr         r2, [r1, #20]       ; [i11|i10]
+    str         r5, [r1, #24]       ; [o13|o12]
+
+    qadd16      r4, r3, r8          ; a1 = [i3+i15 | i2+i14]
+    qadd16      r5, r9, r2          ; b1 = [i7+i11 | i6+i10]
+
+    qadd16      r4, r4, lr          ; a1 + 7
+
+    qsub16      r6, r9, r2          ; c1 = [i7-i11 | i6-i10]
+    qadd16      r2, r4, r5          ; a1 + b1 + 7
+    qsub16      r7, r3, r8          ; d1 = [i3-i15 | i2-i14]
+    qsub16      r3, r4, r5          ; a1 - b1 + 7
+
+    lsl         r8, r2, #16         ; prepare bottom halfword for scaling
+    asr         r2, r2, #4          ; scale top halfword
+    lsl         r9, r3, #16         ; prepare bottom halfword for scaling
+    asr         r3, r3, #4          ; scale top halfword
+    pkhtb       r4, r2, r8, asr #20 ; pack and scale bottom halfword
+    pkhtb       r5, r3, r9, asr #20 ; pack and scale bottom halfword
+
+    smulbt      r2, r6, r12         ; [ ------ | c1*2217]
+    str         r4, [r1, #4]        ; [     o3 |      o2]
+    smultt      r3, r6, r12         ; [c1*2217 | ------ ]
+    str         r5, [r1, #20]       ; [    o11 |     o10]
+
+    smlabb      r8, r7, r12, r2     ; [ ------ | d1*5352]
+    smlatb      r9, r7, r12, r3     ; [d1*5352 | ------ ]
+
+    smulbb      r2, r6, r12         ; [ ------ | c1*5352]
+    smultb      r3, r6, r12         ; [c1*5352 | ------ ]
+
+    lsls        r6, r7, #16         ; d1 != 0 ?
+    addeq       r8, r8, r11         ; c1_b*2217+d1_b*5352+12000 + (d==0)
+    addne       r8, r8, r0          ; c1_b*2217+d1_b*5352+12000 + (d!=0)
+
+    asrs        r6, r7, #16
+    addeq       r9, r9, r11         ; c1_t*2217+d1_t*5352+12000 + (d==0)
+    addne       r9, r9, r0          ; c1_t*2217+d1_t*5352+12000 + (d!=0)
+
+    smlabt      r4, r7, r12, r10    ; [ ------ | d1*2217] + 51000
+    smlatt      r5, r7, r12, r10    ; [d1*2217 | ------ ] + 51000
+
+    pkhtb       r9, r9, r8, asr #16
+
+    sub         r4, r4, r2
+    sub         r5, r5, r3
+
+    str         r9, [r1, #12]       ; [o7 | o6]
+    pkhtb       r5, r5, r4, asr #16 ; [o15|o14]
+
+    str         r5, [r1, #28]       ; [o15|o14]
+
+    ldmfd       sp!, {r4 - r12, pc}
+
+    ENDP
+
+; Used constants
+c7500
+    DCD     7500
+c14500
+    DCD     14500
+c0x22a453a0
+    DCD     0x22a453a0
+c0x00080008
+    DCD     0x00080008
+c12000
+    DCD     12000
+c51000
+    DCD     51000
+c0x00070007
+    DCD     0x00070007
+c0x08a914e8
+    DCD     0x08a914e8
+
+    END
diff --git a/vp8/encoder/arm/armv6/vp8_subtract_armv6.asm b/vp8/encoder/arm/armv6/vp8_subtract_armv6.asm
new file mode 100644 (file)
index 0000000..f329f8f
--- /dev/null
@@ -0,0 +1,272 @@
+;
+;  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_subtract_mby_armv6|
+    EXPORT  |vp8_subtract_mbuv_armv6|
+    EXPORT  |vp8_subtract_b_armv6|
+
+    INCLUDE asm_enc_offsets.asm
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    BLOCK *be
+; r1    BLOCKD *bd
+; r2    int pitch
+|vp8_subtract_b_armv6| PROC
+
+    stmfd   sp!, {r4-r9}
+
+    ldr     r4, [r0, #vp8_block_base_src]
+    ldr     r5, [r0, #vp8_block_src]
+    ldr     r6, [r0, #vp8_block_src_diff]
+
+    ldr     r3, [r4]
+    ldr     r7, [r0, #vp8_block_src_stride]
+    add     r3, r3, r5          ; src = *base_src + src
+    ldr     r8, [r1, #vp8_blockd_predictor]
+
+    mov     r9, #4              ; loop count
+
+loop_block
+
+    ldr     r0, [r3], r7        ; src
+    ldr     r1, [r8], r2        ; pred
+
+    uxtb16  r4, r0              ; [s2 | s0]
+    uxtb16  r5, r1              ; [p2 | p0]
+    uxtb16  r0, r0, ror #8      ; [s3 | s1]
+    uxtb16  r1, r1, ror #8      ; [p3 | p1]
+
+    usub16  r4, r4, r5          ; [d2 | d0]
+    usub16  r5, r0, r1          ; [d3 | d1]
+
+    subs    r9, r9, #1          ; decrement loop counter
+
+    pkhbt   r0, r4, r5, lsl #16 ; [d1 | d0]
+    pkhtb   r1, r5, r4, asr #16 ; [d3 | d2]
+
+    str     r0, [r6, #0]        ; diff
+    str     r1, [r6, #4]        ; diff
+
+    add     r6, r6, r2, lsl #1  ; update diff pointer
+    bne     loop_block
+
+    ldmfd   sp!, {r4-r9}
+    mov     pc, lr
+
+    ENDP
+
+
+; r0    short *diff
+; r1    unsigned char *usrc
+; r2    unsigned char *vsrc
+; r3    int src_stride
+; sp    unsigned char *upred
+; sp    unsigned char *vpred
+; sp    int pred_stride
+|vp8_subtract_mbuv_armv6| PROC
+
+    stmfd   sp!, {r4-r11}
+
+    add     r0, r0, #512        ; set *diff point to Cb
+    mov     r4, #8              ; loop count
+    ldr     r5, [sp, #32]       ; upred
+    ldr     r12, [sp, #40]      ; pred_stride
+
+    ; Subtract U block
+loop_u
+    ldr     r6, [r1]            ; usrc      (A)
+    ldr     r7, [r5]            ; upred     (A)
+
+    uxtb16  r8, r6              ; [s2 | s0] (A)
+    uxtb16  r9, r7              ; [p2 | p0] (A)
+    uxtb16  r10, r6, ror #8     ; [s3 | s1] (A)
+    uxtb16  r11, r7, ror #8     ; [p3 | p1] (A)
+
+    usub16  r6, r8, r9          ; [d2 | d0] (A)
+    usub16  r7, r10, r11        ; [d3 | d1] (A)
+
+    ldr     r10, [r1, #4]       ; usrc      (B)
+    ldr     r11, [r5, #4]       ; upred     (B)
+
+    pkhbt   r8, r6, r7, lsl #16 ; [d1 | d0] (A)
+    pkhtb   r9, r7, r6, asr #16 ; [d3 | d2] (A)
+
+    str     r8, [r0], #4        ; diff      (A)
+    uxtb16  r8, r10             ; [s2 | s0] (B)
+    str     r9, [r0], #4        ; diff      (A)
+
+    uxtb16  r9, r11             ; [p2 | p0] (B)
+    uxtb16  r10, r10, ror #8    ; [s3 | s1] (B)
+    uxtb16  r11, r11, ror #8    ; [p3 | p1] (B)
+
+    usub16  r6, r8, r9          ; [d2 | d0] (B)
+    usub16  r7, r10, r11        ; [d3 | d1] (B)
+
+    add     r1, r1, r3          ; update usrc pointer
+    add     r5, r5, r12         ; update upred pointer
+
+    pkhbt   r8, r6, r7, lsl #16 ; [d1 | d0] (B)
+    pkhtb   r9, r7, r6, asr #16 ; [d3 | d2] (B)
+
+    str     r8, [r0], #4        ; diff      (B)
+    subs    r4, r4, #1          ; update loop counter
+    str     r9, [r0], #4        ; diff      (B)
+
+    bne     loop_u
+
+    ldr     r5, [sp, #36]       ; vpred
+    mov     r4, #8              ; loop count
+
+    ; Subtract V block
+loop_v
+    ldr     r6, [r2]            ; vsrc      (A)
+    ldr     r7, [r5]            ; vpred     (A)
+
+    uxtb16  r8, r6              ; [s2 | s0] (A)
+    uxtb16  r9, r7              ; [p2 | p0] (A)
+    uxtb16  r10, r6, ror #8     ; [s3 | s1] (A)
+    uxtb16  r11, r7, ror #8     ; [p3 | p1] (A)
+
+    usub16  r6, r8, r9          ; [d2 | d0] (A)
+    usub16  r7, r10, r11        ; [d3 | d1] (A)
+
+    ldr     r10, [r2, #4]       ; vsrc      (B)
+    ldr     r11, [r5, #4]       ; vpred     (B)
+
+    pkhbt   r8, r6, r7, lsl #16 ; [d1 | d0] (A)
+    pkhtb   r9, r7, r6, asr #16 ; [d3 | d2] (A)
+
+    str     r8, [r0], #4        ; diff      (A)
+    uxtb16  r8, r10             ; [s2 | s0] (B)
+    str     r9, [r0], #4        ; diff      (A)
+
+    uxtb16  r9, r11             ; [p2 | p0] (B)
+    uxtb16  r10, r10, ror #8    ; [s3 | s1] (B)
+    uxtb16  r11, r11, ror #8    ; [p3 | p1] (B)
+
+    usub16  r6, r8, r9          ; [d2 | d0] (B)
+    usub16  r7, r10, r11        ; [d3 | d1] (B)
+
+    add     r2, r2, r3          ; update vsrc pointer
+    add     r5, r5, r12         ; update vpred pointer
+
+    pkhbt   r8, r6, r7, lsl #16 ; [d1 | d0] (B)
+    pkhtb   r9, r7, r6, asr #16 ; [d3 | d2] (B)
+
+    str     r8, [r0], #4        ; diff      (B)
+    subs    r4, r4, #1          ; update loop counter
+    str     r9, [r0], #4        ; diff      (B)
+
+    bne     loop_v
+
+    ldmfd   sp!, {r4-r11}
+    bx      lr
+
+    ENDP
+
+
+; r0    short *diff
+; r1    unsigned char *src
+; r2    int src_stride
+; r3    unsigned char *pred
+; sp    int pred_stride
+|vp8_subtract_mby_armv6| PROC
+
+    stmfd   sp!, {r4-r11}
+    ldr     r12, [sp, #32]      ; pred_stride
+    mov     r4, #16
+loop
+    ldr     r6, [r1]            ; src       (A)
+    ldr     r7, [r3]            ; pred      (A)
+
+    uxtb16  r8, r6              ; [s2 | s0] (A)
+    uxtb16  r9, r7              ; [p2 | p0] (A)
+    uxtb16  r10, r6, ror #8     ; [s3 | s1] (A)
+    uxtb16  r11, r7, ror #8     ; [p3 | p1] (A)
+
+    usub16  r6, r8, r9          ; [d2 | d0] (A)
+    usub16  r7, r10, r11        ; [d3 | d1] (A)
+
+    ldr     r10, [r1, #4]       ; src       (B)
+    ldr     r11, [r3, #4]       ; pred      (B)
+
+    pkhbt   r8, r6, r7, lsl #16 ; [d1 | d0] (A)
+    pkhtb   r9, r7, r6, asr #16 ; [d3 | d2] (A)
+
+    str     r8, [r0], #4        ; diff      (A)
+    uxtb16  r8, r10             ; [s2 | s0] (B)
+    str     r9, [r0], #4        ; diff      (A)
+
+    uxtb16  r9, r11             ; [p2 | p0] (B)
+    uxtb16  r10, r10, ror #8    ; [s3 | s1] (B)
+    uxtb16  r11, r11, ror #8    ; [p3 | p1] (B)
+
+    usub16  r6, r8, r9          ; [d2 | d0] (B)
+    usub16  r7, r10, r11        ; [d3 | d1] (B)
+
+    ldr     r10, [r1, #8]       ; src       (C)
+    ldr     r11, [r3, #8]       ; pred      (C)
+
+    pkhbt   r8, r6, r7, lsl #16 ; [d1 | d0] (B)
+    pkhtb   r9, r7, r6, asr #16 ; [d3 | d2] (B)
+
+    str     r8, [r0], #4        ; diff      (B)
+    uxtb16  r8, r10             ; [s2 | s0] (C)
+    str     r9, [r0], #4        ; diff      (B)
+
+    uxtb16  r9, r11             ; [p2 | p0] (C)
+    uxtb16  r10, r10, ror #8    ; [s3 | s1] (C)
+    uxtb16  r11, r11, ror #8    ; [p3 | p1] (C)
+
+    usub16  r6, r8, r9          ; [d2 | d0] (C)
+    usub16  r7, r10, r11        ; [d3 | d1] (C)
+
+    ldr     r10, [r1, #12]      ; src       (D)
+    ldr     r11, [r3, #12]      ; pred      (D)
+
+    pkhbt   r8, r6, r7, lsl #16 ; [d1 | d0] (C)
+    pkhtb   r9, r7, r6, asr #16 ; [d3 | d2] (C)
+
+    str     r8, [r0], #4        ; diff      (C)
+    uxtb16  r8, r10             ; [s2 | s0] (D)
+    str     r9, [r0], #4        ; diff      (C)
+
+    uxtb16  r9, r11             ; [p2 | p0] (D)
+    uxtb16  r10, r10, ror #8    ; [s3 | s1] (D)
+    uxtb16  r11, r11, ror #8    ; [p3 | p1] (D)
+
+    usub16  r6, r8, r9          ; [d2 | d0] (D)
+    usub16  r7, r10, r11        ; [d3 | d1] (D)
+
+    add     r1, r1, r2          ; update src pointer
+    add     r3, r3, r12         ; update pred pointer
+
+    pkhbt   r8, r6, r7, lsl #16 ; [d1 | d0] (D)
+    pkhtb   r9, r7, r6, asr #16 ; [d3 | d2] (D)
+
+    str     r8, [r0], #4        ; diff      (D)
+    subs    r4, r4, #1          ; update loop counter
+    str     r9, [r0], #4        ; diff      (D)
+
+    bne     loop
+
+    ldmfd   sp!, {r4-r11}
+    bx      lr
+
+    ENDP
+
+    END
+
diff --git a/vp8/encoder/arm/armv6/walsh_v6.asm b/vp8/encoder/arm/armv6/walsh_v6.asm
new file mode 100644 (file)
index 0000000..5eaf3f2
--- /dev/null
@@ -0,0 +1,212 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+    EXPORT |vp8_short_walsh4x4_armv6|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+
+;short vp8_short_walsh4x4_armv6(short *input, short *output, int pitch)
+; r0    short *input,
+; r1    short *output,
+; r2    int pitch
+|vp8_short_walsh4x4_armv6| PROC
+
+    stmdb       sp!, {r4 - r11, lr}
+
+    ldrd        r4, r5, [r0], r2
+    ldr         lr, c00040004
+    ldrd        r6, r7, [r0], r2
+
+    ; 0-3
+    qadd16      r3, r4, r5          ; [d1|a1] [1+3   |   0+2]
+    qsub16      r4, r4, r5          ; [c1|b1] [1-3   |   0-2]
+
+    ldrd        r8, r9, [r0], r2
+    ; 4-7
+    qadd16      r5, r6, r7          ; [d1|a1] [5+7   |   4+6]
+    qsub16      r6, r6, r7          ; [c1|b1] [5-7   |   4-6]
+
+    ldrd        r10, r11, [r0]
+    ; 8-11
+    qadd16      r7, r8, r9          ; [d1|a1] [9+11  |  8+10]
+    qsub16      r8, r8, r9          ; [c1|b1] [9-11  |  8-10]
+
+    ; 12-15
+    qadd16      r9, r10, r11        ; [d1|a1] [13+15 | 12+14]
+    qsub16      r10, r10, r11       ; [c1|b1] [13-15 | 12-14]
+
+
+    lsls        r2, r3, #16
+    smuad       r11, r3, lr         ; A0 = a1<<2 + d1<<2
+    addne       r11, r11, #1        ; A0 += (a1!=0)
+
+    lsls        r2, r7, #16
+    smuad       r12, r7, lr         ; C0 = a1<<2 + d1<<2
+    addne       r12, r12, #1        ; C0 += (a1!=0)
+
+    add         r0, r11, r12        ; a1_0 = A0 + C0
+    sub         r11, r11, r12       ; b1_0 = A0 - C0
+
+    lsls        r2, r5, #16
+    smuad       r12, r5, lr         ; B0 = a1<<2 + d1<<2
+    addne       r12, r12, #1        ; B0 += (a1!=0)
+
+    lsls        r2, r9, #16
+    smuad       r2, r9, lr          ; D0 = a1<<2 + d1<<2
+    addne       r2, r2, #1          ; D0 += (a1!=0)
+
+    add         lr, r12, r2         ; d1_0 = B0 + D0
+    sub         r12, r12, r2        ; c1_0 = B0 - D0
+
+    ; op[0,4,8,12]
+    adds        r2, r0, lr          ; a2 = a1_0 + d1_0
+    addmi       r2, r2, #1          ; += a2 < 0
+    add         r2, r2, #3          ; += 3
+    subs        r0, r0, lr          ; d2 = a1_0 - d1_0
+    mov         r2, r2, asr #3      ; >> 3
+    strh        r2, [r1]            ; op[0]
+
+    addmi       r0, r0, #1          ; += a2 < 0
+    add         r0, r0, #3          ; += 3
+    ldr         lr, c00040004
+    mov         r0, r0, asr #3      ; >> 3
+    strh        r0, [r1, #24]       ; op[12]
+
+    adds        r2, r11, r12        ; b2 = b1_0 + c1_0
+    addmi       r2, r2, #1          ; += a2 < 0
+    add         r2, r2, #3          ; += 3
+    subs        r0, r11, r12        ; c2 = b1_0 - c1_0
+    mov         r2, r2, asr #3      ; >> 3
+    strh        r2, [r1, #8]        ; op[4]
+
+    addmi       r0, r0, #1          ; += a2 < 0
+    add         r0, r0, #3          ; += 3
+    smusd       r3, r3, lr          ; A3 = a1<<2 - d1<<2
+    smusd       r7, r7, lr          ; C3 = a1<<2 - d1<<2
+    mov         r0, r0, asr #3      ; >> 3
+    strh        r0, [r1, #16]       ; op[8]
+
+
+    ; op[3,7,11,15]
+    add         r0, r3, r7          ; a1_3 = A3 + C3
+    sub         r3, r3, r7          ; b1_3 = A3 - C3
+
+    smusd       r5, r5, lr          ; B3 = a1<<2 - d1<<2
+    smusd       r9, r9, lr          ; D3 = a1<<2 - d1<<2
+    add         r7, r5, r9          ; d1_3 = B3 + D3
+    sub         r5, r5, r9          ; c1_3 = B3 - D3
+
+    adds        r2, r0, r7          ; a2 = a1_3 + d1_3
+    addmi       r2, r2, #1          ; += a2 < 0
+    add         r2, r2, #3          ; += 3
+    adds        r9, r3, r5          ; b2 = b1_3 + c1_3
+    mov         r2, r2, asr #3      ; >> 3
+    strh        r2, [r1, #6]        ; op[3]
+
+    addmi       r9, r9, #1          ; += a2 < 0
+    add         r9, r9, #3          ; += 3
+    subs        r2, r3, r5          ; c2 = b1_3 - c1_3
+    mov         r9, r9, asr #3      ; >> 3
+    strh        r9, [r1, #14]       ; op[7]
+
+    addmi       r2, r2, #1          ; += a2 < 0
+    add         r2, r2, #3          ; += 3
+    subs        r9, r0, r7          ; d2 = a1_3 - d1_3
+    mov         r2, r2, asr #3      ; >> 3
+    strh        r2, [r1, #22]       ; op[11]
+
+    addmi       r9, r9, #1          ; += a2 < 0
+    add         r9, r9, #3          ; += 3
+    smuad       r3, r4, lr          ; A1 = b1<<2 + c1<<2
+    smuad       r5, r8, lr          ; C1 = b1<<2 + c1<<2
+    mov         r9, r9, asr #3      ; >> 3
+    strh        r9, [r1, #30]       ; op[15]
+
+    ; op[1,5,9,13]
+    add         r0, r3, r5          ; a1_1 = A1 + C1
+    sub         r3, r3, r5          ; b1_1 = A1 - C1
+
+    smuad       r7, r6, lr          ; B1 = b1<<2 + c1<<2
+    smuad       r9, r10, lr         ; D1 = b1<<2 + c1<<2
+    add         r5, r7, r9          ; d1_1 = B1 + D1
+    sub         r7, r7, r9          ; c1_1 = B1 - D1
+
+    adds        r2, r0, r5          ; a2 = a1_1 + d1_1
+    addmi       r2, r2, #1          ; += a2 < 0
+    add         r2, r2, #3          ; += 3
+    adds        r9, r3, r7          ; b2 = b1_1 + c1_1
+    mov         r2, r2, asr #3      ; >> 3
+    strh        r2, [r1, #2]        ; op[1]
+
+    addmi       r9, r9, #1          ; += a2 < 0
+    add         r9, r9, #3          ; += 3
+    subs        r2, r3, r7          ; c2 = b1_1 - c1_1
+    mov         r9, r9, asr #3      ; >> 3
+    strh        r9, [r1, #10]       ; op[5]
+
+    addmi       r2, r2, #1          ; += a2 < 0
+    add         r2, r2, #3          ; += 3
+    subs        r9, r0, r5          ; d2 = a1_1 - d1_1
+    mov         r2, r2, asr #3      ; >> 3
+    strh        r2, [r1, #18]       ; op[9]
+
+    addmi       r9, r9, #1          ; += a2 < 0
+    add         r9, r9, #3          ; += 3
+    smusd       r4, r4, lr          ; A2 = b1<<2 - c1<<2
+    smusd       r8, r8, lr          ; C2 = b1<<2 - c1<<2
+    mov         r9, r9, asr #3      ; >> 3
+    strh        r9, [r1, #26]       ; op[13]
+
+
+    ; op[2,6,10,14]
+    add         r11, r4, r8         ; a1_2 = A2 + C2
+    sub         r12, r4, r8         ; b1_2 = A2 - C2
+
+    smusd       r6, r6, lr          ; B2 = b1<<2 - c1<<2
+    smusd       r10, r10, lr        ; D2 = b1<<2 - c1<<2
+    add         r4, r6, r10         ; d1_2 = B2 + D2
+    sub         r8, r6, r10         ; c1_2 = B2 - D2
+
+    adds        r2, r11, r4         ; a2 = a1_2 + d1_2
+    addmi       r2, r2, #1          ; += a2 < 0
+    add         r2, r2, #3          ; += 3
+    adds        r9, r12, r8         ; b2 = b1_2 + c1_2
+    mov         r2, r2, asr #3      ; >> 3
+    strh        r2, [r1, #4]        ; op[2]
+
+    addmi       r9, r9, #1          ; += a2 < 0
+    add         r9, r9, #3          ; += 3
+    subs        r2, r12, r8         ; c2 = b1_2 - c1_2
+    mov         r9, r9, asr #3      ; >> 3
+    strh        r9, [r1, #12]       ; op[6]
+
+    addmi       r2, r2, #1          ; += a2 < 0
+    add         r2, r2, #3          ; += 3
+    subs        r9, r11, r4         ; d2 = a1_2 - d1_2
+    mov         r2, r2, asr #3      ; >> 3
+    strh        r2, [r1, #20]       ; op[10]
+
+    addmi       r9, r9, #1          ; += a2 < 0
+    add         r9, r9, #3          ; += 3
+    mov         r9, r9, asr #3      ; >> 3
+    strh        r9, [r1, #28]       ; op[14]
+
+
+    ldmia       sp!, {r4 - r11, pc}
+    ENDP        ; |vp8_short_walsh4x4_armv6|
+
+c00040004
+    DCD         0x00040004
+
+    END
diff --git a/vp8/encoder/arm/boolhuff_arm.c b/vp8/encoder/arm/boolhuff_arm.c
new file mode 100644 (file)
index 0000000..17a941b
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vp8/encoder/boolhuff.h"
+#include "vpx/internal/vpx_codec_internal.h"
+
+const unsigned int vp8_prob_cost[256] =
+{
+    2047, 2047, 1791, 1641, 1535, 1452, 1385, 1328, 1279, 1235, 1196, 1161, 1129, 1099, 1072, 1046,
+    1023, 1000,  979,  959,  940,  922,  905,  889,  873,  858,  843,  829,  816,  803,  790,  778,
+    767,  755,  744,  733,  723,  713,  703,  693,  684,  675,  666,  657,  649,  641,  633,  625,
+    617,  609,  602,  594,  587,  580,  573,  567,  560,  553,  547,  541,  534,  528,  522,  516,
+    511,  505,  499,  494,  488,  483,  477,  472,  467,  462,  457,  452,  447,  442,  437,  433,
+    428,  424,  419,  415,  410,  406,  401,  397,  393,  389,  385,  381,  377,  373,  369,  365,
+    361,  357,  353,  349,  346,  342,  338,  335,  331,  328,  324,  321,  317,  314,  311,  307,
+    304,  301,  297,  294,  291,  288,  285,  281,  278,  275,  272,  269,  266,  263,  260,  257,
+    255,  252,  249,  246,  243,  240,  238,  235,  232,  229,  227,  224,  221,  219,  216,  214,
+    211,  208,  206,  203,  201,  198,  196,  194,  191,  189,  186,  184,  181,  179,  177,  174,
+    172,  170,  168,  165,  163,  161,  159,  156,  154,  152,  150,  148,  145,  143,  141,  139,
+    137,  135,  133,  131,  129,  127,  125,  123,  121,  119,  117,  115,  113,  111,  109,  107,
+    105,  103,  101,   99,   97,   95,   93,   92,   90,   88,   86,   84,   82,   81,   79,   77,
+    75,   73,   72,   70,   68,   66,   65,   63,   61,   60,   58,   56,   55,   53,   51,   50,
+    48,   46,   45,   43,   41,   40,   38,   37,   35,   33,   32,   30,   29,   27,   25,   24,
+    22,   21,   19,   18,   16,   15,   13,   12,   10,    9,    7,    6,    4,    3,    1,   1
+};
+
+int vp8_validate_buffer_arm(const unsigned char *start,
+                            size_t               len,
+                            const unsigned char *end,
+                            struct vpx_internal_error_info *error)
+{
+    return validate_buffer(start, len, end, error);
+}
diff --git a/vp8/encoder/arm/dct_arm.c b/vp8/encoder/arm/dct_arm.c
new file mode 100644 (file)
index 0000000..af0fb27
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+
+#if HAVE_MEDIA
+
+void vp8_short_fdct8x4_armv6(short *input, short *output, int pitch)
+{
+    vp8_short_fdct4x4_armv6(input,   output,    pitch);
+    vp8_short_fdct4x4_armv6(input + 4, output + 16, pitch);
+}
+
+#endif /* HAVE_MEDIA */
diff --git a/vp8/encoder/arm/neon/fastquantizeb_neon.asm b/vp8/encoder/arm/neon/fastquantizeb_neon.asm
new file mode 100644 (file)
index 0000000..1430588
--- /dev/null
@@ -0,0 +1,258 @@
+;
+;  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_fast_quantize_b_neon|
+    EXPORT  |vp8_fast_quantize_b_pair_neon|
+
+    INCLUDE asm_enc_offsets.asm
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=4
+
+;vp8_fast_quantize_b_pair_neon(BLOCK *b1, BLOCK *b2, BLOCKD *d1, BLOCKD *d2);
+|vp8_fast_quantize_b_pair_neon| PROC
+
+    stmfd           sp!, {r4-r9}
+    vstmdb          sp!, {q4-q7}
+
+    ldr             r4, [r0, #vp8_block_coeff]
+    ldr             r5, [r0, #vp8_block_quant_fast]
+    ldr             r6, [r0, #vp8_block_round]
+
+    vld1.16         {q0, q1}, [r4@128]  ; load z
+
+    ldr             r7, [r2, #vp8_blockd_qcoeff]
+
+    vabs.s16        q4, q0              ; calculate x = abs(z)
+    vabs.s16        q5, q1
+
+    ;right shift 15 to get sign, all 0 if it is positive, all 1 if it is negative
+    vshr.s16        q2, q0, #15         ; sz
+    vshr.s16        q3, q1, #15
+
+    vld1.s16        {q6, q7}, [r6@128]  ; load round_ptr [0-15]
+    vld1.s16        {q8, q9}, [r5@128]  ; load quant_ptr [0-15]
+
+    ldr             r4, [r1, #vp8_block_coeff]
+
+    vadd.s16        q4, q6              ; x + Round
+    vadd.s16        q5, q7
+
+    vld1.16         {q0, q1}, [r4@128]  ; load z2
+
+    vqdmulh.s16     q4, q8              ; y = ((Round+abs(z)) * Quant) >> 16
+    vqdmulh.s16     q5, q9
+
+    vabs.s16        q10, q0             ; calculate x2 = abs(z_2)
+    vabs.s16        q11, q1
+    vshr.s16        q12, q0, #15        ; sz2
+    vshr.s16        q13, q1, #15
+
+    ;modify data to have its original sign
+    veor.s16        q4, q2              ; y^sz
+    veor.s16        q5, q3
+
+    vadd.s16        q10, q6             ; x2 + Round
+    vadd.s16        q11, q7
+
+    ldr             r8, [r2, #vp8_blockd_dequant]
+
+    vqdmulh.s16     q10, q8             ; y2 = ((Round+abs(z)) * Quant) >> 16
+    vqdmulh.s16     q11, q9
+
+    vshr.s16        q4, #1              ; right shift 1 after vqdmulh
+    vshr.s16        q5, #1
+
+    vld1.s16        {q6, q7}, [r8@128]  ;load dequant_ptr[i]
+
+    vsub.s16        q4, q2              ; x1=(y^sz)-sz = (y^sz)-(-1) (2's complement)
+    vsub.s16        q5, q3
+
+    vshr.s16        q10, #1             ; right shift 1 after vqdmulh
+    vshr.s16        q11, #1
+
+    ldr             r9, [r2, #vp8_blockd_dqcoeff]
+
+    veor.s16        q10, q12            ; y2^sz2
+    veor.s16        q11, q13
+
+    vst1.s16        {q4, q5}, [r7]      ; store: qcoeff = x1
+
+
+    vsub.s16        q10, q12            ; x2=(y^sz)-sz = (y^sz)-(-1) (2's complement)
+    vsub.s16        q11, q13
+
+    ldr             r6, [r3, #vp8_blockd_qcoeff]
+
+    vmul.s16        q2, q6, q4          ; x * Dequant
+    vmul.s16        q3, q7, q5
+
+    adr             r0, inv_zig_zag     ; load ptr of inverse zigzag table
+
+    vceq.s16        q8, q8              ; set q8 to all 1
+
+    vst1.s16        {q10, q11}, [r6]    ; store: qcoeff = x2
+
+    vmul.s16        q12, q6, q10        ; x2 * Dequant
+    vmul.s16        q13, q7, q11
+
+    vld1.16         {q6, q7}, [r0@128]  ; load inverse scan order
+
+    vtst.16         q14, q4, q8         ; now find eob
+    vtst.16         q15, q5, q8         ; non-zero element is set to all 1
+
+    vst1.s16        {q2, q3}, [r9]      ; store dqcoeff = x * Dequant
+
+    ldr             r7, [r3, #vp8_blockd_dqcoeff]
+
+    vand            q0, q6, q14         ; get all valid numbers from scan array
+    vand            q1, q7, q15
+
+    vst1.s16        {q12, q13}, [r7]    ; store dqcoeff = x * Dequant
+
+    vtst.16         q2, q10, q8         ; now find eob
+    vtst.16         q3, q11, q8         ; non-zero element is set to all 1
+
+    vmax.u16        q0, q0, q1          ; find maximum value in q0, q1
+
+    vand            q10, q6, q2         ; get all valid numbers from scan array
+    vand            q11, q7, q3
+    vmax.u16        q10, q10, q11       ; find maximum value in q10, q11
+
+    vmax.u16        d0, d0, d1
+    vmax.u16        d20, d20, d21
+    vmovl.u16       q0, d0
+    vmovl.u16       q10, d20
+
+    vmax.u32        d0, d0, d1
+    vmax.u32        d20, d20, d21
+    vpmax.u32       d0, d0, d0
+    vpmax.u32       d20, d20, d20
+
+    ldr             r4, [r2, #vp8_blockd_eob]
+    ldr             r5, [r3, #vp8_blockd_eob]
+
+    vst1.8          {d0[0]}, [r4]       ; store eob
+    vst1.8          {d20[0]}, [r5]      ; store eob
+
+    vldmia          sp!, {q4-q7}
+    ldmfd           sp!, {r4-r9}
+    bx              lr
+
+    ENDP
+
+;void vp8_fast_quantize_b_c(BLOCK *b, BLOCKD *d)
+|vp8_fast_quantize_b_neon| PROC
+
+    stmfd           sp!, {r4-r7}
+
+    ldr             r3, [r0, #vp8_block_coeff]
+    ldr             r4, [r0, #vp8_block_quant_fast]
+    ldr             r5, [r0, #vp8_block_round]
+
+    vld1.16         {q0, q1}, [r3@128]  ; load z
+    vorr.s16        q14, q0, q1         ; check if all zero (step 1)
+    ldr             r6, [r1, #vp8_blockd_qcoeff]
+    ldr             r7, [r1, #vp8_blockd_dqcoeff]
+    vorr.s16        d28, d28, d29       ; check if all zero (step 2)
+
+    vabs.s16        q12, q0             ; calculate x = abs(z)
+    vabs.s16        q13, q1
+
+    ;right shift 15 to get sign, all 0 if it is positive, all 1 if it is negative
+    vshr.s16        q2, q0, #15         ; sz
+    vmov            r2, r3, d28         ; check if all zero (step 3)
+    vshr.s16        q3, q1, #15
+
+    vld1.s16        {q14, q15}, [r5@128]; load round_ptr [0-15]
+    vld1.s16        {q8, q9}, [r4@128]  ; load quant_ptr [0-15]
+
+    vadd.s16        q12, q14            ; x + Round
+    vadd.s16        q13, q15
+
+    adr             r0, inv_zig_zag     ; load ptr of inverse zigzag table
+
+    vqdmulh.s16     q12, q8             ; y = ((Round+abs(z)) * Quant) >> 16
+    vqdmulh.s16     q13, q9
+
+    vld1.16         {q10, q11}, [r0@128]; load inverse scan order
+
+    vceq.s16        q8, q8              ; set q8 to all 1
+
+    ldr             r4, [r1, #vp8_blockd_dequant]
+
+    vshr.s16        q12, #1             ; right shift 1 after vqdmulh
+    vshr.s16        q13, #1
+
+    ldr             r5, [r1, #vp8_blockd_eob]
+
+    orr             r2, r2, r3          ; check if all zero (step 4)
+    cmp             r2, #0              ; check if all zero (step 5)
+    beq             zero_output         ; check if all zero (step 6)
+
+    ;modify data to have its original sign
+    veor.s16        q12, q2             ; y^sz
+    veor.s16        q13, q3
+
+    vsub.s16        q12, q2             ; x1=(y^sz)-sz = (y^sz)-(-1) (2's complement)
+    vsub.s16        q13, q3
+
+    vld1.s16        {q2, q3}, [r4@128]  ; load dequant_ptr[i]
+
+    vtst.16         q14, q12, q8        ; now find eob
+    vtst.16         q15, q13, q8        ; non-zero element is set to all 1
+
+    vst1.s16        {q12, q13}, [r6@128]; store: qcoeff = x1
+
+    vand            q10, q10, q14       ; get all valid numbers from scan array
+    vand            q11, q11, q15
+
+
+    vmax.u16        q0, q10, q11        ; find maximum value in q0, q1
+    vmax.u16        d0, d0, d1
+    vmovl.u16       q0, d0
+
+    vmul.s16        q2, q12             ; x * Dequant
+    vmul.s16        q3, q13
+
+    vmax.u32        d0, d0, d1
+    vpmax.u32       d0, d0, d0
+
+    vst1.s16        {q2, q3}, [r7@128]  ; store dqcoeff = x * Dequant
+
+    vst1.8          {d0[0]}, [r5]       ; store eob
+
+    ldmfd           sp!, {r4-r7}
+    bx              lr
+
+zero_output
+    strb            r2, [r5]            ; store eob
+    vst1.s16        {q0, q1}, [r6@128]  ; qcoeff = 0
+    vst1.s16        {q0, q1}, [r7@128]  ; dqcoeff = 0
+
+    ldmfd           sp!, {r4-r7}
+    bx              lr
+
+    ENDP
+
+; default inverse zigzag table is defined in vp8/common/entropy.c
+    ALIGN 16    ; enable use of @128 bit aligned loads
+inv_zig_zag
+    DCW 0x0001, 0x0002, 0x0006, 0x0007
+    DCW 0x0003, 0x0005, 0x0008, 0x000d
+    DCW 0x0004, 0x0009, 0x000c, 0x000e
+    DCW 0x000a, 0x000b, 0x000f, 0x0010
+
+    END
+
diff --git a/vp8/encoder/arm/neon/picklpf_arm.c b/vp8/encoder/arm/neon/picklpf_arm.c
new file mode 100644 (file)
index 0000000..ec8071e
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "vp8/common/loopfilter.h"
+#include "vpx_scale/yv12config.h"
+
+extern void vp8_memcpy_partial_neon(unsigned char *dst_ptr,
+                                    unsigned char *src_ptr,
+                                    int sz);
+
+
+void vp8_yv12_copy_partial_frame_neon(YV12_BUFFER_CONFIG *src_ybc,
+                                      YV12_BUFFER_CONFIG *dst_ybc)
+{
+    unsigned char *src_y, *dst_y;
+    int yheight;
+    int ystride;
+    int yoffset;
+    int linestocopy;
+
+    yheight  = src_ybc->y_height;
+    ystride  = src_ybc->y_stride;
+
+    /* number of MB rows to use in partial filtering */
+    linestocopy = (yheight >> 4) / PARTIAL_FRAME_FRACTION;
+    linestocopy = linestocopy ? linestocopy << 4 : 16;     /* 16 lines per MB */
+
+    /* Copy extra 4 so that full filter context is available if filtering done
+     * on the copied partial frame and not original. Partial filter does mb
+     * filtering for top row also, which can modify3 pixels above.
+     */
+    linestocopy += 4;
+    /* partial image starts at ~middle of frame (macroblock border) */
+    yoffset  = ystride * (((yheight >> 5) * 16) - 4);
+    src_y = src_ybc->y_buffer + yoffset;
+    dst_y = dst_ybc->y_buffer + yoffset;
+
+    vp8_memcpy_partial_neon(dst_y, src_y, ystride * linestocopy);
+}
diff --git a/vp8/encoder/arm/neon/shortfdct_neon.asm b/vp8/encoder/arm/neon/shortfdct_neon.asm
new file mode 100644 (file)
index 0000000..09dd011
--- /dev/null
@@ -0,0 +1,221 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_short_fdct4x4_neon|
+    EXPORT  |vp8_short_fdct8x4_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=4
+
+
+    ALIGN 16    ; enable use of @128 bit aligned loads
+coeff
+    DCW      5352,  5352,  5352, 5352
+    DCW      2217,  2217,  2217, 2217
+    DCD     14500, 14500, 14500, 14500
+    DCD      7500,  7500,  7500, 7500
+    DCD     12000, 12000, 12000, 12000
+    DCD     51000, 51000, 51000, 51000
+
+;void vp8_short_fdct4x4_c(short *input, short *output, int pitch)
+|vp8_short_fdct4x4_neon| PROC
+
+    ; Part one
+    vld1.16         {d0}, [r0@64], r2
+    adr             r12, coeff
+    vld1.16         {d1}, [r0@64], r2
+    vld1.16         {q8}, [r12@128]!        ; d16=5352,  d17=2217
+    vld1.16         {d2}, [r0@64], r2
+    vld1.32         {q9, q10}, [r12@128]!   ;  q9=14500, q10=7500
+    vld1.16         {d3}, [r0@64], r2
+
+    ; transpose d0=ip[0], d1=ip[1], d2=ip[2], d3=ip[3]
+    vtrn.32         d0, d2
+    vtrn.32         d1, d3
+    vld1.32         {q11,q12}, [r12@128]    ; q11=12000, q12=51000
+    vtrn.16         d0, d1
+    vtrn.16         d2, d3
+
+    vadd.s16        d4, d0, d3      ; a1 = ip[0] + ip[3]
+    vadd.s16        d5, d1, d2      ; b1 = ip[1] + ip[2]
+    vsub.s16        d6, d1, d2      ; c1 = ip[1] - ip[2]
+    vsub.s16        d7, d0, d3      ; d1 = ip[0] - ip[3]
+
+    vshl.s16        q2, q2, #3      ; (a1, b1) << 3
+    vshl.s16        q3, q3, #3      ; (c1, d1) << 3
+
+    vadd.s16        d0, d4, d5      ; op[0] = a1 + b1
+    vsub.s16        d2, d4, d5      ; op[2] = a1 - b1
+
+    vmlal.s16       q9, d7, d16     ; d1*5352 + 14500
+    vmlal.s16       q10, d7, d17    ; d1*2217 + 7500
+    vmlal.s16       q9, d6, d17     ; c1*2217 + d1*5352 + 14500
+    vmlsl.s16       q10, d6, d16    ; d1*2217 - c1*5352 + 7500
+
+    vshrn.s32       d1, q9, #12     ; op[1] = (c1*2217 + d1*5352 + 14500)>>12
+    vshrn.s32       d3, q10, #12    ; op[3] = (d1*2217 - c1*5352 +  7500)>>12
+
+
+    ; Part two
+
+    ; transpose d0=ip[0], d1=ip[4], d2=ip[8], d3=ip[12]
+    vtrn.32         d0, d2
+    vtrn.32         d1, d3
+    vtrn.16         d0, d1
+    vtrn.16         d2, d3
+
+    vmov.s16        d26, #7
+
+    vadd.s16        d4, d0, d3      ; a1 = ip[0] + ip[12]
+    vadd.s16        d5, d1, d2      ; b1 = ip[4] + ip[8]
+    vsub.s16        d6, d1, d2      ; c1 = ip[4] - ip[8]
+    vadd.s16        d4, d4, d26     ; a1 + 7
+    vsub.s16        d7, d0, d3      ; d1 = ip[0] - ip[12]
+
+    vadd.s16        d0, d4, d5      ; op[0] = a1 + b1 + 7
+    vsub.s16        d2, d4, d5      ; op[8] = a1 - b1 + 7
+
+    vmlal.s16       q11, d7, d16    ; d1*5352 + 12000
+    vmlal.s16       q12, d7, d17    ; d1*2217 + 51000
+
+    vceq.s16        d4, d7, #0
+
+    vshr.s16        d0, d0, #4
+    vshr.s16        d2, d2, #4
+
+    vmlal.s16       q11, d6, d17    ; c1*2217 + d1*5352 + 12000
+    vmlsl.s16       q12, d6, d16    ; d1*2217 - c1*5352 + 51000
+
+    vmvn.s16        d4, d4
+    vshrn.s32       d1, q11, #16    ; op[4] = (c1*2217 + d1*5352 + 12000)>>16
+    vsub.s16        d1, d1, d4      ; op[4] += (d1!=0)
+    vshrn.s32       d3, q12, #16    ; op[12]= (d1*2217 - c1*5352 + 51000)>>16
+
+    vst1.16         {q0, q1}, [r1@128]
+
+    bx              lr
+
+    ENDP
+
+;void vp8_short_fdct8x4_c(short *input, short *output, int pitch)
+|vp8_short_fdct8x4_neon| PROC
+
+    ; Part one
+
+    vld1.16         {q0}, [r0@128], r2
+    adr             r12, coeff
+    vld1.16         {q1}, [r0@128], r2
+    vld1.16         {q8}, [r12@128]!        ; d16=5352,  d17=2217
+    vld1.16         {q2}, [r0@128], r2
+    vld1.32         {q9, q10}, [r12@128]!   ;  q9=14500, q10=7500
+    vld1.16         {q3}, [r0@128], r2
+
+    ; transpose q0=ip[0], q1=ip[1], q2=ip[2], q3=ip[3]
+    vtrn.32         q0, q2          ; [A0|B0]
+    vtrn.32         q1, q3          ; [A1|B1]
+    vtrn.16         q0, q1          ; [A2|B2]
+    vtrn.16         q2, q3          ; [A3|B3]
+
+    vadd.s16        q11, q0, q3     ; a1 = ip[0] + ip[3]
+    vadd.s16        q12, q1, q2     ; b1 = ip[1] + ip[2]
+    vsub.s16        q13, q1, q2     ; c1 = ip[1] - ip[2]
+    vsub.s16        q14, q0, q3     ; d1 = ip[0] - ip[3]
+
+    vshl.s16        q11, q11, #3    ; a1 << 3
+    vshl.s16        q12, q12, #3    ; b1 << 3
+    vshl.s16        q13, q13, #3    ; c1 << 3
+    vshl.s16        q14, q14, #3    ; d1 << 3
+
+    vadd.s16        q0, q11, q12    ; [A0 | B0] = a1 + b1
+    vsub.s16        q2, q11, q12    ; [A2 | B2] = a1 - b1
+
+    vmov.s16        q11, q9         ; 14500
+    vmov.s16        q12, q10        ; 7500
+
+    vmlal.s16       q9, d28, d16    ; A[1] = d1*5352 + 14500
+    vmlal.s16       q10, d28, d17   ; A[3] = d1*2217 + 7500
+    vmlal.s16       q11, d29, d16   ; B[1] = d1*5352 + 14500
+    vmlal.s16       q12, d29, d17   ; B[3] = d1*2217 + 7500
+
+    vmlal.s16       q9, d26, d17    ; A[1] = c1*2217 + d1*5352 + 14500
+    vmlsl.s16       q10, d26, d16   ; A[3] = d1*2217 - c1*5352 + 7500
+    vmlal.s16       q11, d27, d17   ; B[1] = c1*2217 + d1*5352 + 14500
+    vmlsl.s16       q12, d27, d16   ; B[3] = d1*2217 - c1*5352 + 7500
+
+    vshrn.s32       d2, q9, #12     ; A[1] = (c1*2217 + d1*5352 + 14500)>>12
+    vshrn.s32       d6, q10, #12    ; A[3] = (d1*2217 - c1*5352 +  7500)>>12
+    vshrn.s32       d3, q11, #12    ; B[1] = (c1*2217 + d1*5352 + 14500)>>12
+    vshrn.s32       d7, q12, #12    ; B[3] = (d1*2217 - c1*5352 +  7500)>>12
+
+
+    ; Part two
+    vld1.32         {q9,q10}, [r12@128]    ; q9=12000, q10=51000
+
+    ; transpose q0=ip[0], q1=ip[4], q2=ip[8], q3=ip[12]
+    vtrn.32         q0, q2          ; q0=[A0 | B0]
+    vtrn.32         q1, q3          ; q1=[A4 | B4]
+    vtrn.16         q0, q1          ; q2=[A8 | B8]
+    vtrn.16         q2, q3          ; q3=[A12|B12]
+
+    vmov.s16        q15, #7
+
+    vadd.s16        q11, q0, q3     ; a1 = ip[0] + ip[12]
+    vadd.s16        q12, q1, q2     ; b1 = ip[4] + ip[8]
+    vadd.s16        q11, q11, q15   ; a1 + 7
+    vsub.s16        q13, q1, q2     ; c1 = ip[4] - ip[8]
+    vsub.s16        q14, q0, q3     ; d1 = ip[0] - ip[12]
+
+    vadd.s16        q0, q11, q12    ; a1 + b1 + 7
+    vsub.s16        q1, q11, q12    ; a1 - b1 + 7
+
+    vmov.s16        q11, q9         ; 12000
+    vmov.s16        q12, q10        ; 51000
+
+    vshr.s16        d0, d0, #4      ; A[0] = (a1 + b1 + 7)>>4
+    vshr.s16        d4, d1, #4      ; B[0] = (a1 + b1 + 7)>>4
+    vshr.s16        d2, d2, #4      ; A[8] = (a1 + b1 + 7)>>4
+    vshr.s16        d6, d3, #4      ; B[8] = (a1 + b1 + 7)>>4
+
+
+    vmlal.s16       q9, d28, d16    ; A[4]  = d1*5352 + 12000
+    vmlal.s16       q10, d28, d17   ; A[12] = d1*2217 + 51000
+    vmlal.s16       q11, d29, d16   ; B[4]  = d1*5352 + 12000
+    vmlal.s16       q12, d29, d17   ; B[12] = d1*2217 + 51000
+
+    vceq.s16        q14, q14, #0
+
+    vmlal.s16       q9, d26, d17    ; A[4]  = c1*2217 + d1*5352 + 12000
+    vmlsl.s16       q10, d26, d16   ; A[12] = d1*2217 - c1*5352 + 51000
+    vmlal.s16       q11, d27, d17   ; B[4]  = c1*2217 + d1*5352 + 12000
+    vmlsl.s16       q12, d27, d16   ; B[12] = d1*2217 - c1*5352 + 51000
+
+    vmvn.s16        q14, q14
+
+    vshrn.s32       d1, q9, #16     ; A[4] = (c1*2217 + d1*5352 + 12000)>>16
+    vshrn.s32       d3, q10, #16    ; A[12]= (d1*2217 - c1*5352 + 51000)>>16
+    vsub.s16        d1, d1, d28     ; A[4] += (d1!=0)
+
+    vshrn.s32       d5, q11, #16    ; B[4] = (c1*2217 + d1*5352 + 12000)>>16
+    vshrn.s32       d7, q12, #16    ; B[12]= (d1*2217 - c1*5352 + 51000)>>16
+    vsub.s16        d5, d5, d29     ; B[4] += (d1!=0)
+
+    vst1.16         {q0, q1}, [r1@128]! ; block A
+    vst1.16         {q2, q3}, [r1@128]! ; block B
+
+    bx              lr
+
+    ENDP
+
+    END
+
diff --git a/vp8/encoder/arm/neon/subtract_neon.asm b/vp8/encoder/arm/neon/subtract_neon.asm
new file mode 100644 (file)
index 0000000..91a328c
--- /dev/null
@@ -0,0 +1,199 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+    EXPORT |vp8_subtract_b_neon|
+    EXPORT |vp8_subtract_mby_neon|
+    EXPORT |vp8_subtract_mbuv_neon|
+
+    INCLUDE asm_enc_offsets.asm
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+;void vp8_subtract_b_neon(BLOCK *be, BLOCKD *bd, int pitch)
+|vp8_subtract_b_neon| PROC
+
+    stmfd   sp!, {r4-r7}
+
+    ldr     r3, [r0, #vp8_block_base_src]
+    ldr     r4, [r0, #vp8_block_src]
+    ldr     r5, [r0, #vp8_block_src_diff]
+    ldr     r3, [r3]
+    ldr     r6, [r0, #vp8_block_src_stride]
+    add     r3, r3, r4                      ; src = *base_src + src
+    ldr     r7, [r1, #vp8_blockd_predictor]
+
+    vld1.8          {d0}, [r3], r6          ;load src
+    vld1.8          {d1}, [r7], r2          ;load pred
+    vld1.8          {d2}, [r3], r6
+    vld1.8          {d3}, [r7], r2
+    vld1.8          {d4}, [r3], r6
+    vld1.8          {d5}, [r7], r2
+    vld1.8          {d6}, [r3], r6
+    vld1.8          {d7}, [r7], r2
+
+    vsubl.u8        q10, d0, d1
+    vsubl.u8        q11, d2, d3
+    vsubl.u8        q12, d4, d5
+    vsubl.u8        q13, d6, d7
+
+    mov             r2, r2, lsl #1
+
+    vst1.16         {d20}, [r5], r2         ;store diff
+    vst1.16         {d22}, [r5], r2
+    vst1.16         {d24}, [r5], r2
+    vst1.16         {d26}, [r5], r2
+
+    ldmfd   sp!, {r4-r7}
+    bx              lr
+
+    ENDP
+
+
+;==========================================
+;void vp8_subtract_mby_neon(short *diff, unsigned char *src, int src_stride
+;                           unsigned char *pred, int pred_stride)
+|vp8_subtract_mby_neon| PROC
+    push            {r4-r7}
+    mov             r12, #4
+    ldr             r4, [sp, #16]           ; pred_stride
+    mov             r6, #32                 ; "diff" stride x2
+    add             r5, r0, #16             ; second diff pointer
+
+subtract_mby_loop
+    vld1.8          {q0}, [r1], r2          ;load src
+    vld1.8          {q1}, [r3], r4          ;load pred
+    vld1.8          {q2}, [r1], r2
+    vld1.8          {q3}, [r3], r4
+    vld1.8          {q4}, [r1], r2
+    vld1.8          {q5}, [r3], r4
+    vld1.8          {q6}, [r1], r2
+    vld1.8          {q7}, [r3], r4
+
+    vsubl.u8        q8, d0, d2
+    vsubl.u8        q9, d1, d3
+    vsubl.u8        q10, d4, d6
+    vsubl.u8        q11, d5, d7
+    vsubl.u8        q12, d8, d10
+    vsubl.u8        q13, d9, d11
+    vsubl.u8        q14, d12, d14
+    vsubl.u8        q15, d13, d15
+
+    vst1.16         {q8}, [r0], r6          ;store diff
+    vst1.16         {q9}, [r5], r6
+    vst1.16         {q10}, [r0], r6
+    vst1.16         {q11}, [r5], r6
+    vst1.16         {q12}, [r0], r6
+    vst1.16         {q13}, [r5], r6
+    vst1.16         {q14}, [r0], r6
+    vst1.16         {q15}, [r5], r6
+
+    subs            r12, r12, #1
+    bne             subtract_mby_loop
+
+    pop             {r4-r7}
+    bx              lr
+    ENDP
+
+;=================================
+;void vp8_subtract_mbuv_c(short *diff, unsigned char *usrc, unsigned char *vsrc,
+;                         int src_stride, unsigned char *upred,
+;                         unsigned char *vpred, int pred_stride)
+
+|vp8_subtract_mbuv_neon| PROC
+    push            {r4-r7}
+    ldr             r4, [sp, #16]       ; upred
+    ldr             r5, [sp, #20]       ; vpred
+    ldr             r6, [sp, #24]       ; pred_stride
+    add             r0, r0, #512        ; short *udiff = diff + 256;
+    mov             r12, #32            ; "diff" stride x2
+    add             r7, r0, #16         ; second diff pointer
+
+;u
+    vld1.8          {d0}, [r1], r3      ;load usrc
+    vld1.8          {d1}, [r4], r6      ;load upred
+    vld1.8          {d2}, [r1], r3
+    vld1.8          {d3}, [r4], r6
+    vld1.8          {d4}, [r1], r3
+    vld1.8          {d5}, [r4], r6
+    vld1.8          {d6}, [r1], r3
+    vld1.8          {d7}, [r4], r6
+    vld1.8          {d8}, [r1], r3
+    vld1.8          {d9}, [r4], r6
+    vld1.8          {d10}, [r1], r3
+    vld1.8          {d11}, [r4], r6
+    vld1.8          {d12}, [r1], r3
+    vld1.8          {d13}, [r4], r6
+    vld1.8          {d14}, [r1], r3
+    vld1.8          {d15}, [r4], r6
+
+    vsubl.u8        q8, d0, d1
+    vsubl.u8        q9, d2, d3
+    vsubl.u8        q10, d4, d5
+    vsubl.u8        q11, d6, d7
+    vsubl.u8        q12, d8, d9
+    vsubl.u8        q13, d10, d11
+    vsubl.u8        q14, d12, d13
+    vsubl.u8        q15, d14, d15
+
+    vst1.16         {q8}, [r0], r12     ;store diff
+    vst1.16         {q9}, [r7], r12
+    vst1.16         {q10}, [r0], r12
+    vst1.16         {q11}, [r7], r12
+    vst1.16         {q12}, [r0], r12
+    vst1.16         {q13}, [r7], r12
+    vst1.16         {q14}, [r0], r12
+    vst1.16         {q15}, [r7], r12
+
+;v
+    vld1.8          {d0}, [r2], r3      ;load vsrc
+    vld1.8          {d1}, [r5], r6      ;load vpred
+    vld1.8          {d2}, [r2], r3
+    vld1.8          {d3}, [r5], r6
+    vld1.8          {d4}, [r2], r3
+    vld1.8          {d5}, [r5], r6
+    vld1.8          {d6}, [r2], r3
+    vld1.8          {d7}, [r5], r6
+    vld1.8          {d8}, [r2], r3
+    vld1.8          {d9}, [r5], r6
+    vld1.8          {d10}, [r2], r3
+    vld1.8          {d11}, [r5], r6
+    vld1.8          {d12}, [r2], r3
+    vld1.8          {d13}, [r5], r6
+    vld1.8          {d14}, [r2], r3
+    vld1.8          {d15}, [r5], r6
+
+    vsubl.u8        q8, d0, d1
+    vsubl.u8        q9, d2, d3
+    vsubl.u8        q10, d4, d5
+    vsubl.u8        q11, d6, d7
+    vsubl.u8        q12, d8, d9
+    vsubl.u8        q13, d10, d11
+    vsubl.u8        q14, d12, d13
+    vsubl.u8        q15, d14, d15
+
+    vst1.16         {q8}, [r0], r12     ;store diff
+    vst1.16         {q9}, [r7], r12
+    vst1.16         {q10}, [r0], r12
+    vst1.16         {q11}, [r7], r12
+    vst1.16         {q12}, [r0], r12
+    vst1.16         {q13}, [r7], r12
+    vst1.16         {q14}, [r0], r12
+    vst1.16         {q15}, [r7], r12
+
+    pop             {r4-r7}
+    bx              lr
+
+    ENDP
+
+    END
diff --git a/vp8/encoder/arm/neon/vp8_memcpy_neon.asm b/vp8/encoder/arm/neon/vp8_memcpy_neon.asm
new file mode 100644 (file)
index 0000000..5b9f11e
--- /dev/null
@@ -0,0 +1,70 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT |vp8_memcpy_partial_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;=========================================
+;this is not a full memcpy function!!!
+;void vp8_memcpy_partial_neon(unsigned char *dst_ptr, unsigned char *src_ptr,
+;                             int sz);
+|vp8_memcpy_partial_neon| PROC
+    ;pld                [r1]                        ;preload pred data
+    ;pld                [r1, #128]
+    ;pld                [r1, #256]
+    ;pld                [r1, #384]
+
+    mov             r12, r2, lsr #8                 ;copy 256 bytes data at one time
+
+memcpy_neon_loop
+    vld1.8          {q0, q1}, [r1]!                 ;load src data
+    subs            r12, r12, #1
+    vld1.8          {q2, q3}, [r1]!
+    vst1.8          {q0, q1}, [r0]!                 ;copy to dst_ptr
+    vld1.8          {q4, q5}, [r1]!
+    vst1.8          {q2, q3}, [r0]!
+    vld1.8          {q6, q7}, [r1]!
+    vst1.8          {q4, q5}, [r0]!
+    vld1.8          {q8, q9}, [r1]!
+    vst1.8          {q6, q7}, [r0]!
+    vld1.8          {q10, q11}, [r1]!
+    vst1.8          {q8, q9}, [r0]!
+    vld1.8          {q12, q13}, [r1]!
+    vst1.8          {q10, q11}, [r0]!
+    vld1.8          {q14, q15}, [r1]!
+    vst1.8          {q12, q13}, [r0]!
+    vst1.8          {q14, q15}, [r0]!
+
+    ;pld                [r1]                        ;preload pred data -- need to adjust for real device
+    ;pld                [r1, #128]
+    ;pld                [r1, #256]
+    ;pld                [r1, #384]
+
+    bne             memcpy_neon_loop
+
+    ands            r3, r2, #0xff                   ;extra copy
+    beq             done_copy_neon_loop
+
+extra_copy_neon_loop
+    vld1.8          {q0}, [r1]!                 ;load src data
+    subs            r3, r3, #16
+    vst1.8          {q0}, [r0]!
+    bne             extra_copy_neon_loop
+
+done_copy_neon_loop
+    bx              lr
+    ENDP
+
+    END
diff --git a/vp8/encoder/arm/neon/vp8_mse16x16_neon.asm b/vp8/encoder/arm/neon/vp8_mse16x16_neon.asm
new file mode 100644 (file)
index 0000000..55edbf5
--- /dev/null
@@ -0,0 +1,116 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_mse16x16_neon|
+    EXPORT  |vp8_get4x4sse_cs_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;============================
+; r0    unsigned char *src_ptr
+; r1    int source_stride
+; r2    unsigned char *ref_ptr
+; r3    int  recon_stride
+; stack unsigned int *sse
+;note: in this function, sum is never used. So, we can remove this part of calculation
+;from vp8_variance().
+
+|vp8_mse16x16_neon| PROC
+    vmov.i8         q7, #0                      ;q7, q8, q9, q10 - sse
+    vmov.i8         q8, #0
+    vmov.i8         q9, #0
+    vmov.i8         q10, #0
+
+    mov             r12, #8
+
+mse16x16_neon_loop
+    vld1.8          {q0}, [r0], r1              ;Load up source and reference
+    vld1.8          {q2}, [r2], r3
+    vld1.8          {q1}, [r0], r1
+    vld1.8          {q3}, [r2], r3
+
+    vsubl.u8        q11, d0, d4
+    vsubl.u8        q12, d1, d5
+    vsubl.u8        q13, d2, d6
+    vsubl.u8        q14, d3, d7
+
+    vmlal.s16       q7, d22, d22
+    vmlal.s16       q8, d23, d23
+
+    subs            r12, r12, #1
+
+    vmlal.s16       q9, d24, d24
+    vmlal.s16       q10, d25, d25
+    vmlal.s16       q7, d26, d26
+    vmlal.s16       q8, d27, d27
+    vmlal.s16       q9, d28, d28
+    vmlal.s16       q10, d29, d29
+
+    bne             mse16x16_neon_loop
+
+    vadd.u32        q7, q7, q8
+    vadd.u32        q9, q9, q10
+
+    ldr             r12, [sp]               ;load *sse from stack
+
+    vadd.u32        q10, q7, q9
+    vpaddl.u32      q1, q10
+    vadd.u64        d0, d2, d3
+
+    vst1.32         {d0[0]}, [r12]
+    vmov.32         r0, d0[0]
+
+    bx              lr
+
+    ENDP
+
+
+;=============================
+; r0    unsigned char *src_ptr,
+; r1    int  source_stride,
+; r2    unsigned char *ref_ptr,
+; r3    int  recon_stride
+|vp8_get4x4sse_cs_neon| PROC
+    vld1.8          {d0}, [r0], r1              ;Load up source and reference
+    vld1.8          {d4}, [r2], r3
+    vld1.8          {d1}, [r0], r1
+    vld1.8          {d5}, [r2], r3
+    vld1.8          {d2}, [r0], r1
+    vld1.8          {d6}, [r2], r3
+    vld1.8          {d3}, [r0], r1
+    vld1.8          {d7}, [r2], r3
+
+    vsubl.u8        q11, d0, d4
+    vsubl.u8        q12, d1, d5
+    vsubl.u8        q13, d2, d6
+    vsubl.u8        q14, d3, d7
+
+    vmull.s16       q7, d22, d22
+    vmull.s16       q8, d24, d24
+    vmull.s16       q9, d26, d26
+    vmull.s16       q10, d28, d28
+
+    vadd.u32        q7, q7, q8
+    vadd.u32        q9, q9, q10
+    vadd.u32        q9, q7, q9
+
+    vpaddl.u32      q1, q9
+    vadd.u64        d0, d2, d3
+
+    vmov.32         r0, d0[0]
+    bx              lr
+
+    ENDP
+
+    END
diff --git a/vp8/encoder/arm/neon/vp8_shortwalsh4x4_neon.asm b/vp8/encoder/arm/neon/vp8_shortwalsh4x4_neon.asm
new file mode 100644 (file)
index 0000000..2226629
--- /dev/null
@@ -0,0 +1,103 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_short_walsh4x4_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;void vp8_short_walsh4x4_neon(short *input, short *output, int pitch)
+; r0   short *input,
+; r1   short *output,
+; r2   int pitch
+|vp8_short_walsh4x4_neon| PROC
+
+    vld1.16         {d0}, [r0@64], r2   ; load input
+    vld1.16         {d1}, [r0@64], r2
+    vld1.16         {d2}, [r0@64], r2
+    vld1.16         {d3}, [r0@64]
+
+    ;First for-loop
+    ;transpose d0, d1, d2, d3. Then, d0=ip[0], d1=ip[1], d2=ip[2], d3=ip[3]
+    vtrn.32         d0, d2
+    vtrn.32         d1, d3
+
+    vmov.s32        q15, #3             ; add 3 to all values
+
+    vtrn.16         d0, d1
+    vtrn.16         d2, d3
+
+    vadd.s16        d4, d0, d2          ; ip[0] + ip[2]
+    vadd.s16        d5, d1, d3          ; ip[1] + ip[3]
+    vsub.s16        d6, d1, d3          ; ip[1] - ip[3]
+    vsub.s16        d7, d0, d2          ; ip[0] - ip[2]
+
+    vshl.s16        d4, d4, #2          ; a1 = (ip[0] + ip[2]) << 2
+    vshl.s16        d5, d5, #2          ; d1 = (ip[1] + ip[3]) << 2
+    vshl.s16        d6, d6, #2          ; c1 = (ip[1] - ip[3]) << 2
+    vceq.s16        d16, d4, #0         ; a1 == 0
+    vshl.s16        d7, d7, #2          ; b1 = (ip[0] - ip[2]) << 2
+
+    vadd.s16        d0, d4, d5          ; a1 + d1
+    vmvn            d16, d16            ; a1 != 0
+    vsub.s16        d3, d4, d5          ; op[3] = a1 - d1
+    vadd.s16        d1, d7, d6          ; op[1] = b1 + c1
+    vsub.s16        d2, d7, d6          ; op[2] = b1 - c1
+    vsub.s16        d0, d0, d16         ; op[0] = a1 + d1 + (a1 != 0)
+
+    ;Second for-loop
+    ;transpose d0, d1, d2, d3, Then, d0=ip[0], d1=ip[4], d2=ip[8], d3=ip[12]
+    vtrn.32         d1, d3
+    vtrn.32         d0, d2
+    vtrn.16         d2, d3
+    vtrn.16         d0, d1
+
+    vaddl.s16       q8, d0, d2          ; a1 = ip[0]+ip[8]
+    vaddl.s16       q9, d1, d3          ; d1 = ip[4]+ip[12]
+    vsubl.s16       q10, d1, d3         ; c1 = ip[4]-ip[12]
+    vsubl.s16       q11, d0, d2         ; b1 = ip[0]-ip[8]
+
+    vadd.s32        q0, q8, q9          ; a2 = a1 + d1
+    vadd.s32        q1, q11, q10        ; b2 = b1 + c1
+    vsub.s32        q2, q11, q10        ; c2 = b1 - c1
+    vsub.s32        q3, q8, q9          ; d2 = a1 - d1
+
+    vclt.s32        q8, q0, #0
+    vclt.s32        q9, q1, #0
+    vclt.s32        q10, q2, #0
+    vclt.s32        q11, q3, #0
+
+    ; subtract -1 (or 0)
+    vsub.s32        q0, q0, q8          ; a2 += a2 < 0
+    vsub.s32        q1, q1, q9          ; b2 += b2 < 0
+    vsub.s32        q2, q2, q10         ; c2 += c2 < 0
+    vsub.s32        q3, q3, q11         ; d2 += d2 < 0
+
+    vadd.s32        q8, q0, q15         ; a2 + 3
+    vadd.s32        q9, q1, q15         ; b2 + 3
+    vadd.s32        q10, q2, q15        ; c2 + 3
+    vadd.s32        q11, q3, q15        ; d2 + 3
+
+    ; vrshrn? would add 1 << 3-1 = 2
+    vshrn.s32       d0, q8, #3
+    vshrn.s32       d1, q9, #3
+    vshrn.s32       d2, q10, #3
+    vshrn.s32       d3, q11, #3
+
+    vst1.16         {q0, q1}, [r1@128]
+
+    bx              lr
+
+    ENDP
+
+    END
diff --git a/vp8/encoder/arm/quantize_arm.c b/vp8/encoder/arm/quantize_arm.c
new file mode 100644 (file)
index 0000000..8999e34
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "vp8/encoder/block.h"
+#include <math.h>
+#include "vpx_mem/vpx_mem.h"
+#include "vp8/encoder/quantize.h"
+#include "vp8/common/entropy.h"
+
+
+#if HAVE_NEON
+
+/* vp8_quantize_mbX functions here differs from corresponding ones in
+ * quantize.c only by using quantize_b_pair function pointer instead of
+ * the regular quantize_b function pointer */
+void vp8_quantize_mby_neon(MACROBLOCK *x)
+{
+    int i;
+    int has_2nd_order = (x->e_mbd.mode_info_context->mbmi.mode != B_PRED
+        && x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
+
+    for (i = 0; i < 16; i+=2)
+        x->quantize_b_pair(&x->block[i], &x->block[i+1],
+                           &x->e_mbd.block[i], &x->e_mbd.block[i+1]);
+
+    if(has_2nd_order)
+        x->quantize_b(&x->block[24], &x->e_mbd.block[24]);
+}
+
+void vp8_quantize_mb_neon(MACROBLOCK *x)
+{
+    int i;
+    int has_2nd_order=(x->e_mbd.mode_info_context->mbmi.mode != B_PRED
+        && x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
+
+    for (i = 0; i < 24; i+=2)
+        x->quantize_b_pair(&x->block[i], &x->block[i+1],
+                           &x->e_mbd.block[i], &x->e_mbd.block[i+1]);
+
+    if (has_2nd_order)
+        x->quantize_b(&x->block[24], &x->e_mbd.block[24]);
+}
+
+
+void vp8_quantize_mbuv_neon(MACROBLOCK *x)
+{
+    int i;
+
+    for (i = 16; i < 24; i+=2)
+        x->quantize_b_pair(&x->block[i], &x->block[i+1],
+                           &x->e_mbd.block[i], &x->e_mbd.block[i+1]);
+}
+
+#endif /* HAVE_NEON */
diff --git a/vp8/encoder/asm_enc_offsets.c b/vp8/encoder/asm_enc_offsets.c
new file mode 100644 (file)
index 0000000..a4169b3
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_ports/asm_offsets.h"
+#include "vpx_config.h"
+#include "block.h"
+#include "vp8/common/blockd.h"
+#include "onyx_int.h"
+#include "treewriter.h"
+#include "tokenize.h"
+
+BEGIN
+
+/* regular quantize */
+DEFINE(vp8_block_coeff,                         offsetof(BLOCK, coeff));
+DEFINE(vp8_block_zbin,                          offsetof(BLOCK, zbin));
+DEFINE(vp8_block_round,                         offsetof(BLOCK, round));
+DEFINE(vp8_block_quant,                         offsetof(BLOCK, quant));
+DEFINE(vp8_block_quant_fast,                    offsetof(BLOCK, quant_fast));
+DEFINE(vp8_block_zbin_extra,                    offsetof(BLOCK, zbin_extra));
+DEFINE(vp8_block_zrun_zbin_boost,               offsetof(BLOCK, zrun_zbin_boost));
+DEFINE(vp8_block_quant_shift,                   offsetof(BLOCK, quant_shift));
+
+DEFINE(vp8_blockd_qcoeff,                       offsetof(BLOCKD, qcoeff));
+DEFINE(vp8_blockd_dequant,                      offsetof(BLOCKD, dequant));
+DEFINE(vp8_blockd_dqcoeff,                      offsetof(BLOCKD, dqcoeff));
+DEFINE(vp8_blockd_eob,                          offsetof(BLOCKD, eob));
+
+/* subtract */
+DEFINE(vp8_block_base_src,                      offsetof(BLOCK, base_src));
+DEFINE(vp8_block_src,                           offsetof(BLOCK, src));
+DEFINE(vp8_block_src_diff,                      offsetof(BLOCK, src_diff));
+DEFINE(vp8_block_src_stride,                    offsetof(BLOCK, src_stride));
+
+DEFINE(vp8_blockd_predictor,                    offsetof(BLOCKD, predictor));
+
+/* pack tokens */
+DEFINE(vp8_writer_lowvalue,                     offsetof(vp8_writer, lowvalue));
+DEFINE(vp8_writer_range,                        offsetof(vp8_writer, range));
+DEFINE(vp8_writer_count,                        offsetof(vp8_writer, count));
+DEFINE(vp8_writer_pos,                          offsetof(vp8_writer, pos));
+DEFINE(vp8_writer_buffer,                       offsetof(vp8_writer, buffer));
+DEFINE(vp8_writer_buffer_end,                   offsetof(vp8_writer, buffer_end));
+DEFINE(vp8_writer_error,                        offsetof(vp8_writer, error));
+
+DEFINE(tokenextra_token,                        offsetof(TOKENEXTRA, Token));
+DEFINE(tokenextra_extra,                        offsetof(TOKENEXTRA, Extra));
+DEFINE(tokenextra_context_tree,                 offsetof(TOKENEXTRA, context_tree));
+DEFINE(tokenextra_skip_eob_node,                offsetof(TOKENEXTRA, skip_eob_node));
+DEFINE(TOKENEXTRA_SZ,                           sizeof(TOKENEXTRA));
+
+DEFINE(vp8_extra_bit_struct_sz,                 sizeof(vp8_extra_bit_struct));
+
+DEFINE(vp8_token_value,                         offsetof(vp8_token, value));
+DEFINE(vp8_token_len,                           offsetof(vp8_token, Len));
+
+DEFINE(vp8_extra_bit_struct_tree,               offsetof(vp8_extra_bit_struct, tree));
+DEFINE(vp8_extra_bit_struct_prob,               offsetof(vp8_extra_bit_struct, prob));
+DEFINE(vp8_extra_bit_struct_len,                offsetof(vp8_extra_bit_struct, Len));
+DEFINE(vp8_extra_bit_struct_base_val,           offsetof(vp8_extra_bit_struct, base_val));
+
+DEFINE(vp8_comp_tplist,                         offsetof(VP8_COMP, tplist));
+DEFINE(vp8_comp_common,                         offsetof(VP8_COMP, common));
+DEFINE(vp8_comp_bc ,                            offsetof(VP8_COMP, bc));
+DEFINE(vp8_writer_sz ,                          sizeof(vp8_writer));
+
+DEFINE(tokenlist_start,                         offsetof(TOKENLIST, start));
+DEFINE(tokenlist_stop,                          offsetof(TOKENLIST, stop));
+DEFINE(TOKENLIST_SZ,                            sizeof(TOKENLIST));
+
+DEFINE(vp8_common_mb_rows,                      offsetof(VP8_COMMON, mb_rows));
+
+END
+
+/* add asserts for any offset that is not supported by assembly code
+ * add asserts for any size that is not supported by assembly code
+
+ * These are used in vp8cx_pack_tokens.  They are hard coded so if their sizes
+ * change they will have to be adjusted.
+ */
+
+#if HAVE_EDSP
+ct_assert(TOKENEXTRA_SZ, sizeof(TOKENEXTRA) == 8)
+ct_assert(vp8_extra_bit_struct_sz, sizeof(vp8_extra_bit_struct) == 16)
+#endif
diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c
new file mode 100644 (file)
index 0000000..3824294
--- /dev/null
@@ -0,0 +1,1734 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vp8/common/header.h"
+#include "encodemv.h"
+#include "vp8/common/entropymode.h"
+#include "vp8/common/findnearmv.h"
+#include "mcomp.h"
+#include "vp8/common/systemdependent.h"
+#include <assert.h>
+#include <stdio.h>
+#include <limits.h>
+#include "vp8/common/pragmas.h"
+#include "vpx/vpx_encoder.h"
+#include "vpx_mem/vpx_mem.h"
+#include "bitstream.h"
+
+#include "defaultcoefcounts.h"
+#include "vp8/common/common.h"
+
+const int vp8cx_base_skip_false_prob[128] =
+{
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    251, 248, 244, 240, 236, 232, 229, 225,
+    221, 217, 213, 208, 204, 199, 194, 190,
+    187, 183, 179, 175, 172, 168, 164, 160,
+    157, 153, 149, 145, 142, 138, 134, 130,
+    127, 124, 120, 117, 114, 110, 107, 104,
+    101, 98,  95,  92,  89,  86,  83, 80,
+    77,  74,  71,  68,  65,  62,  59, 56,
+    53,  50,  47,  44,  41,  38,  35, 32,
+    30,  28,  26,  24,  22,  20,  18, 16,
+};
+
+#if defined(SECTIONBITS_OUTPUT)
+unsigned __int64 Sectionbits[500];
+#endif
+
+#ifdef ENTROPY_STATS
+int intra_mode_stats[10][10][10];
+static unsigned int tree_update_hist [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES] [2];
+extern unsigned int active_section;
+#endif
+
+#ifdef MODE_STATS
+int count_mb_seg[4] = { 0, 0, 0, 0 };
+#endif
+
+
+static void update_mode(
+    vp8_writer *const w,
+    int n,
+    vp8_token tok               [/* n */],
+    vp8_tree tree,
+    vp8_prob Pnew               [/* n-1 */],
+    vp8_prob Pcur               [/* n-1 */],
+    unsigned int bct            [/* n-1 */] [2],
+    const unsigned int num_events[/* n */]
+)
+{
+    unsigned int new_b = 0, old_b = 0;
+    int i = 0;
+
+    vp8_tree_probs_from_distribution(
+        n--, tok, tree,
+        Pnew, bct, num_events,
+        256, 1
+    );
+
+    do
+    {
+        new_b += vp8_cost_branch(bct[i], Pnew[i]);
+        old_b += vp8_cost_branch(bct[i], Pcur[i]);
+    }
+    while (++i < n);
+
+    if (new_b + (n << 8) < old_b)
+    {
+        int i = 0;
+
+        vp8_write_bit(w, 1);
+
+        do
+        {
+            const vp8_prob p = Pnew[i];
+
+            vp8_write_literal(w, Pcur[i] = p ? p : 1, 8);
+        }
+        while (++i < n);
+    }
+    else
+        vp8_write_bit(w, 0);
+}
+
+static void update_mbintra_mode_probs(VP8_COMP *cpi)
+{
+    VP8_COMMON *const x = & cpi->common;
+
+    vp8_writer *const w = cpi->bc;
+
+    {
+        vp8_prob Pnew   [VP8_YMODES-1];
+        unsigned int bct [VP8_YMODES-1] [2];
+
+        update_mode(
+            w, VP8_YMODES, vp8_ymode_encodings, vp8_ymode_tree,
+            Pnew, x->fc.ymode_prob, bct, (unsigned int *)cpi->ymode_count
+        );
+    }
+    {
+        vp8_prob Pnew   [VP8_UV_MODES-1];
+        unsigned int bct [VP8_UV_MODES-1] [2];
+
+        update_mode(
+            w, VP8_UV_MODES, vp8_uv_mode_encodings, vp8_uv_mode_tree,
+            Pnew, x->fc.uv_mode_prob, bct, (unsigned int *)cpi->uv_mode_count
+        );
+    }
+}
+
+static void write_ymode(vp8_writer *bc, int m, const vp8_prob *p)
+{
+    vp8_write_token(bc, vp8_ymode_tree, p, vp8_ymode_encodings + m);
+}
+
+static void kfwrite_ymode(vp8_writer *bc, int m, const vp8_prob *p)
+{
+    vp8_write_token(bc, vp8_kf_ymode_tree, p, vp8_kf_ymode_encodings + m);
+}
+
+static void write_uv_mode(vp8_writer *bc, int m, const vp8_prob *p)
+{
+    vp8_write_token(bc, vp8_uv_mode_tree, p, vp8_uv_mode_encodings + m);
+}
+
+
+static void write_bmode(vp8_writer *bc, int m, const vp8_prob *p)
+{
+    vp8_write_token(bc, vp8_bmode_tree, p, vp8_bmode_encodings + m);
+}
+
+static void write_split(vp8_writer *bc, int x)
+{
+    vp8_write_token(
+        bc, vp8_mbsplit_tree, vp8_mbsplit_probs, vp8_mbsplit_encodings + x
+    );
+}
+
+void vp8_pack_tokens_c(vp8_writer *w, const TOKENEXTRA *p, int xcount)
+{
+    const TOKENEXTRA *stop = p + xcount;
+    unsigned int split;
+    unsigned int shift;
+    int count = w->count;
+    unsigned int range = w->range;
+    unsigned int lowvalue = w->lowvalue;
+
+    while (p < stop)
+    {
+        const int t = p->Token;
+        const vp8_token *a = vp8_coef_encodings + t;
+        const vp8_extra_bit_struct *b = vp8_extra_bits + t;
+        int i = 0;
+        const unsigned char *pp = p->context_tree;
+        int v = a->value;
+        int n = a->Len;
+
+        if (p->skip_eob_node)
+        {
+            n--;
+            i = 2;
+        }
+
+        do
+        {
+            const int bb = (v >> --n) & 1;
+            split = 1 + (((range - 1) * pp[i>>1]) >> 8);
+            i = vp8_coef_tree[i+bb];
+
+            if (bb)
+            {
+                lowvalue += split;
+                range = range - split;
+            }
+            else
+            {
+                range = split;
+            }
+
+            shift = vp8_norm[range];
+            range <<= shift;
+            count += shift;
+
+            if (count >= 0)
+            {
+                int offset = shift - count;
+
+                if ((lowvalue << (offset - 1)) & 0x80000000)
+                {
+                    int x = w->pos - 1;
+
+                    while (x >= 0 && w->buffer[x] == 0xff)
+                    {
+                        w->buffer[x] = (unsigned char)0;
+                        x--;
+                    }
+
+                    w->buffer[x] += 1;
+                }
+
+                validate_buffer(w->buffer + w->pos,
+                                1,
+                                w->buffer_end,
+                                w->error);
+
+                w->buffer[w->pos++] = (lowvalue >> (24 - offset));
+                lowvalue <<= offset;
+                shift = count;
+                lowvalue &= 0xffffff;
+                count -= 8 ;
+            }
+
+            lowvalue <<= shift;
+        }
+        while (n);
+
+
+        if (b->base_val)
+        {
+            const int e = p->Extra, L = b->Len;
+
+            if (L)
+            {
+                const unsigned char *pp = b->prob;
+                int v = e >> 1;
+                int n = L;              /* number of bits in v, assumed nonzero */
+                int i = 0;
+
+                do
+                {
+                    const int bb = (v >> --n) & 1;
+                    split = 1 + (((range - 1) * pp[i>>1]) >> 8);
+                    i = b->tree[i+bb];
+
+                    if (bb)
+                    {
+                        lowvalue += split;
+                        range = range - split;
+                    }
+                    else
+                    {
+                        range = split;
+                    }
+
+                    shift = vp8_norm[range];
+                    range <<= shift;
+                    count += shift;
+
+                    if (count >= 0)
+                    {
+                        int offset = shift - count;
+
+                        if ((lowvalue << (offset - 1)) & 0x80000000)
+                        {
+                            int x = w->pos - 1;
+
+                            while (x >= 0 && w->buffer[x] == 0xff)
+                            {
+                                w->buffer[x] = (unsigned char)0;
+                                x--;
+                            }
+
+                            w->buffer[x] += 1;
+                        }
+
+                        validate_buffer(w->buffer + w->pos,
+                                        1,
+                                        w->buffer_end,
+                                        w->error);
+
+                        w->buffer[w->pos++] = (lowvalue >> (24 - offset));
+                        lowvalue <<= offset;
+                        shift = count;
+                        lowvalue &= 0xffffff;
+                        count -= 8 ;
+                    }
+
+                    lowvalue <<= shift;
+                }
+                while (n);
+            }
+
+
+            {
+
+                split = (range + 1) >> 1;
+
+                if (e & 1)
+                {
+                    lowvalue += split;
+                    range = range - split;
+                }
+                else
+                {
+                    range = split;
+                }
+
+                range <<= 1;
+
+                if ((lowvalue & 0x80000000))
+                {
+                    int x = w->pos - 1;
+
+                    while (x >= 0 && w->buffer[x] == 0xff)
+                    {
+                        w->buffer[x] = (unsigned char)0;
+                        x--;
+                    }
+
+                    w->buffer[x] += 1;
+
+                }
+
+                lowvalue  <<= 1;
+
+                if (!++count)
+                {
+                    count = -8;
+
+                    validate_buffer(w->buffer + w->pos,
+                                    1,
+                                    w->buffer_end,
+                                    w->error);
+
+                    w->buffer[w->pos++] = (lowvalue >> 24);
+                    lowvalue &= 0xffffff;
+                }
+            }
+
+        }
+
+        ++p;
+    }
+
+    w->count = count;
+    w->lowvalue = lowvalue;
+    w->range = range;
+
+}
+
+static void write_partition_size(unsigned char *cx_data, int size)
+{
+    signed char csize;
+
+    csize = size & 0xff;
+    *cx_data = csize;
+    csize = (size >> 8) & 0xff;
+    *(cx_data + 1) = csize;
+    csize = (size >> 16) & 0xff;
+    *(cx_data + 2) = csize;
+
+}
+
+static void pack_tokens_into_partitions_c(VP8_COMP *cpi, unsigned char *cx_data,
+                                          unsigned char * cx_data_end,
+                                          int num_part)
+{
+
+    int i;
+    unsigned char *ptr = cx_data;
+    unsigned char *ptr_end = cx_data_end;
+    vp8_writer * w;
+
+    for (i = 0; i < num_part; i++)
+    {
+        int mb_row;
+
+        w = cpi->bc + i + 1;
+
+        vp8_start_encode(w, ptr, ptr_end);
+
+        for (mb_row = i; mb_row < cpi->common.mb_rows; mb_row += num_part)
+        {
+            const TOKENEXTRA *p    = cpi->tplist[mb_row].start;
+            const TOKENEXTRA *stop = cpi->tplist[mb_row].stop;
+            int tokens = stop - p;
+
+            vp8_pack_tokens_c(w, p, tokens);
+        }
+
+        vp8_stop_encode(w);
+        ptr += w->pos;
+    }
+}
+
+
+static void pack_mb_row_tokens_c(VP8_COMP *cpi, vp8_writer *w)
+{
+    int mb_row;
+
+    for (mb_row = 0; mb_row < cpi->common.mb_rows; mb_row++)
+    {
+        const TOKENEXTRA *p    = cpi->tplist[mb_row].start;
+        const TOKENEXTRA *stop = cpi->tplist[mb_row].stop;
+        int tokens = stop - p;
+
+        vp8_pack_tokens_c(w, p, tokens);
+    }
+
+}
+
+static void write_mv_ref
+(
+    vp8_writer *w, MB_PREDICTION_MODE m, const vp8_prob *p
+)
+{
+#if CONFIG_DEBUG
+    assert(NEARESTMV <= m  &&  m <= SPLITMV);
+#endif
+    vp8_write_token(w, vp8_mv_ref_tree, p,
+                    vp8_mv_ref_encoding_array - NEARESTMV + m);
+}
+
+static void write_sub_mv_ref
+(
+    vp8_writer *w, B_PREDICTION_MODE m, const vp8_prob *p
+)
+{
+#if CONFIG_DEBUG
+    assert(LEFT4X4 <= m  &&  m <= NEW4X4);
+#endif
+    vp8_write_token(w, vp8_sub_mv_ref_tree, p,
+                    vp8_sub_mv_ref_encoding_array - LEFT4X4 + m);
+}
+
+static void write_mv
+(
+    vp8_writer *w, const MV *mv, const int_mv *ref, const MV_CONTEXT *mvc
+)
+{
+    MV e;
+    e.row = mv->row - ref->as_mv.row;
+    e.col = mv->col - ref->as_mv.col;
+
+    vp8_encode_motion_vector(w, &e, mvc);
+}
+
+static void write_mb_features(vp8_writer *w, const MB_MODE_INFO *mi, const MACROBLOCKD *x)
+{
+    // Encode the MB segment id.
+    if (x->segmentation_enabled && x->update_mb_segmentation_map)
+    {
+        switch (mi->segment_id)
+        {
+        case 0:
+            vp8_write(w, 0, x->mb_segment_tree_probs[0]);
+            vp8_write(w, 0, x->mb_segment_tree_probs[1]);
+            break;
+        case 1:
+            vp8_write(w, 0, x->mb_segment_tree_probs[0]);
+            vp8_write(w, 1, x->mb_segment_tree_probs[1]);
+            break;
+        case 2:
+            vp8_write(w, 1, x->mb_segment_tree_probs[0]);
+            vp8_write(w, 0, x->mb_segment_tree_probs[2]);
+            break;
+        case 3:
+            vp8_write(w, 1, x->mb_segment_tree_probs[0]);
+            vp8_write(w, 1, x->mb_segment_tree_probs[2]);
+            break;
+
+            // TRAP.. This should not happen
+        default:
+            vp8_write(w, 0, x->mb_segment_tree_probs[0]);
+            vp8_write(w, 0, x->mb_segment_tree_probs[1]);
+            break;
+        }
+    }
+}
+void vp8_convert_rfct_to_prob(VP8_COMP *const cpi)
+{
+    const int *const rfct = cpi->count_mb_ref_frame_usage;
+    const int rf_intra = rfct[INTRA_FRAME];
+    const int rf_inter = rfct[LAST_FRAME] + rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME];
+
+    // Calculate the probabilities used to code the ref frame based on useage
+    if (!(cpi->prob_intra_coded = rf_intra * 255 / (rf_intra + rf_inter)))
+        cpi->prob_intra_coded = 1;
+
+    cpi->prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
+
+    if (!cpi->prob_last_coded)
+        cpi->prob_last_coded = 1;
+
+    cpi->prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
+                  ? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
+
+    if (!cpi->prob_gf_coded)
+        cpi->prob_gf_coded = 1;
+
+}
+
+static void pack_inter_mode_mvs(VP8_COMP *const cpi)
+{
+    VP8_COMMON *const pc = & cpi->common;
+    vp8_writer *const w = cpi->bc;
+    const MV_CONTEXT *mvc = pc->fc.mvc;
+
+
+    MODE_INFO *m = pc->mi;
+    const int mis = pc->mode_info_stride;
+    int mb_row = -1;
+
+    int prob_skip_false = 0;
+
+    cpi->mb.partition_info = cpi->mb.pi;
+
+    vp8_convert_rfct_to_prob(cpi);
+
+#ifdef ENTROPY_STATS
+    active_section = 1;
+#endif
+
+    if (pc->mb_no_coeff_skip)
+    {
+        int total_mbs = pc->mb_rows * pc->mb_cols;
+
+        prob_skip_false = (total_mbs - cpi->skip_true_count ) * 256 / total_mbs;
+
+        if (prob_skip_false <= 1)
+            prob_skip_false = 1;
+
+        if (prob_skip_false > 255)
+            prob_skip_false = 255;
+
+        cpi->prob_skip_false = prob_skip_false;
+        vp8_write_literal(w, prob_skip_false, 8);
+    }
+
+    vp8_write_literal(w, cpi->prob_intra_coded, 8);
+    vp8_write_literal(w, cpi->prob_last_coded, 8);
+    vp8_write_literal(w, cpi->prob_gf_coded, 8);
+
+    update_mbintra_mode_probs(cpi);
+
+    vp8_write_mvprobs(cpi);
+
+    while (++mb_row < pc->mb_rows)
+    {
+        int mb_col = -1;
+
+        while (++mb_col < pc->mb_cols)
+        {
+            const MB_MODE_INFO *const mi = & m->mbmi;
+            const MV_REFERENCE_FRAME rf = mi->ref_frame;
+            const MB_PREDICTION_MODE mode = mi->mode;
+
+            MACROBLOCKD *xd = &cpi->mb.e_mbd;
+
+            // Distance of Mb to the various image edges.
+            // These specified to 8th pel as they are always compared to MV values that are in 1/8th pel units
+            xd->mb_to_left_edge = -((mb_col * 16) << 3);
+            xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
+            xd->mb_to_top_edge = -((mb_row * 16)) << 3;
+            xd->mb_to_bottom_edge = ((pc->mb_rows - 1 - mb_row) * 16) << 3;
+
+#ifdef ENTROPY_STATS
+            active_section = 9;
+#endif
+
+            if (cpi->mb.e_mbd.update_mb_segmentation_map)
+                write_mb_features(w, mi, &cpi->mb.e_mbd);
+
+            if (pc->mb_no_coeff_skip)
+                vp8_encode_bool(w, m->mbmi.mb_skip_coeff, prob_skip_false);
+
+            if (rf == INTRA_FRAME)
+            {
+                vp8_write(w, 0, cpi->prob_intra_coded);
+#ifdef ENTROPY_STATS
+                active_section = 6;
+#endif
+                write_ymode(w, mode, pc->fc.ymode_prob);
+
+                if (mode == B_PRED)
+                {
+                    int j = 0;
+
+                    do
+                        write_bmode(w, m->bmi[j].as_mode, pc->fc.bmode_prob);
+                    while (++j < 16);
+                }
+
+                write_uv_mode(w, mi->uv_mode, pc->fc.uv_mode_prob);
+            }
+            else    /* inter coded */
+            {
+                int_mv best_mv;
+                vp8_prob mv_ref_p [VP8_MVREFS-1];
+
+                vp8_write(w, 1, cpi->prob_intra_coded);
+
+                if (rf == LAST_FRAME)
+                    vp8_write(w, 0, cpi->prob_last_coded);
+                else
+                {
+                    vp8_write(w, 1, cpi->prob_last_coded);
+                    vp8_write(w, (rf == GOLDEN_FRAME) ? 0 : 1, cpi->prob_gf_coded);
+                }
+
+                {
+                    int_mv n1, n2;
+                    int ct[4];
+
+                    vp8_find_near_mvs(xd, m, &n1, &n2, &best_mv, ct, rf, cpi->common.ref_frame_sign_bias);
+                    vp8_clamp_mv2(&best_mv, xd);
+
+                    vp8_mv_ref_probs(mv_ref_p, ct);
+
+#ifdef ENTROPY_STATS
+                    accum_mv_refs(mode, ct);
+#endif
+
+                }
+
+#ifdef ENTROPY_STATS
+                active_section = 3;
+#endif
+
+                write_mv_ref(w, mode, mv_ref_p);
+
+                switch (mode)   /* new, split require MVs */
+                {
+                case NEWMV:
+
+#ifdef ENTROPY_STATS
+                    active_section = 5;
+#endif
+
+                    write_mv(w, &mi->mv.as_mv, &best_mv, mvc);
+                    break;
+
+                case SPLITMV:
+                {
+                    int j = 0;
+
+#ifdef MODE_STATS
+                    ++count_mb_seg [mi->partitioning];
+#endif
+
+                    write_split(w, mi->partitioning);
+
+                    do
+                    {
+                        B_PREDICTION_MODE blockmode;
+                        int_mv blockmv;
+                        const int *const  L = vp8_mbsplits [mi->partitioning];
+                        int k = -1;  /* first block in subset j */
+                        int mv_contz;
+                        int_mv leftmv, abovemv;
+
+                        blockmode =  cpi->mb.partition_info->bmi[j].mode;
+                        blockmv =  cpi->mb.partition_info->bmi[j].mv;
+#if CONFIG_DEBUG
+                        while (j != L[++k])
+                            if (k >= 16)
+                                assert(0);
+#else
+                        while (j != L[++k]);
+#endif
+                        leftmv.as_int = left_block_mv(m, k);
+                        abovemv.as_int = above_block_mv(m, k, mis);
+                        mv_contz = vp8_mv_cont(&leftmv, &abovemv);
+
+                        write_sub_mv_ref(w, blockmode, vp8_sub_mv_ref_prob2 [mv_contz]);
+
+                        if (blockmode == NEW4X4)
+                        {
+#ifdef ENTROPY_STATS
+                            active_section = 11;
+#endif
+                            write_mv(w, &blockmv.as_mv, &best_mv, (const MV_CONTEXT *) mvc);
+                        }
+                    }
+                    while (++j < cpi->mb.partition_info->count);
+                }
+                break;
+                default:
+                    break;
+                }
+            }
+
+            ++m;
+            cpi->mb.partition_info++;
+        }
+
+        ++m;  /* skip L prediction border */
+        cpi->mb.partition_info++;
+    }
+}
+
+
+static void write_kfmodes(VP8_COMP *cpi)
+{
+    vp8_writer *const bc = cpi->bc;
+    const VP8_COMMON *const c = & cpi->common;
+    /* const */
+    MODE_INFO *m = c->mi;
+
+    int mb_row = -1;
+    int prob_skip_false = 0;
+
+    if (c->mb_no_coeff_skip)
+    {
+        int total_mbs = c->mb_rows * c->mb_cols;
+
+        prob_skip_false = (total_mbs - cpi->skip_true_count ) * 256 / total_mbs;
+
+        if (prob_skip_false <= 1)
+            prob_skip_false = 1;
+
+        if (prob_skip_false >= 255)
+            prob_skip_false = 255;
+
+        cpi->prob_skip_false = prob_skip_false;
+        vp8_write_literal(bc, prob_skip_false, 8);
+    }
+
+    while (++mb_row < c->mb_rows)
+    {
+        int mb_col = -1;
+
+        while (++mb_col < c->mb_cols)
+        {
+            const int ym = m->mbmi.mode;
+
+            if (cpi->mb.e_mbd.update_mb_segmentation_map)
+                write_mb_features(bc, &m->mbmi, &cpi->mb.e_mbd);
+
+            if (c->mb_no_coeff_skip)
+                vp8_encode_bool(bc, m->mbmi.mb_skip_coeff, prob_skip_false);
+
+            kfwrite_ymode(bc, ym, c->kf_ymode_prob);
+
+            if (ym == B_PRED)
+            {
+                const int mis = c->mode_info_stride;
+                int i = 0;
+
+                do
+                {
+                    const B_PREDICTION_MODE A = above_block_mode(m, i, mis);
+                    const B_PREDICTION_MODE L = left_block_mode(m, i);
+                    const int bm = m->bmi[i].as_mode;
+
+#ifdef ENTROPY_STATS
+                    ++intra_mode_stats [A] [L] [bm];
+#endif
+
+                    write_bmode(bc, bm, c->kf_bmode_prob [A] [L]);
+                }
+                while (++i < 16);
+            }
+
+            write_uv_mode(bc, (m++)->mbmi.uv_mode, c->kf_uv_mode_prob);
+        }
+
+        m++;    // skip L prediction border
+    }
+}
+
+#if 0
+/* This function is used for debugging probability trees. */
+static void print_prob_tree(vp8_prob
+     coef_probs[BLOCK_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS][ENTROPY_NODES])
+{
+    /* print coef probability tree */
+    int i,j,k,l;
+    FILE* f = fopen("enc_tree_probs.txt", "a");
+    fprintf(f, "{\n");
+    for (i = 0; i < BLOCK_TYPES; i++)
+    {
+        fprintf(f, "  {\n");
+        for (j = 0; j < COEF_BANDS; j++)
+        {
+            fprintf(f, "    {\n");
+            for (k = 0; k < PREV_COEF_CONTEXTS; k++)
+            {
+                fprintf(f, "      {");
+                for (l = 0; l < ENTROPY_NODES; l++)
+                {
+                    fprintf(f, "%3u, ",
+                            (unsigned int)(coef_probs [i][j][k][l]));
+                }
+                fprintf(f, " }\n");
+            }
+            fprintf(f, "    }\n");
+        }
+        fprintf(f, "  }\n");
+    }
+    fprintf(f, "}\n");
+    fclose(f);
+}
+#endif
+
+static void sum_probs_over_prev_coef_context(
+        const unsigned int probs[PREV_COEF_CONTEXTS][MAX_ENTROPY_TOKENS],
+        unsigned int* out)
+{
+    int i, j;
+    for (i=0; i < MAX_ENTROPY_TOKENS; ++i)
+    {
+        for (j=0; j < PREV_COEF_CONTEXTS; ++j)
+        {
+            const unsigned int tmp = out[i];
+            out[i] += probs[j][i];
+            /* check for wrap */
+            if (out[i] < tmp)
+                out[i] = UINT_MAX;
+        }
+    }
+}
+
+static int prob_update_savings(const unsigned int *ct,
+                                   const vp8_prob oldp, const vp8_prob newp,
+                                   const vp8_prob upd)
+{
+    const int old_b = vp8_cost_branch(ct, oldp);
+    const int new_b = vp8_cost_branch(ct, newp);
+    const int update_b = 8 +
+                         ((vp8_cost_one(upd) - vp8_cost_zero(upd)) >> 8);
+
+    return old_b - new_b - update_b;
+}
+
+static int independent_coef_context_savings(VP8_COMP *cpi)
+{
+    int savings = 0;
+    int i = 0;
+    do
+    {
+        int j = 0;
+        do
+        {
+            int k = 0;
+            unsigned int prev_coef_count_sum[MAX_ENTROPY_TOKENS] = {0};
+            int prev_coef_savings[MAX_ENTROPY_TOKENS] = {0};
+            const unsigned int (*probs)[MAX_ENTROPY_TOKENS];
+            /* Calculate new probabilities given the constraint that
+             * they must be equal over the prev coef contexts
+             */
+
+            probs = (const unsigned int (*)[MAX_ENTROPY_TOKENS])
+                                                    cpi->coef_counts[i][j];
+
+            /* Reset to default probabilities at key frames */
+            if (cpi->common.frame_type == KEY_FRAME)
+                probs = default_coef_counts[i][j];
+
+            sum_probs_over_prev_coef_context(probs, prev_coef_count_sum);
+
+            do
+            {
+                /* at every context */
+
+                /* calc probs and branch cts for this frame only */
+                //vp8_prob new_p           [ENTROPY_NODES];
+                //unsigned int branch_ct   [ENTROPY_NODES] [2];
+
+                int t = 0;      /* token/prob index */
+
+                vp8_tree_probs_from_distribution(
+                    MAX_ENTROPY_TOKENS, vp8_coef_encodings, vp8_coef_tree,
+                    cpi->frame_coef_probs[i][j][k],
+                    cpi->frame_branch_ct [i][j][k],
+                    prev_coef_count_sum,
+                    256, 1);
+
+                do
+                {
+                    const unsigned int *ct  = cpi->frame_branch_ct [i][j][k][t];
+                    const vp8_prob newp = cpi->frame_coef_probs [i][j][k][t];
+                    const vp8_prob oldp = cpi->common.fc.coef_probs [i][j][k][t];
+                    const vp8_prob upd = vp8_coef_update_probs [i][j][k][t];
+                    const int s = prob_update_savings(ct, oldp, newp, upd);
+
+                    if (cpi->common.frame_type != KEY_FRAME ||
+                        (cpi->common.frame_type == KEY_FRAME && newp != oldp))
+                        prev_coef_savings[t] += s;
+                }
+                while (++t < ENTROPY_NODES);
+            }
+            while (++k < PREV_COEF_CONTEXTS);
+            k = 0;
+            do
+            {
+                /* We only update probabilities if we can save bits, except
+                 * for key frames where we have to update all probabilities
+                 * to get the equal probabilities across the prev coef
+                 * contexts.
+                 */
+                if (prev_coef_savings[k] > 0 ||
+                    cpi->common.frame_type == KEY_FRAME)
+                    savings += prev_coef_savings[k];
+            }
+            while (++k < ENTROPY_NODES);
+        }
+        while (++j < COEF_BANDS);
+    }
+    while (++i < BLOCK_TYPES);
+    return savings;
+}
+
+static int default_coef_context_savings(VP8_COMP *cpi)
+{
+    int savings = 0;
+    int i = 0;
+    do
+    {
+        int j = 0;
+        do
+        {
+            int k = 0;
+            do
+            {
+                /* at every context */
+
+                /* calc probs and branch cts for this frame only */
+                //vp8_prob new_p           [ENTROPY_NODES];
+                //unsigned int branch_ct   [ENTROPY_NODES] [2];
+
+                int t = 0;      /* token/prob index */
+
+                vp8_tree_probs_from_distribution(
+                    MAX_ENTROPY_TOKENS, vp8_coef_encodings, vp8_coef_tree,
+                    cpi->frame_coef_probs [i][j][k],
+                    cpi->frame_branch_ct [i][j][k],
+                    cpi->coef_counts [i][j][k],
+                    256, 1
+                );
+
+                do
+                {
+                    const unsigned int *ct  = cpi->frame_branch_ct [i][j][k][t];
+                    const vp8_prob newp = cpi->frame_coef_probs [i][j][k][t];
+                    const vp8_prob oldp = cpi->common.fc.coef_probs [i][j][k][t];
+                    const vp8_prob upd = vp8_coef_update_probs [i][j][k][t];
+                    const int s = prob_update_savings(ct, oldp, newp, upd);
+
+                    if (s > 0)
+                    {
+                        savings += s;
+                    }
+                }
+                while (++t < ENTROPY_NODES);
+            }
+            while (++k < PREV_COEF_CONTEXTS);
+        }
+        while (++j < COEF_BANDS);
+    }
+    while (++i < BLOCK_TYPES);
+    return savings;
+}
+
+void vp8_calc_ref_frame_costs(int *ref_frame_cost,
+                              int prob_intra,
+                              int prob_last,
+                              int prob_garf
+                             )
+{
+    ref_frame_cost[INTRA_FRAME]   = vp8_cost_zero(prob_intra);
+    ref_frame_cost[LAST_FRAME]    = vp8_cost_one(prob_intra)
+                                    + vp8_cost_zero(prob_last);
+    ref_frame_cost[GOLDEN_FRAME]  = vp8_cost_one(prob_intra)
+                                    + vp8_cost_one(prob_last)
+                                    + vp8_cost_zero(prob_garf);
+    ref_frame_cost[ALTREF_FRAME]  = vp8_cost_one(prob_intra)
+                                    + vp8_cost_one(prob_last)
+                                    + vp8_cost_one(prob_garf);
+
+}
+
+int vp8_estimate_entropy_savings(VP8_COMP *cpi)
+{
+    int savings = 0;
+
+    const int *const rfct = cpi->count_mb_ref_frame_usage;
+    const int rf_intra = rfct[INTRA_FRAME];
+    const int rf_inter = rfct[LAST_FRAME] + rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME];
+    int new_intra, new_last, new_garf, oldtotal, newtotal;
+    int ref_frame_cost[MAX_REF_FRAMES];
+
+    vp8_clear_system_state(); //__asm emms;
+
+    if (cpi->common.frame_type != KEY_FRAME)
+    {
+        if (!(new_intra = rf_intra * 255 / (rf_intra + rf_inter)))
+            new_intra = 1;
+
+        new_last = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
+
+        new_garf = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
+                  ? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
+
+
+        vp8_calc_ref_frame_costs(ref_frame_cost,new_intra,new_last,new_garf);
+
+        newtotal =
+            rfct[INTRA_FRAME] * ref_frame_cost[INTRA_FRAME] +
+            rfct[LAST_FRAME] * ref_frame_cost[LAST_FRAME] +
+            rfct[GOLDEN_FRAME] * ref_frame_cost[GOLDEN_FRAME] +
+            rfct[ALTREF_FRAME] * ref_frame_cost[ALTREF_FRAME];
+
+
+        // old costs
+        vp8_calc_ref_frame_costs(ref_frame_cost,cpi->prob_intra_coded,
+                                 cpi->prob_last_coded,cpi->prob_gf_coded);
+
+        oldtotal =
+            rfct[INTRA_FRAME] * ref_frame_cost[INTRA_FRAME] +
+            rfct[LAST_FRAME] * ref_frame_cost[LAST_FRAME] +
+            rfct[GOLDEN_FRAME] * ref_frame_cost[GOLDEN_FRAME] +
+            rfct[ALTREF_FRAME] * ref_frame_cost[ALTREF_FRAME];
+
+        savings += (oldtotal - newtotal) / 256;
+    }
+
+
+    if (cpi->oxcf.error_resilient_mode & VPX_ERROR_RESILIENT_PARTITIONS)
+        savings += independent_coef_context_savings(cpi);
+    else
+        savings += default_coef_context_savings(cpi);
+
+
+    return savings;
+}
+
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+int vp8_update_coef_context(VP8_COMP *cpi)
+{
+    int savings = 0;
+
+
+    if (cpi->common.frame_type == KEY_FRAME)
+    {
+        /* Reset to default counts/probabilities at key frames */
+        vp8_copy(cpi->coef_counts, default_coef_counts);
+    }
+
+    if (cpi->oxcf.error_resilient_mode & VPX_ERROR_RESILIENT_PARTITIONS)
+        savings += independent_coef_context_savings(cpi);
+    else
+        savings += default_coef_context_savings(cpi);
+
+    return savings;
+}
+#endif
+
+void vp8_update_coef_probs(VP8_COMP *cpi)
+{
+    int i = 0;
+#if !(CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)
+    vp8_writer *const w = cpi->bc;
+#endif
+    int savings = 0;
+
+    vp8_clear_system_state(); //__asm emms;
+
+    do
+    {
+        int j = 0;
+
+        do
+        {
+            int k = 0;
+            int prev_coef_savings[ENTROPY_NODES] = {0};
+            if (cpi->oxcf.error_resilient_mode & VPX_ERROR_RESILIENT_PARTITIONS)
+            {
+                for (k = 0; k < PREV_COEF_CONTEXTS; ++k)
+                {
+                    int t;      /* token/prob index */
+                    for (t = 0; t < ENTROPY_NODES; ++t)
+                    {
+                        const unsigned int *ct = cpi->frame_branch_ct [i][j]
+                                                                      [k][t];
+                        const vp8_prob newp = cpi->frame_coef_probs[i][j][k][t];
+                        const vp8_prob oldp = cpi->common.fc.coef_probs[i][j]
+                                                                       [k][t];
+                        const vp8_prob upd = vp8_coef_update_probs[i][j][k][t];
+
+                        prev_coef_savings[t] +=
+                                prob_update_savings(ct, oldp, newp, upd);
+                    }
+                }
+                k = 0;
+            }
+            do
+            {
+                //note: use result from vp8_estimate_entropy_savings, so no need to call vp8_tree_probs_from_distribution here.
+                /* at every context */
+
+                /* calc probs and branch cts for this frame only */
+                //vp8_prob new_p           [ENTROPY_NODES];
+                //unsigned int branch_ct   [ENTROPY_NODES] [2];
+
+                int t = 0;      /* token/prob index */
+
+                //vp8_tree_probs_from_distribution(
+                //    MAX_ENTROPY_TOKENS, vp8_coef_encodings, vp8_coef_tree,
+                //    new_p, branch_ct, (unsigned int *)cpi->coef_counts [i][j][k],
+                //    256, 1
+                //    );
+
+                do
+                {
+                    const vp8_prob newp = cpi->frame_coef_probs [i][j][k][t];
+
+                    vp8_prob *Pold = cpi->common.fc.coef_probs [i][j][k] + t;
+                    const vp8_prob upd = vp8_coef_update_probs [i][j][k][t];
+
+                    int s = prev_coef_savings[t];
+                    int u = 0;
+
+                    if (!(cpi->oxcf.error_resilient_mode &
+                            VPX_ERROR_RESILIENT_PARTITIONS))
+                    {
+                        s = prob_update_savings(
+                                cpi->frame_branch_ct [i][j][k][t],
+                                *Pold, newp, upd);
+                    }
+
+                    if (s > 0)
+                        u = 1;
+
+                    /* Force updates on key frames if the new is different,
+                     * so that we can be sure we end up with equal probabilities
+                     * over the prev coef contexts.
+                     */
+                    if ((cpi->oxcf.error_resilient_mode &
+                            VPX_ERROR_RESILIENT_PARTITIONS) &&
+                        cpi->common.frame_type == KEY_FRAME && newp != *Pold)
+                        u = 1;
+
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+                    cpi->update_probs[i][j][k][t] = u;
+#else
+                    vp8_write(w, u, upd);
+#endif
+
+
+#ifdef ENTROPY_STATS
+                    ++ tree_update_hist [i][j][k][t] [u];
+#endif
+
+                    if (u)
+                    {
+                        /* send/use new probability */
+
+                        *Pold = newp;
+#if !(CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)
+                        vp8_write_literal(w, newp, 8);
+#endif
+
+                        savings += s;
+
+                    }
+
+                }
+                while (++t < ENTROPY_NODES);
+
+                /* Accum token counts for generation of default statistics */
+#ifdef ENTROPY_STATS
+                t = 0;
+
+                do
+                {
+                    context_counters [i][j][k][t] += cpi->coef_counts [i][j][k][t];
+                }
+                while (++t < MAX_ENTROPY_TOKENS);
+
+#endif
+
+            }
+            while (++k < PREV_COEF_CONTEXTS);
+        }
+        while (++j < COEF_BANDS);
+    }
+    while (++i < BLOCK_TYPES);
+
+}
+
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+static void pack_coef_probs(VP8_COMP *cpi)
+{
+    int i = 0;
+    vp8_writer *const w = cpi->bc;
+
+    do
+    {
+        int j = 0;
+
+        do
+        {
+            int k = 0;
+
+            do
+            {
+                int t = 0;      /* token/prob index */
+
+                do
+                {
+                    const vp8_prob newp = cpi->common.fc.coef_probs [i][j][k][t];
+                    const vp8_prob upd = vp8_coef_update_probs [i][j][k][t];
+
+                    const char u = cpi->update_probs[i][j][k][t] ;
+
+                    vp8_write(w, u, upd);
+
+                    if (u)
+                    {
+                        /* send/use new probability */
+                        vp8_write_literal(w, newp, 8);
+                    }
+                }
+                while (++t < ENTROPY_NODES);
+            }
+            while (++k < PREV_COEF_CONTEXTS);
+        }
+        while (++j < COEF_BANDS);
+    }
+    while (++i < BLOCK_TYPES);
+}
+#endif
+
+#ifdef PACKET_TESTING
+FILE *vpxlogc = 0;
+#endif
+
+static void put_delta_q(vp8_writer *bc, int delta_q)
+{
+    if (delta_q != 0)
+    {
+        vp8_write_bit(bc, 1);
+        vp8_write_literal(bc, abs(delta_q), 4);
+
+        if (delta_q < 0)
+            vp8_write_bit(bc, 1);
+        else
+            vp8_write_bit(bc, 0);
+    }
+    else
+        vp8_write_bit(bc, 0);
+}
+
+void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned char * dest_end, unsigned long *size)
+{
+    int i, j;
+    VP8_HEADER oh;
+    VP8_COMMON *const pc = & cpi->common;
+    vp8_writer *const bc = cpi->bc;
+    MACROBLOCKD *const xd = & cpi->mb.e_mbd;
+    int extra_bytes_packed = 0;
+
+    unsigned char *cx_data = dest;
+    unsigned char *cx_data_end = dest_end;
+    const int *mb_feature_data_bits;
+
+    oh.show_frame = (int) pc->show_frame;
+    oh.type = (int)pc->frame_type;
+    oh.version = pc->version;
+    oh.first_partition_length_in_bytes = 0;
+
+    mb_feature_data_bits = vp8_mb_feature_data_bits;
+
+    bc[0].error = &pc->error;
+
+    validate_buffer(cx_data, 3, cx_data_end, &cpi->common.error);
+    cx_data += 3;
+
+#if defined(SECTIONBITS_OUTPUT)
+    Sectionbits[active_section = 1] += sizeof(VP8_HEADER) * 8 * 256;
+#endif
+
+    //vp8_kf_default_bmode_probs() is called in vp8_setup_key_frame() once for each
+    //K frame before encode frame. pc->kf_bmode_prob doesn't get changed anywhere
+    //else. No need to call it again here. --yw
+    //vp8_kf_default_bmode_probs( pc->kf_bmode_prob);
+
+    // every keyframe send startcode, width, height, scale factor, clamp and color type
+    if (oh.type == KEY_FRAME)
+    {
+        int v;
+
+        validate_buffer(cx_data, 7, cx_data_end, &cpi->common.error);
+
+        // Start / synch code
+        cx_data[0] = 0x9D;
+        cx_data[1] = 0x01;
+        cx_data[2] = 0x2a;
+
+        v = (pc->horiz_scale << 14) | pc->Width;
+        cx_data[3] = v;
+        cx_data[4] = v >> 8;
+
+        v = (pc->vert_scale << 14) | pc->Height;
+        cx_data[5] = v;
+        cx_data[6] = v >> 8;
+
+
+        extra_bytes_packed = 7;
+        cx_data += extra_bytes_packed ;
+
+        vp8_start_encode(bc, cx_data, cx_data_end);
+
+        // signal clr type
+        vp8_write_bit(bc, pc->clr_type);
+        vp8_write_bit(bc, pc->clamp_type);
+
+    }
+    else
+        vp8_start_encode(bc, cx_data, cx_data_end);
+
+
+    // Signal whether or not Segmentation is enabled
+    vp8_write_bit(bc, xd->segmentation_enabled);
+
+    // Indicate which features are enabled
+    if (xd->segmentation_enabled)
+    {
+        // Signal whether or not the segmentation map is being updated.
+        vp8_write_bit(bc, xd->update_mb_segmentation_map);
+        vp8_write_bit(bc, xd->update_mb_segmentation_data);
+
+        if (xd->update_mb_segmentation_data)
+        {
+            signed char Data;
+
+            vp8_write_bit(bc, xd->mb_segement_abs_delta);
+
+            // For each segmentation feature (Quant and loop filter level)
+            for (i = 0; i < MB_LVL_MAX; i++)
+            {
+                // For each of the segments
+                for (j = 0; j < MAX_MB_SEGMENTS; j++)
+                {
+                    Data = xd->segment_feature_data[i][j];
+
+                    // Frame level data
+                    if (Data)
+                    {
+                        vp8_write_bit(bc, 1);
+
+                        if (Data < 0)
+                        {
+                            Data = - Data;
+                            vp8_write_literal(bc, Data, mb_feature_data_bits[i]);
+                            vp8_write_bit(bc, 1);
+                        }
+                        else
+                        {
+                            vp8_write_literal(bc, Data, mb_feature_data_bits[i]);
+                            vp8_write_bit(bc, 0);
+                        }
+                    }
+                    else
+                        vp8_write_bit(bc, 0);
+                }
+            }
+        }
+
+        if (xd->update_mb_segmentation_map)
+        {
+            // Write the probs used to decode the segment id for each macro block.
+            for (i = 0; i < MB_FEATURE_TREE_PROBS; i++)
+            {
+                int Data = xd->mb_segment_tree_probs[i];
+
+                if (Data != 255)
+                {
+                    vp8_write_bit(bc, 1);
+                    vp8_write_literal(bc, Data, 8);
+                }
+                else
+                    vp8_write_bit(bc, 0);
+            }
+        }
+    }
+
+    // Code to determine whether or not to update the scan order.
+    vp8_write_bit(bc, pc->filter_type);
+    vp8_write_literal(bc, pc->filter_level, 6);
+    vp8_write_literal(bc, pc->sharpness_level, 3);
+
+    // Write out loop filter deltas applied at the MB level based on mode or ref frame (if they are enabled).
+    vp8_write_bit(bc, xd->mode_ref_lf_delta_enabled);
+
+    if (xd->mode_ref_lf_delta_enabled)
+    {
+        // Do the deltas need to be updated
+        int send_update = xd->mode_ref_lf_delta_update
+                          || cpi->oxcf.error_resilient_mode;
+
+        vp8_write_bit(bc, send_update);
+        if (send_update)
+        {
+            int Data;
+
+            // Send update
+            for (i = 0; i < MAX_REF_LF_DELTAS; i++)
+            {
+                Data = xd->ref_lf_deltas[i];
+
+                // Frame level data
+                if (xd->ref_lf_deltas[i] != xd->last_ref_lf_deltas[i]
+                    || cpi->oxcf.error_resilient_mode)
+                {
+                    xd->last_ref_lf_deltas[i] = xd->ref_lf_deltas[i];
+                    vp8_write_bit(bc, 1);
+
+                    if (Data > 0)
+                    {
+                        vp8_write_literal(bc, (Data & 0x3F), 6);
+                        vp8_write_bit(bc, 0);    // sign
+                    }
+                    else
+                    {
+                        Data = -Data;
+                        vp8_write_literal(bc, (Data & 0x3F), 6);
+                        vp8_write_bit(bc, 1);    // sign
+                    }
+                }
+                else
+                    vp8_write_bit(bc, 0);
+            }
+
+            // Send update
+            for (i = 0; i < MAX_MODE_LF_DELTAS; i++)
+            {
+                Data = xd->mode_lf_deltas[i];
+
+                if (xd->mode_lf_deltas[i] != xd->last_mode_lf_deltas[i]
+                    || cpi->oxcf.error_resilient_mode)
+                {
+                    xd->last_mode_lf_deltas[i] = xd->mode_lf_deltas[i];
+                    vp8_write_bit(bc, 1);
+
+                    if (Data > 0)
+                    {
+                        vp8_write_literal(bc, (Data & 0x3F), 6);
+                        vp8_write_bit(bc, 0);    // sign
+                    }
+                    else
+                    {
+                        Data = -Data;
+                        vp8_write_literal(bc, (Data & 0x3F), 6);
+                        vp8_write_bit(bc, 1);    // sign
+                    }
+                }
+                else
+                    vp8_write_bit(bc, 0);
+            }
+        }
+    }
+
+    //signal here is multi token partition is enabled
+    vp8_write_literal(bc, pc->multi_token_partition, 2);
+
+    // Frame Qbaseline quantizer index
+    vp8_write_literal(bc, pc->base_qindex, 7);
+
+    // Transmit Dc, Second order and Uv quantizer delta information
+    put_delta_q(bc, pc->y1dc_delta_q);
+    put_delta_q(bc, pc->y2dc_delta_q);
+    put_delta_q(bc, pc->y2ac_delta_q);
+    put_delta_q(bc, pc->uvdc_delta_q);
+    put_delta_q(bc, pc->uvac_delta_q);
+
+    // When there is a key frame all reference buffers are updated using the new key frame
+    if (pc->frame_type != KEY_FRAME)
+    {
+        // Should the GF or ARF be updated using the transmitted frame or buffer
+        vp8_write_bit(bc, pc->refresh_golden_frame);
+        vp8_write_bit(bc, pc->refresh_alt_ref_frame);
+
+        // If not being updated from current frame should either GF or ARF be updated from another buffer
+        if (!pc->refresh_golden_frame)
+            vp8_write_literal(bc, pc->copy_buffer_to_gf, 2);
+
+        if (!pc->refresh_alt_ref_frame)
+            vp8_write_literal(bc, pc->copy_buffer_to_arf, 2);
+
+        // Indicate reference frame sign bias for Golden and ARF frames (always 0 for last frame buffer)
+        vp8_write_bit(bc, pc->ref_frame_sign_bias[GOLDEN_FRAME]);
+        vp8_write_bit(bc, pc->ref_frame_sign_bias[ALTREF_FRAME]);
+    }
+
+#if !(CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)
+    if (cpi->oxcf.error_resilient_mode & VPX_ERROR_RESILIENT_PARTITIONS)
+    {
+        if (pc->frame_type == KEY_FRAME)
+            pc->refresh_entropy_probs = 1;
+        else
+            pc->refresh_entropy_probs = 0;
+    }
+#endif
+
+    vp8_write_bit(bc, pc->refresh_entropy_probs);
+
+    if (pc->frame_type != KEY_FRAME)
+        vp8_write_bit(bc, pc->refresh_last_frame);
+
+#ifdef ENTROPY_STATS
+
+    if (pc->frame_type == INTER_FRAME)
+        active_section = 0;
+    else
+        active_section = 7;
+
+#endif
+
+    vp8_clear_system_state();  //__asm emms;
+
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+    pack_coef_probs(cpi);
+#else
+    if (pc->refresh_entropy_probs == 0)
+    {
+        // save a copy for later refresh
+        vpx_memcpy(&cpi->common.lfc, &cpi->common.fc, sizeof(cpi->common.fc));
+    }
+
+    vp8_update_coef_probs(cpi);
+#endif
+
+#ifdef ENTROPY_STATS
+    active_section = 2;
+#endif
+
+    // Write out the mb_no_coeff_skip flag
+    vp8_write_bit(bc, pc->mb_no_coeff_skip);
+
+    if (pc->frame_type == KEY_FRAME)
+    {
+        write_kfmodes(cpi);
+
+#ifdef ENTROPY_STATS
+        active_section = 8;
+#endif
+    }
+    else
+    {
+        pack_inter_mode_mvs(cpi);
+
+#ifdef ENTROPY_STATS
+        active_section = 1;
+#endif
+    }
+
+    vp8_stop_encode(bc);
+
+    cx_data += bc->pos;
+
+    oh.first_partition_length_in_bytes = cpi->bc->pos;
+
+    /* update frame tag */
+    {
+        int v = (oh.first_partition_length_in_bytes << 5) |
+                (oh.show_frame << 4) |
+                (oh.version << 1) |
+                oh.type;
+
+        dest[0] = v;
+        dest[1] = v >> 8;
+        dest[2] = v >> 16;
+    }
+
+    *size = VP8_HEADER_SIZE + extra_bytes_packed + cpi->bc->pos;
+
+    cpi->partition_sz[0] = *size;
+
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+    {
+        const int num_part = (1 << pc->multi_token_partition);
+        unsigned char * dp = cpi->partition_d[0] + cpi->partition_sz[0];
+
+        if (num_part > 1)
+        {
+            /* write token part sizes (all but last) if more than 1 */
+            validate_buffer(dp, 3 * (num_part - 1), cpi->partition_d_end[0],
+                            &pc->error);
+
+            cpi->partition_sz[0] += 3*(num_part-1);
+
+            for(i = 1; i < num_part; i++)
+            {
+                write_partition_size(dp, cpi->partition_sz[i]);
+                dp += 3;
+            }
+        }
+
+        if (!cpi->output_partition)
+        {
+            /* concatenate partition buffers */
+            for(i = 0; i < num_part; i++)
+            {
+                vpx_memmove(dp, cpi->partition_d[i+1], cpi->partition_sz[i+1]);
+                cpi->partition_d[i+1] = dp;
+                dp += cpi->partition_sz[i+1];
+            }
+        }
+
+        /* update total size */
+        *size = 0;
+        for(i = 0; i < num_part+1; i++)
+        {
+            *size += cpi->partition_sz[i];
+        }
+    }
+#else
+    if (pc->multi_token_partition != ONE_PARTITION)
+    {
+        int num_part = 1 << pc->multi_token_partition;
+
+        /* partition size table at the end of first partition */
+        cpi->partition_sz[0] += 3 * (num_part - 1);
+        *size += 3 * (num_part - 1);
+
+        validate_buffer(cx_data, 3 * (num_part - 1), cx_data_end,
+                        &pc->error);
+
+        for(i = 1; i < num_part + 1; i++)
+        {
+            cpi->bc[i].error = &pc->error;
+        }
+
+        pack_tokens_into_partitions(cpi, cx_data + 3 * (num_part - 1),
+                                    cx_data_end, num_part);
+
+        for(i = 1; i < num_part; i++)
+        {
+            cpi->partition_sz[i] = cpi->bc[i].pos;
+            write_partition_size(cx_data, cpi->partition_sz[i]);
+            cx_data += 3;
+            *size += cpi->partition_sz[i]; /* add to total */
+        }
+
+        /* add last partition to total size */
+        cpi->partition_sz[i] = cpi->bc[i].pos;
+        *size += cpi->partition_sz[i];
+    }
+    else
+    {
+        bc[1].error = &pc->error;
+
+        vp8_start_encode(&cpi->bc[1], cx_data, cx_data_end);
+
+#if CONFIG_MULTITHREAD
+        if (cpi->b_multi_threaded)
+            pack_mb_row_tokens(cpi, &cpi->bc[1]);
+        else
+#endif
+            pack_tokens(&cpi->bc[1], cpi->tok, cpi->tok_count);
+
+        vp8_stop_encode(&cpi->bc[1]);
+
+        *size += cpi->bc[1].pos;
+        cpi->partition_sz[1] = cpi->bc[1].pos;
+    }
+#endif
+}
+
+#ifdef ENTROPY_STATS
+void print_tree_update_probs()
+{
+    int i, j, k, l;
+    FILE *f = fopen("context.c", "a");
+    int Sum;
+    fprintf(f, "\n/* Update probabilities for token entropy tree. */\n\n");
+    fprintf(f, "const vp8_prob tree_update_probs[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES] = {\n");
+
+    for (i = 0; i < BLOCK_TYPES; i++)
+    {
+        fprintf(f, "  { \n");
+
+        for (j = 0; j < COEF_BANDS; j++)
+        {
+            fprintf(f, "    {\n");
+
+            for (k = 0; k < PREV_COEF_CONTEXTS; k++)
+            {
+                fprintf(f, "      {");
+
+                for (l = 0; l < ENTROPY_NODES; l++)
+                {
+                    Sum = tree_update_hist[i][j][k][l][0] + tree_update_hist[i][j][k][l][1];
+
+                    if (Sum > 0)
+                    {
+                        if (((tree_update_hist[i][j][k][l][0] * 255) / Sum) > 0)
+                            fprintf(f, "%3ld, ", (tree_update_hist[i][j][k][l][0] * 255) / Sum);
+                        else
+                            fprintf(f, "%3ld, ", 1);
+                    }
+                    else
+                        fprintf(f, "%3ld, ", 128);
+                }
+
+                fprintf(f, "},\n");
+            }
+
+            fprintf(f, "    },\n");
+        }
+
+        fprintf(f, "  },\n");
+    }
+
+    fprintf(f, "};\n");
+    fclose(f);
+}
+#endif
diff --git a/vp8/encoder/bitstream.h b/vp8/encoder/bitstream.h
new file mode 100644 (file)
index 0000000..455a94f
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_BITSTREAM_H
+#define __INC_BITSTREAM_H
+
+#if HAVE_EDSP
+void vp8cx_pack_tokens_armv5(vp8_writer *w, const TOKENEXTRA *p, int xcount,
+                             const vp8_token *,
+                             const vp8_extra_bit_struct *,
+                             const vp8_tree_index *);
+void vp8cx_pack_tokens_into_partitions_armv5(VP8_COMP *,
+                                             unsigned char * cx_data,
+                                             const unsigned char *cx_data_end,
+                                             int num_parts,
+                                             const vp8_token *,
+                                             const vp8_extra_bit_struct *,
+                                             const vp8_tree_index *);
+void vp8cx_pack_mb_row_tokens_armv5(VP8_COMP *cpi, vp8_writer *w,
+                                    const vp8_token *,
+                                    const vp8_extra_bit_struct *,
+                                    const vp8_tree_index *);
+# define pack_tokens(a,b,c)                  \
+    vp8cx_pack_tokens_armv5(a,b,c,vp8_coef_encodings,vp8_extra_bits,vp8_coef_tree)
+# define pack_tokens_into_partitions(a,b,c,d)  \
+    vp8cx_pack_tokens_into_partitions_armv5(a,b,c,d,vp8_coef_encodings,vp8_extra_bits,vp8_coef_tree)
+# define pack_mb_row_tokens(a,b)               \
+    vp8cx_pack_mb_row_tokens_armv5(a,b,vp8_coef_encodings,vp8_extra_bits,vp8_coef_tree)
+#else
+
+void vp8_pack_tokens_c(vp8_writer *w, const TOKENEXTRA *p, int xcount);
+
+# define pack_tokens(a,b,c)                    vp8_pack_tokens_c(a,b,c)
+# define pack_tokens_into_partitions(a,b,c,d)  pack_tokens_into_partitions_c(a,b,c,d)
+# define pack_mb_row_tokens(a,b)               pack_mb_row_tokens_c(a,b)
+#endif
+
+#endif
diff --git a/vp8/encoder/block.h b/vp8/encoder/block.h
new file mode 100644 (file)
index 0000000..6165d04
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_BLOCK_H
+#define __INC_BLOCK_H
+
+#include "vp8/common/onyx.h"
+#include "vp8/common/blockd.h"
+#include "vp8/common/entropymv.h"
+#include "vp8/common/entropy.h"
+#include "vpx_ports/mem.h"
+
+// motion search site
+typedef struct
+{
+    MV mv;
+    int offset;
+} search_site;
+
+typedef struct block
+{
+    // 16 Y blocks, 4 U blocks, 4 V blocks each with 16 entries
+    short *src_diff;
+    short *coeff;
+
+    // 16 Y blocks, 4 U blocks, 4 V blocks each with 16 entries
+    short *quant;
+    short *quant_fast;
+    unsigned char *quant_shift;
+    short *zbin;
+    short *zrun_zbin_boost;
+    short *round;
+
+    // Zbin Over Quant value
+    short zbin_extra;
+
+    unsigned char **base_src;
+    int src;
+    int src_stride;
+} BLOCK;
+
+typedef struct
+{
+    int count;
+    struct
+    {
+        B_PREDICTION_MODE mode;
+        int_mv mv;
+    } bmi[16];
+} PARTITION_INFO;
+
+typedef struct macroblock
+{
+    DECLARE_ALIGNED(16, short, src_diff[400]);       // 16x16 Y 8x8 U 8x8 V 4x4 2nd Y
+    DECLARE_ALIGNED(16, short, coeff[400]);     // 16x16 Y 8x8 U 8x8 V 4x4 2nd Y
+    DECLARE_ALIGNED(16, unsigned char, thismb[256]);
+
+    unsigned char *thismb_ptr;
+    // 16 Y blocks, 4 U blocks, 4 V blocks, 1 DC 2nd order block each with 16 entries
+    BLOCK block[25];
+
+    YV12_BUFFER_CONFIG src;
+
+    MACROBLOCKD e_mbd;
+    PARTITION_INFO *partition_info; /* work pointer */
+    PARTITION_INFO *pi;   /* Corresponds to upper left visible macroblock */
+    PARTITION_INFO *pip;  /* Base of allocated array */
+
+    int ref_frame_cost[MAX_REF_FRAMES];
+
+    search_site *ss;
+    int ss_count;
+    int searches_per_step;
+
+    int errorperbit;
+    int sadperbit16;
+    int sadperbit4;
+    int rddiv;
+    int rdmult;
+    unsigned int * mb_activity_ptr;
+    int * mb_norm_activity_ptr;
+    signed int act_zbin_adj;
+    signed int last_act_zbin_adj;
+
+    int mvcosts[2][MVvals+1];
+    int *mvcost[2];
+    int mvsadcosts[2][MVfpvals+1];
+    int *mvsadcost[2];
+    int mbmode_cost[2][MB_MODE_COUNT];
+    int intra_uv_mode_cost[2][MB_MODE_COUNT];
+    unsigned int bmode_costs[10][10][10];
+    unsigned int inter_bmode_costs[B_MODE_COUNT];
+
+    // These define limits to motion vector components to prevent them from extending outside the UMV borders
+    int mv_col_min;
+    int mv_col_max;
+    int mv_row_min;
+    int mv_row_max;
+
+    int skip;
+
+    int encode_breakout;
+
+    //char * gf_active_ptr;
+    signed char *gf_active_ptr;
+
+    unsigned char *active_ptr;
+    MV_CONTEXT *mvc;
+
+    unsigned int token_costs[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS];
+    int optimize;
+    int q_index;
+
+    void (*short_fdct4x4)(short *input, short *output, int pitch);
+    void (*short_fdct8x4)(short *input, short *output, int pitch);
+    void (*short_walsh4x4)(short *input, short *output, int pitch);
+    void (*quantize_b)(BLOCK *b, BLOCKD *d);
+    void (*quantize_b_pair)(BLOCK *b1, BLOCK *b2, BLOCKD *d0, BLOCKD *d1);
+
+} MACROBLOCK;
+
+
+#endif
diff --git a/vp8/encoder/boolhuff.c b/vp8/encoder/boolhuff.c
new file mode 100644 (file)
index 0000000..74770a2
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "boolhuff.h"
+
+#if defined(SECTIONBITS_OUTPUT)
+unsigned __int64 Sectionbits[500];
+
+#endif
+
+#ifdef ENTROPY_STATS
+unsigned int active_section = 0;
+#endif
+
+const unsigned int vp8_prob_cost[256] =
+{
+    2047, 2047, 1791, 1641, 1535, 1452, 1385, 1328, 1279, 1235, 1196, 1161, 1129, 1099, 1072, 1046,
+    1023, 1000,  979,  959,  940,  922,  905,  889,  873,  858,  843,  829,  816,  803,  790,  778,
+    767,  755,  744,  733,  723,  713,  703,  693,  684,  675,  666,  657,  649,  641,  633,  625,
+    617,  609,  602,  594,  587,  580,  573,  567,  560,  553,  547,  541,  534,  528,  522,  516,
+    511,  505,  499,  494,  488,  483,  477,  472,  467,  462,  457,  452,  447,  442,  437,  433,
+    428,  424,  419,  415,  410,  406,  401,  397,  393,  389,  385,  381,  377,  373,  369,  365,
+    361,  357,  353,  349,  346,  342,  338,  335,  331,  328,  324,  321,  317,  314,  311,  307,
+    304,  301,  297,  294,  291,  288,  285,  281,  278,  275,  272,  269,  266,  263,  260,  257,
+    255,  252,  249,  246,  243,  240,  238,  235,  232,  229,  227,  224,  221,  219,  216,  214,
+    211,  208,  206,  203,  201,  198,  196,  194,  191,  189,  186,  184,  181,  179,  177,  174,
+    172,  170,  168,  165,  163,  161,  159,  156,  154,  152,  150,  148,  145,  143,  141,  139,
+    137,  135,  133,  131,  129,  127,  125,  123,  121,  119,  117,  115,  113,  111,  109,  107,
+    105,  103,  101,   99,   97,   95,   93,   92,   90,   88,   86,   84,   82,   81,   79,   77,
+    75,   73,   72,   70,   68,   66,   65,   63,   61,   60,   58,   56,   55,   53,   51,   50,
+    48,   46,   45,   43,   41,   40,   38,   37,   35,   33,   32,   30,   29,   27,   25,   24,
+    22,   21,   19,   18,   16,   15,   13,   12,   10,    9,    7,    6,    4,    3,    1,   1
+};
+
+void vp8_start_encode(BOOL_CODER *br, unsigned char *source, unsigned char *source_end)
+{
+
+    br->lowvalue   = 0;
+    br->range      = 255;
+    br->count      = -24;
+    br->buffer     = source;
+    br->buffer_end = source_end;
+    br->pos        = 0;
+}
+
+void vp8_stop_encode(BOOL_CODER *br)
+{
+    int i;
+
+    for (i = 0; i < 32; i++)
+        vp8_encode_bool(br, 0, 128);
+}
+
+
+void vp8_encode_value(BOOL_CODER *br, int data, int bits)
+{
+    int bit;
+
+    for (bit = bits - 1; bit >= 0; bit--)
+        vp8_encode_bool(br, (1 & (data >> bit)), 0x80);
+
+}
diff --git a/vp8/encoder/boolhuff.h b/vp8/encoder/boolhuff.h
new file mode 100644 (file)
index 0000000..fb6cbaf
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/****************************************************************************
+*
+*   Module Title :     boolhuff.h
+*
+*   Description  :     Bool Coder header file.
+*
+****************************************************************************/
+#ifndef __INC_BOOLHUFF_H
+#define __INC_BOOLHUFF_H
+
+#include "vpx_ports/mem.h"
+#include "vpx/internal/vpx_codec_internal.h"
+
+typedef struct
+{
+    unsigned int lowvalue;
+    unsigned int range;
+    int count;
+    unsigned int pos;
+    unsigned char *buffer;
+    unsigned char *buffer_end;
+    struct vpx_internal_error_info *error;
+
+    // Variables used to track bit costs without outputing to the bitstream
+    unsigned int  measure_cost;
+    unsigned long bit_counter;
+} BOOL_CODER;
+
+extern void vp8_start_encode(BOOL_CODER *bc, unsigned char *buffer, unsigned char *buffer_end);
+
+extern void vp8_encode_value(BOOL_CODER *br, int data, int bits);
+extern void vp8_stop_encode(BOOL_CODER *bc);
+extern const unsigned int vp8_prob_cost[256];
+
+
+DECLARE_ALIGNED(16, extern const unsigned char, vp8_norm[256]);
+
+static int validate_buffer(const unsigned char *start,
+                           size_t               len,
+                           const unsigned char *end,
+                           struct vpx_internal_error_info *error)
+{
+    if (start + len > start && start + len < end)
+        return 1;
+    else
+        vpx_internal_error(error, VPX_CODEC_CORRUPT_FRAME,
+            "Truncated packet or corrupt partition ");
+
+    return 0;
+}
+static void vp8_encode_bool(BOOL_CODER *br, int bit, int probability)
+{
+    unsigned int split;
+    int count = br->count;
+    unsigned int range = br->range;
+    unsigned int lowvalue = br->lowvalue;
+    register unsigned int shift;
+
+#ifdef ENTROPY_STATS
+#if defined(SECTIONBITS_OUTPUT)
+
+    if (bit)
+        Sectionbits[active_section] += vp8_prob_cost[255-probability];
+    else
+        Sectionbits[active_section] += vp8_prob_cost[probability];
+
+#endif
+#endif
+
+    split = 1 + (((range - 1) * probability) >> 8);
+
+    range = split;
+
+    if (bit)
+    {
+        lowvalue += split;
+        range = br->range - split;
+    }
+
+    shift = vp8_norm[range];
+
+    range <<= shift;
+    count += shift;
+
+    if (count >= 0)
+    {
+        int offset = shift - count;
+
+        if ((lowvalue << (offset - 1)) & 0x80000000)
+        {
+            int x = br->pos - 1;
+
+            while (x >= 0 && br->buffer[x] == 0xff)
+            {
+                br->buffer[x] = (unsigned char)0;
+                x--;
+            }
+
+            br->buffer[x] += 1;
+        }
+
+        validate_buffer(br->buffer + br->pos, 1, br->buffer_end, br->error);
+        br->buffer[br->pos++] = (lowvalue >> (24 - offset));
+
+        lowvalue <<= offset;
+        shift = count;
+        lowvalue &= 0xffffff;
+        count -= 8 ;
+    }
+
+    lowvalue <<= shift;
+    br->count = count;
+    br->lowvalue = lowvalue;
+    br->range = range;
+}
+
+#endif
diff --git a/vp8/encoder/dct.c b/vp8/encoder/dct.c
new file mode 100644 (file)
index 0000000..b5a11ae
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include <math.h>
+
+void vp8_short_fdct4x4_c(short *input, short *output, int pitch)
+{
+    int i;
+    int a1, b1, c1, d1;
+    short *ip = input;
+    short *op = output;
+
+    for (i = 0; i < 4; i++)
+    {
+        a1 = ((ip[0] + ip[3])<<3);
+        b1 = ((ip[1] + ip[2])<<3);
+        c1 = ((ip[1] - ip[2])<<3);
+        d1 = ((ip[0] - ip[3])<<3);
+
+        op[0] = a1 + b1;
+        op[2] = a1 - b1;
+
+        op[1] = (c1 * 2217 + d1 * 5352 +  14500)>>12;
+        op[3] = (d1 * 2217 - c1 * 5352 +   7500)>>12;
+
+        ip += pitch / 2;
+        op += 4;
+
+    }
+    ip = output;
+    op = output;
+    for (i = 0; i < 4; i++)
+    {
+        a1 = ip[0] + ip[12];
+        b1 = ip[4] + ip[8];
+        c1 = ip[4] - ip[8];
+        d1 = ip[0] - ip[12];
+
+        op[0]  = ( a1 + b1 + 7)>>4;
+        op[8]  = ( a1 - b1 + 7)>>4;
+
+        op[4]  =((c1 * 2217 + d1 * 5352 +  12000)>>16) + (d1!=0);
+        op[12] = (d1 * 2217 - c1 * 5352 +  51000)>>16;
+
+        ip++;
+        op++;
+    }
+}
+
+void vp8_short_fdct8x4_c(short *input, short *output, int pitch)
+{
+    vp8_short_fdct4x4_c(input,   output,    pitch);
+    vp8_short_fdct4x4_c(input + 4, output + 16, pitch);
+}
+
+void vp8_short_walsh4x4_c(short *input, short *output, int pitch)
+{
+    int i;
+    int a1, b1, c1, d1;
+    int a2, b2, c2, d2;
+    short *ip = input;
+    short *op = output;
+
+
+    for (i = 0; i < 4; i++)
+    {
+        a1 = ((ip[0] + ip[2])<<2);
+        d1 = ((ip[1] + ip[3])<<2);
+        c1 = ((ip[1] - ip[3])<<2);
+        b1 = ((ip[0] - ip[2])<<2);
+
+        op[0] = a1 + d1 + (a1!=0);
+        op[1] = b1 + c1;
+        op[2] = b1 - c1;
+        op[3] = a1 - d1;
+        ip += pitch / 2;
+        op += 4;
+    }
+
+    ip = output;
+    op = output;
+
+    for (i = 0; i < 4; i++)
+    {
+        a1 = ip[0] + ip[8];
+        d1 = ip[4] + ip[12];
+        c1 = ip[4] - ip[12];
+        b1 = ip[0] - ip[8];
+
+        a2 = a1 + d1;
+        b2 = b1 + c1;
+        c2 = b1 - c1;
+        d2 = a1 - d1;
+
+        a2 += a2<0;
+        b2 += b2<0;
+        c2 += c2<0;
+        d2 += d2<0;
+
+        op[0] = (a2+3) >> 3;
+        op[4] = (b2+3) >> 3;
+        op[8] = (c2+3) >> 3;
+        op[12]= (d2+3) >> 3;
+
+        ip++;
+        op++;
+    }
+}
diff --git a/vp8/encoder/dct_value_cost.h b/vp8/encoder/dct_value_cost.h
new file mode 100644 (file)
index 0000000..e892765
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/* Generated file, included by tokenize.c  */
+/* Values generated by fill_value_tokens() */
+
+static const short dct_value_cost[2048*2] =
+{
+    8285, 8277, 8267, 8259, 8253, 8245, 8226, 8218, 8212, 8204, 8194, 8186,
+    8180, 8172, 8150, 8142, 8136, 8128, 8118, 8110, 8104, 8096, 8077, 8069,
+    8063, 8055, 8045, 8037, 8031, 8023, 7997, 7989, 7983, 7975, 7965, 7957,
+    7951, 7943, 7924, 7916, 7910, 7902, 7892, 7884, 7878, 7870, 7848, 7840,
+    7834, 7826, 7816, 7808, 7802, 7794, 7775, 7767, 7761, 7753, 7743, 7735,
+    7729, 7721, 7923, 7915, 7909, 7901, 7891, 7883, 7877, 7869, 7850, 7842,
+    7836, 7828, 7818, 7810, 7804, 7796, 7774, 7766, 7760, 7752, 7742, 7734,
+    7728, 7720, 7701, 7693, 7687, 7679, 7669, 7661, 7655, 7647, 7621, 7613,
+    7607, 7599, 7589, 7581, 7575, 7567, 7548, 7540, 7534, 7526, 7516, 7508,
+    7502, 7494, 7472, 7464, 7458, 7450, 7440, 7432, 7426, 7418, 7399, 7391,
+    7385, 7377, 7367, 7359, 7353, 7345, 7479, 7471, 7465, 7457, 7447, 7439,
+    7433, 7425, 7406, 7398, 7392, 7384, 7374, 7366, 7360, 7352, 7330, 7322,
+    7316, 7308, 7298, 7290, 7284, 7276, 7257, 7249, 7243, 7235, 7225, 7217,
+    7211, 7203, 7177, 7169, 7163, 7155, 7145, 7137, 7131, 7123, 7104, 7096,
+    7090, 7082, 7072, 7064, 7058, 7050, 7028, 7020, 7014, 7006, 6996, 6988,
+    6982, 6974, 6955, 6947, 6941, 6933, 6923, 6915, 6909, 6901, 7632, 7624,
+    7618, 7610, 7600, 7592, 7586, 7578, 7559, 7551, 7545, 7537, 7527, 7519,
+    7513, 7505, 7483, 7475, 7469, 7461, 7451, 7443, 7437, 7429, 7410, 7402,
+    7396, 7388, 7378, 7370, 7364, 7356, 7330, 7322, 7316, 7308, 7298, 7290,
+    7284, 7276, 7257, 7249, 7243, 7235, 7225, 7217, 7211, 7203, 7181, 7173,
+    7167, 7159, 7149, 7141, 7135, 7127, 7108, 7100, 7094, 7086, 7076, 7068,
+    7062, 7054, 7188, 7180, 7174, 7166, 7156, 7148, 7142, 7134, 7115, 7107,
+    7101, 7093, 7083, 7075, 7069, 7061, 7039, 7031, 7025, 7017, 7007, 6999,
+    6993, 6985, 6966, 6958, 6952, 6944, 6934, 6926, 6920, 6912, 6886, 6878,
+    6872, 6864, 6854, 6846, 6840, 6832, 6813, 6805, 6799, 6791, 6781, 6773,
+    6767, 6759, 6737, 6729, 6723, 6715, 6705, 6697, 6691, 6683, 6664, 6656,
+    6650, 6642, 6632, 6624, 6618, 6610, 6812, 6804, 6798, 6790, 6780, 6772,
+    6766, 6758, 6739, 6731, 6725, 6717, 6707, 6699, 6693, 6685, 6663, 6655,
+    6649, 6641, 6631, 6623, 6617, 6609, 6590, 6582, 6576, 6568, 6558, 6550,
+    6544, 6536, 6510, 6502, 6496, 6488, 6478, 6470, 6464, 6456, 6437, 6429,
+    6423, 6415, 6405, 6397, 6391, 6383, 6361, 6353, 6347, 6339, 6329, 6321,
+    6315, 6307, 6288, 6280, 6274, 6266, 6256, 6248, 6242, 6234, 6368, 6360,
+    6354, 6346, 6336, 6328, 6322, 6314, 6295, 6287, 6281, 6273, 6263, 6255,
+    6249, 6241, 6219, 6211, 6205, 6197, 6187, 6179, 6173, 6165, 6146, 6138,
+    6132, 6124, 6114, 6106, 6100, 6092, 6066, 6058, 6052, 6044, 6034, 6026,
+    6020, 6012, 5993, 5985, 5979, 5971, 5961, 5953, 5947, 5939, 5917, 5909,
+    5903, 5895, 5885, 5877, 5871, 5863, 5844, 5836, 5830, 5822, 5812, 5804,
+    5798, 5790, 6697, 6689, 6683, 6675, 6665, 6657, 6651, 6643, 6624, 6616,
+    6610, 6602, 6592, 6584, 6578, 6570, 6548, 6540, 6534, 6526, 6516, 6508,
+    6502, 6494, 6475, 6467, 6461, 6453, 6443, 6435, 6429, 6421, 6395, 6387,
+    6381, 6373, 6363, 6355, 6349, 6341, 6322, 6314, 6308, 6300, 6290, 6282,
+    6276, 6268, 6246, 6238, 6232, 6224, 6214, 6206, 6200, 6192, 6173, 6165,
+    6159, 6151, 6141, 6133, 6127, 6119, 6253, 6245, 6239, 6231, 6221, 6213,
+    6207, 6199, 6180, 6172, 6166, 6158, 6148, 6140, 6134, 6126, 6104, 6096,
+    6090, 6082, 6072, 6064, 6058, 6050, 6031, 6023, 6017, 6009, 5999, 5991,
+    5985, 5977, 5951, 5943, 5937, 5929, 5919, 5911, 5905, 5897, 5878, 5870,
+    5864, 5856, 5846, 5838, 5832, 5824, 5802, 5794, 5788, 5780, 5770, 5762,
+    5756, 5748, 5729, 5721, 5715, 5707, 5697, 5689, 5683, 5675, 5877, 5869,
+    5863, 5855, 5845, 5837, 5831, 5823, 5804, 5796, 5790, 5782, 5772, 5764,
+    5758, 5750, 5728, 5720, 5714, 5706, 5696, 5688, 5682, 5674, 5655, 5647,
+    5641, 5633, 5623, 5615, 5609, 5601, 5575, 5567, 5561, 5553, 5543, 5535,
+    5529, 5521, 5502, 5494, 5488, 5480, 5470, 5462, 5456, 5448, 5426, 5418,
+    5412, 5404, 5394, 5386, 5380, 5372, 5353, 5345, 5339, 5331, 5321, 5313,
+    5307, 5299, 5433, 5425, 5419, 5411, 5401, 5393, 5387, 5379, 5360, 5352,
+    5346, 5338, 5328, 5320, 5314, 5306, 5284, 5276, 5270, 5262, 5252, 5244,
+    5238, 5230, 5211, 5203, 5197, 5189, 5179, 5171, 5165, 5157, 5131, 5123,
+    5117, 5109, 5099, 5091, 5085, 5077, 5058, 5050, 5044, 5036, 5026, 5018,
+    5012, 5004, 4982, 4974, 4968, 4960, 4950, 4942, 4936, 4928, 4909, 4901,
+    4895, 4887, 4877, 4869, 4863, 4855, 5586, 5578, 5572, 5564, 5554, 5546,
+    5540, 5532, 5513, 5505, 5499, 5491, 5481, 5473, 5467, 5459, 5437, 5429,
+    5423, 5415, 5405, 5397, 5391, 5383, 5364, 5356, 5350, 5342, 5332, 5324,
+    5318, 5310, 5284, 5276, 5270, 5262, 5252, 5244, 5238, 5230, 5211, 5203,
+    5197, 5189, 5179, 5171, 5165, 5157, 5135, 5127, 5121, 5113, 5103, 5095,
+    5089, 5081, 5062, 5054, 5048, 5040, 5030, 5022, 5016, 5008, 5142, 5134,
+    5128, 5120, 5110, 5102, 5096, 5088, 5069, 5061, 5055, 5047, 5037, 5029,
+    5023, 5015, 4993, 4985, 4979, 4971, 4961, 4953, 4947, 4939, 4920, 4912,
+    4906, 4898, 4888, 4880, 4874, 4866, 4840, 4832, 4826, 4818, 4808, 4800,
+    4794, 4786, 4767, 4759, 4753, 4745, 4735, 4727, 4721, 4713, 4691, 4683,
+    4677, 4669, 4659, 4651, 4645, 4637, 4618, 4610, 4604, 4596, 4586, 4578,
+    4572, 4564, 4766, 4758, 4752, 4744, 4734, 4726, 4720, 4712, 4693, 4685,
+    4679, 4671, 4661, 4653, 4647, 4639, 4617, 4609, 4603, 4595, 4585, 4577,
+    4571, 4563, 4544, 4536, 4530, 4522, 4512, 4504, 4498, 4490, 4464, 4456,
+    4450, 4442, 4432, 4424, 4418, 4410, 4391, 4383, 4377, 4369, 4359, 4351,
+    4345, 4337, 4315, 4307, 4301, 4293, 4283, 4275, 4269, 4261, 4242, 4234,
+    4228, 4220, 4210, 4202, 4196, 4188, 4322, 4314, 4308, 4300, 4290, 4282,
+    4276, 4268, 4249, 4241, 4235, 4227, 4217, 4209, 4203, 4195, 4173, 4165,
+    4159, 4151, 4141, 4133, 4127, 4119, 4100, 4092, 4086, 4078, 4068, 4060,
+    4054, 4046, 4020, 4012, 4006, 3998, 3988, 3980, 3974, 3966, 3947, 3939,
+    3933, 3925, 3915, 3907, 3901, 3893, 3871, 3863, 3857, 3849, 3839, 3831,
+    3825, 3817, 3798, 3790, 3784, 3776, 3766, 3758, 3752, 3744, 6697, 6689,
+    6683, 6675, 6665, 6657, 6651, 6643, 6624, 6616, 6610, 6602, 6592, 6584,
+    6578, 6570, 6548, 6540, 6534, 6526, 6516, 6508, 6502, 6494, 6475, 6467,
+    6461, 6453, 6443, 6435, 6429, 6421, 6395, 6387, 6381, 6373, 6363, 6355,
+    6349, 6341, 6322, 6314, 6308, 6300, 6290, 6282, 6276, 6268, 6246, 6238,
+    6232, 6224, 6214, 6206, 6200, 6192, 6173, 6165, 6159, 6151, 6141, 6133,
+    6127, 6119, 6253, 6245, 6239, 6231, 6221, 6213, 6207, 6199, 6180, 6172,
+    6166, 6158, 6148, 6140, 6134, 6126, 6104, 6096, 6090, 6082, 6072, 6064,
+    6058, 6050, 6031, 6023, 6017, 6009, 5999, 5991, 5985, 5977, 5951, 5943,
+    5937, 5929, 5919, 5911, 5905, 5897, 5878, 5870, 5864, 5856, 5846, 5838,
+    5832, 5824, 5802, 5794, 5788, 5780, 5770, 5762, 5756, 5748, 5729, 5721,
+    5715, 5707, 5697, 5689, 5683, 5675, 5877, 5869, 5863, 5855, 5845, 5837,
+    5831, 5823, 5804, 5796, 5790, 5782, 5772, 5764, 5758, 5750, 5728, 5720,
+    5714, 5706, 5696, 5688, 5682, 5674, 5655, 5647, 5641, 5633, 5623, 5615,
+    5609, 5601, 5575, 5567, 5561, 5553, 5543, 5535, 5529, 5521, 5502, 5494,
+    5488, 5480, 5470, 5462, 5456, 5448, 5426, 5418, 5412, 5404, 5394, 5386,
+    5380, 5372, 5353, 5345, 5339, 5331, 5321, 5313, 5307, 5299, 5433, 5425,
+    5419, 5411, 5401, 5393, 5387, 5379, 5360, 5352, 5346, 5338, 5328, 5320,
+    5314, 5306, 5284, 5276, 5270, 5262, 5252, 5244, 5238, 5230, 5211, 5203,
+    5197, 5189, 5179, 5171, 5165, 5157, 5131, 5123, 5117, 5109, 5099, 5091,
+    5085, 5077, 5058, 5050, 5044, 5036, 5026, 5018, 5012, 5004, 4982, 4974,
+    4968, 4960, 4950, 4942, 4936, 4928, 4909, 4901, 4895, 4887, 4877, 4869,
+    4863, 4855, 5586, 5578, 5572, 5564, 5554, 5546, 5540, 5532, 5513, 5505,
+    5499, 5491, 5481, 5473, 5467, 5459, 5437, 5429, 5423, 5415, 5405, 5397,
+    5391, 5383, 5364, 5356, 5350, 5342, 5332, 5324, 5318, 5310, 5284, 5276,
+    5270, 5262, 5252, 5244, 5238, 5230, 5211, 5203, 5197, 5189, 5179, 5171,
+    5165, 5157, 5135, 5127, 5121, 5113, 5103, 5095, 5089, 5081, 5062, 5054,
+    5048, 5040, 5030, 5022, 5016, 5008, 5142, 5134, 5128, 5120, 5110, 5102,
+    5096, 5088, 5069, 5061, 5055, 5047, 5037, 5029, 5023, 5015, 4993, 4985,
+    4979, 4971, 4961, 4953, 4947, 4939, 4920, 4912, 4906, 4898, 4888, 4880,
+    4874, 4866, 4840, 4832, 4826, 4818, 4808, 4800, 4794, 4786, 4767, 4759,
+    4753, 4745, 4735, 4727, 4721, 4713, 4691, 4683, 4677, 4669, 4659, 4651,
+    4645, 4637, 4618, 4610, 4604, 4596, 4586, 4578, 4572, 4564, 4766, 4758,
+    4752, 4744, 4734, 4726, 4720, 4712, 4693, 4685, 4679, 4671, 4661, 4653,
+    4647, 4639, 4617, 4609, 4603, 4595, 4585, 4577, 4571, 4563, 4544, 4536,
+    4530, 4522, 4512, 4504, 4498, 4490, 4464, 4456, 4450, 4442, 4432, 4424,
+    4418, 4410, 4391, 4383, 4377, 4369, 4359, 4351, 4345, 4337, 4315, 4307,
+    4301, 4293, 4283, 4275, 4269, 4261, 4242, 4234, 4228, 4220, 4210, 4202,
+    4196, 4188, 4322, 4314, 4308, 4300, 4290, 4282, 4276, 4268, 4249, 4241,
+    4235, 4227, 4217, 4209, 4203, 4195, 4173, 4165, 4159, 4151, 4141, 4133,
+    4127, 4119, 4100, 4092, 4086, 4078, 4068, 4060, 4054, 4046, 4020, 4012,
+    4006, 3998, 3988, 3980, 3974, 3966, 3947, 3939, 3933, 3925, 3915, 3907,
+    3901, 3893, 3871, 3863, 3857, 3849, 3839, 3831, 3825, 3817, 3798, 3790,
+    3784, 3776, 3766, 3758, 3752, 3744, 4651, 4643, 4637, 4629, 4619, 4611,
+    4605, 4597, 4578, 4570, 4564, 4556, 4546, 4538, 4532, 4524, 4502, 4494,
+    4488, 4480, 4470, 4462, 4456, 4448, 4429, 4421, 4415, 4407, 4397, 4389,
+    4383, 4375, 4349, 4341, 4335, 4327, 4317, 4309, 4303, 4295, 4276, 4268,
+    4262, 4254, 4244, 4236, 4230, 4222, 4200, 4192, 4186, 4178, 4168, 4160,
+    4154, 4146, 4127, 4119, 4113, 4105, 4095, 4087, 4081, 4073, 4207, 4199,
+    4193, 4185, 4175, 4167, 4161, 4153, 4134, 4126, 4120, 4112, 4102, 4094,
+    4088, 4080, 4058, 4050, 4044, 4036, 4026, 4018, 4012, 4004, 3985, 3977,
+    3971, 3963, 3953, 3945, 3939, 3931, 3905, 3897, 3891, 3883, 3873, 3865,
+    3859, 3851, 3832, 3824, 3818, 3810, 3800, 3792, 3786, 3778, 3756, 3748,
+    3742, 3734, 3724, 3716, 3710, 3702, 3683, 3675, 3669, 3661, 3651, 3643,
+    3637, 3629, 3831, 3823, 3817, 3809, 3799, 3791, 3785, 3777, 3758, 3750,
+    3744, 3736, 3726, 3718, 3712, 3704, 3682, 3674, 3668, 3660, 3650, 3642,
+    3636, 3628, 3609, 3601, 3595, 3587, 3577, 3569, 3563, 3555, 3529, 3521,
+    3515, 3507, 3497, 3489, 3483, 3475, 3456, 3448, 3442, 3434, 3424, 3416,
+    3410, 3402, 3380, 3372, 3366, 3358, 3348, 3340, 3334, 3326, 3307, 3299,
+    3293, 3285, 3275, 3267, 3261, 3253, 3387, 3379, 3373, 3365, 3355, 3347,
+    3341, 3333, 3314, 3306, 3300, 3292, 3282, 3274, 3268, 3260, 3238, 3230,
+    3224, 3216, 3206, 3198, 3192, 3184, 3165, 3157, 3151, 3143, 3133, 3125,
+    3119, 3111, 3085, 3077, 3071, 3063, 3053, 3045, 3039, 3031, 3012, 3004,
+    2998, 2990, 2980, 2972, 2966, 2958, 2936, 2928, 2922, 2914, 2904, 2896,
+    2890, 2882, 2863, 2855, 2849, 2841, 2831, 2823, 2817, 2809, 3540, 3532,
+    3526, 3518, 3508, 3500, 3494, 3486, 3467, 3459, 3453, 3445, 3435, 3427,
+    3421, 3413, 3391, 3383, 3377, 3369, 3359, 3351, 3345, 3337, 3318, 3310,
+    3304, 3296, 3286, 3278, 3272, 3264, 3238, 3230, 3224, 3216, 3206, 3198,
+    3192, 3184, 3165, 3157, 3151, 3143, 3133, 3125, 3119, 3111, 3089, 3081,
+    3075, 3067, 3057, 3049, 3043, 3035, 3016, 3008, 3002, 2994, 2984, 2976,
+    2970, 2962, 3096, 3088, 3082, 3074, 3064, 3056, 3050, 3042, 3023, 3015,
+    3009, 3001, 2991, 2983, 2977, 2969, 2947, 2939, 2933, 2925, 2915, 2907,
+    2901, 2893, 2874, 2866, 2860, 2852, 2842, 2834, 2828, 2820, 2794, 2786,
+    2780, 2772, 2762, 2754, 2748, 2740, 2721, 2713, 2707, 2699, 2689, 2681,
+    2675, 2667, 2645, 2637, 2631, 2623, 2613, 2605, 2599, 2591, 2572, 2564,
+    2558, 2550, 2540, 2532, 2526, 2518, 2720, 2712, 2706, 2698, 2688, 2680,
+    2674, 2666, 2647, 2639, 2633, 2625, 2615, 2607, 2601, 2593, 2571, 2563,
+    2557, 2549, 2539, 2531, 2525, 2517, 2498, 2490, 2484, 2476, 2466, 2458,
+    2452, 2444, 2418, 2410, 2404, 2396, 2386, 2378, 2372, 2364, 2345, 2337,
+    2331, 2323, 2313, 2305, 2299, 2291, 2269, 2261, 2255, 2247, 2237, 2229,
+    2223, 2215, 2196, 2188, 2182, 2174, 2164, 2156, 2150, 2142, 2276, 2268,
+    2262, 2254, 2244, 2236, 2230, 2222, 2203, 2195, 2189, 2181, 2171, 2163,
+    2157, 2149, 2127, 2119, 2113, 2105, 2095, 2087, 2081, 2073, 2054, 2046,
+    2040, 2032, 2022, 2014, 2008, 2000, 1974, 1966, 1960, 1952, 1942, 1934,
+    1928, 1920, 1901, 1893, 1887, 1879, 1869, 1861, 1855, 1847, 1825, 1817,
+    1811, 1803, 1793, 1785, 1779, 1771, 1752, 1744, 1738, 1730, 1720, 1712,
+    1706, 1698, 1897, 1883, 1860, 1846, 1819, 1805, 1782, 1768, 1723, 1709,
+    1686, 1672, 1645, 1631, 1608, 1594, 1574, 1560, 1537, 1523, 1496, 1482,
+    1459, 1445, 1400, 1386, 1363, 1349, 1322, 1308, 1285, 1271, 1608, 1565,
+    1535, 1492, 1446, 1403, 1373, 1330, 1312, 1269, 1239, 1196, 1150, 1107,
+    1077, 1034, 1291, 1218, 1171, 1098, 1015, 942, 895, 822, 953, 850,
+    729, 626, 618, 431, 257, 257, 257, 257, 0, 255, 255, 255,
+    255, 429, 616, 624, 727, 848, 951, 820, 893, 940, 1013, 1096,
+    1169, 1216, 1289, 1032, 1075, 1105, 1148, 1194, 1237, 1267, 1310, 1328,
+    1371, 1401, 1444, 1490, 1533, 1563, 1606, 1269, 1283, 1306, 1320, 1347,
+    1361, 1384, 1398, 1443, 1457, 1480, 1494, 1521, 1535, 1558, 1572, 1592,
+    1606, 1629, 1643, 1670, 1684, 1707, 1721, 1766, 1780, 1803, 1817, 1844,
+    1858, 1881, 1895, 1696, 1704, 1710, 1718, 1728, 1736, 1742, 1750, 1769,
+    1777, 1783, 1791, 1801, 1809, 1815, 1823, 1845, 1853, 1859, 1867, 1877,
+    1885, 1891, 1899, 1918, 1926, 1932, 1940, 1950, 1958, 1964, 1972, 1998,
+    2006, 2012, 2020, 2030, 2038, 2044, 2052, 2071, 2079, 2085, 2093, 2103,
+    2111, 2117, 2125, 2147, 2155, 2161, 2169, 2179, 2187, 2193, 2201, 2220,
+    2228, 2234, 2242, 2252, 2260, 2266, 2274, 2140, 2148, 2154, 2162, 2172,
+    2180, 2186, 2194, 2213, 2221, 2227, 2235, 2245, 2253, 2259, 2267, 2289,
+    2297, 2303, 2311, 2321, 2329, 2335, 2343, 2362, 2370, 2376, 2384, 2394,
+    2402, 2408, 2416, 2442, 2450, 2456, 2464, 2474, 2482, 2488, 2496, 2515,
+    2523, 2529, 2537, 2547, 2555, 2561, 2569, 2591, 2599, 2605, 2613, 2623,
+    2631, 2637, 2645, 2664, 2672, 2678, 2686, 2696, 2704, 2710, 2718, 2516,
+    2524, 2530, 2538, 2548, 2556, 2562, 2570, 2589, 2597, 2603, 2611, 2621,
+    2629, 2635, 2643, 2665, 2673, 2679, 2687, 2697, 2705, 2711, 2719, 2738,
+    2746, 2752, 2760, 2770, 2778, 2784, 2792, 2818, 2826, 2832, 2840, 2850,
+    2858, 2864, 2872, 2891, 2899, 2905, 2913, 2923, 2931, 2937, 2945, 2967,
+    2975, 2981, 2989, 2999, 3007, 3013, 3021, 3040, 3048, 3054, 3062, 3072,
+    3080, 3086, 3094, 2960, 2968, 2974, 2982, 2992, 3000, 3006, 3014, 3033,
+    3041, 3047, 3055, 3065, 3073, 3079, 3087, 3109, 3117, 3123, 3131, 3141,
+    3149, 3155, 3163, 3182, 3190, 3196, 3204, 3214, 3222, 3228, 3236, 3262,
+    3270, 3276, 3284, 3294, 3302, 3308, 3316, 3335, 3343, 3349, 3357, 3367,
+    3375, 3381, 3389, 3411, 3419, 3425, 3433, 3443, 3451, 3457, 3465, 3484,
+    3492, 3498, 3506, 3516, 3524, 3530, 3538, 2807, 2815, 2821, 2829, 2839,
+    2847, 2853, 2861, 2880, 2888, 2894, 2902, 2912, 2920, 2926, 2934, 2956,
+    2964, 2970, 2978, 2988, 2996, 3002, 3010, 3029, 3037, 3043, 3051, 3061,
+    3069, 3075, 3083, 3109, 3117, 3123, 3131, 3141, 3149, 3155, 3163, 3182,
+    3190, 3196, 3204, 3214, 3222, 3228, 3236, 3258, 3266, 3272, 3280, 3290,
+    3298, 3304, 3312, 3331, 3339, 3345, 3353, 3363, 3371, 3377, 3385, 3251,
+    3259, 3265, 3273, 3283, 3291, 3297, 3305, 3324, 3332, 3338, 3346, 3356,
+    3364, 3370, 3378, 3400, 3408, 3414, 3422, 3432, 3440, 3446, 3454, 3473,
+    3481, 3487, 3495, 3505, 3513, 3519, 3527, 3553, 3561, 3567, 3575, 3585,
+    3593, 3599, 3607, 3626, 3634, 3640, 3648, 3658, 3666, 3672, 3680, 3702,
+    3710, 3716, 3724, 3734, 3742, 3748, 3756, 3775, 3783, 3789, 3797, 3807,
+    3815, 3821, 3829, 3627, 3635, 3641, 3649, 3659, 3667, 3673, 3681, 3700,
+    3708, 3714, 3722, 3732, 3740, 3746, 3754, 3776, 3784, 3790, 3798, 3808,
+    3816, 3822, 3830, 3849, 3857, 3863, 3871, 3881, 3889, 3895, 3903, 3929,
+    3937, 3943, 3951, 3961, 3969, 3975, 3983, 4002, 4010, 4016, 4024, 4034,
+    4042, 4048, 4056, 4078, 4086, 4092, 4100, 4110, 4118, 4124, 4132, 4151,
+    4159, 4165, 4173, 4183, 4191, 4197, 4205, 4071, 4079, 4085, 4093, 4103,
+    4111, 4117, 4125, 4144, 4152, 4158, 4166, 4176, 4184, 4190, 4198, 4220,
+    4228, 4234, 4242, 4252, 4260, 4266, 4274, 4293, 4301, 4307, 4315, 4325,
+    4333, 4339, 4347, 4373, 4381, 4387, 4395, 4405, 4413, 4419, 4427, 4446,
+    4454, 4460, 4468, 4478, 4486, 4492, 4500, 4522, 4530, 4536, 4544, 4554,
+    4562, 4568, 4576, 4595, 4603, 4609, 4617, 4627, 4635, 4641, 4649, 3742,
+    3750, 3756, 3764, 3774, 3782, 3788, 3796, 3815, 3823, 3829, 3837, 3847,
+    3855, 3861, 3869, 3891, 3899, 3905, 3913, 3923, 3931, 3937, 3945, 3964,
+    3972, 3978, 3986, 3996, 4004, 4010, 4018, 4044, 4052, 4058, 4066, 4076,
+    4084, 4090, 4098, 4117, 4125, 4131, 4139, 4149, 4157, 4163, 4171, 4193,
+    4201, 4207, 4215, 4225, 4233, 4239, 4247, 4266, 4274, 4280, 4288, 4298,
+    4306, 4312, 4320, 4186, 4194, 4200, 4208, 4218, 4226, 4232, 4240, 4259,
+    4267, 4273, 4281, 4291, 4299, 4305, 4313, 4335, 4343, 4349, 4357, 4367,
+    4375, 4381, 4389, 4408, 4416, 4422, 4430, 4440, 4448, 4454, 4462, 4488,
+    4496, 4502, 4510, 4520, 4528, 4534, 4542, 4561, 4569, 4575, 4583, 4593,
+    4601, 4607, 4615, 4637, 4645, 4651, 4659, 4669, 4677, 4683, 4691, 4710,
+    4718, 4724, 4732, 4742, 4750, 4756, 4764, 4562, 4570, 4576, 4584, 4594,
+    4602, 4608, 4616, 4635, 4643, 4649, 4657, 4667, 4675, 4681, 4689, 4711,
+    4719, 4725, 4733, 4743, 4751, 4757, 4765, 4784, 4792, 4798, 4806, 4816,
+    4824, 4830, 4838, 4864, 4872, 4878, 4886, 4896, 4904, 4910, 4918, 4937,
+    4945, 4951, 4959, 4969, 4977, 4983, 4991, 5013, 5021, 5027, 5035, 5045,
+    5053, 5059, 5067, 5086, 5094, 5100, 5108, 5118, 5126, 5132, 5140, 5006,
+    5014, 5020, 5028, 5038, 5046, 5052, 5060, 5079, 5087, 5093, 5101, 5111,
+    5119, 5125, 5133, 5155, 5163, 5169, 5177, 5187, 5195, 5201, 5209, 5228,
+    5236, 5242, 5250, 5260, 5268, 5274, 5282, 5308, 5316, 5322, 5330, 5340,
+    5348, 5354, 5362, 5381, 5389, 5395, 5403, 5413, 5421, 5427, 5435, 5457,
+    5465, 5471, 5479, 5489, 5497, 5503, 5511, 5530, 5538, 5544, 5552, 5562,
+    5570, 5576, 5584, 4853, 4861, 4867, 4875, 4885, 4893, 4899, 4907, 4926,
+    4934, 4940, 4948, 4958, 4966, 4972, 4980, 5002, 5010, 5016, 5024, 5034,
+    5042, 5048, 5056, 5075, 5083, 5089, 5097, 5107, 5115, 5121, 5129, 5155,
+    5163, 5169, 5177, 5187, 5195, 5201, 5209, 5228, 5236, 5242, 5250, 5260,
+    5268, 5274, 5282, 5304, 5312, 5318, 5326, 5336, 5344, 5350, 5358, 5377,
+    5385, 5391, 5399, 5409, 5417, 5423, 5431, 5297, 5305, 5311, 5319, 5329,
+    5337, 5343, 5351, 5370, 5378, 5384, 5392, 5402, 5410, 5416, 5424, 5446,
+    5454, 5460, 5468, 5478, 5486, 5492, 5500, 5519, 5527, 5533, 5541, 5551,
+    5559, 5565, 5573, 5599, 5607, 5613, 5621, 5631, 5639, 5645, 5653, 5672,
+    5680, 5686, 5694, 5704, 5712, 5718, 5726, 5748, 5756, 5762, 5770, 5780,
+    5788, 5794, 5802, 5821, 5829, 5835, 5843, 5853, 5861, 5867, 5875, 5673,
+    5681, 5687, 5695, 5705, 5713, 5719, 5727, 5746, 5754, 5760, 5768, 5778,
+    5786, 5792, 5800, 5822, 5830, 5836, 5844, 5854, 5862, 5868, 5876, 5895,
+    5903, 5909, 5917, 5927, 5935, 5941, 5949, 5975, 5983, 5989, 5997, 6007,
+    6015, 6021, 6029, 6048, 6056, 6062, 6070, 6080, 6088, 6094, 6102, 6124,
+    6132, 6138, 6146, 6156, 6164, 6170, 6178, 6197, 6205, 6211, 6219, 6229,
+    6237, 6243, 6251, 6117, 6125, 6131, 6139, 6149, 6157, 6163, 6171, 6190,
+    6198, 6204, 6212, 6222, 6230, 6236, 6244, 6266, 6274, 6280, 6288, 6298,
+    6306, 6312, 6320, 6339, 6347, 6353, 6361, 6371, 6379, 6385, 6393, 6419,
+    6427, 6433, 6441, 6451, 6459, 6465, 6473, 6492, 6500, 6506, 6514, 6524,
+    6532, 6538, 6546, 6568, 6576, 6582, 6590, 6600, 6608, 6614, 6622, 6641,
+    6649, 6655, 6663, 6673, 6681, 6687, 6695, 3742, 3750, 3756, 3764, 3774,
+    3782, 3788, 3796, 3815, 3823, 3829, 3837, 3847, 3855, 3861, 3869, 3891,
+    3899, 3905, 3913, 3923, 3931, 3937, 3945, 3964, 3972, 3978, 3986, 3996,
+    4004, 4010, 4018, 4044, 4052, 4058, 4066, 4076, 4084, 4090, 4098, 4117,
+    4125, 4131, 4139, 4149, 4157, 4163, 4171, 4193, 4201, 4207, 4215, 4225,
+    4233, 4239, 4247, 4266, 4274, 4280, 4288, 4298, 4306, 4312, 4320, 4186,
+    4194, 4200, 4208, 4218, 4226, 4232, 4240, 4259, 4267, 4273, 4281, 4291,
+    4299, 4305, 4313, 4335, 4343, 4349, 4357, 4367, 4375, 4381, 4389, 4408,
+    4416, 4422, 4430, 4440, 4448, 4454, 4462, 4488, 4496, 4502, 4510, 4520,
+    4528, 4534, 4542, 4561, 4569, 4575, 4583, 4593, 4601, 4607, 4615, 4637,
+    4645, 4651, 4659, 4669, 4677, 4683, 4691, 4710, 4718, 4724, 4732, 4742,
+    4750, 4756, 4764, 4562, 4570, 4576, 4584, 4594, 4602, 4608, 4616, 4635,
+    4643, 4649, 4657, 4667, 4675, 4681, 4689, 4711, 4719, 4725, 4733, 4743,
+    4751, 4757, 4765, 4784, 4792, 4798, 4806, 4816, 4824, 4830, 4838, 4864,
+    4872, 4878, 4886, 4896, 4904, 4910, 4918, 4937, 4945, 4951, 4959, 4969,
+    4977, 4983, 4991, 5013, 5021, 5027, 5035, 5045, 5053, 5059, 5067, 5086,
+    5094, 5100, 5108, 5118, 5126, 5132, 5140, 5006, 5014, 5020, 5028, 5038,
+    5046, 5052, 5060, 5079, 5087, 5093, 5101, 5111, 5119, 5125, 5133, 5155,
+    5163, 5169, 5177, 5187, 5195, 5201, 5209, 5228, 5236, 5242, 5250, 5260,
+    5268, 5274, 5282, 5308, 5316, 5322, 5330, 5340, 5348, 5354, 5362, 5381,
+    5389, 5395, 5403, 5413, 5421, 5427, 5435, 5457, 5465, 5471, 5479, 5489,
+    5497, 5503, 5511, 5530, 5538, 5544, 5552, 5562, 5570, 5576, 5584, 4853,
+    4861, 4867, 4875, 4885, 4893, 4899, 4907, 4926, 4934, 4940, 4948, 4958,
+    4966, 4972, 4980, 5002, 5010, 5016, 5024, 5034, 5042, 5048, 5056, 5075,
+    5083, 5089, 5097, 5107, 5115, 5121, 5129, 5155, 5163, 5169, 5177, 5187,
+    5195, 5201, 5209, 5228, 5236, 5242, 5250, 5260, 5268, 5274, 5282, 5304,
+    5312, 5318, 5326, 5336, 5344, 5350, 5358, 5377, 5385, 5391, 5399, 5409,
+    5417, 5423, 5431, 5297, 5305, 5311, 5319, 5329, 5337, 5343, 5351, 5370,
+    5378, 5384, 5392, 5402, 5410, 5416, 5424, 5446, 5454, 5460, 5468, 5478,
+    5486, 5492, 5500, 5519, 5527, 5533, 5541, 5551, 5559, 5565, 5573, 5599,
+    5607, 5613, 5621, 5631, 5639, 5645, 5653, 5672, 5680, 5686, 5694, 5704,
+    5712, 5718, 5726, 5748, 5756, 5762, 5770, 5780, 5788, 5794, 5802, 5821,
+    5829, 5835, 5843, 5853, 5861, 5867, 5875, 5673, 5681, 5687, 5695, 5705,
+    5713, 5719, 5727, 5746, 5754, 5760, 5768, 5778, 5786, 5792, 5800, 5822,
+    5830, 5836, 5844, 5854, 5862, 5868, 5876, 5895, 5903, 5909, 5917, 5927,
+    5935, 5941, 5949, 5975, 5983, 5989, 5997, 6007, 6015, 6021, 6029, 6048,
+    6056, 6062, 6070, 6080, 6088, 6094, 6102, 6124, 6132, 6138, 6146, 6156,
+    6164, 6170, 6178, 6197, 6205, 6211, 6219, 6229, 6237, 6243, 6251, 6117,
+    6125, 6131, 6139, 6149, 6157, 6163, 6171, 6190, 6198, 6204, 6212, 6222,
+    6230, 6236, 6244, 6266, 6274, 6280, 6288, 6298, 6306, 6312, 6320, 6339,
+    6347, 6353, 6361, 6371, 6379, 6385, 6393, 6419, 6427, 6433, 6441, 6451,
+    6459, 6465, 6473, 6492, 6500, 6506, 6514, 6524, 6532, 6538, 6546, 6568,
+    6576, 6582, 6590, 6600, 6608, 6614, 6622, 6641, 6649, 6655, 6663, 6673,
+    6681, 6687, 6695, 5788, 5796, 5802, 5810, 5820, 5828, 5834, 5842, 5861,
+    5869, 5875, 5883, 5893, 5901, 5907, 5915, 5937, 5945, 5951, 5959, 5969,
+    5977, 5983, 5991, 6010, 6018, 6024, 6032, 6042, 6050, 6056, 6064, 6090,
+    6098, 6104, 6112, 6122, 6130, 6136, 6144, 6163, 6171, 6177, 6185, 6195,
+    6203, 6209, 6217, 6239, 6247, 6253, 6261, 6271, 6279, 6285, 6293, 6312,
+    6320, 6326, 6334, 6344, 6352, 6358, 6366, 6232, 6240, 6246, 6254, 6264,
+    6272, 6278, 6286, 6305, 6313, 6319, 6327, 6337, 6345, 6351, 6359, 6381,
+    6389, 6395, 6403, 6413, 6421, 6427, 6435, 6454, 6462, 6468, 6476, 6486,
+    6494, 6500, 6508, 6534, 6542, 6548, 6556, 6566, 6574, 6580, 6588, 6607,
+    6615, 6621, 6629, 6639, 6647, 6653, 6661, 6683, 6691, 6697, 6705, 6715,
+    6723, 6729, 6737, 6756, 6764, 6770, 6778, 6788, 6796, 6802, 6810, 6608,
+    6616, 6622, 6630, 6640, 6648, 6654, 6662, 6681, 6689, 6695, 6703, 6713,
+    6721, 6727, 6735, 6757, 6765, 6771, 6779, 6789, 6797, 6803, 6811, 6830,
+    6838, 6844, 6852, 6862, 6870, 6876, 6884, 6910, 6918, 6924, 6932, 6942,
+    6950, 6956, 6964, 6983, 6991, 6997, 7005, 7015, 7023, 7029, 7037, 7059,
+    7067, 7073, 7081, 7091, 7099, 7105, 7113, 7132, 7140, 7146, 7154, 7164,
+    7172, 7178, 7186, 7052, 7060, 7066, 7074, 7084, 7092, 7098, 7106, 7125,
+    7133, 7139, 7147, 7157, 7165, 7171, 7179, 7201, 7209, 7215, 7223, 7233,
+    7241, 7247, 7255, 7274, 7282, 7288, 7296, 7306, 7314, 7320, 7328, 7354,
+    7362, 7368, 7376, 7386, 7394, 7400, 7408, 7427, 7435, 7441, 7449, 7459,
+    7467, 7473, 7481, 7503, 7511, 7517, 7525, 7535, 7543, 7549, 7557, 7576,
+    7584, 7590, 7598, 7608, 7616, 7622, 7630, 6899, 6907, 6913, 6921, 6931,
+    6939, 6945, 6953, 6972, 6980, 6986, 6994, 7004, 7012, 7018, 7026, 7048,
+    7056, 7062, 7070, 7080, 7088, 7094, 7102, 7121, 7129, 7135, 7143, 7153,
+    7161, 7167, 7175, 7201, 7209, 7215, 7223, 7233, 7241, 7247, 7255, 7274,
+    7282, 7288, 7296, 7306, 7314, 7320, 7328, 7350, 7358, 7364, 7372, 7382,
+    7390, 7396, 7404, 7423, 7431, 7437, 7445, 7455, 7463, 7469, 7477, 7343,
+    7351, 7357, 7365, 7375, 7383, 7389, 7397, 7416, 7424, 7430, 7438, 7448,
+    7456, 7462, 7470, 7492, 7500, 7506, 7514, 7524, 7532, 7538, 7546, 7565,
+    7573, 7579, 7587, 7597, 7605, 7611, 7619, 7645, 7653, 7659, 7667, 7677,
+    7685, 7691, 7699, 7718, 7726, 7732, 7740, 7750, 7758, 7764, 7772, 7794,
+    7802, 7808, 7816, 7826, 7834, 7840, 7848, 7867, 7875, 7881, 7889, 7899,
+    7907, 7913, 7921, 7719, 7727, 7733, 7741, 7751, 7759, 7765, 7773, 7792,
+    7800, 7806, 7814, 7824, 7832, 7838, 7846, 7868, 7876, 7882, 7890, 7900,
+    7908, 7914, 7922, 7941, 7949, 7955, 7963, 7973, 7981, 7987, 7995, 8021,
+    8029, 8035, 8043, 8053, 8061, 8067, 8075, 8094, 8102, 8108, 8116, 8126,
+    8134, 8140, 8148, 8170, 8178, 8184, 8192, 8202, 8210, 8216, 8224, 8243,
+    8251, 8257, 8265, 8275
+};
diff --git a/vp8/encoder/dct_value_tokens.h b/vp8/encoder/dct_value_tokens.h
new file mode 100644 (file)
index 0000000..ef08eed
--- /dev/null
@@ -0,0 +1,699 @@
+/*
+ *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/* Generated file, included by tokenize.c  */
+/* Values generated by fill_value_tokens() */
+
+static const TOKENVALUE dct_value_tokens[2048*2] =
+{
+    {10, 3963}, {10, 3961}, {10, 3959}, {10, 3957}, {10, 3955}, {10, 3953},
+    {10, 3951}, {10, 3949}, {10, 3947}, {10, 3945}, {10, 3943}, {10, 3941},
+    {10, 3939}, {10, 3937}, {10, 3935}, {10, 3933}, {10, 3931}, {10, 3929},
+    {10, 3927}, {10, 3925}, {10, 3923}, {10, 3921}, {10, 3919}, {10, 3917},
+    {10, 3915}, {10, 3913}, {10, 3911}, {10, 3909}, {10, 3907}, {10, 3905},
+    {10, 3903}, {10, 3901}, {10, 3899}, {10, 3897}, {10, 3895}, {10, 3893},
+    {10, 3891}, {10, 3889}, {10, 3887}, {10, 3885}, {10, 3883}, {10, 3881},
+    {10, 3879}, {10, 3877}, {10, 3875}, {10, 3873}, {10, 3871}, {10, 3869},
+    {10, 3867}, {10, 3865}, {10, 3863}, {10, 3861}, {10, 3859}, {10, 3857},
+    {10, 3855}, {10, 3853}, {10, 3851}, {10, 3849}, {10, 3847}, {10, 3845},
+    {10, 3843}, {10, 3841}, {10, 3839}, {10, 3837}, {10, 3835}, {10, 3833},
+    {10, 3831}, {10, 3829}, {10, 3827}, {10, 3825}, {10, 3823}, {10, 3821},
+    {10, 3819}, {10, 3817}, {10, 3815}, {10, 3813}, {10, 3811}, {10, 3809},
+    {10, 3807}, {10, 3805}, {10, 3803}, {10, 3801}, {10, 3799}, {10, 3797},
+    {10, 3795}, {10, 3793}, {10, 3791}, {10, 3789}, {10, 3787}, {10, 3785},
+    {10, 3783}, {10, 3781}, {10, 3779}, {10, 3777}, {10, 3775}, {10, 3773},
+    {10, 3771}, {10, 3769}, {10, 3767}, {10, 3765}, {10, 3763}, {10, 3761},
+    {10, 3759}, {10, 3757}, {10, 3755}, {10, 3753}, {10, 3751}, {10, 3749},
+    {10, 3747}, {10, 3745}, {10, 3743}, {10, 3741}, {10, 3739}, {10, 3737},
+    {10, 3735}, {10, 3733}, {10, 3731}, {10, 3729}, {10, 3727}, {10, 3725},
+    {10, 3723}, {10, 3721}, {10, 3719}, {10, 3717}, {10, 3715}, {10, 3713},
+    {10, 3711}, {10, 3709}, {10, 3707}, {10, 3705}, {10, 3703}, {10, 3701},
+    {10, 3699}, {10, 3697}, {10, 3695}, {10, 3693}, {10, 3691}, {10, 3689},
+    {10, 3687}, {10, 3685}, {10, 3683}, {10, 3681}, {10, 3679}, {10, 3677},
+    {10, 3675}, {10, 3673}, {10, 3671}, {10, 3669}, {10, 3667}, {10, 3665},
+    {10, 3663}, {10, 3661}, {10, 3659}, {10, 3657}, {10, 3655}, {10, 3653},
+    {10, 3651}, {10, 3649}, {10, 3647}, {10, 3645}, {10, 3643}, {10, 3641},
+    {10, 3639}, {10, 3637}, {10, 3635}, {10, 3633}, {10, 3631}, {10, 3629},
+    {10, 3627}, {10, 3625}, {10, 3623}, {10, 3621}, {10, 3619}, {10, 3617},
+    {10, 3615}, {10, 3613}, {10, 3611}, {10, 3609}, {10, 3607}, {10, 3605},
+    {10, 3603}, {10, 3601}, {10, 3599}, {10, 3597}, {10, 3595}, {10, 3593},
+    {10, 3591}, {10, 3589}, {10, 3587}, {10, 3585}, {10, 3583}, {10, 3581},
+    {10, 3579}, {10, 3577}, {10, 3575}, {10, 3573}, {10, 3571}, {10, 3569},
+    {10, 3567}, {10, 3565}, {10, 3563}, {10, 3561}, {10, 3559}, {10, 3557},
+    {10, 3555}, {10, 3553}, {10, 3551}, {10, 3549}, {10, 3547}, {10, 3545},
+    {10, 3543}, {10, 3541}, {10, 3539}, {10, 3537}, {10, 3535}, {10, 3533},
+    {10, 3531}, {10, 3529}, {10, 3527}, {10, 3525}, {10, 3523}, {10, 3521},
+    {10, 3519}, {10, 3517}, {10, 3515}, {10, 3513}, {10, 3511}, {10, 3509},
+    {10, 3507}, {10, 3505}, {10, 3503}, {10, 3501}, {10, 3499}, {10, 3497},
+    {10, 3495}, {10, 3493}, {10, 3491}, {10, 3489}, {10, 3487}, {10, 3485},
+    {10, 3483}, {10, 3481}, {10, 3479}, {10, 3477}, {10, 3475}, {10, 3473},
+    {10, 3471}, {10, 3469}, {10, 3467}, {10, 3465}, {10, 3463}, {10, 3461},
+    {10, 3459}, {10, 3457}, {10, 3455}, {10, 3453}, {10, 3451}, {10, 3449},
+    {10, 3447}, {10, 3445}, {10, 3443}, {10, 3441}, {10, 3439}, {10, 3437},
+    {10, 3435}, {10, 3433}, {10, 3431}, {10, 3429}, {10, 3427}, {10, 3425},
+    {10, 3423}, {10, 3421}, {10, 3419}, {10, 3417}, {10, 3415}, {10, 3413},
+    {10, 3411}, {10, 3409}, {10, 3407}, {10, 3405}, {10, 3403}, {10, 3401},
+    {10, 3399}, {10, 3397}, {10, 3395}, {10, 3393}, {10, 3391}, {10, 3389},
+    {10, 3387}, {10, 3385}, {10, 3383}, {10, 3381}, {10, 3379}, {10, 3377},
+    {10, 3375}, {10, 3373}, {10, 3371}, {10, 3369}, {10, 3367}, {10, 3365},
+    {10, 3363}, {10, 3361}, {10, 3359}, {10, 3357}, {10, 3355}, {10, 3353},
+    {10, 3351}, {10, 3349}, {10, 3347}, {10, 3345}, {10, 3343}, {10, 3341},
+    {10, 3339}, {10, 3337}, {10, 3335}, {10, 3333}, {10, 3331}, {10, 3329},
+    {10, 3327}, {10, 3325}, {10, 3323}, {10, 3321}, {10, 3319}, {10, 3317},
+    {10, 3315}, {10, 3313}, {10, 3311}, {10, 3309}, {10, 3307}, {10, 3305},
+    {10, 3303}, {10, 3301}, {10, 3299}, {10, 3297}, {10, 3295}, {10, 3293},
+    {10, 3291}, {10, 3289}, {10, 3287}, {10, 3285}, {10, 3283}, {10, 3281},
+    {10, 3279}, {10, 3277}, {10, 3275}, {10, 3273}, {10, 3271}, {10, 3269},
+    {10, 3267}, {10, 3265}, {10, 3263}, {10, 3261}, {10, 3259}, {10, 3257},
+    {10, 3255}, {10, 3253}, {10, 3251}, {10, 3249}, {10, 3247}, {10, 3245},
+    {10, 3243}, {10, 3241}, {10, 3239}, {10, 3237}, {10, 3235}, {10, 3233},
+    {10, 3231}, {10, 3229}, {10, 3227}, {10, 3225}, {10, 3223}, {10, 3221},
+    {10, 3219}, {10, 3217}, {10, 3215}, {10, 3213}, {10, 3211}, {10, 3209},
+    {10, 3207}, {10, 3205}, {10, 3203}, {10, 3201}, {10, 3199}, {10, 3197},
+    {10, 3195}, {10, 3193}, {10, 3191}, {10, 3189}, {10, 3187}, {10, 3185},
+    {10, 3183}, {10, 3181}, {10, 3179}, {10, 3177}, {10, 3175}, {10, 3173},
+    {10, 3171}, {10, 3169}, {10, 3167}, {10, 3165}, {10, 3163}, {10, 3161},
+    {10, 3159}, {10, 3157}, {10, 3155}, {10, 3153}, {10, 3151}, {10, 3149},
+    {10, 3147}, {10, 3145}, {10, 3143}, {10, 3141}, {10, 3139}, {10, 3137},
+    {10, 3135}, {10, 3133}, {10, 3131}, {10, 3129}, {10, 3127}, {10, 3125},
+    {10, 3123}, {10, 3121}, {10, 3119}, {10, 3117}, {10, 3115}, {10, 3113},
+    {10, 3111}, {10, 3109}, {10, 3107}, {10, 3105}, {10, 3103}, {10, 3101},
+    {10, 3099}, {10, 3097}, {10, 3095}, {10, 3093}, {10, 3091}, {10, 3089},
+    {10, 3087}, {10, 3085}, {10, 3083}, {10, 3081}, {10, 3079}, {10, 3077},
+    {10, 3075}, {10, 3073}, {10, 3071}, {10, 3069}, {10, 3067}, {10, 3065},
+    {10, 3063}, {10, 3061}, {10, 3059}, {10, 3057}, {10, 3055}, {10, 3053},
+    {10, 3051}, {10, 3049}, {10, 3047}, {10, 3045}, {10, 3043}, {10, 3041},
+    {10, 3039}, {10, 3037}, {10, 3035}, {10, 3033}, {10, 3031}, {10, 3029},
+    {10, 3027}, {10, 3025}, {10, 3023}, {10, 3021}, {10, 3019}, {10, 3017},
+    {10, 3015}, {10, 3013}, {10, 3011}, {10, 3009}, {10, 3007}, {10, 3005},
+    {10, 3003}, {10, 3001}, {10, 2999}, {10, 2997}, {10, 2995}, {10, 2993},
+    {10, 2991}, {10, 2989}, {10, 2987}, {10, 2985}, {10, 2983}, {10, 2981},
+    {10, 2979}, {10, 2977}, {10, 2975}, {10, 2973}, {10, 2971}, {10, 2969},
+    {10, 2967}, {10, 2965}, {10, 2963}, {10, 2961}, {10, 2959}, {10, 2957},
+    {10, 2955}, {10, 2953}, {10, 2951}, {10, 2949}, {10, 2947}, {10, 2945},
+    {10, 2943}, {10, 2941}, {10, 2939}, {10, 2937}, {10, 2935}, {10, 2933},
+    {10, 2931}, {10, 2929}, {10, 2927}, {10, 2925}, {10, 2923}, {10, 2921},
+    {10, 2919}, {10, 2917}, {10, 2915}, {10, 2913}, {10, 2911}, {10, 2909},
+    {10, 2907}, {10, 2905}, {10, 2903}, {10, 2901}, {10, 2899}, {10, 2897},
+    {10, 2895}, {10, 2893}, {10, 2891}, {10, 2889}, {10, 2887}, {10, 2885},
+    {10, 2883}, {10, 2881}, {10, 2879}, {10, 2877}, {10, 2875}, {10, 2873},
+    {10, 2871}, {10, 2869}, {10, 2867}, {10, 2865}, {10, 2863}, {10, 2861},
+    {10, 2859}, {10, 2857}, {10, 2855}, {10, 2853}, {10, 2851}, {10, 2849},
+    {10, 2847}, {10, 2845}, {10, 2843}, {10, 2841}, {10, 2839}, {10, 2837},
+    {10, 2835}, {10, 2833}, {10, 2831}, {10, 2829}, {10, 2827}, {10, 2825},
+    {10, 2823}, {10, 2821}, {10, 2819}, {10, 2817}, {10, 2815}, {10, 2813},
+    {10, 2811}, {10, 2809}, {10, 2807}, {10, 2805}, {10, 2803}, {10, 2801},
+    {10, 2799}, {10, 2797}, {10, 2795}, {10, 2793}, {10, 2791}, {10, 2789},
+    {10, 2787}, {10, 2785}, {10, 2783}, {10, 2781}, {10, 2779}, {10, 2777},
+    {10, 2775}, {10, 2773}, {10, 2771}, {10, 2769}, {10, 2767}, {10, 2765},
+    {10, 2763}, {10, 2761}, {10, 2759}, {10, 2757}, {10, 2755}, {10, 2753},
+    {10, 2751}, {10, 2749}, {10, 2747}, {10, 2745}, {10, 2743}, {10, 2741},
+    {10, 2739}, {10, 2737}, {10, 2735}, {10, 2733}, {10, 2731}, {10, 2729},
+    {10, 2727}, {10, 2725}, {10, 2723}, {10, 2721}, {10, 2719}, {10, 2717},
+    {10, 2715}, {10, 2713}, {10, 2711}, {10, 2709}, {10, 2707}, {10, 2705},
+    {10, 2703}, {10, 2701}, {10, 2699}, {10, 2697}, {10, 2695}, {10, 2693},
+    {10, 2691}, {10, 2689}, {10, 2687}, {10, 2685}, {10, 2683}, {10, 2681},
+    {10, 2679}, {10, 2677}, {10, 2675}, {10, 2673}, {10, 2671}, {10, 2669},
+    {10, 2667}, {10, 2665}, {10, 2663}, {10, 2661}, {10, 2659}, {10, 2657},
+    {10, 2655}, {10, 2653}, {10, 2651}, {10, 2649}, {10, 2647}, {10, 2645},
+    {10, 2643}, {10, 2641}, {10, 2639}, {10, 2637}, {10, 2635}, {10, 2633},
+    {10, 2631}, {10, 2629}, {10, 2627}, {10, 2625}, {10, 2623}, {10, 2621},
+    {10, 2619}, {10, 2617}, {10, 2615}, {10, 2613}, {10, 2611}, {10, 2609},
+    {10, 2607}, {10, 2605}, {10, 2603}, {10, 2601}, {10, 2599}, {10, 2597},
+    {10, 2595}, {10, 2593}, {10, 2591}, {10, 2589}, {10, 2587}, {10, 2585},
+    {10, 2583}, {10, 2581}, {10, 2579}, {10, 2577}, {10, 2575}, {10, 2573},
+    {10, 2571}, {10, 2569}, {10, 2567}, {10, 2565}, {10, 2563}, {10, 2561},
+    {10, 2559}, {10, 2557}, {10, 2555}, {10, 2553}, {10, 2551}, {10, 2549},
+    {10, 2547}, {10, 2545}, {10, 2543}, {10, 2541}, {10, 2539}, {10, 2537},
+    {10, 2535}, {10, 2533}, {10, 2531}, {10, 2529}, {10, 2527}, {10, 2525},
+    {10, 2523}, {10, 2521}, {10, 2519}, {10, 2517}, {10, 2515}, {10, 2513},
+    {10, 2511}, {10, 2509}, {10, 2507}, {10, 2505}, {10, 2503}, {10, 2501},
+    {10, 2499}, {10, 2497}, {10, 2495}, {10, 2493}, {10, 2491}, {10, 2489},
+    {10, 2487}, {10, 2485}, {10, 2483}, {10, 2481}, {10, 2479}, {10, 2477},
+    {10, 2475}, {10, 2473}, {10, 2471}, {10, 2469}, {10, 2467}, {10, 2465},
+    {10, 2463}, {10, 2461}, {10, 2459}, {10, 2457}, {10, 2455}, {10, 2453},
+    {10, 2451}, {10, 2449}, {10, 2447}, {10, 2445}, {10, 2443}, {10, 2441},
+    {10, 2439}, {10, 2437}, {10, 2435}, {10, 2433}, {10, 2431}, {10, 2429},
+    {10, 2427}, {10, 2425}, {10, 2423}, {10, 2421}, {10, 2419}, {10, 2417},
+    {10, 2415}, {10, 2413}, {10, 2411}, {10, 2409}, {10, 2407}, {10, 2405},
+    {10, 2403}, {10, 2401}, {10, 2399}, {10, 2397}, {10, 2395}, {10, 2393},
+    {10, 2391}, {10, 2389}, {10, 2387}, {10, 2385}, {10, 2383}, {10, 2381},
+    {10, 2379}, {10, 2377}, {10, 2375}, {10, 2373}, {10, 2371}, {10, 2369},
+    {10, 2367}, {10, 2365}, {10, 2363}, {10, 2361}, {10, 2359}, {10, 2357},
+    {10, 2355}, {10, 2353}, {10, 2351}, {10, 2349}, {10, 2347}, {10, 2345},
+    {10, 2343}, {10, 2341}, {10, 2339}, {10, 2337}, {10, 2335}, {10, 2333},
+    {10, 2331}, {10, 2329}, {10, 2327}, {10, 2325}, {10, 2323}, {10, 2321},
+    {10, 2319}, {10, 2317}, {10, 2315}, {10, 2313}, {10, 2311}, {10, 2309},
+    {10, 2307}, {10, 2305}, {10, 2303}, {10, 2301}, {10, 2299}, {10, 2297},
+    {10, 2295}, {10, 2293}, {10, 2291}, {10, 2289}, {10, 2287}, {10, 2285},
+    {10, 2283}, {10, 2281}, {10, 2279}, {10, 2277}, {10, 2275}, {10, 2273},
+    {10, 2271}, {10, 2269}, {10, 2267}, {10, 2265}, {10, 2263}, {10, 2261},
+    {10, 2259}, {10, 2257}, {10, 2255}, {10, 2253}, {10, 2251}, {10, 2249},
+    {10, 2247}, {10, 2245}, {10, 2243}, {10, 2241}, {10, 2239}, {10, 2237},
+    {10, 2235}, {10, 2233}, {10, 2231}, {10, 2229}, {10, 2227}, {10, 2225},
+    {10, 2223}, {10, 2221}, {10, 2219}, {10, 2217}, {10, 2215}, {10, 2213},
+    {10, 2211}, {10, 2209}, {10, 2207}, {10, 2205}, {10, 2203}, {10, 2201},
+    {10, 2199}, {10, 2197}, {10, 2195}, {10, 2193}, {10, 2191}, {10, 2189},
+    {10, 2187}, {10, 2185}, {10, 2183}, {10, 2181}, {10, 2179}, {10, 2177},
+    {10, 2175}, {10, 2173}, {10, 2171}, {10, 2169}, {10, 2167}, {10, 2165},
+    {10, 2163}, {10, 2161}, {10, 2159}, {10, 2157}, {10, 2155}, {10, 2153},
+    {10, 2151}, {10, 2149}, {10, 2147}, {10, 2145}, {10, 2143}, {10, 2141},
+    {10, 2139}, {10, 2137}, {10, 2135}, {10, 2133}, {10, 2131}, {10, 2129},
+    {10, 2127}, {10, 2125}, {10, 2123}, {10, 2121}, {10, 2119}, {10, 2117},
+    {10, 2115}, {10, 2113}, {10, 2111}, {10, 2109}, {10, 2107}, {10, 2105},
+    {10, 2103}, {10, 2101}, {10, 2099}, {10, 2097}, {10, 2095}, {10, 2093},
+    {10, 2091}, {10, 2089}, {10, 2087}, {10, 2085}, {10, 2083}, {10, 2081},
+    {10, 2079}, {10, 2077}, {10, 2075}, {10, 2073}, {10, 2071}, {10, 2069},
+    {10, 2067}, {10, 2065}, {10, 2063}, {10, 2061}, {10, 2059}, {10, 2057},
+    {10, 2055}, {10, 2053}, {10, 2051}, {10, 2049}, {10, 2047}, {10, 2045},
+    {10, 2043}, {10, 2041}, {10, 2039}, {10, 2037}, {10, 2035}, {10, 2033},
+    {10, 2031}, {10, 2029}, {10, 2027}, {10, 2025}, {10, 2023}, {10, 2021},
+    {10, 2019}, {10, 2017}, {10, 2015}, {10, 2013}, {10, 2011}, {10, 2009},
+    {10, 2007}, {10, 2005}, {10, 2003}, {10, 2001}, {10, 1999}, {10, 1997},
+    {10, 1995}, {10, 1993}, {10, 1991}, {10, 1989}, {10, 1987}, {10, 1985},
+    {10, 1983}, {10, 1981}, {10, 1979}, {10, 1977}, {10, 1975}, {10, 1973},
+    {10, 1971}, {10, 1969}, {10, 1967}, {10, 1965}, {10, 1963}, {10, 1961},
+    {10, 1959}, {10, 1957}, {10, 1955}, {10, 1953}, {10, 1951}, {10, 1949},
+    {10, 1947}, {10, 1945}, {10, 1943}, {10, 1941}, {10, 1939}, {10, 1937},
+    {10, 1935}, {10, 1933}, {10, 1931}, {10, 1929}, {10, 1927}, {10, 1925},
+    {10, 1923}, {10, 1921}, {10, 1919}, {10, 1917}, {10, 1915}, {10, 1913},
+    {10, 1911}, {10, 1909}, {10, 1907}, {10, 1905}, {10, 1903}, {10, 1901},
+    {10, 1899}, {10, 1897}, {10, 1895}, {10, 1893}, {10, 1891}, {10, 1889},
+    {10, 1887}, {10, 1885}, {10, 1883}, {10, 1881}, {10, 1879}, {10, 1877},
+    {10, 1875}, {10, 1873}, {10, 1871}, {10, 1869}, {10, 1867}, {10, 1865},
+    {10, 1863}, {10, 1861}, {10, 1859}, {10, 1857}, {10, 1855}, {10, 1853},
+    {10, 1851}, {10, 1849}, {10, 1847}, {10, 1845}, {10, 1843}, {10, 1841},
+    {10, 1839}, {10, 1837}, {10, 1835}, {10, 1833}, {10, 1831}, {10, 1829},
+    {10, 1827}, {10, 1825}, {10, 1823}, {10, 1821}, {10, 1819}, {10, 1817},
+    {10, 1815}, {10, 1813}, {10, 1811}, {10, 1809}, {10, 1807}, {10, 1805},
+    {10, 1803}, {10, 1801}, {10, 1799}, {10, 1797}, {10, 1795}, {10, 1793},
+    {10, 1791}, {10, 1789}, {10, 1787}, {10, 1785}, {10, 1783}, {10, 1781},
+    {10, 1779}, {10, 1777}, {10, 1775}, {10, 1773}, {10, 1771}, {10, 1769},
+    {10, 1767}, {10, 1765}, {10, 1763}, {10, 1761}, {10, 1759}, {10, 1757},
+    {10, 1755}, {10, 1753}, {10, 1751}, {10, 1749}, {10, 1747}, {10, 1745},
+    {10, 1743}, {10, 1741}, {10, 1739}, {10, 1737}, {10, 1735}, {10, 1733},
+    {10, 1731}, {10, 1729}, {10, 1727}, {10, 1725}, {10, 1723}, {10, 1721},
+    {10, 1719}, {10, 1717}, {10, 1715}, {10, 1713}, {10, 1711}, {10, 1709},
+    {10, 1707}, {10, 1705}, {10, 1703}, {10, 1701}, {10, 1699}, {10, 1697},
+    {10, 1695}, {10, 1693}, {10, 1691}, {10, 1689}, {10, 1687}, {10, 1685},
+    {10, 1683}, {10, 1681}, {10, 1679}, {10, 1677}, {10, 1675}, {10, 1673},
+    {10, 1671}, {10, 1669}, {10, 1667}, {10, 1665}, {10, 1663}, {10, 1661},
+    {10, 1659}, {10, 1657}, {10, 1655}, {10, 1653}, {10, 1651}, {10, 1649},
+    {10, 1647}, {10, 1645}, {10, 1643}, {10, 1641}, {10, 1639}, {10, 1637},
+    {10, 1635}, {10, 1633}, {10, 1631}, {10, 1629}, {10, 1627}, {10, 1625},
+    {10, 1623}, {10, 1621}, {10, 1619}, {10, 1617}, {10, 1615}, {10, 1613},
+    {10, 1611}, {10, 1609}, {10, 1607}, {10, 1605}, {10, 1603}, {10, 1601},
+    {10, 1599}, {10, 1597}, {10, 1595}, {10, 1593}, {10, 1591}, {10, 1589},
+    {10, 1587}, {10, 1585}, {10, 1583}, {10, 1581}, {10, 1579}, {10, 1577},
+    {10, 1575}, {10, 1573}, {10, 1571}, {10, 1569}, {10, 1567}, {10, 1565},
+    {10, 1563}, {10, 1561}, {10, 1559}, {10, 1557}, {10, 1555}, {10, 1553},
+    {10, 1551}, {10, 1549}, {10, 1547}, {10, 1545}, {10, 1543}, {10, 1541},
+    {10, 1539}, {10, 1537}, {10, 1535}, {10, 1533}, {10, 1531}, {10, 1529},
+    {10, 1527}, {10, 1525}, {10, 1523}, {10, 1521}, {10, 1519}, {10, 1517},
+    {10, 1515}, {10, 1513}, {10, 1511}, {10, 1509}, {10, 1507}, {10, 1505},
+    {10, 1503}, {10, 1501}, {10, 1499}, {10, 1497}, {10, 1495}, {10, 1493},
+    {10, 1491}, {10, 1489}, {10, 1487}, {10, 1485}, {10, 1483}, {10, 1481},
+    {10, 1479}, {10, 1477}, {10, 1475}, {10, 1473}, {10, 1471}, {10, 1469},
+    {10, 1467}, {10, 1465}, {10, 1463}, {10, 1461}, {10, 1459}, {10, 1457},
+    {10, 1455}, {10, 1453}, {10, 1451}, {10, 1449}, {10, 1447}, {10, 1445},
+    {10, 1443}, {10, 1441}, {10, 1439}, {10, 1437}, {10, 1435}, {10, 1433},
+    {10, 1431}, {10, 1429}, {10, 1427}, {10, 1425}, {10, 1423}, {10, 1421},
+    {10, 1419}, {10, 1417}, {10, 1415}, {10, 1413}, {10, 1411}, {10, 1409},
+    {10, 1407}, {10, 1405}, {10, 1403}, {10, 1401}, {10, 1399}, {10, 1397},
+    {10, 1395}, {10, 1393}, {10, 1391}, {10, 1389}, {10, 1387}, {10, 1385},
+    {10, 1383}, {10, 1381}, {10, 1379}, {10, 1377}, {10, 1375}, {10, 1373},
+    {10, 1371}, {10, 1369}, {10, 1367}, {10, 1365}, {10, 1363}, {10, 1361},
+    {10, 1359}, {10, 1357}, {10, 1355}, {10, 1353}, {10, 1351}, {10, 1349},
+    {10, 1347}, {10, 1345}, {10, 1343}, {10, 1341}, {10, 1339}, {10, 1337},
+    {10, 1335}, {10, 1333}, {10, 1331}, {10, 1329}, {10, 1327}, {10, 1325},
+    {10, 1323}, {10, 1321}, {10, 1319}, {10, 1317}, {10, 1315}, {10, 1313},
+    {10, 1311}, {10, 1309}, {10, 1307}, {10, 1305}, {10, 1303}, {10, 1301},
+    {10, 1299}, {10, 1297}, {10, 1295}, {10, 1293}, {10, 1291}, {10, 1289},
+    {10, 1287}, {10, 1285}, {10, 1283}, {10, 1281}, {10, 1279}, {10, 1277},
+    {10, 1275}, {10, 1273}, {10, 1271}, {10, 1269}, {10, 1267}, {10, 1265},
+    {10, 1263}, {10, 1261}, {10, 1259}, {10, 1257}, {10, 1255}, {10, 1253},
+    {10, 1251}, {10, 1249}, {10, 1247}, {10, 1245}, {10, 1243}, {10, 1241},
+    {10, 1239}, {10, 1237}, {10, 1235}, {10, 1233}, {10, 1231}, {10, 1229},
+    {10, 1227}, {10, 1225}, {10, 1223}, {10, 1221}, {10, 1219}, {10, 1217},
+    {10, 1215}, {10, 1213}, {10, 1211}, {10, 1209}, {10, 1207}, {10, 1205},
+    {10, 1203}, {10, 1201}, {10, 1199}, {10, 1197}, {10, 1195}, {10, 1193},
+    {10, 1191}, {10, 1189}, {10, 1187}, {10, 1185}, {10, 1183}, {10, 1181},
+    {10, 1179}, {10, 1177}, {10, 1175}, {10, 1173}, {10, 1171}, {10, 1169},
+    {10, 1167}, {10, 1165}, {10, 1163}, {10, 1161}, {10, 1159}, {10, 1157},
+    {10, 1155}, {10, 1153}, {10, 1151}, {10, 1149}, {10, 1147}, {10, 1145},
+    {10, 1143}, {10, 1141}, {10, 1139}, {10, 1137}, {10, 1135}, {10, 1133},
+    {10, 1131}, {10, 1129}, {10, 1127}, {10, 1125}, {10, 1123}, {10, 1121},
+    {10, 1119}, {10, 1117}, {10, 1115}, {10, 1113}, {10, 1111}, {10, 1109},
+    {10, 1107}, {10, 1105}, {10, 1103}, {10, 1101}, {10, 1099}, {10, 1097},
+    {10, 1095}, {10, 1093}, {10, 1091}, {10, 1089}, {10, 1087}, {10, 1085},
+    {10, 1083}, {10, 1081}, {10, 1079}, {10, 1077}, {10, 1075}, {10, 1073},
+    {10, 1071}, {10, 1069}, {10, 1067}, {10, 1065}, {10, 1063}, {10, 1061},
+    {10, 1059}, {10, 1057}, {10, 1055}, {10, 1053}, {10, 1051}, {10, 1049},
+    {10, 1047}, {10, 1045}, {10, 1043}, {10, 1041}, {10, 1039}, {10, 1037},
+    {10, 1035}, {10, 1033}, {10, 1031}, {10, 1029}, {10, 1027}, {10, 1025},
+    {10, 1023}, {10, 1021}, {10, 1019}, {10, 1017}, {10, 1015}, {10, 1013},
+    {10, 1011}, {10, 1009}, {10, 1007}, {10, 1005}, {10, 1003}, {10, 1001},
+    {10, 999}, {10, 997}, {10, 995}, {10, 993}, {10, 991}, {10, 989},
+    {10, 987}, {10, 985}, {10, 983}, {10, 981}, {10, 979}, {10, 977},
+    {10, 975}, {10, 973}, {10, 971}, {10, 969}, {10, 967}, {10, 965},
+    {10, 963}, {10, 961}, {10, 959}, {10, 957}, {10, 955}, {10, 953},
+    {10, 951}, {10, 949}, {10, 947}, {10, 945}, {10, 943}, {10, 941},
+    {10, 939}, {10, 937}, {10, 935}, {10, 933}, {10, 931}, {10, 929},
+    {10, 927}, {10, 925}, {10, 923}, {10, 921}, {10, 919}, {10, 917},
+    {10, 915}, {10, 913}, {10, 911}, {10, 909}, {10, 907}, {10, 905},
+    {10, 903}, {10, 901}, {10, 899}, {10, 897}, {10, 895}, {10, 893},
+    {10, 891}, {10, 889}, {10, 887}, {10, 885}, {10, 883}, {10, 881},
+    {10, 879}, {10, 877}, {10, 875}, {10, 873}, {10, 871}, {10, 869},
+    {10, 867}, {10, 865}, {10, 863}, {10, 861}, {10, 859}, {10, 857},
+    {10, 855}, {10, 853}, {10, 851}, {10, 849}, {10, 847}, {10, 845},
+    {10, 843}, {10, 841}, {10, 839}, {10, 837}, {10, 835}, {10, 833},
+    {10, 831}, {10, 829}, {10, 827}, {10, 825}, {10, 823}, {10, 821},
+    {10, 819}, {10, 817}, {10, 815}, {10, 813}, {10, 811}, {10, 809},
+    {10, 807}, {10, 805}, {10, 803}, {10, 801}, {10, 799}, {10, 797},
+    {10, 795}, {10, 793}, {10, 791}, {10, 789}, {10, 787}, {10, 785},
+    {10, 783}, {10, 781}, {10, 779}, {10, 777}, {10, 775}, {10, 773},
+    {10, 771}, {10, 769}, {10, 767}, {10, 765}, {10, 763}, {10, 761},
+    {10, 759}, {10, 757}, {10, 755}, {10, 753}, {10, 751}, {10, 749},
+    {10, 747}, {10, 745}, {10, 743}, {10, 741}, {10, 739}, {10, 737},
+    {10, 735}, {10, 733}, {10, 731}, {10, 729}, {10, 727}, {10, 725},
+    {10, 723}, {10, 721}, {10, 719}, {10, 717}, {10, 715}, {10, 713},
+    {10, 711}, {10, 709}, {10, 707}, {10, 705}, {10, 703}, {10, 701},
+    {10, 699}, {10, 697}, {10, 695}, {10, 693}, {10, 691}, {10, 689},
+    {10, 687}, {10, 685}, {10, 683}, {10, 681}, {10, 679}, {10, 677},
+    {10, 675}, {10, 673}, {10, 671}, {10, 669}, {10, 667}, {10, 665},
+    {10, 663}, {10, 661}, {10, 659}, {10, 657}, {10, 655}, {10, 653},
+    {10, 651}, {10, 649}, {10, 647}, {10, 645}, {10, 643}, {10, 641},
+    {10, 639}, {10, 637}, {10, 635}, {10, 633}, {10, 631}, {10, 629},
+    {10, 627}, {10, 625}, {10, 623}, {10, 621}, {10, 619}, {10, 617},
+    {10, 615}, {10, 613}, {10, 611}, {10, 609}, {10, 607}, {10, 605},
+    {10, 603}, {10, 601}, {10, 599}, {10, 597}, {10, 595}, {10, 593},
+    {10, 591}, {10, 589}, {10, 587}, {10, 585}, {10, 583}, {10, 581},
+    {10, 579}, {10, 577}, {10, 575}, {10, 573}, {10, 571}, {10, 569},
+    {10, 567}, {10, 565}, {10, 563}, {10, 561}, {10, 559}, {10, 557},
+    {10, 555}, {10, 553}, {10, 551}, {10, 549}, {10, 547}, {10, 545},
+    {10, 543}, {10, 541}, {10, 539}, {10, 537}, {10, 535}, {10, 533},
+    {10, 531}, {10, 529}, {10, 527}, {10, 525}, {10, 523}, {10, 521},
+    {10, 519}, {10, 517}, {10, 515}, {10, 513}, {10, 511}, {10, 509},
+    {10, 507}, {10, 505}, {10, 503}, {10, 501}, {10, 499}, {10, 497},
+    {10, 495}, {10, 493}, {10, 491}, {10, 489}, {10, 487}, {10, 485},
+    {10, 483}, {10, 481}, {10, 479}, {10, 477}, {10, 475}, {10, 473},
+    {10, 471}, {10, 469}, {10, 467}, {10, 465}, {10, 463}, {10, 461},
+    {10, 459}, {10, 457}, {10, 455}, {10, 453}, {10, 451}, {10, 449},
+    {10, 447}, {10, 445}, {10, 443}, {10, 441}, {10, 439}, {10, 437},
+    {10, 435}, {10, 433}, {10, 431}, {10, 429}, {10, 427}, {10, 425},
+    {10, 423}, {10, 421}, {10, 419}, {10, 417}, {10, 415}, {10, 413},
+    {10, 411}, {10, 409}, {10, 407}, {10, 405}, {10, 403}, {10, 401},
+    {10, 399}, {10, 397}, {10, 395}, {10, 393}, {10, 391}, {10, 389},
+    {10, 387}, {10, 385}, {10, 383}, {10, 381}, {10, 379}, {10, 377},
+    {10, 375}, {10, 373}, {10, 371}, {10, 369}, {10, 367}, {10, 365},
+    {10, 363}, {10, 361}, {10, 359}, {10, 357}, {10, 355}, {10, 353},
+    {10, 351}, {10, 349}, {10, 347}, {10, 345}, {10, 343}, {10, 341},
+    {10, 339}, {10, 337}, {10, 335}, {10, 333}, {10, 331}, {10, 329},
+    {10, 327}, {10, 325}, {10, 323}, {10, 321}, {10, 319}, {10, 317},
+    {10, 315}, {10, 313}, {10, 311}, {10, 309}, {10, 307}, {10, 305},
+    {10, 303}, {10, 301}, {10, 299}, {10, 297}, {10, 295}, {10, 293},
+    {10, 291}, {10, 289}, {10, 287}, {10, 285}, {10, 283}, {10, 281},
+    {10, 279}, {10, 277}, {10, 275}, {10, 273}, {10, 271}, {10, 269},
+    {10, 267}, {10, 265}, {10, 263}, {10, 261}, {10, 259}, {10, 257},
+    {10, 255}, {10, 253}, {10, 251}, {10, 249}, {10, 247}, {10, 245},
+    {10, 243}, {10, 241}, {10, 239}, {10, 237}, {10, 235}, {10, 233},
+    {10, 231}, {10, 229}, {10, 227}, {10, 225}, {10, 223}, {10, 221},
+    {10, 219}, {10, 217}, {10, 215}, {10, 213}, {10, 211}, {10, 209},
+    {10, 207}, {10, 205}, {10, 203}, {10, 201}, {10, 199}, {10, 197},
+    {10, 195}, {10, 193}, {10, 191}, {10, 189}, {10, 187}, {10, 185},
+    {10, 183}, {10, 181}, {10, 179}, {10, 177}, {10, 175}, {10, 173},
+    {10, 171}, {10, 169}, {10, 167}, {10, 165}, {10, 163}, {10, 161},
+    {10, 159}, {10, 157}, {10, 155}, {10, 153}, {10, 151}, {10, 149},
+    {10, 147}, {10, 145}, {10, 143}, {10, 141}, {10, 139}, {10, 137},
+    {10, 135}, {10, 133}, {10, 131}, {10, 129}, {10, 127}, {10, 125},
+    {10, 123}, {10, 121}, {10, 119}, {10, 117}, {10, 115}, {10, 113},
+    {10, 111}, {10, 109}, {10, 107}, {10, 105}, {10, 103}, {10, 101},
+    {10, 99}, {10, 97}, {10, 95}, {10, 93}, {10, 91}, {10, 89},
+    {10, 87}, {10, 85}, {10, 83}, {10, 81}, {10, 79}, {10, 77},
+    {10, 75}, {10, 73}, {10, 71}, {10, 69}, {10, 67}, {10, 65},
+    {10, 63}, {10, 61}, {10, 59}, {10, 57}, {10, 55}, {10, 53},
+    {10, 51}, {10, 49}, {10, 47}, {10, 45}, {10, 43}, {10, 41},
+    {10, 39}, {10, 37}, {10, 35}, {10, 33}, {10, 31}, {10, 29},
+    {10, 27}, {10, 25}, {10, 23}, {10, 21}, {10, 19}, {10, 17},
+    {10, 15}, {10, 13}, {10, 11}, {10, 9}, {10, 7}, {10, 5},
+    {10, 3}, {10, 1}, {9, 63}, {9, 61}, {9, 59}, {9, 57},
+    {9, 55}, {9, 53}, {9, 51}, {9, 49}, {9, 47}, {9, 45},
+    {9, 43}, {9, 41}, {9, 39}, {9, 37}, {9, 35}, {9, 33},
+    {9, 31}, {9, 29}, {9, 27}, {9, 25}, {9, 23}, {9, 21},
+    {9, 19}, {9, 17}, {9, 15}, {9, 13}, {9, 11}, {9, 9},
+    {9, 7}, {9, 5}, {9, 3}, {9, 1}, {8, 31}, {8, 29},
+    {8, 27}, {8, 25}, {8, 23}, {8, 21}, {8, 19}, {8, 17},
+    {8, 15}, {8, 13}, {8, 11}, {8, 9}, {8, 7}, {8, 5},
+    {8, 3}, {8, 1}, {7, 15}, {7, 13}, {7, 11}, {7, 9},
+    {7, 7}, {7, 5}, {7, 3}, {7, 1}, {6, 7}, {6, 5},
+    {6, 3}, {6, 1}, {5, 3}, {5, 1}, {4, 1}, {3, 1},
+    {2, 1}, {1, 1}, {0, 0}, {1, 0}, {2, 0}, {3, 0},
+    {4, 0}, {5, 0}, {5, 2}, {6, 0}, {6, 2}, {6, 4},
+    {6, 6}, {7, 0}, {7, 2}, {7, 4}, {7, 6}, {7, 8},
+    {7, 10}, {7, 12}, {7, 14}, {8, 0}, {8, 2}, {8, 4},
+    {8, 6}, {8, 8}, {8, 10}, {8, 12}, {8, 14}, {8, 16},
+    {8, 18}, {8, 20}, {8, 22}, {8, 24}, {8, 26}, {8, 28},
+    {8, 30}, {9, 0}, {9, 2}, {9, 4}, {9, 6}, {9, 8},
+    {9, 10}, {9, 12}, {9, 14}, {9, 16}, {9, 18}, {9, 20},
+    {9, 22}, {9, 24}, {9, 26}, {9, 28}, {9, 30}, {9, 32},
+    {9, 34}, {9, 36}, {9, 38}, {9, 40}, {9, 42}, {9, 44},
+    {9, 46}, {9, 48}, {9, 50}, {9, 52}, {9, 54}, {9, 56},
+    {9, 58}, {9, 60}, {9, 62}, {10, 0}, {10, 2}, {10, 4},
+    {10, 6}, {10, 8}, {10, 10}, {10, 12}, {10, 14}, {10, 16},
+    {10, 18}, {10, 20}, {10, 22}, {10, 24}, {10, 26}, {10, 28},
+    {10, 30}, {10, 32}, {10, 34}, {10, 36}, {10, 38}, {10, 40},
+    {10, 42}, {10, 44}, {10, 46}, {10, 48}, {10, 50}, {10, 52},
+    {10, 54}, {10, 56}, {10, 58}, {10, 60}, {10, 62}, {10, 64},
+    {10, 66}, {10, 68}, {10, 70}, {10, 72}, {10, 74}, {10, 76},
+    {10, 78}, {10, 80}, {10, 82}, {10, 84}, {10, 86}, {10, 88},
+    {10, 90}, {10, 92}, {10, 94}, {10, 96}, {10, 98}, {10, 100},
+    {10, 102}, {10, 104}, {10, 106}, {10, 108}, {10, 110}, {10, 112},
+    {10, 114}, {10, 116}, {10, 118}, {10, 120}, {10, 122}, {10, 124},
+    {10, 126}, {10, 128}, {10, 130}, {10, 132}, {10, 134}, {10, 136},
+    {10, 138}, {10, 140}, {10, 142}, {10, 144}, {10, 146}, {10, 148},
+    {10, 150}, {10, 152}, {10, 154}, {10, 156}, {10, 158}, {10, 160},
+    {10, 162}, {10, 164}, {10, 166}, {10, 168}, {10, 170}, {10, 172},
+    {10, 174}, {10, 176}, {10, 178}, {10, 180}, {10, 182}, {10, 184},
+    {10, 186}, {10, 188}, {10, 190}, {10, 192}, {10, 194}, {10, 196},
+    {10, 198}, {10, 200}, {10, 202}, {10, 204}, {10, 206}, {10, 208},
+    {10, 210}, {10, 212}, {10, 214}, {10, 216}, {10, 218}, {10, 220},
+    {10, 222}, {10, 224}, {10, 226}, {10, 228}, {10, 230}, {10, 232},
+    {10, 234}, {10, 236}, {10, 238}, {10, 240}, {10, 242}, {10, 244},
+    {10, 246}, {10, 248}, {10, 250}, {10, 252}, {10, 254}, {10, 256},
+    {10, 258}, {10, 260}, {10, 262}, {10, 264}, {10, 266}, {10, 268},
+    {10, 270}, {10, 272}, {10, 274}, {10, 276}, {10, 278}, {10, 280},
+    {10, 282}, {10, 284}, {10, 286}, {10, 288}, {10, 290}, {10, 292},
+    {10, 294}, {10, 296}, {10, 298}, {10, 300}, {10, 302}, {10, 304},
+    {10, 306}, {10, 308}, {10, 310}, {10, 312}, {10, 314}, {10, 316},
+    {10, 318}, {10, 320}, {10, 322}, {10, 324}, {10, 326}, {10, 328},
+    {10, 330}, {10, 332}, {10, 334}, {10, 336}, {10, 338}, {10, 340},
+    {10, 342}, {10, 344}, {10, 346}, {10, 348}, {10, 350}, {10, 352},
+    {10, 354}, {10, 356}, {10, 358}, {10, 360}, {10, 362}, {10, 364},
+    {10, 366}, {10, 368}, {10, 370}, {10, 372}, {10, 374}, {10, 376},
+    {10, 378}, {10, 380}, {10, 382}, {10, 384}, {10, 386}, {10, 388},
+    {10, 390}, {10, 392}, {10, 394}, {10, 396}, {10, 398}, {10, 400},
+    {10, 402}, {10, 404}, {10, 406}, {10, 408}, {10, 410}, {10, 412},
+    {10, 414}, {10, 416}, {10, 418}, {10, 420}, {10, 422}, {10, 424},
+    {10, 426}, {10, 428}, {10, 430}, {10, 432}, {10, 434}, {10, 436},
+    {10, 438}, {10, 440}, {10, 442}, {10, 444}, {10, 446}, {10, 448},
+    {10, 450}, {10, 452}, {10, 454}, {10, 456}, {10, 458}, {10, 460},
+    {10, 462}, {10, 464}, {10, 466}, {10, 468}, {10, 470}, {10, 472},
+    {10, 474}, {10, 476}, {10, 478}, {10, 480}, {10, 482}, {10, 484},
+    {10, 486}, {10, 488}, {10, 490}, {10, 492}, {10, 494}, {10, 496},
+    {10, 498}, {10, 500}, {10, 502}, {10, 504}, {10, 506}, {10, 508},
+    {10, 510}, {10, 512}, {10, 514}, {10, 516}, {10, 518}, {10, 520},
+    {10, 522}, {10, 524}, {10, 526}, {10, 528}, {10, 530}, {10, 532},
+    {10, 534}, {10, 536}, {10, 538}, {10, 540}, {10, 542}, {10, 544},
+    {10, 546}, {10, 548}, {10, 550}, {10, 552}, {10, 554}, {10, 556},
+    {10, 558}, {10, 560}, {10, 562}, {10, 564}, {10, 566}, {10, 568},
+    {10, 570}, {10, 572}, {10, 574}, {10, 576}, {10, 578}, {10, 580},
+    {10, 582}, {10, 584}, {10, 586}, {10, 588}, {10, 590}, {10, 592},
+    {10, 594}, {10, 596}, {10, 598}, {10, 600}, {10, 602}, {10, 604},
+    {10, 606}, {10, 608}, {10, 610}, {10, 612}, {10, 614}, {10, 616},
+    {10, 618}, {10, 620}, {10, 622}, {10, 624}, {10, 626}, {10, 628},
+    {10, 630}, {10, 632}, {10, 634}, {10, 636}, {10, 638}, {10, 640},
+    {10, 642}, {10, 644}, {10, 646}, {10, 648}, {10, 650}, {10, 652},
+    {10, 654}, {10, 656}, {10, 658}, {10, 660}, {10, 662}, {10, 664},
+    {10, 666}, {10, 668}, {10, 670}, {10, 672}, {10, 674}, {10, 676},
+    {10, 678}, {10, 680}, {10, 682}, {10, 684}, {10, 686}, {10, 688},
+    {10, 690}, {10, 692}, {10, 694}, {10, 696}, {10, 698}, {10, 700},
+    {10, 702}, {10, 704}, {10, 706}, {10, 708}, {10, 710}, {10, 712},
+    {10, 714}, {10, 716}, {10, 718}, {10, 720}, {10, 722}, {10, 724},
+    {10, 726}, {10, 728}, {10, 730}, {10, 732}, {10, 734}, {10, 736},
+    {10, 738}, {10, 740}, {10, 742}, {10, 744}, {10, 746}, {10, 748},
+    {10, 750}, {10, 752}, {10, 754}, {10, 756}, {10, 758}, {10, 760},
+    {10, 762}, {10, 764}, {10, 766}, {10, 768}, {10, 770}, {10, 772},
+    {10, 774}, {10, 776}, {10, 778}, {10, 780}, {10, 782}, {10, 784},
+    {10, 786}, {10, 788}, {10, 790}, {10, 792}, {10, 794}, {10, 796},
+    {10, 798}, {10, 800}, {10, 802}, {10, 804}, {10, 806}, {10, 808},
+    {10, 810}, {10, 812}, {10, 814}, {10, 816}, {10, 818}, {10, 820},
+    {10, 822}, {10, 824}, {10, 826}, {10, 828}, {10, 830}, {10, 832},
+    {10, 834}, {10, 836}, {10, 838}, {10, 840}, {10, 842}, {10, 844},
+    {10, 846}, {10, 848}, {10, 850}, {10, 852}, {10, 854}, {10, 856},
+    {10, 858}, {10, 860}, {10, 862}, {10, 864}, {10, 866}, {10, 868},
+    {10, 870}, {10, 872}, {10, 874}, {10, 876}, {10, 878}, {10, 880},
+    {10, 882}, {10, 884}, {10, 886}, {10, 888}, {10, 890}, {10, 892},
+    {10, 894}, {10, 896}, {10, 898}, {10, 900}, {10, 902}, {10, 904},
+    {10, 906}, {10, 908}, {10, 910}, {10, 912}, {10, 914}, {10, 916},
+    {10, 918}, {10, 920}, {10, 922}, {10, 924}, {10, 926}, {10, 928},
+    {10, 930}, {10, 932}, {10, 934}, {10, 936}, {10, 938}, {10, 940},
+    {10, 942}, {10, 944}, {10, 946}, {10, 948}, {10, 950}, {10, 952},
+    {10, 954}, {10, 956}, {10, 958}, {10, 960}, {10, 962}, {10, 964},
+    {10, 966}, {10, 968}, {10, 970}, {10, 972}, {10, 974}, {10, 976},
+    {10, 978}, {10, 980}, {10, 982}, {10, 984}, {10, 986}, {10, 988},
+    {10, 990}, {10, 992}, {10, 994}, {10, 996}, {10, 998}, {10, 1000},
+    {10, 1002}, {10, 1004}, {10, 1006}, {10, 1008}, {10, 1010}, {10, 1012},
+    {10, 1014}, {10, 1016}, {10, 1018}, {10, 1020}, {10, 1022}, {10, 1024},
+    {10, 1026}, {10, 1028}, {10, 1030}, {10, 1032}, {10, 1034}, {10, 1036},
+    {10, 1038}, {10, 1040}, {10, 1042}, {10, 1044}, {10, 1046}, {10, 1048},
+    {10, 1050}, {10, 1052}, {10, 1054}, {10, 1056}, {10, 1058}, {10, 1060},
+    {10, 1062}, {10, 1064}, {10, 1066}, {10, 1068}, {10, 1070}, {10, 1072},
+    {10, 1074}, {10, 1076}, {10, 1078}, {10, 1080}, {10, 1082}, {10, 1084},
+    {10, 1086}, {10, 1088}, {10, 1090}, {10, 1092}, {10, 1094}, {10, 1096},
+    {10, 1098}, {10, 1100}, {10, 1102}, {10, 1104}, {10, 1106}, {10, 1108},
+    {10, 1110}, {10, 1112}, {10, 1114}, {10, 1116}, {10, 1118}, {10, 1120},
+    {10, 1122}, {10, 1124}, {10, 1126}, {10, 1128}, {10, 1130}, {10, 1132},
+    {10, 1134}, {10, 1136}, {10, 1138}, {10, 1140}, {10, 1142}, {10, 1144},
+    {10, 1146}, {10, 1148}, {10, 1150}, {10, 1152}, {10, 1154}, {10, 1156},
+    {10, 1158}, {10, 1160}, {10, 1162}, {10, 1164}, {10, 1166}, {10, 1168},
+    {10, 1170}, {10, 1172}, {10, 1174}, {10, 1176}, {10, 1178}, {10, 1180},
+    {10, 1182}, {10, 1184}, {10, 1186}, {10, 1188}, {10, 1190}, {10, 1192},
+    {10, 1194}, {10, 1196}, {10, 1198}, {10, 1200}, {10, 1202}, {10, 1204},
+    {10, 1206}, {10, 1208}, {10, 1210}, {10, 1212}, {10, 1214}, {10, 1216},
+    {10, 1218}, {10, 1220}, {10, 1222}, {10, 1224}, {10, 1226}, {10, 1228},
+    {10, 1230}, {10, 1232}, {10, 1234}, {10, 1236}, {10, 1238}, {10, 1240},
+    {10, 1242}, {10, 1244}, {10, 1246}, {10, 1248}, {10, 1250}, {10, 1252},
+    {10, 1254}, {10, 1256}, {10, 1258}, {10, 1260}, {10, 1262}, {10, 1264},
+    {10, 1266}, {10, 1268}, {10, 1270}, {10, 1272}, {10, 1274}, {10, 1276},
+    {10, 1278}, {10, 1280}, {10, 1282}, {10, 1284}, {10, 1286}, {10, 1288},
+    {10, 1290}, {10, 1292}, {10, 1294}, {10, 1296}, {10, 1298}, {10, 1300},
+    {10, 1302}, {10, 1304}, {10, 1306}, {10, 1308}, {10, 1310}, {10, 1312},
+    {10, 1314}, {10, 1316}, {10, 1318}, {10, 1320}, {10, 1322}, {10, 1324},
+    {10, 1326}, {10, 1328}, {10, 1330}, {10, 1332}, {10, 1334}, {10, 1336},
+    {10, 1338}, {10, 1340}, {10, 1342}, {10, 1344}, {10, 1346}, {10, 1348},
+    {10, 1350}, {10, 1352}, {10, 1354}, {10, 1356}, {10, 1358}, {10, 1360},
+    {10, 1362}, {10, 1364}, {10, 1366}, {10, 1368}, {10, 1370}, {10, 1372},
+    {10, 1374}, {10, 1376}, {10, 1378}, {10, 1380}, {10, 1382}, {10, 1384},
+    {10, 1386}, {10, 1388}, {10, 1390}, {10, 1392}, {10, 1394}, {10, 1396},
+    {10, 1398}, {10, 1400}, {10, 1402}, {10, 1404}, {10, 1406}, {10, 1408},
+    {10, 1410}, {10, 1412}, {10, 1414}, {10, 1416}, {10, 1418}, {10, 1420},
+    {10, 1422}, {10, 1424}, {10, 1426}, {10, 1428}, {10, 1430}, {10, 1432},
+    {10, 1434}, {10, 1436}, {10, 1438}, {10, 1440}, {10, 1442}, {10, 1444},
+    {10, 1446}, {10, 1448}, {10, 1450}, {10, 1452}, {10, 1454}, {10, 1456},
+    {10, 1458}, {10, 1460}, {10, 1462}, {10, 1464}, {10, 1466}, {10, 1468},
+    {10, 1470}, {10, 1472}, {10, 1474}, {10, 1476}, {10, 1478}, {10, 1480},
+    {10, 1482}, {10, 1484}, {10, 1486}, {10, 1488}, {10, 1490}, {10, 1492},
+    {10, 1494}, {10, 1496}, {10, 1498}, {10, 1500}, {10, 1502}, {10, 1504},
+    {10, 1506}, {10, 1508}, {10, 1510}, {10, 1512}, {10, 1514}, {10, 1516},
+    {10, 1518}, {10, 1520}, {10, 1522}, {10, 1524}, {10, 1526}, {10, 1528},
+    {10, 1530}, {10, 1532}, {10, 1534}, {10, 1536}, {10, 1538}, {10, 1540},
+    {10, 1542}, {10, 1544}, {10, 1546}, {10, 1548}, {10, 1550}, {10, 1552},
+    {10, 1554}, {10, 1556}, {10, 1558}, {10, 1560}, {10, 1562}, {10, 1564},
+    {10, 1566}, {10, 1568}, {10, 1570}, {10, 1572}, {10, 1574}, {10, 1576},
+    {10, 1578}, {10, 1580}, {10, 1582}, {10, 1584}, {10, 1586}, {10, 1588},
+    {10, 1590}, {10, 1592}, {10, 1594}, {10, 1596}, {10, 1598}, {10, 1600},
+    {10, 1602}, {10, 1604}, {10, 1606}, {10, 1608}, {10, 1610}, {10, 1612},
+    {10, 1614}, {10, 1616}, {10, 1618}, {10, 1620}, {10, 1622}, {10, 1624},
+    {10, 1626}, {10, 1628}, {10, 1630}, {10, 1632}, {10, 1634}, {10, 1636},
+    {10, 1638}, {10, 1640}, {10, 1642}, {10, 1644}, {10, 1646}, {10, 1648},
+    {10, 1650}, {10, 1652}, {10, 1654}, {10, 1656}, {10, 1658}, {10, 1660},
+    {10, 1662}, {10, 1664}, {10, 1666}, {10, 1668}, {10, 1670}, {10, 1672},
+    {10, 1674}, {10, 1676}, {10, 1678}, {10, 1680}, {10, 1682}, {10, 1684},
+    {10, 1686}, {10, 1688}, {10, 1690}, {10, 1692}, {10, 1694}, {10, 1696},
+    {10, 1698}, {10, 1700}, {10, 1702}, {10, 1704}, {10, 1706}, {10, 1708},
+    {10, 1710}, {10, 1712}, {10, 1714}, {10, 1716}, {10, 1718}, {10, 1720},
+    {10, 1722}, {10, 1724}, {10, 1726}, {10, 1728}, {10, 1730}, {10, 1732},
+    {10, 1734}, {10, 1736}, {10, 1738}, {10, 1740}, {10, 1742}, {10, 1744},
+    {10, 1746}, {10, 1748}, {10, 1750}, {10, 1752}, {10, 1754}, {10, 1756},
+    {10, 1758}, {10, 1760}, {10, 1762}, {10, 1764}, {10, 1766}, {10, 1768},
+    {10, 1770}, {10, 1772}, {10, 1774}, {10, 1776}, {10, 1778}, {10, 1780},
+    {10, 1782}, {10, 1784}, {10, 1786}, {10, 1788}, {10, 1790}, {10, 1792},
+    {10, 1794}, {10, 1796}, {10, 1798}, {10, 1800}, {10, 1802}, {10, 1804},
+    {10, 1806}, {10, 1808}, {10, 1810}, {10, 1812}, {10, 1814}, {10, 1816},
+    {10, 1818}, {10, 1820}, {10, 1822}, {10, 1824}, {10, 1826}, {10, 1828},
+    {10, 1830}, {10, 1832}, {10, 1834}, {10, 1836}, {10, 1838}, {10, 1840},
+    {10, 1842}, {10, 1844}, {10, 1846}, {10, 1848}, {10, 1850}, {10, 1852},
+    {10, 1854}, {10, 1856}, {10, 1858}, {10, 1860}, {10, 1862}, {10, 1864},
+    {10, 1866}, {10, 1868}, {10, 1870}, {10, 1872}, {10, 1874}, {10, 1876},
+    {10, 1878}, {10, 1880}, {10, 1882}, {10, 1884}, {10, 1886}, {10, 1888},
+    {10, 1890}, {10, 1892}, {10, 1894}, {10, 1896}, {10, 1898}, {10, 1900},
+    {10, 1902}, {10, 1904}, {10, 1906}, {10, 1908}, {10, 1910}, {10, 1912},
+    {10, 1914}, {10, 1916}, {10, 1918}, {10, 1920}, {10, 1922}, {10, 1924},
+    {10, 1926}, {10, 1928}, {10, 1930}, {10, 1932}, {10, 1934}, {10, 1936},
+    {10, 1938}, {10, 1940}, {10, 1942}, {10, 1944}, {10, 1946}, {10, 1948},
+    {10, 1950}, {10, 1952}, {10, 1954}, {10, 1956}, {10, 1958}, {10, 1960},
+    {10, 1962}, {10, 1964}, {10, 1966}, {10, 1968}, {10, 1970}, {10, 1972},
+    {10, 1974}, {10, 1976}, {10, 1978}, {10, 1980}, {10, 1982}, {10, 1984},
+    {10, 1986}, {10, 1988}, {10, 1990}, {10, 1992}, {10, 1994}, {10, 1996},
+    {10, 1998}, {10, 2000}, {10, 2002}, {10, 2004}, {10, 2006}, {10, 2008},
+    {10, 2010}, {10, 2012}, {10, 2014}, {10, 2016}, {10, 2018}, {10, 2020},
+    {10, 2022}, {10, 2024}, {10, 2026}, {10, 2028}, {10, 2030}, {10, 2032},
+    {10, 2034}, {10, 2036}, {10, 2038}, {10, 2040}, {10, 2042}, {10, 2044},
+    {10, 2046}, {10, 2048}, {10, 2050}, {10, 2052}, {10, 2054}, {10, 2056},
+    {10, 2058}, {10, 2060}, {10, 2062}, {10, 2064}, {10, 2066}, {10, 2068},
+    {10, 2070}, {10, 2072}, {10, 2074}, {10, 2076}, {10, 2078}, {10, 2080},
+    {10, 2082}, {10, 2084}, {10, 2086}, {10, 2088}, {10, 2090}, {10, 2092},
+    {10, 2094}, {10, 2096}, {10, 2098}, {10, 2100}, {10, 2102}, {10, 2104},
+    {10, 2106}, {10, 2108}, {10, 2110}, {10, 2112}, {10, 2114}, {10, 2116},
+    {10, 2118}, {10, 2120}, {10, 2122}, {10, 2124}, {10, 2126}, {10, 2128},
+    {10, 2130}, {10, 2132}, {10, 2134}, {10, 2136}, {10, 2138}, {10, 2140},
+    {10, 2142}, {10, 2144}, {10, 2146}, {10, 2148}, {10, 2150}, {10, 2152},
+    {10, 2154}, {10, 2156}, {10, 2158}, {10, 2160}, {10, 2162}, {10, 2164},
+    {10, 2166}, {10, 2168}, {10, 2170}, {10, 2172}, {10, 2174}, {10, 2176},
+    {10, 2178}, {10, 2180}, {10, 2182}, {10, 2184}, {10, 2186}, {10, 2188},
+    {10, 2190}, {10, 2192}, {10, 2194}, {10, 2196}, {10, 2198}, {10, 2200},
+    {10, 2202}, {10, 2204}, {10, 2206}, {10, 2208}, {10, 2210}, {10, 2212},
+    {10, 2214}, {10, 2216}, {10, 2218}, {10, 2220}, {10, 2222}, {10, 2224},
+    {10, 2226}, {10, 2228}, {10, 2230}, {10, 2232}, {10, 2234}, {10, 2236},
+    {10, 2238}, {10, 2240}, {10, 2242}, {10, 2244}, {10, 2246}, {10, 2248},
+    {10, 2250}, {10, 2252}, {10, 2254}, {10, 2256}, {10, 2258}, {10, 2260},
+    {10, 2262}, {10, 2264}, {10, 2266}, {10, 2268}, {10, 2270}, {10, 2272},
+    {10, 2274}, {10, 2276}, {10, 2278}, {10, 2280}, {10, 2282}, {10, 2284},
+    {10, 2286}, {10, 2288}, {10, 2290}, {10, 2292}, {10, 2294}, {10, 2296},
+    {10, 2298}, {10, 2300}, {10, 2302}, {10, 2304}, {10, 2306}, {10, 2308},
+    {10, 2310}, {10, 2312}, {10, 2314}, {10, 2316}, {10, 2318}, {10, 2320},
+    {10, 2322}, {10, 2324}, {10, 2326}, {10, 2328}, {10, 2330}, {10, 2332},
+    {10, 2334}, {10, 2336}, {10, 2338}, {10, 2340}, {10, 2342}, {10, 2344},
+    {10, 2346}, {10, 2348}, {10, 2350}, {10, 2352}, {10, 2354}, {10, 2356},
+    {10, 2358}, {10, 2360}, {10, 2362}, {10, 2364}, {10, 2366}, {10, 2368},
+    {10, 2370}, {10, 2372}, {10, 2374}, {10, 2376}, {10, 2378}, {10, 2380},
+    {10, 2382}, {10, 2384}, {10, 2386}, {10, 2388}, {10, 2390}, {10, 2392},
+    {10, 2394}, {10, 2396}, {10, 2398}, {10, 2400}, {10, 2402}, {10, 2404},
+    {10, 2406}, {10, 2408}, {10, 2410}, {10, 2412}, {10, 2414}, {10, 2416},
+    {10, 2418}, {10, 2420}, {10, 2422}, {10, 2424}, {10, 2426}, {10, 2428},
+    {10, 2430}, {10, 2432}, {10, 2434}, {10, 2436}, {10, 2438}, {10, 2440},
+    {10, 2442}, {10, 2444}, {10, 2446}, {10, 2448}, {10, 2450}, {10, 2452},
+    {10, 2454}, {10, 2456}, {10, 2458}, {10, 2460}, {10, 2462}, {10, 2464},
+    {10, 2466}, {10, 2468}, {10, 2470}, {10, 2472}, {10, 2474}, {10, 2476},
+    {10, 2478}, {10, 2480}, {10, 2482}, {10, 2484}, {10, 2486}, {10, 2488},
+    {10, 2490}, {10, 2492}, {10, 2494}, {10, 2496}, {10, 2498}, {10, 2500},
+    {10, 2502}, {10, 2504}, {10, 2506}, {10, 2508}, {10, 2510}, {10, 2512},
+    {10, 2514}, {10, 2516}, {10, 2518}, {10, 2520}, {10, 2522}, {10, 2524},
+    {10, 2526}, {10, 2528}, {10, 2530}, {10, 2532}, {10, 2534}, {10, 2536},
+    {10, 2538}, {10, 2540}, {10, 2542}, {10, 2544}, {10, 2546}, {10, 2548},
+    {10, 2550}, {10, 2552}, {10, 2554}, {10, 2556}, {10, 2558}, {10, 2560},
+    {10, 2562}, {10, 2564}, {10, 2566}, {10, 2568}, {10, 2570}, {10, 2572},
+    {10, 2574}, {10, 2576}, {10, 2578}, {10, 2580}, {10, 2582}, {10, 2584},
+    {10, 2586}, {10, 2588}, {10, 2590}, {10, 2592}, {10, 2594}, {10, 2596},
+    {10, 2598}, {10, 2600}, {10, 2602}, {10, 2604}, {10, 2606}, {10, 2608},
+    {10, 2610}, {10, 2612}, {10, 2614}, {10, 2616}, {10, 2618}, {10, 2620},
+    {10, 2622}, {10, 2624}, {10, 2626}, {10, 2628}, {10, 2630}, {10, 2632},
+    {10, 2634}, {10, 2636}, {10, 2638}, {10, 2640}, {10, 2642}, {10, 2644},
+    {10, 2646}, {10, 2648}, {10, 2650}, {10, 2652}, {10, 2654}, {10, 2656},
+    {10, 2658}, {10, 2660}, {10, 2662}, {10, 2664}, {10, 2666}, {10, 2668},
+    {10, 2670}, {10, 2672}, {10, 2674}, {10, 2676}, {10, 2678}, {10, 2680},
+    {10, 2682}, {10, 2684}, {10, 2686}, {10, 2688}, {10, 2690}, {10, 2692},
+    {10, 2694}, {10, 2696}, {10, 2698}, {10, 2700}, {10, 2702}, {10, 2704},
+    {10, 2706}, {10, 2708}, {10, 2710}, {10, 2712}, {10, 2714}, {10, 2716},
+    {10, 2718}, {10, 2720}, {10, 2722}, {10, 2724}, {10, 2726}, {10, 2728},
+    {10, 2730}, {10, 2732}, {10, 2734}, {10, 2736}, {10, 2738}, {10, 2740},
+    {10, 2742}, {10, 2744}, {10, 2746}, {10, 2748}, {10, 2750}, {10, 2752},
+    {10, 2754}, {10, 2756}, {10, 2758}, {10, 2760}, {10, 2762}, {10, 2764},
+    {10, 2766}, {10, 2768}, {10, 2770}, {10, 2772}, {10, 2774}, {10, 2776},
+    {10, 2778}, {10, 2780}, {10, 2782}, {10, 2784}, {10, 2786}, {10, 2788},
+    {10, 2790}, {10, 2792}, {10, 2794}, {10, 2796}, {10, 2798}, {10, 2800},
+    {10, 2802}, {10, 2804}, {10, 2806}, {10, 2808}, {10, 2810}, {10, 2812},
+    {10, 2814}, {10, 2816}, {10, 2818}, {10, 2820}, {10, 2822}, {10, 2824},
+    {10, 2826}, {10, 2828}, {10, 2830}, {10, 2832}, {10, 2834}, {10, 2836},
+    {10, 2838}, {10, 2840}, {10, 2842}, {10, 2844}, {10, 2846}, {10, 2848},
+    {10, 2850}, {10, 2852}, {10, 2854}, {10, 2856}, {10, 2858}, {10, 2860},
+    {10, 2862}, {10, 2864}, {10, 2866}, {10, 2868}, {10, 2870}, {10, 2872},
+    {10, 2874}, {10, 2876}, {10, 2878}, {10, 2880}, {10, 2882}, {10, 2884},
+    {10, 2886}, {10, 2888}, {10, 2890}, {10, 2892}, {10, 2894}, {10, 2896},
+    {10, 2898}, {10, 2900}, {10, 2902}, {10, 2904}, {10, 2906}, {10, 2908},
+    {10, 2910}, {10, 2912}, {10, 2914}, {10, 2916}, {10, 2918}, {10, 2920},
+    {10, 2922}, {10, 2924}, {10, 2926}, {10, 2928}, {10, 2930}, {10, 2932},
+    {10, 2934}, {10, 2936}, {10, 2938}, {10, 2940}, {10, 2942}, {10, 2944},
+    {10, 2946}, {10, 2948}, {10, 2950}, {10, 2952}, {10, 2954}, {10, 2956},
+    {10, 2958}, {10, 2960}, {10, 2962}, {10, 2964}, {10, 2966}, {10, 2968},
+    {10, 2970}, {10, 2972}, {10, 2974}, {10, 2976}, {10, 2978}, {10, 2980},
+    {10, 2982}, {10, 2984}, {10, 2986}, {10, 2988}, {10, 2990}, {10, 2992},
+    {10, 2994}, {10, 2996}, {10, 2998}, {10, 3000}, {10, 3002}, {10, 3004},
+    {10, 3006}, {10, 3008}, {10, 3010}, {10, 3012}, {10, 3014}, {10, 3016},
+    {10, 3018}, {10, 3020}, {10, 3022}, {10, 3024}, {10, 3026}, {10, 3028},
+    {10, 3030}, {10, 3032}, {10, 3034}, {10, 3036}, {10, 3038}, {10, 3040},
+    {10, 3042}, {10, 3044}, {10, 3046}, {10, 3048}, {10, 3050}, {10, 3052},
+    {10, 3054}, {10, 3056}, {10, 3058}, {10, 3060}, {10, 3062}, {10, 3064},
+    {10, 3066}, {10, 3068}, {10, 3070}, {10, 3072}, {10, 3074}, {10, 3076},
+    {10, 3078}, {10, 3080}, {10, 3082}, {10, 3084}, {10, 3086}, {10, 3088},
+    {10, 3090}, {10, 3092}, {10, 3094}, {10, 3096}, {10, 3098}, {10, 3100},
+    {10, 3102}, {10, 3104}, {10, 3106}, {10, 3108}, {10, 3110}, {10, 3112},
+    {10, 3114}, {10, 3116}, {10, 3118}, {10, 3120}, {10, 3122}, {10, 3124},
+    {10, 3126}, {10, 3128}, {10, 3130}, {10, 3132}, {10, 3134}, {10, 3136},
+    {10, 3138}, {10, 3140}, {10, 3142}, {10, 3144}, {10, 3146}, {10, 3148},
+    {10, 3150}, {10, 3152}, {10, 3154}, {10, 3156}, {10, 3158}, {10, 3160},
+    {10, 3162}, {10, 3164}, {10, 3166}, {10, 3168}, {10, 3170}, {10, 3172},
+    {10, 3174}, {10, 3176}, {10, 3178}, {10, 3180}, {10, 3182}, {10, 3184},
+    {10, 3186}, {10, 3188}, {10, 3190}, {10, 3192}, {10, 3194}, {10, 3196},
+    {10, 3198}, {10, 3200}, {10, 3202}, {10, 3204}, {10, 3206}, {10, 3208},
+    {10, 3210}, {10, 3212}, {10, 3214}, {10, 3216}, {10, 3218}, {10, 3220},
+    {10, 3222}, {10, 3224}, {10, 3226}, {10, 3228}, {10, 3230}, {10, 3232},
+    {10, 3234}, {10, 3236}, {10, 3238}, {10, 3240}, {10, 3242}, {10, 3244},
+    {10, 3246}, {10, 3248}, {10, 3250}, {10, 3252}, {10, 3254}, {10, 3256},
+    {10, 3258}, {10, 3260}, {10, 3262}, {10, 3264}, {10, 3266}, {10, 3268},
+    {10, 3270}, {10, 3272}, {10, 3274}, {10, 3276}, {10, 3278}, {10, 3280},
+    {10, 3282}, {10, 3284}, {10, 3286}, {10, 3288}, {10, 3290}, {10, 3292},
+    {10, 3294}, {10, 3296}, {10, 3298}, {10, 3300}, {10, 3302}, {10, 3304},
+    {10, 3306}, {10, 3308}, {10, 3310}, {10, 3312}, {10, 3314}, {10, 3316},
+    {10, 3318}, {10, 3320}, {10, 3322}, {10, 3324}, {10, 3326}, {10, 3328},
+    {10, 3330}, {10, 3332}, {10, 3334}, {10, 3336}, {10, 3338}, {10, 3340},
+    {10, 3342}, {10, 3344}, {10, 3346}, {10, 3348}, {10, 3350}, {10, 3352},
+    {10, 3354}, {10, 3356}, {10, 3358}, {10, 3360}, {10, 3362}, {10, 3364},
+    {10, 3366}, {10, 3368}, {10, 3370}, {10, 3372}, {10, 3374}, {10, 3376},
+    {10, 3378}, {10, 3380}, {10, 3382}, {10, 3384}, {10, 3386}, {10, 3388},
+    {10, 3390}, {10, 3392}, {10, 3394}, {10, 3396}, {10, 3398}, {10, 3400},
+    {10, 3402}, {10, 3404}, {10, 3406}, {10, 3408}, {10, 3410}, {10, 3412},
+    {10, 3414}, {10, 3416}, {10, 3418}, {10, 3420}, {10, 3422}, {10, 3424},
+    {10, 3426}, {10, 3428}, {10, 3430}, {10, 3432}, {10, 3434}, {10, 3436},
+    {10, 3438}, {10, 3440}, {10, 3442}, {10, 3444}, {10, 3446}, {10, 3448},
+    {10, 3450}, {10, 3452}, {10, 3454}, {10, 3456}, {10, 3458}, {10, 3460},
+    {10, 3462}, {10, 3464}, {10, 3466}, {10, 3468}, {10, 3470}, {10, 3472},
+    {10, 3474}, {10, 3476}, {10, 3478}, {10, 3480}, {10, 3482}, {10, 3484},
+    {10, 3486}, {10, 3488}, {10, 3490}, {10, 3492}, {10, 3494}, {10, 3496},
+    {10, 3498}, {10, 3500}, {10, 3502}, {10, 3504}, {10, 3506}, {10, 3508},
+    {10, 3510}, {10, 3512}, {10, 3514}, {10, 3516}, {10, 3518}, {10, 3520},
+    {10, 3522}, {10, 3524}, {10, 3526}, {10, 3528}, {10, 3530}, {10, 3532},
+    {10, 3534}, {10, 3536}, {10, 3538}, {10, 3540}, {10, 3542}, {10, 3544},
+    {10, 3546}, {10, 3548}, {10, 3550}, {10, 3552}, {10, 3554}, {10, 3556},
+    {10, 3558}, {10, 3560}, {10, 3562}, {10, 3564}, {10, 3566}, {10, 3568},
+    {10, 3570}, {10, 3572}, {10, 3574}, {10, 3576}, {10, 3578}, {10, 3580},
+    {10, 3582}, {10, 3584}, {10, 3586}, {10, 3588}, {10, 3590}, {10, 3592},
+    {10, 3594}, {10, 3596}, {10, 3598}, {10, 3600}, {10, 3602}, {10, 3604},
+    {10, 3606}, {10, 3608}, {10, 3610}, {10, 3612}, {10, 3614}, {10, 3616},
+    {10, 3618}, {10, 3620}, {10, 3622}, {10, 3624}, {10, 3626}, {10, 3628},
+    {10, 3630}, {10, 3632}, {10, 3634}, {10, 3636}, {10, 3638}, {10, 3640},
+    {10, 3642}, {10, 3644}, {10, 3646}, {10, 3648}, {10, 3650}, {10, 3652},
+    {10, 3654}, {10, 3656}, {10, 3658}, {10, 3660}, {10, 3662}, {10, 3664},
+    {10, 3666}, {10, 3668}, {10, 3670}, {10, 3672}, {10, 3674}, {10, 3676},
+    {10, 3678}, {10, 3680}, {10, 3682}, {10, 3684}, {10, 3686}, {10, 3688},
+    {10, 3690}, {10, 3692}, {10, 3694}, {10, 3696}, {10, 3698}, {10, 3700},
+    {10, 3702}, {10, 3704}, {10, 3706}, {10, 3708}, {10, 3710}, {10, 3712},
+    {10, 3714}, {10, 3716}, {10, 3718}, {10, 3720}, {10, 3722}, {10, 3724},
+    {10, 3726}, {10, 3728}, {10, 3730}, {10, 3732}, {10, 3734}, {10, 3736},
+    {10, 3738}, {10, 3740}, {10, 3742}, {10, 3744}, {10, 3746}, {10, 3748},
+    {10, 3750}, {10, 3752}, {10, 3754}, {10, 3756}, {10, 3758}, {10, 3760},
+    {10, 3762}, {10, 3764}, {10, 3766}, {10, 3768}, {10, 3770}, {10, 3772},
+    {10, 3774}, {10, 3776}, {10, 3778}, {10, 3780}, {10, 3782}, {10, 3784},
+    {10, 3786}, {10, 3788}, {10, 3790}, {10, 3792}, {10, 3794}, {10, 3796},
+    {10, 3798}, {10, 3800}, {10, 3802}, {10, 3804}, {10, 3806}, {10, 3808},
+    {10, 3810}, {10, 3812}, {10, 3814}, {10, 3816}, {10, 3818}, {10, 3820},
+    {10, 3822}, {10, 3824}, {10, 3826}, {10, 3828}, {10, 3830}, {10, 3832},
+    {10, 3834}, {10, 3836}, {10, 3838}, {10, 3840}, {10, 3842}, {10, 3844},
+    {10, 3846}, {10, 3848}, {10, 3850}, {10, 3852}, {10, 3854}, {10, 3856},
+    {10, 3858}, {10, 3860}, {10, 3862}, {10, 3864}, {10, 3866}, {10, 3868},
+    {10, 3870}, {10, 3872}, {10, 3874}, {10, 3876}, {10, 3878}, {10, 3880},
+    {10, 3882}, {10, 3884}, {10, 3886}, {10, 3888}, {10, 3890}, {10, 3892},
+    {10, 3894}, {10, 3896}, {10, 3898}, {10, 3900}, {10, 3902}, {10, 3904},
+    {10, 3906}, {10, 3908}, {10, 3910}, {10, 3912}, {10, 3914}, {10, 3916},
+    {10, 3918}, {10, 3920}, {10, 3922}, {10, 3924}, {10, 3926}, {10, 3928},
+    {10, 3930}, {10, 3932}, {10, 3934}, {10, 3936}, {10, 3938}, {10, 3940},
+    {10, 3942}, {10, 3944}, {10, 3946}, {10, 3948}, {10, 3950}, {10, 3952},
+    {10, 3954}, {10, 3956}, {10, 3958}, {10, 3960}
+};
diff --git a/vp8/encoder/defaultcoefcounts.h b/vp8/encoder/defaultcoefcounts.h
new file mode 100644 (file)
index 0000000..2c0f3dd
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/* Generated file, included by entropy.c */
+
+static const unsigned int default_coef_counts[BLOCK_TYPES]
+                                             [COEF_BANDS]
+                                             [PREV_COEF_CONTEXTS]
+                                             [MAX_ENTROPY_TOKENS] =
+{
+
+    {
+        /* Block Type ( 0 ) */
+        {
+            /* Coeff Band ( 0 ) */
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+        },
+        {
+            /* Coeff Band ( 1 ) */
+            {30190, 26544, 225,  24,   4,   0,   0,   0,   0,   0,   0, 4171593,},
+            {26846, 25157, 1241, 130,  26,   6,   1,   0,   0,   0,   0, 149987,},
+            {10484, 9538, 1006, 160,  36,  18,   0,   0,   0,   0,   0, 15104,},
+        },
+        {
+            /* Coeff Band ( 2 ) */
+            {25842, 40456, 1126,  83,  11,   2,   0,   0,   0,   0,   0,   0,},
+            {9338, 8010, 512,  73,   7,   3,   2,   0,   0,   0,   0, 43294,},
+            {1047, 751, 149,  31,  13,   6,   1,   0,   0,   0,   0, 879,},
+        },
+        {
+            /* Coeff Band ( 3 ) */
+            {26136, 9826, 252,  13,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {8134, 5574, 191,  14,   2,   0,   0,   0,   0,   0,   0, 35302,},
+            { 605, 677, 116,   9,   1,   0,   0,   0,   0,   0,   0, 611,},
+        },
+        {
+            /* Coeff Band ( 4 ) */
+            {10263, 15463, 283,  17,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {2773, 2191, 128,   9,   2,   2,   0,   0,   0,   0,   0, 10073,},
+            { 134, 125,  32,   4,   0,   2,   0,   0,   0,   0,   0,  50,},
+        },
+        {
+            /* Coeff Band ( 5 ) */
+            {10483, 2663,  23,   1,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {2137, 1251,  27,   1,   1,   0,   0,   0,   0,   0,   0, 14362,},
+            { 116, 156,  14,   2,   1,   0,   0,   0,   0,   0,   0, 190,},
+        },
+        {
+            /* Coeff Band ( 6 ) */
+            {40977, 27614, 412,  28,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {6113, 5213, 261,  22,   3,   0,   0,   0,   0,   0,   0, 26164,},
+            { 382, 312,  50,  14,   2,   0,   0,   0,   0,   0,   0, 345,},
+        },
+        {
+            /* Coeff Band ( 7 ) */
+            {   0,  26,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,  13,   0,   0,   0,   0,   0,   0,   0,   0,   0, 319,},
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   8,},
+        },
+    },
+    {
+        /* Block Type ( 1 ) */
+        {
+            /* Coeff Band ( 0 ) */
+            {3268, 19382, 1043, 250,  93,  82,  49,  26,  17,   8,  25, 82289,},
+            {8758, 32110, 5436, 1832, 827, 668, 420, 153,  24,   0,   3, 52914,},
+            {9337, 23725, 8487, 3954, 2107, 1836, 1069, 399,  59,   0,   0, 18620,},
+        },
+        {
+            /* Coeff Band ( 1 ) */
+            {12419, 8420, 452,  62,   9,   1,   0,   0,   0,   0,   0,   0,},
+            {11715, 8705, 693,  92,  15,   7,   2,   0,   0,   0,   0, 53988,},
+            {7603, 8585, 2306, 778, 270, 145,  39,   5,   0,   0,   0, 9136,},
+        },
+        {
+            /* Coeff Band ( 2 ) */
+            {15938, 14335, 1207, 184,  55,  13,   4,   1,   0,   0,   0,   0,},
+            {7415, 6829, 1138, 244,  71,  26,   7,   0,   0,   0,   0, 9980,},
+            {1580, 1824, 655, 241,  89,  46,  10,   2,   0,   0,   0, 429,},
+        },
+        {
+            /* Coeff Band ( 3 ) */
+            {19453, 5260, 201,  19,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {9173, 3758, 213,  22,   1,   1,   0,   0,   0,   0,   0, 9820,},
+            {1689, 1277, 276,  51,  17,   4,   0,   0,   0,   0,   0, 679,},
+        },
+        {
+            /* Coeff Band ( 4 ) */
+            {12076, 10667, 620,  85,  19,   9,   5,   0,   0,   0,   0,   0,},
+            {4665, 3625, 423,  55,  19,   9,   0,   0,   0,   0,   0, 5127,},
+            { 415, 440, 143,  34,  20,   7,   2,   0,   0,   0,   0, 101,},
+        },
+        {
+            /* Coeff Band ( 5 ) */
+            {12183, 4846, 115,  11,   1,   0,   0,   0,   0,   0,   0,   0,},
+            {4226, 3149, 177,  21,   2,   0,   0,   0,   0,   0,   0, 7157,},
+            { 375, 621, 189,  51,  11,   4,   1,   0,   0,   0,   0, 198,},
+        },
+        {
+            /* Coeff Band ( 6 ) */
+            {61658, 37743, 1203,  94,  10,   3,   0,   0,   0,   0,   0,   0,},
+            {15514, 11563, 903, 111,  14,   5,   0,   0,   0,   0,   0, 25195,},
+            { 929, 1077, 291,  78,  14,   7,   1,   0,   0,   0,   0, 507,},
+        },
+        {
+            /* Coeff Band ( 7 ) */
+            {   0, 990,  15,   3,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0, 412,  13,   0,   0,   0,   0,   0,   0,   0,   0, 1641,},
+            {   0,  18,   7,   1,   0,   0,   0,   0,   0,   0,   0,  30,},
+        },
+    },
+    {
+        /* Block Type ( 2 ) */
+        {
+            /* Coeff Band ( 0 ) */
+            { 953, 24519, 628, 120,  28,  12,   4,   0,   0,   0,   0, 2248798,},
+            {1525, 25654, 2647, 617, 239, 143,  42,   5,   0,   0,   0, 66837,},
+            {1180, 11011, 3001, 1237, 532, 448, 239,  54,   5,   0,   0, 7122,},
+        },
+        {
+            /* Coeff Band ( 1 ) */
+            {1356, 2220,  67,  10,   4,   1,   0,   0,   0,   0,   0,   0,},
+            {1450, 2544, 102,  18,   4,   3,   0,   0,   0,   0,   0, 57063,},
+            {1182, 2110, 470, 130,  41,  21,   0,   0,   0,   0,   0, 6047,},
+        },
+        {
+            /* Coeff Band ( 2 ) */
+            { 370, 3378, 200,  30,   5,   4,   1,   0,   0,   0,   0,   0,},
+            { 293, 1006, 131,  29,  11,   0,   0,   0,   0,   0,   0, 5404,},
+            { 114, 387,  98,  23,   4,   8,   1,   0,   0,   0,   0, 236,},
+        },
+        {
+            /* Coeff Band ( 3 ) */
+            { 579, 194,   4,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            { 395, 213,   5,   1,   0,   0,   0,   0,   0,   0,   0, 4157,},
+            { 119, 122,   4,   0,   0,   0,   0,   0,   0,   0,   0, 300,},
+        },
+        {
+            /* Coeff Band ( 4 ) */
+            {  38, 557,  19,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {  21, 114,  12,   1,   0,   0,   0,   0,   0,   0,   0, 427,},
+            {   0,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   7,},
+        },
+        {
+            /* Coeff Band ( 5 ) */
+            {  52,   7,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {  18,   6,   0,   0,   0,   0,   0,   0,   0,   0,   0, 652,},
+            {   1,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,  30,},
+        },
+        {
+            /* Coeff Band ( 6 ) */
+            { 640, 569,  10,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {  25,  77,   2,   0,   0,   0,   0,   0,   0,   0,   0, 517,},
+            {   4,   7,   0,   0,   0,   0,   0,   0,   0,   0,   0,   3,},
+        },
+        {
+            /* Coeff Band ( 7 ) */
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+        },
+    },
+    {
+        /* Block Type ( 3 ) */
+        {
+            /* Coeff Band ( 0 ) */
+            {2506, 20161, 2707, 767, 261, 178, 107,  30,  14,   3,   0, 100694,},
+            {8806, 36478, 8817, 3268, 1280, 850, 401, 114,  42,   0,   0, 58572,},
+            {11003, 27214, 11798, 5716, 2482, 2072, 1048, 175,  32,   0,   0, 19284,},
+        },
+        {
+            /* Coeff Band ( 1 ) */
+            {9738, 11313, 959, 205,  70,  18,  11,   1,   0,   0,   0,   0,},
+            {12628, 15085, 1507, 273,  52,  19,   9,   0,   0,   0,   0, 54280,},
+            {10701, 15846, 5561, 1926, 813, 570, 249,  36,   0,   0,   0, 6460,},
+        },
+        {
+            /* Coeff Band ( 2 ) */
+            {6781, 22539, 2784, 634, 182, 123,  20,   4,   0,   0,   0,   0,},
+            {6263, 11544, 2649, 790, 259, 168,  27,   5,   0,   0,   0, 20539,},
+            {3109, 4075, 2031, 896, 457, 386, 158,  29,   0,   0,   0, 1138,},
+        },
+        {
+            /* Coeff Band ( 3 ) */
+            {11515, 4079, 465,  73,   5,  14,   2,   0,   0,   0,   0,   0,},
+            {9361, 5834, 650,  96,  24,   8,   4,   0,   0,   0,   0, 22181,},
+            {4343, 3974, 1360, 415, 132,  96,  14,   1,   0,   0,   0, 1267,},
+        },
+        {
+            /* Coeff Band ( 4 ) */
+            {4787, 9297, 823, 168,  44,  12,   4,   0,   0,   0,   0,   0,},
+            {3619, 4472, 719, 198,  60,  31,   3,   0,   0,   0,   0, 8401,},
+            {1157, 1175, 483, 182,  88,  31,   8,   0,   0,   0,   0, 268,},
+        },
+        {
+            /* Coeff Band ( 5 ) */
+            {8299, 1226,  32,   5,   1,   0,   0,   0,   0,   0,   0,   0,},
+            {3502, 1568,  57,   4,   1,   1,   0,   0,   0,   0,   0, 9811,},
+            {1055, 1070, 166,  29,   6,   1,   0,   0,   0,   0,   0, 527,},
+        },
+        {
+            /* Coeff Band ( 6 ) */
+            {27414, 27927, 1989, 347,  69,  26,   0,   0,   0,   0,   0,   0,},
+            {5876, 10074, 1574, 341,  91,  24,   4,   0,   0,   0,   0, 21954,},
+            {1571, 2171, 778, 324, 124,  65,  16,   0,   0,   0,   0, 979,},
+        },
+        {
+            /* Coeff Band ( 7 ) */
+            {   0,  29,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,  23,   0,   0,   0,   0,   0,   0,   0,   0,   0, 459,},
+            {   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,  13,},
+        },
+    },
+};
diff --git a/vp8/encoder/denoising.c b/vp8/encoder/denoising.c
new file mode 100644 (file)
index 0000000..09ed9dd
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "denoising.h"
+
+#include "vp8/common/reconinter.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_rtcd.h"
+
+static const unsigned int NOISE_MOTION_THRESHOLD = 20*20;
+static const unsigned int NOISE_DIFF2_THRESHOLD = 75;
+// SSE_DIFF_THRESHOLD is selected as ~95% confidence assuming var(noise) ~= 100.
+static const unsigned int SSE_DIFF_THRESHOLD = 16*16*20;
+static const unsigned int SSE_THRESHOLD = 16*16*40;
+
+static uint8_t blend(uint8_t state, uint8_t sample, uint8_t factor_q8)
+{
+  return (uint8_t)(
+      (((uint16_t)factor_q8 * ((uint16_t)state) +  // Q8
+        (uint16_t)(256 - factor_q8) * ((uint16_t)sample)) + 128)  // Q8
+      >> 8);
+}
+
+static unsigned int denoiser_motion_compensate(YV12_BUFFER_CONFIG* src,
+                                               YV12_BUFFER_CONFIG* dst,
+                                               MACROBLOCK* x,
+                                               unsigned int best_sse,
+                                               unsigned int zero_mv_sse,
+                                               int recon_yoffset,
+                                               int recon_uvoffset)
+{
+  MACROBLOCKD filter_xd = x->e_mbd;
+  int mv_col;
+  int mv_row;
+  int sse_diff = zero_mv_sse - best_sse;
+  // Compensate the running average.
+  filter_xd.pre.y_buffer = src->y_buffer + recon_yoffset;
+  filter_xd.pre.u_buffer = src->u_buffer + recon_uvoffset;
+  filter_xd.pre.v_buffer = src->v_buffer + recon_uvoffset;
+  // Write the compensated running average to the destination buffer.
+  filter_xd.dst.y_buffer = dst->y_buffer + recon_yoffset;
+  filter_xd.dst.u_buffer = dst->u_buffer + recon_uvoffset;
+  filter_xd.dst.v_buffer = dst->v_buffer + recon_uvoffset;
+  // Use the best MV for the compensation.
+  filter_xd.mode_info_context->mbmi.ref_frame = LAST_FRAME;
+  filter_xd.mode_info_context->mbmi.mode = filter_xd.best_sse_inter_mode;
+  filter_xd.mode_info_context->mbmi.mv = filter_xd.best_sse_mv;
+  filter_xd.mode_info_context->mbmi.need_to_clamp_mvs =
+      filter_xd.need_to_clamp_best_mvs;
+  mv_col = filter_xd.best_sse_mv.as_mv.col;
+  mv_row = filter_xd.best_sse_mv.as_mv.row;
+  if (filter_xd.mode_info_context->mbmi.mode <= B_PRED ||
+      (mv_row*mv_row + mv_col*mv_col <= NOISE_MOTION_THRESHOLD &&
+       sse_diff < SSE_DIFF_THRESHOLD))
+  {
+    // Handle intra blocks as referring to last frame with zero motion and
+    // let the absolute pixel difference affect the filter factor.
+    // Also consider small amount of motion as being random walk due to noise,
+    // if it doesn't mean that we get a much bigger error.
+    // Note that any changes to the mode info only affects the denoising.
+    filter_xd.mode_info_context->mbmi.ref_frame = LAST_FRAME;
+    filter_xd.mode_info_context->mbmi.mode = ZEROMV;
+    filter_xd.mode_info_context->mbmi.mv.as_int = 0;
+    x->e_mbd.best_sse_inter_mode = ZEROMV;
+    x->e_mbd.best_sse_mv.as_int = 0;
+    best_sse = zero_mv_sse;
+  }
+  if (!x->skip)
+  {
+    vp8_build_inter_predictors_mb(&filter_xd);
+  }
+  else
+  {
+    vp8_build_inter16x16_predictors_mb(&filter_xd,
+                                       filter_xd.dst.y_buffer,
+                                       filter_xd.dst.u_buffer,
+                                       filter_xd.dst.v_buffer,
+                                       filter_xd.dst.y_stride,
+                                       filter_xd.dst.uv_stride);
+  }
+  return best_sse;
+}
+
+static void denoiser_filter(YV12_BUFFER_CONFIG* mc_running_avg,
+                            YV12_BUFFER_CONFIG* running_avg,
+                            MACROBLOCK* signal,
+                            unsigned int motion_magnitude2,
+                            int y_offset,
+                            int uv_offset)
+{
+  unsigned char* sig = signal->thismb;
+  int sig_stride = 16;
+  unsigned char* mc_running_avg_y = mc_running_avg->y_buffer + y_offset;
+  int mc_avg_y_stride = mc_running_avg->y_stride;
+  unsigned char* running_avg_y = running_avg->y_buffer + y_offset;
+  int avg_y_stride = running_avg->y_stride;
+  int r, c;
+  for (r = 0; r < 16; r++)
+  {
+    for (c = 0; c < 16; c++)
+    {
+      int diff;
+      int absdiff = 0;
+      unsigned int filter_coefficient;
+      absdiff = sig[c] - mc_running_avg_y[c];
+      absdiff = absdiff > 0 ? absdiff : -absdiff;
+      assert(absdiff >= 0 && absdiff < 256);
+      filter_coefficient = (255 << 8) / (256 + ((absdiff * 330) >> 3));
+      // Allow some additional filtering of static blocks, or blocks with very
+      // small motion vectors.
+      filter_coefficient += filter_coefficient / (3 + (motion_magnitude2 >> 3));
+      filter_coefficient = filter_coefficient > 255 ? 255 : filter_coefficient;
+
+      running_avg_y[c] = blend(mc_running_avg_y[c], sig[c], filter_coefficient);
+      diff = sig[c] - running_avg_y[c];
+
+      if (diff * diff < NOISE_DIFF2_THRESHOLD)
+      {
+        // Replace with mean to suppress the noise.
+        sig[c] = running_avg_y[c];
+      }
+      else
+      {
+        // Replace the filter state with the signal since the change in this
+        // pixel isn't classified as noise.
+        running_avg_y[c] = sig[c];
+      }
+    }
+    sig += sig_stride;
+    mc_running_avg_y += mc_avg_y_stride;
+    running_avg_y += avg_y_stride;
+  }
+}
+
+int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height)
+{
+  assert(denoiser);
+  denoiser->yv12_running_avg.flags = 0;
+  if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_running_avg), width,
+                                  height, VP8BORDERINPIXELS) < 0)
+  {
+      vp8_denoiser_free(denoiser);
+      return 1;
+  }
+  denoiser->yv12_mc_running_avg.flags = 0;
+  if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_mc_running_avg), width,
+                                  height, VP8BORDERINPIXELS) < 0)
+  {
+      vp8_denoiser_free(denoiser);
+      return 1;
+  }
+  vpx_memset(denoiser->yv12_running_avg.buffer_alloc, 0,
+             denoiser->yv12_running_avg.frame_size);
+  vpx_memset(denoiser->yv12_mc_running_avg.buffer_alloc, 0,
+             denoiser->yv12_mc_running_avg.frame_size);
+  return 0;
+}
+
+void vp8_denoiser_free(VP8_DENOISER *denoiser)
+{
+  assert(denoiser);
+  vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_running_avg);
+  vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_mc_running_avg);
+}
+
+void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser,
+                             MACROBLOCK *x,
+                             unsigned int best_sse,
+                             unsigned int zero_mv_sse,
+                             int recon_yoffset,
+                             int recon_uvoffset) {
+  int mv_row;
+  int mv_col;
+  unsigned int motion_magnitude2;
+  // Motion compensate the running average.
+  best_sse = denoiser_motion_compensate(&denoiser->yv12_running_avg,
+                                        &denoiser->yv12_mc_running_avg,
+                                        x,
+                                        best_sse,
+                                        zero_mv_sse,
+                                        recon_yoffset,
+                                        recon_uvoffset);
+
+  mv_row = x->e_mbd.best_sse_mv.as_mv.row;
+  mv_col = x->e_mbd.best_sse_mv.as_mv.col;
+  motion_magnitude2 = mv_row*mv_row + mv_col*mv_col;
+  if (best_sse > SSE_THRESHOLD ||
+      motion_magnitude2 > 8 * NOISE_MOTION_THRESHOLD)
+  {
+    // No filtering of this block since it differs too much from the predictor,
+    // or the motion vector magnitude is considered too big.
+    vp8_copy_mem16x16(x->thismb, 16,
+                      denoiser->yv12_running_avg.y_buffer + recon_yoffset,
+                      denoiser->yv12_running_avg.y_stride);
+    return;
+  }
+  // Filter.
+  denoiser_filter(&denoiser->yv12_mc_running_avg,
+                  &denoiser->yv12_running_avg,
+                  x,
+                  motion_magnitude2,
+                  recon_yoffset,
+                  recon_uvoffset);
+}
diff --git a/vp8/encoder/denoising.h b/vp8/encoder/denoising.h
new file mode 100644 (file)
index 0000000..343531b
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef VP8_ENCODER_DENOISING_H_
+#define VP8_ENCODER_DENOISING_H_
+
+#include "block.h"
+
+typedef struct vp8_denoiser
+{
+  YV12_BUFFER_CONFIG yv12_running_avg;
+  YV12_BUFFER_CONFIG yv12_mc_running_avg;
+} VP8_DENOISER;
+
+int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height);
+
+void vp8_denoiser_free(VP8_DENOISER *denoiser);
+
+void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser,
+                             MACROBLOCK *x,
+                             unsigned int best_sse,
+                             unsigned int zero_mv_sse,
+                             int recon_yoffset,
+                             int recon_uvoffset);
+
+#endif  // VP8_ENCODER_DENOISING_H_
diff --git a/vp8/encoder/encodeframe.c b/vp8/encoder/encodeframe.c
new file mode 100644 (file)
index 0000000..8233873
--- /dev/null
@@ -0,0 +1,1352 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "encodemb.h"
+#include "encodemv.h"
+#include "vp8/common/common.h"
+#include "onyx_int.h"
+#include "vp8/common/extend.h"
+#include "vp8/common/entropymode.h"
+#include "vp8/common/quant_common.h"
+#include "segmentation.h"
+#include "vp8/common/setupintrarecon.h"
+#include "encodeintra.h"
+#include "vp8/common/reconinter.h"
+#include "rdopt.h"
+#include "pickinter.h"
+#include "vp8/common/findnearmv.h"
+#include <stdio.h>
+#include <limits.h>
+#include "vp8/common/invtrans.h"
+#include "vpx_ports/vpx_timer.h"
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+#include "bitstream.h"
+#endif
+#include "encodeframe.h"
+
+extern void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) ;
+extern void vp8_calc_ref_frame_costs(int *ref_frame_cost,
+                                     int prob_intra,
+                                     int prob_last,
+                                     int prob_garf
+                                    );
+extern void vp8_convert_rfct_to_prob(VP8_COMP *const cpi);
+extern void vp8cx_initialize_me_consts(VP8_COMP *cpi, int QIndex);
+extern void vp8_auto_select_speed(VP8_COMP *cpi);
+extern void vp8cx_init_mbrthread_data(VP8_COMP *cpi,
+                                      MACROBLOCK *x,
+                                      MB_ROW_COMP *mbr_ei,
+                                      int mb_row,
+                                      int count);
+static void adjust_act_zbin( VP8_COMP *cpi, MACROBLOCK *x );
+
+#ifdef MODE_STATS
+unsigned int inter_y_modes[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+unsigned int inter_uv_modes[4] = {0, 0, 0, 0};
+unsigned int inter_b_modes[15]  = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+unsigned int y_modes[5]   = {0, 0, 0, 0, 0};
+unsigned int uv_modes[4]  = {0, 0, 0, 0};
+unsigned int b_modes[14]  = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+#endif
+
+
+/* activity_avg must be positive, or flat regions could get a zero weight
+ *  (infinite lambda), which confounds analysis.
+ * This also avoids the need for divide by zero checks in
+ *  vp8_activity_masking().
+ */
+#define VP8_ACTIVITY_AVG_MIN (64)
+
+/* This is used as a reference when computing the source variance for the
+ *  purposes of activity masking.
+ * Eventually this should be replaced by custom no-reference routines,
+ *  which will be faster.
+ */
+static const unsigned char VP8_VAR_OFFS[16]=
+{
+    128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128
+};
+
+
+// Original activity measure from Tim T's code.
+static unsigned int tt_activity_measure( VP8_COMP *cpi, MACROBLOCK *x )
+{
+    unsigned int act;
+    unsigned int sse;
+    /* TODO: This could also be done over smaller areas (8x8), but that would
+     *  require extensive changes elsewhere, as lambda is assumed to be fixed
+     *  over an entire MB in most of the code.
+     * Another option is to compute four 8x8 variances, and pick a single
+     *  lambda using a non-linear combination (e.g., the smallest, or second
+     *  smallest, etc.).
+     */
+    act =  vp8_variance16x16(x->src.y_buffer,
+                    x->src.y_stride, VP8_VAR_OFFS, 0, &sse);
+    act = act<<4;
+
+    /* If the region is flat, lower the activity some more. */
+    if (act < 8<<12)
+        act = act < 5<<12 ? act : 5<<12;
+
+    return act;
+}
+
+// Stub for alternative experimental activity measures.
+static unsigned int alt_activity_measure( VP8_COMP *cpi,
+                                          MACROBLOCK *x, int use_dc_pred )
+{
+    return vp8_encode_intra(cpi,x, use_dc_pred);
+}
+
+
+// Measure the activity of the current macroblock
+// What we measure here is TBD so abstracted to this function
+#define ALT_ACT_MEASURE 1
+static unsigned int mb_activity_measure( VP8_COMP *cpi, MACROBLOCK *x,
+                                  int mb_row, int mb_col)
+{
+    unsigned int mb_activity;
+
+    if  ( ALT_ACT_MEASURE )
+    {
+        int use_dc_pred = (mb_col || mb_row) && (!mb_col || !mb_row);
+
+        // Or use and alternative.
+        mb_activity = alt_activity_measure( cpi, x, use_dc_pred );
+    }
+    else
+    {
+        // Original activity measure from Tim T's code.
+        mb_activity = tt_activity_measure( cpi, x );
+    }
+
+    if ( mb_activity < VP8_ACTIVITY_AVG_MIN )
+        mb_activity = VP8_ACTIVITY_AVG_MIN;
+
+    return mb_activity;
+}
+
+// Calculate an "average" mb activity value for the frame
+#define ACT_MEDIAN 0
+static void calc_av_activity( VP8_COMP *cpi, int64_t activity_sum )
+{
+#if ACT_MEDIAN
+    // Find median: Simple n^2 algorithm for experimentation
+    {
+        unsigned int median;
+        unsigned int i,j;
+        unsigned int * sortlist;
+        unsigned int tmp;
+
+        // Create a list to sort to
+        CHECK_MEM_ERROR(sortlist,
+                        vpx_calloc(sizeof(unsigned int),
+                        cpi->common.MBs));
+
+        // Copy map to sort list
+        vpx_memcpy( sortlist, cpi->mb_activity_map,
+                    sizeof(unsigned int) * cpi->common.MBs );
+
+
+        // Ripple each value down to its correct position
+        for ( i = 1; i < cpi->common.MBs; i ++ )
+        {
+            for ( j = i; j > 0; j -- )
+            {
+                if ( sortlist[j] < sortlist[j-1] )
+                {
+                    // Swap values
+                    tmp = sortlist[j-1];
+                    sortlist[j-1] = sortlist[j];
+                    sortlist[j] = tmp;
+                }
+                else
+                    break;
+            }
+        }
+
+        // Even number MBs so estimate median as mean of two either side.
+        median = ( 1 + sortlist[cpi->common.MBs >> 1] +
+                   sortlist[(cpi->common.MBs >> 1) + 1] ) >> 1;
+
+        cpi->activity_avg = median;
+
+        vpx_free(sortlist);
+    }
+#else
+    // Simple mean for now
+    cpi->activity_avg = (unsigned int)(activity_sum/cpi->common.MBs);
+#endif
+
+    if (cpi->activity_avg < VP8_ACTIVITY_AVG_MIN)
+        cpi->activity_avg = VP8_ACTIVITY_AVG_MIN;
+
+    // Experimental code: return fixed value normalized for several clips
+    if  ( ALT_ACT_MEASURE )
+        cpi->activity_avg = 100000;
+}
+
+#define USE_ACT_INDEX   0
+#define OUTPUT_NORM_ACT_STATS   0
+
+#if USE_ACT_INDEX
+// Calculate and activity index for each mb
+static void calc_activity_index( VP8_COMP *cpi, MACROBLOCK *x )
+{
+    VP8_COMMON *const cm = & cpi->common;
+    int mb_row, mb_col;
+
+    int64_t act;
+    int64_t a;
+    int64_t b;
+
+#if OUTPUT_NORM_ACT_STATS
+    FILE *f = fopen("norm_act.stt", "a");
+    fprintf(f, "\n%12d\n", cpi->activity_avg );
+#endif
+
+    // Reset pointers to start of activity map
+    x->mb_activity_ptr = cpi->mb_activity_map;
+
+    // Calculate normalized mb activity number.
+    for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
+    {
+        // for each macroblock col in image
+        for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+        {
+            // Read activity from the map
+            act = *(x->mb_activity_ptr);
+
+            // Calculate a normalized activity number
+            a = act + 4*cpi->activity_avg;
+            b = 4*act + cpi->activity_avg;
+
+            if ( b >= a )
+                *(x->activity_ptr) = (int)((b + (a>>1))/a) - 1;
+            else
+                *(x->activity_ptr) = 1 - (int)((a + (b>>1))/b);
+
+#if OUTPUT_NORM_ACT_STATS
+            fprintf(f, " %6d", *(x->mb_activity_ptr));
+#endif
+            // Increment activity map pointers
+            x->mb_activity_ptr++;
+        }
+
+#if OUTPUT_NORM_ACT_STATS
+        fprintf(f, "\n");
+#endif
+
+    }
+
+#if OUTPUT_NORM_ACT_STATS
+    fclose(f);
+#endif
+
+}
+#endif
+
+// Loop through all MBs. Note activity of each, average activity and
+// calculate a normalized activity for each
+static void build_activity_map( VP8_COMP *cpi )
+{
+    MACROBLOCK *const x = & cpi->mb;
+    MACROBLOCKD *xd = &x->e_mbd;
+    VP8_COMMON *const cm = & cpi->common;
+
+#if ALT_ACT_MEASURE
+    YV12_BUFFER_CONFIG *new_yv12 = &cm->yv12_fb[cm->new_fb_idx];
+    int recon_yoffset;
+    int recon_y_stride = new_yv12->y_stride;
+#endif
+
+    int mb_row, mb_col;
+    unsigned int mb_activity;
+    int64_t activity_sum = 0;
+
+    // for each macroblock row in image
+    for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
+    {
+#if ALT_ACT_MEASURE
+        // reset above block coeffs
+        xd->up_available = (mb_row != 0);
+        recon_yoffset = (mb_row * recon_y_stride * 16);
+#endif
+        // for each macroblock col in image
+        for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+        {
+#if ALT_ACT_MEASURE
+            xd->dst.y_buffer = new_yv12->y_buffer + recon_yoffset;
+            xd->left_available = (mb_col != 0);
+            recon_yoffset += 16;
+#endif
+            //Copy current mb to a buffer
+            vp8_copy_mem16x16(x->src.y_buffer, x->src.y_stride, x->thismb, 16);
+
+            // measure activity
+            mb_activity = mb_activity_measure( cpi, x, mb_row, mb_col );
+
+            // Keep frame sum
+            activity_sum += mb_activity;
+
+            // Store MB level activity details.
+            *x->mb_activity_ptr = mb_activity;
+
+            // Increment activity map pointer
+            x->mb_activity_ptr++;
+
+            // adjust to the next column of source macroblocks
+            x->src.y_buffer += 16;
+        }
+
+
+        // adjust to the next row of mbs
+        x->src.y_buffer += 16 * x->src.y_stride - 16 * cm->mb_cols;
+
+#if ALT_ACT_MEASURE
+        //extend the recon for intra prediction
+        vp8_extend_mb_row(new_yv12, xd->dst.y_buffer + 16,
+                          xd->dst.u_buffer + 8, xd->dst.v_buffer + 8);
+#endif
+
+    }
+
+    // Calculate an "average" MB activity
+    calc_av_activity(cpi, activity_sum);
+
+#if USE_ACT_INDEX
+    // Calculate an activity index number of each mb
+    calc_activity_index( cpi, x );
+#endif
+
+}
+
+// Macroblock activity masking
+void vp8_activity_masking(VP8_COMP *cpi, MACROBLOCK *x)
+{
+#if USE_ACT_INDEX
+    x->rdmult += *(x->mb_activity_ptr) * (x->rdmult >> 2);
+    x->errorperbit = x->rdmult * 100 /(110 * x->rddiv);
+    x->errorperbit += (x->errorperbit==0);
+#else
+    int64_t a;
+    int64_t b;
+    int64_t act = *(x->mb_activity_ptr);
+
+    // Apply the masking to the RD multiplier.
+    a = act + (2*cpi->activity_avg);
+    b = (2*act) + cpi->activity_avg;
+
+    x->rdmult = (unsigned int)(((int64_t)x->rdmult*b + (a>>1))/a);
+    x->errorperbit = x->rdmult * 100 /(110 * x->rddiv);
+    x->errorperbit += (x->errorperbit==0);
+#endif
+
+    // Activity based Zbin adjustment
+    adjust_act_zbin(cpi, x);
+}
+
+static
+void encode_mb_row(VP8_COMP *cpi,
+                   VP8_COMMON *cm,
+                   int mb_row,
+                   MACROBLOCK  *x,
+                   MACROBLOCKD *xd,
+                   TOKENEXTRA **tp,
+                   int *segment_counts,
+                   int *totalrate)
+{
+    int recon_yoffset, recon_uvoffset;
+    int mb_col;
+    int ref_fb_idx = cm->lst_fb_idx;
+    int dst_fb_idx = cm->new_fb_idx;
+    int recon_y_stride = cm->yv12_fb[ref_fb_idx].y_stride;
+    int recon_uv_stride = cm->yv12_fb[ref_fb_idx].uv_stride;
+    int map_index = (mb_row * cpi->common.mb_cols);
+
+#if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)
+    const int num_part = (1 << cm->multi_token_partition);
+    TOKENEXTRA * tp_start = cpi->tok;
+    vp8_writer *w;
+#endif
+
+#if CONFIG_MULTITHREAD
+    const int nsync = cpi->mt_sync_range;
+    const int rightmost_col = cm->mb_cols + nsync;
+    volatile const int *last_row_current_mb_col;
+    volatile int *current_mb_col = &cpi->mt_current_mb_col[mb_row];
+
+    if ((cpi->b_multi_threaded != 0) && (mb_row != 0))
+        last_row_current_mb_col = &cpi->mt_current_mb_col[mb_row - 1];
+    else
+        last_row_current_mb_col = &rightmost_col;
+#endif
+
+#if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)
+    if(num_part > 1)
+        w= &cpi->bc[1 + (mb_row % num_part)];
+    else
+        w = &cpi->bc[1];
+#endif
+
+    // reset above block coeffs
+    xd->above_context = cm->above_context;
+
+    xd->up_available = (mb_row != 0);
+    recon_yoffset = (mb_row * recon_y_stride * 16);
+    recon_uvoffset = (mb_row * recon_uv_stride * 8);
+
+    cpi->tplist[mb_row].start = *tp;
+    //printf("Main mb_row = %d\n", mb_row);
+
+    // Distance of Mb to the top & bottom edges, specified in 1/8th pel
+    // units as they are always compared to values that are in 1/8th pel units
+    xd->mb_to_top_edge = -((mb_row * 16) << 3);
+    xd->mb_to_bottom_edge = ((cm->mb_rows - 1 - mb_row) * 16) << 3;
+
+    // Set up limit values for vertical motion vector components
+    // to prevent them extending beyond the UMV borders
+    x->mv_row_min = -((mb_row * 16) + (VP8BORDERINPIXELS - 16));
+    x->mv_row_max = ((cm->mb_rows - 1 - mb_row) * 16)
+                        + (VP8BORDERINPIXELS - 16);
+
+    // Set the mb activity pointer to the start of the row.
+    x->mb_activity_ptr = &cpi->mb_activity_map[map_index];
+
+    // for each macroblock col in image
+    for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+    {
+
+#if  (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)
+        *tp = cpi->tok;
+#endif
+        // Distance of Mb to the left & right edges, specified in
+        // 1/8th pel units as they are always compared to values
+        // that are in 1/8th pel units
+        xd->mb_to_left_edge = -((mb_col * 16) << 3);
+        xd->mb_to_right_edge = ((cm->mb_cols - 1 - mb_col) * 16) << 3;
+
+        // Set up limit values for horizontal motion vector components
+        // to prevent them extending beyond the UMV borders
+        x->mv_col_min = -((mb_col * 16) + (VP8BORDERINPIXELS - 16));
+        x->mv_col_max = ((cm->mb_cols - 1 - mb_col) * 16)
+                            + (VP8BORDERINPIXELS - 16);
+
+        xd->dst.y_buffer = cm->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset;
+        xd->dst.u_buffer = cm->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset;
+        xd->dst.v_buffer = cm->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset;
+        xd->left_available = (mb_col != 0);
+
+        x->rddiv = cpi->RDDIV;
+        x->rdmult = cpi->RDMULT;
+
+        //Copy current mb to a buffer
+        vp8_copy_mem16x16(x->src.y_buffer, x->src.y_stride, x->thismb, 16);
+
+#if CONFIG_MULTITHREAD
+        if (cpi->b_multi_threaded != 0)
+        {
+            *current_mb_col = mb_col - 1; // set previous MB done
+
+            if ((mb_col & (nsync - 1)) == 0)
+            {
+                while (mb_col > (*last_row_current_mb_col - nsync))
+                {
+                    x86_pause_hint();
+                    thread_sleep(0);
+                }
+            }
+        }
+#endif
+
+        if(cpi->oxcf.tuning == VP8_TUNE_SSIM)
+            vp8_activity_masking(cpi, x);
+
+        // Is segmentation enabled
+        // MB level adjustment to quantizer
+        if (xd->segmentation_enabled)
+        {
+            // Code to set segment id in xd->mbmi.segment_id for current MB (with range checking)
+            if (cpi->segmentation_map[map_index+mb_col] <= 3)
+                xd->mode_info_context->mbmi.segment_id = cpi->segmentation_map[map_index+mb_col];
+            else
+                xd->mode_info_context->mbmi.segment_id = 0;
+
+            vp8cx_mb_init_quantizer(cpi, x, 1);
+        }
+        else
+            xd->mode_info_context->mbmi.segment_id = 0;         // Set to Segment 0 by default
+
+        x->active_ptr = cpi->active_map + map_index + mb_col;
+
+        if (cm->frame_type == KEY_FRAME)
+        {
+            *totalrate += vp8cx_encode_intra_macroblock(cpi, x, tp);
+#ifdef MODE_STATS
+            y_modes[xd->mbmi.mode] ++;
+#endif
+        }
+        else
+        {
+            *totalrate += vp8cx_encode_inter_macroblock(cpi, x, tp, recon_yoffset, recon_uvoffset, mb_row, mb_col);
+
+#ifdef MODE_STATS
+            inter_y_modes[xd->mbmi.mode] ++;
+
+            if (xd->mbmi.mode == SPLITMV)
+            {
+                int b;
+
+                for (b = 0; b < xd->mbmi.partition_count; b++)
+                {
+                    inter_b_modes[x->partition->bmi[b].mode] ++;
+                }
+            }
+
+#endif
+
+            // Count of last ref frame 0,0 usage
+            if ((xd->mode_info_context->mbmi.mode == ZEROMV) && (xd->mode_info_context->mbmi.ref_frame == LAST_FRAME))
+                cpi->inter_zz_count ++;
+
+            // Special case code for cyclic refresh
+            // If cyclic update enabled then copy xd->mbmi.segment_id; (which may have been updated based on mode
+            // during vp8cx_encode_inter_macroblock()) back into the global segmentation map
+            if ((cpi->current_layer == 0) &&
+                (cpi->cyclic_refresh_mode_enabled && xd->segmentation_enabled))
+            {
+                cpi->segmentation_map[map_index+mb_col] = xd->mode_info_context->mbmi.segment_id;
+
+                // If the block has been refreshed mark it as clean (the magnitude of the -ve influences how long it will be before we consider another refresh):
+                // Else if it was coded (last frame 0,0) and has not already been refreshed then mark it as a candidate for cleanup next time (marked 0)
+                // else mark it as dirty (1).
+                if (xd->mode_info_context->mbmi.segment_id)
+                    cpi->cyclic_refresh_map[map_index+mb_col] = -1;
+                else if ((xd->mode_info_context->mbmi.mode == ZEROMV) && (xd->mode_info_context->mbmi.ref_frame == LAST_FRAME))
+                {
+                    if (cpi->cyclic_refresh_map[map_index+mb_col] == 1)
+                        cpi->cyclic_refresh_map[map_index+mb_col] = 0;
+                }
+                else
+                    cpi->cyclic_refresh_map[map_index+mb_col] = 1;
+
+            }
+        }
+
+        cpi->tplist[mb_row].stop = *tp;
+
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+        /* pack tokens for this MB */
+        {
+            int tok_count = *tp - tp_start;
+            pack_tokens(w, tp_start, tok_count);
+        }
+#endif
+        // Increment pointer into gf usage flags structure.
+        x->gf_active_ptr++;
+
+        // Increment the activity mask pointers.
+        x->mb_activity_ptr++;
+
+        // adjust to the next column of macroblocks
+        x->src.y_buffer += 16;
+        x->src.u_buffer += 8;
+        x->src.v_buffer += 8;
+
+        recon_yoffset += 16;
+        recon_uvoffset += 8;
+
+        // Keep track of segment usage
+        segment_counts[xd->mode_info_context->mbmi.segment_id] ++;
+
+        // skip to next mb
+        xd->mode_info_context++;
+        x->partition_info++;
+        xd->above_context++;
+    }
+
+    //extend the recon for intra prediction
+    vp8_extend_mb_row( &cm->yv12_fb[dst_fb_idx],
+                        xd->dst.y_buffer + 16,
+                        xd->dst.u_buffer + 8,
+                        xd->dst.v_buffer + 8);
+
+#if CONFIG_MULTITHREAD
+    if (cpi->b_multi_threaded != 0)
+        *current_mb_col = rightmost_col;
+#endif
+
+    // this is to account for the border
+    xd->mode_info_context++;
+    x->partition_info++;
+}
+
+static void init_encode_frame_mb_context(VP8_COMP *cpi)
+{
+    MACROBLOCK *const x = & cpi->mb;
+    VP8_COMMON *const cm = & cpi->common;
+    MACROBLOCKD *const xd = & x->e_mbd;
+
+    // GF active flags data structure
+    x->gf_active_ptr = (signed char *)cpi->gf_active_flags;
+
+    // Activity map pointer
+    x->mb_activity_ptr = cpi->mb_activity_map;
+
+    x->act_zbin_adj = 0;
+
+    x->partition_info = x->pi;
+
+    xd->mode_info_context = cm->mi;
+    xd->mode_info_stride = cm->mode_info_stride;
+
+    xd->frame_type = cm->frame_type;
+
+    // reset intra mode contexts
+    if (cm->frame_type == KEY_FRAME)
+        vp8_init_mbmode_probs(cm);
+
+    // Copy data over into macro block data structures.
+    x->src = * cpi->Source;
+    xd->pre = cm->yv12_fb[cm->lst_fb_idx];
+    xd->dst = cm->yv12_fb[cm->new_fb_idx];
+
+    // set up frame for intra coded blocks
+    vp8_setup_intra_recon(&cm->yv12_fb[cm->new_fb_idx]);
+
+    vp8_build_block_offsets(x);
+
+    vp8_setup_block_dptrs(&x->e_mbd);
+
+    vp8_setup_block_ptrs(x);
+
+    xd->mode_info_context->mbmi.mode = DC_PRED;
+    xd->mode_info_context->mbmi.uv_mode = DC_PRED;
+
+    xd->left_context = &cm->left_context;
+
+    vp8_zero(cpi->count_mb_ref_frame_usage)
+    vp8_zero(cpi->ymode_count)
+    vp8_zero(cpi->uv_mode_count)
+
+    x->mvc = cm->fc.mvc;
+
+    vpx_memset(cm->above_context, 0,
+               sizeof(ENTROPY_CONTEXT_PLANES) * cm->mb_cols);
+
+    // Special case treatment when GF and ARF are not sensible options for reference
+    if (cpi->ref_frame_flags == VP8_LAST_FLAG)
+        vp8_calc_ref_frame_costs(x->ref_frame_cost,
+                                 cpi->prob_intra_coded,255,128);
+    else if ((cpi->oxcf.number_of_layers > 1) &&
+               (cpi->ref_frame_flags == VP8_GOLD_FLAG))
+        vp8_calc_ref_frame_costs(x->ref_frame_cost,
+                                 cpi->prob_intra_coded,1,255);
+    else if ((cpi->oxcf.number_of_layers > 1) &&
+                (cpi->ref_frame_flags == VP8_ALT_FLAG))
+        vp8_calc_ref_frame_costs(x->ref_frame_cost,
+                                 cpi->prob_intra_coded,1,1);
+    else
+        vp8_calc_ref_frame_costs(x->ref_frame_cost,
+                                 cpi->prob_intra_coded,
+                                 cpi->prob_last_coded,
+                                 cpi->prob_gf_coded);
+
+    xd->fullpixel_mask = 0xffffffff;
+    if(cm->full_pixel)
+        xd->fullpixel_mask = 0xfffffff8;
+}
+
+void vp8_encode_frame(VP8_COMP *cpi)
+{
+    int mb_row;
+    MACROBLOCK *const x = & cpi->mb;
+    VP8_COMMON *const cm = & cpi->common;
+    MACROBLOCKD *const xd = & x->e_mbd;
+    TOKENEXTRA *tp = cpi->tok;
+    int segment_counts[MAX_MB_SEGMENTS];
+    int totalrate;
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+    BOOL_CODER * bc = &cpi->bc[1]; // bc[0] is for control partition
+    const int num_part = (1 << cm->multi_token_partition);
+#endif
+
+    vpx_memset(segment_counts, 0, sizeof(segment_counts));
+    totalrate = 0;
+
+    if (cpi->compressor_speed == 2)
+    {
+        if (cpi->oxcf.cpu_used < 0)
+            cpi->Speed = -(cpi->oxcf.cpu_used);
+        else
+            vp8_auto_select_speed(cpi);
+    }
+
+    // Functions setup for all frame types so we can use MC in AltRef
+    if (cm->mcomp_filter_type == SIXTAP)
+    {
+        xd->subpixel_predict        = vp8_sixtap_predict4x4;
+        xd->subpixel_predict8x4     = vp8_sixtap_predict8x4;
+        xd->subpixel_predict8x8     = vp8_sixtap_predict8x8;
+        xd->subpixel_predict16x16   = vp8_sixtap_predict16x16;
+    }
+    else
+    {
+        xd->subpixel_predict        = vp8_bilinear_predict4x4;
+        xd->subpixel_predict8x4     = vp8_bilinear_predict8x4;
+        xd->subpixel_predict8x8     = vp8_bilinear_predict8x8;
+        xd->subpixel_predict16x16   = vp8_bilinear_predict16x16;
+    }
+
+    // Reset frame count of inter 0,0 motion vector usage.
+    cpi->inter_zz_count = 0;
+
+    cpi->prediction_error = 0;
+    cpi->intra_error = 0;
+    cpi->skip_true_count = 0;
+    cpi->tok_count = 0;
+
+#if 0
+    // Experimental code
+    cpi->frame_distortion = 0;
+    cpi->last_mb_distortion = 0;
+#endif
+
+    xd->mode_info_context = cm->mi;
+
+    vp8_zero(cpi->MVcount);
+
+    vp8_zero(cpi->coef_counts);
+
+    vp8cx_frame_init_quantizer(cpi);
+
+    vp8_initialize_rd_consts(cpi,
+                             vp8_dc_quant(cm->base_qindex, cm->y1dc_delta_q));
+
+    vp8cx_initialize_me_consts(cpi, cm->base_qindex);
+
+    if(cpi->oxcf.tuning == VP8_TUNE_SSIM)
+    {
+        // Initialize encode frame context.
+        init_encode_frame_mb_context(cpi);
+
+        // Build a frame level activity map
+        build_activity_map(cpi);
+    }
+
+    // re-init encode frame context.
+    init_encode_frame_mb_context(cpi);
+
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+    {
+        int i;
+        for(i = 0; i < num_part; i++)
+        {
+            vp8_start_encode(&bc[i], cpi->partition_d[i + 1],
+                    cpi->partition_d_end[i + 1]);
+            bc[i].error = &cm->error;
+        }
+    }
+
+#endif
+
+    {
+        struct vpx_usec_timer  emr_timer;
+        vpx_usec_timer_start(&emr_timer);
+
+#if CONFIG_MULTITHREAD
+        if (cpi->b_multi_threaded)
+        {
+            int i;
+
+            vp8cx_init_mbrthread_data(cpi, x, cpi->mb_row_ei, 1,  cpi->encoding_thread_count);
+
+            for (i = 0; i < cm->mb_rows; i++)
+                cpi->mt_current_mb_col[i] = -1;
+
+            for (i = 0; i < cpi->encoding_thread_count; i++)
+            {
+                sem_post(&cpi->h_event_start_encoding[i]);
+            }
+
+            for (mb_row = 0; mb_row < cm->mb_rows; mb_row += (cpi->encoding_thread_count + 1))
+            {
+                vp8_zero(cm->left_context)
+
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+                tp = cpi->tok;
+#else
+                tp = cpi->tok + mb_row * (cm->mb_cols * 16 * 24);
+#endif
+
+                encode_mb_row(cpi, cm, mb_row, x, xd, &tp, segment_counts, &totalrate);
+
+                // adjust to the next row of mbs
+                x->src.y_buffer += 16 * x->src.y_stride * (cpi->encoding_thread_count + 1) - 16 * cm->mb_cols;
+                x->src.u_buffer +=  8 * x->src.uv_stride * (cpi->encoding_thread_count + 1) - 8 * cm->mb_cols;
+                x->src.v_buffer +=  8 * x->src.uv_stride * (cpi->encoding_thread_count + 1) - 8 * cm->mb_cols;
+
+                xd->mode_info_context += xd->mode_info_stride * cpi->encoding_thread_count;
+                x->partition_info  += xd->mode_info_stride * cpi->encoding_thread_count;
+                x->gf_active_ptr   += cm->mb_cols * cpi->encoding_thread_count;
+
+                if(mb_row == cm->mb_rows - 1)
+                {
+                    sem_post(&cpi->h_event_end_encoding); /* signal frame encoding end */
+                }
+            }
+
+            sem_wait(&cpi->h_event_end_encoding); /* wait for other threads to finish */
+
+            for (mb_row = 0; mb_row < cm->mb_rows; mb_row ++)
+            {
+                cpi->tok_count += cpi->tplist[mb_row].stop - cpi->tplist[mb_row].start;
+            }
+
+            if (xd->segmentation_enabled)
+            {
+                int i, j;
+
+                if (xd->segmentation_enabled)
+                {
+
+                    for (i = 0; i < cpi->encoding_thread_count; i++)
+                    {
+                        for (j = 0; j < 4; j++)
+                            segment_counts[j] += cpi->mb_row_ei[i].segment_counts[j];
+                    }
+                }
+            }
+
+            for (i = 0; i < cpi->encoding_thread_count; i++)
+            {
+                totalrate += cpi->mb_row_ei[i].totalrate;
+            }
+
+        }
+        else
+#endif
+        {
+            // for each macroblock row in image
+            for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
+            {
+                vp8_zero(cm->left_context)
+
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+                tp = cpi->tok;
+#endif
+
+                encode_mb_row(cpi, cm, mb_row, x, xd, &tp, segment_counts, &totalrate);
+
+                // adjust to the next row of mbs
+                x->src.y_buffer += 16 * x->src.y_stride - 16 * cm->mb_cols;
+                x->src.u_buffer += 8 * x->src.uv_stride - 8 * cm->mb_cols;
+                x->src.v_buffer += 8 * x->src.uv_stride - 8 * cm->mb_cols;
+            }
+
+            cpi->tok_count = tp - cpi->tok;
+        }
+
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+        {
+            int i;
+            for(i = 0; i < num_part; i++)
+            {
+                vp8_stop_encode(&bc[i]);
+                cpi->partition_sz[i+1] = bc[i].pos;
+            }
+        }
+#endif
+
+        vpx_usec_timer_mark(&emr_timer);
+        cpi->time_encode_mb_row += vpx_usec_timer_elapsed(&emr_timer);
+    }
+
+
+    // Work out the segment probabilities if segmentation is enabled
+    if (xd->segmentation_enabled)
+    {
+        int tot_count;
+        int i;
+
+        // Set to defaults
+        vpx_memset(xd->mb_segment_tree_probs, 255 , sizeof(xd->mb_segment_tree_probs));
+
+        tot_count = segment_counts[0] + segment_counts[1] + segment_counts[2] + segment_counts[3];
+
+        if (tot_count)
+        {
+            xd->mb_segment_tree_probs[0] = ((segment_counts[0] + segment_counts[1]) * 255) / tot_count;
+
+            tot_count = segment_counts[0] + segment_counts[1];
+
+            if (tot_count > 0)
+            {
+                xd->mb_segment_tree_probs[1] = (segment_counts[0] * 255) / tot_count;
+            }
+
+            tot_count = segment_counts[2] + segment_counts[3];
+
+            if (tot_count > 0)
+                xd->mb_segment_tree_probs[2] = (segment_counts[2] * 255) / tot_count;
+
+            // Zero probabilities not allowed
+            for (i = 0; i < MB_FEATURE_TREE_PROBS; i ++)
+            {
+                if (xd->mb_segment_tree_probs[i] == 0)
+                    xd->mb_segment_tree_probs[i] = 1;
+            }
+        }
+    }
+
+    // 256 rate units to the bit
+    cpi->projected_frame_size = totalrate >> 8;   // projected_frame_size in units of BYTES
+
+    // Make a note of the percentage MBs coded Intra.
+    if (cm->frame_type == KEY_FRAME)
+    {
+        cpi->this_frame_percent_intra = 100;
+    }
+    else
+    {
+        int tot_modes;
+
+        tot_modes = cpi->count_mb_ref_frame_usage[INTRA_FRAME]
+                    + cpi->count_mb_ref_frame_usage[LAST_FRAME]
+                    + cpi->count_mb_ref_frame_usage[GOLDEN_FRAME]
+                    + cpi->count_mb_ref_frame_usage[ALTREF_FRAME];
+
+        if (tot_modes)
+            cpi->this_frame_percent_intra = cpi->count_mb_ref_frame_usage[INTRA_FRAME] * 100 / tot_modes;
+
+    }
+
+#if 0
+    {
+        int cnt = 0;
+        int flag[2] = {0, 0};
+
+        for (cnt = 0; cnt < MVPcount; cnt++)
+        {
+            if (cm->fc.pre_mvc[0][cnt] != cm->fc.mvc[0][cnt])
+            {
+                flag[0] = 1;
+                vpx_memcpy(cm->fc.pre_mvc[0], cm->fc.mvc[0], MVPcount);
+                break;
+            }
+        }
+
+        for (cnt = 0; cnt < MVPcount; cnt++)
+        {
+            if (cm->fc.pre_mvc[1][cnt] != cm->fc.mvc[1][cnt])
+            {
+                flag[1] = 1;
+                vpx_memcpy(cm->fc.pre_mvc[1], cm->fc.mvc[1], MVPcount);
+                break;
+            }
+        }
+
+        if (flag[0] || flag[1])
+            vp8_build_component_cost_table(cpi->mb.mvcost, (const MV_CONTEXT *) cm->fc.mvc, flag);
+    }
+#endif
+
+#if ! CONFIG_REALTIME_ONLY
+    // Adjust the projected reference frame usage probability numbers to reflect
+    // what we have just seen. This may be useful when we make multiple iterations
+    // of the recode loop rather than continuing to use values from the previous frame.
+    if ((cm->frame_type != KEY_FRAME) && ((cpi->oxcf.number_of_layers > 1) ||
+        (!cm->refresh_alt_ref_frame && !cm->refresh_golden_frame)))
+    {
+      vp8_convert_rfct_to_prob(cpi);
+    }
+#endif
+}
+void vp8_setup_block_ptrs(MACROBLOCK *x)
+{
+    int r, c;
+    int i;
+
+    for (r = 0; r < 4; r++)
+    {
+        for (c = 0; c < 4; c++)
+        {
+            x->block[r*4+c].src_diff = x->src_diff + r * 4 * 16 + c * 4;
+        }
+    }
+
+    for (r = 0; r < 2; r++)
+    {
+        for (c = 0; c < 2; c++)
+        {
+            x->block[16 + r*2+c].src_diff = x->src_diff + 256 + r * 4 * 8 + c * 4;
+        }
+    }
+
+
+    for (r = 0; r < 2; r++)
+    {
+        for (c = 0; c < 2; c++)
+        {
+            x->block[20 + r*2+c].src_diff = x->src_diff + 320 + r * 4 * 8 + c * 4;
+        }
+    }
+
+    x->block[24].src_diff = x->src_diff + 384;
+
+
+    for (i = 0; i < 25; i++)
+    {
+        x->block[i].coeff = x->coeff + i * 16;
+    }
+}
+
+void vp8_build_block_offsets(MACROBLOCK *x)
+{
+    int block = 0;
+    int br, bc;
+
+    vp8_build_block_doffsets(&x->e_mbd);
+
+    // y blocks
+    x->thismb_ptr = &x->thismb[0];
+    for (br = 0; br < 4; br++)
+    {
+        for (bc = 0; bc < 4; bc++)
+        {
+            BLOCK *this_block = &x->block[block];
+            //this_block->base_src = &x->src.y_buffer;
+            //this_block->src_stride = x->src.y_stride;
+            //this_block->src = 4 * br * this_block->src_stride + 4 * bc;
+            this_block->base_src = &x->thismb_ptr;
+            this_block->src_stride = 16;
+            this_block->src = 4 * br * 16 + 4 * bc;
+            ++block;
+        }
+    }
+
+    // u blocks
+    for (br = 0; br < 2; br++)
+    {
+        for (bc = 0; bc < 2; bc++)
+        {
+            BLOCK *this_block = &x->block[block];
+            this_block->base_src = &x->src.u_buffer;
+            this_block->src_stride = x->src.uv_stride;
+            this_block->src = 4 * br * this_block->src_stride + 4 * bc;
+            ++block;
+        }
+    }
+
+    // v blocks
+    for (br = 0; br < 2; br++)
+    {
+        for (bc = 0; bc < 2; bc++)
+        {
+            BLOCK *this_block = &x->block[block];
+            this_block->base_src = &x->src.v_buffer;
+            this_block->src_stride = x->src.uv_stride;
+            this_block->src = 4 * br * this_block->src_stride + 4 * bc;
+            ++block;
+        }
+    }
+}
+
+static void sum_intra_stats(VP8_COMP *cpi, MACROBLOCK *x)
+{
+    const MACROBLOCKD *xd = & x->e_mbd;
+    const MB_PREDICTION_MODE m = xd->mode_info_context->mbmi.mode;
+    const MB_PREDICTION_MODE uvm = xd->mode_info_context->mbmi.uv_mode;
+
+#ifdef MODE_STATS
+    const int is_key = cpi->common.frame_type == KEY_FRAME;
+
+    ++ (is_key ? uv_modes : inter_uv_modes)[uvm];
+
+    if (m == B_PRED)
+    {
+        unsigned int *const bct = is_key ? b_modes : inter_b_modes;
+
+        int b = 0;
+
+        do
+        {
+            ++ bct[xd->block[b].bmi.mode];
+        }
+        while (++b < 16);
+    }
+
+#endif
+
+    ++cpi->ymode_count[m];
+    ++cpi->uv_mode_count[uvm];
+
+}
+
+// Experimental stub function to create a per MB zbin adjustment based on
+// some previously calculated measure of MB activity.
+static void adjust_act_zbin( VP8_COMP *cpi, MACROBLOCK *x )
+{
+#if USE_ACT_INDEX
+    x->act_zbin_adj = *(x->mb_activity_ptr);
+#else
+    int64_t a;
+    int64_t b;
+    int64_t act = *(x->mb_activity_ptr);
+
+    // Apply the masking to the RD multiplier.
+    a = act + 4*cpi->activity_avg;
+    b = 4*act + cpi->activity_avg;
+
+    if ( act > cpi->activity_avg )
+        x->act_zbin_adj = (int)(((int64_t)b + (a>>1))/a) - 1;
+    else
+        x->act_zbin_adj = 1 - (int)(((int64_t)a + (b>>1))/b);
+#endif
+}
+
+int vp8cx_encode_intra_macroblock(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t)
+{
+    MACROBLOCKD *xd = &x->e_mbd;
+    int rate;
+
+    if (cpi->sf.RD && cpi->compressor_speed != 2)
+        vp8_rd_pick_intra_mode(cpi, x, &rate);
+    else
+        vp8_pick_intra_mode(cpi, x, &rate);
+
+    if(cpi->oxcf.tuning == VP8_TUNE_SSIM)
+    {
+        adjust_act_zbin( cpi, x );
+        vp8_update_zbin_extra(cpi, x);
+    }
+
+    if (x->e_mbd.mode_info_context->mbmi.mode == B_PRED)
+        vp8_encode_intra4x4mby(x);
+    else
+        vp8_encode_intra16x16mby(x);
+
+    vp8_encode_intra16x16mbuv(x);
+
+    sum_intra_stats(cpi, x);
+
+    vp8_tokenize_mb(cpi, &x->e_mbd, t);
+
+    if (xd->mode_info_context->mbmi.mode != B_PRED)
+        vp8_inverse_transform_mby(xd);
+
+    vp8_dequant_idct_add_uv_block
+                    (xd->qcoeff+16*16, xd->dequant_uv,
+                     xd->dst.u_buffer, xd->dst.v_buffer,
+                     xd->dst.uv_stride, xd->eobs+16);
+    return rate;
+}
+#ifdef SPEEDSTATS
+extern int cnt_pm;
+#endif
+
+extern void vp8_fix_contexts(MACROBLOCKD *x);
+
+int vp8cx_encode_inter_macroblock
+(
+    VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t,
+    int recon_yoffset, int recon_uvoffset,
+    int mb_row, int mb_col
+)
+{
+    MACROBLOCKD *const xd = &x->e_mbd;
+    int intra_error = 0;
+    int rate;
+    int distortion;
+
+    x->skip = 0;
+
+    if (xd->segmentation_enabled)
+        x->encode_breakout = cpi->segment_encode_breakout[xd->mode_info_context->mbmi.segment_id];
+    else
+        x->encode_breakout = cpi->oxcf.encode_breakout;
+
+#if CONFIG_TEMPORAL_DENOISING
+    // Reset the best sse mode/mv for each macroblock.
+    x->e_mbd.best_sse_inter_mode = 0;
+    x->e_mbd.best_sse_mv.as_int = 0;
+    x->e_mbd.need_to_clamp_best_mvs = 0;
+#endif
+
+    if (cpi->sf.RD)
+    {
+        int zbin_mode_boost_enabled = cpi->zbin_mode_boost_enabled;
+
+        /* Are we using the fast quantizer for the mode selection? */
+        if(cpi->sf.use_fastquant_for_pick)
+        {
+            cpi->mb.quantize_b      = vp8_fast_quantize_b;
+            cpi->mb.quantize_b_pair = vp8_fast_quantize_b_pair;
+
+            /* the fast quantizer does not use zbin_extra, so
+             * do not recalculate */
+            cpi->zbin_mode_boost_enabled = 0;
+        }
+        vp8_rd_pick_inter_mode(cpi, x, recon_yoffset, recon_uvoffset, &rate,
+                               &distortion, &intra_error);
+
+        /* switch back to the regular quantizer for the encode */
+        if (cpi->sf.improved_quant)
+        {
+            cpi->mb.quantize_b      = vp8_regular_quantize_b;
+            cpi->mb.quantize_b_pair = vp8_regular_quantize_b_pair;
+        }
+
+        /* restore cpi->zbin_mode_boost_enabled */
+        cpi->zbin_mode_boost_enabled = zbin_mode_boost_enabled;
+
+    }
+    else
+    {
+        vp8_pick_inter_mode(cpi, x, recon_yoffset, recon_uvoffset, &rate,
+                            &distortion, &intra_error, mb_row, mb_col);
+    }
+
+    cpi->prediction_error += distortion;
+    cpi->intra_error += intra_error;
+
+    if(cpi->oxcf.tuning == VP8_TUNE_SSIM)
+    {
+        // Adjust the zbin based on this MB rate.
+        adjust_act_zbin( cpi, x );
+    }
+
+#if 0
+    // Experimental RD code
+    cpi->frame_distortion += distortion;
+    cpi->last_mb_distortion = distortion;
+#endif
+
+    // MB level adjutment to quantizer setup
+    if (xd->segmentation_enabled)
+    {
+        // If cyclic update enabled
+        if (cpi->current_layer == 0 && cpi->cyclic_refresh_mode_enabled)
+        {
+            // Clear segment_id back to 0 if not coded (last frame 0,0)
+            if ((xd->mode_info_context->mbmi.segment_id == 1) &&
+                ((xd->mode_info_context->mbmi.ref_frame != LAST_FRAME) || (xd->mode_info_context->mbmi.mode != ZEROMV)))
+            {
+                xd->mode_info_context->mbmi.segment_id = 0;
+
+                /* segment_id changed, so update */
+                vp8cx_mb_init_quantizer(cpi, x, 1);
+            }
+        }
+    }
+
+    {
+        // Experimental code. Special case for gf and arf zeromv modes.
+        // Increase zbin size to supress noise
+        cpi->zbin_mode_boost = 0;
+        if (cpi->zbin_mode_boost_enabled)
+        {
+            if ( xd->mode_info_context->mbmi.ref_frame != INTRA_FRAME )
+            {
+                if (xd->mode_info_context->mbmi.mode == ZEROMV)
+                {
+                    if (xd->mode_info_context->mbmi.ref_frame != LAST_FRAME)
+                        cpi->zbin_mode_boost = GF_ZEROMV_ZBIN_BOOST;
+                    else
+                        cpi->zbin_mode_boost = LF_ZEROMV_ZBIN_BOOST;
+                }
+                else if (xd->mode_info_context->mbmi.mode == SPLITMV)
+                    cpi->zbin_mode_boost = 0;
+                else
+                    cpi->zbin_mode_boost = MV_ZBIN_BOOST;
+            }
+        }
+
+        /* The fast quantizer doesn't use zbin_extra, only do so with
+         * the regular quantizer. */
+        if (cpi->sf.improved_quant)
+            vp8_update_zbin_extra(cpi, x);
+    }
+
+    cpi->count_mb_ref_frame_usage[xd->mode_info_context->mbmi.ref_frame] ++;
+
+    if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME)
+    {
+        vp8_encode_intra16x16mbuv(x);
+
+        if (xd->mode_info_context->mbmi.mode == B_PRED)
+        {
+            vp8_encode_intra4x4mby(x);
+        }
+        else
+        {
+            vp8_encode_intra16x16mby(x);
+        }
+
+        sum_intra_stats(cpi, x);
+    }
+    else
+    {
+        int ref_fb_idx;
+
+        if (xd->mode_info_context->mbmi.ref_frame == LAST_FRAME)
+            ref_fb_idx = cpi->common.lst_fb_idx;
+        else if (xd->mode_info_context->mbmi.ref_frame == GOLDEN_FRAME)
+            ref_fb_idx = cpi->common.gld_fb_idx;
+        else
+            ref_fb_idx = cpi->common.alt_fb_idx;
+
+        xd->pre.y_buffer = cpi->common.yv12_fb[ref_fb_idx].y_buffer + recon_yoffset;
+        xd->pre.u_buffer = cpi->common.yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset;
+        xd->pre.v_buffer = cpi->common.yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset;
+
+        if (!x->skip)
+        {
+            vp8_encode_inter16x16(x);
+        }
+        else
+            vp8_build_inter16x16_predictors_mb(xd, xd->dst.y_buffer,
+                                           xd->dst.u_buffer, xd->dst.v_buffer,
+                                           xd->dst.y_stride, xd->dst.uv_stride);
+
+    }
+
+    if (!x->skip)
+    {
+        vp8_tokenize_mb(cpi, xd, t);
+
+        if (xd->mode_info_context->mbmi.mode != B_PRED)
+            vp8_inverse_transform_mby(xd);
+
+        vp8_dequant_idct_add_uv_block
+                        (xd->qcoeff+16*16, xd->dequant_uv,
+                         xd->dst.u_buffer, xd->dst.v_buffer,
+                         xd->dst.uv_stride, xd->eobs+16);
+    }
+    else
+    {
+        /* always set mb_skip_coeff as it is needed by the loopfilter */
+        xd->mode_info_context->mbmi.mb_skip_coeff = 1;
+
+        if (cpi->common.mb_no_coeff_skip)
+        {
+            cpi->skip_true_count ++;
+            vp8_fix_contexts(xd);
+        }
+        else
+        {
+            vp8_stuff_mb(cpi, xd, t);
+        }
+    }
+
+    return rate;
+}
diff --git a/vp8/encoder/encodeframe.h b/vp8/encoder/encodeframe.h
new file mode 100644 (file)
index 0000000..4dd6ba0
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef ENCODEFRAME_H
+#define ENCODEFRAME_H
+extern void vp8_activity_masking(VP8_COMP *cpi, MACROBLOCK *x);
+
+extern void vp8_build_block_offsets(MACROBLOCK *x);
+
+extern void vp8_setup_block_ptrs(MACROBLOCK *x);
+
+extern void vp8_encode_frame(VP8_COMP *cpi);
+
+extern int vp8cx_encode_inter_macroblock(VP8_COMP *cpi, MACROBLOCK *x,
+        TOKENEXTRA **t,
+        int recon_yoffset, int recon_uvoffset,
+        int mb_row, int mb_col);
+
+extern int vp8cx_encode_intra_macroblock(VP8_COMP *cpi, MACROBLOCK *x,
+        TOKENEXTRA **t);
+#endif
diff --git a/vp8/encoder/encodeintra.c b/vp8/encoder/encodeintra.c
new file mode 100644 (file)
index 0000000..1f445b7
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "quantize.h"
+#include "vp8/common/reconintra4x4.h"
+#include "encodemb.h"
+#include "vp8/common/invtrans.h"
+#include "encodeintra.h"
+
+
+int vp8_encode_intra(VP8_COMP *cpi, MACROBLOCK *x, int use_dc_pred)
+{
+
+    int i;
+    int intra_pred_var = 0;
+    (void) cpi;
+
+    if (use_dc_pred)
+    {
+        x->e_mbd.mode_info_context->mbmi.mode = DC_PRED;
+        x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
+        x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
+
+        vp8_encode_intra16x16mby(x);
+
+        vp8_inverse_transform_mby(&x->e_mbd);
+    }
+    else
+    {
+        for (i = 0; i < 16; i++)
+        {
+            x->e_mbd.block[i].bmi.as_mode = B_DC_PRED;
+            vp8_encode_intra4x4block(x, i);
+        }
+    }
+
+    intra_pred_var = vp8_get_mb_ss(x->src_diff);
+
+    return intra_pred_var;
+}
+
+void vp8_encode_intra4x4block(MACROBLOCK *x, int ib)
+{
+    BLOCKD *b = &x->e_mbd.block[ib];
+    BLOCK *be = &x->block[ib];
+    int dst_stride = x->e_mbd.dst.y_stride;
+    unsigned char *base_dst = x->e_mbd.dst.y_buffer;
+
+    vp8_intra4x4_predict(base_dst + b->offset, dst_stride,
+                 b->bmi.as_mode, b->predictor, 16);
+
+    vp8_subtract_b(be, b, 16);
+
+    x->short_fdct4x4(be->src_diff, be->coeff, 32);
+
+    x->quantize_b(be, b);
+
+    if (*b->eob > 1)
+    {
+      vp8_short_idct4x4llm(b->dqcoeff,
+            b->predictor, 16, base_dst + b->offset, dst_stride);
+    }
+    else
+    {
+      vp8_dc_only_idct_add
+            (b->dqcoeff[0], b->predictor, 16, base_dst + b->offset,
+                dst_stride);
+    }
+}
+
+void vp8_encode_intra4x4mby(MACROBLOCK *mb)
+{
+    int i;
+
+    MACROBLOCKD *xd = &mb->e_mbd;
+    intra_prediction_down_copy(xd, xd->dst.y_buffer - xd->dst.y_stride + 16);
+
+    for (i = 0; i < 16; i++)
+        vp8_encode_intra4x4block(mb, i);
+    return;
+}
+
+void vp8_encode_intra16x16mby(MACROBLOCK *x)
+{
+    BLOCK *b = &x->block[0];
+    MACROBLOCKD *xd = &x->e_mbd;
+
+    vp8_build_intra_predictors_mby_s(xd,
+                                         xd->dst.y_buffer - xd->dst.y_stride,
+                                         xd->dst.y_buffer - 1,
+                                         xd->dst.y_stride,
+                                         xd->dst.y_buffer,
+                                         xd->dst.y_stride);
+
+    vp8_subtract_mby(x->src_diff, *(b->base_src),
+        b->src_stride, xd->dst.y_buffer, xd->dst.y_stride);
+
+    vp8_transform_intra_mby(x);
+
+    vp8_quantize_mby(x);
+
+    if (x->optimize)
+        vp8_optimize_mby(x);
+}
+
+void vp8_encode_intra16x16mbuv(MACROBLOCK *x)
+{
+    MACROBLOCKD *xd = &x->e_mbd;
+
+    vp8_build_intra_predictors_mbuv_s(xd, xd->dst.u_buffer - xd->dst.uv_stride,
+                                      xd->dst.v_buffer - xd->dst.uv_stride,
+                                      xd->dst.u_buffer - 1,
+                                      xd->dst.v_buffer - 1,
+                                      xd->dst.uv_stride,
+                                      xd->dst.u_buffer, xd->dst.v_buffer,
+                                      xd->dst.uv_stride);
+
+    vp8_subtract_mbuv(x->src_diff, x->src.u_buffer,
+        x->src.v_buffer, x->src.uv_stride, xd->dst.u_buffer,
+        xd->dst.v_buffer, xd->dst.uv_stride);
+
+    vp8_transform_mbuv(x);
+
+    vp8_quantize_mbuv(x);
+
+    if (x->optimize)
+        vp8_optimize_mbuv(x);
+}
diff --git a/vp8/encoder/encodeintra.h b/vp8/encoder/encodeintra.h
new file mode 100644 (file)
index 0000000..be2141f
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef _ENCODEINTRA_H_
+#define _ENCODEINTRA_H_
+#include "onyx_int.h"
+
+int vp8_encode_intra(VP8_COMP *cpi, MACROBLOCK *x, int use_dc_pred);
+void vp8_encode_intra16x16mby(MACROBLOCK *x);
+void vp8_encode_intra16x16mbuv(MACROBLOCK *x);
+void vp8_encode_intra4x4mby(MACROBLOCK *mb);
+void vp8_encode_intra4x4block(MACROBLOCK *x, int ib);
+#endif
diff --git a/vp8/encoder/encodemb.c b/vp8/encoder/encodemb.c
new file mode 100644 (file)
index 0000000..f89e4f7
--- /dev/null
@@ -0,0 +1,648 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "encodemb.h"
+#include "vp8/common/reconinter.h"
+#include "quantize.h"
+#include "tokenize.h"
+#include "vp8/common/invtrans.h"
+#include "vpx_mem/vpx_mem.h"
+#include "rdopt.h"
+
+void vp8_subtract_b_c(BLOCK *be, BLOCKD *bd, int pitch)
+{
+    unsigned char *src_ptr = (*(be->base_src) + be->src);
+    short *diff_ptr = be->src_diff;
+    unsigned char *pred_ptr = bd->predictor;
+    int src_stride = be->src_stride;
+
+    int r, c;
+
+    for (r = 0; r < 4; r++)
+    {
+        for (c = 0; c < 4; c++)
+        {
+            diff_ptr[c] = src_ptr[c] - pred_ptr[c];
+        }
+
+        diff_ptr += pitch;
+        pred_ptr += pitch;
+        src_ptr  += src_stride;
+    }
+}
+
+void vp8_subtract_mbuv_c(short *diff, unsigned char *usrc, unsigned char *vsrc,
+                         int src_stride, unsigned char *upred,
+                         unsigned char *vpred, int pred_stride)
+{
+    short *udiff = diff + 256;
+    short *vdiff = diff + 320;
+
+    int r, c;
+
+    for (r = 0; r < 8; r++)
+    {
+        for (c = 0; c < 8; c++)
+        {
+            udiff[c] = usrc[c] - upred[c];
+        }
+
+        udiff += 8;
+        upred += pred_stride;
+        usrc  += src_stride;
+    }
+
+    for (r = 0; r < 8; r++)
+    {
+        for (c = 0; c < 8; c++)
+        {
+            vdiff[c] = vsrc[c] - vpred[c];
+        }
+
+        vdiff += 8;
+        vpred += pred_stride;
+        vsrc  += src_stride;
+    }
+}
+
+void vp8_subtract_mby_c(short *diff, unsigned char *src, int src_stride,
+                        unsigned char *pred, int pred_stride)
+{
+    int r, c;
+
+    for (r = 0; r < 16; r++)
+    {
+        for (c = 0; c < 16; c++)
+        {
+            diff[c] = src[c] - pred[c];
+        }
+
+        diff += 16;
+        pred += pred_stride;
+        src  += src_stride;
+    }
+}
+
+static void vp8_subtract_mb(MACROBLOCK *x)
+{
+    BLOCK *b = &x->block[0];
+
+    vp8_subtract_mby(x->src_diff, *(b->base_src),
+        b->src_stride, x->e_mbd.dst.y_buffer, x->e_mbd.dst.y_stride);
+    vp8_subtract_mbuv(x->src_diff, x->src.u_buffer,
+        x->src.v_buffer, x->src.uv_stride, x->e_mbd.dst.u_buffer,
+        x->e_mbd.dst.v_buffer, x->e_mbd.dst.uv_stride);
+}
+
+static void build_dcblock(MACROBLOCK *x)
+{
+    short *src_diff_ptr = &x->src_diff[384];
+    int i;
+
+    for (i = 0; i < 16; i++)
+    {
+        src_diff_ptr[i] = x->coeff[i * 16];
+    }
+}
+
+void vp8_transform_mbuv(MACROBLOCK *x)
+{
+    int i;
+
+    for (i = 16; i < 24; i += 2)
+    {
+        x->short_fdct8x4(&x->block[i].src_diff[0],
+            &x->block[i].coeff[0], 16);
+    }
+}
+
+
+void vp8_transform_intra_mby(MACROBLOCK *x)
+{
+    int i;
+
+    for (i = 0; i < 16; i += 2)
+    {
+        x->short_fdct8x4(&x->block[i].src_diff[0],
+            &x->block[i].coeff[0], 32);
+    }
+
+    // build dc block from 16 y dc values
+    build_dcblock(x);
+
+    // do 2nd order transform on the dc block
+    x->short_walsh4x4(&x->block[24].src_diff[0],
+        &x->block[24].coeff[0], 8);
+
+}
+
+
+static void transform_mb(MACROBLOCK *x)
+{
+    int i;
+
+    for (i = 0; i < 16; i += 2)
+    {
+        x->short_fdct8x4(&x->block[i].src_diff[0],
+            &x->block[i].coeff[0], 32);
+    }
+
+    // build dc block from 16 y dc values
+    if (x->e_mbd.mode_info_context->mbmi.mode != SPLITMV)
+        build_dcblock(x);
+
+    for (i = 16; i < 24; i += 2)
+    {
+        x->short_fdct8x4(&x->block[i].src_diff[0],
+            &x->block[i].coeff[0], 16);
+    }
+
+    // do 2nd order transform on the dc block
+    if (x->e_mbd.mode_info_context->mbmi.mode != SPLITMV)
+        x->short_walsh4x4(&x->block[24].src_diff[0],
+        &x->block[24].coeff[0], 8);
+
+}
+
+
+static void transform_mby(MACROBLOCK *x)
+{
+    int i;
+
+    for (i = 0; i < 16; i += 2)
+    {
+        x->short_fdct8x4(&x->block[i].src_diff[0],
+            &x->block[i].coeff[0], 32);
+    }
+
+    // build dc block from 16 y dc values
+    if (x->e_mbd.mode_info_context->mbmi.mode != SPLITMV)
+    {
+        build_dcblock(x);
+        x->short_walsh4x4(&x->block[24].src_diff[0],
+            &x->block[24].coeff[0], 8);
+    }
+}
+
+
+
+#define RDTRUNC(RM,DM,R,D) ( (128+(R)*(RM)) & 0xFF )
+
+typedef struct vp8_token_state vp8_token_state;
+
+struct vp8_token_state{
+  int           rate;
+  int           error;
+  signed char   next;
+  signed char   token;
+  short         qc;
+};
+
+// TODO: experiments to find optimal multiple numbers
+#define Y1_RD_MULT 4
+#define UV_RD_MULT 2
+#define Y2_RD_MULT 16
+
+static const int plane_rd_mult[4]=
+{
+    Y1_RD_MULT,
+    Y2_RD_MULT,
+    UV_RD_MULT,
+    Y1_RD_MULT
+};
+
+static void optimize_b(MACROBLOCK *mb, int ib, int type,
+                       ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l)
+{
+    BLOCK *b;
+    BLOCKD *d;
+    vp8_token_state tokens[17][2];
+    unsigned best_mask[2];
+    const short *dequant_ptr;
+    const short *coeff_ptr;
+    short *qcoeff_ptr;
+    short *dqcoeff_ptr;
+    int eob;
+    int i0;
+    int rc;
+    int x;
+    int sz = 0;
+    int next;
+    int rdmult;
+    int rddiv;
+    int final_eob;
+    int rd_cost0;
+    int rd_cost1;
+    int rate0;
+    int rate1;
+    int error0;
+    int error1;
+    int t0;
+    int t1;
+    int best;
+    int band;
+    int pt;
+    int i;
+    int err_mult = plane_rd_mult[type];
+
+    b = &mb->block[ib];
+    d = &mb->e_mbd.block[ib];
+
+    /* Enable this to test the effect of RDO as a replacement for the dynamic
+     *  zero bin instead of an augmentation of it.
+     */
+#if 0
+    vp8_strict_quantize_b(b, d);
+#endif
+
+    dequant_ptr = d->dequant;
+    coeff_ptr = b->coeff;
+    qcoeff_ptr = d->qcoeff;
+    dqcoeff_ptr = d->dqcoeff;
+    i0 = !type;
+    eob = *d->eob;
+
+    /* Now set up a Viterbi trellis to evaluate alternative roundings. */
+    rdmult = mb->rdmult * err_mult;
+    if(mb->e_mbd.mode_info_context->mbmi.ref_frame==INTRA_FRAME)
+        rdmult = (rdmult * 9)>>4;
+
+    rddiv = mb->rddiv;
+    best_mask[0] = best_mask[1] = 0;
+    /* Initialize the sentinel node of the trellis. */
+    tokens[eob][0].rate = 0;
+    tokens[eob][0].error = 0;
+    tokens[eob][0].next = 16;
+    tokens[eob][0].token = DCT_EOB_TOKEN;
+    tokens[eob][0].qc = 0;
+    *(tokens[eob] + 1) = *(tokens[eob] + 0);
+    next = eob;
+    for (i = eob; i-- > i0;)
+    {
+        int base_bits;
+        int d2;
+        int dx;
+
+        rc = vp8_default_zig_zag1d[i];
+        x = qcoeff_ptr[rc];
+        /* Only add a trellis state for non-zero coefficients. */
+        if (x)
+        {
+            int shortcut=0;
+            error0 = tokens[next][0].error;
+            error1 = tokens[next][1].error;
+            /* Evaluate the first possibility for this state. */
+            rate0 = tokens[next][0].rate;
+            rate1 = tokens[next][1].rate;
+            t0 = (vp8_dct_value_tokens_ptr + x)->Token;
+            /* Consider both possible successor states. */
+            if (next < 16)
+            {
+                band = vp8_coef_bands[i + 1];
+                pt = vp8_prev_token_class[t0];
+                rate0 +=
+                    mb->token_costs[type][band][pt][tokens[next][0].token];
+                rate1 +=
+                    mb->token_costs[type][band][pt][tokens[next][1].token];
+            }
+            rd_cost0 = RDCOST(rdmult, rddiv, rate0, error0);
+            rd_cost1 = RDCOST(rdmult, rddiv, rate1, error1);
+            if (rd_cost0 == rd_cost1)
+            {
+                rd_cost0 = RDTRUNC(rdmult, rddiv, rate0, error0);
+                rd_cost1 = RDTRUNC(rdmult, rddiv, rate1, error1);
+            }
+            /* And pick the best. */
+            best = rd_cost1 < rd_cost0;
+            base_bits = *(vp8_dct_value_cost_ptr + x);
+            dx = dqcoeff_ptr[rc] - coeff_ptr[rc];
+            d2 = dx*dx;
+            tokens[i][0].rate = base_bits + (best ? rate1 : rate0);
+            tokens[i][0].error = d2 + (best ? error1 : error0);
+            tokens[i][0].next = next;
+            tokens[i][0].token = t0;
+            tokens[i][0].qc = x;
+            best_mask[0] |= best << i;
+            /* Evaluate the second possibility for this state. */
+            rate0 = tokens[next][0].rate;
+            rate1 = tokens[next][1].rate;
+
+            if((abs(x)*dequant_ptr[rc]>abs(coeff_ptr[rc])) &&
+               (abs(x)*dequant_ptr[rc]<abs(coeff_ptr[rc])+dequant_ptr[rc]))
+                shortcut = 1;
+            else
+                shortcut = 0;
+
+            if(shortcut)
+            {
+                sz = -(x < 0);
+                x -= 2*sz + 1;
+            }
+
+            /* Consider both possible successor states. */
+            if (!x)
+            {
+                /* If we reduced this coefficient to zero, check to see if
+                 *  we need to move the EOB back here.
+                 */
+                t0 = tokens[next][0].token == DCT_EOB_TOKEN ?
+                    DCT_EOB_TOKEN : ZERO_TOKEN;
+                t1 = tokens[next][1].token == DCT_EOB_TOKEN ?
+                    DCT_EOB_TOKEN : ZERO_TOKEN;
+            }
+            else
+            {
+                t0=t1 = (vp8_dct_value_tokens_ptr + x)->Token;
+            }
+            if (next < 16)
+            {
+                band = vp8_coef_bands[i + 1];
+                if(t0!=DCT_EOB_TOKEN)
+                {
+                    pt = vp8_prev_token_class[t0];
+                    rate0 += mb->token_costs[type][band][pt][
+                        tokens[next][0].token];
+                }
+                if(t1!=DCT_EOB_TOKEN)
+                {
+                    pt = vp8_prev_token_class[t1];
+                    rate1 += mb->token_costs[type][band][pt][
+                        tokens[next][1].token];
+                }
+            }
+
+            rd_cost0 = RDCOST(rdmult, rddiv, rate0, error0);
+            rd_cost1 = RDCOST(rdmult, rddiv, rate1, error1);
+            if (rd_cost0 == rd_cost1)
+            {
+                rd_cost0 = RDTRUNC(rdmult, rddiv, rate0, error0);
+                rd_cost1 = RDTRUNC(rdmult, rddiv, rate1, error1);
+            }
+            /* And pick the best. */
+            best = rd_cost1 < rd_cost0;
+            base_bits = *(vp8_dct_value_cost_ptr + x);
+
+            if(shortcut)
+            {
+                dx -= (dequant_ptr[rc] + sz) ^ sz;
+                d2 = dx*dx;
+            }
+            tokens[i][1].rate = base_bits + (best ? rate1 : rate0);
+            tokens[i][1].error = d2 + (best ? error1 : error0);
+            tokens[i][1].next = next;
+            tokens[i][1].token =best?t1:t0;
+            tokens[i][1].qc = x;
+            best_mask[1] |= best << i;
+            /* Finally, make this the new head of the trellis. */
+            next = i;
+        }
+        /* There's no choice to make for a zero coefficient, so we don't
+         *  add a new trellis node, but we do need to update the costs.
+         */
+        else
+        {
+            band = vp8_coef_bands[i + 1];
+            t0 = tokens[next][0].token;
+            t1 = tokens[next][1].token;
+            /* Update the cost of each path if we're past the EOB token. */
+            if (t0 != DCT_EOB_TOKEN)
+            {
+                tokens[next][0].rate += mb->token_costs[type][band][0][t0];
+                tokens[next][0].token = ZERO_TOKEN;
+            }
+            if (t1 != DCT_EOB_TOKEN)
+            {
+                tokens[next][1].rate += mb->token_costs[type][band][0][t1];
+                tokens[next][1].token = ZERO_TOKEN;
+            }
+            /* Don't update next, because we didn't add a new node. */
+        }
+    }
+
+    /* Now pick the best path through the whole trellis. */
+    band = vp8_coef_bands[i + 1];
+    VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+    rate0 = tokens[next][0].rate;
+    rate1 = tokens[next][1].rate;
+    error0 = tokens[next][0].error;
+    error1 = tokens[next][1].error;
+    t0 = tokens[next][0].token;
+    t1 = tokens[next][1].token;
+    rate0 += mb->token_costs[type][band][pt][t0];
+    rate1 += mb->token_costs[type][band][pt][t1];
+    rd_cost0 = RDCOST(rdmult, rddiv, rate0, error0);
+    rd_cost1 = RDCOST(rdmult, rddiv, rate1, error1);
+    if (rd_cost0 == rd_cost1)
+    {
+        rd_cost0 = RDTRUNC(rdmult, rddiv, rate0, error0);
+        rd_cost1 = RDTRUNC(rdmult, rddiv, rate1, error1);
+    }
+    best = rd_cost1 < rd_cost0;
+    final_eob = i0 - 1;
+    for (i = next; i < eob; i = next)
+    {
+        x = tokens[i][best].qc;
+        if (x)
+            final_eob = i;
+        rc = vp8_default_zig_zag1d[i];
+        qcoeff_ptr[rc] = x;
+        dqcoeff_ptr[rc] = x * dequant_ptr[rc];
+        next = tokens[i][best].next;
+        best = (best_mask[best] >> i) & 1;
+    }
+    final_eob++;
+
+    *a = *l = (final_eob != !type);
+    *d->eob = (char)final_eob;
+}
+static void check_reset_2nd_coeffs(MACROBLOCKD *x, int type,
+                                   ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l)
+{
+    int sum=0;
+    int i;
+    BLOCKD *bd = &x->block[24];
+
+    if(bd->dequant[0]>=35 && bd->dequant[1]>=35)
+        return;
+
+    for(i=0;i<(*bd->eob);i++)
+    {
+        int coef = bd->dqcoeff[vp8_default_zig_zag1d[i]];
+        sum+= (coef>=0)?coef:-coef;
+        if(sum>=35)
+            return;
+    }
+    /**************************************************************************
+    our inverse hadamard transform effectively is weighted sum of all 16 inputs
+    with weight either 1 or -1. It has a last stage scaling of (sum+3)>>3. And
+    dc only idct is (dc+4)>>3. So if all the sums are between -35 and 29, the
+    output after inverse wht and idct will be all zero. A sum of absolute value
+    smaller than 35 guarantees all 16 different (+1/-1) weighted sums in wht
+    fall between -35 and +35.
+    **************************************************************************/
+    if(sum < 35)
+    {
+        for(i=0;i<(*bd->eob);i++)
+        {
+            int rc = vp8_default_zig_zag1d[i];
+            bd->qcoeff[rc]=0;
+            bd->dqcoeff[rc]=0;
+        }
+        *bd->eob = 0;
+        *a = *l = (*bd->eob != !type);
+    }
+}
+
+static void optimize_mb(MACROBLOCK *x)
+{
+    int b;
+    int type;
+    int has_2nd_order;
+
+    ENTROPY_CONTEXT_PLANES t_above, t_left;
+    ENTROPY_CONTEXT *ta;
+    ENTROPY_CONTEXT *tl;
+
+    vpx_memcpy(&t_above, x->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
+    vpx_memcpy(&t_left, x->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
+
+    ta = (ENTROPY_CONTEXT *)&t_above;
+    tl = (ENTROPY_CONTEXT *)&t_left;
+
+    has_2nd_order = (x->e_mbd.mode_info_context->mbmi.mode != B_PRED
+        && x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
+    type = has_2nd_order ? PLANE_TYPE_Y_NO_DC : PLANE_TYPE_Y_WITH_DC;
+
+    for (b = 0; b < 16; b++)
+    {
+        optimize_b(x, b, type,
+            ta + vp8_block2above[b], tl + vp8_block2left[b]);
+    }
+
+    for (b = 16; b < 24; b++)
+    {
+        optimize_b(x, b, PLANE_TYPE_UV,
+            ta + vp8_block2above[b], tl + vp8_block2left[b]);
+    }
+
+    if (has_2nd_order)
+    {
+        b=24;
+        optimize_b(x, b, PLANE_TYPE_Y2,
+            ta + vp8_block2above[b], tl + vp8_block2left[b]);
+        check_reset_2nd_coeffs(&x->e_mbd, PLANE_TYPE_Y2,
+            ta + vp8_block2above[b], tl + vp8_block2left[b]);
+    }
+}
+
+
+void vp8_optimize_mby(MACROBLOCK *x)
+{
+    int b;
+    int type;
+    int has_2nd_order;
+
+    ENTROPY_CONTEXT_PLANES t_above, t_left;
+    ENTROPY_CONTEXT *ta;
+    ENTROPY_CONTEXT *tl;
+
+    if (!x->e_mbd.above_context)
+        return;
+
+    if (!x->e_mbd.left_context)
+        return;
+
+    vpx_memcpy(&t_above, x->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
+    vpx_memcpy(&t_left, x->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
+
+    ta = (ENTROPY_CONTEXT *)&t_above;
+    tl = (ENTROPY_CONTEXT *)&t_left;
+
+    has_2nd_order = (x->e_mbd.mode_info_context->mbmi.mode != B_PRED
+        && x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
+    type = has_2nd_order ? PLANE_TYPE_Y_NO_DC : PLANE_TYPE_Y_WITH_DC;
+
+    for (b = 0; b < 16; b++)
+    {
+        optimize_b(x, b, type,
+            ta + vp8_block2above[b], tl + vp8_block2left[b]);
+    }
+
+
+    if (has_2nd_order)
+    {
+        b=24;
+        optimize_b(x, b, PLANE_TYPE_Y2,
+            ta + vp8_block2above[b], tl + vp8_block2left[b]);
+        check_reset_2nd_coeffs(&x->e_mbd, PLANE_TYPE_Y2,
+            ta + vp8_block2above[b], tl + vp8_block2left[b]);
+    }
+}
+
+void vp8_optimize_mbuv(MACROBLOCK *x)
+{
+    int b;
+    ENTROPY_CONTEXT_PLANES t_above, t_left;
+    ENTROPY_CONTEXT *ta;
+    ENTROPY_CONTEXT *tl;
+
+    if (!x->e_mbd.above_context)
+        return;
+
+    if (!x->e_mbd.left_context)
+        return;
+
+    vpx_memcpy(&t_above, x->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
+    vpx_memcpy(&t_left, x->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
+
+    ta = (ENTROPY_CONTEXT *)&t_above;
+    tl = (ENTROPY_CONTEXT *)&t_left;
+
+    for (b = 16; b < 24; b++)
+    {
+        optimize_b(x, b, PLANE_TYPE_UV,
+            ta + vp8_block2above[b], tl + vp8_block2left[b]);
+    }
+}
+
+void vp8_encode_inter16x16(MACROBLOCK *x)
+{
+    vp8_build_inter_predictors_mb(&x->e_mbd);
+
+    vp8_subtract_mb(x);
+
+    transform_mb(x);
+
+    vp8_quantize_mb(x);
+
+    if (x->optimize)
+        optimize_mb(x);
+}
+
+/* this funciton is used by first pass only */
+void vp8_encode_inter16x16y(MACROBLOCK *x)
+{
+    BLOCK *b = &x->block[0];
+
+    vp8_build_inter16x16_predictors_mby(&x->e_mbd, x->e_mbd.dst.y_buffer,
+                                        x->e_mbd.dst.y_stride);
+
+    vp8_subtract_mby(x->src_diff, *(b->base_src),
+        b->src_stride, x->e_mbd.dst.y_buffer, x->e_mbd.dst.y_stride);
+
+    transform_mby(x);
+
+    vp8_quantize_mby(x);
+
+    vp8_inverse_transform_mby(&x->e_mbd);
+}
diff --git a/vp8/encoder/encodemb.h b/vp8/encoder/encodemb.h
new file mode 100644 (file)
index 0000000..6badf7d
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_ENCODEMB_H
+#define __INC_ENCODEMB_H
+
+#include "onyx_int.h"
+void vp8_encode_inter16x16(MACROBLOCK *x);
+
+void vp8_build_dcblock(MACROBLOCK *b);
+void vp8_transform_mb(MACROBLOCK *mb);
+void vp8_transform_mbuv(MACROBLOCK *x);
+void vp8_transform_intra_mby(MACROBLOCK *x);
+
+void vp8_optimize_mby(MACROBLOCK *x);
+void vp8_optimize_mbuv(MACROBLOCK *x);
+void vp8_encode_inter16x16y(MACROBLOCK *x);
+#endif
diff --git a/vp8/encoder/encodemv.c b/vp8/encoder/encodemv.c
new file mode 100644 (file)
index 0000000..0145f6d
--- /dev/null
@@ -0,0 +1,417 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vp8/common/common.h"
+#include "encodemv.h"
+#include "vp8/common/entropymode.h"
+#include "vp8/common/systemdependent.h"
+
+#include <math.h>
+
+#ifdef ENTROPY_STATS
+extern unsigned int active_section;
+#endif
+
+static void encode_mvcomponent(
+    vp8_writer *const w,
+    const int v,
+    const struct mv_context *mvc
+)
+{
+    const vp8_prob *p = mvc->prob;
+    const int x = v < 0 ? -v : v;
+
+    if (x < mvnum_short)     // Small
+    {
+        vp8_write(w, 0, p [mvpis_short]);
+        vp8_treed_write(w, vp8_small_mvtree, p + MVPshort, x, 3);
+
+        if (!x)
+            return;         // no sign bit
+    }
+    else                    // Large
+    {
+        int i = 0;
+
+        vp8_write(w, 1, p [mvpis_short]);
+
+        do
+            vp8_write(w, (x >> i) & 1, p [MVPbits + i]);
+
+        while (++i < 3);
+
+        i = mvlong_width - 1;  /* Skip bit 3, which is sometimes implicit */
+
+        do
+            vp8_write(w, (x >> i) & 1, p [MVPbits + i]);
+
+        while (--i > 3);
+
+        if (x & 0xFFF0)
+            vp8_write(w, (x >> 3) & 1, p [MVPbits + 3]);
+    }
+
+    vp8_write(w, v < 0, p [MVPsign]);
+}
+#if 0
+static int max_mv_r = 0;
+static int max_mv_c = 0;
+#endif
+void vp8_encode_motion_vector(vp8_writer *w, const MV *mv, const MV_CONTEXT *mvc)
+{
+
+#if 0
+    {
+        if (abs(mv->row >> 1) > max_mv_r)
+        {
+            FILE *f = fopen("maxmv.stt", "a");
+            max_mv_r = abs(mv->row >> 1);
+            fprintf(f, "New Mv Row Max %6d\n", (mv->row >> 1));
+
+            if ((abs(mv->row) / 2) != max_mv_r)
+                fprintf(f, "MV Row conversion error %6d\n", abs(mv->row) / 2);
+
+            fclose(f);
+        }
+
+        if (abs(mv->col >> 1) > max_mv_c)
+        {
+            FILE *f = fopen("maxmv.stt", "a");
+            fprintf(f, "New Mv Col Max %6d\n", (mv->col >> 1));
+            max_mv_c = abs(mv->col >> 1);
+            fclose(f);
+        }
+    }
+#endif
+
+    encode_mvcomponent(w, mv->row >> 1, &mvc[0]);
+    encode_mvcomponent(w, mv->col >> 1, &mvc[1]);
+}
+
+
+static unsigned int cost_mvcomponent(const int v, const struct mv_context *mvc)
+{
+    const vp8_prob *p = mvc->prob;
+    const int x = v;   //v<0? -v:v;
+    unsigned int cost;
+
+    if (x < mvnum_short)
+    {
+        cost = vp8_cost_zero(p [mvpis_short])
+               + vp8_treed_cost(vp8_small_mvtree, p + MVPshort, x, 3);
+
+        if (!x)
+            return cost;
+    }
+    else
+    {
+        int i = 0;
+        cost = vp8_cost_one(p [mvpis_short]);
+
+        do
+            cost += vp8_cost_bit(p [MVPbits + i], (x >> i) & 1);
+
+        while (++i < 3);
+
+        i = mvlong_width - 1;  /* Skip bit 3, which is sometimes implicit */
+
+        do
+            cost += vp8_cost_bit(p [MVPbits + i], (x >> i) & 1);
+
+        while (--i > 3);
+
+        if (x & 0xFFF0)
+            cost += vp8_cost_bit(p [MVPbits + 3], (x >> 3) & 1);
+    }
+
+    return cost;   // + vp8_cost_bit( p [MVPsign], v < 0);
+}
+
+void vp8_build_component_cost_table(int *mvcost[2], const MV_CONTEXT *mvc, int mvc_flag[2])
+{
+    int i = 1;   //-mv_max;
+    unsigned int cost0 = 0;
+    unsigned int cost1 = 0;
+
+    vp8_clear_system_state();
+
+    i = 1;
+
+    if (mvc_flag[0])
+    {
+        mvcost [0] [0] = cost_mvcomponent(0, &mvc[0]);
+
+        do
+        {
+            //mvcost [0] [i] = cost_mvcomponent( i, &mvc[0]);
+            cost0 = cost_mvcomponent(i, &mvc[0]);
+
+            mvcost [0] [i] = cost0 + vp8_cost_zero(mvc[0].prob[MVPsign]);
+            mvcost [0] [-i] = cost0 + vp8_cost_one(mvc[0].prob[MVPsign]);
+        }
+        while (++i <= mv_max);
+    }
+
+    i = 1;
+
+    if (mvc_flag[1])
+    {
+        mvcost [1] [0] = cost_mvcomponent(0, &mvc[1]);
+
+        do
+        {
+            //mvcost [1] [i] = cost_mvcomponent( i, mvc[1]);
+            cost1 = cost_mvcomponent(i, &mvc[1]);
+
+            mvcost [1] [i] = cost1 + vp8_cost_zero(mvc[1].prob[MVPsign]);
+            mvcost [1] [-i] = cost1 + vp8_cost_one(mvc[1].prob[MVPsign]);
+        }
+        while (++i <= mv_max);
+    }
+}
+
+
+// Motion vector probability table update depends on benefit.
+// Small correction allows for the fact that an update to an MV probability
+// may have benefit in subsequent frames as well as the current one.
+
+#define MV_PROB_UPDATE_CORRECTION   -1
+
+
+static void calc_prob(vp8_prob *p, const unsigned int ct[2])
+{
+    const unsigned int tot = ct[0] + ct[1];
+
+    if (tot)
+    {
+        const vp8_prob x = ((ct[0] * 255) / tot) & -2;
+        *p = x ? x : 1;
+    }
+}
+
+static void update(
+    vp8_writer *const w,
+    const unsigned int ct[2],
+    vp8_prob *const cur_p,
+    const vp8_prob new_p,
+    const vp8_prob update_p,
+    int *updated
+)
+{
+    const int cur_b = vp8_cost_branch(ct, *cur_p);
+    const int new_b = vp8_cost_branch(ct, new_p);
+    const int cost = 7 + MV_PROB_UPDATE_CORRECTION + ((vp8_cost_one(update_p) - vp8_cost_zero(update_p) + 128) >> 8);
+
+    if (cur_b - new_b > cost)
+    {
+        *cur_p = new_p;
+        vp8_write(w, 1, update_p);
+        vp8_write_literal(w, new_p >> 1, 7);
+        *updated = 1;
+
+    }
+    else
+        vp8_write(w, 0, update_p);
+}
+
+static void write_component_probs(
+    vp8_writer *const w,
+    struct mv_context *cur_mvc,
+    const struct mv_context *default_mvc_,
+    const struct mv_context *update_mvc,
+    const unsigned int events [MVvals],
+    unsigned int rc,
+    int *updated
+)
+{
+    vp8_prob *Pcur = cur_mvc->prob;
+    const vp8_prob *default_mvc = default_mvc_->prob;
+    const vp8_prob *Pupdate = update_mvc->prob;
+    unsigned int is_short_ct[2], sign_ct[2];
+
+    unsigned int bit_ct [mvlong_width] [2];
+
+    unsigned int short_ct  [mvnum_short];
+    unsigned int short_bct [mvnum_short-1] [2];
+
+    vp8_prob Pnew [MVPcount];
+
+    (void) rc;
+    vp8_copy_array(Pnew, default_mvc, MVPcount);
+
+    vp8_zero(is_short_ct)
+    vp8_zero(sign_ct)
+    vp8_zero(bit_ct)
+    vp8_zero(short_ct)
+    vp8_zero(short_bct)
+
+
+    //j=0
+    {
+        const int c = events [mv_max];
+
+        is_short_ct [0] += c;     // Short vector
+        short_ct [0] += c;       // Magnitude distribution
+    }
+
+    //j: 1 ~ mv_max (1023)
+    {
+        int j = 1;
+
+        do
+        {
+            const int c1 = events [mv_max + j];  //positive
+            const int c2 = events [mv_max - j];  //negative
+            const int c  = c1 + c2;
+            int a = j;
+
+            sign_ct [0] += c1;
+            sign_ct [1] += c2;
+
+            if (a < mvnum_short)
+            {
+                is_short_ct [0] += c;     // Short vector
+                short_ct [a] += c;       // Magnitude distribution
+            }
+            else
+            {
+                int k = mvlong_width - 1;
+                is_short_ct [1] += c;     // Long vector
+
+                /*  bit 3 not always encoded. */
+                do
+                    bit_ct [k] [(a >> k) & 1] += c;
+
+                while (--k >= 0);
+            }
+        }
+        while (++j <= mv_max);
+    }
+
+    /*
+    {
+        int j = -mv_max;
+        do
+        {
+
+            const int c = events [mv_max + j];
+            int a = j;
+
+            if( j < 0)
+            {
+                sign_ct [1] += c;
+                a = -j;
+            }
+            else if( j)
+                sign_ct [0] += c;
+
+            if( a < mvnum_short)
+            {
+                is_short_ct [0] += c;     // Short vector
+                short_ct [a] += c;       // Magnitude distribution
+            }
+            else
+            {
+                int k = mvlong_width - 1;
+                is_short_ct [1] += c;     // Long vector
+
+                //  bit 3 not always encoded.
+
+                do
+                    bit_ct [k] [(a >> k) & 1] += c;
+                while( --k >= 0);
+            }
+        } while( ++j <= mv_max);
+    }
+    */
+
+    calc_prob(Pnew + mvpis_short, is_short_ct);
+
+    calc_prob(Pnew + MVPsign, sign_ct);
+
+    {
+        vp8_prob p [mvnum_short - 1];    /* actually only need branch ct */
+        int j = 0;
+
+        vp8_tree_probs_from_distribution(
+            8, vp8_small_mvencodings, vp8_small_mvtree,
+            p, short_bct, short_ct,
+            256, 1
+        );
+
+        do
+            calc_prob(Pnew + MVPshort + j, short_bct[j]);
+
+        while (++j < mvnum_short - 1);
+    }
+
+    {
+        int j = 0;
+
+        do
+            calc_prob(Pnew + MVPbits + j, bit_ct[j]);
+
+        while (++j < mvlong_width);
+    }
+
+    update(w, is_short_ct, Pcur + mvpis_short, Pnew[mvpis_short], *Pupdate++, updated);
+
+    update(w, sign_ct, Pcur + MVPsign, Pnew[MVPsign], *Pupdate++, updated);
+
+    {
+        const vp8_prob *const new_p = Pnew + MVPshort;
+        vp8_prob *const cur_p = Pcur + MVPshort;
+
+        int j = 0;
+
+        do
+
+            update(w, short_bct[j], cur_p + j, new_p[j], *Pupdate++, updated);
+
+        while (++j < mvnum_short - 1);
+    }
+
+    {
+        const vp8_prob *const new_p = Pnew + MVPbits;
+        vp8_prob *const cur_p = Pcur + MVPbits;
+
+        int j = 0;
+
+        do
+
+            update(w, bit_ct[j], cur_p + j, new_p[j], *Pupdate++, updated);
+
+        while (++j < mvlong_width);
+    }
+}
+
+void vp8_write_mvprobs(VP8_COMP *cpi)
+{
+    vp8_writer *const w  = cpi->bc;
+    MV_CONTEXT *mvc = cpi->common.fc.mvc;
+    int flags[2] = {0, 0};
+#ifdef ENTROPY_STATS
+    active_section = 4;
+#endif
+    write_component_probs(
+        w, &mvc[0], &vp8_default_mv_context[0], &vp8_mv_update_probs[0], cpi->MVcount[0], 0, &flags[0]
+    );
+    write_component_probs(
+        w, &mvc[1], &vp8_default_mv_context[1], &vp8_mv_update_probs[1], cpi->MVcount[1], 1, &flags[1]
+    );
+
+    if (flags[0] || flags[1])
+        vp8_build_component_cost_table(cpi->mb.mvcost, (const MV_CONTEXT *) cpi->common.fc.mvc, flags);
+
+#ifdef ENTROPY_STATS
+    active_section = 5;
+#endif
+}
diff --git a/vp8/encoder/encodemv.h b/vp8/encoder/encodemv.h
new file mode 100644 (file)
index 0000000..a6116c1
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_ENCODEMV_H
+#define __INC_ENCODEMV_H
+
+#include "onyx_int.h"
+
+void vp8_write_mvprobs(VP8_COMP *);
+void vp8_encode_motion_vector(vp8_writer *, const MV *, const MV_CONTEXT *);
+void vp8_build_component_cost_table(int *mvcost[2], const MV_CONTEXT *mvc, int mvc_flag[2]);
+
+#endif
diff --git a/vp8/encoder/ethreading.c b/vp8/encoder/ethreading.c
new file mode 100644 (file)
index 0000000..2a2cb2f
--- /dev/null
@@ -0,0 +1,588 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "onyx_int.h"
+#include "vp8/common/threading.h"
+#include "vp8/common/common.h"
+#include "vp8/common/extend.h"
+#include "bitstream.h"
+#include "encodeframe.h"
+
+#if CONFIG_MULTITHREAD
+
+extern int vp8cx_encode_inter_macroblock(VP8_COMP *cpi, MACROBLOCK *x,
+                                         TOKENEXTRA **t,
+                                         int recon_yoffset, int recon_uvoffset,
+                                         int mb_row, int mb_col);
+extern int vp8cx_encode_intra_macroblock(VP8_COMP *cpi, MACROBLOCK *x,
+                                         TOKENEXTRA **t);
+extern void vp8cx_mb_init_quantizer(VP8_COMP *cpi, MACROBLOCK *x, int ok_to_skip);
+
+extern void vp8_loopfilter_frame(VP8_COMP *cpi, VP8_COMMON *cm);
+
+static THREAD_FUNCTION thread_loopfilter(void *p_data)
+{
+    VP8_COMP *cpi = (VP8_COMP *)(((LPFTHREAD_DATA *)p_data)->ptr1);
+    VP8_COMMON *cm = &cpi->common;
+
+    while (1)
+    {
+        if (cpi->b_multi_threaded == 0)
+            break;
+
+        if (sem_wait(&cpi->h_event_start_lpf) == 0)
+        {
+            if (cpi->b_multi_threaded == 0) // we're shutting down
+                break;
+
+            vp8_loopfilter_frame(cpi, cm);
+
+            sem_post(&cpi->h_event_end_lpf);
+        }
+    }
+
+    return 0;
+}
+
+static
+THREAD_FUNCTION thread_encoding_proc(void *p_data)
+{
+    int ithread = ((ENCODETHREAD_DATA *)p_data)->ithread;
+    VP8_COMP *cpi = (VP8_COMP *)(((ENCODETHREAD_DATA *)p_data)->ptr1);
+    MB_ROW_COMP *mbri = (MB_ROW_COMP *)(((ENCODETHREAD_DATA *)p_data)->ptr2);
+    ENTROPY_CONTEXT_PLANES mb_row_left_context;
+
+    const int nsync = cpi->mt_sync_range;
+    //printf("Started thread %d\n", ithread);
+
+    while (1)
+    {
+        if (cpi->b_multi_threaded == 0)
+            break;
+
+        //if(WaitForSingleObject(cpi->h_event_mbrencoding[ithread], INFINITE) == WAIT_OBJECT_0)
+        if (sem_wait(&cpi->h_event_start_encoding[ithread]) == 0)
+        {
+            VP8_COMMON *cm = &cpi->common;
+            int mb_row;
+            MACROBLOCK *x = &mbri->mb;
+            MACROBLOCKD *xd = &x->e_mbd;
+            TOKENEXTRA *tp ;
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+            TOKENEXTRA *tp_start = cpi->tok + (1 + ithread) * (16 * 24);
+            const int num_part = (1 << cm->multi_token_partition);
+#endif
+
+            int *segment_counts = mbri->segment_counts;
+            int *totalrate = &mbri->totalrate;
+
+            if (cpi->b_multi_threaded == 0) // we're shutting down
+                break;
+
+            for (mb_row = ithread + 1; mb_row < cm->mb_rows; mb_row += (cpi->encoding_thread_count + 1))
+            {
+
+                int recon_yoffset, recon_uvoffset;
+                int mb_col;
+                int ref_fb_idx = cm->lst_fb_idx;
+                int dst_fb_idx = cm->new_fb_idx;
+                int recon_y_stride = cm->yv12_fb[ref_fb_idx].y_stride;
+                int recon_uv_stride = cm->yv12_fb[ref_fb_idx].uv_stride;
+                int map_index = (mb_row * cm->mb_cols);
+                volatile const int *last_row_current_mb_col;
+                volatile int *current_mb_col = &cpi->mt_current_mb_col[mb_row];
+
+#if  (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)
+                vp8_writer *w = &cpi->bc[1 + (mb_row % num_part)];
+#else
+                tp = cpi->tok + (mb_row * (cm->mb_cols * 16 * 24));
+                cpi->tplist[mb_row].start = tp;
+#endif
+
+                last_row_current_mb_col = &cpi->mt_current_mb_col[mb_row - 1];
+
+                // reset above block coeffs
+                xd->above_context = cm->above_context;
+                xd->left_context = &mb_row_left_context;
+
+                vp8_zero(mb_row_left_context);
+
+                xd->up_available = (mb_row != 0);
+                recon_yoffset = (mb_row * recon_y_stride * 16);
+                recon_uvoffset = (mb_row * recon_uv_stride * 8);
+
+                // Set the mb activity pointer to the start of the row.
+                x->mb_activity_ptr = &cpi->mb_activity_map[map_index];
+
+                // for each macroblock col in image
+                for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+                {
+                    *current_mb_col = mb_col - 1;
+
+                    if ((mb_col & (nsync - 1)) == 0)
+                    {
+                        while (mb_col > (*last_row_current_mb_col - nsync))
+                        {
+                            x86_pause_hint();
+                            thread_sleep(0);
+                        }
+                    }
+
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+                    tp = tp_start;
+#endif
+
+                    // Distance of Mb to the various image edges.
+                    // These specified to 8th pel as they are always compared to values that are in 1/8th pel units
+                    xd->mb_to_left_edge = -((mb_col * 16) << 3);
+                    xd->mb_to_right_edge = ((cm->mb_cols - 1 - mb_col) * 16) << 3;
+                    xd->mb_to_top_edge = -((mb_row * 16) << 3);
+                    xd->mb_to_bottom_edge = ((cm->mb_rows - 1 - mb_row) * 16) << 3;
+
+                    // Set up limit values for motion vectors used to prevent them extending outside the UMV borders
+                    x->mv_col_min = -((mb_col * 16) + (VP8BORDERINPIXELS - 16));
+                    x->mv_col_max = ((cm->mb_cols - 1 - mb_col) * 16) + (VP8BORDERINPIXELS - 16);
+                    x->mv_row_min = -((mb_row * 16) + (VP8BORDERINPIXELS - 16));
+                    x->mv_row_max = ((cm->mb_rows - 1 - mb_row) * 16) + (VP8BORDERINPIXELS - 16);
+
+                    xd->dst.y_buffer = cm->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset;
+                    xd->dst.u_buffer = cm->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset;
+                    xd->dst.v_buffer = cm->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset;
+                    xd->left_available = (mb_col != 0);
+
+                    x->rddiv = cpi->RDDIV;
+                    x->rdmult = cpi->RDMULT;
+
+                    //Copy current mb to a buffer
+                    vp8_copy_mem16x16(x->src.y_buffer, x->src.y_stride, x->thismb, 16);
+
+                    if (cpi->oxcf.tuning == VP8_TUNE_SSIM)
+                        vp8_activity_masking(cpi, x);
+
+                    // Is segmentation enabled
+                    // MB level adjustment to quantizer
+                    if (xd->segmentation_enabled)
+                    {
+                        // Code to set segment id in xd->mbmi.segment_id for current MB (with range checking)
+                        if (cpi->segmentation_map[map_index + mb_col] <= 3)
+                            xd->mode_info_context->mbmi.segment_id = cpi->segmentation_map[map_index + mb_col];
+                        else
+                            xd->mode_info_context->mbmi.segment_id = 0;
+
+                        vp8cx_mb_init_quantizer(cpi, x, 1);
+                    }
+                    else
+                        xd->mode_info_context->mbmi.segment_id = 0; // Set to Segment 0 by default
+
+                    x->active_ptr = cpi->active_map + map_index + mb_col;
+
+                    if (cm->frame_type == KEY_FRAME)
+                    {
+                        *totalrate += vp8cx_encode_intra_macroblock(cpi, x, &tp);
+#ifdef MODE_STATS
+                        y_modes[xd->mbmi.mode] ++;
+#endif
+                    }
+                    else
+                    {
+                        *totalrate += vp8cx_encode_inter_macroblock(cpi, x, &tp, recon_yoffset, recon_uvoffset, mb_row, mb_col);
+
+#ifdef MODE_STATS
+                        inter_y_modes[xd->mbmi.mode] ++;
+
+                        if (xd->mbmi.mode == SPLITMV)
+                        {
+                            int b;
+
+                            for (b = 0; b < xd->mbmi.partition_count; b++)
+                            {
+                                inter_b_modes[x->partition->bmi[b].mode] ++;
+                            }
+                        }
+
+#endif
+
+                        // Count of last ref frame 0,0 usage
+                        if ((xd->mode_info_context->mbmi.mode == ZEROMV) && (xd->mode_info_context->mbmi.ref_frame == LAST_FRAME))
+                            cpi->inter_zz_count++;
+
+                        // Special case code for cyclic refresh
+                        // If cyclic update enabled then copy xd->mbmi.segment_id; (which may have been updated based on mode
+                        // during vp8cx_encode_inter_macroblock()) back into the global segmentation map
+                        if (cpi->cyclic_refresh_mode_enabled && xd->segmentation_enabled)
+                        {
+                            const MB_MODE_INFO * mbmi = &xd->mode_info_context->mbmi;
+                            cpi->segmentation_map[map_index + mb_col] = mbmi->segment_id;
+
+                            // If the block has been refreshed mark it as clean (the magnitude of the -ve influences how long it will be before we consider another refresh):
+                            // Else if it was coded (last frame 0,0) and has not already been refreshed then mark it as a candidate for cleanup next time (marked 0)
+                            // else mark it as dirty (1).
+                            if (mbmi->segment_id)
+                                cpi->cyclic_refresh_map[map_index + mb_col] = -1;
+                            else if ((mbmi->mode == ZEROMV) && (mbmi->ref_frame == LAST_FRAME))
+                            {
+                                if (cpi->cyclic_refresh_map[map_index + mb_col] == 1)
+                                    cpi->cyclic_refresh_map[map_index + mb_col] = 0;
+                            }
+                            else
+                                cpi->cyclic_refresh_map[map_index + mb_col] = 1;
+
+                        }
+                    }
+
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+                    /* pack tokens for this MB */
+                    {
+                        int tok_count = tp - tp_start;
+                        pack_tokens(w, tp_start, tok_count);
+                    }
+#else
+                    cpi->tplist[mb_row].stop = tp;
+#endif
+                    // Increment pointer into gf usage flags structure.
+                    x->gf_active_ptr++;
+
+                    // Increment the activity mask pointers.
+                    x->mb_activity_ptr++;
+
+                    // adjust to the next column of macroblocks
+                    x->src.y_buffer += 16;
+                    x->src.u_buffer += 8;
+                    x->src.v_buffer += 8;
+
+                    recon_yoffset += 16;
+                    recon_uvoffset += 8;
+
+                    // Keep track of segment usage
+                    segment_counts[xd->mode_info_context->mbmi.segment_id]++;
+
+                    // skip to next mb
+                    xd->mode_info_context++;
+                    x->partition_info++;
+                    xd->above_context++;
+                }
+
+                vp8_extend_mb_row( &cm->yv12_fb[dst_fb_idx],
+                                    xd->dst.y_buffer + 16,
+                                    xd->dst.u_buffer + 8,
+                                    xd->dst.v_buffer + 8);
+
+                *current_mb_col = mb_col + nsync;
+
+                // this is to account for the border
+                xd->mode_info_context++;
+                x->partition_info++;
+
+                x->src.y_buffer += 16 * x->src.y_stride * (cpi->encoding_thread_count + 1) - 16 * cm->mb_cols;
+                x->src.u_buffer += 8 * x->src.uv_stride * (cpi->encoding_thread_count + 1) - 8 * cm->mb_cols;
+                x->src.v_buffer += 8 * x->src.uv_stride * (cpi->encoding_thread_count + 1) - 8 * cm->mb_cols;
+
+                xd->mode_info_context += xd->mode_info_stride * cpi->encoding_thread_count;
+                x->partition_info += xd->mode_info_stride * cpi->encoding_thread_count;
+                x->gf_active_ptr   += cm->mb_cols * cpi->encoding_thread_count;
+
+                if (mb_row == cm->mb_rows - 1)
+                {
+                    sem_post(&cpi->h_event_end_encoding); /* signal frame encoding end */
+                }
+            }
+        }
+    }
+
+    //printf("exit thread %d\n", ithread);
+    return 0;
+}
+
+static void setup_mbby_copy(MACROBLOCK *mbdst, MACROBLOCK *mbsrc)
+{
+
+    MACROBLOCK *x = mbsrc;
+    MACROBLOCK *z = mbdst;
+    int i;
+
+    z->ss               = x->ss;
+    z->ss_count          = x->ss_count;
+    z->searches_per_step  = x->searches_per_step;
+    z->errorperbit      = x->errorperbit;
+
+    z->sadperbit16      = x->sadperbit16;
+    z->sadperbit4       = x->sadperbit4;
+
+    /*
+    z->mv_col_min    = x->mv_col_min;
+    z->mv_col_max    = x->mv_col_max;
+    z->mv_row_min    = x->mv_row_min;
+    z->mv_row_max    = x->mv_row_max;
+    */
+
+    z->short_fdct4x4     = x->short_fdct4x4;
+    z->short_fdct8x4     = x->short_fdct8x4;
+    z->short_walsh4x4    = x->short_walsh4x4;
+    z->quantize_b        = x->quantize_b;
+    z->quantize_b_pair   = x->quantize_b_pair;
+    z->optimize          = x->optimize;
+
+    /*
+    z->mvc              = x->mvc;
+    z->src.y_buffer      = x->src.y_buffer;
+    z->src.u_buffer      = x->src.u_buffer;
+    z->src.v_buffer      = x->src.v_buffer;
+    */
+
+
+    vpx_memcpy(z->mvcosts,          x->mvcosts,         sizeof(x->mvcosts));
+    z->mvcost[0] = &z->mvcosts[0][mv_max+1];
+    z->mvcost[1] = &z->mvcosts[1][mv_max+1];
+    z->mvsadcost[0] = &z->mvsadcosts[0][mvfp_max+1];
+    z->mvsadcost[1] = &z->mvsadcosts[1][mvfp_max+1];
+
+
+    vpx_memcpy(z->token_costs,       x->token_costs,      sizeof(x->token_costs));
+    vpx_memcpy(z->inter_bmode_costs,  x->inter_bmode_costs, sizeof(x->inter_bmode_costs));
+    //memcpy(z->mvcosts,            x->mvcosts,         sizeof(x->mvcosts));
+    //memcpy(z->mvcost,         x->mvcost,          sizeof(x->mvcost));
+    vpx_memcpy(z->mbmode_cost,       x->mbmode_cost,      sizeof(x->mbmode_cost));
+    vpx_memcpy(z->intra_uv_mode_cost,  x->intra_uv_mode_cost, sizeof(x->intra_uv_mode_cost));
+    vpx_memcpy(z->bmode_costs,       x->bmode_costs,      sizeof(x->bmode_costs));
+
+    for (i = 0; i < 25; i++)
+    {
+        z->block[i].quant           = x->block[i].quant;
+        z->block[i].quant_fast      = x->block[i].quant_fast;
+        z->block[i].quant_shift     = x->block[i].quant_shift;
+        z->block[i].zbin            = x->block[i].zbin;
+        z->block[i].zrun_zbin_boost   = x->block[i].zrun_zbin_boost;
+        z->block[i].round           = x->block[i].round;
+        z->q_index                  = x->q_index;
+        z->act_zbin_adj             = x->act_zbin_adj;
+        z->last_act_zbin_adj        = x->last_act_zbin_adj;
+        /*
+        z->block[i].src             = x->block[i].src;
+        */
+        z->block[i].src_stride       = x->block[i].src_stride;
+    }
+
+    {
+        MACROBLOCKD *xd = &x->e_mbd;
+        MACROBLOCKD *zd = &z->e_mbd;
+
+        /*
+        zd->mode_info_context = xd->mode_info_context;
+        zd->mode_info        = xd->mode_info;
+
+        zd->mode_info_stride  = xd->mode_info_stride;
+        zd->frame_type       = xd->frame_type;
+        zd->up_available     = xd->up_available   ;
+        zd->left_available   = xd->left_available;
+        zd->left_context     = xd->left_context;
+        zd->last_frame_dc     = xd->last_frame_dc;
+        zd->last_frame_dccons = xd->last_frame_dccons;
+        zd->gold_frame_dc     = xd->gold_frame_dc;
+        zd->gold_frame_dccons = xd->gold_frame_dccons;
+        zd->mb_to_left_edge    = xd->mb_to_left_edge;
+        zd->mb_to_right_edge   = xd->mb_to_right_edge;
+        zd->mb_to_top_edge     = xd->mb_to_top_edge   ;
+        zd->mb_to_bottom_edge  = xd->mb_to_bottom_edge;
+        zd->gf_active_ptr     = xd->gf_active_ptr;
+        zd->frames_since_golden       = xd->frames_since_golden;
+        zd->frames_till_alt_ref_frame   = xd->frames_till_alt_ref_frame;
+        */
+        zd->subpixel_predict         = xd->subpixel_predict;
+        zd->subpixel_predict8x4      = xd->subpixel_predict8x4;
+        zd->subpixel_predict8x8      = xd->subpixel_predict8x8;
+        zd->subpixel_predict16x16    = xd->subpixel_predict16x16;
+        zd->segmentation_enabled     = xd->segmentation_enabled;
+        zd->mb_segement_abs_delta      = xd->mb_segement_abs_delta;
+        vpx_memcpy(zd->segment_feature_data, xd->segment_feature_data, sizeof(xd->segment_feature_data));
+
+        vpx_memcpy(zd->dequant_y1_dc, xd->dequant_y1_dc, sizeof(xd->dequant_y1_dc));
+        vpx_memcpy(zd->dequant_y1, xd->dequant_y1, sizeof(xd->dequant_y1));
+        vpx_memcpy(zd->dequant_y2, xd->dequant_y2, sizeof(xd->dequant_y2));
+        vpx_memcpy(zd->dequant_uv, xd->dequant_uv, sizeof(xd->dequant_uv));
+
+#if 1
+        /*TODO:  Remove dequant from BLOCKD.  This is a temporary solution until
+         * the quantizer code uses a passed in pointer to the dequant constants.
+         * This will also require modifications to the x86 and neon assembly.
+         * */
+        for (i = 0; i < 16; i++)
+            zd->block[i].dequant = zd->dequant_y1;
+        for (i = 16; i < 24; i++)
+            zd->block[i].dequant = zd->dequant_uv;
+        zd->block[24].dequant = zd->dequant_y2;
+#endif
+    }
+}
+
+void vp8cx_init_mbrthread_data(VP8_COMP *cpi,
+                               MACROBLOCK *x,
+                               MB_ROW_COMP *mbr_ei,
+                               int mb_row,
+                               int count
+                              )
+{
+
+    VP8_COMMON *const cm = & cpi->common;
+    MACROBLOCKD *const xd = & x->e_mbd;
+    int i;
+    (void) mb_row;
+
+    for (i = 0; i < count; i++)
+    {
+        MACROBLOCK *mb = & mbr_ei[i].mb;
+        MACROBLOCKD *mbd = &mb->e_mbd;
+
+        mbd->subpixel_predict        = xd->subpixel_predict;
+        mbd->subpixel_predict8x4     = xd->subpixel_predict8x4;
+        mbd->subpixel_predict8x8     = xd->subpixel_predict8x8;
+        mbd->subpixel_predict16x16   = xd->subpixel_predict16x16;
+        mb->gf_active_ptr            = x->gf_active_ptr;
+
+        vpx_memset(mbr_ei[i].segment_counts, 0, sizeof(mbr_ei[i].segment_counts));
+        mbr_ei[i].totalrate = 0;
+
+        mb->partition_info = x->pi + x->e_mbd.mode_info_stride * (i + 1);
+
+        mbd->mode_info_context = cm->mi   + x->e_mbd.mode_info_stride * (i + 1);
+        mbd->mode_info_stride  = cm->mode_info_stride;
+
+        mbd->frame_type = cm->frame_type;
+
+        mb->src = * cpi->Source;
+        mbd->pre = cm->yv12_fb[cm->lst_fb_idx];
+        mbd->dst = cm->yv12_fb[cm->new_fb_idx];
+
+        mb->src.y_buffer += 16 * x->src.y_stride * (i + 1);
+        mb->src.u_buffer +=  8 * x->src.uv_stride * (i + 1);
+        mb->src.v_buffer +=  8 * x->src.uv_stride * (i + 1);
+
+        vp8_build_block_offsets(mb);
+
+        vp8_setup_block_dptrs(mbd);
+
+        vp8_setup_block_ptrs(mb);
+
+        mbd->left_context = &cm->left_context;
+        mb->mvc = cm->fc.mvc;
+
+        setup_mbby_copy(&mbr_ei[i].mb, x);
+
+        mbd->fullpixel_mask = 0xffffffff;
+        if(cm->full_pixel)
+            mbd->fullpixel_mask = 0xfffffff8;
+    }
+}
+
+void vp8cx_create_encoder_threads(VP8_COMP *cpi)
+{
+    const VP8_COMMON * cm = &cpi->common;
+
+    cpi->b_multi_threaded = 0;
+    cpi->encoding_thread_count = 0;
+    cpi->b_lpf_running = 0;
+
+    if (cm->processor_core_count > 1 && cpi->oxcf.multi_threaded > 1)
+    {
+        int ithread;
+        int th_count = cpi->oxcf.multi_threaded - 1;
+
+        /* don't allocate more threads than cores available */
+        if (cpi->oxcf.multi_threaded > cm->processor_core_count)
+            th_count = cm->processor_core_count - 1;
+
+        /* we have th_count + 1 (main) threads processing one row each */
+        /* no point to have more threads than the sync range allows */
+        if(th_count > ((cm->mb_cols / cpi->mt_sync_range) - 1))
+        {
+            th_count = (cm->mb_cols / cpi->mt_sync_range) - 1;
+        }
+
+        if(th_count == 0)
+            return;
+
+        CHECK_MEM_ERROR(cpi->h_encoding_thread, vpx_malloc(sizeof(pthread_t) * th_count));
+        CHECK_MEM_ERROR(cpi->h_event_start_encoding, vpx_malloc(sizeof(sem_t) * th_count));
+        CHECK_MEM_ERROR(cpi->mb_row_ei, vpx_memalign(32, sizeof(MB_ROW_COMP) * th_count));
+        vpx_memset(cpi->mb_row_ei, 0, sizeof(MB_ROW_COMP) * th_count);
+        CHECK_MEM_ERROR(cpi->en_thread_data,
+                        vpx_malloc(sizeof(ENCODETHREAD_DATA) * th_count));
+        CHECK_MEM_ERROR(cpi->mt_current_mb_col,
+                        vpx_malloc(sizeof(*cpi->mt_current_mb_col) * cm->mb_rows));
+
+        sem_init(&cpi->h_event_end_encoding, 0, 0);
+
+        cpi->b_multi_threaded = 1;
+        cpi->encoding_thread_count = th_count;
+
+        /*
+        printf("[VP8:] multi_threaded encoding is enabled with %d threads\n\n",
+               (cpi->encoding_thread_count +1));
+        */
+
+        for (ithread = 0; ithread < th_count; ithread++)
+        {
+            ENCODETHREAD_DATA * ethd = &cpi->en_thread_data[ithread];
+
+            sem_init(&cpi->h_event_start_encoding[ithread], 0, 0);
+            ethd->ithread = ithread;
+            ethd->ptr1 = (void *)cpi;
+            ethd->ptr2 = (void *)&cpi->mb_row_ei[ithread];
+
+            pthread_create(&cpi->h_encoding_thread[ithread], 0, thread_encoding_proc, ethd);
+        }
+
+        {
+            LPFTHREAD_DATA * lpfthd = &cpi->lpf_thread_data;
+
+            sem_init(&cpi->h_event_start_lpf, 0, 0);
+            sem_init(&cpi->h_event_end_lpf, 0, 0);
+
+            lpfthd->ptr1 = (void *)cpi;
+            pthread_create(&cpi->h_filter_thread, 0, thread_loopfilter, lpfthd);
+        }
+    }
+
+}
+
+void vp8cx_remove_encoder_threads(VP8_COMP *cpi)
+{
+    if (cpi->b_multi_threaded)
+    {
+        //shutdown other threads
+        cpi->b_multi_threaded = 0;
+        {
+            int i;
+
+            for (i = 0; i < cpi->encoding_thread_count; i++)
+            {
+                //SetEvent(cpi->h_event_mbrencoding[i]);
+                sem_post(&cpi->h_event_start_encoding[i]);
+                pthread_join(cpi->h_encoding_thread[i], 0);
+
+                sem_destroy(&cpi->h_event_start_encoding[i]);
+            }
+
+            sem_post(&cpi->h_event_start_lpf);
+            pthread_join(cpi->h_filter_thread, 0);
+        }
+
+        sem_destroy(&cpi->h_event_end_encoding);
+        sem_destroy(&cpi->h_event_end_lpf);
+        sem_destroy(&cpi->h_event_start_lpf);
+
+        //free thread related resources
+        vpx_free(cpi->h_event_start_encoding);
+        vpx_free(cpi->h_encoding_thread);
+        vpx_free(cpi->mb_row_ei);
+        vpx_free(cpi->en_thread_data);
+        vpx_free(cpi->mt_current_mb_col);
+    }
+}
+#endif
diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c
new file mode 100644 (file)
index 0000000..8de1a6a
--- /dev/null
@@ -0,0 +1,3198 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <math.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "block.h"
+#include "onyx_int.h"
+#include "vp8/common/variance.h"
+#include "encodeintra.h"
+#include "vp8/common/setupintrarecon.h"
+#include "vp8/common/systemdependent.h"
+#include "mcomp.h"
+#include "firstpass.h"
+#include "vpx_scale/vpxscale.h"
+#include "encodemb.h"
+#include "vp8/common/extend.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vp8/common/swapyv12buffer.h"
+#include "rdopt.h"
+#include "vp8/common/quant_common.h"
+#include "encodemv.h"
+#include "encodeframe.h"
+
+//#define OUTPUT_FPF 1
+
+extern void vp8cx_frame_init_quantizer(VP8_COMP *cpi);
+extern void vp8_set_mbmode_and_mvs(MACROBLOCK *x, MB_PREDICTION_MODE mb, int_mv *mv);
+extern void vp8_alloc_compressor_data(VP8_COMP *cpi);
+
+//#define GFQ_ADJUSTMENT (40 + ((15*Q)/10))
+//#define GFQ_ADJUSTMENT (80 + ((15*Q)/10))
+#define GFQ_ADJUSTMENT vp8_gf_boost_qadjustment[Q]
+extern int vp8_kf_boost_qadjustment[QINDEX_RANGE];
+
+extern const int vp8_gf_boost_qadjustment[QINDEX_RANGE];
+
+#define IIFACTOR   1.5
+#define IIKFACTOR1 1.40
+#define IIKFACTOR2 1.5
+#define RMAX       14.0
+#define GF_RMAX    48.0
+
+#define KF_MB_INTRA_MIN 300
+#define GF_MB_INTRA_MIN 200
+
+#define DOUBLE_DIVIDE_CHECK(X) ((X)<0?(X)-.000001:(X)+.000001)
+
+#define POW1 (double)cpi->oxcf.two_pass_vbrbias/100.0
+#define POW2 (double)cpi->oxcf.two_pass_vbrbias/100.0
+
+#define NEW_BOOST 1
+
+static int vscale_lookup[7] = {0, 1, 1, 2, 2, 3, 3};
+static int hscale_lookup[7] = {0, 0, 1, 1, 2, 2, 3};
+
+
+static const int cq_level[QINDEX_RANGE] =
+{
+    0,0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,
+    9,10,11,11,12,13,13,14,15,15,16,17,17,18,19,20,
+    20,21,22,22,23,24,24,25,26,27,27,28,29,30,30,31,
+    32,33,33,34,35,36,36,37,38,39,39,40,41,42,42,43,
+    44,45,46,46,47,48,49,50,50,51,52,53,54,55,55,56,
+    57,58,59,60,60,61,62,63,64,65,66,67,67,68,69,70,
+    71,72,73,74,75,75,76,77,78,79,80,81,82,83,84,85,
+    86,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100
+};
+
+static void find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame);
+
+// Resets the first pass file to the given position using a relative seek from the current position
+static void reset_fpf_position(VP8_COMP *cpi, FIRSTPASS_STATS *Position)
+{
+    cpi->twopass.stats_in = Position;
+}
+
+static int lookup_next_frame_stats(VP8_COMP *cpi, FIRSTPASS_STATS *next_frame)
+{
+    if (cpi->twopass.stats_in >= cpi->twopass.stats_in_end)
+        return EOF;
+
+    *next_frame = *cpi->twopass.stats_in;
+    return 1;
+}
+
+// Read frame stats at an offset from the current position
+static int read_frame_stats( VP8_COMP *cpi,
+                             FIRSTPASS_STATS *frame_stats,
+                             int offset )
+{
+    FIRSTPASS_STATS * fps_ptr = cpi->twopass.stats_in;
+
+    // Check legality of offset
+    if ( offset >= 0 )
+    {
+        if ( &fps_ptr[offset] >= cpi->twopass.stats_in_end )
+             return EOF;
+    }
+    else if ( offset < 0 )
+    {
+        if ( &fps_ptr[offset] < cpi->twopass.stats_in_start )
+             return EOF;
+    }
+
+    *frame_stats = fps_ptr[offset];
+    return 1;
+}
+
+static int input_stats(VP8_COMP *cpi, FIRSTPASS_STATS *fps)
+{
+    if (cpi->twopass.stats_in >= cpi->twopass.stats_in_end)
+        return EOF;
+
+    *fps = *cpi->twopass.stats_in;
+    cpi->twopass.stats_in =
+         (void*)((char *)cpi->twopass.stats_in + sizeof(FIRSTPASS_STATS));
+    return 1;
+}
+
+static void output_stats(const VP8_COMP            *cpi,
+                         struct vpx_codec_pkt_list *pktlist,
+                         FIRSTPASS_STATS            *stats)
+{
+    struct vpx_codec_cx_pkt pkt;
+    pkt.kind = VPX_CODEC_STATS_PKT;
+    pkt.data.twopass_stats.buf = stats;
+    pkt.data.twopass_stats.sz = sizeof(FIRSTPASS_STATS);
+    vpx_codec_pkt_list_add(pktlist, &pkt);
+
+// TEMP debug code
+#if OUTPUT_FPF
+
+    {
+        FILE *fpfile;
+        fpfile = fopen("firstpass.stt", "a");
+
+        fprintf(fpfile, "%12.0f %12.0f %12.0f %12.4f %12.4f %12.4f %12.4f"
+                " %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f"
+                " %12.0f %12.0f %12.4f\n",
+                stats->frame,
+                stats->intra_error,
+                stats->coded_error,
+                stats->ssim_weighted_pred_err,
+                stats->pcnt_inter,
+                stats->pcnt_motion,
+                stats->pcnt_second_ref,
+                stats->pcnt_neutral,
+                stats->MVr,
+                stats->mvr_abs,
+                stats->MVc,
+                stats->mvc_abs,
+                stats->MVrv,
+                stats->MVcv,
+                stats->mv_in_out_count,
+                stats->new_mv_count,
+                stats->count,
+                stats->duration);
+        fclose(fpfile);
+    }
+#endif
+}
+
+static void zero_stats(FIRSTPASS_STATS *section)
+{
+    section->frame      = 0.0;
+    section->intra_error = 0.0;
+    section->coded_error = 0.0;
+    section->ssim_weighted_pred_err = 0.0;
+    section->pcnt_inter  = 0.0;
+    section->pcnt_motion  = 0.0;
+    section->pcnt_second_ref = 0.0;
+    section->pcnt_neutral = 0.0;
+    section->MVr        = 0.0;
+    section->mvr_abs     = 0.0;
+    section->MVc        = 0.0;
+    section->mvc_abs     = 0.0;
+    section->MVrv       = 0.0;
+    section->MVcv       = 0.0;
+    section->mv_in_out_count  = 0.0;
+    section->new_mv_count = 0.0;
+    section->count      = 0.0;
+    section->duration   = 1.0;
+}
+
+static void accumulate_stats(FIRSTPASS_STATS *section, FIRSTPASS_STATS *frame)
+{
+    section->frame += frame->frame;
+    section->intra_error += frame->intra_error;
+    section->coded_error += frame->coded_error;
+    section->ssim_weighted_pred_err += frame->ssim_weighted_pred_err;
+    section->pcnt_inter  += frame->pcnt_inter;
+    section->pcnt_motion += frame->pcnt_motion;
+    section->pcnt_second_ref += frame->pcnt_second_ref;
+    section->pcnt_neutral += frame->pcnt_neutral;
+    section->MVr        += frame->MVr;
+    section->mvr_abs     += frame->mvr_abs;
+    section->MVc        += frame->MVc;
+    section->mvc_abs     += frame->mvc_abs;
+    section->MVrv       += frame->MVrv;
+    section->MVcv       += frame->MVcv;
+    section->mv_in_out_count  += frame->mv_in_out_count;
+    section->new_mv_count += frame->new_mv_count;
+    section->count      += frame->count;
+    section->duration   += frame->duration;
+}
+
+static void subtract_stats(FIRSTPASS_STATS *section, FIRSTPASS_STATS *frame)
+{
+    section->frame -= frame->frame;
+    section->intra_error -= frame->intra_error;
+    section->coded_error -= frame->coded_error;
+    section->ssim_weighted_pred_err -= frame->ssim_weighted_pred_err;
+    section->pcnt_inter  -= frame->pcnt_inter;
+    section->pcnt_motion -= frame->pcnt_motion;
+    section->pcnt_second_ref -= frame->pcnt_second_ref;
+    section->pcnt_neutral -= frame->pcnt_neutral;
+    section->MVr        -= frame->MVr;
+    section->mvr_abs     -= frame->mvr_abs;
+    section->MVc        -= frame->MVc;
+    section->mvc_abs     -= frame->mvc_abs;
+    section->MVrv       -= frame->MVrv;
+    section->MVcv       -= frame->MVcv;
+    section->mv_in_out_count  -= frame->mv_in_out_count;
+    section->new_mv_count -= frame->new_mv_count;
+    section->count      -= frame->count;
+    section->duration   -= frame->duration;
+}
+
+static void avg_stats(FIRSTPASS_STATS *section)
+{
+    if (section->count < 1.0)
+        return;
+
+    section->intra_error /= section->count;
+    section->coded_error /= section->count;
+    section->ssim_weighted_pred_err /= section->count;
+    section->pcnt_inter  /= section->count;
+    section->pcnt_second_ref /= section->count;
+    section->pcnt_neutral /= section->count;
+    section->pcnt_motion /= section->count;
+    section->MVr        /= section->count;
+    section->mvr_abs     /= section->count;
+    section->MVc        /= section->count;
+    section->mvc_abs     /= section->count;
+    section->MVrv       /= section->count;
+    section->MVcv       /= section->count;
+    section->mv_in_out_count   /= section->count;
+    section->duration   /= section->count;
+}
+
+// Calculate a modified Error used in distributing bits between easier and harder frames
+static double calculate_modified_err(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
+{
+    double av_err = ( cpi->twopass.total_stats.ssim_weighted_pred_err /
+                      cpi->twopass.total_stats.count );
+    double this_err = this_frame->ssim_weighted_pred_err;
+    double modified_err;
+
+    if (this_err > av_err)
+        modified_err = av_err * pow((this_err / DOUBLE_DIVIDE_CHECK(av_err)), POW1);
+    else
+        modified_err = av_err * pow((this_err / DOUBLE_DIVIDE_CHECK(av_err)), POW2);
+
+    return modified_err;
+}
+
+static const double weight_table[256] = {
+0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000,
+0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000,
+0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000,
+0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000,
+0.020000, 0.031250, 0.062500, 0.093750, 0.125000, 0.156250, 0.187500, 0.218750,
+0.250000, 0.281250, 0.312500, 0.343750, 0.375000, 0.406250, 0.437500, 0.468750,
+0.500000, 0.531250, 0.562500, 0.593750, 0.625000, 0.656250, 0.687500, 0.718750,
+0.750000, 0.781250, 0.812500, 0.843750, 0.875000, 0.906250, 0.937500, 0.968750,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000
+};
+
+static double simple_weight(YV12_BUFFER_CONFIG *source)
+{
+    int i, j;
+
+    unsigned char *src = source->y_buffer;
+    double sum_weights = 0.0;
+
+    // Loop throught the Y plane raw examining levels and creating a weight for the image
+    i = source->y_height;
+    do
+    {
+        j = source->y_width;
+        do
+        {
+            sum_weights += weight_table[ *src];
+            src++;
+        }while(--j);
+        src -= source->y_width;
+        src += source->y_stride;
+    }while(--i);
+
+    sum_weights /= (source->y_height * source->y_width);
+
+    return sum_weights;
+}
+
+
+// This function returns the current per frame maximum bitrate target
+static int frame_max_bits(VP8_COMP *cpi)
+{
+    // Max allocation for a single frame based on the max section guidelines passed in and how many bits are left
+    int max_bits;
+
+    // For CBR we need to also consider buffer fullness.
+    // If we are running below the optimal level then we need to gradually tighten up on max_bits.
+    if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+    {
+        double buffer_fullness_ratio = (double)cpi->buffer_level / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.optimal_buffer_level);
+
+        // For CBR base this on the target average bits per frame plus the maximum sedction rate passed in by the user
+        max_bits = (int)(cpi->av_per_frame_bandwidth * ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0));
+
+        // If our buffer is below the optimum level
+        if (buffer_fullness_ratio < 1.0)
+        {
+            // The lower of max_bits / 4 or cpi->av_per_frame_bandwidth / 4.
+            int min_max_bits = ((cpi->av_per_frame_bandwidth >> 2) < (max_bits >> 2)) ? cpi->av_per_frame_bandwidth >> 2 : max_bits >> 2;
+
+            max_bits = (int)(max_bits * buffer_fullness_ratio);
+
+            if (max_bits < min_max_bits)
+                max_bits = min_max_bits;       // Lowest value we will set ... which should allow the buffer to refil.
+        }
+    }
+    // VBR
+    else
+    {
+        // For VBR base this on the bits and frames left plus the two_pass_vbrmax_section rate passed in by the user
+        max_bits = (int)(((double)cpi->twopass.bits_left / (cpi->twopass.total_stats.count - (double)cpi->common.current_video_frame)) * ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0));
+    }
+
+    // Trap case where we are out of bits
+    if (max_bits < 0)
+        max_bits = 0;
+
+    return max_bits;
+}
+
+void vp8_init_first_pass(VP8_COMP *cpi)
+{
+    zero_stats(&cpi->twopass.total_stats);
+}
+
+void vp8_end_first_pass(VP8_COMP *cpi)
+{
+    output_stats(cpi, cpi->output_pkt_list, &cpi->twopass.total_stats);
+}
+
+static void zz_motion_search( VP8_COMP *cpi, MACROBLOCK * x,
+                              YV12_BUFFER_CONFIG * raw_buffer,
+                              int * raw_motion_err,
+                              YV12_BUFFER_CONFIG * recon_buffer,
+                              int * best_motion_err, int recon_yoffset)
+{
+    MACROBLOCKD * const xd = & x->e_mbd;
+    BLOCK *b = &x->block[0];
+    BLOCKD *d = &x->e_mbd.block[0];
+
+    unsigned char *src_ptr = (*(b->base_src) + b->src);
+    int src_stride = b->src_stride;
+    unsigned char *raw_ptr;
+    int raw_stride = raw_buffer->y_stride;
+    unsigned char *ref_ptr;
+    int ref_stride = x->e_mbd.pre.y_stride;
+
+    // Set up pointers for this macro block raw buffer
+    raw_ptr = (unsigned char *)(raw_buffer->y_buffer + recon_yoffset
+                                + d->offset);
+    vp8_mse16x16 ( src_ptr, src_stride, raw_ptr, raw_stride,
+                   (unsigned int *)(raw_motion_err));
+
+    // Set up pointers for this macro block recon buffer
+    xd->pre.y_buffer = recon_buffer->y_buffer + recon_yoffset;
+    ref_ptr = (unsigned char *)(xd->pre.y_buffer + d->offset );
+    vp8_mse16x16 ( src_ptr, src_stride, ref_ptr, ref_stride,
+                   (unsigned int *)(best_motion_err));
+}
+
+static void first_pass_motion_search(VP8_COMP *cpi, MACROBLOCK *x,
+                                     int_mv *ref_mv, MV *best_mv,
+                                     YV12_BUFFER_CONFIG *recon_buffer,
+                                     int *best_motion_err, int recon_yoffset )
+{
+    MACROBLOCKD *const xd = & x->e_mbd;
+    BLOCK *b = &x->block[0];
+    BLOCKD *d = &x->e_mbd.block[0];
+    int num00;
+
+    int_mv tmp_mv;
+    int_mv ref_mv_full;
+
+    int tmp_err;
+    int step_param = 3;                                       //3;          // Dont search over full range for first pass
+    int further_steps = (MAX_MVSEARCH_STEPS - 1) - step_param; //3;
+    int n;
+    vp8_variance_fn_ptr_t v_fn_ptr = cpi->fn_ptr[BLOCK_16X16];
+    int new_mv_mode_penalty = 256;
+
+    // override the default variance function to use MSE
+    v_fn_ptr.vf    = vp8_mse16x16;
+
+    // Set up pointers for this macro block recon buffer
+    xd->pre.y_buffer = recon_buffer->y_buffer + recon_yoffset;
+
+    // Initial step/diamond search centred on best mv
+    tmp_mv.as_int = 0;
+    ref_mv_full.as_mv.col = ref_mv->as_mv.col>>3;
+    ref_mv_full.as_mv.row = ref_mv->as_mv.row>>3;
+    tmp_err = cpi->diamond_search_sad(x, b, d, &ref_mv_full, &tmp_mv, step_param,
+                                      x->sadperbit16, &num00, &v_fn_ptr,
+                                      x->mvcost, ref_mv);
+    if ( tmp_err < INT_MAX-new_mv_mode_penalty )
+        tmp_err += new_mv_mode_penalty;
+
+    if (tmp_err < *best_motion_err)
+    {
+        *best_motion_err = tmp_err;
+        best_mv->row = tmp_mv.as_mv.row;
+        best_mv->col = tmp_mv.as_mv.col;
+    }
+
+    // Further step/diamond searches as necessary
+    n = num00;
+    num00 = 0;
+
+    while (n < further_steps)
+    {
+        n++;
+
+        if (num00)
+            num00--;
+        else
+        {
+            tmp_err = cpi->diamond_search_sad(x, b, d, &ref_mv_full, &tmp_mv,
+                                              step_param + n, x->sadperbit16,
+                                              &num00, &v_fn_ptr, x->mvcost,
+                                              ref_mv);
+            if ( tmp_err < INT_MAX-new_mv_mode_penalty )
+                tmp_err += new_mv_mode_penalty;
+
+            if (tmp_err < *best_motion_err)
+            {
+                *best_motion_err = tmp_err;
+                best_mv->row = tmp_mv.as_mv.row;
+                best_mv->col = tmp_mv.as_mv.col;
+            }
+        }
+    }
+}
+
+void vp8_first_pass(VP8_COMP *cpi)
+{
+    int mb_row, mb_col;
+    MACROBLOCK *const x = & cpi->mb;
+    VP8_COMMON *const cm = & cpi->common;
+    MACROBLOCKD *const xd = & x->e_mbd;
+
+    int recon_yoffset, recon_uvoffset;
+    YV12_BUFFER_CONFIG *lst_yv12 = &cm->yv12_fb[cm->lst_fb_idx];
+    YV12_BUFFER_CONFIG *new_yv12 = &cm->yv12_fb[cm->new_fb_idx];
+    YV12_BUFFER_CONFIG *gld_yv12 = &cm->yv12_fb[cm->gld_fb_idx];
+    int recon_y_stride = lst_yv12->y_stride;
+    int recon_uv_stride = lst_yv12->uv_stride;
+    int64_t intra_error = 0;
+    int64_t coded_error = 0;
+
+    int sum_mvr = 0, sum_mvc = 0;
+    int sum_mvr_abs = 0, sum_mvc_abs = 0;
+    int sum_mvrs = 0, sum_mvcs = 0;
+    int mvcount = 0;
+    int intercount = 0;
+    int second_ref_count = 0;
+    int intrapenalty = 256;
+    int neutral_count = 0;
+    int new_mv_count = 0;
+    int sum_in_vectors = 0;
+    uint32_t lastmv_as_int = 0;
+
+    int_mv zero_ref_mv;
+
+    zero_ref_mv.as_int = 0;
+
+    vp8_clear_system_state();  //__asm emms;
+
+    x->src = * cpi->Source;
+    xd->pre = *lst_yv12;
+    xd->dst = *new_yv12;
+
+    x->partition_info = x->pi;
+
+    xd->mode_info_context = cm->mi;
+
+    vp8_build_block_offsets(x);
+
+    vp8_setup_block_dptrs(&x->e_mbd);
+
+    vp8_setup_block_ptrs(x);
+
+    // set up frame new frame for intra coded blocks
+    vp8_setup_intra_recon(new_yv12);
+    vp8cx_frame_init_quantizer(cpi);
+
+    // Initialise the MV cost table to the defaults
+    //if( cm->current_video_frame == 0)
+    //if ( 0 )
+    {
+        int flag[2] = {1, 1};
+        vp8_initialize_rd_consts(cpi, vp8_dc_quant(cm->base_qindex, cm->y1dc_delta_q));
+        vpx_memcpy(cm->fc.mvc, vp8_default_mv_context, sizeof(vp8_default_mv_context));
+        vp8_build_component_cost_table(cpi->mb.mvcost, (const MV_CONTEXT *) cm->fc.mvc, flag);
+    }
+
+    // for each macroblock row in image
+    for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
+    {
+        int_mv best_ref_mv;
+
+        best_ref_mv.as_int = 0;
+
+        // reset above block coeffs
+        xd->up_available = (mb_row != 0);
+        recon_yoffset = (mb_row * recon_y_stride * 16);
+        recon_uvoffset = (mb_row * recon_uv_stride * 8);
+
+        // Set up limit values for motion vectors to prevent them extending outside the UMV borders
+        x->mv_row_min = -((mb_row * 16) + (VP8BORDERINPIXELS - 16));
+        x->mv_row_max = ((cm->mb_rows - 1 - mb_row) * 16) + (VP8BORDERINPIXELS - 16);
+
+
+        // for each macroblock col in image
+        for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+        {
+            int this_error;
+            int gf_motion_error = INT_MAX;
+            int use_dc_pred = (mb_col || mb_row) && (!mb_col || !mb_row);
+
+            xd->dst.y_buffer = new_yv12->y_buffer + recon_yoffset;
+            xd->dst.u_buffer = new_yv12->u_buffer + recon_uvoffset;
+            xd->dst.v_buffer = new_yv12->v_buffer + recon_uvoffset;
+            xd->left_available = (mb_col != 0);
+
+            //Copy current mb to a buffer
+            vp8_copy_mem16x16(x->src.y_buffer, x->src.y_stride, x->thismb, 16);
+
+            // do intra 16x16 prediction
+            this_error = vp8_encode_intra(cpi, x, use_dc_pred);
+
+            // "intrapenalty" below deals with situations where the intra and inter error scores are very low (eg a plain black frame)
+            // We do not have special cases in first pass for 0,0 and nearest etc so all inter modes carry an overhead cost estimate fot the mv.
+            // When the error score is very low this causes us to pick all or lots of INTRA modes and throw lots of key frames.
+            // This penalty adds a cost matching that of a 0,0 mv to the intra case.
+            this_error += intrapenalty;
+
+            // Cumulative intra error total
+            intra_error += (int64_t)this_error;
+
+            // Set up limit values for motion vectors to prevent them extending outside the UMV borders
+            x->mv_col_min = -((mb_col * 16) + (VP8BORDERINPIXELS - 16));
+            x->mv_col_max = ((cm->mb_cols - 1 - mb_col) * 16) + (VP8BORDERINPIXELS - 16);
+
+            // Other than for the first frame do a motion search
+            if (cm->current_video_frame > 0)
+            {
+                BLOCKD *d = &x->e_mbd.block[0];
+                MV tmp_mv = {0, 0};
+                int tmp_err;
+                int motion_error = INT_MAX;
+                int raw_motion_error = INT_MAX;
+
+                // Simple 0,0 motion with no mv overhead
+                zz_motion_search( cpi, x, cpi->last_frame_unscaled_source,
+                                  &raw_motion_error, lst_yv12, &motion_error,
+                                  recon_yoffset );
+                d->bmi.mv.as_mv.row = 0;
+                d->bmi.mv.as_mv.col = 0;
+
+                if (raw_motion_error < cpi->oxcf.encode_breakout)
+                    goto skip_motion_search;
+
+                // Test last reference frame using the previous best mv as the
+                // starting point (best reference) for the search
+                first_pass_motion_search(cpi, x, &best_ref_mv,
+                                        &d->bmi.mv.as_mv, lst_yv12,
+                                        &motion_error, recon_yoffset);
+
+                // If the current best reference mv is not centred on 0,0 then do a 0,0 based search as well
+                if (best_ref_mv.as_int)
+                {
+                   tmp_err = INT_MAX;
+                   first_pass_motion_search(cpi, x, &zero_ref_mv, &tmp_mv,
+                                     lst_yv12, &tmp_err, recon_yoffset);
+
+                   if ( tmp_err < motion_error )
+                   {
+                        motion_error = tmp_err;
+                        d->bmi.mv.as_mv.row = tmp_mv.row;
+                        d->bmi.mv.as_mv.col = tmp_mv.col;
+                   }
+                }
+
+                // Experimental search in a second reference frame ((0,0) based only)
+                if (cm->current_video_frame > 1)
+                {
+                    first_pass_motion_search(cpi, x, &zero_ref_mv, &tmp_mv, gld_yv12, &gf_motion_error, recon_yoffset);
+
+                    if ((gf_motion_error < motion_error) && (gf_motion_error < this_error))
+                    {
+                        second_ref_count++;
+                        //motion_error = gf_motion_error;
+                        //d->bmi.mv.as_mv.row = tmp_mv.row;
+                        //d->bmi.mv.as_mv.col = tmp_mv.col;
+                    }
+                    /*else
+                    {
+                        xd->pre.y_buffer = cm->last_frame.y_buffer + recon_yoffset;
+                        xd->pre.u_buffer = cm->last_frame.u_buffer + recon_uvoffset;
+                        xd->pre.v_buffer = cm->last_frame.v_buffer + recon_uvoffset;
+                    }*/
+
+
+                    // Reset to last frame as reference buffer
+                    xd->pre.y_buffer = lst_yv12->y_buffer + recon_yoffset;
+                    xd->pre.u_buffer = lst_yv12->u_buffer + recon_uvoffset;
+                    xd->pre.v_buffer = lst_yv12->v_buffer + recon_uvoffset;
+                }
+
+skip_motion_search:
+                /* Intra assumed best */
+                best_ref_mv.as_int = 0;
+
+                if (motion_error <= this_error)
+                {
+                    // Keep a count of cases where the inter and intra were
+                    // very close and very low. This helps with scene cut
+                    // detection for example in cropped clips with black bars
+                    // at the sides or top and bottom.
+                    if( (((this_error-intrapenalty) * 9) <=
+                         (motion_error*10)) &&
+                        (this_error < (2*intrapenalty)) )
+                    {
+                        neutral_count++;
+                    }
+
+                    d->bmi.mv.as_mv.row <<= 3;
+                    d->bmi.mv.as_mv.col <<= 3;
+                    this_error = motion_error;
+                    vp8_set_mbmode_and_mvs(x, NEWMV, &d->bmi.mv);
+                    vp8_encode_inter16x16y(x);
+                    sum_mvr += d->bmi.mv.as_mv.row;
+                    sum_mvr_abs += abs(d->bmi.mv.as_mv.row);
+                    sum_mvc += d->bmi.mv.as_mv.col;
+                    sum_mvc_abs += abs(d->bmi.mv.as_mv.col);
+                    sum_mvrs += d->bmi.mv.as_mv.row * d->bmi.mv.as_mv.row;
+                    sum_mvcs += d->bmi.mv.as_mv.col * d->bmi.mv.as_mv.col;
+                    intercount++;
+
+                    best_ref_mv.as_int = d->bmi.mv.as_int;
+
+                    // Was the vector non-zero
+                    if (d->bmi.mv.as_int)
+                    {
+                        mvcount++;
+
+                        // Was it different from the last non zero vector
+                        if ( d->bmi.mv.as_int != lastmv_as_int )
+                            new_mv_count++;
+                        lastmv_as_int = d->bmi.mv.as_int;
+
+                        // Does the Row vector point inwards or outwards
+                        if (mb_row < cm->mb_rows / 2)
+                        {
+                            if (d->bmi.mv.as_mv.row > 0)
+                                sum_in_vectors--;
+                            else if (d->bmi.mv.as_mv.row < 0)
+                                sum_in_vectors++;
+                        }
+                        else if (mb_row > cm->mb_rows / 2)
+                        {
+                            if (d->bmi.mv.as_mv.row > 0)
+                                sum_in_vectors++;
+                            else if (d->bmi.mv.as_mv.row < 0)
+                                sum_in_vectors--;
+                        }
+
+                        // Does the Row vector point inwards or outwards
+                        if (mb_col < cm->mb_cols / 2)
+                        {
+                            if (d->bmi.mv.as_mv.col > 0)
+                                sum_in_vectors--;
+                            else if (d->bmi.mv.as_mv.col < 0)
+                                sum_in_vectors++;
+                        }
+                        else if (mb_col > cm->mb_cols / 2)
+                        {
+                            if (d->bmi.mv.as_mv.col > 0)
+                                sum_in_vectors++;
+                            else if (d->bmi.mv.as_mv.col < 0)
+                                sum_in_vectors--;
+                        }
+                    }
+                }
+            }
+
+            coded_error += (int64_t)this_error;
+
+            // adjust to the next column of macroblocks
+            x->src.y_buffer += 16;
+            x->src.u_buffer += 8;
+            x->src.v_buffer += 8;
+
+            recon_yoffset += 16;
+            recon_uvoffset += 8;
+        }
+
+        // adjust to the next row of mbs
+        x->src.y_buffer += 16 * x->src.y_stride - 16 * cm->mb_cols;
+        x->src.u_buffer += 8 * x->src.uv_stride - 8 * cm->mb_cols;
+        x->src.v_buffer += 8 * x->src.uv_stride - 8 * cm->mb_cols;
+
+        //extend the recon for intra prediction
+        vp8_extend_mb_row(new_yv12, xd->dst.y_buffer + 16, xd->dst.u_buffer + 8, xd->dst.v_buffer + 8);
+        vp8_clear_system_state();  //__asm emms;
+    }
+
+    vp8_clear_system_state();  //__asm emms;
+    {
+        double weight = 0.0;
+
+        FIRSTPASS_STATS fps;
+
+        fps.frame      = cm->current_video_frame ;
+        fps.intra_error = intra_error >> 8;
+        fps.coded_error = coded_error >> 8;
+        weight = simple_weight(cpi->Source);
+
+
+        if (weight < 0.1)
+            weight = 0.1;
+
+        fps.ssim_weighted_pred_err = fps.coded_error * weight;
+
+        fps.pcnt_inter  = 0.0;
+        fps.pcnt_motion = 0.0;
+        fps.MVr        = 0.0;
+        fps.mvr_abs     = 0.0;
+        fps.MVc        = 0.0;
+        fps.mvc_abs     = 0.0;
+        fps.MVrv       = 0.0;
+        fps.MVcv       = 0.0;
+        fps.mv_in_out_count  = 0.0;
+        fps.new_mv_count = 0.0;
+        fps.count      = 1.0;
+
+        fps.pcnt_inter   = 1.0 * (double)intercount / cm->MBs;
+        fps.pcnt_second_ref = 1.0 * (double)second_ref_count / cm->MBs;
+        fps.pcnt_neutral = 1.0 * (double)neutral_count / cm->MBs;
+
+        if (mvcount > 0)
+        {
+            fps.MVr = (double)sum_mvr / (double)mvcount;
+            fps.mvr_abs = (double)sum_mvr_abs / (double)mvcount;
+            fps.MVc = (double)sum_mvc / (double)mvcount;
+            fps.mvc_abs = (double)sum_mvc_abs / (double)mvcount;
+            fps.MVrv = ((double)sum_mvrs - (fps.MVr * fps.MVr / (double)mvcount)) / (double)mvcount;
+            fps.MVcv = ((double)sum_mvcs - (fps.MVc * fps.MVc / (double)mvcount)) / (double)mvcount;
+            fps.mv_in_out_count = (double)sum_in_vectors / (double)(mvcount * 2);
+            fps.new_mv_count = new_mv_count;
+
+            fps.pcnt_motion = 1.0 * (double)mvcount / cpi->common.MBs;
+        }
+
+        // TODO:  handle the case when duration is set to 0, or something less
+        // than the full time between subsequent cpi->source_time_stamp s  .
+        fps.duration = cpi->source->ts_end
+                       - cpi->source->ts_start;
+
+        // don't want to do output stats with a stack variable!
+        memcpy(&cpi->twopass.this_frame_stats,
+               &fps,
+               sizeof(FIRSTPASS_STATS));
+        output_stats(cpi, cpi->output_pkt_list, &cpi->twopass.this_frame_stats);
+        accumulate_stats(&cpi->twopass.total_stats, &fps);
+    }
+
+    // Copy the previous Last Frame into the GF buffer if specific conditions for doing so are met
+    if ((cm->current_video_frame > 0) &&
+        (cpi->twopass.this_frame_stats.pcnt_inter > 0.20) &&
+        ((cpi->twopass.this_frame_stats.intra_error / cpi->twopass.this_frame_stats.coded_error) > 2.0))
+    {
+        vp8_yv12_copy_frame(lst_yv12, gld_yv12);
+    }
+
+    // swap frame pointers so last frame refers to the frame we just compressed
+    vp8_swap_yv12_buffer(lst_yv12, new_yv12);
+    vp8_yv12_extend_frame_borders(lst_yv12);
+
+    // Special case for the first frame. Copy into the GF buffer as a second reference.
+    if (cm->current_video_frame == 0)
+    {
+        vp8_yv12_copy_frame(lst_yv12, gld_yv12);
+    }
+
+
+    // use this to see what the first pass reconstruction looks like
+    if (0)
+    {
+        char filename[512];
+        FILE *recon_file;
+        sprintf(filename, "enc%04d.yuv", (int) cm->current_video_frame);
+
+        if (cm->current_video_frame == 0)
+            recon_file = fopen(filename, "wb");
+        else
+            recon_file = fopen(filename, "ab");
+
+        if(fwrite(lst_yv12->buffer_alloc, lst_yv12->frame_size, 1, recon_file));
+        fclose(recon_file);
+    }
+
+    cm->current_video_frame++;
+
+}
+extern const int vp8_bits_per_mb[2][QINDEX_RANGE];
+
+// Estimate a cost per mb attributable to overheads such as the coding of
+// modes and motion vectors.
+// Currently simplistic in its assumptions for testing.
+//
+
+
+static double bitcost( double prob )
+{
+    return -(log( prob ) / log( 2.0 ));
+}
+static int64_t estimate_modemvcost(VP8_COMP *cpi,
+                                     FIRSTPASS_STATS * fpstats)
+{
+    int mv_cost;
+    int mode_cost;
+
+    double av_pct_inter = fpstats->pcnt_inter / fpstats->count;
+    double av_pct_motion = fpstats->pcnt_motion / fpstats->count;
+    double av_intra = (1.0 - av_pct_inter);
+
+    double zz_cost;
+    double motion_cost;
+    double intra_cost;
+
+    zz_cost = bitcost(av_pct_inter - av_pct_motion);
+    motion_cost = bitcost(av_pct_motion);
+    intra_cost = bitcost(av_intra);
+
+    // Estimate of extra bits per mv overhead for mbs
+    // << 9 is the normalization to the (bits * 512) used in vp8_bits_per_mb
+    mv_cost = ((int)(fpstats->new_mv_count / fpstats->count) * 8) << 9;
+
+    // Crude estimate of overhead cost from modes
+    // << 9 is the normalization to (bits * 512) used in vp8_bits_per_mb
+    mode_cost =
+        (int)( ( ((av_pct_inter - av_pct_motion) * zz_cost) +
+                 (av_pct_motion * motion_cost) +
+                 (av_intra * intra_cost) ) * cpi->common.MBs ) << 9;
+
+    return mv_cost + mode_cost;
+}
+
+static double calc_correction_factor( double err_per_mb,
+                                      double err_devisor,
+                                      double pt_low,
+                                      double pt_high,
+                                      int Q )
+{
+    double power_term;
+    double error_term = err_per_mb / err_devisor;
+    double correction_factor;
+
+    // Adjustment based on Q to power term.
+    power_term = pt_low + (Q * 0.01);
+    power_term = (power_term > pt_high) ? pt_high : power_term;
+
+    // Adjustments to error term
+    // TBD
+
+    // Calculate correction factor
+    correction_factor = pow(error_term, power_term);
+
+    // Clip range
+    correction_factor =
+        (correction_factor < 0.05)
+            ? 0.05 : (correction_factor > 5.0) ? 5.0 : correction_factor;
+
+    return correction_factor;
+}
+
+static int estimate_max_q(VP8_COMP *cpi,
+                          FIRSTPASS_STATS * fpstats,
+                          int section_target_bandwitdh,
+                          int overhead_bits )
+{
+    int Q;
+    int num_mbs = cpi->common.MBs;
+    int target_norm_bits_per_mb;
+
+    double section_err = (fpstats->coded_error / fpstats->count);
+    double err_per_mb = section_err / num_mbs;
+    double err_correction_factor;
+    double speed_correction = 1.0;
+    int overhead_bits_per_mb;
+
+    if (section_target_bandwitdh <= 0)
+        return cpi->twopass.maxq_max_limit;          // Highest value allowed
+
+    target_norm_bits_per_mb =
+        (section_target_bandwitdh < (1 << 20))
+            ? (512 * section_target_bandwitdh) / num_mbs
+            : 512 * (section_target_bandwitdh / num_mbs);
+
+    // Calculate a corrective factor based on a rolling ratio of bits spent
+    // vs target bits
+    if ((cpi->rolling_target_bits > 0) &&
+        (cpi->active_worst_quality < cpi->worst_quality))
+    {
+        double rolling_ratio;
+
+        rolling_ratio = (double)cpi->rolling_actual_bits /
+                        (double)cpi->rolling_target_bits;
+
+        if (rolling_ratio < 0.95)
+            cpi->twopass.est_max_qcorrection_factor -= 0.005;
+        else if (rolling_ratio > 1.05)
+            cpi->twopass.est_max_qcorrection_factor += 0.005;
+
+        cpi->twopass.est_max_qcorrection_factor =
+            (cpi->twopass.est_max_qcorrection_factor < 0.1)
+                ? 0.1
+                : (cpi->twopass.est_max_qcorrection_factor > 10.0)
+                    ? 10.0 : cpi->twopass.est_max_qcorrection_factor;
+    }
+
+    // Corrections for higher compression speed settings
+    // (reduced compression expected)
+    if ((cpi->compressor_speed == 3) || (cpi->compressor_speed == 1))
+    {
+        if (cpi->oxcf.cpu_used <= 5)
+            speed_correction = 1.04 + (cpi->oxcf.cpu_used * 0.04);
+        else
+            speed_correction = 1.25;
+    }
+
+    // Estimate of overhead bits per mb
+    // Correction to overhead bits for min allowed Q.
+    overhead_bits_per_mb = overhead_bits / num_mbs;
+    overhead_bits_per_mb *= pow( 0.98, (double)cpi->twopass.maxq_min_limit );
+
+    // Try and pick a max Q that will be high enough to encode the
+    // content at the given rate.
+    for (Q = cpi->twopass.maxq_min_limit; Q < cpi->twopass.maxq_max_limit; Q++)
+    {
+        int bits_per_mb_at_this_q;
+
+        // Error per MB based correction factor
+        err_correction_factor =
+            calc_correction_factor(err_per_mb, 150.0, 0.40, 0.90, Q);
+
+        bits_per_mb_at_this_q =
+            vp8_bits_per_mb[INTER_FRAME][Q] + overhead_bits_per_mb;
+
+        bits_per_mb_at_this_q = (int)(.5 + err_correction_factor
+            * speed_correction * cpi->twopass.est_max_qcorrection_factor
+            * cpi->twopass.section_max_qfactor
+            * (double)bits_per_mb_at_this_q);
+
+        // Mode and motion overhead
+        // As Q rises in real encode loop rd code will force overhead down
+        // We make a crude adjustment for this here as *.98 per Q step.
+        overhead_bits_per_mb = (int)((double)overhead_bits_per_mb * 0.98);
+
+        if (bits_per_mb_at_this_q <= target_norm_bits_per_mb)
+            break;
+    }
+
+    // Restriction on active max q for constrained quality mode.
+    if ( (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
+         (Q < cpi->cq_target_quality) )
+    {
+        Q = cpi->cq_target_quality;
+    }
+
+    // Adjust maxq_min_limit and maxq_max_limit limits based on
+    // averaga q observed in clip for non kf/gf.arf frames
+    // Give average a chance to settle though.
+    if ( (cpi->ni_frames >
+                  ((unsigned int)cpi->twopass.total_stats.count >> 8)) &&
+         (cpi->ni_frames > 150) )
+    {
+        cpi->twopass.maxq_max_limit = ((cpi->ni_av_qi + 32) < cpi->worst_quality)
+                                  ? (cpi->ni_av_qi + 32) : cpi->worst_quality;
+        cpi->twopass.maxq_min_limit = ((cpi->ni_av_qi - 32) > cpi->best_quality)
+                                  ? (cpi->ni_av_qi - 32) : cpi->best_quality;
+    }
+
+    return Q;
+}
+
+// For cq mode estimate a cq level that matches the observed
+// complexity and data rate.
+static int estimate_cq( VP8_COMP *cpi,
+                        FIRSTPASS_STATS * fpstats,
+                        int section_target_bandwitdh,
+                        int overhead_bits )
+{
+    int Q;
+    int num_mbs = cpi->common.MBs;
+    int target_norm_bits_per_mb;
+
+    double section_err = (fpstats->coded_error / fpstats->count);
+    double err_per_mb = section_err / num_mbs;
+    double err_correction_factor;
+    double speed_correction = 1.0;
+    double clip_iiratio;
+    double clip_iifactor;
+    int overhead_bits_per_mb;
+
+    if (0)
+    {
+        FILE *f = fopen("epmp.stt", "a");
+        fprintf(f, "%10.2f\n", err_per_mb );
+        fclose(f);
+    }
+
+    target_norm_bits_per_mb = (section_target_bandwitdh < (1 << 20))
+                              ? (512 * section_target_bandwitdh) / num_mbs
+                              : 512 * (section_target_bandwitdh / num_mbs);
+
+    // Estimate of overhead bits per mb
+    overhead_bits_per_mb = overhead_bits / num_mbs;
+
+    // Corrections for higher compression speed settings
+    // (reduced compression expected)
+    if ((cpi->compressor_speed == 3) || (cpi->compressor_speed == 1))
+    {
+        if (cpi->oxcf.cpu_used <= 5)
+            speed_correction = 1.04 + (cpi->oxcf.cpu_used * 0.04);
+        else
+            speed_correction = 1.25;
+    }
+
+    // II ratio correction factor for clip as a whole
+    clip_iiratio = cpi->twopass.total_stats.intra_error /
+                   DOUBLE_DIVIDE_CHECK(cpi->twopass.total_stats.coded_error);
+    clip_iifactor = 1.0 - ((clip_iiratio - 10.0) * 0.025);
+    if (clip_iifactor < 0.80)
+        clip_iifactor = 0.80;
+
+    // Try and pick a Q that can encode the content at the given rate.
+    for (Q = 0; Q < MAXQ; Q++)
+    {
+        int bits_per_mb_at_this_q;
+
+        // Error per MB based correction factor
+        err_correction_factor =
+            calc_correction_factor(err_per_mb, 100.0, 0.40, 0.90, Q);
+
+        bits_per_mb_at_this_q =
+            vp8_bits_per_mb[INTER_FRAME][Q] + overhead_bits_per_mb;
+
+        bits_per_mb_at_this_q =
+            (int)( .5 + err_correction_factor *
+                        speed_correction *
+                        clip_iifactor *
+                        (double)bits_per_mb_at_this_q);
+
+        // Mode and motion overhead
+        // As Q rises in real encode loop rd code will force overhead down
+        // We make a crude adjustment for this here as *.98 per Q step.
+        overhead_bits_per_mb = (int)((double)overhead_bits_per_mb * 0.98);
+
+        if (bits_per_mb_at_this_q <= target_norm_bits_per_mb)
+            break;
+    }
+
+    // Clip value to range "best allowed to (worst allowed - 1)"
+    Q = cq_level[Q];
+    if ( Q >= cpi->worst_quality )
+        Q = cpi->worst_quality - 1;
+    if ( Q < cpi->best_quality )
+        Q = cpi->best_quality;
+
+    return Q;
+}
+
+static int estimate_q(VP8_COMP *cpi, double section_err, int section_target_bandwitdh)
+{
+    int Q;
+    int num_mbs = cpi->common.MBs;
+    int target_norm_bits_per_mb;
+
+    double err_per_mb = section_err / num_mbs;
+    double err_correction_factor;
+    double speed_correction = 1.0;
+
+    target_norm_bits_per_mb = (section_target_bandwitdh < (1 << 20)) ? (512 * section_target_bandwitdh) / num_mbs : 512 * (section_target_bandwitdh / num_mbs);
+
+    // Corrections for higher compression speed settings (reduced compression expected)
+    if ((cpi->compressor_speed == 3) || (cpi->compressor_speed == 1))
+    {
+        if (cpi->oxcf.cpu_used <= 5)
+            speed_correction = 1.04 + (cpi->oxcf.cpu_used * 0.04);
+        else
+            speed_correction = 1.25;
+    }
+
+    // Try and pick a Q that can encode the content at the given rate.
+    for (Q = 0; Q < MAXQ; Q++)
+    {
+        int bits_per_mb_at_this_q;
+
+        // Error per MB based correction factor
+        err_correction_factor =
+            calc_correction_factor(err_per_mb, 150.0, 0.40, 0.90, Q);
+
+        bits_per_mb_at_this_q =
+            (int)( .5 + ( err_correction_factor *
+                          speed_correction *
+                          cpi->twopass.est_max_qcorrection_factor *
+                          (double)vp8_bits_per_mb[INTER_FRAME][Q] / 1.0 ) );
+
+        if (bits_per_mb_at_this_q <= target_norm_bits_per_mb)
+            break;
+    }
+
+    return Q;
+}
+
+// Estimate a worst case Q for a KF group
+static int estimate_kf_group_q(VP8_COMP *cpi, double section_err, int section_target_bandwitdh, double group_iiratio)
+{
+    int Q;
+    int num_mbs = cpi->common.MBs;
+    int target_norm_bits_per_mb = (512 * section_target_bandwitdh) / num_mbs;
+    int bits_per_mb_at_this_q;
+
+    double err_per_mb = section_err / num_mbs;
+    double err_correction_factor;
+    double speed_correction = 1.0;
+    double current_spend_ratio = 1.0;
+
+    double pow_highq = (POW1 < 0.6) ? POW1 + 0.3 : 0.90;
+    double pow_lowq = (POW1 < 0.7) ? POW1 + 0.1 : 0.80;
+
+    double iiratio_correction_factor = 1.0;
+
+    double combined_correction_factor;
+
+    // Trap special case where the target is <= 0
+    if (target_norm_bits_per_mb <= 0)
+        return MAXQ * 2;
+
+    // Calculate a corrective factor based on a rolling ratio of bits spent vs target bits
+    // This is clamped to the range 0.1 to 10.0
+    if (cpi->long_rolling_target_bits <= 0)
+        current_spend_ratio = 10.0;
+    else
+    {
+        current_spend_ratio = (double)cpi->long_rolling_actual_bits / (double)cpi->long_rolling_target_bits;
+        current_spend_ratio = (current_spend_ratio > 10.0) ? 10.0 : (current_spend_ratio < 0.1) ? 0.1 : current_spend_ratio;
+    }
+
+    // Calculate a correction factor based on the quality of prediction in the sequence as indicated by intra_inter error score ratio (IIRatio)
+    // The idea here is to favour subsampling in the hardest sections vs the easyest.
+    iiratio_correction_factor = 1.0 - ((group_iiratio - 6.0) * 0.1);
+
+    if (iiratio_correction_factor < 0.5)
+        iiratio_correction_factor = 0.5;
+
+    // Corrections for higher compression speed settings (reduced compression expected)
+    if ((cpi->compressor_speed == 3) || (cpi->compressor_speed == 1))
+    {
+        if (cpi->oxcf.cpu_used <= 5)
+            speed_correction = 1.04 + (cpi->oxcf.cpu_used * 0.04);
+        else
+            speed_correction = 1.25;
+    }
+
+    // Combine the various factors calculated above
+    combined_correction_factor = speed_correction * iiratio_correction_factor * current_spend_ratio;
+
+    // Try and pick a Q that should be high enough to encode the content at the given rate.
+    for (Q = 0; Q < MAXQ; Q++)
+    {
+        // Error per MB based correction factor
+        err_correction_factor =
+            calc_correction_factor(err_per_mb, 150.0, pow_lowq, pow_highq, Q);
+
+        bits_per_mb_at_this_q =
+            (int)(.5 + ( err_correction_factor *
+                         combined_correction_factor *
+                         (double)vp8_bits_per_mb[INTER_FRAME][Q]) );
+
+        if (bits_per_mb_at_this_q <= target_norm_bits_per_mb)
+            break;
+    }
+
+    // If we could not hit the target even at Max Q then estimate what Q would have bee required
+    while ((bits_per_mb_at_this_q > target_norm_bits_per_mb)  && (Q < (MAXQ * 2)))
+    {
+
+        bits_per_mb_at_this_q = (int)(0.96 * bits_per_mb_at_this_q);
+        Q++;
+    }
+
+    if (0)
+    {
+        FILE *f = fopen("estkf_q.stt", "a");
+        fprintf(f, "%8d %8d %8d %8.2f %8.3f %8.2f %8.3f %8.3f %8.3f %8d\n", cpi->common.current_video_frame, bits_per_mb_at_this_q,
+                target_norm_bits_per_mb, err_per_mb, err_correction_factor,
+                current_spend_ratio, group_iiratio, iiratio_correction_factor,
+                (double)cpi->buffer_level / (double)cpi->oxcf.optimal_buffer_level, Q);
+        fclose(f);
+    }
+
+    return Q;
+}
+
+extern void vp8_new_frame_rate(VP8_COMP *cpi, double framerate);
+
+void vp8_init_second_pass(VP8_COMP *cpi)
+{
+    FIRSTPASS_STATS this_frame;
+    FIRSTPASS_STATS *start_pos;
+
+    double two_pass_min_rate = (double)(cpi->oxcf.target_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100);
+
+    zero_stats(&cpi->twopass.total_stats);
+    zero_stats(&cpi->twopass.total_left_stats);
+
+    if (!cpi->twopass.stats_in_end)
+        return;
+
+    cpi->twopass.total_stats = *cpi->twopass.stats_in_end;
+    cpi->twopass.total_left_stats = cpi->twopass.total_stats;
+
+    // each frame can have a different duration, as the frame rate in the source
+    // isn't guaranteed to be constant.   The frame rate prior to the first frame
+    // encoded in the second pass is a guess.  However the sum duration is not.
+    // Its calculated based on the actual durations of all frames from the first
+    // pass.
+    vp8_new_frame_rate(cpi, 10000000.0 * cpi->twopass.total_stats.count / cpi->twopass.total_stats.duration);
+
+    cpi->output_frame_rate = cpi->frame_rate;
+    cpi->twopass.bits_left = (int64_t)(cpi->twopass.total_stats.duration * cpi->oxcf.target_bandwidth / 10000000.0) ;
+    cpi->twopass.bits_left -= (int64_t)(cpi->twopass.total_stats.duration * two_pass_min_rate / 10000000.0);
+
+    // Calculate a minimum intra value to be used in determining the IIratio
+    // scores used in the second pass. We have this minimum to make sure
+    // that clips that are static but "low complexity" in the intra domain
+    // are still boosted appropriately for KF/GF/ARF
+    cpi->twopass.kf_intra_err_min = KF_MB_INTRA_MIN * cpi->common.MBs;
+    cpi->twopass.gf_intra_err_min = GF_MB_INTRA_MIN * cpi->common.MBs;
+
+    // Scan the first pass file and calculate an average Intra / Inter error score ratio for the sequence
+    {
+        double sum_iiratio = 0.0;
+        double IIRatio;
+
+        start_pos = cpi->twopass.stats_in;               // Note starting "file" position
+
+        while (input_stats(cpi, &this_frame) != EOF)
+        {
+            IIRatio = this_frame.intra_error / DOUBLE_DIVIDE_CHECK(this_frame.coded_error);
+            IIRatio = (IIRatio < 1.0) ? 1.0 : (IIRatio > 20.0) ? 20.0 : IIRatio;
+            sum_iiratio += IIRatio;
+        }
+
+        cpi->twopass.avg_iiratio = sum_iiratio / DOUBLE_DIVIDE_CHECK((double)cpi->twopass.total_stats.count);
+
+        // Reset file position
+        reset_fpf_position(cpi, start_pos);
+    }
+
+    // Scan the first pass file and calculate a modified total error based upon the bias/power function
+    // used to allocate bits
+    {
+        start_pos = cpi->twopass.stats_in;               // Note starting "file" position
+
+        cpi->twopass.modified_error_total = 0.0;
+        cpi->twopass.modified_error_used = 0.0;
+
+        while (input_stats(cpi, &this_frame) != EOF)
+        {
+            cpi->twopass.modified_error_total += calculate_modified_err(cpi, &this_frame);
+        }
+        cpi->twopass.modified_error_left = cpi->twopass.modified_error_total;
+
+        reset_fpf_position(cpi, start_pos);            // Reset file position
+
+    }
+}
+
+void vp8_end_second_pass(VP8_COMP *cpi)
+{
+}
+
+// This function gives and estimate of how badly we believe
+// the prediction quality is decaying from frame to frame.
+static double get_prediction_decay_rate(VP8_COMP *cpi, FIRSTPASS_STATS *next_frame)
+{
+    double prediction_decay_rate;
+    double motion_decay;
+    double motion_pct = next_frame->pcnt_motion;
+
+    // Initial basis is the % mbs inter coded
+    prediction_decay_rate = next_frame->pcnt_inter;
+
+    // High % motion -> somewhat higher decay rate
+    motion_decay = (1.0 - (motion_pct / 20.0));
+    if (motion_decay < prediction_decay_rate)
+        prediction_decay_rate = motion_decay;
+
+    // Adjustment to decay rate based on speed of motion
+    {
+        double this_mv_rabs;
+        double this_mv_cabs;
+        double distance_factor;
+
+        this_mv_rabs = fabs(next_frame->mvr_abs * motion_pct);
+        this_mv_cabs = fabs(next_frame->mvc_abs * motion_pct);
+
+        distance_factor = sqrt((this_mv_rabs * this_mv_rabs) +
+                               (this_mv_cabs * this_mv_cabs)) / 250.0;
+        distance_factor = ((distance_factor > 1.0)
+                                ? 0.0 : (1.0 - distance_factor));
+        if (distance_factor < prediction_decay_rate)
+            prediction_decay_rate = distance_factor;
+    }
+
+    return prediction_decay_rate;
+}
+
+// Function to test for a condition where a complex transition is followed
+// by a static section. For example in slide shows where there is a fade
+// between slides. This is to help with more optimal kf and gf positioning.
+static int detect_transition_to_still(
+    VP8_COMP *cpi,
+    int frame_interval,
+    int still_interval,
+    double loop_decay_rate,
+    double decay_accumulator )
+{
+    int trans_to_still = 0;
+
+    // Break clause to detect very still sections after motion
+    // For example a static image after a fade or other transition
+    // instead of a clean scene cut.
+    if ( (frame_interval > MIN_GF_INTERVAL) &&
+         (loop_decay_rate >= 0.999) &&
+         (decay_accumulator < 0.9) )
+    {
+        int j;
+        FIRSTPASS_STATS * position = cpi->twopass.stats_in;
+        FIRSTPASS_STATS tmp_next_frame;
+        double decay_rate;
+
+        // Look ahead a few frames to see if static condition
+        // persists...
+        for ( j = 0; j < still_interval; j++ )
+        {
+            if (EOF == input_stats(cpi, &tmp_next_frame))
+                break;
+
+            decay_rate = get_prediction_decay_rate(cpi, &tmp_next_frame);
+            if ( decay_rate < 0.999 )
+                break;
+        }
+        // Reset file position
+        reset_fpf_position(cpi, position);
+
+        // Only if it does do we signal a transition to still
+        if ( j == still_interval )
+            trans_to_still = 1;
+    }
+
+    return trans_to_still;
+}
+
+// This function detects a flash through the high relative pcnt_second_ref
+// score in the frame following a flash frame. The offset passed in should
+// reflect this
+static int detect_flash( VP8_COMP *cpi, int offset )
+{
+    FIRSTPASS_STATS next_frame;
+
+    int flash_detected = 0;
+
+    // Read the frame data.
+    // The return is 0 (no flash detected) if not a valid frame
+    if ( read_frame_stats(cpi, &next_frame, offset) != EOF )
+    {
+        // What we are looking for here is a situation where there is a
+        // brief break in prediction (such as a flash) but subsequent frames
+        // are reasonably well predicted by an earlier (pre flash) frame.
+        // The recovery after a flash is indicated by a high pcnt_second_ref
+        // comapred to pcnt_inter.
+        if ( (next_frame.pcnt_second_ref > next_frame.pcnt_inter) &&
+             (next_frame.pcnt_second_ref >= 0.5 ) )
+        {
+            flash_detected = 1;
+
+            /*if (1)
+            {
+                FILE *f = fopen("flash.stt", "a");
+                fprintf(f, "%8.0f %6.2f %6.2f\n",
+                    next_frame.frame,
+                    next_frame.pcnt_inter,
+                    next_frame.pcnt_second_ref);
+                fclose(f);
+            }*/
+        }
+    }
+
+    return flash_detected;
+}
+
+// Update the motion related elements to the GF arf boost calculation
+static void accumulate_frame_motion_stats(
+    VP8_COMP *cpi,
+    FIRSTPASS_STATS * this_frame,
+    double * this_frame_mv_in_out,
+    double * mv_in_out_accumulator,
+    double * abs_mv_in_out_accumulator,
+    double * mv_ratio_accumulator )
+{
+    //double this_frame_mv_in_out;
+    double this_frame_mvr_ratio;
+    double this_frame_mvc_ratio;
+    double motion_pct;
+
+    // Accumulate motion stats.
+    motion_pct = this_frame->pcnt_motion;
+
+    // Accumulate Motion In/Out of frame stats
+    *this_frame_mv_in_out = this_frame->mv_in_out_count * motion_pct;
+    *mv_in_out_accumulator += this_frame->mv_in_out_count * motion_pct;
+    *abs_mv_in_out_accumulator +=
+        fabs(this_frame->mv_in_out_count * motion_pct);
+
+    // Accumulate a measure of how uniform (or conversely how random)
+    // the motion field is. (A ratio of absmv / mv)
+    if (motion_pct > 0.05)
+    {
+        this_frame_mvr_ratio = fabs(this_frame->mvr_abs) /
+                               DOUBLE_DIVIDE_CHECK(fabs(this_frame->MVr));
+
+        this_frame_mvc_ratio = fabs(this_frame->mvc_abs) /
+                               DOUBLE_DIVIDE_CHECK(fabs(this_frame->MVc));
+
+         *mv_ratio_accumulator +=
+            (this_frame_mvr_ratio < this_frame->mvr_abs)
+                ? (this_frame_mvr_ratio * motion_pct)
+                : this_frame->mvr_abs * motion_pct;
+
+        *mv_ratio_accumulator +=
+            (this_frame_mvc_ratio < this_frame->mvc_abs)
+                ? (this_frame_mvc_ratio * motion_pct)
+                : this_frame->mvc_abs * motion_pct;
+
+    }
+}
+
+// Calculate a baseline boost number for the current frame.
+static double calc_frame_boost(
+    VP8_COMP *cpi,
+    FIRSTPASS_STATS * this_frame,
+    double this_frame_mv_in_out )
+{
+    double frame_boost;
+
+    // Underlying boost factor is based on inter intra error ratio
+    if (this_frame->intra_error > cpi->twopass.gf_intra_err_min)
+        frame_boost = (IIFACTOR * this_frame->intra_error /
+                      DOUBLE_DIVIDE_CHECK(this_frame->coded_error));
+    else
+        frame_boost = (IIFACTOR * cpi->twopass.gf_intra_err_min /
+                      DOUBLE_DIVIDE_CHECK(this_frame->coded_error));
+
+    // Increase boost for frames where new data coming into frame
+    // (eg zoom out). Slightly reduce boost if there is a net balance
+    // of motion out of the frame (zoom in).
+    // The range for this_frame_mv_in_out is -1.0 to +1.0
+    if (this_frame_mv_in_out > 0.0)
+        frame_boost += frame_boost * (this_frame_mv_in_out * 2.0);
+    // In extreme case boost is halved
+    else
+        frame_boost += frame_boost * (this_frame_mv_in_out / 2.0);
+
+    // Clip to maximum
+    if (frame_boost > GF_RMAX)
+        frame_boost = GF_RMAX;
+
+    return frame_boost;
+}
+
+#if NEW_BOOST
+static int calc_arf_boost(
+    VP8_COMP *cpi,
+    int offset,
+    int f_frames,
+    int b_frames,
+    int *f_boost,
+    int *b_boost )
+{
+    FIRSTPASS_STATS this_frame;
+
+    int i;
+    double boost_score = 0.0;
+    double mv_ratio_accumulator = 0.0;
+    double decay_accumulator = 1.0;
+    double this_frame_mv_in_out = 0.0;
+    double mv_in_out_accumulator = 0.0;
+    double abs_mv_in_out_accumulator = 0.0;
+    double r;
+    int flash_detected = 0;
+
+    // Search forward from the proposed arf/next gf position
+    for ( i = 0; i < f_frames; i++ )
+    {
+        if ( read_frame_stats(cpi, &this_frame, (i+offset)) == EOF )
+            break;
+
+        // Update the motion related elements to the boost calculation
+        accumulate_frame_motion_stats( cpi, &this_frame,
+            &this_frame_mv_in_out, &mv_in_out_accumulator,
+            &abs_mv_in_out_accumulator, &mv_ratio_accumulator );
+
+        // Calculate the baseline boost number for this frame
+        r = calc_frame_boost( cpi, &this_frame, this_frame_mv_in_out );
+
+        // We want to discount the the flash frame itself and the recovery
+        // frame that follows as both will have poor scores.
+        flash_detected = detect_flash(cpi, (i+offset)) ||
+                         detect_flash(cpi, (i+offset+1));
+
+        // Cumulative effect of prediction quality decay
+        if ( !flash_detected )
+        {
+            decay_accumulator =
+                decay_accumulator *
+                get_prediction_decay_rate(cpi, &this_frame);
+            decay_accumulator =
+                decay_accumulator < 0.1 ? 0.1 : decay_accumulator;
+        }
+        boost_score += (decay_accumulator * r);
+
+        // Break out conditions.
+        if  ( (!flash_detected) &&
+              ((mv_ratio_accumulator > 100.0) ||
+               (abs_mv_in_out_accumulator > 3.0) ||
+               (mv_in_out_accumulator < -2.0) ) )
+        {
+            break;
+        }
+    }
+
+    *f_boost = (int)(boost_score * 100.0) >> 4;
+
+    // Reset for backward looking loop
+    boost_score = 0.0;
+    mv_ratio_accumulator = 0.0;
+    decay_accumulator = 1.0;
+    this_frame_mv_in_out = 0.0;
+    mv_in_out_accumulator = 0.0;
+    abs_mv_in_out_accumulator = 0.0;
+
+    // Search forward from the proposed arf/next gf position
+    for ( i = -1; i >= -b_frames; i-- )
+    {
+        if ( read_frame_stats(cpi, &this_frame, (i+offset)) == EOF )
+            break;
+
+        // Update the motion related elements to the boost calculation
+        accumulate_frame_motion_stats( cpi, &this_frame,
+            &this_frame_mv_in_out, &mv_in_out_accumulator,
+            &abs_mv_in_out_accumulator, &mv_ratio_accumulator );
+
+        // Calculate the baseline boost number for this frame
+        r = calc_frame_boost( cpi, &this_frame, this_frame_mv_in_out );
+
+        // We want to discount the the flash frame itself and the recovery
+        // frame that follows as both will have poor scores.
+        flash_detected = detect_flash(cpi, (i+offset)) ||
+                         detect_flash(cpi, (i+offset+1));
+
+        // Cumulative effect of prediction quality decay
+        if ( !flash_detected )
+        {
+            decay_accumulator =
+                decay_accumulator *
+                get_prediction_decay_rate(cpi, &this_frame);
+            decay_accumulator =
+                decay_accumulator < 0.1 ? 0.1 : decay_accumulator;
+        }
+
+        boost_score += (decay_accumulator * r);
+
+        // Break out conditions.
+        if  ( (!flash_detected) &&
+              ((mv_ratio_accumulator > 100.0) ||
+               (abs_mv_in_out_accumulator > 3.0) ||
+               (mv_in_out_accumulator < -2.0) ) )
+        {
+            break;
+        }
+    }
+    *b_boost = (int)(boost_score * 100.0) >> 4;
+
+    return (*f_boost + *b_boost);
+}
+#endif
+
+// Analyse and define a gf/arf group .
+static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
+{
+    FIRSTPASS_STATS next_frame;
+    FIRSTPASS_STATS *start_pos;
+    int i;
+    double r;
+    double boost_score = 0.0;
+    double old_boost_score = 0.0;
+    double gf_group_err = 0.0;
+    double gf_first_frame_err = 0.0;
+    double mod_frame_err = 0.0;
+
+    double mv_ratio_accumulator = 0.0;
+    double decay_accumulator = 1.0;
+
+    double loop_decay_rate = 1.00;          // Starting decay rate
+
+    double this_frame_mv_in_out = 0.0;
+    double mv_in_out_accumulator = 0.0;
+    double abs_mv_in_out_accumulator = 0.0;
+    double mod_err_per_mb_accumulator = 0.0;
+
+    int max_bits = frame_max_bits(cpi);     // Max for a single frame
+
+    unsigned int allow_alt_ref =
+                    cpi->oxcf.play_alternate && cpi->oxcf.lag_in_frames;
+
+    int alt_boost = 0;
+    int f_boost = 0;
+    int b_boost = 0;
+    int flash_detected;
+
+    cpi->twopass.gf_group_bits = 0;
+    cpi->twopass.gf_decay_rate = 0;
+
+    vp8_clear_system_state();  //__asm emms;
+
+    start_pos = cpi->twopass.stats_in;
+
+    vpx_memset(&next_frame, 0, sizeof(next_frame)); // assure clean
+
+    // Load stats for the current frame.
+    mod_frame_err = calculate_modified_err(cpi, this_frame);
+
+    // Note the error of the frame at the start of the group (this will be
+    // the GF frame error if we code a normal gf
+    gf_first_frame_err = mod_frame_err;
+
+    // Special treatment if the current frame is a key frame (which is also
+    // a gf). If it is then its error score (and hence bit allocation) need
+    // to be subtracted out from the calculation for the GF group
+    if (cpi->common.frame_type == KEY_FRAME)
+        gf_group_err -= gf_first_frame_err;
+
+    // Scan forward to try and work out how many frames the next gf group
+    // should contain and what level of boost is appropriate for the GF
+    // or ARF that will be coded with the group
+    i = 0;
+
+    while (((i < cpi->twopass.static_scene_max_gf_interval) ||
+            ((cpi->twopass.frames_to_key - i) < MIN_GF_INTERVAL)) &&
+           (i < cpi->twopass.frames_to_key))
+    {
+        i++;    // Increment the loop counter
+
+        // Accumulate error score of frames in this gf group
+        mod_frame_err = calculate_modified_err(cpi, this_frame);
+
+        gf_group_err += mod_frame_err;
+
+        mod_err_per_mb_accumulator +=
+            mod_frame_err / DOUBLE_DIVIDE_CHECK((double)cpi->common.MBs);
+
+        if (EOF == input_stats(cpi, &next_frame))
+            break;
+
+        // Test for the case where there is a brief flash but the prediction
+        // quality back to an earlier frame is then restored.
+        flash_detected = detect_flash(cpi, 0);
+
+        // Update the motion related elements to the boost calculation
+        accumulate_frame_motion_stats( cpi, &next_frame,
+            &this_frame_mv_in_out, &mv_in_out_accumulator,
+            &abs_mv_in_out_accumulator, &mv_ratio_accumulator );
+
+        // Calculate a baseline boost number for this frame
+        r = calc_frame_boost( cpi, &next_frame, this_frame_mv_in_out );
+
+        // Cumulative effect of prediction quality decay
+        if ( !flash_detected )
+        {
+            loop_decay_rate = get_prediction_decay_rate(cpi, &next_frame);
+            decay_accumulator = decay_accumulator * loop_decay_rate;
+            decay_accumulator =
+                decay_accumulator < 0.1 ? 0.1 : decay_accumulator;
+        }
+        boost_score += (decay_accumulator * r);
+
+        // Break clause to detect very still sections after motion
+        // For example a staic image after a fade or other transition.
+        if ( detect_transition_to_still( cpi, i, 5,
+                                         loop_decay_rate,
+                                         decay_accumulator ) )
+        {
+            allow_alt_ref = 0;
+            boost_score = old_boost_score;
+            break;
+        }
+
+        // Break out conditions.
+        if  (
+            // Break at cpi->max_gf_interval unless almost totally static
+            (i >= cpi->max_gf_interval && (decay_accumulator < 0.995)) ||
+            (
+                // Dont break out with a very short interval
+                (i > MIN_GF_INTERVAL) &&
+                // Dont break out very close to a key frame
+                ((cpi->twopass.frames_to_key - i) >= MIN_GF_INTERVAL) &&
+                ((boost_score > 20.0) || (next_frame.pcnt_inter < 0.75)) &&
+                (!flash_detected) &&
+                ((mv_ratio_accumulator > 100.0) ||
+                 (abs_mv_in_out_accumulator > 3.0) ||
+                 (mv_in_out_accumulator < -2.0) ||
+                 ((boost_score - old_boost_score) < 2.0))
+            ) )
+        {
+            boost_score = old_boost_score;
+            break;
+        }
+
+        vpx_memcpy(this_frame, &next_frame, sizeof(*this_frame));
+
+        old_boost_score = boost_score;
+    }
+
+    cpi->twopass.gf_decay_rate =
+        (i > 0) ? (int)(100.0 * (1.0 - decay_accumulator)) / i : 0;
+
+    // When using CBR apply additional buffer related upper limits
+    if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+    {
+        double max_boost;
+
+        // For cbr apply buffer related limits
+        if (cpi->drop_frames_allowed)
+        {
+            int df_buffer_level = cpi->oxcf.drop_frames_water_mark *
+                                  (cpi->oxcf.optimal_buffer_level / 100);
+
+            if (cpi->buffer_level > df_buffer_level)
+                max_boost = ((double)((cpi->buffer_level - df_buffer_level) * 2 / 3) * 16.0) / DOUBLE_DIVIDE_CHECK((double)cpi->av_per_frame_bandwidth);
+            else
+                max_boost = 0.0;
+        }
+        else if (cpi->buffer_level > 0)
+        {
+            max_boost = ((double)(cpi->buffer_level * 2 / 3) * 16.0) / DOUBLE_DIVIDE_CHECK((double)cpi->av_per_frame_bandwidth);
+        }
+        else
+        {
+            max_boost = 0.0;
+        }
+
+        if (boost_score > max_boost)
+            boost_score = max_boost;
+    }
+
+    // Dont allow conventional gf too near the next kf
+    if ((cpi->twopass.frames_to_key - i) < MIN_GF_INTERVAL)
+    {
+        while (i < cpi->twopass.frames_to_key)
+        {
+            i++;
+
+            if (EOF == input_stats(cpi, this_frame))
+                break;
+
+            if (i < cpi->twopass.frames_to_key)
+            {
+                mod_frame_err = calculate_modified_err(cpi, this_frame);
+                gf_group_err += mod_frame_err;
+            }
+        }
+    }
+
+    cpi->gfu_boost = (int)(boost_score * 100.0) >> 4;
+
+#if NEW_BOOST
+    // Alterrnative boost calculation for alt ref
+    alt_boost = calc_arf_boost( cpi, 0, (i-1), (i-1), &f_boost, &b_boost );
+#endif
+
+    // Should we use the alternate refernce frame
+    if (allow_alt_ref &&
+        (i >= MIN_GF_INTERVAL) &&
+        // dont use ARF very near next kf
+        (i <= (cpi->twopass.frames_to_key - MIN_GF_INTERVAL)) &&
+#if NEW_BOOST
+        ((next_frame.pcnt_inter > 0.75) ||
+         (next_frame.pcnt_second_ref > 0.5)) &&
+        ((mv_in_out_accumulator / (double)i > -0.2) ||
+         (mv_in_out_accumulator > -2.0)) &&
+        (b_boost > 100) &&
+        (f_boost > 100) )
+#else
+        (next_frame.pcnt_inter > 0.75) &&
+        ((mv_in_out_accumulator / (double)i > -0.2) ||
+         (mv_in_out_accumulator > -2.0)) &&
+        (cpi->gfu_boost > 100) &&
+        (cpi->twopass.gf_decay_rate <=
+            (ARF_DECAY_THRESH + (cpi->gfu_boost / 200))) )
+#endif
+    {
+        int Boost;
+        int allocation_chunks;
+        int Q = (cpi->oxcf.fixed_q < 0)
+                ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
+        int tmp_q;
+        int arf_frame_bits = 0;
+        int group_bits;
+
+#if NEW_BOOST
+        cpi->gfu_boost = alt_boost;
+#endif
+
+        // Estimate the bits to be allocated to the group as a whole
+        if ((cpi->twopass.kf_group_bits > 0) &&
+            (cpi->twopass.kf_group_error_left > 0))
+        {
+            group_bits = (int)((double)cpi->twopass.kf_group_bits *
+                (gf_group_err / (double)cpi->twopass.kf_group_error_left));
+        }
+        else
+            group_bits = 0;
+
+        // Boost for arf frame
+#if NEW_BOOST
+        Boost = (alt_boost * GFQ_ADJUSTMENT) / 100;
+#else
+        Boost = (cpi->gfu_boost * 3 * GFQ_ADJUSTMENT) / (2 * 100);
+#endif
+        Boost += (i * 50);
+
+        // Set max and minimum boost and hence minimum allocation
+        if (Boost > ((cpi->baseline_gf_interval + 1) * 200))
+            Boost = ((cpi->baseline_gf_interval + 1) * 200);
+        else if (Boost < 125)
+            Boost = 125;
+
+        allocation_chunks = (i * 100) + Boost;
+
+        // Normalize Altboost and allocations chunck down to prevent overflow
+        while (Boost > 1000)
+        {
+            Boost /= 2;
+            allocation_chunks /= 2;
+        }
+
+        // Calculate the number of bits to be spent on the arf based on the
+        // boost number
+        arf_frame_bits = (int)((double)Boost * (group_bits /
+                               (double)allocation_chunks));
+
+        // Estimate if there are enough bits available to make worthwhile use
+        // of an arf.
+        tmp_q = estimate_q(cpi, mod_frame_err, (int)arf_frame_bits);
+
+        // Only use an arf if it is likely we will be able to code
+        // it at a lower Q than the surrounding frames.
+        if (tmp_q < cpi->worst_quality)
+        {
+            int half_gf_int;
+            int frames_after_arf;
+            int frames_bwd = cpi->oxcf.arnr_max_frames - 1;
+            int frames_fwd = cpi->oxcf.arnr_max_frames - 1;
+
+            cpi->source_alt_ref_pending = 1;
+
+            // For alt ref frames the error score for the end frame of the
+            // group (the alt ref frame) should not contribute to the group
+            // total and hence the number of bit allocated to the group.
+            // Rather it forms part of the next group (it is the GF at the
+            // start of the next group)
+            // gf_group_err -= mod_frame_err;
+
+            // For alt ref frames alt ref frame is technically part of the
+            // GF frame for the next group but we always base the error
+            // calculation and bit allocation on the current group of frames.
+
+            // Set the interval till the next gf or arf.
+            // For ARFs this is the number of frames to be coded before the
+            // future frame that is coded as an ARF.
+            // The future frame itself is part of the next group
+            cpi->baseline_gf_interval = i;
+
+            // Define the arnr filter width for this group of frames:
+            // We only filter frames that lie within a distance of half
+            // the GF interval from the ARF frame. We also have to trap
+            // cases where the filter extends beyond the end of clip.
+            // Note: this_frame->frame has been updated in the loop
+            // so it now points at the ARF frame.
+            half_gf_int = cpi->baseline_gf_interval >> 1;
+            frames_after_arf = cpi->twopass.total_stats.count -
+                               this_frame->frame - 1;
+
+            switch (cpi->oxcf.arnr_type)
+            {
+            case 1: // Backward filter
+                frames_fwd = 0;
+                if (frames_bwd > half_gf_int)
+                    frames_bwd = half_gf_int;
+                break;
+
+            case 2: // Forward filter
+                if (frames_fwd > half_gf_int)
+                    frames_fwd = half_gf_int;
+                if (frames_fwd > frames_after_arf)
+                    frames_fwd = frames_after_arf;
+                frames_bwd = 0;
+                break;
+
+            case 3: // Centered filter
+            default:
+                frames_fwd >>= 1;
+                if (frames_fwd > frames_after_arf)
+                    frames_fwd = frames_after_arf;
+                if (frames_fwd > half_gf_int)
+                    frames_fwd = half_gf_int;
+
+                frames_bwd = frames_fwd;
+
+                // For even length filter there is one more frame backward
+                // than forward: e.g. len=6 ==> bbbAff, len=7 ==> bbbAfff.
+                if (frames_bwd < half_gf_int)
+                    frames_bwd += (cpi->oxcf.arnr_max_frames+1) & 0x1;
+                break;
+            }
+
+            cpi->active_arnr_frames = frames_bwd + 1 + frames_fwd;
+        }
+        else
+        {
+            cpi->source_alt_ref_pending = 0;
+            cpi->baseline_gf_interval = i;
+        }
+    }
+    else
+    {
+        cpi->source_alt_ref_pending = 0;
+        cpi->baseline_gf_interval = i;
+    }
+
+    // Now decide how many bits should be allocated to the GF group as  a
+    // proportion of those remaining in the kf group.
+    // The final key frame group in the clip is treated as a special case
+    // where cpi->twopass.kf_group_bits is tied to cpi->twopass.bits_left.
+    // This is also important for short clips where there may only be one
+    // key frame.
+    if (cpi->twopass.frames_to_key >= (int)(cpi->twopass.total_stats.count -
+                                            cpi->common.current_video_frame))
+    {
+        cpi->twopass.kf_group_bits =
+            (cpi->twopass.bits_left > 0) ? cpi->twopass.bits_left : 0;
+    }
+
+    // Calculate the bits to be allocated to the group as a whole
+    if ((cpi->twopass.kf_group_bits > 0) &&
+        (cpi->twopass.kf_group_error_left > 0))
+    {
+        cpi->twopass.gf_group_bits =
+            (int)((double)cpi->twopass.kf_group_bits *
+                  (gf_group_err / (double)cpi->twopass.kf_group_error_left));
+    }
+    else
+        cpi->twopass.gf_group_bits = 0;
+
+    cpi->twopass.gf_group_bits =
+        (cpi->twopass.gf_group_bits < 0)
+            ? 0
+            : (cpi->twopass.gf_group_bits > cpi->twopass.kf_group_bits)
+                ? cpi->twopass.kf_group_bits : cpi->twopass.gf_group_bits;
+
+    // Clip cpi->twopass.gf_group_bits based on user supplied data rate
+    // variability limit (cpi->oxcf.two_pass_vbrmax_section)
+    if (cpi->twopass.gf_group_bits > max_bits * cpi->baseline_gf_interval)
+        cpi->twopass.gf_group_bits = max_bits * cpi->baseline_gf_interval;
+
+    // Reset the file position
+    reset_fpf_position(cpi, start_pos);
+
+    // Update the record of error used so far (only done once per gf group)
+    cpi->twopass.modified_error_used += gf_group_err;
+
+    // Assign  bits to the arf or gf.
+    for (i = 0; i <= (cpi->source_alt_ref_pending && cpi->common.frame_type != KEY_FRAME); i++) {
+        int Boost;
+        int allocation_chunks;
+        int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
+        int gf_bits;
+
+        // For ARF frames
+        if (cpi->source_alt_ref_pending && i == 0)
+        {
+#if NEW_BOOST
+            Boost = (alt_boost * GFQ_ADJUSTMENT) / 100;
+#else
+            Boost = (cpi->gfu_boost * 3 * GFQ_ADJUSTMENT) / (2 * 100);
+#endif
+            Boost += (cpi->baseline_gf_interval * 50);
+
+            // Set max and minimum boost and hence minimum allocation
+            if (Boost > ((cpi->baseline_gf_interval + 1) * 200))
+                Boost = ((cpi->baseline_gf_interval + 1) * 200);
+            else if (Boost < 125)
+                Boost = 125;
+
+            allocation_chunks =
+                ((cpi->baseline_gf_interval + 1) * 100) + Boost;
+        }
+        // Else for standard golden frames
+        else
+        {
+            // boost based on inter / intra ratio of subsequent frames
+            Boost = (cpi->gfu_boost * GFQ_ADJUSTMENT) / 100;
+
+            // Set max and minimum boost and hence minimum allocation
+            if (Boost > (cpi->baseline_gf_interval * 150))
+                Boost = (cpi->baseline_gf_interval * 150);
+            else if (Boost < 125)
+                Boost = 125;
+
+            allocation_chunks =
+                (cpi->baseline_gf_interval * 100) + (Boost - 100);
+        }
+
+        // Normalize Altboost and allocations chunck down to prevent overflow
+        while (Boost > 1000)
+        {
+            Boost /= 2;
+            allocation_chunks /= 2;
+        }
+
+        // Calculate the number of bits to be spent on the gf or arf based on
+        // the boost number
+        gf_bits = (int)((double)Boost *
+                        (cpi->twopass.gf_group_bits /
+                         (double)allocation_chunks));
+
+        // If the frame that is to be boosted is simpler than the average for
+        // the gf/arf group then use an alternative calculation
+        // based on the error score of the frame itself
+        if (mod_frame_err < gf_group_err / (double)cpi->baseline_gf_interval)
+        {
+            double  alt_gf_grp_bits;
+            int     alt_gf_bits;
+
+            alt_gf_grp_bits =
+                (double)cpi->twopass.kf_group_bits  *
+                (mod_frame_err * (double)cpi->baseline_gf_interval) /
+                DOUBLE_DIVIDE_CHECK((double)cpi->twopass.kf_group_error_left);
+
+            alt_gf_bits = (int)((double)Boost * (alt_gf_grp_bits /
+                                                 (double)allocation_chunks));
+
+            if (gf_bits > alt_gf_bits)
+            {
+                gf_bits = alt_gf_bits;
+            }
+        }
+        // Else if it is harder than other frames in the group make sure it at
+        // least receives an allocation in keeping with its relative error
+        // score, otherwise it may be worse off than an "un-boosted" frame
+        else
+        {
+            int alt_gf_bits =
+                (int)((double)cpi->twopass.kf_group_bits *
+                      mod_frame_err /
+                      DOUBLE_DIVIDE_CHECK((double)cpi->twopass.kf_group_error_left));
+
+            if (alt_gf_bits > gf_bits)
+            {
+                gf_bits = alt_gf_bits;
+            }
+        }
+
+        // Apply an additional limit for CBR
+        if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+        {
+            if (cpi->twopass.gf_bits > (cpi->buffer_level >> 1))
+                cpi->twopass.gf_bits = cpi->buffer_level >> 1;
+        }
+
+        // Dont allow a negative value for gf_bits
+        if (gf_bits < 0)
+            gf_bits = 0;
+
+        gf_bits += cpi->min_frame_bandwidth;                     // Add in minimum for a frame
+
+        if (i == 0)
+        {
+            cpi->twopass.gf_bits = gf_bits;
+        }
+        if (i == 1 || (!cpi->source_alt_ref_pending && (cpi->common.frame_type != KEY_FRAME)))
+        {
+            cpi->per_frame_bandwidth = gf_bits;                 // Per frame bit target for this frame
+        }
+    }
+
+    {
+        // Adjust KF group bits and error remainin
+        cpi->twopass.kf_group_error_left -= gf_group_err;
+        cpi->twopass.kf_group_bits -= cpi->twopass.gf_group_bits;
+
+        if (cpi->twopass.kf_group_bits < 0)
+            cpi->twopass.kf_group_bits = 0;
+
+        // Note the error score left in the remaining frames of the group.
+        // For normal GFs we want to remove the error score for the first frame of the group (except in Key frame case where this has already happened)
+        if (!cpi->source_alt_ref_pending && cpi->common.frame_type != KEY_FRAME)
+            cpi->twopass.gf_group_error_left = gf_group_err - gf_first_frame_err;
+        else
+            cpi->twopass.gf_group_error_left = gf_group_err;
+
+        cpi->twopass.gf_group_bits -= cpi->twopass.gf_bits - cpi->min_frame_bandwidth;
+
+        if (cpi->twopass.gf_group_bits < 0)
+            cpi->twopass.gf_group_bits = 0;
+
+        // This condition could fail if there are two kfs very close together
+        // despite (MIN_GF_INTERVAL) and would cause a devide by 0 in the
+        // calculation of cpi->twopass.alt_extra_bits.
+        if ( cpi->baseline_gf_interval >= 3 )
+        {
+#if NEW_BOOST
+            int boost = (cpi->source_alt_ref_pending)
+                        ? b_boost : cpi->gfu_boost;
+#else
+            int boost = cpi->gfu_boost;
+#endif
+            if ( boost >= 150 )
+            {
+                int pct_extra;
+
+                pct_extra = (boost - 100) / 50;
+                pct_extra = (pct_extra > 20) ? 20 : pct_extra;
+
+                cpi->twopass.alt_extra_bits =
+                    (cpi->twopass.gf_group_bits * pct_extra) / 100;
+                cpi->twopass.gf_group_bits -= cpi->twopass.alt_extra_bits;
+                cpi->twopass.alt_extra_bits /=
+                    ((cpi->baseline_gf_interval-1)>>1);
+            }
+            else
+                cpi->twopass.alt_extra_bits = 0;
+        }
+        else
+            cpi->twopass.alt_extra_bits = 0;
+    }
+
+    // Adjustments based on a measure of complexity of the section
+    if (cpi->common.frame_type != KEY_FRAME)
+    {
+        FIRSTPASS_STATS sectionstats;
+        double Ratio;
+
+        zero_stats(&sectionstats);
+        reset_fpf_position(cpi, start_pos);
+
+        for (i = 0 ; i < cpi->baseline_gf_interval ; i++)
+        {
+            input_stats(cpi, &next_frame);
+            accumulate_stats(&sectionstats, &next_frame);
+        }
+
+        avg_stats(&sectionstats);
+
+        cpi->twopass.section_intra_rating =
+            sectionstats.intra_error /
+            DOUBLE_DIVIDE_CHECK(sectionstats.coded_error);
+
+        Ratio = sectionstats.intra_error / DOUBLE_DIVIDE_CHECK(sectionstats.coded_error);
+        //if( (Ratio > 11) ) //&& (sectionstats.pcnt_second_ref < .20) )
+        //{
+        cpi->twopass.section_max_qfactor = 1.0 - ((Ratio - 10.0) * 0.025);
+
+        if (cpi->twopass.section_max_qfactor < 0.80)
+            cpi->twopass.section_max_qfactor = 0.80;
+
+        //}
+        //else
+        //    cpi->twopass.section_max_qfactor = 1.0;
+
+        reset_fpf_position(cpi, start_pos);
+    }
+}
+
+// Allocate bits to a normal frame that is neither a gf an arf or a key frame.
+static void assign_std_frame_bits(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
+{
+    int    target_frame_size;                                                             // gf_group_error_left
+
+    double modified_err;
+    double err_fraction;                                                                 // What portion of the remaining GF group error is used by this frame
+
+    int max_bits = frame_max_bits(cpi);    // Max for a single frame
+
+    // Calculate modified prediction error used in bit allocation
+    modified_err = calculate_modified_err(cpi, this_frame);
+
+    if (cpi->twopass.gf_group_error_left > 0)
+        err_fraction = modified_err / cpi->twopass.gf_group_error_left;                              // What portion of the remaining GF group error is used by this frame
+    else
+        err_fraction = 0.0;
+
+    target_frame_size = (int)((double)cpi->twopass.gf_group_bits * err_fraction);                    // How many of those bits available for allocation should we give it?
+
+    // Clip to target size to 0 - max_bits (or cpi->twopass.gf_group_bits) at the top end.
+    if (target_frame_size < 0)
+        target_frame_size = 0;
+    else
+    {
+        if (target_frame_size > max_bits)
+            target_frame_size = max_bits;
+
+        if (target_frame_size > cpi->twopass.gf_group_bits)
+            target_frame_size = cpi->twopass.gf_group_bits;
+    }
+
+    cpi->twopass.gf_group_error_left -= modified_err;                                               // Adjust error remaining
+    cpi->twopass.gf_group_bits -= target_frame_size;                                                // Adjust bits remaining
+
+    if (cpi->twopass.gf_group_bits < 0)
+        cpi->twopass.gf_group_bits = 0;
+
+    target_frame_size += cpi->min_frame_bandwidth;                                          // Add in the minimum number of bits that is set aside for every frame.
+
+    // Every other frame gets a few extra bits
+    if ( (cpi->common.frames_since_golden & 0x01) &&
+         (cpi->frames_till_gf_update_due > 0) )
+    {
+        target_frame_size += cpi->twopass.alt_extra_bits;
+    }
+
+    cpi->per_frame_bandwidth = target_frame_size;                                           // Per frame bit target for this frame
+}
+
+void vp8_second_pass(VP8_COMP *cpi)
+{
+    int tmp_q;
+    int frames_left = (int)(cpi->twopass.total_stats.count - cpi->common.current_video_frame);
+
+    FIRSTPASS_STATS this_frame = {0};
+    FIRSTPASS_STATS this_frame_copy;
+
+    double this_frame_intra_error;
+    double this_frame_coded_error;
+
+    int overhead_bits;
+
+    if (!cpi->twopass.stats_in)
+    {
+        return ;
+    }
+
+    vp8_clear_system_state();
+
+    if (EOF == input_stats(cpi, &this_frame))
+        return;
+
+    this_frame_intra_error = this_frame.intra_error;
+    this_frame_coded_error = this_frame.coded_error;
+
+    // keyframe and section processing !
+    if (cpi->twopass.frames_to_key == 0)
+    {
+        // Define next KF group and assign bits to it
+        vpx_memcpy(&this_frame_copy, &this_frame, sizeof(this_frame));
+        find_next_key_frame(cpi, &this_frame_copy);
+
+        // Special case: Error error_resilient_mode mode does not make much sense for two pass but with its current meaning but this code is designed to stop
+        // outlandish behaviour if someone does set it when using two pass. It effectively disables GF groups.
+        // This is temporary code till we decide what should really happen in this case.
+        if (cpi->oxcf.error_resilient_mode)
+        {
+            cpi->twopass.gf_group_bits = cpi->twopass.kf_group_bits;
+            cpi->twopass.gf_group_error_left = cpi->twopass.kf_group_error_left;
+            cpi->baseline_gf_interval = cpi->twopass.frames_to_key;
+            cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
+            cpi->source_alt_ref_pending = 0;
+        }
+
+    }
+
+    // Is this a GF / ARF (Note that a KF is always also a GF)
+    if (cpi->frames_till_gf_update_due == 0)
+    {
+        // Define next gf group and assign bits to it
+        vpx_memcpy(&this_frame_copy, &this_frame, sizeof(this_frame));
+        define_gf_group(cpi, &this_frame_copy);
+
+        // If we are going to code an altref frame at the end of the group and the current frame is not a key frame....
+        // If the previous group used an arf this frame has already benefited from that arf boost and it should not be given extra bits
+        // If the previous group was NOT coded using arf we may want to apply some boost to this GF as well
+        if (cpi->source_alt_ref_pending && (cpi->common.frame_type != KEY_FRAME))
+        {
+            // Assign a standard frames worth of bits from those allocated to the GF group
+            int bak = cpi->per_frame_bandwidth;
+            vpx_memcpy(&this_frame_copy, &this_frame, sizeof(this_frame));
+            assign_std_frame_bits(cpi, &this_frame_copy);
+            cpi->per_frame_bandwidth = bak;
+        }
+    }
+
+    // Otherwise this is an ordinary frame
+    else
+    {
+        // Special case: Error error_resilient_mode mode does not make much sense for two pass but with its current meaning but this code is designed to stop
+        // outlandish behaviour if someone does set it when using two pass. It effectively disables GF groups.
+        // This is temporary code till we decide what should really happen in this case.
+        if (cpi->oxcf.error_resilient_mode)
+        {
+            cpi->frames_till_gf_update_due = cpi->twopass.frames_to_key;
+
+            if (cpi->common.frame_type != KEY_FRAME)
+            {
+                // Assign bits from those allocated to the GF group
+                vpx_memcpy(&this_frame_copy, &this_frame, sizeof(this_frame));
+                assign_std_frame_bits(cpi, &this_frame_copy);
+            }
+        }
+        else
+        {
+            // Assign bits from those allocated to the GF group
+            vpx_memcpy(&this_frame_copy, &this_frame, sizeof(this_frame));
+            assign_std_frame_bits(cpi, &this_frame_copy);
+        }
+    }
+
+    // Keep a globally available copy of this and the next frame's iiratio.
+    cpi->twopass.this_iiratio = this_frame_intra_error /
+                        DOUBLE_DIVIDE_CHECK(this_frame_coded_error);
+    {
+        FIRSTPASS_STATS next_frame;
+        if ( lookup_next_frame_stats(cpi, &next_frame) != EOF )
+        {
+            cpi->twopass.next_iiratio = next_frame.intra_error /
+                                DOUBLE_DIVIDE_CHECK(next_frame.coded_error);
+        }
+    }
+
+    // Set nominal per second bandwidth for this frame
+    cpi->target_bandwidth = cpi->per_frame_bandwidth * cpi->output_frame_rate;
+    if (cpi->target_bandwidth < 0)
+        cpi->target_bandwidth = 0;
+
+
+    // Account for mv, mode and other overheads.
+    overhead_bits = estimate_modemvcost(
+                        cpi, &cpi->twopass.total_left_stats );
+
+    // Special case code for first frame.
+    if (cpi->common.current_video_frame == 0)
+    {
+        cpi->twopass.est_max_qcorrection_factor = 1.0;
+
+        // Set a cq_level in constrained quality mode.
+        if ( cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY )
+        {
+            int est_cq;
+
+            est_cq =
+                estimate_cq( cpi,
+                             &cpi->twopass.total_left_stats,
+                             (int)(cpi->twopass.bits_left / frames_left),
+                             overhead_bits );
+
+            cpi->cq_target_quality = cpi->oxcf.cq_level;
+            if ( est_cq > cpi->cq_target_quality )
+                cpi->cq_target_quality = est_cq;
+        }
+
+        // guess at maxq needed in 2nd pass
+        cpi->twopass.maxq_max_limit = cpi->worst_quality;
+        cpi->twopass.maxq_min_limit = cpi->best_quality;
+
+        tmp_q = estimate_max_q(
+                    cpi,
+                    &cpi->twopass.total_left_stats,
+                    (int)(cpi->twopass.bits_left / frames_left),
+                    overhead_bits );
+
+        // Limit the maxq value returned subsequently.
+        // This increases the risk of overspend or underspend if the initial
+        // estimate for the clip is bad, but helps prevent excessive
+        // variation in Q, especially near the end of a clip
+        // where for example a small overspend may cause Q to crash
+        cpi->twopass.maxq_max_limit = ((tmp_q + 32) < cpi->worst_quality)
+                                  ? (tmp_q + 32) : cpi->worst_quality;
+        cpi->twopass.maxq_min_limit = ((tmp_q - 32) > cpi->best_quality)
+                                  ? (tmp_q - 32) : cpi->best_quality;
+
+        cpi->active_worst_quality         = tmp_q;
+        cpi->ni_av_qi                     = tmp_q;
+    }
+
+    // The last few frames of a clip almost always have to few or too many
+    // bits and for the sake of over exact rate control we dont want to make
+    // radical adjustments to the allowed quantizer range just to use up a
+    // few surplus bits or get beneath the target rate.
+    else if ( (cpi->common.current_video_frame <
+                 (((unsigned int)cpi->twopass.total_stats.count * 255)>>8)) &&
+              ((cpi->common.current_video_frame + cpi->baseline_gf_interval) <
+                 (unsigned int)cpi->twopass.total_stats.count) )
+    {
+        if (frames_left < 1)
+            frames_left = 1;
+
+        tmp_q = estimate_max_q(
+                    cpi,
+                    &cpi->twopass.total_left_stats,
+                    (int)(cpi->twopass.bits_left / frames_left),
+                    overhead_bits );
+
+        // Move active_worst_quality but in a damped way
+        if (tmp_q > cpi->active_worst_quality)
+            cpi->active_worst_quality ++;
+        else if (tmp_q < cpi->active_worst_quality)
+            cpi->active_worst_quality --;
+
+        cpi->active_worst_quality =
+            ((cpi->active_worst_quality * 3) + tmp_q + 2) / 4;
+    }
+
+    cpi->twopass.frames_to_key --;
+
+    // Update the total stats remaining sturcture
+    subtract_stats(&cpi->twopass.total_left_stats, &this_frame );
+}
+
+
+static int test_candidate_kf(VP8_COMP *cpi,  FIRSTPASS_STATS *last_frame, FIRSTPASS_STATS *this_frame, FIRSTPASS_STATS *next_frame)
+{
+    int is_viable_kf = 0;
+
+    // Does the frame satisfy the primary criteria of a key frame
+    //      If so, then examine how well it predicts subsequent frames
+    if ((this_frame->pcnt_second_ref < 0.10) &&
+        (next_frame->pcnt_second_ref < 0.10) &&
+        ((this_frame->pcnt_inter < 0.05) ||
+         (
+             ((this_frame->pcnt_inter - this_frame->pcnt_neutral) < .25) &&
+             ((this_frame->intra_error / DOUBLE_DIVIDE_CHECK(this_frame->coded_error)) < 2.5) &&
+             ((fabs(last_frame->coded_error - this_frame->coded_error) / DOUBLE_DIVIDE_CHECK(this_frame->coded_error) > .40) ||
+              (fabs(last_frame->intra_error - this_frame->intra_error) / DOUBLE_DIVIDE_CHECK(this_frame->intra_error) > .40) ||
+              ((next_frame->intra_error / DOUBLE_DIVIDE_CHECK(next_frame->coded_error)) > 3.5)
+             )
+         )
+        )
+       )
+    {
+        int i;
+        FIRSTPASS_STATS *start_pos;
+
+        FIRSTPASS_STATS local_next_frame;
+
+        double boost_score = 0.0;
+        double old_boost_score = 0.0;
+        double decay_accumulator = 1.0;
+        double next_iiratio;
+
+        vpx_memcpy(&local_next_frame, next_frame, sizeof(*next_frame));
+
+        // Note the starting file position so we can reset to it
+        start_pos = cpi->twopass.stats_in;
+
+        // Examine how well the key frame predicts subsequent frames
+        for (i = 0 ; i < 16; i++)
+        {
+            next_iiratio = (IIKFACTOR1 * local_next_frame.intra_error / DOUBLE_DIVIDE_CHECK(local_next_frame.coded_error)) ;
+
+            if (next_iiratio > RMAX)
+                next_iiratio = RMAX;
+
+            // Cumulative effect of decay in prediction quality
+            if (local_next_frame.pcnt_inter > 0.85)
+                decay_accumulator = decay_accumulator * local_next_frame.pcnt_inter;
+            else
+                decay_accumulator = decay_accumulator * ((0.85 + local_next_frame.pcnt_inter) / 2.0);
+
+            //decay_accumulator = decay_accumulator * local_next_frame.pcnt_inter;
+
+            // Keep a running total
+            boost_score += (decay_accumulator * next_iiratio);
+
+            // Test various breakout clauses
+            if ((local_next_frame.pcnt_inter < 0.05) ||
+                (next_iiratio < 1.5) ||
+                (((local_next_frame.pcnt_inter -
+                   local_next_frame.pcnt_neutral) < 0.20) &&
+                 (next_iiratio < 3.0)) ||
+                ((boost_score - old_boost_score) < 0.5) ||
+                (local_next_frame.intra_error < 200)
+               )
+            {
+                break;
+            }
+
+            old_boost_score = boost_score;
+
+            // Get the next frame details
+            if (EOF == input_stats(cpi, &local_next_frame))
+                break;
+        }
+
+        // If there is tolerable prediction for at least the next 3 frames then break out else discard this pottential key frame and move on
+        if (boost_score > 5.0 && (i > 3))
+            is_viable_kf = 1;
+        else
+        {
+            // Reset the file position
+            reset_fpf_position(cpi, start_pos);
+
+            is_viable_kf = 0;
+        }
+    }
+
+    return is_viable_kf;
+}
+static void find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
+{
+    int i,j;
+    FIRSTPASS_STATS last_frame;
+    FIRSTPASS_STATS first_frame;
+    FIRSTPASS_STATS next_frame;
+    FIRSTPASS_STATS *start_position;
+
+    double decay_accumulator = 1.0;
+    double boost_score = 0;
+    double old_boost_score = 0.0;
+    double loop_decay_rate;
+
+    double kf_mod_err = 0.0;
+    double kf_group_err = 0.0;
+    double kf_group_intra_err = 0.0;
+    double kf_group_coded_err = 0.0;
+    double recent_loop_decay[8] = {1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0};
+
+    vpx_memset(&next_frame, 0, sizeof(next_frame)); // assure clean
+
+    vp8_clear_system_state();  //__asm emms;
+    start_position = cpi->twopass.stats_in;
+
+    cpi->common.frame_type = KEY_FRAME;
+
+    // is this a forced key frame by interval
+    cpi->this_key_frame_forced = cpi->next_key_frame_forced;
+
+    // Clear the alt ref active flag as this can never be active on a key frame
+    cpi->source_alt_ref_active = 0;
+
+    // Kf is always a gf so clear frames till next gf counter
+    cpi->frames_till_gf_update_due = 0;
+
+    cpi->twopass.frames_to_key = 1;
+
+    // Take a copy of the initial frame details
+    vpx_memcpy(&first_frame, this_frame, sizeof(*this_frame));
+
+    cpi->twopass.kf_group_bits = 0;        // Total bits avaialable to kf group
+    cpi->twopass.kf_group_error_left = 0;  // Group modified error score.
+
+    kf_mod_err = calculate_modified_err(cpi, this_frame);
+
+    // find the next keyframe
+    i = 0;
+    while (cpi->twopass.stats_in < cpi->twopass.stats_in_end)
+    {
+        // Accumulate kf group error
+        kf_group_err += calculate_modified_err(cpi, this_frame);
+
+        // These figures keep intra and coded error counts for all frames including key frames in the group.
+        // The effect of the key frame itself can be subtracted out using the first_frame data collected above
+        kf_group_intra_err += this_frame->intra_error;
+        kf_group_coded_err += this_frame->coded_error;
+
+        // load a the next frame's stats
+        vpx_memcpy(&last_frame, this_frame, sizeof(*this_frame));
+        input_stats(cpi, this_frame);
+
+        // Provided that we are not at the end of the file...
+        if (cpi->oxcf.auto_key
+            && lookup_next_frame_stats(cpi, &next_frame) != EOF)
+        {
+            // Normal scene cut check
+            if ( ( i >= MIN_GF_INTERVAL ) &&
+                 test_candidate_kf(cpi, &last_frame, this_frame, &next_frame) )
+            {
+                break;
+            }
+
+            // How fast is prediction quality decaying
+            loop_decay_rate = get_prediction_decay_rate(cpi, &next_frame);
+
+            // We want to know something about the recent past... rather than
+            // as used elsewhere where we are concened with decay in prediction
+            // quality since the last GF or KF.
+            recent_loop_decay[i%8] = loop_decay_rate;
+            decay_accumulator = 1.0;
+            for (j = 0; j < 8; j++)
+            {
+                decay_accumulator = decay_accumulator * recent_loop_decay[j];
+            }
+
+            // Special check for transition or high motion followed by a
+            // to a static scene.
+            if ( detect_transition_to_still( cpi, i,
+                                             (cpi->key_frame_frequency-i),
+                                             loop_decay_rate,
+                                             decay_accumulator ) )
+            {
+                break;
+            }
+
+
+            // Step on to the next frame
+            cpi->twopass.frames_to_key ++;
+
+            // If we don't have a real key frame within the next two
+            // forcekeyframeevery intervals then break out of the loop.
+            if (cpi->twopass.frames_to_key >= 2 *(int)cpi->key_frame_frequency)
+                break;
+        } else
+            cpi->twopass.frames_to_key ++;
+
+        i++;
+    }
+
+    // If there is a max kf interval set by the user we must obey it.
+    // We already breakout of the loop above at 2x max.
+    // This code centers the extra kf if the actual natural
+    // interval is between 1x and 2x
+    if (cpi->oxcf.auto_key
+        && cpi->twopass.frames_to_key > (int)cpi->key_frame_frequency )
+    {
+        FIRSTPASS_STATS *current_pos = cpi->twopass.stats_in;
+        FIRSTPASS_STATS tmp_frame;
+
+        cpi->twopass.frames_to_key /= 2;
+
+        // Copy first frame details
+        vpx_memcpy(&tmp_frame, &first_frame, sizeof(first_frame));
+
+        // Reset to the start of the group
+        reset_fpf_position(cpi, start_position);
+
+        kf_group_err = 0;
+        kf_group_intra_err = 0;
+        kf_group_coded_err = 0;
+
+        // Rescan to get the correct error data for the forced kf group
+        for( i = 0; i < cpi->twopass.frames_to_key; i++ )
+        {
+            // Accumulate kf group errors
+            kf_group_err += calculate_modified_err(cpi, &tmp_frame);
+            kf_group_intra_err += tmp_frame.intra_error;
+            kf_group_coded_err += tmp_frame.coded_error;
+
+            // Load a the next frame's stats
+            input_stats(cpi, &tmp_frame);
+        }
+
+        // Reset to the start of the group
+        reset_fpf_position(cpi, current_pos);
+
+        cpi->next_key_frame_forced = 1;
+    }
+    else
+        cpi->next_key_frame_forced = 0;
+
+    // Special case for the last frame of the file
+    if (cpi->twopass.stats_in >= cpi->twopass.stats_in_end)
+    {
+        // Accumulate kf group error
+        kf_group_err += calculate_modified_err(cpi, this_frame);
+
+        // These figures keep intra and coded error counts for all frames including key frames in the group.
+        // The effect of the key frame itself can be subtracted out using the first_frame data collected above
+        kf_group_intra_err += this_frame->intra_error;
+        kf_group_coded_err += this_frame->coded_error;
+    }
+
+    // Calculate the number of bits that should be assigned to the kf group.
+    if ((cpi->twopass.bits_left > 0) && (cpi->twopass.modified_error_left > 0.0))
+    {
+        // Max for a single normal frame (not key frame)
+        int max_bits = frame_max_bits(cpi);
+
+        // Maximum bits for the kf group
+        int64_t max_grp_bits;
+
+        // Default allocation based on bits left and relative
+        // complexity of the section
+        cpi->twopass.kf_group_bits = (int64_t)( cpi->twopass.bits_left *
+                                          ( kf_group_err /
+                                            cpi->twopass.modified_error_left ));
+
+        // Clip based on maximum per frame rate defined by the user.
+        max_grp_bits = (int64_t)max_bits * (int64_t)cpi->twopass.frames_to_key;
+        if (cpi->twopass.kf_group_bits > max_grp_bits)
+            cpi->twopass.kf_group_bits = max_grp_bits;
+
+        // Additional special case for CBR if buffer is getting full.
+        if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+        {
+            int opt_buffer_lvl = cpi->oxcf.optimal_buffer_level;
+            int buffer_lvl = cpi->buffer_level;
+
+            // If the buffer is near or above the optimal and this kf group is
+            // not being allocated much then increase the allocation a bit.
+            if (buffer_lvl >= opt_buffer_lvl)
+            {
+                int high_water_mark = (opt_buffer_lvl +
+                                       cpi->oxcf.maximum_buffer_size) >> 1;
+
+                int64_t av_group_bits;
+
+                // Av bits per frame * number of frames
+                av_group_bits = (int64_t)cpi->av_per_frame_bandwidth *
+                                (int64_t)cpi->twopass.frames_to_key;
+
+                // We are at or above the maximum.
+                if (cpi->buffer_level >= high_water_mark)
+                {
+                    int64_t min_group_bits;
+
+                    min_group_bits = av_group_bits +
+                                     (int64_t)(buffer_lvl -
+                                                 high_water_mark);
+
+                    if (cpi->twopass.kf_group_bits < min_group_bits)
+                        cpi->twopass.kf_group_bits = min_group_bits;
+                }
+                // We are above optimal but below the maximum
+                else if (cpi->twopass.kf_group_bits < av_group_bits)
+                {
+                    int64_t bits_below_av = av_group_bits -
+                                              cpi->twopass.kf_group_bits;
+
+                    cpi->twopass.kf_group_bits +=
+                       (int64_t)((double)bits_below_av *
+                                   (double)(buffer_lvl - opt_buffer_lvl) /
+                                   (double)(high_water_mark - opt_buffer_lvl));
+                }
+            }
+        }
+    }
+    else
+        cpi->twopass.kf_group_bits = 0;
+
+    // Reset the first pass file position
+    reset_fpf_position(cpi, start_position);
+
+    // determine how big to make this keyframe based on how well the subsequent frames use inter blocks
+    decay_accumulator = 1.0;
+    boost_score = 0.0;
+    loop_decay_rate = 1.00;       // Starting decay rate
+
+    for (i = 0 ; i < cpi->twopass.frames_to_key ; i++)
+    {
+        double r;
+
+        if (EOF == input_stats(cpi, &next_frame))
+            break;
+
+        if (next_frame.intra_error > cpi->twopass.kf_intra_err_min)
+            r = (IIKFACTOR2 * next_frame.intra_error /
+                     DOUBLE_DIVIDE_CHECK(next_frame.coded_error));
+        else
+            r = (IIKFACTOR2 * cpi->twopass.kf_intra_err_min /
+                     DOUBLE_DIVIDE_CHECK(next_frame.coded_error));
+
+        if (r > RMAX)
+            r = RMAX;
+
+        // How fast is prediction quality decaying
+        loop_decay_rate = get_prediction_decay_rate(cpi, &next_frame);
+
+        decay_accumulator = decay_accumulator * loop_decay_rate;
+        decay_accumulator = decay_accumulator < 0.1 ? 0.1 : decay_accumulator;
+
+        boost_score += (decay_accumulator * r);
+
+        if ((i > MIN_GF_INTERVAL) &&
+            ((boost_score - old_boost_score) < 1.0))
+        {
+            break;
+        }
+
+        old_boost_score = boost_score;
+    }
+
+    if (1)
+    {
+        FIRSTPASS_STATS sectionstats;
+        double Ratio;
+
+        zero_stats(&sectionstats);
+        reset_fpf_position(cpi, start_position);
+
+        for (i = 0 ; i < cpi->twopass.frames_to_key ; i++)
+        {
+            input_stats(cpi, &next_frame);
+            accumulate_stats(&sectionstats, &next_frame);
+        }
+
+        avg_stats(&sectionstats);
+
+        cpi->twopass.section_intra_rating =
+            sectionstats.intra_error
+            / DOUBLE_DIVIDE_CHECK(sectionstats.coded_error);
+
+        Ratio = sectionstats.intra_error / DOUBLE_DIVIDE_CHECK(sectionstats.coded_error);
+        // if( (Ratio > 11) ) //&& (sectionstats.pcnt_second_ref < .20) )
+        //{
+        cpi->twopass.section_max_qfactor = 1.0 - ((Ratio - 10.0) * 0.025);
+
+        if (cpi->twopass.section_max_qfactor < 0.80)
+            cpi->twopass.section_max_qfactor = 0.80;
+
+        //}
+        //else
+        //    cpi->twopass.section_max_qfactor = 1.0;
+    }
+
+    // When using CBR apply additional buffer fullness related upper limits
+    if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+    {
+        double max_boost;
+
+        if (cpi->drop_frames_allowed)
+        {
+            int df_buffer_level = cpi->oxcf.drop_frames_water_mark * (cpi->oxcf.optimal_buffer_level / 100);
+
+            if (cpi->buffer_level > df_buffer_level)
+                max_boost = ((double)((cpi->buffer_level - df_buffer_level) * 2 / 3) * 16.0) / DOUBLE_DIVIDE_CHECK((double)cpi->av_per_frame_bandwidth);
+            else
+                max_boost = 0.0;
+        }
+        else if (cpi->buffer_level > 0)
+        {
+            max_boost = ((double)(cpi->buffer_level * 2 / 3) * 16.0) / DOUBLE_DIVIDE_CHECK((double)cpi->av_per_frame_bandwidth);
+        }
+        else
+        {
+            max_boost = 0.0;
+        }
+
+        if (boost_score > max_boost)
+            boost_score = max_boost;
+    }
+
+    // Reset the first pass file position
+    reset_fpf_position(cpi, start_position);
+
+    // Work out how many bits to allocate for the key frame itself
+    if (1)
+    {
+        int kf_boost = boost_score;
+        int allocation_chunks;
+        int Counter = cpi->twopass.frames_to_key;
+        int alt_kf_bits;
+        YV12_BUFFER_CONFIG *lst_yv12 = &cpi->common.yv12_fb[cpi->common.lst_fb_idx];
+        // Min boost based on kf interval
+#if 0
+
+        while ((kf_boost < 48) && (Counter > 0))
+        {
+            Counter -= 2;
+            kf_boost ++;
+        }
+
+#endif
+
+        if (kf_boost < 48)
+        {
+            kf_boost += ((Counter + 1) >> 1);
+
+            if (kf_boost > 48) kf_boost = 48;
+        }
+
+        // bigger frame sizes need larger kf boosts, smaller frames smaller boosts...
+        if ((lst_yv12->y_width * lst_yv12->y_height) > (320 * 240))
+            kf_boost += 2 * (lst_yv12->y_width * lst_yv12->y_height) / (320 * 240);
+        else if ((lst_yv12->y_width * lst_yv12->y_height) < (320 * 240))
+            kf_boost -= 4 * (320 * 240) / (lst_yv12->y_width * lst_yv12->y_height);
+
+        kf_boost = (int)((double)kf_boost * 100.0) >> 4;                          // Scale 16 to 100
+
+        // Adjustment to boost based on recent average q
+        //kf_boost = kf_boost * vp8_kf_boost_qadjustment[cpi->ni_av_qi] / 100;
+
+        if (kf_boost < 250)                                                      // Min KF boost
+            kf_boost = 250;
+
+        // We do three calculations for kf size.
+        // The first is based on the error score for the whole kf group.
+        // The second (optionaly) on the key frames own error if this is
+        // smaller than the average for the group.
+        // The final one insures that the frame receives at least the
+        // allocation it would have received based on its own error score vs
+        // the error score remaining
+        // Special case if the sequence appears almost totaly static
+        // as measured by the decay accumulator. In this case we want to
+        // spend almost all of the bits on the key frame.
+        // cpi->twopass.frames_to_key-1 because key frame itself is taken
+        // care of by kf_boost.
+        if ( decay_accumulator >= 0.99 )
+        {
+            allocation_chunks =
+                ((cpi->twopass.frames_to_key - 1) * 10) + kf_boost;
+        }
+        else
+        {
+            allocation_chunks =
+                ((cpi->twopass.frames_to_key - 1) * 100) + kf_boost;
+        }
+
+        // Normalize Altboost and allocations chunck down to prevent overflow
+        while (kf_boost > 1000)
+        {
+            kf_boost /= 2;
+            allocation_chunks /= 2;
+        }
+
+        cpi->twopass.kf_group_bits = (cpi->twopass.kf_group_bits < 0) ? 0 : cpi->twopass.kf_group_bits;
+
+        // Calculate the number of bits to be spent on the key frame
+        cpi->twopass.kf_bits  = (int)((double)kf_boost * ((double)cpi->twopass.kf_group_bits / (double)allocation_chunks));
+
+        // Apply an additional limit for CBR
+        if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+        {
+            if (cpi->twopass.kf_bits > ((3 * cpi->buffer_level) >> 2))
+                cpi->twopass.kf_bits = (3 * cpi->buffer_level) >> 2;
+        }
+
+        // If the key frame is actually easier than the average for the
+        // kf group (which does sometimes happen... eg a blank intro frame)
+        // Then use an alternate calculation based on the kf error score
+        // which should give a smaller key frame.
+        if (kf_mod_err < kf_group_err / cpi->twopass.frames_to_key)
+        {
+            double  alt_kf_grp_bits =
+                        ((double)cpi->twopass.bits_left *
+                         (kf_mod_err * (double)cpi->twopass.frames_to_key) /
+                         DOUBLE_DIVIDE_CHECK(cpi->twopass.modified_error_left));
+
+            alt_kf_bits = (int)((double)kf_boost *
+                                (alt_kf_grp_bits / (double)allocation_chunks));
+
+            if (cpi->twopass.kf_bits > alt_kf_bits)
+            {
+                cpi->twopass.kf_bits = alt_kf_bits;
+            }
+        }
+        // Else if it is much harder than other frames in the group make sure
+        // it at least receives an allocation in keeping with its relative
+        // error score
+        else
+        {
+            alt_kf_bits =
+                (int)((double)cpi->twopass.bits_left *
+                      (kf_mod_err /
+                       DOUBLE_DIVIDE_CHECK(cpi->twopass.modified_error_left)));
+
+            if (alt_kf_bits > cpi->twopass.kf_bits)
+            {
+                cpi->twopass.kf_bits = alt_kf_bits;
+            }
+        }
+
+        cpi->twopass.kf_group_bits -= cpi->twopass.kf_bits;
+        cpi->twopass.kf_bits += cpi->min_frame_bandwidth;                                          // Add in the minimum frame allowance
+
+        cpi->per_frame_bandwidth = cpi->twopass.kf_bits;                                           // Peer frame bit target for this frame
+        cpi->target_bandwidth = cpi->twopass.kf_bits * cpi->output_frame_rate;                      // Convert to a per second bitrate
+    }
+
+    // Note the total error score of the kf group minus the key frame itself
+    cpi->twopass.kf_group_error_left = (int)(kf_group_err - kf_mod_err);
+
+    // Adjust the count of total modified error left.
+    // The count of bits left is adjusted elsewhere based on real coded frame sizes
+    cpi->twopass.modified_error_left -= kf_group_err;
+
+    if (cpi->oxcf.allow_spatial_resampling)
+    {
+        int resample_trigger = 0;
+        int last_kf_resampled = 0;
+        int kf_q;
+        int scale_val = 0;
+        int hr, hs, vr, vs;
+        int new_width = cpi->oxcf.Width;
+        int new_height = cpi->oxcf.Height;
+
+        int projected_buffer_level = cpi->buffer_level;
+        int tmp_q;
+
+        double projected_bits_perframe;
+        double group_iiratio = (kf_group_intra_err - first_frame.intra_error) / (kf_group_coded_err - first_frame.coded_error);
+        double err_per_frame = kf_group_err / cpi->twopass.frames_to_key;
+        double bits_per_frame;
+        double av_bits_per_frame;
+        double effective_size_ratio;
+
+        if ((cpi->common.Width != cpi->oxcf.Width) || (cpi->common.Height != cpi->oxcf.Height))
+            last_kf_resampled = 1;
+
+        // Set back to unscaled by defaults
+        cpi->common.horiz_scale = NORMAL;
+        cpi->common.vert_scale = NORMAL;
+
+        // Calculate Average bits per frame.
+        //av_bits_per_frame = cpi->twopass.bits_left/(double)(cpi->twopass.total_stats.count - cpi->common.current_video_frame);
+        av_bits_per_frame = cpi->oxcf.target_bandwidth / DOUBLE_DIVIDE_CHECK((double)cpi->frame_rate);
+        //if ( av_bits_per_frame < 0.0 )
+        //  av_bits_per_frame = 0.0
+
+        // CBR... Use the clip average as the target for deciding resample
+        if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+        {
+            bits_per_frame = av_bits_per_frame;
+        }
+
+        // In VBR we want to avoid downsampling in easy section unless we are under extreme pressure
+        // So use the larger of target bitrate for this sectoion or average bitrate for sequence
+        else
+        {
+            bits_per_frame = cpi->twopass.kf_group_bits / cpi->twopass.frames_to_key;     // This accounts for how hard the section is...
+
+            if (bits_per_frame < av_bits_per_frame)                      // Dont turn to resampling in easy sections just because they have been assigned a small number of bits
+                bits_per_frame = av_bits_per_frame;
+        }
+
+        // bits_per_frame should comply with our minimum
+        if (bits_per_frame < (cpi->oxcf.target_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100))
+            bits_per_frame = (cpi->oxcf.target_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100);
+
+        // Work out if spatial resampling is necessary
+        kf_q = estimate_kf_group_q(cpi, err_per_frame, bits_per_frame, group_iiratio);
+
+        // If we project a required Q higher than the maximum allowed Q then make a guess at the actual size of frames in this section
+        projected_bits_perframe = bits_per_frame;
+        tmp_q = kf_q;
+
+        while (tmp_q > cpi->worst_quality)
+        {
+            projected_bits_perframe *= 1.04;
+            tmp_q--;
+        }
+
+        // Guess at buffer level at the end of the section
+        projected_buffer_level = cpi->buffer_level - (int)((projected_bits_perframe - av_bits_per_frame) * cpi->twopass.frames_to_key);
+
+        if (0)
+        {
+            FILE *f = fopen("Subsamle.stt", "a");
+            fprintf(f, " %8d %8d %8d %8d %12.0f %8d %8d %8d\n",  cpi->common.current_video_frame, kf_q, cpi->common.horiz_scale, cpi->common.vert_scale,  kf_group_err / cpi->twopass.frames_to_key, (int)(cpi->twopass.kf_group_bits / cpi->twopass.frames_to_key), new_height, new_width);
+            fclose(f);
+        }
+
+        // The trigger for spatial resampling depends on the various parameters such as whether we are streaming (CBR) or VBR.
+        if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+        {
+            // Trigger resample if we are projected to fall below down sample level or
+            // resampled last time and are projected to remain below the up sample level
+            if ((projected_buffer_level < (cpi->oxcf.resample_down_water_mark * cpi->oxcf.optimal_buffer_level / 100)) ||
+                (last_kf_resampled && (projected_buffer_level < (cpi->oxcf.resample_up_water_mark * cpi->oxcf.optimal_buffer_level / 100))))
+                //( ((cpi->buffer_level < (cpi->oxcf.resample_down_water_mark * cpi->oxcf.optimal_buffer_level / 100))) &&
+                //  ((projected_buffer_level < (cpi->oxcf.resample_up_water_mark * cpi->oxcf.optimal_buffer_level / 100))) ))
+                resample_trigger = 1;
+            else
+                resample_trigger = 0;
+        }
+        else
+        {
+            int64_t clip_bits = (int64_t)(cpi->twopass.total_stats.count * cpi->oxcf.target_bandwidth / DOUBLE_DIVIDE_CHECK((double)cpi->frame_rate));
+            int64_t over_spend = cpi->oxcf.starting_buffer_level - cpi->buffer_level;
+
+            if ((last_kf_resampled && (kf_q > cpi->worst_quality)) ||                                               // If triggered last time the threshold for triggering again is reduced
+                ((kf_q > cpi->worst_quality) &&                                                                  // Projected Q higher than allowed and ...
+                 (over_spend > clip_bits / 20)))                                                               // ... Overspend > 5% of total bits
+                resample_trigger = 1;
+            else
+                resample_trigger = 0;
+
+        }
+
+        if (resample_trigger)
+        {
+            while ((kf_q >= cpi->worst_quality) && (scale_val < 6))
+            {
+                scale_val ++;
+
+                cpi->common.vert_scale   = vscale_lookup[scale_val];
+                cpi->common.horiz_scale  = hscale_lookup[scale_val];
+
+                Scale2Ratio(cpi->common.horiz_scale, &hr, &hs);
+                Scale2Ratio(cpi->common.vert_scale, &vr, &vs);
+
+                new_width = ((hs - 1) + (cpi->oxcf.Width * hr)) / hs;
+                new_height = ((vs - 1) + (cpi->oxcf.Height * vr)) / vs;
+
+                // Reducing the area to 1/4 does not reduce the complexity (err_per_frame) to 1/4...
+                // effective_sizeratio attempts to provide a crude correction for this
+                effective_size_ratio = (double)(new_width * new_height) / (double)(cpi->oxcf.Width * cpi->oxcf.Height);
+                effective_size_ratio = (1.0 + (3.0 * effective_size_ratio)) / 4.0;
+
+                // Now try again and see what Q we get with the smaller image size
+                kf_q = estimate_kf_group_q(cpi, err_per_frame * effective_size_ratio, bits_per_frame, group_iiratio);
+
+                if (0)
+                {
+                    FILE *f = fopen("Subsamle.stt", "a");
+                    fprintf(f, "******** %8d %8d %8d %12.0f %8d %8d %8d\n",  kf_q, cpi->common.horiz_scale, cpi->common.vert_scale,  kf_group_err / cpi->twopass.frames_to_key, (int)(cpi->twopass.kf_group_bits / cpi->twopass.frames_to_key), new_height, new_width);
+                    fclose(f);
+                }
+            }
+        }
+
+        if ((cpi->common.Width != new_width) || (cpi->common.Height != new_height))
+        {
+            cpi->common.Width = new_width;
+            cpi->common.Height = new_height;
+            vp8_alloc_compressor_data(cpi);
+        }
+    }
+}
diff --git a/vp8/encoder/firstpass.h b/vp8/encoder/firstpass.h
new file mode 100644 (file)
index 0000000..95e1e54
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#if !defined __INC_FIRSTPASS_H
+#define      __INC_FIRSTPASS_H
+
+extern void vp8_init_first_pass(VP8_COMP *cpi);
+extern void vp8_first_pass(VP8_COMP *cpi);
+extern void vp8_end_first_pass(VP8_COMP *cpi);
+
+extern void vp8_init_second_pass(VP8_COMP *cpi);
+extern void vp8_second_pass(VP8_COMP *cpi);
+extern void vp8_end_second_pass(VP8_COMP *cpi);
+
+extern size_t vp8_firstpass_stats_sz(unsigned int mb_count);
+#endif
diff --git a/vp8/encoder/lookahead.c b/vp8/encoder/lookahead.c
new file mode 100644 (file)
index 0000000..4c92281
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#include <assert.h>
+#include <stdlib.h>
+#include "vpx_config.h"
+#include "lookahead.h"
+#include "vp8/common/extend.h"
+
+#define MAX_LAG_BUFFERS (CONFIG_REALTIME_ONLY? 1 : 25)
+
+struct lookahead_ctx
+{
+    unsigned int max_sz;         /* Absolute size of the queue */
+    unsigned int sz;             /* Number of buffers currently in the queue */
+    unsigned int read_idx;       /* Read index */
+    unsigned int write_idx;      /* Write index */
+    struct lookahead_entry *buf; /* Buffer list */
+};
+
+
+/* Return the buffer at the given absolute index and increment the index */
+static struct lookahead_entry *
+pop(struct lookahead_ctx *ctx,
+    unsigned int         *idx)
+{
+    unsigned int            index = *idx;
+    struct lookahead_entry *buf = ctx->buf + index;
+
+    assert(index < ctx->max_sz);
+    if(++index >= ctx->max_sz)
+        index -= ctx->max_sz;
+    *idx = index;
+    return buf;
+}
+
+
+void
+vp8_lookahead_destroy(struct lookahead_ctx *ctx)
+{
+    if(ctx)
+    {
+        if(ctx->buf)
+        {
+            unsigned int i;
+
+            for(i = 0; i < ctx->max_sz; i++)
+                vp8_yv12_de_alloc_frame_buffer(&ctx->buf[i].img);
+            free(ctx->buf);
+        }
+        free(ctx);
+    }
+}
+
+
+struct lookahead_ctx*
+vp8_lookahead_init(unsigned int width,
+                   unsigned int height,
+                   unsigned int depth)
+{
+    struct lookahead_ctx *ctx = NULL;
+    unsigned int i;
+
+    /* Clamp the lookahead queue depth */
+    if(depth < 1)
+        depth = 1;
+    else if(depth > MAX_LAG_BUFFERS)
+        depth = MAX_LAG_BUFFERS;
+
+    /* Keep last frame in lookahead buffer by increasing depth by 1.*/
+    depth += 1;
+
+    /* Align the buffer dimensions */
+    width = (width + 15) & ~15;
+    height = (height + 15) & ~15;
+
+    /* Allocate the lookahead structures */
+    ctx = calloc(1, sizeof(*ctx));
+    if(ctx)
+    {
+        ctx->max_sz = depth;
+        ctx->buf = calloc(depth, sizeof(*ctx->buf));
+        if(!ctx->buf)
+            goto bail;
+        for(i=0; i<depth; i++)
+            if (vp8_yv12_alloc_frame_buffer(&ctx->buf[i].img,
+                                            width, height, VP8BORDERINPIXELS))
+                goto bail;
+    }
+    return ctx;
+bail:
+    vp8_lookahead_destroy(ctx);
+    return NULL;
+}
+
+
+int
+vp8_lookahead_push(struct lookahead_ctx *ctx,
+                   YV12_BUFFER_CONFIG   *src,
+                   int64_t               ts_start,
+                   int64_t               ts_end,
+                   unsigned int          flags,
+                   unsigned char        *active_map)
+{
+    struct lookahead_entry* buf;
+    int row, col, active_end;
+    int mb_rows = (src->y_height + 15) >> 4;
+    int mb_cols = (src->y_width + 15) >> 4;
+
+    if(ctx->sz + 2 > ctx->max_sz)
+        return 1;
+    ctx->sz++;
+    buf = pop(ctx, &ctx->write_idx);
+
+    // Only do this partial copy if the following conditions are all met:
+    // 1. Lookahead queue has has size of 1.
+    // 2. Active map is provided.
+    // 3. This is not a key frame, golden nor altref frame.
+    if (ctx->max_sz == 1 && active_map && !flags)
+    {
+        for (row = 0; row < mb_rows; ++row)
+        {
+            col = 0;
+
+            while (1)
+            {
+                // Find the first active macroblock in this row.
+                for (; col < mb_cols; ++col)
+                {
+                    if (active_map[col])
+                        break;
+                }
+
+                // No more active macroblock in this row.
+                if (col == mb_cols)
+                    break;
+
+                // Find the end of active region in this row.
+                active_end = col;
+
+                for (; active_end < mb_cols; ++active_end)
+                {
+                    if (!active_map[active_end])
+                        break;
+                }
+
+                // Only copy this active region.
+                vp8_copy_and_extend_frame_with_rect(src, &buf->img,
+                                                    row << 4,
+                                                    col << 4, 16,
+                                                    (active_end - col) << 4);
+
+                // Start again from the end of this active region.
+                col = active_end;
+            }
+
+            active_map += mb_cols;
+        }
+    }
+    else
+    {
+        vp8_copy_and_extend_frame(src, &buf->img);
+    }
+    buf->ts_start = ts_start;
+    buf->ts_end = ts_end;
+    buf->flags = flags;
+    return 0;
+}
+
+
+struct lookahead_entry*
+vp8_lookahead_pop(struct lookahead_ctx *ctx,
+                  int                   drain)
+{
+    struct lookahead_entry* buf = NULL;
+
+    if(ctx->sz && (drain || ctx->sz == ctx->max_sz - 1))
+    {
+        buf = pop(ctx, &ctx->read_idx);
+        ctx->sz--;
+    }
+    return buf;
+}
+
+
+struct lookahead_entry*
+vp8_lookahead_peek(struct lookahead_ctx *ctx,
+                   unsigned int          index,
+                   int                   direction)
+{
+    struct lookahead_entry* buf = NULL;
+
+    if (direction == PEEK_FORWARD)
+    {
+        assert(index < ctx->max_sz - 1);
+        if(index < ctx->sz)
+        {
+            index += ctx->read_idx;
+            if(index >= ctx->max_sz)
+                index -= ctx->max_sz;
+            buf = ctx->buf + index;
+        }
+    }
+    else if (direction == PEEK_BACKWARD)
+    {
+        assert(index == 1);
+
+        if(ctx->read_idx == 0)
+            index = ctx->max_sz - 1;
+        else
+            index = ctx->read_idx - index;
+        buf = ctx->buf + index;
+    }
+
+    return buf;
+}
+
+
+unsigned int
+vp8_lookahead_depth(struct lookahead_ctx *ctx)
+{
+    return ctx->sz;
+}
diff --git a/vp8/encoder/lookahead.h b/vp8/encoder/lookahead.h
new file mode 100644 (file)
index 0000000..cf56b75
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef LOOKAHEAD_H
+#define LOOKAHEAD_H
+#include "vpx_scale/yv12config.h"
+#include "vpx/vpx_integer.h"
+
+struct lookahead_entry
+{
+    YV12_BUFFER_CONFIG  img;
+    int64_t             ts_start;
+    int64_t             ts_end;
+    unsigned int        flags;
+};
+
+
+struct lookahead_ctx;
+
+/**\brief Initializes the lookahead stage
+ *
+ * The lookahead stage is a queue of frame buffers on which some analysis
+ * may be done when buffers are enqueued.
+ *
+ *
+ */
+struct lookahead_ctx* vp8_lookahead_init(unsigned int width,
+                                         unsigned int height,
+                                         unsigned int depth
+                                         );
+
+
+/**\brief Destroys the lookahead stage
+ *
+ */
+void vp8_lookahead_destroy(struct lookahead_ctx *ctx);
+
+
+/**\brief Enqueue a source buffer
+ *
+ * This function will copy the source image into a new framebuffer with
+ * the expected stride/border.
+ *
+ * If active_map is non-NULL and there is only one frame in the queue, then copy
+ * only active macroblocks.
+ *
+ * \param[in] ctx         Pointer to the lookahead context
+ * \param[in] src         Pointer to the image to enqueue
+ * \param[in] ts_start    Timestamp for the start of this frame
+ * \param[in] ts_end      Timestamp for the end of this frame
+ * \param[in] flags       Flags set on this frame
+ * \param[in] active_map  Map that specifies which macroblock is active
+ */
+int
+vp8_lookahead_push(struct lookahead_ctx *ctx,
+                   YV12_BUFFER_CONFIG   *src,
+                   int64_t               ts_start,
+                   int64_t               ts_end,
+                   unsigned int          flags,
+                   unsigned char        *active_map);
+
+
+/**\brief Get the next source buffer to encode
+ *
+ *
+ * \param[in] ctx       Pointer to the lookahead context
+ * \param[in] drain     Flag indicating the buffer should be drained
+ *                      (return a buffer regardless of the current queue depth)
+ *
+ * \retval NULL, if drain set and queue is empty
+ * \retval NULL, if drain not set and queue not of the configured depth
+ *
+ */
+struct lookahead_entry*
+vp8_lookahead_pop(struct lookahead_ctx *ctx,
+                  int                   drain);
+
+
+#define PEEK_FORWARD   1
+#define PEEK_BACKWARD -1
+/**\brief Get a future source buffer to encode
+ *
+ * \param[in] ctx       Pointer to the lookahead context
+ * \param[in] index     Index of the frame to be returned, 0 == next frame
+ *
+ * \retval NULL, if no buffer exists at the specified index
+ *
+ */
+struct lookahead_entry*
+vp8_lookahead_peek(struct lookahead_ctx *ctx,
+                   unsigned int          index,
+                   int                   direction);
+
+
+/**\brief Get the number of frames currently in the lookahead queue
+ *
+ * \param[in] ctx       Pointer to the lookahead context
+ */
+unsigned int
+vp8_lookahead_depth(struct lookahead_ctx *ctx);
+
+
+#endif
diff --git a/vp8/encoder/mcomp.c b/vp8/encoder/mcomp.c
new file mode 100644 (file)
index 0000000..67e4f7e
--- /dev/null
@@ -0,0 +1,2003 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "onyx_int.h"
+#include "mcomp.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_config.h"
+#include <stdio.h>
+#include <limits.h>
+#include <math.h>
+#include "vp8/common/findnearmv.h"
+
+#ifdef ENTROPY_STATS
+static int mv_ref_ct [31] [4] [2];
+static int mv_mode_cts [4] [2];
+#endif
+
+int vp8_mv_bit_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int Weight)
+{
+    // MV costing is based on the distribution of vectors in the previous frame and as such will tend to
+    // over state the cost of vectors. In addition coding a new vector can have a knock on effect on the
+    // cost of subsequent vectors and the quality of prediction from NEAR and NEAREST for subsequent blocks.
+    // The "Weight" parameter allows, to a limited extent, for some account to be taken of these factors.
+    return ((mvcost[0][(mv->as_mv.row - ref->as_mv.row) >> 1] + mvcost[1][(mv->as_mv.col - ref->as_mv.col) >> 1]) * Weight) >> 7;
+}
+
+static int mv_err_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int error_per_bit)
+{
+    return ((mvcost[0][(mv->as_mv.row - ref->as_mv.row) >> 1] +
+        mvcost[1][(mv->as_mv.col - ref->as_mv.col) >> 1])
+        * error_per_bit + 128) >> 8;
+}
+
+static int mvsad_err_cost(int_mv *mv, int_mv *ref, int *mvsadcost[2], int error_per_bit)
+{
+    /* Calculate sad error cost on full pixel basis. */
+    return ((mvsadcost[0][(mv->as_mv.row - ref->as_mv.row)] +
+        mvsadcost[1][(mv->as_mv.col - ref->as_mv.col)])
+        * error_per_bit + 128) >> 8;
+}
+
+void vp8_init_dsmotion_compensation(MACROBLOCK *x, int stride)
+{
+    int Len;
+    int search_site_count = 0;
+
+
+    // Generate offsets for 4 search sites per step.
+    Len = MAX_FIRST_STEP;
+    x->ss[search_site_count].mv.col = 0;
+    x->ss[search_site_count].mv.row = 0;
+    x->ss[search_site_count].offset = 0;
+    search_site_count++;
+
+    while (Len > 0)
+    {
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = 0;
+        x->ss[search_site_count].mv.row = -Len;
+        x->ss[search_site_count].offset = -Len * stride;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = 0;
+        x->ss[search_site_count].mv.row = Len;
+        x->ss[search_site_count].offset = Len * stride;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = -Len;
+        x->ss[search_site_count].mv.row = 0;
+        x->ss[search_site_count].offset = -Len;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = Len;
+        x->ss[search_site_count].mv.row = 0;
+        x->ss[search_site_count].offset = Len;
+        search_site_count++;
+
+        // Contract.
+        Len /= 2;
+    }
+
+    x->ss_count = search_site_count;
+    x->searches_per_step = 4;
+}
+
+void vp8_init3smotion_compensation(MACROBLOCK *x, int stride)
+{
+    int Len;
+    int search_site_count = 0;
+
+    // Generate offsets for 8 search sites per step.
+    Len = MAX_FIRST_STEP;
+    x->ss[search_site_count].mv.col = 0;
+    x->ss[search_site_count].mv.row = 0;
+    x->ss[search_site_count].offset = 0;
+    search_site_count++;
+
+    while (Len > 0)
+    {
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = 0;
+        x->ss[search_site_count].mv.row = -Len;
+        x->ss[search_site_count].offset = -Len * stride;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = 0;
+        x->ss[search_site_count].mv.row = Len;
+        x->ss[search_site_count].offset = Len * stride;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = -Len;
+        x->ss[search_site_count].mv.row = 0;
+        x->ss[search_site_count].offset = -Len;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = Len;
+        x->ss[search_site_count].mv.row = 0;
+        x->ss[search_site_count].offset = Len;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = -Len;
+        x->ss[search_site_count].mv.row = -Len;
+        x->ss[search_site_count].offset = -Len * stride - Len;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = Len;
+        x->ss[search_site_count].mv.row = -Len;
+        x->ss[search_site_count].offset = -Len * stride + Len;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = -Len;
+        x->ss[search_site_count].mv.row = Len;
+        x->ss[search_site_count].offset = Len * stride - Len;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = Len;
+        x->ss[search_site_count].mv.row = Len;
+        x->ss[search_site_count].offset = Len * stride + Len;
+        search_site_count++;
+
+
+        // Contract.
+        Len /= 2;
+    }
+
+    x->ss_count = search_site_count;
+    x->searches_per_step = 8;
+}
+
+/*
+ * To avoid the penalty for crossing cache-line read, preload the reference
+ * area in a small buffer, which is aligned to make sure there won't be crossing
+ * cache-line read while reading from this buffer. This reduced the cpu
+ * cycles spent on reading ref data in sub-pixel filter functions.
+ * TODO: Currently, since sub-pixel search range here is -3 ~ 3, copy 22 rows x
+ * 32 cols area that is enough for 16x16 macroblock. Later, for SPLITMV, we
+ * could reduce the area.
+ */
+#define MVC(r,c) (((mvcost[0][(r)-rr] + mvcost[1][(c) - rc]) * error_per_bit + 128 )>>8 ) // estimated cost of a motion vector (r,c)
+#define PRE(r,c) (y + (((r)>>2) * y_stride + ((c)>>2) -(offset))) // pointer to predictor base of a motionvector
+#define SP(x) (((x)&3)<<1) // convert motion vector component to offset for svf calc
+#define DIST(r,c) vfp->svf( PRE(r,c), y_stride, SP(c),SP(r), z,b->src_stride,&sse) // returns subpixel variance error function.
+#define IFMVCV(r,c,s,e) if ( c >= minc && c <= maxc && r >= minr && r <= maxr) s else e;
+#define ERR(r,c) (MVC(r,c)+DIST(r,c)) // returns distortion + motion vector cost
+#define CHECK_BETTER(v,r,c) IFMVCV(r,c,{thismse = DIST(r,c); if((v = (MVC(r,c)+thismse)) < besterr) { besterr = v; br=r; bc=c; *distortion = thismse; *sse1 = sse; }}, v=INT_MAX;)// checks if (r,c) has better score than previous best
+
+int vp8_find_best_sub_pixel_step_iteratively(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
+                                             int_mv *bestmv, int_mv *ref_mv,
+                                             int error_per_bit,
+                                             const vp8_variance_fn_ptr_t *vfp,
+                                             int *mvcost[2], int *distortion,
+                                             unsigned int *sse1)
+{
+    unsigned char *z = (*(b->base_src) + b->src);
+
+    int rr = ref_mv->as_mv.row >> 1, rc = ref_mv->as_mv.col >> 1;
+    int br = bestmv->as_mv.row << 2, bc = bestmv->as_mv.col << 2;
+    int tr = br, tc = bc;
+    unsigned int besterr = INT_MAX;
+    unsigned int left, right, up, down, diag;
+    unsigned int sse;
+    unsigned int whichdir;
+    unsigned int halfiters = 4;
+    unsigned int quarteriters = 4;
+    int thismse;
+
+    int minc = MAX(x->mv_col_min << 2, (ref_mv->as_mv.col >> 1) - ((1 << mvlong_width) - 1));
+    int maxc = MIN(x->mv_col_max << 2, (ref_mv->as_mv.col >> 1) + ((1 << mvlong_width) - 1));
+    int minr = MAX(x->mv_row_min << 2, (ref_mv->as_mv.row >> 1) - ((1 << mvlong_width) - 1));
+    int maxr = MIN(x->mv_row_max << 2, (ref_mv->as_mv.row >> 1) + ((1 << mvlong_width) - 1));
+
+    int y_stride;
+    int offset;
+    int pre_stride = x->e_mbd.pre.y_stride;
+    unsigned char *base_pre = x->e_mbd.pre.y_buffer;
+
+
+#if ARCH_X86 || ARCH_X86_64
+    MACROBLOCKD *xd = &x->e_mbd;
+    unsigned char *y0 = base_pre + d->offset + (bestmv->as_mv.row) * pre_stride + bestmv->as_mv.col;
+    unsigned char *y;
+    int buf_r1, buf_r2, buf_c1, buf_c2;
+
+    // Clamping to avoid out-of-range data access
+    buf_r1 = ((bestmv->as_mv.row - 3) < x->mv_row_min)?(bestmv->as_mv.row - x->mv_row_min):3;
+    buf_r2 = ((bestmv->as_mv.row + 3) > x->mv_row_max)?(x->mv_row_max - bestmv->as_mv.row):3;
+    buf_c1 = ((bestmv->as_mv.col - 3) < x->mv_col_min)?(bestmv->as_mv.col - x->mv_col_min):3;
+    buf_c2 = ((bestmv->as_mv.col + 3) > x->mv_col_max)?(x->mv_col_max - bestmv->as_mv.col):3;
+    y_stride = 32;
+
+    /* Copy to intermediate buffer before searching. */
+    vfp->copymem(y0 - buf_c1 - pre_stride*buf_r1, pre_stride, xd->y_buf, y_stride, 16+buf_r1+buf_r2);
+    y = xd->y_buf + y_stride*buf_r1 +buf_c1;
+#else
+    unsigned char *y = base_pre + d->offset + (bestmv->as_mv.row) * pre_stride + bestmv->as_mv.col;
+    y_stride = pre_stride;
+#endif
+
+    offset = (bestmv->as_mv.row) * y_stride + bestmv->as_mv.col;
+
+    // central mv
+    bestmv->as_mv.row <<= 3;
+    bestmv->as_mv.col <<= 3;
+
+    // calculate central point error
+    besterr = vfp->vf(y, y_stride, z, b->src_stride, sse1);
+    *distortion = besterr;
+    besterr += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
+
+    // TODO: Each subsequent iteration checks at least one point in common with the last iteration could be 2 ( if diag selected)
+    while (--halfiters)
+    {
+        // 1/2 pel
+        CHECK_BETTER(left, tr, tc - 2);
+        CHECK_BETTER(right, tr, tc + 2);
+        CHECK_BETTER(up, tr - 2, tc);
+        CHECK_BETTER(down, tr + 2, tc);
+
+        whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
+
+        switch (whichdir)
+        {
+        case 0:
+            CHECK_BETTER(diag, tr - 2, tc - 2);
+            break;
+        case 1:
+            CHECK_BETTER(diag, tr - 2, tc + 2);
+            break;
+        case 2:
+            CHECK_BETTER(diag, tr + 2, tc - 2);
+            break;
+        case 3:
+            CHECK_BETTER(diag, tr + 2, tc + 2);
+            break;
+        }
+
+        // no reason to check the same one again.
+        if (tr == br && tc == bc)
+            break;
+
+        tr = br;
+        tc = bc;
+    }
+
+    // TODO: Each subsequent iteration checks at least one point in common with the last iteration could be 2 ( if diag selected)
+    // 1/4 pel
+    while (--quarteriters)
+    {
+        CHECK_BETTER(left, tr, tc - 1);
+        CHECK_BETTER(right, tr, tc + 1);
+        CHECK_BETTER(up, tr - 1, tc);
+        CHECK_BETTER(down, tr + 1, tc);
+
+        whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
+
+        switch (whichdir)
+        {
+        case 0:
+            CHECK_BETTER(diag, tr - 1, tc - 1);
+            break;
+        case 1:
+            CHECK_BETTER(diag, tr - 1, tc + 1);
+            break;
+        case 2:
+            CHECK_BETTER(diag, tr + 1, tc - 1);
+            break;
+        case 3:
+            CHECK_BETTER(diag, tr + 1, tc + 1);
+            break;
+        }
+
+        // no reason to check the same one again.
+        if (tr == br && tc == bc)
+            break;
+
+        tr = br;
+        tc = bc;
+    }
+
+    bestmv->as_mv.row = br << 1;
+    bestmv->as_mv.col = bc << 1;
+
+    if ((abs(bestmv->as_mv.col - ref_mv->as_mv.col) > (MAX_FULL_PEL_VAL<<3)) ||
+        (abs(bestmv->as_mv.row - ref_mv->as_mv.row) > (MAX_FULL_PEL_VAL<<3)))
+        return INT_MAX;
+
+    return besterr;
+}
+#undef MVC
+#undef PRE
+#undef SP
+#undef DIST
+#undef IFMVCV
+#undef ERR
+#undef CHECK_BETTER
+
+int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
+                                 int_mv *bestmv, int_mv *ref_mv,
+                                 int error_per_bit,
+                                 const vp8_variance_fn_ptr_t *vfp,
+                                 int *mvcost[2], int *distortion,
+                                 unsigned int *sse1)
+{
+    int bestmse = INT_MAX;
+    int_mv startmv;
+    int_mv this_mv;
+    unsigned char *z = (*(b->base_src) + b->src);
+    int left, right, up, down, diag;
+    unsigned int sse;
+    int whichdir ;
+    int thismse;
+    int y_stride;
+    int pre_stride = x->e_mbd.pre.y_stride;
+    unsigned char *base_pre = x->e_mbd.pre.y_buffer;
+
+#if ARCH_X86 || ARCH_X86_64
+    MACROBLOCKD *xd = &x->e_mbd;
+    unsigned char *y0 = base_pre + d->offset + (bestmv->as_mv.row) * pre_stride + bestmv->as_mv.col;
+    unsigned char *y;
+
+    y_stride = 32;
+    /* Copy 18 rows x 32 cols area to intermediate buffer before searching. */
+     vfp->copymem(y0 - 1 - pre_stride, pre_stride, xd->y_buf, y_stride, 18);
+     y = xd->y_buf + y_stride + 1;
+#else
+     unsigned char *y = base_pre + d->offset + (bestmv->as_mv.row) * pre_stride + bestmv->as_mv.col;
+     y_stride = pre_stride;
+#endif
+
+    // central mv
+    bestmv->as_mv.row <<= 3;
+    bestmv->as_mv.col <<= 3;
+    startmv = *bestmv;
+
+    // calculate central point error
+    bestmse = vfp->vf(y, y_stride, z, b->src_stride, sse1);
+    *distortion = bestmse;
+    bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
+
+    // go left then right and check error
+    this_mv.as_mv.row = startmv.as_mv.row;
+    this_mv.as_mv.col = ((startmv.as_mv.col - 8) | 4);
+    thismse = vfp->svf_halfpix_h(y - 1, y_stride, z, b->src_stride, &sse);
+    left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (left < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = left;
+        *distortion = thismse;
+        *sse1 = sse;
+    }
+
+    this_mv.as_mv.col += 8;
+    thismse = vfp->svf_halfpix_h(y, y_stride, z, b->src_stride, &sse);
+    right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (right < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = right;
+        *distortion = thismse;
+        *sse1 = sse;
+    }
+
+    // go up then down and check error
+    this_mv.as_mv.col = startmv.as_mv.col;
+    this_mv.as_mv.row = ((startmv.as_mv.row - 8) | 4);
+    thismse =  vfp->svf_halfpix_v(y - y_stride, y_stride, z, b->src_stride, &sse);
+    up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (up < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = up;
+        *distortion = thismse;
+        *sse1 = sse;
+    }
+
+    this_mv.as_mv.row += 8;
+    thismse = vfp->svf_halfpix_v(y, y_stride, z, b->src_stride, &sse);
+    down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (down < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = down;
+        *distortion = thismse;
+        *sse1 = sse;
+    }
+
+
+    // now check 1 more diagonal
+    whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
+    //for(whichdir =0;whichdir<4;whichdir++)
+    //{
+    this_mv = startmv;
+
+    switch (whichdir)
+    {
+    case 0:
+        this_mv.as_mv.col = (this_mv.as_mv.col - 8) | 4;
+        this_mv.as_mv.row = (this_mv.as_mv.row - 8) | 4;
+        thismse = vfp->svf_halfpix_hv(y - 1 - y_stride, y_stride, z, b->src_stride, &sse);
+        break;
+    case 1:
+        this_mv.as_mv.col += 4;
+        this_mv.as_mv.row = (this_mv.as_mv.row - 8) | 4;
+        thismse = vfp->svf_halfpix_hv(y - y_stride, y_stride, z, b->src_stride, &sse);
+        break;
+    case 2:
+        this_mv.as_mv.col = (this_mv.as_mv.col - 8) | 4;
+        this_mv.as_mv.row += 4;
+        thismse = vfp->svf_halfpix_hv(y - 1, y_stride, z, b->src_stride, &sse);
+        break;
+    case 3:
+    default:
+        this_mv.as_mv.col += 4;
+        this_mv.as_mv.row += 4;
+        thismse = vfp->svf_halfpix_hv(y, y_stride, z, b->src_stride, &sse);
+        break;
+    }
+
+    diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (diag < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = diag;
+        *distortion = thismse;
+        *sse1 = sse;
+    }
+
+//  }
+
+
+    // time to check quarter pels.
+    if (bestmv->as_mv.row < startmv.as_mv.row)
+        y -= y_stride;
+
+    if (bestmv->as_mv.col < startmv.as_mv.col)
+        y--;
+
+    startmv = *bestmv;
+
+
+
+    // go left then right and check error
+    this_mv.as_mv.row = startmv.as_mv.row;
+
+    if (startmv.as_mv.col & 7)
+    {
+        this_mv.as_mv.col = startmv.as_mv.col - 2;
+        thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
+    }
+    else
+    {
+        this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
+        thismse = vfp->svf(y - 1, y_stride, 6, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
+    }
+
+    left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (left < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = left;
+        *distortion = thismse;
+        *sse1 = sse;
+    }
+
+    this_mv.as_mv.col += 4;
+    thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
+    right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (right < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = right;
+        *distortion = thismse;
+        *sse1 = sse;
+    }
+
+    // go up then down and check error
+    this_mv.as_mv.col = startmv.as_mv.col;
+
+    if (startmv.as_mv.row & 7)
+    {
+        this_mv.as_mv.row = startmv.as_mv.row - 2;
+        thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
+    }
+    else
+    {
+        this_mv.as_mv.row = (startmv.as_mv.row - 8) | 6;
+        thismse = vfp->svf(y - y_stride, y_stride, this_mv.as_mv.col & 7, 6, z, b->src_stride, &sse);
+    }
+
+    up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (up < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = up;
+        *distortion = thismse;
+        *sse1 = sse;
+    }
+
+    this_mv.as_mv.row += 4;
+    thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
+    down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (down < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = down;
+        *distortion = thismse;
+        *sse1 = sse;
+    }
+
+
+    // now check 1 more diagonal
+    whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
+
+//  for(whichdir=0;whichdir<4;whichdir++)
+//  {
+    this_mv = startmv;
+
+    switch (whichdir)
+    {
+    case 0:
+
+        if (startmv.as_mv.row & 7)
+        {
+            this_mv.as_mv.row -= 2;
+
+            if (startmv.as_mv.col & 7)
+            {
+                this_mv.as_mv.col -= 2;
+                thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
+            }
+            else
+            {
+                this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
+                thismse = vfp->svf(y - 1, y_stride, 6, this_mv.as_mv.row & 7, z, b->src_stride, &sse);;
+            }
+        }
+        else
+        {
+            this_mv.as_mv.row = (startmv.as_mv.row - 8) | 6;
+
+            if (startmv.as_mv.col & 7)
+            {
+                this_mv.as_mv.col -= 2;
+                thismse = vfp->svf(y - y_stride, y_stride, this_mv.as_mv.col & 7, 6, z, b->src_stride, &sse);
+            }
+            else
+            {
+                this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
+                thismse = vfp->svf(y - y_stride - 1, y_stride, 6, 6, z, b->src_stride, &sse);
+            }
+        }
+
+        break;
+    case 1:
+        this_mv.as_mv.col += 2;
+
+        if (startmv.as_mv.row & 7)
+        {
+            this_mv.as_mv.row -= 2;
+            thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
+        }
+        else
+        {
+            this_mv.as_mv.row = (startmv.as_mv.row - 8) | 6;
+            thismse = vfp->svf(y - y_stride, y_stride, this_mv.as_mv.col & 7, 6, z, b->src_stride, &sse);
+        }
+
+        break;
+    case 2:
+        this_mv.as_mv.row += 2;
+
+        if (startmv.as_mv.col & 7)
+        {
+            this_mv.as_mv.col -= 2;
+            thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
+        }
+        else
+        {
+            this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
+            thismse = vfp->svf(y - 1, y_stride, 6, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
+        }
+
+        break;
+    case 3:
+        this_mv.as_mv.col += 2;
+        this_mv.as_mv.row += 2;
+        thismse = vfp->svf(y, y_stride,  this_mv.as_mv.col & 7, this_mv.as_mv.row & 7, z, b->src_stride, &sse);
+        break;
+    }
+
+    diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (diag < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = diag;
+        *distortion = thismse;
+        *sse1 = sse;
+    }
+
+    return bestmse;
+}
+
+int vp8_find_best_half_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
+                                  int_mv *bestmv, int_mv *ref_mv,
+                                  int error_per_bit,
+                                  const vp8_variance_fn_ptr_t *vfp,
+                                  int *mvcost[2], int *distortion,
+                                  unsigned int *sse1)
+{
+    int bestmse = INT_MAX;
+    int_mv startmv;
+    int_mv this_mv;
+    unsigned char *z = (*(b->base_src) + b->src);
+    int left, right, up, down, diag;
+    unsigned int sse;
+    int whichdir ;
+    int thismse;
+    int y_stride;
+    int pre_stride = x->e_mbd.pre.y_stride;
+    unsigned char *base_pre = x->e_mbd.pre.y_buffer;
+
+#if ARCH_X86 || ARCH_X86_64
+    MACROBLOCKD *xd = &x->e_mbd;
+    unsigned char *y0 = base_pre + d->offset + (bestmv->as_mv.row) * pre_stride + bestmv->as_mv.col;
+    unsigned char *y;
+
+    y_stride = 32;
+    /* Copy 18 rows x 32 cols area to intermediate buffer before searching. */
+    vfp->copymem(y0 - 1 - pre_stride, pre_stride, xd->y_buf, y_stride, 18);
+    y = xd->y_buf + y_stride + 1;
+#else
+    unsigned char *y = base_pre + d->offset + (bestmv->as_mv.row) * pre_stride + bestmv->as_mv.col;
+    y_stride = pre_stride;
+#endif
+
+    // central mv
+    bestmv->as_mv.row <<= 3;
+    bestmv->as_mv.col <<= 3;
+    startmv = *bestmv;
+
+    // calculate central point error
+    bestmse = vfp->vf(y, y_stride, z, b->src_stride, sse1);
+    *distortion = bestmse;
+    bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
+
+    // go left then right and check error
+    this_mv.as_mv.row = startmv.as_mv.row;
+    this_mv.as_mv.col = ((startmv.as_mv.col - 8) | 4);
+    thismse = vfp->svf_halfpix_h(y - 1, y_stride, z, b->src_stride, &sse);
+    left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (left < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = left;
+        *distortion = thismse;
+        *sse1 = sse;
+    }
+
+    this_mv.as_mv.col += 8;
+    thismse = vfp->svf_halfpix_h(y, y_stride, z, b->src_stride, &sse);
+    right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (right < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = right;
+        *distortion = thismse;
+        *sse1 = sse;
+    }
+
+    // go up then down and check error
+    this_mv.as_mv.col = startmv.as_mv.col;
+    this_mv.as_mv.row = ((startmv.as_mv.row - 8) | 4);
+    thismse = vfp->svf_halfpix_v(y - y_stride, y_stride, z, b->src_stride, &sse);
+    up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (up < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = up;
+        *distortion = thismse;
+        *sse1 = sse;
+    }
+
+    this_mv.as_mv.row += 8;
+    thismse = vfp->svf_halfpix_v(y, y_stride, z, b->src_stride, &sse);
+    down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (down < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = down;
+        *distortion = thismse;
+        *sse1 = sse;
+    }
+
+    // now check 1 more diagonal -
+    whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
+    this_mv = startmv;
+
+    switch (whichdir)
+    {
+    case 0:
+        this_mv.as_mv.col = (this_mv.as_mv.col - 8) | 4;
+        this_mv.as_mv.row = (this_mv.as_mv.row - 8) | 4;
+        thismse = vfp->svf_halfpix_hv(y - 1 - y_stride, y_stride, z, b->src_stride, &sse);
+        break;
+    case 1:
+        this_mv.as_mv.col += 4;
+        this_mv.as_mv.row = (this_mv.as_mv.row - 8) | 4;
+        thismse = vfp->svf_halfpix_hv(y - y_stride, y_stride, z, b->src_stride, &sse);
+        break;
+    case 2:
+        this_mv.as_mv.col = (this_mv.as_mv.col - 8) | 4;
+        this_mv.as_mv.row += 4;
+        thismse = vfp->svf_halfpix_hv(y - 1, y_stride, z, b->src_stride, &sse);
+        break;
+    case 3:
+    default:
+        this_mv.as_mv.col += 4;
+        this_mv.as_mv.row += 4;
+        thismse = vfp->svf_halfpix_hv(y, y_stride, z, b->src_stride, &sse);
+        break;
+    }
+
+    diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (diag < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = diag;
+        *distortion = thismse;
+        *sse1 = sse;
+    }
+
+    return bestmse;
+}
+
+#define CHECK_BOUNDS(range) \
+{\
+    all_in = 1;\
+    all_in &= ((br-range) >= x->mv_row_min);\
+    all_in &= ((br+range) <= x->mv_row_max);\
+    all_in &= ((bc-range) >= x->mv_col_min);\
+    all_in &= ((bc+range) <= x->mv_col_max);\
+}
+
+#define CHECK_POINT \
+{\
+    if (this_mv.as_mv.col < x->mv_col_min) continue;\
+    if (this_mv.as_mv.col > x->mv_col_max) continue;\
+    if (this_mv.as_mv.row < x->mv_row_min) continue;\
+    if (this_mv.as_mv.row > x->mv_row_max) continue;\
+}
+
+#define CHECK_BETTER \
+{\
+    if (thissad < bestsad)\
+    {\
+        thissad += mvsad_err_cost(&this_mv, &fcenter_mv, mvsadcost, sad_per_bit);\
+        if (thissad < bestsad)\
+        {\
+            bestsad = thissad;\
+            best_site = i;\
+        }\
+    }\
+}
+
+static const MV next_chkpts[6][3] =
+{
+    {{ -2, 0}, { -1, -2}, {1, -2}},
+    {{ -1, -2}, {1, -2}, {2, 0}},
+    {{1, -2}, {2, 0}, {1, 2}},
+    {{2, 0}, {1, 2}, { -1, 2}},
+    {{1, 2}, { -1, 2}, { -2, 0}},
+    {{ -1, 2}, { -2, 0}, { -1, -2}}
+};
+
+int vp8_hex_search
+(
+    MACROBLOCK *x,
+    BLOCK *b,
+    BLOCKD *d,
+    int_mv *ref_mv,
+    int_mv *best_mv,
+    int search_param,
+    int sad_per_bit,
+    const vp8_variance_fn_ptr_t *vfp,
+    int *mvsadcost[2],
+    int *mvcost[2],
+    int_mv *center_mv
+)
+{
+    MV hex[6] = { { -1, -2}, {1, -2}, {2, 0}, {1, 2}, { -1, 2}, { -2, 0} } ;
+    MV neighbors[4] = {{0, -1}, { -1, 0}, {1, 0}, {0, 1}} ;
+    int i, j;
+
+    unsigned char *what = (*(b->base_src) + b->src);
+    int what_stride = b->src_stride;
+    int pre_stride = x->e_mbd.pre.y_stride;
+    unsigned char *base_pre = x->e_mbd.pre.y_buffer;
+
+    int in_what_stride = pre_stride;
+    int br, bc;
+    int_mv this_mv;
+    unsigned int bestsad = 0x7fffffff;
+    unsigned int thissad;
+    unsigned char *base_offset;
+    unsigned char *this_offset;
+    int k = -1;
+    int all_in;
+    int best_site = -1;
+    int hex_range = 127;
+    int dia_range = 8;
+
+    int_mv fcenter_mv;
+    fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
+    fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
+
+    // adjust ref_mv to make sure it is within MV range
+    vp8_clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
+    br = ref_mv->as_mv.row;
+    bc = ref_mv->as_mv.col;
+
+    // Work out the start point for the search
+    base_offset = (unsigned char *)(base_pre + d->offset);
+    this_offset = base_offset + (br * (pre_stride)) + bc;
+    this_mv.as_mv.row = br;
+    this_mv.as_mv.col = bc;
+    bestsad = vfp->sdf( what, what_stride, this_offset,
+                        in_what_stride, 0x7fffffff)
+            + mvsad_err_cost(&this_mv, &fcenter_mv, mvsadcost, sad_per_bit);
+
+#if CONFIG_MULTI_RES_ENCODING
+    /* Lower search range based on prediction info */
+    if (search_param >= 6) goto cal_neighbors;
+    else if (search_param >= 5) hex_range = 4;
+    else if (search_param >= 4) hex_range = 6;
+    else if (search_param >= 3) hex_range = 15;
+    else if (search_param >= 2) hex_range = 31;
+    else if (search_param >= 1) hex_range = 63;
+
+    dia_range = 8;
+#endif
+
+    // hex search
+    //j=0
+    CHECK_BOUNDS(2)
+
+    if(all_in)
+    {
+        for (i = 0; i < 6; i++)
+        {
+            this_mv.as_mv.row = br + hex[i].row;
+            this_mv.as_mv.col = bc + hex[i].col;
+            this_offset = base_offset + (this_mv.as_mv.row * in_what_stride) + this_mv.as_mv.col;
+            thissad=vfp->sdf( what, what_stride, this_offset, in_what_stride, bestsad);
+            CHECK_BETTER
+        }
+    }else
+    {
+        for (i = 0; i < 6; i++)
+        {
+            this_mv.as_mv.row = br + hex[i].row;
+            this_mv.as_mv.col = bc + hex[i].col;
+            CHECK_POINT
+            this_offset = base_offset + (this_mv.as_mv.row * in_what_stride) + this_mv.as_mv.col;
+            thissad=vfp->sdf( what, what_stride, this_offset, in_what_stride, bestsad);
+            CHECK_BETTER
+        }
+    }
+
+    if (best_site == -1)
+        goto cal_neighbors;
+    else
+    {
+        br += hex[best_site].row;
+        bc += hex[best_site].col;
+        k = best_site;
+    }
+
+    for (j = 1; j < hex_range; j++)
+    {
+        best_site = -1;
+        CHECK_BOUNDS(2)
+
+        if(all_in)
+        {
+            for (i = 0; i < 3; i++)
+            {
+                this_mv.as_mv.row = br + next_chkpts[k][i].row;
+                this_mv.as_mv.col = bc + next_chkpts[k][i].col;
+                this_offset = base_offset + (this_mv.as_mv.row * (in_what_stride)) + this_mv.as_mv.col;
+                thissad = vfp->sdf( what, what_stride, this_offset, in_what_stride, bestsad);
+                CHECK_BETTER
+            }
+        }else
+        {
+            for (i = 0; i < 3; i++)
+            {
+                this_mv.as_mv.row = br + next_chkpts[k][i].row;
+                this_mv.as_mv.col = bc + next_chkpts[k][i].col;
+                CHECK_POINT
+                this_offset = base_offset + (this_mv.as_mv.row * (in_what_stride)) + this_mv.as_mv.col;
+                thissad = vfp->sdf( what, what_stride, this_offset, in_what_stride, bestsad);
+                CHECK_BETTER
+            }
+        }
+
+        if (best_site == -1)
+            break;
+        else
+        {
+            br += next_chkpts[k][best_site].row;
+            bc += next_chkpts[k][best_site].col;
+            k += 5 + best_site;
+            if (k >= 12) k -= 12;
+            else if (k >= 6) k -= 6;
+        }
+    }
+
+    // check 4 1-away neighbors
+cal_neighbors:
+    for (j = 0; j < dia_range; j++)
+    {
+        best_site = -1;
+        CHECK_BOUNDS(1)
+
+        if(all_in)
+        {
+            for (i = 0; i < 4; i++)
+            {
+                this_mv.as_mv.row = br + neighbors[i].row;
+                this_mv.as_mv.col = bc + neighbors[i].col;
+                this_offset = base_offset + (this_mv.as_mv.row * (in_what_stride)) + this_mv.as_mv.col;
+                thissad = vfp->sdf( what, what_stride, this_offset, in_what_stride, bestsad);
+                CHECK_BETTER
+            }
+        }else
+        {
+            for (i = 0; i < 4; i++)
+            {
+                this_mv.as_mv.row = br + neighbors[i].row;
+                this_mv.as_mv.col = bc + neighbors[i].col;
+                CHECK_POINT
+                this_offset = base_offset + (this_mv.as_mv.row * (in_what_stride)) + this_mv.as_mv.col;
+                thissad = vfp->sdf( what, what_stride, this_offset, in_what_stride, bestsad);
+                CHECK_BETTER
+            }
+        }
+
+        if (best_site == -1)
+            break;
+        else
+        {
+            br += neighbors[best_site].row;
+            bc += neighbors[best_site].col;
+        }
+    }
+
+    best_mv->as_mv.row = br;
+    best_mv->as_mv.col = bc;
+
+    return bestsad;
+}
+#undef CHECK_BOUNDS
+#undef CHECK_POINT
+#undef CHECK_BETTER
+
+int vp8_diamond_search_sad_c
+(
+    MACROBLOCK *x,
+    BLOCK *b,
+    BLOCKD *d,
+    int_mv *ref_mv,
+    int_mv *best_mv,
+    int search_param,
+    int sad_per_bit,
+    int *num00,
+    vp8_variance_fn_ptr_t *fn_ptr,
+    int *mvcost[2],
+    int_mv *center_mv
+)
+{
+    int i, j, step;
+
+    unsigned char *what = (*(b->base_src) + b->src);
+    int what_stride = b->src_stride;
+    unsigned char *in_what;
+    int pre_stride = x->e_mbd.pre.y_stride;
+    unsigned char *base_pre = x->e_mbd.pre.y_buffer;
+    int in_what_stride = pre_stride;
+    unsigned char *best_address;
+
+    int tot_steps;
+    int_mv this_mv;
+
+    int bestsad = INT_MAX;
+    int best_site = 0;
+    int last_site = 0;
+
+    int ref_row;
+    int ref_col;
+    int this_row_offset;
+    int this_col_offset;
+    search_site *ss;
+
+    unsigned char *check_here;
+    int thissad;
+
+    int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]};
+    int_mv fcenter_mv;
+    fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
+    fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
+
+    vp8_clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
+    ref_row = ref_mv->as_mv.row;
+    ref_col = ref_mv->as_mv.col;
+    *num00 = 0;
+    best_mv->as_mv.row = ref_row;
+    best_mv->as_mv.col = ref_col;
+
+    // Work out the start point for the search
+    in_what = (unsigned char *)(base_pre + d->offset + (ref_row * pre_stride) + ref_col);
+    best_address = in_what;
+
+    // Check the starting position
+    bestsad = fn_ptr->sdf(what, what_stride, in_what,
+                          in_what_stride, 0x7fffffff)
+              + mvsad_err_cost(best_mv, &fcenter_mv, mvsadcost, sad_per_bit);
+
+    // search_param determines the length of the initial step and hence the number of iterations
+    // 0 = initial step (MAX_FIRST_STEP) pel : 1 = (MAX_FIRST_STEP/2) pel, 2 = (MAX_FIRST_STEP/4) pel... etc.
+    ss = &x->ss[search_param * x->searches_per_step];
+    tot_steps = (x->ss_count / x->searches_per_step) - search_param;
+
+    i = 1;
+
+    for (step = 0; step < tot_steps ; step++)
+    {
+        for (j = 0 ; j < x->searches_per_step ; j++)
+        {
+            // Trap illegal vectors
+            this_row_offset = best_mv->as_mv.row + ss[i].mv.row;
+            this_col_offset = best_mv->as_mv.col + ss[i].mv.col;
+
+            if ((this_col_offset > x->mv_col_min) && (this_col_offset < x->mv_col_max) &&
+            (this_row_offset > x->mv_row_min) && (this_row_offset < x->mv_row_max))
+
+            {
+                check_here = ss[i].offset + best_address;
+                thissad = fn_ptr->sdf(what, what_stride, check_here , in_what_stride, bestsad);
+
+                if (thissad < bestsad)
+                {
+                    this_mv.as_mv.row = this_row_offset;
+                    this_mv.as_mv.col = this_col_offset;
+                    thissad += mvsad_err_cost(&this_mv, &fcenter_mv,
+                                                mvsadcost, sad_per_bit);
+
+                    if (thissad < bestsad)
+                    {
+                        bestsad = thissad;
+                        best_site = i;
+                    }
+                }
+            }
+
+            i++;
+        }
+
+        if (best_site != last_site)
+        {
+            best_mv->as_mv.row += ss[best_site].mv.row;
+            best_mv->as_mv.col += ss[best_site].mv.col;
+            best_address += ss[best_site].offset;
+            last_site = best_site;
+        }
+        else if (best_address == in_what)
+            (*num00)++;
+    }
+
+    this_mv.as_mv.row = best_mv->as_mv.row << 3;
+    this_mv.as_mv.col = best_mv->as_mv.col << 3;
+
+    if (bestsad == INT_MAX)
+        return INT_MAX;
+
+    return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad))
+        + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit);
+}
+
+int vp8_diamond_search_sadx4
+(
+    MACROBLOCK *x,
+    BLOCK *b,
+    BLOCKD *d,
+    int_mv *ref_mv,
+    int_mv *best_mv,
+    int search_param,
+    int sad_per_bit,
+    int *num00,
+    vp8_variance_fn_ptr_t *fn_ptr,
+    int *mvcost[2],
+    int_mv *center_mv
+)
+{
+    int i, j, step;
+
+    unsigned char *what = (*(b->base_src) + b->src);
+    int what_stride = b->src_stride;
+    unsigned char *in_what;
+    int pre_stride = x->e_mbd.pre.y_stride;
+    unsigned char *base_pre = x->e_mbd.pre.y_buffer;
+    int in_what_stride = pre_stride;
+    unsigned char *best_address;
+
+    int tot_steps;
+    int_mv this_mv;
+
+    unsigned int bestsad = UINT_MAX;
+    int best_site = 0;
+    int last_site = 0;
+
+    int ref_row;
+    int ref_col;
+    int this_row_offset;
+    int this_col_offset;
+    search_site *ss;
+
+    unsigned char *check_here;
+    unsigned int thissad;
+
+    int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]};
+    int_mv fcenter_mv;
+    fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
+    fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
+
+    vp8_clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
+    ref_row = ref_mv->as_mv.row;
+    ref_col = ref_mv->as_mv.col;
+    *num00 = 0;
+    best_mv->as_mv.row = ref_row;
+    best_mv->as_mv.col = ref_col;
+
+    // Work out the start point for the search
+    in_what = (unsigned char *)(base_pre + d->offset + (ref_row * pre_stride) + ref_col);
+    best_address = in_what;
+
+    // Check the starting position
+    bestsad = fn_ptr->sdf(what, what_stride,
+                          in_what, in_what_stride, 0x7fffffff)
+              + mvsad_err_cost(best_mv, &fcenter_mv, mvsadcost, sad_per_bit);
+
+    // search_param determines the length of the initial step and hence the number of iterations
+    // 0 = initial step (MAX_FIRST_STEP) pel : 1 = (MAX_FIRST_STEP/2) pel, 2 = (MAX_FIRST_STEP/4) pel... etc.
+    ss = &x->ss[search_param * x->searches_per_step];
+    tot_steps = (x->ss_count / x->searches_per_step) - search_param;
+
+    i = 1;
+
+    for (step = 0; step < tot_steps ; step++)
+    {
+        int all_in = 1, t;
+
+        // To know if all neighbor points are within the bounds, 4 bounds checking are enough instead of
+        // checking 4 bounds for each points.
+        all_in &= ((best_mv->as_mv.row + ss[i].mv.row)> x->mv_row_min);
+        all_in &= ((best_mv->as_mv.row + ss[i+1].mv.row) < x->mv_row_max);
+        all_in &= ((best_mv->as_mv.col + ss[i+2].mv.col) > x->mv_col_min);
+        all_in &= ((best_mv->as_mv.col + ss[i+3].mv.col) < x->mv_col_max);
+
+        if (all_in)
+        {
+            unsigned int sad_array[4];
+
+            for (j = 0 ; j < x->searches_per_step ; j += 4)
+            {
+                unsigned char *block_offset[4];
+
+                for (t = 0; t < 4; t++)
+                    block_offset[t] = ss[i+t].offset + best_address;
+
+                fn_ptr->sdx4df(what, what_stride, block_offset, in_what_stride, sad_array);
+
+                for (t = 0; t < 4; t++, i++)
+                {
+                    if (sad_array[t] < bestsad)
+                    {
+                        this_mv.as_mv.row = best_mv->as_mv.row + ss[i].mv.row;
+                        this_mv.as_mv.col = best_mv->as_mv.col + ss[i].mv.col;
+                        sad_array[t] += mvsad_err_cost(&this_mv, &fcenter_mv,
+                                                       mvsadcost, sad_per_bit);
+
+                        if (sad_array[t] < bestsad)
+                        {
+                            bestsad = sad_array[t];
+                            best_site = i;
+                        }
+                    }
+                }
+            }
+        }
+        else
+        {
+            for (j = 0 ; j < x->searches_per_step ; j++)
+            {
+                // Trap illegal vectors
+                this_row_offset = best_mv->as_mv.row + ss[i].mv.row;
+                this_col_offset = best_mv->as_mv.col + ss[i].mv.col;
+
+                if ((this_col_offset > x->mv_col_min) && (this_col_offset < x->mv_col_max) &&
+                (this_row_offset > x->mv_row_min) && (this_row_offset < x->mv_row_max))
+                {
+                    check_here = ss[i].offset + best_address;
+                    thissad = fn_ptr->sdf(what, what_stride, check_here , in_what_stride, bestsad);
+
+                    if (thissad < bestsad)
+                    {
+                        this_mv.as_mv.row = this_row_offset;
+                        this_mv.as_mv.col = this_col_offset;
+                        thissad += mvsad_err_cost(&this_mv, &fcenter_mv,
+                                                   mvsadcost, sad_per_bit);
+
+                        if (thissad < bestsad)
+                        {
+                            bestsad = thissad;
+                            best_site = i;
+                        }
+                    }
+                }
+                i++;
+            }
+        }
+
+        if (best_site != last_site)
+        {
+            best_mv->as_mv.row += ss[best_site].mv.row;
+            best_mv->as_mv.col += ss[best_site].mv.col;
+            best_address += ss[best_site].offset;
+            last_site = best_site;
+        }
+        else if (best_address == in_what)
+            (*num00)++;
+    }
+
+    this_mv.as_mv.row = best_mv->as_mv.row << 3;
+    this_mv.as_mv.col = best_mv->as_mv.col << 3;
+
+    if (bestsad == INT_MAX)
+        return INT_MAX;
+
+    return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad))
+        + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit);
+}
+
+int vp8_full_search_sad_c(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
+                        int sad_per_bit, int distance,
+                        vp8_variance_fn_ptr_t *fn_ptr, int *mvcost[2],
+                        int_mv *center_mv)
+{
+    unsigned char *what = (*(b->base_src) + b->src);
+    int what_stride = b->src_stride;
+    unsigned char *in_what;
+    int pre_stride = x->e_mbd.pre.y_stride;
+    unsigned char *base_pre = x->e_mbd.pre.y_buffer;
+    int in_what_stride = pre_stride;
+    int mv_stride = pre_stride;
+    unsigned char *bestaddress;
+    int_mv *best_mv = &d->bmi.mv;
+    int_mv this_mv;
+    int bestsad = INT_MAX;
+    int r, c;
+
+    unsigned char *check_here;
+    int thissad;
+
+    int ref_row = ref_mv->as_mv.row;
+    int ref_col = ref_mv->as_mv.col;
+
+    int row_min = ref_row - distance;
+    int row_max = ref_row + distance;
+    int col_min = ref_col - distance;
+    int col_max = ref_col + distance;
+
+    int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]};
+    int_mv fcenter_mv;
+    fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
+    fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
+
+    // Work out the mid point for the search
+    in_what = base_pre + d->offset;
+    bestaddress = in_what + (ref_row * pre_stride) + ref_col;
+
+    best_mv->as_mv.row = ref_row;
+    best_mv->as_mv.col = ref_col;
+
+    // Baseline value at the centre
+    bestsad = fn_ptr->sdf(what, what_stride, bestaddress,
+                          in_what_stride, 0x7fffffff)
+              + mvsad_err_cost(best_mv, &fcenter_mv, mvsadcost, sad_per_bit);
+
+    // Apply further limits to prevent us looking using vectors that stretch beyiond the UMV border
+    if (col_min < x->mv_col_min)
+        col_min = x->mv_col_min;
+
+    if (col_max > x->mv_col_max)
+        col_max = x->mv_col_max;
+
+    if (row_min < x->mv_row_min)
+        row_min = x->mv_row_min;
+
+    if (row_max > x->mv_row_max)
+        row_max = x->mv_row_max;
+
+    for (r = row_min; r < row_max ; r++)
+    {
+        this_mv.as_mv.row = r;
+        check_here = r * mv_stride + in_what + col_min;
+
+        for (c = col_min; c < col_max; c++)
+        {
+            thissad = fn_ptr->sdf(what, what_stride, check_here , in_what_stride, bestsad);
+
+            this_mv.as_mv.col = c;
+            thissad  += mvsad_err_cost(&this_mv, &fcenter_mv,
+                        mvsadcost, sad_per_bit);
+
+            if (thissad < bestsad)
+            {
+                bestsad = thissad;
+                best_mv->as_mv.row = r;
+                best_mv->as_mv.col = c;
+                bestaddress = check_here;
+            }
+
+            check_here++;
+        }
+    }
+
+    this_mv.as_mv.row = best_mv->as_mv.row << 3;
+    this_mv.as_mv.col = best_mv->as_mv.col << 3;
+
+    if (bestsad < INT_MAX)
+        return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride, (unsigned int *)(&thissad))
+        + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit);
+    else
+        return INT_MAX;
+}
+
+int vp8_full_search_sadx3(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
+                          int sad_per_bit, int distance,
+                          vp8_variance_fn_ptr_t *fn_ptr, int *mvcost[2],
+                          int_mv *center_mv)
+{
+    unsigned char *what = (*(b->base_src) + b->src);
+    int what_stride = b->src_stride;
+    unsigned char *in_what;
+    int pre_stride = x->e_mbd.pre.y_stride;
+    unsigned char *base_pre = x->e_mbd.pre.y_buffer;
+    int in_what_stride = pre_stride;
+    int mv_stride = pre_stride;
+    unsigned char *bestaddress;
+    int_mv *best_mv = &d->bmi.mv;
+    int_mv this_mv;
+    unsigned int bestsad = UINT_MAX;
+    int r, c;
+
+    unsigned char *check_here;
+    unsigned int thissad;
+
+    int ref_row = ref_mv->as_mv.row;
+    int ref_col = ref_mv->as_mv.col;
+
+    int row_min = ref_row - distance;
+    int row_max = ref_row + distance;
+    int col_min = ref_col - distance;
+    int col_max = ref_col + distance;
+
+    unsigned int sad_array[3];
+
+    int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]};
+    int_mv fcenter_mv;
+    fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
+    fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
+
+    // Work out the mid point for the search
+    in_what = base_pre + d->offset;
+    bestaddress = in_what + (ref_row * pre_stride) + ref_col;
+
+    best_mv->as_mv.row = ref_row;
+    best_mv->as_mv.col = ref_col;
+
+    // Baseline value at the centre
+    bestsad = fn_ptr->sdf(what, what_stride,
+                          bestaddress, in_what_stride, 0x7fffffff)
+              + mvsad_err_cost(best_mv, &fcenter_mv, mvsadcost, sad_per_bit);
+
+    // Apply further limits to prevent us looking using vectors that stretch beyiond the UMV border
+    if (col_min < x->mv_col_min)
+        col_min = x->mv_col_min;
+
+    if (col_max > x->mv_col_max)
+        col_max = x->mv_col_max;
+
+    if (row_min < x->mv_row_min)
+        row_min = x->mv_row_min;
+
+    if (row_max > x->mv_row_max)
+        row_max = x->mv_row_max;
+
+    for (r = row_min; r < row_max ; r++)
+    {
+        this_mv.as_mv.row = r;
+        check_here = r * mv_stride + in_what + col_min;
+        c = col_min;
+
+        while ((c + 2) < col_max)
+        {
+            int i;
+
+            fn_ptr->sdx3f(what, what_stride, check_here , in_what_stride, sad_array);
+
+            for (i = 0; i < 3; i++)
+            {
+                thissad = sad_array[i];
+
+                if (thissad < bestsad)
+                {
+                    this_mv.as_mv.col = c;
+                    thissad  += mvsad_err_cost(&this_mv, &fcenter_mv,
+                                                mvsadcost, sad_per_bit);
+
+                    if (thissad < bestsad)
+                    {
+                        bestsad = thissad;
+                        best_mv->as_mv.row = r;
+                        best_mv->as_mv.col = c;
+                        bestaddress = check_here;
+                    }
+                }
+
+                check_here++;
+                c++;
+            }
+        }
+
+        while (c < col_max)
+        {
+            thissad = fn_ptr->sdf(what, what_stride, check_here , in_what_stride, bestsad);
+
+            if (thissad < bestsad)
+            {
+                this_mv.as_mv.col = c;
+                thissad  += mvsad_err_cost(&this_mv, &fcenter_mv,
+                                            mvsadcost, sad_per_bit);
+
+                if (thissad < bestsad)
+                {
+                    bestsad = thissad;
+                    best_mv->as_mv.row = r;
+                    best_mv->as_mv.col = c;
+                    bestaddress = check_here;
+                }
+            }
+
+            check_here ++;
+            c ++;
+        }
+
+    }
+
+    this_mv.as_mv.row = best_mv->as_mv.row << 3;
+    this_mv.as_mv.col = best_mv->as_mv.col << 3;
+
+    if (bestsad < INT_MAX)
+        return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride, (unsigned int *)(&thissad))
+        + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit);
+    else
+        return INT_MAX;
+}
+
+int vp8_full_search_sadx8(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
+                          int sad_per_bit, int distance,
+                          vp8_variance_fn_ptr_t *fn_ptr, int *mvcost[2],
+                          int_mv *center_mv)
+{
+    unsigned char *what = (*(b->base_src) + b->src);
+    int what_stride = b->src_stride;
+    int pre_stride = x->e_mbd.pre.y_stride;
+    unsigned char *base_pre = x->e_mbd.pre.y_buffer;
+    unsigned char *in_what;
+    int in_what_stride = pre_stride;
+    int mv_stride = pre_stride;
+    unsigned char *bestaddress;
+    int_mv *best_mv = &d->bmi.mv;
+    int_mv this_mv;
+    unsigned int bestsad = UINT_MAX;
+    int r, c;
+
+    unsigned char *check_here;
+    unsigned int thissad;
+
+    int ref_row = ref_mv->as_mv.row;
+    int ref_col = ref_mv->as_mv.col;
+
+    int row_min = ref_row - distance;
+    int row_max = ref_row + distance;
+    int col_min = ref_col - distance;
+    int col_max = ref_col + distance;
+
+    DECLARE_ALIGNED_ARRAY(16, unsigned short, sad_array8, 8);
+    unsigned int sad_array[3];
+
+    int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]};
+    int_mv fcenter_mv;
+    fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
+    fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
+
+    // Work out the mid point for the search
+    in_what = base_pre + d->offset;
+    bestaddress = in_what + (ref_row * pre_stride) + ref_col;
+
+    best_mv->as_mv.row = ref_row;
+    best_mv->as_mv.col = ref_col;
+
+    // Baseline value at the centre
+    bestsad = fn_ptr->sdf(what, what_stride,
+                          bestaddress, in_what_stride, 0x7fffffff)
+              + mvsad_err_cost(best_mv, &fcenter_mv, mvsadcost, sad_per_bit);
+
+    // Apply further limits to prevent us looking using vectors that stretch beyiond the UMV border
+    if (col_min < x->mv_col_min)
+        col_min = x->mv_col_min;
+
+    if (col_max > x->mv_col_max)
+        col_max = x->mv_col_max;
+
+    if (row_min < x->mv_row_min)
+        row_min = x->mv_row_min;
+
+    if (row_max > x->mv_row_max)
+        row_max = x->mv_row_max;
+
+    for (r = row_min; r < row_max ; r++)
+    {
+        this_mv.as_mv.row = r;
+        check_here = r * mv_stride + in_what + col_min;
+        c = col_min;
+
+        while ((c + 7) < col_max)
+        {
+            int i;
+
+            fn_ptr->sdx8f(what, what_stride, check_here , in_what_stride, sad_array8);
+
+            for (i = 0; i < 8; i++)
+            {
+                thissad = (unsigned int)sad_array8[i];
+
+                if (thissad < bestsad)
+                {
+                    this_mv.as_mv.col = c;
+                    thissad  += mvsad_err_cost(&this_mv, &fcenter_mv,
+                                                mvsadcost, sad_per_bit);
+
+                    if (thissad < bestsad)
+                    {
+                        bestsad = thissad;
+                        best_mv->as_mv.row = r;
+                        best_mv->as_mv.col = c;
+                        bestaddress = check_here;
+                    }
+                }
+
+                check_here++;
+                c++;
+            }
+        }
+
+        while ((c + 2) < col_max)
+        {
+            int i;
+
+            fn_ptr->sdx3f(what, what_stride, check_here , in_what_stride, sad_array);
+
+            for (i = 0; i < 3; i++)
+            {
+                thissad = sad_array[i];
+
+                if (thissad < bestsad)
+                {
+                    this_mv.as_mv.col = c;
+                    thissad  += mvsad_err_cost(&this_mv, &fcenter_mv,
+                        mvsadcost, sad_per_bit);
+
+                    if (thissad < bestsad)
+                    {
+                        bestsad = thissad;
+                        best_mv->as_mv.row = r;
+                        best_mv->as_mv.col = c;
+                        bestaddress = check_here;
+                    }
+                }
+
+                check_here++;
+                c++;
+            }
+        }
+
+        while (c < col_max)
+        {
+            thissad = fn_ptr->sdf(what, what_stride, check_here , in_what_stride, bestsad);
+
+            if (thissad < bestsad)
+            {
+                this_mv.as_mv.col = c;
+                thissad  += mvsad_err_cost(&this_mv, &fcenter_mv,
+                    mvsadcost, sad_per_bit);
+
+                if (thissad < bestsad)
+                {
+                    bestsad = thissad;
+                    best_mv->as_mv.row = r;
+                    best_mv->as_mv.col = c;
+                    bestaddress = check_here;
+                }
+            }
+
+            check_here ++;
+            c ++;
+        }
+    }
+
+    this_mv.as_mv.row = best_mv->as_mv.row << 3;
+    this_mv.as_mv.col = best_mv->as_mv.col << 3;
+
+    if (bestsad < INT_MAX)
+        return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride, (unsigned int *)(&thissad))
+        + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit);
+    else
+        return INT_MAX;
+}
+
+int vp8_refining_search_sad_c(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
+                            int error_per_bit, int search_range,
+                            vp8_variance_fn_ptr_t *fn_ptr, int *mvcost[2],
+                            int_mv *center_mv)
+{
+    MV neighbors[4] = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};
+    int i, j;
+    short this_row_offset, this_col_offset;
+
+    int what_stride = b->src_stride;
+    int pre_stride = x->e_mbd.pre.y_stride;
+    unsigned char *base_pre = x->e_mbd.pre.y_buffer;
+    int in_what_stride = pre_stride;
+    unsigned char *what = (*(b->base_src) + b->src);
+    unsigned char *best_address = (unsigned char *)(base_pre + d->offset +
+        (ref_mv->as_mv.row * pre_stride) + ref_mv->as_mv.col);
+    unsigned char *check_here;
+    unsigned int thissad;
+    int_mv this_mv;
+    unsigned int bestsad = INT_MAX;
+
+    int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]};
+    int_mv fcenter_mv;
+
+    fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
+    fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
+
+    bestsad = fn_ptr->sdf(what, what_stride, best_address, in_what_stride, 0x7fffffff) + mvsad_err_cost(ref_mv, &fcenter_mv, mvsadcost, error_per_bit);
+
+    for (i=0; i<search_range; i++)
+    {
+        int best_site = -1;
+
+        for (j = 0 ; j < 4 ; j++)
+        {
+            this_row_offset = ref_mv->as_mv.row + neighbors[j].row;
+            this_col_offset = ref_mv->as_mv.col + neighbors[j].col;
+
+            if ((this_col_offset > x->mv_col_min) && (this_col_offset < x->mv_col_max) &&
+            (this_row_offset > x->mv_row_min) && (this_row_offset < x->mv_row_max))
+            {
+                check_here = (neighbors[j].row)*in_what_stride + neighbors[j].col + best_address;
+                thissad = fn_ptr->sdf(what, what_stride, check_here , in_what_stride, bestsad);
+
+                if (thissad < bestsad)
+                {
+                    this_mv.as_mv.row = this_row_offset;
+                    this_mv.as_mv.col = this_col_offset;
+                    thissad += mvsad_err_cost(&this_mv, &fcenter_mv, mvsadcost, error_per_bit);
+
+                    if (thissad < bestsad)
+                    {
+                        bestsad = thissad;
+                        best_site = j;
+                    }
+                }
+            }
+        }
+
+        if (best_site == -1)
+            break;
+        else
+        {
+            ref_mv->as_mv.row += neighbors[best_site].row;
+            ref_mv->as_mv.col += neighbors[best_site].col;
+            best_address += (neighbors[best_site].row)*in_what_stride + neighbors[best_site].col;
+        }
+    }
+
+    this_mv.as_mv.row = ref_mv->as_mv.row << 3;
+    this_mv.as_mv.col = ref_mv->as_mv.col << 3;
+
+    if (bestsad < INT_MAX)
+        return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad))
+        + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit);
+    else
+        return INT_MAX;
+}
+
+int vp8_refining_search_sadx4(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
+                              int_mv *ref_mv, int error_per_bit,
+                              int search_range, vp8_variance_fn_ptr_t *fn_ptr,
+                              int *mvcost[2], int_mv *center_mv)
+{
+    MV neighbors[4] = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};
+    int i, j;
+    short this_row_offset, this_col_offset;
+
+    int what_stride = b->src_stride;
+    int pre_stride = x->e_mbd.pre.y_stride;
+    unsigned char *base_pre = x->e_mbd.pre.y_buffer;
+    int in_what_stride = pre_stride;
+    unsigned char *what = (*(b->base_src) + b->src);
+    unsigned char *best_address = (unsigned char *)(base_pre + d->offset +
+        (ref_mv->as_mv.row * pre_stride) + ref_mv->as_mv.col);
+    unsigned char *check_here;
+    unsigned int thissad;
+    int_mv this_mv;
+    unsigned int bestsad = INT_MAX;
+
+    int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]};
+    int_mv fcenter_mv;
+
+    fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
+    fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
+
+    bestsad = fn_ptr->sdf(what, what_stride, best_address, in_what_stride, 0x7fffffff) + mvsad_err_cost(ref_mv, &fcenter_mv, mvsadcost, error_per_bit);
+
+    for (i=0; i<search_range; i++)
+    {
+        int best_site = -1;
+        int all_in = 1;
+
+        all_in &= ((ref_mv->as_mv.row - 1) > x->mv_row_min);
+        all_in &= ((ref_mv->as_mv.row + 1) < x->mv_row_max);
+        all_in &= ((ref_mv->as_mv.col - 1) > x->mv_col_min);
+        all_in &= ((ref_mv->as_mv.col + 1) < x->mv_col_max);
+
+        if(all_in)
+        {
+            unsigned int sad_array[4];
+            unsigned char *block_offset[4];
+            block_offset[0] = best_address - in_what_stride;
+            block_offset[1] = best_address - 1;
+            block_offset[2] = best_address + 1;
+            block_offset[3] = best_address + in_what_stride;
+
+            fn_ptr->sdx4df(what, what_stride, block_offset, in_what_stride, sad_array);
+
+            for (j = 0; j < 4; j++)
+            {
+                if (sad_array[j] < bestsad)
+                {
+                    this_mv.as_mv.row = ref_mv->as_mv.row + neighbors[j].row;
+                    this_mv.as_mv.col = ref_mv->as_mv.col + neighbors[j].col;
+                    sad_array[j] += mvsad_err_cost(&this_mv, &fcenter_mv, mvsadcost, error_per_bit);
+
+                    if (sad_array[j] < bestsad)
+                    {
+                        bestsad = sad_array[j];
+                        best_site = j;
+                    }
+                }
+            }
+        }
+        else
+        {
+            for (j = 0 ; j < 4 ; j++)
+            {
+                this_row_offset = ref_mv->as_mv.row + neighbors[j].row;
+                this_col_offset = ref_mv->as_mv.col + neighbors[j].col;
+
+                if ((this_col_offset > x->mv_col_min) && (this_col_offset < x->mv_col_max) &&
+                (this_row_offset > x->mv_row_min) && (this_row_offset < x->mv_row_max))
+                {
+                    check_here = (neighbors[j].row)*in_what_stride + neighbors[j].col + best_address;
+                    thissad = fn_ptr->sdf(what, what_stride, check_here , in_what_stride, bestsad);
+
+                    if (thissad < bestsad)
+                    {
+                        this_mv.as_mv.row = this_row_offset;
+                        this_mv.as_mv.col = this_col_offset;
+                        thissad += mvsad_err_cost(&this_mv, &fcenter_mv, mvsadcost, error_per_bit);
+
+                        if (thissad < bestsad)
+                        {
+                            bestsad = thissad;
+                            best_site = j;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (best_site == -1)
+            break;
+        else
+        {
+            ref_mv->as_mv.row += neighbors[best_site].row;
+            ref_mv->as_mv.col += neighbors[best_site].col;
+            best_address += (neighbors[best_site].row)*in_what_stride + neighbors[best_site].col;
+        }
+    }
+
+    this_mv.as_mv.row = ref_mv->as_mv.row << 3;
+    this_mv.as_mv.col = ref_mv->as_mv.col << 3;
+
+    if (bestsad < INT_MAX)
+        return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad))
+        + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit);
+    else
+        return INT_MAX;
+}
+
+#ifdef ENTROPY_STATS
+void print_mode_context(void)
+{
+    FILE *f = fopen("modecont.c", "w");
+    int i, j;
+
+    fprintf(f, "#include \"entropy.h\"\n");
+    fprintf(f, "const int vp8_mode_contexts[6][4] =\n");
+    fprintf(f, "{\n");
+
+    for (j = 0; j < 6; j++)
+    {
+        fprintf(f, "  { // %d \n", j);
+        fprintf(f, "    ");
+
+        for (i = 0; i < 4; i++)
+        {
+            int overal_prob;
+            int this_prob;
+            int count; // = mv_ref_ct[j][i][0]+mv_ref_ct[j][i][1];
+
+            // Overall probs
+            count = mv_mode_cts[i][0] + mv_mode_cts[i][1];
+
+            if (count)
+                overal_prob = 256 * mv_mode_cts[i][0] / count;
+            else
+                overal_prob = 128;
+
+            if (overal_prob == 0)
+                overal_prob = 1;
+
+            // context probs
+            count = mv_ref_ct[j][i][0] + mv_ref_ct[j][i][1];
+
+            if (count)
+                this_prob = 256 * mv_ref_ct[j][i][0] / count;
+            else
+                this_prob = 128;
+
+            if (this_prob == 0)
+                this_prob = 1;
+
+            fprintf(f, "%5d, ", this_prob);
+            //fprintf(f,"%5d, %5d, %8d,", this_prob, overal_prob, (this_prob << 10)/overal_prob);
+            //fprintf(f,"%8d, ", (this_prob << 10)/overal_prob);
+        }
+
+        fprintf(f, "  },\n");
+    }
+
+    fprintf(f, "};\n");
+    fclose(f);
+}
+
+/* MV ref count ENTROPY_STATS stats code */
+#ifdef ENTROPY_STATS
+void init_mv_ref_counts()
+{
+    vpx_memset(mv_ref_ct, 0, sizeof(mv_ref_ct));
+    vpx_memset(mv_mode_cts, 0, sizeof(mv_mode_cts));
+}
+
+void accum_mv_refs(MB_PREDICTION_MODE m, const int ct[4])
+{
+    if (m == ZEROMV)
+    {
+        ++mv_ref_ct [ct[0]] [0] [0];
+        ++mv_mode_cts[0][0];
+    }
+    else
+    {
+        ++mv_ref_ct [ct[0]] [0] [1];
+        ++mv_mode_cts[0][1];
+
+        if (m == NEARESTMV)
+        {
+            ++mv_ref_ct [ct[1]] [1] [0];
+            ++mv_mode_cts[1][0];
+        }
+        else
+        {
+            ++mv_ref_ct [ct[1]] [1] [1];
+            ++mv_mode_cts[1][1];
+
+            if (m == NEARMV)
+            {
+                ++mv_ref_ct [ct[2]] [2] [0];
+                ++mv_mode_cts[2][0];
+            }
+            else
+            {
+                ++mv_ref_ct [ct[2]] [2] [1];
+                ++mv_mode_cts[2][1];
+
+                if (m == NEWMV)
+                {
+                    ++mv_ref_ct [ct[3]] [3] [0];
+                    ++mv_mode_cts[3][0];
+                }
+                else
+                {
+                    ++mv_ref_ct [ct[3]] [3] [1];
+                    ++mv_mode_cts[3][1];
+                }
+            }
+        }
+    }
+}
+
+#endif/* END MV ref count ENTROPY_STATS stats code */
+
+#endif
diff --git a/vp8/encoder/mcomp.h b/vp8/encoder/mcomp.h
new file mode 100644 (file)
index 0000000..cdb0cb6
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_MCOMP_H
+#define __INC_MCOMP_H
+
+#include "block.h"
+#include "vp8/common/variance.h"
+
+#ifdef ENTROPY_STATS
+extern void init_mv_ref_counts();
+extern void accum_mv_refs(MB_PREDICTION_MODE, const int near_mv_ref_cts[4]);
+#endif
+
+
+#define MAX_MVSEARCH_STEPS 8                                    // The maximum number of steps in a step search given the largest allowed initial step
+#define MAX_FULL_PEL_VAL ((1 << (MAX_MVSEARCH_STEPS)) - 1)      // Max full pel mv specified in 1 pel units
+#define MAX_FIRST_STEP (1 << (MAX_MVSEARCH_STEPS-1))            // Maximum size of the first step in full pel units
+
+extern void print_mode_context(void);
+extern int vp8_mv_bit_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int Weight);
+extern void vp8_init_dsmotion_compensation(MACROBLOCK *x, int stride);
+extern void vp8_init3smotion_compensation(MACROBLOCK *x,  int stride);
+
+
+extern int vp8_hex_search
+(
+    MACROBLOCK *x,
+    BLOCK *b,
+    BLOCKD *d,
+    int_mv *ref_mv,
+    int_mv *best_mv,
+    int search_param,
+    int error_per_bit,
+    const vp8_variance_fn_ptr_t *vf,
+    int *mvsadcost[2],
+    int *mvcost[2],
+    int_mv *center_mv
+);
+
+typedef int (fractional_mv_step_fp)
+    (MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *bestmv, int_mv *ref_mv,
+     int error_per_bit, const vp8_variance_fn_ptr_t *vfp, int *mvcost[2],
+     int *distortion, unsigned int *sse);
+
+extern fractional_mv_step_fp vp8_find_best_sub_pixel_step_iteratively;
+extern fractional_mv_step_fp vp8_find_best_sub_pixel_step;
+extern fractional_mv_step_fp vp8_find_best_half_pixel_step;
+extern fractional_mv_step_fp vp8_skip_fractional_mv_step;
+
+typedef int (*vp8_full_search_fn_t)
+    (
+     MACROBLOCK *x,
+     BLOCK *b,
+     BLOCKD *d,
+     int_mv *ref_mv,
+     int sad_per_bit,
+     int distance,
+     vp8_variance_fn_ptr_t *fn_ptr,
+     int *mvcost[2],
+     int_mv *center_mv
+    );
+
+typedef int (*vp8_refining_search_fn_t)
+    (
+     MACROBLOCK *x,
+     BLOCK *b,
+     BLOCKD *d,
+     int_mv *ref_mv,
+     int sad_per_bit,
+     int distance,
+     vp8_variance_fn_ptr_t *fn_ptr,
+     int *mvcost[2],
+     int_mv *center_mv
+    );
+
+typedef int (*vp8_diamond_search_fn_t)
+    (
+     MACROBLOCK *x,
+     BLOCK *b,
+     BLOCKD *d,
+     int_mv *ref_mv,
+     int_mv *best_mv,
+     int search_param,
+     int sad_per_bit,
+     int *num00,
+     vp8_variance_fn_ptr_t *fn_ptr,
+     int *mvcost[2],
+     int_mv *center_mv
+    );
+
+#endif
diff --git a/vp8/encoder/modecosts.c b/vp8/encoder/modecosts.c
new file mode 100644 (file)
index 0000000..c636c48
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vp8/common/blockd.h"
+#include "onyx_int.h"
+#include "treewriter.h"
+#include "vp8/common/entropymode.h"
+
+
+void vp8_init_mode_costs(VP8_COMP *c)
+{
+    VP8_COMMON *x = &c->common;
+    {
+        const vp8_tree_p T = vp8_bmode_tree;
+
+        int i = 0;
+
+        do
+        {
+            int j = 0;
+
+            do
+            {
+                vp8_cost_tokens((int *)c->mb.bmode_costs[i][j], x->kf_bmode_prob[i][j], T);
+            }
+            while (++j < VP8_BINTRAMODES);
+        }
+        while (++i < VP8_BINTRAMODES);
+
+        vp8_cost_tokens((int *)c->mb.inter_bmode_costs, x->fc.bmode_prob, T);
+    }
+    vp8_cost_tokens((int *)c->mb.inter_bmode_costs, x->fc.sub_mv_ref_prob, vp8_sub_mv_ref_tree);
+
+    vp8_cost_tokens(c->mb.mbmode_cost[1], x->fc.ymode_prob, vp8_ymode_tree);
+    vp8_cost_tokens(c->mb.mbmode_cost[0], x->kf_ymode_prob, vp8_kf_ymode_tree);
+
+    vp8_cost_tokens(c->mb.intra_uv_mode_cost[1], x->fc.uv_mode_prob, vp8_uv_mode_tree);
+    vp8_cost_tokens(c->mb.intra_uv_mode_cost[0], x->kf_uv_mode_prob, vp8_uv_mode_tree);
+}
diff --git a/vp8/encoder/modecosts.h b/vp8/encoder/modecosts.h
new file mode 100644 (file)
index 0000000..99ef119
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_MODECOSTS_H
+#define __INC_MODECOSTS_H
+
+void vp8_init_mode_costs(VP8_COMP *x);
+
+#endif
diff --git a/vp8/encoder/mr_dissim.c b/vp8/encoder/mr_dissim.c
new file mode 100644 (file)
index 0000000..7a62a06
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include <limits.h>
+#include "vpx_config.h"
+#include "onyx_int.h"
+#include "mr_dissim.h"
+#include "vpx_mem/vpx_mem.h"
+#include "rdopt.h"
+
+void vp8_cal_low_res_mb_cols(VP8_COMP *cpi)
+{
+    int low_res_w;
+
+    /* Support arbitrary down-sampling factor */
+    unsigned int iw = cpi->oxcf.Width*cpi->oxcf.mr_down_sampling_factor.den
+                      + cpi->oxcf.mr_down_sampling_factor.num - 1;
+
+    low_res_w = iw/cpi->oxcf.mr_down_sampling_factor.num;
+    cpi->mr_low_res_mb_cols = ((low_res_w + 15) >> 4);
+}
+
+#define GET_MV(x)    \
+if(x->mbmi.ref_frame !=INTRA_FRAME)   \
+{   \
+    mvx[cnt] = x->mbmi.mv.as_mv.row;  \
+    mvy[cnt] = x->mbmi.mv.as_mv.col;  \
+    cnt++;    \
+}
+
+#define GET_MV_SIGN(x)    \
+if(x->mbmi.ref_frame !=INTRA_FRAME)   \
+{   \
+    mvx[cnt] = x->mbmi.mv.as_mv.row;  \
+    mvy[cnt] = x->mbmi.mv.as_mv.col;  \
+    if (cm->ref_frame_sign_bias[x->mbmi.ref_frame]  \
+        != cm->ref_frame_sign_bias[tmp->mbmi.ref_frame])  \
+    {  \
+        mvx[cnt] *= -1;   \
+        mvy[cnt] *= -1;   \
+    }  \
+    cnt++;  \
+}
+
+void vp8_cal_dissimilarity(VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = &cpi->common;
+
+    /* Note: The first row & first column in mip are outside the frame, which
+     * were initialized to all 0.(ref_frame, mode, mv...)
+     * Their ref_frame = 0 means they won't be counted in the following
+     * calculation.
+     */
+    if (cpi->oxcf.mr_total_resolutions >1
+        && cpi->oxcf.mr_encoder_id < (cpi->oxcf.mr_total_resolutions - 1))
+    {
+        /* Store info for show/no-show frames for supporting alt_ref.
+         * If parent frame is alt_ref, child has one too.
+         */
+        if(cm->frame_type != KEY_FRAME)
+        {
+            int mb_row;
+            int mb_col;
+            /* Point to beginning of allocated MODE_INFO arrays. */
+            MODE_INFO *tmp = cm->mip + cm->mode_info_stride;
+            LOWER_RES_INFO* store_mode_info
+                            = (LOWER_RES_INFO*)cpi->oxcf.mr_low_res_mode_info;
+
+            for (mb_row = 0; mb_row < cm->mb_rows; mb_row ++)
+            {
+                tmp++;
+                for (mb_col = 0; mb_col < cm->mb_cols; mb_col ++)
+                {
+                    int dissim = INT_MAX;
+
+                    if(tmp->mbmi.ref_frame !=INTRA_FRAME)
+                    {
+                        int              mvx[8];
+                        int              mvy[8];
+                        int              mmvx;
+                        int              mmvy;
+                        int              cnt=0;
+                        const MODE_INFO *here = tmp;
+                        const MODE_INFO *above = here - cm->mode_info_stride;
+                        const MODE_INFO *left = here - 1;
+                        const MODE_INFO *aboveleft = above - 1;
+                        const MODE_INFO *aboveright = NULL;
+                        const MODE_INFO *right = NULL;
+                        const MODE_INFO *belowleft = NULL;
+                        const MODE_INFO *below = NULL;
+                        const MODE_INFO *belowright = NULL;
+
+                        /* If alternate reference frame is used, we have to
+                         * check sign of MV. */
+                        if(cpi->oxcf.play_alternate)
+                        {
+                            /* Gather mv of neighboring MBs */
+                            GET_MV_SIGN(above)
+                            GET_MV_SIGN(left)
+                            GET_MV_SIGN(aboveleft)
+
+                            if(mb_col < (cm->mb_cols-1))
+                            {
+                                right = here + 1;
+                                aboveright = above + 1;
+                                GET_MV_SIGN(right)
+                                GET_MV_SIGN(aboveright)
+                            }
+
+                            if(mb_row < (cm->mb_rows-1))
+                            {
+                                below = here + cm->mode_info_stride;
+                                belowleft = below - 1;
+                                GET_MV_SIGN(below)
+                                GET_MV_SIGN(belowleft)
+                            }
+
+                            if(mb_col < (cm->mb_cols-1)
+                                && mb_row < (cm->mb_rows-1))
+                            {
+                                belowright = below + 1;
+                                GET_MV_SIGN(belowright)
+                            }
+                        }else
+                        {
+                            /* No alt_ref and gather mv of neighboring MBs */
+                            GET_MV(above)
+                            GET_MV(left)
+                            GET_MV(aboveleft)
+
+                            if(mb_col < (cm->mb_cols-1))
+                            {
+                                right = here + 1;
+                                aboveright = above + 1;
+                                GET_MV(right)
+                                GET_MV(aboveright)
+                            }
+
+                            if(mb_row < (cm->mb_rows-1))
+                            {
+                                below = here + cm->mode_info_stride;
+                                belowleft = below - 1;
+                                GET_MV(below)
+                                GET_MV(belowleft)
+                            }
+
+                            if(mb_col < (cm->mb_cols-1)
+                                && mb_row < (cm->mb_rows-1))
+                            {
+                                belowright = below + 1;
+                                GET_MV(belowright)
+                            }
+                        }
+
+                        if (cnt > 0)
+                        {
+                            int max_mvx = mvx[0];
+                            int min_mvx = mvx[0];
+                            int max_mvy = mvy[0];
+                            int min_mvy = mvy[0];
+                            int i;
+
+                            if (cnt > 1)
+                            {
+                                for (i=1; i< cnt; i++)
+                                {
+                                    if (mvx[i] > max_mvx) max_mvx = mvx[i];
+                                    else if (mvx[i] < min_mvx) min_mvx = mvx[i];
+                                    if (mvy[i] > max_mvy) max_mvy = mvy[i];
+                                    else if (mvy[i] < min_mvy) min_mvy = mvy[i];
+                                }
+                            }
+
+                            mmvx = MAX(abs(min_mvx - here->mbmi.mv.as_mv.row),
+                                       abs(max_mvx - here->mbmi.mv.as_mv.row));
+                            mmvy = MAX(abs(min_mvy - here->mbmi.mv.as_mv.col),
+                                       abs(max_mvy - here->mbmi.mv.as_mv.col));
+                            dissim = MAX(mmvx, mmvy);
+                        }
+                    }
+
+                    /* Store mode info for next resolution encoding */
+                    store_mode_info->mode = tmp->mbmi.mode;
+                    store_mode_info->ref_frame = tmp->mbmi.ref_frame;
+                    store_mode_info->mv.as_int = tmp->mbmi.mv.as_int;
+                    store_mode_info->dissim = dissim;
+                    tmp++;
+                    store_mode_info++;
+                }
+            }
+        }
+    }
+}
diff --git a/vp8/encoder/mr_dissim.h b/vp8/encoder/mr_dissim.h
new file mode 100644 (file)
index 0000000..3d2c203
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_MR_DISSIM_H
+#define __INC_MR_DISSIM_H
+#include "vpx_config.h"
+
+extern void vp8_cal_low_res_mb_cols(VP8_COMP *cpi);
+extern void vp8_cal_dissimilarity(VP8_COMP *cpi);
+
+#endif
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
new file mode 100644 (file)
index 0000000..cee62fa
--- /dev/null
@@ -0,0 +1,5369 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vp8/common/onyxc_int.h"
+#include "onyx_int.h"
+#include "vp8/common/systemdependent.h"
+#include "quantize.h"
+#include "vp8/common/alloccommon.h"
+#include "mcomp.h"
+#include "firstpass.h"
+#include "psnr.h"
+#include "vpx_scale/vpxscale.h"
+#include "vp8/common/extend.h"
+#include "ratectrl.h"
+#include "vp8/common/quant_common.h"
+#include "segmentation.h"
+#if CONFIG_POSTPROC
+#include "vp8/common/postproc.h"
+#endif
+#include "vpx_mem/vpx_mem.h"
+#include "vp8/common/swapyv12buffer.h"
+#include "vp8/common/threading.h"
+#include "vpx_ports/vpx_timer.h"
+#if ARCH_ARM
+#include "vpx_ports/arm.h"
+#endif
+#if CONFIG_MULTI_RES_ENCODING
+#include "mr_dissim.h"
+#endif
+#include "encodeframe.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <limits.h>
+
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+extern int vp8_update_coef_context(VP8_COMP *cpi);
+extern void vp8_update_coef_probs(VP8_COMP *cpi);
+#endif
+
+extern void vp8cx_pick_filter_level_fast(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi);
+extern void vp8cx_set_alt_lf_level(VP8_COMP *cpi, int filt_val);
+extern void vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi);
+
+extern void vp8_deblock_frame(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *post, int filt_lvl, int low_var_thresh, int flag);
+extern void print_parms(VP8_CONFIG *ocf, char *filenam);
+extern unsigned int vp8_get_processor_freq();
+extern void print_tree_update_probs();
+extern void vp8cx_create_encoder_threads(VP8_COMP *cpi);
+extern void vp8cx_remove_encoder_threads(VP8_COMP *cpi);
+#if HAVE_NEON
+extern void vp8_yv12_copy_frame_func_neon(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc);
+extern void vp8_yv12_copy_src_frame_func_neon(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc);
+#endif
+
+int vp8_estimate_entropy_savings(VP8_COMP *cpi);
+
+int vp8_calc_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest);
+
+extern void vp8_temporal_filter_prepare_c(VP8_COMP *cpi, int distance);
+
+static void set_default_lf_deltas(VP8_COMP *cpi);
+
+extern const int vp8_gf_interval_table[101];
+
+#if CONFIG_INTERNAL_STATS
+#include "math.h"
+
+extern double vp8_calc_ssim
+(
+    YV12_BUFFER_CONFIG *source,
+    YV12_BUFFER_CONFIG *dest,
+    int lumamask,
+    double *weight
+);
+
+
+extern double vp8_calc_ssimg
+(
+    YV12_BUFFER_CONFIG *source,
+    YV12_BUFFER_CONFIG *dest,
+    double *ssim_y,
+    double *ssim_u,
+    double *ssim_v
+);
+
+
+#endif
+
+
+#ifdef OUTPUT_YUV_SRC
+FILE *yuv_file;
+#endif
+
+#if 0
+FILE *framepsnr;
+FILE *kf_list;
+FILE *keyfile;
+#endif
+
+#if 0
+extern int skip_true_count;
+extern int skip_false_count;
+#endif
+
+
+#ifdef ENTROPY_STATS
+extern int intra_mode_stats[10][10][10];
+#endif
+
+#ifdef SPEEDSTATS
+unsigned int frames_at_speed[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+unsigned int tot_pm = 0;
+unsigned int cnt_pm = 0;
+unsigned int tot_ef = 0;
+unsigned int cnt_ef = 0;
+#endif
+
+#ifdef MODE_STATS
+extern unsigned __int64 Sectionbits[50];
+extern int y_modes[5]  ;
+extern int uv_modes[4] ;
+extern int b_modes[10]  ;
+
+extern int inter_y_modes[10] ;
+extern int inter_uv_modes[4] ;
+extern unsigned int inter_b_modes[15];
+#endif
+
+extern const int vp8_bits_per_mb[2][QINDEX_RANGE];
+
+extern const int qrounding_factors[129];
+extern const int qzbin_factors[129];
+extern void vp8cx_init_quantizer(VP8_COMP *cpi);
+extern const int vp8cx_base_skip_false_prob[128];
+
+// Tables relating active max Q to active min Q
+static const unsigned char kf_low_motion_minq[QINDEX_RANGE] =
+{
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,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,2,2,2,2,
+    3,3,3,3,3,3,4,4,4,5,5,5,5,5,6,6,
+    6,6,7,7,8,8,8,8,9,9,10,10,10,10,11,11,
+    11,11,12,12,13,13,13,13,14,14,15,15,15,15,16,16,
+    16,16,17,17,18,18,18,18,19,20,20,21,21,22,23,23
+};
+static const unsigned char kf_high_motion_minq[QINDEX_RANGE] =
+{
+    0,0,0,0,0,0,0,0,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,2,2,2,2,3,3,3,3,
+    3,3,3,3,4,4,4,4,5,5,5,5,5,5,6,6,
+    6,6,7,7,8,8,8,8,9,9,10,10,10,10,11,11,
+    11,11,12,12,13,13,13,13,14,14,15,15,15,15,16,16,
+    16,16,17,17,18,18,18,18,19,19,20,20,20,20,21,21,
+    21,21,22,22,23,23,24,25,25,26,26,27,28,28,29,30
+};
+static const unsigned char gf_low_motion_minq[QINDEX_RANGE] =
+{
+    0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,
+    3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,
+    7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,
+    11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,
+    19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,
+    27,27,28,28,29,29,30,30,31,31,32,32,33,33,34,34,
+    35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,
+    43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58
+};
+static const unsigned char gf_mid_motion_minq[QINDEX_RANGE] =
+{
+    0,0,0,0,1,1,1,1,1,1,2,2,3,3,3,4,
+    4,4,5,5,5,6,6,6,7,7,7,8,8,8,9,9,
+    9,10,10,10,10,11,11,11,12,12,12,12,13,13,13,14,
+    14,14,15,15,16,16,17,17,18,18,19,19,20,20,21,21,
+    22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,
+    30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,
+    38,39,39,40,40,41,41,42,42,43,43,44,45,46,47,48,
+    49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64
+};
+static const unsigned char gf_high_motion_minq[QINDEX_RANGE] =
+{
+    0,0,0,0,1,1,1,1,1,2,2,2,3,3,3,4,
+    4,4,5,5,5,6,6,6,7,7,7,8,8,8,9,9,
+    9,10,10,10,11,11,12,12,13,13,14,14,15,15,16,16,
+    17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,
+    25,25,26,26,27,27,28,28,29,29,30,30,31,31,32,32,
+    33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,
+    41,41,42,42,43,44,45,46,47,48,49,50,51,52,53,54,
+    55,56,57,58,59,60,62,64,66,68,70,72,74,76,78,80
+};
+static const unsigned char inter_minq[QINDEX_RANGE] =
+{
+    0,0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,
+    9,10,11,11,12,13,13,14,15,15,16,17,17,18,19,20,
+    20,21,22,22,23,24,24,25,26,27,27,28,29,30,30,31,
+    32,33,33,34,35,36,36,37,38,39,39,40,41,42,42,43,
+    44,45,46,46,47,48,49,50,50,51,52,53,54,55,55,56,
+    57,58,59,60,60,61,62,63,64,65,66,67,67,68,69,70,
+    71,72,73,74,75,75,76,77,78,79,80,81,82,83,84,85,
+    86,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100
+};
+
+#ifdef PACKET_TESTING
+extern FILE *vpxlogc;
+#endif
+
+static void save_layer_context(VP8_COMP *cpi)
+{
+    LAYER_CONTEXT *lc = &cpi->layer_context[cpi->current_layer];
+
+    // Save layer dependent coding state
+    lc->target_bandwidth                 = cpi->target_bandwidth;
+    //lc->target_bandwidth                 = cpi->oxcf.target_bandwidth;
+    lc->starting_buffer_level            = cpi->oxcf.starting_buffer_level;
+    lc->optimal_buffer_level             = cpi->oxcf.optimal_buffer_level;
+    lc->maximum_buffer_size              = cpi->oxcf.maximum_buffer_size;
+    lc->starting_buffer_level_in_ms      = cpi->oxcf.starting_buffer_level_in_ms;
+    lc->optimal_buffer_level_in_ms       = cpi->oxcf.optimal_buffer_level_in_ms;
+    lc->maximum_buffer_size_in_ms        = cpi->oxcf.maximum_buffer_size_in_ms;
+    lc->buffer_level                     = cpi->buffer_level;
+    lc->bits_off_target                  = cpi->bits_off_target;
+    lc->total_actual_bits                = cpi->total_actual_bits;
+    lc->worst_quality                    = cpi->worst_quality;
+    lc->active_worst_quality             = cpi->active_worst_quality;
+    lc->best_quality                     = cpi->best_quality;
+    lc->active_best_quality              = cpi->active_best_quality;
+    lc->ni_av_qi                         = cpi->ni_av_qi;
+    lc->ni_tot_qi                        = cpi->ni_tot_qi;
+    lc->ni_frames                        = cpi->ni_frames;
+    lc->avg_frame_qindex                 = cpi->avg_frame_qindex;
+    lc->rate_correction_factor           = cpi->rate_correction_factor;
+    lc->key_frame_rate_correction_factor = cpi->key_frame_rate_correction_factor;
+    lc->gf_rate_correction_factor        = cpi->gf_rate_correction_factor;
+    lc->zbin_over_quant                  = cpi->zbin_over_quant;
+    lc->inter_frame_target               = cpi->inter_frame_target;
+    lc->total_byte_count                 = cpi->total_byte_count;
+    lc->filter_level                     = cpi->common.filter_level;
+
+    lc->last_frame_percent_intra         = cpi->last_frame_percent_intra;
+
+    memcpy (lc->count_mb_ref_frame_usage,
+            cpi->count_mb_ref_frame_usage,
+            sizeof(cpi->count_mb_ref_frame_usage));
+}
+
+static void restore_layer_context(VP8_COMP *cpi, const int layer)
+{
+    LAYER_CONTEXT *lc = &cpi->layer_context[layer];
+
+    // Restore layer dependent coding state
+    cpi->current_layer                    = layer;
+    cpi->target_bandwidth                 = lc->target_bandwidth;
+    cpi->oxcf.target_bandwidth            = lc->target_bandwidth;
+    cpi->oxcf.starting_buffer_level       = lc->starting_buffer_level;
+    cpi->oxcf.optimal_buffer_level        = lc->optimal_buffer_level;
+    cpi->oxcf.maximum_buffer_size         = lc->maximum_buffer_size;
+    cpi->oxcf.starting_buffer_level_in_ms = lc->starting_buffer_level_in_ms;
+    cpi->oxcf.optimal_buffer_level_in_ms  = lc->optimal_buffer_level_in_ms;
+    cpi->oxcf.maximum_buffer_size_in_ms   = lc->maximum_buffer_size_in_ms;
+    cpi->buffer_level                     = lc->buffer_level;
+    cpi->bits_off_target                  = lc->bits_off_target;
+    cpi->total_actual_bits                = lc->total_actual_bits;
+    //cpi->worst_quality                    = lc->worst_quality;
+    cpi->active_worst_quality             = lc->active_worst_quality;
+    //cpi->best_quality                     = lc->best_quality;
+    cpi->active_best_quality              = lc->active_best_quality;
+    cpi->ni_av_qi                         = lc->ni_av_qi;
+    cpi->ni_tot_qi                        = lc->ni_tot_qi;
+    cpi->ni_frames                        = lc->ni_frames;
+    cpi->avg_frame_qindex                 = lc->avg_frame_qindex;
+    cpi->rate_correction_factor           = lc->rate_correction_factor;
+    cpi->key_frame_rate_correction_factor = lc->key_frame_rate_correction_factor;
+    cpi->gf_rate_correction_factor        = lc->gf_rate_correction_factor;
+    cpi->zbin_over_quant                  = lc->zbin_over_quant;
+    cpi->inter_frame_target               = lc->inter_frame_target;
+    cpi->total_byte_count                 = lc->total_byte_count;
+    cpi->common.filter_level              = lc->filter_level;
+
+    cpi->last_frame_percent_intra         = lc->last_frame_percent_intra;
+
+    memcpy (cpi->count_mb_ref_frame_usage,
+            lc->count_mb_ref_frame_usage,
+            sizeof(cpi->count_mb_ref_frame_usage));
+}
+
+static void setup_features(VP8_COMP *cpi)
+{
+    // Set up default state for MB feature flags
+    cpi->mb.e_mbd.segmentation_enabled = 0;
+    cpi->mb.e_mbd.update_mb_segmentation_map = 0;
+    cpi->mb.e_mbd.update_mb_segmentation_data = 0;
+    vpx_memset(cpi->mb.e_mbd.mb_segment_tree_probs, 255, sizeof(cpi->mb.e_mbd.mb_segment_tree_probs));
+    vpx_memset(cpi->mb.e_mbd.segment_feature_data, 0, sizeof(cpi->mb.e_mbd.segment_feature_data));
+
+    cpi->mb.e_mbd.mode_ref_lf_delta_enabled = 0;
+    cpi->mb.e_mbd.mode_ref_lf_delta_update = 0;
+    vpx_memset(cpi->mb.e_mbd.ref_lf_deltas, 0, sizeof(cpi->mb.e_mbd.ref_lf_deltas));
+    vpx_memset(cpi->mb.e_mbd.mode_lf_deltas, 0, sizeof(cpi->mb.e_mbd.mode_lf_deltas));
+    vpx_memset(cpi->mb.e_mbd.last_ref_lf_deltas, 0, sizeof(cpi->mb.e_mbd.ref_lf_deltas));
+    vpx_memset(cpi->mb.e_mbd.last_mode_lf_deltas, 0, sizeof(cpi->mb.e_mbd.mode_lf_deltas));
+
+    set_default_lf_deltas(cpi);
+
+}
+
+
+static void dealloc_raw_frame_buffers(VP8_COMP *cpi);
+
+
+static void dealloc_compressor_data(VP8_COMP *cpi)
+{
+    vpx_free(cpi->tplist);
+    cpi->tplist = NULL;
+
+    // Delete last frame MV storage buffers
+    vpx_free(cpi->lfmv);
+    cpi->lfmv = 0;
+
+    vpx_free(cpi->lf_ref_frame_sign_bias);
+    cpi->lf_ref_frame_sign_bias = 0;
+
+    vpx_free(cpi->lf_ref_frame);
+    cpi->lf_ref_frame = 0;
+
+    // Delete sementation map
+    vpx_free(cpi->segmentation_map);
+    cpi->segmentation_map = 0;
+
+    vpx_free(cpi->active_map);
+    cpi->active_map = 0;
+
+    vp8_de_alloc_frame_buffers(&cpi->common);
+
+    vp8_yv12_de_alloc_frame_buffer(&cpi->pick_lf_lvl_frame);
+    vp8_yv12_de_alloc_frame_buffer(&cpi->scaled_source);
+    dealloc_raw_frame_buffers(cpi);
+
+    vpx_free(cpi->tok);
+    cpi->tok = 0;
+
+    // Structure used to monitor GF usage
+    vpx_free(cpi->gf_active_flags);
+    cpi->gf_active_flags = 0;
+
+    // Activity mask based per mb zbin adjustments
+    vpx_free(cpi->mb_activity_map);
+    cpi->mb_activity_map = 0;
+    vpx_free(cpi->mb_norm_activity_map);
+    cpi->mb_norm_activity_map = 0;
+
+    vpx_free(cpi->mb.pip);
+    cpi->mb.pip = 0;
+}
+
+static void enable_segmentation(VP8_COMP *cpi)
+{
+    // Set the appropriate feature bit
+    cpi->mb.e_mbd.segmentation_enabled = 1;
+    cpi->mb.e_mbd.update_mb_segmentation_map = 1;
+    cpi->mb.e_mbd.update_mb_segmentation_data = 1;
+}
+static void disable_segmentation(VP8_COMP *cpi)
+{
+    // Clear the appropriate feature bit
+    cpi->mb.e_mbd.segmentation_enabled = 0;
+}
+
+// Valid values for a segment are 0 to 3
+// Segmentation map is arrange as [Rows][Columns]
+static void set_segmentation_map(VP8_COMP *cpi, unsigned char *segmentation_map)
+{
+    // Copy in the new segmentation map
+    vpx_memcpy(cpi->segmentation_map, segmentation_map, (cpi->common.mb_rows * cpi->common.mb_cols));
+
+    // Signal that the map should be updated.
+    cpi->mb.e_mbd.update_mb_segmentation_map = 1;
+    cpi->mb.e_mbd.update_mb_segmentation_data = 1;
+}
+
+// The values given for each segment can be either deltas (from the default value chosen for the frame) or absolute values.
+//
+// Valid range for abs values is (0-127 for MB_LVL_ALT_Q) , (0-63 for SEGMENT_ALT_LF)
+// Valid range for delta values are (+/-127 for MB_LVL_ALT_Q) , (+/-63 for SEGMENT_ALT_LF)
+//
+// abs_delta = SEGMENT_DELTADATA (deltas) abs_delta = SEGMENT_ABSDATA (use the absolute values given).
+//
+//
+static void set_segment_data(VP8_COMP *cpi, signed char *feature_data, unsigned char abs_delta)
+{
+    cpi->mb.e_mbd.mb_segement_abs_delta = abs_delta;
+    vpx_memcpy(cpi->segment_feature_data, feature_data, sizeof(cpi->segment_feature_data));
+}
+
+
+static void segmentation_test_function(VP8_COMP *cpi)
+{
+    unsigned char *seg_map;
+    signed char feature_data[MB_LVL_MAX][MAX_MB_SEGMENTS];
+
+    // Create a temporary map for segmentation data.
+    CHECK_MEM_ERROR(seg_map, vpx_calloc(cpi->common.mb_rows * cpi->common.mb_cols, 1));
+
+    // MB loop to set local segmentation map
+    /*for ( i = 0; i < cpi->common.mb_rows; i++ )
+    {
+        for ( j = 0; j < cpi->common.mb_cols; j++ )
+        {
+            //seg_map[(i*cpi->common.mb_cols) + j] = (j % 2) + ((i%2)* 2);
+            //if ( j < cpi->common.mb_cols/2 )
+
+            // Segment 1 around the edge else 0
+            if ( (i == 0) || (j == 0) || (i == (cpi->common.mb_rows-1)) || (j == (cpi->common.mb_cols-1)) )
+                seg_map[(i*cpi->common.mb_cols) + j] = 1;
+            //else if ( (i < 2) || (j < 2) || (i > (cpi->common.mb_rows-3)) || (j > (cpi->common.mb_cols-3)) )
+            //  seg_map[(i*cpi->common.mb_cols) + j] = 2;
+            //else if ( (i < 5) || (j < 5) || (i > (cpi->common.mb_rows-6)) || (j > (cpi->common.mb_cols-6)) )
+            //  seg_map[(i*cpi->common.mb_cols) + j] = 3;
+            else
+                seg_map[(i*cpi->common.mb_cols) + j] = 0;
+        }
+    }*/
+
+    // Set the segmentation Map
+    set_segmentation_map(cpi, seg_map);
+
+    // Activate segmentation.
+    enable_segmentation(cpi);
+
+    // Set up the quant segment data
+    feature_data[MB_LVL_ALT_Q][0] = 0;
+    feature_data[MB_LVL_ALT_Q][1] = 4;
+    feature_data[MB_LVL_ALT_Q][2] = 0;
+    feature_data[MB_LVL_ALT_Q][3] = 0;
+    // Set up the loop segment data
+    feature_data[MB_LVL_ALT_LF][0] = 0;
+    feature_data[MB_LVL_ALT_LF][1] = 0;
+    feature_data[MB_LVL_ALT_LF][2] = 0;
+    feature_data[MB_LVL_ALT_LF][3] = 0;
+
+    // Initialise the feature data structure
+    // SEGMENT_DELTADATA    0, SEGMENT_ABSDATA      1
+    set_segment_data(cpi, &feature_data[0][0], SEGMENT_DELTADATA);
+
+    // Delete sementation map
+        vpx_free(seg_map);
+
+    seg_map = 0;
+
+}
+
+// A simple function to cyclically refresh the background at a lower Q
+static void cyclic_background_refresh(VP8_COMP *cpi, int Q, int lf_adjustment)
+{
+    unsigned char *seg_map;
+    signed char feature_data[MB_LVL_MAX][MAX_MB_SEGMENTS];
+    int i;
+    int block_count = cpi->cyclic_refresh_mode_max_mbs_perframe;
+    int mbs_in_frame = cpi->common.mb_rows * cpi->common.mb_cols;
+
+    // Create a temporary map for segmentation data.
+    CHECK_MEM_ERROR(seg_map, vpx_calloc(cpi->common.mb_rows * cpi->common.mb_cols, 1));
+
+    cpi->cyclic_refresh_q = Q;
+
+    for (i = Q; i > 0; i--)
+    {
+        if (vp8_bits_per_mb[cpi->common.frame_type][i] >= ((vp8_bits_per_mb[cpi->common.frame_type][Q]*(Q + 128)) / 64))
+            //if ( vp8_bits_per_mb[cpi->common.frame_type][i] >= ((vp8_bits_per_mb[cpi->common.frame_type][Q]*((2*Q)+96))/64) )
+        {
+            break;
+        }
+    }
+
+    cpi->cyclic_refresh_q = i;
+
+    // Only update for inter frames
+    if (cpi->common.frame_type != KEY_FRAME)
+    {
+        // Cycle through the macro_block rows
+        // MB loop to set local segmentation map
+        for (i = cpi->cyclic_refresh_mode_index; i < mbs_in_frame; i++)
+        {
+            // If the MB is as a candidate for clean up then mark it for possible boost/refresh (segment 1)
+            // The segment id may get reset to 0 later if the MB gets coded anything other than last frame 0,0
+            // as only (last frame 0,0) MBs are eligable for refresh : that is to say Mbs likely to be background blocks.
+            if (cpi->cyclic_refresh_map[i] == 0)
+            {
+                seg_map[i] = 1;
+            }
+            else
+            {
+                seg_map[i] = 0;
+
+                // Skip blocks that have been refreshed recently anyway.
+                if (cpi->cyclic_refresh_map[i] < 0)
+                    //cpi->cyclic_refresh_map[i] = cpi->cyclic_refresh_map[i] / 16;
+                    cpi->cyclic_refresh_map[i]++;
+            }
+
+
+            if (block_count > 0)
+                block_count--;
+            else
+                break;
+
+        }
+
+        // If we have gone through the frame reset to the start
+        cpi->cyclic_refresh_mode_index = i;
+
+        if (cpi->cyclic_refresh_mode_index >= mbs_in_frame)
+            cpi->cyclic_refresh_mode_index = 0;
+    }
+
+    // Set the segmentation Map
+    set_segmentation_map(cpi, seg_map);
+
+    // Activate segmentation.
+    enable_segmentation(cpi);
+
+    // Set up the quant segment data
+    feature_data[MB_LVL_ALT_Q][0] = 0;
+    feature_data[MB_LVL_ALT_Q][1] = (cpi->cyclic_refresh_q - Q);
+    feature_data[MB_LVL_ALT_Q][2] = 0;
+    feature_data[MB_LVL_ALT_Q][3] = 0;
+
+    // Set up the loop segment data
+    feature_data[MB_LVL_ALT_LF][0] = 0;
+    feature_data[MB_LVL_ALT_LF][1] = lf_adjustment;
+    feature_data[MB_LVL_ALT_LF][2] = 0;
+    feature_data[MB_LVL_ALT_LF][3] = 0;
+
+    // Initialise the feature data structure
+    // SEGMENT_DELTADATA    0, SEGMENT_ABSDATA      1
+    set_segment_data(cpi, &feature_data[0][0], SEGMENT_DELTADATA);
+
+    // Delete sementation map
+    vpx_free(seg_map);
+
+    seg_map = 0;
+
+}
+
+static void set_default_lf_deltas(VP8_COMP *cpi)
+{
+    cpi->mb.e_mbd.mode_ref_lf_delta_enabled = 1;
+    cpi->mb.e_mbd.mode_ref_lf_delta_update = 1;
+
+    vpx_memset(cpi->mb.e_mbd.ref_lf_deltas, 0, sizeof(cpi->mb.e_mbd.ref_lf_deltas));
+    vpx_memset(cpi->mb.e_mbd.mode_lf_deltas, 0, sizeof(cpi->mb.e_mbd.mode_lf_deltas));
+
+    // Test of ref frame deltas
+    cpi->mb.e_mbd.ref_lf_deltas[INTRA_FRAME] = 2;
+    cpi->mb.e_mbd.ref_lf_deltas[LAST_FRAME] = 0;
+    cpi->mb.e_mbd.ref_lf_deltas[GOLDEN_FRAME] = -2;
+    cpi->mb.e_mbd.ref_lf_deltas[ALTREF_FRAME] = -2;
+
+    cpi->mb.e_mbd.mode_lf_deltas[0] = 4;               // BPRED
+    cpi->mb.e_mbd.mode_lf_deltas[1] = -2;              // Zero
+    cpi->mb.e_mbd.mode_lf_deltas[2] = 2;               // New mv
+    cpi->mb.e_mbd.mode_lf_deltas[3] = 4;               // Split mv
+}
+
+/* Convenience macros for mapping speed and mode into a continuous
+ * range
+ */
+#define GOOD(x) (x+1)
+#define RT(x) (x+7)
+
+static int speed_map(int speed, const int *map)
+{
+    int res;
+
+    do
+    {
+        res = *map++;
+    } while(speed >= *map++);
+    return res;
+}
+
+static const int thresh_mult_map_znn[] = {
+    /* map common to zero, nearest, and near */
+    0, GOOD(2), 1500, GOOD(3), 2000, RT(0), 1000, RT(2), 2000, INT_MAX
+};
+
+static const int thresh_mult_map_vhpred[] = {
+    1000, GOOD(2), 1500, GOOD(3), 2000, RT(0), 1000, RT(1), 2000,
+    RT(7), INT_MAX, INT_MAX
+};
+
+static const int thresh_mult_map_bpred[] = {
+    2000, GOOD(0), 2500, GOOD(2), 5000, GOOD(3), 7500, RT(0), 2500, RT(1), 5000,
+    RT(6), INT_MAX, INT_MAX
+};
+
+static const int thresh_mult_map_tm[] = {
+    1000, GOOD(2), 1500, GOOD(3), 2000, RT(0), 0, RT(1), 1000, RT(2), 2000,
+    RT(7), INT_MAX, INT_MAX
+};
+
+static const int thresh_mult_map_new1[] = {
+    1000, GOOD(2), 2000, RT(0), 2000, INT_MAX
+};
+
+static const int thresh_mult_map_new2[] = {
+    1000, GOOD(2), 2000, GOOD(3), 2500, GOOD(5), 4000, RT(0), 2000, RT(2), 2500,
+    RT(5), 4000, INT_MAX
+};
+
+static const int thresh_mult_map_split1[] = {
+    2500, GOOD(0), 1700, GOOD(2), 10000, GOOD(3), 25000, GOOD(4), INT_MAX,
+    RT(0), 5000, RT(1), 10000, RT(2), 25000, RT(3), INT_MAX, INT_MAX
+};
+
+static const int thresh_mult_map_split2[] = {
+    5000, GOOD(0), 4500, GOOD(2), 20000, GOOD(3), 50000, GOOD(4), INT_MAX,
+    RT(0), 10000, RT(1), 20000, RT(2), 50000, RT(3), INT_MAX, INT_MAX
+};
+
+static const int mode_check_freq_map_zn2[] = {
+    /* {zero,nearest}{2,3} */
+    0, RT(10), 1<<1, RT(11), 1<<2, RT(12), 1<<3, INT_MAX
+};
+
+static const int mode_check_freq_map_vhbpred[] = {
+    0, GOOD(5), 2, RT(0), 0, RT(3), 2, RT(5), 4, INT_MAX
+};
+
+static const int mode_check_freq_map_near2[] = {
+    0, GOOD(5), 2, RT(0), 0, RT(3), 2, RT(10), 1<<2, RT(11), 1<<3, RT(12), 1<<4,
+    INT_MAX
+};
+
+static const int mode_check_freq_map_new1[] = {
+    0, RT(10), 1<<1, RT(11), 1<<2, RT(12), 1<<3, INT_MAX
+};
+
+static const int mode_check_freq_map_new2[] = {
+    0, GOOD(5), 4, RT(0), 0, RT(3), 4, RT(10), 1<<3, RT(11), 1<<4, RT(12), 1<<5,
+    INT_MAX
+};
+
+static const int mode_check_freq_map_split1[] = {
+    0, GOOD(2), 2, GOOD(3), 7, RT(1), 2, RT(2), 7, INT_MAX
+};
+
+static const int mode_check_freq_map_split2[] = {
+    0, GOOD(1), 2, GOOD(2), 4, GOOD(3), 15, RT(1), 4, RT(2), 15, INT_MAX
+};
+
+void vp8_set_speed_features(VP8_COMP *cpi)
+{
+    SPEED_FEATURES *sf = &cpi->sf;
+    int Mode = cpi->compressor_speed;
+    int Speed = cpi->Speed;
+    int i;
+    VP8_COMMON *cm = &cpi->common;
+    int last_improved_quant = sf->improved_quant;
+    int ref_frames;
+
+    // Initialise default mode frequency sampling variables
+    for (i = 0; i < MAX_MODES; i ++)
+    {
+        cpi->mode_check_freq[i] = 0;
+        cpi->mode_test_hit_counts[i] = 0;
+        cpi->mode_chosen_counts[i] = 0;
+    }
+
+    cpi->mbs_tested_so_far = 0;
+
+    // best quality defaults
+    sf->RD = 1;
+    sf->search_method = NSTEP;
+    sf->improved_quant = 1;
+    sf->improved_dct = 1;
+    sf->auto_filter = 1;
+    sf->recode_loop = 1;
+    sf->quarter_pixel_search = 1;
+    sf->half_pixel_search = 1;
+    sf->iterative_sub_pixel = 1;
+    sf->optimize_coefficients = 1;
+    sf->use_fastquant_for_pick = 0;
+    sf->no_skip_block4x4_search = 1;
+
+    sf->first_step = 0;
+    sf->max_step_search_steps = MAX_MVSEARCH_STEPS;
+    sf->improved_mv_pred = 1;
+
+    // default thresholds to 0
+    for (i = 0; i < MAX_MODES; i++)
+        sf->thresh_mult[i] = 0;
+
+    /* Count enabled references */
+    ref_frames = 1;
+    if (cpi->ref_frame_flags & VP8_LAST_FLAG)
+        ref_frames++;
+    if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
+        ref_frames++;
+    if (cpi->ref_frame_flags & VP8_ALT_FLAG)
+        ref_frames++;
+
+    /* Convert speed to continuous range, with clamping */
+    if (Mode == 0)
+        Speed = 0;
+    else if (Mode == 2)
+        Speed = RT(Speed);
+    else
+    {
+        if (Speed > 5)
+            Speed = 5;
+        Speed = GOOD(Speed);
+    }
+
+    sf->thresh_mult[THR_ZERO1] =
+    sf->thresh_mult[THR_NEAREST1] =
+    sf->thresh_mult[THR_NEAR1] =
+    sf->thresh_mult[THR_DC] = 0; /* always */
+
+    sf->thresh_mult[THR_ZERO2] =
+    sf->thresh_mult[THR_ZERO3] =
+    sf->thresh_mult[THR_NEAREST2] =
+    sf->thresh_mult[THR_NEAREST3] =
+    sf->thresh_mult[THR_NEAR2]  =
+    sf->thresh_mult[THR_NEAR3]  = speed_map(Speed, thresh_mult_map_znn);
+
+    sf->thresh_mult[THR_V_PRED] =
+    sf->thresh_mult[THR_H_PRED] = speed_map(Speed, thresh_mult_map_vhpred);
+    sf->thresh_mult[THR_B_PRED] = speed_map(Speed, thresh_mult_map_bpred);
+    sf->thresh_mult[THR_TM]     = speed_map(Speed, thresh_mult_map_tm);
+    sf->thresh_mult[THR_NEW1]   = speed_map(Speed, thresh_mult_map_new1);
+    sf->thresh_mult[THR_NEW2]   =
+    sf->thresh_mult[THR_NEW3]   = speed_map(Speed, thresh_mult_map_new2);
+    sf->thresh_mult[THR_SPLIT1] = speed_map(Speed, thresh_mult_map_split1);
+    sf->thresh_mult[THR_SPLIT2] =
+    sf->thresh_mult[THR_SPLIT3] = speed_map(Speed, thresh_mult_map_split2);
+
+    cpi->mode_check_freq[THR_ZERO1] =
+    cpi->mode_check_freq[THR_NEAREST1] =
+    cpi->mode_check_freq[THR_NEAR1] =
+    cpi->mode_check_freq[THR_TM]     =
+    cpi->mode_check_freq[THR_DC] = 0; /* always */
+
+    cpi->mode_check_freq[THR_ZERO2] =
+    cpi->mode_check_freq[THR_ZERO3] =
+    cpi->mode_check_freq[THR_NEAREST2] =
+    cpi->mode_check_freq[THR_NEAREST3] = speed_map(Speed,
+                                                   mode_check_freq_map_zn2);
+
+    cpi->mode_check_freq[THR_NEAR2]  =
+    cpi->mode_check_freq[THR_NEAR3]  = speed_map(Speed,
+                                                 mode_check_freq_map_near2);
+
+    cpi->mode_check_freq[THR_V_PRED] =
+    cpi->mode_check_freq[THR_H_PRED] =
+    cpi->mode_check_freq[THR_B_PRED] = speed_map(Speed,
+                                                 mode_check_freq_map_vhbpred);
+    cpi->mode_check_freq[THR_NEW1]   = speed_map(Speed,
+                                                 mode_check_freq_map_new1);
+    cpi->mode_check_freq[THR_NEW2]   =
+    cpi->mode_check_freq[THR_NEW3]   = speed_map(Speed,
+                                                 mode_check_freq_map_new2);
+    cpi->mode_check_freq[THR_SPLIT1] = speed_map(Speed,
+                                                 mode_check_freq_map_split1);
+    cpi->mode_check_freq[THR_SPLIT2] =
+    cpi->mode_check_freq[THR_SPLIT3] = speed_map(Speed,
+                                                 mode_check_freq_map_split2);
+    Speed = cpi->Speed;
+    switch (Mode)
+    {
+#if !(CONFIG_REALTIME_ONLY)
+    case 0: // best quality mode
+        sf->first_step = 0;
+        sf->max_step_search_steps = MAX_MVSEARCH_STEPS;
+        break;
+    case 1:
+    case 3:
+        if (Speed > 0)
+        {
+            /* Disable coefficient optimization above speed 0 */
+            sf->optimize_coefficients = 0;
+            sf->use_fastquant_for_pick = 1;
+            sf->no_skip_block4x4_search = 0;
+
+            sf->first_step = 1;
+        }
+
+        if (Speed > 2)
+        {
+            sf->improved_quant = 0;
+            sf->improved_dct = 0;
+
+            // Only do recode loop on key frames, golden frames and
+            // alt ref frames
+            sf->recode_loop = 2;
+
+        }
+
+        if (Speed > 3)
+        {
+            sf->auto_filter = 1;
+            sf->recode_loop = 0; // recode loop off
+            sf->RD = 0;         // Turn rd off
+
+        }
+
+        if (Speed > 4)
+        {
+            sf->auto_filter = 0;                     // Faster selection of loop filter
+        }
+
+        break;
+#endif
+    case 2:
+        sf->optimize_coefficients = 0;
+        sf->recode_loop = 0;
+        sf->auto_filter = 1;
+        sf->iterative_sub_pixel = 1;
+        sf->search_method = NSTEP;
+
+        if (Speed > 0)
+        {
+            sf->improved_quant = 0;
+            sf->improved_dct = 0;
+
+            sf->use_fastquant_for_pick = 1;
+            sf->no_skip_block4x4_search = 0;
+            sf->first_step = 1;
+        }
+
+        if (Speed > 2)
+            sf->auto_filter = 0;                     // Faster selection of loop filter
+
+        if (Speed > 3)
+        {
+            sf->RD = 0;
+            sf->auto_filter = 1;
+        }
+
+        if (Speed > 4)
+        {
+            sf->auto_filter = 0;                     // Faster selection of loop filter
+            sf->search_method = HEX;
+            sf->iterative_sub_pixel = 0;
+        }
+
+        if (Speed > 6)
+        {
+            unsigned int sum = 0;
+            unsigned int total_mbs = cm->MBs;
+            int i, thresh;
+            unsigned int total_skip;
+
+            int min = 2000;
+
+            if (cpi->oxcf.encode_breakout > 2000)
+                min = cpi->oxcf.encode_breakout;
+
+            min >>= 7;
+
+            for (i = 0; i < min; i++)
+            {
+                sum += cpi->error_bins[i];
+            }
+
+            total_skip = sum;
+            sum = 0;
+
+            // i starts from 2 to make sure thresh started from 2048
+            for (; i < 1024; i++)
+            {
+                sum += cpi->error_bins[i];
+
+                if (10 * sum >= (unsigned int)(cpi->Speed - 6)*(total_mbs - total_skip))
+                    break;
+            }
+
+            i--;
+            thresh = (i << 7);
+
+            if (thresh < 2000)
+                thresh = 2000;
+
+            if (ref_frames > 1)
+            {
+                sf->thresh_mult[THR_NEW1 ] = thresh;
+                sf->thresh_mult[THR_NEAREST1  ] = thresh >> 1;
+                sf->thresh_mult[THR_NEAR1     ] = thresh >> 1;
+            }
+
+            if (ref_frames > 2)
+            {
+                sf->thresh_mult[THR_NEW2] = thresh << 1;
+                sf->thresh_mult[THR_NEAREST2 ] = thresh;
+                sf->thresh_mult[THR_NEAR2    ] = thresh;
+            }
+
+            if (ref_frames > 3)
+            {
+                sf->thresh_mult[THR_NEW3] = thresh << 1;
+                sf->thresh_mult[THR_NEAREST3 ] = thresh;
+                sf->thresh_mult[THR_NEAR3    ] = thresh;
+            }
+
+            sf->improved_mv_pred = 0;
+        }
+
+        if (Speed > 8)
+            sf->quarter_pixel_search = 0;
+
+        if(cm->version == 0)
+        {
+            cm->filter_type = NORMAL_LOOPFILTER;
+
+            if (Speed >= 14)
+                cm->filter_type = SIMPLE_LOOPFILTER;
+        }
+        else
+        {
+            cm->filter_type = SIMPLE_LOOPFILTER;
+        }
+
+        // This has a big hit on quality. Last resort
+        if (Speed >= 15)
+            sf->half_pixel_search = 0;
+
+        vpx_memset(cpi->error_bins, 0, sizeof(cpi->error_bins));
+
+    }; /* switch */
+
+    // Slow quant, dct and trellis not worthwhile for first pass
+    // so make sure they are always turned off.
+    if ( cpi->pass == 1 )
+    {
+        sf->improved_quant = 0;
+        sf->optimize_coefficients = 0;
+        sf->improved_dct = 0;
+    }
+
+    if (cpi->sf.search_method == NSTEP)
+    {
+        vp8_init3smotion_compensation(&cpi->mb, cm->yv12_fb[cm->lst_fb_idx].y_stride);
+    }
+    else if (cpi->sf.search_method == DIAMOND)
+    {
+        vp8_init_dsmotion_compensation(&cpi->mb, cm->yv12_fb[cm->lst_fb_idx].y_stride);
+    }
+
+    if (cpi->sf.improved_dct)
+    {
+        cpi->mb.short_fdct8x4 = vp8_short_fdct8x4;
+        cpi->mb.short_fdct4x4 = vp8_short_fdct4x4;
+    }
+    else
+    {
+        /* No fast FDCT defined for any platform at this time. */
+        cpi->mb.short_fdct8x4 = vp8_short_fdct8x4;
+        cpi->mb.short_fdct4x4 = vp8_short_fdct4x4;
+    }
+
+    cpi->mb.short_walsh4x4 = vp8_short_walsh4x4;
+
+    if (cpi->sf.improved_quant)
+    {
+        cpi->mb.quantize_b      = vp8_regular_quantize_b;
+        cpi->mb.quantize_b_pair = vp8_regular_quantize_b_pair;
+    }
+    else
+    {
+        cpi->mb.quantize_b      = vp8_fast_quantize_b;
+        cpi->mb.quantize_b_pair = vp8_fast_quantize_b_pair;
+    }
+    if (cpi->sf.improved_quant != last_improved_quant)
+        vp8cx_init_quantizer(cpi);
+
+    if (cpi->sf.iterative_sub_pixel == 1)
+    {
+        cpi->find_fractional_mv_step = vp8_find_best_sub_pixel_step_iteratively;
+    }
+    else if (cpi->sf.quarter_pixel_search)
+    {
+        cpi->find_fractional_mv_step = vp8_find_best_sub_pixel_step;
+    }
+    else if (cpi->sf.half_pixel_search)
+    {
+        cpi->find_fractional_mv_step = vp8_find_best_half_pixel_step;
+    }
+    else
+    {
+        cpi->find_fractional_mv_step = vp8_skip_fractional_mv_step;
+    }
+
+    if (cpi->sf.optimize_coefficients == 1 && cpi->pass!=1)
+        cpi->mb.optimize = 1;
+    else
+        cpi->mb.optimize = 0;
+
+    if (cpi->common.full_pixel)
+        cpi->find_fractional_mv_step = vp8_skip_fractional_mv_step;
+
+#ifdef SPEEDSTATS
+    frames_at_speed[cpi->Speed]++;
+#endif
+}
+#undef GOOD
+#undef RT
+
+static void alloc_raw_frame_buffers(VP8_COMP *cpi)
+{
+#if VP8_TEMPORAL_ALT_REF
+    int width = (cpi->oxcf.Width + 15) & ~15;
+    int height = (cpi->oxcf.Height + 15) & ~15;
+#endif
+
+    cpi->lookahead = vp8_lookahead_init(cpi->oxcf.Width, cpi->oxcf.Height,
+                                        cpi->oxcf.lag_in_frames);
+    if(!cpi->lookahead)
+        vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
+                           "Failed to allocate lag buffers");
+
+#if VP8_TEMPORAL_ALT_REF
+
+    if (vp8_yv12_alloc_frame_buffer(&cpi->alt_ref_buffer,
+                                    width, height, VP8BORDERINPIXELS))
+        vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
+                           "Failed to allocate altref buffer");
+
+#endif
+}
+
+
+static void dealloc_raw_frame_buffers(VP8_COMP *cpi)
+{
+#if VP8_TEMPORAL_ALT_REF
+    vp8_yv12_de_alloc_frame_buffer(&cpi->alt_ref_buffer);
+#endif
+    vp8_lookahead_destroy(cpi->lookahead);
+}
+
+
+static int vp8_alloc_partition_data(VP8_COMP *cpi)
+{
+        vpx_free(cpi->mb.pip);
+
+    cpi->mb.pip = vpx_calloc((cpi->common.mb_cols + 1) *
+                                (cpi->common.mb_rows + 1),
+                                sizeof(PARTITION_INFO));
+    if(!cpi->mb.pip)
+        return 1;
+
+    cpi->mb.pi = cpi->mb.pip + cpi->common.mode_info_stride + 1;
+
+    return 0;
+}
+
+void vp8_alloc_compressor_data(VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = & cpi->common;
+
+    int width = cm->Width;
+    int height = cm->Height;
+
+    if (vp8_alloc_frame_buffers(cm, width, height))
+        vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
+                           "Failed to allocate frame buffers");
+
+    if (vp8_alloc_partition_data(cpi))
+        vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
+                           "Failed to allocate partition data");
+
+
+    if ((width & 0xf) != 0)
+        width += 16 - (width & 0xf);
+
+    if ((height & 0xf) != 0)
+        height += 16 - (height & 0xf);
+
+
+    if (vp8_yv12_alloc_frame_buffer(&cpi->pick_lf_lvl_frame,
+                                    width, height, VP8BORDERINPIXELS))
+        vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
+                           "Failed to allocate last frame buffer");
+
+    if (vp8_yv12_alloc_frame_buffer(&cpi->scaled_source,
+                                    width, height, VP8BORDERINPIXELS))
+        vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
+                           "Failed to allocate scaled source buffer");
+
+    vpx_free(cpi->tok);
+
+    {
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+        unsigned int tokens = 8 * 24 * 16; /* one MB for each thread */
+#else
+        unsigned int tokens = cm->mb_rows * cm->mb_cols * 24 * 16;
+#endif
+        CHECK_MEM_ERROR(cpi->tok, vpx_calloc(tokens, sizeof(*cpi->tok)));
+    }
+
+    // Data used for real time vc mode to see if gf needs refreshing
+    cpi->inter_zz_count = 0;
+    cpi->gf_bad_count = 0;
+    cpi->gf_update_recommended = 0;
+
+
+    // Structures used to minitor GF usage
+    vpx_free(cpi->gf_active_flags);
+    CHECK_MEM_ERROR(cpi->gf_active_flags,
+                    vpx_calloc(1, cm->mb_rows * cm->mb_cols));
+    cpi->gf_active_count = cm->mb_rows * cm->mb_cols;
+
+    vpx_free(cpi->mb_activity_map);
+    CHECK_MEM_ERROR(cpi->mb_activity_map,
+                    vpx_calloc(sizeof(unsigned int),
+                    cm->mb_rows * cm->mb_cols));
+
+    vpx_free(cpi->mb_norm_activity_map);
+    CHECK_MEM_ERROR(cpi->mb_norm_activity_map,
+                    vpx_calloc(sizeof(unsigned int),
+                    cm->mb_rows * cm->mb_cols));
+
+#if CONFIG_MULTITHREAD
+    if (width < 640)
+        cpi->mt_sync_range = 1;
+    else if (width <= 1280)
+        cpi->mt_sync_range = 4;
+    else if (width <= 2560)
+        cpi->mt_sync_range = 8;
+    else
+        cpi->mt_sync_range = 16;
+#endif
+
+    vpx_free(cpi->tplist);
+
+    CHECK_MEM_ERROR(cpi->tplist, vpx_malloc(sizeof(TOKENLIST) * cpi->common.mb_rows));
+}
+
+
+// Quant MOD
+static const int q_trans[] =
+{
+    0,   1,  2,  3,  4,  5,  7,  8,
+    9,  10, 12, 13, 15, 17, 18, 19,
+    20,  21, 23, 24, 25, 26, 27, 28,
+    29,  30, 31, 33, 35, 37, 39, 41,
+    43,  45, 47, 49, 51, 53, 55, 57,
+    59,  61, 64, 67, 70, 73, 76, 79,
+    82,  85, 88, 91, 94, 97, 100, 103,
+    106, 109, 112, 115, 118, 121, 124, 127,
+};
+
+int vp8_reverse_trans(int x)
+{
+    int i;
+
+    for (i = 0; i < 64; i++)
+        if (q_trans[i] >= x)
+            return i;
+
+    return 63;
+};
+void vp8_new_frame_rate(VP8_COMP *cpi, double framerate)
+{
+    if(framerate < .1)
+        framerate = 30;
+
+    cpi->frame_rate             = framerate;
+    cpi->output_frame_rate      = framerate;
+    cpi->per_frame_bandwidth    = (int)(cpi->oxcf.target_bandwidth /
+                                  cpi->output_frame_rate);
+    cpi->av_per_frame_bandwidth = cpi->per_frame_bandwidth;
+    cpi->min_frame_bandwidth    = (int)(cpi->av_per_frame_bandwidth *
+                                  cpi->oxcf.two_pass_vbrmin_section / 100);
+
+    // Set Maximum gf/arf interval
+    cpi->max_gf_interval = ((int)(cpi->output_frame_rate / 2.0) + 2);
+
+    if(cpi->max_gf_interval < 12)
+        cpi->max_gf_interval = 12;
+
+    // Extended interval for genuinely static scenes
+    cpi->twopass.static_scene_max_gf_interval = cpi->key_frame_frequency >> 1;
+
+     // Special conditions when altr ref frame enabled in lagged compress mode
+    if (cpi->oxcf.play_alternate && cpi->oxcf.lag_in_frames)
+    {
+        if (cpi->max_gf_interval > cpi->oxcf.lag_in_frames - 1)
+            cpi->max_gf_interval = cpi->oxcf.lag_in_frames - 1;
+
+        if (cpi->twopass.static_scene_max_gf_interval > cpi->oxcf.lag_in_frames - 1)
+            cpi->twopass.static_scene_max_gf_interval = cpi->oxcf.lag_in_frames - 1;
+    }
+
+    if ( cpi->max_gf_interval > cpi->twopass.static_scene_max_gf_interval )
+        cpi->max_gf_interval = cpi->twopass.static_scene_max_gf_interval;
+}
+
+
+static int
+rescale(int val, int num, int denom)
+{
+    int64_t llnum = num;
+    int64_t llden = denom;
+    int64_t llval = val;
+
+    return llval * llnum / llden;
+}
+
+
+static void init_config(VP8_COMP *cpi, VP8_CONFIG *oxcf)
+{
+    VP8_COMMON *cm = &cpi->common;
+
+    cpi->oxcf = *oxcf;
+
+    cpi->auto_gold = 1;
+    cpi->auto_adjust_gold_quantizer = 1;
+    cpi->goldfreq = 7;
+
+    cm->version = oxcf->Version;
+    vp8_setup_version(cm);
+
+    /* frame rate is not available on the first frame, as it's derived from
+     * the observed timestamps. The actual value used here doesn't matter
+     * too much, as it will adapt quickly. If the reciprocal of the timebase
+     * seems like a reasonable framerate, then use that as a guess, otherwise
+     * use 30.
+     */
+    cpi->frame_rate = (double)(oxcf->timebase.den) /
+                      (double)(oxcf->timebase.num);
+
+    if (cpi->frame_rate > 180)
+        cpi->frame_rate = 30;
+
+    cpi->ref_frame_rate = cpi->frame_rate;
+
+    // change includes all joint functionality
+    vp8_change_config(cpi, oxcf);
+
+    // Initialize active best and worst q and average q values.
+    cpi->active_worst_quality         = cpi->oxcf.worst_allowed_q;
+    cpi->active_best_quality          = cpi->oxcf.best_allowed_q;
+    cpi->avg_frame_qindex             = cpi->oxcf.worst_allowed_q;
+
+    // Initialise the starting buffer levels
+    cpi->buffer_level                 = cpi->oxcf.starting_buffer_level;
+    cpi->bits_off_target              = cpi->oxcf.starting_buffer_level;
+
+    cpi->rolling_target_bits          = cpi->av_per_frame_bandwidth;
+    cpi->rolling_actual_bits          = cpi->av_per_frame_bandwidth;
+    cpi->long_rolling_target_bits     = cpi->av_per_frame_bandwidth;
+    cpi->long_rolling_actual_bits     = cpi->av_per_frame_bandwidth;
+
+    cpi->total_actual_bits            = 0;
+    cpi->total_target_vs_actual       = 0;
+
+    // Temporal scalabilty
+    if (cpi->oxcf.number_of_layers > 1)
+    {
+        unsigned int i;
+        double prev_layer_frame_rate=0;
+
+        for (i=0; i<cpi->oxcf.number_of_layers; i++)
+        {
+            LAYER_CONTEXT *lc = &cpi->layer_context[i];
+
+            // Layer configuration
+            lc->frame_rate =
+                        cpi->output_frame_rate / cpi->oxcf.rate_decimator[i];
+            lc->target_bandwidth = cpi->oxcf.target_bitrate[i] * 1000;
+
+            lc->starting_buffer_level_in_ms = oxcf->starting_buffer_level;
+            lc->optimal_buffer_level_in_ms  = oxcf->optimal_buffer_level;
+            lc->maximum_buffer_size_in_ms   = oxcf->maximum_buffer_size;
+
+            lc->starting_buffer_level =
+              rescale(oxcf->starting_buffer_level,
+                          lc->target_bandwidth, 1000);
+
+            if (oxcf->optimal_buffer_level == 0)
+                lc->optimal_buffer_level = lc->target_bandwidth / 8;
+            else
+                lc->optimal_buffer_level =
+                  rescale(oxcf->optimal_buffer_level,
+                          lc->target_bandwidth, 1000);
+
+            if (oxcf->maximum_buffer_size == 0)
+                lc->maximum_buffer_size = lc->target_bandwidth / 8;
+            else
+                lc->maximum_buffer_size =
+                  rescale(oxcf->maximum_buffer_size,
+                          lc->target_bandwidth, 1000);
+
+            // Work out the average size of a frame within this layer
+            if (i > 0)
+                lc->avg_frame_size_for_layer = (cpi->oxcf.target_bitrate[i] -
+                    cpi->oxcf.target_bitrate[i-1]) * 1000 /
+                    (lc->frame_rate - prev_layer_frame_rate);
+
+            lc->active_worst_quality         = cpi->oxcf.worst_allowed_q;
+            lc->active_best_quality          = cpi->oxcf.best_allowed_q;
+            lc->avg_frame_qindex             = cpi->oxcf.worst_allowed_q;
+
+            lc->buffer_level                 = lc->starting_buffer_level;
+            lc->bits_off_target              = lc->starting_buffer_level;
+
+            lc->total_actual_bits                 = 0;
+            lc->ni_av_qi                          = 0;
+            lc->ni_tot_qi                         = 0;
+            lc->ni_frames                         = 0;
+            lc->rate_correction_factor            = 1.0;
+            lc->key_frame_rate_correction_factor  = 1.0;
+            lc->gf_rate_correction_factor         = 1.0;
+            lc->inter_frame_target                = 0.0;
+
+            prev_layer_frame_rate = lc->frame_rate;
+        }
+    }
+
+#if VP8_TEMPORAL_ALT_REF
+    {
+        int i;
+
+        cpi->fixed_divide[0] = 0;
+
+        for (i = 1; i < 512; i++)
+            cpi->fixed_divide[i] = 0x80000 / i;
+    }
+#endif
+}
+
+static void update_layer_contexts (VP8_COMP *cpi)
+{
+    VP8_CONFIG *oxcf = &cpi->oxcf;
+
+    /* Update snapshots of the layer contexts to reflect new parameters */
+    if (oxcf->number_of_layers > 1)
+    {
+        unsigned int i;
+        double prev_layer_frame_rate=0;
+
+        for (i=0; i<oxcf->number_of_layers; i++)
+        {
+            LAYER_CONTEXT *lc = &cpi->layer_context[i];
+
+            lc->frame_rate =
+                cpi->ref_frame_rate / oxcf->rate_decimator[i];
+            lc->target_bandwidth = oxcf->target_bitrate[i] * 1000;
+
+            lc->starting_buffer_level = rescale(
+                          oxcf->starting_buffer_level_in_ms,
+                          lc->target_bandwidth, 1000);
+
+            if (oxcf->optimal_buffer_level == 0)
+                lc->optimal_buffer_level = lc->target_bandwidth / 8;
+            else
+                lc->optimal_buffer_level = rescale(
+                          oxcf->optimal_buffer_level_in_ms,
+                          lc->target_bandwidth, 1000);
+
+            if (oxcf->maximum_buffer_size == 0)
+                lc->maximum_buffer_size = lc->target_bandwidth / 8;
+            else
+                lc->maximum_buffer_size = rescale(
+                          oxcf->maximum_buffer_size_in_ms,
+                          lc->target_bandwidth, 1000);
+
+            // Work out the average size of a frame within this layer
+            if (i > 0)
+                lc->avg_frame_size_for_layer = (oxcf->target_bitrate[i] -
+                    oxcf->target_bitrate[i-1]) * 1000 /
+                    (lc->frame_rate - prev_layer_frame_rate);
+
+            lc->active_worst_quality         = oxcf->worst_allowed_q;
+            lc->active_best_quality          = oxcf->best_allowed_q;
+            lc->avg_frame_qindex             = oxcf->worst_allowed_q;
+
+            prev_layer_frame_rate = lc->frame_rate;
+        }
+    }
+}
+
+void vp8_change_config(VP8_COMP *cpi, VP8_CONFIG *oxcf)
+{
+    VP8_COMMON *cm = &cpi->common;
+    int last_w, last_h;
+
+    if (!cpi)
+        return;
+
+    if (!oxcf)
+        return;
+
+#if CONFIG_MULTITHREAD
+    /*  wait for the last picture loopfilter thread done */
+    if (cpi->b_lpf_running)
+    {
+        sem_wait(&cpi->h_event_end_lpf);
+        cpi->b_lpf_running = 0;
+    }
+#endif
+
+    if (cm->version != oxcf->Version)
+    {
+        cm->version = oxcf->Version;
+        vp8_setup_version(cm);
+    }
+
+    last_w = cpi->oxcf.Width;
+    last_h = cpi->oxcf.Height;
+
+    cpi->oxcf = *oxcf;
+
+    switch (cpi->oxcf.Mode)
+    {
+
+    case MODE_REALTIME:
+        cpi->pass = 0;
+        cpi->compressor_speed = 2;
+
+        if (cpi->oxcf.cpu_used < -16)
+        {
+            cpi->oxcf.cpu_used = -16;
+        }
+
+        if (cpi->oxcf.cpu_used > 16)
+            cpi->oxcf.cpu_used = 16;
+
+        break;
+
+    case MODE_GOODQUALITY:
+        cpi->pass = 0;
+        cpi->compressor_speed = 1;
+
+        if (cpi->oxcf.cpu_used < -5)
+        {
+            cpi->oxcf.cpu_used = -5;
+        }
+
+        if (cpi->oxcf.cpu_used > 5)
+            cpi->oxcf.cpu_used = 5;
+
+        break;
+
+    case MODE_BESTQUALITY:
+        cpi->pass = 0;
+        cpi->compressor_speed = 0;
+        break;
+
+    case MODE_FIRSTPASS:
+        cpi->pass = 1;
+        cpi->compressor_speed = 1;
+        break;
+    case MODE_SECONDPASS:
+        cpi->pass = 2;
+        cpi->compressor_speed = 1;
+
+        if (cpi->oxcf.cpu_used < -5)
+        {
+            cpi->oxcf.cpu_used = -5;
+        }
+
+        if (cpi->oxcf.cpu_used > 5)
+            cpi->oxcf.cpu_used = 5;
+
+        break;
+    case MODE_SECONDPASS_BEST:
+        cpi->pass = 2;
+        cpi->compressor_speed = 0;
+        break;
+    }
+
+    if (cpi->pass == 0)
+        cpi->auto_worst_q = 1;
+
+    cpi->oxcf.worst_allowed_q = q_trans[oxcf->worst_allowed_q];
+    cpi->oxcf.best_allowed_q = q_trans[oxcf->best_allowed_q];
+    cpi->oxcf.cq_level = q_trans[cpi->oxcf.cq_level];
+
+    if (oxcf->fixed_q >= 0)
+    {
+        if (oxcf->worst_allowed_q < 0)
+            cpi->oxcf.fixed_q = q_trans[0];
+        else
+            cpi->oxcf.fixed_q = q_trans[oxcf->worst_allowed_q];
+
+        if (oxcf->alt_q < 0)
+            cpi->oxcf.alt_q = q_trans[0];
+        else
+            cpi->oxcf.alt_q = q_trans[oxcf->alt_q];
+
+        if (oxcf->key_q < 0)
+            cpi->oxcf.key_q = q_trans[0];
+        else
+            cpi->oxcf.key_q = q_trans[oxcf->key_q];
+
+        if (oxcf->gold_q < 0)
+            cpi->oxcf.gold_q = q_trans[0];
+        else
+            cpi->oxcf.gold_q = q_trans[oxcf->gold_q];
+
+    }
+
+    cpi->baseline_gf_interval =
+        cpi->oxcf.alt_freq ? cpi->oxcf.alt_freq : DEFAULT_GF_INTERVAL;
+
+    cpi->ref_frame_flags = VP8_ALT_FLAG | VP8_GOLD_FLAG | VP8_LAST_FLAG;
+
+    //cpi->use_golden_frame_only = 0;
+    //cpi->use_last_frame_only = 0;
+    cm->refresh_golden_frame = 0;
+    cm->refresh_last_frame = 1;
+    cm->refresh_entropy_probs = 1;
+
+#if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)
+    cpi->oxcf.token_partitions = 3;
+#endif
+
+    if (cpi->oxcf.token_partitions >= 0 && cpi->oxcf.token_partitions <= 3)
+        cm->multi_token_partition =
+            (TOKEN_PARTITION) cpi->oxcf.token_partitions;
+
+    setup_features(cpi);
+
+    {
+        int i;
+
+        for (i = 0; i < MAX_MB_SEGMENTS; i++)
+            cpi->segment_encode_breakout[i] = cpi->oxcf.encode_breakout;
+    }
+
+    // At the moment the first order values may not be > MAXQ
+    if (cpi->oxcf.fixed_q > MAXQ)
+        cpi->oxcf.fixed_q = MAXQ;
+
+    // local file playback mode == really big buffer
+    if (cpi->oxcf.end_usage == USAGE_LOCAL_FILE_PLAYBACK)
+    {
+        cpi->oxcf.starting_buffer_level       = 60000;
+        cpi->oxcf.optimal_buffer_level        = 60000;
+        cpi->oxcf.maximum_buffer_size         = 240000;
+        cpi->oxcf.starting_buffer_level_in_ms = 60000;
+        cpi->oxcf.optimal_buffer_level_in_ms  = 60000;
+        cpi->oxcf.maximum_buffer_size_in_ms   = 240000;
+    }
+
+    // Convert target bandwidth from Kbit/s to Bit/s
+    cpi->oxcf.target_bandwidth       *= 1000;
+
+    cpi->oxcf.starting_buffer_level =
+        rescale(cpi->oxcf.starting_buffer_level,
+                cpi->oxcf.target_bandwidth, 1000);
+
+    // Set or reset optimal and maximum buffer levels.
+    if (cpi->oxcf.optimal_buffer_level == 0)
+        cpi->oxcf.optimal_buffer_level = cpi->oxcf.target_bandwidth / 8;
+    else
+        cpi->oxcf.optimal_buffer_level =
+            rescale(cpi->oxcf.optimal_buffer_level,
+                    cpi->oxcf.target_bandwidth, 1000);
+
+    if (cpi->oxcf.maximum_buffer_size == 0)
+        cpi->oxcf.maximum_buffer_size = cpi->oxcf.target_bandwidth / 8;
+    else
+        cpi->oxcf.maximum_buffer_size =
+            rescale(cpi->oxcf.maximum_buffer_size,
+                    cpi->oxcf.target_bandwidth, 1000);
+
+    // Set up frame rate and related parameters rate control values.
+    vp8_new_frame_rate(cpi, cpi->frame_rate);
+
+    // Set absolute upper and lower quality limits
+    cpi->worst_quality               = cpi->oxcf.worst_allowed_q;
+    cpi->best_quality                = cpi->oxcf.best_allowed_q;
+
+    // active values should only be modified if out of new range
+    if (cpi->active_worst_quality > cpi->oxcf.worst_allowed_q)
+    {
+      cpi->active_worst_quality = cpi->oxcf.worst_allowed_q;
+    }
+    // less likely
+    else if (cpi->active_worst_quality < cpi->oxcf.best_allowed_q)
+    {
+      cpi->active_worst_quality = cpi->oxcf.best_allowed_q;
+    }
+    if (cpi->active_best_quality < cpi->oxcf.best_allowed_q)
+    {
+      cpi->active_best_quality = cpi->oxcf.best_allowed_q;
+    }
+    // less likely
+    else if (cpi->active_best_quality > cpi->oxcf.worst_allowed_q)
+    {
+      cpi->active_best_quality = cpi->oxcf.worst_allowed_q;
+    }
+
+    cpi->buffered_mode = cpi->oxcf.optimal_buffer_level > 0;
+
+    cpi->cq_target_quality = cpi->oxcf.cq_level;
+
+    // Only allow dropped frames in buffered mode
+    cpi->drop_frames_allowed = cpi->oxcf.allow_df && cpi->buffered_mode;
+
+    if (!cm->use_bilinear_mc_filter)
+        cm->mcomp_filter_type = SIXTAP;
+    else
+        cm->mcomp_filter_type = BILINEAR;
+
+    cpi->target_bandwidth = cpi->oxcf.target_bandwidth;
+
+
+    cm->Width       = cpi->oxcf.Width;
+    cm->Height      = cpi->oxcf.Height;
+
+    /* TODO(jkoleszar): if an internal spatial resampling is active,
+     * and we downsize the input image, maybe we should clear the
+     * internal scale immediately rather than waiting for it to
+     * correct.
+     */
+
+    // VP8 sharpness level mapping 0-7 (vs 0-10 in general VPx dialogs)
+    if (cpi->oxcf.Sharpness > 7)
+        cpi->oxcf.Sharpness = 7;
+
+    cm->sharpness_level = cpi->oxcf.Sharpness;
+
+    if (cm->horiz_scale != NORMAL || cm->vert_scale != NORMAL)
+    {
+        int UNINITIALIZED_IS_SAFE(hr), UNINITIALIZED_IS_SAFE(hs);
+        int UNINITIALIZED_IS_SAFE(vr), UNINITIALIZED_IS_SAFE(vs);
+
+        Scale2Ratio(cm->horiz_scale, &hr, &hs);
+        Scale2Ratio(cm->vert_scale, &vr, &vs);
+
+        // always go to the next whole number
+        cm->Width = (hs - 1 + cpi->oxcf.Width * hr) / hs;
+        cm->Height = (vs - 1 + cpi->oxcf.Height * vr) / vs;
+    }
+
+    if (last_w != cpi->oxcf.Width || last_h != cpi->oxcf.Height)
+        cpi->force_next_frame_intra = 1;
+
+    if (((cm->Width + 15) & 0xfffffff0) !=
+          cm->yv12_fb[cm->lst_fb_idx].y_width ||
+        ((cm->Height + 15) & 0xfffffff0) !=
+          cm->yv12_fb[cm->lst_fb_idx].y_height ||
+        cm->yv12_fb[cm->lst_fb_idx].y_width == 0)
+    {
+        alloc_raw_frame_buffers(cpi);
+        vp8_alloc_compressor_data(cpi);
+    }
+
+    if (cpi->oxcf.fixed_q >= 0)
+    {
+        cpi->last_q[0] = cpi->oxcf.fixed_q;
+        cpi->last_q[1] = cpi->oxcf.fixed_q;
+    }
+
+    cpi->Speed = cpi->oxcf.cpu_used;
+
+    // force to allowlag to 0 if lag_in_frames is 0;
+    if (cpi->oxcf.lag_in_frames == 0)
+    {
+        cpi->oxcf.allow_lag = 0;
+    }
+    // Limit on lag buffers as these are not currently dynamically allocated
+    else if (cpi->oxcf.lag_in_frames > MAX_LAG_BUFFERS)
+        cpi->oxcf.lag_in_frames = MAX_LAG_BUFFERS;
+
+    // YX Temp
+    cpi->alt_ref_source = NULL;
+    cpi->is_src_frame_alt_ref = 0;
+
+#if CONFIG_TEMPORAL_DENOISING
+    if (cpi->oxcf.noise_sensitivity)
+    {
+      if (!cpi->denoiser.yv12_mc_running_avg.buffer_alloc)
+      {
+        int width = (cpi->oxcf.Width + 15) & ~15;
+        int height = (cpi->oxcf.Height + 15) & ~15;
+        vp8_denoiser_allocate(&cpi->denoiser, width, height);
+      }
+    }
+#endif
+
+#if 0
+    // Experimental RD Code
+    cpi->frame_distortion = 0;
+    cpi->last_frame_distortion = 0;
+#endif
+
+}
+
+#define M_LOG2_E 0.693147180559945309417
+#define log2f(x) (log (x) / (float) M_LOG2_E)
+static void cal_mvsadcosts(int *mvsadcost[2])
+{
+    int i = 1;
+
+    mvsadcost [0] [0] = 300;
+    mvsadcost [1] [0] = 300;
+
+    do
+    {
+        double z = 256 * (2 * (log2f(8 * i) + .6));
+        mvsadcost [0][i] = (int) z;
+        mvsadcost [1][i] = (int) z;
+        mvsadcost [0][-i] = (int) z;
+        mvsadcost [1][-i] = (int) z;
+    }
+    while (++i <= mvfp_max);
+}
+
+struct VP8_COMP* vp8_create_compressor(VP8_CONFIG *oxcf)
+{
+    int i;
+
+    VP8_COMP *cpi;
+    VP8_COMMON *cm;
+
+    cpi = vpx_memalign(32, sizeof(VP8_COMP));
+    // Check that the CPI instance is valid
+    if (!cpi)
+        return 0;
+
+    cm = &cpi->common;
+
+    vpx_memset(cpi, 0, sizeof(VP8_COMP));
+
+    if (setjmp(cm->error.jmp))
+    {
+        cpi->common.error.setjmp = 0;
+        vp8_remove_compressor(&cpi);
+        return 0;
+    }
+
+    cpi->common.error.setjmp = 1;
+
+    CHECK_MEM_ERROR(cpi->mb.ss, vpx_calloc(sizeof(search_site), (MAX_MVSEARCH_STEPS * 8) + 1));
+
+    vp8_create_common(&cpi->common);
+
+    init_config(cpi, oxcf);
+
+    memcpy(cpi->base_skip_false_prob, vp8cx_base_skip_false_prob, sizeof(vp8cx_base_skip_false_prob));
+    cpi->common.current_video_frame   = 0;
+    cpi->kf_overspend_bits            = 0;
+    cpi->kf_bitrate_adjustment        = 0;
+    cpi->frames_till_gf_update_due      = 0;
+    cpi->gf_overspend_bits            = 0;
+    cpi->non_gf_bitrate_adjustment     = 0;
+    cpi->prob_last_coded              = 128;
+    cpi->prob_gf_coded                = 128;
+    cpi->prob_intra_coded             = 63;
+
+    // Prime the recent reference frame usage counters.
+    // Hereafter they will be maintained as a sort of moving average
+    cpi->recent_ref_frame_usage[INTRA_FRAME]  = 1;
+    cpi->recent_ref_frame_usage[LAST_FRAME]   = 1;
+    cpi->recent_ref_frame_usage[GOLDEN_FRAME] = 1;
+    cpi->recent_ref_frame_usage[ALTREF_FRAME] = 1;
+
+    // Set reference frame sign bias for ALTREF frame to 1 (for now)
+    cpi->common.ref_frame_sign_bias[ALTREF_FRAME] = 1;
+
+    cpi->twopass.gf_decay_rate = 0;
+    cpi->baseline_gf_interval = DEFAULT_GF_INTERVAL;
+
+    cpi->gold_is_last = 0 ;
+    cpi->alt_is_last  = 0 ;
+    cpi->gold_is_alt  = 0 ;
+
+    // allocate memory for storing last frame's MVs for MV prediction.
+    CHECK_MEM_ERROR(cpi->lfmv, vpx_calloc((cpi->common.mb_rows+2) * (cpi->common.mb_cols+2), sizeof(int_mv)));
+    CHECK_MEM_ERROR(cpi->lf_ref_frame_sign_bias, vpx_calloc((cpi->common.mb_rows+2) * (cpi->common.mb_cols+2), sizeof(int)));
+    CHECK_MEM_ERROR(cpi->lf_ref_frame, vpx_calloc((cpi->common.mb_rows+2) * (cpi->common.mb_cols+2), sizeof(int)));
+
+    // Create the encoder segmentation map and set all entries to 0
+    CHECK_MEM_ERROR(cpi->segmentation_map, vpx_calloc(cpi->common.mb_rows * cpi->common.mb_cols, 1));
+    CHECK_MEM_ERROR(cpi->active_map, vpx_calloc(cpi->common.mb_rows * cpi->common.mb_cols, 1));
+    vpx_memset(cpi->active_map , 1, (cpi->common.mb_rows * cpi->common.mb_cols));
+    cpi->active_map_enabled = 0;
+
+#if 0
+    // Experimental code for lagged and one pass
+    // Initialise one_pass GF frames stats
+    // Update stats used for GF selection
+    if (cpi->pass == 0)
+    {
+        cpi->one_pass_frame_index = 0;
+
+        for (i = 0; i < MAX_LAG_BUFFERS; i++)
+        {
+            cpi->one_pass_frame_stats[i].frames_so_far = 0;
+            cpi->one_pass_frame_stats[i].frame_intra_error = 0.0;
+            cpi->one_pass_frame_stats[i].frame_coded_error = 0.0;
+            cpi->one_pass_frame_stats[i].frame_pcnt_inter = 0.0;
+            cpi->one_pass_frame_stats[i].frame_pcnt_motion = 0.0;
+            cpi->one_pass_frame_stats[i].frame_mvr = 0.0;
+            cpi->one_pass_frame_stats[i].frame_mvr_abs = 0.0;
+            cpi->one_pass_frame_stats[i].frame_mvc = 0.0;
+            cpi->one_pass_frame_stats[i].frame_mvc_abs = 0.0;
+        }
+    }
+#endif
+
+    // Should we use the cyclic refresh method.
+    // Currently this is tied to error resilliant mode
+    cpi->cyclic_refresh_mode_enabled = cpi->oxcf.error_resilient_mode;
+    cpi->cyclic_refresh_mode_max_mbs_perframe = (cpi->common.mb_rows * cpi->common.mb_cols) / 40;
+    cpi->cyclic_refresh_mode_index = 0;
+    cpi->cyclic_refresh_q = 32;
+
+    if (cpi->cyclic_refresh_mode_enabled)
+    {
+        CHECK_MEM_ERROR(cpi->cyclic_refresh_map, vpx_calloc((cpi->common.mb_rows * cpi->common.mb_cols), 1));
+    }
+    else
+        cpi->cyclic_refresh_map = (signed char *) NULL;
+
+    // Test function for segmentation
+    //segmentation_test_function( cpi);
+
+#ifdef ENTROPY_STATS
+    init_context_counters();
+#endif
+
+    /*Initialize the feed-forward activity masking.*/
+    cpi->activity_avg = 90<<12;
+
+    cpi->frames_since_key = 8;        // Give a sensible default for the first frame.
+    cpi->key_frame_frequency = cpi->oxcf.key_freq;
+    cpi->this_key_frame_forced = 0;
+    cpi->next_key_frame_forced = 0;
+
+    cpi->source_alt_ref_pending = 0;
+    cpi->source_alt_ref_active = 0;
+    cpi->common.refresh_alt_ref_frame = 0;
+
+    cpi->b_calculate_psnr = CONFIG_INTERNAL_STATS;
+#if CONFIG_INTERNAL_STATS
+    cpi->b_calculate_ssimg = 0;
+
+    cpi->count = 0;
+    cpi->bytes = 0;
+
+    if (cpi->b_calculate_psnr)
+    {
+        cpi->total_sq_error = 0.0;
+        cpi->total_sq_error2 = 0.0;
+        cpi->total_y = 0.0;
+        cpi->total_u = 0.0;
+        cpi->total_v = 0.0;
+        cpi->total = 0.0;
+        cpi->totalp_y = 0.0;
+        cpi->totalp_u = 0.0;
+        cpi->totalp_v = 0.0;
+        cpi->totalp = 0.0;
+        cpi->tot_recode_hits = 0;
+        cpi->summed_quality = 0;
+        cpi->summed_weights = 0;
+    }
+
+    if (cpi->b_calculate_ssimg)
+    {
+        cpi->total_ssimg_y = 0;
+        cpi->total_ssimg_u = 0;
+        cpi->total_ssimg_v = 0;
+        cpi->total_ssimg_all = 0;
+    }
+
+#endif
+
+#ifndef LLONG_MAX
+#define LLONG_MAX  9223372036854775807LL
+#endif
+    cpi->first_time_stamp_ever = LLONG_MAX;
+
+    cpi->frames_till_gf_update_due      = 0;
+    cpi->key_frame_count              = 1;
+
+    cpi->ni_av_qi                     = cpi->oxcf.worst_allowed_q;
+    cpi->ni_tot_qi                    = 0;
+    cpi->ni_frames                   = 0;
+    cpi->total_byte_count             = 0;
+
+    cpi->drop_frame                  = 0;
+    cpi->drop_count                  = 0;
+    cpi->max_drop_count               = 0;
+    cpi->max_consec_dropped_frames     = 4;
+
+    cpi->rate_correction_factor         = 1.0;
+    cpi->key_frame_rate_correction_factor = 1.0;
+    cpi->gf_rate_correction_factor  = 1.0;
+    cpi->twopass.est_max_qcorrection_factor  = 1.0;
+
+    cpi->mb.mvcost[0] = &cpi->mb.mvcosts[0][mv_max+1];
+    cpi->mb.mvcost[1] = &cpi->mb.mvcosts[1][mv_max+1];
+    cpi->mb.mvsadcost[0] = &cpi->mb.mvsadcosts[0][mvfp_max+1];
+    cpi->mb.mvsadcost[1] = &cpi->mb.mvsadcosts[1][mvfp_max+1];
+
+    cal_mvsadcosts(cpi->mb.mvsadcost);
+
+    for (i = 0; i < KEY_FRAME_CONTEXT; i++)
+    {
+        cpi->prior_key_frame_distance[i] = (int)cpi->output_frame_rate;
+    }
+
+#ifdef OUTPUT_YUV_SRC
+    yuv_file = fopen("bd.yuv", "ab");
+#endif
+
+#if 0
+    framepsnr = fopen("framepsnr.stt", "a");
+    kf_list = fopen("kf_list.stt", "w");
+#endif
+
+    cpi->output_pkt_list = oxcf->output_pkt_list;
+
+#if !(CONFIG_REALTIME_ONLY)
+
+    if (cpi->pass == 1)
+    {
+        vp8_init_first_pass(cpi);
+    }
+    else if (cpi->pass == 2)
+    {
+        size_t packet_sz = sizeof(FIRSTPASS_STATS);
+        int packets = oxcf->two_pass_stats_in.sz / packet_sz;
+
+        cpi->twopass.stats_in_start = oxcf->two_pass_stats_in.buf;
+        cpi->twopass.stats_in = cpi->twopass.stats_in_start;
+        cpi->twopass.stats_in_end = (void*)((char *)cpi->twopass.stats_in
+                            + (packets - 1) * packet_sz);
+        vp8_init_second_pass(cpi);
+    }
+
+#endif
+
+    if (cpi->compressor_speed == 2)
+    {
+        cpi->cpu_freq            = 0; //vp8_get_processor_freq();
+        cpi->avg_encode_time      = 0;
+        cpi->avg_pick_mode_time    = 0;
+    }
+
+    vp8_set_speed_features(cpi);
+
+    // Set starting values of RD threshold multipliers (128 = *1)
+    for (i = 0; i < MAX_MODES; i++)
+    {
+        cpi->rd_thresh_mult[i] = 128;
+    }
+
+#ifdef ENTROPY_STATS
+    init_mv_ref_counts();
+#endif
+
+#if CONFIG_MULTITHREAD
+    vp8cx_create_encoder_threads(cpi);
+#endif
+
+    cpi->fn_ptr[BLOCK_16X16].sdf            = vp8_sad16x16;
+    cpi->fn_ptr[BLOCK_16X16].vf             = vp8_variance16x16;
+    cpi->fn_ptr[BLOCK_16X16].svf            = vp8_sub_pixel_variance16x16;
+    cpi->fn_ptr[BLOCK_16X16].svf_halfpix_h  = vp8_variance_halfpixvar16x16_h;
+    cpi->fn_ptr[BLOCK_16X16].svf_halfpix_v  = vp8_variance_halfpixvar16x16_v;
+    cpi->fn_ptr[BLOCK_16X16].svf_halfpix_hv = vp8_variance_halfpixvar16x16_hv;
+    cpi->fn_ptr[BLOCK_16X16].sdx3f          = vp8_sad16x16x3;
+    cpi->fn_ptr[BLOCK_16X16].sdx8f          = vp8_sad16x16x8;
+    cpi->fn_ptr[BLOCK_16X16].sdx4df         = vp8_sad16x16x4d;
+
+    cpi->fn_ptr[BLOCK_16X8].sdf            = vp8_sad16x8;
+    cpi->fn_ptr[BLOCK_16X8].vf             = vp8_variance16x8;
+    cpi->fn_ptr[BLOCK_16X8].svf            = vp8_sub_pixel_variance16x8;
+    cpi->fn_ptr[BLOCK_16X8].svf_halfpix_h  = NULL;
+    cpi->fn_ptr[BLOCK_16X8].svf_halfpix_v  = NULL;
+    cpi->fn_ptr[BLOCK_16X8].svf_halfpix_hv = NULL;
+    cpi->fn_ptr[BLOCK_16X8].sdx3f          = vp8_sad16x8x3;
+    cpi->fn_ptr[BLOCK_16X8].sdx8f          = vp8_sad16x8x8;
+    cpi->fn_ptr[BLOCK_16X8].sdx4df         = vp8_sad16x8x4d;
+
+    cpi->fn_ptr[BLOCK_8X16].sdf            = vp8_sad8x16;
+    cpi->fn_ptr[BLOCK_8X16].vf             = vp8_variance8x16;
+    cpi->fn_ptr[BLOCK_8X16].svf            = vp8_sub_pixel_variance8x16;
+    cpi->fn_ptr[BLOCK_8X16].svf_halfpix_h  = NULL;
+    cpi->fn_ptr[BLOCK_8X16].svf_halfpix_v  = NULL;
+    cpi->fn_ptr[BLOCK_8X16].svf_halfpix_hv = NULL;
+    cpi->fn_ptr[BLOCK_8X16].sdx3f          = vp8_sad8x16x3;
+    cpi->fn_ptr[BLOCK_8X16].sdx8f          = vp8_sad8x16x8;
+    cpi->fn_ptr[BLOCK_8X16].sdx4df         = vp8_sad8x16x4d;
+
+    cpi->fn_ptr[BLOCK_8X8].sdf            = vp8_sad8x8;
+    cpi->fn_ptr[BLOCK_8X8].vf             = vp8_variance8x8;
+    cpi->fn_ptr[BLOCK_8X8].svf            = vp8_sub_pixel_variance8x8;
+    cpi->fn_ptr[BLOCK_8X8].svf_halfpix_h  = NULL;
+    cpi->fn_ptr[BLOCK_8X8].svf_halfpix_v  = NULL;
+    cpi->fn_ptr[BLOCK_8X8].svf_halfpix_hv = NULL;
+    cpi->fn_ptr[BLOCK_8X8].sdx3f          = vp8_sad8x8x3;
+    cpi->fn_ptr[BLOCK_8X8].sdx8f          = vp8_sad8x8x8;
+    cpi->fn_ptr[BLOCK_8X8].sdx4df         = vp8_sad8x8x4d;
+
+    cpi->fn_ptr[BLOCK_4X4].sdf            = vp8_sad4x4;
+    cpi->fn_ptr[BLOCK_4X4].vf             = vp8_variance4x4;
+    cpi->fn_ptr[BLOCK_4X4].svf            = vp8_sub_pixel_variance4x4;
+    cpi->fn_ptr[BLOCK_4X4].svf_halfpix_h  = NULL;
+    cpi->fn_ptr[BLOCK_4X4].svf_halfpix_v  = NULL;
+    cpi->fn_ptr[BLOCK_4X4].svf_halfpix_hv = NULL;
+    cpi->fn_ptr[BLOCK_4X4].sdx3f          = vp8_sad4x4x3;
+    cpi->fn_ptr[BLOCK_4X4].sdx8f          = vp8_sad4x4x8;
+    cpi->fn_ptr[BLOCK_4X4].sdx4df         = vp8_sad4x4x4d;
+
+#if ARCH_X86 || ARCH_X86_64
+    cpi->fn_ptr[BLOCK_16X16].copymem      = vp8_copy32xn;
+    cpi->fn_ptr[BLOCK_16X8].copymem       = vp8_copy32xn;
+    cpi->fn_ptr[BLOCK_8X16].copymem       = vp8_copy32xn;
+    cpi->fn_ptr[BLOCK_8X8].copymem        = vp8_copy32xn;
+    cpi->fn_ptr[BLOCK_4X4].copymem        = vp8_copy32xn;
+#endif
+
+    cpi->full_search_sad = vp8_full_search_sad;
+    cpi->diamond_search_sad = vp8_diamond_search_sad;
+    cpi->refining_search_sad = vp8_refining_search_sad;
+
+    // make sure frame 1 is okay
+    cpi->error_bins[0] = cpi->common.MBs;
+
+    //vp8cx_init_quantizer() is first called here. Add check in vp8cx_frame_init_quantizer() so that vp8cx_init_quantizer is only called later
+    //when needed. This will avoid unnecessary calls of vp8cx_init_quantizer() for every frame.
+    vp8cx_init_quantizer(cpi);
+
+    vp8_loop_filter_init(cm);
+
+    cpi->common.error.setjmp = 0;
+
+#if CONFIG_MULTI_RES_ENCODING
+    /* Calculate # of MBs in a row in lower-resolution level image. */
+    if (cpi->oxcf.mr_encoder_id > 0)
+        vp8_cal_low_res_mb_cols(cpi);
+#endif
+
+    return  cpi;
+
+}
+
+
+void vp8_remove_compressor(VP8_COMP **ptr)
+{
+    VP8_COMP *cpi = *ptr;
+
+    if (!cpi)
+        return;
+
+    if (cpi && (cpi->common.current_video_frame > 0))
+    {
+#if !(CONFIG_REALTIME_ONLY)
+
+        if (cpi->pass == 2)
+        {
+            vp8_end_second_pass(cpi);
+        }
+
+#endif
+
+#ifdef ENTROPY_STATS
+        print_context_counters();
+        print_tree_update_probs();
+        print_mode_context();
+#endif
+
+#if CONFIG_INTERNAL_STATS
+
+        if (cpi->pass != 1)
+        {
+            FILE *f = fopen("opsnr.stt", "a");
+            double time_encoded = (cpi->last_end_time_stamp_seen
+                                   - cpi->first_time_stamp_ever) / 10000000.000;
+            double total_encode_time = (cpi->time_receive_data +
+                                            cpi->time_compress_data) / 1000.000;
+            double dr = (double)cpi->bytes * 8.0 / 1000.0 / time_encoded;
+
+            if (cpi->b_calculate_psnr)
+            {
+                YV12_BUFFER_CONFIG *lst_yv12 =
+                              &cpi->common.yv12_fb[cpi->common.lst_fb_idx];
+
+                if (cpi->oxcf.number_of_layers > 1)
+                {
+                    int i;
+
+                    fprintf(f, "Layer\tBitrate\tAVGPsnr\tGLBPsnr\tAVPsnrP\t"
+                               "GLPsnrP\tVPXSSIM\t\n");
+                    for (i=0; i<cpi->oxcf.number_of_layers; i++)
+                    {
+                        double dr = (double)cpi->bytes_in_layer[i] *
+                                              8.0 / 1000.0  / time_encoded;
+                        double samples = 3.0 / 2 * cpi->frames_in_layer[i] *
+                                         lst_yv12->y_width * lst_yv12->y_height;
+                        double total_psnr = vp8_mse2psnr(samples, 255.0,
+                                                  cpi->total_error2[i]);
+                        double total_psnr2 = vp8_mse2psnr(samples, 255.0,
+                                                  cpi->total_error2_p[i]);
+                        double total_ssim = 100 * pow(cpi->sum_ssim[i] /
+                                                      cpi->sum_weights[i], 8.0);
+
+                        fprintf(f, "%5d\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t"
+                                   "%7.3f\t%7.3f\n",
+                                   i, dr,
+                                   cpi->sum_psnr[i] / cpi->frames_in_layer[i],
+                                   total_psnr,
+                                   cpi->sum_psnr_p[i] / cpi->frames_in_layer[i],
+                                   total_psnr2, total_ssim);
+                    }
+                }
+                else
+                {
+                    double samples = 3.0 / 2 * cpi->count *
+                                        lst_yv12->y_width * lst_yv12->y_height;
+                    double total_psnr = vp8_mse2psnr(samples, 255.0,
+                                                         cpi->total_sq_error);
+                    double total_psnr2 = vp8_mse2psnr(samples, 255.0,
+                                                         cpi->total_sq_error2);
+                    double total_ssim = 100 * pow(cpi->summed_quality /
+                                                      cpi->summed_weights, 8.0);
+
+                    fprintf(f, "Bitrate\tAVGPsnr\tGLBPsnr\tAVPsnrP\t"
+                               "GLPsnrP\tVPXSSIM\t  Time(us)\n");
+                    fprintf(f, "%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t"
+                               "%7.3f\t%8.0f\n",
+                               dr, cpi->total / cpi->count, total_psnr,
+                               cpi->totalp / cpi->count, total_psnr2,
+                               total_ssim, total_encode_time);
+                }
+            }
+
+            if (cpi->b_calculate_ssimg)
+            {
+                if (cpi->oxcf.number_of_layers > 1)
+                {
+                    int i;
+
+                    fprintf(f, "Layer\tBitRate\tSSIM_Y\tSSIM_U\tSSIM_V\tSSIM_A\t"
+                               "Time(us)\n");
+                    for (i=0; i<cpi->oxcf.number_of_layers; i++)
+                    {
+                        double dr = (double)cpi->bytes_in_layer[i] *
+                                    8.0 / 1000.0  / time_encoded;
+                        fprintf(f, "%5d\t%7.3f\t%6.4f\t"
+                                "%6.4f\t%6.4f\t%6.4f\t%8.0f\n",
+                                i, dr,
+                                cpi->total_ssimg_y_in_layer[i] /
+                                     cpi->frames_in_layer[i],
+                                cpi->total_ssimg_u_in_layer[i] /
+                                     cpi->frames_in_layer[i],
+                                cpi->total_ssimg_v_in_layer[i] /
+                                     cpi->frames_in_layer[i],
+                                cpi->total_ssimg_all_in_layer[i] /
+                                     cpi->frames_in_layer[i],
+                                total_encode_time);
+                    }
+                }
+                else
+                {
+                    fprintf(f, "BitRate\tSSIM_Y\tSSIM_U\tSSIM_V\tSSIM_A\t"
+                               "Time(us)\n");
+                    fprintf(f, "%7.3f\t%6.4f\t%6.4f\t%6.4f\t%6.4f\t%8.0f\n", dr,
+                            cpi->total_ssimg_y / cpi->count,
+                            cpi->total_ssimg_u / cpi->count,
+                            cpi->total_ssimg_v / cpi->count,
+                            cpi->total_ssimg_all / cpi->count, total_encode_time);
+                }
+            }
+
+            fclose(f);
+#if 0
+            f = fopen("qskip.stt", "a");
+            fprintf(f, "minq:%d -maxq:%d skiptrue:skipfalse = %d:%d\n", cpi->oxcf.best_allowed_q, cpi->oxcf.worst_allowed_q, skiptruecount, skipfalsecount);
+            fclose(f);
+#endif
+
+        }
+
+#endif
+
+
+#ifdef SPEEDSTATS
+
+        if (cpi->compressor_speed == 2)
+        {
+            int i;
+            FILE *f = fopen("cxspeed.stt", "a");
+            cnt_pm /= cpi->common.MBs;
+
+            for (i = 0; i < 16; i++)
+                fprintf(f, "%5d", frames_at_speed[i]);
+
+            fprintf(f, "\n");
+            //fprintf(f, "%10d PM %10d %10d %10d EF %10d %10d %10d\n", cpi->Speed, cpi->avg_pick_mode_time, (tot_pm/cnt_pm), cnt_pm,  cpi->avg_encode_time, 0, 0);
+            fclose(f);
+        }
+
+#endif
+
+
+#ifdef MODE_STATS
+        {
+            extern int count_mb_seg[4];
+            FILE *f = fopen("modes.stt", "a");
+            double dr = (double)cpi->frame_rate * (double)bytes * (double)8 / (double)count / (double)1000 ;
+            fprintf(f, "intra_mode in Intra Frames:\n");
+            fprintf(f, "Y: %8d, %8d, %8d, %8d, %8d\n", y_modes[0], y_modes[1], y_modes[2], y_modes[3], y_modes[4]);
+            fprintf(f, "UV:%8d, %8d, %8d, %8d\n", uv_modes[0], uv_modes[1], uv_modes[2], uv_modes[3]);
+            fprintf(f, "B: ");
+            {
+                int i;
+
+                for (i = 0; i < 10; i++)
+                    fprintf(f, "%8d, ", b_modes[i]);
+
+                fprintf(f, "\n");
+
+            }
+
+            fprintf(f, "Modes in Inter Frames:\n");
+            fprintf(f, "Y: %8d, %8d, %8d, %8d, %8d, %8d, %8d, %8d, %8d, %8d\n",
+                    inter_y_modes[0], inter_y_modes[1], inter_y_modes[2], inter_y_modes[3], inter_y_modes[4],
+                    inter_y_modes[5], inter_y_modes[6], inter_y_modes[7], inter_y_modes[8], inter_y_modes[9]);
+            fprintf(f, "UV:%8d, %8d, %8d, %8d\n", inter_uv_modes[0], inter_uv_modes[1], inter_uv_modes[2], inter_uv_modes[3]);
+            fprintf(f, "B: ");
+            {
+                int i;
+
+                for (i = 0; i < 15; i++)
+                    fprintf(f, "%8d, ", inter_b_modes[i]);
+
+                fprintf(f, "\n");
+
+            }
+            fprintf(f, "P:%8d, %8d, %8d, %8d\n", count_mb_seg[0], count_mb_seg[1], count_mb_seg[2], count_mb_seg[3]);
+            fprintf(f, "PB:%8d, %8d, %8d, %8d\n", inter_b_modes[LEFT4X4], inter_b_modes[ABOVE4X4], inter_b_modes[ZERO4X4], inter_b_modes[NEW4X4]);
+
+
+
+            fclose(f);
+        }
+#endif
+
+#ifdef ENTROPY_STATS
+        {
+            int i, j, k;
+            FILE *fmode = fopen("modecontext.c", "w");
+
+            fprintf(fmode, "\n#include \"entropymode.h\"\n\n");
+            fprintf(fmode, "const unsigned int vp8_kf_default_bmode_counts ");
+            fprintf(fmode, "[VP8_BINTRAMODES] [VP8_BINTRAMODES] [VP8_BINTRAMODES] =\n{\n");
+
+            for (i = 0; i < 10; i++)
+            {
+
+                fprintf(fmode, "    { //Above Mode :  %d\n", i);
+
+                for (j = 0; j < 10; j++)
+                {
+
+                    fprintf(fmode, "        {");
+
+                    for (k = 0; k < 10; k++)
+                    {
+                        if (!intra_mode_stats[i][j][k])
+                            fprintf(fmode, " %5d, ", 1);
+                        else
+                            fprintf(fmode, " %5d, ", intra_mode_stats[i][j][k]);
+                    }
+
+                    fprintf(fmode, "}, // left_mode %d\n", j);
+
+                }
+
+                fprintf(fmode, "    },\n");
+
+            }
+
+            fprintf(fmode, "};\n");
+            fclose(fmode);
+        }
+#endif
+
+
+#if defined(SECTIONBITS_OUTPUT)
+
+        if (0)
+        {
+            int i;
+            FILE *f = fopen("tokenbits.stt", "a");
+
+            for (i = 0; i < 28; i++)
+                fprintf(f, "%8d", (int)(Sectionbits[i] / 256));
+
+            fprintf(f, "\n");
+            fclose(f);
+        }
+
+#endif
+
+#if 0
+        {
+            printf("\n_pick_loop_filter_level:%d\n", cpi->time_pick_lpf / 1000);
+            printf("\n_frames recive_data encod_mb_row compress_frame  Total\n");
+            printf("%6d %10ld %10ld %10ld %10ld\n", cpi->common.current_video_frame, cpi->time_receive_data / 1000, cpi->time_encode_mb_row / 1000, cpi->time_compress_data / 1000, (cpi->time_receive_data + cpi->time_compress_data) / 1000);
+        }
+#endif
+
+    }
+
+#if CONFIG_MULTITHREAD
+    vp8cx_remove_encoder_threads(cpi);
+#endif
+
+#if CONFIG_TEMPORAL_DENOISING
+    vp8_denoiser_free(&cpi->denoiser);
+#endif
+    dealloc_compressor_data(cpi);
+    vpx_free(cpi->mb.ss);
+    vpx_free(cpi->tok);
+    vpx_free(cpi->cyclic_refresh_map);
+
+    vp8_remove_common(&cpi->common);
+    vpx_free(cpi);
+    *ptr = 0;
+
+#ifdef OUTPUT_YUV_SRC
+    fclose(yuv_file);
+#endif
+
+#if 0
+
+    if (keyfile)
+        fclose(keyfile);
+
+    if (framepsnr)
+        fclose(framepsnr);
+
+    if (kf_list)
+        fclose(kf_list);
+
+#endif
+
+}
+
+
+static uint64_t calc_plane_error(unsigned char *orig, int orig_stride,
+                                 unsigned char *recon, int recon_stride,
+                                 unsigned int cols, unsigned int rows)
+{
+    unsigned int row, col;
+    uint64_t total_sse = 0;
+    int diff;
+
+    for (row = 0; row + 16 <= rows; row += 16)
+    {
+        for (col = 0; col + 16 <= cols; col += 16)
+        {
+            unsigned int sse;
+
+            vp8_mse16x16(orig + col, orig_stride,
+                                            recon + col, recon_stride,
+                                            &sse);
+            total_sse += sse;
+        }
+
+        /* Handle odd-sized width */
+        if (col < cols)
+        {
+            unsigned int   border_row, border_col;
+            unsigned char *border_orig = orig;
+            unsigned char *border_recon = recon;
+
+            for (border_row = 0; border_row < 16; border_row++)
+            {
+                for (border_col = col; border_col < cols; border_col++)
+                {
+                    diff = border_orig[border_col] - border_recon[border_col];
+                    total_sse += diff * diff;
+                }
+
+                border_orig += orig_stride;
+                border_recon += recon_stride;
+            }
+        }
+
+        orig += orig_stride * 16;
+        recon += recon_stride * 16;
+    }
+
+    /* Handle odd-sized height */
+    for (; row < rows; row++)
+    {
+        for (col = 0; col < cols; col++)
+        {
+            diff = orig[col] - recon[col];
+            total_sse += diff * diff;
+        }
+
+        orig += orig_stride;
+        recon += recon_stride;
+    }
+
+    vp8_clear_system_state();
+    return total_sse;
+}
+
+
+static void generate_psnr_packet(VP8_COMP *cpi)
+{
+    YV12_BUFFER_CONFIG      *orig = cpi->Source;
+    YV12_BUFFER_CONFIG      *recon = cpi->common.frame_to_show;
+    struct vpx_codec_cx_pkt  pkt;
+    uint64_t                 sse;
+    int                      i;
+    unsigned int             width = cpi->common.Width;
+    unsigned int             height = cpi->common.Height;
+
+    pkt.kind = VPX_CODEC_PSNR_PKT;
+    sse = calc_plane_error(orig->y_buffer, orig->y_stride,
+                           recon->y_buffer, recon->y_stride,
+                           width, height);
+    pkt.data.psnr.sse[0] = sse;
+    pkt.data.psnr.sse[1] = sse;
+    pkt.data.psnr.samples[0] = width * height;
+    pkt.data.psnr.samples[1] = width * height;
+
+    width = (width + 1) / 2;
+    height = (height + 1) / 2;
+
+    sse = calc_plane_error(orig->u_buffer, orig->uv_stride,
+                           recon->u_buffer, recon->uv_stride,
+                           width, height);
+    pkt.data.psnr.sse[0] += sse;
+    pkt.data.psnr.sse[2] = sse;
+    pkt.data.psnr.samples[0] += width * height;
+    pkt.data.psnr.samples[2] = width * height;
+
+    sse = calc_plane_error(orig->v_buffer, orig->uv_stride,
+                           recon->v_buffer, recon->uv_stride,
+                           width, height);
+    pkt.data.psnr.sse[0] += sse;
+    pkt.data.psnr.sse[3] = sse;
+    pkt.data.psnr.samples[0] += width * height;
+    pkt.data.psnr.samples[3] = width * height;
+
+    for (i = 0; i < 4; i++)
+        pkt.data.psnr.psnr[i] = vp8_mse2psnr(pkt.data.psnr.samples[i], 255.0,
+                                             pkt.data.psnr.sse[i]);
+
+    vpx_codec_pkt_list_add(cpi->output_pkt_list, &pkt);
+}
+
+
+int vp8_use_as_reference(VP8_COMP *cpi, int ref_frame_flags)
+{
+    if (ref_frame_flags > 7)
+        return -1 ;
+
+    cpi->ref_frame_flags = ref_frame_flags;
+    return 0;
+}
+int vp8_update_reference(VP8_COMP *cpi, int ref_frame_flags)
+{
+    if (ref_frame_flags > 7)
+        return -1 ;
+
+    cpi->common.refresh_golden_frame = 0;
+    cpi->common.refresh_alt_ref_frame = 0;
+    cpi->common.refresh_last_frame   = 0;
+
+    if (ref_frame_flags & VP8_LAST_FLAG)
+        cpi->common.refresh_last_frame = 1;
+
+    if (ref_frame_flags & VP8_GOLD_FLAG)
+        cpi->common.refresh_golden_frame = 1;
+
+    if (ref_frame_flags & VP8_ALT_FLAG)
+        cpi->common.refresh_alt_ref_frame = 1;
+
+    return 0;
+}
+
+int vp8_get_reference(VP8_COMP *cpi, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
+{
+    VP8_COMMON *cm = &cpi->common;
+    int ref_fb_idx;
+
+    if (ref_frame_flag == VP8_LAST_FLAG)
+        ref_fb_idx = cm->lst_fb_idx;
+    else if (ref_frame_flag == VP8_GOLD_FLAG)
+        ref_fb_idx = cm->gld_fb_idx;
+    else if (ref_frame_flag == VP8_ALT_FLAG)
+        ref_fb_idx = cm->alt_fb_idx;
+    else
+        return -1;
+
+    vp8_yv12_copy_frame(&cm->yv12_fb[ref_fb_idx], sd);
+
+    return 0;
+}
+int vp8_set_reference(VP8_COMP *cpi, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
+{
+    VP8_COMMON *cm = &cpi->common;
+
+    int ref_fb_idx;
+
+    if (ref_frame_flag == VP8_LAST_FLAG)
+        ref_fb_idx = cm->lst_fb_idx;
+    else if (ref_frame_flag == VP8_GOLD_FLAG)
+        ref_fb_idx = cm->gld_fb_idx;
+    else if (ref_frame_flag == VP8_ALT_FLAG)
+        ref_fb_idx = cm->alt_fb_idx;
+    else
+        return -1;
+
+    vp8_yv12_copy_frame(sd, &cm->yv12_fb[ref_fb_idx]);
+
+    return 0;
+}
+int vp8_update_entropy(VP8_COMP *cpi, int update)
+{
+    VP8_COMMON *cm = &cpi->common;
+    cm->refresh_entropy_probs = update;
+
+    return 0;
+}
+
+
+#if OUTPUT_YUV_SRC
+void vp8_write_yuv_frame(const char *name, YV12_BUFFER_CONFIG *s)
+{
+    FILE *yuv_file = fopen(name, "ab");
+    unsigned char *src = s->y_buffer;
+    int h = s->y_height;
+
+    do
+    {
+        fwrite(src, s->y_width, 1,  yuv_file);
+        src += s->y_stride;
+    }
+    while (--h);
+
+    src = s->u_buffer;
+    h = s->uv_height;
+
+    do
+    {
+        fwrite(src, s->uv_width, 1,  yuv_file);
+        src += s->uv_stride;
+    }
+    while (--h);
+
+    src = s->v_buffer;
+    h = s->uv_height;
+
+    do
+    {
+        fwrite(src, s->uv_width, 1, yuv_file);
+        src += s->uv_stride;
+    }
+    while (--h);
+
+    fclose(yuv_file);
+}
+#endif
+
+
+static void scale_and_extend_source(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = &cpi->common;
+
+    // are we resizing the image
+    if (cm->horiz_scale != 0 || cm->vert_scale != 0)
+    {
+#if CONFIG_SPATIAL_RESAMPLING
+        int UNINITIALIZED_IS_SAFE(hr), UNINITIALIZED_IS_SAFE(hs);
+        int UNINITIALIZED_IS_SAFE(vr), UNINITIALIZED_IS_SAFE(vs);
+        int tmp_height;
+
+        if (cm->vert_scale == 3)
+            tmp_height = 9;
+        else
+            tmp_height = 11;
+
+        Scale2Ratio(cm->horiz_scale, &hr, &hs);
+        Scale2Ratio(cm->vert_scale, &vr, &vs);
+
+        vp8_scale_frame(sd, &cpi->scaled_source, cm->temp_scale_frame.y_buffer,
+                        tmp_height, hs, hr, vs, vr, 0);
+
+        vp8_yv12_extend_frame_borders(&cpi->scaled_source);
+        cpi->Source = &cpi->scaled_source;
+#endif
+    }
+    else
+        cpi->Source = sd;
+}
+
+
+static void resize_key_frame(VP8_COMP *cpi)
+{
+#if CONFIG_SPATIAL_RESAMPLING
+    VP8_COMMON *cm = &cpi->common;
+
+    // Do we need to apply resampling for one pass cbr.
+    // In one pass this is more limited than in two pass cbr
+    // The test and any change is only made one per key frame sequence
+    if (cpi->oxcf.allow_spatial_resampling && (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER))
+    {
+        int UNINITIALIZED_IS_SAFE(hr), UNINITIALIZED_IS_SAFE(hs);
+        int UNINITIALIZED_IS_SAFE(vr), UNINITIALIZED_IS_SAFE(vs);
+        int new_width, new_height;
+
+        // If we are below the resample DOWN watermark then scale down a notch.
+        if (cpi->buffer_level < (cpi->oxcf.resample_down_water_mark * cpi->oxcf.optimal_buffer_level / 100))
+        {
+            cm->horiz_scale = (cm->horiz_scale < ONETWO) ? cm->horiz_scale + 1 : ONETWO;
+            cm->vert_scale = (cm->vert_scale < ONETWO) ? cm->vert_scale + 1 : ONETWO;
+        }
+        // Should we now start scaling back up
+        else if (cpi->buffer_level > (cpi->oxcf.resample_up_water_mark * cpi->oxcf.optimal_buffer_level / 100))
+        {
+            cm->horiz_scale = (cm->horiz_scale > NORMAL) ? cm->horiz_scale - 1 : NORMAL;
+            cm->vert_scale = (cm->vert_scale > NORMAL) ? cm->vert_scale - 1 : NORMAL;
+        }
+
+        // Get the new hieght and width
+        Scale2Ratio(cm->horiz_scale, &hr, &hs);
+        Scale2Ratio(cm->vert_scale, &vr, &vs);
+        new_width = ((hs - 1) + (cpi->oxcf.Width * hr)) / hs;
+        new_height = ((vs - 1) + (cpi->oxcf.Height * vr)) / vs;
+
+        // If the image size has changed we need to reallocate the buffers
+        // and resample the source image
+        if ((cm->Width != new_width) || (cm->Height != new_height))
+        {
+            cm->Width = new_width;
+            cm->Height = new_height;
+            vp8_alloc_compressor_data(cpi);
+            scale_and_extend_source(cpi->un_scaled_source, cpi);
+        }
+    }
+
+#endif
+}
+
+
+static void update_alt_ref_frame_stats(VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = &cpi->common;
+
+    // Select an interval before next GF or altref
+    if (!cpi->auto_gold)
+        cpi->frames_till_gf_update_due = cpi->goldfreq;
+
+    if ((cpi->pass != 2) && cpi->frames_till_gf_update_due)
+    {
+        cpi->current_gf_interval = cpi->frames_till_gf_update_due;
+
+        // Set the bits per frame that we should try and recover in subsequent inter frames
+        // to account for the extra GF spend... note that his does not apply for GF updates
+        // that occur coincident with a key frame as the extra cost of key frames is dealt
+        // with elsewhere.
+
+        cpi->gf_overspend_bits += cpi->projected_frame_size;
+        cpi->non_gf_bitrate_adjustment = cpi->gf_overspend_bits / cpi->frames_till_gf_update_due;
+    }
+
+    // Update data structure that monitors level of reference to last GF
+    vpx_memset(cpi->gf_active_flags, 1, (cm->mb_rows * cm->mb_cols));
+    cpi->gf_active_count = cm->mb_rows * cm->mb_cols;
+
+    // this frame refreshes means next frames don't unless specified by user
+    cpi->common.frames_since_golden = 0;
+
+    // Clear the alternate reference update pending flag.
+    cpi->source_alt_ref_pending = 0;
+
+    // Set the alternate refernce frame active flag
+    cpi->source_alt_ref_active = 1;
+
+
+}
+static void update_golden_frame_stats(VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = &cpi->common;
+
+    // Update the Golden frame usage counts.
+    if (cm->refresh_golden_frame)
+    {
+        // Select an interval before next GF
+        if (!cpi->auto_gold)
+            cpi->frames_till_gf_update_due = cpi->goldfreq;
+
+        if ((cpi->pass != 2) && (cpi->frames_till_gf_update_due > 0))
+        {
+            cpi->current_gf_interval = cpi->frames_till_gf_update_due;
+
+            // Set the bits per frame that we should try and recover in subsequent inter frames
+            // to account for the extra GF spend... note that his does not apply for GF updates
+            // that occur coincident with a key frame as the extra cost of key frames is dealt
+            // with elsewhere.
+            if ((cm->frame_type != KEY_FRAME) && !cpi->source_alt_ref_active)
+            {
+                // Calcluate GF bits to be recovered
+                // Projected size - av frame bits available for inter frames for clip as a whole
+                cpi->gf_overspend_bits += (cpi->projected_frame_size - cpi->inter_frame_target);
+            }
+
+            cpi->non_gf_bitrate_adjustment = cpi->gf_overspend_bits / cpi->frames_till_gf_update_due;
+
+        }
+
+        // Update data structure that monitors level of reference to last GF
+        vpx_memset(cpi->gf_active_flags, 1, (cm->mb_rows * cm->mb_cols));
+        cpi->gf_active_count = cm->mb_rows * cm->mb_cols;
+
+        // this frame refreshes means next frames don't unless specified by user
+        cm->refresh_golden_frame = 0;
+        cpi->common.frames_since_golden = 0;
+
+        //if ( cm->frame_type == KEY_FRAME )
+        //{
+        cpi->recent_ref_frame_usage[INTRA_FRAME] = 1;
+        cpi->recent_ref_frame_usage[LAST_FRAME] = 1;
+        cpi->recent_ref_frame_usage[GOLDEN_FRAME] = 1;
+        cpi->recent_ref_frame_usage[ALTREF_FRAME] = 1;
+        //}
+        //else
+        //{
+        //  // Carry a potrtion of count over to begining of next gf sequence
+        //  cpi->recent_ref_frame_usage[INTRA_FRAME] >>= 5;
+        //  cpi->recent_ref_frame_usage[LAST_FRAME] >>= 5;
+        //  cpi->recent_ref_frame_usage[GOLDEN_FRAME] >>= 5;
+        //  cpi->recent_ref_frame_usage[ALTREF_FRAME] >>= 5;
+        //}
+
+        // ******** Fixed Q test code only ************
+        // If we are going to use the ALT reference for the next group of frames set a flag to say so.
+        if (cpi->oxcf.fixed_q >= 0 &&
+            cpi->oxcf.play_alternate && !cpi->common.refresh_alt_ref_frame)
+        {
+            cpi->source_alt_ref_pending = 1;
+            cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
+        }
+
+        if (!cpi->source_alt_ref_pending)
+            cpi->source_alt_ref_active = 0;
+
+        // Decrement count down till next gf
+        if (cpi->frames_till_gf_update_due > 0)
+            cpi->frames_till_gf_update_due--;
+
+    }
+    else if (!cpi->common.refresh_alt_ref_frame)
+    {
+        // Decrement count down till next gf
+        if (cpi->frames_till_gf_update_due > 0)
+            cpi->frames_till_gf_update_due--;
+
+        if (cpi->common.frames_till_alt_ref_frame)
+            cpi->common.frames_till_alt_ref_frame --;
+
+        cpi->common.frames_since_golden ++;
+
+        if (cpi->common.frames_since_golden > 1)
+        {
+            cpi->recent_ref_frame_usage[INTRA_FRAME] += cpi->count_mb_ref_frame_usage[INTRA_FRAME];
+            cpi->recent_ref_frame_usage[LAST_FRAME] += cpi->count_mb_ref_frame_usage[LAST_FRAME];
+            cpi->recent_ref_frame_usage[GOLDEN_FRAME] += cpi->count_mb_ref_frame_usage[GOLDEN_FRAME];
+            cpi->recent_ref_frame_usage[ALTREF_FRAME] += cpi->count_mb_ref_frame_usage[ALTREF_FRAME];
+        }
+    }
+}
+
+// This function updates the reference frame probability estimates that
+// will be used during mode selection
+static void update_rd_ref_frame_probs(VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = &cpi->common;
+
+    const int *const rfct = cpi->count_mb_ref_frame_usage;
+    const int rf_intra = rfct[INTRA_FRAME];
+    const int rf_inter = rfct[LAST_FRAME] + rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME];
+
+    if (cm->frame_type == KEY_FRAME)
+    {
+        cpi->prob_intra_coded = 255;
+        cpi->prob_last_coded  = 128;
+        cpi->prob_gf_coded  = 128;
+    }
+    else if (!(rf_intra + rf_inter))
+    {
+        cpi->prob_intra_coded = 63;
+        cpi->prob_last_coded  = 128;
+        cpi->prob_gf_coded    = 128;
+    }
+
+    // update reference frame costs since we can do better than what we got last frame.
+    if (cpi->oxcf.number_of_layers == 1)
+    {
+        if (cpi->common.refresh_alt_ref_frame)
+        {
+            cpi->prob_intra_coded += 40;
+            cpi->prob_last_coded = 200;
+            cpi->prob_gf_coded = 1;
+        }
+        else if (cpi->common.frames_since_golden == 0)
+        {
+            cpi->prob_last_coded = 214;
+        }
+        else if (cpi->common.frames_since_golden == 1)
+        {
+            cpi->prob_last_coded = 192;
+            cpi->prob_gf_coded = 220;
+        }
+        else if (cpi->source_alt_ref_active)
+        {
+            cpi->prob_gf_coded -= 20;
+
+            if (cpi->prob_gf_coded < 10)
+                cpi->prob_gf_coded = 10;
+        }
+        if (!cpi->source_alt_ref_active)
+            cpi->prob_gf_coded = 255;
+    }
+}
+
+
+// 1 = key, 0 = inter
+static int decide_key_frame(VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = &cpi->common;
+
+    int code_key_frame = 0;
+
+    cpi->kf_boost = 0;
+
+    if (cpi->Speed > 11)
+        return 0;
+
+    // Clear down mmx registers
+    vp8_clear_system_state();  //__asm emms;
+
+    if ((cpi->compressor_speed == 2) && (cpi->Speed >= 5) && (cpi->sf.RD == 0))
+    {
+        double change = 1.0 * abs((int)(cpi->intra_error - cpi->last_intra_error)) / (1 + cpi->last_intra_error);
+        double change2 = 1.0 * abs((int)(cpi->prediction_error - cpi->last_prediction_error)) / (1 + cpi->last_prediction_error);
+        double minerror = cm->MBs * 256;
+
+#if 0
+
+        if (10 * cpi->intra_error / (1 + cpi->prediction_error) < 15
+            && cpi->prediction_error > minerror
+            && (change > .25 || change2 > .25))
+        {
+            FILE *f = fopen("intra_inter.stt", "a");
+
+            if (cpi->prediction_error <= 0)
+                cpi->prediction_error = 1;
+
+            fprintf(f, "%d %d %d %d %14.4f\n",
+                    cm->current_video_frame,
+                    (int) cpi->prediction_error,
+                    (int) cpi->intra_error,
+                    (int)((10 * cpi->intra_error) / cpi->prediction_error),
+                    change);
+
+            fclose(f);
+        }
+
+#endif
+
+        cpi->last_intra_error = cpi->intra_error;
+        cpi->last_prediction_error = cpi->prediction_error;
+
+        if (10 * cpi->intra_error / (1 + cpi->prediction_error) < 15
+            && cpi->prediction_error > minerror
+            && (change > .25 || change2 > .25))
+        {
+            /*(change > 1.4 || change < .75)&& cpi->this_frame_percent_intra > cpi->last_frame_percent_intra + 3*/
+            return 1;
+        }
+
+        return 0;
+
+    }
+
+    // If the following are true we might as well code a key frame
+    if (((cpi->this_frame_percent_intra == 100) &&
+         (cpi->this_frame_percent_intra > (cpi->last_frame_percent_intra + 2))) ||
+        ((cpi->this_frame_percent_intra > 95) &&
+         (cpi->this_frame_percent_intra >= (cpi->last_frame_percent_intra + 5))))
+    {
+        code_key_frame = 1;
+    }
+    // in addition if the following are true and this is not a golden frame then code a key frame
+    // Note that on golden frames there often seems to be a pop in intra useage anyway hence this
+    // restriction is designed to prevent spurious key frames. The Intra pop needs to be investigated.
+    else if (((cpi->this_frame_percent_intra > 60) &&
+              (cpi->this_frame_percent_intra > (cpi->last_frame_percent_intra * 2))) ||
+             ((cpi->this_frame_percent_intra > 75) &&
+              (cpi->this_frame_percent_intra > (cpi->last_frame_percent_intra * 3 / 2))) ||
+             ((cpi->this_frame_percent_intra > 90) &&
+              (cpi->this_frame_percent_intra > (cpi->last_frame_percent_intra + 10))))
+    {
+        if (!cm->refresh_golden_frame)
+            code_key_frame = 1;
+    }
+
+    return code_key_frame;
+
+}
+
+#if !(CONFIG_REALTIME_ONLY)
+static void Pass1Encode(VP8_COMP *cpi, unsigned long *size, unsigned char *dest, unsigned int *frame_flags)
+{
+    (void) size;
+    (void) dest;
+    (void) frame_flags;
+    vp8_set_quantizer(cpi, 26);
+
+    vp8_first_pass(cpi);
+}
+#endif
+
+#if 0
+void write_cx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame)
+{
+
+    // write the frame
+    FILE *yframe;
+    int i;
+    char filename[255];
+
+    sprintf(filename, "cx\\y%04d.raw", this_frame);
+    yframe = fopen(filename, "wb");
+
+    for (i = 0; i < frame->y_height; i++)
+        fwrite(frame->y_buffer + i * frame->y_stride, frame->y_width, 1, yframe);
+
+    fclose(yframe);
+    sprintf(filename, "cx\\u%04d.raw", this_frame);
+    yframe = fopen(filename, "wb");
+
+    for (i = 0; i < frame->uv_height; i++)
+        fwrite(frame->u_buffer + i * frame->uv_stride, frame->uv_width, 1, yframe);
+
+    fclose(yframe);
+    sprintf(filename, "cx\\v%04d.raw", this_frame);
+    yframe = fopen(filename, "wb");
+
+    for (i = 0; i < frame->uv_height; i++)
+        fwrite(frame->v_buffer + i * frame->uv_stride, frame->uv_width, 1, yframe);
+
+    fclose(yframe);
+}
+#endif
+// return of 0 means drop frame
+
+// Function to test for conditions that indeicate we should loop
+// back and recode a frame.
+static int recode_loop_test( VP8_COMP *cpi,
+                              int high_limit, int low_limit,
+                              int q, int maxq, int minq )
+{
+    int force_recode = 0;
+    VP8_COMMON *cm = &cpi->common;
+
+    // Is frame recode allowed at all
+    // Yes if either recode mode 1 is selected or mode two is selcted
+    // and the frame is a key frame. golden frame or alt_ref_frame
+    if ( (cpi->sf.recode_loop == 1) ||
+         ( (cpi->sf.recode_loop == 2) &&
+           ( (cm->frame_type == KEY_FRAME) ||
+             cm->refresh_golden_frame ||
+             cm->refresh_alt_ref_frame ) ) )
+    {
+        // General over and under shoot tests
+        if ( ((cpi->projected_frame_size > high_limit) && (q < maxq)) ||
+             ((cpi->projected_frame_size < low_limit) && (q > minq)) )
+        {
+            force_recode = 1;
+        }
+        // Special Constrained quality tests
+        else if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY)
+        {
+            // Undershoot and below auto cq level
+            if ( (q > cpi->cq_target_quality) &&
+                 (cpi->projected_frame_size <
+                     ((cpi->this_frame_target * 7) >> 3)))
+            {
+                force_recode = 1;
+            }
+            // Severe undershoot and between auto and user cq level
+            else if ( (q > cpi->oxcf.cq_level) &&
+                      (cpi->projected_frame_size < cpi->min_frame_bandwidth) &&
+                      (cpi->active_best_quality > cpi->oxcf.cq_level))
+            {
+                force_recode = 1;
+                cpi->active_best_quality = cpi->oxcf.cq_level;
+            }
+        }
+    }
+
+    return force_recode;
+}
+
+static void update_reference_frames(VP8_COMMON *cm)
+{
+    YV12_BUFFER_CONFIG *yv12_fb = cm->yv12_fb;
+
+    // At this point the new frame has been encoded.
+    // If any buffer copy / swapping is signaled it should be done here.
+
+    if (cm->frame_type == KEY_FRAME)
+    {
+        yv12_fb[cm->new_fb_idx].flags |= VP8_GOLD_FLAG | VP8_ALT_FLAG ;
+
+        yv12_fb[cm->gld_fb_idx].flags &= ~VP8_GOLD_FLAG;
+        yv12_fb[cm->alt_fb_idx].flags &= ~VP8_ALT_FLAG;
+
+        cm->alt_fb_idx = cm->gld_fb_idx = cm->new_fb_idx;
+    }
+    else    /* For non key frames */
+    {
+        if (cm->refresh_alt_ref_frame)
+        {
+            assert(!cm->copy_buffer_to_arf);
+
+            cm->yv12_fb[cm->new_fb_idx].flags |= VP8_ALT_FLAG;
+            cm->yv12_fb[cm->alt_fb_idx].flags &= ~VP8_ALT_FLAG;
+            cm->alt_fb_idx = cm->new_fb_idx;
+        }
+        else if (cm->copy_buffer_to_arf)
+        {
+            assert(!(cm->copy_buffer_to_arf & ~0x3));
+
+            if (cm->copy_buffer_to_arf == 1)
+            {
+                if(cm->alt_fb_idx != cm->lst_fb_idx)
+                {
+                    yv12_fb[cm->lst_fb_idx].flags |= VP8_ALT_FLAG;
+                    yv12_fb[cm->alt_fb_idx].flags &= ~VP8_ALT_FLAG;
+                    cm->alt_fb_idx = cm->lst_fb_idx;
+                }
+            }
+            else /* if (cm->copy_buffer_to_arf == 2) */
+            {
+                if(cm->alt_fb_idx != cm->gld_fb_idx)
+                {
+                    yv12_fb[cm->gld_fb_idx].flags |= VP8_ALT_FLAG;
+                    yv12_fb[cm->alt_fb_idx].flags &= ~VP8_ALT_FLAG;
+                    cm->alt_fb_idx = cm->gld_fb_idx;
+                }
+            }
+        }
+
+        if (cm->refresh_golden_frame)
+        {
+            assert(!cm->copy_buffer_to_gf);
+
+            cm->yv12_fb[cm->new_fb_idx].flags |= VP8_GOLD_FLAG;
+            cm->yv12_fb[cm->gld_fb_idx].flags &= ~VP8_GOLD_FLAG;
+            cm->gld_fb_idx = cm->new_fb_idx;
+        }
+        else if (cm->copy_buffer_to_gf)
+        {
+            assert(!(cm->copy_buffer_to_arf & ~0x3));
+
+            if (cm->copy_buffer_to_gf == 1)
+            {
+                if(cm->gld_fb_idx != cm->lst_fb_idx)
+                {
+                    yv12_fb[cm->lst_fb_idx].flags |= VP8_GOLD_FLAG;
+                    yv12_fb[cm->gld_fb_idx].flags &= ~VP8_GOLD_FLAG;
+                    cm->gld_fb_idx = cm->lst_fb_idx;
+                }
+            }
+            else /* if (cm->copy_buffer_to_gf == 2) */
+            {
+                if(cm->alt_fb_idx != cm->gld_fb_idx)
+                {
+                    yv12_fb[cm->alt_fb_idx].flags |= VP8_GOLD_FLAG;
+                    yv12_fb[cm->gld_fb_idx].flags &= ~VP8_GOLD_FLAG;
+                    cm->gld_fb_idx = cm->alt_fb_idx;
+                }
+            }
+        }
+    }
+
+    if (cm->refresh_last_frame)
+    {
+        cm->yv12_fb[cm->new_fb_idx].flags |= VP8_LAST_FLAG;
+        cm->yv12_fb[cm->lst_fb_idx].flags &= ~VP8_LAST_FLAG;
+        cm->lst_fb_idx = cm->new_fb_idx;
+    }
+}
+
+void vp8_loopfilter_frame(VP8_COMP *cpi, VP8_COMMON *cm)
+{
+    if (cm->no_lpf)
+    {
+        cm->filter_level = 0;
+    }
+    else
+    {
+        struct vpx_usec_timer timer;
+
+        vp8_clear_system_state();
+
+        vpx_usec_timer_start(&timer);
+        if (cpi->sf.auto_filter == 0)
+            vp8cx_pick_filter_level_fast(cpi->Source, cpi);
+
+        else
+            vp8cx_pick_filter_level(cpi->Source, cpi);
+
+        vpx_usec_timer_mark(&timer);
+        cpi->time_pick_lpf += vpx_usec_timer_elapsed(&timer);
+    }
+
+#if CONFIG_MULTITHREAD
+    if (cpi->b_multi_threaded)
+        sem_post(&cpi->h_event_end_lpf); /* signal that we have set filter_level */
+#endif
+
+    if (cm->filter_level > 0)
+    {
+        vp8cx_set_alt_lf_level(cpi, cm->filter_level);
+        vp8_loop_filter_frame(cm, &cpi->mb.e_mbd);
+    }
+
+    vp8_yv12_extend_frame_borders(cm->frame_to_show);
+#if CONFIG_TEMPORAL_DENOISING
+    if (cpi->oxcf.noise_sensitivity)
+    {
+      vp8_yv12_extend_frame_borders(&cpi->denoiser.yv12_running_avg);
+    }
+#endif
+}
+
+static void encode_frame_to_data_rate
+(
+    VP8_COMP *cpi,
+    unsigned long *size,
+    unsigned char *dest,
+    unsigned char* dest_end,
+    unsigned int *frame_flags
+)
+{
+    int Q;
+    int frame_over_shoot_limit;
+    int frame_under_shoot_limit;
+
+    int Loop = 0;
+    int loop_count;
+
+    VP8_COMMON *cm = &cpi->common;
+    int active_worst_qchanged = 0;
+
+#if !(CONFIG_REALTIME_ONLY)
+    int q_low;
+    int q_high;
+    int zbin_oq_high;
+    int zbin_oq_low = 0;
+    int top_index;
+    int bottom_index;
+    int overshoot_seen = 0;
+    int undershoot_seen = 0;
+#endif
+
+    int drop_mark = cpi->oxcf.drop_frames_water_mark * cpi->oxcf.optimal_buffer_level / 100;
+    int drop_mark75 = drop_mark * 2 / 3;
+    int drop_mark50 = drop_mark / 4;
+    int drop_mark25 = drop_mark / 8;
+
+
+    // Clear down mmx registers to allow floating point in what follows
+    vp8_clear_system_state();
+
+#if CONFIG_MULTITHREAD
+    /*  wait for the last picture loopfilter thread done */
+    if (cpi->b_lpf_running)
+    {
+        sem_wait(&cpi->h_event_end_lpf);
+        cpi->b_lpf_running = 0;
+    }
+#endif
+
+    // Test code for segmentation of gf/arf (0,0)
+    //segmentation_test_function( cpi);
+
+    if(cpi->force_next_frame_intra)
+    {
+        cm->frame_type = KEY_FRAME;  /* delayed intra frame */
+        cpi->force_next_frame_intra = 0;
+    }
+
+    // For an alt ref frame in 2 pass we skip the call to the second pass function that sets the target bandwidth
+#if !(CONFIG_REALTIME_ONLY)
+
+    if (cpi->pass == 2)
+    {
+        if (cpi->common.refresh_alt_ref_frame)
+        {
+            cpi->per_frame_bandwidth = cpi->twopass.gf_bits;                           // Per frame bit target for the alt ref frame
+            cpi->target_bandwidth = cpi->twopass.gf_bits * cpi->output_frame_rate;      // per second target bitrate
+        }
+    }
+    else
+#endif
+        cpi->per_frame_bandwidth  = (int)(cpi->target_bandwidth / cpi->output_frame_rate);
+
+    // Default turn off buffer to buffer copying
+    cm->copy_buffer_to_gf = 0;
+    cm->copy_buffer_to_arf = 0;
+
+    // Clear zbin over-quant value and mode boost values.
+    cpi->zbin_over_quant = 0;
+    cpi->zbin_mode_boost = 0;
+
+    // Enable or disable mode based tweaking of the zbin
+    // For 2 Pass Only used where GF/ARF prediction quality
+    // is above a threshold
+    cpi->zbin_mode_boost_enabled = 1;
+    if (cpi->pass == 2)
+    {
+        if ( cpi->gfu_boost <= 400 )
+        {
+            cpi->zbin_mode_boost_enabled = 0;
+        }
+    }
+
+    // Current default encoder behaviour for the altref sign bias
+    if (cpi->source_alt_ref_active)
+        cpi->common.ref_frame_sign_bias[ALTREF_FRAME] = 1;
+    else
+        cpi->common.ref_frame_sign_bias[ALTREF_FRAME] = 0;
+
+    // Check to see if a key frame is signalled
+    // For two pass with auto key frame enabled cm->frame_type may already be set, but not for one pass.
+    if ((cm->current_video_frame == 0) ||
+        (cm->frame_flags & FRAMEFLAGS_KEY) ||
+        (cpi->oxcf.auto_key && (cpi->frames_since_key % cpi->key_frame_frequency == 0)))
+    {
+        // Key frame from VFW/auto-keyframe/first frame
+        cm->frame_type = KEY_FRAME;
+    }
+
+    // Set default state for segment and mode based loop filter update flags
+    cpi->mb.e_mbd.update_mb_segmentation_map = 0;
+    cpi->mb.e_mbd.update_mb_segmentation_data = 0;
+    cpi->mb.e_mbd.mode_ref_lf_delta_update = 0;
+
+    // Set various flags etc to special state if it is a key frame
+    if (cm->frame_type == KEY_FRAME)
+    {
+        int i;
+
+        // Reset the loop filter deltas and segmentation map
+        setup_features(cpi);
+
+        // If segmentation is enabled force a map update for key frames
+        if (cpi->mb.e_mbd.segmentation_enabled)
+        {
+            cpi->mb.e_mbd.update_mb_segmentation_map = 1;
+            cpi->mb.e_mbd.update_mb_segmentation_data = 1;
+        }
+
+        // The alternate reference frame cannot be active for a key frame
+        cpi->source_alt_ref_active = 0;
+
+        // Reset the RD threshold multipliers to default of * 1 (128)
+        for (i = 0; i < MAX_MODES; i++)
+        {
+            cpi->rd_thresh_mult[i] = 128;
+        }
+    }
+
+    // Test code for segmentation
+    //if ( (cm->frame_type == KEY_FRAME) || ((cm->current_video_frame % 2) == 0))
+    //if ( (cm->current_video_frame % 2) == 0 )
+    //  enable_segmentation(cpi);
+    //else
+    //  disable_segmentation(cpi);
+
+#if 0
+    // Experimental code for lagged compress and one pass
+    // Initialise one_pass GF frames stats
+    // Update stats used for GF selection
+    //if ( cpi->pass == 0 )
+    {
+        cpi->one_pass_frame_index = cm->current_video_frame % MAX_LAG_BUFFERS;
+
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frames_so_far = 0;
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_intra_error = 0.0;
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_coded_error = 0.0;
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_pcnt_inter = 0.0;
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_pcnt_motion = 0.0;
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_mvr = 0.0;
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_mvr_abs = 0.0;
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_mvc = 0.0;
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_mvc_abs = 0.0;
+    }
+#endif
+
+    update_rd_ref_frame_probs(cpi);
+
+    if (cpi->drop_frames_allowed)
+    {
+        // The reset to decimation 0 is only done here for one pass.
+        // Once it is set two pass leaves decimation on till the next kf.
+        if ((cpi->buffer_level > drop_mark) && (cpi->decimation_factor > 0))
+            cpi->decimation_factor --;
+
+        if (cpi->buffer_level > drop_mark75 && cpi->decimation_factor > 0)
+            cpi->decimation_factor = 1;
+
+        else if (cpi->buffer_level < drop_mark25 && (cpi->decimation_factor == 2 || cpi->decimation_factor == 3))
+        {
+            cpi->decimation_factor = 3;
+        }
+        else if (cpi->buffer_level < drop_mark50 && (cpi->decimation_factor == 1 || cpi->decimation_factor == 2))
+        {
+            cpi->decimation_factor = 2;
+        }
+        else if (cpi->buffer_level < drop_mark75 && (cpi->decimation_factor == 0 || cpi->decimation_factor == 1))
+        {
+            cpi->decimation_factor = 1;
+        }
+        //vpx_log("Encoder: Decimation Factor: %d \n",cpi->decimation_factor);
+    }
+
+    // The following decimates the frame rate according to a regular pattern (i.e. to 1/2 or 2/3 frame rate)
+    // This can be used to help prevent buffer under-run in CBR mode. Alternatively it might be desirable in
+    // some situations to drop frame rate but throw more bits at each frame.
+    //
+    // Note that dropping a key frame can be problematic if spatial resampling is also active
+    if (cpi->decimation_factor > 0)
+    {
+        switch (cpi->decimation_factor)
+        {
+        case 1:
+            cpi->per_frame_bandwidth  = cpi->per_frame_bandwidth * 3 / 2;
+            break;
+        case 2:
+            cpi->per_frame_bandwidth  = cpi->per_frame_bandwidth * 5 / 4;
+            break;
+        case 3:
+            cpi->per_frame_bandwidth  = cpi->per_frame_bandwidth * 5 / 4;
+            break;
+        }
+
+        // Note that we should not throw out a key frame (especially when spatial resampling is enabled).
+        if ((cm->frame_type == KEY_FRAME)) // && cpi->oxcf.allow_spatial_resampling )
+        {
+            cpi->decimation_count = cpi->decimation_factor;
+        }
+        else if (cpi->decimation_count > 0)
+        {
+            cpi->decimation_count --;
+
+            cpi->bits_off_target += cpi->av_per_frame_bandwidth;
+            if (cpi->bits_off_target > cpi->oxcf.maximum_buffer_size)
+                cpi->bits_off_target = cpi->oxcf.maximum_buffer_size;
+
+            cm->current_video_frame++;
+            cpi->frames_since_key++;
+
+#if CONFIG_INTERNAL_STATS
+            cpi->count ++;
+#endif
+
+            cpi->buffer_level = cpi->bits_off_target;
+
+            if (cpi->oxcf.number_of_layers > 1)
+            {
+                unsigned int i;
+
+                // Propagate bits saved by dropping the frame to higher layers
+                for (i=cpi->current_layer+1; i<cpi->oxcf.number_of_layers; i++)
+                {
+                    LAYER_CONTEXT *lc = &cpi->layer_context[i];
+                    lc->bits_off_target += cpi->av_per_frame_bandwidth;
+                    if (lc->bits_off_target > lc->maximum_buffer_size)
+                        lc->bits_off_target = lc->maximum_buffer_size;
+                    lc->buffer_level = lc->bits_off_target;
+                }
+            }
+
+            return;
+        }
+        else
+            cpi->decimation_count = cpi->decimation_factor;
+    }
+
+    // Decide how big to make the frame
+    if (!vp8_pick_frame_size(cpi))
+    {
+        cm->current_video_frame++;
+        cpi->frames_since_key++;
+        return;
+    }
+
+    // Reduce active_worst_allowed_q for CBR if our buffer is getting too full.
+    // This has a knock on effect on active best quality as well.
+    // For CBR if the buffer reaches its maximum level then we can no longer
+    // save up bits for later frames so we might as well use them up
+    // on the current frame.
+    if ((cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
+        (cpi->buffer_level >= cpi->oxcf.optimal_buffer_level) && cpi->buffered_mode)
+    {
+        int Adjustment = cpi->active_worst_quality / 4;       // Max adjustment is 1/4
+
+        if (Adjustment)
+        {
+            int buff_lvl_step;
+
+            if (cpi->buffer_level < cpi->oxcf.maximum_buffer_size)
+            {
+                buff_lvl_step = (cpi->oxcf.maximum_buffer_size - cpi->oxcf.optimal_buffer_level) / Adjustment;
+
+                if (buff_lvl_step)
+                    Adjustment = (cpi->buffer_level - cpi->oxcf.optimal_buffer_level) / buff_lvl_step;
+                else
+                    Adjustment = 0;
+            }
+
+            cpi->active_worst_quality -= Adjustment;
+
+            if(cpi->active_worst_quality < cpi->active_best_quality)
+                cpi->active_worst_quality = cpi->active_best_quality;
+        }
+    }
+
+    // Set an active best quality and if necessary active worst quality
+    // There is some odd behavior for one pass here that needs attention.
+    if ( (cpi->pass == 2) || (cpi->ni_frames > 150))
+    {
+        vp8_clear_system_state();
+
+        Q = cpi->active_worst_quality;
+
+        if ( cm->frame_type == KEY_FRAME )
+        {
+            if ( cpi->pass == 2 )
+            {
+                if (cpi->gfu_boost > 600)
+                   cpi->active_best_quality = kf_low_motion_minq[Q];
+                else
+                   cpi->active_best_quality = kf_high_motion_minq[Q];
+
+                // Special case for key frames forced because we have reached
+                // the maximum key frame interval. Here force the Q to a range
+                // based on the ambient Q to reduce the risk of popping
+                if ( cpi->this_key_frame_forced )
+                {
+                    if ( cpi->active_best_quality > cpi->avg_frame_qindex * 7/8)
+                        cpi->active_best_quality = cpi->avg_frame_qindex * 7/8;
+                    else if ( cpi->active_best_quality < cpi->avg_frame_qindex >> 2 )
+                        cpi->active_best_quality = cpi->avg_frame_qindex >> 2;
+                }
+            }
+            // One pass more conservative
+            else
+               cpi->active_best_quality = kf_high_motion_minq[Q];
+        }
+
+        else if (cpi->oxcf.number_of_layers==1 &&
+                (cm->refresh_golden_frame || cpi->common.refresh_alt_ref_frame))
+        {
+            // Use the lower of cpi->active_worst_quality and recent
+            // average Q as basis for GF/ARF Q limit unless last frame was
+            // a key frame.
+            if ( (cpi->frames_since_key > 1) &&
+               (cpi->avg_frame_qindex < cpi->active_worst_quality) )
+            {
+                Q = cpi->avg_frame_qindex;
+            }
+
+            // For constrained quality dont allow Q less than the cq level
+            if ( (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
+                 (Q < cpi->cq_target_quality) )
+            {
+                Q = cpi->cq_target_quality;
+            }
+
+            if ( cpi->pass == 2 )
+            {
+                if ( cpi->gfu_boost > 1000 )
+                    cpi->active_best_quality = gf_low_motion_minq[Q];
+                else if ( cpi->gfu_boost < 400 )
+                    cpi->active_best_quality = gf_high_motion_minq[Q];
+                else
+                    cpi->active_best_quality = gf_mid_motion_minq[Q];
+
+                // Constrained quality use slightly lower active best.
+                if ( cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY )
+                {
+                    cpi->active_best_quality =
+                        cpi->active_best_quality * 15/16;
+                }
+            }
+            // One pass more conservative
+            else
+                cpi->active_best_quality = gf_high_motion_minq[Q];
+        }
+        else
+        {
+            cpi->active_best_quality = inter_minq[Q];
+
+            // For the constant/constrained quality mode we dont want
+            // q to fall below the cq level.
+            if ((cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
+                (cpi->active_best_quality < cpi->cq_target_quality) )
+            {
+                // If we are strongly undershooting the target rate in the last
+                // frames then use the user passed in cq value not the auto
+                // cq value.
+                if ( cpi->rolling_actual_bits < cpi->min_frame_bandwidth )
+                    cpi->active_best_quality = cpi->oxcf.cq_level;
+                else
+                    cpi->active_best_quality = cpi->cq_target_quality;
+            }
+        }
+
+        // If CBR and the buffer is as full then it is reasonable to allow
+        // higher quality on the frames to prevent bits just going to waste.
+        if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+        {
+            // Note that the use of >= here elliminates the risk of a devide
+            // by 0 error in the else if clause
+            if (cpi->buffer_level >= cpi->oxcf.maximum_buffer_size)
+                cpi->active_best_quality = cpi->best_quality;
+
+            else if (cpi->buffer_level > cpi->oxcf.optimal_buffer_level)
+            {
+                int Fraction = ((cpi->buffer_level - cpi->oxcf.optimal_buffer_level) * 128) / (cpi->oxcf.maximum_buffer_size - cpi->oxcf.optimal_buffer_level);
+                int min_qadjustment = ((cpi->active_best_quality - cpi->best_quality) * Fraction) / 128;
+
+                cpi->active_best_quality -= min_qadjustment;
+            }
+        }
+    }
+    // Make sure constrained quality mode limits are adhered to for the first
+    // few frames of one pass encodes
+    else if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY)
+    {
+        if ( (cm->frame_type == KEY_FRAME) ||
+             cm->refresh_golden_frame || cpi->common.refresh_alt_ref_frame )
+        {
+             cpi->active_best_quality = cpi->best_quality;
+        }
+        else if (cpi->active_best_quality < cpi->cq_target_quality)
+        {
+            cpi->active_best_quality = cpi->cq_target_quality;
+        }
+    }
+
+    // Clip the active best and worst quality values to limits
+    if (cpi->active_worst_quality > cpi->worst_quality)
+        cpi->active_worst_quality = cpi->worst_quality;
+
+    if (cpi->active_best_quality < cpi->best_quality)
+        cpi->active_best_quality = cpi->best_quality;
+
+    if ( cpi->active_worst_quality < cpi->active_best_quality )
+        cpi->active_worst_quality = cpi->active_best_quality;
+
+    // Determine initial Q to try
+    Q = vp8_regulate_q(cpi, cpi->this_frame_target);
+
+#if !(CONFIG_REALTIME_ONLY)
+
+    // Set highest allowed value for Zbin over quant
+    if (cm->frame_type == KEY_FRAME)
+        zbin_oq_high = 0; //ZBIN_OQ_MAX/16
+    else if ((cpi->oxcf.number_of_layers == 1) && ((cm->refresh_alt_ref_frame ||
+              (cm->refresh_golden_frame && !cpi->source_alt_ref_active))))
+    {
+          zbin_oq_high = 16;
+    }
+    else
+        zbin_oq_high = ZBIN_OQ_MAX;
+#endif
+
+    // Setup background Q adjustment for error resilient mode.
+    // For multi-layer encodes only enable this for the base layer.
+    if (cpi->cyclic_refresh_mode_enabled && (cpi->current_layer==0))
+        cyclic_background_refresh(cpi, Q, 0);
+
+    vp8_compute_frame_size_bounds(cpi, &frame_under_shoot_limit, &frame_over_shoot_limit);
+
+#if !(CONFIG_REALTIME_ONLY)
+    // Limit Q range for the adaptive loop.
+    bottom_index = cpi->active_best_quality;
+    top_index    = cpi->active_worst_quality;
+    q_low  = cpi->active_best_quality;
+    q_high = cpi->active_worst_quality;
+#endif
+
+    vp8_save_coding_context(cpi);
+
+    loop_count = 0;
+
+    scale_and_extend_source(cpi->un_scaled_source, cpi);
+
+#if !(CONFIG_REALTIME_ONLY) && CONFIG_POSTPROC && !(CONFIG_TEMPORAL_DENOISING)
+
+    if (cpi->oxcf.noise_sensitivity > 0)
+    {
+        unsigned char *src;
+        int l = 0;
+
+        switch (cpi->oxcf.noise_sensitivity)
+        {
+        case 1:
+            l = 20;
+            break;
+        case 2:
+            l = 40;
+            break;
+        case 3:
+            l = 60;
+            break;
+        case 4:
+            l = 80;
+            break;
+        case 5:
+            l = 100;
+            break;
+        case 6:
+            l = 150;
+            break;
+        }
+
+
+        if (cm->frame_type == KEY_FRAME)
+        {
+            vp8_de_noise(cpi->Source, cpi->Source, l , 1,  0);
+        }
+        else
+        {
+            vp8_de_noise(cpi->Source, cpi->Source, l , 1,  0);
+
+            src = cpi->Source->y_buffer;
+
+            if (cpi->Source->y_stride < 0)
+            {
+                src += cpi->Source->y_stride * (cpi->Source->y_height - 1);
+            }
+        }
+    }
+
+#endif
+
+#ifdef OUTPUT_YUV_SRC
+    vp8_write_yuv_frame(cpi->Source);
+#endif
+
+    do
+    {
+        vp8_clear_system_state();  //__asm emms;
+
+        /*
+        if(cpi->is_src_frame_alt_ref)
+            Q = 127;
+            */
+
+        vp8_set_quantizer(cpi, Q);
+
+        // setup skip prob for costing in mode/mv decision
+        if (cpi->common.mb_no_coeff_skip)
+        {
+            cpi->prob_skip_false = cpi->base_skip_false_prob[Q];
+
+            if (cm->frame_type != KEY_FRAME)
+            {
+                if (cpi->common.refresh_alt_ref_frame)
+                {
+                    if (cpi->last_skip_false_probs[2] != 0)
+                        cpi->prob_skip_false = cpi->last_skip_false_probs[2];
+
+                    /*
+                                        if(cpi->last_skip_false_probs[2]!=0 && abs(Q- cpi->last_skip_probs_q[2])<=16 )
+                       cpi->prob_skip_false = cpi->last_skip_false_probs[2];
+                                        else if (cpi->last_skip_false_probs[2]!=0)
+                       cpi->prob_skip_false = (cpi->last_skip_false_probs[2]  + cpi->prob_skip_false ) / 2;
+                       */
+                }
+                else if (cpi->common.refresh_golden_frame)
+                {
+                    if (cpi->last_skip_false_probs[1] != 0)
+                        cpi->prob_skip_false = cpi->last_skip_false_probs[1];
+
+                    /*
+                                        if(cpi->last_skip_false_probs[1]!=0 && abs(Q- cpi->last_skip_probs_q[1])<=16 )
+                       cpi->prob_skip_false = cpi->last_skip_false_probs[1];
+                                        else if (cpi->last_skip_false_probs[1]!=0)
+                       cpi->prob_skip_false = (cpi->last_skip_false_probs[1]  + cpi->prob_skip_false ) / 2;
+                       */
+                }
+                else
+                {
+                    if (cpi->last_skip_false_probs[0] != 0)
+                        cpi->prob_skip_false = cpi->last_skip_false_probs[0];
+
+                    /*
+                    if(cpi->last_skip_false_probs[0]!=0 && abs(Q- cpi->last_skip_probs_q[0])<=16 )
+                        cpi->prob_skip_false = cpi->last_skip_false_probs[0];
+                    else if(cpi->last_skip_false_probs[0]!=0)
+                        cpi->prob_skip_false = (cpi->last_skip_false_probs[0]  + cpi->prob_skip_false ) / 2;
+                        */
+                }
+
+                //as this is for cost estimate, let's make sure it does not go extreme eitehr way
+                if (cpi->prob_skip_false < 5)
+                    cpi->prob_skip_false = 5;
+
+                if (cpi->prob_skip_false > 250)
+                    cpi->prob_skip_false = 250;
+
+                if (cpi->oxcf.number_of_layers == 1 && cpi->is_src_frame_alt_ref)
+                    cpi->prob_skip_false = 1;
+            }
+
+#if 0
+
+            if (cpi->pass != 1)
+            {
+                FILE *f = fopen("skip.stt", "a");
+                fprintf(f, "%d, %d, %4d ", cpi->common.refresh_golden_frame, cpi->common.refresh_alt_ref_frame, cpi->prob_skip_false);
+                fclose(f);
+            }
+
+#endif
+
+        }
+
+        if (cm->frame_type == KEY_FRAME)
+        {
+            resize_key_frame(cpi);
+            vp8_setup_key_frame(cpi);
+        }
+
+
+
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+        {
+            if(cpi->oxcf.error_resilient_mode)
+                cm->refresh_entropy_probs = 0;
+
+            if (cpi->oxcf.error_resilient_mode & VPX_ERROR_RESILIENT_PARTITIONS)
+            {
+                if (cm->frame_type == KEY_FRAME)
+                    cm->refresh_entropy_probs = 1;
+            }
+
+            if (cm->refresh_entropy_probs == 0)
+            {
+                // save a copy for later refresh
+                vpx_memcpy(&cm->lfc, &cm->fc, sizeof(cm->fc));
+            }
+
+            vp8_update_coef_context(cpi);
+
+            vp8_update_coef_probs(cpi);
+
+            // transform / motion compensation build reconstruction frame
+            // +pack coef partitions
+            vp8_encode_frame(cpi);
+
+            /* cpi->projected_frame_size is not needed for RT mode */
+        }
+#else
+        // transform / motion compensation build reconstruction frame
+        vp8_encode_frame(cpi);
+
+        cpi->projected_frame_size -= vp8_estimate_entropy_savings(cpi);
+        cpi->projected_frame_size = (cpi->projected_frame_size > 0) ? cpi->projected_frame_size : 0;
+#endif
+        vp8_clear_system_state();  //__asm emms;
+
+        // Test to see if the stats generated for this frame indicate that we should have coded a key frame
+        // (assuming that we didn't)!
+        if (cpi->pass != 2 && cpi->oxcf.auto_key && cm->frame_type != KEY_FRAME)
+        {
+            int key_frame_decision = decide_key_frame(cpi);
+
+            if (cpi->compressor_speed == 2)
+            {
+                /* we don't do re-encoding in realtime mode
+                 * if key frame is decided then we force it on next frame */
+                cpi->force_next_frame_intra = key_frame_decision;
+            }
+#if !(CONFIG_REALTIME_ONLY)
+            else if (key_frame_decision)
+            {
+                // Reset all our sizing numbers and recode
+                cm->frame_type = KEY_FRAME;
+
+                vp8_pick_frame_size(cpi);
+
+                // Clear the Alt reference frame active flag when we have a key frame
+                cpi->source_alt_ref_active = 0;
+
+                // Reset the loop filter deltas and segmentation map
+                setup_features(cpi);
+
+                // If segmentation is enabled force a map update for key frames
+                if (cpi->mb.e_mbd.segmentation_enabled)
+                {
+                    cpi->mb.e_mbd.update_mb_segmentation_map = 1;
+                    cpi->mb.e_mbd.update_mb_segmentation_data = 1;
+                }
+
+                vp8_restore_coding_context(cpi);
+
+                Q = vp8_regulate_q(cpi, cpi->this_frame_target);
+
+                vp8_compute_frame_size_bounds(cpi, &frame_under_shoot_limit, &frame_over_shoot_limit);
+
+                // Limit Q range for the adaptive loop.
+                bottom_index = cpi->active_best_quality;
+                top_index    = cpi->active_worst_quality;
+                q_low  = cpi->active_best_quality;
+                q_high = cpi->active_worst_quality;
+
+                loop_count++;
+                Loop = 1;
+
+                continue;
+            }
+#endif
+        }
+
+        vp8_clear_system_state();
+
+        if (frame_over_shoot_limit == 0)
+            frame_over_shoot_limit = 1;
+
+        // Are we are overshooting and up against the limit of active max Q.
+        if (((cpi->pass != 2) || (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)) &&
+            (Q == cpi->active_worst_quality)                     &&
+            (cpi->active_worst_quality < cpi->worst_quality)      &&
+            (cpi->projected_frame_size > frame_over_shoot_limit))
+        {
+            int over_size_percent = ((cpi->projected_frame_size - frame_over_shoot_limit) * 100) / frame_over_shoot_limit;
+
+            // If so is there any scope for relaxing it
+            while ((cpi->active_worst_quality < cpi->worst_quality) && (over_size_percent > 0))
+            {
+                cpi->active_worst_quality++;
+
+                over_size_percent = (int)(over_size_percent * 0.96);        // Assume 1 qstep = about 4% on frame size.
+            }
+#if !(CONFIG_REALTIME_ONLY)
+            top_index = cpi->active_worst_quality;
+#endif
+            // If we have updated the active max Q do not call vp8_update_rate_correction_factors() this loop.
+            active_worst_qchanged = 1;
+        }
+        else
+            active_worst_qchanged = 0;
+
+#if !(CONFIG_REALTIME_ONLY)
+        // Special case handling for forced key frames
+        if ( (cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced )
+        {
+            int last_q = Q;
+            int kf_err = vp8_calc_ss_err(cpi->Source,
+                                         &cm->yv12_fb[cm->new_fb_idx]);
+
+            // The key frame is not good enough
+            if ( kf_err > ((cpi->ambient_err * 7) >> 3) )
+            {
+                // Lower q_high
+                q_high = (Q > q_low) ? (Q - 1) : q_low;
+
+                // Adjust Q
+                Q = (q_high + q_low) >> 1;
+            }
+            // The key frame is much better than the previous frame
+            else if ( kf_err < (cpi->ambient_err >> 1) )
+            {
+                // Raise q_low
+                q_low = (Q < q_high) ? (Q + 1) : q_high;
+
+                // Adjust Q
+                Q = (q_high + q_low + 1) >> 1;
+            }
+
+            // Clamp Q to upper and lower limits:
+            if (Q > q_high)
+                Q = q_high;
+            else if (Q < q_low)
+                Q = q_low;
+
+            Loop = Q != last_q;
+        }
+
+        // Is the projected frame size out of range and are we allowed to attempt to recode.
+        else if ( recode_loop_test( cpi,
+                               frame_over_shoot_limit, frame_under_shoot_limit,
+                               Q, top_index, bottom_index ) )
+        {
+            int last_q = Q;
+            int Retries = 0;
+
+            // Frame size out of permitted range:
+            // Update correction factor & compute new Q to try...
+
+            // Frame is too large
+            if (cpi->projected_frame_size > cpi->this_frame_target)
+            {
+                //if ( cpi->zbin_over_quant == 0 )
+                q_low = (Q < q_high) ? (Q + 1) : q_high; // Raise Qlow as to at least the current value
+
+                if (cpi->zbin_over_quant > 0)            // If we are using over quant do the same for zbin_oq_low
+                    zbin_oq_low = (cpi->zbin_over_quant < zbin_oq_high) ? (cpi->zbin_over_quant + 1) : zbin_oq_high;
+
+                //if ( undershoot_seen || (Q == MAXQ) )
+                if (undershoot_seen)
+                {
+                    // Update rate_correction_factor unless cpi->active_worst_quality has changed.
+                    if (!active_worst_qchanged)
+                        vp8_update_rate_correction_factors(cpi, 1);
+
+                    Q = (q_high + q_low + 1) / 2;
+
+                    // Adjust cpi->zbin_over_quant (only allowed when Q is max)
+                    if (Q < MAXQ)
+                        cpi->zbin_over_quant = 0;
+                    else
+                    {
+                        zbin_oq_low = (cpi->zbin_over_quant < zbin_oq_high) ? (cpi->zbin_over_quant + 1) : zbin_oq_high;
+                        cpi->zbin_over_quant = (zbin_oq_high + zbin_oq_low) / 2;
+                    }
+                }
+                else
+                {
+                    // Update rate_correction_factor unless cpi->active_worst_quality has changed.
+                    if (!active_worst_qchanged)
+                        vp8_update_rate_correction_factors(cpi, 0);
+
+                    Q = vp8_regulate_q(cpi, cpi->this_frame_target);
+
+                    while (((Q < q_low) || (cpi->zbin_over_quant < zbin_oq_low)) && (Retries < 10))
+                    {
+                        vp8_update_rate_correction_factors(cpi, 0);
+                        Q = vp8_regulate_q(cpi, cpi->this_frame_target);
+                        Retries ++;
+                    }
+                }
+
+                overshoot_seen = 1;
+            }
+            // Frame is too small
+            else
+            {
+                if (cpi->zbin_over_quant == 0)
+                    q_high = (Q > q_low) ? (Q - 1) : q_low; // Lower q_high if not using over quant
+                else                                    // else lower zbin_oq_high
+                    zbin_oq_high = (cpi->zbin_over_quant > zbin_oq_low) ? (cpi->zbin_over_quant - 1) : zbin_oq_low;
+
+                if (overshoot_seen)
+                {
+                    // Update rate_correction_factor unless cpi->active_worst_quality has changed.
+                    if (!active_worst_qchanged)
+                        vp8_update_rate_correction_factors(cpi, 1);
+
+                    Q = (q_high + q_low) / 2;
+
+                    // Adjust cpi->zbin_over_quant (only allowed when Q is max)
+                    if (Q < MAXQ)
+                        cpi->zbin_over_quant = 0;
+                    else
+                        cpi->zbin_over_quant = (zbin_oq_high + zbin_oq_low) / 2;
+                }
+                else
+                {
+                    // Update rate_correction_factor unless cpi->active_worst_quality has changed.
+                    if (!active_worst_qchanged)
+                        vp8_update_rate_correction_factors(cpi, 0);
+
+                    Q = vp8_regulate_q(cpi, cpi->this_frame_target);
+
+                    // Special case reset for qlow for constrained quality.
+                    // This should only trigger where there is very substantial
+                    // undershoot on a frame and the auto cq level is above
+                    // the user passsed in value.
+                    if ( (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
+                         (Q < q_low) )
+                    {
+                        q_low = Q;
+                    }
+
+                    while (((Q > q_high) || (cpi->zbin_over_quant > zbin_oq_high)) && (Retries < 10))
+                    {
+                        vp8_update_rate_correction_factors(cpi, 0);
+                        Q = vp8_regulate_q(cpi, cpi->this_frame_target);
+                        Retries ++;
+                    }
+                }
+
+                undershoot_seen = 1;
+            }
+
+            // Clamp Q to upper and lower limits:
+            if (Q > q_high)
+                Q = q_high;
+            else if (Q < q_low)
+                Q = q_low;
+
+            // Clamp cpi->zbin_over_quant
+            cpi->zbin_over_quant = (cpi->zbin_over_quant < zbin_oq_low) ? zbin_oq_low : (cpi->zbin_over_quant > zbin_oq_high) ? zbin_oq_high : cpi->zbin_over_quant;
+
+            Loop = Q != last_q;
+        }
+        else
+#endif
+            Loop = 0;
+
+        if (cpi->is_src_frame_alt_ref)
+            Loop = 0;
+
+        if (Loop == 1)
+        {
+            vp8_restore_coding_context(cpi);
+            loop_count++;
+#if CONFIG_INTERNAL_STATS
+            cpi->tot_recode_hits++;
+#endif
+        }
+    }
+    while (Loop == 1);
+
+#if 0
+    // Experimental code for lagged and one pass
+    // Update stats used for one pass GF selection
+    {
+        /*
+            int frames_so_far;
+            double frame_intra_error;
+            double frame_coded_error;
+            double frame_pcnt_inter;
+            double frame_pcnt_motion;
+            double frame_mvr;
+            double frame_mvr_abs;
+            double frame_mvc;
+            double frame_mvc_abs;
+        */
+
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index].frame_coded_error = (double)cpi->prediction_error;
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index].frame_intra_error = (double)cpi->intra_error;
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index].frame_pcnt_inter = (double)(100 - cpi->this_frame_percent_intra) / 100.0;
+    }
+#endif
+
+    // Special case code to reduce pulsing when key frames are forced at a
+    // fixed interval. Note the reconstruction error if it is the frame before
+    // the force key frame
+    if ( cpi->next_key_frame_forced && (cpi->twopass.frames_to_key == 0) )
+    {
+        cpi->ambient_err = vp8_calc_ss_err(cpi->Source,
+                                           &cm->yv12_fb[cm->new_fb_idx]);
+    }
+
+    /* This frame's MVs are saved and will be used in next frame's MV predictor.
+     * Last frame has one more line(add to bottom) and one more column(add to
+     * right) than cm->mip. The edge elements are initialized to 0.
+     */
+#if CONFIG_MULTI_RES_ENCODING
+    if(!cpi->oxcf.mr_encoder_id && cm->show_frame)
+#else
+    if(cm->show_frame)   /* do not save for altref frame */
+#endif
+    {
+        int mb_row;
+        int mb_col;
+        /* Point to beginning of allocated MODE_INFO arrays. */
+        MODE_INFO *tmp = cm->mip;
+
+        if(cm->frame_type != KEY_FRAME)
+        {
+            for (mb_row = 0; mb_row < cm->mb_rows+1; mb_row ++)
+            {
+                for (mb_col = 0; mb_col < cm->mb_cols+1; mb_col ++)
+                {
+                    if(tmp->mbmi.ref_frame != INTRA_FRAME)
+                        cpi->lfmv[mb_col + mb_row*(cm->mode_info_stride+1)].as_int = tmp->mbmi.mv.as_int;
+
+                    cpi->lf_ref_frame_sign_bias[mb_col + mb_row*(cm->mode_info_stride+1)] = cm->ref_frame_sign_bias[tmp->mbmi.ref_frame];
+                    cpi->lf_ref_frame[mb_col + mb_row*(cm->mode_info_stride+1)] = tmp->mbmi.ref_frame;
+                    tmp++;
+                }
+            }
+        }
+    }
+
+#if CONFIG_MULTI_RES_ENCODING
+    vp8_cal_dissimilarity(cpi);
+#endif
+
+    // Update the GF useage maps.
+    // This is done after completing the compression of a frame when all
+    // modes etc. are finalized but before loop filter
+    if (cpi->oxcf.number_of_layers == 1)
+        vp8_update_gf_useage_maps(cpi, cm, &cpi->mb);
+
+    if (cm->frame_type == KEY_FRAME)
+        cm->refresh_last_frame = 1;
+
+#if 0
+    {
+        FILE *f = fopen("gfactive.stt", "a");
+        fprintf(f, "%8d %8d %8d %8d %8d\n", cm->current_video_frame, (100 * cpi->gf_active_count) / (cpi->common.mb_rows * cpi->common.mb_cols), cpi->this_iiratio, cpi->next_iiratio, cm->refresh_golden_frame);
+        fclose(f);
+    }
+#endif
+
+    // For inter frames the current default behavior is that when
+    // cm->refresh_golden_frame is set we copy the old GF over to the ARF buffer
+    // This is purely an encoder decision at present.
+    if (!cpi->oxcf.error_resilient_mode && cm->refresh_golden_frame)
+        cm->copy_buffer_to_arf  = 2;
+    else
+        cm->copy_buffer_to_arf  = 0;
+
+    cm->frame_to_show = &cm->yv12_fb[cm->new_fb_idx];
+
+#if CONFIG_MULTITHREAD
+    if (cpi->b_multi_threaded)
+    {
+        sem_post(&cpi->h_event_start_lpf); /* start loopfilter in separate thread */
+        cpi->b_lpf_running = 1;
+    }
+    else
+#endif
+    {
+        vp8_loopfilter_frame(cpi, cm);
+    }
+
+    update_reference_frames(cm);
+
+#if !(CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)
+    if (cpi->oxcf.error_resilient_mode)
+    {
+        cm->refresh_entropy_probs = 0;
+    }
+#endif
+
+#if CONFIG_MULTITHREAD
+    /* wait that filter_level is picked so that we can continue with stream packing */
+    if (cpi->b_multi_threaded)
+        sem_wait(&cpi->h_event_end_lpf);
+#endif
+
+    // build the bitstream
+    vp8_pack_bitstream(cpi, dest, dest_end, size);
+
+#if CONFIG_MULTITHREAD
+    /* if PSNR packets are generated we have to wait for the lpf */
+    if (cpi->b_lpf_running && cpi->b_calculate_psnr)
+    {
+        sem_wait(&cpi->h_event_end_lpf);
+        cpi->b_lpf_running = 0;
+    }
+#endif
+
+    /* Move storing frame_type out of the above loop since it is also
+     * needed in motion search besides loopfilter */
+    cm->last_frame_type = cm->frame_type;
+
+    // Update rate control heuristics
+    cpi->total_byte_count += (*size);
+    cpi->projected_frame_size = (*size) << 3;
+
+    if (cpi->oxcf.number_of_layers > 1)
+    {
+        unsigned int i;
+        for (i=cpi->current_layer+1; i<cpi->oxcf.number_of_layers; i++)
+          cpi->layer_context[i].total_byte_count += (*size);
+    }
+
+    if (!active_worst_qchanged)
+        vp8_update_rate_correction_factors(cpi, 2);
+
+    cpi->last_q[cm->frame_type] = cm->base_qindex;
+
+    if (cm->frame_type == KEY_FRAME)
+    {
+        vp8_adjust_key_frame_context(cpi);
+    }
+
+    // Keep a record of ambient average Q.
+    if (cm->frame_type != KEY_FRAME)
+        cpi->avg_frame_qindex = (2 + 3 * cpi->avg_frame_qindex + cm->base_qindex) >> 2;
+
+    // Keep a record from which we can calculate the average Q excluding GF updates and key frames
+    if ((cm->frame_type != KEY_FRAME) && ((cpi->oxcf.number_of_layers > 1) ||
+        (!cm->refresh_golden_frame && !cm->refresh_alt_ref_frame)))
+    {
+        cpi->ni_frames++;
+
+        // Calculate the average Q for normal inter frames (not key or GFU
+        // frames).
+        if ( cpi->pass == 2 )
+        {
+            cpi->ni_tot_qi += Q;
+            cpi->ni_av_qi = (cpi->ni_tot_qi / cpi->ni_frames);
+        }
+        else
+        {
+            // Damp value for first few frames
+            if (cpi->ni_frames > 150 )
+            {
+                cpi->ni_tot_qi += Q;
+                cpi->ni_av_qi = (cpi->ni_tot_qi / cpi->ni_frames);
+            }
+            // For one pass, early in the clip ... average the current frame Q
+            // value with the worstq entered by the user as a dampening measure
+            else
+            {
+                cpi->ni_tot_qi += Q;
+                cpi->ni_av_qi = ((cpi->ni_tot_qi / cpi->ni_frames) + cpi->worst_quality + 1) / 2;
+            }
+
+            // If the average Q is higher than what was used in the last frame
+            // (after going through the recode loop to keep the frame size within range)
+            // then use the last frame value - 1.
+            // The -1 is designed to stop Q and hence the data rate, from progressively
+            // falling away during difficult sections, but at the same time reduce the number of
+            // itterations around the recode loop.
+            if (Q > cpi->ni_av_qi)
+                cpi->ni_av_qi = Q - 1;
+        }
+    }
+
+#if 0
+
+    // If the frame was massively oversize and we are below optimal buffer level drop next frame
+    if ((cpi->drop_frames_allowed) &&
+        (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
+        (cpi->buffer_level < cpi->oxcf.drop_frames_water_mark * cpi->oxcf.optimal_buffer_level / 100) &&
+        (cpi->projected_frame_size > (4 * cpi->this_frame_target)))
+    {
+        cpi->drop_frame = 1;
+    }
+
+#endif
+
+    // Set the count for maximum consecutive dropped frames based upon the ratio of
+    // this frame size to the target average per frame bandwidth.
+    // (cpi->av_per_frame_bandwidth > 0) is just a sanity check to prevent / 0.
+    if (cpi->drop_frames_allowed && (cpi->av_per_frame_bandwidth > 0))
+    {
+        cpi->max_drop_count = cpi->projected_frame_size / cpi->av_per_frame_bandwidth;
+
+        if (cpi->max_drop_count > cpi->max_consec_dropped_frames)
+            cpi->max_drop_count = cpi->max_consec_dropped_frames;
+    }
+
+    // Update the buffer level variable.
+    // Non-viewable frames are a special case and are treated as pure overhead.
+    if ( !cm->show_frame )
+        cpi->bits_off_target -= cpi->projected_frame_size;
+    else
+        cpi->bits_off_target += cpi->av_per_frame_bandwidth - cpi->projected_frame_size;
+
+    // Clip the buffer level to the maximum specified buffer size
+    if (cpi->bits_off_target > cpi->oxcf.maximum_buffer_size)
+        cpi->bits_off_target = cpi->oxcf.maximum_buffer_size;
+
+    // Rolling monitors of whether we are over or underspending used to help regulate min and Max Q in two pass.
+    cpi->rolling_target_bits = ((cpi->rolling_target_bits * 3) + cpi->this_frame_target + 2) / 4;
+    cpi->rolling_actual_bits = ((cpi->rolling_actual_bits * 3) + cpi->projected_frame_size + 2) / 4;
+    cpi->long_rolling_target_bits = ((cpi->long_rolling_target_bits * 31) + cpi->this_frame_target + 16) / 32;
+    cpi->long_rolling_actual_bits = ((cpi->long_rolling_actual_bits * 31) + cpi->projected_frame_size + 16) / 32;
+
+    // Actual bits spent
+    cpi->total_actual_bits += cpi->projected_frame_size;
+
+    // Debug stats
+    cpi->total_target_vs_actual += (cpi->this_frame_target - cpi->projected_frame_size);
+
+    cpi->buffer_level = cpi->bits_off_target;
+
+    // Propagate values to higher temporal layers
+    if (cpi->oxcf.number_of_layers > 1)
+    {
+        unsigned int i;
+
+        for (i=cpi->current_layer+1; i<cpi->oxcf.number_of_layers; i++)
+        {
+            LAYER_CONTEXT *lc = &cpi->layer_context[i];
+            int bits_off_for_this_layer = lc->target_bandwidth / lc->frame_rate
+                                                - cpi->projected_frame_size;
+
+            lc->bits_off_target += bits_off_for_this_layer;
+
+            // Clip buffer level to maximum buffer size for the layer
+            if (lc->bits_off_target > lc->maximum_buffer_size)
+                lc->bits_off_target = lc->maximum_buffer_size;
+
+            lc->total_actual_bits += cpi->projected_frame_size;
+            lc->total_target_vs_actual += bits_off_for_this_layer;
+            lc->buffer_level = lc->bits_off_target;
+        }
+    }
+
+    // Update bits left to the kf and gf groups to account for overshoot or undershoot on these frames
+    if (cm->frame_type == KEY_FRAME)
+    {
+        cpi->twopass.kf_group_bits += cpi->this_frame_target - cpi->projected_frame_size;
+
+        if (cpi->twopass.kf_group_bits < 0)
+            cpi->twopass.kf_group_bits = 0 ;
+    }
+    else if (cm->refresh_golden_frame || cm->refresh_alt_ref_frame)
+    {
+        cpi->twopass.gf_group_bits += cpi->this_frame_target - cpi->projected_frame_size;
+
+        if (cpi->twopass.gf_group_bits < 0)
+            cpi->twopass.gf_group_bits = 0 ;
+    }
+
+    if (cm->frame_type != KEY_FRAME)
+    {
+        if (cpi->common.refresh_alt_ref_frame)
+        {
+            cpi->last_skip_false_probs[2] = cpi->prob_skip_false;
+            cpi->last_skip_probs_q[2] = cm->base_qindex;
+        }
+        else if (cpi->common.refresh_golden_frame)
+        {
+            cpi->last_skip_false_probs[1] = cpi->prob_skip_false;
+            cpi->last_skip_probs_q[1] = cm->base_qindex;
+        }
+        else
+        {
+            cpi->last_skip_false_probs[0] = cpi->prob_skip_false;
+            cpi->last_skip_probs_q[0] = cm->base_qindex;
+
+            //update the baseline
+            cpi->base_skip_false_prob[cm->base_qindex] = cpi->prob_skip_false;
+
+        }
+    }
+
+#if 0 && CONFIG_INTERNAL_STATS
+    {
+        FILE *f = fopen("tmp.stt", "a");
+
+        vp8_clear_system_state();  //__asm emms;
+
+        if (cpi->twopass.total_left_stats.coded_error != 0.0)
+            fprintf(f, "%10d %10d %10d %10d %10d %10d %10d %10d %10d %6d %6d"
+                       "%6d %6d %6d %5d %5d %5d %8d %8.2f %10d %10.3f"
+                       "%10.3f %8d\n",
+                       cpi->common.current_video_frame, cpi->this_frame_target,
+                       cpi->projected_frame_size,
+                       (cpi->projected_frame_size - cpi->this_frame_target),
+                       (int)cpi->total_target_vs_actual,
+                       cpi->buffer_level,
+                       (cpi->oxcf.starting_buffer_level-cpi->bits_off_target),
+                       (int)cpi->total_actual_bits, cm->base_qindex,
+                       cpi->active_best_quality, cpi->active_worst_quality,
+                       cpi->ni_av_qi, cpi->cq_target_quality,
+                       cpi->zbin_over_quant,
+                       //cpi->avg_frame_qindex, cpi->zbin_over_quant,
+                       cm->refresh_golden_frame, cm->refresh_alt_ref_frame,
+                       cm->frame_type, cpi->gfu_boost,
+                       cpi->twopass.est_max_qcorrection_factor,
+                       (int)cpi->twopass.bits_left,
+                       cpi->twopass.total_left_stats.coded_error,
+                       (double)cpi->twopass.bits_left /
+                           cpi->twopass.total_left_stats.coded_error,
+                       cpi->tot_recode_hits);
+        else
+            fprintf(f, "%10d %10d %10d %10d %10d %10d %10d %10d %10d %6d %6d"
+                       "%6d %6d %6d %5d %5d %5d %8d %8.2f %10d %10.3f"
+                       "%8d\n",
+                       cpi->common.current_video_frame,
+                       cpi->this_frame_target, cpi->projected_frame_size,
+                       (cpi->projected_frame_size - cpi->this_frame_target),
+                       (int)cpi->total_target_vs_actual,
+                       cpi->buffer_level,
+                       (cpi->oxcf.starting_buffer_level-cpi->bits_off_target),
+                       (int)cpi->total_actual_bits, cm->base_qindex,
+                       cpi->active_best_quality, cpi->active_worst_quality,
+                       cpi->ni_av_qi, cpi->cq_target_quality,
+                       cpi->zbin_over_quant,
+                       //cpi->avg_frame_qindex, cpi->zbin_over_quant,
+                       cm->refresh_golden_frame, cm->refresh_alt_ref_frame,
+                       cm->frame_type, cpi->gfu_boost,
+                       cpi->twopass.est_max_qcorrection_factor,
+                       (int)cpi->twopass.bits_left,
+                       cpi->twopass.total_left_stats.coded_error,
+                       cpi->tot_recode_hits);
+
+        fclose(f);
+
+        {
+            FILE *fmodes = fopen("Modes.stt", "a");
+            int i;
+
+            fprintf(fmodes, "%6d:%1d:%1d:%1d ",
+                        cpi->common.current_video_frame,
+                        cm->frame_type, cm->refresh_golden_frame,
+                        cm->refresh_alt_ref_frame);
+
+            for (i = 0; i < MAX_MODES; i++)
+                fprintf(fmodes, "%5d ", cpi->mode_chosen_counts[i]);
+
+            fprintf(fmodes, "\n");
+
+            fclose(fmodes);
+        }
+    }
+
+#endif
+
+    // If this was a kf or Gf note the Q
+    if ((cm->frame_type == KEY_FRAME) || cm->refresh_golden_frame || cm->refresh_alt_ref_frame)
+        cm->last_kf_gf_q = cm->base_qindex;
+
+    if (cm->refresh_golden_frame == 1)
+        cm->frame_flags = cm->frame_flags | FRAMEFLAGS_GOLDEN;
+    else
+        cm->frame_flags = cm->frame_flags&~FRAMEFLAGS_GOLDEN;
+
+    if (cm->refresh_alt_ref_frame == 1)
+        cm->frame_flags = cm->frame_flags | FRAMEFLAGS_ALTREF;
+    else
+        cm->frame_flags = cm->frame_flags&~FRAMEFLAGS_ALTREF;
+
+
+    if (cm->refresh_last_frame & cm->refresh_golden_frame) // both refreshed
+        cpi->gold_is_last = 1;
+    else if (cm->refresh_last_frame ^ cm->refresh_golden_frame) // 1 refreshed but not the other
+        cpi->gold_is_last = 0;
+
+    if (cm->refresh_last_frame & cm->refresh_alt_ref_frame) // both refreshed
+        cpi->alt_is_last = 1;
+    else if (cm->refresh_last_frame ^ cm->refresh_alt_ref_frame) // 1 refreshed but not the other
+        cpi->alt_is_last = 0;
+
+    if (cm->refresh_alt_ref_frame & cm->refresh_golden_frame) // both refreshed
+        cpi->gold_is_alt = 1;
+    else if (cm->refresh_alt_ref_frame ^ cm->refresh_golden_frame) // 1 refreshed but not the other
+        cpi->gold_is_alt = 0;
+
+    cpi->ref_frame_flags = VP8_ALT_FLAG | VP8_GOLD_FLAG | VP8_LAST_FLAG;
+
+    if (cpi->gold_is_last)
+        cpi->ref_frame_flags &= ~VP8_GOLD_FLAG;
+
+    if (cpi->alt_is_last)
+        cpi->ref_frame_flags &= ~VP8_ALT_FLAG;
+
+    if (cpi->gold_is_alt)
+        cpi->ref_frame_flags &= ~VP8_ALT_FLAG;
+
+
+    if (!cpi->oxcf.error_resilient_mode)
+    {
+        if (cpi->oxcf.play_alternate && cm->refresh_alt_ref_frame && (cm->frame_type != KEY_FRAME))
+            // Update the alternate reference frame stats as appropriate.
+            update_alt_ref_frame_stats(cpi);
+        else
+            // Update the Golden frame stats as appropriate.
+            update_golden_frame_stats(cpi);
+    }
+
+    if (cm->frame_type == KEY_FRAME)
+    {
+        // Tell the caller that the frame was coded as a key frame
+        *frame_flags = cm->frame_flags | FRAMEFLAGS_KEY;
+
+        // As this frame is a key frame  the next defaults to an inter frame.
+        cm->frame_type = INTER_FRAME;
+
+        cpi->last_frame_percent_intra = 100;
+    }
+    else
+    {
+        *frame_flags = cm->frame_flags&~FRAMEFLAGS_KEY;
+
+        cpi->last_frame_percent_intra = cpi->this_frame_percent_intra;
+    }
+
+    // Clear the one shot update flags for segmentation map and mode/ref loop filter deltas.
+    cpi->mb.e_mbd.update_mb_segmentation_map = 0;
+    cpi->mb.e_mbd.update_mb_segmentation_data = 0;
+    cpi->mb.e_mbd.mode_ref_lf_delta_update = 0;
+
+
+    // Dont increment frame counters if this was an altref buffer update not a real frame
+    if (cm->show_frame)
+    {
+        cm->current_video_frame++;
+        cpi->frames_since_key++;
+    }
+
+    // reset to normal state now that we are done.
+
+
+
+#if 0
+    {
+        char filename[512];
+        FILE *recon_file;
+        sprintf(filename, "enc%04d.yuv", (int) cm->current_video_frame);
+        recon_file = fopen(filename, "wb");
+        fwrite(cm->yv12_fb[cm->lst_fb_idx].buffer_alloc,
+               cm->yv12_fb[cm->lst_fb_idx].frame_size, 1, recon_file);
+        fclose(recon_file);
+    }
+#endif
+
+    // DEBUG
+    //vp8_write_yuv_frame("encoder_recon.yuv", cm->frame_to_show);
+
+
+}
+
+
+static void check_gf_quality(VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = &cpi->common;
+    int gf_active_pct = (100 * cpi->gf_active_count) / (cm->mb_rows * cm->mb_cols);
+    int gf_ref_usage_pct = (cpi->count_mb_ref_frame_usage[GOLDEN_FRAME] * 100) / (cm->mb_rows * cm->mb_cols);
+    int last_ref_zz_useage = (cpi->inter_zz_count * 100) / (cm->mb_rows * cm->mb_cols);
+
+    // Gf refresh is not currently being signalled
+    if (cpi->gf_update_recommended == 0)
+    {
+        if (cpi->common.frames_since_golden > 7)
+        {
+            // Low use of gf
+            if ((gf_active_pct < 10) || ((gf_active_pct + gf_ref_usage_pct) < 15))
+            {
+                // ...but last frame zero zero usage is reasonbable so a new gf might be appropriate
+                if (last_ref_zz_useage >= 25)
+                {
+                    cpi->gf_bad_count ++;
+
+                    if (cpi->gf_bad_count >= 8)   // Check that the condition is stable
+                    {
+                        cpi->gf_update_recommended = 1;
+                        cpi->gf_bad_count = 0;
+                    }
+                }
+                else
+                    cpi->gf_bad_count = 0;        // Restart count as the background is not stable enough
+            }
+            else
+                cpi->gf_bad_count = 0;            // Gf useage has picked up so reset count
+        }
+    }
+    // If the signal is set but has not been read should we cancel it.
+    else if (last_ref_zz_useage < 15)
+    {
+        cpi->gf_update_recommended = 0;
+        cpi->gf_bad_count = 0;
+    }
+
+#if 0
+    {
+        FILE *f = fopen("gfneeded.stt", "a");
+        fprintf(f, "%10d %10d %10d %10d %10ld \n",
+                cm->current_video_frame,
+                cpi->common.frames_since_golden,
+                gf_active_pct, gf_ref_usage_pct,
+                cpi->gf_update_recommended);
+        fclose(f);
+    }
+
+#endif
+}
+
+#if !(CONFIG_REALTIME_ONLY)
+static void Pass2Encode(VP8_COMP *cpi, unsigned long *size, unsigned char *dest, unsigned char * dest_end, unsigned int *frame_flags)
+{
+
+    if (!cpi->common.refresh_alt_ref_frame)
+        vp8_second_pass(cpi);
+
+    encode_frame_to_data_rate(cpi, size, dest, dest_end, frame_flags);
+    cpi->twopass.bits_left -= 8 * *size;
+
+    if (!cpi->common.refresh_alt_ref_frame)
+    {
+        double two_pass_min_rate = (double)(cpi->oxcf.target_bandwidth
+            *cpi->oxcf.two_pass_vbrmin_section / 100);
+        cpi->twopass.bits_left += (int64_t)(two_pass_min_rate / cpi->frame_rate);
+    }
+}
+#endif
+
+//For ARM NEON, d8-d15 are callee-saved registers, and need to be saved by us.
+#if HAVE_NEON
+extern void vp8_push_neon(int64_t *store);
+extern void vp8_pop_neon(int64_t *store);
+#endif
+
+
+int vp8_receive_raw_frame(VP8_COMP *cpi, unsigned int frame_flags, YV12_BUFFER_CONFIG *sd, int64_t time_stamp, int64_t end_time)
+{
+#if HAVE_NEON
+    int64_t store_reg[8];
+#endif
+    VP8_COMMON            *cm = &cpi->common;
+    struct vpx_usec_timer  timer;
+    int                    res = 0;
+
+#if HAVE_NEON
+#if CONFIG_RUNTIME_CPU_DETECT
+    if (cm->cpu_caps & HAS_NEON)
+#endif
+    {
+        vp8_push_neon(store_reg);
+    }
+#endif
+
+    vpx_usec_timer_start(&timer);
+
+    /* Reinit the lookahead buffer if the frame size changes */
+    if (sd->y_width != cpi->oxcf.Width || sd->y_height != cpi->oxcf.Height)
+    {
+        assert(cpi->oxcf.lag_in_frames < 2);
+        dealloc_raw_frame_buffers(cpi);
+        alloc_raw_frame_buffers(cpi);
+    }
+
+    if(vp8_lookahead_push(cpi->lookahead, sd, time_stamp, end_time,
+                          frame_flags, cpi->active_map_enabled ? cpi->active_map : NULL))
+        res = -1;
+    cm->clr_type = sd->clrtype;
+    vpx_usec_timer_mark(&timer);
+    cpi->time_receive_data += vpx_usec_timer_elapsed(&timer);
+
+#if HAVE_NEON
+#if CONFIG_RUNTIME_CPU_DETECT
+    if (cm->cpu_caps & HAS_NEON)
+#endif
+    {
+        vp8_pop_neon(store_reg);
+    }
+#endif
+
+    return res;
+}
+
+
+static int frame_is_reference(const VP8_COMP *cpi)
+{
+    const VP8_COMMON *cm = &cpi->common;
+    const MACROBLOCKD *xd = &cpi->mb.e_mbd;
+
+    return cm->frame_type == KEY_FRAME || cm->refresh_last_frame
+           || cm->refresh_golden_frame || cm->refresh_alt_ref_frame
+           || cm->copy_buffer_to_gf || cm->copy_buffer_to_arf
+           || cm->refresh_entropy_probs
+           || xd->mode_ref_lf_delta_update
+           || xd->update_mb_segmentation_map || xd->update_mb_segmentation_data;
+}
+
+
+int vp8_get_compressed_data(VP8_COMP *cpi, unsigned int *frame_flags, unsigned long *size, unsigned char *dest, unsigned char *dest_end, int64_t *time_stamp, int64_t *time_end, int flush)
+{
+#if HAVE_NEON
+    int64_t store_reg[8];
+#endif
+    VP8_COMMON *cm;
+    struct vpx_usec_timer  tsctimer;
+    struct vpx_usec_timer  ticktimer;
+    struct vpx_usec_timer  cmptimer;
+    YV12_BUFFER_CONFIG    *force_src_buffer = NULL;
+
+    if (!cpi)
+        return -1;
+
+    cm = &cpi->common;
+
+    if (setjmp(cpi->common.error.jmp))
+    {
+        cpi->common.error.setjmp = 0;
+        return VPX_CODEC_CORRUPT_FRAME;
+    }
+
+    cpi->common.error.setjmp = 1;
+
+#if HAVE_NEON
+#if CONFIG_RUNTIME_CPU_DETECT
+    if (cm->cpu_caps & HAS_NEON)
+#endif
+    {
+        vp8_push_neon(store_reg);
+    }
+#endif
+
+    vpx_usec_timer_start(&cmptimer);
+
+    cpi->source = NULL;
+
+#if !(CONFIG_REALTIME_ONLY)
+    // Should we code an alternate reference frame
+    if (cpi->oxcf.error_resilient_mode == 0 &&
+        cpi->oxcf.play_alternate &&
+        cpi->source_alt_ref_pending)
+    {
+        if ((cpi->source = vp8_lookahead_peek(cpi->lookahead,
+                                              cpi->frames_till_gf_update_due,
+                                              PEEK_FORWARD)))
+        {
+            cpi->alt_ref_source = cpi->source;
+            if (cpi->oxcf.arnr_max_frames > 0)
+            {
+                vp8_temporal_filter_prepare_c(cpi,
+                                              cpi->frames_till_gf_update_due);
+                force_src_buffer = &cpi->alt_ref_buffer;
+            }
+            cm->frames_till_alt_ref_frame = cpi->frames_till_gf_update_due;
+            cm->refresh_alt_ref_frame = 1;
+            cm->refresh_golden_frame = 0;
+            cm->refresh_last_frame = 0;
+            cm->show_frame = 0;
+            cpi->source_alt_ref_pending = 0;  // Clear Pending alt Ref flag.
+            cpi->is_src_frame_alt_ref = 0;
+        }
+    }
+#endif
+
+    if (!cpi->source)
+    {
+        /* Read last frame source if we are encoding first pass. */
+        if (cpi->pass == 1 && cm->current_video_frame > 0)
+        {
+            if((cpi->last_source = vp8_lookahead_peek(cpi->lookahead, 1,
+                                                      PEEK_BACKWARD)) == NULL)
+              return -1;
+        }
+
+
+        if ((cpi->source = vp8_lookahead_pop(cpi->lookahead, flush)))
+        {
+            cm->show_frame = 1;
+
+            cpi->is_src_frame_alt_ref = cpi->alt_ref_source
+                                        && (cpi->source == cpi->alt_ref_source);
+
+            if(cpi->is_src_frame_alt_ref)
+                cpi->alt_ref_source = NULL;
+        }
+    }
+
+    if (cpi->source)
+    {
+        cpi->Source = force_src_buffer ? force_src_buffer : &cpi->source->img;
+        cpi->un_scaled_source = cpi->Source;
+        *time_stamp = cpi->source->ts_start;
+        *time_end = cpi->source->ts_end;
+        *frame_flags = cpi->source->flags;
+
+        if (cpi->pass == 1 && cm->current_video_frame > 0)
+        {
+            cpi->last_frame_unscaled_source = &cpi->last_source->img;
+        }
+    }
+    else
+    {
+        *size = 0;
+#if !(CONFIG_REALTIME_ONLY)
+
+        if (flush && cpi->pass == 1 && !cpi->twopass.first_pass_done)
+        {
+            vp8_end_first_pass(cpi);    /* get last stats packet */
+            cpi->twopass.first_pass_done = 1;
+        }
+
+#endif
+
+#if HAVE_NEON
+#if CONFIG_RUNTIME_CPU_DETECT
+        if (cm->cpu_caps & HAS_NEON)
+#endif
+        {
+            vp8_pop_neon(store_reg);
+        }
+#endif
+        return -1;
+    }
+
+    if (cpi->source->ts_start < cpi->first_time_stamp_ever)
+    {
+        cpi->first_time_stamp_ever = cpi->source->ts_start;
+        cpi->last_end_time_stamp_seen = cpi->source->ts_start;
+    }
+
+    // adjust frame rates based on timestamps given
+    if (cm->show_frame)
+    {
+        int64_t this_duration;
+        int step = 0;
+
+        if (cpi->source->ts_start == cpi->first_time_stamp_ever)
+        {
+            this_duration = cpi->source->ts_end - cpi->source->ts_start;
+            step = 1;
+        }
+        else
+        {
+            int64_t last_duration;
+
+            this_duration = cpi->source->ts_end - cpi->last_end_time_stamp_seen;
+            last_duration = cpi->last_end_time_stamp_seen
+                            - cpi->last_time_stamp_seen;
+            // do a step update if the duration changes by 10%
+            if (last_duration)
+                step = ((this_duration - last_duration) * 10 / last_duration);
+        }
+
+        if (this_duration)
+        {
+            if (step)
+                cpi->ref_frame_rate = 10000000.0 / this_duration;
+            else
+            {
+                double avg_duration, interval;
+
+                /* Average this frame's rate into the last second's average
+                 * frame rate. If we haven't seen 1 second yet, then average
+                 * over the whole interval seen.
+                 */
+                interval = cpi->source->ts_end - cpi->first_time_stamp_ever;
+                if(interval > 10000000.0)
+                    interval = 10000000;
+
+                avg_duration = 10000000.0 / cpi->ref_frame_rate;
+                avg_duration *= (interval - avg_duration + this_duration);
+                avg_duration /= interval;
+
+                cpi->ref_frame_rate = 10000000.0 / avg_duration;
+            }
+
+            if (cpi->oxcf.number_of_layers > 1)
+            {
+                int i;
+
+                // Update frame rates for each layer
+                for (i=0; i<cpi->oxcf.number_of_layers; i++)
+                {
+                    LAYER_CONTEXT *lc = &cpi->layer_context[i];
+                    lc->frame_rate = cpi->ref_frame_rate /
+                                  cpi->oxcf.rate_decimator[i];
+                }
+            }
+            else
+                vp8_new_frame_rate(cpi, cpi->ref_frame_rate);
+        }
+
+        cpi->last_time_stamp_seen = cpi->source->ts_start;
+        cpi->last_end_time_stamp_seen = cpi->source->ts_end;
+    }
+
+    if (cpi->oxcf.number_of_layers > 1)
+    {
+        int layer;
+
+        update_layer_contexts (cpi);
+
+        // Restore layer specific context & set frame rate
+        layer = cpi->oxcf.layer_id[
+                            cm->current_video_frame % cpi->oxcf.periodicity];
+        restore_layer_context (cpi, layer);
+        vp8_new_frame_rate (cpi, cpi->layer_context[layer].frame_rate);
+    }
+
+    if (cpi->compressor_speed == 2)
+    {
+        if (cpi->oxcf.number_of_layers == 1)
+            check_gf_quality(cpi);
+        vpx_usec_timer_start(&tsctimer);
+        vpx_usec_timer_start(&ticktimer);
+    }
+
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+    {
+        int i;
+        const int num_part = (1 << cm->multi_token_partition);
+        /* the available bytes in dest */
+        const unsigned long dest_size = dest_end - dest;
+        const int tok_part_buff_size = (dest_size * 9) / (10 * num_part);
+
+        unsigned char *dp = dest;
+
+        cpi->partition_d[0] = dp;
+        dp += dest_size/10;         /* reserve 1/10 for control partition */
+        cpi->partition_d_end[0] = dp;
+
+        for(i = 0; i < num_part; i++)
+        {
+            cpi->partition_d[i + 1] = dp;
+            dp += tok_part_buff_size;
+            cpi->partition_d_end[i + 1] = dp;
+        }
+    }
+#endif
+
+    // start with a 0 size frame
+    *size = 0;
+
+    // Clear down mmx registers
+    vp8_clear_system_state();  //__asm emms;
+
+    cm->frame_type = INTER_FRAME;
+    cm->frame_flags = *frame_flags;
+
+#if 0
+
+    if (cm->refresh_alt_ref_frame)
+    {
+        //cm->refresh_golden_frame = 1;
+        cm->refresh_golden_frame = 0;
+        cm->refresh_last_frame = 0;
+    }
+    else
+    {
+        cm->refresh_golden_frame = 0;
+        cm->refresh_last_frame = 1;
+    }
+
+#endif
+    /* find a free buffer for the new frame */
+    {
+        int i = 0;
+        for(; i < NUM_YV12_BUFFERS; i++)
+        {
+            if(!cm->yv12_fb[i].flags)
+            {
+                cm->new_fb_idx = i;
+                break;
+            }
+        }
+
+        assert(i < NUM_YV12_BUFFERS );
+    }
+#if !(CONFIG_REALTIME_ONLY)
+
+    if (cpi->pass == 1)
+    {
+        Pass1Encode(cpi, size, dest, frame_flags);
+    }
+    else if (cpi->pass == 2)
+    {
+        Pass2Encode(cpi, size, dest, dest_end, frame_flags);
+    }
+    else
+#endif
+        encode_frame_to_data_rate(cpi, size, dest, dest_end, frame_flags);
+
+    if (cpi->compressor_speed == 2)
+    {
+        unsigned int duration, duration2;
+        vpx_usec_timer_mark(&tsctimer);
+        vpx_usec_timer_mark(&ticktimer);
+
+        duration = vpx_usec_timer_elapsed(&ticktimer);
+        duration2 = (unsigned int)((double)duration / 2);
+
+        if (cm->frame_type != KEY_FRAME)
+        {
+            if (cpi->avg_encode_time == 0)
+                cpi->avg_encode_time = duration;
+            else
+                cpi->avg_encode_time = (7 * cpi->avg_encode_time + duration) >> 3;
+        }
+
+        if (duration2)
+        {
+            //if(*frame_flags!=1)
+            {
+
+                if (cpi->avg_pick_mode_time == 0)
+                    cpi->avg_pick_mode_time = duration2;
+                else
+                    cpi->avg_pick_mode_time = (7 * cpi->avg_pick_mode_time + duration2) >> 3;
+            }
+        }
+
+    }
+
+    if (cm->refresh_entropy_probs == 0)
+    {
+        vpx_memcpy(&cm->fc, &cm->lfc, sizeof(cm->fc));
+    }
+
+    // Save the contexts separately for alt ref, gold and last.
+    // (TODO jbb -> Optimize this with pointers to avoid extra copies. )
+    if(cm->refresh_alt_ref_frame)
+        vpx_memcpy(&cpi->lfc_a, &cm->fc, sizeof(cm->fc));
+
+    if(cm->refresh_golden_frame)
+        vpx_memcpy(&cpi->lfc_g, &cm->fc, sizeof(cm->fc));
+
+    if(cm->refresh_last_frame)
+        vpx_memcpy(&cpi->lfc_n, &cm->fc, sizeof(cm->fc));
+
+    // if its a dropped frame honor the requests on subsequent frames
+    if (*size > 0)
+    {
+        cpi->droppable = !frame_is_reference(cpi);
+
+        // return to normal state
+        cm->refresh_entropy_probs = 1;
+        cm->refresh_alt_ref_frame = 0;
+        cm->refresh_golden_frame = 0;
+        cm->refresh_last_frame = 1;
+        cm->frame_type = INTER_FRAME;
+
+    }
+
+    // Save layer specific state
+    if (cpi->oxcf.number_of_layers > 1)
+        save_layer_context (cpi);
+
+    vpx_usec_timer_mark(&cmptimer);
+    cpi->time_compress_data += vpx_usec_timer_elapsed(&cmptimer);
+
+    if (cpi->b_calculate_psnr && cpi->pass != 1 && cm->show_frame)
+    {
+        generate_psnr_packet(cpi);
+    }
+
+#if CONFIG_INTERNAL_STATS
+
+    if (cpi->pass != 1)
+    {
+        cpi->bytes += *size;
+
+        if (cm->show_frame)
+        {
+
+            cpi->count ++;
+
+            if (cpi->b_calculate_psnr)
+            {
+                double ye,ue,ve;
+                double frame_psnr;
+                YV12_BUFFER_CONFIG      *orig = cpi->Source;
+                YV12_BUFFER_CONFIG      *recon = cpi->common.frame_to_show;
+                int y_samples = orig->y_height * orig->y_width ;
+                int uv_samples = orig->uv_height * orig->uv_width ;
+                int t_samples = y_samples + 2 * uv_samples;
+                int64_t sq_error, sq_error2;
+
+                ye = calc_plane_error(orig->y_buffer, orig->y_stride,
+                  recon->y_buffer, recon->y_stride, orig->y_width, orig->y_height);
+
+                ue = calc_plane_error(orig->u_buffer, orig->uv_stride,
+                  recon->u_buffer, recon->uv_stride, orig->uv_width, orig->uv_height);
+
+                ve = calc_plane_error(orig->v_buffer, orig->uv_stride,
+                  recon->v_buffer, recon->uv_stride, orig->uv_width, orig->uv_height);
+
+                sq_error = ye + ue + ve;
+
+                frame_psnr = vp8_mse2psnr(t_samples, 255.0, sq_error);
+
+                cpi->total_y += vp8_mse2psnr(y_samples, 255.0, ye);
+                cpi->total_u += vp8_mse2psnr(uv_samples, 255.0, ue);
+                cpi->total_v += vp8_mse2psnr(uv_samples, 255.0, ve);
+                cpi->total_sq_error += sq_error;
+                cpi->total  += frame_psnr;
+#if CONFIG_POSTPROC
+                {
+                    YV12_BUFFER_CONFIG      *pp = &cm->post_proc_buffer;
+                    double frame_psnr2, frame_ssim2 = 0;
+                    double weight = 0;
+
+                    vp8_deblock(cm->frame_to_show, &cm->post_proc_buffer, cm->filter_level * 10 / 6, 1, 0);
+                    vp8_clear_system_state();
+
+                    ye = calc_plane_error(orig->y_buffer, orig->y_stride,
+                      pp->y_buffer, pp->y_stride, orig->y_width, orig->y_height);
+
+                    ue = calc_plane_error(orig->u_buffer, orig->uv_stride,
+                      pp->u_buffer, pp->uv_stride, orig->uv_width, orig->uv_height);
+
+                    ve = calc_plane_error(orig->v_buffer, orig->uv_stride,
+                      pp->v_buffer, pp->uv_stride, orig->uv_width, orig->uv_height);
+
+                    sq_error2 = ye + ue + ve;
+
+                    frame_psnr2 = vp8_mse2psnr(t_samples, 255.0, sq_error2);
+
+                    cpi->totalp_y += vp8_mse2psnr(y_samples, 255.0, ye);
+                    cpi->totalp_u += vp8_mse2psnr(uv_samples, 255.0, ue);
+                    cpi->totalp_v += vp8_mse2psnr(uv_samples, 255.0, ve);
+                    cpi->total_sq_error2 += sq_error2;
+                    cpi->totalp  += frame_psnr2;
+
+                    frame_ssim2 = vp8_calc_ssim(cpi->Source,
+                      &cm->post_proc_buffer, 1, &weight);
+
+                    cpi->summed_quality += frame_ssim2 * weight;
+                    cpi->summed_weights += weight;
+
+                    if (cpi->oxcf.number_of_layers > 1)
+                    {
+                         int i;
+
+                         for (i=cpi->current_layer;
+                                       i<cpi->oxcf.number_of_layers; i++)
+                         {
+                             cpi->frames_in_layer[i]++;
+
+                             cpi->bytes_in_layer[i] += *size;
+                             cpi->sum_psnr[i]       += frame_psnr;
+                             cpi->sum_psnr_p[i]     += frame_psnr2;
+                             cpi->total_error2[i]   += sq_error;
+                             cpi->total_error2_p[i] += sq_error2;
+                             cpi->sum_ssim[i]       += frame_ssim2 * weight;
+                             cpi->sum_weights[i]    += weight;
+                         }
+                    }
+                }
+#endif
+            }
+
+            if (cpi->b_calculate_ssimg)
+            {
+                double y, u, v, frame_all;
+                frame_all =  vp8_calc_ssimg(cpi->Source, cm->frame_to_show,
+                    &y, &u, &v);
+
+                if (cpi->oxcf.number_of_layers > 1)
+                {
+                    int i;
+
+                    for (i=cpi->current_layer;
+                         i<cpi->oxcf.number_of_layers; i++)
+                    {
+                        if (!cpi->b_calculate_psnr)
+                            cpi->frames_in_layer[i]++;
+
+                        cpi->total_ssimg_y_in_layer[i] += y;
+                        cpi->total_ssimg_u_in_layer[i] += u;
+                        cpi->total_ssimg_v_in_layer[i] += v;
+                        cpi->total_ssimg_all_in_layer[i] += frame_all;
+                    }
+                }
+                else
+                {
+                    cpi->total_ssimg_y += y;
+                    cpi->total_ssimg_u += u;
+                    cpi->total_ssimg_v += v;
+                    cpi->total_ssimg_all += frame_all;
+                }
+            }
+
+        }
+    }
+
+#if 0
+
+    if (cpi->common.frame_type != 0 && cpi->common.base_qindex == cpi->oxcf.worst_allowed_q)
+    {
+        skiptruecount += cpi->skip_true_count;
+        skipfalsecount += cpi->skip_false_count;
+    }
+
+#endif
+#if 0
+
+    if (cpi->pass != 1)
+    {
+        FILE *f = fopen("skip.stt", "a");
+        fprintf(f, "frame:%4d flags:%4x Q:%4d P:%4d Size:%5d\n", cpi->common.current_video_frame, *frame_flags, cpi->common.base_qindex, cpi->prob_skip_false, *size);
+
+        if (cpi->is_src_frame_alt_ref == 1)
+            fprintf(f, "skipcount: %4d framesize: %d\n", cpi->skip_true_count , *size);
+
+        fclose(f);
+    }
+
+#endif
+#endif
+
+#if HAVE_NEON
+#if CONFIG_RUNTIME_CPU_DETECT
+    if (cm->cpu_caps & HAS_NEON)
+#endif
+    {
+        vp8_pop_neon(store_reg);
+    }
+#endif
+
+    cpi->common.error.setjmp = 0;
+
+    return 0;
+}
+
+int vp8_get_preview_raw_frame(VP8_COMP *cpi, YV12_BUFFER_CONFIG *dest, vp8_ppflags_t *flags)
+{
+    if (cpi->common.refresh_alt_ref_frame)
+        return -1;
+    else
+    {
+        int ret;
+
+#if CONFIG_MULTITHREAD
+        if(cpi->b_lpf_running)
+        {
+            sem_wait(&cpi->h_event_end_lpf);
+            cpi->b_lpf_running = 0;
+        }
+#endif
+
+#if CONFIG_POSTPROC
+        ret = vp8_post_proc_frame(&cpi->common, dest, flags);
+#else
+
+        if (cpi->common.frame_to_show)
+        {
+            *dest = *cpi->common.frame_to_show;
+            dest->y_width = cpi->common.Width;
+            dest->y_height = cpi->common.Height;
+            dest->uv_height = cpi->common.Height / 2;
+            ret = 0;
+        }
+        else
+        {
+            ret = -1;
+        }
+
+#endif //!CONFIG_POSTPROC
+        vp8_clear_system_state();
+        return ret;
+    }
+}
+
+int vp8_set_roimap(VP8_COMP *cpi, unsigned char *map, unsigned int rows, unsigned int cols, int delta_q[4], int delta_lf[4], unsigned int threshold[4])
+{
+    signed char feature_data[MB_LVL_MAX][MAX_MB_SEGMENTS];
+
+    if (cpi->common.mb_rows != rows || cpi->common.mb_cols != cols)
+        return -1;
+
+    if (!map)
+    {
+        disable_segmentation(cpi);
+        return 0;
+    }
+
+    // Set the segmentation Map
+    set_segmentation_map(cpi, map);
+
+    // Activate segmentation.
+    enable_segmentation(cpi);
+
+    // Set up the quant segment data
+    feature_data[MB_LVL_ALT_Q][0] = delta_q[0];
+    feature_data[MB_LVL_ALT_Q][1] = delta_q[1];
+    feature_data[MB_LVL_ALT_Q][2] = delta_q[2];
+    feature_data[MB_LVL_ALT_Q][3] = delta_q[3];
+
+    // Set up the loop segment data s
+    feature_data[MB_LVL_ALT_LF][0] = delta_lf[0];
+    feature_data[MB_LVL_ALT_LF][1] = delta_lf[1];
+    feature_data[MB_LVL_ALT_LF][2] = delta_lf[2];
+    feature_data[MB_LVL_ALT_LF][3] = delta_lf[3];
+
+    cpi->segment_encode_breakout[0] = threshold[0];
+    cpi->segment_encode_breakout[1] = threshold[1];
+    cpi->segment_encode_breakout[2] = threshold[2];
+    cpi->segment_encode_breakout[3] = threshold[3];
+
+    // Initialise the feature data structure
+    // SEGMENT_DELTADATA    0, SEGMENT_ABSDATA      1
+    set_segment_data(cpi, &feature_data[0][0], SEGMENT_DELTADATA);
+
+    return 0;
+}
+
+int vp8_set_active_map(VP8_COMP *cpi, unsigned char *map, unsigned int rows, unsigned int cols)
+{
+    if (rows == cpi->common.mb_rows && cols == cpi->common.mb_cols)
+    {
+        if (map)
+        {
+            vpx_memcpy(cpi->active_map, map, rows * cols);
+            cpi->active_map_enabled = 1;
+        }
+        else
+            cpi->active_map_enabled = 0;
+
+        return 0;
+    }
+    else
+    {
+        //cpi->active_map_enabled = 0;
+        return -1 ;
+    }
+}
+
+int vp8_set_internal_size(VP8_COMP *cpi, VPX_SCALING horiz_mode, VPX_SCALING vert_mode)
+{
+    if (horiz_mode <= ONETWO)
+        cpi->common.horiz_scale = horiz_mode;
+    else
+        return -1;
+
+    if (vert_mode <= ONETWO)
+        cpi->common.vert_scale  = vert_mode;
+    else
+        return -1;
+
+    return 0;
+}
+
+
+
+int vp8_calc_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest)
+{
+    int i, j;
+    int Total = 0;
+
+    unsigned char *src = source->y_buffer;
+    unsigned char *dst = dest->y_buffer;
+
+    // Loop through the Y plane raw and reconstruction data summing (square differences)
+    for (i = 0; i < source->y_height; i += 16)
+    {
+        for (j = 0; j < source->y_width; j += 16)
+        {
+            unsigned int sse;
+            Total += vp8_mse16x16(src + j, source->y_stride, dst + j, dest->y_stride, &sse);
+        }
+
+        src += 16 * source->y_stride;
+        dst += 16 * dest->y_stride;
+    }
+
+    return Total;
+}
+
+
+int vp8_get_quantizer(VP8_COMP *cpi)
+{
+    return cpi->common.base_qindex;
+}
diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h
new file mode 100644 (file)
index 0000000..900141b
--- /dev/null
@@ -0,0 +1,720 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_VP8_INT_H
+#define __INC_VP8_INT_H
+
+#include <stdio.h>
+#include "vpx_config.h"
+#include "vp8/common/onyx.h"
+#include "treewriter.h"
+#include "tokenize.h"
+#include "vp8/common/onyxc_int.h"
+#include "vp8/common/variance.h"
+#include "encodemb.h"
+#include "quantize.h"
+#include "vp8/common/entropy.h"
+#include "vp8/common/threading.h"
+#include "vpx_ports/mem.h"
+#include "vpx/internal/vpx_codec_internal.h"
+#include "mcomp.h"
+#include "vp8/common/findnearmv.h"
+#include "lookahead.h"
+#if CONFIG_TEMPORAL_DENOISING
+#include "vp8/encoder/denoising.h"
+#endif
+
+//#define SPEEDSTATS 1
+#define MIN_GF_INTERVAL             4
+#define DEFAULT_GF_INTERVAL         7
+
+#define KEY_FRAME_CONTEXT 5
+
+#define MAX_LAG_BUFFERS (CONFIG_REALTIME_ONLY? 1 : 25)
+
+#define AF_THRESH   25
+#define AF_THRESH2  100
+#define ARF_DECAY_THRESH 12
+#define MAX_MODES 20
+
+#define MIN_THRESHMULT  32
+#define MAX_THRESHMULT  512
+
+#define GF_ZEROMV_ZBIN_BOOST 12
+#define LF_ZEROMV_ZBIN_BOOST 6
+#define MV_ZBIN_BOOST        4
+#define ZBIN_OQ_MAX 192
+
+#if !(CONFIG_REALTIME_ONLY)
+#define VP8_TEMPORAL_ALT_REF 1
+#endif
+
+#define MAX(x,y) (((x)>(y))?(x):(y))
+#define MIN(x,y) (((x)<(y))?(x):(y))
+
+typedef struct
+{
+    int kf_indicated;
+    unsigned int frames_since_key;
+    unsigned int frames_since_golden;
+    int filter_level;
+    int frames_till_gf_update_due;
+    int recent_ref_frame_usage[MAX_REF_FRAMES];
+
+    MV_CONTEXT mvc[2];
+    int mvcosts[2][MVvals+1];
+
+#ifdef MODE_STATS
+    // Stats
+    int y_modes[5];
+    int uv_modes[4];
+    int b_modes[10];
+    int inter_y_modes[10];
+    int inter_uv_modes[4];
+    int inter_b_modes[10];
+#endif
+
+    vp8_prob ymode_prob[4], uv_mode_prob[3];   /* interframe intra mode probs */
+    vp8_prob kf_ymode_prob[4], kf_uv_mode_prob[3];   /* keyframe "" */
+
+    int ymode_count[5], uv_mode_count[4];  /* intra MB type cts this frame */
+
+    int count_mb_ref_frame_usage[MAX_REF_FRAMES];
+
+    int this_frame_percent_intra;
+    int last_frame_percent_intra;
+
+
+} CODING_CONTEXT;
+
+typedef struct
+{
+    double frame;
+    double intra_error;
+    double coded_error;
+    double ssim_weighted_pred_err;
+    double pcnt_inter;
+    double pcnt_motion;
+    double pcnt_second_ref;
+    double pcnt_neutral;
+    double MVr;
+    double mvr_abs;
+    double MVc;
+    double mvc_abs;
+    double MVrv;
+    double MVcv;
+    double mv_in_out_count;
+    double new_mv_count;
+    double duration;
+    double count;
+}
+FIRSTPASS_STATS;
+
+typedef struct
+{
+    int frames_so_far;
+    double frame_intra_error;
+    double frame_coded_error;
+    double frame_pcnt_inter;
+    double frame_pcnt_motion;
+    double frame_mvr;
+    double frame_mvr_abs;
+    double frame_mvc;
+    double frame_mvc_abs;
+
+} ONEPASS_FRAMESTATS;
+
+
+typedef enum
+{
+    THR_ZERO1          = 0,
+    THR_DC             = 1,
+
+    THR_NEAREST1       = 2,
+    THR_NEAR1          = 3,
+
+    THR_ZERO2          = 4,
+    THR_NEAREST2       = 5,
+
+    THR_ZERO3          = 6,
+    THR_NEAREST3       = 7,
+
+    THR_NEAR2          = 8,
+    THR_NEAR3          = 9,
+
+    THR_V_PRED         = 10,
+    THR_H_PRED         = 11,
+    THR_TM             = 12,
+
+    THR_NEW1           = 13,
+    THR_NEW2           = 14,
+    THR_NEW3           = 15,
+
+    THR_SPLIT1         = 16,
+    THR_SPLIT2         = 17,
+    THR_SPLIT3         = 18,
+
+    THR_B_PRED         = 19
+}
+THR_MODES;
+
+typedef enum
+{
+    DIAMOND = 0,
+    NSTEP = 1,
+    HEX = 2
+} SEARCH_METHODS;
+
+typedef struct
+{
+    int RD;
+    SEARCH_METHODS search_method;
+    int improved_quant;
+    int improved_dct;
+    int auto_filter;
+    int recode_loop;
+    int iterative_sub_pixel;
+    int half_pixel_search;
+    int quarter_pixel_search;
+    int thresh_mult[MAX_MODES];
+    int max_step_search_steps;
+    int first_step;
+    int optimize_coefficients;
+
+    int use_fastquant_for_pick;
+    int no_skip_block4x4_search;
+    int improved_mv_pred;
+
+} SPEED_FEATURES;
+
+typedef struct
+{
+    MACROBLOCK  mb;
+    int segment_counts[MAX_MB_SEGMENTS];
+    int totalrate;
+} MB_ROW_COMP;
+
+typedef struct
+{
+    TOKENEXTRA *start;
+    TOKENEXTRA *stop;
+} TOKENLIST;
+
+typedef struct
+{
+    int ithread;
+    void *ptr1;
+    void *ptr2;
+} ENCODETHREAD_DATA;
+typedef struct
+{
+    int ithread;
+    void *ptr1;
+} LPFTHREAD_DATA;
+
+enum
+{
+    BLOCK_16X8,
+    BLOCK_8X16,
+    BLOCK_8X8,
+    BLOCK_4X4,
+    BLOCK_16X16,
+    BLOCK_MAX_SEGMENTS
+};
+
+typedef struct
+{
+    // Layer configuration
+    double frame_rate;
+    int target_bandwidth;
+
+    // Layer specific coding parameters
+    int starting_buffer_level;
+    int optimal_buffer_level;
+    int maximum_buffer_size;
+    int starting_buffer_level_in_ms;
+    int optimal_buffer_level_in_ms;
+    int maximum_buffer_size_in_ms;
+
+    int avg_frame_size_for_layer;
+
+    int buffer_level;
+    int bits_off_target;
+
+    int64_t total_actual_bits;
+    int total_target_vs_actual;
+
+    int worst_quality;
+    int active_worst_quality;
+    int best_quality;
+    int active_best_quality;
+
+    int ni_av_qi;
+    int ni_tot_qi;
+    int ni_frames;
+    int avg_frame_qindex;
+
+    double rate_correction_factor;
+    double key_frame_rate_correction_factor;
+    double gf_rate_correction_factor;
+
+    int zbin_over_quant;
+
+    int inter_frame_target;
+    int64_t total_byte_count;
+
+    int filter_level;
+
+    int last_frame_percent_intra;
+
+    int count_mb_ref_frame_usage[MAX_REF_FRAMES];
+
+} LAYER_CONTEXT;
+
+typedef struct VP8_COMP
+{
+
+    DECLARE_ALIGNED(16, short, Y1quant[QINDEX_RANGE][16]);
+    DECLARE_ALIGNED(16, unsigned char, Y1quant_shift[QINDEX_RANGE][16]);
+    DECLARE_ALIGNED(16, short, Y1zbin[QINDEX_RANGE][16]);
+    DECLARE_ALIGNED(16, short, Y1round[QINDEX_RANGE][16]);
+
+    DECLARE_ALIGNED(16, short, Y2quant[QINDEX_RANGE][16]);
+    DECLARE_ALIGNED(16, unsigned char, Y2quant_shift[QINDEX_RANGE][16]);
+    DECLARE_ALIGNED(16, short, Y2zbin[QINDEX_RANGE][16]);
+    DECLARE_ALIGNED(16, short, Y2round[QINDEX_RANGE][16]);
+
+    DECLARE_ALIGNED(16, short, UVquant[QINDEX_RANGE][16]);
+    DECLARE_ALIGNED(16, unsigned char, UVquant_shift[QINDEX_RANGE][16]);
+    DECLARE_ALIGNED(16, short, UVzbin[QINDEX_RANGE][16]);
+    DECLARE_ALIGNED(16, short, UVround[QINDEX_RANGE][16]);
+
+    DECLARE_ALIGNED(16, short, zrun_zbin_boost_y1[QINDEX_RANGE][16]);
+    DECLARE_ALIGNED(16, short, zrun_zbin_boost_y2[QINDEX_RANGE][16]);
+    DECLARE_ALIGNED(16, short, zrun_zbin_boost_uv[QINDEX_RANGE][16]);
+    DECLARE_ALIGNED(16, short, Y1quant_fast[QINDEX_RANGE][16]);
+    DECLARE_ALIGNED(16, short, Y2quant_fast[QINDEX_RANGE][16]);
+    DECLARE_ALIGNED(16, short, UVquant_fast[QINDEX_RANGE][16]);
+
+
+    MACROBLOCK mb;
+    VP8_COMMON common;
+    vp8_writer bc[9]; // one boolcoder for each partition
+
+    VP8_CONFIG oxcf;
+
+    struct lookahead_ctx    *lookahead;
+    struct lookahead_entry  *source;
+    struct lookahead_entry  *alt_ref_source;
+    struct lookahead_entry  *last_source;
+
+    YV12_BUFFER_CONFIG *Source;
+    YV12_BUFFER_CONFIG *un_scaled_source;
+    YV12_BUFFER_CONFIG scaled_source;
+    YV12_BUFFER_CONFIG *last_frame_unscaled_source;
+
+    int source_alt_ref_pending; // frame in src_buffers has been identified to be encoded as an alt ref
+    int source_alt_ref_active;  // an alt ref frame has been encoded and is usable
+
+    int is_src_frame_alt_ref;   // source of frame to encode is an exact copy of an alt ref frame
+
+    int gold_is_last; // golden frame same as last frame ( short circuit gold searches)
+    int alt_is_last;  // Alt reference frame same as last ( short circuit altref search)
+    int gold_is_alt;  // don't do both alt and gold search ( just do gold).
+
+    //int refresh_alt_ref_frame;
+    YV12_BUFFER_CONFIG pick_lf_lvl_frame;
+
+    TOKENEXTRA *tok;
+    unsigned int tok_count;
+
+
+    unsigned int frames_since_key;
+    unsigned int key_frame_frequency;
+    unsigned int this_key_frame_forced;
+    unsigned int next_key_frame_forced;
+
+    // Ambient reconstruction err target for force key frames
+    int ambient_err;
+
+    unsigned int mode_check_freq[MAX_MODES];
+    unsigned int mode_test_hit_counts[MAX_MODES];
+    unsigned int mode_chosen_counts[MAX_MODES];
+    unsigned int mbs_tested_so_far;
+
+    int rd_thresh_mult[MAX_MODES];
+    int rd_baseline_thresh[MAX_MODES];
+    int rd_threshes[MAX_MODES];
+
+    int RDMULT;
+    int RDDIV ;
+
+    CODING_CONTEXT coding_context;
+
+    // Rate targetting variables
+    int64_t prediction_error;
+    int64_t last_prediction_error;
+    int64_t intra_error;
+    int64_t last_intra_error;
+
+    int this_frame_target;
+    int projected_frame_size;
+    int last_q[2];                   // Separate values for Intra/Inter
+
+    double rate_correction_factor;
+    double key_frame_rate_correction_factor;
+    double gf_rate_correction_factor;
+
+    int frames_till_gf_update_due;      // Count down till next GF
+    int current_gf_interval;          // GF interval chosen when we coded the last GF
+
+    int gf_overspend_bits;            // Total bits overspent becasue of GF boost (cumulative)
+
+    int non_gf_bitrate_adjustment;     // Used in the few frames following a GF to recover the extra bits spent in that GF
+
+    int kf_overspend_bits;            // Extra bits spent on key frames that need to be recovered on inter frames
+    int kf_bitrate_adjustment;        // Current number of bit s to try and recover on each inter frame.
+    int max_gf_interval;
+    int baseline_gf_interval;
+    int active_arnr_frames;           // <= cpi->oxcf.arnr_max_frames
+
+    int64_t key_frame_count;
+    int prior_key_frame_distance[KEY_FRAME_CONTEXT];
+    int per_frame_bandwidth;          // Current section per frame bandwidth target
+    int av_per_frame_bandwidth;        // Average frame size target for clip
+    int min_frame_bandwidth;          // Minimum allocation that should be used for any frame
+    int inter_frame_target;
+    double output_frame_rate;
+    int64_t last_time_stamp_seen;
+    int64_t last_end_time_stamp_seen;
+    int64_t first_time_stamp_ever;
+
+    int ni_av_qi;
+    int ni_tot_qi;
+    int ni_frames;
+    int avg_frame_qindex;
+
+    int zbin_over_quant;
+    int zbin_mode_boost;
+    int zbin_mode_boost_enabled;
+    int last_zbin_over_quant;
+    int last_zbin_mode_boost;
+
+    int64_t total_byte_count;
+
+    int buffered_mode;
+
+    double frame_rate;
+    double ref_frame_rate;
+    int64_t buffer_level;
+    int bits_off_target;
+
+    int rolling_target_bits;
+    int rolling_actual_bits;
+
+    int long_rolling_target_bits;
+    int long_rolling_actual_bits;
+
+    int64_t total_actual_bits;
+    int total_target_vs_actual;        // debug stats
+
+    int worst_quality;
+    int active_worst_quality;
+    int best_quality;
+    int active_best_quality;
+
+    int cq_target_quality;
+
+    int drop_frames_allowed;          // Are we permitted to drop frames?
+    int drop_frame;                  // Drop this frame?
+    int drop_count;                  // How many frames have we dropped?
+    int max_drop_count;               // How many frames should we drop?
+    int max_consec_dropped_frames;     // Limit number of consecutive frames that can be dropped.
+
+
+    int ymode_count [VP8_YMODES];        /* intra MB type cts this frame */
+    int uv_mode_count[VP8_UV_MODES];       /* intra MB type cts this frame */
+
+    unsigned int MVcount [2] [MVvals];  /* (row,col) MV cts this frame */
+
+    unsigned int coef_counts [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS];  /* for this frame */
+
+    //DECLARE_ALIGNED(16, int, coef_counts_backup [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS]);   //not used any more
+    //save vp8_tree_probs_from_distribution result for each frame to avoid repeat calculation
+    vp8_prob frame_coef_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES];
+    char update_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES];
+
+    unsigned int frame_branch_ct [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES][2];
+
+    int gfu_boost;
+    int kf_boost;
+    int last_boost;
+
+    int target_bandwidth;
+    struct vpx_codec_pkt_list  *output_pkt_list;
+
+#if 0
+    // Experimental code for lagged and one pass
+    ONEPASS_FRAMESTATS one_pass_frame_stats[MAX_LAG_BUFFERS];
+    int one_pass_frame_index;
+#endif
+
+    int decimation_factor;
+    int decimation_count;
+
+    // for real time encoding
+    int avg_encode_time;              //microsecond
+    int avg_pick_mode_time;            //microsecond
+    int Speed;
+    unsigned int cpu_freq;           //Mhz
+    int compressor_speed;
+
+    int interquantizer;
+    int auto_gold;
+    int auto_adjust_gold_quantizer;
+    int goldfreq;
+    int auto_worst_q;
+    int cpu_used;
+    int pass;
+
+
+    int prob_intra_coded;
+    int prob_last_coded;
+    int prob_gf_coded;
+    int prob_skip_false;
+    int last_skip_false_probs[3];
+    int last_skip_probs_q[3];
+    int recent_ref_frame_usage[MAX_REF_FRAMES];
+
+    int count_mb_ref_frame_usage[MAX_REF_FRAMES];
+    int this_frame_percent_intra;
+    int last_frame_percent_intra;
+
+    int ref_frame_flags;
+
+    SPEED_FEATURES sf;
+    int error_bins[1024];
+
+    // Data used for real time conferencing mode to help determine if it would be good to update the gf
+    int inter_zz_count;
+    int gf_bad_count;
+    int gf_update_recommended;
+    int skip_true_count;
+
+    unsigned char *segmentation_map;
+    signed char segment_feature_data[MB_LVL_MAX][MAX_MB_SEGMENTS];            // Segment data (can be deltas or absolute values)
+    int  segment_encode_breakout[MAX_MB_SEGMENTS];                    // segment threashold for encode breakout
+
+    unsigned char *active_map;
+    unsigned int active_map_enabled;
+    // Video conferencing cyclic refresh mode flags etc
+    // This is a mode designed to clean up the background over time in live encoding scenarious. It uses segmentation
+    int cyclic_refresh_mode_enabled;
+    int cyclic_refresh_mode_max_mbs_perframe;
+    int cyclic_refresh_mode_index;
+    int cyclic_refresh_q;
+    signed char *cyclic_refresh_map;
+
+#if CONFIG_MULTITHREAD
+    // multithread data
+    int * mt_current_mb_col;
+    int mt_sync_range;
+    int b_multi_threaded;
+    int encoding_thread_count;
+    int b_lpf_running;
+
+    pthread_t *h_encoding_thread;
+    pthread_t h_filter_thread;
+
+    MB_ROW_COMP *mb_row_ei;
+    ENCODETHREAD_DATA *en_thread_data;
+    LPFTHREAD_DATA lpf_thread_data;
+
+    //events
+    sem_t *h_event_start_encoding;
+    sem_t h_event_end_encoding;
+    sem_t h_event_start_lpf;
+    sem_t h_event_end_lpf;
+#endif
+
+    TOKENLIST *tplist;
+    unsigned int partition_sz[MAX_PARTITIONS];
+    unsigned char *partition_d[MAX_PARTITIONS];
+    unsigned char *partition_d_end[MAX_PARTITIONS];
+    // end of multithread data
+
+
+    fractional_mv_step_fp *find_fractional_mv_step;
+    vp8_full_search_fn_t full_search_sad;
+    vp8_refining_search_fn_t refining_search_sad;
+    vp8_diamond_search_fn_t diamond_search_sad;
+    vp8_variance_fn_ptr_t fn_ptr[BLOCK_MAX_SEGMENTS];
+    unsigned int time_receive_data;
+    unsigned int time_compress_data;
+    unsigned int time_pick_lpf;
+    unsigned int time_encode_mb_row;
+
+    int base_skip_false_prob[128];
+
+    FRAME_CONTEXT lfc_n; /* last frame entropy */
+    FRAME_CONTEXT lfc_a; /* last alt ref entropy */
+    FRAME_CONTEXT lfc_g; /* last gold ref entropy */
+
+
+    struct twopass_rc
+    {
+        unsigned int section_intra_rating;
+        double section_max_qfactor;
+        unsigned int next_iiratio;
+        unsigned int this_iiratio;
+        FIRSTPASS_STATS total_stats;
+        FIRSTPASS_STATS this_frame_stats;
+        FIRSTPASS_STATS *stats_in, *stats_in_end, *stats_in_start;
+        FIRSTPASS_STATS total_left_stats;
+        int first_pass_done;
+        int64_t bits_left;
+        int64_t clip_bits_total;
+        double avg_iiratio;
+        double modified_error_total;
+        double modified_error_used;
+        double modified_error_left;
+        double kf_intra_err_min;
+        double gf_intra_err_min;
+        int frames_to_key;
+        int maxq_max_limit;
+        int maxq_min_limit;
+        int gf_decay_rate;
+        int static_scene_max_gf_interval;
+        int kf_bits;
+        int gf_group_error_left;           // Remaining error from uncoded frames in a gf group. Two pass use only
+
+        // Projected total bits available for a key frame group of frames
+        int64_t kf_group_bits;
+
+        // Error score of frames still to be coded in kf group
+        int64_t kf_group_error_left;
+
+        int gf_group_bits;                // Projected Bits available for a group of frames including 1 GF or ARF
+        int gf_bits;                     // Bits for the golden frame or ARF - 2 pass only
+        int alt_extra_bits;
+        double est_max_qcorrection_factor;
+    } twopass;
+
+#if VP8_TEMPORAL_ALT_REF
+    YV12_BUFFER_CONFIG alt_ref_buffer;
+    YV12_BUFFER_CONFIG *frames[MAX_LAG_BUFFERS];
+    int fixed_divide[512];
+#endif
+
+#if CONFIG_INTERNAL_STATS
+    int    count;
+    double total_y;
+    double total_u;
+    double total_v;
+    double total ;
+    double total_sq_error;
+    double totalp_y;
+    double totalp_u;
+    double totalp_v;
+    double totalp;
+    double total_sq_error2;
+    int    bytes;
+    double summed_quality;
+    double summed_weights;
+    unsigned int tot_recode_hits;
+
+
+    double total_ssimg_y;
+    double total_ssimg_u;
+    double total_ssimg_v;
+    double total_ssimg_all;
+
+    int b_calculate_ssimg;
+#endif
+    int b_calculate_psnr;
+
+    // Per MB activity measurement
+    unsigned int activity_avg;
+    unsigned int * mb_activity_map;
+    int * mb_norm_activity_map;
+
+    // Record of which MBs still refer to last golden frame either
+    // directly or through 0,0
+    unsigned char *gf_active_flags;
+    int gf_active_count;
+
+    int output_partition;
+
+    //Store last frame's MV info for next frame MV prediction
+    int_mv *lfmv;
+    int *lf_ref_frame_sign_bias;
+    int *lf_ref_frame;
+
+    int force_next_frame_intra; /* force next frame to intra when kf_auto says so */
+
+    int droppable;
+
+#if CONFIG_TEMPORAL_DENOISING
+    VP8_DENOISER denoiser;
+#endif
+
+    // Coding layer state variables
+    unsigned int current_layer;
+    LAYER_CONTEXT layer_context[VPX_TS_MAX_LAYERS];
+
+    int64_t frames_in_layer[VPX_TS_MAX_LAYERS];
+    int64_t bytes_in_layer[VPX_TS_MAX_LAYERS];
+    double sum_psnr[VPX_TS_MAX_LAYERS];
+    double sum_psnr_p[VPX_TS_MAX_LAYERS];
+    double total_error2[VPX_TS_MAX_LAYERS];
+    double total_error2_p[VPX_TS_MAX_LAYERS];
+    double sum_ssim[VPX_TS_MAX_LAYERS];
+    double sum_weights[VPX_TS_MAX_LAYERS];
+
+    double total_ssimg_y_in_layer[VPX_TS_MAX_LAYERS];
+    double total_ssimg_u_in_layer[VPX_TS_MAX_LAYERS];
+    double total_ssimg_v_in_layer[VPX_TS_MAX_LAYERS];
+    double total_ssimg_all_in_layer[VPX_TS_MAX_LAYERS];
+
+#if CONFIG_MULTI_RES_ENCODING
+    /* Number of MBs per row at lower-resolution level */
+    int    mr_low_res_mb_cols;
+#endif
+
+} VP8_COMP;
+
+void control_data_rate(VP8_COMP *cpi);
+
+void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned char *dest_end, unsigned long *size);
+
+int rd_cost_intra_mb(MACROBLOCKD *x);
+
+void vp8_tokenize_mb(VP8_COMP *, MACROBLOCKD *, TOKENEXTRA **);
+
+void vp8_set_speed_features(VP8_COMP *cpi);
+
+#if CONFIG_DEBUG
+#define CHECK_MEM_ERROR(lval,expr) do {\
+        lval = (expr); \
+        if(!lval) \
+            vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,\
+                               "Failed to allocate "#lval" at %s:%d", \
+                               __FILE__,__LINE__);\
+    } while(0)
+#else
+#define CHECK_MEM_ERROR(lval,expr) do {\
+        lval = (expr); \
+        if(!lval) \
+            vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,\
+                               "Failed to allocate "#lval);\
+    } while(0)
+#endif
+#endif
diff --git a/vp8/encoder/pickinter.c b/vp8/encoder/pickinter.c
new file mode 100644 (file)
index 0000000..dafb645
--- /dev/null
@@ -0,0 +1,1176 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include <limits.h>
+#include "vpx_config.h"
+#include "onyx_int.h"
+#include "modecosts.h"
+#include "encodeintra.h"
+#include "vp8/common/entropymode.h"
+#include "pickinter.h"
+#include "vp8/common/findnearmv.h"
+#include "encodemb.h"
+#include "vp8/common/reconinter.h"
+#include "vp8/common/reconintra4x4.h"
+#include "vp8/common/variance.h"
+#include "mcomp.h"
+#include "rdopt.h"
+#include "vpx_mem/vpx_mem.h"
+#if CONFIG_TEMPORAL_DENOISING
+#include "denoising.h"
+#endif
+
+extern int VP8_UVSSE(MACROBLOCK *x);
+
+#ifdef SPEEDSTATS
+extern unsigned int cnt_pm;
+#endif
+
+extern const int vp8_ref_frame_order[MAX_MODES];
+extern const MB_PREDICTION_MODE vp8_mode_order[MAX_MODES];
+
+extern int vp8_cost_mv_ref(MB_PREDICTION_MODE m, const int near_mv_ref_ct[4]);
+
+
+int vp8_skip_fractional_mv_step(MACROBLOCK *mb, BLOCK *b, BLOCKD *d,
+                                int_mv *bestmv, int_mv *ref_mv,
+                                int error_per_bit,
+                                const vp8_variance_fn_ptr_t *vfp,
+                                int *mvcost[2], int *distortion,
+                                unsigned int *sse)
+{
+    (void) b;
+    (void) d;
+    (void) ref_mv;
+    (void) error_per_bit;
+    (void) vfp;
+    (void) mvcost;
+    (void) distortion;
+    (void) sse;
+    bestmv->as_mv.row <<= 3;
+    bestmv->as_mv.col <<= 3;
+    return 0;
+}
+
+
+static int get_inter_mbpred_error(MACROBLOCK *mb,
+                                  const vp8_variance_fn_ptr_t *vfp,
+                                  unsigned int *sse,
+                                  int_mv this_mv)
+{
+
+    BLOCK *b = &mb->block[0];
+    BLOCKD *d = &mb->e_mbd.block[0];
+    unsigned char *what = (*(b->base_src) + b->src);
+    int what_stride = b->src_stride;
+    int pre_stride = mb->e_mbd.pre.y_stride;
+    unsigned char *in_what = mb->e_mbd.pre.y_buffer + d->offset ;
+    int in_what_stride = pre_stride;
+    int xoffset = this_mv.as_mv.col & 7;
+    int yoffset = this_mv.as_mv.row & 7;
+
+    in_what += (this_mv.as_mv.row >> 3) * pre_stride + (this_mv.as_mv.col >> 3);
+
+    if (xoffset | yoffset)
+    {
+        return vfp->svf(in_what, in_what_stride, xoffset, yoffset, what, what_stride, sse);
+    }
+    else
+    {
+        return vfp->vf(what, what_stride, in_what, in_what_stride, sse);
+    }
+
+}
+
+
+unsigned int vp8_get4x4sse_cs_c
+(
+    const unsigned char *src_ptr,
+    int  source_stride,
+    const unsigned char *ref_ptr,
+    int  recon_stride
+)
+{
+    int distortion = 0;
+    int r, c;
+
+    for (r = 0; r < 4; r++)
+    {
+        for (c = 0; c < 4; c++)
+        {
+            int diff = src_ptr[c] - ref_ptr[c];
+            distortion += diff * diff;
+        }
+
+        src_ptr += source_stride;
+        ref_ptr += recon_stride;
+    }
+
+    return distortion;
+}
+
+static int get_prediction_error(BLOCK *be, BLOCKD *b)
+{
+    unsigned char *sptr;
+    unsigned char *dptr;
+    sptr = (*(be->base_src) + be->src);
+    dptr = b->predictor;
+
+    return vp8_get4x4sse_cs(sptr, be->src_stride, dptr, 16);
+
+}
+
+static int pick_intra4x4block(
+    MACROBLOCK *x,
+    int ib,
+    B_PREDICTION_MODE *best_mode,
+    unsigned int *mode_costs,
+
+    int *bestrate,
+    int *bestdistortion)
+{
+
+    BLOCKD *b = &x->e_mbd.block[ib];
+    BLOCK *be = &x->block[ib];
+    int dst_stride = x->e_mbd.dst.y_stride;
+    unsigned char *base_dst = x->e_mbd.dst.y_buffer;
+    B_PREDICTION_MODE mode;
+    int best_rd = INT_MAX;       // 1<<30
+    int rate;
+    int distortion;
+
+    for (mode = B_DC_PRED; mode <= B_HE_PRED /*B_HU_PRED*/; mode++)
+    {
+        int this_rd;
+
+        rate = mode_costs[mode];
+        vp8_intra4x4_predict
+                     (base_dst + b->offset, dst_stride,
+                      mode, b->predictor, 16);
+        distortion = get_prediction_error(be, b);
+        this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);
+
+        if (this_rd < best_rd)
+        {
+            *bestrate = rate;
+            *bestdistortion = distortion;
+            best_rd = this_rd;
+            *best_mode = mode;
+        }
+    }
+
+    b->bmi.as_mode = (B_PREDICTION_MODE)(*best_mode);
+    vp8_encode_intra4x4block(x, ib);
+    return best_rd;
+}
+
+
+static int pick_intra4x4mby_modes
+(
+    MACROBLOCK *mb,
+    int *Rate,
+    int *best_dist
+)
+{
+    MACROBLOCKD *const xd = &mb->e_mbd;
+    int i;
+    int cost = mb->mbmode_cost [xd->frame_type] [B_PRED];
+    int error;
+    int distortion = 0;
+    unsigned int *bmode_costs;
+
+    intra_prediction_down_copy(xd, xd->dst.y_buffer - xd->dst.y_stride + 16);
+
+    bmode_costs = mb->inter_bmode_costs;
+
+    for (i = 0; i < 16; i++)
+    {
+        MODE_INFO *const mic = xd->mode_info_context;
+        const int mis = xd->mode_info_stride;
+
+        B_PREDICTION_MODE UNINITIALIZED_IS_SAFE(best_mode);
+        int UNINITIALIZED_IS_SAFE(r), UNINITIALIZED_IS_SAFE(d);
+
+        if (mb->e_mbd.frame_type == KEY_FRAME)
+        {
+            const B_PREDICTION_MODE A = above_block_mode(mic, i, mis);
+            const B_PREDICTION_MODE L = left_block_mode(mic, i);
+
+            bmode_costs  = mb->bmode_costs[A][L];
+        }
+
+
+        pick_intra4x4block(mb, i, &best_mode, bmode_costs, &r, &d);
+
+        cost += r;
+        distortion += d;
+        mic->bmi[i].as_mode = best_mode;
+
+        // Break out case where we have already exceeded best so far value
+        // that was passed in
+        if (distortion > *best_dist)
+            break;
+    }
+
+    *Rate = cost;
+
+    if (i == 16)
+    {
+        *best_dist = distortion;
+        error = RDCOST(mb->rdmult, mb->rddiv, cost, distortion);
+    }
+    else
+    {
+        *best_dist = INT_MAX;
+        error = INT_MAX;
+    }
+
+    return error;
+}
+
+static void pick_intra_mbuv_mode(MACROBLOCK *mb)
+{
+
+    MACROBLOCKD *x = &mb->e_mbd;
+    unsigned char *uabove_row = x->dst.u_buffer - x->dst.uv_stride;
+    unsigned char *vabove_row = x->dst.v_buffer - x->dst.uv_stride;
+    unsigned char *usrc_ptr = (mb->block[16].src + *mb->block[16].base_src);
+    unsigned char *vsrc_ptr = (mb->block[20].src + *mb->block[20].base_src);
+    int uvsrc_stride = mb->block[16].src_stride;
+    unsigned char uleft_col[8];
+    unsigned char vleft_col[8];
+    unsigned char utop_left = uabove_row[-1];
+    unsigned char vtop_left = vabove_row[-1];
+    int i, j;
+    int expected_udc;
+    int expected_vdc;
+    int shift;
+    int Uaverage = 0;
+    int Vaverage = 0;
+    int diff;
+    int pred_error[4] = {0, 0, 0, 0}, best_error = INT_MAX;
+    MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(best_mode);
+
+
+    for (i = 0; i < 8; i++)
+    {
+        uleft_col[i] = x->dst.u_buffer [i* x->dst.uv_stride -1];
+        vleft_col[i] = x->dst.v_buffer [i* x->dst.uv_stride -1];
+    }
+
+    if (!x->up_available && !x->left_available)
+    {
+        expected_udc = 128;
+        expected_vdc = 128;
+    }
+    else
+    {
+        shift = 2;
+
+        if (x->up_available)
+        {
+
+            for (i = 0; i < 8; i++)
+            {
+                Uaverage += uabove_row[i];
+                Vaverage += vabove_row[i];
+            }
+
+            shift ++;
+
+        }
+
+        if (x->left_available)
+        {
+            for (i = 0; i < 8; i++)
+            {
+                Uaverage += uleft_col[i];
+                Vaverage += vleft_col[i];
+            }
+
+            shift ++;
+
+        }
+
+        expected_udc = (Uaverage + (1 << (shift - 1))) >> shift;
+        expected_vdc = (Vaverage + (1 << (shift - 1))) >> shift;
+    }
+
+
+    for (i = 0; i < 8; i++)
+    {
+        for (j = 0; j < 8; j++)
+        {
+
+            int predu = uleft_col[i] + uabove_row[j] - utop_left;
+            int predv = vleft_col[i] + vabove_row[j] - vtop_left;
+            int u_p, v_p;
+
+            u_p = usrc_ptr[j];
+            v_p = vsrc_ptr[j];
+
+            if (predu < 0)
+                predu = 0;
+
+            if (predu > 255)
+                predu = 255;
+
+            if (predv < 0)
+                predv = 0;
+
+            if (predv > 255)
+                predv = 255;
+
+
+            diff = u_p - expected_udc;
+            pred_error[DC_PRED] += diff * diff;
+            diff = v_p - expected_vdc;
+            pred_error[DC_PRED] += diff * diff;
+
+
+            diff = u_p - uabove_row[j];
+            pred_error[V_PRED] += diff * diff;
+            diff = v_p - vabove_row[j];
+            pred_error[V_PRED] += diff * diff;
+
+
+            diff = u_p - uleft_col[i];
+            pred_error[H_PRED] += diff * diff;
+            diff = v_p - vleft_col[i];
+            pred_error[H_PRED] += diff * diff;
+
+
+            diff = u_p - predu;
+            pred_error[TM_PRED] += diff * diff;
+            diff = v_p - predv;
+            pred_error[TM_PRED] += diff * diff;
+
+
+        }
+
+        usrc_ptr += uvsrc_stride;
+        vsrc_ptr += uvsrc_stride;
+
+        if (i == 3)
+        {
+            usrc_ptr = (mb->block[18].src + *mb->block[18].base_src);
+            vsrc_ptr = (mb->block[22].src + *mb->block[22].base_src);
+        }
+
+
+
+    }
+
+
+    for (i = DC_PRED; i <= TM_PRED; i++)
+    {
+        if (best_error > pred_error[i])
+        {
+            best_error = pred_error[i];
+            best_mode = (MB_PREDICTION_MODE)i;
+        }
+    }
+
+
+    mb->e_mbd.mode_info_context->mbmi.uv_mode = best_mode;
+
+}
+
+static void update_mvcount(VP8_COMP *cpi, MACROBLOCKD *xd, int_mv *best_ref_mv)
+{
+    /* Split MV modes currently not supported when RD is nopt enabled,
+     * therefore, only need to modify MVcount in NEWMV mode. */
+    if (xd->mode_info_context->mbmi.mode == NEWMV)
+    {
+        cpi->MVcount[0][mv_max+((xd->mode_info_context->mbmi.mv.as_mv.row -
+                                      best_ref_mv->as_mv.row) >> 1)]++;
+        cpi->MVcount[1][mv_max+((xd->mode_info_context->mbmi.mv.as_mv.col -
+                                      best_ref_mv->as_mv.col) >> 1)]++;
+    }
+}
+
+
+#if CONFIG_MULTI_RES_ENCODING
+static
+void get_lower_res_motion_info(VP8_COMP *cpi, MACROBLOCKD *xd, int *dissim,
+                               int *parent_ref_frame,
+                               MB_PREDICTION_MODE *parent_mode,
+                               int_mv *parent_ref_mv, int mb_row, int mb_col)
+{
+    LOWER_RES_INFO* store_mode_info
+                          = (LOWER_RES_INFO*)cpi->oxcf.mr_low_res_mode_info;
+    unsigned int parent_mb_index;
+    //unsigned int parent_mb_index = map_640x480_to_320x240[mb_row][mb_col];
+
+    /* Consider different down_sampling_factor.  */
+    {
+        /* TODO: Removed the loop that supports special down_sampling_factor
+         * such as 2, 4, 8. Will revisit it if needed.
+         * Should also try using a look-up table to see if it helps
+         * performance. */
+        int parent_mb_row, parent_mb_col;
+
+        parent_mb_row = mb_row*cpi->oxcf.mr_down_sampling_factor.den
+                    /cpi->oxcf.mr_down_sampling_factor.num;
+        parent_mb_col = mb_col*cpi->oxcf.mr_down_sampling_factor.den
+                    /cpi->oxcf.mr_down_sampling_factor.num;
+        parent_mb_index = parent_mb_row*cpi->mr_low_res_mb_cols + parent_mb_col;
+    }
+
+    /* Read lower-resolution mode & motion result from memory.*/
+    *parent_ref_frame = store_mode_info[parent_mb_index].ref_frame;
+    *parent_mode =  store_mode_info[parent_mb_index].mode;
+    *dissim = store_mode_info[parent_mb_index].dissim;
+
+    /* For highest-resolution encoder, adjust dissim value. Lower its quality
+     * for good performance. */
+    if (cpi->oxcf.mr_encoder_id == (cpi->oxcf.mr_total_resolutions - 1))
+        *dissim>>=1;
+
+    if(*parent_ref_frame != INTRA_FRAME)
+    {
+        /* Consider different down_sampling_factor.
+         * The result can be rounded to be more precise, but it takes more time.
+         */
+        //int round = cpi->oxcf.mr_down_sampling_factor.den/2;
+        (*parent_ref_mv).as_mv.row = store_mode_info[parent_mb_index].mv.as_mv.row
+                                  *cpi->oxcf.mr_down_sampling_factor.num
+                                  /cpi->oxcf.mr_down_sampling_factor.den;
+        (*parent_ref_mv).as_mv.col = store_mode_info[parent_mb_index].mv.as_mv.col
+                                  *cpi->oxcf.mr_down_sampling_factor.num
+                                  /cpi->oxcf.mr_down_sampling_factor.den;
+
+        vp8_clamp_mv2(parent_ref_mv, xd);
+    }
+}
+#endif
+
+static void check_for_encode_breakout(unsigned int sse, MACROBLOCK* x)
+{
+    if (sse < x->encode_breakout)
+    {
+        // Check u and v to make sure skip is ok
+        int sse2 = 0;
+
+        sse2 = VP8_UVSSE(x);
+
+        if (sse2 * 2 < x->encode_breakout)
+            x->skip = 1;
+        else
+            x->skip = 0;
+    }
+}
+
+static int evaluate_inter_mode(unsigned int* sse, int rate2, int* distortion2, VP8_COMP *cpi, MACROBLOCK *x)
+{
+    MB_PREDICTION_MODE this_mode = x->e_mbd.mode_info_context->mbmi.mode;
+    int_mv mv = x->e_mbd.mode_info_context->mbmi.mv;
+    int this_rd;
+    /* Exit early and don't compute the distortion if this macroblock
+     * is marked inactive. */
+    if (cpi->active_map_enabled && x->active_ptr[0] == 0)
+    {
+        *sse = 0;
+        *distortion2 = 0;
+        x->skip = 1;
+        return INT_MAX;
+    }
+
+    if((this_mode != NEWMV) ||
+        !(cpi->sf.half_pixel_search) || cpi->common.full_pixel==1)
+        *distortion2 = get_inter_mbpred_error(x,
+                                              &cpi->fn_ptr[BLOCK_16X16],
+                                              sse, mv);
+
+    this_rd = RDCOST(x->rdmult, x->rddiv, rate2, *distortion2);
+
+    check_for_encode_breakout(*sse, x);
+    return this_rd;
+}
+
+void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
+                         int recon_uvoffset, int *returnrate,
+                         int *returndistortion, int *returnintra, int mb_row,
+                         int mb_col)
+{
+    BLOCK *b = &x->block[0];
+    BLOCKD *d = &x->e_mbd.block[0];
+    MACROBLOCKD *xd = &x->e_mbd;
+    MB_MODE_INFO best_mbmode;
+
+    int_mv best_ref_mv_sb[2];
+    int_mv mode_mv_sb[2][MB_MODE_COUNT];
+    int_mv best_ref_mv;
+    int_mv *mode_mv;
+    MB_PREDICTION_MODE this_mode;
+    int num00;
+    int mdcounts[4];
+    int best_rd = INT_MAX; // 1 << 30;
+    int best_intra_rd = INT_MAX;
+    int mode_index;
+    int rate;
+    int rate2;
+    int distortion2;
+    int bestsme = INT_MAX;
+    int best_mode_index = 0;
+    unsigned int sse = INT_MAX, best_rd_sse = INT_MAX;
+#if CONFIG_TEMPORAL_DENOISING
+    unsigned int zero_mv_sse = 0, best_sse = INT_MAX;
+#endif
+
+    int_mv mvp;
+
+    int near_sadidx[8] = {0, 1, 2, 3, 4, 5, 6, 7};
+    int saddone=0;
+    int sr=0;    //search range got from mv_pred(). It uses step_param levels. (0-7)
+
+    unsigned char *plane[4][3];
+    int ref_frame_map[4];
+    int sign_bias = 0;
+
+#if CONFIG_MULTI_RES_ENCODING
+    int dissim = INT_MAX;
+    int parent_ref_frame = 0;
+    int_mv parent_ref_mv;
+    MB_PREDICTION_MODE parent_mode = 0;
+
+    if (cpi->oxcf.mr_encoder_id)
+        get_lower_res_motion_info(cpi, xd, &dissim, &parent_ref_frame,
+                                  &parent_mode, &parent_ref_mv, mb_row, mb_col);
+#endif
+
+    mode_mv = mode_mv_sb[sign_bias];
+    best_ref_mv.as_int = 0;
+    vpx_memset(mode_mv_sb, 0, sizeof(mode_mv_sb));
+    vpx_memset(&best_mbmode, 0, sizeof(best_mbmode));
+
+    /* Setup search priorities */
+    get_reference_search_order(cpi, ref_frame_map);
+
+    /* Check to see if there is at least 1 valid reference frame that we need
+     * to calculate near_mvs.
+     */
+    if (ref_frame_map[1] > 0)
+    {
+        sign_bias = vp8_find_near_mvs_bias(&x->e_mbd,
+                                           x->e_mbd.mode_info_context,
+                                           mode_mv_sb,
+                                           best_ref_mv_sb,
+                                           mdcounts,
+                                           ref_frame_map[1],
+                                           cpi->common.ref_frame_sign_bias);
+
+        mode_mv = mode_mv_sb[sign_bias];
+        best_ref_mv.as_int = best_ref_mv_sb[sign_bias].as_int;
+    }
+
+    get_predictor_pointers(cpi, plane, recon_yoffset, recon_uvoffset);
+
+    cpi->mbs_tested_so_far++; // Count of the number of MBs tested so far this frame
+
+    *returnintra = INT_MAX;
+    x->skip = 0;
+
+    x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
+
+    // if we encode a new mv this is important
+    // find the best new motion vector
+    for (mode_index = 0; mode_index < MAX_MODES; mode_index++)
+    {
+        int frame_cost;
+        int this_rd = INT_MAX;
+        int this_ref_frame = ref_frame_map[vp8_ref_frame_order[mode_index]];
+
+        if (best_rd <= cpi->rd_threshes[mode_index])
+            continue;
+
+        if (this_ref_frame < 0)
+            continue;
+
+        x->e_mbd.mode_info_context->mbmi.ref_frame = this_ref_frame;
+
+#if CONFIG_MULTI_RES_ENCODING
+        if (cpi->oxcf.mr_encoder_id)
+        {
+            /* If parent MB is intra, child MB is intra. */
+            if (!parent_ref_frame && this_ref_frame)
+                continue;
+
+            /* If parent MB is inter, and it is unlikely there are multiple
+             * objects in parent MB, we use parent ref frame as child MB's
+             * ref frame. */
+            if (parent_ref_frame && dissim < 8
+                && parent_ref_frame != this_ref_frame)
+                continue;
+        }
+#endif
+
+        // everything but intra
+        if (x->e_mbd.mode_info_context->mbmi.ref_frame)
+        {
+            x->e_mbd.pre.y_buffer = plane[this_ref_frame][0];
+            x->e_mbd.pre.u_buffer = plane[this_ref_frame][1];
+            x->e_mbd.pre.v_buffer = plane[this_ref_frame][2];
+
+            if (sign_bias != cpi->common.ref_frame_sign_bias[this_ref_frame])
+            {
+                sign_bias = cpi->common.ref_frame_sign_bias[this_ref_frame];
+                mode_mv = mode_mv_sb[sign_bias];
+                best_ref_mv.as_int = best_ref_mv_sb[sign_bias].as_int;
+            }
+
+#if CONFIG_MULTI_RES_ENCODING
+            if (cpi->oxcf.mr_encoder_id)
+            {
+                if (vp8_mode_order[mode_index] == NEARESTMV &&
+                    mode_mv[NEARESTMV].as_int ==0)
+                    continue;
+                if (vp8_mode_order[mode_index] == NEARMV &&
+                    mode_mv[NEARMV].as_int ==0)
+                    continue;
+
+                if (vp8_mode_order[mode_index] == NEWMV && parent_mode == ZEROMV
+                    && best_ref_mv.as_int==0) //&& dissim==0
+                    continue;
+                else if(vp8_mode_order[mode_index] == NEWMV && dissim==0
+                    && best_ref_mv.as_int==parent_ref_mv.as_int)
+                    continue;
+            }
+#endif
+        }
+
+        /* Check to see if the testing frequency for this mode is at its max
+         * If so then prevent it from being tested and increase the threshold
+         * for its testing */
+        if (cpi->mode_test_hit_counts[mode_index] &&
+                                         (cpi->mode_check_freq[mode_index] > 1))
+        {
+            if (cpi->mbs_tested_so_far <= (cpi->mode_check_freq[mode_index] *
+                                         cpi->mode_test_hit_counts[mode_index]))
+            {
+                /* Increase the threshold for coding this mode to make it less
+                 * likely to be chosen */
+                cpi->rd_thresh_mult[mode_index] += 4;
+
+                if (cpi->rd_thresh_mult[mode_index] > MAX_THRESHMULT)
+                    cpi->rd_thresh_mult[mode_index] = MAX_THRESHMULT;
+
+                cpi->rd_threshes[mode_index] =
+                                 (cpi->rd_baseline_thresh[mode_index] >> 7) *
+                                 cpi->rd_thresh_mult[mode_index];
+                continue;
+            }
+        }
+
+        /* We have now reached the point where we are going to test the current
+         * mode so increment the counter for the number of times it has been
+         * tested */
+        cpi->mode_test_hit_counts[mode_index] ++;
+
+        rate2 = 0;
+        distortion2 = 0;
+
+        this_mode = vp8_mode_order[mode_index];
+
+        x->e_mbd.mode_info_context->mbmi.mode = this_mode;
+        x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
+
+        /* Work out the cost assosciated with selecting the reference frame */
+        frame_cost =
+            x->ref_frame_cost[x->e_mbd.mode_info_context->mbmi.ref_frame];
+        rate2 += frame_cost;
+
+        /* Only consider ZEROMV/ALTREF_FRAME for alt ref frame,
+         * unless ARNR filtering is enabled in which case we want
+         * an unfiltered alternative */
+        if (cpi->is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0))
+        {
+            if (this_mode != ZEROMV ||
+                x->e_mbd.mode_info_context->mbmi.ref_frame != ALTREF_FRAME)
+                continue;
+        }
+
+        switch (this_mode)
+        {
+        case B_PRED:
+            /* Pass best so far to pick_intra4x4mby_modes to use as breakout */
+            distortion2 = best_rd_sse;
+            pick_intra4x4mby_modes(x, &rate, &distortion2);
+
+            if (distortion2 == INT_MAX)
+            {
+                this_rd = INT_MAX;
+            }
+            else
+            {
+                rate2 += rate;
+                distortion2 = vp8_variance16x16(
+                                    *(b->base_src), b->src_stride,
+                                    x->e_mbd.predictor, 16, &sse);
+                this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
+
+                if (this_rd < best_intra_rd)
+                {
+                    best_intra_rd = this_rd;
+                    *returnintra = distortion2;
+                }
+            }
+
+            break;
+
+        case SPLITMV:
+
+            // Split MV modes currently not supported when RD is nopt enabled.
+            break;
+
+        case DC_PRED:
+        case V_PRED:
+        case H_PRED:
+        case TM_PRED:
+            vp8_build_intra_predictors_mby_s(xd,
+                                             xd->dst.y_buffer - xd->dst.y_stride,
+                                             xd->dst.y_buffer - 1,
+                                             xd->dst.y_stride,
+                                             xd->predictor,
+                                             16);
+            distortion2 = vp8_variance16x16
+                                          (*(b->base_src), b->src_stride,
+                                          x->e_mbd.predictor, 16, &sse);
+            rate2 += x->mbmode_cost[x->e_mbd.frame_type][x->e_mbd.mode_info_context->mbmi.mode];
+            this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
+
+            if (this_rd < best_intra_rd)
+            {
+                best_intra_rd = this_rd;
+                *returnintra = distortion2;
+            }
+            break;
+
+        case NEWMV:
+        {
+            int thissme;
+            int step_param;
+            int further_steps;
+            int n = 0;
+            int sadpb = x->sadperbit16;
+            int_mv mvp_full;
+
+            int col_min = ((best_ref_mv.as_mv.col+7)>>3) - MAX_FULL_PEL_VAL;
+            int row_min = ((best_ref_mv.as_mv.row+7)>>3) - MAX_FULL_PEL_VAL;
+            int col_max = (best_ref_mv.as_mv.col>>3)
+                         + MAX_FULL_PEL_VAL;
+            int row_max = (best_ref_mv.as_mv.row>>3)
+                         + MAX_FULL_PEL_VAL;
+
+            int tmp_col_min = x->mv_col_min;
+            int tmp_col_max = x->mv_col_max;
+            int tmp_row_min = x->mv_row_min;
+            int tmp_row_max = x->mv_row_max;
+
+            int speed_adjust = (cpi->Speed > 5) ? ((cpi->Speed >= 8)? 3 : 2) : 1;
+
+            // Further step/diamond searches as necessary
+            step_param = cpi->sf.first_step + speed_adjust;
+
+#if CONFIG_MULTI_RES_ENCODING
+            if (cpi->oxcf.mr_encoder_id)
+            {
+                // Use parent MV as predictor. Adjust search range accordingly.
+                mvp.as_int = parent_ref_mv.as_int;
+                mvp_full.as_mv.col = parent_ref_mv.as_mv.col>>3;
+                mvp_full.as_mv.row = parent_ref_mv.as_mv.row>>3;
+
+                if(dissim <=32) step_param += 3;
+                else if(dissim <=128) step_param += 2;
+                else step_param += 1;
+            }else
+#endif
+            {
+                if(cpi->sf.improved_mv_pred)
+                {
+                    if(!saddone)
+                    {
+                        vp8_cal_sad(cpi,xd,x, recon_yoffset ,&near_sadidx[0] );
+                        saddone = 1;
+                    }
+
+                    vp8_mv_pred(cpi, &x->e_mbd, x->e_mbd.mode_info_context,
+                                &mvp,x->e_mbd.mode_info_context->mbmi.ref_frame,
+                                cpi->common.ref_frame_sign_bias, &sr,
+                                &near_sadidx[0]);
+
+                    sr += speed_adjust;
+                    //adjust search range according to sr from mv prediction
+                    if(sr > step_param)
+                        step_param = sr;
+
+                    mvp_full.as_mv.col = mvp.as_mv.col>>3;
+                    mvp_full.as_mv.row = mvp.as_mv.row>>3;
+                }else
+                {
+                    mvp.as_int = best_ref_mv.as_int;
+                    mvp_full.as_mv.col = best_ref_mv.as_mv.col>>3;
+                    mvp_full.as_mv.row = best_ref_mv.as_mv.row>>3;
+                }
+            }
+
+#if CONFIG_MULTI_RES_ENCODING
+            if (cpi->oxcf.mr_encoder_id && dissim <= 2 &&
+                MAX(abs(best_ref_mv.as_mv.row - parent_ref_mv.as_mv.row),
+                    abs(best_ref_mv.as_mv.col - parent_ref_mv.as_mv.col)) <= 4)
+            {
+                d->bmi.mv.as_int = mvp_full.as_int;
+                mode_mv[NEWMV].as_int = mvp_full.as_int;
+
+                cpi->find_fractional_mv_step(x, b, d, &d->bmi.mv, &best_ref_mv,
+                                             x->errorperbit,
+                                             &cpi->fn_ptr[BLOCK_16X16],
+                                             cpi->mb.mvcost,
+                                             &distortion2,&sse);
+            }else
+#endif
+            {
+                /* Get intersection of UMV window and valid MV window to
+                 * reduce # of checks in diamond search. */
+                if (x->mv_col_min < col_min )
+                    x->mv_col_min = col_min;
+                if (x->mv_col_max > col_max )
+                    x->mv_col_max = col_max;
+                if (x->mv_row_min < row_min )
+                    x->mv_row_min = row_min;
+                if (x->mv_row_max > row_max )
+                    x->mv_row_max = row_max;
+
+                further_steps = (cpi->Speed >= 8)?
+                           0: (cpi->sf.max_step_search_steps - 1 - step_param);
+
+                if (cpi->sf.search_method == HEX)
+                {
+#if CONFIG_MULTI_RES_ENCODING
+                /* TODO: In higher-res pick_inter_mode, step_param is used to
+                 * modify hex search range. Here, set step_param to 0 not to
+                 * change the behavior in lowest-resolution encoder.
+                 * Will improve it later.
+                 */
+                if (!cpi->oxcf.mr_encoder_id)
+                    step_param = 0;
+#endif
+                    bestsme = vp8_hex_search(x, b, d, &mvp_full, &d->bmi.mv,
+                                          step_param, sadpb,
+                                          &cpi->fn_ptr[BLOCK_16X16],
+                                          x->mvsadcost, x->mvcost, &best_ref_mv);
+                    mode_mv[NEWMV].as_int = d->bmi.mv.as_int;
+                }
+                else
+                {
+                    bestsme = cpi->diamond_search_sad(x, b, d, &mvp_full,
+                                          &d->bmi.mv, step_param, sadpb, &num00,
+                                          &cpi->fn_ptr[BLOCK_16X16],
+                                          x->mvcost, &best_ref_mv);
+                    mode_mv[NEWMV].as_int = d->bmi.mv.as_int;
+
+                    // Further step/diamond searches as necessary
+                    n = 0;
+                    //further_steps = (cpi->sf.max_step_search_steps - 1) - step_param;
+
+                    n = num00;
+                    num00 = 0;
+
+                    while (n < further_steps)
+                    {
+                        n++;
+
+                        if (num00)
+                            num00--;
+                        else
+                        {
+                            thissme =
+                            cpi->diamond_search_sad(x, b, d, &mvp_full,
+                                                    &d->bmi.mv,
+                                                    step_param + n,
+                                                    sadpb, &num00,
+                                                    &cpi->fn_ptr[BLOCK_16X16],
+                                                    x->mvcost, &best_ref_mv);
+                            if (thissme < bestsme)
+                            {
+                                bestsme = thissme;
+                                mode_mv[NEWMV].as_int = d->bmi.mv.as_int;
+                            }
+                            else
+                            {
+                                d->bmi.mv.as_int = mode_mv[NEWMV].as_int;
+                            }
+                        }
+                    }
+                }
+
+                x->mv_col_min = tmp_col_min;
+                x->mv_col_max = tmp_col_max;
+                x->mv_row_min = tmp_row_min;
+                x->mv_row_max = tmp_row_max;
+
+                if (bestsme < INT_MAX)
+                    cpi->find_fractional_mv_step(x, b, d, &d->bmi.mv,
+                                             &best_ref_mv, x->errorperbit,
+                                             &cpi->fn_ptr[BLOCK_16X16],
+                                             cpi->mb.mvcost,
+                                             &distortion2,&sse);
+            }
+
+            mode_mv[NEWMV].as_int = d->bmi.mv.as_int;
+
+            // mv cost;
+            rate2 += vp8_mv_bit_cost(&mode_mv[NEWMV], &best_ref_mv,
+                                     cpi->mb.mvcost, 128);
+        }
+
+        case NEARESTMV:
+        case NEARMV:
+
+            if (mode_mv[this_mode].as_int == 0)
+                continue;
+
+        case ZEROMV:
+
+            /* Trap vectors that reach beyond the UMV borders
+             * Note that ALL New MV, Nearest MV Near MV and Zero MV code drops
+             * through to this point because of the lack of break statements
+             * in the previous two cases.
+             */
+            if (((mode_mv[this_mode].as_mv.row >> 3) < x->mv_row_min) ||
+                ((mode_mv[this_mode].as_mv.row >> 3) > x->mv_row_max) ||
+                ((mode_mv[this_mode].as_mv.col >> 3) < x->mv_col_min) ||
+                ((mode_mv[this_mode].as_mv.col >> 3) > x->mv_col_max))
+                continue;
+
+            rate2 += vp8_cost_mv_ref(this_mode, mdcounts);
+            x->e_mbd.mode_info_context->mbmi.mv.as_int =
+                                                    mode_mv[this_mode].as_int;
+            this_rd = evaluate_inter_mode(&sse, rate2, &distortion2, cpi, x);
+
+            break;
+        default:
+            break;
+        }
+
+#if CONFIG_TEMPORAL_DENOISING
+        if (cpi->oxcf.noise_sensitivity)
+        {
+          // Store for later use by denoiser.
+          if (this_mode == ZEROMV &&
+              x->e_mbd.mode_info_context->mbmi.ref_frame == LAST_FRAME)
+          {
+            zero_mv_sse = sse;
+          }
+
+          // Store the best NEWMV in x for later use in the denoiser.
+          // We are restricted to the LAST_FRAME since the denoiser only keeps
+          // one filter state.
+          if (x->e_mbd.mode_info_context->mbmi.mode == NEWMV &&
+              x->e_mbd.mode_info_context->mbmi.ref_frame == LAST_FRAME)
+          {
+            best_sse = sse;
+            x->e_mbd.best_sse_inter_mode = NEWMV;
+            x->e_mbd.best_sse_mv = x->e_mbd.mode_info_context->mbmi.mv;
+            x->e_mbd.need_to_clamp_best_mvs =
+                x->e_mbd.mode_info_context->mbmi.need_to_clamp_mvs;
+          }
+        }
+#endif
+
+        if (this_rd < best_rd || x->skip)
+        {
+            // Note index of best mode
+            best_mode_index = mode_index;
+
+            *returnrate = rate2;
+            *returndistortion = distortion2;
+            best_rd_sse = sse;
+            best_rd = this_rd;
+            vpx_memcpy(&best_mbmode, &x->e_mbd.mode_info_context->mbmi,
+                       sizeof(MB_MODE_INFO));
+
+            /* Testing this mode gave rise to an improvement in best error
+             * score. Lower threshold a bit for next time
+             */
+            cpi->rd_thresh_mult[mode_index] =
+                     (cpi->rd_thresh_mult[mode_index] >= (MIN_THRESHMULT + 2)) ?
+                     cpi->rd_thresh_mult[mode_index] - 2 : MIN_THRESHMULT;
+            cpi->rd_threshes[mode_index] =
+                                   (cpi->rd_baseline_thresh[mode_index] >> 7) *
+                                   cpi->rd_thresh_mult[mode_index];
+        }
+
+        /* If the mode did not help improve the best error case then raise the
+         * threshold for testing that mode next time around.
+         */
+        else
+        {
+            cpi->rd_thresh_mult[mode_index] += 4;
+
+            if (cpi->rd_thresh_mult[mode_index] > MAX_THRESHMULT)
+                cpi->rd_thresh_mult[mode_index] = MAX_THRESHMULT;
+
+            cpi->rd_threshes[mode_index] =
+                         (cpi->rd_baseline_thresh[mode_index] >> 7) *
+                         cpi->rd_thresh_mult[mode_index];
+        }
+
+        if (x->skip)
+            break;
+    }
+
+    // Reduce the activation RD thresholds for the best choice mode
+    if ((cpi->rd_baseline_thresh[best_mode_index] > 0) && (cpi->rd_baseline_thresh[best_mode_index] < (INT_MAX >> 2)))
+    {
+        int best_adjustment = (cpi->rd_thresh_mult[best_mode_index] >> 3);
+
+        cpi->rd_thresh_mult[best_mode_index] =
+                        (cpi->rd_thresh_mult[best_mode_index]
+                        >= (MIN_THRESHMULT + best_adjustment)) ?
+                        cpi->rd_thresh_mult[best_mode_index] - best_adjustment :
+                        MIN_THRESHMULT;
+        cpi->rd_threshes[best_mode_index] =
+                        (cpi->rd_baseline_thresh[best_mode_index] >> 7) *
+                        cpi->rd_thresh_mult[best_mode_index];
+    }
+
+
+    {
+        int this_rdbin = (*returndistortion >> 7);
+
+        if (this_rdbin >= 1024)
+        {
+            this_rdbin = 1023;
+        }
+
+        cpi->error_bins[this_rdbin] ++;
+    }
+
+#if CONFIG_TEMPORAL_DENOISING
+    if (cpi->oxcf.noise_sensitivity)
+    {
+      if (x->e_mbd.best_sse_inter_mode == DC_PRED) {
+        // No best MV found.
+        x->e_mbd.best_sse_inter_mode = best_mbmode.mode;
+        x->e_mbd.best_sse_mv = best_mbmode.mv;
+        x->e_mbd.need_to_clamp_best_mvs = best_mbmode.need_to_clamp_mvs;
+        best_sse = best_rd_sse;
+      }
+      vp8_denoiser_denoise_mb(&cpi->denoiser, x, best_sse, zero_mv_sse,
+                              recon_yoffset, recon_uvoffset);
+
+      // Reevaluate ZEROMV after denoising.
+      if (best_mbmode.ref_frame == INTRA_FRAME)
+      {
+        int this_rd = 0;
+        rate2 = 0;
+        distortion2 = 0;
+        x->e_mbd.mode_info_context->mbmi.ref_frame = LAST_FRAME;
+        rate2 += x->ref_frame_cost[x->e_mbd.mode_info_context->mbmi.ref_frame];
+        this_mode = ZEROMV;
+        rate2 += vp8_cost_mv_ref(this_mode, mdcounts);
+        x->e_mbd.mode_info_context->mbmi.mode = this_mode;
+        x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
+        x->e_mbd.mode_info_context->mbmi.mv.as_int = 0;
+        this_rd = evaluate_inter_mode(&sse, rate2, &distortion2, cpi, x);
+
+        if (this_rd < best_rd || x->skip)
+        {
+            vpx_memcpy(&best_mbmode, &x->e_mbd.mode_info_context->mbmi,
+                       sizeof(MB_MODE_INFO));
+        }
+      }
+    }
+#endif
+
+    if (cpi->is_src_frame_alt_ref &&
+        (best_mbmode.mode != ZEROMV || best_mbmode.ref_frame != ALTREF_FRAME))
+    {
+        x->e_mbd.mode_info_context->mbmi.mode = ZEROMV;
+        x->e_mbd.mode_info_context->mbmi.ref_frame = ALTREF_FRAME;
+        x->e_mbd.mode_info_context->mbmi.mv.as_int = 0;
+        x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
+        x->e_mbd.mode_info_context->mbmi.mb_skip_coeff =
+                                        (cpi->common.mb_no_coeff_skip);
+        x->e_mbd.mode_info_context->mbmi.partitioning = 0;
+
+        return;
+    }
+
+    /* set to the best mb mode, this copy can be skip if x->skip since it
+     * already has the right content */
+    if (!x->skip)
+        vpx_memcpy(&x->e_mbd.mode_info_context->mbmi, &best_mbmode,
+                   sizeof(MB_MODE_INFO));
+
+    if (best_mbmode.mode <= B_PRED)
+    {
+        /* set mode_info_context->mbmi.uv_mode */
+        pick_intra_mbuv_mode(x);
+    }
+
+    if (sign_bias
+      != cpi->common.ref_frame_sign_bias[xd->mode_info_context->mbmi.ref_frame])
+        best_ref_mv.as_int = best_ref_mv_sb[!sign_bias].as_int;
+
+    update_mvcount(cpi, &x->e_mbd, &best_ref_mv);
+}
+
+
+void vp8_pick_intra_mode(VP8_COMP *cpi, MACROBLOCK *x, int *rate_)
+{
+    int error4x4, error16x16 = INT_MAX;
+    int rate, best_rate = 0, distortion, best_sse;
+    MB_PREDICTION_MODE mode, best_mode = DC_PRED;
+    int this_rd;
+    unsigned int sse;
+    BLOCK *b = &x->block[0];
+    MACROBLOCKD *xd = &x->e_mbd;
+
+    xd->mode_info_context->mbmi.ref_frame = INTRA_FRAME;
+
+    pick_intra_mbuv_mode(x);
+
+    for (mode = DC_PRED; mode <= TM_PRED; mode ++)
+    {
+        xd->mode_info_context->mbmi.mode = mode;
+        vp8_build_intra_predictors_mby_s(xd,
+                                         xd->dst.y_buffer - xd->dst.y_stride,
+                                         xd->dst.y_buffer - 1,
+                                         xd->dst.y_stride,
+                                         xd->predictor,
+                                         16);
+        distortion = vp8_variance16x16
+            (*(b->base_src), b->src_stride, xd->predictor, 16, &sse);
+        rate = x->mbmode_cost[xd->frame_type][mode];
+        this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);
+
+        if (error16x16 > this_rd)
+        {
+            error16x16 = this_rd;
+            best_mode = mode;
+            best_sse = sse;
+            best_rate = rate;
+        }
+    }
+    xd->mode_info_context->mbmi.mode = best_mode;
+
+    error4x4 = pick_intra4x4mby_modes(x, &rate,
+                                      &best_sse);
+    if (error4x4 < error16x16)
+    {
+        xd->mode_info_context->mbmi.mode = B_PRED;
+        best_rate = rate;
+    }
+
+    *rate_ = best_rate;
+}
diff --git a/vp8/encoder/pickinter.h b/vp8/encoder/pickinter.h
new file mode 100644 (file)
index 0000000..3d83782
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_PICKINTER_H
+#define __INC_PICKINTER_H
+#include "vpx_config.h"
+#include "vp8/common/onyxc_int.h"
+
+extern void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
+                                int recon_uvoffset, int *returnrate,
+                                int *returndistortion, int *returnintra,
+                                int mb_row, int mb_col);
+extern void vp8_pick_intra_mode(VP8_COMP *cpi, MACROBLOCK *x, int *rate);
+
+#endif
diff --git a/vp8/encoder/picklpf.c b/vp8/encoder/picklpf.c
new file mode 100644 (file)
index 0000000..21af45a
--- /dev/null
@@ -0,0 +1,392 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vp8/common/onyxc_int.h"
+#include "onyx_int.h"
+#include "quantize.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_scale/vpxscale.h"
+#include "vp8/common/alloccommon.h"
+#include "vp8/common/loopfilter.h"
+#if ARCH_ARM
+#include "vpx_ports/arm.h"
+#endif
+
+extern int vp8_calc_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest);
+
+void vp8_yv12_copy_partial_frame_c(YV12_BUFFER_CONFIG *src_ybc,
+                                   YV12_BUFFER_CONFIG *dst_ybc)
+{
+    unsigned char *src_y, *dst_y;
+    int yheight;
+    int ystride;
+    int yoffset;
+    int linestocopy;
+
+    yheight  = src_ybc->y_height;
+    ystride  = src_ybc->y_stride;
+
+    /* number of MB rows to use in partial filtering */
+    linestocopy = (yheight >> 4) / PARTIAL_FRAME_FRACTION;
+    linestocopy = linestocopy ? linestocopy << 4 : 16;     /* 16 lines per MB */
+
+    /* Copy extra 4 so that full filter context is available if filtering done
+     * on the copied partial frame and not original. Partial filter does mb
+     * filtering for top row also, which can modify3 pixels above.
+     */
+    linestocopy += 4;
+    /* partial image starts at ~middle of frame (macroblock border)*/
+    yoffset  = ystride * (((yheight >> 5) * 16) - 4);
+    src_y = src_ybc->y_buffer + yoffset;
+    dst_y = dst_ybc->y_buffer + yoffset;
+
+    vpx_memcpy(dst_y, src_y, ystride * linestocopy);
+}
+
+static int calc_partial_ssl_err(YV12_BUFFER_CONFIG *source,
+                                YV12_BUFFER_CONFIG *dest)
+{
+    int i, j;
+    int Total = 0;
+    int srcoffset, dstoffset;
+    unsigned char *src = source->y_buffer;
+    unsigned char *dst = dest->y_buffer;
+
+    int linestocopy;
+
+    /* number of MB rows to use in partial filtering */
+    linestocopy = (source->y_height >> 4) / PARTIAL_FRAME_FRACTION;
+    linestocopy = linestocopy ? linestocopy << 4 : 16;     /* 16 lines per MB */
+
+
+    /* partial image starts at ~middle of frame (macroblock border)*/
+    srcoffset = source->y_stride * ((dest->y_height >> 5) * 16);
+    dstoffset = dest->y_stride   * ((dest->y_height >> 5) * 16);
+
+    src += srcoffset;
+    dst += dstoffset;
+
+    // Loop through the Y plane raw and reconstruction data summing (square differences)
+    for (i = 0; i < linestocopy; i += 16)
+    {
+        for (j = 0; j < source->y_width; j += 16)
+        {
+            unsigned int sse;
+            Total += vp8_mse16x16(src + j, source->y_stride,
+                                                     dst + j, dest->y_stride,
+                                                     &sse);
+        }
+
+        src += 16 * source->y_stride;
+        dst += 16 * dest->y_stride;
+    }
+
+    return Total;
+}
+
+// Enforce a minimum filter level based upon baseline Q
+static int get_min_filter_level(VP8_COMP *cpi, int base_qindex)
+{
+    int min_filter_level;
+
+    if (cpi->source_alt_ref_active && cpi->common.refresh_golden_frame &&
+        !cpi->common.refresh_alt_ref_frame)
+        min_filter_level = 0;
+    else
+    {
+        if (base_qindex <= 6)
+            min_filter_level = 0;
+        else if (base_qindex <= 16)
+            min_filter_level = 1;
+        else
+            min_filter_level = (base_qindex / 8);
+    }
+
+    return min_filter_level;
+}
+
+// Enforce a maximum filter level based upon baseline Q
+static int get_max_filter_level(VP8_COMP *cpi, int base_qindex)
+{
+    // PGW August 2006: Highest filter values almost always a bad idea
+
+    // jbb chg: 20100118 - not so any more with this overquant stuff allow high values
+    // with lots of intra coming in.
+    int max_filter_level = MAX_LOOP_FILTER ;//* 3 / 4;
+    (void)base_qindex;
+
+    if (cpi->twopass.section_intra_rating > 8)
+        max_filter_level = MAX_LOOP_FILTER * 3 / 4;
+
+    return max_filter_level;
+}
+
+void vp8cx_pick_filter_level_fast(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = &cpi->common;
+
+    int best_err = 0;
+    int filt_err = 0;
+    int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
+    int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
+    int filt_val;
+    int best_filt_val = cm->filter_level;
+    YV12_BUFFER_CONFIG * saved_frame = cm->frame_to_show;
+
+    /* Replace unfiltered frame buffer with a new one */
+    cm->frame_to_show = &cpi->pick_lf_lvl_frame;
+
+    if (cm->frame_type == KEY_FRAME)
+        cm->sharpness_level = 0;
+    else
+        cm->sharpness_level = cpi->oxcf.Sharpness;
+
+    if (cm->sharpness_level != cm->last_sharpness_level)
+    {
+        vp8_loop_filter_update_sharpness(&cm->lf_info, cm->sharpness_level);
+        cm->last_sharpness_level = cm->sharpness_level;
+    }
+
+    // Start the search at the previous frame filter level unless it is now out of range.
+    if (cm->filter_level < min_filter_level)
+        cm->filter_level = min_filter_level;
+    else if (cm->filter_level > max_filter_level)
+        cm->filter_level = max_filter_level;
+
+    filt_val = cm->filter_level;
+    best_filt_val = filt_val;
+
+    // Get the err using the previous frame's filter value.
+
+    /* Copy the unfiltered / processed recon buffer to the new buffer */
+    vp8_yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
+    vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
+
+    best_err = calc_partial_ssl_err(sd, cm->frame_to_show);
+
+    filt_val -= 1 + (filt_val > 10);
+
+    // Search lower filter levels
+    while (filt_val >= min_filter_level)
+    {
+        // Apply the loop filter
+        vp8_yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
+        vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
+
+        // Get the err for filtered frame
+        filt_err = calc_partial_ssl_err(sd, cm->frame_to_show);
+
+        // Update the best case record or exit loop.
+        if (filt_err < best_err)
+        {
+            best_err = filt_err;
+            best_filt_val = filt_val;
+        }
+        else
+            break;
+
+        // Adjust filter level
+        filt_val -= 1 + (filt_val > 10);
+    }
+
+    // Search up (note that we have already done filt_val = cm->filter_level)
+    filt_val = cm->filter_level + 1 + (filt_val > 10);
+
+    if (best_filt_val == cm->filter_level)
+    {
+        // Resist raising filter level for very small gains
+        best_err -= (best_err >> 10);
+
+        while (filt_val < max_filter_level)
+        {
+            // Apply the loop filter
+            vp8_yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
+
+            vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
+
+            // Get the err for filtered frame
+            filt_err = calc_partial_ssl_err(sd, cm->frame_to_show);
+
+            // Update the best case record or exit loop.
+            if (filt_err < best_err)
+            {
+                // Do not raise filter level if improvement is < 1 part in 4096
+                best_err = filt_err - (filt_err >> 10);
+
+                best_filt_val = filt_val;
+            }
+            else
+                break;
+
+            // Adjust filter level
+            filt_val += 1 + (filt_val > 10);
+        }
+    }
+
+    cm->filter_level = best_filt_val;
+
+    if (cm->filter_level < min_filter_level)
+        cm->filter_level = min_filter_level;
+
+    if (cm->filter_level > max_filter_level)
+        cm->filter_level = max_filter_level;
+
+    /* restore unfiltered frame pointer */
+    cm->frame_to_show = saved_frame;
+}
+
+// Stub function for now Alt LF not used
+void vp8cx_set_alt_lf_level(VP8_COMP *cpi, int filt_val)
+{
+    MACROBLOCKD *mbd = &cpi->mb.e_mbd;
+    (void) filt_val;
+
+    mbd->segment_feature_data[MB_LVL_ALT_LF][0] = cpi->segment_feature_data[MB_LVL_ALT_LF][0];
+    mbd->segment_feature_data[MB_LVL_ALT_LF][1] = cpi->segment_feature_data[MB_LVL_ALT_LF][1];
+    mbd->segment_feature_data[MB_LVL_ALT_LF][2] = cpi->segment_feature_data[MB_LVL_ALT_LF][2];
+    mbd->segment_feature_data[MB_LVL_ALT_LF][3] = cpi->segment_feature_data[MB_LVL_ALT_LF][3];
+}
+
+void vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = &cpi->common;
+
+    int best_err = 0;
+    int filt_err = 0;
+    int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
+    int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
+
+    int filter_step;
+    int filt_high = 0;
+    int filt_mid = cm->filter_level;      // Start search at previous frame filter level
+    int filt_low = 0;
+    int filt_best;
+    int filt_direction = 0;
+
+    int Bias = 0;                       // Bias against raising loop filter and in favor of lowering it
+
+    int ss_err[MAX_LOOP_FILTER + 1];
+
+    YV12_BUFFER_CONFIG * saved_frame = cm->frame_to_show;
+
+    vpx_memset(ss_err, 0, sizeof(ss_err));
+
+    /* Replace unfiltered frame buffer with a new one */
+    cm->frame_to_show = &cpi->pick_lf_lvl_frame;
+
+    if (cm->frame_type == KEY_FRAME)
+        cm->sharpness_level = 0;
+    else
+        cm->sharpness_level = cpi->oxcf.Sharpness;
+
+    // Start the search at the previous frame filter level unless it is now out of range.
+    filt_mid = cm->filter_level;
+
+    if (filt_mid < min_filter_level)
+        filt_mid = min_filter_level;
+    else if (filt_mid > max_filter_level)
+        filt_mid = max_filter_level;
+
+    // Define the initial step size
+    filter_step = (filt_mid < 16) ? 4 : filt_mid / 4;
+
+    // Get baseline error score
+
+    /* Copy the unfiltered / processed recon buffer to the new buffer */
+    vp8_yv12_copy_y(saved_frame, cm->frame_to_show);
+
+    vp8cx_set_alt_lf_level(cpi, filt_mid);
+    vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_mid);
+
+    best_err = vp8_calc_ss_err(sd, cm->frame_to_show);
+
+    ss_err[filt_mid] = best_err;
+
+    filt_best = filt_mid;
+
+    while (filter_step > 0)
+    {
+        Bias = (best_err >> (15 - (filt_mid / 8))) * filter_step; //PGW change 12/12/06 for small images
+
+        // jbb chg: 20100118 - in sections with lots of new material coming in don't bias as much to a low filter value
+        if (cpi->twopass.section_intra_rating < 20)
+            Bias = Bias * cpi->twopass.section_intra_rating / 20;
+
+        filt_high = ((filt_mid + filter_step) > max_filter_level) ? max_filter_level : (filt_mid + filter_step);
+        filt_low = ((filt_mid - filter_step) < min_filter_level) ? min_filter_level : (filt_mid - filter_step);
+
+        if ((filt_direction <= 0) && (filt_low != filt_mid))
+        {
+            if(ss_err[filt_low] == 0)
+            {
+                // Get Low filter error score
+                vp8_yv12_copy_y(saved_frame, cm->frame_to_show);
+                vp8cx_set_alt_lf_level(cpi, filt_low);
+                vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_low);
+
+                filt_err = vp8_calc_ss_err(sd, cm->frame_to_show);
+                ss_err[filt_low] = filt_err;
+            }
+            else
+                filt_err = ss_err[filt_low];
+
+            // If value is close to the best so far then bias towards a lower loop filter value.
+            if ((filt_err - Bias) < best_err)
+            {
+                // Was it actually better than the previous best?
+                if (filt_err < best_err)
+                    best_err = filt_err;
+
+                filt_best = filt_low;
+            }
+        }
+
+        // Now look at filt_high
+        if ((filt_direction >= 0) && (filt_high != filt_mid))
+        {
+            if(ss_err[filt_high] == 0)
+            {
+                vp8_yv12_copy_y(saved_frame, cm->frame_to_show);
+                vp8cx_set_alt_lf_level(cpi, filt_high);
+                vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_high);
+
+                filt_err = vp8_calc_ss_err(sd, cm->frame_to_show);
+                ss_err[filt_high] = filt_err;
+            }
+            else
+                filt_err = ss_err[filt_high];
+
+            // Was it better than the previous best?
+            if (filt_err < (best_err - Bias))
+            {
+                best_err = filt_err;
+                filt_best = filt_high;
+            }
+        }
+
+        // Half the step distance if the best filter value was the same as last time
+        if (filt_best == filt_mid)
+        {
+            filter_step = filter_step / 2;
+            filt_direction = 0;
+        }
+        else
+        {
+            filt_direction = (filt_best < filt_mid) ? -1 : 1;
+            filt_mid = filt_best;
+        }
+    }
+
+    cm->filter_level = filt_best;
+
+    /* restore unfiltered frame pointer */
+    cm->frame_to_show = saved_frame;
+}
diff --git a/vp8/encoder/ppc/csystemdependent.c b/vp8/encoder/ppc/csystemdependent.c
new file mode 100644 (file)
index 0000000..63f2357
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vp8/encoder/variance.h"
+#include "vp8/encoder/onyx_int.h"
+
+SADFunction *vp8_sad16x16;
+SADFunction *vp8_sad16x8;
+SADFunction *vp8_sad8x16;
+SADFunction *vp8_sad8x8;
+SADFunction *vp8_sad4x4;
+
+variance_function *vp8_variance4x4;
+variance_function *vp8_variance8x8;
+variance_function *vp8_variance8x16;
+variance_function *vp8_variance16x8;
+variance_function *vp8_variance16x16;
+
+variance_function *vp8_mse16x16;
+
+sub_pixel_variance_function *vp8_sub_pixel_variance4x4;
+sub_pixel_variance_function *vp8_sub_pixel_variance8x8;
+sub_pixel_variance_function *vp8_sub_pixel_variance8x16;
+sub_pixel_variance_function *vp8_sub_pixel_variance16x8;
+sub_pixel_variance_function *vp8_sub_pixel_variance16x16;
+
+int (*vp8_block_error)(short *coeff, short *dqcoeff);
+int (*vp8_mbblock_error)(MACROBLOCK *mb, int dc);
+
+int (*vp8_mbuverror)(MACROBLOCK *mb);
+unsigned int (*vp8_get_mb_ss)(short *);
+void (*vp8_short_fdct4x4)(short *input, short *output, int pitch);
+void (*vp8_short_fdct8x4)(short *input, short *output, int pitch);
+void (*vp8_fast_fdct4x4)(short *input, short *output, int pitch);
+void (*vp8_fast_fdct8x4)(short *input, short *output, int pitch);
+void (*short_walsh4x4)(short *input, short *output, int pitch);
+
+void (*vp8_subtract_b)(BLOCK *be, BLOCKD *bd, int pitch);
+void (*vp8_subtract_mby)(short *diff, unsigned char *src, unsigned char *pred, int stride);
+void (*vp8_subtract_mbuv)(short *diff, unsigned char *usrc, unsigned char *vsrc, unsigned char *pred, int stride);
+void (*vp8_fast_quantize_b)(BLOCK *b, BLOCKD *d);
+
+unsigned int (*vp8_get4x4sse_cs)(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride);
+
+// c imports
+extern int block_error_c(short *coeff, short *dqcoeff);
+extern int vp8_mbblock_error_c(MACROBLOCK *mb, int dc);
+
+extern int vp8_mbuverror_c(MACROBLOCK *mb);
+extern unsigned int vp8_get8x8var_c(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride, unsigned int *SSE, int *Sum);
+extern void short_fdct4x4_c(short *input, short *output, int pitch);
+extern void short_fdct8x4_c(short *input, short *output, int pitch);
+extern void vp8_short_walsh4x4_c(short *input, short *output, int pitch);
+
+extern void vp8_subtract_b_c(BLOCK *be, BLOCKD *bd, int pitch);
+extern void subtract_mby_c(short *diff, unsigned char *src, unsigned char *pred, int stride);
+extern void subtract_mbuv_c(short *diff, unsigned char *usrc, unsigned char *vsrc, unsigned char *pred, int stride);
+extern void vp8_fast_quantize_b_c(BLOCK *b, BLOCKD *d);
+
+extern SADFunction sad16x16_c;
+extern SADFunction sad16x8_c;
+extern SADFunction sad8x16_c;
+extern SADFunction sad8x8_c;
+extern SADFunction sad4x4_c;
+
+extern variance_function variance16x16_c;
+extern variance_function variance8x16_c;
+extern variance_function variance16x8_c;
+extern variance_function variance8x8_c;
+extern variance_function variance4x4_c;
+extern variance_function mse16x16_c;
+
+extern sub_pixel_variance_function sub_pixel_variance4x4_c;
+extern sub_pixel_variance_function sub_pixel_variance8x8_c;
+extern sub_pixel_variance_function sub_pixel_variance8x16_c;
+extern sub_pixel_variance_function sub_pixel_variance16x8_c;
+extern sub_pixel_variance_function sub_pixel_variance16x16_c;
+
+extern unsigned int vp8_get_mb_ss_c(short *);
+extern unsigned int vp8_get4x4sse_cs_c(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride);
+
+// ppc
+extern int vp8_block_error_ppc(short *coeff, short *dqcoeff);
+
+extern void vp8_short_fdct4x4_ppc(short *input, short *output, int pitch);
+extern void vp8_short_fdct8x4_ppc(short *input, short *output, int pitch);
+
+extern void vp8_subtract_mby_ppc(short *diff, unsigned char *src, unsigned char *pred, int stride);
+extern void vp8_subtract_mbuv_ppc(short *diff, unsigned char *usrc, unsigned char *vsrc, unsigned char *pred, int stride);
+
+extern SADFunction vp8_sad16x16_ppc;
+extern SADFunction vp8_sad16x8_ppc;
+extern SADFunction vp8_sad8x16_ppc;
+extern SADFunction vp8_sad8x8_ppc;
+extern SADFunction vp8_sad4x4_ppc;
+
+extern variance_function vp8_variance16x16_ppc;
+extern variance_function vp8_variance8x16_ppc;
+extern variance_function vp8_variance16x8_ppc;
+extern variance_function vp8_variance8x8_ppc;
+extern variance_function vp8_variance4x4_ppc;
+extern variance_function vp8_mse16x16_ppc;
+
+extern sub_pixel_variance_function vp8_sub_pixel_variance4x4_ppc;
+extern sub_pixel_variance_function vp8_sub_pixel_variance8x8_ppc;
+extern sub_pixel_variance_function vp8_sub_pixel_variance8x16_ppc;
+extern sub_pixel_variance_function vp8_sub_pixel_variance16x8_ppc;
+extern sub_pixel_variance_function vp8_sub_pixel_variance16x16_ppc;
+
+extern unsigned int vp8_get8x8var_ppc(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride, unsigned int *SSE, int *Sum);
+extern unsigned int vp8_get16x16var_ppc(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride, unsigned int *SSE, int *Sum);
+
+void vp8_cmachine_specific_config(void)
+{
+    // Pure C:
+    vp8_mbuverror               = vp8_mbuverror_c;
+    vp8_fast_quantize_b           = vp8_fast_quantize_b_c;
+    vp8_short_fdct4x4            = vp8_short_fdct4x4_ppc;
+    vp8_short_fdct8x4            = vp8_short_fdct8x4_ppc;
+    vp8_fast_fdct4x4             = vp8_short_fdct4x4_ppc;
+    vp8_fast_fdct8x4             = vp8_short_fdct8x4_ppc;
+    short_walsh4x4               = vp8_short_walsh4x4_c;
+
+    vp8_variance4x4             = vp8_variance4x4_ppc;
+    vp8_variance8x8             = vp8_variance8x8_ppc;
+    vp8_variance8x16            = vp8_variance8x16_ppc;
+    vp8_variance16x8            = vp8_variance16x8_ppc;
+    vp8_variance16x16           = vp8_variance16x16_ppc;
+    vp8_mse16x16                = vp8_mse16x16_ppc;
+
+    vp8_sub_pixel_variance4x4     = vp8_sub_pixel_variance4x4_ppc;
+    vp8_sub_pixel_variance8x8     = vp8_sub_pixel_variance8x8_ppc;
+    vp8_sub_pixel_variance8x16    = vp8_sub_pixel_variance8x16_ppc;
+    vp8_sub_pixel_variance16x8    = vp8_sub_pixel_variance16x8_ppc;
+    vp8_sub_pixel_variance16x16   = vp8_sub_pixel_variance16x16_ppc;
+
+    vp8_get_mb_ss                 = vp8_get_mb_ss_c;
+    vp8_get4x4sse_cs            = vp8_get4x4sse_cs_c;
+
+    vp8_sad16x16                = vp8_sad16x16_ppc;
+    vp8_sad16x8                 = vp8_sad16x8_ppc;
+    vp8_sad8x16                 = vp8_sad8x16_ppc;
+    vp8_sad8x8                  = vp8_sad8x8_ppc;
+    vp8_sad4x4                  = vp8_sad4x4_ppc;
+
+    vp8_block_error              = vp8_block_error_ppc;
+    vp8_mbblock_error            = vp8_mbblock_error_c;
+
+    vp8_subtract_b               = vp8_subtract_b_c;
+    vp8_subtract_mby             = vp8_subtract_mby_ppc;
+    vp8_subtract_mbuv            = vp8_subtract_mbuv_ppc;
+}
diff --git a/vp8/encoder/ppc/encodemb_altivec.asm b/vp8/encoder/ppc/encodemb_altivec.asm
new file mode 100644 (file)
index 0000000..6e0099d
--- /dev/null
@@ -0,0 +1,153 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    .globl vp8_subtract_mbuv_ppc
+    .globl vp8_subtract_mby_ppc
+
+;# r3 short *diff
+;# r4 unsigned char *usrc
+;# r5 unsigned char *vsrc
+;# r6 unsigned char *pred
+;# r7 int stride
+vp8_subtract_mbuv_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xf000
+    mtspr   256, r12            ;# set VRSAVE
+
+    li      r9, 256
+    add     r3, r3, r9
+    add     r3, r3, r9
+    add     r6, r6, r9
+
+    li      r10, 16
+    li      r9,  4
+    mtctr   r9
+
+    vspltisw v0, 0
+
+mbu_loop:
+    lvsl    v5, 0, r4           ;# permutate value for alignment
+    lvx     v1, 0, r4           ;# src
+    lvx     v2, 0, r6           ;# pred
+
+    add     r4, r4, r7
+    addi    r6, r6, 16
+
+    vperm   v1, v1, v0, v5
+
+    vmrghb  v3, v0, v1          ;# unpack high src  to short
+    vmrghb  v4, v0, v2          ;# unpack high pred to short
+
+    lvsl    v5, 0, r4           ;# permutate value for alignment
+    lvx     v1, 0, r4           ;# src
+
+    add     r4, r4, r7
+
+    vsubshs v3, v3, v4
+
+    stvx    v3, 0, r3           ;# store out diff
+
+    vperm   v1, v1, v0, v5
+
+    vmrghb  v3, v0, v1          ;# unpack high src  to short
+    vmrglb  v4, v0, v2          ;# unpack high pred to short
+
+    vsubshs v3, v3, v4
+
+    stvx    v3, r10, r3         ;# store out diff
+
+    addi    r3, r3, 32
+
+    bdnz    mbu_loop
+
+    mtctr   r9
+
+mbv_loop:
+    lvsl    v5, 0, r5           ;# permutate value for alignment
+    lvx     v1, 0, r5           ;# src
+    lvx     v2, 0, r6           ;# pred
+
+    add     r5, r5, r7
+    addi    r6, r6, 16
+
+    vperm   v1, v1, v0, v5
+
+    vmrghb  v3, v0, v1          ;# unpack high src  to short
+    vmrghb  v4, v0, v2          ;# unpack high pred to short
+
+    lvsl    v5, 0, r5           ;# permutate value for alignment
+    lvx     v1, 0, r5           ;# src
+
+    add     r5, r5, r7
+
+    vsubshs v3, v3, v4
+
+    stvx    v3, 0, r3           ;# store out diff
+
+    vperm   v1, v1, v0, v5
+
+    vmrghb  v3, v0, v1          ;# unpack high src  to short
+    vmrglb  v4, v0, v2          ;# unpack high pred to short
+
+    vsubshs v3, v3, v4
+
+    stvx    v3, r10, r3         ;# store out diff
+
+    addi    r3, r3, 32
+
+    bdnz    mbv_loop
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+;# r3 short *diff
+;# r4 unsigned char *src
+;# r5 unsigned char *pred
+;# r6 int stride
+vp8_subtract_mby_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xf800
+    mtspr   256, r12            ;# set VRSAVE
+
+    li      r10, 16
+    mtctr   r10
+
+    vspltisw v0, 0
+
+mby_loop:
+    lvx     v1, 0, r4           ;# src
+    lvx     v2, 0, r5           ;# pred
+
+    add     r4, r4, r6
+    addi    r5, r5, 16
+
+    vmrghb  v3, v0, v1          ;# unpack high src  to short
+    vmrghb  v4, v0, v2          ;# unpack high pred to short
+
+    vsubshs v3, v3, v4
+
+    stvx    v3, 0, r3           ;# store out diff
+
+    vmrglb  v3, v0, v1          ;# unpack low src  to short
+    vmrglb  v4, v0, v2          ;# unpack low pred to short
+
+    vsubshs v3, v3, v4
+
+    stvx    v3, r10, r3         ;# store out diff
+
+    addi    r3, r3, 32
+
+    bdnz    mby_loop
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
diff --git a/vp8/encoder/ppc/fdct_altivec.asm b/vp8/encoder/ppc/fdct_altivec.asm
new file mode 100644 (file)
index 0000000..935d0cb
--- /dev/null
@@ -0,0 +1,205 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    .globl vp8_short_fdct4x4_ppc
+    .globl vp8_short_fdct8x4_ppc
+
+.macro load_c V, LABEL, OFF, R0, R1
+    lis     \R0, \LABEL@ha
+    la      \R1, \LABEL@l(\R0)
+    lvx     \V, \OFF, \R1
+.endm
+
+;# Forward and inverse DCTs are nearly identical; only differences are
+;#   in normalization (fwd is twice unitary, inv is half unitary)
+;#   and that they are of course transposes of each other.
+;#
+;#   The following three accomplish most of implementation and
+;#   are used only by ppc_idct.c and ppc_fdct.c.
+.macro prologue
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xfffc
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    li      r6, 16
+
+    load_c v0, dct_tab, 0, r9, r10
+    lvx     v1,   r6, r10
+    addi    r10, r10, 32
+    lvx     v2,    0, r10
+    lvx     v3,   r6, r10
+
+    load_c v4, ppc_dctperm_tab,  0, r9, r10
+    load_c v5, ppc_dctperm_tab, r6, r9, r10
+
+    load_c v6, round_tab, 0, r10, r9
+.endm
+
+.macro epilogue
+    addi    r1, r1, 32          ;# recover stack
+
+    mtspr   256, r11            ;# reset old VRSAVE
+.endm
+
+;# Do horiz xf on two rows of coeffs  v8 = a0 a1 a2 a3  b0 b1 b2 b3.
+;#   a/A are the even rows 0,2   b/B are the odd rows 1,3
+;#   For fwd transform, indices are horizontal positions, then frequencies.
+;#   For inverse transform, frequencies then positions.
+;#   The two resulting  A0..A3  B0..B3  are later combined
+;#   and vertically transformed.
+
+.macro two_rows_horiz Dst
+    vperm   v9, v8, v8, v4      ;# v9 = a2 a3 a0 a1  b2 b3 b0 b1
+
+    vmsumshm v10, v0, v8, v6
+    vmsumshm v10, v1, v9, v10
+    vsraw   v10, v10, v7        ;# v10 = A0 A1  B0 B1
+
+    vmsumshm v11, v2, v8, v6
+    vmsumshm v11, v3, v9, v11
+    vsraw   v11, v11, v7        ;# v11 = A2 A3  B2 B3
+
+    vpkuwum v10, v10, v11       ;# v10  = A0 A1  B0 B1  A2 A3  B2 B3
+    vperm   \Dst, v10, v10, v5  ;# Dest = A0 B0  A1 B1  A2 B2  A3 B3
+.endm
+
+;# Vertical xf on two rows. DCT values in comments are for inverse transform;
+;#   forward transform uses transpose.
+
+.macro two_rows_vert Ceven, Codd
+    vspltw  v8, \Ceven, 0       ;# v8 = c00 c10  or  c02 c12 four times
+    vspltw  v9, \Codd,  0       ;# v9 = c20 c30  or  c22 c32 ""
+    vmsumshm v8, v8, v12, v6
+    vmsumshm v8, v9, v13, v8
+    vsraw   v10, v8, v7
+
+    vspltw  v8, \Codd,  1       ;# v8 = c01 c11  or  c03 c13
+    vspltw  v9, \Ceven, 1       ;# v9 = c21 c31  or  c23 c33
+    vmsumshm v8, v8, v12, v6
+    vmsumshm v8, v9, v13, v8
+    vsraw   v8, v8, v7
+
+    vpkuwum v8, v10, v8         ;# v8 = rows 0,1  or 2,3
+.endm
+
+.macro two_rows_h Dest
+    stw     r0,  0(r8)
+    lwz     r0,  4(r3)
+    stw     r0,  4(r8)
+    lwzux   r0, r3,r5
+    stw     r0,  8(r8)
+    lwz     r0,  4(r3)
+    stw     r0, 12(r8)
+    lvx     v8,  0,r8
+    two_rows_horiz \Dest
+.endm
+
+    .align 2
+;# r3 short *input
+;# r4 short *output
+;# r5 int pitch
+vp8_short_fdct4x4_ppc:
+
+    prologue
+
+    vspltisw v7, 14             ;# == 14, fits in 5 signed bits
+    addi    r8, r1, 0
+
+
+    lwz     r0, 0(r3)
+    two_rows_h v12                ;# v12 = H00 H10  H01 H11  H02 H12  H03 H13
+
+    lwzux   r0, r3, r5
+    two_rows_h v13                ;# v13 = H20 H30  H21 H31  H22 H32  H23 H33
+
+    lvx     v6, r6, r9          ;# v6 = Vround
+    vspltisw v7, -16            ;# == 16 == -16, only low 5 bits matter
+
+    two_rows_vert v0, v1
+    stvx    v8, 0, r4
+    two_rows_vert v2, v3
+    stvx    v8, r6, r4
+
+    epilogue
+
+    blr
+
+    .align 2
+;# r3 short *input
+;# r4 short *output
+;# r5 int pitch
+vp8_short_fdct8x4_ppc:
+    prologue
+
+    vspltisw v7, 14             ;# == 14, fits in 5 signed bits
+    addi    r8,  r1, 0
+    addi    r10, r3, 0
+
+    lwz     r0, 0(r3)
+    two_rows_h v12                ;# v12 = H00 H10  H01 H11  H02 H12  H03 H13
+
+    lwzux   r0, r3, r5
+    two_rows_h v13                ;# v13 = H20 H30  H21 H31  H22 H32  H23 H33
+
+    lvx     v6, r6, r9          ;# v6 = Vround
+    vspltisw v7, -16            ;# == 16 == -16, only low 5 bits matter
+
+    two_rows_vert v0, v1
+    stvx    v8, 0, r4
+    two_rows_vert v2, v3
+    stvx    v8, r6, r4
+
+    ;# Next block
+    addi    r3, r10, 8
+    addi    r4, r4, 32
+    lvx     v6, 0, r9           ;# v6 = Hround
+
+    vspltisw v7, 14             ;# == 14, fits in 5 signed bits
+    addi    r8, r1, 0
+
+    lwz     r0, 0(r3)
+    two_rows_h v12                ;# v12 = H00 H10  H01 H11  H02 H12  H03 H13
+
+    lwzux   r0, r3, r5
+    two_rows_h v13                ;# v13 = H20 H30  H21 H31  H22 H32  H23 H33
+
+    lvx     v6, r6, r9          ;# v6 = Vround
+    vspltisw v7, -16            ;# == 16 == -16, only low 5 bits matter
+
+    two_rows_vert v0, v1
+    stvx    v8, 0, r4
+    two_rows_vert v2, v3
+    stvx    v8, r6, r4
+
+    epilogue
+
+    blr
+
+    .data
+    .align 4
+ppc_dctperm_tab:
+    .byte 4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11
+    .byte 0,1,4,5, 2,3,6,7, 8,9,12,13, 10,11,14,15
+
+    .align 4
+dct_tab:
+    .short  23170, 23170,-12540,-30274, 23170, 23170,-12540,-30274
+    .short  23170, 23170, 30274, 12540, 23170, 23170, 30274, 12540
+
+    .short  23170,-23170, 30274,-12540, 23170,-23170, 30274,-12540
+    .short -23170, 23170, 12540,-30274,-23170, 23170, 12540,-30274
+
+    .align 4
+round_tab:
+    .long (1 << (14-1)), (1 << (14-1)), (1 << (14-1)), (1 << (14-1))
+    .long (1 << (16-1)), (1 << (16-1)), (1 << (16-1)), (1 << (16-1))
diff --git a/vp8/encoder/ppc/rdopt_altivec.asm b/vp8/encoder/ppc/rdopt_altivec.asm
new file mode 100644 (file)
index 0000000..ba48230
--- /dev/null
@@ -0,0 +1,51 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    .globl vp8_block_error_ppc
+
+    .align 2
+;# r3 short *Coeff
+;# r4 short *dqcoeff
+vp8_block_error_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xf800
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    stw     r5, 12(r1)          ;# tranfer dc to vector register
+
+    lvx     v0, 0, r3           ;# Coeff
+    lvx     v1, 0, r4           ;# dqcoeff
+
+    li      r10, 16
+
+    vspltisw v3, 0
+
+    vsubshs v0, v0, v1
+
+    vmsumshm v2, v0, v0, v3     ;# multiply differences
+
+    lvx     v0, r10, r3         ;# Coeff
+    lvx     v1, r10, r4         ;# dqcoeff
+
+    vsubshs v0, v0, v1
+
+    vmsumshm v1, v0, v0, v2     ;# multiply differences
+    vsumsws v1, v1, v3          ;# sum up
+
+    stvx    v1, 0, r1
+    lwz     r3, 12(r1)          ;# return value
+
+    addi    r1, r1, 32          ;# recover stack
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
diff --git a/vp8/encoder/psnr.c b/vp8/encoder/psnr.c
new file mode 100644 (file)
index 0000000..5119bb8
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_scale/yv12config.h"
+#include "math.h"
+#include "vp8/common/systemdependent.h" /* for vp8_clear_system_state() */
+
+#define MAX_PSNR 60
+
+double vp8_mse2psnr(double Samples, double Peak, double Mse)
+{
+    double psnr;
+
+    if ((double)Mse > 0.0)
+        psnr = 10.0 * log10(Peak * Peak * Samples / Mse);
+    else
+        psnr = MAX_PSNR;      // Limit to prevent / 0
+
+    if (psnr > MAX_PSNR)
+        psnr = MAX_PSNR;
+
+    return psnr;
+}
diff --git a/vp8/encoder/psnr.h b/vp8/encoder/psnr.h
new file mode 100644 (file)
index 0000000..7f6269a
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_PSNR_H
+#define __INC_PSNR_H
+
+extern double vp8_mse2psnr(double Samples, double Peak, double Mse);
+
+#endif
diff --git a/vp8/encoder/quantize.c b/vp8/encoder/quantize.c
new file mode 100644 (file)
index 0000000..766d2b2
--- /dev/null
@@ -0,0 +1,814 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include <math.h>
+#include "vpx_mem/vpx_mem.h"
+
+#include "onyx_int.h"
+#include "quantize.h"
+#include "vp8/common/quant_common.h"
+
+#define EXACT_QUANT
+
+#ifdef EXACT_FASTQUANT
+void vp8_fast_quantize_b_c(BLOCK *b, BLOCKD *d)
+{
+    int i, rc, eob;
+    int zbin;
+    int x, y, z, sz;
+    short *coeff_ptr       = b->coeff;
+    short *zbin_ptr        = b->zbin;
+    short *round_ptr       = b->round;
+    short *quant_ptr       = b->quant_fast;
+    unsigned char *quant_shift_ptr = b->quant_shift;
+    short *qcoeff_ptr      = d->qcoeff;
+    short *dqcoeff_ptr     = d->dqcoeff;
+    short *dequant_ptr     = d->dequant;
+
+    vpx_memset(qcoeff_ptr, 0, 32);
+    vpx_memset(dqcoeff_ptr, 0, 32);
+
+    eob = -1;
+
+    for (i = 0; i < 16; i++)
+    {
+        rc   = vp8_default_zig_zag1d[i];
+        z    = coeff_ptr[rc];
+        zbin = zbin_ptr[rc] ;
+
+        sz = (z >> 31);                                 // sign of z
+        x  = (z ^ sz) - sz;                             // x = abs(z)
+
+        if (x >= zbin)
+        {
+            x += round_ptr[rc];
+            y  = (((x * quant_ptr[rc]) >> 16) + x)
+                 >> quant_shift_ptr[rc];                // quantize (x)
+            x  = (y ^ sz) - sz;                         // get the sign back
+            qcoeff_ptr[rc] = x;                          // write to destination
+            dqcoeff_ptr[rc] = x * dequant_ptr[rc];        // dequantized value
+
+            if (y)
+            {
+                eob = i;                                // last nonzero coeffs
+            }
+        }
+    }
+    *d->eob = (char)(eob + 1);
+}
+
+#else
+
+void vp8_fast_quantize_b_c(BLOCK *b, BLOCKD *d)
+{
+    int i, rc, eob;
+    int x, y, z, sz;
+    short *coeff_ptr   = b->coeff;
+    short *round_ptr   = b->round;
+    short *quant_ptr   = b->quant_fast;
+    short *qcoeff_ptr  = d->qcoeff;
+    short *dqcoeff_ptr = d->dqcoeff;
+    short *dequant_ptr = d->dequant;
+
+    eob = -1;
+    for (i = 0; i < 16; i++)
+    {
+        rc   = vp8_default_zig_zag1d[i];
+        z    = coeff_ptr[rc];
+
+        sz = (z >> 31);                                 // sign of z
+        x  = (z ^ sz) - sz;                             // x = abs(z)
+
+        y  = ((x + round_ptr[rc]) * quant_ptr[rc]) >> 16; // quantize (x)
+        x  = (y ^ sz) - sz;                         // get the sign back
+        qcoeff_ptr[rc] = x;                          // write to destination
+        dqcoeff_ptr[rc] = x * dequant_ptr[rc];        // dequantized value
+
+        if (y)
+        {
+            eob = i;                                // last nonzero coeffs
+        }
+    }
+    *d->eob = (char)(eob + 1);
+}
+
+#endif
+
+#ifdef EXACT_QUANT
+void vp8_regular_quantize_b_c(BLOCK *b, BLOCKD *d)
+{
+    int i, rc, eob;
+    int zbin;
+    int x, y, z, sz;
+    short *zbin_boost_ptr  = b->zrun_zbin_boost;
+    short *coeff_ptr       = b->coeff;
+    short *zbin_ptr        = b->zbin;
+    short *round_ptr       = b->round;
+    short *quant_ptr       = b->quant;
+    unsigned char *quant_shift_ptr = b->quant_shift;
+    short *qcoeff_ptr      = d->qcoeff;
+    short *dqcoeff_ptr     = d->dqcoeff;
+    short *dequant_ptr     = d->dequant;
+    short zbin_oq_value    = b->zbin_extra;
+
+    vpx_memset(qcoeff_ptr, 0, 32);
+    vpx_memset(dqcoeff_ptr, 0, 32);
+
+    eob = -1;
+
+    for (i = 0; i < 16; i++)
+    {
+        rc   = vp8_default_zig_zag1d[i];
+        z    = coeff_ptr[rc];
+
+        zbin = zbin_ptr[rc] + *zbin_boost_ptr + zbin_oq_value;
+
+        zbin_boost_ptr ++;
+        sz = (z >> 31);                                 // sign of z
+        x  = (z ^ sz) - sz;                             // x = abs(z)
+
+        if (x >= zbin)
+        {
+            x += round_ptr[rc];
+            y  = (((x * quant_ptr[rc]) >> 16) + x)
+                 >> quant_shift_ptr[rc];                // quantize (x)
+            x  = (y ^ sz) - sz;                         // get the sign back
+            qcoeff_ptr[rc]  = x;                        // write to destination
+            dqcoeff_ptr[rc] = x * dequant_ptr[rc];      // dequantized value
+
+            if (y)
+            {
+                eob = i;                                // last nonzero coeffs
+                zbin_boost_ptr = b->zrun_zbin_boost;    // reset zero runlength
+            }
+        }
+    }
+
+    *d->eob = (char)(eob + 1);
+}
+
+/* Perform regular quantization, with unbiased rounding and no zero bin. */
+void vp8_strict_quantize_b_c(BLOCK *b, BLOCKD *d)
+{
+    int i;
+    int rc;
+    int eob;
+    int x;
+    int y;
+    int z;
+    int sz;
+    short *coeff_ptr;
+    short *quant_ptr;
+    unsigned char *quant_shift_ptr;
+    short *qcoeff_ptr;
+    short *dqcoeff_ptr;
+    short *dequant_ptr;
+
+    coeff_ptr       = b->coeff;
+    quant_ptr       = b->quant;
+    quant_shift_ptr = b->quant_shift;
+    qcoeff_ptr      = d->qcoeff;
+    dqcoeff_ptr     = d->dqcoeff;
+    dequant_ptr     = d->dequant;
+    eob = - 1;
+    vpx_memset(qcoeff_ptr, 0, 32);
+    vpx_memset(dqcoeff_ptr, 0, 32);
+    for (i = 0; i < 16; i++)
+    {
+        int dq;
+        int round;
+
+        /*TODO: These arrays should be stored in zig-zag order.*/
+        rc = vp8_default_zig_zag1d[i];
+        z = coeff_ptr[rc];
+        dq = dequant_ptr[rc];
+        round = dq >> 1;
+        /* Sign of z. */
+        sz = -(z < 0);
+        x = (z + sz) ^ sz;
+        x += round;
+        if (x >= dq)
+        {
+            /* Quantize x. */
+            y  = (((x * quant_ptr[rc]) >> 16) + x) >> quant_shift_ptr[rc];
+            /* Put the sign back. */
+            x = (y + sz) ^ sz;
+            /* Save the coefficient and its dequantized value. */
+            qcoeff_ptr[rc] = x;
+            dqcoeff_ptr[rc] = x * dq;
+            /* Remember the last non-zero coefficient. */
+            if (y)
+                eob = i;
+        }
+    }
+
+    *d->eob = (char)(eob + 1);
+}
+
+#else
+
+void vp8_regular_quantize_b_c(BLOCK *b, BLOCKD *d)
+{
+    int i, rc, eob;
+    int zbin;
+    int x, y, z, sz;
+    short *zbin_boost_ptr = b->zrun_zbin_boost;
+    short *coeff_ptr      = b->coeff;
+    short *zbin_ptr       = b->zbin;
+    short *round_ptr      = b->round;
+    short *quant_ptr      = b->quant;
+    short *qcoeff_ptr     = d->qcoeff;
+    short *dqcoeff_ptr    = d->dqcoeff;
+    short *dequant_ptr    = d->dequant;
+    short zbin_oq_value   = b->zbin_extra;
+
+    vpx_memset(qcoeff_ptr, 0, 32);
+    vpx_memset(dqcoeff_ptr, 0, 32);
+
+    eob = -1;
+
+    for (i = 0; i < 16; i++)
+    {
+        rc   = vp8_default_zig_zag1d[i];
+        z    = coeff_ptr[rc];
+
+        //if ( i == 0 )
+        //    zbin = zbin_ptr[rc] + *zbin_boost_ptr + zbin_oq_value/2;
+        //else
+        zbin = zbin_ptr[rc] + *zbin_boost_ptr + zbin_oq_value;
+
+        zbin_boost_ptr ++;
+        sz = (z >> 31);                                 // sign of z
+        x  = (z ^ sz) - sz;                             // x = abs(z)
+
+        if (x >= zbin)
+        {
+            y  = ((x + round_ptr[rc]) * quant_ptr[rc]) >> 16; // quantize (x)
+            x  = (y ^ sz) - sz;                         // get the sign back
+            qcoeff_ptr[rc]  = x;                         // write to destination
+            dqcoeff_ptr[rc] = x * dequant_ptr[rc];        // dequantized value
+
+            if (y)
+            {
+                eob = i;                                // last nonzero coeffs
+                zbin_boost_ptr = &b->zrun_zbin_boost[0];    // reset zero runlength
+            }
+        }
+    }
+
+    *d->eob = (char)(eob + 1);
+}
+
+#endif
+
+void vp8_quantize_mby_c(MACROBLOCK *x)
+{
+    int i;
+    int has_2nd_order = (x->e_mbd.mode_info_context->mbmi.mode != B_PRED
+        && x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
+
+    for (i = 0; i < 16; i++)
+        x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
+
+    if(has_2nd_order)
+        x->quantize_b(&x->block[24], &x->e_mbd.block[24]);
+}
+
+void vp8_quantize_mb_c(MACROBLOCK *x)
+{
+    int i;
+    int has_2nd_order=(x->e_mbd.mode_info_context->mbmi.mode != B_PRED
+        && x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
+
+    for (i = 0; i < 24+has_2nd_order; i++)
+        x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
+}
+
+
+void vp8_quantize_mbuv_c(MACROBLOCK *x)
+{
+    int i;
+
+    for (i = 16; i < 24; i++)
+        x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
+}
+
+/* quantize_b_pair function pointer in MACROBLOCK structure is set to one of
+ * these two C functions if corresponding optimized routine is not available.
+ * NEON optimized version implements currently the fast quantization for pair
+ * of blocks. */
+void vp8_regular_quantize_b_pair(BLOCK *b1, BLOCK *b2, BLOCKD *d1, BLOCKD *d2)
+{
+    vp8_regular_quantize_b(b1, d1);
+    vp8_regular_quantize_b(b2, d2);
+}
+
+void vp8_fast_quantize_b_pair_c(BLOCK *b1, BLOCK *b2, BLOCKD *d1, BLOCKD *d2)
+{
+    vp8_fast_quantize_b_c(b1, d1);
+    vp8_fast_quantize_b_c(b2, d2);
+}
+
+
+static const int qrounding_factors[129] =
+{
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48
+};
+
+
+static const int qzbin_factors[129] =
+{
+    84, 84, 84, 84, 84, 84, 84, 84,
+    84, 84, 84, 84, 84, 84, 84, 84,
+    84, 84, 84, 84, 84, 84, 84, 84,
+    84, 84, 84, 84, 84, 84, 84, 84,
+    84, 84, 84, 84, 84, 84, 84, 84,
+    84, 84, 84, 84, 84, 84, 84, 84,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80
+};
+
+
+static const int qrounding_factors_y2[129] =
+{
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48
+};
+
+
+static const int qzbin_factors_y2[129] =
+{
+    84, 84, 84, 84, 84, 84, 84, 84,
+    84, 84, 84, 84, 84, 84, 84, 84,
+    84, 84, 84, 84, 84, 84, 84, 84,
+    84, 84, 84, 84, 84, 84, 84, 84,
+    84, 84, 84, 84, 84, 84, 84, 84,
+    84, 84, 84, 84, 84, 84, 84, 84,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80
+};
+
+
+#define EXACT_QUANT
+#ifdef EXACT_QUANT
+static void invert_quant(int improved_quant, short *quant,
+                               unsigned char *shift, short d)
+{
+    if(improved_quant)
+    {
+        unsigned t;
+        int l;
+        t = d;
+        for(l = 0; t > 1; l++)
+            t>>=1;
+        t = 1 + (1<<(16+l))/d;
+        *quant = (short)(t - (1<<16));
+        *shift = l;
+    }
+    else
+    {
+        *quant = (1 << 16) / d;
+        *shift = 0;
+    }
+}
+
+
+void vp8cx_init_quantizer(VP8_COMP *cpi)
+{
+    int i;
+    int quant_val;
+    int Q;
+
+    int zbin_boost[16] = {0, 0, 8, 10, 12, 14, 16, 20, 24, 28, 32, 36, 40, 44,
+                          44, 44};
+
+    for (Q = 0; Q < QINDEX_RANGE; Q++)
+    {
+        // dc values
+        quant_val = vp8_dc_quant(Q, cpi->common.y1dc_delta_q);
+        cpi->Y1quant_fast[Q][0] = (1 << 16) / quant_val;
+        invert_quant(cpi->sf.improved_quant, cpi->Y1quant[Q] + 0,
+                     cpi->Y1quant_shift[Q] + 0, quant_val);
+        cpi->Y1zbin[Q][0] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
+        cpi->Y1round[Q][0] = (qrounding_factors[Q] * quant_val) >> 7;
+        cpi->common.Y1dequant[Q][0] = quant_val;
+        cpi->zrun_zbin_boost_y1[Q][0] = (quant_val * zbin_boost[0]) >> 7;
+
+        quant_val = vp8_dc2quant(Q, cpi->common.y2dc_delta_q);
+        cpi->Y2quant_fast[Q][0] = (1 << 16) / quant_val;
+        invert_quant(cpi->sf.improved_quant, cpi->Y2quant[Q] + 0,
+                     cpi->Y2quant_shift[Q] + 0, quant_val);
+        cpi->Y2zbin[Q][0] = ((qzbin_factors_y2[Q] * quant_val) + 64) >> 7;
+        cpi->Y2round[Q][0] = (qrounding_factors_y2[Q] * quant_val) >> 7;
+        cpi->common.Y2dequant[Q][0] = quant_val;
+        cpi->zrun_zbin_boost_y2[Q][0] = (quant_val * zbin_boost[0]) >> 7;
+
+        quant_val = vp8_dc_uv_quant(Q, cpi->common.uvdc_delta_q);
+        cpi->UVquant_fast[Q][0] = (1 << 16) / quant_val;
+        invert_quant(cpi->sf.improved_quant, cpi->UVquant[Q] + 0,
+                     cpi->UVquant_shift[Q] + 0, quant_val);
+        cpi->UVzbin[Q][0] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;;
+        cpi->UVround[Q][0] = (qrounding_factors[Q] * quant_val) >> 7;
+        cpi->common.UVdequant[Q][0] = quant_val;
+        cpi->zrun_zbin_boost_uv[Q][0] = (quant_val * zbin_boost[0]) >> 7;
+
+        // all the ac values = ;
+        quant_val = vp8_ac_yquant(Q);
+        cpi->Y1quant_fast[Q][1] = (1 << 16) / quant_val;
+        invert_quant(cpi->sf.improved_quant, cpi->Y1quant[Q] + 1,
+                     cpi->Y1quant_shift[Q] + 1, quant_val);
+        cpi->Y1zbin[Q][1] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
+        cpi->Y1round[Q][1] = (qrounding_factors[Q] * quant_val) >> 7;
+        cpi->common.Y1dequant[Q][1] = quant_val;
+        cpi->zrun_zbin_boost_y1[Q][1] = (quant_val * zbin_boost[1]) >> 7;
+
+        quant_val = vp8_ac2quant(Q, cpi->common.y2ac_delta_q);
+        cpi->Y2quant_fast[Q][1] = (1 << 16) / quant_val;
+        invert_quant(cpi->sf.improved_quant, cpi->Y2quant[Q] + 1,
+                     cpi->Y2quant_shift[Q] + 1, quant_val);
+        cpi->Y2zbin[Q][1] = ((qzbin_factors_y2[Q] * quant_val) + 64) >> 7;
+        cpi->Y2round[Q][1] = (qrounding_factors_y2[Q] * quant_val) >> 7;
+        cpi->common.Y2dequant[Q][1] = quant_val;
+        cpi->zrun_zbin_boost_y2[Q][1] = (quant_val * zbin_boost[1]) >> 7;
+
+        quant_val = vp8_ac_uv_quant(Q, cpi->common.uvac_delta_q);
+        cpi->UVquant_fast[Q][1] = (1 << 16) / quant_val;
+        invert_quant(cpi->sf.improved_quant, cpi->UVquant[Q] + 1,
+                     cpi->UVquant_shift[Q] + 1, quant_val);
+        cpi->UVzbin[Q][1] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
+        cpi->UVround[Q][1] = (qrounding_factors[Q] * quant_val) >> 7;
+        cpi->common.UVdequant[Q][1] = quant_val;
+        cpi->zrun_zbin_boost_uv[Q][1] = (quant_val * zbin_boost[1]) >> 7;
+
+        for (i = 2; i < 16; i++)
+        {
+            cpi->Y1quant_fast[Q][i] = cpi->Y1quant_fast[Q][1];
+            cpi->Y1quant[Q][i] = cpi->Y1quant[Q][1];
+            cpi->Y1quant_shift[Q][i] = cpi->Y1quant_shift[Q][1];
+            cpi->Y1zbin[Q][i] = cpi->Y1zbin[Q][1];
+            cpi->Y1round[Q][i] = cpi->Y1round[Q][1];
+            cpi->zrun_zbin_boost_y1[Q][i] = (cpi->common.Y1dequant[Q][1] *
+                                             zbin_boost[i]) >> 7;
+
+            cpi->Y2quant_fast[Q][i] = cpi->Y2quant_fast[Q][1];
+            cpi->Y2quant[Q][i] = cpi->Y2quant[Q][1];
+            cpi->Y2quant_shift[Q][i] = cpi->Y2quant_shift[Q][1];
+            cpi->Y2zbin[Q][i] = cpi->Y2zbin[Q][1];
+            cpi->Y2round[Q][i] = cpi->Y2round[Q][1];
+            cpi->zrun_zbin_boost_y2[Q][i] = (cpi->common.Y2dequant[Q][1] *
+                                             zbin_boost[i]) >> 7;
+
+            cpi->UVquant_fast[Q][i] = cpi->UVquant_fast[Q][1];
+            cpi->UVquant[Q][i] = cpi->UVquant[Q][1];
+            cpi->UVquant_shift[Q][i] = cpi->UVquant_shift[Q][1];
+            cpi->UVzbin[Q][i] = cpi->UVzbin[Q][1];
+            cpi->UVround[Q][i] = cpi->UVround[Q][1];
+            cpi->zrun_zbin_boost_uv[Q][i] = (cpi->common.UVdequant[Q][1] *
+                                             zbin_boost[i]) >> 7;
+        }
+    }
+}
+#else
+void vp8cx_init_quantizer(VP8_COMP *cpi)
+{
+    int i;
+    int quant_val;
+    int Q;
+
+    int zbin_boost[16] = {0, 0, 8, 10, 12, 14, 16, 20, 24, 28, 32, 36, 40, 44, 44, 44};
+
+    for (Q = 0; Q < QINDEX_RANGE; Q++)
+    {
+        // dc values
+        quant_val = vp8_dc_quant(Q, cpi->common.y1dc_delta_q);
+        cpi->Y1quant[Q][0] = (1 << 16) / quant_val;
+        cpi->Y1zbin[Q][0] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
+        cpi->Y1round[Q][0] = (qrounding_factors[Q] * quant_val) >> 7;
+        cpi->common.Y1dequant[Q][0] = quant_val;
+        cpi->zrun_zbin_boost_y1[Q][0] = (quant_val * zbin_boost[0]) >> 7;
+
+        quant_val = vp8_dc2quant(Q, cpi->common.y2dc_delta_q);
+        cpi->Y2quant[Q][0] = (1 << 16) / quant_val;
+        cpi->Y2zbin[Q][0] = ((qzbin_factors_y2[Q] * quant_val) + 64) >> 7;
+        cpi->Y2round[Q][0] = (qrounding_factors_y2[Q] * quant_val) >> 7;
+        cpi->common.Y2dequant[Q][0] = quant_val;
+        cpi->zrun_zbin_boost_y2[Q][0] = (quant_val * zbin_boost[0]) >> 7;
+
+        quant_val = vp8_dc_uv_quant(Q, cpi->common.uvdc_delta_q);
+        cpi->UVquant[Q][0] = (1 << 16) / quant_val;
+        cpi->UVzbin[Q][0] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;;
+        cpi->UVround[Q][0] = (qrounding_factors[Q] * quant_val) >> 7;
+        cpi->common.UVdequant[Q][0] = quant_val;
+        cpi->zrun_zbin_boost_uv[Q][0] = (quant_val * zbin_boost[0]) >> 7;
+
+        // all the ac values = ;
+        for (i = 1; i < 16; i++)
+        {
+            int rc = vp8_default_zig_zag1d[i];
+
+            quant_val = vp8_ac_yquant(Q);
+            cpi->Y1quant[Q][rc] = (1 << 16) / quant_val;
+            cpi->Y1zbin[Q][rc] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
+            cpi->Y1round[Q][rc] = (qrounding_factors[Q] * quant_val) >> 7;
+            cpi->common.Y1dequant[Q][rc] = quant_val;
+            cpi->zrun_zbin_boost_y1[Q][i] = (quant_val * zbin_boost[i]) >> 7;
+
+            quant_val = vp8_ac2quant(Q, cpi->common.y2ac_delta_q);
+            cpi->Y2quant[Q][rc] = (1 << 16) / quant_val;
+            cpi->Y2zbin[Q][rc] = ((qzbin_factors_y2[Q] * quant_val) + 64) >> 7;
+            cpi->Y2round[Q][rc] = (qrounding_factors_y2[Q] * quant_val) >> 7;
+            cpi->common.Y2dequant[Q][rc] = quant_val;
+            cpi->zrun_zbin_boost_y2[Q][i] = (quant_val * zbin_boost[i]) >> 7;
+
+            quant_val = vp8_ac_uv_quant(Q, cpi->common.uvac_delta_q);
+            cpi->UVquant[Q][rc] = (1 << 16) / quant_val;
+            cpi->UVzbin[Q][rc] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
+            cpi->UVround[Q][rc] = (qrounding_factors[Q] * quant_val) >> 7;
+            cpi->common.UVdequant[Q][rc] = quant_val;
+            cpi->zrun_zbin_boost_uv[Q][i] = (quant_val * zbin_boost[i]) >> 7;
+        }
+    }
+}
+#endif
+
+#define ZBIN_EXTRA_Y \
+    (( cpi->common.Y1dequant[QIndex][1] *  \
+    ( cpi->zbin_over_quant +  \
+      cpi->zbin_mode_boost +  \
+      x->act_zbin_adj ) ) >> 7)
+
+#define ZBIN_EXTRA_UV \
+    (( cpi->common.UVdequant[QIndex][1] *  \
+    ( cpi->zbin_over_quant +  \
+      cpi->zbin_mode_boost +  \
+      x->act_zbin_adj ) ) >> 7)
+
+#define ZBIN_EXTRA_Y2 \
+    (( cpi->common.Y2dequant[QIndex][1] *  \
+    ( (cpi->zbin_over_quant / 2) +  \
+       cpi->zbin_mode_boost +  \
+       x->act_zbin_adj ) ) >> 7)
+
+void vp8cx_mb_init_quantizer(VP8_COMP *cpi, MACROBLOCK *x, int ok_to_skip)
+{
+    int i;
+    int QIndex;
+    MACROBLOCKD *xd = &x->e_mbd;
+    int zbin_extra;
+
+    // Select the baseline MB Q index.
+    if (xd->segmentation_enabled)
+    {
+        // Abs Value
+        if (xd->mb_segement_abs_delta == SEGMENT_ABSDATA)
+
+            QIndex = xd->segment_feature_data[MB_LVL_ALT_Q][xd->mode_info_context->mbmi.segment_id];
+        // Delta Value
+        else
+        {
+            QIndex = cpi->common.base_qindex + xd->segment_feature_data[MB_LVL_ALT_Q][xd->mode_info_context->mbmi.segment_id];
+            QIndex = (QIndex >= 0) ? ((QIndex <= MAXQ) ? QIndex : MAXQ) : 0;    // Clamp to valid range
+        }
+    }
+    else
+        QIndex = cpi->common.base_qindex;
+
+    /* This initialization should be called at least once. Use ok_to_skip to
+     * decide if it is ok to skip.
+     * Before encoding a frame, this function is always called with ok_to_skip
+     * =0, which means no skiping of calculations. The "last" values are
+     * initialized at that time.
+     */
+    if (!ok_to_skip || QIndex != x->q_index)
+    {
+
+        xd->dequant_y1_dc[0] = 1;
+        xd->dequant_y1[0] = cpi->common.Y1dequant[QIndex][0];
+        xd->dequant_y2[0] = cpi->common.Y2dequant[QIndex][0];
+        xd->dequant_uv[0] = cpi->common.UVdequant[QIndex][0];
+
+        for (i = 1; i < 16; i++)
+        {
+            xd->dequant_y1_dc[i] =
+            xd->dequant_y1[i] = cpi->common.Y1dequant[QIndex][1];
+            xd->dequant_y2[i] = cpi->common.Y2dequant[QIndex][1];
+            xd->dequant_uv[i] = cpi->common.UVdequant[QIndex][1];
+        }
+#if 1
+        /*TODO:  Remove dequant from BLOCKD.  This is a temporary solution until
+         * the quantizer code uses a passed in pointer to the dequant constants.
+         * This will also require modifications to the x86 and neon assembly.
+         * */
+        for (i = 0; i < 16; i++)
+            x->e_mbd.block[i].dequant = xd->dequant_y1; //cpi->common.Y1dequant[QIndex];
+        for (i = 16; i < 24; i++)
+            x->e_mbd.block[i].dequant = xd->dequant_uv; //cpi->common.UVdequant[QIndex];
+        x->e_mbd.block[24].dequant = xd->dequant_y2; //cpi->common.Y2dequant[QIndex];
+#endif
+
+        // Y
+        zbin_extra = ZBIN_EXTRA_Y;
+
+        for (i = 0; i < 16; i++)
+        {
+            x->block[i].quant = cpi->Y1quant[QIndex];
+            x->block[i].quant_fast = cpi->Y1quant_fast[QIndex];
+            x->block[i].quant_shift = cpi->Y1quant_shift[QIndex];
+            x->block[i].zbin = cpi->Y1zbin[QIndex];
+            x->block[i].round = cpi->Y1round[QIndex];
+            x->block[i].zrun_zbin_boost = cpi->zrun_zbin_boost_y1[QIndex];
+            x->block[i].zbin_extra = (short)zbin_extra;
+        }
+
+        // UV
+        zbin_extra = ZBIN_EXTRA_UV;
+
+        for (i = 16; i < 24; i++)
+        {
+            x->block[i].quant = cpi->UVquant[QIndex];
+            x->block[i].quant_fast = cpi->UVquant_fast[QIndex];
+            x->block[i].quant_shift = cpi->UVquant_shift[QIndex];
+            x->block[i].zbin = cpi->UVzbin[QIndex];
+            x->block[i].round = cpi->UVround[QIndex];
+            x->block[i].zrun_zbin_boost = cpi->zrun_zbin_boost_uv[QIndex];
+            x->block[i].zbin_extra = (short)zbin_extra;
+        }
+
+        // Y2
+        zbin_extra = ZBIN_EXTRA_Y2;
+
+        x->block[24].quant_fast = cpi->Y2quant_fast[QIndex];
+        x->block[24].quant = cpi->Y2quant[QIndex];
+        x->block[24].quant_shift = cpi->Y2quant_shift[QIndex];
+        x->block[24].zbin = cpi->Y2zbin[QIndex];
+        x->block[24].round = cpi->Y2round[QIndex];
+        x->block[24].zrun_zbin_boost = cpi->zrun_zbin_boost_y2[QIndex];
+        x->block[24].zbin_extra = (short)zbin_extra;
+
+        /* save this macroblock QIndex for vp8_update_zbin_extra() */
+        x->q_index = QIndex;
+
+        cpi->last_zbin_over_quant = cpi->zbin_over_quant;
+        cpi->last_zbin_mode_boost = cpi->zbin_mode_boost;
+        x->last_act_zbin_adj = x->act_zbin_adj;
+
+
+
+    }
+    else if(cpi->last_zbin_over_quant != cpi->zbin_over_quant
+            || cpi->last_zbin_mode_boost != cpi->zbin_mode_boost
+            || x->last_act_zbin_adj != x->act_zbin_adj)
+    {
+        // Y
+        zbin_extra = ZBIN_EXTRA_Y;
+
+        for (i = 0; i < 16; i++)
+            x->block[i].zbin_extra = (short)zbin_extra;
+
+        // UV
+        zbin_extra = ZBIN_EXTRA_UV;
+
+        for (i = 16; i < 24; i++)
+            x->block[i].zbin_extra = (short)zbin_extra;
+
+        // Y2
+        zbin_extra = ZBIN_EXTRA_Y2;
+        x->block[24].zbin_extra = (short)zbin_extra;
+
+        cpi->last_zbin_over_quant = cpi->zbin_over_quant;
+        cpi->last_zbin_mode_boost = cpi->zbin_mode_boost;
+        x->last_act_zbin_adj = x->act_zbin_adj;
+    }
+}
+
+void vp8_update_zbin_extra(VP8_COMP *cpi, MACROBLOCK *x)
+{
+    int i;
+    int QIndex = x->q_index;
+    int zbin_extra;
+
+    // Y
+    zbin_extra = ZBIN_EXTRA_Y;
+
+    for (i = 0; i < 16; i++)
+        x->block[i].zbin_extra = (short)zbin_extra;
+
+    // UV
+    zbin_extra = ZBIN_EXTRA_UV;
+
+    for (i = 16; i < 24; i++)
+        x->block[i].zbin_extra = (short)zbin_extra;
+
+    // Y2
+    zbin_extra = ZBIN_EXTRA_Y2;
+    x->block[24].zbin_extra = (short)zbin_extra;
+}
+#undef ZBIN_EXTRA_Y
+#undef ZBIN_EXTRA_UV
+#undef ZBIN_EXTRA_Y2
+
+void vp8cx_frame_init_quantizer(VP8_COMP *cpi)
+{
+    // Clear Zbin mode boost for default case
+    cpi->zbin_mode_boost = 0;
+
+    // MB level quantizer setup
+    vp8cx_mb_init_quantizer(cpi, &cpi->mb, 0);
+}
+
+
+void vp8_set_quantizer(struct VP8_COMP *cpi, int Q)
+{
+    VP8_COMMON *cm = &cpi->common;
+    MACROBLOCKD *mbd = &cpi->mb.e_mbd;
+    int update = 0;
+    int new_delta_q;
+    cm->base_qindex = Q;
+
+    /* if any of the delta_q values are changing update flag has to be set */
+    /* currently only y2dc_delta_q may change */
+
+    cm->y1dc_delta_q = 0;
+    cm->y2ac_delta_q = 0;
+    cm->uvdc_delta_q = 0;
+    cm->uvac_delta_q = 0;
+
+    if (Q < 4)
+    {
+        new_delta_q = 4-Q;
+    }
+    else
+        new_delta_q = 0;
+
+    update |= cm->y2dc_delta_q != new_delta_q;
+    cm->y2dc_delta_q = new_delta_q;
+
+
+    // Set Segment specific quatizers
+    mbd->segment_feature_data[MB_LVL_ALT_Q][0] = cpi->segment_feature_data[MB_LVL_ALT_Q][0];
+    mbd->segment_feature_data[MB_LVL_ALT_Q][1] = cpi->segment_feature_data[MB_LVL_ALT_Q][1];
+    mbd->segment_feature_data[MB_LVL_ALT_Q][2] = cpi->segment_feature_data[MB_LVL_ALT_Q][2];
+    mbd->segment_feature_data[MB_LVL_ALT_Q][3] = cpi->segment_feature_data[MB_LVL_ALT_Q][3];
+
+    /* quantizer has to be reinitialized for any delta_q changes */
+    if(update)
+        vp8cx_init_quantizer(cpi);
+
+}
diff --git a/vp8/encoder/quantize.h b/vp8/encoder/quantize.h
new file mode 100644 (file)
index 0000000..d55496c
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_QUANTIZE_H
+#define __INC_QUANTIZE_H
+
+struct VP8_COMP;
+struct macroblock;
+extern void vp8_set_quantizer(struct VP8_COMP *cpi, int Q);
+extern void vp8cx_frame_init_quantizer(struct VP8_COMP *cpi);
+extern void vp8_update_zbin_extra(struct VP8_COMP *cpi, struct macroblock *x);
+extern void vp8cx_mb_init_quantizer(struct VP8_COMP *cpi, struct macroblock *x, int ok_to_skip);
+extern void vp8cx_init_quantizer(struct VP8_COMP *cpi);
+
+#endif
diff --git a/vp8/encoder/ratectrl.c b/vp8/encoder/ratectrl.c
new file mode 100644 (file)
index 0000000..472e85f
--- /dev/null
@@ -0,0 +1,1569 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <assert.h>
+
+#include "math.h"
+#include "vp8/common/common.h"
+#include "ratectrl.h"
+#include "vp8/common/entropymode.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vp8/common/systemdependent.h"
+#include "encodemv.h"
+
+
+#define MIN_BPB_FACTOR          0.01
+#define MAX_BPB_FACTOR          50
+
+extern const MB_PREDICTION_MODE vp8_mode_order[MAX_MODES];
+
+
+
+#ifdef MODE_STATS
+extern int y_modes[5];
+extern int uv_modes[4];
+extern int b_modes[10];
+
+extern int inter_y_modes[10];
+extern int inter_uv_modes[4];
+extern int inter_b_modes[10];
+#endif
+
+// Bits Per MB at different Q (Multiplied by 512)
+#define BPER_MB_NORMBITS    9
+
+// Work in progress recalibration of baseline rate tables based on
+// the assumption that bits per mb is inversely proportional to the
+// quantizer value.
+const int vp8_bits_per_mb[2][QINDEX_RANGE] =
+{
+    // Intra case 450000/Qintra
+    {
+        1125000,900000, 750000, 642857, 562500, 500000, 450000, 450000,
+        409090, 375000, 346153, 321428, 300000, 281250, 264705, 264705,
+        250000, 236842, 225000, 225000, 214285, 214285, 204545, 204545,
+        195652, 195652, 187500, 180000, 180000, 173076, 166666, 160714,
+        155172, 150000, 145161, 140625, 136363, 132352, 128571, 125000,
+        121621, 121621, 118421, 115384, 112500, 109756, 107142, 104651,
+        102272, 100000, 97826,  97826,  95744,  93750,  91836,  90000,
+        88235,  86538,  84905,  83333,  81818,  80357,  78947,  77586,
+        76271,  75000,  73770,  72580,  71428,  70312,  69230,  68181,
+        67164,  66176,  65217,  64285,  63380,  62500,  61643,  60810,
+        60000,  59210,  59210,  58441,  57692,  56962,  56250,  55555,
+        54878,  54216,  53571,  52941,  52325,  51724,  51136,  50561,
+        49450,  48387,  47368,  46875,  45918,  45000,  44554,  44117,
+        43269,  42452,  41666,  40909,  40178,  39473,  38793,  38135,
+        36885,  36290,  35714,  35156,  34615,  34090,  33582,  33088,
+        32608,  32142,  31468,  31034,  30405,  29801,  29220,  28662,
+    },
+    // Inter case 285000/Qinter
+    {
+        712500, 570000, 475000, 407142, 356250, 316666, 285000, 259090,
+        237500, 219230, 203571, 190000, 178125, 167647, 158333, 150000,
+        142500, 135714, 129545, 123913, 118750, 114000, 109615, 105555,
+        101785, 98275,  95000,  91935,  89062,  86363,  83823,  81428,
+        79166,  77027,  75000,  73076,  71250,  69512,  67857,  66279,
+        64772,  63333,  61956,  60638,  59375,  58163,  57000,  55882,
+        54807,  53773,  52777,  51818,  50892,  50000,  49137,  47500,
+        45967,  44531,  43181,  41911,  40714,  39583,  38513,  37500,
+        36538,  35625,  34756,  33928,  33139,  32386,  31666,  30978,
+        30319,  29687,  29081,  28500,  27941,  27403,  26886,  26388,
+        25909,  25446,  25000,  24568,  23949,  23360,  22800,  22265,
+        21755,  21268,  20802,  20357,  19930,  19520,  19127,  18750,
+        18387,  18037,  17701,  17378,  17065,  16764,  16473,  16101,
+        15745,  15405,  15079,  14766,  14467,  14179,  13902,  13636,
+        13380,  13133,  12895,  12666,  12445,  12179,  11924,  11632,
+        11445,  11220,  11003,  10795,  10594,  10401,  10215,  10035,
+    }
+};
+
+static const int kf_boost_qadjustment[QINDEX_RANGE] =
+{
+    128, 129, 130, 131, 132, 133, 134, 135,
+    136, 137, 138, 139, 140, 141, 142, 143,
+    144, 145, 146, 147, 148, 149, 150, 151,
+    152, 153, 154, 155, 156, 157, 158, 159,
+    160, 161, 162, 163, 164, 165, 166, 167,
+    168, 169, 170, 171, 172, 173, 174, 175,
+    176, 177, 178, 179, 180, 181, 182, 183,
+    184, 185, 186, 187, 188, 189, 190, 191,
+    192, 193, 194, 195, 196, 197, 198, 199,
+    200, 200, 201, 201, 202, 203, 203, 203,
+    204, 204, 205, 205, 206, 206, 207, 207,
+    208, 208, 209, 209, 210, 210, 211, 211,
+    212, 212, 213, 213, 214, 214, 215, 215,
+    216, 216, 217, 217, 218, 218, 219, 219,
+    220, 220, 220, 220, 220, 220, 220, 220,
+    220, 220, 220, 220, 220, 220, 220, 220,
+};
+
+//#define GFQ_ADJUSTMENT (Q+100)
+#define GFQ_ADJUSTMENT vp8_gf_boost_qadjustment[Q]
+const int vp8_gf_boost_qadjustment[QINDEX_RANGE] =
+{
+    80, 82, 84, 86, 88, 90, 92, 94,
+    96, 97, 98, 99, 100, 101, 102, 103,
+    104, 105, 106, 107, 108, 109, 110, 111,
+    112, 113, 114, 115, 116, 117, 118, 119,
+    120, 121, 122, 123, 124, 125, 126, 127,
+    128, 129, 130, 131, 132, 133, 134, 135,
+    136, 137, 138, 139, 140, 141, 142, 143,
+    144, 145, 146, 147, 148, 149, 150, 151,
+    152, 153, 154, 155, 156, 157, 158, 159,
+    160, 161, 162, 163, 164, 165, 166, 167,
+    168, 169, 170, 171, 172, 173, 174, 175,
+    176, 177, 178, 179, 180, 181, 182, 183,
+    184, 184, 185, 185, 186, 186, 187, 187,
+    188, 188, 189, 189, 190, 190, 191, 191,
+    192, 192, 193, 193, 194, 194, 194, 194,
+    195, 195, 196, 196, 197, 197, 198, 198
+};
+
+/*
+const int vp8_gf_boost_qadjustment[QINDEX_RANGE] =
+{
+    100,101,102,103,104,105,105,106,
+    106,107,107,108,109,109,110,111,
+    112,113,114,115,116,117,118,119,
+    120,121,122,123,124,125,126,127,
+    128,129,130,131,132,133,134,135,
+    136,137,138,139,140,141,142,143,
+    144,145,146,147,148,149,150,151,
+    152,153,154,155,156,157,158,159,
+    160,161,162,163,164,165,166,167,
+    168,169,170,170,171,171,172,172,
+    173,173,173,174,174,174,175,175,
+    175,176,176,176,177,177,177,177,
+    178,178,179,179,180,180,181,181,
+    182,182,183,183,184,184,185,185,
+    186,186,187,187,188,188,189,189,
+    190,190,191,191,192,192,193,193,
+};
+*/
+
+static const int kf_gf_boost_qlimits[QINDEX_RANGE] =
+{
+    150, 155, 160, 165, 170, 175, 180, 185,
+    190, 195, 200, 205, 210, 215, 220, 225,
+    230, 235, 240, 245, 250, 255, 260, 265,
+    270, 275, 280, 285, 290, 295, 300, 305,
+    310, 320, 330, 340, 350, 360, 370, 380,
+    390, 400, 410, 420, 430, 440, 450, 460,
+    470, 480, 490, 500, 510, 520, 530, 540,
+    550, 560, 570, 580, 590, 600, 600, 600,
+    600, 600, 600, 600, 600, 600, 600, 600,
+    600, 600, 600, 600, 600, 600, 600, 600,
+    600, 600, 600, 600, 600, 600, 600, 600,
+    600, 600, 600, 600, 600, 600, 600, 600,
+    600, 600, 600, 600, 600, 600, 600, 600,
+    600, 600, 600, 600, 600, 600, 600, 600,
+    600, 600, 600, 600, 600, 600, 600, 600,
+    600, 600, 600, 600, 600, 600, 600, 600,
+};
+
+// % adjustment to target kf size based on seperation from previous frame
+static const int kf_boost_seperation_adjustment[16] =
+{
+    30,   40,   50,   55,   60,   65,   70,   75,
+    80,   85,   90,   95,  100,  100,  100,  100,
+};
+
+
+static const int gf_adjust_table[101] =
+{
+    100,
+    115, 130, 145, 160, 175, 190, 200, 210, 220, 230,
+    240, 260, 270, 280, 290, 300, 310, 320, 330, 340,
+    350, 360, 370, 380, 390, 400, 400, 400, 400, 400,
+    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
+    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
+    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
+    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
+    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
+    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
+    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
+};
+
+static const int gf_intra_usage_adjustment[20] =
+{
+    125, 120, 115, 110, 105, 100,  95,  85,  80,  75,
+    70,  65,  60,  55,  50,  50,  50,  50,  50,  50,
+};
+
+static const int gf_interval_table[101] =
+{
+    7,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+    9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+    11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+};
+
+static const unsigned int prior_key_frame_weight[KEY_FRAME_CONTEXT] = { 1, 2, 3, 4, 5 };
+
+
+void vp8_save_coding_context(VP8_COMP *cpi)
+{
+    CODING_CONTEXT *const cc = & cpi->coding_context;
+
+    // Stores a snapshot of key state variables which can subsequently be
+    // restored with a call to vp8_restore_coding_context. These functions are
+    // intended for use in a re-code loop in vp8_compress_frame where the
+    // quantizer value is adjusted between loop iterations.
+
+    cc->frames_since_key          = cpi->frames_since_key;
+    cc->filter_level             = cpi->common.filter_level;
+    cc->frames_till_gf_update_due   = cpi->frames_till_gf_update_due;
+    cc->frames_since_golden       = cpi->common.frames_since_golden;
+
+    vp8_copy(cc->mvc,      cpi->common.fc.mvc);
+    vp8_copy(cc->mvcosts,  cpi->mb.mvcosts);
+
+    vp8_copy(cc->kf_ymode_prob,   cpi->common.kf_ymode_prob);
+    vp8_copy(cc->ymode_prob,   cpi->common.fc.ymode_prob);
+    vp8_copy(cc->kf_uv_mode_prob,  cpi->common.kf_uv_mode_prob);
+    vp8_copy(cc->uv_mode_prob,  cpi->common.fc.uv_mode_prob);
+
+    vp8_copy(cc->ymode_count, cpi->ymode_count);
+    vp8_copy(cc->uv_mode_count, cpi->uv_mode_count);
+
+
+    // Stats
+#ifdef MODE_STATS
+    vp8_copy(cc->y_modes,       y_modes);
+    vp8_copy(cc->uv_modes,      uv_modes);
+    vp8_copy(cc->b_modes,       b_modes);
+    vp8_copy(cc->inter_y_modes,  inter_y_modes);
+    vp8_copy(cc->inter_uv_modes, inter_uv_modes);
+    vp8_copy(cc->inter_b_modes,  inter_b_modes);
+#endif
+
+    cc->this_frame_percent_intra = cpi->this_frame_percent_intra;
+}
+
+
+void vp8_restore_coding_context(VP8_COMP *cpi)
+{
+    CODING_CONTEXT *const cc = & cpi->coding_context;
+
+    // Restore key state variables to the snapshot state stored in the
+    // previous call to vp8_save_coding_context.
+
+    cpi->frames_since_key         =   cc->frames_since_key;
+    cpi->common.filter_level     =   cc->filter_level;
+    cpi->frames_till_gf_update_due  =   cc->frames_till_gf_update_due;
+    cpi->common.frames_since_golden       =   cc->frames_since_golden;
+
+    vp8_copy(cpi->common.fc.mvc, cc->mvc);
+
+    vp8_copy(cpi->mb.mvcosts, cc->mvcosts);
+
+    vp8_copy(cpi->common.kf_ymode_prob,   cc->kf_ymode_prob);
+    vp8_copy(cpi->common.fc.ymode_prob,   cc->ymode_prob);
+    vp8_copy(cpi->common.kf_uv_mode_prob,  cc->kf_uv_mode_prob);
+    vp8_copy(cpi->common.fc.uv_mode_prob,  cc->uv_mode_prob);
+
+    vp8_copy(cpi->ymode_count, cc->ymode_count);
+    vp8_copy(cpi->uv_mode_count, cc->uv_mode_count);
+
+    // Stats
+#ifdef MODE_STATS
+    vp8_copy(y_modes, cc->y_modes);
+    vp8_copy(uv_modes, cc->uv_modes);
+    vp8_copy(b_modes, cc->b_modes);
+    vp8_copy(inter_y_modes, cc->inter_y_modes);
+    vp8_copy(inter_uv_modes, cc->inter_uv_modes);
+    vp8_copy(inter_b_modes, cc->inter_b_modes);
+#endif
+
+
+    cpi->this_frame_percent_intra = cc->this_frame_percent_intra;
+}
+
+
+void vp8_setup_key_frame(VP8_COMP *cpi)
+{
+    // Setup for Key frame:
+
+    vp8_default_coef_probs(& cpi->common);
+
+
+    vp8_kf_default_bmode_probs(cpi->common.kf_bmode_prob);
+
+    vpx_memcpy(cpi->common.fc.mvc, vp8_default_mv_context, sizeof(vp8_default_mv_context));
+    {
+        int flag[2] = {1, 1};
+        vp8_build_component_cost_table(cpi->mb.mvcost, (const MV_CONTEXT *) cpi->common.fc.mvc, flag);
+    }
+
+    vpx_memset(cpi->common.fc.pre_mvc, 0, sizeof(cpi->common.fc.pre_mvc));  //initialize pre_mvc to all zero.
+
+    // Make sure we initialize separate contexts for altref,gold, and normal.
+    // TODO shouldn't need 3 different copies of structure to do this!
+    vpx_memcpy(&cpi->lfc_a, &cpi->common.fc, sizeof(cpi->common.fc));
+    vpx_memcpy(&cpi->lfc_g, &cpi->common.fc, sizeof(cpi->common.fc));
+    vpx_memcpy(&cpi->lfc_n, &cpi->common.fc, sizeof(cpi->common.fc));
+
+    //cpi->common.filter_level = 0;      // Reset every key frame.
+    cpi->common.filter_level = cpi->common.base_qindex * 3 / 8 ;
+
+    // Provisional interval before next GF
+    if (cpi->auto_gold)
+        //cpi->frames_till_gf_update_due = DEFAULT_GF_INTERVAL;
+        cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
+    else
+        cpi->frames_till_gf_update_due = cpi->goldfreq;
+
+    cpi->common.refresh_golden_frame = 1;
+    cpi->common.refresh_alt_ref_frame = 1;
+}
+
+
+static int estimate_bits_at_q(int frame_kind, int Q, int MBs,
+                              double correction_factor)
+{
+    int Bpm = (int)(.5 + correction_factor * vp8_bits_per_mb[frame_kind][Q]);
+
+    /* Attempt to retain reasonable accuracy without overflow. The cutoff is
+     * chosen such that the maximum product of Bpm and MBs fits 31 bits. The
+     * largest Bpm takes 20 bits.
+     */
+    if (MBs > (1 << 11))
+        return (Bpm >> BPER_MB_NORMBITS) * MBs;
+    else
+        return (Bpm * MBs) >> BPER_MB_NORMBITS;
+}
+
+
+static void calc_iframe_target_size(VP8_COMP *cpi)
+{
+    // boost defaults to half second
+    int kf_boost;
+    int target;
+
+    // Clear down mmx registers to allow floating point in what follows
+    vp8_clear_system_state();  //__asm emms;
+
+    if (cpi->oxcf.fixed_q >= 0)
+    {
+        int Q = cpi->oxcf.key_q;
+
+        target = estimate_bits_at_q(INTRA_FRAME, Q, cpi->common.MBs,
+                                    cpi->key_frame_rate_correction_factor);
+    }
+    else if (cpi->pass == 2)
+    {
+        // New Two pass RC
+        target = cpi->per_frame_bandwidth;
+    }
+    // First Frame is a special case
+    else if (cpi->common.current_video_frame == 0)
+    {
+        /* 1 Pass there is no information on which to base size so use
+         * bandwidth per second * fraction of the initial buffer
+         * level
+         */
+        target = cpi->oxcf.starting_buffer_level / 2;
+
+        if(target > cpi->oxcf.target_bandwidth * 3 / 2)
+            target = cpi->oxcf.target_bandwidth * 3 / 2;
+    }
+    else
+    {
+        // if this keyframe was forced, use a more recent Q estimate
+        int Q = (cpi->common.frame_flags & FRAMEFLAGS_KEY)
+                ? cpi->avg_frame_qindex : cpi->ni_av_qi;
+
+        int initial_boost = 24; // Corresponds to: |2.5 * per_frame_bandwidth|
+        // Boost depends somewhat on frame rate: only used for 1 layer case.
+        if (cpi->oxcf.number_of_layers == 1) {
+          kf_boost = MAX(initial_boost, (int)(2 * cpi->output_frame_rate - 16));
+        }
+        else {
+          // Initial factor: set target size to: |2.5 * per_frame_bandwidth|.
+          kf_boost = initial_boost;
+        }
+
+        // adjustment up based on q: this factor ranges from ~1.2 to 2.2.
+        kf_boost = kf_boost * kf_boost_qadjustment[Q] / 100;
+
+        // frame separation adjustment ( down)
+        if (cpi->frames_since_key  < cpi->output_frame_rate / 2)
+            kf_boost = (int)(kf_boost
+                       * cpi->frames_since_key / (cpi->output_frame_rate / 2));
+
+        // Minimal target size is |2* per_frame_bandwidth|.
+        if (kf_boost < 16)
+            kf_boost = 16;
+
+        target = ((16 + kf_boost) * cpi->per_frame_bandwidth) >> 4;
+    }
+
+
+    if (cpi->oxcf.rc_max_intra_bitrate_pct)
+    {
+        unsigned int max_rate = cpi->per_frame_bandwidth
+                                * cpi->oxcf.rc_max_intra_bitrate_pct / 100;
+
+        if (target > max_rate)
+            target = max_rate;
+    }
+
+    cpi->this_frame_target = target;
+
+    // TODO: if we separate rate targeting from Q targetting, move this.
+    // Reset the active worst quality to the baseline value for key frames.
+    if (cpi->pass != 2)
+        cpi->active_worst_quality = cpi->worst_quality;
+
+#if 0
+    {
+        FILE *f;
+
+        f = fopen("kf_boost.stt", "a");
+        //fprintf(f, " %8d %10d %10d %10d %10d %10d %10d\n",
+        //  cpi->common.current_video_frame,  cpi->target_bandwidth, cpi->frames_to_key, kf_boost_qadjustment[cpi->ni_av_qi], cpi->kf_boost, (cpi->this_frame_target *100 / cpi->per_frame_bandwidth), cpi->this_frame_target );
+
+        fprintf(f, " %8u %10d %10d %10d\n",
+                cpi->common.current_video_frame,  cpi->gfu_boost, cpi->baseline_gf_interval, cpi->source_alt_ref_pending);
+
+        fclose(f);
+    }
+#endif
+}
+
+
+//  Do the best we can to define the parameters for the next GF based on what
+// information we have available.
+static void calc_gf_params(VP8_COMP *cpi)
+{
+    int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
+    int Boost = 0;
+
+    int gf_frame_useage = 0;      // Golden frame useage since last GF
+    int tot_mbs = cpi->recent_ref_frame_usage[INTRA_FRAME]  +
+                  cpi->recent_ref_frame_usage[LAST_FRAME]   +
+                  cpi->recent_ref_frame_usage[GOLDEN_FRAME] +
+                  cpi->recent_ref_frame_usage[ALTREF_FRAME];
+
+    int pct_gf_active = (100 * cpi->gf_active_count) / (cpi->common.mb_rows * cpi->common.mb_cols);
+
+    // Reset the last boost indicator
+    //cpi->last_boost = 100;
+
+    if (tot_mbs)
+        gf_frame_useage = (cpi->recent_ref_frame_usage[GOLDEN_FRAME] + cpi->recent_ref_frame_usage[ALTREF_FRAME]) * 100 / tot_mbs;
+
+    if (pct_gf_active > gf_frame_useage)
+        gf_frame_useage = pct_gf_active;
+
+    // Not two pass
+    if (cpi->pass != 2)
+    {
+        // Single Pass lagged mode: TBD
+        if (0)
+        {
+        }
+
+        // Single Pass compression: Has to use current and historical data
+        else
+        {
+#if 0
+            // Experimental code
+            int index = cpi->one_pass_frame_index;
+            int frames_to_scan = (cpi->max_gf_interval <= MAX_LAG_BUFFERS) ? cpi->max_gf_interval : MAX_LAG_BUFFERS;
+
+            /*
+            // *************** Experimental code - incomplete
+            double decay_val = 1.0;
+            double IIAccumulator = 0.0;
+            double last_iiaccumulator = 0.0;
+            double IIRatio;
+
+            cpi->one_pass_frame_index = cpi->common.current_video_frame%MAX_LAG_BUFFERS;
+
+            for ( i = 0; i < (frames_to_scan - 1); i++ )
+            {
+                if ( index < 0 )
+                    index = MAX_LAG_BUFFERS;
+                index --;
+
+                if ( cpi->one_pass_frame_stats[index].frame_coded_error > 0.0 )
+                {
+                    IIRatio = cpi->one_pass_frame_stats[index].frame_intra_error / cpi->one_pass_frame_stats[index].frame_coded_error;
+
+                    if ( IIRatio > 30.0 )
+                        IIRatio = 30.0;
+                }
+                else
+                    IIRatio = 30.0;
+
+                IIAccumulator += IIRatio * decay_val;
+
+                decay_val = decay_val * cpi->one_pass_frame_stats[index].frame_pcnt_inter;
+
+                if (    (i > MIN_GF_INTERVAL) &&
+                        ((IIAccumulator - last_iiaccumulator) < 2.0) )
+                {
+                    break;
+                }
+                last_iiaccumulator = IIAccumulator;
+            }
+
+            Boost = IIAccumulator*100.0/16.0;
+            cpi->baseline_gf_interval = i;
+
+            */
+#else
+
+            /*************************************************************/
+            // OLD code
+
+            // Adjust boost based upon ambient Q
+            Boost = GFQ_ADJUSTMENT;
+
+            // Adjust based upon most recently measure intra useage
+            Boost = Boost * gf_intra_usage_adjustment[(cpi->this_frame_percent_intra < 15) ? cpi->this_frame_percent_intra : 14] / 100;
+
+            // Adjust gf boost based upon GF usage since last GF
+            Boost = Boost * gf_adjust_table[gf_frame_useage] / 100;
+#endif
+        }
+
+        // golden frame boost without recode loop often goes awry.  be safe by keeping numbers down.
+        if (!cpi->sf.recode_loop)
+        {
+            if (cpi->compressor_speed == 2)
+                Boost = Boost / 2;
+        }
+
+        // Apply an upper limit based on Q for 1 pass encodes
+        if (Boost > kf_gf_boost_qlimits[Q] && (cpi->pass == 0))
+            Boost = kf_gf_boost_qlimits[Q];
+
+        // Apply lower limits to boost.
+        else if (Boost < 110)
+            Boost = 110;
+
+        // Note the boost used
+        cpi->last_boost = Boost;
+
+    }
+
+    // Estimate next interval
+    // This is updated once the real frame size/boost is known.
+    if (cpi->oxcf.fixed_q == -1)
+    {
+        if (cpi->pass == 2)         // 2 Pass
+        {
+            cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
+        }
+        else                            // 1 Pass
+        {
+            cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
+
+            if (cpi->last_boost > 750)
+                cpi->frames_till_gf_update_due++;
+
+            if (cpi->last_boost > 1000)
+                cpi->frames_till_gf_update_due++;
+
+            if (cpi->last_boost > 1250)
+                cpi->frames_till_gf_update_due++;
+
+            if (cpi->last_boost >= 1500)
+                cpi->frames_till_gf_update_due ++;
+
+            if (gf_interval_table[gf_frame_useage] > cpi->frames_till_gf_update_due)
+                cpi->frames_till_gf_update_due = gf_interval_table[gf_frame_useage];
+
+            if (cpi->frames_till_gf_update_due > cpi->max_gf_interval)
+                cpi->frames_till_gf_update_due = cpi->max_gf_interval;
+        }
+    }
+    else
+        cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
+
+    // ARF on or off
+    if (cpi->pass != 2)
+    {
+        // For now Alt ref is not allowed except in 2 pass modes.
+        cpi->source_alt_ref_pending = 0;
+
+        /*if ( cpi->oxcf.fixed_q == -1)
+        {
+            if ( cpi->oxcf.play_alternate && (cpi->last_boost > (100 + (AF_THRESH*cpi->frames_till_gf_update_due)) ) )
+                cpi->source_alt_ref_pending = 1;
+            else
+                cpi->source_alt_ref_pending = 0;
+        }*/
+    }
+}
+
+
+static void calc_pframe_target_size(VP8_COMP *cpi)
+{
+    int min_frame_target;
+    int Adjustment;
+    int old_per_frame_bandwidth = cpi->per_frame_bandwidth;
+
+    if ( cpi->current_layer > 0)
+        cpi->per_frame_bandwidth =
+            cpi->layer_context[cpi->current_layer].avg_frame_size_for_layer;
+
+    min_frame_target = 0;
+
+    if (cpi->pass == 2)
+    {
+        min_frame_target = cpi->min_frame_bandwidth;
+
+        if (min_frame_target < (cpi->av_per_frame_bandwidth >> 5))
+            min_frame_target = cpi->av_per_frame_bandwidth >> 5;
+    }
+    else if (min_frame_target < cpi->per_frame_bandwidth / 4)
+        min_frame_target = cpi->per_frame_bandwidth / 4;
+
+
+    // Special alt reference frame case
+    if((cpi->common.refresh_alt_ref_frame) && (cpi->oxcf.number_of_layers == 1))
+    {
+        if (cpi->pass == 2)
+        {
+            cpi->per_frame_bandwidth = cpi->twopass.gf_bits;                       // Per frame bit target for the alt ref frame
+            cpi->this_frame_target = cpi->per_frame_bandwidth;
+        }
+
+        /* One Pass ??? TBD */
+        /*else
+        {
+            int frames_in_section;
+            int allocation_chunks;
+            int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
+            int alt_boost;
+            int max_arf_rate;
+
+            alt_boost = (cpi->gfu_boost * 3 * GFQ_ADJUSTMENT) / (2 * 100);
+            alt_boost += (cpi->frames_till_gf_update_due * 50);
+
+            // If alt ref is not currently active then we have a pottential double hit with GF and ARF so reduce the boost a bit.
+            // A similar thing is done on GFs that preceed a arf update.
+            if ( !cpi->source_alt_ref_active )
+                alt_boost = alt_boost * 3 / 4;
+
+            frames_in_section = cpi->frames_till_gf_update_due+1;                                   // Standard frames + GF
+            allocation_chunks = (frames_in_section * 100) + alt_boost;
+
+            // Normalize Altboost and allocations chunck down to prevent overflow
+            while ( alt_boost > 1000 )
+            {
+                alt_boost /= 2;
+                allocation_chunks /= 2;
+            }
+
+            else
+            {
+                int bits_in_section;
+
+                if ( cpi->kf_overspend_bits > 0 )
+                {
+                    Adjustment = (cpi->kf_bitrate_adjustment <= cpi->kf_overspend_bits) ? cpi->kf_bitrate_adjustment : cpi->kf_overspend_bits;
+
+                    if ( Adjustment > (cpi->per_frame_bandwidth - min_frame_target) )
+                        Adjustment = (cpi->per_frame_bandwidth - min_frame_target);
+
+                    cpi->kf_overspend_bits -= Adjustment;
+
+                    // Calculate an inter frame bandwidth target for the next few frames designed to recover
+                    // any extra bits spent on the key frame.
+                    cpi->inter_frame_target = cpi->per_frame_bandwidth - Adjustment;
+                    if ( cpi->inter_frame_target < min_frame_target )
+                        cpi->inter_frame_target = min_frame_target;
+                }
+                else
+                    cpi->inter_frame_target = cpi->per_frame_bandwidth;
+
+                bits_in_section = cpi->inter_frame_target * frames_in_section;
+
+                // Avoid loss of precision but avoid overflow
+                if ( (bits_in_section>>7) > allocation_chunks )
+                    cpi->this_frame_target = alt_boost * (bits_in_section / allocation_chunks);
+                else
+                    cpi->this_frame_target = (alt_boost * bits_in_section) / allocation_chunks;
+            }
+        }
+        */
+    }
+
+    // Normal frames (gf,and inter)
+    else
+    {
+        // 2 pass
+        if (cpi->pass == 2)
+        {
+            cpi->this_frame_target = cpi->per_frame_bandwidth;
+        }
+        // 1 pass
+        else
+        {
+            // Make rate adjustment to recover bits spent in key frame
+            // Test to see if the key frame inter data rate correction should still be in force
+            if (cpi->kf_overspend_bits > 0)
+            {
+                Adjustment = (cpi->kf_bitrate_adjustment <= cpi->kf_overspend_bits) ? cpi->kf_bitrate_adjustment : cpi->kf_overspend_bits;
+
+                if (Adjustment > (cpi->per_frame_bandwidth - min_frame_target))
+                    Adjustment = (cpi->per_frame_bandwidth - min_frame_target);
+
+                cpi->kf_overspend_bits -= Adjustment;
+
+                // Calculate an inter frame bandwidth target for the next few frames designed to recover
+                // any extra bits spent on the key frame.
+                cpi->this_frame_target = cpi->per_frame_bandwidth - Adjustment;
+
+                if (cpi->this_frame_target < min_frame_target)
+                    cpi->this_frame_target = min_frame_target;
+            }
+            else
+                cpi->this_frame_target = cpi->per_frame_bandwidth;
+
+            // If appropriate make an adjustment to recover bits spent on a recent GF
+            if ((cpi->gf_overspend_bits > 0) && (cpi->this_frame_target > min_frame_target))
+            {
+                int Adjustment = (cpi->non_gf_bitrate_adjustment <= cpi->gf_overspend_bits) ? cpi->non_gf_bitrate_adjustment : cpi->gf_overspend_bits;
+
+                if (Adjustment > (cpi->this_frame_target - min_frame_target))
+                    Adjustment = (cpi->this_frame_target - min_frame_target);
+
+                cpi->gf_overspend_bits -= Adjustment;
+                cpi->this_frame_target -= Adjustment;
+            }
+
+            // Apply small + and - boosts for non gf frames
+            if ((cpi->last_boost > 150) && (cpi->frames_till_gf_update_due > 0) &&
+                (cpi->current_gf_interval >= (MIN_GF_INTERVAL << 1)))
+            {
+                // % Adjustment limited to the range 1% to 10%
+                Adjustment = (cpi->last_boost - 100) >> 5;
+
+                if (Adjustment < 1)
+                    Adjustment = 1;
+                else if (Adjustment > 10)
+                    Adjustment = 10;
+
+                // Convert to bits
+                Adjustment = (cpi->this_frame_target * Adjustment) / 100;
+
+                if (Adjustment > (cpi->this_frame_target - min_frame_target))
+                    Adjustment = (cpi->this_frame_target - min_frame_target);
+
+                if (cpi->common.frames_since_golden == (cpi->current_gf_interval >> 1))
+                    cpi->this_frame_target += ((cpi->current_gf_interval - 1) * Adjustment);
+                else
+                    cpi->this_frame_target -= Adjustment;
+            }
+        }
+    }
+
+    // Sanity check that the total sum of adjustments is not above the maximum allowed
+    // That is that having allowed for KF and GF penalties we have not pushed the
+    // current interframe target to low. If the adjustment we apply here is not capable of recovering
+    // all the extra bits we have spent in the KF or GF then the remainder will have to be recovered over
+    // a longer time span via other buffer / rate control mechanisms.
+    if (cpi->this_frame_target < min_frame_target)
+        cpi->this_frame_target = min_frame_target;
+
+    if (!cpi->common.refresh_alt_ref_frame)
+        // Note the baseline target data rate for this inter frame.
+        cpi->inter_frame_target = cpi->this_frame_target;
+
+    // One Pass specific code
+    if (cpi->pass == 0)
+    {
+        // Adapt target frame size with respect to any buffering constraints:
+        if (cpi->buffered_mode)
+        {
+            int one_percent_bits = 1 + cpi->oxcf.optimal_buffer_level / 100;
+
+            if ((cpi->buffer_level < cpi->oxcf.optimal_buffer_level) ||
+                (cpi->bits_off_target < cpi->oxcf.optimal_buffer_level))
+            {
+                int percent_low = 0;
+
+                // Decide whether or not we need to adjust the frame data rate target.
+                //
+                // If we are are below the optimal buffer fullness level and adherence
+                // to buffering constraints is important to the end usage then adjust
+                // the per frame target.
+                if ((cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
+                    (cpi->buffer_level < cpi->oxcf.optimal_buffer_level))
+                {
+                    percent_low =
+                        (cpi->oxcf.optimal_buffer_level - cpi->buffer_level) /
+                        one_percent_bits;
+                }
+                // Are we overshooting the long term clip data rate...
+                else if (cpi->bits_off_target < 0)
+                {
+                    // Adjust per frame data target downwards to compensate.
+                    percent_low = (int)(100 * -cpi->bits_off_target /
+                                       (cpi->total_byte_count * 8));
+                }
+
+                if (percent_low > cpi->oxcf.under_shoot_pct)
+                    percent_low = cpi->oxcf.under_shoot_pct;
+                else if (percent_low < 0)
+                    percent_low = 0;
+
+                // lower the target bandwidth for this frame.
+                cpi->this_frame_target -=
+                        (cpi->this_frame_target * percent_low) / 200;
+
+                // Are we using allowing control of active_worst_allowed_q
+                // according to buffer level.
+                if (cpi->auto_worst_q && cpi->ni_frames > 150)
+                {
+                    int critical_buffer_level;
+
+                    // For streaming applications the most important factor is
+                    // cpi->buffer_level as this takes into account the
+                    // specified short term buffering constraints. However,
+                    // hitting the long term clip data rate target is also
+                    // important.
+                    if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+                    {
+                        // Take the smaller of cpi->buffer_level and
+                        // cpi->bits_off_target
+                        critical_buffer_level =
+                            (cpi->buffer_level < cpi->bits_off_target)
+                            ? cpi->buffer_level : cpi->bits_off_target;
+                    }
+                    // For local file playback short term buffering constraints
+                    // are less of an issue
+                    else
+                    {
+                        // Consider only how we are doing for the clip as a
+                        // whole
+                        critical_buffer_level = cpi->bits_off_target;
+                    }
+
+                    // Set the active worst quality based upon the selected
+                    // buffer fullness number.
+                    if (critical_buffer_level < cpi->oxcf.optimal_buffer_level)
+                    {
+                        if ( critical_buffer_level >
+                             (cpi->oxcf.optimal_buffer_level >> 2) )
+                        {
+                            int64_t qadjustment_range =
+                                      cpi->worst_quality - cpi->ni_av_qi;
+                            int64_t above_base =
+                                      (critical_buffer_level -
+                                       (cpi->oxcf.optimal_buffer_level >> 2));
+
+                            // Step active worst quality down from
+                            // cpi->ni_av_qi when (critical_buffer_level ==
+                            // cpi->optimal_buffer_level) to
+                            // cpi->worst_quality when
+                            // (critical_buffer_level ==
+                            //     cpi->optimal_buffer_level >> 2)
+                            cpi->active_worst_quality =
+                                cpi->worst_quality -
+                                ((qadjustment_range * above_base) /
+                                 (cpi->oxcf.optimal_buffer_level*3>>2));
+                        }
+                        else
+                        {
+                            cpi->active_worst_quality = cpi->worst_quality;
+                        }
+                    }
+                    else
+                    {
+                        cpi->active_worst_quality = cpi->ni_av_qi;
+                    }
+                }
+                else
+                {
+                    cpi->active_worst_quality = cpi->worst_quality;
+                }
+            }
+            else
+            {
+                int percent_high = 0;
+
+                if ((cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+                     && (cpi->buffer_level > cpi->oxcf.optimal_buffer_level))
+                {
+                    percent_high = (cpi->buffer_level
+                                    - cpi->oxcf.optimal_buffer_level)
+                                   / one_percent_bits;
+                }
+                else if (cpi->bits_off_target > cpi->oxcf.optimal_buffer_level)
+                {
+                    percent_high = (int)((100 * cpi->bits_off_target)
+                                         / (cpi->total_byte_count * 8));
+                }
+
+                if (percent_high > cpi->oxcf.over_shoot_pct)
+                    percent_high = cpi->oxcf.over_shoot_pct;
+                else if (percent_high < 0)
+                    percent_high = 0;
+
+                cpi->this_frame_target += (cpi->this_frame_target *
+                                          percent_high) / 200;
+
+                // Are we allowing control of active_worst_allowed_q according
+                // to buffer level.
+                if (cpi->auto_worst_q && cpi->ni_frames > 150)
+                {
+                    // When using the relaxed buffer model stick to the user specified value
+                    cpi->active_worst_quality = cpi->ni_av_qi;
+                }
+                else
+                {
+                    cpi->active_worst_quality = cpi->worst_quality;
+                }
+            }
+
+            // Set active_best_quality to prevent quality rising too high
+            cpi->active_best_quality = cpi->best_quality;
+
+            // Worst quality obviously must not be better than best quality
+            if (cpi->active_worst_quality <= cpi->active_best_quality)
+                cpi->active_worst_quality = cpi->active_best_quality + 1;
+
+            if(cpi->active_worst_quality > 127)
+                cpi->active_worst_quality = 127;
+        }
+        // Unbuffered mode (eg. video conferencing)
+        else
+        {
+            // Set the active worst quality
+            cpi->active_worst_quality = cpi->worst_quality;
+        }
+
+        // Special trap for constrained quality mode
+        // "active_worst_quality" may never drop below cq level
+        // for any frame type.
+        if ( cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY &&
+             cpi->active_worst_quality < cpi->cq_target_quality)
+        {
+            cpi->active_worst_quality = cpi->cq_target_quality;
+        }
+    }
+
+    // Test to see if we have to drop a frame
+    // The auto-drop frame code is only used in buffered mode.
+    // In unbufferd mode (eg vide conferencing) the descision to
+    // code or drop a frame is made outside the codec in response to real
+    // world comms or buffer considerations.
+    if (cpi->drop_frames_allowed && cpi->buffered_mode &&
+        (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
+        ((cpi->common.frame_type != KEY_FRAME))) //|| !cpi->oxcf.allow_spatial_resampling) )
+    {
+        // Check for a buffer underun-crisis in which case we have to drop a frame
+        if ((cpi->buffer_level < 0))
+        {
+#if 0
+            FILE *f = fopen("dec.stt", "a");
+            fprintf(f, "%10d %10d %10d %10d ***** BUFFER EMPTY\n",
+                    (int) cpi->common.current_video_frame,
+                    cpi->decimation_factor, cpi->common.horiz_scale,
+                    (cpi->buffer_level * 100) / cpi->oxcf.optimal_buffer_level);
+            fclose(f);
+#endif
+            //vpx_log("Decoder: Drop frame due to bandwidth: %d \n",cpi->buffer_level, cpi->av_per_frame_bandwidth);
+
+            cpi->drop_frame = 1;
+        }
+
+#if 0
+        // Check for other drop frame crtieria (Note 2 pass cbr uses decimation on whole KF sections)
+        else if ((cpi->buffer_level < cpi->oxcf.drop_frames_water_mark * cpi->oxcf.optimal_buffer_level / 100) &&
+                 (cpi->drop_count < cpi->max_drop_count) && (cpi->pass == 0))
+        {
+            cpi->drop_frame = 1;
+        }
+
+#endif
+
+        if (cpi->drop_frame)
+        {
+            // Update the buffer level variable.
+            cpi->bits_off_target += cpi->av_per_frame_bandwidth;
+            if (cpi->bits_off_target > cpi->oxcf.maximum_buffer_size)
+              cpi->bits_off_target = cpi->oxcf.maximum_buffer_size;
+            cpi->buffer_level = cpi->bits_off_target;
+        }
+        else
+            cpi->drop_count = 0;
+    }
+
+    // Adjust target frame size for Golden Frames:
+    if (cpi->oxcf.error_resilient_mode == 0 &&
+        (cpi->frames_till_gf_update_due == 0) && !cpi->drop_frame)
+    {
+        //int Boost = 0;
+        int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
+
+        int gf_frame_useage = 0;      // Golden frame useage since last GF
+        int tot_mbs = cpi->recent_ref_frame_usage[INTRA_FRAME]  +
+                      cpi->recent_ref_frame_usage[LAST_FRAME]   +
+                      cpi->recent_ref_frame_usage[GOLDEN_FRAME] +
+                      cpi->recent_ref_frame_usage[ALTREF_FRAME];
+
+        int pct_gf_active = (100 * cpi->gf_active_count) / (cpi->common.mb_rows * cpi->common.mb_cols);
+
+        // Reset the last boost indicator
+        //cpi->last_boost = 100;
+
+        if (tot_mbs)
+            gf_frame_useage = (cpi->recent_ref_frame_usage[GOLDEN_FRAME] + cpi->recent_ref_frame_usage[ALTREF_FRAME]) * 100 / tot_mbs;
+
+        if (pct_gf_active > gf_frame_useage)
+            gf_frame_useage = pct_gf_active;
+
+        // Is a fixed manual GF frequency being used
+        if (cpi->auto_gold)
+        {
+            // For one pass throw a GF if recent frame intra useage is low or the GF useage is high
+            if ((cpi->pass == 0) && (cpi->this_frame_percent_intra < 15 || gf_frame_useage >= 5))
+                cpi->common.refresh_golden_frame = 1;
+
+            // Two pass GF descision
+            else if (cpi->pass == 2)
+                cpi->common.refresh_golden_frame = 1;
+        }
+
+#if 0
+
+        // Debug stats
+        if (0)
+        {
+            FILE *f;
+
+            f = fopen("gf_useaget.stt", "a");
+            fprintf(f, " %8ld %10ld %10ld %10ld %10ld\n",
+                    cpi->common.current_video_frame,  cpi->gfu_boost, GFQ_ADJUSTMENT, cpi->gfu_boost, gf_frame_useage);
+            fclose(f);
+        }
+
+#endif
+
+        if (cpi->common.refresh_golden_frame == 1)
+        {
+#if 0
+
+            if (0)   // p_gw
+            {
+                FILE *f;
+
+                f = fopen("GFexit.stt", "a");
+                fprintf(f, "%8ld GF coded\n", cpi->common.current_video_frame);
+                fclose(f);
+            }
+
+#endif
+
+            if (cpi->auto_adjust_gold_quantizer)
+            {
+                calc_gf_params(cpi);
+            }
+
+            // If we are using alternate ref instead of gf then do not apply the boost
+            // It will instead be applied to the altref update
+            // Jims modified boost
+            if (!cpi->source_alt_ref_active)
+            {
+                if (cpi->oxcf.fixed_q < 0)
+                {
+                    if (cpi->pass == 2)
+                    {
+                        cpi->this_frame_target = cpi->per_frame_bandwidth;          // The spend on the GF is defined in the two pass code for two pass encodes
+                    }
+                    else
+                    {
+                        int Boost = cpi->last_boost;
+                        int frames_in_section = cpi->frames_till_gf_update_due + 1;
+                        int allocation_chunks = (frames_in_section * 100) + (Boost - 100);
+                        int bits_in_section = cpi->inter_frame_target * frames_in_section;
+
+                        // Normalize Altboost and allocations chunck down to prevent overflow
+                        while (Boost > 1000)
+                        {
+                            Boost /= 2;
+                            allocation_chunks /= 2;
+                        }
+
+                        // Avoid loss of precision but avoid overflow
+                        if ((bits_in_section >> 7) > allocation_chunks)
+                            cpi->this_frame_target = Boost * (bits_in_section / allocation_chunks);
+                        else
+                            cpi->this_frame_target = (Boost * bits_in_section) / allocation_chunks;
+                    }
+                }
+                else
+                    cpi->this_frame_target =
+                        (estimate_bits_at_q(1, Q, cpi->common.MBs, 1.0)
+                         * cpi->last_boost) / 100;
+
+            }
+            // If there is an active ARF at this location use the minimum
+            // bits on this frame even if it is a contructed arf.
+            // The active maximum quantizer insures that an appropriate
+            // number of bits will be spent if needed for contstructed ARFs.
+            else
+            {
+                cpi->this_frame_target = 0;
+            }
+
+            cpi->current_gf_interval = cpi->frames_till_gf_update_due;
+
+        }
+    }
+
+    cpi->per_frame_bandwidth = old_per_frame_bandwidth;
+}
+
+
+void vp8_update_rate_correction_factors(VP8_COMP *cpi, int damp_var)
+{
+    int    Q = cpi->common.base_qindex;
+    int    correction_factor = 100;
+    double rate_correction_factor;
+    double adjustment_limit;
+
+    int    projected_size_based_on_q = 0;
+
+    // Clear down mmx registers to allow floating point in what follows
+    vp8_clear_system_state();  //__asm emms;
+
+    if (cpi->common.frame_type == KEY_FRAME)
+    {
+        rate_correction_factor = cpi->key_frame_rate_correction_factor;
+    }
+    else
+    {
+        if (cpi->common.refresh_alt_ref_frame || cpi->common.refresh_golden_frame)
+            rate_correction_factor = cpi->gf_rate_correction_factor;
+        else
+            rate_correction_factor = cpi->rate_correction_factor;
+    }
+
+    // Work out how big we would have expected the frame to be at this Q given the current correction factor.
+    // Stay in double to avoid int overflow when values are large
+    //projected_size_based_on_q = ((int)(.5 + rate_correction_factor * vp8_bits_per_mb[cpi->common.frame_type][Q]) * cpi->common.MBs) >> BPER_MB_NORMBITS;
+    projected_size_based_on_q = (int)(((.5 + rate_correction_factor * vp8_bits_per_mb[cpi->common.frame_type][Q]) * cpi->common.MBs) / (1 << BPER_MB_NORMBITS));
+
+    // Make some allowance for cpi->zbin_over_quant
+    if (cpi->zbin_over_quant > 0)
+    {
+        int Z = cpi->zbin_over_quant;
+        double Factor = 0.99;
+        double factor_adjustment = 0.01 / 256.0; //(double)ZBIN_OQ_MAX;
+
+        while (Z > 0)
+        {
+            Z --;
+            projected_size_based_on_q =
+                (int)(Factor * projected_size_based_on_q);
+            Factor += factor_adjustment;
+
+            if (Factor  >= 0.999)
+                Factor = 0.999;
+        }
+    }
+
+    // Work out a size correction factor.
+    //if ( cpi->this_frame_target > 0 )
+    //  correction_factor = (100 * cpi->projected_frame_size) / cpi->this_frame_target;
+    if (projected_size_based_on_q > 0)
+        correction_factor = (100 * cpi->projected_frame_size) / projected_size_based_on_q;
+
+    // More heavily damped adjustment used if we have been oscillating either side of target
+    switch (damp_var)
+    {
+    case 0:
+        adjustment_limit = 0.75;
+        break;
+    case 1:
+        adjustment_limit = 0.375;
+        break;
+    case 2:
+    default:
+        adjustment_limit = 0.25;
+        break;
+    }
+
+    //if ( (correction_factor > 102) && (Q < cpi->active_worst_quality) )
+    if (correction_factor > 102)
+    {
+        // We are not already at the worst allowable quality
+        correction_factor = (int)(100.5 + ((correction_factor - 100) * adjustment_limit));
+        rate_correction_factor = ((rate_correction_factor * correction_factor) / 100);
+
+        // Keep rate_correction_factor within limits
+        if (rate_correction_factor > MAX_BPB_FACTOR)
+            rate_correction_factor = MAX_BPB_FACTOR;
+    }
+    //else if ( (correction_factor < 99) && (Q > cpi->active_best_quality) )
+    else if (correction_factor < 99)
+    {
+        // We are not already at the best allowable quality
+        correction_factor = (int)(100.5 - ((100 - correction_factor) * adjustment_limit));
+        rate_correction_factor = ((rate_correction_factor * correction_factor) / 100);
+
+        // Keep rate_correction_factor within limits
+        if (rate_correction_factor < MIN_BPB_FACTOR)
+            rate_correction_factor = MIN_BPB_FACTOR;
+    }
+
+    if (cpi->common.frame_type == KEY_FRAME)
+        cpi->key_frame_rate_correction_factor = rate_correction_factor;
+    else
+    {
+        if (cpi->common.refresh_alt_ref_frame || cpi->common.refresh_golden_frame)
+            cpi->gf_rate_correction_factor = rate_correction_factor;
+        else
+            cpi->rate_correction_factor = rate_correction_factor;
+    }
+}
+
+
+int vp8_regulate_q(VP8_COMP *cpi, int target_bits_per_frame)
+{
+    int Q = cpi->active_worst_quality;
+
+    // Reset Zbin OQ value
+    cpi->zbin_over_quant = 0;
+
+    if (cpi->oxcf.fixed_q >= 0)
+    {
+        Q = cpi->oxcf.fixed_q;
+
+        if (cpi->common.frame_type == KEY_FRAME)
+        {
+            Q = cpi->oxcf.key_q;
+        }
+        else if (cpi->common.refresh_alt_ref_frame)
+        {
+            Q = cpi->oxcf.alt_q;
+        }
+        else if (cpi->common.refresh_golden_frame)
+        {
+            Q = cpi->oxcf.gold_q;
+        }
+
+    }
+    else
+    {
+        int i;
+        int last_error = INT_MAX;
+        int target_bits_per_mb;
+        int bits_per_mb_at_this_q;
+        double correction_factor;
+
+        // Select the appropriate correction factor based upon type of frame.
+        if (cpi->common.frame_type == KEY_FRAME)
+            correction_factor = cpi->key_frame_rate_correction_factor;
+        else
+        {
+            if (cpi->common.refresh_alt_ref_frame || cpi->common.refresh_golden_frame)
+                correction_factor = cpi->gf_rate_correction_factor;
+            else
+                correction_factor = cpi->rate_correction_factor;
+        }
+
+        // Calculate required scaling factor based on target frame size and size of frame produced using previous Q
+        if (target_bits_per_frame >= (INT_MAX >> BPER_MB_NORMBITS))
+            target_bits_per_mb = (target_bits_per_frame / cpi->common.MBs) << BPER_MB_NORMBITS;       // Case where we would overflow int
+        else
+            target_bits_per_mb = (target_bits_per_frame << BPER_MB_NORMBITS) / cpi->common.MBs;
+
+        i = cpi->active_best_quality;
+
+        do
+        {
+            bits_per_mb_at_this_q = (int)(.5 + correction_factor * vp8_bits_per_mb[cpi->common.frame_type][i]);
+
+            if (bits_per_mb_at_this_q <= target_bits_per_mb)
+            {
+                if ((target_bits_per_mb - bits_per_mb_at_this_q) <= last_error)
+                    Q = i;
+                else
+                    Q = i - 1;
+
+                break;
+            }
+            else
+                last_error = bits_per_mb_at_this_q - target_bits_per_mb;
+        }
+        while (++i <= cpi->active_worst_quality);
+
+
+        // If we are at MAXQ then enable Q over-run which seeks to claw back additional bits through things like
+        // the RD multiplier and zero bin size.
+        if (Q >= MAXQ)
+        {
+            int zbin_oqmax;
+
+            double Factor = 0.99;
+            double factor_adjustment = 0.01 / 256.0; //(double)ZBIN_OQ_MAX;
+
+            if (cpi->common.frame_type == KEY_FRAME)
+                zbin_oqmax = 0; //ZBIN_OQ_MAX/16
+            else if (cpi->common.refresh_alt_ref_frame || (cpi->common.refresh_golden_frame && !cpi->source_alt_ref_active))
+                zbin_oqmax = 16;
+            else
+                zbin_oqmax = ZBIN_OQ_MAX;
+
+            /*{
+                double Factor = (double)target_bits_per_mb/(double)bits_per_mb_at_this_q;
+                double Oq;
+
+                Factor = Factor/1.2683;
+
+                Oq = pow( Factor, (1.0/-0.165) );
+
+                if ( Oq > zbin_oqmax )
+                    Oq = zbin_oqmax;
+
+                cpi->zbin_over_quant = (int)Oq;
+            }*/
+
+            // Each incrment in the zbin is assumed to have a fixed effect on bitrate. This is not of course true.
+            // The effect will be highly clip dependent and may well have sudden steps.
+            // The idea here is to acheive higher effective quantizers than the normal maximum by expanding the zero
+            // bin and hence decreasing the number of low magnitude non zero coefficients.
+            while (cpi->zbin_over_quant < zbin_oqmax)
+            {
+                cpi->zbin_over_quant ++;
+
+                if (cpi->zbin_over_quant > zbin_oqmax)
+                    cpi->zbin_over_quant = zbin_oqmax;
+
+                // Adjust bits_per_mb_at_this_q estimate
+                bits_per_mb_at_this_q = (int)(Factor * bits_per_mb_at_this_q);
+                Factor += factor_adjustment;
+
+                if (Factor  >= 0.999)
+                    Factor = 0.999;
+
+                if (bits_per_mb_at_this_q <= target_bits_per_mb)    // Break out if we get down to the target rate
+                    break;
+            }
+
+        }
+    }
+
+    return Q;
+}
+
+
+static int estimate_keyframe_frequency(VP8_COMP *cpi)
+{
+    int i;
+
+    // Average key frame frequency
+    int av_key_frame_frequency = 0;
+
+    /* First key frame at start of sequence is a special case. We have no
+     * frequency data.
+     */
+    if (cpi->key_frame_count == 1)
+    {
+        /* Assume a default of 1 kf every 2 seconds, or the max kf interval,
+         * whichever is smaller.
+         */
+        int key_freq = cpi->oxcf.key_freq>0 ? cpi->oxcf.key_freq : 1;
+        av_key_frame_frequency = (int)cpi->output_frame_rate * 2;
+
+        if (cpi->oxcf.auto_key && av_key_frame_frequency > key_freq)
+            av_key_frame_frequency = cpi->oxcf.key_freq;
+
+        cpi->prior_key_frame_distance[KEY_FRAME_CONTEXT - 1]
+            = av_key_frame_frequency;
+    }
+    else
+    {
+        unsigned int total_weight = 0;
+        int last_kf_interval =
+                (cpi->frames_since_key > 0) ? cpi->frames_since_key : 1;
+
+        /* reset keyframe context and calculate weighted average of last
+         * KEY_FRAME_CONTEXT keyframes
+         */
+        for (i = 0; i < KEY_FRAME_CONTEXT; i++)
+        {
+            if (i < KEY_FRAME_CONTEXT - 1)
+                cpi->prior_key_frame_distance[i]
+                    = cpi->prior_key_frame_distance[i+1];
+            else
+                cpi->prior_key_frame_distance[i] = last_kf_interval;
+
+            av_key_frame_frequency += prior_key_frame_weight[i]
+                                      * cpi->prior_key_frame_distance[i];
+            total_weight += prior_key_frame_weight[i];
+        }
+
+        av_key_frame_frequency  /= total_weight;
+
+    }
+    return av_key_frame_frequency;
+}
+
+
+void vp8_adjust_key_frame_context(VP8_COMP *cpi)
+{
+    // Clear down mmx registers to allow floating point in what follows
+    vp8_clear_system_state();
+
+    // Do we have any key frame overspend to recover?
+    // Two-pass overspend handled elsewhere.
+    if ((cpi->pass != 2)
+         && (cpi->projected_frame_size > cpi->per_frame_bandwidth))
+    {
+        int overspend;
+
+        /* Update the count of key frame overspend to be recovered in
+         * subsequent frames. A portion of the KF overspend is treated as gf
+         * overspend (and hence recovered more quickly) as the kf is also a
+         * gf. Otherwise the few frames following each kf tend to get more
+         * bits allocated than those following other gfs.
+         */
+        overspend = (cpi->projected_frame_size - cpi->per_frame_bandwidth);
+
+        if (cpi->oxcf.number_of_layers > 1)
+            cpi->kf_overspend_bits += overspend;
+        else
+        {
+            cpi->kf_overspend_bits += overspend * 7 / 8;
+            cpi->gf_overspend_bits += overspend * 1 / 8;
+        }
+
+        /* Work out how much to try and recover per frame. */
+        cpi->kf_bitrate_adjustment = cpi->kf_overspend_bits
+                                     / estimate_keyframe_frequency(cpi);
+    }
+
+    cpi->frames_since_key = 0;
+    cpi->key_frame_count++;
+}
+
+
+void vp8_compute_frame_size_bounds(VP8_COMP *cpi, int *frame_under_shoot_limit, int *frame_over_shoot_limit)
+{
+    // Set-up bounds on acceptable frame size:
+    if (cpi->oxcf.fixed_q >= 0)
+    {
+        // Fixed Q scenario: frame size never outranges target (there is no target!)
+        *frame_under_shoot_limit = 0;
+        *frame_over_shoot_limit  = INT_MAX;
+    }
+    else
+    {
+        if (cpi->common.frame_type == KEY_FRAME)
+        {
+            *frame_over_shoot_limit  = cpi->this_frame_target * 9 / 8;
+            *frame_under_shoot_limit = cpi->this_frame_target * 7 / 8;
+        }
+        else
+        {
+            if (cpi->oxcf.number_of_layers > 1 ||
+                cpi->common.refresh_alt_ref_frame ||
+                cpi->common.refresh_golden_frame)
+            {
+                *frame_over_shoot_limit  = cpi->this_frame_target * 9 / 8;
+                *frame_under_shoot_limit = cpi->this_frame_target * 7 / 8;
+            }
+            else
+            {
+                // For CBR take buffer fullness into account
+                if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+                {
+                    if (cpi->buffer_level >= ((cpi->oxcf.optimal_buffer_level + cpi->oxcf.maximum_buffer_size) >> 1))
+                    {
+                        // Buffer is too full so relax overshoot and tighten undershoot
+                        *frame_over_shoot_limit  = cpi->this_frame_target * 12 / 8;
+                        *frame_under_shoot_limit = cpi->this_frame_target * 6 / 8;
+                    }
+                    else if (cpi->buffer_level <= (cpi->oxcf.optimal_buffer_level >> 1))
+                    {
+                        // Buffer is too low so relax undershoot and tighten overshoot
+                        *frame_over_shoot_limit  = cpi->this_frame_target * 10 / 8;
+                        *frame_under_shoot_limit = cpi->this_frame_target * 4 / 8;
+                    }
+                    else
+                    {
+                        *frame_over_shoot_limit  = cpi->this_frame_target * 11 / 8;
+                        *frame_under_shoot_limit = cpi->this_frame_target * 5 / 8;
+                    }
+                }
+                // VBR and CQ mode
+                // Note that tighter restrictions here can help quality but hurt encode speed
+                else
+                {
+                    // Stron overshoot limit for constrained quality
+                    if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY)
+                    {
+                        *frame_over_shoot_limit  = cpi->this_frame_target * 11 / 8;
+                        *frame_under_shoot_limit = cpi->this_frame_target * 2 / 8;
+                    }
+                    else
+                    {
+                        *frame_over_shoot_limit  = cpi->this_frame_target * 11 / 8;
+                        *frame_under_shoot_limit = cpi->this_frame_target * 5 / 8;
+                    }
+                }
+            }
+        }
+
+        // For very small rate targets where the fractional adjustment
+        // (eg * 7/8) may be tiny make sure there is at least a minimum
+        // range.
+        *frame_over_shoot_limit += 200;
+        *frame_under_shoot_limit -= 200;
+        if ( *frame_under_shoot_limit < 0 )
+            *frame_under_shoot_limit = 0;
+
+    }
+}
+
+
+// return of 0 means drop frame
+int vp8_pick_frame_size(VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = &cpi->common;
+
+    if (cm->frame_type == KEY_FRAME)
+        calc_iframe_target_size(cpi);
+    else
+    {
+        calc_pframe_target_size(cpi);
+
+        // Check if we're dropping the frame:
+        if (cpi->drop_frame)
+        {
+            cpi->drop_frame = 0;
+            cpi->drop_count++;
+            return 0;
+        }
+    }
+    return 1;
+}
diff --git a/vp8/encoder/ratectrl.h b/vp8/encoder/ratectrl.h
new file mode 100644 (file)
index 0000000..d4f7796
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#if !defined __INC_RATECTRL_H
+
+#include "onyx_int.h"
+
+extern void vp8_save_coding_context(VP8_COMP *cpi);
+extern void vp8_restore_coding_context(VP8_COMP *cpi);
+
+extern void vp8_setup_key_frame(VP8_COMP *cpi);
+extern void vp8_update_rate_correction_factors(VP8_COMP *cpi, int damp_var);
+extern int vp8_regulate_q(VP8_COMP *cpi, int target_bits_per_frame);
+extern void vp8_adjust_key_frame_context(VP8_COMP *cpi);
+extern void vp8_compute_frame_size_bounds(VP8_COMP *cpi, int *frame_under_shoot_limit, int *frame_over_shoot_limit);
+
+// return of 0 means drop frame
+extern int vp8_pick_frame_size(VP8_COMP *cpi);
+
+#endif
diff --git a/vp8/encoder/rdopt.c b/vp8/encoder/rdopt.c
new file mode 100644 (file)
index 0000000..2b706ba
--- /dev/null
@@ -0,0 +1,2576 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include <stdio.h>
+#include <math.h>
+#include <limits.h>
+#include <assert.h>
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "vp8/common/pragmas.h"
+#include "tokenize.h"
+#include "treewriter.h"
+#include "onyx_int.h"
+#include "modecosts.h"
+#include "encodeintra.h"
+#include "vp8/common/entropymode.h"
+#include "vp8/common/reconinter.h"
+#include "vp8/common/reconintra4x4.h"
+#include "vp8/common/findnearmv.h"
+#include "vp8/common/quant_common.h"
+#include "encodemb.h"
+#include "quantize.h"
+#include "vp8/common/variance.h"
+#include "mcomp.h"
+#include "rdopt.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vp8/common/systemdependent.h"
+#if CONFIG_TEMPORAL_DENOISING
+#include "denoising.h"
+#endif
+
+extern void vp8_update_zbin_extra(VP8_COMP *cpi, MACROBLOCK *x);
+
+#define MAXF(a,b)            (((a) > (b)) ? (a) : (b))
+
+typedef struct rate_distortion_struct
+{
+    int rate2;
+    int rate_y;
+    int rate_uv;
+    int distortion2;
+    int distortion_uv;
+} RATE_DISTORTION;
+
+typedef struct best_mode_struct
+{
+  int yrd;
+  int rd;
+  int intra_rd;
+  MB_MODE_INFO mbmode;
+  union b_mode_info bmodes[16];
+  PARTITION_INFO partition;
+} BEST_MODE;
+
+static const int auto_speed_thresh[17] =
+{
+    1000,
+    200,
+    150,
+    130,
+    150,
+    125,
+    120,
+    115,
+    115,
+    115,
+    115,
+    115,
+    115,
+    115,
+    115,
+    115,
+    105
+};
+
+const MB_PREDICTION_MODE vp8_mode_order[MAX_MODES] =
+{
+    ZEROMV,
+    DC_PRED,
+
+    NEARESTMV,
+    NEARMV,
+
+    ZEROMV,
+    NEARESTMV,
+
+    ZEROMV,
+    NEARESTMV,
+
+    NEARMV,
+    NEARMV,
+
+    V_PRED,
+    H_PRED,
+    TM_PRED,
+
+    NEWMV,
+    NEWMV,
+    NEWMV,
+
+    SPLITMV,
+    SPLITMV,
+    SPLITMV,
+
+    B_PRED,
+};
+
+/* This table determines the search order in reference frame priority order,
+ * which may not necessarily match INTRA,LAST,GOLDEN,ARF
+ */
+const int vp8_ref_frame_order[MAX_MODES] =
+{
+    1,
+    0,
+
+    1,
+    1,
+
+    2,
+    2,
+
+    3,
+    3,
+
+    2,
+    3,
+
+    0,
+    0,
+    0,
+
+    1,
+    2,
+    3,
+
+    1,
+    2,
+    3,
+
+    0,
+};
+
+static void fill_token_costs(
+    unsigned int c      [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS],
+    const vp8_prob p    [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [ENTROPY_NODES]
+)
+{
+    int i, j, k;
+
+
+    for (i = 0; i < BLOCK_TYPES; i++)
+        for (j = 0; j < COEF_BANDS; j++)
+            for (k = 0; k < PREV_COEF_CONTEXTS; k++)
+                // check for pt=0 and band > 1 if block type 0 and 0 if blocktype 1
+                if(k==0 && j>(i==0) )
+                    vp8_cost_tokens2((int *)(c [i][j][k]), p [i][j][k], vp8_coef_tree,2);
+                else
+                    vp8_cost_tokens((int *)(c [i][j][k]), p [i][j][k], vp8_coef_tree);
+}
+
+static int rd_iifactor [ 32 ] =  {    4,   4,   3,   2,   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,
+                                 };
+
+/* values are now correlated to quantizer */
+static int sad_per_bit16lut[QINDEX_RANGE] =
+{
+    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,  4,  4,
+    4,  4,  4,  4,  4,  4,  4,  4,
+    4,  4,  5,  5,  5,  5,  5,  5,
+    5,  5,  5,  5,  5,  5,  6,  6,
+    6,  6,  6,  6,  6,  6,  6,  6,
+    6,  6,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  7,  8,  8,
+    8,  8,  8,  8,  8,  8,  8,  8,
+    8,  8,  9,  9,  9,  9,  9,  9,
+    9,  9,  9,  9,  9,  9,  10, 10,
+    10, 10, 10, 10, 10, 10, 11, 11,
+    11, 11, 11, 11, 12, 12, 12, 12,
+    12, 12, 13, 13, 13, 13, 14, 14
+};
+static int sad_per_bit4lut[QINDEX_RANGE] =
+{
+    2,  2,  2,  2,  2,  2,  3,  3,
+    3,  3,  3,  3,  3,  3,  3,  3,
+    3,  3,  3,  3,  4,  4,  4,  4,
+    4,  4,  4,  4,  4,  4,  5,  5,
+    5,  5,  5,  5,  6,  6,  6,  6,
+    6,  6,  6,  6,  6,  6,  6,  6,
+    7,  7,  7,  7,  7,  7,  7,  7,
+    7,  7,  7,  7,  7,  8,  8,  8,
+    8,  8,  9,  9,  9,  9,  9,  9,
+    10, 10, 10, 10, 10, 10, 10, 10,
+    11, 11, 11, 11, 11, 11, 11, 11,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    13, 13, 13, 13, 13, 13, 13, 14,
+    14, 14, 14, 14, 15, 15, 15, 15,
+    16, 16, 16, 16, 17, 17, 17, 18,
+    18, 18, 19, 19, 19, 20, 20, 20,
+};
+
+void vp8cx_initialize_me_consts(VP8_COMP *cpi, int QIndex)
+{
+    cpi->mb.sadperbit16 =  sad_per_bit16lut[QIndex];
+    cpi->mb.sadperbit4  =  sad_per_bit4lut[QIndex];
+}
+
+void vp8_initialize_rd_consts(VP8_COMP *cpi, int Qvalue)
+{
+    int q;
+    int i;
+    double capped_q = (Qvalue < 160) ? (double)Qvalue : 160.0;
+    double rdconst = 2.80;
+
+    vp8_clear_system_state();  //__asm emms;
+
+    // Further tests required to see if optimum is different
+    // for key frames, golden frames and arf frames.
+    // if (cpi->common.refresh_golden_frame ||
+    //     cpi->common.refresh_alt_ref_frame)
+    cpi->RDMULT = (int)(rdconst * (capped_q * capped_q));
+
+    // Extend rate multiplier along side quantizer zbin increases
+    if (cpi->zbin_over_quant  > 0)
+    {
+        double oq_factor;
+        double modq;
+
+        // Experimental code using the same basic equation as used for Q above
+        // The units of cpi->zbin_over_quant are 1/128 of Q bin size
+        oq_factor = 1.0 + ((double)0.0015625 * cpi->zbin_over_quant);
+        modq = (int)((double)capped_q * oq_factor);
+        cpi->RDMULT = (int)(rdconst * (modq * modq));
+    }
+
+    if (cpi->pass == 2 && (cpi->common.frame_type != KEY_FRAME))
+    {
+        if (cpi->twopass.next_iiratio > 31)
+            cpi->RDMULT += (cpi->RDMULT * rd_iifactor[31]) >> 4;
+        else
+            cpi->RDMULT +=
+                (cpi->RDMULT * rd_iifactor[cpi->twopass.next_iiratio]) >> 4;
+    }
+
+    cpi->mb.errorperbit = (cpi->RDMULT / 110);
+    cpi->mb.errorperbit += (cpi->mb.errorperbit==0);
+
+    vp8_set_speed_features(cpi);
+
+    q = (int)pow(Qvalue, 1.25);
+
+    if (q < 8)
+        q = 8;
+
+    if (cpi->RDMULT > 1000)
+    {
+        cpi->RDDIV = 1;
+        cpi->RDMULT /= 100;
+
+        for (i = 0; i < MAX_MODES; i++)
+        {
+            if (cpi->sf.thresh_mult[i] < INT_MAX)
+            {
+                cpi->rd_threshes[i] = cpi->sf.thresh_mult[i] * q / 100;
+            }
+            else
+            {
+                cpi->rd_threshes[i] = INT_MAX;
+            }
+
+            cpi->rd_baseline_thresh[i] = cpi->rd_threshes[i];
+        }
+    }
+    else
+    {
+        cpi->RDDIV = 100;
+
+        for (i = 0; i < MAX_MODES; i++)
+        {
+            if (cpi->sf.thresh_mult[i] < (INT_MAX / q))
+            {
+                cpi->rd_threshes[i] = cpi->sf.thresh_mult[i] * q;
+            }
+            else
+            {
+                cpi->rd_threshes[i] = INT_MAX;
+            }
+
+            cpi->rd_baseline_thresh[i] = cpi->rd_threshes[i];
+        }
+    }
+
+    {
+      // build token cost array for the type of frame we have now
+      FRAME_CONTEXT *l = &cpi->lfc_n;
+
+      if(cpi->common.refresh_alt_ref_frame)
+          l = &cpi->lfc_a;
+      else if(cpi->common.refresh_golden_frame)
+          l = &cpi->lfc_g;
+
+      fill_token_costs(
+          cpi->mb.token_costs,
+          (const vp8_prob( *)[8][3][11]) l->coef_probs
+      );
+      /*
+      fill_token_costs(
+          cpi->mb.token_costs,
+          (const vp8_prob( *)[8][3][11]) cpi->common.fc.coef_probs);
+      */
+
+
+      // TODO make these mode costs depend on last,alt or gold too.  (jbb)
+      vp8_init_mode_costs(cpi);
+
+      // TODO figure onnnnuut why making mv cost frame type dependent didn't help (jbb)
+      //vp8_build_component_cost_table(cpi->mb.mvcost, (const MV_CONTEXT *) l->mvc, flags);
+
+    }
+
+}
+
+void vp8_auto_select_speed(VP8_COMP *cpi)
+{
+    int milliseconds_for_compress = (int)(1000000 / cpi->frame_rate);
+
+    milliseconds_for_compress = milliseconds_for_compress * (16 - cpi->oxcf.cpu_used) / 16;
+
+#if 0
+
+    if (0)
+    {
+        FILE *f;
+
+        f = fopen("speed.stt", "a");
+        fprintf(f, " %8ld %10ld %10ld %10ld\n",
+                cpi->common.current_video_frame, cpi->Speed, milliseconds_for_compress, cpi->avg_pick_mode_time);
+        fclose(f);
+    }
+
+#endif
+
+    /*
+    // this is done during parameter valid check
+    if( cpi->oxcf.cpu_used > 16)
+        cpi->oxcf.cpu_used = 16;
+    if( cpi->oxcf.cpu_used < -16)
+        cpi->oxcf.cpu_used = -16;
+    */
+
+    if (cpi->avg_pick_mode_time < milliseconds_for_compress && (cpi->avg_encode_time - cpi->avg_pick_mode_time) < milliseconds_for_compress)
+    {
+        if (cpi->avg_pick_mode_time == 0)
+        {
+            cpi->Speed = 4;
+        }
+        else
+        {
+            if (milliseconds_for_compress * 100 < cpi->avg_encode_time * 95)
+            {
+                cpi->Speed          += 2;
+                cpi->avg_pick_mode_time = 0;
+                cpi->avg_encode_time = 0;
+
+                if (cpi->Speed > 16)
+                {
+                    cpi->Speed = 16;
+                }
+            }
+
+            if (milliseconds_for_compress * 100 > cpi->avg_encode_time * auto_speed_thresh[cpi->Speed])
+            {
+                cpi->Speed          -= 1;
+                cpi->avg_pick_mode_time = 0;
+                cpi->avg_encode_time = 0;
+
+                // In real-time mode, cpi->speed is in [4, 16].
+                if (cpi->Speed < 4)        //if ( cpi->Speed < 0 )
+                {
+                    cpi->Speed = 4;        //cpi->Speed = 0;
+                }
+            }
+        }
+    }
+    else
+    {
+        cpi->Speed += 4;
+
+        if (cpi->Speed > 16)
+            cpi->Speed = 16;
+
+
+        cpi->avg_pick_mode_time = 0;
+        cpi->avg_encode_time = 0;
+    }
+}
+
+int vp8_block_error_c(short *coeff, short *dqcoeff)
+{
+    int i;
+    int error = 0;
+
+    for (i = 0; i < 16; i++)
+    {
+        int this_diff = coeff[i] - dqcoeff[i];
+        error += this_diff * this_diff;
+    }
+
+    return error;
+}
+
+int vp8_mbblock_error_c(MACROBLOCK *mb, int dc)
+{
+    BLOCK  *be;
+    BLOCKD *bd;
+    int i, j;
+    int berror, error = 0;
+
+    for (i = 0; i < 16; i++)
+    {
+        be = &mb->block[i];
+        bd = &mb->e_mbd.block[i];
+
+        berror = 0;
+
+        for (j = dc; j < 16; j++)
+        {
+            int this_diff = be->coeff[j] - bd->dqcoeff[j];
+            berror += this_diff * this_diff;
+        }
+
+        error += berror;
+    }
+
+    return error;
+}
+
+int vp8_mbuverror_c(MACROBLOCK *mb)
+{
+
+    BLOCK  *be;
+    BLOCKD *bd;
+
+
+    int i;
+    int error = 0;
+
+    for (i = 16; i < 24; i++)
+    {
+        be = &mb->block[i];
+        bd = &mb->e_mbd.block[i];
+
+        error += vp8_block_error_c(be->coeff, bd->dqcoeff);
+    }
+
+    return error;
+}
+
+int VP8_UVSSE(MACROBLOCK *x)
+{
+    unsigned char *uptr, *vptr;
+    unsigned char *upred_ptr = (*(x->block[16].base_src) + x->block[16].src);
+    unsigned char *vpred_ptr = (*(x->block[20].base_src) + x->block[20].src);
+    int uv_stride = x->block[16].src_stride;
+
+    unsigned int sse1 = 0;
+    unsigned int sse2 = 0;
+    int mv_row = x->e_mbd.mode_info_context->mbmi.mv.as_mv.row;
+    int mv_col = x->e_mbd.mode_info_context->mbmi.mv.as_mv.col;
+    int offset;
+    int pre_stride = x->e_mbd.pre.uv_stride;
+
+    if (mv_row < 0)
+        mv_row -= 1;
+    else
+        mv_row += 1;
+
+    if (mv_col < 0)
+        mv_col -= 1;
+    else
+        mv_col += 1;
+
+    mv_row /= 2;
+    mv_col /= 2;
+
+    offset = (mv_row >> 3) * pre_stride + (mv_col >> 3);
+    uptr = x->e_mbd.pre.u_buffer + offset;
+    vptr = x->e_mbd.pre.v_buffer + offset;
+
+    if ((mv_row | mv_col) & 7)
+    {
+        vp8_sub_pixel_variance8x8(uptr, pre_stride,
+            mv_col & 7, mv_row & 7, upred_ptr, uv_stride, &sse2);
+        vp8_sub_pixel_variance8x8(vptr, pre_stride,
+            mv_col & 7, mv_row & 7, vpred_ptr, uv_stride, &sse1);
+        sse2 += sse1;
+    }
+    else
+    {
+        vp8_variance8x8(uptr, pre_stride,
+            upred_ptr, uv_stride, &sse2);
+        vp8_variance8x8(vptr, pre_stride,
+            vpred_ptr, uv_stride, &sse1);
+        sse2 += sse1;
+    }
+    return sse2;
+
+}
+
+static int cost_coeffs(MACROBLOCK *mb, BLOCKD *b, int type, ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l)
+{
+    int c = !type;              /* start at coef 0, unless Y with Y2 */
+    int eob = (int)(*b->eob);
+    int pt ;    /* surrounding block/prev coef predictor */
+    int cost = 0;
+    short *qcoeff_ptr = b->qcoeff;
+
+    VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+
+# define QC( I)  ( qcoeff_ptr [vp8_default_zig_zag1d[I]] )
+
+    for (; c < eob; c++)
+    {
+        int v = QC(c);
+        int t = vp8_dct_value_tokens_ptr[v].Token;
+        cost += mb->token_costs [type] [vp8_coef_bands[c]] [pt] [t];
+        cost += vp8_dct_value_cost_ptr[v];
+        pt = vp8_prev_token_class[t];
+    }
+
+# undef QC
+
+    if (c < 16)
+        cost += mb->token_costs [type] [vp8_coef_bands[c]] [pt] [DCT_EOB_TOKEN];
+
+    pt = (c != !type); // is eob first coefficient;
+    *a = *l = pt;
+
+    return cost;
+}
+
+static int vp8_rdcost_mby(MACROBLOCK *mb)
+{
+    int cost = 0;
+    int b;
+    MACROBLOCKD *x = &mb->e_mbd;
+    ENTROPY_CONTEXT_PLANES t_above, t_left;
+    ENTROPY_CONTEXT *ta;
+    ENTROPY_CONTEXT *tl;
+
+    vpx_memcpy(&t_above, mb->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
+    vpx_memcpy(&t_left, mb->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
+
+    ta = (ENTROPY_CONTEXT *)&t_above;
+    tl = (ENTROPY_CONTEXT *)&t_left;
+
+    for (b = 0; b < 16; b++)
+        cost += cost_coeffs(mb, x->block + b, PLANE_TYPE_Y_NO_DC,
+                    ta + vp8_block2above[b], tl + vp8_block2left[b]);
+
+    cost += cost_coeffs(mb, x->block + 24, PLANE_TYPE_Y2,
+                ta + vp8_block2above[24], tl + vp8_block2left[24]);
+
+    return cost;
+}
+
+static void macro_block_yrd( MACROBLOCK *mb,
+                             int *Rate,
+                             int *Distortion)
+{
+    int b;
+    MACROBLOCKD *const x = &mb->e_mbd;
+    BLOCK   *const mb_y2 = mb->block + 24;
+    BLOCKD *const x_y2  = x->block + 24;
+    short *Y2DCPtr = mb_y2->src_diff;
+    BLOCK *beptr;
+    int d;
+
+    vp8_subtract_mby( mb->src_diff, *(mb->block[0].base_src),
+        mb->block[0].src_stride,  mb->e_mbd.predictor, 16);
+
+    // Fdct and building the 2nd order block
+    for (beptr = mb->block; beptr < mb->block + 16; beptr += 2)
+    {
+        mb->short_fdct8x4(beptr->src_diff, beptr->coeff, 32);
+        *Y2DCPtr++ = beptr->coeff[0];
+        *Y2DCPtr++ = beptr->coeff[16];
+    }
+
+    // 2nd order fdct
+    mb->short_walsh4x4(mb_y2->src_diff, mb_y2->coeff, 8);
+
+    // Quantization
+    for (b = 0; b < 16; b++)
+    {
+        mb->quantize_b(&mb->block[b], &mb->e_mbd.block[b]);
+    }
+
+    // DC predication and Quantization of 2nd Order block
+    mb->quantize_b(mb_y2, x_y2);
+
+    // Distortion
+    d = vp8_mbblock_error(mb, 1) << 2;
+    d += vp8_block_error(mb_y2->coeff, x_y2->dqcoeff);
+
+    *Distortion = (d >> 4);
+
+    // rate
+    *Rate = vp8_rdcost_mby(mb);
+}
+
+static void copy_predictor(unsigned char *dst, const unsigned char *predictor)
+{
+    const unsigned int *p = (const unsigned int *)predictor;
+    unsigned int *d = (unsigned int *)dst;
+    d[0] = p[0];
+    d[4] = p[4];
+    d[8] = p[8];
+    d[12] = p[12];
+}
+static int rd_pick_intra4x4block(
+    VP8_COMP *cpi,
+    MACROBLOCK *x,
+    BLOCK *be,
+    BLOCKD *b,
+    B_PREDICTION_MODE *best_mode,
+    unsigned int *bmode_costs,
+    ENTROPY_CONTEXT *a,
+    ENTROPY_CONTEXT *l,
+
+    int *bestrate,
+    int *bestratey,
+    int *bestdistortion)
+{
+    B_PREDICTION_MODE mode;
+    int best_rd = INT_MAX;
+    int rate = 0;
+    int distortion;
+
+    ENTROPY_CONTEXT ta = *a, tempa = *a;
+    ENTROPY_CONTEXT tl = *l, templ = *l;
+    /*
+     * The predictor buffer is a 2d buffer with a stride of 16.  Create
+     * a temp buffer that meets the stride requirements, but we are only
+     * interested in the left 4x4 block
+     * */
+    DECLARE_ALIGNED_ARRAY(16, unsigned char,  best_predictor, 16*4);
+    DECLARE_ALIGNED_ARRAY(16, short, best_dqcoeff, 16);
+    int dst_stride = x->e_mbd.dst.y_stride;
+    unsigned char *base_dst = x->e_mbd.dst.y_buffer;
+
+    for (mode = B_DC_PRED; mode <= B_HU_PRED; mode++)
+    {
+        int this_rd;
+        int ratey;
+
+        rate = bmode_costs[mode];
+
+        vp8_intra4x4_predict(base_dst + b->offset, dst_stride, mode,
+                             b->predictor, 16);
+        vp8_subtract_b(be, b, 16);
+        x->short_fdct4x4(be->src_diff, be->coeff, 32);
+        x->quantize_b(be, b);
+
+        tempa = ta;
+        templ = tl;
+
+        ratey = cost_coeffs(x, b, PLANE_TYPE_Y_WITH_DC, &tempa, &templ);
+        rate += ratey;
+        distortion = vp8_block_error(be->coeff, b->dqcoeff) >> 2;
+
+        this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);
+
+        if (this_rd < best_rd)
+        {
+            *bestrate = rate;
+            *bestratey = ratey;
+            *bestdistortion = distortion;
+            best_rd = this_rd;
+            *best_mode = mode;
+            *a = tempa;
+            *l = templ;
+            copy_predictor(best_predictor, b->predictor);
+            vpx_memcpy(best_dqcoeff, b->dqcoeff, 32);
+        }
+    }
+    b->bmi.as_mode = (B_PREDICTION_MODE)(*best_mode);
+
+    vp8_short_idct4x4llm(best_dqcoeff, best_predictor, 16, base_dst + b->offset,
+                         dst_stride);
+
+    return best_rd;
+}
+
+static int rd_pick_intra4x4mby_modes(VP8_COMP *cpi, MACROBLOCK *mb, int *Rate,
+                                     int *rate_y, int *Distortion, int best_rd)
+{
+    MACROBLOCKD *const xd = &mb->e_mbd;
+    int i;
+    int cost = mb->mbmode_cost [xd->frame_type] [B_PRED];
+    int distortion = 0;
+    int tot_rate_y = 0;
+    int64_t total_rd = 0;
+    ENTROPY_CONTEXT_PLANES t_above, t_left;
+    ENTROPY_CONTEXT *ta;
+    ENTROPY_CONTEXT *tl;
+    unsigned int *bmode_costs;
+
+    vpx_memcpy(&t_above, mb->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
+    vpx_memcpy(&t_left, mb->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
+
+    ta = (ENTROPY_CONTEXT *)&t_above;
+    tl = (ENTROPY_CONTEXT *)&t_left;
+
+    intra_prediction_down_copy(xd, xd->dst.y_buffer - xd->dst.y_stride + 16);
+
+    bmode_costs = mb->inter_bmode_costs;
+
+    for (i = 0; i < 16; i++)
+    {
+        MODE_INFO *const mic = xd->mode_info_context;
+        const int mis = xd->mode_info_stride;
+        B_PREDICTION_MODE UNINITIALIZED_IS_SAFE(best_mode);
+        int UNINITIALIZED_IS_SAFE(r), UNINITIALIZED_IS_SAFE(ry), UNINITIALIZED_IS_SAFE(d);
+
+        if (mb->e_mbd.frame_type == KEY_FRAME)
+        {
+            const B_PREDICTION_MODE A = above_block_mode(mic, i, mis);
+            const B_PREDICTION_MODE L = left_block_mode(mic, i);
+
+            bmode_costs  = mb->bmode_costs[A][L];
+        }
+
+        total_rd += rd_pick_intra4x4block(
+            cpi, mb, mb->block + i, xd->block + i, &best_mode, bmode_costs,
+            ta + vp8_block2above[i],
+            tl + vp8_block2left[i], &r, &ry, &d);
+
+        cost += r;
+        distortion += d;
+        tot_rate_y += ry;
+
+        mic->bmi[i].as_mode = best_mode;
+
+        if(total_rd >= (int64_t)best_rd)
+            break;
+    }
+
+    if(total_rd >= (int64_t)best_rd)
+        return INT_MAX;
+
+    *Rate = cost;
+    *rate_y = tot_rate_y;
+    *Distortion = distortion;
+
+    return RDCOST(mb->rdmult, mb->rddiv, cost, distortion);
+}
+
+
+static int rd_pick_intra16x16mby_mode(VP8_COMP *cpi,
+                                      MACROBLOCK *x,
+                                      int *Rate,
+                                      int *rate_y,
+                                      int *Distortion)
+{
+    MB_PREDICTION_MODE mode;
+    MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(mode_selected);
+    int rate, ratey;
+    int distortion;
+    int best_rd = INT_MAX;
+    int this_rd;
+    MACROBLOCKD *xd = &x->e_mbd;
+
+    //Y Search for 16x16 intra prediction mode
+    for (mode = DC_PRED; mode <= TM_PRED; mode++)
+    {
+        xd->mode_info_context->mbmi.mode = mode;
+
+        vp8_build_intra_predictors_mby_s(xd,
+                                         xd->dst.y_buffer - xd->dst.y_stride,
+                                         xd->dst.y_buffer - 1,
+                                         xd->dst.y_stride,
+                                         xd->predictor,
+                                         16);
+
+        macro_block_yrd(x, &ratey, &distortion);
+        rate = ratey + x->mbmode_cost[xd->frame_type]
+                                     [xd->mode_info_context->mbmi.mode];
+
+        this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);
+
+        if (this_rd < best_rd)
+        {
+            mode_selected = mode;
+            best_rd = this_rd;
+            *Rate = rate;
+            *rate_y = ratey;
+            *Distortion = distortion;
+        }
+    }
+
+    xd->mode_info_context->mbmi.mode = mode_selected;
+    return best_rd;
+}
+
+static int rd_cost_mbuv(MACROBLOCK *mb)
+{
+    int b;
+    int cost = 0;
+    MACROBLOCKD *x = &mb->e_mbd;
+    ENTROPY_CONTEXT_PLANES t_above, t_left;
+    ENTROPY_CONTEXT *ta;
+    ENTROPY_CONTEXT *tl;
+
+    vpx_memcpy(&t_above, mb->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
+    vpx_memcpy(&t_left, mb->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
+
+    ta = (ENTROPY_CONTEXT *)&t_above;
+    tl = (ENTROPY_CONTEXT *)&t_left;
+
+    for (b = 16; b < 24; b++)
+        cost += cost_coeffs(mb, x->block + b, PLANE_TYPE_UV,
+                    ta + vp8_block2above[b], tl + vp8_block2left[b]);
+
+    return cost;
+}
+
+
+static int rd_inter16x16_uv(VP8_COMP *cpi, MACROBLOCK *x, int *rate,
+                            int *distortion, int fullpixel)
+{
+    vp8_build_inter16x16_predictors_mbuv(&x->e_mbd);
+    vp8_subtract_mbuv(x->src_diff,
+        x->src.u_buffer, x->src.v_buffer, x->src.uv_stride,
+        &x->e_mbd.predictor[256], &x->e_mbd.predictor[320], 8);
+
+    vp8_transform_mbuv(x);
+    vp8_quantize_mbuv(x);
+
+    *rate       = rd_cost_mbuv(x);
+    *distortion = vp8_mbuverror(x) / 4;
+
+    return RDCOST(x->rdmult, x->rddiv, *rate, *distortion);
+}
+
+static int rd_inter4x4_uv(VP8_COMP *cpi, MACROBLOCK *x, int *rate,
+                          int *distortion, int fullpixel)
+{
+    vp8_build_inter4x4_predictors_mbuv(&x->e_mbd);
+    vp8_subtract_mbuv(x->src_diff,
+        x->src.u_buffer, x->src.v_buffer, x->src.uv_stride,
+        &x->e_mbd.predictor[256], &x->e_mbd.predictor[320], 8);
+
+    vp8_transform_mbuv(x);
+    vp8_quantize_mbuv(x);
+
+    *rate       = rd_cost_mbuv(x);
+    *distortion = vp8_mbuverror(x) / 4;
+
+    return RDCOST(x->rdmult, x->rddiv, *rate, *distortion);
+}
+
+static void rd_pick_intra_mbuv_mode(VP8_COMP *cpi, MACROBLOCK *x, int *rate, int *rate_tokenonly, int *distortion)
+{
+    MB_PREDICTION_MODE mode;
+    MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(mode_selected);
+    int best_rd = INT_MAX;
+    int UNINITIALIZED_IS_SAFE(d), UNINITIALIZED_IS_SAFE(r);
+    int rate_to;
+    MACROBLOCKD *xd = &x->e_mbd;
+
+    for (mode = DC_PRED; mode <= TM_PRED; mode++)
+    {
+        int rate;
+        int distortion;
+        int this_rd;
+
+        xd->mode_info_context->mbmi.uv_mode = mode;
+
+        vp8_build_intra_predictors_mbuv_s(xd,
+                                          xd->dst.u_buffer - xd->dst.uv_stride,
+                                          xd->dst.v_buffer - xd->dst.uv_stride,
+                                          xd->dst.u_buffer - 1,
+                                          xd->dst.v_buffer - 1,
+                                          xd->dst.uv_stride,
+                                          &xd->predictor[256], &xd->predictor[320],
+                                          8);
+
+
+        vp8_subtract_mbuv(x->src_diff,
+                      x->src.u_buffer, x->src.v_buffer, x->src.uv_stride,
+                      &xd->predictor[256], &xd->predictor[320], 8);
+        vp8_transform_mbuv(x);
+        vp8_quantize_mbuv(x);
+
+        rate_to = rd_cost_mbuv(x);
+        rate = rate_to + x->intra_uv_mode_cost[xd->frame_type][xd->mode_info_context->mbmi.uv_mode];
+
+        distortion = vp8_mbuverror(x) / 4;
+
+        this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);
+
+        if (this_rd < best_rd)
+        {
+            best_rd = this_rd;
+            d = distortion;
+            r = rate;
+            *rate_tokenonly = rate_to;
+            mode_selected = mode;
+        }
+    }
+
+    *rate = r;
+    *distortion = d;
+
+    xd->mode_info_context->mbmi.uv_mode = mode_selected;
+}
+
+int vp8_cost_mv_ref(MB_PREDICTION_MODE m, const int near_mv_ref_ct[4])
+{
+    vp8_prob p [VP8_MVREFS-1];
+    assert(NEARESTMV <= m  &&  m <= SPLITMV);
+    vp8_mv_ref_probs(p, near_mv_ref_ct);
+    return vp8_cost_token(vp8_mv_ref_tree, p,
+                          vp8_mv_ref_encoding_array - NEARESTMV + m);
+}
+
+void vp8_set_mbmode_and_mvs(MACROBLOCK *x, MB_PREDICTION_MODE mb, int_mv *mv)
+{
+    x->e_mbd.mode_info_context->mbmi.mode = mb;
+    x->e_mbd.mode_info_context->mbmi.mv.as_int = mv->as_int;
+}
+
+static int labels2mode(
+    MACROBLOCK *x,
+    int const *labelings, int which_label,
+    B_PREDICTION_MODE this_mode,
+    int_mv *this_mv, int_mv *best_ref_mv,
+    int *mvcost[2]
+)
+{
+    MACROBLOCKD *const xd = & x->e_mbd;
+    MODE_INFO *const mic = xd->mode_info_context;
+    const int mis = xd->mode_info_stride;
+
+    int cost = 0;
+    int thismvcost = 0;
+
+    /* We have to be careful retrieving previously-encoded motion vectors.
+       Ones from this macroblock have to be pulled from the BLOCKD array
+       as they have not yet made it to the bmi array in our MB_MODE_INFO. */
+
+    int i = 0;
+
+    do
+    {
+        BLOCKD *const d = xd->block + i;
+        const int row = i >> 2,  col = i & 3;
+
+        B_PREDICTION_MODE m;
+
+        if (labelings[i] != which_label)
+            continue;
+
+        if (col  &&  labelings[i] == labelings[i-1])
+            m = LEFT4X4;
+        else if (row  &&  labelings[i] == labelings[i-4])
+            m = ABOVE4X4;
+        else
+        {
+            // the only time we should do costing for new motion vector or mode
+            // is when we are on a new label  (jbb May 08, 2007)
+            switch (m = this_mode)
+            {
+            case NEW4X4 :
+                thismvcost  = vp8_mv_bit_cost(this_mv, best_ref_mv, mvcost, 102);
+                break;
+            case LEFT4X4:
+                this_mv->as_int = col ? d[-1].bmi.mv.as_int : left_block_mv(mic, i);
+                break;
+            case ABOVE4X4:
+                this_mv->as_int = row ? d[-4].bmi.mv.as_int : above_block_mv(mic, i, mis);
+                break;
+            case ZERO4X4:
+                this_mv->as_int = 0;
+                break;
+            default:
+                break;
+            }
+
+            if (m == ABOVE4X4)  // replace above with left if same
+            {
+                int_mv left_mv;
+
+                left_mv.as_int = col ? d[-1].bmi.mv.as_int :
+                                        left_block_mv(mic, i);
+
+                if (left_mv.as_int == this_mv->as_int)
+                    m = LEFT4X4;
+            }
+
+            cost = x->inter_bmode_costs[ m];
+        }
+
+        d->bmi.mv.as_int = this_mv->as_int;
+
+        x->partition_info->bmi[i].mode = m;
+        x->partition_info->bmi[i].mv.as_int = this_mv->as_int;
+
+    }
+    while (++i < 16);
+
+    cost += thismvcost ;
+    return cost;
+}
+
+static int rdcost_mbsegment_y(MACROBLOCK *mb, const int *labels,
+                              int which_label, ENTROPY_CONTEXT *ta,
+                              ENTROPY_CONTEXT *tl)
+{
+    int cost = 0;
+    int b;
+    MACROBLOCKD *x = &mb->e_mbd;
+
+    for (b = 0; b < 16; b++)
+        if (labels[ b] == which_label)
+            cost += cost_coeffs(mb, x->block + b, PLANE_TYPE_Y_WITH_DC,
+                                ta + vp8_block2above[b],
+                                tl + vp8_block2left[b]);
+
+    return cost;
+
+}
+static unsigned int vp8_encode_inter_mb_segment(MACROBLOCK *x, int const *labels, int which_label)
+{
+    int i;
+    unsigned int distortion = 0;
+    int pre_stride = x->e_mbd.pre.y_stride;
+    unsigned char *base_pre = x->e_mbd.pre.y_buffer;
+
+
+    for (i = 0; i < 16; i++)
+    {
+        if (labels[i] == which_label)
+        {
+            BLOCKD *bd = &x->e_mbd.block[i];
+            BLOCK *be = &x->block[i];
+
+            vp8_build_inter_predictors_b(bd, 16, base_pre, pre_stride, x->e_mbd.subpixel_predict);
+            vp8_subtract_b(be, bd, 16);
+            x->short_fdct4x4(be->src_diff, be->coeff, 32);
+
+            // set to 0 no way to account for 2nd order DC so discount
+            //be->coeff[0] = 0;
+            x->quantize_b(be, bd);
+
+            distortion += vp8_block_error(be->coeff, bd->dqcoeff);
+        }
+    }
+
+    return distortion;
+}
+
+
+static const unsigned int segmentation_to_sseshift[4] = {3, 3, 2, 0};
+
+
+typedef struct
+{
+  int_mv *ref_mv;
+  int_mv mvp;
+
+  int segment_rd;
+  int segment_num;
+  int r;
+  int d;
+  int segment_yrate;
+  B_PREDICTION_MODE modes[16];
+  int_mv mvs[16];
+  unsigned char eobs[16];
+
+  int mvthresh;
+  int *mdcounts;
+
+  int_mv sv_mvp[4];     // save 4 mvp from 8x8
+  int sv_istep[2];  // save 2 initial step_param for 16x8/8x16
+
+} BEST_SEG_INFO;
+
+
+static void rd_check_segment(VP8_COMP *cpi, MACROBLOCK *x,
+                             BEST_SEG_INFO *bsi, unsigned int segmentation)
+{
+    int i;
+    int const *labels;
+    int br = 0;
+    int bd = 0;
+    B_PREDICTION_MODE this_mode;
+
+
+    int label_count;
+    int this_segment_rd = 0;
+    int label_mv_thresh;
+    int rate = 0;
+    int sbr = 0;
+    int sbd = 0;
+    int segmentyrate = 0;
+
+    vp8_variance_fn_ptr_t *v_fn_ptr;
+
+    ENTROPY_CONTEXT_PLANES t_above, t_left;
+    ENTROPY_CONTEXT *ta;
+    ENTROPY_CONTEXT *tl;
+    ENTROPY_CONTEXT_PLANES t_above_b, t_left_b;
+    ENTROPY_CONTEXT *ta_b;
+    ENTROPY_CONTEXT *tl_b;
+
+    vpx_memcpy(&t_above, x->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
+    vpx_memcpy(&t_left, x->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
+
+    ta = (ENTROPY_CONTEXT *)&t_above;
+    tl = (ENTROPY_CONTEXT *)&t_left;
+    ta_b = (ENTROPY_CONTEXT *)&t_above_b;
+    tl_b = (ENTROPY_CONTEXT *)&t_left_b;
+
+    br = 0;
+    bd = 0;
+
+    v_fn_ptr = &cpi->fn_ptr[segmentation];
+    labels = vp8_mbsplits[segmentation];
+    label_count = vp8_mbsplit_count[segmentation];
+
+    // 64 makes this threshold really big effectively
+    // making it so that we very rarely check mvs on
+    // segments.   setting this to 1 would make mv thresh
+    // roughly equal to what it is for macroblocks
+    label_mv_thresh = 1 * bsi->mvthresh / label_count ;
+
+    // Segmentation method overheads
+    rate = vp8_cost_token(vp8_mbsplit_tree, vp8_mbsplit_probs, vp8_mbsplit_encodings + segmentation);
+    rate += vp8_cost_mv_ref(SPLITMV, bsi->mdcounts);
+    this_segment_rd += RDCOST(x->rdmult, x->rddiv, rate, 0);
+    br += rate;
+
+    for (i = 0; i < label_count; i++)
+    {
+        int_mv mode_mv[B_MODE_COUNT];
+        int best_label_rd = INT_MAX;
+        B_PREDICTION_MODE mode_selected = ZERO4X4;
+        int bestlabelyrate = 0;
+
+        // search for the best motion vector on this segment
+        for (this_mode = LEFT4X4; this_mode <= NEW4X4 ; this_mode ++)
+        {
+            int this_rd;
+            int distortion;
+            int labelyrate;
+            ENTROPY_CONTEXT_PLANES t_above_s, t_left_s;
+            ENTROPY_CONTEXT *ta_s;
+            ENTROPY_CONTEXT *tl_s;
+
+            vpx_memcpy(&t_above_s, &t_above, sizeof(ENTROPY_CONTEXT_PLANES));
+            vpx_memcpy(&t_left_s, &t_left, sizeof(ENTROPY_CONTEXT_PLANES));
+
+            ta_s = (ENTROPY_CONTEXT *)&t_above_s;
+            tl_s = (ENTROPY_CONTEXT *)&t_left_s;
+
+            if (this_mode == NEW4X4)
+            {
+                int sseshift;
+                int num00;
+                int step_param = 0;
+                int further_steps;
+                int n;
+                int thissme;
+                int bestsme = INT_MAX;
+                int_mv  temp_mv;
+                BLOCK *c;
+                BLOCKD *e;
+
+                // Is the best so far sufficiently good that we cant justify doing and new motion search.
+                if (best_label_rd < label_mv_thresh)
+                    break;
+
+                if(cpi->compressor_speed)
+                {
+                    if (segmentation == BLOCK_8X16 || segmentation == BLOCK_16X8)
+                    {
+                        bsi->mvp.as_int = bsi->sv_mvp[i].as_int;
+                        if (i==1 && segmentation == BLOCK_16X8)
+                          bsi->mvp.as_int = bsi->sv_mvp[2].as_int;
+
+                        step_param = bsi->sv_istep[i];
+                    }
+
+                    // use previous block's result as next block's MV predictor.
+                    if (segmentation == BLOCK_4X4 && i>0)
+                    {
+                        bsi->mvp.as_int = x->e_mbd.block[i-1].bmi.mv.as_int;
+                        if (i==4 || i==8 || i==12)
+                            bsi->mvp.as_int = x->e_mbd.block[i-4].bmi.mv.as_int;
+                        step_param = 2;
+                    }
+                }
+
+                further_steps = (MAX_MVSEARCH_STEPS - 1) - step_param;
+
+                {
+                    int sadpb = x->sadperbit4;
+                    int_mv mvp_full;
+
+                    mvp_full.as_mv.row = bsi->mvp.as_mv.row >>3;
+                    mvp_full.as_mv.col = bsi->mvp.as_mv.col >>3;
+
+                    // find first label
+                    n = vp8_mbsplit_offset[segmentation][i];
+
+                    c = &x->block[n];
+                    e = &x->e_mbd.block[n];
+
+                    {
+                        bestsme = cpi->diamond_search_sad(x, c, e, &mvp_full,
+                                                &mode_mv[NEW4X4], step_param,
+                                                sadpb, &num00, v_fn_ptr,
+                                                x->mvcost, bsi->ref_mv);
+
+                        n = num00;
+                        num00 = 0;
+
+                        while (n < further_steps)
+                        {
+                            n++;
+
+                            if (num00)
+                                num00--;
+                            else
+                            {
+                                thissme = cpi->diamond_search_sad(x, c, e,
+                                                    &mvp_full, &temp_mv,
+                                                    step_param + n, sadpb,
+                                                    &num00, v_fn_ptr,
+                                                    x->mvcost, bsi->ref_mv);
+
+                                if (thissme < bestsme)
+                                {
+                                    bestsme = thissme;
+                                    mode_mv[NEW4X4].as_int = temp_mv.as_int;
+                                }
+                            }
+                        }
+                    }
+
+                    sseshift = segmentation_to_sseshift[segmentation];
+
+                    // Should we do a full search (best quality only)
+                    if ((cpi->compressor_speed == 0) && (bestsme >> sseshift) > 4000)
+                    {
+                        /* Check if mvp_full is within the range. */
+                        vp8_clamp_mv(&mvp_full, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
+
+                        thissme = cpi->full_search_sad(x, c, e, &mvp_full,
+                                                       sadpb, 16, v_fn_ptr,
+                                                       x->mvcost, bsi->ref_mv);
+
+                        if (thissme < bestsme)
+                        {
+                            bestsme = thissme;
+                            mode_mv[NEW4X4].as_int = e->bmi.mv.as_int;
+                        }
+                        else
+                        {
+                            // The full search result is actually worse so re-instate the previous best vector
+                            e->bmi.mv.as_int = mode_mv[NEW4X4].as_int;
+                        }
+                    }
+                }
+
+                if (bestsme < INT_MAX)
+                {
+                    int distortion;
+                    unsigned int sse;
+                    cpi->find_fractional_mv_step(x, c, e, &mode_mv[NEW4X4],
+                        bsi->ref_mv, x->errorperbit, v_fn_ptr, x->mvcost,
+                        &distortion, &sse);
+
+                }
+            } /* NEW4X4 */
+
+            rate = labels2mode(x, labels, i, this_mode, &mode_mv[this_mode],
+                               bsi->ref_mv, x->mvcost);
+
+            // Trap vectors that reach beyond the UMV borders
+            if (((mode_mv[this_mode].as_mv.row >> 3) < x->mv_row_min) || ((mode_mv[this_mode].as_mv.row >> 3) > x->mv_row_max) ||
+                ((mode_mv[this_mode].as_mv.col >> 3) < x->mv_col_min) || ((mode_mv[this_mode].as_mv.col >> 3) > x->mv_col_max))
+            {
+                continue;
+            }
+
+            distortion = vp8_encode_inter_mb_segment(x, labels, i) / 4;
+
+            labelyrate = rdcost_mbsegment_y(x, labels, i, ta_s, tl_s);
+            rate += labelyrate;
+
+            this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);
+
+            if (this_rd < best_label_rd)
+            {
+                sbr = rate;
+                sbd = distortion;
+                bestlabelyrate = labelyrate;
+                mode_selected = this_mode;
+                best_label_rd = this_rd;
+
+                vpx_memcpy(ta_b, ta_s, sizeof(ENTROPY_CONTEXT_PLANES));
+                vpx_memcpy(tl_b, tl_s, sizeof(ENTROPY_CONTEXT_PLANES));
+
+            }
+        } /*for each 4x4 mode*/
+
+        vpx_memcpy(ta, ta_b, sizeof(ENTROPY_CONTEXT_PLANES));
+        vpx_memcpy(tl, tl_b, sizeof(ENTROPY_CONTEXT_PLANES));
+
+        labels2mode(x, labels, i, mode_selected, &mode_mv[mode_selected],
+                    bsi->ref_mv, x->mvcost);
+
+        br += sbr;
+        bd += sbd;
+        segmentyrate += bestlabelyrate;
+        this_segment_rd += best_label_rd;
+
+        if (this_segment_rd >= bsi->segment_rd)
+            break;
+
+    } /* for each label */
+
+    if (this_segment_rd < bsi->segment_rd)
+    {
+        bsi->r = br;
+        bsi->d = bd;
+        bsi->segment_yrate = segmentyrate;
+        bsi->segment_rd = this_segment_rd;
+        bsi->segment_num = segmentation;
+
+        // store everything needed to come back to this!!
+        for (i = 0; i < 16; i++)
+        {
+            bsi->mvs[i].as_mv = x->partition_info->bmi[i].mv.as_mv;
+            bsi->modes[i] = x->partition_info->bmi[i].mode;
+            bsi->eobs[i] = x->e_mbd.eobs[i];
+        }
+    }
+}
+
+static
+void vp8_cal_step_param(int sr, int *sp)
+{
+    int step = 0;
+
+    if (sr > MAX_FIRST_STEP) sr = MAX_FIRST_STEP;
+    else if (sr < 1) sr = 1;
+
+    while (sr>>=1)
+        step++;
+
+    *sp = MAX_MVSEARCH_STEPS - 1 - step;
+}
+
+static int vp8_rd_pick_best_mbsegmentation(VP8_COMP *cpi, MACROBLOCK *x,
+                                           int_mv *best_ref_mv, int best_rd,
+                                           int *mdcounts, int *returntotrate,
+                                           int *returnyrate, int *returndistortion,
+                                           int mvthresh)
+{
+    int i;
+    BEST_SEG_INFO bsi;
+
+    vpx_memset(&bsi, 0, sizeof(bsi));
+
+    bsi.segment_rd = best_rd;
+    bsi.ref_mv = best_ref_mv;
+    bsi.mvp.as_int = best_ref_mv->as_int;
+    bsi.mvthresh = mvthresh;
+    bsi.mdcounts = mdcounts;
+
+    for(i = 0; i < 16; i++)
+    {
+        bsi.modes[i] = ZERO4X4;
+    }
+
+    if(cpi->compressor_speed == 0)
+    {
+        /* for now, we will keep the original segmentation order
+           when in best quality mode */
+        rd_check_segment(cpi, x, &bsi, BLOCK_16X8);
+        rd_check_segment(cpi, x, &bsi, BLOCK_8X16);
+        rd_check_segment(cpi, x, &bsi, BLOCK_8X8);
+        rd_check_segment(cpi, x, &bsi, BLOCK_4X4);
+    }
+    else
+    {
+        int sr;
+
+        rd_check_segment(cpi, x, &bsi, BLOCK_8X8);
+
+        if (bsi.segment_rd < best_rd)
+        {
+            int col_min = ((best_ref_mv->as_mv.col+7)>>3) - MAX_FULL_PEL_VAL;
+            int row_min = ((best_ref_mv->as_mv.row+7)>>3) - MAX_FULL_PEL_VAL;
+            int col_max = (best_ref_mv->as_mv.col>>3) + MAX_FULL_PEL_VAL;
+            int row_max = (best_ref_mv->as_mv.row>>3) + MAX_FULL_PEL_VAL;
+
+            int tmp_col_min = x->mv_col_min;
+            int tmp_col_max = x->mv_col_max;
+            int tmp_row_min = x->mv_row_min;
+            int tmp_row_max = x->mv_row_max;
+
+            /* Get intersection of UMV window and valid MV window to reduce # of checks in diamond search. */
+            if (x->mv_col_min < col_min )
+                x->mv_col_min = col_min;
+            if (x->mv_col_max > col_max )
+                x->mv_col_max = col_max;
+            if (x->mv_row_min < row_min )
+                x->mv_row_min = row_min;
+            if (x->mv_row_max > row_max )
+                x->mv_row_max = row_max;
+
+            /* Get 8x8 result */
+            bsi.sv_mvp[0].as_int = bsi.mvs[0].as_int;
+            bsi.sv_mvp[1].as_int = bsi.mvs[2].as_int;
+            bsi.sv_mvp[2].as_int = bsi.mvs[8].as_int;
+            bsi.sv_mvp[3].as_int = bsi.mvs[10].as_int;
+
+            /* Use 8x8 result as 16x8/8x16's predictor MV. Adjust search range according to the closeness of 2 MV. */
+            /* block 8X16 */
+            {
+                sr = MAXF((abs(bsi.sv_mvp[0].as_mv.row - bsi.sv_mvp[2].as_mv.row))>>3, (abs(bsi.sv_mvp[0].as_mv.col - bsi.sv_mvp[2].as_mv.col))>>3);
+                vp8_cal_step_param(sr, &bsi.sv_istep[0]);
+
+                sr = MAXF((abs(bsi.sv_mvp[1].as_mv.row - bsi.sv_mvp[3].as_mv.row))>>3, (abs(bsi.sv_mvp[1].as_mv.col - bsi.sv_mvp[3].as_mv.col))>>3);
+                vp8_cal_step_param(sr, &bsi.sv_istep[1]);
+
+                rd_check_segment(cpi, x, &bsi, BLOCK_8X16);
+            }
+
+            /* block 16X8 */
+            {
+                sr = MAXF((abs(bsi.sv_mvp[0].as_mv.row - bsi.sv_mvp[1].as_mv.row))>>3, (abs(bsi.sv_mvp[0].as_mv.col - bsi.sv_mvp[1].as_mv.col))>>3);
+                vp8_cal_step_param(sr, &bsi.sv_istep[0]);
+
+                sr = MAXF((abs(bsi.sv_mvp[2].as_mv.row - bsi.sv_mvp[3].as_mv.row))>>3, (abs(bsi.sv_mvp[2].as_mv.col - bsi.sv_mvp[3].as_mv.col))>>3);
+                vp8_cal_step_param(sr, &bsi.sv_istep[1]);
+
+                rd_check_segment(cpi, x, &bsi, BLOCK_16X8);
+            }
+
+            /* If 8x8 is better than 16x8/8x16, then do 4x4 search */
+            /* Not skip 4x4 if speed=0 (good quality) */
+            if (cpi->sf.no_skip_block4x4_search || bsi.segment_num == BLOCK_8X8)  /* || (sv_segment_rd8x8-bsi.segment_rd) < sv_segment_rd8x8>>5) */
+            {
+                bsi.mvp.as_int = bsi.sv_mvp[0].as_int;
+                rd_check_segment(cpi, x, &bsi, BLOCK_4X4);
+            }
+
+            /* restore UMV window */
+            x->mv_col_min = tmp_col_min;
+            x->mv_col_max = tmp_col_max;
+            x->mv_row_min = tmp_row_min;
+            x->mv_row_max = tmp_row_max;
+        }
+    }
+
+    /* set it to the best */
+    for (i = 0; i < 16; i++)
+    {
+        BLOCKD *bd = &x->e_mbd.block[i];
+
+        bd->bmi.mv.as_int = bsi.mvs[i].as_int;
+        *bd->eob = bsi.eobs[i];
+    }
+
+    *returntotrate = bsi.r;
+    *returndistortion = bsi.d;
+    *returnyrate = bsi.segment_yrate;
+
+    /* save partitions */
+    x->e_mbd.mode_info_context->mbmi.partitioning = bsi.segment_num;
+    x->partition_info->count = vp8_mbsplit_count[bsi.segment_num];
+
+    for (i = 0; i < x->partition_info->count; i++)
+    {
+        int j;
+
+        j = vp8_mbsplit_offset[bsi.segment_num][i];
+
+        x->partition_info->bmi[i].mode = bsi.modes[j];
+        x->partition_info->bmi[i].mv.as_mv = bsi.mvs[j].as_mv;
+    }
+    /*
+     * used to set x->e_mbd.mode_info_context->mbmi.mv.as_int
+     */
+    x->partition_info->bmi[15].mv.as_int = bsi.mvs[15].as_int;
+
+    return bsi.segment_rd;
+}
+
+//The improved MV prediction
+void vp8_mv_pred
+(
+    VP8_COMP *cpi,
+    MACROBLOCKD *xd,
+    const MODE_INFO *here,
+    int_mv *mvp,
+    int refframe,
+    int *ref_frame_sign_bias,
+    int *sr,
+    int near_sadidx[]
+)
+{
+    const MODE_INFO *above = here - xd->mode_info_stride;
+    const MODE_INFO *left = here - 1;
+    const MODE_INFO *aboveleft = above - 1;
+    int_mv           near_mvs[8];
+    int              near_ref[8];
+    int_mv           mv;
+    int              vcnt=0;
+    int              find=0;
+    int              mb_offset;
+
+    int              mvx[8];
+    int              mvy[8];
+    int              i;
+
+    mv.as_int = 0;
+
+    if(here->mbmi.ref_frame != INTRA_FRAME)
+    {
+        near_mvs[0].as_int = near_mvs[1].as_int = near_mvs[2].as_int = near_mvs[3].as_int = near_mvs[4].as_int = near_mvs[5].as_int = near_mvs[6].as_int = near_mvs[7].as_int = 0;
+        near_ref[0] = near_ref[1] = near_ref[2] = near_ref[3] = near_ref[4] = near_ref[5] = near_ref[6] = near_ref[7] = 0;
+
+        // read in 3 nearby block's MVs from current frame as prediction candidates.
+        if (above->mbmi.ref_frame != INTRA_FRAME)
+        {
+            near_mvs[vcnt].as_int = above->mbmi.mv.as_int;
+            mv_bias(ref_frame_sign_bias[above->mbmi.ref_frame], refframe, &near_mvs[vcnt], ref_frame_sign_bias);
+            near_ref[vcnt] =  above->mbmi.ref_frame;
+        }
+        vcnt++;
+        if (left->mbmi.ref_frame != INTRA_FRAME)
+        {
+            near_mvs[vcnt].as_int = left->mbmi.mv.as_int;
+            mv_bias(ref_frame_sign_bias[left->mbmi.ref_frame], refframe, &near_mvs[vcnt], ref_frame_sign_bias);
+            near_ref[vcnt] =  left->mbmi.ref_frame;
+        }
+        vcnt++;
+        if (aboveleft->mbmi.ref_frame != INTRA_FRAME)
+        {
+            near_mvs[vcnt].as_int = aboveleft->mbmi.mv.as_int;
+            mv_bias(ref_frame_sign_bias[aboveleft->mbmi.ref_frame], refframe, &near_mvs[vcnt], ref_frame_sign_bias);
+            near_ref[vcnt] =  aboveleft->mbmi.ref_frame;
+        }
+        vcnt++;
+
+        // read in 5 nearby block's MVs from last frame.
+        if(cpi->common.last_frame_type != KEY_FRAME)
+        {
+            mb_offset = (-xd->mb_to_top_edge/128 + 1) * (xd->mode_info_stride +1) + (-xd->mb_to_left_edge/128 +1) ;
+
+            // current in last frame
+            if (cpi->lf_ref_frame[mb_offset] != INTRA_FRAME)
+            {
+                near_mvs[vcnt].as_int = cpi->lfmv[mb_offset].as_int;
+                mv_bias(cpi->lf_ref_frame_sign_bias[mb_offset], refframe, &near_mvs[vcnt], ref_frame_sign_bias);
+                near_ref[vcnt] =  cpi->lf_ref_frame[mb_offset];
+            }
+            vcnt++;
+
+            // above in last frame
+            if (cpi->lf_ref_frame[mb_offset - xd->mode_info_stride-1] != INTRA_FRAME)
+            {
+                near_mvs[vcnt].as_int = cpi->lfmv[mb_offset - xd->mode_info_stride-1].as_int;
+                mv_bias(cpi->lf_ref_frame_sign_bias[mb_offset - xd->mode_info_stride-1], refframe, &near_mvs[vcnt], ref_frame_sign_bias);
+                near_ref[vcnt] =  cpi->lf_ref_frame[mb_offset - xd->mode_info_stride-1];
+            }
+            vcnt++;
+
+            // left in last frame
+            if (cpi->lf_ref_frame[mb_offset-1] != INTRA_FRAME)
+            {
+                near_mvs[vcnt].as_int = cpi->lfmv[mb_offset -1].as_int;
+                mv_bias(cpi->lf_ref_frame_sign_bias[mb_offset -1], refframe, &near_mvs[vcnt], ref_frame_sign_bias);
+                near_ref[vcnt] =  cpi->lf_ref_frame[mb_offset - 1];
+            }
+            vcnt++;
+
+            // right in last frame
+            if (cpi->lf_ref_frame[mb_offset +1] != INTRA_FRAME)
+            {
+                near_mvs[vcnt].as_int = cpi->lfmv[mb_offset +1].as_int;
+                mv_bias(cpi->lf_ref_frame_sign_bias[mb_offset +1], refframe, &near_mvs[vcnt], ref_frame_sign_bias);
+                near_ref[vcnt] =  cpi->lf_ref_frame[mb_offset +1];
+            }
+            vcnt++;
+
+            // below in last frame
+            if (cpi->lf_ref_frame[mb_offset + xd->mode_info_stride +1] != INTRA_FRAME)
+            {
+                near_mvs[vcnt].as_int = cpi->lfmv[mb_offset + xd->mode_info_stride +1].as_int;
+                mv_bias(cpi->lf_ref_frame_sign_bias[mb_offset + xd->mode_info_stride +1], refframe, &near_mvs[vcnt], ref_frame_sign_bias);
+                near_ref[vcnt] =  cpi->lf_ref_frame[mb_offset + xd->mode_info_stride +1];
+            }
+            vcnt++;
+        }
+
+        for(i=0; i< vcnt; i++)
+        {
+            if(near_ref[near_sadidx[i]] != INTRA_FRAME)
+            {
+                if(here->mbmi.ref_frame == near_ref[near_sadidx[i]])
+                {
+                    mv.as_int = near_mvs[near_sadidx[i]].as_int;
+                    find = 1;
+                    if (i < 3)
+                        *sr = 3;
+                    else
+                        *sr = 2;
+                    break;
+                }
+            }
+        }
+
+        if(!find)
+        {
+            for(i=0; i<vcnt; i++)
+            {
+                mvx[i] = near_mvs[i].as_mv.row;
+                mvy[i] = near_mvs[i].as_mv.col;
+            }
+
+            insertsortmv(mvx, vcnt);
+            insertsortmv(mvy, vcnt);
+            mv.as_mv.row = mvx[vcnt/2];
+            mv.as_mv.col = mvy[vcnt/2];
+
+            find = 1;
+            //sr is set to 0 to allow calling function to decide the search range.
+            *sr = 0;
+        }
+    }
+
+    /* Set up return values */
+    mvp->as_int = mv.as_int;
+    vp8_clamp_mv2(mvp, xd);
+}
+
+void vp8_cal_sad(VP8_COMP *cpi, MACROBLOCKD *xd, MACROBLOCK *x, int recon_yoffset, int near_sadidx[])
+{
+
+    int near_sad[8] = {0}; // 0-cf above, 1-cf left, 2-cf aboveleft, 3-lf current, 4-lf above, 5-lf left, 6-lf right, 7-lf below
+    BLOCK *b = &x->block[0];
+    unsigned char *src_y_ptr = *(b->base_src);
+
+    //calculate sad for current frame 3 nearby MBs.
+    if( xd->mb_to_top_edge==0 && xd->mb_to_left_edge ==0)
+    {
+        near_sad[0] = near_sad[1] = near_sad[2] = INT_MAX;
+    }else if(xd->mb_to_top_edge==0)
+    {   //only has left MB for sad calculation.
+        near_sad[0] = near_sad[2] = INT_MAX;
+        near_sad[1] = cpi->fn_ptr[BLOCK_16X16].sdf(src_y_ptr, b->src_stride, xd->dst.y_buffer - 16,xd->dst.y_stride, 0x7fffffff);
+    }else if(xd->mb_to_left_edge ==0)
+    {   //only has left MB for sad calculation.
+        near_sad[1] = near_sad[2] = INT_MAX;
+        near_sad[0] = cpi->fn_ptr[BLOCK_16X16].sdf(src_y_ptr, b->src_stride, xd->dst.y_buffer - xd->dst.y_stride *16,xd->dst.y_stride, 0x7fffffff);
+    }else
+    {
+        near_sad[0] = cpi->fn_ptr[BLOCK_16X16].sdf(src_y_ptr, b->src_stride, xd->dst.y_buffer - xd->dst.y_stride *16,xd->dst.y_stride, 0x7fffffff);
+        near_sad[1] = cpi->fn_ptr[BLOCK_16X16].sdf(src_y_ptr, b->src_stride, xd->dst.y_buffer - 16,xd->dst.y_stride, 0x7fffffff);
+        near_sad[2] = cpi->fn_ptr[BLOCK_16X16].sdf(src_y_ptr, b->src_stride, xd->dst.y_buffer - xd->dst.y_stride *16 -16,xd->dst.y_stride, 0x7fffffff);
+    }
+
+    if(cpi->common.last_frame_type != KEY_FRAME)
+    {
+        //calculate sad for last frame 5 nearby MBs.
+        unsigned char *pre_y_buffer = cpi->common.yv12_fb[cpi->common.lst_fb_idx].y_buffer + recon_yoffset;
+        int pre_y_stride = cpi->common.yv12_fb[cpi->common.lst_fb_idx].y_stride;
+
+        if(xd->mb_to_top_edge==0) near_sad[4] = INT_MAX;
+        if(xd->mb_to_left_edge ==0) near_sad[5] = INT_MAX;
+        if(xd->mb_to_right_edge ==0) near_sad[6] = INT_MAX;
+        if(xd->mb_to_bottom_edge==0) near_sad[7] = INT_MAX;
+
+        if(near_sad[4] != INT_MAX)
+            near_sad[4] = cpi->fn_ptr[BLOCK_16X16].sdf(src_y_ptr, b->src_stride, pre_y_buffer - pre_y_stride *16, pre_y_stride, 0x7fffffff);
+        if(near_sad[5] != INT_MAX)
+            near_sad[5] = cpi->fn_ptr[BLOCK_16X16].sdf(src_y_ptr, b->src_stride, pre_y_buffer - 16, pre_y_stride, 0x7fffffff);
+        near_sad[3] = cpi->fn_ptr[BLOCK_16X16].sdf(src_y_ptr, b->src_stride, pre_y_buffer, pre_y_stride, 0x7fffffff);
+        if(near_sad[6] != INT_MAX)
+            near_sad[6] = cpi->fn_ptr[BLOCK_16X16].sdf(src_y_ptr, b->src_stride, pre_y_buffer + 16, pre_y_stride, 0x7fffffff);
+        if(near_sad[7] != INT_MAX)
+            near_sad[7] = cpi->fn_ptr[BLOCK_16X16].sdf(src_y_ptr, b->src_stride, pre_y_buffer + pre_y_stride *16, pre_y_stride, 0x7fffffff);
+    }
+
+    if(cpi->common.last_frame_type != KEY_FRAME)
+    {
+        insertsortsad(near_sad, near_sadidx, 8);
+    }else
+    {
+        insertsortsad(near_sad, near_sadidx, 3);
+    }
+}
+
+static void rd_update_mvcount(VP8_COMP *cpi, MACROBLOCK *x, int_mv *best_ref_mv)
+{
+    if (x->e_mbd.mode_info_context->mbmi.mode == SPLITMV)
+    {
+        int i;
+
+        for (i = 0; i < x->partition_info->count; i++)
+        {
+            if (x->partition_info->bmi[i].mode == NEW4X4)
+            {
+                cpi->MVcount[0][mv_max+((x->partition_info->bmi[i].mv.as_mv.row
+                                          - best_ref_mv->as_mv.row) >> 1)]++;
+                cpi->MVcount[1][mv_max+((x->partition_info->bmi[i].mv.as_mv.col
+                                          - best_ref_mv->as_mv.col) >> 1)]++;
+            }
+        }
+    }
+    else if (x->e_mbd.mode_info_context->mbmi.mode == NEWMV)
+    {
+        cpi->MVcount[0][mv_max+((x->e_mbd.mode_info_context->mbmi.mv.as_mv.row
+                                          - best_ref_mv->as_mv.row) >> 1)]++;
+        cpi->MVcount[1][mv_max+((x->e_mbd.mode_info_context->mbmi.mv.as_mv.col
+                                          - best_ref_mv->as_mv.col) >> 1)]++;
+    }
+}
+
+static int evaluate_inter_mode_rd(int mdcounts[4],
+                                  RATE_DISTORTION* rd,
+                                  int* disable_skip,
+                                  VP8_COMP *cpi, MACROBLOCK *x)
+{
+    MB_PREDICTION_MODE this_mode = x->e_mbd.mode_info_context->mbmi.mode;
+    BLOCK *b = &x->block[0];
+    MACROBLOCKD *xd = &x->e_mbd;
+    int distortion;
+    vp8_build_inter16x16_predictors_mby(&x->e_mbd, x->e_mbd.predictor, 16);
+
+    if (cpi->active_map_enabled && x->active_ptr[0] == 0) {
+        x->skip = 1;
+    }
+    else if (x->encode_breakout)
+    {
+        unsigned int sse;
+        unsigned int var;
+        int threshold = (xd->block[0].dequant[1]
+                    * xd->block[0].dequant[1] >>4);
+
+        if(threshold < x->encode_breakout)
+            threshold = x->encode_breakout;
+
+        var = vp8_variance16x16
+                (*(b->base_src), b->src_stride,
+                x->e_mbd.predictor, 16, &sse);
+
+        if (sse < threshold)
+        {
+             unsigned int q2dc = xd->block[24].dequant[0];
+            /* If theres is no codeable 2nd order dc
+               or a very small uniform pixel change change */
+            if ((sse - var < q2dc * q2dc >>4) ||
+                (sse /2 > var && sse-var < 64))
+            {
+                // Check u and v to make sure skip is ok
+                int sse2=  VP8_UVSSE(x);
+                if (sse2 * 2 < threshold)
+                {
+                    x->skip = 1;
+                    rd->distortion2 = sse + sse2;
+                    rd->rate2 = 500;
+
+                    /* for best_yrd calculation */
+                    rd->rate_uv = 0;
+                    rd->distortion_uv = sse2;
+
+                    *disable_skip = 1;
+                    return RDCOST(x->rdmult, x->rddiv, rd->rate2,
+                                  rd->distortion2);
+                }
+            }
+        }
+    }
+
+
+    //intermodecost[mode_index] = vp8_cost_mv_ref(this_mode, mdcounts);   // Experimental debug code
+
+    // Add in the Mv/mode cost
+    rd->rate2 += vp8_cost_mv_ref(this_mode, mdcounts);
+
+    // Y cost and distortion
+    macro_block_yrd(x, &rd->rate_y, &distortion);
+    rd->rate2 += rd->rate_y;
+    rd->distortion2 += distortion;
+
+    // UV cost and distortion
+    rd_inter16x16_uv(cpi, x, &rd->rate_uv, &rd->distortion_uv,
+                     cpi->common.full_pixel);
+    rd->rate2 += rd->rate_uv;
+    rd->distortion2 += rd->distortion_uv;
+    return INT_MAX;
+}
+
+static int calculate_final_rd_costs(int this_rd,
+                                    RATE_DISTORTION* rd,
+                                    int* other_cost,
+                                    int disable_skip,
+                                    int uv_intra_tteob,
+                                    int intra_rd_penalty,
+                                    VP8_COMP *cpi, MACROBLOCK *x)
+{
+    MB_PREDICTION_MODE this_mode = x->e_mbd.mode_info_context->mbmi.mode;
+    // Where skip is allowable add in the default per mb cost for the no skip case.
+    // where we then decide to skip we have to delete this and replace it with the
+    // cost of signallying a skip
+    if (cpi->common.mb_no_coeff_skip)
+    {
+        *other_cost += vp8_cost_bit(cpi->prob_skip_false, 0);
+        rd->rate2 += *other_cost;
+    }
+
+    /* Estimate the reference frame signaling cost and add it
+     * to the rolling cost variable.
+     */
+    rd->rate2 +=
+        x->ref_frame_cost[x->e_mbd.mode_info_context->mbmi.ref_frame];
+
+    if (!disable_skip)
+    {
+        // Test for the condition where skip block will be activated because there are no non zero coefficients and make any necessary adjustment for rate
+        if (cpi->common.mb_no_coeff_skip)
+        {
+            int i;
+            int tteob;
+            int has_y2_block = (this_mode!=SPLITMV && this_mode!=B_PRED);
+
+            tteob = 0;
+            if(has_y2_block)
+                tteob += x->e_mbd.eobs[24];
+
+            for (i = 0; i < 16; i++)
+                tteob += (x->e_mbd.eobs[i] > has_y2_block);
+
+            if (x->e_mbd.mode_info_context->mbmi.ref_frame)
+            {
+                for (i = 16; i < 24; i++)
+                    tteob += x->e_mbd.eobs[i];
+            }
+            else
+                tteob += uv_intra_tteob;
+
+            if (tteob == 0)
+            {
+                rd->rate2 -= (rd->rate_y + rd->rate_uv);
+                //for best_yrd calculation
+                rd->rate_uv = 0;
+
+                // Back out no skip flag costing and add in skip flag costing
+                if (cpi->prob_skip_false)
+                {
+                    int prob_skip_cost;
+
+                    prob_skip_cost = vp8_cost_bit(cpi->prob_skip_false, 1);
+                    prob_skip_cost -= vp8_cost_bit(cpi->prob_skip_false, 0);
+                    rd->rate2 += prob_skip_cost;
+                    *other_cost += prob_skip_cost;
+                }
+            }
+        }
+        // Calculate the final RD estimate for this mode
+        this_rd = RDCOST(x->rdmult, x->rddiv, rd->rate2, rd->distortion2);
+        if (this_rd < INT_MAX && x->e_mbd.mode_info_context->mbmi.ref_frame
+                                 == INTRA_FRAME)
+            this_rd += intra_rd_penalty;
+    }
+    return this_rd;
+}
+
+static void update_best_mode(BEST_MODE* best_mode, int this_rd,
+                             RATE_DISTORTION* rd, int other_cost, MACROBLOCK *x)
+{
+    MB_PREDICTION_MODE this_mode = x->e_mbd.mode_info_context->mbmi.mode;
+
+    other_cost +=
+    x->ref_frame_cost[x->e_mbd.mode_info_context->mbmi.ref_frame];
+
+    /* Calculate the final y RD estimate for this mode */
+    best_mode->yrd = RDCOST(x->rdmult, x->rddiv, (rd->rate2-rd->rate_uv-other_cost),
+                      (rd->distortion2-rd->distortion_uv));
+
+    best_mode->rd = this_rd;
+    vpx_memcpy(&best_mode->mbmode, &x->e_mbd.mode_info_context->mbmi, sizeof(MB_MODE_INFO));
+    vpx_memcpy(&best_mode->partition, x->partition_info, sizeof(PARTITION_INFO));
+
+    if ((this_mode == B_PRED) || (this_mode == SPLITMV))
+    {
+        int i;
+        for (i = 0; i < 16; i++)
+        {
+            best_mode->bmodes[i] = x->e_mbd.block[i].bmi;
+        }
+    }
+}
+
+void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
+                            int recon_uvoffset, int *returnrate,
+                            int *returndistortion, int *returnintra)
+{
+    BLOCK *b = &x->block[0];
+    BLOCKD *d = &x->e_mbd.block[0];
+    MACROBLOCKD *xd = &x->e_mbd;
+    int_mv best_ref_mv_sb[2];
+    int_mv mode_mv_sb[2][MB_MODE_COUNT];
+    int_mv best_ref_mv;
+    int_mv *mode_mv;
+    MB_PREDICTION_MODE this_mode;
+    int num00;
+    int best_mode_index = 0;
+    BEST_MODE best_mode;
+
+    int i;
+    int mode_index;
+    int mdcounts[4];
+    int rate;
+    RATE_DISTORTION rd;
+    int uv_intra_rate, uv_intra_distortion, uv_intra_rate_tokenonly;
+    int uv_intra_tteob = 0;
+    int uv_intra_done = 0;
+
+    MB_PREDICTION_MODE uv_intra_mode = 0;
+    int_mv mvp;
+    int near_sadidx[8] = {0, 1, 2, 3, 4, 5, 6, 7};
+    int saddone=0;
+    int sr=0;    //search range got from mv_pred(). It uses step_param levels. (0-7)
+
+    unsigned char *plane[4][3];
+    int ref_frame_map[4];
+    int sign_bias = 0;
+
+    int intra_rd_penalty =  10* vp8_dc_quant(cpi->common.base_qindex,
+                                             cpi->common.y1dc_delta_q);
+
+    mode_mv = mode_mv_sb[sign_bias];
+    best_ref_mv.as_int = 0;
+    best_mode.rd = INT_MAX;
+    best_mode.yrd = INT_MAX;
+    best_mode.intra_rd = INT_MAX;
+    vpx_memset(mode_mv_sb, 0, sizeof(mode_mv_sb));
+    vpx_memset(&best_mode.mbmode, 0, sizeof(best_mode.mbmode));
+    vpx_memset(&best_mode.bmodes, 0, sizeof(best_mode.bmodes));
+
+    /* Setup search priorities */
+    get_reference_search_order(cpi, ref_frame_map);
+
+    /* Check to see if there is at least 1 valid reference frame that we need
+     * to calculate near_mvs.
+     */
+    if (ref_frame_map[1] > 0)
+    {
+        sign_bias = vp8_find_near_mvs_bias(&x->e_mbd,
+                                           x->e_mbd.mode_info_context,
+                                           mode_mv_sb,
+                                           best_ref_mv_sb,
+                                           mdcounts,
+                                           ref_frame_map[1],
+                                           cpi->common.ref_frame_sign_bias);
+
+        mode_mv = mode_mv_sb[sign_bias];
+        best_ref_mv.as_int = best_ref_mv_sb[sign_bias].as_int;
+    }
+
+    get_predictor_pointers(cpi, plane, recon_yoffset, recon_uvoffset);
+
+    *returnintra = INT_MAX;
+    cpi->mbs_tested_so_far++;          // Count of the number of MBs tested so far this frame
+
+    x->skip = 0;
+
+    for (mode_index = 0; mode_index < MAX_MODES; mode_index++)
+    {
+        int this_rd = INT_MAX;
+        int disable_skip = 0;
+        int other_cost = 0;
+        int this_ref_frame = ref_frame_map[vp8_ref_frame_order[mode_index]];
+
+        // Test best rd so far against threshold for trying this mode.
+        if (best_mode.rd <= cpi->rd_threshes[mode_index])
+            continue;
+
+        if (this_ref_frame < 0)
+            continue;
+
+        // These variables hold are rolling total cost and distortion for this mode
+        rd.rate2 = 0;
+        rd.distortion2 = 0;
+
+        this_mode = vp8_mode_order[mode_index];
+
+        x->e_mbd.mode_info_context->mbmi.mode = this_mode;
+        x->e_mbd.mode_info_context->mbmi.ref_frame = this_ref_frame;
+
+        // Only consider ZEROMV/ALTREF_FRAME for alt ref frame,
+        // unless ARNR filtering is enabled in which case we want
+        // an unfiltered alternative
+        if (cpi->is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0))
+        {
+            if (this_mode != ZEROMV || x->e_mbd.mode_info_context->mbmi.ref_frame != ALTREF_FRAME)
+                continue;
+        }
+
+        /* everything but intra */
+        if (x->e_mbd.mode_info_context->mbmi.ref_frame)
+        {
+            x->e_mbd.pre.y_buffer = plane[this_ref_frame][0];
+            x->e_mbd.pre.u_buffer = plane[this_ref_frame][1];
+            x->e_mbd.pre.v_buffer = plane[this_ref_frame][2];
+
+            if (sign_bias != cpi->common.ref_frame_sign_bias[this_ref_frame])
+            {
+                sign_bias = cpi->common.ref_frame_sign_bias[this_ref_frame];
+                mode_mv = mode_mv_sb[sign_bias];
+                best_ref_mv.as_int = best_ref_mv_sb[sign_bias].as_int;
+            }
+        }
+
+        // Check to see if the testing frequency for this mode is at its max
+        // If so then prevent it from being tested and increase the threshold for its testing
+        if (cpi->mode_test_hit_counts[mode_index] && (cpi->mode_check_freq[mode_index] > 1))
+        {
+            if (cpi->mbs_tested_so_far  <= cpi->mode_check_freq[mode_index] * cpi->mode_test_hit_counts[mode_index])
+            {
+                // Increase the threshold for coding this mode to make it less likely to be chosen
+                cpi->rd_thresh_mult[mode_index] += 4;
+
+                if (cpi->rd_thresh_mult[mode_index] > MAX_THRESHMULT)
+                    cpi->rd_thresh_mult[mode_index] = MAX_THRESHMULT;
+
+                cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index];
+
+                continue;
+            }
+        }
+
+        // We have now reached the point where we are going to test the current mode so increment the counter for the number of times it has been tested
+        cpi->mode_test_hit_counts[mode_index] ++;
+
+        // Experimental code. Special case for gf and arf zeromv modes. Increase zbin size to supress noise
+        if (cpi->zbin_mode_boost_enabled)
+        {
+            if ( this_ref_frame == INTRA_FRAME )
+                cpi->zbin_mode_boost = 0;
+            else
+            {
+                if (vp8_mode_order[mode_index] == ZEROMV)
+                {
+                    if (this_ref_frame != LAST_FRAME)
+                        cpi->zbin_mode_boost = GF_ZEROMV_ZBIN_BOOST;
+                    else
+                        cpi->zbin_mode_boost = LF_ZEROMV_ZBIN_BOOST;
+                }
+                else if (vp8_mode_order[mode_index] == SPLITMV)
+                    cpi->zbin_mode_boost = 0;
+                else
+                    cpi->zbin_mode_boost = MV_ZBIN_BOOST;
+            }
+
+            vp8_update_zbin_extra(cpi, x);
+        }
+
+        if(!uv_intra_done && this_ref_frame == INTRA_FRAME)
+        {
+            rd_pick_intra_mbuv_mode(cpi, x, &uv_intra_rate,
+                                    &uv_intra_rate_tokenonly,
+                                    &uv_intra_distortion);
+            uv_intra_mode = x->e_mbd.mode_info_context->mbmi.uv_mode;
+
+            /*
+             * Total of the eobs is used later to further adjust rate2. Since uv
+             * block's intra eobs will be overwritten when we check inter modes,
+             * we need to save uv_intra_tteob here.
+             */
+            for (i = 16; i < 24; i++)
+                uv_intra_tteob += x->e_mbd.eobs[i];
+
+            uv_intra_done = 1;
+        }
+
+        switch (this_mode)
+        {
+        case B_PRED:
+        {
+            int tmp_rd;
+
+            // Note the rate value returned here includes the cost of coding the BPRED mode : x->mbmode_cost[x->e_mbd.frame_type][BPRED];
+            int distortion;
+            tmp_rd = rd_pick_intra4x4mby_modes(cpi, x, &rate, &rd.rate_y, &distortion, best_mode.yrd);
+            rd.rate2 += rate;
+            rd.distortion2 += distortion;
+
+            if(tmp_rd < best_mode.yrd)
+            {
+                rd.rate2 += uv_intra_rate;
+                rd.rate_uv = uv_intra_rate_tokenonly;
+                rd.distortion2 += uv_intra_distortion;
+                rd.distortion_uv = uv_intra_distortion;
+            }
+            else
+            {
+                this_rd = INT_MAX;
+                disable_skip = 1;
+            }
+        }
+        break;
+
+        case SPLITMV:
+        {
+            int tmp_rd;
+            int this_rd_thresh;
+            int distortion;
+
+            this_rd_thresh = (vp8_ref_frame_order[mode_index] == 1) ? cpi->rd_threshes[THR_NEW1] : cpi->rd_threshes[THR_NEW3];
+            this_rd_thresh = (vp8_ref_frame_order[mode_index] == 2) ? cpi->rd_threshes[THR_NEW2] : this_rd_thresh;
+
+            tmp_rd = vp8_rd_pick_best_mbsegmentation(cpi, x, &best_ref_mv,
+                                                     best_mode.yrd, mdcounts,
+                                                     &rate, &rd.rate_y, &distortion, this_rd_thresh) ;
+
+            rd.rate2 += rate;
+            rd.distortion2 += distortion;
+
+            // If even the 'Y' rd value of split is higher than best so far then dont bother looking at UV
+            if (tmp_rd < best_mode.yrd)
+            {
+                // Now work out UV cost and add it in
+                rd_inter4x4_uv(cpi, x, &rd.rate_uv, &rd.distortion_uv, cpi->common.full_pixel);
+                rd.rate2 += rd.rate_uv;
+                rd.distortion2 += rd.distortion_uv;
+            }
+            else
+            {
+                this_rd = INT_MAX;
+                disable_skip = 1;
+            }
+        }
+        break;
+        case DC_PRED:
+        case V_PRED:
+        case H_PRED:
+        case TM_PRED:
+        {
+            int distortion;
+            x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
+
+            vp8_build_intra_predictors_mby_s(xd,
+                                             xd->dst.y_buffer - xd->dst.y_stride,
+                                             xd->dst.y_buffer - 1,
+                                             xd->dst.y_stride,
+                                             xd->predictor,
+                                             16);
+            macro_block_yrd(x, &rd.rate_y, &distortion) ;
+            rd.rate2 += rd.rate_y;
+            rd.distortion2 += distortion;
+            rd.rate2 += x->mbmode_cost[x->e_mbd.frame_type][x->e_mbd.mode_info_context->mbmi.mode];
+            rd.rate2 += uv_intra_rate;
+            rd.rate_uv = uv_intra_rate_tokenonly;
+            rd.distortion2 += uv_intra_distortion;
+            rd.distortion_uv = uv_intra_distortion;
+        }
+        break;
+
+        case NEWMV:
+        {
+            int thissme;
+            int bestsme = INT_MAX;
+            int step_param = cpi->sf.first_step;
+            int further_steps;
+            int n;
+            int do_refine=1;   /* If last step (1-away) of n-step search doesn't pick the center point as the best match,
+                                  we will do a final 1-away diamond refining search  */
+
+            int sadpb = x->sadperbit16;
+            int_mv mvp_full;
+
+            int col_min = ((best_ref_mv.as_mv.col+7)>>3) - MAX_FULL_PEL_VAL;
+            int row_min = ((best_ref_mv.as_mv.row+7)>>3) - MAX_FULL_PEL_VAL;
+            int col_max = (best_ref_mv.as_mv.col>>3) + MAX_FULL_PEL_VAL;
+            int row_max = (best_ref_mv.as_mv.row>>3) + MAX_FULL_PEL_VAL;
+
+            int tmp_col_min = x->mv_col_min;
+            int tmp_col_max = x->mv_col_max;
+            int tmp_row_min = x->mv_row_min;
+            int tmp_row_max = x->mv_row_max;
+
+            if(!saddone)
+            {
+                vp8_cal_sad(cpi,xd,x, recon_yoffset ,&near_sadidx[0] );
+                saddone = 1;
+            }
+
+            vp8_mv_pred(cpi, &x->e_mbd, x->e_mbd.mode_info_context, &mvp,
+                        x->e_mbd.mode_info_context->mbmi.ref_frame, cpi->common.ref_frame_sign_bias, &sr, &near_sadidx[0]);
+
+            mvp_full.as_mv.col = mvp.as_mv.col>>3;
+            mvp_full.as_mv.row = mvp.as_mv.row>>3;
+
+            // Get intersection of UMV window and valid MV window to reduce # of checks in diamond search.
+            if (x->mv_col_min < col_min )
+                x->mv_col_min = col_min;
+            if (x->mv_col_max > col_max )
+                x->mv_col_max = col_max;
+            if (x->mv_row_min < row_min )
+                x->mv_row_min = row_min;
+            if (x->mv_row_max > row_max )
+                x->mv_row_max = row_max;
+
+            //adjust search range according to sr from mv prediction
+            if(sr > step_param)
+                step_param = sr;
+
+            // Initial step/diamond search
+            {
+                bestsme = cpi->diamond_search_sad(x, b, d, &mvp_full, &d->bmi.mv,
+                                        step_param, sadpb, &num00,
+                                        &cpi->fn_ptr[BLOCK_16X16],
+                                        x->mvcost, &best_ref_mv);
+                mode_mv[NEWMV].as_int = d->bmi.mv.as_int;
+
+                // Further step/diamond searches as necessary
+                n = 0;
+                further_steps = (cpi->sf.max_step_search_steps - 1) - step_param;
+
+                n = num00;
+                num00 = 0;
+
+                /* If there won't be more n-step search, check to see if refining search is needed. */
+                if (n > further_steps)
+                    do_refine = 0;
+
+                while (n < further_steps)
+                {
+                    n++;
+
+                    if (num00)
+                        num00--;
+                    else
+                    {
+                        thissme = cpi->diamond_search_sad(x, b, d, &mvp_full,
+                                    &d->bmi.mv, step_param + n, sadpb, &num00,
+                                    &cpi->fn_ptr[BLOCK_16X16], x->mvcost,
+                                    &best_ref_mv);
+
+                        /* check to see if refining search is needed. */
+                        if (num00 > (further_steps-n))
+                            do_refine = 0;
+
+                        if (thissme < bestsme)
+                        {
+                            bestsme = thissme;
+                            mode_mv[NEWMV].as_int = d->bmi.mv.as_int;
+                        }
+                        else
+                        {
+                            d->bmi.mv.as_int = mode_mv[NEWMV].as_int;
+                        }
+                    }
+                }
+            }
+
+            /* final 1-away diamond refining search */
+            if (do_refine == 1)
+            {
+                int search_range;
+
+                //It seems not a good way to set search_range. Need further investigation.
+                //search_range = MAXF(abs((mvp.row>>3) - d->bmi.mv.as_mv.row), abs((mvp.col>>3) - d->bmi.mv.as_mv.col));
+                search_range = 8;
+
+                //thissme = cpi->full_search_sad(x, b, d, &d->bmi.mv.as_mv, sadpb, search_range, &cpi->fn_ptr[BLOCK_16X16], x->mvcost, &best_ref_mv);
+                thissme = cpi->refining_search_sad(x, b, d, &d->bmi.mv, sadpb,
+                                       search_range, &cpi->fn_ptr[BLOCK_16X16],
+                                       x->mvcost, &best_ref_mv);
+
+                if (thissme < bestsme)
+                {
+                    bestsme = thissme;
+                    mode_mv[NEWMV].as_int = d->bmi.mv.as_int;
+                }
+                else
+                {
+                    d->bmi.mv.as_int = mode_mv[NEWMV].as_int;
+                }
+            }
+
+            x->mv_col_min = tmp_col_min;
+            x->mv_col_max = tmp_col_max;
+            x->mv_row_min = tmp_row_min;
+            x->mv_row_max = tmp_row_max;
+
+            if (bestsme < INT_MAX)
+            {
+                int dis; /* TODO: use dis in distortion calculation later. */
+                unsigned int sse;
+                cpi->find_fractional_mv_step(x, b, d, &d->bmi.mv, &best_ref_mv,
+                                             x->errorperbit,
+                                             &cpi->fn_ptr[BLOCK_16X16],
+                                             x->mvcost, &dis, &sse);
+            }
+
+            mode_mv[NEWMV].as_int = d->bmi.mv.as_int;
+
+            // Add the new motion vector cost to our rolling cost variable
+            rd.rate2 += vp8_mv_bit_cost(&mode_mv[NEWMV], &best_ref_mv, x->mvcost, 96);
+        }
+
+        case NEARESTMV:
+        case NEARMV:
+            // Clip "next_nearest" so that it does not extend to far out of image
+            vp8_clamp_mv2(&mode_mv[this_mode], xd);
+
+            // Do not bother proceeding if the vector (from newmv,nearest or near) is 0,0 as this should then be coded using the zeromv mode.
+            if (((this_mode == NEARMV) || (this_mode == NEARESTMV)) && (mode_mv[this_mode].as_int == 0))
+                continue;
+
+        case ZEROMV:
+
+            // Trap vectors that reach beyond the UMV borders
+            // Note that ALL New MV, Nearest MV Near MV and Zero MV code drops through to this point
+            // because of the lack of break statements in the previous two cases.
+            if (((mode_mv[this_mode].as_mv.row >> 3) < x->mv_row_min) || ((mode_mv[this_mode].as_mv.row >> 3) > x->mv_row_max) ||
+                ((mode_mv[this_mode].as_mv.col >> 3) < x->mv_col_min) || ((mode_mv[this_mode].as_mv.col >> 3) > x->mv_col_max))
+                continue;
+
+            vp8_set_mbmode_and_mvs(x, this_mode, &mode_mv[this_mode]);
+            this_rd = evaluate_inter_mode_rd(mdcounts, &rd,
+                                             &disable_skip, cpi, x);
+            break;
+
+        default:
+            break;
+        }
+
+        this_rd = calculate_final_rd_costs(this_rd, &rd, &other_cost,
+                                           disable_skip, uv_intra_tteob,
+                                           intra_rd_penalty, cpi, x);
+
+        // Keep record of best intra distortion
+        if ((x->e_mbd.mode_info_context->mbmi.ref_frame == INTRA_FRAME) &&
+            (this_rd < best_mode.intra_rd) )
+        {
+          best_mode.intra_rd = this_rd;
+            *returnintra = rd.distortion2 ;
+        }
+
+#if CONFIG_TEMPORAL_DENOISING
+        if (cpi->oxcf.noise_sensitivity)
+        {
+          // Store the best NEWMV in x for later use in the denoiser.
+          // We are restricted to the LAST_FRAME since the denoiser only keeps
+          // one filter state.
+          if (x->e_mbd.mode_info_context->mbmi.mode == NEWMV &&
+              x->e_mbd.mode_info_context->mbmi.ref_frame == LAST_FRAME)
+          {
+            x->e_mbd.best_sse_inter_mode = NEWMV;
+            x->e_mbd.best_sse_mv = x->e_mbd.mode_info_context->mbmi.mv;
+            x->e_mbd.need_to_clamp_best_mvs =
+                x->e_mbd.mode_info_context->mbmi.need_to_clamp_mvs;
+          }
+        }
+#endif
+
+        // Did this mode help.. i.i is it the new best mode
+        if (this_rd < best_mode.rd || x->skip)
+        {
+            // Note index of best mode so far
+            best_mode_index = mode_index;
+            *returnrate = rd.rate2;
+            *returndistortion = rd.distortion2;
+            if (this_mode <= B_PRED)
+            {
+                x->e_mbd.mode_info_context->mbmi.uv_mode = uv_intra_mode;
+                /* required for left and above block mv */
+                x->e_mbd.mode_info_context->mbmi.mv.as_int = 0;
+            }
+            update_best_mode(&best_mode, this_rd, &rd, other_cost, x);
+
+
+            // Testing this mode gave rise to an improvement in best error score. Lower threshold a bit for next time
+            cpi->rd_thresh_mult[mode_index] = (cpi->rd_thresh_mult[mode_index] >= (MIN_THRESHMULT + 2)) ? cpi->rd_thresh_mult[mode_index] - 2 : MIN_THRESHMULT;
+            cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index];
+        }
+
+        // If the mode did not help improve the best error case then raise the threshold for testing that mode next time around.
+        else
+        {
+            cpi->rd_thresh_mult[mode_index] += 4;
+
+            if (cpi->rd_thresh_mult[mode_index] > MAX_THRESHMULT)
+                cpi->rd_thresh_mult[mode_index] = MAX_THRESHMULT;
+
+            cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index];
+        }
+
+        if (x->skip)
+            break;
+
+    }
+
+    // Reduce the activation RD thresholds for the best choice mode
+    if ((cpi->rd_baseline_thresh[best_mode_index] > 0) && (cpi->rd_baseline_thresh[best_mode_index] < (INT_MAX >> 2)))
+    {
+        int best_adjustment = (cpi->rd_thresh_mult[best_mode_index] >> 2);
+
+        cpi->rd_thresh_mult[best_mode_index] = (cpi->rd_thresh_mult[best_mode_index] >= (MIN_THRESHMULT + best_adjustment)) ? cpi->rd_thresh_mult[best_mode_index] - best_adjustment : MIN_THRESHMULT;
+        cpi->rd_threshes[best_mode_index] = (cpi->rd_baseline_thresh[best_mode_index] >> 7) * cpi->rd_thresh_mult[best_mode_index];
+
+        // If we chose a split mode then reset the new MV thresholds as well
+        /*if ( vp8_mode_order[best_mode_index] == SPLITMV )
+        {
+            best_adjustment = 4; //(cpi->rd_thresh_mult[THR_NEWMV] >> 4);
+            cpi->rd_thresh_mult[THR_NEWMV] = (cpi->rd_thresh_mult[THR_NEWMV] >= (MIN_THRESHMULT+best_adjustment)) ? cpi->rd_thresh_mult[THR_NEWMV]-best_adjustment: MIN_THRESHMULT;
+            cpi->rd_threshes[THR_NEWMV] = (cpi->rd_baseline_thresh[THR_NEWMV] >> 7) * cpi->rd_thresh_mult[THR_NEWMV];
+
+            best_adjustment = 4; //(cpi->rd_thresh_mult[THR_NEWG] >> 4);
+            cpi->rd_thresh_mult[THR_NEWG] = (cpi->rd_thresh_mult[THR_NEWG] >= (MIN_THRESHMULT+best_adjustment)) ? cpi->rd_thresh_mult[THR_NEWG]-best_adjustment: MIN_THRESHMULT;
+            cpi->rd_threshes[THR_NEWG] = (cpi->rd_baseline_thresh[THR_NEWG] >> 7) * cpi->rd_thresh_mult[THR_NEWG];
+
+            best_adjustment = 4; //(cpi->rd_thresh_mult[THR_NEWA] >> 4);
+            cpi->rd_thresh_mult[THR_NEWA] = (cpi->rd_thresh_mult[THR_NEWA] >= (MIN_THRESHMULT+best_adjustment)) ? cpi->rd_thresh_mult[THR_NEWA]-best_adjustment: MIN_THRESHMULT;
+            cpi->rd_threshes[THR_NEWA] = (cpi->rd_baseline_thresh[THR_NEWA] >> 7) * cpi->rd_thresh_mult[THR_NEWA];
+        }*/
+
+    }
+
+    // Note how often each mode chosen as best
+    cpi->mode_chosen_counts[best_mode_index] ++;
+
+#if CONFIG_TEMPORAL_DENOISING
+    if (cpi->oxcf.noise_sensitivity)
+    {
+      if (x->e_mbd.best_sse_inter_mode == DC_PRED) {
+        // No best MV found.
+        x->e_mbd.best_sse_inter_mode = best_mode.mbmode.mode;
+        x->e_mbd.best_sse_mv = best_mode.mbmode.mv;
+        x->e_mbd.need_to_clamp_best_mvs = best_mode.mbmode.need_to_clamp_mvs;
+      }
+
+      // TODO(holmer): No SSEs are calculated in rdopt.c. What else can be used?
+      vp8_denoiser_denoise_mb(&cpi->denoiser, x, 0, 0,
+                              recon_yoffset, recon_uvoffset);
+      // Reevalute ZEROMV if the current mode is INTRA.
+      if (best_mode.mbmode.ref_frame == INTRA_FRAME)
+      {
+        int this_rd = INT_MAX;
+        int disable_skip = 0;
+        int other_cost = 0;
+        vpx_memset(&rd, 0, sizeof(rd));
+        x->e_mbd.mode_info_context->mbmi.ref_frame = LAST_FRAME;
+        rd.rate2 += x->ref_frame_cost[LAST_FRAME];
+        rd.rate2 += vp8_cost_mv_ref(ZEROMV, mdcounts);
+        x->e_mbd.mode_info_context->mbmi.mode = ZEROMV;
+        x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
+        x->e_mbd.mode_info_context->mbmi.mv.as_int = 0;
+        this_rd = evaluate_inter_mode_rd(mdcounts, &rd, &disable_skip, cpi, x);
+        this_rd = calculate_final_rd_costs(this_rd, &rd, &other_cost,
+                                           disable_skip, uv_intra_tteob,
+                                           intra_rd_penalty, cpi, x);
+        if (this_rd < best_mode.rd || x->skip)
+        {
+            // Note index of best mode so far
+            best_mode_index = mode_index;
+            *returnrate = rd.rate2;
+            *returndistortion = rd.distortion2;
+            update_best_mode(&best_mode, this_rd, &rd, other_cost, x);
+        }
+      }
+    }
+#endif
+
+    if (cpi->is_src_frame_alt_ref &&
+        (best_mode.mbmode.mode != ZEROMV || best_mode.mbmode.ref_frame != ALTREF_FRAME))
+    {
+        x->e_mbd.mode_info_context->mbmi.mode = ZEROMV;
+        x->e_mbd.mode_info_context->mbmi.ref_frame = ALTREF_FRAME;
+        x->e_mbd.mode_info_context->mbmi.mv.as_int = 0;
+        x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
+        x->e_mbd.mode_info_context->mbmi.mb_skip_coeff =
+                                        (cpi->common.mb_no_coeff_skip);
+        x->e_mbd.mode_info_context->mbmi.partitioning = 0;
+        return;
+    }
+
+
+    // macroblock modes
+    vpx_memcpy(&x->e_mbd.mode_info_context->mbmi, &best_mode.mbmode, sizeof(MB_MODE_INFO));
+
+    if (best_mode.mbmode.mode == B_PRED)
+    {
+        for (i = 0; i < 16; i++)
+            xd->mode_info_context->bmi[i].as_mode = best_mode.bmodes[i].as_mode;
+    }
+
+    if (best_mode.mbmode.mode == SPLITMV)
+    {
+        for (i = 0; i < 16; i++)
+            xd->mode_info_context->bmi[i].mv.as_int = best_mode.bmodes[i].mv.as_int;
+
+        vpx_memcpy(x->partition_info, &best_mode.partition, sizeof(PARTITION_INFO));
+
+        x->e_mbd.mode_info_context->mbmi.mv.as_int =
+                                      x->partition_info->bmi[15].mv.as_int;
+    }
+
+    if (sign_bias
+        != cpi->common.ref_frame_sign_bias[xd->mode_info_context->mbmi.ref_frame])
+        best_ref_mv.as_int = best_ref_mv_sb[!sign_bias].as_int;
+
+    rd_update_mvcount(cpi, x, &best_ref_mv);
+}
+
+void vp8_rd_pick_intra_mode(VP8_COMP *cpi, MACROBLOCK *x, int *rate_)
+{
+    int error4x4, error16x16;
+    int rate4x4, rate16x16 = 0, rateuv;
+    int dist4x4, dist16x16, distuv;
+    int rate;
+    int rate4x4_tokenonly = 0;
+    int rate16x16_tokenonly = 0;
+    int rateuv_tokenonly = 0;
+
+    x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
+
+    rd_pick_intra_mbuv_mode(cpi, x, &rateuv, &rateuv_tokenonly, &distuv);
+    rate = rateuv;
+
+    error16x16 = rd_pick_intra16x16mby_mode(cpi, x,
+                                            &rate16x16, &rate16x16_tokenonly,
+                                            &dist16x16);
+
+    error4x4 = rd_pick_intra4x4mby_modes(cpi, x,
+                                         &rate4x4, &rate4x4_tokenonly,
+                                         &dist4x4, error16x16);
+
+    if (error4x4 < error16x16)
+    {
+        x->e_mbd.mode_info_context->mbmi.mode = B_PRED;
+        rate += rate4x4;
+    }
+    else
+    {
+        rate += rate16x16;
+    }
+
+    *rate_ = rate;
+}
diff --git a/vp8/encoder/rdopt.h b/vp8/encoder/rdopt.h
new file mode 100644 (file)
index 0000000..db939f9
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_RDOPT_H
+#define __INC_RDOPT_H
+
+#define RDCOST(RM,DM,R,D) ( ((128+(R)*(RM)) >> 8) + (DM)*(D) )
+
+static void insertsortmv(int arr[], int len)
+{
+    int i, j, k;
+
+    for ( i = 1 ; i <= len-1 ; i++ )
+    {
+        for ( j = 0 ; j < i ; j++ )
+        {
+            if ( arr[j] > arr[i] )
+            {
+                int temp;
+
+                temp = arr[i];
+
+                for ( k = i; k >j; k--)
+                    arr[k] = arr[k - 1] ;
+
+                arr[j] = temp ;
+            }
+        }
+    }
+}
+
+static void insertsortsad(int arr[],int idx[], int len)
+{
+    int i, j, k;
+
+    for ( i = 1 ; i <= len-1 ; i++ )
+    {
+        for ( j = 0 ; j < i ; j++ )
+        {
+            if ( arr[j] > arr[i] )
+            {
+                int temp, tempi;
+
+                temp = arr[i];
+                tempi = idx[i];
+
+                for ( k = i; k >j; k--)
+                {
+                    arr[k] = arr[k - 1] ;
+                    idx[k] = idx[k - 1];
+                }
+
+                arr[j] = temp ;
+                idx[j] = tempi;
+            }
+        }
+    }
+}
+
+extern void vp8_initialize_rd_consts(VP8_COMP *cpi, int Qvalue);
+extern void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int recon_uvoffset, int *returnrate, int *returndistortion, int *returnintra);
+extern void vp8_rd_pick_intra_mode(VP8_COMP *cpi, MACROBLOCK *x, int *rate);
+
+
+static void get_plane_pointers(const YV12_BUFFER_CONFIG *fb,
+                               unsigned char            *plane[3],
+                               unsigned int              recon_yoffset,
+                               unsigned int              recon_uvoffset)
+{
+    plane[0] = fb->y_buffer + recon_yoffset;
+    plane[1] = fb->u_buffer + recon_uvoffset;
+    plane[2] = fb->v_buffer + recon_uvoffset;
+}
+
+
+static void get_predictor_pointers(const VP8_COMP *cpi,
+                                       unsigned char  *plane[4][3],
+                                       unsigned int    recon_yoffset,
+                                       unsigned int    recon_uvoffset)
+{
+    if (cpi->ref_frame_flags & VP8_LAST_FLAG)
+        get_plane_pointers(&cpi->common.yv12_fb[cpi->common.lst_fb_idx],
+                           plane[LAST_FRAME], recon_yoffset, recon_uvoffset);
+
+    if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
+        get_plane_pointers(&cpi->common.yv12_fb[cpi->common.gld_fb_idx],
+                           plane[GOLDEN_FRAME], recon_yoffset, recon_uvoffset);
+
+    if (cpi->ref_frame_flags & VP8_ALT_FLAG)
+        get_plane_pointers(&cpi->common.yv12_fb[cpi->common.alt_fb_idx],
+                           plane[ALTREF_FRAME], recon_yoffset, recon_uvoffset);
+}
+
+
+static void get_reference_search_order(const VP8_COMP *cpi,
+                                           int             ref_frame_map[4])
+{
+    int i=0;
+
+    ref_frame_map[i++] = INTRA_FRAME;
+    if (cpi->ref_frame_flags & VP8_LAST_FLAG)
+        ref_frame_map[i++] = LAST_FRAME;
+    if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
+        ref_frame_map[i++] = GOLDEN_FRAME;
+    if (cpi->ref_frame_flags & VP8_ALT_FLAG)
+        ref_frame_map[i++] = ALTREF_FRAME;
+    for(; i<4; i++)
+        ref_frame_map[i] = -1;
+}
+
+
+extern void vp8_mv_pred
+(
+    VP8_COMP *cpi,
+    MACROBLOCKD *xd,
+    const MODE_INFO *here,
+    int_mv *mvp,
+    int refframe,
+    int *ref_frame_sign_bias,
+    int *sr,
+    int near_sadidx[]
+);
+void vp8_cal_sad(VP8_COMP *cpi, MACROBLOCKD *xd, MACROBLOCK *x, int recon_yoffset, int near_sadidx[]);
+
+#endif
diff --git a/vp8/encoder/segmentation.c b/vp8/encoder/segmentation.c
new file mode 100644 (file)
index 0000000..fc0967d
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "segmentation.h"
+#include "vpx_mem/vpx_mem.h"
+
+void vp8_update_gf_useage_maps(VP8_COMP *cpi, VP8_COMMON *cm, MACROBLOCK *x)
+{
+    int mb_row, mb_col;
+
+    MODE_INFO *this_mb_mode_info = cm->mi;
+
+    x->gf_active_ptr = (signed char *)cpi->gf_active_flags;
+
+    if ((cm->frame_type == KEY_FRAME) || (cm->refresh_golden_frame))
+    {
+        // Reset Gf useage monitors
+        vpx_memset(cpi->gf_active_flags, 1, (cm->mb_rows * cm->mb_cols));
+        cpi->gf_active_count = cm->mb_rows * cm->mb_cols;
+    }
+    else
+    {
+        // for each macroblock row in image
+        for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
+        {
+            // for each macroblock col in image
+            for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+            {
+
+                // If using golden then set GF active flag if not already set.
+                // If using last frame 0,0 mode then leave flag as it is
+                // else if using non 0,0 motion or intra modes then clear flag if it is currently set
+                if ((this_mb_mode_info->mbmi.ref_frame == GOLDEN_FRAME) || (this_mb_mode_info->mbmi.ref_frame == ALTREF_FRAME))
+                {
+                    if (*(x->gf_active_ptr) == 0)
+                    {
+                        *(x->gf_active_ptr) = 1;
+                        cpi->gf_active_count ++;
+                    }
+                }
+                else if ((this_mb_mode_info->mbmi.mode != ZEROMV) && *(x->gf_active_ptr))
+                {
+                    *(x->gf_active_ptr) = 0;
+                    cpi->gf_active_count--;
+                }
+
+                x->gf_active_ptr++;          // Step onto next entry
+                this_mb_mode_info++;           // skip to next mb
+
+            }
+
+            // this is to account for the border
+            this_mb_mode_info++;
+        }
+    }
+}
diff --git a/vp8/encoder/segmentation.h b/vp8/encoder/segmentation.h
new file mode 100644 (file)
index 0000000..12815b0
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "string.h"
+#include "vp8/common/blockd.h"
+#include "onyx_int.h"
+
+extern void vp8_update_gf_useage_maps(VP8_COMP *cpi, VP8_COMMON *cm, MACROBLOCK *x);
diff --git a/vp8/encoder/ssim.c b/vp8/encoder/ssim.c
new file mode 100644 (file)
index 0000000..e751608
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "onyx_int.h"
+
+void vp8_ssim_parms_16x16_c
+(
+    unsigned char *s,
+    int sp,
+    unsigned char *r,
+    int rp,
+    unsigned long *sum_s,
+    unsigned long *sum_r,
+    unsigned long *sum_sq_s,
+    unsigned long *sum_sq_r,
+    unsigned long *sum_sxr
+)
+{
+    int i,j;
+    for(i=0;i<16;i++,s+=sp,r+=rp)
+     {
+         for(j=0;j<16;j++)
+         {
+             *sum_s += s[j];
+             *sum_r += r[j];
+             *sum_sq_s += s[j] * s[j];
+             *sum_sq_r += r[j] * r[j];
+             *sum_sxr += s[j] * r[j];
+         }
+     }
+}
+void vp8_ssim_parms_8x8_c
+(
+    unsigned char *s,
+    int sp,
+    unsigned char *r,
+    int rp,
+    unsigned long *sum_s,
+    unsigned long *sum_r,
+    unsigned long *sum_sq_s,
+    unsigned long *sum_sq_r,
+    unsigned long *sum_sxr
+)
+{
+    int i,j;
+    for(i=0;i<8;i++,s+=sp,r+=rp)
+     {
+         for(j=0;j<8;j++)
+         {
+             *sum_s += s[j];
+             *sum_r += r[j];
+             *sum_sq_s += s[j] * s[j];
+             *sum_sq_r += r[j] * r[j];
+             *sum_sxr += s[j] * r[j];
+         }
+     }
+}
+
+const static int64_t cc1 =  26634; // (64^2*(.01*255)^2
+const static int64_t cc2 = 239708; // (64^2*(.03*255)^2
+
+static double similarity
+(
+    unsigned long sum_s,
+    unsigned long sum_r,
+    unsigned long sum_sq_s,
+    unsigned long sum_sq_r,
+    unsigned long sum_sxr,
+    int count
+)
+{
+    int64_t ssim_n, ssim_d;
+    int64_t c1, c2;
+
+    //scale the constants by number of pixels
+    c1 = (cc1*count*count)>>12;
+    c2 = (cc2*count*count)>>12;
+
+    ssim_n = (2*sum_s*sum_r+ c1)*((int64_t) 2*count*sum_sxr-
+          (int64_t) 2*sum_s*sum_r+c2);
+
+    ssim_d = (sum_s*sum_s +sum_r*sum_r+c1)*
+        ((int64_t)count*sum_sq_s-(int64_t)sum_s*sum_s +
+        (int64_t)count*sum_sq_r-(int64_t) sum_r*sum_r +c2) ;
+
+    return ssim_n * 1.0 / ssim_d;
+}
+
+static double ssim_16x16(unsigned char *s,int sp, unsigned char *r,int rp)
+{
+    unsigned long sum_s=0,sum_r=0,sum_sq_s=0,sum_sq_r=0,sum_sxr=0;
+    vp8_ssim_parms_16x16(s, sp, r, rp, &sum_s, &sum_r, &sum_sq_s, &sum_sq_r, &sum_sxr);
+    return similarity(sum_s, sum_r, sum_sq_s, sum_sq_r, sum_sxr, 256);
+}
+static double ssim_8x8(unsigned char *s,int sp, unsigned char *r,int rp)
+{
+    unsigned long sum_s=0,sum_r=0,sum_sq_s=0,sum_sq_r=0,sum_sxr=0;
+    vp8_ssim_parms_8x8(s, sp, r, rp, &sum_s, &sum_r, &sum_sq_s, &sum_sq_r, &sum_sxr);
+    return similarity(sum_s, sum_r, sum_sq_s, sum_sq_r, sum_sxr, 64);
+}
+
+// TODO: (jbb) tried to scale this function such that we may be able to use it
+// for distortion metric in mode selection code ( provided we do a reconstruction)
+long dssim(unsigned char *s,int sp, unsigned char *r,int rp)
+{
+    unsigned long sum_s=0,sum_r=0,sum_sq_s=0,sum_sq_r=0,sum_sxr=0;
+    int64_t ssim3;
+    int64_t ssim_n1,ssim_n2;
+    int64_t ssim_d1,ssim_d2;
+    int64_t ssim_t1,ssim_t2;
+    int64_t c1, c2;
+
+    // normalize by 256/64
+    c1 = cc1*16;
+    c2 = cc2*16;
+
+    vp8_ssim_parms_16x16(s, sp, r, rp, &sum_s, &sum_r, &sum_sq_s, &sum_sq_r, &sum_sxr);
+    ssim_n1 = (2*sum_s*sum_r+ c1);
+
+    ssim_n2 =((int64_t) 2*256*sum_sxr-(int64_t) 2*sum_s*sum_r+c2);
+
+    ssim_d1 =((int64_t)sum_s*sum_s +(int64_t)sum_r*sum_r+c1);
+
+    ssim_d2 = (256 * (int64_t) sum_sq_s-(int64_t) sum_s*sum_s +
+                    (int64_t) 256*sum_sq_r-(int64_t) sum_r*sum_r +c2) ;
+
+    ssim_t1 = 256 - 256 * ssim_n1 / ssim_d1;
+    ssim_t2 = 256 - 256 * ssim_n2 / ssim_d2;
+
+    ssim3 = 256 *ssim_t1 * ssim_t2;
+    if(ssim3 <0 )
+        ssim3=0;
+    return (long)( ssim3  );
+}
+
+// We are using a 8x8 moving window with starting location of each 8x8 window
+// on the 4x4 pixel grid. Such arrangement allows the windows to overlap
+// block boundaries to penalize blocking artifacts.
+double vp8_ssim2
+(
+    unsigned char *img1,
+    unsigned char *img2,
+    int stride_img1,
+    int stride_img2,
+    int width,
+    int height
+)
+{
+    int i,j;
+    int samples =0;
+    double ssim_total=0;
+
+    // sample point start with each 4x4 location
+    for(i=0; i < height-8; i+=4, img1 += stride_img1*4, img2 += stride_img2*4)
+    {
+        for(j=0; j < width-8; j+=4 )
+        {
+            double v = ssim_8x8(img1+j, stride_img1, img2+j, stride_img2);
+            ssim_total += v;
+            samples++;
+        }
+    }
+    ssim_total /= samples;
+    return ssim_total;
+}
+double vp8_calc_ssim
+(
+    YV12_BUFFER_CONFIG *source,
+    YV12_BUFFER_CONFIG *dest,
+    int lumamask,
+    double *weight
+)
+{
+    double a, b, c;
+    double ssimv;
+
+    a = vp8_ssim2(source->y_buffer, dest->y_buffer,
+                 source->y_stride, dest->y_stride, source->y_width,
+                 source->y_height);
+
+    b = vp8_ssim2(source->u_buffer, dest->u_buffer,
+                 source->uv_stride, dest->uv_stride, source->uv_width,
+                 source->uv_height);
+
+    c = vp8_ssim2(source->v_buffer, dest->v_buffer,
+                 source->uv_stride, dest->uv_stride, source->uv_width,
+                 source->uv_height);
+
+    ssimv = a * .8 + .1 * (b + c);
+
+    *weight = 1;
+
+    return ssimv;
+}
+
+double vp8_calc_ssimg
+(
+    YV12_BUFFER_CONFIG *source,
+    YV12_BUFFER_CONFIG *dest,
+    double *ssim_y,
+    double *ssim_u,
+    double *ssim_v
+)
+{
+    double ssim_all = 0;
+    double a, b, c;
+
+    a = vp8_ssim2(source->y_buffer, dest->y_buffer,
+                 source->y_stride, dest->y_stride, source->y_width,
+                 source->y_height);
+
+    b = vp8_ssim2(source->u_buffer, dest->u_buffer,
+                 source->uv_stride, dest->uv_stride, source->uv_width,
+                 source->uv_height);
+
+    c = vp8_ssim2(source->v_buffer, dest->v_buffer,
+                 source->uv_stride, dest->uv_stride, source->uv_width,
+                 source->uv_height);
+    *ssim_y = a;
+    *ssim_u = b;
+    *ssim_v = c;
+    ssim_all = (a * 4 + b + c) /6;
+
+    return ssim_all;
+}
diff --git a/vp8/encoder/temporal_filter.c b/vp8/encoder/temporal_filter.c
new file mode 100644 (file)
index 0000000..6c61b36
--- /dev/null
@@ -0,0 +1,533 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vp8/common/onyxc_int.h"
+#include "onyx_int.h"
+#include "vp8/common/systemdependent.h"
+#include "quantize.h"
+#include "vp8/common/alloccommon.h"
+#include "mcomp.h"
+#include "firstpass.h"
+#include "psnr.h"
+#include "vpx_scale/vpxscale.h"
+#include "vp8/common/extend.h"
+#include "ratectrl.h"
+#include "vp8/common/quant_common.h"
+#include "segmentation.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vp8/common/swapyv12buffer.h"
+#include "vp8/common/threading.h"
+#include "vpx_ports/vpx_timer.h"
+
+#include <math.h>
+#include <limits.h>
+
+#define ALT_REF_MC_ENABLED 1    // dis/enable MC in AltRef filtering
+#define ALT_REF_SUBPEL_ENABLED 1 // dis/enable subpel in MC AltRef filtering
+
+#if VP8_TEMPORAL_ALT_REF
+
+static void vp8_temporal_filter_predictors_mb_c
+(
+    MACROBLOCKD *x,
+    unsigned char *y_mb_ptr,
+    unsigned char *u_mb_ptr,
+    unsigned char *v_mb_ptr,
+    int stride,
+    int mv_row,
+    int mv_col,
+    unsigned char *pred
+)
+{
+    int offset;
+    unsigned char *yptr, *uptr, *vptr;
+
+    // Y
+    yptr = y_mb_ptr + (mv_row >> 3) * stride + (mv_col >> 3);
+
+    if ((mv_row | mv_col) & 7)
+    {
+        x->subpixel_predict16x16(yptr, stride,
+                                    mv_col & 7, mv_row & 7, &pred[0], 16);
+    }
+    else
+    {
+        vp8_copy_mem16x16(yptr, stride, &pred[0], 16);
+    }
+
+    // U & V
+    mv_row >>= 1;
+    mv_col >>= 1;
+    stride = (stride + 1) >> 1;
+    offset = (mv_row >> 3) * stride + (mv_col >> 3);
+    uptr = u_mb_ptr + offset;
+    vptr = v_mb_ptr + offset;
+
+    if ((mv_row | mv_col) & 7)
+    {
+        x->subpixel_predict8x8(uptr, stride,
+                            mv_col & 7, mv_row & 7, &pred[256], 8);
+        x->subpixel_predict8x8(vptr, stride,
+                            mv_col & 7, mv_row & 7, &pred[320], 8);
+    }
+    else
+    {
+        vp8_copy_mem8x8(uptr, stride, &pred[256], 8);
+        vp8_copy_mem8x8(vptr, stride, &pred[320], 8);
+    }
+}
+void vp8_temporal_filter_apply_c
+(
+    unsigned char *frame1,
+    unsigned int stride,
+    unsigned char *frame2,
+    unsigned int block_size,
+    int strength,
+    int filter_weight,
+    unsigned int *accumulator,
+    unsigned short *count
+)
+{
+    unsigned int i, j, k;
+    int modifier;
+    int byte = 0;
+
+    for (i = 0,k = 0; i < block_size; i++)
+    {
+        for (j = 0; j < block_size; j++, k++)
+        {
+
+            int src_byte = frame1[byte];
+            int pixel_value = *frame2++;
+
+            modifier   = src_byte - pixel_value;
+            // This is an integer approximation of:
+            // float coeff = (3.0 * modifer * modifier) / pow(2, strength);
+            // modifier =  (int)roundf(coeff > 16 ? 0 : 16-coeff);
+            modifier  *= modifier;
+            modifier  *= 3;
+            modifier  += 1 << (strength - 1);
+            modifier >>= strength;
+
+            if (modifier > 16)
+                modifier = 16;
+
+            modifier = 16 - modifier;
+            modifier *= filter_weight;
+
+            count[k] += modifier;
+            accumulator[k] += modifier * pixel_value;
+
+            byte++;
+        }
+
+        byte += stride - block_size;
+    }
+}
+
+#if ALT_REF_MC_ENABLED
+static int dummy_cost[2*mv_max+1];
+
+static int vp8_temporal_filter_find_matching_mb_c
+(
+    VP8_COMP *cpi,
+    YV12_BUFFER_CONFIG *arf_frame,
+    YV12_BUFFER_CONFIG *frame_ptr,
+    int mb_offset,
+    int error_thresh
+)
+{
+    MACROBLOCK *x = &cpi->mb;
+    int step_param;
+    int sadpb = x->sadperbit16;
+    int bestsme = INT_MAX;
+
+    BLOCK *b = &x->block[0];
+    BLOCKD *d = &x->e_mbd.block[0];
+    int_mv best_ref_mv1;
+    int_mv best_ref_mv1_full; /* full-pixel value of best_ref_mv1 */
+
+    int *mvcost[2]    = { &dummy_cost[mv_max+1], &dummy_cost[mv_max+1] };
+    int *mvsadcost[2] = { &dummy_cost[mv_max+1], &dummy_cost[mv_max+1] };
+
+    // Save input state
+    unsigned char **base_src = b->base_src;
+    int src = b->src;
+    int src_stride = b->src_stride;
+    unsigned char *base_pre = x->e_mbd.pre.y_buffer;
+    int pre = d->offset;
+    int pre_stride = x->e_mbd.pre.y_stride;
+
+    best_ref_mv1.as_int = 0;
+    best_ref_mv1_full.as_mv.col = best_ref_mv1.as_mv.col >>3;
+    best_ref_mv1_full.as_mv.row = best_ref_mv1.as_mv.row >>3;
+
+    // Setup frame pointers
+    b->base_src = &arf_frame->y_buffer;
+    b->src_stride = arf_frame->y_stride;
+    b->src = mb_offset;
+
+    x->e_mbd.pre.y_buffer = frame_ptr->y_buffer;
+    x->e_mbd.pre.y_stride = frame_ptr->y_stride;
+    d->offset = mb_offset;
+
+    // Further step/diamond searches as necessary
+    if (cpi->Speed < 8)
+    {
+        step_param = cpi->sf.first_step + (cpi->Speed > 5);
+    }
+    else
+    {
+        step_param = cpi->sf.first_step + 2;
+    }
+
+    /*cpi->sf.search_method == HEX*/
+    // TODO Check that the 16x16 vf & sdf are selected here
+    bestsme = vp8_hex_search(x, b, d,
+        &best_ref_mv1_full, &d->bmi.mv,
+        step_param,
+        sadpb,
+        &cpi->fn_ptr[BLOCK_16X16],
+        mvsadcost, mvcost, &best_ref_mv1);
+
+#if ALT_REF_SUBPEL_ENABLED
+    // Try sub-pixel MC?
+    //if (bestsme > error_thresh && bestsme < INT_MAX)
+    {
+        int distortion;
+        unsigned int sse;
+        bestsme = cpi->find_fractional_mv_step(x, b, d,
+                    &d->bmi.mv, &best_ref_mv1,
+                    x->errorperbit, &cpi->fn_ptr[BLOCK_16X16],
+                    mvcost, &distortion, &sse);
+    }
+#endif
+
+    // Save input state
+    b->base_src = base_src;
+    b->src = src;
+    b->src_stride = src_stride;
+    x->e_mbd.pre.y_buffer = base_pre;
+    d->offset = pre;
+    x->e_mbd.pre.y_stride = pre_stride;
+
+    return bestsme;
+}
+#endif
+
+static void vp8_temporal_filter_iterate_c
+(
+    VP8_COMP *cpi,
+    int frame_count,
+    int alt_ref_index,
+    int strength
+)
+{
+    int byte;
+    int frame;
+    int mb_col, mb_row;
+    unsigned int filter_weight;
+    int mb_cols = cpi->common.mb_cols;
+    int mb_rows = cpi->common.mb_rows;
+    int mb_y_offset = 0;
+    int mb_uv_offset = 0;
+    DECLARE_ALIGNED_ARRAY(16, unsigned int, accumulator, 16*16 + 8*8 + 8*8);
+    DECLARE_ALIGNED_ARRAY(16, unsigned short, count, 16*16 + 8*8 + 8*8);
+    MACROBLOCKD *mbd = &cpi->mb.e_mbd;
+    YV12_BUFFER_CONFIG *f = cpi->frames[alt_ref_index];
+    unsigned char *dst1, *dst2;
+    DECLARE_ALIGNED_ARRAY(16, unsigned char,  predictor, 16*16 + 8*8 + 8*8);
+
+    // Save input state
+    unsigned char *y_buffer = mbd->pre.y_buffer;
+    unsigned char *u_buffer = mbd->pre.u_buffer;
+    unsigned char *v_buffer = mbd->pre.v_buffer;
+
+    for (mb_row = 0; mb_row < mb_rows; mb_row++)
+    {
+#if ALT_REF_MC_ENABLED
+        // Source frames are extended to 16 pixels.  This is different than
+        //  L/A/G reference frames that have a border of 32 (VP8BORDERINPIXELS)
+        // A 6 tap filter is used for motion search.  This requires 2 pixels
+        //  before and 3 pixels after.  So the largest Y mv on a border would
+        //  then be 16 - 3.  The UV blocks are half the size of the Y and
+        //  therefore only extended by 8.  The largest mv that a UV block
+        //  can support is 8 - 3.  A UV mv is half of a Y mv.
+        //  (16 - 3) >> 1 == 6 which is greater than 8 - 3.
+        // To keep the mv in play for both Y and UV planes the max that it
+        //  can be on a border is therefore 16 - 5.
+        cpi->mb.mv_row_min = -((mb_row * 16) + (16 - 5));
+        cpi->mb.mv_row_max = ((cpi->common.mb_rows - 1 - mb_row) * 16)
+                                + (16 - 5);
+#endif
+
+        for (mb_col = 0; mb_col < mb_cols; mb_col++)
+        {
+            int i, j, k;
+            int stride;
+
+            vpx_memset(accumulator, 0, 384*sizeof(unsigned int));
+            vpx_memset(count, 0, 384*sizeof(unsigned short));
+
+#if ALT_REF_MC_ENABLED
+            cpi->mb.mv_col_min = -((mb_col * 16) + (16 - 5));
+            cpi->mb.mv_col_max = ((cpi->common.mb_cols - 1 - mb_col) * 16)
+                                    + (16 - 5);
+#endif
+
+            for (frame = 0; frame < frame_count; frame++)
+            {
+                int err = 0;
+
+                if (cpi->frames[frame] == NULL)
+                    continue;
+
+                mbd->block[0].bmi.mv.as_mv.row = 0;
+                mbd->block[0].bmi.mv.as_mv.col = 0;
+
+#if ALT_REF_MC_ENABLED
+#define THRESH_LOW   10000
+#define THRESH_HIGH  20000
+
+                // Find best match in this frame by MC
+                err = vp8_temporal_filter_find_matching_mb_c
+                      (cpi,
+                       cpi->frames[alt_ref_index],
+                       cpi->frames[frame],
+                       mb_y_offset,
+                       THRESH_LOW);
+
+#endif
+                // Assign higher weight to matching MB if it's error
+                // score is lower. If not applying MC default behavior
+                // is to weight all MBs equal.
+                filter_weight = err<THRESH_LOW
+                                  ? 2 : err<THRESH_HIGH ? 1 : 0;
+
+                if (filter_weight != 0)
+                {
+                    // Construct the predictors
+                    vp8_temporal_filter_predictors_mb_c
+                        (mbd,
+                         cpi->frames[frame]->y_buffer + mb_y_offset,
+                         cpi->frames[frame]->u_buffer + mb_uv_offset,
+                         cpi->frames[frame]->v_buffer + mb_uv_offset,
+                         cpi->frames[frame]->y_stride,
+                         mbd->block[0].bmi.mv.as_mv.row,
+                         mbd->block[0].bmi.mv.as_mv.col,
+                         predictor);
+
+                    // Apply the filter (YUV)
+                    vp8_temporal_filter_apply
+                        (f->y_buffer + mb_y_offset,
+                         f->y_stride,
+                         predictor,
+                         16,
+                         strength,
+                         filter_weight,
+                         accumulator,
+                         count);
+
+                    vp8_temporal_filter_apply
+                        (f->u_buffer + mb_uv_offset,
+                         f->uv_stride,
+                         predictor + 256,
+                         8,
+                         strength,
+                         filter_weight,
+                         accumulator + 256,
+                         count + 256);
+
+                    vp8_temporal_filter_apply
+                        (f->v_buffer + mb_uv_offset,
+                         f->uv_stride,
+                         predictor + 320,
+                         8,
+                         strength,
+                         filter_weight,
+                         accumulator + 320,
+                         count + 320);
+                }
+            }
+
+            // Normalize filter output to produce AltRef frame
+            dst1 = cpi->alt_ref_buffer.y_buffer;
+            stride = cpi->alt_ref_buffer.y_stride;
+            byte = mb_y_offset;
+            for (i = 0,k = 0; i < 16; i++)
+            {
+                for (j = 0; j < 16; j++, k++)
+                {
+                    unsigned int pval = accumulator[k] + (count[k] >> 1);
+                    pval *= cpi->fixed_divide[count[k]];
+                    pval >>= 19;
+
+                    dst1[byte] = (unsigned char)pval;
+
+                    // move to next pixel
+                    byte++;
+                }
+
+                byte += stride - 16;
+            }
+
+            dst1 = cpi->alt_ref_buffer.u_buffer;
+            dst2 = cpi->alt_ref_buffer.v_buffer;
+            stride = cpi->alt_ref_buffer.uv_stride;
+            byte = mb_uv_offset;
+            for (i = 0,k = 256; i < 8; i++)
+            {
+                for (j = 0; j < 8; j++, k++)
+                {
+                    int m=k+64;
+
+                    // U
+                    unsigned int pval = accumulator[k] + (count[k] >> 1);
+                    pval *= cpi->fixed_divide[count[k]];
+                    pval >>= 19;
+                    dst1[byte] = (unsigned char)pval;
+
+                    // V
+                    pval = accumulator[m] + (count[m] >> 1);
+                    pval *= cpi->fixed_divide[count[m]];
+                    pval >>= 19;
+                    dst2[byte] = (unsigned char)pval;
+
+                    // move to next pixel
+                    byte++;
+                }
+
+                byte += stride - 8;
+            }
+
+            mb_y_offset += 16;
+            mb_uv_offset += 8;
+        }
+
+        mb_y_offset += 16*(f->y_stride-mb_cols);
+        mb_uv_offset += 8*(f->uv_stride-mb_cols);
+    }
+
+    // Restore input state
+    mbd->pre.y_buffer = y_buffer;
+    mbd->pre.u_buffer = u_buffer;
+    mbd->pre.v_buffer = v_buffer;
+}
+
+void vp8_temporal_filter_prepare_c
+(
+    VP8_COMP *cpi,
+    int distance
+)
+{
+    int frame = 0;
+
+    int num_frames_backward = 0;
+    int num_frames_forward = 0;
+    int frames_to_blur_backward = 0;
+    int frames_to_blur_forward = 0;
+    int frames_to_blur = 0;
+    int start_frame = 0;
+
+    int strength = cpi->oxcf.arnr_strength;
+
+    int blur_type = cpi->oxcf.arnr_type;
+
+    int max_frames = cpi->active_arnr_frames;
+
+    num_frames_backward = distance;
+    num_frames_forward = vp8_lookahead_depth(cpi->lookahead)
+                         - (num_frames_backward + 1);
+
+    switch (blur_type)
+    {
+    case 1:
+        /////////////////////////////////////////
+        // Backward Blur
+
+        frames_to_blur_backward = num_frames_backward;
+
+        if (frames_to_blur_backward >= max_frames)
+            frames_to_blur_backward = max_frames - 1;
+
+        frames_to_blur = frames_to_blur_backward + 1;
+        break;
+
+    case 2:
+        /////////////////////////////////////////
+        // Forward Blur
+
+        frames_to_blur_forward = num_frames_forward;
+
+        if (frames_to_blur_forward >= max_frames)
+            frames_to_blur_forward = max_frames - 1;
+
+        frames_to_blur = frames_to_blur_forward + 1;
+        break;
+
+    case 3:
+    default:
+        /////////////////////////////////////////
+        // Center Blur
+        frames_to_blur_forward = num_frames_forward;
+        frames_to_blur_backward = num_frames_backward;
+
+        if (frames_to_blur_forward > frames_to_blur_backward)
+            frames_to_blur_forward = frames_to_blur_backward;
+
+        if (frames_to_blur_backward > frames_to_blur_forward)
+            frames_to_blur_backward = frames_to_blur_forward;
+
+        // When max_frames is even we have 1 more frame backward than forward
+        if (frames_to_blur_forward > (max_frames - 1) / 2)
+            frames_to_blur_forward = ((max_frames - 1) / 2);
+
+        if (frames_to_blur_backward > (max_frames / 2))
+            frames_to_blur_backward = (max_frames / 2);
+
+        frames_to_blur = frames_to_blur_backward + frames_to_blur_forward + 1;
+        break;
+    }
+
+    start_frame = distance + frames_to_blur_forward;
+
+#ifdef DEBUGFWG
+    // DEBUG FWG
+    printf("max:%d FBCK:%d FFWD:%d ftb:%d ftbbck:%d ftbfwd:%d sei:%d lasei:%d start:%d"
+           , max_frames
+           , num_frames_backward
+           , num_frames_forward
+           , frames_to_blur
+           , frames_to_blur_backward
+           , frames_to_blur_forward
+           , cpi->source_encode_index
+           , cpi->last_alt_ref_sei
+           , start_frame);
+#endif
+
+    // Setup frame pointers, NULL indicates frame not included in filter
+    vpx_memset(cpi->frames, 0, max_frames*sizeof(YV12_BUFFER_CONFIG *));
+    for (frame = 0; frame < frames_to_blur; frame++)
+    {
+        int which_buffer =  start_frame - frame;
+        struct lookahead_entry* buf = vp8_lookahead_peek(cpi->lookahead,
+                                                         which_buffer,
+                                                         PEEK_FORWARD);
+        cpi->frames[frames_to_blur-1-frame] = &buf->img;
+    }
+
+    vp8_temporal_filter_iterate_c (
+        cpi,
+        frames_to_blur,
+        frames_to_blur_backward,
+        strength );
+}
+#endif
diff --git a/vp8/encoder/tokenize.c b/vp8/encoder/tokenize.c
new file mode 100644 (file)
index 0000000..ef41fa8
--- /dev/null
@@ -0,0 +1,598 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include "onyx_int.h"
+#include "tokenize.h"
+#include "vpx_mem/vpx_mem.h"
+
+/* Global event counters used for accumulating statistics across several
+   compressions, then generating context.c = initial stats. */
+
+#ifdef ENTROPY_STATS
+_int64 context_counters[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS];
+#endif
+void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) ;
+void vp8_fix_contexts(MACROBLOCKD *x);
+
+#include "dct_value_tokens.h"
+#include "dct_value_cost.h"
+
+const TOKENVALUE *const vp8_dct_value_tokens_ptr = dct_value_tokens +
+        DCT_MAX_VALUE;
+const short *const vp8_dct_value_cost_ptr = dct_value_cost + DCT_MAX_VALUE;
+
+#if 0
+int skip_true_count = 0;
+int skip_false_count = 0;
+#endif
+
+/* function used to generate dct_value_tokens and dct_value_cost tables */
+/*
+static void fill_value_tokens()
+{
+
+    TOKENVALUE *t = dct_value_tokens + DCT_MAX_VALUE;
+    const vp8_extra_bit_struct *e = vp8_extra_bits;
+
+    int i = -DCT_MAX_VALUE;
+    int sign = 1;
+
+    do
+    {
+        if (!i)
+            sign = 0;
+
+        {
+            const int a = sign ? -i : i;
+            int eb = sign;
+
+            if (a > 4)
+            {
+                int j = 4;
+
+                while (++j < 11  &&  e[j].base_val <= a) {}
+
+                t[i].Token = --j;
+                eb |= (a - e[j].base_val) << 1;
+            }
+            else
+                t[i].Token = a;
+
+            t[i].Extra = eb;
+        }
+
+        // initialize the cost for extra bits for all possible coefficient value.
+        {
+            int cost = 0;
+            const vp8_extra_bit_struct *p = vp8_extra_bits + t[i].Token;
+
+            if (p->base_val)
+            {
+                const int extra = t[i].Extra;
+                const int Length = p->Len;
+
+                if (Length)
+                    cost += vp8_treed_cost(p->tree, p->prob, extra >> 1, Length);
+
+                cost += vp8_cost_bit(vp8_prob_half, extra & 1); // sign
+                dct_value_cost[i + DCT_MAX_VALUE] = cost;
+            }
+
+        }
+
+    }
+    while (++i < DCT_MAX_VALUE);
+
+    vp8_dct_value_tokens_ptr = dct_value_tokens + DCT_MAX_VALUE;
+    vp8_dct_value_cost_ptr   = dct_value_cost + DCT_MAX_VALUE;
+}
+*/
+
+static void tokenize2nd_order_b
+(
+    MACROBLOCKD *x,
+    TOKENEXTRA **tp,
+    VP8_COMP *cpi
+)
+{
+    int pt;             /* near block/prev token context index */
+    int c;              /* start at DC */
+    TOKENEXTRA *t = *tp;/* store tokens starting here */
+    const BLOCKD *b;
+    const short *qcoeff_ptr;
+    ENTROPY_CONTEXT * a;
+    ENTROPY_CONTEXT * l;
+    int band, rc, v, token;
+    int eob;
+
+    b = x->block + 24;
+    qcoeff_ptr = b->qcoeff;
+    a = (ENTROPY_CONTEXT *)x->above_context + 8;
+    l = (ENTROPY_CONTEXT *)x->left_context + 8;
+    eob = x->eobs[24];
+    VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+
+    if(!eob)
+    {
+        /* c = band for this case */
+        t->Token = DCT_EOB_TOKEN;
+        t->context_tree = cpi->common.fc.coef_probs [1] [0] [pt];
+        t->skip_eob_node = 0;
+
+        ++cpi->coef_counts       [1] [0] [pt] [DCT_EOB_TOKEN];
+        t++;
+        *tp = t;
+        *a = *l = 0;
+        return;
+    }
+
+    v = qcoeff_ptr[0];
+    t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
+    token    = vp8_dct_value_tokens_ptr[v].Token;
+    t->Token = token;
+
+    t->context_tree = cpi->common.fc.coef_probs [1] [0] [pt];
+    t->skip_eob_node = 0;
+    ++cpi->coef_counts       [1] [0] [pt] [token];
+    pt = vp8_prev_token_class[token];
+    t++;
+    c = 1;
+
+    for (; c < eob; c++)
+    {
+        rc = vp8_default_zig_zag1d[c];
+        band = vp8_coef_bands[c];
+        v = qcoeff_ptr[rc];
+
+        t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
+        token    = vp8_dct_value_tokens_ptr[v].Token;
+
+        t->Token = token;
+        t->context_tree = cpi->common.fc.coef_probs [1] [band] [pt];
+
+        t->skip_eob_node = ((pt == 0));
+
+        ++cpi->coef_counts       [1] [band] [pt] [token];
+
+        pt = vp8_prev_token_class[token];
+        t++;
+    }
+    if (c < 16)
+    {
+        band = vp8_coef_bands[c];
+        t->Token = DCT_EOB_TOKEN;
+        t->context_tree = cpi->common.fc.coef_probs [1] [band] [pt];
+
+        t->skip_eob_node = 0;
+
+        ++cpi->coef_counts       [1] [band] [pt] [DCT_EOB_TOKEN];
+
+        t++;
+    }
+
+    *tp = t;
+    *a = *l = 1;
+
+}
+
+static void tokenize1st_order_b
+(
+    MACROBLOCKD *x,
+    TOKENEXTRA **tp,
+    int type,           /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
+    VP8_COMP *cpi
+)
+{
+    unsigned int block;
+    const BLOCKD *b;
+    int pt;             /* near block/prev token context index */
+    int c;
+    int token;
+    TOKENEXTRA *t = *tp;/* store tokens starting here */
+    const short *qcoeff_ptr;
+    ENTROPY_CONTEXT * a;
+    ENTROPY_CONTEXT * l;
+    int band, rc, v;
+    int tmp1, tmp2;
+
+    b = x->block;
+    /* Luma */
+    for (block = 0; block < 16; block++, b++)
+    {
+        tmp1 = vp8_block2above[block];
+        tmp2 = vp8_block2left[block];
+        qcoeff_ptr = b->qcoeff;
+        a = (ENTROPY_CONTEXT *)x->above_context + tmp1;
+        l = (ENTROPY_CONTEXT *)x->left_context + tmp2;
+
+        VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+
+        c = type ? 0 : 1;
+
+        if(c >= *b->eob)
+        {
+            /* c = band for this case */
+            t->Token = DCT_EOB_TOKEN;
+            t->context_tree = cpi->common.fc.coef_probs [type] [c] [pt];
+            t->skip_eob_node = 0;
+
+            ++cpi->coef_counts       [type] [c] [pt] [DCT_EOB_TOKEN];
+            t++;
+            *tp = t;
+            *a = *l = 0;
+            continue;
+        }
+
+        v = qcoeff_ptr[c];
+
+        t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
+        token    = vp8_dct_value_tokens_ptr[v].Token;
+        t->Token = token;
+
+        t->context_tree = cpi->common.fc.coef_probs [type] [c] [pt];
+        t->skip_eob_node = 0;
+        ++cpi->coef_counts       [type] [c] [pt] [token];
+        pt = vp8_prev_token_class[token];
+        t++;
+        c++;
+
+        for (; c < *b->eob; c++)
+        {
+            rc = vp8_default_zig_zag1d[c];
+            band = vp8_coef_bands[c];
+            v = qcoeff_ptr[rc];
+
+            t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
+            token    = vp8_dct_value_tokens_ptr[v].Token;
+
+            t->Token = token;
+            t->context_tree = cpi->common.fc.coef_probs [type] [band] [pt];
+
+            t->skip_eob_node = (pt == 0);
+            ++cpi->coef_counts       [type] [band] [pt] [token];
+
+            pt = vp8_prev_token_class[token];
+            t++;
+        }
+        if (c < 16)
+        {
+            band = vp8_coef_bands[c];
+            t->Token = DCT_EOB_TOKEN;
+            t->context_tree = cpi->common.fc.coef_probs [type] [band] [pt];
+
+            t->skip_eob_node = 0;
+            ++cpi->coef_counts       [type] [band] [pt] [DCT_EOB_TOKEN];
+
+            t++;
+        }
+        *tp = t;
+        *a = *l = 1;
+    }
+
+    /* Chroma */
+    for (block = 16; block < 24; block++, b++)
+    {
+        tmp1 = vp8_block2above[block];
+        tmp2 = vp8_block2left[block];
+        qcoeff_ptr = b->qcoeff;
+        a = (ENTROPY_CONTEXT *)x->above_context + tmp1;
+        l = (ENTROPY_CONTEXT *)x->left_context + tmp2;
+
+        VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+
+        if(!(*b->eob))
+        {
+            /* c = band for this case */
+            t->Token = DCT_EOB_TOKEN;
+            t->context_tree = cpi->common.fc.coef_probs [2] [0] [pt];
+            t->skip_eob_node = 0;
+
+            ++cpi->coef_counts       [2] [0] [pt] [DCT_EOB_TOKEN];
+            t++;
+            *tp = t;
+            *a = *l = 0;
+            continue;
+        }
+
+        v = qcoeff_ptr[0];
+
+        t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
+        token    = vp8_dct_value_tokens_ptr[v].Token;
+        t->Token = token;
+
+        t->context_tree = cpi->common.fc.coef_probs [2] [0] [pt];
+        t->skip_eob_node = 0;
+        ++cpi->coef_counts       [2] [0] [pt] [token];
+        pt = vp8_prev_token_class[token];
+        t++;
+        c = 1;
+
+        for (; c < *b->eob; c++)
+        {
+            rc = vp8_default_zig_zag1d[c];
+            band = vp8_coef_bands[c];
+            v = qcoeff_ptr[rc];
+
+            t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
+            token    = vp8_dct_value_tokens_ptr[v].Token;
+
+            t->Token = token;
+            t->context_tree = cpi->common.fc.coef_probs [2] [band] [pt];
+
+            t->skip_eob_node = (pt == 0);
+
+            ++cpi->coef_counts       [2] [band] [pt] [token];
+
+            pt = vp8_prev_token_class[token];
+            t++;
+        }
+        if (c < 16)
+        {
+            band = vp8_coef_bands[c];
+            t->Token = DCT_EOB_TOKEN;
+            t->context_tree = cpi->common.fc.coef_probs [2] [band] [pt];
+
+            t->skip_eob_node = 0;
+
+            ++cpi->coef_counts       [2] [band] [pt] [DCT_EOB_TOKEN];
+
+            t++;
+        }
+        *tp = t;
+        *a = *l = 1;
+    }
+}
+
+
+static int mb_is_skippable(MACROBLOCKD *x, int has_y2_block)
+{
+    int skip = 1;
+    int i = 0;
+
+    if (has_y2_block)
+    {
+        for (i = 0; i < 16; i++)
+            skip &= (x->eobs[i] < 2);
+    }
+
+    for (; i < 24 + has_y2_block; i++)
+        skip &= (!x->eobs[i]);
+
+    return skip;
+}
+
+
+void vp8_tokenize_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t)
+{
+    int plane_type;
+    int has_y2_block;
+
+    has_y2_block = (x->mode_info_context->mbmi.mode != B_PRED
+                    && x->mode_info_context->mbmi.mode != SPLITMV);
+
+    x->mode_info_context->mbmi.mb_skip_coeff = mb_is_skippable(x, has_y2_block);
+    if (x->mode_info_context->mbmi.mb_skip_coeff)
+    {
+        if (!cpi->common.mb_no_coeff_skip)
+        {
+            vp8_stuff_mb(cpi, x, t);
+        }
+        else
+        {
+            vp8_fix_contexts(x);
+            cpi->skip_true_count++;
+        }
+
+        return;
+    }
+
+    plane_type = 3;
+    if(has_y2_block)
+    {
+        tokenize2nd_order_b(x, t, cpi);
+        plane_type = 0;
+    }
+
+    tokenize1st_order_b(x, t, plane_type, cpi);
+}
+
+
+#ifdef ENTROPY_STATS
+
+void init_context_counters(void)
+{
+    vpx_memset(context_counters, 0, sizeof(context_counters));
+}
+
+void print_context_counters()
+{
+
+    int type, band, pt, t;
+
+    FILE *const f = fopen("context.c", "w");
+
+    fprintf(f, "#include \"entropy.h\"\n");
+
+    fprintf(f, "\n/* *** GENERATED FILE: DO NOT EDIT *** */\n\n");
+
+    fprintf(f, "int Contexts[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS];\n\n");
+
+    fprintf(f, "const int default_contexts[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS] = {");
+
+# define Comma( X) (X? ",":"")
+
+    type = 0;
+
+    do
+    {
+        fprintf(f, "%s\n  { /* block Type %d */", Comma(type), type);
+
+        band = 0;
+
+        do
+        {
+            fprintf(f, "%s\n    { /* Coeff Band %d */", Comma(band), band);
+
+            pt = 0;
+
+            do
+            {
+                fprintf(f, "%s\n      {", Comma(pt));
+
+                t = 0;
+
+                do
+                {
+                    const _int64 x = context_counters [type] [band] [pt] [t];
+                    const int y = (int) x;
+
+                    assert(x == (_int64) y);  /* no overflow handling yet */
+                    fprintf(f, "%s %d", Comma(t), y);
+
+                }
+                while (++t < MAX_ENTROPY_TOKENS);
+
+                fprintf(f, "}");
+            }
+            while (++pt < PREV_COEF_CONTEXTS);
+
+            fprintf(f, "\n    }");
+
+        }
+        while (++band < COEF_BANDS);
+
+        fprintf(f, "\n  }");
+    }
+    while (++type < BLOCK_TYPES);
+
+    fprintf(f, "\n};\n");
+    fclose(f);
+}
+#endif
+
+
+static void stuff2nd_order_b
+(
+    TOKENEXTRA **tp,
+    ENTROPY_CONTEXT *a,
+    ENTROPY_CONTEXT *l,
+    VP8_COMP *cpi
+)
+{
+    int pt; /* near block/prev token context index */
+    TOKENEXTRA *t = *tp;        /* store tokens starting here */
+    VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+
+    t->Token = DCT_EOB_TOKEN;
+    t->context_tree = cpi->common.fc.coef_probs [1] [0] [pt];
+    t->skip_eob_node = 0;
+    ++cpi->coef_counts       [1] [0] [pt] [DCT_EOB_TOKEN];
+    ++t;
+
+    *tp = t;
+    pt = 0;
+    *a = *l = pt;
+
+}
+
+static void stuff1st_order_b
+(
+    TOKENEXTRA **tp,
+    ENTROPY_CONTEXT *a,
+    ENTROPY_CONTEXT *l,
+    int type,
+    VP8_COMP *cpi
+)
+{
+    int pt; /* near block/prev token context index */
+    int band;
+    TOKENEXTRA *t = *tp;        /* store tokens starting here */
+    VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+    band = type ? 0 : 1;
+    t->Token = DCT_EOB_TOKEN;
+    t->context_tree = cpi->common.fc.coef_probs [type] [band] [pt];
+    t->skip_eob_node = 0;
+    ++cpi->coef_counts       [type] [band] [pt] [DCT_EOB_TOKEN];
+    ++t;
+    *tp = t;
+    pt = 0; /* 0 <-> all coeff data is zero */
+    *a = *l = pt;
+
+}
+static
+void stuff1st_order_buv
+(
+    TOKENEXTRA **tp,
+    ENTROPY_CONTEXT *a,
+    ENTROPY_CONTEXT *l,
+    VP8_COMP *cpi
+)
+{
+    int pt; /* near block/prev token context index */
+    TOKENEXTRA *t = *tp;        /* store tokens starting here */
+    VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+
+    t->Token = DCT_EOB_TOKEN;
+    t->context_tree = cpi->common.fc.coef_probs [2] [0] [pt];
+    t->skip_eob_node = 0;
+    ++cpi->coef_counts[2] [0] [pt] [DCT_EOB_TOKEN];
+    ++t;
+    *tp = t;
+    pt = 0; /* 0 <-> all coeff data is zero */
+    *a = *l = pt;
+
+}
+
+void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t)
+{
+    ENTROPY_CONTEXT * A = (ENTROPY_CONTEXT *)x->above_context;
+    ENTROPY_CONTEXT * L = (ENTROPY_CONTEXT *)x->left_context;
+    int plane_type;
+    int b;
+    plane_type = 3;
+    if((x->mode_info_context->mbmi.mode != B_PRED
+                        && x->mode_info_context->mbmi.mode != SPLITMV))
+    {
+        stuff2nd_order_b(t,
+                     A + vp8_block2above[24], L + vp8_block2left[24], cpi);
+        plane_type = 0;
+    }
+
+    for (b = 0; b < 16; b++)
+        stuff1st_order_b(t,
+                         A + vp8_block2above[b],
+                         L + vp8_block2left[b], plane_type, cpi);
+
+    for (b = 16; b < 24; b++)
+        stuff1st_order_buv(t,
+                           A + vp8_block2above[b],
+                           L + vp8_block2left[b], cpi);
+
+}
+void vp8_fix_contexts(MACROBLOCKD *x)
+{
+    /* Clear entropy contexts for Y2 blocks */
+    if (x->mode_info_context->mbmi.mode != B_PRED && x->mode_info_context->mbmi.mode != SPLITMV)
+    {
+        vpx_memset(x->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES));
+        vpx_memset(x->left_context, 0, sizeof(ENTROPY_CONTEXT_PLANES));
+    }
+    else
+    {
+        vpx_memset(x->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES)-1);
+        vpx_memset(x->left_context, 0, sizeof(ENTROPY_CONTEXT_PLANES)-1);
+    }
+
+}
diff --git a/vp8/encoder/tokenize.h b/vp8/encoder/tokenize.h
new file mode 100644 (file)
index 0000000..c2d1438
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef tokenize_h
+#define tokenize_h
+
+#include "vp8/common/entropy.h"
+#include "block.h"
+
+void vp8_tokenize_initialize();
+
+typedef struct
+{
+    short Token;
+    short Extra;
+} TOKENVALUE;
+
+typedef struct
+{
+    const vp8_prob *context_tree;
+    short           Extra;
+    unsigned char   Token;
+    unsigned char   skip_eob_node;
+} TOKENEXTRA;
+
+int rd_cost_mby(MACROBLOCKD *);
+
+#ifdef ENTROPY_STATS
+void init_context_counters();
+void print_context_counters();
+
+extern _int64 context_counters[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS];
+#endif
+
+extern const short *const vp8_dct_value_cost_ptr;
+/* TODO: The Token field should be broken out into a separate char array to
+ *  improve cache locality, since it's needed for costing when the rest of the
+ *  fields are not.
+ */
+extern const TOKENVALUE *const vp8_dct_value_tokens_ptr;
+
+#endif  /* tokenize_h */
diff --git a/vp8/encoder/treewriter.c b/vp8/encoder/treewriter.c
new file mode 100644 (file)
index 0000000..ef25f67
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "treewriter.h"
+
+static void cost(
+    int *const C,
+    vp8_tree T,
+    const vp8_prob *const P,
+    int i,
+    int c
+)
+{
+    const vp8_prob p = P [i>>1];
+
+    do
+    {
+        const vp8_tree_index j = T[i];
+        const int d = c + vp8_cost_bit(p, i & 1);
+
+        if (j <= 0)
+            C[-j] = d;
+        else
+            cost(C, T, P, j, d);
+    }
+    while (++i & 1);
+}
+void vp8_cost_tokens(int *c, const vp8_prob *p, vp8_tree t)
+{
+    cost(c, t, p, 0, 0);
+}
+void vp8_cost_tokens2(int *c, const vp8_prob *p, vp8_tree t,int start)
+{
+    cost(c, t, p, start, 0);
+}
diff --git a/vp8/encoder/treewriter.h b/vp8/encoder/treewriter.h
new file mode 100644 (file)
index 0000000..48574f3
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __INC_TREEWRITER_H
+#define __INC_TREEWRITER_H
+
+/* Trees map alphabets into huffman-like codes suitable for an arithmetic
+   bit coder.  Timothy S Murphy  11 October 2004 */
+
+#include "vp8/common/treecoder.h"
+
+#include "boolhuff.h"       /* for now */
+
+typedef BOOL_CODER vp8_writer;
+
+#define vp8_write vp8_encode_bool
+#define vp8_write_literal vp8_encode_value
+#define vp8_write_bit( W, V) vp8_write( W, V, vp8_prob_half)
+
+#define vp8bc_write vp8bc_write_bool
+#define vp8bc_write_literal vp8bc_write_bits
+#define vp8bc_write_bit( W, V) vp8bc_write_bits( W, V, 1)
+
+
+/* Approximate length of an encoded bool in 256ths of a bit at given prob */
+
+#define vp8_cost_zero( x) ( vp8_prob_cost[x])
+#define vp8_cost_one( x)  vp8_cost_zero( vp8_complement(x))
+
+#define vp8_cost_bit( x, b) vp8_cost_zero( (b)?  vp8_complement(x) : (x) )
+
+/* VP8BC version is scaled by 2^20 rather than 2^8; see bool_coder.h */
+
+
+/* Both of these return bits, not scaled bits. */
+
+static unsigned int vp8_cost_branch(const unsigned int ct[2], vp8_prob p)
+{
+    /* Imitate existing calculation */
+
+    return ((ct[0] * vp8_cost_zero(p))
+            + (ct[1] * vp8_cost_one(p))) >> 8;
+}
+
+/* Small functions to write explicit values and tokens, as well as
+   estimate their lengths. */
+
+static void vp8_treed_write
+(
+    vp8_writer *const w,
+    vp8_tree t,
+    const vp8_prob *const p,
+    int v,
+    int n               /* number of bits in v, assumed nonzero */
+)
+{
+    vp8_tree_index i = 0;
+
+    do
+    {
+        const int b = (v >> --n) & 1;
+        vp8_write(w, b, p[i>>1]);
+        i = t[i+b];
+    }
+    while (n);
+}
+static void vp8_write_token
+(
+    vp8_writer *const w,
+    vp8_tree t,
+    const vp8_prob *const p,
+    vp8_token *const x
+)
+{
+    vp8_treed_write(w, t, p, x->value, x->Len);
+}
+
+static int vp8_treed_cost(
+    vp8_tree t,
+    const vp8_prob *const p,
+    int v,
+    int n               /* number of bits in v, assumed nonzero */
+)
+{
+    int c = 0;
+    vp8_tree_index i = 0;
+
+    do
+    {
+        const int b = (v >> --n) & 1;
+        c += vp8_cost_bit(p[i>>1], b);
+        i = t[i+b];
+    }
+    while (n);
+
+    return c;
+}
+static int vp8_cost_token
+(
+    vp8_tree t,
+    const vp8_prob *const p,
+    vp8_token *const x
+)
+{
+    return vp8_treed_cost(t, p, x->value, x->Len);
+}
+
+/* Fill array of costs for all possible token values. */
+
+void vp8_cost_tokens(
+    int *Costs, const vp8_prob *, vp8_tree
+);
+
+void vp8_cost_tokens2(
+    int *Costs, const vp8_prob *, vp8_tree, int
+);
+
+#endif
diff --git a/vp8/encoder/x86/dct_mmx.asm b/vp8/encoder/x86/dct_mmx.asm
new file mode 100644 (file)
index 0000000..f07b030
--- /dev/null
@@ -0,0 +1,241 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;void vp8_short_fdct4x4_mmx(short *input, short *output, int pitch)
+global sym(vp8_short_fdct4x4_mmx)
+sym(vp8_short_fdct4x4_mmx):
+    push        rbp
+    mov         rbp,        rsp
+    SHADOW_ARGS_TO_STACK 3
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rsi,        arg(0)      ; input
+        mov         rdi,        arg(1)      ; output
+
+        movsxd      rax,        dword ptr arg(2) ;pitch
+
+        lea         rcx,        [rsi + rax*2]
+        ; read the input data
+        movq        mm0,        [rsi]
+        movq        mm1,        [rsi + rax]
+
+        movq        mm2,        [rcx]
+        movq        mm4,        [rcx + rax]
+
+        ; transpose for the first stage
+        movq        mm3,        mm0         ; 00 01 02 03
+        movq        mm5,        mm2         ; 20 21 22 23
+
+        punpcklwd   mm0,        mm1         ; 00 10 01 11
+        punpckhwd   mm3,        mm1         ; 02 12 03 13
+
+        punpcklwd   mm2,        mm4         ; 20 30 21 31
+        punpckhwd   mm5,        mm4         ; 22 32 23 33
+
+        movq        mm1,        mm0         ; 00 10 01 11
+        punpckldq   mm0,        mm2         ; 00 10 20 30
+
+        punpckhdq   mm1,        mm2         ; 01 11 21 31
+
+        movq        mm2,        mm3         ; 02 12 03 13
+        punpckldq   mm2,        mm5         ; 02 12 22 32
+
+        punpckhdq   mm3,        mm5         ; 03 13 23 33
+
+        ; mm0 0
+        ; mm1 1
+        ; mm2 2
+        ; mm3 3
+
+        ; first stage
+        movq        mm5,        mm0
+        movq        mm4,        mm1
+
+        paddw       mm0,        mm3         ; a1 = 0 + 3
+        paddw       mm1,        mm2         ; b1 = 1 + 2
+
+        psubw       mm4,        mm2         ; c1 = 1 - 2
+        psubw       mm5,        mm3         ; d1 = 0 - 3
+
+        psllw       mm5,        3
+        psllw       mm4,        3
+
+        psllw       mm0,        3
+        psllw       mm1,        3
+
+        ; output 0 and 2
+        movq        mm2,        mm0         ; a1
+
+        paddw       mm0,        mm1         ; op[0] = a1 + b1
+        psubw       mm2,        mm1         ; op[2] = a1 - b1
+
+        ; output 1 and 3
+        ; interleave c1, d1
+        movq        mm1,        mm5         ; d1
+        punpcklwd   mm1,        mm4         ; c1 d1
+        punpckhwd   mm5,        mm4         ; c1 d1
+
+        movq        mm3,        mm1
+        movq        mm4,        mm5
+
+        pmaddwd     mm1,        MMWORD PTR[GLOBAL (_5352_2217)]    ; c1*2217 + d1*5352
+        pmaddwd     mm4,        MMWORD PTR[GLOBAL (_5352_2217)]    ; c1*2217 + d1*5352
+
+        pmaddwd     mm3,        MMWORD PTR[GLOBAL(_2217_neg5352)]  ; d1*2217 - c1*5352
+        pmaddwd     mm5,        MMWORD PTR[GLOBAL(_2217_neg5352)]  ; d1*2217 - c1*5352
+
+        paddd       mm1,        MMWORD PTR[GLOBAL(_14500)]
+        paddd       mm4,        MMWORD PTR[GLOBAL(_14500)]
+        paddd       mm3,        MMWORD PTR[GLOBAL(_7500)]
+        paddd       mm5,        MMWORD PTR[GLOBAL(_7500)]
+
+        psrad       mm1,        12          ; (c1 * 2217 + d1 * 5352 +  14500)>>12
+        psrad       mm4,        12          ; (c1 * 2217 + d1 * 5352 +  14500)>>12
+        psrad       mm3,        12          ; (d1 * 2217 - c1 * 5352 +   7500)>>12
+        psrad       mm5,        12          ; (d1 * 2217 - c1 * 5352 +   7500)>>12
+
+        packssdw    mm1,        mm4         ; op[1]
+        packssdw    mm3,        mm5         ; op[3]
+
+        ; done with vertical
+        ; transpose for the second stage
+        movq        mm4,        mm0         ; 00 10 20 30
+        movq        mm5,        mm2         ; 02 12 22 32
+
+        punpcklwd   mm0,        mm1         ; 00 01 10 11
+        punpckhwd   mm4,        mm1         ; 20 21 30 31
+
+        punpcklwd   mm2,        mm3         ; 02 03 12 13
+        punpckhwd   mm5,        mm3         ; 22 23 32 33
+
+        movq        mm1,        mm0         ; 00 01 10 11
+        punpckldq   mm0,        mm2         ; 00 01 02 03
+
+        punpckhdq   mm1,        mm2         ; 01 22 12 13
+
+        movq        mm2,        mm4         ; 20 31 30 31
+        punpckldq   mm2,        mm5         ; 20 21 22 23
+
+        punpckhdq   mm4,        mm5         ; 30 31 32 33
+
+        ; mm0 0
+        ; mm1 1
+        ; mm2 2
+        ; mm3 4
+
+        movq        mm5,        mm0
+        movq        mm3,        mm1
+
+        paddw       mm0,        mm4         ; a1 = 0 + 3
+        paddw       mm1,        mm2         ; b1 = 1 + 2
+
+        psubw       mm3,        mm2         ; c1 = 1 - 2
+        psubw       mm5,        mm4         ; d1 = 0 - 3
+
+        pxor        mm6,        mm6         ; zero out for compare
+
+        pcmpeqw     mm6,        mm5         ; d1 != 0
+
+        pandn       mm6,        MMWORD PTR[GLOBAL(_cmp_mask)]   ; clear upper,
+                                                                ; and keep bit 0 of lower
+
+        ; output 0 and 2
+        movq        mm2,        mm0         ; a1
+
+        paddw       mm0,        mm1         ; a1 + b1
+        psubw       mm2,        mm1         ; a1 - b1
+
+        paddw       mm0,        MMWORD PTR[GLOBAL(_7w)]
+        paddw       mm2,        MMWORD PTR[GLOBAL(_7w)]
+
+        psraw       mm0,        4           ; op[0] = (a1 + b1 + 7)>>4
+        psraw       mm2,        4           ; op[8] = (a1 - b1 + 7)>>4
+
+        movq        MMWORD PTR[rdi + 0 ],  mm0
+        movq        MMWORD PTR[rdi + 16],  mm2
+
+        ; output 1 and 3
+        ; interleave c1, d1
+        movq        mm1,        mm5         ; d1
+        punpcklwd   mm1,        mm3         ; c1 d1
+        punpckhwd   mm5,        mm3         ; c1 d1
+
+        movq        mm3,        mm1
+        movq        mm4,        mm5
+
+        pmaddwd     mm1,        MMWORD PTR[GLOBAL (_5352_2217)]    ; c1*2217 + d1*5352
+        pmaddwd     mm4,        MMWORD PTR[GLOBAL (_5352_2217)]    ; c1*2217 + d1*5352
+
+        pmaddwd     mm3,        MMWORD PTR[GLOBAL(_2217_neg5352)]  ; d1*2217 - c1*5352
+        pmaddwd     mm5,        MMWORD PTR[GLOBAL(_2217_neg5352)]  ; d1*2217 - c1*5352
+
+        paddd       mm1,        MMWORD PTR[GLOBAL(_12000)]
+        paddd       mm4,        MMWORD PTR[GLOBAL(_12000)]
+        paddd       mm3,        MMWORD PTR[GLOBAL(_51000)]
+        paddd       mm5,        MMWORD PTR[GLOBAL(_51000)]
+
+        psrad       mm1,        16          ; (c1 * 2217 + d1 * 5352 +  14500)>>16
+        psrad       mm4,        16          ; (c1 * 2217 + d1 * 5352 +  14500)>>16
+        psrad       mm3,        16          ; (d1 * 2217 - c1 * 5352 +   7500)>>16
+        psrad       mm5,        16          ; (d1 * 2217 - c1 * 5352 +   7500)>>16
+
+        packssdw    mm1,        mm4         ; op[4]
+        packssdw    mm3,        mm5         ; op[12]
+
+        paddw       mm1,        mm6         ; op[4] += (d1!=0)
+
+        movq        MMWORD PTR[rdi + 8 ],  mm1
+        movq        MMWORD PTR[rdi + 24],  mm3
+
+     ; begin epilog
+    pop         rdi
+    pop         rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+SECTION_RODATA
+align 8
+_5352_2217:
+    dw 5352
+    dw 2217
+    dw 5352
+    dw 2217
+align 8
+_2217_neg5352:
+    dw 2217
+    dw -5352
+    dw 2217
+    dw -5352
+align 8
+_cmp_mask:
+    times 4 dw 1
+align 8
+_7w:
+    times 4 dw 7
+align 8
+_14500:
+    times 2 dd 14500
+align 8
+_7500:
+    times 2 dd 7500
+align 8
+_12000:
+    times 2 dd 12000
+align 8
+_51000:
+    times 2 dd 51000
diff --git a/vp8/encoder/x86/dct_sse2.asm b/vp8/encoder/x86/dct_sse2.asm
new file mode 100644 (file)
index 0000000..3d52a5d
--- /dev/null
@@ -0,0 +1,432 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+%macro STACK_FRAME_CREATE 0
+%if ABI_IS_32BIT
+  %define       input       rsi
+  %define       output      rdi
+  %define       pitch       rax
+    push        rbp
+    mov         rbp, rsp
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    mov         rsi, arg(0)
+    mov         rdi, arg(1)
+
+    movsxd      rax, dword ptr arg(2)
+    lea         rcx, [rsi + rax*2]
+%else
+  %ifidn __OUTPUT_FORMAT__,x64
+    %define     input       rcx
+    %define     output      rdx
+    %define     pitch       r8
+    SAVE_XMM 7, u
+  %else
+    %define     input       rdi
+    %define     output      rsi
+    %define     pitch       rdx
+  %endif
+%endif
+%endmacro
+
+%macro STACK_FRAME_DESTROY 0
+  %define     input
+  %define     output
+  %define     pitch
+
+%if ABI_IS_32BIT
+    pop         rdi
+    pop         rsi
+    RESTORE_GOT
+    pop         rbp
+%else
+  %ifidn __OUTPUT_FORMAT__,x64
+    RESTORE_XMM
+  %endif
+%endif
+    ret
+%endmacro
+
+;void vp8_short_fdct4x4_sse2(short *input, short *output, int pitch)
+global sym(vp8_short_fdct4x4_sse2)
+sym(vp8_short_fdct4x4_sse2):
+
+    STACK_FRAME_CREATE
+
+    movq        xmm0, MMWORD PTR[input        ] ;03 02 01 00
+    movq        xmm2, MMWORD PTR[input+  pitch] ;13 12 11 10
+    lea         input,          [input+2*pitch]
+    movq        xmm1, MMWORD PTR[input        ] ;23 22 21 20
+    movq        xmm3, MMWORD PTR[input+  pitch] ;33 32 31 30
+
+    punpcklqdq  xmm0, xmm2                      ;13 12 11 10 03 02 01 00
+    punpcklqdq  xmm1, xmm3                      ;33 32 31 30 23 22 21 20
+
+    movdqa      xmm2, xmm0
+    punpckldq   xmm0, xmm1                      ;23 22 03 02 21 20 01 00
+    punpckhdq   xmm2, xmm1                      ;33 32 13 12 31 30 11 10
+    movdqa      xmm1, xmm0
+    punpckldq   xmm0, xmm2                      ;31 21 30 20 11 10 01 00
+    pshufhw     xmm1, xmm1, 0b1h                ;22 23 02 03 xx xx xx xx
+    pshufhw     xmm2, xmm2, 0b1h                ;32 33 12 13 xx xx xx xx
+
+    punpckhdq   xmm1, xmm2                      ;32 33 22 23 12 13 02 03
+    movdqa      xmm3, xmm0
+    paddw       xmm0, xmm1                      ;b1 a1 b1 a1 b1 a1 b1 a1
+    psubw       xmm3, xmm1                      ;c1 d1 c1 d1 c1 d1 c1 d1
+    psllw       xmm0, 3                         ;b1 <<= 3 a1 <<= 3
+    psllw       xmm3, 3                         ;c1 <<= 3 d1 <<= 3
+
+    movdqa      xmm1, xmm0
+    pmaddwd     xmm0, XMMWORD PTR[GLOBAL(_mult_add)]    ;a1 + b1
+    pmaddwd     xmm1, XMMWORD PTR[GLOBAL(_mult_sub)]    ;a1 - b1
+    movdqa      xmm4, xmm3
+    pmaddwd     xmm3, XMMWORD PTR[GLOBAL(_5352_2217)]   ;c1*2217 + d1*5352
+    pmaddwd     xmm4, XMMWORD PTR[GLOBAL(_2217_neg5352)];d1*2217 - c1*5352
+
+    paddd       xmm3, XMMWORD PTR[GLOBAL(_14500)]
+    paddd       xmm4, XMMWORD PTR[GLOBAL(_7500)]
+    psrad       xmm3, 12            ;(c1 * 2217 + d1 * 5352 +  14500)>>12
+    psrad       xmm4, 12            ;(d1 * 2217 - c1 * 5352 +   7500)>>12
+
+    packssdw    xmm0, xmm1                      ;op[2] op[0]
+    packssdw    xmm3, xmm4                      ;op[3] op[1]
+    ; 23 22 21 20 03 02 01 00
+    ;
+    ; 33 32 31 30 13 12 11 10
+    ;
+    movdqa      xmm2, xmm0
+    punpcklqdq  xmm0, xmm3                      ;13 12 11 10 03 02 01 00
+    punpckhqdq  xmm2, xmm3                      ;23 22 21 20 33 32 31 30
+
+    movdqa      xmm3, xmm0
+    punpcklwd   xmm0, xmm2                      ;32 30 22 20 12 10 02 00
+    punpckhwd   xmm3, xmm2                      ;33 31 23 21 13 11 03 01
+    movdqa      xmm2, xmm0
+    punpcklwd   xmm0, xmm3                      ;13 12 11 10 03 02 01 00
+    punpckhwd   xmm2, xmm3                      ;33 32 31 30 23 22 21 20
+
+    movdqa      xmm5, XMMWORD PTR[GLOBAL(_7)]
+    pshufd      xmm2, xmm2, 04eh
+    movdqa      xmm3, xmm0
+    paddw       xmm0, xmm2                      ;b1 b1 b1 b1 a1 a1 a1 a1
+    psubw       xmm3, xmm2                      ;c1 c1 c1 c1 d1 d1 d1 d1
+
+    pshufd      xmm0, xmm0, 0d8h                ;b1 b1 a1 a1 b1 b1 a1 a1
+    movdqa      xmm2, xmm3                      ;save d1 for compare
+    pshufd      xmm3, xmm3, 0d8h                ;c1 c1 d1 d1 c1 c1 d1 d1
+    pshuflw     xmm0, xmm0, 0d8h                ;b1 b1 a1 a1 b1 a1 b1 a1
+    pshuflw     xmm3, xmm3, 0d8h                ;c1 c1 d1 d1 c1 d1 c1 d1
+    pshufhw     xmm0, xmm0, 0d8h                ;b1 a1 b1 a1 b1 a1 b1 a1
+    pshufhw     xmm3, xmm3, 0d8h                ;c1 d1 c1 d1 c1 d1 c1 d1
+    movdqa      xmm1, xmm0
+    pmaddwd     xmm0, XMMWORD PTR[GLOBAL(_mult_add)] ;a1 + b1
+    pmaddwd     xmm1, XMMWORD PTR[GLOBAL(_mult_sub)] ;a1 - b1
+
+    pxor        xmm4, xmm4                      ;zero out for compare
+    paddd       xmm0, xmm5
+    paddd       xmm1, xmm5
+    pcmpeqw     xmm2, xmm4
+    psrad       xmm0, 4                         ;(a1 + b1 + 7)>>4
+    psrad       xmm1, 4                         ;(a1 - b1 + 7)>>4
+    pandn       xmm2, XMMWORD PTR[GLOBAL(_cmp_mask)] ;clear upper,
+                                                     ;and keep bit 0 of lower
+
+    movdqa      xmm4, xmm3
+    pmaddwd     xmm3, XMMWORD PTR[GLOBAL(_5352_2217)]    ;c1*2217 + d1*5352
+    pmaddwd     xmm4, XMMWORD PTR[GLOBAL(_2217_neg5352)] ;d1*2217 - c1*5352
+    paddd       xmm3, XMMWORD PTR[GLOBAL(_12000)]
+    paddd       xmm4, XMMWORD PTR[GLOBAL(_51000)]
+    packssdw    xmm0, xmm1                      ;op[8] op[0]
+    psrad       xmm3, 16                ;(c1 * 2217 + d1 * 5352 +  12000)>>16
+    psrad       xmm4, 16                ;(d1 * 2217 - c1 * 5352 +  51000)>>16
+
+    packssdw    xmm3, xmm4                      ;op[12] op[4]
+    movdqa      xmm1, xmm0
+    paddw       xmm3, xmm2                      ;op[4] += (d1!=0)
+    punpcklqdq  xmm0, xmm3                      ;op[4] op[0]
+    punpckhqdq  xmm1, xmm3                      ;op[12] op[8]
+
+    movdqa      XMMWORD PTR[output +  0], xmm0
+    movdqa      XMMWORD PTR[output + 16], xmm1
+
+    STACK_FRAME_DESTROY
+
+;void vp8_short_fdct8x4_sse2(short *input, short *output, int pitch)
+global sym(vp8_short_fdct8x4_sse2)
+sym(vp8_short_fdct8x4_sse2):
+
+    STACK_FRAME_CREATE
+
+        ; read the input data
+        movdqa      xmm0,       [input        ]
+        movdqa      xmm2,       [input+  pitch]
+        lea         input,      [input+2*pitch]
+        movdqa      xmm4,       [input        ]
+        movdqa      xmm3,       [input+  pitch]
+
+        ; transpose for the first stage
+        movdqa      xmm1,       xmm0        ; 00 01 02 03 04 05 06 07
+        movdqa      xmm5,       xmm4        ; 20 21 22 23 24 25 26 27
+
+        punpcklwd   xmm0,       xmm2        ; 00 10 01 11 02 12 03 13
+        punpckhwd   xmm1,       xmm2        ; 04 14 05 15 06 16 07 17
+
+        punpcklwd   xmm4,       xmm3        ; 20 30 21 31 22 32 23 33
+        punpckhwd   xmm5,       xmm3        ; 24 34 25 35 26 36 27 37
+
+        movdqa      xmm2,       xmm0        ; 00 10 01 11 02 12 03 13
+        punpckldq   xmm0,       xmm4        ; 00 10 20 30 01 11 21 31
+
+        punpckhdq   xmm2,       xmm4        ; 02 12 22 32 03 13 23 33
+
+        movdqa      xmm4,       xmm1        ; 04 14 05 15 06 16 07 17
+        punpckldq   xmm4,       xmm5        ; 04 14 24 34 05 15 25 35
+
+        punpckhdq   xmm1,       xmm5        ; 06 16 26 36 07 17 27 37
+        movdqa      xmm3,       xmm2        ; 02 12 22 32 03 13 23 33
+
+        punpckhqdq  xmm3,       xmm1        ; 03 13 23 33 07 17 27 37
+        punpcklqdq  xmm2,       xmm1        ; 02 12 22 32 06 16 26 36
+
+        movdqa      xmm1,       xmm0        ; 00 10 20 30 01 11 21 31
+        punpcklqdq  xmm0,       xmm4        ; 00 10 20 30 04 14 24 34
+
+        punpckhqdq  xmm1,       xmm4        ; 01 11 21 32 05 15 25 35
+
+        ; xmm0 0
+        ; xmm1 1
+        ; xmm2 2
+        ; xmm3 3
+
+        ; first stage
+        movdqa      xmm5,       xmm0
+        movdqa      xmm4,       xmm1
+
+        paddw       xmm0,       xmm3        ; a1 = 0 + 3
+        paddw       xmm1,       xmm2        ; b1 = 1 + 2
+
+        psubw       xmm4,       xmm2        ; c1 = 1 - 2
+        psubw       xmm5,       xmm3        ; d1 = 0 - 3
+
+        psllw       xmm5,        3
+        psllw       xmm4,        3
+
+        psllw       xmm0,        3
+        psllw       xmm1,        3
+
+        ; output 0 and 2
+        movdqa      xmm2,       xmm0        ; a1
+
+        paddw       xmm0,       xmm1        ; op[0] = a1 + b1
+        psubw       xmm2,       xmm1        ; op[2] = a1 - b1
+
+        ; output 1 and 3
+        ; interleave c1, d1
+        movdqa      xmm1,       xmm5        ; d1
+        punpcklwd   xmm1,       xmm4        ; c1 d1
+        punpckhwd   xmm5,       xmm4        ; c1 d1
+
+        movdqa      xmm3,       xmm1
+        movdqa      xmm4,       xmm5
+
+        pmaddwd     xmm1,       XMMWORD PTR[GLOBAL (_5352_2217)]    ; c1*2217 + d1*5352
+        pmaddwd     xmm4,       XMMWORD PTR[GLOBAL (_5352_2217)]    ; c1*2217 + d1*5352
+
+        pmaddwd     xmm3,       XMMWORD PTR[GLOBAL(_2217_neg5352)]  ; d1*2217 - c1*5352
+        pmaddwd     xmm5,       XMMWORD PTR[GLOBAL(_2217_neg5352)]  ; d1*2217 - c1*5352
+
+        paddd       xmm1,       XMMWORD PTR[GLOBAL(_14500)]
+        paddd       xmm4,       XMMWORD PTR[GLOBAL(_14500)]
+        paddd       xmm3,       XMMWORD PTR[GLOBAL(_7500)]
+        paddd       xmm5,       XMMWORD PTR[GLOBAL(_7500)]
+
+        psrad       xmm1,       12          ; (c1 * 2217 + d1 * 5352 +  14500)>>12
+        psrad       xmm4,       12          ; (c1 * 2217 + d1 * 5352 +  14500)>>12
+        psrad       xmm3,       12          ; (d1 * 2217 - c1 * 5352 +   7500)>>12
+        psrad       xmm5,       12          ; (d1 * 2217 - c1 * 5352 +   7500)>>12
+
+        packssdw    xmm1,       xmm4        ; op[1]
+        packssdw    xmm3,       xmm5        ; op[3]
+
+        ; done with vertical
+        ; transpose for the second stage
+        movdqa      xmm4,       xmm0         ; 00 10 20 30 04 14 24 34
+        movdqa      xmm5,       xmm2         ; 02 12 22 32 06 16 26 36
+
+        punpcklwd   xmm0,       xmm1         ; 00 01 10 11 20 21 30 31
+        punpckhwd   xmm4,       xmm1         ; 04 05 14 15 24 25 34 35
+
+        punpcklwd   xmm2,       xmm3         ; 02 03 12 13 22 23 32 33
+        punpckhwd   xmm5,       xmm3         ; 06 07 16 17 26 27 36 37
+
+        movdqa      xmm1,       xmm0         ; 00 01 10 11 20 21 30 31
+        punpckldq   xmm0,       xmm2         ; 00 01 02 03 10 11 12 13
+
+        punpckhdq   xmm1,       xmm2         ; 20 21 22 23 30 31 32 33
+
+        movdqa      xmm2,       xmm4         ; 04 05 14 15 24 25 34 35
+        punpckldq   xmm2,       xmm5         ; 04 05 06 07 14 15 16 17
+
+        punpckhdq   xmm4,       xmm5         ; 24 25 26 27 34 35 36 37
+        movdqa      xmm3,       xmm1         ; 20 21 22 23 30 31 32 33
+
+        punpckhqdq  xmm3,       xmm4         ; 30 31 32 33 34 35 36 37
+        punpcklqdq  xmm1,       xmm4         ; 20 21 22 23 24 25 26 27
+
+        movdqa      xmm4,       xmm0         ; 00 01 02 03 10 11 12 13
+        punpcklqdq  xmm0,       xmm2         ; 00 01 02 03 04 05 06 07
+
+        punpckhqdq  xmm4,       xmm2         ; 10 11 12 13 14 15 16 17
+
+        ; xmm0 0
+        ; xmm1 4
+        ; xmm2 1
+        ; xmm3 3
+
+        movdqa      xmm5,       xmm0
+        movdqa      xmm2,       xmm1
+
+        paddw       xmm0,       xmm3        ; a1 = 0 + 3
+        paddw       xmm1,       xmm4        ; b1 = 1 + 2
+
+        psubw       xmm4,       xmm2        ; c1 = 1 - 2
+        psubw       xmm5,       xmm3        ; d1 = 0 - 3
+
+        pxor        xmm6,       xmm6        ; zero out for compare
+
+        pcmpeqw     xmm6,       xmm5        ; d1 != 0
+
+        pandn       xmm6,       XMMWORD PTR[GLOBAL(_cmp_mask8x4)]   ; clear upper,
+                                                                    ; and keep bit 0 of lower
+
+        ; output 0 and 2
+        movdqa      xmm2,       xmm0        ; a1
+
+        paddw       xmm0,       xmm1        ; a1 + b1
+        psubw       xmm2,       xmm1        ; a1 - b1
+
+        paddw       xmm0,       XMMWORD PTR[GLOBAL(_7w)]
+        paddw       xmm2,       XMMWORD PTR[GLOBAL(_7w)]
+
+        psraw       xmm0,       4           ; op[0] = (a1 + b1 + 7)>>4
+        psraw       xmm2,       4           ; op[8] = (a1 - b1 + 7)>>4
+
+        ; output 1 and 3
+        ; interleave c1, d1
+        movdqa      xmm1,       xmm5        ; d1
+        punpcklwd   xmm1,       xmm4        ; c1 d1
+        punpckhwd   xmm5,       xmm4        ; c1 d1
+
+        movdqa      xmm3,       xmm1
+        movdqa      xmm4,       xmm5
+
+        pmaddwd     xmm1,       XMMWORD PTR[GLOBAL (_5352_2217)]    ; c1*2217 + d1*5352
+        pmaddwd     xmm4,       XMMWORD PTR[GLOBAL (_5352_2217)]    ; c1*2217 + d1*5352
+
+        pmaddwd     xmm3,       XMMWORD PTR[GLOBAL(_2217_neg5352)]  ; d1*2217 - c1*5352
+        pmaddwd     xmm5,       XMMWORD PTR[GLOBAL(_2217_neg5352)]  ; d1*2217 - c1*5352
+
+        paddd       xmm1,       XMMWORD PTR[GLOBAL(_12000)]
+        paddd       xmm4,       XMMWORD PTR[GLOBAL(_12000)]
+        paddd       xmm3,       XMMWORD PTR[GLOBAL(_51000)]
+        paddd       xmm5,       XMMWORD PTR[GLOBAL(_51000)]
+
+        psrad       xmm1,       16          ; (c1 * 2217 + d1 * 5352 +  14500)>>16
+        psrad       xmm4,       16          ; (c1 * 2217 + d1 * 5352 +  14500)>>16
+        psrad       xmm3,       16          ; (d1 * 2217 - c1 * 5352 +   7500)>>16
+        psrad       xmm5,       16          ; (d1 * 2217 - c1 * 5352 +   7500)>>16
+
+        packssdw    xmm1,       xmm4        ; op[4]
+        packssdw    xmm3,       xmm5        ; op[12]
+
+        paddw       xmm1,       xmm6        ; op[4] += (d1!=0)
+
+        movdqa      xmm4,       xmm0
+        movdqa      xmm5,       xmm2
+
+        punpcklqdq  xmm0,       xmm1
+        punpckhqdq  xmm4,       xmm1
+
+        punpcklqdq  xmm2,       xmm3
+        punpckhqdq  xmm5,       xmm3
+
+        movdqa      XMMWORD PTR[output + 0 ],  xmm0
+        movdqa      XMMWORD PTR[output + 16],  xmm2
+        movdqa      XMMWORD PTR[output + 32],  xmm4
+        movdqa      XMMWORD PTR[output + 48],  xmm5
+
+    STACK_FRAME_DESTROY
+
+SECTION_RODATA
+align 16
+_5352_2217:
+    dw 5352
+    dw 2217
+    dw 5352
+    dw 2217
+    dw 5352
+    dw 2217
+    dw 5352
+    dw 2217
+align 16
+_2217_neg5352:
+    dw 2217
+    dw -5352
+    dw 2217
+    dw -5352
+    dw 2217
+    dw -5352
+    dw 2217
+    dw -5352
+align 16
+_mult_add:
+    times 8 dw 1
+align 16
+_cmp_mask:
+    times 4 dw 1
+    times 4 dw 0
+align 16
+_cmp_mask8x4:
+    times 8 dw 1
+align 16
+_mult_sub:
+    dw 1
+    dw -1
+    dw 1
+    dw -1
+    dw 1
+    dw -1
+    dw 1
+    dw -1
+align 16
+_7:
+    times 4 dd 7
+align 16
+_7w:
+    times 8 dw 7
+align 16
+_14500:
+    times 4 dd 14500
+align 16
+_7500:
+    times 4 dd 7500
+align 16
+_12000:
+    times 4 dd 12000
+align 16
+_51000:
+    times 4 dd 51000
diff --git a/vp8/encoder/x86/encodeopt.asm b/vp8/encoder/x86/encodeopt.asm
new file mode 100644 (file)
index 0000000..7ec7d60
--- /dev/null
@@ -0,0 +1,386 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;int vp8_block_error_xmm(short *coeff_ptr,  short *dcoef_ptr)
+global sym(vp8_block_error_xmm)
+sym(vp8_block_error_xmm):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 2
+    push rsi
+    push rdi
+    ; end prologue
+
+        mov         rsi,        arg(0) ;coeff_ptr
+        mov         rdi,        arg(1) ;dcoef_ptr
+
+        movdqa      xmm0,       [rsi]
+        movdqa      xmm1,       [rdi]
+
+        movdqa      xmm2,       [rsi+16]
+        movdqa      xmm3,       [rdi+16]
+
+        psubw       xmm0,       xmm1
+        psubw       xmm2,       xmm3
+
+        pmaddwd     xmm0,       xmm0
+        pmaddwd     xmm2,       xmm2
+
+        paddd       xmm0,       xmm2
+
+        pxor        xmm5,       xmm5
+        movdqa      xmm1,       xmm0
+
+        punpckldq   xmm0,       xmm5
+        punpckhdq   xmm1,       xmm5
+
+        paddd       xmm0,       xmm1
+        movdqa      xmm1,       xmm0
+
+        psrldq      xmm0,       8
+        paddd       xmm0,       xmm1
+
+        movq        rax,        xmm0
+
+    pop rdi
+    pop rsi
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;int vp8_block_error_mmx(short *coeff_ptr,  short *dcoef_ptr)
+global sym(vp8_block_error_mmx)
+sym(vp8_block_error_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 2
+    push rsi
+    push rdi
+    ; end prolog
+
+
+        mov         rsi,        arg(0) ;coeff_ptr
+        pxor        mm7,        mm7
+
+        mov         rdi,        arg(1) ;dcoef_ptr
+        movq        mm3,        [rsi]
+
+        movq        mm4,        [rdi]
+        movq        mm5,        [rsi+8]
+
+        movq        mm6,        [rdi+8]
+        pxor        mm1,        mm1 ; from movd mm1, dc ; dc =0
+
+        movq        mm2,        mm7
+        psubw       mm5,        mm6
+
+        por         mm1,        mm2
+        pmaddwd     mm5,        mm5
+
+        pcmpeqw     mm1,        mm7
+        psubw       mm3,        mm4
+
+        pand        mm1,        mm3
+        pmaddwd     mm1,        mm1
+
+        paddd       mm1,        mm5
+        movq        mm3,        [rsi+16]
+
+        movq        mm4,        [rdi+16]
+        movq        mm5,        [rsi+24]
+
+        movq        mm6,        [rdi+24]
+        psubw       mm5,        mm6
+
+        pmaddwd     mm5,        mm5
+        psubw       mm3,        mm4
+
+        pmaddwd     mm3,        mm3
+        paddd       mm3,        mm5
+
+        paddd       mm1,        mm3
+        movq        mm0,        mm1
+
+        psrlq       mm1,        32
+        paddd       mm0,        mm1
+
+        movq        rax,        mm0
+
+    pop rdi
+    pop rsi
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;int vp8_mbblock_error_mmx_impl(short *coeff_ptr, short *dcoef_ptr, int dc);
+global sym(vp8_mbblock_error_mmx_impl)
+sym(vp8_mbblock_error_mmx_impl):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 3
+    push rsi
+    push rdi
+    ; end prolog
+
+
+        mov         rsi,        arg(0) ;coeff_ptr
+        pxor        mm7,        mm7
+
+        mov         rdi,        arg(1) ;dcoef_ptr
+        pxor        mm2,        mm2
+
+        movd        mm1,        dword ptr arg(2) ;dc
+        por         mm1,        mm2
+
+        pcmpeqw     mm1,        mm7
+        mov         rcx,        16
+
+.mberror_loop_mmx:
+        movq        mm3,       [rsi]
+        movq        mm4,       [rdi]
+
+        movq        mm5,       [rsi+8]
+        movq        mm6,       [rdi+8]
+
+
+        psubw       mm5,        mm6
+        pmaddwd     mm5,        mm5
+
+        psubw       mm3,        mm4
+        pand        mm3,        mm1
+
+        pmaddwd     mm3,        mm3
+        paddd       mm2,        mm5
+
+        paddd       mm2,        mm3
+        movq        mm3,       [rsi+16]
+
+        movq        mm4,       [rdi+16]
+        movq        mm5,       [rsi+24]
+
+        movq        mm6,       [rdi+24]
+        psubw       mm5,        mm6
+
+        pmaddwd     mm5,        mm5
+        psubw       mm3,        mm4
+
+        pmaddwd     mm3,        mm3
+        paddd       mm2,        mm5
+
+        paddd       mm2,        mm3
+        add         rsi,        32
+
+        add         rdi,        32
+        sub         rcx,        1
+
+        jnz         .mberror_loop_mmx
+
+        movq        mm0,        mm2
+        psrlq       mm2,        32
+
+        paddd       mm0,        mm2
+        movq        rax,        mm0
+
+    pop rdi
+    pop rsi
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;int vp8_mbblock_error_xmm_impl(short *coeff_ptr, short *dcoef_ptr, int dc);
+global sym(vp8_mbblock_error_xmm_impl)
+sym(vp8_mbblock_error_xmm_impl):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 3
+    SAVE_XMM 6
+    push rsi
+    push rdi
+    ; end prolog
+
+
+        mov         rsi,        arg(0) ;coeff_ptr
+        pxor        xmm6,       xmm6
+
+        mov         rdi,        arg(1) ;dcoef_ptr
+        pxor        xmm4,       xmm4
+
+        movd        xmm5,       dword ptr arg(2) ;dc
+        por         xmm5,       xmm4
+
+        pcmpeqw     xmm5,       xmm6
+        mov         rcx,        16
+
+.mberror_loop:
+        movdqa      xmm0,       [rsi]
+        movdqa      xmm1,       [rdi]
+
+        movdqa      xmm2,       [rsi+16]
+        movdqa      xmm3,       [rdi+16]
+
+
+        psubw       xmm2,       xmm3
+        pmaddwd     xmm2,       xmm2
+
+        psubw       xmm0,       xmm1
+        pand        xmm0,       xmm5
+
+        pmaddwd     xmm0,       xmm0
+        add         rsi,        32
+
+        add         rdi,        32
+
+        sub         rcx,        1
+        paddd       xmm4,       xmm2
+
+        paddd       xmm4,       xmm0
+        jnz         .mberror_loop
+
+        movdqa      xmm0,       xmm4
+        punpckldq   xmm0,       xmm6
+
+        punpckhdq   xmm4,       xmm6
+        paddd       xmm0,       xmm4
+
+        movdqa      xmm1,       xmm0
+        psrldq      xmm0,       8
+
+        paddd       xmm0,       xmm1
+        movq        rax,        xmm0
+
+    pop rdi
+    pop rsi
+    ; begin epilog
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;int vp8_mbuverror_mmx_impl(short *s_ptr, short *d_ptr);
+global sym(vp8_mbuverror_mmx_impl)
+sym(vp8_mbuverror_mmx_impl):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 2
+    push rsi
+    push rdi
+    ; end prolog
+
+
+        mov             rsi,        arg(0) ;s_ptr
+        mov             rdi,        arg(1) ;d_ptr
+
+        mov             rcx,        16
+        pxor            mm7,        mm7
+
+.mbuverror_loop_mmx:
+
+        movq            mm1,        [rsi]
+        movq            mm2,        [rdi]
+
+        psubw           mm1,        mm2
+        pmaddwd         mm1,        mm1
+
+
+        movq            mm3,        [rsi+8]
+        movq            mm4,        [rdi+8]
+
+        psubw           mm3,        mm4
+        pmaddwd         mm3,        mm3
+
+
+        paddd           mm7,        mm1
+        paddd           mm7,        mm3
+
+
+        add             rsi,        16
+        add             rdi,        16
+
+        dec             rcx
+        jnz             .mbuverror_loop_mmx
+
+        movq            mm0,        mm7
+        psrlq           mm7,        32
+
+        paddd           mm0,        mm7
+        movq            rax,        mm0
+
+    pop rdi
+    pop rsi
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;int vp8_mbuverror_xmm_impl(short *s_ptr, short *d_ptr);
+global sym(vp8_mbuverror_xmm_impl)
+sym(vp8_mbuverror_xmm_impl):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 2
+    push rsi
+    push rdi
+    ; end prolog
+
+
+        mov             rsi,        arg(0) ;s_ptr
+        mov             rdi,        arg(1) ;d_ptr
+
+        mov             rcx,        16
+        pxor            xmm3,       xmm3
+
+.mbuverror_loop:
+
+        movdqa          xmm1,       [rsi]
+        movdqa          xmm2,       [rdi]
+
+        psubw           xmm1,       xmm2
+        pmaddwd         xmm1,       xmm1
+
+        paddd           xmm3,       xmm1
+
+        add             rsi,        16
+        add             rdi,        16
+
+        dec             rcx
+        jnz             .mbuverror_loop
+
+        pxor        xmm0,           xmm0
+        movdqa      xmm1,           xmm3
+
+        movdqa      xmm2,           xmm1
+        punpckldq   xmm1,           xmm0
+
+        punpckhdq   xmm2,           xmm0
+        paddd       xmm1,           xmm2
+
+        movdqa      xmm2,           xmm1
+
+        psrldq      xmm1,           8
+        paddd       xmm1,           xmm2
+
+        movq            rax,            xmm1
+
+    pop rdi
+    pop rsi
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
diff --git a/vp8/encoder/x86/fwalsh_sse2.asm b/vp8/encoder/x86/fwalsh_sse2.asm
new file mode 100644 (file)
index 0000000..71efd56
--- /dev/null
@@ -0,0 +1,164 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;void vp8_short_walsh4x4_sse2(short *input, short *output, int pitch)
+global sym(vp8_short_walsh4x4_sse2)
+sym(vp8_short_walsh4x4_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 3
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    mov     rsi, arg(0)           ; input
+    mov     rdi, arg(1)           ; output
+    movsxd  rdx, dword ptr arg(2) ; pitch
+
+    ; first for loop
+    movq    xmm0, MMWORD PTR [rsi]           ; load input
+    movq    xmm1, MMWORD PTR [rsi + rdx]
+    lea     rsi,  [rsi + rdx*2]
+    movq    xmm2, MMWORD PTR [rsi]
+    movq    xmm3, MMWORD PTR [rsi + rdx]
+
+    punpcklwd xmm0,  xmm1
+    punpcklwd xmm2,  xmm3
+
+    movdqa    xmm1, xmm0
+    punpckldq xmm0, xmm2           ; ip[1] ip[0]
+    punpckhdq xmm1, xmm2           ; ip[3] ip[2]
+
+    movdqa    xmm2, xmm0
+    paddw     xmm0, xmm1
+    psubw     xmm2, xmm1
+
+    psllw     xmm0, 2              ; d1  a1
+    psllw     xmm2, 2              ; c1  b1
+
+    movdqa    xmm1, xmm0
+    punpcklqdq xmm0, xmm2          ; b1  a1
+    punpckhqdq xmm1, xmm2          ; c1  d1
+
+    pxor      xmm6, xmm6
+    movq      xmm6, xmm0
+    pxor      xmm7, xmm7
+    pcmpeqw   xmm7, xmm6
+    paddw     xmm7, [GLOBAL(c1)]
+
+    movdqa    xmm2, xmm0
+    paddw     xmm0, xmm1           ; b1+c1  a1+d1
+    psubw     xmm2, xmm1           ; b1-c1  a1-d1
+    paddw     xmm0, xmm7           ; b1+c1  a1+d1+(a1!=0)
+
+    ; second for loop
+    ; input: 13  9  5  1 12  8  4  0 (xmm0)
+    ;        14 10  6  2 15 11  7  3 (xmm2)
+    ; after shuffle:
+    ;        13  5  9  1 12  4  8  0 (xmm0)
+    ;        14  6 10  2 15  7 11  3 (xmm1)
+    pshuflw   xmm3, xmm0, 0xd8
+    pshufhw   xmm0, xmm3, 0xd8
+    pshuflw   xmm3, xmm2, 0xd8
+    pshufhw   xmm1, xmm3, 0xd8
+
+    movdqa    xmm2, xmm0
+    pmaddwd   xmm0, [GLOBAL(c1)]    ; d11 a11 d10 a10
+    pmaddwd   xmm2, [GLOBAL(cn1)]   ; c11 b11 c10 b10
+    movdqa    xmm3, xmm1
+    pmaddwd   xmm1, [GLOBAL(c1)]    ; d12 a12 d13 a13
+    pmaddwd   xmm3, [GLOBAL(cn1)]   ; c12 b12 c13 b13
+
+    pshufd    xmm4, xmm0, 0xd8      ; d11 d10 a11 a10
+    pshufd    xmm5, xmm2, 0xd8      ; c11 c10 b11 b10
+    pshufd    xmm6, xmm1, 0x72      ; d13 d12 a13 a12
+    pshufd    xmm7, xmm3, 0x72      ; c13 c12 b13 b12
+
+    movdqa    xmm0, xmm4
+    punpcklqdq xmm0, xmm5           ; b11 b10 a11 a10
+    punpckhqdq xmm4, xmm5           ; c11 c10 d11 d10
+    movdqa    xmm1, xmm6
+    punpcklqdq xmm1, xmm7           ; b13 b12 a13 a12
+    punpckhqdq xmm6, xmm7           ; c13 c12 d13 d12
+
+    movdqa    xmm2, xmm0
+    paddd     xmm0, xmm4            ; b21 b20 a21 a20
+    psubd     xmm2, xmm4            ; c21 c20 d21 d20
+    movdqa    xmm3, xmm1
+    paddd     xmm1, xmm6            ; b23 b22 a23 a22
+    psubd     xmm3, xmm6            ; c23 c22 d23 d22
+
+    pxor      xmm4, xmm4
+    movdqa    xmm5, xmm4
+    pcmpgtd   xmm4, xmm0
+    pcmpgtd   xmm5, xmm2
+    pand      xmm4, [GLOBAL(cd1)]
+    pand      xmm5, [GLOBAL(cd1)]
+
+    pxor      xmm6, xmm6
+    movdqa    xmm7, xmm6
+    pcmpgtd   xmm6, xmm1
+    pcmpgtd   xmm7, xmm3
+    pand      xmm6, [GLOBAL(cd1)]
+    pand      xmm7, [GLOBAL(cd1)]
+
+    paddd     xmm0, xmm4
+    paddd     xmm2, xmm5
+    paddd     xmm0, [GLOBAL(cd3)]
+    paddd     xmm2, [GLOBAL(cd3)]
+    paddd     xmm1, xmm6
+    paddd     xmm3, xmm7
+    paddd     xmm1, [GLOBAL(cd3)]
+    paddd     xmm3, [GLOBAL(cd3)]
+
+    psrad     xmm0, 3
+    psrad     xmm1, 3
+    psrad     xmm2, 3
+    psrad     xmm3, 3
+    movdqa    xmm4, xmm0
+    punpcklqdq xmm0, xmm1           ; a23 a22 a21 a20
+    punpckhqdq xmm4, xmm1           ; b23 b22 b21 b20
+    movdqa    xmm5, xmm2
+    punpckhqdq xmm2, xmm3           ; c23 c22 c21 c20
+    punpcklqdq xmm5, xmm3           ; d23 d22 d21 d20
+
+    packssdw  xmm0, xmm4            ; b23 b22 b21 b20 a23 a22 a21 a20
+    packssdw  xmm2, xmm5            ; d23 d22 d21 d20 c23 c22 c21 c20
+
+    movdqa  XMMWORD PTR [rdi], xmm0
+    movdqa  XMMWORD PTR [rdi + 16], xmm2
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+SECTION_RODATA
+align 16
+c1:
+    dw 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001
+align 16
+cn1:
+    dw 0x0001, 0xffff, 0x0001, 0xffff, 0x0001, 0xffff, 0x0001, 0xffff
+align 16
+cd1:
+    dd 0x00000001, 0x00000001, 0x00000001, 0x00000001
+align 16
+cd3:
+    dd 0x00000003, 0x00000003, 0x00000003, 0x00000003
diff --git a/vp8/encoder/x86/quantize_mmx.asm b/vp8/encoder/x86/quantize_mmx.asm
new file mode 100644 (file)
index 0000000..f29a54e
--- /dev/null
@@ -0,0 +1,286 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;int vp8_fast_quantize_b_impl_mmx(short *coeff_ptr, short *zbin_ptr,
+;                           short *qcoeff_ptr,short *dequant_ptr,
+;                           short *scan_mask, short *round_ptr,
+;                           short *quant_ptr, short *dqcoeff_ptr);
+global sym(vp8_fast_quantize_b_impl_mmx)
+sym(vp8_fast_quantize_b_impl_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 8
+    push rsi
+    push rdi
+    ; end prolog
+
+
+        mov             rsi,        arg(0) ;coeff_ptr
+        movq            mm0,        [rsi]
+
+        mov             rax,        arg(1) ;zbin_ptr
+        movq            mm1,        [rax]
+
+        movq            mm3,        mm0
+        psraw           mm0,        15
+
+        pxor            mm3,        mm0
+        psubw           mm3,        mm0         ; abs
+
+        movq            mm2,        mm3
+        pcmpgtw         mm1,        mm2
+
+        pandn           mm1,        mm2
+        movq            mm3,        mm1
+
+        mov             rdx,        arg(6) ;quant_ptr
+        movq            mm1,        [rdx]
+
+        mov             rcx,        arg(5) ;round_ptr
+        movq            mm2,        [rcx]
+
+        paddw           mm3,        mm2
+        pmulhuw         mm3,        mm1
+
+        pxor            mm3,        mm0
+        psubw           mm3,        mm0     ;gain the sign back
+
+        mov             rdi,        arg(2) ;qcoeff_ptr
+        movq            mm0,        mm3
+
+        movq            [rdi],      mm3
+
+        mov             rax,        arg(3) ;dequant_ptr
+        movq            mm2,        [rax]
+
+        pmullw          mm3,        mm2
+        mov             rax,        arg(7) ;dqcoeff_ptr
+
+        movq            [rax],      mm3
+
+        ; next 8
+        movq            mm4,        [rsi+8]
+
+        mov             rax,        arg(1) ;zbin_ptr
+        movq            mm5,        [rax+8]
+
+        movq            mm7,        mm4
+        psraw           mm4,        15
+
+        pxor            mm7,        mm4
+        psubw           mm7,        mm4         ; abs
+
+        movq            mm6,        mm7
+        pcmpgtw         mm5,        mm6
+
+        pandn           mm5,        mm6
+        movq            mm7,        mm5
+
+        movq            mm5,        [rdx+8]
+        movq            mm6,        [rcx+8]
+
+        paddw           mm7,        mm6
+        pmulhuw         mm7,        mm5
+
+        pxor            mm7,        mm4
+        psubw           mm7,        mm4;gain the sign back
+
+        mov             rdi,        arg(2) ;qcoeff_ptr
+
+        movq            mm1,        mm7
+        movq            [rdi+8],    mm7
+
+        mov             rax,        arg(3) ;dequant_ptr
+        movq            mm6,        [rax+8]
+
+        pmullw          mm7,        mm6
+        mov             rax,        arg(7) ;dqcoeff_ptr
+
+        movq            [rax+8],    mm7
+
+
+                ; next 8
+        movq            mm4,        [rsi+16]
+
+        mov             rax,        arg(1) ;zbin_ptr
+        movq            mm5,        [rax+16]
+
+        movq            mm7,        mm4
+        psraw           mm4,        15
+
+        pxor            mm7,        mm4
+        psubw           mm7,        mm4         ; abs
+
+        movq            mm6,        mm7
+        pcmpgtw         mm5,        mm6
+
+        pandn           mm5,        mm6
+        movq            mm7,        mm5
+
+        movq            mm5,        [rdx+16]
+        movq            mm6,        [rcx+16]
+
+        paddw           mm7,        mm6
+        pmulhuw         mm7,        mm5
+
+        pxor            mm7,        mm4
+        psubw           mm7,        mm4;gain the sign back
+
+        mov             rdi,        arg(2) ;qcoeff_ptr
+
+        movq            mm1,        mm7
+        movq            [rdi+16],   mm7
+
+        mov             rax,        arg(3) ;dequant_ptr
+        movq            mm6,        [rax+16]
+
+        pmullw          mm7,        mm6
+        mov             rax,        arg(7) ;dqcoeff_ptr
+
+        movq            [rax+16],   mm7
+
+
+                ; next 8
+        movq            mm4,        [rsi+24]
+
+        mov             rax,        arg(1) ;zbin_ptr
+        movq            mm5,        [rax+24]
+
+        movq            mm7,        mm4
+        psraw           mm4,        15
+
+        pxor            mm7,        mm4
+        psubw           mm7,        mm4         ; abs
+
+        movq            mm6,        mm7
+        pcmpgtw         mm5,        mm6
+
+        pandn           mm5,        mm6
+        movq            mm7,        mm5
+
+        movq            mm5,        [rdx+24]
+        movq            mm6,        [rcx+24]
+
+        paddw           mm7,        mm6
+        pmulhuw         mm7,        mm5
+
+        pxor            mm7,        mm4
+        psubw           mm7,        mm4;gain the sign back
+
+        mov             rdi,        arg(2) ;qcoeff_ptr
+
+        movq            mm1,        mm7
+        movq            [rdi+24],   mm7
+
+        mov             rax,        arg(3) ;dequant_ptr
+        movq            mm6,        [rax+24]
+
+        pmullw          mm7,        mm6
+        mov             rax,        arg(7) ;dqcoeff_ptr
+
+        movq            [rax+24],   mm7
+
+
+
+        mov             rdi,        arg(4) ;scan_mask
+        mov             rsi,        arg(2) ;qcoeff_ptr
+
+        pxor            mm5,        mm5
+        pxor            mm7,        mm7
+
+        movq            mm0,        [rsi]
+        movq            mm1,        [rsi+8]
+
+        movq            mm2,        [rdi]
+        movq            mm3,        [rdi+8];
+
+        pcmpeqw         mm0,        mm7
+        pcmpeqw         mm1,        mm7
+
+        pcmpeqw         mm6,        mm6
+        pxor            mm0,        mm6
+
+        pxor            mm1,        mm6
+        psrlw           mm0,        15
+
+        psrlw           mm1,        15
+        pmaddwd         mm0,        mm2
+
+        pmaddwd         mm1,        mm3
+        movq            mm5,        mm0
+
+        paddd           mm5,        mm1
+
+        movq            mm0,        [rsi+16]
+        movq            mm1,        [rsi+24]
+
+        movq            mm2,        [rdi+16]
+        movq            mm3,        [rdi+24];
+
+        pcmpeqw         mm0,        mm7
+        pcmpeqw         mm1,        mm7
+
+        pcmpeqw         mm6,        mm6
+        pxor            mm0,        mm6
+
+        pxor            mm1,        mm6
+        psrlw           mm0,        15
+
+        psrlw           mm1,        15
+        pmaddwd         mm0,        mm2
+
+        pmaddwd         mm1,        mm3
+        paddd           mm5,        mm0
+
+        paddd           mm5,        mm1
+        movq            mm0,        mm5
+
+        psrlq           mm5,        32
+        paddd           mm0,        mm5
+
+        ; eob adjustment begins here
+        movq            rcx,        mm0
+        and             rcx,        0xffff
+
+        xor             rdx,        rdx
+        sub             rdx,        rcx ; rdx=-rcx
+
+        bsr             rax,        rcx
+        inc             rax
+
+        sar             rdx,        31
+        and             rax,        rdx
+        ; Substitute the sse assembly for the old mmx mixed assembly/C. The
+        ; following is kept as reference
+        ;    movq            rcx,        mm0
+        ;    bsr             rax,        rcx
+        ;
+        ;    mov             eob,        rax
+        ;    mov             eee,        rcx
+        ;
+        ;if(eee==0)
+        ;{
+        ;    eob=-1;
+        ;}
+        ;else if(eee<0)
+        ;{
+        ;    eob=15;
+        ;}
+        ;d->eob = eob+1;
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
diff --git a/vp8/encoder/x86/quantize_sse2.asm b/vp8/encoder/x86/quantize_sse2.asm
new file mode 100644 (file)
index 0000000..7c249ff
--- /dev/null
@@ -0,0 +1,386 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license and patent
+;  grant that can be found in the LICENSE file in the root of the source
+;  tree. All contributing project authors may be found in the AUTHORS
+;  file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+%include "asm_enc_offsets.asm"
+
+
+; void vp8_regular_quantize_b_sse2 | arg
+;  (BLOCK  *b,                     |  0
+;   BLOCKD *d)                     |  1
+
+global sym(vp8_regular_quantize_b_sse2)
+sym(vp8_regular_quantize_b_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SAVE_XMM 7
+    GET_GOT     rbx
+
+%if ABI_IS_32BIT
+    push        rdi
+    push        rsi
+%else
+  %ifidn __OUTPUT_FORMAT__,x64
+    push        rdi
+    push        rsi
+  %endif
+%endif
+
+    ALIGN_STACK 16, rax
+    %define zrun_zbin_boost   0  ;  8
+    %define abs_minus_zbin    8  ; 32
+    %define temp_qcoeff       40 ; 32
+    %define qcoeff            72 ; 32
+    %define stack_size        104
+    sub         rsp, stack_size
+    ; end prolog
+
+%if ABI_IS_32BIT
+    mov         rdi, arg(0)                 ; BLOCK *b
+    mov         rsi, arg(1)                 ; BLOCKD *d
+%else
+  %ifidn __OUTPUT_FORMAT__,x64
+    mov         rdi, rcx                    ; BLOCK *b
+    mov         rsi, rdx                    ; BLOCKD *d
+  %else
+    ;mov         rdi, rdi                    ; BLOCK *b
+    ;mov         rsi, rsi                    ; BLOCKD *d
+  %endif
+%endif
+
+    mov         rdx, [rdi + vp8_block_coeff] ; coeff_ptr
+    mov         rcx, [rdi + vp8_block_zbin] ; zbin_ptr
+    movd        xmm7, [rdi + vp8_block_zbin_extra] ; zbin_oq_value
+
+    ; z
+    movdqa      xmm0, [rdx]
+    movdqa      xmm4, [rdx + 16]
+    mov         rdx, [rdi + vp8_block_round] ; round_ptr
+
+    pshuflw     xmm7, xmm7, 0
+    punpcklwd   xmm7, xmm7                  ; duplicated zbin_oq_value
+
+    movdqa      xmm1, xmm0
+    movdqa      xmm5, xmm4
+
+    ; sz
+    psraw       xmm0, 15
+    psraw       xmm4, 15
+
+    ; (z ^ sz)
+    pxor        xmm1, xmm0
+    pxor        xmm5, xmm4
+
+    ; x = abs(z)
+    psubw       xmm1, xmm0
+    psubw       xmm5, xmm4
+
+    movdqa      xmm2, [rcx]
+    movdqa      xmm3, [rcx + 16]
+    mov         rcx, [rdi + vp8_block_quant] ; quant_ptr
+
+    ; *zbin_ptr + zbin_oq_value
+    paddw       xmm2, xmm7
+    paddw       xmm3, xmm7
+
+    ; x - (*zbin_ptr + zbin_oq_value)
+    psubw       xmm1, xmm2
+    psubw       xmm5, xmm3
+    movdqa      [rsp + abs_minus_zbin], xmm1
+    movdqa      [rsp + abs_minus_zbin + 16], xmm5
+
+    ; add (zbin_ptr + zbin_oq_value) back
+    paddw       xmm1, xmm2
+    paddw       xmm5, xmm3
+
+    movdqa      xmm2, [rdx]
+    movdqa      xmm6, [rdx + 16]
+
+    movdqa      xmm3, [rcx]
+    movdqa      xmm7, [rcx + 16]
+
+    ; x + round
+    paddw       xmm1, xmm2
+    paddw       xmm5, xmm6
+
+    ; y = x * quant_ptr >> 16
+    pmulhw      xmm3, xmm1
+    pmulhw      xmm7, xmm5
+
+    ; y += x
+    paddw       xmm1, xmm3
+    paddw       xmm5, xmm7
+
+    movdqa      [rsp + temp_qcoeff], xmm1
+    movdqa      [rsp + temp_qcoeff + 16], xmm5
+
+    pxor        xmm6, xmm6
+    ; zero qcoeff
+    movdqa      [rsp + qcoeff], xmm6
+    movdqa      [rsp + qcoeff + 16], xmm6
+
+    mov         rdx, [rdi + vp8_block_zrun_zbin_boost] ; zbin_boost_ptr
+    mov         rax, [rdi + vp8_block_quant_shift] ; quant_shift_ptr
+    mov         [rsp + zrun_zbin_boost], rdx
+
+%macro ZIGZAG_LOOP 1
+    ; x
+    movsx       ecx, WORD PTR[rsp + abs_minus_zbin + %1 * 2]
+
+    ; if (x >= zbin)
+    sub         cx, WORD PTR[rdx]           ; x - zbin
+    lea         rdx, [rdx + 2]              ; zbin_boost_ptr++
+    jl          .rq_zigzag_loop_%1           ; x < zbin
+
+    movsx       edi, WORD PTR[rsp + temp_qcoeff + %1 * 2]
+
+    ; downshift by quant_shift[rc]
+    movsx       cx, BYTE PTR[rax + %1]      ; quant_shift_ptr[rc]
+    sar         edi, cl                     ; also sets Z bit
+    je          .rq_zigzag_loop_%1           ; !y
+    mov         WORD PTR[rsp + qcoeff + %1 * 2], di ;qcoeff_ptr[rc] = temp_qcoeff[rc]
+    mov         rdx, [rsp + zrun_zbin_boost] ; reset to b->zrun_zbin_boost
+.rq_zigzag_loop_%1:
+%endmacro
+; in vp8_default_zig_zag1d order: see vp8/common/entropy.c
+ZIGZAG_LOOP  0
+ZIGZAG_LOOP  1
+ZIGZAG_LOOP  4
+ZIGZAG_LOOP  8
+ZIGZAG_LOOP  5
+ZIGZAG_LOOP  2
+ZIGZAG_LOOP  3
+ZIGZAG_LOOP  6
+ZIGZAG_LOOP  9
+ZIGZAG_LOOP 12
+ZIGZAG_LOOP 13
+ZIGZAG_LOOP 10
+ZIGZAG_LOOP  7
+ZIGZAG_LOOP 11
+ZIGZAG_LOOP 14
+ZIGZAG_LOOP 15
+
+    movdqa      xmm2, [rsp + qcoeff]
+    movdqa      xmm3, [rsp + qcoeff + 16]
+
+    mov         rcx, [rsi + vp8_blockd_dequant] ; dequant_ptr
+    mov         rdi, [rsi + vp8_blockd_dqcoeff] ; dqcoeff_ptr
+
+    ; y ^ sz
+    pxor        xmm2, xmm0
+    pxor        xmm3, xmm4
+    ; x = (y ^ sz) - sz
+    psubw       xmm2, xmm0
+    psubw       xmm3, xmm4
+
+    ; dequant
+    movdqa      xmm0, [rcx]
+    movdqa      xmm1, [rcx + 16]
+
+    mov         rcx, [rsi + vp8_blockd_qcoeff] ; qcoeff_ptr
+
+    pmullw      xmm0, xmm2
+    pmullw      xmm1, xmm3
+
+    movdqa      [rcx], xmm2        ; store qcoeff
+    movdqa      [rcx + 16], xmm3
+    movdqa      [rdi], xmm0        ; store dqcoeff
+    movdqa      [rdi + 16], xmm1
+
+    mov         rcx, [rsi + vp8_blockd_eob]
+
+    ; select the last value (in zig_zag order) for EOB
+    pcmpeqw     xmm2, xmm6
+    pcmpeqw     xmm3, xmm6
+    ; !
+    pcmpeqw     xmm6, xmm6
+    pxor        xmm2, xmm6
+    pxor        xmm3, xmm6
+    ; mask inv_zig_zag
+    pand        xmm2, [GLOBAL(inv_zig_zag)]
+    pand        xmm3, [GLOBAL(inv_zig_zag + 16)]
+    ; select the max value
+    pmaxsw      xmm2, xmm3
+    pshufd      xmm3, xmm2, 00001110b
+    pmaxsw      xmm2, xmm3
+    pshuflw     xmm3, xmm2, 00001110b
+    pmaxsw      xmm2, xmm3
+    pshuflw     xmm3, xmm2, 00000001b
+    pmaxsw      xmm2, xmm3
+    movd        eax, xmm2
+    and         eax, 0xff
+
+    mov         BYTE PTR [rcx], al          ; store eob
+
+    ; begin epilog
+    add         rsp, stack_size
+    pop         rsp
+%if ABI_IS_32BIT
+    pop         rsi
+    pop         rdi
+%else
+  %ifidn __OUTPUT_FORMAT__,x64
+    pop         rsi
+    pop         rdi
+  %endif
+%endif
+    RESTORE_GOT
+    RESTORE_XMM
+    pop         rbp
+    ret
+
+; void vp8_fast_quantize_b_sse2 | arg
+;  (BLOCK  *b,                  |  0
+;   BLOCKD *d)                  |  1
+
+global sym(vp8_fast_quantize_b_sse2)
+sym(vp8_fast_quantize_b_sse2):
+    push        rbp
+    mov         rbp, rsp
+    GET_GOT     rbx
+
+%if ABI_IS_32BIT
+    push        rdi
+    push        rsi
+%else
+  %ifidn __OUTPUT_FORMAT__,x64
+    push        rdi
+    push        rsi
+  %else
+    ; these registers are used for passing arguments
+  %endif
+%endif
+
+    ; end prolog
+
+%if ABI_IS_32BIT
+    mov         rdi, arg(0)                 ; BLOCK *b
+    mov         rsi, arg(1)                 ; BLOCKD *d
+%else
+  %ifidn __OUTPUT_FORMAT__,x64
+    mov         rdi, rcx                    ; BLOCK *b
+    mov         rsi, rdx                    ; BLOCKD *d
+  %else
+    ;mov         rdi, rdi                    ; BLOCK *b
+    ;mov         rsi, rsi                    ; BLOCKD *d
+  %endif
+%endif
+
+    mov         rax, [rdi + vp8_block_coeff]
+    mov         rcx, [rdi + vp8_block_round]
+    mov         rdx, [rdi + vp8_block_quant_fast]
+
+    ; z = coeff
+    movdqa      xmm0, [rax]
+    movdqa      xmm4, [rax + 16]
+
+    ; dup z so we can save sz
+    movdqa      xmm1, xmm0
+    movdqa      xmm5, xmm4
+
+    ; sz = z >> 15
+    psraw       xmm0, 15
+    psraw       xmm4, 15
+
+    ; x = abs(z) = (z ^ sz) - sz
+    pxor        xmm1, xmm0
+    pxor        xmm5, xmm4
+    psubw       xmm1, xmm0
+    psubw       xmm5, xmm4
+
+    ; x += round
+    paddw       xmm1, [rcx]
+    paddw       xmm5, [rcx + 16]
+
+    mov         rax, [rsi + vp8_blockd_qcoeff]
+    mov         rcx, [rsi + vp8_blockd_dequant]
+    mov         rdi, [rsi + vp8_blockd_dqcoeff]
+
+    ; y = x * quant >> 16
+    pmulhw      xmm1, [rdx]
+    pmulhw      xmm5, [rdx + 16]
+
+    ; x = (y ^ sz) - sz
+    pxor        xmm1, xmm0
+    pxor        xmm5, xmm4
+    psubw       xmm1, xmm0
+    psubw       xmm5, xmm4
+
+    ; qcoeff = x
+    movdqa      [rax], xmm1
+    movdqa      [rax + 16], xmm5
+
+    ; x * dequant
+    movdqa      xmm2, xmm1
+    movdqa      xmm3, xmm5
+    pmullw      xmm2, [rcx]
+    pmullw      xmm3, [rcx + 16]
+
+    ; dqcoeff = x * dequant
+    movdqa      [rdi], xmm2
+    movdqa      [rdi + 16], xmm3
+
+    pxor        xmm4, xmm4                  ;clear all bits
+    pcmpeqw     xmm1, xmm4
+    pcmpeqw     xmm5, xmm4
+
+    pcmpeqw     xmm4, xmm4                  ;set all bits
+    pxor        xmm1, xmm4
+    pxor        xmm5, xmm4
+
+    pand        xmm1, [GLOBAL(inv_zig_zag)]
+    pand        xmm5, [GLOBAL(inv_zig_zag + 16)]
+
+    pmaxsw      xmm1, xmm5
+
+    mov         rcx, [rsi + vp8_blockd_eob]
+
+    ; now down to 8
+    pshufd      xmm5, xmm1, 00001110b
+
+    pmaxsw      xmm1, xmm5
+
+    ; only 4 left
+    pshuflw     xmm5, xmm1, 00001110b
+
+    pmaxsw      xmm1, xmm5
+
+    ; okay, just 2!
+    pshuflw     xmm5, xmm1, 00000001b
+
+    pmaxsw      xmm1, xmm5
+
+    movd        eax, xmm1
+    and         eax, 0xff
+
+    mov         BYTE PTR [rcx], al          ; store eob
+
+    ; begin epilog
+%if ABI_IS_32BIT
+    pop         rsi
+    pop         rdi
+%else
+  %ifidn __OUTPUT_FORMAT__,x64
+    pop         rsi
+    pop         rdi
+  %endif
+%endif
+
+    RESTORE_GOT
+    pop         rbp
+    ret
+
+SECTION_RODATA
+align 16
+inv_zig_zag:
+  dw 0x0001, 0x0002, 0x0006, 0x0007
+  dw 0x0003, 0x0005, 0x0008, 0x000d
+  dw 0x0004, 0x0009, 0x000c, 0x000e
+  dw 0x000a, 0x000b, 0x000f, 0x0010
diff --git a/vp8/encoder/x86/quantize_sse4.asm b/vp8/encoder/x86/quantize_sse4.asm
new file mode 100644 (file)
index 0000000..70eac0c
--- /dev/null
@@ -0,0 +1,256 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license and patent
+;  grant that can be found in the LICENSE file in the root of the source
+;  tree. All contributing project authors may be found in the AUTHORS
+;  file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+%include "asm_enc_offsets.asm"
+
+
+; void vp8_regular_quantize_b_sse4 | arg
+;  (BLOCK  *b,                     |  0
+;   BLOCKD *d)                     |  1
+
+global sym(vp8_regular_quantize_b_sse4)
+sym(vp8_regular_quantize_b_sse4):
+
+%if ABI_IS_32BIT
+    push        rbp
+    mov         rbp, rsp
+    GET_GOT     rbx
+    push        rdi
+    push        rsi
+
+    ALIGN_STACK 16, rax
+    %define qcoeff      0 ; 32
+    %define stack_size 32
+    sub         rsp, stack_size
+%else
+  %ifidn __OUTPUT_FORMAT__,x64
+    SAVE_XMM 8, u
+    push        rdi
+    push        rsi
+  %endif
+%endif
+    ; end prolog
+
+%if ABI_IS_32BIT
+    mov         rdi, arg(0)                 ; BLOCK *b
+    mov         rsi, arg(1)                 ; BLOCKD *d
+%else
+  %ifidn __OUTPUT_FORMAT__,x64
+    mov         rdi, rcx                    ; BLOCK *b
+    mov         rsi, rdx                    ; BLOCKD *d
+  %else
+    ;mov         rdi, rdi                    ; BLOCK *b
+    ;mov         rsi, rsi                    ; BLOCKD *d
+  %endif
+%endif
+
+    mov         rax, [rdi + vp8_block_coeff]
+    mov         rcx, [rdi + vp8_block_zbin]
+    mov         rdx, [rdi + vp8_block_round]
+    movd        xmm7, [rdi + vp8_block_zbin_extra]
+
+    ; z
+    movdqa      xmm0, [rax]
+    movdqa      xmm1, [rax + 16]
+
+    ; duplicate zbin_oq_value
+    pshuflw     xmm7, xmm7, 0
+    punpcklwd   xmm7, xmm7
+
+    movdqa      xmm2, xmm0
+    movdqa      xmm3, xmm1
+
+    ; sz
+    psraw       xmm0, 15
+    psraw       xmm1, 15
+
+    ; (z ^ sz)
+    pxor        xmm2, xmm0
+    pxor        xmm3, xmm1
+
+    ; x = abs(z)
+    psubw       xmm2, xmm0
+    psubw       xmm3, xmm1
+
+    ; zbin
+    movdqa      xmm4, [rcx]
+    movdqa      xmm5, [rcx + 16]
+
+    ; *zbin_ptr + zbin_oq_value
+    paddw       xmm4, xmm7
+    paddw       xmm5, xmm7
+
+    movdqa      xmm6, xmm2
+    movdqa      xmm7, xmm3
+
+    ; x - (*zbin_ptr + zbin_oq_value)
+    psubw       xmm6, xmm4
+    psubw       xmm7, xmm5
+
+    ; round
+    movdqa      xmm4, [rdx]
+    movdqa      xmm5, [rdx + 16]
+
+    mov         rax, [rdi + vp8_block_quant_shift]
+    mov         rcx, [rdi + vp8_block_quant]
+    mov         rdx, [rdi + vp8_block_zrun_zbin_boost]
+
+    ; x + round
+    paddw       xmm2, xmm4
+    paddw       xmm3, xmm5
+
+    ; quant
+    movdqa      xmm4, [rcx]
+    movdqa      xmm5, [rcx + 16]
+
+    ; y = x * quant_ptr >> 16
+    pmulhw      xmm4, xmm2
+    pmulhw      xmm5, xmm3
+
+    ; y += x
+    paddw       xmm2, xmm4
+    paddw       xmm3, xmm5
+
+    pxor        xmm4, xmm4
+%if ABI_IS_32BIT
+    movdqa      [rsp + qcoeff], xmm4
+    movdqa      [rsp + qcoeff + 16], xmm4
+%else
+    pxor        xmm8, xmm8
+%endif
+
+    ; quant_shift
+    movdqa      xmm5, [rax]
+
+    ; zrun_zbin_boost
+    mov         rax, rdx
+
+%macro ZIGZAG_LOOP 5
+    ; x
+    pextrw      ecx, %4, %2
+
+    ; if (x >= zbin)
+    sub         cx, WORD PTR[rdx]           ; x - zbin
+    lea         rdx, [rdx + 2]              ; zbin_boost_ptr++
+    jl          .rq_zigzag_loop_%1          ; x < zbin
+
+    pextrw      edi, %3, %2                 ; y
+
+    ; downshift by quant_shift[rc]
+    pextrb      ecx, xmm5, %1               ; quant_shift[rc]
+    sar         edi, cl                     ; also sets Z bit
+    je          .rq_zigzag_loop_%1          ; !y
+%if ABI_IS_32BIT
+    mov         WORD PTR[rsp + qcoeff + %1 *2], di
+%else
+    pinsrw      %5, edi, %2                 ; qcoeff[rc]
+%endif
+    mov         rdx, rax                    ; reset to b->zrun_zbin_boost
+.rq_zigzag_loop_%1:
+%endmacro
+; in vp8_default_zig_zag1d order: see vp8/common/entropy.c
+ZIGZAG_LOOP  0, 0, xmm2, xmm6, xmm4
+ZIGZAG_LOOP  1, 1, xmm2, xmm6, xmm4
+ZIGZAG_LOOP  4, 4, xmm2, xmm6, xmm4
+ZIGZAG_LOOP  8, 0, xmm3, xmm7, xmm8
+ZIGZAG_LOOP  5, 5, xmm2, xmm6, xmm4
+ZIGZAG_LOOP  2, 2, xmm2, xmm6, xmm4
+ZIGZAG_LOOP  3, 3, xmm2, xmm6, xmm4
+ZIGZAG_LOOP  6, 6, xmm2, xmm6, xmm4
+ZIGZAG_LOOP  9, 1, xmm3, xmm7, xmm8
+ZIGZAG_LOOP 12, 4, xmm3, xmm7, xmm8
+ZIGZAG_LOOP 13, 5, xmm3, xmm7, xmm8
+ZIGZAG_LOOP 10, 2, xmm3, xmm7, xmm8
+ZIGZAG_LOOP  7, 7, xmm2, xmm6, xmm4
+ZIGZAG_LOOP 11, 3, xmm3, xmm7, xmm8
+ZIGZAG_LOOP 14, 6, xmm3, xmm7, xmm8
+ZIGZAG_LOOP 15, 7, xmm3, xmm7, xmm8
+
+    mov         rcx, [rsi + vp8_blockd_dequant]
+    mov         rdi, [rsi + vp8_blockd_dqcoeff]
+
+%if ABI_IS_32BIT
+    movdqa      xmm4, [rsp + qcoeff]
+    movdqa      xmm5, [rsp + qcoeff + 16]
+%else
+    %define     xmm5 xmm8
+%endif
+
+    ; y ^ sz
+    pxor        xmm4, xmm0
+    pxor        xmm5, xmm1
+    ; x = (y ^ sz) - sz
+    psubw       xmm4, xmm0
+    psubw       xmm5, xmm1
+
+    ; dequant
+    movdqa      xmm0, [rcx]
+    movdqa      xmm1, [rcx + 16]
+
+    mov         rcx, [rsi + vp8_blockd_qcoeff]
+
+    pmullw      xmm0, xmm4
+    pmullw      xmm1, xmm5
+
+    ; store qcoeff
+    movdqa      [rcx], xmm4
+    movdqa      [rcx + 16], xmm5
+
+    ; store dqcoeff
+    movdqa      [rdi], xmm0
+    movdqa      [rdi + 16], xmm1
+
+    mov         rcx, [rsi + vp8_blockd_eob]
+
+    ; select the last value (in zig_zag order) for EOB
+    pxor        xmm6, xmm6
+    pcmpeqw     xmm4, xmm6
+    pcmpeqw     xmm5, xmm6
+
+    packsswb    xmm4, xmm5
+    pshufb      xmm4, [GLOBAL(zig_zag1d)]
+    pmovmskb    edx, xmm4
+    xor         rdi, rdi
+    mov         eax, -1
+    xor         dx, ax
+    bsr         eax, edx
+    sub         edi, edx
+    sar         edi, 31
+    add         eax, 1
+    and         eax, edi
+
+    mov         BYTE PTR [rcx], al          ; store eob
+
+    ; begin epilog
+%if ABI_IS_32BIT
+    add         rsp, stack_size
+    pop         rsp
+
+    pop         rsi
+    pop         rdi
+    RESTORE_GOT
+    pop         rbp
+%else
+  %undef xmm5
+  %ifidn __OUTPUT_FORMAT__,x64
+    pop         rsi
+    pop         rdi
+    RESTORE_XMM
+  %endif
+%endif
+
+    ret
+
+SECTION_RODATA
+align 16
+; vp8/common/entropy.c: vp8_default_zig_zag1d
+zig_zag1d:
+    db 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
diff --git a/vp8/encoder/x86/quantize_ssse3.asm b/vp8/encoder/x86/quantize_ssse3.asm
new file mode 100644 (file)
index 0000000..e698e90
--- /dev/null
@@ -0,0 +1,138 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license and patent
+;  grant that can be found in the LICENSE file in the root of the source
+;  tree. All contributing project authors may be found in the AUTHORS
+;  file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+%include "asm_enc_offsets.asm"
+
+
+; void vp8_fast_quantize_b_ssse3 | arg
+;  (BLOCK  *b,                   |  0
+;   BLOCKD *d)                   |  1
+;
+
+global sym(vp8_fast_quantize_b_ssse3)
+sym(vp8_fast_quantize_b_ssse3):
+    push        rbp
+    mov         rbp, rsp
+    GET_GOT     rbx
+
+%if ABI_IS_32BIT
+    push        rdi
+    push        rsi
+%else
+  %ifidn __OUTPUT_FORMAT__,x64
+    push        rdi
+    push        rsi
+  %endif
+%endif
+    ; end prolog
+
+%if ABI_IS_32BIT
+    mov         rdi, arg(0)                 ; BLOCK *b
+    mov         rsi, arg(1)                 ; BLOCKD *d
+%else
+  %ifidn __OUTPUT_FORMAT__,x64
+    mov         rdi, rcx                    ; BLOCK *b
+    mov         rsi, rdx                    ; BLOCKD *d
+  %else
+    ;mov         rdi, rdi                    ; BLOCK *b
+    ;mov         rsi, rsi                    ; BLOCKD *d
+  %endif
+%endif
+
+    mov         rax, [rdi + vp8_block_coeff]
+    mov         rcx, [rdi + vp8_block_round]
+    mov         rdx, [rdi + vp8_block_quant_fast]
+
+    ; coeff
+    movdqa      xmm0, [rax]
+    movdqa      xmm4, [rax + 16]
+
+    ; round
+    movdqa      xmm2, [rcx]
+    movdqa      xmm3, [rcx + 16]
+
+    movdqa      xmm1, xmm0
+    movdqa      xmm5, xmm4
+
+    ; sz = z >> 15
+    psraw       xmm0, 15
+    psraw       xmm4, 15
+
+    pabsw       xmm1, xmm1
+    pabsw       xmm5, xmm5
+
+    paddw       xmm1, xmm2
+    paddw       xmm5, xmm3
+
+    ; quant_fast
+    pmulhw      xmm1, [rdx]
+    pmulhw      xmm5, [rdx + 16]
+
+    mov         rax, [rsi + vp8_blockd_qcoeff]
+    mov         rdi, [rsi + vp8_blockd_dequant]
+    mov         rcx, [rsi + vp8_blockd_dqcoeff]
+
+    movdqa      xmm2, xmm1                  ;store y for getting eob
+    movdqa      xmm3, xmm5
+
+    pxor        xmm1, xmm0
+    pxor        xmm5, xmm4
+    psubw       xmm1, xmm0
+    psubw       xmm5, xmm4
+
+    movdqa      [rax], xmm1
+    movdqa      [rax + 16], xmm5
+
+    movdqa      xmm0, [rdi]
+    movdqa      xmm4, [rdi + 16]
+
+    pmullw      xmm0, xmm1
+    pmullw      xmm4, xmm5
+    pxor        xmm1, xmm1
+
+    pcmpgtw     xmm2, xmm1                  ;calculate eob
+    pcmpgtw     xmm3, xmm1
+    packsswb    xmm2, xmm3
+    pshufb      xmm2, [GLOBAL(zz_shuf)]
+
+    pmovmskb    edx, xmm2
+
+    movdqa      [rcx], xmm0                 ;store dqcoeff
+    movdqa      [rcx + 16], xmm4            ;store dqcoeff
+    mov         rcx, [rsi + vp8_blockd_eob]
+
+    bsr         eax, edx                    ;count 0
+    add         eax, 1
+
+    cmp         edx, 0                      ;if all 0, eob=0
+    cmove       eax, edx
+
+    mov         BYTE PTR [rcx], al          ;store eob
+
+    ; begin epilog
+%if ABI_IS_32BIT
+    pop         rsi
+    pop         rdi
+%else
+  %ifidn __OUTPUT_FORMAT__,x64
+    pop         rsi
+    pop         rdi
+  %endif
+%endif
+
+    RESTORE_GOT
+    pop         rbp
+    ret
+
+SECTION_RODATA
+align 16
+zz_shuf:
+    db 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
diff --git a/vp8/encoder/x86/ssim_opt.asm b/vp8/encoder/x86/ssim_opt.asm
new file mode 100644 (file)
index 0000000..c6db3d1
--- /dev/null
@@ -0,0 +1,216 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+%include "vpx_ports/x86_abi_support.asm"
+
+; tabulate_ssim - sums sum_s,sum_r,sum_sq_s,sum_sq_r, sum_sxr
+%macro TABULATE_SSIM 0
+        paddusw         xmm15, xmm3  ; sum_s
+        paddusw         xmm14, xmm4  ; sum_r
+        movdqa          xmm1, xmm3
+        pmaddwd         xmm1, xmm1
+        paddd           xmm13, xmm1 ; sum_sq_s
+        movdqa          xmm2, xmm4
+        pmaddwd         xmm2, xmm2
+        paddd           xmm12, xmm2 ; sum_sq_r
+        pmaddwd         xmm3, xmm4
+        paddd           xmm11, xmm3  ; sum_sxr
+%endmacro
+
+; Sum across the register %1 starting with q words
+%macro SUM_ACROSS_Q 1
+        movdqa          xmm2,%1
+        punpckldq       %1,xmm0
+        punpckhdq       xmm2,xmm0
+        paddq           %1,xmm2
+        movdqa          xmm2,%1
+        punpcklqdq      %1,xmm0
+        punpckhqdq      xmm2,xmm0
+        paddq           %1,xmm2
+%endmacro
+
+; Sum across the register %1 starting with q words
+%macro SUM_ACROSS_W 1
+        movdqa          xmm1, %1
+        punpcklwd       %1,xmm0
+        punpckhwd       xmm1,xmm0
+        paddd           %1, xmm1
+        SUM_ACROSS_Q    %1
+%endmacro
+;void ssim_parms_sse2(
+;    unsigned char *s,
+;    int sp,
+;    unsigned char *r,
+;    int rp
+;    unsigned long *sum_s,
+;    unsigned long *sum_r,
+;    unsigned long *sum_sq_s,
+;    unsigned long *sum_sq_r,
+;    unsigned long *sum_sxr);
+;
+; TODO: Use parm passing through structure, probably don't need the pxors
+; ( calling app will initialize to 0 ) could easily fit everything in sse2
+; without too much hastle, and can probably do better estimates with psadw
+; or pavgb At this point this is just meant to be first pass for calculating
+; all the parms needed for 16x16 ssim so we can play with dssim as distortion
+; in mode selection code.
+global sym(vp8_ssim_parms_16x16_sse2)
+sym(vp8_ssim_parms_16x16_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 9
+    SAVE_XMM 15
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    mov             rsi,        arg(0) ;s
+    mov             rcx,        arg(1) ;sp
+    mov             rdi,        arg(2) ;r
+    mov             rax,        arg(3) ;rp
+
+    pxor            xmm0, xmm0
+    pxor            xmm15,xmm15  ;sum_s
+    pxor            xmm14,xmm14  ;sum_r
+    pxor            xmm13,xmm13  ;sum_sq_s
+    pxor            xmm12,xmm12  ;sum_sq_r
+    pxor            xmm11,xmm11  ;sum_sxr
+
+    mov             rdx, 16      ;row counter
+.NextRow:
+
+    ;grab source and reference pixels
+    movdqu          xmm5, [rsi]
+    movdqu          xmm6, [rdi]
+    movdqa          xmm3, xmm5
+    movdqa          xmm4, xmm6
+    punpckhbw       xmm3, xmm0 ; high_s
+    punpckhbw       xmm4, xmm0 ; high_r
+
+    TABULATE_SSIM
+
+    movdqa          xmm3, xmm5
+    movdqa          xmm4, xmm6
+    punpcklbw       xmm3, xmm0 ; low_s
+    punpcklbw       xmm4, xmm0 ; low_r
+
+    TABULATE_SSIM
+
+    add             rsi, rcx   ; next s row
+    add             rdi, rax   ; next r row
+
+    dec             rdx        ; counter
+    jnz .NextRow
+
+    SUM_ACROSS_W    xmm15
+    SUM_ACROSS_W    xmm14
+    SUM_ACROSS_Q    xmm13
+    SUM_ACROSS_Q    xmm12
+    SUM_ACROSS_Q    xmm11
+
+    mov             rdi,arg(4)
+    movd            [rdi], xmm15;
+    mov             rdi,arg(5)
+    movd            [rdi], xmm14;
+    mov             rdi,arg(6)
+    movd            [rdi], xmm13;
+    mov             rdi,arg(7)
+    movd            [rdi], xmm12;
+    mov             rdi,arg(8)
+    movd            [rdi], xmm11;
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void ssim_parms_sse2(
+;    unsigned char *s,
+;    int sp,
+;    unsigned char *r,
+;    int rp
+;    unsigned long *sum_s,
+;    unsigned long *sum_r,
+;    unsigned long *sum_sq_s,
+;    unsigned long *sum_sq_r,
+;    unsigned long *sum_sxr);
+;
+; TODO: Use parm passing through structure, probably don't need the pxors
+; ( calling app will initialize to 0 ) could easily fit everything in sse2
+; without too much hastle, and can probably do better estimates with psadw
+; or pavgb At this point this is just meant to be first pass for calculating
+; all the parms needed for 16x16 ssim so we can play with dssim as distortion
+; in mode selection code.
+global sym(vp8_ssim_parms_8x8_sse2)
+sym(vp8_ssim_parms_8x8_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 9
+    SAVE_XMM 15
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    mov             rsi,        arg(0) ;s
+    mov             rcx,        arg(1) ;sp
+    mov             rdi,        arg(2) ;r
+    mov             rax,        arg(3) ;rp
+
+    pxor            xmm0, xmm0
+    pxor            xmm15,xmm15  ;sum_s
+    pxor            xmm14,xmm14  ;sum_r
+    pxor            xmm13,xmm13  ;sum_sq_s
+    pxor            xmm12,xmm12  ;sum_sq_r
+    pxor            xmm11,xmm11  ;sum_sxr
+
+    mov             rdx, 8      ;row counter
+.NextRow:
+
+    ;grab source and reference pixels
+    movq            xmm3, [rsi]
+    movq            xmm4, [rdi]
+    punpcklbw       xmm3, xmm0 ; low_s
+    punpcklbw       xmm4, xmm0 ; low_r
+
+    TABULATE_SSIM
+
+    add             rsi, rcx   ; next s row
+    add             rdi, rax   ; next r row
+
+    dec             rdx        ; counter
+    jnz .NextRow
+
+    SUM_ACROSS_W    xmm15
+    SUM_ACROSS_W    xmm14
+    SUM_ACROSS_Q    xmm13
+    SUM_ACROSS_Q    xmm12
+    SUM_ACROSS_Q    xmm11
+
+    mov             rdi,arg(4)
+    movd            [rdi], xmm15;
+    mov             rdi,arg(5)
+    movd            [rdi], xmm14;
+    mov             rdi,arg(6)
+    movd            [rdi], xmm13;
+    mov             rdi,arg(7)
+    movd            [rdi], xmm12;
+    mov             rdi,arg(8)
+    movd            [rdi], xmm11;
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
diff --git a/vp8/encoder/x86/subtract_mmx.asm b/vp8/encoder/x86/subtract_mmx.asm
new file mode 100644 (file)
index 0000000..75e8aa3
--- /dev/null
@@ -0,0 +1,223 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;void vp8_subtract_b_mmx_impl(unsigned char *z,  int src_stride,
+;                            short *diff, unsigned char *Predictor,
+;                            int pitch);
+global sym(vp8_subtract_b_mmx_impl)
+sym(vp8_subtract_b_mmx_impl):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push rsi
+    push rdi
+    ; end prolog
+
+
+        mov     rdi,        arg(2) ;diff
+        mov     rax,        arg(3) ;Predictor
+        mov     rsi,        arg(0) ;z
+        movsxd  rdx,        dword ptr arg(1);src_stride;
+        movsxd  rcx,        dword ptr arg(4);pitch
+        pxor    mm7,        mm7
+
+        movd    mm0,        [rsi]
+        movd    mm1,        [rax]
+        punpcklbw   mm0,    mm7
+        punpcklbw   mm1,    mm7
+        psubw   mm0,        mm1
+        movq    [rdi],      mm0
+
+
+        movd    mm0,        [rsi+rdx]
+        movd    mm1,        [rax+rcx]
+        punpcklbw   mm0,    mm7
+        punpcklbw   mm1,    mm7
+        psubw   mm0,        mm1
+        movq    [rdi+rcx*2],mm0
+
+
+        movd    mm0,        [rsi+rdx*2]
+        movd    mm1,        [rax+rcx*2]
+        punpcklbw   mm0,    mm7
+        punpcklbw   mm1,    mm7
+        psubw   mm0,        mm1
+        movq    [rdi+rcx*4],        mm0
+
+        lea     rsi,        [rsi+rdx*2]
+        lea     rcx,        [rcx+rcx*2]
+
+
+
+        movd    mm0,        [rsi+rdx]
+        movd    mm1,        [rax+rcx]
+        punpcklbw   mm0,    mm7
+        punpcklbw   mm1,    mm7
+        psubw   mm0,        mm1
+        movq    [rdi+rcx*2],        mm0
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_subtract_mby_mmx(short *diff, unsigned char *src, int src_stride,
+;unsigned char *pred, int pred_stride)
+global sym(vp8_subtract_mby_mmx)
+sym(vp8_subtract_mby_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push rsi
+    push rdi
+    ; end prolog
+
+    mov         rdi,        arg(0)          ;diff
+    mov         rsi,        arg(1)          ;src
+    movsxd      rdx,        dword ptr arg(2);src_stride
+    mov         rax,        arg(3)          ;pred
+    push        rbx
+    movsxd      rbx,        dword ptr arg(4);pred_stride
+
+    pxor        mm0,        mm0
+    mov         rcx,        16
+
+
+.submby_loop:
+    movq        mm1,        [rsi]
+    movq        mm3,        [rax]
+
+    movq        mm2,        mm1
+    movq        mm4,        mm3
+
+    punpcklbw   mm1,        mm0
+    punpcklbw   mm3,        mm0
+
+    punpckhbw   mm2,        mm0
+    punpckhbw   mm4,        mm0
+
+    psubw       mm1,        mm3
+    psubw       mm2,        mm4
+
+    movq        [rdi],      mm1
+    movq        [rdi+8],    mm2
+
+    movq        mm1,        [rsi+8]
+    movq        mm3,        [rax+8]
+
+    movq        mm2,        mm1
+    movq        mm4,        mm3
+
+    punpcklbw   mm1,        mm0
+    punpcklbw   mm3,        mm0
+
+    punpckhbw   mm2,        mm0
+    punpckhbw   mm4,        mm0
+
+    psubw       mm1,        mm3
+    psubw       mm2,        mm4
+
+    movq        [rdi+16],   mm1
+    movq        [rdi+24],   mm2
+    add         rdi,        32
+    lea         rax,        [rax+rbx]
+    lea         rsi,        [rsi+rdx]
+    dec         rcx
+    jnz         .submby_loop
+
+    pop rbx
+    pop rdi
+    pop rsi
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;vp8_subtract_mbuv_mmx(short *diff, unsigned char *usrc, unsigned char *vsrc,
+;                         int src_stride, unsigned char *upred,
+;                         unsigned char *vpred, int pred_stride)
+
+global sym(vp8_subtract_mbuv_mmx)
+sym(vp8_subtract_mbuv_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    push rsi
+    push rdi
+    ; end prolog
+
+    mov         rdi,        arg(0)          ;diff
+    mov         rsi,        arg(1)          ;usrc
+    movsxd      rdx,        dword ptr arg(3);src_stride;
+    mov         rax,        arg(4)          ;upred
+    add         rdi,        256*2           ;diff = diff + 256 (shorts)
+    mov         rcx,        8
+    push        rbx
+    movsxd      rbx,        dword ptr arg(6);pred_stride
+
+    pxor        mm7,        mm7
+
+.submbu_loop:
+    movq        mm0,        [rsi]
+    movq        mm1,        [rax]
+    movq        mm3,        mm0
+    movq        mm4,        mm1
+    punpcklbw   mm0,        mm7
+    punpcklbw   mm1,        mm7
+    punpckhbw   mm3,        mm7
+    punpckhbw   mm4,        mm7
+    psubw       mm0,        mm1
+    psubw       mm3,        mm4
+    movq        [rdi],      mm0
+    movq        [rdi+8],    mm3
+    add         rdi, 16
+    add         rsi, rdx
+    add         rax, rbx
+
+    dec         rcx
+    jnz         .submbu_loop
+
+    mov         rsi,        arg(2)          ;vsrc
+    mov         rax,        arg(5)          ;vpred
+    mov         rcx,        8
+
+.submbv_loop:
+    movq        mm0,        [rsi]
+    movq        mm1,        [rax]
+    movq        mm3,        mm0
+    movq        mm4,        mm1
+    punpcklbw   mm0,        mm7
+    punpcklbw   mm1,        mm7
+    punpckhbw   mm3,        mm7
+    punpckhbw   mm4,        mm7
+    psubw       mm0,        mm1
+    psubw       mm3,        mm4
+    movq        [rdi],      mm0
+    movq        [rdi+8],    mm3
+    add         rdi, 16
+    add         rsi, rdx
+    add         rax, rbx
+
+    dec         rcx
+    jnz         .submbv_loop
+
+    pop         rbx
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
diff --git a/vp8/encoder/x86/subtract_sse2.asm b/vp8/encoder/x86/subtract_sse2.asm
new file mode 100644 (file)
index 0000000..008e9c7
--- /dev/null
@@ -0,0 +1,245 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;void vp8_subtract_b_sse2_impl(unsigned char *z,  int src_stride,
+;                            short *diff, unsigned char *Predictor,
+;                            int pitch);
+global sym(vp8_subtract_b_sse2_impl)
+sym(vp8_subtract_b_sse2_impl):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    ; end prolog
+
+        mov     rdi,        arg(2) ;diff
+        mov     rax,        arg(3) ;Predictor
+        mov     rsi,        arg(0) ;z
+        movsxd  rdx,        dword ptr arg(1);src_stride;
+        movsxd  rcx,        dword ptr arg(4);pitch
+        pxor    mm7,        mm7
+
+        movd    mm0,        [rsi]
+        movd    mm1,        [rax]
+        punpcklbw   mm0,    mm7
+        punpcklbw   mm1,    mm7
+        psubw   mm0,        mm1
+        movq    MMWORD PTR [rdi],      mm0
+
+        movd    mm0,        [rsi+rdx]
+        movd    mm1,        [rax+rcx]
+        punpcklbw   mm0,    mm7
+        punpcklbw   mm1,    mm7
+        psubw   mm0,        mm1
+        movq    MMWORD PTR [rdi+rcx*2], mm0
+
+        movd    mm0,        [rsi+rdx*2]
+        movd    mm1,        [rax+rcx*2]
+        punpcklbw   mm0,    mm7
+        punpcklbw   mm1,    mm7
+        psubw   mm0,        mm1
+        movq    MMWORD PTR [rdi+rcx*4], mm0
+
+        lea     rsi,        [rsi+rdx*2]
+        lea     rcx,        [rcx+rcx*2]
+
+        movd    mm0,        [rsi+rdx]
+        movd    mm1,        [rax+rcx]
+        punpcklbw   mm0,    mm7
+        punpcklbw   mm1,    mm7
+        psubw   mm0,        mm1
+        movq    MMWORD PTR [rdi+rcx*2], mm0
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_subtract_mby_sse2(short *diff, unsigned char *src, int src_stride,
+;unsigned char *pred, int pred_stride)
+global sym(vp8_subtract_mby_sse2)
+sym(vp8_subtract_mby_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    ; end prolog
+
+    mov         rdi,        arg(0)          ;diff
+    mov         rsi,        arg(1)          ;src
+    movsxd      rdx,        dword ptr arg(2);src_stride
+    mov         rax,        arg(3)          ;pred
+    movdqa      xmm4,       [GLOBAL(t80)]
+    push        rbx
+    mov         rcx,        8               ; do two lines at one time
+    movsxd      rbx,        dword ptr arg(4);pred_stride
+
+.submby_loop:
+    movdqa      xmm0,       [rsi]           ; src
+    movdqa      xmm1,       [rax]           ; pred
+
+    movdqa      xmm2,       xmm0
+    psubb       xmm0,       xmm1
+
+    pxor        xmm1,       xmm4            ;convert to signed values
+    pxor        xmm2,       xmm4
+    pcmpgtb     xmm1,       xmm2            ; obtain sign information
+
+    movdqa      xmm2,       xmm0
+    punpcklbw   xmm0,       xmm1            ; put sign back to subtraction
+    punpckhbw   xmm2,       xmm1            ; put sign back to subtraction
+
+    movdqa      xmm3,       [rsi + rdx]
+    movdqa      xmm5,       [rax + rbx]
+
+    lea         rsi,        [rsi+rdx*2]
+    lea         rax,        [rax+rbx*2]
+
+    movdqa      [rdi],      xmm0
+    movdqa      [rdi +16],  xmm2
+
+    movdqa      xmm1,       xmm3
+    psubb       xmm3,       xmm5
+
+    pxor        xmm5,       xmm4            ;convert to signed values
+    pxor        xmm1,       xmm4
+    pcmpgtb     xmm5,       xmm1            ; obtain sign information
+
+    movdqa      xmm1,       xmm3
+    punpcklbw   xmm3,       xmm5            ; put sign back to subtraction
+    punpckhbw   xmm1,       xmm5            ; put sign back to subtraction
+
+    movdqa      [rdi +32],  xmm3
+    movdqa      [rdi +48],  xmm1
+
+    add         rdi,        64
+    dec         rcx
+    jnz         .submby_loop
+
+    pop rbx
+    pop rdi
+    pop rsi
+    ; begin epilog
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;vp8_subtract_mbuv_sse2(short *diff, unsigned char *usrc, unsigned char *vsrc,
+;                         int src_stride, unsigned char *upred,
+;                         unsigned char *vpred, int pred_stride)
+global sym(vp8_subtract_mbuv_sse2)
+sym(vp8_subtract_mbuv_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    ; end prolog
+
+    movdqa      xmm4,       [GLOBAL(t80)]
+    mov         rdi,        arg(0)          ;diff
+    mov         rsi,        arg(1)          ;usrc
+    movsxd      rdx,        dword ptr arg(3);src_stride;
+    mov         rax,        arg(4)          ;upred
+    add         rdi,        256*2           ;diff = diff + 256 (shorts)
+    mov         rcx,        4
+    push        rbx
+    movsxd      rbx,        dword ptr arg(6);pred_stride
+
+    ;u
+.submbu_loop:
+    movq        xmm0,       [rsi]           ; src
+    movq        xmm2,       [rsi+rdx]       ; src -- next line
+    movq        xmm1,       [rax]           ; pred
+    movq        xmm3,       [rax+rbx]       ; pred -- next line
+    lea         rsi,        [rsi + rdx*2]
+    lea         rax,        [rax + rbx*2]
+
+    punpcklqdq  xmm0,       xmm2
+    punpcklqdq  xmm1,       xmm3
+
+    movdqa      xmm2,       xmm0
+    psubb       xmm0,       xmm1            ; subtraction with sign missed
+
+    pxor        xmm1,       xmm4            ;convert to signed values
+    pxor        xmm2,       xmm4
+    pcmpgtb     xmm1,       xmm2            ; obtain sign information
+
+    movdqa      xmm2,       xmm0
+    movdqa      xmm3,       xmm1
+    punpcklbw   xmm0,       xmm1            ; put sign back to subtraction
+    punpckhbw   xmm2,       xmm3            ; put sign back to subtraction
+
+    movdqa      [rdi],      xmm0            ; store difference
+    movdqa      [rdi +16],  xmm2            ; store difference
+    add         rdi,        32
+    sub         rcx, 1
+    jnz         .submbu_loop
+
+    mov         rsi,        arg(2)          ;vsrc
+    mov         rax,        arg(5)          ;vpred
+    mov         rcx,        4
+
+    ;v
+.submbv_loop:
+    movq        xmm0,       [rsi]           ; src
+    movq        xmm2,       [rsi+rdx]       ; src -- next line
+    movq        xmm1,       [rax]           ; pred
+    movq        xmm3,       [rax+rbx]       ; pred -- next line
+    lea         rsi,        [rsi + rdx*2]
+    lea         rax,        [rax + rbx*2]
+
+    punpcklqdq  xmm0,       xmm2
+    punpcklqdq  xmm1,       xmm3
+
+    movdqa      xmm2,       xmm0
+    psubb       xmm0,       xmm1            ; subtraction with sign missed
+
+    pxor        xmm1,       xmm4            ;convert to signed values
+    pxor        xmm2,       xmm4
+    pcmpgtb     xmm1,       xmm2            ; obtain sign information
+
+    movdqa      xmm2,       xmm0
+    movdqa      xmm3,       xmm1
+    punpcklbw   xmm0,       xmm1            ; put sign back to subtraction
+    punpckhbw   xmm2,       xmm3            ; put sign back to subtraction
+
+    movdqa      [rdi],      xmm0            ; store difference
+    movdqa      [rdi +16],  xmm2            ; store difference
+    add         rdi,        32
+    sub         rcx, 1
+    jnz         .submbv_loop
+
+    pop         rbx
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+SECTION_RODATA
+align 16
+t80:
+    times 16 db 0x80
diff --git a/vp8/encoder/x86/temporal_filter_apply_sse2.asm b/vp8/encoder/x86/temporal_filter_apply_sse2.asm
new file mode 100644 (file)
index 0000000..b97c694
--- /dev/null
@@ -0,0 +1,207 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+; void vp8_temporal_filter_apply_sse2 | arg
+;  (unsigned char  *frame1,           |  0
+;   unsigned int    stride,           |  1
+;   unsigned char  *frame2,           |  2
+;   unsigned int    block_size,       |  3
+;   int             strength,         |  4
+;   int             filter_weight,    |  5
+;   unsigned int   *accumulator,      |  6
+;   unsigned short *count)            |  7
+global sym(vp8_temporal_filter_apply_sse2)
+sym(vp8_temporal_filter_apply_sse2):
+
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 8
+    SAVE_XMM 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ALIGN_STACK 16, rax
+    %define block_size    0
+    %define strength      16
+    %define filter_weight 32
+    %define rounding_bit  48
+    %define rbp_backup    64
+    %define stack_size    80
+    sub         rsp,           stack_size
+    mov         [rsp + rbp_backup], rbp
+    ; end prolog
+
+        mov         rdx,            arg(3)
+        mov         [rsp + block_size], rdx
+        movd        xmm6,            arg(4)
+        movdqa      [rsp + strength], xmm6 ; where strength is used, all 16 bytes are read
+
+        ; calculate the rounding bit outside the loop
+        ; 0x8000 >> (16 - strength)
+        mov         rdx,            16
+        sub         rdx,            arg(4) ; 16 - strength
+        movd        xmm4,           rdx    ; can't use rdx w/ shift
+        movdqa      xmm5,           [GLOBAL(_const_top_bit)]
+        psrlw       xmm5,           xmm4
+        movdqa      [rsp + rounding_bit], xmm5
+
+        mov         rsi,            arg(0) ; src/frame1
+        mov         rdx,            arg(2) ; predictor frame
+        mov         rdi,            arg(6) ; accumulator
+        mov         rax,            arg(7) ; count
+
+        ; dup the filter weight and store for later
+        movd        xmm0,           arg(5) ; filter_weight
+        pshuflw     xmm0,           xmm0, 0
+        punpcklwd   xmm0,           xmm0
+        movdqa      [rsp + filter_weight], xmm0
+
+        mov         rbp,            arg(1) ; stride
+        pxor        xmm7,           xmm7   ; zero for extraction
+
+        lea         rcx,            [rdx + 16*16*1]
+        cmp         dword ptr [rsp + block_size], 8
+        jne         .temporal_filter_apply_load_16
+        lea         rcx,            [rdx + 8*8*1]
+
+.temporal_filter_apply_load_8:
+        movq        xmm0,           [rsi]  ; first row
+        lea         rsi,            [rsi + rbp] ; += stride
+        punpcklbw   xmm0,           xmm7   ; src[ 0- 7]
+        movq        xmm1,           [rsi]  ; second row
+        lea         rsi,            [rsi + rbp] ; += stride
+        punpcklbw   xmm1,           xmm7   ; src[ 8-15]
+        jmp         .temporal_filter_apply_load_finished
+
+.temporal_filter_apply_load_16:
+        movdqa      xmm0,           [rsi]  ; src (frame1)
+        lea         rsi,            [rsi + rbp] ; += stride
+        movdqa      xmm1,           xmm0
+        punpcklbw   xmm0,           xmm7   ; src[ 0- 7]
+        punpckhbw   xmm1,           xmm7   ; src[ 8-15]
+
+.temporal_filter_apply_load_finished:
+        movdqa      xmm2,           [rdx]  ; predictor (frame2)
+        movdqa      xmm3,           xmm2
+        punpcklbw   xmm2,           xmm7   ; pred[ 0- 7]
+        punpckhbw   xmm3,           xmm7   ; pred[ 8-15]
+
+        ; modifier = src_byte - pixel_value
+        psubw       xmm0,           xmm2   ; src - pred[ 0- 7]
+        psubw       xmm1,           xmm3   ; src - pred[ 8-15]
+
+        ; modifier *= modifier
+        pmullw      xmm0,           xmm0   ; modifer[ 0- 7]^2
+        pmullw      xmm1,           xmm1   ; modifer[ 8-15]^2
+
+        ; modifier *= 3
+        pmullw      xmm0,           [GLOBAL(_const_3w)]
+        pmullw      xmm1,           [GLOBAL(_const_3w)]
+
+        ; modifer += 0x8000 >> (16 - strength)
+        paddw       xmm0,           [rsp + rounding_bit]
+        paddw       xmm1,           [rsp + rounding_bit]
+
+        ; modifier >>= strength
+        psrlw       xmm0,           [rsp + strength]
+        psrlw       xmm1,           [rsp + strength]
+
+        ; modifier = 16 - modifier
+        ; saturation takes care of modifier > 16
+        movdqa      xmm3,           [GLOBAL(_const_16w)]
+        movdqa      xmm2,           [GLOBAL(_const_16w)]
+        psubusw     xmm3,           xmm1
+        psubusw     xmm2,           xmm0
+
+        ; modifier *= filter_weight
+        pmullw      xmm2,           [rsp + filter_weight]
+        pmullw      xmm3,           [rsp + filter_weight]
+
+        ; count
+        movdqa      xmm4,           [rax]
+        movdqa      xmm5,           [rax+16]
+        ; += modifier
+        paddw       xmm4,           xmm2
+        paddw       xmm5,           xmm3
+        ; write back
+        movdqa      [rax],          xmm4
+        movdqa      [rax+16],       xmm5
+        lea         rax,            [rax + 16*2] ; count += 16*(sizeof(short))
+
+        ; load and extract the predictor up to shorts
+        pxor        xmm7,           xmm7
+        movdqa      xmm0,           [rdx]
+        lea         rdx,            [rdx + 16*1] ; pred += 16*(sizeof(char))
+        movdqa      xmm1,           xmm0
+        punpcklbw   xmm0,           xmm7   ; pred[ 0- 7]
+        punpckhbw   xmm1,           xmm7   ; pred[ 8-15]
+
+        ; modifier *= pixel_value
+        pmullw      xmm0,           xmm2
+        pmullw      xmm1,           xmm3
+
+        ; expand to double words
+        movdqa      xmm2,           xmm0
+        punpcklwd   xmm0,           xmm7   ; [ 0- 3]
+        punpckhwd   xmm2,           xmm7   ; [ 4- 7]
+        movdqa      xmm3,           xmm1
+        punpcklwd   xmm1,           xmm7   ; [ 8-11]
+        punpckhwd   xmm3,           xmm7   ; [12-15]
+
+        ; accumulator
+        movdqa      xmm4,           [rdi]
+        movdqa      xmm5,           [rdi+16]
+        movdqa      xmm6,           [rdi+32]
+        movdqa      xmm7,           [rdi+48]
+        ; += modifier
+        paddd       xmm4,           xmm0
+        paddd       xmm5,           xmm2
+        paddd       xmm6,           xmm1
+        paddd       xmm7,           xmm3
+        ; write back
+        movdqa      [rdi],          xmm4
+        movdqa      [rdi+16],       xmm5
+        movdqa      [rdi+32],       xmm6
+        movdqa      [rdi+48],       xmm7
+        lea         rdi,            [rdi + 16*4] ; accumulator += 16*(sizeof(int))
+
+        cmp         rdx,            rcx
+        je          .temporal_filter_apply_epilog
+        pxor        xmm7,           xmm7   ; zero for extraction
+        cmp         dword ptr [rsp + block_size], 16
+        je          .temporal_filter_apply_load_16
+        jmp         .temporal_filter_apply_load_8
+
+.temporal_filter_apply_epilog:
+    ; begin epilog
+    mov         rbp,            [rsp + rbp_backup]
+    add         rsp,            stack_size
+    pop         rsp
+    pop         rdi
+    pop         rsi
+    RESTORE_GOT
+    RESTORE_XMM
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+SECTION_RODATA
+align 16
+_const_3w:
+    times 8 dw 3
+align 16
+_const_top_bit:
+    times 8 dw 1<<15
+align 16
+_const_16w
+    times 8 dw 16
diff --git a/vp8/encoder/x86/vp8_enc_stubs_mmx.c b/vp8/encoder/x86/vp8_enc_stubs_mmx.c
new file mode 100644 (file)
index 0000000..da25f52
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "vpx_ports/x86.h"
+#include "vp8/encoder/block.h"
+
+void vp8_short_fdct4x4_mmx(short *input, short *output, int pitch);
+void vp8_short_fdct8x4_mmx(short *input, short *output, int pitch)
+{
+    vp8_short_fdct4x4_mmx(input,   output,    pitch);
+    vp8_short_fdct4x4_mmx(input + 4, output + 16, pitch);
+}
+
+int vp8_fast_quantize_b_impl_mmx(short *coeff_ptr, short *zbin_ptr,
+                                 short *qcoeff_ptr, short *dequant_ptr,
+                                 const short *scan_mask, short *round_ptr,
+                                 short *quant_ptr, short *dqcoeff_ptr);
+void vp8_fast_quantize_b_mmx(BLOCK *b, BLOCKD *d)
+{
+    const short *scan_mask   = vp8_default_zig_zag_mask;
+    short *coeff_ptr   = b->coeff;
+    short *zbin_ptr    = b->zbin;
+    short *round_ptr   = b->round;
+    short *quant_ptr   = b->quant_fast;
+    short *qcoeff_ptr  = d->qcoeff;
+    short *dqcoeff_ptr = d->dqcoeff;
+    short *dequant_ptr = d->dequant;
+
+    *d->eob = (char)vp8_fast_quantize_b_impl_mmx(
+                                                 coeff_ptr,
+                                                 zbin_ptr,
+                                                 qcoeff_ptr,
+                                                 dequant_ptr,
+                                                 scan_mask,
+
+                                                 round_ptr,
+                                                 quant_ptr,
+                                                 dqcoeff_ptr
+                                                 );
+}
+
+int vp8_mbblock_error_mmx_impl(short *coeff_ptr, short *dcoef_ptr, int dc);
+int vp8_mbblock_error_mmx(MACROBLOCK *mb, int dc)
+{
+    short *coeff_ptr =  mb->block[0].coeff;
+    short *dcoef_ptr =  mb->e_mbd.block[0].dqcoeff;
+    return vp8_mbblock_error_mmx_impl(coeff_ptr, dcoef_ptr, dc);
+}
+
+int vp8_mbuverror_mmx_impl(short *s_ptr, short *d_ptr);
+int vp8_mbuverror_mmx(MACROBLOCK *mb)
+{
+    short *s_ptr = &mb->coeff[256];
+    short *d_ptr = &mb->e_mbd.dqcoeff[256];
+    return vp8_mbuverror_mmx_impl(s_ptr, d_ptr);
+}
+
+void vp8_subtract_b_mmx_impl(unsigned char *z,  int src_stride,
+                             short *diff, unsigned char *predictor,
+                             int pitch);
+void vp8_subtract_b_mmx(BLOCK *be, BLOCKD *bd, int pitch)
+{
+    unsigned char *z = *(be->base_src) + be->src;
+    unsigned int  src_stride = be->src_stride;
+    short *diff = &be->src_diff[0];
+    unsigned char *predictor = &bd->predictor[0];
+    vp8_subtract_b_mmx_impl(z, src_stride, diff, predictor, pitch);
+}
diff --git a/vp8/encoder/x86/vp8_enc_stubs_sse2.c b/vp8/encoder/x86/vp8_enc_stubs_sse2.c
new file mode 100644 (file)
index 0000000..68db815
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+#include "vpx_ports/x86.h"
+#include "vp8/encoder/block.h"
+
+int vp8_mbblock_error_xmm_impl(short *coeff_ptr, short *dcoef_ptr, int dc);
+int vp8_mbblock_error_xmm(MACROBLOCK *mb, int dc)
+{
+    short *coeff_ptr =  mb->block[0].coeff;
+    short *dcoef_ptr =  mb->e_mbd.block[0].dqcoeff;
+    return vp8_mbblock_error_xmm_impl(coeff_ptr, dcoef_ptr, dc);
+}
+
+int vp8_mbuverror_xmm_impl(short *s_ptr, short *d_ptr);
+int vp8_mbuverror_xmm(MACROBLOCK *mb)
+{
+    short *s_ptr = &mb->coeff[256];
+    short *d_ptr = &mb->e_mbd.dqcoeff[256];
+    return vp8_mbuverror_xmm_impl(s_ptr, d_ptr);
+}
+
+void vp8_subtract_b_sse2_impl(unsigned char *z,  int src_stride,
+                             short *diff, unsigned char *predictor,
+                             int pitch);
+void vp8_subtract_b_sse2(BLOCK *be, BLOCKD *bd, int pitch)
+{
+    unsigned char *z = *(be->base_src) + be->src;
+    unsigned int  src_stride = be->src_stride;
+    short *diff = &be->src_diff[0];
+    unsigned char *predictor = &bd->predictor[0];
+    vp8_subtract_b_sse2_impl(z, src_stride, diff, predictor, pitch);
+}
diff --git a/vp8/exports_dec b/vp8/exports_dec
new file mode 100644 (file)
index 0000000..100ac5c
--- /dev/null
@@ -0,0 +1,2 @@
+data vpx_codec_vp8_dx_algo
+text vpx_codec_vp8_dx
diff --git a/vp8/exports_enc b/vp8/exports_enc
new file mode 100644 (file)
index 0000000..29ff35e
--- /dev/null
@@ -0,0 +1,2 @@
+data vpx_codec_vp8_cx_algo
+text vpx_codec_vp8_cx
diff --git a/vp8/vp8_common.mk b/vp8/vp8_common.mk
new file mode 100644 (file)
index 0000000..3a7b146
--- /dev/null
@@ -0,0 +1,187 @@
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+VP8_COMMON_SRCS-yes += vp8_common.mk
+VP8_COMMON_SRCS-yes += common/pragmas.h
+VP8_COMMON_SRCS-yes += common/ppflags.h
+VP8_COMMON_SRCS-yes += common/onyx.h
+VP8_COMMON_SRCS-yes += common/onyxd.h
+VP8_COMMON_SRCS-yes += common/alloccommon.c
+VP8_COMMON_SRCS-yes += common/asm_com_offsets.c
+VP8_COMMON_SRCS-yes += common/blockd.c
+VP8_COMMON_SRCS-yes += common/coefupdateprobs.h
+VP8_COMMON_SRCS-yes += common/debugmodes.c
+VP8_COMMON_SRCS-yes += common/default_coef_probs.h
+VP8_COMMON_SRCS-yes += common/dequantize.c
+VP8_COMMON_SRCS-yes += common/entropy.c
+VP8_COMMON_SRCS-yes += common/entropymode.c
+VP8_COMMON_SRCS-yes += common/entropymv.c
+VP8_COMMON_SRCS-yes += common/extend.c
+VP8_COMMON_SRCS-yes += common/filter.c
+VP8_COMMON_SRCS-yes += common/filter.h
+VP8_COMMON_SRCS-yes += common/findnearmv.c
+VP8_COMMON_SRCS-yes += common/generic/systemdependent.c
+VP8_COMMON_SRCS-yes += common/idct_blk.c
+VP8_COMMON_SRCS-yes += common/idctllm.c
+VP8_COMMON_SRCS-yes += common/idctllm_test.cc
+VP8_COMMON_SRCS-yes += common/alloccommon.h
+VP8_COMMON_SRCS-yes += common/blockd.h
+VP8_COMMON_SRCS-yes += common/common.h
+VP8_COMMON_SRCS-yes += common/entropy.h
+VP8_COMMON_SRCS-yes += common/entropymode.h
+VP8_COMMON_SRCS-yes += common/entropymv.h
+VP8_COMMON_SRCS-yes += common/extend.h
+VP8_COMMON_SRCS-yes += common/findnearmv.h
+VP8_COMMON_SRCS-yes += common/header.h
+VP8_COMMON_SRCS-yes += common/invtrans.h
+VP8_COMMON_SRCS-yes += common/loopfilter.h
+VP8_COMMON_SRCS-yes += common/modecont.h
+VP8_COMMON_SRCS-yes += common/mv.h
+VP8_COMMON_SRCS-yes += common/onyxc_int.h
+VP8_COMMON_SRCS-yes += common/quant_common.h
+VP8_COMMON_SRCS-yes += common/reconinter.h
+VP8_COMMON_SRCS-yes += common/reconintra4x4.h
+VP8_COMMON_SRCS-yes += common/rtcd.c
+VP8_COMMON_SRCS-yes += common/rtcd_defs.sh
+VP8_COMMON_SRCS-yes += common/setupintrarecon.h
+VP8_COMMON_SRCS-yes += common/swapyv12buffer.h
+VP8_COMMON_SRCS-yes += common/systemdependent.h
+VP8_COMMON_SRCS-yes += common/threading.h
+VP8_COMMON_SRCS-yes += common/treecoder.h
+VP8_COMMON_SRCS-yes += common/loopfilter.c
+VP8_COMMON_SRCS-yes += common/loopfilter_filters.c
+VP8_COMMON_SRCS-yes += common/mbpitch.c
+VP8_COMMON_SRCS-yes += common/modecont.c
+VP8_COMMON_SRCS-yes += common/quant_common.c
+VP8_COMMON_SRCS-yes += common/reconinter.c
+VP8_COMMON_SRCS-yes += common/reconintra.c
+VP8_COMMON_SRCS-yes += common/reconintra4x4.c
+VP8_COMMON_SRCS-yes += common/sad_c.c
+VP8_COMMON_SRCS-yes += common/setupintrarecon.c
+VP8_COMMON_SRCS-yes += common/swapyv12buffer.c
+VP8_COMMON_SRCS-yes += common/variance_c.c
+VP8_COMMON_SRCS-yes += common/variance.h
+VP8_COMMON_SRCS-yes += common/vp8_entropymodedata.h
+
+
+
+VP8_COMMON_SRCS-$(CONFIG_POSTPROC_VISUALIZER) += common/textblit.c
+VP8_COMMON_SRCS-yes += common/treecoder.c
+
+VP8_COMMON_SRCS-$(ARCH_X86)$(ARCH_X86_64) += common/x86/filter_x86.c
+VP8_COMMON_SRCS-$(ARCH_X86)$(ARCH_X86_64) += common/x86/filter_x86.h
+VP8_COMMON_SRCS-$(ARCH_X86)$(ARCH_X86_64) += common/x86/vp8_asm_stubs.c
+VP8_COMMON_SRCS-$(ARCH_X86)$(ARCH_X86_64) += common/x86/loopfilter_x86.c
+VP8_COMMON_SRCS-$(CONFIG_POSTPROC) += common/mfqe.c
+VP8_COMMON_SRCS-$(CONFIG_POSTPROC) += common/postproc.h
+VP8_COMMON_SRCS-$(CONFIG_POSTPROC) += common/postproc.c
+VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/dequantize_mmx.asm
+VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/idct_blk_mmx.c
+VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/idctllm_mmx.asm
+VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/idctllm_mmx_test.cc
+VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/iwalsh_mmx.asm
+VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/loopfilter_mmx.asm
+VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/recon_mmx.asm
+VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/sad_mmx.asm
+VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/subpixel_mmx.asm
+VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/variance_mmx.c
+VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/variance_impl_mmx.asm
+VP8_COMMON_SRCS-$(HAVE_SSE2) += common/x86/idct_blk_sse2.c
+VP8_COMMON_SRCS-$(HAVE_SSE2) += common/x86/idctllm_sse2.asm
+VP8_COMMON_SRCS-$(HAVE_SSE2) += common/x86/recon_sse2.asm
+VP8_COMMON_SRCS-$(HAVE_SSE2) += common/x86/recon_wrapper_sse2.c
+VP8_COMMON_SRCS-$(HAVE_SSE2) += common/x86/sad_sse2.asm
+VP8_COMMON_SRCS-$(HAVE_SSE2) += common/x86/subpixel_sse2.asm
+VP8_COMMON_SRCS-$(HAVE_SSE2) += common/x86/loopfilter_sse2.asm
+VP8_COMMON_SRCS-$(HAVE_SSE2) += common/x86/iwalsh_sse2.asm
+VP8_COMMON_SRCS-$(HAVE_SSE2) += common/x86/variance_sse2.c
+VP8_COMMON_SRCS-$(HAVE_SSE2) += common/x86/variance_impl_sse2.asm
+VP8_COMMON_SRCS-$(HAVE_SSE3) += common/x86/sad_sse3.asm
+VP8_COMMON_SRCS-$(HAVE_SSSE3) += common/x86/sad_ssse3.asm
+VP8_COMMON_SRCS-$(HAVE_SSSE3) += common/x86/subpixel_ssse3.asm
+VP8_COMMON_SRCS-$(HAVE_SSSE3) += common/x86/variance_ssse3.c
+VP8_COMMON_SRCS-$(HAVE_SSSE3) += common/x86/variance_impl_ssse3.asm
+VP8_COMMON_SRCS-$(HAVE_SSE4_1) += common/x86/sad_sse4.asm
+
+ifeq ($(CONFIG_POSTPROC),yes)
+VP8_COMMON_SRCS-$(ARCH_X86)$(ARCH_X86_64) += common/x86/postproc_x86.c
+VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/postproc_mmx.asm
+VP8_COMMON_SRCS-$(HAVE_SSE2) += common/x86/mfqe_sse2.asm
+VP8_COMMON_SRCS-$(HAVE_SSE2) += common/x86/postproc_sse2.asm
+endif
+
+ifeq ($(ARCH_X86_64),yes)
+VP8_COMMON_SRCS-$(HAVE_SSE2) += common/x86/loopfilter_block_sse2.asm
+endif
+
+# common (c)
+VP8_COMMON_SRCS-$(ARCH_ARM)  += common/arm/filter_arm.c
+VP8_COMMON_SRCS-$(ARCH_ARM)  += common/arm/loopfilter_arm.c
+VP8_COMMON_SRCS-$(ARCH_ARM)  += common/arm/reconintra_arm.c
+VP8_COMMON_SRCS-$(ARCH_ARM)  += common/arm/dequantize_arm.c
+VP8_COMMON_SRCS-$(ARCH_ARM)  += common/arm/variance_arm.c
+
+# common (media)
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/bilinearfilter_arm.c
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/bilinearfilter_arm.h
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/bilinearfilter_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/copymem8x4_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/copymem8x8_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/copymem16x16_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/dc_only_idct_add_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/iwalsh_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/filter_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/idct_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/loopfilter_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/simpleloopfilter_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/sixtappredict8x4_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/intra4x4_predict_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/dequant_idct_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/dequantize_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/idct_blk_v6.c
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/vp8_sad16x16_armv6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/vp8_variance8x8_armv6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/vp8_variance16x16_armv6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/vp8_variance_halfpixvar16x16_h_armv6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/vp8_variance_halfpixvar16x16_v_armv6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_MEDIA)  += common/arm/armv6/vp8_variance_halfpixvar16x16_hv_armv6$(ASM)
+
+# common (neon)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/bilinearpredict4x4_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/bilinearpredict8x4_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/bilinearpredict8x8_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/bilinearpredict16x16_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/copymem8x4_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/copymem8x8_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/copymem16x16_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/dc_only_idct_add_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/iwalsh_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/loopfilter_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/loopfiltersimplehorizontaledge_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/loopfiltersimpleverticaledge_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/mbloopfilter_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/shortidct4x4llm_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/sad8_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/sad16_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/sixtappredict4x4_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/sixtappredict8x4_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/sixtappredict8x8_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/sixtappredict16x16_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/buildintrapredictorsmby_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/save_reg_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/dequant_idct_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/idct_dequant_full_2x_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/idct_dequant_0_2x_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/dequantizeb_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/idct_blk_neon.c
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/variance_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/vp8_subpixelvariance8x8_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/vp8_subpixelvariance16x16_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_NEON)  += common/arm/neon/vp8_subpixelvariance16x16s_neon$(ASM)
diff --git a/vp8/vp8_cx_iface.c b/vp8/vp8_cx_iface.c
new file mode 100644 (file)
index 0000000..5fb74c4
--- /dev/null
@@ -0,0 +1,1294 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx/vpx_codec.h"
+#include "vpx/internal/vpx_codec_internal.h"
+#include "vpx_version.h"
+#include "vp8/encoder/onyx_int.h"
+#include "vpx/vp8cx.h"
+#include "vp8/encoder/firstpass.h"
+#include "vp8/common/onyx.h"
+#include <stdlib.h>
+#include <string.h>
+
+struct vp8_extracfg
+{
+    struct vpx_codec_pkt_list *pkt_list;
+    vp8e_encoding_mode      encoding_mode;               /** best, good, realtime            */
+    int                         cpu_used;                    /** available cpu percentage in 1/16*/
+    unsigned int                enable_auto_alt_ref;           /** if encoder decides to uses alternate reference frame */
+    unsigned int                noise_sensitivity;
+    unsigned int                Sharpness;
+    unsigned int                static_thresh;
+    unsigned int                token_partitions;
+    unsigned int                arnr_max_frames;    /* alt_ref Noise Reduction Max Frame Count */
+    unsigned int                arnr_strength;    /* alt_ref Noise Reduction Strength */
+    unsigned int                arnr_type;        /* alt_ref filter type */
+    vp8e_tuning                 tuning;
+    unsigned int                cq_level;         /* constrained quality level */
+    unsigned int                rc_max_intra_bitrate_pct;
+
+};
+
+struct extraconfig_map
+{
+    int                 usage;
+    struct vp8_extracfg cfg;
+};
+
+static const struct extraconfig_map extracfg_map[] =
+{
+    {
+        0,
+        {
+            NULL,
+#if !(CONFIG_REALTIME_ONLY)
+            VP8_BEST_QUALITY_ENCODING,  /* Encoding Mode */
+            0,                          /* cpu_used      */
+#else
+            VP8_REAL_TIME_ENCODING,     /* Encoding Mode */
+            4,                          /* cpu_used      */
+#endif
+            0,                          /* enable_auto_alt_ref */
+            0,                          /* noise_sensitivity */
+            0,                          /* Sharpness */
+            0,                          /* static_thresh */
+#if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)
+            VP8_EIGHT_TOKENPARTITION,
+#else
+            VP8_ONE_TOKENPARTITION,     /* token_partitions */
+#endif
+            0,                          /* arnr_max_frames */
+            3,                          /* arnr_strength */
+            3,                          /* arnr_type*/
+            0,                          /* tuning*/
+            10,                         /* cq_level */
+            0,                          /* rc_max_intra_bitrate_pct */
+        }
+    }
+};
+
+struct vpx_codec_alg_priv
+{
+    vpx_codec_priv_t        base;
+    vpx_codec_enc_cfg_t     cfg;
+    struct vp8_extracfg     vp8_cfg;
+    VP8_CONFIG              oxcf;
+    struct VP8_COMP        *cpi;
+    unsigned char          *cx_data;
+    unsigned int            cx_data_sz;
+    vpx_image_t             preview_img;
+    unsigned int            next_frame_flag;
+    vp8_postproc_cfg_t      preview_ppcfg;
+    vpx_codec_pkt_list_decl(64) pkt_list;              // changed to accomendate the maximum number of lagged frames allowed
+    unsigned int                fixed_kf_cntr;
+};
+
+
+static vpx_codec_err_t
+update_error_state(vpx_codec_alg_priv_t                 *ctx,
+                   const struct vpx_internal_error_info *error)
+{
+    vpx_codec_err_t res;
+
+    if ((res = error->error_code))
+        ctx->base.err_detail = error->has_detail
+                               ? error->detail
+                               : NULL;
+
+    return res;
+}
+
+
+#undef ERROR
+#define ERROR(str) do {\
+        ctx->base.err_detail = str;\
+        return VPX_CODEC_INVALID_PARAM;\
+    } while(0)
+
+#define RANGE_CHECK(p,memb,lo,hi) do {\
+        if(!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
+            ERROR(#memb " out of range ["#lo".."#hi"]");\
+    } while(0)
+
+#define RANGE_CHECK_HI(p,memb,hi) do {\
+        if(!((p)->memb <= (hi))) \
+            ERROR(#memb " out of range [.."#hi"]");\
+    } while(0)
+
+#define RANGE_CHECK_LO(p,memb,lo) do {\
+        if(!((p)->memb >= (lo))) \
+            ERROR(#memb " out of range ["#lo"..]");\
+    } while(0)
+
+#define RANGE_CHECK_BOOL(p,memb) do {\
+        if(!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean");\
+    } while(0)
+
+static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t      *ctx,
+                                       const vpx_codec_enc_cfg_t *cfg,
+                                       const struct vp8_extracfg *vp8_cfg,
+                                       int                        finalize)
+{
+    RANGE_CHECK(cfg, g_w,                   1, 16383); /* 14 bits available */
+    RANGE_CHECK(cfg, g_h,                   1, 16383); /* 14 bits available */
+    RANGE_CHECK(cfg, g_timebase.den,        1, 1000000000);
+    RANGE_CHECK(cfg, g_timebase.num,        1, cfg->g_timebase.den);
+    RANGE_CHECK_HI(cfg, g_profile,          3);
+    RANGE_CHECK_HI(cfg, rc_max_quantizer,   63);
+    RANGE_CHECK_HI(cfg, rc_min_quantizer,   cfg->rc_max_quantizer);
+    RANGE_CHECK_HI(cfg, g_threads,          64);
+#if !(CONFIG_REALTIME_ONLY)
+    RANGE_CHECK_HI(cfg, g_lag_in_frames,    25);
+#else
+    RANGE_CHECK_HI(cfg, g_lag_in_frames,    0);
+#endif
+    RANGE_CHECK(cfg, rc_end_usage,          VPX_VBR, VPX_CQ);
+    RANGE_CHECK_HI(cfg, rc_undershoot_pct,  1000);
+    RANGE_CHECK_HI(cfg, rc_overshoot_pct,   1000);
+    RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
+    RANGE_CHECK(cfg, kf_mode,               VPX_KF_DISABLED, VPX_KF_AUTO);
+    //RANGE_CHECK_BOOL(cfg,                 g_delete_firstpassfile);
+    RANGE_CHECK_BOOL(cfg,                   rc_resize_allowed);
+    RANGE_CHECK_HI(cfg, rc_dropframe_thresh,   100);
+    RANGE_CHECK_HI(cfg, rc_resize_up_thresh,   100);
+    RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100);
+#if !(CONFIG_REALTIME_ONLY)
+    RANGE_CHECK(cfg,        g_pass,         VPX_RC_ONE_PASS, VPX_RC_LAST_PASS);
+#else
+    RANGE_CHECK(cfg,        g_pass,         VPX_RC_ONE_PASS, VPX_RC_ONE_PASS);
+#endif
+
+    /* VP8 does not support a lower bound on the keyframe interval in
+     * automatic keyframe placement mode.
+     */
+    if (cfg->kf_mode != VPX_KF_DISABLED && cfg->kf_min_dist != cfg->kf_max_dist
+        && cfg->kf_min_dist > 0)
+        ERROR("kf_min_dist not supported in auto mode, use 0 "
+              "or kf_max_dist instead.");
+
+    RANGE_CHECK_BOOL(vp8_cfg,               enable_auto_alt_ref);
+    RANGE_CHECK(vp8_cfg, cpu_used,           -16, 16);
+#if !(CONFIG_REALTIME_ONLY)
+    RANGE_CHECK(vp8_cfg, encoding_mode,      VP8_BEST_QUALITY_ENCODING, VP8_REAL_TIME_ENCODING);
+#else
+    RANGE_CHECK(vp8_cfg, encoding_mode,      VP8_REAL_TIME_ENCODING, VP8_REAL_TIME_ENCODING);
+#endif
+
+#if CONFIG_REALTIME_ONLY && !CONFIG_TEMPORAL_DENOISING
+    RANGE_CHECK(vp8_cfg, noise_sensitivity,  0, 0);
+#else
+    RANGE_CHECK_HI(vp8_cfg, noise_sensitivity,  6);
+#endif
+
+    RANGE_CHECK(vp8_cfg, token_partitions,   VP8_ONE_TOKENPARTITION, VP8_EIGHT_TOKENPARTITION);
+    RANGE_CHECK_HI(vp8_cfg, Sharpness,       7);
+    RANGE_CHECK(vp8_cfg, arnr_max_frames, 0, 15);
+    RANGE_CHECK_HI(vp8_cfg, arnr_strength,   6);
+    RANGE_CHECK(vp8_cfg, arnr_type,       1, 3);
+    RANGE_CHECK(vp8_cfg, cq_level, 0, 63);
+    if(finalize && cfg->rc_end_usage == VPX_CQ)
+        RANGE_CHECK(vp8_cfg, cq_level,
+                    cfg->rc_min_quantizer, cfg->rc_max_quantizer);
+
+#if !(CONFIG_REALTIME_ONLY)
+    if (cfg->g_pass == VPX_RC_LAST_PASS)
+    {
+        size_t           packet_sz = sizeof(FIRSTPASS_STATS);
+        int              n_packets = cfg->rc_twopass_stats_in.sz / packet_sz;
+        FIRSTPASS_STATS *stats;
+
+        if (!cfg->rc_twopass_stats_in.buf)
+            ERROR("rc_twopass_stats_in.buf not set.");
+
+        if (cfg->rc_twopass_stats_in.sz % packet_sz)
+            ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
+
+        if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
+            ERROR("rc_twopass_stats_in requires at least two packets.");
+
+        stats = (void*)((char *)cfg->rc_twopass_stats_in.buf
+                + (n_packets - 1) * packet_sz);
+
+        if ((int)(stats->count + 0.5) != n_packets - 1)
+            ERROR("rc_twopass_stats_in missing EOS stats packet");
+    }
+#endif
+
+    RANGE_CHECK(cfg, ts_number_layers, 1, 5);
+
+    if (cfg->ts_number_layers > 1)
+    {
+        int i;
+        RANGE_CHECK_HI(cfg, ts_periodicity, 16);
+
+        for (i=1; i<cfg->ts_number_layers; i++)
+            if (cfg->ts_target_bitrate[i] <= cfg->ts_target_bitrate[i-1])
+                ERROR("ts_target_bitrate entries are not strictly increasing");
+
+        RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers-1], 1, 1);
+        for (i=cfg->ts_number_layers-2; i>0; i--)
+            if (cfg->ts_rate_decimator[i-1] != 2*cfg->ts_rate_decimator[i])
+                ERROR("ts_rate_decimator factors are not powers of 2");
+
+        RANGE_CHECK_HI(cfg, ts_layer_id[i], cfg->ts_number_layers-1);
+    }
+
+#if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)
+    if(cfg->g_threads > (1 << vp8_cfg->token_partitions))
+        ERROR("g_threads cannot be bigger than number of token partitions");
+#endif
+
+    return VPX_CODEC_OK;
+}
+
+
+static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
+                                    const vpx_image_t    *img)
+{
+    switch (img->fmt)
+    {
+    case VPX_IMG_FMT_YV12:
+    case VPX_IMG_FMT_I420:
+    case VPX_IMG_FMT_VPXI420:
+    case VPX_IMG_FMT_VPXYV12:
+        break;
+    default:
+        ERROR("Invalid image format. Only YV12 and I420 images are supported");
+    }
+
+    if ((img->d_w != ctx->cfg.g_w) || (img->d_h != ctx->cfg.g_h))
+        ERROR("Image size must match encoder init configuration size");
+
+    return VPX_CODEC_OK;
+}
+
+
+static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
+                                       vpx_codec_enc_cfg_t cfg,
+                                       struct vp8_extracfg vp8_cfg,
+                                       vpx_codec_priv_enc_mr_cfg_t *mr_cfg)
+{
+    oxcf->multi_threaded         = cfg.g_threads;
+    oxcf->Version               = cfg.g_profile;
+
+    oxcf->Width                 = cfg.g_w;
+    oxcf->Height                = cfg.g_h;
+    oxcf->timebase              = cfg.g_timebase;
+
+    oxcf->error_resilient_mode = cfg.g_error_resilient;
+
+    switch (cfg.g_pass)
+    {
+    case VPX_RC_ONE_PASS:
+        oxcf->Mode = MODE_BESTQUALITY;
+        break;
+    case VPX_RC_FIRST_PASS:
+        oxcf->Mode = MODE_FIRSTPASS;
+        break;
+    case VPX_RC_LAST_PASS:
+        oxcf->Mode = MODE_SECONDPASS_BEST;
+        break;
+    }
+
+    if (cfg.g_pass == VPX_RC_FIRST_PASS)
+    {
+        oxcf->allow_lag     = 0;
+        oxcf->lag_in_frames = 0;
+    }
+    else
+    {
+        oxcf->allow_lag     = (cfg.g_lag_in_frames) > 0;
+        oxcf->lag_in_frames = cfg.g_lag_in_frames;
+    }
+
+    oxcf->allow_df               = (cfg.rc_dropframe_thresh > 0);
+    oxcf->drop_frames_water_mark   = cfg.rc_dropframe_thresh;
+
+    oxcf->allow_spatial_resampling = cfg.rc_resize_allowed;
+    oxcf->resample_up_water_mark   = cfg.rc_resize_up_thresh;
+    oxcf->resample_down_water_mark = cfg.rc_resize_down_thresh;
+
+    if (cfg.rc_end_usage == VPX_VBR)
+    {
+        oxcf->end_usage = USAGE_LOCAL_FILE_PLAYBACK;
+    }
+    else if (cfg.rc_end_usage == VPX_CBR)
+    {
+        oxcf->end_usage = USAGE_STREAM_FROM_SERVER;
+    }
+    else if (cfg.rc_end_usage == VPX_CQ)
+    {
+        oxcf->end_usage = USAGE_CONSTRAINED_QUALITY;
+    }
+
+    oxcf->target_bandwidth         = cfg.rc_target_bitrate;
+    oxcf->rc_max_intra_bitrate_pct = vp8_cfg.rc_max_intra_bitrate_pct;
+
+    oxcf->best_allowed_q           = cfg.rc_min_quantizer;
+    oxcf->worst_allowed_q          = cfg.rc_max_quantizer;
+    oxcf->cq_level                 = vp8_cfg.cq_level;
+    oxcf->fixed_q = -1;
+
+    oxcf->under_shoot_pct          = cfg.rc_undershoot_pct;
+    oxcf->over_shoot_pct           = cfg.rc_overshoot_pct;
+
+    oxcf->maximum_buffer_size_in_ms   = cfg.rc_buf_sz;
+    oxcf->starting_buffer_level_in_ms = cfg.rc_buf_initial_sz;
+    oxcf->optimal_buffer_level_in_ms  = cfg.rc_buf_optimal_sz;
+
+    oxcf->maximum_buffer_size      = cfg.rc_buf_sz;
+    oxcf->starting_buffer_level    = cfg.rc_buf_initial_sz;
+    oxcf->optimal_buffer_level     = cfg.rc_buf_optimal_sz;
+
+    oxcf->two_pass_vbrbias         = cfg.rc_2pass_vbr_bias_pct;
+    oxcf->two_pass_vbrmin_section  = cfg.rc_2pass_vbr_minsection_pct;
+    oxcf->two_pass_vbrmax_section  = cfg.rc_2pass_vbr_maxsection_pct;
+
+    oxcf->auto_key                 = cfg.kf_mode == VPX_KF_AUTO
+                                       && cfg.kf_min_dist != cfg.kf_max_dist;
+    //oxcf->kf_min_dist            = cfg.kf_min_dis;
+    oxcf->key_freq                 = cfg.kf_max_dist;
+
+    oxcf->number_of_layers         = cfg.ts_number_layers;
+    oxcf->periodicity              = cfg.ts_periodicity;
+
+    if (oxcf->number_of_layers > 1)
+    {
+        memcpy (oxcf->target_bitrate, cfg.ts_target_bitrate,
+                          sizeof(cfg.ts_target_bitrate));
+        memcpy (oxcf->rate_decimator, cfg.ts_rate_decimator,
+                          sizeof(cfg.ts_rate_decimator));
+        memcpy (oxcf->layer_id, cfg.ts_layer_id, sizeof(cfg.ts_layer_id));
+    }
+
+#if CONFIG_MULTI_RES_ENCODING
+    /* When mr_cfg is NULL, oxcf->mr_total_resolutions and oxcf->mr_encoder_id
+     * are both memset to 0, which ensures the correct logic under this
+     * situation.
+     */
+    if(mr_cfg)
+    {
+        oxcf->mr_total_resolutions        = mr_cfg->mr_total_resolutions;
+        oxcf->mr_encoder_id               = mr_cfg->mr_encoder_id;
+        oxcf->mr_down_sampling_factor.num = mr_cfg->mr_down_sampling_factor.num;
+        oxcf->mr_down_sampling_factor.den = mr_cfg->mr_down_sampling_factor.den;
+        oxcf->mr_low_res_mode_info        = mr_cfg->mr_low_res_mode_info;
+    }
+#endif
+
+    //oxcf->delete_first_pass_file = cfg.g_delete_firstpassfile;
+    //strcpy(oxcf->first_pass_file, cfg.g_firstpass_file);
+
+    oxcf->cpu_used               = vp8_cfg.cpu_used;
+    oxcf->encode_breakout        = vp8_cfg.static_thresh;
+    oxcf->play_alternate         = vp8_cfg.enable_auto_alt_ref;
+    oxcf->noise_sensitivity      = vp8_cfg.noise_sensitivity;
+    oxcf->Sharpness              = vp8_cfg.Sharpness;
+    oxcf->token_partitions       = vp8_cfg.token_partitions;
+
+    oxcf->two_pass_stats_in      = cfg.rc_twopass_stats_in;
+    oxcf->output_pkt_list        = vp8_cfg.pkt_list;
+
+    oxcf->arnr_max_frames        = vp8_cfg.arnr_max_frames;
+    oxcf->arnr_strength          = vp8_cfg.arnr_strength;
+    oxcf->arnr_type              = vp8_cfg.arnr_type;
+
+    oxcf->tuning                 = vp8_cfg.tuning;
+
+    /*
+        printf("Current VP8 Settings: \n");
+        printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
+        printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
+        printf("Sharpness: %d\n",    oxcf->Sharpness);
+        printf("cpu_used: %d\n",  oxcf->cpu_used);
+        printf("Mode: %d\n",     oxcf->Mode);
+        printf("delete_first_pass_file: %d\n",  oxcf->delete_first_pass_file);
+        printf("auto_key: %d\n",  oxcf->auto_key);
+        printf("key_freq: %d\n", oxcf->key_freq);
+        printf("end_usage: %d\n", oxcf->end_usage);
+        printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
+        printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
+        printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
+        printf("optimal_buffer_level: %d\n",  oxcf->optimal_buffer_level);
+        printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
+        printf("fixed_q: %d\n",  oxcf->fixed_q);
+        printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
+        printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
+        printf("allow_spatial_resampling: %d\n",  oxcf->allow_spatial_resampling);
+        printf("resample_down_water_mark: %d\n", oxcf->resample_down_water_mark);
+        printf("resample_up_water_mark: %d\n", oxcf->resample_up_water_mark);
+        printf("allow_df: %d\n", oxcf->allow_df);
+        printf("drop_frames_water_mark: %d\n", oxcf->drop_frames_water_mark);
+        printf("two_pass_vbrbias: %d\n",  oxcf->two_pass_vbrbias);
+        printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
+        printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
+        printf("allow_lag: %d\n", oxcf->allow_lag);
+        printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
+        printf("play_alternate: %d\n", oxcf->play_alternate);
+        printf("Version: %d\n", oxcf->Version);
+        printf("multi_threaded: %d\n",   oxcf->multi_threaded);
+        printf("encode_breakout: %d\n", oxcf->encode_breakout);
+    */
+    return VPX_CODEC_OK;
+}
+
+static vpx_codec_err_t vp8e_set_config(vpx_codec_alg_priv_t       *ctx,
+                                       const vpx_codec_enc_cfg_t  *cfg)
+{
+    vpx_codec_err_t res;
+
+    if (((cfg->g_w != ctx->cfg.g_w) || (cfg->g_h != ctx->cfg.g_h))
+        && cfg->g_lag_in_frames > 1)
+        ERROR("Cannot change width or height after initialization");
+
+    /* Prevent increasing lag_in_frames. This check is stricter than it needs
+     * to be -- the limit is not increasing past the first lag_in_frames
+     * value, but we don't track the initial config, only the last successful
+     * config.
+     */
+    if ((cfg->g_lag_in_frames > ctx->cfg.g_lag_in_frames))
+        ERROR("Cannot increase lag_in_frames");
+
+    res = validate_config(ctx, cfg, &ctx->vp8_cfg, 0);
+
+    if (!res)
+    {
+        ctx->cfg = *cfg;
+        set_vp8e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg, NULL);
+        vp8_change_config(ctx->cpi, &ctx->oxcf);
+    }
+
+    return res;
+}
+
+
+int vp8_reverse_trans(int);
+
+
+static vpx_codec_err_t get_param(vpx_codec_alg_priv_t *ctx,
+                                 int                   ctrl_id,
+                                 va_list               args)
+{
+    void *arg = va_arg(args, void *);
+
+#define MAP(id, var) case id: *(RECAST(id, arg)) = var; break
+
+    if (!arg)
+        return VPX_CODEC_INVALID_PARAM;
+
+    switch (ctrl_id)
+    {
+        MAP(VP8E_GET_LAST_QUANTIZER, vp8_get_quantizer(ctx->cpi));
+        MAP(VP8E_GET_LAST_QUANTIZER_64, vp8_reverse_trans(vp8_get_quantizer(ctx->cpi)));
+    }
+
+    return VPX_CODEC_OK;
+#undef MAP
+}
+
+
+static vpx_codec_err_t set_param(vpx_codec_alg_priv_t *ctx,
+                                 int                   ctrl_id,
+                                 va_list               args)
+{
+    vpx_codec_err_t     res  = VPX_CODEC_OK;
+    struct vp8_extracfg xcfg = ctx->vp8_cfg;
+
+#define MAP(id, var) case id: var = CAST(id, args); break;
+
+    switch (ctrl_id)
+    {
+        MAP(VP8E_SET_CPUUSED,               xcfg.cpu_used);
+        MAP(VP8E_SET_ENABLEAUTOALTREF,      xcfg.enable_auto_alt_ref);
+        MAP(VP8E_SET_NOISE_SENSITIVITY,     xcfg.noise_sensitivity);
+        MAP(VP8E_SET_SHARPNESS,             xcfg.Sharpness);
+        MAP(VP8E_SET_STATIC_THRESHOLD,      xcfg.static_thresh);
+        MAP(VP8E_SET_TOKEN_PARTITIONS,      xcfg.token_partitions);
+
+        MAP(VP8E_SET_ARNR_MAXFRAMES,        xcfg.arnr_max_frames);
+        MAP(VP8E_SET_ARNR_STRENGTH ,        xcfg.arnr_strength);
+        MAP(VP8E_SET_ARNR_TYPE     ,        xcfg.arnr_type);
+        MAP(VP8E_SET_TUNING,                xcfg.tuning);
+        MAP(VP8E_SET_CQ_LEVEL,              xcfg.cq_level);
+        MAP(VP8E_SET_MAX_INTRA_BITRATE_PCT, xcfg.rc_max_intra_bitrate_pct);
+
+    }
+
+    res = validate_config(ctx, &ctx->cfg, &xcfg, 0);
+
+    if (!res)
+    {
+        ctx->vp8_cfg = xcfg;
+        set_vp8e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg, NULL);
+        vp8_change_config(ctx->cpi, &ctx->oxcf);
+    }
+
+    return res;
+#undef MAP
+}
+
+static vpx_codec_err_t vp8e_mr_alloc_mem(const vpx_codec_enc_cfg_t *cfg,
+                                        void **mem_loc)
+{
+    vpx_codec_err_t res = 0;
+
+#if CONFIG_MULTI_RES_ENCODING
+    int mb_rows = ((cfg->g_w + 15) >>4);
+    int mb_cols = ((cfg->g_h + 15) >>4);
+
+    *mem_loc = calloc(mb_rows*mb_cols, sizeof(LOWER_RES_INFO));
+    if(!(*mem_loc))
+    {
+        free(*mem_loc);
+        res = VPX_CODEC_MEM_ERROR;
+    }
+    else
+        res = VPX_CODEC_OK;
+#endif
+
+    return res;
+}
+
+static vpx_codec_err_t vp8e_init(vpx_codec_ctx_t *ctx,
+                                 vpx_codec_priv_enc_mr_cfg_t *mr_cfg)
+{
+    vpx_codec_err_t        res = VPX_CODEC_OK;
+    struct vpx_codec_alg_priv *priv;
+    vpx_codec_enc_cfg_t       *cfg;
+    unsigned int               i;
+
+    struct VP8_COMP *optr;
+
+    if (!ctx->priv)
+    {
+        priv = calloc(1, sizeof(struct vpx_codec_alg_priv));
+
+        if (!priv)
+        {
+            return VPX_CODEC_MEM_ERROR;
+        }
+
+        ctx->priv = &priv->base;
+        ctx->priv->sz = sizeof(*ctx->priv);
+        ctx->priv->iface = ctx->iface;
+        ctx->priv->alg_priv = priv;
+        ctx->priv->init_flags = ctx->init_flags;
+
+        if (ctx->config.enc)
+        {
+            /* Update the reference to the config structure to an
+             * internal copy.
+             */
+            ctx->priv->alg_priv->cfg = *ctx->config.enc;
+            ctx->config.enc = &ctx->priv->alg_priv->cfg;
+        }
+
+        cfg =  &ctx->priv->alg_priv->cfg;
+
+        /* Select the extra vp8 configuration table based on the current
+         * usage value. If the current usage value isn't found, use the
+         * values for usage case 0.
+         */
+        for (i = 0;
+             extracfg_map[i].usage && extracfg_map[i].usage != cfg->g_usage;
+             i++);
+
+        priv->vp8_cfg = extracfg_map[i].cfg;
+        priv->vp8_cfg.pkt_list = &priv->pkt_list.head;
+
+        priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 2;
+
+        if (priv->cx_data_sz < 32768) priv->cx_data_sz = 32768;
+
+        priv->cx_data = malloc(priv->cx_data_sz);
+
+        if (!priv->cx_data)
+        {
+            return VPX_CODEC_MEM_ERROR;
+        }
+
+        res = validate_config(priv, &priv->cfg, &priv->vp8_cfg, 0);
+
+        if (!res)
+        {
+            if(mr_cfg)
+                ctx->priv->enc.total_encoders   = mr_cfg->mr_total_resolutions;
+            else
+                ctx->priv->enc.total_encoders   = 1;
+
+            set_vp8e_config(&ctx->priv->alg_priv->oxcf,
+                             ctx->priv->alg_priv->cfg,
+                             ctx->priv->alg_priv->vp8_cfg,
+                             mr_cfg);
+
+            optr = vp8_create_compressor(&ctx->priv->alg_priv->oxcf);
+
+            if (!optr)
+                res = VPX_CODEC_MEM_ERROR;
+            else
+                ctx->priv->alg_priv->cpi = optr;
+        }
+    }
+
+    return res;
+}
+
+static vpx_codec_err_t vp8e_destroy(vpx_codec_alg_priv_t *ctx)
+{
+#if CONFIG_MULTI_RES_ENCODING
+    /* Free multi-encoder shared memory */
+    if (ctx->oxcf.mr_total_resolutions > 0 && (ctx->oxcf.mr_encoder_id == ctx->oxcf.mr_total_resolutions-1))
+        free(ctx->oxcf.mr_low_res_mode_info);
+#endif
+
+    free(ctx->cx_data);
+    vp8_remove_compressor(&ctx->cpi);
+    free(ctx);
+    return VPX_CODEC_OK;
+}
+
+static vpx_codec_err_t image2yuvconfig(const vpx_image_t   *img,
+                                       YV12_BUFFER_CONFIG  *yv12)
+{
+    vpx_codec_err_t        res = VPX_CODEC_OK;
+    yv12->y_buffer = img->planes[VPX_PLANE_Y];
+    yv12->u_buffer = img->planes[VPX_PLANE_U];
+    yv12->v_buffer = img->planes[VPX_PLANE_V];
+
+    yv12->y_width  = img->d_w;
+    yv12->y_height = img->d_h;
+    yv12->uv_width = (1 + yv12->y_width) / 2;
+    yv12->uv_height = (1 + yv12->y_height) / 2;
+
+    yv12->y_stride = img->stride[VPX_PLANE_Y];
+    yv12->uv_stride = img->stride[VPX_PLANE_U];
+
+    yv12->border  = (img->stride[VPX_PLANE_Y] - img->w) / 2;
+    yv12->clrtype = (img->fmt == VPX_IMG_FMT_VPXI420 || img->fmt == VPX_IMG_FMT_VPXYV12); //REG_YUV = 0
+    return res;
+}
+
+static void pick_quickcompress_mode(vpx_codec_alg_priv_t  *ctx,
+                                    unsigned long          duration,
+                                    unsigned long          deadline)
+{
+    unsigned int new_qc;
+
+#if !(CONFIG_REALTIME_ONLY)
+    /* Use best quality mode if no deadline is given. */
+    new_qc = MODE_BESTQUALITY;
+
+    if (deadline)
+    {
+        uint64_t     duration_us;
+
+        /* Convert duration parameter from stream timebase to microseconds */
+        duration_us = (uint64_t)duration * 1000000
+                      * (uint64_t)ctx->cfg.g_timebase.num
+                      / (uint64_t)ctx->cfg.g_timebase.den;
+
+        /* If the deadline is more that the duration this frame is to be shown,
+         * use good quality mode. Otherwise use realtime mode.
+         */
+        new_qc = (deadline > duration_us) ? MODE_GOODQUALITY : MODE_REALTIME;
+    }
+
+#else
+    new_qc = MODE_REALTIME;
+#endif
+
+    if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS)
+        new_qc = MODE_FIRSTPASS;
+    else if (ctx->cfg.g_pass == VPX_RC_LAST_PASS)
+        new_qc = (new_qc == MODE_BESTQUALITY)
+                 ? MODE_SECONDPASS_BEST
+                 : MODE_SECONDPASS;
+
+    if (ctx->oxcf.Mode != new_qc)
+    {
+        ctx->oxcf.Mode = new_qc;
+        vp8_change_config(ctx->cpi, &ctx->oxcf);
+    }
+}
+
+
+static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t  *ctx,
+                                   const vpx_image_t     *img,
+                                   vpx_codec_pts_t        pts,
+                                   unsigned long          duration,
+                                   vpx_enc_frame_flags_t  flags,
+                                   unsigned long          deadline)
+{
+    vpx_codec_err_t res = VPX_CODEC_OK;
+
+    if (!ctx->cfg.rc_target_bitrate)
+        return res;
+
+    if (img)
+        res = validate_img(ctx, img);
+
+    if (!res)
+        res = validate_config(ctx, &ctx->cfg, &ctx->vp8_cfg, 1);
+
+    pick_quickcompress_mode(ctx, duration, deadline);
+    vpx_codec_pkt_list_init(&ctx->pkt_list);
+
+    /* Handle Flags */
+    if (((flags & VP8_EFLAG_NO_UPD_GF) && (flags & VP8_EFLAG_FORCE_GF))
+        || ((flags & VP8_EFLAG_NO_UPD_ARF) && (flags & VP8_EFLAG_FORCE_ARF)))
+    {
+        ctx->base.err_detail = "Conflicting flags.";
+        return VPX_CODEC_INVALID_PARAM;
+    }
+
+    if (flags & (VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF
+                 | VP8_EFLAG_NO_REF_ARF))
+    {
+        int ref = 7;
+
+        if (flags & VP8_EFLAG_NO_REF_LAST)
+            ref ^= VP8_LAST_FLAG;
+
+        if (flags & VP8_EFLAG_NO_REF_GF)
+            ref ^= VP8_GOLD_FLAG;
+
+        if (flags & VP8_EFLAG_NO_REF_ARF)
+            ref ^= VP8_ALT_FLAG;
+
+        vp8_use_as_reference(ctx->cpi, ref);
+    }
+
+    if (flags & (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF
+                 | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_FORCE_GF
+                 | VP8_EFLAG_FORCE_ARF))
+    {
+        int upd = 7;
+
+        if (flags & VP8_EFLAG_NO_UPD_LAST)
+            upd ^= VP8_LAST_FLAG;
+
+        if (flags & VP8_EFLAG_NO_UPD_GF)
+            upd ^= VP8_GOLD_FLAG;
+
+        if (flags & VP8_EFLAG_NO_UPD_ARF)
+            upd ^= VP8_ALT_FLAG;
+
+        vp8_update_reference(ctx->cpi, upd);
+    }
+
+    if (flags & VP8_EFLAG_NO_UPD_ENTROPY)
+    {
+        vp8_update_entropy(ctx->cpi, 0);
+    }
+
+    /* Handle fixed keyframe intervals */
+    if (ctx->cfg.kf_mode == VPX_KF_AUTO
+        && ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist)
+    {
+        if (++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist)
+        {
+            flags |= VPX_EFLAG_FORCE_KF;
+            ctx->fixed_kf_cntr = 1;
+        }
+    }
+
+    /* Initialize the encoder instance on the first frame*/
+    if (!res && ctx->cpi)
+    {
+        unsigned int lib_flags;
+        YV12_BUFFER_CONFIG sd;
+        int64_t dst_time_stamp, dst_end_time_stamp;
+        unsigned long size, cx_data_sz;
+        unsigned char *cx_data;
+        unsigned char *cx_data_end;
+        int comp_data_state = 0;
+
+        /* Set up internal flags */
+        if (ctx->base.init_flags & VPX_CODEC_USE_PSNR)
+            ((VP8_COMP *)ctx->cpi)->b_calculate_psnr = 1;
+
+        if (ctx->base.init_flags & VPX_CODEC_USE_OUTPUT_PARTITION)
+            ((VP8_COMP *)ctx->cpi)->output_partition = 1;
+
+        /* Convert API flags to internal codec lib flags */
+        lib_flags = (flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;
+
+        /* vp8 use 10,000,000 ticks/second as time stamp */
+        dst_time_stamp    = pts * 10000000 * ctx->cfg.g_timebase.num / ctx->cfg.g_timebase.den;
+        dst_end_time_stamp = (pts + duration) * 10000000 * ctx->cfg.g_timebase.num / ctx->cfg.g_timebase.den;
+
+        if (img != NULL)
+        {
+            res = image2yuvconfig(img, &sd);
+
+            if (vp8_receive_raw_frame(ctx->cpi, ctx->next_frame_flag | lib_flags,
+                                      &sd, dst_time_stamp, dst_end_time_stamp))
+            {
+                VP8_COMP *cpi = (VP8_COMP *)ctx->cpi;
+                res = update_error_state(ctx, &cpi->common.error);
+            }
+
+            /* reset for next frame */
+            ctx->next_frame_flag = 0;
+        }
+
+        cx_data = ctx->cx_data;
+        cx_data_sz = ctx->cx_data_sz;
+        cx_data_end = ctx->cx_data + cx_data_sz;
+        lib_flags = 0;
+
+        while (cx_data_sz >= ctx->cx_data_sz / 2)
+        {
+            comp_data_state = vp8_get_compressed_data(ctx->cpi,
+                                                  &lib_flags,
+                                                  &size,
+                                                  cx_data,
+                                                  cx_data_end,
+                                                  &dst_time_stamp,
+                                                  &dst_end_time_stamp,
+                                                  !img);
+
+            if(comp_data_state == VPX_CODEC_CORRUPT_FRAME)
+                return VPX_CODEC_CORRUPT_FRAME;
+            else if(comp_data_state == -1)
+                break;
+
+            if (size)
+            {
+                vpx_codec_pts_t    round, delta;
+                vpx_codec_cx_pkt_t pkt;
+                VP8_COMP *cpi = (VP8_COMP *)ctx->cpi;
+
+                /* Add the frame packet to the list of returned packets. */
+                round = 1000000 * ctx->cfg.g_timebase.num / 2 - 1;
+                delta = (dst_end_time_stamp - dst_time_stamp);
+                pkt.kind = VPX_CODEC_CX_FRAME_PKT;
+                pkt.data.frame.pts =
+                    (dst_time_stamp * ctx->cfg.g_timebase.den + round)
+                    / ctx->cfg.g_timebase.num / 10000000;
+                pkt.data.frame.duration =
+                    (delta * ctx->cfg.g_timebase.den + round)
+                    / ctx->cfg.g_timebase.num / 10000000;
+                pkt.data.frame.flags = lib_flags << 16;
+
+                if (lib_flags & FRAMEFLAGS_KEY)
+                    pkt.data.frame.flags |= VPX_FRAME_IS_KEY;
+
+                if (!cpi->common.show_frame)
+                {
+                    pkt.data.frame.flags |= VPX_FRAME_IS_INVISIBLE;
+
+                    // This timestamp should be as close as possible to the
+                    // prior PTS so that if a decoder uses pts to schedule when
+                    // to do this, we start right after last frame was decoded.
+                    // Invisible frames have no duration.
+                    pkt.data.frame.pts = ((cpi->last_time_stamp_seen
+                        * ctx->cfg.g_timebase.den + round)
+                        / ctx->cfg.g_timebase.num / 10000000) + 1;
+                    pkt.data.frame.duration = 0;
+                }
+
+                if (cpi->droppable)
+                    pkt.data.frame.flags |= VPX_FRAME_IS_DROPPABLE;
+
+                if (cpi->output_partition)
+                {
+                    int i;
+                    const int num_partitions =
+                            (1 << cpi->common.multi_token_partition) + 1;
+
+                    pkt.data.frame.flags |= VPX_FRAME_IS_FRAGMENT;
+
+                    for (i = 0; i < num_partitions; ++i)
+                    {
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+                        pkt.data.frame.buf = cpi->partition_d[i];
+#else
+                        pkt.data.frame.buf = cx_data;
+                        cx_data += cpi->partition_sz[i];
+                        cx_data_sz -= cpi->partition_sz[i];
+#endif
+                        pkt.data.frame.sz = cpi->partition_sz[i];
+                        pkt.data.frame.partition_id = i;
+                        /* don't set the fragment bit for the last partition */
+                        if (i == (num_partitions - 1))
+                            pkt.data.frame.flags &= ~VPX_FRAME_IS_FRAGMENT;
+                        vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
+                    }
+#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
+                    /* In lagged mode the encoder can buffer multiple frames.
+                     * We don't want this in partitioned output because
+                     * partitions are spread all over the output buffer.
+                     * So, force an exit!
+                     */
+                    cx_data_sz -= ctx->cx_data_sz / 2;
+#endif
+                }
+                else
+                {
+                    pkt.data.frame.buf = cx_data;
+                    pkt.data.frame.sz  = size;
+                    pkt.data.frame.partition_id = -1;
+                    vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
+                    cx_data += size;
+                    cx_data_sz -= size;
+                }
+
+                //printf("timestamp: %lld, duration: %d\n", pkt->data.frame.pts, pkt->data.frame.duration);
+            }
+        }
+    }
+
+    return res;
+}
+
+
+static const vpx_codec_cx_pkt_t *vp8e_get_cxdata(vpx_codec_alg_priv_t  *ctx,
+        vpx_codec_iter_t      *iter)
+{
+    return vpx_codec_pkt_list_get(&ctx->pkt_list.head, iter);
+}
+
+static vpx_codec_err_t vp8e_set_reference(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+    vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
+
+    if (data)
+    {
+        vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
+        YV12_BUFFER_CONFIG sd;
+
+        image2yuvconfig(&frame->img, &sd);
+        vp8_set_reference(ctx->cpi, frame->frame_type, &sd);
+        return VPX_CODEC_OK;
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+
+}
+
+static vpx_codec_err_t vp8e_get_reference(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+
+    vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
+
+    if (data)
+    {
+        vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
+        YV12_BUFFER_CONFIG sd;
+
+        image2yuvconfig(&frame->img, &sd);
+        vp8_get_reference(ctx->cpi, frame->frame_type, &sd);
+        return VPX_CODEC_OK;
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+}
+
+static vpx_codec_err_t vp8e_set_previewpp(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+#if CONFIG_POSTPROC
+    vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
+    (void)ctr_id;
+
+    if (data)
+    {
+        ctx->preview_ppcfg = *((vp8_postproc_cfg_t *)data);
+        return VPX_CODEC_OK;
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+#else
+    (void)ctx;
+    (void)ctr_id;
+    (void)args;
+    return VPX_CODEC_INCAPABLE;
+#endif
+}
+
+
+static vpx_image_t *vp8e_get_preview(vpx_codec_alg_priv_t *ctx)
+{
+
+    YV12_BUFFER_CONFIG sd;
+    vp8_ppflags_t flags = {0};
+
+    if (ctx->preview_ppcfg.post_proc_flag)
+    {
+        flags.post_proc_flag        = ctx->preview_ppcfg.post_proc_flag;
+        flags.deblocking_level      = ctx->preview_ppcfg.deblocking_level;
+        flags.noise_level           = ctx->preview_ppcfg.noise_level;
+    }
+
+    if (0 == vp8_get_preview_raw_frame(ctx->cpi, &sd, &flags))
+    {
+
+        /*
+        vpx_img_wrap(&ctx->preview_img, VPX_IMG_FMT_YV12,
+            sd.y_width + 2*VP8BORDERINPIXELS,
+            sd.y_height + 2*VP8BORDERINPIXELS,
+            1,
+            sd.buffer_alloc);
+        vpx_img_set_rect(&ctx->preview_img,
+            VP8BORDERINPIXELS, VP8BORDERINPIXELS,
+            sd.y_width, sd.y_height);
+            */
+
+        ctx->preview_img.bps = 12;
+        ctx->preview_img.planes[VPX_PLANE_Y] = sd.y_buffer;
+        ctx->preview_img.planes[VPX_PLANE_U] = sd.u_buffer;
+        ctx->preview_img.planes[VPX_PLANE_V] = sd.v_buffer;
+
+        if (sd.clrtype == REG_YUV)
+            ctx->preview_img.fmt = VPX_IMG_FMT_I420;
+        else
+            ctx->preview_img.fmt = VPX_IMG_FMT_VPXI420;
+
+        ctx->preview_img.x_chroma_shift = 1;
+        ctx->preview_img.y_chroma_shift = 1;
+
+        ctx->preview_img.d_w = sd.y_width;
+        ctx->preview_img.d_h = sd.y_height;
+        ctx->preview_img.stride[VPX_PLANE_Y] = sd.y_stride;
+        ctx->preview_img.stride[VPX_PLANE_U] = sd.uv_stride;
+        ctx->preview_img.stride[VPX_PLANE_V] = sd.uv_stride;
+        ctx->preview_img.w   = sd.y_width;
+        ctx->preview_img.h   = sd.y_height;
+
+        return &ctx->preview_img;
+    }
+    else
+        return NULL;
+}
+
+static vpx_codec_err_t vp8e_update_entropy(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+    int update = va_arg(args, int);
+    vp8_update_entropy(ctx->cpi, update);
+    return VPX_CODEC_OK;
+
+}
+
+static vpx_codec_err_t vp8e_update_reference(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+    int update = va_arg(args, int);
+    vp8_update_reference(ctx->cpi, update);
+    return VPX_CODEC_OK;
+}
+
+static vpx_codec_err_t vp8e_use_reference(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+    int reference_flag = va_arg(args, int);
+    vp8_use_as_reference(ctx->cpi, reference_flag);
+    return VPX_CODEC_OK;
+}
+
+static vpx_codec_err_t vp8e_set_roi_map(vpx_codec_alg_priv_t *ctx,
+                                        int ctr_id,
+                                        va_list args)
+{
+    vpx_roi_map_t *data = va_arg(args, vpx_roi_map_t *);
+
+    if (data)
+    {
+        vpx_roi_map_t *roi = (vpx_roi_map_t *)data;
+
+        if (!vp8_set_roimap(ctx->cpi, roi->roi_map, roi->rows, roi->cols, roi->delta_q, roi->delta_lf, roi->static_threshold))
+            return VPX_CODEC_OK;
+        else
+            return VPX_CODEC_INVALID_PARAM;
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+}
+
+
+static vpx_codec_err_t vp8e_set_activemap(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+    vpx_active_map_t *data = va_arg(args, vpx_active_map_t *);
+
+    if (data)
+    {
+
+        vpx_active_map_t *map = (vpx_active_map_t *)data;
+
+        if (!vp8_set_active_map(ctx->cpi, map->active_map, map->rows, map->cols))
+            return VPX_CODEC_OK;
+        else
+            return VPX_CODEC_INVALID_PARAM;
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+}
+
+static vpx_codec_err_t vp8e_set_scalemode(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+
+    vpx_scaling_mode_t *data =  va_arg(args, vpx_scaling_mode_t *);
+
+    if (data)
+    {
+        int res;
+        vpx_scaling_mode_t scalemode = *(vpx_scaling_mode_t *)data ;
+        res = vp8_set_internal_size(ctx->cpi, scalemode.h_scaling_mode, scalemode.v_scaling_mode);
+
+        if (!res)
+        {
+            /*force next frame a key frame to effect scaling mode */
+            ctx->next_frame_flag |= FRAMEFLAGS_KEY;
+            return VPX_CODEC_OK;
+        }
+        else
+            return VPX_CODEC_INVALID_PARAM;
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+}
+
+
+static vpx_codec_ctrl_fn_map_t vp8e_ctf_maps[] =
+{
+    {VP8_SET_REFERENCE,                 vp8e_set_reference},
+    {VP8_COPY_REFERENCE,                vp8e_get_reference},
+    {VP8_SET_POSTPROC,                  vp8e_set_previewpp},
+    {VP8E_UPD_ENTROPY,                  vp8e_update_entropy},
+    {VP8E_UPD_REFERENCE,                vp8e_update_reference},
+    {VP8E_USE_REFERENCE,                vp8e_use_reference},
+    {VP8E_SET_ROI_MAP,                  vp8e_set_roi_map},
+    {VP8E_SET_ACTIVEMAP,                vp8e_set_activemap},
+    {VP8E_SET_SCALEMODE,                vp8e_set_scalemode},
+    {VP8E_SET_CPUUSED,                  set_param},
+    {VP8E_SET_NOISE_SENSITIVITY,        set_param},
+    {VP8E_SET_ENABLEAUTOALTREF,         set_param},
+    {VP8E_SET_SHARPNESS,                set_param},
+    {VP8E_SET_STATIC_THRESHOLD,         set_param},
+    {VP8E_SET_TOKEN_PARTITIONS,         set_param},
+    {VP8E_GET_LAST_QUANTIZER,           get_param},
+    {VP8E_GET_LAST_QUANTIZER_64,        get_param},
+    {VP8E_SET_ARNR_MAXFRAMES,           set_param},
+    {VP8E_SET_ARNR_STRENGTH ,           set_param},
+    {VP8E_SET_ARNR_TYPE     ,           set_param},
+    {VP8E_SET_TUNING,                   set_param},
+    {VP8E_SET_CQ_LEVEL,                 set_param},
+    {VP8E_SET_MAX_INTRA_BITRATE_PCT,    set_param},
+    { -1, NULL},
+};
+
+static vpx_codec_enc_cfg_map_t vp8e_usage_cfg_map[] =
+{
+    {
+    0,
+    {
+        0,                  /* g_usage */
+        0,                  /* g_threads */
+        0,                  /* g_profile */
+
+        320,                /* g_width */
+        240,                /* g_height */
+        {1, 30},            /* g_timebase */
+
+        0,                  /* g_error_resilient */
+
+        VPX_RC_ONE_PASS,    /* g_pass */
+
+        0,                  /* g_lag_in_frames */
+
+        0,                  /* rc_dropframe_thresh */
+        0,                  /* rc_resize_allowed */
+        60,                 /* rc_resize_down_thresold */
+        30,                 /* rc_resize_up_thresold */
+
+        VPX_VBR,            /* rc_end_usage */
+#if VPX_ENCODER_ABI_VERSION > (1 + VPX_CODEC_ABI_VERSION)
+        {0},                /* rc_twopass_stats_in */
+#endif
+        256,                /* rc_target_bandwidth */
+        4,                  /* rc_min_quantizer */
+        63,                 /* rc_max_quantizer */
+        100,                /* rc_undershoot_pct */
+        100,                /* rc_overshoot_pct */
+
+        6000,               /* rc_max_buffer_size */
+        4000,               /* rc_buffer_initial_size; */
+        5000,               /* rc_buffer_optimal_size; */
+
+        50,                 /* rc_two_pass_vbrbias  */
+        0,                  /* rc_two_pass_vbrmin_section */
+        400,                /* rc_two_pass_vbrmax_section */
+
+        /* keyframing settings (kf) */
+        VPX_KF_AUTO,        /* g_kfmode*/
+        0,                  /* kf_min_dist */
+        128,                /* kf_max_dist */
+
+#if VPX_ENCODER_ABI_VERSION == (1 + VPX_CODEC_ABI_VERSION)
+        1,                  /* g_delete_first_pass_file */
+        "vp8.fpf"           /* first pass filename */
+#endif
+
+        1,                  /* ts_number_layers */
+        {0},                /* ts_target_bitrate */
+        {0},                /* ts_rate_decimator */
+        0,                  /* ts_periodicity */
+        {0},                /* ts_layer_id */
+    }},
+    { -1, {NOT_IMPLEMENTED}}
+};
+
+
+#ifndef VERSION_STRING
+#define VERSION_STRING
+#endif
+CODEC_INTERFACE(vpx_codec_vp8_cx) =
+{
+    "WebM Project VP8 Encoder" VERSION_STRING,
+    VPX_CODEC_INTERNAL_ABI_VERSION,
+    VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR |
+    VPX_CODEC_CAP_OUTPUT_PARTITION,
+    /* vpx_codec_caps_t          caps; */
+    vp8e_init,          /* vpx_codec_init_fn_t       init; */
+    vp8e_destroy,       /* vpx_codec_destroy_fn_t    destroy; */
+    vp8e_ctf_maps,      /* vpx_codec_ctrl_fn_map_t  *ctrl_maps; */
+    NOT_IMPLEMENTED,    /* vpx_codec_get_mmap_fn_t   get_mmap; */
+    NOT_IMPLEMENTED,    /* vpx_codec_set_mmap_fn_t   set_mmap; */
+    {
+        NOT_IMPLEMENTED,    /* vpx_codec_peek_si_fn_t    peek_si; */
+        NOT_IMPLEMENTED,    /* vpx_codec_get_si_fn_t     get_si; */
+        NOT_IMPLEMENTED,    /* vpx_codec_decode_fn_t     decode; */
+        NOT_IMPLEMENTED,    /* vpx_codec_frame_get_fn_t  frame_get; */
+    },
+    {
+        vp8e_usage_cfg_map, /* vpx_codec_enc_cfg_map_t    peek_si; */
+        vp8e_encode,        /* vpx_codec_encode_fn_t      encode; */
+        vp8e_get_cxdata,    /* vpx_codec_get_cx_data_fn_t   frame_get; */
+        vp8e_set_config,
+        NOT_IMPLEMENTED,
+        vp8e_get_preview,
+        vp8e_mr_alloc_mem,
+    } /* encoder functions */
+};
diff --git a/vp8/vp8_dx_iface.c b/vp8/vp8_dx_iface.c
new file mode 100644 (file)
index 0000000..37773db
--- /dev/null
@@ -0,0 +1,787 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include "vpx/vpx_decoder.h"
+#include "vpx/vp8dx.h"
+#include "vpx/internal/vpx_codec_internal.h"
+#include "vpx_version.h"
+#include "common/onyxd.h"
+#include "decoder/onyxd_int.h"
+
+#define VP8_CAP_POSTPROC (CONFIG_POSTPROC ? VPX_CODEC_CAP_POSTPROC : 0)
+#define VP8_CAP_ERROR_CONCEALMENT (CONFIG_ERROR_CONCEALMENT ? \
+                                    VPX_CODEC_CAP_ERROR_CONCEALMENT : 0)
+
+typedef vpx_codec_stream_info_t  vp8_stream_info_t;
+
+/* Structures for handling memory allocations */
+typedef enum
+{
+    VP8_SEG_ALG_PRIV     = 256,
+    VP8_SEG_MAX
+} mem_seg_id_t;
+#define NELEMENTS(x) ((int)(sizeof(x)/sizeof(x[0])))
+
+static unsigned long vp8_priv_sz(const vpx_codec_dec_cfg_t *si, vpx_codec_flags_t);
+
+typedef struct
+{
+    unsigned int   id;
+    unsigned long  sz;
+    unsigned int   align;
+    unsigned int   flags;
+    unsigned long(*calc_sz)(const vpx_codec_dec_cfg_t *, vpx_codec_flags_t);
+} mem_req_t;
+
+static const mem_req_t vp8_mem_req_segs[] =
+{
+    {VP8_SEG_ALG_PRIV,    0, 8, VPX_CODEC_MEM_ZERO, vp8_priv_sz},
+    {VP8_SEG_MAX, 0, 0, 0, NULL}
+};
+
+struct vpx_codec_alg_priv
+{
+    vpx_codec_priv_t        base;
+    vpx_codec_mmap_t        mmaps[NELEMENTS(vp8_mem_req_segs)-1];
+    vpx_codec_dec_cfg_t     cfg;
+    vp8_stream_info_t       si;
+    int                     defer_alloc;
+    int                     decoder_init;
+    struct VP8D_COMP       *pbi;
+    int                     postproc_cfg_set;
+    vp8_postproc_cfg_t      postproc_cfg;
+#if CONFIG_POSTPROC_VISUALIZER
+    unsigned int            dbg_postproc_flag;
+    int                     dbg_color_ref_frame_flag;
+    int                     dbg_color_mb_modes_flag;
+    int                     dbg_color_b_modes_flag;
+    int                     dbg_display_mv_flag;
+#endif
+    vpx_image_t             img;
+    int                     img_setup;
+    int                     img_avail;
+};
+
+static unsigned long vp8_priv_sz(const vpx_codec_dec_cfg_t *si, vpx_codec_flags_t flags)
+{
+    /* Although this declaration is constant, we can't use it in the requested
+     * segments list because we want to define the requested segments list
+     * before defining the private type (so that the number of memory maps is
+     * known)
+     */
+    (void)si;
+    return sizeof(vpx_codec_alg_priv_t);
+}
+
+
+static void vp8_mmap_dtor(vpx_codec_mmap_t *mmap)
+{
+    free(mmap->priv);
+}
+
+static vpx_codec_err_t vp8_mmap_alloc(vpx_codec_mmap_t *mmap)
+{
+    vpx_codec_err_t  res;
+    unsigned int   align;
+
+    align = mmap->align ? mmap->align - 1 : 0;
+
+    if (mmap->flags & VPX_CODEC_MEM_ZERO)
+        mmap->priv = calloc(1, mmap->sz + align);
+    else
+        mmap->priv = malloc(mmap->sz + align);
+
+    res = (mmap->priv) ? VPX_CODEC_OK : VPX_CODEC_MEM_ERROR;
+    mmap->base = (void *)((((uintptr_t)mmap->priv) + align) & ~(uintptr_t)align);
+    mmap->dtor = vp8_mmap_dtor;
+    return res;
+}
+
+static vpx_codec_err_t vp8_validate_mmaps(const vp8_stream_info_t *si,
+        const vpx_codec_mmap_t        *mmaps,
+        vpx_codec_flags_t              init_flags)
+{
+    int i;
+    vpx_codec_err_t res = VPX_CODEC_OK;
+
+    for (i = 0; i < NELEMENTS(vp8_mem_req_segs) - 1; i++)
+    {
+        /* Ensure the segment has been allocated */
+        if (!mmaps[i].base)
+        {
+            res = VPX_CODEC_MEM_ERROR;
+            break;
+        }
+
+        /* Verify variable size segment is big enough for the current si. */
+        if (vp8_mem_req_segs[i].calc_sz)
+        {
+            vpx_codec_dec_cfg_t cfg;
+
+            cfg.w = si->w;
+            cfg.h = si->h;
+
+            if (mmaps[i].sz < vp8_mem_req_segs[i].calc_sz(&cfg, init_flags))
+            {
+                res = VPX_CODEC_MEM_ERROR;
+                break;
+            }
+        }
+    }
+
+    return res;
+}
+
+static void vp8_init_ctx(vpx_codec_ctx_t *ctx, const vpx_codec_mmap_t *mmap)
+{
+    int i;
+
+    ctx->priv = mmap->base;
+    ctx->priv->sz = sizeof(*ctx->priv);
+    ctx->priv->iface = ctx->iface;
+    ctx->priv->alg_priv = mmap->base;
+
+    for (i = 0; i < NELEMENTS(ctx->priv->alg_priv->mmaps); i++)
+        ctx->priv->alg_priv->mmaps[i].id = vp8_mem_req_segs[i].id;
+
+    ctx->priv->alg_priv->mmaps[0] = *mmap;
+    ctx->priv->alg_priv->si.sz = sizeof(ctx->priv->alg_priv->si);
+    ctx->priv->init_flags = ctx->init_flags;
+
+    if (ctx->config.dec)
+    {
+        /* Update the reference to the config structure to an internal copy. */
+        ctx->priv->alg_priv->cfg = *ctx->config.dec;
+        ctx->config.dec = &ctx->priv->alg_priv->cfg;
+    }
+}
+
+static void *mmap_lkup(vpx_codec_alg_priv_t *ctx, unsigned int id)
+{
+    int i;
+
+    for (i = 0; i < NELEMENTS(ctx->mmaps); i++)
+        if (ctx->mmaps[i].id == id)
+            return ctx->mmaps[i].base;
+
+    return NULL;
+}
+static void vp8_finalize_mmaps(vpx_codec_alg_priv_t *ctx)
+{
+    /* nothing to clean up */
+}
+
+static vpx_codec_err_t vp8_init(vpx_codec_ctx_t *ctx,
+                                vpx_codec_priv_enc_mr_cfg_t *data)
+{
+    vpx_codec_err_t        res = VPX_CODEC_OK;
+    (void) data;
+
+    /* This function only allocates space for the vpx_codec_alg_priv_t
+     * structure. More memory may be required at the time the stream
+     * information becomes known.
+     */
+    if (!ctx->priv)
+    {
+        vpx_codec_mmap_t mmap;
+
+        mmap.id = vp8_mem_req_segs[0].id;
+        mmap.sz = sizeof(vpx_codec_alg_priv_t);
+        mmap.align = vp8_mem_req_segs[0].align;
+        mmap.flags = vp8_mem_req_segs[0].flags;
+
+        res = vp8_mmap_alloc(&mmap);
+
+        if (!res)
+        {
+            vp8_init_ctx(ctx, &mmap);
+
+            ctx->priv->alg_priv->defer_alloc = 1;
+            /*post processing level initialized to do nothing */
+        }
+    }
+
+    return res;
+}
+
+static vpx_codec_err_t vp8_destroy(vpx_codec_alg_priv_t *ctx)
+{
+    int i;
+
+    vp8dx_remove_decompressor(ctx->pbi);
+
+    for (i = NELEMENTS(ctx->mmaps) - 1; i >= 0; i--)
+    {
+        if (ctx->mmaps[i].dtor)
+            ctx->mmaps[i].dtor(&ctx->mmaps[i]);
+    }
+
+    return VPX_CODEC_OK;
+}
+
+static vpx_codec_err_t vp8_peek_si(const uint8_t         *data,
+                                   unsigned int           data_sz,
+                                   vpx_codec_stream_info_t *si)
+{
+    vpx_codec_err_t res = VPX_CODEC_OK;
+
+    if(data + data_sz <= data)
+        res = VPX_CODEC_INVALID_PARAM;
+    else
+    {
+        /* Parse uncompresssed part of key frame header.
+         * 3 bytes:- including version, frame type and an offset
+         * 3 bytes:- sync code (0x9d, 0x01, 0x2a)
+         * 4 bytes:- including image width and height in the lowest 14 bits
+         *           of each 2-byte value.
+         */
+        si->is_kf = 0;
+
+        if (data_sz >= 10 && !(data[0] & 0x01))  /* I-Frame */
+        {
+            const uint8_t *c = data + 3;
+            si->is_kf = 1;
+
+            /* vet via sync code */
+            if (c[0] != 0x9d || c[1] != 0x01 || c[2] != 0x2a)
+                res = VPX_CODEC_UNSUP_BITSTREAM;
+
+            si->w = (c[3] | (c[4] << 8)) & 0x3fff;
+            si->h = (c[5] | (c[6] << 8)) & 0x3fff;
+
+            /*printf("w=%d, h=%d\n", si->w, si->h);*/
+            if (!(si->h | si->w))
+                res = VPX_CODEC_UNSUP_BITSTREAM;
+        }
+        else
+            res = VPX_CODEC_UNSUP_BITSTREAM;
+    }
+
+    return res;
+
+}
+
+static vpx_codec_err_t vp8_get_si(vpx_codec_alg_priv_t    *ctx,
+                                  vpx_codec_stream_info_t *si)
+{
+
+    unsigned int sz;
+
+    if (si->sz >= sizeof(vp8_stream_info_t))
+        sz = sizeof(vp8_stream_info_t);
+    else
+        sz = sizeof(vpx_codec_stream_info_t);
+
+    memcpy(si, &ctx->si, sz);
+    si->sz = sz;
+
+    return VPX_CODEC_OK;
+}
+
+
+static vpx_codec_err_t
+update_error_state(vpx_codec_alg_priv_t                 *ctx,
+                   const struct vpx_internal_error_info *error)
+{
+    vpx_codec_err_t res;
+
+    if ((res = error->error_code))
+        ctx->base.err_detail = error->has_detail
+                               ? error->detail
+                               : NULL;
+
+    return res;
+}
+
+static void yuvconfig2image(vpx_image_t               *img,
+                            const YV12_BUFFER_CONFIG  *yv12,
+                            void                      *user_priv)
+{
+    /** vpx_img_wrap() doesn't allow specifying independent strides for
+      * the Y, U, and V planes, nor other alignment adjustments that
+      * might be representable by a YV12_BUFFER_CONFIG, so we just
+      * initialize all the fields.*/
+    img->fmt = yv12->clrtype == REG_YUV ?
+        VPX_IMG_FMT_I420 : VPX_IMG_FMT_VPXI420;
+    img->w = yv12->y_stride;
+    img->h = (yv12->y_height + 2 * VP8BORDERINPIXELS + 15) & ~15;
+    img->d_w = yv12->y_width;
+    img->d_h = yv12->y_height;
+    img->x_chroma_shift = 1;
+    img->y_chroma_shift = 1;
+    img->planes[VPX_PLANE_Y] = yv12->y_buffer;
+    img->planes[VPX_PLANE_U] = yv12->u_buffer;
+    img->planes[VPX_PLANE_V] = yv12->v_buffer;
+    img->planes[VPX_PLANE_ALPHA] = NULL;
+    img->stride[VPX_PLANE_Y] = yv12->y_stride;
+    img->stride[VPX_PLANE_U] = yv12->uv_stride;
+    img->stride[VPX_PLANE_V] = yv12->uv_stride;
+    img->stride[VPX_PLANE_ALPHA] = yv12->y_stride;
+    img->bps = 12;
+    img->user_priv = user_priv;
+    img->img_data = yv12->buffer_alloc;
+    img->img_data_owner = 0;
+    img->self_allocd = 0;
+}
+
+static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t  *ctx,
+                                  const uint8_t         *data,
+                                  unsigned int            data_sz,
+                                  void                    *user_priv,
+                                  long                    deadline)
+{
+    vpx_codec_err_t res = VPX_CODEC_OK;
+
+    ctx->img_avail = 0;
+
+    /* Determine the stream parameters. Note that we rely on peek_si to
+     * validate that we have a buffer that does not wrap around the top
+     * of the heap.
+     */
+    if (!ctx->si.h)
+        res = ctx->base.iface->dec.peek_si(data, data_sz, &ctx->si);
+
+
+    /* Perform deferred allocations, if required */
+    if (!res && ctx->defer_alloc)
+    {
+        int i;
+
+        for (i = 1; !res && i < NELEMENTS(ctx->mmaps); i++)
+        {
+            vpx_codec_dec_cfg_t cfg;
+
+            cfg.w = ctx->si.w;
+            cfg.h = ctx->si.h;
+            ctx->mmaps[i].id = vp8_mem_req_segs[i].id;
+            ctx->mmaps[i].sz = vp8_mem_req_segs[i].sz;
+            ctx->mmaps[i].align = vp8_mem_req_segs[i].align;
+            ctx->mmaps[i].flags = vp8_mem_req_segs[i].flags;
+
+            if (!ctx->mmaps[i].sz)
+                ctx->mmaps[i].sz = vp8_mem_req_segs[i].calc_sz(&cfg,
+                                   ctx->base.init_flags);
+
+            res = vp8_mmap_alloc(&ctx->mmaps[i]);
+        }
+
+        if (!res)
+            vp8_finalize_mmaps(ctx);
+
+        ctx->defer_alloc = 0;
+    }
+
+    /* Initialize the decoder instance on the first frame*/
+    if (!res && !ctx->decoder_init)
+    {
+        res = vp8_validate_mmaps(&ctx->si, ctx->mmaps, ctx->base.init_flags);
+
+        if (!res)
+        {
+            VP8D_CONFIG oxcf;
+            struct VP8D_COMP* optr;
+
+            oxcf.Width = ctx->si.w;
+            oxcf.Height = ctx->si.h;
+            oxcf.Version = 9;
+            oxcf.postprocess = 0;
+            oxcf.max_threads = ctx->cfg.threads;
+            oxcf.error_concealment =
+                    (ctx->base.init_flags & VPX_CODEC_USE_ERROR_CONCEALMENT);
+            oxcf.input_fragments =
+                    (ctx->base.init_flags & VPX_CODEC_USE_INPUT_FRAGMENTS);
+
+            optr = vp8dx_create_decompressor(&oxcf);
+
+            /* If postprocessing was enabled by the application and a
+             * configuration has not been provided, default it.
+             */
+            if (!ctx->postproc_cfg_set
+                && (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC))
+            {
+                ctx->postproc_cfg.post_proc_flag =
+                    VP8_DEBLOCK | VP8_DEMACROBLOCK | VP8_MFQE;
+                ctx->postproc_cfg.deblocking_level = 4;
+                ctx->postproc_cfg.noise_level = 0;
+            }
+
+            if (!optr)
+                res = VPX_CODEC_ERROR;
+            else
+                ctx->pbi = optr;
+        }
+
+        ctx->decoder_init = 1;
+    }
+
+    if (!res && ctx->pbi)
+    {
+        YV12_BUFFER_CONFIG sd;
+        int64_t time_stamp = 0, time_end_stamp = 0;
+        vp8_ppflags_t flags = {0};
+
+        if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC)
+        {
+            flags.post_proc_flag= ctx->postproc_cfg.post_proc_flag
+#if CONFIG_POSTPROC_VISUALIZER
+
+                                | ((ctx->dbg_color_ref_frame_flag != 0) ? VP8D_DEBUG_CLR_FRM_REF_BLKS : 0)
+                                | ((ctx->dbg_color_mb_modes_flag != 0) ? VP8D_DEBUG_CLR_BLK_MODES : 0)
+                                | ((ctx->dbg_color_b_modes_flag != 0) ? VP8D_DEBUG_CLR_BLK_MODES : 0)
+                                | ((ctx->dbg_display_mv_flag != 0) ? VP8D_DEBUG_DRAW_MV : 0)
+#endif
+                                ;
+            flags.deblocking_level      = ctx->postproc_cfg.deblocking_level;
+            flags.noise_level           = ctx->postproc_cfg.noise_level;
+#if CONFIG_POSTPROC_VISUALIZER
+            flags.display_ref_frame_flag= ctx->dbg_color_ref_frame_flag;
+            flags.display_mb_modes_flag = ctx->dbg_color_mb_modes_flag;
+            flags.display_b_modes_flag  = ctx->dbg_color_b_modes_flag;
+            flags.display_mv_flag       = ctx->dbg_display_mv_flag;
+#endif
+        }
+
+        if (vp8dx_receive_compressed_data(ctx->pbi, data_sz, data, deadline))
+        {
+            VP8D_COMP *pbi = (VP8D_COMP *)ctx->pbi;
+            res = update_error_state(ctx, &pbi->common.error);
+        }
+
+        if (!res && 0 == vp8dx_get_raw_frame(ctx->pbi, &sd, &time_stamp, &time_end_stamp, &flags))
+        {
+            yuvconfig2image(&ctx->img, &sd, user_priv);
+            ctx->img_avail = 1;
+        }
+    }
+
+    return res;
+}
+
+static vpx_image_t *vp8_get_frame(vpx_codec_alg_priv_t  *ctx,
+                                  vpx_codec_iter_t      *iter)
+{
+    vpx_image_t *img = NULL;
+
+    if (ctx->img_avail)
+    {
+        /* iter acts as a flip flop, so an image is only returned on the first
+         * call to get_frame.
+         */
+        if (!(*iter))
+        {
+            img = &ctx->img;
+            *iter = img;
+        }
+    }
+
+    return img;
+}
+
+
+static
+vpx_codec_err_t vp8_xma_get_mmap(const vpx_codec_ctx_t      *ctx,
+                                 vpx_codec_mmap_t           *mmap,
+                                 vpx_codec_iter_t           *iter)
+{
+    vpx_codec_err_t     res;
+    const mem_req_t  *seg_iter = *iter;
+
+    /* Get address of next segment request */
+    do
+    {
+        if (!seg_iter)
+            seg_iter = vp8_mem_req_segs;
+        else if (seg_iter->id != VP8_SEG_MAX)
+            seg_iter++;
+
+        *iter = (vpx_codec_iter_t)seg_iter;
+
+        if (seg_iter->id != VP8_SEG_MAX)
+        {
+            mmap->id = seg_iter->id;
+            mmap->sz = seg_iter->sz;
+            mmap->align = seg_iter->align;
+            mmap->flags = seg_iter->flags;
+
+            if (!seg_iter->sz)
+                mmap->sz = seg_iter->calc_sz(ctx->config.dec, ctx->init_flags);
+
+            res = VPX_CODEC_OK;
+        }
+        else
+            res = VPX_CODEC_LIST_END;
+    }
+    while (!mmap->sz && res != VPX_CODEC_LIST_END);
+
+    return res;
+}
+
+static vpx_codec_err_t vp8_xma_set_mmap(vpx_codec_ctx_t         *ctx,
+                                        const vpx_codec_mmap_t  *mmap)
+{
+    vpx_codec_err_t res = VPX_CODEC_MEM_ERROR;
+    int i, done;
+
+    if (!ctx->priv)
+    {
+        if (mmap->id == VP8_SEG_ALG_PRIV)
+        {
+            if (!ctx->priv)
+            {
+                vp8_init_ctx(ctx, mmap);
+                res = VPX_CODEC_OK;
+            }
+        }
+    }
+
+    done = 1;
+
+    if (!res && ctx->priv->alg_priv)
+    {
+        for (i = 0; i < NELEMENTS(ctx->priv->alg_priv->mmaps); i++)
+        {
+            if (ctx->priv->alg_priv->mmaps[i].id == mmap->id)
+                if (!ctx->priv->alg_priv->mmaps[i].base)
+                {
+                    ctx->priv->alg_priv->mmaps[i] = *mmap;
+                    res = VPX_CODEC_OK;
+                }
+
+            done &= (ctx->priv->alg_priv->mmaps[i].base != NULL);
+        }
+    }
+
+    if (done && !res)
+    {
+        vp8_finalize_mmaps(ctx->priv->alg_priv);
+        res = ctx->iface->init(ctx, NULL);
+    }
+
+    return res;
+}
+
+static vpx_codec_err_t image2yuvconfig(const vpx_image_t   *img,
+                                       YV12_BUFFER_CONFIG  *yv12)
+{
+    vpx_codec_err_t        res = VPX_CODEC_OK;
+    yv12->y_buffer = img->planes[VPX_PLANE_Y];
+    yv12->u_buffer = img->planes[VPX_PLANE_U];
+    yv12->v_buffer = img->planes[VPX_PLANE_V];
+
+    yv12->y_width  = img->d_w;
+    yv12->y_height = img->d_h;
+    yv12->uv_width = yv12->y_width / 2;
+    yv12->uv_height = yv12->y_height / 2;
+
+    yv12->y_stride = img->stride[VPX_PLANE_Y];
+    yv12->uv_stride = img->stride[VPX_PLANE_U];
+
+    yv12->border  = (img->stride[VPX_PLANE_Y] - img->d_w) / 2;
+    yv12->clrtype = (img->fmt == VPX_IMG_FMT_VPXI420 || img->fmt == VPX_IMG_FMT_VPXYV12);
+
+    return res;
+}
+
+
+static vpx_codec_err_t vp8_set_reference(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+
+    vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
+
+    if (data)
+    {
+        vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
+        YV12_BUFFER_CONFIG sd;
+
+        image2yuvconfig(&frame->img, &sd);
+
+        return vp8dx_set_reference(ctx->pbi, frame->frame_type, &sd);
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+
+}
+
+static vpx_codec_err_t vp8_get_reference(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+
+    vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
+
+    if (data)
+    {
+        vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
+        YV12_BUFFER_CONFIG sd;
+
+        image2yuvconfig(&frame->img, &sd);
+
+        return vp8dx_get_reference(ctx->pbi, frame->frame_type, &sd);
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+
+}
+
+static vpx_codec_err_t vp8_set_postproc(vpx_codec_alg_priv_t *ctx,
+                                        int ctr_id,
+                                        va_list args)
+{
+#if CONFIG_POSTPROC
+    vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
+
+    if (data)
+    {
+        ctx->postproc_cfg_set = 1;
+        ctx->postproc_cfg = *((vp8_postproc_cfg_t *)data);
+        return VPX_CODEC_OK;
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+
+#else
+    return VPX_CODEC_INCAPABLE;
+#endif
+}
+
+static vpx_codec_err_t vp8_set_dbg_options(vpx_codec_alg_priv_t *ctx,
+                                        int ctrl_id,
+                                        va_list args)
+{
+#if CONFIG_POSTPROC_VISUALIZER && CONFIG_POSTPROC
+    int data = va_arg(args, int);
+
+#define MAP(id, var) case id: var = data; break;
+
+    switch (ctrl_id)
+    {
+        MAP (VP8_SET_DBG_COLOR_REF_FRAME,   ctx->dbg_color_ref_frame_flag);
+        MAP (VP8_SET_DBG_COLOR_MB_MODES,    ctx->dbg_color_mb_modes_flag);
+        MAP (VP8_SET_DBG_COLOR_B_MODES,     ctx->dbg_color_b_modes_flag);
+        MAP (VP8_SET_DBG_DISPLAY_MV,        ctx->dbg_display_mv_flag);
+    }
+
+    return VPX_CODEC_OK;
+#else
+    return VPX_CODEC_INCAPABLE;
+#endif
+}
+
+static vpx_codec_err_t vp8_get_last_ref_updates(vpx_codec_alg_priv_t *ctx,
+                                                int ctrl_id,
+                                                va_list args)
+{
+    int *update_info = va_arg(args, int *);
+    VP8D_COMP *pbi = (VP8D_COMP *)ctx->pbi;
+
+    if (update_info)
+    {
+        *update_info = pbi->common.refresh_alt_ref_frame * (int) VP8_ALTR_FRAME
+            + pbi->common.refresh_golden_frame * (int) VP8_GOLD_FRAME
+            + pbi->common.refresh_last_frame * (int) VP8_LAST_FRAME;
+
+        return VPX_CODEC_OK;
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+}
+
+extern int vp8dx_references_buffer( VP8_COMMON *oci, int ref_frame );
+static vpx_codec_err_t vp8_get_last_ref_frame(vpx_codec_alg_priv_t *ctx,
+                                              int ctrl_id,
+                                              va_list args)
+{
+    int *ref_info = va_arg(args, int *);
+    VP8D_COMP *pbi = (VP8D_COMP *)ctx->pbi;
+    VP8_COMMON *oci = &pbi->common;
+
+    if (ref_info)
+    {
+        *ref_info =
+            (vp8dx_references_buffer( oci, ALTREF_FRAME )?VP8_ALTR_FRAME:0) |
+            (vp8dx_references_buffer( oci, GOLDEN_FRAME )?VP8_GOLD_FRAME:0) |
+            (vp8dx_references_buffer( oci, LAST_FRAME )?VP8_LAST_FRAME:0);
+
+        return VPX_CODEC_OK;
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+}
+
+static vpx_codec_err_t vp8_get_frame_corrupted(vpx_codec_alg_priv_t *ctx,
+                                               int ctrl_id,
+                                               va_list args)
+{
+
+    int *corrupted = va_arg(args, int *);
+
+    if (corrupted)
+    {
+        VP8D_COMP *pbi = (VP8D_COMP *)ctx->pbi;
+        *corrupted = pbi->common.frame_to_show->corrupted;
+
+        return VPX_CODEC_OK;
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+
+}
+
+vpx_codec_ctrl_fn_map_t vp8_ctf_maps[] =
+{
+    {VP8_SET_REFERENCE,             vp8_set_reference},
+    {VP8_COPY_REFERENCE,            vp8_get_reference},
+    {VP8_SET_POSTPROC,              vp8_set_postproc},
+    {VP8_SET_DBG_COLOR_REF_FRAME,   vp8_set_dbg_options},
+    {VP8_SET_DBG_COLOR_MB_MODES,    vp8_set_dbg_options},
+    {VP8_SET_DBG_COLOR_B_MODES,     vp8_set_dbg_options},
+    {VP8_SET_DBG_DISPLAY_MV,        vp8_set_dbg_options},
+    {VP8D_GET_LAST_REF_UPDATES,     vp8_get_last_ref_updates},
+    {VP8D_GET_FRAME_CORRUPTED,      vp8_get_frame_corrupted},
+    {VP8D_GET_LAST_REF_USED,        vp8_get_last_ref_frame},
+    { -1, NULL},
+};
+
+
+#ifndef VERSION_STRING
+#define VERSION_STRING
+#endif
+CODEC_INTERFACE(vpx_codec_vp8_dx) =
+{
+    "WebM Project VP8 Decoder" VERSION_STRING,
+    VPX_CODEC_INTERNAL_ABI_VERSION,
+    VPX_CODEC_CAP_DECODER | VP8_CAP_POSTPROC | VP8_CAP_ERROR_CONCEALMENT |
+    VPX_CODEC_CAP_INPUT_FRAGMENTS,
+    /* vpx_codec_caps_t          caps; */
+    vp8_init,         /* vpx_codec_init_fn_t       init; */
+    vp8_destroy,      /* vpx_codec_destroy_fn_t    destroy; */
+    vp8_ctf_maps,     /* vpx_codec_ctrl_fn_map_t  *ctrl_maps; */
+    vp8_xma_get_mmap, /* vpx_codec_get_mmap_fn_t   get_mmap; */
+    vp8_xma_set_mmap, /* vpx_codec_set_mmap_fn_t   set_mmap; */
+    {
+        vp8_peek_si,      /* vpx_codec_peek_si_fn_t    peek_si; */
+        vp8_get_si,       /* vpx_codec_get_si_fn_t     get_si; */
+        vp8_decode,       /* vpx_codec_decode_fn_t     decode; */
+        vp8_get_frame,    /* vpx_codec_frame_get_fn_t  frame_get; */
+    },
+    { /* encoder functions */
+        NOT_IMPLEMENTED,
+        NOT_IMPLEMENTED,
+        NOT_IMPLEMENTED,
+        NOT_IMPLEMENTED,
+        NOT_IMPLEMENTED,
+        NOT_IMPLEMENTED
+    }
+};
diff --git a/vp8/vp8cx.mk b/vp8/vp8cx.mk
new file mode 100644 (file)
index 0000000..019edbd
--- /dev/null
@@ -0,0 +1,116 @@
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+
+include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8_common.mk
+
+VP8_CX_EXPORTS += exports_enc
+
+VP8_CX_SRCS-yes += $(VP8_COMMON_SRCS-yes)
+VP8_CX_SRCS-no  += $(VP8_COMMON_SRCS-no)
+VP8_CX_SRCS_REMOVE-yes += $(VP8_COMMON_SRCS_REMOVE-yes)
+VP8_CX_SRCS_REMOVE-no  += $(VP8_COMMON_SRCS_REMOVE-no)
+
+ifeq ($(ARCH_ARM),yes)
+  include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8cx_arm.mk
+endif
+
+VP8_CX_SRCS-yes += vp8_cx_iface.c
+
+# encoder
+#INCLUDES += algo/vpx_common/vpx_mem/include
+#INCLUDES += common
+#INCLUDES += common
+#INCLUDES += common
+#INCLUDES += algo/vpx_ref/cpu_id/include
+#INCLUDES += common
+#INCLUDES += encoder
+
+VP8_CX_SRCS-yes += encoder/asm_enc_offsets.c
+VP8_CX_SRCS-yes += encoder/defaultcoefcounts.h
+VP8_CX_SRCS-yes += encoder/bitstream.c
+VP8_CX_SRCS-yes += encoder/boolhuff.c
+VP8_CX_SRCS-yes += encoder/dct.c
+VP8_CX_SRCS-yes += encoder/encodeframe.c
+VP8_CX_SRCS-yes += encoder/encodeframe.h
+VP8_CX_SRCS-yes += encoder/encodeintra.c
+VP8_CX_SRCS-yes += encoder/encodemb.c
+VP8_CX_SRCS-yes += encoder/encodemv.c
+VP8_CX_SRCS-$(CONFIG_MULTITHREAD) += encoder/ethreading.c
+VP8_CX_SRCS-yes += encoder/firstpass.c
+VP8_CX_SRCS-yes += encoder/block.h
+VP8_CX_SRCS-yes += encoder/boolhuff.h
+VP8_CX_SRCS-yes += encoder/bitstream.h
+VP8_CX_SRCS-$(CONFIG_TEMPORAL_DENOISING) += encoder/denoising.h
+VP8_CX_SRCS-$(CONFIG_TEMPORAL_DENOISING) += encoder/denoising.c
+VP8_CX_SRCS-yes += encoder/encodeintra.h
+VP8_CX_SRCS-yes += encoder/encodemb.h
+VP8_CX_SRCS-yes += encoder/encodemv.h
+VP8_CX_SRCS-yes += encoder/firstpass.h
+VP8_CX_SRCS-yes += encoder/lookahead.c
+VP8_CX_SRCS-yes += encoder/lookahead.h
+VP8_CX_SRCS-yes += encoder/mcomp.h
+VP8_CX_SRCS-yes += encoder/modecosts.h
+VP8_CX_SRCS-yes += encoder/onyx_int.h
+VP8_CX_SRCS-yes += encoder/pickinter.h
+VP8_CX_SRCS-yes += encoder/psnr.h
+VP8_CX_SRCS-yes += encoder/quantize.h
+VP8_CX_SRCS-yes += encoder/ratectrl.h
+VP8_CX_SRCS-yes += encoder/rdopt.h
+VP8_CX_SRCS-yes += encoder/tokenize.h
+VP8_CX_SRCS-yes += encoder/treewriter.h
+VP8_CX_SRCS-yes += encoder/mcomp.c
+VP8_CX_SRCS-yes += encoder/modecosts.c
+VP8_CX_SRCS-yes += encoder/onyx_if.c
+VP8_CX_SRCS-yes += encoder/pickinter.c
+VP8_CX_SRCS-yes += encoder/picklpf.c
+VP8_CX_SRCS-yes += encoder/psnr.c
+VP8_CX_SRCS-yes += encoder/quantize.c
+VP8_CX_SRCS-yes += encoder/ratectrl.c
+VP8_CX_SRCS-yes += encoder/rdopt.c
+VP8_CX_SRCS-yes += encoder/segmentation.c
+VP8_CX_SRCS-yes += encoder/segmentation.h
+VP8_CX_SRCS-$(CONFIG_INTERNAL_STATS) += encoder/ssim.c
+VP8_CX_SRCS-yes += encoder/tokenize.c
+VP8_CX_SRCS-yes += encoder/dct_value_cost.h
+VP8_CX_SRCS-yes += encoder/dct_value_tokens.h
+VP8_CX_SRCS-yes += encoder/treewriter.c
+VP8_CX_SRCS-$(CONFIG_INTERNAL_STATS) += common/postproc.h
+VP8_CX_SRCS-$(CONFIG_INTERNAL_STATS) += common/postproc.c
+VP8_CX_SRCS-yes += encoder/temporal_filter.c
+VP8_CX_SRCS-$(CONFIG_MULTI_RES_ENCODING) += encoder/mr_dissim.c
+VP8_CX_SRCS-$(CONFIG_MULTI_RES_ENCODING) += encoder/mr_dissim.h
+
+ifeq ($(CONFIG_REALTIME_ONLY),yes)
+VP8_CX_SRCS_REMOVE-yes += encoder/firstpass.c
+VP8_CX_SRCS_REMOVE-yes += encoder/temporal_filter.c
+endif
+
+VP8_CX_SRCS-$(HAVE_MMX) += encoder/x86/dct_mmx.asm
+VP8_CX_SRCS-$(HAVE_MMX) += encoder/x86/subtract_mmx.asm
+VP8_CX_SRCS-$(HAVE_MMX) += encoder/x86/vp8_enc_stubs_mmx.c
+VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/dct_sse2.asm
+VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/fwalsh_sse2.asm
+VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/quantize_sse2.asm
+VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/subtract_sse2.asm
+VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/temporal_filter_apply_sse2.asm
+VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp8_enc_stubs_sse2.c
+VP8_CX_SRCS-$(HAVE_SSSE3) += encoder/x86/quantize_ssse3.asm
+VP8_CX_SRCS-$(HAVE_SSE4_1) += encoder/x86/quantize_sse4.asm
+VP8_CX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += encoder/x86/quantize_mmx.asm
+VP8_CX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += encoder/x86/encodeopt.asm
+VP8_CX_SRCS-$(ARCH_X86_64) += encoder/x86/ssim_opt.asm
+
+ifeq ($(CONFIG_REALTIME_ONLY),yes)
+VP8_CX_SRCS_REMOVE-$(HAVE_SSE2) += encoder/x86/temporal_filter_apply_sse2.asm
+endif
+
+
+VP8_CX_SRCS-yes := $(filter-out $(VP8_CX_SRCS_REMOVE-yes),$(VP8_CX_SRCS-yes))
diff --git a/vp8/vp8cx_arm.mk b/vp8/vp8cx_arm.mk
new file mode 100644 (file)
index 0000000..b16615d
--- /dev/null
@@ -0,0 +1,44 @@
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+
+#VP8_CX_SRCS list is modified according to different platforms.
+
+#File list for arm
+# encoder
+VP8_CX_SRCS-$(ARCH_ARM)  += encoder/arm/dct_arm.c
+VP8_CX_SRCS-$(ARCH_ARM)  += encoder/arm/quantize_arm.c
+
+#File list for edsp
+# encoder
+VP8_CX_SRCS-$(HAVE_EDSP) += encoder/arm/boolhuff_arm.c
+VP8_CX_SRCS_REMOVE-$(HAVE_EDSP)  += encoder/boolhuff.c
+VP8_CX_SRCS-$(HAVE_EDSP)  += encoder/arm/armv5te/boolhuff_armv5te$(ASM)
+VP8_CX_SRCS-$(HAVE_EDSP)  += encoder/arm/armv5te/vp8_packtokens_armv5$(ASM)
+VP8_CX_SRCS-$(HAVE_EDSP)  += encoder/arm/armv5te/vp8_packtokens_mbrow_armv5$(ASM)
+VP8_CX_SRCS-$(HAVE_EDSP)  += encoder/arm/armv5te/vp8_packtokens_partitions_armv5$(ASM)
+
+#File list for media
+# encoder
+VP8_CX_SRCS-$(HAVE_MEDIA)  += encoder/arm/armv6/vp8_subtract_armv6$(ASM)
+VP8_CX_SRCS-$(HAVE_MEDIA)  += encoder/arm/armv6/vp8_short_fdct4x4_armv6$(ASM)
+VP8_CX_SRCS-$(HAVE_MEDIA)  += encoder/arm/armv6/vp8_fast_quantize_b_armv6$(ASM)
+VP8_CX_SRCS-$(HAVE_MEDIA)  += encoder/arm/armv6/vp8_mse16x16_armv6$(ASM)
+VP8_CX_SRCS-$(HAVE_MEDIA)  += encoder/arm/armv6/walsh_v6$(ASM)
+
+#File list for neon
+# encoder
+VP8_CX_SRCS-$(HAVE_NEON)  += encoder/arm/neon/fastquantizeb_neon$(ASM)
+VP8_CX_SRCS-$(HAVE_NEON)  += encoder/arm/neon/picklpf_arm.c
+VP8_CX_SRCS-$(HAVE_NEON)  += encoder/arm/neon/shortfdct_neon$(ASM)
+VP8_CX_SRCS-$(HAVE_NEON)  += encoder/arm/neon/subtract_neon$(ASM)
+VP8_CX_SRCS-$(HAVE_NEON)  += encoder/arm/neon/vp8_mse16x16_neon$(ASM)
+VP8_CX_SRCS-$(HAVE_NEON)  += encoder/arm/neon/vp8_memcpy_neon$(ASM)
+VP8_CX_SRCS-$(HAVE_NEON)  += encoder/arm/neon/vp8_shortwalsh4x4_neon$(ASM)
diff --git a/vp8/vp8dx.mk b/vp8/vp8dx.mk
new file mode 100644 (file)
index 0000000..2cfd280
--- /dev/null
@@ -0,0 +1,64 @@
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+
+include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8_common.mk
+
+VP8_DX_EXPORTS += exports_dec
+
+VP8_DX_SRCS-yes += $(VP8_COMMON_SRCS-yes)
+VP8_DX_SRCS-no  += $(VP8_COMMON_SRCS-no)
+VP8_DX_SRCS_REMOVE-yes += $(VP8_COMMON_SRCS_REMOVE-yes)
+VP8_DX_SRCS_REMOVE-no  += $(VP8_COMMON_SRCS_REMOVE-no)
+
+VP8_DX_SRCS-yes += vp8_dx_iface.c
+
+# common
+#define ARM
+#define DISABLE_THREAD
+
+#INCLUDES += algo/vpx_common/vpx_mem/include
+#INCLUDES += common
+#INCLUDES += common
+#INCLUDES += common
+#INCLUDES += common
+#INCLUDES += decoder
+
+
+
+# decoder
+#define ARM
+#define DISABLE_THREAD
+
+#INCLUDES += algo/vpx_common/vpx_mem/include
+#INCLUDES += common
+#INCLUDES += common
+#INCLUDES += common
+#INCLUDES += common
+#INCLUDES += decoder
+
+VP8_DX_SRCS-yes += decoder/asm_dec_offsets.c
+VP8_DX_SRCS-yes += decoder/dboolhuff.c
+VP8_DX_SRCS-yes += decoder/decodemv.c
+VP8_DX_SRCS-yes += decoder/decodframe.c
+VP8_DX_SRCS-yes += decoder/detokenize.c
+VP8_DX_SRCS-$(CONFIG_ERROR_CONCEALMENT) += decoder/ec_types.h
+VP8_DX_SRCS-$(CONFIG_ERROR_CONCEALMENT) += decoder/error_concealment.h
+VP8_DX_SRCS-$(CONFIG_ERROR_CONCEALMENT) += decoder/error_concealment.c
+VP8_DX_SRCS-yes += decoder/dboolhuff.h
+VP8_DX_SRCS-yes += decoder/decodemv.h
+VP8_DX_SRCS-yes += decoder/decoderthreading.h
+VP8_DX_SRCS-yes += decoder/detokenize.h
+VP8_DX_SRCS-yes += decoder/onyxd_int.h
+VP8_DX_SRCS-yes += decoder/treereader.h
+VP8_DX_SRCS-yes += decoder/onyxd_if.c
+VP8_DX_SRCS-$(CONFIG_MULTITHREAD) += decoder/threading.c
+
+VP8_DX_SRCS-yes := $(filter-out $(VP8_DX_SRCS_REMOVE-yes),$(VP8_DX_SRCS-yes))
diff --git a/vp8_multi_resolution_encoder.c b/vp8_multi_resolution_encoder.c
new file mode 100644 (file)
index 0000000..78f50c2
--- /dev/null
@@ -0,0 +1,476 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * This is an example demonstrating multi-resolution encoding in VP8.
+ * High-resolution input video is down-sampled to lower-resolutions. The
+ * encoder then encodes the video and outputs multiple bitstreams with
+ * different resolutions.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include "math.h"
+#define VPX_CODEC_DISABLE_COMPAT 1
+#include "vpx/vpx_encoder.h"
+#include "vpx/vp8cx.h"
+#include "vpx_ports/mem_ops.h"
+#define interface (vpx_codec_vp8_cx())
+#define fourcc    0x30385056
+
+#define IVF_FILE_HDR_SZ  (32)
+#define IVF_FRAME_HDR_SZ (12)
+
+/*
+ * The input video frame is downsampled several times to generate a multi-level
+ * hierarchical structure. NUM_ENCODERS is defined as the number of encoding
+ * levels required. For example, if the size of input video is 1280x720,
+ * NUM_ENCODERS is 3, and down-sampling factor is 2, the encoder outputs 3
+ * bitstreams with resolution of 1280x720(level 0), 640x360(level 1), and
+ * 320x180(level 2) respectively.
+ */
+#define NUM_ENCODERS 3
+
+/* This example uses the scaler function in libyuv. */
+#include "third_party/libyuv/include/libyuv/basic_types.h"
+#include "third_party/libyuv/include/libyuv/scale.h"
+#include "third_party/libyuv/include/libyuv/cpu_id.h"
+
+static double vp8_mse2psnr(double Samples, double Peak, double Mse)
+{
+    double psnr;
+
+    if ((double)Mse > 0.0)
+        psnr = 10.0 * log10(Peak * Peak * Samples / Mse);
+    else
+        psnr = 60;      // Limit to prevent / 0
+
+    if (psnr > 60)
+        psnr = 60;
+
+    return psnr;
+}
+
+static void die(const char *fmt, ...) {
+    va_list ap;
+
+    va_start(ap, fmt);
+    vprintf(fmt, ap);
+    if(fmt[strlen(fmt)-1] != '\n')
+        printf("\n");
+    exit(EXIT_FAILURE);
+}
+
+static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
+    const char *detail = vpx_codec_error_detail(ctx);
+
+    printf("%s: %s\n", s, vpx_codec_error(ctx));
+    if(detail)
+        printf("    %s\n",detail);
+    exit(EXIT_FAILURE);
+}
+
+int (*read_frame_p)(FILE *f, vpx_image_t *img);
+
+static int read_frame(FILE *f, vpx_image_t *img) {
+    size_t nbytes, to_read;
+    int    res = 1;
+
+    to_read = img->w*img->h*3/2;
+    nbytes = fread(img->planes[0], 1, to_read, f);
+    if(nbytes != to_read) {
+        res = 0;
+        if(nbytes > 0)
+            printf("Warning: Read partial frame. Check your width & height!\n");
+    }
+    return res;
+}
+
+static int read_frame_by_row(FILE *f, vpx_image_t *img) {
+    size_t nbytes, to_read;
+    int    res = 1;
+    int plane;
+
+    for (plane = 0; plane < 3; plane++)
+    {
+        unsigned char *ptr;
+        int w = (plane ? (1 + img->d_w) / 2 : img->d_w);
+        int h = (plane ? (1 + img->d_h) / 2 : img->d_h);
+        int r;
+
+        /* Determine the correct plane based on the image format. The for-loop
+         * always counts in Y,U,V order, but this may not match the order of
+         * the data on disk.
+         */
+        switch (plane)
+        {
+        case 1:
+            ptr = img->planes[img->fmt==VPX_IMG_FMT_YV12? VPX_PLANE_V : VPX_PLANE_U];
+            break;
+        case 2:
+            ptr = img->planes[img->fmt==VPX_IMG_FMT_YV12?VPX_PLANE_U : VPX_PLANE_V];
+            break;
+        default:
+            ptr = img->planes[plane];
+        }
+
+        for (r = 0; r < h; r++)
+        {
+            to_read = w;
+
+            nbytes = fread(ptr, 1, to_read, f);
+            if(nbytes != to_read) {
+                res = 0;
+                if(nbytes > 0)
+                    printf("Warning: Read partial frame. Check your width & height!\n");
+                break;
+            }
+
+            ptr += img->stride[plane];
+        }
+        if (!res)
+            break;
+    }
+
+    return res;
+}
+
+static void write_ivf_file_header(FILE *outfile,
+                                  const vpx_codec_enc_cfg_t *cfg,
+                                  int frame_cnt) {
+    char header[32];
+
+    if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
+        return;
+    header[0] = 'D';
+    header[1] = 'K';
+    header[2] = 'I';
+    header[3] = 'F';
+    mem_put_le16(header+4,  0);                   /* version */
+    mem_put_le16(header+6,  32);                  /* headersize */
+    mem_put_le32(header+8,  fourcc);              /* headersize */
+    mem_put_le16(header+12, cfg->g_w);            /* width */
+    mem_put_le16(header+14, cfg->g_h);            /* height */
+    mem_put_le32(header+16, cfg->g_timebase.den); /* rate */
+    mem_put_le32(header+20, cfg->g_timebase.num); /* scale */
+    mem_put_le32(header+24, frame_cnt);           /* length */
+    mem_put_le32(header+28, 0);                   /* unused */
+
+    if(fwrite(header, 1, 32, outfile));
+}
+
+static void write_ivf_frame_header(FILE *outfile,
+                                   const vpx_codec_cx_pkt_t *pkt)
+{
+    char             header[12];
+    vpx_codec_pts_t  pts;
+
+    if(pkt->kind != VPX_CODEC_CX_FRAME_PKT)
+        return;
+
+    pts = pkt->data.frame.pts;
+    mem_put_le32(header, pkt->data.frame.sz);
+    mem_put_le32(header+4, pts&0xFFFFFFFF);
+    mem_put_le32(header+8, pts >> 32);
+
+    if(fwrite(header, 1, 12, outfile));
+}
+
+int main(int argc, char **argv)
+{
+    FILE                *infile, *outfile[NUM_ENCODERS];
+    vpx_codec_ctx_t      codec[NUM_ENCODERS];
+    vpx_codec_enc_cfg_t  cfg[NUM_ENCODERS];
+    vpx_codec_pts_t      frame_cnt = 0;
+    vpx_image_t          raw[NUM_ENCODERS];
+    vpx_codec_err_t      res[NUM_ENCODERS];
+
+    int                  i;
+    long                 width;
+    long                 height;
+    int                  frame_avail;
+    int                  got_data;
+    int                  flags = 0;
+
+    /*Currently, only realtime mode is supported in multi-resolution encoding.*/
+    int                  arg_deadline = VPX_DL_REALTIME;
+
+    /* Set show_psnr to 1/0 to show/not show PSNR. Choose show_psnr=0 if you
+       don't need to know PSNR, which will skip PSNR calculation and save
+       encoding time. */
+    int                  show_psnr = 0;
+    uint64_t             psnr_sse_total[NUM_ENCODERS] = {0};
+    uint64_t             psnr_samples_total[NUM_ENCODERS] = {0};
+    double               psnr_totals[NUM_ENCODERS][4] = {{0,0}};
+    int                  psnr_count[NUM_ENCODERS] = {0};
+
+    /* Set the required target bitrates for each resolution level.
+     * If target bitrate for highest-resolution level is set to 0,
+     * (i.e. target_bitrate[0]=0), we skip encoding at that level.
+     */
+    unsigned int         target_bitrate[NUM_ENCODERS]={1400, 500, 100};
+    /* Enter the frame rate of the input video */
+    int                  framerate = 30;
+    /* Set down-sampling factor for each resolution level.
+       dsf[0] controls down sampling from level 0 to level 1;
+       dsf[1] controls down sampling from level 1 to level 2;
+       dsf[2] is not used. */
+    vpx_rational_t dsf[NUM_ENCODERS] = {{2, 1}, {2, 1}, {1, 1}};
+
+    if(argc!= (5+NUM_ENCODERS))
+        die("Usage: %s <width> <height> <infile> <outfile(s)> <output psnr?>\n",
+            argv[0]);
+
+    printf("Using %s\n",vpx_codec_iface_name(interface));
+
+    width = strtol(argv[1], NULL, 0);
+    height = strtol(argv[2], NULL, 0);
+
+    if(width < 16 || width%2 || height <16 || height%2)
+        die("Invalid resolution: %ldx%ld", width, height);
+
+    /* Open input video file for encoding */
+    if(!(infile = fopen(argv[3], "rb")))
+        die("Failed to open %s for reading", argv[3]);
+
+    /* Open output file for each encoder to output bitstreams */
+    for (i=0; i< NUM_ENCODERS; i++)
+    {
+        if(!target_bitrate[i])
+        {
+            outfile[i] = NULL;
+            continue;
+        }
+
+        if(!(outfile[i] = fopen(argv[i+4], "wb")))
+            die("Failed to open %s for writing", argv[i+4]);
+    }
+
+    show_psnr = strtol(argv[NUM_ENCODERS + 4], NULL, 0);
+
+    /* Populate default encoder configuration */
+    for (i=0; i< NUM_ENCODERS; i++)
+    {
+        res[i] = vpx_codec_enc_config_default(interface, &cfg[i], 0);
+        if(res[i]) {
+            printf("Failed to get config: %s\n", vpx_codec_err_to_string(res[i]));
+            return EXIT_FAILURE;
+        }
+    }
+
+    /*
+     * Update the default configuration according to needs of the application.
+     */
+    /* Highest-resolution encoder settings */
+    cfg[0].g_w = width;
+    cfg[0].g_h = height;
+    cfg[0].g_threads = 1;                           /* number of threads used */
+    cfg[0].rc_dropframe_thresh = 0;
+    cfg[0].rc_end_usage = VPX_CBR;
+    cfg[0].rc_resize_allowed = 0;
+    cfg[0].rc_min_quantizer = 4;
+    cfg[0].rc_max_quantizer = 56;
+    cfg[0].rc_undershoot_pct = 98;
+    cfg[0].rc_overshoot_pct = 100;
+    cfg[0].rc_buf_initial_sz = 500;
+    cfg[0].rc_buf_optimal_sz = 600;
+    cfg[0].rc_buf_sz = 1000;
+    //cfg[0].rc_dropframe_thresh = 10;
+    cfg[0].g_error_resilient = 1;              /* Enable error resilient mode */
+    cfg[0].g_lag_in_frames   = 0;
+
+    /* Disable automatic keyframe placement */
+    //cfg[0].kf_mode           = VPX_KF_DISABLED;
+    cfg[0].kf_min_dist = cfg[0].kf_max_dist = 1000;
+
+    cfg[0].rc_target_bitrate = target_bitrate[0];       /* Set target bitrate */
+    cfg[0].g_timebase.num = 1;                          /* Set fps */
+    cfg[0].g_timebase.den = framerate;
+
+    /* Other-resolution encoder settings */
+    for (i=1; i< NUM_ENCODERS; i++)
+    {
+        memcpy(&cfg[i], &cfg[0], sizeof(vpx_codec_enc_cfg_t));
+
+        cfg[i].g_threads = 1;                       /* number of threads used */
+        cfg[i].rc_target_bitrate = target_bitrate[i];
+
+        /* Note: Width & height of other-resolution encoders are calculated
+         * from the highest-resolution encoder's size and the corresponding
+         * down_sampling_factor.
+         */
+        {
+            unsigned int iw = cfg[i-1].g_w*dsf[i-1].den + dsf[i-1].num - 1;
+            unsigned int ih = cfg[i-1].g_h*dsf[i-1].den + dsf[i-1].num - 1;
+            cfg[i].g_w = iw/dsf[i-1].num;
+            cfg[i].g_h = ih/dsf[i-1].num;
+        }
+
+        /* Make width & height to be multiplier of 2. */
+        // Should support odd size ???
+        if((cfg[i].g_w)%2)cfg[i].g_w++;
+        if((cfg[i].g_h)%2)cfg[i].g_h++;
+    }
+
+    /* Allocate image for each encoder */
+    for (i=0; i< NUM_ENCODERS; i++)
+        if(!vpx_img_alloc(&raw[i], VPX_IMG_FMT_I420, cfg[i].g_w, cfg[i].g_h, 32))
+            die("Failed to allocate image", cfg[i].g_w, cfg[i].g_h);
+
+    if (raw[0].stride[VPX_PLANE_Y] == raw[0].d_w)
+        read_frame_p = read_frame;
+    else
+        read_frame_p = read_frame_by_row;
+
+    for (i=0; i< NUM_ENCODERS; i++)
+        if(outfile[i])
+            write_ivf_file_header(outfile[i], &cfg[i], 0);
+
+    /* Initialize multi-encoder */
+    if(vpx_codec_enc_init_multi(&codec[0], interface, &cfg[0], NUM_ENCODERS,
+                                (show_psnr ? VPX_CODEC_USE_PSNR : 0), &dsf[0]))
+        die_codec(&codec[0], "Failed to initialize encoder");
+
+    /* The extra encoding configuration parameters can be set as follows. */
+    /* Set encoding speed */
+    for ( i=0; i<NUM_ENCODERS; i++)
+    {
+        int speed = -6;
+        if(vpx_codec_control(&codec[i], VP8E_SET_CPUUSED, speed))
+            die_codec(&codec[i], "Failed to set cpu_used");
+    }
+    /* Set static thresh for highest-resolution encoder. Set it to 1000 for
+     * better performance. */
+    {
+        unsigned int static_thresh = 1000;
+        if(vpx_codec_control(&codec[0], VP8E_SET_STATIC_THRESHOLD, static_thresh))
+            die_codec(&codec[0], "Failed to set static threshold");
+    }
+    /* Set static thresh = 0 for other encoders for better quality */
+    for ( i=1; i<NUM_ENCODERS; i++)
+    {
+        unsigned int static_thresh = 0;
+        if(vpx_codec_control(&codec[i], VP8E_SET_STATIC_THRESHOLD, static_thresh))
+            die_codec(&codec[i], "Failed to set static threshold");
+    }
+
+    frame_avail = 1;
+    got_data = 0;
+
+    while(frame_avail || got_data)
+    {
+        vpx_codec_iter_t iter[NUM_ENCODERS]={NULL};
+        const vpx_codec_cx_pkt_t *pkt[NUM_ENCODERS];
+
+        flags = 0;
+        frame_avail = read_frame_p(infile, &raw[0]);
+
+        if(frame_avail)
+        {
+            for ( i=1; i<NUM_ENCODERS; i++)
+            {
+                /*Scale the image down a number of times by downsampling factor*/
+                /* FilterMode 1 or 2 give better psnr than FilterMode 0. */
+                I420Scale(raw[i-1].planes[VPX_PLANE_Y], raw[i-1].stride[VPX_PLANE_Y],
+                          raw[i-1].planes[VPX_PLANE_U], raw[i-1].stride[VPX_PLANE_U],
+                          raw[i-1].planes[VPX_PLANE_V], raw[i-1].stride[VPX_PLANE_V],
+                          raw[i-1].d_w, raw[i-1].d_h,
+                          raw[i].planes[VPX_PLANE_Y], raw[i].stride[VPX_PLANE_Y],
+                          raw[i].planes[VPX_PLANE_U], raw[i].stride[VPX_PLANE_U],
+                          raw[i].planes[VPX_PLANE_V], raw[i].stride[VPX_PLANE_V],
+                          raw[i].d_w, raw[i].d_h, 1);
+            }
+        }
+
+        /* Encode each frame at multi-levels */
+        if(vpx_codec_encode(&codec[0], frame_avail? &raw[0] : NULL,
+            frame_cnt, 1, flags, arg_deadline))
+            die_codec(&codec[0], "Failed to encode frame");
+
+        for (i=NUM_ENCODERS-1; i>=0 ; i--)
+        {
+            got_data = 0;
+
+            while( (pkt[i] = vpx_codec_get_cx_data(&codec[i], &iter[i])) )
+            {
+                got_data = 1;
+                switch(pkt[i]->kind) {
+                    case VPX_CODEC_CX_FRAME_PKT:
+                        write_ivf_frame_header(outfile[i], pkt[i]);
+                        if(fwrite(pkt[i]->data.frame.buf, 1, pkt[i]->data.frame.sz,
+                                  outfile[i]));
+                    break;
+                    case VPX_CODEC_PSNR_PKT:
+                        if (show_psnr)
+                        {
+                            int j;
+
+                            psnr_sse_total[i] += pkt[i]->data.psnr.sse[0];
+                            psnr_samples_total[i] += pkt[i]->data.psnr.samples[0];
+                            for (j = 0; j < 4; j++)
+                            {
+                                //fprintf(stderr, "%.3lf ", pkt[i]->data.psnr.psnr[j]);
+                                psnr_totals[i][j] += pkt[i]->data.psnr.psnr[j];
+                            }
+                            psnr_count[i]++;
+                        }
+
+                        break;
+                    default:
+                        break;
+                }
+                printf(pkt[i]->kind == VPX_CODEC_CX_FRAME_PKT
+                       && (pkt[i]->data.frame.flags & VPX_FRAME_IS_KEY)? "K":".");
+                fflush(stdout);
+            }
+        }
+        frame_cnt++;
+    }
+    printf("\n");
+
+    fclose(infile);
+
+    printf("Processed %ld frames.\n",(long int)frame_cnt-1);
+    for (i=0; i< NUM_ENCODERS; i++)
+    {
+        /* Calculate PSNR and print it out */
+        if ( (show_psnr) && (psnr_count[i]>0) )
+        {
+            int j;
+            double ovpsnr = vp8_mse2psnr(psnr_samples_total[i], 255.0,
+                                         psnr_sse_total[i]);
+
+            fprintf(stderr, "\n ENC%d PSNR (Overall/Avg/Y/U/V)", i);
+
+            fprintf(stderr, " %.3lf", ovpsnr);
+            for (j = 0; j < 4; j++)
+            {
+                fprintf(stderr, " %.3lf", psnr_totals[i][j]/psnr_count[i]);
+            }
+        }
+
+        if(vpx_codec_destroy(&codec[i]))
+            die_codec(&codec[i], "Failed to destroy codec");
+
+        vpx_img_free(&raw[i]);
+
+        if(!outfile[i])
+            continue;
+
+        /* Try to rewrite the file header with the actual frame count */
+        if(!fseek(outfile[i], 0, SEEK_SET))
+            write_ivf_file_header(outfile[i], &cfg[i], frame_cnt-1);
+        fclose(outfile[i]);
+    }
+    printf("\n");
+
+    return EXIT_SUCCESS;
+}
diff --git a/vp8_scalable_patterns.c b/vp8_scalable_patterns.c
new file mode 100644 (file)
index 0000000..4311b1a
--- /dev/null
@@ -0,0 +1,565 @@
+/*
+ *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This is an example demonstrating how to implement a multi-layer VP8
+ * encoding scheme based on temporal scalability for video applications
+ * that benefit from a scalable bitstream.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#define VPX_CODEC_DISABLE_COMPAT 1
+#include "vpx/vpx_encoder.h"
+#include "vpx/vp8cx.h"
+#define interface (vpx_codec_vp8_cx())
+#define fourcc    0x30385056
+
+#define IVF_FILE_HDR_SZ  (32)
+#define IVF_FRAME_HDR_SZ (12)
+
+static void mem_put_le16(char *mem, unsigned int val) {
+    mem[0] = val;
+    mem[1] = val>>8;
+}
+
+static void mem_put_le32(char *mem, unsigned int val) {
+    mem[0] = val;
+    mem[1] = val>>8;
+    mem[2] = val>>16;
+    mem[3] = val>>24;
+}
+
+static void die(const char *fmt, ...) {
+    va_list ap;
+
+    va_start(ap, fmt);
+    vprintf(fmt, ap);
+    if(fmt[strlen(fmt)-1] != '\n')
+        printf("\n");
+    exit(EXIT_FAILURE);
+}
+
+static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
+    const char *detail = vpx_codec_error_detail(ctx);
+
+    printf("%s: %s\n", s, vpx_codec_error(ctx));
+    if(detail)
+        printf("    %s\n",detail);
+    exit(EXIT_FAILURE);
+}
+
+static int read_frame(FILE *f, vpx_image_t *img) {
+    size_t nbytes, to_read;
+    int    res = 1;
+
+    to_read = img->w*img->h*3/2;
+    nbytes = fread(img->planes[0], 1, to_read, f);
+    if(nbytes != to_read) {
+        res = 0;
+        if(nbytes > 0)
+            printf("Warning: Read partial frame. Check your width & height!\n");
+    }
+    return res;
+}
+
+static void write_ivf_file_header(FILE *outfile,
+                                  const vpx_codec_enc_cfg_t *cfg,
+                                  int frame_cnt) {
+    char header[32];
+
+    if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
+        return;
+    header[0] = 'D';
+    header[1] = 'K';
+    header[2] = 'I';
+    header[3] = 'F';
+    mem_put_le16(header+4,  0);                   /* version */
+    mem_put_le16(header+6,  32);                  /* headersize */
+    mem_put_le32(header+8,  fourcc);              /* headersize */
+    mem_put_le16(header+12, cfg->g_w);            /* width */
+    mem_put_le16(header+14, cfg->g_h);            /* height */
+    mem_put_le32(header+16, cfg->g_timebase.den); /* rate */
+    mem_put_le32(header+20, cfg->g_timebase.num); /* scale */
+    mem_put_le32(header+24, frame_cnt);           /* length */
+    mem_put_le32(header+28, 0);                   /* unused */
+
+    if(fwrite(header, 1, 32, outfile));
+}
+
+
+static void write_ivf_frame_header(FILE *outfile,
+                                   const vpx_codec_cx_pkt_t *pkt)
+{
+    char             header[12];
+    vpx_codec_pts_t  pts;
+
+    if(pkt->kind != VPX_CODEC_CX_FRAME_PKT)
+        return;
+
+    pts = pkt->data.frame.pts;
+    mem_put_le32(header, pkt->data.frame.sz);
+    mem_put_le32(header+4, pts&0xFFFFFFFF);
+    mem_put_le32(header+8, pts >> 32);
+
+    if(fwrite(header, 1, 12, outfile));
+}
+
+static int mode_to_num_layers[9] = {2, 2, 3, 3, 3, 3, 5, 2, 3};
+
+int main(int argc, char **argv) {
+    FILE                *infile, *outfile[VPX_TS_MAX_LAYERS];
+    vpx_codec_ctx_t      codec;
+    vpx_codec_enc_cfg_t  cfg;
+    int                  frame_cnt = 0;
+    vpx_image_t          raw;
+    vpx_codec_err_t      res;
+    unsigned int         width;
+    unsigned int         height;
+    int                  frame_avail;
+    int                  got_data;
+    int                  flags = 0;
+    int                  i;
+    int                  pts = 0;              // PTS starts at 0
+    int                  frame_duration = 1;   // 1 timebase tick per frame
+
+    int                  layering_mode = 0;
+    int                  frames_in_layer[VPX_TS_MAX_LAYERS] = {0};
+    int                  layer_flags[VPX_TS_MAX_PERIODICITY] = {0};
+    int                  flag_periodicity;
+    int                  max_intra_size_pct;
+
+    // Check usage and arguments
+    if (argc < 9)
+        die("Usage: %s <infile> <outfile> <width> <height> <rate_num> "
+            " <rate_den> <mode> <Rate_0> ... <Rate_nlayers-1>\n", argv[0]);
+
+    width  = strtol (argv[3], NULL, 0);
+    height = strtol (argv[4], NULL, 0);
+    if (width < 16 || width%2 || height <16 || height%2)
+        die ("Invalid resolution: %d x %d", width, height);
+
+    if (!sscanf(argv[7], "%d", &layering_mode))
+        die ("Invalid mode %s", argv[7]);
+    if (layering_mode<0 || layering_mode>8)
+        die ("Invalid mode (0..8) %s", argv[7]);
+
+    if (argc != 8+mode_to_num_layers[layering_mode])
+        die ("Invalid number of arguments");
+
+    if (!vpx_img_alloc (&raw, VPX_IMG_FMT_I420, width, height, 1))
+        die ("Failed to allocate image", width, height);
+
+    printf("Using %s\n",vpx_codec_iface_name(interface));
+
+    // Populate encoder configuration
+    res = vpx_codec_enc_config_default(interface, &cfg, 0);
+    if(res) {
+        printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
+        return EXIT_FAILURE;
+    }
+
+    // Update the default configuration with our settings
+    cfg.g_w = width;
+    cfg.g_h = height;
+
+    // Timebase format e.g. 30fps: numerator=1, demoninator=30
+    if (!sscanf (argv[5], "%d", &cfg.g_timebase.num ))
+        die ("Invalid timebase numerator %s", argv[5]);
+    if (!sscanf (argv[6], "%d", &cfg.g_timebase.den ))
+        die ("Invalid timebase denominator %s", argv[6]);
+
+    for (i=8; i<8+mode_to_num_layers[layering_mode]; i++)
+        if (!sscanf(argv[i], "%d", &cfg.ts_target_bitrate[i-8]))
+            die ("Invalid data rate %s", argv[i]);
+
+    // Real time parameters
+    cfg.rc_dropframe_thresh = 0;  // 30
+    cfg.rc_end_usage        = VPX_CBR;
+    cfg.rc_resize_allowed   = 0;
+    cfg.rc_min_quantizer    = 8;
+    cfg.rc_max_quantizer    = 56;
+    cfg.rc_undershoot_pct   = 100;
+    cfg.rc_overshoot_pct    = 15;
+    cfg.rc_buf_initial_sz   = 500;
+    cfg.rc_buf_optimal_sz   = 600;
+    cfg.rc_buf_sz           = 1000;
+
+    // Enable error resilient mode
+    cfg.g_error_resilient = 1;
+    cfg.g_lag_in_frames   = 0;
+    cfg.kf_mode           = VPX_KF_DISABLED;
+
+    // Disable automatic keyframe placement
+    cfg.kf_min_dist = cfg.kf_max_dist = 1000;
+
+    // Temporal scaling parameters:
+    // NOTE: The 3 prediction frames cannot be used interchangeably due to
+    // differences in the way they are handled throughout the code. The
+    // frames should be allocated to layers in the order LAST, GF, ARF.
+    // Other combinations work, but may produce slightly inferior results.
+    switch (layering_mode)
+    {
+
+    case 0:
+    {
+        // 2-layers, 2-frame period
+        int ids[2] = {0,1};
+        cfg.ts_number_layers     = 2;
+        cfg.ts_periodicity       = 2;
+        cfg.ts_rate_decimator[0] = 2;
+        cfg.ts_rate_decimator[1] = 1;
+        memcpy(cfg.ts_layer_id, ids, sizeof(ids));
+
+        flag_periodicity = cfg.ts_periodicity;
+#if 1
+        // 0=L, 1=GF, Intra-layer prediction enabled
+        layer_flags[0] = VPX_EFLAG_FORCE_KF  |
+                         VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
+                         VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
+        layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
+                         VP8_EFLAG_NO_REF_ARF;
+#else
+        // 0=L, 1=GF, Intra-layer prediction disabled
+        layer_flags[0] = VPX_EFLAG_FORCE_KF  |
+                         VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
+                         VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
+        layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
+                         VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_LAST;
+#endif
+        break;
+    }
+
+    case 1:
+    {
+        // 2-layers, 3-frame period
+        int ids[3] = {0,1,1};
+        cfg.ts_number_layers     = 2;
+        cfg.ts_periodicity       = 3;
+        cfg.ts_rate_decimator[0] = 3;
+        cfg.ts_rate_decimator[1] = 1;
+        memcpy(cfg.ts_layer_id, ids, sizeof(ids));
+
+        flag_periodicity = cfg.ts_periodicity;
+
+        // 0=L, 1=GF, Intra-layer prediction enabled
+        layer_flags[0] = VPX_EFLAG_FORCE_KF  |
+                         VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
+                         VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+        layer_flags[1] =
+        layer_flags[2] = VP8_EFLAG_NO_REF_GF  |
+                         VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF |
+                                                VP8_EFLAG_NO_UPD_LAST;
+        break;
+    }
+
+    case 2:
+    {
+        // 3-layers, 6-frame period
+        int ids[6] = {0,2,2,1,2,2};
+        cfg.ts_number_layers     = 3;
+        cfg.ts_periodicity       = 6;
+        cfg.ts_rate_decimator[0] = 6;
+        cfg.ts_rate_decimator[1] = 3;
+        cfg.ts_rate_decimator[2] = 1;
+        memcpy(cfg.ts_layer_id, ids, sizeof(ids));
+
+        flag_periodicity = cfg.ts_periodicity;
+
+        // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled
+        layer_flags[0] = VPX_EFLAG_FORCE_KF  |
+                         VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
+                         VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+        layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF |
+                                                VP8_EFLAG_NO_UPD_LAST;
+        layer_flags[1] =
+        layer_flags[2] =
+        layer_flags[4] =
+        layer_flags[5] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
+        break;
+    }
+
+    case 3:
+    {
+        // 3-layers, 4-frame period
+        int ids[4] = {0,2,1,2};
+        cfg.ts_number_layers     = 3;
+        cfg.ts_periodicity       = 4;
+        cfg.ts_rate_decimator[0] = 4;
+        cfg.ts_rate_decimator[1] = 2;
+        cfg.ts_rate_decimator[2] = 1;
+        memcpy(cfg.ts_layer_id, ids, sizeof(ids));
+
+        flag_periodicity = cfg.ts_periodicity;
+
+        // 0=L, 1=GF, 2=ARF, Intra-layer prediction disabled
+        layer_flags[0] = VPX_EFLAG_FORCE_KF  |
+                         VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
+                         VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+        layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
+                         VP8_EFLAG_NO_UPD_ARF |
+                         VP8_EFLAG_NO_UPD_LAST;
+        layer_flags[1] =
+        layer_flags[3] = VP8_EFLAG_NO_REF_ARF |
+                         VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
+                         VP8_EFLAG_NO_UPD_ARF;
+        break;
+    }
+
+    case 4:
+    {
+        // 3-layers, 4-frame period
+        int ids[4] = {0,2,1,2};
+        cfg.ts_number_layers     = 3;
+        cfg.ts_periodicity       = 4;
+        cfg.ts_rate_decimator[0] = 4;
+        cfg.ts_rate_decimator[1] = 2;
+        cfg.ts_rate_decimator[2] = 1;
+        memcpy(cfg.ts_layer_id, ids, sizeof(ids));
+
+        flag_periodicity = cfg.ts_periodicity;
+
+        // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled in layer 1,
+        // disabled in layer 2
+        layer_flags[0] = VPX_EFLAG_FORCE_KF  |
+                         VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
+                         VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+        layer_flags[2] = VP8_EFLAG_NO_REF_ARF |
+                         VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
+        layer_flags[1] =
+        layer_flags[3] = VP8_EFLAG_NO_REF_ARF |
+                         VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
+                         VP8_EFLAG_NO_UPD_ARF;
+        break;
+    }
+
+    case 5:
+    {
+        // 3-layers, 4-frame period
+        int ids[4] = {0,2,1,2};
+        cfg.ts_number_layers     = 3;
+        cfg.ts_periodicity       = 4;
+        cfg.ts_rate_decimator[0] = 4;
+        cfg.ts_rate_decimator[1] = 2;
+        cfg.ts_rate_decimator[2] = 1;
+        memcpy(cfg.ts_layer_id, ids, sizeof(ids));
+
+        flag_periodicity = cfg.ts_periodicity;
+
+        // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled
+        layer_flags[0] = VPX_EFLAG_FORCE_KF  |
+                         VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
+                         VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+        layer_flags[2] = VP8_EFLAG_NO_REF_ARF |
+                         VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
+        layer_flags[1] =
+        layer_flags[3] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
+        break;
+    }
+
+    case 6:
+    {
+        // NOTE: Probably of academic interest only
+
+        // 5-layers, 16-frame period
+        int ids[16] = {0,4,3,4,2,4,3,4,1,4,3,4,2,4,3,4};
+        cfg.ts_number_layers     = 5;
+        cfg.ts_periodicity       = 16;
+        cfg.ts_rate_decimator[0] = 16;
+        cfg.ts_rate_decimator[1] = 8;
+        cfg.ts_rate_decimator[2] = 4;
+        cfg.ts_rate_decimator[3] = 2;
+        cfg.ts_rate_decimator[4] = 1;
+        memcpy(cfg.ts_layer_id, ids, sizeof(ids));
+
+        flag_periodicity = cfg.ts_periodicity;
+
+        layer_flags[0]  = VPX_EFLAG_FORCE_KF;
+        layer_flags[1]  =
+        layer_flags[3]  =
+        layer_flags[5]  =
+        layer_flags[7]  =
+        layer_flags[9]  =
+        layer_flags[11] =
+        layer_flags[13] =
+        layer_flags[15] = VP8_EFLAG_NO_UPD_LAST |
+                          VP8_EFLAG_NO_UPD_GF   |
+                          VP8_EFLAG_NO_UPD_ARF;
+        layer_flags[2]  =
+        layer_flags[6]  =
+        layer_flags[10] =
+        layer_flags[14] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_GF;
+        layer_flags[4]  =
+        layer_flags[12] = VP8_EFLAG_NO_REF_LAST |
+                          VP8_EFLAG_NO_UPD_ARF;
+        layer_flags[8]  = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF;
+        break;
+    }
+
+    case 7:
+    {
+        // 2-layers
+        int ids[2] = {0,1};
+        cfg.ts_number_layers     = 2;
+        cfg.ts_periodicity       = 2;
+        cfg.ts_rate_decimator[0] = 2;
+        cfg.ts_rate_decimator[1] = 1;
+        memcpy(cfg.ts_layer_id, ids, sizeof(ids));
+
+        flag_periodicity = 8;
+
+        // 0=L, 1=GF
+        layer_flags[0] = VPX_EFLAG_FORCE_KF  |
+                         VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
+                         VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+        layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
+                         VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
+        layer_flags[2] =
+        layer_flags[4] =
+        layer_flags[6] = VP8_EFLAG_NO_REF_GF  | VP8_EFLAG_NO_REF_ARF |
+                         VP8_EFLAG_NO_UPD_GF  | VP8_EFLAG_NO_UPD_ARF;
+        layer_flags[3] =
+        layer_flags[5] = VP8_EFLAG_NO_REF_ARF |
+                         VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
+        layer_flags[7] = VP8_EFLAG_NO_REF_ARF |
+                         VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
+                         VP8_EFLAG_NO_UPD_ARF |
+                         VP8_EFLAG_NO_UPD_ENTROPY;
+        break;
+    }
+
+    case 8:
+    default:
+    {
+        // 3-layers
+        int ids[4] = {0,2,1,2};
+        cfg.ts_number_layers     = 3;
+        cfg.ts_periodicity       = 4;
+        cfg.ts_rate_decimator[0] = 4;
+        cfg.ts_rate_decimator[1] = 2;
+        cfg.ts_rate_decimator[2] = 1;
+        memcpy(cfg.ts_layer_id, ids, sizeof(ids));
+
+        flag_periodicity = 8;
+
+        // 0=L, 1=GF, 2=ARF
+        layer_flags[0] = VPX_EFLAG_FORCE_KF  |
+                         VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
+                         VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+        layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
+                         VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
+        layer_flags[2] = VP8_EFLAG_NO_REF_GF   | VP8_EFLAG_NO_REF_ARF |
+                         VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
+        layer_flags[3] =
+        layer_flags[5] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
+        layer_flags[4] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
+                         VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+        layer_flags[6] = VP8_EFLAG_NO_REF_ARF |
+                         VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
+        layer_flags[7] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
+                         VP8_EFLAG_NO_UPD_ARF |
+                         VP8_EFLAG_NO_UPD_ENTROPY;
+        break;
+    }
+    }
+
+    // Open input file
+    if(!(infile = fopen(argv[1], "rb")))
+        die("Failed to open %s for reading", argv[1]);
+
+    // Open an output file for each stream
+    for (i=0; i<cfg.ts_number_layers; i++)
+    {
+        char file_name[512];
+        sprintf (file_name, "%s_%d.ivf", argv[2], i);
+        if (!(outfile[i] = fopen(file_name, "wb")))
+            die("Failed to open %s for writing", file_name);
+        write_ivf_file_header(outfile[i], &cfg, 0);
+    }
+
+    // Initialize codec
+    if (vpx_codec_enc_init (&codec, interface, &cfg, 0))
+        die_codec (&codec, "Failed to initialize encoder");
+
+    // Cap CPU & first I-frame size
+    vpx_codec_control (&codec, VP8E_SET_CPUUSED,                -6);
+    vpx_codec_control (&codec, VP8E_SET_STATIC_THRESHOLD,      800);
+    vpx_codec_control (&codec, VP8E_SET_NOISE_SENSITIVITY,       2);
+
+    max_intra_size_pct = (int) (((double)cfg.rc_buf_optimal_sz * 0.5)
+                         * ((double) cfg.g_timebase.den / cfg.g_timebase.num)
+                         / 10.0);
+    //printf ("max_intra_size_pct=%d\n", max_intra_size_pct);
+
+    vpx_codec_control(&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT,
+                      max_intra_size_pct);
+    //    vpx_codec_control (&codec, VP8E_SET_TOKEN_PARTITIONS,
+    //                      static_cast<vp8e_token_partitions>(_tokenPartitions));
+
+    frame_avail = 1;
+    while (frame_avail || got_data) {
+        vpx_codec_iter_t iter = NULL;
+        const vpx_codec_cx_pkt_t *pkt;
+
+        flags = layer_flags[frame_cnt % flag_periodicity];
+
+        frame_avail = read_frame(infile, &raw);
+        if (vpx_codec_encode(&codec, frame_avail? &raw : NULL, pts,
+                            1, flags, VPX_DL_REALTIME))
+            die_codec(&codec, "Failed to encode frame");
+
+        // Reset KF flag
+        if (layering_mode != 6)
+            layer_flags[0] &= ~VPX_EFLAG_FORCE_KF;
+
+        got_data = 0;
+        while ( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
+            got_data = 1;
+            switch (pkt->kind) {
+            case VPX_CODEC_CX_FRAME_PKT:
+                for (i=cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity];
+                                              i<cfg.ts_number_layers; i++)
+                {
+                    write_ivf_frame_header(outfile[i], pkt);
+                    if (fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
+                              outfile[i]));
+                    frames_in_layer[i]++;
+                }
+                break;
+            default:
+                break;
+            }
+            printf (pkt->kind == VPX_CODEC_CX_FRAME_PKT
+                    && (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":".");
+            fflush (stdout);
+        }
+        frame_cnt++;
+        pts += frame_duration;
+    }
+    printf ("\n");
+    fclose (infile);
+
+    printf ("Processed %d frames.\n",frame_cnt-1);
+    if (vpx_codec_destroy(&codec))
+            die_codec (&codec, "Failed to destroy codec");
+
+    // Try to rewrite the output file headers with the actual frame count
+    for (i=0; i<cfg.ts_number_layers; i++)
+    {
+        if (!fseek(outfile[i], 0, SEEK_SET))
+            write_ivf_file_header (outfile[i], &cfg, frames_in_layer[i]);
+        fclose (outfile[i]);
+    }
+
+    return EXIT_SUCCESS;
+}
+
diff --git a/vpx/exports_com b/vpx/exports_com
new file mode 100644 (file)
index 0000000..2ab0509
--- /dev/null
@@ -0,0 +1,16 @@
+text vpx_codec_build_config
+text vpx_codec_control_
+text vpx_codec_destroy
+text vpx_codec_err_to_string
+text vpx_codec_error
+text vpx_codec_error_detail
+text vpx_codec_get_caps
+text vpx_codec_iface_name
+text vpx_codec_version
+text vpx_codec_version_extra_str
+text vpx_codec_version_str
+text vpx_img_alloc
+text vpx_img_flip
+text vpx_img_free
+text vpx_img_set_rect
+text vpx_img_wrap
diff --git a/vpx/exports_dec b/vpx/exports_dec
new file mode 100644 (file)
index 0000000..ed121f7
--- /dev/null
@@ -0,0 +1,9 @@
+text vpx_codec_dec_init_ver
+text vpx_codec_decode
+text vpx_codec_get_frame
+text vpx_codec_get_mem_map
+text vpx_codec_get_stream_info
+text vpx_codec_peek_stream_info
+text vpx_codec_register_put_frame_cb
+text vpx_codec_register_put_slice_cb
+text vpx_codec_set_mem_map
diff --git a/vpx/exports_enc b/vpx/exports_enc
new file mode 100644 (file)
index 0000000..3d56749
--- /dev/null
@@ -0,0 +1,8 @@
+text vpx_codec_enc_config_default
+text vpx_codec_enc_config_set
+text vpx_codec_enc_init_ver
+text vpx_codec_encode
+text vpx_codec_get_cx_data
+text vpx_codec_get_global_headers
+text vpx_codec_get_preview_frame
+text vpx_codec_set_cx_data_buf
diff --git a/vpx/internal/vpx_codec_internal.h b/vpx/internal/vpx_codec_internal.h
new file mode 100644 (file)
index 0000000..0703d6a
--- /dev/null
@@ -0,0 +1,490 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*!\file
+ * \brief Describes the decoder algorithm interface for algorithm
+ *        implementations.
+ *
+ * This file defines the private structures and data types that are only
+ * relevant to implementing an algorithm, as opposed to using it.
+ *
+ * To create a decoder algorithm class, an interface structure is put
+ * into the global namespace:
+ *     <pre>
+ *     my_codec.c:
+ *       vpx_codec_iface_t my_codec = {
+ *           "My Codec v1.0",
+ *           VPX_CODEC_ALG_ABI_VERSION,
+ *           ...
+ *       };
+ *     </pre>
+ *
+ * An application instantiates a specific decoder instance by using
+ * vpx_codec_init() and a pointer to the algorithm's interface structure:
+ *     <pre>
+ *     my_app.c:
+ *       extern vpx_codec_iface_t my_codec;
+ *       {
+ *           vpx_codec_ctx_t algo;
+ *           res = vpx_codec_init(&algo, &my_codec);
+ *       }
+ *     </pre>
+ *
+ * Once initialized, the instance is manged using other functions from
+ * the vpx_codec_* family.
+ */
+#ifndef VPX_CODEC_INTERNAL_H
+#define VPX_CODEC_INTERNAL_H
+#include "../vpx_decoder.h"
+#include "../vpx_encoder.h"
+#include <stdarg.h>
+
+
+/*!\brief Current ABI version number
+ *
+ * \internal
+ * If this file is altered in any way that changes the ABI, this value
+ * must be bumped.  Examples include, but are not limited to, changing
+ * types, removing or reassigning enums, adding/removing/rearranging
+ * fields to structures
+ */
+#define VPX_CODEC_INTERNAL_ABI_VERSION (4) /**<\hideinitializer*/
+
+typedef struct vpx_codec_alg_priv  vpx_codec_alg_priv_t;
+typedef struct vpx_codec_priv_enc_mr_cfg vpx_codec_priv_enc_mr_cfg_t;
+
+/*!\brief init function pointer prototype
+ *
+ * Performs algorithm-specific initialization of the decoder context. This
+ * function is called by the generic vpx_codec_init() wrapper function, so
+ * plugins implementing this interface may trust the input parameters to be
+ * properly initialized.
+ *
+ * \param[in] ctx   Pointer to this instance's context
+ * \retval #VPX_CODEC_OK
+ *     The input stream was recognized and decoder initialized.
+ * \retval #VPX_CODEC_MEM_ERROR
+ *     Memory operation failed.
+ */
+typedef vpx_codec_err_t (*vpx_codec_init_fn_t)(vpx_codec_ctx_t *ctx,
+                                             vpx_codec_priv_enc_mr_cfg_t *data);
+
+/*!\brief destroy function pointer prototype
+ *
+ * Performs algorithm-specific destruction of the decoder context. This
+ * function is called by the generic vpx_codec_destroy() wrapper function,
+ * so plugins implementing this interface may trust the input parameters
+ * to be properly initialized.
+ *
+ * \param[in] ctx   Pointer to this instance's context
+ * \retval #VPX_CODEC_OK
+ *     The input stream was recognized and decoder initialized.
+ * \retval #VPX_CODEC_MEM_ERROR
+ *     Memory operation failed.
+ */
+typedef vpx_codec_err_t (*vpx_codec_destroy_fn_t)(vpx_codec_alg_priv_t *ctx);
+
+/*!\brief parse stream info function pointer prototype
+ *
+ * Performs high level parsing of the bitstream. This function is called by
+ * the generic vpx_codec_parse_stream() wrapper function, so plugins implementing
+ * this interface may trust the input parameters to be properly initialized.
+ *
+ * \param[in]      data    Pointer to a block of data to parse
+ * \param[in]      data_sz Size of the data buffer
+ * \param[in,out]  si      Pointer to stream info to update. The size member
+ *                         \ref MUST be properly initialized, but \ref MAY be
+ *                         clobbered by the algorithm. This parameter \ref MAY
+ *                         be NULL.
+ *
+ * \retval #VPX_CODEC_OK
+ *     Bitstream is parsable and stream information updated
+ */
+typedef vpx_codec_err_t (*vpx_codec_peek_si_fn_t)(const uint8_t         *data,
+        unsigned int           data_sz,
+        vpx_codec_stream_info_t *si);
+
+/*!\brief Return information about the current stream.
+ *
+ * Returns information about the stream that has been parsed during decoding.
+ *
+ * \param[in]      ctx     Pointer to this instance's context
+ * \param[in,out]  si      Pointer to stream info to update. The size member
+ *                         \ref MUST be properly initialized, but \ref MAY be
+ *                         clobbered by the algorithm. This parameter \ref MAY
+ *                         be NULL.
+ *
+ * \retval #VPX_CODEC_OK
+ *     Bitstream is parsable and stream information updated
+ */
+typedef vpx_codec_err_t (*vpx_codec_get_si_fn_t)(vpx_codec_alg_priv_t    *ctx,
+        vpx_codec_stream_info_t *si);
+
+/*!\brief control function pointer prototype
+ *
+ * This function is used to exchange algorithm specific data with the decoder
+ * instance. This can be used to implement features specific to a particular
+ * algorithm.
+ *
+ * This function is called by the generic vpx_codec_control() wrapper
+ * function, so plugins implementing this interface may trust the input
+ * parameters to be properly initialized. However,  this interface does not
+ * provide type safety for the exchanged data or assign meanings to the
+ * control codes. Those details should be specified in the algorithm's
+ * header file. In particular, the ctrl_id parameter is guaranteed to exist
+ * in the algorithm's control mapping table, and the data parameter may be NULL.
+ *
+ *
+ * \param[in]     ctx              Pointer to this instance's context
+ * \param[in]     ctrl_id          Algorithm specific control identifier
+ * \param[in,out] data             Data to exchange with algorithm instance.
+ *
+ * \retval #VPX_CODEC_OK
+ *     The internal state data was deserialized.
+ */
+typedef vpx_codec_err_t (*vpx_codec_control_fn_t)(vpx_codec_alg_priv_t  *ctx,
+        int                  ctrl_id,
+        va_list              ap);
+
+/*!\brief control function pointer mapping
+ *
+ * This structure stores the mapping between control identifiers and
+ * implementing functions. Each algorithm provides a list of these
+ * mappings. This list is searched by the vpx_codec_control() wrapper
+ * function to determine which function to invoke. The special
+ * value {0, NULL} is used to indicate end-of-list, and must be
+ * present. The special value {0, <non-null>} can be used as a catch-all
+ * mapping. This implies that ctrl_id values chosen by the algorithm
+ * \ref MUST be non-zero.
+ */
+typedef const struct
+{
+    int                    ctrl_id;
+    vpx_codec_control_fn_t   fn;
+} vpx_codec_ctrl_fn_map_t;
+
+/*!\brief decode data function pointer prototype
+ *
+ * Processes a buffer of coded data. If the processing results in a new
+ * decoded frame becoming available, #VPX_CODEC_CB_PUT_SLICE and
+ * #VPX_CODEC_CB_PUT_FRAME events are generated as appropriate. This
+ * function is called by the generic vpx_codec_decode() wrapper function,
+ * so plugins implementing this interface may trust the input parameters
+ * to be properly initialized.
+ *
+ * \param[in] ctx          Pointer to this instance's context
+ * \param[in] data         Pointer to this block of new coded data. If
+ *                         NULL, a #VPX_CODEC_CB_PUT_FRAME event is posted
+ *                         for the previously decoded frame.
+ * \param[in] data_sz      Size of the coded data, in bytes.
+ *
+ * \return Returns #VPX_CODEC_OK if the coded data was processed completely
+ *         and future pictures can be decoded without error. Otherwise,
+ *         see the descriptions of the other error codes in ::vpx_codec_err_t
+ *         for recoverability capabilities.
+ */
+typedef vpx_codec_err_t (*vpx_codec_decode_fn_t)(vpx_codec_alg_priv_t  *ctx,
+        const uint8_t         *data,
+        unsigned int     data_sz,
+        void        *user_priv,
+        long         deadline);
+
+/*!\brief Decoded frames iterator
+ *
+ * Iterates over a list of the frames available for display. The iterator
+ * storage should be initialized to NULL to start the iteration. Iteration is
+ * complete when this function returns NULL.
+ *
+ * The list of available frames becomes valid upon completion of the
+ * vpx_codec_decode call, and remains valid until the next call to vpx_codec_decode.
+ *
+ * \param[in]     ctx      Pointer to this instance's context
+ * \param[in out] iter     Iterator storage, initialized to NULL
+ *
+ * \return Returns a pointer to an image, if one is ready for display. Frames
+ *         produced will always be in PTS (presentation time stamp) order.
+ */
+typedef vpx_image_t*(*vpx_codec_get_frame_fn_t)(vpx_codec_alg_priv_t *ctx,
+        vpx_codec_iter_t     *iter);
+
+
+/*\brief eXternal Memory Allocation memory map get iterator
+ *
+ * Iterates over a list of the memory maps requested by the decoder. The
+ * iterator storage should be initialized to NULL to start the iteration.
+ * Iteration is complete when this function returns NULL.
+ *
+ * \param[in out] iter     Iterator storage, initialized to NULL
+ *
+ * \return Returns a pointer to an memory segment descriptor, or NULL to
+ *         indicate end-of-list.
+ */
+typedef vpx_codec_err_t (*vpx_codec_get_mmap_fn_t)(const vpx_codec_ctx_t      *ctx,
+        vpx_codec_mmap_t           *mmap,
+        vpx_codec_iter_t           *iter);
+
+
+/*\brief eXternal Memory Allocation memory map set iterator
+ *
+ * Sets a memory descriptor inside the decoder instance.
+ *
+ * \param[in] ctx      Pointer to this instance's context
+ * \param[in] mmap     Memory map to store.
+ *
+ * \retval #VPX_CODEC_OK
+ *     The memory map was accepted and stored.
+ * \retval #VPX_CODEC_MEM_ERROR
+ *     The memory map was rejected.
+ */
+typedef vpx_codec_err_t (*vpx_codec_set_mmap_fn_t)(vpx_codec_ctx_t         *ctx,
+        const vpx_codec_mmap_t  *mmap);
+
+
+typedef vpx_codec_err_t (*vpx_codec_encode_fn_t)(vpx_codec_alg_priv_t  *ctx,
+        const vpx_image_t     *img,
+        vpx_codec_pts_t        pts,
+        unsigned long          duration,
+        vpx_enc_frame_flags_t  flags,
+        unsigned long          deadline);
+typedef const vpx_codec_cx_pkt_t*(*vpx_codec_get_cx_data_fn_t)(vpx_codec_alg_priv_t *ctx,
+        vpx_codec_iter_t     *iter);
+
+typedef vpx_codec_err_t
+(*vpx_codec_enc_config_set_fn_t)(vpx_codec_alg_priv_t       *ctx,
+                                 const vpx_codec_enc_cfg_t  *cfg);
+typedef vpx_fixed_buf_t *
+(*vpx_codec_get_global_headers_fn_t)(vpx_codec_alg_priv_t   *ctx);
+
+typedef vpx_image_t *
+(*vpx_codec_get_preview_frame_fn_t)(vpx_codec_alg_priv_t   *ctx);
+
+typedef vpx_codec_err_t
+(*vpx_codec_enc_mr_get_mem_loc_fn_t)(const vpx_codec_enc_cfg_t     *cfg,
+                                   void **mem_loc);
+
+/*!\brief usage configuration mapping
+ *
+ * This structure stores the mapping between usage identifiers and
+ * configuration structures. Each algorithm provides a list of these
+ * mappings. This list is searched by the vpx_codec_enc_config_default()
+ * wrapper function to determine which config to return. The special value
+ * {-1, {0}} is used to indicate end-of-list, and must be present. At least
+ * one mapping must be present, in addition to the end-of-list.
+ *
+ */
+typedef const struct
+{
+    int                 usage;
+    vpx_codec_enc_cfg_t cfg;
+} vpx_codec_enc_cfg_map_t;
+
+#define NOT_IMPLEMENTED 0
+
+/*!\brief Decoder algorithm interface interface
+ *
+ * All decoders \ref MUST expose a variable of this type.
+ */
+struct vpx_codec_iface
+{
+    const char               *name;        /**< Identification String  */
+    int                       abi_version; /**< Implemented ABI version */
+    vpx_codec_caps_t          caps;    /**< Decoder capabilities */
+    vpx_codec_init_fn_t       init;    /**< \copydoc ::vpx_codec_init_fn_t */
+    vpx_codec_destroy_fn_t    destroy;     /**< \copydoc ::vpx_codec_destroy_fn_t */
+    vpx_codec_ctrl_fn_map_t  *ctrl_maps;   /**< \copydoc ::vpx_codec_ctrl_fn_map_t */
+    vpx_codec_get_mmap_fn_t   get_mmap;    /**< \copydoc ::vpx_codec_get_mmap_fn_t */
+    vpx_codec_set_mmap_fn_t   set_mmap;    /**< \copydoc ::vpx_codec_set_mmap_fn_t */
+    struct
+    {
+        vpx_codec_peek_si_fn_t    peek_si;     /**< \copydoc ::vpx_codec_peek_si_fn_t */
+        vpx_codec_get_si_fn_t     get_si;      /**< \copydoc ::vpx_codec_peek_si_fn_t */
+        vpx_codec_decode_fn_t     decode;      /**< \copydoc ::vpx_codec_decode_fn_t */
+        vpx_codec_get_frame_fn_t  get_frame;   /**< \copydoc ::vpx_codec_get_frame_fn_t */
+    } dec;
+    struct
+    {
+        vpx_codec_enc_cfg_map_t           *cfg_maps;      /**< \copydoc ::vpx_codec_enc_cfg_map_t */
+        vpx_codec_encode_fn_t              encode;        /**< \copydoc ::vpx_codec_encode_fn_t */
+        vpx_codec_get_cx_data_fn_t         get_cx_data;   /**< \copydoc ::vpx_codec_get_cx_data_fn_t */
+        vpx_codec_enc_config_set_fn_t      cfg_set;       /**< \copydoc ::vpx_codec_enc_config_set_fn_t */
+        vpx_codec_get_global_headers_fn_t  get_glob_hdrs; /**< \copydoc ::vpx_codec_get_global_headers_fn_t */
+        vpx_codec_get_preview_frame_fn_t   get_preview;   /**< \copydoc ::vpx_codec_get_preview_frame_fn_t */
+        vpx_codec_enc_mr_get_mem_loc_fn_t  mr_get_mem_loc;   /**< \copydoc ::vpx_codec_enc_mr_get_mem_loc_fn_t */
+    } enc;
+};
+
+/*!\brief Callback function pointer / user data pair storage */
+typedef struct vpx_codec_priv_cb_pair
+{
+    union
+    {
+        vpx_codec_put_frame_cb_fn_t    put_frame;
+        vpx_codec_put_slice_cb_fn_t    put_slice;
+    } u;
+    void                            *user_priv;
+} vpx_codec_priv_cb_pair_t;
+
+
+/*!\brief Instance private storage
+ *
+ * This structure is allocated by the algorithm's init function. It can be
+ * extended in one of two ways. First, a second, algorithm specific structure
+ * can be allocated and the priv member pointed to it. Alternatively, this
+ * structure can be made the first member of the algorithm specific structure,
+ * and the pointer cast to the proper type.
+ */
+struct vpx_codec_priv
+{
+    unsigned int                    sz;
+    vpx_codec_iface_t              *iface;
+    struct vpx_codec_alg_priv      *alg_priv;
+    const char                     *err_detail;
+    vpx_codec_flags_t               init_flags;
+    struct
+    {
+        vpx_codec_priv_cb_pair_t    put_frame_cb;
+        vpx_codec_priv_cb_pair_t    put_slice_cb;
+    } dec;
+    struct
+    {
+        int                         tbd;
+        struct vpx_fixed_buf        cx_data_dst_buf;
+        unsigned int                cx_data_pad_before;
+        unsigned int                cx_data_pad_after;
+        vpx_codec_cx_pkt_t          cx_data_pkt;
+        unsigned int                total_encoders;
+    } enc;
+};
+
+/*
+ * Multi-resolution encoding internal configuration
+ */
+struct vpx_codec_priv_enc_mr_cfg
+{
+    unsigned int           mr_total_resolutions;
+    unsigned int           mr_encoder_id;
+    struct vpx_rational    mr_down_sampling_factor;
+    void*                  mr_low_res_mode_info;
+};
+
+#undef VPX_CTRL_USE_TYPE
+#define VPX_CTRL_USE_TYPE(id, typ) \
+    static typ id##__value(va_list args) {return va_arg(args, typ);} \
+    static typ id##__convert(void *x)\
+    {\
+        union\
+        {\
+            void *x;\
+            typ   d;\
+        } u;\
+        u.x = x;\
+        return u.d;\
+    }
+
+
+#undef VPX_CTRL_USE_TYPE_DEPRECATED
+#define VPX_CTRL_USE_TYPE_DEPRECATED(id, typ) \
+    static typ id##__value(va_list args) {return va_arg(args, typ);} \
+    static typ id##__convert(void *x)\
+    {\
+        union\
+        {\
+            void *x;\
+            typ   d;\
+        } u;\
+        u.x = x;\
+        return u.d;\
+    }
+
+#define CAST(id, arg) id##__value(arg)
+#define RECAST(id, x) id##__convert(x)
+
+
+/* CODEC_INTERFACE convenience macro
+ *
+ * By convention, each codec interface is a struct with extern linkage, where
+ * the symbol is suffixed with _algo. A getter function is also defined to
+ * return a pointer to the struct, since in some cases it's easier to work
+ * with text symbols than data symbols (see issue #169). This function has
+ * the same name as the struct, less the _algo suffix. The CODEC_INTERFACE
+ * macro is provided to define this getter function automatically.
+ */
+#define CODEC_INTERFACE(id)\
+vpx_codec_iface_t* id(void) { return &id##_algo; }\
+vpx_codec_iface_t  id##_algo
+
+
+/* Internal Utility Functions
+ *
+ * The following functions are intended to be used inside algorithms as
+ * utilities for manipulating vpx_codec_* data structures.
+ */
+struct vpx_codec_pkt_list
+{
+    unsigned int            cnt;
+    unsigned int            max;
+    struct vpx_codec_cx_pkt pkts[1];
+};
+
+#define vpx_codec_pkt_list_decl(n)\
+    union {struct vpx_codec_pkt_list head;\
+        struct {struct vpx_codec_pkt_list head;\
+            struct vpx_codec_cx_pkt    pkts[n];} alloc;}
+
+#define vpx_codec_pkt_list_init(m)\
+    (m)->alloc.head.cnt = 0,\
+                          (m)->alloc.head.max = sizeof((m)->alloc.pkts) / sizeof((m)->alloc.pkts[0])
+
+int
+vpx_codec_pkt_list_add(struct vpx_codec_pkt_list *,
+                       const struct vpx_codec_cx_pkt *);
+
+const vpx_codec_cx_pkt_t*
+vpx_codec_pkt_list_get(struct vpx_codec_pkt_list *list,
+                       vpx_codec_iter_t           *iter);
+
+
+#include <stdio.h>
+#include <setjmp.h>
+struct vpx_internal_error_info
+{
+    vpx_codec_err_t  error_code;
+    int              has_detail;
+    char             detail[80];
+    int              setjmp;
+    jmp_buf          jmp;
+};
+
+static void vpx_internal_error(struct vpx_internal_error_info *info,
+                               vpx_codec_err_t                 error,
+                               const char                     *fmt,
+                               ...)
+{
+    va_list ap;
+
+    info->error_code = error;
+    info->has_detail = 0;
+
+    if (fmt)
+    {
+        size_t  sz = sizeof(info->detail);
+
+        info->has_detail = 1;
+        va_start(ap, fmt);
+        vsnprintf(info->detail, sz - 1, fmt, ap);
+        va_end(ap);
+        info->detail[sz-1] = '\0';
+    }
+
+    if (info->setjmp)
+        longjmp(info->jmp, info->error_code);
+}
+#endif
diff --git a/vpx/src/vpx_codec.c b/vpx/src/vpx_codec.c
new file mode 100644 (file)
index 0000000..f1a8b67
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*!\file
+ * \brief Provides the high level interface to wrap decoder algorithms.
+ *
+ */
+#include <stdarg.h>
+#include "vpx/vpx_integer.h"
+#include "vpx/internal/vpx_codec_internal.h"
+#include "vpx_version.h"
+
+#define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var)
+
+int vpx_codec_version(void)
+{
+    return VERSION_PACKED;
+}
+
+
+const char *vpx_codec_version_str(void)
+{
+    return VERSION_STRING_NOSP;
+}
+
+
+const char *vpx_codec_version_extra_str(void)
+{
+    return VERSION_EXTRA;
+}
+
+
+const char *vpx_codec_iface_name(vpx_codec_iface_t *iface)
+{
+    return iface ? iface->name : "<invalid interface>";
+}
+
+const char *vpx_codec_err_to_string(vpx_codec_err_t  err)
+{
+    switch (err)
+    {
+    case VPX_CODEC_OK:
+        return "Success";
+    case VPX_CODEC_ERROR:
+        return "Unspecified internal error";
+    case VPX_CODEC_MEM_ERROR:
+        return "Memory allocation error";
+    case VPX_CODEC_ABI_MISMATCH:
+        return "ABI version mismatch";
+    case VPX_CODEC_INCAPABLE:
+        return "Codec does not implement requested capability";
+    case VPX_CODEC_UNSUP_BITSTREAM:
+        return "Bitstream not supported by this decoder";
+    case VPX_CODEC_UNSUP_FEATURE:
+        return "Bitstream required feature not supported by this decoder";
+    case VPX_CODEC_CORRUPT_FRAME:
+        return "Corrupt frame detected";
+    case  VPX_CODEC_INVALID_PARAM:
+        return "Invalid parameter";
+    case VPX_CODEC_LIST_END:
+        return "End of iterated list";
+    }
+
+    return "Unrecognized error code";
+}
+
+const char *vpx_codec_error(vpx_codec_ctx_t  *ctx)
+{
+    return (ctx) ? vpx_codec_err_to_string(ctx->err)
+           : vpx_codec_err_to_string(VPX_CODEC_INVALID_PARAM);
+}
+
+const char *vpx_codec_error_detail(vpx_codec_ctx_t  *ctx)
+{
+    if (ctx && ctx->err)
+        return ctx->priv ? ctx->priv->err_detail : ctx->err_detail;
+
+    return NULL;
+}
+
+
+vpx_codec_err_t vpx_codec_destroy(vpx_codec_ctx_t *ctx)
+{
+    vpx_codec_err_t res;
+
+    if (!ctx)
+        res = VPX_CODEC_INVALID_PARAM;
+    else if (!ctx->iface || !ctx->priv)
+        res = VPX_CODEC_ERROR;
+    else
+    {
+        if (ctx->priv->alg_priv)
+            ctx->iface->destroy(ctx->priv->alg_priv);
+
+        ctx->iface = NULL;
+        ctx->name = NULL;
+        ctx->priv = NULL;
+        res = VPX_CODEC_OK;
+    }
+
+    return SAVE_STATUS(ctx, res);
+}
+
+
+vpx_codec_caps_t vpx_codec_get_caps(vpx_codec_iface_t *iface)
+{
+    return (iface) ? iface->caps : 0;
+}
+
+
+vpx_codec_err_t vpx_codec_control_(vpx_codec_ctx_t  *ctx,
+                                   int               ctrl_id,
+                                   ...)
+{
+    vpx_codec_err_t res;
+
+    if (!ctx || !ctrl_id)
+        res = VPX_CODEC_INVALID_PARAM;
+    else if (!ctx->iface || !ctx->priv || !ctx->iface->ctrl_maps)
+        res = VPX_CODEC_ERROR;
+    else
+    {
+        vpx_codec_ctrl_fn_map_t *entry;
+
+        res = VPX_CODEC_ERROR;
+
+        for (entry = ctx->iface->ctrl_maps; entry && entry->fn; entry++)
+        {
+            if (!entry->ctrl_id || entry->ctrl_id == ctrl_id)
+            {
+                va_list  ap;
+
+                va_start(ap, ctrl_id);
+                res = entry->fn(ctx->priv->alg_priv, ctrl_id, ap);
+                va_end(ap);
+                break;
+            }
+        }
+    }
+
+    return SAVE_STATUS(ctx, res);
+}
diff --git a/vpx/src/vpx_decoder.c b/vpx/src/vpx_decoder.c
new file mode 100644 (file)
index 0000000..59a783d
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*!\file
+ * \brief Provides the high level interface to wrap decoder algorithms.
+ *
+ */
+#include <string.h>
+#include "vpx/internal/vpx_codec_internal.h"
+
+#define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var)
+
+vpx_codec_err_t vpx_codec_dec_init_ver(vpx_codec_ctx_t      *ctx,
+                                       vpx_codec_iface_t    *iface,
+                                       vpx_codec_dec_cfg_t  *cfg,
+                                       vpx_codec_flags_t     flags,
+                                       int                   ver)
+{
+    vpx_codec_err_t res;
+
+    if (ver != VPX_DECODER_ABI_VERSION)
+        res = VPX_CODEC_ABI_MISMATCH;
+    else if (!ctx || !iface)
+        res = VPX_CODEC_INVALID_PARAM;
+    else if (iface->abi_version != VPX_CODEC_INTERNAL_ABI_VERSION)
+        res = VPX_CODEC_ABI_MISMATCH;
+    else if ((flags & VPX_CODEC_USE_XMA) && !(iface->caps & VPX_CODEC_CAP_XMA))
+        res = VPX_CODEC_INCAPABLE;
+    else if ((flags & VPX_CODEC_USE_POSTPROC) && !(iface->caps & VPX_CODEC_CAP_POSTPROC))
+        res = VPX_CODEC_INCAPABLE;
+    else if ((flags & VPX_CODEC_USE_ERROR_CONCEALMENT) &&
+            !(iface->caps & VPX_CODEC_CAP_ERROR_CONCEALMENT))
+        res = VPX_CODEC_INCAPABLE;
+    else if ((flags & VPX_CODEC_USE_INPUT_FRAGMENTS) &&
+            !(iface->caps & VPX_CODEC_CAP_INPUT_FRAGMENTS))
+        res = VPX_CODEC_INCAPABLE;
+    else if (!(iface->caps & VPX_CODEC_CAP_DECODER))
+        res = VPX_CODEC_INCAPABLE;
+    else
+    {
+        memset(ctx, 0, sizeof(*ctx));
+        ctx->iface = iface;
+        ctx->name = iface->name;
+        ctx->priv = NULL;
+        ctx->init_flags = flags;
+        ctx->config.dec = cfg;
+        res = VPX_CODEC_OK;
+
+        if (!(flags & VPX_CODEC_USE_XMA))
+        {
+            res = ctx->iface->init(ctx, NULL);
+
+            if (res)
+            {
+                ctx->err_detail = ctx->priv ? ctx->priv->err_detail : NULL;
+                vpx_codec_destroy(ctx);
+            }
+
+            if (ctx->priv)
+                ctx->priv->iface = ctx->iface;
+        }
+    }
+
+    return SAVE_STATUS(ctx, res);
+}
+
+
+vpx_codec_err_t vpx_codec_peek_stream_info(vpx_codec_iface_t       *iface,
+        const uint8_t         *data,
+        unsigned int           data_sz,
+        vpx_codec_stream_info_t *si)
+{
+    vpx_codec_err_t res;
+
+    if (!iface || !data || !data_sz || !si
+        || si->sz < sizeof(vpx_codec_stream_info_t))
+        res = VPX_CODEC_INVALID_PARAM;
+    else
+    {
+        /* Set default/unknown values */
+        si->w = 0;
+        si->h = 0;
+
+        res = iface->dec.peek_si(data, data_sz, si);
+    }
+
+    return res;
+}
+
+
+vpx_codec_err_t vpx_codec_get_stream_info(vpx_codec_ctx_t         *ctx,
+        vpx_codec_stream_info_t *si)
+{
+    vpx_codec_err_t res;
+
+    if (!ctx || !si || si->sz < sizeof(vpx_codec_stream_info_t))
+        res = VPX_CODEC_INVALID_PARAM;
+    else if (!ctx->iface || !ctx->priv)
+        res = VPX_CODEC_ERROR;
+    else
+    {
+        /* Set default/unknown values */
+        si->w = 0;
+        si->h = 0;
+
+        res = ctx->iface->dec.get_si(ctx->priv->alg_priv, si);
+    }
+
+    return SAVE_STATUS(ctx, res);
+}
+
+
+vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t    *ctx,
+                                 const uint8_t        *data,
+                                 unsigned int    data_sz,
+                                 void       *user_priv,
+                                 long        deadline)
+{
+    vpx_codec_err_t res;
+
+    /* Sanity checks */
+    /* NULL data ptr allowed if data_sz is 0 too */
+    if (!ctx || (!data && data_sz))
+        res = VPX_CODEC_INVALID_PARAM;
+    else if (!ctx->iface || !ctx->priv)
+        res = VPX_CODEC_ERROR;
+    else
+    {
+        res = ctx->iface->dec.decode(ctx->priv->alg_priv, data, data_sz,
+                                     user_priv, deadline);
+    }
+
+    return SAVE_STATUS(ctx, res);
+}
+
+vpx_image_t *vpx_codec_get_frame(vpx_codec_ctx_t  *ctx,
+                                 vpx_codec_iter_t *iter)
+{
+    vpx_image_t *img;
+
+    if (!ctx || !iter || !ctx->iface || !ctx->priv)
+        img = NULL;
+    else
+        img = ctx->iface->dec.get_frame(ctx->priv->alg_priv, iter);
+
+    return img;
+}
+
+
+vpx_codec_err_t vpx_codec_register_put_frame_cb(vpx_codec_ctx_t             *ctx,
+        vpx_codec_put_frame_cb_fn_t  cb,
+        void                      *user_priv)
+{
+    vpx_codec_err_t res;
+
+    if (!ctx || !cb)
+        res = VPX_CODEC_INVALID_PARAM;
+    else if (!ctx->iface || !ctx->priv
+             || !(ctx->iface->caps & VPX_CODEC_CAP_PUT_FRAME))
+        res = VPX_CODEC_ERROR;
+    else
+    {
+        ctx->priv->dec.put_frame_cb.u.put_frame = cb;
+        ctx->priv->dec.put_frame_cb.user_priv = user_priv;
+        res = VPX_CODEC_OK;
+    }
+
+    return SAVE_STATUS(ctx, res);
+}
+
+
+vpx_codec_err_t vpx_codec_register_put_slice_cb(vpx_codec_ctx_t             *ctx,
+        vpx_codec_put_slice_cb_fn_t  cb,
+        void                      *user_priv)
+{
+    vpx_codec_err_t res;
+
+    if (!ctx || !cb)
+        res = VPX_CODEC_INVALID_PARAM;
+    else if (!ctx->iface || !ctx->priv
+             || !(ctx->iface->caps & VPX_CODEC_CAP_PUT_FRAME))
+        res = VPX_CODEC_ERROR;
+    else
+    {
+        ctx->priv->dec.put_slice_cb.u.put_slice = cb;
+        ctx->priv->dec.put_slice_cb.user_priv = user_priv;
+        res = VPX_CODEC_OK;
+    }
+
+    return SAVE_STATUS(ctx, res);
+}
+
+
+vpx_codec_err_t vpx_codec_get_mem_map(vpx_codec_ctx_t                *ctx,
+                                      vpx_codec_mmap_t               *mmap,
+                                      vpx_codec_iter_t               *iter)
+{
+    vpx_codec_err_t res = VPX_CODEC_OK;
+
+    if (!ctx || !mmap || !iter || !ctx->iface)
+        res = VPX_CODEC_INVALID_PARAM;
+    else if (!(ctx->iface->caps & VPX_CODEC_CAP_XMA))
+        res = VPX_CODEC_ERROR;
+    else
+        res = ctx->iface->get_mmap(ctx, mmap, iter);
+
+    return SAVE_STATUS(ctx, res);
+}
+
+
+vpx_codec_err_t vpx_codec_set_mem_map(vpx_codec_ctx_t   *ctx,
+                                      vpx_codec_mmap_t  *mmap,
+                                      unsigned int     num_maps)
+{
+    vpx_codec_err_t res = VPX_CODEC_MEM_ERROR;
+
+    if (!ctx || !mmap || !ctx->iface)
+        res = VPX_CODEC_INVALID_PARAM;
+    else if (!(ctx->iface->caps & VPX_CODEC_CAP_XMA))
+        res = VPX_CODEC_ERROR;
+    else
+    {
+        unsigned int i;
+
+        for (i = 0; i < num_maps; i++, mmap++)
+        {
+            if (!mmap->base)
+                break;
+
+            /* Everything look ok, set the mmap in the decoder */
+            res = ctx->iface->set_mmap(ctx, mmap);
+
+            if (res)
+                break;
+        }
+    }
+
+    return SAVE_STATUS(ctx, res);
+}
diff --git a/vpx/src/vpx_encoder.c b/vpx/src/vpx_encoder.c
new file mode 100644 (file)
index 0000000..03ddc62
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*!\file
+ * \brief Provides the high level interface to wrap encoder algorithms.
+ *
+ */
+#include <limits.h>
+#include <string.h>
+#include "vpx/internal/vpx_codec_internal.h"
+#include "vpx_config.h"
+
+#define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var)
+
+vpx_codec_err_t vpx_codec_enc_init_ver(vpx_codec_ctx_t      *ctx,
+                                       vpx_codec_iface_t    *iface,
+                                       vpx_codec_enc_cfg_t  *cfg,
+                                       vpx_codec_flags_t     flags,
+                                       int                   ver)
+{
+    vpx_codec_err_t res;
+
+    if (ver != VPX_ENCODER_ABI_VERSION)
+        res = VPX_CODEC_ABI_MISMATCH;
+    else if (!ctx || !iface || !cfg)
+        res = VPX_CODEC_INVALID_PARAM;
+    else if (iface->abi_version != VPX_CODEC_INTERNAL_ABI_VERSION)
+        res = VPX_CODEC_ABI_MISMATCH;
+    else if (!(iface->caps & VPX_CODEC_CAP_ENCODER))
+        res = VPX_CODEC_INCAPABLE;
+    else if ((flags & VPX_CODEC_USE_XMA) && !(iface->caps & VPX_CODEC_CAP_XMA))
+        res = VPX_CODEC_INCAPABLE;
+    else if ((flags & VPX_CODEC_USE_PSNR)
+             && !(iface->caps & VPX_CODEC_CAP_PSNR))
+        res = VPX_CODEC_INCAPABLE;
+    else if ((flags & VPX_CODEC_USE_OUTPUT_PARTITION)
+             && !(iface->caps & VPX_CODEC_CAP_OUTPUT_PARTITION))
+        res = VPX_CODEC_INCAPABLE;
+    else
+    {
+        ctx->iface = iface;
+        ctx->name = iface->name;
+        ctx->priv = NULL;
+        ctx->init_flags = flags;
+        ctx->config.enc = cfg;
+        res = ctx->iface->init(ctx, NULL);
+
+        if (res)
+        {
+            ctx->err_detail = ctx->priv ? ctx->priv->err_detail : NULL;
+            vpx_codec_destroy(ctx);
+        }
+
+        if (ctx->priv)
+            ctx->priv->iface = ctx->iface;
+    }
+
+    return SAVE_STATUS(ctx, res);
+}
+
+vpx_codec_err_t vpx_codec_enc_init_multi_ver(vpx_codec_ctx_t      *ctx,
+                                             vpx_codec_iface_t    *iface,
+                                             vpx_codec_enc_cfg_t  *cfg,
+                                             int                   num_enc,
+                                             vpx_codec_flags_t     flags,
+                                             vpx_rational_t       *dsf,
+                                             int                   ver)
+{
+    vpx_codec_err_t res = 0;
+
+    if (ver != VPX_ENCODER_ABI_VERSION)
+        res = VPX_CODEC_ABI_MISMATCH;
+    else if (!ctx || !iface || !cfg || (num_enc > 16 || num_enc < 1))
+        res = VPX_CODEC_INVALID_PARAM;
+    else if (iface->abi_version != VPX_CODEC_INTERNAL_ABI_VERSION)
+        res = VPX_CODEC_ABI_MISMATCH;
+    else if (!(iface->caps & VPX_CODEC_CAP_ENCODER))
+        res = VPX_CODEC_INCAPABLE;
+    else if ((flags & VPX_CODEC_USE_XMA) && !(iface->caps & VPX_CODEC_CAP_XMA))
+        res = VPX_CODEC_INCAPABLE;
+    else if ((flags & VPX_CODEC_USE_PSNR)
+             && !(iface->caps & VPX_CODEC_CAP_PSNR))
+        res = VPX_CODEC_INCAPABLE;
+    else if ((flags & VPX_CODEC_USE_OUTPUT_PARTITION)
+             && !(iface->caps & VPX_CODEC_CAP_OUTPUT_PARTITION))
+        res = VPX_CODEC_INCAPABLE;
+    else
+    {
+        int i;
+        void *mem_loc = NULL;
+
+        if(!(res = iface->enc.mr_get_mem_loc(cfg, &mem_loc)))
+        {
+            for (i = 0; i < num_enc; i++)
+            {
+                vpx_codec_priv_enc_mr_cfg_t mr_cfg;
+
+                /* Validate down-sampling factor. */
+                if(dsf->num < 1 || dsf->num > 4096 || dsf->den < 1 ||
+                   dsf->den > dsf->num)
+                {
+                    res = VPX_CODEC_INVALID_PARAM;
+                    break;
+                }
+
+                mr_cfg.mr_low_res_mode_info = mem_loc;
+                mr_cfg.mr_total_resolutions = num_enc;
+                mr_cfg.mr_encoder_id = num_enc-1-i;
+                mr_cfg.mr_down_sampling_factor.num = dsf->num;
+                mr_cfg.mr_down_sampling_factor.den = dsf->den;
+
+                ctx->iface = iface;
+                ctx->name = iface->name;
+                ctx->priv = NULL;
+                ctx->init_flags = flags;
+                ctx->config.enc = cfg;
+                res = ctx->iface->init(ctx, &mr_cfg);
+
+                if (res)
+                {
+                    ctx->err_detail = ctx->priv ? ctx->priv->err_detail : NULL;
+                    vpx_codec_destroy(ctx);
+                }
+
+                if (ctx->priv)
+                    ctx->priv->iface = ctx->iface;
+
+                if (res)
+                    break;
+
+                ctx++;
+                cfg++;
+                dsf++;
+            }
+        }
+    }
+
+    return SAVE_STATUS(ctx, res);
+}
+
+
+vpx_codec_err_t  vpx_codec_enc_config_default(vpx_codec_iface_t    *iface,
+        vpx_codec_enc_cfg_t  *cfg,
+        unsigned int          usage)
+{
+    vpx_codec_err_t res;
+    vpx_codec_enc_cfg_map_t *map;
+
+    if (!iface || !cfg || usage > INT_MAX)
+        res = VPX_CODEC_INVALID_PARAM;
+    else if (!(iface->caps & VPX_CODEC_CAP_ENCODER))
+        res = VPX_CODEC_INCAPABLE;
+    else
+    {
+        res = VPX_CODEC_INVALID_PARAM;
+
+        for (map = iface->enc.cfg_maps; map->usage >= 0; map++)
+        {
+            if (map->usage == (int)usage)
+            {
+                *cfg = map->cfg;
+                cfg->g_usage = usage;
+                res = VPX_CODEC_OK;
+                break;
+            }
+        }
+    }
+
+    return res;
+}
+
+
+#if ARCH_X86 || ARCH_X86_64
+/* On X86, disable the x87 unit's internal 80 bit precision for better
+ * consistency with the SSE unit's 64 bit precision.
+ */
+#include "vpx_ports/x86.h"
+#define FLOATING_POINT_INIT() do {\
+        unsigned short x87_orig_mode = x87_set_double_precision();
+#define FLOATING_POINT_RESTORE() \
+    x87_set_control_word(x87_orig_mode); }while(0)
+
+
+#else
+static void FLOATING_POINT_INIT() {}
+static void FLOATING_POINT_RESTORE() {}
+#endif
+
+
+vpx_codec_err_t  vpx_codec_encode(vpx_codec_ctx_t            *ctx,
+                                  const vpx_image_t          *img,
+                                  vpx_codec_pts_t             pts,
+                                  unsigned long               duration,
+                                  vpx_enc_frame_flags_t       flags,
+                                  unsigned long               deadline)
+{
+    vpx_codec_err_t res = 0;
+
+    if (!ctx || (img && !duration))
+        res = VPX_CODEC_INVALID_PARAM;
+    else if (!ctx->iface || !ctx->priv)
+        res = VPX_CODEC_ERROR;
+    else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
+        res = VPX_CODEC_INCAPABLE;
+    else
+    {
+        /* Execute in a normalized floating point environment, if the platform
+         * requires it.
+         */
+        unsigned int num_enc =ctx->priv->enc.total_encoders;
+
+        FLOATING_POINT_INIT();
+
+        if (num_enc == 1)
+            res = ctx->iface->enc.encode(ctx->priv->alg_priv, img, pts,
+                                         duration, flags, deadline);
+        else
+        {
+            /* Multi-resolution encoding:
+             * Encode multi-levels in reverse order. For example,
+             * if mr_total_resolutions = 3, first encode level 2,
+             * then encode level 1, and finally encode level 0.
+             */
+            int i;
+
+            ctx += num_enc - 1;
+            if (img) img += num_enc - 1;
+
+            for (i = num_enc-1; i >= 0; i--)
+            {
+                if ((res = ctx->iface->enc.encode(ctx->priv->alg_priv, img, pts,
+                                                  duration, flags, deadline)))
+                    break;
+
+                ctx--;
+                if (img) img--;
+            }
+            ctx++;
+        }
+
+        FLOATING_POINT_RESTORE();
+    }
+
+    return SAVE_STATUS(ctx, res);
+}
+
+
+const vpx_codec_cx_pkt_t *vpx_codec_get_cx_data(vpx_codec_ctx_t   *ctx,
+        vpx_codec_iter_t  *iter)
+{
+    const vpx_codec_cx_pkt_t *pkt = NULL;
+
+    if (ctx)
+    {
+        if (!iter)
+            ctx->err = VPX_CODEC_INVALID_PARAM;
+        else if (!ctx->iface || !ctx->priv)
+            ctx->err = VPX_CODEC_ERROR;
+        else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
+            ctx->err = VPX_CODEC_INCAPABLE;
+        else
+            pkt = ctx->iface->enc.get_cx_data(ctx->priv->alg_priv, iter);
+    }
+
+    if (pkt && pkt->kind == VPX_CODEC_CX_FRAME_PKT)
+    {
+        /* If the application has specified a destination area for the
+         * compressed data, and the codec has not placed the data there,
+         * and it fits, copy it.
+         */
+        char *dst_buf = ctx->priv->enc.cx_data_dst_buf.buf;
+
+        if (dst_buf
+            && pkt->data.raw.buf != dst_buf
+            && pkt->data.raw.sz
+            + ctx->priv->enc.cx_data_pad_before
+            + ctx->priv->enc.cx_data_pad_after
+            <= ctx->priv->enc.cx_data_dst_buf.sz)
+        {
+            vpx_codec_cx_pkt_t *modified_pkt = &ctx->priv->enc.cx_data_pkt;
+
+            memcpy(dst_buf + ctx->priv->enc.cx_data_pad_before,
+                   pkt->data.raw.buf, pkt->data.raw.sz);
+            *modified_pkt = *pkt;
+            modified_pkt->data.raw.buf = dst_buf;
+            modified_pkt->data.raw.sz += ctx->priv->enc.cx_data_pad_before
+                                         + ctx->priv->enc.cx_data_pad_after;
+            pkt = modified_pkt;
+        }
+
+        if (dst_buf == pkt->data.raw.buf)
+        {
+            ctx->priv->enc.cx_data_dst_buf.buf = dst_buf + pkt->data.raw.sz;
+            ctx->priv->enc.cx_data_dst_buf.sz -= pkt->data.raw.sz;
+        }
+    }
+
+    return pkt;
+}
+
+
+vpx_codec_err_t vpx_codec_set_cx_data_buf(vpx_codec_ctx_t       *ctx,
+        const vpx_fixed_buf_t *buf,
+        unsigned int           pad_before,
+        unsigned int           pad_after)
+{
+    if (!ctx || !ctx->priv)
+        return VPX_CODEC_INVALID_PARAM;
+
+    if (buf)
+    {
+        ctx->priv->enc.cx_data_dst_buf = *buf;
+        ctx->priv->enc.cx_data_pad_before = pad_before;
+        ctx->priv->enc.cx_data_pad_after = pad_after;
+    }
+    else
+    {
+        ctx->priv->enc.cx_data_dst_buf.buf = NULL;
+        ctx->priv->enc.cx_data_dst_buf.sz = 0;
+        ctx->priv->enc.cx_data_pad_before = 0;
+        ctx->priv->enc.cx_data_pad_after = 0;
+    }
+
+    return VPX_CODEC_OK;
+}
+
+
+const vpx_image_t *vpx_codec_get_preview_frame(vpx_codec_ctx_t   *ctx)
+{
+    vpx_image_t *img = NULL;
+
+    if (ctx)
+    {
+        if (!ctx->iface || !ctx->priv)
+            ctx->err = VPX_CODEC_ERROR;
+        else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
+            ctx->err = VPX_CODEC_INCAPABLE;
+        else if (!ctx->iface->enc.get_preview)
+            ctx->err = VPX_CODEC_INCAPABLE;
+        else
+            img = ctx->iface->enc.get_preview(ctx->priv->alg_priv);
+    }
+
+    return img;
+}
+
+
+vpx_fixed_buf_t *vpx_codec_get_global_headers(vpx_codec_ctx_t   *ctx)
+{
+    vpx_fixed_buf_t *buf = NULL;
+
+    if (ctx)
+    {
+        if (!ctx->iface || !ctx->priv)
+            ctx->err = VPX_CODEC_ERROR;
+        else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
+            ctx->err = VPX_CODEC_INCAPABLE;
+        else if (!ctx->iface->enc.get_glob_hdrs)
+            ctx->err = VPX_CODEC_INCAPABLE;
+        else
+            buf = ctx->iface->enc.get_glob_hdrs(ctx->priv->alg_priv);
+    }
+
+    return buf;
+}
+
+
+vpx_codec_err_t  vpx_codec_enc_config_set(vpx_codec_ctx_t            *ctx,
+        const vpx_codec_enc_cfg_t  *cfg)
+{
+    vpx_codec_err_t res;
+
+    if (!ctx || !ctx->iface || !ctx->priv || !cfg)
+        res = VPX_CODEC_INVALID_PARAM;
+    else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
+        res = VPX_CODEC_INCAPABLE;
+    else
+        res = ctx->iface->enc.cfg_set(ctx->priv->alg_priv, cfg);
+
+    return SAVE_STATUS(ctx, res);
+}
+
+
+int vpx_codec_pkt_list_add(struct vpx_codec_pkt_list *list,
+                           const struct vpx_codec_cx_pkt *pkt)
+{
+    if (list->cnt < list->max)
+    {
+        list->pkts[list->cnt++] = *pkt;
+        return 0;
+    }
+
+    return 1;
+}
+
+
+const vpx_codec_cx_pkt_t *vpx_codec_pkt_list_get(struct vpx_codec_pkt_list *list,
+        vpx_codec_iter_t           *iter)
+{
+    const vpx_codec_cx_pkt_t *pkt;
+
+    if (!(*iter))
+    {
+        *iter = list->pkts;
+    }
+
+    pkt = (const void *) * iter;
+
+    if ((size_t)(pkt - list->pkts) < list->cnt)
+        *iter = pkt + 1;
+    else
+        pkt = NULL;
+
+    return pkt;
+}
diff --git a/vpx/src/vpx_image.c b/vpx/src/vpx_image.c
new file mode 100644 (file)
index 0000000..336b6e2
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include "vpx/vpx_image.h"
+
+#define ADDRESS_STORAGE_SIZE      sizeof(size_t)
+/*returns an addr aligned to the byte boundary specified by align*/
+#define align_addr(addr,align) (void*)(((size_t)(addr) + ((align) - 1)) & (size_t)-(align))
+
+/* Memalign code is copied from vpx_mem.c */
+static void *img_buf_memalign(size_t align, size_t size)
+{
+    void *addr,
+         * x = NULL;
+
+    addr = malloc(size + align - 1 + ADDRESS_STORAGE_SIZE);
+
+    if (addr)
+    {
+        x = align_addr((unsigned char *)addr + ADDRESS_STORAGE_SIZE, (int)align);
+        /* save the actual malloc address */
+        ((size_t *)x)[-1] = (size_t)addr;
+    }
+
+    return x;
+}
+
+static void img_buf_free(void *memblk)
+{
+    if (memblk)
+    {
+        void *addr = (void *)(((size_t *)memblk)[-1]);
+        free(addr);
+    }
+}
+
+static vpx_image_t *img_alloc_helper(vpx_image_t  *img,
+                                     vpx_img_fmt_t fmt,
+                                     unsigned int  d_w,
+                                     unsigned int  d_h,
+                                     unsigned int  buf_align,
+                                     unsigned int  stride_align,
+                                     unsigned char      *img_data)
+{
+
+    unsigned int  h, w, s, xcs, ycs, bps;
+    int           align;
+
+    /* Treat align==0 like align==1 */
+    if (!buf_align)
+        buf_align = 1;
+
+    /* Validate alignment (must be power of 2) */
+    if (buf_align & (buf_align - 1))
+        goto fail;
+
+    /* Treat align==0 like align==1 */
+    if (!stride_align)
+        stride_align = 1;
+
+    /* Validate alignment (must be power of 2) */
+    if (stride_align & (stride_align - 1))
+        goto fail;
+
+    /* Get sample size for this format */
+    switch (fmt)
+    {
+    case VPX_IMG_FMT_RGB32:
+    case VPX_IMG_FMT_RGB32_LE:
+    case VPX_IMG_FMT_ARGB:
+    case VPX_IMG_FMT_ARGB_LE:
+        bps = 32;
+        break;
+    case VPX_IMG_FMT_RGB24:
+    case VPX_IMG_FMT_BGR24:
+        bps = 24;
+        break;
+    case VPX_IMG_FMT_RGB565:
+    case VPX_IMG_FMT_RGB565_LE:
+    case VPX_IMG_FMT_RGB555:
+    case VPX_IMG_FMT_RGB555_LE:
+    case VPX_IMG_FMT_UYVY:
+    case VPX_IMG_FMT_YUY2:
+    case VPX_IMG_FMT_YVYU:
+        bps = 16;
+        break;
+    case VPX_IMG_FMT_I420:
+    case VPX_IMG_FMT_YV12:
+    case VPX_IMG_FMT_VPXI420:
+    case VPX_IMG_FMT_VPXYV12:
+        bps = 12;
+        break;
+    default:
+        bps = 16;
+        break;
+    }
+
+    /* Get chroma shift values for this format */
+    switch (fmt)
+    {
+    case VPX_IMG_FMT_I420:
+    case VPX_IMG_FMT_YV12:
+    case VPX_IMG_FMT_VPXI420:
+    case VPX_IMG_FMT_VPXYV12:
+        xcs = 1;
+        break;
+    default:
+        xcs = 0;
+        break;
+    }
+
+    switch (fmt)
+    {
+    case VPX_IMG_FMT_I420:
+    case VPX_IMG_FMT_YV12:
+    case VPX_IMG_FMT_VPXI420:
+    case VPX_IMG_FMT_VPXYV12:
+        ycs = 1;
+        break;
+    default:
+        ycs = 0;
+        break;
+    }
+
+    /* Calculate storage sizes given the chroma subsampling */
+    align = (1 << xcs) - 1;
+    w = (d_w + align) & ~align;
+    align = (1 << ycs) - 1;
+    h = (d_h + align) & ~align;
+    s = (fmt & VPX_IMG_FMT_PLANAR) ? w : bps * w / 8;
+    s = (s + stride_align - 1) & ~(stride_align - 1);
+
+    /* Allocate the new image */
+    if (!img)
+    {
+        img = (vpx_image_t *)calloc(1, sizeof(vpx_image_t));
+
+        if (!img)
+            goto fail;
+
+        img->self_allocd = 1;
+    }
+    else
+    {
+        memset(img, 0, sizeof(vpx_image_t));
+    }
+
+    img->img_data = img_data;
+
+    if (!img_data)
+    {
+        img->img_data = img_buf_memalign(buf_align, ((fmt & VPX_IMG_FMT_PLANAR)?
+                                         h * s * bps / 8 : h * s));
+        img->img_data_owner = 1;
+    }
+
+    if (!img->img_data)
+        goto fail;
+
+    img->fmt = fmt;
+    img->w = w;
+    img->h = h;
+    img->x_chroma_shift = xcs;
+    img->y_chroma_shift = ycs;
+    img->bps = bps;
+
+    /* Calculate strides */
+    img->stride[VPX_PLANE_Y] = img->stride[VPX_PLANE_ALPHA] = s;
+    img->stride[VPX_PLANE_U] = img->stride[VPX_PLANE_V] = s >> xcs;
+
+    /* Default viewport to entire image */
+    if (!vpx_img_set_rect(img, 0, 0, d_w, d_h))
+        return img;
+
+fail:
+    vpx_img_free(img);
+    return NULL;
+}
+
+vpx_image_t *vpx_img_alloc(vpx_image_t  *img,
+                           vpx_img_fmt_t fmt,
+                           unsigned int  d_w,
+                           unsigned int  d_h,
+                           unsigned int  align)
+{
+    return img_alloc_helper(img, fmt, d_w, d_h, align, align, NULL);
+}
+
+vpx_image_t *vpx_img_wrap(vpx_image_t  *img,
+                          vpx_img_fmt_t fmt,
+                          unsigned int  d_w,
+                          unsigned int  d_h,
+                          unsigned int  stride_align,
+                          unsigned char       *img_data)
+{
+    /* By setting buf_align = 1, we don't change buffer alignment in this
+     * function. */
+    return img_alloc_helper(img, fmt, d_w, d_h, 1, stride_align, img_data);
+}
+
+int vpx_img_set_rect(vpx_image_t  *img,
+                     unsigned int  x,
+                     unsigned int  y,
+                     unsigned int  w,
+                     unsigned int  h)
+{
+    unsigned char      *data;
+
+    if (x + w <= img->w && y + h <= img->h)
+    {
+        img->d_w = w;
+        img->d_h = h;
+
+        /* Calculate plane pointers */
+        if (!(img->fmt & VPX_IMG_FMT_PLANAR))
+        {
+            img->planes[VPX_PLANE_PACKED] =
+                img->img_data + x * img->bps / 8 + y * img->stride[VPX_PLANE_PACKED];
+        }
+        else
+        {
+            data = img->img_data;
+
+            if (img->fmt & VPX_IMG_FMT_HAS_ALPHA)
+            {
+                img->planes[VPX_PLANE_ALPHA] =
+                    data + x + y * img->stride[VPX_PLANE_ALPHA];
+                data += img->h * img->stride[VPX_PLANE_ALPHA];
+            }
+
+            img->planes[VPX_PLANE_Y] = data + x + y * img->stride[VPX_PLANE_Y];
+            data += img->h * img->stride[VPX_PLANE_Y];
+
+            if (!(img->fmt & VPX_IMG_FMT_UV_FLIP))
+            {
+                img->planes[VPX_PLANE_U] = data
+                                       + (x >> img->x_chroma_shift)
+                                       + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_U];
+                data += (img->h >> img->y_chroma_shift) * img->stride[VPX_PLANE_U];
+                img->planes[VPX_PLANE_V] = data
+                                       + (x >> img->x_chroma_shift)
+                                       + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_V];
+            }
+            else
+            {
+                img->planes[VPX_PLANE_V] = data
+                                       + (x >> img->x_chroma_shift)
+                                       + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_V];
+                data += (img->h >> img->y_chroma_shift) * img->stride[VPX_PLANE_V];
+                img->planes[VPX_PLANE_U] = data
+                                       + (x >> img->x_chroma_shift)
+                                       + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_U];
+            }
+        }
+
+        return 0;
+    }
+
+    return -1;
+}
+
+void vpx_img_flip(vpx_image_t *img)
+{
+    /* Note: In the calculation pointer adjustment calculation, we want the
+     * rhs to be promoted to a signed type. Section 6.3.1.8 of the ISO C99
+     * standard indicates that if the adjustment parameter is unsigned, the
+     * stride parameter will be promoted to unsigned, causing errors when
+     * the lhs is a larger type than the rhs.
+     */
+    img->planes[VPX_PLANE_Y] += (signed)(img->d_h - 1) * img->stride[VPX_PLANE_Y];
+    img->stride[VPX_PLANE_Y] = -img->stride[VPX_PLANE_Y];
+
+    img->planes[VPX_PLANE_U] += (signed)((img->d_h >> img->y_chroma_shift) - 1)
+                            * img->stride[VPX_PLANE_U];
+    img->stride[VPX_PLANE_U] = -img->stride[VPX_PLANE_U];
+
+    img->planes[VPX_PLANE_V] += (signed)((img->d_h >> img->y_chroma_shift) - 1)
+                            * img->stride[VPX_PLANE_V];
+    img->stride[VPX_PLANE_V] = -img->stride[VPX_PLANE_V];
+
+    img->planes[VPX_PLANE_ALPHA] += (signed)(img->d_h - 1) * img->stride[VPX_PLANE_ALPHA];
+    img->stride[VPX_PLANE_ALPHA] = -img->stride[VPX_PLANE_ALPHA];
+}
+
+void vpx_img_free(vpx_image_t *img)
+{
+    if (img)
+    {
+        if (img->img_data && img->img_data_owner)
+            img_buf_free(img->img_data);
+
+        if (img->self_allocd)
+            free(img);
+    }
+}
diff --git a/vpx/vp8.h b/vpx/vp8.h
new file mode 100644 (file)
index 0000000..2952203
--- /dev/null
+++ b/vpx/vp8.h
@@ -0,0 +1,123 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*!\defgroup vp8 VP8
+ * \ingroup codecs
+ * VP8 is vpx's newest video compression algorithm that uses motion
+ * compensated prediction, Discrete Cosine Transform (DCT) coding of the
+ * prediction error signal and context dependent entropy coding techniques
+ * based on arithmetic principles. It features:
+ *  - YUV 4:2:0 image format
+ *  - Macro-block based coding (16x16 luma plus two 8x8 chroma)
+ *  - 1/4 (1/8) pixel accuracy motion compensated prediction
+ *  - 4x4 DCT transform
+ *  - 128 level linear quantizer
+ *  - In loop deblocking filter
+ *  - Context-based entropy coding
+ *
+ * @{
+ */
+/*!\file
+ * \brief Provides controls common to both the VP8 encoder and decoder.
+ */
+#ifndef VP8_H
+#define VP8_H
+#include "vpx_codec_impl_top.h"
+
+/*!\brief Control functions
+ *
+ * The set of macros define the control functions of VP8 interface
+ */
+enum vp8_com_control_id
+{
+    VP8_SET_REFERENCE           = 1,    /**< pass in an external frame into decoder to be used as reference frame */
+    VP8_COPY_REFERENCE          = 2,    /**< get a copy of reference frame from the decoder */
+    VP8_SET_POSTPROC            = 3,    /**< set the decoder's post processing settings  */
+    VP8_SET_DBG_COLOR_REF_FRAME = 4,    /**< set the reference frames to color for each macroblock */
+    VP8_SET_DBG_COLOR_MB_MODES  = 5,    /**< set which macro block modes to color */
+    VP8_SET_DBG_COLOR_B_MODES   = 6,    /**< set which blocks modes to color */
+    VP8_SET_DBG_DISPLAY_MV      = 7,    /**< set which motion vector modes to draw */
+    VP8_COMMON_CTRL_ID_MAX,
+    VP8_DECODER_CTRL_ID_START   = 256
+};
+
+/*!\brief post process flags
+ *
+ * The set of macros define VP8 decoder post processing flags
+ */
+enum vp8_postproc_level
+{
+    VP8_NOFILTERING             = 0,
+    VP8_DEBLOCK                 = 1<<0,
+    VP8_DEMACROBLOCK            = 1<<1,
+    VP8_ADDNOISE                = 1<<2,
+    VP8_DEBUG_TXT_FRAME_INFO    = 1<<3, /**< print frame information */
+    VP8_DEBUG_TXT_MBLK_MODES    = 1<<4, /**< print macro block modes over each macro block */
+    VP8_DEBUG_TXT_DC_DIFF       = 1<<5, /**< print dc diff for each macro block */
+    VP8_DEBUG_TXT_RATE_INFO     = 1<<6, /**< print video rate info (encoder only) */
+    VP8_MFQE                    = 1<<10
+};
+
+/*!\brief post process flags
+ *
+ * This define a structure that describe the post processing settings. For
+ * the best objective measure (using the PSNR metric) set post_proc_flag
+ * to VP8_DEBLOCK and deblocking_level to 1.
+ */
+
+typedef struct vp8_postproc_cfg
+{
+    int post_proc_flag;         /**< the types of post processing to be done, should be combination of "vp8_postproc_level" */
+    int deblocking_level;       /**< the strength of deblocking, valid range [0, 16] */
+    int noise_level;            /**< the strength of additive noise, valid range [0, 16] */
+} vp8_postproc_cfg_t;
+
+/*!\brief reference frame type
+ *
+ * The set of macros define the type of VP8 reference frames
+ */
+typedef enum vpx_ref_frame_type
+{
+    VP8_LAST_FRAME = 1,
+    VP8_GOLD_FRAME = 2,
+    VP8_ALTR_FRAME = 4
+} vpx_ref_frame_type_t;
+
+/*!\brief reference frame data struct
+ *
+ * define the data struct to access vp8 reference frames
+ */
+
+typedef struct vpx_ref_frame
+{
+    vpx_ref_frame_type_t  frame_type;   /**< which reference frame */
+    vpx_image_t           img;          /**< reference frame data in image format */
+} vpx_ref_frame_t;
+
+
+/*!\brief vp8 decoder control function parameter type
+ *
+ * defines the data type for each of VP8 decoder control function requires
+ */
+
+VPX_CTRL_USE_TYPE(VP8_SET_REFERENCE,           vpx_ref_frame_t *)
+VPX_CTRL_USE_TYPE(VP8_COPY_REFERENCE,          vpx_ref_frame_t *)
+VPX_CTRL_USE_TYPE(VP8_SET_POSTPROC,            vp8_postproc_cfg_t *)
+VPX_CTRL_USE_TYPE(VP8_SET_DBG_COLOR_REF_FRAME, int)
+VPX_CTRL_USE_TYPE(VP8_SET_DBG_COLOR_MB_MODES,  int)
+VPX_CTRL_USE_TYPE(VP8_SET_DBG_COLOR_B_MODES,   int)
+VPX_CTRL_USE_TYPE(VP8_SET_DBG_DISPLAY_MV,      int)
+
+
+/*! @} - end defgroup vp8 */
+
+#include "vpx_codec_impl_bottom.h"
+#endif
diff --git a/vpx/vp8cx.h b/vpx/vp8cx.h
new file mode 100644 (file)
index 0000000..0af631c
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*!\defgroup vp8_encoder WebM VP8 Encoder
+ * \ingroup vp8
+ *
+ * @{
+ */
+#include "vp8.h"
+
+/*!\file
+ * \brief Provides definitions for using the VP8 encoder algorithm within the
+ *        vpx Codec Interface.
+ */
+#ifndef VP8CX_H
+#define VP8CX_H
+#include "vpx_codec_impl_top.h"
+
+/*!\name Algorithm interface for VP8
+ *
+ * This interface provides the capability to encode raw VP8 streams, as would
+ * be found in AVI files.
+ * @{
+ */
+extern vpx_codec_iface_t  vpx_codec_vp8_cx_algo;
+extern vpx_codec_iface_t* vpx_codec_vp8_cx(void);
+/*!@} - end algorithm interface member group*/
+
+
+/*
+ * Algorithm Flags
+ */
+
+/*!\brief Don't reference the last frame
+ *
+ * When this flag is set, the encoder will not use the last frame as a
+ * predictor. When not set, the encoder will choose whether to use the
+ * last frame or not automatically.
+ */
+#define VP8_EFLAG_NO_REF_LAST      (1<<16)
+
+
+/*!\brief Don't reference the golden frame
+ *
+ * When this flag is set, the encoder will not use the golden frame as a
+ * predictor. When not set, the encoder will choose whether to use the
+ * golden frame or not automatically.
+ */
+#define VP8_EFLAG_NO_REF_GF        (1<<17)
+
+
+/*!\brief Don't reference the alternate reference frame
+ *
+ * When this flag is set, the encoder will not use the alt ref frame as a
+ * predictor. When not set, the encoder will choose whether to use the
+ * alt ref frame or not automatically.
+ */
+#define VP8_EFLAG_NO_REF_ARF       (1<<21)
+
+
+/*!\brief Don't update the last frame
+ *
+ * When this flag is set, the encoder will not update the last frame with
+ * the contents of the current frame.
+ */
+#define VP8_EFLAG_NO_UPD_LAST      (1<<18)
+
+
+/*!\brief Don't update the golden frame
+ *
+ * When this flag is set, the encoder will not update the golden frame with
+ * the contents of the current frame.
+ */
+#define VP8_EFLAG_NO_UPD_GF        (1<<22)
+
+
+/*!\brief Don't update the alternate reference frame
+ *
+ * When this flag is set, the encoder will not update the alt ref frame with
+ * the contents of the current frame.
+ */
+#define VP8_EFLAG_NO_UPD_ARF       (1<<23)
+
+
+/*!\brief Force golden frame update
+ *
+ * When this flag is set, the encoder copy the contents of the current frame
+ * to the golden frame buffer.
+ */
+#define VP8_EFLAG_FORCE_GF         (1<<19)
+
+
+/*!\brief Force alternate reference frame update
+ *
+ * When this flag is set, the encoder copy the contents of the current frame
+ * to the alternate reference frame buffer.
+ */
+#define VP8_EFLAG_FORCE_ARF        (1<<24)
+
+
+/*!\brief Disable entropy update
+ *
+ * When this flag is set, the encoder will not update its internal entropy
+ * model based on the entropy of this frame.
+ */
+#define VP8_EFLAG_NO_UPD_ENTROPY   (1<<20)
+
+
+/*!\brief VP8 encoder control functions
+ *
+ * This set of macros define the control functions available for the VP8
+ * encoder interface.
+ *
+ * \sa #vpx_codec_control
+ */
+enum vp8e_enc_control_id
+{
+    VP8E_UPD_ENTROPY           = 5,  /**< control function to set mode of entropy update in encoder */
+    VP8E_UPD_REFERENCE,              /**< control function to set reference update mode in encoder */
+    VP8E_USE_REFERENCE,              /**< control function to set which reference frame encoder can use */
+    VP8E_SET_ROI_MAP,                /**< control function to pass an ROI map to encoder */
+    VP8E_SET_ACTIVEMAP,              /**< control function to pass an Active map to encoder */
+    VP8E_SET_SCALEMODE         = 11, /**< control function to set encoder scaling mode */
+    /*!\brief control function to set vp8 encoder cpuused
+     *
+     * Changes in this value influences, among others, the encoder's selection
+     * of motion estimation methods. Values greater than 0 will increase encoder
+     * speed at the expense of quality.
+     * The full set of adjustments can be found in
+     * onyx_if.c:vp8_set_speed_features().
+     * \todo List highlights of the changes at various levels.
+     *
+     * \note Valid range: -16..16
+     */
+    VP8E_SET_CPUUSED           = 13,
+    VP8E_SET_ENABLEAUTOALTREF,       /**< control function to enable vp8 to automatic set and use altref frame */
+    VP8E_SET_NOISE_SENSITIVITY,      /**< control function to set noise sensitivity */
+    VP8E_SET_SHARPNESS,              /**< control function to set sharpness */
+    VP8E_SET_STATIC_THRESHOLD,       /**< control function to set the threshold for macroblocks treated static */
+    VP8E_SET_TOKEN_PARTITIONS,       /**< control function to set the number of token partitions  */
+    VP8E_GET_LAST_QUANTIZER,         /**< return the quantizer chosen by the
+                                          encoder for the last frame using the internal
+                                          scale */
+    VP8E_GET_LAST_QUANTIZER_64,      /**< return the quantizer chosen by the
+                                          encoder for the last frame, using the 0..63
+                                          scale as used by the rc_*_quantizer config
+                                          parameters */
+    VP8E_SET_ARNR_MAXFRAMES,         /**< control function to set the max number of frames blurred creating arf*/
+    VP8E_SET_ARNR_STRENGTH ,         /**< control function to set the filter strength for the arf */
+    VP8E_SET_ARNR_TYPE     ,         /**< control function to set the type of filter to use for the arf*/
+    VP8E_SET_TUNING,                 /**< control function to set visual tuning */
+    /*!\brief control function to set constrained quality level
+     *
+     * \attention For this value to be used vpx_codec_enc_cfg_t::g_usage must be
+     *            set to #VPX_CQ.
+     * \note Valid range: 0..63
+     */
+    VP8E_SET_CQ_LEVEL,
+
+    /*!\brief Max data rate for Intra frames
+     *
+     * This value controls additional clamping on the maximum size of a
+     * keyframe. It is expressed as a percentage of the average
+     * per-frame bitrate, with the special (and default) value 0 meaning
+     * unlimited, or no additional clamping beyond the codec's built-in
+     * algorithm.
+     *
+     * For example, to allocate no more than 4.5 frames worth of bitrate
+     * to a keyframe, set this to 450.
+     *
+     */
+    VP8E_SET_MAX_INTRA_BITRATE_PCT
+};
+
+/*!\brief vpx 1-D scaling mode
+ *
+ * This set of constants define 1-D vpx scaling modes
+ */
+typedef enum vpx_scaling_mode_1d
+{
+    VP8E_NORMAL      = 0,
+    VP8E_FOURFIVE    = 1,
+    VP8E_THREEFIVE   = 2,
+    VP8E_ONETWO      = 3
+} VPX_SCALING_MODE;
+
+
+/*!\brief  vpx region of interest map
+ *
+ * These defines the data structures for the region of interest map
+ *
+ */
+
+typedef struct vpx_roi_map
+{
+    unsigned char *roi_map;      /**< specify an id between 0 and 3 for each 16x16 region within a frame */
+    unsigned int   rows;         /**< number of rows */
+    unsigned int   cols;         /**< number of cols */
+    int     delta_q[4];          /**< quantizer delta [-64, 64] off baseline for regions with id between 0 and 3*/
+    int     delta_lf[4];         /**< loop filter strength delta [-32, 32] for regions with id between 0 and 3 */
+    unsigned int   static_threshold[4];/**< threshold for region to be treated as static */
+} vpx_roi_map_t;
+
+/*!\brief  vpx active region map
+ *
+ * These defines the data structures for active region map
+ *
+ */
+
+
+typedef struct vpx_active_map
+{
+    unsigned char  *active_map; /**< specify an on (1) or off (0) each 16x16 region within a frame */
+    unsigned int    rows;       /**< number of rows */
+    unsigned int    cols;       /**< number of cols */
+} vpx_active_map_t;
+
+/*!\brief  vpx image scaling mode
+ *
+ * This defines the data structure for image scaling mode
+ *
+ */
+typedef struct vpx_scaling_mode
+{
+    VPX_SCALING_MODE    h_scaling_mode;  /**< horizontal scaling mode */
+    VPX_SCALING_MODE    v_scaling_mode;  /**< vertical scaling mode   */
+} vpx_scaling_mode_t;
+
+/*!\brief VP8 encoding mode
+ *
+ * This defines VP8 encoding mode
+ *
+ */
+typedef enum
+{
+    VP8_BEST_QUALITY_ENCODING,
+    VP8_GOOD_QUALITY_ENCODING,
+    VP8_REAL_TIME_ENCODING
+} vp8e_encoding_mode;
+
+/*!\brief VP8 token partition mode
+ *
+ * This defines VP8 partitioning mode for compressed data, i.e., the number of
+ * sub-streams in the bitstream. Used for parallelized decoding.
+ *
+ */
+
+typedef enum
+{
+    VP8_ONE_TOKENPARTITION   = 0,
+    VP8_TWO_TOKENPARTITION   = 1,
+    VP8_FOUR_TOKENPARTITION  = 2,
+    VP8_EIGHT_TOKENPARTITION = 3
+} vp8e_token_partitions;
+
+
+/*!\brief VP8 model tuning parameters
+ *
+ * Changes the encoder to tune for certain types of input material.
+ *
+ */
+typedef enum
+{
+    VP8_TUNE_PSNR,
+    VP8_TUNE_SSIM
+} vp8e_tuning;
+
+
+/*!\brief VP8 encoder control function parameter type
+ *
+ * Defines the data types that VP8E control functions take. Note that
+ * additional common controls are defined in vp8.h
+ *
+ */
+
+
+/* These controls have been deprecated in favor of the flags parameter to
+ * vpx_codec_encode(). See the definition of VP8_EFLAG_* above.
+ */
+VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_UPD_ENTROPY,            int)
+VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_UPD_REFERENCE,          int)
+VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_USE_REFERENCE,          int)
+
+VPX_CTRL_USE_TYPE(VP8E_SET_ROI_MAP,            vpx_roi_map_t *)
+VPX_CTRL_USE_TYPE(VP8E_SET_ACTIVEMAP,          vpx_active_map_t *)
+VPX_CTRL_USE_TYPE(VP8E_SET_SCALEMODE,          vpx_scaling_mode_t *)
+
+VPX_CTRL_USE_TYPE(VP8E_SET_CPUUSED,            int)
+VPX_CTRL_USE_TYPE(VP8E_SET_ENABLEAUTOALTREF,   unsigned int)
+VPX_CTRL_USE_TYPE(VP8E_SET_NOISE_SENSITIVITY,  unsigned int)
+VPX_CTRL_USE_TYPE(VP8E_SET_SHARPNESS,          unsigned int)
+VPX_CTRL_USE_TYPE(VP8E_SET_STATIC_THRESHOLD,   unsigned int)
+VPX_CTRL_USE_TYPE(VP8E_SET_TOKEN_PARTITIONS,   vp8e_token_partitions)
+
+VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_MAXFRAMES,     unsigned int)
+VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_STRENGTH ,     unsigned int)
+VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_TYPE     ,     unsigned int)
+VPX_CTRL_USE_TYPE(VP8E_SET_TUNING,             vp8e_tuning)
+VPX_CTRL_USE_TYPE(VP8E_SET_CQ_LEVEL     ,      unsigned int)
+
+VPX_CTRL_USE_TYPE(VP8E_GET_LAST_QUANTIZER,     int *)
+VPX_CTRL_USE_TYPE(VP8E_GET_LAST_QUANTIZER_64,  int *)
+
+VPX_CTRL_USE_TYPE(VP8E_SET_MAX_INTRA_BITRATE_PCT, unsigned int)
+
+
+/*! @} - end defgroup vp8_encoder */
+#include "vpx_codec_impl_bottom.h"
+#endif
diff --git a/vpx/vp8dx.h b/vpx/vp8dx.h
new file mode 100644 (file)
index 0000000..8661035
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vp8.h"
+
+/*!\defgroup vp8_decoder WebM VP8 Decoder
+ * \ingroup vp8
+ *
+ * @{
+ */
+/*!\file
+ * \brief Provides definitions for using the VP8 algorithm within the vpx Decoder
+ *        interface.
+ */
+#ifndef VP8DX_H
+#define VP8DX_H
+#include "vpx_codec_impl_top.h"
+
+/*!\name Algorithm interface for VP8
+ *
+ * This interface provides the capability to decode raw VP8 streams, as would
+ * be found in AVI files and other non-Flash uses.
+ * @{
+ */
+extern vpx_codec_iface_t  vpx_codec_vp8_dx_algo;
+extern vpx_codec_iface_t* vpx_codec_vp8_dx(void);
+/*!@} - end algorithm interface member group*/
+
+/* Include controls common to both the encoder and decoder */
+#include "vp8.h"
+
+
+/*!\brief VP8 decoder control functions
+ *
+ * This set of macros define the control functions available for the VP8
+ * decoder interface.
+ *
+ * \sa #vpx_codec_control
+ */
+enum vp8_dec_control_id
+{
+    /** control function to get info on which reference frames were updated
+     *  by the last decode
+     */
+    VP8D_GET_LAST_REF_UPDATES = VP8_DECODER_CTRL_ID_START,
+
+    /** check if the indicated frame is corrupted */
+    VP8D_GET_FRAME_CORRUPTED,
+
+    /** control function to get info on which reference frames were used
+     *  by the last decode
+     */
+    VP8D_GET_LAST_REF_USED,
+
+    VP8_DECODER_CTRL_ID_MAX
+} ;
+
+
+/*!\brief VP8 decoder control function parameter type
+ *
+ * Defines the data types that VP8D control functions take. Note that
+ * additional common controls are defined in vp8.h
+ *
+ */
+
+
+VPX_CTRL_USE_TYPE(VP8D_GET_LAST_REF_UPDATES,   int *)
+VPX_CTRL_USE_TYPE(VP8D_GET_FRAME_CORRUPTED,    int *)
+VPX_CTRL_USE_TYPE(VP8D_GET_LAST_REF_USED,      int *)
+
+/*! @} - end defgroup vp8_decoder */
+
+
+#include "vpx_codec_impl_bottom.h"
+#endif
diff --git a/vpx/vpx_codec.h b/vpx/vpx_codec.h
new file mode 100644 (file)
index 0000000..d92e165
--- /dev/null
@@ -0,0 +1,554 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*!\defgroup codec Common Algorithm Interface
+ * This abstraction allows applications to easily support multiple video
+ * formats with minimal code duplication. This section describes the interface
+ * common to all codecs (both encoders and decoders).
+ * @{
+ */
+
+/*!\file
+ * \brief Describes the codec algorithm interface to applications.
+ *
+ * This file describes the interface between an application and a
+ * video codec algorithm.
+ *
+ * An application instantiates a specific codec instance by using
+ * vpx_codec_init() and a pointer to the algorithm's interface structure:
+ *     <pre>
+ *     my_app.c:
+ *       extern vpx_codec_iface_t my_codec;
+ *       {
+ *           vpx_codec_ctx_t algo;
+ *           res = vpx_codec_init(&algo, &my_codec);
+ *       }
+ *     </pre>
+ *
+ * Once initialized, the instance is manged using other functions from
+ * the vpx_codec_* family.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef VPX_CODEC_H
+#define VPX_CODEC_H
+#include "vpx_integer.h"
+#include "vpx_image.h"
+
+    /*!\brief Decorator indicating a function is deprecated */
+#ifndef DEPRECATED
+#if defined(__GNUC__) && __GNUC__
+#define DEPRECATED          __attribute__ ((deprecated))
+#define DECLSPEC_DEPRECATED /**< \copydoc #DEPRECATED */
+#elif defined(_MSC_VER)
+#define DEPRECATED
+#define DECLSPEC_DEPRECATED __declspec(deprecated) /**< \copydoc #DEPRECATED */
+#else
+#define DEPRECATED
+#define DECLSPEC_DEPRECATED /**< \copydoc #DEPRECATED */
+#endif
+#endif
+
+    /*!\brief Decorator indicating a function is potentially unused */
+#ifdef UNUSED
+#elif __GNUC__
+#define UNUSED __attribute__ ((unused))
+#else
+#define UNUSED
+#endif
+
+    /*!\brief Current ABI version number
+     *
+     * \internal
+     * If this file is altered in any way that changes the ABI, this value
+     * must be bumped.  Examples include, but are not limited to, changing
+     * types, removing or reassigning enums, adding/removing/rearranging
+     * fields to structures
+     */
+#define VPX_CODEC_ABI_VERSION (2 + VPX_IMAGE_ABI_VERSION) /**<\hideinitializer*/
+
+    /*!\brief Algorithm return codes */
+    typedef enum {
+        /*!\brief Operation completed without error */
+        VPX_CODEC_OK,
+
+        /*!\brief Unspecified error */
+        VPX_CODEC_ERROR,
+
+        /*!\brief Memory operation failed */
+        VPX_CODEC_MEM_ERROR,
+
+        /*!\brief ABI version mismatch */
+        VPX_CODEC_ABI_MISMATCH,
+
+        /*!\brief Algorithm does not have required capability */
+        VPX_CODEC_INCAPABLE,
+
+        /*!\brief The given bitstream is not supported.
+         *
+         * The bitstream was unable to be parsed at the highest level. The decoder
+         * is unable to proceed. This error \ref SHOULD be treated as fatal to the
+         * stream. */
+        VPX_CODEC_UNSUP_BITSTREAM,
+
+        /*!\brief Encoded bitstream uses an unsupported feature
+         *
+         * The decoder does not implement a feature required by the encoder. This
+         * return code should only be used for features that prevent future
+         * pictures from being properly decoded. This error \ref MAY be treated as
+         * fatal to the stream or \ref MAY be treated as fatal to the current GOP.
+         */
+        VPX_CODEC_UNSUP_FEATURE,
+
+        /*!\brief The coded data for this stream is corrupt or incomplete
+         *
+         * There was a problem decoding the current frame.  This return code
+         * should only be used for failures that prevent future pictures from
+         * being properly decoded. This error \ref MAY be treated as fatal to the
+         * stream or \ref MAY be treated as fatal to the current GOP. If decoding
+         * is continued for the current GOP, artifacts may be present.
+         */
+        VPX_CODEC_CORRUPT_FRAME,
+
+        /*!\brief An application-supplied parameter is not valid.
+         *
+         */
+        VPX_CODEC_INVALID_PARAM,
+
+        /*!\brief An iterator reached the end of list.
+         *
+         */
+        VPX_CODEC_LIST_END
+
+    }
+    vpx_codec_err_t;
+
+
+    /*! \brief Codec capabilities bitfield
+     *
+     *  Each codec advertises the capabilities it supports as part of its
+     *  ::vpx_codec_iface_t interface structure. Capabilities are extra interfaces
+     *  or functionality, and are not required to be supported.
+     *
+     *  The available flags are specified by VPX_CODEC_CAP_* defines.
+     */
+    typedef long vpx_codec_caps_t;
+#define VPX_CODEC_CAP_DECODER 0x1 /**< Is a decoder */
+#define VPX_CODEC_CAP_ENCODER 0x2 /**< Is an encoder */
+#define VPX_CODEC_CAP_XMA     0x4 /**< Supports eXternal Memory Allocation */
+
+
+    /*! \brief Initialization-time Feature Enabling
+     *
+     *  Certain codec features must be known at initialization time, to allow for
+     *  proper memory allocation.
+     *
+     *  The available flags are specified by VPX_CODEC_USE_* defines.
+     */
+    typedef long vpx_codec_flags_t;
+#define VPX_CODEC_USE_XMA 0x00000001    /**< Use eXternal Memory Allocation mode */
+
+
+    /*!\brief Codec interface structure.
+     *
+     * Contains function pointers and other data private to the codec
+     * implementation. This structure is opaque to the application.
+     */
+    typedef const struct vpx_codec_iface vpx_codec_iface_t;
+
+
+    /*!\brief Codec private data structure.
+     *
+     * Contains data private to the codec implementation. This structure is opaque
+     * to the application.
+     */
+    typedef       struct vpx_codec_priv  vpx_codec_priv_t;
+
+
+    /*!\brief Iterator
+     *
+     * Opaque storage used for iterating over lists.
+     */
+    typedef const void *vpx_codec_iter_t;
+
+
+    /*!\brief Codec context structure
+     *
+     * All codecs \ref MUST support this context structure fully. In general,
+     * this data should be considered private to the codec algorithm, and
+     * not be manipulated or examined by the calling application. Applications
+     * may reference the 'name' member to get a printable description of the
+     * algorithm.
+     */
+    typedef struct vpx_codec_ctx
+    {
+        const char              *name;        /**< Printable interface name */
+        vpx_codec_iface_t       *iface;       /**< Interface pointers */
+        vpx_codec_err_t          err;         /**< Last returned error */
+        const char              *err_detail;  /**< Detailed info, if available */
+        vpx_codec_flags_t        init_flags;  /**< Flags passed at init time */
+        union
+        {
+            struct vpx_codec_dec_cfg  *dec;   /**< Decoder Configuration Pointer */
+            struct vpx_codec_enc_cfg  *enc;   /**< Encoder Configuration Pointer */
+            void                      *raw;
+        }                        config;      /**< Configuration pointer aliasing union */
+        vpx_codec_priv_t        *priv;        /**< Algorithm private storage */
+    } vpx_codec_ctx_t;
+
+
+    /*
+     * Library Version Number Interface
+     *
+     * For example, see the following sample return values:
+     *     vpx_codec_version()           (1<<16 | 2<<8 | 3)
+     *     vpx_codec_version_str()       "v1.2.3-rc1-16-gec6a1ba"
+     *     vpx_codec_version_extra_str() "rc1-16-gec6a1ba"
+     */
+
+    /*!\brief Return the version information (as an integer)
+     *
+     * Returns a packed encoding of the library version number. This will only include
+     * the major.minor.patch component of the version number. Note that this encoded
+     * value should be accessed through the macros provided, as the encoding may change
+     * in the future.
+     *
+     */
+    int vpx_codec_version(void);
+#define VPX_VERSION_MAJOR(v) ((v>>16)&0xff) /**< extract major from packed version */
+#define VPX_VERSION_MINOR(v) ((v>>8)&0xff)  /**< extract minor from packed version */
+#define VPX_VERSION_PATCH(v) ((v>>0)&0xff)  /**< extract patch from packed version */
+
+    /*!\brief Return the version major number */
+#define vpx_codec_version_major() ((vpx_codec_version()>>16)&0xff)
+
+    /*!\brief Return the version minor number */
+#define vpx_codec_version_minor() ((vpx_codec_version()>>8)&0xff)
+
+    /*!\brief Return the version patch number */
+#define vpx_codec_version_patch() ((vpx_codec_version()>>0)&0xff)
+
+
+    /*!\brief Return the version information (as a string)
+     *
+     * Returns a printable string containing the full library version number. This may
+     * contain additional text following the three digit version number, as to indicate
+     * release candidates, prerelease versions, etc.
+     *
+     */
+    const char *vpx_codec_version_str(void);
+
+
+    /*!\brief Return the version information (as a string)
+     *
+     * Returns a printable "extra string". This is the component of the string returned
+     * by vpx_codec_version_str() following the three digit version number.
+     *
+     */
+    const char *vpx_codec_version_extra_str(void);
+
+
+    /*!\brief Return the build configuration
+     *
+     * Returns a printable string containing an encoded version of the build
+     * configuration. This may be useful to vpx support.
+     *
+     */
+    const char *vpx_codec_build_config(void);
+
+
+    /*!\brief Return the name for a given interface
+     *
+     * Returns a human readable string for name of the given codec interface.
+     *
+     * \param[in]    iface     Interface pointer
+     *
+     */
+    const char *vpx_codec_iface_name(vpx_codec_iface_t *iface);
+
+
+    /*!\brief Convert error number to printable string
+     *
+     * Returns a human readable string for the last error returned by the
+     * algorithm. The returned error will be one line and will not contain
+     * any newline characters.
+     *
+     *
+     * \param[in]    err     Error number.
+     *
+     */
+    const char *vpx_codec_err_to_string(vpx_codec_err_t  err);
+
+
+    /*!\brief Retrieve error synopsis for codec context
+     *
+     * Returns a human readable string for the last error returned by the
+     * algorithm. The returned error will be one line and will not contain
+     * any newline characters.
+     *
+     *
+     * \param[in]    ctx     Pointer to this instance's context.
+     *
+     */
+    const char *vpx_codec_error(vpx_codec_ctx_t  *ctx);
+
+
+    /*!\brief Retrieve detailed error information for codec context
+     *
+     * Returns a human readable string providing detailed information about
+     * the last error.
+     *
+     * \param[in]    ctx     Pointer to this instance's context.
+     *
+     * \retval NULL
+     *     No detailed information is available.
+     */
+    const char *vpx_codec_error_detail(vpx_codec_ctx_t  *ctx);
+
+
+    /* REQUIRED FUNCTIONS
+     *
+     * The following functions are required to be implemented for all codecs.
+     * They represent the base case functionality expected of all codecs.
+     */
+
+    /*!\brief Destroy a codec instance
+     *
+     * Destroys a codec context, freeing any associated memory buffers.
+     *
+     * \param[in] ctx   Pointer to this instance's context
+     *
+     * \retval #VPX_CODEC_OK
+     *     The codec algorithm initialized.
+     * \retval #VPX_CODEC_MEM_ERROR
+     *     Memory allocation failed.
+     */
+    vpx_codec_err_t vpx_codec_destroy(vpx_codec_ctx_t *ctx);
+
+
+    /*!\brief Get the capabilities of an algorithm.
+     *
+     * Retrieves the capabilities bitfield from the algorithm's interface.
+     *
+     * \param[in] iface   Pointer to the algorithm interface
+     *
+     */
+    vpx_codec_caps_t vpx_codec_get_caps(vpx_codec_iface_t *iface);
+
+
+    /*!\brief Control algorithm
+     *
+     * This function is used to exchange algorithm specific data with the codec
+     * instance. This can be used to implement features specific to a particular
+     * algorithm.
+     *
+     * This wrapper function dispatches the request to the helper function
+     * associated with the given ctrl_id. It tries to call this function
+     * transparently, but will return #VPX_CODEC_ERROR if the request could not
+     * be dispatched.
+     *
+     * Note that this function should not be used directly. Call the
+     * #vpx_codec_control wrapper macro instead.
+     *
+     * \param[in]     ctx              Pointer to this instance's context
+     * \param[in]     ctrl_id          Algorithm specific control identifier
+     *
+     * \retval #VPX_CODEC_OK
+     *     The control request was processed.
+     * \retval #VPX_CODEC_ERROR
+     *     The control request was not processed.
+     * \retval #VPX_CODEC_INVALID_PARAM
+     *     The data was not valid.
+     */
+    vpx_codec_err_t vpx_codec_control_(vpx_codec_ctx_t  *ctx,
+                                       int               ctrl_id,
+                                       ...);
+#if defined(VPX_DISABLE_CTRL_TYPECHECKS) && VPX_DISABLE_CTRL_TYPECHECKS
+#    define vpx_codec_control(ctx,id,data) vpx_codec_control_(ctx,id,data)
+#    define VPX_CTRL_USE_TYPE(id, typ)
+#    define VPX_CTRL_USE_TYPE_DEPRECATED(id, typ)
+#    define VPX_CTRL_VOID(id, typ)
+
+#else
+    /*!\brief vpx_codec_control wrapper macro
+     *
+     * This macro allows for type safe conversions across the variadic parameter
+     * to vpx_codec_control_().
+     *
+     * \internal
+     * It works by dispatching the call to the control function through a wrapper
+     * function named with the id parameter.
+     */
+#    define vpx_codec_control(ctx,id,data) vpx_codec_control_##id(ctx,id,data)\
+    /**<\hideinitializer*/
+
+
+    /*!\brief vpx_codec_control type definition macro
+     *
+     * This macro allows for type safe conversions across the variadic parameter
+     * to vpx_codec_control_(). It defines the type of the argument for a given
+     * control identifier.
+     *
+     * \internal
+     * It defines a static function with
+     * the correctly typed arguments as a wrapper to the type-unsafe internal
+     * function.
+     */
+#    define VPX_CTRL_USE_TYPE(id, typ) \
+    static vpx_codec_err_t \
+    vpx_codec_control_##id(vpx_codec_ctx_t*, int, typ) UNUSED;\
+    \
+    static vpx_codec_err_t \
+    vpx_codec_control_##id(vpx_codec_ctx_t  *ctx, int ctrl_id, typ data) {\
+        return vpx_codec_control_(ctx, ctrl_id, data);\
+    } /**<\hideinitializer*/
+
+
+    /*!\brief vpx_codec_control deprecated type definition macro
+     *
+     * Like #VPX_CTRL_USE_TYPE, but indicates that the specified control is
+     * deprecated and should not be used. Consult the documentation for your
+     * codec for more information.
+     *
+     * \internal
+     * It defines a static function with the correctly typed arguments as a
+     * wrapper to the type-unsafe internal function.
+     */
+#    define VPX_CTRL_USE_TYPE_DEPRECATED(id, typ) \
+    DECLSPEC_DEPRECATED static vpx_codec_err_t \
+    vpx_codec_control_##id(vpx_codec_ctx_t*, int, typ) DEPRECATED UNUSED;\
+    \
+    DECLSPEC_DEPRECATED static vpx_codec_err_t \
+    vpx_codec_control_##id(vpx_codec_ctx_t  *ctx, int ctrl_id, typ data) {\
+        return vpx_codec_control_(ctx, ctrl_id, data);\
+    } /**<\hideinitializer*/
+
+
+    /*!\brief vpx_codec_control void type definition macro
+     *
+     * This macro allows for type safe conversions across the variadic parameter
+     * to vpx_codec_control_(). It indicates that a given control identifier takes
+     * no argument.
+     *
+     * \internal
+     * It defines a static function without a data argument as a wrapper to the
+     * type-unsafe internal function.
+     */
+#    define VPX_CTRL_VOID(id) \
+    static vpx_codec_err_t \
+    vpx_codec_control_##id(vpx_codec_ctx_t*, int) UNUSED;\
+    \
+    static vpx_codec_err_t \
+    vpx_codec_control_##id(vpx_codec_ctx_t  *ctx, int ctrl_id) {\
+        return vpx_codec_control_(ctx, ctrl_id);\
+    } /**<\hideinitializer*/
+
+
+#endif
+
+
+    /*!\defgroup cap_xma External Memory Allocation Functions
+     *
+     * The following functions are required to be implemented for all codecs
+     * that advertise the VPX_CODEC_CAP_XMA capability. Calling these functions
+     * for codecs that don't advertise this capability will result in an error
+     * code being returned, usually VPX_CODEC_INCAPABLE
+     * @{
+     */
+
+
+    /*!\brief Memory Map Entry
+     *
+     * This structure is used to contain the properties of a memory segment. It
+     * is populated by the codec in the request phase, and by the calling
+     * application once the requested allocation has been performed.
+     */
+    typedef struct vpx_codec_mmap
+    {
+        /*
+         * The following members are set by the codec when requesting a segment
+         */
+        unsigned int   id;     /**< identifier for the segment's contents */
+        unsigned long  sz;     /**< size of the segment, in bytes */
+        unsigned int   align;  /**< required alignment of the segment, in bytes */
+        unsigned int   flags;  /**< bitfield containing segment properties */
+#define VPX_CODEC_MEM_ZERO     0x1  /**< Segment must be zeroed by allocation */
+#define VPX_CODEC_MEM_WRONLY   0x2  /**< Segment need not be readable */
+#define VPX_CODEC_MEM_FAST     0x4  /**< Place in fast memory, if available */
+
+        /* The following members are to be filled in by the allocation function */
+        void          *base;   /**< pointer to the allocated segment */
+        void (*dtor)(struct vpx_codec_mmap *map);         /**< destructor to call */
+        void          *priv;   /**< allocator private storage */
+    } vpx_codec_mmap_t; /**< alias for struct vpx_codec_mmap */
+
+
+    /*!\brief Iterate over the list of segments to allocate.
+     *
+     * Iterates over a list of the segments to allocate. The iterator storage
+     * should be initialized to NULL to start the iteration. Iteration is complete
+     * when this function returns VPX_CODEC_LIST_END. The amount of memory needed to
+     * allocate is dependent upon the size of the encoded stream. In cases where the
+     * stream is not available at allocation time, a fixed size must be requested.
+     * The codec will not be able to operate on streams larger than the size used at
+     * allocation time.
+     *
+     * \param[in]      ctx     Pointer to this instance's context.
+     * \param[out]     mmap    Pointer to the memory map entry to populate.
+     * \param[in,out]  iter    Iterator storage, initialized to NULL
+     *
+     * \retval #VPX_CODEC_OK
+     *     The memory map entry was populated.
+     * \retval #VPX_CODEC_ERROR
+     *     Codec does not support XMA mode.
+     * \retval #VPX_CODEC_MEM_ERROR
+     *     Unable to determine segment size from stream info.
+     */
+    vpx_codec_err_t vpx_codec_get_mem_map(vpx_codec_ctx_t                *ctx,
+                                          vpx_codec_mmap_t               *mmap,
+                                          vpx_codec_iter_t               *iter);
+
+
+    /*!\brief Identify allocated segments to codec instance
+     *
+     * Stores a list of allocated segments in the codec. Segments \ref MUST be
+     * passed in the order they are read from vpx_codec_get_mem_map(), but may be
+     * passed in groups of any size. Segments \ref MUST be set only once. The
+     * allocation function \ref MUST ensure that the vpx_codec_mmap_t::base member
+     * is non-NULL. If the segment requires cleanup handling (e.g., calling free()
+     * or close()) then the vpx_codec_mmap_t::dtor member \ref MUST be populated.
+     *
+     * \param[in]      ctx     Pointer to this instance's context.
+     * \param[in]      mmaps   Pointer to the first memory map entry in the list.
+     * \param[in]      num_maps  Number of entries being set at this time
+     *
+     * \retval #VPX_CODEC_OK
+     *     The segment was stored in the codec context.
+     * \retval #VPX_CODEC_INCAPABLE
+     *     Codec does not support XMA mode.
+     * \retval #VPX_CODEC_MEM_ERROR
+     *     Segment base address was not set, or segment was already stored.
+
+     */
+    vpx_codec_err_t  vpx_codec_set_mem_map(vpx_codec_ctx_t   *ctx,
+                                           vpx_codec_mmap_t  *mmaps,
+                                           unsigned int       num_maps);
+
+    /*!@} - end defgroup cap_xma*/
+    /*!@} - end defgroup codec*/
+
+
+#endif
+#ifdef __cplusplus
+}
+#endif
diff --git a/vpx/vpx_codec.mk b/vpx/vpx_codec.mk
new file mode 100644 (file)
index 0000000..427fd0f
--- /dev/null
@@ -0,0 +1,25 @@
+##
+##  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+##
+##  Use of this source code is governed by a BSD-style license
+##  that can be found in the LICENSE file in the root of the source
+##  tree. An additional intellectual property rights grant can be found
+##  in the file PATENTS.  All contributing project authors may
+##  be found in the AUTHORS file in the root of the source tree.
+##
+
+
+API_EXPORTS += exports
+
+API_SRCS-yes                += src/vpx_decoder.c
+API_SRCS-yes                += vpx_decoder.h
+API_SRCS-yes                += src/vpx_encoder.c
+API_SRCS-yes                += vpx_encoder.h
+API_SRCS-yes                += internal/vpx_codec_internal.h
+API_SRCS-yes                += src/vpx_codec.c
+API_SRCS-yes                += src/vpx_image.c
+API_SRCS-yes                += vpx_codec.h
+API_SRCS-yes                += vpx_codec.mk
+API_SRCS-yes                += vpx_codec_impl_bottom.h
+API_SRCS-yes                += vpx_codec_impl_top.h
+API_SRCS-yes                += vpx_image.h
diff --git a/vpx/vpx_codec_impl_bottom.h b/vpx/vpx_codec_impl_bottom.h
new file mode 100644 (file)
index 0000000..6eb79a8
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file is to be included at the bottom of the header files defining the
+ * interface to individual codecs and contains matching blocks to those defined
+ * in vpx_codec_impl_top.h
+ */
+#ifdef __cplusplus
+}
+#endif
diff --git a/vpx/vpx_codec_impl_top.h b/vpx/vpx_codec_impl_top.h
new file mode 100644 (file)
index 0000000..c9b8cfa
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file is to be included at the top of the header files defining the
+ * interface to individual codecs and contains various workarounds common
+ * to all codec implementations.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
diff --git a/vpx/vpx_decoder.h b/vpx/vpx_decoder.h
new file mode 100644 (file)
index 0000000..7992cc4
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*!\defgroup decoder Decoder Algorithm Interface
+ * \ingroup codec
+ * This abstraction allows applications using this decoder to easily support
+ * multiple video formats with minimal code duplication. This section describes
+ * the interface common to all decoders.
+ * @{
+ */
+
+/*!\file
+ * \brief Describes the decoder algorithm interface to applications.
+ *
+ * This file describes the interface between an application and a
+ * video decoder algorithm.
+ *
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef VPX_DECODER_H
+#define VPX_DECODER_H
+#include "vpx_codec.h"
+
+    /*!\brief Current ABI version number
+     *
+     * \internal
+     * If this file is altered in any way that changes the ABI, this value
+     * must be bumped.  Examples include, but are not limited to, changing
+     * types, removing or reassigning enums, adding/removing/rearranging
+     * fields to structures
+     */
+#define VPX_DECODER_ABI_VERSION (2 + VPX_CODEC_ABI_VERSION) /**<\hideinitializer*/
+
+    /*! \brief Decoder capabilities bitfield
+     *
+     *  Each decoder advertises the capabilities it supports as part of its
+     *  ::vpx_codec_iface_t interface structure. Capabilities are extra interfaces
+     *  or functionality, and are not required to be supported by a decoder.
+     *
+     *  The available flags are specified by VPX_CODEC_CAP_* defines.
+     */
+#define VPX_CODEC_CAP_PUT_SLICE  0x10000 /**< Will issue put_slice callbacks */
+#define VPX_CODEC_CAP_PUT_FRAME  0x20000 /**< Will issue put_frame callbacks */
+#define VPX_CODEC_CAP_POSTPROC   0x40000 /**< Can postprocess decoded frame */
+#define VPX_CODEC_CAP_ERROR_CONCEALMENT   0x80000 /**< Can conceal errors due to
+                                                       packet loss */
+#define VPX_CODEC_CAP_INPUT_FRAGMENTS   0x100000 /**< Can receive encoded frames
+                                                    one fragment at a time */
+
+    /*! \brief Initialization-time Feature Enabling
+     *
+     *  Certain codec features must be known at initialization time, to allow for
+     *  proper memory allocation.
+     *
+     *  The available flags are specified by VPX_CODEC_USE_* defines.
+     */
+#define VPX_CODEC_USE_POSTPROC   0x10000 /**< Postprocess decoded frame */
+#define VPX_CODEC_USE_ERROR_CONCEALMENT 0x20000 /**< Conceal errors in decoded
+                                                     frames */
+#define VPX_CODEC_USE_INPUT_FRAGMENTS   0x40000 /**< The input frame should be
+                                                    passed to the decoder one
+                                                    fragment at a time */
+
+    /*!\brief Stream properties
+     *
+     * This structure is used to query or set properties of the decoded
+     * stream. Algorithms may extend this structure with data specific
+     * to their bitstream by setting the sz member appropriately.
+     */
+    typedef struct vpx_codec_stream_info
+    {
+        unsigned int sz;     /**< Size of this structure */
+        unsigned int w;      /**< Width (or 0 for unknown/default) */
+        unsigned int h;      /**< Height (or 0 for unknown/default) */
+        unsigned int is_kf;  /**< Current frame is a keyframe */
+    } vpx_codec_stream_info_t;
+
+    /* REQUIRED FUNCTIONS
+     *
+     * The following functions are required to be implemented for all decoders.
+     * They represent the base case functionality expected of all decoders.
+     */
+
+
+    /*!\brief Initialization Configurations
+     *
+     * This structure is used to pass init time configuration options to the
+     * decoder.
+     */
+    typedef struct vpx_codec_dec_cfg
+    {
+        unsigned int threads; /**< Maximum number of threads to use, default 1 */
+        unsigned int w;      /**< Width */
+        unsigned int h;      /**< Height */
+    } vpx_codec_dec_cfg_t; /**< alias for struct vpx_codec_dec_cfg */
+
+
+    /*!\brief Initialize a decoder instance
+     *
+     * Initializes a decoder context using the given interface. Applications
+     * should call the vpx_codec_dec_init convenience macro instead of this
+     * function directly, to ensure that the ABI version number parameter
+     * is properly initialized.
+     *
+     * In XMA mode (activated by setting VPX_CODEC_USE_XMA in the flags
+     * parameter), the storage pointed to by the cfg parameter must be
+     * kept readable and stable until all memory maps have been set.
+     *
+     * \param[in]    ctx     Pointer to this instance's context.
+     * \param[in]    iface   Pointer to the algorithm interface to use.
+     * \param[in]    cfg     Configuration to use, if known. May be NULL.
+     * \param[in]    flags   Bitfield of VPX_CODEC_USE_* flags
+     * \param[in]    ver     ABI version number. Must be set to
+     *                       VPX_DECODER_ABI_VERSION
+     * \retval #VPX_CODEC_OK
+     *     The decoder algorithm initialized.
+     * \retval #VPX_CODEC_MEM_ERROR
+     *     Memory allocation failed.
+     */
+    vpx_codec_err_t vpx_codec_dec_init_ver(vpx_codec_ctx_t      *ctx,
+                                           vpx_codec_iface_t    *iface,
+                                           vpx_codec_dec_cfg_t  *cfg,
+                                           vpx_codec_flags_t     flags,
+                                           int                   ver);
+
+    /*!\brief Convenience macro for vpx_codec_dec_init_ver()
+     *
+     * Ensures the ABI version parameter is properly set.
+     */
+#define vpx_codec_dec_init(ctx, iface, cfg, flags) \
+    vpx_codec_dec_init_ver(ctx, iface, cfg, flags, VPX_DECODER_ABI_VERSION)
+
+
+    /*!\brief Parse stream info from a buffer
+     *
+     * Performs high level parsing of the bitstream. Construction of a decoder
+     * context is not necessary. Can be used to determine if the bitstream is
+     * of the proper format, and to extract information from the stream.
+     *
+     * \param[in]      iface   Pointer to the algorithm interface
+     * \param[in]      data    Pointer to a block of data to parse
+     * \param[in]      data_sz Size of the data buffer
+     * \param[in,out]  si      Pointer to stream info to update. The size member
+     *                         \ref MUST be properly initialized, but \ref MAY be
+     *                         clobbered by the algorithm. This parameter \ref MAY
+     *                         be NULL.
+     *
+     * \retval #VPX_CODEC_OK
+     *     Bitstream is parsable and stream information updated
+     */
+    vpx_codec_err_t vpx_codec_peek_stream_info(vpx_codec_iface_t       *iface,
+            const uint8_t           *data,
+            unsigned int             data_sz,
+            vpx_codec_stream_info_t *si);
+
+
+    /*!\brief Return information about the current stream.
+     *
+     * Returns information about the stream that has been parsed during decoding.
+     *
+     * \param[in]      ctx     Pointer to this instance's context
+     * \param[in,out]  si      Pointer to stream info to update. The size member
+     *                         \ref MUST be properly initialized, but \ref MAY be
+     *                         clobbered by the algorithm. This parameter \ref MAY
+     *                         be NULL.
+     *
+     * \retval #VPX_CODEC_OK
+     *     Bitstream is parsable and stream information updated
+     */
+    vpx_codec_err_t vpx_codec_get_stream_info(vpx_codec_ctx_t         *ctx,
+            vpx_codec_stream_info_t *si);
+
+
+    /*!\brief Decode data
+     *
+     * Processes a buffer of coded data. If the processing results in a new
+     * decoded frame becoming available, PUT_SLICE and PUT_FRAME events may be
+     * generated, as appropriate. Encoded data \ref MUST be passed in DTS (decode
+     * time stamp) order. Frames produced will always be in PTS (presentation
+     * time stamp) order.
+     * If the decoder is configured with VPX_CODEC_USE_INPUT_FRAGMENTS enabled,
+     * data and data_sz can contain a fragment of the encoded frame. Fragment
+     * \#n must contain at least partition \#n, but can also contain subsequent
+     * partitions (\#n+1 - \#n+i), and if so, fragments \#n+1, .., \#n+i must
+     * be empty. When no more data is available, this function should be called
+     * with NULL as data and 0 as data_sz. The memory passed to this function
+     * must be available until the frame has been decoded.
+     *
+     * \param[in] ctx          Pointer to this instance's context
+     * \param[in] data         Pointer to this block of new coded data. If
+     *                         NULL, a VPX_CODEC_CB_PUT_FRAME event is posted
+     *                         for the previously decoded frame.
+     * \param[in] data_sz      Size of the coded data, in bytes.
+     * \param[in] user_priv    Application specific data to associate with
+     *                         this frame.
+     * \param[in] deadline     Soft deadline the decoder should attempt to meet,
+     *                         in us. Set to zero for unlimited.
+     *
+     * \return Returns #VPX_CODEC_OK if the coded data was processed completely
+     *         and future pictures can be decoded without error. Otherwise,
+     *         see the descriptions of the other error codes in ::vpx_codec_err_t
+     *         for recoverability capabilities.
+     */
+    vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t    *ctx,
+                                     const uint8_t        *data,
+                                     unsigned int            data_sz,
+                                     void               *user_priv,
+                                     long                deadline);
+
+
+    /*!\brief Decoded frames iterator
+     *
+     * Iterates over a list of the frames available for display. The iterator
+     * storage should be initialized to NULL to start the iteration. Iteration is
+     * complete when this function returns NULL.
+     *
+     * The list of available frames becomes valid upon completion of the
+     * vpx_codec_decode call, and remains valid until the next call to vpx_codec_decode.
+     *
+     * \param[in]     ctx      Pointer to this instance's context
+     * \param[in,out] iter     Iterator storage, initialized to NULL
+     *
+     * \return Returns a pointer to an image, if one is ready for display. Frames
+     *         produced will always be in PTS (presentation time stamp) order.
+     */
+    vpx_image_t *vpx_codec_get_frame(vpx_codec_ctx_t  *ctx,
+                                     vpx_codec_iter_t *iter);
+
+
+    /*!\defgroup cap_put_frame Frame-Based Decoding Functions
+     *
+     * The following functions are required to be implemented for all decoders
+     * that advertise the VPX_CODEC_CAP_PUT_FRAME capability. Calling these functions
+     * for codecs that don't advertise this capability will result in an error
+     * code being returned, usually VPX_CODEC_ERROR
+     * @{
+     */
+
+    /*!\brief put frame callback prototype
+     *
+     * This callback is invoked by the decoder to notify the application of
+     * the availability of decoded image data.
+     */
+    typedef void (*vpx_codec_put_frame_cb_fn_t)(void        *user_priv,
+            const vpx_image_t *img);
+
+
+    /*!\brief Register for notification of frame completion.
+     *
+     * Registers a given function to be called when a decoded frame is
+     * available.
+     *
+     * \param[in] ctx          Pointer to this instance's context
+     * \param[in] cb           Pointer to the callback function
+     * \param[in] user_priv    User's private data
+     *
+     * \retval #VPX_CODEC_OK
+     *     Callback successfully registered.
+     * \retval #VPX_CODEC_ERROR
+     *     Decoder context not initialized, or algorithm not capable of
+     *     posting slice completion.
+     */
+    vpx_codec_err_t vpx_codec_register_put_frame_cb(vpx_codec_ctx_t             *ctx,
+            vpx_codec_put_frame_cb_fn_t  cb,
+            void                        *user_priv);
+
+
+    /*!@} - end defgroup cap_put_frame */
+
+    /*!\defgroup cap_put_slice Slice-Based Decoding Functions
+     *
+     * The following functions are required to be implemented for all decoders
+     * that advertise the VPX_CODEC_CAP_PUT_SLICE capability. Calling these functions
+     * for codecs that don't advertise this capability will result in an error
+     * code being returned, usually VPX_CODEC_ERROR
+     * @{
+     */
+
+    /*!\brief put slice callback prototype
+     *
+     * This callback is invoked by the decoder to notify the application of
+     * the availability of partially decoded image data. The
+     */
+    typedef void (*vpx_codec_put_slice_cb_fn_t)(void         *user_priv,
+            const vpx_image_t      *img,
+            const vpx_image_rect_t *valid,
+            const vpx_image_rect_t *update);
+
+
+    /*!\brief Register for notification of slice completion.
+     *
+     * Registers a given function to be called when a decoded slice is
+     * available.
+     *
+     * \param[in] ctx          Pointer to this instance's context
+     * \param[in] cb           Pointer to the callback function
+     * \param[in] user_priv    User's private data
+     *
+     * \retval #VPX_CODEC_OK
+     *     Callback successfully registered.
+     * \retval #VPX_CODEC_ERROR
+     *     Decoder context not initialized, or algorithm not capable of
+     *     posting slice completion.
+     */
+    vpx_codec_err_t vpx_codec_register_put_slice_cb(vpx_codec_ctx_t             *ctx,
+            vpx_codec_put_slice_cb_fn_t  cb,
+            void                        *user_priv);
+
+
+    /*!@} - end defgroup cap_put_slice*/
+
+    /*!@} - end defgroup decoder*/
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/vpx/vpx_encoder.h b/vpx/vpx_encoder.h
new file mode 100644 (file)
index 0000000..239036e
--- /dev/null
@@ -0,0 +1,931 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*!\defgroup encoder Encoder Algorithm Interface
+ * \ingroup codec
+ * This abstraction allows applications using this encoder to easily support
+ * multiple video formats with minimal code duplication. This section describes
+ * the interface common to all encoders.
+ * @{
+ */
+
+/*!\file
+ * \brief Describes the encoder algorithm interface to applications.
+ *
+ * This file describes the interface between an application and a
+ * video encoder algorithm.
+ *
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef VPX_ENCODER_H
+#define VPX_ENCODER_H
+#include "vpx_codec.h"
+
+/*! Temporal Scalability: Maximum length of the sequence defining frame
+ * layer membership
+ */
+#define VPX_TS_MAX_PERIODICITY 16
+
+/*! Temporal Scalability: Maximum number of coding layers */
+#define VPX_TS_MAX_LAYERS       5
+
+/*!\deprecated Use #VPX_TS_MAX_PERIODICITY instead. */
+#define MAX_PERIODICITY VPX_TS_MAX_PERIODICITY
+
+/*!\deprecated Use #VPX_TS_MAX_LAYERS instead. */
+#define MAX_LAYERS      VPX_TS_MAX_LAYERS
+
+    /*!\brief Current ABI version number
+     *
+     * \internal
+     * If this file is altered in any way that changes the ABI, this value
+     * must be bumped.  Examples include, but are not limited to, changing
+     * types, removing or reassigning enums, adding/removing/rearranging
+     * fields to structures
+     */
+#define VPX_ENCODER_ABI_VERSION (3 + VPX_CODEC_ABI_VERSION) /**<\hideinitializer*/
+
+
+    /*! \brief Encoder capabilities bitfield
+     *
+     *  Each encoder advertises the capabilities it supports as part of its
+     *  ::vpx_codec_iface_t interface structure. Capabilities are extra
+     *  interfaces or functionality, and are not required to be supported
+     *  by an encoder.
+     *
+     *  The available flags are specified by VPX_CODEC_CAP_* defines.
+     */
+#define VPX_CODEC_CAP_PSNR  0x10000 /**< Can issue PSNR packets */
+
+    /*! Can output one partition at a time. Each partition is returned in its
+     *  own VPX_CODEC_CX_FRAME_PKT, with the FRAME_IS_FRAGMENT flag set for
+     *  every partition but the last. In this mode all frames are always
+     *  returned partition by partition.
+     */
+#define VPX_CODEC_CAP_OUTPUT_PARTITION  0x20000
+
+
+    /*! \brief Initialization-time Feature Enabling
+     *
+     *  Certain codec features must be known at initialization time, to allow
+     *  for proper memory allocation.
+     *
+     *  The available flags are specified by VPX_CODEC_USE_* defines.
+     */
+#define VPX_CODEC_USE_PSNR  0x10000 /**< Calculate PSNR on each frame */
+#define VPX_CODEC_USE_OUTPUT_PARTITION  0x20000 /**< Make the encoder output one
+                                                     partition at a time. */
+
+
+    /*!\brief Generic fixed size buffer structure
+     *
+     * This structure is able to hold a reference to any fixed size buffer.
+     */
+    typedef struct vpx_fixed_buf
+    {
+        void          *buf; /**< Pointer to the data */
+        size_t         sz;  /**< Length of the buffer, in chars */
+    } vpx_fixed_buf_t; /**< alias for struct vpx_fixed_buf */
+
+
+    /*!\brief Time Stamp Type
+     *
+     * An integer, which when multiplied by the stream's time base, provides
+     * the absolute time of a sample.
+     */
+    typedef int64_t vpx_codec_pts_t;
+
+
+    /*!\brief Compressed Frame Flags
+     *
+     * This type represents a bitfield containing information about a compressed
+     * frame that may be useful to an application. The most significant 16 bits
+     * can be used by an algorithm to provide additional detail, for example to
+     * support frame types that are codec specific (MPEG-1 D-frames for example)
+     */
+    typedef uint32_t vpx_codec_frame_flags_t;
+#define VPX_FRAME_IS_KEY       0x1 /**< frame is the start of a GOP */
+#define VPX_FRAME_IS_DROPPABLE 0x2 /**< frame can be dropped without affecting
+    the stream (no future frame depends on
+                this one) */
+#define VPX_FRAME_IS_INVISIBLE 0x4 /**< frame should be decoded but will not
+    be shown */
+#define VPX_FRAME_IS_FRAGMENT  0x8 /**< this is a fragment of the encoded
+    frame */
+
+    /*!\brief Error Resilient flags
+     *
+     * These flags define which error resilient features to enable in the
+     * encoder. The flags are specified through the
+     * vpx_codec_enc_cfg::g_error_resilient variable.
+     */
+    typedef uint32_t vpx_codec_er_flags_t;
+#define VPX_ERROR_RESILIENT_DEFAULT     0x1 /**< Improve resiliency against
+                                                 losses of whole frames */
+#define VPX_ERROR_RESILIENT_PARTITIONS  0x2 /**< The frame partitions are
+                                                 independently decodable by the
+                                                 bool decoder, meaning that
+                                                 partitions can be decoded even
+                                                 though earlier partitions have
+                                                 been lost. Note that intra
+                                                 predicition is still done over
+                                                 the partition boundary. */
+
+    /*!\brief Encoder output packet variants
+     *
+     * This enumeration lists the different kinds of data packets that can be
+     * returned by calls to vpx_codec_get_cx_data(). Algorithms \ref MAY
+     * extend this list to provide additional functionality.
+     */
+    enum vpx_codec_cx_pkt_kind
+    {
+        VPX_CODEC_CX_FRAME_PKT,    /**< Compressed video frame */
+        VPX_CODEC_STATS_PKT,       /**< Two-pass statistics for this frame */
+        VPX_CODEC_PSNR_PKT,        /**< PSNR statistics for this frame */
+        VPX_CODEC_CUSTOM_PKT = 256 /**< Algorithm extensions  */
+    };
+
+
+    /*!\brief Encoder output packet
+     *
+     * This structure contains the different kinds of output data the encoder
+     * may produce while compressing a frame.
+     */
+    typedef struct vpx_codec_cx_pkt
+    {
+        enum vpx_codec_cx_pkt_kind  kind; /**< packet variant */
+        union
+        {
+            struct
+            {
+                void                    *buf;      /**< compressed data buffer */
+                size_t                   sz;       /**< length of compressed data */
+                vpx_codec_pts_t          pts;      /**< time stamp to show frame
+                                                    (in timebase units) */
+                unsigned long            duration; /**< duration to show frame
+                                                    (in timebase units) */
+                vpx_codec_frame_flags_t  flags;    /**< flags for this frame */
+                int                      partition_id; /**< the partition id
+                                              defines the decoding order
+                                              of the partitions. Only
+                                              applicable when "output partition"
+                                              mode is enabled. First partition
+                                              has id 0.*/
+
+            } frame;  /**< data for compressed frame packet */
+            struct vpx_fixed_buf twopass_stats;  /**< data for two-pass packet */
+            struct vpx_psnr_pkt
+            {
+                unsigned int samples[4];  /**< Number of samples, total/y/u/v */
+                uint64_t     sse[4];      /**< sum squared error, total/y/u/v */
+                double       psnr[4];     /**< PSNR, total/y/u/v */
+            } psnr;                       /**< data for PSNR packet */
+            struct vpx_fixed_buf raw;     /**< data for arbitrary packets */
+
+            /* This packet size is fixed to allow codecs to extend this
+             * interface without having to manage storage for raw packets,
+             * i.e., if it's smaller than 128 bytes, you can store in the
+             * packet list directly.
+             */
+            char pad[128 - sizeof(enum vpx_codec_cx_pkt_kind)]; /**< fixed sz */
+        } data; /**< packet data */
+    } vpx_codec_cx_pkt_t; /**< alias for struct vpx_codec_cx_pkt */
+
+
+    /*!\brief Rational Number
+     *
+     * This structure holds a fractional value.
+     */
+    typedef struct vpx_rational
+    {
+        int num; /**< fraction numerator */
+        int den; /**< fraction denominator */
+    } vpx_rational_t; /**< alias for struct vpx_rational */
+
+
+    /*!\brief Multi-pass Encoding Pass */
+    enum vpx_enc_pass
+    {
+        VPX_RC_ONE_PASS,   /**< Single pass mode */
+        VPX_RC_FIRST_PASS, /**< First pass of multi-pass mode */
+        VPX_RC_LAST_PASS   /**< Final pass of multi-pass mode */
+    };
+
+
+    /*!\brief Rate control mode */
+    enum vpx_rc_mode
+    {
+        VPX_VBR, /**< Variable Bit Rate (VBR) mode */
+        VPX_CBR,  /**< Constant Bit Rate (CBR) mode */
+        VPX_CQ   /**< Constant Quality  (CQ)  mode */
+    };
+
+
+    /*!\brief Keyframe placement mode.
+     *
+     * This enumeration determines whether keyframes are placed automatically by
+     * the encoder or whether this behavior is disabled. Older releases of this
+     * SDK were implemented such that VPX_KF_FIXED meant keyframes were disabled.
+     * This name is confusing for this behavior, so the new symbols to be used
+     * are VPX_KF_AUTO and VPX_KF_DISABLED.
+     */
+    enum vpx_kf_mode
+    {
+        VPX_KF_FIXED, /**< deprecated, implies VPX_KF_DISABLED */
+        VPX_KF_AUTO,  /**< Encoder determines optimal placement automatically */
+        VPX_KF_DISABLED = 0 /**< Encoder does not place keyframes. */
+    };
+
+
+    /*!\brief Encoded Frame Flags
+     *
+     * This type indicates a bitfield to be passed to vpx_codec_encode(), defining
+     * per-frame boolean values. By convention, bits common to all codecs will be
+     * named VPX_EFLAG_*, and bits specific to an algorithm will be named
+     * /algo/_eflag_*. The lower order 16 bits are reserved for common use.
+     */
+    typedef long vpx_enc_frame_flags_t;
+#define VPX_EFLAG_FORCE_KF (1<<0)  /**< Force this frame to be a keyframe */
+
+
+    /*!\brief Encoder configuration structure
+     *
+     * This structure contains the encoder settings that have common representations
+     * across all codecs. This doesn't imply that all codecs support all features,
+     * however.
+     */
+    typedef struct vpx_codec_enc_cfg
+    {
+        /*
+         * generic settings (g)
+         */
+
+        /*!\brief Algorithm specific "usage" value
+         *
+         * Algorithms may define multiple values for usage, which may convey the
+         * intent of how the application intends to use the stream. If this value
+         * is non-zero, consult the documentation for the codec to determine its
+         * meaning.
+         */
+        unsigned int           g_usage;
+
+
+        /*!\brief Maximum number of threads to use
+         *
+         * For multi-threaded implementations, use no more than this number of
+         * threads. The codec may use fewer threads than allowed. The value
+         * 0 is equivalent to the value 1.
+         */
+        unsigned int           g_threads;
+
+
+        /*!\brief Bitstream profile to use
+         *
+         * Some codecs support a notion of multiple bitstream profiles. Typically
+         * this maps to a set of features that are turned on or off. Often the
+         * profile to use is determined by the features of the intended decoder.
+         * Consult the documentation for the codec to determine the valid values
+         * for this parameter, or set to zero for a sane default.
+         */
+        unsigned int           g_profile;  /**< profile of bitstream to use */
+
+
+
+        /*!\brief Width of the frame
+         *
+         * This value identifies the presentation resolution of the frame,
+         * in pixels. Note that the frames passed as input to the encoder must
+         * have this resolution. Frames will be presented by the decoder in this
+         * resolution, independent of any spatial resampling the encoder may do.
+         */
+        unsigned int           g_w;
+
+
+        /*!\brief Height of the frame
+         *
+         * This value identifies the presentation resolution of the frame,
+         * in pixels. Note that the frames passed as input to the encoder must
+         * have this resolution. Frames will be presented by the decoder in this
+         * resolution, independent of any spatial resampling the encoder may do.
+         */
+        unsigned int           g_h;
+
+
+        /*!\brief Stream timebase units
+         *
+         * Indicates the smallest interval of time, in seconds, used by the stream.
+         * For fixed frame rate material, or variable frame rate material where
+         * frames are timed at a multiple of a given clock (ex: video capture),
+         * the \ref RECOMMENDED method is to set the timebase to the reciprocal
+         * of the frame rate (ex: 1001/30000 for 29.970 Hz NTSC). This allows the
+         * pts to correspond to the frame number, which can be handy. For
+         * re-encoding video from containers with absolute time timestamps, the
+         * \ref RECOMMENDED method is to set the timebase to that of the parent
+         * container or multimedia framework (ex: 1/1000 for ms, as in FLV).
+         */
+        struct vpx_rational    g_timebase;
+
+
+        /*!\brief Enable error resilient modes.
+         *
+         * The error resilient bitfield indicates to the encoder which features
+         * it should enable to take measures for streaming over lossy or noisy
+         * links.
+         */
+        vpx_codec_er_flags_t   g_error_resilient;
+
+
+        /*!\brief Multi-pass Encoding Mode
+         *
+         * This value should be set to the current phase for multi-pass encoding.
+         * For single pass, set to #VPX_RC_ONE_PASS.
+         */
+        enum vpx_enc_pass      g_pass;
+
+
+        /*!\brief Allow lagged encoding
+         *
+         * If set, this value allows the encoder to consume a number of input
+         * frames before producing output frames. This allows the encoder to
+         * base decisions for the current frame on future frames. This does
+         * increase the latency of the encoding pipeline, so it is not appropriate
+         * in all situations (ex: realtime encoding).
+         *
+         * Note that this is a maximum value -- the encoder may produce frames
+         * sooner than the given limit. Set this value to 0 to disable this
+         * feature.
+         */
+        unsigned int           g_lag_in_frames;
+
+
+        /*
+         * rate control settings (rc)
+         */
+
+        /*!\brief Temporal resampling configuration, if supported by the codec.
+         *
+         * Temporal resampling allows the codec to "drop" frames as a strategy to
+         * meet its target data rate. This can cause temporal discontinuities in
+         * the encoded video, which may appear as stuttering during playback. This
+         * trade-off is often acceptable, but for many applications is not. It can
+         * be disabled in these cases.
+         *
+         * Note that not all codecs support this feature. All vpx VPx codecs do.
+         * For other codecs, consult the documentation for that algorithm.
+         *
+         * This threshold is described as a percentage of the target data buffer.
+         * When the data buffer falls below this percentage of fullness, a
+         * dropped frame is indicated. Set the threshold to zero (0) to disable
+         * this feature.
+         */
+        unsigned int           rc_dropframe_thresh;
+
+
+        /*!\brief Enable/disable spatial resampling, if supported by the codec.
+         *
+         * Spatial resampling allows the codec to compress a lower resolution
+         * version of the frame, which is then upscaled by the encoder to the
+         * correct presentation resolution. This increases visual quality at
+         * low data rates, at the expense of CPU time on the encoder/decoder.
+         */
+        unsigned int           rc_resize_allowed;
+
+
+        /*!\brief Spatial resampling up watermark.
+         *
+         * This threshold is described as a percentage of the target data buffer.
+         * When the data buffer rises above this percentage of fullness, the
+         * encoder will step up to a higher resolution version of the frame.
+         */
+        unsigned int           rc_resize_up_thresh;
+
+
+        /*!\brief Spatial resampling down watermark.
+         *
+         * This threshold is described as a percentage of the target data buffer.
+         * When the data buffer falls below this percentage of fullness, the
+         * encoder will step down to a lower resolution version of the frame.
+         */
+        unsigned int           rc_resize_down_thresh;
+
+
+        /*!\brief Rate control algorithm to use.
+         *
+         * Indicates whether the end usage of this stream is to be streamed over
+         * a bandwidth constrained link, indicating that Constant Bit Rate (CBR)
+         * mode should be used, or whether it will be played back on a high
+         * bandwidth link, as from a local disk, where higher variations in
+         * bitrate are acceptable.
+         */
+        enum vpx_rc_mode       rc_end_usage;
+
+
+        /*!\brief Two-pass stats buffer.
+         *
+         * A buffer containing all of the stats packets produced in the first
+         * pass, concatenated.
+         */
+        struct vpx_fixed_buf   rc_twopass_stats_in;
+
+
+        /*!\brief Target data rate
+         *
+         * Target bandwidth to use for this stream, in kilobits per second.
+         */
+        unsigned int           rc_target_bitrate;
+
+
+        /*
+         * quantizer settings
+         */
+
+
+        /*!\brief Minimum (Best Quality) Quantizer
+         *
+         * The quantizer is the most direct control over the quality of the
+         * encoded image. The range of valid values for the quantizer is codec
+         * specific. Consult the documentation for the codec to determine the
+         * values to use. To determine the range programmatically, call
+         * vpx_codec_enc_config_default() with a usage value of 0.
+         */
+        unsigned int           rc_min_quantizer;
+
+
+        /*!\brief Maximum (Worst Quality) Quantizer
+         *
+         * The quantizer is the most direct control over the quality of the
+         * encoded image. The range of valid values for the quantizer is codec
+         * specific. Consult the documentation for the codec to determine the
+         * values to use. To determine the range programmatically, call
+         * vpx_codec_enc_config_default() with a usage value of 0.
+         */
+        unsigned int           rc_max_quantizer;
+
+
+        /*
+         * bitrate tolerance
+         */
+
+
+        /*!\brief Rate control adaptation undershoot control
+         *
+         * This value, expressed as a percentage of the target bitrate,
+         * controls the maximum allowed adaptation speed of the codec.
+         * This factor controls the maximum amount of bits that can
+         * be subtracted from the target bitrate in order to compensate
+         * for prior overshoot.
+         *
+         * Valid values in the range 0-1000.
+         */
+        unsigned int           rc_undershoot_pct;
+
+
+        /*!\brief Rate control adaptation overshoot control
+         *
+         * This value, expressed as a percentage of the target bitrate,
+         * controls the maximum allowed adaptation speed of the codec.
+         * This factor controls the maximum amount of bits that can
+         * be added to the target bitrate in order to compensate for
+         * prior undershoot.
+         *
+         * Valid values in the range 0-1000.
+         */
+        unsigned int           rc_overshoot_pct;
+
+
+        /*
+         * decoder buffer model parameters
+         */
+
+
+        /*!\brief Decoder Buffer Size
+         *
+         * This value indicates the amount of data that may be buffered by the
+         * decoding application. Note that this value is expressed in units of
+         * time (milliseconds). For example, a value of 5000 indicates that the
+         * client will buffer (at least) 5000ms worth of encoded data. Use the
+         * target bitrate (#rc_target_bitrate) to convert to bits/bytes, if
+         * necessary.
+         */
+        unsigned int           rc_buf_sz;
+
+
+        /*!\brief Decoder Buffer Initial Size
+         *
+         * This value indicates the amount of data that will be buffered by the
+         * decoding application prior to beginning playback. This value is
+         * expressed in units of time (milliseconds). Use the target bitrate
+         * (#rc_target_bitrate) to convert to bits/bytes, if necessary.
+         */
+        unsigned int           rc_buf_initial_sz;
+
+
+        /*!\brief Decoder Buffer Optimal Size
+         *
+         * This value indicates the amount of data that the encoder should try
+         * to maintain in the decoder's buffer. This value is expressed in units
+         * of time (milliseconds). Use the target bitrate (#rc_target_bitrate)
+         * to convert to bits/bytes, if necessary.
+         */
+        unsigned int           rc_buf_optimal_sz;
+
+
+        /*
+         * 2 pass rate control parameters
+         */
+
+
+        /*!\brief Two-pass mode CBR/VBR bias
+         *
+         * Bias, expressed on a scale of 0 to 100, for determining target size
+         * for the current frame. The value 0 indicates the optimal CBR mode
+         * value should be used. The value 100 indicates the optimal VBR mode
+         * value should be used. Values in between indicate which way the
+         * encoder should "lean."
+         */
+        unsigned int           rc_2pass_vbr_bias_pct;       /**< RC mode bias between CBR and VBR(0-100: 0->CBR, 100->VBR)   */
+
+
+        /*!\brief Two-pass mode per-GOP minimum bitrate
+         *
+         * This value, expressed as a percentage of the target bitrate, indicates
+         * the minimum bitrate to be used for a single GOP (aka "section")
+         */
+        unsigned int           rc_2pass_vbr_minsection_pct;
+
+
+        /*!\brief Two-pass mode per-GOP maximum bitrate
+         *
+         * This value, expressed as a percentage of the target bitrate, indicates
+         * the maximum bitrate to be used for a single GOP (aka "section")
+         */
+        unsigned int           rc_2pass_vbr_maxsection_pct;
+
+
+        /*
+         * keyframing settings (kf)
+         */
+
+        /*!\brief Keyframe placement mode
+         *
+         * This value indicates whether the encoder should place keyframes at a
+         * fixed interval, or determine the optimal placement automatically
+         * (as governed by the #kf_min_dist and #kf_max_dist parameters)
+         */
+        enum vpx_kf_mode       kf_mode;
+
+
+        /*!\brief Keyframe minimum interval
+         *
+         * This value, expressed as a number of frames, prevents the encoder from
+         * placing a keyframe nearer than kf_min_dist to the previous keyframe. At
+         * least kf_min_dist frames non-keyframes will be coded before the next
+         * keyframe. Set kf_min_dist equal to kf_max_dist for a fixed interval.
+         */
+        unsigned int           kf_min_dist;
+
+
+        /*!\brief Keyframe maximum interval
+         *
+         * This value, expressed as a number of frames, forces the encoder to code
+         * a keyframe if one has not been coded in the last kf_max_dist frames.
+         * A value of 0 implies all frames will be keyframes. Set kf_min_dist
+         * equal to kf_max_dist for a fixed interval.
+         */
+        unsigned int           kf_max_dist;
+
+        /*
+         * Temporal scalability settings (ts)
+         */
+
+        /*!\brief Number of coding layers
+         *
+         * This value specifies the number of coding layers to be used.
+         */
+        unsigned int           ts_number_layers;
+
+        /*!\brief Target bitrate for each layer
+         *
+         * These values specify the target coding bitrate for each coding layer.
+         */
+        unsigned int           ts_target_bitrate[VPX_TS_MAX_LAYERS];
+
+        /*!\brief Frame rate decimation factor for each layer
+         *
+         * These values specify the frame rate decimation factors to apply
+         * to each layer.
+         */
+        unsigned int           ts_rate_decimator[VPX_TS_MAX_LAYERS];
+
+        /*!\brief Length of the sequence defining frame layer membership
+         *
+         * This value specifies the length of the sequence that defines the
+         * membership of frames to layers. For example, if ts_periodicity=8 then
+         * frames are assigned to coding layers with a repeated sequence of
+         * length 8.
+         */
+        unsigned int           ts_periodicity;
+
+        /*!\brief Template defining the membership of frames to coding layers
+         *
+         * This array defines the membership of frames to coding layers. For a
+         * 2-layer encoding that assigns even numbered frames to one layer (0)
+         * and odd numbered frames to a second layer (1) with ts_periodicity=8,
+         * then ts_layer_id = (0,1,0,1,0,1,0,1).
+         */
+        unsigned int           ts_layer_id[VPX_TS_MAX_PERIODICITY];
+    } vpx_codec_enc_cfg_t; /**< alias for struct vpx_codec_enc_cfg */
+
+
+    /*!\brief Initialize an encoder instance
+     *
+     * Initializes a encoder context using the given interface. Applications
+     * should call the vpx_codec_enc_init convenience macro instead of this
+     * function directly, to ensure that the ABI version number parameter
+     * is properly initialized.
+     *
+     * In XMA mode (activated by setting VPX_CODEC_USE_XMA in the flags
+     * parameter), the storage pointed to by the cfg parameter must be
+     * kept readable and stable until all memory maps have been set.
+     *
+     * \param[in]    ctx     Pointer to this instance's context.
+     * \param[in]    iface   Pointer to the algorithm interface to use.
+     * \param[in]    cfg     Configuration to use, if known. May be NULL.
+     * \param[in]    flags   Bitfield of VPX_CODEC_USE_* flags
+     * \param[in]    ver     ABI version number. Must be set to
+     *                       VPX_ENCODER_ABI_VERSION
+     * \retval #VPX_CODEC_OK
+     *     The decoder algorithm initialized.
+     * \retval #VPX_CODEC_MEM_ERROR
+     *     Memory allocation failed.
+     */
+    vpx_codec_err_t vpx_codec_enc_init_ver(vpx_codec_ctx_t      *ctx,
+                                           vpx_codec_iface_t    *iface,
+                                           vpx_codec_enc_cfg_t  *cfg,
+                                           vpx_codec_flags_t     flags,
+                                           int                   ver);
+
+
+    /*!\brief Convenience macro for vpx_codec_enc_init_ver()
+     *
+     * Ensures the ABI version parameter is properly set.
+     */
+#define vpx_codec_enc_init(ctx, iface, cfg, flags) \
+    vpx_codec_enc_init_ver(ctx, iface, cfg, flags, VPX_ENCODER_ABI_VERSION)
+
+
+    /*!\brief Initialize multi-encoder instance
+     *
+     * Initializes multi-encoder context using the given interface.
+     * Applications should call the vpx_codec_enc_init_multi convenience macro
+     * instead of this function directly, to ensure that the ABI version number
+     * parameter is properly initialized.
+     *
+     * In XMA mode (activated by setting VPX_CODEC_USE_XMA in the flags
+     * parameter), the storage pointed to by the cfg parameter must be
+     * kept readable and stable until all memory maps have been set.
+     *
+     * \param[in]    ctx     Pointer to this instance's context.
+     * \param[in]    iface   Pointer to the algorithm interface to use.
+     * \param[in]    cfg     Configuration to use, if known. May be NULL.
+     * \param[in]    num_enc Total number of encoders.
+     * \param[in]    flags   Bitfield of VPX_CODEC_USE_* flags
+     * \param[in]    dsf     Pointer to down-sampling factors.
+     * \param[in]    ver     ABI version number. Must be set to
+     *                       VPX_ENCODER_ABI_VERSION
+     * \retval #VPX_CODEC_OK
+     *     The decoder algorithm initialized.
+     * \retval #VPX_CODEC_MEM_ERROR
+     *     Memory allocation failed.
+     */
+    vpx_codec_err_t vpx_codec_enc_init_multi_ver(vpx_codec_ctx_t      *ctx,
+                                                 vpx_codec_iface_t    *iface,
+                                                 vpx_codec_enc_cfg_t  *cfg,
+                                                 int                   num_enc,
+                                                 vpx_codec_flags_t     flags,
+                                                 vpx_rational_t       *dsf,
+                                                 int                   ver);
+
+
+    /*!\brief Convenience macro for vpx_codec_enc_init_multi_ver()
+     *
+     * Ensures the ABI version parameter is properly set.
+     */
+#define vpx_codec_enc_init_multi(ctx, iface, cfg, num_enc, flags, dsf) \
+    vpx_codec_enc_init_multi_ver(ctx, iface, cfg, num_enc, flags, dsf, \
+                                 VPX_ENCODER_ABI_VERSION)
+
+
+    /*!\brief Get a default configuration
+     *
+     * Initializes a encoder configuration structure with default values. Supports
+     * the notion of "usages" so that an algorithm may offer different default
+     * settings depending on the user's intended goal. This function \ref SHOULD
+     * be called by all applications to initialize the configuration structure
+     * before specializing the configuration with application specific values.
+     *
+     * \param[in]    iface   Pointer to the algorithm interface to use.
+     * \param[out]   cfg     Configuration buffer to populate
+     * \param[in]    usage   End usage. Set to 0 or use codec specific values.
+     *
+     * \retval #VPX_CODEC_OK
+     *     The configuration was populated.
+     * \retval #VPX_CODEC_INCAPABLE
+     *     Interface is not an encoder interface.
+     * \retval #VPX_CODEC_INVALID_PARAM
+     *     A parameter was NULL, or the usage value was not recognized.
+     */
+    vpx_codec_err_t  vpx_codec_enc_config_default(vpx_codec_iface_t    *iface,
+            vpx_codec_enc_cfg_t  *cfg,
+            unsigned int          usage);
+
+
+    /*!\brief Set or change configuration
+     *
+     * Reconfigures an encoder instance according to the given configuration.
+     *
+     * \param[in]    ctx     Pointer to this instance's context
+     * \param[in]    cfg     Configuration buffer to use
+     *
+     * \retval #VPX_CODEC_OK
+     *     The configuration was populated.
+     * \retval #VPX_CODEC_INCAPABLE
+     *     Interface is not an encoder interface.
+     * \retval #VPX_CODEC_INVALID_PARAM
+     *     A parameter was NULL, or the usage value was not recognized.
+     */
+    vpx_codec_err_t  vpx_codec_enc_config_set(vpx_codec_ctx_t            *ctx,
+            const vpx_codec_enc_cfg_t  *cfg);
+
+
+    /*!\brief Get global stream headers
+     *
+     * Retrieves a stream level global header packet, if supported by the codec.
+     *
+     * \param[in]    ctx     Pointer to this instance's context
+     *
+     * \retval NULL
+     *     Encoder does not support global header
+     * \retval Non-NULL
+     *     Pointer to buffer containing global header packet
+     */
+    vpx_fixed_buf_t *vpx_codec_get_global_headers(vpx_codec_ctx_t   *ctx);
+
+
+#define VPX_DL_REALTIME     (1)        /**< deadline parameter analogous to
+    *   VPx REALTIME mode. */
+#define VPX_DL_GOOD_QUALITY (1000000)  /**< deadline parameter analogous to
+    *   VPx GOOD QUALITY mode. */
+#define VPX_DL_BEST_QUALITY (0)        /**< deadline parameter analogous to
+    *   VPx BEST QUALITY mode. */
+    /*!\brief Encode a frame
+     *
+     * Encodes a video frame at the given "presentation time." The presentation
+     * time stamp (PTS) \ref MUST be strictly increasing.
+     *
+     * The encoder supports the notion of a soft real-time deadline. Given a
+     * non-zero value to the deadline parameter, the encoder will make a "best
+     * effort" guarantee to  return before the given time slice expires. It is
+     * implicit that limiting the available time to encode will degrade the
+     * output quality. The encoder can be given an unlimited time to produce the
+     * best possible frame by specifying a deadline of '0'. This deadline
+     * supercedes the VPx notion of "best quality, good quality, realtime".
+     * Applications that wish to map these former settings to the new deadline
+     * based system can use the symbols #VPX_DL_REALTIME, #VPX_DL_GOOD_QUALITY,
+     * and #VPX_DL_BEST_QUALITY.
+     *
+     * When the last frame has been passed to the encoder, this function should
+     * continue to be called, with the img parameter set to NULL. This will
+     * signal the end-of-stream condition to the encoder and allow it to encode
+     * any held buffers. Encoding is complete when vpx_codec_encode() is called
+     * and vpx_codec_get_cx_data() returns no data.
+     *
+     * \param[in]    ctx       Pointer to this instance's context
+     * \param[in]    img       Image data to encode, NULL to flush.
+     * \param[in]    pts       Presentation time stamp, in timebase units.
+     * \param[in]    duration  Duration to show frame, in timebase units.
+     * \param[in]    flags     Flags to use for encoding this frame.
+     * \param[in]    deadline  Time to spend encoding, in microseconds. (0=infinite)
+     *
+     * \retval #VPX_CODEC_OK
+     *     The configuration was populated.
+     * \retval #VPX_CODEC_INCAPABLE
+     *     Interface is not an encoder interface.
+     * \retval #VPX_CODEC_INVALID_PARAM
+     *     A parameter was NULL, the image format is unsupported, etc.
+     */
+    vpx_codec_err_t  vpx_codec_encode(vpx_codec_ctx_t            *ctx,
+                                      const vpx_image_t          *img,
+                                      vpx_codec_pts_t             pts,
+                                      unsigned long               duration,
+                                      vpx_enc_frame_flags_t       flags,
+                                      unsigned long               deadline);
+
+    /*!\brief Set compressed data output buffer
+     *
+     * Sets the buffer that the codec should output the compressed data
+     * into. This call effectively sets the buffer pointer returned in the
+     * next VPX_CODEC_CX_FRAME_PKT packet. Subsequent packets will be
+     * appended into this buffer. The buffer is preserved across frames,
+     * so applications must periodically call this function after flushing
+     * the accumulated compressed data to disk or to the network to reset
+     * the pointer to the buffer's head.
+     *
+     * `pad_before` bytes will be skipped before writing the compressed
+     * data, and `pad_after` bytes will be appended to the packet. The size
+     * of the packet will be the sum of the size of the actual compressed
+     * data, pad_before, and pad_after. The padding bytes will be preserved
+     * (not overwritten).
+     *
+     * Note that calling this function does not guarantee that the returned
+     * compressed data will be placed into the specified buffer. In the
+     * event that the encoded data will not fit into the buffer provided,
+     * the returned packet \ref MAY point to an internal buffer, as it would
+     * if this call were never used. In this event, the output packet will
+     * NOT have any padding, and the application must free space and copy it
+     * to the proper place. This is of particular note in configurations
+     * that may output multiple packets for a single encoded frame (e.g., lagged
+     * encoding) or if the application does not reset the buffer periodically.
+     *
+     * Applications may restore the default behavior of the codec providing
+     * the compressed data buffer by calling this function with a NULL
+     * buffer.
+     *
+     * Applications \ref MUSTNOT call this function during iteration of
+     * vpx_codec_get_cx_data().
+     *
+     * \param[in]    ctx         Pointer to this instance's context
+     * \param[in]    buf         Buffer to store compressed data into
+     * \param[in]    pad_before  Bytes to skip before writing compressed data
+     * \param[in]    pad_after   Bytes to skip after writing compressed data
+     *
+     * \retval #VPX_CODEC_OK
+     *     The buffer was set successfully.
+     * \retval #VPX_CODEC_INVALID_PARAM
+     *     A parameter was NULL, the image format is unsupported, etc.
+     */
+    vpx_codec_err_t vpx_codec_set_cx_data_buf(vpx_codec_ctx_t       *ctx,
+            const vpx_fixed_buf_t *buf,
+            unsigned int           pad_before,
+            unsigned int           pad_after);
+
+
+    /*!\brief Encoded data iterator
+     *
+     * Iterates over a list of data packets to be passed from the encoder to the
+     * application. The different kinds of packets available are enumerated in
+     * #vpx_codec_cx_pkt_kind.
+     *
+     * #VPX_CODEC_CX_FRAME_PKT packets should be passed to the application's
+     * muxer. Multiple compressed frames may be in the list.
+     * #VPX_CODEC_STATS_PKT packets should be appended to a global buffer.
+     *
+     * The application \ref MUST silently ignore any packet kinds that it does
+     * not recognize or support.
+     *
+     * The data buffers returned from this function are only guaranteed to be
+     * valid until the application makes another call to any vpx_codec_* function.
+     *
+     * \param[in]     ctx      Pointer to this instance's context
+     * \param[in,out] iter     Iterator storage, initialized to NULL
+     *
+     * \return Returns a pointer to an output data packet (compressed frame data,
+     *         two-pass statistics, etc.) or NULL to signal end-of-list.
+     *
+     */
+    const vpx_codec_cx_pkt_t *vpx_codec_get_cx_data(vpx_codec_ctx_t   *ctx,
+            vpx_codec_iter_t  *iter);
+
+
+    /*!\brief Get Preview Frame
+     *
+     * Returns an image that can be used as a preview. Shows the image as it would
+     * exist at the decompressor. The application \ref MUST NOT write into this
+     * image buffer.
+     *
+     * \param[in]     ctx      Pointer to this instance's context
+     *
+     * \return Returns a pointer to a preview image, or NULL if no image is
+     *         available.
+     *
+     */
+    const vpx_image_t *vpx_codec_get_preview_frame(vpx_codec_ctx_t   *ctx);
+
+
+    /*!@} - end defgroup encoder*/
+
+#endif
+#ifdef __cplusplus
+}
+#endif
diff --git a/vpx/vpx_image.h b/vpx/vpx_image.h
new file mode 100644 (file)
index 0000000..3e42447
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*!\file
+ * \brief Describes the vpx image descriptor and associated operations
+ *
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef VPX_IMAGE_H
+#define VPX_IMAGE_H
+
+    /*!\brief Current ABI version number
+     *
+     * \internal
+     * If this file is altered in any way that changes the ABI, this value
+     * must be bumped.  Examples include, but are not limited to, changing
+     * types, removing or reassigning enums, adding/removing/rearranging
+     * fields to structures
+     */
+#define VPX_IMAGE_ABI_VERSION (1) /**<\hideinitializer*/
+
+
+#define VPX_IMG_FMT_PLANAR     0x100  /**< Image is a planar format */
+#define VPX_IMG_FMT_UV_FLIP    0x200  /**< V plane precedes U plane in memory */
+#define VPX_IMG_FMT_HAS_ALPHA  0x400  /**< Image has an alpha channel component */
+
+
+    /*!\brief List of supported image formats */
+    typedef enum vpx_img_fmt {
+        VPX_IMG_FMT_NONE,
+        VPX_IMG_FMT_RGB24,   /**< 24 bit per pixel packed RGB */
+        VPX_IMG_FMT_RGB32,   /**< 32 bit per pixel packed 0RGB */
+        VPX_IMG_FMT_RGB565,  /**< 16 bit per pixel, 565 */
+        VPX_IMG_FMT_RGB555,  /**< 16 bit per pixel, 555 */
+        VPX_IMG_FMT_UYVY,    /**< UYVY packed YUV */
+        VPX_IMG_FMT_YUY2,    /**< YUYV packed YUV */
+        VPX_IMG_FMT_YVYU,    /**< YVYU packed YUV */
+        VPX_IMG_FMT_BGR24,   /**< 24 bit per pixel packed BGR */
+        VPX_IMG_FMT_RGB32_LE, /**< 32 bit packed BGR0 */
+        VPX_IMG_FMT_ARGB,     /**< 32 bit packed ARGB, alpha=255 */
+        VPX_IMG_FMT_ARGB_LE,  /**< 32 bit packed BGRA, alpha=255 */
+        VPX_IMG_FMT_RGB565_LE,  /**< 16 bit per pixel, gggbbbbb rrrrrggg */
+        VPX_IMG_FMT_RGB555_LE,  /**< 16 bit per pixel, gggbbbbb 0rrrrrgg */
+        VPX_IMG_FMT_YV12    = VPX_IMG_FMT_PLANAR | VPX_IMG_FMT_UV_FLIP | 1, /**< planar YVU */
+        VPX_IMG_FMT_I420    = VPX_IMG_FMT_PLANAR | 2,
+        VPX_IMG_FMT_VPXYV12 = VPX_IMG_FMT_PLANAR | VPX_IMG_FMT_UV_FLIP | 3, /** < planar 4:2:0 format with vpx color space */
+        VPX_IMG_FMT_VPXI420 = VPX_IMG_FMT_PLANAR | 4   /** < planar 4:2:0 format with vpx color space */
+    }
+    vpx_img_fmt_t; /**< alias for enum vpx_img_fmt */
+
+#if !defined(VPX_CODEC_DISABLE_COMPAT) || !VPX_CODEC_DISABLE_COMPAT
+#define IMG_FMT_PLANAR         VPX_IMG_FMT_PLANAR     /**< \deprecated Use #VPX_IMG_FMT_PLANAR */
+#define IMG_FMT_UV_FLIP        VPX_IMG_FMT_UV_FLIP    /**< \deprecated Use #VPX_IMG_FMT_UV_FLIP */
+#define IMG_FMT_HAS_ALPHA      VPX_IMG_FMT_HAS_ALPHA  /**< \deprecated Use #VPX_IMG_FMT_HAS_ALPHA */
+
+    /*!\brief Deprecated list of supported image formats
+     * \deprecated New code should use #vpx_img_fmt
+     */
+#define img_fmt   vpx_img_fmt
+    /*!\brief alias for enum img_fmt.
+     * \deprecated New code should use #vpx_img_fmt_t
+     */
+#define img_fmt_t vpx_img_fmt_t
+
+#define IMG_FMT_NONE       VPX_IMG_FMT_NONE       /**< \deprecated Use #VPX_IMG_FMT_NONE */
+#define IMG_FMT_RGB24      VPX_IMG_FMT_RGB24      /**< \deprecated Use #VPX_IMG_FMT_RGB24 */
+#define IMG_FMT_RGB32      VPX_IMG_FMT_RGB32      /**< \deprecated Use #VPX_IMG_FMT_RGB32 */
+#define IMG_FMT_RGB565     VPX_IMG_FMT_RGB565     /**< \deprecated Use #VPX_IMG_FMT_RGB565 */
+#define IMG_FMT_RGB555     VPX_IMG_FMT_RGB555     /**< \deprecated Use #VPX_IMG_FMT_RGB555 */
+#define IMG_FMT_UYVY       VPX_IMG_FMT_UYVY       /**< \deprecated Use #VPX_IMG_FMT_UYVY */
+#define IMG_FMT_YUY2       VPX_IMG_FMT_YUY2       /**< \deprecated Use #VPX_IMG_FMT_YUY2 */
+#define IMG_FMT_YVYU       VPX_IMG_FMT_YVYU       /**< \deprecated Use #VPX_IMG_FMT_YVYU */
+#define IMG_FMT_BGR24      VPX_IMG_FMT_BGR24      /**< \deprecated Use #VPX_IMG_FMT_BGR24 */
+#define IMG_FMT_RGB32_LE   VPX_IMG_FMT_RGB32_LE   /**< \deprecated Use #VPX_IMG_FMT_RGB32_LE */
+#define IMG_FMT_ARGB       VPX_IMG_FMT_ARGB       /**< \deprecated Use #VPX_IMG_FMT_ARGB */
+#define IMG_FMT_ARGB_LE    VPX_IMG_FMT_ARGB_LE    /**< \deprecated Use #VPX_IMG_FMT_ARGB_LE */
+#define IMG_FMT_RGB565_LE  VPX_IMG_FMT_RGB565_LE  /**< \deprecated Use #VPX_IMG_FMT_RGB565_LE */
+#define IMG_FMT_RGB555_LE  VPX_IMG_FMT_RGB555_LE  /**< \deprecated Use #VPX_IMG_FMT_RGB555_LE */
+#define IMG_FMT_YV12       VPX_IMG_FMT_YV12       /**< \deprecated Use #VPX_IMG_FMT_YV12 */
+#define IMG_FMT_I420       VPX_IMG_FMT_I420       /**< \deprecated Use #VPX_IMG_FMT_I420 */
+#define IMG_FMT_VPXYV12    VPX_IMG_FMT_VPXYV12    /**< \deprecated Use #VPX_IMG_FMT_VPXYV12 */
+#define IMG_FMT_VPXI420    VPX_IMG_FMT_VPXI420    /**< \deprecated Use #VPX_IMG_FMT_VPXI420 */
+#endif /* VPX_CODEC_DISABLE_COMPAT */
+
+    /**\brief Image Descriptor */
+    typedef struct vpx_image
+    {
+        vpx_img_fmt_t fmt; /**< Image Format */
+
+        /* Image storage dimensions */
+        unsigned int  w;   /**< Stored image width */
+        unsigned int  h;   /**< Stored image height */
+
+        /* Image display dimensions */
+        unsigned int  d_w;   /**< Displayed image width */
+        unsigned int  d_h;   /**< Displayed image height */
+
+        /* Chroma subsampling info */
+        unsigned int  x_chroma_shift;   /**< subsampling order, X */
+        unsigned int  y_chroma_shift;   /**< subsampling order, Y */
+
+        /* Image data pointers. */
+#define VPX_PLANE_PACKED 0   /**< To be used for all packed formats */
+#define VPX_PLANE_Y      0   /**< Y (Luminance) plane */
+#define VPX_PLANE_U      1   /**< U (Chroma) plane */
+#define VPX_PLANE_V      2   /**< V (Chroma) plane */
+#define VPX_PLANE_ALPHA  3   /**< A (Transparency) plane */
+#if !defined(VPX_CODEC_DISABLE_COMPAT) || !VPX_CODEC_DISABLE_COMPAT
+#define PLANE_PACKED     VPX_PLANE_PACKED
+#define PLANE_Y          VPX_PLANE_Y
+#define PLANE_U          VPX_PLANE_U
+#define PLANE_V          VPX_PLANE_V
+#define PLANE_ALPHA      VPX_PLANE_ALPHA
+#endif
+        unsigned char *planes[4];  /**< pointer to the top left pixel for each plane */
+        int      stride[4];  /**< stride between rows for each plane */
+
+        int     bps; /**< bits per sample (for packed formats) */
+
+        /* The following member may be set by the application to associate data
+         * with this image.
+         */
+        void    *user_priv; /**< may be set by the application to associate data
+                         *   with this image. */
+
+        /* The following members should be treated as private. */
+        unsigned char *img_data;       /**< private */
+        int      img_data_owner; /**< private */
+        int      self_allocd;    /**< private */
+    } vpx_image_t; /**< alias for struct vpx_image */
+
+    /**\brief Representation of a rectangle on a surface */
+    typedef struct vpx_image_rect
+    {
+        unsigned int x; /**< leftmost column */
+        unsigned int y; /**< topmost row */
+        unsigned int w; /**< width */
+        unsigned int h; /**< height */
+    } vpx_image_rect_t; /**< alias for struct vpx_image_rect */
+
+    /*!\brief Open a descriptor, allocating storage for the underlying image
+     *
+     * Returns a descriptor for storing an image of the given format. The
+     * storage for the descriptor is allocated on the heap.
+     *
+     * \param[in]    img       Pointer to storage for descriptor. If this parameter
+     *                         is NULL, the storage for the descriptor will be
+     *                         allocated on the heap.
+     * \param[in]    fmt       Format for the image
+     * \param[in]    d_w       Width of the image
+     * \param[in]    d_h       Height of the image
+     * \param[in]    align     Alignment, in bytes, of the image buffer and
+     *                         each row in the image(stride).
+     *
+     * \return Returns a pointer to the initialized image descriptor. If the img
+     *         parameter is non-null, the value of the img parameter will be
+     *         returned.
+     */
+    vpx_image_t *vpx_img_alloc(vpx_image_t  *img,
+                               vpx_img_fmt_t fmt,
+                               unsigned int d_w,
+                               unsigned int d_h,
+                               unsigned int align);
+
+    /*!\brief Open a descriptor, using existing storage for the underlying image
+     *
+     * Returns a descriptor for storing an image of the given format. The
+     * storage for descriptor has been allocated elsewhere, and a descriptor is
+     * desired to "wrap" that storage.
+     *
+     * \param[in]    img       Pointer to storage for descriptor. If this parameter
+     *                         is NULL, the storage for the descriptor will be
+     *                         allocated on the heap.
+     * \param[in]    fmt       Format for the image
+     * \param[in]    d_w       Width of the image
+     * \param[in]    d_h       Height of the image
+     * \param[in]    align     Alignment, in bytes, of each row in the image.
+     * \param[in]    img_data  Storage to use for the image
+     *
+     * \return Returns a pointer to the initialized image descriptor. If the img
+     *         parameter is non-null, the value of the img parameter will be
+     *         returned.
+     */
+    vpx_image_t *vpx_img_wrap(vpx_image_t  *img,
+                              vpx_img_fmt_t fmt,
+                              unsigned int d_w,
+                              unsigned int d_h,
+                              unsigned int align,
+                              unsigned char      *img_data);
+
+
+    /*!\brief Set the rectangle identifying the displayed portion of the image
+     *
+     * Updates the displayed rectangle (aka viewport) on the image surface to
+     * match the specified coordinates and size.
+     *
+     * \param[in]    img       Image descriptor
+     * \param[in]    x         leftmost column
+     * \param[in]    y         topmost row
+     * \param[in]    w         width
+     * \param[in]    h         height
+     *
+     * \return 0 if the requested rectangle is valid, nonzero otherwise.
+     */
+    int vpx_img_set_rect(vpx_image_t  *img,
+                         unsigned int  x,
+                         unsigned int  y,
+                         unsigned int  w,
+                         unsigned int  h);
+
+
+    /*!\brief Flip the image vertically (top for bottom)
+     *
+     * Adjusts the image descriptor's pointers and strides to make the image
+     * be referenced upside-down.
+     *
+     * \param[in]    img       Image descriptor
+     */
+    void vpx_img_flip(vpx_image_t *img);
+
+    /*!\brief Close an image descriptor
+     *
+     * Frees all allocated storage associated with an image descriptor.
+     *
+     * \param[in]    img       Image descriptor
+     */
+    void vpx_img_free(vpx_image_t *img);
+
+#endif
+#ifdef __cplusplus
+}
+#endif
diff --git a/vpx/vpx_integer.h b/vpx/vpx_integer.h
new file mode 100644 (file)
index 0000000..218bca7
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef VPX_INTEGER_H
+#define VPX_INTEGER_H
+
+/* get ptrdiff_t, size_t, wchar_t, NULL */
+#include <stddef.h>
+
+#if (defined(_MSC_VER) && (_MSC_VER < 1600)) || defined(VPX_EMULATE_INTTYPES)
+typedef signed char  int8_t;
+typedef signed short int16_t;
+typedef signed int   int32_t;
+
+typedef unsigned char  uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int   uint32_t;
+
+#if (defined(_MSC_VER) && (_MSC_VER < 1600))
+typedef signed __int64   int64_t;
+typedef unsigned __int64 uint64_t;
+#endif
+
+#ifndef _UINTPTR_T_DEFINED
+typedef size_t uintptr_t;
+#endif
+
+#else
+
+/* Most platforms have the C99 standard integer types. */
+
+#if defined(__cplusplus) && !defined(__STDC_FORMAT_MACROS)
+#define __STDC_FORMAT_MACROS
+#endif
+#include <stdint.h>
+
+#endif
+
+/* VS2010 defines stdint.h, but not inttypes.h */
+#if defined(_MSC_VER)
+#define PRId64 "I64d"
+#else
+#include <inttypes.h>
+#endif
+
+#endif
diff --git a/vpx_mem/include/vpx_mem_intrnl.h b/vpx_mem/include/vpx_mem_intrnl.h
new file mode 100644 (file)
index 0000000..63c6b77
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __VPX_MEM_INTRNL_H__
+#define __VPX_MEM_INTRNL_H__
+#include "vpx_config.h"
+
+#ifndef CONFIG_MEM_MANAGER
+# if defined(VXWORKS)
+#  define CONFIG_MEM_MANAGER  1 /*include heap manager functionality,*/
+/*default: enabled on vxworks*/
+# else
+#  define CONFIG_MEM_MANAGER  0 /*include heap manager functionality*/
+# endif
+#endif /*CONFIG_MEM_MANAGER*/
+
+#ifndef CONFIG_MEM_TRACKER
+# define CONFIG_MEM_TRACKER     1 /*include xvpx_* calls in the lib*/
+#endif
+
+#ifndef CONFIG_MEM_CHECKS
+# define CONFIG_MEM_CHECKS      0 /*include some basic safety checks in
+vpx_memcpy, _memset, and _memmove*/
+#endif
+
+#ifndef USE_GLOBAL_FUNCTION_POINTERS
+# define USE_GLOBAL_FUNCTION_POINTERS   0  /*use function pointers instead of compiled functions.*/
+#endif
+
+#if CONFIG_MEM_TRACKER
+# include "vpx_mem_tracker.h"
+# if VPX_MEM_TRACKER_VERSION_CHIEF != 2 || VPX_MEM_TRACKER_VERSION_MAJOR != 5
+#  error "vpx_mem requires memory tracker version 2.5 to track memory usage"
+# endif
+#endif
+
+#define ADDRESS_STORAGE_SIZE      sizeof(size_t)
+
+#ifndef DEFAULT_ALIGNMENT
+# if defined(VXWORKS)
+#  define DEFAULT_ALIGNMENT        32        /*default addr alignment to use in
+                                               calls to vpx_* functions other
+                                               than vpx_memalign*/
+# else
+#  define DEFAULT_ALIGNMENT        1
+# endif
+#endif
+
+#if DEFAULT_ALIGNMENT < 1
+# error "DEFAULT_ALIGNMENT must be >= 1!"
+#endif
+
+#if CONFIG_MEM_TRACKER
+# define TRY_BOUNDS_CHECK         1        /*when set to 1 pads each allocation,
+                                             integrity can be checked using
+                                             vpx_memory_tracker_check_integrity
+                                             or on free by defining*/
+/*TRY_BOUNDS_CHECK_ON_FREE*/
+#else
+# define TRY_BOUNDS_CHECK         0
+#endif /*CONFIG_MEM_TRACKER*/
+
+#if TRY_BOUNDS_CHECK
+# define TRY_BOUNDS_CHECK_ON_FREE 0          /*checks mem integrity on every
+                                               free, very expensive*/
+# define BOUNDS_CHECK_VALUE       0xdeadbeef /*value stored before/after ea.
+                                               mem addr for bounds checking*/
+# define BOUNDS_CHECK_PAD_SIZE    32         /*size of the padding before and
+                                               after ea allocation to be filled
+                                               with BOUNDS_CHECK_VALUE.
+                                               this should be a multiple of 4*/
+#else
+# define BOUNDS_CHECK_VALUE       0
+# define BOUNDS_CHECK_PAD_SIZE    0
+#endif /*TRY_BOUNDS_CHECK*/
+
+#ifndef REMOVE_PRINTFS
+# define REMOVE_PRINTFS 0
+#endif
+
+/* Should probably use a vpx_mem logger function. */
+#if REMOVE_PRINTFS
+# define _P(x)
+#else
+# define _P(x) x
+#endif
+
+/*returns an addr aligned to the byte boundary specified by align*/
+#define align_addr(addr,align) (void*)(((size_t)(addr) + ((align) - 1)) & (size_t)-(align))
+
+#endif /*__VPX_MEM_INTRNL_H__*/
diff --git a/vpx_mem/include/vpx_mem_tracker.h b/vpx_mem/include/vpx_mem_tracker.h
new file mode 100644 (file)
index 0000000..ef2b29b
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __VPX_MEM_TRACKER_H__
+#define __VPX_MEM_TRACKER_H__
+
+/* vpx_mem_tracker version info */
+#define vpx_mem_tracker_version "2.5.1.1"
+
+#define VPX_MEM_TRACKER_VERSION_CHIEF 2
+#define VPX_MEM_TRACKER_VERSION_MAJOR 5
+#define VPX_MEM_TRACKER_VERSION_MINOR 1
+#define VPX_MEM_TRACKER_VERSION_PATCH 1
+/* END - vpx_mem_tracker version info */
+
+#include <stdarg.h>
+
+struct mem_block
+{
+    size_t addr;
+    unsigned int size,
+             line;
+    char *file;
+    struct mem_block *prev,
+            * next;
+
+    int padded; // This mem_block has padding for integrity checks.
+    // As of right now, this should only be 0 if
+    // using vpx_mem_alloc to allocate cache memory.
+    // 2005-01-11 tjf
+};
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+    /*
+        vpx_memory_tracker_init(int padding_size, int pad_value)
+          padding_size - the size of the padding before and after each mem addr.
+                         Values > 0 indicate that integrity checks can be performed
+                         by inspecting these areas.
+          pad_value - the initial value within the padding area before and after
+                      each mem addr.
+
+        Initializes the memory tracker interface. Should be called before any
+        other calls to the memory tracker.
+    */
+    int vpx_memory_tracker_init(int padding_size, int pad_value);
+
+    /*
+        vpx_memory_tracker_destroy()
+        Deinitializes the memory tracker interface
+    */
+    void vpx_memory_tracker_destroy();
+
+    /*
+        vpx_memory_tracker_add(size_t addr, unsigned int size,
+                             char * file, unsigned int line)
+          addr - memory address to be added to list
+          size - size of addr
+          file - the file addr was referenced from
+          line - the line in file addr was referenced from
+        Adds memory address addr, it's size, file and line it came from
+        to the memory tracker allocation table
+    */
+    void vpx_memory_tracker_add(size_t addr, unsigned int size,
+                                char *file, unsigned int line,
+                                int padded);
+
+    /*
+        vpx_memory_tracker_add(size_t addr, unsigned int size, char * file, unsigned int line)
+          addr - memory address to be added to be removed
+          padded - if 0, disables bounds checking on this memory block even if bounds
+          checking is enabled. (for example, when allocating cache memory, we still want
+          to check for memory leaks, but we do not waste cache space for bounds check padding)
+        Removes the specified address from the memory tracker's allocation
+        table
+        Return:
+          0: on success
+          -1: if memory allocation table's mutex could not be locked
+          -2: if the addr was not found in the list
+    */
+    int vpx_memory_tracker_remove(size_t addr);
+
+    /*
+        vpx_memory_tracker_find(unsigned int addr)
+          addr - address to be found in the memory tracker's
+                 allocation table
+        Return:
+            If found, pointer to the memory block that matches addr
+            NULL otherwise
+    */
+    struct mem_block *vpx_memory_tracker_find(size_t addr);
+
+    /*
+        vpx_memory_tracker_dump()
+        Dumps the current contents of the memory
+        tracker allocation table
+    */
+    void vpx_memory_tracker_dump();
+
+    /*
+        vpx_memory_tracker_check_integrity()
+        If a padding_size was provided to vpx_memory_tracker_init()
+        This function will verify that the region before and after each
+        memory address contains the specified pad_value. Should the check
+        fail, the filename and line of the check will be printed out.
+    */
+    void vpx_memory_tracker_check_integrity(char *file, unsigned int line);
+
+    /*
+        vpx_memory_tracker_set_log_type
+          type - value representing the logging type to use
+          option - type specific option. This will be interpreted differently
+                   based on the type.
+        Sets the logging type for the memory tracker.
+        Values currently supported:
+          0: if option is NULL, log to stderr, otherwise interpret option as a
+             filename and attempt to open it.
+          1: Use output_debug_string (WIN32 only), option ignored
+        Return:
+          0: on success
+          -1: if the logging type could not be set, because the value was invalid
+              or because a file could not be opened
+    */
+    int vpx_memory_tracker_set_log_type(int type, char *option);
+
+    /*
+        vpx_memory_tracker_set_log_func
+          userdata - ptr to be passed to the supplied logfunc, can be NULL
+          logfunc - the logging function to be used to output data from
+                    vpx_memory_track_dump/check_integrity
+        Sets a logging function to be used by the memory tracker.
+        Return:
+          0: on success
+          -1: if the logging type could not be set because logfunc was NULL
+    */
+    int vpx_memory_tracker_set_log_func(void *userdata,
+                                        void(*logfunc)(void *userdata,
+                                                const char *fmt, va_list args));
+
+    /* Wrappers to standard library functions. */
+    typedef void*(* mem_track_malloc_func)(size_t);
+    typedef void*(* mem_track_calloc_func)(size_t, size_t);
+    typedef void*(* mem_track_realloc_func)(void *, size_t);
+    typedef void (* mem_track_free_func)(void *);
+    typedef void*(* mem_track_memcpy_func)(void *, const void *, size_t);
+    typedef void*(* mem_track_memset_func)(void *, int, size_t);
+    typedef void*(* mem_track_memmove_func)(void *, const void *, size_t);
+
+    /*
+        vpx_memory_tracker_set_functions
+
+        Sets the function pointers for the standard library functions.
+
+        Return:
+          0: on success
+          -1: if the use global function pointers is not set.
+    */
+    int vpx_memory_tracker_set_functions(mem_track_malloc_func g_malloc_l
+                                         , mem_track_calloc_func g_calloc_l
+                                         , mem_track_realloc_func g_realloc_l
+                                         , mem_track_free_func g_free_l
+                                         , mem_track_memcpy_func g_memcpy_l
+                                         , mem_track_memset_func g_memset_l
+                                         , mem_track_memmove_func g_memmove_l);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif //__VPX_MEM_TRACKER_H__
diff --git a/vpx_mem/memory_manager/hmm_alloc.c b/vpx_mem/memory_manager/hmm_alloc.c
new file mode 100644 (file)
index 0000000..22c4a54
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/* This code is in the public domain.
+** Version: 1.1  Author: Walt Karas
+*/
+
+#include "hmm_intrnl.h"
+
+void *U(alloc)(U(descriptor) *desc, U(size_aau) n)
+{
+#ifdef HMM_AUDIT_FAIL
+
+    if (desc->avl_tree_root)
+        AUDIT_BLOCK(PTR_REC_TO_HEAD(desc->avl_tree_root))
+#endif
+
+        if (desc->last_freed)
+        {
+#ifdef HMM_AUDIT_FAIL
+            AUDIT_BLOCK(desc->last_freed)
+#endif
+
+            U(into_free_collection)(desc, (head_record *)(desc->last_freed));
+
+            desc->last_freed = 0;
+        }
+
+    /* Add space for block header. */
+    n += HEAD_AAUS;
+
+    /* Convert n from number of address alignment units to block alignment
+    ** units. */
+    n = DIV_ROUND_UP(n, HMM_BLOCK_ALIGN_UNIT);
+
+    if (n < MIN_BLOCK_BAUS)
+        n = MIN_BLOCK_BAUS;
+
+    {
+        /* Search for the first node of the bin containing the smallest
+        ** block big enough to satisfy request. */
+        ptr_record *ptr_rec_ptr =
+            U(avl_search)(
+                (U(avl_avl) *) & (desc->avl_tree_root), (U(size_bau)) n,
+                AVL_GREATER_EQUAL);
+
+        /* If an approprate bin is found, satisfy the allocation request,
+        ** otherwise return null pointer. */
+        return(ptr_rec_ptr ?
+               U(alloc_from_bin)(desc, ptr_rec_ptr, (U(size_bau)) n) : 0);
+    }
+}
diff --git a/vpx_mem/memory_manager/hmm_base.c b/vpx_mem/memory_manager/hmm_base.c
new file mode 100644 (file)
index 0000000..ad1da03
--- /dev/null
@@ -0,0 +1,434 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/* This code is in the public domain.
+** Version: 1.1  Author: Walt Karas
+*/
+
+#include "hmm_intrnl.h"
+
+void U(init)(U(descriptor) *desc)
+{
+    desc->avl_tree_root = 0;
+    desc->last_freed = 0;
+}
+
+/* Remove a free block from a bin's doubly-linked list when it is not,
+** the first block in the bin.
+*/
+void U(dll_remove)(
+    /* Pointer to pointer record in the block to be removed. */
+    ptr_record *to_remove)
+{
+    to_remove->prev->next = to_remove->next;
+
+    if (to_remove->next)
+        to_remove->next->prev = to_remove->prev;
+}
+
+/* Put a block into the free collection of a heap.
+*/
+void U(into_free_collection)(
+    /* Pointer to heap descriptor. */
+    U(descriptor) *desc,
+    /* Pointer to head record of block. */
+    head_record *head_ptr)
+{
+    ptr_record *ptr_rec_ptr = HEAD_TO_PTR_REC(head_ptr);
+
+    ptr_record *bin_front_ptr =
+        U(avl_insert)((U(avl_avl) *) & (desc->avl_tree_root), ptr_rec_ptr);
+
+    if (bin_front_ptr != ptr_rec_ptr)
+    {
+        /* The block was not inserted into the AVL tree because there is
+        ** already a bin for the size of the block. */
+
+        MARK_SUCCESSIVE_BLOCK_IN_FREE_BIN(head_ptr)
+        ptr_rec_ptr->self = ptr_rec_ptr;
+
+        /* Make the block the new second block in the bin's doubly-linked
+        ** list. */
+        ptr_rec_ptr->prev = bin_front_ptr;
+        ptr_rec_ptr->next = bin_front_ptr->next;
+        bin_front_ptr->next = ptr_rec_ptr;
+
+        if (ptr_rec_ptr->next)
+            ptr_rec_ptr->next->prev = ptr_rec_ptr;
+    }
+    else
+        /* Block is first block in new bin. */
+        ptr_rec_ptr->next = 0;
+}
+
+/* Allocate a block from a given bin.  Returns a pointer to the payload
+** of the removed block.  The "last freed" pointer must be null prior
+** to calling this function.
+*/
+void *U(alloc_from_bin)(
+    /* Pointer to heap descriptor. */
+    U(descriptor) *desc,
+    /* Pointer to pointer record of first block in bin. */
+    ptr_record *bin_front_ptr,
+    /* Number of BAUs needed in the allocated block.  If the block taken
+    ** from the bin is significantly larger than the number of BAUs needed,
+    ** the "extra" BAUs are split off to form a new free block. */
+    U(size_bau) n_baus)
+{
+    head_record *head_ptr;
+    U(size_bau) rem_baus;
+
+    if (bin_front_ptr->next)
+    {
+        /* There are multiple blocks in this bin.  Use the 2nd block in
+        ** the bin to avoid needless change to the AVL tree.
+        */
+
+        ptr_record *ptr_rec_ptr = bin_front_ptr->next;
+        head_ptr = PTR_REC_TO_HEAD(ptr_rec_ptr);
+
+#ifdef AUDIT_FAIL
+        AUDIT_BLOCK(head_ptr)
+#endif
+
+        U(dll_remove)(ptr_rec_ptr);
+    }
+    else
+    {
+        /* There is only one block in the bin, so it has to be removed
+        ** from the AVL tree.
+        */
+
+        head_ptr = PTR_REC_TO_HEAD(bin_front_ptr);
+
+        U(avl_remove)(
+            (U(avl_avl) *) &(desc->avl_tree_root), BLOCK_BAUS(head_ptr));
+    }
+
+    MARK_BLOCK_ALLOCATED(head_ptr)
+
+    rem_baus = BLOCK_BAUS(head_ptr) - n_baus;
+
+    if (rem_baus >= MIN_BLOCK_BAUS)
+    {
+        /* Since there are enough "extra" BAUs, split them off to form
+        ** a new free block.
+        */
+
+        head_record *rem_head_ptr =
+            (head_record *) BAUS_FORWARD(head_ptr, n_baus);
+
+        /* Change the next block's header to reflect the fact that the
+        ** block preceeding it is now smaller.
+        */
+        SET_PREV_BLOCK_BAUS(
+            BAUS_FORWARD(head_ptr, head_ptr->block_size), rem_baus)
+
+        head_ptr->block_size = n_baus;
+
+        rem_head_ptr->previous_block_size = n_baus;
+        rem_head_ptr->block_size = rem_baus;
+
+        desc->last_freed = rem_head_ptr;
+    }
+
+    return(HEAD_TO_PTR_REC(head_ptr));
+}
+
+/* Take a block out of the free collection.
+*/
+void U(out_of_free_collection)(
+    /* Descriptor of heap that block is in. */
+    U(descriptor) *desc,
+    /* Pointer to head of block to take out of free collection. */
+    head_record *head_ptr)
+{
+    ptr_record *ptr_rec_ptr = HEAD_TO_PTR_REC(head_ptr);
+
+    if (ptr_rec_ptr->self == ptr_rec_ptr)
+        /* Block is not the front block in its bin, so all we have to
+        ** do is take it out of the bin's doubly-linked list. */
+        U(dll_remove)(ptr_rec_ptr);
+    else
+    {
+        ptr_record *next = ptr_rec_ptr->next;
+
+        if (next)
+            /* Block is the front block in its bin, and there is at least
+            ** one other block in the bin.  Substitute the next block for
+            ** the front block. */
+            U(avl_subst)((U(avl_avl) *) &(desc->avl_tree_root), next);
+        else
+            /* Block is the front block in its bin, but there is no other
+            ** block in the bin.  Eliminate the bin. */
+            U(avl_remove)(
+                (U(avl_avl) *) &(desc->avl_tree_root), BLOCK_BAUS(head_ptr));
+    }
+}
+
+void U(free)(U(descriptor) *desc, void *payload_ptr)
+{
+    /* Flags if coalesce with adjacent block. */
+    int coalesce;
+
+    head_record *fwd_head_ptr;
+    head_record *free_head_ptr = PTR_REC_TO_HEAD(payload_ptr);
+
+    desc->num_baus_can_shrink = 0;
+
+#ifdef HMM_AUDIT_FAIL
+
+    AUDIT_BLOCK(free_head_ptr)
+
+    /* Make sure not freeing an already free block. */
+    if (!IS_BLOCK_ALLOCATED(free_head_ptr))
+        HMM_AUDIT_FAIL
+
+        if (desc->avl_tree_root)
+            /* Audit root block in AVL tree. */
+            AUDIT_BLOCK(PTR_REC_TO_HEAD(desc->avl_tree_root))
+
+#endif
+
+            fwd_head_ptr =
+                (head_record *) BAUS_FORWARD(free_head_ptr, free_head_ptr->block_size);
+
+    if (free_head_ptr->previous_block_size)
+    {
+        /* Coalesce with backward block if possible. */
+
+        head_record *bkwd_head_ptr =
+            (head_record *) BAUS_BACKWARD(
+                free_head_ptr, free_head_ptr->previous_block_size);
+
+#ifdef HMM_AUDIT_FAIL
+        AUDIT_BLOCK(bkwd_head_ptr)
+#endif
+
+        if (bkwd_head_ptr == (head_record *)(desc->last_freed))
+        {
+            desc->last_freed = 0;
+            coalesce = 1;
+        }
+        else if (IS_BLOCK_ALLOCATED(bkwd_head_ptr))
+            coalesce = 0;
+        else
+        {
+            U(out_of_free_collection)(desc, bkwd_head_ptr);
+            coalesce = 1;
+        }
+
+        if (coalesce)
+        {
+            bkwd_head_ptr->block_size += free_head_ptr->block_size;
+            SET_PREV_BLOCK_BAUS(fwd_head_ptr, BLOCK_BAUS(bkwd_head_ptr))
+            free_head_ptr = bkwd_head_ptr;
+        }
+    }
+
+    if (fwd_head_ptr->block_size == 0)
+    {
+        /* Block to be freed is last block before dummy end-of-chunk block. */
+        desc->end_of_shrinkable_chunk =
+            BAUS_FORWARD(fwd_head_ptr, DUMMY_END_BLOCK_BAUS);
+        desc->num_baus_can_shrink = BLOCK_BAUS(free_head_ptr);
+
+        if (PREV_BLOCK_BAUS(free_head_ptr) == 0)
+            /* Free block is the entire chunk, so shrinking can eliminate
+            ** entire chunk including dummy end block. */
+            desc->num_baus_can_shrink += DUMMY_END_BLOCK_BAUS;
+    }
+    else
+    {
+        /* Coalesce with forward block if possible. */
+
+#ifdef HMM_AUDIT_FAIL
+        AUDIT_BLOCK(fwd_head_ptr)
+#endif
+
+        if (fwd_head_ptr == (head_record *)(desc->last_freed))
+        {
+            desc->last_freed = 0;
+            coalesce = 1;
+        }
+        else if (IS_BLOCK_ALLOCATED(fwd_head_ptr))
+            coalesce = 0;
+        else
+        {
+            U(out_of_free_collection)(desc, fwd_head_ptr);
+            coalesce = 1;
+        }
+
+        if (coalesce)
+        {
+            free_head_ptr->block_size += fwd_head_ptr->block_size;
+
+            fwd_head_ptr =
+                (head_record *) BAUS_FORWARD(
+                    fwd_head_ptr, BLOCK_BAUS(fwd_head_ptr));
+
+            SET_PREV_BLOCK_BAUS(fwd_head_ptr, BLOCK_BAUS(free_head_ptr))
+
+            if (fwd_head_ptr->block_size == 0)
+            {
+                /* Coalesced block to be freed is last block before dummy
+                ** end-of-chunk block. */
+                desc->end_of_shrinkable_chunk =
+                    BAUS_FORWARD(fwd_head_ptr, DUMMY_END_BLOCK_BAUS);
+                desc->num_baus_can_shrink = BLOCK_BAUS(free_head_ptr);
+
+                if (PREV_BLOCK_BAUS(free_head_ptr) == 0)
+                    /* Free block is the entire chunk, so shrinking can
+                    ** eliminate entire chunk including dummy end block. */
+                    desc->num_baus_can_shrink += DUMMY_END_BLOCK_BAUS;
+            }
+        }
+    }
+
+    if (desc->last_freed)
+    {
+        /* There is a last freed block, but it is not adjacent to the
+        ** block being freed by this call to free, so put the last
+        ** freed block into the free collection.
+        */
+
+#ifdef HMM_AUDIT_FAIL
+        AUDIT_BLOCK(desc->last_freed)
+#endif
+
+        U(into_free_collection)(desc, (head_record *)(desc->last_freed));
+    }
+
+    desc->last_freed = free_head_ptr;
+}
+
+void U(new_chunk)(U(descriptor) *desc, void *start, U(size_bau) n_baus)
+{
+#ifdef HMM_AUDIT_FAIL
+
+    if (desc->avl_tree_root)
+        /* Audit root block in AVL tree. */
+        AUDIT_BLOCK(PTR_REC_TO_HEAD(desc->avl_tree_root))
+#endif
+
+#undef HEAD_PTR
+#define HEAD_PTR ((head_record *) start)
+
+        /* Make the chunk one big free block followed by a dummy end block.
+        */
+
+        n_baus -= DUMMY_END_BLOCK_BAUS;
+
+    HEAD_PTR->previous_block_size = 0;
+    HEAD_PTR->block_size = n_baus;
+
+    U(into_free_collection)(desc, HEAD_PTR);
+
+    /* Set up the dummy end block. */
+    start = BAUS_FORWARD(start, n_baus);
+    HEAD_PTR->previous_block_size = n_baus;
+    HEAD_PTR->block_size = 0;
+
+#undef HEAD_PTR
+}
+
+#ifdef HMM_AUDIT_FAIL
+
+/* Function that does audit fail actions defined my preprocessor symbol,
+** and returns a dummy integer value.
+*/
+int U(audit_block_fail_dummy_return)(void)
+{
+    HMM_AUDIT_FAIL
+
+    /* Dummy return. */
+    return(0);
+}
+
+#endif
+
+/* AVL Tree instantiation. */
+
+#ifdef HMM_AUDIT_FAIL
+
+/* The AVL tree generic package passes an ACCESS of 1 when it "touches"
+** a child node for the first time during a particular operation.  I use
+** this feature to audit only one time (per operation) the free blocks
+** that are tree nodes.  Since the root node is not a child node, it has
+** to be audited directly.
+*/
+
+/* The pain you feel while reading these macros will not be in vain.  It
+** will remove all doubt from you mind that C++ inline functions are
+** a very good thing.
+*/
+
+#define AVL_GET_LESS(H, ACCESS) \
+    (((ACCESS) ? AUDIT_BLOCK_AS_EXPR(PTR_REC_TO_HEAD(H)) : 0), (H)->self)
+#define AVL_GET_GREATER(H, ACCESS) \
+    (((ACCESS) ? AUDIT_BLOCK_AS_EXPR(PTR_REC_TO_HEAD(H)) : 0), (H)->prev)
+
+#else
+
+#define AVL_GET_LESS(H, ACCESS) ((H)->self)
+#define AVL_GET_GREATER(H, ACCESS) ((H)->prev)
+
+#endif
+
+#define AVL_SET_LESS(H, LH) (H)->self = (LH);
+#define AVL_SET_GREATER(H, GH) (H)->prev = (GH);
+
+/*  high bit of high bit of
+**  block_size  previous_block_size balance factor
+**  ----------- ------------------- --------------
+**  0       0           n/a (block allocated)
+**  0       1           1
+**  1       0           -1
+**  1       1           0
+*/
+
+#define AVL_GET_BALANCE_FACTOR(H) \
+    ((((head_record *) (PTR_REC_TO_HEAD(H)))->block_size & \
+      HIGH_BIT_BAU_SIZE) ? \
+     (((head_record *) (PTR_REC_TO_HEAD(H)))->previous_block_size & \
+      HIGH_BIT_BAU_SIZE ? 0 : -1) : 1)
+
+#define AVL_SET_BALANCE_FACTOR(H, BF) \
+    {                         \
+        register head_record *p =               \
+                                                (head_record *) PTR_REC_TO_HEAD(H);       \
+        register int bal_f = (BF);              \
+        \
+        if (bal_f <= 0)                 \
+            p->block_size |= HIGH_BIT_BAU_SIZE;       \
+        else                        \
+            p->block_size &= ~HIGH_BIT_BAU_SIZE;      \
+        if (bal_f >= 0)                 \
+            p->previous_block_size |= HIGH_BIT_BAU_SIZE;  \
+        else                        \
+            p->previous_block_size &= ~HIGH_BIT_BAU_SIZE; \
+    }
+
+#define COMPARE_KEY_KEY(K1, K2) ((K1) == (K2) ? 0 : ((K1) > (K2) ? 1 : -1))
+
+#define AVL_COMPARE_KEY_NODE(K, H) \
+    COMPARE_KEY_KEY(K, BLOCK_BAUS(PTR_REC_TO_HEAD(H)))
+
+#define AVL_COMPARE_NODE_NODE(H1, H2) \
+    COMPARE_KEY_KEY(BLOCK_BAUS(PTR_REC_TO_HEAD(H1)), \
+                    BLOCK_BAUS(PTR_REC_TO_HEAD(H2)))
+
+#define AVL_NULL ((ptr_record *) 0)
+
+#define AVL_IMPL_MASK \
+    ( AVL_IMPL_INSERT | AVL_IMPL_SEARCH | AVL_IMPL_REMOVE | AVL_IMPL_SUBST )
+
+#include "cavl_impl.h"
diff --git a/vpx_mem/memory_manager/hmm_dflt_abort.c b/vpx_mem/memory_manager/hmm_dflt_abort.c
new file mode 100644 (file)
index 0000000..d92435c
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/* This code is in the public domain.
+** Version: 1.1  Author: Walt Karas
+*/
+
+/* The function in this file performs default actions if self-auditing
+** finds heap corruption.  Don't rely on this code to handle the
+** case where HMM is being used to implement the malloc and free standard
+** library functions.  Rewrite the function if necessary to avoid using
+** I/O and execution termination functions that call malloc or free.
+** In Unix, for example, you would replace the fputs calls with calls
+** to the write system call using file handle number 2.
+*/
+#include "hmm_intrnl.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+static int entered = 0;
+
+/* Print abort message, file and line.  Terminate execution.
+*/
+void hmm_dflt_abort(const char *file, const char *line)
+{
+    /* Avoid use of printf(), which is more likely to use heap. */
+
+    if (entered)
+
+        /* The standard I/O functions called a heap function and caused
+        ** an indirect recursive call to this function.  So we'll have
+        ** to just exit without printing a message.  */
+        while (1);
+
+    entered = 1;
+
+    fputs("\n_abort - Heap corruption\n" "File: ", stderr);
+    fputs(file, stderr);
+    fputs("  Line: ", stderr);
+    fputs(line, stderr);
+    fputs("\n\n", stderr);
+    fputs("hmm_dflt_abort: while(1)!!!\n", stderr);
+    fflush(stderr);
+
+    while (1);
+}
diff --git a/vpx_mem/memory_manager/hmm_grow.c b/vpx_mem/memory_manager/hmm_grow.c
new file mode 100644 (file)
index 0000000..9a4b6e4
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/* This code is in the public domain.
+** Version: 1.1  Author: Walt Karas
+*/
+
+#include "hmm_intrnl.h"
+
+void U(grow_chunk)(U(descriptor) *desc, void *end, U(size_bau) n_baus)
+{
+#undef HEAD_PTR
+#define HEAD_PTR ((head_record *) end)
+
+    end = BAUS_BACKWARD(end, DUMMY_END_BLOCK_BAUS);
+
+#ifdef HMM_AUDIT_FAIL
+
+    if (HEAD_PTR->block_size != 0)
+        /* Chunk does not have valid dummy end block. */
+        HMM_AUDIT_FAIL
+
+#endif
+
+        /* Create a new block that absorbs the old dummy end block. */
+        HEAD_PTR->block_size = n_baus;
+
+    /* Set up the new dummy end block. */
+    {
+        head_record *dummy = (head_record *) BAUS_FORWARD(end, n_baus);
+        dummy->previous_block_size = n_baus;
+        dummy->block_size = 0;
+    }
+
+    /* Simply free the new block, allowing it to coalesce with any
+    ** free block at that was the last block in the chunk prior to
+    ** growth.
+    */
+    U(free)(desc, HEAD_TO_PTR_REC(end));
+
+#undef HEAD_PTR
+}
diff --git a/vpx_mem/memory_manager/hmm_largest.c b/vpx_mem/memory_manager/hmm_largest.c
new file mode 100644 (file)
index 0000000..c3c6f2c
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/* This code is in the public domain.
+** Version: 1.1  Author: Walt Karas
+*/
+
+#include "hmm_intrnl.h"
+
+U(size_aau) U(largest_available)(U(descriptor) *desc)
+{
+    U(size_bau) largest;
+
+    if (!(desc->avl_tree_root))
+        largest = 0;
+    else
+    {
+#ifdef HMM_AUDIT_FAIL
+        /* Audit root block in AVL tree. */
+        AUDIT_BLOCK(PTR_REC_TO_HEAD(desc->avl_tree_root))
+#endif
+
+        largest =
+            BLOCK_BAUS(
+                PTR_REC_TO_HEAD(
+                    U(avl_search)(
+                        (U(avl_avl) *) & (desc->avl_tree_root),
+                        (U(size_bau)) ~(U(size_bau)) 0, AVL_LESS)));
+    }
+
+    if (desc->last_freed)
+    {
+        /* Size of last freed block. */
+        register U(size_bau) lf_size;
+
+#ifdef HMM_AUDIT_FAIL
+        AUDIT_BLOCK(desc->last_freed)
+#endif
+
+        lf_size = BLOCK_BAUS(desc->last_freed);
+
+        if (lf_size > largest)
+            largest = lf_size;
+    }
+
+    /* Convert largest size to AAUs and subract head size leaving payload
+    ** size.
+    */
+    return(largest ?
+           ((largest * ((U(size_aau)) HMM_BLOCK_ALIGN_UNIT)) - HEAD_AAUS) :
+           0);
+}
diff --git a/vpx_mem/memory_manager/hmm_resize.c b/vpx_mem/memory_manager/hmm_resize.c
new file mode 100644 (file)
index 0000000..f90da96
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/* This code is in the public domain.
+** Version: 1.1  Author: Walt Karas
+*/
+
+#include "hmm_intrnl.h"
+
+int U(resize)(U(descriptor) *desc, void *mem, U(size_aau) n)
+{
+    U(size_aau) i;
+    head_record *next_head_ptr;
+    head_record *head_ptr = PTR_REC_TO_HEAD(mem);
+
+    /* Flag. */
+    int next_block_free;
+
+    /* Convert n from desired block size in AAUs to BAUs. */
+    n += HEAD_AAUS;
+    n = DIV_ROUND_UP(n, HMM_BLOCK_ALIGN_UNIT);
+
+    if (n < MIN_BLOCK_BAUS)
+        n = MIN_BLOCK_BAUS;
+
+#ifdef HMM_AUDIT_FAIL
+
+    AUDIT_BLOCK(head_ptr)
+
+    if (!IS_BLOCK_ALLOCATED(head_ptr))
+        HMM_AUDIT_FAIL
+
+        if (desc->avl_tree_root)
+            AUDIT_BLOCK(PTR_REC_TO_HEAD(desc->avl_tree_root))
+
+#endif
+
+            i = head_ptr->block_size;
+
+    next_head_ptr =
+        (head_record *) BAUS_FORWARD(head_ptr, head_ptr->block_size);
+
+    next_block_free =
+        (next_head_ptr == desc->last_freed) ||
+        !IS_BLOCK_ALLOCATED(next_head_ptr);
+
+    if (next_block_free)
+        /* Block can expand into next free block. */
+        i += BLOCK_BAUS(next_head_ptr);
+
+    if (n > i)
+        /* Not enough room for block to expand. */
+        return(-1);
+
+    if (next_block_free)
+    {
+#ifdef HMM_AUDIT_FAIL
+        AUDIT_BLOCK(next_head_ptr)
+#endif
+
+        if (next_head_ptr == desc->last_freed)
+            desc->last_freed = 0;
+        else
+            U(out_of_free_collection)(desc, next_head_ptr);
+
+        next_head_ptr =
+            (head_record *) BAUS_FORWARD(head_ptr, (U(size_bau)) i);
+    }
+
+    /* Set i to number of "extra" BAUs. */
+    i -= n;
+
+    if (i < MIN_BLOCK_BAUS)
+        /* Not enough extra BAUs to be a block on their own, so just keep them
+        ** in the block being resized.
+        */
+    {
+        n += i;
+        i = n;
+    }
+    else
+    {
+        /* There are enough "leftover" BAUs in the next block to
+        ** form a remainder block. */
+
+        head_record *rem_head_ptr;
+
+        rem_head_ptr = (head_record *) BAUS_FORWARD(head_ptr, n);
+
+        rem_head_ptr->previous_block_size = (U(size_bau)) n;
+        rem_head_ptr->block_size = (U(size_bau)) i;
+
+        if (desc->last_freed)
+        {
+#ifdef HMM_AUDIT_FAIL
+            AUDIT_BLOCK(desc->last_freed)
+#endif
+
+            U(into_free_collection)(desc, (head_record *)(desc->last_freed));
+
+            desc->last_freed = 0;
+        }
+
+        desc->last_freed = rem_head_ptr;
+    }
+
+    head_ptr->block_size = (U(size_bau)) n;
+    next_head_ptr->previous_block_size = (U(size_bau)) i;
+
+    return(0);
+}
diff --git a/vpx_mem/memory_manager/hmm_shrink.c b/vpx_mem/memory_manager/hmm_shrink.c
new file mode 100644 (file)
index 0000000..78fe268
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/* This code is in the public domain.
+** Version: 1.1  Author: Walt Karas
+*/
+
+#include "hmm_intrnl.h"
+
+void U(shrink_chunk)(U(descriptor) *desc, U(size_bau) n_baus_to_shrink)
+{
+    head_record *dummy_end_block = (head_record *)
+                                   BAUS_BACKWARD(desc->end_of_shrinkable_chunk, DUMMY_END_BLOCK_BAUS);
+
+#ifdef HMM_AUDIT_FAIL
+
+    if (dummy_end_block->block_size != 0)
+        /* Chunk does not have valid dummy end block. */
+        HMM_AUDIT_FAIL
+
+#endif
+
+        if (n_baus_to_shrink)
+        {
+            head_record *last_block = (head_record *)
+                                      BAUS_BACKWARD(
+                                          dummy_end_block, dummy_end_block->previous_block_size);
+
+#ifdef HMM_AUDIT_FAIL
+            AUDIT_BLOCK(last_block)
+#endif
+
+            if (last_block == desc->last_freed)
+            {
+                U(size_bau) bs = BLOCK_BAUS(last_block);
+
+                /* Chunk will not be shrunk out of existence if
+                ** 1.  There is at least one allocated block in the chunk
+                **     and the amount to shrink is exactly the size of the
+                **     last block, OR
+                ** 2.  After the last block is shrunk, there will be enough
+                **     BAUs left in it to form a minimal size block. */
+                int chunk_will_survive =
+                    (PREV_BLOCK_BAUS(last_block) && (n_baus_to_shrink == bs)) ||
+                    (n_baus_to_shrink <= (U(size_bau))(bs - MIN_BLOCK_BAUS));
+
+                if (chunk_will_survive ||
+                    (!PREV_BLOCK_BAUS(last_block) &&
+                     (n_baus_to_shrink ==
+                      (U(size_bau))(bs + DUMMY_END_BLOCK_BAUS))))
+                {
+                    desc->last_freed = 0;
+
+                    if (chunk_will_survive)
+                    {
+                        bs -= n_baus_to_shrink;
+
+                        if (bs)
+                        {
+                            /* The last (non-dummy) block was not completely
+                            ** eliminated by the shrink. */
+
+                            last_block->block_size = bs;
+
+                            /* Create new dummy end record.
+                            */
+                            dummy_end_block =
+                                (head_record *) BAUS_FORWARD(last_block, bs);
+                            dummy_end_block->previous_block_size = bs;
+                            dummy_end_block->block_size = 0;
+
+#ifdef HMM_AUDIT_FAIL
+
+                            if (desc->avl_tree_root)
+                                AUDIT_BLOCK(PTR_REC_TO_HEAD(desc->avl_tree_root))
+#endif
+
+                                U(into_free_collection)(desc, last_block);
+                        }
+                        else
+                        {
+                            /* The last (non-dummy) block was completely
+                            ** eliminated by the shrink.  Make its head
+                            ** the new dummy end block.
+                            */
+                            last_block->block_size = 0;
+                            last_block->previous_block_size &= ~HIGH_BIT_BAU_SIZE;
+                        }
+                    }
+                }
+
+#ifdef HMM_AUDIT_FAIL
+                else
+                    HMM_AUDIT_FAIL
+#endif
+                }
+
+#ifdef HMM_AUDIT_FAIL
+            else
+                HMM_AUDIT_FAIL
+#endif
+            }
+}
diff --git a/vpx_mem/memory_manager/hmm_true.c b/vpx_mem/memory_manager/hmm_true.c
new file mode 100644 (file)
index 0000000..3f7be8f
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/* This code is in the public domain.
+** Version: 1.1  Author: Walt Karas
+*/
+
+#include "hmm_intrnl.h"
+
+U(size_aau) U(true_size)(void *payload_ptr)
+{
+    register  head_record *head_ptr = PTR_REC_TO_HEAD(payload_ptr);
+
+#ifdef HMM_AUDIT_FAIL
+    AUDIT_BLOCK(head_ptr)
+#endif
+
+    /* Convert block size from BAUs to AAUs.  Subtract head size, leaving
+    ** payload size.
+    */
+    return(
+              (BLOCK_BAUS(head_ptr) * ((U(size_aau)) HMM_BLOCK_ALIGN_UNIT)) -
+              HEAD_AAUS);
+}
diff --git a/vpx_mem/memory_manager/include/cavl_if.h b/vpx_mem/memory_manager/include/cavl_if.h
new file mode 100644 (file)
index 0000000..1b2c9b7
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/* Abstract AVL Tree Generic C Package.
+** Interface generation header file.
+**
+** This code is in the public domain.  See cavl_tree.html for interface
+** documentation.
+**
+** Version: 1.5  Author: Walt Karas
+*/
+
+/* This header contains the definition of CHAR_BIT (number of bits in a
+** char). */
+#include <limits.h>
+
+#undef L_
+#undef L_EST_LONG_BIT
+#undef L_SIZE
+#undef L_SC
+#undef L_LONG_BIT
+#undef L_BIT_ARR_DEFN
+
+#ifndef AVL_SEARCH_TYPE_DEFINED_
+#define AVL_SEARCH_TYPE_DEFINED_
+
+typedef enum
+{
+    AVL_EQUAL = 1,
+    AVL_LESS = 2,
+    AVL_GREATER = 4,
+    AVL_LESS_EQUAL = AVL_EQUAL | AVL_LESS,
+    AVL_GREATER_EQUAL = AVL_EQUAL | AVL_GREATER
+}
+avl_search_type;
+
+#endif
+
+#ifdef AVL_UNIQUE
+
+#define L_ AVL_UNIQUE
+
+#else
+
+#define L_(X) X
+
+#endif
+
+/* Determine storage class for function prototypes. */
+#ifdef AVL_PRIVATE
+
+#define L_SC static
+
+#else
+
+#define L_SC extern
+
+#endif
+
+#ifdef AVL_SIZE
+
+#define L_SIZE AVL_SIZE
+
+#else
+
+#define L_SIZE unsigned long
+
+#endif
+
+typedef struct
+{
+#ifdef AVL_INSIDE_STRUCT
+
+    AVL_INSIDE_STRUCT
+
+#endif
+
+    AVL_HANDLE root;
+}
+L_(avl);
+
+/* Function prototypes. */
+
+L_SC void L_(init)(L_(avl) *tree);
+
+L_SC int L_(is_empty)(L_(avl) *tree);
+
+L_SC AVL_HANDLE L_(insert)(L_(avl) *tree, AVL_HANDLE h);
+
+L_SC AVL_HANDLE L_(search)(L_(avl) *tree, AVL_KEY k, avl_search_type st);
+
+L_SC AVL_HANDLE L_(search_least)(L_(avl) *tree);
+
+L_SC AVL_HANDLE L_(search_greatest)(L_(avl) *tree);
+
+L_SC AVL_HANDLE L_(remove)(L_(avl) *tree, AVL_KEY k);
+
+L_SC AVL_HANDLE L_(subst)(L_(avl) *tree, AVL_HANDLE new_node);
+
+#ifdef AVL_BUILD_ITER_TYPE
+
+L_SC int L_(build)(
+    L_(avl) *tree, AVL_BUILD_ITER_TYPE p, L_SIZE num_nodes);
+
+#endif
+
+/* ANSI C/ISO C++ require that a long have at least 32 bits.  Set
+** L_EST_LONG_BIT to be the greatest multiple of 8 in the range
+** 32 - 64 (inclusive) that is less than or equal to the number of
+** bits in a long.
+*/
+
+#if (((LONG_MAX >> 31) >> 7) == 0)
+
+#define L_EST_LONG_BIT 32
+
+#elif (((LONG_MAX >> 31) >> 15) == 0)
+
+#define L_EST_LONG_BIT 40
+
+#elif (((LONG_MAX >> 31) >> 23) == 0)
+
+#define L_EST_LONG_BIT 48
+
+#elif (((LONG_MAX >> 31) >> 31) == 0)
+
+#define L_EST_LONG_BIT 56
+
+#else
+
+#define L_EST_LONG_BIT 64
+
+#endif
+
+/* Number of bits in a long. */
+#define L_LONG_BIT (sizeof(long) * CHAR_BIT)
+
+/* The macro L_BIT_ARR_DEFN defines a bit array whose index is a (0-based)
+** node depth.  The definition depends on whether the maximum depth is more
+** or less than the number of bits in a single long.
+*/
+
+#if ((AVL_MAX_DEPTH) > L_EST_LONG_BIT)
+
+/* Maximum depth may be more than number of bits in a long. */
+
+#define L_BIT_ARR_DEFN(NAME) \
+    unsigned long NAME[((AVL_MAX_DEPTH) + L_LONG_BIT - 1) / L_LONG_BIT];
+
+#else
+
+/* Maximum depth is definitely less than number of bits in a long. */
+
+#define L_BIT_ARR_DEFN(NAME) unsigned long NAME;
+
+#endif
+
+/* Iterator structure. */
+typedef struct
+{
+    /* Tree being iterated over. */
+    L_(avl) *tree_;
+
+    /* Records a path into the tree.  If bit n is true, indicates
+    ** take greater branch from the nth node in the path, otherwise
+    ** take the less branch.  bit 0 gives branch from root, and
+    ** so on. */
+    L_BIT_ARR_DEFN(branch)
+
+    /* Zero-based depth of path into tree. */
+    unsigned depth;
+
+    /* Handles of nodes in path from root to current node (returned by *). */
+    AVL_HANDLE path_h[(AVL_MAX_DEPTH) - 1];
+}
+L_(iter);
+
+/* Iterator function prototypes. */
+
+L_SC void L_(start_iter)(
+    L_(avl) *tree, L_(iter) *iter, AVL_KEY k, avl_search_type st);
+
+L_SC void L_(start_iter_least)(L_(avl) *tree, L_(iter) *iter);
+
+L_SC void L_(start_iter_greatest)(L_(avl) *tree, L_(iter) *iter);
+
+L_SC AVL_HANDLE L_(get_iter)(L_(iter) *iter);
+
+L_SC void L_(incr_iter)(L_(iter) *iter);
+
+L_SC void L_(decr_iter)(L_(iter) *iter);
+
+L_SC void L_(init_iter)(L_(iter) *iter);
+
+#define AVL_IMPL_INIT           1
+#define AVL_IMPL_IS_EMPTY       (1 << 1)
+#define AVL_IMPL_INSERT         (1 << 2)
+#define AVL_IMPL_SEARCH         (1 << 3)
+#define AVL_IMPL_SEARCH_LEAST       (1 << 4)
+#define AVL_IMPL_SEARCH_GREATEST    (1 << 5)
+#define AVL_IMPL_REMOVE         (1 << 6)
+#define AVL_IMPL_BUILD          (1 << 7)
+#define AVL_IMPL_START_ITER     (1 << 8)
+#define AVL_IMPL_START_ITER_LEAST   (1 << 9)
+#define AVL_IMPL_START_ITER_GREATEST    (1 << 10)
+#define AVL_IMPL_GET_ITER       (1 << 11)
+#define AVL_IMPL_INCR_ITER      (1 << 12)
+#define AVL_IMPL_DECR_ITER      (1 << 13)
+#define AVL_IMPL_INIT_ITER      (1 << 14)
+#define AVL_IMPL_SUBST          (1 << 15)
+
+#define AVL_IMPL_ALL            (~0)
+
+#undef L_
+#undef L_EST_LONG_BIT
+#undef L_SIZE
+#undef L_SC
+#undef L_LONG_BIT
+#undef L_BIT_ARR_DEFN
diff --git a/vpx_mem/memory_manager/include/cavl_impl.h b/vpx_mem/memory_manager/include/cavl_impl.h
new file mode 100644 (file)
index 0000000..5e165dd
--- /dev/null
@@ -0,0 +1,1267 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/* Abstract AVL Tree Generic C Package.
+** Implementation generation header file.
+**
+** This code is in the public domain.  See cavl_tree.html for interface
+** documentation.
+**
+** Version: 1.5  Author: Walt Karas
+*/
+
+#undef L_
+#undef L_EST_LONG_BIT
+#undef L_SIZE
+#undef l_tree
+#undef L_MASK_HIGH_BIT
+#undef L_LONG_BIT
+#undef L_BIT_ARR_DEFN
+#undef L_BIT_ARR_VAL
+#undef L_BIT_ARR_0
+#undef L_BIT_ARR_1
+#undef L_BIT_ARR_ALL
+#undef L_BIT_ARR_LONGS
+#undef L_IMPL_MASK
+#undef L_CHECK_READ_ERROR
+#undef L_CHECK_READ_ERROR_INV_DEPTH
+#undef L_SC
+#undef L_BALANCE_PARAM_PREFIX
+
+#ifdef AVL_UNIQUE
+
+#define L_ AVL_UNIQUE
+
+#else
+
+#define L_(X) X
+
+#endif
+
+/* Determine correct storage class for functions */
+#ifdef AVL_PRIVATE
+
+#define L_SC static
+
+#else
+
+#define L_SC
+
+#endif
+
+#ifdef AVL_SIZE
+
+#define L_SIZE AVL_SIZE
+
+#else
+
+#define L_SIZE unsigned long
+
+#endif
+
+#define L_MASK_HIGH_BIT ((int) ~ ((~ (unsigned) 0) >> 1))
+
+/* ANSI C/ISO C++ require that a long have at least 32 bits.  Set
+** L_EST_LONG_BIT to be the greatest multiple of 8 in the range
+** 32 - 64 (inclusive) that is less than or equal to the number of
+** bits in a long.
+*/
+
+#if (((LONG_MAX >> 31) >> 7) == 0)
+
+#define L_EST_LONG_BIT 32
+
+#elif (((LONG_MAX >> 31) >> 15) == 0)
+
+#define L_EST_LONG_BIT 40
+
+#elif (((LONG_MAX >> 31) >> 23) == 0)
+
+#define L_EST_LONG_BIT 48
+
+#elif (((LONG_MAX >> 31) >> 31) == 0)
+
+#define L_EST_LONG_BIT 56
+
+#else
+
+#define L_EST_LONG_BIT 64
+
+#endif
+
+#define L_LONG_BIT (sizeof(long) * CHAR_BIT)
+
+#if ((AVL_MAX_DEPTH) > L_EST_LONG_BIT)
+
+/* The maximum depth may be greater than the number of bits in a long,
+** so multiple longs are needed to hold a bit array indexed by node
+** depth. */
+
+#define L_BIT_ARR_LONGS (((AVL_MAX_DEPTH) + L_LONG_BIT - 1) / L_LONG_BIT)
+
+#define L_BIT_ARR_DEFN(NAME) unsigned long NAME[L_BIT_ARR_LONGS];
+
+#define L_BIT_ARR_VAL(BIT_ARR, BIT_NUM) \
+    ((BIT_ARR)[(BIT_NUM) / L_LONG_BIT] & (1L << ((BIT_NUM) % L_LONG_BIT)))
+
+#define L_BIT_ARR_0(BIT_ARR, BIT_NUM) \
+    (BIT_ARR)[(BIT_NUM) / L_LONG_BIT] &= ~(1L << ((BIT_NUM) % L_LONG_BIT));
+
+#define L_BIT_ARR_1(BIT_ARR, BIT_NUM) \
+    (BIT_ARR)[(BIT_NUM) / L_LONG_BIT] |= 1L << ((BIT_NUM) % L_LONG_BIT);
+
+#define L_BIT_ARR_ALL(BIT_ARR, BIT_VAL) \
+    { int i = L_BIT_ARR_LONGS; do (BIT_ARR)[--i] = 0L - (BIT_VAL); while(i); }
+
+#else /* The bit array can definitely fit in one long */
+
+#define L_BIT_ARR_DEFN(NAME) unsigned long NAME;
+
+#define L_BIT_ARR_VAL(BIT_ARR, BIT_NUM) ((BIT_ARR) & (1L << (BIT_NUM)))
+
+#define L_BIT_ARR_0(BIT_ARR, BIT_NUM) (BIT_ARR) &= ~(1L << (BIT_NUM));
+
+#define L_BIT_ARR_1(BIT_ARR, BIT_NUM) (BIT_ARR) |= 1L << (BIT_NUM);
+
+#define L_BIT_ARR_ALL(BIT_ARR, BIT_VAL) (BIT_ARR) = 0L - (BIT_VAL);
+
+#endif
+
+#ifdef AVL_READ_ERRORS_HAPPEN
+
+#define L_CHECK_READ_ERROR(ERROR_RETURN) \
+    { if (AVL_READ_ERROR) return(ERROR_RETURN); }
+
+#else
+
+#define L_CHECK_READ_ERROR(ERROR_RETURN)
+
+#endif
+
+/* The presumed reason that an instantiation places additional fields
+** inside the AVL tree structure is that the SET_ and GET_ macros
+** need these fields.  The "balance" function does not explicitly use
+** any fields in the AVL tree structure, so only pass an AVL tree
+** structure pointer to "balance" if it has instantiation-specific
+** fields that are (presumably) needed by the SET_/GET_ calls within
+** "balance".
+*/
+#ifdef AVL_INSIDE_STRUCT
+
+#define L_BALANCE_PARAM_CALL_PREFIX l_tree,
+#define L_BALANCE_PARAM_DECL_PREFIX L_(avl) *l_tree,
+
+#else
+
+#define L_BALANCE_PARAM_CALL_PREFIX
+#define L_BALANCE_PARAM_DECL_PREFIX
+
+#endif
+
+#ifdef AVL_IMPL_MASK
+
+#define L_IMPL_MASK (AVL_IMPL_MASK)
+
+#else
+
+/* Define all functions. */
+#define L_IMPL_MASK AVL_IMPL_ALL
+
+#endif
+
+#if (L_IMPL_MASK & AVL_IMPL_INIT)
+
+L_SC void L_(init)(L_(avl) *l_tree)
+{
+    l_tree->root = AVL_NULL;
+}
+
+#endif
+
+#if (L_IMPL_MASK & AVL_IMPL_IS_EMPTY)
+
+L_SC int L_(is_empty)(L_(avl) *l_tree)
+{
+    return(l_tree->root == AVL_NULL);
+}
+
+#endif
+
+/* Put the private balance function in the same compilation module as
+** the insert function.  */
+#if (L_IMPL_MASK & AVL_IMPL_INSERT)
+
+/* Balances subtree, returns handle of root node of subtree after balancing.
+*/
+L_SC AVL_HANDLE L_(balance)(L_BALANCE_PARAM_DECL_PREFIX AVL_HANDLE bal_h)
+{
+    AVL_HANDLE deep_h;
+
+    /* Either the "greater than" or the "less than" subtree of
+    ** this node has to be 2 levels deeper (or else it wouldn't
+    ** need balancing).
+    */
+    if (AVL_GET_BALANCE_FACTOR(bal_h) > 0)
+    {
+        /* "Greater than" subtree is deeper. */
+
+        deep_h = AVL_GET_GREATER(bal_h, 1);
+
+        L_CHECK_READ_ERROR(AVL_NULL)
+
+        if (AVL_GET_BALANCE_FACTOR(deep_h) < 0)
+        {
+            int bf;
+
+            AVL_HANDLE old_h = bal_h;
+            bal_h = AVL_GET_LESS(deep_h, 1);
+            L_CHECK_READ_ERROR(AVL_NULL)
+            AVL_SET_GREATER(old_h, AVL_GET_LESS(bal_h, 1))
+            AVL_SET_LESS(deep_h, AVL_GET_GREATER(bal_h, 1))
+            AVL_SET_LESS(bal_h, old_h)
+            AVL_SET_GREATER(bal_h, deep_h)
+
+            bf = AVL_GET_BALANCE_FACTOR(bal_h);
+
+            if (bf != 0)
+            {
+                if (bf > 0)
+                {
+                    AVL_SET_BALANCE_FACTOR(old_h, -1)
+                    AVL_SET_BALANCE_FACTOR(deep_h, 0)
+                }
+                else
+                {
+                    AVL_SET_BALANCE_FACTOR(deep_h, 1)
+                    AVL_SET_BALANCE_FACTOR(old_h, 0)
+                }
+
+                AVL_SET_BALANCE_FACTOR(bal_h, 0)
+            }
+            else
+            {
+                AVL_SET_BALANCE_FACTOR(old_h, 0)
+                AVL_SET_BALANCE_FACTOR(deep_h, 0)
+            }
+        }
+        else
+        {
+            AVL_SET_GREATER(bal_h, AVL_GET_LESS(deep_h, 0))
+            AVL_SET_LESS(deep_h, bal_h)
+
+            if (AVL_GET_BALANCE_FACTOR(deep_h) == 0)
+            {
+                AVL_SET_BALANCE_FACTOR(deep_h, -1)
+                AVL_SET_BALANCE_FACTOR(bal_h, 1)
+            }
+            else
+            {
+                AVL_SET_BALANCE_FACTOR(deep_h, 0)
+                AVL_SET_BALANCE_FACTOR(bal_h, 0)
+            }
+
+            bal_h = deep_h;
+        }
+    }
+    else
+    {
+        /* "Less than" subtree is deeper. */
+
+        deep_h = AVL_GET_LESS(bal_h, 1);
+        L_CHECK_READ_ERROR(AVL_NULL)
+
+        if (AVL_GET_BALANCE_FACTOR(deep_h) > 0)
+        {
+            int bf;
+            AVL_HANDLE old_h = bal_h;
+            bal_h = AVL_GET_GREATER(deep_h, 1);
+            L_CHECK_READ_ERROR(AVL_NULL)
+            AVL_SET_LESS(old_h, AVL_GET_GREATER(bal_h, 0))
+            AVL_SET_GREATER(deep_h, AVL_GET_LESS(bal_h, 0))
+            AVL_SET_GREATER(bal_h, old_h)
+            AVL_SET_LESS(bal_h, deep_h)
+
+            bf = AVL_GET_BALANCE_FACTOR(bal_h);
+
+            if (bf != 0)
+            {
+                if (bf < 0)
+                {
+                    AVL_SET_BALANCE_FACTOR(old_h, 1)
+                    AVL_SET_BALANCE_FACTOR(deep_h, 0)
+                }
+                else
+                {
+                    AVL_SET_BALANCE_FACTOR(deep_h, -1)
+                    AVL_SET_BALANCE_FACTOR(old_h, 0)
+                }
+
+                AVL_SET_BALANCE_FACTOR(bal_h, 0)
+            }
+            else
+            {
+                AVL_SET_BALANCE_FACTOR(old_h, 0)
+                AVL_SET_BALANCE_FACTOR(deep_h, 0)
+            }
+        }
+        else
+        {
+            AVL_SET_LESS(bal_h, AVL_GET_GREATER(deep_h, 0))
+            AVL_SET_GREATER(deep_h, bal_h)
+
+            if (AVL_GET_BALANCE_FACTOR(deep_h) == 0)
+            {
+                AVL_SET_BALANCE_FACTOR(deep_h, 1)
+                AVL_SET_BALANCE_FACTOR(bal_h, -1)
+            }
+            else
+            {
+                AVL_SET_BALANCE_FACTOR(deep_h, 0)
+                AVL_SET_BALANCE_FACTOR(bal_h, 0)
+            }
+
+            bal_h = deep_h;
+        }
+    }
+
+    return(bal_h);
+}
+
+L_SC AVL_HANDLE L_(insert)(L_(avl) *l_tree, AVL_HANDLE h)
+{
+    AVL_SET_LESS(h, AVL_NULL)
+    AVL_SET_GREATER(h, AVL_NULL)
+    AVL_SET_BALANCE_FACTOR(h, 0)
+
+    if (l_tree->root == AVL_NULL)
+        l_tree->root = h;
+    else
+    {
+        /* Last unbalanced node encountered in search for insertion point. */
+        AVL_HANDLE unbal = AVL_NULL;
+        /* Parent of last unbalanced node. */
+        AVL_HANDLE parent_unbal = AVL_NULL;
+        /* Balance factor of last unbalanced node. */
+        int unbal_bf;
+
+        /* Zero-based depth in tree. */
+        unsigned depth = 0, unbal_depth = 0;
+
+        /* Records a path into the tree.  If bit n is true, indicates
+        ** take greater branch from the nth node in the path, otherwise
+        ** take the less branch.  bit 0 gives branch from root, and
+        ** so on. */
+        L_BIT_ARR_DEFN(branch)
+
+        AVL_HANDLE hh = l_tree->root;
+        AVL_HANDLE parent = AVL_NULL;
+        int cmp;
+
+        do
+        {
+            if (AVL_GET_BALANCE_FACTOR(hh) != 0)
+            {
+                unbal = hh;
+                parent_unbal = parent;
+                unbal_depth = depth;
+            }
+
+            cmp = AVL_COMPARE_NODE_NODE(h, hh);
+
+            if (cmp == 0)
+                /* Duplicate key. */
+                return(hh);
+
+            parent = hh;
+
+            if (cmp > 0)
+            {
+                hh = AVL_GET_GREATER(hh, 1);
+                L_BIT_ARR_1(branch, depth)
+            }
+            else
+            {
+                hh = AVL_GET_LESS(hh, 1);
+                L_BIT_ARR_0(branch, depth)
+            }
+
+            L_CHECK_READ_ERROR(AVL_NULL)
+            depth++;
+        }
+        while (hh != AVL_NULL);
+
+        /*  Add node to insert as leaf of tree. */
+        if (cmp < 0)
+            AVL_SET_LESS(parent, h)
+            else
+                AVL_SET_GREATER(parent, h)
+
+                depth = unbal_depth;
+
+        if (unbal == AVL_NULL)
+            hh = l_tree->root;
+        else
+        {
+            cmp = L_BIT_ARR_VAL(branch, depth) ? 1 : -1;
+            depth++;
+            unbal_bf = AVL_GET_BALANCE_FACTOR(unbal);
+
+            if (cmp < 0)
+                unbal_bf--;
+            else  /* cmp > 0 */
+                unbal_bf++;
+
+            hh = cmp < 0 ? AVL_GET_LESS(unbal, 1) : AVL_GET_GREATER(unbal, 1);
+            L_CHECK_READ_ERROR(AVL_NULL)
+
+            if ((unbal_bf != -2) && (unbal_bf != 2))
+            {
+                /* No rebalancing of tree is necessary. */
+                AVL_SET_BALANCE_FACTOR(unbal, unbal_bf)
+                unbal = AVL_NULL;
+            }
+        }
+
+        if (hh != AVL_NULL)
+            while (h != hh)
+            {
+                cmp = L_BIT_ARR_VAL(branch, depth) ? 1 : -1;
+                depth++;
+
+                if (cmp < 0)
+                {
+                    AVL_SET_BALANCE_FACTOR(hh, -1)
+                    hh = AVL_GET_LESS(hh, 1);
+                }
+                else /* cmp > 0 */
+                {
+                    AVL_SET_BALANCE_FACTOR(hh, 1)
+                    hh = AVL_GET_GREATER(hh, 1);
+                }
+
+                L_CHECK_READ_ERROR(AVL_NULL)
+            }
+
+        if (unbal != AVL_NULL)
+        {
+            unbal = L_(balance)(L_BALANCE_PARAM_CALL_PREFIX unbal);
+            L_CHECK_READ_ERROR(AVL_NULL)
+
+            if (parent_unbal == AVL_NULL)
+                l_tree->root = unbal;
+            else
+            {
+                depth = unbal_depth - 1;
+                cmp = L_BIT_ARR_VAL(branch, depth) ? 1 : -1;
+
+                if (cmp < 0)
+                    AVL_SET_LESS(parent_unbal, unbal)
+                    else  /* cmp > 0 */
+                        AVL_SET_GREATER(parent_unbal, unbal)
+                    }
+        }
+
+    }
+
+    return(h);
+}
+
+#endif
+
+#if (L_IMPL_MASK & AVL_IMPL_SEARCH)
+
+L_SC AVL_HANDLE L_(search)(L_(avl) *l_tree, AVL_KEY k, avl_search_type st)
+{
+    int cmp, target_cmp;
+    AVL_HANDLE match_h = AVL_NULL;
+    AVL_HANDLE h = l_tree->root;
+
+    if (st & AVL_LESS)
+        target_cmp = 1;
+    else if (st & AVL_GREATER)
+        target_cmp = -1;
+    else
+        target_cmp = 0;
+
+    while (h != AVL_NULL)
+    {
+        cmp = AVL_COMPARE_KEY_NODE(k, h);
+
+        if (cmp == 0)
+        {
+            if (st & AVL_EQUAL)
+            {
+                match_h = h;
+                break;
+            }
+
+            cmp = -target_cmp;
+        }
+        else if (target_cmp != 0)
+            if (!((cmp ^ target_cmp) & L_MASK_HIGH_BIT))
+                /* cmp and target_cmp are both positive or both negative. */
+                match_h = h;
+
+        h = cmp < 0 ? AVL_GET_LESS(h, 1) : AVL_GET_GREATER(h, 1);
+        L_CHECK_READ_ERROR(AVL_NULL)
+    }
+
+    return(match_h);
+}
+
+#endif
+
+#if (L_IMPL_MASK & AVL_IMPL_SEARCH_LEAST)
+
+L_SC AVL_HANDLE L_(search_least)(L_(avl) *l_tree)
+{
+    AVL_HANDLE h = l_tree->root;
+    AVL_HANDLE parent = AVL_NULL;
+
+    while (h != AVL_NULL)
+    {
+        parent = h;
+        h = AVL_GET_LESS(h, 1);
+        L_CHECK_READ_ERROR(AVL_NULL)
+    }
+
+    return(parent);
+}
+
+#endif
+
+#if (L_IMPL_MASK & AVL_IMPL_SEARCH_GREATEST)
+
+L_SC AVL_HANDLE L_(search_greatest)(L_(avl) *l_tree)
+{
+    AVL_HANDLE h = l_tree->root;
+    AVL_HANDLE parent = AVL_NULL;
+
+    while (h != AVL_NULL)
+    {
+        parent = h;
+        h = AVL_GET_GREATER(h, 1);
+        L_CHECK_READ_ERROR(AVL_NULL)
+    }
+
+    return(parent);
+}
+
+#endif
+
+#if (L_IMPL_MASK & AVL_IMPL_REMOVE)
+
+/* Prototype of balance function (called by remove) in case not in
+** same compilation unit.
+*/
+L_SC AVL_HANDLE L_(balance)(L_BALANCE_PARAM_DECL_PREFIX AVL_HANDLE bal_h);
+
+L_SC AVL_HANDLE L_(remove)(L_(avl) *l_tree, AVL_KEY k)
+{
+    /* Zero-based depth in tree. */
+    unsigned depth = 0, rm_depth;
+
+    /* Records a path into the tree.  If bit n is true, indicates
+    ** take greater branch from the nth node in the path, otherwise
+    ** take the less branch.  bit 0 gives branch from root, and
+    ** so on. */
+    L_BIT_ARR_DEFN(branch)
+
+    AVL_HANDLE h = l_tree->root;
+    AVL_HANDLE parent = AVL_NULL;
+    AVL_HANDLE child;
+    AVL_HANDLE path;
+    int cmp, cmp_shortened_sub_with_path;
+    int reduced_depth;
+    int bf;
+    AVL_HANDLE rm;
+    AVL_HANDLE parent_rm;
+
+    for (; ;)
+    {
+        if (h == AVL_NULL)
+            /* No node in tree with given key. */
+            return(AVL_NULL);
+
+        cmp = AVL_COMPARE_KEY_NODE(k, h);
+
+        if (cmp == 0)
+            /* Found node to remove. */
+            break;
+
+        parent = h;
+
+        if (cmp > 0)
+        {
+            h = AVL_GET_GREATER(h, 1);
+            L_BIT_ARR_1(branch, depth)
+        }
+        else
+        {
+            h = AVL_GET_LESS(h, 1);
+            L_BIT_ARR_0(branch, depth)
+        }
+
+        L_CHECK_READ_ERROR(AVL_NULL)
+        depth++;
+        cmp_shortened_sub_with_path = cmp;
+    }
+
+    rm = h;
+    parent_rm = parent;
+    rm_depth = depth;
+
+    /* If the node to remove is not a leaf node, we need to get a
+    ** leaf node, or a node with a single leaf as its child, to put
+    ** in the place of the node to remove.  We will get the greatest
+    ** node in the less subtree (of the node to remove), or the least
+    ** node in the greater subtree.  We take the leaf node from the
+    ** deeper subtree, if there is one. */
+
+    if (AVL_GET_BALANCE_FACTOR(h) < 0)
+    {
+        child = AVL_GET_LESS(h, 1);
+        L_BIT_ARR_0(branch, depth)
+        cmp = -1;
+    }
+    else
+    {
+        child = AVL_GET_GREATER(h, 1);
+        L_BIT_ARR_1(branch, depth)
+        cmp = 1;
+    }
+
+    L_CHECK_READ_ERROR(AVL_NULL)
+    depth++;
+
+    if (child != AVL_NULL)
+    {
+        cmp = -cmp;
+
+        do
+        {
+            parent = h;
+            h = child;
+
+            if (cmp < 0)
+            {
+                child = AVL_GET_LESS(h, 1);
+                L_BIT_ARR_0(branch, depth)
+            }
+            else
+            {
+                child = AVL_GET_GREATER(h, 1);
+                L_BIT_ARR_1(branch, depth)
+            }
+
+            L_CHECK_READ_ERROR(AVL_NULL)
+            depth++;
+        }
+        while (child != AVL_NULL);
+
+        if (parent == rm)
+            /* Only went through do loop once.  Deleted node will be replaced
+            ** in the tree structure by one of its immediate children. */
+            cmp_shortened_sub_with_path = -cmp;
+        else
+            cmp_shortened_sub_with_path = cmp;
+
+        /* Get the handle of the opposite child, which may not be null. */
+        child = cmp > 0 ? AVL_GET_LESS(h, 0) : AVL_GET_GREATER(h, 0);
+    }
+
+    if (parent == AVL_NULL)
+        /* There were only 1 or 2 nodes in this tree. */
+        l_tree->root = child;
+    else if (cmp_shortened_sub_with_path < 0)
+        AVL_SET_LESS(parent, child)
+        else
+            AVL_SET_GREATER(parent, child)
+
+            /* "path" is the parent of the subtree being eliminated or reduced
+            ** from a depth of 2 to 1.  If "path" is the node to be removed, we
+            ** set path to the node we're about to poke into the position of the
+            ** node to be removed. */
+            path = parent == rm ? h : parent;
+
+    if (h != rm)
+    {
+        /* Poke in the replacement for the node to be removed. */
+        AVL_SET_LESS(h, AVL_GET_LESS(rm, 0))
+        AVL_SET_GREATER(h, AVL_GET_GREATER(rm, 0))
+        AVL_SET_BALANCE_FACTOR(h, AVL_GET_BALANCE_FACTOR(rm))
+
+        if (parent_rm == AVL_NULL)
+            l_tree->root = h;
+        else
+        {
+            depth = rm_depth - 1;
+
+            if (L_BIT_ARR_VAL(branch, depth))
+                AVL_SET_GREATER(parent_rm, h)
+                else
+                    AVL_SET_LESS(parent_rm, h)
+                }
+    }
+
+    if (path != AVL_NULL)
+    {
+        /* Create a temporary linked list from the parent of the path node
+        ** to the root node. */
+        h = l_tree->root;
+        parent = AVL_NULL;
+        depth = 0;
+
+        while (h != path)
+        {
+            if (L_BIT_ARR_VAL(branch, depth))
+            {
+                child = AVL_GET_GREATER(h, 1);
+                AVL_SET_GREATER(h, parent)
+            }
+            else
+            {
+                child = AVL_GET_LESS(h, 1);
+                AVL_SET_LESS(h, parent)
+            }
+
+            L_CHECK_READ_ERROR(AVL_NULL)
+            depth++;
+            parent = h;
+            h = child;
+        }
+
+        /* Climb from the path node to the root node using the linked
+        ** list, restoring the tree structure and rebalancing as necessary.
+        */
+        reduced_depth = 1;
+        cmp = cmp_shortened_sub_with_path;
+
+        for (; ;)
+        {
+            if (reduced_depth)
+            {
+                bf = AVL_GET_BALANCE_FACTOR(h);
+
+                if (cmp < 0)
+                    bf++;
+                else  /* cmp > 0 */
+                    bf--;
+
+                if ((bf == -2) || (bf == 2))
+                {
+                    h = L_(balance)(L_BALANCE_PARAM_CALL_PREFIX h);
+                    L_CHECK_READ_ERROR(AVL_NULL)
+                    bf = AVL_GET_BALANCE_FACTOR(h);
+                }
+                else
+                    AVL_SET_BALANCE_FACTOR(h, bf)
+                    reduced_depth = (bf == 0);
+            }
+
+            if (parent == AVL_NULL)
+                break;
+
+            child = h;
+            h = parent;
+            depth--;
+            cmp = L_BIT_ARR_VAL(branch, depth) ? 1 : -1;
+
+            if (cmp < 0)
+            {
+                parent = AVL_GET_LESS(h, 1);
+                AVL_SET_LESS(h, child)
+            }
+            else
+            {
+                parent = AVL_GET_GREATER(h, 1);
+                AVL_SET_GREATER(h, child)
+            }
+
+            L_CHECK_READ_ERROR(AVL_NULL)
+        }
+
+        l_tree->root = h;
+    }
+
+    return(rm);
+}
+
+#endif
+
+#if (L_IMPL_MASK & AVL_IMPL_SUBST)
+
+L_SC AVL_HANDLE L_(subst)(L_(avl) *l_tree, AVL_HANDLE new_node)
+{
+    AVL_HANDLE h = l_tree->root;
+    AVL_HANDLE parent = AVL_NULL;
+    int cmp, last_cmp;
+
+    /* Search for node already in tree with same key. */
+    for (; ;)
+    {
+        if (h == AVL_NULL)
+            /* No node in tree with same key as new node. */
+            return(AVL_NULL);
+
+        cmp = AVL_COMPARE_NODE_NODE(new_node, h);
+
+        if (cmp == 0)
+            /* Found the node to substitute new one for. */
+            break;
+
+        last_cmp = cmp;
+        parent = h;
+        h = cmp < 0 ? AVL_GET_LESS(h, 1) : AVL_GET_GREATER(h, 1);
+        L_CHECK_READ_ERROR(AVL_NULL)
+    }
+
+    /* Copy tree housekeeping fields from node in tree to new node. */
+    AVL_SET_LESS(new_node, AVL_GET_LESS(h, 0))
+    AVL_SET_GREATER(new_node, AVL_GET_GREATER(h, 0))
+    AVL_SET_BALANCE_FACTOR(new_node, AVL_GET_BALANCE_FACTOR(h))
+
+    if (parent == AVL_NULL)
+        /* New node is also new root. */
+        l_tree->root = new_node;
+    else
+    {
+        /* Make parent point to new node. */
+        if (last_cmp < 0)
+            AVL_SET_LESS(parent, new_node)
+            else
+                AVL_SET_GREATER(parent, new_node)
+            }
+
+    return(h);
+}
+
+#endif
+
+#ifdef AVL_BUILD_ITER_TYPE
+
+#if (L_IMPL_MASK & AVL_IMPL_BUILD)
+
+L_SC int L_(build)(
+    L_(avl) *l_tree, AVL_BUILD_ITER_TYPE p, L_SIZE num_nodes)
+{
+    /* Gives path to subtree being built.  If bit n is false, branch
+    ** less from the node at depth n, if true branch greater. */
+    L_BIT_ARR_DEFN(branch)
+
+    /* If bit n is true, then for the current subtree at depth n, its
+    ** greater subtree has one more node than its less subtree. */
+    L_BIT_ARR_DEFN(rem)
+
+    /* Depth of root node of current subtree. */
+    unsigned depth = 0;
+
+    /* Number of nodes in current subtree. */
+    L_SIZE num_sub = num_nodes;
+
+    /* The algorithm relies on a stack of nodes whose less subtree has
+    ** been built, but whose greater subtree has not yet been built.
+    ** The stack is implemented as linked list.  The nodes are linked
+    ** together by having the "greater" handle of a node set to the
+    ** next node in the list.  "less_parent" is the handle of the first
+    ** node in the list. */
+    AVL_HANDLE less_parent = AVL_NULL;
+
+    /* h is root of current subtree, child is one of its children. */
+    AVL_HANDLE h;
+    AVL_HANDLE child;
+
+    if (num_nodes == 0)
+    {
+        l_tree->root = AVL_NULL;
+        return(1);
+    }
+
+    for (; ;)
+    {
+        while (num_sub > 2)
+        {
+            /* Subtract one for root of subtree. */
+            num_sub--;
+
+            if (num_sub & 1)
+                L_BIT_ARR_1(rem, depth)
+                else
+                    L_BIT_ARR_0(rem, depth)
+                    L_BIT_ARR_0(branch, depth)
+                    depth++;
+
+            num_sub >>= 1;
+        }
+
+        if (num_sub == 2)
+        {
+            /* Build a subtree with two nodes, slanting to greater.
+            ** I arbitrarily chose to always have the extra node in the
+            ** greater subtree when there is an odd number of nodes to
+            ** split between the two subtrees. */
+
+            h = AVL_BUILD_ITER_VAL(p);
+            L_CHECK_READ_ERROR(0)
+            AVL_BUILD_ITER_INCR(p)
+            child = AVL_BUILD_ITER_VAL(p);
+            L_CHECK_READ_ERROR(0)
+            AVL_BUILD_ITER_INCR(p)
+            AVL_SET_LESS(child, AVL_NULL)
+            AVL_SET_GREATER(child, AVL_NULL)
+            AVL_SET_BALANCE_FACTOR(child, 0)
+            AVL_SET_GREATER(h, child)
+            AVL_SET_LESS(h, AVL_NULL)
+            AVL_SET_BALANCE_FACTOR(h, 1)
+        }
+        else  /* num_sub == 1 */
+        {
+            /* Build a subtree with one node. */
+
+            h = AVL_BUILD_ITER_VAL(p);
+            L_CHECK_READ_ERROR(0)
+            AVL_BUILD_ITER_INCR(p)
+            AVL_SET_LESS(h, AVL_NULL)
+            AVL_SET_GREATER(h, AVL_NULL)
+            AVL_SET_BALANCE_FACTOR(h, 0)
+        }
+
+        while (depth)
+        {
+            depth--;
+
+            if (!L_BIT_ARR_VAL(branch, depth))
+                /* We've completed a less subtree. */
+                break;
+
+            /* We've completed a greater subtree, so attach it to
+            ** its parent (that is less than it).  We pop the parent
+            ** off the stack of less parents. */
+            child = h;
+            h = less_parent;
+            less_parent = AVL_GET_GREATER(h, 1);
+            L_CHECK_READ_ERROR(0)
+            AVL_SET_GREATER(h, child)
+            /* num_sub = 2 * (num_sub - rem[depth]) + rem[depth] + 1 */
+            num_sub <<= 1;
+            num_sub += L_BIT_ARR_VAL(rem, depth) ? 0 : 1;
+
+            if (num_sub & (num_sub - 1))
+                /* num_sub is not a power of 2. */
+                AVL_SET_BALANCE_FACTOR(h, 0)
+                else
+                    /* num_sub is a power of 2. */
+                    AVL_SET_BALANCE_FACTOR(h, 1)
+                }
+
+        if (num_sub == num_nodes)
+            /* We've completed the full tree. */
+            break;
+
+        /* The subtree we've completed is the less subtree of the
+        ** next node in the sequence. */
+
+        child = h;
+        h = AVL_BUILD_ITER_VAL(p);
+        L_CHECK_READ_ERROR(0)
+        AVL_BUILD_ITER_INCR(p)
+        AVL_SET_LESS(h, child)
+
+        /* Put h into stack of less parents. */
+        AVL_SET_GREATER(h, less_parent)
+        less_parent = h;
+
+        /* Proceed to creating greater than subtree of h. */
+        L_BIT_ARR_1(branch, depth)
+        num_sub += L_BIT_ARR_VAL(rem, depth) ? 1 : 0;
+        depth++;
+
+    } /* end for ( ; ; ) */
+
+    l_tree->root = h;
+
+    return(1);
+}
+
+#endif
+
+#endif
+
+#if (L_IMPL_MASK & AVL_IMPL_INIT_ITER)
+
+/* Initialize depth to invalid value, to indicate iterator is
+** invalid.   (Depth is zero-base.)  It's not necessary to initialize
+** iterators prior to passing them to the "start" function.
+*/
+L_SC void L_(init_iter)(L_(iter) *iter)
+{
+    iter->depth = ~0;
+}
+
+#endif
+
+#ifdef AVL_READ_ERRORS_HAPPEN
+
+#define L_CHECK_READ_ERROR_INV_DEPTH \
+    { if (AVL_READ_ERROR) { iter->depth = ~0; return; } }
+
+#else
+
+#define L_CHECK_READ_ERROR_INV_DEPTH
+
+#endif
+
+#if (L_IMPL_MASK & AVL_IMPL_START_ITER)
+
+L_SC void L_(start_iter)(
+    L_(avl) *l_tree, L_(iter) *iter, AVL_KEY k, avl_search_type st)
+{
+    AVL_HANDLE h = l_tree->root;
+    unsigned d = 0;
+    int cmp, target_cmp;
+
+    /* Save the tree that we're going to iterate through in a
+    ** member variable. */
+    iter->tree_ = l_tree;
+
+    iter->depth = ~0;
+
+    if (h == AVL_NULL)
+        /* Tree is empty. */
+        return;
+
+    if (st & AVL_LESS)
+        /* Key can be greater than key of starting node. */
+        target_cmp = 1;
+    else if (st & AVL_GREATER)
+        /* Key can be less than key of starting node. */
+        target_cmp = -1;
+    else
+        /* Key must be same as key of starting node. */
+        target_cmp = 0;
+
+    for (; ;)
+    {
+        cmp = AVL_COMPARE_KEY_NODE(k, h);
+
+        if (cmp == 0)
+        {
+            if (st & AVL_EQUAL)
+            {
+                /* Equal node was sought and found as starting node. */
+                iter->depth = d;
+                break;
+            }
+
+            cmp = -target_cmp;
+        }
+        else if (target_cmp != 0)
+            if (!((cmp ^ target_cmp) & L_MASK_HIGH_BIT))
+                /* cmp and target_cmp are both negative or both positive. */
+                iter->depth = d;
+
+        h = cmp < 0 ? AVL_GET_LESS(h, 1) : AVL_GET_GREATER(h, 1);
+        L_CHECK_READ_ERROR_INV_DEPTH
+
+        if (h == AVL_NULL)
+            break;
+
+        if (cmp > 0)
+            L_BIT_ARR_1(iter->branch, d)
+            else
+                L_BIT_ARR_0(iter->branch, d)
+                iter->path_h[d++] = h;
+    }
+}
+
+#endif
+
+#if (L_IMPL_MASK & AVL_IMPL_START_ITER_LEAST)
+
+L_SC void L_(start_iter_least)(L_(avl) *l_tree, L_(iter) *iter)
+{
+    AVL_HANDLE h = l_tree->root;
+
+    iter->tree_ = l_tree;
+
+    iter->depth = ~0;
+
+    L_BIT_ARR_ALL(iter->branch, 0)
+
+    while (h != AVL_NULL)
+    {
+        if (iter->depth != ~0)
+            iter->path_h[iter->depth] = h;
+
+        iter->depth++;
+        h = AVL_GET_LESS(h, 1);
+        L_CHECK_READ_ERROR_INV_DEPTH
+    }
+}
+
+#endif
+
+#if (L_IMPL_MASK & AVL_IMPL_START_ITER_GREATEST)
+
+L_SC void L_(start_iter_greatest)(L_(avl) *l_tree, L_(iter) *iter)
+{
+    AVL_HANDLE h = l_tree->root;
+
+    iter->tree_ = l_tree;
+
+    iter->depth = ~0;
+
+    L_BIT_ARR_ALL(iter->branch, 1)
+
+    while (h != AVL_NULL)
+    {
+        if (iter->depth != ~0)
+            iter->path_h[iter->depth] = h;
+
+        iter->depth++;
+        h = AVL_GET_GREATER(h, 1);
+        L_CHECK_READ_ERROR_INV_DEPTH
+    }
+}
+
+#endif
+
+#if (L_IMPL_MASK & AVL_IMPL_GET_ITER)
+
+L_SC AVL_HANDLE L_(get_iter)(L_(iter) *iter)
+{
+    if (iter->depth == ~0)
+        return(AVL_NULL);
+
+    return(iter->depth == 0 ?
+           iter->tree_->root : iter->path_h[iter->depth - 1]);
+}
+
+#endif
+
+#if (L_IMPL_MASK & AVL_IMPL_INCR_ITER)
+
+L_SC void L_(incr_iter)(L_(iter) *iter)
+{
+#define l_tree (iter->tree_)
+
+    if (iter->depth != ~0)
+    {
+        AVL_HANDLE h =
+            AVL_GET_GREATER((iter->depth == 0 ?
+                             iter->tree_->root : iter->path_h[iter->depth - 1]), 1);
+        L_CHECK_READ_ERROR_INV_DEPTH
+
+        if (h == AVL_NULL)
+            do
+            {
+                if (iter->depth == 0)
+                {
+                    iter->depth = ~0;
+                    break;
+                }
+
+                iter->depth--;
+            }
+            while (L_BIT_ARR_VAL(iter->branch, iter->depth));
+        else
+        {
+            L_BIT_ARR_1(iter->branch, iter->depth)
+            iter->path_h[iter->depth++] = h;
+
+            for (; ;)
+            {
+                h = AVL_GET_LESS(h, 1);
+                L_CHECK_READ_ERROR_INV_DEPTH
+
+                if (h == AVL_NULL)
+                    break;
+
+                L_BIT_ARR_0(iter->branch, iter->depth)
+                iter->path_h[iter->depth++] = h;
+            }
+        }
+    }
+
+#undef l_tree
+}
+
+#endif
+
+#if (L_IMPL_MASK & AVL_IMPL_DECR_ITER)
+
+L_SC void L_(decr_iter)(L_(iter) *iter)
+{
+#define l_tree (iter->tree_)
+
+    if (iter->depth != ~0)
+    {
+        AVL_HANDLE h =
+            AVL_GET_LESS((iter->depth == 0 ?
+                          iter->tree_->root : iter->path_h[iter->depth - 1]), 1);
+        L_CHECK_READ_ERROR_INV_DEPTH
+
+        if (h == AVL_NULL)
+            do
+            {
+                if (iter->depth == 0)
+                {
+                    iter->depth = ~0;
+                    break;
+                }
+
+                iter->depth--;
+            }
+            while (!L_BIT_ARR_VAL(iter->branch, iter->depth));
+        else
+        {
+            L_BIT_ARR_0(iter->branch, iter->depth)
+            iter->path_h[iter->depth++] = h;
+
+            for (; ;)
+            {
+                h = AVL_GET_GREATER(h, 1);
+                L_CHECK_READ_ERROR_INV_DEPTH
+
+                if (h == AVL_NULL)
+                    break;
+
+                L_BIT_ARR_1(iter->branch, iter->depth)
+                iter->path_h[iter->depth++] = h;
+            }
+        }
+    }
+
+#undef l_tree
+}
+
+#endif
+
+/* Tidy up the preprocessor symbol name space. */
+#undef L_
+#undef L_EST_LONG_BIT
+#undef L_SIZE
+#undef L_MASK_HIGH_BIT
+#undef L_LONG_BIT
+#undef L_BIT_ARR_DEFN
+#undef L_BIT_ARR_VAL
+#undef L_BIT_ARR_0
+#undef L_BIT_ARR_1
+#undef L_BIT_ARR_ALL
+#undef L_CHECK_READ_ERROR
+#undef L_CHECK_READ_ERROR_INV_DEPTH
+#undef L_BIT_ARR_LONGS
+#undef L_IMPL_MASK
+#undef L_CHECK_READ_ERROR
+#undef L_CHECK_READ_ERROR_INV_DEPTH
+#undef L_SC
+#undef L_BALANCE_PARAM_CALL_PREFIX
+#undef L_BALANCE_PARAM_DECL_PREFIX
diff --git a/vpx_mem/memory_manager/include/heapmm.h b/vpx_mem/memory_manager/include/heapmm.h
new file mode 100644 (file)
index 0000000..33004ca
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/* This code is in the public domain.
+** Version: 1.1  Author: Walt Karas
+*/
+
+/* External header file for Heap Memory Manager.  See documentation in
+** heapmm.html.
+*/
+
+#undef HMM_PROCESS
+
+/* Include once per configuration in a particular translation unit. */
+
+#ifndef HMM_CNFG_NUM
+
+/* Default configuration. */
+
+#ifndef HMM_INC_CNFG_DFLT
+#define HMM_INC_CNFG_DFLT
+#define HMM_PROCESS
+#endif
+
+#elif HMM_CNFG_NUM == 0
+
+/* Test configuration. */
+
+#ifndef HMM_INC_CNFG_0
+#define HMM_INC_CNFG_0
+#define HMM_PROCESS
+#endif
+
+#elif HMM_CNFG_NUM == 1
+
+#ifndef HMM_INC_CNFG_1
+#define HMM_INC_CNFG_1
+#define HMM_PROCESS
+#endif
+
+#elif HMM_CNFG_NUM == 2
+
+#ifndef HMM_INC_CNFG_2
+#define HMM_INC_CNFG_2
+#define HMM_PROCESS
+#endif
+
+#elif HMM_CNFG_NUM == 3
+
+#ifndef HMM_INC_CNFG_3
+#define HMM_INC_CNFG_3
+#define HMM_PROCESS
+#endif
+
+#elif HMM_CNFG_NUM == 4
+
+#ifndef HMM_INC_CNFG_4
+#define HMM_INC_CNFG_4
+#define HMM_PROCESS
+#endif
+
+#elif HMM_CNFG_NUM == 5
+
+#ifndef HMM_INC_CNFG_5
+#define HMM_INC_CNFG_5
+#define HMM_PROCESS
+#endif
+
+#endif
+
+#ifdef HMM_PROCESS
+
+#include "hmm_cnfg.h"
+
+/* Heap descriptor. */
+typedef struct HMM_UNIQUE(structure)
+{
+    /* private: */
+
+    /* Pointer to (payload of) root node in AVL tree.  This field should
+    ** really be the AVL tree descriptor (type avl_avl).  But (in the
+    ** instantiation of the AVL tree generic package used in package) the
+    ** AVL tree descriptor simply contains a pointer to the root.  So,
+    ** whenever a pointer to the AVL tree descriptor is needed, I use the
+    ** cast:
+    **
+    ** (avl_avl *) &(heap_desc->avl_tree_root)
+    **
+    ** (where heap_desc is a pointer to a heap descriptor).  This trick
+    ** allows me to avoid including cavl_if.h in this external header. */
+    void *avl_tree_root;
+
+    /* Pointer to first byte of last block freed, after any coalescing. */
+    void *last_freed;
+
+    /* public: */
+
+    HMM_UNIQUE(size_bau) num_baus_can_shrink;
+    void *end_of_shrinkable_chunk;
+}
+HMM_UNIQUE(descriptor);
+
+/* Prototypes for externally-callable functions. */
+
+void HMM_UNIQUE(init)(HMM_UNIQUE(descriptor) *desc);
+
+void *HMM_UNIQUE(alloc)(
+    HMM_UNIQUE(descriptor) *desc, HMM_UNIQUE(size_aau) num_addr_align_units);
+
+/* NOT YET IMPLEMENTED */
+void *HMM_UNIQUE(greedy_alloc)(
+    HMM_UNIQUE(descriptor) *desc, HMM_UNIQUE(size_aau) needed_addr_align_units,
+    HMM_UNIQUE(size_aau) coveted_addr_align_units);
+
+int HMM_UNIQUE(resize)(
+    HMM_UNIQUE(descriptor) *desc, void *mem,
+    HMM_UNIQUE(size_aau) num_addr_align_units);
+
+/* NOT YET IMPLEMENTED */
+int HMM_UNIQUE(greedy_resize)(
+    HMM_UNIQUE(descriptor) *desc, void *mem,
+    HMM_UNIQUE(size_aau) needed_addr_align_units,
+    HMM_UNIQUE(size_aau) coveted_addr_align_units);
+
+void HMM_UNIQUE(free)(HMM_UNIQUE(descriptor) *desc, void *mem);
+
+HMM_UNIQUE(size_aau) HMM_UNIQUE(true_size)(void *mem);
+
+HMM_UNIQUE(size_aau) HMM_UNIQUE(largest_available)(
+    HMM_UNIQUE(descriptor) *desc);
+
+void HMM_UNIQUE(new_chunk)(
+    HMM_UNIQUE(descriptor) *desc, void *start_of_chunk,
+    HMM_UNIQUE(size_bau) num_block_align_units);
+
+void HMM_UNIQUE(grow_chunk)(
+    HMM_UNIQUE(descriptor) *desc, void *end_of_chunk,
+    HMM_UNIQUE(size_bau) num_block_align_units);
+
+/* NOT YET IMPLEMENTED */
+void HMM_UNIQUE(shrink_chunk)(
+    HMM_UNIQUE(descriptor) *desc,
+    HMM_UNIQUE(size_bau) num_block_align_units);
+
+#endif /* defined HMM_PROCESS */
diff --git a/vpx_mem/memory_manager/include/hmm_cnfg.h b/vpx_mem/memory_manager/include/hmm_cnfg.h
new file mode 100644 (file)
index 0000000..30b9f50
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/* This code is in the public domain.
+** Version: 1.1  Author: Walt Karas
+*/
+
+/* Configure Heap Memory Manager for processor architecture, compiler,
+** and desired performance characteristics.  This file is included
+** by heapmm.h, so these definitions can be used by code external to
+** HMM.  You can change the default configuration, and/or create alternate
+** configuration(s).
+*/
+
+/* To allow for multiple configurations of HMM to be used in the same
+** compilation unit, undefine all preprocessor symbols that will be
+** defined below.
+*/
+#undef HMM_ADDR_ALIGN_UNIT
+#undef HMM_BLOCK_ALIGN_UNIT
+#undef HMM_UNIQUE
+#undef HMM_DESC_PARAM
+#undef HMM_SYM_TO_STRING
+#undef HMM_SYM_TO_STRING
+#undef HMM_AUDIT_FAIL
+
+/* Turn X into a string after one macro expansion pass of X.  This trick
+** works with both GCC and Visual C++. */
+#define HMM_SYM_TO_STRING(X) HMM_SYM_TO_STRING(X)
+#define HMM_SYM_TO_STRING(X) #X
+
+#ifndef HMM_CNFG_NUM
+
+/* Default configuration. */
+
+/* Use hmm_ prefix to avoid identifier conflicts. */
+#define HMM_UNIQUE(BASE) hmm_ ## BASE
+
+/* Number of bytes in an Address Alignment Unit (AAU). */
+//fwg
+//#define HMM_ADDR_ALIGN_UNIT sizeof(int)
+#define HMM_ADDR_ALIGN_UNIT 32
+
+/* Number of AAUs in a Block Alignment Unit (BAU). */
+#define HMM_BLOCK_ALIGN_UNIT 1
+
+/* Type of unsigned integer big enough to hold the size of a Block in AAUs. */
+typedef unsigned long HMM_UNIQUE(size_aau);
+
+/* Type of unsigned integer big enough to hold the size of a Block/Chunk
+** in BAUs.  The high bit will be robbed. */
+typedef unsigned long HMM_UNIQUE(size_bau);
+
+void hmm_dflt_abort(const char *, const char *);
+
+/* Actions upon a self-audit failure.  Must expand to a single complete
+** statement.  If you remove the definition of this macro, no self-auditing
+** will be performed. */
+#define HMM_AUDIT_FAIL \
+    hmm_dflt_abort(__FILE__, HMM_SYM_TO_STRING(__LINE__));
+
+#elif HMM_CNFG_NUM == 0
+
+/* Definitions for testing. */
+
+#define HMM_UNIQUE(BASE) thmm_ ## BASE
+
+#define HMM_ADDR_ALIGN_UNIT sizeof(int)
+
+#define HMM_BLOCK_ALIGN_UNIT 3
+
+typedef unsigned HMM_UNIQUE(size_aau);
+
+typedef unsigned short HMM_UNIQUE(size_bau);
+
+/* Under this test setup, a long jump is done if there is a self-audit
+** failure.
+*/
+
+extern jmp_buf HMM_UNIQUE(jmp_buf);
+extern const char *HMM_UNIQUE(fail_file);
+extern unsigned HMM_UNIQUE(fail_line);
+
+#define HMM_AUDIT_FAIL \
+    { HMM_UNIQUE(fail_file) = __FILE__; HMM_UNIQUE(fail_line) = __LINE__; \
+        longjmp(HMM_UNIQUE(jmp_buf), 1); }
+
+#elif HMM_CNFG_NUM == 1
+
+/* Put configuration 1 definitions here (if there is a configuration 1). */
+
+#elif HMM_CNFG_NUM == 2
+
+/* Put configuration 2 definitions here. */
+
+#elif HMM_CNFG_NUM == 3
+
+/* Put configuration 3 definitions here. */
+
+#elif HMM_CNFG_NUM == 4
+
+/* Put configuration 4 definitions here. */
+
+#elif HMM_CNFG_NUM == 5
+
+/* Put configuration 5 definitions here. */
+
+#endif
diff --git a/vpx_mem/memory_manager/include/hmm_intrnl.h b/vpx_mem/memory_manager/include/hmm_intrnl.h
new file mode 100644 (file)
index 0000000..5d62abc
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/* This code is in the public domain.
+** Version: 1.1  Author: Walt Karas
+*/
+
+#ifndef HMM_INTRNL_H_
+#define HMM_INTRNL_H_
+
+#ifdef __uClinux__
+# include <lddk.h>
+#endif
+
+#include "heapmm.h"
+
+#define U(BASE) HMM_UNIQUE(BASE)
+
+/* Mask of high bit of variable of size_bau type. */
+#define HIGH_BIT_BAU_SIZE \
+    ((U(size_bau)) ~ (((U(size_bau)) ~ (U(size_bau)) 0) >> 1))
+
+/* Add a given number of AAUs to pointer. */
+#define AAUS_FORWARD(PTR, AAU_OFFSET) \
+    (((char *) (PTR)) + ((AAU_OFFSET) * ((U(size_aau)) HMM_ADDR_ALIGN_UNIT)))
+
+/* Subtract a given number of AAUs from pointer. */
+#define AAUS_BACKWARD(PTR, AAU_OFFSET) \
+    (((char *) (PTR)) - ((AAU_OFFSET) * ((U(size_aau)) HMM_ADDR_ALIGN_UNIT)))
+
+/* Add a given number of BAUs to a pointer. */
+#define BAUS_FORWARD(PTR, BAU_OFFSET) \
+    AAUS_FORWARD((PTR), (BAU_OFFSET) * ((U(size_aau)) HMM_BLOCK_ALIGN_UNIT))
+
+/* Subtract a given number of BAUs to a pointer. */
+#define BAUS_BACKWARD(PTR, BAU_OFFSET) \
+    AAUS_BACKWARD((PTR), (BAU_OFFSET) * ((U(size_aau)) HMM_BLOCK_ALIGN_UNIT))
+
+typedef struct head_struct
+{
+    /* Sizes in Block Alignment Units. */
+    HMM_UNIQUE(size_bau) previous_block_size, block_size;
+}
+head_record;
+
+typedef struct ptr_struct
+{
+    struct ptr_struct *self, *prev, *next;
+}
+ptr_record;
+
+/* Divide and round up any fraction to the next whole number. */
+#define DIV_ROUND_UP(NUMER, DENOM) (((NUMER) + (DENOM) - 1) / (DENOM))
+
+/* Number of AAUs in a block head. */
+#define HEAD_AAUS DIV_ROUND_UP(sizeof(head_record), HMM_ADDR_ALIGN_UNIT)
+
+/* Number of AAUs in a block pointer record. */
+#define PTR_RECORD_AAUS DIV_ROUND_UP(sizeof(ptr_record), HMM_ADDR_ALIGN_UNIT)
+
+/* Number of BAUs in a dummy end record (at end of chunk). */
+#define DUMMY_END_BLOCK_BAUS DIV_ROUND_UP(HEAD_AAUS, HMM_BLOCK_ALIGN_UNIT)
+
+/* Minimum number of BAUs in a block (allowing room for the pointer record. */
+#define MIN_BLOCK_BAUS \
+    DIV_ROUND_UP(HEAD_AAUS + PTR_RECORD_AAUS, HMM_BLOCK_ALIGN_UNIT)
+
+/* Return number of BAUs in block (masking off high bit containing block
+** status). */
+#define BLOCK_BAUS(HEAD_PTR) \
+    (((head_record *) (HEAD_PTR))->block_size & ~HIGH_BIT_BAU_SIZE)
+
+/* Return number of BAUs in previous block (masking off high bit containing
+** block status). */
+#define PREV_BLOCK_BAUS(HEAD_PTR) \
+    (((head_record *) (HEAD_PTR))->previous_block_size & ~HIGH_BIT_BAU_SIZE)
+
+/* Set number of BAUs in previous block, preserving high bit containing
+** block status. */
+#define SET_PREV_BLOCK_BAUS(HEAD_PTR, N_BAUS) \
+    { register head_record *h_ptr = (head_record *) (HEAD_PTR); \
+        h_ptr->previous_block_size &= HIGH_BIT_BAU_SIZE; \
+        h_ptr->previous_block_size |= (N_BAUS); }
+
+/* Convert pointer to pointer record of block to pointer to block's head
+** record. */
+#define PTR_REC_TO_HEAD(PTR_REC_PTR) \
+    ((head_record *) AAUS_BACKWARD(PTR_REC_PTR, HEAD_AAUS))
+
+/* Convert pointer to block head to pointer to block's pointer record. */
+#define HEAD_TO_PTR_REC(HEAD_PTR) \
+    ((ptr_record *) AAUS_FORWARD(HEAD_PTR, HEAD_AAUS))
+
+/* Returns non-zero if block is allocated. */
+#define IS_BLOCK_ALLOCATED(HEAD_PTR) \
+    (((((head_record *) (HEAD_PTR))->block_size | \
+       ((head_record *) (HEAD_PTR))->previous_block_size) & \
+      HIGH_BIT_BAU_SIZE) == 0)
+
+#define MARK_BLOCK_ALLOCATED(HEAD_PTR) \
+    { register head_record *h_ptr = (head_record *) (HEAD_PTR); \
+        h_ptr->block_size &= ~HIGH_BIT_BAU_SIZE; \
+        h_ptr->previous_block_size &= ~HIGH_BIT_BAU_SIZE; }
+
+/* Mark a block as free when it is not the first block in a bin (and
+** therefore not a node in the AVL tree). */
+#define MARK_SUCCESSIVE_BLOCK_IN_FREE_BIN(HEAD_PTR) \
+    { register head_record *h_ptr = (head_record *) (HEAD_PTR); \
+        h_ptr->block_size |= HIGH_BIT_BAU_SIZE; }
+
+/* Prototypes for internal functions implemented in one file and called in
+** another.
+*/
+
+void U(into_free_collection)(U(descriptor) *desc, head_record *head_ptr);
+
+void U(out_of_free_collection)(U(descriptor) *desc, head_record *head_ptr);
+
+void *U(alloc_from_bin)(
+    U(descriptor) *desc, ptr_record *bin_front_ptr, U(size_bau) n_baus);
+
+#ifdef HMM_AUDIT_FAIL
+
+/* Simply contains a reference to the HMM_AUDIT_FAIL macro and a
+** dummy return. */
+int U(audit_block_fail_dummy_return)(void);
+
+
+/* Auditing a block consists of checking that the size in its head
+** matches the previous block size in the head of the next block. */
+#define AUDIT_BLOCK_AS_EXPR(HEAD_PTR) \
+    ((BLOCK_BAUS(HEAD_PTR) == \
+      PREV_BLOCK_BAUS(BAUS_FORWARD(HEAD_PTR, BLOCK_BAUS(HEAD_PTR)))) ? \
+     0 : U(audit_block_fail_dummy_return)())
+
+#define AUDIT_BLOCK(HEAD_PTR) \
+    { void *h_ptr = (HEAD_PTR); AUDIT_BLOCK_AS_EXPR(h_ptr); }
+
+#endif
+
+/* Interface to AVL tree generic package instantiation. */
+
+#define AVL_UNIQUE(BASE) U(avl_ ## BASE)
+
+#define AVL_HANDLE ptr_record *
+
+#define AVL_KEY U(size_bau)
+
+#define AVL_MAX_DEPTH 64
+
+#include "cavl_if.h"
+
+#endif /* Include once. */
diff --git a/vpx_mem/vpx_mem.c b/vpx_mem/vpx_mem.c
new file mode 100644 (file)
index 0000000..eade432
--- /dev/null
@@ -0,0 +1,722 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#define __VPX_MEM_C__
+
+#include "vpx_mem.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "include/vpx_mem_intrnl.h"
+
+#if CONFIG_MEM_TRACKER
+#ifndef VPX_NO_GLOBALS
+static unsigned long g_alloc_count = 0;
+#else
+#include "vpx_global_handling.h"
+#define g_alloc_count vpxglobalm(vpxmem,g_alloc_count)
+#endif
+#endif
+
+#if CONFIG_MEM_MANAGER
+# include "heapmm.h"
+# include "hmm_intrnl.h"
+
+# define SHIFT_HMM_ADDR_ALIGN_UNIT 5
+# define TOTAL_MEMORY_TO_ALLOCATE  20971520 /* 20 * 1024 * 1024 */
+
+# define MM_DYNAMIC_MEMORY 1
+# if MM_DYNAMIC_MEMORY
+static unsigned char *g_p_mng_memory_raw = NULL;
+static unsigned char *g_p_mng_memory     = NULL;
+# else
+static unsigned char g_p_mng_memory[TOTAL_MEMORY_TO_ALLOCATE];
+# endif
+
+static size_t g_mm_memory_size = TOTAL_MEMORY_TO_ALLOCATE;
+
+static hmm_descriptor hmm_d;
+static int g_mng_memory_allocated = 0;
+
+static int vpx_mm_create_heap_memory();
+static void *vpx_mm_realloc(void *memblk, size_t size);
+#endif /*CONFIG_MEM_MANAGER*/
+
+#if USE_GLOBAL_FUNCTION_POINTERS
+struct GLOBAL_FUNC_POINTERS
+{
+    g_malloc_func g_malloc;
+    g_calloc_func g_calloc;
+    g_realloc_func g_realloc;
+    g_free_func g_free;
+    g_memcpy_func g_memcpy;
+    g_memset_func g_memset;
+    g_memmove_func g_memmove;
+} *g_func = NULL;
+
+# define VPX_MALLOC_L  g_func->g_malloc
+# define VPX_REALLOC_L g_func->g_realloc
+# define VPX_FREE_L    g_func->g_free
+# define VPX_MEMCPY_L  g_func->g_memcpy
+# define VPX_MEMSET_L  g_func->g_memset
+# define VPX_MEMMOVE_L g_func->g_memmove
+#else
+# define VPX_MALLOC_L  malloc
+# define VPX_REALLOC_L realloc
+# define VPX_FREE_L    free
+# define VPX_MEMCPY_L  memcpy
+# define VPX_MEMSET_L  memset
+# define VPX_MEMMOVE_L memmove
+#endif /* USE_GLOBAL_FUNCTION_POINTERS */
+
+unsigned int vpx_mem_get_version()
+{
+    unsigned int ver = ((unsigned int)(unsigned char)VPX_MEM_VERSION_CHIEF << 24 |
+                        (unsigned int)(unsigned char)VPX_MEM_VERSION_MAJOR << 16 |
+                        (unsigned int)(unsigned char)VPX_MEM_VERSION_MINOR << 8  |
+                        (unsigned int)(unsigned char)VPX_MEM_VERSION_PATCH);
+    return ver;
+}
+
+int vpx_mem_set_heap_size(size_t size)
+{
+    int ret = -1;
+
+#if CONFIG_MEM_MANAGER
+#if MM_DYNAMIC_MEMORY
+
+    if (!g_mng_memory_allocated && size)
+    {
+        g_mm_memory_size = size;
+        ret = 0;
+    }
+    else
+        ret = -3;
+
+#else
+    ret = -2;
+#endif
+#else
+    (void)size;
+#endif
+
+    return ret;
+}
+
+void *vpx_memalign(size_t align, size_t size)
+{
+    void *addr,
+         * x = NULL;
+
+#if CONFIG_MEM_MANAGER
+    int number_aau;
+
+    if (vpx_mm_create_heap_memory() < 0)
+    {
+        _P(printf("[vpx][mm] ERROR vpx_memalign() Couldn't create memory for Heap.\n");)
+    }
+
+    number_aau = ((size + align - 1 + ADDRESS_STORAGE_SIZE) >>
+                  SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
+
+    addr = hmm_alloc(&hmm_d, number_aau);
+#else
+    addr = VPX_MALLOC_L(size + align - 1 + ADDRESS_STORAGE_SIZE);
+#endif /*CONFIG_MEM_MANAGER*/
+
+    if (addr)
+    {
+        x = align_addr((unsigned char *)addr + ADDRESS_STORAGE_SIZE, (int)align);
+        /* save the actual malloc address */
+        ((size_t *)x)[-1] = (size_t)addr;
+    }
+
+    return x;
+}
+
+void *vpx_malloc(size_t size)
+{
+    return vpx_memalign(DEFAULT_ALIGNMENT, size);
+}
+
+void *vpx_calloc(size_t num, size_t size)
+{
+    void *x;
+
+    x = vpx_memalign(DEFAULT_ALIGNMENT, num * size);
+
+    if (x)
+        VPX_MEMSET_L(x, 0, num * size);
+
+    return x;
+}
+
+void *vpx_realloc(void *memblk, size_t size)
+{
+    void *addr,
+         * new_addr = NULL;
+    int align = DEFAULT_ALIGNMENT;
+
+    /*
+    The realloc() function changes the size of the object pointed to by
+    ptr to the size specified by size, and returns a pointer to the
+    possibly moved block. The contents are unchanged up to the lesser
+    of the new and old sizes. If ptr is null, realloc() behaves like
+    malloc() for the specified size. If size is zero (0) and ptr is
+    not a null pointer, the object pointed to is freed.
+    */
+    if (!memblk)
+        new_addr = vpx_malloc(size);
+    else if (!size)
+        vpx_free(memblk);
+    else
+    {
+        addr   = (void *)(((size_t *)memblk)[-1]);
+        memblk = NULL;
+
+#if CONFIG_MEM_MANAGER
+        new_addr = vpx_mm_realloc(addr, size + align + ADDRESS_STORAGE_SIZE);
+#else
+        new_addr = VPX_REALLOC_L(addr, size + align + ADDRESS_STORAGE_SIZE);
+#endif
+
+        if (new_addr)
+        {
+            addr = new_addr;
+            new_addr = (void *)(((size_t)
+                                 ((unsigned char *)new_addr + ADDRESS_STORAGE_SIZE) + (align - 1)) &
+                                (size_t) - align);
+            /* save the actual malloc address */
+            ((size_t *)new_addr)[-1] = (size_t)addr;
+        }
+    }
+
+    return new_addr;
+}
+
+void vpx_free(void *memblk)
+{
+    if (memblk)
+    {
+        void *addr = (void *)(((size_t *)memblk)[-1]);
+#if CONFIG_MEM_MANAGER
+        hmm_free(&hmm_d, addr);
+#else
+        VPX_FREE_L(addr);
+#endif
+    }
+}
+
+#if CONFIG_MEM_TRACKER
+void *xvpx_memalign(size_t align, size_t size, char *file, int line)
+{
+#if TRY_BOUNDS_CHECK
+    unsigned char *x_bounds;
+#endif
+
+    void *x;
+
+    if (g_alloc_count == 0)
+    {
+#if TRY_BOUNDS_CHECK
+        int i_rv = vpx_memory_tracker_init(BOUNDS_CHECK_PAD_SIZE, BOUNDS_CHECK_VALUE);
+#else
+        int i_rv = vpx_memory_tracker_init(0, 0);
+#endif
+
+        if (i_rv < 0)
+        {
+            _P(printf("ERROR xvpx_malloc MEM_TRACK_USAGE error vpx_memory_tracker_init().\n");)
+        }
+    }
+
+#if TRY_BOUNDS_CHECK
+    {
+        int i;
+        unsigned int tempme = BOUNDS_CHECK_VALUE;
+
+        x_bounds = vpx_memalign(align, size + (BOUNDS_CHECK_PAD_SIZE * 2));
+
+        if (x_bounds)
+        {
+            /*we're aligning the address twice here but to keep things
+              consistent we want to have the padding come before the stored
+              address so no matter what free function gets called we will
+              attempt to free the correct address*/
+            x_bounds = (unsigned char *)(((size_t *)x_bounds)[-1]);
+            x = align_addr(x_bounds + BOUNDS_CHECK_PAD_SIZE + ADDRESS_STORAGE_SIZE,
+                           (int)align);
+            /* save the actual malloc address */
+            ((size_t *)x)[-1] = (size_t)x_bounds;
+
+            for (i = 0; i < BOUNDS_CHECK_PAD_SIZE; i += sizeof(unsigned int))
+            {
+                VPX_MEMCPY_L(x_bounds + i, &tempme, sizeof(unsigned int));
+                VPX_MEMCPY_L((unsigned char *)x + size + i,
+                             &tempme, sizeof(unsigned int));
+            }
+        }
+        else
+            x = NULL;
+    }
+#else
+    x = vpx_memalign(align, size);
+#endif /*TRY_BOUNDS_CHECK*/
+
+    g_alloc_count++;
+
+    vpx_memory_tracker_add((size_t)x, (unsigned int)size, file, line, 1);
+
+    return x;
+}
+
+void *xvpx_malloc(size_t size, char *file, int line)
+{
+    return xvpx_memalign(DEFAULT_ALIGNMENT, size, file, line);
+}
+
+void *xvpx_calloc(size_t num, size_t size, char *file, int line)
+{
+    void *x = xvpx_memalign(DEFAULT_ALIGNMENT, num * size, file, line);
+
+    if (x)
+        VPX_MEMSET_L(x, 0, num * size);
+
+    return x;
+}
+
+void *xvpx_realloc(void *memblk, size_t size, char *file, int line)
+{
+    struct mem_block *p = NULL;
+    int orig_size = 0,
+        orig_line = 0;
+    char *orig_file = NULL;
+
+#if TRY_BOUNDS_CHECK
+    unsigned char *x_bounds = memblk ?
+                              (unsigned char *)(((size_t *)memblk)[-1]) :
+                              NULL;
+#endif
+
+    void *x;
+
+    if (g_alloc_count == 0)
+    {
+#if TRY_BOUNDS_CHECK
+
+        if (!vpx_memory_tracker_init(BOUNDS_CHECK_PAD_SIZE, BOUNDS_CHECK_VALUE))
+#else
+        if (!vpx_memory_tracker_init(0, 0))
+#endif
+        {
+            _P(printf("ERROR xvpx_malloc MEM_TRACK_USAGE error vpx_memory_tracker_init().\n");)
+        }
+    }
+
+    if ((p = vpx_memory_tracker_find((size_t)memblk)))
+    {
+        orig_size = p->size;
+        orig_file = p->file;
+        orig_line = p->line;
+    }
+
+#if TRY_BOUNDS_CHECK_ON_FREE
+    vpx_memory_tracker_check_integrity(file, line);
+#endif
+
+    /* have to do this regardless of success, because
+     * the memory that does get realloc'd may change
+     * the bounds values of this block
+     */
+    vpx_memory_tracker_remove((size_t)memblk);
+
+#if TRY_BOUNDS_CHECK
+    {
+        int i;
+        unsigned int tempme = BOUNDS_CHECK_VALUE;
+
+        x_bounds = vpx_realloc(memblk, size + (BOUNDS_CHECK_PAD_SIZE * 2));
+
+        if (x_bounds)
+        {
+            x_bounds = (unsigned char *)(((size_t *)x_bounds)[-1]);
+            x = align_addr(x_bounds + BOUNDS_CHECK_PAD_SIZE + ADDRESS_STORAGE_SIZE,
+                           (int)DEFAULT_ALIGNMENT);
+            /* save the actual malloc address */
+            ((size_t *)x)[-1] = (size_t)x_bounds;
+
+            for (i = 0; i < BOUNDS_CHECK_PAD_SIZE; i += sizeof(unsigned int))
+            {
+                VPX_MEMCPY_L(x_bounds + i, &tempme, sizeof(unsigned int));
+                VPX_MEMCPY_L((unsigned char *)x + size + i,
+                             &tempme, sizeof(unsigned int));
+            }
+        }
+        else
+            x = NULL;
+    }
+#else
+    x = vpx_realloc(memblk, size);
+#endif /*TRY_BOUNDS_CHECK*/
+
+    if (!memblk) ++g_alloc_count;
+
+    if (x)
+        vpx_memory_tracker_add((size_t)x, (unsigned int)size, file, line, 1);
+    else
+        vpx_memory_tracker_add((size_t)memblk, orig_size, orig_file, orig_line, 1);
+
+    return x;
+}
+
+void xvpx_free(void *p_address, char *file, int line)
+{
+#if TRY_BOUNDS_CHECK
+    unsigned char *p_bounds_address = (unsigned char *)p_address;
+    /*p_bounds_address -= BOUNDS_CHECK_PAD_SIZE;*/
+#endif
+
+#if !TRY_BOUNDS_CHECK_ON_FREE
+    (void)file;
+    (void)line;
+#endif
+
+    if (p_address)
+    {
+#if TRY_BOUNDS_CHECK_ON_FREE
+        vpx_memory_tracker_check_integrity(file, line);
+#endif
+
+        /* if the addr isn't found in the list, assume it was allocated via
+         * vpx_ calls not xvpx_, therefore it does not contain any padding
+         */
+        if (vpx_memory_tracker_remove((size_t)p_address) == -2)
+        {
+            p_bounds_address = p_address;
+            _P(fprintf(stderr, "[vpx_mem][xvpx_free] addr: %p not found in"
+                       " list; freed from file:%s"
+                       " line:%d\n", p_address, file, line));
+        }
+        else
+            --g_alloc_count;
+
+#if TRY_BOUNDS_CHECK
+        vpx_free(p_bounds_address);
+#else
+        vpx_free(p_address);
+#endif
+
+        if (!g_alloc_count)
+            vpx_memory_tracker_destroy();
+    }
+}
+
+#endif /*CONFIG_MEM_TRACKER*/
+
+#if CONFIG_MEM_CHECKS
+#if defined(VXWORKS)
+#include <task_lib.h> /*for task_delay()*/
+/* This function is only used to get a stack trace of the player
+object so we can se where we are having a problem. */
+static int get_my_tt(int task)
+{
+    tt(task);
+
+    return 0;
+}
+
+static void vx_sleep(int msec)
+{
+    int ticks_to_sleep = 0;
+
+    if (msec)
+    {
+        int msec_per_tick = 1000 / sys_clk_rate_get();
+
+        if (msec < msec_per_tick)
+            ticks_to_sleep++;
+        else
+            ticks_to_sleep = msec / msec_per_tick;
+    }
+
+    task_delay(ticks_to_sleep);
+}
+#endif
+#endif
+
+void *vpx_memcpy(void *dest, const void *source, size_t length)
+{
+#if CONFIG_MEM_CHECKS
+
+    if (((int)dest < 0x4000) || ((int)source < 0x4000))
+    {
+        _P(printf("WARNING: vpx_memcpy dest:0x%x source:0x%x len:%d\n", (int)dest, (int)source, length);)
+
+#if defined(VXWORKS)
+        sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
+
+        vx_sleep(10000);
+#endif
+    }
+
+#endif
+
+    return VPX_MEMCPY_L(dest, source, length);
+}
+
+void *vpx_memset(void *dest, int val, size_t length)
+{
+#if CONFIG_MEM_CHECKS
+
+    if ((int)dest < 0x4000)
+    {
+        _P(printf("WARNING: vpx_memset dest:0x%x val:%d len:%d\n", (int)dest, val, length);)
+
+#if defined(VXWORKS)
+        sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
+
+        vx_sleep(10000);
+#endif
+    }
+
+#endif
+
+    return VPX_MEMSET_L(dest, val, length);
+}
+
+void *vpx_memmove(void *dest, const void *src, size_t count)
+{
+#if CONFIG_MEM_CHECKS
+
+    if (((int)dest < 0x4000) || ((int)src < 0x4000))
+    {
+        _P(printf("WARNING: vpx_memmove dest:0x%x src:0x%x count:%d\n", (int)dest, (int)src, count);)
+
+#if defined(VXWORKS)
+        sp(get_my_tt, task_id_self(), 0, 0, 0, 0, 0, 0, 0, 0);
+
+        vx_sleep(10000);
+#endif
+    }
+
+#endif
+
+    return VPX_MEMMOVE_L(dest, src, count);
+}
+
+#if CONFIG_MEM_MANAGER
+
+static int vpx_mm_create_heap_memory()
+{
+    int i_rv = 0;
+
+    if (!g_mng_memory_allocated)
+    {
+#if MM_DYNAMIC_MEMORY
+        g_p_mng_memory_raw =
+            (unsigned char *)malloc(g_mm_memory_size + HMM_ADDR_ALIGN_UNIT);
+
+        if (g_p_mng_memory_raw)
+        {
+            g_p_mng_memory = (unsigned char *)((((unsigned int)g_p_mng_memory_raw) +
+                                                HMM_ADDR_ALIGN_UNIT - 1) &
+                                               -(int)HMM_ADDR_ALIGN_UNIT);
+
+            _P(printf("[vpx][mm] total memory size:%d g_p_mng_memory_raw:0x%x g_p_mng_memory:0x%x\n"
+                      , g_mm_memory_size + HMM_ADDR_ALIGN_UNIT
+                      , (unsigned int)g_p_mng_memory_raw
+                      , (unsigned int)g_p_mng_memory);)
+        }
+        else
+        {
+            _P(printf("[vpx][mm] Couldn't allocate memory:%d for vpx memory manager.\n"
+                      , g_mm_memory_size);)
+
+            i_rv = -1;
+        }
+
+        if (g_p_mng_memory)
+#endif
+        {
+            int chunk_size = 0;
+
+            g_mng_memory_allocated = 1;
+
+            hmm_init(&hmm_d);
+
+            chunk_size = g_mm_memory_size >> SHIFT_HMM_ADDR_ALIGN_UNIT;
+
+            chunk_size -= DUMMY_END_BLOCK_BAUS;
+
+            _P(printf("[vpx][mm] memory size:%d for vpx memory manager. g_p_mng_memory:0x%x  chunk_size:%d\n"
+                      , g_mm_memory_size
+                      , (unsigned int)g_p_mng_memory
+                      , chunk_size);)
+
+            hmm_new_chunk(&hmm_d, (void *)g_p_mng_memory, chunk_size);
+        }
+
+#if MM_DYNAMIC_MEMORY
+        else
+        {
+            _P(printf("[vpx][mm] Couldn't allocate memory:%d for vpx memory manager.\n"
+                      , g_mm_memory_size);)
+
+            i_rv = -1;
+        }
+
+#endif
+    }
+
+    return i_rv;
+}
+
+static void *vpx_mm_realloc(void *memblk, size_t size)
+{
+    void *p_ret = NULL;
+
+    if (vpx_mm_create_heap_memory() < 0)
+    {
+        _P(printf("[vpx][mm] ERROR vpx_mm_realloc() Couldn't create memory for Heap.\n");)
+    }
+    else
+    {
+        int i_rv = 0;
+        int old_num_aaus;
+        int new_num_aaus;
+
+        old_num_aaus = hmm_true_size(memblk);
+        new_num_aaus = (size >> SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
+
+        if (old_num_aaus == new_num_aaus)
+        {
+            p_ret = memblk;
+        }
+        else
+        {
+            i_rv = hmm_resize(&hmm_d, memblk, new_num_aaus);
+
+            if (i_rv == 0)
+            {
+                p_ret = memblk;
+            }
+            else
+            {
+                /* Error. Try to malloc and then copy data. */
+                void *p_from_malloc;
+
+                new_num_aaus = (size >> SHIFT_HMM_ADDR_ALIGN_UNIT) + 1;
+                p_from_malloc  = hmm_alloc(&hmm_d, new_num_aaus);
+
+                if (p_from_malloc)
+                {
+                    vpx_memcpy(p_from_malloc, memblk, size);
+                    hmm_free(&hmm_d, memblk);
+
+                    p_ret = p_from_malloc;
+                }
+            }
+        }
+    }
+
+    return p_ret;
+}
+#endif /*CONFIG_MEM_MANAGER*/
+
+#if USE_GLOBAL_FUNCTION_POINTERS
+# if CONFIG_MEM_TRACKER
+extern int vpx_memory_tracker_set_functions(g_malloc_func g_malloc_l
+        , g_calloc_func g_calloc_l
+        , g_realloc_func g_realloc_l
+        , g_free_func g_free_l
+        , g_memcpy_func g_memcpy_l
+        , g_memset_func g_memset_l
+        , g_memmove_func g_memmove_l);
+# endif
+#endif /*USE_GLOBAL_FUNCTION_POINTERS*/
+int vpx_mem_set_functions(g_malloc_func g_malloc_l
+                          , g_calloc_func g_calloc_l
+                          , g_realloc_func g_realloc_l
+                          , g_free_func g_free_l
+                          , g_memcpy_func g_memcpy_l
+                          , g_memset_func g_memset_l
+                          , g_memmove_func g_memmove_l)
+{
+#if USE_GLOBAL_FUNCTION_POINTERS
+
+    /* If use global functions is turned on then the
+    application must set the global functions before
+    it does anything else or vpx_mem will have
+    unpredictable results. */
+    if (!g_func)
+    {
+        g_func = (struct GLOBAL_FUNC_POINTERS *)
+                 g_malloc_l(sizeof(struct GLOBAL_FUNC_POINTERS));
+
+        if (!g_func)
+        {
+            return -1;
+        }
+    }
+
+#if CONFIG_MEM_TRACKER
+    {
+        int rv = 0;
+        rv = vpx_memory_tracker_set_functions(g_malloc_l
+                                              , g_calloc_l
+                                              , g_realloc_l
+                                              , g_free_l
+                                              , g_memcpy_l
+                                              , g_memset_l
+                                              , g_memmove_l);
+
+        if (rv < 0)
+        {
+            return rv;
+        }
+    }
+#endif
+
+    g_func->g_malloc  = g_malloc_l;
+    g_func->g_calloc  = g_calloc_l;
+    g_func->g_realloc = g_realloc_l;
+    g_func->g_free    = g_free_l;
+    g_func->g_memcpy  = g_memcpy_l;
+    g_func->g_memset  = g_memset_l;
+    g_func->g_memmove = g_memmove_l;
+
+    return 0;
+#else
+    (void)g_malloc_l;
+    (void)g_calloc_l;
+    (void)g_realloc_l;
+    (void)g_free_l;
+    (void)g_memcpy_l;
+    (void)g_memset_l;
+    (void)g_memmove_l;
+    return -1;
+#endif
+}
+
+int vpx_mem_unset_functions()
+{
+#if USE_GLOBAL_FUNCTION_POINTERS
+
+    if (g_func)
+    {
+        g_free_func temp_free = g_func->g_free;
+        temp_free(g_func);
+        g_func = NULL;
+    }
+
+#endif
+    return 0;
+}
diff --git a/vpx_mem/vpx_mem.h b/vpx_mem/vpx_mem.h
new file mode 100644 (file)
index 0000000..749eaa4
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __VPX_MEM_H__
+#define __VPX_MEM_H__
+
+#if defined(__uClinux__)
+# include <lddk.h>
+#endif
+
+/* vpx_mem version info */
+#define vpx_mem_version "2.2.1.5"
+
+#define VPX_MEM_VERSION_CHIEF 2
+#define VPX_MEM_VERSION_MAJOR 2
+#define VPX_MEM_VERSION_MINOR 1
+#define VPX_MEM_VERSION_PATCH 5
+/* end - vpx_mem version info */
+
+#ifndef VPX_TRACK_MEM_USAGE
+# define VPX_TRACK_MEM_USAGE       0  /* enable memory tracking/integrity checks */
+#endif
+#ifndef VPX_CHECK_MEM_FUNCTIONS
+# define VPX_CHECK_MEM_FUNCTIONS   0  /* enable basic safety checks in _memcpy,
+                                         _memset, and _memmove */
+#endif
+#ifndef REPLACE_BUILTIN_FUNCTIONS
+# define REPLACE_BUILTIN_FUNCTIONS 0  /* replace builtin functions with their
+                                         vpx_ equivalents */
+#endif
+
+#include <stdlib.h>
+#include <stddef.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+    /*
+        vpx_mem_get_version()
+        provided for runtime version checking. Returns an unsigned int of the form
+        CHIEF | MAJOR | MINOR | PATCH, where the chief version number is the high
+        order byte.
+    */
+    unsigned int vpx_mem_get_version(void);
+
+    /*
+        vpx_mem_set_heap_size(size_t size)
+          size - size in bytes for the memory manager to allocate for its heap
+        Sets the memory manager's initial heap size
+        Return:
+          0: on success
+          -1: if memory manager calls have not been included in the vpx_mem lib
+          -2: if the memory manager has been compiled to use static memory
+          -3: if the memory manager has already allocated its heap
+    */
+    int vpx_mem_set_heap_size(size_t size);
+
+    void *vpx_memalign(size_t align, size_t size);
+    void *vpx_malloc(size_t size);
+    void *vpx_calloc(size_t num, size_t size);
+    void *vpx_realloc(void *memblk, size_t size);
+    void vpx_free(void *memblk);
+
+    void *vpx_memcpy(void *dest, const void *src, size_t length);
+    void *vpx_memset(void *dest, int val, size_t length);
+    void *vpx_memmove(void *dest, const void *src, size_t count);
+
+    /* special memory functions */
+    void *vpx_mem_alloc(int id, size_t size, size_t align);
+    void vpx_mem_free(int id, void *mem, size_t size);
+
+    /* Wrappers to standard library functions. */
+    typedef void*(* g_malloc_func)(size_t);
+    typedef void*(* g_calloc_func)(size_t, size_t);
+    typedef void*(* g_realloc_func)(void *, size_t);
+    typedef void (* g_free_func)(void *);
+    typedef void*(* g_memcpy_func)(void *, const void *, size_t);
+    typedef void*(* g_memset_func)(void *, int, size_t);
+    typedef void*(* g_memmove_func)(void *, const void *, size_t);
+
+    int vpx_mem_set_functions(g_malloc_func g_malloc_l
+                              , g_calloc_func g_calloc_l
+                              , g_realloc_func g_realloc_l
+                              , g_free_func g_free_l
+                              , g_memcpy_func g_memcpy_l
+                              , g_memset_func g_memset_l
+                              , g_memmove_func g_memmove_l);
+    int vpx_mem_unset_functions(void);
+
+
+    /* some defines for backward compatibility */
+#define DMEM_GENERAL 0
+
+#define duck_memalign(X,Y,Z) vpx_memalign(X,Y)
+#define duck_malloc(X,Y) vpx_malloc(X)
+#define duck_calloc(X,Y,Z) vpx_calloc(X,Y)
+#define duck_realloc  vpx_realloc
+#define duck_free     vpx_free
+#define duck_memcpy   vpx_memcpy
+#define duck_memmove  vpx_memmove
+#define duck_memset   vpx_memset
+
+#if REPLACE_BUILTIN_FUNCTIONS
+# ifndef __VPX_MEM_C__
+#  define memalign vpx_memalign
+#  define malloc   vpx_malloc
+#  define calloc   vpx_calloc
+#  define realloc  vpx_realloc
+#  define free     vpx_free
+#  define memcpy   vpx_memcpy
+#  define memmove  vpx_memmove
+#  define memset   vpx_memset
+# endif
+#endif
+
+#if CONFIG_MEM_TRACKER
+#include <stdarg.h>
+    /*from vpx_mem/vpx_mem_tracker.c*/
+    extern void vpx_memory_tracker_dump();
+    extern void vpx_memory_tracker_check_integrity(char *file, unsigned int line);
+    extern int vpx_memory_tracker_set_log_type(int type, char *option);
+    extern int vpx_memory_tracker_set_log_func(void *userdata,
+            void(*logfunc)(void *userdata,
+                           const char *fmt, va_list args));
+# ifndef __VPX_MEM_C__
+#  define vpx_memalign(align, size) xvpx_memalign((align), (size), __FILE__, __LINE__)
+#  define vpx_malloc(size)          xvpx_malloc((size), __FILE__, __LINE__)
+#  define vpx_calloc(num, size)     xvpx_calloc(num, size, __FILE__, __LINE__)
+#  define vpx_realloc(addr, size)   xvpx_realloc(addr, size, __FILE__, __LINE__)
+#  define vpx_free(addr)            xvpx_free(addr, __FILE__, __LINE__)
+#  define vpx_memory_tracker_check_integrity() vpx_memory_tracker_check_integrity(__FILE__, __LINE__)
+#  define vpx_mem_alloc(id,size,align) xvpx_mem_alloc(id, size, align, __FILE__, __LINE__)
+#  define vpx_mem_free(id,mem,size) xvpx_mem_free(id, mem, size, __FILE__, __LINE__)
+# endif
+
+    void *xvpx_memalign(size_t align, size_t size, char *file, int line);
+    void *xvpx_malloc(size_t size, char *file, int line);
+    void *xvpx_calloc(size_t num, size_t size, char *file, int line);
+    void *xvpx_realloc(void *memblk, size_t size, char *file, int line);
+    void xvpx_free(void *memblk, char *file, int line);
+    void *xvpx_mem_alloc(int id, size_t size, size_t align, char *file, int line);
+    void xvpx_mem_free(int id, void *mem, size_t size, char *file, int line);
+
+#else
+# ifndef __VPX_MEM_C__
+#  define vpx_memory_tracker_dump()
+#  define vpx_memory_tracker_check_integrity()
+#  define vpx_memory_tracker_set_log_type(t,o) 0
+#  define vpx_memory_tracker_set_log_func(u,f) 0
+# endif
+#endif
+
+#if !VPX_CHECK_MEM_FUNCTIONS
+# ifndef __VPX_MEM_C__
+#  include <string.h>
+#  define vpx_memcpy  memcpy
+#  define vpx_memset  memset
+#  define vpx_memmove memmove
+# endif
+#endif
+
+#ifdef VPX_MEM_PLTFRM
+# include VPX_MEM_PLTFRM
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __VPX_MEM_H__ */
diff --git a/vpx_mem/vpx_mem.mk b/vpx_mem/vpx_mem.mk
new file mode 100644 (file)
index 0000000..4663c5a
--- /dev/null
@@ -0,0 +1,22 @@
+MEM_SRCS-yes += vpx_mem.mk
+MEM_SRCS-yes += vpx_mem.c
+MEM_SRCS-yes += vpx_mem.h
+MEM_SRCS-yes += include/vpx_mem_intrnl.h
+
+MEM_SRCS-$(CONFIG_MEM_TRACKER) += vpx_mem_tracker.c
+MEM_SRCS-$(CONFIG_MEM_TRACKER) += include/vpx_mem_tracker.h
+
+MEM_SRCS-$(CONFIG_MEM_MANAGER) += memory_manager/hmm_true.c
+MEM_SRCS-$(CONFIG_MEM_MANAGER) += memory_manager/hmm_resize.c
+MEM_SRCS-$(CONFIG_MEM_MANAGER) += memory_manager/hmm_shrink.c
+MEM_SRCS-$(CONFIG_MEM_MANAGER) += memory_manager/hmm_largest.c
+MEM_SRCS-$(CONFIG_MEM_MANAGER) += memory_manager/hmm_dflt_abort.c
+MEM_SRCS-$(CONFIG_MEM_MANAGER) += memory_manager/hmm_base.c
+MEM_SRCS-$(CONFIG_MEM_MANAGER) += memory_manager/include
+MEM_SRCS-$(CONFIG_MEM_MANAGER) += memory_manager/include/hmm_intrnl.h
+MEM_SRCS-$(CONFIG_MEM_MANAGER) += memory_manager/include/cavl_if.h
+MEM_SRCS-$(CONFIG_MEM_MANAGER) += memory_manager/include/hmm_cnfg.h
+MEM_SRCS-$(CONFIG_MEM_MANAGER) += memory_manager/include/heapmm.h
+MEM_SRCS-$(CONFIG_MEM_MANAGER) += memory_manager/include/cavl_impl.h
+MEM_SRCS-$(CONFIG_MEM_MANAGER) += memory_manager/hmm_grow.c
+MEM_SRCS-$(CONFIG_MEM_MANAGER) += memory_manager/hmm_alloc.c
diff --git a/vpx_mem/vpx_mem_tracker.c b/vpx_mem/vpx_mem_tracker.c
new file mode 100644 (file)
index 0000000..b37076e
--- /dev/null
@@ -0,0 +1,798 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+  vpx_mem_tracker.c
+
+  jwz 2003-09-30:
+   Stores a list of addreses, their size, and file and line they came from.
+   All exposed lib functions are prefaced by vpx_ and allow the global list
+   to be thread safe.
+   Current supported platforms are:
+    Linux, Win32, win_ce and vx_works
+   Further support can be added by defining the platform specific mutex
+   in the memory_tracker struct as well as calls to create/destroy/lock/unlock
+   the mutex in vpx_memory_tracker_init/Destroy and memory_tracker_lock_mutex/unlock_mutex
+*/
+#include "vpx_config.h"
+
+#if defined(__uClinux__)
+# include <lddk.h>
+#endif
+
+#if HAVE_PTHREAD_H
+# include <pthread.h>
+#elif defined(WIN32) || defined(_WIN32_WCE)
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# include <winbase.h>
+#elif defined(VXWORKS)
+# include <sem_lib.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> //VXWORKS doesn't have a malloc/memory.h file,
+//this should pull in malloc,free,etc.
+#include <stdarg.h>
+
+#include "include/vpx_mem_tracker.h"
+
+#undef vpx_malloc   //undefine any vpx_mem macros that may affect calls to
+#undef vpx_free     //memory functions in this file
+#undef vpx_memcpy
+#undef vpx_memset
+
+
+#ifndef USE_GLOBAL_FUNCTION_POINTERS
+# define USE_GLOBAL_FUNCTION_POINTERS   0  //use function pointers instead of compiled functions.
+#endif
+
+#if USE_GLOBAL_FUNCTION_POINTERS
+static mem_track_malloc_func g_malloc   = malloc;
+static mem_track_calloc_func g_calloc   = calloc;
+static mem_track_realloc_func g_realloc = realloc;
+static mem_track_free_func g_free       = free;
+static mem_track_memcpy_func g_memcpy   = memcpy;
+static mem_track_memset_func g_memset   = memset;
+static mem_track_memmove_func g_memmove = memmove;
+# define MEM_TRACK_MALLOC g_malloc
+# define MEM_TRACK_FREE   g_free
+# define MEM_TRACK_MEMCPY g_memcpy
+# define MEM_TRACK_MEMSET g_memset
+#else
+# define MEM_TRACK_MALLOC vpx_malloc
+# define MEM_TRACK_FREE   vpx_free
+# define MEM_TRACK_MEMCPY vpx_memcpy
+# define MEM_TRACK_MEMSET vpx_memset
+#endif // USE_GLOBAL_FUNCTION_POINTERS
+
+/* prototypes for internal library functions */
+static void memtrack_log(const char *fmt, ...);
+static void memory_tracker_dump();
+static void memory_tracker_check_integrity(char *file, unsigned int line);
+static void memory_tracker_add(size_t addr, unsigned int size,
+                               char *file, unsigned int line,
+                               int padded);
+static int memory_tracker_remove(size_t addr);
+static struct mem_block *memory_tracker_find(size_t addr);
+
+#if defined(NO_MUTEX)
+# define memory_tracker_lock_mutex() (!g_b_mem_tracker_inited)
+# define memory_tracker_unlock_mutex()
+#else
+static int memory_tracker_lock_mutex();
+static int memory_tracker_unlock_mutex();
+#endif
+
+#ifndef VPX_NO_GLOBALS
+struct memory_tracker
+{
+    struct mem_block *head,
+            * tail;
+    int len,
+        totalsize;
+    unsigned int current_allocated,
+             max_allocated;
+
+#if HAVE_PTHREAD_H
+    pthread_mutex_t mutex;
+#elif defined(WIN32) || defined(_WIN32_WCE)
+    HANDLE mutex;
+#elif defined(VXWORKS)
+    SEM_ID mutex;
+#elif defined(NO_MUTEX)
+#else
+#error "No mutex type defined for this platform!"
+#endif
+
+    int padding_size,
+        pad_value;
+};
+
+static struct memory_tracker memtrack;   //our global memory allocation list
+static int g_b_mem_tracker_inited = 0;     //indicates whether the global list has
+//been initialized (1:yes/0:no)
+static struct
+{
+    FILE *file;
+    int type;
+    void (*func)(void *userdata, const char *fmt, va_list args);
+    void *userdata;
+} g_logging = {NULL, 0, NULL, NULL};
+#else
+# include "vpx_global_handling.h"
+#define g_b_mem_tracker_inited vpxglobalm(vpxmem,g_b_mem_tracker_inited)
+#define g_logging vpxglobalm(vpxmem,g_logging)
+#define memtrack vpxglobalm(vpxmem,memtrack)
+#endif // #ifndef VPX_NO_GLOBALS
+
+extern void *vpx_malloc(size_t size);
+extern void vpx_free(void *memblk);
+extern void *vpx_memcpy(void *dest, const void *src, size_t length);
+extern void *vpx_memset(void *dest, int val, size_t length);
+
+/*
+ *
+ * Exposed library functions
+ *
+*/
+
+/*
+    vpx_memory_tracker_init(int padding_size, int pad_value)
+      padding_size - the size of the padding before and after each mem addr.
+                     Values > 0 indicate that integrity checks can be performed
+                     by inspecting these areas.
+      pad_value - the initial value within the padding area before and after
+                  each mem addr.
+
+    Initializes global memory tracker structure
+    Allocates the head of the list
+*/
+int vpx_memory_tracker_init(int padding_size, int pad_value)
+{
+    if (!g_b_mem_tracker_inited)
+    {
+        if ((memtrack.head = (struct mem_block *)
+                             MEM_TRACK_MALLOC(sizeof(struct mem_block))))
+        {
+            int ret;
+
+            MEM_TRACK_MEMSET(memtrack.head, 0, sizeof(struct mem_block));
+
+            memtrack.tail = memtrack.head;
+
+            memtrack.current_allocated = 0;
+            memtrack.max_allocated     = 0;
+
+            memtrack.padding_size = padding_size;
+            memtrack.pad_value    = pad_value;
+
+#if HAVE_PTHREAD_H
+            ret = pthread_mutex_init(&memtrack.mutex,
+                                     NULL);            /*mutex attributes (NULL=default)*/
+#elif defined(WIN32) || defined(_WIN32_WCE)
+            memtrack.mutex = CreateMutex(NULL,   /*security attributes*/
+                                          FALSE,  /*we don't want initial ownership*/
+                                          NULL);  /*mutex name*/
+            ret = !memtrack.mutex;
+#elif defined(VXWORKS)
+            memtrack.mutex = sem_bcreate(SEM_Q_FIFO, /*SEM_Q_FIFO non-priority based mutex*/
+                                         SEM_FULL);  /*SEM_FULL initial state is unlocked*/
+            ret = !memtrack.mutex;
+#elif defined(NO_MUTEX)
+            ret = 0;
+#endif
+
+            if (ret)
+            {
+                memtrack_log("vpx_memory_tracker_init: Error creating mutex!\n");
+
+                MEM_TRACK_FREE(memtrack.head);
+                memtrack.head = NULL;
+            }
+            else
+            {
+                memtrack_log("Memory Tracker init'd, v."vpx_mem_tracker_version" pad_size:%d pad_val:0x%x %d\n"
+                             , padding_size
+                             , pad_value
+                             , pad_value);
+                g_b_mem_tracker_inited = 1;
+            }
+        }
+    }
+
+    return g_b_mem_tracker_inited;
+}
+
+/*
+    vpx_memory_tracker_destroy()
+    If our global struct was initialized zeros out all its members,
+    frees memory and destroys it's mutex
+*/
+void vpx_memory_tracker_destroy()
+{
+    if (!memory_tracker_lock_mutex())
+    {
+        struct mem_block *p  = memtrack.head,
+                                  * p2 = memtrack.head;
+
+        memory_tracker_dump();
+
+        while (p)
+    {
+            p2 = p;
+            p  = p->next;
+
+            MEM_TRACK_FREE(p2);
+        }
+
+        memtrack.head              = NULL;
+        memtrack.tail              = NULL;
+        memtrack.len               = 0;
+        memtrack.current_allocated = 0;
+        memtrack.max_allocated     = 0;
+
+        if (!g_logging.type && g_logging.file && g_logging.file != stderr)
+        {
+            fclose(g_logging.file);
+            g_logging.file = NULL;
+        }
+
+        memory_tracker_unlock_mutex();
+
+        g_b_mem_tracker_inited = 0;
+    }
+}
+
+/*
+    vpx_memory_tracker_add(size_t addr, unsigned int size,
+                         char * file, unsigned int line)
+      addr - memory address to be added to list
+      size - size of addr
+      file - the file addr was referenced from
+      line - the line in file addr was referenced from
+    Adds memory address addr, it's size, file and line it came from
+    to the global list via the thread safe internal library function
+*/
+void vpx_memory_tracker_add(size_t addr, unsigned int size,
+                            char *file, unsigned int line,
+                            int padded)
+{
+    memory_tracker_add(addr, size, file, line, padded);
+}
+
+/*
+    vpx_memory_tracker_remove(size_t addr)
+      addr - memory address to be removed from list
+    Removes addr from the global list via the thread safe
+    internal remove function
+    Return:
+      Same as described for memory_tracker_remove
+*/
+int vpx_memory_tracker_remove(size_t addr)
+{
+    return memory_tracker_remove(addr);
+}
+
+/*
+    vpx_memory_tracker_find(size_t addr)
+      addr - address to be found in list
+    Return:
+        If found, pointer to the memory block that matches addr
+        NULL otherwise
+*/
+struct mem_block *vpx_memory_tracker_find(size_t addr)
+{
+    struct mem_block *p = NULL;
+
+    if (!memory_tracker_lock_mutex())
+    {
+        p = memory_tracker_find(addr);
+        memory_tracker_unlock_mutex();
+    }
+
+    return p;
+}
+
+/*
+    vpx_memory_tracker_dump()
+    Locks the memory tracker's mutex and calls the internal
+    library function to dump the current contents of the
+    global memory allocation list
+*/
+void vpx_memory_tracker_dump()
+{
+    if (!memory_tracker_lock_mutex())
+    {
+        memory_tracker_dump();
+        memory_tracker_unlock_mutex();
+    }
+}
+
+/*
+    vpx_memory_tracker_check_integrity(char* file, unsigned int line)
+      file - The file name where the check was placed
+      line - The line in file where the check was placed
+    Locks the memory tracker's mutex and calls the internal
+    integrity check function to inspect every address in the global
+    memory allocation list
+*/
+void vpx_memory_tracker_check_integrity(char *file, unsigned int line)
+{
+    if (!memory_tracker_lock_mutex())
+    {
+        memory_tracker_check_integrity(file, line);
+        memory_tracker_unlock_mutex();
+    }
+}
+
+/*
+    vpx_memory_tracker_set_log_type
+    Sets the logging type for the memory tracker. Based on the value it will
+    direct its output to the appropriate place.
+    Return:
+      0: on success
+      -1: if the logging type could not be set, because the value was invalid
+          or because a file could not be opened
+*/
+int vpx_memory_tracker_set_log_type(int type, char *option)
+{
+    int ret = -1;
+
+    switch (type)
+    {
+    case 0:
+        g_logging.type = 0;
+
+        if (!option)
+        {
+            g_logging.file = stderr;
+            ret = 0;
+        }
+        else
+        {
+            if ((g_logging.file = fopen((char *)option, "w")))
+                ret = 0;
+        }
+
+        break;
+#if defined(WIN32) && !defined(_WIN32_WCE)
+    case 1:
+        g_logging.type = type;
+        ret = 0;
+        break;
+#endif
+    default:
+        break;
+    }
+
+    //output the version to the new logging destination
+    if (!ret)
+        memtrack_log("Memory Tracker logging initialized, "
+                     "Memory Tracker v."vpx_mem_tracker_version"\n");
+
+    return ret;
+}
+
+/*
+    vpx_memory_tracker_set_log_func
+    Sets a logging function to be used by the memory tracker.
+    Return:
+      0: on success
+      -1: if the logging type could not be set because logfunc was NULL
+*/
+int vpx_memory_tracker_set_log_func(void *userdata,
+                                    void(*logfunc)(void *userdata,
+                                            const char *fmt, va_list args))
+{
+    int ret = -1;
+
+    if (logfunc)
+    {
+        g_logging.type     = -1;
+        g_logging.userdata = userdata;
+        g_logging.func     = logfunc;
+        ret = 0;
+    }
+
+    //output the version to the new logging destination
+    if (!ret)
+        memtrack_log("Memory Tracker logging initialized, "
+                     "Memory Tracker v."vpx_mem_tracker_version"\n");
+
+    return ret;
+}
+
+/*
+ *
+ * END - Exposed library functions
+ *
+*/
+
+
+/*
+ *
+ * Internal library functions
+ *
+*/
+
+static void memtrack_log(const char *fmt, ...)
+{
+    va_list list;
+
+    va_start(list, fmt);
+
+    switch (g_logging.type)
+    {
+    case -1:
+
+        if (g_logging.func)
+            g_logging.func(g_logging.userdata, fmt, list);
+
+        break;
+    case 0:
+
+        if (g_logging.file)
+        {
+            vfprintf(g_logging.file, fmt, list);
+            fflush(g_logging.file);
+        }
+
+        break;
+#if defined(WIN32) && !defined(_WIN32_WCE)
+    case 1:
+    {
+        char temp[1024];
+        _vsnprintf(temp, sizeof(temp) / sizeof(char) - 1, fmt, list);
+        OutputDebugString(temp);
+    }
+    break;
+#endif
+    default:
+        break;
+    }
+
+    va_end(list);
+}
+
+/*
+    memory_tracker_dump()
+    Dumps the current contents of the global memory allocation list
+*/
+static void memory_tracker_dump()
+{
+    int i = 0;
+    struct mem_block *p = (memtrack.head ? memtrack.head->next : NULL);
+
+    memtrack_log("\n_currently Allocated= %d; Max allocated= %d\n",
+                 memtrack.current_allocated, memtrack.max_allocated);
+
+    while (p)
+    {
+#if defined(WIN32) && !defined(_WIN32_WCE)
+
+        /*when using outputdebugstring, output filenames so they
+          can be clicked to be opened in visual studio*/
+        if (g_logging.type == 1)
+            memtrack_log("memblocks[%d].addr= 0x%.8x, memblocks[%d].size= %d, file:\n"
+                         "  %s(%d):\n", i,
+                         p->addr, i, p->size,
+                         p->file, p->line);
+        else
+#endif
+            memtrack_log("memblocks[%d].addr= 0x%.8x, memblocks[%d].size= %d, file: %s, line: %d\n", i,
+                         p->addr, i, p->size,
+                         p->file, p->line);
+
+        p = p->next;
+        ++i;
+    }
+
+    memtrack_log("\n");
+}
+
+/*
+    memory_tracker_check_integrity(char* file, unsigned int file)
+      file - the file name where the check was placed
+      line - the line in file where the check was placed
+    If a padding_size was supplied to vpx_memory_tracker_init()
+    this function will check ea. addr in the list verifying that
+    addr-padding_size and addr+padding_size is filled with pad_value
+*/
+static void memory_tracker_check_integrity(char *file, unsigned int line)
+{
+    if (memtrack.padding_size)
+    {
+        int i,
+            index = 0;
+        unsigned char *p_show_me,
+                 * p_show_me2;
+        unsigned int tempme = memtrack.pad_value,
+                     dead1,
+                     dead2;
+        unsigned char *x_bounds;
+        struct mem_block *p = memtrack.head->next;
+
+        while (p)
+        {
+            //x_bounds = (unsigned char*)p->addr;
+            //back up VPX_BYTE_ALIGNMENT
+            //x_bounds -= memtrack.padding_size;
+
+            if (p->padded)   // can the bounds be checked?
+            {
+                /*yes, move to the address that was actually allocated
+                by the vpx_* calls*/
+                x_bounds = (unsigned char *)(((size_t *)p->addr)[-1]);
+
+                for (i = 0; i < memtrack.padding_size; i += sizeof(unsigned int))
+                {
+                    p_show_me = (x_bounds + i);
+                    p_show_me2 = (unsigned char *)(p->addr + p->size + i);
+
+                    MEM_TRACK_MEMCPY(&dead1, p_show_me, sizeof(unsigned int));
+                    MEM_TRACK_MEMCPY(&dead2, p_show_me2, sizeof(unsigned int));
+
+                    if ((dead1 != tempme) || (dead2 != tempme))
+                    {
+                        memtrack_log("\n[vpx_mem integrity check failed]:\n"
+                                     "    index[%d,%d] {%s:%d} addr=0x%x, size=%d,"
+                                     " file: %s, line: %d c0:0x%x c1:0x%x\n",
+                                     index, i, file, line, p->addr, p->size, p->file,
+                                     p->line, dead1, dead2);
+                    }
+                }
+            }
+
+            ++index;
+            p = p->next;
+        }
+    }
+}
+
+/*
+    memory_tracker_add(size_t addr, unsigned int size,
+                     char * file, unsigned int line)
+    Adds an address (addr), it's size, file and line number to our list.
+    Adjusts the total bytes allocated and max bytes allocated if necessary.
+    If memory cannot be allocated the list will be destroyed.
+*/
+void memory_tracker_add(size_t addr, unsigned int size,
+                        char *file, unsigned int line,
+                        int padded)
+{
+    if (!memory_tracker_lock_mutex())
+    {
+        struct mem_block *p;
+
+        p = MEM_TRACK_MALLOC(sizeof(struct mem_block));
+
+        if (p)
+        {
+            p->prev       = memtrack.tail;
+            p->prev->next = p;
+            p->addr       = addr;
+            p->size       = size;
+            p->line       = line;
+            p->file       = file;
+            p->padded     = padded;
+            p->next       = NULL;
+
+            memtrack.tail = p;
+
+            memtrack.current_allocated += size;
+
+            if (memtrack.current_allocated > memtrack.max_allocated)
+                memtrack.max_allocated = memtrack.current_allocated;
+
+            //memtrack_log("memory_tracker_add: added addr=0x%.8x\n", addr);
+
+            memory_tracker_unlock_mutex();
+        }
+        else
+        {
+            memtrack_log("memory_tracker_add: error allocating memory!\n");
+            memory_tracker_unlock_mutex();
+            vpx_memory_tracker_destroy();
+        }
+    }
+}
+
+/*
+    memory_tracker_remove(size_t addr)
+    Removes an address and its corresponding size (if they exist)
+    from the memory tracker list and adjusts the current number
+    of bytes allocated.
+    Return:
+      0: on success
+      -1: if the mutex could not be locked
+      -2: if the addr was not found in the list
+*/
+int memory_tracker_remove(size_t addr)
+{
+    int ret = -1;
+
+    if (!memory_tracker_lock_mutex())
+    {
+        struct mem_block *p;
+
+        if ((p = memory_tracker_find(addr)))
+        {
+            memtrack.current_allocated -= p->size;
+
+            p->prev->next = p->next;
+
+            if (p->next)
+                p->next->prev = p->prev;
+            else
+                memtrack.tail = p->prev;
+
+            ret = 0;
+            MEM_TRACK_FREE(p);
+        }
+        else
+        {
+            if (addr)
+                memtrack_log("memory_tracker_remove(): addr not found in list,"
+                             " 0x%.8x\n", addr);
+
+            ret = -2;
+        }
+
+        memory_tracker_unlock_mutex();
+    }
+
+    return ret;
+}
+
+/*
+    memory_tracker_find(size_t addr)
+    Finds an address in our addrs list
+    NOTE: the mutex MUST be locked in the other internal
+          functions before calling this one. This avoids
+          the need for repeated locking and unlocking as in Remove
+    Returns: pointer to the mem block if found, NULL otherwise
+*/
+static struct mem_block *memory_tracker_find(size_t addr)
+{
+    struct mem_block *p = NULL;
+
+    if (memtrack.head)
+    {
+        p = memtrack.head->next;
+
+        while (p && (p->addr != addr))
+            p = p->next;
+    }
+
+    return p;
+}
+
+
+#if !defined(NO_MUTEX)
+/*
+    memory_tracker_lock_mutex()
+    Locks the memory tracker mutex with a platform specific call
+    Returns:
+        0: Success
+       <0: Failure, either the mutex was not initialized
+           or the call to lock the mutex failed
+*/
+static int memory_tracker_lock_mutex()
+{
+    int ret = -1;
+
+    if (g_b_mem_tracker_inited)
+    {
+
+#if HAVE_PTHREAD_H
+        ret = pthread_mutex_lock(&memtrack.mutex);
+#elif defined(WIN32) || defined(_WIN32_WCE)
+        ret = WaitForSingleObject(memtrack.mutex, INFINITE);
+#elif defined(VXWORKS)
+        ret = sem_take(memtrack.mutex, WAIT_FOREVER);
+#endif
+
+        if (ret)
+        {
+            memtrack_log("memory_tracker_lock_mutex: mutex lock failed\n");
+        }
+    }
+
+    return ret;
+}
+
+/*
+    memory_tracker_unlock_mutex()
+    Unlocks the memory tracker mutex with a platform specific call
+    Returns:
+        0: Success
+       <0: Failure, either the mutex was not initialized
+           or the call to unlock the mutex failed
+*/
+static int memory_tracker_unlock_mutex()
+{
+    int ret = -1;
+
+    if (g_b_mem_tracker_inited)
+    {
+
+#if HAVE_PTHREAD_H
+        ret = pthread_mutex_unlock(&memtrack.mutex);
+#elif defined(WIN32) || defined(_WIN32_WCE)
+        ret = !ReleaseMutex(memtrack.mutex);
+#elif defined(VXWORKS)
+        ret = sem_give(memtrack.mutex);
+#endif
+
+        if (ret)
+        {
+            memtrack_log("memory_tracker_unlock_mutex: mutex unlock failed\n");
+        }
+    }
+
+    return ret;
+}
+#endif
+
+/*
+    vpx_memory_tracker_set_functions
+
+    Sets the function pointers for the standard library functions.
+
+    Return:
+      0: on success
+      -1: if the use global function pointers is not set.
+*/
+int vpx_memory_tracker_set_functions(mem_track_malloc_func g_malloc_l
+                                     , mem_track_calloc_func g_calloc_l
+                                     , mem_track_realloc_func g_realloc_l
+                                     , mem_track_free_func g_free_l
+                                     , mem_track_memcpy_func g_memcpy_l
+                                     , mem_track_memset_func g_memset_l
+                                     , mem_track_memmove_func g_memmove_l)
+{
+#if USE_GLOBAL_FUNCTION_POINTERS
+
+    if (g_malloc_l)
+        g_malloc = g_malloc_l;
+
+    if (g_calloc_l)
+        g_calloc = g_calloc_l;
+
+    if (g_realloc_l)
+        g_realloc = g_realloc_l;
+
+    if (g_free_l)
+        g_free = g_free_l;
+
+    if (g_memcpy_l)
+        g_memcpy = g_memcpy_l;
+
+    if (g_memset_l)
+        g_memset = g_memset_l;
+
+    if (g_memmove_l)
+        g_memmove = g_memmove_l;
+
+    return 0;
+#else
+    (void)g_malloc_l;
+    (void)g_calloc_l;
+    (void)g_realloc_l;
+    (void)g_free_l;
+    (void)g_memcpy_l;
+    (void)g_memset_l;
+    (void)g_memmove_l;
+    return -1;
+#endif
+}
diff --git a/vpx_ports/arm.h b/vpx_ports/arm.h
new file mode 100644 (file)
index 0000000..525a764
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef VPX_PORTS_ARM_H
+#define VPX_PORTS_ARM_H
+#include <stdlib.h>
+#include "vpx_config.h"
+
+/*ARMv5TE "Enhanced DSP" instructions.*/
+#define HAS_EDSP  0x01
+/*ARMv6 "Parallel" or "Media" instructions.*/
+#define HAS_MEDIA 0x02
+/*ARMv7 optional NEON instructions.*/
+#define HAS_NEON  0x04
+
+int arm_cpu_caps(void);
+
+#endif
+
diff --git a/vpx_ports/arm_cpudetect.c b/vpx_ports/arm_cpudetect.c
new file mode 100644 (file)
index 0000000..ebe428d
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "arm.h"
+
+static int arm_cpu_env_flags(int *flags)
+{
+    char *env;
+    env = getenv("VPX_SIMD_CAPS");
+    if (env && *env)
+    {
+        *flags = (int)strtol(env, NULL, 0);
+        return 0;
+    }
+    *flags = 0;
+    return -1;
+}
+
+static int arm_cpu_env_mask(void)
+{
+    char *env;
+    env = getenv("VPX_SIMD_CAPS_MASK");
+    return env && *env ? (int)strtol(env, NULL, 0) : ~0;
+}
+
+
+#if defined(_MSC_VER)
+/*For GetExceptionCode() and EXCEPTION_ILLEGAL_INSTRUCTION.*/
+#define WIN32_LEAN_AND_MEAN
+#define WIN32_EXTRA_LEAN
+#include <windows.h>
+
+int arm_cpu_caps(void)
+{
+    int flags;
+    int mask;
+    if (!arm_cpu_env_flags(&flags))
+    {
+        return flags;
+    }
+    mask = arm_cpu_env_mask();
+    /* MSVC has no inline __asm support for ARM, but it does let you __emit
+     *  instructions via their assembled hex code.
+     * All of these instructions should be essentially nops.
+     */
+#if defined(HAVE_EDSP)
+    if (mask & HAS_EDSP)
+    {
+        __try
+        {
+            /*PLD [r13]*/
+            __emit(0xF5DDF000);
+            flags |= HAS_EDSP;
+        }
+        __except(GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION)
+        {
+            /*Ignore exception.*/
+        }
+    }
+#if defined(HAVE_MEDIA)
+    if (mask & HAS_MEDIA)
+        __try
+        {
+            /*SHADD8 r3,r3,r3*/
+            __emit(0xE6333F93);
+            flags |= HAS_MEDIA;
+        }
+        __except(GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION)
+        {
+            /*Ignore exception.*/
+        }
+    }
+#if defined(HAVE_NEON)
+    if (mask & HAS_NEON)
+    {
+        __try
+        {
+            /*VORR q0,q0,q0*/
+            __emit(0xF2200150);
+            flags |= HAS_NEON;
+        }
+        __except(GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION)
+        {
+            /*Ignore exception.*/
+        }
+    }
+#endif
+#endif
+#endif
+    return flags & mask;
+}
+
+#elif defined(__linux__)
+#if defined(__ANDROID__)
+#include <cpu-features.h>
+
+int arm_cpu_caps(void)
+{
+    int flags;
+    int mask;
+    uint64_t features;
+    if (!arm_cpu_env_flags(&flags))
+    {
+        return flags;
+    }
+    mask = arm_cpu_env_mask();
+    features = android_getCpuFeatures();
+
+#if defined(HAVE_EDSP)
+    flags |= HAS_EDSP;
+#endif
+#if defined(HAVE_MEDIA)
+    flags |= HAS_MEDIA;
+#endif
+#if defined(HAVE_NEON)
+    if (features & ANDROID_CPU_ARM_FEATURE_NEON)
+        flags |= HAS_NEON;
+#endif
+    return flags & mask;
+}
+#else // !defined(__ANDROID__)
+#include <stdio.h>
+
+int arm_cpu_caps(void)
+{
+    FILE *fin;
+    int flags;
+    int mask;
+    if (!arm_cpu_env_flags(&flags))
+    {
+        return flags;
+    }
+    mask = arm_cpu_env_mask();
+    /* Reading /proc/self/auxv would be easier, but that doesn't work reliably
+     *  on Android.
+     * This also means that detection will fail in Scratchbox.
+     */
+    fin = fopen("/proc/cpuinfo","r");
+    if(fin != NULL)
+    {
+        /* 512 should be enough for anybody (it's even enough for all the flags
+         * that x86 has accumulated... so far).
+         */
+        char buf[512];
+        while (fgets(buf, 511, fin) != NULL)
+        {
+#if defined(HAVE_EDSP) || defined(HAVE_NEON)
+            if (memcmp(buf, "Features", 8) == 0)
+            {
+                char *p;
+#if defined(HAVE_EDSP)
+                p=strstr(buf, " edsp");
+                if (p != NULL && (p[5] == ' ' || p[5] == '\n'))
+                {
+                    flags |= HAS_EDSP;
+                }
+#if defined(HAVE_NEON)
+                p = strstr(buf, " neon");
+                if (p != NULL && (p[5] == ' ' || p[5] == '\n'))
+                {
+                    flags |= HAS_NEON;
+                }
+#endif
+#endif
+            }
+#endif
+#if defined(HAVE_MEDIA)
+            if (memcmp(buf, "CPU architecture:",17) == 0){
+                int version;
+                version = atoi(buf+17);
+                if (version >= 6)
+                {
+                    flags |= HAS_MEDIA;
+                }
+            }
+#endif
+        }
+        fclose(fin);
+    }
+    return flags & mask;
+}
+#endif // defined(__linux__)
+#elif !CONFIG_RUNTIME_CPU_DETECT
+
+int arm_cpu_caps(void)
+{
+    int flags;
+    int mask;
+    if (!arm_cpu_env_flags(&flags))
+    {
+        return flags;
+    }
+    mask = arm_cpu_env_mask();
+#if defined(HAVE_EDSP)
+    flags |= HAS_EDSP;
+#endif
+#if defined(HAVE_MEDIA)
+    flags |= HAS_MEDIA;
+#endif
+#if defined(HAVE_NEON)
+    flags |= HAS_NEON;
+#endif
+    return flags & mask;
+}
+
+#else
+#error "--enable-runtime-cpu-detect selected, but no CPU detection method " \
+ "available for your platform. Reconfigure without --enable-runtime-cpu-detect."
+#endif
diff --git a/vpx_ports/asm_offsets.h b/vpx_ports/asm_offsets.h
new file mode 100644 (file)
index 0000000..d3b4fc7
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef VPX_PORTS_ASM_OFFSETS_H
+#define VPX_PORTS_ASM_OFFSETS_H
+
+#include <stddef.h>
+
+#define ct_assert(name,cond) \
+    static void assert_##name(void) UNUSED;\
+    static void assert_##name(void) {switch(0){case 0:case !!(cond):;}}
+
+#if INLINE_ASM
+#define DEFINE(sym, val) asm("\n" #sym " EQU %0" : : "i" (val));
+#define BEGIN int main(void) {
+#define END return 0; }
+#else
+#define DEFINE(sym, val) int sym = val;
+#define BEGIN
+#define END
+#endif
+
+#endif /* VPX_PORTS_ASM_OFFSETS_H */
diff --git a/vpx_ports/emms.asm b/vpx_ports/emms.asm
new file mode 100644 (file)
index 0000000..306e235
--- /dev/null
@@ -0,0 +1,38 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+section .text
+    global sym(vpx_reset_mmx_state)
+sym(vpx_reset_mmx_state):
+    emms
+    ret
+
+
+%ifidn __OUTPUT_FORMAT__,x64
+global sym(vpx_winx64_fldcw)
+sym(vpx_winx64_fldcw):
+    sub   rsp, 8
+    mov   [rsp], rcx ; win x64 specific
+    fldcw [rsp]
+    add   rsp, 8
+    ret
+
+
+global sym(vpx_winx64_fstcw)
+sym(vpx_winx64_fstcw):
+    sub   rsp, 8
+    fstcw [rsp]
+    mov   rax, [rsp]
+    add   rsp, 8
+    ret
+%endif
diff --git a/vpx_ports/mem.h b/vpx_ports/mem.h
new file mode 100644 (file)
index 0000000..29e507f
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef VPX_PORTS_MEM_H
+#define VPX_PORTS_MEM_H
+#include "vpx_config.h"
+#include "vpx/vpx_integer.h"
+
+#if (defined(__GNUC__) && __GNUC__) || defined(__SUNPRO_C)
+#define DECLARE_ALIGNED(n,typ,val)  typ val __attribute__ ((aligned (n)))
+#elif defined(_MSC_VER)
+#define DECLARE_ALIGNED(n,typ,val)  __declspec(align(n)) typ val
+#else
+#warning No alignment directives known for this compiler.
+#define DECLARE_ALIGNED(n,typ,val)  typ val
+#endif
+#endif
+
+
+/* Declare an aligned array on the stack, for situations where the stack
+ * pointer may not have the alignment we expect. Creates an array with a
+ * modified name, then defines val to be a pointer, and aligns that pointer
+ * within the array.
+ */
+#define DECLARE_ALIGNED_ARRAY(a,typ,val,n)\
+typ val##_[(n)+(a)/sizeof(typ)+1];\
+typ *val = (typ*)((((intptr_t)val##_)+(a)-1)&((intptr_t)-(a)))
+
+
+/* Indicates that the usage of the specified variable has been audited to assure
+ * that it's safe to use uninitialized. Silences 'may be used uninitialized'
+ * warnings on gcc.
+ */
+#if defined(__GNUC__) && __GNUC__
+#define UNINITIALIZED_IS_SAFE(x) x=x
+#else
+#define UNINITIALIZED_IS_SAFE(x) x
+#endif
diff --git a/vpx_ports/mem_ops.h b/vpx_ports/mem_ops.h
new file mode 100644 (file)
index 0000000..0e52368
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/* \file
+ * \brief Provides portable memory access primitives
+ *
+ * This function provides portable primitives for getting and setting of
+ * signed and unsigned integers in 16, 24, and 32 bit sizes. The operations
+ * can be performed on unaligned data regardless of hardware support for
+ * unaligned accesses.
+ *
+ * The type used to pass the integral values may be changed by defining
+ * MEM_VALUE_T with the appropriate type. The type given must be an integral
+ * numeric type.
+ *
+ * The actual functions instantiated have the MEM_VALUE_T type name pasted
+ * on to the symbol name. This allows the developer to instantiate these
+ * operations for multiple types within the same translation unit. This is
+ * of somewhat questionable utility, but the capability exists nonetheless.
+ * Users not making use of this functionality should call the functions
+ * without the type name appended, and the preprocessor will take care of
+ * it.
+ *
+ * NOTE: This code is not supported on platforms where char > 1 octet ATM.
+ */
+
+#ifndef MAU_T
+/* Minimum Access Unit for this target */
+#define MAU_T unsigned char
+#endif
+
+#ifndef MEM_VALUE_T
+#define MEM_VALUE_T int
+#endif
+
+#undef MEM_VALUE_T_SZ_BITS
+#define MEM_VALUE_T_SZ_BITS (sizeof(MEM_VALUE_T) << 3)
+
+#undef  mem_ops_wrap_symbol
+#define mem_ops_wrap_symbol(fn) mem_ops_wrap_symbol2(fn, MEM_VALUE_T)
+#undef  mem_ops_wrap_symbol2
+#define mem_ops_wrap_symbol2(fn,typ) mem_ops_wrap_symbol3(fn,typ)
+#undef  mem_ops_wrap_symbol3
+#define mem_ops_wrap_symbol3(fn,typ) fn##_as_##typ
+
+/*
+ * Include aligned access routines
+ */
+#define INCLUDED_BY_MEM_OPS_H
+#include "mem_ops_aligned.h"
+#undef  INCLUDED_BY_MEM_OPS_H
+
+#undef  mem_get_be16
+#define mem_get_be16 mem_ops_wrap_symbol(mem_get_be16)
+static unsigned MEM_VALUE_T mem_get_be16(const void *vmem)
+{
+    unsigned MEM_VALUE_T  val;
+    const MAU_T          *mem = (const MAU_T *)vmem;
+
+    val = mem[0] << 8;
+    val |= mem[1];
+    return val;
+}
+
+#undef  mem_get_be24
+#define mem_get_be24 mem_ops_wrap_symbol(mem_get_be24)
+static unsigned MEM_VALUE_T mem_get_be24(const void *vmem)
+{
+    unsigned MEM_VALUE_T  val;
+    const MAU_T          *mem = (const MAU_T *)vmem;
+
+    val = mem[0] << 16;
+    val |= mem[1] << 8;
+    val |= mem[2];
+    return val;
+}
+
+#undef  mem_get_be32
+#define mem_get_be32 mem_ops_wrap_symbol(mem_get_be32)
+static unsigned MEM_VALUE_T mem_get_be32(const void *vmem)
+{
+    unsigned MEM_VALUE_T  val;
+    const MAU_T          *mem = (const MAU_T *)vmem;
+
+    val = mem[0] << 24;
+    val |= mem[1] << 16;
+    val |= mem[2] << 8;
+    val |= mem[3];
+    return val;
+}
+
+#undef  mem_get_le16
+#define mem_get_le16 mem_ops_wrap_symbol(mem_get_le16)
+static unsigned MEM_VALUE_T mem_get_le16(const void *vmem)
+{
+    unsigned MEM_VALUE_T  val;
+    const MAU_T          *mem = (const MAU_T *)vmem;
+
+    val = mem[1] << 8;
+    val |= mem[0];
+    return val;
+}
+
+#undef  mem_get_le24
+#define mem_get_le24 mem_ops_wrap_symbol(mem_get_le24)
+static unsigned MEM_VALUE_T mem_get_le24(const void *vmem)
+{
+    unsigned MEM_VALUE_T  val;
+    const MAU_T          *mem = (const MAU_T *)vmem;
+
+    val = mem[2] << 16;
+    val |= mem[1] << 8;
+    val |= mem[0];
+    return val;
+}
+
+#undef  mem_get_le32
+#define mem_get_le32 mem_ops_wrap_symbol(mem_get_le32)
+static unsigned MEM_VALUE_T mem_get_le32(const void *vmem)
+{
+    unsigned MEM_VALUE_T  val;
+    const MAU_T          *mem = (const MAU_T *)vmem;
+
+    val = mem[3] << 24;
+    val |= mem[2] << 16;
+    val |= mem[1] << 8;
+    val |= mem[0];
+    return val;
+}
+
+#define mem_get_s_generic(end,sz) \
+    static signed MEM_VALUE_T mem_get_s##end##sz(const void *vmem) {\
+        const MAU_T *mem = (const MAU_T*)vmem;\
+        signed MEM_VALUE_T val = mem_get_##end##sz(mem);\
+        return (val << (MEM_VALUE_T_SZ_BITS - sz)) >> (MEM_VALUE_T_SZ_BITS - sz);\
+    }
+
+#undef  mem_get_sbe16
+#define mem_get_sbe16 mem_ops_wrap_symbol(mem_get_sbe16)
+mem_get_s_generic(be, 16);
+
+#undef  mem_get_sbe24
+#define mem_get_sbe24 mem_ops_wrap_symbol(mem_get_sbe24)
+mem_get_s_generic(be, 24);
+
+#undef  mem_get_sbe32
+#define mem_get_sbe32 mem_ops_wrap_symbol(mem_get_sbe32)
+mem_get_s_generic(be, 32);
+
+#undef  mem_get_sle16
+#define mem_get_sle16 mem_ops_wrap_symbol(mem_get_sle16)
+mem_get_s_generic(le, 16);
+
+#undef  mem_get_sle24
+#define mem_get_sle24 mem_ops_wrap_symbol(mem_get_sle24)
+mem_get_s_generic(le, 24);
+
+#undef  mem_get_sle32
+#define mem_get_sle32 mem_ops_wrap_symbol(mem_get_sle32)
+mem_get_s_generic(le, 32);
+
+#undef  mem_put_be16
+#define mem_put_be16 mem_ops_wrap_symbol(mem_put_be16)
+static void mem_put_be16(void *vmem, MEM_VALUE_T val)
+{
+    MAU_T *mem = (MAU_T *)vmem;
+
+    mem[0] = (val >> 8) & 0xff;
+    mem[1] = (val >> 0) & 0xff;
+}
+
+#undef  mem_put_be24
+#define mem_put_be24 mem_ops_wrap_symbol(mem_put_be24)
+static void mem_put_be24(void *vmem, MEM_VALUE_T val)
+{
+    MAU_T *mem = (MAU_T *)vmem;
+
+    mem[0] = (val >> 16) & 0xff;
+    mem[1] = (val >>  8) & 0xff;
+    mem[2] = (val >>  0) & 0xff;
+}
+
+#undef  mem_put_be32
+#define mem_put_be32 mem_ops_wrap_symbol(mem_put_be32)
+static void mem_put_be32(void *vmem, MEM_VALUE_T val)
+{
+    MAU_T *mem = (MAU_T *)vmem;
+
+    mem[0] = (val >> 24) & 0xff;
+    mem[1] = (val >> 16) & 0xff;
+    mem[2] = (val >>  8) & 0xff;
+    mem[3] = (val >>  0) & 0xff;
+}
+
+#undef  mem_put_le16
+#define mem_put_le16 mem_ops_wrap_symbol(mem_put_le16)
+static void mem_put_le16(void *vmem, MEM_VALUE_T val)
+{
+    MAU_T *mem = (MAU_T *)vmem;
+
+    mem[0] = (val >>  0) & 0xff;
+    mem[1] = (val >>  8) & 0xff;
+}
+
+#undef  mem_put_le24
+#define mem_put_le24 mem_ops_wrap_symbol(mem_put_le24)
+static void mem_put_le24(void *vmem, MEM_VALUE_T val)
+{
+    MAU_T *mem = (MAU_T *)vmem;
+
+    mem[0] = (val >>  0) & 0xff;
+    mem[1] = (val >>  8) & 0xff;
+    mem[2] = (val >> 16) & 0xff;
+}
+
+#undef  mem_put_le32
+#define mem_put_le32 mem_ops_wrap_symbol(mem_put_le32)
+static void mem_put_le32(void *vmem, MEM_VALUE_T val)
+{
+    MAU_T *mem = (MAU_T *)vmem;
+
+    mem[0] = (val >>  0) & 0xff;
+    mem[1] = (val >>  8) & 0xff;
+    mem[2] = (val >> 16) & 0xff;
+    mem[3] = (val >> 24) & 0xff;
+}
diff --git a/vpx_ports/mem_ops_aligned.h b/vpx_ports/mem_ops_aligned.h
new file mode 100644 (file)
index 0000000..0fbba65
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/* \file
+ * \brief Provides portable memory access primitives for operating on aligned
+ *        data
+ *
+ * This file is split from mem_ops.h for easier maintenance. See mem_ops.h
+ * for a more detailed description of these primitives.
+ */
+#ifndef INCLUDED_BY_MEM_OPS_H
+#error Include mem_ops.h, not mem_ops_aligned.h directly.
+#endif
+
+/* Architectures that provide instructions for doing this byte swapping
+ * could redefine these macros.
+ */
+#define swap_endian_16(val,raw) do {\
+        val = ((raw>>8) & 0x00ff) \
+              | ((raw<<8) & 0xff00);\
+    } while(0)
+#define swap_endian_32(val,raw) do {\
+        val = ((raw>>24) & 0x000000ff) \
+              | ((raw>>8)  & 0x0000ff00) \
+              | ((raw<<8)  & 0x00ff0000) \
+              | ((raw<<24) & 0xff000000); \
+    } while(0)
+#define swap_endian_16_se(val,raw) do {\
+        swap_endian_16(val,raw);\
+        val = ((val << 16) >> 16);\
+    } while(0)
+#define swap_endian_32_se(val,raw) swap_endian_32(val,raw)
+
+#define mem_get_ne_aligned_generic(end,sz) \
+    static unsigned MEM_VALUE_T mem_get_##end##sz##_aligned(const void *vmem) {\
+        const uint##sz##_t *mem = (const uint##sz##_t *)vmem;\
+        return *mem;\
+    }
+
+#define mem_get_sne_aligned_generic(end,sz) \
+    static signed MEM_VALUE_T mem_get_s##end##sz##_aligned(const void *vmem) {\
+        const int##sz##_t *mem = (const int##sz##_t *)vmem;\
+        return *mem;\
+    }
+
+#define mem_get_se_aligned_generic(end,sz) \
+    static unsigned MEM_VALUE_T mem_get_##end##sz##_aligned(const void *vmem) {\
+        const uint##sz##_t *mem = (const uint##sz##_t *)vmem;\
+        unsigned MEM_VALUE_T val, raw = *mem;\
+        swap_endian_##sz(val,raw);\
+        return val;\
+    }
+
+#define mem_get_sse_aligned_generic(end,sz) \
+    static signed MEM_VALUE_T mem_get_s##end##sz##_aligned(const void *vmem) {\
+        const int##sz##_t *mem = (const int##sz##_t *)vmem;\
+        unsigned MEM_VALUE_T val, raw = *mem;\
+        swap_endian_##sz##_se(val,raw);\
+        return val;\
+    }
+
+#define mem_put_ne_aligned_generic(end,sz) \
+    static void mem_put_##end##sz##_aligned(void *vmem, MEM_VALUE_T val) {\
+        uint##sz##_t *mem = (uint##sz##_t *)vmem;\
+        *mem = (uint##sz##_t)val;\
+    }
+
+#define mem_put_se_aligned_generic(end,sz) \
+    static void mem_put_##end##sz##_aligned(void *vmem, MEM_VALUE_T val) {\
+        uint##sz##_t *mem = (uint##sz##_t *)vmem, raw;\
+        swap_endian_##sz(raw,val);\
+        *mem = (uint##sz##_t)raw;\
+    }
+
+#include "vpx_config.h"
+#if CONFIG_BIG_ENDIAN
+#define mem_get_be_aligned_generic(sz)  mem_get_ne_aligned_generic(be,sz)
+#define mem_get_sbe_aligned_generic(sz) mem_get_sne_aligned_generic(be,sz)
+#define mem_get_le_aligned_generic(sz)  mem_get_se_aligned_generic(le,sz)
+#define mem_get_sle_aligned_generic(sz) mem_get_sse_aligned_generic(le,sz)
+#define mem_put_be_aligned_generic(sz)  mem_put_ne_aligned_generic(be,sz)
+#define mem_put_le_aligned_generic(sz)  mem_put_se_aligned_generic(le,sz)
+#else
+#define mem_get_be_aligned_generic(sz)  mem_get_se_aligned_generic(be,sz)
+#define mem_get_sbe_aligned_generic(sz) mem_get_sse_aligned_generic(be,sz)
+#define mem_get_le_aligned_generic(sz)  mem_get_ne_aligned_generic(le,sz)
+#define mem_get_sle_aligned_generic(sz) mem_get_sne_aligned_generic(le,sz)
+#define mem_put_be_aligned_generic(sz)  mem_put_se_aligned_generic(be,sz)
+#define mem_put_le_aligned_generic(sz)  mem_put_ne_aligned_generic(le,sz)
+#endif
+
+#undef  mem_get_be16_aligned
+#define mem_get_be16_aligned mem_ops_wrap_symbol(mem_get_be16_aligned)
+mem_get_be_aligned_generic(16);
+
+#undef  mem_get_be32_aligned
+#define mem_get_be32_aligned mem_ops_wrap_symbol(mem_get_be32_aligned)
+mem_get_be_aligned_generic(32);
+
+#undef  mem_get_le16_aligned
+#define mem_get_le16_aligned mem_ops_wrap_symbol(mem_get_le16_aligned)
+mem_get_le_aligned_generic(16);
+
+#undef  mem_get_le32_aligned
+#define mem_get_le32_aligned mem_ops_wrap_symbol(mem_get_le32_aligned)
+mem_get_le_aligned_generic(32);
+
+#undef  mem_get_sbe16_aligned
+#define mem_get_sbe16_aligned mem_ops_wrap_symbol(mem_get_sbe16_aligned)
+mem_get_sbe_aligned_generic(16);
+
+#undef  mem_get_sbe32_aligned
+#define mem_get_sbe32_aligned mem_ops_wrap_symbol(mem_get_sbe32_aligned)
+mem_get_sbe_aligned_generic(32);
+
+#undef  mem_get_sle16_aligned
+#define mem_get_sle16_aligned mem_ops_wrap_symbol(mem_get_sle16_aligned)
+mem_get_sle_aligned_generic(16);
+
+#undef  mem_get_sle32_aligned
+#define mem_get_sle32_aligned mem_ops_wrap_symbol(mem_get_sle32_aligned)
+mem_get_sle_aligned_generic(32);
+
+#undef  mem_put_be16_aligned
+#define mem_put_be16_aligned mem_ops_wrap_symbol(mem_put_be16_aligned)
+mem_put_be_aligned_generic(16);
+
+#undef  mem_put_be32_aligned
+#define mem_put_be32_aligned mem_ops_wrap_symbol(mem_put_be32_aligned)
+mem_put_be_aligned_generic(32);
+
+#undef  mem_put_le16_aligned
+#define mem_put_le16_aligned mem_ops_wrap_symbol(mem_put_le16_aligned)
+mem_put_le_aligned_generic(16);
+
+#undef  mem_put_le32_aligned
+#define mem_put_le32_aligned mem_ops_wrap_symbol(mem_put_le32_aligned)
+mem_put_le_aligned_generic(32);
+
+#undef mem_get_ne_aligned_generic
+#undef mem_get_se_aligned_generic
+#undef mem_get_sne_aligned_generic
+#undef mem_get_sse_aligned_generic
+#undef mem_put_ne_aligned_generic
+#undef mem_put_se_aligned_generic
+#undef swap_endian_16
+#undef swap_endian_32
+#undef swap_endian_16_se
+#undef swap_endian_32_se
diff --git a/vpx_ports/vpx_timer.h b/vpx_ports/vpx_timer.h
new file mode 100644 (file)
index 0000000..d07e086
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef VPX_TIMER_H
+#define VPX_TIMER_H
+#include "vpx/vpx_integer.h"
+
+#if CONFIG_OS_SUPPORT
+
+#if defined(_WIN32)
+/*
+ * Win32 specific includes
+ */
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#else
+/*
+ * POSIX specific includes
+ */
+#include <sys/time.h>
+
+/* timersub is not provided by msys at this time. */
+#ifndef timersub
+#define timersub(a, b, result) \
+    do { \
+        (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+        (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
+        if ((result)->tv_usec < 0) { \
+            --(result)->tv_sec; \
+            (result)->tv_usec += 1000000; \
+        } \
+    } while (0)
+#endif
+#endif
+
+
+struct vpx_usec_timer
+{
+#if defined(_WIN32)
+    LARGE_INTEGER  begin, end;
+#else
+    struct timeval begin, end;
+#endif
+};
+
+
+static void
+vpx_usec_timer_start(struct vpx_usec_timer *t)
+{
+#if defined(_WIN32)
+    QueryPerformanceCounter(&t->begin);
+#else
+    gettimeofday(&t->begin, NULL);
+#endif
+}
+
+
+static void
+vpx_usec_timer_mark(struct vpx_usec_timer *t)
+{
+#if defined(_WIN32)
+    QueryPerformanceCounter(&t->end);
+#else
+    gettimeofday(&t->end, NULL);
+#endif
+}
+
+
+static int64_t
+vpx_usec_timer_elapsed(struct vpx_usec_timer *t)
+{
+#if defined(_WIN32)
+    LARGE_INTEGER freq, diff;
+
+    diff.QuadPart = t->end.QuadPart - t->begin.QuadPart;
+
+    QueryPerformanceFrequency(&freq);
+    return diff.QuadPart * 1000000 / freq.QuadPart;
+#else
+    struct timeval diff;
+
+    timersub(&t->end, &t->begin, &diff);
+    return diff.tv_sec * 1000000 + diff.tv_usec;
+#endif
+}
+
+#else /* CONFIG_OS_SUPPORT = 0*/
+
+/* Empty timer functions if CONFIG_OS_SUPPORT = 0 */
+#ifndef timersub
+#define timersub(a, b, result)
+#endif
+
+struct vpx_usec_timer
+{
+    void *dummy;
+};
+
+static void
+vpx_usec_timer_start(struct vpx_usec_timer *t) { }
+
+static void
+vpx_usec_timer_mark(struct vpx_usec_timer *t) { }
+
+static long
+vpx_usec_timer_elapsed(struct vpx_usec_timer *t) { return 0; }
+
+#endif /* CONFIG_OS_SUPPORT */
+
+#endif
diff --git a/vpx_ports/vpxtypes.h b/vpx_ports/vpxtypes.h
new file mode 100644 (file)
index 0000000..f2fb089
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __VPXTYPES_H__
+#define __VPXTYPES_H__
+
+#include "vpx_config.h"
+
+//#include <sys/types.h>
+#ifdef _MSC_VER
+# include <basetsd.h>
+typedef SSIZE_T ssize_t;
+#endif
+
+#if defined(HAVE_STDINT_H) && HAVE_STDINT_H
+/* C99 types are preferred to vpx integer types */
+# include <stdint.h>
+#endif
+
+/*!\defgroup basetypes Base Types
+  @{*/
+#if !defined(HAVE_STDINT_H) && !defined(INT_T_DEFINED)
+# ifdef STRICTTYPES
+typedef signed char  int8_t;
+typedef signed short int16_t;
+typedef signed int   int32_t;
+# else
+typedef char         int8_t;
+typedef short        int16_t;
+typedef int          int32_t;
+# endif
+typedef unsigned char  uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int   uint32_t;
+#endif
+
+typedef int8_t     vpxs8;
+typedef uint8_t    vpxu8;
+typedef int16_t    vpxs16;
+typedef uint16_t   vpxu16;
+typedef int32_t    vpxs32;
+typedef uint32_t   vpxu32;
+typedef int32_t    vpxbool;
+
+enum {vpxfalse, vpxtrue};
+
+/*!\def OTC
+   \brief a macro suitable for declaring a constant #vpxtc*/
+/*!\def VPXTC
+   \brief printf format string suitable for printing an #vpxtc*/
+#ifdef UNICODE
+# ifdef NO_WCHAR
+#  error "no non-wchar support added yet"
+# else
+#  include <wchar.h>
+typedef wchar_t vpxtc;
+#  define OTC(str) L ## str
+#  define VPXTC "ls"
+# endif /*NO_WCHAR*/
+#else
+typedef char vpxtc;
+# define OTC(str) (vpxtc*)str
+# define VPXTC "s"
+#endif /*UNICODE*/
+/*@} end - base types*/
+
+/*!\addtogroup basetypes
+  @{*/
+/*!\def VPX64
+   \brief printf format string suitable for printing an #vpxs64*/
+#if defined(HAVE_STDINT_H)
+# define VPX64 PRId64
+typedef int64_t vpxs64;
+#elif defined(HASLONGLONG)
+# undef  PRId64
+# define PRId64 "lld"
+# define VPX64 PRId64
+typedef long long vpxs64;
+#elif defined(WIN32) || defined(_WIN32_WCE)
+# undef  PRId64
+# define PRId64 "I64d"
+# define VPX64 PRId64
+typedef __int64 vpxs64;
+typedef unsigned __int64 vpxu64;
+#elif defined(__uClinux__) && defined(CHIP_DM642)
+# include <lddk.h>
+# undef  PRId64
+# define PRId64 "lld"
+# define VPX64 PRId64
+typedef long vpxs64;
+#else
+# error "64 bit integer type undefined for this platform!"
+#endif
+#if !defined(HAVE_STDINT_H) && !defined(INT_T_DEFINED)
+typedef vpxs64 int64_t;
+typedef vpxu64 uint64_t;
+#endif
+/*!@} end - base types*/
+
+/*!\ingroup basetypes
+   \brief Common return type*/
+typedef enum
+{
+    VPX_NOT_FOUND        = -404,
+    VPX_BUFFER_EMPTY     = -202,
+    VPX_BUFFER_FULL      = -201,
+
+    VPX_CONNREFUSED      = -102,
+    VPX_TIMEDOUT         = -101,
+    VPX_WOULDBLOCK       = -100,
+
+    VPX_NET_ERROR        = -9,
+    VPX_INVALID_VERSION  = -8,
+    VPX_INPROGRESS       = -7,
+    VPX_NOT_SUPP         = -6,
+    VPX_NO_MEM           = -3,
+    VPX_INVALID_PARAMS   = -2,
+    VPX_ERROR            = -1,
+    VPX_OK               = 0,
+    VPX_DONE             = 1
+} vpxsc;
+
+#if defined(WIN32) || defined(_WIN32_WCE)
+# define DLLIMPORT __declspec(dllimport)
+# define DLLEXPORT __declspec(dllexport)
+# define DLLLOCAL
+#elif defined(LINUX)
+# define DLLIMPORT
+/*visibility attribute support is available in 3.4 and later.
+  see: http://gcc.gnu.org/wiki/Visibility for more info*/
+# if defined(__GNUC__) && ((__GNUC__<<16|(__GNUC_MINOR__&0xff)) >= (3<<16|4))
+#  define GCC_HASCLASSVISIBILITY
+# endif /*defined(__GNUC__) && __GNUC_PREREQ(3,4)*/
+# ifdef GCC_HASCLASSVISIBILITY
+#  define DLLEXPORT   __attribute__ ((visibility("default")))
+#  define DLLLOCAL __attribute__ ((visibility("hidden")))
+# else
+#  define DLLEXPORT
+#  define DLLLOCAL
+# endif /*GCC_HASCLASSVISIBILITY*/
+#endif /*platform ifdefs*/
+
+#endif /*__VPXTYPES_H__*/
+
+#undef VPXAPI
+/*!\def VPXAPI
+   \brief library calling convention/storage class attributes.
+
+   Specifies whether the function is imported through a dll
+   or is from a static library.*/
+#ifdef VPXDLL
+# ifdef VPXDLLEXPORT
+#  define VPXAPI DLLEXPORT
+# else
+#  define VPXAPI DLLIMPORT
+# endif /*VPXDLLEXPORT*/
+#else
+# define VPXAPI
+#endif /*VPXDLL*/
diff --git a/vpx_ports/x86.h b/vpx_ports/x86.h
new file mode 100644 (file)
index 0000000..1341c7f
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef VPX_PORTS_X86_H
+#define VPX_PORTS_X86_H
+#include <stdlib.h>
+#include "vpx_config.h"
+
+typedef enum
+{
+    VPX_CPU_UNKNOWN = -1,
+    VPX_CPU_AMD,
+    VPX_CPU_AMD_OLD,
+    VPX_CPU_CENTAUR,
+    VPX_CPU_CYRIX,
+    VPX_CPU_INTEL,
+    VPX_CPU_NEXGEN,
+    VPX_CPU_NSC,
+    VPX_CPU_RISE,
+    VPX_CPU_SIS,
+    VPX_CPU_TRANSMETA,
+    VPX_CPU_TRANSMETA_OLD,
+    VPX_CPU_UMC,
+    VPX_CPU_VIA,
+
+    VPX_CPU_LAST
+}  vpx_cpu_t;
+
+#if defined(__GNUC__) && __GNUC__
+#if ARCH_X86_64
+#define cpuid(func,ax,bx,cx,dx)\
+    __asm__ __volatile__ (\
+                          "cpuid           \n\t" \
+                          : "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) \
+                          : "a"  (func));
+#else
+#define cpuid(func,ax,bx,cx,dx)\
+    __asm__ __volatile__ (\
+                          "mov %%ebx, %%edi   \n\t" \
+                          "cpuid              \n\t" \
+                          "xchg %%edi, %%ebx  \n\t" \
+                          : "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
+                          : "a" (func));
+#endif
+#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#if ARCH_X86_64
+#define cpuid(func,ax,bx,cx,dx)\
+    asm volatile (\
+                  "xchg %rsi, %rbx \n\t" \
+                  "cpuid           \n\t" \
+                  "movl %ebx, %edi \n\t" \
+                  "xchg %rsi, %rbx \n\t" \
+                  : "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
+                  : "a"  (func));
+#else
+#define cpuid(func,ax,bx,cx,dx)\
+    asm volatile (\
+                  "pushl %ebx       \n\t" \
+                  "cpuid            \n\t" \
+                  "movl %ebx, %edi  \n\t" \
+                  "popl %ebx        \n\t" \
+                  : "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
+                  : "a" (func));
+#endif
+#else
+#if ARCH_X86_64
+void __cpuid(int CPUInfo[4], int info_type);
+#pragma intrinsic(__cpuid)
+#define cpuid(func,a,b,c,d) do{\
+        int regs[4];\
+        __cpuid(regs,func); a=regs[0];  b=regs[1];  c=regs[2];  d=regs[3];\
+    } while(0)
+#else
+#define cpuid(func,a,b,c,d)\
+    __asm mov eax, func\
+    __asm cpuid\
+    __asm mov a, eax\
+    __asm mov b, ebx\
+    __asm mov c, ecx\
+    __asm mov d, edx
+#endif
+#endif
+
+#define HAS_MMX   0x01
+#define HAS_SSE   0x02
+#define HAS_SSE2  0x04
+#define HAS_SSE3  0x08
+#define HAS_SSSE3 0x10
+#define HAS_SSE4_1 0x20
+#ifndef BIT
+#define BIT(n) (1<<n)
+#endif
+
+static int
+x86_simd_caps(void)
+{
+    unsigned int flags = 0;
+    unsigned int mask = ~0;
+    unsigned int reg_eax, reg_ebx, reg_ecx, reg_edx;
+    char *env;
+    (void)reg_ebx;
+
+    /* See if the CPU capabilities are being overridden by the environment */
+    env = getenv("VPX_SIMD_CAPS");
+
+    if (env && *env)
+        return (int)strtol(env, NULL, 0);
+
+    env = getenv("VPX_SIMD_CAPS_MASK");
+
+    if (env && *env)
+        mask = strtol(env, NULL, 0);
+
+    /* Ensure that the CPUID instruction supports extended features */
+    cpuid(0, reg_eax, reg_ebx, reg_ecx, reg_edx);
+
+    if (reg_eax < 1)
+        return 0;
+
+    /* Get the standard feature flags */
+    cpuid(1, reg_eax, reg_ebx, reg_ecx, reg_edx);
+
+    if (reg_edx & BIT(23)) flags |= HAS_MMX;
+
+    if (reg_edx & BIT(25)) flags |= HAS_SSE; /* aka xmm */
+
+    if (reg_edx & BIT(26)) flags |= HAS_SSE2; /* aka wmt */
+
+    if (reg_ecx & BIT(0))  flags |= HAS_SSE3;
+
+    if (reg_ecx & BIT(9))  flags |= HAS_SSSE3;
+
+    if (reg_ecx & BIT(19)) flags |= HAS_SSE4_1;
+
+    return flags & mask;
+}
+
+vpx_cpu_t vpx_x86_vendor(void);
+
+#if ARCH_X86_64 && defined(_MSC_VER)
+unsigned __int64 __rdtsc(void);
+#pragma intrinsic(__rdtsc)
+#endif
+static unsigned int
+x86_readtsc(void)
+{
+#if defined(__GNUC__) && __GNUC__
+    unsigned int tsc;
+    __asm__ __volatile__("rdtsc\n\t":"=a"(tsc):);
+    return tsc;
+#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+    unsigned int tsc;
+    asm volatile("rdtsc\n\t":"=a"(tsc):);
+    return tsc;
+#else
+#if ARCH_X86_64
+    return __rdtsc();
+#else
+    __asm  rdtsc;
+#endif
+#endif
+}
+
+
+#if defined(__GNUC__) && __GNUC__
+#define x86_pause_hint()\
+    __asm__ __volatile__ ("pause \n\t")
+#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#define x86_pause_hint()\
+    asm volatile ("pause \n\t")
+#else
+#if ARCH_X86_64
+#define x86_pause_hint()\
+    _mm_pause();
+#else
+#define x86_pause_hint()\
+    __asm pause
+#endif
+#endif
+
+#if defined(__GNUC__) && __GNUC__
+static void
+x87_set_control_word(unsigned short mode)
+{
+    __asm__ __volatile__("fldcw %0" : : "m"(*&mode));
+}
+static unsigned short
+x87_get_control_word(void)
+{
+    unsigned short mode;
+    __asm__ __volatile__("fstcw %0\n\t":"=m"(*&mode):);
+    return mode;
+}
+#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+static void
+x87_set_control_word(unsigned short mode)
+{
+    asm volatile("fldcw %0" : : "m"(*&mode));
+}
+static unsigned short
+x87_get_control_word(void)
+{
+    unsigned short mode;
+    asm volatile("fstcw %0\n\t":"=m"(*&mode):);
+    return mode;
+}
+#elif ARCH_X86_64
+/* No fldcw intrinsics on Windows x64, punt to external asm */
+extern void           vpx_winx64_fldcw(unsigned short mode);
+extern unsigned short vpx_winx64_fstcw(void);
+#define x87_set_control_word vpx_winx64_fldcw
+#define x87_get_control_word vpx_winx64_fstcw
+#else
+static void
+x87_set_control_word(unsigned short mode)
+{
+    __asm { fldcw mode }
+}
+static unsigned short
+x87_get_control_word(void)
+{
+    unsigned short mode;
+    __asm { fstcw mode }
+    return mode;
+}
+#endif
+
+static unsigned short
+x87_set_double_precision(void)
+{
+    unsigned short mode = x87_get_control_word();
+    x87_set_control_word((mode&~0x300) | 0x200);
+    return mode;
+}
+
+
+extern void vpx_reset_mmx_state(void);
+#endif
+
diff --git a/vpx_ports/x86_abi_support.asm b/vpx_ports/x86_abi_support.asm
new file mode 100644 (file)
index 0000000..cef6a0b
--- /dev/null
@@ -0,0 +1,334 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+%include "vpx_config.asm"
+
+; 32/64 bit compatibility macros
+;
+; In general, we make the source use 64 bit syntax, then twiddle with it using
+; the preprocessor to get the 32 bit syntax on 32 bit platforms.
+;
+%ifidn __OUTPUT_FORMAT__,elf32
+%define ABI_IS_32BIT 1
+%elifidn __OUTPUT_FORMAT__,macho32
+%define ABI_IS_32BIT 1
+%elifidn __OUTPUT_FORMAT__,win32
+%define ABI_IS_32BIT 1
+%elifidn __OUTPUT_FORMAT__,aout
+%define ABI_IS_32BIT 1
+%else
+%define ABI_IS_32BIT 0
+%endif
+
+%if ABI_IS_32BIT
+%define rax eax
+%define rbx ebx
+%define rcx ecx
+%define rdx edx
+%define rsi esi
+%define rdi edi
+%define rsp esp
+%define rbp ebp
+%define movsxd mov
+%macro movq 2
+  %ifidn %1,eax
+    movd %1,%2
+  %elifidn %2,eax
+    movd %1,%2
+  %elifidn %1,ebx
+    movd %1,%2
+  %elifidn %2,ebx
+    movd %1,%2
+  %elifidn %1,ecx
+    movd %1,%2
+  %elifidn %2,ecx
+    movd %1,%2
+  %elifidn %1,edx
+    movd %1,%2
+  %elifidn %2,edx
+    movd %1,%2
+  %elifidn %1,esi
+    movd %1,%2
+  %elifidn %2,esi
+    movd %1,%2
+  %elifidn %1,edi
+    movd %1,%2
+  %elifidn %2,edi
+    movd %1,%2
+  %elifidn %1,esp
+    movd %1,%2
+  %elifidn %2,esp
+    movd %1,%2
+  %elifidn %1,ebp
+    movd %1,%2
+  %elifidn %2,ebp
+    movd %1,%2
+  %else
+    movq %1,%2
+  %endif
+%endmacro
+%endif
+
+
+; sym()
+; Return the proper symbol name for the target ABI.
+;
+; Certain ABIs, notably MS COFF and Darwin MACH-O, require that symbols
+; with C linkage be prefixed with an underscore.
+;
+%ifidn   __OUTPUT_FORMAT__,elf32
+%define sym(x) x
+%elifidn __OUTPUT_FORMAT__,elf64
+%define sym(x) x
+%elifidn __OUTPUT_FORMAT__,x64
+%define sym(x) x
+%else
+%define sym(x) _ %+ x
+%endif
+
+; arg()
+; Return the address specification of the given argument
+;
+%if ABI_IS_32BIT
+  %define arg(x) [ebp+8+4*x]
+%else
+  ; 64 bit ABI passes arguments in registers. This is a workaround to get up
+  ; and running quickly. Relies on SHADOW_ARGS_TO_STACK
+  %ifidn __OUTPUT_FORMAT__,x64
+    %define arg(x) [rbp+16+8*x]
+  %else
+    %define arg(x) [rbp-8-8*x]
+  %endif
+%endif
+
+; REG_SZ_BYTES, REG_SZ_BITS
+; Size of a register
+%if ABI_IS_32BIT
+%define REG_SZ_BYTES 4
+%define REG_SZ_BITS  32
+%else
+%define REG_SZ_BYTES 8
+%define REG_SZ_BITS  64
+%endif
+
+
+; ALIGN_STACK <alignment> <register>
+; This macro aligns the stack to the given alignment (in bytes). The stack
+; is left such that the previous value of the stack pointer is the first
+; argument on the stack (ie, the inverse of this macro is 'pop rsp.')
+; This macro uses one temporary register, which is not preserved, and thus
+; must be specified as an argument.
+%macro ALIGN_STACK 2
+    mov         %2, rsp
+    and         rsp, -%1
+    lea         rsp, [rsp - (%1 - REG_SZ_BYTES)]
+    push        %2
+%endmacro
+
+
+;
+; The Microsoft assembler tries to impose a certain amount of type safety in
+; its register usage. YASM doesn't recognize these directives, so we just
+; %define them away to maintain as much compatibility as possible with the
+; original inline assembler we're porting from.
+;
+%idefine PTR
+%idefine XMMWORD
+%idefine MMWORD
+
+; PIC macros
+;
+%if ABI_IS_32BIT
+  %if CONFIG_PIC=1
+  %ifidn __OUTPUT_FORMAT__,elf32
+    %define GET_GOT_SAVE_ARG 1
+    %define WRT_PLT wrt ..plt
+    %macro GET_GOT 1
+      extern _GLOBAL_OFFSET_TABLE_
+      push %1
+      call %%get_got
+      %%sub_offset:
+      jmp %%exitGG
+      %%get_got:
+      mov %1, [esp]
+      add %1, _GLOBAL_OFFSET_TABLE_ + $$ - %%sub_offset wrt ..gotpc
+      ret
+      %%exitGG:
+      %undef GLOBAL
+      %define GLOBAL(x) x + %1 wrt ..gotoff
+      %undef RESTORE_GOT
+      %define RESTORE_GOT pop %1
+    %endmacro
+  %elifidn __OUTPUT_FORMAT__,macho32
+    %define GET_GOT_SAVE_ARG 1
+    %macro GET_GOT 1
+      push %1
+      call %%get_got
+      %%get_got:
+      pop  %1
+      %undef GLOBAL
+      %define GLOBAL(x) x + %1 - %%get_got
+      %undef RESTORE_GOT
+      %define RESTORE_GOT pop %1
+    %endmacro
+  %endif
+  %endif
+  %define HIDDEN_DATA(x) x
+%else
+  %macro GET_GOT 1
+  %endmacro
+  %define GLOBAL(x) rel x
+  %ifidn __OUTPUT_FORMAT__,elf64
+    %define WRT_PLT wrt ..plt
+    %define HIDDEN_DATA(x) x:data hidden
+  %else
+    %define HIDDEN_DATA(x) x
+  %endif
+%endif
+%ifnmacro GET_GOT
+    %macro GET_GOT 1
+    %endmacro
+    %define GLOBAL(x) x
+%endif
+%ifndef RESTORE_GOT
+%define RESTORE_GOT
+%endif
+%ifndef WRT_PLT
+%define WRT_PLT
+%endif
+
+%if ABI_IS_32BIT
+  %macro SHADOW_ARGS_TO_STACK 1
+  %endm
+  %define UNSHADOW_ARGS
+%else
+%ifidn __OUTPUT_FORMAT__,x64
+  %macro SHADOW_ARGS_TO_STACK 1 ; argc
+    %if %1 > 0
+        mov arg(0),rcx
+    %endif
+    %if %1 > 1
+        mov arg(1),rdx
+    %endif
+    %if %1 > 2
+        mov arg(2),r8
+    %endif
+    %if %1 > 3
+        mov arg(3),r9
+    %endif
+  %endm
+%else
+  %macro SHADOW_ARGS_TO_STACK 1 ; argc
+    %if %1 > 0
+        push rdi
+    %endif
+    %if %1 > 1
+        push rsi
+    %endif
+    %if %1 > 2
+        push rdx
+    %endif
+    %if %1 > 3
+        push rcx
+    %endif
+    %if %1 > 4
+        push r8
+    %endif
+    %if %1 > 5
+        push r9
+    %endif
+    %if %1 > 6
+      %assign i %1-6
+      %assign off 16
+      %rep i
+        mov rax,[rbp+off]
+        push rax
+        %assign off off+8
+      %endrep
+    %endif
+  %endm
+%endif
+  %define UNSHADOW_ARGS mov rsp, rbp
+%endif
+
+; Win64 ABI requires that XMM6:XMM15 are callee saved
+; SAVE_XMM n, [u]
+; store registers 6-n on the stack
+; if u is specified, use unaligned movs.
+; Win64 ABI requires 16 byte stack alignment, but then pushes an 8 byte return
+; value. Typically we follow this up with 'push rbp' - re-aligning the stack -
+; but in some cases this is not done and unaligned movs must be used.
+%ifidn __OUTPUT_FORMAT__,x64
+%macro SAVE_XMM 1-2 a
+  %if %1 < 6
+    %error Only xmm registers 6-15 must be preserved
+  %else
+    %assign last_xmm %1
+    %define movxmm movdq %+ %2
+    %assign xmm_stack_space ((last_xmm - 5) * 16)
+    sub rsp, xmm_stack_space
+    %assign i 6
+    %rep (last_xmm - 5)
+      movxmm [rsp + ((i - 6) * 16)], xmm %+ i
+      %assign i i+1
+    %endrep
+  %endif
+%endmacro
+%macro RESTORE_XMM 0
+  %ifndef last_xmm
+    %error RESTORE_XMM must be paired with SAVE_XMM n
+  %else
+    %assign i last_xmm
+    %rep (last_xmm - 5)
+      movxmm xmm %+ i, [rsp +((i - 6) * 16)]
+      %assign i i-1
+    %endrep
+    add rsp, xmm_stack_space
+    ; there are a couple functions which return from multiple places.
+    ; otherwise, we could uncomment these:
+    ; %undef last_xmm
+    ; %undef xmm_stack_space
+    ; %undef movxmm
+  %endif
+%endmacro
+%else
+%macro SAVE_XMM 1-2
+%endmacro
+%macro RESTORE_XMM 0
+%endmacro
+%endif
+
+; Name of the rodata section
+;
+; .rodata seems to be an elf-ism, as it doesn't work on OSX.
+;
+%ifidn __OUTPUT_FORMAT__,macho64
+%define SECTION_RODATA section .text
+%elifidn __OUTPUT_FORMAT__,macho32
+%macro SECTION_RODATA 0
+section .text
+%endmacro
+%elifidn __OUTPUT_FORMAT__,aout
+%define SECTION_RODATA section .data
+%else
+%define SECTION_RODATA section .rodata
+%endif
+
+
+; Tell GNU ld that we don't require an executable stack.
+%ifidn __OUTPUT_FORMAT__,elf32
+section .note.GNU-stack noalloc noexec nowrite progbits
+section .text
+%elifidn __OUTPUT_FORMAT__,elf64
+section .note.GNU-stack noalloc noexec nowrite progbits
+section .text
+%endif
+
diff --git a/vpx_ports/x86_cpuid.c b/vpx_ports/x86_cpuid.c
new file mode 100644 (file)
index 0000000..ce64033
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <string.h>
+#include "x86.h"
+
+struct cpuid_vendors
+{
+    char vendor_string[12];
+    vpx_cpu_t vendor_id;
+};
+
+static struct cpuid_vendors cpuid_vendor_list[VPX_CPU_LAST] =
+{
+    { "AuthenticAMD", VPX_CPU_AMD           },
+    { "AMDisbetter!", VPX_CPU_AMD_OLD       },
+    { "CentaurHauls", VPX_CPU_CENTAUR       },
+    { "CyrixInstead", VPX_CPU_CYRIX         },
+    { "GenuineIntel", VPX_CPU_INTEL         },
+    { "NexGenDriven", VPX_CPU_NEXGEN        },
+    { "Geode by NSC", VPX_CPU_NSC           },
+    { "RiseRiseRise", VPX_CPU_RISE          },
+    { "SiS SiS SiS ", VPX_CPU_SIS           },
+    { "GenuineTMx86", VPX_CPU_TRANSMETA     },
+    { "TransmetaCPU", VPX_CPU_TRANSMETA_OLD },
+    { "UMC UMC UMC ", VPX_CPU_UMC           },
+    { "VIA VIA VIA ", VPX_CPU_VIA           },
+};
+
+vpx_cpu_t vpx_x86_vendor(void)
+{
+    unsigned int reg_eax;
+    unsigned int vs[3];
+    int i;
+
+    /* Get the Vendor String from the CPU */
+    cpuid(0, reg_eax, vs[0], vs[2], vs[1]);
+
+    for (i = 0; i < VPX_CPU_LAST; i++)
+    {
+        if (strncmp ((const char *)vs, cpuid_vendor_list[i].vendor_string, 12) == 0)
+           return (cpuid_vendor_list[i].vendor_id);
+    }
+
+    return VPX_CPU_UNKNOWN;
+}
diff --git a/vpx_scale/arm/neon/vp8_vpxyv12_copy_y_neon.asm b/vpx_scale/arm/neon/vp8_vpxyv12_copy_y_neon.asm
new file mode 100644 (file)
index 0000000..9189641
--- /dev/null
@@ -0,0 +1,122 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_yv12_copy_y_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    INCLUDE asm_com_offsets.asm
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+;void vpxyv12_copy_y_neon(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc)
+|vp8_yv12_copy_y_neon| PROC
+    push            {r4 - r11, lr}
+    vpush           {d8-d15}
+
+    ldr             r4, [r0, #yv12_buffer_config_y_height]
+    ldr             r5, [r0, #yv12_buffer_config_y_width]
+    ldr             r6, [r0, #yv12_buffer_config_y_stride]
+    ldr             r7, [r1, #yv12_buffer_config_y_stride]
+    ldr             r2, [r0, #yv12_buffer_config_y_buffer]       ;srcptr1
+    ldr             r3, [r1, #yv12_buffer_config_y_buffer]       ;dstptr1
+
+    ; copy two rows at one time
+    mov             lr, r4, lsr #1
+
+cp_src_to_dst_height_loop1
+    mov             r8, r2
+    mov             r9, r3
+    add             r10, r2, r6
+    add             r11, r3, r7
+    movs            r12, r5, lsr #7
+    ble             extra_copy_needed   ; y_width < 128
+
+cp_src_to_dst_width_loop1
+    vld1.8          {q0, q1}, [r8]!
+    vld1.8          {q8, q9}, [r10]!
+    vld1.8          {q2, q3}, [r8]!
+    vld1.8          {q10, q11}, [r10]!
+    vld1.8          {q4, q5}, [r8]!
+    vld1.8          {q12, q13}, [r10]!
+    vld1.8          {q6, q7}, [r8]!
+    vld1.8          {q14, q15}, [r10]!
+
+    subs            r12, r12, #1
+
+    vst1.8          {q0, q1}, [r9]!
+    vst1.8          {q8, q9}, [r11]!
+    vst1.8          {q2, q3}, [r9]!
+    vst1.8          {q10, q11}, [r11]!
+    vst1.8          {q4, q5}, [r9]!
+    vst1.8          {q12, q13}, [r11]!
+    vst1.8          {q6, q7}, [r9]!
+    vst1.8          {q14, q15}, [r11]!
+
+    bne             cp_src_to_dst_width_loop1
+
+    subs            lr, lr, #1
+    add             r2, r2, r6, lsl #1
+    add             r3, r3, r7, lsl #1
+
+    bne             cp_src_to_dst_height_loop1
+
+extra_copy_needed
+    ands            r10, r5, #0x7f                  ;check to see if extra copy is needed
+    sub             r11, r5, r10
+    ldr             r2, [r0, #yv12_buffer_config_y_buffer]       ;srcptr1
+    ldr             r3, [r1, #yv12_buffer_config_y_buffer]       ;dstptr1
+    bne             extra_cp_src_to_dst_width1
+end_of_cp_src_to_dst1
+
+    vpop            {d8 - d15}
+    pop             {r4-r11, pc}
+
+;=============================
+extra_cp_src_to_dst_width1
+    add             r2, r2, r11
+    add             r3, r3, r11
+    add             r0, r8, r6
+    add             r11, r9, r7
+
+    mov             lr, r4, lsr #1
+extra_cp_src_to_dst_height_loop1
+    mov             r8, r2
+    mov             r9, r3
+    add             r0, r8, r6
+    add             r11, r9, r7
+
+    mov             r12, r10
+
+extra_cp_src_to_dst_width_loop1
+    vld1.8          {q0}, [r8]!
+    vld1.8          {q1}, [r0]!
+
+    subs            r12, r12, #16
+
+    vst1.8          {q0}, [r9]!
+    vst1.8          {q1}, [r11]!
+    bne             extra_cp_src_to_dst_width_loop1
+
+    subs            lr, lr, #1
+
+    add             r2, r2, r6, lsl #1
+    add             r3, r3, r7, lsl #1
+
+    bne             extra_cp_src_to_dst_height_loop1
+
+    b               end_of_cp_src_to_dst1
+
+    ENDP
+
+    END
diff --git a/vpx_scale/arm/neon/vp8_vpxyv12_copyframe_func_neon.asm b/vpx_scale/arm/neon/vp8_vpxyv12_copyframe_func_neon.asm
new file mode 100644 (file)
index 0000000..e55d076
--- /dev/null
@@ -0,0 +1,233 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_yv12_copy_frame_func_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    INCLUDE asm_com_offsets.asm
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+;void vp8_yv12_copy_frame_func_neon(YV12_BUFFER_CONFIG *src_ybc,
+;                                   YV12_BUFFER_CONFIG *dst_ybc);
+
+|vp8_yv12_copy_frame_func_neon| PROC
+    push            {r4 - r11, lr}
+    vpush           {d8 - d15}
+
+    sub             sp, sp, #16
+
+    ;Copy Y plane
+    ldr             r8, [r0, #yv12_buffer_config_u_buffer]       ;srcptr1
+    ldr             r9, [r1, #yv12_buffer_config_u_buffer]       ;srcptr1
+    ldr             r10, [r0, #yv12_buffer_config_v_buffer]      ;srcptr1
+    ldr             r11, [r1, #yv12_buffer_config_v_buffer]      ;srcptr1
+
+    ldr             r4, [r0, #yv12_buffer_config_y_height]
+    ldr             r5, [r0, #yv12_buffer_config_y_width]
+    ldr             r6, [r0, #yv12_buffer_config_y_stride]
+    ldr             r7, [r1, #yv12_buffer_config_y_stride]
+    ldr             r2, [r0, #yv12_buffer_config_y_buffer]       ;srcptr1
+    ldr             r3, [r1, #yv12_buffer_config_y_buffer]       ;dstptr1
+
+    str             r8, [sp]
+    str             r9, [sp, #4]
+    str             r10, [sp, #8]
+    str             r11, [sp, #12]
+
+    ; copy two rows at one time
+    mov             lr, r4, lsr #1
+
+cp_src_to_dst_height_loop
+    mov             r8, r2
+    mov             r9, r3
+    add             r10, r2, r6
+    add             r11, r3, r7
+    movs            r12, r5, lsr #7
+    ble             extra_cp_needed   ; y_width < 128
+
+cp_src_to_dst_width_loop
+    vld1.8          {q0, q1}, [r8]!
+    vld1.8          {q8, q9}, [r10]!
+    vld1.8          {q2, q3}, [r8]!
+    vld1.8          {q10, q11}, [r10]!
+    vld1.8          {q4, q5}, [r8]!
+    vld1.8          {q12, q13}, [r10]!
+    vld1.8          {q6, q7}, [r8]!
+    vld1.8          {q14, q15}, [r10]!
+
+    subs            r12, r12, #1
+
+    vst1.8          {q0, q1}, [r9]!
+    vst1.8          {q8, q9}, [r11]!
+    vst1.8          {q2, q3}, [r9]!
+    vst1.8          {q10, q11}, [r11]!
+    vst1.8          {q4, q5}, [r9]!
+    vst1.8          {q12, q13}, [r11]!
+    vst1.8          {q6, q7}, [r9]!
+    vst1.8          {q14, q15}, [r11]!
+
+    bne             cp_src_to_dst_width_loop
+
+    subs            lr, lr, #1
+    add             r2, r2, r6, lsl #1
+    add             r3, r3, r7, lsl #1
+
+    bne             cp_src_to_dst_height_loop
+
+extra_cp_needed
+    ands            r10, r5, #0x7f                  ;check to see if extra copy is needed
+    sub             r11, r5, r10
+    ldr             r2, [r0, #yv12_buffer_config_y_buffer]       ;srcptr1
+    ldr             r3, [r1, #yv12_buffer_config_y_buffer]       ;dstptr1
+    bne             extra_cp_src_to_dst_width
+end_of_cp_src_to_dst
+
+;Copy U & V planes
+    ldr             r2, [sp]        ;srcptr1
+    ldr             r3, [sp, #4]        ;dstptr1
+    mov             r4, r4, lsr #1                  ;src uv_height
+    mov             r5, r5, lsr #1                  ;src uv_width
+    mov             r6, r6, lsr #1                  ;src uv_stride
+    mov             r7, r7, lsr #1                  ;dst uv_stride
+
+    mov             r1, #2
+
+cp_uv_loop
+
+    ;copy two rows at one time
+    mov             lr, r4, lsr #1
+
+cp_src_to_dst_height_uv_loop
+    mov             r8, r2
+    mov             r9, r3
+    add             r10, r2, r6
+    add             r11, r3, r7
+    movs            r12, r5, lsr #6
+    ble             extra_uv_cp_needed
+
+cp_src_to_dst_width_uv_loop
+    vld1.8          {q0, q1}, [r8]!
+    vld1.8          {q8, q9}, [r10]!
+    vld1.8          {q2, q3}, [r8]!
+    vld1.8          {q10, q11}, [r10]!
+
+    subs            r12, r12, #1
+
+    vst1.8          {q0, q1}, [r9]!
+    vst1.8          {q8, q9}, [r11]!
+    vst1.8          {q2, q3}, [r9]!
+    vst1.8          {q10, q11}, [r11]!
+
+    bne             cp_src_to_dst_width_uv_loop
+
+    subs            lr, lr, #1
+    add             r2, r2, r6, lsl #1
+    add             r3, r3, r7, lsl #1
+
+    bne             cp_src_to_dst_height_uv_loop
+
+extra_uv_cp_needed
+    ands            r10, r5, #0x3f                  ;check to see if extra copy is needed
+    sub             r11, r5, r10
+    ldr             r2, [sp]        ;srcptr1
+    ldr             r3, [sp, #4]        ;dstptr1
+    bne             extra_cp_src_to_dst_uv_width
+end_of_cp_src_to_dst_uv
+
+    subs            r1, r1, #1
+
+    addne               sp, sp, #8
+
+    ldrne               r2, [sp]        ;srcptr1
+    ldrne               r3, [sp, #4]        ;dstptr1
+
+    bne             cp_uv_loop
+
+    add             sp, sp, #8
+
+    vpop            {d8 - d15}
+    pop             {r4 - r11, pc}
+
+;=============================
+extra_cp_src_to_dst_width
+    add             r2, r2, r11
+    add             r3, r3, r11
+    add             r0, r8, r6
+    add             r11, r9, r7
+
+    mov             lr, r4, lsr #1
+extra_cp_src_to_dst_height_loop
+    mov             r8, r2
+    mov             r9, r3
+    add             r0, r8, r6
+    add             r11, r9, r7
+
+    mov             r12, r10
+
+extra_cp_src_to_dst_width_loop
+    vld1.8          {q0}, [r8]!
+    vld1.8          {q1}, [r0]!
+
+    subs            r12, r12, #16
+
+    vst1.8          {q0}, [r9]!
+    vst1.8          {q1}, [r11]!
+    bne             extra_cp_src_to_dst_width_loop
+
+    subs            lr, lr, #1
+
+    add             r2, r2, r6, lsl #1
+    add             r3, r3, r7, lsl #1
+
+    bne             extra_cp_src_to_dst_height_loop
+
+    b               end_of_cp_src_to_dst
+
+;=================================
+extra_cp_src_to_dst_uv_width
+    add             r2, r2, r11
+    add             r3, r3, r11
+    add             r0, r8, r6
+    add             r11, r9, r7
+
+    mov             lr, r4, lsr #1
+extra_cp_src_to_dst_height_uv_loop
+    mov             r8, r2
+    mov             r9, r3
+    add             r0, r8, r6
+    add             r11, r9, r7
+
+    mov             r12, r10
+
+extra_cp_src_to_dst_width_uv_loop
+    vld1.8          {d0}, [r8]!
+    vld1.8          {d1}, [r0]!
+
+    subs            r12, r12, #8
+
+    vst1.8          {d0}, [r9]!
+    vst1.8          {d1}, [r11]!
+    bne             extra_cp_src_to_dst_width_uv_loop
+
+    subs            lr, lr, #1
+
+    add             r2, r2, r6, lsl #1
+    add             r3, r3, r7, lsl #1
+
+    bne             extra_cp_src_to_dst_height_uv_loop
+
+    b               end_of_cp_src_to_dst_uv
+
+    ENDP
+    END
diff --git a/vpx_scale/arm/neon/vp8_vpxyv12_copysrcframe_func_neon.asm b/vpx_scale/arm/neon/vp8_vpxyv12_copysrcframe_func_neon.asm
new file mode 100644 (file)
index 0000000..ec64dbc
--- /dev/null
@@ -0,0 +1,258 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_yv12_copy_src_frame_func_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    INCLUDE asm_com_offsets.asm
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;Note: This function is used to copy source data in src_buffer[i] at beginning of
+;the encoding. The buffer has a width and height of cpi->oxcf.Width and cpi->oxcf.Height,
+;which can be ANY numbers(NOT always multiples of 16 or 4).
+
+;void vp8_yv12_copy_src_frame_func_neon(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc);
+
+|vp8_yv12_copy_src_frame_func_neon| PROC
+    push            {r4 - r11, lr}
+    vpush           {d8 - d15}
+
+    ;Copy Y plane
+    ldr             r4, [r0, #yv12_buffer_config_y_height]
+    ldr             r5, [r0, #yv12_buffer_config_y_width]
+    ldr             r6, [r0, #yv12_buffer_config_y_stride]
+    ldr             r7, [r1, #yv12_buffer_config_y_stride]
+    ldr             r2, [r0, #yv12_buffer_config_y_buffer]       ;srcptr1
+    ldr             r3, [r1, #yv12_buffer_config_y_buffer]       ;dstptr1
+
+    add             r10, r2, r6             ;second row src
+    add             r11, r3, r7             ;second row dst
+    mov             r6, r6, lsl #1
+    mov             r7, r7, lsl #1
+    sub             r6, r6, r5              ;adjust stride
+    sub             r7, r7, r5
+
+    ; copy two rows at one time
+    mov             lr, r4, lsr #1
+
+cp_src_to_dst_height_loop
+    mov             r12, r5
+
+cp_width_128_loop
+    vld1.8          {q0, q1}, [r2]!
+    vld1.8          {q4, q5}, [r10]!
+    vld1.8          {q2, q3}, [r2]!
+    vld1.8          {q6, q7}, [r10]!
+    vld1.8          {q8, q9}, [r2]!
+    vld1.8          {q12, q13}, [r10]!
+    vld1.8          {q10, q11}, [r2]!
+    vld1.8          {q14, q15}, [r10]!
+    sub             r12, r12, #128
+    cmp             r12, #128
+    vst1.8          {q0, q1}, [r3]!
+    vst1.8          {q4, q5}, [r11]!
+    vst1.8          {q2, q3}, [r3]!
+    vst1.8          {q6, q7}, [r11]!
+    vst1.8          {q8, q9}, [r3]!
+    vst1.8          {q12, q13}, [r11]!
+    vst1.8          {q10, q11}, [r3]!
+    vst1.8          {q14, q15}, [r11]!
+    bhs             cp_width_128_loop
+
+    cmp             r12, #0
+    beq             cp_width_done
+
+cp_width_8_loop
+    vld1.8          {d0}, [r2]!
+    vld1.8          {d1}, [r10]!
+    sub             r12, r12, #8
+    cmp             r12, #8
+    vst1.8          {d0}, [r3]!
+    vst1.8          {d1}, [r11]!
+    bhs             cp_width_8_loop
+
+    cmp             r12, #0
+    beq             cp_width_done
+
+cp_width_1_loop
+    ldrb            r8, [r2], #1
+    subs            r12, r12, #1
+    strb            r8, [r3], #1
+    ldrb            r8, [r10], #1
+    strb            r8, [r11], #1
+    bne             cp_width_1_loop
+
+cp_width_done
+    subs            lr, lr, #1
+    add             r2, r2, r6
+    add             r3, r3, r7
+    add             r10, r10, r6
+    add             r11, r11, r7
+    bne             cp_src_to_dst_height_loop
+
+;copy last line for Y if y_height is odd
+    tst             r4, #1
+    beq             cp_width_done_1
+    mov             r12, r5
+
+cp_width_128_loop_1
+    vld1.8          {q0, q1}, [r2]!
+    vld1.8          {q2, q3}, [r2]!
+    vld1.8          {q8, q9}, [r2]!
+    vld1.8          {q10, q11}, [r2]!
+    sub             r12, r12, #128
+    cmp             r12, #128
+    vst1.8          {q0, q1}, [r3]!
+    vst1.8          {q2, q3}, [r3]!
+    vst1.8          {q8, q9}, [r3]!
+    vst1.8          {q10, q11}, [r3]!
+    bhs             cp_width_128_loop_1
+
+    cmp             r12, #0
+    beq             cp_width_done_1
+
+cp_width_8_loop_1
+    vld1.8          {d0}, [r2]!
+    sub             r12, r12, #8
+    cmp             r12, #8
+    vst1.8          {d0}, [r3]!
+    bhs             cp_width_8_loop_1
+
+    cmp             r12, #0
+    beq             cp_width_done_1
+
+cp_width_1_loop_1
+    ldrb            r8, [r2], #1
+    subs            r12, r12, #1
+    strb            r8, [r3], #1
+    bne             cp_width_1_loop_1
+cp_width_done_1
+
+;Copy U & V planes
+    ldr             r4, [r0, #yv12_buffer_config_uv_height]
+    ldr             r5, [r0, #yv12_buffer_config_uv_width]
+    ldr             r6, [r0, #yv12_buffer_config_uv_stride]
+    ldr             r7, [r1, #yv12_buffer_config_uv_stride]
+    ldr             r2, [r0, #yv12_buffer_config_u_buffer]       ;srcptr1
+    ldr             r3, [r1, #yv12_buffer_config_u_buffer]       ;dstptr1
+
+    add             r10, r2, r6             ;second row src
+    add             r11, r3, r7             ;second row dst
+    mov             r6, r6, lsl #1
+    mov             r7, r7, lsl #1
+    sub             r6, r6, r5              ;adjust stride
+    sub             r7, r7, r5
+
+    mov             r9, #2
+
+cp_uv_loop
+    ;copy two rows at one time
+    mov             lr, r4, lsr #1
+
+cp_src_to_dst_height_uv_loop
+    mov             r12, r5
+
+cp_width_uv_64_loop
+    vld1.8          {q0, q1}, [r2]!
+    vld1.8          {q4, q5}, [r10]!
+    vld1.8          {q2, q3}, [r2]!
+    vld1.8          {q6, q7}, [r10]!
+    sub             r12, r12, #64
+    cmp             r12, #64
+    vst1.8          {q0, q1}, [r3]!
+    vst1.8          {q4, q5}, [r11]!
+    vst1.8          {q2, q3}, [r3]!
+    vst1.8          {q6, q7}, [r11]!
+    bhs             cp_width_uv_64_loop
+
+    cmp             r12, #0
+    beq             cp_width_uv_done
+
+cp_width_uv_8_loop
+    vld1.8          {d0}, [r2]!
+    vld1.8          {d1}, [r10]!
+    sub             r12, r12, #8
+    cmp             r12, #8
+    vst1.8          {d0}, [r3]!
+    vst1.8          {d1}, [r11]!
+    bhs             cp_width_uv_8_loop
+
+    cmp             r12, #0
+    beq             cp_width_uv_done
+
+cp_width_uv_1_loop
+    ldrb            r8, [r2], #1
+    subs            r12, r12, #1
+    strb            r8, [r3], #1
+    ldrb            r8, [r10], #1
+    strb            r8, [r11], #1
+    bne             cp_width_uv_1_loop
+
+cp_width_uv_done
+    subs            lr, lr, #1
+    add             r2, r2, r6
+    add             r3, r3, r7
+    add             r10, r10, r6
+    add             r11, r11, r7
+    bne             cp_src_to_dst_height_uv_loop
+
+;copy last line for U & V if uv_height is odd
+    tst             r4, #1
+    beq             cp_width_uv_done_1
+    mov             r12, r5
+
+cp_width_uv_64_loop_1
+    vld1.8          {q0, q1}, [r2]!
+    vld1.8          {q2, q3}, [r2]!
+    sub             r12, r12, #64
+    cmp             r12, #64
+    vst1.8          {q0, q1}, [r3]!
+    vst1.8          {q2, q3}, [r3]!
+    bhs             cp_width_uv_64_loop_1
+
+    cmp             r12, #0
+    beq             cp_width_uv_done_1
+
+cp_width_uv_8_loop_1
+    vld1.8          {d0}, [r2]!
+    sub             r12, r12, #8
+    cmp             r12, #8
+    vst1.8          {d0}, [r3]!
+    bhs             cp_width_uv_8_loop_1
+
+    cmp             r12, #0
+    beq             cp_width_uv_done_1
+
+cp_width_uv_1_loop_1
+    ldrb            r8, [r2], #1
+    subs            r12, r12, #1
+    strb            r8, [r3], #1
+    bne             cp_width_uv_1_loop_1
+cp_width_uv_done_1
+
+    subs            r9, r9, #1
+    ldrne           r2, [r0, #yv12_buffer_config_v_buffer]      ;srcptr1
+    ldrne           r3, [r1, #yv12_buffer_config_v_buffer]      ;dstptr1
+    ldrne           r10, [r0, #yv12_buffer_config_uv_stride]
+    ldrne           r11, [r1, #yv12_buffer_config_uv_stride]
+
+    addne           r10, r2, r10                ;second row src
+    addne           r11, r3, r11                ;second row dst
+
+    bne             cp_uv_loop
+
+    vpop            {d8 - d15}
+    pop             {r4 - r11, pc}
+
+    ENDP
+    END
diff --git a/vpx_scale/arm/neon/vp8_vpxyv12_extendframeborders_neon.asm b/vpx_scale/arm/neon/vp8_vpxyv12_extendframeborders_neon.asm
new file mode 100644 (file)
index 0000000..ebc4242
--- /dev/null
@@ -0,0 +1,308 @@
+;
+;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license
+;  that can be found in the LICENSE file in the root of the source
+;  tree. An additional intellectual property rights grant can be found
+;  in the file PATENTS.  All contributing project authors may
+;  be found in the AUTHORS file in the root of the source tree.
+;
+
+
+    EXPORT  |vp8_yv12_extend_frame_borders_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    INCLUDE asm_com_offsets.asm
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;void vp8_yv12_extend_frame_borders_neon (YV12_BUFFER_CONFIG *ybf);
+; we depend on VP8BORDERINPIXELS being 32
+
+|vp8_yv12_extend_frame_borders_neon| PROC
+    push            {r4 - r10, lr}
+    vpush           {d8 - d15}
+
+    ; Border = 32
+    ldr             r3, [r0, #yv12_buffer_config_y_width]  ; plane_width
+    ldr             r1, [r0, #yv12_buffer_config_y_buffer] ; src_ptr1
+    ldr             r4, [r0, #yv12_buffer_config_y_height] ; plane_height
+    ldr             lr, [r0, #yv12_buffer_config_y_stride] ; plane_stride
+
+; Border copy for Y plane
+; copy the left and right most columns out
+    add             r6, r1, r3              ; dest_ptr2 = src_ptr2 + 1 (src_ptr1 + plane_width)
+    sub             r2, r6, #1              ; src_ptr2 = src_ptr1 + plane_width - 1
+    sub             r5, r1, #32             ; dest_ptr1 = src_ptr1 - Border
+
+    mov             r12, r4, lsr #2         ; plane_height / 4
+
+copy_left_right_y
+    vld1.8          {d0[], d1[]}, [r1], lr
+    vld1.8          {d4[], d5[]}, [r2], lr
+    vld1.8          {d8[], d9[]}, [r1], lr
+    vld1.8          {d12[], d13[]}, [r2], lr
+    vld1.8          {d16[], d17[]}, [r1], lr
+    vld1.8          {d20[], d21[]}, [r2], lr
+    vld1.8          {d24[], d25[]}, [r1], lr
+    vld1.8          {d28[], d29[]}, [r2], lr
+
+    vmov            q1, q0
+    vmov            q3, q2
+    vmov            q5, q4
+    vmov            q7, q6
+    vmov            q9, q8
+    vmov            q11, q10
+    vmov            q13, q12
+    vmov            q15, q14
+
+    subs            r12, r12, #1
+
+    vst1.8          {q0, q1}, [r5], lr
+    vst1.8          {q2, q3}, [r6], lr
+    vst1.8          {q4, q5}, [r5], lr
+    vst1.8          {q6, q7}, [r6], lr
+    vst1.8          {q8, q9}, [r5], lr
+    vst1.8          {q10, q11}, [r6], lr
+    vst1.8          {q12, q13}, [r5], lr
+    vst1.8          {q14, q15}, [r6], lr
+
+    bne             copy_left_right_y
+
+;Now copy the top and bottom source lines into each line of the respective borders
+    ldr             r1, [r0, #yv12_buffer_config_y_buffer] ; y_buffer
+    mul             r8, r4, lr              ; plane_height * plane_stride
+
+    ; copy width is plane_stride
+    movs            r12, lr, lsr #7         ; plane_stride / 128
+
+    sub             r1, r1, #32             ; src_ptr1 = y_buffer - Border
+    add             r6, r1, r8              ; dest_ptr2 = src_ptr2 - plane_stride (src_ptr1 + (plane_height * plane_stride))
+    sub             r2, r6, lr              ; src_ptr2 = src_ptr1 + (plane_height * plane_stride) - plane_stride
+    sub             r5, r1, lr, asl #5      ; dest_ptr1 = src_ptr1 - (Border * plane_stride)
+    ble             extra_y_copy_needed     ; plane stride < 128
+
+copy_top_bottom_y
+    vld1.8          {q0, q1}, [r1]!
+    vld1.8          {q8, q9}, [r2]!
+    vld1.8          {q2, q3}, [r1]!
+    vld1.8          {q10, q11}, [r2]!
+    vld1.8          {q4, q5}, [r1]!
+    vld1.8          {q12, q13}, [r2]!
+    vld1.8          {q6, q7}, [r1]!
+    vld1.8          {q14, q15}, [r2]!
+
+    mov             r7, #32                 ; Border
+
+top_bottom_32
+    subs            r7, r7, #1
+
+    vst1.8          {q0, q1}, [r5]!
+    vst1.8          {q8, q9}, [r6]!
+    vst1.8          {q2, q3}, [r5]!
+    vst1.8          {q10, q11}, [r6]!
+    vst1.8          {q4, q5}, [r5]!
+    vst1.8          {q12, q13}, [r6]!
+    vst1.8          {q6, q7}, [r5]!
+    vst1.8          {q14, q15}, [r6]!
+
+    add             r5, r5, lr              ; dest_ptr1 += plane_stride
+    sub             r5, r5, #128            ; dest_ptr1 -= 128
+    add             r6, r6, lr              ; dest_ptr2 += plane_stride
+    sub             r6, r6, #128            ; dest_ptr2 -= 128
+
+    bne             top_bottom_32
+
+    sub             r5, r1, lr, asl #5      ; src_ptr1 - (Border* plane_stride)
+    add             r6, r2, lr              ; src_ptr2 + plane_stride
+
+    subs            r12, r12, #1
+    bne             copy_top_bottom_y
+
+extra_y_copy_needed
+    mov             r7, lr, lsr #4          ; check to see if extra copy is needed
+    ands            r7, r7, #0x7
+    bne             extra_top_bottom_y
+end_of_border_copy_y
+
+;Border copy for U, V planes
+; Border = 16
+    ldr             r7, [r0, #yv12_buffer_config_u_buffer]  ; src_ptr1
+    ldr             lr, [r0, #yv12_buffer_config_uv_stride] ; plane_stride
+    ldr             r3, [r0, #yv12_buffer_config_uv_width]  ; plane_width
+    ldr             r4, [r0, #yv12_buffer_config_uv_height] ; plane_height
+
+    mov             r10, #2
+
+;copy the left and right most columns out
+border_copy_uv
+    mov             r1, r7                  ; src_ptr1 needs to be saved for second half of loop
+    sub             r5, r1, #16             ; dest_ptr1 = src_ptr1 - Border
+    add             r6, r1, r3              ; dest_ptr2 = src_ptr2 + 1 (src_ptr1 + plane_width)
+    sub             r2, r6, #1              ; src_ptr2 = src_ptr1 + plane_width - 1
+
+    mov             r12, r4, lsr #3         ; plane_height / 8
+
+copy_left_right_uv
+    vld1.8          {d0[], d1[]}, [r1], lr
+    vld1.8          {d2[], d3[]}, [r2], lr
+    vld1.8          {d4[], d5[]}, [r1], lr
+    vld1.8          {d6[], d7[]}, [r2], lr
+    vld1.8          {d8[], d9[]},  [r1], lr
+    vld1.8          {d10[], d11[]}, [r2], lr
+    vld1.8          {d12[], d13[]}, [r1], lr
+    vld1.8          {d14[], d15[]}, [r2], lr
+    vld1.8          {d16[], d17[]}, [r1], lr
+    vld1.8          {d18[], d19[]}, [r2], lr
+    vld1.8          {d20[], d21[]}, [r1], lr
+    vld1.8          {d22[], d23[]}, [r2], lr
+    vld1.8          {d24[], d25[]}, [r1], lr
+    vld1.8          {d26[], d27[]}, [r2], lr
+    vld1.8          {d28[], d29[]}, [r1], lr
+    vld1.8          {d30[], d31[]}, [r2], lr
+
+    subs            r12, r12, #1
+
+    vst1.8          {q0}, [r5], lr
+    vst1.8          {q1}, [r6], lr
+    vst1.8          {q2}, [r5], lr
+    vst1.8          {q3}, [r6], lr
+    vst1.8          {q4}, [r5], lr
+    vst1.8          {q5}, [r6], lr
+    vst1.8          {q6}, [r5], lr
+    vst1.8          {q7}, [r6], lr
+    vst1.8          {q8}, [r5], lr
+    vst1.8          {q9}, [r6], lr
+    vst1.8          {q10}, [r5], lr
+    vst1.8          {q11}, [r6], lr
+    vst1.8          {q12}, [r5], lr
+    vst1.8          {q13}, [r6], lr
+    vst1.8          {q14}, [r5], lr
+    vst1.8          {q15}, [r6], lr
+
+    bne             copy_left_right_uv
+
+;Now copy the top and bottom source lines into each line of the respective borders
+    mov             r1, r7
+    mul             r8, r4, lr              ; plane_height * plane_stride
+    movs            r12, lr, lsr #6         ; plane_stride / 64
+
+    sub             r1, r1, #16             ; src_ptr1 = u_buffer - Border
+    add             r6, r1, r8              ; dest_ptr2 = src_ptr2 + plane_stride (src_ptr1 + (plane_height * plane_stride)
+    sub             r2, r6, lr              ; src_ptr2 = src_ptr1 + (plane_height * plane_stride) - plane_stride
+    sub             r5, r1, lr, asl #4      ; dest_ptr1 = src_ptr1 - (Border * plane_stride)
+    ble             extra_uv_copy_needed    ; plane_stride < 64
+
+copy_top_bottom_uv
+    vld1.8          {q0, q1}, [r1]!
+    vld1.8          {q8, q9}, [r2]!
+    vld1.8          {q2, q3}, [r1]!
+    vld1.8          {q10, q11}, [r2]!
+
+    mov             r7, #16                 ; Border
+
+top_bottom_16
+    subs            r7, r7, #1
+
+    vst1.8          {q0, q1}, [r5]!
+    vst1.8          {q8, q9}, [r6]!
+    vst1.8          {q2, q3}, [r5]!
+    vst1.8          {q10, q11}, [r6]!
+
+    add             r5, r5, lr              ; dest_ptr1 += plane_stride
+    sub             r5, r5, #64
+    add             r6, r6, lr              ; dest_ptr2 += plane_stride
+    sub             r6, r6, #64
+
+    bne             top_bottom_16
+
+    sub             r5, r1, lr, asl #4      ; dest_ptr1 = src_ptr1 - (Border * plane_stride)
+    add             r6, r2, lr              ; dest_ptr2 = src_ptr2 + plane_stride
+
+    subs            r12, r12, #1
+    bne             copy_top_bottom_uv
+extra_uv_copy_needed
+    mov             r7, lr, lsr #3          ; check to see if extra copy is needed
+    ands            r7, r7, #0x7
+    bne             extra_top_bottom_uv
+
+end_of_border_copy_uv
+    subs            r10, r10, #1
+    ldrne           r7, [r0, #yv12_buffer_config_v_buffer] ; src_ptr1
+    bne             border_copy_uv
+
+    vpop            {d8 - d15}
+    pop             {r4 - r10, pc}
+
+;;;;;;;;;;;;;;;;;;;;;;
+extra_top_bottom_y
+    vld1.8          {q0}, [r1]!
+    vld1.8          {q2}, [r2]!
+
+    mov             r9, #4                  ; 32 >> 3
+
+extra_top_bottom_32
+    subs            r9, r9, #1
+
+    vst1.8          {q0}, [r5], lr
+    vst1.8          {q2}, [r6], lr
+    vst1.8          {q0}, [r5], lr
+    vst1.8          {q2}, [r6], lr
+    vst1.8          {q0}, [r5], lr
+    vst1.8          {q2}, [r6], lr
+    vst1.8          {q0}, [r5], lr
+    vst1.8          {q2}, [r6], lr
+    vst1.8          {q0}, [r5], lr
+    vst1.8          {q2}, [r6], lr
+    vst1.8          {q0}, [r5], lr
+    vst1.8          {q2}, [r6], lr
+    vst1.8          {q0}, [r5], lr
+    vst1.8          {q2}, [r6], lr
+    vst1.8          {q0}, [r5], lr
+    vst1.8          {q2}, [r6], lr
+    bne             extra_top_bottom_32
+
+    sub             r5, r1, lr, asl #5      ; src_ptr1 - (Border * plane_stride)
+    add             r6, r2, lr              ; src_ptr2 + plane_stride
+    subs            r7, r7, #1
+    bne             extra_top_bottom_y
+
+    b               end_of_border_copy_y
+
+extra_top_bottom_uv
+    vld1.8          {d0}, [r1]!
+    vld1.8          {d8}, [r2]!
+
+    mov             r9, #2                  ; 16 >> 3
+
+extra_top_bottom_16
+    subs            r9, r9, #1
+
+    vst1.8          {d0}, [r5], lr
+    vst1.8          {d8}, [r6], lr
+    vst1.8          {d0}, [r5], lr
+    vst1.8          {d8}, [r6], lr
+    vst1.8          {d0}, [r5], lr
+    vst1.8          {d8}, [r6], lr
+    vst1.8          {d0}, [r5], lr
+    vst1.8          {d8}, [r6], lr
+    vst1.8          {d0}, [r5], lr
+    vst1.8          {d8}, [r6], lr
+    vst1.8          {d0}, [r5], lr
+    vst1.8          {d8}, [r6], lr
+    vst1.8          {d0}, [r5], lr
+    vst1.8          {d8}, [r6], lr
+    vst1.8          {d0}, [r5], lr
+    vst1.8          {d8}, [r6], lr
+    bne             extra_top_bottom_16
+
+    sub             r5, r1, lr, asl #4      ; src_ptr1 - (Border * plane_stride)
+    add             r6, r2, lr              ; src_ptr2 + plane_stride
+    subs            r7, r7, #1
+    bne             extra_top_bottom_uv
+
+    b               end_of_border_copy_uv
+
+    ENDP
+    END
diff --git a/vpx_scale/arm/neon/yv12extend_arm.c b/vpx_scale/arm/neon/yv12extend_arm.c
new file mode 100644 (file)
index 0000000..7529fc6
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_scale/yv12config.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_scale/vpxscale.h"
+
+extern void vp8_yv12_copy_frame_func_neon(YV12_BUFFER_CONFIG *src_ybc,
+                                          YV12_BUFFER_CONFIG *dst_ybc);
+
+void vp8_yv12_copy_frame_neon(YV12_BUFFER_CONFIG *src_ybc,
+                              YV12_BUFFER_CONFIG *dst_ybc)
+{
+    vp8_yv12_copy_frame_func_neon(src_ybc, dst_ybc);
+
+    vp8_yv12_extend_frame_borders_neon(dst_ybc);
+}
diff --git a/vpx_scale/generic/bicubic_scaler.c b/vpx_scale/generic/bicubic_scaler.c
new file mode 100644 (file)
index 0000000..4468e9d
--- /dev/null
@@ -0,0 +1,602 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include <float.h>
+#include <math.h>
+#include <stdio.h>
+#include "vpx_mem/vpx_mem.h"
+#include "vpxscale_arbitrary.h"
+
+#define FIXED_POINT
+
+#define MAX_IN_WIDTH        800
+#define MAX_IN_HEIGHT       600
+#define MAX_OUT_WIDTH       800
+#define MAX_OUT_HEIGHT      600
+#define MAX_OUT_DIMENSION   ((MAX_OUT_WIDTH > MAX_OUT_HEIGHT) ? \
+                             MAX_OUT_WIDTH : MAX_OUT_HEIGHT)
+
+BICUBIC_SCALER_STRUCT g_b_scaler;
+static int g_first_time = 1;
+
+#pragma DATA_SECTION(g_hbuf, "VP6_HEAP")
+#pragma DATA_ALIGN (g_hbuf, 32);
+unsigned char g_hbuf[MAX_OUT_DIMENSION];
+
+#pragma DATA_SECTION(g_hbuf_uv, "VP6_HEAP")
+#pragma DATA_ALIGN (g_hbuf_uv, 32);
+unsigned char g_hbuf_uv[MAX_OUT_DIMENSION];
+
+
+#ifdef FIXED_POINT
+static int a_i = 0.6 * 65536;
+#else
+static float a = -0.6;
+#endif
+
+#ifdef FIXED_POINT
+//         3     2
+// C0 = a*t - a*t
+//
+static short c0_fixed(unsigned int t)
+{
+    // put t in Q16 notation
+    unsigned short v1, v2;
+
+    // Q16
+    v1 = (a_i * t) >> 16;
+    v1 = (v1 * t) >> 16;
+
+    // Q16
+    v2 = (a_i * t) >> 16;
+    v2 = (v2 * t) >> 16;
+    v2 = (v2 * t) >> 16;
+
+    // Q12
+    return -((v1 - v2) >> 4);
+}
+
+//                     2          3
+// C1 = a*t + (3-2*a)*t  - (2-a)*t
+//
+static short c1_fixed(unsigned int t)
+{
+    unsigned short v1, v2, v3;
+    unsigned short two, three;
+
+    // Q16
+    v1 = (a_i * t) >> 16;
+
+    // Q13
+    two = 2 << 13;
+    v2 = two - (a_i >> 3);
+    v2 = (v2 * t) >> 16;
+    v2 = (v2 * t) >> 16;
+    v2 = (v2 * t) >> 16;
+
+    // Q13
+    three = 3 << 13;
+    v3 = three - (2 * (a_i >> 3));
+    v3 = (v3 * t) >> 16;
+    v3 = (v3 * t) >> 16;
+
+    // Q12
+    return (((v1 >> 3) - v2 + v3) >> 1);
+
+}
+
+//                 2          3
+// C2 = 1 - (3-a)*t  + (2-a)*t
+//
+static short c2_fixed(unsigned int t)
+{
+    unsigned short v1, v2, v3;
+    unsigned short two, three;
+
+    // Q13
+    v1 = 1 << 13;
+
+    // Q13
+    three = 3 << 13;
+    v2 = three - (a_i >> 3);
+    v2 = (v2 * t) >> 16;
+    v2 = (v2 * t) >> 16;
+
+    // Q13
+    two = 2 << 13;
+    v3 = two - (a_i >> 3);
+    v3 = (v3 * t) >> 16;
+    v3 = (v3 * t) >> 16;
+    v3 = (v3 * t) >> 16;
+
+    // Q12
+    return (v1 - v2 + v3) >> 1;
+}
+
+//                 2      3
+// C3 = a*t - 2*a*t  + a*t
+//
+static short c3_fixed(unsigned int t)
+{
+    int v1, v2, v3;
+
+    // Q16
+    v1 = (a_i * t) >> 16;
+
+    // Q15
+    v2 = 2 * (a_i >> 1);
+    v2 = (v2 * t) >> 16;
+    v2 = (v2 * t) >> 16;
+
+    // Q16
+    v3 = (a_i * t) >> 16;
+    v3 = (v3 * t) >> 16;
+    v3 = (v3 * t) >> 16;
+
+    // Q12
+    return ((v2 - (v1 >> 1) - (v3 >> 1)) >> 3);
+}
+#else
+//          3     2
+// C0 = -a*t + a*t
+//
+float C0(float t)
+{
+    return -a * t * t * t + a * t * t;
+}
+
+//                      2          3
+// C1 = -a*t + (2*a+3)*t  - (a+2)*t
+//
+float C1(float t)
+{
+    return -(a + 2.0f) * t * t * t + (2.0f * a + 3.0f) * t * t - a * t;
+}
+
+//                 2          3
+// C2 = 1 - (a+3)*t  + (a+2)*t
+//
+float C2(float t)
+{
+    return (a + 2.0f) * t * t * t - (a + 3.0f) * t * t + 1.0f;
+}
+
+//                 2      3
+// C3 = a*t - 2*a*t  + a*t
+//
+float C3(float t)
+{
+    return a * t * t * t - 2.0f * a * t * t + a * t;
+}
+#endif
+
+#if 0
+int compare_real_fixed()
+{
+    int i, errors = 0;
+    float mult = 1.0 / 10000.0;
+    unsigned int fixed_mult = mult * 4294967296;//65536;
+    unsigned int phase_offset_int;
+    float phase_offset_real;
+
+    for (i = 0; i < 10000; i++)
+    {
+        int fixed0, fixed1, fixed2, fixed3, fixed_total;
+        int real0, real1, real2, real3, real_total;
+
+        phase_offset_real = (float)i * mult;
+        phase_offset_int = (fixed_mult * i) >> 16;
+//      phase_offset_int = phase_offset_real * 65536;
+
+        fixed0 = c0_fixed(phase_offset_int);
+        real0 = C0(phase_offset_real) * 4096.0;
+
+        if ((abs(fixed0) > (abs(real0) + 1)) || (abs(fixed0) < (abs(real0) - 1)))
+            errors++;
+
+        fixed1 = c1_fixed(phase_offset_int);
+        real1 = C1(phase_offset_real) * 4096.0;
+
+        if ((abs(fixed1) > (abs(real1) + 1)) || (abs(fixed1) < (abs(real1) - 1)))
+            errors++;
+
+        fixed2 = c2_fixed(phase_offset_int);
+        real2 = C2(phase_offset_real) * 4096.0;
+
+        if ((abs(fixed2) > (abs(real2) + 1)) || (abs(fixed2) < (abs(real2) - 1)))
+            errors++;
+
+        fixed3 = c3_fixed(phase_offset_int);
+        real3 = C3(phase_offset_real) * 4096.0;
+
+        if ((abs(fixed3) > (abs(real3) + 1)) || (abs(fixed3) < (abs(real3) - 1)))
+            errors++;
+
+        fixed_total = fixed0 + fixed1 + fixed2 + fixed3;
+        real_total = real0 + real1 + real2 + real3;
+
+        if ((fixed_total > 4097) || (fixed_total < 4094))
+            errors ++;
+
+        if ((real_total > 4097) || (real_total < 4095))
+            errors ++;
+    }
+
+    return errors;
+}
+#endif
+
+// Find greatest common denominator between two integers.  Method used here is
+//  slow compared to Euclid's algorithm, but does not require any division.
+int gcd(int a, int b)
+{
+    // Problem with this algorithm is that if a or b = 0 this function
+    //  will never exit.  Don't want to return 0 because any computation
+    //  that was based on a common denoninator and tried to reduce by
+    //  dividing by 0 would fail.  Best solution that could be thought of
+    //  would to be fail by returing a 1;
+    if (a <= 0 || b <= 0)
+        return 1;
+
+    while (a != b)
+    {
+        if (b > a)
+            b = b - a;
+        else
+        {
+            int tmp = a;//swap large and
+            a = b; //small
+            b = tmp;
+        }
+    }
+
+    return b;
+}
+
+void bicubic_coefficient_init()
+{
+    vpx_memset(&g_b_scaler, 0, sizeof(BICUBIC_SCALER_STRUCT));
+    g_first_time = 0;
+}
+
+void bicubic_coefficient_destroy()
+{
+    if (!g_first_time)
+    {
+        vpx_free(g_b_scaler.l_w);
+
+        vpx_free(g_b_scaler.l_h);
+
+        vpx_free(g_b_scaler.l_h_uv);
+
+        vpx_free(g_b_scaler.c_w);
+
+        vpx_free(g_b_scaler.c_h);
+
+        vpx_free(g_b_scaler.c_h_uv);
+
+        vpx_memset(&g_b_scaler, 0, sizeof(BICUBIC_SCALER_STRUCT));
+    }
+}
+
+// Create the coeffients that will be used for the cubic interpolation.
+//  Because scaling does not have to be equal in the vertical and horizontal
+//  regimes the phase offsets will be different.  There are 4 coefficents
+//  for each point, two on each side.  The layout is that there are the
+//  4 coefficents for each phase in the array and then the next phase.
+int bicubic_coefficient_setup(int in_width, int in_height, int out_width, int out_height)
+{
+    int i;
+#ifdef FIXED_POINT
+    int phase_offset_int;
+    unsigned int fixed_mult;
+    int product_val = 0;
+#else
+    float phase_offset;
+#endif
+    int gcd_w, gcd_h, gcd_h_uv, d_w, d_h, d_h_uv;
+
+    if (g_first_time)
+        bicubic_coefficient_init();
+
+
+    // check to see if the coefficents have already been set up correctly
+    if ((in_width == g_b_scaler.in_width) && (in_height == g_b_scaler.in_height)
+        && (out_width == g_b_scaler.out_width) && (out_height == g_b_scaler.out_height))
+        return 0;
+
+    g_b_scaler.in_width = in_width;
+    g_b_scaler.in_height = in_height;
+    g_b_scaler.out_width = out_width;
+    g_b_scaler.out_height = out_height;
+
+    // Don't want to allow crazy scaling, just try and prevent a catastrophic
+    //  failure here.  Want to fail after setting the member functions so if
+    //  if the scaler is called the member functions will not scale.
+    if (out_width <= 0 || out_height <= 0)
+        return -1;
+
+    // reduce in/out width and height ratios using the gcd
+    gcd_w = gcd(out_width, in_width);
+    gcd_h = gcd(out_height, in_height);
+    gcd_h_uv = gcd(out_height, in_height / 2);
+
+    // the numerator width and height are to be saved in
+    //  globals so they can be used during the scaling process
+    //  without having to be recalculated.
+    g_b_scaler.nw = out_width / gcd_w;
+    d_w = in_width / gcd_w;
+
+    g_b_scaler.nh = out_height / gcd_h;
+    d_h = in_height / gcd_h;
+
+    g_b_scaler.nh_uv = out_height / gcd_h_uv;
+    d_h_uv = (in_height / 2) / gcd_h_uv;
+
+    // allocate memory for the coefficents
+    vpx_free(g_b_scaler.l_w);
+
+    vpx_free(g_b_scaler.l_h);
+
+    vpx_free(g_b_scaler.l_h_uv);
+
+    g_b_scaler.l_w = (short *)vpx_memalign(32, out_width * 2);
+    g_b_scaler.l_h = (short *)vpx_memalign(32, out_height * 2);
+    g_b_scaler.l_h_uv = (short *)vpx_memalign(32, out_height * 2);
+
+    vpx_free(g_b_scaler.c_w);
+
+    vpx_free(g_b_scaler.c_h);
+
+    vpx_free(g_b_scaler.c_h_uv);
+
+    g_b_scaler.c_w = (short *)vpx_memalign(32, g_b_scaler.nw * 4 * 2);
+    g_b_scaler.c_h = (short *)vpx_memalign(32, g_b_scaler.nh * 4 * 2);
+    g_b_scaler.c_h_uv = (short *)vpx_memalign(32, g_b_scaler.nh_uv * 4 * 2);
+
+    g_b_scaler.hbuf = g_hbuf;
+    g_b_scaler.hbuf_uv = g_hbuf_uv;
+
+    // Set up polyphase filter taps.  This needs to be done before
+    //  the scaling because of the floating point math required.  The
+    //  coefficients are multiplied by 2^12 so that fixed point math
+    //  can be used in the main scaling loop.
+#ifdef FIXED_POINT
+    fixed_mult = (1.0 / (float)g_b_scaler.nw) * 4294967296;
+
+    product_val = 0;
+
+    for (i = 0; i < g_b_scaler.nw; i++)
+    {
+        if (product_val > g_b_scaler.nw)
+            product_val -= g_b_scaler.nw;
+
+        phase_offset_int = (fixed_mult * product_val) >> 16;
+
+        g_b_scaler.c_w[i*4]   = c3_fixed(phase_offset_int);
+        g_b_scaler.c_w[i*4+1] = c2_fixed(phase_offset_int);
+        g_b_scaler.c_w[i*4+2] = c1_fixed(phase_offset_int);
+        g_b_scaler.c_w[i*4+3] = c0_fixed(phase_offset_int);
+
+        product_val += d_w;
+    }
+
+
+    fixed_mult = (1.0 / (float)g_b_scaler.nh) * 4294967296;
+
+    product_val = 0;
+
+    for (i = 0; i < g_b_scaler.nh; i++)
+    {
+        if (product_val > g_b_scaler.nh)
+            product_val -= g_b_scaler.nh;
+
+        phase_offset_int = (fixed_mult * product_val) >> 16;
+
+        g_b_scaler.c_h[i*4]   = c0_fixed(phase_offset_int);
+        g_b_scaler.c_h[i*4+1] = c1_fixed(phase_offset_int);
+        g_b_scaler.c_h[i*4+2] = c2_fixed(phase_offset_int);
+        g_b_scaler.c_h[i*4+3] = c3_fixed(phase_offset_int);
+
+        product_val += d_h;
+    }
+
+    fixed_mult = (1.0 / (float)g_b_scaler.nh_uv) * 4294967296;
+
+    product_val = 0;
+
+    for (i = 0; i < g_b_scaler.nh_uv; i++)
+    {
+        if (product_val > g_b_scaler.nh_uv)
+            product_val -= g_b_scaler.nh_uv;
+
+        phase_offset_int = (fixed_mult * product_val) >> 16;
+
+        g_b_scaler.c_h_uv[i*4]   = c0_fixed(phase_offset_int);
+        g_b_scaler.c_h_uv[i*4+1] = c1_fixed(phase_offset_int);
+        g_b_scaler.c_h_uv[i*4+2] = c2_fixed(phase_offset_int);
+        g_b_scaler.c_h_uv[i*4+3] = c3_fixed(phase_offset_int);
+
+        product_val += d_h_uv;
+    }
+
+#else
+
+    for (i = 0; i < g_nw; i++)
+    {
+        phase_offset = (float)((i * d_w) % g_nw) / (float)g_nw;
+        g_c_w[i*4]   = (C3(phase_offset) * 4096.0);
+        g_c_w[i*4+1] = (C2(phase_offset) * 4096.0);
+        g_c_w[i*4+2] = (C1(phase_offset) * 4096.0);
+        g_c_w[i*4+3] = (C0(phase_offset) * 4096.0);
+    }
+
+    for (i = 0; i < g_nh; i++)
+    {
+        phase_offset = (float)((i * d_h) % g_nh) / (float)g_nh;
+        g_c_h[i*4]   = (C0(phase_offset) * 4096.0);
+        g_c_h[i*4+1] = (C1(phase_offset) * 4096.0);
+        g_c_h[i*4+2] = (C2(phase_offset) * 4096.0);
+        g_c_h[i*4+3] = (C3(phase_offset) * 4096.0);
+    }
+
+    for (i = 0; i < g_nh_uv; i++)
+    {
+        phase_offset = (float)((i * d_h_uv) % g_nh_uv) / (float)g_nh_uv;
+        g_c_h_uv[i*4]   = (C0(phase_offset) * 4096.0);
+        g_c_h_uv[i*4+1] = (C1(phase_offset) * 4096.0);
+        g_c_h_uv[i*4+2] = (C2(phase_offset) * 4096.0);
+        g_c_h_uv[i*4+3] = (C3(phase_offset) * 4096.0);
+    }
+
+#endif
+
+    // Create an array that corresponds input lines to output lines.
+    //  This doesn't require floating point math, but it does require
+    //  a division and because hardware division is not present that
+    //  is a call.
+    for (i = 0; i < out_width; i++)
+    {
+        g_b_scaler.l_w[i] = (i * d_w) / g_b_scaler.nw;
+
+        if ((g_b_scaler.l_w[i] + 2) <= in_width)
+            g_b_scaler.max_usable_out_width = i;
+
+    }
+
+    for (i = 0; i < out_height + 1; i++)
+    {
+        g_b_scaler.l_h[i] = (i * d_h) / g_b_scaler.nh;
+        g_b_scaler.l_h_uv[i] = (i * d_h_uv) / g_b_scaler.nh_uv;
+    }
+
+    return 0;
+}
+
+int bicubic_scale(int in_width, int in_height, int in_stride,
+                  int out_width, int out_height, int out_stride,
+                  unsigned char *input_image, unsigned char *output_image)
+{
+    short *RESTRICT l_w, * RESTRICT l_h;
+    short *RESTRICT c_w, * RESTRICT c_h;
+    unsigned char *RESTRICT ip, * RESTRICT op;
+    unsigned char *RESTRICT hbuf;
+    int h, w, lw, lh;
+    int temp_sum;
+    int phase_offset_w, phase_offset_h;
+
+    c_w = g_b_scaler.c_w;
+    c_h = g_b_scaler.c_h;
+
+    op = output_image;
+
+    l_w = g_b_scaler.l_w;
+    l_h = g_b_scaler.l_h;
+
+    phase_offset_h = 0;
+
+    for (h = 0; h < out_height; h++)
+    {
+        // select the row to work on
+        lh = l_h[h];
+        ip = input_image + (in_stride * lh);
+
+        // vp8_filter the row vertically into an temporary buffer.
+        //  If the phase offset == 0 then all the multiplication
+        //  is going to result in the output equalling the input.
+        //  So instead point the temporary buffer to the input.
+        //  Also handle the boundry condition of not being able to
+        //  filter that last lines.
+        if (phase_offset_h && (lh < in_height - 2))
+        {
+            hbuf = g_b_scaler.hbuf;
+
+            for (w = 0; w < in_width; w++)
+            {
+                temp_sum =  c_h[phase_offset_h*4+3] * ip[w - in_stride];
+                temp_sum += c_h[phase_offset_h*4+2] * ip[w];
+                temp_sum += c_h[phase_offset_h*4+1] * ip[w + in_stride];
+                temp_sum += c_h[phase_offset_h*4]   * ip[w + 2*in_stride];
+
+                hbuf[w] = temp_sum >> 12;
+            }
+        }
+        else
+            hbuf = ip;
+
+        // increase the phase offset for the next time around.
+        if (++phase_offset_h >= g_b_scaler.nh)
+            phase_offset_h = 0;
+
+        // now filter and expand it horizontally into the final
+        //  output buffer
+        phase_offset_w = 0;
+
+        for (w = 0; w < out_width; w++)
+        {
+            // get the index to use to expand the image
+            lw = l_w[w];
+
+            temp_sum =  c_w[phase_offset_w*4]   * hbuf[lw - 1];
+            temp_sum += c_w[phase_offset_w*4+1] * hbuf[lw];
+            temp_sum += c_w[phase_offset_w*4+2] * hbuf[lw + 1];
+            temp_sum += c_w[phase_offset_w*4+3] * hbuf[lw + 2];
+            temp_sum = temp_sum >> 12;
+
+            if (++phase_offset_w >= g_b_scaler.nw)
+                phase_offset_w = 0;
+
+            // boundry conditions
+            if ((lw + 2) >= in_width)
+                temp_sum = hbuf[lw];
+
+            if (lw == 0)
+                temp_sum = hbuf[0];
+
+            op[w] = temp_sum;
+        }
+
+        op += out_stride;
+    }
+
+    return 0;
+}
+
+void bicubic_scale_frame_reset()
+{
+    g_b_scaler.out_width = 0;
+    g_b_scaler.out_height = 0;
+}
+
+void bicubic_scale_frame(YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst,
+                         int new_width, int new_height)
+{
+
+    dst->y_width = new_width;
+    dst->y_height = new_height;
+    dst->uv_width = new_width / 2;
+    dst->uv_height = new_height / 2;
+
+    dst->y_stride = dst->y_width;
+    dst->uv_stride = dst->uv_width;
+
+    bicubic_scale(src->y_width, src->y_height, src->y_stride,
+                  new_width, new_height, dst->y_stride,
+                  src->y_buffer, dst->y_buffer);
+
+    bicubic_scale(src->uv_width, src->uv_height, src->uv_stride,
+                  new_width / 2, new_height / 2, dst->uv_stride,
+                  src->u_buffer, dst->u_buffer);
+
+    bicubic_scale(src->uv_width, src->uv_height, src->uv_stride,
+                  new_width / 2, new_height / 2, dst->uv_stride,
+                  src->v_buffer, dst->v_buffer);
+}
diff --git a/vpx_scale/generic/gen_scalers.c b/vpx_scale/generic/gen_scalers.c
new file mode 100644 (file)
index 0000000..9beb162
--- /dev/null
@@ -0,0 +1,956 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_scale/vpxscale.h"
+#include "vpx_mem/vpx_mem.h"
+/****************************************************************************
+*  Imports
+****************************************************************************/
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vp8_horizontal_line_4_5_scale_c
+ *
+ *  INPUTS        : const unsigned char *source : Pointer to source data.
+ *                  unsigned int source_width    : Stride of source.
+ *                  unsigned char *dest         : Pointer to destination data.
+ *                  unsigned int dest_width      : Stride of destination (NOT USED).
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Copies horizontal line of pixels from source to
+ *                  destination scaling up by 4 to 5.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+void vp8_horizontal_line_4_5_scale_c
+(
+    const unsigned char *source,
+    unsigned int source_width,
+    unsigned char *dest,
+    unsigned int dest_width
+)
+{
+    unsigned i;
+    unsigned int a, b, c;
+    unsigned char *des = dest;
+    const unsigned char *src = source;
+
+    (void) dest_width;
+
+    for (i = 0; i < source_width - 4; i += 4)
+    {
+        a = src[0];
+        b = src[1];
+        des [0] = (unsigned char) a;
+        des [1] = (unsigned char)((a * 51 + 205 * b + 128) >> 8);
+        c = src[2] * 154;
+        a = src[3];
+        des [2] = (unsigned char)((b * 102 + c + 128) >> 8);
+        des [3] = (unsigned char)((c + 102 * a + 128) >> 8);
+        b = src[4];
+        des [4] = (unsigned char)((a * 205 + 51 * b + 128) >> 8);
+
+        src += 4;
+        des += 5;
+    }
+
+    a = src[0];
+    b = src[1];
+    des [0] = (unsigned char)(a);
+    des [1] = (unsigned char)((a * 51 + 205 * b + 128) >> 8);
+    c = src[2] * 154;
+    a = src[3];
+    des [2] = (unsigned char)((b * 102 + c + 128) >> 8);
+    des [3] = (unsigned char)((c + 102 * a + 128) >> 8);
+    des [4] = (unsigned char)(a);
+
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vp8_vertical_band_4_5_scale_c
+ *
+ *  INPUTS        : unsigned char *dest    : Pointer to destination data.
+ *                  unsigned int dest_pitch : Stride of destination data.
+ *                  unsigned int dest_width : Width of destination data.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Scales vertical band of pixels by scale 4 to 5. The
+ *                  height of the band scaled is 4-pixels.
+ *
+ *  SPECIAL NOTES : The routine uses the first line of the band below
+ *                  the current band.
+ *
+ ****************************************************************************/
+void vp8_vertical_band_4_5_scale_c(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width)
+{
+    unsigned int i;
+    unsigned int a, b, c, d;
+    unsigned char *des = dest;
+
+    for (i = 0; i < dest_width; i++)
+    {
+        a = des [0];
+        b = des [dest_pitch];
+
+        des[dest_pitch] = (unsigned char)((a * 51 + 205 * b + 128) >> 8);
+
+        c = des[dest_pitch*2] * 154;
+        d = des[dest_pitch*3];
+
+        des [dest_pitch*2] = (unsigned char)((b * 102 + c + 128) >> 8);
+        des [dest_pitch*3] = (unsigned char)((c + 102 * d + 128) >> 8);
+
+        /* First line in next band */
+        a = des [dest_pitch * 5];
+        des [dest_pitch * 4] = (unsigned char)((d * 205 + 51 * a + 128) >> 8);
+
+        des ++;
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vp8_last_vertical_band_4_5_scale_c
+ *
+ *  INPUTS        : unsigned char *dest    : Pointer to destination data.
+ *                  unsigned int dest_pitch : Stride of destination data.
+ *                  unsigned int dest_width : Width of destination data.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Scales last vertical band of pixels by scale 4 to 5. The
+ *                  height of the band scaled is 4-pixels.
+ *
+ *  SPECIAL NOTES : The routine does not have available the first line of
+ *                  the band below the current band, since this is the
+ *                  last band.
+ *
+ ****************************************************************************/
+void vp8_last_vertical_band_4_5_scale_c(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width)
+{
+    unsigned int i;
+    unsigned int a, b, c, d;
+    unsigned char *des = dest;
+
+    for (i = 0; i < dest_width; ++i)
+    {
+        a = des[0];
+        b = des[dest_pitch];
+
+        des[dest_pitch] = (unsigned char)((a * 51 + 205 * b + 128) >> 8);
+
+        c = des[dest_pitch*2] * 154;
+        d = des[dest_pitch*3];
+
+        des [dest_pitch*2] = (unsigned char)((b * 102 + c + 128) >> 8);
+        des [dest_pitch*3] = (unsigned char)((c + 102 * d + 128) >> 8);
+
+        /* No other line for interplation of this line, so .. */
+        des[dest_pitch*4] = (unsigned char) d;
+
+        des++;
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vp8_horizontal_line_2_3_scale_c
+ *
+ *  INPUTS        : const unsigned char *source : Pointer to source data.
+ *                  unsigned int source_width    : Stride of source.
+ *                  unsigned char *dest         : Pointer to destination data.
+ *                  unsigned int dest_width      : Stride of destination (NOT USED).
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Copies horizontal line of pixels from source to
+ *                  destination scaling up by 2 to 3.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ *
+ ****************************************************************************/
+void vp8_horizontal_line_2_3_scale_c
+(
+    const unsigned char *source,
+    unsigned int source_width,
+    unsigned char *dest,
+    unsigned int dest_width
+)
+{
+    unsigned int i;
+    unsigned int a, b, c;
+    unsigned char *des = dest;
+    const unsigned char *src = source;
+
+    (void) dest_width;
+
+    for (i = 0; i < source_width - 2; i += 2)
+    {
+        a = src[0];
+        b = src[1];
+        c = src[2];
+
+        des [0] = (unsigned char)(a);
+        des [1] = (unsigned char)((a * 85 + 171 * b + 128) >> 8);
+        des [2] = (unsigned char)((b * 171 + 85 * c + 128) >> 8);
+
+        src += 2;
+        des += 3;
+    }
+
+    a = src[0];
+    b = src[1];
+    des [0] = (unsigned char)(a);
+    des [1] = (unsigned char)((a * 85 + 171 * b + 128) >> 8);
+    des [2] = (unsigned char)(b);
+}
+
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vp8_vertical_band_2_3_scale_c
+ *
+ *  INPUTS        : unsigned char *dest    : Pointer to destination data.
+ *                  unsigned int dest_pitch : Stride of destination data.
+ *                  unsigned int dest_width : Width of destination data.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Scales vertical band of pixels by scale 2 to 3. The
+ *                  height of the band scaled is 2-pixels.
+ *
+ *  SPECIAL NOTES : The routine uses the first line of the band below
+ *                  the current band.
+ *
+ ****************************************************************************/
+void vp8_vertical_band_2_3_scale_c(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width)
+{
+    unsigned int i;
+    unsigned int a, b, c;
+    unsigned char *des = dest;
+
+    for (i = 0; i < dest_width; i++)
+    {
+        a = des [0];
+        b = des [dest_pitch];
+        c = des[dest_pitch*3];
+        des [dest_pitch  ] = (unsigned char)((a * 85 + 171 * b + 128) >> 8);
+        des [dest_pitch*2] = (unsigned char)((b * 171 + 85 * c + 128) >> 8);
+
+        des++;
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vp8_last_vertical_band_2_3_scale_c
+ *
+ *  INPUTS        : unsigned char *dest    : Pointer to destination data.
+ *                  unsigned int dest_pitch : Stride of destination data.
+ *                  unsigned int dest_width : Width of destination data.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Scales last vertical band of pixels by scale 2 to 3. The
+ *                  height of the band scaled is 2-pixels.
+ *
+ *  SPECIAL NOTES : The routine does not have available the first line of
+ *                  the band below the current band, since this is the
+ *                  last band.
+ *
+ ****************************************************************************/
+void vp8_last_vertical_band_2_3_scale_c(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width)
+{
+    unsigned int i;
+    unsigned int a, b;
+    unsigned char *des = dest;
+
+    for (i = 0; i < dest_width; ++i)
+    {
+        a = des [0];
+        b = des [dest_pitch];
+
+        des [dest_pitch  ] = (unsigned char)((a * 85 + 171 * b + 128) >> 8);
+        des [dest_pitch*2] = (unsigned char)(b);
+        des++;
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vp8_horizontal_line_3_5_scale_c
+ *
+ *  INPUTS        : const unsigned char *source : Pointer to source data.
+ *                  unsigned int source_width    : Stride of source.
+ *                  unsigned char *dest         : Pointer to destination data.
+ *                  unsigned int dest_width      : Stride of destination (NOT USED).
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Copies horizontal line of pixels from source to
+ *                  destination scaling up by 3 to 5.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ *
+ ****************************************************************************/
+void vp8_horizontal_line_3_5_scale_c
+(
+    const unsigned char *source,
+    unsigned int source_width,
+    unsigned char *dest,
+    unsigned int dest_width
+)
+{
+    unsigned int i;
+    unsigned int a, b, c;
+    unsigned char *des = dest;
+    const unsigned char *src = source;
+
+    (void) dest_width;
+
+    for (i = 0; i < source_width - 3; i += 3)
+    {
+        a = src[0];
+        b = src[1];
+        des [0] = (unsigned char)(a);
+        des [1] = (unsigned char)((a * 102 + 154 * b + 128) >> 8);
+
+        c = src[2] ;
+        des [2] = (unsigned char)((b * 205 + c * 51 + 128) >> 8);
+        des [3] = (unsigned char)((b * 51 + c * 205 + 128) >> 8);
+
+        a = src[3];
+        des [4] = (unsigned char)((c * 154 + a * 102 + 128) >> 8);
+
+        src += 3;
+        des += 5;
+    }
+
+    a = src[0];
+    b = src[1];
+    des [0] = (unsigned char)(a);
+
+    des [1] = (unsigned char)((a * 102 + 154 * b + 128) >> 8);
+    c = src[2] ;
+    des [2] = (unsigned char)((b * 205 + c * 51 + 128) >> 8);
+    des [3] = (unsigned char)((b * 51 + c * 205 + 128) >> 8);
+
+    des [4] = (unsigned char)(c);
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vp8_vertical_band_3_5_scale_c
+ *
+ *  INPUTS        : unsigned char *dest    : Pointer to destination data.
+ *                  unsigned int dest_pitch : Stride of destination data.
+ *                  unsigned int dest_width : Width of destination data.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Scales vertical band of pixels by scale 3 to 5. The
+ *                  height of the band scaled is 3-pixels.
+ *
+ *  SPECIAL NOTES : The routine uses the first line of the band below
+ *                  the current band.
+ *
+ ****************************************************************************/
+void vp8_vertical_band_3_5_scale_c(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width)
+{
+    unsigned int i;
+    unsigned int a, b, c;
+    unsigned char *des = dest;
+
+    for (i = 0; i < dest_width; i++)
+    {
+        a = des [0];
+        b = des [dest_pitch];
+        des [dest_pitch] = (unsigned char)((a * 102 + 154 * b + 128) >> 8);
+
+        c = des[dest_pitch*2];
+        des [dest_pitch*2] = (unsigned char)((b * 205 + c * 51 + 128) >> 8);
+        des [dest_pitch*3] = (unsigned char)((b * 51 + c * 205 + 128) >> 8);
+
+        /* First line in next band... */
+        a = des [dest_pitch * 5];
+        des [dest_pitch * 4] = (unsigned char)((c * 154 + a * 102 + 128) >> 8);
+
+        des++;
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vp8_last_vertical_band_3_5_scale_c
+ *
+ *  INPUTS        : unsigned char *dest    : Pointer to destination data.
+ *                  unsigned int dest_pitch : Stride of destination data.
+ *                  unsigned int dest_width : Width of destination data.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Scales last vertical band of pixels by scale 3 to 5. The
+ *                  height of the band scaled is 3-pixels.
+ *
+ *  SPECIAL NOTES : The routine does not have available the first line of
+ *                  the band below the current band, since this is the
+ *                  last band.
+ *
+ ****************************************************************************/
+void vp8_last_vertical_band_3_5_scale_c(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width)
+{
+    unsigned int i;
+    unsigned int a, b, c;
+    unsigned char *des = dest;
+
+    for (i = 0; i < dest_width; ++i)
+    {
+        a = des [0];
+        b = des [dest_pitch];
+
+        des [ dest_pitch ] = (unsigned char)((a * 102 + 154 * b + 128) >> 8);
+
+        c = des[dest_pitch*2];
+        des [dest_pitch*2] = (unsigned char)((b * 205 + c * 51 + 128) >> 8);
+        des [dest_pitch*3] = (unsigned char)((b * 51 + c * 205 + 128) >> 8);
+
+        /* No other line for interplation of this line, so .. */
+        des [ dest_pitch * 4 ] = (unsigned char)(c) ;
+
+        des++;
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vp8_horizontal_line_3_4_scale_c
+ *
+ *  INPUTS        : const unsigned char *source : Pointer to source data.
+ *                  unsigned int source_width    : Stride of source.
+ *                  unsigned char *dest         : Pointer to destination data.
+ *                  unsigned int dest_width      : Stride of destination (NOT USED).
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Copies horizontal line of pixels from source to
+ *                  destination scaling up by 3 to 4.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ *
+ ****************************************************************************/
+void vp8_horizontal_line_3_4_scale_c
+(
+    const unsigned char *source,
+    unsigned int source_width,
+    unsigned char *dest,
+    unsigned int dest_width
+)
+{
+    unsigned int i;
+    unsigned int a, b, c;
+    unsigned char *des = dest;
+    const unsigned char *src = source;
+
+    (void) dest_width;
+
+    for (i = 0; i < source_width - 3; i += 3)
+    {
+        a = src[0];
+        b = src[1];
+        des [0] = (unsigned char)(a);
+        des [1] = (unsigned char)((a * 64 + b * 192 + 128) >> 8);
+
+        c = src[2];
+        des [2] = (unsigned char)((b + c + 1) >> 1);
+
+        a = src[3];
+        des [3] = (unsigned char)((c * 192 + a * 64 + 128) >> 8);
+
+        src += 3;
+        des += 4;
+    }
+
+    a = src[0];
+    b = src[1];
+    des [0] = (unsigned char)(a);
+    des [1] = (unsigned char)((a * 64 + b * 192 + 128) >> 8);
+
+    c = src[2] ;
+    des [2] = (unsigned char)((b + c + 1) >> 1);
+    des [3] = (unsigned char)(c);
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vp8_vertical_band_3_4_scale_c
+ *
+ *  INPUTS        : unsigned char *dest    : Pointer to destination data.
+ *                  unsigned int dest_pitch : Stride of destination data.
+ *                  unsigned int dest_width : Width of destination data.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Scales vertical band of pixels by scale 3 to 4. The
+ *                  height of the band scaled is 3-pixels.
+ *
+ *  SPECIAL NOTES : The routine uses the first line of the band below
+ *                  the current band.
+ *
+ ****************************************************************************/
+void vp8_vertical_band_3_4_scale_c(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width)
+{
+    unsigned int i;
+    unsigned int a, b, c;
+    unsigned char *des = dest;
+
+    for (i = 0; i < dest_width; i++)
+    {
+        a = des [0];
+        b = des [dest_pitch];
+        des [dest_pitch]   = (unsigned char)((a * 64 + b * 192 + 128) >> 8);
+
+        c = des[dest_pitch*2];
+        des [dest_pitch*2] = (unsigned char)((b + c + 1) >> 1);
+
+        /* First line in next band... */
+        a = des [dest_pitch*4];
+        des [dest_pitch*3] = (unsigned char)((c * 192 + a * 64 + 128) >> 8);
+
+        des++;
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vp8_last_vertical_band_3_4_scale_c
+ *
+ *  INPUTS        : unsigned char *dest    : Pointer to destination data.
+ *                  unsigned int dest_pitch : Stride of destination data.
+ *                  unsigned int dest_width : Width of destination data.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Scales last vertical band of pixels by scale 3 to 4. The
+ *                  height of the band scaled is 3-pixels.
+ *
+ *  SPECIAL NOTES : The routine does not have available the first line of
+ *                  the band below the current band, since this is the
+ *                  last band.
+ *
+ ****************************************************************************/
+void vp8_last_vertical_band_3_4_scale_c(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width)
+{
+    unsigned int i;
+    unsigned int a, b, c;
+    unsigned char *des = dest;
+
+    for (i = 0; i < dest_width; ++i)
+    {
+        a = des [0];
+        b = des [dest_pitch];
+
+        des [dest_pitch]   = (unsigned char)((a * 64 + b * 192 + 128) >> 8);
+
+        c = des[dest_pitch*2];
+        des [dest_pitch*2] = (unsigned char)((b + c + 1) >> 1);
+
+        /* No other line for interplation of this line, so .. */
+        des [dest_pitch*3] = (unsigned char)(c);
+
+        des++;
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vp8_horizontal_line_1_2_scale_c
+ *
+ *  INPUTS        : const unsigned char *source : Pointer to source data.
+ *                  unsigned int source_width    : Stride of source.
+ *                  unsigned char *dest         : Pointer to destination data.
+ *                  unsigned int dest_width      : Stride of destination (NOT USED).
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Copies horizontal line of pixels from source to
+ *                  destination scaling up by 1 to 2.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+void vp8_horizontal_line_1_2_scale_c
+(
+    const unsigned char *source,
+    unsigned int source_width,
+    unsigned char *dest,
+    unsigned int dest_width
+)
+{
+    unsigned int i;
+    unsigned int a, b;
+    unsigned char *des = dest;
+    const unsigned char *src = source;
+
+    (void) dest_width;
+
+    for (i = 0; i < source_width - 1; i += 1)
+    {
+        a = src[0];
+        b = src[1];
+        des [0] = (unsigned char)(a);
+        des [1] = (unsigned char)((a + b + 1) >> 1);
+        src += 1;
+        des += 2;
+    }
+
+    a = src[0];
+    des [0] = (unsigned char)(a);
+    des [1] = (unsigned char)(a);
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vp8_vertical_band_1_2_scale_c
+ *
+ *  INPUTS        : unsigned char *dest    : Pointer to destination data.
+ *                  unsigned int dest_pitch : Stride of destination data.
+ *                  unsigned int dest_width : Width of destination data.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Scales vertical band of pixels by scale 1 to 2. The
+ *                  height of the band scaled is 1-pixel.
+ *
+ *  SPECIAL NOTES : The routine uses the first line of the band below
+ *                  the current band.
+ *
+ ****************************************************************************/
+void vp8_vertical_band_1_2_scale_c(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width)
+{
+    unsigned int i;
+    unsigned int a, b;
+    unsigned char *des = dest;
+
+    for (i = 0; i < dest_width; i++)
+    {
+        a = des [0];
+        b = des [dest_pitch * 2];
+
+        des[dest_pitch] = (unsigned char)((a + b + 1) >> 1);
+
+        des++;
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vp8_last_vertical_band_1_2_scale_c
+ *
+ *  INPUTS        : unsigned char *dest    : Pointer to destination data.
+ *                  unsigned int dest_pitch : Stride of destination data.
+ *                  unsigned int dest_width : Width of destination data.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Scales last vertical band of pixels by scale 1 to 2. The
+ *                  height of the band scaled is 1-pixel.
+ *
+ *  SPECIAL NOTES : The routine does not have available the first line of
+ *                  the band below the current band, since this is the
+ *                  last band.
+ *
+ ****************************************************************************/
+void vp8_last_vertical_band_1_2_scale_c(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width)
+{
+    unsigned int i;
+    unsigned char *des = dest;
+
+    for (i = 0; i < dest_width; ++i)
+    {
+        des[dest_pitch] = des[0];
+        des++;
+    }
+}
+
+
+
+
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vp8_horizontal_line_4_5_scale_c
+ *
+ *  INPUTS        : const unsigned char *source : Pointer to source data.
+ *                  unsigned int source_width    : Stride of source.
+ *                  unsigned char *dest         : Pointer to destination data.
+ *                  unsigned int dest_width      : Stride of destination (NOT USED).
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Copies horizontal line of pixels from source to
+ *                  destination scaling up by 4 to 5.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+void vp8_horizontal_line_5_4_scale_c
+(
+    const unsigned char *source,
+    unsigned int source_width,
+    unsigned char *dest,
+    unsigned int dest_width
+)
+{
+    unsigned i;
+    unsigned int a, b, c, d, e;
+    unsigned char *des = dest;
+    const unsigned char *src = source;
+
+    (void) dest_width;
+
+    for (i = 0; i < source_width; i += 5)
+    {
+        a = src[0];
+        b = src[1];
+        c = src[2];
+        d = src[3];
+        e = src[4];
+
+        des[0] = (unsigned char) a;
+        des[1] = (unsigned char)((b * 192 + c * 64 + 128) >> 8);
+        des[2] = (unsigned char)((c * 128 + d * 128 + 128) >> 8);
+        des[3] = (unsigned char)((d * 64 + e * 192 + 128) >> 8);
+
+        src += 5;
+        des += 4;
+    }
+}
+
+
+
+
+void vp8_vertical_band_5_4_scale_c(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width)
+{
+    unsigned int i;
+    unsigned int a, b, c, d, e;
+    unsigned char *des = dest;
+    unsigned char *src = source;
+
+    for (i = 0; i < dest_width; i++)
+    {
+
+        a = src[0 * src_pitch];
+        b = src[1 * src_pitch];
+        c = src[2 * src_pitch];
+        d = src[3 * src_pitch];
+        e = src[4 * src_pitch];
+
+        des[0 * dest_pitch] = (unsigned char) a;
+        des[1 * dest_pitch] = (unsigned char)((b * 192 + c * 64 + 128) >> 8);
+        des[2 * dest_pitch] = (unsigned char)((c * 128 + d * 128 + 128) >> 8);
+        des[3 * dest_pitch] = (unsigned char)((d * 64 + e * 192 + 128) >> 8);
+
+        src ++;
+        des ++;
+
+    }
+}
+
+
+/*7***************************************************************************
+ *
+ *  ROUTINE       : vp8_horizontal_line_3_5_scale_c
+ *
+ *  INPUTS        : const unsigned char *source : Pointer to source data.
+ *                  unsigned int source_width    : Stride of source.
+ *                  unsigned char *dest         : Pointer to destination data.
+ *                  unsigned int dest_width      : Stride of destination (NOT USED).
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Copies horizontal line of pixels from source to
+ *                  destination scaling up by 3 to 5.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ *
+ ****************************************************************************/
+void vp8_horizontal_line_5_3_scale_c
+(
+    const unsigned char *source,
+    unsigned int source_width,
+    unsigned char *dest,
+    unsigned int dest_width
+)
+{
+    unsigned int i;
+    unsigned int a, b, c, d , e;
+    unsigned char *des = dest;
+    const unsigned char *src = source;
+
+    (void) dest_width;
+
+    for (i = 0; i < source_width; i += 5)
+    {
+        a = src[0];
+        b = src[1];
+        c = src[2];
+        d = src[3];
+        e = src[4];
+
+        des[0] = (unsigned char) a;
+        des[1] = (unsigned char)((b * 85  + c * 171 + 128) >> 8);
+        des[2] = (unsigned char)((d * 171 + e * 85 + 128) >> 8);
+
+        src += 5;
+        des += 3;
+    }
+
+}
+
+void vp8_vertical_band_5_3_scale_c(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width)
+{
+    unsigned int i;
+    unsigned int a, b, c, d, e;
+    unsigned char *des = dest;
+    unsigned char *src = source;
+
+    for (i = 0; i < dest_width; i++)
+    {
+
+        a = src[0 * src_pitch];
+        b = src[1 * src_pitch];
+        c = src[2 * src_pitch];
+        d = src[3 * src_pitch];
+        e = src[4 * src_pitch];
+
+        des[0 * dest_pitch] = (unsigned char) a;
+        des[1 * dest_pitch] = (unsigned char)((b * 85 + c * 171 + 128) >> 8);
+        des[2 * dest_pitch] = (unsigned char)((d * 171 + e * 85 + 128) >> 8);
+
+        src ++;
+        des ++;
+
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vp8_horizontal_line_1_2_scale_c
+ *
+ *  INPUTS        : const unsigned char *source : Pointer to source data.
+ *                  unsigned int source_width    : Stride of source.
+ *                  unsigned char *dest         : Pointer to destination data.
+ *                  unsigned int dest_width      : Stride of destination (NOT USED).
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Copies horizontal line of pixels from source to
+ *                  destination scaling up by 1 to 2.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+void vp8_horizontal_line_2_1_scale_c
+(
+    const unsigned char *source,
+    unsigned int source_width,
+    unsigned char *dest,
+    unsigned int dest_width
+)
+{
+    unsigned int i;
+    unsigned int a;
+    unsigned char *des = dest;
+    const unsigned char *src = source;
+
+    (void) dest_width;
+
+    for (i = 0; i < source_width; i += 2)
+    {
+        a = src[0];
+        des [0] = (unsigned char)(a);
+        src += 2;
+        des += 1;
+    }
+
+
+
+}
+void vp8_vertical_band_2_1_scale_c(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width)
+{
+    (void) dest_pitch;
+    (void) src_pitch;
+    vpx_memcpy(dest, source, dest_width);
+}
+
+void vp8_vertical_band_2_1_scale_i_c(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width)
+{
+    int i;
+    int temp;
+    int width = dest_width;
+
+    (void) dest_pitch;
+
+    for (i = 0; i < width; i++)
+    {
+        temp = 8;
+        temp += source[i-(int)src_pitch] * 3;
+        temp += source[i] * 10;
+        temp += source[i+src_pitch] * 3;
+        temp >>= 4 ;
+        dest[i] = (unsigned char)(temp);
+    }
+
+}
diff --git a/vpx_scale/generic/vpxscale.c b/vpx_scale/generic/vpxscale.c
new file mode 100644 (file)
index 0000000..c02e4ff
--- /dev/null
@@ -0,0 +1,1059 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/****************************************************************************
+ *
+ *   Module Title :     scale.c
+ *
+ *   Description  :     Image scaling functions.
+ *
+ ***************************************************************************/
+
+/****************************************************************************
+*  Header Files
+****************************************************************************/
+#include "vpx_rtcd.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_scale/yv12config.h"
+#include "vpx_scale/scale_mode.h"
+
+typedef struct
+{
+    int     expanded_frame_width;
+    int     expanded_frame_height;
+
+    int HScale;
+    int HRatio;
+    int VScale;
+    int VRatio;
+
+    YV12_BUFFER_CONFIG *src_yuv_config;
+    YV12_BUFFER_CONFIG *dst_yuv_config;
+
+} SCALE_VARS;
+
+/****************************************************************************
+ *
+ *  ROUTINE       :     horizontal_line_copy
+ *
+ *  INPUTS        :     None
+ *
+ *
+ *  OUTPUTS       :     None.
+ *
+ *  RETURNS       :     None
+ *
+ *  FUNCTION      :     1 to 1 scaling up for a horizontal line of pixles
+ *
+ *  SPECIAL NOTES :     None.
+ *
+ *  ERRORS        :     None.
+ *
+ ****************************************************************************/
+static
+void horizontal_line_copy(
+    const unsigned char *source,
+    unsigned int source_width,
+    unsigned char *dest,
+    unsigned int dest_width
+)
+{
+    (void) dest_width;
+
+    duck_memcpy(dest, source, source_width);
+}
+/****************************************************************************
+ *
+ *  ROUTINE       :     null_scale
+ *
+ *  INPUTS        :     None
+ *
+ *
+ *  OUTPUTS       :     None.
+ *
+ *  RETURNS       :     None
+ *
+ *  FUNCTION      :     1 to 1 scaling up for a vertical band
+ *
+ *  SPECIAL NOTES :     None.
+ *
+ *  ERRORS        :     None.
+ *
+ ****************************************************************************/
+static
+void null_scale(
+    unsigned char *dest,
+    unsigned int dest_pitch,
+    unsigned int dest_width
+)
+{
+    (void) dest;
+    (void) dest_pitch;
+    (void) dest_width;
+
+    return;
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : scale1d_2t1_i
+ *
+ *  INPUTS        : const unsigned char *source : Pointer to data to be scaled.
+ *                  int source_step              : Number of pixels to step on in source.
+ *                  unsigned int source_scale    : Scale for source (UNUSED).
+ *                  unsigned int source_length   : Length of source (UNUSED).
+ *                  unsigned char *dest         : Pointer to output data array.
+ *                  int dest_step                : Number of pixels to step on in destination.
+ *                  unsigned int dest_scale      : Scale for destination (UNUSED).
+ *                  unsigned int dest_length     : Length of destination.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Performs 2-to-1 interpolated scaling.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+static
+void scale1d_2t1_i
+(
+    const unsigned char *source,
+    int source_step,
+    unsigned int source_scale,
+    unsigned int source_length,
+    unsigned char *dest,
+    int dest_step,
+    unsigned int dest_scale,
+    unsigned int dest_length
+)
+{
+    unsigned int i, j;
+    unsigned int temp;
+    int source_pitch = source_step;
+    (void) source_length;
+    (void) source_scale;
+    (void) dest_scale;
+
+    source_step *= 2;
+    dest[0] = source[0];
+
+    for (i = dest_step, j = source_step; i < dest_length * dest_step; i += dest_step, j += source_step)
+    {
+        temp = 8;
+        temp += 3 * source[j-source_pitch];
+        temp += 10 * source[j];
+        temp += 3 * source[j+source_pitch];
+        temp >>= 4;
+        dest[i] = (char)(temp);
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : scale1d_2t1_ps
+ *
+ *  INPUTS        : const unsigned char *source : Pointer to data to be scaled.
+ *                  int source_step              : Number of pixels to step on in source.
+ *                  unsigned int source_scale    : Scale for source (UNUSED).
+ *                  unsigned int source_length   : Length of source (UNUSED).
+ *                  unsigned char *dest         : Pointer to output data array.
+ *                  int dest_step                : Number of pixels to step on in destination.
+ *                  unsigned int dest_scale      : Scale for destination (UNUSED).
+ *                  unsigned int dest_length     : Length of destination.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Performs 2-to-1 point subsampled scaling.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+static
+void scale1d_2t1_ps
+(
+    const unsigned char *source,
+    int source_step,
+    unsigned int source_scale,
+    unsigned int source_length,
+    unsigned char *dest,
+    int dest_step,
+    unsigned int dest_scale,
+    unsigned int dest_length
+)
+{
+    unsigned int i, j;
+
+    (void) source_length;
+    (void) source_scale;
+    (void) dest_scale;
+
+    source_step *= 2;
+    j = 0;
+
+    for (i = 0; i < dest_length * dest_step; i += dest_step, j += source_step)
+        dest[i] = source[j];
+}
+/****************************************************************************
+ *
+ *  ROUTINE       : scale1d_c
+ *
+ *  INPUTS        : const unsigned char *source : Pointer to data to be scaled.
+ *                  int source_step              : Number of pixels to step on in source.
+ *                  unsigned int source_scale    : Scale for source.
+ *                  unsigned int source_length   : Length of source (UNUSED).
+ *                  unsigned char *dest         : Pointer to output data array.
+ *                  int dest_step                : Number of pixels to step on in destination.
+ *                  unsigned int dest_scale      : Scale for destination.
+ *                  unsigned int dest_length     : Length of destination.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Performs linear interpolation in one dimension.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+static
+void scale1d_c
+(
+    const unsigned char *source,
+    int source_step,
+    unsigned int source_scale,
+    unsigned int source_length,
+    unsigned char *dest,
+    int dest_step,
+    unsigned int dest_scale,
+    unsigned int dest_length
+)
+{
+    unsigned int i;
+    unsigned int round_value = dest_scale / 2;
+    unsigned int left_modifier = dest_scale;
+    unsigned int right_modifier = 0;
+    unsigned char left_pixel = *source;
+    unsigned char right_pixel = *(source + source_step);
+
+    (void) source_length;
+
+    /* These asserts are needed if there are boundary issues... */
+    /*assert ( dest_scale > source_scale );*/
+    /*assert ( (source_length-1) * dest_scale >= (dest_length-1) * source_scale );*/
+
+    for (i = 0; i < dest_length * dest_step; i += dest_step)
+    {
+        dest[i] = (char)((left_modifier * left_pixel + right_modifier * right_pixel + round_value) / dest_scale);
+
+        right_modifier += source_scale;
+
+        while (right_modifier > dest_scale)
+        {
+            right_modifier -= dest_scale;
+            source += source_step;
+            left_pixel = *source;
+            right_pixel = *(source + source_step);
+        }
+
+        left_modifier = dest_scale - right_modifier;
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : Scale2D
+ *
+ *  INPUTS        : const unsigned char *source  : Pointer to data to be scaled.
+ *                  int source_pitch              : Stride of source image.
+ *                  unsigned int source_width     : Width of input image.
+ *                  unsigned int source_height    : Height of input image.
+ *                  unsigned char *dest          : Pointer to output data array.
+ *                  int dest_pitch                : Stride of destination image.
+ *                  unsigned int dest_width       : Width of destination image.
+ *                  unsigned int dest_height      : Height of destination image.
+ *                  unsigned char *temp_area      : Pointer to temp work area.
+ *                  unsigned char temp_area_height : Height of temp work area.
+ *                  unsigned int hscale          : Horizontal scale factor numerator.
+ *                  unsigned int hratio          : Horizontal scale factor denominator.
+ *                  unsigned int vscale          : Vertical scale factor numerator.
+ *                  unsigned int vratio          : Vertical scale factor denominator.
+ *                  unsigned int interlaced      : Interlace flag.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Performs 2-tap linear interpolation in two dimensions.
+ *
+ *  SPECIAL NOTES : Expansion is performed one band at a time to help with
+ *                  caching.
+ *
+ ****************************************************************************/
+static
+void Scale2D
+(
+    /*const*/
+    unsigned char *source,
+    int source_pitch,
+    unsigned int source_width,
+    unsigned int source_height,
+    unsigned char *dest,
+    int dest_pitch,
+    unsigned int dest_width,
+    unsigned int dest_height,
+    unsigned char *temp_area,
+    unsigned char temp_area_height,
+    unsigned int hscale,
+    unsigned int hratio,
+    unsigned int vscale,
+    unsigned int vratio,
+    unsigned int interlaced
+)
+{
+    /*unsigned*/
+    int i, j, k;
+    int bands;
+    int dest_band_height;
+    int source_band_height;
+
+    typedef void (*Scale1D)(const unsigned char * source, int source_step, unsigned int source_scale, unsigned int source_length,
+                            unsigned char * dest, int dest_step, unsigned int dest_scale, unsigned int dest_length);
+
+    Scale1D Scale1Dv = scale1d_c;
+    Scale1D Scale1Dh = scale1d_c;
+
+    void (*horiz_line_scale)(const unsigned char *, unsigned int, unsigned char *, unsigned int) = NULL;
+    void (*vert_band_scale)(unsigned char *, unsigned int, unsigned char *, unsigned int, unsigned int) = NULL;
+
+    int ratio_scalable = 1;
+    int interpolation = 0;
+
+    unsigned char *source_base; /* = (unsigned char *) ((source_pitch >= 0) ? source : (source + ((source_height-1) * source_pitch))); */
+    unsigned char *line_src;
+
+
+    source_base = (unsigned char *)source;
+
+    if (source_pitch < 0)
+    {
+        int offset;
+
+        offset = (source_height - 1);
+        offset *= source_pitch;
+
+        source_base += offset;
+    }
+
+    /* find out the ratio for each direction */
+    switch (hratio * 10 / hscale)
+    {
+    case 8:
+        /* 4-5 Scale in Width direction */
+        horiz_line_scale = vp8_horizontal_line_5_4_scale;
+        break;
+    case 6:
+        /* 3-5 Scale in Width direction */
+        horiz_line_scale = vp8_horizontal_line_5_3_scale;
+        break;
+    case 5:
+        /* 1-2 Scale in Width direction */
+        horiz_line_scale = vp8_horizontal_line_2_1_scale;
+        break;
+    default:
+        /* The ratio is not acceptable now */
+        /* throw("The ratio is not acceptable for now!"); */
+        ratio_scalable = 0;
+        break;
+    }
+
+    switch (vratio * 10 / vscale)
+    {
+    case 8:
+        /* 4-5 Scale in vertical direction */
+        vert_band_scale     = vp8_vertical_band_5_4_scale;
+        source_band_height  = 5;
+        dest_band_height    = 4;
+        break;
+    case 6:
+        /* 3-5 Scale in vertical direction */
+        vert_band_scale     = vp8_vertical_band_5_3_scale;
+        source_band_height  = 5;
+        dest_band_height    = 3;
+        break;
+    case 5:
+        /* 1-2 Scale in vertical direction */
+
+        if (interlaced)
+        {
+            /* if the content is interlaced, point sampling is used */
+            vert_band_scale     = vp8_vertical_band_2_1_scale;
+        }
+        else
+        {
+
+            interpolation = 1;
+            /* if the content is progressive, interplo */
+            vert_band_scale     = vp8_vertical_band_2_1_scale_i;
+
+        }
+
+        source_band_height  = 2;
+        dest_band_height    = 1;
+        break;
+    default:
+        /* The ratio is not acceptable now */
+        /* throw("The ratio is not acceptable for now!"); */
+        ratio_scalable = 0;
+        break;
+    }
+
+    if (ratio_scalable)
+    {
+        if (source_height == dest_height)
+        {
+            /* for each band of the image */
+            for (k = 0; k < (int)dest_height; k++)
+            {
+                horiz_line_scale(source, source_width, dest, dest_width);
+                source += source_pitch;
+                dest   += dest_pitch;
+            }
+
+            return;
+        }
+
+        if (interpolation)
+        {
+            if (source < source_base)
+                source = source_base;
+
+            horiz_line_scale(source, source_width, temp_area, dest_width);
+        }
+
+        for (k = 0; k < (int)(dest_height + dest_band_height - 1) / dest_band_height; k++)
+        {
+            /* scale one band horizontally */
+            for (i = 0; i < source_band_height; i++)
+            {
+                /* Trap case where we could read off the base of the source buffer */
+
+                line_src = (unsigned char *)source + i * source_pitch;
+
+                if (line_src < source_base)
+                    line_src = source_base;
+
+                horiz_line_scale(line_src, source_width,
+                                 temp_area + (i + 1)*dest_pitch, dest_width);
+            }
+
+            /* Vertical scaling is in place */
+            vert_band_scale(temp_area + dest_pitch, dest_pitch, dest, dest_pitch, dest_width);
+
+            if (interpolation)
+                vpx_memcpy(temp_area, temp_area + source_band_height * dest_pitch, dest_width);
+
+            /* Next band... */
+            source += (unsigned long) source_band_height  * source_pitch;
+            dest   += (unsigned long) dest_band_height * dest_pitch;
+        }
+
+        return;
+    }
+
+    if (hscale == 2 && hratio == 1)
+        Scale1Dh = scale1d_2t1_ps;
+
+    if (vscale == 2 && vratio == 1)
+    {
+        if (interlaced)
+            Scale1Dv = scale1d_2t1_ps;
+        else
+            Scale1Dv = scale1d_2t1_i;
+    }
+
+    if (source_height == dest_height)
+    {
+        /* for each band of the image */
+        for (k = 0; k < (int)dest_height; k++)
+        {
+            Scale1Dh(source, 1, hscale, source_width + 1, dest, 1, hratio, dest_width);
+            source += source_pitch;
+            dest   += dest_pitch;
+        }
+
+        return;
+    }
+
+    if (dest_height > source_height)
+    {
+        dest_band_height   = temp_area_height - 1;
+        source_band_height = dest_band_height * source_height / dest_height;
+    }
+    else
+    {
+        source_band_height = temp_area_height - 1;
+        dest_band_height   = source_band_height * vratio / vscale;
+    }
+
+    /* first row needs to be done so that we can stay one row ahead for vertical zoom */
+    Scale1Dh(source, 1, hscale, source_width + 1, temp_area, 1, hratio, dest_width);
+
+    /* for each band of the image */
+    bands = (dest_height + dest_band_height - 1) / dest_band_height;
+
+    for (k = 0; k < bands; k++)
+    {
+        /* scale one band horizontally */
+        for (i = 1; i < source_band_height + 1; i++)
+        {
+            if (k * source_band_height + i < (int) source_height)
+            {
+                Scale1Dh(source + i * source_pitch, 1, hscale, source_width + 1,
+                         temp_area + i * dest_pitch, 1, hratio, dest_width);
+            }
+            else  /*  Duplicate the last row */
+            {
+                /* copy temp_area row 0 over from last row in the past */
+                duck_memcpy(temp_area + i * dest_pitch, temp_area + (i - 1)*dest_pitch, dest_pitch);
+            }
+        }
+
+        /* scale one band vertically */
+        for (j = 0; j < (int)dest_width; j++)
+        {
+            Scale1Dv(&temp_area[j], dest_pitch, vscale, source_band_height + 1,
+                     &dest[j], dest_pitch, vratio, dest_band_height);
+        }
+
+        /* copy temp_area row 0 over from last row in the past */
+        duck_memcpy(temp_area, temp_area + source_band_height * dest_pitch, dest_pitch);
+
+        /* move to the next band */
+        source += source_band_height * source_pitch;
+        dest   += dest_band_height * dest_pitch;
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       :
+ *
+ *  INPUTS        : YV12_BUFFER_CONFIG *src       : Pointer to frame to be scaled.
+ *                  YV12_BUFFER_CONFIG *dst       : Pointer to buffer to hold scaled frame.
+ *                  unsigned char *temp_area      : Pointer to temp work area.
+ *                  unsigned char temp_area_height : Height of temp work area.
+ *                  unsigned int hscale          : Horizontal scale factor numerator.
+ *                  unsigned int hratio          : Horizontal scale factor denominator.
+ *                  unsigned int vscale          : Vertical scale factor numerator.
+ *                  unsigned int vratio          : Vertical scale factor denominator.
+ *                  unsigned int interlaced      : Interlace flag.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Performs 2-tap linear interpolation in two dimensions.
+ *
+ *  SPECIAL NOTES : Expansion is performed one band at a time to help with
+ *                  caching.
+ *
+ ****************************************************************************/
+void vp8_scale_frame
+(
+    YV12_BUFFER_CONFIG *src,
+    YV12_BUFFER_CONFIG *dst,
+    unsigned char *temp_area,
+    unsigned char temp_height,
+    unsigned int hscale,
+    unsigned int hratio,
+    unsigned int vscale,
+    unsigned int vratio,
+    unsigned int interlaced
+)
+{
+    int i;
+    int dw = (hscale - 1 + src->y_width * hratio) / hscale;
+    int dh = (vscale - 1 + src->y_height * vratio) / vscale;
+
+    /* call our internal scaling routines!! */
+    Scale2D((unsigned char *) src->y_buffer, src->y_stride, src->y_width, src->y_height,
+            (unsigned char *) dst->y_buffer, dst->y_stride, dw, dh,
+            temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced);
+
+    if (dw < (int)dst->y_width)
+        for (i = 0; i < dh; i++)
+            duck_memset(dst->y_buffer + i * dst->y_stride + dw - 1, dst->y_buffer[i*dst->y_stride+dw-2], dst->y_width - dw + 1);
+
+    if (dh < (int)dst->y_height)
+        for (i = dh - 1; i < (int)dst->y_height; i++)
+            duck_memcpy(dst->y_buffer + i * dst->y_stride, dst->y_buffer + (dh - 2) * dst->y_stride, dst->y_width + 1);
+
+    Scale2D((unsigned char *) src->u_buffer, src->uv_stride, src->uv_width, src->uv_height,
+            (unsigned char *) dst->u_buffer, dst->uv_stride, dw / 2, dh / 2,
+            temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced);
+
+    if (dw / 2 < (int)dst->uv_width)
+        for (i = 0; i < dst->uv_height; i++)
+            duck_memset(dst->u_buffer + i * dst->uv_stride + dw / 2 - 1, dst->u_buffer[i*dst->uv_stride+dw/2-2], dst->uv_width - dw / 2 + 1);
+
+    if (dh / 2 < (int)dst->uv_height)
+        for (i = dh / 2 - 1; i < (int)dst->y_height / 2; i++)
+            duck_memcpy(dst->u_buffer + i * dst->uv_stride, dst->u_buffer + (dh / 2 - 2)*dst->uv_stride, dst->uv_width);
+
+    Scale2D((unsigned char *) src->v_buffer, src->uv_stride, src->uv_width, src->uv_height,
+            (unsigned char *) dst->v_buffer, dst->uv_stride, dw / 2, dh / 2,
+            temp_area, temp_height, hscale, hratio, vscale, vratio, interlaced);
+
+    if (dw / 2 < (int)dst->uv_width)
+        for (i = 0; i < dst->uv_height; i++)
+            duck_memset(dst->v_buffer + i * dst->uv_stride + dw / 2 - 1, dst->v_buffer[i*dst->uv_stride+dw/2-2], dst->uv_width - dw / 2 + 1);
+
+    if (dh / 2 < (int) dst->uv_height)
+        for (i = dh / 2 - 1; i < (int)dst->y_height / 2; i++)
+            duck_memcpy(dst->v_buffer + i * dst->uv_stride, dst->v_buffer + (dh / 2 - 2)*dst->uv_stride, dst->uv_width);
+}
+/****************************************************************************
+ *
+ *  ROUTINE       : any_ratio_2d_scale
+ *
+ *  INPUTS        : SCALE_INSTANCE *si      : Pointer to post-processor instance (NOT USED).
+ *                  const unsigned char *source : Pointer to source image.
+ *                  unsigned int source_pitch    : Stride of source image.
+ *                  unsigned int source_width    : Width of source image.
+ *                  unsigned int source_height   : Height of source image (NOT USED).
+ *                  unsigned char *dest         : Pointer to destination image.
+ *                  unsigned int dest_pitch      : Stride of destination image.
+ *                  unsigned int dest_width      : Width of destination image.
+ *                  unsigned int dest_height     : Height of destination image.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : int: 1 if image scaled, 0 if image could not be scaled.
+ *
+ *  FUNCTION      : Scale the image with changing apect ratio.
+ *
+ *  SPECIAL NOTES : This scaling is a bi-linear scaling. Need to re-work the
+ *                  whole function for new scaling algorithm.
+ *
+ ****************************************************************************/
+static
+int any_ratio_2d_scale
+(
+    SCALE_VARS *si,
+    const unsigned char *source,
+    int source_pitch,
+    unsigned int source_width,
+    unsigned int source_height,
+    unsigned char *dest,
+    unsigned int dest_pitch,
+    unsigned int dest_width,
+    unsigned int dest_height
+)
+{
+    unsigned int i, k;
+    unsigned int src_band_height  = 0;
+    unsigned int dest_band_height = 0;
+
+    /* suggested scale factors */
+    int hs = si->HScale;
+    int hr = si->HRatio;
+    int vs = si->VScale;
+    int vr = si->VRatio;
+
+    /* assume the ratios are scalable instead of should be centered */
+    int ratio_scalable = 1;
+
+    const unsigned char *source_base = ((source_pitch >= 0) ? source : (source + ((source_height - 1) * source_pitch)));
+    const unsigned char *line_src;
+
+    void (*horiz_line_scale)(const unsigned char *, unsigned int, unsigned char *, unsigned int) = NULL;
+    void (*vert_band_scale)(unsigned char *, unsigned int, unsigned int) = NULL;
+    void (*last_vert_band_scale)(unsigned char *, unsigned int, unsigned int) = NULL;
+
+    (void) si;
+
+    /* find out the ratio for each direction */
+    switch (hr * 30 / hs)
+    {
+    case 24:
+        /* 4-5 Scale in Width direction */
+        horiz_line_scale = vp8_horizontal_line_4_5_scale;
+        break;
+    case 22:
+        /* 3-4 Scale in Width direction */
+        horiz_line_scale = vp8_horizontal_line_3_4_scale;
+        break;
+
+    case 20:
+        /* 4-5 Scale in Width direction */
+        horiz_line_scale = vp8_horizontal_line_2_3_scale;
+        break;
+    case 18:
+        /* 3-5 Scale in Width direction */
+        horiz_line_scale = vp8_horizontal_line_3_5_scale;
+        break;
+    case 15:
+        /* 1-2 Scale in Width direction */
+        horiz_line_scale = vp8_horizontal_line_1_2_scale;
+        break;
+    case 30:
+        /* no scale in Width direction */
+        horiz_line_scale = horizontal_line_copy;
+        break;
+    default:
+        /* The ratio is not acceptable now */
+        /* throw("The ratio is not acceptable for now!"); */
+        ratio_scalable = 0;
+        break;
+    }
+
+    switch (vr * 30 / vs)
+    {
+    case 24:
+        /* 4-5 Scale in vertical direction */
+        vert_band_scale     = vp8_vertical_band_4_5_scale;
+        last_vert_band_scale = vp8_last_vertical_band_4_5_scale;
+        src_band_height     = 4;
+        dest_band_height    = 5;
+        break;
+    case 22:
+        /* 3-4 Scale in vertical direction */
+        vert_band_scale     = vp8_vertical_band_3_4_scale;
+        last_vert_band_scale = vp8_last_vertical_band_3_4_scale;
+        src_band_height     = 3;
+        dest_band_height    = 4;
+        break;
+    case 20:
+        /* 2-3 Scale in vertical direction */
+        vert_band_scale     = vp8_vertical_band_2_3_scale;
+        last_vert_band_scale = vp8_last_vertical_band_2_3_scale;
+        src_band_height     = 2;
+        dest_band_height    = 3;
+        break;
+    case 18:
+        /* 3-5 Scale in vertical direction */
+        vert_band_scale     = vp8_vertical_band_3_5_scale;
+        last_vert_band_scale = vp8_last_vertical_band_3_5_scale;
+        src_band_height     = 3;
+        dest_band_height    = 5;
+        break;
+    case 15:
+        /* 1-2 Scale in vertical direction */
+        vert_band_scale     = vp8_vertical_band_1_2_scale;
+        last_vert_band_scale = vp8_last_vertical_band_1_2_scale;
+        src_band_height     = 1;
+        dest_band_height    = 2;
+        break;
+    case 30:
+        /* no scale in Width direction */
+        vert_band_scale     = null_scale;
+        last_vert_band_scale = null_scale;
+        src_band_height     = 4;
+        dest_band_height    = 4;
+        break;
+    default:
+        /* The ratio is not acceptable now */
+        /* throw("The ratio is not acceptable for now!"); */
+        ratio_scalable = 0;
+        break;
+    }
+
+    if (ratio_scalable == 0)
+        return ratio_scalable;
+
+    horiz_line_scale(source, source_width, dest, dest_width);
+
+    /* except last band */
+    for (k = 0; k < (dest_height + dest_band_height - 1) / dest_band_height - 1; k++)
+    {
+        /* scale one band horizontally */
+        for (i = 1; i < src_band_height; i++)
+        {
+            /* Trap case where we could read off the base of the source buffer */
+            line_src = source + i * source_pitch;
+
+            if (line_src < source_base)
+                line_src = source_base;
+
+            horiz_line_scale(line_src, source_width,
+                             dest + i * dest_pitch, dest_width);
+        }
+
+        /* first line of next band */
+        /* Trap case where we could read off the base of the source buffer */
+        line_src = source + src_band_height * source_pitch;
+
+        if (line_src < source_base)
+            line_src = source_base;
+
+        horiz_line_scale(line_src, source_width,
+                         dest + dest_band_height * dest_pitch,
+                         dest_width);
+
+        /* Vertical scaling is in place */
+        vert_band_scale(dest, dest_pitch, dest_width);
+
+        /* Next band... */
+        source += src_band_height  * source_pitch;
+        dest   += dest_band_height * dest_pitch;
+    }
+
+    /* scale one band horizontally */
+    for (i = 1; i < src_band_height; i++)
+    {
+        /* Trap case where we could read off the base of the source buffer */
+        line_src = source + i * source_pitch;
+
+        if (line_src < source_base)
+            line_src = source_base;
+
+        horiz_line_scale(line_src, source_width,
+                         dest + i * dest_pitch,
+                         dest_width);
+    }
+
+    /* Vertical scaling is in place */
+    last_vert_band_scale(dest, dest_pitch, dest_width);
+
+    return ratio_scalable;
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : any_ratio_frame_scale
+ *
+ *  INPUTS        : SCALE_INSTANCE *si       : Pointer to post-processor instance (NOT USED).
+ *                  unsigned char *frame_buffer           : Pointer to source image.
+ *                  int YOffset                : Offset from start of buffer to Y samples.
+ *                  int UVOffset               : Offset from start of buffer to UV samples.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : int: 1 if image scaled, 0 if image could not be scaled.
+ *
+ *  FUNCTION      : Scale the image with changing apect ratio.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+static
+int any_ratio_frame_scale(SCALE_VARS *scale_vars, int YOffset, int UVOffset)
+{
+    int i;
+    int ew;
+    int eh;
+
+    /* suggested scale factors */
+    int hs = scale_vars->HScale;
+    int hr = scale_vars->HRatio;
+    int vs = scale_vars->VScale;
+    int vr = scale_vars->VRatio;
+
+    int ratio_scalable = 1;
+
+    int sw = (scale_vars->expanded_frame_width * hr + hs - 1) / hs;
+    int sh = (scale_vars->expanded_frame_height * vr + vs - 1) / vs;
+    int dw = scale_vars->expanded_frame_width;
+    int dh = scale_vars->expanded_frame_height;
+    YV12_BUFFER_CONFIG *src_yuv_config = scale_vars->src_yuv_config;
+    YV12_BUFFER_CONFIG *dst_yuv_config = scale_vars->dst_yuv_config;
+
+    if (hr == 3)
+        ew = (sw + 2) / 3 * 3 * hs / hr;
+    else
+        ew = (sw + 7) / 8 * 8 * hs / hr;
+
+    if (vr == 3)
+        eh = (sh + 2) / 3 * 3 * vs / vr;
+    else
+        eh = (sh + 7) / 8 * 8 * vs / vr;
+
+    ratio_scalable = any_ratio_2d_scale(scale_vars,
+                                        (const unsigned char *)src_yuv_config->y_buffer,
+                                        src_yuv_config->y_stride, sw, sh,
+                                        (unsigned char *) dst_yuv_config->y_buffer + YOffset,
+                                        dst_yuv_config->y_stride, dw, dh);
+
+    for (i = 0; i < eh; i++)
+        duck_memset(dst_yuv_config->y_buffer + YOffset + i * dst_yuv_config->y_stride + dw, 0, ew - dw);
+
+    for (i = dh; i < eh; i++)
+        duck_memset(dst_yuv_config->y_buffer + YOffset + i * dst_yuv_config->y_stride, 0, ew);
+
+    if (ratio_scalable == 0)
+        return ratio_scalable;
+
+    sw = (sw + 1) >> 1;
+    sh = (sh + 1) >> 1;
+    dw = (dw + 1) >> 1;
+    dh = (dh + 1) >> 1;
+
+    any_ratio_2d_scale(scale_vars,
+                       (const unsigned char *)src_yuv_config->u_buffer,
+                       src_yuv_config->y_stride / 2, sw, sh,
+                       (unsigned char *)dst_yuv_config->u_buffer + UVOffset,
+                       dst_yuv_config->uv_stride, dw, dh);
+
+    any_ratio_2d_scale(scale_vars,
+                       (const unsigned char *)src_yuv_config->v_buffer,
+                       src_yuv_config->y_stride / 2, sw, sh,
+                       (unsigned char *)dst_yuv_config->v_buffer + UVOffset,
+                       dst_yuv_config->uv_stride, dw, dh);
+
+    return ratio_scalable;
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : center_image
+ *
+ *  INPUTS        : SCALE_INSTANCE *si       : Pointer to post-processor instance.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Centers the image without scaling in the output buffer.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+static void
+center_image(YV12_BUFFER_CONFIG *src_yuv_config, YV12_BUFFER_CONFIG *dst_yuv_config)
+{
+    int i;
+    int row_offset, col_offset;
+    unsigned char *src_data_pointer;
+    unsigned char *dst_data_pointer;
+
+    /* center values */
+    row_offset = (dst_yuv_config->y_height - src_yuv_config->y_height) / 2;
+    col_offset = (dst_yuv_config->y_width - src_yuv_config->y_width) / 2;
+
+    /* Y's */
+    src_data_pointer = src_yuv_config->y_buffer;
+    dst_data_pointer = (unsigned char *)dst_yuv_config->y_buffer + (row_offset * dst_yuv_config->y_stride) + col_offset;
+
+    for (i = 0; i < src_yuv_config->y_height; i++)
+    {
+        duck_memcpy(dst_data_pointer, src_data_pointer, src_yuv_config->y_width);
+        dst_data_pointer += dst_yuv_config->y_stride;
+        src_data_pointer += src_yuv_config->y_stride;
+    }
+
+    row_offset /= 2;
+    col_offset /= 2;
+
+    /* U's */
+    src_data_pointer = src_yuv_config->u_buffer;
+    dst_data_pointer = (unsigned char *)dst_yuv_config->u_buffer + (row_offset * dst_yuv_config->uv_stride) + col_offset;
+
+    for (i = 0; i < src_yuv_config->uv_height; i++)
+    {
+        duck_memcpy(dst_data_pointer, src_data_pointer, src_yuv_config->uv_width);
+        dst_data_pointer += dst_yuv_config->uv_stride;
+        src_data_pointer += src_yuv_config->uv_stride;
+    }
+
+    /* V's */
+    src_data_pointer = src_yuv_config->v_buffer;
+    dst_data_pointer = (unsigned char *)dst_yuv_config->v_buffer + (row_offset * dst_yuv_config->uv_stride) + col_offset;
+
+    for (i = 0; i < src_yuv_config->uv_height; i++)
+    {
+        duck_memcpy(dst_data_pointer, src_data_pointer, src_yuv_config->uv_width);
+        dst_data_pointer += dst_yuv_config->uv_stride;
+        src_data_pointer += src_yuv_config->uv_stride;
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : scale_or_center
+ *
+ *  INPUTS        : SCALE_INSTANCE *si       : Pointer to post-processor instance.
+ *
+ *
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Decides to scale or center image in scale buffer for blit
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+void
+vp8_yv12_scale_or_center
+(
+    YV12_BUFFER_CONFIG *src_yuv_config,
+    YV12_BUFFER_CONFIG *dst_yuv_config,
+    int expanded_frame_width,
+    int expanded_frame_height,
+    int scaling_mode,
+    int HScale,
+    int HRatio,
+    int VScale,
+    int VRatio
+)
+{
+    /*if ( ppi->post_processing_level )
+          update_umvborder ( ppi, frame_buffer );*/
+
+
+    switch (scaling_mode)
+    {
+    case SCALE_TO_FIT:
+    case MAINTAIN_ASPECT_RATIO:
+    {
+        SCALE_VARS scale_vars;
+        /* center values */
+#if 1
+        int row = (dst_yuv_config->y_height - expanded_frame_height) / 2;
+        int col = (dst_yuv_config->y_width  - expanded_frame_width) / 2;
+        /*int YOffset  = row * dst_yuv_config->y_width + col;
+        int UVOffset = (row>>1) * dst_yuv_config->uv_width + (col>>1);*/
+        int YOffset  = row * dst_yuv_config->y_stride + col;
+        int UVOffset = (row >> 1) * dst_yuv_config->uv_stride + (col >> 1);
+#else
+        int row = (src_yuv_config->y_height - expanded_frame_height) / 2;
+        int col = (src_yuv_config->y_width  - expanded_frame_width) / 2;
+        int YOffset  = row * src_yuv_config->y_width + col;
+        int UVOffset = (row >> 1) * src_yuv_config->uv_width + (col >> 1);
+#endif
+
+        scale_vars.dst_yuv_config = dst_yuv_config;
+        scale_vars.src_yuv_config = src_yuv_config;
+        scale_vars.HScale = HScale;
+        scale_vars.HRatio = HRatio;
+        scale_vars.VScale = VScale;
+        scale_vars.VRatio = VRatio;
+        scale_vars.expanded_frame_width = expanded_frame_width;
+        scale_vars.expanded_frame_height = expanded_frame_height;
+
+        /* perform center and scale */
+        any_ratio_frame_scale(&scale_vars, YOffset, UVOffset);
+
+        break;
+    }
+    case CENTER:
+        center_image(src_yuv_config, dst_yuv_config);
+        break;
+
+    default:
+        break;
+    }
+}
diff --git a/vpx_scale/generic/yv12config.c b/vpx_scale/generic/yv12config.c
new file mode 100644 (file)
index 0000000..eff594e
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_scale/yv12config.h"
+#include "vpx_mem/vpx_mem.h"
+
+/****************************************************************************
+*  Exports
+****************************************************************************/
+
+/****************************************************************************
+ *
+ ****************************************************************************/
+int
+vp8_yv12_de_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf)
+{
+    if (ybf)
+    {
+        vpx_free(ybf->buffer_alloc);
+
+        /* buffer_alloc isn't accessed by most functions.  Rather y_buffer,
+          u_buffer and v_buffer point to buffer_alloc and are used.  Clear out
+          all of this so that a freed pointer isn't inadvertently used */
+        vpx_memset (ybf, 0, sizeof (YV12_BUFFER_CONFIG));
+    }
+    else
+    {
+        return -1;
+    }
+
+    return 0;
+}
+
+/****************************************************************************
+ *
+ ****************************************************************************/
+int
+vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, int width, int height, int border)
+{
+/*NOTE:*/
+
+    if (ybf)
+    {
+        int y_stride = ((width + 2 * border) + 31) & ~31;
+        int yplane_size = (height + 2 * border) * y_stride;
+        int uv_width = width >> 1;
+        int uv_height = height >> 1;
+        /** There is currently a bunch of code which assumes
+          *  uv_stride == y_stride/2, so enforce this here. */
+        int uv_stride = y_stride >> 1;
+        int uvplane_size = (uv_height + border) * uv_stride;
+
+        vp8_yv12_de_alloc_frame_buffer(ybf);
+
+        /** Only support allocating buffers that have a height and width that
+          *  are multiples of 16, and a border that's a multiple of 32.
+          * The border restriction is required to get 16-byte alignment of the
+          *  start of the chroma rows without intoducing an arbitrary gap
+          *  between planes, which would break the semantics of things like
+          *  vpx_img_set_rect(). */
+        if ((width & 0xf) | (height & 0xf) | (border & 0x1f))
+            return -3;
+
+        ybf->y_width  = width;
+        ybf->y_height = height;
+        ybf->y_stride = y_stride;
+
+        ybf->uv_width = uv_width;
+        ybf->uv_height = uv_height;
+        ybf->uv_stride = uv_stride;
+
+        ybf->border = border;
+        ybf->frame_size = yplane_size + 2 * uvplane_size;
+
+        ybf->buffer_alloc = (unsigned char *) vpx_memalign(32, ybf->frame_size);
+
+        if (ybf->buffer_alloc == NULL)
+            return -1;
+
+        ybf->y_buffer = ybf->buffer_alloc + (border * y_stride) + border;
+        ybf->u_buffer = ybf->buffer_alloc + yplane_size + (border / 2  * uv_stride) + border / 2;
+        ybf->v_buffer = ybf->buffer_alloc + yplane_size + uvplane_size + (border / 2  * uv_stride) + border / 2;
+
+        ybf->corrupted = 0; /* assume not currupted by errors */
+    }
+    else
+    {
+        return -2;
+    }
+
+    return 0;
+}
diff --git a/vpx_scale/generic/yv12extend.c b/vpx_scale/generic/yv12extend.c
new file mode 100644 (file)
index 0000000..638633b
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#include "vpx_scale/yv12config.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_scale/vpxscale.h"
+
+/****************************************************************************
+*  Exports
+****************************************************************************/
+
+/****************************************************************************
+ *
+ ****************************************************************************/
+void
+vp8_yv12_extend_frame_borders_c(YV12_BUFFER_CONFIG *ybf)
+{
+    int i;
+    unsigned char *src_ptr1, *src_ptr2;
+    unsigned char *dest_ptr1, *dest_ptr2;
+
+    unsigned int Border;
+    int plane_stride;
+    int plane_height;
+    int plane_width;
+
+    /***********/
+    /* Y Plane */
+    /***********/
+    Border = ybf->border;
+    plane_stride = ybf->y_stride;
+    plane_height = ybf->y_height;
+    plane_width = ybf->y_width;
+
+    /* copy the left and right most columns out */
+    src_ptr1 = ybf->y_buffer;
+    src_ptr2 = src_ptr1 + plane_width - 1;
+    dest_ptr1 = src_ptr1 - Border;
+    dest_ptr2 = src_ptr2 + 1;
+
+    for (i = 0; i < plane_height; i++)
+    {
+        vpx_memset(dest_ptr1, src_ptr1[0], Border);
+        vpx_memset(dest_ptr2, src_ptr2[0], Border);
+        src_ptr1  += plane_stride;
+        src_ptr2  += plane_stride;
+        dest_ptr1 += plane_stride;
+        dest_ptr2 += plane_stride;
+    }
+
+    /* Now copy the top and bottom source lines into each line of the respective borders */
+    src_ptr1 = ybf->y_buffer - Border;
+    src_ptr2 = src_ptr1 + (plane_height * plane_stride) - plane_stride;
+    dest_ptr1 = src_ptr1 - (Border * plane_stride);
+    dest_ptr2 = src_ptr2 + plane_stride;
+
+    for (i = 0; i < (int)Border; i++)
+    {
+        vpx_memcpy(dest_ptr1, src_ptr1, plane_stride);
+        vpx_memcpy(dest_ptr2, src_ptr2, plane_stride);
+        dest_ptr1 += plane_stride;
+        dest_ptr2 += plane_stride;
+    }
+
+
+    /***********/
+    /* U Plane */
+    /***********/
+    plane_stride = ybf->uv_stride;
+    plane_height = ybf->uv_height;
+    plane_width = ybf->uv_width;
+    Border /= 2;
+
+    /* copy the left and right most columns out */
+    src_ptr1 = ybf->u_buffer;
+    src_ptr2 = src_ptr1 + plane_width - 1;
+    dest_ptr1 = src_ptr1 - Border;
+    dest_ptr2 = src_ptr2 + 1;
+
+    for (i = 0; i < plane_height; i++)
+    {
+        vpx_memset(dest_ptr1, src_ptr1[0], Border);
+        vpx_memset(dest_ptr2, src_ptr2[0], Border);
+        src_ptr1  += plane_stride;
+        src_ptr2  += plane_stride;
+        dest_ptr1 += plane_stride;
+        dest_ptr2 += plane_stride;
+    }
+
+    /* Now copy the top and bottom source lines into each line of the respective borders */
+    src_ptr1 = ybf->u_buffer - Border;
+    src_ptr2 = src_ptr1 + (plane_height * plane_stride) - plane_stride;
+    dest_ptr1 = src_ptr1 - (Border * plane_stride);
+    dest_ptr2 = src_ptr2 + plane_stride;
+
+    for (i = 0; i < (int)(Border); i++)
+    {
+        vpx_memcpy(dest_ptr1, src_ptr1, plane_stride);
+        vpx_memcpy(dest_ptr2, src_ptr2, plane_stride);
+        dest_ptr1 += plane_stride;
+        dest_ptr2 += plane_stride;
+    }
+
+    /***********/
+    /* V Plane */
+    /***********/
+
+    /* copy the left and right most columns out */
+    src_ptr1 = ybf->v_buffer;
+    src_ptr2 = src_ptr1 + plane_width - 1;
+    dest_ptr1 = src_ptr1 - Border;
+    dest_ptr2 = src_ptr2 + 1;
+
+    for (i = 0; i < plane_height; i++)
+    {
+        vpx_memset(dest_ptr1, src_ptr1[0], Border);
+        vpx_memset(dest_ptr2, src_ptr2[0], Border);
+        src_ptr1  += plane_stride;
+        src_ptr2  += plane_stride;
+        dest_ptr1 += plane_stride;
+        dest_ptr2 += plane_stride;
+    }
+
+    /* Now copy the top and bottom source lines into each line of the respective borders */
+    src_ptr1 = ybf->v_buffer - Border;
+    src_ptr2 = src_ptr1 + (plane_height * plane_stride) - plane_stride;
+    dest_ptr1 = src_ptr1 - (Border * plane_stride);
+    dest_ptr2 = src_ptr2 + plane_stride;
+
+    for (i = 0; i < (int)(Border); i++)
+    {
+        vpx_memcpy(dest_ptr1, src_ptr1, plane_stride);
+        vpx_memcpy(dest_ptr2, src_ptr2, plane_stride);
+        dest_ptr1 += plane_stride;
+        dest_ptr2 += plane_stride;
+    }
+}
+
+
+static void
+extend_frame_borders_yonly_c(YV12_BUFFER_CONFIG *ybf)
+{
+    int i;
+    unsigned char *src_ptr1, *src_ptr2;
+    unsigned char *dest_ptr1, *dest_ptr2;
+
+    unsigned int Border;
+    int plane_stride;
+    int plane_height;
+    int plane_width;
+
+    /***********/
+    /* Y Plane */
+    /***********/
+    Border = ybf->border;
+    plane_stride = ybf->y_stride;
+    plane_height = ybf->y_height;
+    plane_width = ybf->y_width;
+
+    /* copy the left and right most columns out */
+    src_ptr1 = ybf->y_buffer;
+    src_ptr2 = src_ptr1 + plane_width - 1;
+    dest_ptr1 = src_ptr1 - Border;
+    dest_ptr2 = src_ptr2 + 1;
+
+    for (i = 0; i < plane_height; i++)
+    {
+        vpx_memset(dest_ptr1, src_ptr1[0], Border);
+        vpx_memset(dest_ptr2, src_ptr2[0], Border);
+        src_ptr1  += plane_stride;
+        src_ptr2  += plane_stride;
+        dest_ptr1 += plane_stride;
+        dest_ptr2 += plane_stride;
+    }
+
+    /* Now copy the top and bottom source lines into each line of the respective borders */
+    src_ptr1 = ybf->y_buffer - Border;
+    src_ptr2 = src_ptr1 + (plane_height * plane_stride) - plane_stride;
+    dest_ptr1 = src_ptr1 - (Border * plane_stride);
+    dest_ptr2 = src_ptr2 + plane_stride;
+
+    for (i = 0; i < (int)Border; i++)
+    {
+        vpx_memcpy(dest_ptr1, src_ptr1, plane_stride);
+        vpx_memcpy(dest_ptr2, src_ptr2, plane_stride);
+        dest_ptr1 += plane_stride;
+        dest_ptr2 += plane_stride;
+    }
+
+    plane_stride /= 2;
+    plane_height /= 2;
+    plane_width /= 2;
+    Border /= 2;
+
+}
+
+
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vp8_yv12_copy_frame
+ *
+ *  INPUTS        :
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Copies the source image into the destination image and
+ *                  updates the destination's UMV borders.
+ *
+ *  SPECIAL NOTES : The frames are assumed to be identical in size.
+ *
+ ****************************************************************************/
+void
+vp8_yv12_copy_frame_c(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc)
+{
+    int row;
+    unsigned char *source, *dest;
+
+    source = src_ybc->y_buffer;
+    dest = dst_ybc->y_buffer;
+
+    for (row = 0; row < src_ybc->y_height; row++)
+    {
+        vpx_memcpy(dest, source, src_ybc->y_width);
+        source += src_ybc->y_stride;
+        dest   += dst_ybc->y_stride;
+    }
+
+    source = src_ybc->u_buffer;
+    dest = dst_ybc->u_buffer;
+
+    for (row = 0; row < src_ybc->uv_height; row++)
+    {
+        vpx_memcpy(dest, source, src_ybc->uv_width);
+        source += src_ybc->uv_stride;
+        dest   += dst_ybc->uv_stride;
+    }
+
+    source = src_ybc->v_buffer;
+    dest = dst_ybc->v_buffer;
+
+    for (row = 0; row < src_ybc->uv_height; row++)
+    {
+        vpx_memcpy(dest, source, src_ybc->uv_width);
+        source += src_ybc->uv_stride;
+        dest   += dst_ybc->uv_stride;
+    }
+
+    vp8_yv12_extend_frame_borders_c(dst_ybc);
+}
+
+void vp8_yv12_copy_y_c(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc)
+{
+    int row;
+    unsigned char *source, *dest;
+
+
+    source = src_ybc->y_buffer;
+    dest = dst_ybc->y_buffer;
+
+    for (row = 0; row < src_ybc->y_height; row++)
+    {
+        vpx_memcpy(dest, source, src_ybc->y_width);
+        source += src_ybc->y_stride;
+        dest   += dst_ybc->y_stride;
+    }
+}
diff --git a/vpx_scale/generic/yv12extend_generic.h b/vpx_scale/generic/yv12extend_generic.h
new file mode 100644 (file)
index 0000000..cc2a554
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef YV12_EXTEND_GENERIC_H
+#define YV12_EXTEND_GENERIC_H
+
+#include "vpx_scale/yv12config.h"
+
+    void vp8_yv12_extend_frame_borders(YV12_BUFFER_CONFIG *ybf);
+
+    /* Copy Y,U,V buffer data from src to dst, filling border of dst as well. */
+    void vp8_yv12_copy_frame(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc);
+
+    /* Copy Y buffer data from src_ybc to dst_ybc without filling border data */
+    void vp8_yv12_copy_y_c(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc);
+
+#endif /* YV12_EXTEND_GENERIC_H */
diff --git a/vpx_scale/include/generic/vpxscale_arbitrary.h b/vpx_scale/include/generic/vpxscale_arbitrary.h
new file mode 100644 (file)
index 0000000..39de181
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef __VPX_SCALE_ARBITRARY_H__
+#define __VPX_SCALE_ARBITRARY_H__
+
+#include "vpx_scale/yv12config.h"
+
+typedef struct
+{
+    int in_width;
+    int in_height;
+
+    int out_width;
+    int out_height;
+    int max_usable_out_width;
+
+    // numerator for the width and height
+    int nw;
+    int nh;
+    int nh_uv;
+
+    // output to input correspondance array
+    short *l_w;
+    short *l_h;
+    short *l_h_uv;
+
+    // polyphase coefficients
+    short *c_w;
+    short *c_h;
+    short *c_h_uv;
+
+    // buffer for horizontal filtering.
+    unsigned char *hbuf;
+    unsigned char *hbuf_uv;
+} BICUBIC_SCALER_STRUCT;
+
+int bicubic_coefficient_setup(int in_width, int in_height, int out_width, int out_height);
+int bicubic_scale(int in_width, int in_height, int in_stride,
+                  int out_width, int out_height, int out_stride,
+                  unsigned char *input_image, unsigned char *output_image);
+void bicubic_scale_frame_reset();
+void bicubic_scale_frame(YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst,
+                         int new_width, int new_height);
+void bicubic_coefficient_init();
+void bicubic_coefficient_destroy();
+
+#endif /* __VPX_SCALE_ARBITRARY_H__ */
diff --git a/vpx_scale/include/generic/vpxscale_depricated.h b/vpx_scale/include/generic/vpxscale_depricated.h
new file mode 100644 (file)
index 0000000..3f7fe0f
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/****************************************************************************
+*
+*   Module Title :     postp.h
+*
+*   Description  :     Post processor interface
+*
+****************************************************************************/
+#ifndef VPXSCALE_H
+#define VPXSCALE_H
+
+extern void (*vp8_vertical_band_4_5_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width);
+extern void (*vp8_last_vertical_band_4_5_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width);
+extern void (*vp8_vertical_band_3_5_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width);
+extern void (*vp8_last_vertical_band_3_5_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width);
+extern void (*vp8_horizontal_line_1_2_scale)(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width);
+extern void (*vp8_horizontal_line_3_5_scale)(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width);
+extern void (*vp8_horizontal_line_4_5_scale)(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width);
+extern void (*vp8_vertical_band_1_2_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width);
+extern void (*vp8_last_vertical_band_1_2_scale)(unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width);
+
+extern void  dmachine_specific_config(int mmx_enabled, int xmm_enabled, int wmt_enabled);
+
+#endif
diff --git a/vpx_scale/scale_mode.h b/vpx_scale/scale_mode.h
new file mode 100644 (file)
index 0000000..1476e64
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/****************************************************************************
+*
+*****************************************************************************
+*/
+
+#ifndef SCALE_MODE_H
+#define SCALE_MODE_H
+
+typedef enum
+{
+    MAINTAIN_ASPECT_RATIO   = 0x0,
+    SCALE_TO_FIT            = 0x1,
+    CENTER                  = 0x2,
+    OTHER                   = 0x3
+} SCALE_MODE;
+
+
+#endif
diff --git a/vpx_scale/vpx_scale.mk b/vpx_scale/vpx_scale.mk
new file mode 100644 (file)
index 0000000..dc89478
--- /dev/null
@@ -0,0 +1,18 @@
+SCALE_SRCS-yes += vpx_scale.mk
+SCALE_SRCS-yes += scale_mode.h
+SCALE_SRCS-yes += yv12config.h
+SCALE_SRCS-yes += vpxscale.h
+SCALE_SRCS-yes += generic/vpxscale.c
+SCALE_SRCS-yes += generic/yv12config.c
+SCALE_SRCS-yes += generic/yv12extend.c
+SCALE_SRCS-yes += generic/yv12extend_generic.h
+SCALE_SRCS-$(CONFIG_SPATIAL_RESAMPLING) += generic/gen_scalers.c
+
+#neon
+SCALE_SRCS-$(HAVE_NEON)  += arm/neon/vp8_vpxyv12_copyframe_func_neon$(ASM)
+SCALE_SRCS-$(HAVE_NEON)  += arm/neon/vp8_vpxyv12_copy_y_neon$(ASM)
+SCALE_SRCS-$(HAVE_NEON)  += arm/neon/vp8_vpxyv12_copysrcframe_func_neon$(ASM)
+SCALE_SRCS-$(HAVE_NEON)  += arm/neon/vp8_vpxyv12_extendframeborders_neon$(ASM)
+SCALE_SRCS-$(HAVE_NEON)  += arm/neon/yv12extend_arm.c
+
+SCALE_SRCS-no += $(SCALE_SRCS_REMOVE-yes)
diff --git a/vpx_scale/vpxscale.h b/vpx_scale/vpxscale.h
new file mode 100644 (file)
index 0000000..8919a24
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef VPXSCALE_H
+#define VPXSCALE_H
+
+#include "vpx_scale/yv12config.h"
+
+extern void vp8_yv12_scale_or_center
+(
+    YV12_BUFFER_CONFIG *src_yuv_config,
+    YV12_BUFFER_CONFIG *dst_yuv_config,
+    int expanded_frame_width,
+    int expanded_frame_height,
+    int scaling_mode,
+    int HScale,
+    int HRatio,
+    int VScale,
+    int VRatio
+);
+extern void vp8_scale_frame
+(
+    YV12_BUFFER_CONFIG *src,
+    YV12_BUFFER_CONFIG *dst,
+    unsigned char *temp_area,
+    unsigned char temp_height,
+    unsigned int hscale,
+    unsigned int hratio,
+    unsigned int vscale,
+    unsigned int vratio,
+    unsigned int interlaced
+);
+
+#endif
diff --git a/vpx_scale/win32/scaleopt.c b/vpx_scale/win32/scaleopt.c
new file mode 100644 (file)
index 0000000..3711fe5
--- /dev/null
@@ -0,0 +1,1750 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/****************************************************************************
+*
+*   Module Title :     scaleopt.cpp
+*
+*   Description  :     Optimized scaling functions
+*
+****************************************************************************/
+#include "pragmas.h"
+
+
+
+/****************************************************************************
+*  Module Statics
+****************************************************************************/
+__declspec(align(16)) const static unsigned short one_fifth[]  = { 51, 51, 51, 51 };
+__declspec(align(16)) const static unsigned short two_fifths[] = { 102, 102, 102, 102 };
+__declspec(align(16)) const static unsigned short three_fifths[] = { 154, 154, 154, 154 };
+__declspec(align(16)) const static unsigned short four_fifths[] = { 205, 205, 205, 205 };
+__declspec(align(16)) const static unsigned short round_values[] = { 128, 128, 128, 128 };
+__declspec(align(16)) const static unsigned short four_ones[] = { 1, 1, 1, 1};
+__declspec(align(16)) const static unsigned short const45_2[] = {205, 154, 102,  51 };
+__declspec(align(16)) const static unsigned short const45_1[] = { 51, 102, 154, 205 };
+__declspec(align(16)) const static unsigned char  mask45[] = { 0, 0, 0, 0, 0, 0, 255, 0};
+__declspec(align(16)) const static unsigned short const35_2[] = { 154,  51, 205, 102 };
+__declspec(align(16)) const static unsigned short const35_1[] = { 102, 205,  51, 154 };
+
+
+
+#include "vpx_scale/vpxscale.h"
+#include "vpx_mem/vpx_mem.h"
+
+/****************************************************************************
+ *
+ *  ROUTINE       : horizontal_line_3_5_scale_mmx
+ *
+ *  INPUTS        : const unsigned char *source :
+ *                  unsigned int source_width    :
+ *                  unsigned char *dest         :
+ *                  unsigned int dest_width      :
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : 3 to 5 up-scaling of a horizontal line of pixels.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+static
+void horizontal_line_3_5_scale_mmx
+(
+    const unsigned char *source,
+    unsigned int source_width,
+    unsigned char *dest,
+    unsigned int dest_width
+)
+{
+    (void) dest_width;
+
+    __asm
+    {
+
+        push ebx
+
+        mov         esi,    source
+        mov         edi,    dest
+
+        mov         ecx,    source_width
+        lea         edx,    [esi+ecx-3];
+
+        movq        mm5,    const35_1       // mm5 = 66 xx cd xx 33 xx 9a xx
+        movq        mm6,    const35_2       // mm6 = 9a xx 33 xx cd xx 66 xx
+
+        movq        mm4,    round_values     // mm4 = 80 xx 80 xx 80 xx 80 xx
+        pxor        mm7,    mm7             // clear mm7
+
+        horiz_line_3_5_loop:
+
+        mov        eax,    DWORD PTR [esi] // eax = 00 01 02 03
+        mov        ebx,    eax
+
+        and         ebx,    0xffff00        // ebx = xx 01 02 xx
+        mov         ecx,    eax             // ecx = 00 01 02 03
+
+        and         eax,    0xffff0000      // eax = xx xx 02 03
+        xor         ecx,    eax             // ecx = 00 01 xx xx
+
+        shr         ebx,    8               // ebx = 01 02 xx xx
+        or          eax,    ebx             // eax = 01 02 02 03
+
+        shl         ebx,    16              // ebx = xx xx 01 02
+        movd        mm1,    eax             // mm1 = 01 02 02 03 xx xx xx xx
+
+        or          ebx,    ecx             // ebx = 00 01 01 02
+        punpcklbw   mm1,    mm7             // mm1 = 01 xx 02 xx 02 xx 03 xx
+
+        movd        mm0,    ebx             // mm0 = 00 01 01 02
+        pmullw      mm1,    mm6             //
+
+        punpcklbw   mm0,    mm7             // mm0 = 00 xx 01 xx 01 xx 02 xx
+        pmullw      mm0,    mm5             //
+
+        mov         [edi],  ebx             // writeoutput 00 xx xx xx
+        add         esi,    3
+
+        add         edi,    5
+        paddw       mm0,    mm1
+
+        paddw       mm0,    mm4
+        psrlw       mm0,    8
+
+        cmp         esi,    edx
+        packuswb    mm0,    mm7
+
+        movd        DWORD Ptr [edi-4], mm0
+        jl          horiz_line_3_5_loop
+
+//Exit:
+        mov         eax,    DWORD PTR [esi] // eax = 00 01 02 03
+        mov         ebx,    eax
+
+        and         ebx,    0xffff00        // ebx = xx 01 02 xx
+        mov         ecx,    eax             // ecx = 00 01 02 03
+
+        and         eax,    0xffff0000      // eax = xx xx 02 03
+        xor         ecx,    eax             // ecx = 00 01 xx xx
+
+        shr         ebx,    8               // ebx = 01 02 xx xx
+        or          eax,    ebx             // eax = 01 02 02 03
+
+        shl         eax,    8               // eax = xx 01 02 02
+        and         eax,    0xffff0000      // eax = xx xx 02 02
+
+        or          eax,    ebx             // eax = 01 02 02 02
+
+        shl         ebx,    16              // ebx = xx xx 01 02
+        movd        mm1,    eax             // mm1 = 01 02 02 02 xx xx xx xx
+
+        or          ebx,    ecx             // ebx = 00 01 01 02
+        punpcklbw   mm1,    mm7             // mm1 = 01 xx 02 xx 02 xx 02 xx
+
+        movd        mm0,    ebx             // mm0 = 00 01 01 02
+        pmullw      mm1,    mm6             //
+
+        punpcklbw   mm0,    mm7             // mm0 = 00 xx 01 xx 01 xx 02 xx
+        pmullw      mm0,    mm5             //
+
+        mov         [edi],  ebx             // writeoutput 00 xx xx xx
+        paddw       mm0,    mm1
+
+        paddw       mm0,    mm4
+        psrlw       mm0,    8
+
+        packuswb    mm0,    mm7
+        movd        DWORD Ptr [edi+1], mm0
+
+        pop ebx
+
+    }
+
+}
+
+
+/****************************************************************************
+ *
+ *  ROUTINE       : horizontal_line_4_5_scale_mmx
+ *
+ *  INPUTS        : const unsigned char *source :
+ *                  unsigned int source_width    :
+ *                  unsigned char *dest         :
+ *                  unsigned int dest_width      :
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : 4 to 5 up-scaling of a horizontal line of pixels.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+static
+void horizontal_line_4_5_scale_mmx
+(
+    const unsigned char *source,
+    unsigned int source_width,
+    unsigned char *dest,
+    unsigned int dest_width
+)
+{
+    (void)dest_width;
+
+    __asm
+    {
+
+        mov         esi,    source
+        mov         edi,    dest
+
+        mov         ecx,    source_width
+        lea         edx,    [esi+ecx-8];
+
+        movq        mm5,    const45_1       // mm5 = 33 xx 66 xx 9a xx cd xx
+        movq        mm6,    const45_2       // mm6 = cd xx 9a xx 66 xx 33 xx
+
+        movq        mm4,    round_values     // mm4 = 80 xx 80 xx 80 xx 80 xx
+        pxor        mm7,    mm7             // clear mm7
+
+        horiz_line_4_5_loop:
+
+        movq        mm0,    QWORD PTR [esi]           // mm0 = 00 01 02 03 04 05 06 07
+        movq        mm1,    QWORD PTR [esi+1];        // mm1 = 01 02 03 04 05 06 07 08
+
+        movq        mm2,    mm0             // mm2 = 00 01 02 03 04 05 06 07
+        movq        mm3,    mm1             // mm3 = 01 02 03 04 05 06 07 08
+
+        movd        DWORD PTR [edi],  mm0             // write output 00 xx xx xx
+        punpcklbw   mm0,    mm7             // mm0 = 00 xx 01 xx 02 xx 03 xx
+
+        punpcklbw   mm1,    mm7             // mm1 = 01 xx 02 xx 03 xx 04 xx
+        pmullw      mm0,    mm5             // 00* 51 01*102 02*154 03*205
+
+        pmullw      mm1,    mm6             // 01*205 02*154 03*102 04* 51
+        punpckhbw   mm2,    mm7             // mm2 = 04 xx 05 xx 06 xx 07 xx
+
+        movd        DWORD PTR [edi+5], mm2            // write ouput 05 xx xx xx
+        pmullw      mm2,    mm5             // 04* 51 05*102 06*154 07*205
+
+        punpckhbw   mm3,    mm7             // mm3 = 05 xx 06 xx 07 xx 08 xx
+        pmullw      mm3,    mm6             // 05*205 06*154 07*102 08* 51
+
+        paddw       mm0,    mm1             // added round values
+        paddw       mm0,    mm4
+
+        psrlw       mm0,    8               // output: 01 xx 02 xx 03 xx 04 xx
+        packuswb    mm0,    mm7
+
+        movd        DWORD PTR [edi+1], mm0  // write output 01 02 03 04
+        add         edi,    10
+
+        add         esi,    8
+        paddw       mm2,    mm3             //
+
+        paddw       mm2,    mm4             // added round values
+        cmp         esi,    edx
+
+        psrlw       mm2,    8
+        packuswb    mm2,    mm7
+
+        movd        DWORD PTR [edi-4], mm2 // writeoutput 06 07 08 09
+        jl         horiz_line_4_5_loop
+
+//Exit:
+        movq        mm0,    [esi]           // mm0 = 00 01 02 03 04 05 06 07
+        movq        mm1,    mm0             // mm1 = 00 01 02 03 04 05 06 07
+
+        movq        mm2,    mm0             // mm2 = 00 01 02 03 04 05 06 07
+        psrlq       mm1,    8               // mm1 = 01 02 03 04 05 06 07 00
+
+        movq        mm3,    mask45          // mm3 = 00 00 00 00 00 00 ff 00
+        pand        mm3,    mm1             // mm3 = 00 00 00 00 00 00 07 00
+
+        psllq       mm3,    8               // mm3 = 00 00 00 00 00 00 00 07
+        por         mm1,    mm3             // mm1 = 01 02 03 04 05 06 07 07
+
+        movq        mm3,    mm1
+
+        movd        DWORD PTR [edi],  mm0   // write output 00 xx xx xx
+        punpcklbw   mm0,    mm7             // mm0 = 00 xx 01 xx 02 xx 03 xx
+
+        punpcklbw   mm1,    mm7             // mm1 = 01 xx 02 xx 03 xx 04 xx
+        pmullw      mm0,    mm5             // 00* 51 01*102 02*154 03*205
+
+        pmullw      mm1,    mm6             // 01*205 02*154 03*102 04* 51
+        punpckhbw   mm2,    mm7             // mm2 = 04 xx 05 xx 06 xx 07 xx
+
+        movd        DWORD PTR [edi+5], mm2  // write ouput 05 xx xx xx
+        pmullw      mm2,    mm5             // 04* 51 05*102 06*154 07*205
+
+        punpckhbw   mm3,    mm7             // mm3 = 05 xx 06 xx 07 xx 08 xx
+        pmullw      mm3,    mm6             // 05*205 06*154 07*102 07* 51
+
+        paddw       mm0,    mm1             // added round values
+        paddw       mm0,    mm4
+
+        psrlw       mm0,    8               // output: 01 xx 02 xx 03 xx 04 xx
+        packuswb    mm0,    mm7             // 01 02 03 04 xx xx xx xx
+
+        movd        DWORD PTR [edi+1], mm0  // write output 01 02 03 04
+        paddw       mm2,    mm3             //
+
+        paddw       mm2,    mm4             // added round values
+        psrlw       mm2,    8
+
+        packuswb    mm2,    mm7
+        movd        DWORD PTR [edi+6], mm2  // writeoutput 06 07 08 09
+
+
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vertical_band_4_5_scale_mmx
+ *
+ *  INPUTS        : unsigned char *dest    :
+ *                  unsigned int dest_pitch :
+ *                  unsigned int dest_width :
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : 4 to 5 up-scaling of a 4 pixel high band of pixels.
+ *
+ *  SPECIAL NOTES : The routine uses the first line of the band below
+ *                  the current band. The function also has a "C" only
+ *                  version.
+ *
+ ****************************************************************************/
+static
+void vertical_band_4_5_scale_mmx
+(
+    unsigned char *dest,
+    unsigned int dest_pitch,
+    unsigned int dest_width
+)
+{
+    __asm
+    {
+
+        mov         esi,    dest                    // Get the source and destination pointer
+        mov         ecx,    dest_pitch               // Get the pitch size
+
+        lea         edi,    [esi+ecx*2]             // tow lines below
+        add         edi,    ecx                     // three lines below
+
+        pxor        mm7,    mm7                     // clear out mm7
+        mov         edx,    dest_width               // Loop counter
+
+        vs_4_5_loop:
+
+        movq        mm0,    QWORD ptr [esi]         // src[0];
+        movq        mm1,    QWORD ptr [esi+ecx]     // src[1];
+
+        movq        mm2,    mm0                     // Make a copy
+        punpcklbw   mm0,    mm7                     // unpack low to word
+
+        movq        mm5,    one_fifth
+        punpckhbw   mm2,    mm7                     // unpack high to word
+
+        pmullw      mm0,    mm5                     // a * 1/5
+
+        movq        mm3,    mm1                     // make a copy
+        punpcklbw   mm1,    mm7                     // unpack low to word
+
+        pmullw      mm2,    mm5                     // a * 1/5
+        movq        mm6,    four_fifths               // constan
+
+        movq        mm4,    mm1                     // copy of low b
+        pmullw      mm4,    mm6                     // b * 4/5
+
+        punpckhbw   mm3,    mm7                     // unpack high to word
+        movq        mm5,    mm3                     // copy of high b
+
+        pmullw      mm5,    mm6                     // b * 4/5
+        paddw       mm0,    mm4                     // a * 1/5 + b * 4/5
+
+        paddw       mm2,    mm5                     // a * 1/5 + b * 4/5
+        paddw       mm0,    round_values             // + 128
+
+        paddw       mm2,    round_values             // + 128
+        psrlw       mm0,    8
+
+        psrlw       mm2,    8
+        packuswb    mm0,    mm2                     // des [1]
+
+        movq        QWORD ptr [esi+ecx], mm0        // write des[1]
+        movq        mm0,    [esi+ecx*2]             // mm0 = src[2]
+
+        // mm1, mm3 --- Src[1]
+        // mm0 --- Src[2]
+        // mm7 for unpacking
+
+        movq        mm5,    two_fifths
+        movq        mm2,    mm0                     // make a copy
+
+        pmullw      mm1,    mm5                     // b * 2/5
+        movq        mm6,    three_fifths
+
+
+        punpcklbw   mm0,    mm7                     // unpack low to word
+        pmullw      mm3,    mm5                     // b * 2/5
+
+        movq        mm4,    mm0                     // make copy of c
+        punpckhbw   mm2,    mm7                     // unpack high to word
+
+        pmullw      mm4,    mm6                     // c * 3/5
+        movq        mm5,    mm2
+
+        pmullw      mm5,    mm6                     // c * 3/5
+        paddw       mm1,    mm4                     // b * 2/5 + c * 3/5
+
+        paddw       mm3,    mm5                     // b * 2/5 + c * 3/5
+        paddw       mm1,    round_values             // + 128
+
+        paddw       mm3,    round_values             // + 128
+        psrlw       mm1,    8
+
+        psrlw       mm3,    8
+        packuswb    mm1,    mm3                     // des[2]
+
+        movq        QWORD ptr [esi+ecx*2], mm1      // write des[2]
+        movq        mm1,    [edi]                   // mm1=Src[3];
+
+        // mm0, mm2 --- Src[2]
+        // mm1 --- Src[3]
+        // mm6 --- 3/5
+        // mm7 for unpacking
+
+        pmullw      mm0,    mm6                     // c * 3/5
+        movq        mm5,    two_fifths               // mm5 = 2/5
+
+        movq        mm3,    mm1                     // make a copy
+        pmullw      mm2,    mm6                     // c * 3/5
+
+        punpcklbw   mm1,    mm7                     // unpack low
+        movq        mm4,    mm1                     // make a copy
+
+        punpckhbw   mm3,    mm7                     // unpack high
+        pmullw      mm4,    mm5                     // d * 2/5
+
+        movq        mm6,    mm3                     // make a copy
+        pmullw      mm6,    mm5                     // d * 2/5
+
+        paddw       mm0,    mm4                     // c * 3/5 + d * 2/5
+        paddw       mm2,    mm6                     // c * 3/5 + d * 2/5
+
+        paddw       mm0,    round_values             // + 128
+        paddw       mm2,    round_values             // + 128
+
+        psrlw       mm0,    8
+        psrlw       mm2,    8
+
+        packuswb    mm0,    mm2                     // des[3]
+        movq        QWORD ptr [edi], mm0            // write des[3]
+
+        //  mm1, mm3 --- Src[3]
+        //  mm7 -- cleared for unpacking
+
+        movq        mm0,    [edi+ecx*2]             // mm0, Src[0] of the next group
+
+        movq        mm5,    four_fifths              // mm5 = 4/5
+        pmullw      mm1,    mm5                     // d * 4/5
+
+        movq        mm6,    one_fifth                // mm6 = 1/5
+        movq        mm2,    mm0                     // make a copy
+
+        pmullw      mm3,    mm5                     // d * 4/5
+        punpcklbw   mm0,    mm7                     // unpack low
+
+        pmullw      mm0,    mm6                     // an * 1/5
+        punpckhbw   mm2,    mm7                     // unpack high
+
+        paddw       mm1,    mm0                     // d * 4/5 + an * 1/5
+        pmullw      mm2,    mm6                     // an * 1/5
+
+        paddw       mm3,    mm2                     // d * 4/5 + an * 1/5
+        paddw       mm1,    round_values             // + 128
+
+        paddw       mm3,    round_values             // + 128
+        psrlw       mm1,    8
+
+        psrlw       mm3,    8
+        packuswb    mm1,    mm3                     // des[4]
+
+        movq        QWORD ptr [edi+ecx], mm1        // write des[4]
+
+        add         edi,    8
+        add         esi,    8
+
+        sub         edx,    8
+        jg         vs_4_5_loop
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : last_vertical_band_4_5_scale_mmx
+ *
+ *  INPUTS        : unsigned char *dest    :
+ *                  unsigned int dest_pitch :
+ *                  unsigned int dest_width :
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : None
+ *
+ *  FUNCTION      : 4 to 5 up-scaling of the last 4-pixel high band in an image.
+ *
+ *  SPECIAL NOTES : The routine uses the first line of the band below
+ *                  the current band. The function also has an "C" only
+ *                  version.
+ *
+ ****************************************************************************/
+static
+void last_vertical_band_4_5_scale_mmx
+(
+    unsigned char *dest,
+    unsigned int dest_pitch,
+    unsigned int dest_width
+)
+{
+    __asm
+    {
+        mov         esi,    dest                    // Get the source and destination pointer
+        mov         ecx,    dest_pitch               // Get the pitch size
+
+        lea         edi,    [esi+ecx*2]             // tow lines below
+        add         edi,    ecx                     // three lines below
+
+        pxor        mm7,    mm7                     // clear out mm7
+        mov         edx,    dest_width               // Loop counter
+
+        last_vs_4_5_loop:
+
+        movq        mm0,    QWORD ptr [esi]         // src[0];
+        movq        mm1,    QWORD ptr [esi+ecx]     // src[1];
+
+        movq        mm2,    mm0                     // Make a copy
+        punpcklbw   mm0,    mm7                     // unpack low to word
+
+        movq        mm5,    one_fifth
+        punpckhbw   mm2,    mm7                     // unpack high to word
+
+        pmullw      mm0,    mm5                     // a * 1/5
+
+        movq        mm3,    mm1                     // make a copy
+        punpcklbw   mm1,    mm7                     // unpack low to word
+
+        pmullw      mm2,    mm5                     // a * 1/5
+        movq        mm6,    four_fifths               // constan
+
+        movq        mm4,    mm1                     // copy of low b
+        pmullw      mm4,    mm6                     // b * 4/5
+
+        punpckhbw   mm3,    mm7                     // unpack high to word
+        movq        mm5,    mm3                     // copy of high b
+
+        pmullw      mm5,    mm6                     // b * 4/5
+        paddw       mm0,    mm4                     // a * 1/5 + b * 4/5
+
+        paddw       mm2,    mm5                     // a * 1/5 + b * 4/5
+        paddw       mm0,    round_values             // + 128
+
+        paddw       mm2,    round_values             // + 128
+        psrlw       mm0,    8
+
+        psrlw       mm2,    8
+        packuswb    mm0,    mm2                     // des [1]
+
+        movq        QWORD ptr [esi+ecx], mm0        // write des[1]
+        movq        mm0,    [esi+ecx*2]             // mm0 = src[2]
+
+        // mm1, mm3 --- Src[1]
+        // mm0 --- Src[2]
+        // mm7 for unpacking
+
+        movq        mm5,    two_fifths
+        movq        mm2,    mm0                     // make a copy
+
+        pmullw      mm1,    mm5                     // b * 2/5
+        movq        mm6,    three_fifths
+
+
+        punpcklbw   mm0,    mm7                     // unpack low to word
+        pmullw      mm3,    mm5                     // b * 2/5
+
+        movq        mm4,    mm0                     // make copy of c
+        punpckhbw   mm2,    mm7                     // unpack high to word
+
+        pmullw      mm4,    mm6                     // c * 3/5
+        movq        mm5,    mm2
+
+        pmullw      mm5,    mm6                     // c * 3/5
+        paddw       mm1,    mm4                     // b * 2/5 + c * 3/5
+
+        paddw       mm3,    mm5                     // b * 2/5 + c * 3/5
+        paddw       mm1,    round_values             // + 128
+
+        paddw       mm3,    round_values             // + 128
+        psrlw       mm1,    8
+
+        psrlw       mm3,    8
+        packuswb    mm1,    mm3                     // des[2]
+
+        movq        QWORD ptr [esi+ecx*2], mm1      // write des[2]
+        movq        mm1,    [edi]                   // mm1=Src[3];
+
+        movq        QWORD ptr [edi+ecx], mm1        // write des[4];
+
+        // mm0, mm2 --- Src[2]
+        // mm1 --- Src[3]
+        // mm6 --- 3/5
+        // mm7 for unpacking
+
+        pmullw      mm0,    mm6                     // c * 3/5
+        movq        mm5,    two_fifths               // mm5 = 2/5
+
+        movq        mm3,    mm1                     // make a copy
+        pmullw      mm2,    mm6                     // c * 3/5
+
+        punpcklbw   mm1,    mm7                     // unpack low
+        movq        mm4,    mm1                     // make a copy
+
+        punpckhbw   mm3,    mm7                     // unpack high
+        pmullw      mm4,    mm5                     // d * 2/5
+
+        movq        mm6,    mm3                     // make a copy
+        pmullw      mm6,    mm5                     // d * 2/5
+
+        paddw       mm0,    mm4                     // c * 3/5 + d * 2/5
+        paddw       mm2,    mm6                     // c * 3/5 + d * 2/5
+
+        paddw       mm0,    round_values             // + 128
+        paddw       mm2,    round_values             // + 128
+
+        psrlw       mm0,    8
+        psrlw       mm2,    8
+
+        packuswb    mm0,    mm2                     // des[3]
+        movq        QWORD ptr [edi], mm0            // write des[3]
+
+        //  mm1, mm3 --- Src[3]
+        //  mm7 -- cleared for unpacking
+        add         edi,    8
+        add         esi,    8
+
+        sub         edx,    8
+        jg          last_vs_4_5_loop
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vertical_band_3_5_scale_mmx
+ *
+ *  INPUTS        : unsigned char *dest    :
+ *                  unsigned int dest_pitch :
+ *                  unsigned int dest_width :
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : 3 to 5 up-scaling of a 3-pixel high band of pixels.
+ *
+ *  SPECIAL NOTES : The routine uses the first line of the band below
+ *                  the current band. The function also has an "C" only
+ *                  version.
+ *
+ ****************************************************************************/
+static
+void vertical_band_3_5_scale_mmx
+(
+    unsigned char *dest,
+    unsigned int dest_pitch,
+    unsigned int dest_width
+)
+{
+    __asm
+    {
+        mov         esi,    dest                    // Get the source and destination pointer
+        mov         ecx,    dest_pitch               // Get the pitch size
+
+        lea         edi,    [esi+ecx*2]             // tow lines below
+        add         edi,    ecx                     // three lines below
+
+        pxor        mm7,    mm7                     // clear out mm7
+        mov         edx,    dest_width               // Loop counter
+
+        vs_3_5_loop:
+
+        movq        mm0,    QWORD ptr [esi]         // src[0];
+        movq        mm1,    QWORD ptr [esi+ecx]     // src[1];
+
+        movq        mm2,    mm0                     // Make a copy
+        punpcklbw   mm0,    mm7                     // unpack low to word
+
+        movq        mm5,    two_fifths               // mm5 = 2/5
+        punpckhbw   mm2,    mm7                     // unpack high to word
+
+        pmullw      mm0,    mm5                     // a * 2/5
+
+        movq        mm3,    mm1                     // make a copy
+        punpcklbw   mm1,    mm7                     // unpack low to word
+
+        pmullw      mm2,    mm5                     // a * 2/5
+        movq        mm6,    three_fifths             // mm6 = 3/5
+
+        movq        mm4,    mm1                     // copy of low b
+        pmullw      mm4,    mm6                     // b * 3/5
+
+        punpckhbw   mm3,    mm7                     // unpack high to word
+        movq        mm5,    mm3                     // copy of high b
+
+        pmullw      mm5,    mm6                     // b * 3/5
+        paddw       mm0,    mm4                     // a * 2/5 + b * 3/5
+
+        paddw       mm2,    mm5                     // a * 2/5 + b * 3/5
+        paddw       mm0,    round_values             // + 128
+
+        paddw       mm2,    round_values             // + 128
+        psrlw       mm0,    8
+
+        psrlw       mm2,    8
+        packuswb    mm0,    mm2                     // des [1]
+
+        movq        QWORD ptr [esi+ecx], mm0        // write des[1]
+        movq        mm0,    [esi+ecx*2]             // mm0 = src[2]
+
+        // mm1, mm3 --- Src[1]
+        // mm0 --- Src[2]
+        // mm7 for unpacking
+
+        movq        mm4,    mm1                     // b low
+        pmullw      mm1,    four_fifths              // b * 4/5 low
+
+        movq        mm5,    mm3                     // b high
+        pmullw      mm3,    four_fifths              // b * 4/5 high
+
+        movq        mm2,    mm0                     // c
+        pmullw      mm4,    one_fifth                // b * 1/5
+
+        punpcklbw   mm0,    mm7                     // c low
+        pmullw      mm5,    one_fifth                // b * 1/5
+
+        movq        mm6,    mm0                     // make copy of c low
+        punpckhbw   mm2,    mm7                     // c high
+
+        pmullw      mm6,    one_fifth                // c * 1/5 low
+        movq        mm7,    mm2                     // make copy of c high
+
+        pmullw      mm7,    one_fifth                // c * 1/5 high
+        paddw       mm1,    mm6                     // b * 4/5 + c * 1/5 low
+
+        paddw       mm3,    mm7                     // b * 4/5 + c * 1/5 high
+        movq        mm6,    mm0                     // make copy of c low
+
+        pmullw      mm6,    four_fifths              // c * 4/5 low
+        movq        mm7,    mm2                     // make copy of c high
+
+        pmullw      mm7,    four_fifths              // c * 4/5 high
+
+        paddw       mm4,    mm6                     // b * 1/5 + c * 4/5 low
+        paddw       mm5,    mm7                     // b * 1/5 + c * 4/5 high
+
+        paddw       mm1,    round_values             // + 128
+        paddw       mm3,    round_values             // + 128
+
+        psrlw       mm1,    8
+        psrlw       mm3,    8
+
+        packuswb    mm1,    mm3                     // des[2]
+        movq        QWORD ptr [esi+ecx*2], mm1      // write des[2]
+
+        paddw       mm4,    round_values             // + 128
+        paddw       mm5,    round_values             // + 128
+
+        psrlw       mm4,    8
+        psrlw       mm5,    8
+
+        packuswb    mm4,    mm5                     // des[3]
+        movq        QWORD ptr [edi], mm4            // write des[3]
+
+        //  mm0, mm2 --- Src[3]
+
+        pxor        mm7,    mm7                     // clear mm7 for unpacking
+        movq        mm1,    [edi+ecx*2]             // mm1 = Src[0] of the next group
+
+        movq        mm5,    three_fifths             // mm5 = 3/5
+        pmullw      mm0,    mm5                     // d * 3/5
+
+        movq        mm6,    two_fifths                // mm6 = 2/5
+        movq        mm3,    mm1                     // make a copy
+
+        pmullw      mm2,    mm5                     // d * 3/5
+        punpcklbw   mm1,    mm7                     // unpack low
+
+        pmullw      mm1,    mm6                     // an * 2/5
+        punpckhbw   mm3,    mm7                     // unpack high
+
+        paddw       mm0,    mm1                     // d * 3/5 + an * 2/5
+        pmullw      mm3,    mm6                     // an * 2/5
+
+        paddw       mm2,    mm3                     // d * 3/5 + an * 2/5
+        paddw       mm0,    round_values             // + 128
+
+        paddw       mm2,    round_values             // + 128
+        psrlw       mm0,    8
+
+        psrlw       mm2,    8
+        packuswb    mm0,    mm2                     // des[4]
+
+        movq        QWORD ptr [edi+ecx], mm0        // write des[4]
+
+        add         edi,    8
+        add         esi,    8
+
+        sub         edx,    8
+        jg          vs_3_5_loop
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : last_vertical_band_3_5_scale_mmx
+ *
+ *  INPUTS        : unsigned char *dest    :
+ *                  unsigned int dest_pitch :
+ *                  unsigned int dest_width :
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : 3 to 5 up-scaling of a 3-pixel high band of pixels.
+ *
+ *  SPECIAL NOTES : The routine uses the first line of the band below
+ *                  the current band. The function also has an "C" only
+ *                  version.
+ *
+ ****************************************************************************/
+static
+void last_vertical_band_3_5_scale_mmx
+(
+    unsigned char *dest,
+    unsigned int dest_pitch,
+    unsigned int dest_width
+)
+{
+    __asm
+    {
+        mov         esi,    dest                    // Get the source and destination pointer
+        mov         ecx,    dest_pitch               // Get the pitch size
+
+        lea         edi,    [esi+ecx*2]             // tow lines below
+        add         edi,    ecx                     // three lines below
+
+        pxor        mm7,    mm7                     // clear out mm7
+        mov         edx,    dest_width               // Loop counter
+
+
+        last_vs_3_5_loop:
+
+        movq        mm0,    QWORD ptr [esi]         // src[0];
+        movq        mm1,    QWORD ptr [esi+ecx]     // src[1];
+
+        movq        mm2,    mm0                     // Make a copy
+        punpcklbw   mm0,    mm7                     // unpack low to word
+
+        movq        mm5,    two_fifths               // mm5 = 2/5
+        punpckhbw   mm2,    mm7                     // unpack high to word
+
+        pmullw      mm0,    mm5                     // a * 2/5
+
+        movq        mm3,    mm1                     // make a copy
+        punpcklbw   mm1,    mm7                     // unpack low to word
+
+        pmullw      mm2,    mm5                     // a * 2/5
+        movq        mm6,    three_fifths             // mm6 = 3/5
+
+        movq        mm4,    mm1                     // copy of low b
+        pmullw      mm4,    mm6                     // b * 3/5
+
+        punpckhbw   mm3,    mm7                     // unpack high to word
+        movq        mm5,    mm3                     // copy of high b
+
+        pmullw      mm5,    mm6                     // b * 3/5
+        paddw       mm0,    mm4                     // a * 2/5 + b * 3/5
+
+        paddw       mm2,    mm5                     // a * 2/5 + b * 3/5
+        paddw       mm0,    round_values             // + 128
+
+        paddw       mm2,    round_values             // + 128
+        psrlw       mm0,    8
+
+        psrlw       mm2,    8
+        packuswb    mm0,    mm2                     // des [1]
+
+        movq        QWORD ptr [esi+ecx], mm0        // write des[1]
+        movq        mm0,    [esi+ecx*2]             // mm0 = src[2]
+
+
+
+        // mm1, mm3 --- Src[1]
+        // mm0 --- Src[2]
+        // mm7 for unpacking
+
+        movq        mm4,    mm1                     // b low
+        pmullw      mm1,    four_fifths              // b * 4/5 low
+
+        movq        QWORD ptr [edi+ecx], mm0        // write des[4]
+
+        movq        mm5,    mm3                     // b high
+        pmullw      mm3,    four_fifths              // b * 4/5 high
+
+        movq        mm2,    mm0                     // c
+        pmullw      mm4,    one_fifth                // b * 1/5
+
+        punpcklbw   mm0,    mm7                     // c low
+        pmullw      mm5,    one_fifth                // b * 1/5
+
+        movq        mm6,    mm0                     // make copy of c low
+        punpckhbw   mm2,    mm7                     // c high
+
+        pmullw      mm6,    one_fifth                // c * 1/5 low
+        movq        mm7,    mm2                     // make copy of c high
+
+        pmullw      mm7,    one_fifth                // c * 1/5 high
+        paddw       mm1,    mm6                     // b * 4/5 + c * 1/5 low
+
+        paddw       mm3,    mm7                     // b * 4/5 + c * 1/5 high
+        movq        mm6,    mm0                     // make copy of c low
+
+        pmullw      mm6,    four_fifths              // c * 4/5 low
+        movq        mm7,    mm2                     // make copy of c high
+
+        pmullw      mm7,    four_fifths              // c * 4/5 high
+
+        paddw       mm4,    mm6                     // b * 1/5 + c * 4/5 low
+        paddw       mm5,    mm7                     // b * 1/5 + c * 4/5 high
+
+        paddw       mm1,    round_values             // + 128
+        paddw       mm3,    round_values             // + 128
+
+        psrlw       mm1,    8
+        psrlw       mm3,    8
+
+        packuswb    mm1,    mm3                     // des[2]
+        movq        QWORD ptr [esi+ecx*2], mm1      // write des[2]
+
+        paddw       mm4,    round_values             // + 128
+        paddw       mm5,    round_values             // + 128
+
+        psrlw       mm4,    8
+        psrlw       mm5,    8
+
+        packuswb    mm4,    mm5                     // des[3]
+        movq        QWORD ptr [edi], mm4            // write des[3]
+
+        //  mm0, mm2 --- Src[3]
+
+        add         edi,    8
+        add         esi,    8
+
+        sub         edx,    8
+        jg          last_vs_3_5_loop
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : vertical_band_1_2_scale_mmx
+ *
+ *  INPUTS        : unsigned char *dest    :
+ *                  unsigned int dest_pitch :
+ *                  unsigned int dest_width :
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : 1 to 2 up-scaling of a band of pixels.
+ *
+ *  SPECIAL NOTES : The routine uses the first line of the band below
+ *                  the current band. The function also has an "C" only
+ *                  version.
+ *
+ ****************************************************************************/
+static
+void vertical_band_1_2_scale_mmx
+(
+    unsigned char *dest,
+    unsigned int dest_pitch,
+    unsigned int dest_width
+)
+{
+    __asm
+    {
+
+        mov         esi,    dest                    // Get the source and destination pointer
+        mov         ecx,    dest_pitch               // Get the pitch size
+
+        pxor        mm7,    mm7                     // clear out mm7
+        mov         edx,    dest_width               // Loop counter
+
+        vs_1_2_loop:
+
+        movq        mm0,    [esi]                   // get Src[0]
+        movq        mm1,    [esi + ecx * 2]         // get Src[1]
+
+        movq        mm2,    mm0                     // make copy before unpack
+        movq        mm3,    mm1                     // make copy before unpack
+
+        punpcklbw   mm0,    mm7                     // low Src[0]
+        movq        mm6,    four_ones                // mm6= 1, 1, 1, 1
+
+        punpcklbw   mm1,    mm7                     // low Src[1]
+        paddw       mm0,    mm1                     // low (a + b)
+
+        punpckhbw   mm2,    mm7                     // high Src[0]
+        paddw       mm0,    mm6                     // low (a + b + 1)
+
+        punpckhbw   mm3,    mm7
+        paddw       mm2,    mm3                     // high (a + b )
+
+        psraw       mm0,    1                       // low (a + b +1 )/2
+        paddw       mm2,    mm6                     // high (a + b + 1)
+
+        psraw       mm2,    1                       // high (a + b + 1)/2
+        packuswb    mm0,    mm2                     // pack results
+
+        movq        [esi+ecx], mm0                  // write out eight bytes
+        add         esi,    8
+
+        sub         edx,    8
+        jg          vs_1_2_loop
+    }
+
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : last_vertical_band_1_2_scale_mmx
+ *
+ *  INPUTS        : unsigned char *dest    :
+ *                  unsigned int dest_pitch :
+ *                  unsigned int dest_width :
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : 1 to 2 up-scaling of band of pixels.
+ *
+ *  SPECIAL NOTES : The routine uses the first line of the band below
+ *                  the current band. The function also has an "C" only
+ *                  version.
+ *
+ ****************************************************************************/
+static
+void last_vertical_band_1_2_scale_mmx
+(
+    unsigned char *dest,
+    unsigned int dest_pitch,
+    unsigned int dest_width
+)
+{
+    __asm
+    {
+        mov         esi,    dest                    // Get the source and destination pointer
+        mov         ecx,    dest_pitch               // Get the pitch size
+
+        mov         edx,    dest_width               // Loop counter
+
+        last_vs_1_2_loop:
+
+        movq        mm0,    [esi]                   // get Src[0]
+        movq        [esi+ecx], mm0                  // write out eight bytes
+
+        add         esi,    8
+        sub         edx,    8
+
+        jg         last_vs_1_2_loop
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : horizontal_line_1_2_scale
+ *
+ *  INPUTS        : const unsigned char *source :
+ *                  unsigned int source_width    :
+ *                  unsigned char *dest         :
+ *                  unsigned int dest_width      :
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : 1 to 2 up-scaling of a horizontal line of pixels.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+static
+void horizontal_line_1_2_scale_mmx
+(
+    const unsigned char *source,
+    unsigned int source_width,
+    unsigned char *dest,
+    unsigned int dest_width
+)
+{
+    (void) dest_width;
+
+    __asm
+    {
+        mov         esi,    source
+        mov         edi,    dest
+
+        pxor        mm7,    mm7
+        movq        mm6,    four_ones
+
+        mov         ecx,    source_width
+
+        hs_1_2_loop:
+
+        movq        mm0,    [esi]
+        movq        mm1,    [esi+1]
+
+        movq        mm2,    mm0
+        movq        mm3,    mm1
+
+        movq        mm4,    mm0
+        punpcklbw   mm0,    mm7
+
+        punpcklbw   mm1,    mm7
+        paddw       mm0,    mm1
+
+        paddw       mm0,    mm6
+        punpckhbw   mm2,    mm7
+
+        punpckhbw   mm3,    mm7
+        paddw       mm2,    mm3
+
+        paddw       mm2,    mm6
+        psraw       mm0,    1
+
+        psraw       mm2,    1
+        packuswb    mm0,    mm2
+
+        movq        mm2,    mm4
+        punpcklbw   mm2,    mm0
+
+        movq        [edi],  mm2
+        punpckhbw   mm4,    mm0
+
+        movq        [edi+8], mm4
+        add         esi,    8
+
+        add         edi,    16
+        sub         ecx,    8
+
+        cmp         ecx,    8
+        jg          hs_1_2_loop
+
+// last eight pixel
+
+        movq        mm0,    [esi]
+        movq        mm1,    mm0
+
+        movq        mm2,    mm0
+        movq        mm3,    mm1
+
+        psrlq       mm1,    8
+        psrlq       mm3,    56
+
+        psllq       mm3,    56
+        por         mm1,    mm3
+
+        movq        mm3,    mm1
+        movq        mm4,    mm0
+
+        punpcklbw   mm0,    mm7
+        punpcklbw   mm1,    mm7
+
+        paddw       mm0,    mm1
+        paddw       mm0,    mm6
+
+        punpckhbw   mm2,    mm7
+        punpckhbw   mm3,    mm7
+
+        paddw       mm2,    mm3
+        paddw       mm2,    mm6
+
+        psraw       mm0,    1
+        psraw       mm2,    1
+
+        packuswb    mm0,    mm2
+        movq        mm2,    mm4
+
+        punpcklbw   mm2,    mm0
+        movq        [edi],  mm2
+
+        punpckhbw   mm4,    mm0
+        movq        [edi+8], mm4
+    }
+}
+
+
+
+
+
+__declspec(align(16)) const static unsigned short const54_2[] = {  0,  64, 128, 192 };
+__declspec(align(16)) const static unsigned short const54_1[] = {256, 192, 128,  64 };
+
+
+/****************************************************************************
+ *
+ *  ROUTINE       : horizontal_line_5_4_scale_mmx
+ *
+ *  INPUTS        : const unsigned char *source : Pointer to source data.
+ *                  unsigned int source_width    : Stride of source.
+ *                  unsigned char *dest         : Pointer to destination data.
+ *                  unsigned int dest_width      : Stride of destination (NOT USED).
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Copies horizontal line of pixels from source to
+ *                  destination scaling up by 4 to 5.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+static
+void horizontal_line_5_4_scale_mmx
+(
+    const unsigned char *source,
+    unsigned int source_width,
+    unsigned char *dest,
+    unsigned int dest_width
+)
+{
+    /*
+    unsigned i;
+    unsigned int a, b, c, d, e;
+    unsigned char *des = dest;
+    const unsigned char *src = source;
+
+    (void) dest_width;
+
+    for ( i=0; i<source_width; i+=5 )
+    {
+        a = src[0];
+        b = src[1];
+        c = src[2];
+        d = src[3];
+        e = src[4];
+
+        des[0] = a;
+        des[1] = ((b*192 + c* 64 + 128)>>8);
+        des[2] = ((c*128 + d*128 + 128)>>8);
+        des[3] = ((d* 64 + e*192 + 128)>>8);
+
+        src += 5;
+        des += 4;
+    }
+    */
+    (void) dest_width;
+
+    __asm
+    {
+
+        mov         esi,        source              ;
+        mov         edi,        dest                ;
+
+        mov         ecx,        source_width         ;
+        movq        mm5,        const54_1           ;
+
+        pxor        mm7,        mm7                 ;
+        movq        mm6,        const54_2           ;
+
+        movq        mm4,        round_values         ;
+        lea         edx,        [esi+ecx]           ;
+        horizontal_line_5_4_loop:
+
+        movq        mm0,        QWORD PTR  [esi]    ;
+        00 01 02 03 04 05 06 07
+        movq        mm1,        mm0                 ;
+        00 01 02 03 04 05 06 07
+
+        psrlq       mm0,        8                   ;
+        01 02 03 04 05 06 07 xx
+        punpcklbw   mm1,        mm7                 ;
+        xx 00 xx 01 xx 02 xx 03
+
+        punpcklbw   mm0,        mm7                 ;
+        xx 01 xx 02 xx 03 xx 04
+        pmullw      mm1,        mm5
+
+        pmullw      mm0,        mm6
+        add         esi,        5
+
+        add         edi,        4
+        paddw       mm1,        mm0
+
+        paddw       mm1,        mm4
+        psrlw       mm1,        8
+
+        cmp         esi,        edx
+        packuswb    mm1,        mm7
+
+        movd        DWORD PTR [edi-4], mm1
+
+        jl          horizontal_line_5_4_loop
+
+    }
+
+}
+__declspec(align(16)) const static unsigned short one_fourths[]   = {  64,  64,  64, 64  };
+__declspec(align(16)) const static unsigned short two_fourths[]   = { 128, 128, 128, 128 };
+__declspec(align(16)) const static unsigned short three_fourths[] = { 192, 192, 192, 192 };
+
+static
+void vertical_band_5_4_scale_mmx(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width)
+{
+
+    __asm
+    {
+        push        ebx
+
+        mov         esi,    source                    // Get the source and destination pointer
+        mov         ecx,    src_pitch               // Get the pitch size
+
+        mov         edi,    dest                    // tow lines below
+        pxor        mm7,    mm7                     // clear out mm7
+
+        mov         edx,    dest_pitch               // Loop counter
+        mov         ebx,    dest_width
+
+        vs_5_4_loop:
+
+        movd        mm0,    DWORD ptr [esi]         // src[0];
+        movd        mm1,    DWORD ptr [esi+ecx]     // src[1];
+
+        movd        mm2,    DWORD ptr [esi+ecx*2]
+        lea         eax,    [esi+ecx*2]             //
+
+        punpcklbw   mm1,    mm7
+        punpcklbw   mm2,    mm7
+
+        movq        mm3,    mm2
+        pmullw      mm1,    three_fourths
+
+        pmullw      mm2,    one_fourths
+        movd        mm4,    [eax+ecx]
+
+        pmullw      mm3,    two_fourths
+        punpcklbw   mm4,    mm7
+
+        movq        mm5,    mm4
+        pmullw      mm4,    two_fourths
+
+        paddw       mm1,    mm2
+        movd        mm6,    [eax+ecx*2]
+
+        pmullw      mm5,    one_fourths
+        paddw       mm1,    round_values;
+
+        paddw       mm3,    mm4
+        psrlw       mm1,    8
+
+        punpcklbw   mm6,    mm7
+        paddw       mm3,    round_values
+
+        pmullw      mm6,    three_fourths
+        psrlw       mm3,    8
+
+        packuswb    mm1,    mm7
+        packuswb    mm3,    mm7
+
+        movd        DWORD PTR [edi], mm0
+        movd        DWORD PTR [edi+edx], mm1
+
+
+        paddw       mm5,    mm6
+        movd        DWORD PTR [edi+edx*2], mm3
+
+        lea         eax,    [edi+edx*2]
+        paddw       mm5,    round_values
+
+        psrlw       mm5,    8
+        add         edi,    4
+
+        packuswb    mm5,    mm7
+        movd        DWORD PTR [eax+edx], mm5
+
+        add         esi,    4
+        sub         ebx,    4
+
+        jg         vs_5_4_loop
+
+        pop         ebx
+    }
+}
+
+
+__declspec(align(16)) const static unsigned short const53_1[] = {  0,  85, 171, 0 };
+__declspec(align(16)) const static unsigned short const53_2[] = {256, 171,  85, 0 };
+
+
+static
+void horizontal_line_5_3_scale_mmx
+(
+    const unsigned char *source,
+    unsigned int source_width,
+    unsigned char *dest,
+    unsigned int dest_width
+)
+{
+
+    (void) dest_width;
+    __asm
+    {
+
+        mov         esi,        source              ;
+        mov         edi,        dest                ;
+
+        mov         ecx,        source_width         ;
+        movq        mm5,        const53_1           ;
+
+        pxor        mm7,        mm7                 ;
+        movq        mm6,        const53_2           ;
+
+        movq        mm4,        round_values         ;
+        lea         edx,        [esi+ecx-5]         ;
+        horizontal_line_5_3_loop:
+
+        movq        mm0,        QWORD PTR  [esi]    ;
+        00 01 02 03 04 05 06 07
+        movq        mm1,        mm0                 ;
+        00 01 02 03 04 05 06 07
+
+        psllw       mm0,        8                   ;
+        xx 00 xx 02 xx 04 xx 06
+        psrlw       mm1,        8                   ;
+        01 xx 03 xx 05 xx 07 xx
+
+        psrlw       mm0,        8                   ;
+        00 xx 02 xx 04 xx 06 xx
+        psllq       mm1,        16                  ;
+        xx xx 01 xx 03 xx 05 xx
+
+        pmullw      mm0,        mm6
+
+        pmullw      mm1,        mm5
+        add         esi,        5
+
+        add         edi,        3
+        paddw       mm1,        mm0
+
+        paddw       mm1,        mm4
+        psrlw       mm1,        8
+
+        cmp         esi,        edx
+        packuswb    mm1,        mm7
+
+        movd        DWORD PTR [edi-3], mm1
+        jl          horizontal_line_5_3_loop
+
+//exit condition
+        movq        mm0,        QWORD PTR  [esi]    ;
+        00 01 02 03 04 05 06 07
+        movq        mm1,        mm0                 ;
+        00 01 02 03 04 05 06 07
+
+        psllw       mm0,        8                   ;
+        xx 00 xx 02 xx 04 xx 06
+        psrlw       mm1,        8                   ;
+        01 xx 03 xx 05 xx 07 xx
+
+        psrlw       mm0,        8                   ;
+        00 xx 02 xx 04 xx 06 xx
+        psllq       mm1,        16                  ;
+        xx xx 01 xx 03 xx 05 xx
+
+        pmullw      mm0,        mm6
+
+        pmullw      mm1,        mm5
+        paddw       mm1,        mm0
+
+        paddw       mm1,        mm4
+        psrlw       mm1,        8
+
+        packuswb    mm1,        mm7
+        movd        eax,        mm1
+
+        mov         edx,        eax
+        shr         edx,        16
+
+        mov         WORD PTR[edi],   ax
+        mov         BYTE PTR[edi+2], dl
+
+    }
+
+}
+
+__declspec(align(16)) const static unsigned short one_thirds[] = {  85,  85,  85,  85 };
+__declspec(align(16)) const static unsigned short two_thirds[] = { 171, 171, 171, 171 };
+
+static
+void vertical_band_5_3_scale_mmx(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width)
+{
+
+    __asm
+    {
+        push        ebx
+
+        mov         esi,    source                    // Get the source and destination pointer
+        mov         ecx,    src_pitch               // Get the pitch size
+
+        mov         edi,    dest                    // tow lines below
+        pxor        mm7,    mm7                     // clear out mm7
+
+        mov         edx,    dest_pitch               // Loop counter
+        movq        mm5,    one_thirds
+
+        movq        mm6,    two_thirds
+        mov         ebx,    dest_width;
+
+        vs_5_3_loop:
+
+        movd        mm0,    DWORD ptr [esi]         // src[0];
+        movd        mm1,    DWORD ptr [esi+ecx]     // src[1];
+
+        movd        mm2,    DWORD ptr [esi+ecx*2]
+        lea         eax,    [esi+ecx*2]             //
+
+        punpcklbw   mm1,    mm7
+        punpcklbw   mm2,    mm7
+
+        pmullw      mm1,    mm5
+        pmullw      mm2,    mm6
+
+        movd        mm3,    DWORD ptr [eax+ecx]
+        movd        mm4,    DWORD ptr [eax+ecx*2]
+
+        punpcklbw   mm3,    mm7
+        punpcklbw   mm4,    mm7
+
+        pmullw      mm3,    mm6
+        pmullw      mm4,    mm5
+
+
+        movd        DWORD PTR [edi], mm0
+        paddw       mm1,    mm2
+
+        paddw       mm1,    round_values
+        psrlw       mm1,    8
+
+        packuswb    mm1,    mm7
+        paddw       mm3,    mm4
+
+        paddw       mm3,    round_values
+        movd        DWORD PTR [edi+edx], mm1
+
+        psrlw       mm3,    8
+        packuswb    mm3,    mm7
+
+        movd        DWORD PTR [edi+edx*2], mm3
+
+
+        add         edi,    4
+        add         esi,    4
+
+        sub         ebx,    4
+        jg          vs_5_3_loop
+
+        pop         ebx
+    }
+}
+
+
+
+
+/****************************************************************************
+ *
+ *  ROUTINE       : horizontal_line_2_1_scale
+ *
+ *  INPUTS        : const unsigned char *source :
+ *                  unsigned int source_width    :
+ *                  unsigned char *dest         :
+ *                  unsigned int dest_width      :
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : 1 to 2 up-scaling of a horizontal line of pixels.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+static
+void horizontal_line_2_1_scale_mmx
+(
+    const unsigned char *source,
+    unsigned int source_width,
+    unsigned char *dest,
+    unsigned int dest_width
+)
+{
+    (void) dest_width;
+    (void) source_width;
+    __asm
+    {
+        mov         esi,    source
+        mov         edi,    dest
+
+        pxor        mm7,    mm7
+        mov         ecx,    dest_width
+
+        xor         edx,    edx
+        hs_2_1_loop:
+
+        movq        mm0,    [esi+edx*2]
+        psllw       mm0,    8
+
+        psrlw       mm0,    8
+        packuswb    mm0,    mm7
+
+        movd        DWORD Ptr [edi+edx], mm0;
+        add         edx,    4
+
+        cmp         edx,    ecx
+        jl          hs_2_1_loop
+
+    }
+}
+
+
+
+static
+void vertical_band_2_1_scale_mmx(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width)
+{
+    (void) dest_pitch;
+    (void) src_pitch;
+    vpx_memcpy(dest, source, dest_width);
+}
+
+
+__declspec(align(16)) const static unsigned short three_sixteenths[] = {  48,  48,  48,  48 };
+__declspec(align(16)) const static unsigned short ten_sixteenths[]   = { 160, 160, 160, 160 };
+
+static
+void vertical_band_2_1_scale_i_mmx(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width)
+{
+
+    (void) dest_pitch;
+    __asm
+    {
+        mov         esi,        source
+        mov         edi,        dest
+
+        mov         eax,        src_pitch
+        mov         edx,        dest_width
+
+        pxor        mm7,        mm7
+        sub         esi,        eax             //back one line
+
+
+        lea         ecx,        [esi+edx];
+        movq        mm6,        round_values;
+
+        movq        mm5,        three_sixteenths;
+        movq        mm4,        ten_sixteenths;
+
+        vs_2_1_i_loop:
+        movd        mm0,        [esi]           //
+        movd        mm1,        [esi+eax]       //
+
+        movd        mm2,        [esi+eax*2]     //
+        punpcklbw   mm0,        mm7
+
+        pmullw      mm0,        mm5
+        punpcklbw   mm1,        mm7
+
+        pmullw      mm1,        mm4
+        punpcklbw   mm2,        mm7
+
+        pmullw      mm2,        mm5
+        paddw       mm0,        round_values
+
+        paddw       mm1,        mm2
+        paddw       mm0,        mm1
+
+        psrlw       mm0,        8
+        packuswb    mm0,        mm7
+
+        movd        DWORD PTR [edi],        mm0
+        add         esi,        4
+
+        add         edi,        4;
+        cmp         esi,        ecx
+        jl          vs_2_1_i_loop
+
+    }
+}
+
+
+
+void
+register_mmxscalers(void)
+{
+    vp8_horizontal_line_1_2_scale        = horizontal_line_1_2_scale_mmx;
+    vp8_vertical_band_1_2_scale          = vertical_band_1_2_scale_mmx;
+    vp8_last_vertical_band_1_2_scale      = last_vertical_band_1_2_scale_mmx;
+    vp8_horizontal_line_3_5_scale        = horizontal_line_3_5_scale_mmx;
+    vp8_vertical_band_3_5_scale          = vertical_band_3_5_scale_mmx;
+    vp8_last_vertical_band_3_5_scale      = last_vertical_band_3_5_scale_mmx;
+    vp8_horizontal_line_4_5_scale        = horizontal_line_4_5_scale_mmx;
+    vp8_vertical_band_4_5_scale          = vertical_band_4_5_scale_mmx;
+    vp8_last_vertical_band_4_5_scale      = last_vertical_band_4_5_scale_mmx;
+
+    vp8_horizontal_line_3_4_scale        = vp8cx_horizontal_line_3_4_scale_c;
+    vp8_vertical_band_3_4_scale          = vp8cx_vertical_band_3_4_scale_c;
+    vp8_last_vertical_band_3_4_scale      = vp8cx_last_vertical_band_3_4_scale_c;
+    vp8_horizontal_line_2_3_scale        = vp8cx_horizontal_line_2_3_scale_c;
+    vp8_vertical_band_2_3_scale          = vp8cx_vertical_band_2_3_scale_c;
+    vp8_last_vertical_band_2_3_scale      = vp8cx_last_vertical_band_2_3_scale_c;
+
+
+
+    vp8_vertical_band_5_4_scale           = vertical_band_5_4_scale_mmx;
+    vp8_vertical_band_5_3_scale           = vertical_band_5_3_scale_mmx;
+    vp8_vertical_band_2_1_scale           = vertical_band_2_1_scale_mmx;
+    vp8_vertical_band_2_1_scale_i         = vertical_band_2_1_scale_i_mmx;
+    vp8_horizontal_line_2_1_scale         = horizontal_line_2_1_scale_mmx;
+    vp8_horizontal_line_5_3_scale         = horizontal_line_5_3_scale_mmx;
+    vp8_horizontal_line_5_4_scale         = horizontal_line_5_4_scale_mmx;
+
+
+
+
+}
diff --git a/vpx_scale/win32/scalesystemdependent.c b/vpx_scale/win32/scalesystemdependent.c
new file mode 100644 (file)
index 0000000..19e61c3
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/****************************************************************************
+*
+*   Module Title :     system_dependent.c
+*
+*   Description  :     Miscellaneous system dependent functions
+*
+****************************************************************************/
+
+/****************************************************************************
+*  Header Files
+****************************************************************************/
+#include "vpx_scale/vpxscale.h"
+#include "cpuidlib.h"
+
+/****************************************************************************
+*  Imports
+*****************************************************************************/
+extern void register_generic_scalers(void);
+extern void register_mmxscalers(void);
+
+/****************************************************************************
+ *
+ *  ROUTINE       : post_proc_machine_specific_config
+ *
+ *  INPUTS        : UINT32 Version : Codec version number.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Checks for machine specifc features such as MMX support
+ *                  sets appropriate flags and function pointers.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+void
+vp8_scale_machine_specific_config(void)
+{
+    // If MMX supported then set to use MMX versions of functions else
+    // use original 'C' versions.
+    int mmx_enabled;
+    int xmm_enabled;
+    int wmt_enabled;
+
+    vpx_get_processor_flags(&mmx_enabled, &xmm_enabled, &wmt_enabled);
+
+    if (mmx_enabled || xmm_enabled || wmt_enabled)
+    {
+        register_mmxscalers();
+    }
+    else
+    {
+        vp8_horizontal_line_1_2_scale        = vp8cx_horizontal_line_1_2_scale_c;
+        vp8_vertical_band_1_2_scale          = vp8cx_vertical_band_1_2_scale_c;
+        vp8_last_vertical_band_1_2_scale      = vp8cx_last_vertical_band_1_2_scale_c;
+        vp8_horizontal_line_3_5_scale        = vp8cx_horizontal_line_3_5_scale_c;
+        vp8_vertical_band_3_5_scale          = vp8cx_vertical_band_3_5_scale_c;
+        vp8_last_vertical_band_3_5_scale      = vp8cx_last_vertical_band_3_5_scale_c;
+        vp8_horizontal_line_3_4_scale        = vp8cx_horizontal_line_3_4_scale_c;
+        vp8_vertical_band_3_4_scale          = vp8cx_vertical_band_3_4_scale_c;
+        vp8_last_vertical_band_3_4_scale      = vp8cx_last_vertical_band_3_4_scale_c;
+        vp8_horizontal_line_2_3_scale        = vp8cx_horizontal_line_2_3_scale_c;
+        vp8_vertical_band_2_3_scale          = vp8cx_vertical_band_2_3_scale_c;
+        vp8_last_vertical_band_2_3_scale      = vp8cx_last_vertical_band_2_3_scale_c;
+        vp8_horizontal_line_4_5_scale        = vp8cx_horizontal_line_4_5_scale_c;
+        vp8_vertical_band_4_5_scale          = vp8cx_vertical_band_4_5_scale_c;
+        vp8_last_vertical_band_4_5_scale      = vp8cx_last_vertical_band_4_5_scale_c;
+
+
+        vp8_vertical_band_5_4_scale           = vp8cx_vertical_band_5_4_scale_c;
+        vp8_vertical_band_5_3_scale           = vp8cx_vertical_band_5_3_scale_c;
+        vp8_vertical_band_2_1_scale           = vp8cx_vertical_band_2_1_scale_c;
+        vp8_vertical_band_2_1_scale_i         = vp8cx_vertical_band_2_1_scale_i_c;
+        vp8_horizontal_line_2_1_scale         = vp8cx_horizontal_line_2_1_scale_c;
+        vp8_horizontal_line_5_3_scale         = vp8cx_horizontal_line_5_3_scale_c;
+        vp8_horizontal_line_5_4_scale         = vp8cx_horizontal_line_5_4_scale_c;
+
+    }
+}
diff --git a/vpx_scale/yv12config.h b/vpx_scale/yv12config.h
new file mode 100644 (file)
index 0000000..800f700
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef YV12_CONFIG_H
+#define YV12_CONFIG_H
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define VP7BORDERINPIXELS       48
+#define VP8BORDERINPIXELS       32
+
+    /*************************************
+     For INT_YUV:
+
+     Y = (R+G*2+B)/4;
+     U = (R-B)/2;
+     V =  (G*2 - R - B)/4;
+    And
+     R = Y+U-V;
+     G = Y+V;
+     B = Y-U-V;
+    ************************************/
+    typedef enum
+    {
+        REG_YUV = 0,    /* Regular yuv */
+        INT_YUV = 1     /* The type of yuv that can be tranfer to and from RGB through integer transform */
+              }
+              YUV_TYPE;
+
+    typedef struct yv12_buffer_config
+    {
+        int   y_width;
+        int   y_height;
+        int   y_stride;
+/*    int   yinternal_width; */
+
+        int   uv_width;
+        int   uv_height;
+        int   uv_stride;
+/*    int   uvinternal_width; */
+
+        unsigned char *y_buffer;
+        unsigned char *u_buffer;
+        unsigned char *v_buffer;
+
+        unsigned char *buffer_alloc;
+        int border;
+        int frame_size;
+        YUV_TYPE clrtype;
+
+        int corrupted;
+        int flags;
+    } YV12_BUFFER_CONFIG;
+
+    int vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, int width, int height, int border);
+    int vp8_yv12_de_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /*YV12_CONFIG_H*/
diff --git a/vpxdec.c b/vpxdec.c
new file mode 100644 (file)
index 0000000..4482f3d
--- /dev/null
+++ b/vpxdec.c
@@ -0,0 +1,1154 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/* This is a simple program that reads ivf files and decodes them
+ * using the new interface. Decoded frames are output as YV12 raw.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <limits.h>
+
+#define VPX_CODEC_DISABLE_COMPAT 1
+#include "vpx_config.h"
+#include "vpx/vpx_decoder.h"
+#include "vpx_ports/vpx_timer.h"
+#if CONFIG_VP8_DECODER
+#include "vpx/vp8dx.h"
+#endif
+#if CONFIG_MD5
+#include "md5_utils.h"
+#endif
+#include "tools_common.h"
+#include "nestegg/include/nestegg/nestegg.h"
+
+#if CONFIG_OS_SUPPORT
+#if defined(_MSC_VER)
+#include <io.h>
+#define snprintf _snprintf
+#define isatty   _isatty
+#define fileno   _fileno
+#else
+#include <unistd.h>
+#endif
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX 256
+#endif
+
+static const char *exec_name;
+
+#define VP8_FOURCC (0x00385056)
+static const struct
+{
+    char const *name;
+    const vpx_codec_iface_t *iface;
+    unsigned int             fourcc;
+    unsigned int             fourcc_mask;
+} ifaces[] =
+{
+#if CONFIG_VP8_DECODER
+    {"vp8",  &vpx_codec_vp8_dx_algo,   VP8_FOURCC, 0x00FFFFFF},
+#endif
+};
+
+#include "args.h"
+static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1,
+                                  "Codec to use");
+static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0,
+                                  "Output raw YV12 frames");
+static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0,
+                                  "Output raw I420 frames");
+static const arg_def_t flipuvarg = ARG_DEF(NULL, "flipuv", 0,
+                                   "Flip the chroma planes in the output");
+static const arg_def_t noblitarg = ARG_DEF(NULL, "noblit", 0,
+                                   "Don't process the decoded frames");
+static const arg_def_t progressarg = ARG_DEF(NULL, "progress", 0,
+                                     "Show progress after each frame decodes");
+static const arg_def_t limitarg = ARG_DEF(NULL, "limit", 1,
+                                  "Stop decoding after n frames");
+static const arg_def_t postprocarg = ARG_DEF(NULL, "postproc", 0,
+                                     "Postprocess decoded frames");
+static const arg_def_t summaryarg = ARG_DEF(NULL, "summary", 0,
+                                    "Show timing summary");
+static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
+                                    "Output file name pattern (see below)");
+static const arg_def_t threadsarg = ARG_DEF("t", "threads", 1,
+                                    "Max threads to use");
+static const arg_def_t verbosearg = ARG_DEF("v", "verbose", 0,
+                                  "Show version string");
+static const arg_def_t error_concealment = ARG_DEF(NULL, "error-concealment", 0,
+                                       "Enable decoder error-concealment");
+
+
+#if CONFIG_MD5
+static const arg_def_t md5arg = ARG_DEF(NULL, "md5", 0,
+                                        "Compute the MD5 sum of the decoded frame");
+#endif
+static const arg_def_t *all_args[] =
+{
+    &codecarg, &use_yv12, &use_i420, &flipuvarg, &noblitarg,
+    &progressarg, &limitarg, &postprocarg, &summaryarg, &outputfile,
+    &threadsarg, &verbosearg,
+#if CONFIG_MD5
+    &md5arg,
+#endif
+    &error_concealment,
+    NULL
+};
+
+#if CONFIG_VP8_DECODER
+static const arg_def_t addnoise_level = ARG_DEF(NULL, "noise-level", 1,
+                                        "Enable VP8 postproc add noise");
+static const arg_def_t deblock = ARG_DEF(NULL, "deblock", 0,
+                                 "Enable VP8 deblocking");
+static const arg_def_t demacroblock_level = ARG_DEF(NULL, "demacroblock-level", 1,
+        "Enable VP8 demacroblocking, w/ level");
+static const arg_def_t pp_debug_info = ARG_DEF(NULL, "pp-debug-info", 1,
+                                       "Enable VP8 visible debug info");
+static const arg_def_t pp_disp_ref_frame = ARG_DEF(NULL, "pp-dbg-ref-frame", 1,
+                                       "Display only selected reference frame per macro block");
+static const arg_def_t pp_disp_mb_modes = ARG_DEF(NULL, "pp-dbg-mb-modes", 1,
+                                       "Display only selected macro block modes");
+static const arg_def_t pp_disp_b_modes = ARG_DEF(NULL, "pp-dbg-b-modes", 1,
+                                       "Display only selected block modes");
+static const arg_def_t pp_disp_mvs = ARG_DEF(NULL, "pp-dbg-mvs", 1,
+                                       "Draw only selected motion vectors");
+static const arg_def_t mfqe = ARG_DEF(NULL, "mfqe", 0,
+                                       "Enable multiframe quality enhancement");
+
+static const arg_def_t *vp8_pp_args[] =
+{
+    &addnoise_level, &deblock, &demacroblock_level, &pp_debug_info,
+    &pp_disp_ref_frame, &pp_disp_mb_modes, &pp_disp_b_modes, &pp_disp_mvs, &mfqe,
+    NULL
+};
+#endif
+
+static void usage_exit()
+{
+    int i;
+
+    fprintf(stderr, "Usage: %s <options> filename\n\n"
+            "Options:\n", exec_name);
+    arg_show_usage(stderr, all_args);
+#if CONFIG_VP8_DECODER
+    fprintf(stderr, "\nVP8 Postprocessing Options:\n");
+    arg_show_usage(stderr, vp8_pp_args);
+#endif
+    fprintf(stderr,
+            "\nOutput File Patterns:\n\n"
+            "  The -o argument specifies the name of the file(s) to "
+            "write to. If the\n  argument does not include any escape "
+            "characters, the output will be\n  written to a single file. "
+            "Otherwise, the filename will be calculated by\n  expanding "
+            "the following escape characters:\n"
+            "\n\t%%w   - Frame width"
+            "\n\t%%h   - Frame height"
+            "\n\t%%<n> - Frame number, zero padded to <n> places (1..9)"
+            "\n\n  Pattern arguments are only supported in conjunction "
+            "with the --yv12 and\n  --i420 options. If the -o option is "
+            "not specified, the output will be\n  directed to stdout.\n"
+            );
+    fprintf(stderr, "\nIncluded decoders:\n\n");
+
+    for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
+        fprintf(stderr, "    %-6s - %s\n",
+                ifaces[i].name,
+                vpx_codec_iface_name(ifaces[i].iface));
+
+    exit(EXIT_FAILURE);
+}
+
+void die(const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    fprintf(stderr, "\n");
+    usage_exit();
+}
+
+static unsigned int mem_get_le16(const void *vmem)
+{
+    unsigned int  val;
+    const unsigned char *mem = (const unsigned char *)vmem;
+
+    val = mem[1] << 8;
+    val |= mem[0];
+    return val;
+}
+
+static unsigned int mem_get_le32(const void *vmem)
+{
+    unsigned int  val;
+    const unsigned char *mem = (const unsigned char *)vmem;
+
+    val = mem[3] << 24;
+    val |= mem[2] << 16;
+    val |= mem[1] << 8;
+    val |= mem[0];
+    return val;
+}
+
+enum file_kind
+{
+    RAW_FILE,
+    IVF_FILE,
+    WEBM_FILE
+};
+
+struct input_ctx
+{
+    enum file_kind  kind;
+    FILE           *infile;
+    nestegg        *nestegg_ctx;
+    nestegg_packet *pkt;
+    unsigned int    chunk;
+    unsigned int    chunks;
+    unsigned int    video_track;
+};
+
+#define IVF_FRAME_HDR_SZ (sizeof(uint32_t) + sizeof(uint64_t))
+#define RAW_FRAME_HDR_SZ (sizeof(uint32_t))
+static int read_frame(struct input_ctx      *input,
+                      uint8_t               **buf,
+                      size_t                *buf_sz,
+                      size_t                *buf_alloc_sz)
+{
+    char            raw_hdr[IVF_FRAME_HDR_SZ];
+    size_t          new_buf_sz;
+    FILE           *infile = input->infile;
+    enum file_kind  kind = input->kind;
+    if(kind == WEBM_FILE)
+    {
+        if(input->chunk >= input->chunks)
+        {
+            unsigned int track;
+
+            do
+            {
+                /* End of this packet, get another. */
+                if(input->pkt)
+                    nestegg_free_packet(input->pkt);
+
+                if(nestegg_read_packet(input->nestegg_ctx, &input->pkt) <= 0
+                   || nestegg_packet_track(input->pkt, &track))
+                    return 1;
+
+            } while(track != input->video_track);
+
+            if(nestegg_packet_count(input->pkt, &input->chunks))
+                return 1;
+            input->chunk = 0;
+        }
+
+        if(nestegg_packet_data(input->pkt, input->chunk, buf, buf_sz))
+            return 1;
+        input->chunk++;
+
+        return 0;
+    }
+    /* For both the raw and ivf formats, the frame size is the first 4 bytes
+     * of the frame header. We just need to special case on the header
+     * size.
+     */
+    else if (fread(raw_hdr, kind==IVF_FILE
+                   ? IVF_FRAME_HDR_SZ : RAW_FRAME_HDR_SZ, 1, infile) != 1)
+    {
+        if (!feof(infile))
+            fprintf(stderr, "Failed to read frame size\n");
+
+        new_buf_sz = 0;
+    }
+    else
+    {
+        new_buf_sz = mem_get_le32(raw_hdr);
+
+        if (new_buf_sz > 256 * 1024 * 1024)
+        {
+            fprintf(stderr, "Error: Read invalid frame size (%u)\n",
+                    (unsigned int)new_buf_sz);
+            new_buf_sz = 0;
+        }
+
+        if (kind == RAW_FILE && new_buf_sz > 256 * 1024)
+            fprintf(stderr, "Warning: Read invalid frame size (%u)"
+                    " - not a raw file?\n", (unsigned int)new_buf_sz);
+
+        if (new_buf_sz > *buf_alloc_sz)
+        {
+            uint8_t *new_buf = realloc(*buf, 2 * new_buf_sz);
+
+            if (new_buf)
+            {
+                *buf = new_buf;
+                *buf_alloc_sz = 2 * new_buf_sz;
+            }
+            else
+            {
+                fprintf(stderr, "Failed to allocate compressed data buffer\n");
+                new_buf_sz = 0;
+            }
+        }
+    }
+
+    *buf_sz = new_buf_sz;
+
+    if (!feof(infile))
+    {
+        if (fread(*buf, 1, *buf_sz, infile) != *buf_sz)
+        {
+            fprintf(stderr, "Failed to read full frame\n");
+            return 1;
+        }
+
+        return 0;
+    }
+
+    return 1;
+}
+
+void *out_open(const char *out_fn, int do_md5)
+{
+    void *out = NULL;
+
+    if (do_md5)
+    {
+#if CONFIG_MD5
+        MD5Context *md5_ctx = out = malloc(sizeof(MD5Context));
+        (void)out_fn;
+        MD5Init(md5_ctx);
+#endif
+    }
+    else
+    {
+        FILE *outfile = out = strcmp("-", out_fn) ? fopen(out_fn, "wb")
+                                                  : set_binary_mode(stdout);
+
+        if (!outfile)
+        {
+            fprintf(stderr, "Failed to output file");
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    return out;
+}
+
+void out_put(void *out, const uint8_t *buf, unsigned int len, int do_md5)
+{
+    if (do_md5)
+    {
+#if CONFIG_MD5
+        MD5Update(out, buf, len);
+#endif
+    }
+    else
+    {
+        if(fwrite(buf, 1, len, out));
+    }
+}
+
+void out_close(void *out, const char *out_fn, int do_md5)
+{
+    if (do_md5)
+    {
+#if CONFIG_MD5
+        uint8_t md5[16];
+        int i;
+
+        MD5Final(md5, out);
+        free(out);
+
+        for (i = 0; i < 16; i++)
+            printf("%02x", md5[i]);
+
+        printf("  %s\n", out_fn);
+#endif
+    }
+    else
+    {
+        fclose(out);
+    }
+}
+
+unsigned int file_is_ivf(FILE *infile,
+                         unsigned int *fourcc,
+                         unsigned int *width,
+                         unsigned int *height,
+                         unsigned int *fps_den,
+                         unsigned int *fps_num)
+{
+    char raw_hdr[32];
+    int is_ivf = 0;
+
+    if (fread(raw_hdr, 1, 32, infile) == 32)
+    {
+        if (raw_hdr[0] == 'D' && raw_hdr[1] == 'K'
+            && raw_hdr[2] == 'I' && raw_hdr[3] == 'F')
+        {
+            is_ivf = 1;
+
+            if (mem_get_le16(raw_hdr + 4) != 0)
+                fprintf(stderr, "Error: Unrecognized IVF version! This file may not"
+                        " decode properly.");
+
+            *fourcc = mem_get_le32(raw_hdr + 8);
+            *width = mem_get_le16(raw_hdr + 12);
+            *height = mem_get_le16(raw_hdr + 14);
+            *fps_num = mem_get_le32(raw_hdr + 16);
+            *fps_den = mem_get_le32(raw_hdr + 20);
+
+            /* Some versions of vpxenc used 1/(2*fps) for the timebase, so
+             * we can guess the framerate using only the timebase in this
+             * case. Other files would require reading ahead to guess the
+             * timebase, like we do for webm.
+             */
+            if(*fps_num < 1000)
+            {
+                /* Correct for the factor of 2 applied to the timebase in the
+                 * encoder.
+                 */
+                if(*fps_num&1)*fps_den<<=1;
+                else *fps_num>>=1;
+            }
+            else
+            {
+                /* Don't know FPS for sure, and don't have readahead code
+                 * (yet?), so just default to 30fps.
+                 */
+                *fps_num = 30;
+                *fps_den = 1;
+            }
+        }
+    }
+
+    if (!is_ivf)
+        rewind(infile);
+
+    return is_ivf;
+}
+
+
+unsigned int file_is_raw(FILE *infile,
+                         unsigned int *fourcc,
+                         unsigned int *width,
+                         unsigned int *height,
+                         unsigned int *fps_den,
+                         unsigned int *fps_num)
+{
+    unsigned char buf[32];
+    int is_raw = 0;
+    vpx_codec_stream_info_t si;
+
+    si.sz = sizeof(si);
+
+    if (fread(buf, 1, 32, infile) == 32)
+    {
+        int i;
+
+        if(mem_get_le32(buf) < 256 * 1024 * 1024)
+            for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
+                if(!vpx_codec_peek_stream_info(ifaces[i].iface,
+                                               buf + 4, 32 - 4, &si))
+                {
+                    is_raw = 1;
+                    *fourcc = ifaces[i].fourcc;
+                    *width = si.w;
+                    *height = si.h;
+                    *fps_num = 30;
+                    *fps_den = 1;
+                    break;
+                }
+    }
+
+    rewind(infile);
+    return is_raw;
+}
+
+
+static int
+nestegg_read_cb(void *buffer, size_t length, void *userdata)
+{
+    FILE *f = userdata;
+
+    if(fread(buffer, 1, length, f) < length)
+    {
+        if (ferror(f))
+            return -1;
+        if (feof(f))
+            return 0;
+    }
+    return 1;
+}
+
+
+static int
+nestegg_seek_cb(int64_t offset, int whence, void * userdata)
+{
+    switch(whence) {
+        case NESTEGG_SEEK_SET: whence = SEEK_SET; break;
+        case NESTEGG_SEEK_CUR: whence = SEEK_CUR; break;
+        case NESTEGG_SEEK_END: whence = SEEK_END; break;
+    };
+    return fseek(userdata, offset, whence)? -1 : 0;
+}
+
+
+static int64_t
+nestegg_tell_cb(void * userdata)
+{
+    return ftell(userdata);
+}
+
+
+static void
+nestegg_log_cb(nestegg * context, unsigned int severity, char const * format,
+               ...)
+{
+    va_list ap;
+
+    va_start(ap, format);
+    vfprintf(stderr, format, ap);
+    fprintf(stderr, "\n");
+    va_end(ap);
+}
+
+
+static int
+webm_guess_framerate(struct input_ctx *input,
+                     unsigned int     *fps_den,
+                     unsigned int     *fps_num)
+{
+    unsigned int i;
+    uint64_t     tstamp=0;
+
+    /* Guess the framerate. Read up to 1 second, or 50 video packets,
+     * whichever comes first.
+     */
+    for(i=0; tstamp < 1000000000 && i < 50;)
+    {
+        nestegg_packet * pkt;
+        unsigned int track;
+
+        if(nestegg_read_packet(input->nestegg_ctx, &pkt) <= 0)
+            break;
+
+        nestegg_packet_track(pkt, &track);
+        if(track == input->video_track)
+        {
+            nestegg_packet_tstamp(pkt, &tstamp);
+            i++;
+        }
+
+        nestegg_free_packet(pkt);
+    }
+
+    if(nestegg_track_seek(input->nestegg_ctx, input->video_track, 0))
+        goto fail;
+
+    *fps_num = (i - 1) * 1000000;
+    *fps_den = tstamp / 1000;
+    return 0;
+fail:
+    nestegg_destroy(input->nestegg_ctx);
+    input->nestegg_ctx = NULL;
+    rewind(input->infile);
+    return 1;
+}
+
+
+static int
+file_is_webm(struct input_ctx *input,
+             unsigned int     *fourcc,
+             unsigned int     *width,
+             unsigned int     *height,
+             unsigned int     *fps_den,
+             unsigned int     *fps_num)
+{
+    unsigned int i, n;
+    int          track_type = -1;
+
+    nestegg_io io = {nestegg_read_cb, nestegg_seek_cb, nestegg_tell_cb,
+                     input->infile};
+    nestegg_video_params params;
+
+    if(nestegg_init(&input->nestegg_ctx, io, NULL))
+        goto fail;
+
+    if(nestegg_track_count(input->nestegg_ctx, &n))
+        goto fail;
+
+    for(i=0; i<n; i++)
+    {
+        track_type = nestegg_track_type(input->nestegg_ctx, i);
+
+        if(track_type == NESTEGG_TRACK_VIDEO)
+            break;
+        else if(track_type < 0)
+            goto fail;
+    }
+
+    if(nestegg_track_codec_id(input->nestegg_ctx, i) != NESTEGG_CODEC_VP8)
+    {
+        fprintf(stderr, "Not VP8 video, quitting.\n");
+        exit(1);
+    }
+
+    input->video_track = i;
+
+    if(nestegg_track_video_params(input->nestegg_ctx, i, &params))
+        goto fail;
+
+    *fps_den = 0;
+    *fps_num = 0;
+    *fourcc = VP8_FOURCC;
+    *width = params.width;
+    *height = params.height;
+    return 1;
+fail:
+    input->nestegg_ctx = NULL;
+    rewind(input->infile);
+    return 0;
+}
+
+
+void show_progress(int frame_in, int frame_out, unsigned long dx_time)
+{
+    fprintf(stderr, "%d decoded frames/%d showed frames in %lu us (%.2f fps)\r",
+            frame_in, frame_out, dx_time,
+            (float)frame_out * 1000000.0 / (float)dx_time);
+}
+
+
+void generate_filename(const char *pattern, char *out, size_t q_len,
+                       unsigned int d_w, unsigned int d_h,
+                       unsigned int frame_in)
+{
+    const char *p = pattern;
+    char *q = out;
+
+    do
+    {
+        char *next_pat = strchr(p, '%');
+
+        if(p == next_pat)
+        {
+            size_t pat_len;
+
+            // parse the pattern
+            q[q_len - 1] = '\0';
+            switch(p[1])
+            {
+            case 'w': snprintf(q, q_len - 1, "%d", d_w); break;
+            case 'h': snprintf(q, q_len - 1, "%d", d_h); break;
+            case '1': snprintf(q, q_len - 1, "%d", frame_in); break;
+            case '2': snprintf(q, q_len - 1, "%02d", frame_in); break;
+            case '3': snprintf(q, q_len - 1, "%03d", frame_in); break;
+            case '4': snprintf(q, q_len - 1, "%04d", frame_in); break;
+            case '5': snprintf(q, q_len - 1, "%05d", frame_in); break;
+            case '6': snprintf(q, q_len - 1, "%06d", frame_in); break;
+            case '7': snprintf(q, q_len - 1, "%07d", frame_in); break;
+            case '8': snprintf(q, q_len - 1, "%08d", frame_in); break;
+            case '9': snprintf(q, q_len - 1, "%09d", frame_in); break;
+            default:
+                die("Unrecognized pattern %%%c\n", p[1]);
+            }
+
+            pat_len = strlen(q);
+            if(pat_len >= q_len - 1)
+                die("Output filename too long.\n");
+            q += pat_len;
+            p += 2;
+            q_len -= pat_len;
+        }
+        else
+        {
+            size_t copy_len;
+
+            // copy the next segment
+            if(!next_pat)
+                copy_len = strlen(p);
+            else
+                copy_len = next_pat - p;
+
+            if(copy_len >= q_len - 1)
+                die("Output filename too long.\n");
+
+            memcpy(q, p, copy_len);
+            q[copy_len] = '\0';
+            q += copy_len;
+            p += copy_len;
+            q_len -= copy_len;
+        }
+    } while(*p);
+}
+
+
+int main(int argc, const char **argv_)
+{
+    vpx_codec_ctx_t          decoder;
+    char                  *fn = NULL;
+    int                    i;
+    uint8_t               *buf = NULL;
+    size_t                 buf_sz = 0, buf_alloc_sz = 0;
+    FILE                  *infile;
+    int                    frame_in = 0, frame_out = 0, flipuv = 0, noblit = 0, do_md5 = 0, progress = 0;
+    int                    stop_after = 0, postproc = 0, summary = 0, quiet = 1;
+    int                    ec_enabled = 0;
+    vpx_codec_iface_t       *iface = NULL;
+    unsigned int           fourcc;
+    unsigned long          dx_time = 0;
+    struct arg               arg;
+    char                   **argv, **argi, **argj;
+    const char             *outfile_pattern = 0;
+    char                    outfile[PATH_MAX];
+    int                     single_file;
+    int                     use_y4m = 1;
+    unsigned int            width;
+    unsigned int            height;
+    unsigned int            fps_den;
+    unsigned int            fps_num;
+    void                   *out = NULL;
+    vpx_codec_dec_cfg_t     cfg = {0};
+#if CONFIG_VP8_DECODER
+    vp8_postproc_cfg_t      vp8_pp_cfg = {0};
+    int                     vp8_dbg_color_ref_frame = 0;
+    int                     vp8_dbg_color_mb_modes = 0;
+    int                     vp8_dbg_color_b_modes = 0;
+    int                     vp8_dbg_display_mv = 0;
+#endif
+    struct input_ctx        input = {0};
+    int                     frames_corrupted = 0;
+    int                     dec_flags = 0;
+
+    /* Parse command line */
+    exec_name = argv_[0];
+    argv = argv_dup(argc - 1, argv_ + 1);
+
+    for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step)
+    {
+        memset(&arg, 0, sizeof(arg));
+        arg.argv_step = 1;
+
+        if (arg_match(&arg, &codecarg, argi))
+        {
+            int j, k = -1;
+
+            for (j = 0; j < sizeof(ifaces) / sizeof(ifaces[0]); j++)
+                if (!strcmp(ifaces[j].name, arg.val))
+                    k = j;
+
+            if (k >= 0)
+                iface = ifaces[k].iface;
+            else
+                die("Error: Unrecognized argument (%s) to --codec\n",
+                    arg.val);
+        }
+        else if (arg_match(&arg, &outputfile, argi))
+            outfile_pattern = arg.val;
+        else if (arg_match(&arg, &use_yv12, argi))
+        {
+            use_y4m = 0;
+            flipuv = 1;
+        }
+        else if (arg_match(&arg, &use_i420, argi))
+        {
+            use_y4m = 0;
+            flipuv = 0;
+        }
+        else if (arg_match(&arg, &flipuvarg, argi))
+            flipuv = 1;
+        else if (arg_match(&arg, &noblitarg, argi))
+            noblit = 1;
+        else if (arg_match(&arg, &progressarg, argi))
+            progress = 1;
+        else if (arg_match(&arg, &limitarg, argi))
+            stop_after = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &postprocarg, argi))
+            postproc = 1;
+        else if (arg_match(&arg, &md5arg, argi))
+            do_md5 = 1;
+        else if (arg_match(&arg, &summaryarg, argi))
+            summary = 1;
+        else if (arg_match(&arg, &threadsarg, argi))
+            cfg.threads = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &verbosearg, argi))
+            quiet = 0;
+
+#if CONFIG_VP8_DECODER
+        else if (arg_match(&arg, &addnoise_level, argi))
+        {
+            postproc = 1;
+            vp8_pp_cfg.post_proc_flag |= VP8_ADDNOISE;
+            vp8_pp_cfg.noise_level = arg_parse_uint(&arg);
+        }
+        else if (arg_match(&arg, &demacroblock_level, argi))
+        {
+            postproc = 1;
+            vp8_pp_cfg.post_proc_flag |= VP8_DEMACROBLOCK;
+            vp8_pp_cfg.deblocking_level = arg_parse_uint(&arg);
+        }
+        else if (arg_match(&arg, &deblock, argi))
+        {
+            postproc = 1;
+            vp8_pp_cfg.post_proc_flag |= VP8_DEBLOCK;
+        }
+        else if (arg_match(&arg, &mfqe, argi))
+        {
+            postproc = 1;
+            vp8_pp_cfg.post_proc_flag |= VP8_MFQE;
+        }
+        else if (arg_match(&arg, &pp_debug_info, argi))
+        {
+            unsigned int level = arg_parse_uint(&arg);
+
+            postproc = 1;
+            vp8_pp_cfg.post_proc_flag &= ~0x7;
+
+            if (level)
+                vp8_pp_cfg.post_proc_flag |= level;
+        }
+        else if (arg_match(&arg, &pp_disp_ref_frame, argi))
+        {
+            unsigned int flags = arg_parse_int(&arg);
+            if (flags)
+            {
+                postproc = 1;
+                vp8_dbg_color_ref_frame = flags;
+            }
+        }
+        else if (arg_match(&arg, &pp_disp_mb_modes, argi))
+        {
+            unsigned int flags = arg_parse_int(&arg);
+            if (flags)
+            {
+                postproc = 1;
+                vp8_dbg_color_mb_modes = flags;
+            }
+        }
+        else if (arg_match(&arg, &pp_disp_b_modes, argi))
+        {
+            unsigned int flags = arg_parse_int(&arg);
+            if (flags)
+            {
+                postproc = 1;
+                vp8_dbg_color_b_modes = flags;
+            }
+        }
+        else if (arg_match(&arg, &pp_disp_mvs, argi))
+        {
+            unsigned int flags = arg_parse_int(&arg);
+            if (flags)
+            {
+                postproc = 1;
+                vp8_dbg_display_mv = flags;
+            }
+        }
+        else if (arg_match(&arg, &error_concealment, argi))
+        {
+            ec_enabled = 1;
+        }
+
+#endif
+        else
+            argj++;
+    }
+
+    /* Check for unrecognized options */
+    for (argi = argv; *argi; argi++)
+        if (argi[0][0] == '-' && strlen(argi[0]) > 1)
+            die("Error: Unrecognized option %s\n", *argi);
+
+    /* Handle non-option arguments */
+    fn = argv[0];
+
+    if (!fn)
+        usage_exit();
+
+    /* Open file */
+    infile = strcmp(fn, "-") ? fopen(fn, "rb") : set_binary_mode(stdin);
+
+    if (!infile)
+    {
+        fprintf(stderr, "Failed to open file '%s'",
+                strcmp(fn, "-") ? fn : "stdin");
+        return EXIT_FAILURE;
+    }
+#if CONFIG_OS_SUPPORT
+    /* Make sure we don't dump to the terminal, unless forced to with -o - */
+    if(!outfile_pattern && isatty(fileno(stdout)) && !do_md5 && !noblit)
+    {
+        fprintf(stderr,
+                "Not dumping raw video to your terminal. Use '-o -' to "
+                "override.\n");
+        return EXIT_FAILURE;
+    }
+#endif
+    input.infile = infile;
+    if(file_is_ivf(infile, &fourcc, &width, &height, &fps_den,
+                   &fps_num))
+        input.kind = IVF_FILE;
+    else if(file_is_webm(&input, &fourcc, &width, &height, &fps_den, &fps_num))
+        input.kind = WEBM_FILE;
+    else if(file_is_raw(infile, &fourcc, &width, &height, &fps_den, &fps_num))
+        input.kind = RAW_FILE;
+    else
+    {
+        fprintf(stderr, "Unrecognized input file type.\n");
+        return EXIT_FAILURE;
+    }
+
+    /* If the output file is not set or doesn't have a sequence number in
+     * it, then we only open it once.
+     */
+    outfile_pattern = outfile_pattern ? outfile_pattern : "-";
+    single_file = 1;
+    {
+        const char *p = outfile_pattern;
+        do
+        {
+            p = strchr(p, '%');
+            if(p && p[1] >= '1' && p[1] <= '9')
+            {
+                // pattern contains sequence number, so it's not unique.
+                single_file = 0;
+                break;
+            }
+            if(p)
+                p++;
+        } while(p);
+    }
+
+    if(single_file && !noblit)
+    {
+        generate_filename(outfile_pattern, outfile, sizeof(outfile)-1,
+                          width, height, 0);
+        out = out_open(outfile, do_md5);
+    }
+
+    if (use_y4m && !noblit)
+    {
+        char buffer[128];
+        if (!single_file)
+        {
+            fprintf(stderr, "YUV4MPEG2 not supported with output patterns,"
+                            " try --i420 or --yv12.\n");
+            return EXIT_FAILURE;
+        }
+
+        if(input.kind == WEBM_FILE)
+            if(webm_guess_framerate(&input, &fps_den, &fps_num))
+            {
+                fprintf(stderr, "Failed to guess framerate -- error parsing "
+                                "webm file?\n");
+                return EXIT_FAILURE;
+            }
+
+
+        /*Note: We can't output an aspect ratio here because IVF doesn't
+           store one, and neither does VP8.
+          That will have to wait until these tools support WebM natively.*/
+        sprintf(buffer, "YUV4MPEG2 C%s W%u H%u F%u:%u I%c\n",
+                "420jpeg", width, height, fps_num, fps_den, 'p');
+        out_put(out, (unsigned char *)buffer, strlen(buffer), do_md5);
+    }
+
+    /* Try to determine the codec from the fourcc. */
+    for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
+        if ((fourcc & ifaces[i].fourcc_mask) == ifaces[i].fourcc)
+        {
+            vpx_codec_iface_t  *ivf_iface = ifaces[i].iface;
+
+            if (iface && iface != ivf_iface)
+                fprintf(stderr, "Notice -- IVF header indicates codec: %s\n",
+                        ifaces[i].name);
+            else
+                iface = ivf_iface;
+
+            break;
+        }
+
+    dec_flags = (postproc ? VPX_CODEC_USE_POSTPROC : 0) |
+                (ec_enabled ? VPX_CODEC_USE_ERROR_CONCEALMENT : 0);
+    if (vpx_codec_dec_init(&decoder, iface ? iface :  ifaces[0].iface, &cfg,
+                           dec_flags))
+    {
+        fprintf(stderr, "Failed to initialize decoder: %s\n", vpx_codec_error(&decoder));
+        return EXIT_FAILURE;
+    }
+
+    if (!quiet)
+        fprintf(stderr, "%s\n", decoder.name);
+
+#if CONFIG_VP8_DECODER
+
+    if (vp8_pp_cfg.post_proc_flag
+        && vpx_codec_control(&decoder, VP8_SET_POSTPROC, &vp8_pp_cfg))
+    {
+        fprintf(stderr, "Failed to configure postproc: %s\n", vpx_codec_error(&decoder));
+        return EXIT_FAILURE;
+    }
+
+    if (vp8_dbg_color_ref_frame
+        && vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_REF_FRAME, vp8_dbg_color_ref_frame))
+    {
+        fprintf(stderr, "Failed to configure reference block visualizer: %s\n", vpx_codec_error(&decoder));
+        return EXIT_FAILURE;
+    }
+
+    if (vp8_dbg_color_mb_modes
+        && vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_MB_MODES, vp8_dbg_color_mb_modes))
+    {
+        fprintf(stderr, "Failed to configure macro block visualizer: %s\n", vpx_codec_error(&decoder));
+        return EXIT_FAILURE;
+    }
+
+    if (vp8_dbg_color_b_modes
+        && vpx_codec_control(&decoder, VP8_SET_DBG_COLOR_B_MODES, vp8_dbg_color_b_modes))
+    {
+        fprintf(stderr, "Failed to configure block visualizer: %s\n", vpx_codec_error(&decoder));
+        return EXIT_FAILURE;
+    }
+
+    if (vp8_dbg_display_mv
+        && vpx_codec_control(&decoder, VP8_SET_DBG_DISPLAY_MV, vp8_dbg_display_mv))
+    {
+        fprintf(stderr, "Failed to configure motion vector visualizer: %s\n", vpx_codec_error(&decoder));
+        return EXIT_FAILURE;
+    }
+#endif
+
+    /* Decode file */
+    while (!read_frame(&input, &buf, &buf_sz, &buf_alloc_sz))
+    {
+        vpx_codec_iter_t  iter = NULL;
+        vpx_image_t    *img;
+        struct vpx_usec_timer timer;
+        int                   corrupted;
+
+        vpx_usec_timer_start(&timer);
+
+        if (vpx_codec_decode(&decoder, buf, buf_sz, NULL, 0))
+        {
+            const char *detail = vpx_codec_error_detail(&decoder);
+            fprintf(stderr, "Failed to decode frame: %s\n", vpx_codec_error(&decoder));
+
+            if (detail)
+                fprintf(stderr, "  Additional information: %s\n", detail);
+
+            goto fail;
+        }
+
+        vpx_usec_timer_mark(&timer);
+        dx_time += vpx_usec_timer_elapsed(&timer);
+
+        ++frame_in;
+
+        if (vpx_codec_control(&decoder, VP8D_GET_FRAME_CORRUPTED, &corrupted))
+        {
+            fprintf(stderr, "Failed VP8_GET_FRAME_CORRUPTED: %s\n",
+                    vpx_codec_error(&decoder));
+            goto fail;
+        }
+        frames_corrupted += corrupted;
+
+        if ((img = vpx_codec_get_frame(&decoder, &iter)))
+            ++frame_out;
+
+        if (progress)
+            show_progress(frame_in, frame_out, dx_time);
+
+        if (!noblit)
+        {
+            if (img)
+            {
+                unsigned int y;
+                char out_fn[PATH_MAX];
+                uint8_t *buf;
+
+                if (!single_file)
+                {
+                    size_t len = sizeof(out_fn)-1;
+
+                    out_fn[len] = '\0';
+                    generate_filename(outfile_pattern, out_fn, len-1,
+                                      img->d_w, img->d_h, frame_in);
+                    out = out_open(out_fn, do_md5);
+                }
+                else if(use_y4m)
+                    out_put(out, (unsigned char *)"FRAME\n", 6, do_md5);
+
+                buf = img->planes[VPX_PLANE_Y];
+
+                for (y = 0; y < img->d_h; y++)
+                {
+                    out_put(out, buf, img->d_w, do_md5);
+                    buf += img->stride[VPX_PLANE_Y];
+                }
+
+                buf = img->planes[flipuv?VPX_PLANE_V:VPX_PLANE_U];
+
+                for (y = 0; y < (1 + img->d_h) / 2; y++)
+                {
+                    out_put(out, buf, (1 + img->d_w) / 2, do_md5);
+                    buf += img->stride[VPX_PLANE_U];
+                }
+
+                buf = img->planes[flipuv?VPX_PLANE_U:VPX_PLANE_V];
+
+                for (y = 0; y < (1 + img->d_h) / 2; y++)
+                {
+                    out_put(out, buf, (1 + img->d_w) / 2, do_md5);
+                    buf += img->stride[VPX_PLANE_V];
+                }
+
+                if (!single_file)
+                    out_close(out, out_fn, do_md5);
+            }
+        }
+
+        if (stop_after && frame_in >= stop_after)
+            break;
+    }
+
+    if (summary || progress)
+    {
+        show_progress(frame_in, frame_out, dx_time);
+        fprintf(stderr, "\n");
+    }
+
+    if (frames_corrupted)
+        fprintf(stderr, "WARNING: %d frames corrupted.\n",frames_corrupted);
+
+fail:
+
+    if (vpx_codec_destroy(&decoder))
+    {
+        fprintf(stderr, "Failed to destroy decoder: %s\n", vpx_codec_error(&decoder));
+        return EXIT_FAILURE;
+    }
+
+    if (single_file && !noblit)
+        out_close(out, outfile, do_md5);
+
+    if(input.nestegg_ctx)
+        nestegg_destroy(input.nestegg_ctx);
+    if(input.kind != WEBM_FILE)
+        free(buf);
+    fclose(infile);
+    free(argv);
+
+    return frames_corrupted ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/vpxenc.c b/vpxenc.c
new file mode 100644 (file)
index 0000000..d32b21b
--- /dev/null
+++ b/vpxenc.c
@@ -0,0 +1,2544 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/* This is a simple program that encodes YV12 files and generates ivf
+ * files using the new interface.
+ */
+#if defined(_WIN32) || !CONFIG_OS_SUPPORT
+#define USE_POSIX_MMAP 0
+#else
+#define USE_POSIX_MMAP 1
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <limits.h>
+#include <assert.h>
+#include "vpx/vpx_encoder.h"
+#if USE_POSIX_MMAP
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+#include "vpx/vp8cx.h"
+#include "vpx_ports/mem_ops.h"
+#include "vpx_ports/vpx_timer.h"
+#include "tools_common.h"
+#include "y4minput.h"
+#include "libmkv/EbmlWriter.h"
+#include "libmkv/EbmlIDs.h"
+
+/* Need special handling of these functions on Windows */
+#if defined(_MSC_VER)
+/* MSVS doesn't define off_t, and uses _f{seek,tell}i64 */
+typedef __int64 off_t;
+#define fseeko _fseeki64
+#define ftello _ftelli64
+#elif defined(_WIN32)
+/* MinGW defines off_t as long
+   and uses f{seek,tell}o64/off64_t for large files */
+#define fseeko fseeko64
+#define ftello ftello64
+#define off_t off64_t
+#endif
+
+#if defined(_MSC_VER)
+#define LITERALU64(n) n
+#else
+#define LITERALU64(n) n##LLU
+#endif
+
+/* We should use 32-bit file operations in WebM file format
+ * when building ARM executable file (.axf) with RVCT */
+#if !CONFIG_OS_SUPPORT
+typedef long off_t;
+#define fseeko fseek
+#define ftello ftell
+#endif
+
+static const char *exec_name;
+
+static const struct codec_item
+{
+    char const              *name;
+    const vpx_codec_iface_t *iface;
+    unsigned int             fourcc;
+} codecs[] =
+{
+#if CONFIG_VP8_ENCODER
+    {"vp8",  &vpx_codec_vp8_cx_algo, 0x30385056},
+#endif
+};
+
+static void usage_exit();
+
+#define LOG_ERROR(label) do \
+{\
+    const char *l=label;\
+    va_list ap;\
+    va_start(ap, fmt);\
+    if(l)\
+        fprintf(stderr, "%s: ", l);\
+    vfprintf(stderr, fmt, ap);\
+    fprintf(stderr, "\n");\
+    va_end(ap);\
+} while(0)
+
+void die(const char *fmt, ...)
+{
+    LOG_ERROR(NULL);
+    usage_exit();
+}
+
+
+void fatal(const char *fmt, ...)
+{
+    LOG_ERROR("Fatal");
+    exit(EXIT_FAILURE);
+}
+
+
+void warn(const char *fmt, ...)
+{
+    LOG_ERROR("Warning");
+}
+
+
+static void ctx_exit_on_error(vpx_codec_ctx_t *ctx, const char *s, ...)
+{
+    va_list ap;
+
+    va_start(ap, s);
+    if (ctx->err)
+    {
+        const char *detail = vpx_codec_error_detail(ctx);
+
+        vfprintf(stderr, s, ap);
+        fprintf(stderr, ": %s\n", vpx_codec_error(ctx));
+
+        if (detail)
+            fprintf(stderr, "    %s\n", detail);
+
+        exit(EXIT_FAILURE);
+    }
+}
+
+/* This structure is used to abstract the different ways of handling
+ * first pass statistics.
+ */
+typedef struct
+{
+    vpx_fixed_buf_t buf;
+    int             pass;
+    FILE           *file;
+    char           *buf_ptr;
+    size_t          buf_alloc_sz;
+} stats_io_t;
+
+int stats_open_file(stats_io_t *stats, const char *fpf, int pass)
+{
+    int res;
+
+    stats->pass = pass;
+
+    if (pass == 0)
+    {
+        stats->file = fopen(fpf, "wb");
+        stats->buf.sz = 0;
+        stats->buf.buf = NULL,
+                   res = (stats->file != NULL);
+    }
+    else
+    {
+#if 0
+#elif USE_POSIX_MMAP
+        struct stat stat_buf;
+        int fd;
+
+        fd = open(fpf, O_RDONLY);
+        stats->file = fdopen(fd, "rb");
+        fstat(fd, &stat_buf);
+        stats->buf.sz = stat_buf.st_size;
+        stats->buf.buf = mmap(NULL, stats->buf.sz, PROT_READ, MAP_PRIVATE,
+                              fd, 0);
+        res = (stats->buf.buf != NULL);
+#else
+        size_t nbytes;
+
+        stats->file = fopen(fpf, "rb");
+
+        if (fseek(stats->file, 0, SEEK_END))
+            fatal("First-pass stats file must be seekable!");
+
+        stats->buf.sz = stats->buf_alloc_sz = ftell(stats->file);
+        rewind(stats->file);
+
+        stats->buf.buf = malloc(stats->buf_alloc_sz);
+
+        if (!stats->buf.buf)
+            fatal("Failed to allocate first-pass stats buffer (%lu bytes)",
+                  (unsigned long)stats->buf_alloc_sz);
+
+        nbytes = fread(stats->buf.buf, 1, stats->buf.sz, stats->file);
+        res = (nbytes == stats->buf.sz);
+#endif
+    }
+
+    return res;
+}
+
+int stats_open_mem(stats_io_t *stats, int pass)
+{
+    int res;
+    stats->pass = pass;
+
+    if (!pass)
+    {
+        stats->buf.sz = 0;
+        stats->buf_alloc_sz = 64 * 1024;
+        stats->buf.buf = malloc(stats->buf_alloc_sz);
+    }
+
+    stats->buf_ptr = stats->buf.buf;
+    res = (stats->buf.buf != NULL);
+    return res;
+}
+
+
+void stats_close(stats_io_t *stats, int last_pass)
+{
+    if (stats->file)
+    {
+        if (stats->pass == last_pass)
+        {
+#if 0
+#elif USE_POSIX_MMAP
+            munmap(stats->buf.buf, stats->buf.sz);
+#else
+            free(stats->buf.buf);
+#endif
+        }
+
+        fclose(stats->file);
+        stats->file = NULL;
+    }
+    else
+    {
+        if (stats->pass == last_pass)
+            free(stats->buf.buf);
+    }
+}
+
+void stats_write(stats_io_t *stats, const void *pkt, size_t len)
+{
+    if (stats->file)
+    {
+        if(fwrite(pkt, 1, len, stats->file));
+    }
+    else
+    {
+        if (stats->buf.sz + len > stats->buf_alloc_sz)
+        {
+            size_t  new_sz = stats->buf_alloc_sz + 64 * 1024;
+            char   *new_ptr = realloc(stats->buf.buf, new_sz);
+
+            if (new_ptr)
+            {
+                stats->buf_ptr = new_ptr + (stats->buf_ptr - (char *)stats->buf.buf);
+                stats->buf.buf = new_ptr;
+                stats->buf_alloc_sz = new_sz;
+            }
+            else
+                fatal("Failed to realloc firstpass stats buffer.");
+        }
+
+        memcpy(stats->buf_ptr, pkt, len);
+        stats->buf.sz += len;
+        stats->buf_ptr += len;
+    }
+}
+
+vpx_fixed_buf_t stats_get(stats_io_t *stats)
+{
+    return stats->buf;
+}
+
+/* Stereo 3D packed frame format */
+typedef enum stereo_format
+{
+    STEREO_FORMAT_MONO       = 0,
+    STEREO_FORMAT_LEFT_RIGHT = 1,
+    STEREO_FORMAT_BOTTOM_TOP = 2,
+    STEREO_FORMAT_TOP_BOTTOM = 3,
+    STEREO_FORMAT_RIGHT_LEFT = 11
+} stereo_format_t;
+
+enum video_file_type
+{
+    FILE_TYPE_RAW,
+    FILE_TYPE_IVF,
+    FILE_TYPE_Y4M
+};
+
+struct detect_buffer {
+    char buf[4];
+    size_t buf_read;
+    size_t position;
+};
+
+
+struct input_state
+{
+    char                 *fn;
+    FILE                 *file;
+    y4m_input             y4m;
+    struct detect_buffer  detect;
+    enum video_file_type  file_type;
+    unsigned int          w;
+    unsigned int          h;
+    struct vpx_rational   framerate;
+    int                   use_i420;
+};
+
+
+#define IVF_FRAME_HDR_SZ (4+8) /* 4 byte size + 8 byte timestamp */
+static int read_frame(struct input_state *input, vpx_image_t *img)
+{
+    FILE *f = input->file;
+    enum video_file_type file_type = input->file_type;
+    y4m_input *y4m = &input->y4m;
+    struct detect_buffer *detect = &input->detect;
+    int plane = 0;
+    int shortread = 0;
+
+    if (file_type == FILE_TYPE_Y4M)
+    {
+        if (y4m_input_fetch_frame(y4m, f, img) < 1)
+           return 0;
+    }
+    else
+    {
+        if (file_type == FILE_TYPE_IVF)
+        {
+            char junk[IVF_FRAME_HDR_SZ];
+
+            /* Skip the frame header. We know how big the frame should be. See
+             * write_ivf_frame_header() for documentation on the frame header
+             * layout.
+             */
+            if(fread(junk, 1, IVF_FRAME_HDR_SZ, f));
+        }
+
+        for (plane = 0; plane < 3; plane++)
+        {
+            unsigned char *ptr;
+            int w = (plane ? (1 + img->d_w) / 2 : img->d_w);
+            int h = (plane ? (1 + img->d_h) / 2 : img->d_h);
+            int r;
+
+            /* Determine the correct plane based on the image format. The for-loop
+             * always counts in Y,U,V order, but this may not match the order of
+             * the data on disk.
+             */
+            switch (plane)
+            {
+            case 1:
+                ptr = img->planes[img->fmt==VPX_IMG_FMT_YV12? VPX_PLANE_V : VPX_PLANE_U];
+                break;
+            case 2:
+                ptr = img->planes[img->fmt==VPX_IMG_FMT_YV12?VPX_PLANE_U : VPX_PLANE_V];
+                break;
+            default:
+                ptr = img->planes[plane];
+            }
+
+            for (r = 0; r < h; r++)
+            {
+                size_t needed = w;
+                size_t buf_position = 0;
+                const size_t left = detect->buf_read - detect->position;
+                if (left > 0)
+                {
+                    const size_t more = (left < needed) ? left : needed;
+                    memcpy(ptr, detect->buf + detect->position, more);
+                    buf_position = more;
+                    needed -= more;
+                    detect->position += more;
+                }
+                if (needed > 0)
+                {
+                    shortread |= (fread(ptr + buf_position, 1, needed, f) < needed);
+                }
+
+                ptr += img->stride[plane];
+            }
+        }
+    }
+
+    return !shortread;
+}
+
+
+unsigned int file_is_y4m(FILE      *infile,
+                         y4m_input *y4m,
+                         char       detect[4])
+{
+    if(memcmp(detect, "YUV4", 4) == 0)
+    {
+        return 1;
+    }
+    return 0;
+}
+
+#define IVF_FILE_HDR_SZ (32)
+unsigned int file_is_ivf(struct input_state *input,
+                         unsigned int *fourcc)
+{
+    char raw_hdr[IVF_FILE_HDR_SZ];
+    int is_ivf = 0;
+    FILE *infile = input->file;
+    unsigned int *width = &input->w;
+    unsigned int *height = &input->h;
+    struct detect_buffer *detect = &input->detect;
+
+    if(memcmp(detect->buf, "DKIF", 4) != 0)
+        return 0;
+
+    /* See write_ivf_file_header() for more documentation on the file header
+     * layout.
+     */
+    if (fread(raw_hdr + 4, 1, IVF_FILE_HDR_SZ - 4, infile)
+        == IVF_FILE_HDR_SZ - 4)
+    {
+        {
+            is_ivf = 1;
+
+            if (mem_get_le16(raw_hdr + 4) != 0)
+                warn("Unrecognized IVF version! This file may not decode "
+                     "properly.");
+
+            *fourcc = mem_get_le32(raw_hdr + 8);
+        }
+    }
+
+    if (is_ivf)
+    {
+        *width = mem_get_le16(raw_hdr + 12);
+        *height = mem_get_le16(raw_hdr + 14);
+        detect->position = 4;
+    }
+
+    return is_ivf;
+}
+
+
+static void write_ivf_file_header(FILE *outfile,
+                                  const vpx_codec_enc_cfg_t *cfg,
+                                  unsigned int fourcc,
+                                  int frame_cnt)
+{
+    char header[32];
+
+    if (cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
+        return;
+
+    header[0] = 'D';
+    header[1] = 'K';
+    header[2] = 'I';
+    header[3] = 'F';
+    mem_put_le16(header + 4,  0);                 /* version */
+    mem_put_le16(header + 6,  32);                /* headersize */
+    mem_put_le32(header + 8,  fourcc);            /* headersize */
+    mem_put_le16(header + 12, cfg->g_w);          /* width */
+    mem_put_le16(header + 14, cfg->g_h);          /* height */
+    mem_put_le32(header + 16, cfg->g_timebase.den); /* rate */
+    mem_put_le32(header + 20, cfg->g_timebase.num); /* scale */
+    mem_put_le32(header + 24, frame_cnt);         /* length */
+    mem_put_le32(header + 28, 0);                 /* unused */
+
+    if(fwrite(header, 1, 32, outfile));
+}
+
+
+static void write_ivf_frame_header(FILE *outfile,
+                                   const vpx_codec_cx_pkt_t *pkt)
+{
+    char             header[12];
+    vpx_codec_pts_t  pts;
+
+    if (pkt->kind != VPX_CODEC_CX_FRAME_PKT)
+        return;
+
+    pts = pkt->data.frame.pts;
+    mem_put_le32(header, pkt->data.frame.sz);
+    mem_put_le32(header + 4, pts & 0xFFFFFFFF);
+    mem_put_le32(header + 8, pts >> 32);
+
+    if(fwrite(header, 1, 12, outfile));
+}
+
+static void write_ivf_frame_size(FILE *outfile, size_t size)
+{
+    char             header[4];
+    mem_put_le32(header, size);
+    fwrite(header, 1, 4, outfile);
+}
+
+
+typedef off_t EbmlLoc;
+
+
+struct cue_entry
+{
+    unsigned int time;
+    uint64_t     loc;
+};
+
+
+struct EbmlGlobal
+{
+    int debug;
+
+    FILE    *stream;
+    int64_t last_pts_ms;
+    vpx_rational_t  framerate;
+
+    /* These pointers are to the start of an element */
+    off_t    position_reference;
+    off_t    seek_info_pos;
+    off_t    segment_info_pos;
+    off_t    track_pos;
+    off_t    cue_pos;
+    off_t    cluster_pos;
+
+    /* This pointer is to a specific element to be serialized */
+    off_t    track_id_pos;
+
+    /* These pointers are to the size field of the element */
+    EbmlLoc  startSegment;
+    EbmlLoc  startCluster;
+
+    uint32_t cluster_timecode;
+    int      cluster_open;
+
+    struct cue_entry *cue_list;
+    unsigned int      cues;
+
+};
+
+
+void Ebml_Write(EbmlGlobal *glob, const void *buffer_in, unsigned long len)
+{
+    if(fwrite(buffer_in, 1, len, glob->stream));
+}
+
+#define WRITE_BUFFER(s) \
+for(i = len-1; i>=0; i--)\
+{ \
+    x = *(const s *)buffer_in >> (i * CHAR_BIT); \
+    Ebml_Write(glob, &x, 1); \
+}
+void Ebml_Serialize(EbmlGlobal *glob, const void *buffer_in, int buffer_size, unsigned long len)
+{
+    char x;
+    int i;
+
+    /* buffer_size:
+     * 1 - int8_t;
+     * 2 - int16_t;
+     * 3 - int32_t;
+     * 4 - int64_t;
+     */
+    switch (buffer_size)
+    {
+        case 1:
+            WRITE_BUFFER(int8_t)
+            break;
+        case 2:
+            WRITE_BUFFER(int16_t)
+            break;
+        case 4:
+            WRITE_BUFFER(int32_t)
+            break;
+        case 8:
+            WRITE_BUFFER(int64_t)
+            break;
+        default:
+            break;
+    }
+}
+#undef WRITE_BUFFER
+
+/* Need a fixed size serializer for the track ID. libmkv provides a 64 bit
+ * one, but not a 32 bit one.
+ */
+static void Ebml_SerializeUnsigned32(EbmlGlobal *glob, unsigned long class_id, uint64_t ui)
+{
+    unsigned char sizeSerialized = 4 | 0x80;
+    Ebml_WriteID(glob, class_id);
+    Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
+    Ebml_Serialize(glob, &ui, sizeof(ui), 4);
+}
+
+
+static void
+Ebml_StartSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc,
+                          unsigned long class_id)
+{
+    //todo this is always taking 8 bytes, this may need later optimization
+    //this is a key that says length unknown
+    uint64_t unknownLen =  LITERALU64(0x01FFFFFFFFFFFFFF);
+
+    Ebml_WriteID(glob, class_id);
+    *ebmlLoc = ftello(glob->stream);
+    Ebml_Serialize(glob, &unknownLen, sizeof(unknownLen), 8);
+}
+
+static void
+Ebml_EndSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc)
+{
+    off_t pos;
+    uint64_t size;
+
+    /* Save the current stream pointer */
+    pos = ftello(glob->stream);
+
+    /* Calculate the size of this element */
+    size = pos - *ebmlLoc - 8;
+    size |=  LITERALU64(0x0100000000000000);
+
+    /* Seek back to the beginning of the element and write the new size */
+    fseeko(glob->stream, *ebmlLoc, SEEK_SET);
+    Ebml_Serialize(glob, &size, sizeof(size), 8);
+
+    /* Reset the stream pointer */
+    fseeko(glob->stream, pos, SEEK_SET);
+}
+
+
+static void
+write_webm_seek_element(EbmlGlobal *ebml, unsigned long id, off_t pos)
+{
+    uint64_t offset = pos - ebml->position_reference;
+    EbmlLoc start;
+    Ebml_StartSubElement(ebml, &start, Seek);
+    Ebml_SerializeBinary(ebml, SeekID, id);
+    Ebml_SerializeUnsigned64(ebml, SeekPosition, offset);
+    Ebml_EndSubElement(ebml, &start);
+}
+
+
+static void
+write_webm_seek_info(EbmlGlobal *ebml)
+{
+
+    off_t pos;
+
+    /* Save the current stream pointer */
+    pos = ftello(ebml->stream);
+
+    if(ebml->seek_info_pos)
+        fseeko(ebml->stream, ebml->seek_info_pos, SEEK_SET);
+    else
+        ebml->seek_info_pos = pos;
+
+    {
+        EbmlLoc start;
+
+        Ebml_StartSubElement(ebml, &start, SeekHead);
+        write_webm_seek_element(ebml, Tracks, ebml->track_pos);
+        write_webm_seek_element(ebml, Cues,   ebml->cue_pos);
+        write_webm_seek_element(ebml, Info,   ebml->segment_info_pos);
+        Ebml_EndSubElement(ebml, &start);
+    }
+    {
+        //segment info
+        EbmlLoc startInfo;
+        uint64_t frame_time;
+        char version_string[64];
+
+        /* Assemble version string */
+        if(ebml->debug)
+            strcpy(version_string, "vpxenc");
+        else
+        {
+            strcpy(version_string, "vpxenc ");
+            strncat(version_string,
+                    vpx_codec_version_str(),
+                    sizeof(version_string) - 1 - strlen(version_string));
+        }
+
+        frame_time = (uint64_t)1000 * ebml->framerate.den
+                     / ebml->framerate.num;
+        ebml->segment_info_pos = ftello(ebml->stream);
+        Ebml_StartSubElement(ebml, &startInfo, Info);
+        Ebml_SerializeUnsigned(ebml, TimecodeScale, 1000000);
+        Ebml_SerializeFloat(ebml, Segment_Duration,
+                            ebml->last_pts_ms + frame_time);
+        Ebml_SerializeString(ebml, 0x4D80, version_string);
+        Ebml_SerializeString(ebml, 0x5741, version_string);
+        Ebml_EndSubElement(ebml, &startInfo);
+    }
+}
+
+
+static void
+write_webm_file_header(EbmlGlobal                *glob,
+                       const vpx_codec_enc_cfg_t *cfg,
+                       const struct vpx_rational *fps,
+                       stereo_format_t            stereo_fmt)
+{
+    {
+        EbmlLoc start;
+        Ebml_StartSubElement(glob, &start, EBML);
+        Ebml_SerializeUnsigned(glob, EBMLVersion, 1);
+        Ebml_SerializeUnsigned(glob, EBMLReadVersion, 1); //EBML Read Version
+        Ebml_SerializeUnsigned(glob, EBMLMaxIDLength, 4); //EBML Max ID Length
+        Ebml_SerializeUnsigned(glob, EBMLMaxSizeLength, 8); //EBML Max Size Length
+        Ebml_SerializeString(glob, DocType, "webm"); //Doc Type
+        Ebml_SerializeUnsigned(glob, DocTypeVersion, 2); //Doc Type Version
+        Ebml_SerializeUnsigned(glob, DocTypeReadVersion, 2); //Doc Type Read Version
+        Ebml_EndSubElement(glob, &start);
+    }
+    {
+        Ebml_StartSubElement(glob, &glob->startSegment, Segment); //segment
+        glob->position_reference = ftello(glob->stream);
+        glob->framerate = *fps;
+        write_webm_seek_info(glob);
+
+        {
+            EbmlLoc trackStart;
+            glob->track_pos = ftello(glob->stream);
+            Ebml_StartSubElement(glob, &trackStart, Tracks);
+            {
+                unsigned int trackNumber = 1;
+                uint64_t     trackID = 0;
+
+                EbmlLoc start;
+                Ebml_StartSubElement(glob, &start, TrackEntry);
+                Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
+                glob->track_id_pos = ftello(glob->stream);
+                Ebml_SerializeUnsigned32(glob, TrackUID, trackID);
+                Ebml_SerializeUnsigned(glob, TrackType, 1); //video is always 1
+                Ebml_SerializeString(glob, CodecID, "V_VP8");
+                {
+                    unsigned int pixelWidth = cfg->g_w;
+                    unsigned int pixelHeight = cfg->g_h;
+                    float        frameRate   = (float)fps->num/(float)fps->den;
+
+                    EbmlLoc videoStart;
+                    Ebml_StartSubElement(glob, &videoStart, Video);
+                    Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth);
+                    Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight);
+                    Ebml_SerializeUnsigned(glob, StereoMode, stereo_fmt);
+                    Ebml_SerializeFloat(glob, FrameRate, frameRate);
+                    Ebml_EndSubElement(glob, &videoStart); //Video
+                }
+                Ebml_EndSubElement(glob, &start); //Track Entry
+            }
+            Ebml_EndSubElement(glob, &trackStart);
+        }
+        // segment element is open
+    }
+}
+
+
+static void
+write_webm_block(EbmlGlobal                *glob,
+                 const vpx_codec_enc_cfg_t *cfg,
+                 const vpx_codec_cx_pkt_t  *pkt)
+{
+    unsigned long  block_length;
+    unsigned char  track_number;
+    unsigned short block_timecode = 0;
+    unsigned char  flags;
+    int64_t        pts_ms;
+    int            start_cluster = 0, is_keyframe;
+
+    /* Calculate the PTS of this frame in milliseconds */
+    pts_ms = pkt->data.frame.pts * 1000
+             * (uint64_t)cfg->g_timebase.num / (uint64_t)cfg->g_timebase.den;
+    if(pts_ms <= glob->last_pts_ms)
+        pts_ms = glob->last_pts_ms + 1;
+    glob->last_pts_ms = pts_ms;
+
+    /* Calculate the relative time of this block */
+    if(pts_ms - glob->cluster_timecode > SHRT_MAX)
+        start_cluster = 1;
+    else
+        block_timecode = pts_ms - glob->cluster_timecode;
+
+    is_keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY);
+    if(start_cluster || is_keyframe)
+    {
+        if(glob->cluster_open)
+            Ebml_EndSubElement(glob, &glob->startCluster);
+
+        /* Open the new cluster */
+        block_timecode = 0;
+        glob->cluster_open = 1;
+        glob->cluster_timecode = pts_ms;
+        glob->cluster_pos = ftello(glob->stream);
+        Ebml_StartSubElement(glob, &glob->startCluster, Cluster); //cluster
+        Ebml_SerializeUnsigned(glob, Timecode, glob->cluster_timecode);
+
+        /* Save a cue point if this is a keyframe. */
+        if(is_keyframe)
+        {
+            struct cue_entry *cue, *new_cue_list;
+
+            new_cue_list = realloc(glob->cue_list,
+                                   (glob->cues+1) * sizeof(struct cue_entry));
+            if(new_cue_list)
+                glob->cue_list = new_cue_list;
+            else
+                fatal("Failed to realloc cue list.");
+
+            cue = &glob->cue_list[glob->cues];
+            cue->time = glob->cluster_timecode;
+            cue->loc = glob->cluster_pos;
+            glob->cues++;
+        }
+    }
+
+    /* Write the Simple Block */
+    Ebml_WriteID(glob, SimpleBlock);
+
+    block_length = pkt->data.frame.sz + 4;
+    block_length |= 0x10000000;
+    Ebml_Serialize(glob, &block_length, sizeof(block_length), 4);
+
+    track_number = 1;
+    track_number |= 0x80;
+    Ebml_Write(glob, &track_number, 1);
+
+    Ebml_Serialize(glob, &block_timecode, sizeof(block_timecode), 2);
+
+    flags = 0;
+    if(is_keyframe)
+        flags |= 0x80;
+    if(pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE)
+        flags |= 0x08;
+    Ebml_Write(glob, &flags, 1);
+
+    Ebml_Write(glob, pkt->data.frame.buf, pkt->data.frame.sz);
+}
+
+
+static void
+write_webm_file_footer(EbmlGlobal *glob, long hash)
+{
+
+    if(glob->cluster_open)
+        Ebml_EndSubElement(glob, &glob->startCluster);
+
+    {
+        EbmlLoc start;
+        unsigned int i;
+
+        glob->cue_pos = ftello(glob->stream);
+        Ebml_StartSubElement(glob, &start, Cues);
+        for(i=0; i<glob->cues; i++)
+        {
+            struct cue_entry *cue = &glob->cue_list[i];
+            EbmlLoc start;
+
+            Ebml_StartSubElement(glob, &start, CuePoint);
+            {
+                EbmlLoc start;
+
+                Ebml_SerializeUnsigned(glob, CueTime, cue->time);
+
+                Ebml_StartSubElement(glob, &start, CueTrackPositions);
+                Ebml_SerializeUnsigned(glob, CueTrack, 1);
+                Ebml_SerializeUnsigned64(glob, CueClusterPosition,
+                                         cue->loc - glob->position_reference);
+                //Ebml_SerializeUnsigned(glob, CueBlockNumber, cue->blockNumber);
+                Ebml_EndSubElement(glob, &start);
+            }
+            Ebml_EndSubElement(glob, &start);
+        }
+        Ebml_EndSubElement(glob, &start);
+    }
+
+    Ebml_EndSubElement(glob, &glob->startSegment);
+
+    /* Patch up the seek info block */
+    write_webm_seek_info(glob);
+
+    /* Patch up the track id */
+    fseeko(glob->stream, glob->track_id_pos, SEEK_SET);
+    Ebml_SerializeUnsigned32(glob, TrackUID, glob->debug ? 0xDEADBEEF : hash);
+
+    fseeko(glob->stream, 0, SEEK_END);
+}
+
+
+/* Murmur hash derived from public domain reference implementation at
+ *   http://sites.google.com/site/murmurhash/
+ */
+static unsigned int murmur ( const void * key, int len, unsigned int seed )
+{
+    const unsigned int m = 0x5bd1e995;
+    const int r = 24;
+
+    unsigned int h = seed ^ len;
+
+    const unsigned char * data = (const unsigned char *)key;
+
+    while(len >= 4)
+    {
+        unsigned int k;
+
+        k  = data[0];
+        k |= data[1] << 8;
+        k |= data[2] << 16;
+        k |= data[3] << 24;
+
+        k *= m;
+        k ^= k >> r;
+        k *= m;
+
+        h *= m;
+        h ^= k;
+
+        data += 4;
+        len -= 4;
+    }
+
+    switch(len)
+    {
+    case 3: h ^= data[2] << 16;
+    case 2: h ^= data[1] << 8;
+    case 1: h ^= data[0];
+            h *= m;
+    };
+
+    h ^= h >> 13;
+    h *= m;
+    h ^= h >> 15;
+
+    return h;
+}
+
+#include "math.h"
+
+static double vp8_mse2psnr(double Samples, double Peak, double Mse)
+{
+    double psnr;
+
+    if ((double)Mse > 0.0)
+        psnr = 10.0 * log10(Peak * Peak * Samples / Mse);
+    else
+        psnr = 60;      // Limit to prevent / 0
+
+    if (psnr > 60)
+        psnr = 60;
+
+    return psnr;
+}
+
+
+#include "args.h"
+static const arg_def_t debugmode = ARG_DEF("D", "debug", 0,
+        "Debug mode (makes output deterministic)");
+static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
+        "Output filename");
+static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0,
+                                  "Input file is YV12 ");
+static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0,
+                                  "Input file is I420 (default)");
+static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1,
+                                  "Codec to use");
+static const arg_def_t passes           = ARG_DEF("p", "passes", 1,
+        "Number of passes (1/2)");
+static const arg_def_t pass_arg         = ARG_DEF(NULL, "pass", 1,
+        "Pass to execute (1/2)");
+static const arg_def_t fpf_name         = ARG_DEF(NULL, "fpf", 1,
+        "First pass statistics file name");
+static const arg_def_t limit = ARG_DEF(NULL, "limit", 1,
+                                       "Stop encoding after n input frames");
+static const arg_def_t deadline         = ARG_DEF("d", "deadline", 1,
+        "Deadline per frame (usec)");
+static const arg_def_t best_dl          = ARG_DEF(NULL, "best", 0,
+        "Use Best Quality Deadline");
+static const arg_def_t good_dl          = ARG_DEF(NULL, "good", 0,
+        "Use Good Quality Deadline");
+static const arg_def_t rt_dl            = ARG_DEF(NULL, "rt", 0,
+        "Use Realtime Quality Deadline");
+static const arg_def_t verbosearg       = ARG_DEF("v", "verbose", 0,
+        "Show encoder parameters");
+static const arg_def_t psnrarg          = ARG_DEF(NULL, "psnr", 0,
+        "Show PSNR in status line");
+static const arg_def_t framerate        = ARG_DEF(NULL, "fps", 1,
+        "Stream frame rate (rate/scale)");
+static const arg_def_t use_ivf          = ARG_DEF(NULL, "ivf", 0,
+        "Output IVF (default is WebM)");
+static const arg_def_t out_part = ARG_DEF("P", "output-partitions", 0,
+        "Makes encoder output partitions. Requires IVF output!");
+static const arg_def_t q_hist_n         = ARG_DEF(NULL, "q-hist", 1,
+        "Show quantizer histogram (n-buckets)");
+static const arg_def_t rate_hist_n         = ARG_DEF(NULL, "rate-hist", 1,
+        "Show rate histogram (n-buckets)");
+static const arg_def_t *main_args[] =
+{
+    &debugmode,
+    &outputfile, &codecarg, &passes, &pass_arg, &fpf_name, &limit, &deadline,
+    &best_dl, &good_dl, &rt_dl,
+    &verbosearg, &psnrarg, &use_ivf, &out_part, &q_hist_n, &rate_hist_n,
+    NULL
+};
+
+static const arg_def_t usage            = ARG_DEF("u", "usage", 1,
+        "Usage profile number to use");
+static const arg_def_t threads          = ARG_DEF("t", "threads", 1,
+        "Max number of threads to use");
+static const arg_def_t profile          = ARG_DEF(NULL, "profile", 1,
+        "Bitstream profile number to use");
+static const arg_def_t width            = ARG_DEF("w", "width", 1,
+        "Frame width");
+static const arg_def_t height           = ARG_DEF("h", "height", 1,
+        "Frame height");
+static const struct arg_enum_list stereo_mode_enum[] = {
+    {"mono"      , STEREO_FORMAT_MONO},
+    {"left-right", STEREO_FORMAT_LEFT_RIGHT},
+    {"bottom-top", STEREO_FORMAT_BOTTOM_TOP},
+    {"top-bottom", STEREO_FORMAT_TOP_BOTTOM},
+    {"right-left", STEREO_FORMAT_RIGHT_LEFT},
+    {NULL, 0}
+};
+static const arg_def_t stereo_mode      = ARG_DEF_ENUM(NULL, "stereo-mode", 1,
+        "Stereo 3D video format", stereo_mode_enum);
+static const arg_def_t timebase         = ARG_DEF(NULL, "timebase", 1,
+        "Output timestamp precision (fractional seconds)");
+static const arg_def_t error_resilient  = ARG_DEF(NULL, "error-resilient", 1,
+        "Enable error resiliency features");
+static const arg_def_t lag_in_frames    = ARG_DEF(NULL, "lag-in-frames", 1,
+        "Max number of frames to lag");
+
+static const arg_def_t *global_args[] =
+{
+    &use_yv12, &use_i420, &usage, &threads, &profile,
+    &width, &height, &stereo_mode, &timebase, &framerate, &error_resilient,
+    &lag_in_frames, NULL
+};
+
+static const arg_def_t dropframe_thresh   = ARG_DEF(NULL, "drop-frame", 1,
+        "Temporal resampling threshold (buf %)");
+static const arg_def_t resize_allowed     = ARG_DEF(NULL, "resize-allowed", 1,
+        "Spatial resampling enabled (bool)");
+static const arg_def_t resize_up_thresh   = ARG_DEF(NULL, "resize-up", 1,
+        "Upscale threshold (buf %)");
+static const arg_def_t resize_down_thresh = ARG_DEF(NULL, "resize-down", 1,
+        "Downscale threshold (buf %)");
+static const struct arg_enum_list end_usage_enum[] = {
+    {"vbr", VPX_VBR},
+    {"cbr", VPX_CBR},
+    {"cq",  VPX_CQ},
+    {NULL, 0}
+};
+static const arg_def_t end_usage          = ARG_DEF_ENUM(NULL, "end-usage", 1,
+        "Rate control mode", end_usage_enum);
+static const arg_def_t target_bitrate     = ARG_DEF(NULL, "target-bitrate", 1,
+        "Bitrate (kbps)");
+static const arg_def_t min_quantizer      = ARG_DEF(NULL, "min-q", 1,
+        "Minimum (best) quantizer");
+static const arg_def_t max_quantizer      = ARG_DEF(NULL, "max-q", 1,
+        "Maximum (worst) quantizer");
+static const arg_def_t undershoot_pct     = ARG_DEF(NULL, "undershoot-pct", 1,
+        "Datarate undershoot (min) target (%)");
+static const arg_def_t overshoot_pct      = ARG_DEF(NULL, "overshoot-pct", 1,
+        "Datarate overshoot (max) target (%)");
+static const arg_def_t buf_sz             = ARG_DEF(NULL, "buf-sz", 1,
+        "Client buffer size (ms)");
+static const arg_def_t buf_initial_sz     = ARG_DEF(NULL, "buf-initial-sz", 1,
+        "Client initial buffer size (ms)");
+static const arg_def_t buf_optimal_sz     = ARG_DEF(NULL, "buf-optimal-sz", 1,
+        "Client optimal buffer size (ms)");
+static const arg_def_t *rc_args[] =
+{
+    &dropframe_thresh, &resize_allowed, &resize_up_thresh, &resize_down_thresh,
+    &end_usage, &target_bitrate, &min_quantizer, &max_quantizer,
+    &undershoot_pct, &overshoot_pct, &buf_sz, &buf_initial_sz, &buf_optimal_sz,
+    NULL
+};
+
+
+static const arg_def_t bias_pct = ARG_DEF(NULL, "bias-pct", 1,
+                                  "CBR/VBR bias (0=CBR, 100=VBR)");
+static const arg_def_t minsection_pct = ARG_DEF(NULL, "minsection-pct", 1,
+                                        "GOP min bitrate (% of target)");
+static const arg_def_t maxsection_pct = ARG_DEF(NULL, "maxsection-pct", 1,
+                                        "GOP max bitrate (% of target)");
+static const arg_def_t *rc_twopass_args[] =
+{
+    &bias_pct, &minsection_pct, &maxsection_pct, NULL
+};
+
+
+static const arg_def_t kf_min_dist = ARG_DEF(NULL, "kf-min-dist", 1,
+                                     "Minimum keyframe interval (frames)");
+static const arg_def_t kf_max_dist = ARG_DEF(NULL, "kf-max-dist", 1,
+                                     "Maximum keyframe interval (frames)");
+static const arg_def_t kf_disabled = ARG_DEF(NULL, "disable-kf", 0,
+                                     "Disable keyframe placement");
+static const arg_def_t *kf_args[] =
+{
+    &kf_min_dist, &kf_max_dist, &kf_disabled, NULL
+};
+
+
+#if CONFIG_VP8_ENCODER
+static const arg_def_t noise_sens = ARG_DEF(NULL, "noise-sensitivity", 1,
+                                    "Noise sensitivity (frames to blur)");
+static const arg_def_t sharpness = ARG_DEF(NULL, "sharpness", 1,
+                                   "Filter sharpness (0-7)");
+static const arg_def_t static_thresh = ARG_DEF(NULL, "static-thresh", 1,
+                                       "Motion detection threshold");
+#endif
+
+#if CONFIG_VP8_ENCODER
+static const arg_def_t cpu_used = ARG_DEF(NULL, "cpu-used", 1,
+                                  "CPU Used (-16..16)");
+#endif
+
+
+#if CONFIG_VP8_ENCODER
+static const arg_def_t token_parts = ARG_DEF(NULL, "token-parts", 1,
+                                     "Number of token partitions to use, log2");
+static const arg_def_t auto_altref = ARG_DEF(NULL, "auto-alt-ref", 1,
+                                     "Enable automatic alt reference frames");
+static const arg_def_t arnr_maxframes = ARG_DEF(NULL, "arnr-maxframes", 1,
+                                        "AltRef Max Frames");
+static const arg_def_t arnr_strength = ARG_DEF(NULL, "arnr-strength", 1,
+                                       "AltRef Strength");
+static const arg_def_t arnr_type = ARG_DEF(NULL, "arnr-type", 1,
+                                   "AltRef Type");
+static const struct arg_enum_list tuning_enum[] = {
+    {"psnr", VP8_TUNE_PSNR},
+    {"ssim", VP8_TUNE_SSIM},
+    {NULL, 0}
+};
+static const arg_def_t tune_ssim = ARG_DEF_ENUM(NULL, "tune", 1,
+                                   "Material to favor", tuning_enum);
+static const arg_def_t cq_level = ARG_DEF(NULL, "cq-level", 1,
+                                   "Constrained Quality Level");
+static const arg_def_t max_intra_rate_pct = ARG_DEF(NULL, "max-intra-rate", 1,
+        "Max I-frame bitrate (pct)");
+
+static const arg_def_t *vp8_args[] =
+{
+    &cpu_used, &auto_altref, &noise_sens, &sharpness, &static_thresh,
+    &token_parts, &arnr_maxframes, &arnr_strength, &arnr_type,
+    &tune_ssim, &cq_level, &max_intra_rate_pct, NULL
+};
+static const int vp8_arg_ctrl_map[] =
+{
+    VP8E_SET_CPUUSED, VP8E_SET_ENABLEAUTOALTREF,
+    VP8E_SET_NOISE_SENSITIVITY, VP8E_SET_SHARPNESS, VP8E_SET_STATIC_THRESHOLD,
+    VP8E_SET_TOKEN_PARTITIONS,
+    VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH , VP8E_SET_ARNR_TYPE,
+    VP8E_SET_TUNING, VP8E_SET_CQ_LEVEL, VP8E_SET_MAX_INTRA_BITRATE_PCT, 0
+};
+#endif
+
+static const arg_def_t *no_args[] = { NULL };
+
+static void usage_exit()
+{
+    int i;
+
+    fprintf(stderr, "Usage: %s <options> -o dst_filename src_filename \n",
+            exec_name);
+
+    fprintf(stderr, "\nOptions:\n");
+    arg_show_usage(stdout, main_args);
+    fprintf(stderr, "\nEncoder Global Options:\n");
+    arg_show_usage(stdout, global_args);
+    fprintf(stderr, "\nRate Control Options:\n");
+    arg_show_usage(stdout, rc_args);
+    fprintf(stderr, "\nTwopass Rate Control Options:\n");
+    arg_show_usage(stdout, rc_twopass_args);
+    fprintf(stderr, "\nKeyframe Placement Options:\n");
+    arg_show_usage(stdout, kf_args);
+#if CONFIG_VP8_ENCODER
+    fprintf(stderr, "\nVP8 Specific Options:\n");
+    arg_show_usage(stdout, vp8_args);
+#endif
+    fprintf(stderr, "\nStream timebase (--timebase):\n"
+            "  The desired precision of timestamps in the output, expressed\n"
+            "  in fractional seconds. Default is 1/1000.\n");
+    fprintf(stderr, "\n"
+           "Included encoders:\n"
+           "\n");
+
+    for (i = 0; i < sizeof(codecs) / sizeof(codecs[0]); i++)
+        fprintf(stderr, "    %-6s - %s\n",
+               codecs[i].name,
+               vpx_codec_iface_name(codecs[i].iface));
+
+    exit(EXIT_FAILURE);
+}
+
+
+#define HIST_BAR_MAX 40
+struct hist_bucket
+{
+    int low, high, count;
+};
+
+
+static int merge_hist_buckets(struct hist_bucket *bucket,
+                              int *buckets_,
+                              int max_buckets)
+{
+    int small_bucket = 0, merge_bucket = INT_MAX, big_bucket=0;
+    int buckets = *buckets_;
+    int i;
+
+    /* Find the extrema for this list of buckets */
+    big_bucket = small_bucket = 0;
+    for(i=0; i < buckets; i++)
+    {
+        if(bucket[i].count < bucket[small_bucket].count)
+            small_bucket = i;
+        if(bucket[i].count > bucket[big_bucket].count)
+            big_bucket = i;
+    }
+
+    /* If we have too many buckets, merge the smallest with an adjacent
+     * bucket.
+     */
+    while(buckets > max_buckets)
+    {
+        int last_bucket = buckets - 1;
+
+        // merge the small bucket with an adjacent one.
+        if(small_bucket == 0)
+            merge_bucket = 1;
+        else if(small_bucket == last_bucket)
+            merge_bucket = last_bucket - 1;
+        else if(bucket[small_bucket - 1].count < bucket[small_bucket + 1].count)
+            merge_bucket = small_bucket - 1;
+        else
+            merge_bucket = small_bucket + 1;
+
+        assert(abs(merge_bucket - small_bucket) <= 1);
+        assert(small_bucket < buckets);
+        assert(big_bucket < buckets);
+        assert(merge_bucket < buckets);
+
+        if(merge_bucket < small_bucket)
+        {
+            bucket[merge_bucket].high = bucket[small_bucket].high;
+            bucket[merge_bucket].count += bucket[small_bucket].count;
+        }
+        else
+        {
+            bucket[small_bucket].high = bucket[merge_bucket].high;
+            bucket[small_bucket].count += bucket[merge_bucket].count;
+            merge_bucket = small_bucket;
+        }
+
+        assert(bucket[merge_bucket].low != bucket[merge_bucket].high);
+
+        buckets--;
+
+        /* Remove the merge_bucket from the list, and find the new small
+         * and big buckets while we're at it
+         */
+        big_bucket = small_bucket = 0;
+        for(i=0; i < buckets; i++)
+        {
+            if(i > merge_bucket)
+                bucket[i] = bucket[i+1];
+
+            if(bucket[i].count < bucket[small_bucket].count)
+                small_bucket = i;
+            if(bucket[i].count > bucket[big_bucket].count)
+                big_bucket = i;
+        }
+
+    }
+
+    *buckets_ = buckets;
+    return bucket[big_bucket].count;
+}
+
+
+static void show_histogram(const struct hist_bucket *bucket,
+                           int                       buckets,
+                           int                       total,
+                           int                       scale)
+{
+    const char *pat1, *pat2;
+    int i;
+
+    switch((int)(log(bucket[buckets-1].high)/log(10))+1)
+    {
+        case 1:
+        case 2:
+            pat1 = "%4d %2s: ";
+            pat2 = "%4d-%2d: ";
+            break;
+        case 3:
+            pat1 = "%5d %3s: ";
+            pat2 = "%5d-%3d: ";
+            break;
+        case 4:
+            pat1 = "%6d %4s: ";
+            pat2 = "%6d-%4d: ";
+            break;
+        case 5:
+            pat1 = "%7d %5s: ";
+            pat2 = "%7d-%5d: ";
+            break;
+        case 6:
+            pat1 = "%8d %6s: ";
+            pat2 = "%8d-%6d: ";
+            break;
+        case 7:
+            pat1 = "%9d %7s: ";
+            pat2 = "%9d-%7d: ";
+            break;
+        default:
+            pat1 = "%12d %10s: ";
+            pat2 = "%12d-%10d: ";
+            break;
+    }
+
+    for(i=0; i<buckets; i++)
+    {
+        int len;
+        int j;
+        float pct;
+
+        pct = 100.0 * (float)bucket[i].count / (float)total;
+        len = HIST_BAR_MAX * bucket[i].count / scale;
+        if(len < 1)
+            len = 1;
+        assert(len <= HIST_BAR_MAX);
+
+        if(bucket[i].low == bucket[i].high)
+            fprintf(stderr, pat1, bucket[i].low, "");
+        else
+            fprintf(stderr, pat2, bucket[i].low, bucket[i].high);
+
+        for(j=0; j<HIST_BAR_MAX; j++)
+            fprintf(stderr, j<len?"=":" ");
+        fprintf(stderr, "\t%5d (%6.2f%%)\n",bucket[i].count,pct);
+    }
+}
+
+
+static void show_q_histogram(const int counts[64], int max_buckets)
+{
+    struct hist_bucket bucket[64];
+    int buckets = 0;
+    int total = 0;
+    int scale;
+    int i;
+
+
+    for(i=0; i<64; i++)
+    {
+        if(counts[i])
+        {
+            bucket[buckets].low = bucket[buckets].high = i;
+            bucket[buckets].count = counts[i];
+            buckets++;
+            total += counts[i];
+        }
+    }
+
+    fprintf(stderr, "\nQuantizer Selection:\n");
+    scale = merge_hist_buckets(bucket, &buckets, max_buckets);
+    show_histogram(bucket, buckets, total, scale);
+}
+
+
+#define RATE_BINS (100)
+struct rate_hist
+{
+    int64_t            *pts;
+    int                *sz;
+    int                 samples;
+    int                 frames;
+    struct hist_bucket  bucket[RATE_BINS];
+    int                 total;
+};
+
+
+static void init_rate_histogram(struct rate_hist          *hist,
+                                const vpx_codec_enc_cfg_t *cfg,
+                                const vpx_rational_t      *fps)
+{
+    int i;
+
+    /* Determine the number of samples in the buffer. Use the file's framerate
+     * to determine the number of frames in rc_buf_sz milliseconds, with an
+     * adjustment (5/4) to account for alt-refs
+     */
+    hist->samples = cfg->rc_buf_sz * 5 / 4 * fps->num / fps->den / 1000;
+
+    // prevent division by zero
+    if (hist->samples == 0)
+      hist->samples=1;
+
+    hist->pts = calloc(hist->samples, sizeof(*hist->pts));
+    hist->sz = calloc(hist->samples, sizeof(*hist->sz));
+    for(i=0; i<RATE_BINS; i++)
+    {
+        hist->bucket[i].low = INT_MAX;
+        hist->bucket[i].high = 0;
+        hist->bucket[i].count = 0;
+    }
+}
+
+
+static void destroy_rate_histogram(struct rate_hist *hist)
+{
+    free(hist->pts);
+    free(hist->sz);
+}
+
+
+static void update_rate_histogram(struct rate_hist          *hist,
+                                  const vpx_codec_enc_cfg_t *cfg,
+                                  const vpx_codec_cx_pkt_t  *pkt)
+{
+    int i, idx;
+    int64_t now, then, sum_sz = 0, avg_bitrate;
+
+    now = pkt->data.frame.pts * 1000
+          * (uint64_t)cfg->g_timebase.num / (uint64_t)cfg->g_timebase.den;
+
+    idx = hist->frames++ % hist->samples;
+    hist->pts[idx] = now;
+    hist->sz[idx] = pkt->data.frame.sz;
+
+    if(now < cfg->rc_buf_initial_sz)
+        return;
+
+    then = now;
+
+    /* Sum the size over the past rc_buf_sz ms */
+    for(i = hist->frames; i > 0 && hist->frames - i < hist->samples; i--)
+    {
+        int i_idx = (i-1) % hist->samples;
+
+        then = hist->pts[i_idx];
+        if(now - then > cfg->rc_buf_sz)
+            break;
+        sum_sz += hist->sz[i_idx];
+    }
+
+    if (now == then)
+        return;
+
+    avg_bitrate = sum_sz * 8 * 1000 / (now - then);
+    idx = avg_bitrate * (RATE_BINS/2) / (cfg->rc_target_bitrate * 1000);
+    if(idx < 0)
+        idx = 0;
+    if(idx > RATE_BINS-1)
+        idx = RATE_BINS-1;
+    if(hist->bucket[idx].low > avg_bitrate)
+        hist->bucket[idx].low = avg_bitrate;
+    if(hist->bucket[idx].high < avg_bitrate)
+        hist->bucket[idx].high = avg_bitrate;
+    hist->bucket[idx].count++;
+    hist->total++;
+}
+
+
+static void show_rate_histogram(struct rate_hist          *hist,
+                                const vpx_codec_enc_cfg_t *cfg,
+                                int                        max_buckets)
+{
+    int i, scale;
+    int buckets = 0;
+
+    for(i = 0; i < RATE_BINS; i++)
+    {
+        if(hist->bucket[i].low == INT_MAX)
+            continue;
+        hist->bucket[buckets++] = hist->bucket[i];
+    }
+
+    fprintf(stderr, "\nRate (over %dms window):\n", cfg->rc_buf_sz);
+    scale = merge_hist_buckets(hist->bucket, &buckets, max_buckets);
+    show_histogram(hist->bucket, buckets, hist->total, scale);
+}
+
+#define NELEMENTS(x) (sizeof(x)/sizeof(x[0]))
+#define ARG_CTRL_CNT_MAX NELEMENTS(vp8_arg_ctrl_map)
+
+
+/* Configuration elements common to all streams */
+struct global_config
+{
+    const struct codec_item  *codec;
+    int                       passes;
+    int                       pass;
+    int                       usage;
+    int                       deadline;
+    int                       use_i420;
+    int                       verbose;
+    int                       limit;
+    int                       show_psnr;
+    int                       have_framerate;
+    struct vpx_rational       framerate;
+    int                       out_part;
+    int                       debug;
+    int                       show_q_hist_buckets;
+    int                       show_rate_hist_buckets;
+};
+
+
+/* Per-stream configuration */
+struct stream_config
+{
+    struct vpx_codec_enc_cfg  cfg;
+    const char               *out_fn;
+    const char               *stats_fn;
+    stereo_format_t           stereo_fmt;
+    int                       arg_ctrls[ARG_CTRL_CNT_MAX][2];
+    int                       arg_ctrl_cnt;
+    int                       write_webm;
+    int                       have_kf_max_dist;
+};
+
+
+struct stream_state
+{
+    int                       index;
+    struct stream_state      *next;
+    struct stream_config      config;
+    FILE                     *file;
+    struct rate_hist          rate_hist;
+    EbmlGlobal                ebml;
+    uint32_t                  hash;
+    uint64_t                  psnr_sse_total;
+    uint64_t                  psnr_samples_total;
+    double                    psnr_totals[4];
+    int                       psnr_count;
+    int                       counts[64];
+    vpx_codec_ctx_t           encoder;
+    unsigned int              frames_out;
+    uint64_t                  cx_time;
+    size_t                    nbytes;
+    stats_io_t                stats;
+};
+
+
+void validate_positive_rational(const char          *msg,
+                                struct vpx_rational *rat)
+{
+    if (rat->den < 0)
+    {
+        rat->num *= -1;
+        rat->den *= -1;
+    }
+
+    if (rat->num < 0)
+        die("Error: %s must be positive\n", msg);
+
+    if (!rat->den)
+        die("Error: %s has zero denominator\n", msg);
+}
+
+
+static void parse_global_config(struct global_config *global, char **argv)
+{
+    char       **argi, **argj;
+    struct arg   arg;
+
+    /* Initialize default parameters */
+    memset(global, 0, sizeof(*global));
+    global->codec = codecs;
+    global->passes = 1;
+    global->use_i420 = 1;
+
+    for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step)
+    {
+        arg.argv_step = 1;
+
+        if (arg_match(&arg, &codecarg, argi))
+        {
+            int j, k = -1;
+
+            for (j = 0; j < sizeof(codecs) / sizeof(codecs[0]); j++)
+                if (!strcmp(codecs[j].name, arg.val))
+                    k = j;
+
+            if (k >= 0)
+                global->codec = codecs + k;
+            else
+                die("Error: Unrecognized argument (%s) to --codec\n",
+                    arg.val);
+
+        }
+        else if (arg_match(&arg, &passes, argi))
+        {
+            global->passes = arg_parse_uint(&arg);
+
+            if (global->passes < 1 || global->passes > 2)
+                die("Error: Invalid number of passes (%d)\n", global->passes);
+        }
+        else if (arg_match(&arg, &pass_arg, argi))
+        {
+            global->pass = arg_parse_uint(&arg);
+
+            if (global->pass < 1 || global->pass > 2)
+                die("Error: Invalid pass selected (%d)\n",
+                    global->pass);
+        }
+        else if (arg_match(&arg, &usage, argi))
+            global->usage = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &deadline, argi))
+            global->deadline = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &best_dl, argi))
+            global->deadline = VPX_DL_BEST_QUALITY;
+        else if (arg_match(&arg, &good_dl, argi))
+            global->deadline = VPX_DL_GOOD_QUALITY;
+        else if (arg_match(&arg, &rt_dl, argi))
+            global->deadline = VPX_DL_REALTIME;
+        else if (arg_match(&arg, &use_yv12, argi))
+            global->use_i420 = 0;
+        else if (arg_match(&arg, &use_i420, argi))
+            global->use_i420 = 1;
+        else if (arg_match(&arg, &verbosearg, argi))
+            global->verbose = 1;
+        else if (arg_match(&arg, &limit, argi))
+            global->limit = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &psnrarg, argi))
+            global->show_psnr = 1;
+        else if (arg_match(&arg, &framerate, argi))
+        {
+            global->framerate = arg_parse_rational(&arg);
+            validate_positive_rational(arg.name, &global->framerate);
+            global->have_framerate = 1;
+        }
+        else if (arg_match(&arg,&out_part, argi))
+            global->out_part = 1;
+        else if (arg_match(&arg, &debugmode, argi))
+            global->debug = 1;
+        else if (arg_match(&arg, &q_hist_n, argi))
+            global->show_q_hist_buckets = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &rate_hist_n, argi))
+            global->show_rate_hist_buckets = arg_parse_uint(&arg);
+        else
+            argj++;
+    }
+
+    /* Validate global config */
+
+    if (global->pass)
+    {
+        /* DWIM: Assume the user meant passes=2 if pass=2 is specified */
+        if (global->pass > global->passes)
+        {
+            warn("Assuming --pass=%d implies --passes=%d\n",
+                 global->pass, global->pass);
+            global->passes = global->pass;
+        }
+    }
+}
+
+
+void open_input_file(struct input_state *input)
+{
+    unsigned int fourcc;
+
+    /* Parse certain options from the input file, if possible */
+    input->file = strcmp(input->fn, "-") ? fopen(input->fn, "rb")
+                                         : set_binary_mode(stdin);
+
+    if (!input->file)
+        fatal("Failed to open input file");
+
+    /* For RAW input sources, these bytes will applied on the first frame
+     *  in read_frame().
+     */
+    input->detect.buf_read = fread(input->detect.buf, 1, 4, input->file);
+    input->detect.position = 0;
+
+    if (input->detect.buf_read == 4
+        && file_is_y4m(input->file, &input->y4m, input->detect.buf))
+    {
+        if (y4m_input_open(&input->y4m, input->file, input->detect.buf, 4) >= 0)
+        {
+            input->file_type = FILE_TYPE_Y4M;
+            input->w = input->y4m.pic_w;
+            input->h = input->y4m.pic_h;
+            input->framerate.num = input->y4m.fps_n;
+            input->framerate.den = input->y4m.fps_d;
+            input->use_i420 = 0;
+        }
+        else
+            fatal("Unsupported Y4M stream.");
+    }
+    else if (input->detect.buf_read == 4 && file_is_ivf(input, &fourcc))
+    {
+        input->file_type = FILE_TYPE_IVF;
+        switch (fourcc)
+        {
+        case 0x32315659:
+            input->use_i420 = 0;
+            break;
+        case 0x30323449:
+            input->use_i420 = 1;
+            break;
+        default:
+            fatal("Unsupported fourcc (%08x) in IVF", fourcc);
+        }
+    }
+    else
+    {
+        input->file_type = FILE_TYPE_RAW;
+    }
+}
+
+
+static void close_input_file(struct input_state *input)
+{
+    fclose(input->file);
+    if (input->file_type == FILE_TYPE_Y4M)
+        y4m_input_close(&input->y4m);
+}
+
+static struct stream_state *new_stream(struct global_config *global,
+                                       struct stream_state  *prev)
+{
+    struct stream_state *stream;
+
+    stream = calloc(1, sizeof(*stream));
+    if(!stream)
+        fatal("Failed to allocate new stream.");
+    if(prev)
+    {
+        memcpy(stream, prev, sizeof(*stream));
+        stream->index++;
+        prev->next = stream;
+    }
+    else
+    {
+        vpx_codec_err_t  res;
+
+        /* Populate encoder configuration */
+        res = vpx_codec_enc_config_default(global->codec->iface,
+                                           &stream->config.cfg,
+                                           global->usage);
+        if (res)
+            fatal("Failed to get config: %s\n", vpx_codec_err_to_string(res));
+
+        /* Change the default timebase to a high enough value so that the
+         * encoder will always create strictly increasing timestamps.
+         */
+        stream->config.cfg.g_timebase.den = 1000;
+
+        /* Never use the library's default resolution, require it be parsed
+         * from the file or set on the command line.
+         */
+        stream->config.cfg.g_w = 0;
+        stream->config.cfg.g_h = 0;
+
+        /* Initialize remaining stream parameters */
+        stream->config.stereo_fmt = STEREO_FORMAT_MONO;
+        stream->config.write_webm = 1;
+        stream->ebml.last_pts_ms = -1;
+
+        /* Allows removal of the application version from the EBML tags */
+        stream->ebml.debug = global->debug;
+    }
+
+    /* Output files must be specified for each stream */
+    stream->config.out_fn = NULL;
+
+    stream->next = NULL;
+    return stream;
+}
+
+
+static int parse_stream_params(struct global_config *global,
+                               struct stream_state  *stream,
+                               char **argv)
+{
+    char                   **argi, **argj;
+    struct arg               arg;
+    static const arg_def_t **ctrl_args = no_args;
+    static const int        *ctrl_args_map = NULL;
+    struct stream_config    *config = &stream->config;
+    int                      eos_mark_found = 0;
+
+    /* Handle codec specific options */
+    if (global->codec->iface == &vpx_codec_vp8_cx_algo)
+    {
+        ctrl_args = vp8_args;
+        ctrl_args_map = vp8_arg_ctrl_map;
+    }
+
+    for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step)
+    {
+        arg.argv_step = 1;
+
+        /* Once we've found an end-of-stream marker (--) we want to continue
+         * shifting arguments but not consuming them.
+         */
+        if (eos_mark_found)
+        {
+            argj++;
+            continue;
+        }
+        else if (!strcmp(*argj, "--"))
+        {
+            eos_mark_found = 1;
+            continue;
+        }
+
+        if (0);
+        else if (arg_match(&arg, &outputfile, argi))
+            config->out_fn = arg.val;
+        else if (arg_match(&arg, &fpf_name, argi))
+            config->stats_fn = arg.val;
+        else if (arg_match(&arg, &use_ivf, argi))
+            config->write_webm = 0;
+        else if (arg_match(&arg, &threads, argi))
+            config->cfg.g_threads = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &profile, argi))
+            config->cfg.g_profile = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &width, argi))
+            config->cfg.g_w = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &height, argi))
+            config->cfg.g_h = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &stereo_mode, argi))
+            config->stereo_fmt = arg_parse_enum_or_int(&arg);
+        else if (arg_match(&arg, &timebase, argi))
+        {
+            config->cfg.g_timebase = arg_parse_rational(&arg);
+            validate_positive_rational(arg.name, &config->cfg.g_timebase);
+        }
+        else if (arg_match(&arg, &error_resilient, argi))
+            config->cfg.g_error_resilient = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &lag_in_frames, argi))
+            config->cfg.g_lag_in_frames = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &dropframe_thresh, argi))
+            config->cfg.rc_dropframe_thresh = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &resize_allowed, argi))
+            config->cfg.rc_resize_allowed = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &resize_up_thresh, argi))
+            config->cfg.rc_resize_up_thresh = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &resize_down_thresh, argi))
+            config->cfg.rc_resize_down_thresh = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &end_usage, argi))
+            config->cfg.rc_end_usage = arg_parse_enum_or_int(&arg);
+        else if (arg_match(&arg, &target_bitrate, argi))
+            config->cfg.rc_target_bitrate = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &min_quantizer, argi))
+            config->cfg.rc_min_quantizer = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &max_quantizer, argi))
+            config->cfg.rc_max_quantizer = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &undershoot_pct, argi))
+            config->cfg.rc_undershoot_pct = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &overshoot_pct, argi))
+            config->cfg.rc_overshoot_pct = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &buf_sz, argi))
+            config->cfg.rc_buf_sz = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &buf_initial_sz, argi))
+            config->cfg.rc_buf_initial_sz = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &buf_optimal_sz, argi))
+            config->cfg.rc_buf_optimal_sz = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &bias_pct, argi))
+        {
+            config->cfg.rc_2pass_vbr_bias_pct = arg_parse_uint(&arg);
+
+            if (global->passes < 2)
+                warn("option %s ignored in one-pass mode.\n", arg.name);
+        }
+        else if (arg_match(&arg, &minsection_pct, argi))
+        {
+            config->cfg.rc_2pass_vbr_minsection_pct = arg_parse_uint(&arg);
+
+            if (global->passes < 2)
+                warn("option %s ignored in one-pass mode.\n", arg.name);
+        }
+        else if (arg_match(&arg, &maxsection_pct, argi))
+        {
+            config->cfg.rc_2pass_vbr_maxsection_pct = arg_parse_uint(&arg);
+
+            if (global->passes < 2)
+                warn("option %s ignored in one-pass mode.\n", arg.name);
+        }
+        else if (arg_match(&arg, &kf_min_dist, argi))
+            config->cfg.kf_min_dist = arg_parse_uint(&arg);
+        else if (arg_match(&arg, &kf_max_dist, argi))
+        {
+            config->cfg.kf_max_dist = arg_parse_uint(&arg);
+            config->have_kf_max_dist = 1;
+        }
+        else if (arg_match(&arg, &kf_disabled, argi))
+            config->cfg.kf_mode = VPX_KF_DISABLED;
+        else
+        {
+            int i, match = 0;
+
+            for (i = 0; ctrl_args[i]; i++)
+            {
+                if (arg_match(&arg, ctrl_args[i], argi))
+                {
+                    int j;
+                    match = 1;
+
+                    /* Point either to the next free element or the first
+                    * instance of this control.
+                    */
+                    for(j=0; j<config->arg_ctrl_cnt; j++)
+                        if(config->arg_ctrls[j][0] == ctrl_args_map[i])
+                            break;
+
+                    /* Update/insert */
+                    assert(j < ARG_CTRL_CNT_MAX);
+                    if (j < ARG_CTRL_CNT_MAX)
+                    {
+                        config->arg_ctrls[j][0] = ctrl_args_map[i];
+                        config->arg_ctrls[j][1] = arg_parse_enum_or_int(&arg);
+                        if(j == config->arg_ctrl_cnt)
+                            config->arg_ctrl_cnt++;
+                    }
+
+                }
+            }
+
+            if (!match)
+                argj++;
+        }
+    }
+
+    return eos_mark_found;
+}
+
+
+#define FOREACH_STREAM(func)\
+do\
+{\
+    struct stream_state  *stream;\
+\
+    for(stream = streams; stream; stream = stream->next)\
+        func;\
+}while(0)
+
+
+static void validate_stream_config(struct stream_state *stream)
+{
+    struct stream_state *streami;
+
+    if(!stream->config.cfg.g_w || !stream->config.cfg.g_h)
+        fatal("Stream %d: Specify stream dimensions with --width (-w) "
+              " and --height (-h)", stream->index);
+
+    for(streami = stream; streami; streami = streami->next)
+    {
+        /* All streams require output files */
+        if(!streami->config.out_fn)
+            fatal("Stream %d: Output file is required (specify with -o)",
+                  streami->index);
+
+        /* Check for two streams outputting to the same file */
+        if(streami != stream)
+        {
+            const char *a = stream->config.out_fn;
+            const char *b = streami->config.out_fn;
+            if(!strcmp(a,b) && strcmp(a, "/dev/null") && strcmp(a, ":nul"))
+                fatal("Stream %d: duplicate output file (from stream %d)",
+                      streami->index, stream->index);
+        }
+
+        /* Check for two streams sharing a stats file. */
+        if(streami != stream)
+        {
+            const char *a = stream->config.stats_fn;
+            const char *b = streami->config.stats_fn;
+            if(a && b && !strcmp(a,b))
+                fatal("Stream %d: duplicate stats file (from stream %d)",
+                      streami->index, stream->index);
+        }
+    }
+}
+
+
+static void set_stream_dimensions(struct stream_state *stream,
+                                  unsigned int w,
+                                  unsigned int h)
+{
+    if ((stream->config.cfg.g_w && stream->config.cfg.g_w != w)
+        ||(stream->config.cfg.g_h && stream->config.cfg.g_h != h))
+        fatal("Stream %d: Resizing not yet supported", stream->index);
+    stream->config.cfg.g_w = w;
+    stream->config.cfg.g_h = h;
+}
+
+
+static void set_default_kf_interval(struct stream_state  *stream,
+                                    struct global_config *global)
+{
+    /* Use a max keyframe interval of 5 seconds, if none was
+     * specified on the command line.
+     */
+    if (!stream->config.have_kf_max_dist)
+    {
+        double framerate = (double)global->framerate.num/global->framerate.den;
+        if (framerate > 0.0)
+            stream->config.cfg.kf_max_dist = 5.0*framerate;
+    }
+}
+
+
+static void show_stream_config(struct stream_state  *stream,
+                               struct global_config *global,
+                               struct input_state   *input)
+{
+
+#define SHOW(field) \
+    fprintf(stderr, "    %-28s = %d\n", #field, stream->config.cfg.field)
+
+    if(stream->index == 0)
+    {
+        fprintf(stderr, "Codec: %s\n",
+                vpx_codec_iface_name(global->codec->iface));
+        fprintf(stderr, "Source file: %s Format: %s\n", input->fn,
+                input->use_i420 ? "I420" : "YV12");
+    }
+    if(stream->next || stream->index)
+        fprintf(stderr, "\nStream Index: %d\n", stream->index);
+    fprintf(stderr, "Destination file: %s\n", stream->config.out_fn);
+    fprintf(stderr, "Encoder parameters:\n");
+
+    SHOW(g_usage);
+    SHOW(g_threads);
+    SHOW(g_profile);
+    SHOW(g_w);
+    SHOW(g_h);
+    SHOW(g_timebase.num);
+    SHOW(g_timebase.den);
+    SHOW(g_error_resilient);
+    SHOW(g_pass);
+    SHOW(g_lag_in_frames);
+    SHOW(rc_dropframe_thresh);
+    SHOW(rc_resize_allowed);
+    SHOW(rc_resize_up_thresh);
+    SHOW(rc_resize_down_thresh);
+    SHOW(rc_end_usage);
+    SHOW(rc_target_bitrate);
+    SHOW(rc_min_quantizer);
+    SHOW(rc_max_quantizer);
+    SHOW(rc_undershoot_pct);
+    SHOW(rc_overshoot_pct);
+    SHOW(rc_buf_sz);
+    SHOW(rc_buf_initial_sz);
+    SHOW(rc_buf_optimal_sz);
+    SHOW(rc_2pass_vbr_bias_pct);
+    SHOW(rc_2pass_vbr_minsection_pct);
+    SHOW(rc_2pass_vbr_maxsection_pct);
+    SHOW(kf_mode);
+    SHOW(kf_min_dist);
+    SHOW(kf_max_dist);
+}
+
+
+static void open_output_file(struct stream_state *stream,
+                             struct global_config *global)
+{
+    const char *fn = stream->config.out_fn;
+
+    stream->file = strcmp(fn, "-") ? fopen(fn, "wb") : set_binary_mode(stdout);
+
+    if (!stream->file)
+        fatal("Failed to open output file");
+
+    if(stream->config.write_webm && fseek(stream->file, 0, SEEK_CUR))
+        fatal("WebM output to pipes not supported.");
+
+    if(stream->config.write_webm)
+    {
+        stream->ebml.stream = stream->file;
+        write_webm_file_header(&stream->ebml, &stream->config.cfg,
+                               &global->framerate,
+                               stream->config.stereo_fmt);
+    }
+    else
+        write_ivf_file_header(stream->file, &stream->config.cfg,
+                              global->codec->fourcc, 0);
+}
+
+
+static void close_output_file(struct stream_state *stream,
+                              unsigned int         fourcc)
+{
+    if(stream->config.write_webm)
+    {
+        write_webm_file_footer(&stream->ebml, stream->hash);
+        free(stream->ebml.cue_list);
+        stream->ebml.cue_list = NULL;
+    }
+    else
+    {
+        if (!fseek(stream->file, 0, SEEK_SET))
+            write_ivf_file_header(stream->file, &stream->config.cfg,
+                                  fourcc,
+                                  stream->frames_out);
+    }
+
+    fclose(stream->file);
+}
+
+
+static void setup_pass(struct stream_state  *stream,
+                       struct global_config *global,
+                       int                   pass)
+{
+    if (stream->config.stats_fn)
+    {
+        if (!stats_open_file(&stream->stats, stream->config.stats_fn,
+                             pass))
+            fatal("Failed to open statistics store");
+    }
+    else
+    {
+        if (!stats_open_mem(&stream->stats, pass))
+            fatal("Failed to open statistics store");
+    }
+
+    stream->config.cfg.g_pass = global->passes == 2
+        ? pass ? VPX_RC_LAST_PASS : VPX_RC_FIRST_PASS
+        : VPX_RC_ONE_PASS;
+    if (pass)
+        stream->config.cfg.rc_twopass_stats_in = stats_get(&stream->stats);
+
+    stream->cx_time = 0;
+    stream->nbytes = 0;
+    stream->frames_out = 0;
+}
+
+
+static void initialize_encoder(struct stream_state  *stream,
+                               struct global_config *global)
+{
+    int i;
+    int flags = 0;
+
+    flags |= global->show_psnr ? VPX_CODEC_USE_PSNR : 0;
+    flags |= global->out_part ? VPX_CODEC_USE_OUTPUT_PARTITION : 0;
+
+    /* Construct Encoder Context */
+    vpx_codec_enc_init(&stream->encoder, global->codec->iface,
+                        &stream->config.cfg, flags);
+    ctx_exit_on_error(&stream->encoder, "Failed to initialize encoder");
+
+    /* Note that we bypass the vpx_codec_control wrapper macro because
+     * we're being clever to store the control IDs in an array. Real
+     * applications will want to make use of the enumerations directly
+     */
+    for (i = 0; i < stream->config.arg_ctrl_cnt; i++)
+    {
+        int ctrl = stream->config.arg_ctrls[i][0];
+        int value = stream->config.arg_ctrls[i][1];
+        if (vpx_codec_control_(&stream->encoder, ctrl, value))
+            fprintf(stderr, "Error: Tried to set control %d = %d\n",
+                    ctrl, value);
+
+        ctx_exit_on_error(&stream->encoder, "Failed to control codec");
+    }
+}
+
+
+static void encode_frame(struct stream_state  *stream,
+                         struct global_config *global,
+                         struct vpx_image     *img,
+                         unsigned int          frames_in)
+{
+    vpx_codec_pts_t frame_start, next_frame_start;
+    struct vpx_codec_enc_cfg *cfg = &stream->config.cfg;
+    struct vpx_usec_timer timer;
+
+    frame_start = (cfg->g_timebase.den * (int64_t)(frames_in - 1)
+                  * global->framerate.den)
+                  / cfg->g_timebase.num / global->framerate.num;
+    next_frame_start = (cfg->g_timebase.den * (int64_t)(frames_in)
+                        * global->framerate.den)
+                        / cfg->g_timebase.num / global->framerate.num;
+    vpx_usec_timer_start(&timer);
+    vpx_codec_encode(&stream->encoder, img, frame_start,
+                     next_frame_start - frame_start,
+                     0, global->deadline);
+    vpx_usec_timer_mark(&timer);
+    stream->cx_time += vpx_usec_timer_elapsed(&timer);
+    ctx_exit_on_error(&stream->encoder, "Stream %d: Failed to encode frame",
+                      stream->index);
+}
+
+
+static void update_quantizer_histogram(struct stream_state *stream)
+{
+    if(stream->config.cfg.g_pass != VPX_RC_FIRST_PASS)
+    {
+        int q;
+
+        vpx_codec_control(&stream->encoder, VP8E_GET_LAST_QUANTIZER_64, &q);
+        ctx_exit_on_error(&stream->encoder, "Failed to read quantizer");
+        stream->counts[q]++;
+    }
+}
+
+
+static void get_cx_data(struct stream_state  *stream,
+                        struct global_config *global,
+                        int                  *got_data)
+{
+    const vpx_codec_cx_pkt_t *pkt;
+    const struct vpx_codec_enc_cfg *cfg = &stream->config.cfg;
+    vpx_codec_iter_t iter = NULL;
+
+    while ((pkt = vpx_codec_get_cx_data(&stream->encoder, &iter)))
+    {
+        static size_t fsize = 0;
+        static off_t ivf_header_pos = 0;
+
+        *got_data = 1;
+
+        switch (pkt->kind)
+        {
+        case VPX_CODEC_CX_FRAME_PKT:
+            if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT))
+            {
+                stream->frames_out++;
+            }
+            fprintf(stderr, " %6luF",
+                    (unsigned long)pkt->data.frame.sz);
+
+            update_rate_histogram(&stream->rate_hist, cfg, pkt);
+            if(stream->config.write_webm)
+            {
+                /* Update the hash */
+                if(!stream->ebml.debug)
+                    stream->hash = murmur(pkt->data.frame.buf,
+                                          pkt->data.frame.sz, stream->hash);
+
+                write_webm_block(&stream->ebml, cfg, pkt);
+            }
+            else
+            {
+                if (pkt->data.frame.partition_id <= 0)
+                {
+                    ivf_header_pos = ftello(stream->file);
+                    fsize = pkt->data.frame.sz;
+
+                    write_ivf_frame_header(stream->file, pkt);
+                }
+                else
+                {
+                    fsize += pkt->data.frame.sz;
+
+                    if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT))
+                    {
+                        off_t currpos = ftello(stream->file);
+                        fseeko(stream->file, ivf_header_pos, SEEK_SET);
+                        write_ivf_frame_size(stream->file, fsize);
+                        fseeko(stream->file, currpos, SEEK_SET);
+                    }
+                }
+
+                fwrite(pkt->data.frame.buf, 1,
+                       pkt->data.frame.sz, stream->file);
+            }
+            stream->nbytes += pkt->data.raw.sz;
+            break;
+        case VPX_CODEC_STATS_PKT:
+            stream->frames_out++;
+            fprintf(stderr, " %6luS",
+                   (unsigned long)pkt->data.twopass_stats.sz);
+            stats_write(&stream->stats,
+                        pkt->data.twopass_stats.buf,
+                        pkt->data.twopass_stats.sz);
+            stream->nbytes += pkt->data.raw.sz;
+            break;
+        case VPX_CODEC_PSNR_PKT:
+
+            if (global->show_psnr)
+            {
+                int i;
+
+                stream->psnr_sse_total += pkt->data.psnr.sse[0];
+                stream->psnr_samples_total += pkt->data.psnr.samples[0];
+                for (i = 0; i < 4; i++)
+                {
+                    fprintf(stderr, "%.3lf ", pkt->data.psnr.psnr[i]);
+                    stream->psnr_totals[i] += pkt->data.psnr.psnr[i];
+                }
+                stream->psnr_count++;
+            }
+
+            break;
+        default:
+            break;
+        }
+    }
+}
+
+
+static void show_psnr(struct stream_state  *stream)
+{
+    int i;
+    double ovpsnr;
+
+    if (!stream->psnr_count)
+        return;
+
+    fprintf(stderr, "Stream %d PSNR (Overall/Avg/Y/U/V)", stream->index);
+    ovpsnr = vp8_mse2psnr(stream->psnr_samples_total, 255.0,
+                          stream->psnr_sse_total);
+    fprintf(stderr, " %.3lf", ovpsnr);
+
+    for (i = 0; i < 4; i++)
+    {
+        fprintf(stderr, " %.3lf", stream->psnr_totals[i]/stream->psnr_count);
+    }
+    fprintf(stderr, "\n");
+}
+
+
+float usec_to_fps(uint64_t usec, unsigned int frames)
+{
+    return usec > 0 ? (float)frames * 1000000.0 / (float)usec : 0;
+}
+
+
+int main(int argc, const char **argv_)
+{
+    int                    pass;
+    vpx_image_t            raw;
+    int                    frame_avail, got_data;
+
+    struct input_state       input = {0};
+    struct global_config     global;
+    struct stream_state     *streams = NULL;
+    char                   **argv, **argi;
+    unsigned long            cx_time = 0;
+    int                      stream_cnt = 0;
+
+    exec_name = argv_[0];
+
+    if (argc < 3)
+        usage_exit();
+
+    /* Setup default input stream settings */
+    input.framerate.num = 30;
+    input.framerate.den = 1;
+    input.use_i420 = 1;
+
+    /* First parse the global configuration values, because we want to apply
+     * other parameters on top of the default configuration provided by the
+     * codec.
+     */
+    argv = argv_dup(argc - 1, argv_ + 1);
+    parse_global_config(&global, argv);
+
+    {
+        /* Now parse each stream's parameters. Using a local scope here
+         * due to the use of 'stream' as loop variable in FOREACH_STREAM
+         * loops
+         */
+        struct stream_state *stream = NULL;
+
+        do
+        {
+            stream = new_stream(&global, stream);
+            stream_cnt++;
+            if(!streams)
+                streams = stream;
+        } while(parse_stream_params(&global, stream, argv));
+    }
+
+    /* Check for unrecognized options */
+    for (argi = argv; *argi; argi++)
+        if (argi[0][0] == '-' && argi[0][1])
+            die("Error: Unrecognized option %s\n", *argi);
+
+    /* Handle non-option arguments */
+    input.fn = argv[0];
+
+    if (!input.fn)
+        usage_exit();
+
+    for (pass = global.pass ? global.pass - 1 : 0; pass < global.passes; pass++)
+    {
+        int frames_in = 0;
+
+        open_input_file(&input);
+
+        /* If the input file doesn't specify its w/h (raw files), try to get
+         * the data from the first stream's configuration.
+         */
+        if(!input.w || !input.h)
+            FOREACH_STREAM({
+                if(stream->config.cfg.g_w && stream->config.cfg.g_h)
+                {
+                    input.w = stream->config.cfg.g_w;
+                    input.h = stream->config.cfg.g_h;
+                    break;
+                }
+            });
+
+        /* Update stream configurations from the input file's parameters */
+        FOREACH_STREAM(set_stream_dimensions(stream, input.w, input.h));
+        FOREACH_STREAM(validate_stream_config(stream));
+
+        /* Ensure that --passes and --pass are consistent. If --pass is set and
+         * --passes=2, ensure --fpf was set.
+         */
+        if (global.pass && global.passes == 2)
+            FOREACH_STREAM({
+                if(!stream->config.stats_fn)
+                    die("Stream %d: Must specify --fpf when --pass=%d"
+                        " and --passes=2\n", stream->index, global.pass);
+            });
+
+
+        /* Use the frame rate from the file only if none was specified
+         * on the command-line.
+         */
+        if (!global.have_framerate)
+            global.framerate = input.framerate;
+
+        FOREACH_STREAM(set_default_kf_interval(stream, &global));
+
+        /* Show configuration */
+        if (global.verbose && pass == 0)
+            FOREACH_STREAM(show_stream_config(stream, &global, &input));
+
+        if(pass == (global.pass ? global.pass - 1 : 0)) {
+            if (input.file_type == FILE_TYPE_Y4M)
+                /*The Y4M reader does its own allocation.
+                  Just initialize this here to avoid problems if we never read any
+                   frames.*/
+                memset(&raw, 0, sizeof(raw));
+            else
+                vpx_img_alloc(&raw,
+                              input.use_i420 ? VPX_IMG_FMT_I420
+                                             : VPX_IMG_FMT_YV12,
+                              input.w, input.h, 1);
+
+            FOREACH_STREAM(init_rate_histogram(&stream->rate_hist,
+                                               &stream->config.cfg,
+                                               &global.framerate));
+        }
+
+        FOREACH_STREAM(open_output_file(stream, &global));
+        FOREACH_STREAM(setup_pass(stream, &global, pass));
+        FOREACH_STREAM(initialize_encoder(stream, &global));
+
+        frame_avail = 1;
+        got_data = 0;
+
+        while (frame_avail || got_data)
+        {
+            struct vpx_usec_timer timer;
+
+            if (!global.limit || frames_in < global.limit)
+            {
+                frame_avail = read_frame(&input, &raw);
+
+                if (frame_avail)
+                    frames_in++;
+
+                if(stream_cnt == 1)
+                    fprintf(stderr,
+                            "\rPass %d/%d frame %4d/%-4d %7"PRId64"B \033[K",
+                            pass + 1, global.passes, frames_in,
+                            streams->frames_out, (int64_t)streams->nbytes);
+                else
+                    fprintf(stderr,
+                            "\rPass %d/%d frame %4d %7lu %s (%.2f fps)\033[K",
+                            pass + 1, global.passes, frames_in,
+                            cx_time > 9999999 ? cx_time / 1000 : cx_time,
+                            cx_time > 9999999 ? "ms" : "us",
+                            usec_to_fps(cx_time, frames_in));
+
+            }
+            else
+                frame_avail = 0;
+
+            vpx_usec_timer_start(&timer);
+            FOREACH_STREAM(encode_frame(stream, &global,
+                                        frame_avail ? &raw : NULL,
+                                        frames_in));
+            vpx_usec_timer_mark(&timer);
+            cx_time += vpx_usec_timer_elapsed(&timer);
+
+            FOREACH_STREAM(update_quantizer_histogram(stream));
+
+            got_data = 0;
+            FOREACH_STREAM(get_cx_data(stream, &global, &got_data));
+
+            fflush(stdout);
+        }
+
+        if(stream_cnt > 1)
+            fprintf(stderr, "\n");
+
+        FOREACH_STREAM(fprintf(
+            stderr,
+            "\rPass %d/%d frame %4d/%-4d %7"PRId64"B %7lub/f %7"PRId64"b/s"
+            " %7"PRId64" %s (%.2f fps)\033[K\n", pass + 1,
+            global.passes, frames_in, stream->frames_out, (int64_t)stream->nbytes,
+            frames_in ? (unsigned long)(stream->nbytes * 8 / frames_in) : 0,
+            frames_in ? (int64_t)stream->nbytes * 8
+                        * (int64_t)global.framerate.num / global.framerate.den
+                        / frames_in
+                      : 0,
+            stream->cx_time > 9999999 ? stream->cx_time / 1000 : stream->cx_time,
+            stream->cx_time > 9999999 ? "ms" : "us",
+            usec_to_fps(stream->cx_time, frames_in));
+        );
+
+        if (global.show_psnr)
+            FOREACH_STREAM(show_psnr(stream));
+
+        FOREACH_STREAM(vpx_codec_destroy(&stream->encoder));
+
+        close_input_file(&input);
+
+        FOREACH_STREAM(close_output_file(stream, global.codec->fourcc));
+
+        FOREACH_STREAM(stats_close(&stream->stats, global.passes-1));
+
+        if (global.pass)
+            break;
+    }
+
+    if (global.show_q_hist_buckets)
+        FOREACH_STREAM(show_q_histogram(stream->counts,
+                                        global.show_q_hist_buckets));
+
+    if (global.show_rate_hist_buckets)
+        FOREACH_STREAM(show_rate_histogram(&stream->rate_hist,
+                                           &stream->config.cfg,
+                                           global.show_rate_hist_buckets));
+    FOREACH_STREAM(destroy_rate_histogram(&stream->rate_hist));
+
+    vpx_img_free(&raw);
+    free(argv);
+    free(streams);
+    return EXIT_SUCCESS;
+}
diff --git a/y4minput.c b/y4minput.c
new file mode 100644 (file)
index 0000000..dd51421
--- /dev/null
@@ -0,0 +1,871 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ *
+ *  Based on code from the OggTheora software codec source code,
+ *  Copyright (C) 2002-2010 The Xiph.Org Foundation and contributors.
+ */
+#include <stdlib.h>
+#include <string.h>
+#include "y4minput.h"
+
+static int y4m_parse_tags(y4m_input *_y4m,char *_tags){
+  int   got_w;
+  int   got_h;
+  int   got_fps;
+  int   got_interlace;
+  int   got_par;
+  int   got_chroma;
+  char *p;
+  char *q;
+  got_w=got_h=got_fps=got_interlace=got_par=got_chroma=0;
+  for(p=_tags;;p=q){
+    /*Skip any leading spaces.*/
+    while(*p==' ')p++;
+    /*If that's all we have, stop.*/
+    if(p[0]=='\0')break;
+    /*Find the end of this tag.*/
+    for(q=p+1;*q!='\0'&&*q!=' ';q++);
+    /*Process the tag.*/
+    switch(p[0]){
+      case 'W':{
+        if(sscanf(p+1,"%d",&_y4m->pic_w)!=1)return -1;
+        got_w=1;
+      }break;
+      case 'H':{
+        if(sscanf(p+1,"%d",&_y4m->pic_h)!=1)return -1;
+        got_h=1;
+      }break;
+      case 'F':{
+        if(sscanf(p+1,"%d:%d",&_y4m->fps_n,&_y4m->fps_d)!=2){
+          return -1;
+        }
+        got_fps=1;
+      }break;
+      case 'I':{
+        _y4m->interlace=p[1];
+        got_interlace=1;
+      }break;
+      case 'A':{
+        if(sscanf(p+1,"%d:%d",&_y4m->par_n,&_y4m->par_d)!=2){
+          return -1;
+        }
+        got_par=1;
+      }break;
+      case 'C':{
+        if(q-p>16)return -1;
+        memcpy(_y4m->chroma_type,p+1,q-p-1);
+        _y4m->chroma_type[q-p-1]='\0';
+        got_chroma=1;
+      }break;
+      /*Ignore unknown tags.*/
+    }
+  }
+  if(!got_w||!got_h||!got_fps)return -1;
+  if(!got_interlace)_y4m->interlace='?';
+  if(!got_par)_y4m->par_n=_y4m->par_d=0;
+  /*Chroma-type is not specified in older files, e.g., those generated by
+     mplayer.*/
+  if(!got_chroma)strcpy(_y4m->chroma_type,"420");
+  return 0;
+}
+
+
+
+/*All anti-aliasing filters in the following conversion functions are based on
+   one of two window functions:
+  The 6-tap Lanczos window (for down-sampling and shifts):
+   sinc(\pi*t)*sinc(\pi*t/3), |t|<3  (sinc(t)==sin(t)/t)
+   0,                         |t|>=3
+  The 4-tap Mitchell window (for up-sampling):
+   7|t|^3-12|t|^2+16/3,             |t|<1
+   -(7/3)|x|^3+12|x|^2-20|x|+32/3,  |t|<2
+   0,                               |t|>=2
+  The number of taps is intentionally kept small to reduce computational
+   overhead and limit ringing.
+
+  The taps from these filters are scaled so that their sum is 1, and the result
+   is scaled by 128 and rounded to integers to create a filter whose
+   intermediate values fit inside 16 bits.
+  Coefficients are rounded in such a way as to ensure their sum is still 128,
+   which is usually equivalent to normal rounding.
+
+  Conversions which require both horizontal and vertical filtering could
+   have these steps pipelined, for less memory consumption and better cache
+   performance, but we do them separately for simplicity.*/
+
+#define OC_MINI(_a,_b)      ((_a)>(_b)?(_b):(_a))
+#define OC_MAXI(_a,_b)      ((_a)<(_b)?(_b):(_a))
+#define OC_CLAMPI(_a,_b,_c) (OC_MAXI(_a,OC_MINI(_b,_c)))
+
+/*420jpeg chroma samples are sited like:
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |   BR  |       |   BR  |
+  |       |       |       |
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |   BR  |       |   BR  |
+  |       |       |       |
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+
+  420mpeg2 chroma samples are sited like:
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  BR      |       BR      |
+  |       |       |       |
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  BR      |       BR      |
+  |       |       |       |
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+
+  We use a resampling filter to shift the site locations one quarter pixel (at
+   the chroma plane's resolution) to the right.
+  The 4:2:2 modes look exactly the same, except there are twice as many chroma
+   lines, and they are vertically co-sited with the luma samples in both the
+   mpeg2 and jpeg cases (thus requiring no vertical resampling).*/
+static void y4m_42xmpeg2_42xjpeg_helper(unsigned char *_dst,
+ const unsigned char *_src,int _c_w,int _c_h){
+  int y;
+  int x;
+  for(y=0;y<_c_h;y++){
+    /*Filter: [4 -17 114 35 -9 1]/128, derived from a 6-tap Lanczos
+       window.*/
+    for(x=0;x<OC_MINI(_c_w,2);x++){
+      _dst[x]=(unsigned char)OC_CLAMPI(0,(4*_src[0]-17*_src[OC_MAXI(x-1,0)]+
+       114*_src[x]+35*_src[OC_MINI(x+1,_c_w-1)]-9*_src[OC_MINI(x+2,_c_w-1)]+
+       _src[OC_MINI(x+3,_c_w-1)]+64)>>7,255);
+    }
+    for(;x<_c_w-3;x++){
+      _dst[x]=(unsigned char)OC_CLAMPI(0,(4*_src[x-2]-17*_src[x-1]+
+       114*_src[x]+35*_src[x+1]-9*_src[x+2]+_src[x+3]+64)>>7,255);
+    }
+    for(;x<_c_w;x++){
+      _dst[x]=(unsigned char)OC_CLAMPI(0,(4*_src[x-2]-17*_src[x-1]+
+       114*_src[x]+35*_src[OC_MINI(x+1,_c_w-1)]-9*_src[OC_MINI(x+2,_c_w-1)]+
+       _src[_c_w-1]+64)>>7,255);
+    }
+    _dst+=_c_w;
+    _src+=_c_w;
+  }
+}
+
+/*Handles both 422 and 420mpeg2 to 422jpeg and 420jpeg, respectively.*/
+static void y4m_convert_42xmpeg2_42xjpeg(y4m_input *_y4m,unsigned char *_dst,
+ unsigned char *_aux){
+  int c_w;
+  int c_h;
+  int c_sz;
+  int pli;
+  /*Skip past the luma data.*/
+  _dst+=_y4m->pic_w*_y4m->pic_h;
+  /*Compute the size of each chroma plane.*/
+  c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
+  c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
+  c_sz=c_w*c_h;
+  for(pli=1;pli<3;pli++){
+    y4m_42xmpeg2_42xjpeg_helper(_dst,_aux,c_w,c_h);
+    _dst+=c_sz;
+    _aux+=c_sz;
+  }
+}
+
+/*This format is only used for interlaced content, but is included for
+   completeness.
+
+  420jpeg chroma samples are sited like:
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |   BR  |       |   BR  |
+  |       |       |       |
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |   BR  |       |   BR  |
+  |       |       |       |
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+
+  420paldv chroma samples are sited like:
+  YR------Y-------YR------Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+  YB------Y-------YB------Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+  YR------Y-------YR------Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+  YB------Y-------YB------Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+
+  We use a resampling filter to shift the site locations one quarter pixel (at
+   the chroma plane's resolution) to the right.
+  Then we use another filter to move the C_r location down one quarter pixel,
+   and the C_b location up one quarter pixel.*/
+static void y4m_convert_42xpaldv_42xjpeg(y4m_input *_y4m,unsigned char *_dst,
+ unsigned char *_aux){
+  unsigned char *tmp;
+  int            c_w;
+  int            c_h;
+  int            c_sz;
+  int            pli;
+  int            y;
+  int            x;
+  /*Skip past the luma data.*/
+  _dst+=_y4m->pic_w*_y4m->pic_h;
+  /*Compute the size of each chroma plane.*/
+  c_w=(_y4m->pic_w+1)/2;
+  c_h=(_y4m->pic_h+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
+  c_sz=c_w*c_h;
+  tmp=_aux+2*c_sz;
+  for(pli=1;pli<3;pli++){
+    /*First do the horizontal re-sampling.
+      This is the same as the mpeg2 case, except that after the horizontal
+       case, we need to apply a second vertical filter.*/
+    y4m_42xmpeg2_42xjpeg_helper(tmp,_aux,c_w,c_h);
+    _aux+=c_sz;
+    switch(pli){
+      case 1:{
+        /*Slide C_b up a quarter-pel.
+          This is the same filter used above, but in the other order.*/
+        for(x=0;x<c_w;x++){
+          for(y=0;y<OC_MINI(c_h,3);y++){
+            _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(tmp[0]
+             -9*tmp[OC_MAXI(y-2,0)*c_w]+35*tmp[OC_MAXI(y-1,0)*c_w]
+             +114*tmp[y*c_w]-17*tmp[OC_MINI(y+1,c_h-1)*c_w]
+             +4*tmp[OC_MINI(y+2,c_h-1)*c_w]+64)>>7,255);
+          }
+          for(;y<c_h-2;y++){
+            _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(tmp[(y-3)*c_w]
+             -9*tmp[(y-2)*c_w]+35*tmp[(y-1)*c_w]+114*tmp[y*c_w]
+             -17*tmp[(y+1)*c_w]+4*tmp[(y+2)*c_w]+64)>>7,255);
+          }
+          for(;y<c_h;y++){
+            _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(tmp[(y-3)*c_w]
+             -9*tmp[(y-2)*c_w]+35*tmp[(y-1)*c_w]+114*tmp[y*c_w]
+             -17*tmp[OC_MINI(y+1,c_h-1)*c_w]+4*tmp[(c_h-1)*c_w]+64)>>7,255);
+          }
+          _dst++;
+          tmp++;
+        }
+        _dst+=c_sz-c_w;
+        tmp-=c_w;
+      }break;
+      case 2:{
+        /*Slide C_r down a quarter-pel.
+          This is the same as the horizontal filter.*/
+        for(x=0;x<c_w;x++){
+          for(y=0;y<OC_MINI(c_h,2);y++){
+            _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(4*tmp[0]
+             -17*tmp[OC_MAXI(y-1,0)*c_w]+114*tmp[y*c_w]
+             +35*tmp[OC_MINI(y+1,c_h-1)*c_w]-9*tmp[OC_MINI(y+2,c_h-1)*c_w]
+             +tmp[OC_MINI(y+3,c_h-1)*c_w]+64)>>7,255);
+          }
+          for(;y<c_h-3;y++){
+            _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(4*tmp[(y-2)*c_w]
+             -17*tmp[(y-1)*c_w]+114*tmp[y*c_w]+35*tmp[(y+1)*c_w]
+             -9*tmp[(y+2)*c_w]+tmp[(y+3)*c_w]+64)>>7,255);
+          }
+          for(;y<c_h;y++){
+            _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(4*tmp[(y-2)*c_w]
+             -17*tmp[(y-1)*c_w]+114*tmp[y*c_w]+35*tmp[OC_MINI(y+1,c_h-1)*c_w]
+             -9*tmp[OC_MINI(y+2,c_h-1)*c_w]+tmp[(c_h-1)*c_w]+64)>>7,255);
+          }
+          _dst++;
+          tmp++;
+        }
+      }break;
+    }
+    /*For actual interlaced material, this would have to be done separately on
+       each field, and the shift amounts would be different.
+      C_r moves down 1/8, C_b up 3/8 in the top field, and C_r moves down 3/8,
+       C_b up 1/8 in the bottom field.
+      The corresponding filters would be:
+       Down 1/8 (reverse order for up): [3 -11 125 15 -4 0]/128
+       Down 3/8 (reverse order for up): [4 -19 98 56 -13 2]/128*/
+  }
+}
+
+/*Perform vertical filtering to reduce a single plane from 4:2:2 to 4:2:0.
+  This is used as a helper by several converation routines.*/
+static void y4m_422jpeg_420jpeg_helper(unsigned char *_dst,
+ const unsigned char *_src,int _c_w,int _c_h){
+  int y;
+  int x;
+  /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
+  for(x=0;x<_c_w;x++){
+    for(y=0;y<OC_MINI(_c_h,2);y+=2){
+      _dst[(y>>1)*_c_w]=OC_CLAMPI(0,(64*_src[0]
+       +78*_src[OC_MINI(1,_c_h-1)*_c_w]
+       -17*_src[OC_MINI(2,_c_h-1)*_c_w]
+       +3*_src[OC_MINI(3,_c_h-1)*_c_w]+64)>>7,255);
+    }
+    for(;y<_c_h-3;y+=2){
+      _dst[(y>>1)*_c_w]=OC_CLAMPI(0,(3*(_src[(y-2)*_c_w]+_src[(y+3)*_c_w])
+       -17*(_src[(y-1)*_c_w]+_src[(y+2)*_c_w])
+       +78*(_src[y*_c_w]+_src[(y+1)*_c_w])+64)>>7,255);
+    }
+    for(;y<_c_h;y+=2){
+      _dst[(y>>1)*_c_w]=OC_CLAMPI(0,(3*(_src[(y-2)*_c_w]
+       +_src[(_c_h-1)*_c_w])-17*(_src[(y-1)*_c_w]
+       +_src[OC_MINI(y+2,_c_h-1)*_c_w])
+       +78*(_src[y*_c_w]+_src[OC_MINI(y+1,_c_h-1)*_c_w])+64)>>7,255);
+    }
+    _src++;
+    _dst++;
+  }
+}
+
+/*420jpeg chroma samples are sited like:
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |   BR  |       |   BR  |
+  |       |       |       |
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |   BR  |       |   BR  |
+  |       |       |       |
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+
+  422jpeg chroma samples are sited like:
+  Y---BR--Y-------Y---BR--Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+  Y---BR--Y-------Y---BR--Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+  Y---BR--Y-------Y---BR--Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+  Y---BR--Y-------Y---BR--Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+
+  We use a resampling filter to decimate the chroma planes by two in the
+   vertical direction.*/
+static void y4m_convert_422jpeg_420jpeg(y4m_input *_y4m,unsigned char *_dst,
+ unsigned char *_aux){
+  int c_w;
+  int c_h;
+  int c_sz;
+  int dst_c_w;
+  int dst_c_h;
+  int dst_c_sz;
+  int pli;
+  /*Skip past the luma data.*/
+  _dst+=_y4m->pic_w*_y4m->pic_h;
+  /*Compute the size of each chroma plane.*/
+  c_w=(_y4m->pic_w+_y4m->src_c_dec_h-1)/_y4m->src_c_dec_h;
+  c_h=_y4m->pic_h;
+  dst_c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
+  dst_c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
+  c_sz=c_w*c_h;
+  dst_c_sz=dst_c_w*dst_c_h;
+  for(pli=1;pli<3;pli++){
+    y4m_422jpeg_420jpeg_helper(_dst,_aux,c_w,c_h);
+    _aux+=c_sz;
+    _dst+=dst_c_sz;
+  }
+}
+
+/*420jpeg chroma samples are sited like:
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |   BR  |       |   BR  |
+  |       |       |       |
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |   BR  |       |   BR  |
+  |       |       |       |
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+
+  422 chroma samples are sited like:
+  YBR-----Y-------YBR-----Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+  YBR-----Y-------YBR-----Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+  YBR-----Y-------YBR-----Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+  YBR-----Y-------YBR-----Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+
+  We use a resampling filter to shift the original site locations one quarter
+   pixel (at the original chroma resolution) to the right.
+  Then we use a second resampling filter to decimate the chroma planes by two
+   in the vertical direction.*/
+static void y4m_convert_422_420jpeg(y4m_input *_y4m,unsigned char *_dst,
+ unsigned char *_aux){
+  unsigned char *tmp;
+  int            c_w;
+  int            c_h;
+  int            c_sz;
+  int            dst_c_h;
+  int            dst_c_sz;
+  int            pli;
+  /*Skip past the luma data.*/
+  _dst+=_y4m->pic_w*_y4m->pic_h;
+  /*Compute the size of each chroma plane.*/
+  c_w=(_y4m->pic_w+_y4m->src_c_dec_h-1)/_y4m->src_c_dec_h;
+  c_h=_y4m->pic_h;
+  dst_c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
+  c_sz=c_w*c_h;
+  dst_c_sz=c_w*dst_c_h;
+  tmp=_aux+2*c_sz;
+  for(pli=1;pli<3;pli++){
+    /*In reality, the horizontal and vertical steps could be pipelined, for
+       less memory consumption and better cache performance, but we do them
+       separately for simplicity.*/
+    /*First do horizontal filtering (convert to 422jpeg)*/
+    y4m_42xmpeg2_42xjpeg_helper(tmp,_aux,c_w,c_h);
+    /*Now do the vertical filtering.*/
+    y4m_422jpeg_420jpeg_helper(_dst,tmp,c_w,c_h);
+    _aux+=c_sz;
+    _dst+=dst_c_sz;
+  }
+}
+
+/*420jpeg chroma samples are sited like:
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |   BR  |       |   BR  |
+  |       |       |       |
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |   BR  |       |   BR  |
+  |       |       |       |
+  Y-------Y-------Y-------Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+
+  411 chroma samples are sited like:
+  YBR-----Y-------Y-------Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+  YBR-----Y-------Y-------Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+  YBR-----Y-------Y-------Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+  YBR-----Y-------Y-------Y-------
+  |       |       |       |
+  |       |       |       |
+  |       |       |       |
+
+  We use a filter to resample at site locations one eighth pixel (at the source
+   chroma plane's horizontal resolution) and five eighths of a pixel to the
+   right.
+  Then we use another filter to decimate the planes by 2 in the vertical
+   direction.*/
+static void y4m_convert_411_420jpeg(y4m_input *_y4m,unsigned char *_dst,
+ unsigned char *_aux){
+  unsigned char *tmp;
+  int            c_w;
+  int            c_h;
+  int            c_sz;
+  int            dst_c_w;
+  int            dst_c_h;
+  int            dst_c_sz;
+  int            tmp_sz;
+  int            pli;
+  int            y;
+  int            x;
+  /*Skip past the luma data.*/
+  _dst+=_y4m->pic_w*_y4m->pic_h;
+  /*Compute the size of each chroma plane.*/
+  c_w=(_y4m->pic_w+_y4m->src_c_dec_h-1)/_y4m->src_c_dec_h;
+  c_h=_y4m->pic_h;
+  dst_c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
+  dst_c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
+  c_sz=c_w*c_h;
+  dst_c_sz=dst_c_w*dst_c_h;
+  tmp_sz=dst_c_w*c_h;
+  tmp=_aux+2*c_sz;
+  for(pli=1;pli<3;pli++){
+    /*In reality, the horizontal and vertical steps could be pipelined, for
+       less memory consumption and better cache performance, but we do them
+       separately for simplicity.*/
+    /*First do horizontal filtering (convert to 422jpeg)*/
+    for(y=0;y<c_h;y++){
+      /*Filters: [1 110 18 -1]/128 and [-3 50 86 -5]/128, both derived from a
+         4-tap Mitchell window.*/
+      for(x=0;x<OC_MINI(c_w,1);x++){
+        tmp[x<<1]=(unsigned char)OC_CLAMPI(0,(111*_aux[0]
+         +18*_aux[OC_MINI(1,c_w-1)]-_aux[OC_MINI(2,c_w-1)]+64)>>7,255);
+        tmp[x<<1|1]=(unsigned char)OC_CLAMPI(0,(47*_aux[0]
+         +86*_aux[OC_MINI(1,c_w-1)]-5*_aux[OC_MINI(2,c_w-1)]+64)>>7,255);
+      }
+      for(;x<c_w-2;x++){
+        tmp[x<<1]=(unsigned char)OC_CLAMPI(0,(_aux[x-1]+110*_aux[x]
+         +18*_aux[x+1]-_aux[x+2]+64)>>7,255);
+        tmp[x<<1|1]=(unsigned char)OC_CLAMPI(0,(-3*_aux[x-1]+50*_aux[x]
+         +86*_aux[x+1]-5*_aux[x+2]+64)>>7,255);
+      }
+      for(;x<c_w;x++){
+        tmp[x<<1]=(unsigned char)OC_CLAMPI(0,(_aux[x-1]+110*_aux[x]
+         +18*_aux[OC_MINI(x+1,c_w-1)]-_aux[c_w-1]+64)>>7,255);
+        if((x<<1|1)<dst_c_w){
+          tmp[x<<1|1]=(unsigned char)OC_CLAMPI(0,(-3*_aux[x-1]+50*_aux[x]
+           +86*_aux[OC_MINI(x+1,c_w-1)]-5*_aux[c_w-1]+64)>>7,255);
+        }
+      }
+      tmp+=dst_c_w;
+      _aux+=c_w;
+    }
+    tmp-=tmp_sz;
+    /*Now do the vertical filtering.*/
+    y4m_422jpeg_420jpeg_helper(_dst,tmp,dst_c_w,c_h);
+    _dst+=dst_c_sz;
+  }
+}
+
+/*Convert 444 to 420jpeg.*/
+static void y4m_convert_444_420jpeg(y4m_input *_y4m,unsigned char *_dst,
+ unsigned char *_aux){
+  unsigned char *tmp;
+  int            c_w;
+  int            c_h;
+  int            c_sz;
+  int            dst_c_w;
+  int            dst_c_h;
+  int            dst_c_sz;
+  int            tmp_sz;
+  int            pli;
+  int            y;
+  int            x;
+  /*Skip past the luma data.*/
+  _dst+=_y4m->pic_w*_y4m->pic_h;
+  /*Compute the size of each chroma plane.*/
+  c_w=(_y4m->pic_w+_y4m->src_c_dec_h-1)/_y4m->src_c_dec_h;
+  c_h=_y4m->pic_h;
+  dst_c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
+  dst_c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
+  c_sz=c_w*c_h;
+  dst_c_sz=dst_c_w*dst_c_h;
+  tmp_sz=dst_c_w*c_h;
+  tmp=_aux+2*c_sz;
+  for(pli=1;pli<3;pli++){
+    /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
+    for(y=0;y<c_h;y++){
+      for(x=0;x<OC_MINI(c_w,2);x+=2){
+        tmp[x>>1]=OC_CLAMPI(0,(64*_aux[0]+78*_aux[OC_MINI(1,c_w-1)]
+         -17*_aux[OC_MINI(2,c_w-1)]
+         +3*_aux[OC_MINI(3,c_w-1)]+64)>>7,255);
+      }
+      for(;x<c_w-3;x+=2){
+        tmp[x>>1]=OC_CLAMPI(0,(3*(_aux[x-2]+_aux[x+3])
+         -17*(_aux[x-1]+_aux[x+2])+78*(_aux[x]+_aux[x+1])+64)>>7,255);
+      }
+      for(;x<c_w;x+=2){
+        tmp[x>>1]=OC_CLAMPI(0,(3*(_aux[x-2]+_aux[c_w-1])-
+         17*(_aux[x-1]+_aux[OC_MINI(x+2,c_w-1)])+
+         78*(_aux[x]+_aux[OC_MINI(x+1,c_w-1)])+64)>>7,255);
+      }
+      tmp+=dst_c_w;
+      _aux+=c_w;
+    }
+    tmp-=tmp_sz;
+    /*Now do the vertical filtering.*/
+    y4m_422jpeg_420jpeg_helper(_dst,tmp,dst_c_w,c_h);
+    _dst+=dst_c_sz;
+  }
+}
+
+/*The image is padded with empty chroma components at 4:2:0.*/
+static void y4m_convert_mono_420jpeg(y4m_input *_y4m,unsigned char *_dst,
+ unsigned char *_aux){
+  int c_sz;
+  _dst+=_y4m->pic_w*_y4m->pic_h;
+  c_sz=((_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h)*
+   ((_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v);
+  memset(_dst,128,c_sz*2);
+}
+
+/*No conversion function needed.*/
+static void y4m_convert_null(y4m_input *_y4m,unsigned char *_dst,
+ unsigned char *_aux){
+}
+
+int y4m_input_open(y4m_input *_y4m,FILE *_fin,char *_skip,int _nskip){
+  char buffer[80];
+  int  ret;
+  int  i;
+  /*Read until newline, or 80 cols, whichever happens first.*/
+  for(i=0;i<79;i++){
+    if(_nskip>0){
+      buffer[i]=*_skip++;
+      _nskip--;
+    }
+    else{
+      ret=fread(buffer+i,1,1,_fin);
+      if(ret<1)return -1;
+    }
+    if(buffer[i]=='\n')break;
+  }
+  /*We skipped too much header data.*/
+  if(_nskip>0)return -1;
+  if(i==79){
+    fprintf(stderr,"Error parsing header; not a YUV2MPEG2 file?\n");
+    return -1;
+  }
+  buffer[i]='\0';
+  if(memcmp(buffer,"YUV4MPEG",8)){
+    fprintf(stderr,"Incomplete magic for YUV4MPEG file.\n");
+    return -1;
+  }
+  if(buffer[8]!='2'){
+    fprintf(stderr,"Incorrect YUV input file version; YUV4MPEG2 required.\n");
+  }
+  ret=y4m_parse_tags(_y4m,buffer+5);
+  if(ret<0){
+    fprintf(stderr,"Error parsing YUV4MPEG2 header.\n");
+    return ret;
+  }
+  if(_y4m->interlace=='?'){
+    fprintf(stderr,"Warning: Input video interlacing format unknown; "
+     "assuming progressive scan.\n");
+  }
+  else if(_y4m->interlace!='p'){
+    fprintf(stderr,"Input video is interlaced; "
+     "Only progressive scan handled.\n");
+    return -1;
+  }
+  if(strcmp(_y4m->chroma_type,"420")==0||
+   strcmp(_y4m->chroma_type,"420jpeg")==0){
+    _y4m->src_c_dec_h=_y4m->dst_c_dec_h=_y4m->src_c_dec_v=_y4m->dst_c_dec_v=2;
+    _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h
+     +2*((_y4m->pic_w+1)/2)*((_y4m->pic_h+1)/2);
+    /*Natively supported: no conversion required.*/
+    _y4m->aux_buf_sz=_y4m->aux_buf_read_sz=0;
+    _y4m->convert=y4m_convert_null;
+  }
+  else if(strcmp(_y4m->chroma_type,"420mpeg2")==0){
+    _y4m->src_c_dec_h=_y4m->dst_c_dec_h=_y4m->src_c_dec_v=_y4m->dst_c_dec_v=2;
+    _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
+    /*Chroma filter required: read into the aux buf first.*/
+    _y4m->aux_buf_sz=_y4m->aux_buf_read_sz=
+     2*((_y4m->pic_w+1)/2)*((_y4m->pic_h+1)/2);
+    _y4m->convert=y4m_convert_42xmpeg2_42xjpeg;
+  }
+  else if(strcmp(_y4m->chroma_type,"420paldv")==0){
+    _y4m->src_c_dec_h=_y4m->dst_c_dec_h=_y4m->src_c_dec_v=_y4m->dst_c_dec_v=2;
+    _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
+    /*Chroma filter required: read into the aux buf first.
+      We need to make two filter passes, so we need some extra space in the
+       aux buffer.*/
+    _y4m->aux_buf_sz=3*((_y4m->pic_w+1)/2)*((_y4m->pic_h+1)/2);
+    _y4m->aux_buf_read_sz=2*((_y4m->pic_w+1)/2)*((_y4m->pic_h+1)/2);
+    _y4m->convert=y4m_convert_42xpaldv_42xjpeg;
+  }
+  else if(strcmp(_y4m->chroma_type,"422jpeg")==0){
+    _y4m->src_c_dec_h=_y4m->dst_c_dec_h=2;
+    _y4m->src_c_dec_v=1;
+    _y4m->dst_c_dec_v=2;
+    _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
+    /*Chroma filter required: read into the aux buf first.*/
+    _y4m->aux_buf_sz=_y4m->aux_buf_read_sz=2*((_y4m->pic_w+1)/2)*_y4m->pic_h;
+    _y4m->convert=y4m_convert_422jpeg_420jpeg;
+  }
+  else if(strcmp(_y4m->chroma_type,"422")==0){
+    _y4m->src_c_dec_h=_y4m->dst_c_dec_h=2;
+    _y4m->src_c_dec_v=1;
+    _y4m->dst_c_dec_v=2;
+    _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
+    /*Chroma filter required: read into the aux buf first.
+      We need to make two filter passes, so we need some extra space in the
+       aux buffer.*/
+    _y4m->aux_buf_read_sz=2*((_y4m->pic_w+1)/2)*_y4m->pic_h;
+    _y4m->aux_buf_sz=_y4m->aux_buf_read_sz+((_y4m->pic_w+1)/2)*_y4m->pic_h;
+    _y4m->convert=y4m_convert_422_420jpeg;
+  }
+  else if(strcmp(_y4m->chroma_type,"411")==0){
+    _y4m->src_c_dec_h=4;
+    _y4m->dst_c_dec_h=2;
+    _y4m->src_c_dec_v=1;
+    _y4m->dst_c_dec_v=2;
+    _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
+    /*Chroma filter required: read into the aux buf first.
+      We need to make two filter passes, so we need some extra space in the
+       aux buffer.*/
+    _y4m->aux_buf_read_sz=2*((_y4m->pic_w+3)/4)*_y4m->pic_h;
+    _y4m->aux_buf_sz=_y4m->aux_buf_read_sz+((_y4m->pic_w+1)/2)*_y4m->pic_h;
+    _y4m->convert=y4m_convert_411_420jpeg;
+  }
+  else if(strcmp(_y4m->chroma_type,"444")==0){
+    _y4m->src_c_dec_h=1;
+    _y4m->dst_c_dec_h=2;
+    _y4m->src_c_dec_v=1;
+    _y4m->dst_c_dec_v=2;
+    _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
+    /*Chroma filter required: read into the aux buf first.
+      We need to make two filter passes, so we need some extra space in the
+       aux buffer.*/
+    _y4m->aux_buf_read_sz=2*_y4m->pic_w*_y4m->pic_h;
+    _y4m->aux_buf_sz=_y4m->aux_buf_read_sz+((_y4m->pic_w+1)/2)*_y4m->pic_h;
+    _y4m->convert=y4m_convert_444_420jpeg;
+  }
+  else if(strcmp(_y4m->chroma_type,"444alpha")==0){
+    _y4m->src_c_dec_h=1;
+    _y4m->dst_c_dec_h=2;
+    _y4m->src_c_dec_v=1;
+    _y4m->dst_c_dec_v=2;
+    _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
+    /*Chroma filter required: read into the aux buf first.
+      We need to make two filter passes, so we need some extra space in the
+       aux buffer.
+      The extra plane also gets read into the aux buf.
+      It will be discarded.*/
+    _y4m->aux_buf_sz=_y4m->aux_buf_read_sz=3*_y4m->pic_w*_y4m->pic_h;
+    _y4m->convert=y4m_convert_444_420jpeg;
+  }
+  else if(strcmp(_y4m->chroma_type,"mono")==0){
+    _y4m->src_c_dec_h=_y4m->src_c_dec_v=0;
+    _y4m->dst_c_dec_h=_y4m->dst_c_dec_v=2;
+    _y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
+    /*No extra space required, but we need to clear the chroma planes.*/
+    _y4m->aux_buf_sz=_y4m->aux_buf_read_sz=0;
+    _y4m->convert=y4m_convert_mono_420jpeg;
+  }
+  else{
+    fprintf(stderr,"Unknown chroma sampling type: %s\n",_y4m->chroma_type);
+    return -1;
+  }
+  /*The size of the final frame buffers is always computed from the
+     destination chroma decimation type.*/
+  _y4m->dst_buf_sz=_y4m->pic_w*_y4m->pic_h
+   +2*((_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h)*
+   ((_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v);
+  _y4m->dst_buf=(unsigned char *)malloc(_y4m->dst_buf_sz);
+  _y4m->aux_buf=(unsigned char *)malloc(_y4m->aux_buf_sz);
+  return 0;
+}
+
+void y4m_input_close(y4m_input *_y4m){
+  free(_y4m->dst_buf);
+  free(_y4m->aux_buf);
+}
+
+int y4m_input_fetch_frame(y4m_input *_y4m,FILE *_fin,vpx_image_t *_img){
+  char frame[6];
+  int  pic_sz;
+  int  c_w;
+  int  c_h;
+  int  c_sz;
+  int  ret;
+  /*Read and skip the frame header.*/
+  ret=fread(frame,1,6,_fin);
+  if(ret<6)return 0;
+  if(memcmp(frame,"FRAME",5)){
+    fprintf(stderr,"Loss of framing in Y4M input data\n");
+    return -1;
+  }
+  if(frame[5]!='\n'){
+    char c;
+    int  j;
+    for(j=0;j<79&&fread(&c,1,1,_fin)&&c!='\n';j++);
+    if(j==79){
+      fprintf(stderr,"Error parsing Y4M frame header\n");
+      return -1;
+    }
+  }
+  /*Read the frame data that needs no conversion.*/
+  if(fread(_y4m->dst_buf,1,_y4m->dst_buf_read_sz,_fin)!=_y4m->dst_buf_read_sz){
+    fprintf(stderr,"Error reading Y4M frame data.\n");
+    return -1;
+  }
+  /*Read the frame data that does need conversion.*/
+  if(fread(_y4m->aux_buf,1,_y4m->aux_buf_read_sz,_fin)!=_y4m->aux_buf_read_sz){
+    fprintf(stderr,"Error reading Y4M frame data.\n");
+    return -1;
+  }
+  /*Now convert the just read frame.*/
+  (*_y4m->convert)(_y4m,_y4m->dst_buf,_y4m->aux_buf);
+  /*Fill in the frame buffer pointers.
+    We don't use vpx_img_wrap() because it forces padding for odd picture
+     sizes, which would require a separate fread call for every row.*/
+  memset(_img,0,sizeof(*_img));
+  /*Y4M has the planes in Y'CbCr order, which libvpx calls Y, U, and V.*/
+  _img->fmt=IMG_FMT_I420;
+  _img->w=_img->d_w=_y4m->pic_w;
+  _img->h=_img->d_h=_y4m->pic_h;
+  /*This is hard-coded to 4:2:0 for now, as that's all VP8 supports.*/
+  _img->x_chroma_shift=1;
+  _img->y_chroma_shift=1;
+  _img->bps=12;
+  /*Set up the buffer pointers.*/
+  pic_sz=_y4m->pic_w*_y4m->pic_h;
+  c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
+  c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
+  c_sz=c_w*c_h;
+  _img->stride[PLANE_Y]=_y4m->pic_w;
+  _img->stride[PLANE_U]=_img->stride[PLANE_V]=c_w;
+  _img->planes[PLANE_Y]=_y4m->dst_buf;
+  _img->planes[PLANE_U]=_y4m->dst_buf+pic_sz;
+  _img->planes[PLANE_V]=_y4m->dst_buf+pic_sz+c_sz;
+  return 1;
+}
diff --git a/y4minput.h b/y4minput.h
new file mode 100644 (file)
index 0000000..1a01bcd
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ *
+ *  Based on code from the OggTheora software codec source code,
+ *  Copyright (C) 2002-2010 The Xiph.Org Foundation and contributors.
+ */
+#if !defined(_y4minput_H)
+# define _y4minput_H (1)
+# include <stdio.h>
+# include "vpx/vpx_image.h"
+
+
+
+typedef struct y4m_input y4m_input;
+
+
+
+/*The function used to perform chroma conversion.*/
+typedef void (*y4m_convert_func)(y4m_input *_y4m,
+ unsigned char *_dst,unsigned char *_src);
+
+
+
+struct y4m_input{
+  int               pic_w;
+  int               pic_h;
+  int               fps_n;
+  int               fps_d;
+  int               par_n;
+  int               par_d;
+  char              interlace;
+  int               src_c_dec_h;
+  int               src_c_dec_v;
+  int               dst_c_dec_h;
+  int               dst_c_dec_v;
+  char              chroma_type[16];
+  /*The size of each converted frame buffer.*/
+  size_t            dst_buf_sz;
+  /*The amount to read directly into the converted frame buffer.*/
+  size_t            dst_buf_read_sz;
+  /*The size of the auxilliary buffer.*/
+  size_t            aux_buf_sz;
+  /*The amount to read into the auxilliary buffer.*/
+  size_t            aux_buf_read_sz;
+  y4m_convert_func  convert;
+  unsigned char    *dst_buf;
+  unsigned char    *aux_buf;
+};
+
+int y4m_input_open(y4m_input *_y4m,FILE *_fin,char *_skip,int _nskip);
+void y4m_input_close(y4m_input *_y4m);
+int y4m_input_fetch_frame(y4m_input *_y4m,FILE *_fin,vpx_image_t *img);
+
+#endif